+off_t
+getsize_backup_api(
+ char *program,
+ char *disk,
+ char *amdevice,
+ int level,
+ option_t *options,
+ time_t dumpsince,
+ char **errmsg)
+{
+ int pipeinfd[2], pipeoutfd[2], nullfd;
+ pid_t dumppid;
+ off_t size = (off_t)-1;
+ FILE *dumpout, *toolin;
+ char *line = NULL;
+ char *cmd = NULL;
+ char *cmdline;
+ 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);
+ amwait_t wait_status;
+ char levelstr[NUM_STR_SIZE];
+ backup_support_option_t *bsu;
+
+ (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);
+
+ i=0;
+ argvchild[i++] = program;
+ argvchild[i++] = "estimate";
+ if (bsu->message_line == 1) {
+ argvchild[i++] = "--message";
+ argvchild[i++] = "line";
+ }
+ if (g_options->config && bsu->config == 1) {
+ argvchild[i++] = "--config";
+ argvchild[i++] = g_options->config;
+ }
+ if (g_options->hostname && bsu->host == 1) {
+ argvchild[i++] = "--host";
+ argvchild[i++] = g_options->hostname;
+ }
+ argvchild[i++] = "--device";
+ argvchild[i++] = amdevice;
+ if (disk && bsu->disk == 1) {
+ argvchild[i++] = "--disk";
+ argvchild[i++] = disk;
+ }
+ if (level <= bsu->max_level) {
+ argvchild[i++] = "--level";
+ g_snprintf(levelstr,SIZEOF(levelstr),"%d",level);
+ argvchild[i++] = levelstr;
+ }
+
+ argvchild[i] = NULL;
+
+ cmdline = stralloc(cmd);
+ for(j = 1; j < i; j++)
+ cmdline = vstrextend(&cmdline, " ", argvchild[i], 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);
+ goto common_exit;
+ }
+
+ if (pipe(pipeinfd) < 0) {
+ *errmsg = vstrallocf(_("getsize_backup_api could create data pipes: %s"),
+ strerror(errno));
+ dbprintf("%s\n", *errmsg);
+ goto common_exit;
+ }
+
+ if (pipe(pipeoutfd) < 0) {
+ *errmsg = vstrallocf(_("getsize_backup_api could create data pipes: %s"),
+ strerror(errno));
+ dbprintf("%s\n", *errmsg);
+ goto common_exit;
+ }
+
+ start_time = curclock();
+
+ switch(dumppid = fork()) {
+ case -1:
+ size = (off_t)-1;
+ goto common_exit;
+ default:
+ break; /* parent */
+ case 0:
+ dup2(pipeinfd[0], 0);
+ dup2(pipeoutfd[1], 1);
+ dup2(nullfd, 2);
+ aclose(pipeinfd[1]);
+ aclose(pipeoutfd[0]);
+ safe_fd(-1, 0);
+
+ execve(cmd, argvchild, safe_env());
+ error(_("exec %s failed: %s"), cmd, strerror(errno));
+ /*NOTREACHED*/
+ }
+ amfree(newoptstr);
+
+ 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);
+
+ dumpout = fdopen(pipeoutfd[0],"r");
+ if (!dumpout) {
+ error(_("Can't fdopen: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+
+ for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
+ long long size1_ = (long long)0;
+ long long size2_ = (long long)0;
+ if (line[0] == '\0')
+ continue;
+ dbprintf("%s\n", line);
+ i = sscanf(line, "%lld %lld", &size1_, &size2_);
+ size1 = (off_t)size1_;
+ size2 = (off_t)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\n"), line);
+ }
+ break;
+ }
+ }
+ 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");
+ }
+ 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());
+ } else if (WIFEXITED(wait_status)) {
+ if (WEXITSTATUS(wait_status) != 0) {
+ *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());
+ }
+ dbprintf(_("after %s %s wait\n"), cmd, qdisk);
+
+ aclose(nullfd);
+ afclose(dumpout);
+
+common_exit:
+
+ amfree(cmd);
+ amfree(newoptstr);
+ amfree(qdisk);
+ amfree(qamdevice);
+ return size;
+}
+