* file named AUTHORS, in the root directory of this distribution.
*/
/*
- * $Id: amfetchdump.c,v 1.16.2.1 2006/09/27 12:04:09 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"
#include "find.h"
#include "changer.h"
#include "logfile.h"
+#include "cmdline.h"
+#include "server_util.h"
#define CREAT_MODE 0640
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(void);
-tapelist_t *list_needed_tapes(match_list_t *match_list);
+tapelist_t *list_needed_tapes(GSList *dumpspecs, int only_one, disklist_t *diskqp);
void usage(void);
int main(int argc, char **argv);
static void cleanup(void);
-/*
- * Do exit(2) after an error, rather than exit(1).
- */
-
-void
-errexit(void)
-{
- exit(2);
-}
-
-
/*
* Print usage message and terminate.
*/
void
usage(void)
{
- fprintf(stderr, "Usage: amfetchdump [options] config hostname [diskname [datestamp [level [hostname [diskname [datestamp [level ... ]]]]]]] [-o configoption]*\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 <output dir> Restore files to this directory.\n");
- fprintf(stderr, " -d <device> 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 <dst_file> 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 <blocksize> 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 <output dir> Restore files to this directory.\n"));
+ g_fprintf(stderr, _(" -d <device> 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 <dst_file> 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 <blocksize> 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
*/
tapelist_t *
list_needed_tapes(
- match_list_t * match_list)
+ 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);
- /*NOTREACHED*/
- }
- 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 %s %s %s %d had status '%s', skipping\n",
- curmatch->timestamp, 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 " OFF_T_FMT ", using most recent\n",
+ 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;
+ }
+
+ 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,
- (OFF_T_FMT_TYPE)rstfile->filenum);
- keep = 0;
- }
- }
- if(!keep){
- amfree(rstfile);
- break;
+ (long long)curmatch->filenum);
+ keep = 0;
}
- rstfile->next = curtape->files;
-
- if(curmatch->filenum < 1) curtape->isafile = 1;
- else curtape->isafile = 0;
- curtape->files = rstfile;
+ }
+ 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);
}
{
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 new_argc, my_argc;
- char **new_argv, **my_argv;
+ int minimum_arguments;
+ config_overwrites_t *cfg_ovr = NULL;
+ disklist_t diskq;
+ char * conf_diskfile = NULL;
+
+ /*
+ * 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).
*/
set_pname("amfetchdump");
- dbopen(DBG_SUBDIR_SERVER);
-
-#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);
- /*NOTREACHED*/
- }
-
- /*@ignore@*/
- initgroups(CLIENT_LOGIN, client_gid);
- /*@end@*/
- 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);
-
- parse_server_conf(argc, argv, &new_argc, &new_argv);
- my_argc = new_argc;
- my_argv = new_argv;
+ dbopen(DBG_SUBDIR_SERVER);
- if(my_argc <= 1) {
- usage();
- /*NOTREACHED*/
- }
+ erroutput_type = ERR_INTERACTIVE;
+ error_exit_status = 2;
rst_flags = new_rst_flags();
rst_flags->wait_tape_prompt = 1;
/* handle options */
- while( (opt = getopt(my_argc, my_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->blocksize = (ssize_t)strtol(optarg, &e, 10);
} 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;
rst_flags->compress = 1;
rst_flags->comp_type = COMPRESS_BEST_OPT;
break;
- case 'p': rst_flags->pipe_to_fd = fileno(stdout); 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 '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*/
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"));
}
}
/*NOTREACHED*/
}
- config_name = my_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);
- /*NOTREACHED*/
+ if (rst_flags->inventory_log) {
+ minimum_arguments = 1;
+ } else {
+ minimum_arguments = 2;
}
- amfree(conffile);
-
- dbrename(config_name, DBG_SUBDIR_SERVER);
-
- if((my_argc - optind) < 1 && !rst_flags->inventory_log){
- fprintf(stderr, "Not enough arguments\n\n");
+
+ 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 < my_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 = my_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();
- /*NOTREACHED*/
- }
- arg_state = ARG_GET_DISK;
- break;
- case ARG_GET_DISK:
- me->diskname = my_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();
- /*NOTREACHED*/
- }
- arg_state = ARG_GET_DATE;
- break;
- case ARG_GET_DATE:
- me->datestamp = my_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();
- /*NOTREACHED*/
- }
- arg_state = ARG_GET_LEVL;
- break;
- case ARG_GET_LEVL:
- me->level = my_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();
- /*NOTREACHED*/
- }
- }
- }
+ config_init(CONFIG_INIT_EXPLICIT_NAME, argv[optind++]);
+ apply_config_overwrites(cfg_ovr);
- /* 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;
+ conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
+ read_diskfile(conf_diskfile, &diskq);
+ amfree(conf_diskfile);
+
+ 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, stdin, 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 */
if(get_lock == 0) {
- error("%s exists: amdump or amflush is already running, or you must run amcleanup", rst_conf_logfile);
+ 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);
}
- search_tapes(NULL, stdin, 1, needed_tapes, match_list, rst_flags, NULL);
+ 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);
- free_new_argv(new_argc, new_argv);
return(0);
}
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);
+ }
}
}