📄 amindexd.c
字号:
/* * 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: amindexd.c,v 1.106 2006/07/25 18:27:57 martinea Exp $ * * This is the server daemon part of the index client/server system. * It is assumed that this is launched from inetd instead of being * started as a daemon because it is not often used *//*** Notes:** - this server will do very little until it knows what Amanda config it** is to use. Setting the config has the side effect of changing to the** index directory.** - XXX - I'm pretty sure the config directory name should have '/'s stripped** from it. It is given to us by an unknown person via the network.*/#include "amanda.h"#include "conffile.h"#include "diskfile.h"#include "arglist.h"#include "clock.h"#include "version.h"#include "amindex.h"#include "disk_history.h"#include "list_dir.h"#include "logfile.h"#include "token.h"#include "find.h"#include "tapefile.h"#include "util.h"#include "amandad.h"#include "pipespawn.h"#include "sockaddr-util.h"#include <grp.h>#define amindexd_debug(i,x) do { \ if ((i) <= debug_amindexd) { \ dbprintf(x); \ } \} while (0)typedef struct REMOVE_ITEM{ char *filename; struct REMOVE_ITEM *next;} REMOVE_ITEM;/* state */static int from_amandad;static char local_hostname[MAX_HOSTNAME_LENGTH+1]; /* me! */static char *dump_hostname = NULL; /* machine we are restoring */static char *disk_name; /* disk we are restoring */char *qdisk_name = NULL; /* disk we are restoring */static char *target_date = NULL;static disklist_t disk_list; /* all disks in cur config */static find_result_t *output_find = NULL;static g_option_t *g_options = NULL;static int amindexd_debug = 0;static REMOVE_ITEM *uncompress_remove = NULL; /* uncompressed files to remove */static am_feature_t *our_features = NULL;static am_feature_t *their_features = NULL;static REMOVE_ITEM *remove_files(REMOVE_ITEM *);static char *uncompress_file(char *, char **);static int process_ls_dump(char *, DUMP_ITEM *, int, char **);static size_t reply_buffer_size = 1;static char *reply_buffer = NULL;static char *amandad_auth = NULL;static FILE *cmdin;static FILE *cmdout;static void reply(int, char *, ...) G_GNUC_PRINTF(2, 3);static void lreply(int, char *, ...) G_GNUC_PRINTF(2, 3);static void fast_lreply(int, char *, ...) G_GNUC_PRINTF(2, 3);static am_host_t *is_dump_host_valid(char *);static int is_disk_valid(char *);static int check_and_load_config(char *);static int build_disk_table(void);static int disk_history_list(void);static int is_dir_valid_opaque(char *);static int opaque_ls(char *, int);static void opaque_ls_one (DIR_ITEM *dir_item, am_feature_e marshall_feature, int recursive);static int tapedev_is(void);static int are_dumps_compressed(void);static char *amindexd_nicedate (char *datestamp);static int cmp_date (const char *date1, const char *date2);static char *clean_backslash(char *line);static char *get_index_name(char *dump_hostname, char *hostname, char *diskname, char *timestamps, int level);static int get_index_dir(char *dump_hostname, char *hostname, char *diskname);int main(int, char **);static REMOVE_ITEM *remove_files( REMOVE_ITEM *remove){ REMOVE_ITEM *prev; while(remove) { dbprintf(_("removing index file: %s\n"), remove->filename); unlink(remove->filename); amfree(remove->filename); prev = remove; remove = remove->next; amfree(prev); } return remove;}static char *uncompress_file( char * filename_gz, char ** emsg){ char *cmd = NULL; char *filename = NULL; struct stat stat_filename; int result; size_t len; int pipe_from_gzip; int pipe_to_sort; int indexfd; int nullfd; int debugfd; char line[STR_SIZE]; FILE *pipe_stream; pid_t pid_gzip; pid_t pid_sort; amwait_t wait_status; filename = stralloc(filename_gz); len = strlen(filename); if(len > 3 && strcmp(&(filename[len-3]),".gz")==0) { filename[len-3]='\0'; } else if(len > 2 && strcmp(&(filename[len-2]),".Z")==0) { filename[len-2]='\0'; } /* uncompress the file */ result=stat(filename,&stat_filename); if(result==-1 && errno==ENOENT) { /* file does not exist */ struct stat statbuf; REMOVE_ITEM *remove_file; /* * Check that compressed file exists manually. */ if (stat(filename_gz, &statbuf) < 0) { *emsg = newvstrallocf(*emsg, _("Compressed file '%s' is inaccessable: %s"), filename_gz, strerror(errno)); dbprintf("%s\n",*emsg); amfree(filename); return NULL; }#ifdef UNCOMPRESS_OPT# define PARAM_UNCOMPRESS_OPT UNCOMPRESS_OPT#else# define PARAM_UNCOMPRESS_OPT skip_argument#endif nullfd = open("/dev/null", O_RDONLY); indexfd = open(filename,O_WRONLY|O_CREAT, 0600); if (indexfd == -1) { *emsg = newvstrallocf(*emsg, _("Can't open '%s' for writting: %s"), filename, strerror(errno)); dbprintf("%s\n",*emsg); amfree(filename); return NULL; } /* just use our stderr directly for the pipe's stderr; in * main() we send stderr to the debug file, or /dev/null * if debugging is disabled */ debugfd = STDERR_FILENO; /* start the uncompress process */ putenv(stralloc("LC_ALL=C")); pid_gzip = pipespawn(UNCOMPRESS_PATH, STDOUT_PIPE, &nullfd, &pipe_from_gzip, &debugfd, UNCOMPRESS_PATH, PARAM_UNCOMPRESS_OPT, filename_gz, NULL); aclose(nullfd); pipe_stream = fdopen(pipe_from_gzip,"r"); if(pipe_stream == NULL) { *emsg = newvstrallocf(*emsg, _("Can't fdopen pipe from gzip: %s"), strerror(errno)); dbprintf("%s\n",*emsg); amfree(filename); return NULL; } /* start the sort process */ putenv(stralloc("LC_ALL=C")); pid_sort = pipespawn(SORT_PATH, STDIN_PIPE, &pipe_to_sort, &indexfd, &debugfd, SORT_PATH, NULL); aclose(indexfd); /* send all ouput from uncompress process to sort process */ /* clean the data with clean_backslash */ while (fgets(line, STR_SIZE, pipe_stream) != NULL) { if (line[0] != '\0') { if (index(line,'/')) { clean_backslash(line); fullwrite(pipe_to_sort,line,strlen(line)); } } } fclose(pipe_stream); aclose(pipe_to_sort); if (waitpid(pid_gzip, &wait_status, 0) < 0) { if (!WIFEXITED(wait_status)) { dbprintf(_("Uncompress exited with signal %d"), WTERMSIG(wait_status)); } else if (WEXITSTATUS(wait_status) != 0) { dbprintf(_("Uncompress exited with status %d"), WEXITSTATUS(wait_status)); } else { dbprintf(_("Uncompres returned negative value: %s"), strerror(errno)); } } if (waitpid(pid_sort, &wait_status, 0) < 0) { if (!WIFEXITED(wait_status)) { dbprintf(_("Sort exited with signal %d"), WTERMSIG(wait_status)); } else if (WEXITSTATUS(wait_status) != 0) { dbprintf(_("Sort exited with status %d"), WEXITSTATUS(wait_status)); } else { dbprintf(_("Sort returned negative value: %s"), strerror(errno)); } } /* add at beginning */ remove_file = (REMOVE_ITEM *)alloc(SIZEOF(REMOVE_ITEM)); remove_file->filename = stralloc(filename); remove_file->next = uncompress_remove; uncompress_remove = remove_file; } else if(!S_ISREG((stat_filename.st_mode))) { amfree(*emsg); *emsg = vstrallocf(_("\"%s\" is not a regular file"), filename); errno = -1; amfree(filename); amfree(cmd); return NULL; } amfree(cmd); return filename;}/* find all matching entries in a dump listing *//* return -1 if error */static intprocess_ls_dump( char * dir, DUMP_ITEM * dump_item, int recursive, char ** emsg){ char line[STR_SIZE]; char *old_line = NULL; char *filename = NULL; char *filename_gz; char *dir_slash = NULL; FILE *fp; char *s; int ch; size_t len_dir_slash; if (strcmp(dir, "/") == 0) { dir_slash = stralloc(dir); } else { dir_slash = stralloc2(dir, "/"); } filename_gz = get_index_name(dump_hostname, dump_item->hostname, disk_name, dump_item->date, dump_item->level); if (filename_gz == NULL) { *emsg = stralloc(_("index file not found")); amfree(filename_gz); return -1; } if((filename = uncompress_file(filename_gz, emsg)) == NULL) { amfree(filename_gz); amfree(dir_slash); return -1; } amfree(filename_gz); if((fp = fopen(filename,"r"))==0) { amfree(*emsg); *emsg = vstrallocf("%s", strerror(errno)); amfree(dir_slash); return -1; } len_dir_slash=strlen(dir_slash); while (fgets(line, STR_SIZE, fp) != NULL) { if (line[0] != '\0') { if(line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; if(strncmp(dir_slash, line, len_dir_slash) == 0) { if(!recursive) { s = line + len_dir_slash; ch = *s++; while(ch && ch != '/') ch = *s++;/* find end of the file name */ if(ch == '/') { ch = *s++; } s[-1] = '\0'; } if(old_line == NULL || strcmp(line, old_line) != 0) { add_dir_list_item(dump_item, line); amfree(old_line); old_line = stralloc(line); } } } } afclose(fp); /*@i@*/ amfree(old_line); amfree(filename); amfree(dir_slash); return 0;}/* send a 1 line reply to the client */printf_arglist_function1(static void reply, int, n, char *, fmt){ va_list args; int len; if(!reply_buffer) reply_buffer = alloc(reply_buffer_size); while(1) { arglist_start(args, fmt); len = g_vsnprintf(reply_buffer, reply_buffer_size, fmt, args); arglist_end(args); if (len > -1 && (size_t)len < reply_buffer_size-1) break; reply_buffer_size *= 2; amfree(reply_buffer); reply_buffer = alloc(reply_buffer_size); } if (g_fprintf(cmdout,"%03d %s\r\n", n, reply_buffer) < 0) { dbprintf(_("! error %d (%s) in printf\n"), errno, strerror(errno)); uncompress_remove = remove_files(uncompress_remove); exit(1); } if (fflush(cmdout) != 0) { dbprintf(_("! error %d (%s) in fflush\n"), errno, strerror(errno)); uncompress_remove = remove_files(uncompress_remove); exit(1); } dbprintf(_("< %03d %s\n"), n, reply_buffer);}/* send one line of a multi-line response */printf_arglist_function1(static void lreply, int, n, char *, fmt){ va_list args; int len; if(!reply_buffer) reply_buffer = alloc(reply_buffer_size); while(1) { arglist_start(args, fmt); len = g_vsnprintf(reply_buffer, reply_buffer_size, fmt, args); arglist_end(args); if (len > -1 && (size_t)len < reply_buffer_size-1) break; reply_buffer_size *= 2; amfree(reply_buffer); reply_buffer = alloc(reply_buffer_size); } if (g_fprintf(cmdout,"%03d-%s\r\n", n, reply_buffer) < 0) { dbprintf(_("! error %d (%s) in printf\n"), errno, strerror(errno)); uncompress_remove = remove_files(uncompress_remove); exit(1); } if (fflush(cmdout) != 0) { dbprintf(_("! error %d (%s) in fflush\n"), errno, strerror(errno));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -