X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fsendsize.c;h=359688c49aa6ff59d8f49ea6b4ce2339bc2d89c4;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=4a335b7bdfb4a0ddf25d6ad5ea15666533d8219d;hpb=fb2bd066c2f8b34addafe48d62550e3033a59431;p=debian%2Famanda diff --git a/client-src/sendsize.c b/client-src/sendsize.c index 4a335b7..359688c 100644 --- a/client-src/sendsize.c +++ b/client-src/sendsize.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: sendsize.c,v 1.171 2006/08/24 01:57:15 paddy_s Exp $ + * $Id: sendsize.c 10421 2008-03-06 18:48:30Z martineau $ * * send estimated backup sizes using dump */ @@ -83,19 +83,13 @@ typedef struct level_estimates_s { typedef struct disk_estimates_s { struct disk_estimates_s *next; - char *amname; char *qamname; - char *amdevice; char *qamdevice; char *dirname; char *qdirname; - char *program; - char *calcprog; - int program_is_backup_api; - int spindle; pid_t child; int done; - option_t *options; + dle_t *dle; level_estimate_t est[DUMP_LEVELS]; } disk_estimates_t; @@ -104,31 +98,27 @@ disk_estimates_t *est_list; static am_feature_t *our_features = NULL; static char *our_feature_string = NULL; static g_option_t *g_options = NULL; +static gboolean amandates_started = FALSE; /* local functions */ int main(int argc, char **argv); -void add_diskest(char *disk, char *amdevice, int level, int spindle, - int program_is_backup_api, char *prog, char *calcprog, - option_t *options); +void dle_add_diskest(dle_t *dle); void calc_estimates(disk_estimates_t *est); void free_estimates(disk_estimates_t *est); void dump_calc_estimates(disk_estimates_t *); void star_calc_estimates(disk_estimates_t *); void smbtar_calc_estimates(disk_estimates_t *); void gnutar_calc_estimates(disk_estimates_t *); -void backup_api_calc_estimate(disk_estimates_t *); +void application_api_calc_estimate(disk_estimates_t *); void generic_calc_estimates(disk_estimates_t *); - int main( int argc, char ** argv) { - int level, spindle; - char *prog, *calcprog, *dumpdate; - option_t *options = NULL; - int program_is_backup_api; + int level; + char *dumpdate; disk_estimates_t *est; disk_estimates_t *est1; disk_estimates_t *est_prev; @@ -139,13 +129,11 @@ main( int done; int need_wait; int dumpsrunning; - char *disk = NULL; char *qdisk = NULL; char *qlist = NULL; - char *amdevice = NULL; char *qamdevice = NULL; - char *amandates_file; - int amandates_read = 0; + dle_t *dle; + GSList *errlist; (void)argc; /* Quiet unused parameter warning */ (void)argv; /* Quiet unused parameter warning */ @@ -178,6 +166,7 @@ main( 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); @@ -212,20 +201,24 @@ main( config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, g_options->config); - dbrename(config_name, DBG_SUBDIR_CLIENT); + dbrename(get_config_name(), DBG_SUBDIR_CLIENT); } - continue; - } + /* 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 (amandates_read == 0) { - amandates_file = getconf_str(CNF_AMANDATES); - if(!start_amandates(amandates_file, 0)) - error("error [opening %s: %s]", amandates_file, - strerror(errno)); - amandates_read = 1; + if (am_has_feature(g_options->features, fe_req_xml)) { + break; + } + continue; } + dle = alloc_dle(); s = line; ch = *s++; @@ -234,44 +227,46 @@ main( err_extra = stralloc(_("no program name")); goto err; /* no program name */ } - prog = s - 1; + dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; - program_is_backup_api=0; - if(strncmp_const(prog, "CALCSIZE") == 0) { + dle->program_is_application_api=0; + if(strncmp_const(dle->program, "CALCSIZE") == 0) { skip_whitespace(s, ch); /* find the program name */ if(ch == '\0') { err_extra = stralloc(_("no program name")); goto err; } - calcprog = s - 1; + dle->calcsize = 1; + dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; - if (strcmp(calcprog,"BACKUP") == 0) { - program_is_backup_api=1; + 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 */ } - calcprog = s - 1; + dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; } } else { - calcprog = NULL; - if (strcmp(prog,"BACKUP") == 0) { - program_is_backup_api=1; + dle->calcsize = 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 */ } - prog = s - 1; + 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') { @@ -281,14 +276,12 @@ main( if (qdisk != NULL) amfree(qdisk); - if (disk != NULL) - amfree(disk); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the disk name */ qdisk = stralloc(fp); - disk = unquote_string(qdisk); + dle->disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { @@ -300,11 +293,11 @@ main( skip_quoted_string(s, ch); s[-1] = '\0'; qamdevice = stralloc(fp); - amdevice = unquote_string(qamdevice); + dle->device = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { - amdevice = stralloc(disk); + dle->device = stralloc(dle->disk); qamdevice = stralloc(qdisk); } @@ -318,6 +311,7 @@ main( goto err; } skip_integer(s, ch); + dle->level = g_slist_append(dle->level, GINT_TO_POINTER(level)); skip_whitespace(s, ch); /* find the dump date */ if(ch == '\0') { @@ -329,11 +323,11 @@ main( s[-1] = '\0'; (void)dumpdate; /* XXX: Set but not used */ - spindle = 0; /* default spindle */ + dle->spindle = 0; /* default spindle */ skip_whitespace(s, ch); /* find the spindle */ if(ch != '\0') { - if(sscanf(s - 1, "%d", &spindle) != 1) { + if(sscanf(s - 1, "%d", &dle->spindle) != 1) { err_extra = stralloc(_("bad spindle")); goto err; /* bad spindle */ } @@ -342,35 +336,32 @@ main( skip_whitespace(s, ch); /* find the parameters */ if(ch != '\0') { if(strncmp_const(s-1, "OPTIONS |;") == 0) { - options = parse_options(s + 8, - disk, - amdevice, - g_options->features, - 0); + parse_options(s + 8, + dle, + g_options->features, + 0); } else { - options = alloc(SIZEOF(option_t)); - init_options(options); while (ch != '\0') { if(strncmp_const(s-1, "exclude-file=") == 0) { qlist = unquote_string(s+12); - options->exclude_file = - append_sl(options->exclude_file, qlist); + dle->exclude_file = + append_sl(dle->exclude_file, qlist); amfree(qlist); } else if(strncmp_const(s-1, "exclude-list=") == 0) { qlist = unquote_string(s+12); - options->exclude_list = - append_sl(options->exclude_list, qlist); + dle->exclude_list = + append_sl(dle->exclude_list, qlist); amfree(qlist); } else if(strncmp_const(s-1, "include-file=") == 0) { qlist = unquote_string(s+12); - options->include_file = - append_sl(options->include_file, qlist); + dle->include_file = + append_sl(dle->include_file, qlist); amfree(qlist); } else if(strncmp_const(s-1, "include-list=") == 0) { qlist = unquote_string(s+12); - options->include_list = - append_sl(options->include_list, qlist); + dle->include_list = + append_sl(dle->include_list, qlist); amfree(qlist); } else { err_extra = vstrallocf(_("Invalid parameter (%s)"), s-1); @@ -382,33 +373,43 @@ main( } } } - else { - options = alloc(SIZEOF(option_t)); - init_options(options); - } - } - else { - options = alloc(SIZEOF(option_t)); - init_options(options); } /*@ignore@*/ - add_diskest(disk, amdevice, level, spindle, program_is_backup_api, prog, calcprog, options); + dle_add_diskest(dle); /*@end@*/ - amfree(disk); - amfree(qdisk); - amfree(amdevice); - amfree(qamdevice); } if (g_options == NULL) { - printf(_("ERROR [Missing OPTIONS line in sendsize input]\n")); + g_printf(_("ERROR [Missing OPTIONS line in sendsize input]\n")); error(_("Missing OPTIONS line in sendsize input\n")); /*NOTREACHED*/ } amfree(line); - finish_amandates(); - free_amandates(); + if (am_has_feature(g_options->features, fe_req_xml)) { + char *errmsg = NULL; + dle_t *dles, *dle; + + dles = amxml_parse_node_FILE(stdin, &errmsg); + if (errmsg) { + err_extra = errmsg; + goto err; + } + for (dle = dles; dle != NULL; dle = dle->next) { + dle_add_diskest(dle); + } + } + + if (amandates_started) { + finish_amandates(); + free_amandates(); + amandates_started = FALSE; + } + + for(est = est_list; est != NULL; est = est->next) { + run_client_scripts(EXECUTE_ON_PRE_HOST_ESTIMATE, g_options, est->dle, + stdout); + } dumpsrunning = 0; need_wait = 0; @@ -454,6 +455,8 @@ main( est->done = 1; est->child = 0; dumpsrunning--; + run_client_scripts(EXECUTE_ON_POST_DLE_ESTIMATE, g_options, + est->dle, stdout); } } /* @@ -478,7 +481,7 @@ main( /* * Make sure there is no spindle conflict. */ - if(est->spindle != -1) { + if(est->dle->spindle != -1) { for(est1 = est_list; est1 != NULL; est1 = est1->next) { if(est1->child == 0 || est == est1 || est1->done) { /* @@ -487,7 +490,7 @@ main( */ continue; } - if(est1->spindle == est->spindle) { + if(est1->dle->spindle == est->dle->spindle) { break; /* oops -- they match */ } } @@ -503,6 +506,9 @@ main( } } else { done = 0; + run_client_scripts(EXECUTE_ON_PRE_DLE_ESTIMATE, g_options, + est->dle, stdout); + if((est->child = fork()) == 0) { calc_estimates(est); /* child does the estimate */ exit(0); @@ -514,6 +520,11 @@ main( } } + for(est = est_list; est != NULL; est = est->next) { + run_client_scripts(EXECUTE_ON_POST_HOST_ESTIMATE, g_options, est->dle, + stdout); + } + est_prev = NULL; for(est = est_list; est != NULL; est = est->next) { free_estimates(est); @@ -529,52 +540,87 @@ main( dbclose(); return 0; err: - g_printf(_("FORMAT ERROR IN REQUEST PACKET\n")); if (err_extra) { + g_printf(_("FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra); dbprintf(_("REQ packet is bogus: %s\n"), err_extra); amfree(err_extra); } else { + g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET\n")); dbprintf(_("REQ packet is bogus\n")); } + + free_g_options(g_options); + dbclose(); return 1; } void -add_diskest( - char * disk, - char * amdevice, - int level, - int spindle, - int program_is_backup_api, - char * prog, - char * calcprog, - option_t * options) +dle_add_diskest( + dle_t *dle) { disk_estimates_t *newp, *curp; amandates_t *amdp; int dumplev, estlev; time_t dumpdate; + GSList *level; + char *amandates_file; + gboolean need_amandates = FALSE; - if (level < 0) - level = 0; - if (level >= DUMP_LEVELS) - level = DUMP_LEVELS - 1; + level = dle->level; + if (level == NULL) { + g_printf(_("ERROR Missing level in request\n")); + return; + } + + /* should we use amandates for this? */ + if (dle->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); + if (!gnutar_list_dir || !*gnutar_list_dir) + need_amandates = TRUE; + } + + /* start amandates here, before adding this DLE to est_list, in case + * we encounter an error. */ + if (need_amandates) { + if (!amandates_started) { + amandates_file = getconf_str(CNF_AMANDATES); + if(!start_amandates(amandates_file, 0)) { + char *errstr = strerror(errno); + char *qamname = quote_string(dle->disk); + char *errmsg = vstrallocf(_("could not open %s: %s"), amandates_file, errstr); + char *qerrmsg = quote_string(errmsg); + g_printf(_("%s %d ERROR %s\n"), qamname, 0, qerrmsg); + amfree(qamname); + amfree(errmsg); + amfree(qerrmsg); + return; + } + amandates_started = TRUE; + } + } + + 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); + } for(curp = est_list; curp != NULL; curp = curp->next) { - if(strcmp(curp->amname, disk) == 0) { + if(strcmp(curp->dle->disk, dle->disk) == 0) { /* already have disk info, just note the level request */ - curp->est[level].needestimate = 1; - if(options) { - free_sl(options->exclude_file); - free_sl(options->exclude_list); - free_sl(options->include_file); - free_sl(options->include_list); - amfree(options->auth); - amfree(options->str); - amfree(options); + level = dle->level; + while (level != NULL) { + curp->est[GPOINTER_TO_INT(level->data)].needestimate = 1; + level = g_slist_next(level); } + return; } } @@ -583,32 +629,39 @@ add_diskest( memset(newp, 0, SIZEOF(*newp)); newp->next = est_list; est_list = newp; - newp->amname = stralloc(disk); - newp->qamname = quote_string(disk); - newp->amdevice = stralloc(amdevice); - newp->qamdevice = quote_string(amdevice); - newp->dirname = amname_to_dirname(newp->amdevice); - newp->qdirname = quote_string(newp->dirname); - newp->program = stralloc(prog); - if(calcprog != NULL) - newp->calcprog = stralloc(calcprog); - else - newp->calcprog = NULL; - newp->program_is_backup_api = program_is_backup_api; - newp->spindle = spindle; - newp->est[level].needestimate = 1; - newp->options = options; + newp->qamname = quote_string(dle->disk); + if (dle->device) { + newp->qamdevice = quote_string(dle->device); + newp->dirname = amname_to_dirname(dle->device); + newp->qdirname = quote_string(newp->dirname); + } else { + newp->qamdevice = stralloc(""); + 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); + } + newp->dle = dle; /* fill in dump-since dates */ - - amdp = amandates_lookup(newp->amname); - - newp->est[0].dumpsince = EPOCH; - for(dumplev = 0; dumplev < DUMP_LEVELS; dumplev++) { - dumpdate = amdp->dates[dumplev]; - for(estlev = dumplev+1; estlev < DUMP_LEVELS; estlev++) { - if(dumpdate > newp->est[estlev].dumpsince) - newp->est[estlev].dumpsince = dumpdate; + if (need_amandates) { + amdp = amandates_lookup(newp->dle->disk); + + newp->est[0].dumpsince = EPOCH; + for(dumplev = 0; dumplev < DUMP_LEVELS; dumplev++) { + dumpdate = amdp->dates[dumplev]; + for(estlev = dumplev+1; estlev < DUMP_LEVELS; estlev++) { + if(dumpdate > newp->est[estlev].dumpsince) + newp->est[estlev].dumpsince = dumpdate; + } + } + } else { + /* just zero everything out */ + for(dumplev = 0; dumplev < DUMP_LEVELS; dumplev++) { + newp->est[dumplev].dumpsince = 0; } } } @@ -618,21 +671,12 @@ void free_estimates( disk_estimates_t * est) { - amfree(est->amname); amfree(est->qamname); - amfree(est->amdevice); amfree(est->qamdevice); amfree(est->dirname); amfree(est->qdirname); - amfree(est->program); - if(est->options) { - free_sl(est->options->exclude_file); - free_sl(est->options->exclude_list); - free_sl(est->options->include_file); - free_sl(est->options->include_list); - amfree(est->options->str); - amfree(est->options->auth); - amfree(est->options); + if(est->dle) { +/* free DLE */ } } @@ -645,38 +689,40 @@ void calc_estimates( disk_estimates_t * est) { - dbprintf(_("calculating for amname %s, dirname %s, spindle %d\n"), - est->qamname, est->qdirname, est->spindle); - - if(est->program_is_backup_api == 1) - backup_api_calc_estimate(est); + dbprintf(_("calculating for amname %s, dirname %s, spindle %d %s\n"), + 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] == '/') + dbprintf(_("Can't use CALCSIZE for samba estimate: %s %s\n"), + est->qamname, est->qdirname); + else + generic_calc_estimates(est); else #ifndef USE_GENERIC_CALCSIZE - if(strcmp(est->program, "DUMP") == 0) + if(strcmp(est->dle->program, "DUMP") == 0) dump_calc_estimates(est); else #endif #ifdef SAMBA_CLIENT - if (strcmp(est->program, "GNUTAR") == 0 && - est->amdevice[0] == '/' && est->amdevice[1] == '/') + 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->program, "GNUTAR") == 0) + if (strcmp(est->dle->program, "GNUTAR") == 0) gnutar_calc_estimates(est); else #endif -#ifdef SAMBA_CLIENT - if (est->amdevice[0] == '/' && est->amdevice[1] == '/') - dbprintf(_("Can't use CALCSIZE for samba estimate: %s %s\n"), - est->qamname, est->qdirname); - else -#endif - generic_calc_estimates(est); + 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->spindle); + est->qamname, est->qdirname, est->dle->spindle); } /* @@ -685,51 +731,114 @@ calc_estimates( */ /* local functions */ -off_t getsize_dump(char *disk, char *amdevice, int level, option_t *options, - char **errmsg); -off_t getsize_smbtar(char *disk, char *amdevice, int level, option_t *options, - char **errmsg); -off_t getsize_gnutar(char *disk, char *amdevice, int level, - option_t *options, time_t dumpsince, char **errmsg); -off_t getsize_backup_api(char *program, char *disk, char *amdevice, int level, - option_t *options, time_t dumpsince, char **errmsg); +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); double first_num(char *str); void -backup_api_calc_estimate( +application_api_calc_estimate( disk_estimates_t * est) { int level; - off_t size; - char *errmsg = NULL, *qerrmsg; + int i; + int levels[DUMP_LEVELS]; + int nb_level = 0; + backup_support_option_t *bsu; + GPtrArray *errarray; + + bsu = backup_support_option(est->dle->program, g_options, est->dle->disk, + est->dle->device, &errarray); + if (!bsu) { + guint i; + for (i=0; i < errarray->len; i++) { + char *line; + char *errmsg; + char *qerrmsg; + line = g_ptr_array_index(errarray, i); + if(am_has_feature(g_options->features, + fe_rep_sendsize_quoted_error)) { + errmsg = g_strdup_printf(_("Application '%s': %s"), + est->dle->program, line); + qerrmsg = quote_string(errmsg); + for (level = 0; level < DUMP_LEVELS; level++) { + if (est->est[level].needestimate) { + g_printf(_("%s %d ERROR %s\n"), + est->dle->disk, level, qerrmsg); + dbprintf(_("%s %d ERROR A %s\n"), + est->qamname, level, qerrmsg); + } + } + amfree(errmsg); + amfree(qerrmsg); + } + } + if (i == 0) { /* nothing in errarray */ + char *errmsg; + char *qerrmsg; + errmsg = g_strdup_printf( + _("Application '%s': cannon execute support command"), + est->dle->program); + qerrmsg = quote_string(errmsg); + for (level = 0; level < DUMP_LEVELS; level++) { + if (est->est[level].needestimate) { + g_printf(_("%s %d ERROR %s\n"), + est->dle->disk, level, qerrmsg); + dbprintf(_("%s %d ERROR %s\n"), + est->qamname, level, qerrmsg); + } + } + amfree(errmsg); + amfree(qerrmsg); + } + for (level = 0; level < DUMP_LEVELS; level++) { + est->est[level].needestimate = 0; + } + g_ptr_array_free(errarray, TRUE); + } for(level = 0; level < DUMP_LEVELS; level++) { if (est->est[level].needestimate) { - dbprintf(_("getting size via application API for %s %s level %d\n"), - est->qamname, est->qamdevice, level); - size = getsize_backup_api(est->program, est->amname, est->amdevice, - level, est->options, - est->est[level].dumpsince, &errmsg); + if (level > bsu->max_level) { + /* planner will not even consider this level */ + 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) { + /* planner will consider this level, */ + /* but use a server-side estimate */ + g_printf("%s %d SIZE %lld\n", est->qamname, level, + (long long)-1); + est->est[level].needestimate = 0; + } else { + levels[nb_level++] = level; + } + } + } - amflock(1, "size"); + if (nb_level == 0) + return; - g_printf(_("%s %d SIZE %lld\n"), est->qamname, level, - (long long)size); - if (errmsg && errmsg[0] != '\0') { - if(am_has_feature(g_options->features, - fe_rep_sendsize_quoted_error)) { - qerrmsg = quote_string(errmsg); - dbprintf(_("errmsg is %s\n"), errmsg); - g_printf(_("%s %d ERROR %s\n"), - est->qamname, level, qerrmsg); - amfree(qerrmsg); - } - } - amfree(errmsg); - fflush(stdout); + if (bsu->multi_estimate) { + for (i=0;iqamname, est->qamdevice, levels[i]); + } + getsize_application_api(est, nb_level, levels, bsu); - amfunlock(1, "size"); + } else { + for(level = 0; level < DUMP_LEVELS; level++) { + if (est->est[level].needestimate) { + dbprintf( + _("getting size via application API for %s %s level %d\n"), + est->qamname, est->qamdevice, level); + levels[0] = level; + getsize_application_api(est, 1, levels, bsu); + } } } } @@ -758,6 +867,7 @@ generic_calc_estimates( amwait_t wait_status; char *errmsg = NULL, *qerrmsg; char tmppath[PATH_MAX]; + int len; cmd = vstralloc(amlibexecdir, "/", "calcsize", versionsuffix(), NULL); @@ -769,28 +879,25 @@ generic_calc_estimates( else my_argv[my_argc++] = stralloc("NOCONFIG"); - my_argv[my_argc++] = stralloc(est->calcprog); - - my_argv[my_argc++] = stralloc(est->amname); + my_argv[my_argc++] = stralloc(est->dle->program); + canonicalize_pathname(est->dle->disk, tmppath); + my_argv[my_argc++] = stralloc(tmppath); canonicalize_pathname(est->dirname, tmppath); my_argv[my_argc++] = stralloc(tmppath); + if (est->dle->exclude_file) + nb_exclude += est->dle->exclude_file->nb_element; + if (est->dle->exclude_list) + nb_exclude += est->dle->exclude_list->nb_element; + if (est->dle->include_file) + nb_include += est->dle->include_file->nb_element; + if (est->dle->include_list) + nb_include += est->dle->include_list->nb_element; - if(est->options->exclude_file) - nb_exclude += est->options->exclude_file->nb_element; - if(est->options->exclude_list) - nb_exclude += est->options->exclude_list->nb_element; - if(est->options->include_file) - nb_include += est->options->include_file->nb_element; - if(est->options->include_list) - nb_include += est->options->include_list->nb_element; - - if(nb_exclude > 0) - file_exclude = build_exclude(est->amname, - est->amdevice, est->options, 0); - if(nb_include > 0) - file_include = build_include(est->amname, - est->amdevice, est->options, 0); + if (nb_exclude > 0) + file_exclude = build_exclude(est->dle, 0); + if (nb_include > 0) + file_include = build_include(est->dle, 0); if(file_exclude) { my_argv[my_argc++] = stralloc("-X"); @@ -832,7 +939,8 @@ generic_calc_estimates( goto common_exit; } - calcpid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv); + calcpid = pipespawnv(cmd, STDERR_PIPE, 0, + &nullfd, &nullfd, &pipefd, my_argv); amfree(cmd); dumpout = fdopen(pipefd,"r"); @@ -840,12 +948,15 @@ generic_calc_estimates( error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } - match_expr = vstralloc(est->qamname," %d SIZE %lld", NULL); + match_expr = vstralloc(" %d SIZE %lld", NULL); + len = strlen(est->qamname); for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { long long size_ = (long long)0; - if (line[0] == '\0') + if (line[0] == '\0' || (int)strlen(line) <= len) continue; - if(sscanf(line, match_expr, &level, &size_) == 2) { + /* Don't use sscanf for est->qamname because it can have a '%'. */ + if (strncmp(line, est->qamname, len) == 0 && + sscanf(line+len, match_expr, &level, &size_) == 2) { g_printf("%s\n", line); /* write to amandad */ dbprintf(_("estimate size for %s level %d: %lld KB\n"), est->qamname, @@ -914,8 +1025,7 @@ dump_calc_estimates( if(est->est[level].needestimate) { dbprintf(_("getting size via dump for %s level %d\n"), est->qamname, level); - size = getsize_dump(est->amname, est->amdevice, - level, est->options, &errmsg); + size = getsize_dump(est->dle, level, &errmsg); amflock(1, "size"); @@ -952,8 +1062,7 @@ smbtar_calc_estimates( if(est->est[level].needestimate) { dbprintf(_("getting size via smbclient for %s level %d\n"), est->qamname, level); - size = getsize_smbtar(est->amname, est->amdevice, level, - est->options, &errmsg); + size = getsize_smbtar(est->dle, level, &errmsg); amflock(1, "size"); @@ -991,8 +1100,8 @@ gnutar_calc_estimates( if (est->est[level].needestimate) { dbprintf(_("getting size via gnutar for %s level %d\n"), est->qamname, level); - size = getsize_gnutar(est->amname, est->amdevice, level, - est->options, est->est[level].dumpsince, + size = getsize_gnutar(est->dle, level, + est->est[level].dumpsince, &errmsg); amflock(1, "size"); @@ -1084,10 +1193,8 @@ regex_scale_t re_size[] = { off_t getsize_dump( - char *disk, - char *amdevice, + dle_t *dle, int level, - option_t *options G_GNUC_UNUSED, char **errmsg) { int pipefd[2], nullfd, stdoutfd, killctl[2]; @@ -1104,7 +1211,7 @@ getsize_dump( char level_str[NUM_STR_SIZE]; int s; times_t start_time; - char *qdisk = quote_string(disk); + char *qdisk = quote_string(dle->disk); char *qdevice; char *config; amwait_t wait_status; @@ -1112,11 +1219,17 @@ getsize_dump( int is_rundump = 1; #endif + 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); - device = amname_to_devname(amdevice); + device = amname_to_devname(dle->device); qdevice = quote_string(device); - fstype = amname_to_fstype(amdevice); + fstype = amname_to_fstype(dle->device); dbprintf(_("calculating for device %s with %s\n"), qdevice, fstype); @@ -1455,7 +1568,7 @@ getsize_dump( cmd, name); } else if(size == (off_t)0 && level == 0) { dbprintf(_("possible %s%s problem -- is \"%s\" really empty?\n"), - cmd, name, disk); + cmd, name, dle->disk); dbprintf(".....\n"); } else { dbprintf(_("estimate size for %s level %d: %lld KB\n"), @@ -1536,10 +1649,8 @@ getsize_dump( #ifdef SAMBA_CLIENT off_t getsize_smbtar( - char *disk, - char *amdevice, + dle_t *dle, int level, - option_t *options, char **errmsg) { int pipefd = -1, nullfd = -1, passwdfd = -1; @@ -1555,14 +1666,18 @@ getsize_smbtar( char *pw_fd_env; times_t start_time; char *error_pn = NULL; - char *qdisk = quote_string(disk); + char *qdisk = quote_string(dle->disk); amwait_t wait_status; - (void)options; /* Quiet unused parameter warning */ - error_pn = stralloc2(get_pname(), "-smbclient"); - parsesharename(amdevice, &share, &subdir); + 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) { amfree(share); amfree(subdir); @@ -1587,7 +1702,7 @@ getsize_smbtar( } set_pname(error_pn); amfree(error_pn); - error(_("cannot find password for %s"), disk); + error(_("cannot find password for %s"), dle->disk); /*NOTREACHED*/ } lpass = strlen(user_and_password); @@ -1600,7 +1715,7 @@ getsize_smbtar( } set_pname(error_pn); amfree(error_pn); - error(_("password field not \'user%%pass\' for %s"), disk); + error(_("password field not \'user%%pass\' for %s"), dle->disk); /*NOTREACHED*/ } *pwtext++ = '\0'; @@ -1651,7 +1766,7 @@ getsize_smbtar( } else { pw_fd_env = "dummy_PASSWD_FD"; } - dumppid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE, + dumppid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE, 0, &nullfd, &nullfd, &pipefd, pw_fd_env, &passwdfd, "smbclient", @@ -1673,7 +1788,7 @@ getsize_smbtar( amfree(domain); } aclose(nullfd); - if(pwtext_len > 0 && fullwrite(passwdfd, pwtext, (size_t)pwtext_len) < 0) { + if(pwtext_len > 0 && full_write(passwdfd, pwtext, pwtext_len) < pwtext_len) { int save_errno = errno; memset(user_and_password, '\0', (size_t)lpass); @@ -1730,7 +1845,7 @@ getsize_smbtar( dbprintf(".....\n"); } else if(size == (off_t)0 && level == 0) { dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"), - SAMBA_CLIENT, disk); + SAMBA_CLIENT, dle->disk); dbprintf(".....\n"); } dbprintf(_("estimate size for %s level %d: %lld KB\n"), @@ -1772,10 +1887,8 @@ getsize_smbtar( #ifdef GNUTAR off_t getsize_gnutar( - char *disk, - char *amdevice, + dle_t *dle, int level, - option_t *options, time_t dumpsince, char **errmsg) { @@ -1803,18 +1916,24 @@ getsize_gnutar( int infd, outfd; ssize_t nb; char buf[32768]; - char *qdisk = quote_string(disk); + char *qdisk = quote_string(dle->disk); char *gnutar_list_dir; amwait_t wait_status; char tmppath[PATH_MAX]; - if(options->exclude_file) nb_exclude += options->exclude_file->nb_element; - if(options->exclude_list) nb_exclude += options->exclude_list->nb_element; - if(options->include_file) nb_include += options->include_file->nb_element; - if(options->include_list) nb_include += options->include_list->nb_element; + 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; + 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(disk, amdevice, options, 0); - if(nb_include > 0) file_include = build_include(disk, amdevice, options, 0); + 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; @@ -1825,7 +1944,7 @@ getsize_gnutar( if (gnutar_list_dir) { char number[NUM_STR_SIZE]; int baselevel; - char *sdisk = sanitise_filename(disk); + char *sdisk = sanitise_filename(dle->disk); basename = vstralloc(gnutar_list_dir, "/", @@ -1876,7 +1995,7 @@ getsize_gnutar( } while ((nb = read(infd, &buf, SIZEOF(buf))) > 0) { - if (fullwrite(outfd, &buf, (size_t)nb) < nb) { + if (full_write(outfd, &buf, (size_t)nb) < (size_t)nb) { *errmsg = vstrallocf(_("writing to %s: %s"), incrname, strerror(errno)); dbprintf("%s\n", *errmsg); @@ -1914,7 +2033,7 @@ getsize_gnutar( gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec); - dirname = amname_to_dirname(amdevice); + dirname = amname_to_dirname(dle->device); cmd = vstralloc(amlibexecdir, "/", "runtar", versionsuffix(), NULL); my_argv[i++] = "runtar"; @@ -1931,6 +2050,9 @@ getsize_gnutar( my_argv[i++] = "--create"; my_argv[i++] = "--file"; my_argv[i++] = "/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"; canonicalize_pathname(dirname, tmppath); my_argv[i++] = tmppath; @@ -1978,7 +2100,8 @@ getsize_gnutar( goto common_exit; } - dumppid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv); + dumppid = pipespawnv(cmd, STDERR_PIPE, 0, + &nullfd, &nullfd, &pipefd, my_argv); dumpout = fdopen(pipefd,"r"); if (!dumpout) { @@ -2019,7 +2142,7 @@ getsize_gnutar( dbprintf(".....\n"); } else if(size == (off_t)0 && level == 0) { dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"), - my_argv[0], disk); + my_argv[0], dle->disk); dbprintf(".....\n"); } dbprintf(_("estimate size for %s level %d: %lld KB\n"), @@ -2072,48 +2195,47 @@ common_exit: #endif off_t -getsize_backup_api( - char *program, - char *disk, - char *amdevice, - int level, - option_t *options, - time_t dumpsince, - char **errmsg) +getsize_application_api( + disk_estimates_t *est, + int nb_level, + int *levels, + backup_support_option_t *bsu) { - int pipeinfd[2], pipeoutfd[2], nullfd; + dle_t *dle = est->dle; + int pipeinfd[2], pipeoutfd[2], pipeerrfd[2]; pid_t dumppid; off_t size = (off_t)-1; - FILE *dumpout, *toolin; + FILE *dumpout; + FILE *dumperr; char *line = NULL; char *cmd = NULL; char *cmdline; - char dumptimestr[80]; - struct tm *gmtm; - int i, j; - char *argvchild[10]; + int i, j, k; + char **argvchild; char *newoptstr = NULL; off_t size1, size2; times_t start_time; - char *qdisk = quote_string(disk); - char *qamdevice = quote_string(amdevice); + char *qdisk = quote_string(dle->disk); + char *qamdevice = quote_string(dle->device); amwait_t wait_status; char levelstr[NUM_STR_SIZE]; - backup_support_option_t *bsu; + GSList *scriptlist; + script_t *script; + char *errmsg = NULL; - (void)options; - gmtm = gmtime(&dumpsince); - 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); - - cmd = vstralloc(DUMPER_DIR, "/", program, NULL); - - bsu = backup_support_option(program, g_options, disk, amdevice); + cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL); i=0; - argvchild[i++] = program; + 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"; if (bsu->message_line == 1) { argvchild[i++] = "--message"; @@ -2128,43 +2250,54 @@ getsize_backup_api( argvchild[i++] = g_options->hostname; } argvchild[i++] = "--device"; - argvchild[i++] = amdevice; - if (disk && bsu->disk == 1) { + argvchild[i++] = dle->device; + if (dle->disk && bsu->disk == 1) { argvchild[i++] = "--disk"; - argvchild[i++] = disk; + argvchild[i++] = dle->disk; } - if (level <= bsu->max_level) { + for (j=0; j < nb_level; j++) { argvchild[i++] = "--level"; - g_snprintf(levelstr,SIZEOF(levelstr),"%d",level); - argvchild[i++] = levelstr; + g_snprintf(levelstr,SIZEOF(levelstr),"%d", levels[j]); + argvchild[i++] = stralloc(levelstr); + } + if (dle->calcsize && bsu->calcsize) { + argvchild[i++] = "--calcsize"; + } + + i += application_property_add_to_argv(&argvchild[i], dle, bsu); + + 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); + } } argvchild[i] = NULL; cmdline = stralloc(cmd); for(j = 1; j < i; j++) - cmdline = vstrextend(&cmdline, " ", argvchild[i], NULL); + cmdline = vstrextend(&cmdline, " ", argvchild[j], NULL); dbprintf("running: \"%s\"\n", cmdline); amfree(cmdline); - if ((nullfd = open("/dev/null", O_RDWR)) == -1) { - *errmsg = vstrallocf(_("Cannot access /dev/null : %s"), - strerror(errno)); - dbprintf("%s\n", *errmsg); + if (pipe(pipeerrfd) < 0) { + errmsg = vstrallocf(_("getsize_application_api could not create data pipes: %s"), + strerror(errno)); goto common_exit; } if (pipe(pipeinfd) < 0) { - *errmsg = vstrallocf(_("getsize_backup_api could create data pipes: %s"), - strerror(errno)); - dbprintf("%s\n", *errmsg); + errmsg = vstrallocf(_("getsize_application_api could not create data pipes: %s"), + strerror(errno)); goto common_exit; } if (pipe(pipeoutfd) < 0) { - *errmsg = vstrallocf(_("getsize_backup_api could create data pipes: %s"), - strerror(errno)); - dbprintf("%s\n", *errmsg); + errmsg = vstrallocf(_("getsize_application_api could not create data pipes: %s"), + strerror(errno)); goto common_exit; } @@ -2179,9 +2312,10 @@ getsize_backup_api( case 0: dup2(pipeinfd[0], 0); dup2(pipeoutfd[1], 1); - dup2(nullfd, 2); + dup2(pipeerrfd[1], 2); aclose(pipeinfd[1]); aclose(pipeoutfd[0]); + aclose(pipeerrfd[0]); safe_fd(-1, 0); execve(cmd, argvchild, safe_env()); @@ -2192,16 +2326,8 @@ getsize_backup_api( aclose(pipeinfd[0]); aclose(pipeoutfd[1]); - - toolin = fdopen(pipeinfd[1],"w"); - if (!toolin) { - error("Can't fdopen: %s", strerror(errno)); - /*NOTREACHED*/ - } - - output_tool_property(toolin, options); - fflush(toolin); - fclose(toolin); + aclose(pipeerrfd[1]); + aclose(pipeinfd[1]); dumpout = fdopen(pipeoutfd[0],"r"); if (!dumpout) { @@ -2212,69 +2338,102 @@ getsize_backup_api( for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { long long size1_ = (long long)0; long long size2_ = (long long)0; + int level = 0; if (line[0] == '\0') continue; dbprintf("%s\n", line); - i = sscanf(line, "%lld %lld", &size1_, &size2_); + if (strncmp(line,"ERROR ", 6) == 0) { + char *errmsg, *qerrmsg; + + errmsg = stralloc(line+6); + qerrmsg = quote_string(errmsg); + dbprintf(_("errmsg is %s\n"), errmsg); + g_printf(_("%s %d ERROR %s\n"), est->qamname, levels[0], qerrmsg); + amfree(qerrmsg); + continue; + } + i = sscanf(line, "%d %lld %lld", &level, &size1_, &size2_); + if (i != 3) { + i = sscanf(line, "%lld %lld", &size1_, &size2_); + level = levels[0]; + if (i != 2) { + char *errmsg, *qerrmsg; + + errmsg = vstrallocf(_("bad line %s"), line); + qerrmsg = quote_string(errmsg); + dbprintf(_("errmsg is %s\n"), errmsg); + g_printf(_("%s %d ERROR %s\n"), est->qamname, levels[0], qerrmsg); + amfree(qerrmsg); + continue; + } + } size1 = (off_t)size1_; size2 = (off_t)size2_; - if(i == 2) { + if (size1 <= 0 || size2 <=0) + size = -1; + else if (size1 * size2 > 0) size = size1 * size2; - } - if(size > -1) { - amfree(line); - while ((line = agets(dumpout)) != NULL) { - if (line[0] != '\0') - break; - amfree(line); - } - if(line != NULL) { - dbprintf(_("%s\n"), line); + dbprintf(_("estimate size for %s level %d: %lld KB\n"), + qamdevice, + level, + (long long)size); + g_printf("%s %d SIZE %lld\n", est->qamname, level, (long long)size); + } + amfree(line); + + dumperr = fdopen(pipeerrfd[0],"r"); + if (!dumperr) { + error(_("Can't fdopen: %s"), strerror(errno)); + /*NOTREACHED*/ + } + + while ((line = agets(dumperr)) != NULL) { + if (strlen(line) > 0) { + char *err = g_strdup_printf(_("Application '%s': %s"), + dle->program, line); + char *qerr = quote_string(err); + for (j=0; j < nb_level; j++) { + fprintf(stdout, "%s %d ERROR %s\n", + est->qamname, levels[j], qerr); } - break; + dbprintf("ERROR %s", qerr); + amfree(err); + amfree(qerr); } + amfree(line); } - amfree(line); dbprintf(".....\n"); - dbprintf(_("estimate time for %s level %d: %s\n"), qamdevice, level, - walltime_str(timessub(curclock(), start_time))); - if(size == (off_t)-1) { - *errmsg = vstrallocf(_("no size line match in %s output"), cmd); - dbprintf(_("%s for %s\n"), cmd, qdisk); - dbprintf(".....\n"); - } else if(size == (off_t)0 && level == 0) { - dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"), - cmd, qdisk); - dbprintf(".....\n"); + if (nb_level == 1) { + dbprintf(_("estimate time for %s level %d: %s\n"), qamdevice, + levels[0], walltime_str(timessub(curclock(), start_time))); + } else { + dbprintf(_("estimate time for %s all level: %s\n"), qamdevice, + walltime_str(timessub(curclock(), start_time))); } - dbprintf(_("estimate size for %s level %d: %lld KB\n"), - qamdevice, - level, - (long long)size); kill(-dumppid, SIGTERM); dbprintf(_("waiting for %s \"%s\" child\n"), cmd, qdisk); waitpid(dumppid, &wait_status, 0); if (WIFSIGNALED(wait_status)) { - *errmsg = vstrallocf(_("%s terminated with signal %d: see %s"), - cmd, WTERMSIG(wait_status), dbfn()); + errmsg = vstrallocf(_("%s terminated with signal %d: see %s"), + cmd, WTERMSIG(wait_status), dbfn()); } else if (WIFEXITED(wait_status)) { if (WEXITSTATUS(wait_status) != 0) { - *errmsg = vstrallocf(_("%s exited with status %d: see %s"), cmd, - WEXITSTATUS(wait_status), dbfn()); + errmsg = vstrallocf(_("%s exited with status %d: see %s"), cmd, + WEXITSTATUS(wait_status), dbfn()); } else { /* Normal exit */ } } else { - *errmsg = vstrallocf(_("%s got bad exit: see %s"), - cmd, dbfn()); + errmsg = vstrallocf(_("%s got bad exit: see %s"), + cmd, dbfn()); } dbprintf(_("after %s %s wait\n"), cmd, qdisk); - aclose(nullfd); afclose(dumpout); + afclose(dumperr); common_exit: @@ -2282,6 +2441,15 @@ common_exit: amfree(newoptstr); amfree(qdisk); amfree(qamdevice); + if (errmsg) { + char *qerrmsg = quote_string(errmsg); + dbprintf(_("errmsg is %s\n"), errmsg); + for (j=0; j < nb_level; j++) { + g_printf(_("%s %d ERROR %s\n"), est->qamname, levels[j], qerrmsg); + } + amfree(errmsg); + amfree(qerrmsg); + } return size; }