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.1.2.27 2003/07/02 17:03:32 martinea Exp $
31 #include "client_util.h"
35 #define MAXMAXDUMPS 16
37 static char *fixup_relative(name, device)
43 char *dirname = amname_to_dirname(device);
44 newname = vstralloc(dirname, "/", name , NULL);
48 newname = stralloc(name);
54 static char *get_name(diskname, exin, t, n)
55 char *diskname, *exin;
59 char number[NUM_STR_SIZE];
63 ts = construct_timestamp(&t);
67 ap_snprintf(number, sizeof(number), "%03d", n - 1);
69 filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".",
76 static char *build_name(disk, exin, verbose)
80 char *filename = NULL;
81 char *afilename = NULL;
88 char *test_name = NULL;
89 int match_len, d_name_len;
93 diskname = sanitise_filename(disk);
95 dbgdir = stralloc2(AMANDA_TMPDIR, "/");
96 if((d = opendir(AMANDA_TMPDIR)) == NULL) {
97 error("open debug directory \"%s\": %s",
98 AMANDA_TMPDIR, strerror(errno));
100 test_name = get_name(diskname, exin,
101 curtime - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
102 match_len = strlen(get_pname()) + strlen(diskname) + 2;
103 while((entry = readdir(d)) != NULL) {
104 if(is_dot_or_dotdot(entry->d_name)) {
107 d_name_len = strlen(entry->d_name);
108 if(strncmp(test_name, entry->d_name, match_len) != 0
109 || d_name_len < match_len + 14 + 8
110 || strcmp(entry->d_name+ d_name_len - 7, exin) != 0) {
111 continue; /* not one of our files */
113 if(strcmp(entry->d_name, test_name) < 0) {
114 e = newvstralloc(e, dbgdir, entry->d_name, NULL);
115 (void) unlink(e); /* get rid of old file */
124 filename = get_name(diskname, exin, curtime, n);
125 afilename = newvstralloc(afilename, dbgdir, filename, NULL);
126 if((fd=open(afilename, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0600)) < 0){
134 } while(!afilename && n < 1000);
136 if(afilename == NULL) {
137 filename = get_name(diskname, exin, curtime, 0);
138 afilename = newvstralloc(afilename, dbgdir, filename, NULL);
139 dbprintf(("%s: Cannot create '%s'\n", debug_prefix(NULL), afilename));
141 printf("ERROR [cannot create: %s]\n", afilename);
153 static int add_exclude(file_exclude, aexc, verbose)
160 if(aexc[l-1] == '\n') {
164 fprintf(file_exclude, "%s\n", aexc);
168 static int add_include(disk, device, file_include, ainc, verbose)
177 if(ainc[l-1] == '\n') {
182 dbprintf(("%s: include must be at least 3 character long: %s\n",
183 debug_prefix(NULL), ainc));
185 printf("ERROR [include must be at least 3 character long: %s]\n", ainc);
188 else if(ainc[0] != '.' && ainc[0] != '\0' && ainc[1] != '/') {
189 dbprintf(("%s: include must start with './': %s\n",
190 debug_prefix(NULL), ainc));
192 printf("ERROR [include must start with './': %s]\n", ainc);
196 char *incname = ainc+2;
197 if(strchr(incname, '/')) {
198 fprintf(file_include, "./%s\n", incname);
204 struct dirent *entry;
206 regex = glob_to_regex(incname);
207 if((d = opendir(device)) == NULL) {
208 dbprintf(("%s: Can't open disk '%s']\n",
209 debug_prefix(NULL), device));
211 printf("ERROR [Can't open disk '%s']\n", device);
215 while((entry = readdir(d)) != NULL) {
216 if(is_dot_or_dotdot(entry->d_name)) {
219 if(match(regex, entry->d_name)) {
220 fprintf(file_include, "./%s\n", entry->d_name);
231 char *build_exclude(disk, device, options, verbose)
243 if(options->exclude_file) nb_exclude += options->exclude_file->nb_element;
244 if(options->exclude_list) nb_exclude += options->exclude_list->nb_element;
246 if(nb_exclude == 0) return NULL;
248 if((filename = build_name(disk, "exclude", verbose)) != NULL) {
249 if((file_exclude = fopen(filename,"w")) != NULL) {
251 if(options->exclude_file) {
252 for(excl = options->exclude_file->first; excl != NULL;
254 add_exclude(file_exclude, excl->name,
255 verbose && options->exclude_optional == 0);
259 if(options->exclude_list) {
260 for(excl = options->exclude_list->first; excl != NULL;
262 char *exclname = fixup_relative(excl->name, device);
263 if((exclude = fopen(exclname, "r")) != NULL) {
264 while ((aexc = agets(exclude)) != NULL) {
265 add_exclude(file_exclude, aexc,
266 verbose && options->exclude_optional == 0);
272 dbprintf(("%s: Can't open exclude file '%s': %s\n",
276 if(verbose && (options->exclude_optional == 0 ||
278 printf("ERROR [Can't open exclude file '%s': %s]\n",
279 exclname, strerror(errno));
284 fclose(file_exclude);
287 dbprintf(("%s: Can't create exclude file '%s': %s\n",
292 printf("ERROR [Can't create exclude file '%s': %s]\n", filename,
300 char *build_include(disk, device, options, verbose)
314 if(options->include_file) nb_include += options->include_file->nb_element;
315 if(options->include_list) nb_include += options->include_list->nb_element;
317 if(nb_include == 0) return NULL;
319 if((filename = build_name(disk, "include", verbose)) != NULL) {
320 if((file_include = fopen(filename,"w")) != NULL) {
322 if(options->include_file) {
323 for(incl = options->include_file->first; incl != NULL;
325 nb_exp += add_include(disk, device, file_include,
327 verbose && options->include_optional == 0);
331 if(options->include_list) {
332 for(incl = options->include_list->first; incl != NULL;
334 char *inclname = fixup_relative(incl->name, device);
335 if((include = fopen(inclname, "r")) != NULL) {
336 while ((ainc = agets(include)) != NULL) {
337 nb_exp += add_include(disk, device,
339 verbose && options->include_optional == 0);
345 dbprintf(("%s: Can't open include file '%s': %s\n",
349 if(verbose && (options->include_optional == 0 ||
351 printf("ERROR [Can't open include file '%s': %s]\n",
352 inclname, strerror(errno));
357 fclose(file_include);
360 dbprintf(("%s: Can't create include file '%s': %s\n",
365 printf("ERROR [Can't create include file '%s': %s]\n", filename,
371 dbprintf(("%s: No include for '%s'\n", debug_prefix(NULL), disk));
372 if(verbose && options->include_optional == 0)
373 printf("ERROR [No include for '%s']\n", disk);
380 void init_options(options)
384 options->compress = NO_COMPR;
385 options->no_record = 0;
386 options->bsd_auth = 0;
387 options->createindex = 0;
389 options->krb4_auth = 0;
390 options->kencrypt = 0;
392 options->exclude_file = NULL;
393 options->exclude_list = NULL;
394 options->include_file = NULL;
395 options->include_list = NULL;
396 options->exclude_optional = 0;
397 options->include_optional = 0;
401 option_t *parse_options(str, disk, device, fs, verbose)
411 options = alloc(sizeof(option_t));
412 init_options(options);
413 options->str = stralloc(str);
418 while (tok != NULL) {
419 if(am_has_feature(fs, fe_options_auth)
420 && strncmp(tok, "auth=", 5) == 0) {
426 dbprintf(("%s: multiple auth option\n",
427 debug_prefix(NULL)));
429 printf("ERROR [multiple auth option]\n");
432 if(strcasecmp(tok + 5, "bsd") == 0) {
433 options->bsd_auth = 1;
436 else if(strcasecmp(tok + 5, "krb4") == 0) {
437 options->krb4_auth = 1;
441 dbprintf(("%s: unknown auth= value \"%s\"\n",
442 debug_prefix(NULL), tok + 5));
444 printf("ERROR [unknown auth= value \"%s\"]\n", tok + 5);
448 else if(strcmp(tok, "compress-fast") == 0) {
449 if(options->compress != NO_COMPR) {
450 dbprintf(("%s: multiple compress option\n",
451 debug_prefix(NULL)));
453 printf("ERROR [multiple compress option]\n");
456 options->compress = COMPR_FAST;
458 else if(strcmp(tok, "compress-best") == 0) {
459 if(options->compress != NO_COMPR) {
460 dbprintf(("%s: multiple compress option\n",
461 debug_prefix(NULL)));
463 printf("ERROR [multiple compress option]\n");
466 options->compress = COMPR_BEST;
468 else if(strcmp(tok, "srvcomp-fast") == 0) {
469 if(options->compress != NO_COMPR) {
470 dbprintf(("%s: multiple compress option\n",
471 debug_prefix(NULL)));
473 printf("ERROR [multiple compress option]\n");
476 options->compress = COMPR_SERVER_FAST;
478 else if(strcmp(tok, "srvcomp-best") == 0) {
479 if(options->compress != NO_COMPR) {
480 dbprintf(("%s: multiple compress option\n",
481 debug_prefix(NULL)));
483 printf("ERROR [multiple compress option]\n");
486 options->compress = COMPR_SERVER_BEST;
488 else if(strcmp(tok, "no-record") == 0) {
489 if(options->no_record != 0) {
490 dbprintf(("%s: multiple no-record option\n",
491 debug_prefix(NULL)));
493 printf("ERROR [multiple no-record option]\n");
496 options->no_record = 1;
498 else if(strcmp(tok, "bsd-auth") == 0) {
504 dbprintf(("%s: multiple auth option\n",
505 debug_prefix(NULL)));
507 printf("ERROR [multiple auth option]\n");
510 options->bsd_auth = 1;
512 else if(strcmp(tok, "index") == 0) {
513 if(options->createindex != 0) {
514 dbprintf(("%s: multiple index option\n",
515 debug_prefix(NULL)));
517 printf("ERROR [multiple index option]\n");
520 options->createindex = 1;
523 else if(strcmp(tok, "krb4-auth") == 0) {
524 if(options->bsd_auth + options->krb4_auth > 0) {
525 dbprintf(("%s: multiple auth option\n",
526 debug_prefix(NULL)));
528 printf("ERROR [multiple auth option]\n");
531 options->krb4_auth = 1;
533 else if(strcmp(tok, "kencrypt") == 0) {
534 if(options->kencrypt != 0) {
535 dbprintf(("%s: multiple kencrypt option\n",
536 debug_prefix(NULL)));
538 printf("ERROR [multiple kencrypt option]\n");
541 options->kencrypt = 1;
544 else if(strcmp(tok, "exclude-optional") == 0) {
545 if(options->exclude_optional != 0) {
546 dbprintf(("%s: multiple exclude-optional option\n",
547 debug_prefix(NULL)));
549 printf("ERROR [multiple exclude-optional option]\n");
552 options->exclude_optional = 1;
554 else if(strcmp(tok, "include-optional") == 0) {
555 if(options->include_optional != 0) {
556 dbprintf(("%s: multiple include-optional option\n",
557 debug_prefix(NULL)));
559 printf("ERROR [multiple include-optional option]\n");
562 options->include_optional = 1;
564 else if(strncmp(tok,"exclude-file=", 13) == 0) {
566 options->exclude_file = append_sl(options->exclude_file,exc);
568 else if(strncmp(tok,"exclude-list=", 13) == 0) {
570 options->exclude_list = append_sl(options->exclude_list, exc);
572 else if(strncmp(tok,"include-file=", 13) == 0) {
574 options->include_file = append_sl(options->include_file,exc);
576 else if(strncmp(tok,"include-list=", 13) == 0) {
578 options->include_list = append_sl(options->include_list, exc);
580 else if(strcmp(tok,"|") == 0) {
583 dbprintf(("%s: unknown option \"%s\"\n",
584 debug_prefix(NULL), tok));
586 printf("ERROR [unknown option \"%s\"]\n", tok);
589 tok = strtok(NULL, ";");
596 void init_g_options(g_options)
597 g_option_t *g_options;
599 g_options->features = NULL;
600 g_options->hostname = NULL;
601 g_options->maxdumps = 0;
605 g_option_t *parse_g_options(str, verbose)
609 g_option_t *g_options;
613 g_options = alloc(sizeof(g_option_t));
614 init_g_options(g_options);
615 g_options->str = stralloc(str);
620 while (tok != NULL) {
621 if(strncmp(tok,"features=", 9) == 0) {
622 if(g_options->features != NULL) {
623 dbprintf(("%s: multiple features option\n",
624 debug_prefix(NULL)));
626 printf("ERROR [multiple features option]\n");
629 if((g_options->features = am_string_to_feature(tok+9)) == NULL) {
630 dbprintf(("%s: bad features value \"%s\n",
631 debug_prefix(NULL), tok+10));
633 printf("ERROR [bad features value \"%s\"]\n", tok+10);
637 else if(strncmp(tok,"hostname=", 9) == 0) {
638 if(g_options->hostname != NULL) {
639 dbprintf(("%s: multiple hostname option\n",
640 debug_prefix(NULL)));
642 printf("ERROR [multiple hostname option]\n");
645 g_options->hostname = stralloc(tok+9);
647 else if(strncmp(tok,"maxdumps=", 9) == 0) {
648 if(g_options->maxdumps != 0) {
649 dbprintf(("%s: multiple maxdumps option\n",
650 debug_prefix(NULL)));
652 printf("ERROR [multiple maxdumps option]\n");
655 if(sscanf(tok+9, "%d;", &new_maxdumps) == 1) {
656 if (new_maxdumps > MAXMAXDUMPS) {
657 g_options->maxdumps = MAXMAXDUMPS;
659 else if (new_maxdumps > 0) {
660 g_options->maxdumps = new_maxdumps;
663 dbprintf(("%s: bad maxdumps value \"%s\"\n",
664 debug_prefix(NULL), tok+9));
666 printf("ERROR [bad maxdumps value \"%s\"]\n",
672 dbprintf(("%s: bad maxdumps value \"%s\"\n",
673 debug_prefix(NULL), tok+9));
675 printf("ERROR [bad maxdumps value \"%s\"]\n",
681 dbprintf(("%s: unknown option \"%s\"\n",
682 debug_prefix(NULL), tok));
684 printf("ERROR [unknown option \"%s\"]\n", tok);
687 tok = strtok(NULL, ";");
689 if(g_options->features == NULL) {
690 g_options->features = am_set_default_feature_set();
692 if(g_options->maxdumps == 0) /* default */
693 g_options->maxdumps = 1;