X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fsendsize.c;h=d005fe0dc1872f82525aa4aac561c1a667855944;hb=HEAD;hp=359688c49aa6ff59d8f49ea6b4ce2339bc2d89c4;hpb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;p=debian%2Famanda diff --git a/client-src/sendsize.c b/client-src/sendsize.c index 359688c..d005fe0 100644 --- a/client-src/sendsize.c +++ b/client-src/sendsize.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 University of Maryland at College Park + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -30,16 +31,15 @@ */ #include "amanda.h" +#include "match.h" #include "pipespawn.h" #include "amfeatures.h" #include "amandates.h" #include "clock.h" #include "util.h" #include "getfsent.h" -#include "version.h" #include "client_util.h" #include "conffile.h" -#include "amandad.h" #ifdef SAMBA_CLIENT #include "findpass.h" @@ -79,6 +79,7 @@ typedef struct level_estimates_s { time_t dumpsince; int estsize; int needestimate; + int server; /* server can do estimate */ } level_estimate_t; typedef struct disk_estimates_s { @@ -122,6 +123,7 @@ main( disk_estimates_t *est; disk_estimates_t *est1; disk_estimates_t *est_prev; + disk_estimates_t *est_next; char *line = NULL; char *s, *fp; int ch; @@ -134,10 +136,16 @@ main( char *qamdevice = NULL; dle_t *dle; GSList *errlist; + am_level_t *alevel; (void)argc; /* Quiet unused parameter warning */ (void)argv; /* Quiet unused parameter warning */ + if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { + printf("sendsize-%s\n", VERSION); + return (0); + } + /* initialize */ /* @@ -150,6 +158,7 @@ main( textdomain("amanda"); safe_fd(-1, 0); + openbsd_fd_inform(); safe_cd(); set_pname("sendsize"); @@ -157,10 +166,11 @@ main( /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); - erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); + add_amanda_log_handler(amanda_log_stderr); + add_amanda_log_handler(amanda_log_syslog); dbopen(DBG_SUBDIR_CLIENT); startclock(); - dbprintf(_("version %s\n"), version()); + dbprintf(_("version %s\n"), VERSION); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); @@ -238,7 +248,8 @@ main( err_extra = stralloc(_("no program name")); goto err; } - dle->calcsize = 1; + dle->estimatelist = g_slist_append(dle->estimatelist, + GINT_TO_POINTER(ES_CALCSIZE)); dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; @@ -254,7 +265,8 @@ main( } } else { - dle->calcsize = 0; + dle->estimatelist = g_slist_append(dle->estimatelist, + GINT_TO_POINTER(ES_CLIENT)); if (strcmp(dle->program,"APPLICATION") == 0) { dle->program_is_application_api=1; skip_whitespace(s, ch); /* find dumper name */ @@ -311,7 +323,9 @@ main( goto err; } skip_integer(s, ch); - dle->level = g_slist_append(dle->level, GINT_TO_POINTER(level)); + alevel = g_new0(am_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') { @@ -406,6 +420,20 @@ main( amandates_started = FALSE; } + est_prev = NULL; + for(est = est_list; est != NULL; est = est_next) { + int good = merge_dles_properties(est->dle, 0); + est_next = est->next; + if (!good) { + if (est == est_list) { + est_list = est_next; + } else { + est_prev->next = est_next; + } + } else { + est_prev = est; + } + } for(est = est_list; est != NULL; est = est->next) { run_client_scripts(EXECUTE_ON_PRE_HOST_ESTIMATE, g_options, est->dle, stdout); @@ -541,7 +569,7 @@ main( return 0; err: if (err_extra) { - g_printf(_("FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra); + g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra); dbprintf(_("REQ packet is bogus: %s\n"), err_extra); amfree(err_extra); } else { @@ -564,19 +592,23 @@ dle_add_diskest( amandates_t *amdp; int dumplev, estlev; time_t dumpdate; - GSList *level; + levellist_t levellist; char *amandates_file; gboolean need_amandates = FALSE; + estimatelist_t el; - level = dle->level; - if (level == NULL) { + if (dle->levellist == NULL) { g_printf(_("ERROR Missing level in request\n")); return; } /* should we use amandates for this? */ - if (dle->calcsize) - need_amandates = TRUE; + for (el = dle->estimatelist; el != NULL; el=el->next) { + estimate_t estimate = (estimate_t)GPOINTER_TO_INT(el->data); + if (estimate == ES_CALCSIZE) + need_amandates = TRUE; + } + if (strcmp(dle->program, "GNUTAR") == 0) { /* GNUTAR only needs amandates if gnutar_list_dir is NULL */ char *gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR); @@ -604,21 +636,26 @@ dle_add_diskest( } } - while (level != NULL) { - if (GPOINTER_TO_INT(level->data) < 0) - level->data = GINT_TO_POINTER(0); - if (GPOINTER_TO_INT(level->data) >= DUMP_LEVELS) - level->data = GINT_TO_POINTER(DUMP_LEVELS - 1); - level = g_slist_next(level); + levellist = dle->levellist; + while (levellist != NULL) { + am_level_t *alevel = (am_level_t *)levellist->data; + if (alevel->level < 0) + alevel->level = 0; + if (alevel->level >= DUMP_LEVELS) + alevel->level = DUMP_LEVELS - 1; + levellist = g_slist_next(levellist); } for(curp = est_list; curp != NULL; curp = curp->next) { if(strcmp(curp->dle->disk, dle->disk) == 0) { /* already have disk info, just note the level request */ - level = dle->level; - while (level != NULL) { - curp->est[GPOINTER_TO_INT(level->data)].needestimate = 1; - level = g_slist_next(level); + levellist = dle->levellist; + while (levellist != NULL) { + am_level_t *alevel = (am_level_t *)levellist->data; + int level = alevel->level; + curp->est[level].needestimate = 1; + curp->est[level].server = alevel->server; + levellist = g_slist_next(levellist); } return; @@ -639,10 +676,12 @@ dle_add_diskest( newp->dirname = stralloc(""); newp->qdirname = stralloc(""); } - level = dle->level; - while (level != NULL) { - newp->est[GPOINTER_TO_INT(level->data)].needestimate = 1; - level = g_slist_next(level); + levellist = dle->levellist; + while (levellist != NULL) { + am_level_t *alevel = (am_level_t *)levellist->data; + newp->est[alevel->level].needestimate = 1; + newp->est[alevel->level].server = alevel->server; + levellist = g_slist_next(levellist); } newp->dle = dle; @@ -675,8 +714,8 @@ free_estimates( amfree(est->qamdevice); amfree(est->dirname); amfree(est->qdirname); - if(est->dle) { -/* free DLE */ + if (est->dle) { + free_dle(est->dle); } } @@ -690,36 +729,73 @@ calc_estimates( disk_estimates_t * est) { dbprintf(_("calculating for amname %s, dirname %s, spindle %d %s\n"), - est->qamname, est->qdirname, est->dle->spindle, est->dle->program); + est->qamname, est->qdirname, est->dle->spindle, est->dle->program); if(est->dle->program_is_application_api == 1) application_api_calc_estimate(est); - else - if(est->dle->calcsize == 1) - if (est->dle->device[0] == '/' && est->dle->device[1] == '/') + else { + estimatelist_t el; + estimate_t estimate; + int level; + estimate_t estimate_method = ES_ES; + estimate_t client_method = ES_ES; + + /* find estimate method to use */ + for (el = est->dle->estimatelist; el != NULL; el = el->next) { + estimate = (estimate_t)GPOINTER_TO_INT(el->data); + if (estimate == ES_SERVER) { + if (estimate_method == ES_ES) + estimate_method = ES_SERVER; + } + if (estimate == ES_CLIENT || + (estimate == ES_CALCSIZE && + (est->dle->device[0] != '/' || est->dle->device[1] != '/'))) { + if (client_method == ES_ES) + client_method = estimate; + if (estimate_method == ES_ES) + estimate_method = estimate; + } + } + + /* do server estimate */ + if (estimate_method == ES_SERVER) { + for (level = 0; level < DUMP_LEVELS; level++) { + if (est->est[level].needestimate) { + if (est->est[level].server || client_method == ES_ES) { + g_printf(_("%s %d SIZE -1\n"), est->qamname, level); + est->est[level].needestimate = 0; + } + } + } + } + + if (client_method == ES_ES && estimate_method != ES_SERVER) { + g_printf(_("%s %d SIZE -2\n"), est->qamname, 0); dbprintf(_("Can't use CALCSIZE for samba estimate: %s %s\n"), est->qamname, est->qdirname); - else + } else if (client_method == ES_CALCSIZE) { generic_calc_estimates(est); - else + } else if (client_method == ES_CLIENT) { #ifndef USE_GENERIC_CALCSIZE - if(strcmp(est->dle->program, "DUMP") == 0) - dump_calc_estimates(est); - else + if (strcmp(est->dle->program, "DUMP") == 0) + dump_calc_estimates(est); + else #endif #ifdef SAMBA_CLIENT - if (strcmp(est->dle->program, "GNUTAR") == 0 && - est->dle->device[0] == '/' && est->dle->device[1] == '/') - smbtar_calc_estimates(est); - else + if (strcmp(est->dle->program, "GNUTAR") == 0 && + est->dle->device[0] == '/' && est->dle->device[1] == '/') + smbtar_calc_estimates(est); + else #endif #ifdef GNUTAR - if (strcmp(est->dle->program, "GNUTAR") == 0) - gnutar_calc_estimates(est); - else + if (strcmp(est->dle->program, "GNUTAR") == 0) + gnutar_calc_estimates(est); + else #endif - dbprintf(_("Invalid program: %s %s %s\n"), - est->qamname, est->qdirname, est->dle->program); + dbprintf(_("Invalid program: %s %s %s\n"), + est->qamname, est->qdirname, est->dle->program); + } + } dbprintf(_("done with amname %s dirname %s spindle %d\n"), est->qamname, est->qdirname, est->dle->spindle); @@ -734,7 +810,6 @@ calc_estimates( off_t getsize_dump(dle_t *dle, int level, char **errmsg); off_t getsize_smbtar(dle_t *dle, int level, char **errmsg); off_t getsize_gnutar(dle_t *dle, int level, time_t dumpsince, char **errmsg); -off_t getsize_star(dle_t *dle, int level, time_t dumpsince, char **errmsg); off_t getsize_application_api(disk_estimates_t *est, int nb_level, int *levels, backup_support_option_t *bsu); off_t handle_dumpline(char *str); @@ -750,6 +825,12 @@ application_api_calc_estimate( int nb_level = 0; backup_support_option_t *bsu; GPtrArray *errarray; + estimatelist_t el; + estimate_t estimate; + estimate_t estimate_method = ES_ES; + estimate_t client_method = ES_ES; + int has_calcsize = 0; + int has_client = 0; bsu = backup_support_option(est->dle->program, g_options, est->dle->disk, est->dle->device, &errarray); @@ -769,7 +850,7 @@ application_api_calc_estimate( if (est->est[level].needestimate) { g_printf(_("%s %d ERROR %s\n"), est->dle->disk, level, qerrmsg); - dbprintf(_("%s %d ERROR A %s\n"), + dbprintf(_("%s %d ERROR %s\n"), est->qamname, level, qerrmsg); } } @@ -801,6 +882,39 @@ application_api_calc_estimate( g_ptr_array_free(errarray, TRUE); } + if (est->dle->data_path == DATA_PATH_AMANDA && + (bsu->data_path_set & DATA_PATH_AMANDA)==0) { + g_printf("%s %d ERROR application %s doesn't support amanda data-path\n", est->qamname, 0, est->dle->program); + amfree(bsu); + return; + } + if (est->dle->data_path == DATA_PATH_DIRECTTCP && + (bsu->data_path_set & DATA_PATH_DIRECTTCP)==0) { + g_printf("%s %d ERROR application %s doesn't support directtcp data-path\n", est->qamname, 0, est->dle->program); + amfree(bsu); + return; + } + + /* find estimate method to use */ + for (el = est->dle->estimatelist; el != NULL; el = el->next) { + estimate = (estimate_t)GPOINTER_TO_INT(el->data); + if (estimate == ES_CLIENT) + has_client = 1; + if (estimate == ES_CALCSIZE) + has_calcsize = 1; + if (estimate == ES_SERVER) { + if (estimate_method == ES_ES) + estimate_method = ES_SERVER; + } + if ((estimate == ES_CLIENT && bsu->client_estimate) || + (estimate == ES_CALCSIZE && bsu->calcsize)) { + if (client_method == ES_ES) + client_method = estimate; + if (estimate_method == ES_ES) + estimate_method = estimate; + } + } + for(level = 0; level < DUMP_LEVELS; level++) { if (est->est[level].needestimate) { if (level > bsu->max_level) { @@ -808,20 +922,54 @@ application_api_calc_estimate( g_printf("%s %d SIZE %lld\n", est->qamname, level, (long long)-2); est->est[level].needestimate = 0; - } else if (est->dle->estimate == ES_SERVER) { + dbprintf(_("Application '%s' can't estimate level %d\n"), + est->dle->program, level); + } else if (estimate_method == ES_ES) { + g_printf("%s %d SIZE %lld\n", est->qamname, level, + (long long)-2); + est->est[level].needestimate = 0; + if (am_has_feature(g_options->features, + fe_rep_sendsize_quoted_error)) { + char *errmsg, *qerrmsg; + if (has_client && !bsu->client_estimate && + has_calcsize && !bsu->calcsize) { + errmsg = vstrallocf(_("Application '%s' can't do CLIENT or CALCSIZE estimate"), + est->dle->program); + } else if (has_client && !bsu->client_estimate) { + errmsg = vstrallocf(_("Application '%s' can't do CLIENT estimate"), + est->dle->program); + } else if (has_calcsize && !bsu->calcsize) { + errmsg = vstrallocf(_("Application '%s' can't do CALCSIZE estimate"), + est->dle->program); + } else { + errmsg = vstrallocf(_("Application '%s' can't do estimate"), + est->dle->program); + } + qerrmsg = quote_string(errmsg); + dbprintf(_("errmsg is %s\n"), errmsg); + g_printf("%s %d ERROR %s\n", + est->qamname, 0, qerrmsg); + amfree(errmsg); + amfree(qerrmsg); + } + } else if (estimate_method == ES_SERVER && + (est->est[level].server || client_method == ES_ES)) { /* planner will consider this level, */ /* but use a server-side estimate */ - g_printf("%s %d SIZE %lld\n", est->qamname, level, - (long long)-1); + g_printf("%s %d SIZE -1\n", est->qamname, level); est->est[level].needestimate = 0; - } else { + } else if (client_method == ES_CLIENT) { + levels[nb_level++] = level; + } else if (client_method == ES_CALCSIZE) { levels[nb_level++] = level; } } } - if (nb_level == 0) + if (nb_level == 0) { + amfree(bsu); return; + } if (bsu->multi_estimate) { for (i=0;iconfig) - my_argv[my_argc++] = stralloc(g_options->config); + g_ptr_array_add(argv_ptr, stralloc(g_options->config)); else - my_argv[my_argc++] = stralloc("NOCONFIG"); + g_ptr_array_add(argv_ptr, stralloc("NOCONFIG")); - my_argv[my_argc++] = stralloc(est->dle->program); + g_ptr_array_add(argv_ptr, stralloc(est->dle->program)); canonicalize_pathname(est->dle->disk, tmppath); - my_argv[my_argc++] = stralloc(tmppath); + g_ptr_array_add(argv_ptr, stralloc(tmppath)); canonicalize_pathname(est->dirname, tmppath); - my_argv[my_argc++] = stralloc(tmppath); + g_ptr_array_add(argv_ptr, stralloc(tmppath)); if (est->dle->exclude_file) nb_exclude += est->dle->exclude_file->nb_element; @@ -900,34 +1049,37 @@ generic_calc_estimates( file_include = build_include(est->dle, 0); if(file_exclude) { - my_argv[my_argc++] = stralloc("-X"); - my_argv[my_argc++] = file_exclude; + g_ptr_array_add(argv_ptr, stralloc("-X")); + g_ptr_array_add(argv_ptr, stralloc(file_exclude)); } if(file_include) { - my_argv[my_argc++] = stralloc("-I"); - my_argv[my_argc++] = file_include; + g_ptr_array_add(argv_ptr, stralloc("-I")); + g_ptr_array_add(argv_ptr, stralloc(file_include)); } start_time = curclock(); - cmdline = stralloc(my_argv[0]); - for(i = 1; i < my_argc; i++) - cmdline = vstrextend(&cmdline, " ", my_argv[i], NULL); + command = (char *)g_ptr_array_index(argv_ptr, 0); + cmdline = stralloc(command); + for(i = 1; i < argv_ptr->len-1; i++) { + cmdline = vstrextend(&cmdline, " ", + (char *)g_ptr_array_index(argv_ptr, i), NULL); + } dbprintf(_("running: \"%s\"\n"), cmdline); amfree(cmdline); for(level = 0; level < DUMP_LEVELS; level++) { if(est->est[level].needestimate) { g_snprintf(number, SIZEOF(number), "%d", level); - my_argv[my_argc++] = stralloc(number); + g_ptr_array_add(argv_ptr, stralloc(number)); dbprintf(" %s", number); g_snprintf(number, SIZEOF(number), "%ld", (long)est->est[level].dumpsince); - my_argv[my_argc++] = stralloc(number); + g_ptr_array_add(argv_ptr, stralloc(number)); dbprintf(" %s", number); } } - my_argv[my_argc] = NULL; + g_ptr_array_add(argv_ptr, NULL); dbprintf("\n"); fflush(stderr); fflush(stdout); @@ -940,7 +1092,7 @@ generic_calc_estimates( } calcpid = pipespawnv(cmd, STDERR_PIPE, 0, - &nullfd, &nullfd, &pipefd, my_argv); + &nullfd, &nullfd, &pipefd, (char **)argv_ptr->pdata); amfree(cmd); dumpout = fdopen(pipefd,"r"); @@ -950,7 +1102,7 @@ generic_calc_estimates( } match_expr = vstralloc(" %d SIZE %lld", NULL); len = strlen(est->qamname); - for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + for(; (line = agets(dumpout)) != NULL; free(line)) { long long size_ = (long long)0; if (line[0] == '\0' || (int)strlen(line) <= len) continue; @@ -963,12 +1115,11 @@ generic_calc_estimates( level, size_); } - size = (off_t)size_; } amfree(match_expr); dbprintf(_("waiting for %s %s child (pid=%d)\n"), - my_argv[0], est->qamdevice, (int)calcpid); + command, est->qamdevice, (int)calcpid); waitpid(calcpid, &wait_status, 0); if (WIFSIGNALED(wait_status)) { errmsg = vstrallocf(_("%s terminated with signal %d: see %s"), @@ -987,7 +1138,7 @@ generic_calc_estimates( "calcsize", dbfn()); } dbprintf(_("after %s %s wait: child pid=%d status=%d\n"), - my_argv[0], est->qamdevice, + command, est->qamdevice, (int)calcpid, WEXITSTATUS(wait_status)); dbprintf(_(".....\n")); @@ -1006,9 +1157,7 @@ common_exit: } } amfree(errmsg); - for(i = 0; i < my_argc; i++) { - amfree(my_argv[i]); - } + g_ptr_array_free_full(argv_ptr); amfree(cmd); } @@ -1127,7 +1276,7 @@ gnutar_calc_estimates( } #endif -typedef struct regex_s { +typedef struct regex_scale_s { char *regex; int scale; } regex_scale_t; @@ -1221,9 +1370,6 @@ getsize_dump( if (level > 9) return -2; /* planner will not even consider this level */ - if (dle->estimate == ES_SERVER) - return -1; /* planner will consider this level, */ - /* but use a server-side estimate */ g_snprintf(level_str, SIZEOF(level_str), "%d", level); @@ -1234,7 +1380,7 @@ getsize_dump( dbprintf(_("calculating for device %s with %s\n"), qdevice, fstype); - cmd = vstralloc(amlibexecdir, "/rundump", versionsuffix(), NULL); + cmd = vstralloc(amlibexecdir, "/rundump", NULL); rundump_cmd = stralloc(cmd); if (g_options->config) config = g_options->config; @@ -1308,10 +1454,6 @@ getsize_dump( #endif /* } */ { name = stralloc(" (vdump)"); - amfree(device); - amfree(qdevice); - device = amname_to_dirname(amdevice); - qdevice = quote_string(device); dumpkeys = vstralloc(level_str, "b", "f", NULL); dbprintf(_("running \"%s%s %s 60 - %s\"\n"), cmd, name, dumpkeys, qdevice); @@ -1410,8 +1552,7 @@ getsize_dump( default: { char *config; - char *killpgrp_cmd = vstralloc(amlibexecdir, "/killpgrp", - versionsuffix(), NULL); + char *killpgrp_cmd = vstralloc(amlibexecdir, "/killpgrp", NULL); dbprintf(_("running %s\n"), killpgrp_cmd); dup2(killctl[0], 0); dup2(nullfd, 1); @@ -1673,9 +1814,6 @@ getsize_smbtar( if (level > 1) return -2; /* planner will not even consider this level */ - if (dle->estimate == ES_SERVER) - return -1; /* planner will consider this level, */ - /* but use a server-side estimate */ parsesharename(dle->device, &share, &subdir); if (!share) { @@ -1904,12 +2042,12 @@ getsize_gnutar( FILE *out = NULL; char *line = NULL; char *cmd = NULL; + char *command = NULL; char dumptimestr[80]; struct tm *gmtm; int nb_exclude = 0; int nb_include = 0; - char **my_argv; - int i; + GPtrArray *argv_ptr = g_ptr_array_new(); char *file_exclude = NULL; char *file_include = NULL; times_t start_time; @@ -1923,9 +2061,6 @@ getsize_gnutar( if (level > 9) return -2; /* planner will not even consider this level */ - if (dle->estimate == ES_SERVER) - return -1; /* planner will consider this level, */ - /* but use a server-side estimate */ if(dle->exclude_file) nb_exclude += dle->exclude_file->nb_element; if(dle->exclude_list) nb_exclude += dle->exclude_list->nb_element; @@ -1935,9 +2070,6 @@ getsize_gnutar( if(nb_exclude > 0) file_exclude = build_exclude(dle, 0); if(nb_include > 0) file_include = build_include(dle, 0); - my_argv = alloc(SIZEOF(char *) * 22); - i = 0; - gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR); if (strlen(gnutar_list_dir) == 0) gnutar_list_dir = NULL; @@ -2035,35 +2167,35 @@ getsize_gnutar( dirname = amname_to_dirname(dle->device); - cmd = vstralloc(amlibexecdir, "/", "runtar", versionsuffix(), NULL); - my_argv[i++] = "runtar"; + cmd = vstralloc(amlibexecdir, "/", "runtar", NULL); + g_ptr_array_add(argv_ptr, stralloc("runtar")); if (g_options->config) - my_argv[i++] = g_options->config; + g_ptr_array_add(argv_ptr, stralloc(g_options->config)); else - my_argv[i++] = "NOCONFIG"; + g_ptr_array_add(argv_ptr, stralloc("NOCONFIG")); #ifdef GNUTAR - my_argv[i++] = GNUTAR; + g_ptr_array_add(argv_ptr, stralloc(GNUTAR)); #else - my_argv[i++] = "tar"; + g_ptr_array_add(argv_ptr, stralloc("tar")); #endif - my_argv[i++] = "--create"; - my_argv[i++] = "--file"; - my_argv[i++] = "/dev/null"; + g_ptr_array_add(argv_ptr, stralloc("--create")); + g_ptr_array_add(argv_ptr, stralloc("--file")); + g_ptr_array_add(argv_ptr, stralloc("/dev/null")); /* use --numeric-owner for estimates, to reduce the number of user/group * lookups required */ - my_argv[i++] = "--numeric-owner"; - my_argv[i++] = "--directory"; + g_ptr_array_add(argv_ptr, stralloc("--numeric-owner")); + g_ptr_array_add(argv_ptr, stralloc("--directory")); canonicalize_pathname(dirname, tmppath); - my_argv[i++] = tmppath; - my_argv[i++] = "--one-file-system"; + g_ptr_array_add(argv_ptr, stralloc(tmppath)); + g_ptr_array_add(argv_ptr, stralloc("--one-file-system")); if (gnutar_list_dir) { - my_argv[i++] = "--listed-incremental"; - my_argv[i++] = incrname; + g_ptr_array_add(argv_ptr, stralloc("--listed-incremental")); + g_ptr_array_add(argv_ptr, stralloc(incrname)); } else { - my_argv[i++] = "--incremental"; - my_argv[i++] = "--newer"; - my_argv[i++] = dumptimestr; + g_ptr_array_add(argv_ptr, stralloc("--incremental")); + g_ptr_array_add(argv_ptr, stralloc("--newer")); + g_ptr_array_add(argv_ptr, stralloc(dumptimestr)); } #ifdef ENABLE_GNUTAR_ATIME_PRESERVE /* --atime-preserve causes gnutar to call @@ -2071,25 +2203,25 @@ getsize_gnutar( * adjust their atime. However, utime() * updates the file's ctime, so incremental * dumps will think the file has changed. */ - my_argv[i++] = "--atime-preserve"; + g_ptr_array_add(argv_ptr, stralloc("--atime-preserve")); #endif - my_argv[i++] = "--sparse"; - my_argv[i++] = "--ignore-failed-read"; - my_argv[i++] = "--totals"; + g_ptr_array_add(argv_ptr, stralloc("--sparse")); + g_ptr_array_add(argv_ptr, stralloc("--ignore-failed-read")); + g_ptr_array_add(argv_ptr, stralloc("--totals")); if(file_exclude) { - my_argv[i++] = "--exclude-from"; - my_argv[i++] = file_exclude; + g_ptr_array_add(argv_ptr, stralloc("--exclude-from")); + g_ptr_array_add(argv_ptr, stralloc(file_exclude)); } if(file_include) { - my_argv[i++] = "--files-from"; - my_argv[i++] = file_include; + g_ptr_array_add(argv_ptr, stralloc("--files-from")); + g_ptr_array_add(argv_ptr, stralloc(file_include)); } else { - my_argv[i++] = "."; + g_ptr_array_add(argv_ptr, stralloc(".")); } - my_argv[i++] = NULL; + g_ptr_array_add(argv_ptr, NULL); start_time = curclock(); @@ -2100,8 +2232,9 @@ getsize_gnutar( goto common_exit; } + command = (char *)g_ptr_array_index(argv_ptr, 0); dumppid = pipespawnv(cmd, STDERR_PIPE, 0, - &nullfd, &nullfd, &pipefd, my_argv); + &nullfd, &nullfd, &pipefd, (char **)argv_ptr->pdata); dumpout = fdopen(pipefd,"r"); if (!dumpout) { @@ -2137,12 +2270,13 @@ getsize_gnutar( level, walltime_str(timessub(curclock(), start_time))); if(size == (off_t)-1) { - *errmsg = vstrallocf(_("no size line match in %s output"), my_argv[0]); + *errmsg = vstrallocf(_("no size line match in %s output"), + command); dbprintf(_("%s for %s\n"), *errmsg, qdisk); dbprintf(".....\n"); } else if(size == (off_t)0 && level == 0) { dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"), - my_argv[0], dle->disk); + command, dle->disk); dbprintf(".....\n"); } dbprintf(_("estimate size for %s level %d: %lld KB\n"), @@ -2152,7 +2286,8 @@ getsize_gnutar( kill(-dumppid, SIGTERM); - dbprintf(_("waiting for %s \"%s\" child\n"), my_argv[0], qdisk); + dbprintf(_("waiting for %s \"%s\" child\n"), + command, qdisk); waitpid(dumppid, &wait_status, 0); if (WIFSIGNALED(wait_status)) { *errmsg = vstrallocf(_("%s terminated with signal %d: see %s"), @@ -2168,7 +2303,7 @@ getsize_gnutar( *errmsg = vstrallocf(_("%s got bad exit: see %s"), cmd, dbfn()); } - dbprintf(_("after %s %s wait\n"), my_argv[0], qdisk); + dbprintf(_("after %s %s wait\n"), command, qdisk); common_exit: @@ -2179,7 +2314,7 @@ common_exit: amfree(basename); amfree(dirname); amfree(inputname); - amfree(my_argv); + g_ptr_array_free_full(argv_ptr); amfree(qdisk); amfree(cmd); amfree(file_exclude); @@ -2210,8 +2345,9 @@ getsize_application_api( char *line = NULL; char *cmd = NULL; char *cmdline; - int i, j, k; - char **argvchild; + guint i; + int j; + GPtrArray *argv_ptr = g_ptr_array_new(); char *newoptstr = NULL; off_t size1, size2; times_t start_time; @@ -2222,64 +2358,65 @@ getsize_application_api( GSList *scriptlist; script_t *script; char *errmsg = NULL; + estimate_t estimate; + estimatelist_t el; cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL); - i=0; - k = application_property_argv_size(dle); - for (scriptlist = dle->scriptlist; scriptlist != NULL; - scriptlist = scriptlist->next) { - script = (script_t *)scriptlist->data; - if (script->result && script->result->proplist) { - k += property_argv_size(script->result->proplist); - } - } - argvchild = g_new0(char *, 16 + k + DUMP_LEVELS*2); - argvchild[i++] = dle->program; - argvchild[i++] = "estimate"; + g_ptr_array_add(argv_ptr, stralloc(dle->program)); + g_ptr_array_add(argv_ptr, stralloc("estimate")); if (bsu->message_line == 1) { - argvchild[i++] = "--message"; - argvchild[i++] = "line"; + g_ptr_array_add(argv_ptr, stralloc("--message")); + g_ptr_array_add(argv_ptr, stralloc("line")); } if (g_options->config && bsu->config == 1) { - argvchild[i++] = "--config"; - argvchild[i++] = g_options->config; + 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) { - argvchild[i++] = "--host"; - argvchild[i++] = g_options->hostname; + g_ptr_array_add(argv_ptr, stralloc("--host")); + g_ptr_array_add(argv_ptr, stralloc(g_options->hostname)); } - argvchild[i++] = "--device"; - argvchild[i++] = dle->device; + g_ptr_array_add(argv_ptr, stralloc("--device")); + g_ptr_array_add(argv_ptr, stralloc(dle->device)); if (dle->disk && bsu->disk == 1) { - argvchild[i++] = "--disk"; - argvchild[i++] = dle->disk; + g_ptr_array_add(argv_ptr, stralloc("--disk")); + g_ptr_array_add(argv_ptr, stralloc(dle->disk)); } for (j=0; j < nb_level; j++) { - argvchild[i++] = "--level"; + g_ptr_array_add(argv_ptr, stralloc("--level")); g_snprintf(levelstr,SIZEOF(levelstr),"%d", levels[j]); - argvchild[i++] = stralloc(levelstr); + g_ptr_array_add(argv_ptr, stralloc(levelstr)); + } + /* find the first in ES_CLIENT and ES_CALCSIZE */ + estimate = ES_CLIENT; + for (el = dle->estimatelist; el != NULL; el = el->next) { + estimate = (estimate_t)GPOINTER_TO_INT(el->data); + if ((estimate == ES_CLIENT && bsu->client_estimate) || + (estimate == ES_CALCSIZE && bsu->calcsize)) + break; + estimate = ES_CLIENT; } - if (dle->calcsize && bsu->calcsize) { - argvchild[i++] = "--calcsize"; + if (estimate == ES_CALCSIZE && bsu->calcsize) { + g_ptr_array_add(argv_ptr, stralloc("--calcsize")); } - i += application_property_add_to_argv(&argvchild[i], dle, bsu); + 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) { - i += property_add_to_argv(&argvchild[i], - script->result->proplist); + property_add_to_argv(argv_ptr, script->result->proplist); } } - argvchild[i] = NULL; + g_ptr_array_add(argv_ptr, NULL); cmdline = stralloc(cmd); - for(j = 1; j < i; j++) - cmdline = vstrextend(&cmdline, " ", argvchild[j], NULL); + for(i = 1; i < argv_ptr->len-1; i++) + cmdline = vstrextend(&cmdline, " ", + (char *)g_ptr_array_index(argv_ptr, i), NULL); dbprintf("running: \"%s\"\n", cmdline); amfree(cmdline); @@ -2318,7 +2455,7 @@ getsize_application_api( aclose(pipeerrfd[0]); safe_fd(-1, 0); - execve(cmd, argvchild, safe_env()); + execve(cmd, (char **)argv_ptr->pdata, safe_env()); error(_("exec %s failed: %s"), cmd, strerror(errno)); /*NOTREACHED*/ } @@ -2438,6 +2575,7 @@ getsize_application_api( common_exit: amfree(cmd); + g_ptr_array_free_full(argv_ptr); amfree(newoptstr); amfree(qdisk); amfree(qamdevice);