2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: client_util.c,v 1.34 2006/05/25 01:47:11 johnfranks Exp $
33 #include "client_util.h"
36 #include "pipespawn.h"
38 #define MAXMAXDUMPS 16
40 static int add_exclude(FILE *file_exclude, char *aexc, int verbose);
41 static int add_include(char *disk, char *device, FILE *file_include, char *ainc, int verbose);
42 static char *build_name(char *disk, char *exin, int verbose);
43 static char *get_name(char *diskname, char *exin, time_t t, int n);
53 char *dirname = amname_to_dirname(device);
54 newname = vstralloc(dirname, "/", name , NULL);
58 newname = stralloc(name);
71 char number[NUM_STR_SIZE];
75 ts = construct_timestamp(&t);
79 snprintf(number, SIZEOF(number), "%03d", n - 1);
81 filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".",
96 char *filename = NULL;
97 char *afilename = NULL;
103 struct dirent *entry;
105 size_t match_len, d_name_len;
109 diskname = sanitise_filename(disk);
111 dbgdir = stralloc2(AMANDA_TMPDIR, "/");
112 if((d = opendir(AMANDA_TMPDIR)) == NULL) {
113 error("open debug directory \"%s\": %s",
114 AMANDA_TMPDIR, strerror(errno));
117 test_name = get_name(diskname, exin,
118 curtime - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
119 match_len = strlen(get_pname()) + strlen(diskname) + 2;
120 while((entry = readdir(d)) != NULL) {
121 if(is_dot_or_dotdot(entry->d_name)) {
124 d_name_len = strlen(entry->d_name);
125 if(strncmp(test_name, entry->d_name, match_len) != 0
126 || d_name_len < match_len + 14 + 8
127 || strcmp(entry->d_name+ d_name_len - 7, exin) != 0) {
128 continue; /* not one of our files */
130 if(strcmp(entry->d_name, test_name) < 0) {
131 e = newvstralloc(e, dbgdir, entry->d_name, NULL);
132 (void) unlink(e); /* get rid of old file */
141 filename = get_name(diskname, exin, curtime, n);
142 afilename = newvstralloc(afilename, dbgdir, filename, NULL);
143 if((fd=open(afilename, O_WRONLY|O_CREAT|O_APPEND, 0600)) < 0){
151 } while(!afilename && n < 1000);
153 if(afilename == NULL) {
154 filename = get_name(diskname, exin, curtime, 0);
155 afilename = newvstralloc(afilename, dbgdir, filename, NULL);
156 quoted = quote_string(afilename);
157 dbprintf(("%s: Cannot create %s (%s)\n",
158 debug_prefix_time(NULL), quoted, strerror(errno)));
160 printf("ERROR [cannot create %s (%s)]\n",
161 quoted, strerror(errno));
184 (void)verbose; /* Quiet unused parameter warning */
187 if(aexc[l-1] == '\n') {
191 file = quoted = quote_string(aexc);
193 file[strlen(file) - 1] = '\0';
196 fprintf(file_exclude, "%s\n", file);
213 (void)disk; /* Quiet unused parameter warning */
216 if(ainc[l-1] == '\n') {
220 if (strncmp(ainc, "./", 2) != 0) {
221 quoted = quote_string(ainc);
222 dbprintf(("%s: include must start with './' (%s)\n",
223 debug_prefix_time(NULL), quoted));
225 printf("ERROR [include must start with './' (%s)]\n", quoted);
230 char *incname = ainc+2;
232 if(strchr(incname, '/')) {
233 file = quoted = quote_string(ainc);
235 file[strlen(file) - 1] = '\0';
238 fprintf(file_include, "%s\n", file);
245 struct dirent *entry;
247 regex = glob_to_regex(incname);
248 if((d = opendir(device)) == NULL) {
249 quoted = quote_string(device);
250 dbprintf(("%s: Can't open disk %s\n",
251 debug_prefix_time(NULL), quoted));
253 printf("ERROR [Can't open disk %s]\n", quoted);
258 while((entry = readdir(d)) != NULL) {
259 if(is_dot_or_dotdot(entry->d_name)) {
262 if(match(regex, entry->d_name)) {
263 incname = vstralloc("./", entry->d_name, NULL);
264 file = quoted = quote_string(incname);
266 file[strlen(file) - 1] = '\0';
269 fprintf(file_include, "%s\n", file);
298 if(options->exclude_file) nb_exclude += options->exclude_file->nb_element;
299 if(options->exclude_list) nb_exclude += options->exclude_list->nb_element;
301 if(nb_exclude == 0) return NULL;
303 if((filename = build_name(disk, "exclude", verbose)) != NULL) {
304 if((file_exclude = fopen(filename,"w")) != NULL) {
306 if(options->exclude_file) {
307 for(excl = options->exclude_file->first; excl != NULL;
309 add_exclude(file_exclude, excl->name,
310 verbose && options->exclude_optional == 0);
314 if(options->exclude_list) {
315 for(excl = options->exclude_list->first; excl != NULL;
317 char *exclname = fixup_relative(excl->name, device);
318 if((exclude = fopen(exclname, "r")) != NULL) {
319 while ((aexc = agets(exclude)) != NULL) {
320 if (aexc[0] == '\0') {
324 add_exclude(file_exclude, aexc,
325 verbose && options->exclude_optional == 0);
331 quoted = quote_string(exclname);
332 dbprintf(("%s: Can't open exclude file %s (%s)\n",
333 debug_prefix_time(NULL),
334 quoted, strerror(errno)));
335 if(verbose && (options->exclude_optional == 0 ||
337 printf("ERROR [Can't open exclude file %s (%s)]\n",
338 quoted, strerror(errno));
345 fclose(file_exclude);
348 quoted = quote_string(filename);
349 dbprintf(("%s: Can't create exclude file %s (%s)\n",
350 debug_prefix_time(NULL),
351 quoted, strerror(errno)));
353 printf("ERROR [Can't create exclude file %s (%s)]\n",
354 quoted, strerror(errno));
379 if(options->include_file) nb_include += options->include_file->nb_element;
380 if(options->include_list) nb_include += options->include_list->nb_element;
382 if(nb_include == 0) return NULL;
384 if((filename = build_name(disk, "include", verbose)) != NULL) {
385 if((file_include = fopen(filename,"w")) != NULL) {
387 if(options->include_file) {
388 for(incl = options->include_file->first; incl != NULL;
390 nb_exp += add_include(disk, device, file_include,
392 verbose && options->include_optional == 0);
396 if(options->include_list) {
397 for(incl = options->include_list->first; incl != NULL;
399 char *inclname = fixup_relative(incl->name, device);
400 if((include = fopen(inclname, "r")) != NULL) {
401 while ((ainc = agets(include)) != NULL) {
402 if (ainc[0] == '\0') {
406 nb_exp += add_include(disk, device,
408 verbose && options->include_optional == 0);
414 quoted = quote_string(inclname);
415 dbprintf(("%s: Can't open include file %s (%s)\n",
416 debug_prefix_time(NULL), quoted, strerror(errno)));
417 if(verbose && (options->include_optional == 0 ||
419 printf("ERROR [Can't open include file %s (%s)]\n",
420 quoted, strerror(errno));
427 fclose(file_include);
430 quoted = quote_string(filename);
431 dbprintf(("%s: Can't create include file %s (%s)\n",
432 debug_prefix_time(NULL), quoted, strerror(errno)));
434 printf("ERROR [Can't create include file %s (%s)]\n",
435 quoted, strerror(errno));
442 quoted = quote_string(disk);
443 dbprintf(("%s: No include for %s\n", debug_prefix_time(NULL), quoted));
444 if(verbose && options->include_optional == 0) {
445 printf("ERROR [No include for %s]\n", quoted);
459 options->compress = COMP_NONE;
460 options->srvcompprog = NULL;
461 options->clntcompprog = NULL;
462 options->encrypt = ENCRYPT_NONE;
463 options->srv_encrypt = NULL;
464 options->clnt_encrypt = NULL;
465 options->srv_decrypt_opt = NULL;
466 options->clnt_decrypt_opt = NULL;
467 options->no_record = 0;
468 options->createindex = 0;
469 options->auth = NULL;
470 options->exclude_file = NULL;
471 options->exclude_list = NULL;
472 options->include_file = NULL;
473 options->include_list = NULL;
474 options->exclude_optional = 0;
475 options->include_optional = 0;
493 (void)disk; /* Quiet unused parameter warning */
494 (void)device; /* Quiet unused parameter warning */
496 options = alloc(SIZEOF(option_t));
497 init_options(options);
498 options->str = stralloc(str);
503 while (tok != NULL) {
504 if(am_has_feature(fs, fe_options_auth)
505 && BSTRNCMP(tok,"auth=") == 0) {
506 if(options->auth != NULL) {
507 quoted = quote_string(tok + 5);
508 dbprintf(("%s: multiple auth option %s\n",
509 debug_prefix_time(NULL), quoted));
511 printf("ERROR [multiple auth option %s]\n", quoted);
515 options->auth = stralloc(&tok[5]);
517 else if(am_has_feature(fs, fe_options_bsd_auth)
518 && BSTRNCMP(tok, "bsd-auth") == 0) {
519 if(options->auth != NULL) {
520 dbprintf(("%s: multiple auth option\n",
521 debug_prefix_time(NULL)));
523 printf("ERROR [multiple auth option]\n");
526 options->auth = stralloc("bsd");
528 else if(am_has_feature(fs, fe_options_krb4_auth)
529 && BSTRNCMP(tok, "krb4-auth") == 0) {
530 if(options->auth != NULL) {
531 dbprintf(("%s: multiple auth option\n",
532 debug_prefix_time(NULL)));
534 printf("ERROR [multiple auth option]\n");
537 options->auth = stralloc("krb4");
539 else if(BSTRNCMP(tok, "compress-fast") == 0) {
540 if(options->compress != COMP_NONE) {
541 dbprintf(("%s: multiple compress option\n",
542 debug_prefix_time(NULL)));
544 printf("ERROR [multiple compress option]\n");
547 options->compress = COMP_FAST;
549 else if(BSTRNCMP(tok, "compress-best") == 0) {
550 if(options->compress != COMP_NONE) {
551 dbprintf(("%s: multiple compress option\n",
552 debug_prefix_time(NULL)));
554 printf("ERROR [multiple compress option]\n");
557 options->compress = COMP_BEST;
559 else if(BSTRNCMP(tok, "srvcomp-fast") == 0) {
560 if(options->compress != COMP_NONE) {
561 dbprintf(("%s: multiple compress option\n",
562 debug_prefix_time(NULL)));
564 printf("ERROR [multiple compress option]\n");
567 options->compress = COMP_SERVER_FAST;
569 else if(BSTRNCMP(tok, "srvcomp-best") == 0) {
570 if(options->compress != COMP_NONE) {
571 dbprintf(("%s: multiple compress option\n",
572 debug_prefix_time(NULL)));
574 printf("ERROR [multiple compress option]\n");
577 options->compress = COMP_SERVER_BEST;
579 else if(BSTRNCMP(tok, "srvcomp-cust=") == 0) {
580 if(options->compress != COMP_NONE) {
581 dbprintf(("%s: multiple compress option\n",
582 debug_prefix_time(NULL)));
584 printf("ERROR [multiple compress option]\n");
587 options->srvcompprog = stralloc(tok + SIZEOF("srvcomp-cust=") -1);
588 options->compress = COMP_SERVER_CUST;
590 else if(BSTRNCMP(tok, "comp-cust=") == 0) {
591 if(options->compress != COMP_NONE) {
592 dbprintf(("%s: multiple compress option\n",
593 debug_prefix_time(NULL)));
595 printf("ERROR [multiple compress option]\n");
598 options->clntcompprog = stralloc(tok + SIZEOF("comp-cust=") -1);
599 options->compress = COMP_CUST;
600 /* parse encryption options */
602 else if(BSTRNCMP(tok, "encrypt-serv-cust=") == 0) {
603 if(options->encrypt != ENCRYPT_NONE) {
604 dbprintf(("%s: multiple encrypt option\n",
605 debug_prefix_time(NULL)));
607 printf("ERROR [multiple encrypt option]\n");
610 options->srv_encrypt = stralloc(tok + SIZEOF("encrypt-serv-cust=") -1);
611 options->encrypt = ENCRYPT_SERV_CUST;
613 else if(BSTRNCMP(tok, "encrypt-cust=") == 0) {
614 if(options->encrypt != ENCRYPT_NONE) {
615 dbprintf(("%s: multiple encrypt option\n",
616 debug_prefix_time(NULL)));
618 printf("ERROR [multiple encrypt option]\n");
621 options->clnt_encrypt= stralloc(tok + SIZEOF("encrypt-cust=") -1);
622 options->encrypt = ENCRYPT_CUST;
624 else if(BSTRNCMP(tok, "server-decrypt-option=") == 0) {
625 options->srv_decrypt_opt = stralloc(tok + SIZEOF("server-decrypt-option=") -1);
627 else if(BSTRNCMP(tok, "client-decrypt-option=") == 0) {
628 options->clnt_decrypt_opt = stralloc(tok + SIZEOF("client-decrypt-option=") -1);
630 else if(BSTRNCMP(tok, "no-record") == 0) {
631 if(options->no_record != 0) {
632 dbprintf(("%s: multiple no-record option\n",
633 debug_prefix_time(NULL)));
635 printf("ERROR [multiple no-record option]\n");
638 options->no_record = 1;
640 else if(BSTRNCMP(tok, "index") == 0) {
641 if(options->createindex != 0) {
642 dbprintf(("%s: multiple index option\n",
643 debug_prefix_time(NULL)));
645 printf("ERROR [multiple index option]\n");
648 options->createindex = 1;
650 else if(BSTRNCMP(tok, "exclude-optional") == 0) {
651 if(options->exclude_optional != 0) {
652 dbprintf(("%s: multiple exclude-optional option\n",
653 debug_prefix_time(NULL)));
655 printf("ERROR [multiple exclude-optional option]\n");
658 options->exclude_optional = 1;
660 else if(strcmp(tok, "include-optional") == 0) {
661 if(options->include_optional != 0) {
662 dbprintf(("%s: multiple include-optional option\n",
663 debug_prefix_time(NULL)));
665 printf("ERROR [multiple include-optional option]\n");
668 options->include_optional = 1;
670 else if(BSTRNCMP(tok,"exclude-file=") == 0) {
671 exc = unquote_string(&tok[13]);
672 options->exclude_file = append_sl(options->exclude_file, exc);
675 else if(BSTRNCMP(tok,"exclude-list=") == 0) {
676 exc = unquote_string(&tok[13]);
677 options->exclude_list = append_sl(options->exclude_list, exc);
680 else if(BSTRNCMP(tok,"include-file=") == 0) {
681 inc = unquote_string(&tok[13]);
682 options->include_file = append_sl(options->include_file, inc);
685 else if(BSTRNCMP(tok,"include-list=") == 0) {
686 inc = unquote_string(&tok[13]);
687 options->include_list = append_sl(options->include_list, inc);
690 else if(strcmp(tok,"|") != 0) {
691 quoted = quote_string(tok);
692 dbprintf(("%s: unknown option %s\n",
693 debug_prefix_time(NULL), quoted));
695 printf("ERROR [unknown option: %s]\n", quoted);
699 tok = strtok(NULL, ";");
706 output_tool_property(
713 if (!is_empty_sl(options->exclude_file)) {
714 for(sle = options->exclude_file->first ; sle != NULL; sle=sle->next) {
715 q = quote_string(sle->name);
716 fprintf(tool, "EXCLUDE-FILE %s\n", q);
721 if (!is_empty_sl(options->exclude_list)) {
722 for(sle = options->exclude_list->first ; sle != NULL; sle=sle->next) {
723 q = quote_string(sle->name);
724 fprintf(tool, "EXCLUDE-LIST %s\n", q);
729 if (!is_empty_sl(options->include_file)) {
730 for(sle = options->include_file->first ; sle != NULL; sle=sle->next) {
731 q = quote_string(sle->name);
732 fprintf(tool, "INCLUDE-FILE %s\n", q);
737 if (!is_empty_sl(options->include_list)) {
738 for(sle = options->include_list->first ; sle != NULL; sle=sle->next) {
739 q = quote_string(sle->name);
740 fprintf(tool, "INCLUDE-LIST %s\n", q);
745 if (!is_empty_sl(options->exclude_file) ||
746 !is_empty_sl(options->exclude_list)) {
747 if (options->exclude_optional)
748 fprintf(tool, "EXCLUDE-OPTIONAL YES\n");
750 fprintf(tool, "EXCLUDE-OPTIONAL NO\n");
753 if (!is_empty_sl(options->include_file) ||
754 !is_empty_sl(options->include_list)) {
755 if (options->include_optional)
756 fprintf(tool, "INCLUDE-OPTIONAL YES\n");
758 fprintf(tool, "INCLUDE-OPTIONAL NO\n");
762 backup_support_option_t *
763 backup_support_option(
765 g_option_t *g_options,
770 int supportin, supportout, supporterr;
776 backup_support_option_t *bsu;
778 cmd = vstralloc(DUMPER_DIR, "/", program, NULL);
779 argvchild = malloc(5 * SIZEOF(char *));
781 argvchild[i++] = program;
782 argvchild[i++] = "support";
783 if (g_options->config) {
784 argvchild[i++] = "--config";
785 argvchild[i++] = g_options->config;
787 if (g_options->hostname) {
788 argvchild[i++] = "--host";
789 argvchild[i++] = g_options->hostname;
792 argvchild[i++] = "--disk";
793 argvchild[i++] = disk;
796 argvchild[i++] = "--device";
797 argvchild[i++] = amdevice;
799 argvchild[i++] = NULL;
801 supporterr = fileno(stderr);
802 supportpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE, &supportin,
803 &supportout, &supporterr, argvchild);
807 bsu = malloc(SIZEOF(*bsu));
808 memset(bsu, '\0', SIZEOF(*bsu));
809 streamout = fdopen(supportout, "r");
810 while((line = agets(streamout)) != NULL) {
811 dbprintf(("support line: %s\n", line));
812 if (strncmp(line,"CONFIG ", 7) == 0) {
813 if (strcmp(line+7, "YES") == 0)
815 } else if (strncmp(line,"HOST ", 5) == 0) {
816 if (strcmp(line+5, "YES") == 0)
818 } else if (strncmp(line,"DISK ", 5) == 0) {
819 if (strcmp(line+5, "YES") == 0)
821 } else if (strncmp(line,"INDEX-LINE ", 11) == 0) {
822 if (strcmp(line+11, "YES") == 0)
824 } else if (strncmp(line,"INDEX-XML ", 10) == 0) {
825 if (strcmp(line+10, "YES") == 0)
827 } else if (strncmp(line,"MESSAGE-LINE ", 13) == 0) {
828 if (strcmp(line+13, "YES") == 0)
829 bsu->message_line = 1;
830 } else if (strncmp(line,"MESSAGE-XML ", 12) == 0) {
831 if (strcmp(line+12, "YES") == 0)
832 bsu->message_xml = 1;
833 } else if (strncmp(line,"RECORD ", 7) == 0) {
834 if (strcmp(line+7, "YES") == 0)
836 } else if (strncmp(line,"INCLUDE-FILE ", 13) == 0) {
837 if (strcmp(line+13, "YES") == 0)
838 bsu->include_file = 1;
839 } else if (strncmp(line,"INCLUDE-LIST ", 13) == 0) {
840 if (strcmp(line+13, "YES") == 0)
841 bsu->include_list = 1;
842 } else if (strncmp(line,"EXCLUDE-FILE ", 13) == 0) {
843 if (strcmp(line+13, "YES") == 0)
844 bsu->exclude_file = 1;
845 } else if (strncmp(line,"EXCLUDE-LIST ", 13) == 0) {
846 if (strcmp(line+13, "YES") == 0)
847 bsu->exclude_list = 1;
848 } else if (strncmp(line,"COLLECTION ", 11) == 0) {
849 if (strcmp(line+11, "YES") == 0)
851 } else if (strncmp(line,"MAX-LEVEL ", 10) == 0) {
852 bsu->max_level = atoi(line+10);
854 dbprintf(("Invalid support line: %s\n", line));