Exemple #1
0
int
main(
    int		argc,
    char **	argv)
{
    int c;
    char *command;
    application_argument_t argument;
    int i;

#ifdef GNUTAR
    gnutar_path = GNUTAR;
#else
    gnutar_path = NULL;
#endif
    gnutar_directory = NULL;
    gnutar_onefilesystem = 1;
    gnutar_atimepreserve = 1;
    gnutar_checkdevice = 1;
    gnutar_sparse = 1;
    gnutar_no_unquote = 0;
    exit_handling = NULL;

    /* 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");

    if (argc < 2) {
        printf("ERROR no command given to amgtar\n");
        error(_("No command given to amgtar"));
    }

    /* drop root privileges */
    if (!set_root_privs(0)) {
	if (strcmp(argv[1], "selfcheck") == 0) {
	    printf("ERROR amgtar must be run setuid root\n");
	}
	error(_("amgtar must be run setuid root"));
    }

    safe_fd(3, 2);

    set_pname("amgtar");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

#if defined(USE_DBMALLOC)
    malloc_size_1 = malloc_inuse(&malloc_hist_1);
#endif

    add_amanda_log_handler(amanda_log_stderr);
    add_amanda_log_handler(amanda_log_syslog);
    dbopen(DBG_SUBDIR_CLIENT);
    startclock();
    dbprintf(_("version %s\n"), version());

    config_init(CONFIG_INIT_CLIENT, NULL);

    //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED);
    //root for amrecover
    //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup

    /* parse argument */
    command = argv[1];

    argument.config     = NULL;
    argument.host       = NULL;
    argument.message    = 0;
    argument.collection = 0;
    argument.calcsize   = 0;
    argument.tar_blocksize = NULL;
    argument.level      = NULL;
    init_dle(&argument.dle);

    while (1) {
	int option_index = 0;
    	c = getopt_long (argc, argv, "", long_options, &option_index);
	if (c == -1) {
	    break;
	}
	switch (c) {
	case 1: argument.config = stralloc(optarg);
		break;
	case 2: argument.host = stralloc(optarg);
		break;
	case 3: argument.dle.disk = stralloc(optarg);
		break;
	case 4: argument.dle.device = stralloc(optarg);
		break;
	case 5: argument.level = g_slist_append(argument.level,
					        GINT_TO_POINTER(atoi(optarg)));
		break;
	case 6: argument.dle.create_index = 1;
		break;
	case 7: argument.message = 1;
		break;
	case 8: argument.collection = 1;
		break;
	case 9: argument.dle.record = 1;
		break;
	case 10: gnutar_path = stralloc(optarg);
		 break;
	case 11: gnutar_listdir = stralloc(optarg);
		 break;
	case 12: if (optarg && strcasecmp(optarg, "NO") == 0)
		     gnutar_onefilesystem = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     gnutar_onefilesystem = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad ONE-FILE-SYSTEM property value (%s)]\n"), get_pname(), optarg);
		 break;
	case 13: if (optarg && strcasecmp(optarg, "NO") == 0)
		     gnutar_sparse = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     gnutar_sparse = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg);
		 break;
	case 14: if (optarg && strcasecmp(optarg, "NO") == 0)
		     gnutar_atimepreserve = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     gnutar_atimepreserve = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad ATIME-PRESERVE property value (%s)]\n"), get_pname(), optarg);
		 break;
	case 15: if (optarg && strcasecmp(optarg, "NO") == 0)
		     gnutar_checkdevice = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     gnutar_checkdevice = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad CHECK-DEVICE property value (%s)]\n"), get_pname(), optarg);
		 break;
	case 16: if (optarg)
		     argument.dle.include_file =
			 append_sl(argument.dle.include_file, optarg);
		 break;
	case 17: if (optarg)
		     argument.dle.include_list =
			 append_sl(argument.dle.include_list, optarg);
		 break;
	case 18: argument.dle.include_optional = 1;
		 break;
	case 19: if (optarg)
		     argument.dle.exclude_file =
			 append_sl(argument.dle.exclude_file, optarg);
		 break;
	case 20: if (optarg)
		     argument.dle.exclude_list =
			 append_sl(argument.dle.exclude_list, optarg);
		 break;
	case 21: argument.dle.exclude_optional = 1;
		 break;
	case 22: gnutar_directory = stralloc(optarg);
		 break;
	case 23: if (optarg)
		     normal_message = 
			 g_slist_append(normal_message, optarg);
		 break;
	case 24: if (optarg)
		     ignore_message = 
			 g_slist_append(ignore_message, optarg);
		 break;
	case 25: if (optarg)
		     strange_message = 
			 g_slist_append(strange_message, optarg);
		 break;
	case 26: if (optarg)
		     exit_handling = stralloc(optarg);
		 break;
	case 27: argument.calcsize = 1;
		 break;
	case 28: argument.tar_blocksize = stralloc(optarg);
		 break;
	case 29: if (optarg && strcasecmp(optarg, "NO") == 0)
		     gnutar_no_unquote = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     gnutar_no_unquote = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad No_UNQUOTE property value (%s)]\n"), get_pname(), optarg);
		 break;
	case ':':
	case '?':
		break;
	}
    }

    argument.argc = argc - optind;
    argument.argv = argv + optind;

    if (argument.config) {
	config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
		    argument.config);
	dbrename(get_config_name(), DBG_SUBDIR_CLIENT);
    }

    if (config_errors(NULL) >= CFGERR_ERRORS) {
	g_critical(_("errors processing config file"));
    }

    re_table = build_re_table(init_re_table, normal_message, ignore_message,
			      strange_message);

    for(i=0;i<256;i++)
	exit_value[i] = 1; /* BAD  */
    exit_value[0] = 0;     /* GOOD */
    exit_value[1] = 0;     /* GOOD */
    if (exit_handling) {
	char *s = exit_handling;
	while (s) {
	    char *r = strchr(s, '=');
	    if (r) {
		int j = atoi(s);
		if (j >= 0 && j < 256) {
		    r++;
		    if (strncasecmp(r, "GOOD", 4) == 0) {
			exit_value[j] = 0;
		    }
		}
	    }
	    s = strchr(s+1, ' ');
	}
    }

    gnutar_listdir = getconf_str(CNF_GNUTAR_LIST_DIR);
    if (strlen(gnutar_listdir) == 0)
	gnutar_listdir = NULL;

    if (gnutar_path) {
	dbprintf("GNUTAR-PATH %s\n", gnutar_path);
    } else {
	dbprintf("GNUTAR-PATH is not set\n");
    }
    if (gnutar_listdir) {
	    dbprintf("GNUTAR-LISTDIR %s\n", gnutar_listdir);
    } else {
	dbprintf("GNUTAR-LISTDIR is not set\n");
    }
    if (gnutar_directory) {
	dbprintf("DIRECTORY %s\n", gnutar_directory);
    }
    dbprintf("ONE-FILE-SYSTEM %s\n", gnutar_onefilesystem? "yes":"no");
    dbprintf("SPARSE %s\n", gnutar_sparse? "yes":"no");
    dbprintf("NO-UNQUOTE %s\n", gnutar_no_unquote? "yes":"no");
    dbprintf("ATIME-PRESERVE %s\n", gnutar_atimepreserve? "yes":"no");
    dbprintf("CHECK-DEVICE %s\n", gnutar_checkdevice? "yes":"no");
    {
	amregex_t *rp;
	for (rp = re_table; rp->regex != NULL; rp++) {
	    switch (rp->typ) {
		case DMP_NORMAL : dbprintf("NORMAL %s\n", rp->regex); break;
		case DMP_IGNORE : dbprintf("IGNORE %s\n", rp->regex); break;
		case DMP_STRANGE: dbprintf("STRANGE %s\n", rp->regex); break;
		case DMP_SIZE   : dbprintf("SIZE %s\n", rp->regex); break;
		case DMP_ERROR  : dbprintf("ERROR %s\n", rp->regex); break;
	    }
	}
    }

    if (strcmp(command, "support") == 0) {
	amgtar_support(&argument);
    } else if (strcmp(command, "selfcheck") == 0) {
	amgtar_selfcheck(&argument);
    } else if (strcmp(command, "estimate") == 0) {
	amgtar_estimate(&argument);
    } else if (strcmp(command, "backup") == 0) {
	amgtar_backup(&argument);
    } else if (strcmp(command, "restore") == 0) {
	amgtar_restore(&argument);
    } else if (strcmp(command, "validate") == 0) {
	amgtar_validate(&argument);
    } else {
	dbprintf("Unknown command `%s'.\n", command);
	fprintf(stderr, "Unknown command `%s'.\n", command);
	exit (1);
    }
    return 0;
}
Exemple #2
0
int
main(
    int		argc,
    char **	argv)
{
    int interactive = 0;
    int level = 0;
    int mesgpipe[2];
    dle_t *dle = NULL;
    char *dumpdate, *stroptions;
    char *qdisk = NULL;
    char *qamdevice = NULL;
    char *line = NULL;
    char *err_extra = NULL;
    char *s;
    int i;
    int ch;
    GSList *errlist;
    FILE   *mesgstream;
    level_t *alevel;

    /* 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 for config errors comes later) */

    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);
    }

    qdisk = NULL;
    dumpdate = NULL;
    stroptions = NULL;

    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(get_config_name(), DBG_SUBDIR_CLIENT);
	    }

	    /* check for any config errors now */
	    if (config_errors(&errlist) >= CFGERR_ERRORS) {
		char *errstr = config_errors_to_error_string(errlist);
		g_printf("%s\n", errstr);
		dbclose();
		return 1;
	    }

	    if (am_has_feature(g_options->features, fe_req_xml)) {
		break;
	    }
	    continue;
	}

	if (dle && dle->program != NULL) {
	    err_extra = _("multiple requests");
	    goto err;
	}

	dbprintf(_("  sendbackup req: <%s>\n"), line);
	dle = alloc_dle();

	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 */
	}
	dle->program = s - 1;
	skip_non_whitespace(s, ch);
	s[-1] = '\0';

        if (strcmp(dle->program, "APPLICATION")==0) {
            dle->program_is_application_api=1;
            skip_whitespace(s, ch);             /* find dumper name */
            if (ch == '\0') {
                goto err;                       /* no program */
            }
            dle->program = s - 1;
            skip_non_whitespace(s, ch);
            s[-1] = '\0';
        }
	dle->program = stralloc(dle->program);

	skip_whitespace(s, ch);			/* find the disk name */
	if(ch == '\0') {
	    err_extra = _("no disk name");
	    goto err;				/* no disk name */
	}

	amfree(qdisk);
	qdisk = s - 1;
	ch = *qdisk;
	skip_quoted_string(s, ch);
	s[-1] = '\0';
	qdisk = stralloc(qdisk);
	dle->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(qamdevice);
	    qamdevice = s - 1;
	    ch = *qamdevice;
	    skip_quoted_string(s, ch);
	    s[-1] = '\0';
	    qamdevice = stralloc(qamdevice);
	    dle->device = unquote_string(qamdevice);
	    skip_whitespace(s, ch);		/* find level number */
	}
	else {
	    dle->device = stralloc(dle->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);
	alevel = g_new0(level_t, 1);
	alevel->level = level;
	dle->levellist = g_slist_append(dle->levellist, alevel);

	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) {
	g_printf(_("ERROR [Missing OPTIONS line in sendbackup input]\n"));
	error(_("Missing OPTIONS line in sendbackup input\n"));
	/*NOTREACHED*/
    }

    if (am_has_feature(g_options->features, fe_req_xml)) {
	char *errmsg = NULL;

	dle = amxml_parse_node_FILE(stdin, &errmsg);
	if (errmsg) {
	    err_extra = errmsg;
	    goto err;
	}
	if (!dle) {
	    err_extra = _("One DLE required");
	    goto err;
	} else if (dle->next) {
	    err_extra = _("Only one DLE allowed");
	    goto err;
	}

	qdisk = quote_string(dle->disk);
	if (dle->device == NULL)
	    dle->device = stralloc(dle->disk);
	qamdevice = quote_string(dle->device);
	dumpdate = stralloc("NODATE");
	stroptions = stralloc("");
    } else {
	parse_options(stroptions, dle, g_options->features, 0);
    }
    gdle = dle;

    if (dle->program   == NULL ||
	dle->disk      == NULL ||
	dle->device    == NULL ||
	dle->levellist == NULL ||
	dumpdate       == NULL) {
	err_extra = _("no valid sendbackup request");
	goto err;
    }

    if (g_slist_length(dle->levellist) != 1) {
	err_extra = _("Too many level");
	goto err;
    }

    alevel = (level_t *)dle->levellist->data;
    level = alevel->level;
    dbprintf(_("  Parsed request as: program `%s'\n"), dle->program);
    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 (dle->program_is_application_api==1) {
	/* check that the application_api exist */
    } else {
	for(i = 0; programs[i]; i++) {
	    if (strcmp(programs[i]->name, dle->program) == 0) {
		break;
	    }
	}
	if (programs[i] == NULL) {
	    dbprintf(_("ERROR [%s: unknown program %s]\n"), get_pname(),
		     dle->program);
	    error(_("ERROR [%s: unknown program %s]"), get_pname(),
		  dle->program);
	    /*NOTREACHED*/
	}
	program = programs[i];
    }

    if(!interactive) {
	datafd = DATA_FD_OFFSET + 0;
	mesgfd = DATA_FD_OFFSET + 2;
	indexfd = DATA_FD_OFFSET + 4;
    }
    if (!dle->create_index)
	indexfd = -1;

    if (dle->auth && amandad_auth) {
	if(strcasecmp(dle->auth, amandad_auth) != 0) {
	    g_printf(_("ERROR [client configured for auth=%s while server requested '%s']\n"),
		   amandad_auth, dle->auth);
	    exit(-1);
	}
    }

    if (dle->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);
    }
    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 || (dle->create_index && indexfd == -1)) {
        dbclose();
        exit(1);
      }
    }

    mesgstream = fdopen(mesgfd,"w");
    run_client_scripts(EXECUTE_ON_PRE_DLE_BACKUP, g_options, dle, mesgstream);
    fflush(mesgstream);

    if (dle->program_is_application_api==1) {
	guint j;
	char *cmd=NULL;
	GPtrArray *argv_ptr;
	char levelstr[20];
	backup_support_option_t *bsu;
	char *compopt = NULL;
	char *encryptopt = skip_argument;
	int compout, dumpout;
	GSList    *scriptlist;
	script_t  *script;
	time_t     cur_dumptime;
	int        result;
	GPtrArray *errarray;
	int        errfd[2];
	FILE      *dumperr;

	/*  apply client-side encryption here */
	if ( dle->encrypt == ENCRYPT_CUST ) {
	    encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
			       &compout, &datafd, &mesgfd,
			       dle->clnt_encrypt, encryptopt, NULL);
	    dbprintf(_("encrypt: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
	} else {
	    compout = datafd;
	    encpid = -1;
	}

	/*  now do the client-side compression */
	if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
	    compopt = skip_argument;
#if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
	    if(dle->compress == COMP_BEST) {
		compopt = COMPRESS_BEST_OPT;
	    } else {
		compopt = COMPRESS_FAST_OPT;
	    }
#endif
	    comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0,
				&dumpout, &compout, &mesgfd,
				COMPRESS_PATH, compopt, NULL);
	    dbprintf(_("gnutar: pid %ld: %s"), (long)comppid, COMPRESS_PATH);
	    if(compopt != skip_argument) {
		dbprintf(_("pid %ld: %s %s\n"),
			 (long)comppid, COMPRESS_PATH, compopt);
	    } else {
		dbprintf(_("pid %ld: %s\n"), (long)comppid, COMPRESS_PATH);
	    }
	} else if (dle->compress == COMP_CUST) {
	    compopt = skip_argument;
	    comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
				&dumpout, &compout, &mesgfd,
				dle->compprog, compopt, NULL);
	    if(compopt != skip_argument) {
		dbprintf(_("pid %ld: %s %s\n"),
			 (long)comppid, dle->compprog, compopt);
	    } else {
		dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog);
	    }
	} else {
	    dumpout = compout;
	    comppid = -1;
	}

	cur_dumptime = time(0);
	bsu = backup_support_option(dle->program, g_options, dle->disk,
				    dle->device, &errarray);
	if (!bsu) {
	    char  *errmsg;
	    char  *qerrmsg;
	    guint  i;
	    for (i=0; i < errarray->len; i++) {
		errmsg = g_ptr_array_index(errarray, i);
		qerrmsg = quote_string(errmsg);
		fdprintf(mesgfd,
			  _("sendbackup: error [Application '%s': %s]\n"),
			  dle->program, errmsg);
		dbprintf("aa: %s\n",qerrmsg);
		amfree(qerrmsg);
	    }
	    if (i == 0) { /* no errarray */
		errmsg = vstrallocf(_("Can't execute application '%s'"),
				    dle->program);
		qerrmsg = quote_string(errmsg);
		fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg);
		dbprintf(_("ERROR %s\n"), qerrmsg);
		amfree(qerrmsg);
		amfree(errmsg);
	    }
	    return 0;
	}

	if (pipe(errfd) < 0) {
	    char  *errmsg;
	    char  *qerrmsg;
	    errmsg = vstrallocf(_("Application '%s': can't create pipe"),
				    dle->program);
	    qerrmsg = quote_string(errmsg);
	    fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg);
	    dbprintf(_("ERROR %s\n"), qerrmsg);
	    amfree(qerrmsg);
	    amfree(errmsg);
	    return 0;
	}

	switch(application_api_pid=fork()) {
	case 0:
	    argv_ptr = g_ptr_array_new();
	    cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL);
	    g_ptr_array_add(argv_ptr, stralloc(dle->program));
	    g_ptr_array_add(argv_ptr, stralloc("backup"));
	    if (bsu->message_line == 1) {
		g_ptr_array_add(argv_ptr, stralloc("--message"));
		g_ptr_array_add(argv_ptr, stralloc("line"));
	    }
	    if (g_options->config && bsu->config == 1) {
		g_ptr_array_add(argv_ptr, stralloc("--config"));
		g_ptr_array_add(argv_ptr, stralloc(g_options->config));
	    }
	    if (g_options->hostname && bsu->host == 1) {
		g_ptr_array_add(argv_ptr, stralloc("--host"));
		g_ptr_array_add(argv_ptr, stralloc(g_options->hostname));
	    }
	    if (dle->disk && bsu->disk == 1) {
		g_ptr_array_add(argv_ptr, stralloc("--disk"));
		g_ptr_array_add(argv_ptr, stralloc(dle->disk));
	    }
	    g_ptr_array_add(argv_ptr, stralloc("--device"));
	    g_ptr_array_add(argv_ptr, stralloc(dle->device));
	    if (level <= bsu->max_level) {
		g_ptr_array_add(argv_ptr, stralloc("--level"));
		g_snprintf(levelstr,19,"%d",level);
		g_ptr_array_add(argv_ptr, stralloc(levelstr));
	    }
	    if (indexfd != -1 && bsu->index_line == 1) {
		g_ptr_array_add(argv_ptr, stralloc("--index"));
		g_ptr_array_add(argv_ptr, stralloc("line"));
	    }
	    if (dle->record && bsu->record == 1) {
		g_ptr_array_add(argv_ptr, stralloc("--record"));
	    }
	    application_property_add_to_argv(argv_ptr, dle, bsu);

	    for (scriptlist = dle->scriptlist; scriptlist != NULL;
		 scriptlist = scriptlist->next) {
		script = (script_t *)scriptlist->data;
		if (script->result && script->result->proplist) {
		    property_add_to_argv(argv_ptr, script->result->proplist);
		}
	    }

	    g_ptr_array_add(argv_ptr, NULL);
	    dbprintf(_("%s: running \"%s\n"), get_pname(), cmd);
	    for (j = 1; j < argv_ptr->len - 1; j++)
		dbprintf(" %s\n", (char *)g_ptr_array_index(argv_ptr,j));
	    dbprintf(_("\"\n"));
	    if(dup2(dumpout, 1) == -1) {
		error(_("Can't dup2: %s"),strerror(errno));
		/*NOTREACHED*/
	    }
	    if (dup2(errfd[1], 2) == -1) {
		error(_("Can't dup2: %s"),strerror(errno));
		/*NOTREACHED*/
	    }
	    if(dup2(mesgfd, 3) == -1) {
		error(_("Can't dup2: %s"),strerror(errno));
		/*NOTREACHED*/
	    }
	    if(indexfd > 0) {
		if(dup2(indexfd, 4) == -1) {
		    error(_("Can't dup2: %s"),strerror(errno));
		    /*NOTREACHED*/
		}
		fcntl(indexfd, F_SETFD, 0);
	    }
	    application_api_info_tapeheader(mesgfd, dle->program, dle);
	    if (indexfd != 0) {
		safe_fd(3, 2);
	    } else {
		safe_fd(3, 1);
	    }
	    execve(cmd, (char **)argv_ptr->pdata, safe_env());
	    exit(1);
	    break;
 
	default:
	    break;
	case -1:
	    error(_("%s: fork returned: %s"), get_pname(), strerror(errno));
	}

	close(errfd[1]);
	dumperr = fdopen(errfd[0],"r");
	if (!dumperr) {
	    error(_("Can't fdopen: %s"), strerror(errno));
	    /*NOTREACHED*/
	}

	result = 0;
	while ((line = agets(dumperr)) != NULL) {
	    if (strlen(line) > 0) {
		fdprintf(mesgfd, "sendbackup: error [%s]\n", line);
		dbprintf("error: %s\n", line);
		result = 1;
	    }
	    amfree(line);
	}

	result |= check_result(mesgfd);
	if (result == 0) {
	    char *amandates_file;

	    amandates_file = getconf_str(CNF_AMANDATES);
	    if(start_amandates(amandates_file, 1)) {
		amandates_updateone(dle->disk, level, cur_dumptime);
		finish_amandates();
		free_amandates();
	    } else {
		if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE &&
		    bsu->calcsize) {
		    error(_("error [opening %s for writing: %s]"),
			  amandates_file, strerror(errno));
		} else {
		    g_debug(_("non-fatal error opening '%s' for writing: %s]"),
			    amandates_file, strerror(errno));
		}
	    }
	}
	amfree(bsu);
     } 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);
	    error(_("error [opening mesg pipe: %s]"), s);
	}

	program->start_backup(dle, g_options->hostname,
			      datafd, mesgpipe[1], indexfd);
	dbprintf(_("Started backup\n"));
	parse_backup_messages(dle, mesgpipe[0]);
	dbprintf(_("Parsed backup messages\n"));
    }

    run_client_scripts(EXECUTE_ON_POST_DLE_BACKUP, g_options, dle, mesgstream);
    fflush(mesgstream);

    amfree(qdisk);
    amfree(qamdevice);
    amfree(dumpdate);
    amfree(stroptions);
    amfree(our_feature_string);
    am_release_feature_set(our_features);
    our_features = NULL;
    free_g_options(g_options);

    dbclose();

    return 0;

 err:
    if (err_extra) {
	g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra);
	dbprintf(_("REQ packet is bogus: %s\n"), err_extra);
    } else {
	g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET\n"));
	dbprintf(_("REQ packet is bogus\n"));
    }

    amfree(qdisk);
    amfree(qamdevice);
    amfree(dumpdate);
    amfree(stroptions);
    amfree(our_feature_string);

    dbclose();
    return 1;
}
Exemple #3
0
int
main(
    int		argc,
    char **	argv)
{
    int c;
    char *command;
    application_argument_t argument;

#ifdef STAR
    star_path = STAR;
#else
    star_path = NULL;
#endif
    star_tardumps = "/etc/tardumps";
    star_dle_tardumps = 0;
    star_onefilesystem = 1;
    star_sparse = 1;
    star_directory = NULL;

    /* 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");

    if (argc < 2) {
	printf("ERROR no command given to amstar\n");
	error(_("No command given to amstar"));
    }

    /* drop root privileges */
    if (!set_root_privs(0)) {
	if (strcmp(argv[1], "selfcheck") == 0) {
	    printf("ERROR amstar must be run setuid root\n");
	}
	error(_("amstar must be run setuid root"));
    }

    safe_fd(3, 2);

    set_pname("amstar");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

#if defined(USE_DBMALLOC)
    malloc_size_1 = malloc_inuse(&malloc_hist_1);
#endif

    add_amanda_log_handler(amanda_log_stderr);
    add_amanda_log_handler(amanda_log_syslog);
    dbopen(DBG_SUBDIR_CLIENT);
    startclock();
    dbprintf(_("version %s\n"), VERSION);

    config_init(CONFIG_INIT_CLIENT, NULL);

    //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED);
    //root for amrecover
    //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup

    /* parse argument */
    command = argv[1];

    argument.config     = NULL;
    argument.host       = NULL;
    argument.message    = 0;
    argument.collection = 0;
    argument.calcsize   = 0;
    argument.level      = NULL;
    argument.command_options = NULL;
    init_dle(&argument.dle);

    opterr = 0;
    while (1) {
	int option_index = 0;
    	c = getopt_long (argc, argv, "", long_options, &option_index);
	if (c == -1)
	    break;

	switch (c) {
	case 1: argument.config = stralloc(optarg);
		break;
	case 2: argument.host = stralloc(optarg);
		break;
	case 3: argument.dle.disk = stralloc(optarg);
		break;
	case 4: argument.dle.device = stralloc(optarg);
		break;
	case 5: argument.level = g_slist_append(argument.level,
						GINT_TO_POINTER(atoi(optarg)));
		break;
	case 6: argument.dle.create_index = 1;
		break;
	case 7: argument.message = 1;
		break;
	case 8: argument.collection = 1;
		break;
	case 9: argument.dle.record = 1;
		break;
	case 10: star_path = stralloc(optarg);
		 break;
	case 11: star_tardumps = stralloc(optarg);
		 break;
	case 12: if (optarg && strcasecmp(optarg, "NO") == 0)
		     star_dle_tardumps = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     star_dle_tardumps = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad STAR-DLE-TARDUMP property value (%s)]\n"), get_pname(), optarg);
		 break;
	case 13: if (optarg && strcasecmp(optarg, "YES") != 0) {
		     /* This option is required to be YES */
		     /* star_onefilesystem = 0; */
		 }
		 break;
	case 14: if (optarg && strcasecmp(optarg, "NO") == 0)
		     star_sparse = 0;
		 else if (optarg && strcasecmp(optarg, "YES") == 0)
		     star_sparse = 1;
		 else if (strcasecmp(command, "selfcheck") == 0)
		     printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg);
		 break;
	case 15: argument.calcsize = 1;
		 break;
        case 16: if (optarg)
                     normal_message =
                         g_slist_append(normal_message, optarg);
                 break;
        case 17: if (optarg)
                     ignore_message =
                         g_slist_append(ignore_message, optarg);
                 break;
        case 18: if (optarg)
                     strange_message =
                         g_slist_append(strange_message, optarg);
                 break;
	case 19: if (optarg)
		     argument.dle.include_list =
			 append_sl(argument.dle.include_list, optarg);
		 break;
	case 20: if (optarg)
		     argument.dle.exclude_list =
			 append_sl(argument.dle.exclude_list, optarg);
		 break;
	case 21: if (optarg)
		     star_directory = stralloc(optarg);
		 break;
	case 22: argument.command_options =
			g_slist_append(argument.command_options,
				       stralloc(optarg));
	case 23: if (optarg)
		     argument.dle.exclude_file =
			 append_sl(argument.dle.exclude_file, optarg);
		 break;
	case ':':
	case '?':
		break;
	}
    }

    if (!argument.dle.disk && argument.dle.device)
	argument.dle.disk = stralloc(argument.dle.device);
    if (!argument.dle.device && argument.dle.disk)
	argument.dle.device = stralloc(argument.dle.disk);

    argument.argc = argc - optind;
    argument.argv = argv + optind;

    if (argument.config) {
	/* overlay this configuration on the existing (nameless) configuration */
	config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
		    argument.config);
	dbrename(get_config_name(), DBG_SUBDIR_CLIENT);

    }

    if (config_errors(NULL) >= CFGERR_ERRORS) {
	g_critical(_("errors processing config file"));
    }

    re_table = build_re_table(init_re_table, normal_message, ignore_message,
			      strange_message);

    if (strcmp(command, "support") == 0) {
	amstar_support(&argument);
    } else if (strcmp(command, "selfcheck") == 0) {
	amstar_selfcheck(&argument);
    } else if (strcmp(command, "estimate") == 0) {
	amstar_estimate(&argument);
    } else if (strcmp(command, "backup") == 0) {
	amstar_backup(&argument);
    } else if (strcmp(command, "restore") == 0) {
	amstar_restore(&argument);
    } else if (strcmp(command, "validate") == 0) {
	amstar_validate(&argument);
    } else {
	fprintf(stderr, "Unknown command `%s'.\n", command);
	exit (1);
    }
    return 0;
}
Exemple #4
0
/*
 * Send the requested file.
 */
int tftp_sendfile(int f, union sock_addr *peeraddr,
		   int fd, const char *name, const char *mode)
{
    struct tftphdr *ap;         /* data and ack packets */
    struct tftphdr *dp;
    int n;
    volatile int is_request;
    volatile u_short block;
    volatile int size, convert;
    volatile off_t amount;
    union sock_addr from;
    socklen_t fromlen;
    FILE *file;
    u_short ap_opcode, ap_block;

    startclock();               /* start stat's clock */
    dp = r_init();              /* reset fillbuf/read-ahead code */
    ap = (struct tftphdr *)ackbuf;
    convert = !strcmp(mode, "netascii");
    file = fdopen(fd, convert ? "rt" : "rb");
    block = 0;
    is_request = 1;             /* First packet is the actual WRQ */
    amount = 0;

    bsd_signal(SIGALRM, timer);
    do {
        if (is_request) {
            size = makerequest(WRQ, name, dp, mode) - 4;
        } else {
            /*      size = read(fd, dp->th_data, SEGSIZE);   */
            size = readit(file, &dp, convert);
            if (size < 0) {
                nak(f, peeraddr, errno + 100, NULL);
                break;
            }
            dp->th_opcode = htons((u_short) DATA);
            dp->th_block = htons((u_short) block);
        }
        timeout = 0;
        (void)sigsetjmp(timeoutbuf, 1);

        if (trace)
            tpacket("sent", dp, size + 4);
        n = sendto(f, dp, size + 4, 0,
                   &(peeraddr->sa), SOCKLEN(peeraddr));
        if (n != size + 4) {
            perror("tftp: sendto");
            goto abort;
        }
        read_ahead(file, convert);
        for (;;) {
            alarm(rexmtval);
            do {
                fromlen = sizeof(from);
                n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
                             &from.sa, &fromlen);
            } while (n <= 0);
            alarm(0);
            if (n < 0) {
                perror("tftp: recvfrom");
                goto abort;
            }
            sa_set_port(peeraddr, SOCKPORT(&from));  /* added */
            if (trace)
                tpacket("received", ap, n);
            /* should verify packet came from server */
            ap_opcode = ntohs((u_short) ap->th_opcode);
            ap_block = ntohs((u_short) ap->th_block);
            if (ap_opcode == ERROR) {
                printf("Error code %d: %s\n", ap_block, ap->th_msg);
                goto abort;
            }
            if (ap_opcode == ACK) {
                int j;

                if (ap_block == block) {
                    break;
                }
                /* On an error, try to synchronize
                 * both sides.
                 */
                j = synchnet(f);
                if (j && trace) {
                    printf("discarded %d packets\n", j);
                }
                /*
                 * RFC1129/RFC1350: We MUST NOT re-send the DATA
                 * packet in response to an invalid ACK.  Doing so
                 * would cause the Sorcerer's Apprentice bug.
                 */
            }
        }
        if (!is_request)
            amount += size;
        is_request = 0;
        block++;
    } while (size == SEGSIZE || block == 1);
  abort:
    fclose(file);
    stopclock();
    //if (amount > 0)
    //    printstats("Sent", amount);
    return amount;
}
Exemple #5
0
/*
 * Receive a file.
 */
int tftp_recvfile(int f, union sock_addr *peeraddr,
		   int fd, const char *name, const char *mode)
{
    struct tftphdr *ap;
    struct tftphdr *dp;
    int n;
    volatile u_short block;
    volatile int size, firsttrip;
    volatile unsigned long amount;
    union sock_addr from;
    socklen_t fromlen;
    FILE *file;
    volatile int convert;       /* true if converting crlf -> lf */
    u_short dp_opcode, dp_block;

    startclock();
    dp = w_init();
    ap = (struct tftphdr *)ackbuf;
    convert = !strcmp(mode, "netascii");
    file = fdopen(fd, convert ? "wt" : "wb");
    block = 1;
    firsttrip = 1;
    amount = 0;

    bsd_signal(SIGALRM, timer);
    do {
        if (firsttrip) {
            size = makerequest(RRQ, name, ap, mode);
            firsttrip = 0;
        } else {
            ap->th_opcode = htons((u_short) ACK);
            ap->th_block = htons((u_short) block);
            size = 4;
            block++;
        }
        timeout = 0;
        (void)sigsetjmp(timeoutbuf, 1);
      send_ack:
        if (trace)
            tpacket("sent", ap, size);
        if (sendto(f, ackbuf, size, 0, &(peeraddr->sa),
                   SOCKLEN(peeraddr)) != size) {
            alarm(0);
            perror("tftp: sendto");
            goto abort;
        }
        write_behind(file, convert);
        for (;;) {
            alarm(rexmtval);
            do {
                fromlen = sizeof(from);
                n = recvfrom(f, dp, PKTSIZE, 0,
                             &from.sa, &fromlen);
            } while (n <= 0);
            alarm(0);
            if (n < 0) {
                perror("tftp: recvfrom");
                goto abort;
            }
            sa_set_port(peeraddr, SOCKPORT(&from));  /* added */
            if (trace)
                tpacket("received", dp, n);
            /* should verify client address */
            dp_opcode = ntohs((u_short) dp->th_opcode);
            dp_block = ntohs((u_short) dp->th_block);
            if (dp_opcode == ERROR) {
                printf("Error code %d: %s\n", dp_block, dp->th_msg);
                goto abort;
            }
            if (dp_opcode == DATA) {
                int j;

                if (dp_block == block) {
                    break;      /* have next packet */
                }
                /* On an error, try to synchronize
                 * both sides.
                 */
                j = synchnet(f);
                if (j && trace) {
                    printf("discarded %d packets\n", j);
                }
                if (dp_block == (block - 1)) {
                    goto send_ack;      /* resend ack */
                }
            }
        }
        /*      size = write(fd, dp->th_data, n - 4); */
        size = writeit(file, &dp, n - 4, convert);
        if (size < 0) {
            nak(f, peeraddr, errno + 100, NULL);
            break;
        }
        amount += size;
    } while (size == SEGSIZE);
  abort:                       /* ok to ack, since user */
    ap->th_opcode = htons((u_short) ACK);       /* has seen err msg */
    ap->th_block = htons((u_short) block);
    (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)peeraddr,
                 SOCKLEN(peeraddr));
    write_behind(file, convert);        /* flush last buffer */
    fclose(file);
    stopclock();
    //if (amount > 0)
    //    printstats("Received", amount);
    return amount;
}
Exemple #6
0
/*
 * Send the requested file.
 */
void
sendfile(int fd, char *name, char *mode)
{
	register struct tftphdr *ap;       /* data and ack packets */
	struct tftphdr *dp;
	volatile int block = 0, size = 0;
	int n;
	volatile unsigned long amount = 0;
	struct sockaddr_in from;
	socklen_t fromlen;
	volatile int convert;            /* true if doing nl->crlf conversion */
	FILE *file;

	startclock();           /* start stat's clock */
	dp = r_init();          /* reset fillbuf/read-ahead code */
	ap = (struct tftphdr *)ackbuf;
	file = fdopen(fd, "r");
	convert = !strcmp(mode, "netascii");

	signal(SIGALRM, timer);
	do {
		if (block == 0)
			size = makerequest(WRQ, name, dp, mode) - 4;
		else {
		/*      size = read(fd, dp->th_data, SEGSIZE);   */
			size = readit(file, &dp, convert);
			if (size < 0) {
				nak(errno + 100);
				break;
			}
			dp->th_opcode = htons((u_short)DATA);
			dp->th_block = htons((u_short)block);
		}
		timeout = 0;
		(void) sigsetjmp(timeoutbuf, 1);
send_data:
		if (trace)
			tpacket("sent", dp, size + 4);
		n = sendto(f, dp, size + 4, 0,
		    (struct sockaddr *)&s_inn, sizeof(s_inn));
		if (n != size + 4) {
			perror("tftp: sendto");
			goto abort;
		}
		read_ahead(file, convert);
		for ( ; ; ) {
			alarm(rexmtval);
			do {
				fromlen = sizeof (from);
				n = recvfrom(f, ackbuf, sizeof (ackbuf), 0,
				    (struct sockaddr *)&from, &fromlen);
			} while (n <= 0);
			alarm(0);
			if (n < 0) {
				perror("tftp: recvfrom");
				goto abort;
			}
			s_inn.sin_port = from.sin_port;   /* added */
			if (trace)
				tpacket("received", ap, n);
			/* should verify packet came from server */
			ap->th_opcode = ntohs(ap->th_opcode);
			ap->th_block = ntohs(ap->th_block);
			if (ap->th_opcode == ERROR) {
				printf("Error code %d: %s\n", ap->th_code,
					ap->th_msg);
				goto abort;
			}
			if (ap->th_opcode == ACK) {
				volatile int j = 0;

				if (ap->th_block == block) {
					break;
				}
				/* On an error, try to synchronize
				 * both sides.
				 */
				j = synchnet(f);
				if (j && trace) {
					printf("discarded %d packets\n",
							j);
				}
				if (ap->th_block == (block-1)) {
					goto send_data;
				}
			}
		}
		if (block > 0)
			amount += size;
		block++;
	} while (size == SEGSIZE || block == 1);
abort:
	fclose(file);
	stopclock();
	if (amount > 0)
		printstats("Sent", amount);
}
Exemple #7
0
static int
do_chunk(
    int			infd,
    struct databuf *	db)
{
    size_t nread;
    char header_buf[DISK_BLOCK_BYTES];

    startclock();

    dumpsize = dumpbytes = filesize = (off_t)0;
    headersize = 0;
    memset(header_buf, 0, sizeof(header_buf));

    /*
     * The first thing we should receive is the file header, which we
     * need to save into "file", as well as write out.  Later, the
     * chunk code will rewrite it.
     */
    nread = full_read(infd, header_buf, SIZEOF(header_buf));
    if (nread != sizeof(header_buf)) {
        if(errno != 0) {
            errstr = vstrallocf(_("cannot read header: %s"), strerror(errno));
        } else {
            errstr = vstrallocf(_("cannot read header: got %zd bytes instead of %zd"),
                                nread, sizeof(header_buf));
        }
        return 0;
    }
    parse_file_header(header_buf, &file, (size_t)nread);
    if(write_tapeheader(db->fd, &file)) {
        int save_errno = errno;
        char *m = vstrallocf(_("write_tapeheader file %s: %s"),
                             db->filename, strerror(errno));
        errstr = quote_string(m);
        amfree(m);
        if(save_errno == ENOSPC) {
            putresult(NO_ROOM, "%s %lld\n", handle,
                      (long long)(db->use+db->split_size-dumpsize));
        }
        return 0;
    }
    dumpsize += (off_t)DISK_BLOCK_KB;
    filesize = (off_t)DISK_BLOCK_KB;
    headersize += DISK_BLOCK_KB;

    /*
     * We've written the file header.  Now, just write data until the
     * end.
     */
    while ((nread = full_read(infd, db->buf,
                              (size_t)(db->datalimit - db->datain))) > 0) {
        db->datain += nread;
        while(db->dataout < db->datain) {
            if(!databuf_flush(db)) {
                return 0;
            }
        }
    }
    while(db->dataout < db->datain) {
        if(!databuf_flush(db)) {
            return 0;
        }
    }
    if(dumpbytes > (off_t)0) {
        dumpsize += (off_t)1;			/* count partial final KByte */
        filesize += (off_t)1;
    }
    return 1;
}
Exemple #8
0
int
main(
    int		argc,
    char **	argv)
{
    char *line = NULL;
    char *qdisk = NULL;
    char *qamdevice = NULL;
    char *optstr = NULL;
    char *err_extra = NULL;
    char *s, *fp;
    int ch;
    dle_t *dle = NULL;
    int level;
    GSList *errlist;
    level_t *alevel;

    if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
	printf("selfcheck-%s\n", VERSION);
	return (0);
    }

    /* 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(-1, 0);
    openbsd_fd_inform();
    safe_cd();

    set_pname("selfcheck");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    add_amanda_log_handler(amanda_log_stderr);
    add_amanda_log_handler(amanda_log_syslog);
    dbopen(DBG_SUBDIR_CLIENT);
    startclock();
    dbprintf(_("version %s\n"), VERSION);
    g_printf("OK version %s\n", VERSION);

    print_platform();
    if(argc > 2 && g_str_equal(argv[1], "amandad")) {
	amandad_auth = g_strdup(argv[2]);
    }

    config_init(CONFIG_INIT_CLIENT, NULL);
    /* (check for config errors comes later) */

    check_running_as(RUNNING_AS_CLIENT_LOGIN);

    our_features = am_init_feature_set();
    our_feature_string = am_feature_to_string(our_features);

    /* handle all service requests */

    /*@ignore@*/
    for(; (line = agets(stdin)) != NULL; free(line)) {
    /*@end@*/
	if (line[0] == '\0')
	    continue;

	if(strncmp_const(line, "OPTIONS ") == 0) {
	    if (g_options) {
		g_printf(_("ERROR [Multiple OPTIONS line in selfcheck input]\n"));
		error(_("Multiple OPTIONS line in selfcheck input\n"));
		/*NOTREACHED*/
	    }
	    g_options = parse_g_options(line+8, 1);
	    if(!g_options->hostname) {
		g_options->hostname = g_malloc(MAX_HOSTNAME_LENGTH+1);
		gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH);
		g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0';
	    }

	    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);
	    }
	    g_printf("\n");
	    fflush(stdout);

	    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(get_config_name(), DBG_SUBDIR_CLIENT);
	    }

	    /* check for any config errors now */
	    if (config_errors(&errlist) >= CFGERR_ERRORS) {
		char *errstr = config_errors_to_error_string(errlist);
		g_printf("%s\n", errstr);
		amfree(errstr);
		amfree(line);
		dbclose();
		return 1;
	    }

	    if (am_has_feature(g_options->features, fe_req_xml)) {
		break;
	    }
	    continue;
	}

	dle = alloc_dle();
	s = line;
	ch = *s++;

	skip_whitespace(s, ch);			/* find program name */
	if (ch == '\0') {
	    goto err;				/* no program */
	}
	dle->program = s - 1;
	skip_non_whitespace(s, ch);
	s[-1] = '\0';				/* terminate the program name */

	dle->program_is_application_api = 0;
	if(g_str_equal(dle->program, "APPLICATION")) {
	    dle->program_is_application_api = 1;
	    skip_whitespace(s, ch);		/* find dumper name */
	    if (ch == '\0') {
		goto err;			/* no program */
	    }
	    dle->program = s - 1;
	    skip_non_whitespace(s, ch);
	    s[-1] = '\0';			/* terminate the program name */
	}

	if(strncmp_const(dle->program, "CALCSIZE") == 0) {
	    skip_whitespace(s, ch);		/* find program name */
	    if (ch == '\0') {
		goto err;			/* no program */
	    }
	    dle->program = s - 1;
	    skip_non_whitespace(s, ch);
	    s[-1] = '\0';
	    dle->estimatelist = g_slist_append(dle->estimatelist,
					       GINT_TO_POINTER(ES_CALCSIZE));
	}
	else {
	    dle->estimatelist = g_slist_append(dle->estimatelist,
					       GINT_TO_POINTER(ES_CLIENT));
	}

	skip_whitespace(s, ch);			/* find disk name */
	if (ch == '\0') {
	    goto err;				/* no disk */
	}
	qdisk = s - 1;
	skip_quoted_string(s, ch);
	s[-1] = '\0';				/* terminate the disk name */
	dle->disk = unquote_string(qdisk);

	skip_whitespace(s, ch);                 /* find the device or level */
	if (ch == '\0') {
	    goto err;				/* no device or level */
	}
	if(!isdigit((int)s[-1])) {
	    fp = s - 1;
	    skip_quoted_string(s, ch);
	     s[-1] = '\0';			/* terminate the device */
	    qamdevice = g_strdup(fp);
	    dle->device = unquote_string(qamdevice);
	    skip_whitespace(s, ch);		/* find level number */
	}
	else {
	    dle->device = g_strdup(dle->disk);
	    qamdevice = g_strdup(qdisk);
	}
	amfree(qamdevice);

						/* find level number */
	if (ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
	    goto err;				/* bad level */
	}
	alevel = g_new0(level_t, 1);
	alevel->level = level;
	dle->levellist = g_slist_append(dle->levellist, alevel);
	skip_integer(s, ch);

	skip_whitespace(s, ch);
	if (ch && strncmp_const_skip(s - 1, "OPTIONS ", s, ch) == 0) {
	    skip_whitespace(s, ch);		/* find the option string */
	    if(ch == '\0') {
		goto err;			/* bad options string */
	    }
	    optstr = s - 1;
	    skip_quoted_string(s, ch);
	    s[-1] = '\0';			/* terminate the options */
	    parse_options(optstr, dle, g_options->features, 1);
	    /*@ignore@*/

	    check_options(dle);
	    check_disk(dle);

	    /*@end@*/
	} else if (ch == '\0') {
	    /* check all since no option */
	    need_samba=1;
	    need_rundump=1;
	    need_dump=1;
	    need_restore=1;
	    need_vdump=1;
	    need_vrestore=1;
	    need_xfsdump=1;
	    need_xfsrestore=1;
	    need_vxdump=1;
	    need_vxrestore=1;
	    need_runtar=1;
	    need_gnutar=1;
	    need_compress_path=1;
	    need_calcsize=1;
	    need_global_check=1;
	    /*@ignore@*/
	    check_disk(dle);
	    /*@end@*/
	} else {
	    goto err;				/* bad syntax */
	}
	free_dle(dle);
	dle = NULL;
    }
    if (g_options == NULL) {
	g_printf(_("ERROR [Missing OPTIONS line in selfcheck input]\n"));
	error(_("Missing OPTIONS line in selfcheck input\n"));
	/*NOTREACHED*/
    }

    if (am_has_feature(g_options->features, fe_req_xml)) {
	char  *errmsg = NULL;
	dle_t *dles, *dle, *dle_next;

	dles = amxml_parse_node_FILE(stdin, &errmsg);
	if (errmsg) {
	    err_extra = errmsg;
	    goto err;
	}
	if (merge_dles_properties(dles, 1) == 0) {
	    goto checkoverall;
	}
	for (dle = dles; dle != NULL; dle = dle->next) {
	    run_client_scripts(EXECUTE_ON_PRE_HOST_AMCHECK, g_options, dle,
			       stdout);
	}
	for (dle = dles; dle != NULL; dle = dle->next) {
	    check_options(dle);
	    run_client_scripts(EXECUTE_ON_PRE_DLE_AMCHECK, g_options, dle,
			       stdout);
	    check_disk(dle);
	    run_client_scripts(EXECUTE_ON_POST_DLE_AMCHECK, g_options, dle,
			       stdout);
	}
	for (dle = dles; dle != NULL; dle = dle->next) {
	    run_client_scripts(EXECUTE_ON_POST_HOST_AMCHECK, g_options, dle,
			       stdout);
	}
	for (dle = dles; dle != NULL; dle = dle_next) {
	    dle_next = dle->next;
	    free_dle(dle);
	}
    }

checkoverall:
    check_overall();

    amfree(line);
    amfree(our_feature_string);
    am_release_feature_set(our_features);
    our_features = NULL;
    free_g_options(g_options);

    dbclose();
    return 0;

 err:
    if (err_extra) {
	g_printf(_("ERROR [FORMAT ERROR IN REQUEST PACKET %s]\n"), err_extra);
	dbprintf(_("REQ packet is bogus: %s\n"), err_extra);
    } else {
	g_printf(_("ERROR [FORMAT ERROR IN REQUEST PACKET]\n"));
	dbprintf(_("REQ packet is bogus\n"));
    }
    amfree(err_extra);
    amfree(line);
    if (dle)
	free_dle(dle);
    dbclose();
    return 1;
}