+off_t
+getsize_application_api(
+ disk_estimates_t *est,
+ int nb_level,
+ int *levels,
+ backup_support_option_t *bsu)
+{
+ dle_t *dle = est->dle;
+ int pipeinfd[2], pipeoutfd[2], pipeerrfd[2];
+ pid_t dumppid;
+ off_t size = (off_t)-1;
+ FILE *dumpout;
+ FILE *dumperr;
+ char *line = NULL;
+ char *cmd = NULL;
+ char *cmdline;
+ guint i;
+ int j;
+ GPtrArray *argv_ptr = g_ptr_array_new();
+ char *newoptstr = NULL;
+ off_t size1, size2;
+ times_t start_time;
+ char *qdisk = quote_string(dle->disk);
+ char *qamdevice = quote_string(dle->device);
+ amwait_t wait_status;
+ char levelstr[NUM_STR_SIZE];
+ GSList *scriptlist;
+ script_t *script;
+ char *errmsg = NULL;
+ estimate_t estimate;
+ estimatelist_t el;
+
+ cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL);
+
+ g_ptr_array_add(argv_ptr, stralloc(dle->program));
+ g_ptr_array_add(argv_ptr, stralloc("estimate"));
+ if (bsu->message_line == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--message"));
+ g_ptr_array_add(argv_ptr, stralloc("line"));
+ }
+ if (g_options->config && bsu->config == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--config"));
+ g_ptr_array_add(argv_ptr, stralloc(g_options->config));
+ }
+ if (g_options->hostname && bsu->host == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--host"));
+ g_ptr_array_add(argv_ptr, stralloc(g_options->hostname));
+ }
+ g_ptr_array_add(argv_ptr, stralloc("--device"));
+ g_ptr_array_add(argv_ptr, stralloc(dle->device));
+ if (dle->disk && bsu->disk == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--disk"));
+ g_ptr_array_add(argv_ptr, stralloc(dle->disk));
+ }
+ for (j=0; j < nb_level; j++) {
+ g_ptr_array_add(argv_ptr, stralloc("--level"));
+ g_snprintf(levelstr,SIZEOF(levelstr),"%d", levels[j]);
+ g_ptr_array_add(argv_ptr, stralloc(levelstr));
+ }
+ /* find the first in ES_CLIENT and ES_CALCSIZE */
+ estimate = ES_CLIENT;
+ for (el = dle->estimatelist; el != NULL; el = el->next) {
+ estimate = (estimate_t)GPOINTER_TO_INT(el->data);
+ if ((estimate == ES_CLIENT && bsu->client_estimate) ||
+ (estimate == ES_CALCSIZE && bsu->calcsize))
+ break;
+ estimate = ES_CLIENT;
+ }
+ if (estimate == ES_CALCSIZE && bsu->calcsize) {
+ g_ptr_array_add(argv_ptr, stralloc("--calcsize"));
+ }
+
+ application_property_add_to_argv(argv_ptr, dle, bsu, g_options->features);
+
+ for (scriptlist = dle->scriptlist; scriptlist != NULL;
+ scriptlist = scriptlist->next) {
+ script = (script_t *)scriptlist->data;
+ if (script->result && script->result->proplist) {
+ property_add_to_argv(argv_ptr, script->result->proplist);
+ }
+ }
+
+ g_ptr_array_add(argv_ptr, NULL);
+
+ cmdline = stralloc(cmd);
+ for(i = 1; i < argv_ptr->len-1; i++)
+ cmdline = vstrextend(&cmdline, " ",
+ (char *)g_ptr_array_index(argv_ptr, i), NULL);
+ dbprintf("running: \"%s\"\n", cmdline);
+ amfree(cmdline);
+
+ if (pipe(pipeerrfd) < 0) {
+ errmsg = vstrallocf(_("getsize_application_api could not create data pipes: %s"),
+ strerror(errno));
+ goto common_exit;
+ }
+
+ if (pipe(pipeinfd) < 0) {
+ errmsg = vstrallocf(_("getsize_application_api could not create data pipes: %s"),
+ strerror(errno));
+ goto common_exit;
+ }
+
+ if (pipe(pipeoutfd) < 0) {
+ errmsg = vstrallocf(_("getsize_application_api could not create data pipes: %s"),
+ 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(pipeinfd[0], 0);
+ dup2(pipeoutfd[1], 1);
+ dup2(pipeerrfd[1], 2);
+ aclose(pipeinfd[1]);
+ aclose(pipeoutfd[0]);
+ aclose(pipeerrfd[0]);
+ safe_fd(-1, 0);
+
+ execve(cmd, (char **)argv_ptr->pdata, safe_env());
+ error(_("exec %s failed: %s"), cmd, strerror(errno));
+ /*NOTREACHED*/
+ }
+ amfree(newoptstr);
+
+ aclose(pipeinfd[0]);
+ aclose(pipeoutfd[1]);
+ aclose(pipeerrfd[1]);
+ aclose(pipeinfd[1]);
+
+ 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;
+ int level = 0;
+ if (line[0] == '\0')
+ continue;
+ dbprintf("%s\n", line);
+ if (strncmp(line,"ERROR ", 6) == 0) {
+ char *errmsg, *qerrmsg;
+
+ errmsg = stralloc(line+6);
+ qerrmsg = quote_string(errmsg);
+ dbprintf(_("errmsg is %s\n"), errmsg);
+ g_printf(_("%s %d ERROR %s\n"), est->qamname, levels[0], qerrmsg);
+ amfree(qerrmsg);
+ continue;
+ }
+ i = sscanf(line, "%d %lld %lld", &level, &size1_, &size2_);
+ if (i != 3) {
+ i = sscanf(line, "%lld %lld", &size1_, &size2_);
+ level = levels[0];
+ if (i != 2) {
+ char *errmsg, *qerrmsg;
+
+ errmsg = vstrallocf(_("bad line %s"), line);
+ qerrmsg = quote_string(errmsg);
+ dbprintf(_("errmsg is %s\n"), errmsg);
+ g_printf(_("%s %d ERROR %s\n"), est->qamname, levels[0], qerrmsg);
+ amfree(qerrmsg);
+ continue;
+ }
+ }
+ size1 = (off_t)size1_;
+ size2 = (off_t)size2_;
+ if (size1 <= 0 || size2 <=0)
+ size = -1;
+ else if (size1 * size2 > 0)
+ size = size1 * size2;
+ dbprintf(_("estimate size for %s level %d: %lld KB\n"),
+ qamdevice,
+ level,
+ (long long)size);
+ g_printf("%s %d SIZE %lld\n", est->qamname, level, (long long)size);
+ }
+ amfree(line);
+
+ dumperr = fdopen(pipeerrfd[0],"r");
+ if (!dumperr) {
+ error(_("Can't fdopen: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+
+ while ((line = agets(dumperr)) != NULL) {
+ if (strlen(line) > 0) {
+ char *err = g_strdup_printf(_("Application '%s': %s"),
+ dle->program, line);
+ char *qerr = quote_string(err);
+ for (j=0; j < nb_level; j++) {
+ fprintf(stdout, "%s %d ERROR %s\n",
+ est->qamname, levels[j], qerr);
+ }
+ dbprintf("ERROR %s", qerr);
+ amfree(err);
+ amfree(qerr);
+ }
+ amfree(line);
+ }
+
+ dbprintf(".....\n");
+ if (nb_level == 1) {
+ dbprintf(_("estimate time for %s level %d: %s\n"), qamdevice,
+ levels[0], walltime_str(timessub(curclock(), start_time)));
+ } else {
+ dbprintf(_("estimate time for %s all level: %s\n"), qamdevice,
+ walltime_str(timessub(curclock(), start_time)));
+ }
+
+ 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);
+
+ afclose(dumpout);
+ afclose(dumperr);
+
+common_exit:
+
+ amfree(cmd);
+ g_ptr_array_free_full(argv_ptr);
+ amfree(newoptstr);
+ amfree(qdisk);
+ amfree(qamdevice);
+ if (errmsg) {
+ char *qerrmsg = quote_string(errmsg);
+ dbprintf(_("errmsg is %s\n"), errmsg);
+ for (j=0; j < nb_level; j++) {
+ g_printf(_("%s %d ERROR %s\n"), est->qamname, levels[j], qerrmsg);
+ }
+ amfree(errmsg);
+ amfree(qerrmsg);
+ }
+ return size;
+}
+