* 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
*/
char *amdevice;
char *dirname;
char *program;
+ char *calcprog;
+ int program_is_wrapper;
int spindle;
pid_t child;
int done;
/* 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 *));
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;
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;
/* 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);
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";
}
}
- add_diskest(disk, amdevice, level, spindle, prog, options);
+ add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options);
amfree(amdevice);
}
amfree(line);
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);
}
-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;
free_sl(options->exclude_list);
free_sl(options->include_file);
free_sl(options->include_list);
+ amfree(options->auth);
amfree(options->str);
amfree(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;
free_sl(est->options->include_file);
free_sl(est->options->include_list);
amfree(est->options->str);
+ amfree(est->options->auth);
amfree(est->options);
}
}
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);
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; i<argc; ++i)
- dbprintf((" %s", argv[i]));
+ if(file_include) {
+ my_argv[my_argc++] = stralloc("-I");
+ my_argv[my_argc++] = file_include;
+ }
+ start_time = curclock();
+
+ dbprintf(("%s: running cmd: %s", debug_prefix_time(NULL), my_argv[0]));
+ for(i=0; i<my_argc; ++i)
+ dbprintf((" %s", my_argv[i]));
for(level = 0; level < DUMP_LEVELS; level++) {
if(est->est[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;
{"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
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);
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);
amfree(rundump_cmd);
amfree(device);
amfree(name);
+ amfree(fstype);
return -1;
default:
break;
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",
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)
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);
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 {
#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);
-#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);
else {
my_argv[i++] = ".";
}
-#endif /* USE_QUICK_AND_DIRTY_ESTIMATES */
my_argv[i++] = NULL;
start_time = curclock();
}
#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;