X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fsendsize.c;h=dc8a67dd9e6b2e978a8edffaf737e2f128285b1c;hb=1194fb66aa28d9929c3f2bef3cc6c1c3f40a60a4;hp=c13f8754d28ceaa0f248953bea4fa77f08aa92b0;hpb=3ab887b9bc819a846c75dd7f2ee5d41fac22b19f;p=debian%2Famanda diff --git a/client-src/sendsize.c b/client-src/sendsize.c index c13f875..dc8a67d 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.97.2.13.4.6.2.23 2003/10/24 20:38:23 kovert Exp $ + * $Id: sendsize.c,v 1.152 2006/03/09 16:51:41 martinea Exp $ * * send estimated backup sizes using dump */ @@ -79,6 +79,8 @@ typedef struct disk_estimates_s { char *amdevice; char *dirname; char *program; + char *calcprog; + int program_is_wrapper; int spindle; pid_t child; int done; @@ -94,13 +96,15 @@ static g_option_t *g_options = NULL; /* local functions */ int main P((int argc, char **argv)); -void add_diskest P((char *disk, char *amdevice, int level, int spindle, - char *prog, option_t *options)); +void add_diskest P((char *disk, char *amdevice, int level, int spindle, + int program_is_wrapper, char *prog, char *calcprog, + option_t *options)); void calc_estimates P((disk_estimates_t *est)); void free_estimates P((disk_estimates_t *est)); void dump_calc_estimates P((disk_estimates_t *)); void smbtar_calc_estimates P((disk_estimates_t *)); void gnutar_calc_estimates P((disk_estimates_t *)); +void wrapper_calc_estimates P((disk_estimates_t *)); void generic_calc_estimates P((disk_estimates_t *)); @@ -109,8 +113,9 @@ int argc; char **argv; { int level, spindle; - char *prog, *disk, *amdevice, *dumpdate; + char *prog, *calcprog, *disk, *amdevice, *dumpdate; option_t *options = NULL; + int program_is_wrapper; disk_estimates_t *est; disk_estimates_t *est1; disk_estimates_t *est_prev; @@ -118,7 +123,6 @@ char **argv; char *s, *fp; int ch; char *err_extra = NULL; - int fd; unsigned long malloc_hist_1, malloc_size_1; unsigned long malloc_hist_2, malloc_size_2; int done; @@ -128,20 +132,14 @@ char **argv; /* initialize */ - for(fd = 3; fd < FD_SETSIZE; fd++) { - /* - * Make sure nobody spoofs us with a lot of extra open files - * that would cause an open we do to get a very high file - * descriptor, which in turn might be used as an index into - * an array (e.g. an fd_set). - */ - close(fd); - } - + safe_fd(-1, 0); safe_cd(); set_pname("sendsize"); + /* Don't die when child closes pipe */ + signal(SIGPIPE, SIG_IGN); + malloc_size_1 = malloc_inuse(&malloc_hist_1); erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); @@ -196,6 +194,32 @@ char **argv; skip_non_whitespace(s, ch); s[-1] = '\0'; + program_is_wrapper=0; + if(strcmp(prog,"DUMPER")==0) { + program_is_wrapper=1; + skip_whitespace(s, ch); /* find dumper name */ + if (ch == '\0') { + goto err; /* no program */ + } + prog = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + } + + if(strncmp(prog, "CALCSIZE", 8) == 0) { + skip_whitespace(s, ch); /* find the program name */ + if(ch == '\0') { + err_extra = "no program name"; + goto err; + } + calcprog = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + } + else { + calcprog = NULL; + } + skip_whitespace(s, ch); /* find the disk name */ if(ch == '\0') { err_extra = "no disk name"; @@ -281,7 +305,7 @@ char **argv; } } - add_diskest(disk, amdevice, level, spindle, prog, options); + add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options); amfree(amdevice); } amfree(line); @@ -412,8 +436,8 @@ char **argv; our_features = NULL; am_release_feature_set(g_options->features); g_options->features = NULL; - amfree(g_options->str); amfree(g_options->hostname); + amfree(g_options->str); amfree(g_options); malloc_size_2 = malloc_inuse(&malloc_hist_2); @@ -437,9 +461,9 @@ char **argv; } -void add_diskest(disk, amdevice, level, spindle, prog, options) -char *disk, *amdevice, *prog; -int level, spindle; +void add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options) +char *disk, *amdevice, *prog, *calcprog; +int level, spindle, program_is_wrapper; option_t *options; { disk_estimates_t *newp, *curp; @@ -456,6 +480,7 @@ option_t *options; free_sl(options->exclude_list); free_sl(options->include_file); free_sl(options->include_list); + amfree(options->auth); amfree(options->str); amfree(options); } @@ -471,6 +496,11 @@ option_t *options; newp->amdevice = stralloc(amdevice); newp->dirname = amname_to_dirname(newp->amdevice); newp->program = stralloc(prog); + if(calcprog != NULL) + newp->calcprog = stralloc(calcprog); + else + newp->calcprog = NULL; + newp->program_is_wrapper = program_is_wrapper; newp->spindle = spindle; newp->est[level].needestimate = 1; newp->options = options; @@ -503,6 +533,7 @@ disk_estimates_t *est; free_sl(est->options->include_file); free_sl(est->options->include_list); amfree(est->options->str); + amfree(est->options->auth); amfree(est->options); } } @@ -519,6 +550,9 @@ disk_estimates_t *est; debug_prefix_time(NULL), est->amname, est->dirname, est->spindle)); + if(est->program_is_wrapper == 1) + wrapper_calc_estimates(est); + else #ifndef USE_GENERIC_CALCSIZE if(strcmp(est->program, "DUMP") == 0) dump_calc_estimates(est); @@ -535,91 +569,175 @@ disk_estimates_t *est; gnutar_calc_estimates(est); else #endif - generic_calc_estimates(est); +#ifdef SAMBA_CLIENT + if (est->amdevice[0] == '/' && est->amdevice[1] == '/') + dbprintf(("%s: Can't use CALCSIZE for samba estimate: %s %s\n", + debug_prefix_time(NULL), + est->amname, est->dirname)); + else +#endif + generic_calc_estimates(est); dbprintf(("%s: done with amname '%s', dirname '%s', spindle %d\n", debug_prefix_time(NULL), est->amname, est->dirname, est->spindle)); } +/* + * ------------------------------------------------------------------------ + * + */ + +/* local functions */ +long getsize_dump P((char *disk, char *amdevice, int level, option_t *options)); +long getsize_smbtar P((char *disk, char *amdevice, int level, option_t *options)); +long getsize_gnutar P((char *disk, char *amdevice, int level, + option_t *options, time_t dumpsince)); +long getsize_wrapper P((char *program, char *disk, char *amdevice, int level, + option_t *options, time_t dumpsince)); +long handle_dumpline P((char *str)); +double first_num P((char *str)); + +void wrapper_calc_estimates(est) +disk_estimates_t *est; +{ + int level; + long size; + + for(level = 0; level < DUMP_LEVELS; level++) { + if (est->est[level].needestimate) { + dbprintf(("%s: getting size via wrapper for %s level %d\n", + debug_prefix_time(NULL), est->amname, level)); + size = getsize_wrapper(est->program, est->amname, est->amdevice, level, est->options, + est->est[level].dumpsince); + + amflock(1, "size"); + + fseek(stdout, (off_t)0, SEEK_SET); + + printf("%s %d SIZE %ld\n", est->amname, level, size); + fflush(stdout); + + amfunlock(1, "size"); + } + } +} + + void generic_calc_estimates(est) disk_estimates_t *est; { + int pipefd = -1, nullfd = -1; char *cmd; - char *argv[DUMP_LEVELS*2+10]; + char *my_argv[DUMP_LEVELS*2+20]; char number[NUM_STR_SIZE]; - int i, level, argc, calcpid; + int i, level, my_argc, calcpid; + int nb_exclude = 0; + int nb_include = 0; + char *file_exclude = NULL; + char *file_include = NULL; + times_t start_time; + FILE *dumpout = NULL; + long size = 1; + char *line = NULL; + char *match_expr; cmd = vstralloc(libexecdir, "/", "calcsize", versionsuffix(), NULL); - argc = 0; - argv[argc++] = stralloc("calcsize"); - argv[argc++] = stralloc(est->program); -#ifdef BUILTIN_EXCLUDE_SUPPORT - if(est->exclude && *est->exclude) { - argv[argc++] = stralloc("-X"); - argv[argc++] = stralloc(est->exclude); + my_argc = 0; + my_argv[my_argc++] = stralloc("calcsize"); + my_argv[my_argc++] = stralloc(est->calcprog); + + my_argv[my_argc++] = stralloc(est->amname); + my_argv[my_argc++] = stralloc(est->dirname); + + + 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(file_exclude) { + my_argv[my_argc++] = stralloc("-X"); + my_argv[my_argc++] = file_exclude; } -#endif - argv[argc++] = stralloc(est->amdevice); - argv[argc++] = stralloc(est->dirname); - dbprintf(("%s: running cmd: %s", debug_prefix_time(NULL), argv[0])); - for(i=0; iest[level].needestimate) { - ap_snprintf(number, sizeof(number), "%d", level); - argv[argc++] = stralloc(number); + snprintf(number, sizeof(number), "%d", level); + my_argv[my_argc++] = stralloc(number); dbprintf((" %s", number)); - ap_snprintf(number, sizeof(number), + snprintf(number, sizeof(number), "%ld", (long)est->est[level].dumpsince); - argv[argc++] = stralloc(number); + my_argv[my_argc++] = stralloc(number); dbprintf((" %s", number)); } } - argv[argc] = NULL; + my_argv[my_argc] = NULL; dbprintf(("\n")); fflush(stderr); fflush(stdout); - switch(calcpid = fork()) { - case -1: - error("%s: fork returned: %s", cmd, strerror(errno)); - default: - break; - case 0: - execve(cmd, argv, safe_env()); - error("%s: execve returned: %s", cmd, strerror(errno)); - exit(1); - } - for(i = 0; i < argc; i++) { - amfree(argv[i]); + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + dbprintf(("Cannot access /dev/null : %s\n", strerror(errno))); + goto common_exit; } + + calcpid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv); amfree(cmd); + dumpout = fdopen(pipefd,"r"); + match_expr = vstralloc(est->amname," %d SIZE %ld", NULL); + for(size = -1; (line = agets(dumpout)) != NULL; free(line)) { + if(sscanf(line, match_expr, &level, &size) == 2) { + printf("%s\n", line); /* write to amandad */ + dbprintf(("%s: estimate size for %s level %d: %ld KB\n", + debug_prefix(NULL), + est->amname, + level, + size)); + } + } + amfree(match_expr); + dbprintf(("%s: waiting for %s \"%s\" child\n", - debug_prefix_time(NULL), argv[0], est->amdevice)); + debug_prefix_time(NULL), my_argv[0], est->amdevice)); wait(NULL); dbprintf(("%s: after %s \"%s\" wait\n", - debug_prefix_time(NULL), argv[0], est->amdevice)); -} + debug_prefix_time(NULL), my_argv[0], est->amdevice)); + dbprintf(("%s: .....\n", debug_prefix_time(NULL))); + dbprintf(("%s: estimate time for %s: %s\n", + debug_prefix(NULL), + est->amname, + walltime_str(timessub(curclock(), start_time)))); -/* - * ------------------------------------------------------------------------ - * - */ +common_exit: + for(i = 0; i < my_argc; i++) { + amfree(my_argv[i]); + } + amfree(cmd); +} -/* local functions */ -void dump_calc_estimates P((disk_estimates_t *est)); -long getsize_dump P((char *disk, char *amdevice, int level, option_t *options)); -long getsize_smbtar P((char *disk, char *amdevice, int level, option_t *options)); -long getsize_gnutar P((char *disk, char *amdevice, int level, - option_t *options, time_t dumpsince)); -long handle_dumpline P((char *str)); -double first_num P((char *str)); void dump_calc_estimates(est) disk_estimates_t *est; @@ -743,10 +861,6 @@ regex_t re_size[] = { {"xfsdump: estimated dump size: [0-9][0-9]* bytes", 1}, /* Irix 6.2 xfs */ #endif -#ifdef USE_QUICK_AND_DIRTY_ESTIMATES - {"amqde estimate: [0-9][0-9]* kb", 1024}, /* amqde */ -#endif - #ifdef GNUTAR {"Total bytes written: [0-9][0-9]*", 1}, /* Gnutar client */ #endif @@ -785,7 +899,7 @@ long getsize_dump(disk, amdevice, level, options) int s; times_t start_time; - ap_snprintf(level_str, sizeof(level_str), "%d", level); + snprintf(level_str, sizeof(level_str), "%d", level); device = amname_to_devname(amdevice); fstype = amname_to_fstype(amdevice); @@ -796,7 +910,15 @@ long getsize_dump(disk, amdevice, level, options) cmd = vstralloc(libexecdir, "/rundump", versionsuffix(), NULL); rundump_cmd = stralloc(cmd); - stdoutfd = nullfd = open("/dev/null", O_RDWR); + if ((stdoutfd = nullfd = open("/dev/null", O_RDWR)) == -1) { + dbprintf(("getsize_dump could not open /dev/null: %s\n", + strerror(errno))); + amfree(cmd); + amfree(rundump_cmd); + amfree(fstype); + amfree(device); + return(-1); + } pipefd[0] = pipefd[1] = killctl[0] = killctl[1] = -1; pipe(pipefd); @@ -906,6 +1028,7 @@ long getsize_dump(disk, amdevice, level, options) amfree(rundump_cmd); amfree(device); amfree(name); + amfree(fstype); return -1; default: break; @@ -1033,16 +1156,19 @@ long getsize_dump(disk, amdevice, level, options) dbprintf(("%s: no size line match in %s%s output for \"%s\"\n", debug_prefix(NULL), cmd, name, disk)); dbprintf(("%s: .....\n", debug_prefix(NULL))); + dbprintf(("%s: Run %s%s manually to check for errors\n", + debug_prefix(NULL), cmd, name)); } else if(size == 0 && level == 0) { dbprintf(("%s: possible %s%s problem -- is \"%s\" really empty?\n", debug_prefix(NULL), cmd, name, disk)); dbprintf(("%s: .....\n", debug_prefix(NULL))); - } - dbprintf(("%s: estimate size for %s level %d: %ld KB\n", + } else { + dbprintf(("%s: estimate size for %s level %d: %ld KB\n", debug_prefix(NULL), disk, level, size)); + } if (killctl[1] != -1) { dbprintf(("%s: asking killpgrp to terminate\n", @@ -1176,7 +1302,19 @@ long getsize_smbtar(disk, amdevice, level, optionns) amfree(error_pn); error("cannot make share name of %s", share); } - nullfd = open("/dev/null", O_RDWR); + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + 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); + amfree(sharename); + error("could not open /dev/null: %s\n", + strerror(errno)); + } #if SAMBA_VERSION >= 2 if (level == 0) @@ -1349,7 +1487,7 @@ time_t dumpsince; if(ch == '/' || isspace(ch)) s[-1] = '_'; } - ap_snprintf(number, sizeof(number), "%d", level); + snprintf(number, sizeof(number), "%d", level); incrname = vstralloc(basename, "_", number, ".new", NULL); unlink(incrname); @@ -1361,7 +1499,7 @@ time_t dumpsince; baselevel = level; while (in == NULL) { if (--baselevel >= 0) { - ap_snprintf(number, sizeof(number), "%d", baselevel); + snprintf(number, sizeof(number), "%d", baselevel); inputname = newvstralloc(inputname, basename, "_", number, NULL); } else { @@ -1422,7 +1560,7 @@ time_t dumpsince; #endif gmtm = gmtime(&dumpsince); - ap_snprintf(dumptimestr, sizeof(dumptimestr), + 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); @@ -1431,22 +1569,6 @@ time_t dumpsince; -#ifdef USE_QUICK_AND_DIRTY_ESTIMATES - ap_snprintf(dumptimestr, sizeof(dumptimestr), "%ld", dumpsince); - - cmd = vstralloc(libexecdir, "/", "amqde", versionsuffix(), NULL); - - my_argv[i++] = vstralloc(libexecdir, "/", "amqde", versionsuffix(), NULL); - my_argv[i++] = "-s"; - my_argv[i++] = dumptimestr; - if(file_exclude) { /* at present, this is not used... */ - my_argv[i++] = "-x"; - my_argv[i++] = file_exclude; - } - /* [XXX] need to also consider implementation of --files-from */ - my_argv[i++] = dirname; - my_argv[i++] = NULL; -#else #ifdef GNUTAR cmd = vstralloc(libexecdir, "/", "runtar", versionsuffix(), NULL); @@ -1492,7 +1614,6 @@ time_t dumpsince; else { my_argv[i++] = "."; } -#endif /* USE_QUICK_AND_DIRTY_ESTIMATES */ my_argv[i++] = NULL; start_time = curclock(); @@ -1567,6 +1688,134 @@ common_exit: } #endif +long getsize_wrapper(program, disk, amdevice, level, options, dumpsince) +char *program, *disk, *amdevice; +int level; +option_t *options; +time_t dumpsince; +{ + int pipefd[2], nullfd, dumppid; + long size; + FILE *dumpout; + char *line = NULL; + char *cmd = NULL; + char dumptimestr[80]; + struct tm *gmtm; + int i, j; + char *argvchild[10]; + char *newoptstr = NULL; + long size1, size2; + times_t start_time; + + gmtm = gmtime(&dumpsince); + 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); + + i=0; + argvchild[i++] = program; + argvchild[i++] = "estimate"; + if(level == 0) + argvchild[i++] = "full"; + else { + char levelstr[NUM_STR_SIZE]; + snprintf(levelstr,sizeof(levelstr),"%d",level); + argvchild[i++] = "level"; + argvchild[i++] = levelstr; + } + argvchild[i++] = amdevice; + newoptstr = vstralloc(options->str,"estimate-direct;", NULL); + argvchild[i++] = newoptstr; + argvchild[i] = NULL; + + dbprintf(("%s: running %s", debug_prefix_time(NULL), cmd)); + for(j = 1; j < i; j++) { + dbprintf((" %s", argvchild[j])); + } + dbprintf(("\n")); + nullfd = open("/dev/null", O_RDWR); + pipe(pipefd); + + start_time = curclock(); + + switch(dumppid = fork()) { + case -1: + size = -1; + goto common_exit; + default: + break; /* parent */ + case 0: + dup2(nullfd, 0); + dup2(nullfd, 2); + dup2(pipefd[1], 1); + aclose(pipefd[0]); + + execve(cmd, argvchild, safe_env()); + error("exec %s failed: %s", cmd, strerror(errno)); + } + amfree(newoptstr); + + aclose(pipefd[1]); + dumpout = fdopen(pipefd[0],"r"); + + for(size = -1; (line = agets(dumpout)) != NULL; free(line)) { + dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); + i = sscanf(line,"%ld %ld",&size1, &size2); + if(i == 2) { + size = size1 * size2; + } + if(size > -1) { + amfree(line); + if((line = agets(dumpout)) != NULL) { + dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); + } + break; + } + } + amfree(line); + + dbprintf(("%s: .....\n", debug_prefix_time(NULL))); + dbprintf(("%s: estimate time for %s level %d: %s\n", + debug_prefix(NULL), + amdevice, + level, + walltime_str(timessub(curclock(), start_time)))); + if(size == -1) { + dbprintf(("%s: no size line match in %s output for \"%s\"\n", + debug_prefix(NULL), cmd, disk)); + dbprintf(("%s: .....\n", debug_prefix(NULL))); + } else if(size == 0 && level == 0) { + dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n", + debug_prefix(NULL), cmd, disk)); + dbprintf(("%s: .....\n", debug_prefix(NULL))); + } + dbprintf(("%s: estimate size for %s level %d: %ld KB\n", + debug_prefix(NULL), + amdevice, + level, + size)); + + kill(-dumppid, SIGTERM); + + dbprintf(("%s: waiting for %s \"%s\" child\n", + debug_prefix_time(NULL), cmd, disk)); + wait(NULL); + dbprintf(("%s: after %s \"%s\" wait\n", + debug_prefix_time(NULL), cmd, disk)); + + aclose(nullfd); + afclose(dumpout); + +common_exit: + + amfree(cmd); + amfree(newoptstr); + return size; +} + double first_num(str) char *str;