示例#1
0
文件: find.c 项目: hangie/amanda
/* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr,
 * dynamic_disklist */
gboolean
search_logfile(
    find_result_t **output_find,
    const char *label,
    const char *passed_datestamp,
    const char *logfile,
    disklist_t * dynamic_disklist)
{
    FILE *logf;
    char *host, *host_undo;
    char *disk = NULL, *qdisk, *disk_undo;
    char *date, *date_undo;
    int  partnum;
    int  totalparts;
    int  maxparts = -1;
    char *number;
    int fileno;
    char *current_label;
    char *rest, *rest_undo;
    char *ck_label=NULL;
    int level = 0;
    off_t filenum;
    char *ck_datestamp=NULL;
    char *datestamp;
    char *s;
    int ch;
    disk_t *dp;
    GHashTable* valid_label;
    GHashTable* part_by_dle;
    find_result_t *part_find;
    find_result_t *a_part_find;
    gboolean right_label = FALSE;
    gboolean found_something = FALSE;
    double sec;
    off_t kb;
    off_t bytes;
    off_t orig_kb;
    int   taper_part = 0;

    g_return_val_if_fail(output_find != NULL, 0);
    g_return_val_if_fail(logfile != NULL, 0);

    current_label = g_strdup("");
    if (string_chunk == NULL) {
	string_chunk = g_string_chunk_new(32768);
    }
    valid_label = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
    part_by_dle = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
    datestamp = g_strdup(passed_datestamp);

    if((logf = fopen(logfile, "r")) == NULL) {
	error(_("could not open logfile %s: %s"), logfile, strerror(errno));
	/*NOTREACHED*/
    }

    filenum = (off_t)0;
    while(get_logline(logf)) {
	if (curlog == L_START && curprog == P_TAPER) {
	    amfree(ck_label);
	    ck_datestamp = NULL;
	    if(parse_taper_datestamp_log(curstr, &ck_datestamp,
                                         &ck_label) == 0) {
		g_printf(_("strange log line in %s \"start taper %s\"\n"),
                         logfile, curstr);
                continue;
	    }
            if (datestamp != NULL) {
                if (!g_str_equal(datestamp, ck_datestamp)) {
                    g_printf(_("Log file %s stamped %s, expecting %s!\n"),
                             logfile, ck_datestamp, datestamp);
		    amfree(ck_label);
                    break;
                }
            }

            right_label = volume_matches(label, ck_label, ck_datestamp);
	    if (right_label && ck_label) {
		g_hash_table_insert(valid_label, g_strdup(ck_label),
				    GINT_TO_POINTER(1));
	    }
	    if (label && datestamp && right_label) {
		found_something = TRUE;
	    }
            amfree(current_label);
            current_label = ck_label;
	    ck_label = NULL;
            if (datestamp == NULL) {
                datestamp = g_strdup(ck_datestamp);
            }
	    filenum = (off_t)0;
	}
	if (!datestamp)
	    continue;
	if (right_label &&
	    (curlog == L_SUCCESS ||
	     curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) &&
	    curprog == P_TAPER) {
	    filenum++;
	} else if (right_label && curlog == L_PARTIAL && curprog == P_TAPER &&
		   taper_part == 0) {
	    filenum++;
	}
	partnum = -1;
	totalparts = -1;
	if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS ||
	    curlog == L_DONE    || curlog == L_FAIL ||
	    curlog == L_CHUNK   || curlog == L_PART || curlog == L_PARTIAL ||
	    curlog == L_PARTPARTIAL ) {
	    s = curstr;
	    ch = *s++;

	    skip_whitespace(s, ch);
	    if(ch == '\0') {
		g_printf(_("strange log line in %s \"%s\"\n"),
		    logfile, curstr);
		continue;
	    }

	    if (curlog == L_PART || curlog == L_PARTPARTIAL) {
		char *part_label;
		char *qpart_label = s - 1;
		taper_part++;
		skip_quoted_string(s, ch);
		s[-1] = '\0';

		part_label = unquote_string(qpart_label);
		if (!g_hash_table_lookup(valid_label, part_label)) {
		    amfree(part_label);
		    continue;
		}
		amfree(current_label);
		current_label = part_label;

		skip_whitespace(s, ch);
		if(ch == '\0') {
		    g_printf("strange log line in %s \"%s\"\n",
			   logfile, curstr);
		    continue;
		}

		number = s - 1;
		skip_non_whitespace(s, ch);
		s[-1] = '\0';
		fileno = atoi(number);
		filenum = fileno;
		if (filenum == 0)
		    continue;

		skip_whitespace(s, ch);
		if(ch == '\0') {
		    g_printf("strange log line in %s \"%s\"\n",
			   logfile, curstr);
		    continue;
		}
	    } else {
		taper_part = 0;
	    }

	    host = s - 1;
	    skip_non_whitespace(s, ch);
	    host_undo = s - 1;
	    *host_undo = '\0';

	    skip_whitespace(s, ch);
	    if(ch == '\0') {
		g_printf(_("strange log line in %s \"%s\"\n"),
		    logfile, curstr);
		continue;
	    }
	    qdisk = s - 1;
	    skip_quoted_string(s, ch);
	    disk_undo = s - 1;
	    *disk_undo = '\0';
	    disk = unquote_string(qdisk);

	    skip_whitespace(s, ch);
	    if(ch == '\0') {
		g_printf(_("strange log line in %s \"%s\"\n"),
                         logfile, curstr);
		amfree(disk);
		continue;
	    }
	    date = s - 1;
	    skip_non_whitespace(s, ch);
	    date_undo = s - 1;
	    *date_undo = '\0';

	    if(strlen(date) < 3) { /* old log didn't have datestamp */
		level = atoi(date);
		date = datestamp;
		partnum = 1;
		totalparts = 1;
	    } else {
		if (curprog == P_TAPER &&
			(curlog == L_CHUNK || curlog == L_PART ||
			 curlog == L_PARTPARTIAL || curlog == L_PARTIAL ||
			 curlog == L_DONE)) {
		    char *s1, ch1;
		    skip_whitespace(s, ch);
		    number = s - 1;
		    skip_non_whitespace(s, ch);
		    s1 = &s[-1];
		    ch1 = *s1;
		    skip_whitespace(s, ch);
		    if (*(s-1) != '[') {
			*s1 = ch1;
			sscanf(number, "%d/%d", &partnum, &totalparts);
			if (partnum > maxparts)
			    maxparts = partnum;
			if (totalparts > maxparts)
			    maxparts = totalparts;
		    } else { /* nparts is not in all PARTIAL lines */
			partnum = 1;
			totalparts = 1;
			s = number + 1;
		    }
		} else {
		    skip_whitespace(s, ch);
		}
		if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
		    g_printf(_("Fstrange log line in %s \"%s\"\n"),
		    logfile, s-1);
		    amfree(disk);
		    continue;
		}
		skip_integer(s, ch);
	    }

	    skip_whitespace(s, ch);
	    if(ch == '\0') {
		g_printf(_("strange log line in %s \"%s\"\n"),
		    logfile, curstr);
		amfree(disk);
		continue;
	    }
	    rest = s - 1;
	    skip_non_whitespace(s, ch);
	    rest_undo = s - 1;
	    *rest_undo = '\0';
	    if (g_str_equal(rest, "[sec")) {
		skip_whitespace(s, ch);
		if(ch == '\0') {
		    g_printf(_("strange log line in %s \"%s\"\n"),
			     logfile, curstr);
		    amfree(disk);
		    continue;
		}
		sec = atof(s - 1);
		skip_non_whitespace(s, ch);
		skip_whitespace(s, ch);
		rest = s - 1;
		skip_non_whitespace(s, ch);
		rest_undo = s - 1;
		*rest_undo = '\0';
		if (!g_str_equal(rest, "kb") &&
		    !g_str_equal(rest, "bytes")) {
		    g_printf(_("Bstrange log line in %s \"%s\"\n"),
			     logfile, curstr);
		    amfree(disk);
		    continue;
		}

		skip_whitespace(s, ch);
		if (ch == '\0') {
		     g_printf(_("strange log line in %s \"%s\"\n"),
			      logfile, curstr);
		     amfree(disk);
		     continue;
		}
		if (g_str_equal(rest, "kb")) {
		    kb = atof(s - 1);
		    bytes = 0;
		} else {
		    bytes = atof(s - 1);
		    kb = bytes / 1024;
		}
		skip_non_whitespace(s, ch);
		skip_whitespace(s, ch);
		rest = s - 1;
		skip_non_whitespace(s, ch);
		rest_undo = s - 1;
		*rest_undo = '\0';
		if (!g_str_equal(rest, "kps")) {
		    g_printf(_("Cstrange log line in %s \"%s\"\n"),
			     logfile, curstr);
		    amfree(disk);
		    continue;
		}

		skip_whitespace(s, ch);
		if (ch == '\0') {
		    g_printf(_("strange log line in %s \"%s\"\n"),
			     logfile, curstr);
		    amfree(disk);
		    continue;
		}
		/* kps = atof(s - 1); */
		skip_non_whitespace(s, ch);
		skip_whitespace(s, ch);
		rest = s - 1;
		skip_non_whitespace(s, ch);
		rest_undo = s - 1;
		*rest_undo = '\0';
		if (!g_str_equal(rest, "orig-kb")) {
		    orig_kb = 0;
		} else {

		    skip_whitespace(s, ch);
		    if(ch == '\0') {
			g_printf(_("strange log line in %s \"%s\"\n"),
				 logfile, curstr);
			amfree(disk);
			continue;
		    }
		    orig_kb = atof(s - 1);
		}
	    } else {
		sec = 0;
		kb = 0;
		bytes = 0;
		orig_kb = 0;
		*rest_undo = ' ';
	    }

	    if (g_str_has_prefix(rest, "error")) rest += 6;
	    if (g_str_has_prefix(rest, "config")) rest += 7;

	    dp = lookup_disk(host,disk);
	    if ( dp == NULL ) {
		if (dynamic_disklist == NULL) {
		    amfree(disk);
		    continue;
		}
		dp = add_disk(dynamic_disklist, host, disk);
		enqueue_disk(dynamic_disklist, dp);
	    }
            if (find_match(host, disk)) {
		if(curprog == P_TAPER) {
		    char *key = g_strdup_printf(
					"HOST:%s DISK:%s: DATE:%s LEVEL:%d",
					host, disk, date, level);
		    find_result_t *new_output_find = g_new0(find_result_t, 1);
		    part_find = g_hash_table_lookup(part_by_dle, key);
		    maxparts = partnum;
		    if (maxparts < totalparts)
			maxparts = totalparts;
		    for (a_part_find = part_find;
			 a_part_find;
			 a_part_find = a_part_find->next) {
			if (maxparts < a_part_find->partnum)
			    maxparts = a_part_find->partnum;
			if (maxparts < a_part_find->totalparts)
			    maxparts = a_part_find->totalparts;
		    }
		    new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date);
		    new_output_find->write_timestamp = g_string_chunk_insert_const(string_chunk, datestamp);
		    new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host);
		    new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk);
		    new_output_find->level=level;
		    new_output_find->partnum = partnum;
		    new_output_find->totalparts = totalparts;
		    new_output_find->label=g_string_chunk_insert_const(string_chunk, current_label);
		    new_output_find->status=NULL;
		    new_output_find->dump_status=NULL;
		    new_output_find->message="";
		    new_output_find->filenum=filenum;
		    new_output_find->sec=sec;
		    new_output_find->kb=kb;
		    new_output_find->bytes=bytes;
		    new_output_find->orig_kb=orig_kb;
		    new_output_find->next=NULL;
		    if (curlog == L_SUCCESS) {
			new_output_find->status = "OK";
			new_output_find->dump_status = "OK";
			new_output_find->next = *output_find;
			new_output_find->partnum = 1; /* L_SUCCESS is pre-splitting */
			*output_find = new_output_find;
                        found_something = TRUE;
		    } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE ||
			       curlog == L_PARTIAL      || curlog == L_FAIL) {
			/* result line */
			if (curlog == L_PARTIAL || curlog == L_FAIL) {
			    /* set dump_status of each part */
			    for (a_part_find = part_find;
				 a_part_find;
				 a_part_find = a_part_find->next) {
				if (curlog == L_PARTIAL)
				    a_part_find->dump_status = "PARTIAL";
				else {
				    a_part_find->dump_status = "FAIL";
				    a_part_find->message = g_string_chunk_insert_const(string_chunk, rest);
				}
			    }
			} else {
			    if (maxparts > -1) { /* format with part */
				/* must check if all part are there */
				int num_part = maxparts;
				for (a_part_find = part_find;
				     a_part_find;
				     a_part_find = a_part_find->next) {
				    if (a_part_find->partnum == num_part &&
					g_str_equal(a_part_find->status, "OK"))
					num_part--;
			        }
				/* set dump_status of each part */
				for (a_part_find = part_find;
				     a_part_find;
				     a_part_find = a_part_find->next) {
				    if (num_part == 0) {
					a_part_find->dump_status = "OK";
				    } else {
					a_part_find->dump_status = "FAIL";
					a_part_find->message =
						g_string_chunk_insert_const(string_chunk, "Missing part");
				    }
				}
			    }
			}
			if (curlog == L_DONE) {
			    for (a_part_find = part_find;
				 a_part_find;
			         a_part_find = a_part_find->next) {
				if (a_part_find->totalparts == -1) {
				    a_part_find->totalparts = maxparts;
				}
				if (a_part_find->orig_kb == 0) {
				    a_part_find->orig_kb = orig_kb;
				}
			    }
			}
			if (part_find) { /* find last element */
			    for (a_part_find = part_find;
				 a_part_find->next != NULL;
				 a_part_find=a_part_find->next) {
			    }
			    /* merge part_find to *output_find */
			    a_part_find->next = *output_find;
			    *output_find = part_find;
			    part_find = NULL;
			    maxparts = -1;
                            found_something = TRUE;
			    g_hash_table_remove(part_by_dle, key);
			}
			free_find_result(&new_output_find);
		    } else { /* part line */
			if (curlog == L_PART || curlog == L_CHUNK) {
			    new_output_find->status = "OK";
			    new_output_find->dump_status = "OK";
			} else { /* PARTPARTIAL */
			    new_output_find->status = "PARTIAL";
			    new_output_find->dump_status = "PARTIAL";
			}
			/* Add to part_find list */
			if (part_find) {
			    new_output_find->next = part_find;
			    part_find = new_output_find;
			} else {
			    new_output_find->next = NULL;
			    part_find = new_output_find;
			}
			g_hash_table_insert(part_by_dle, g_strdup(key),
					    part_find);
			found_something = TRUE;
		    }
		    amfree(key);
		}
		else if(curlog == L_FAIL) {
		    char *status_failed;
		    /* print other failures too -- this is a hack to ensure that failures which
		     * did not make it to tape are also listed in the output of 'amadmin x find';
		     * users that do not want this information (e.g., Amanda::DB::Catalog) should
		     * filter dumps with a NULL label. */
		    find_result_t *new_output_find = g_new0(find_result_t, 1);
		    new_output_find->next = *output_find;
		    new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date);
		    new_output_find->write_timestamp = g_strdup("00000000000000"); /* dump was not written.. */
		    new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host);
		    new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk);
		    new_output_find->level=level;
		    new_output_find->label=NULL;
		    new_output_find->partnum=partnum;
		    new_output_find->totalparts=totalparts;
		    new_output_find->filenum=0;
		    new_output_find->sec=sec;
		    new_output_find->kb=kb;
		    new_output_find->bytes=bytes;
		    new_output_find->orig_kb=orig_kb;
		    status_failed = g_strjoin(NULL, 
			 "FAILED (",
			 program_str[(int)curprog],
			 ") ",
			 rest,
			 NULL);
		    new_output_find->status = g_string_chunk_insert_const(string_chunk, status_failed);
		    amfree(status_failed);
		    new_output_find->dump_status="";
		    new_output_find->message="";
		    *output_find=new_output_find;
                    found_something = TRUE;
		    maxparts = -1;
		}
	    }
	    amfree(disk);
	}
    }

    g_hash_table_destroy(valid_label);
    afclose(logf);
    amfree(datestamp);
    amfree(current_label);
    amfree(disk);

    return found_something;
}
示例#2
0
文件: amtrmidx.c 项目: neepher/amanda
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;
}
示例#3
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);
}