X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fsendsize.c;h=e99071c24f9747a25d079fd2ee4374e9c2463656;hb=34197d9f46a5f4e944378cbb65fca32ee0eec7b9;hp=c13f8754d28ceaa0f248953bea4fa77f08aa92b0;hpb=3ab887b9bc819a846c75dd7f2ee5d41fac22b19f;p=debian%2Famanda diff --git a/client-src/sendsize.c b/client-src/sendsize.c index c13f875..e99071c 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.171.2.4 2006/12/22 14:42:42 martinea Exp $ * * send estimated backup sizes using dump */ @@ -38,6 +38,8 @@ #include "getfsent.h" #include "version.h" #include "client_util.h" +#include "clientconf.h" +#include "amandad.h" #ifdef SAMBA_CLIENT #include "findpass.h" @@ -76,9 +78,14 @@ 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_wrapper; int spindle; pid_t child; int done; @@ -93,24 +100,29 @@ static char *our_feature_string = NULL; 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 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 generic_calc_estimates P((disk_estimates_t *)); - - -int main(argc, argv) -int argc; -char **argv; +int main(int argc, char **argv); +void add_diskest(char *disk, char *amdevice, int level, int spindle, + int program_is_wrapper, char *prog, char *calcprog, + option_t *options); +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 wrapper_calc_estimates(disk_estimates_t *); +void generic_calc_estimates(disk_estimates_t *); + + +int +main( + int argc, + char ** argv) { int level, spindle; - char *prog, *disk, *amdevice, *dumpdate; + char *prog, *calcprog, *dumpdate; option_t *options = NULL; + int program_is_wrapper; disk_estimates_t *est; disk_estimates_t *est1; disk_estimates_t *est_prev; @@ -118,34 +130,41 @@ 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; int need_wait; int dumpsrunning; + char *disk = NULL; + char *qdisk = NULL; + char *qlist = NULL; + char *amdevice = NULL; + char *qamdevice = NULL; + char *conffile; + char *amandates_file; + int amandates_read = 0; +#if defined(USE_DBMALLOC) + unsigned long malloc_hist_1, malloc_size_1; + unsigned long malloc_hist_2, malloc_size_2; +#endif + (void)argc; /* Quiet unused parameter warning */ + (void)argv; /* Quiet unused parameter warning */ /* 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); + +#if defined(USE_DBMALLOC) malloc_size_1 = malloc_inuse(&malloc_hist_1); +#endif erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); - dbopen(); + dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(("%s: version %s\n", get_pname(), version())); @@ -154,13 +173,20 @@ char **argv; set_debug_prefix_pid(getpid()); - /* handle all service requests */ + conffile = vstralloc(CONFIG_DIR, "/", "amanda-client.conf", NULL); + if (read_clientconf(conffile) > 0) { + error("error reading conffile: %s", conffile); + /*NOTREACHED*/ + } + amfree(conffile); - start_amandates(0); + /* handle all service requests */ for(; (line = agets(stdin)) != NULL; free(line)) { + if (line[0] == '\0') + continue; #define sc "OPTIONS " - if(strncmp(line, sc, sizeof(sc)-1) == 0) { + if(strncmp(line, sc, SIZEOF(sc)-1) == 0) { #undef sc g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { @@ -181,73 +207,135 @@ char **argv; } printf("\n"); fflush(stdout); + + if (g_options->config) { + conffile = vstralloc(CONFIG_DIR, "/", g_options->config, "/", + "amanda-client.conf", NULL); + if (read_clientconf(conffile) > 0) { + error("error reading conffile: %s", conffile); + /*NOTREACHED*/ + } + amfree(conffile); + + dbrename(g_options->config, DBG_SUBDIR_CLIENT); + } + continue; } + if (amandates_read == 0) { + amandates_file = client_getconf_str(CLN_AMANDATES); + if(!start_amandates(amandates_file, 0)) + error("error [opening %s: %s]", amandates_file, + strerror(errno)); + amandates_read = 1; + } + s = line; ch = *s++; skip_whitespace(s, ch); /* find the program name */ if(ch == '\0') { - err_extra = "no program name"; + err_extra = stralloc("no program name"); goto err; /* no program name */ } prog = s - 1; 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 = stralloc("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"; + err_extra = stralloc("no disk name"); goto err; /* no disk name */ } - disk = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; + + 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); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { - err_extra = "bad level"; + err_extra = stralloc("bad level"); goto err; } if(!isdigit((int)s[-1])) { fp = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; - amdevice = stralloc(fp); + qamdevice = stralloc(fp); + amdevice = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { amdevice = stralloc(disk); + qamdevice = stralloc(qdisk); } /* find the level number */ if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { - err_extra = "bad level"; + err_extra = stralloc("bad level"); goto err; /* bad level */ } + if (level < 0 || level >= DUMP_LEVELS) { + err_extra = stralloc("bad level"); + goto err; + } skip_integer(s, ch); skip_whitespace(s, ch); /* find the dump date */ if(ch == '\0') { - err_extra = "no dumpdate"; + err_extra = stralloc("no dumpdate"); goto err; /* no dumpdate */ } dumpdate = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; + (void)dumpdate; /* XXX: Set but not used */ spindle = 0; /* default spindle */ skip_whitespace(s, ch); /* find the spindle */ if(ch != '\0') { if(sscanf(s - 1, "%d", &spindle) != 1) { - err_extra = "bad spindle"; + err_extra = stralloc("bad spindle"); goto err; /* bad spindle */ } skip_integer(s, ch); - skip_whitespace(s, ch); /* find the exclusion list */ + skip_whitespace(s, ch); /* find the parameters */ if(ch != '\0') { if(strncmp(s-1, "OPTIONS |;",10) == 0) { options = parse_options(s + 8, @@ -257,32 +345,61 @@ char **argv; 0); } else { - options = alloc(sizeof(option_t)); + options = alloc(SIZEOF(option_t)); init_options(options); - if(strncmp(s-1, "exclude-file=", 13) == 0) { - options->exclude_file = - append_sl(options->exclude_file, s+12); - } - if(strncmp(s-1, "exclude-list=", 13) == 0) { - options->exclude_list = - append_sl(options->exclude_list, s+12); - } - - skip_non_whitespace(s, ch); - if(ch) { - err_extra = "extra text at end"; - goto err; /* should have gotten to end */ + while (ch != '\0') { + if(strncmp(s-1, "exclude-file=", 13) == 0) { + qlist = unquote_string(s+12); + options->exclude_file = + append_sl(options->exclude_file, qlist); + amfree(qlist); + } else if(strncmp(s-1, "exclude-list=", 13) == 0) { + options->exclude_list = + append_sl(options->exclude_list, qlist); + qlist = unquote_string(s+12); + amfree(qlist); + } else if(strncmp(s-1, "include-file=", 13) == 0) { + options->include_file = + append_sl(options->include_file, qlist); + qlist = unquote_string(s+12); + amfree(qlist); + } else if(strncmp(s-1, "include-list=", 13) == 0) { + options->include_list = + append_sl(options->include_list, qlist); + qlist = unquote_string(s+12); + amfree(qlist); + } else { + err_extra = vstralloc("Invalid parameter (", + s-1, ")", NULL); + goto err; /* should have gotten to end */ + } + skip_quoted_string(s, ch); + skip_whitespace(s, ch); /* find the inclusion list */ + amfree(qlist); } } } else { - options = alloc(sizeof(option_t)); + options = alloc(SIZEOF(option_t)); init_options(options); } } + else { + options = alloc(SIZEOF(option_t)); + init_options(options); + } - add_diskest(disk, amdevice, level, spindle, prog, options); + /*@ignore@*/ + add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options); + /*@end@*/ + amfree(disk); + amfree(qdisk); amfree(amdevice); + amfree(qamdevice); + } + if (g_options == NULL) { + error("Missing OPTIONS line in sendsize input\n"); + /*NOTREACHED*/ } amfree(line); @@ -309,6 +426,7 @@ char **argv; child_pid = wait(&child_status); if(child_pid == -1) { error("wait failed: %s", strerror(errno)); + /*NOTREACHED*/ } if(WIFSIGNALED(child_status)) { dbprintf(("%s: child %ld terminated with signal %d\n", @@ -395,6 +513,7 @@ char **argv; exit(0); } else if(est->child == -1) { error("calc_estimates fork failed: %s", strerror(errno)); + /*NOTREACHED*/ } dumpsrunning++; /* parent */ } @@ -412,17 +531,17 @@ 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); +#if defined(USE_DBMALLOC) malloc_size_2 = malloc_inuse(&malloc_hist_2); if(malloc_size_1 != malloc_size_2) { -#if defined(USE_DBMALLOC) malloc_list(dbfd(), malloc_hist_1, malloc_hist_2); -#endif } +#endif dbclose(); return 0; @@ -432,21 +551,33 @@ char **argv; debug_prefix_time(NULL), err_extra ? ": " : "", err_extra ? err_extra : "")); + amfree(err_extra); dbclose(); return 1; } -void add_diskest(disk, amdevice, level, spindle, prog, options) -char *disk, *amdevice, *prog; -int level, spindle; -option_t *options; +void +add_diskest( + char * disk, + char * amdevice, + int level, + int spindle, + int program_is_wrapper, + char * prog, + char * calcprog, + option_t * options) { disk_estimates_t *newp, *curp; amandates_t *amdp; int dumplev, estlev; time_t dumpdate; + if (level < 0) + level = 0; + if (level >= DUMP_LEVELS) + level = DUMP_LEVELS - 1; + for(curp = est_list; curp != NULL; curp = curp->next) { if(strcmp(curp->amname, disk) == 0) { /* already have disk info, just note the level request */ @@ -456,6 +587,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); } @@ -463,14 +595,22 @@ option_t *options; } } - newp = (disk_estimates_t *) alloc(sizeof(disk_estimates_t)); - memset(newp, 0, sizeof(*newp)); + newp = (disk_estimates_t *) alloc(SIZEOF(disk_estimates_t)); + 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_wrapper = program_is_wrapper; newp->spindle = spindle; newp->est[level].needestimate = 1; newp->options = options; @@ -490,12 +630,16 @@ option_t *options; } -void free_estimates(est) -disk_estimates_t *est; +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); @@ -503,6 +647,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); } } @@ -512,13 +657,17 @@ disk_estimates_t *est; * */ -void calc_estimates(est) -disk_estimates_t *est; +void +calc_estimates( + disk_estimates_t * est) { - dbprintf(("%s: calculating for amname '%s', dirname '%s', spindle %d\n", + dbprintf(("%s: calculating for amname %s, dirname %s, spindle %d\n", debug_prefix_time(NULL), - est->amname, est->dirname, est->spindle)); - + est->qamname, est->qdirname, 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,109 +684,223 @@ 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->qamname, est->qdirname)); + else +#endif + generic_calc_estimates(est); - dbprintf(("%s: done with amname '%s', dirname '%s', spindle %d\n", + dbprintf(("%s: done with amname %s dirname %s spindle %d\n", debug_prefix_time(NULL), - est->amname, est->dirname, est->spindle)); + est->qamname, est->qdirname, est->spindle)); +} + +/* + * ------------------------------------------------------------------------ + * + */ + +/* local functions */ +off_t getsize_dump(char *disk, char *amdevice, int level, option_t *options); +off_t getsize_star(char *disk, char *amdevice, int level, + option_t *options, time_t dumpsince); +off_t getsize_smbtar(char *disk, char *amdevice, int level, option_t *options); +off_t getsize_gnutar(char *disk, char *amdevice, int level, + option_t *options, time_t dumpsince); +off_t getsize_wrapper(char *program, char *disk, char *amdevice, int level, + option_t *options, time_t dumpsince); +off_t handle_dumpline(char *str); +double first_num(char *str); + +void +wrapper_calc_estimates( + disk_estimates_t * est) +{ + int level; + off_t 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->qamname, level)); + size = getsize_wrapper(est->program, est->amname, est->amdevice, + level, est->options, est->est[level].dumpsince); + + amflock(1, "size"); + + if (fseek(stdout, 0L, SEEK_END) < 0) { + dbprintf(("wrapper_calc_estimates: warning - seek failed: %s\n", + strerror(errno))); + } + + printf("%s %d SIZE " OFF_T_FMT "\n", est->qamname, level, + (OFF_T_FMT_TYPE)size); + fflush(stdout); + + amfunlock(1, "size"); + } + } } -void generic_calc_estimates(est) -disk_estimates_t *est; + +void +generic_calc_estimates( + disk_estimates_t * est) { + int pipefd = -1, nullfd = -1; char *cmd; - char *argv[DUMP_LEVELS*2+10]; + char *my_argv[DUMP_LEVELS*2+22]; char number[NUM_STR_SIZE]; - int i, level, argc, calcpid; + int i, level, my_argc, status; + pid_t calcpid; + int nb_exclude = 0; + int nb_include = 0; + char *file_exclude = NULL; + char *file_include = NULL; + times_t start_time; + FILE *dumpout = NULL; + off_t size = (off_t)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"); + if (g_options->config) + my_argv[my_argc++] = stralloc(g_options->config); + 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->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); - dbprintf(("%s: waiting for %s \"%s\" child\n", - debug_prefix_time(NULL), argv[0], est->amdevice)); - wait(NULL); - dbprintf(("%s: after %s \"%s\" wait\n", - debug_prefix_time(NULL), argv[0], est->amdevice)); -} + dumpout = fdopen(pipefd,"r"); + if (!dumpout) { + error("Can't fdopen: %s", strerror(errno)); + /*NOTREACHED*/ + } + match_expr = vstralloc(est->qamname," %d SIZE " OFF_T_FMT, NULL); + for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + if (line[0] == '\0') + continue; + if(sscanf(line, match_expr, &level, &size) == 2) { + printf("%s\n", line); /* write to amandad */ + dbprintf(("%s: estimate size for %s level %d: " OFF_T_FMT " KB\n", + debug_prefix(NULL), + est->qamname, + level, + size)); + } + } + amfree(match_expr); + dbprintf(("%s: waiting for %s %s child (pid=%d)\n", + debug_prefix_time(NULL), my_argv[0], est->qamdevice, calcpid)); + wait(&status); + dbprintf(("%s: after %s %s wait: child pid=%d status=%d\n", + debug_prefix_time(NULL), my_argv[0], est->qamdevice, + calcpid, WEXITSTATUS(status))); -/* - * ------------------------------------------------------------------------ - * - */ + dbprintf(("%s: .....\n", debug_prefix_time(NULL))); + dbprintf(("%s: estimate time for %s: %s\n", + debug_prefix(NULL), + est->qamname, + walltime_str(timessub(curclock(), start_time)))); -/* 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; +common_exit: + for(i = 0; i < my_argc; i++) { + amfree(my_argv[i]); + } + amfree(cmd); +} + + +void +dump_calc_estimates( + disk_estimates_t * est) { int level; - long size; + off_t size; for(level = 0; level < DUMP_LEVELS; level++) { if(est->est[level].needestimate) { dbprintf(("%s: getting size via dump for %s level %d\n", - debug_prefix_time(NULL), est->amname, level)); - size = getsize_dump(est->amname, est->amdevice,level, est->options); + debug_prefix_time(NULL), est->qamname, level)); + size = getsize_dump(est->amname, est->amdevice, + level, est->options); amflock(1, "size"); - fseek(stdout, (off_t)0, SEEK_SET); + if (fseek(stdout, 0L, SEEK_END) < 0) { + dbprintf(("dump_calc_estimates: warning - seek failed: %s\n", + strerror(errno))); + } - printf("%s %d SIZE %ld\n", est->amname, level, size); + printf("%s %d SIZE " OFF_T_FMT "\n", + est->qamname, level, (OFF_T_FMT_TYPE)size); fflush(stdout); amfunlock(1, "size"); @@ -646,23 +909,28 @@ disk_estimates_t *est; } #ifdef SAMBA_CLIENT -void smbtar_calc_estimates(est) -disk_estimates_t *est; +void +smbtar_calc_estimates( + disk_estimates_t * est) { int level; - long size; + off_t size; for(level = 0; level < DUMP_LEVELS; level++) { if(est->est[level].needestimate) { dbprintf(("%s: getting size via smbclient for %s level %d\n", - debug_prefix_time(NULL), est->amname, level)); + debug_prefix_time(NULL), est->qamname, level)); size = getsize_smbtar(est->amname, est->amdevice, level, est->options); amflock(1, "size"); - fseek(stdout, (off_t)0, SEEK_SET); + if (fseek(stdout, 0L, SEEK_END) < 0) { + dbprintf(("smbtar_calc_estimates: warning - seek failed: %s\n", + strerror(errno))); + } - printf("%s %d SIZE %ld\n", est->amname, level, size); + printf("%s %d SIZE " OFF_T_FMT "\n", + est->qamname, level, (OFF_T_FMT_TYPE)size); fflush(stdout); amfunlock(1, "size"); @@ -672,24 +940,29 @@ disk_estimates_t *est; #endif #ifdef GNUTAR -void gnutar_calc_estimates(est) -disk_estimates_t *est; +void +gnutar_calc_estimates( + disk_estimates_t * est) { int level; - long size; + off_t size; for(level = 0; level < DUMP_LEVELS; level++) { if (est->est[level].needestimate) { dbprintf(("%s: getting size via gnutar for %s level %d\n", - debug_prefix_time(NULL), est->amname, level)); + debug_prefix_time(NULL), est->qamname, level)); size = getsize_gnutar(est->amname, est->amdevice, level, est->options, est->est[level].dumpsince); amflock(1, "size"); - fseek(stdout, (off_t)0, SEEK_SET); + if (fseek(stdout, 0L, SEEK_END) < 0) { + dbprintf(("gnutar_calc_estimates: warning - seek failed: %s\n", + strerror(errno))); + } - printf("%s %d SIZE %ld\n", est->amname, level, size); + printf("%s %d SIZE " OFF_T_FMT "\n", + est->qamname, level, (OFF_T_FMT_TYPE)size); fflush(stdout); amfunlock(1, "size"); @@ -703,12 +976,13 @@ typedef struct regex_s { int scale; } regex_t; +/*@ignore@*/ regex_t re_size[] = { #ifdef DUMP {" DUMP: estimated -*[0-9][0-9]* tape blocks", 1024}, {" DUMP: [Ee]stimated [0-9][0-9]* blocks", 512}, - {" DUMP: [Ee]stimated [0-9][0-9]* bytes", 1}, /* Ultrix 4.4 */ - {" UFSDUMP: estimated [0-9][0-9]* blocks", 512}, /* NEC EWS-UX */ + {" DUMP: [Ee]stimated [0-9][0-9]* bytes", 1}, /* Ultrix 4.4 */ + {" UFSDUMP: estimated [0-9][0-9]* blocks", 512}, /* NEC EWS-UX */ {"dump: Estimate: [0-9][0-9]* tape blocks", 1024}, /* OSF/1 */ {"backup: There are an estimated [0-9][0-9]* tape blocks.",1024}, /* AIX */ {"backup: estimated [0-9][0-9]* 1k blocks", 1024}, /* AIX */ @@ -716,37 +990,33 @@ regex_t re_size[] = { {"backup: [0-9][0-9]* tape blocks on [0-9][0-9]* tape(s)",1024}, /* AIX */ {"backup: [0-9][0-9]* 1k blocks on [0-9][0-9]* volume(s)",1024}, /* AIX */ {"dump: Estimate: [0-9][0-9]* blocks being output to pipe",1024}, - /* DU 4.0 dump */ - {"dump: Dumping [0-9][0-9]* bytes, ", 1}, /* DU 4.0 vdump */ - {"DUMP: estimated [0-9][0-9]* KB output", 1024}, /* HPUX */ - {"DUMP: estimated [0-9][0-9]* KB\\.", 1024}, /* NetApp */ - {" UFSDUMP: estimated [0-9][0-9]* blocks", 512}, /* Sinix */ + /* DU 4.0 dump */ + {"dump: Dumping [0-9][0-9]* bytes, ", 1}, /* DU 4.0 vdump */ + {"DUMP: estimated [0-9][0-9]* KB output", 1024}, /* HPUX */ + {"DUMP: estimated [0-9][0-9]* KB\\.", 1024}, /* NetApp */ + {" UFSDUMP: estimated [0-9][0-9]* blocks", 512}, /* Sinix */ #ifdef HAVE_DUMP_ESTIMATE {"[0-9][0-9]* blocks, [0-9][0-9]*.[0-9][0-9]* volumes", 1024}, - /* DU 3.2g dump -E */ - {"^[0-9][0-9]* blocks$", 1024}, /* DU 4.0 dump -E */ - {"^[0-9][0-9]*$", 1}, /* Solaris ufsdump -S */ + /* DU 3.2g dump -E */ + {"^[0-9][0-9]* blocks$", 1024}, /* DU 4.0 dump -E */ + {"^[0-9][0-9]*$", 1}, /* Solaris ufsdump -S */ #endif #endif #ifdef VDUMP - {"vdump: Dumping [0-9][0-9]* bytes, ", 1}, /* OSF/1 vdump */ + {"vdump: Dumping [0-9][0-9]* bytes, ", 1}, /* OSF/1 vdump */ #endif #ifdef VXDUMP - {"vxdump: estimated [0-9][0-9]* blocks", 512}, /* HPUX's vxdump */ - {" VXDUMP: estimated [0-9][0-9]* blocks", 512}, /* Sinix */ + {"vxdump: estimated [0-9][0-9]* blocks", 512}, /* HPUX's vxdump */ + {" VXDUMP: estimated [0-9][0-9]* blocks", 512}, /* Sinix */ #endif #ifdef XFSDUMP {"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 @@ -763,16 +1033,18 @@ regex_t re_size[] = { { NULL, 0 } }; - - -long getsize_dump(disk, amdevice, level, options) - char *disk, *amdevice; - int level; - option_t *options; +/*@end@*/ + +off_t +getsize_dump( + char *disk, + char *amdevice, + int level, + option_t * options) { int pipefd[2], nullfd, stdoutfd, killctl[2]; pid_t dumppid; - long size; + off_t size; FILE *dumpout; char *dumpkeys = NULL; char *device = NULL; @@ -784,21 +1056,55 @@ long getsize_dump(disk, amdevice, level, options) char level_str[NUM_STR_SIZE]; int s; times_t start_time; + char *qdisk = quote_string(disk); + char *qdevice; + char *config; +#if defined(DUMP) || defined(VDUMP) || defined(VXDUMP) || defined(XFSDUMP) + int is_rundump = 1; +#endif + + (void)options; /* Quiet unused parameter warning */ + + (void)getsize_smbtar; /* Quiet unused parameter warning */ - ap_snprintf(level_str, sizeof(level_str), "%d", level); + snprintf(level_str, SIZEOF(level_str), "%d", level); device = amname_to_devname(amdevice); + qdevice = quote_string(device); fstype = amname_to_fstype(amdevice); - dbprintf(("%s: calculating for device '%s' with '%s'\n", - debug_prefix_time(NULL), device, fstype)); + dbprintf(("%s: calculating for device %s with %s\n", + debug_prefix_time(NULL), qdevice, fstype)); cmd = vstralloc(libexecdir, "/rundump", versionsuffix(), NULL); rundump_cmd = stralloc(cmd); - - stdoutfd = nullfd = open("/dev/null", O_RDWR); + if (g_options->config) + config = g_options->config; + else + config = "NOCONFIG"; + 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); + amfree(qdevice); + amfree(qdisk); + return(-1); + } pipefd[0] = pipefd[1] = killctl[0] = killctl[1] = -1; - pipe(pipefd); + if (pipe(pipefd) < 0) { + dbprintf(("getsize_dump could create data pipes: %s\n", + strerror(errno))); + amfree(cmd); + amfree(rundump_cmd); + amfree(fstype); + amfree(device); + amfree(qdevice); + amfree(qdisk); + return(-1); + } #ifdef XFSDUMP /* { */ #ifdef DUMP /* { */ @@ -807,9 +1113,9 @@ long getsize_dump(disk, amdevice, level, options) if (1) #endif /* } */ { - name = stralloc(" (xfsdump)"); + name = stralloc(" (xfsdump)"); dbprintf(("%s: running \"%s%s -F -J -l %s - %s\"\n", - debug_prefix_time(NULL), cmd, name, level_str, device)); + debug_prefix_time(NULL), cmd, name, level_str, qdevice)); } else #endif /* } */ @@ -821,14 +1127,16 @@ long getsize_dump(disk, amdevice, level, options) #endif /* } */ { #ifdef USE_RUNDUMP - name = stralloc(" (vxdump)"); + name = stralloc(" (vxdump)"); #else name = stralloc(""); cmd = newstralloc(cmd, VXDUMP); + config = skip_argument; + is_rundump = 0; #endif dumpkeys = vstralloc(level_str, "s", "f", NULL); - dbprintf(("%s: running \"%s%s %s 1048576 - %s\"\n", - debug_prefix_time(NULL), cmd, name, dumpkeys, device)); + dbprintf(("%s: running \"%s%s %s 1048576 - %s\"\n", + debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice)); } else #endif /* } */ @@ -841,10 +1149,12 @@ long getsize_dump(disk, amdevice, level, options) { name = stralloc(" (vdump)"); amfree(device); + amfree(qdevice); device = amname_to_dirname(amdevice); + qdevice = quote_string(device); dumpkeys = vstralloc(level_str, "b", "f", NULL); dbprintf(("%s: running \"%s%s %s 60 - %s\"\n", - debug_prefix_time(NULL), cmd, name, dumpkeys, device)); + debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice)); } else #endif /* } */ @@ -859,20 +1169,28 @@ long getsize_dump(disk, amdevice, level, options) # else /* } { */ name = stralloc(""); cmd = newstralloc(cmd, DUMP); + config = skip_argument; + is_rundump = 0; # endif /* } */ # ifdef AIX_BACKUP /* { */ dumpkeys = vstralloc("-", level_str, "f", NULL); dbprintf(("%s: running \"%s%s %s - %s\"\n", - debug_prefix_time(NULL), cmd, name, dumpkeys, device)); + debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice)); # else /* } { */ +# ifdef HAVE_DUMP_ESTIMATE +# define PARAM_DUMP_ESTIMATE HAVE_DUMP_ESTIMATE +# else +# define PARAM_DUMP_ESTIMATE "" +# endif +# ifdef HAVE_HONOR_NODUMP +# define PARAM_HONOR_NODUMP "h" +# else +# define PARAM_HONOR_NODUMP "" +# endif dumpkeys = vstralloc(level_str, -# ifdef HAVE_DUMP_ESTIMATE /* { */ - HAVE_DUMP_ESTIMATE, -# endif /* } */ -# ifdef HAVE_HONOR_NODUMP /* { */ - "h", -# endif /* } */ + PARAM_DUMP_ESTIMATE, + PARAM_DUMP_ESTIMATE, "s", "f", NULL); # ifdef HAVE_DUMP_ESTIMATE @@ -881,10 +1199,10 @@ long getsize_dump(disk, amdevice, level, options) # ifdef HAVE_HONOR_NODUMP /* { */ dbprintf(("%s: running \"%s%s %s 0 1048576 - %s\"\n", - debug_prefix_time(NULL), cmd, name, dumpkeys, device)); + debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice)); # else /* } { */ dbprintf(("%s: running \"%s%s %s 1048576 - %s\"\n", - debug_prefix_time(NULL), cmd, name, dumpkeys, device)); + debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice)); # endif /* } */ # endif /* } */ } @@ -892,9 +1210,15 @@ long getsize_dump(disk, amdevice, level, options) #endif /* } */ { error("no dump program available"); + /*NOTREACHED*/ } - pipe(killctl); + if (pipe(killctl) < 0) { + dbprintf(("%s: Could not create pipe: %s\n", + debug_prefix(NULL), strerror(errno))); + /* Message will be printed later... */ + killctl[0] = killctl[1] = -1; + } start_time = curclock(); switch(dumppid = fork()) { @@ -905,7 +1229,10 @@ long getsize_dump(disk, amdevice, level, options) amfree(cmd); amfree(rundump_cmd); amfree(device); + amfree(qdevice); + amfree(qdisk); amfree(name); + amfree(fstype); return -1; default: break; @@ -913,8 +1240,7 @@ long getsize_dump(disk, amdevice, level, options) if(SETPGRP == -1) SETPGRP_FAILED(); else if (killctl[0] == -1 || killctl[1] == -1) - dbprintf(("%s: pipe for killpgrp failed, trying without killpgrp\n", - debug_prefix(NULL))); + dbprintf(("%s: Trying without killpgrp\n", debug_prefix(NULL))); else { switch(fork()) { case -1: @@ -924,6 +1250,7 @@ long getsize_dump(disk, amdevice, level, options) default: { + char *config; char *killpgrp_cmd = vstralloc(libexecdir, "/killpgrp", versionsuffix(), NULL); dbprintf(("%s: running %s\n", @@ -935,7 +1262,12 @@ long getsize_dump(disk, amdevice, level, options) close(pipefd[1]); close(killctl[1]); close(nullfd); - execle(killpgrp_cmd, killpgrp_cmd, (char *)0, safe_env()); + if (g_options->config) + config = g_options->config; + else + config = "NOCONFIG"; + execle(killpgrp_cmd, killpgrp_cmd, config, (char *)0, + safe_env()); dbprintf(("%s: cannot execute %s: %s\n", debug_prefix(NULL), killpgrp_cmd, strerror(errno))); exit(-1); @@ -961,8 +1293,12 @@ long getsize_dump(disk, amdevice, level, options) #else if (1) #endif - execle(cmd, "xfsdump", "-F", "-J", "-l", level_str, "-", device, - (char *)0, safe_env()); + if (is_rundump) + execle(cmd, "rundump", config, "xfsdump", "-F", "-J", "-l", + level_str, "-", device, (char *)0, safe_env()); + else + execle(cmd, "xfsdump", "-F", "-J", "-l", + level_str, "-", device, (char *)0, safe_env()); else #endif #ifdef VXDUMP @@ -971,8 +1307,12 @@ long getsize_dump(disk, amdevice, level, options) #else if (1) #endif - execle(cmd, "vxdump", dumpkeys, "1048576", "-", device, (char *)0, - safe_env()); + if (is_rundump) + execle(cmd, "rundump", config, "vxdump", dumpkeys, "1048576", + "-", device, (char *)0, safe_env()); + else + execle(cmd, "vxdump", dumpkeys, "1048576", "-", + device, (char *)0, safe_env()); else #endif #ifdef VDUMP @@ -981,24 +1321,42 @@ long getsize_dump(disk, amdevice, level, options) #else if (1) #endif - execle(cmd, "vdump", dumpkeys, "60", "-", device, (char *)0, - safe_env()); + if (is_rundump) + execle(cmd, "rundump", config, "vdump", dumpkeys, "60", "-", + device, (char *)0, safe_env()); + else + execle(cmd, "vdump", dumpkeys, "60", "-", + device, (char *)0, safe_env()); else #endif #ifdef DUMP # ifdef AIX_BACKUP - execle(cmd, "backup", dumpkeys, "-", device, (char *)0, safe_env()); + if (is_rundump) + execle(cmd, "rundump", config, "backup", dumpkeys, "-", + device, (char *)0, safe_env()); + else + execle(cmd, "backup", dumpkeys, "-", + device, (char *)0, safe_env()); # else - execle(cmd, "dump", dumpkeys, + if (is_rundump) { + execle(cmd, "rundump", config, "dump", dumpkeys, #ifdef HAVE_HONOR_NODUMP - "0", + "0", #endif - "1048576", "-", device, (char *)0, safe_env()); + "1048576", "-", device, (char *)0, safe_env()); + } else { + execle(cmd, "dump", dumpkeys, +#ifdef HAVE_HONOR_NODUMP + "0", +#endif + "1048576", "-", device, (char *)0, safe_env()); + } # endif #endif { error("exec %s failed or no dump program available: %s", cmd, strerror(errno)); + /*NOTREACHED*/ } } @@ -1009,13 +1367,24 @@ long getsize_dump(disk, amdevice, level, options) if (killctl[0] != -1) aclose(killctl[0]); dumpout = fdopen(pipefd[0],"r"); + if (!dumpout) { + error("Can't fdopen: %s", strerror(errno)); + /*NOTREACHED*/ + } - for(size = -1; (line = agets(dumpout)) != NULL; free(line)) { + for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + if (line[0] == '\0') + continue; dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); size = handle_dumpline(line); - if(size > -1) { + if(size > (off_t)-1) { amfree(line); - if((line = agets(dumpout)) != NULL) { + while ((line = agets(dumpout)) != NULL) { + if (line[0] != '\0') + break; + amfree(line); + } + if (line != NULL) { dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); } break; @@ -1026,23 +1395,26 @@ long getsize_dump(disk, amdevice, level, options) dbprintf(("%s: .....\n", debug_prefix_time(NULL))); dbprintf(("%s: estimate time for %s level %d: %s\n", debug_prefix(NULL), - disk, + qdisk, level, walltime_str(timessub(curclock(), start_time)))); - if(size == -1) { + if(size == (off_t)-1) { 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))); - } else if(size == 0 && level == 0) { + dbprintf(("%s: Run %s%s manually to check for errors\n", + debug_prefix(NULL), cmd, name)); + } else if(size == (off_t)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, + qdisk, level, size)); + } if (killctl[1] != -1) { dbprintf(("%s: asking killpgrp to terminate\n", @@ -1085,10 +1457,10 @@ long getsize_dump(disk, amdevice, level, options) } dbprintf(("%s: waiting for %s%s \"%s\" child\n", - debug_prefix_time(NULL), cmd, name, disk)); + debug_prefix_time(NULL), cmd, name, qdisk)); wait(NULL); - dbprintf(("%s: after %s%s \"%s\" wait\n", - debug_prefix_time(NULL), cmd, name, disk)); + dbprintf(("%s: after %s%s %s wait\n", + debug_prefix_time(NULL), cmd, name, qdisk)); terminated: @@ -1096,6 +1468,8 @@ long getsize_dump(disk, amdevice, level, options) afclose(dumpout); amfree(device); + amfree(qdevice); + amfree(qdisk); amfree(fstype); amfree(cmd); @@ -1105,24 +1479,29 @@ long getsize_dump(disk, amdevice, level, options) } #ifdef SAMBA_CLIENT -long getsize_smbtar(disk, amdevice, level, optionns) - char *disk, *amdevice; - int level; - option_t *optionns; +off_t +getsize_smbtar( + char *disk, + char *amdevice, + int level, + option_t * options) { int pipefd = -1, nullfd = -1, passwdfd = -1; - int dumppid; - long size; + pid_t dumppid; + off_t size; FILE *dumpout; char *tarkeys, *sharename, *user_and_password = NULL, *domain = NULL; char *share = NULL, *subdir = NULL; - int lpass; + size_t lpass; char *pwtext; - int pwtext_len; + size_t pwtext_len; char *line; char *pw_fd_env; times_t start_time; char *error_pn = NULL; + char *qdisk = quote_string(disk); + + (void)options; /* Quiet unused parameter warning */ error_pn = stralloc2(get_pname(), "-smbclient"); @@ -1132,14 +1511,16 @@ long getsize_smbtar(disk, amdevice, level, optionns) amfree(subdir); set_pname(error_pn); amfree(error_pn); - error("cannot parse disk entry '%s' for share/subdir", disk); + 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", disk); + error("subdirectory specified for share %s but samba not v2 or better", qdisk); + /*NOTREACHED*/ } if ((user_and_password = findpass(share, &domain)) == NULL) { @@ -1150,10 +1531,11 @@ long getsize_smbtar(disk, amdevice, level, optionns) set_pname(error_pn); amfree(error_pn); error("cannot find password for %s", disk); + /*NOTREACHED*/ } lpass = strlen(user_and_password); if ((pwtext = strchr(user_and_password, '%')) == NULL) { - memset(user_and_password, '\0', lpass); + memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); if(domain) { memset(domain, '\0', strlen(domain)); @@ -1162,11 +1544,12 @@ long getsize_smbtar(disk, amdevice, level, optionns) set_pname(error_pn); amfree(error_pn); error("password field not \'user%%pass\' for %s", disk); + /*NOTREACHED*/ } *pwtext++ = '\0'; pwtext_len = strlen(pwtext); if ((sharename = makesharename(share, 0)) == NULL) { - memset(user_and_password, '\0', lpass); + memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); if(domain) { memset(domain, '\0', strlen(domain)); @@ -1175,8 +1558,22 @@ long getsize_smbtar(disk, amdevice, level, optionns) set_pname(error_pn); amfree(error_pn); error("cannot make share name of %s", share); + /*NOTREACHED*/ + } + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + memset(user_and_password, '\0', (size_t)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)); + /*NOTREACHED*/ } - nullfd = open("/dev/null", O_RDWR); #if SAMBA_VERSION >= 2 if (level == 0) @@ -1219,17 +1616,18 @@ long getsize_smbtar(disk, amdevice, level, optionns) amfree(domain); } aclose(nullfd); - if(pwtext_len > 0 && fullwrite(passwdfd, pwtext, pwtext_len) < 0) { + if(pwtext_len > 0 && fullwrite(passwdfd, pwtext, (size_t)pwtext_len) < 0) { int save_errno = errno; - memset(user_and_password, '\0', lpass); + memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); aclose(passwdfd); set_pname(error_pn); amfree(error_pn); error("password write failed: %s", strerror(save_errno)); + /*NOTREACHED*/ } - memset(user_and_password, '\0', lpass); + memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); aclose(passwdfd); amfree(sharename); @@ -1237,13 +1635,24 @@ long getsize_smbtar(disk, amdevice, level, optionns) amfree(subdir); amfree(error_pn); dumpout = fdopen(pipefd,"r"); + if (!dumpout) { + error("Can't fdopen: %s", strerror(errno)); + /*NOTREACHED*/ + } - for(size = -1; (line = agets(dumpout)) != NULL; free(line)) { + for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + if (line[0] == '\0') + continue; dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); size = handle_dumpline(line); if(size > -1) { amfree(line); - if((line = agets(dumpout)) != NULL) { + while ((line = agets(dumpout)) != NULL) { + if (line[0] != '\0') + break; + amfree(line); + } + if(line != NULL) { dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); } break; @@ -1254,50 +1663,54 @@ long getsize_smbtar(disk, amdevice, level, optionns) dbprintf(("%s: .....\n", debug_prefix_time(NULL))); dbprintf(("%s: estimate time for %s level %d: %s\n", debug_prefix(NULL), - disk, + qdisk, level, walltime_str(timessub(curclock(), start_time)))); - if(size == -1) { + if(size == (off_t)-1) { dbprintf(("%s: no size line match in %s output for \"%s\"\n", debug_prefix(NULL), SAMBA_CLIENT, disk)); dbprintf(("%s: .....\n", debug_prefix(NULL))); - } else if(size == 0 && level == 0) { + } else if(size == (off_t)0 && level == 0) { dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n", debug_prefix(NULL), SAMBA_CLIENT, disk)); dbprintf(("%s: .....\n", debug_prefix(NULL))); } dbprintf(("%s: estimate size for %s level %d: %ld KB\n", debug_prefix(NULL), - disk, + qdisk, level, size)); kill(-dumppid, SIGTERM); dbprintf(("%s: waiting for %s \"%s\" child\n", - debug_prefix_time(NULL), SAMBA_CLIENT, disk)); + debug_prefix_time(NULL), SAMBA_CLIENT, qdisk)); wait(NULL); - dbprintf(("%s: after %s \"%s\" wait\n", - debug_prefix_time(NULL), SAMBA_CLIENT, disk)); + dbprintf(("%s: after %s %s wait\n", + debug_prefix_time(NULL), SAMBA_CLIENT, qdisk)); afclose(dumpout); pipefd = -1; amfree(error_pn); + amfree(qdisk); return size; } #endif #ifdef GNUTAR -long getsize_gnutar(disk, amdevice, level, options, dumpsince) -char *disk, *amdevice; -int level; -option_t *options; -time_t dumpsince; +off_t +getsize_gnutar( + char *disk, + char *amdevice, + int level, + option_t * options, + time_t dumpsince) { - int pipefd = -1, nullfd = -1, dumppid; - long size = -1; + int pipefd = -1, nullfd = -1; + pid_t dumppid; + off_t size = (off_t)-1; FILE *dumpout = NULL; char *incrname = NULL; char *basename = NULL; @@ -1316,6 +1729,11 @@ time_t dumpsince; char *file_exclude = NULL; char *file_include = NULL; times_t start_time; + int infd, outfd; + ssize_t nb; + char buf[32768]; + char *qdisk = quote_string(disk); + char *gnutar_list_dir; if(options->exclude_file) nb_exclude += options->exclude_file->nb_element; if(options->exclude_list) nb_exclude += options->exclude_list->nb_element; @@ -1325,17 +1743,19 @@ time_t dumpsince; if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 0); if(nb_include > 0) file_include = build_include(disk, amdevice, options, 0); - my_argv = alloc(sizeof(char *) * 21); + my_argv = alloc(SIZEOF(char *) * 22); i = 0; -#ifdef GNUTAR_LISTED_INCREMENTAL_DIR - { + gnutar_list_dir = client_getconf_str(CLN_GNUTAR_LIST_DIR); + if (strlen(gnutar_list_dir) == 0) + gnutar_list_dir = NULL; + if (gnutar_list_dir) { char number[NUM_STR_SIZE]; char *s; int ch; int baselevel; - basename = vstralloc(GNUTAR_LISTED_INCREMENTAL_DIR, + basename = vstralloc(gnutar_list_dir, "/", g_options->hostname, disk, @@ -1344,12 +1764,12 @@ time_t dumpsince; * The loop starts at the first character of the host name, * not the '/'. */ - s = basename + sizeof(GNUTAR_LISTED_INCREMENTAL_DIR); + s = basename + strlen(gnutar_list_dir) + 1; while((ch = *s++) != '\0') { 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); @@ -1359,15 +1779,16 @@ time_t dumpsince; * be true for a level 0), arrange to read from /dev/null. */ baselevel = level; - while (in == NULL) { + infd = -1; + while (infd == -1) { if (--baselevel >= 0) { - ap_snprintf(number, sizeof(number), "%d", baselevel); + snprintf(number, SIZEOF(number), "%d", baselevel); inputname = newvstralloc(inputname, basename, "_", number, NULL); } else { inputname = newstralloc(inputname, "/dev/null"); } - if ((in = fopen(inputname, "r")) == NULL) { + if ((infd = open(inputname, O_RDONLY)) == -1) { int save_errno = errno; dbprintf(("%s: gnutar: error opening %s: %s\n", @@ -1381,75 +1802,57 @@ time_t dumpsince; /* * Copy the previous listed incremental file to the new one. */ - if ((out = fopen(incrname, "w")) == NULL) { + if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) { dbprintf(("%s: opening %s: %s\n", debug_prefix(NULL), incrname, strerror(errno))); goto common_exit; } - for (; (line = agets(in)) != NULL; free(line)) { - if (fputs(line, out) == EOF || putc('\n', out) == EOF) { + while ((nb = read(infd, &buf, SIZEOF(buf))) > 0) { + if (fullwrite(outfd, &buf, (size_t)nb) < nb) { dbprintf(("%s: writing to %s: %s\n", debug_prefix(NULL), incrname, strerror(errno))); goto common_exit; } } - amfree(line); - if (ferror(in)) { + if (nb < 0) { dbprintf(("%s: reading from %s: %s\n", debug_prefix(NULL), inputname, strerror(errno))); goto common_exit; } - if (fclose(in) == EOF) { + + if (close(infd) != 0) { dbprintf(("%s: closing %s: %s\n", debug_prefix(NULL), inputname, strerror(errno))); - in = NULL; goto common_exit; } - in = NULL; - if (fclose(out) == EOF) { + if (close(outfd) != 0) { dbprintf(("%s: closing %s: %s\n", debug_prefix(NULL), incrname, strerror(errno))); - out = NULL; goto common_exit; } - out = NULL; amfree(inputname); amfree(basename); } -#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); dirname = amname_to_dirname(amdevice); - - -#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); + my_argv[i++] = "runtar"; + if (g_options->config) + my_argv[i++] = g_options->config; + else + my_argv[i++] = "NOCONFIG"; +#ifdef GNUTAR my_argv[i++] = GNUTAR; #else my_argv[i++] = "tar"; @@ -1460,14 +1863,14 @@ time_t dumpsince; my_argv[i++] = "--directory"; my_argv[i++] = dirname; my_argv[i++] = "--one-file-system"; -#ifdef GNUTAR_LISTED_INCREMENTAL_DIR - my_argv[i++] = "--listed-incremental"; - my_argv[i++] = incrname; -#else - my_argv[i++] = "--incremental"; - my_argv[i++] = "--newer"; - my_argv[i++] = dumptimestr; -#endif + if (gnutar_list_dir) { + my_argv[i++] = "--listed-incremental"; + my_argv[i++] = incrname; + } else { + my_argv[i++] = "--incremental"; + my_argv[i++] = "--newer"; + my_argv[i++] = dumptimestr; + } #ifdef ENABLE_GNUTAR_ATIME_PRESERVE /* --atime-preserve causes gnutar to call * utime() after reading files in order to @@ -1492,26 +1895,39 @@ time_t dumpsince; else { my_argv[i++] = "."; } -#endif /* USE_QUICK_AND_DIRTY_ESTIMATES */ my_argv[i++] = NULL; start_time = curclock(); - nullfd = open("/dev/null", O_RDWR); + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + dbprintf(("Cannot access /dev/null : %s\n", strerror(errno))); + goto common_exit; + } + dumppid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv); - amfree(cmd); - amfree(file_exclude); - amfree(file_include); dumpout = fdopen(pipefd,"r"); + if (!dumpout) { + error("Can't fdopen: %s", strerror(errno)); + /*NOTREACHED*/ + } - for(size = -1; (line = agets(dumpout)) != NULL; free(line)) { + for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + if (line[0] == '\0') + continue; dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); size = handle_dumpline(line); - if(size > -1) { + if(size > (off_t)-1) { amfree(line); - if((line = agets(dumpout)) != NULL) { + while ((line = agets(dumpout)) != NULL) { + if (line[0] != '\0') { + break; + } + amfree(line); + } + if (line != NULL) { dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); + break; } break; } @@ -1521,31 +1937,31 @@ time_t dumpsince; dbprintf(("%s: .....\n", debug_prefix_time(NULL))); dbprintf(("%s: estimate time for %s level %d: %s\n", debug_prefix(NULL), - disk, + qdisk, level, walltime_str(timessub(curclock(), start_time)))); - if(size == -1) { + if(size == (off_t)-1) { dbprintf(("%s: no size line match in %s output for \"%s\"\n", debug_prefix(NULL), my_argv[0], disk)); dbprintf(("%s: .....\n", debug_prefix(NULL))); - } else if(size == 0 && level == 0) { + } else if(size == (off_t)0 && level == 0) { dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n", debug_prefix(NULL), my_argv[0], disk)); dbprintf(("%s: .....\n", debug_prefix(NULL))); } dbprintf(("%s: estimate size for %s level %d: %ld KB\n", debug_prefix(NULL), - disk, + qdisk, level, size)); kill(-dumppid, SIGTERM); dbprintf(("%s: waiting for %s \"%s\" child\n", - debug_prefix_time(NULL), my_argv[0], disk)); + debug_prefix_time(NULL), my_argv[0], qdisk)); wait(NULL); - dbprintf(("%s: after %s \"%s\" wait\n", - debug_prefix_time(NULL), my_argv[0], disk)); + dbprintf(("%s: after %s %s wait\n", + debug_prefix_time(NULL), my_argv[0], qdisk)); common_exit: @@ -1557,6 +1973,10 @@ common_exit: amfree(dirname); amfree(inputname); amfree(my_argv); + amfree(qdisk); + amfree(cmd); + amfree(file_exclude); + amfree(file_include); aclose(nullfd); afclose(dumpout); @@ -1567,12 +1987,173 @@ common_exit: } #endif +off_t +getsize_wrapper( + char *program, + char *disk, + char *amdevice, + int level, + option_t * options, + time_t dumpsince) +{ + int pipefd[2], nullfd; + pid_t dumppid; + off_t size = (off_t)-1; + FILE *dumpout; + char *line = NULL; + char *cmd = NULL; + char dumptimestr[80]; + struct tm *gmtm; + int i, j; + char *argvchild[10]; + char *newoptstr = NULL; + off_t size1, size2; + times_t start_time; + char *qdisk = quote_string(disk); + char *qamdevice = quote_string(amdevice); + + 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")); + + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + dbprintf(("Cannot access /dev/null : %s\n", strerror(errno))); + goto common_exit; + } + + if (pipe(pipefd) < 0) { + dbprintf(("getsize_wrapper could create data pipes: %s\n", + strerror(errno))); + goto common_exit; + } + + start_time = curclock(); + + switch(dumppid = fork()) { + case -1: + size = (off_t)-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)); + /*NOTREACHED*/ + } + amfree(newoptstr); + + aclose(pipefd[1]); + dumpout = fdopen(pipefd[0],"r"); + if (!dumpout) { + error("Can't fdopen: %s", strerror(errno)); + /*NOTREACHED*/ + } + + for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + if (line[0] == '\0') + continue; + dbprintf(("%s: %s\n", debug_prefix_time(NULL), line)); + i = sscanf(line, OFF_T_FMT " " OFF_T_FMT, + (OFF_T_FMT_TYPE *)&size1, + (OFF_T_FMT_TYPE *)&size2); + if(i == 2) { + 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: %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), + qamdevice, + level, + walltime_str(timessub(curclock(), start_time)))); + if(size == (off_t)-1) { + dbprintf(("%s: no size line match in %s output for \"%s\"\n", + debug_prefix(NULL), cmd, qdisk)); + dbprintf(("%s: .....\n", debug_prefix(NULL))); + } else if(size == (off_t)0 && level == 0) { + dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n", + debug_prefix(NULL), cmd, qdisk)); + dbprintf(("%s: .....\n", debug_prefix(NULL))); + } + dbprintf(("%s: estimate size for %s level %d: " OFF_T_FMT " KB\n", + debug_prefix(NULL), + qamdevice, + level, + size)); + + kill(-dumppid, SIGTERM); + + dbprintf(("%s: waiting for %s \"%s\" child\n", + debug_prefix_time(NULL), cmd, qdisk)); + wait(NULL); + dbprintf(("%s: after %s %s wait\n", + debug_prefix_time(NULL), cmd, qdisk)); + + aclose(nullfd); + afclose(dumpout); + +common_exit: + + amfree(cmd); + amfree(newoptstr); + amfree(qdisk); + amfree(qamdevice); + return size; +} + -double first_num(str) -char *str; /* * Returns the value of the first integer in a string. */ + +double +first_num( + char * str) { char *start; int ch; @@ -1584,27 +2165,32 @@ char *str; while(isdigit(ch) || (ch == '.')) ch = *str++; str[-1] = '\0'; d = atof(start); - str[-1] = ch; + str[-1] = (char)ch; return d; } -long handle_dumpline(str) -char *str; /* * Checks the dump output line against the error and size regex tables. */ + +off_t +handle_dumpline( + char * str) { regex_t *rp; double size; /* check for size match */ + /*@ignore@*/ for(rp = re_size; rp->regex != NULL; rp++) { if(match(rp->regex, str)) { size = ((first_num(str)*rp->scale+1023.0)/1024.0); - if(size < 0) size = 1; /* found on NeXT -- sigh */ - return (long) size; + if(size < 0.0) + size = 1.0; /* found on NeXT -- sigh */ + return (off_t)size; } } - return -1; + /*@end@*/ + return (off_t)-1; }