2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: amstar.c 8888 2007-10-02 13:40:42Z martineau $
29 * send estimated backup sizes using dump
34 * STAR-PATH (default STAR)
42 * INCLUDE-LIST (for restore only)
43 * EXCLUDE-LIST (for restore only)
49 #include "pipespawn.h"
50 #include "amfeatures.h"
51 #include "amandates.h"
55 #include "client_util.h"
58 #include "sendbackup.h"
60 int debug_application = 1;
61 #define application_debug(i, ...) do { \
62 if ((i) <= debug_application) { \
63 dbprintf(__VA_ARGS__); \
67 static amregex_t init_re_table[] = {
68 /* tar prints the size in bytes */
69 AM_SIZE_RE("star: [0-9][0-9]* blocks", 10240, 1),
70 AM_NORMAL_RE("^could not open conf file"),
71 AM_NORMAL_RE("^Type of this level "),
72 AM_NORMAL_RE("^Date of this level "),
73 AM_NORMAL_RE("^Date of last level "),
74 AM_NORMAL_RE("^Dump record level "),
75 AM_NORMAL_RE("^Throughput"),
76 AM_NORMAL_RE("^.*is sparse$"),
78 #ifdef IGNORE_TAR_ERRORS
79 AM_NORMAL_RE("^.*shrunk*$"),
80 AM_NORMAL_RE("^.*changed size.*$"),
81 AM_NORMAL_RE("^.*Cannot listxattr for.*$"),
82 AM_NORMAL_RE("^.Cannot: stat .*$"),
83 AM_NORMAL_RE("^.Missing links .*$"),
84 AM_NORMAL_RE("^.Cannot get xattr.*$"),
85 AM_NORMAL_RE("^.Cannot.*acl.*$"),
88 AM_NORMAL_RE("^star: dumped [0-9][0-9]* (tar )?files"),
89 AM_NORMAL_RE("^.*The following problems occurred during .* processing.*$"),
90 AM_NORMAL_RE("^.*Processed all possible files, despite earlier errors.*$"),
91 AM_NORMAL_RE("^.*not written due to problems during backup.*$"),
93 AM_STRANGE_RE("^Perform a level 0 dump first.*$"),
95 /* catch-all: DMP_STRANGE is returned for all other lines */
98 static amregex_t *re_table;
100 /* local functions */
101 int main(int argc, char **argv);
103 typedef struct application_argument_s {
110 GSList *command_options;
114 } application_argument_t;
116 enum { CMD_ESTIMATE, CMD_BACKUP };
118 static void amstar_support(application_argument_t *argument);
119 static void amstar_selfcheck(application_argument_t *argument);
120 static void amstar_estimate(application_argument_t *argument);
121 static void amstar_backup(application_argument_t *argument);
122 static void amstar_restore(application_argument_t *argument);
123 static void amstar_validate(application_argument_t *argument);
124 static GPtrArray *amstar_build_argv(application_argument_t *argument,
128 static char *star_path;
129 static char *star_tardumps;
130 static int star_dle_tardumps;
131 static int star_onefilesystem;
132 static int star_sparse;
133 static char *star_directory;
134 static GSList *normal_message = NULL;
135 static GSList *ignore_message = NULL;
136 static GSList *strange_message = NULL;
138 static struct option long_options[] = {
139 {"config" , 1, NULL, 1},
140 {"host" , 1, NULL, 2},
141 {"disk" , 1, NULL, 3},
142 {"device" , 1, NULL, 4},
143 {"level" , 1, NULL, 5},
144 {"index" , 1, NULL, 6},
145 {"message" , 1, NULL, 7},
146 {"collection" , 0, NULL, 8},
147 {"record" , 0, NULL, 9},
148 {"star-path" , 1, NULL, 10},
149 {"star-tardump" , 1, NULL, 11},
150 {"star-dle-tardump", 1, NULL, 12},
151 {"one-file-system" , 1, NULL, 13},
152 {"sparse" , 1, NULL, 14},
153 {"calcsize" , 0, NULL, 15},
154 {"normal" , 1, NULL, 16},
155 {"ignore" , 1, NULL, 17},
156 {"strange" , 1, NULL, 18},
157 {"include-list" , 1, NULL, 19},
158 {"exclude-list" , 1, NULL, 20},
159 {"directory" , 1, NULL, 21},
160 {"command-options" , 1, NULL, 22},
172 application_argument_t argument;
179 star_tardumps = "/etc/tardumps";
180 star_dle_tardumps = 0;
181 star_onefilesystem = 1;
183 star_directory = NULL;
188 * Configure program for internationalization:
189 * 1) Only set the message locale for now.
190 * 2) Set textdomain for all amanda related programs to "amanda"
191 * We don't want to be forced to support dozens of message catalogs.
193 setlocale(LC_MESSAGES, "C");
194 textdomain("amanda");
197 printf("ERROR no command given to amstar\n");
198 error(_("No command given to amstar"));
201 /* drop root privileges */
202 if (!set_root_privs(0)) {
203 if (strcmp(argv[1], "selfcheck") == 0) {
204 printf("ERROR amstar must be run setuid root\n");
206 error(_("amstar must be run setuid root"));
213 /* Don't die when child closes pipe */
214 signal(SIGPIPE, SIG_IGN);
216 #if defined(USE_DBMALLOC)
217 malloc_size_1 = malloc_inuse(&malloc_hist_1);
220 add_amanda_log_handler(amanda_log_stderr);
221 add_amanda_log_handler(amanda_log_syslog);
222 dbopen(DBG_SUBDIR_CLIENT);
224 dbprintf(_("version %s\n"), VERSION);
226 config_init(CONFIG_INIT_CLIENT, NULL);
228 //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED);
230 //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup
235 argument.config = NULL;
236 argument.host = NULL;
237 argument.message = 0;
238 argument.collection = 0;
239 argument.calcsize = 0;
240 argument.level = NULL;
241 argument.command_options = NULL;
242 init_dle(&argument.dle);
246 int option_index = 0;
247 c = getopt_long (argc, argv, "", long_options, &option_index);
252 case 1: argument.config = stralloc(optarg);
254 case 2: argument.host = stralloc(optarg);
256 case 3: argument.dle.disk = stralloc(optarg);
258 case 4: argument.dle.device = stralloc(optarg);
260 case 5: argument.level = g_slist_append(argument.level,
261 GINT_TO_POINTER(atoi(optarg)));
263 case 6: argument.dle.create_index = 1;
265 case 7: argument.message = 1;
267 case 8: argument.collection = 1;
269 case 9: argument.dle.record = 1;
271 case 10: star_path = stralloc(optarg);
273 case 11: star_tardumps = stralloc(optarg);
275 case 12: if (optarg && strcasecmp(optarg, "NO") == 0)
276 star_dle_tardumps = 0;
277 else if (optarg && strcasecmp(optarg, "YES") == 0)
278 star_dle_tardumps = 1;
279 else if (strcasecmp(command, "selfcheck") == 0)
280 printf(_("ERROR [%s: bad STAR-DLE-TARDUMP property value (%s)]\n"), get_pname(), optarg);
282 case 13: if (optarg && strcasecmp(optarg, "YES") != 0) {
283 /* This option is required to be YES */
284 /* star_onefilesystem = 0; */
287 case 14: if (optarg && strcasecmp(optarg, "NO") == 0)
289 else if (optarg && strcasecmp(optarg, "YES") == 0)
291 else if (strcasecmp(command, "selfcheck") == 0)
292 printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg);
294 case 15: argument.calcsize = 1;
298 g_slist_append(normal_message, optarg);
302 g_slist_append(ignore_message, optarg);
306 g_slist_append(strange_message, optarg);
309 argument.dle.include_list =
310 append_sl(argument.dle.include_list, optarg);
313 argument.dle.exclude_list =
314 append_sl(argument.dle.exclude_list, optarg);
317 star_directory = stralloc(optarg);
319 case 22: argument.command_options =
320 g_slist_append(argument.command_options,
328 if (!argument.dle.disk && argument.dle.device)
329 argument.dle.disk = stralloc(argument.dle.device);
330 if (!argument.dle.device && argument.dle.disk)
331 argument.dle.device = stralloc(argument.dle.disk);
333 argument.argc = argc - optind;
334 argument.argv = argv + optind;
336 if (argument.config) {
337 /* overlay this configuration on the existing (nameless) configuration */
338 config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
340 dbrename(get_config_name(), DBG_SUBDIR_CLIENT);
344 if (config_errors(NULL) >= CFGERR_ERRORS) {
345 g_critical(_("errors processing config file"));
348 re_table = build_re_table(init_re_table, normal_message, ignore_message,
351 if (strcmp(command, "support") == 0) {
352 amstar_support(&argument);
353 } else if (strcmp(command, "selfcheck") == 0) {
354 amstar_selfcheck(&argument);
355 } else if (strcmp(command, "estimate") == 0) {
356 amstar_estimate(&argument);
357 } else if (strcmp(command, "backup") == 0) {
358 amstar_backup(&argument);
359 } else if (strcmp(command, "restore") == 0) {
360 amstar_restore(&argument);
361 } else if (strcmp(command, "validate") == 0) {
362 amstar_validate(&argument);
364 fprintf(stderr, "Unknown command `%s'.\n", command);
372 application_argument_t *argument)
375 fprintf(stdout, "CONFIG YES\n");
376 fprintf(stdout, "HOST YES\n");
377 fprintf(stdout, "DISK YES\n");
378 fprintf(stdout, "MAX-LEVEL 9\n");
379 fprintf(stdout, "INDEX-LINE YES\n");
380 fprintf(stdout, "INDEX-XML NO\n");
381 fprintf(stdout, "MESSAGE-LINE YES\n");
382 fprintf(stdout, "MESSAGE-XML NO\n");
383 fprintf(stdout, "RECORD YES\n");
384 fprintf(stdout, "INCLUDE-FILE NO\n");
385 fprintf(stdout, "INCLUDE-LIST YES\n");
386 fprintf(stdout, "EXCLUDE-FILE YES\n");
387 fprintf(stdout, "EXCLUDE-LIST YES\n");
388 fprintf(stdout, "COLLECTION NO\n");
389 fprintf(stdout, "MULTI-ESTIMATE YES\n");
390 fprintf(stdout, "CALCSIZE YES\n");
391 fprintf(stdout, "CLIENT-ESTIMATE YES\n");
396 application_argument_t *argument)
398 fprintf(stdout, "OK amstar\n");
399 if (argument->dle.disk) {
400 char *qdisk = quote_string(argument->dle.disk);
401 fprintf(stdout, "OK %s\n", qdisk);
404 if (argument->dle.device) {
405 char *qdevice = quote_string(argument->dle.device);
406 fprintf(stdout, "OK %s\n", qdevice);
409 if (star_directory) {
410 char *qdirectory = quote_string(star_directory);
411 fprintf(stdout, "OK %s\n", qdirectory);
415 if (argument->dle.include_list &&
416 argument->dle.include_list->nb_element >= 0) {
417 fprintf(stdout, "ERROR include-list not supported for backup\n");
419 if (argument->dle.exclude_list &&
420 argument->dle.exclude_list->nb_element >= 0) {
421 fprintf(stdout, "ERROR exclude-list not supported for backup\n");
425 fprintf(stdout, "ERROR STAR-PATH not defined\n");
427 check_file(star_path, X_OK);
430 if (argument->calcsize) {
431 char *calcsize = vstralloc(amlibexecdir, "/", "calcsize", NULL);
432 check_file(calcsize, X_OK);
433 check_suid(calcsize);
438 char *amandates_file;
439 amandates_file = getconf_str(CNF_AMANDATES);
440 check_file(amandates_file, R_OK|W_OK);
447 application_argument_t *argument)
453 FILE *dumpout = NULL;
459 amwait_t wait_status;
464 GSList *levels = NULL;
466 if (!argument->level) {
467 fprintf(stderr, "ERROR No level argument\n");
468 error(_("No level argument"));
470 if (!argument->dle.disk) {
471 fprintf(stderr, "ERROR No disk argument\n");
472 error(_("No disk argument"));
474 if (!argument->dle.device) {
475 fprintf(stderr, "ERROR No device argument\n");
476 error(_("No device argument"));
479 if (argument->dle.include_list &&
480 argument->dle.include_list->nb_element >= 0) {
481 fprintf(stderr, "ERROR include-list not supported for backup\n");
483 if (argument->dle.exclude_list &&
484 argument->dle.exclude_list->nb_element >= 0) {
485 fprintf(stderr, "ERROR exclude-list not supported for backup\n");
488 qdisk = quote_string(argument->dle.disk);
489 if (argument->calcsize) {
492 if (star_directory) {
493 dirname = amname_to_dirname(star_directory);
495 dirname = amname_to_dirname(argument->dle.device);
497 run_calcsize(argument->config, "STAR", argument->dle.disk, dirname,
498 argument->level, NULL, NULL);
503 errmsg = vstrallocf(_("STAR-PATH not defined"));
506 cmd = stralloc(star_path);
508 start_time = curclock();
510 for (levels = argument->level; levels != NULL; levels = levels->next) {
511 level = GPOINTER_TO_INT(levels->data);
512 argv_ptr = amstar_build_argv(argument, level, CMD_ESTIMATE);
514 if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
515 errmsg = vstrallocf(_("Cannot access /dev/null : %s"),
520 starpid = pipespawnv(cmd, STDERR_PIPE, 1,
521 &nullfd, &nullfd, &pipefd,
522 (char **)argv_ptr->pdata);
524 dumpout = fdopen(pipefd,"r");
526 errmsg = vstrallocf(_("Can't fdopen: %s"), strerror(errno));
531 while (size < 0 && (fgets(line, sizeof(line), dumpout)) != NULL) {
532 if (line[strlen(line)-1] == '\n') /* remove trailling \n */
533 line[strlen(line)-1] = '\0';
536 dbprintf("%s\n", line);
537 /* check for size match */
539 for(rp = re_table; rp->regex != NULL; rp++) {
540 if(match(rp->regex, line)) {
541 if (rp->typ == DMP_SIZE) {
542 size = ((the_num(line, rp->field)*rp->scale+1023.0)/1024.0);
544 size = 1.0; /* found on NeXT -- sigh */
552 while ((fgets(line, sizeof(line), dumpout)) != NULL) {
553 dbprintf("%s", line);
557 dbprintf(_("estimate time for %s level %d: %s\n"),
560 walltime_str(timessub(curclock(), start_time)));
561 if(size == (off_t)-1) {
562 errmsg = vstrallocf(_("no size line match in %s output"),
564 dbprintf(_("%s for %s\n"), errmsg, qdisk);
566 } else if(size == (off_t)0 && argument->level == 0) {
567 dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"),
568 cmd, argument->dle.disk);
571 dbprintf(_("estimate size for %s level %d: %lld KB\n"),
576 kill(-starpid, SIGTERM);
578 dbprintf(_("waiting for %s \"%s\" child\n"), cmd, qdisk);
579 waitpid(starpid, &wait_status, 0);
580 if (WIFSIGNALED(wait_status)) {
581 errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
582 cmd, WTERMSIG(wait_status), dbfn());
583 } else if (WIFEXITED(wait_status)) {
584 if (WEXITSTATUS(wait_status) != 0) {
585 errmsg = vstrallocf(_("%s exited with status %d: see %s"),
586 cmd, WEXITSTATUS(wait_status), dbfn());
591 errmsg = vstrallocf(_("%s got bad exit: see %s"), cmd, dbfn());
593 dbprintf(_("after %s %s wait\n"), cmd, qdisk);
595 g_ptr_array_free_full(argv_ptr);
600 fprintf(stdout, "%d %lld 1\n", level, (long long)size);
607 dbprintf("%s\n", errmsg);
608 qerrmsg = quote_string(errmsg);
610 dbprintf("%s", errmsg);
611 fprintf(stdout, "ERROR %s\n", qerrmsg);
619 application_argument_t *argument)
626 off_t dump_size = -1;
636 FILE *indexstream = NULL;
642 regex_t regex_special;
643 regex_t regex_symbolic;
646 mesgstream = fdopen(mesgf, "w");
648 error(_("error mesgstream(%d): %s\n"), mesgf, strerror(errno));
651 if (!argument->level) {
652 fprintf(mesgstream, "? No level argument\n");
653 error(_("No level argument"));
655 if (!argument->dle.disk) {
656 fprintf(mesgstream, "? No disk argument\n");
657 error(_("No disk argument"));
659 if (!argument->dle.device) {
660 fprintf(mesgstream, "? No device argument\n");
661 error(_("No device argument"));
664 if (argument->dle.include_list &&
665 argument->dle.include_list->nb_element >= 0) {
666 fprintf(mesgstream, "? include-list not supported for backup\n");
668 if (argument->dle.exclude_list &&
669 argument->dle.exclude_list->nb_element >= 0) {
670 fprintf(mesgstream, "? exclude-list not supported for backup\n");
673 level = GPOINTER_TO_INT(argument->level->data);
675 qdisk = quote_string(argument->dle.disk);
677 argv_ptr = amstar_build_argv(argument, level, CMD_BACKUP);
679 cmd = stralloc(star_path);
681 starpid = pipespawnv(cmd, STDIN_PIPE|STDERR_PIPE, 1,
682 &dumpin, &dataf, &outf, (char **)argv_ptr->pdata);
684 g_ptr_array_free_full(argv_ptr);
685 /* close the write ends of the pipes */
688 if (argument->dle.create_index) {
689 indexstream = fdopen(indexf, "w");
691 error(_("error indexstream(%d): %s\n"), indexf, strerror(errno));
694 outstream = fdopen(outf, "r");
696 error(_("error outstream(%d): %s\n"), outf, strerror(errno));
699 regcomp(®ex_root, "^a \\.\\/ directory$", REG_EXTENDED|REG_NEWLINE);
700 regcomp(®ex_dir, "^a (.*) directory$", REG_EXTENDED|REG_NEWLINE);
701 regcomp(®ex_file, "^a (.*) (.*) bytes", REG_EXTENDED|REG_NEWLINE);
702 regcomp(®ex_special, "^a (.*) special", REG_EXTENDED|REG_NEWLINE);
703 regcomp(®ex_symbolic, "^a (.*) symbolic", REG_EXTENDED|REG_NEWLINE);
704 regcomp(®ex_hard, "^a (.*) link to", REG_EXTENDED|REG_NEWLINE);
706 while ((fgets(line, sizeof(line), outstream)) != NULL) {
707 regmatch_t regmatch[3];
709 if (line[strlen(line)-1] == '\n') /* remove trailling \n */
710 line[strlen(line)-1] = '\0';
712 if (regexec(®ex_root, line, 1, regmatch, 0) == 0) {
713 if (argument->dle.create_index)
714 fprintf(indexstream, "%s\n", "/");
718 if (regexec(®ex_dir, line, 3, regmatch, 0) == 0) {
719 if (argument->dle.create_index && regmatch[1].rm_so == 2) {
720 line[regmatch[1].rm_eo+1]='\0';
721 fprintf(indexstream, "/%s\n", &line[regmatch[1].rm_so]);
726 if (regexec(®ex_file, line, 3, regmatch, 0) == 0 ||
727 regexec(®ex_special, line, 3, regmatch, 0) == 0 ||
728 regexec(®ex_symbolic, line, 3, regmatch, 0) == 0 ||
729 regexec(®ex_hard, line, 3, regmatch, 0) == 0) {
730 if (argument->dle.create_index && regmatch[1].rm_so == 2) {
731 line[regmatch[1].rm_eo]='\0';
732 fprintf(indexstream, "/%s\n", &line[regmatch[1].rm_so]);
737 for (rp = re_table; rp->regex != NULL; rp++) {
738 if (match(rp->regex, line)) {
742 if (rp->typ == DMP_SIZE) {
743 dump_size = (long)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0);
769 dbprintf("%3d: %7s(%c): %s\n", rp->srcline, type, startchr, line);
770 fprintf(mesgstream,"%c %s\n", startchr, line);
773 regfree(®ex_root);
775 regfree(®ex_file);
776 regfree(®ex_special);
777 regfree(®ex_symbolic);
778 regfree(®ex_hard);
780 dbprintf(_("gnutar: %s: pid %ld\n"), cmd, (long)starpid);
782 dbprintf("sendbackup: size %lld\n", (long long)dump_size);
783 fprintf(mesgstream, "sendbackup: size %lld\n", (long long)dump_size);
784 dbprintf("sendbackup: end\n");
785 fprintf(mesgstream, "sendbackup: end\n");
788 if (argument->dle.create_index)
797 application_argument_t *argument)
800 GPtrArray *argv_ptr = g_ptr_array_new();
806 error(_("STAR-PATH not defined"));
809 cmd = stralloc(star_path);
811 g_ptr_array_add(argv_ptr, stralloc(star_path));
812 if (star_directory) {
813 struct stat stat_buf;
814 if(stat(star_directory, &stat_buf) != 0) {
815 fprintf(stderr,"can not stat directory %s: %s\n", star_directory, strerror(errno));
818 if (!S_ISDIR(stat_buf.st_mode)) {
819 fprintf(stderr,"%s is not a directory\n", star_directory);
822 if (access(star_directory, W_OK) != 0 ) {
823 fprintf(stderr, "Can't write to %s: %s\n", star_directory, strerror(errno));
827 g_ptr_array_add(argv_ptr, stralloc("-C"));
828 g_ptr_array_add(argv_ptr, stralloc(star_directory));
830 g_ptr_array_add(argv_ptr, stralloc("-x"));
831 g_ptr_array_add(argv_ptr, stralloc("-v"));
832 g_ptr_array_add(argv_ptr, stralloc("-xattr"));
833 g_ptr_array_add(argv_ptr, stralloc("-acl"));
834 g_ptr_array_add(argv_ptr, stralloc("errctl=WARN|SAMEFILE|SETTIME|DIFF|SETACL|SETXATTR|SETMODE|BADACL *"));
835 g_ptr_array_add(argv_ptr, stralloc("-no-fifo"));
836 g_ptr_array_add(argv_ptr, stralloc("-f"));
837 g_ptr_array_add(argv_ptr, stralloc("-"));
839 if (argument->dle.exclude_list &&
840 argument->dle.exclude_list->nb_element == 1) {
841 g_ptr_array_add(argv_ptr, stralloc("-exclude-from"));
842 g_ptr_array_add(argv_ptr,
843 stralloc(argument->dle.exclude_list->first->name));
846 if (argument->dle.include_list &&
847 argument->dle.include_list->nb_element == 1) {
848 g_ptr_array_add(argv_ptr,
850 argument->dle.include_list->first->name));
852 for (j=1; j< argument->argc; j++)
853 g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]+2));/*remove ./ */
854 g_ptr_array_add(argv_ptr, NULL);
856 debug_executing(argv_ptr);
859 execve(cmd, (char **)argv_ptr->pdata, env);
861 error(_("error [exec %s: %s]"), cmd, e);
867 application_argument_t *argument G_GNUC_UNUSED)
870 GPtrArray *argv_ptr = g_ptr_array_new();
876 dbprintf("STAR-PATH not set; Piping to /dev/null\n");
877 fprintf(stderr,"STAR-PATH not set; Piping to /dev/null\n");
881 cmd = stralloc(star_path);
883 g_ptr_array_add(argv_ptr, stralloc(star_path));
884 g_ptr_array_add(argv_ptr, stralloc("-t"));
885 g_ptr_array_add(argv_ptr, stralloc("-f"));
886 g_ptr_array_add(argv_ptr, stralloc("-"));
887 g_ptr_array_add(argv_ptr, NULL);
889 debug_executing(argv_ptr);
891 execve(cmd, (char **)argv_ptr->pdata, env);
893 dbprintf("failed to execute %s: %s; Piping to /dev/null\n", cmd, e);
894 fprintf(stderr,"failed to execute %s: %s; Piping to /dev/null\n", cmd, e);
896 while (read(0, buf, 32768) > 0) {
901 static GPtrArray *amstar_build_argv(
902 application_argument_t *argument,
908 char levelstr[NUM_STR_SIZE+7];
909 GPtrArray *argv_ptr = g_ptr_array_new();
914 if (star_directory) {
915 dirname = amname_to_dirname(star_directory);
917 dirname = amname_to_dirname(argument->dle.device);
919 fsname = vstralloc("fs-name=", dirname, NULL);
920 for (s = fsname; *s != '\0'; s++) {
921 if (iscntrl((int)*s))
924 snprintf(levelstr, SIZEOF(levelstr), "-level=%d", level);
926 if (star_dle_tardumps) {
927 char *sdisk = sanitise_filename(argument->dle.disk);
928 tardumpfile = vstralloc(star_tardumps, sdisk, NULL);
931 tardumpfile = stralloc(star_tardumps);
934 g_ptr_array_add(argv_ptr, stralloc(star_path));
936 g_ptr_array_add(argv_ptr, stralloc("-c"));
937 g_ptr_array_add(argv_ptr, stralloc("-f"));
938 if (command == CMD_ESTIMATE) {
939 g_ptr_array_add(argv_ptr, stralloc("/dev/null"));
941 g_ptr_array_add(argv_ptr, stralloc("-"));
943 g_ptr_array_add(argv_ptr, stralloc("-C"));
944 #if defined(__CYGWIN__)
946 char tmppath[PATH_MAX];
948 cygwin_conv_to_full_posix_path(dirname, tmppath);
949 g_ptr_array_add(argv_ptr, stralloc(tmppath));
952 g_ptr_array_add(argv_ptr, stralloc(dirname));
954 g_ptr_array_add(argv_ptr, stralloc(fsname));
955 if (star_onefilesystem)
956 g_ptr_array_add(argv_ptr, stralloc("-xdev"));
957 g_ptr_array_add(argv_ptr, stralloc("-link-dirs"));
958 g_ptr_array_add(argv_ptr, stralloc(levelstr));
959 g_ptr_array_add(argv_ptr, stralloc2("tardumps=", tardumpfile));
960 if (command == CMD_BACKUP)
961 g_ptr_array_add(argv_ptr, stralloc("-wtardumps"));
962 g_ptr_array_add(argv_ptr, stralloc("-xattr"));
963 g_ptr_array_add(argv_ptr, stralloc("-acl"));
964 g_ptr_array_add(argv_ptr, stralloc("H=exustar"));
965 g_ptr_array_add(argv_ptr, stralloc("errctl=WARN|SAMEFILE|DIFF|GROW|SHRINK|SPECIALFILE|GETXATTR|BADACL *"));
967 g_ptr_array_add(argv_ptr, stralloc("-sparse"));
968 g_ptr_array_add(argv_ptr, stralloc("-dodesc"));
970 for (copt = argument->command_options; copt != NULL; copt = copt->next) {
971 g_ptr_array_add(argv_ptr, stralloc((char *)copt->data));
974 if (command == CMD_BACKUP && argument->dle.create_index)
975 g_ptr_array_add(argv_ptr, stralloc("-v"));
977 g_ptr_array_add(argv_ptr, stralloc("."));
979 g_ptr_array_add(argv_ptr, NULL);