X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fdiskfile.c;h=42fa544ea4cdea37c7c336a4c76f07c5430f81d8;hb=96f35b20267e8b1a1c846d476f27fcd330e0b018;hp=e2abcf9111eb57ead44daa4bbe161b10adf708ad;hpb=3ab887b9bc819a846c75dd7f2ee5d41fac22b19f;p=debian%2Famanda diff --git a/server-src/diskfile.c b/server-src/diskfile.c index e2abcf9..42fa544 100644 --- a/server-src/diskfile.c +++ b/server-src/diskfile.c @@ -25,7 +25,7 @@ * University of Maryland at College Park */ /* - * $Id: diskfile.c,v 1.27.4.6.4.3.2.15 2003/12/16 22:36:45 martinea Exp $ + * $Id: diskfile.c,v 1.95 2006/07/26 15:17:37 martinea Exp $ * * read disklist file */ @@ -33,74 +33,101 @@ #include "arglist.h" #include "conffile.h" #include "diskfile.h" +#include "util.h" +#include "amxml.h" - -static disklist_t lst; -static FILE *diskf; -static char *diskfname = NULL; -static host_t *hostlist; -static int line_num, got_parserror; +static am_host_t *hostlist; +static netif_t *all_netifs; /* local functions */ -static char *upcase P((char *st)); -static int read_diskline P((void)); -static void parserror P((char *format, ...)) - __attribute__ ((format (printf, 1, 2))); +static char *upcase(char *st); +static int parse_diskline(disklist_t *, const char *, FILE *, int *, char **); +static void disk_parserror(const char *, int, const char *, ...) + G_GNUC_PRINTF(3, 4); -disklist_t *read_diskfile(filename) -char *filename; +cfgerr_level_t +read_diskfile( + const char *filename, + disklist_t *lst) { - extern int errno; + FILE *diskf; + int line_num; + char *line = NULL; /* initialize */ - hostlist = NULL; - lst.head = lst.tail = NULL; - diskfname = newstralloc(diskfname, filename); - malloc_mark(diskfname); - line_num = got_parserror = 0; + lst->head = lst->tail = NULL; + line_num = 0; - if((diskf = fopen(filename, "r")) == NULL) - error("could not open disklist file \"%s\": %s", - filename, strerror(errno)); + /* if we already have config errors, then don't bother */ + if (config_errors(NULL) >= CFGERR_ERRORS) { + return config_errors(NULL); + } - while(read_diskline()); - afclose(diskf); + if ((diskf = fopen(filename, "r")) == NULL) { + config_add_error(CFGERR_ERRORS, + vstrallocf(_("Could not open '%s': %s"), filename, strerror(errno))); + goto end; + /*NOTREACHED*/ + } + + while ((line = agets(diskf)) != NULL) { + line_num++; + if (line[0] != '\0') { + if (parse_diskline(lst, filename, diskf, &line_num, &line) < 0) { + goto end; + } + } + amfree(line); + } - if(got_parserror) return NULL; - else return &lst; +end: + amfree(line); + afclose(diskf); + return config_errors(NULL); } -host_t *lookup_host(hostname) -char *hostname; +am_host_t * +lookup_host( + const char *hostname) { - host_t *p; + am_host_t *p; - for(p = hostlist; p != NULL; p = p->next) { + for (p = hostlist; p != NULL; p = p->next) { if(strcasecmp(p->hostname, hostname) == 0) return p; } - return NULL; + return (NULL); } -disk_t *lookup_disk(hostname, diskname) -char *hostname, *diskname; +disk_t * +lookup_disk( + const char *hostname, + const char *diskname) { - host_t *host; + am_host_t *host; disk_t *disk; host = lookup_host(hostname); - if(host == NULL) return NULL; + if (host == NULL) + return (NULL); - for(disk = host->disks; disk != NULL; disk = disk->hostnext) { - if(strcmp(disk->name, diskname) == 0) return disk; + for (disk = host->disks; disk != NULL; disk = disk->hostnext) { + if (strcmp(disk->name, diskname) == 0) + return (disk); } - return NULL; + return (NULL); } -void enqueue_disk(list, disk) /* put disk on end of queue */ -disklist_t *list; -disk_t *disk; + +/* + * put disk on end of queue + */ + +void +enqueue_disk( + disklist_t *list, + disk_t * disk) { if(list->tail == NULL) list->head = disk; else list->tail->next = disk; @@ -110,9 +137,15 @@ disk_t *disk; disk->next = NULL; } -void headqueue_disk(list, disk) /* put disk on head of queue */ -disklist_t *list; -disk_t *disk; + +/* + * put disk on head of queue + */ + +void +headqueue_disk( + disklist_t *list, + disk_t * disk) { if(list->head == NULL) list->tail = disk; else list->head->prev = disk; @@ -122,10 +155,16 @@ disk_t *disk; disk->prev = NULL; } -void insert_disk(list, disk, cmp) /* insert in sorted order */ -disklist_t *list; -disk_t *disk; -int (*cmp) P((disk_t *a, disk_t *b)); + +/* + * insert in sorted order + */ + +void +insert_disk( + disklist_t *list, + disk_t * disk, + int (*cmp)(disk_t *a, disk_t *b)) { disk_t *prev, *ptr; @@ -146,26 +185,41 @@ int (*cmp) P((disk_t *a, disk_t *b)); else ptr->prev = disk; } -disk_t *add_disk(hostname, diskname) -char *hostname; -char *diskname; +disk_t * +add_disk( + disklist_t *list, + char * hostname, + char * diskname) { disk_t *disk; - host_t *host; + am_host_t *host; - disk = alloc(sizeof(disk_t)); + disk = alloc(SIZEOF(disk_t)); + bzero(disk, SIZEOF(disk_t)); disk->line = 0; + disk->tape_splitsize = (off_t)0; + disk->split_diskbuffer = NULL; + disk->fallback_splitsize = (off_t)0; + disk->hostname = stralloc(hostname); disk->name = stralloc(diskname); disk->device = stralloc(diskname); disk->spindle = -1; disk->up = NULL; disk->compress = COMP_NONE; + disk->encrypt = ENCRYPT_NONE; disk->start_t = 0; disk->todo = 1; + disk->index = 1; + disk->exclude_list = NULL; + disk->exclude_file = NULL; + disk->include_list = NULL; + disk->include_file = NULL; + disk->application = NULL; + disk->pp_scriptlist = NULL; host = lookup_host(hostname); if(host == NULL) { - host = alloc(sizeof(host_t)); + host = alloc(SIZEOF(am_host_t)); host->next = hostlist; hostlist = host; @@ -177,8 +231,10 @@ char *diskname; host->start_t = 0; host->up = NULL; host->features = NULL; + host->pre_script = 0; + host->post_script = 0; } - enqueue_disk(&lst, disk); + enqueue_disk(list, disk); disk->host = host; disk->hostnext = host->disks; @@ -187,22 +243,35 @@ char *diskname; return disk; } -int find_disk(list, disk) -disklist_t *list; -disk_t *disk; -/* check if disk is present in list. Return true if so, false otherwise. */ -{ -disk_t *t; - for( t = list->head; t && t != disk; t = t->next ); +/* + * check if disk is present in list. Return true if so, false otherwise. + */ - return t == disk; +int +find_disk( + disklist_t *list, + disk_t * disk) +{ + disk_t *t; + + t = list->head; + while ((t != NULL) && (t != disk)) { + t = t->next; + } + return (t == disk); } -void sort_disk(in, out, cmp) /* sort a whole queue */ -disklist_t *in; -disklist_t *out; -int (*cmp) P((disk_t *a, disk_t *b)); + +/* + * sort a whole queue + */ + +void +sort_disk( + disklist_t *in, + disklist_t *out, + int (*cmp)(disk_t *a, disk_t *b)) { disklist_t *tmp; disk_t *disk; @@ -216,8 +285,14 @@ int (*cmp) P((disk_t *a, disk_t *b)); insert_disk(out, disk, cmp); } -disk_t *dequeue_disk(list) /* remove disk from front of queue */ -disklist_t *list; + +/* + * remove disk from front of queue + */ + +disk_t * +dequeue_disk( + disklist_t *list) { disk_t *disk; @@ -233,9 +308,10 @@ disklist_t *list; return disk; } -void remove_disk(list, disk) -disklist_t *list; -disk_t *disk; +void +remove_disk( + disklist_t *list, + disk_t * disk) { if(disk->prev == NULL) list->head = disk->next; else disk->prev->next = disk->next; @@ -246,197 +322,401 @@ disk_t *disk; disk->prev = disk->next = NULL; } -static char *upcase(st) -char *st; +void +free_disklist( + disklist_t* dl) +{ + disk_t *dp; + am_host_t *host, *hostnext; + + while (dl->head != NULL) { + dp = dequeue_disk(dl); + amfree(dp->name); + amfree(dp->hostname); + amfree(dp->device); + free_sl(dp->exclude_file); + free_sl(dp->exclude_list); + free_sl(dp->include_file); + free_sl(dp->include_list); + free(dp); + } + + for(host=hostlist; host != NULL; host = hostnext) { + amfree(host->hostname); + am_release_feature_set(host->features); + host->features = NULL; + hostnext = host->next; + amfree(host); + } + hostlist=NULL; +} + +static char * +upcase( + char *st) { char *s = st; while(*s) { - if(islower((int)*s)) *s = toupper(*s); + if(islower((int)*s)) *s = (char)toupper((int)*s); s++; } return st; } -static int read_diskline() +/* return 0 on success */ +/* return -1 on error */ +static int +parse_diskline( + disklist_t *lst, + const char *filename, + FILE * diskf, + int * line_num_p, + /*@keep@*/ char ** line_p) { - host_t *host; + am_host_t *host; disk_t *disk; dumptype_t *dtype; - interface_t *netif = 0; + netif_t *netif = NULL; + interface_t *cfg_if = NULL; char *hostname = NULL; char *diskname, *diskdevice; - static char *line = NULL; - char *s = NULL, *fp; - int ch = '\0', dup = 0; - char *dn; + char *dumptype; + char *s, *fp; + int ch, dup = 0; + char *line = *line_p; + int line_num = *line_num_p; + struct tm *stm; + time_t st; + char *shost, *sdisk; + am_host_t *p; + disk_t *dp; - amfree(line); - for(; (line = agets(diskf)) != NULL; free(line)) { - line_num += 1; - s = line; - ch = *s++; + assert(filename != NULL); + assert(line_num > 0); + assert(line != NULL); - skip_whitespace(s, ch); - if(ch != '\0' && ch != '#') break; - } - if(line == NULL) return 0; + s = line; + ch = *s++; + skip_whitespace(s, ch); + if(ch == '\0' || ch == '#') + return (0); fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; host = lookup_host(fp); if (host == NULL) { - hostname = stralloc(fp); - malloc_mark(hostname); + hostname = stralloc(fp); } else { - hostname = host->hostname; + hostname = stralloc(host->hostname); + if (strcmp(host->hostname, fp) != 0) { + disk_parserror(filename, line_num, "Same host with different case: \"%s\" and \"%s\".", host->hostname, fp); + return -1; + } + } + + shost = sanitise_filename(hostname); + for (p = hostlist; p != NULL; p = p->next) { + char *shostp = sanitise_filename(p->hostname); + if (strcmp(hostname, p->hostname) && + !strcmp(shost, shostp)) { + disk_parserror(filename, line_num, "Two hosts are mapping to the same name: \"%s\" and \"%s\"", p->hostname, hostname); + return(-1); + } + else if (strcasecmp(hostname, p->hostname) && + match_host(hostname, p->hostname) && + match_host(p->hostname, hostname)) { + disk_parserror(filename, line_num, _("Duplicate host name: \"%s\" and \"%s\""), p->hostname, hostname); + return(-1); + } + amfree(shostp); } + amfree(shost); skip_whitespace(s, ch); if(ch == '\0' || ch == '#') { - parserror("disk device name expected"); - return 1; + disk_parserror(filename, line_num, _("disk device name expected")); + amfree(hostname); + return (-1); } + fp = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; - diskname = stralloc(fp); - + diskname = unquote_string(fp); + if (strlen(diskname) == 0) { + disk_parserror(filename, line_num, _("invalid empty diskname")); + amfree(hostname); + return (-1); + } skip_whitespace(s, ch); if(ch == '\0' || ch == '#') { - parserror("disk dumptype expected"); - if(host == NULL) amfree(hostname); + disk_parserror(filename, line_num, _("disk dumptype expected")); + amfree(hostname); amfree(diskname); - return 1; + return (-1); } fp = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; /* diskdevice */ - dn = stralloc(fp); - if(fp[0] != '{' && (dtype = lookup_dumptype(upcase(fp))) == NULL) { - diskdevice = dn; - skip_whitespace(s, ch); - if(ch == '\0' || ch == '#') { - parserror("disk dumptype expected"); - if(host == NULL) amfree(hostname); - amfree(diskname); - amfree(diskdevice); - return 1; - } - fp = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - } - else { - diskdevice = NULL; - amfree(dn); + dumptype = NULL; + diskdevice = NULL; + if(fp[0] != '{') { + dumptype = unquote_string(fp); + if (strlen(dumptype) == 0) { + disk_parserror(filename, line_num, _("invalid empty diskdevice")); + amfree(hostname); + return (-1); + } + if ((dtype = lookup_dumptype(dumptype)) == NULL) { + diskdevice = dumptype; + skip_whitespace(s, ch); + if(ch == '\0' || ch == '#') { + disk_parserror(filename, line_num, + _("disk dumptype '%s' not found"), dumptype); + amfree(hostname); + amfree(diskdevice); + amfree(diskname); + return (-1); + } + + fp = s - 1; + skip_quoted_string(s, ch); + s[-1] = '\0'; + if (fp[0] != '{') { + dumptype = unquote_string(fp); + } + } } /* check for duplicate disk */ - if(host && (disk = lookup_disk(hostname, diskname)) != NULL) { - parserror("duplicate disk record, previous on line %d", disk->line); - dup = 1; - } else { - disk = alloc(sizeof(disk_t)); - malloc_mark(disk); + disk = NULL; + if (host) { + if ((disk = lookup_disk(hostname, diskname)) != NULL) { + dup = 1; + } else { + disk = host->disks; + do { + char *a1, *a2; + a1 = clean_regex(diskname); + a2 = clean_regex(disk->name); + + if (match_disk(a1, disk->name) && match_disk(a2, diskname)) { + dup = 1; + } else { + disk = disk->hostnext; + } + amfree(a1); + amfree(a2); + } + while (dup == 0 && disk != NULL); + } + if (dup == 1) { + disk_parserror(filename, line_num, + _("duplicate disk record, previous on line %d"), + disk->line); + } + } + if (!disk) { + disk = alloc(SIZEOF(disk_t)); disk->line = line_num; + disk->hostname = stralloc(hostname); disk->name = diskname; disk->device = diskdevice; - malloc_mark(disk->name); disk->spindle = -1; disk->up = NULL; disk->inprogress = 0; + disk->application = NULL; + disk->pp_scriptlist = NULL; + } + + if (host) { + sdisk = sanitise_filename(diskname); + for (dp = host->disks; dp != NULL; dp = dp->hostnext) { + char *sdiskp = sanitise_filename(dp->name); + if (strcmp(diskname, dp->name) != 0 && + strcmp(sdisk, sdiskp) == 0) { + disk_parserror(filename, line_num, + _("Two disks are mapping to the same name: \"%s\" and \"%s\"; you must use different diskname"), + dp->name, diskname); + return(-1); + } + amfree(sdiskp); + } + amfree(sdisk); } if (fp[0] == '{') { - s[-1] = ch; + s[-1] = (char)ch; s = fp+2; skip_whitespace(s, ch); if (ch != '\0' && ch != '#') { - parserror("expected line break after `{\', ignoring rest of line"); + disk_parserror(filename, line_num, + _("expected line break after `{\', ignoring rest of line")); } if (strchr(s-1, '}') && (strchr(s-1, '#') == NULL || strchr(s-1, '}') < strchr(s-1, '#'))) { - if(host == NULL) amfree(hostname); + disk_parserror(filename, line_num,_("'}' on same line than '{'")); + amfree(hostname); if(!dup) { + amfree(disk->device); amfree(disk->name); amfree(disk); + } else { + amfree(diskdevice); + amfree(diskname); } - return 1; + return (-1); } - amfree(line); - dtype = read_dumptype(vstralloc("custom(", hostname, - ":", disk->name, ")", 0), - diskf, diskfname, &line_num); - - line = agets(diskf); - /* line_num += 1; */ /* read_dumptype did it already */ - + ":", disk->name, ")", + ".", anonymous_value(), NULL), + diskf, (char*)filename, line_num_p); if (dtype == NULL || dup) { - if(host == NULL) amfree(hostname); + disk_parserror(filename, line_num, + _("read of custom dumptype failed")); + amfree(hostname); if(!dup) { - amfree(disk->name); - amfree(disk); + amfree(disk->device); + amfree(disk->name); + amfree(disk); + } else { + amfree(diskdevice); + amfree(diskname); } - return line != NULL; + return (-1); } + amfree(line); + + *line_p = line = agets(diskf); + line_num = *line_num_p; /* no incr, read_dumptype did it already */ if (line == NULL) - line = stralloc(""); + *line_p = line = stralloc(""); s = line; ch = *s++; - } else if((dtype = lookup_dumptype(upcase(fp))) == NULL) { - parserror("undefined dumptype `%s'", fp); - if(host == NULL) amfree(hostname); - if(!dup) { - amfree(disk->name); - amfree(disk); + } else { + if((dtype = lookup_dumptype(dumptype)) == NULL) { + char *qdt = quote_string(dumptype); + + disk_parserror(filename, line_num, _("undefined dumptype `%s'"), qdt); + amfree(qdt); + amfree(dumptype); + amfree(hostname); + if (!dup) { + amfree(disk->device); + amfree(disk->name); + amfree(disk); + } else { + amfree(diskdevice); + amfree(diskname); + } + return (-1); } - return 1; } if (dup) { - if(host == NULL) amfree(hostname); - return 1; - } - - disk->dtype_name = dtype->name; - disk->program = dtype->program; - disk->exclude_file = duplicate_sl(dtype->exclude_file); - disk->exclude_list = duplicate_sl(dtype->exclude_list); - disk->include_file = duplicate_sl(dtype->include_file); - disk->include_list = duplicate_sl(dtype->include_list); - disk->exclude_optional = dtype->exclude_optional; - disk->include_optional = dtype->include_optional; - disk->priority = dtype->priority; - disk->dumpcycle = dtype->dumpcycle; - disk->frequency = dtype->frequency; - disk->auth = dtype->auth; - disk->maxdumps = dtype->maxdumps; - disk->maxpromoteday = dtype->maxpromoteday; - disk->start_t = dtype->start_t; - disk->strategy = dtype->strategy; - disk->compress = dtype->compress; - disk->comprate[0] = dtype->comprate[0]; - disk->comprate[1] = dtype->comprate[1]; - disk->record = dtype->record; - disk->skip_incr = dtype->skip_incr; - disk->skip_full = dtype->skip_full; - disk->no_hold = dtype->no_hold; - disk->kencrypt = dtype->kencrypt; - disk->index = dtype->index; - disk->todo = 1; + /* disk_parserror already called, above */ + g_assert(config_errors(NULL) != CFGERR_OK); + amfree(hostname); + amfree(diskdevice); + amfree(diskname); + return (-1); + } + + disk->dtype_name = dumptype_name(dtype); + disk->program = dumptype_get_program(dtype); + disk->exclude_list = duplicate_sl(dumptype_get_exclude(dtype).sl_list); + disk->exclude_file = duplicate_sl(dumptype_get_exclude(dtype).sl_file); + disk->exclude_optional = dumptype_get_exclude(dtype).optional; + disk->include_list = duplicate_sl(dumptype_get_include(dtype).sl_list); + disk->include_file = duplicate_sl(dumptype_get_include(dtype).sl_file); + disk->include_optional = dumptype_get_include(dtype).optional; + disk->priority = dumptype_get_priority(dtype); + disk->dumpcycle = dumptype_get_dumpcycle(dtype); +/* disk->frequency = dumptype_get_frequency(dtype);*/ + disk->security_driver = dumptype_get_security_driver(dtype); + disk->maxdumps = dumptype_get_maxdumps(dtype); + disk->tape_splitsize = dumptype_get_tape_splitsize(dtype); + disk->split_diskbuffer = dumptype_get_split_diskbuffer(dtype); + disk->fallback_splitsize = dumptype_get_fallback_splitsize(dtype); + disk->maxpromoteday = dumptype_get_maxpromoteday(dtype); + disk->bumppercent = dumptype_get_bumppercent(dtype); + disk->bumpsize = dumptype_get_bumpsize(dtype); + disk->bumpdays = dumptype_get_bumpdays(dtype); + disk->bumpmult = dumptype_get_bumpmult(dtype); + disk->starttime = dumptype_get_starttime(dtype); + disk->application = dumptype_get_application(dtype); + disk->pp_scriptlist = dumptype_get_pp_scriptlist(dtype); + disk->start_t = 0; + if (disk->starttime > 0) { + st = time(NULL); + disk->start_t = st; + stm = localtime(&st); + disk->start_t -= stm->tm_sec + 60 * stm->tm_min + 3600 * stm->tm_hour; + disk->start_t += disk->starttime / 100 * 3600 + + disk->starttime % 100 * 60; + if ((disk->start_t - st) < -43200) + disk->start_t += 86400; + } + disk->strategy = dumptype_get_strategy(dtype); + disk->ignore = dumptype_get_ignore(dtype); + disk->estimate = dumptype_get_estimate(dtype); + disk->compress = dumptype_get_compress(dtype); + disk->srvcompprog = dumptype_get_srvcompprog(dtype); + disk->clntcompprog = dumptype_get_clntcompprog(dtype); + disk->encrypt = dumptype_get_encrypt(dtype); + disk->srv_decrypt_opt = dumptype_get_srv_decrypt_opt(dtype); + disk->clnt_decrypt_opt = dumptype_get_clnt_decrypt_opt(dtype); + disk->srv_encrypt = dumptype_get_srv_encrypt(dtype); + disk->clnt_encrypt = dumptype_get_clnt_encrypt(dtype); + disk->amandad_path = dumptype_get_amandad_path(dtype); + disk->client_username = dumptype_get_client_username(dtype); + disk->ssh_keys = dumptype_get_ssh_keys(dtype); + disk->comprate[0] = dumptype_get_comprate(dtype)[0]; + disk->comprate[1] = dumptype_get_comprate(dtype)[1]; + + /* + * Boolean parameters with no value (Appears here as value 2) defaults + * to TRUE for backward compatibility and for logical consistency. + */ + disk->record = dumptype_get_record(dtype) != 0; + disk->skip_incr = dumptype_get_skip_incr(dtype) != 0; + disk->skip_full = dumptype_get_skip_full(dtype) != 0; + disk->to_holdingdisk = dumptype_get_to_holdingdisk(dtype); + disk->kencrypt = dumptype_get_kencrypt(dtype) != 0; + disk->index = dumptype_get_index(dtype) != 0; + + disk->todo = 1; skip_whitespace(s, ch); fp = s - 1; if(ch && ch != '#') { /* get optional spindle number */ + char *fp1; + int is_digit=1; + + skip_non_whitespace(s, ch); + s[-1] = '\0'; + fp1=fp; + if (*fp1 == '-') fp1++; + for(;*fp1!='\0';fp1++) { + if(!isdigit((int)*fp1)) { + is_digit = 0; + } + } + if(is_digit == 0) { + disk_parserror(filename, line_num, _("non-integer spindle `%s'"), fp); + amfree(hostname); + amfree(disk->name); + amfree(disk); + return (-1); + } disk->spindle = atoi(fp); skip_integer(s, ch); } @@ -446,37 +726,58 @@ static int read_diskline() if(ch && ch != '#') { /* get optional network interface */ skip_non_whitespace(s, ch); s[-1] = '\0'; - if((netif = lookup_interface(upcase(fp))) == NULL) { - parserror("undefined network interface `%s'", fp); - if(host == NULL) amfree(hostname); + if((cfg_if = lookup_interface(upcase(fp))) == NULL) { + disk_parserror(filename, line_num, + _("undefined network interface `%s'"), fp); + amfree(hostname); amfree(disk->name); amfree(disk); - return 1; + return (-1); } } else { - netif = lookup_interface(""); + cfg_if = lookup_interface("default"); + } + + /* see if we already have a netif_t for this interface */ + for (netif = all_netifs; netif != NULL; netif = netif->next) { + if (netif->config == cfg_if) + break; + } + + /* nope; make up a new one */ + if (!netif) { + netif = alloc(sizeof(*netif)); + netif->next = all_netifs; + all_netifs = netif; + netif->config = cfg_if; + netif->curusage = 0; } skip_whitespace(s, ch); if(ch && ch != '#') { /* now we have garbage, ignore it */ - parserror("end of line expected"); + disk_parserror(filename, line_num, _("end of line expected")); } - if(dtype->ignore || dtype->strategy == DS_SKIP) { - amfree(diskname); - free_sl(disk->exclude_file); - free_sl(disk->exclude_list); - free_sl(disk->include_file); - free_sl(disk->include_list); - amfree(disk); - return 1; + if (disk->program && disk->application && + strcmp(disk->program,"APPLICATION")) { + disk_parserror(filename, line_num, + _("Both program and application set")); + } + + if (disk->program && strcmp(disk->program,"APPLICATION")==0 && + !disk->application) { + disk_parserror(filename, line_num, + _("program set to APPLICATION but no application set")); + } + + if(dumptype_get_ignore(dtype) || dumptype_get_strategy(dtype) == DS_SKIP) { + disk->todo = 0; } /* success, add disk to lists */ if(host == NULL) { /* new host */ - host = alloc(sizeof(host_t)); - malloc_mark(host); + host = alloc(SIZEOF(am_host_t)); host->next = hostlist; hostlist = host; @@ -489,74 +790,88 @@ static int read_diskline() host->start_t = 0; host->up = NULL; host->features = NULL; + host->pre_script = 0; + host->post_script = 0; + } else { + amfree(hostname); } host->netif = netif; - enqueue_disk(&lst, disk); + enqueue_disk(lst, disk); disk->host = host; disk->hostnext = host->disks; host->disks = disk; host->maxdumps = disk->maxdumps; - return 1; + return (0); } -printf_arglist_function(static void parserror, char *, format) +printf_arglist_function2(void disk_parserror, const char *, filename, + int, line_num, const char *, format) { va_list argp; + char * msg; + char * errstr; - /* print error message */ + /* format the error message and hand it off to conffile */ - fprintf(stderr, "\"%s\", line %d: ", diskfname, line_num); arglist_start(argp, format); - vfprintf(stderr, format, argp); + msg = g_strdup_vprintf(format, argp); + errstr = g_strdup_printf("\"%s\", line %d: %s", filename, line_num, msg); + amfree(msg); arglist_end(argp); - fputc('\n', stderr); - got_parserror = 1; + config_add_error(CFGERR_ERRORS, errstr); } -void dump_queue(st, q, npr, f) -char *st; -disklist_t q; -int npr; /* we print first npr disks on queue, plus last two */ -FILE *f; +void +dump_queue( + char * st, + disklist_t q, + int npr, /* we print first npr disks on queue, plus last two */ + FILE * f) { disk_t *d,*p; int pos; + char *qname; if(empty(q)) { - fprintf(f, "%s QUEUE: empty\n", st); + g_fprintf(f, _("%s QUEUE: empty\n"), st); return; } - fprintf(f, "%s QUEUE:\n", st); + g_fprintf(f, _("%s QUEUE:\n"), st); for(pos = 0, d = q.head, p = NULL; d != NULL; p = d, d = d->next, pos++) { - if(pos < npr) fprintf(f, "%3d: %-10s %-4s\n", - pos, d->host->hostname, d->name); + qname = quote_string(d->name); + if(pos < npr) g_fprintf(f, "%3d: %-10s %-4s\n", + pos, d->host->hostname, qname); + amfree(qname); } if(pos > npr) { - if(pos > npr+2) fprintf(f, " ...\n"); + if(pos > npr+2) g_fprintf(f, " ...\n"); if(pos > npr+1) { d = p->prev; - fprintf(f, "%3d: %-10s %-4s\n", pos-2, d->host->hostname, d->name); + g_fprintf(f, "%3d: %-10s %-4s\n", pos-2, d->host->hostname, d->name); } d = p; - fprintf(f, "%3d: %-10s %-4s\n", pos-1, d->host->hostname, d->name); + g_fprintf(f, "%3d: %-10s %-4s\n", pos-1, d->host->hostname, d->name); } } -char *optionstr(dp, their_features, fdout) -disk_t *dp; -am_feature_t * their_features; -FILE *fdout; +char * +optionstr( + disk_t * dp, + am_feature_t * their_features, + FILE * fdout) { char *auth_opt = NULL; char *kencrypt_opt = ""; char *compress_opt = ""; + char *encrypt_opt = stralloc(""); + char *decrypt_opt = stralloc(""); char *record_opt = ""; char *index_opt = ""; char *exclude_file = NULL; @@ -570,60 +885,40 @@ FILE *fdout; sle_t *excl; int nb_exclude_file; int nb_include_file; - - /* modification by BIS@BBN 4/25/2003: - * The first "if" statement has a number of problems, so I removed the - * am_has_feature(dp->host->features, fe_options_auth) - * condition and caused the first case to always fail. - * 1) If dp->host is a NULL pointer, subsequent tests which look - * at dp->host->features or dp->host->hostname will cause a dump. - * It appears that there should be an assertion that dp->host - * is NOT NULL. - * 2) The code which checks for the kencrypt feature is only executed - * in the case where dp->auth == AUTH_KRB4. If we enable Kerberos IV - * in the first case, then the code checking for kencrypt will never - * be executed. - * 3) The option processing code in server-src/dumper.c and - * client-src/sendbackup.c do not yet handle the "auth=krb4" - * option style of specifying Kerberos IV. - * Getting rid of the whole first case seems to take care of problems - * 2 and 3, but not problem 1. - */ - if(dp->host && 0) - /* && am_has_feature(dp->host->features, fe_options_auth)) */ { - auth_opt = stralloc("auth="); - if(dp->auth == AUTH_BSD) { - strappend(auth_opt, "bsd"); - } else if(dp->auth == AUTH_KRB4) { - strappend(auth_opt, "krb4"); - } else { - strappend(auth_opt, "unknown"); - } - strappend(auth_opt, ";"); - } else if(dp->auth == AUTH_BSD) { - if(am_has_feature(dp->host->features, fe_options_bsd_auth)) { + char *qdpname; + char *qname; + int err=0; + + assert(dp != NULL); + assert(dp->host != NULL); + + qdpname = quote_string(dp->name); + if(am_has_feature(dp->host->features, fe_options_auth)) { + auth_opt = vstralloc("auth=", dp->security_driver, ";", NULL); + } else if(strcasecmp(dp->security_driver, "bsd") == 0) { + if(am_has_feature(dp->host->features, fe_options_bsd_auth)) auth_opt = stralloc("bsd-auth;"); - } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support bsd-auth\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support auth or bsd-auth\n"), + dp->host->hostname, qdpname); } - } else if(dp->auth == AUTH_KRB4) { - if(am_has_feature(dp->host->features, fe_options_krb4_auth)) { + } else if(strcasecmp(dp->security_driver, "krb4") == 0) { + if(am_has_feature(dp->host->features, fe_options_krb4_auth)) auth_opt = stralloc("krb4-auth;"); - } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support krb4-auth\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support auth or krb4-auth\n"), + dp->host->hostname, qdpname); } if(dp->kencrypt) { if(am_has_feature(dp->host->features, fe_options_kencrypt)) { kencrypt_opt = "kencrypt;"; } else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support kencrypt\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support kencrypt\n"), + dp->host->hostname, qdpname); } } } @@ -634,9 +929,9 @@ FILE *fdout; compress_opt = "compress-fast;"; } else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support fast compression\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support fast compression\n"), + dp->host->hostname, qdpname); } break; case COMP_BEST: @@ -644,30 +939,143 @@ FILE *fdout; compress_opt = "compress-best;"; } else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support best compression\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support best compression\n"), + dp->host->hostname, qdpname); + } + break; + case COMP_CUST: + if(am_has_feature(their_features, fe_options_compress_cust)) { + compress_opt = vstralloc("comp-cust=", dp->clntcompprog, ";", NULL); + if (BSTRNCMP(compress_opt, "comp-cust=;") == 0){ + if(fdout) { + g_fprintf(fdout, + _("ERROR: %s:%s client custom compression with no compression program specified\n"), + dp->host->hostname, qdpname); + } + err++; + } + } + else if(fdout) { + g_fprintf(fdout, + _("WARNING: %s:%s does not support client custom compression\n"), + dp->host->hostname, qdpname); } break; - case COMP_SERV_FAST: + case COMP_SERVER_FAST: if(am_has_feature(their_features, fe_options_srvcomp_fast)) { compress_opt = "srvcomp-fast;"; } break; - case COMP_SERV_BEST: + case COMP_SERVER_BEST: if(am_has_feature(their_features, fe_options_srvcomp_best)) { compress_opt = "srvcomp-best;"; } break; + case COMP_SERVER_CUST: + if(am_has_feature(their_features, fe_options_srvcomp_cust)) { + compress_opt = vstralloc("srvcomp-cust=", dp->srvcompprog, ";", NULL); + if (BSTRNCMP(compress_opt, "srvcomp-cust=;") == 0){ + if(fdout) { + g_fprintf(fdout, + _("ERROR: %s:%s server custom compression with no compression program specified\n"), + dp->host->hostname, qdpname); + } + err++; + } + } + else if(fdout) { + g_fprintf(fdout, + _("WARNING: %s:%s does not support server custom compression\n"), + dp->host->hostname, qdpname); + } + break; } + switch(dp->encrypt) { + case ENCRYPT_CUST: + if(am_has_feature(their_features, fe_options_encrypt_cust)) { + encrypt_opt = newvstralloc(encrypt_opt, "encrypt-cust=", + dp->clnt_encrypt, ";", NULL); + if (BSTRNCMP(encrypt_opt, "encrypt-cust=;") == 0) { + if(fdout) { + g_fprintf(fdout, + _("ERROR: %s:%s encrypt client with no encryption program specified\n"), + dp->host->hostname, qdpname); + } + err++; + } + if ( dp->compress == COMP_SERVER_FAST || + dp->compress == COMP_SERVER_BEST || + dp->compress == COMP_SERVER_CUST ) { + if(fdout) { + g_fprintf(fdout, + _("ERROR: %s:Client encryption with server compression is " + "not supported. See amanda.conf(5) for detail.\n"), + dp->host->hostname); + } + err++; + } + if(dp->clnt_decrypt_opt) { + if(am_has_feature(their_features, fe_options_client_decrypt_option)) { + decrypt_opt = newvstralloc(decrypt_opt, "client-decrypt-option=", + dp->clnt_decrypt_opt, ";", NULL); + } + else if(fdout) { + g_fprintf(fdout, + _("WARNING: %s:%s does not support client decrypt option\n"), + dp->host->hostname, qdpname); + } + } + } + else if(fdout) { + g_fprintf(fdout, + _("WARNING: %s:%s does not support client data encryption\n"), + dp->host->hostname, qdpname); + } + break; + case ENCRYPT_SERV_CUST: + if(am_has_feature(their_features, fe_options_encrypt_serv_cust)) { + encrypt_opt = newvstralloc(encrypt_opt, "encrypt-serv-cust=", + dp->srv_encrypt, ";", NULL); + if (BSTRNCMP(encrypt_opt, "encrypt-serv-cust=;") == 0){ + if(fdout) { + g_fprintf(fdout, + _("ERROR: %s:%s No encryption program specified in dumptypes\n"), + dp->host->hostname, qdpname); + g_fprintf(fdout, _("Change the dumptype in the disklist or mention " + "the ecnryption program to use in the dumptypes file\n")); + + } + err++; + } + if(dp->srv_decrypt_opt) { + if(am_has_feature(their_features, fe_options_server_decrypt_option)) { + decrypt_opt = newvstralloc(decrypt_opt, "server-decrypt-option=", + dp->srv_decrypt_opt, ";", NULL); + } + else if(fdout) { + g_fprintf(fdout, + _("WARNING: %s:%s client version does not support server data decryption\n"), + dp->host->hostname, qdpname); + } + } + } + else if(fdout) { + g_fprintf(fdout, + _("WARNING: %s:%s client version does not support server data encryption\n"), + dp->host->hostname, qdpname); + } + break; + } + if(!dp->record) { if(am_has_feature(their_features, fe_options_no_record)) { record_opt = "no-record;"; } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support no record\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, _("WARNING: %s:%s does not support no record\n"), + dp->host->hostname, qdpname); } } @@ -676,11 +1084,14 @@ FILE *fdout; index_opt = "index;"; } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support index\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, _("WARNING: %s:%s does not support index\n"), + dp->host->hostname, qdpname); } } + if(dp->kencrypt) kencrypt_opt = "kencrypt;"; + + exclude_file = stralloc(""); nb_exclude_file = 0; if(dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) { @@ -690,23 +1101,25 @@ FILE *fdout; dp->exclude_file->nb_element == 1) { for(excl = dp->exclude_file->first; excl != NULL; excl = excl->next) { - exc = newvstralloc( exc, "exclude-file=", excl->name, - ";", NULL); + qname = quote_string(excl->name); + exc = newvstralloc( exc, "exclude-file=", qname, ";", NULL); strappend(exclude_file, exc); + amfree(qname); } } else { - exc = newvstralloc(exc, "exclude-file=", - dp->exclude_file->last->name, ";", NULL); + qname = quote_string(dp->exclude_file->last->name); + exc = newvstralloc(exc, "exclude-file=", qname, ";", NULL); strappend(exclude_file, exc); if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support multiple exclude\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support multiple exclude\n"), + dp->host->hostname, qdpname); } + amfree(qname); } } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support exclude file\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, _("WARNING: %s:%s does not support exclude file\n"), + dp->host->hostname, qdpname); } } exclude_list = stralloc(""); @@ -716,23 +1129,25 @@ FILE *fdout; (dp->exclude_list->nb_element == 1 && nb_exclude_file == 0)) { for(excl = dp->exclude_list->first; excl != NULL; excl = excl->next) { - exc = newvstralloc( exc, "exclude-list=", excl->name, - ";", NULL); + qname = quote_string(excl->name); + exc = newvstralloc( exc, "exclude-list=", qname, ";", NULL); strappend(exclude_list, exc); + amfree(qname); } } else { - exc = newvstralloc(exc, "exclude-list=", - dp->exclude_list->last->name, ";", NULL); + qname = quote_string(dp->exclude_list->last->name); + exc = newvstralloc(exc, "exclude-list=", qname, ";", NULL); strappend(exclude_list, exc); if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support multiple exclude\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support multiple exclude\n"), + dp->host->hostname, qdpname); } + amfree(qname); } } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support exclude list\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, _("WARNING: %s:%s does not support exclude list\n"), + dp->host->hostname, qdpname); } } @@ -745,23 +1160,25 @@ FILE *fdout; dp->include_file->nb_element == 1) { for(excl = dp->include_file->first; excl != NULL; excl = excl->next) { - exc = newvstralloc( exc, "include-file=", excl->name, - ";", NULL); + qname = quote_string(excl->name); + exc = newvstralloc(exc, "include-file=", qname, ";", NULL); strappend(include_file, exc); + amfree(qname); } } else { - exc = newvstralloc(exc, "include-file=", - dp->include_file->last->name, ";", NULL); + qname = quote_string(dp->include_file->last->name); + exc = newvstralloc(exc, "include-file=", qname, ";", NULL); strappend(include_file, exc); if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support multiple include\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support multiple include\n"), + dp->host->hostname, qdpname); } + amfree(qname); } } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support include file\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, _("WARNING: %s:%s does not support include file\n"), + dp->host->hostname, qdpname); } } include_list = stralloc(""); @@ -771,23 +1188,25 @@ FILE *fdout; (dp->include_list->nb_element == 1 && nb_include_file == 0)) { for(excl = dp->include_list->first; excl != NULL; excl = excl->next) { - exc = newvstralloc( exc, "include-list=", excl->name, - ";", NULL); + qname = quote_string(excl->name); + exc = newvstralloc(exc, "include-list=", qname, ";", NULL); strappend(include_list, exc); + amfree(qname); } } else { - exc = newvstralloc(exc, "include-list=", - dp->include_list->last->name, ";", NULL); + qname = quote_string(dp->include_list->last->name); + exc = newvstralloc(exc, "include-list=", qname, ";", NULL); strappend(include_list, exc); if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support multiple include\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support multiple include\n"), + dp->host->hostname, qdpname); } + amfree(qname); } } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support include list\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, _("WARNING: %s:%s does not support include list\n"), + dp->host->hostname, qdpname); } } @@ -796,9 +1215,9 @@ FILE *fdout; excl_opt = "exclude-optional;"; } else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support optional exclude\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support optional exclude\n"), + dp->host->hostname, qdpname); } } if(dp->include_optional) { @@ -806,9 +1225,9 @@ FILE *fdout; incl_opt = "include-optional;"; } else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support optional include\n", - dp->host->hostname, dp->name); + g_fprintf(fdout, + _("WARNING: %s:%s does not support optional include\n"), + dp->host->hostname, qdpname); } } @@ -816,6 +1235,8 @@ FILE *fdout; auth_opt, kencrypt_opt, compress_opt, + encrypt_opt, + decrypt_opt, record_opt, index_opt, exclude_file, @@ -825,20 +1246,658 @@ FILE *fdout; excl_opt, incl_opt, NULL); + amfree(qdpname); amfree(auth_opt); + amfree(exclude_list); amfree(exclude_file); + amfree(include_file); + amfree(include_list); + amfree(exc); + amfree(decrypt_opt); + amfree(encrypt_opt); + + /* result contains at least 'auth=...' */ + if ( err ) { + amfree(result); + return NULL; + } else { + return result; + } +} + + +char * +xml_optionstr( + disk_t * dp, + am_feature_t * their_features, + FILE * fdout, + int to_server) +{ + char *auth_opt = stralloc(""); + char *kencrypt_opt = stralloc(""); + char *compress_opt = stralloc(""); + char *encrypt_opt = stralloc(""); + char *decrypt_opt = stralloc(""); + char *record_opt = stralloc(""); + char *index_opt = stralloc(""); + char *exclude = stralloc(""); + char *exclude_file = NULL; + char *exclude_list = NULL; + char *include = stralloc(""); + char *include_file = NULL; + char *include_list = NULL; + char *excl_opt = ""; + char *incl_opt = ""; + char *exc = NULL; + char *script_opt; + char *result = NULL; + sle_t *excl; + int nb_exclude_file; + int nb_include_file; + char *qdpname; + char *q64name; + int err=0; + + assert(dp != NULL); + assert(dp->host != NULL); + + qdpname = quote_string(dp->name); + if(am_has_feature(dp->host->features, fe_options_auth)) { + auth_opt = vstralloc(" ", dp->security_driver, "\n", NULL); + } else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support auth\n"), + dp->host->hostname, qdpname); + } + + switch(dp->compress) { + case COMP_FAST: + if(am_has_feature(their_features, fe_options_compress_fast)) { + compress_opt = " FAST\n"; + } + else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support fast compression\n"), + dp->host->hostname, qdpname); + } + break; + case COMP_BEST: + if(am_has_feature(their_features, fe_options_compress_best)) { + compress_opt = " BEST\n"; + } + else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support best compression\n"), + dp->host->hostname, qdpname); + } + break; + case COMP_CUST: + if(am_has_feature(their_features, fe_options_compress_cust)) { + if (dp->clntcompprog == NULL) { + if(fdout) { + fprintf(fdout, + _("ERROR: %s:%s client custom compression with no compression program specified\n"), + dp->host->hostname, qdpname); + } + err++; + } else { + + compress_opt = vstralloc(" CUSTOM" + "", + dp->clntcompprog, + "\n" + " \n", NULL); + } + } + else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support client custom compression\n"), + dp->host->hostname, qdpname); + } + break; + case COMP_SERVER_FAST: + compress_opt = " SERVER-FAST\n"; + break; + case COMP_SERVER_BEST: + compress_opt = " SERVER-BEST\n"; + break; + case COMP_SERVER_CUST: + compress_opt = " SERVER-CUSTOM\n"; + if (dp->srvcompprog == NULL) { + if(fdout) { + fprintf(fdout, + _("ERROR: %s:%s server custom compression with no compression program specified\n"), + dp->host->hostname, qdpname); + } + err++; + } else { + compress_opt = vstralloc(" SERVER-CUSTOM" + "", + dp->srvcompprog, + "\n" + " \n", NULL); + } + break; + } + + switch(dp->encrypt) { + case ENCRYPT_CUST: + if(am_has_feature(their_features, fe_options_encrypt_cust)) { + if(dp->clnt_decrypt_opt) { + if(am_has_feature(their_features, fe_options_client_decrypt_option)) { + decrypt_opt = newvstralloc(decrypt_opt, + " ", + dp->clnt_decrypt_opt, + "\n", NULL); + } else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support client decrypt option\n"), + dp->host->hostname, qdpname); + } + } + if (dp->clnt_encrypt == NULL) { + if(fdout) { + fprintf(fdout, + _("ERROR: %s:%s encrypt client with no encryption program specified\n"), + dp->host->hostname, qdpname); + } + err++; + } else if (decrypt_opt) { + encrypt_opt = newvstralloc(encrypt_opt, + " CUSTOM" + "", + dp->clnt_encrypt, + "\n", + decrypt_opt, + " \n", NULL); + } + if (dp->compress == COMP_SERVER_FAST || + dp->compress == COMP_SERVER_BEST || + dp->compress == COMP_SERVER_CUST ) { + if(fdout) { + fprintf(fdout, + _("ERROR: %s:Client encryption with server compression is " + "not supported. See amanda.conf(5) for detail.\n"), + dp->host->hostname); + } + err++; + } + } else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support client data encryption\n"), + dp->host->hostname, qdpname); + } + break; + case ENCRYPT_SERV_CUST: + if (dp->srv_encrypt != NULL && to_server) { + decrypt_opt = newvstralloc(decrypt_opt, + " ", + dp->srv_decrypt_opt, + "\n", NULL); + encrypt_opt = newvstralloc(encrypt_opt, + " SERVER-CUSTOM" + "", + dp->srv_encrypt, + "\n", + decrypt_opt, + " \n", NULL); + } else if (dp->srv_encrypt == NULL) { + if(fdout) { + fprintf(fdout, + _("ERROR: %s:%s No encryption program specified in dumptypes\n"), + dp->host->hostname, qdpname); + fprintf(fdout, + _("Change the dumptype in the disklist or mention " + "the encryption program to use in the dumptypes file\n")); + } + err++; + } + break; + } + + if(!dp->record) { + if(am_has_feature(their_features, fe_options_no_record)) { + record_opt = " NO\n"; + } + else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support no record\n"), + dp->host->hostname, qdpname); + } + } else { + record_opt = " YES\n"; + } + + if(dp->index) { + if(am_has_feature(their_features, fe_options_index)) { + index_opt = " YES\n"; + } + else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support index\n"), + dp->host->hostname, qdpname); + } + } + + if(dp->kencrypt) { + if(am_has_feature(their_features, fe_options_kencrypt)) { + kencrypt_opt = " YES\n"; + } + else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support kencrypt\n"), + dp->host->hostname, qdpname); + } + } + + exclude_file = stralloc(""); + nb_exclude_file = 0; + if(dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) { + nb_exclude_file = dp->exclude_file->nb_element; + if(am_has_feature(their_features, fe_options_exclude_file)) { + if(am_has_feature(their_features, fe_options_multiple_exclude) || + dp->exclude_file->nb_element == 1) { + for(excl = dp->exclude_file->first; excl != NULL; + excl = excl->next) { + q64name = amxml_format_tag("file", excl->name); + exc = newvstralloc( exc, " ", q64name, "\n", NULL); + strappend(exclude_file, exc); + amfree(q64name); + } + } else { + q64name = amxml_format_tag("file", dp->exclude_file->last->name); + exc = newvstralloc(exc, " ", q64name, "\n", NULL); + strappend(exclude_file, exc); + if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support multiple exclude\n"), + dp->host->hostname, qdpname); + } + amfree(q64name); + } + } else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support exclude file\n"), + dp->host->hostname, qdpname); + } + } + exclude_list = stralloc(""); + if(dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) { + if(am_has_feature(their_features, fe_options_exclude_list)) { + if(am_has_feature(their_features, fe_options_multiple_exclude) || + (dp->exclude_list->nb_element == 1 && nb_exclude_file == 0)) { + for(excl = dp->exclude_list->first; excl != NULL; + excl = excl->next) { + q64name = amxml_format_tag("list", excl->name); + exc = newvstralloc(exc, " ", q64name, "\n", NULL); + strappend(exclude_list, exc); + amfree(q64name); + } + } else { + q64name = amxml_format_tag("list", dp->exclude_list->last->name); + exc = newvstralloc(exc, " ", q64name, "\n", NULL); + strappend(exclude_list, exc); + if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support multiple exclude\n"), + dp->host->hostname, qdpname); + } + amfree(q64name); + } + } else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support exclude list\n"), + dp->host->hostname, qdpname); + } + } + + include_file = stralloc(""); + nb_include_file = 0; + if(dp->include_file != NULL && dp->include_file->nb_element > 0) { + nb_include_file = dp->include_file->nb_element; + if(am_has_feature(their_features, fe_options_include_file)) { + if(am_has_feature(their_features, fe_options_multiple_include) || + dp->include_file->nb_element == 1) { + for(excl = dp->include_file->first; excl != NULL; + excl = excl->next) { + q64name = amxml_format_tag("file", excl->name); + exc = newvstralloc( exc, " ", q64name, "\n", NULL); + strappend(include_file, exc); + amfree(q64name); + } + } else { + q64name = amxml_format_tag("file", dp->include_file->last->name); + exc = newvstralloc(exc, " ", q64name, "\n", NULL); + strappend(include_file, exc); + if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support multiple include\n"), + dp->host->hostname, qdpname); + } + amfree(q64name); + } + } else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support include file\n"), + dp->host->hostname, qdpname); + } + } + include_list = stralloc(""); + if(dp->include_list != NULL && dp->include_list->nb_element > 0) { + if(am_has_feature(their_features, fe_options_include_list)) { + if(am_has_feature(their_features, fe_options_multiple_include) || + (dp->include_list->nb_element == 1 && nb_include_file == 0)) { + for(excl = dp->include_list->first; excl != NULL; + excl = excl->next) { + q64name = amxml_format_tag("list", excl->name); + exc = newvstralloc( exc, " ", q64name, "\n", NULL); + strappend(include_list, exc); + amfree(q64name); + } + } else { + q64name = amxml_format_tag("list", dp->include_list->last->name); + exc = newvstralloc(exc, " ", q64name, "\n", NULL); + strappend(include_list, exc); + if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support multiple include\n"), + dp->host->hostname, qdpname); + } + amfree(q64name); + } + } else if(fdout) { + fprintf(fdout, _("WARNING: %s:%s does not support include list\n"), + dp->host->hostname, qdpname); + } + } + + if(dp->exclude_optional) { + if(am_has_feature(their_features, fe_options_optional_exclude)) { + excl_opt = " YES\n"; + } + else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support optional exclude\n"), + dp->host->hostname, qdpname); + } + } + if(dp->include_optional) { + if(am_has_feature(their_features, fe_options_optional_include)) { + incl_opt = " YES\n"; + } + else if(fdout) { + fprintf(fdout, + _("WARNING: %s:%s does not support optional include\n"), + dp->host->hostname, qdpname); + } + } + + if (dp->exclude_file || dp->exclude_list) + exclude = newvstralloc(exclude, + " \n", + exclude_file, + exclude_list, + excl_opt, + " \n", NULL); + if (dp->include_file || dp->include_list) + include = newvstralloc(include, + " \n", + include_file, + include_list, + incl_opt, + " \n", NULL); + script_opt = xml_scripts(dp->pp_scriptlist, their_features); + result = vstralloc(auth_opt, + kencrypt_opt, + compress_opt, + encrypt_opt, + record_opt, + index_opt, + exclude, + include, + script_opt, + NULL); + + amfree(qdpname); + amfree(auth_opt); + amfree(exclude); amfree(exclude_list); + amfree(exclude_file); + amfree(include); amfree(include_file); amfree(include_list); amfree(exc); + amfree(decrypt_opt); + amfree(encrypt_opt); + + /* result contains at least 'auth=...' */ + if ( err ) { + amfree(result); + return NULL; + } else { + return result; + } +} + +char * +clean_dle_str_for_client( + char *dle_str) +{ + char *rval_dle_str; + char *hack1, *hack2; + + if (!dle_str) + return NULL; + + rval_dle_str = stralloc(dle_str); + + /* Remove everything between " SERVER-CUSTOM" and "\n" + */ +#define SC "\n" +#define SC_LEN strlen(SC) + hack1 = strstr(rval_dle_str, " SERVER-CUSTOM"); + if (hack1) { + hack2 = strstr(hack1, SC); + /* +1 is to also move the trailing '\0' */ + memmove(hack1, hack2 + SC_LEN, strlen(hack2 + SC_LEN) + 1); + } +#undef SC +#undef SC_LEN + + return rval_dle_str; +} + +typedef struct { + am_feature_t *features; + char *result; +} xml_app_t; + +/* A GHFunc (callback for g_hash_table_foreach) */ +static void xml_property( + gpointer key_p, + gpointer value_p, + gpointer user_data_p) +{ + char *property_s = key_p; + char *b64property; + property_t *property = value_p; + char *b64value_data; + xml_app_t *xml_app = user_data_p; + GSList *value; + + b64property = amxml_format_tag("name", property_s); + vstrextend(&xml_app->result, " \n", + " ", b64property, "\n", NULL); + // TODO if client have fe_xml_property_priority + if (property->priority && + am_has_feature(xml_app->features, fe_xml_property_priority)) { + vstrextend(&xml_app->result, " yes\n", NULL); + } + for(value = property->values; value != NULL; value = value->next) { + b64value_data = amxml_format_tag("value", value->data); + vstrextend(&xml_app->result, " ", b64value_data, "\n", NULL); + amfree(b64value_data); + } + vstrextend(&xml_app->result, " \n", NULL); + + amfree(b64property); +} - return result; +char * +xml_application( + application_t *application, + am_feature_t *their_features) +{ + char *plugin; + char *b64plugin; + xml_app_t xml_app; + proplist_t proplist; + + xml_app.features = their_features; + xml_app.result = NULL; + plugin = application_get_plugin(application); + b64plugin = amxml_format_tag("plugin", plugin); + xml_app.result = vstralloc(" \n", + " ", b64plugin, "\n", + NULL); + proplist = application_get_property(application); + g_hash_table_foreach(proplist, xml_property, &xml_app); + vstrextend(&xml_app.result, " \n", NULL); + + amfree(b64plugin); + + return xml_app.result; +} + + +char * +xml_scripts( + pp_scriptlist_t pp_scriptlist, + am_feature_t *their_features) +{ + char *plugin; + char *b64plugin; + char *xml_scr; + char *xml_scr1; + char *str = ""; + char *sep; + char *eo_str; + execute_on_t execute_on; + int execute_where; + proplist_t proplist; + pp_scriptlist_t pp_scriptlist1; + pp_script_t *pp_script; + xml_app_t xml_app; + + xml_app.features = their_features; + + xml_scr = stralloc(""); + for (pp_scriptlist1=pp_scriptlist; pp_scriptlist1 != NULL; + pp_scriptlist1 = pp_scriptlist1->next) { + pp_script = pp_scriptlist1->data; + plugin = pp_script_get_plugin(pp_script); + b64plugin = amxml_format_tag("plugin", plugin); + xml_scr1 = vstralloc(" \n", NULL); + amfree(b64plugin); + amfree(xml_app.result); + } + return xml_scr; } -void match_disklist(disklist_t *origqp, int sargc, char **sargv) +char * +match_disklist( + disklist_t *origqp, + int sargc, + char ** sargv) { char *prevhost = NULL; + char *errstr = NULL; int i; int match_a_host; int match_a_disk; @@ -846,7 +1905,7 @@ void match_disklist(disklist_t *origqp, int sargc, char **sargv) disk_t *dp; if(sargc <= 0) - return; + return NULL; for(dp = origqp->head; dp != NULL; dp = dp->next) { if(dp->todo == 1) @@ -867,7 +1926,8 @@ void match_disklist(disklist_t *origqp, int sargc, char **sargv) (match_disk(sargv[i], dp->name) || (dp->device && match_disk(sargv[i], dp->device)))) { if(match_a_host) { - error("Argument %s match a host and a disk",sargv[i]); + error(_("Argument %s cannot be both a host and a disk"),sargv[i]); + /*NOTREACHED*/ } else { if(dp->todo == -1) { @@ -891,8 +1951,9 @@ void match_disklist(disklist_t *origqp, int sargc, char **sargv) prev_match = 1; } else { + char *errstr1 = vstrallocf(_("Argument '%s' matches neither a host nor a disk.\n"), sargv[i]); + vstrextend(&errstr, errstr1, NULL); prev_match = 0; - /*error("%s match nothing",sargv[i]);*/ } } } @@ -909,116 +1970,123 @@ void match_disklist(disklist_t *origqp, int sargc, char **sargv) if(dp->todo == -1) dp->todo = 0; } + + return errstr; +} + +netif_t * +disklist_netifs(void) +{ + return all_netifs; } - #ifdef TEST -void -dump_disk(dp) -disk_t *dp; +static void dump_disk(const disk_t *); +static void dump_disklist(const disklist_t *); +int main(int, char *[]); + +static void +dump_disk( + const disk_t * dp) { - printf(" DISK %s (HOST %s, LINE %d) TYPE %s NAME %s SPINDLE %d\n", + g_printf(_(" DISK %s (HOST %s, LINE %d) TYPE %s NAME %s SPINDLE %d\n"), dp->name, dp->host->hostname, dp->line, dp->dtype_name, dp->name == NULL? "(null)": dp->name, dp->spindle); } -void -dump_disklist() +static void +dump_disklist( + const disklist_t * lst) { - disk_t *dp, *prev; - host_t *hp; + const disk_t *dp, *prev; + const am_host_t *hp; if(hostlist == NULL) { - printf("DISKLIST not read in\n"); + g_printf(_("DISKLIST not read in\n")); return; } - printf("DISKLIST BY HOSTNAME:\n"); + g_printf(_("DISKLIST BY HOSTNAME:\n")); for(hp = hostlist; hp != NULL; hp = hp->next) { - printf("HOST %s INTERFACE %s\n", + char *if_name = NULL; + if (hp->netif && hp->netif->config) + if_name = interface_name(hp->netif->config); + + g_printf(_("HOST %s INTERFACE %s\n"), hp->hostname, - (hp->netif == NULL||hp->netif->name == NULL) ? "(null)" - : hp->netif->name); + if_name ? _("(null)") : if_name); for(dp = hp->disks; dp != NULL; dp = dp->hostnext) dump_disk(dp); putchar('\n'); } - printf("DISKLIST IN FILE ORDER:\n"); + g_printf(_("DISKLIST IN FILE ORDER:\n")); prev = NULL; - for(dp = lst.head; dp != NULL; prev = dp, dp = dp->next) { + for(dp = lst->head; dp != NULL; prev = dp, dp = dp->next) { dump_disk(dp); /* check pointers */ - if(dp->prev != prev) printf("*** prev pointer mismatch!\n"); - if(dp->next == NULL && lst.tail != dp) printf("tail mismatch!\n"); + if(dp->prev != prev) g_printf(_("*** prev pointer mismatch!\n")); + if(dp->next == NULL && lst->tail != dp) g_printf(_("tail mismatch!\n")); } } int -main(argc, argv) -int argc; -char *argv[]; +main( + int argc, + char ** argv) { char *conffile; char *conf_diskfile; + disklist_t lst; int result; - int fd; - unsigned long malloc_hist_1, malloc_size_1; - unsigned long malloc_hist_2, malloc_size_2; - for(fd = 3; fd < FD_SETSIZE; fd++) { - /* - * Make sure nobody spoofs us with a lot of extra open files - * that would cause an open we do to get a very high file - * descriptor, which in turn might be used as an index into - * an array (e.g. an fd_set). - */ - close(fd); - } + /* + * Configure program for internationalization: + * 1) Only set the message locale for now. + * 2) Set textdomain for all amanda related programs to "amanda" + * We don't want to be forced to support dozens of message catalogs. + */ + setlocale(LC_MESSAGES, "C"); + textdomain("amanda"); + + safe_fd(-1, 0); set_pname("diskfile"); - malloc_size_1 = malloc_inuse(&malloc_hist_1); + dbopen(DBG_SUBDIR_SERVER); + + /* Don't die when child closes pipe */ + signal(SIGPIPE, SIG_IGN); if (argc>1) { - config_name = argv[1]; - if (strchr(config_name, '/') != NULL) { - config_dir = stralloc2(argv[1], "/"); - config_name = strrchr(config_name, '/') + 1; - } else { - config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); - } + config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]); } else { - config_dir = stralloc(""); + config_init(CONFIG_INIT_USE_CWD, NULL) } - conffile = stralloc2(config_dir, CONFFILE_NAME); - if((result = read_conffile(conffile)) == 0) { - conf_diskfile = getconf_str(CNF_DISKFILE); - if (*conf_diskfile == '/') { - conf_diskfile = stralloc(conf_diskfile); - } else { - conf_diskfile = stralloc2(config_dir, conf_diskfile); - } - if((result = (read_diskfile(conf_diskfile) == NULL)) == 0) { - dump_disklist(); + + if (config_errors(NULL) >= CFGERR_WARNINGS) { + config_print_errors(); + if (config_errors(NULL) >= CFGERR_ERRORS) { + g_critical(_("errors processing config file")); } - amfree(conf_diskfile); } - amfree(conffile); - amfree(config_dir); - - malloc_size_2 = malloc_inuse(&malloc_hist_2); - if(malloc_size_1 != malloc_size_2) { - malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); + conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); + result = read_diskfile(conf_diskfile, &lst); + if(result == CFGERR_OK) { + dump_disklist(&lst); + } else { + config_print_errors(); } + amfree(conf_diskfile); + amfree(conffile); + amfree(config_dir); return result; } - #endif /* TEST */