Пример #1
0
/*
 * Convert a previously str-ified and escaped list of tapes back into a
 * tapelist structure.
 */
tapelist_t *
unmarshal_tapelist_str(
    char *	tapelist_str,
    int		with_storage)
{
    char *temp_storage, *temp_label, *temp_filenum;
    int l_idx, n_idx;
    size_t input_length;
    tapelist_t *tapelist = NULL;

    if(!tapelist_str) return(NULL);

    input_length = strlen(tapelist_str);

    temp_label = g_malloc(input_length+1);
    temp_storage = g_malloc(input_length+1);
    temp_filenum = g_malloc(input_length+1);

    do {
	/* first, read the storage part */
	if (with_storage) {
	    memset(temp_storage, '\0', input_length+1);
            l_idx = 0;
	    while(*tapelist_str != ':' && *tapelist_str != '\0'){
		if(*tapelist_str == '\\')
		    tapelist_str++; /* skip escapes */
		temp_storage[l_idx] = *tapelist_str;
		if(*tapelist_str == '\0')
		    break; /* bad format, should kvetch */
		tapelist_str++;
		l_idx++;
	    }
	    if(*tapelist_str != '\0')
		tapelist_str++;
	}

	/* then, read the label part */
	memset(temp_label, '\0', input_length+1);
        l_idx = 0;
	while(*tapelist_str != ':' && *tapelist_str != '\0'){
	    if(*tapelist_str == '\\')
		tapelist_str++; /* skip escapes */
	    temp_label[l_idx] = *tapelist_str;
	    if(*tapelist_str == '\0')
		break; /* bad format, should kvetch */
	    tapelist_str++;
	    l_idx++;
	}
	if(*tapelist_str != '\0')
	    tapelist_str++;
	tapelist = append_to_tapelist(tapelist, temp_storage, temp_label, (off_t)-1, -1, 0);

	/* now read the list of file numbers */
	while(*tapelist_str != ';' && *tapelist_str != '\0'){
	    off_t filenum;

	    memset(temp_filenum, '\0', input_length+1);
	    n_idx = 0;
	    while(*tapelist_str != ';' && *tapelist_str != ',' &&
		    *tapelist_str != '\0'){
		temp_filenum[n_idx] = *tapelist_str; 
		tapelist_str++;
		n_idx++;
	    }
	    filenum = OFF_T_ATOI(temp_filenum);

	    tapelist = append_to_tapelist(tapelist, temp_storage, temp_label, filenum, -1, 0);
	    if(*tapelist_str != '\0' && *tapelist_str != ';')
		tapelist_str++;
	}
	if(*tapelist_str != '\0')
	    tapelist_str++;

    } while(*tapelist_str != '\0');

    amfree(temp_label);
    amfree(temp_storage);
    amfree(temp_filenum);

    return(tapelist);
}
Пример #2
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);
}