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

📄 restore.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission.  U.M. makes no representations about the * suitability of this software for any purpose.  It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team.  Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: restore.c 6512 2007-05-24 17:00:24Z ian $ * * retrieves files from an amanda tape */#include "amanda.h"#include "util.h"#include "restore.h"#include "find.h"#include "changer.h"#include "logfile.h"#include "fileheader.h"#include "arglist.h"#include "cmdline.h"#include <signal.h>#include <timestamp.h>#include <device.h>#include <queueing.h>#include <glib.h>typedef enum {    LOAD_NEXT = 1,     /* An unknown new slot has been loaded. */    LOAD_CHANGER = -2, /* The requested slot has been loaded. */    LOAD_STOP = -1,    /* The search is complete. */} LoadStatus;typedef enum {    RESTORE_STATUS_NEXT_FILE,    RESTORE_STATUS_NEXT_TAPE,    RESTORE_STATUS_STOP} RestoreFileStatus;int file_number;/* stuff we're stuck having global */static int backwards;static int exitassemble = 0;char *rst_conf_logdir = NULL;char *rst_conf_logfile = NULL;static char *curslot = NULL;typedef struct open_output_s {    struct open_output_s *next;    dumpfile_t *file;    int lastpartnum;    pid_t comp_enc_pid;    int outfd;} open_output_t;typedef struct dumplist_s {    struct dumplist_s *next;    dumpfile_t *file;} dumplist_t;struct seentapes_s {    struct seentapes_s *next;    char *slotstr;    char *label;    dumplist_t *files;};static open_output_t *open_outputs = NULL;static dumplist_t *alldumps_list = NULL;/* local functions */static void append_file_to_fd(char *filename, int fd);static int headers_equal(dumpfile_t *file1, dumpfile_t *file2, int ignore_partnums);static int already_have_dump(dumpfile_t *file);static void handle_sigint(int sig);static int scan_init(void *ud, int rc, int ns, int bk, int s);static Device * conditional_device_open(char * tapedev, FILE * orompt_out,                                        rst_flags_t * flags,                                        am_feature_t * their_features,                                        tapelist_t * desired_tape);int loadlabel_slot(void *ud, int rc, char *slotstr, char *device);char *label_of_current_slot(char *cur_tapedev, FILE *prompt_out,			    int *tapefd, dumpfile_t *file, rst_flags_t *flags,			    am_feature_t *their_features,			    ssize_t *read_result, tapelist_t *desired_tape);LoadStatus load_next_tape(char **cur_tapedev, FILE *prompt_out, int backwards,		   rst_flags_t *flags, am_feature_t *their_features,		   tapelist_t *desired_tape);LoadStatus load_manual_tape(char **cur_tapedev, FILE *prompt_out, FILE *prompt_in,		     rst_flags_t *flags, am_feature_t *their_features,		     tapelist_t *desired_tape);/* * We might want to flush any open dumps and unmerged splits before exiting * on SIGINT, so do so. */static voidhandle_sigint(    int		sig){    (void)sig;	/* Quiet unused parameter warning */    flush_open_outputs(exitassemble, NULL);    if(rst_conf_logfile) unlink(rst_conf_logfile);    exit(0);}intlock_logfile(void){    rst_conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));    rst_conf_logfile = vstralloc(rst_conf_logdir, "/log", NULL);    if (access(rst_conf_logfile, F_OK) == 0) {	dbprintf(_("%s exists: amdump or amflush is already running, "		  "or you must run amcleanup\n"), rst_conf_logfile);	return 0;    }    log_add(L_INFO, get_pname());    return 1;}/* * Return 1 if the two fileheaders match in name, disk, type, split chunk part * number, and datestamp, and 0 if not.  The part number can be optionally * ignored. */intheaders_equal(    dumpfile_t *file1,    dumpfile_t *file2,    int		ignore_partnums){    if(!file1 || !file2) return(0);        if(file1->dumplevel == file2->dumplevel &&	   file1->type == file2->type &&	   !strcmp(file1->datestamp, file2->datestamp) &&	   !strcmp(file1->name, file2->name) &&	   !strcmp(file1->disk, file2->disk) &&	   (ignore_partnums || file1->partnum == file2->partnum)){	return(1);    }    return(0);}/* * See whether we're already pulled an exact copy of the given file (chunk * number and all).  Returns 0 if not, 1 if so. */intalready_have_dump(    dumpfile_t *file){    dumplist_t *fileentry = NULL;    if(!file) return(0);    for(fileentry=alldumps_list;fileentry;fileentry=fileentry->next){	if(headers_equal(file, fileentry->file, 0)) return(1);    }    return(0);}/* * Open the named file and append its contents to the (hopefully open) file * descriptor supplies. */static voidappend_file_to_fd(    char *	filename,    int		write_fd){    int read_fd;    read_fd = robust_open(filename, O_RDONLY, 0);    if (read_fd < 0) {	error(_("can't open %s: %s"), filename, strerror(errno));	/*NOTREACHED*/    }    if (!do_consumer_producer_queue(fd_read_producer, GINT_TO_POINTER(read_fd),                                    fd_write_consumer,                                    GINT_TO_POINTER(write_fd))) {        error("Error copying data from file \"%s\" to fd %d.\n",              filename, write_fd);        g_assert_not_reached();    }    aclose(read_fd);}/* A user_init function for changer_find(). See changer.h for   documentation. */static int scan_init(G_GNUC_UNUSED void *	ud, int	rc, G_GNUC_UNUSED int ns,          int bk, G_GNUC_UNUSED int s) {    if(rc) {        error(_("could not get changer info: %s"), changer_resultstr);	/*NOTREACHED*/    }    backwards = bk;    return 0;}typedef struct {    char ** cur_tapedev;    char * searchlabel;} loadlabel_data;/* DANGER WILL ROBINSON: This function references globals:          char * curslot; */intloadlabel_slot(void *	datap,               int	rc,               char *	slotstr,               char *	device_name){    loadlabel_data * data = (loadlabel_data*)datap;    Device * device;    ReadLabelStatusFlags label_status;    g_return_val_if_fail(rc > 1 || device_name != NULL, 0);    g_return_val_if_fail(slotstr != NULL, 0);    amfree(curslot);    if(rc > 1) {        error(_("could not load slot %s: %s"), slotstr, changer_resultstr);        g_assert_not_reached();    }    if(rc == 1) {        g_fprintf(stderr, _("%s: slot %s: %s\n"),                get_pname(), slotstr, changer_resultstr);        return 0;    }         device = device_open(device_name);    if (device == NULL) {        g_fprintf(stderr, "%s: slot %s: Could not open device.\n",                get_pname(), slotstr);        return 0;    }    device_set_startup_properties_from_config(device);    label_status = device_read_label(device);    if (label_status != READ_LABEL_STATUS_SUCCESS) {        char * errstr =            g_english_strjoinv_and_free                (g_flags_nick_to_strv(label_status,                                      READ_LABEL_STATUS_FLAGS_TYPE), "or");        g_fprintf(stderr, "%s: slot %s: Error reading tape label:\n"                "%s: slot %s: %s\n",                get_pname(), slotstr, get_pname(), slotstr, errstr);        g_object_unref(device);        return 0;    }    g_assert(device->volume_label != NULL);    if (device->volume_label == NULL) {        g_fprintf(stderr, "%s: slot %s: Could not read tape label.\n",                get_pname(), slotstr);        g_object_unref(device);        return 0;    }    if (!device_start(device, ACCESS_READ, NULL, NULL)) {        g_fprintf(stderr, "%s: slot %s: Could not open device for reading.\n",                get_pname(), slotstr);        return 0;    }    g_fprintf(stderr, "%s: slot %s: time %-14s label %s",            get_pname(), slotstr, device->volume_time, device->volume_label);    if(strcmp(device->volume_label, data->searchlabel) != 0) {        g_fprintf(stderr, " (wrong tape)\n");        g_object_unref(device);        return 0;    }    g_fprintf(stderr, " (exact label match)\n");    g_object_unref(device);    curslot = newstralloc(curslot, slotstr);    amfree(*(data->cur_tapedev));    *(data->cur_tapedev) = stralloc(device_name);    return 1;}/* non-local functions follow *//* * Check whether we've read all of the preceding parts of a given split dump, * generally used to see if we're done and can close the thing. */inthave_all_parts (    dumpfile_t *file,    int		upto){    int c;    int *foundparts = NULL;    dumplist_t *fileentry = NULL;    if(!file || file->partnum < 1) return(0);    if(upto < 1) upto = file->totalparts;    foundparts = alloc(SIZEOF(*foundparts) * upto);     for(c = 0 ; c< upto; c++) foundparts[c] = 0;        for(fileentry=alldumps_list;fileentry; fileentry=fileentry->next){	dumpfile_t *cur_file = fileentry->file;	if(headers_equal(file, cur_file, 1)){	    if(cur_file->partnum > upto){		amfree(foundparts);		return(0);	    }	    foundparts[cur_file->partnum - 1] = 1;	}    }    for(c = 0 ; c< upto; c++){	if(!foundparts[c]){	    amfree(foundparts);	    return(0);	}    }        amfree(foundparts);    return(1);}/* * Free up the open filehandles and memory we were using to track in-progress * dumpfiles (generally for split ones we're putting back together).  If * applicable, also find the ones that are continuations of one another and * string them together.  If given an optional file header argument, flush * only that dump and do not flush/free any others. */voidflush_open_outputs(    int		reassemble,    dumpfile_t *only_file){    open_output_t *cur_out = NULL, *prev = NULL;    find_result_t *sorted_files = NULL;    amwait_t compress_status;    if(!only_file){	g_fprintf(stderr, "\n");    }    /*     * Deal with any split dumps we've been working on, appending pieces     * that haven't yet been appended and closing filehandles we've been     * holding onto.     */    if(reassemble){	find_result_t *cur_find_res = NULL;	int outfd = -1, lastpartnum = -1;	dumpfile_t *main_file = NULL;	cur_out = open_outputs;		/* stick the dumpfile_t's into a list find_result_t's so that we can	   abuse existing sort functionality */	for(cur_out=open_outputs; cur_out; cur_out=cur_out->next){	    find_result_t *cur_find_res = NULL;	    dumpfile_t *cur_file = cur_out->file;	    /* if we requested a particular file, do only that one */	    if(only_file && !headers_equal(cur_file, only_file, 1)){		continue;	    }	    cur_find_res = alloc(SIZEOF(find_result_t));	    memset(cur_find_res, '\0', SIZEOF(find_result_t));	    cur_find_res->timestamp = stralloc(cur_file->datestamp);	    cur_find_res->hostname = stralloc(cur_file->name);	    cur_find_res->diskname = stralloc(cur_file->disk);	    cur_find_res->level = cur_file->dumplevel;	    if(cur_file->partnum < 1) cur_find_res->partnum = stralloc("--");	    else{		char part_str[NUM_STR_SIZE];		g_snprintf(part_str, SIZEOF(part_str), "%d", cur_file->partnum);		cur_find_res->partnum = stralloc(part_str);	    }	    cur_find_res->user_ptr = (void*)cur_out;

⌨️ 快捷键说明

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