Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
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*/
    }
}
Пример #5
0
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();
}
Пример #6
0
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
0
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 */
}
Пример #10
0
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;
}
Пример #11
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);
}
Пример #12
0
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);
}
Пример #13
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);
}
Пример #14
0
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);
}
Пример #15
0
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);
}