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

📄 sendbackup.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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: sendbackup.c,v 1.88 2006/07/25 18:27:56 martinea Exp $ * * common code for the sendbackup-* programs. */#include "amanda.h"#include "sendbackup.h"#include "clock.h"#include "pipespawn.h"#include "amfeatures.h"#include "amandad.h"#include "arglist.h"#include "getfsent.h"#include "version.h"#include "conffile.h"#define sendbackup_debug(i, ...) do {	\	if ((i) <= debug_sendbackup) {	\	    dbprintf(__VA_LIST__);	\	}				\} while (0)#define TIMEOUT 30pid_t comppid = (pid_t)-1;pid_t dumppid = (pid_t)-1;pid_t tarpid = (pid_t)-1;pid_t encpid = (pid_t)-1;pid_t indexpid = (pid_t)-1;char *errorstr = NULL;int datafd;int mesgfd;int indexfd;option_t *options;g_option_t *g_options = NULL;long dump_size = -1;backup_program_t *program = NULL;static am_feature_t *our_features = NULL;static char *our_feature_string = NULL;static char *amandad_auth = NULL;/* local functions */int main(int argc, char **argv);char *optionstr(option_t *options);char *childstr(pid_t pid);int check_status(pid_t pid, amwait_t w);pid_t pipefork(void (*func)(void), char *fname, int *stdinfd,		int stdoutfd, int stderrfd);void parse_backup_messages(int mesgin);static void process_dumpline(char *str);static void save_fd(int *, int);void backup_api_info_tapeheader(int mesgfd, char *prog, option_t *options);double the_num(char *str, int pos);char *optionstr(    option_t *	options){    static char *optstr = NULL;    char *compress_opt;    char *encrypt_opt;    char *decrypt_opt;    char *record_opt = "";    char *index_opt = "";    char *auth_opt;    char *exclude_file_opt;    char *exclude_list_opt;    char *exc = NULL;    sle_t *excl;    if(options->compress == COMP_BEST)	compress_opt = stralloc("compress-best;");    else if(options->compress == COMP_FAST)	compress_opt = stralloc("compress-fast;");    else if(options->compress == COMP_SERVER_BEST)	compress_opt = stralloc("srvcomp-best;");    else if(options->compress == COMP_SERVER_FAST)	compress_opt = stralloc("srvcomp-fast;");    else if(options->compress == COMP_SERVER_CUST)	compress_opt = vstralloc("srvcomp-cust=", options->srvcompprog, ";", NULL);    else if(options->compress == COMP_CUST)	compress_opt = vstralloc("comp-cust=", options->clntcompprog, ";", NULL);    else	compress_opt = stralloc("");        if(options->encrypt == ENCRYPT_CUST) {      encrypt_opt = vstralloc("encrypt-cust=", options->clnt_encrypt, ";", NULL);      if (options->clnt_decrypt_opt)	decrypt_opt = vstralloc("client-decrypt-option=", options->clnt_decrypt_opt, ";", NULL);      else	decrypt_opt = stralloc("");    }    else if(options->encrypt == ENCRYPT_SERV_CUST) {      encrypt_opt = vstralloc("encrypt-serv-cust=", options->srv_encrypt, ";", NULL);      if(options->srv_decrypt_opt)	decrypt_opt = vstralloc("server-decrypt-option=", options->srv_decrypt_opt, ";", NULL);      else	decrypt_opt = stralloc("");    }    else {	encrypt_opt = stralloc("");	decrypt_opt = stralloc("");    }    if(options->no_record) record_opt = "no-record;";    if(options->auth) auth_opt = vstralloc("auth=", options->auth, ";", NULL);	else auth_opt = stralloc("");    if(options->createindex) index_opt = "index;";    exclude_file_opt = stralloc("");    if(options->exclude_file) {	for(excl = options->exclude_file->first; excl != NULL; excl=excl->next){	    exc = newvstralloc(exc, "exclude-file=", excl->name, ";", NULL);	    strappend(exclude_file_opt, exc);	}    }    exclude_list_opt = stralloc("");    if(options->exclude_list) {	for(excl = options->exclude_list->first; excl != NULL; excl=excl->next){	    exc = newvstralloc(exc, "exclude-list=", excl->name, ";", NULL);	    strappend(exclude_list_opt, exc);	}    }    amfree(exc);    optstr = newvstralloc(optstr,			  compress_opt,			  encrypt_opt,			  decrypt_opt,			  record_opt,			  index_opt,			  auth_opt,			  exclude_file_opt,			  exclude_list_opt,			  NULL);    amfree(compress_opt);    amfree(encrypt_opt);    amfree(decrypt_opt);    amfree(auth_opt);    amfree(exclude_file_opt);    amfree(exclude_list_opt);    return optstr;}intmain(    int		argc,    char **	argv){    int interactive = 0;    int level = 0;    int mesgpipe[2];    char *prog, *dumpdate, *stroptions;    int program_is_backup_api;    char *disk = NULL;    char *qdisk = NULL;    char *amdevice = NULL;    char *qamdevice = NULL;    char *line = NULL;    char *err_extra = NULL;    char *s;    int i;    int ch;    FILE *toolin;    int status;    /* initialize */    /*     * 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");     safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);    safe_cd();    set_pname("sendbackup");    /* Don't die when child closes pipe */    signal(SIGPIPE, SIG_IGN);    /* Don't die when interrupt received */    signal(SIGINT, SIG_IGN);    if(argc > 1 && strcmp(argv[1],"-t") == 0) {	interactive = 1;	argc--;	argv++;    } else {	interactive = 0;    }    erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);    dbopen(DBG_SUBDIR_CLIENT);    startclock();    dbprintf(_("Version %s\n"), version());    if(argc > 2 && strcmp(argv[1], "amandad") == 0) {	amandad_auth = stralloc(argv[2]);    }    our_features = am_init_feature_set();    our_feature_string = am_feature_to_string(our_features);    config_init(CONFIG_INIT_CLIENT, NULL);    check_running_as(RUNNING_AS_CLIENT_LOGIN);    if(interactive) {	/*	 * In interactive (debug) mode, the backup data is sent to	 * /dev/null and none of the network connections back to driver	 * programs on the tape host are set up.  The index service is	 * run and goes to stdout.	 */	g_fprintf(stderr, _("%s: running in interactive test mode\n"), get_pname());	fflush(stderr);    }    prog = NULL;    disk = NULL;    qdisk = NULL;    amdevice = NULL;    dumpdate = NULL;    stroptions = NULL;    program_is_backup_api=0;    for(; (line = agets(stdin)) != NULL; free(line)) {	if (line[0] == '\0')	    continue;	if(interactive) {	    g_fprintf(stderr, "%s> ", get_pname());	    fflush(stderr);	}	if(strncmp_const(line, "OPTIONS ") == 0) {	    g_options = parse_g_options(line+8, 1);	    if(!g_options->hostname) {		g_options->hostname = alloc(MAX_HOSTNAME_LENGTH+1);		gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH);		g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0';	    }	    if (g_options->config) {		/* overlay this configuration on the existing (nameless) configuration */		config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,			    g_options->config);		dbrename(config_name, DBG_SUBDIR_CLIENT);	    }	    continue;	}	if (prog != NULL) {	    err_extra = _("multiple requests");	    goto err;	}	dbprintf(_("  sendbackup req: <%s>\n"), line);	s = line;	ch = *s++;	skip_whitespace(s, ch);			/* find the program name */	if(ch == '\0') {	    err_extra = _("no program name");	    goto err;				/* no program name */	}	prog = s - 1;	skip_non_whitespace(s, ch);	s[-1] = '\0';	if(strcmp(prog,"BACKUP")==0) {	    program_is_backup_api=1;	    skip_whitespace(s, ch);		/* find dumper name */	    if (ch == '\0') {		goto err;			/* no program */	    }	    prog = s - 1;	    skip_non_whitespace(s, ch);	    s[-1] = '\0';	}	prog = stralloc(prog);	skip_whitespace(s, ch);			/* find the disk name */	if(ch == '\0') {	    err_extra = _("no disk name");	    goto err;				/* no disk name */	}	amfree(disk);	amfree(qdisk);	qdisk = s - 1;	ch = *qdisk;	skip_quoted_string(s, ch);	s[-1] = '\0';	qdisk = stralloc(qdisk);	disk = unquote_string(qdisk);	skip_whitespace(s, ch);			/* find the device or level */	if (ch == '\0') {	    err_extra = _("bad level");	    goto err;	}	if(!isdigit((int)s[-1])) {	    amfree(amdevice);	    amfree(qamdevice);	    qamdevice = s - 1;	    ch = *qamdevice;	    skip_quoted_string(s, ch);	    s[-1] = '\0';	    qamdevice = stralloc(qamdevice);	    amdevice = unquote_string(qamdevice);	    skip_whitespace(s, ch);		/* find level number */	}	else {	    amdevice = stralloc(disk);	    qamdevice = stralloc(qdisk);	}						/* find the level number */	if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {	    err_extra = _("bad level");	    goto err;				/* bad level */	}	skip_integer(s, ch);	skip_whitespace(s, ch);			/* find the dump date */	if(ch == '\0') {	    err_extra = _("no dumpdate");	    goto err;				/* no dumpdate */	}	amfree(dumpdate);	dumpdate = s - 1;	skip_non_whitespace(s, ch);	s[-1] = '\0';	dumpdate = stralloc(dumpdate);	skip_whitespace(s, ch);			/* find the options keyword */	if(ch == '\0') {	    err_extra = _("no options");	    goto err;				/* no options */	}	if(strncmp_const_skip(s - 1, "OPTIONS ", s, ch) != 0) {	    err_extra = _("no OPTIONS keyword");	    goto err;				/* no options */	}	skip_whitespace(s, ch);			/* find the options string */	if(ch == '\0') {	    err_extra = _("bad options string");	    goto err;				/* no options */	}	amfree(stroptions);	stroptions = stralloc(s - 1);    }    amfree(line);    if (g_options == NULL) {	printf(_("ERROR [Missing OPTIONS line in sendbackup input]\n"));	error(_("Missing OPTIONS line in sendbackup input\n"));	/*NOTREACHED*/    }    if (prog       == NULL ||	disk       == NULL ||	amdevice   == NULL ||	dumpdate   == NULL ||	stroptions == NULL) {	err_extra = _("no valid sendbackup request");	goto err;    }	    dbprintf(_("  Parsed request as: program `%s'\n"), prog);    dbprintf(_("                     disk `%s'\n"), qdisk);    dbprintf(_("                     device `%s'\n"), qamdevice);    dbprintf(_("                     level %d\n"), level);    dbprintf(_("                     since %s\n"), dumpdate);    dbprintf(_("                     options `%s'\n"), stroptions);    if(program_is_backup_api==1) {	/* check that the backup_api exist */    }    else {	for(i = 0; programs[i]; i++) {	    if (strcmp(programs[i]->name, prog) == 0) {		break;	    }	}	if (programs[i] == NULL) {	    dbprintf(_("ERROR [%s: unknown program %s]\n"), get_pname(), prog);	    error(_("ERROR [%s: unknown program %s]"), get_pname(), prog);	    /*NOTREACHED*/	}	program = programs[i];    }    options = parse_options(stroptions, disk, amdevice, g_options->features, 0);    if(!interactive) {	datafd = DATA_FD_OFFSET + 0;	mesgfd = DATA_FD_OFFSET + 2;	indexfd = DATA_FD_OFFSET + 4;    }    if (!options->createindex)	indexfd = -1;    if(options->auth && amandad_auth) {	if(strcasecmp(options->auth, amandad_auth) != 0) {	    g_printf(_("ERROR [client configured for auth=%s while server requested '%s']\n"),		   amandad_auth, options->auth);	    exit(-1);	}    }    if (options->kencrypt) {	g_printf("KENCRYPT\n");    }    g_printf(_("CONNECT DATA %d MESG %d INDEX %d\n"),	   DATA_FD_OFFSET, DATA_FD_OFFSET+1,	   indexfd == -1 ? -1 : DATA_FD_OFFSET+2);    g_printf(_("OPTIONS "));    if(am_has_feature(g_options->features, fe_rep_options_features)) {	g_printf("features=%s;", our_feature_string);    }    if(am_has_feature(g_options->features, fe_rep_options_hostname)) {	g_printf("hostname=%s;", g_options->hostname);    }    if(am_has_feature(g_options->features, fe_rep_options_sendbackup_options)) {	g_printf("%s", optionstr(options));    }    g_printf("\n");    fflush(stdout);    if (freopen("/dev/null", "w", stdout) == NULL) {	dbprintf(_("Error redirecting stdout to /dev/null: %s\n"),		 strerror(errno));        exit(1);    }    if(interactive) {      if((datafd = open("/dev/null", O_RDWR)) < 0) {	error(_("ERROR [open of /dev/null for debug data stream: %s]\n"),		strerror(errno));	/*NOTREACHED*/      }      mesgfd = 2;      indexfd = 1;    }    if(!interactive) {      if(datafd == -1 || mesgfd == -1 || (options->createindex && indexfd == -1)) {        dbclose();        exit(1);      }    }    if(program_is_backup_api==1) {	pid_t backup_api_pid;	int i, j;	char *cmd=NULL;	char *argvchild[20];	char levelstr[20];	int property_pipe[2];	backup_support_option_t *bsu;	if (pipe(property_pipe) < 0) {	    error(_("Can't create pipe: %s"),strerror(errno));	    /*NOTREACHED*/	}	bsu = backup_support_option(prog, g_options, disk, amdevice);	switch(backup_api_pid=fork()) {	case 0:	    aclose(property_pipe[1]);	    if(dup2(property_pipe[0], 0) == -1) {		error(_("Can't dup2: %s"),strerror(errno));		/*NOTREACHED*/	    }	    if(dup2(datafd, 1) == -1) {		error(_("Can't dup2: %s"),strerror(errno));		/*NOTREACHED*/	    }	    if(dup2(mesgfd, 2) == -1) {		error(_("Can't dup2: %s"),strerror(errno));		/*NOTREACHED*/	    }	    if(indexfd != 0) {		if(dup2(indexfd, 3) == -1) {		    error(_("Can't dup2: %s"),strerror(errno));		    /*NOTREACHED*/		}		fcntl(indexfd, F_SETFD, 0);		fcntl(3, F_SETFD, 0);		safe_fd(3, 1);	    } else {		safe_fd(-1, 0);	    }	    cmd = vstralloc(DUMPER_DIR, "/", prog, NULL);	    i=0;	    argvchild[i++] = prog;	    argvchild[i++] = "backup";	    if (bsu->message_line == 1) {		argvchild[i++] = "--message";		argvchild[i++] = "line";	    }	    if (g_options->config && bsu->config == 1) {		argvchild[i++] = "--config";		argvchild[i++] = g_options->config;	    }	    if (g_options->hostname && bsu->host == 1) {		argvchild[i++] = "--host";		argvchild[i++] = g_options->hostname;	    }	    if (disk && bsu->disk == 1) {		argvchild[i++] = "--disk";		argvchild[i++] = disk;	    }	    argvchild[i++] = "--device";	    argvchild[i++] = amdevice;	    if (level <= bsu->max_level) {		argvchild[i++] = "--level";		g_snprintf(levelstr,19,"%d",level);		argvchild[i++] = levelstr;	    }	    if (indexfd != 0 && bsu->index_line == 1) {		argvchild[i++] = "--index";		argvchild[i++] = "line";	    }	    if (!options->no_record && bsu->record == 1) {		argvchild[i++] = "--record";	    }	    argvchild[i] = NULL;	    dbprintf(_("%s: running \"%s"), get_pname(), cmd);	    for(j=1;j<i;j++) dbprintf(" %s",argvchild[j]);	    dbprintf(_("\"\n"));	    backup_api_info_tapeheader(mesgfd, prog, options);	    execve(cmd, argvchild, safe_env());	    exit(1);	    break; 	default:	    aclose(property_pipe[0]);	    toolin = fdopen(property_pipe[1],"w");	    if (!toolin) {		error(_("Can't fdopen: %s"), strerror(errno));		/*NOTREACHED*/	    }	    output_tool_property(toolin, options);	    fflush(toolin);	    fclose(toolin);	    break;	case -1:	    error(_("%s: fork returned: %s"), get_pname(), strerror(errno));	}	amfree(bsu);	if (waitpid(backup_api_pid, &status, 0) < 0) {	    if (!WIFEXITED(status)) {		dbprintf(_("Tool exited with signal %d"), WTERMSIG(status));	    } else if (WEXITSTATUS(status) != 0) {		dbprintf(_("Tool exited with status %d"), WEXITSTATUS(status));	    } else {		dbprintf(_("waitpid returned negative value"));	    }	}     }    else {	if(!interactive) {	    /* redirect stderr */	    if(dup2(mesgfd, 2) == -1) {		dbprintf(_("Error redirecting stderr to fd %d: %s\n"),			 mesgfd, strerror(errno));		dbclose();		exit(1);	    }	} 	if(pipe(mesgpipe) == -1) {	    s = strerror(errno);	    dbprintf(_("error [opening mesg pipe: %s]\n"), s);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -