📄 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.117 2006/08/24 01:57:15 paddy_s Exp $ * * implements the "extract" command in amrecover */#include "amanda.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"#include "conffile.h"#include "protocol.h"#include "event.h"#include "security.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 3static struct { const char *name; security_stream_t *fd;} amidxtaped_streams[] = {#define CTLFD 0 { "CTL", NULL },#define DATAFD 1 { "DATA", NULL },};#define NSTREAMS (int)(sizeof(amidxtaped_streams) / sizeof(amidxtaped_streams[0]))static void amidxtaped_response(void *, pkt_t *, security_handle_t *);static void stop_amidxtaped(void);char *amidxtaped_client_get_security_conf(char *, void *);static char *dump_device_name = NULL;static char *errstr;static char *amidxtaped_line = NULL;extern char *localhost;/* global pid storage for interrupt handler */pid_t extract_restore_child_pid = -1;static EXTRACT_LIST *extract_list = NULL;static const security_driver_t *amidxtaped_secdrv;#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);static int is_empty_dir(char *fname);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 check_file_overwrite(char *filename);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);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 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(security_stream_t *stream, char *cmd);int writer_intermediary(EXTRACT_LIST *elist);int get_amidxtaped_line(void);static void read_amidxtaped_data(void *, void *, ssize_t);/* * 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; SELECT_ARG_TYPE 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);}int add_to_unlink_list(char *path);int do_unlink_list(void);void free_unlink_list(void);typedef struct s_unlink_list { char *path; struct s_unlink_list *next;} t_unlink_list;t_unlink_list *unlink_list = NULL;intadd_to_unlink_list( char *path){ t_unlink_list *ul; if (!unlink_list) { unlink_list = alloc(SIZEOF(*unlink_list)); unlink_list->path = stralloc(path); unlink_list->next = NULL; } else { for (ul = unlink_list; ul != NULL; ul = ul->next) { if (strcmp(ul->path, path) == 0) return 0; } ul = alloc(SIZEOF(*ul)); ul->path = stralloc(path); ul->next = unlink_list; unlink_list = ul; } return 1;}intdo_unlink_list(void){ t_unlink_list *ul; int ret = 1; for (ul = unlink_list; ul != NULL; ul = ul->next) { if (unlink(ul->path) < 0) { g_fprintf(stderr,_("Can't unlink %s: %s\n"), ul->path, strerror(errno)); ret = 0; } } return ret;}voidfree_unlink_list(void){ t_unlink_list *ul, *ul1; for (ul = unlink_list; ul != NULL; ul = ul1) { amfree(ul->path); ul1 = ul->next; amfree(ul); } unlink_list = NULL;}voidcheck_file_overwrite( char *dir){ EXTRACT_LIST *this; EXTRACT_LIST_ITEM *fn; struct stat stat_buf; char *filename; char *path, *s; for (this = extract_list; this != NULL; this = this->next) { for (fn = this->files; fn != NULL ; fn = fn->next) { /* Check path component of fn->path */ path = stralloc2(dir, fn->path); if (path[strlen(path)-1] == '/') { path[strlen(path)-1] = '\0'; } s = path + strlen(dir) + 1; while((s = strchr(s, '/'))) { *s = '\0'; if (lstat(path, &stat_buf) == 0) { if(!S_ISDIR(stat_buf.st_mode)) { if (add_to_unlink_list(path)) { g_printf(_("WARNING: %s is not a directory, " "it will be deleted.\n"), path); } } } else if (errno != ENOENT) { g_printf(_("Can't stat %s: %s\n"), path, strerror(errno));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -