void log_rename( char * datestamp) { char *conf_logdir; char *logfile; char *fname = NULL; char seq_str[NUM_STR_SIZE]; unsigned int seq; struct stat statbuf; if(datestamp == NULL) datestamp = "error"; conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); logfile = g_strjoin(NULL, conf_logdir, "/log", NULL); for(seq = 0; 1; seq++) { /* if you've got MAXINT files in your dir... */ g_snprintf(seq_str, sizeof(seq_str), "%u", seq); g_free(fname); fname = g_strconcat(logfile, ".", datestamp, ".", seq_str, NULL); if(stat(fname, &statbuf) == -1 && errno == ENOENT) break; } if(rename(logfile, fname) == -1) { error(_("could not rename \"%s\" to \"%s\": %s"), logfile, fname, strerror(errno)); /*NOTREACHED*/ } amfree(fname); amfree(logfile); amfree(conf_logdir); }
char * getindexfname( char * host, char * disk, char * date, int level) { char *conf_indexdir; char *buf; char level_str[NUM_STR_SIZE]; char datebuf[14 + 1]; char *dc = NULL; char *pc; int ch; if (date != NULL) { dc = date; pc = datebuf; while (pc < datebuf + sizeof(datebuf)) { ch = *dc++; *pc++ = (char)ch; if (ch == '\0') { break; } else if (! isdigit (ch)) { pc--; } } datebuf[sizeof(datebuf)-1] = '\0'; dc = datebuf; g_snprintf(level_str, sizeof(level_str), "%d", level); } host = sanitise_filename(host); if (disk != NULL) { disk = sanitise_filename(disk); } conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR)); /* * Note: g_strjoin(NULL, ) will stop at the first NULL, which might be * "disk" or "dc" (datebuf) rather than the full file name. */ buf = g_strjoin(NULL, conf_indexdir, "/", host, "/", disk, "/", dc, "_", level_str, COMPRESS_SUFFIX, NULL); amfree(conf_indexdir); amfree(host); amfree(disk); return buf; }
static void update_tapelist( taper_state_t *state) { char *tapelist_name = NULL; char *tapelist_name_old = NULL; tape_t *tp; char *comment = NULL; tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST)); if (state->cur_tape == 0) { tapelist_name_old = stralloc2(tapelist_name, ".yesterday"); } else { char cur_str[NUM_STR_SIZE]; g_snprintf(cur_str, SIZEOF(cur_str), "%d", state->cur_tape - 1); tapelist_name_old = vstralloc(tapelist_name, ".today.", cur_str, NULL); } if (read_tapelist(tapelist_name) != 0) { log_add(L_INFO, "pid-done %ld", (long)getpid()); error("could not load tapelist \"%s\"", tapelist_name); /*NOTREACHED*/ } /* make a copy of the tapelist file */ if (write_tapelist(tapelist_name_old)) { log_add(L_INFO, "pid-done %ld", (long)getpid()); error("could not write tapelist: %s", strerror(errno)); /*NOTREACHED*/ } amfree(tapelist_name_old); /* get a copy of the comment, before freeing the old record */ tp = lookup_tapelabel(state->device->volume_label); if (tp && tp->comment) comment = stralloc(tp->comment); /* edit the tapelist and rewrite it */ remove_tapelabel(state->device->volume_label); add_tapelabel(state->driver_start_time, state->device->volume_label, comment); if (write_tapelist(tapelist_name)) { error("could not write tapelist: %s", strerror(errno)); /*NOTREACHED*/ } amfree(tapelist_name); amfree(comment); }
static void open_log(void) { char *conf_logdir; conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); logfile = g_strjoin(NULL, conf_logdir, "/log", NULL); amfree(conf_logdir); logfd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600); if(logfd == -1) { error(_("could not open log file %s: %s"), logfile, strerror(errno)); /*NOTREACHED*/ } if(amflock(logfd, "log") == -1) { error(_("could not lock log file %s: %s"), logfile, strerror(errno)); /*NOTREACHED*/ } }
void update_info_dumper( disk_t *dp, off_t origsize, off_t dumpsize, time_t dumptime) { int level, i; info_t info; stats_t *infp; perf_t *perfp; char *conf_infofile; level = sched(dp)->level; conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE)); if (open_infofile(conf_infofile)) { error(_("could not open info db \"%s\""), conf_infofile); /*NOTREACHED*/ } amfree(conf_infofile); get_info(dp->host->hostname, dp->name, &info); /* Clean up information about this and higher-level dumps. This assumes that update_info_dumper() is always run before update_info_taper(). */ for (i = level; i < DUMP_LEVELS; ++i) { infp = &info.inf[i]; infp->size = (off_t)-1; infp->csize = (off_t)-1; infp->secs = (time_t)-1; infp->date = (time_t)-1; infp->label[0] = '\0'; infp->filenum = 0; } /* now store information about this dump */ infp = &info.inf[level]; infp->size = origsize; infp->csize = dumpsize; infp->secs = dumptime; if (sched(dp)->timestamp == 0) { infp->date = 0; } else { infp->date = get_time_from_timestamp(sched(dp)->datestamp); } if(level == 0) perfp = &info.full; else perfp = &info.incr; /* Update the stats, but only if the new values are meaningful */ if(dp->compress != COMP_NONE && origsize > (off_t)0) { newperf(perfp->comp, (double)dumpsize/(double)origsize); } if(dumptime > (time_t)0) { if((off_t)dumptime >= dumpsize) newperf(perfp->rate, 1); else newperf(perfp->rate, (double)dumpsize/(double)dumptime); } if(origsize >= (off_t)0 && getconf_int(CNF_RESERVE)<100) { info.command = NO_COMMAND; } if (origsize >= (off_t)0 && level == info.last_level) { info.consecutive_runs++; } else if (origsize >= (off_t)0) { info.last_level = level; info.consecutive_runs = 1; } if(origsize >= (off_t)0 && dumpsize >= (off_t)0) { for(i=NB_HISTORY-1;i>0;i--) { info.history[i] = info.history[i-1]; } info.history[0].level = level; info.history[0].size = origsize; info.history[0].csize = dumpsize; if (sched(dp)->timestamp == 0) { info.history[0].date = 0; } else { info.history[0].date = get_time_from_timestamp(sched(dp)->datestamp); } info.history[0].secs = dumptime; } if (put_info(dp->host->hostname, dp->name, &info)) { int save_errno = errno; g_fprintf(stderr, _("infofile update failed (%s,'%s'): %s\n"), dp->host->hostname, dp->name, strerror(save_errno)); log_add(L_ERROR, _("infofile update failed (%s,'%s'): %s\n"), dp->host->hostname, dp->name, strerror(save_errno)); error(_("infofile update failed (%s,'%s'): %s\n"), dp->host->hostname, dp->name, strerror(save_errno)); /*NOTREACHED*/ } close_infofile(); }
int main( int argc, char ** argv) { char *logfname; char *conf_logdir; FILE *logfile; config_overrides_t *cfg_ovr = NULL; char *cfg_opt = 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"); safe_fd(-1, 0); set_pname("amlogroll"); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); /* Process options */ cfg_ovr = extract_commandline_config_overrides(&argc, &argv); if (argc >= 2) { cfg_opt = argv[1]; } /* read configuration files */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } safe_cd(); /* must happen after config_init */ check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); logfname = vstralloc(conf_logdir, "/", "log", NULL); amfree(conf_logdir); if((logfile = fopen(logfname, "r")) == NULL) { error(_("could not open log %s: %s"), logfname, strerror(errno)); /*NOTREACHED*/ } amfree(logfname); add_amanda_log_handler(amanda_log_trace_log); while(get_logline(logfile)) { if(curlog == L_START) { handle_start(); if(datestamp != NULL) { break; } } } afclose(logfile); log_rename(datestamp); amfree(datestamp); dbclose(); return 0; }
int main( int argc, char ** argv) { GList *dlist; GList *dlist1; disk_t *diskp; disklist_t diskl; size_t i; char *conf_diskfile; char *conf_tapelist; char *conf_indexdir; find_result_t *output_find; time_t tmp_time; int amtrmidx_debug = 0; config_overrides_t *cfg_ovr = NULL; gboolean compress_index; gboolean sort_index; char *lock_file; file_lock *lock_index; if (argc > 1 && argv[1] && g_str_equal(argv[1], "--version")) { printf("amtrmidx-%s\n", VERSION); return (0); } /* * 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"); safe_fd(-1, 0); safe_cd(); set_pname("amtrmidx"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); dbprintf(_("%s: version %s\n"), argv[0], VERSION); cfg_ovr = extract_commandline_config_overrides(&argc, &argv); if (argc > 1 && g_str_equal(argv[1], "-t")) { amtrmidx_debug = 1; argc--; argv++; } if (argc < 2) { g_fprintf(stderr, _("Usage: %s [-t] <config> [-o configoption]*\n"), argv[0]); return 1; } set_config_overrides(cfg_ovr); config_init_with_global(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, argv[1]); conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); read_diskfile(conf_diskfile, &diskl); 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); conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } amfree(conf_tapelist); compress_index = getconf_boolean(CNF_COMPRESS_INDEX); sort_index = getconf_boolean(CNF_SORT_INDEX); output_find = find_dump(&diskl); conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR)); /* take a lock file to prevent concurent trim */ lock_file = g_strdup_printf("%s/%s", conf_indexdir, "lock"); lock_index = file_lock_new(lock_file); if (file_lock_lock_wr(lock_index) != 0) goto lock_failed; /* now go through the list of disks and find which have indexes */ time(&tmp_time); tmp_time -= 7*24*60*60; /* back one week */ for (dlist = diskl.head; dlist != NULL; dlist = dlist->next) { diskp = dlist->data; if (diskp->index) { char *indexdir, *qindexdir; DIR *d; struct dirent *f; char **names; size_t name_length; size_t name_count; char *host; char *disk, *qdisk; size_t len_date; disk_t *dp; GSList *matching_dp = NULL; /* get listing of indices, newest first */ host = sanitise_filename(diskp->host->hostname); disk = sanitise_filename(diskp->name); qdisk = quote_string(diskp->name); indexdir = g_strjoin(NULL, conf_indexdir, "/", host, "/", disk, "/", NULL); qindexdir = quote_string(indexdir); /* find all dles that use the same indexdir */ for (dlist1 = diskl.head; dlist1 != NULL; dlist1 = dlist1->next) { char *dp_host, *dp_disk; dp = dlist1->data; dp_host = sanitise_filename(dp->host->hostname); dp_disk = sanitise_filename(dp->name); if (g_str_equal(host, dp_host) && g_str_equal(disk, dp_disk)) { matching_dp = g_slist_append(matching_dp, dp); } amfree(dp_host); amfree(dp_disk); } dbprintf("%s %s -> %s\n", diskp->host->hostname, qdisk, qindexdir); amfree(qdisk); if ((d = opendir(indexdir)) == NULL) { dbprintf(_("could not open index directory %s\n"), qindexdir); amfree(host); amfree(disk); amfree(indexdir); amfree(qindexdir); g_slist_free(matching_dp); continue; } name_length = 100; names = (char **)g_malloc(name_length * sizeof(char *)); name_count = 0; while ((f = readdir(d)) != NULL) { size_t l; if(is_dot_or_dotdot(f->d_name)) { continue; } for(i = 0; i < sizeof("YYYYMMDDHHMMSS")-1; i++) { if(! isdigit((int)(f->d_name[i]))) { break; } } len_date = i; /* len_date=8 for YYYYMMDD */ /* len_date=14 for YYYYMMDDHHMMSS */ if((len_date != 8 && len_date != 14) || f->d_name[len_date] != '_' || ! isdigit((int)(f->d_name[len_date+1]))) { continue; /* not an index file */ } /* * Clear out old index temp files. */ l = strlen(f->d_name) - (sizeof(".tmp")-1); if ((l > (len_date + 1)) && (g_str_equal(f->d_name + l, ".tmp"))) { struct stat sbuf; char *path, *qpath; path = g_strconcat(indexdir, f->d_name, NULL); qpath = quote_string(path); if(lstat(path, &sbuf) != -1 && ((sbuf.st_mode & S_IFMT) == S_IFREG) && ((time_t)sbuf.st_mtime < tmp_time)) { dbprintf("rm %s\n", qpath); if(amtrmidx_debug == 0 && unlink(path) == -1) { dbprintf(_("Error removing %s: %s\n"), qpath, strerror(errno)); } } amfree(qpath); amfree(path); continue; } if(name_count >= name_length) { char **new_names; new_names = g_malloc((name_length * 2) * sizeof(char *)); memcpy(new_names, names, name_length * sizeof(char *)); amfree(names); names = new_names; name_length *= 2; } names[name_count++] = g_strdup(f->d_name); } closedir(d); qsort(names, name_count, sizeof(char *), sort_by_name_reversed); /* * Search for the first full dump past the minimum number * of index files to keep. */ for(i = 0; i < name_count; i++) { char *datestamp; int level; size_t len_date; int matching = 0; GSList *mdp; for(len_date = 0; len_date < sizeof("YYYYMMDDHHMMSS")-1; len_date++) { if(! isdigit((int)(names[i][len_date]))) { break; } } datestamp = g_strdup(names[i]); datestamp[len_date] = '\0'; if (sscanf(&names[i][len_date+1], "%d", &level) != 1) level = 0; for (mdp = matching_dp; mdp != NULL; mdp = mdp->next) { dp = mdp->data; if (dump_exist(output_find, dp->host->hostname, dp->name, datestamp, level)) { matching = 1; } } if (!matching) { struct stat sbuf; char *path, *qpath; path = g_strconcat(indexdir, names[i], NULL); qpath = quote_string(path); if(lstat(path, &sbuf) != -1 && ((sbuf.st_mode & S_IFMT) == S_IFREG) && ((time_t)sbuf.st_mtime < tmp_time)) { dbprintf("rm %s\n", qpath); if(amtrmidx_debug == 0 && unlink(path) == -1) { dbprintf(_("Error removing %s: %s\n"), qpath, strerror(errno)); } } amfree(qpath); amfree(path); } /* Did it require un/compression and/or sorting */ { char *orig_name = getindexfname(host, disk, datestamp, level); char *sorted_name = getindex_sorted_fname(host, disk, datestamp, level); char *sorted_gz_name = getindex_sorted_gz_fname(host, disk, datestamp, level); char *unsorted_name = getindex_unsorted_fname(host, disk, datestamp, level); char *unsorted_gz_name = getindex_unsorted_gz_fname(host, disk, datestamp, level); gboolean orig_exist = FALSE; gboolean sorted_exist = FALSE; gboolean sorted_gz_exist = FALSE; gboolean unsorted_exist = FALSE; gboolean unsorted_gz_exist = FALSE; int fd; int uncompress_err_fd = -1; int sort_err_fd = -1; int compress_err_fd = -1; pid_t uncompress_pid = -1; pid_t sort_pid = -1; pid_t compress_pid = -1; orig_exist = file_exists(orig_name); sorted_exist = file_exists(sorted_name); sorted_gz_exist = file_exists(sorted_gz_name); unsorted_exist = file_exists(unsorted_name); unsorted_gz_exist = file_exists(unsorted_gz_name); if (sort_index && compress_index) { if (!sorted_gz_exist) { if (sorted_exist) { // COMPRESS compress_pid = run_compress(-1, NULL, &compress_err_fd, sorted_name, sorted_gz_name); unlink(sorted_name); } else if (unsorted_exist) { // SORT AND COMPRESS sort_pid = run_sort(-1, &fd, &sort_err_fd, unsorted_name, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(unsorted_name); } else if (unsorted_gz_exist) { // UNCOMPRESS SORT AND COMPRESS uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, unsorted_gz_name, NULL); sort_pid = run_sort(fd, &fd, &sort_err_fd, NULL, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS SORT AND COMPRESS uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, orig_name, NULL); sort_pid = run_sort(fd, &fd, &sort_err_fd, NULL, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(orig_name); } } else { if (sorted_exist) { unlink(sorted_name); } if (unsorted_exist) { unlink(unsorted_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (sort_index && !compress_index) { if (!sorted_exist) { if (sorted_gz_exist) { // UNCOMPRESS uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, sorted_gz_name, sorted_name); unlink(sorted_gz_name); } else if (unsorted_exist) { // SORT sort_pid = run_sort(-1, NULL, &sort_err_fd, unsorted_name, sorted_name); unlink(unsorted_name); } else if (unsorted_gz_exist) { // UNCOMPRESS AND SORT uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, unsorted_gz_name, NULL); sort_pid = run_sort(fd, NULL, &sort_err_fd, NULL, sorted_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS AND SORT uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, orig_name, NULL); sort_pid = run_sort(fd, NULL, &sort_err_fd, NULL, sorted_name); unlink(orig_name); } } else { if (sorted_gz_exist) { unlink(sorted_gz_name); } if (unsorted_exist) { unlink(unsorted_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (!sort_index && compress_index) { if (!sorted_gz_exist && !unsorted_gz_exist) { if (sorted_exist) { // COMPRESS sorted compress_pid = run_compress(-1, NULL, &compress_err_fd, sorted_name, sorted_gz_name); unlink(sorted_name); } else if (unsorted_exist) { // COMPRESS unsorted compress_pid = run_compress(-1, NULL, &compress_err_fd, unsorted_name, unsorted_gz_name); unlink(unsorted_name); } else if (orig_exist) { // RENAME orig rename(orig_name, unsorted_gz_name); } } else { if (sorted_exist) { unlink(sorted_name); } if (unsorted_exist) { unlink(unsorted_name); } if (sorted_gz_exist && unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (!sort_index && !compress_index) { if (!sorted_exist && !unsorted_exist) { if (sorted_gz_exist) { // UNCOMPRESS sorted uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, sorted_gz_name, sorted_name); unlink(sorted_gz_name); } else if (unsorted_gz_exist) { // UNCOMPRESS unsorted uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, unsorted_gz_name, unsorted_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS orig uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, orig_name, unsorted_name); unlink(orig_name); } } else { if (sorted_gz_exist) { unlink(sorted_gz_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } if (sorted_exist && unsorted_exist) { unlink(unsorted_name); } } } if (uncompress_pid != -1) wait_process(uncompress_pid, uncompress_err_fd, "uncompress"); if (sort_pid != -1) wait_process(sort_pid, sort_err_fd, "sort"); if (compress_pid != -1) wait_process(compress_pid, compress_err_fd, "compress"); g_free(orig_name); g_free(sorted_name); g_free(sorted_gz_name); g_free(unsorted_name); g_free(unsorted_gz_name); } amfree(datestamp); amfree(names[i]); } g_slist_free(matching_dp); amfree(names); amfree(host); amfree(disk); amfree(indexdir); amfree(qindexdir); } } file_lock_unlock(lock_index); lock_failed: file_lock_free(lock_index); amfree(conf_indexdir); amfree(lock_file); free_find_result(&output_find); clear_tapelist(); free_disklist(&diskl); unload_disklist(); dbclose(); return 0; }
int main(int argc, char ** argv) { char * tapelist_name; taper_state_t state; config_overwrites_t *cfg_ovr = NULL; char *cfg_opt = 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"); safe_fd(-1, 0); set_pname("taper"); dbopen("server"); device_api_init(); init_taper_state(&state); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); g_fprintf(stderr, _("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), argv[0], version()); dbprintf(_("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), argv[0], version()); /* Process options */ cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); if(argc > 2) { error("Too many arguments!\n"); g_assert_not_reached(); } if (argc > 1) cfg_opt = argv[1]; config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); apply_config_overwrites(cfg_ovr); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } safe_cd(); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_trace_log); check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST)); if (read_tapelist(tapelist_name) != 0) { log_add(L_INFO, "pid-done %ld", (long)getpid()); error("could not load tapelist \"%s\"", tapelist_name); g_assert_not_reached(); } amfree(tapelist_name); state.have_changer = changer_init(); if (state.have_changer < 0) { log_add(L_INFO, "pid-done %ld", (long)getpid()); error("changer initialization failed: %s", strerror(errno)); g_assert_not_reached(); } state.next_tape_label = NULL; state.next_tape_device = NULL; state.cur_tape = 0; if (!find_first_tape(&state)) { log_add(L_INFO, "pid-done %ld", (long)getpid()); return EXIT_SUCCESS; } while (process_driver_command(&state)); log_add(L_INFO, "pid-done %ld", (long)getpid()); return EXIT_SUCCESS; }
int main( int argc, char ** argv) { int foreground; int batch; int redirect; char **datearg = NULL; int nb_datearg = 0; char *conf_diskfile; char *conf_tapelist; char *conf_logfile; int conf_usetimestamps; disklist_t diskq; disk_t *dp; pid_t pid; pid_t driver_pid, reporter_pid; amwait_t exitcode; int opt; GSList *holding_list=NULL, *holding_file; int driver_pipe[2]; char date_string[100]; char date_string_standard[100]; time_t today; char *errstr; struct tm *tm; char *tapedev; char *tpchanger; char *qdisk, *qhname; GSList *datestamp_list = NULL; config_overrides_t *cfg_ovr; char **config_options; find_result_t *holding_files; disklist_t holding_disklist = { NULL, 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"); safe_fd(-1, 0); safe_cd(); set_pname("amflush"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); foreground = 0; batch = 0; redirect = 1; /* process arguments */ cfg_ovr = new_config_overrides(argc/2); while((opt = getopt(argc, argv, "bfso:D:")) != EOF) { switch(opt) { case 'b': batch = 1; break; case 'f': foreground = 1; break; case 's': redirect = 0; break; case 'o': add_config_override_opt(cfg_ovr, optarg); break; case 'D': if (datearg == NULL) datearg = g_malloc(21*sizeof(char *)); if(nb_datearg == 20) { g_fprintf(stderr,_("maximum of 20 -D arguments.\n")); exit(1); } datearg[nb_datearg++] = g_strdup(optarg); datearg[nb_datearg] = NULL; break; } } argc -= optind, argv += optind; if(!foreground && !redirect) { g_fprintf(stderr,_("Can't redirect to stdout/stderr if not in forground.\n")); exit(1); } if(argc < 1) { error(_("Usage: amflush [-b] [-f] [-s] [-D date]* [-o configoption]* <confdir> [host [disk]* ]*")); /*NOTREACHED*/ } set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_EXPLICIT_NAME, argv[0]); 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); /* load DLEs from the holding disk, in case there's anything to flush there */ search_holding_disk(&holding_files, &holding_disklist); /* note that the dumps are added to the global disklist, so we need not * consult holding_files or holding_disklist after this. The holding-only * dumps will be filtered properly by match_disklist, setting the dp->todo * flag appropriately. */ errstr = match_disklist(&diskq, argc-1, argv+1); if (errstr) { g_printf(_("%s"),errstr); amfree(errstr); } conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } amfree(conf_tapelist); conf_usetimestamps = getconf_boolean(CNF_USETIMESTAMPS); amflush_datestamp = get_datestamp_from_time(0); if(conf_usetimestamps == 0) { amflush_timestamp = g_strdup(amflush_datestamp); } else { amflush_timestamp = get_timestamp_from_time(0); } conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); conf_logfile = g_strjoin(NULL, conf_logdir, "/log", NULL); if (access(conf_logfile, F_OK) == 0) { run_amcleanup(get_config_name()); } if (access(conf_logfile, F_OK) == 0) { char *process_name = get_master_process(conf_logfile); error(_("%s exists: %s is already running, or you must run amcleanup"), conf_logfile, process_name); /*NOTREACHED*/ } driver_program = g_strjoin(NULL, amlibexecdir, "/", "driver", NULL); reporter_program = g_strjoin(NULL, sbindir, "/", "amreport", NULL); logroll_program = g_strjoin(NULL, amlibexecdir, "/", "amlogroll", NULL); tapedev = getconf_str(CNF_TAPEDEV); tpchanger = getconf_str(CNF_TPCHANGER); if (tapedev == NULL && tpchanger == NULL) { error(_("No tapedev or tpchanger specified")); } /* if dates were specified (-D), then use match_datestamp * against the list of all datestamps to turn that list * into a set of existing datestamps (basically, evaluate the * expressions into actual datestamps) */ if(datearg) { GSList *all_datestamps; GSList *datestamp; int i, ok; all_datestamps = holding_get_all_datestamps(); for(datestamp = all_datestamps; datestamp != NULL; datestamp = datestamp->next) { ok = 0; for(i=0; i<nb_datearg && ok==0; i++) { ok = match_datestamp(datearg[i], (char *)datestamp->data); } if (ok) datestamp_list = g_slist_insert_sorted(datestamp_list, g_strdup((char *)datestamp->data), g_compare_strings); } slist_free_full(all_datestamps, g_free); } else { /* otherwise, in batch mode, use all datestamps */ if(batch) { datestamp_list = holding_get_all_datestamps(); } /* or allow the user to pick datestamps */ else { datestamp_list = pick_datestamp(); } } if(!datestamp_list) { g_printf(_("Could not find any Amanda directories to flush.\n")); exit(1); } holding_list = holding_get_files_for_flush(datestamp_list); if (holding_list == NULL) { g_printf(_("Could not find any valid dump image, check directory.\n")); exit(1); } if (access(conf_logfile, F_OK) == 0) { char *process_name = get_master_process(conf_logfile); error(_("%s exists: someone started %s"), conf_logfile, process_name); /*NOTREACHED*/ } log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); if(!batch) confirm(datestamp_list); for(dp = diskq.head; dp != NULL; dp = dp->next) { if(dp->todo) { char *qname; qname = quote_string(dp->name); log_add(L_DISK, "%s %s", dp->host->hostname, qname); amfree(qname); } } if(!foreground) { /* write it before redirecting stdout */ puts(_("Running in background, you can log off now.")); puts(_("You'll get mail when amflush is finished.")); } if(redirect) redirect_stderr(); if(!foreground) detach(); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_trace_log); today = time(NULL); tm = localtime(&today); if (tm) { strftime(date_string, 100, "%a %b %e %H:%M:%S %Z %Y", tm); strftime(date_string_standard, 100, "%Y-%m-%d %H:%M:%S %Z", tm); } else { error(_("BAD DATE")); /* should never happen */ } g_fprintf(stderr, _("amflush: start at %s\n"), date_string); g_fprintf(stderr, _("amflush: datestamp %s\n"), amflush_timestamp); g_fprintf(stderr, _("amflush: starttime %s\n"), amflush_timestamp); g_fprintf(stderr, _("amflush: starttime-locale-independent %s\n"), date_string_standard); log_add(L_START, _("date %s"), amflush_timestamp); /* START DRIVER */ if(pipe(driver_pipe) == -1) { error(_("error [opening pipe to driver: %s]"), strerror(errno)); /*NOTREACHED*/ } if((driver_pid = fork()) == 0) { /* * This is the child process. */ dup2(driver_pipe[0], 0); close(driver_pipe[1]); config_options = get_config_options(3); config_options[0] = "driver"; config_options[1] = get_config_name(); config_options[2] = "nodump"; safe_fd(-1, 0); execve(driver_program, config_options, safe_env()); error(_("cannot exec %s: %s"), driver_program, strerror(errno)); /*NOTREACHED*/ } else if(driver_pid == -1) { error(_("cannot fork for %s: %s"), driver_program, strerror(errno)); /*NOTREACHED*/ } driver_stream = fdopen(driver_pipe[1], "w"); if (!driver_stream) { error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } g_fprintf(driver_stream, "DATE %s\n", amflush_timestamp); for(holding_file=holding_list; holding_file != NULL; holding_file = holding_file->next) { dumpfile_t file; holding_file_get_dumpfile((char *)holding_file->data, &file); if (holding_file_size((char *)holding_file->data, 1) <= 0) { g_debug("%s is empty - ignoring", (char *)holding_file->data); log_add(L_INFO, "%s: removing file with no data.", (char *)holding_file->data); holding_file_unlink((char *)holding_file->data); dumpfile_free_data(&file); continue; } /* search_holding_disk should have already ensured that every * holding dumpfile has an entry in the dynamic disklist */ dp = lookup_disk(file.name, file.disk); assert(dp != NULL); /* but match_disklist may have indicated we should not flush it */ if (dp->todo == 0) continue; qdisk = quote_string(file.disk); qhname = quote_string((char *)holding_file->data); g_fprintf(stderr, "FLUSH %s %s %s %d %s\n", file.name, qdisk, file.datestamp, file.dumplevel, qhname); g_debug("flushing '%s'", (char *)holding_file->data); g_fprintf(driver_stream, "FLUSH %s %s %s %d %s\n", file.name, qdisk, file.datestamp, file.dumplevel, qhname); amfree(qdisk); amfree(qhname); dumpfile_free_data(&file); } g_fprintf(stderr, "ENDFLUSH\n"); fflush(stderr); g_fprintf(driver_stream, "ENDFLUSH\n"); fflush(driver_stream); fclose(driver_stream); /* WAIT DRIVER */ while(1) { if((pid = wait(&exitcode)) == -1) { if(errno == EINTR) { continue; } else { error(_("wait for %s: %s"), driver_program, strerror(errno)); /*NOTREACHED*/ } } else if (pid == driver_pid) { break; } } slist_free_full(datestamp_list, g_free); datestamp_list = NULL; slist_free_full(holding_list, g_free); holding_list = NULL; if(redirect) { /* rename errfile */ char *errfile, *errfilex, *nerrfilex, number[100]; int tapecycle; int maxdays, days; struct stat stat_buf; errfile = g_strjoin(NULL, conf_logdir, "/amflush", NULL); errfilex = NULL; nerrfilex = NULL; tapecycle = getconf_int(CNF_TAPECYCLE); maxdays = tapecycle + 2; days = 1; /* First, find out the last existing errfile, */ /* to avoid ``infinite'' loops if tapecycle is infinite */ g_snprintf(number,100,"%d",days); errfilex = newvstralloc(errfilex, errfile, ".", number, NULL); while ( days < maxdays && stat(errfilex,&stat_buf)==0) { days++; g_snprintf(number,100,"%d",days); errfilex = newvstralloc(errfilex, errfile, ".", number, NULL); } g_snprintf(number,100,"%d",days); errfilex = newvstralloc(errfilex, errfile, ".", number, NULL); nerrfilex = NULL; while (days > 1) { amfree(nerrfilex); nerrfilex = errfilex; days--; g_snprintf(number,100,"%d",days); errfilex = g_strjoin(NULL, errfile, ".", number, NULL); if (rename(errfilex, nerrfilex) != 0) { error(_("cannot rename \"%s\" to \"%s\": %s"), errfilex, nerrfilex, strerror(errno)); /*NOTREACHED*/ } } errfilex = newvstralloc(errfilex, errfile, ".1", NULL); if (rename(errfile,errfilex) != 0) { error(_("cannot rename \"%s\" to \"%s\": %s"), errfilex, nerrfilex, strerror(errno)); /*NOTREACHED*/ } amfree(errfile); amfree(errfilex); amfree(nerrfilex); } /* * Have amreport generate report and send mail. Note that we do * not bother checking the exit status. If it does not work, it * can be rerun. */ if((reporter_pid = fork()) == 0) { /* * This is the child process. */ config_options = get_config_options(3); config_options[0] = "amreport"; config_options[1] = get_config_name(); config_options[2] = "--from-amdump"; safe_fd(-1, 0); execve(reporter_program, config_options, safe_env()); error(_("cannot exec %s: %s"), reporter_program, strerror(errno)); /*NOTREACHED*/ } else if(reporter_pid == -1) { error(_("cannot fork for %s: %s"), reporter_program, strerror(errno)); /*NOTREACHED*/ } while(1) { if((pid = wait(&exitcode)) == -1) { if(errno == EINTR) { continue; } else { error(_("wait for %s: %s"), reporter_program, strerror(errno)); /*NOTREACHED*/ } } else if (pid == reporter_pid) { break; } } log_add(L_INFO, "pid-done %ld", (long)getpid()); /* * Call amlogroll to rename the log file to its datestamped version. * Since we exec at this point, our exit code will be that of amlogroll. */ config_options = get_config_options(2); config_options[0] = "amlogroll"; config_options[1] = get_config_name(); safe_fd(-1, 0); execve(logroll_program, config_options, safe_env()); error(_("cannot exec %s: %s"), logroll_program, strerror(errno)); /*NOTREACHED*/ return 0; /* keep the compiler happy */ }
int main( int argc, char ** argv) { disklist_t diskl; int no_keep; /* files per system to keep */ char **output_find_log; DIR *dir; struct dirent *adir; char **name; int useful; char *olddir; char *oldfile = NULL, *newfile = NULL; time_t today, date_keep; char *logname = NULL; struct stat stat_log; struct stat stat_old; char *conf_diskfile; char *conf_tapelist; char *conf_logdir; int dumpcycle; config_overwrites_t *cfg_ovr = 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"); safe_fd(-1, 0); safe_cd(); set_pname("amtrmlog"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); if (argc > 1 && strcmp(argv[1], "-t") == 0) { amtrmidx_debug = 1; argc--; argv++; } if (argc < 2) { g_fprintf(stderr, _("Usage: %s [-t] <config> [-o configoption]*\n"), argv[0]); return 1; } dbopen(DBG_SUBDIR_SERVER); dbprintf(_("%s: version %s\n"), argv[0], version()); config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]); apply_config_overwrites(cfg_ovr); conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); read_diskfile(conf_diskfile, &diskl); 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); conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if (read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } amfree(conf_tapelist); today = time((time_t *)NULL); dumpcycle = getconf_int(CNF_DUMPCYCLE); if(dumpcycle > 5000) dumpcycle = 5000; date_keep = today - (dumpcycle * 86400); output_find_log = find_log(); /* determine how many log to keep */ no_keep = getconf_int(CNF_TAPECYCLE) * 2; dbprintf(plural(_("Keeping %d log file\n"), _("Keeping %d log files\n"), no_keep), no_keep); conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); olddir = vstralloc(conf_logdir, "/oldlog", NULL); if (mkpdir(olddir, 0700, (uid_t)-1, (gid_t)-1) != 0) { error(_("could not create parents of %s: %s"), olddir, strerror(errno)); /*NOTREACHED*/ } if (mkdir(olddir, 0700) != 0 && errno != EEXIST) { error(_("could not create %s: %s"), olddir, strerror(errno)); /*NOTREACHED*/ } if (stat(olddir,&stat_old) == -1) { error(_("can't stat oldlog directory \"%s\": %s"), olddir, strerror(errno)); /*NOTREACHED*/ } if (!S_ISDIR(stat_old.st_mode)) { error(_("Oldlog directory \"%s\" is not a directory"), olddir); /*NOTREACHED*/ } if ((dir = opendir(conf_logdir)) == NULL) { error(_("could not open log directory \"%s\": %s"), conf_logdir,strerror(errno)); /*NOTREACHED*/ } while ((adir=readdir(dir)) != NULL) { if(strncmp(adir->d_name,"log.",4)==0) { useful=0; for (name=output_find_log;*name !=NULL; name++) { if((strlen(adir->d_name) >= 13 && strlen(*name) >= 13 && adir->d_name[12] == '.' && (*name)[12] == '.' && strncmp(adir->d_name,*name,12)==0) || strncmp(adir->d_name,*name,18)==0) { useful=1; break; } } logname=newvstralloc(logname, conf_logdir, "/" ,adir->d_name, NULL); if(stat(logname,&stat_log)==0) { if((time_t)stat_log.st_mtime > date_keep) { useful = 1; } } if(useful == 0) { oldfile = newvstralloc(oldfile, conf_logdir, "/", adir->d_name, NULL); newfile = newvstralloc(newfile, olddir, "/", adir->d_name, NULL); if (rename(oldfile,newfile) != 0) { error(_("could not rename \"%s\" to \"%s\": %s"), oldfile, newfile, strerror(errno)); /*NOTREACHED*/ } } } } closedir(dir); for (name = output_find_log; *name != NULL; name++) { amfree(*name); } amfree(output_find_log); amfree(logname); amfree(oldfile); amfree(newfile); amfree(olddir); amfree(conf_logdir); clear_tapelist(); free_disklist(&diskl); dbclose(); return 0; }
find_result_t * find_dump(disklist_t* diskqp) { char *conf_logdir, *logfile = NULL; int tape, tape1, maxtape, logs; unsigned seq; tape_t *tp, *tp1; find_result_t *output_find = NULL; gboolean *tape_seen = NULL; if (string_chunk == NULL) { string_chunk = g_string_chunk_new(32768); } conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); maxtape = lookup_nb_tape(); tape_seen = g_new0(gboolean, maxtape+1); for(tape = 1; tape <= maxtape; tape++) { if (tape_seen[tape] == 1) continue; tp = lookup_tapepos(tape); if(tp == NULL) continue; /* find all tape with the same datestamp */ for (tape1 = tape; tape1 <= maxtape; tape1++) { tp1 = lookup_tapepos(tape1); if (tp1 == NULL) continue; if (!g_str_equal(tp->datestamp, tp1->datestamp)) continue; tape_seen[tape1] = 1; } /* search log files */ logs = 0; /* new-style log.<date>.<seq> */ for(seq = 0; 1; seq++) { char seq_str[NUM_STR_SIZE]; g_snprintf(seq_str, sizeof(seq_str), "%u", seq); g_free(logfile); logfile = g_strconcat(conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL); if(access(logfile, R_OK) != 0) break; if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } /* search old-style amflush log, if any */ g_free(logfile); logfile = g_strconcat(conf_logdir, "/log.", tp->datestamp, ".amflush", NULL); if(access(logfile,R_OK) == 0) { if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } /* search old-style main log, if any */ g_free(logfile); logfile = g_strconcat(conf_logdir, "/log.", tp->datestamp, NULL); if(access(logfile,R_OK) == 0) { if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } } g_free(tape_seen); amfree(logfile); amfree(conf_logdir); search_holding_disk(&output_find, diskqp); return(output_find); }
int main( int argc, char ** argv) { extern int optind; int opt; GSList *dumpspecs = NULL; int fd; tapelist_t *needed_tapes = NULL; char *e; rst_flags_t *rst_flags; int minimum_arguments; config_overrides_t *cfg_ovr = NULL; disklist_t diskq; char * conf_diskfile = NULL; am_feature_t *our_features = am_init_feature_set(); /* * 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"); set_pname("amfetchdump"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); error_exit_status = 2; rst_flags = new_rst_flags(); rst_flags->wait_tape_prompt = 1; /* handle options */ cfg_ovr = new_config_overrides(argc/2); while( (opt = getopt_long(argc, argv, "alht:scCpb:nwi:d:O:o:", long_options, NULL)) != -1) { switch(opt) { case 0: switch (loptions) { case 1: rst_flags->headers = 1; if (strcmp(optarg, "-") == 0) rst_flags->header_to_fd = STDOUT_FILENO; else rst_flags->header_to_fd = atoi(optarg); if (fcntl(rst_flags->header_to_fd, F_GETFL, NULL) == -1) { error(_("fd %d: %s\n"), rst_flags->header_to_fd, strerror(errno)); } break; case 2: rst_flags->headers = 1; rst_flags->header_to_fd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (rst_flags->header_to_fd == -1) { error(_("Can't create '%s': %s\n"), optarg, strerror(errno)); } break; } break; 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); /*NOTREACHED*/ } if(rst_flags->blocksize < DISK_BLOCK_BYTES) { 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 '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 = 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_override_opt(cfg_ovr, optarg); break; default: usage(); /*NOTREACHED*/ } } for(fd = 3; fd < (int)FD_SETSIZE; fd++) { if (fd != debug_fd() && fd != rst_flags->pipe_to_fd && fd != rst_flags->header_to_fd) { /* * Make sure nobody spoofs us with a lot of extra open files * 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). */ close(fd); } } /* Check some flags that affect inventorying */ if(rst_flags->inventory_log){ if(rst_flags->inline_assemble) rst_flags->delay_assemble = 1; rst_flags->inline_assemble = 0; rst_flags->leave_comp = 1; if(rst_flags->compress){ error(_("Cannot force compression when doing inventory/search")); /*NOTREACHED*/ } g_fprintf(stderr, _("Doing inventory/search, dumps will not be uncompressed or assembled on-the-fly.\n")); } else{ if(rst_flags->delay_assemble){ 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(); /*NOTREACHED*/ } if (rst_flags->inventory_log) { minimum_arguments = 1; } else { minimum_arguments = 2; } if(argc - optind < minimum_arguments) { usage(); /*NOTREACHED*/ } config_init(CONFIG_INIT_EXPLICIT_NAME, argv[optind++]); apply_config_overrides(cfg_ovr); 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){ g_fprintf(stderr, _("Beginning tape-by-tape search.\n")); search_tapes(stderr, stdin, rst_flags->alt_tapedev == NULL, NULL, dumpspecs, rst_flags, our_features); dbclose(); exit(0); } /* Decide what tapes we'll need */ 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) { 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, our_features); cleanup(); 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); dbclose(); return(0); }
/* * 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( GSList * dumpspecs, int only_one, disklist_t *diskqp) { 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 usage_order_counter = 0; 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); /*NOTREACHED*/ } amfree(conf_tapelist); /* Grab a find_output_t of all logged dumps */ alldumps = find_dump(diskqp); if(alldumps == NULL){ g_fprintf(stderr, _("No dump records found\n")); dbclose(); exit(1); } /* Compare all known dumps to our match list, note what we'll need */ matches = dumps_match_dumpspecs(alldumps, dumpspecs, 1); /* D = dump_timestamp, newest first * h = hostname * k = diskname * l = level * p = partnum * w = write_timestamp */ sort_find_result("Dhklpw", &matches); for(curmatch = matches; curmatch; curmatch = curmatch->next) { int havetape = 0; /* 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)) { 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); 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, (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) { needed_tape_t *newtape = g_new0(needed_tape_t, 1); newtape->usage_order = usage_order_counter++; 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 */ } /* 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); } } } /* 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); }
find_result_t * find_dump(disklist_t* diskqp) { char *conf_logdir, *logfile = NULL; int tape, maxtape, logs; unsigned seq; tape_t *tp; find_result_t *output_find = NULL; GHashTable *tape_seen = g_hash_table_new(g_str_hash, g_str_equal); if (string_chunk == NULL) { string_chunk = g_string_chunk_new(32768); } conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); maxtape = lookup_nb_tape(); for(tape = 1; tape <= maxtape; tape++) { tp = lookup_tapepos(tape); if(tp == NULL) continue; /* Do not search the log file if we already searched that datestamp */ if (g_hash_table_lookup(tape_seen, tp->datestamp)) { continue; } g_hash_table_insert(tape_seen, tp->datestamp, GINT_TO_POINTER(1)); /* search log files */ logs = 0; /* new-style log.<date>.<seq> */ for(seq = 0; 1; seq++) { char seq_str[NUM_STR_SIZE]; g_snprintf(seq_str, sizeof(seq_str), "%u", seq); g_free(logfile); logfile = g_strconcat(conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL); if(access(logfile, R_OK) != 0) break; if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } /* search old-style amflush log, if any */ g_free(logfile); logfile = g_strconcat(conf_logdir, "/log.", tp->datestamp, ".amflush", NULL); if(access(logfile,R_OK) == 0) { if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } /* search old-style main log, if any */ g_free(logfile); logfile = g_strconcat(conf_logdir, "/log.", tp->datestamp, NULL); if(access(logfile,R_OK) == 0) { if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } } g_hash_table_destroy(tape_seen); amfree(logfile); amfree(conf_logdir); search_holding_disk(&output_find, diskqp); return(output_find); }
char * make_logname( char *process, char *datestamp) { char *conf_logdir; char *fname = NULL; char *logf; if (datestamp == NULL) datestamp = g_strdup("error-00000000"); conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); fname = g_strjoin(NULL, conf_logdir, "/log", NULL); while (1) { int fd; g_free(logfile); logfile = g_strconcat(fname, ".", datestamp, ".0", NULL); /* try to create it */ fd = open(logfile, O_EXCL | O_CREAT | O_WRONLY, 0600); if (fd > -1) { FILE *file; file = fdopen(fd, "w"); if (file) { gchar *text = g_strdup_printf("INFO %s %s pid %ld\n", process, process, (long)getpid()); fprintf(file, "%s", text); fclose(file); file = fopen(logfile, "r"); if (file) { char line[1000]; if (fgets(line, 1000, file)) { if (g_str_equal(line, text)) { /* the file is for us */ g_free(text); fclose(file); break; } } fclose(file); } g_free(text); } } /* increase datestamp */ datestamp[13]++; if (datestamp[13] == ':') { datestamp[13] = '0'; datestamp[12]++; if (datestamp[12] == '6') { datestamp[12] = '0'; datestamp[11]++; if (datestamp[11] == ':') { datestamp[11] = '0'; datestamp[10]++; if (datestamp[10] == '6') { datestamp[10] = '0'; datestamp[9]++; if (datestamp[9] == ':') { datestamp[9] = '0'; datestamp[8]++; } } } } } } unlink(fname); logf = g_strdup(rindex(logfile,'/')+1); if (symlink(logf, fname) == -1) { g_debug("Can't symlink '%s' to '%s': %s", fname, logf, strerror(errno)); } amfree(logf); amfree(fname); amfree(conf_logdir); return (datestamp); }