Esempio n. 1
0
static pid_t
run_sort(
    int   fd_in,
    int  *fd_out,
    int  *fd_err,
    char *source_filename,
    char *dest_filename)
{
    int   in_fd;
    int   out_fd;
    int   create_pipe = STDERR_PIPE;
    pid_t pid;
    gchar *tmpdir = getconf_str(CNF_TMPDIR);

    if (fd_in == -1) {
	in_fd = open(source_filename, O_RDONLY);
    } else {
	in_fd = fd_in;
    }

    if (dest_filename) {
	out_fd = open(dest_filename, O_WRONLY|O_CREAT, S_IRUSR);
    } else {
	create_pipe |= STDOUT_PIPE;
    }


    pid = pipespawn(SORT_PATH, create_pipe, 0,
		    &in_fd, &out_fd, fd_err,
		    SORT_PATH, "-T", tmpdir, NULL);
    close(in_fd);
    if (dest_filename) {
	close(out_fd);
    } else {
	*fd_out = out_fd;
    }
    return pid;
}
Esempio n. 2
0
static pid_t
run_uncompress(
    int   fd_in,
    int  *fd_out,
    int  *fd_err,
    char *source_filename,
    char *dest_filename)
{
    int   in_fd;
    int   out_fd;
    int   create_pipe = STDERR_PIPE;
    pid_t pid;

    if (fd_in == -1) {
	in_fd = open(source_filename, O_RDONLY);
    } else {
	in_fd = fd_in;
    }

    if (dest_filename) {
	out_fd = open(dest_filename, O_WRONLY|O_CREAT, S_IRUSR);
    } else {
	create_pipe |= STDOUT_PIPE;
    }

    pid = pipespawn(UNCOMPRESS_PATH, create_pipe, 0,
		    &in_fd, &out_fd, fd_err,
		    UNCOMPRESS_PATH, UNCOMPRESS_OPT, NULL);
    close(in_fd);
    if (dest_filename) {
	close(out_fd);
    } else {
	*fd_out = out_fd;
    }
    return pid;
}
Esempio n. 3
0
/*
 *  doing similar to $ gtar | compression | encryption 
 */
static void
start_backup(
    dle_t      *dle,
    char       *host,
    int		dataf,
    int		mesgf,
    int		indexf)
{
    char tmppath[PATH_MAX];
    int dumpin, dumpout, compout;
    char *cmd = NULL;
    char *indexcmd = NULL;
    char *dirname = NULL;
    int l;
    char dumptimestr[80] = "UNUSED";
    struct tm *gmtm;
    amandates_t *amdates = NULL;
    time_t prev_dumptime = 0;
    char *error_pn = NULL;
    char *compopt  = NULL;
    char *encryptopt = skip_argument;
    char *tquoted;
    char *fquoted;
    char *qdisk;
    int infd, outfd;
    ssize_t nb;
    char buf[32768];
    char *amandates_file = NULL;
    am_level_t *alevel = (am_level_t *)dle->levellist->data;
    int      level  = alevel->level;
    int        native_pipe[2];
    int        client_pipe[2];
    int        data_out;

    have_filter = FALSE;
    crc32_init(&native_crc.crc);
    crc32_init(&client_crc.crc);

    /* create pipes to compute the native CRC */
    if (pipe(native_pipe) < 0) {
	char  *errmsg;
	char  *qerrmsg;
	errmsg = g_strdup_printf(_("Program '%s': can't create pipe"),
				 dle->program);
	qerrmsg = quote_string(errmsg);
	fdprintf(mesgf, _("sendbackup: error [%s]\n"), errmsg);
	dbprintf(_("ERROR %s\n"), qerrmsg);
	amfree(qerrmsg);
	amfree(errmsg);
	return;
    }

    if (dle->encrypt == ENCRYPT_CUST ||
        dle->compress == COMP_FAST ||
        dle->compress == COMP_BEST ||
        dle->compress == COMP_CUST) {

        have_filter = TRUE;

        /* create pipes to compute the client CRC */
        if (pipe(client_pipe) < 0) {
            char  *errmsg;
            char  *qerrmsg;
            errmsg = g_strdup_printf(_("Application '%s': can't create pipe"),
                                     dle->program);
            qerrmsg = quote_string(errmsg);
            fdprintf(mesgf, _("sendbackup: error [%s]\n"), errmsg);
            dbprintf(_("ERROR %s\n"), qerrmsg);
            amfree(qerrmsg);
            amfree(errmsg);
            return;
        }
        data_out = client_pipe[1];
	client_pipe[1] = -1;
    } else {
        data_out = dataf;
	dataf = -1;
    }

    error_pn = g_strconcat(get_pname(), "-smbclient", NULL);

    qdisk = quote_string(dle->disk);
    dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, level);

    g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
	    get_pname(), host, qdisk, level);

     /*  apply client-side encryption here */
     if ( dle->encrypt == ENCRYPT_CUST ) {
        encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
			&compout, &data_out, &mesgf,
			dle->clnt_encrypt, encryptopt, NULL);
        dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
	aclose(data_out);
    } else {
        compout = data_out;
	data_out = -1;
        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, &mesgf,
			    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);
	}
	aclose(compout);
     } else if (dle->compress == COMP_CUST) {
        compopt = skip_argument;
	comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
			    &dumpout, &compout, &mesgf,
			    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);
	}
	aclose(compout);
    } else {
	dumpout = compout;
	compout = -1;
	comppid = -1;
    }

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

#ifdef SAMBA_CLIENT							/* { */
    if (dle->device[0] == '/' && dle->device[1]=='/')
	amfree(incrname);
    else
#endif									/* } */
    if (gnutar_list_dir) {
	char *basename = NULL;
	char number[NUM_STR_SIZE];
	char *inputname = NULL;
	int baselevel;
	char *sdisk = sanitise_filename(dle->disk);

	basename = g_strjoin(NULL, gnutar_list_dir,
			     "/",
			     host,
			     sdisk,
			     NULL);
	amfree(sdisk);

	g_snprintf(number, sizeof(number), "%d", level);
	incrname = g_strjoin(NULL, basename, "_", number, ".new", NULL);
	unlink(incrname);

	/*
	 * Open the listed incremental file from the previous level.  Search
	 * backward until one is found.  If none are found (which will also
	 * be true for a level 0), arrange to read from /dev/null.
	 */
	baselevel = level;
	infd = -1;
	while (infd == -1) {
	    if (--baselevel >= 0) {
		g_snprintf(number, sizeof(number), "%d", baselevel);
		g_free(inputname);
		inputname = g_strconcat(basename, "_", number, NULL);
	    } else {
		g_free(inputname);
		inputname = g_strdup("/dev/null");
	    }
	    if ((infd = open(inputname, O_RDONLY)) == -1) {
		int save_errno = errno;
		char *qname = quote_string(inputname);

		dbprintf(_("gnutar: error opening '%s': %s\n"),
			  qname,
			  strerror(save_errno));
		if (baselevel < 0) {
		    error(_("error [opening '%s': %s]"), qname, strerror(save_errno));
		    /*NOTREACHED*/
		}
		amfree(qname);
	    }
	}

	/*
	 * Copy the previous listed incremental file to the new one.
	 */
	if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) {
	    error(_("error [opening '%s': %s]"), incrname, strerror(errno));
	    /*NOTREACHED*/
	}

	while ((nb = read(infd, &buf, sizeof(buf))) > 0) {
	    if (full_write(outfd, &buf, (size_t)nb) < (size_t)nb) {
		error(_("error [writing to '%s': %s]"), incrname,
		       strerror(errno));
		/*NOTREACHED*/
	    }
	}

	if (nb < 0) {
	    error(_("error [reading from '%s': %s]"), inputname, strerror(errno));
	    /*NOTREACHED*/
	}

	if (close(infd) != 0) {
	    error(_("error [closing '%s': %s]"), inputname, strerror(errno));
	    /*NOTREACHED*/
	}
	if (close(outfd) != 0) {
	    error(_("error [closing '%s': %s]"), incrname, strerror(errno));
	    /*NOTREACHED*/
	}

	tquoted = quote_string(incrname);
	if(baselevel >= 0) {
	    fquoted = quote_string(inputname);
	    dbprintf(_("doing level %d dump as listed-incremental from '%s' to '%s'\n"),
		     level, fquoted, tquoted);
	    amfree(fquoted);
	} else {
	    dbprintf(_("doing level %d dump as listed-incremental to '%s'\n"),
		     level, tquoted);
	}
	amfree(tquoted);
	amfree(inputname);
	amfree(basename);
    } else {
	/* no gnutar-listdir, so we're using amandates */

	/* find previous dump time, failing completely if there's a problem */
	amandates_file = getconf_str(CNF_AMANDATES);
	if(!start_amandates(amandates_file, 0)) {
	    error(_("error [opening %s: %s]"), amandates_file, strerror(errno));
	    /*NOTREACHED*/
	}

	amdates = amandates_lookup(dle->disk);

	prev_dumptime = EPOCH;
	for(l = 0; l < level; l++) {
	    if(amdates->dates[l] > prev_dumptime)
		prev_dumptime = amdates->dates[l];
	}

	finish_amandates();
	free_amandates();

	gmtm = gmtime(&prev_dumptime);
	g_snprintf(dumptimestr, sizeof(dumptimestr),
		    "%04d-%02d-%02d %2d:%02d:%02d GMT",
		    gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
		    gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);

	dbprintf(_("gnutar: doing level %d dump from amandates-derived date: %s\n"),
		  level, dumptimestr);
    }

    dirname = amname_to_dirname(dle->device);

    cur_dumptime = time(0);
    cur_level = level;
    cur_disk = g_strdup(dle->disk);
#ifdef GNUTAR
#  define PROGRAM_GNUTAR GNUTAR
#else
#  define PROGRAM_GNUTAR "tar"
#endif
    indexcmd = g_strjoin(NULL, 
			 PROGRAM_GNUTAR,
			 " -tf", " -",
			 " 2>/dev/null",
			 " | sed", " -e",
			 " \'s/^\\.//\'",
			 NULL);

#ifdef SAMBA_CLIENT							/* { */
    /* Use sambatar if the disk to back up is a PC disk */
    if (dle->device[0] == '/' && dle->device[1]=='/') {
	char *sharename = NULL, *user_and_password = NULL, *domain = NULL;
	char *share = NULL, *subdir = NULL;
	char *pwtext = NULL;
	char *taropt;
	int passwdf = -1;
	size_t lpass;
	size_t pwtext_len;
	char *pw_fd_env;

	parsesharename(dle->device, &share, &subdir);
	if (!share) {
	    amfree(share);
	    amfree(subdir);
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("cannot parse disk entry %s for share/subdir"), qdisk);
	    /*NOTREACHED*/
	}
	if ((subdir) && (SAMBA_VERSION < 2)) {
	    amfree(share);
	    amfree(subdir);
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("subdirectory specified for share %s but samba not v2 or better"), qdisk);
	    /*NOTREACHED*/
	}
	if ((user_and_password = findpass(share, &domain)) == NULL) {
	    if(domain) {
		memset(domain, '\0', strlen(domain));
		amfree(domain);
	    }
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("error [invalid samba host or password not found?]"));
	    /*NOTREACHED*/
	}
	lpass = strlen(user_and_password);
	if ((pwtext = strchr(user_and_password, '%')) == NULL) {
	    memset(user_and_password, '\0', lpass);
	    amfree(user_and_password);
	    if(domain) {
		memset(domain, '\0', strlen(domain));
		amfree(domain);
	    }
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("password field not \'user%%pass\' for %s"), qdisk);
	    /*NOTREACHED*/
	}
	*pwtext++ = '\0';
	pwtext_len = strlen(pwtext);
	if ((sharename = makesharename(share, 0)) == 0) {
	    memset(user_and_password, '\0', lpass);
	    amfree(user_and_password);
	    if(domain) {
		memset(domain, '\0', strlen(domain));
		amfree(domain);
	    }
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("error [can't make share name of %s]"), share);
	    /*NOTREACHED*/
	}

	taropt = g_strdup("-T");
	if(dle->exclude_file && dle->exclude_file->nb_element == 1) {
	    strappend(taropt, "X");
	}
#if SAMBA_VERSION >= 2
	strappend(taropt, "q");
#endif
	strappend(taropt, "c");
	if (level != 0) {
	    strappend(taropt, "g");
	} else if (dle->record) {
	    strappend(taropt, "a");
	}

	if (subdir) {
	    dbprintf(_("gnutar: backup of %s/%s\n"), sharename, subdir);
	} else {
	    dbprintf(_("gnutar: backup of %s\n"), sharename);
	}

	program->backup_name = program->restore_name = SAMBA_CLIENT;
	cmd = g_strdup(program->backup_name);
	info_tapeheader(dle);

	start_index(dle->create_index, native_pipe[1], mesgf, indexf, indexcmd);

	if (pwtext_len > 0) {
	    pw_fd_env = "PASSWD_FD";
	} else {
	    pw_fd_env = "dummy_PASSWD_FD";
	}
	dumppid = pipespawn(cmd, STDIN_PIPE|PASSWD_PIPE, 0,
			    &dumpin, &native_pipe[1], &mesgf,
			    pw_fd_env, &passwdf,
			    "smbclient",
			    sharename,
			    *user_and_password ? "-U" : skip_argument,
			    *user_and_password ? user_and_password : skip_argument,
			    "-E",
			    domain ? "-W" : skip_argument,
			    domain ? domain : skip_argument,
#if SAMBA_VERSION >= 2
			    subdir ? "-D" : skip_argument,
			    subdir ? subdir : skip_argument,
#endif
			    "-d0",
			    taropt,
			    "-",
			    dle->exclude_file && dle->exclude_file->nb_element == 1 ? dle->exclude_file->first->name : skip_argument,
			    NULL);
	if(domain) {
	    memset(domain, '\0', strlen(domain));
	    amfree(domain);
	}
	if(pwtext_len > 0 && full_write(passwdf, pwtext, pwtext_len) < pwtext_len) {
	    int save_errno = errno;

	    aclose(passwdf);
	    memset(user_and_password, '\0', lpass);
	    amfree(user_and_password);
	    set_pname(error_pn);
	    amfree(error_pn);
	    error(_("error [password write failed: %s]"), strerror(save_errno));
	    /*NOTREACHED*/
	}
	memset(user_and_password, '\0', lpass);
	amfree(user_and_password);
	aclose(passwdf);
	amfree(sharename);
	amfree(share);
	amfree(subdir);
	amfree(taropt);
	tarpid = dumppid;
    } else
#endif			/*end of samba */
    {

	int nb_exclude = 0;
	int nb_include = 0;
	GPtrArray *argv_ptr = g_ptr_array_new();
	char *file_exclude = NULL;
	char *file_include = NULL;
	messagelist_t mlist = NULL;

	if (dle->exclude_file) nb_exclude+=dle->exclude_file->nb_element;
	if (dle->exclude_list) nb_exclude+=dle->exclude_list->nb_element;
	if (dle->include_file) nb_include+=dle->include_file->nb_element;
	if (dle->include_list) nb_include+=dle->include_list->nb_element;

	if (nb_exclude > 0) file_exclude = build_exclude(dle, &mlist);
	if (nb_include > 0) file_include = build_include(dle, dirname, &mlist);
	g_slist_free(mlist); // MUST also free the message

	cmd = g_strjoin(NULL, amlibexecdir, "/", "runtar", NULL);
	info_tapeheader(dle);

	start_index(dle->create_index, native_pipe[1], mesgf, indexf, indexcmd);

	g_ptr_array_add(argv_ptr, g_strdup("runtar"));
	if (g_options->config)
	    g_ptr_array_add(argv_ptr, g_strdup(g_options->config));
	else
	    g_ptr_array_add(argv_ptr, g_strdup("NOCONFIG"));
#ifdef GNUTAR
	g_ptr_array_add(argv_ptr, g_strdup(GNUTAR));
#else
	g_ptr_array_add(argv_ptr, g_strdup("tar"));
#endif
	g_ptr_array_add(argv_ptr, g_strdup("--create"));
	g_ptr_array_add(argv_ptr, g_strdup("--file"));
	g_ptr_array_add(argv_ptr, g_strdup("-"));
	g_ptr_array_add(argv_ptr, g_strdup("--directory"));
	canonicalize_pathname(dirname, tmppath);
	g_ptr_array_add(argv_ptr, g_strdup(tmppath));
	g_ptr_array_add(argv_ptr, g_strdup("--one-file-system"));
	if (gnutar_list_dir && incrname) {
	    g_ptr_array_add(argv_ptr, g_strdup("--listed-incremental"));
	    g_ptr_array_add(argv_ptr, g_strdup(incrname));
	} else {
	    g_ptr_array_add(argv_ptr, g_strdup("--incremental"));
	    g_ptr_array_add(argv_ptr, g_strdup("--newer"));
	    g_ptr_array_add(argv_ptr, g_strdup(dumptimestr));
	}
#ifdef ENABLE_GNUTAR_ATIME_PRESERVE
	/* --atime-preserve causes gnutar to call
	 * utime() after reading files in order to
	 * adjust their atime.  However, utime()
	 * updates the file's ctime, so incremental
	 * dumps will think the file has changed. */
	g_ptr_array_add(argv_ptr, g_strdup("--atime-preserve"));
#endif
	g_ptr_array_add(argv_ptr, g_strdup("--sparse"));
	g_ptr_array_add(argv_ptr, g_strdup("--ignore-failed-read"));
	g_ptr_array_add(argv_ptr, g_strdup("--totals"));

	if(file_exclude) {
	    g_ptr_array_add(argv_ptr, g_strdup("--exclude-from"));
	    g_ptr_array_add(argv_ptr, g_strdup(file_exclude));
	}

	if(file_include) {
	    g_ptr_array_add(argv_ptr, g_strdup("--files-from"));
	    g_ptr_array_add(argv_ptr, g_strdup(file_include));
	}
	else {
	    g_ptr_array_add(argv_ptr, g_strdup("."));
	}
	    g_ptr_array_add(argv_ptr, NULL);
	dumppid = pipespawnv(cmd, STDIN_PIPE, 0,
			     &dumpin, &native_pipe[1], &mesgf,
			     (char **)argv_ptr->pdata);
	tarpid = dumppid;
	amfree(file_exclude);
	amfree(file_include);
	g_ptr_array_free_full(argv_ptr);
    }
    dbprintf(_("gnutar: %s: pid %ld\n"), cmd, (long)dumppid);

    amfree(qdisk);
    amfree(dirname);
    amfree(cmd);
    amfree(indexcmd);
    amfree(error_pn);

    /* close the write ends of the pipes */

    aclose(dumpin);
    aclose(native_pipe[1]);
    aclose(mesgf);
    if (dle->create_index)
	aclose(indexf);

    if (shm_control_name) {
	shm_ring = shm_ring_link(shm_control_name);
	shm_ring_producer_set_size(shm_ring, NETWORK_BLOCK_BYTES*16, NETWORK_BLOCK_BYTES*4);
	native_crc.in  = native_pipe[0];
	if (!have_filter) {
	    native_crc.out = dumpout;
	    native_crc.shm_ring = shm_ring;
	    native_crc.thread = g_thread_create(handle_crc_to_shm_ring_thread,
					(gpointer)&native_crc, TRUE, NULL);
	} else {
	    native_crc.out = dumpout;
	    native_crc.thread = g_thread_create(handle_crc_thread,
					(gpointer)&native_crc, TRUE, NULL);
	    client_crc.in  = client_pipe[0];
	    client_crc.out = dataf;
	    client_crc.shm_ring = shm_ring;
	    client_crc.thread = g_thread_create(handle_crc_to_shm_ring_thread,
					(gpointer)&client_crc, TRUE, NULL);
	}
    } else {
	native_crc.in  = native_pipe[0];
	native_crc.out = dumpout;
	native_crc.thread = g_thread_create(handle_crc_thread,
					(gpointer)&native_crc, TRUE, NULL);

	if (have_filter) {
	    client_crc.in  = client_pipe[0];
	    client_crc.out = dataf;
	    client_crc.thread = g_thread_create(handle_crc_thread,
					(gpointer)&client_crc, TRUE, NULL);
	}
    }
}
Esempio n. 4
0
static void
start_backup(
    dle_t      *dle,
    char       *host,
    int		dataf,
    int		mesgf,
    int		indexf)
{
    int dumpin, dumpout, compout;
    char *dumpkeys = NULL;
    char *device = NULL;
    char *fstype = NULL;
    char *cmd = NULL;
    char *cmdX = NULL;
    char *indexcmd = NULL;
    char level_str[NUM_STR_SIZE];
    char *compopt  = NULL;
    char *encryptopt = skip_argument;
    char *qdisk;
    char *config;
    am_level_t *alevel = (am_level_t *)dle->levellist->data;
    int      level  = alevel->level;

    g_snprintf(level_str, sizeof(level_str), "%d", level);

    qdisk = quote_string(dle->disk);
    dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, level);

    g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
	    get_pname(), host, qdisk, level);
    amfree(qdisk);

    /*  apply client-side encryption here */
    if (dle->encrypt == ENCRYPT_CUST ) {
        encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
	                   &compout, &dataf, &mesgf,
	                   dle->clnt_encrypt, encryptopt, NULL);
        dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
    } else {
        compout = dataf;
        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, &mesgf,
			    COMPRESS_PATH, compopt, NULL);
	dbprintf(_("dump: pid %ld: %s"), (long)comppid, COMPRESS_PATH);
	if(compopt != skip_argument) {
	    dbprintf(" %s", compopt);
	}
	dbprintf("\n");
     } else if (dle->compress == COMP_CUST) {
        compopt = skip_argument;
	comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
			    &dumpout, &compout, &mesgf,
			    dle->compprog, compopt, NULL);
	dbprintf(_("gnutar-cust: pid %ld: %s"),
		(long)comppid, dle->compprog);
	if(compopt != skip_argument) {
	    dbprintf(" %s", compopt);
	}
	dbprintf("\n");
    } else {
	dumpout = compout;
	comppid = -1;
    }

    /* invoke dump */
    device = amname_to_devname(dle->device);
    fstype = amname_to_fstype(dle->device);

    dbprintf(_("dumping device '%s' with '%s'\n"), device, fstype);

#if defined(USE_RUNDUMP) || !defined(DUMP)
    cmd = g_strjoin(NULL, amlibexecdir, "/", "rundump", NULL);
    cmdX = cmd;
    if (g_options->config)
	config = g_options->config;
    else
	config = "NOCONFIG";
#else
    cmd = g_strdup(DUMP);
    cmdX = skip_argument;
    config = skip_argument;
#endif

#ifndef AIX_BACKUP					/* { */
    /* normal dump */
#ifdef XFSDUMP						/* { */
#ifdef DUMP						/* { */
    if (g_str_equal(amname_to_fstype(dle->device), "xfs"))
#else							/* } { */
    if (1)
#endif							/* } */
    {
        char *progname;
        g_free(cmd);
        progname = cmd = g_strconcat(amlibexecdir, "/", "rundump", NULL);
	cmdX = cmd;
	if (g_options->config)
	    config = g_options->config;
	else
	    config = "NOCONFIG";

	program->backup_name  = XFSDUMP;
	program->restore_name = XFSRESTORE;

	indexcmd = g_strjoin(NULL, XFSRESTORE, " -t", " -v", " silent", " -",
	    " 2>/dev/null", " | sed", " -e", " \'s/^/\\//\'", NULL);

	info_tapeheader(dle);

	start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

	dumpkeys = g_strdup(level_str);
	dumppid = pipespawn(progname, STDIN_PIPE, 0,
			    &dumpin, &dumpout, &mesgf,
			    cmdX, config,
			    "xfsdump",
			    !dle->record ? "-J" : skip_argument,
			    "-F",
			    "-l", dumpkeys,
			    "-",
			    device,
			    NULL);
    }
    else
#endif							/* } */
#ifdef VXDUMP						/* { */
#ifdef DUMP
    if (g_str_equal(amname_to_fstype(dle->device), "vxfs"))
#else
    if (1)
#endif
    {
char *progname;
#ifdef USE_RUNDUMP
        g_free(cmd);
        progname = cmd = g_strconcat(amlibexecdir, "/", "rundump", NULL);
	cmdX = cmd;
	if (g_options->config)
	    config = g_options->config;
	else
	    config = "NOCONFIG";
#else
	char *progname;
        g_free(cmd);
        progname = cmd = g_strdup(VXDUMP);
	cmdX = skip_argument;
	config = skip_argument;
#endif
	program->backup_name  = VXDUMP;
	program->restore_name = VXRESTORE;

	dumpkeys = g_strjoin(NULL, level_str,
			     !dle->record ? "" : "u",
			     "s",
			     "f",
			     NULL);

	indexcmd = g_strjoin(NULL, VXRESTORE,
			     " -tvf", " -",
			     " 2>/dev/null",
			     " | ",
			     LEAF_AND_DIRS,
			     NULL);
	info_tapeheader(dle);

	start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

	dumppid = pipespawn(progname, STDIN_PIPE, 0,
			    &dumpin, &dumpout, &mesgf, 
			    cmdX, config,
			    "vxdump",
			    dumpkeys,
			    "1048576",
			    "-",
			    device,
			    NULL);
    }
    else
#endif							/* } */

#ifdef VDUMP						/* { */
#ifdef DUMP
    if (g_str_equal(amname_to_fstype(dle->device), "advfs"))
#else
    if (1)
#endif
    {
        g_free(cmd);
        cmd = g_strconcat(amlibexecdir, "/", "rundump", NULL);
	cmdX = cmd;
	if (g_options->config)
	    config = g_options->config;
	else
	    config = "NOCONFIG";
	g_free(device);
	device = g_strdup(amname_to_dirname(dle->device));
	program->backup_name  = VDUMP;
	program->restore_name = VRESTORE;

	dumpkeys = g_strjoin(NULL, level_str,
			     !dle->record ? "" : "u",
			     "b",
			     "f",
			     NULL);

	indexcmd = g_strjoin(NULL, VRESTORE,
			     " -tvf", " -",
			     " 2>/dev/null",
			     " | ",
			     "sed -e \'\n/^\\./ {\ns/^\\.//\ns/, [0-9]*$//\ns/^\\.//\ns/ @-> .*$//\nt\n}\nd\n\'",
			     NULL);
	info_tapeheader(dle);

	start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

	dumppid = pipespawn(cmd, STDIN_PIPE, 0,
			    &dumpin, &dumpout, &mesgf, 
			    cmdX, config,
			    "vdump",
			    dumpkeys,
			    "60",
			    "-",
			    device,
			    NULL);
    }
    else
#endif							/* } */

    {
#ifndef RESTORE
#define RESTORE "restore"
#endif

#ifdef HAVE_HONOR_NODUMP
#  define PARAM_HONOR_NODUMP "h"
#else
#  define PARAM_HONOR_NODUMP ""
#endif

#ifdef __FreeBSD__
# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043)
#  define FREEBSD_EXTRA_KEYS "bL"
# else
#  define FREEBSD_EXTRA_KEYS "b"
# endif
#else
# define FREEBSD_EXTRA_KEYS ""
#endif

	dumpkeys = g_strjoin(NULL, level_str,
			     !dle->record ? "" : "u",
			     FREEBSD_EXTRA_KEYS,
			     "s",
			     PARAM_HONOR_NODUMP,
			     "f",
			     NULL);

	indexcmd = g_strjoin(NULL, RESTORE,
			     " -tvf", " -",
			     " 2>&1",
			     /* not to /dev/null because of DU's dump */
			     " | ",
			     LEAF_AND_DIRS,
			     NULL);
	info_tapeheader(dle);

	start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

	dumppid = pipespawn(cmd, STDIN_PIPE, 0,
			    &dumpin, &dumpout, &mesgf, 
			    cmdX, config,
			    "dump",
			    dumpkeys,
#ifdef __FreeBSD__
			    "64",
#endif
			    "1048576",
#ifdef HAVE_HONOR_NODUMP
			    "0",
#endif
			    "-",
			    device,
			    NULL);
    }
#else							/* } { */
    /* AIX backup program */
    dumpkeys = g_strjoin(NULL, "-",
			 level_str,
			 !dle->record ? "" : "u",
			 "f",
			 NULL);

    indexcmd = g_strjoin(NULL, RESTORE,
			 " -B",
			 " -tvf", " -",
			 " 2>/dev/null",
			 " | ",
			 LEAF_AND_DIRS,
			 NULL);
    info_tapeheader(dle);

    start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);

    dumppid = pipespawn(cmd, STDIN_PIPE, 0,
			&dumpin, &dumpout, &mesgf, 
			cmdX, config,
			"backup",
			dumpkeys,
			"-",
			device,
			NULL);
#endif							/* } */

    amfree(dumpkeys);
    amfree(fstype);
    amfree(device);
    amfree(cmd);
    amfree(indexcmd);

    /* close the write ends of the pipes */

    aclose(dumpin);
    aclose(dumpout);
    aclose(compout);
    aclose(dataf);
    aclose(mesgf);
    if (dle->create_index)
	aclose(indexf);
}
Esempio n. 5
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;
}
Esempio n. 6
0
static void
check_disk(
    dle_t *dle)
{
    char *device = NULL;
    char *err = NULL;
    char *user_and_password = NULL;
    char *domain = NULL;
    char *share = NULL, *subdir = NULL;
    size_t lpass = 0;
    int amode = R_OK;
    int access_result;
    char *access_type;
    char *extra_info = NULL;
    char *qdisk = NULL;
    char *qamdevice = NULL;
    char *qdevice = NULL;

    if (dle->disk) {
	need_global_check=1;
	qdisk = quote_string(dle->disk);
	qamdevice = quote_string(dle->device);
	device = g_strdup("nodevice");
	dbprintf(_("checking disk %s\n"), qdisk);
	if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE) {
	    if (dle->device[0] == '/' && dle->device[1] == '/') {
		err = g_strdup_printf(
		    _("Can't use CALCSIZE for samba estimate, use CLIENT: %s"),
		    dle->device);
		goto common_exit;
	    }
	}

	if (g_str_equal(dle->program, "GNUTAR")) {
            if(dle->device[0] == '/' && dle->device[1] == '/') {
		#ifdef SAMBA_CLIENT
		int nullfd, checkerr;
		int passwdfd;
		char *pwtext;
		size_t pwtext_len;
		pid_t checkpid;
		amwait_t retstat;
		pid_t wpid;
		int rc;
		char *line;
		char *sep;
		FILE *ferr;
		char *pw_fd_env;
		int errdos;

		parsesharename(dle->device, &share, &subdir);
		if (!share) {
		    err = g_strdup_printf(
			      _("cannot parse for share/subdir disk entry %s"),
			      dle->device);
		    goto common_exit;
		}
		if ((subdir) && (SAMBA_VERSION < 2)) {
		    err = g_strdup_printf(_("subdirectory specified for share '%s' but, samba is not v2 or better"),
				     dle->device);
		    goto common_exit;
		}
		if ((user_and_password = findpass(share, &domain)) == NULL) {
		    err = g_strdup_printf(_("cannot find password for %s"),
				     dle->device);
		    goto common_exit;
		}
		lpass = strlen(user_and_password);
		if ((pwtext = strchr(user_and_password, '%')) == NULL) {
		    err = g_strdup_printf(
				_("password field not \'user%%pass\' for %s"),
				dle->device);
		    goto common_exit;
		}
		*pwtext++ = '\0';
		pwtext_len = (size_t)strlen(pwtext);
		amfree(device);
		if ((device = makesharename(share, 0)) == NULL) {
		    err = g_strdup_printf(_("cannot make share name of %s"), share);
		    goto common_exit;
		}

		if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
	            err = g_strdup_printf(_("Cannot access /dev/null : %s"),
				     strerror(errno));
		    goto common_exit;
		}

		if (pwtext_len > 0) {
		    pw_fd_env = "PASSWD_FD";
		} else {
		    pw_fd_env = "dummy_PASSWD_FD";
		}
		checkpid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE, 0,
				     &nullfd, &nullfd, &checkerr,
				     pw_fd_env, &passwdfd,
				     "smbclient",
				     device,
				     *user_and_password ? "-U" : skip_argument,
				     *user_and_password ? user_and_password
							: skip_argument,
				     "-E",
				     domain ? "-W" : skip_argument,
				     domain ? domain : skip_argument,
#if SAMBA_VERSION >= 2
				     subdir ? "-D" : skip_argument,
				     subdir ? subdir : skip_argument,
#endif
				     "-c", "quit",
				     NULL);
		checkpid = checkpid;
		amfree(domain);
		aclose(nullfd);
		/*@ignore@*/
		if ((pwtext_len > 0) &&
		    full_write(passwdfd, pwtext, pwtext_len) < pwtext_len) {
		    err = g_strdup_printf(_("password write failed: %s: %s"),
				     dle->device, strerror(errno));
		    aclose(passwdfd);
		    goto common_exit;
		}
		/*@end@*/
		memset(user_and_password, '\0', (size_t)lpass);
		amfree(user_and_password);
		aclose(passwdfd);
		ferr = fdopen(checkerr, "r");
		if (!ferr) {
		    g_printf(_("ERROR [Can't fdopen ferr: %s]\n"), strerror(errno));
		    error(_("Can't fdopen ferr: %s"), strerror(errno));
		    /*NOTREACHED*/
		}
		sep = "";
		errdos = 0;
		for(sep = ""; (line = agets(ferr)) != NULL; free(line)) {
		    if (line[0] == '\0')
			continue;
		    strappend(extra_info, sep);
		    strappend(extra_info, line);
		    sep = ": ";
		    if(strstr(line, "ERRDOS") != NULL) {
			errdos = 1;
		    }
		}
		afclose(ferr);
		checkerr = -1;
		rc = 0;
		sep = "";
		while ((wpid = wait(&retstat)) != -1) {
		    if (!WIFEXITED(retstat) || WEXITSTATUS(retstat) != 0) {
			char *exitstr = str_exit_status("smbclient", retstat);
			strappend(err, sep);
			strappend(err, exitstr);
			sep = "\n";
			amfree(exitstr);

			rc = 1;
		    }
		}
		if (errdos != 0 || rc != 0) {
		    char *tmpbuf;
		    if (extra_info) {
                        tmpbuf = g_strdup_printf( _("samba access error: %s: %s %s"),
                            dle->device, extra_info, err);
			amfree(extra_info);
		    } else {
			tmpbuf = g_strdup_printf(_("samba access error: %s: %s"),
                            dle->device, err);
		    }
		    g_free(err);
		    err = tmpbuf;
		}
#else
		err = g_strdup_printf(
			      _("This client is not configured for samba: %s"),
			      qdisk);
#endif
		goto common_exit;
	    }
	    amode = F_OK;
	    amfree(device);
	    device = amname_to_dirname(dle->device);
	} else if (g_str_equal(dle->program, "DUMP")) {
	    if(dle->device[0] == '/' && dle->device[1] == '/') {
		err = g_strdup_printf(
		  _("The DUMP program cannot handle samba shares, use GNUTAR: %s"),
		  qdisk);
		goto common_exit;
	    }
#ifdef VDUMP								/* { */
#ifdef DUMP								/* { */
            if (g_str_equal(amname_to_fstype(dle->device), "advfs"))
#else									/* }{*/
	    if (1)
#endif									/* } */
	    {
		amfree(device);
		device = amname_to_dirname(dle->device);
		amode = F_OK;
	    } else
#endif									/* } */
	    {
		amfree(device);
		device = amname_to_devname(dle->device);
#ifdef USE_RUNDUMP
		amode = F_OK;
#else
		amode = R_OK;
#endif
	    }
	}
    }
    if (dle->program_is_application_api) {
	pid_t                    application_api_pid;
	backup_support_option_t *bsu;
	int                      app_err[2];
	GPtrArray               *errarray;

	bsu = backup_support_option(dle->program, g_options, dle->disk,
				    dle->device, &errarray);

	if (!bsu) {
	    char  *line;
	    guint  i;
	    for (i=0; i < errarray->len; i++) {
		line = g_ptr_array_index(errarray, i);
		fprintf(stdout, _("ERROR Application '%s': %s\n"),
			dle->program, line);
		amfree(line);
	    }
	    err = g_strdup_printf(_("Application '%s': can't run support command"),
			     dle->program);
	    goto common_exit;
	}

	if (dle->data_path == DATA_PATH_AMANDA &&
	    (bsu->data_path_set & DATA_PATH_AMANDA)==0) {
	    g_printf("ERROR application %s doesn't support amanda data-path\n",
		     dle->program);
	}
	if (dle->data_path == DATA_PATH_DIRECTTCP &&
	    (bsu->data_path_set & DATA_PATH_DIRECTTCP)==0) {
	    g_printf("ERROR application %s doesn't support directtcp data-path\n",
		     dle->program);
	}
	if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE &&
			    !bsu->calcsize) {
	    g_printf("ERROR application %s doesn't support calcsize estimate\n",
		     dle->program);
	}
	if (dle->include_file && dle->include_file->nb_element > 0 &&
	    !bsu->include_file) {
	    g_printf("ERROR application %s doesn't support include-file\n",
		   dle->program);
	}
	if (dle->include_list && dle->include_list->nb_element > 0 &&
	    !bsu->include_list) {
	    g_printf("ERROR application %s doesn't support include-list\n",
		   dle->program);
	}
	if (dle->include_optional && !bsu->include_optional) {
	    g_printf("ERROR application %s doesn't support optional include\n",
		   dle->program);
	}
	if (dle->exclude_file && dle->exclude_file->nb_element > 0 &&
	    !bsu->exclude_file) {
	    g_printf("ERROR application %s doesn't support exclude-file\n",
		   dle->program);
	}
	if (dle->exclude_list && dle->exclude_list->nb_element > 0 &&
	    !bsu->exclude_list) {
	    g_printf("ERROR application %s doesn't support exclude-list\n",
		   dle->program);
	}
	if (dle->exclude_optional && !bsu->exclude_optional) {
	    g_printf("ERROR application %s doesn't support optional exclude\n",
		   dle->program);
	}
	fflush(stdout);fflush(stderr);

	if (pipe(app_err) < 0) {
	    err = g_strdup_printf(_("Application '%s': can't create pipe"),
			     dle->program);
	    goto common_exit;
	}

	switch (application_api_pid = fork()) {
	case -1:
	    err = g_strdup_printf(_("fork failed: %s"), strerror(errno));
	    goto common_exit;

	case 0: /* child */
	    {
		GPtrArray *argv_ptr = g_ptr_array_new();
                GPtrArray *argv_quoted = g_ptr_array_new();
                gchar **args, **quoted_strings, **ptr;
		char *cmd = g_strjoin(NULL, APPLICATION_DIR, "/", dle->program, NULL);
		GSList   *scriptlist;
		script_t *script;
		estimatelist_t el;
		char *cmdline;

		aclose(app_err[0]);
		dup2(app_err[1], 2);

		g_ptr_array_add(argv_ptr, g_strdup(dle->program));
		g_ptr_array_add(argv_ptr, g_strdup("selfcheck"));
		if (bsu->message_line == 1) {
		    g_ptr_array_add(argv_ptr, g_strdup("--message"));
		    g_ptr_array_add(argv_ptr, g_strdup("line"));
		}
		if (g_options->config != NULL && bsu->config == 1) {
		    g_ptr_array_add(argv_ptr, g_strdup("--config"));
		    g_ptr_array_add(argv_ptr, g_strdup(g_options->config));
		}
		if (g_options->hostname != NULL && bsu->host == 1) {
		    g_ptr_array_add(argv_ptr, g_strdup("--host"));
		    g_ptr_array_add(argv_ptr, g_strdup(g_options->hostname));
		}
		if (dle->disk != NULL && bsu->disk == 1) {
		    g_ptr_array_add(argv_ptr, g_strdup("--disk"));
		    g_ptr_array_add(argv_ptr, g_strdup(dle->disk));
		}
		if (dle->device) {
		    g_ptr_array_add(argv_ptr, g_strdup("--device"));
		    g_ptr_array_add(argv_ptr, g_strdup(dle->device));
		}
		if (dle->create_index && bsu->index_line == 1) {
		    g_ptr_array_add(argv_ptr, g_strdup("--index"));
		    g_ptr_array_add(argv_ptr, g_strdup("line"));
		}
		if (dle->record && bsu->record == 1) {
		    g_ptr_array_add(argv_ptr, g_strdup("--record"));
		}
		
		for (el = dle->estimatelist; el != NULL; el=el->next) {
		    estimate_t estimate = (estimate_t)GPOINTER_TO_INT(el->data);
		    if (estimate == ES_CALCSIZE && bsu->calcsize == 1) {
			g_ptr_array_add(argv_ptr, g_strdup("--calcsize"));
		    }
		}
		application_property_add_to_argv(argv_ptr, dle, bsu,
						 g_options->features);

		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);
                args = (gchar **)g_ptr_array_free(argv_ptr, FALSE);

                /*
                 * Build the command line to display
                 */
                g_ptr_array_add(argv_quoted, g_strdup(cmd));

                for (ptr = args; *ptr; ptr++)
                    g_ptr_array_add(argv_quoted, quote_string(*ptr));

                g_ptr_array_add(argv_quoted, NULL);

                quoted_strings = (gchar **)g_ptr_array_free(argv_quoted, FALSE);

                cmdline = g_strjoinv(" ", quoted_strings);
                g_strfreev(quoted_strings);

		dbprintf(_("Spawning \"%s\" in pipeline\n"), cmdline);
		amfree(cmdline);

		safe_fd(-1, 0);
		execve(cmd, args, safe_env());
		g_printf(_("ERROR [Can't execute %s: %s]\n"), cmd, strerror(errno));
		exit(127);
	    }
	default: /* parent */
	    {
		int   status;
		FILE *app_stderr;
		char *line;

		aclose(app_err[1]);
		app_stderr = fdopen(app_err[0], "r");
		if (!app_stderr) {
		    g_printf(_("ERROR [Can't fdopen app_stderr: %s]\n"),
			     strerror(errno));
		    error(_("Can't fdopen app_stderr: %s"), strerror(errno));
		    /*NOTREACHED*/
		}
		while((line = agets(app_stderr)) != NULL) {
		    if (strlen(line) > 0) {
			fprintf(stdout, "ERROR Application '%s': %s\n",
				dle->program, line);
			dbprintf("ERROR %s\n", line);
		    }
		    amfree(line);
		}
		fclose(app_stderr);
		if (waitpid(application_api_pid, &status, 0) < 0) {
		    err = g_strdup_printf(_("waitpid failed: %s"),
					 strerror(errno));
		    goto common_exit;
		} else if (!WIFEXITED(status)) {
		    err = g_strdup_printf(_("Application '%s': exited with signal %d"),
				     dle->program, WTERMSIG(status));
		    goto common_exit;
		} else if (WEXITSTATUS(status) != 0) {
		    err = g_strdup_printf(_("Application '%s': exited with status %d"),
				     dle->program, WEXITSTATUS(status));
		    goto common_exit;
		}
	    }
	}
	amfree(bsu);
	fflush(stdout);fflush(stderr);
	amfree(device);
	amfree(qamdevice);
	amfree(qdisk);
	return;
    }

    if (device) {
	qdevice = quote_string(device);
	dbprintf(_("device %s\n"), qdevice);

	/* skip accessability test if this is an AFS entry */
	if(strncmp_const(device, "afs:") != 0) {
#ifdef CHECK_FOR_ACCESS_WITH_OPEN
	    access_result = open(device, O_RDONLY);
	    access_type = "open";
#else
	    access_result = access(device, amode);
	    access_type = "access";
#endif
	    if(access_result == -1) {
		err = g_strdup_printf(_("Could not %s %s (%s): %s"),
				 access_type, qdevice, qdisk, strerror(errno));
	    }
#ifdef CHECK_FOR_ACCESS_WITH_OPEN
	    aclose(access_result);
#endif
	}
    }

common_exit:

    if (!qdevice)
	qdevice = quote_string(device);

    amfree(share);
    amfree(subdir);
    if(user_and_password) {
	memset(user_and_password, '\0', (size_t)lpass);
	amfree(user_and_password);
    }
    amfree(domain);

    if(err) {
	g_printf(_("ERROR %s\n"), err);
	dbprintf(_("%s\n"), err);
	amfree(err);
    } else {
	if (dle->disk) {
	    g_printf("OK %s\n", qdisk);
	    dbprintf(_("disk %s OK\n"), qdisk);
	}
	if (dle->device) {
	    g_printf("OK %s\n", qamdevice);
	    dbprintf(_("amdevice %s OK\n"), qamdevice);
	}
	if (device) {
	    g_printf("OK %s\n", qdevice);
	    dbprintf(_("device %s OK\n"), qdevice);
	}
    }
    if(extra_info) {
	dbprintf(_("extra info: %s\n"), extra_info);
	amfree(extra_info);
    }
    amfree(qdisk);
    amfree(qdevice);
    amfree(qamdevice);
    amfree(device);

    /* XXX perhaps do something with level: read dumpdates and sanity check */
}