X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=application-src%2Famgtar.c;h=7cf28a1ffce292a70c68b0bd3a31d4f1036eb130;hb=refs%2Ftags%2Fupstream%2F3.3.1;hp=c3e59666b1d473dfa5607a336b94f9d3a378916c;hpb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;p=debian%2Famanda diff --git a/application-src/amgtar.c b/application-src/amgtar.c index c3e5966..7cf28a1 100644 --- a/application-src/amgtar.c +++ b/application-src/amgtar.c @@ -39,11 +39,17 @@ * SPARSE (default YES) * ATIME-PRESERVE (default YES) * CHECK-DEVICE (default YES) + * NO-UNQUOTE (default NO) + * ACLS (default NO) + * SELINUX (default NO) + * XATTRS (default NO) * INCLUDE-FILE * INCLUDE-LIST + * INCLUDE-LIST-GLOB * INCLUDE-OPTIONAL * EXCLUDE-FILE * EXCLUDE-LIST + * EXCLUDE-LIST-GLOB * EXCLUDE-OPTIONAL * NORMAL * IGNORE @@ -51,20 +57,19 @@ * EXIT-HANDLING (1=GOOD 2=BAD) * TAR-BLOCKSIZE (default does not add --blocking-factor option, * using tar's default) + * VERBOSE */ #include "amanda.h" +#include "match.h" #include "pipespawn.h" #include "amfeatures.h" #include "clock.h" #include "util.h" #include "getfsent.h" -#include "version.h" #include "client_util.h" #include "conffile.h" -#include "amandad.h" #include "getopt.h" -#include "sendbackup.h" int debug_application = 1; #define application_debug(i, ...) do { \ @@ -110,9 +115,13 @@ typedef struct application_argument_s { int calcsize; char *tar_blocksize; GSList *level; + GSList *command_options; + char *include_list_glob; + char *exclude_list_glob; dle_t dle; int argc; char **argv; + int verbose; } application_argument_t; enum { CMD_ESTIMATE, CMD_BACKUP }; @@ -126,25 +135,21 @@ static void amgtar_validate(application_argument_t *argument); static void amgtar_build_exinclude(dle_t *dle, int verbose, int *nb_exclude, char **file_exclude, int *nb_include, char **file_include); -static char *amgtar_get_incrname(application_argument_t *argument, int level); -static char **amgtar_build_argv(application_argument_t *argument, - char *incrname, int command); -static amregex_t *build_re_table(amregex_t *orig_re_table, - GSList *normal_message, - GSList *ignore_message, - GSList *strange_message); -static void add_type_table(dmpline_t typ, - amregex_t **re_table, amregex_t *orig_re_table, - GSList *normal_message, GSList *ignore_message, - GSList *strange_message); -static void add_list_table(dmpline_t typ, amregex_t **re_table, - GSList *message); +static char *amgtar_get_incrname(application_argument_t *argument, int level, + FILE *mesgstream, int command); +static GPtrArray *amgtar_build_argv(application_argument_t *argument, + char *incrname, char **file_exclude, + char **file_include, int command); static char *gnutar_path; static char *gnutar_listdir; static char *gnutar_directory; static int gnutar_onefilesystem; static int gnutar_atimepreserve; +static int gnutar_acls; +static int gnutar_selinux; +static int gnutar_xattrs; static int gnutar_checkdevice; +static int gnutar_no_unquote; static int gnutar_sparse; static GSList *normal_message = NULL; static GSList *ignore_message = NULL; @@ -181,124 +186,100 @@ static struct option long_options[] = { {"exit-handling" , 1, NULL, 26}, {"calcsize" , 0, NULL, 27}, {"tar-blocksize" , 1, NULL, 28}, + {"no-unquote" , 1, NULL, 29}, + {"acls" , 1, NULL, 30}, + {"selinux" , 1, NULL, 31}, + {"xattrs" , 1, NULL, 32}, + {"command-options" , 1, NULL, 33}, + {"include-list-glob", 1, NULL, 34}, + {"exclude-list-glob", 1, NULL, 35}, + {"verbose" , 1, NULL, 36}, {NULL, 0, NULL, 0} }; - -void -add_type_table( - dmpline_t typ, - amregex_t **re_table, - amregex_t *orig_re_table, - GSList *normal_message, - GSList *ignore_message, - GSList *strange_message) +static char * +escape_tar_glob( + char *str, + int *in_argv) { - amregex_t *rp; - - for(rp = orig_re_table; rp->regex != NULL; rp++) { - if (rp->typ == typ) { - int found = 0; - GSList *mes; - - for (mes = normal_message; mes != NULL; mes = mes->next) { - if (strcmp(rp->regex, (char *)mes->data) == 0) - found = 1; - } - for (mes = ignore_message; mes != NULL; mes = mes->next) { - if (strcmp(rp->regex, (char *)mes->data) == 0) - found = 1; - } - for (mes = strange_message; mes != NULL; mes = mes->next) { - if (strcmp(rp->regex, (char *)mes->data) == 0) - found = 1; - } - if (found == 0) { - (*re_table)->regex = rp->regex; - (*re_table)->srcline = rp->srcline; - (*re_table)->scale = rp->scale; - (*re_table)->field = rp->field; - (*re_table)->typ = rp->typ; - (*re_table)++; + char *result = malloc(4*strlen(str)+1); + char *r = result; + char *s; + + *in_argv = 0; + for (s = str; *s != '\0'; s++) { + if (*s == '\\') { + char c = *(s+1); + if (c == '\\') { + *r++ = '\\'; + *r++ = '\\'; + *r++ = '\\'; + s++; + } else if (c == '?') { + *r++ = 127; + s++; + continue; + } else if (c == 'a') { + *r++ = 7; + s++; + continue; + } else if (c == 'b') { + *r++ = 8; + s++; + continue; + } else if (c == 'f') { + *r++ = 12; + s++; + continue; + } else if (c == 'n') { + *r++ = 10; + s++; + *in_argv = 1; + continue; + } else if (c == 'r') { + *r++ = 13; + s++; + *in_argv = 1; + continue; + } else if (c == 't') { + *r++ = 9; + s++; + continue; + } else if (c == 'v') { + *r++ = 11; + s++; + continue; + } else if (c >= '0' && c <= '9') { + char d = c-'0'; + s++; + c = *(s+1); + if (c >= '0' && c <= '9') { + d = (d*8)+(c-'0'); + s++; + c = *(s+1); + if (c >= '0' && c <= '9') { + d = (d*8)+(c-'0'); + s++; + } + } + *r++ = d; + continue; + } else { + *r++ = '\\'; } + } else if (*s == '?') { + *r++ = '\\'; + *r++ = '\\'; + } else if (*s == '*' || *s == '[') { + *r++ = '\\'; } + *r++ = *s; } -} + *r = '\0'; -void -add_list_table( - dmpline_t typ, - amregex_t **re_table, - GSList *message) -{ - GSList *mes; - - for (mes = message; mes != NULL; mes = mes->next) { - (*re_table)->regex = (char *)mes->data; - (*re_table)->srcline = 0; - (*re_table)->scale = 0; - (*re_table)->field = 0; - (*re_table)->typ = typ; - (*re_table)++; - } + return result; } -amregex_t * -build_re_table( - amregex_t *orig_re_table, - GSList *normal_message, - GSList *ignore_message, - GSList *strange_message) -{ - int nb = 0; - amregex_t *rp; - amregex_t *re_table, *new_re_table; - - for(rp = orig_re_table; rp->regex != NULL; rp++) { - nb++; - } - nb += g_slist_length(normal_message); - nb += g_slist_length(ignore_message); - nb += g_slist_length(strange_message); - nb ++; - - re_table = new_re_table = malloc(nb * sizeof(amregex_t)); - - /* add SIZE from orig_re_table */ - add_type_table(DMP_SIZE, &re_table, orig_re_table, - normal_message, ignore_message, strange_message); - - /* add ignore_message */ - add_list_table(DMP_IGNORE, &re_table, ignore_message); - - /* add IGNORE from orig_re_table */ - add_type_table(DMP_IGNORE, &re_table, orig_re_table, - normal_message, ignore_message, strange_message); - - /* add normal_message */ - add_list_table(DMP_NORMAL, &re_table, normal_message); - - /* add NORMAL from orig_re_table */ - add_type_table(DMP_NORMAL, &re_table, orig_re_table, - normal_message, ignore_message, strange_message); - - /* add strange_message */ - add_list_table(DMP_STRANGE, &re_table, strange_message); - - /* add STRANGE from orig_re_table */ - add_type_table(DMP_STRANGE, &re_table, orig_re_table, - normal_message, ignore_message, strange_message); - - /* Add DMP_STRANGE with NULL regex, */ - /* it is not copied by previous statement */ - re_table->regex = NULL; - re_table->srcline = 0; - re_table->scale = 0; - re_table->field = 0; - re_table->typ = DMP_STRANGE; - - return new_re_table; -} int main( @@ -315,11 +296,16 @@ main( #else gnutar_path = NULL; #endif + gnutar_listdir = NULL; gnutar_directory = NULL; gnutar_onefilesystem = 1; gnutar_atimepreserve = 1; + gnutar_acls = 0; + gnutar_selinux = 0; + gnutar_xattrs = 0; gnutar_checkdevice = 1; gnutar_sparse = 1; + gnutar_no_unquote = 0; exit_handling = NULL; /* initialize */ @@ -329,12 +315,20 @@ main( * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. - */ + */ setlocale(LC_MESSAGES, "C"); - textdomain("amanda"); + textdomain("amanda"); + + if (argc < 2) { + printf("ERROR no command given to amgtar\n"); + error(_("No command given to amgtar")); + } /* drop root privileges */ if (!set_root_privs(0)) { + if (strcmp(argv[1], "selfcheck") == 0) { + printf("ERROR amgtar must be run setuid root\n"); + } error(_("amgtar must be run setuid root")); } @@ -349,10 +343,11 @@ main( malloc_size_1 = malloc_inuse(&malloc_hist_1); #endif - erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); + add_amanda_log_handler(amanda_log_stderr); + add_amanda_log_handler(amanda_log_syslog); dbopen(DBG_SUBDIR_CLIENT); startclock(); - dbprintf(_("version %s\n"), version()); + dbprintf(_("version %s\n"), VERSION); config_init(CONFIG_INIT_CLIENT, NULL); @@ -363,6 +358,7 @@ main( /* parse argument */ command = argv[1]; + gnutar_listdir = stralloc(getconf_str(CNF_GNUTAR_LIST_DIR)); argument.config = NULL; argument.host = NULL; argument.message = 0; @@ -370,7 +366,12 @@ main( argument.calcsize = 0; argument.tar_blocksize = NULL; argument.level = NULL; + argument.command_options = NULL; + argument.include_list_glob = NULL; + argument.exclude_list_glob = NULL; + argument.verbose = 0; init_dle(&argument.dle); + argument.dle.record = 0; while (1) { int option_index = 0; @@ -402,17 +403,33 @@ main( break; case 11: gnutar_listdir = stralloc(optarg); break; - case 12: if (optarg && strcasecmp(optarg, "YES") != 0) + case 12: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_onefilesystem = 0; + else if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_onefilesystem = 1; + else if (strcasecmp(command, "selfcheck") == 0) + printf(_("ERROR [%s: bad ONE-FILE-SYSTEM property value (%s)]\n"), get_pname(), optarg); break; - case 13: if (optarg && strcasecmp(optarg, "YES") != 0) + case 13: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_sparse = 0; + else if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_sparse = 1; + else if (strcasecmp(command, "selfcheck") == 0) + printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg); break; - case 14: if (optarg && strcasecmp(optarg, "YES") != 0) + case 14: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_atimepreserve = 0; + else if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_atimepreserve = 1; + else if (strcasecmp(command, "selfcheck") == 0) + printf(_("ERROR [%s: bad ATIME-PRESERVE property value (%s)]\n"), get_pname(), optarg); break; - case 15: if (optarg && strcasecmp(optarg, "YES") != 0) + case 15: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_checkdevice = 0; + else if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_checkdevice = 1; + else if (strcasecmp(command, "selfcheck") == 0) + printf(_("ERROR [%s: bad CHECK-DEVICE property value (%s)]\n"), get_pname(), optarg); break; case 16: if (optarg) argument.dle.include_file = @@ -454,12 +471,47 @@ main( case 27: argument.calcsize = 1; break; case 28: argument.tar_blocksize = stralloc(optarg); + break; + case 29: if (optarg && strcasecmp(optarg, "NO") == 0) + gnutar_no_unquote = 0; + else if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_no_unquote = 1; + else if (strcasecmp(command, "selfcheck") == 0) + printf(_("ERROR [%s: bad No_UNQUOTE property value (%s)]\n"), get_pname(), optarg); + break; + case 30: if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_acls = 1; + break; + case 31: if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_selinux = 1; + break; + case 32: if (optarg && strcasecmp(optarg, "YES") == 0) + gnutar_xattrs = 1; + break; + case 33: argument.command_options = + g_slist_append(argument.command_options, + stralloc(optarg)); + break; + case 34: if (optarg) + argument.include_list_glob = stralloc(optarg); + break; + case 35: if (optarg) + argument.exclude_list_glob = stralloc(optarg); + break; + case 36: if (optarg && strcasecmp(optarg, "YES") == 0) + argument.verbose = 1; + break; case ':': case '?': break; } } + if (!argument.dle.disk && argument.dle.device) + argument.dle.disk = stralloc(argument.dle.device); + if (!argument.dle.device && argument.dle.disk) + argument.dle.device = stralloc(argument.dle.disk); + argument.argc = argc - optind; argument.argv = argv + optind; @@ -483,7 +535,7 @@ main( if (exit_handling) { char *s = exit_handling; while (s) { - char *r = index(s, '='); + char *r = strchr(s, '='); if (r) { int j = atoi(s); if (j >= 0 && j < 256) { @@ -491,13 +543,12 @@ main( if (strncasecmp(r, "GOOD", 4) == 0) { exit_value[j] = 0; } - s = index(s, ' '); } } + s = strchr(s+1, ' '); } } - gnutar_listdir = getconf_str(CNF_GNUTAR_LIST_DIR); if (strlen(gnutar_listdir) == 0) gnutar_listdir = NULL; @@ -516,7 +567,11 @@ main( } dbprintf("ONE-FILE-SYSTEM %s\n", gnutar_onefilesystem? "yes":"no"); dbprintf("SPARSE %s\n", gnutar_sparse? "yes":"no"); + dbprintf("NO-UNQUOTE %s\n", gnutar_no_unquote? "yes":"no"); dbprintf("ATIME-PRESERVE %s\n", gnutar_atimepreserve? "yes":"no"); + dbprintf("ACLS %s\n", gnutar_acls? "yes":"no"); + dbprintf("SELINUX %s\n", gnutar_selinux? "yes":"no"); + dbprintf("XATTRS %s\n", gnutar_xattrs? "yes":"no"); dbprintf("CHECK-DEVICE %s\n", gnutar_checkdevice? "yes":"no"); { amregex_t *rp; @@ -559,7 +614,7 @@ amgtar_support( fprintf(stdout, "CONFIG YES\n"); fprintf(stdout, "HOST YES\n"); fprintf(stdout, "DISK YES\n"); - fprintf(stdout, "MAX-LEVEL 9\n"); + fprintf(stdout, "MAX-LEVEL 399\n"); fprintf(stdout, "INDEX-LINE YES\n"); fprintf(stdout, "INDEX-XML NO\n"); fprintf(stdout, "MESSAGE-LINE YES\n"); @@ -567,23 +622,53 @@ amgtar_support( fprintf(stdout, "RECORD YES\n"); fprintf(stdout, "INCLUDE-FILE YES\n"); fprintf(stdout, "INCLUDE-LIST YES\n"); + fprintf(stdout, "INCLUDE-LIST-GLOB YES\n"); fprintf(stdout, "INCLUDE-OPTIONAL YES\n"); fprintf(stdout, "EXCLUDE-FILE YES\n"); fprintf(stdout, "EXCLUDE-LIST YES\n"); + fprintf(stdout, "EXCLUDE-LIST-GLOB YES\n"); fprintf(stdout, "EXCLUDE-OPTIONAL YES\n"); fprintf(stdout, "COLLECTION NO\n"); fprintf(stdout, "MULTI-ESTIMATE YES\n"); fprintf(stdout, "CALCSIZE YES\n"); + fprintf(stdout, "CLIENT-ESTIMATE YES\n"); } static void amgtar_selfcheck( application_argument_t *argument) { + if (argument->dle.disk) { + char *qdisk = quote_string(argument->dle.disk); + fprintf(stdout, "OK disk %s\n", qdisk); + amfree(qdisk); + } + + printf("OK amgtar version %s\n", VERSION); amgtar_build_exinclude(&argument->dle, 1, NULL, NULL, NULL, NULL); + printf("OK amgtar\n"); if (gnutar_path) { - check_file(gnutar_path, X_OK); + if (check_file(gnutar_path, X_OK)) { + char *gtar_version; + GPtrArray *argv_ptr = g_ptr_array_new(); + + g_ptr_array_add(argv_ptr, gnutar_path); + g_ptr_array_add(argv_ptr, "--version"); + g_ptr_array_add(argv_ptr, NULL); + + gtar_version = get_first_line(argv_ptr); + if (gtar_version) { + char *gv; + for (gv = gtar_version; *gv && !g_ascii_isdigit(*gv); gv++); + printf("OK amgtar gtar-version %s\n", gv); + } else { + printf(_("ERROR [Can't get %s version]\n"), gnutar_path); + } + + g_ptr_array_free(argv_ptr, TRUE); + amfree(gtar_version); + } } else { printf(_("ERROR [GNUTAR program not available]\n")); } @@ -597,12 +682,17 @@ amgtar_selfcheck( printf(_("ERROR [No GNUTAR-LISTDIR]\n")); } - fprintf(stdout, "OK %s\n", argument->dle.disk); if (gnutar_directory) { check_dir(gnutar_directory, R_OK); - } else { + } else if (argument->dle.device) { check_dir(argument->dle.device, R_OK); } + if (argument->calcsize) { + char *calcsize = vstralloc(amlibexecdir, "/", "calcsize", NULL); + check_file(calcsize, X_OK); + check_suid(calcsize); + amfree(calcsize); + } set_root_privs(0); } @@ -610,37 +700,50 @@ static void amgtar_estimate( application_argument_t *argument) { - char *incrname = NULL; - char **my_argv = NULL; - char *cmd = NULL; - int nullfd = -1; - int pipefd = -1; - FILE *dumpout = NULL; - off_t size = -1; - char line[32768]; - char *errmsg = NULL; - char *qerrmsg = NULL; - char *qdisk; - amwait_t wait_status; - int tarpid; + char *incrname = NULL; + GPtrArray *argv_ptr; + char *cmd = NULL; + int nullfd = -1; + int pipefd = -1; + FILE *dumpout = NULL; + off_t size = -1; + char line[32768]; + char *errmsg = NULL; + char *qerrmsg = NULL; + char *qdisk; + amwait_t wait_status; + int tarpid; amregex_t *rp; - times_t start_time; - int level; - GSList *levels; + times_t start_time; + int level; + GSList *levels; + char *file_exclude; + char *file_include; + + if (!argument->level) { + fprintf(stderr, "ERROR No level argument\n"); + error(_("No level argument")); + } + if (!argument->dle.disk) { + fprintf(stderr, "ERROR No disk argument\n"); + error(_("No disk argument")); + } + if (!argument->dle.device) { + fprintf(stderr, "ERROR No device argument\n"); + error(_("No device argument")); + } qdisk = quote_string(argument->dle.disk); if (argument->calcsize) { char *dirname; - char *file_exclude; - char *file_include; int nb_exclude; int nb_include; if (gnutar_directory) { dirname = gnutar_directory; } else { - dirname = amname_to_dirname(argument->dle.device); + dirname = argument->dle.device; } amgtar_build_exinclude(&argument->dle, 1, &nb_exclude, &file_exclude, @@ -648,6 +751,13 @@ amgtar_estimate( run_calcsize(argument->config, "GNUTAR", argument->dle.disk, dirname, argument->level, file_exclude, file_include); + + if (argument->verbose == 0) { + if (file_exclude) + unlink(file_exclude); + if (file_include) + unlink(file_include); + } return; } @@ -663,9 +773,10 @@ amgtar_estimate( for (levels = argument->level; levels != NULL; levels = levels->next) { level = GPOINTER_TO_INT(levels->data); - incrname = amgtar_get_incrname(argument, level); + incrname = amgtar_get_incrname(argument, level, stdout, CMD_ESTIMATE); cmd = stralloc(gnutar_path); - my_argv = amgtar_build_argv(argument, incrname, CMD_ESTIMATE); + argv_ptr = amgtar_build_argv(argument, incrname, &file_exclude, + &file_include, CMD_ESTIMATE); start_time = curclock(); @@ -676,7 +787,8 @@ amgtar_estimate( } tarpid = pipespawnv(cmd, STDERR_PIPE, 1, - &nullfd, &nullfd, &pipefd, my_argv); + &nullfd, &nullfd, &pipefd, + (char **)argv_ptr->pdata); dumpout = fdopen(pipefd,"r"); if (!dumpout) { @@ -716,13 +828,12 @@ amgtar_estimate( level, walltime_str(timessub(curclock(), start_time))); if(size == (off_t)-1) { - errmsg = vstrallocf(_("no size line match in %s output"), - my_argv[0]); + errmsg = vstrallocf(_("no size line match in %s output"), cmd); dbprintf(_("%s for %s\n"), errmsg, qdisk); dbprintf(".....\n"); } else if(size == (off_t)0 && argument->level == 0) { dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"), - my_argv[0], argument->dle.disk); + cmd, argument->dle.disk); dbprintf(".....\n"); } dbprintf(_("estimate size for %s level %d: %lld KB\n"), @@ -732,7 +843,7 @@ amgtar_estimate( kill(-tarpid, SIGTERM); - dbprintf(_("waiting for %s \"%s\" child\n"), my_argv[0], qdisk); + dbprintf(_("waiting for %s \"%s\" child\n"), cmd, qdisk); waitpid(tarpid, &wait_status, 0); if (WIFSIGNALED(wait_status)) { errmsg = vstrallocf(_("%s terminated with signal %d: see %s"), @@ -748,7 +859,7 @@ amgtar_estimate( errmsg = vstrallocf(_("%s got bad exit: see %s"), cmd, dbfn()); } - dbprintf(_("after %s %s wait\n"), my_argv[0], qdisk); + dbprintf(_("after %s %s wait\n"), cmd, qdisk); common_exit: if (errmsg) { @@ -759,7 +870,15 @@ common_exit: if (incrname) { unlink(incrname); } - amfree(my_argv); + + if (argument->verbose == 0) { + if (file_exclude) + unlink(file_exclude); + if (file_include) + unlink(file_include); + } + + g_ptr_array_free_full(argv_ptr); amfree(cmd); aclose(nullfd); @@ -784,28 +903,33 @@ static void amgtar_backup( application_argument_t *argument) { - int dumpin; - char *cmd = NULL; - char *qdisk; - char *incrname; - char line[32768]; + int dumpin; + char *cmd = NULL; + char *qdisk; + char *incrname; + char line[32768]; amregex_t *rp; - off_t dump_size = -1; - char *type; - char startchr; - - int dataf = 1; - int mesgf = 3; - int indexf = 4; - int outf; - FILE *mesgstream; - FILE *indexstream = NULL; - FILE *outstream; - char *errmsg = NULL; - amwait_t wait_status; + off_t dump_size = -1; + char *type; + char startchr; + int dataf = 1; + int mesgf = 3; + int indexf = 4; + int outf; + FILE *mesgstream; + FILE *indexstream = NULL; + FILE *outstream; + char *errmsg = NULL; + amwait_t wait_status; + GPtrArray *argv_ptr; + int tarpid; + char *file_exclude; + char *file_include; - char **my_argv; - int tarpid; + mesgstream = fdopen(mesgf, "w"); + if (!mesgstream) { + error(_("error mesgstream(%d): %s\n"), mesgf, strerror(errno)); + } if (!gnutar_path) { error(_("GNUTAR-PATH not defined")); @@ -814,15 +938,30 @@ amgtar_backup( error(_("GNUTAR-LISTDIR not defined")); } + if (!argument->level) { + fprintf(mesgstream, "? No level argument\n"); + error(_("No level argument")); + } + if (!argument->dle.disk) { + fprintf(mesgstream, "? No disk argument\n"); + error(_("No disk argument")); + } + if (!argument->dle.device) { + fprintf(mesgstream, "? No device argument\n"); + error(_("No device argument")); + } + qdisk = quote_string(argument->dle.disk); incrname = amgtar_get_incrname(argument, - GPOINTER_TO_INT(argument->level->data)); + GPOINTER_TO_INT(argument->level->data), + mesgstream, CMD_BACKUP); cmd = stralloc(gnutar_path); - my_argv = amgtar_build_argv(argument, incrname, CMD_BACKUP); + argv_ptr = amgtar_build_argv(argument, incrname, &file_exclude, + &file_include, CMD_BACKUP); tarpid = pipespawnv(cmd, STDIN_PIPE|STDERR_PIPE, 1, - &dumpin, &dataf, &outf, my_argv); + &dumpin, &dataf, &outf, (char **)argv_ptr->pdata); /* close the write ends of the pipes */ aclose(dumpin); @@ -833,10 +972,6 @@ amgtar_backup( error(_("error indexstream(%d): %s\n"), indexf, strerror(errno)); } } - mesgstream = fdopen(mesgf, "w"); - if (!mesgstream) { - error(_("error mesgstream(%d): %s\n"), mesgf, strerror(errno)); - } outstream = fdopen(outf, "r"); if (!outstream) { error(_("error outstream(%d): %s\n"), outf, strerror(errno)); @@ -856,7 +991,7 @@ amgtar_backup( } } if(rp->typ == DMP_SIZE) { - dump_size = (long)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0); + dump_size = (off_t)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0); } switch(rp->typ) { case DMP_NORMAL: @@ -902,24 +1037,33 @@ amgtar_backup( errmsg = vstrallocf(_("%s got bad exit: see %s"), cmd, dbfn()); } - dbprintf(_("after %s %s wait\n"), my_argv[0], qdisk); + dbprintf(_("after %s %s wait\n"), cmd, qdisk); dbprintf(_("amgtar: %s: pid %ld\n"), cmd, (long)tarpid); if (errmsg) { dbprintf("%s", errmsg); g_fprintf(mesgstream, "sendbackup: error [%s]\n", errmsg); } - if (incrname && strlen(incrname) > 4) { - char *nodotnew; - nodotnew = stralloc(incrname); - nodotnew[strlen(nodotnew)-4] = '\0'; - if (rename(incrname, nodotnew)) { - dbprintf(_("%s: warning [renaming %s to %s: %s]\n"), - get_pname(), incrname, nodotnew, strerror(errno)); - g_fprintf(mesgstream, _("? warning [renaming %s to %s: %s]\n"), - incrname, nodotnew, strerror(errno)); + if (!errmsg && incrname && strlen(incrname) > 4) { + if (argument->dle.record) { + char *nodotnew; + nodotnew = stralloc(incrname); + nodotnew[strlen(nodotnew)-4] = '\0'; + if (rename(incrname, nodotnew)) { + dbprintf(_("%s: warning [renaming %s to %s: %s]\n"), + get_pname(), incrname, nodotnew, strerror(errno)); + g_fprintf(mesgstream, _("? warning [renaming %s to %s: %s]\n"), + incrname, nodotnew, strerror(errno)); + } + amfree(nodotnew); + } else { + if (unlink(incrname) == -1) { + dbprintf(_("%s: warning [unlink %s: %s]\n"), + get_pname(), incrname, strerror(errno)); + g_fprintf(mesgstream, _("? warning [unlink %s: %s]\n"), + incrname, strerror(errno)); + } } - amfree(nodotnew); } dbprintf("sendbackup: size %lld\n", (long long)dump_size); @@ -932,71 +1076,229 @@ amgtar_backup( fclose(mesgstream); + if (argument->verbose == 0) { + if (file_exclude) + unlink(file_exclude); + if (file_include) + unlink(file_include); + } + amfree(incrname); amfree(qdisk); amfree(cmd); + g_ptr_array_free_full(argv_ptr); } static void amgtar_restore( application_argument_t *argument) { - char *cmd; - char **my_argv; - char **env; - int i, j; - char *e; + char *cmd; + GPtrArray *argv_ptr = g_ptr_array_new(); + char **env; + int j; + char *e; + char *include_filename = NULL; + char *exclude_filename = NULL; + int tarpid; if (!gnutar_path) { error(_("GNUTAR-PATH not defined")); } cmd = stralloc(gnutar_path); - my_argv = alloc(SIZEOF(char *) * (6 + argument->argc)); - i = 0; - my_argv[i++] = stralloc(gnutar_path); - my_argv[i++] = stralloc("--numeric-owner"); - my_argv[i++] = stralloc("-xpGvf"); - my_argv[i++] = stralloc("-"); - - for (j=1; j< argument->argc; j++) { - my_argv[i++] = stralloc(argument->argv[j]); + g_ptr_array_add(argv_ptr, stralloc(gnutar_path)); + g_ptr_array_add(argv_ptr, stralloc("--numeric-owner")); + if (gnutar_no_unquote) + g_ptr_array_add(argv_ptr, stralloc("--no-unquote")); + if (gnutar_acls) + g_ptr_array_add(argv_ptr, stralloc("--acls")); + if (gnutar_selinux) + g_ptr_array_add(argv_ptr, stralloc("--selinux")); + if (gnutar_xattrs) + g_ptr_array_add(argv_ptr, stralloc("--xattrs")); + /* ignore trailing zero blocks on input (this was the default until tar-1.21) */ + g_ptr_array_add(argv_ptr, stralloc("--ignore-zeros")); + g_ptr_array_add(argv_ptr, stralloc("-xpGvf")); + g_ptr_array_add(argv_ptr, stralloc("-")); + if (gnutar_directory) { + struct stat stat_buf; + if(stat(gnutar_directory, &stat_buf) != 0) { + fprintf(stderr,"can not stat directory %s: %s\n", gnutar_directory, strerror(errno)); + exit(1); + } + if (!S_ISDIR(stat_buf.st_mode)) { + fprintf(stderr,"%s is not a directory\n", gnutar_directory); + exit(1); + } + if (access(gnutar_directory, W_OK) != 0) { + fprintf(stderr, "Can't write to %s: %s\n", gnutar_directory, strerror(errno)); + exit(1); + } + g_ptr_array_add(argv_ptr, stralloc("--directory")); + g_ptr_array_add(argv_ptr, stralloc(gnutar_directory)); } - my_argv[i++] = NULL; - env = safe_env(); - become_root(); - execve(cmd, my_argv, env); - e = strerror(errno); - error(_("error [exec %s: %s]"), cmd, e); + g_ptr_array_add(argv_ptr, stralloc("--wildcards")); + if (argument->dle.exclude_list && + argument->dle.exclude_list->nb_element == 1) { + FILE *exclude; + char *sdisk; + int in_argv; + int entry_in_exclude = 0; + char line[2*PATH_MAX]; + FILE *exclude_list; + + if (argument->dle.disk) { + sdisk = sanitise_filename(argument->dle.disk); + } else { + sdisk = g_strdup_printf("no_dle-%d", getpid()); + } + exclude_filename= vstralloc(AMANDA_TMPDIR, "/", "exclude-", sdisk, NULL); + exclude_list = fopen(argument->dle.exclude_list->first->name, "r"); + + exclude = fopen(exclude_filename, "w"); + while (fgets(line, 2*PATH_MAX, exclude_list)) { + char *escaped; + line[strlen(line)-1] = '\0'; /* remove '\n' */ + escaped = escape_tar_glob(line, &in_argv); + if (in_argv) { + g_ptr_array_add(argv_ptr, "--exclude"); + g_ptr_array_add(argv_ptr, escaped); + } else { + fprintf(exclude,"%s\n", escaped); + entry_in_exclude++; + amfree(escaped); + } + } + fclose(exclude); + g_ptr_array_add(argv_ptr, stralloc("--exclude-from")); + g_ptr_array_add(argv_ptr, exclude_filename); + } + + if (argument->exclude_list_glob) { + g_ptr_array_add(argv_ptr, stralloc("--exclude-from")); + g_ptr_array_add(argv_ptr, stralloc(argument->exclude_list_glob)); + } + + { + GPtrArray *argv_include = g_ptr_array_new(); + FILE *include; + char *sdisk; + int in_argv; + guint i; + int entry_in_include = 0; + + if (argument->dle.disk) { + sdisk = sanitise_filename(argument->dle.disk); + } else { + sdisk = g_strdup_printf("no_dle-%d", getpid()); + } + include_filename = vstralloc(AMANDA_TMPDIR, "/", "include-", sdisk, NULL); + include = fopen(include_filename, "w"); + if (argument->dle.include_list && + argument->dle.include_list->nb_element == 1) { + char line[2*PATH_MAX]; + FILE *include_list = fopen(argument->dle.include_list->first->name, "r"); + while (fgets(line, 2*PATH_MAX, include_list)) { + char *escaped; + line[strlen(line)-1] = '\0'; /* remove '\n' */ + escaped = escape_tar_glob(line, &in_argv); + if (in_argv) { + g_ptr_array_add(argv_include, escaped); + } else { + fprintf(include,"%s\n", escaped); + entry_in_include++; + amfree(escaped); + } + } + } + + for (j=1; j< argument->argc; j++) { + char *escaped = escape_tar_glob(argument->argv[j], &in_argv); + if (in_argv) { + g_ptr_array_add(argv_include, escaped); + } else { + fprintf(include,"%s\n", escaped); + entry_in_include++; + amfree(escaped); + } + } + fclose(include); + + if (entry_in_include) { + g_ptr_array_add(argv_ptr, stralloc("--files-from")); + g_ptr_array_add(argv_ptr, include_filename); + } + + if (argument->include_list_glob) { + g_ptr_array_add(argv_ptr, stralloc("--files-from")); + g_ptr_array_add(argv_ptr, stralloc(argument->include_list_glob)); + } + + for (i = 0; i < argv_include->len; i++) { + g_ptr_array_add(argv_ptr, (char *)g_ptr_array_index(argv_include,i)); + } + } + g_ptr_array_add(argv_ptr, NULL); + + debug_executing(argv_ptr); + + tarpid = fork(); + switch (tarpid) { + case -1: error(_("%s: fork returned: %s"), get_pname(), strerror(errno)); + case 0: + env = safe_env(); + become_root(); + execve(cmd, (char **)argv_ptr->pdata, env); + e = strerror(errno); + error(_("error [exec %s: %s]"), cmd, e); + break; + default: break; + } + + waitpid(tarpid, NULL, 0); + if (argument->verbose == 0) { + if (exclude_filename) + unlink(exclude_filename); + if (include_filename) + unlink(include_filename); + } } static void amgtar_validate( application_argument_t *argument G_GNUC_UNUSED) { - char *cmd; - char **my_argv; - char **env; - int i; - char *e; + char *cmd; + GPtrArray *argv_ptr = g_ptr_array_new(); + char **env; + char *e; + char buf[32768]; if (!gnutar_path) { - error(_("GNUTAR-PATH not defined")); + dbprintf("GNUTAR-PATH not set; Piping to /dev/null\n"); + fprintf(stderr,"GNUTAR-PATH not set; Piping to /dev/null\n"); + goto pipe_to_null; } cmd = stralloc(gnutar_path); - my_argv = alloc(SIZEOF(char *) * 4); - i = 0; - my_argv[i++] = stralloc(gnutar_path); - my_argv[i++] = stralloc("-tf"); - my_argv[i++] = stralloc("-"); - my_argv[i++] = NULL; - + g_ptr_array_add(argv_ptr, stralloc(gnutar_path)); + /* ignore trailing zero blocks on input (this was the default until tar-1.21) */ + g_ptr_array_add(argv_ptr, stralloc("--ignore-zeros")); + g_ptr_array_add(argv_ptr, stralloc("-tf")); + g_ptr_array_add(argv_ptr, stralloc("-")); + g_ptr_array_add(argv_ptr, NULL); + + debug_executing(argv_ptr); env = safe_env(); - execve(cmd, my_argv, env); + execve(cmd, (char **)argv_ptr->pdata, env); e = strerror(errno); - error(_("error [exec %s: %s]"), cmd, e); + dbprintf("failed to execute %s: %s; Piping to /dev/null\n", cmd, e); + fprintf(stderr,"failed to execute %s: %s; Piping to /dev/null\n", cmd, e); +pipe_to_null: + while (read(0, buf, 32768) > 0) { + } } static void @@ -1039,7 +1341,9 @@ amgtar_build_exinclude( static char * amgtar_get_incrname( application_argument_t *argument, - int level) + int level, + FILE *mesgstream, + int command) { char *basename = NULL; char *incrname = NULL; @@ -1086,7 +1390,12 @@ amgtar_get_incrname( inputname, strerror(errno)); dbprintf("%s\n", errmsg); if (baselevel < 0) { - return NULL; + if (command == CMD_ESTIMATE) { + fprintf(mesgstream, "ERROR %s\n", errmsg); + } else { + fprintf(mesgstream, "? %s\n", errmsg); + } + exit(1); } amfree(errmsg); } @@ -1096,10 +1405,15 @@ amgtar_get_incrname( * Copy the previous listed incremental file to the new one. */ if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) { - errmsg = vstrallocf(_("opening %s: %s"), + errmsg = vstrallocf(_("error opening %s: %s"), incrname, strerror(errno)); dbprintf("%s\n", errmsg); - return NULL; + if (command == CMD_ESTIMATE) { + fprintf(mesgstream, "ERROR %s\n", errmsg); + } else { + fprintf(mesgstream, "? %s\n", errmsg); + } + exit(1); } while ((nb = read(infd, &buf, SIZEOF(buf))) > 0) { @@ -1137,78 +1451,87 @@ amgtar_get_incrname( return incrname; } -char **amgtar_build_argv( +GPtrArray *amgtar_build_argv( application_argument_t *argument, - char *incrname, - int command) + char *incrname, + char **file_exclude, + char **file_include, + int command) { - int i; int nb_exclude; int nb_include; - char *file_exclude; - char *file_include; char *dirname; char tmppath[PATH_MAX]; - char **my_argv; + GPtrArray *argv_ptr = g_ptr_array_new(); + GSList *copt; amgtar_build_exinclude(&argument->dle, 1, - &nb_exclude, &file_exclude, - &nb_include, &file_include); + &nb_exclude, file_exclude, + &nb_include, file_include); if (gnutar_directory) { dirname = gnutar_directory; } else { - dirname = amname_to_dirname(argument->dle.device); + dirname = argument->dle.device; } - my_argv = alloc(SIZEOF(char *) * 23); - i = 0; + g_ptr_array_add(argv_ptr, stralloc(gnutar_path)); - my_argv[i++] = gnutar_path; - - my_argv[i++] = "--create"; + g_ptr_array_add(argv_ptr, stralloc("--create")); if (command == CMD_BACKUP && argument->dle.create_index) - my_argv[i++] = "--verbose"; - my_argv[i++] = "--file"; + g_ptr_array_add(argv_ptr, stralloc("--verbose")); + g_ptr_array_add(argv_ptr, stralloc("--file")); if (command == CMD_ESTIMATE) { - my_argv[i++] = "/dev/null"; + g_ptr_array_add(argv_ptr, stralloc("/dev/null")); } else { - my_argv[i++] = "-"; + g_ptr_array_add(argv_ptr, stralloc("-")); } - my_argv[i++] = "--directory"; + if (gnutar_no_unquote) + g_ptr_array_add(argv_ptr, stralloc("--no-unquote")); + g_ptr_array_add(argv_ptr, stralloc("--directory")); canonicalize_pathname(dirname, tmppath); - my_argv[i++] = stralloc(tmppath); + g_ptr_array_add(argv_ptr, stralloc(tmppath)); if (gnutar_onefilesystem) - my_argv[i++] = "--one-file-system"; + g_ptr_array_add(argv_ptr, stralloc("--one-file-system")); if (gnutar_atimepreserve) - my_argv[i++] = "--atime-preserve=system"; + g_ptr_array_add(argv_ptr, stralloc("--atime-preserve=system")); if (!gnutar_checkdevice) - my_argv[i++] = "--no-check-device"; - my_argv[i++] = "--listed-incremental"; - my_argv[i++] = incrname; + g_ptr_array_add(argv_ptr, stralloc("--no-check-device")); + if (gnutar_acls) + g_ptr_array_add(argv_ptr, stralloc("--acls")); + if (gnutar_selinux) + g_ptr_array_add(argv_ptr, stralloc("--selinux")); + if (gnutar_xattrs) + g_ptr_array_add(argv_ptr, stralloc("--xattrs")); + g_ptr_array_add(argv_ptr, stralloc("--listed-incremental")); + g_ptr_array_add(argv_ptr, stralloc(incrname)); if (gnutar_sparse) - my_argv[i++] = "--sparse"; + g_ptr_array_add(argv_ptr, stralloc("--sparse")); if (argument->tar_blocksize) { - my_argv[i++] = "--blocking-factor"; - my_argv[i++] = argument->tar_blocksize; + g_ptr_array_add(argv_ptr, stralloc("--blocking-factor")); + g_ptr_array_add(argv_ptr, stralloc(argument->tar_blocksize)); + } + g_ptr_array_add(argv_ptr, stralloc("--ignore-failed-read")); + g_ptr_array_add(argv_ptr, stralloc("--totals")); + + for (copt = argument->command_options; copt != NULL; copt = copt->next) { + g_ptr_array_add(argv_ptr, stralloc((char *)copt->data)); } - my_argv[i++] = "--ignore-failed-read"; - my_argv[i++] = "--totals"; - if(file_exclude) { - my_argv[i++] = "--exclude-from"; - my_argv[i++] = file_exclude; + if (*file_exclude) { + g_ptr_array_add(argv_ptr, stralloc("--exclude-from")); + g_ptr_array_add(argv_ptr, stralloc(*file_exclude)); } - if(file_include) { - my_argv[i++] = "--files-from"; - my_argv[i++] = file_include; + if (*file_include) { + g_ptr_array_add(argv_ptr, stralloc("--files-from")); + g_ptr_array_add(argv_ptr, stralloc(*file_include)); } else { - my_argv[i++] = "."; + g_ptr_array_add(argv_ptr, stralloc(".")); } - my_argv[i++] = NULL; + g_ptr_array_add(argv_ptr, NULL); - return(my_argv); + return(argv_ptr); }