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 $
32 #include "client_util.h"
36 #define MAXMAXDUMPS 16
38 static int add_exclude(FILE *file_exclude, char *aexc, int verbose);
39 static int add_include(char *disk, char *device, FILE *file_include, char *ainc, int verbose);
40 static char *build_name(char *disk, char *exin, int verbose);
41 static char *get_name(char *diskname, char *exin, time_t t, int n);
51 char *dirname = amname_to_dirname(device);
52 newname = vstralloc(dirname, "/", name , NULL);
56 newname = stralloc(name);
69 char number[NUM_STR_SIZE];
73 ts = construct_timestamp(&t);
77 snprintf(number, SIZEOF(number), "%03d", n - 1);
79 filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".",
94 char *filename = NULL;
95 char *afilename = NULL;
101 struct dirent *entry;
103 size_t match_len, d_name_len;
107 diskname = sanitise_filename(disk);
109 dbgdir = stralloc2(AMANDA_TMPDIR, "/");
110 if((d = opendir(AMANDA_TMPDIR)) == NULL) {
111 error("open debug directory \"%s\": %s",
112 AMANDA_TMPDIR, strerror(errno));
115 test_name = get_name(diskname, exin,
116 curtime - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
117 match_len = strlen(get_pname()) + strlen(diskname) + 2;
118 while((entry = readdir(d)) != NULL) {
119 if(is_dot_or_dotdot(entry->d_name)) {
122 d_name_len = strlen(entry->d_name);
123 if(strncmp(test_name, entry->d_name, match_len) != 0
124 || d_name_len < match_len + 14 + 8
125 || strcmp(entry->d_name+ d_name_len - 7, exin) != 0) {
126 continue; /* not one of our files */
128 if(strcmp(entry->d_name, test_name) < 0) {
129 e = newvstralloc(e, dbgdir, entry->d_name, NULL);
130 (void) unlink(e); /* get rid of old file */
139 filename = get_name(diskname, exin, curtime, n);
140 afilename = newvstralloc(afilename, dbgdir, filename, NULL);
141 if((fd=open(afilename, O_WRONLY|O_CREAT|O_APPEND, 0600)) < 0){
149 } while(!afilename && n < 1000);
151 if(afilename == NULL) {
152 filename = get_name(diskname, exin, curtime, 0);
153 afilename = newvstralloc(afilename, dbgdir, filename, NULL);
154 quoted = quote_string(afilename);
155 dbprintf(("%s: Cannot create %s (%s)\n",
156 debug_prefix(NULL), quoted, strerror(errno)));
158 printf("ERROR [cannot create %s (%s)]\n",
159 quoted, strerror(errno));
182 (void)verbose; /* Quiet unused parameter warning */
185 if(aexc[l-1] == '\n') {
189 file = quoted = quote_string(aexc);
191 file[strlen(file) - 1] = '\0';
194 fprintf(file_exclude, "%s\n", file);
211 (void)disk; /* Quiet unused parameter warning */
214 if(ainc[l-1] == '\n') {
218 if (strncmp(ainc, "./", 2) != 0) {
219 quoted = quote_string(ainc);
220 dbprintf(("%s: include must start with './' (%s)\n",
221 debug_prefix(NULL), quoted));
223 printf("ERROR [include must start with './' (%s)]\n", quoted);
228 char *incname = ainc+2;
230 if(strchr(incname, '/')) {
231 file = quoted = quote_string(ainc);
233 file[strlen(file) - 1] = '\0';
236 fprintf(file_include, "%s\n", file);
243 struct dirent *entry;
245 regex = glob_to_regex(incname);
246 if((d = opendir(device)) == NULL) {
247 quoted = quote_string(device);
248 dbprintf(("%s: Can't open disk %s\n",
249 debug_prefix(NULL), quoted));
251 printf("ERROR [Can't open disk %s]\n", quoted);
256 while((entry = readdir(d)) != NULL) {
257 if(is_dot_or_dotdot(entry->d_name)) {
260 if(match(regex, entry->d_name)) {
261 incname = vstralloc("./", entry->d_name, NULL);
262 file = quoted = quote_string(incname);
264 file[strlen(file) - 1] = '\0';
267 fprintf(file_include, "%s\n", file);
296 if(options->exclude_file) nb_exclude += options->exclude_file->nb_element;
297 if(options->exclude_list) nb_exclude += options->exclude_list->nb_element;
299 if(nb_exclude == 0) return NULL;
301 if((filename = build_name(disk, "exclude", verbose)) != NULL) {
302 if((file_exclude = fopen(filename,"w")) != NULL) {
304 if(options->exclude_file) {
305 for(excl = options->exclude_file->first; excl != NULL;
307 add_exclude(file_exclude, excl->name,
308 verbose && options->exclude_optional == 0);
312 if(options->exclude_list) {
313 for(excl = options->exclude_list->first; excl != NULL;
315 char *exclname = fixup_relative(excl->name, device);
316 if((exclude = fopen(exclname, "r")) != NULL) {
317 while ((aexc = agets(exclude)) != NULL) {
318 if (aexc[0] == '\0') {
322 add_exclude(file_exclude, aexc,
323 verbose && options->exclude_optional == 0);
329 quoted = quote_string(exclname);
330 dbprintf(("%s: Can't open exclude file %s (%s)\n",
332 quoted, strerror(errno)));
333 if(verbose && (options->exclude_optional == 0 ||
335 printf("ERROR [Can't open exclude file %s (%s)]\n",
336 quoted, strerror(errno));
343 fclose(file_exclude);
346 quoted = quote_string(filename);
347 dbprintf(("%s: Can't create exclude file %s (%s)\n",
349 quoted, strerror(errno)));
351 printf("ERROR [Can't create exclude file %s (%s)]\n",
352 quoted, strerror(errno));
377 if(options->include_file) nb_include += options->include_file->nb_element;
378 if(options->include_list) nb_include += options->include_list->nb_element;
380 if(nb_include == 0) return NULL;
382 if((filename = build_name(disk, "include", verbose)) != NULL) {
383 if((file_include = fopen(filename,"w")) != NULL) {
385 if(options->include_file) {
386 for(incl = options->include_file->first; incl != NULL;
388 nb_exp += add_include(disk, device, file_include,
390 verbose && options->include_optional == 0);
394 if(options->include_list) {
395 for(incl = options->include_list->first; incl != NULL;
397 char *inclname = fixup_relative(incl->name, device);
398 if((include = fopen(inclname, "r")) != NULL) {
399 while ((ainc = agets(include)) != NULL) {
400 if (ainc[0] == '\0') {
404 nb_exp += add_include(disk, device,
406 verbose && options->include_optional == 0);
412 quoted = quote_string(inclname);
413 dbprintf(("%s: Can't open include file %s (%s)\n",
414 debug_prefix(NULL), quoted, strerror(errno)));
415 if(verbose && (options->include_optional == 0 ||
417 printf("ERROR [Can't open include file %s (%s)]\n",
418 quoted, strerror(errno));
425 fclose(file_include);
428 quoted = quote_string(filename);
429 dbprintf(("%s: Can't create include file %s (%s)\n",
430 debug_prefix(NULL), quoted, strerror(errno)));
432 printf("ERROR [Can't create include file %s (%s)]\n",
433 quoted, strerror(errno));
440 quoted = quote_string(disk);
441 dbprintf(("%s: No include for %s\n", debug_prefix(NULL), quoted));
442 if(verbose && options->include_optional == 0) {
443 printf("ERROR [No include for %s]\n", quoted);
457 options->compress = NO_COMPR;
458 options->srvcompprog = NULL;
459 options->clntcompprog = NULL;
460 options->encrypt = ENCRYPT_NONE;
461 options->srv_encrypt = NULL;
462 options->clnt_encrypt = NULL;
463 options->srv_decrypt_opt = NULL;
464 options->clnt_decrypt_opt = NULL;
465 options->no_record = 0;
466 options->createindex = 0;
467 options->auth = NULL;
468 options->exclude_file = NULL;
469 options->exclude_list = NULL;
470 options->include_file = NULL;
471 options->include_list = NULL;
472 options->exclude_optional = 0;
473 options->include_optional = 0;
491 (void)disk; /* Quiet unused parameter warning */
492 (void)device; /* Quiet unused parameter warning */
494 options = alloc(SIZEOF(option_t));
495 init_options(options);
496 options->str = stralloc(str);
501 while (tok != NULL) {
502 if(am_has_feature(fs, fe_options_auth)
503 && BSTRNCMP(tok,"auth=") == 0) {
504 if(options->auth != NULL) {
505 quoted = quote_string(tok + 5);
506 dbprintf(("%s: multiple auth option %s\n",
507 debug_prefix(NULL), quoted));
509 printf("ERROR [multiple auth option %s]\n", quoted);
513 options->auth = stralloc(&tok[5]);
515 else if(am_has_feature(fs, fe_options_bsd_auth)
516 && BSTRNCMP(tok, "bsd-auth") == 0) {
517 if(options->auth != NULL) {
518 dbprintf(("%s: multiple auth option\n",
519 debug_prefix(NULL)));
521 printf("ERROR [multiple auth option]\n");
524 options->auth = stralloc("bsd");
526 else if(am_has_feature(fs, fe_options_krb4_auth)
527 && BSTRNCMP(tok, "krb4-auth") == 0) {
528 if(options->auth != NULL) {
529 dbprintf(("%s: multiple auth option\n",
530 debug_prefix(NULL)));
532 printf("ERROR [multiple auth option]\n");
535 options->auth = stralloc("krb4");
537 else if(BSTRNCMP(tok, "compress-fast") == 0) {
538 if(options->compress != NO_COMPR) {
539 dbprintf(("%s: multiple compress option\n",
540 debug_prefix(NULL)));
542 printf("ERROR [multiple compress option]\n");
545 options->compress = COMPR_FAST;
547 else if(BSTRNCMP(tok, "compress-best") == 0) {
548 if(options->compress != NO_COMPR) {
549 dbprintf(("%s: multiple compress option\n",
550 debug_prefix(NULL)));
552 printf("ERROR [multiple compress option]\n");
555 options->compress = COMPR_BEST;
557 else if(BSTRNCMP(tok, "srvcomp-fast") == 0) {
558 if(options->compress != NO_COMPR) {
559 dbprintf(("%s: multiple compress option\n",
560 debug_prefix(NULL)));
562 printf("ERROR [multiple compress option]\n");
565 options->compress = COMPR_SERVER_FAST;
567 else if(BSTRNCMP(tok, "srvcomp-best") == 0) {
568 if(options->compress != NO_COMPR) {
569 dbprintf(("%s: multiple compress option\n",
570 debug_prefix(NULL)));
572 printf("ERROR [multiple compress option]\n");
575 options->compress = COMPR_SERVER_BEST;
577 else if(BSTRNCMP(tok, "srvcomp-cust=") == 0) {
578 if(options->compress != NO_COMPR) {
579 dbprintf(("%s: multiple compress option\n",
580 debug_prefix(NULL)));
582 printf("ERROR [multiple compress option]\n");
585 options->srvcompprog = stralloc(tok + SIZEOF("srvcomp-cust=") -1);
586 options->compress = COMPR_SERVER_CUST;
588 else if(BSTRNCMP(tok, "comp-cust=") == 0) {
589 if(options->compress != NO_COMPR) {
590 dbprintf(("%s: multiple compress option\n",
591 debug_prefix(NULL)));
593 printf("ERROR [multiple compress option]\n");
596 options->clntcompprog = stralloc(tok + SIZEOF("comp-cust=") -1);
597 options->compress = COMPR_CUST;
598 /* parse encryption options */
600 else if(BSTRNCMP(tok, "encrypt-serv-cust=") == 0) {
601 if(options->encrypt != ENCRYPT_NONE) {
602 dbprintf(("%s: multiple encrypt option\n",
603 debug_prefix(NULL)));
605 printf("ERROR [multiple encrypt option]\n");
608 options->srv_encrypt = stralloc(tok + SIZEOF("encrypt-serv-cust=") -1);
609 options->encrypt = ENCRYPT_SERV_CUST;
611 else if(BSTRNCMP(tok, "encrypt-cust=") == 0) {
612 if(options->encrypt != ENCRYPT_NONE) {
613 dbprintf(("%s: multiple encrypt option\n",
614 debug_prefix(NULL)));
616 printf("ERROR [multiple encrypt option]\n");
619 options->clnt_encrypt= stralloc(tok + SIZEOF("encrypt-cust=") -1);
620 options->encrypt = ENCRYPT_CUST;
622 else if(BSTRNCMP(tok, "server-decrypt-option=") == 0) {
623 options->srv_decrypt_opt = stralloc(tok + SIZEOF("server-decrypt-option=") -1);
625 else if(BSTRNCMP(tok, "client-decrypt-option=") == 0) {
626 options->clnt_decrypt_opt = stralloc(tok + SIZEOF("client-decrypt-option=") -1);
628 else if(BSTRNCMP(tok, "no-record") == 0) {
629 if(options->no_record != 0) {
630 dbprintf(("%s: multiple no-record option\n",
631 debug_prefix(NULL)));
633 printf("ERROR [multiple no-record option]\n");
636 options->no_record = 1;
638 else if(BSTRNCMP(tok, "index") == 0) {
639 if(options->createindex != 0) {
640 dbprintf(("%s: multiple index option\n",
641 debug_prefix(NULL)));
643 printf("ERROR [multiple index option]\n");
646 options->createindex = 1;
648 else if(BSTRNCMP(tok, "exclude-optional") == 0) {
649 if(options->exclude_optional != 0) {
650 dbprintf(("%s: multiple exclude-optional option\n",
651 debug_prefix(NULL)));
653 printf("ERROR [multiple exclude-optional option]\n");
656 options->exclude_optional = 1;
658 else if(strcmp(tok, "include-optional") == 0) {
659 if(options->include_optional != 0) {
660 dbprintf(("%s: multiple include-optional option\n",
661 debug_prefix(NULL)));
663 printf("ERROR [multiple include-optional option]\n");
666 options->include_optional = 1;
668 else if(BSTRNCMP(tok,"exclude-file=") == 0) {
669 exc = unquote_string(&tok[13]);
670 options->exclude_file = append_sl(options->exclude_file, exc);
673 else if(BSTRNCMP(tok,"exclude-list=") == 0) {
674 exc = unquote_string(&tok[13]);
675 options->exclude_list = append_sl(options->exclude_list, exc);
678 else if(BSTRNCMP(tok,"include-file=") == 0) {
679 inc = unquote_string(&tok[13]);
680 options->include_file = append_sl(options->include_file, inc);
683 else if(BSTRNCMP(tok,"include-list=") == 0) {
684 inc = unquote_string(&tok[13]);
685 options->include_list = append_sl(options->include_list, inc);
688 else if(strcmp(tok,"|") != 0) {
689 quoted = quote_string(tok);
690 dbprintf(("%s: unknown option %s\n",
691 debug_prefix(NULL), quoted));
693 printf("ERROR [unknown option: %s]\n", quoted);
697 tok = strtok(NULL, ";");