X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fdiskfile.c;h=544346a66e7d307d461cf005fe1fe908a834fd46;hb=949b8910a5e23c4285d0b1aedacfc82a14dc97a5;hp=da5dd0c1710e9ac0b6aacd59374f27635db0b0b1;hpb=34197d9f46a5f4e944378cbb65fca32ee0eec7b9;p=debian%2Famanda diff --git a/server-src/diskfile.c b/server-src/diskfile.c index da5dd0c..544346a 100644 --- a/server-src/diskfile.c +++ b/server-src/diskfile.c @@ -25,41 +25,51 @@ * University of Maryland at College Park */ /* - * $Id: diskfile.c,v 1.95.2.12 2007/01/26 14:33:24 martinea Exp $ + * $Id: diskfile.c,v 1.95 2006/07/26 15:17:37 martinea Exp $ * * read disklist file */ #include "amanda.h" +#include "match.h" #include "arglist.h" #include "conffile.h" #include "diskfile.h" #include "util.h" +#include "amxml.h" static am_host_t *hostlist; +static netif_t *all_netifs; /* local functions */ 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 *, ...) - __attribute__ ((format (printf, 3, 4))); + G_GNUC_PRINTF(3, 4); -int +cfgerr_level_t read_diskfile( const char *filename, disklist_t *lst) { FILE *diskf; int line_num; - char *line; + char *line = NULL; /* initialize */ hostlist = NULL; lst->head = lst->tail = NULL; line_num = 0; + /* if we already have config errors, then don't bother */ + if (config_errors(NULL) >= CFGERR_ERRORS) { + return config_errors(NULL); + } + if ((diskf = fopen(filename, "r")) == NULL) { - return -1; + config_add_error(CFGERR_ERRORS, + vstrallocf(_("Could not open '%s': %s"), filename, strerror(errno))); + goto end; /*NOTREACHED*/ } @@ -67,16 +77,22 @@ read_diskfile( line_num++; if (line[0] != '\0') { if (parse_diskline(lst, filename, diskf, &line_num, &line) < 0) { - amfree(line); - afclose(diskf); - return (-1); + goto end; } } amfree(line); } +end: + amfree(line); afclose(diskf); - return (0); + return config_errors(NULL); +} + +am_host_t * +get_hostlist(void) +{ + return hostlist; } am_host_t * @@ -186,10 +202,15 @@ add_disk( am_host_t *host; disk = alloc(SIZEOF(disk_t)); + bzero(disk, SIZEOF(disk_t)); disk->line = 0; + disk->allow_split = 0; + disk->max_warnings = 20; + disk->splitsize = (off_t)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; @@ -203,6 +224,8 @@ add_disk( 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) { @@ -218,6 +241,8 @@ add_disk( host->start_t = 0; host->up = NULL; host->features = NULL; + host->pre_script = 0; + host->post_script = 0; } enqueue_disk(list, disk); @@ -313,10 +338,14 @@ free_disklist( { disk_t *dp; am_host_t *host, *hostnext; + netif_t *netif, *next_if; while (dl->head != NULL) { dp = dequeue_disk(dl); + amfree(dp->filename); amfree(dp->name); + amfree(dp->hostname); + amfree(dp->device); free_sl(dp->exclude_file); free_sl(dp->exclude_list); free_sl(dp->include_file); @@ -332,6 +361,12 @@ free_disklist( amfree(host); } hostlist=NULL; + + for (netif = all_netifs; netif != NULL; netif = next_if) { + next_if = netif->next; + amfree(netif); + } + all_netifs = NULL; } static char * @@ -361,7 +396,8 @@ parse_diskline( 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; char *dumptype; @@ -374,6 +410,7 @@ parse_diskline( char *shost, *sdisk; am_host_t *p; disk_t *dp; + identlist_t pp_iter; assert(filename != NULL); assert(line_num > 0); @@ -388,14 +425,35 @@ parse_diskline( fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; + if (g_str_equal(fp, "includefile")) { + char *include_name; + char *include_filename; + skip_whitespace(s, ch); + if (ch == '\0' || ch == '#') { + disk_parserror(filename, line_num, _("include filename name expected")); + return (-1); + } + fp = s - 1; + skip_quoted_string(s, ch); + s[-1] = '\0'; + include_name = unquote_string(fp); + include_filename = config_dir_relative(include_name); + read_diskfile(include_filename, lst); + g_free(include_filename); + g_free(include_name); + if (config_errors(NULL) >= CFGERR_WARNINGS) { + return -1; + } else { + return 0; + } + } host = lookup_host(fp); if (host == NULL) { hostname = stralloc(fp); - malloc_mark(hostname); } else { 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); + disk_parserror(filename, line_num, _("Same host with different case: \"%s\" and \"%s\"."), host->hostname, fp); return -1; } } @@ -403,15 +461,15 @@ parse_diskline( 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 host are mapping to the same name: \"%s\" and \"%s\"", p->hostname, 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); + disk_parserror(filename, line_num, _("Duplicate host name: \"%s\" and \"%s\""), p->hostname, hostname); return(-1); } amfree(shostp); @@ -420,7 +478,7 @@ parse_diskline( skip_whitespace(s, ch); if(ch == '\0' || ch == '#') { - disk_parserror(filename, line_num, "disk device name expected"); + disk_parserror(filename, line_num, _("disk device name expected")); amfree(hostname); return (-1); } @@ -429,10 +487,14 @@ parse_diskline( skip_quoted_string(s, ch); s[-1] = '\0'; 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 == '#') { - disk_parserror(filename, line_num, "disk dumptype expected"); + disk_parserror(filename, line_num, _("disk dumptype expected")); amfree(hostname); amfree(diskname); return (-1); @@ -446,12 +508,17 @@ parse_diskline( 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); + _("disk dumptype '%s' not found"), dumptype); amfree(hostname); amfree(diskdevice); amfree(diskname); @@ -475,42 +542,49 @@ parse_diskline( } else { disk = host->disks; do { - if (match_disk(diskname, disk->name) && - match_disk(disk->name, diskname)) { + char *a1, *a2; + a1 = clean_regex(diskname, 1); + a2 = clean_regex(disk->name, 1); + + 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", + _("duplicate disk record, previous on line %d"), disk->line); } } if (!disk) { disk = alloc(SIZEOF(disk_t)); - malloc_mark(disk); + disk->filename = g_strdup(filename); disk->line = line_num; + disk->hostname = 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; + disk->dataport_list = NULL; } if (host) { sdisk = sanitise_filename(diskname); - for (dp = host->disks; dp != NULL; dp = dp->next) { + 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 disk are mapping to the same name: \"%s\" and \"%s\"" - ", you must use different diskname", + _("Two disks are mapping to the same name: \"%s\" and \"%s\"; you must use different diskname"), dp->name, diskname); return(-1); } @@ -525,13 +599,13 @@ parse_diskline( skip_whitespace(s, ch); if (ch != '\0' && ch != '#') { disk_parserror(filename, line_num, - "expected line break after `{\', ignoring rest of line"); + _("expected line break after `{\', ignoring rest of line")); } if (strchr(s-1, '}') && (strchr(s-1, '#') == NULL || strchr(s-1, '}') < strchr(s-1, '#'))) { - disk_parserror(filename, line_num,"'}' on same line than '{'"); + disk_parserror(filename, line_num,_("'}' on same line than '{'")); amfree(hostname); if(!dup) { amfree(disk->device); @@ -543,14 +617,13 @@ parse_diskline( } return (-1); } - amfree(line); - dtype = read_dumptype(vstralloc("custom(", hostname, - ":", disk->name, ")", NULL), + ":", disk->name, ")", + ".", anonymous_value(), NULL), diskf, (char*)filename, line_num_p); if (dtype == NULL || dup) { disk_parserror(filename, line_num, - "read of custom dumptype failed"); + _("read of custom dumptype failed")); amfree(hostname); if(!dup) { amfree(disk->device); @@ -562,6 +635,7 @@ parse_diskline( } return (-1); } + amfree(line); *line_p = line = agets(diskf); line_num = *line_num_p; /* no incr, read_dumptype did it already */ @@ -574,9 +648,8 @@ parse_diskline( if((dtype = lookup_dumptype(dumptype)) == NULL) { char *qdt = quote_string(dumptype); - disk_parserror(filename, line_num, "undefined dumptype `%s'", qdt); + disk_parserror(filename, line_num, _("undefined dumptype `%s'"), qdt); amfree(qdt); - amfree(dumptype); amfree(hostname); if (!dup) { amfree(disk->device); @@ -588,16 +661,20 @@ parse_diskline( } return (-1); } + amfree(dumptype); } if (dup) { + /* disk_parserror already called, above */ + g_assert(config_errors(NULL) != CFGERR_OK); amfree(hostname); amfree(diskdevice); amfree(diskname); return (-1); } - disk->dtype_name = dtype->name; + disk->dtype_name = dumptype_name(dtype); + disk->config = 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); @@ -608,17 +685,27 @@ parse_diskline( 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->auth = dumptype_get_auth(dtype); disk->maxdumps = dumptype_get_maxdumps(dtype); + disk->allow_split = dumptype_get_allow_split(dtype); + disk->max_warnings = dumptype_get_max_warnings(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); + if (disk->allow_split) { + tapetype_t *tapetype = lookup_tapetype(getconf_str(CNF_TAPETYPE)); + disk->splitsize = tapetype_get_part_size(tapetype); + } else { + disk->splitsize = disk->tape_splitsize; + } 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->starttime = dumptype_get_starttime(dtype); + disk->application = dumptype_get_application(dtype); + disk->pp_scriptlist = dumptype_get_scriptlist(dtype); disk->start_t = 0; if (disk->starttime > 0) { st = time(NULL); @@ -631,7 +718,8 @@ parse_diskline( disk->start_t += 86400; } disk->strategy = dumptype_get_strategy(dtype); - disk->estimate = dumptype_get_estimate(dtype); + disk->ignore = dumptype_get_ignore(dtype); + disk->estimatelist = dumptype_get_estimatelist(dtype); disk->compress = dumptype_get_compress(dtype); disk->srvcompprog = dumptype_get_srvcompprog(dtype); disk->clntcompprog = dumptype_get_clntcompprog(dtype); @@ -642,9 +730,12 @@ parse_diskline( 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->client_port = dumptype_get_client_port(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]; + disk->data_path = dumptype_get_data_path(dtype); + disk->dump_limit = dumptype_get_dump_limit(dtype); /* * Boolean parameters with no value (Appears here as value 2) defaults @@ -675,7 +766,7 @@ parse_diskline( } } if(is_digit == 0) { - disk_parserror(filename, line_num, "non-integer spindle `%s'", fp); + disk_parserror(filename, line_num, _("non-integer spindle `%s'"), fp); amfree(hostname); amfree(disk->name); amfree(disk); @@ -690,39 +781,86 @@ parse_diskline( if(ch && ch != '#') { /* get optional network interface */ skip_non_whitespace(s, ch); s[-1] = '\0'; - if((netif = lookup_interface(upcase(fp))) == NULL) { + if((cfg_if = lookup_interface(upcase(fp))) == NULL) { disk_parserror(filename, line_num, - "undefined network interface `%s'", fp); + _("undefined network interface `%s'"), fp); amfree(hostname); amfree(disk->name); amfree(disk); return (-1); } } else { - netif = lookup_interface("default"); + 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 */ - disk_parserror(filename, line_num, "end of line expected"); + disk_parserror(filename, line_num, _("end of line expected")); } - if(dumptype_get_ignore(dtype) || dumptype_get_strategy(dtype) == DS_SKIP) { - amfree(hostname); - amfree(disk->name); - amfree(disk); - return (0); + 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 (disk->application) { + application_t *application; + char *plugin; + + application = lookup_application(disk->application); + g_assert(application != NULL); + plugin = application_get_plugin(application); + if (!plugin || strlen(plugin) == 0) { + disk_parserror(filename, line_num, + _("plugin not set for application")); + } + } + + for (pp_iter = disk->pp_scriptlist; pp_iter != NULL; + pp_iter = pp_iter->next) { + pp_script_t *pp_script; + char *plugin; + char *pp_script_name; + + pp_script_name = (char*)pp_iter->data; + pp_script = lookup_pp_script(pp_script_name); + g_assert(pp_script != NULL); + plugin = pp_script_get_plugin(pp_script); + if (!plugin || strlen(plugin) == 0) { + disk_parserror(filename, line_num, _("plugin not set for script")); + } } /* success, add disk to lists */ if(host == NULL) { /* new host */ host = alloc(SIZEOF(am_host_t)); - malloc_mark(host); host->next = hostlist; hostlist = host; - host->hostname = hostname; + host->hostname = stralloc(hostname); hostname = NULL; host->disks = NULL; host->inprogress = 0; @@ -731,8 +869,8 @@ parse_diskline( host->start_t = 0; host->up = NULL; host->features = NULL; - } else { - amfree(hostname); + host->pre_script = 0; + host->post_script = 0; } host->netif = netif; @@ -752,14 +890,18 @@ 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: ", filename, 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); + + config_add_error(CFGERR_ERRORS, errstr); } @@ -775,32 +917,180 @@ dump_queue( 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++) { qname = quote_string(d->name); - if(pos < npr) fprintf(f, "%3d: %-10s %-4s\n", + 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); } } +GPtrArray * +validate_optionstr( + disk_t *dp) +{ + GPtrArray *errarray; + int nb_exclude; + int nb_include; + am_feature_t *their_features = dp->host->features; + + assert(dp != NULL); + assert(dp->host != NULL); + + errarray = g_ptr_array_new(); + + if (!am_has_feature(their_features, fe_options_auth)) { + if (strcasecmp(dp->auth, "bsd") == 0) + if (!am_has_feature(their_features, fe_options_bsd_auth)) + g_ptr_array_add(errarray, _("does not support auth")); + } + + switch(dp->compress) { + case COMP_FAST: + if (!am_has_feature(their_features, fe_options_compress_fast)) { + g_ptr_array_add(errarray, _("does not support fast compression")); + } + break; + case COMP_BEST: + if (!am_has_feature(their_features, fe_options_compress_best)) { + g_ptr_array_add(errarray, _("does not support best compression")); + } + break; + case COMP_CUST: + if (am_has_feature(their_features, fe_options_compress_cust)) { + if (dp->clntcompprog == NULL || strlen(dp->clntcompprog) == 0) { + g_ptr_array_add(errarray, _("client custom compression with no compression program specified")); + } + } else { + g_ptr_array_add(errarray, _("does not support client custom compression")); + } + break; + case COMP_SERVER_FAST: + break; + case COMP_SERVER_BEST: + break; + case COMP_SERVER_CUST: + if (dp->srvcompprog == NULL || strlen(dp->srvcompprog) == 0) { + g_ptr_array_add(errarray, _("server custom compression with no compression program specified")); + } + 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)) { + g_ptr_array_add(errarray, _("does not support client decrypt option")); + } + } + if (dp->clnt_encrypt == NULL || strlen(dp->clnt_encrypt) == 0) { + g_ptr_array_add(errarray, _("encrypt client with no encryption program specified")); + } + if (dp->compress == COMP_SERVER_FAST || + dp->compress == COMP_SERVER_BEST || + dp->compress == COMP_SERVER_CUST ) { + g_ptr_array_add(errarray, _("Client encryption with server compression is not supported. See amanda.conf(5) for detail")); + } + } else { + g_ptr_array_add(errarray, _("does not support client data encryption")); + } + break; + case ENCRYPT_SERV_CUST: + if (dp->srv_encrypt == NULL || strlen(dp->srv_encrypt) == 0) { + g_ptr_array_add(errarray, _("No encryption program specified in dumptypes, Change the dumptype in the disklist or mention the encryption program to use in the dumptypes file")); + } + break; + } + + if (!dp->record) { + if (!am_has_feature(their_features, fe_options_no_record)) { + g_ptr_array_add(errarray, _("does not support no record")); + } + } + + if (dp->index) { + if (!am_has_feature(their_features, fe_options_index)) { + g_ptr_array_add(errarray, _("does not support index")); + } + } + + if (dp->kencrypt) { + if (!am_has_feature(their_features, fe_options_kencrypt)) { + g_ptr_array_add(errarray, _("does not support kencrypt")); + } + } + + nb_exclude = 0; + if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) { + nb_exclude = dp->exclude_file->nb_element; + if (!am_has_feature(their_features, fe_options_exclude_file)) { + g_ptr_array_add(errarray, _("does not support exclude file")); + } + } + + if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) { + nb_exclude += dp->exclude_list->nb_element; + if (!am_has_feature(their_features, fe_options_exclude_list)) { + g_ptr_array_add(errarray, _("does not support exclude list")); + } + } + + if (nb_exclude > 1 && + !am_has_feature(their_features, fe_options_multiple_exclude)) { + g_ptr_array_add(errarray, _("does not support multiple exclude")); + } + + nb_include = 0; + if (dp->include_file != NULL && dp->include_file->nb_element > 0) { + nb_include = dp->include_file->nb_element; + if (!am_has_feature(their_features, fe_options_include_file)) { + g_ptr_array_add(errarray, ("does not support include file")); + } + } + + if (dp->include_list != NULL && dp->include_list->nb_element > 0) { + nb_include += dp->include_list->nb_element; + if (!am_has_feature(their_features, fe_options_include_list)) { + g_ptr_array_add(errarray, _("does not support include list")); + } + } + + if (nb_include > 1 && + !am_has_feature(their_features, fe_options_multiple_exclude)) { + g_ptr_array_add(errarray, _("does not support multiple include")); + } + + if (dp->exclude_optional) { + if (!am_has_feature(their_features, fe_options_optional_exclude)) { + g_ptr_array_add(errarray, _("does not support optional exclude")); + } + } + if (dp->include_optional) { + if (!am_has_feature(their_features, fe_options_optional_include)) { + g_ptr_array_add(errarray, _("does not support optional include")); + } + } + + return errarray; +} + char * optionstr( - disk_t * dp, - am_feature_t * their_features, - FILE * fdout) + disk_t * dp) { char *auth_opt = NULL; char *kencrypt_opt = ""; @@ -818,347 +1108,120 @@ optionstr( char *exc = NULL; char *result = NULL; sle_t *excl; - int nb_exclude_file; - int nb_include_file; char *qdpname; char *qname; - int err=0; + am_feature_t *their_features = dp->host->features; 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)) + if (am_has_feature(their_features, fe_options_auth)) { + auth_opt = vstralloc("auth=", dp->auth, ";", NULL); + } else if(strcasecmp(dp->auth, "bsd") == 0) { + if(am_has_feature(their_features, fe_options_bsd_auth)) auth_opt = stralloc("bsd-auth;"); - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support auth or bsd-auth\n", - dp->host->hostname, qdpname); - } - } 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 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, qdpname); - } - } } switch(dp->compress) { case COMP_FAST: - if(am_has_feature(their_features, fe_options_compress_fast)) { - compress_opt = "compress-fast;"; - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support fast compression\n", - dp->host->hostname, qdpname); - } + compress_opt = "compress-fast;"; break; case COMP_BEST: - if(am_has_feature(their_features, fe_options_compress_best)) { - compress_opt = "compress-best;"; - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support best compression\n", - dp->host->hostname, qdpname); - } + compress_opt = "compress-best;"; 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) { - fprintf(fdout, - "ERROR: %s:%s client custom compression with no compression program specified\n", - dp->host->hostname, qdpname); - } - err++; - } - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support client custom compression\n", - dp->host->hostname, qdpname); - } + compress_opt = vstralloc("comp-cust=", dp->clntcompprog, ";", NULL); break; - case COMP_SERV_FAST: - if(am_has_feature(their_features, fe_options_srvcomp_fast)) { - compress_opt = "srvcomp-fast;"; - } + case COMP_SERVER_FAST: + compress_opt = "srvcomp-fast;"; break; - case COMP_SERV_BEST: - if(am_has_feature(their_features, fe_options_srvcomp_best)) { - compress_opt = "srvcomp-best;"; - } + case COMP_SERVER_BEST: + compress_opt = "srvcomp-best;"; break; - case COMP_SERV_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) { - fprintf(fdout, - "ERROR: %s:%s server custom compression with no compression program specified\n", - dp->host->hostname, qdpname); - } - err++; - } - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support server custom compression\n", - dp->host->hostname, qdpname); - } + case COMP_SERVER_CUST: + compress_opt = vstralloc("srvcomp-cust=", dp->srvcompprog, ";", NULL); 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) { - fprintf(fdout, - "ERROR: %s:%s encrypt client with no encryption program specified\n", - dp->host->hostname, qdpname); - } - err++; - } - if ( dp->compress == COMP_SERV_FAST || - dp->compress == COMP_SERV_BEST || - dp->compress == COMP_SERV_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++; - } - if(dp->clnt_decrypt_opt) { - if(am_has_feature(their_features, fe_options_client_decrypt_option)) { + encrypt_opt = newvstralloc(encrypt_opt, "encrypt-cust=", + dp->clnt_encrypt, ";", NULL); + if (dp->clnt_decrypt_opt) { decrypt_opt = newvstralloc(decrypt_opt, "client-decrypt-option=", dp->clnt_decrypt_opt, ";", NULL); - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support client decrypt option\n", - dp->host->hostname, qdpname); - } - } - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support client data encryption\n", - dp->host->hostname, qdpname); - } - break; + } + 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) { - fprintf(fdout, - "ERROR: %s:%s encrypt server with no encryption program specified\n", - dp->host->hostname, qdpname); - } - 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) { - fprintf(fdout, - "WARNING: %s:%s does not support server decrypt option\n", - dp->host->hostname, qdpname); - } - } - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support server data encryption\n", - dp->host->hostname, qdpname); - } + encrypt_opt = newvstralloc(encrypt_opt, "encrypt-serv-cust=", + dp->srv_encrypt, ";", NULL); + if (dp->srv_decrypt_opt) { + decrypt_opt = newvstralloc(decrypt_opt, "server-decrypt-option=", + dp->srv_decrypt_opt, ";", NULL); + } 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, qdpname); - } - } - if(dp->index) { - if(am_has_feature(their_features, fe_options_index)) { - index_opt = "index;"; - } - else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support index\n", - dp->host->hostname, qdpname); - } + if (!dp->record) { + record_opt = "no-record;"; } - if(dp->kencrypt) kencrypt_opt = "kencrypt;"; + if (dp->index) { + index_opt = "index;"; + } + if (dp->kencrypt) { + kencrypt_opt = "kencrypt;"; + } 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) { - qname = quote_string(excl->name); - exc = newvstralloc( exc, "exclude-file=", qname, ";", NULL); - strappend(exclude_file, exc); - amfree(qname); - } - } else { - 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, qdpname); - } - amfree(qname); - } - } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support exclude file\n", - dp->host->hostname, qdpname); + if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) { + for(excl = dp->exclude_file->first; excl != NULL; + excl = excl->next) { + qname = quote_string(excl->name); + exc = newvstralloc( exc, "exclude-file=", qname, ";", NULL); + strappend(exclude_file, exc); + amfree(qname); } } 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) { - qname = quote_string(excl->name); - exc = newvstralloc( exc, "exclude-list=", qname, ";", NULL); - strappend(exclude_list, exc); - amfree(qname); - } - } else { - 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, qdpname); - } - amfree(qname); - } - } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support exclude list\n", - dp->host->hostname, qdpname); + if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) { + for(excl = dp->exclude_list->first; excl != NULL; + excl = excl->next) { + qname = quote_string(excl->name); + exc = newvstralloc( exc, "exclude-list=", qname, ";", NULL); + strappend(exclude_list, exc); + amfree(qname); } } 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) { - qname = quote_string(excl->name); - exc = newvstralloc(exc, "include-file=", qname, ";", NULL); - strappend(include_file, exc); - amfree(qname); - } - } else { - 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, qdpname); - } - amfree(qname); - } - } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support include file\n", - dp->host->hostname, qdpname); + if (dp->include_file != NULL && dp->include_file->nb_element > 0) { + for(excl = dp->include_file->first; excl != NULL; + excl = excl->next) { + qname = quote_string(excl->name); + exc = newvstralloc(exc, "include-file=", qname, ";", NULL); + strappend(include_file, exc); + amfree(qname); } } 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) { - qname = quote_string(excl->name); - exc = newvstralloc(exc, "include-list=", qname, ";", NULL); - strappend(include_list, exc); - amfree(qname); - } - } else { - 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, qdpname); - } - amfree(qname); - } - } else if(fdout) { - fprintf(fdout, "WARNING: %s:%s does not support include list\n", - dp->host->hostname, qdpname); + if (dp->include_list != NULL && dp->include_list->nb_element > 0) { + for(excl = dp->include_list->first; excl != NULL; + excl = excl->next) { + qname = quote_string(excl->name); + exc = newvstralloc(exc, "include-list=", qname, ";", NULL); + strappend(include_list, exc); + amfree(qname); } } - if(dp->exclude_optional) { - if(am_has_feature(their_features, fe_options_optional_exclude)) { - excl_opt = "exclude-optional;"; - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support optional exclude\n", - dp->host->hostname, qdpname); - } + if (dp->exclude_optional) { + excl_opt = "exclude-optional;"; } - if(dp->include_optional) { - if(am_has_feature(their_features, fe_options_optional_include)) { - incl_opt = "include-optional;"; - } - else if(fdout) { - fprintf(fdout, - "WARNING: %s:%s does not support optional include\n", - dp->host->hostname, qdpname); - } + if (dp->include_optional) { + incl_opt = "include-optional;"; } result = vstralloc(";", @@ -1187,15 +1250,604 @@ optionstr( amfree(encrypt_opt); /* result contains at least 'auth=...' */ - if ( err ) { - amfree(result); + return result; +} + +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 *tmp; + property_t *property = value_p; + xml_app_t *xml_app = user_data_p; + GSList *value; + GString *strbuf; + + strbuf = g_string_new(xml_app->result); + + tmp = amxml_format_tag("name", (char *)key_p); + g_string_append_printf(strbuf, " \n %s\n", tmp); + g_free(tmp); + + // TODO if client have fe_xml_property_priority + if (property->priority + && am_has_feature(xml_app->features, fe_xml_property_priority)) + g_string_append(strbuf, " yes\n"); + + for (value = property->values; value != NULL; value = value->next) { + tmp = amxml_format_tag("value", value->data); + g_string_append_printf(strbuf, " %s", tmp); + g_free(tmp); + } + g_string_append_printf(strbuf, "\n \n"); + + g_free(xml_app->result); + xml_app->result = g_string_free(strbuf, FALSE); +} + +char * +xml_optionstr( + disk_t * dp, + int to_server) +{ + char *auth_opt; + char *kencrypt_opt; + char *compress_opt; + char *encrypt_opt = stralloc(""); + char *decrypt_opt = stralloc(""); + char *record_opt; + char *index_opt; + char *data_path_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; + char *qdpname; + char *q64name; + am_feature_t *their_features = dp->host->features; + + assert(dp != NULL); + assert(dp->host != NULL); + + qdpname = quote_string(dp->name); + if (am_has_feature(their_features, fe_options_auth)) { + auth_opt = vstralloc(" ", dp->auth, "\n", NULL); + } else { + auth_opt = stralloc(""); + } + + switch(dp->compress) { + case COMP_FAST: + compress_opt = stralloc(" FAST\n"); + break; + case COMP_BEST: + compress_opt = stralloc(" BEST\n"); + break; + case COMP_CUST: + compress_opt = vstralloc(" CUSTOM" + "", + dp->clntcompprog, + "\n" + " \n", NULL); + break; + case COMP_SERVER_FAST: + compress_opt = stralloc(" SERVER-FAST\n"); + break; + case COMP_SERVER_BEST: + compress_opt = stralloc(" SERVER-BEST\n"); + break; + case COMP_SERVER_CUST: + compress_opt = vstralloc(" SERVER-CUSTOM" + "", + dp->srvcompprog, + "\n" + " \n", NULL); + break; + default: + compress_opt = stralloc(""); + } + + switch(dp->encrypt) { + case ENCRYPT_CUST: + if (dp->clnt_decrypt_opt) { + decrypt_opt = newvstralloc(decrypt_opt, + " ", + dp->clnt_decrypt_opt, + "\n", NULL); + } + if (decrypt_opt) { + encrypt_opt = newvstralloc(encrypt_opt, + " CUSTOM" + "", + dp->clnt_encrypt, + "\n", + decrypt_opt, + " \n", NULL); + } + break; + case ENCRYPT_SERV_CUST: + if (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); + } + break; + } + + if (!dp->record) { + record_opt = " NO\n"; + } else { + record_opt = " YES\n"; + } + + if(dp->index) { + index_opt = " YES\n"; + } else { + index_opt = ""; + } + + if (dp->kencrypt) { + kencrypt_opt = " YES\n"; + } else { + kencrypt_opt = ""; + } + + if (am_has_feature(their_features, fe_xml_data_path)) { + switch(dp->data_path) { + case DATA_PATH_AMANDA: + amfree(data_path_opt); + data_path_opt = stralloc(" AMANDA\n"); + break; + case DATA_PATH_DIRECTTCP: + { /* dp->dataport_list is not set for selfcheck/sendsize */ + if (am_has_feature(their_features, fe_xml_directtcp_list)) { + char *s, *sc; + char *value, *b64value; + + amfree(data_path_opt); + data_path_opt = stralloc(" DIRECTTCP"); + if (dp->dataport_list) { + s = sc = stralloc(dp->dataport_list); + do { + value = s; + s = strchr(s, ';'); + if (s) { + *s++ = '\0'; + } + + b64value = amxml_format_tag("directtcp", value); + vstrextend(&data_path_opt, "\n ", b64value, NULL); + amfree(b64value); + } while (s); + amfree(sc); + strappend(data_path_opt, "\n "); + } + strappend(data_path_opt, "\n"); + } + } + break; + } + } + + exclude_file = stralloc(""); + if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) { + 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); + } + } + exclude_list = stralloc(""); + if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 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); + } + } + + include_file = stralloc(""); + if (dp->include_file != NULL && dp->include_file->nb_element > 0) { + 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); + } + } + include_list = stralloc(""); + if (dp->include_list != NULL && dp->include_list->nb_element > 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); + } + } + + if (dp->exclude_optional) { + excl_opt = " YES\n"; + } + if (dp->include_optional) { + incl_opt = " YES\n"; + } + + 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, + data_path_opt, + exclude, + include, + script_opt, + NULL); + + amfree(qdpname); + amfree(auth_opt); + amfree(data_path_opt); + amfree(compress_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); + amfree(script_opt); + + /* result contains at least 'auth=...' */ + return result; +} + +char * +xml_dumptype_properties( + disk_t *dp) +{ + xml_app_t xml_dumptype; + + xml_dumptype.result = g_strdup(""); + xml_dumptype.features = NULL; + if (dp && dp->config) { + g_hash_table_foreach(dumptype_get_property(dp->config), xml_property, + &xml_dumptype); + } + return xml_dumptype.result; +} + +char * +xml_estimate( + estimatelist_t estimatelist, + am_feature_t *their_features) +{ + estimatelist_t el; + char *l = NULL; + + if (am_has_feature(their_features, fe_xml_estimatelist)) { + vstrextend(&l, " ", NULL); + for (el=estimatelist; el != NULL; el = el->next) { + switch (GPOINTER_TO_INT(el->data)) { + case ES_CLIENT : vstrextend(&l, "CLIENT ", NULL); break; + case ES_SERVER : vstrextend(&l, "SERVER ", NULL); break; + case ES_CALCSIZE: vstrextend(&l, "CALCSIZE ", NULL); break; + } + } + vstrextend(&l, "", NULL); + } else { /* add the first estimate only */ + if (am_has_feature(their_features, fe_xml_estimate)) { + vstrextend(&l, " ", NULL); + switch (GPOINTER_TO_INT(estimatelist->data)) { + case ES_CLIENT : vstrextend(&l, "CLIENT", NULL); break; + case ES_SERVER : vstrextend(&l, "SERVER", NULL); break; + case ES_CALCSIZE: vstrextend(&l, "CALCSIZE", NULL); break; + } + } + vstrextend(&l, "", NULL); + if (GPOINTER_TO_INT(estimatelist->data) == ES_CALCSIZE) { + vstrextend(&l, " YES", NULL); + } + } + + return l; +} + +char * +clean_dle_str_for_client( + char *dle_str, + am_feature_t *their_features) +{ + char *rval_dle_str; + char *hack1, *hack2; + char *pend, *pscript, *pproperty, *eproperty; + int len; + + 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 + + if (!am_has_feature(their_features, fe_dumptype_property)) { +#define SC "\n" +#define SC_LEN strlen(SC) + /* remove all dle properties, they are before backup-program or script + properties */ + hack1 = rval_dle_str; + pend = strstr(rval_dle_str, ""); + pscript = strstr(rval_dle_str, "\n", NULL); + amfree(b64plugin); + amfree(xml_app.result); + amfree(xml_scr1); + } + return xml_scr; +} + + +void +disable_skip_disk( + disklist_t *origqp) +{ + disk_t *dp; + + for (dp = origqp->head; dp != NULL; dp = dp->next) { + if (dp->ignore || dp->strategy == DS_SKIP) + dp->todo = 0; + } +} + + char * match_disklist( disklist_t *origqp, @@ -1208,6 +1860,7 @@ match_disklist( int match_a_host; int match_a_disk; int prev_match; + disk_t *dp_skip; disk_t *dp; if(sargc <= 0) @@ -1226,13 +1879,14 @@ match_disklist( match_a_host = 1; } match_a_disk = 0; + dp_skip = NULL; for(dp = origqp->head; dp != NULL; dp = dp->next) { if(prevhost != NULL && match_host(prevhost, dp->host->hostname) && (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 { @@ -1240,6 +1894,13 @@ match_disklist( dp->todo = 1; match_a_disk = 1; prev_match = 0; + } else if (dp->todo == 0) { + match_a_disk = 1; + prev_match = 0; + dp_skip = dp; + } else { /* dp->todo == 1 */ + match_a_disk = 1; + prev_match = 0; } } } @@ -1249,24 +1910,59 @@ match_disklist( if(prev_match == 1) { /* all disk of the previous host */ for(dp = origqp->head; dp != NULL; dp = dp->next) { if(match_host(prevhost,dp->host->hostname)) - if(dp->todo == -1) + if(dp->todo == -1) { dp->todo = 1; + match_a_disk = 1; + } + } + if (!match_a_disk) { + char *errstr1; + errstr1 = vstrallocf(_("All disks on host '%s' are ignored or have strategy \"skip\".\n"), prevhost); + vstrextend(&errstr, errstr1, NULL); + amfree(errstr1); } } prevhost = sargv[i]; prev_match = 1; } else { - vstrextend(&errstr, "Argument '", sargv[i], "' match neither a host nor a disk.\n", NULL); + char *errstr1; + if (strchr(sargv[i], (int)'\\')) { + errstr1 = vstrallocf(_("Argument '%s' matches neither a host nor a disk; quoting may not be correct.\n"), sargv[i]); + } else { + errstr1 = vstrallocf(_("Argument '%s' matches neither a host nor a disk.\n"), sargv[i]); + } + vstrextend(&errstr, errstr1, NULL); + amfree(errstr1); + prev_match = 0; } + } else if (dp_skip) { + char *errstr1; + if (dp_skip->strategy == DS_SKIP) { + errstr1 = vstrallocf(_("Argument '%s' matches a disk with strategy \"skip\".\n"), sargv[i]); + } else { + errstr1 = vstrallocf(_("Argument '%s' matches a disk marked \"ignore\".\n"), sargv[i]); + } + vstrextend(&errstr, errstr1, NULL); + amfree(errstr1); + prev_match = 0; } } if(prev_match == 1) { /* all disk of the previous host */ + match_a_disk = 0; for(dp = origqp->head; dp != NULL; dp = dp->next) { if(match_host(prevhost,dp->host->hostname)) - if(dp->todo == -1) + if(dp->todo == -1) { dp->todo = 1; + match_a_disk = 1; + } + } + if (!match_a_disk) { + char *errstr1; + errstr1 = vstrallocf(_("All disks on host '%s' are ignored or have strategy \"skip\".\n"), prevhost); + vstrextend(&errstr, errstr1, NULL); + amfree(errstr1); } } @@ -1278,6 +1974,42 @@ match_disklist( return errstr; } +gboolean +match_dumpfile( + dumpfile_t *file, + int sargc, + char ** sargv) +{ + disk_t d; + am_host_t h; + disklist_t dl; + + /* rather than try to reproduce the adaptive matching logic in + * match_disklist, this simply creates a new, fake disklist with one + * element in it, and calls match_disklist directly */ + + bzero(&h, sizeof(h)); + h.hostname = file->name; + h.disks = &d; + + bzero(&d, sizeof(d)); + d.host = &h; + d.hostname = file->name; + d.name = file->disk; + d.device = file->disk; + d.todo = 1; + + dl.head = dl.tail = &d; + + (void)match_disklist(&dl, sargc, sargv); + return d.todo; +} + +netif_t * +disklist_netifs(void) +{ + return all_netifs; +} #ifdef TEST @@ -1289,7 +2021,7 @@ 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); @@ -1303,31 +2035,34 @@ dump_disklist( 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) { 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")); } } @@ -1340,8 +2075,15 @@ main( char *conf_diskfile; disklist_t lst; int result; - unsigned long malloc_hist_1, malloc_size_1; - unsigned long malloc_hist_2, malloc_size_2; + + /* + * 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); @@ -1352,41 +2094,29 @@ main( /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); - malloc_size_1 = malloc_inuse(&malloc_hist_1); - 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); - } - result = read_diskfile(conf_diskfile, &lst); - if(result == 0) { - dump_disklist(&lst); + + 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; }