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

📄 extract_list.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998, 2000 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: extract_list.c,v 1.6 2006/08/24 01:57:15 paddy_s Exp $ * * implements the "extract" command in amrecover */#include "amanda.h"#include "conffile.h"#include "version.h"#include "amrecover.h"#include "fileheader.h"#include "dgram.h"#include "stream.h"#include "tapelist.h"#ifdef SAMBA_CLIENT#include "findpass.h"#endif#include "util.h"typedef struct EXTRACT_LIST_ITEM {    char *path;    struct EXTRACT_LIST_ITEM *next;}EXTRACT_LIST_ITEM;typedef struct EXTRACT_LIST {    char *date;			/* date tape created */    int  level;			/* level of dump */    char *tape;			/* tape label */    off_t fileno;		/* fileno on tape */    EXTRACT_LIST_ITEM *files;	/* files to get off tape */    struct EXTRACT_LIST *next;}EXTRACT_LIST;#define SKIP_TAPE 2#define RETRY_TAPE 3char *dump_device_name = NULL;extern char *localhost;/* global pid storage for interrupt handler */pid_t extract_restore_child_pid = -1;static EXTRACT_LIST *extract_list = NULL;static int tape_control_sock = -1;static int tape_data_sock = -1;#ifdef SAMBA_CLIENTunsigned short samba_extract_method = SAMBA_TAR;#endif /* SAMBA_CLIENT */#define READ_TIMEOUT	240*60EXTRACT_LIST *first_tape_list(void);EXTRACT_LIST *next_tape_list(EXTRACT_LIST *list);int is_extract_list_nonempty(void);int length_of_tape_list(EXTRACT_LIST *tape_list);void add_file(char *path, char *regex);void add_glob(char *glob);void add_regex(char *regex);void clear_extract_list(void);void clean_tape_list(EXTRACT_LIST *tape_list);void clean_extract_list(void);void delete_file(char *path, char *regex);void delete_glob(char *glob);void delete_regex(char *regex);void delete_tape_list(EXTRACT_LIST *tape_list);void display_extract_list(char *file);void extract_files(void);void read_file_header(char *buffer,			dumpfile_t *file,			size_t buflen,			int tapedev);void writer_intermediary(int ctl_fd, int data_fd, EXTRACT_LIST *elist);void writer_intermediary(int ctl_fd, int data_fd, EXTRACT_LIST *elist);static int add_extract_item(DIR_ITEM *ditem);static int delete_extract_item(DIR_ITEM *ditem);static int extract_files_setup(char *label, off_t fsf);static int okay_to_continue(int allow_tape,			int allow_skip,			int allow_retry);static int okay_to_continue(int, int,  int);static ssize_t read_buffer(int datafd,			char *buffer,			size_t buflen,			long timeout_s);static void clear_tape_list(EXTRACT_LIST *tape_list);static void extract_files_child(int in_fd, EXTRACT_LIST *elist);static void send_to_tape_server(int tss, char *cmd);/* * Function:  ssize_t read_buffer(datafd, buffer, buflen, timeout_s) * * Description: *	read data from input file desciptor waiting up to timeout_s *	seconds before returning data. * * Inputs: *	datafd    - File descriptor to read from. *	buffer    - Buffer to read into. *	buflen    - Maximum number of bytes to read into buffer. *	timeout_s - Seconds to wait before returning what was already read. * * Returns: *      >0	  - Number of data bytes in buffer. *       0	  - EOF *      -1        - errno == ETIMEDOUT if no data available in specified time. *                  errno == ENFILE if datafd is invalid. *                  otherwise errno is set by select or read.. */static ssize_tread_buffer(    int		datafd,    char *	buffer,    size_t	buflen,    long	timeout_s){    ssize_t size = 0;    fd_set readset;    struct timeval timeout;    char *dataptr;    ssize_t spaceleft;    int nfound;    if(datafd < 0 || datafd >= (int)FD_SETSIZE) {	errno = EMFILE;					/* out of range */	return -1;    }    dataptr = buffer;    spaceleft = (ssize_t)buflen;    do {        FD_ZERO(&readset);        FD_SET(datafd, &readset);        timeout.tv_sec = timeout_s;        timeout.tv_usec = 0;        nfound = select(datafd+1, &readset, NULL, NULL, &timeout);        if(nfound < 0 ) {            /* Select returned an error. */	    g_fprintf(stderr,_("select error: %s\n"), strerror(errno));            size = -1;	    break;        }	if (nfound == 0) {            /* Select timed out. */            if (timeout_s != 0)  {                /* Not polling: a real read timeout */                g_fprintf(stderr,_("timeout waiting for restore\n"));                g_fprintf(stderr,_("increase READ_TIMEOUT in recover-src/extract_list.c if your tape is slow\n"));            }            errno = ETIMEDOUT;            size = -1;	    break;        }	if(!FD_ISSET(datafd, &readset))	    continue;        /* Select says data is available, so read it.  */        size = read(datafd, dataptr, (size_t)spaceleft);        if (size < 0) {	    if ((errno == EINTR) || (errno == EAGAIN)) {		continue;	    }	    if (errno != EPIPE) {	        g_fprintf(stderr, _("read_buffer: read error - %s"),		    strerror(errno));	        break;	    }	    size = 0;	}        spaceleft -= size;        dataptr += size;    } while ((size > 0) && (spaceleft > 0));    return ((((ssize_t)buflen-spaceleft) > 0) ? ((ssize_t)buflen-spaceleft) : size);}EXTRACT_LIST *first_tape_list(void){    return extract_list;}EXTRACT_LIST *next_tape_list(    /*@keep@*/ EXTRACT_LIST *list){    if (list == NULL)	return NULL;    return list->next;}static voidclear_tape_list(    EXTRACT_LIST *	tape_list){    EXTRACT_LIST_ITEM *this, *next;        this = tape_list->files;    while (this != NULL)    {	next = this->next;        amfree(this->path);        amfree(this);	this = next;    }    tape_list->files = NULL;}/* remove a tape list from the extract list, clearing the tape list   beforehand if necessary */voiddelete_tape_list(    EXTRACT_LIST *	tape_list){    EXTRACT_LIST *this, *prev;    if (tape_list == NULL)        return;    /* is it first on the list? */    if (tape_list == extract_list)    {	extract_list = tape_list->next;	clear_tape_list(tape_list);        amfree(tape_list->date);        amfree(tape_list->tape);	amfree(tape_list);	return;    }    /* so not first on list - find it and delete */    prev = extract_list;    this = extract_list->next;    while (this != NULL)    {	if (this == tape_list)	{	    prev->next = tape_list->next;	    clear_tape_list(tape_list);            amfree(tape_list->date);            amfree(tape_list->tape);	    amfree(tape_list);	    return;	}	prev = this;	this = this->next;    }    /*NOTREACHED*/}/* return the number of files on a tape's list */intlength_of_tape_list(    EXTRACT_LIST *	tape_list){    EXTRACT_LIST_ITEM *fn;    int n;    n = 0;    for (fn = tape_list->files; fn != NULL; fn = fn->next)	n++;    return n;}voidclear_extract_list(void){    while (extract_list != NULL)	delete_tape_list(extract_list);}voidclean_tape_list(    EXTRACT_LIST *tape_list){    EXTRACT_LIST_ITEM *fn1, *pfn1, *ofn1;    EXTRACT_LIST_ITEM *fn2, *pfn2, *ofn2;    int remove_fn1;    int remove_fn2;    pfn1 = NULL;    fn1 = tape_list->files;    while (fn1 != NULL) {	remove_fn1 = 0;	pfn2 = fn1;	fn2 = fn1->next;	while (fn2 != NULL && remove_fn1 == 0) {	    remove_fn2 = 0;	    if(strcmp(fn1->path, fn2->path) == 0) {		remove_fn2 = 1;	    } else if (strncmp(fn1->path, fn2->path, strlen(fn1->path)) == 0 &&		       ((strlen(fn2->path) > strlen(fn1->path) &&			 fn2->path[strlen(fn1->path)] == '/') ||		       (fn1->path[strlen(fn1->path)-1] == '/'))) {		remove_fn2 = 1;	    } else if (strncmp(fn2->path, fn1->path, strlen(fn2->path)) == 0 &&		       ((strlen(fn1->path) > strlen(fn2->path) &&			 fn1->path[strlen(fn2->path)] == '/')  ||		       (fn2->path[strlen(fn2->path)-1] == '/'))) {		remove_fn1 = 1;		break;	    }	    if (remove_fn2) {		dbprintf(_("removing path %s, it is included in %s\n"),			  fn2->path, fn1->path);		ofn2 = fn2;		fn2 = fn2->next;		amfree(ofn2->path);		amfree(ofn2);		pfn2->next = fn2;	    } else if (remove_fn1 == 0) {		pfn2 = fn2;		fn2 = fn2->next;	    }	}	if(remove_fn1 != 0) {	    /* fn2->path is always valid */	    /*@i@*/ dbprintf(_("removing path %s, it is included in %s\n"),	    /*@i@*/	      fn1->path, fn2->path);	    ofn1 = fn1;	    fn1 = fn1->next;	    amfree(ofn1->path);	    if(pfn1 == NULL) {		amfree(tape_list->files);		tape_list->files = fn1;	    } else {		amfree(pfn1->next);		pfn1->next = fn1;	    }	} else {	    pfn1 = fn1;	    fn1 = fn1->next;	}    }}voidclean_extract_list(void){    EXTRACT_LIST *this;    for (this = extract_list; this != NULL; this = this->next)	clean_tape_list(this);}/* returns -1 if error *//* returns  0 on succes *//* returns  1 if already added */static intadd_extract_item(    DIR_ITEM *	ditem){    EXTRACT_LIST *this, *this1;    EXTRACT_LIST_ITEM *that, *curr;    char *ditem_path = NULL;    ditem_path = stralloc(ditem->path);    clean_pathname(ditem_path);    for (this = extract_list; this != NULL; this = this->next)    {	/* see if this is the list for the tape */		if (this->level == ditem->level && strcmp(this->tape, ditem->tape) == 0)	{	    /* yes, so add to list */	    curr=this->files;	    while(curr!=NULL)	    {		if (strcmp(curr->path, ditem_path) == 0) {		    amfree(ditem_path);		    return 1;		}		curr=curr->next;	    }	    that = (EXTRACT_LIST_ITEM *)alloc(sizeof(EXTRACT_LIST_ITEM));            that->path = stralloc(ditem_path);	    that->next = this->files;	    this->files = that;		/* add at front since easiest */	    amfree(ditem_path);	    return 0;	}    }    /* so this is the first time we have seen this tape */    this = (EXTRACT_LIST *)alloc(sizeof(EXTRACT_LIST));    this->tape = stralloc(ditem->tape);    this->level = ditem->level;    this->fileno = ditem->fileno;    this->date = stralloc(ditem->date);    that = (EXTRACT_LIST_ITEM *)alloc(sizeof(EXTRACT_LIST_ITEM));    that->path = stralloc(ditem_path);    that->next = NULL;    this->files = that;    /* add this in date increasing order          */    /* because restore must be done in this order */    /* add at begining */    if(extract_list==NULL || strcmp(this->date,extract_list->date) < 0)     {	this->next = extract_list;	extract_list = this;	amfree(ditem_path);	return 0;    }    for (this1 = extract_list; this1->next != NULL; this1 = this1->next)    {	/* add in the middle */	if(strcmp(this->date,this1->next->date) < 0)	{	    this->next = this1->next;	    this1->next = this;	    amfree(ditem_path);	    return 0;	}    }    /* add at end */    this->next = NULL;    this1->next = this;    amfree(ditem_path);    return 0;}/* returns -1 if error *//* returns  0 on deletion *//* returns  1 if not there */static intdelete_extract_item(    DIR_ITEM *	ditem){    EXTRACT_LIST *this;    EXTRACT_LIST_ITEM *that, *prev;    char *ditem_path = NULL;    ditem_path = stralloc(ditem->path);    clean_pathname(ditem_path);    for (this = extract_list; this != NULL; this = this->next)    {	/* see if this is the list for the tape */		if (this->level == ditem->level && strcmp(this->tape, ditem->tape) == 0)	{	    /* yes, so find file on list */	    that = this->files;	    if (strcmp(that->path, ditem_path) == 0)	    {		/* first on list */		this->files = that->next;                amfree(that->path);		amfree(that);		/* if list empty delete it */		if (this->files == NULL)		    delete_tape_list(this);		amfree(ditem_path);		return 0;	    }	    prev = that;	    that = that->next;	    while (that != NULL)	    {		if (strcmp(that->path, ditem_path) == 0)		{		    prev->next = that->next;                    amfree(that->path);		    amfree(that);		    amfree(ditem_path);		    return 0;		}		prev = that;		that = that->next;	    }	    amfree(ditem_path);	    return 1;	}    }    amfree(ditem_path);    return 1;}voidadd_glob(    char *	glob){    char *regex;    char *regex_path;    char *s;    char *uqglob = unquote_string(glob);    regex = glob_to_regex(uqglob);    dbprintf(_("add_glob (%s) -> %s\n"), uqglob, regex);    if ((s = validate_regexp(regex)) != NULL) {	g_printf(_("%s is not a valid shell wildcard pattern: "), glob);	puts(s);    } else {        /*         * glob_to_regex() anchors the beginning of the pattern with ^,         * but we will be tacking it onto the end of the current directory         * in add_file, so strip that off.  Also, it anchors the end with         * $, but we need to match an optional trailing /, so tack that on         * the end.         */        regex_path = stralloc(regex + 1);        regex_path[strlen(regex_path) - 1] = '\0';        strappend(regex_path, "[/]*$");        add_file(uqglob, regex_path);        amfree(regex_path);    }    amfree(regex);    amfree(uqglob);}voidadd_regex(    char *	regex){

⌨️ 快捷键说明

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