diff options
Diffstat (limited to 'src/bindcf.c')
-rw-r--r-- | src/bindcf.c | 180 |
1 files changed, 136 insertions, 44 deletions
diff --git a/src/bindcf.c b/src/bindcf.c index e5fdd67..932b65b 100644 --- a/src/bindcf.c +++ b/src/bindcf.c @@ -23,5 +23,32 @@ char *zone_conf_file; -static char *bind_working_dir; +char *bind_working_dir; static struct grecs_node *bind_tree; +struct filesym { + const char *name; + struct grecs_node *node; +}; +static struct grecs_symtab *filetab; + +static struct grecs_node * +find_file(const char *name, struct grecs_node *node) +{ + int install = 1; + struct filesym key, *ret; + if (!filetab) { + filetab = grecs_symtab_create_default(sizeof(struct filesym)); + if (!filetab) + grecs_alloc_die(); + } + key.name = name; + ret = grecs_symtab_lookup_or_install(filetab, &key, &install); + if (!ret) + grecs_alloc_die(); + if (install) { + ret->node = node; + return NULL; + } + return ret->node; +} + void @@ -136,2 +163,6 @@ new_zone(struct nssync *sp, const char *zone, char *file) struct grecs_node *node, *np; +#define fake_locus(n) do { \ + (n)->locus.file = __FILE__; \ + (n)->locus.line = __LINE__; \ + } while (0) @@ -145,3 +176,4 @@ new_zone(struct nssync *sp, const char *zone, char *file) node->v.value->v.string = grecs_strdup(zone); - + fake_locus(node); + np = grecs_node_create(grecs_node_stmt, NULL); @@ -151,3 +183,4 @@ new_zone(struct nssync *sp, const char *zone, char *file) np->v.value->v.string = grecs_strdup(file); - + fake_locus(node); + node->down = np; @@ -156,2 +189,3 @@ new_zone(struct nssync *sp, const char *zone, char *file) np->ident = "$found$"; + fake_locus(node); grecs_node_bind(node, np, 1); @@ -159,2 +193,3 @@ new_zone(struct nssync *sp, const char *zone, char *file) grecs_node_bind(sp->zone_tree, node, 1); +#undef fake_locus } @@ -198,7 +233,31 @@ safe_filename(const char *file) -char * -bindcf_lookup(struct nssync *sp, const char *zone) +static char * +bindcf_zone_name(struct nssync *sp, const char *zone) { + char *name; char *env[5]; struct wordsplit ws; + + env[0] = "zone"; + env[1] = safe_filename(zone); + env[2] = "synctag"; + env[3] = sp->tag; + env[4] = NULL; + ws.ws_env = (const char**)env; + if (wordsplit(sp->zone_file_pattern, &ws, + WRDSF_NOCMD | WRDSF_ENV | WRDSF_ENV_KV | + WRDSF_NOSPLIT | WRDSF_KEEPUNDEF)) { + error("cannot split zone-file-pattern: %s", + wordsplit_strerror(&ws)); + exit(EX_SOFTWARE); + } + grecs_free(env[1]); + name = absolute_name(ws.ws_wordv[0], bind_working_dir); + wordsplit_free(&ws); + return name; +} + +char * +bindcf_lookup(struct nssync *sp, const char *zone) +{ char *name; @@ -214,3 +273,6 @@ bindcf_lookup(struct nssync *sp, const char *zone) + name = bindcf_zone_name(sp, zone); + if (node) { + char *oname; struct grecs_node *np = grecs_find_node(node->down, "file"); @@ -225,4 +287,4 @@ bindcf_lookup(struct nssync *sp, const char *zone) np->v.value->type != GRECS_TYPE_STRING) { - error("%s:%d: suspicious file statement", - np->locus.file, np->locus.line); + grecs_error(&np->locus, 0, + "suspicious file statement"); error_count++; @@ -230,4 +292,16 @@ bindcf_lookup(struct nssync *sp, const char *zone) } - name = absolute_name(np->v.value->v.string, bind_working_dir); - + oname = absolute_name(np->v.value->v.string, bind_working_dir); + if (strcmp(oname, name)) { + debug(1, ("renaming zone file %s to %s", oname, name)); + if (move_file(oname, name)) { + free(oname); + free(name); + error_count++; + return NULL; + } + grecs_free(np->v.value->v.string); + np->v.value->v.string = name; + name = grecs_strdup(np->v.value->v.string); + } + np = grecs_node_create(grecs_node_stmt, NULL); @@ -239,19 +313,3 @@ bindcf_lookup(struct nssync *sp, const char *zone) /* No zone statement: new zone */ - env[0] = "zone"; - env[1] = safe_filename(zone); - env[2] = "synctag"; - env[3] = sp->tag; - env[4] = NULL; - ws.ws_env = (const char**)env; - if (wordsplit(sp->zone_file_pattern, &ws, - WRDSF_NOCMD | WRDSF_ENV | WRDSF_ENV_KV | - WRDSF_NOSPLIT | WRDSF_KEEPUNDEF)) { - error("cannot split zone-file-pattern: %s", - wordsplit_strerror(&ws)); - exit(EX_SOFTWARE); - } - grecs_free(env[1]); - name = absolute_name(ws.ws_wordv[0], bind_working_dir); - wordsplit_free(&ws); - + name = bindcf_zone_name(sp, zone); new_zone(sp, zone, name); @@ -306,23 +364,57 @@ flush_zone_list(struct nssync *sp) for (node = sp->zone_tree->down; node; node = node->next) { + struct grecs_node *file_node = + grecs_find_node(node->down, "file"); + char *file = NULL; + struct grecs_node *np = NULL; + + if (file_node) { + file = absolute_name(file_node->v.value->v.string, + bind_working_dir); + np = find_file(file, file_node); + } + if (grecs_find_node(node->down, "$found$")) { + if (np) { + int fd; + char *new_name = NULL; + size_t size = 0; + + if (grecs_asprintf(&new_name, &size, + "%s.XXXXXX", + file_node->v.value->v.string)) + grecs_alloc_die(); + fd = mkstemp(new_name); + if (fd == -1) { + grecs_error(&node->locus, 0, + "can't create temporary: " + "%s", + strerror(errno)); + error_count++; + continue; + } + close(fd); + grecs_warning(&node->locus, 0, + "file %s already in use; " + "using %s instead", + file_node->v.value->v.string, + new_name); + grecs_warning(&np->locus, 0, + "this is the location of " + "the previous definition"); + grecs_free(file_node->v.value->v.string); + file_node->v.value->v.string = new_name; + } output_zone(fp, node); zone_count++; - } else { - char *file; - struct grecs_node *np = grecs_find_node(node->down, - "file"); - if (!np) { - error("about to delete zone %s, which has " - "no file definition", - node->v.value->v.string); - } else if (file = - absolute_name(np->v.value->v.string, - bind_working_dir)) { - debug(1, ("deleting zone %s, file %s", - node->v.value->v.string, - file)); - if (!dry_run_mode && unlink(file)) { - error("unlink(%s): %s", - file, strerror(errno)); - } + } else if (!file_node) { + error("about to delete zone %s, which has " + "no file definition", + node->v.value->v.string); + } else if (file && !np) { + debug(1, ("deleting zone %s, file %s", + node->v.value->v.string, + file)); + if (!dry_run_mode && unlink(file)) { + error("unlink(%s): %s", + file, strerror(errno)); } |