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

📄 dumper.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-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 + -