📄 dumper.c
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1999 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: dumper.c,v 1.190 2006/08/30 19:53:57 martinea Exp $ * * requests remote amandad processes to dump filesystems */#include "amanda.h"#include "amindex.h"#include "arglist.h"#include "clock.h"#include "conffile.h"#include "event.h"#include "logfile.h"#include "packet.h"#include "protocol.h"#include "security.h"#include "stream.h"#include "token.h"#include "version.h"#include "fileheader.h"#include "amfeatures.h"#include "server_util.h"#include "util.h"#include "timestamp.h"#define dumper_debug(i,x) do { \ if ((i) <= debug_dumper) { \ dbprintf(x); \ } \} while (0)#ifndef SEEK_SET#define SEEK_SET 0#endif#ifndef SEEK_CUR#define SEEK_CUR 1#endif#define CONNECT_TIMEOUT 5*60#define STARTUP_TIMEOUT 60struct databuf { int fd; /* file to flush to */ char *buf; char *datain; /* data buffer markers */ char *dataout; char *datalimit; pid_t compresspid; /* valid if fd is pipe to compress */ pid_t encryptpid; /* valid if fd is pipe to encrypt */};static char *handle = NULL;static char *errstr = NULL;static off_t dumpbytes;static off_t dumpsize, headersize, origsize;static comp_t srvcompress = COMP_NONE;char *srvcompprog = NULL;char *clntcompprog = NULL;static encrypt_t srvencrypt = ENCRYPT_NONE;char *srv_encrypt = NULL;char *clnt_encrypt = NULL;char *srv_decrypt_opt = NULL;char *clnt_decrypt_opt = NULL;static kencrypt_type dumper_kencrypt;static FILE *errf = NULL;static char *hostname = NULL;am_feature_t *their_features = NULL;static char *diskname = NULL;static char *qdiskname = NULL;static char *device = NULL;static char *options = NULL;static char *progname = NULL;static char *amandad_path=NULL;static char *client_username=NULL;static char *ssh_keys=NULL;static int level;static char *dumpdate = NULL;static char *dumper_timestamp = NULL;static time_t conf_dtimeout;static int indexfderror;static int set_datafd;static dumpfile_t file;static struct { const char *name; security_stream_t *fd;} streams[] = {#define DATAFD 0 { "DATA", NULL },#define MESGFD 1 { "MESG", NULL },#define INDEXFD 2 { "INDEX", NULL },};#define NSTREAMS (int)(sizeof(streams) / sizeof(streams[0]))static am_feature_t *our_features = NULL;static char *our_feature_string = NULL;/* local functions */int main(int, char **);static int do_dump(struct databuf *);static void check_options(char *);static void finish_tapeheader(dumpfile_t *);static ssize_t write_tapeheader(int, dumpfile_t *);static void databuf_init(struct databuf *, int);static int databuf_write(struct databuf *, const void *, size_t);static int databuf_flush(struct databuf *);static void process_dumpeof(void);static void process_dumpline(const char *);static void add_msg_data(const char *, size_t);static void parse_info_line(char *);static void log_msgout(logtype_t);static char * dumper_get_security_conf (char *, void *);static int runcompress(int, pid_t *, comp_t);static int runencrypt(int, pid_t *, encrypt_t);static void sendbackup_response(void *, pkt_t *, security_handle_t *);static int startup_dump(const char *, const char *, const char *, int, const char *, const char *, const char *, const char *, const char *, const char *);static void stop_dump(void);static void read_indexfd(void *, void *, ssize_t);static void read_datafd(void *, void *, ssize_t);static void read_mesgfd(void *, void *, ssize_t);static void timeout(time_t);static void timeout_callback(void *);static voidcheck_options( char *options){ char *compmode = NULL; char *compend = NULL; char *encryptmode = NULL; char *encryptend = NULL; char *decryptmode = NULL; char *decryptend = NULL; /* parse the compression option */ if (strstr(options, "srvcomp-best;") != NULL) srvcompress = COMP_BEST; else if (strstr(options, "srvcomp-fast;") != NULL) srvcompress = COMP_FAST; else if ((compmode = strstr(options, "srvcomp-cust=")) != NULL) { compend = strchr(compmode, ';'); if (compend ) { srvcompress = COMP_SERVER_CUST; *compend = '\0'; srvcompprog = stralloc(compmode + strlen("srvcomp-cust=")); *compend = ';'; } } else if ((compmode = strstr(options, "comp-cust=")) != NULL) { compend = strchr(compmode, ';'); if (compend) { srvcompress = COMP_CUST; *compend = '\0'; clntcompprog = stralloc(compmode + strlen("comp-cust=")); *compend = ';'; } } else { srvcompress = COMP_NONE; } /* now parse the encryption option */ if ((encryptmode = strstr(options, "encrypt-serv-cust=")) != NULL) { encryptend = strchr(encryptmode, ';'); if (encryptend) { srvencrypt = ENCRYPT_SERV_CUST; *encryptend = '\0'; srv_encrypt = stralloc(encryptmode + strlen("encrypt-serv-cust=")); *encryptend = ';'; } } else if ((encryptmode = strstr(options, "encrypt-cust=")) != NULL) { encryptend = strchr(encryptmode, ';'); if (encryptend) { srvencrypt = ENCRYPT_CUST; *encryptend = '\0'; clnt_encrypt = stralloc(encryptmode + strlen("encrypt-cust=")); *encryptend = ';'; } } else { srvencrypt = ENCRYPT_NONE; } /* get the decryption option parameter */ if ((decryptmode = strstr(options, "server-decrypt-option=")) != NULL) { decryptend = strchr(decryptmode, ';'); if (decryptend) { *decryptend = '\0'; srv_decrypt_opt = stralloc(decryptmode + strlen("server-decrypt-option=")); *decryptend = ';'; } } else if ((decryptmode = strstr(options, "client-decrypt-option=")) != NULL) { decryptend = strchr(decryptmode, ';'); if (decryptend) { *decryptend = '\0'; clnt_decrypt_opt = stralloc(decryptmode + strlen("client-decrypt-option=")); *decryptend = ';'; } } if (strstr(options, "kencrypt;") != NULL) { dumper_kencrypt = KENCRYPT_WILL_DO; } else { dumper_kencrypt = KENCRYPT_NONE; }}intmain( int argc, char ** argv){ static struct databuf db; struct cmdargs cmdargs; cmd_t cmd; int outfd = -1; int rc; in_port_t taper_port; char *q = NULL; int a; int res; config_overwrites_t *cfg_ovr = NULL; char *cfg_opt = NULL; /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); /* drop root privileges */ if (!set_root_privs(0)) { error(_("dumper must be run setuid root")); } safe_fd(-1, 0); set_pname("dumper"); dbopen(DBG_SUBDIR_SERVER); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE); set_logerror(logerror); cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); if (argc > 1) cfg_opt = argv[1]; config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD | CONFIG_INIT_FATAL, cfg_opt); apply_config_overwrites(cfg_ovr); safe_cd(); /* do this *after* config_init() */ check_running_as(RUNNING_AS_DUMPUSER); dbrename(config_name, DBG_SUBDIR_SERVER); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); g_fprintf(stderr, _("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), argv[0], version()); fflush(stderr); /* now, make sure we are a valid user */ signal(SIGPIPE, SIG_IGN); conf_dtimeout = (time_t)getconf_int(CNF_DTIMEOUT); protocol_init(); do { cmd = getcmd(&cmdargs); switch(cmd) { case START: if(cmdargs.argc < 2) error(_("error [dumper START: not enough args: timestamp]")); dumper_timestamp = newstralloc(dumper_timestamp, cmdargs.argv[2]); break; case ABORT: break; case QUIT: break; case PORT_DUMP: /* * PORT-DUMP * handle * port * host * features * disk * device * level * dumpdate * progname * amandad_path * client_username * ssh_keys * options */ cmdargs.argc++; /* true count of args */ a = 2; if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: handle]")); /*NOTREACHED*/ } handle = newstralloc(handle, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: port]")); /*NOTREACHED*/ } taper_port = (in_port_t)atoi(cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: hostname]")); /*NOTREACHED*/ } hostname = newstralloc(hostname, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: features]")); /*NOTREACHED*/ } am_release_feature_set(their_features); their_features = am_string_to_feature(cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: diskname]")); /*NOTREACHED*/ } qdiskname = newstralloc(qdiskname, cmdargs.argv[a++]); if (diskname != NULL) amfree(diskname); diskname = unquote_string(qdiskname); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: device]")); /*NOTREACHED*/ } device = newstralloc(device, cmdargs.argv[a++]); if(strcmp(device,"NODEVICE") == 0) amfree(device); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: level]")); /*NOTREACHED*/ } level = atoi(cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: dumpdate]")); /*NOTREACHED*/ } dumpdate = newstralloc(dumpdate, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: program]")); /*NOTREACHED*/ } progname = newstralloc(progname, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: amandad_path]")); /*NOTREACHED*/ } amandad_path = newstralloc(amandad_path, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: client_username]")); } client_username = newstralloc(client_username, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: ssh_keys]")); } ssh_keys = newstralloc(ssh_keys, cmdargs.argv[a++]); if(a >= cmdargs.argc) { error(_("error [dumper PORT-DUMP: not enough args: options]")); } options = newstralloc(options, cmdargs.argv[a++]); if(a != cmdargs.argc) { error(_("error [dumper PORT-DUMP: too many args: %d != %d]"), cmdargs.argc, a); /*NOTREACHED*/ } /* Double-check that 'localhost' resolves properly */ if ((res = resolve_hostname("localhost", 0, NULL, NULL) != 0)) { errstr = newvstrallocf(errstr, _("could not resolve localhost: %s"), gai_strerror(res)); q = squotef(errstr); putresult(FAILED, "%s %s\n", handle, q); log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname, dumper_timestamp, level, errstr); amfree(q); break; } /* connect outf to chunker/taper port */ outfd = stream_client("localhost", taper_port, STREAM_BUFSIZE, 0, NULL, 0); if (outfd == -1) { errstr = newvstrallocf(errstr, _("port open: %s"), strerror(errno)); q = squotef(errstr); putresult(FAILED, "%s %s\n", handle, q); log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname, dumper_timestamp, level, errstr); amfree(q); break; } databuf_init(&db, outfd); check_options(options); rc = startup_dump(hostname, diskname, device, level, dumpdate, progname, amandad_path, client_username, ssh_keys, options); if (rc != 0) { q = squote(errstr); putresult(rc == 2? FAILED : TRYAGAIN, "%s %s\n", handle, q); if (rc == 2) log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname, dumper_timestamp, level, errstr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -