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

📄 restore.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
	    cur_find_res->next = sorted_files;	    sorted_files = cur_find_res;	}	sort_find_result("hkdlp", &sorted_files);	/* now we have an in-order list of the files we need to concatenate */	cur_find_res = sorted_files;	for(cur_find_res=sorted_files;		cur_find_res;		cur_find_res=cur_find_res->next){	    dumpfile_t *cur_file = NULL;	    cur_out = (open_output_t*)cur_find_res->user_ptr;	    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;	    }	    if(cur_file->type == F_SPLIT_DUMPFILE) {		/* is it a continuation of one we've been writing? */		if(main_file && cur_file->partnum > lastpartnum &&			headers_equal(cur_file, main_file, 1)){		    char *cur_filename;		    char *main_filename;		    /* effectively changing filehandles */		    aclose(cur_out->outfd);		    cur_out->outfd = outfd;		    cur_filename  = make_filename(cur_file);		    main_filename = make_filename(main_file);		    g_fprintf(stderr, _("Merging %s with %s\n"),		            cur_filename, main_filename);		    append_file_to_fd(cur_filename, outfd);		    if(unlink(cur_filename) < 0){			g_fprintf(stderr, _("Failed to unlink %s: %s\n"),			             cur_filename, strerror(errno));		    }		    amfree(cur_filename);		    amfree(main_filename);		}		/* or a new file? */		else {		    if(outfd >= 0) aclose(outfd);		    amfree(main_file);		    main_file = alloc(SIZEOF(dumpfile_t));		    memcpy(main_file, cur_file, SIZEOF(dumpfile_t));		    outfd = cur_out->outfd;		    if(outfd < 0) {			char *cur_filename = make_filename(cur_file);			open(cur_filename, O_RDWR|O_APPEND);			if (outfd < 0) {			  error(_("Couldn't open %s for appending: %s"),			        cur_filename, strerror(errno));			  /*NOTREACHED*/			}			amfree(cur_filename);		    }		}		lastpartnum = cur_file->partnum;	    }	    else {		aclose(cur_out->outfd);	    }	}	if(outfd >= 0) {	    aclose(outfd);	}	amfree(main_file);	free_find_result(&sorted_files);    }    /*     * Now that the split dump closure is done, free up resources we don't     * need anymore.     */    for(cur_out=open_outputs; cur_out; cur_out=cur_out->next){	dumpfile_t *cur_file = NULL;	amfree(prev);	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;	}	if(!reassemble) {	    aclose(cur_out->outfd);	}	if(cur_out->comp_enc_pid > 0){	    waitpid(cur_out->comp_enc_pid, &compress_status, 0);	}	amfree(cur_out->file);	prev = cur_out;    }    open_outputs = NULL;}/* * Turn a fileheader into a string suited for use on the filesystem. */char *make_filename(    dumpfile_t *file){    char number[NUM_STR_SIZE];    char part[NUM_STR_SIZE];    char totalparts[NUM_STR_SIZE];    char *sfn = NULL;    char *fn = NULL;    char *pad = NULL;    size_t padlen = 0;    g_snprintf(number, SIZEOF(number), "%d", file->dumplevel);    g_snprintf(part, SIZEOF(part), "%d", file->partnum);    if(file->totalparts < 0) {	g_snprintf(totalparts, SIZEOF(totalparts), "UNKNOWN");    }    else {	g_snprintf(totalparts, SIZEOF(totalparts), "%d", file->totalparts);    }    padlen = strlen(totalparts) + 1 - strlen(part);    pad = alloc(padlen);    memset(pad, '0', padlen);    pad[padlen - 1] = '\0';    g_snprintf(part, SIZEOF(part), "%s%d", pad, file->partnum);    sfn = sanitise_filename(file->disk);    fn = vstralloc(file->name,		   ".",		   sfn, 		   ".",		   file->datestamp,		   ".",		   number,		   NULL);    if (file->partnum > 0) {	vstrextend(&fn, ".", part, NULL);    }    amfree(sfn);    amfree(pad);    return fn;}/* Returns 1 if the dump file matches the hostname and diskname * regular expressions given on the command line, 0 otherwise.  As a  * special case, empty regexs and NULLs are considered equivalent to  * ".*": they match everything. * * @param file: the file to examine * @param datestamp: the datestamp regex, or NULL for any * @param hostname: the hostname regex, or NULL for any * @param diskname: the diskname regex, or NULL for any * @param level: the level regex, or NULL for any * @returns: 1 if the dump file matches */static intdisk_match(    dumpfile_t *file,    char *	datestamp,    char *	hostname,    char *	diskname,    char *	level){    char level_str[NUM_STR_SIZE];    g_snprintf(level_str, SIZEOF(level_str), "%d", file->dumplevel);    if(file->type != F_DUMPFILE && file->type != F_SPLIT_DUMPFILE) return 0;    if((!hostname || *hostname == '\0' || match_host(hostname, file->name)) &&       (!diskname || *diskname == '\0' || match_disk(diskname, file->disk)) &&       (!datestamp || *datestamp == '\0' || match_datestamp(datestamp, file->datestamp)) &&       (!level || *level == '\0' || match_level(level, level_str)))	return 1;    else	return 0;}/* * Reads the first block of a holding disk file. */static gbooleanread_holding_disk_header(    dumpfile_t *       file,    int                        tapefd,    rst_flags_t *      flags){    ssize_t bytes_read;    char *buffer;    size_t blocksize;    if(flags->blocksize > 0)        blocksize = (size_t)flags->blocksize;    else        blocksize = DISK_BLOCK_BYTES;    buffer = alloc(blocksize);    bytes_read = fullread(tapefd, buffer, blocksize);    if(bytes_read < 0) {	g_fprintf(stderr, _("%s: error reading file header: %s\n"),		get_pname(), strerror(errno));	file->type = F_UNKNOWN;    } else if((size_t)bytes_read < DISK_BLOCK_BYTES) {	if(bytes_read == 0) {	    g_fprintf(stderr, _("%s: missing file header block\n"), get_pname());	} else {	    g_fprintf(stderr,		    plural(_("%s: short file header block: %zd byte"),	    		   _("%s: short file header block: %zd bytes\n"),			   bytes_read),		    get_pname(), (size_t)bytes_read);	}	file->type = F_UNKNOWN;    } else {        parse_file_header(buffer, file, (size_t)bytes_read);    }    amfree(buffer);    return (file->type != F_UNKNOWN &&            file->type != F_EMPTY &&            file->type != F_WEIRD);}/* * Restore the current file from tape.  Depending on the settings of * the command line flags, the file might need to be compressed or * uncompressed.  If so, a pipe through compress or uncompress is set * up.  The final output usually goes to a file named host.disk.date.lev, * but with the -p flag the output goes to stdout (and presumably is * piped to restore). *//* FIXME: Mondo function that needs refactoring. */void restore(RestoreSource * source,             rst_flags_t *	flags){    int dest = -1, out;    int file_is_compressed;    int is_continuation = 0;    int check_for_aborted = 0;    char *tmp_filename = NULL, *final_filename = NULL;    struct stat statinfo;    open_output_t *myout = NULL, *oldout = NULL;    dumplist_t *tempdump = NULL, *fileentry = NULL;    char *buffer;    int need_compress=0, need_uncompress=0, need_decrypt=0;    int stage=0;    struct pipeline {        int	pipe[2];    } pipes[3];    char * filename;    filename = make_filename(source->header);    memset(pipes, -1, SIZEOF(pipes));    if(already_have_dump(source->header)){	g_fprintf(stderr, _(" *** Duplicate file %s, one is probably an aborted write\n"), filename);	check_for_aborted = 1;    }    /* store a shorthand record of this dump */    tempdump = malloc(SIZEOF(dumplist_t));    tempdump->file = malloc(SIZEOF(dumpfile_t));    tempdump->next = NULL;    memcpy(tempdump->file, source->header, SIZEOF(dumpfile_t));    /*     * If we're appending chunked files to one another, and if this is a     * continuation of a file we just restored, and we've still got the     * output handle from that previous restore, we're golden.  Phew.     */    if(flags->inline_assemble && source->header->type == F_SPLIT_DUMPFILE){	myout = open_outputs;	while(myout != NULL){	    if(myout->file->type == F_SPLIT_DUMPFILE &&               headers_equal(source->header, myout->file, 1)){		if(source->header->partnum == myout->lastpartnum + 1){		    is_continuation = 1;		    break;		}	    }	    myout = myout->next;	}	if(myout != NULL) myout->lastpartnum = source->header->partnum;	else if(source->header->partnum != 1){	    g_fprintf(stderr, _("%s:      Chunk out of order, will save to disk and append to output.\n"), get_pname());	    flags->pipe_to_fd = -1;	    flags->compress = 0;	    flags->leave_comp = 1;	}	if(myout == NULL){	    myout = alloc(SIZEOF(open_output_t));	    memset(myout, 0, SIZEOF(open_output_t));	}    }    else{      myout = alloc(SIZEOF(open_output_t));      memset(myout, 0, SIZEOF(open_output_t));    }    if(is_continuation && flags->pipe_to_fd == -1){	char *filename;	filename = make_filename(myout->file);	g_fprintf(stderr, _("%s:      appending to %s\n"), get_pname(),		filename);	amfree(filename);    }    /* adjust compression flag */    file_is_compressed = source->header->compressed;    if(!flags->compress && file_is_compressed &&       !known_compress_type(source->header)) {	g_fprintf(stderr, 		_("%s: unknown compression suffix %s, can't uncompress\n"),		get_pname(), source->header->comp_suffix);	flags->compress = 1;    }    /* set up final destination file */    if(is_continuation && myout != NULL) {      out = myout->outfd;    } else {      if(flags->pipe_to_fd != -1) {  	  dest = flags->pipe_to_fd;      } else {  	  char *filename_ext = NULL;    	  if(flags->compress) {  	      filename_ext = file_is_compressed ? source->header->comp_suffix  	  				      : COMPRESS_SUFFIX;  	  } else if(flags->raw) {  	      filename_ext = ".RAW";  	  } else {  	      filename_ext = "";  	  }  	  filename_ext = stralloc2(filename, filename_ext);	  tmp_filename = stralloc(filename_ext); 	  if(flags->restore_dir != NULL) {	      char *tmpstr = vstralloc(flags->restore_dir, "/",	                               tmp_filename, NULL);	      amfree(tmp_filename);	      tmp_filename = tmpstr;	  } 	  final_filename = tmp_filename; 	  tmp_filename = vstralloc(final_filename, ".tmp", NULL);  	  if((dest = open(tmp_filename, (O_CREAT | O_RDWR | O_TRUNC),			  CREAT_MODE)) < 0) {  	      error(_("could not create output file %s: %s"),	      	    tmp_filename, strerror(errno));              /*NOTREACHED*/	  }  	  amfree(filename_ext);      }        out = dest;    }    /*     * If -r or -h, write the header before compress or uncompress pipe.     * Only write DISK_BLOCK_BYTES, regardless of how much was read.     * This makes the output look like a holding disk image, and also     * makes it easier to remove the header (e.g. in amrecover) since     * it has a fixed size.     */    if(flags->raw || (flags->headers && !is_continuation)) {	ssize_t w;	dumpfile_t tmp_hdr;	if(flags->compress && !file_is_compressed) {	    source->header->compressed = 1;	    g_snprintf(source->header->uncompress_cmd,                     SIZEOF(source->header->uncompress_cmd),		        " %s %s |", UNCOMPRESS_PATH,#ifdef UNCOMPRESS_OPT		        UNCOMPRESS_OPT#else		        ""#endif		        );	    strncpy(source->header->comp_suffix,		    COMPRESS_SUFFIX,		    SIZEOF(source->header->comp_suffix)-1);	    source->header->comp_suffix[SIZEOF(source->header->comp_suffix)-1]                = '\0';	}	memcpy(&tmp_hdr, source->header, SIZEOF(dumpfile_t));	/* remove CONT_FILENAME from header */	memset(source->header->cont_filename, '\0',               SIZEOF(source->header->cont_filename));	source->header->blocksize = DISK_BLOCK_BYTES;	/*	 * Dumb down split file headers as well, so that older versions of	 * things like amrecover won't gag on them.	 */	if(source->header->type == F_SPLIT_DUMPFILE && flags->mask_splits){	    source->header->type = F_DUMPFILE;	}	buffer = alloc(DISK_BLOCK_BYTES);	buffer = build_header(source->header, DISK_BLOCK_BYTES);	if((w = fullwrite(out, buffer,                          DISK_BLOCK_BYTES)) != DISK_BLOCK_BYTES) {	    if(w < 0) {		error(_("write error: %s"), strerror(errno));		/*NOTREACHED*/	    } else {

⌨️ 快捷键说明

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