⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amadmin.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 4 页
字号:
					argv+(start_argc-1));	if (errstr) {	    g_printf("%s", errstr);	    amfree(errstr);	}	output_find = find_dump(NULL);    }    sort_find_result(sort_order, &output_find);    print_find_result(output_find);    free_find_result(&output_find);    amfree(sort_order);}/* ------------------------ */static GSList *get_file_list(    int argc,    char **argv,    int allow_empty){    GSList * file_list = NULL;    GSList * dumplist;    int flags;    flags = CMDLINE_PARSE_DATESTAMP;    if (allow_empty) flags |= CMDLINE_EMPTY_TO_WILDCARD;    dumplist = cmdline_parse_dumpspecs(argc, argv, flags);    file_list = cmdline_match_holding(dumplist);    dumpspec_list_free(dumplist);    return file_list;}/* Given a file header, find the history element in curinfo most likely * corresponding to that dump (this is not an exact science). * * @param info: the info_t element for this DLE * @param file: the header of the file * @returns: index of the matching history element, or -1 if not found */static intholding_file_find_history(    info_t *info,    dumpfile_t *file){    int matching_hist_idx = -1;    int nhist;    int i;    /* Begin by trying to find the history element matching this dump.     * The datestamp on the dump is for the entire run of amdump, while the     * 'date' in the history element of 'info' is the time the dump itself     * began.  A matching history element, then, is the earliest element     * with a 'date' equal to or later than the date of the dumpfile.     *     * We compare using formatted datestamps; even using seconds since epoch,     * we would still face timezone issues, and have to do a reverse (timezone     * to gmt) translation.     */    /* get to the end of the history list and search backward */    for (nhist = 0; info->history[nhist].level > -1; nhist++) /* empty loop */;    for (i = nhist-1; i > -1; i--) {        char *info_datestamp = get_timestamp_from_time(info->history[i].date);        int order = strcmp(file->datestamp, info_datestamp);        amfree(info_datestamp);        if (order <= 0) {            /* only a match if the levels are equal */            if (info->history[i].level == file->dumplevel) {                matching_hist_idx = i;            }            break;        }    }    return matching_hist_idx;}/* A holding file is 'outdated' if a subsequent dump of the same DLE was made * at the same level or a lower leve; for example, a level 2 dump is outdated if * there is a subsequent level 2, or a subsequent level 0. * * @param file: the header of the file * @returns: true if the file is outdated */static intholding_file_is_outdated(    dumpfile_t *file){    info_t info;    int matching_hist_idx;    if (get_info(file->name, file->disk, &info) == -1) {	return 0; /* assume it's not outdated */    }    /* if the last level is less than the level of this dump, then     * it's outdated */    if (info.last_level < file->dumplevel)	return 1;    /* otherwise, we need to see if this dump is the last at its level */    matching_hist_idx = holding_file_find_history(&info, file);    if (matching_hist_idx == -1) {        return 0; /* assume it's not outdated */    }    /* compare the date of the history element with the most recent date     * for this level.  If they match, then this is the last dump at this     * level, and we checked above for more recent lower-level dumps, so     * the dump is not outdated. */    if (info.history[matching_hist_idx].date == 	info.inf[info.history[matching_hist_idx].level].date) {	return 0;    } else {	return 1;    }}static intremove_holding_file_from_catalog(    char *filename){    static int warnings_printed; /* only print once per invocation */    dumpfile_t file;    info_t info;    int matching_hist_idx = -1;    history_t matching_hist; /* will be a copy */    int i;    if (!holding_file_get_dumpfile(filename, &file)) {        g_printf(_("Could not read holding file %s\n"), filename);        return 0;    }    if (get_info(file.name, file.disk, &info) == -1) {	    g_printf(_("WARNING: No curinfo record for %s:%s\n"), file.name, file.disk);	    return 1; /* not an error */    }    matching_hist_idx = holding_file_find_history(&info, &file);    if (matching_hist_idx == -1) {        g_printf(_("WARNING: No dump matching %s found in curinfo.\n"), filename);	return 1; /* not an error */    }    /* make a copy */    matching_hist = info.history[matching_hist_idx];    /* Remove the history element itself before doing the stats */    for (i = matching_hist_idx; i <= NB_HISTORY; i++) {        info.history[i] = info.history[i+1];    }    info.history[NB_HISTORY].level = -1;    /* Remove stats for that history element, if necessary.  Doing so     * will result in an inconsistent set of backups, so we warn the     * user and adjust last_level to make the next dump get us a      * consistent picture. */    if (matching_hist.date == info.inf[matching_hist.level].date) {        /* search for an earlier dump at this level */        for (i = matching_hist_idx; info.history[i].level > -1; i++) {            if (info.history[i].level == matching_hist.level)                break;        }        if (info.history[i].level < 0) {            /* not found => zero it out */            info.inf[matching_hist.level].date = (time_t)-1; /* flag as not set */            info.inf[matching_hist.level].label[0] = '\0';        } else {            /* found => reconstruct stats as best we can */            info.inf[matching_hist.level].size = info.history[i].size;            info.inf[matching_hist.level].csize = info.history[i].csize;            info.inf[matching_hist.level].secs = info.history[i].secs;            info.inf[matching_hist.level].date = info.history[i].date;            info.inf[matching_hist.level].filenum = 0; /* we don't know */            info.inf[matching_hist.level].label[0] = '\0'; /* we don't know */        }        /* set last_level to the level we just deleted, and set command         * appropriately to make sure planner does a new dump at this level         * or lower */        info.last_level = matching_hist.level;        if (info.last_level == 0) {            g_printf(_("WARNING: Deleting the most recent full dump; forcing a full dump at next run.\n"));            SET(info.command, FORCE_FULL);        } else {            g_printf(_("WARNING: Deleting the most recent level %d dump; forcing a level %d dump or \nWARNING: lower at next run.\n"),                info.last_level, info.last_level);            SET(info.command, FORCE_NO_BUMP);        }        /* Search for and display any subsequent runs that depended on this one */        warnings_printed = 0;        for (i = matching_hist_idx-1; i >= 0; i--) {            char *datestamp;            if (info.history[i].level <= matching_hist.level) break;            datestamp = get_timestamp_from_time(info.history[i].date);            g_printf(_("WARNING: Level %d dump made %s can no longer be accurately restored.\n"),                 info.history[i].level, datestamp);            amfree(datestamp);            warnings_printed = 1;        }        if (warnings_printed)            g_printf(_("WARNING: (note, dates shown above are for dumps, and may be later than the\nWARNING: corresponding run date)\n"));    }    /* recalculate consecutive_runs based on the history: find the first run     * at this level, and then count the consecutive runs at that level. This     * number may be zero (if we just deleted the last run at this level) */    info.consecutive_runs = 0;    for (i = 0; info.history[i].level >= 0; i++) {        if (info.history[i].level == info.last_level) break;    }    while (info.history[i+info.consecutive_runs].level == info.last_level)        info.consecutive_runs++;    /* this function doesn't touch the performance stats */    /* write out the changes */    if (put_info(file.name, file.disk, &info) == -1) {	    g_printf(_("Could not write curinfo record for %s:%s\n"), file.name, file.disk);	    return 0;    }    return 1;}voidholding(    int		argc,    char **	argv){    GSList *file_list;    GSList *li;    enum { HOLDING_USAGE, HOLDING_LIST, HOLDING_DELETE } action = HOLDING_USAGE;    int long_list = 0;    int outdated_list = 0;    dumpfile_t file;    if (argc < 4)        action = HOLDING_USAGE;    else if (strcmp(argv[3], "list") == 0 && argc >= 4)        action = HOLDING_LIST;    else if (strcmp(argv[3], "delete") == 0 && argc > 4)        action = HOLDING_DELETE;    switch (action) {        case HOLDING_USAGE:            g_fprintf(stderr,                    _("%s: expecting \"holding list [-l] [-d]\" or \"holding delete <host> [ .. ]\"\n"),                    get_pname());            usage();            return;        case HOLDING_LIST:            argc -= 4; argv += 4;	    while (argc && argv[0][0] == '-') {		switch (argv[0][1]) {		    case 'l': 			long_list = 1; 			break;		    case 'd': /* have to use '-d', and not '-o', because of parse_config */			outdated_list = 1;			break;		    default:			g_fprintf(stderr, _("Unknown option -%c\n"), argv[0][1]);			usage();			return;		}		argc--; argv++;	    }	    /* header */            if (long_list) {                g_printf("%-10s %-2s %-4s %s\n", 		    _("size (kB)"), _("lv"), _("outd"), _("dump specification"));            }            file_list = get_file_list(argc, argv, 1);            for (li = file_list; li != NULL; li = li->next) {                char *dumpstr;		int is_outdated;                if (!holding_file_get_dumpfile((char *)li->data, &file)) {                    g_fprintf(stderr, _("Error reading %s\n"), (char *)li->data);                    continue;                }	        is_outdated = holding_file_is_outdated(&file);                dumpstr = cmdline_format_dumpspec_components(file.name, file.disk, file.datestamp, NULL);		/* only print this entry if we're printing everything, or if it's outdated and		 * we're only printing outdated files (-o) */		if (!outdated_list || is_outdated) {		    if (long_list) {			g_printf("%-10lld %-2d %-4s %s\n", 			       (long long)holding_file_size((char *)li->data, 0),			       file.dumplevel,			       is_outdated? " *":"",			       dumpstr);		    } else {			g_printf("%s\n", dumpstr);		    }		}                amfree(dumpstr);            }            g_slist_free_full(file_list);            break;        case HOLDING_DELETE:            argc -= 4; argv += 4;            file_list = get_file_list(argc, argv, 0);            for (li = file_list; li != NULL; li = li->next) {                g_fprintf(stderr, _("Deleting '%s'\n"), (char *)li->data);                /* remove it from the catalog */                if (!remove_holding_file_from_catalog((char *)li->data))                    exit(1);                /* unlink it */                if (!holding_file_unlink((char *)li->data)) {                    error(_("Could not delete '%s'"), (char *)li->data);                }            }            g_slist_free_full(file_list);            break;    }}/* ------------------------ *//* shared code with planner.c */intbump_thresh(    int		level){    int bump = getconf_int(CNF_BUMPSIZE);    double mult = getconf_real(CNF_BUMPMULT);    while(--level)	bump = (int)((double)bump * mult);    return bump;}voidbumpsize(    int		argc,    char **	argv){    int l;    int conf_bumppercent = getconf_int(CNF_BUMPPERCENT);    double conf_bumpmult = getconf_real(CNF_BUMPMULT);    (void)argc;	/* Quiet unused parameter warning */    (void)argv;	/* Quiet unused parameter warning */    g_printf(_("Current bump parameters:\n"));    if(conf_bumppercent == 0) {	g_printf(_("  bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n"),	       getconf_int(CNF_BUMPSIZE));	g_printf(_("  bumpdays %5d\t- minimum days at each level\n"),	       getconf_int(CNF_BUMPDAYS));	g_printf(_("  bumpmult %5.5lg\t- threshold = bumpsize * bumpmult**(level-1)\n\n"),	       conf_bumpmult);	g_printf(_("      Bump -> To  Threshold\n"));	for(l = 1; l < 9; l++)	    g_printf(_("\t%d  ->  %d  %9d KB\n"), l, l+1, bump_thresh(l));	putchar('\n');    }    else {	double bumppercent = (double)conf_bumppercent;	g_printf(_("  bumppercent %3d %%\t- minimum savings (threshold) to bump level 1 -> 2\n"),	       conf_bumppercent);	g_printf(_("  bumpdays %5d\t- minimum days at each level\n"),	       getconf_int(CNF_BUMPDAYS));	g_printf(_("  bumpmult %5.5lg\t- threshold = disk_size * bumppercent * bumpmult**(level-1)\n\n"),	       conf_bumpmult);	g_printf(_("      Bump -> To  Threshold\n"));	for(l = 1; l < 9; l++) {	    g_printf(_("\t%d  ->  %d  %7.2lf %%\n"), l, l+1, bumppercent);	    bumppercent *= conf_bumpmult;	    if(bumppercent >= 100.000) { bumppercent = 100.0;}	}	putchar('\n');    }}/* ----------------------------------------------- */void export_one(disk_t *dp);voidexport_db(    int		argc,    char **	argv){    disk_t *dp;    time_t curtime;    char hostname[MAX_HOSTNAME_LENGTH+1];    int i;    g_printf(_("CURINFO Version %s CONF %s\n"), version(), getconf_str(CNF_ORG));    curtime = time(0);    if(gethostname(hostname, SIZEOF(hostname)-1) == -1) {	error(_("could not determine host name: %s\n"), strerror(errno));	/*NOTREACHED*/    }    hostname[SIZEOF(hostname)-1] = '\0';    g_printf(_("# Generated by:\n#    host: %s\n#    date: %s"),	   hostname, ctime(&curtime));    g_printf(_("#    command:"));    for(i = 0; i < argc; i++)	g_printf(_(" %s"), argv[i]);    g_printf(_("\n# This file can be merged back in with \"amadmin import\".\n"));    g_printf(_("# Edit only with care.\n"));    if(argc >= 4)	diskloop(argc, argv, "export", export_one);    else for(dp = diskq.head; dp != NULL; dp = dp->next)	export_one(dp);}voidexport_one(    disk_t *	dp){    info_t info;    int i,l;    if(get_info(dp->host->hostname, dp->name, &info)) {	g_fprintf(stderr, _("Warning: no curinfo record for %s:%s\n"),		dp->host->hostname, dp->name);	return;    }    g_printf(_("host: %s\ndisk: %s\n"), dp->host->hostname, dp->name);    g_printf(_("command: %u\n"), info.command);    g_printf(_("last_level: %d\n"),info.last_level);    g_printf(_("consecutive_runs: %d\n"),info.consecutive_runs);    g_printf(_("full-rate:"));    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.full.rate[i]);    g_printf(_("\nfull-comp:"));    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.full.comp[i]);    g_printf(_("\nincr-rate:"));    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.incr.rate[i]);    g_printf(_("\nincr-comp:"));    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.incr.comp[i]);    g_printf("\n");    for(l=0;l<DUMP_LEVELS;l++) {	if(info.inf[l].date < (time_t)0 && info.inf[l].label[0] == '\0') continue;	g_printf(_("stats: %d %lld %lld %jd %jd %lld %s\n"), l,	       (long long)info.inf[l].size,	       (long long)info.inf[l].csize,	       (intmax_t)info.inf[l].secs,	       (intmax_t)info.inf[l].date,	       (long long)info.inf[l].filenum,	       info.inf[l].label);    }    for(l=0;info.history[l].level > -1;l++) {	g_printf(_("history: %d %lld %lld %jd\n"),	       info.history[l].level,	       (long long)info.history[l].size,	       (long long)info.history[l].csize,	       (intmax_t)info.history[l].date);    }    g_printf("//\n");}/* ----------------------------------------------- */int import_one(void);char *impget_line(void);voidimport_db(    int		argc,    char **	argv){    int vers_maj;    int vers_min;    int vers_patch;    int newer;    char *org;    char *line = NULL;    char *hdr;    char *s;    int rc;    int ch;    (void)argc;	/* Quiet unused parameter warning */    (void)argv;	/* Quiet unused parameter warning */    /* process header line */    if((line = agets(stdin)) == NULL) {	g_fprintf(stderr, _("%s: empty input.\n"), get_pname());	return;    }    s = line;    ch = *s++;    hdr = "version";    if(strncmp_const_skip(s - 1, "CURINFO Version", s, ch) != 0) {	goto bad_header;    }    ch = *s++;    skip_whitespace(s, ch);    if(ch == '\0'       || sscanf(s - 1, "%d.%d.%d", &vers_maj, &vers_min, &vers_patch) != 3) {	goto bad_header;    }    skip_integer(s, ch);			/* skip over major */    if(ch != '.') {	goto bad_header;    }    ch = *s++;    skip_integer(s, ch);			/* skip over minor */    if(ch != '.') {	goto bad_header;    }    ch = *s++;    skip_integer(s, ch);			/* skip over patch */    hdr = "comment";    if(ch == '\0') {	goto bad_header;    }    skip_non_whitespace(s, ch);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -