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

📄 restore.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
	    changer_find(&data, scan_init, loadlabel_slot,			 desired_tape->label);            return LOAD_CHANGER;	} else {	    amfree(curslot);	    changer_loadslot("next", &curslot,			     cur_tapedev);            return LOAD_NEXT;	}    } else {	assert(!flags->amidxtaped);	amfree(curslot);	changer_loadslot("next", &curslot, cur_tapedev);        return LOAD_NEXT;    }    g_assert_not_reached();}/* will never return LOAD_CHANGER. */LoadStatusload_manual_tape(    char         **tapedev_ptr,    FILE          *prompt_out,    FILE          *prompt_in,    rst_flags_t   *flags,    am_feature_t  *their_features,    tapelist_t    *desired_tape){    char *input = NULL;    if (flags->amidxtaped) {	if (their_features &&	    am_has_feature(their_features,			   fe_amrecover_FEEDME)) {	    g_fprintf(prompt_out, "FEEDME %s\r\n",		    desired_tape->label);	    fflush(prompt_out);	    input = agets(prompt_in);/* Strips \n but not \r */	    if(!input) {		error(_("Connection lost with amrecover"));		/*NOTREACHED*/	    } else if (strcmp("OK\r", input) == 0) {	    } else if (strncmp("TAPE ", input, 5) == 0) {		amfree(*tapedev_ptr);		*tapedev_ptr = alloc(1025);		if (sscanf(input, "TAPE %1024s\r", *tapedev_ptr) != 1) {		    error(_("Got bad response from amrecover: %s"), input);		    /*NOTREACHED*/		}	    } else {		send_message(prompt_out, flags, their_features,			     _("Got bad response from amrecover: %s"), input);		error(_("Got bad response from amrecover: %s"), input);		/*NOTREACHED*/	    }	} else {	    send_message(prompt_out, flags, their_features,			 _("Client doesn't support fe_amrecover_FEEDME"));	    error(_("Client doesn't support fe_amrecover_FEEDME"));	    /*NOTREACHED*/	}    }    else {	if (desired_tape) {	    g_fprintf(prompt_out,		    _("Insert tape labeled %s in device %s \n"		    "and press enter, ^D to finish reading tapes\n"),		    desired_tape->label, *tapedev_ptr);	} else {	    g_fprintf(prompt_out,_("Insert a tape to search and press "		    "enter, ^D to finish reading tapes\n"));	}	fflush(prompt_out);	if((input = agets(prompt_in)) == NULL)            return LOAD_STOP;    }    amfree(input);    return LOAD_NEXT;}/* Search a seen-tapes list for a particular name, to see if we've already * processed this tape. Returns TRUE if this label has already been seen. */static gboolean check_volume_seen(seentapes_t * list, char * label) {    seentapes_t * cur_tape;    for (cur_tape = list; cur_tape != NULL; cur_tape = cur_tape->next) {        if (strcmp(cur_tape->label, label) == 0) {            return TRUE;        }    }    return FALSE;}/* Add a volume to the seen tapes list. */static void record_seen_volume(seentapes_t ** list, char * label,                               char * slotstr) {    seentapes_t * new_entry;    if (list == NULL)        return;    new_entry = malloc(sizeof(seentapes_t));    new_entry->label = stralloc(label);    if (slotstr == NULL) {        new_entry->slotstr = NULL;    } else {        new_entry->slotstr = stralloc(slotstr);    }    new_entry->files = NULL;    new_entry->next = *list;    *list = new_entry;}/* Record a specific dump on a volume. */static void record_seen_dump(seentapes_t * volume, dumpfile_t * header) {    dumplist_t * this_dump;    if (volume == NULL)        return;        this_dump = malloc(sizeof(*this_dump));    this_dump->file = g_memdup(header, sizeof(*header));    this_dump->next = NULL;    if (volume->files) {        dumplist_t * tmp_dump = volume->files;        while (tmp_dump->next != NULL) {            tmp_dump = tmp_dump->next;        }        tmp_dump->next = this_dump;    } else {        volume->files = this_dump;    }}static void print_tape_inventory(FILE * logstream, seentapes_t * tape_seen,                                 char * timestamp, char * label,                                 int tape_count) {    char * logline;    dumplist_t * fileentry;    logline = log_genstring(L_START, "taper",                            "datestamp %s label %s tape %d",                            timestamp, label, tape_count);    fputs(logline, logstream);    amfree(logline);    for(fileentry=tape_seen->files; fileentry; fileentry=fileentry->next){        switch (fileentry->file->type) {        case F_DUMPFILE:            logline = log_genstring(L_SUCCESS, "taper",                                    "%s %s %s %d [faked log entry]",                                    fileentry->file->name,                                    fileentry->file->disk,                                    fileentry->file->datestamp,                                    fileentry->file->dumplevel);            break;        case F_SPLIT_DUMPFILE:            logline = log_genstring(L_CHUNK, "taper",                                     "%s %s %s %d %d [faked log entry]",                                    fileentry->file->name,                                    fileentry->file->disk,                                    fileentry->file->datestamp,                                    fileentry->file->partnum,                                    fileentry->file->dumplevel);            break;        default:            break;        }        if(logline != NULL){            fputs(logline, logstream);            amfree(logline);            fflush(logstream);        }    }}/* Check if the given header matches the given dumpspecs. Returns   TRUE if dumpspecs is NULL and false if the header is NULL. Returns   true if the header matches the  match list. */static gboolean run_dumpspecs(GSList * dumpspecs,                               dumpfile_t * header) {    dumpspec_t *ds;    if (dumpspecs == NULL)        return TRUE;    if (header == NULL)        return FALSE;    while (dumpspecs) {	ds = (dumpspec_t *)dumpspecs->data;        if (disk_match(header, ds->datestamp, ds->host,                       ds->disk, ds->level) != 0) {            return TRUE;        }	dumpspecs = dumpspecs->next;    }    return FALSE;}/* A wrapper around restore() above. This function does some extra   checking to seek to the file in question and ensure that we really,   really want to use it.   The next_file argument provides instruction on what to do if the   requested file does not exist on the volume: If next_file is NULL   then if the requested file is missing the function will return   RESTORE_STATUS_NEXT_FILE. If next_file is not NULL then the first   extant file whose number is equal to or greater than file_num will   be attempted. *next_file will be filled in with the number of the   file following the one that was attempted. */static RestoreFileStatustry_restore_single_file(Device * device, int file_num, int* next_file,                        FILE * prompt_out,                        rst_flags_t * flags,                        am_feature_t * their_features,                        dumpfile_t * first_restored_file,                        GSList * dumpspecs,                        seentapes_t * tape_seen) {    RestoreSource source;    source.u.device = device;    source.restore_mode = DEVICE_MODE;    source.header = device_seek_file(device, file_num);    if (source.header == NULL) {        /* This definitely indicates an error. */        send_message(prompt_out, flags, their_features,                     "Could not seek device %s to file %d.",                     device->device_name, file_num);        return RESTORE_STATUS_NEXT_TAPE;    } else if (source.header->type == F_TAPEEND) {        amfree(source.header);        return RESTORE_STATUS_NEXT_TAPE;    } else if (device->file != file_num) {        if (next_file == NULL) {            send_message(prompt_out, flags, their_features,                         "Requested file %d does not exist.",                         file_num);            return RESTORE_STATUS_NEXT_FILE;        } else {            send_message(prompt_out, flags, their_features,                         "Skipped from file %d to file %d.",                          file_num, device->file);            file_num = device->file;        }    }    if (next_file != NULL) {        *next_file = file_num + 1;    }        g_return_val_if_fail(source.header->type == F_DUMPFILE ||                         source.header->type == F_CONT_DUMPFILE ||                         source.header->type == F_SPLIT_DUMPFILE,                         RESTORE_STATUS_NEXT_FILE);        if (!run_dumpspecs(dumpspecs, source.header)) {	if(!flags->amidxtaped) {            g_fprintf(prompt_out, "%s: %d: skipping ",		    get_pname(), file_num);            print_header(prompt_out, source.header);	}        return RESTORE_STATUS_NEXT_FILE;    }    if (first_restored_file != NULL &&        first_restored_file->type != F_UNKNOWN &&        !headers_equal(first_restored_file, source.header, 1) &&        (flags->pipe_to_fd == fileno(stdout))) {        return RESTORE_STATUS_STOP;    }    if (!flags->amidxtaped) {	g_fprintf(stderr, "%s: %d: restoring ",		get_pname(), file_num);	print_header(stderr, source.header);    }    record_seen_dump(tape_seen, source.header);    restore(&source, flags);    if (first_restored_file) {	memcpy(first_restored_file, source.header, sizeof(dumpfile_t));    }    return RESTORE_STATUS_NEXT_FILE;}/* This function handles processing of a particular tape or holding   disk file. It returns TRUE if it is useful to load another tape.*/gbooleansearch_a_tape(Device      * device,              FILE         *prompt_out, /* Where to send any prompts */              rst_flags_t  *flags,      /* Restore options. */              am_feature_t *their_features,               tapelist_t   *desired_tape, /* A list of desired tape files */              GSList *dumpspecs, /* What disks to restore. */              seentapes_t **tape_seen,  /* Where to record data on                                           this tape. */              /* May be NULL. If zeroed, will be filled in with the                 first restored file. If already filled in, then we                 may only restore other files from the same dump. */              dumpfile_t   * first_restored_file,              int           tape_count,              FILE * logstream) {    seentapes_t * tape_seen_head = NULL;    RestoreSource source;    off_t       filenum;    int         tapefile_idx = -1;    int         i;    RestoreFileStatus restore_status = RESTORE_STATUS_NEXT_TAPE;    source.restore_mode = DEVICE_MODE;    source.u.device = device;    filenum = (off_t)0;    if(desired_tape && desired_tape->numfiles > 0)	tapefile_idx = 0;    if (desired_tape) {	dbprintf(_("search_a_tape: desired_tape=%p label=%s\n"),		  desired_tape, desired_tape->label);	dbprintf(_("tape:   numfiles = %d\n"), desired_tape->numfiles);	for (i=0; i < desired_tape->numfiles; i++) {	    dbprintf(_("tape:   files[%d] = %lld\n"),		      i, (long long)desired_tape->files[i]);	}    } else {	dbprintf(_("search_a_tape: no desired_tape\n"));    }    dbprintf(_("current tapefile_idx = %d\n"), tapefile_idx);    if (tape_seen) {        if (check_volume_seen(*tape_seen, device->volume_label)) {            send_message(prompt_out, flags, their_features,                         "Skipping repeat tape %s in slot %s",                         device->volume_label, curslot);            return TRUE;        }        record_seen_volume(tape_seen, device->volume_label, curslot);        tape_seen_head = *tape_seen;    }	    if (desired_tape && desired_tape->numfiles > 0) {        /* Iterate the tape list, handle each file in order. */        int file_index;        for (file_index = 0; file_index < desired_tape->numfiles;             file_index ++) {            int file_num = desired_tape->files[file_index];            restore_status = try_restore_single_file(device, file_num, NULL,                                                     prompt_out, flags,                                                     their_features,                                                     first_restored_file,                                                     NULL, tape_seen_head);            if (restore_status != RESTORE_STATUS_NEXT_FILE)                break;        }    } else if(flags->fsf && flags->amidxtaped) {        /* Restore a single file, then quit. */        restore_status =            try_restore_single_file(device, flags->fsf, NULL, prompt_out, flags,                                    their_features, first_restored_file,                                    dumpspecs, tape_seen_head);    } else {        /* Search the tape from beginning to end. */        int file_num;        if (flags->fsf > 0) {            file_num = flags->fsf;        } else {            file_num = 1;        }	if (!flags->amidxtaped) {            g_fprintf(prompt_out, "Restoring from tape %s starting with file %d.\n",		    device->volume_label, file_num);	    fflush(prompt_out);	}        for (;;) {            restore_status =                try_restore_single_file(device, file_num, &file_num,                                        prompt_out, flags,                                        their_features, first_restored_file,                                        dumpspecs, tape_seen_head);            if (restore_status != RESTORE_STATUS_NEXT_FILE)                break;        }    }        /* spit out our accumulated list of dumps, if we're inventorying */    if (logstream != NULL) {        print_tape_inventory(logstream, tape_seen_head, device->volume_time,                             device->volume_label, tape_count);    }    return (restore_status != RESTORE_STATUS_STOP);}static void free_seen_tapes(seentapes_t * seentapes) {    while (seentapes != NULL) {	seentapes_t *tape_seen = seentapes;	seentapes = seentapes->next;	while(tape_seen->files != NULL) {	    dumplist_t *temp_dump = tape_seen->files;	    tape_seen->files = temp_dump->next;	    amfree(temp_dump->file);	    amfree(temp_dump);	}	amfree(tape_seen->label);	amfree(tape_seen->slotstr);	amfree(tape_seen);	    }}/* Spit out a list of expected tapes, so people with manual changers know

⌨️ 快捷键说明

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