📄 extract_list.c
字号:
/* * 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 + -