X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=restore-src%2Famfetchdump.c;h=927149da4e94b6f93adbfcbb88784147926a6f32;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=e94ce290f1c843b4965d8a296204552686b04fce;hpb=1194fb66aa28d9929c3f2bef3cc6c1c3f40a60a4;p=debian%2Famanda diff --git a/restore-src/amfetchdump.c b/restore-src/amfetchdump.c index e94ce29..927149d 100644 --- a/restore-src/amfetchdump.c +++ b/restore-src/amfetchdump.c @@ -24,13 +24,12 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: amfetchdump.c,v 1.7 2006/03/14 13:12:01 martinea Exp $ + * $Id: amfetchdump.c,v 1.16 2006/08/24 01:57:15 paddy_s Exp $ * * retrieves specific dumps from a set of amanda tapes */ #include "amanda.h" -#include "tapeio.h" #include "fileheader.h" #include "util.h" #include "restore.h" @@ -39,10 +38,11 @@ #include "find.h" #include "changer.h" #include "logfile.h" +#include "cmdline.h" +#include "server_util.h" #define CREAT_MODE 0640 -extern char *rst_conf_logdir; extern char *rst_conf_logfile; extern char *config_dir; int get_lock = 0; @@ -50,222 +50,253 @@ int get_lock = 0; typedef struct needed_tapes_s { char *label; int isafile; - find_result_t *files; - struct needed_tapes_s *next; - struct needed_tapes_s *prev; + GSList *files; } needed_tape_t; /* local functions */ -void errexit P((void)); -void handle_sigpipe P((int sig)); -tapelist_t *list_needed_tapes P((match_list_t *match_list)); -void usage P((void)); -int main P((int argc, char **argv)); +tapelist_t *list_needed_tapes(GSList *dumpspecs, int only_one, disklist_t *diskqp); +void usage(void); +int main(int argc, char **argv); /* exit routine */ -static int parent_pid = -1; -static void cleanup P((void)); - -void errexit() -/* - * Do exit(2) after an error, rather than exit(1). - */ -{ - exit(2); -} +static pid_t parent_pid = -1; +static void cleanup(void); -void usage() /* * Print usage message and terminate. */ + +void +usage(void) { - fprintf(stderr, "Usage: amfetchdump [options] config hostname [diskname [datestamp [level [hostname [diskname [datestamp [level ... ]]]]]]]\n\n"); - fprintf(stderr, "Goes and grabs a dump from tape, moving tapes around and assembling parts as\n"); - fprintf(stderr, "necessary. Files are restored to the current directory, unless otherwise\nspecified.\n\n"); - fprintf(stderr, " -p Pipe exactly *one* complete dumpfile to stdout, instead of to disk.\n"); - fprintf(stderr, " -o Restore files to this directory.\n"); - fprintf(stderr, " -d Force restoration from a particular tape device.\n"); - fprintf(stderr, " -c Compress output, fastest method available.\n"); - fprintf(stderr, " -C Compress output, best filesize method available.\n"); - fprintf(stderr, " -l Leave dumps (un)compressed, whichever way they were originally on tape.\n"); - fprintf(stderr, " -a Assume all tapes are available via changer, do not prompt for initial load.\n"); - fprintf(stderr, " -i Search through tapes and write out an inventory while we\n restore. Useful only if normal logs are unavailable.\n"); - fprintf(stderr, " -w Wait to put split dumps together until all chunks have been restored.\n"); - fprintf(stderr, " -n Do not reassemble split dumpfiles.\n"); - fprintf(stderr, " -k Skip the rewind/label read when reading a new tape.\n"); - fprintf(stderr, " -s Do not use fast forward to skip files we won't restore. Use only if fsf\n causes your tapes to skip too far.\n"); - fprintf(stderr, " -b Force a particular block size (default is 32kb).\n"); + g_fprintf(stderr, _("Usage: amfetchdump [options] config hostname [diskname [datestamp [level [hostname [diskname [datestamp [level ... ]]]]]]] [-o configoption]*\n\n")); + g_fprintf(stderr, _("Goes and grabs a dump from tape, moving tapes around and assembling parts as\n")); + g_fprintf(stderr, _("necessary. Files are restored to the current directory, unless otherwise\nspecified.\n\n")); + g_fprintf(stderr, _(" -p Pipe exactly *one* complete dumpfile to stdout, instead of to disk.\n")); + g_fprintf(stderr, _(" -O Restore files to this directory.\n")); + g_fprintf(stderr, _(" -d Force restoration from a particular tape device.\n")); + g_fprintf(stderr, _(" -c Compress output, fastest method available.\n")); + g_fprintf(stderr, _(" -C Compress output, best filesize method available.\n")); + g_fprintf(stderr, _(" -l Leave dumps (un)compressed, whichever way they were originally on tape.\n")); + g_fprintf(stderr, _(" -a Assume all tapes are available via changer, do not prompt for initial load.\n")); + g_fprintf(stderr, _(" -i Search through tapes and write out an inventory while we\n restore. Useful only if normal logs are unavailable.\n")); + g_fprintf(stderr, _(" -w Wait to put split dumps together until all chunks have been restored.\n")); + g_fprintf(stderr, _(" -n Do not reassemble split dumpfiles.\n")); + g_fprintf(stderr, _(" -k Skip the rewind/label read when reading a new tape.\n")); + g_fprintf(stderr, _(" -s Do not use fast forward to skip files we won't restore. Use only if fsf\n causes your tapes to skip too far.\n")); + g_fprintf(stderr, _(" -b Force a particular block size (default is 32kb).\n")); exit(1); } +static gint +sort_needed_tapes_by_write_timestamp( + gconstpointer a, + gconstpointer b) +{ + needed_tape_t *a_nt = (needed_tape_t *)a; + needed_tape_t *b_nt = (needed_tape_t *)b; + tape_t *a_t = a_nt->isafile? NULL : lookup_tapelabel(a_nt->label); + tape_t *b_t = b_nt->isafile? NULL : lookup_tapelabel(b_nt->label); + char *a_ds = a_t? a_t->datestamp : "none"; + char *b_ds = b_t? b_t->datestamp : "none"; + + return strcmp(a_ds, b_ds); +} + /* * Build the list of tapes we'll be wanting, and include data about the * files we want from said tapes while we're at it (the whole find_result * should do fine) */ -tapelist_t *list_needed_tapes(match_list) -match_list_t *match_list; +tapelist_t * +list_needed_tapes( + GSList * dumpspecs, + int only_one, + disklist_t *diskqp) { - needed_tape_t *needed_tapes = NULL, *curtape = NULL; - disklist_t diskqp; - match_list_t *me = NULL; + GSList *needed_tapes = NULL; + GSList *seen_dumps = NULL; + GSList *iter, *iter2; find_result_t *alldumps = NULL; + find_result_t *curmatch = NULL; + find_result_t *matches = NULL; tapelist_t *tapes = NULL; - int numtapes = 0; - char *conf_diskfile, *conf_tapelist; - - /* For disks and tape lists */ - conf_diskfile = getconf_str(CNF_DISKFILE); - conf_tapelist = getconf_str(CNF_TAPELIST); - if (*conf_diskfile == '/') { - conf_diskfile = stralloc(conf_diskfile); - } else { - conf_diskfile = stralloc2(config_dir, conf_diskfile); - } - if(read_diskfile(conf_diskfile, &diskqp) != 0) { - error("could not load disklist \"%s\"", conf_diskfile); - } - if (*conf_tapelist == '/') { - conf_tapelist = stralloc(conf_tapelist); - } else { - conf_tapelist = stralloc2(config_dir, conf_tapelist); - } + char *conf_tapelist; + + /* Load the tape list */ + conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { - error("could not load tapelist \"%s\"", conf_tapelist); + error(_("could not load tapelist \"%s\""), conf_tapelist); + /*NOTREACHED*/ } - amfree(conf_diskfile); amfree(conf_tapelist); /* Grab a find_output_t of all logged dumps */ - alldumps = find_dump(1, &diskqp); - free_disklist(&diskqp); + alldumps = find_dump(diskqp); if(alldumps == NULL){ - fprintf(stderr, "No dump records found\n"); + g_fprintf(stderr, _("No dump records found\n")); exit(1); } - + /* Compare all known dumps to our match list, note what we'll need */ - for(me = match_list; me; me = me->next) { - find_result_t *curmatch = NULL; - find_result_t *matches = NULL; - - matches = dumps_match(alldumps, me->hostname, me->diskname, - me->datestamp, me->level, 1); - sort_find_result("Dhklp", &matches); - for(curmatch = matches; curmatch; curmatch = curmatch->next){ - int havetape = 0; - if(strcmp("OK", curmatch->status)){ - fprintf(stderr,"Dump %d %s %s %d had status '%s', skipping\n", - curmatch->datestamp, curmatch->hostname, - curmatch->diskname, curmatch->level, - curmatch->status); - continue; - } - for(curtape = needed_tapes; curtape; curtape = curtape->next) { - if(!strcmp(curtape->label, curmatch->label)){ - find_result_t *rsttemp = NULL; - find_result_t *rstfile = alloc(sizeof(find_result_t)); - int keep = 1; - - memcpy(rstfile, curmatch, sizeof(find_result_t)); - - havetape = 1; - - for(rsttemp = curtape->files; - rsttemp; - rsttemp=rsttemp->next){ - if(rstfile->filenum == rsttemp->filenum){ - fprintf(stderr, "Seeing multiple entries for tape %s file %d, using most recent\n", curtape->label, rstfile->filenum); - keep = 0; - } - } - if(!keep){ - amfree(rstfile); - break; - } - rstfile->next = curtape->files; + matches = dumps_match_dumpspecs(alldumps, dumpspecs, 1); + sort_find_result("Dhklpw", &matches); + for(curmatch = matches; curmatch; curmatch = curmatch->next) { + int havetape = 0; + + g_fprintf(stderr, "Examining %s %s on %s\n", curmatch->hostname, curmatch->diskname, curmatch->label); + /* keep only first dump if only_one */ + if (only_one && + curmatch != matches && + (strcmp(curmatch->hostname, matches->hostname) || + strcmp(curmatch->diskname, matches->diskname) || + strcmp(curmatch->timestamp, matches->timestamp) || + curmatch->level != matches->level)) { + g_fprintf(stderr, "only_one matched\n"); + continue; + } + if(strcmp("OK", curmatch->status)){ + g_fprintf(stderr,_("Dump %s %s %s %d had status '%s', skipping\n"), + curmatch->timestamp, curmatch->hostname, + curmatch->diskname, curmatch->level, + curmatch->status); + g_fprintf(stderr, "!OK\n"); + continue; + } - if(curmatch->filenum < 1) curtape->isafile = 1; - else curtape->isafile = 0; - curtape->files = rstfile; + for(iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; + if (!strcmp(curtape->label, curmatch->label)) { + int keep = 1; + + havetape = 1; + + for(iter2 = curtape->files; iter2; iter2 = iter2->next){ + find_result_t *rsttemp = iter2->data; + if(curmatch->filenum == rsttemp->filenum){ + g_fprintf(stderr, _("Seeing multiple entries for tape " + "%s file %lld, using most recent\n"), + curtape->label, + (long long)curmatch->filenum); + keep = 0; + } + } + if(!keep){ break; } + + curtape->isafile = (curmatch->filenum < 1); + curtape->files = g_slist_prepend(curtape->files, curmatch); + break; } - if(!havetape){ - find_result_t *rstfile = alloc(sizeof(find_result_t)); - needed_tape_t *newtape = - alloc(sizeof(needed_tape_t)); - memcpy(rstfile, curmatch, sizeof(find_result_t)); - rstfile->next = NULL; - newtape->files = rstfile; - if(curmatch->filenum < 1) newtape->isafile = 1; - else newtape->isafile = 0; - newtape->label = curmatch->label; - if(needed_tapes){ - needed_tapes->prev->next = newtape; - newtape->prev = needed_tapes->prev; - needed_tapes->prev = newtape; - } - else{ - needed_tapes = newtape; - needed_tapes->prev = needed_tapes; - } - newtape->next = NULL; - numtapes++; -#if 0 -// free_find_result(rstfile); -#endif - } /* if(!havetape) */ - - } /* for(curmatch = matches ... */ - } /* for(me = match_list ... */ - - if(numtapes == 0){ - fprintf(stderr, "No matching dumps found\n"); + } + if (!havetape) { + needed_tape_t *newtape = g_new0(needed_tape_t, 1); + newtape->files = g_slist_prepend(newtape->files, curmatch); + newtape->isafile = (curmatch->filenum < 1); + newtape->label = curmatch->label; + needed_tapes = g_slist_prepend(needed_tapes, newtape); + } /* if(!havetape) */ + + } /* for(curmatch = matches ... */ + + if(g_slist_length(needed_tapes) == 0){ + g_fprintf(stderr, _("No matching dumps found\n")); exit(1); + /* NOTREACHED */ } - /* stick that list in a structure that librestore will understand */ - for(curtape = needed_tapes; curtape; curtape = curtape->next) { - find_result_t *curfind = NULL; - for(curfind = curtape->files; curfind; curfind = curfind->next) { - tapes = append_to_tapelist(tapes, curtape->label, - curfind->filenum, curtape->isafile); + /* sort the tapelist by tape write_timestamp */ + needed_tapes = g_slist_sort(needed_tapes, sort_needed_tapes_by_write_timestamp); + + /* stick that list in a structure that librestore will understand, removing + * files we have already seen in the process; this prefers the earliest written + * copy of any dumps which are available on multiple tapes */ + seen_dumps = NULL; + for(iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; + for(iter2 = curtape->files; iter2; iter2 = iter2->next) { + find_result_t *curfind = iter2->data; + find_result_t *prev; + GSList *iter; + int have_part; + + /* have we already seen this? */ + have_part = 0; + for (iter = seen_dumps; iter; iter = iter->next) { + prev = iter->data; + + if (!strcmp(prev->partnum, curfind->partnum) && + !strcmp(prev->hostname, curfind->hostname) && + !strcmp(prev->diskname, curfind->diskname) && + !strcmp(prev->timestamp, curfind->timestamp) && + prev->level == curfind->level) { + have_part = 1; + break; + } + } + + if (!have_part) { + seen_dumps = g_slist_prepend(seen_dumps, curfind); + tapes = append_to_tapelist(tapes, curtape->label, + curfind->filenum, -1, curtape->isafile); + } } } - fprintf(stderr, "%d tape(s) needed for restoration\n", numtapes); + /* free our resources */ + for (iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; + g_slist_free(curtape->files); + g_free(curtape); + } + g_slist_free(seen_dumps); + g_slist_free(needed_tapes); + free_find_result(&matches); + + /* and we're done */ + g_fprintf(stderr, _("%d tape(s) needed for restoration\n"), num_entries(tapes)); return(tapes); } -int main(argc, argv) -int argc; -char **argv; + /* * Parses command line, then loops through all files on tape, restoring * files that match the command line criteria. */ + +int +main( + int argc, + char ** argv) { extern int optind; int opt; - char *errstr; - match_list_t *match_list = NULL; - match_list_t *me = NULL; + GSList *dumpspecs = NULL; int fd; - char *config_name = NULL; - char *conffile = NULL; tapelist_t *needed_tapes = NULL; char *e; - int arg_state; rst_flags_t *rst_flags; - struct passwd *pwent; + int minimum_arguments; + config_overwrites_t *cfg_ovr = NULL; + disklist_t diskq; + char * conf_diskfile = NULL; - for(fd = 3; fd < FD_SETSIZE; fd++) { + /* + * Configure program for internationalization: + * 1) Only set the message locale for now. + * 2) Set textdomain for all amanda related programs to "amanda" + * We don't want to be forced to support dozens of message catalogs. + */ + setlocale(LC_MESSAGES, "C"); + textdomain("amanda"); + + for(fd = 3; fd < (int)FD_SETSIZE; fd++) { /* * Make sure nobody spoofs us with a lot of extra open files - * that would cause an open we do to get a very high file + * that would cause a successful open to get a very high file * descriptor, which in turn might be used as an index into * an array (e.g. an fd_set). */ @@ -274,72 +305,55 @@ char **argv; set_pname("amfetchdump"); -#ifdef FORCE_USERID - - /* we'd rather not run as root */ - - if(client_uid == (uid_t) -1 && (pwent = getpwnam(CLIENT_LOGIN)) != NULL) { - client_uid = pwent->pw_uid; - client_gid = pwent->pw_gid; - endpwent(); - } - if(geteuid() == 0) { - if(client_uid == (uid_t) -1) { - error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN); - } - - initgroups(CLIENT_LOGIN, client_gid); - setgid(client_gid); - setuid(client_uid); - } - -#endif /* FORCE_USERID */ - /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); - erroutput_type = ERR_INTERACTIVE; - - onerror(errexit); + dbopen(DBG_SUBDIR_SERVER); - if(argc <= 1) usage(); + erroutput_type = ERR_INTERACTIVE; + error_exit_status = 2; rst_flags = new_rst_flags(); rst_flags->wait_tape_prompt = 1; - + /* handle options */ - while( (opt = getopt(argc, argv, "alht:scCpb:nwi:d:o:")) != -1) { + cfg_ovr = new_config_overwrites(argc/2); + while( (opt = getopt(argc, argv, "alht:scCpb:nwi:d:O:o:")) != -1) { switch(opt) { - case 'b': rst_flags->compress = 1; break; - rst_flags->blocksize = strtol(optarg, &e, 10); + case 'b': + rst_flags->blocksize = (ssize_t)strtol(optarg, &e, 10); if(*e == 'k' || *e == 'K') { rst_flags->blocksize *= 1024; } else if(*e == 'm' || *e == 'M') { rst_flags->blocksize *= 1024 * 1024; } else if(*e != '\0') { - error("invalid blocksize value \"%s\"", optarg); + error(_("invalid blocksize value \"%s\""), optarg); + /*NOTREACHED*/ } if(rst_flags->blocksize < DISK_BLOCK_BYTES) { - error("minimum block size is %dk", DISK_BLOCK_BYTES / 1024); + error(_("minimum block size is %dk"), DISK_BLOCK_BYTES / 1024); + /*NOTREACHED*/ } break; case 'c': rst_flags->compress = 1; break; - case 'o': rst_flags->restore_dir = stralloc(optarg) ; break; + case 'O': rst_flags->restore_dir = stralloc(optarg) ; break; case 'd': rst_flags->alt_tapedev = stralloc(optarg) ; break; case 'C': rst_flags->compress = 1; rst_flags->comp_type = COMPRESS_BEST_OPT; break; - case 'p': rst_flags->pipe_to_fd = fileno(stdout); break; - case 's': rst_flags->fsf = 0; break; + case 'p': rst_flags->pipe_to_fd = STDOUT_FILENO; break; + case 's': rst_flags->fsf = (off_t)0; break; case 'l': rst_flags->leave_comp = 1; break; case 'i': rst_flags->inventory_log = stralloc(optarg); break; case 'n': rst_flags->inline_assemble = 0; break; case 'w': rst_flags->delay_assemble = 1; break; case 'a': rst_flags->wait_tape_prompt = 0; break; case 'h': rst_flags->headers = 1; break; + case 'o': add_config_overwrite_opt(cfg_ovr, optarg); break; default: usage(); + /*NOTREACHED*/ } } @@ -349,127 +363,93 @@ char **argv; rst_flags->inline_assemble = 0; rst_flags->leave_comp = 1; if(rst_flags->compress){ - error("Cannot force compression when doing inventory/search"); + error(_("Cannot force compression when doing inventory/search")); + /*NOTREACHED*/ } - fprintf(stderr, "Doing inventory/search, dumps will not be uncompressed or assembled on-the-fly.\n"); + g_fprintf(stderr, _("Doing inventory/search, dumps will not be uncompressed or assembled on-the-fly.\n")); } else{ if(rst_flags->delay_assemble){ - fprintf(stderr, "Using -w, split dumpfiles will *not* be automatically uncompressed.\n"); + g_fprintf(stderr, _("Using -w, split dumpfiles will *not* be automatically uncompressed.\n")); } } /* make sure our options all make sense otherwise */ - if(check_rst_flags(rst_flags) == -1) usage(); - - config_name = argv[optind++]; - config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); - conffile = stralloc2(config_dir, CONFFILE_NAME); - if (read_conffile(conffile)) { - error("errors processing config file \"%s\"", conffile); + if(check_rst_flags(rst_flags) == -1) { + usage(); + /*NOTREACHED*/ } - amfree(conffile); - - if((argc - optind) < 1 && !rst_flags->inventory_log){ - fprintf(stderr, "Not enough arguments\n\n"); + if (rst_flags->inventory_log) { + minimum_arguments = 1; + } else { + minimum_arguments = 2; + } + + if(argc - optind < minimum_arguments) { usage(); + /*NOTREACHED*/ } -#define ARG_GET_HOST 0 -#define ARG_GET_DISK 1 -#define ARG_GET_DATE 2 -#define ARG_GET_LEVL 3 - - arg_state = ARG_GET_HOST; - while(optind < argc) { - switch(arg_state) { - case ARG_GET_HOST: - /* - * New host/disk/date/level set, so allocate a match_list. - */ - me = alloc(sizeof(*me)); - me->hostname = argv[optind++]; - me->diskname = ""; - me->datestamp = ""; - me->level = ""; - me->next = match_list; - match_list = me; - if(me->hostname[0] != '\0' - && (errstr=validate_regexp(me->hostname)) != NULL) { - fprintf(stderr, "%s: bad hostname regex \"%s\": %s\n", - get_pname(), me->hostname, errstr); - usage(); - } - arg_state = ARG_GET_DISK; - break; - case ARG_GET_DISK: - me->diskname = argv[optind++]; - if(me->diskname[0] != '\0' - && (errstr=validate_regexp(me->diskname)) != NULL) { - fprintf(stderr, "%s: bad diskname regex \"%s\": %s\n", - get_pname(), me->diskname, errstr); - usage(); - } - arg_state = ARG_GET_DATE; - break; - case ARG_GET_DATE: - me->datestamp = argv[optind++]; - if(me->datestamp[0] != '\0' - && (errstr=validate_regexp(me->datestamp)) != NULL) { - fprintf(stderr, "%s: bad datestamp regex \"%s\": %s\n", - get_pname(), me->datestamp, errstr); - usage(); - } - arg_state = ARG_GET_LEVL; - break; - case ARG_GET_LEVL: - me->level = argv[optind++]; - if(me->level[0] != '\0' - && (errstr=validate_regexp(me->level)) != NULL) { - fprintf(stderr, "%s: bad level regex \"%s\": %s\n", - get_pname(), me->level, errstr); - usage(); - } - } - } + config_init(CONFIG_INIT_EXPLICIT_NAME, argv[optind++]); + apply_config_overwrites(cfg_ovr); + + conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); + read_diskfile(conf_diskfile, &diskq); + amfree(conf_diskfile); - /* XXX I don't think this can happen */ - if(match_list == NULL && !rst_flags->inventory_log) { - match_list = alloc(sizeof(*match_list)); - match_list->hostname = ""; - match_list->diskname = ""; - match_list->datestamp = ""; - match_list->level = ""; - match_list->next = NULL; + if (config_errors(NULL) >= CFGERR_WARNINGS) { + config_print_errors(); + if (config_errors(NULL) >= CFGERR_ERRORS) { + g_critical(_("errors processing config file")); + } } + check_running_as(RUNNING_AS_DUMPUSER); + + dbrename(get_config_name(), DBG_SUBDIR_SERVER); + + dumpspecs = cmdline_parse_dumpspecs(argc - optind, argv + optind, + CMDLINE_PARSE_DATESTAMP | + CMDLINE_PARSE_LEVEL | + CMDLINE_EMPTY_TO_WILDCARD); + /* * We've been told explicitly to go and search through the tapes the hard * way. */ if(rst_flags->inventory_log){ - fprintf(stderr, "Beginning tape-by-tape search.\n"); - search_tapes(stderr, 1, NULL, match_list, rst_flags, NULL); + g_fprintf(stderr, _("Beginning tape-by-tape search.\n")); + search_tapes(stderr, stdin, rst_flags->alt_tapedev == NULL, + NULL, dumpspecs, rst_flags, NULL); exit(0); } /* Decide what tapes we'll need */ - needed_tapes = list_needed_tapes(match_list); - + needed_tapes = list_needed_tapes(dumpspecs, + rst_flags->pipe_to_fd == STDOUT_FILENO, + &diskq); + parent_pid = getpid(); atexit(cleanup); get_lock = lock_logfile(); /* config is loaded, should be ok here */ - search_tapes(NULL, 1, needed_tapes, match_list, rst_flags, NULL); + if(get_lock == 0) { + char *process_name = get_master_process(rst_conf_logfile); + error(_("%s exists: %s is already running, or you must run amcleanup"), rst_conf_logfile, process_name); + } + log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); + search_tapes(NULL, stdin, rst_flags->alt_tapedev == NULL, + needed_tapes, dumpspecs, rst_flags, NULL); cleanup(); - free_match_list(match_list); + dumpspec_list_free(dumpspecs); if(rst_flags->inline_assemble || rst_flags->delay_assemble) flush_open_outputs(1, NULL); else flush_open_outputs(0, NULL); + free_disklist(&diskq); free_rst_flags(rst_flags); return(0); @@ -478,8 +458,10 @@ char **argv; static void cleanup(void) { - if(parent_pid == getpid()) { - if(get_lock) unlink(rst_conf_logfile); + if (parent_pid == getpid()) { + if (get_lock) { + log_add(L_INFO, "pid-done %ld\n", (long)getpid()); + unlink(rst_conf_logfile); + } } } -