X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftar.c;h=170871593f2754655b247d279c062b602f8214a8;hb=0057cd6803a8fa322591a5cc7661d87ab77d9db6;hp=e3300fbf47a9d5e77b988f32d54d075cb12bdece;hpb=92773d860f94323c14cc8c1b27436f2e73a174fd;p=chaz%2Ftar diff --git a/src/tar.c b/src/tar.c index e3300fb..1708715 100644 --- a/src/tar.c +++ b/src/tar.c @@ -214,9 +214,10 @@ subcommand_string (enum subcommand c) case UPDATE_SUBCOMMAND: return "-u"; - default: - abort (); + case TEST_LABEL_SUBCOMMAND: + return "--test-label"; } + abort (); } void @@ -614,23 +615,18 @@ static struct argp_option options[] = { {"no-auto-compress", NO_AUTO_COMPRESS_OPTION, 0, 0, N_("do not use archive suffix to determine the compression program"), GRID+1 }, - {"bzip2", 'j', 0, 0, - N_("filter the archive through bzip2"), GRID+1 }, - {"gzip", 'z', 0, 0, - N_("filter the archive through gzip"), GRID+1 }, + {"use-compress-program", 'I', N_("PROG"), 0, + N_("filter through PROG (must accept -d)"), GRID+1 }, + /* Note: docstrings for the options below are generated by tar_help_filter */ + {"bzip2", 'j', 0, 0, NULL, GRID+1 }, + {"gzip", 'z', 0, 0, NULL, GRID+1 }, {"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, {"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, - {"compress", 'Z', 0, 0, - N_("filter the archive through compress"), GRID+1 }, + {"compress", 'Z', 0, 0, NULL, GRID+1 }, {"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, - {"lzma", LZMA_OPTION, 0, 0, - N_("filter the archive through lzma"), GRID+1 }, - {"lzop", LZOP_OPTION, 0, 0, - N_("filter the archive through lzop"), GRID+8 }, - {"xz", 'J', 0, 0, - N_("filter the archive through xz"), GRID+8 }, - {"use-compress-program", 'I', N_("PROG"), 0, - N_("filter through PROG (must accept -d)"), GRID+1 }, + {"lzma", LZMA_OPTION, 0, 0, NULL, GRID+1 }, + {"lzop", LZOP_OPTION, 0, 0, NULL, GRID+1 }, + {"xz", 'J', 0, 0, NULL, GRID+1 }, #undef GRID #define GRID 100 @@ -903,9 +899,7 @@ add_exclude_array (char const * const * fv) static char * format_default_settings (void) { - char *s; - - asprintf (&s, + return xasprintf ( "--format=%s -f%s -b%d --quoting-style=%s --rmt-command=%s" #ifdef REMOTE_SHELL " --rsh-command=%s" @@ -914,12 +908,11 @@ format_default_settings (void) archive_format_string (DEFAULT_ARCHIVE_FORMAT), DEFAULT_ARCHIVE, DEFAULT_BLOCKING, quoting_style_args[DEFAULT_QUOTING_STYLE], - DEFAULT_RMT_COMMAND, + DEFAULT_RMT_COMMAND #ifdef REMOTE_SHELL - REMOTE_SHELL + , REMOTE_SHELL #endif ); - return s; } @@ -929,7 +922,7 @@ set_subcommand_option (enum subcommand subcommand) if (subcommand_option != UNKNOWN_SUBCOMMAND && subcommand_option != subcommand) USAGE_ERROR ((0, 0, - _("You may not specify more than one `-Acdtrux' option"))); + _("You may not specify more than one `-Acdtrux' or `--test-label' option"))); subcommand_option = subcommand; } @@ -1002,12 +995,12 @@ set_stat_signal (const char *name) struct textual_date { struct textual_date *next; - struct timespec *ts; + struct timespec ts; const char *option; - const char *date; + char *date; }; -static void +static int get_date_or_file (struct tar_args *args, const char *option, const char *str, struct timespec *ts) { @@ -1030,17 +1023,19 @@ get_date_or_file (struct tar_args *args, const char *option, WARN ((0, 0, _("Substituting %s for unknown date format %s"), tartime (*ts, false), quote (str))); ts->tv_nsec = 0; + return 1; } else { struct textual_date *p = xmalloc (sizeof (*p)); - p->ts = ts; + p->ts = *ts; p->option = option; - p->date = str; + p->date = xstrdup (str); p->next = args->textual_date; args->textual_date = p; } } + return 0; } static void @@ -1050,10 +1045,14 @@ report_textual_dates (struct tar_args *args) for (p = args->textual_date; p; ) { struct textual_date *next = p->next; - char const *treated_as = tartime (*p->ts, true); - if (strcmp (p->date, treated_as) != 0) - WARN ((0, 0, _("Option %s: Treating date `%s' as %s"), - p->option, p->date, treated_as)); + if (verbose_option) + { + char const *treated_as = tartime (p->ts, true); + if (strcmp (p->date, treated_as) != 0) + WARN ((0, 0, _("Option %s: Treating date `%s' as %s"), + p->option, p->date, treated_as)); + } + free (p->date); free (p); p = next; } @@ -1254,24 +1253,103 @@ tar_help_filter (int key, const char *text, void *input) struct obstack stk; char *s; - if (key != ARGP_KEY_HELP_EXTRA) - return (char*) text; + switch (key) + { + default: + s = (char*) text; + break; + + case 'j': + s = xasprintf (_("filter the archive through %s"), BZIP2_PROGRAM); + break; + + case 'z': + s = xasprintf (_("filter the archive through %s"), GZIP_PROGRAM); + break; + + case 'Z': + s = xasprintf (_("filter the archive through %s"), COMPRESS_PROGRAM); + break; + case LZMA_OPTION: + s = xasprintf (_("filter the archive through %s"), LZMA_PROGRAM); + break; + + case 'J': + s = xasprintf (_("filter the archive through %s"), XZ_PROGRAM); + break; + + case ARGP_KEY_HELP_EXTRA: + obstack_init (&stk); + s = _("Valid arguments for the --quoting-style option are:"); + obstack_grow (&stk, s, strlen (s)); + obstack_grow (&stk, "\n\n", 2); + tar_list_quoting_styles (&stk, " "); + s = _("\n*This* tar defaults to:\n"); + obstack_grow (&stk, s, strlen (s)); + s = format_default_settings (); + obstack_grow (&stk, s, strlen (s)); + obstack_1grow (&stk, '\n'); + obstack_1grow (&stk, 0); + s = xstrdup (obstack_finish (&stk)); + obstack_free (&stk, NULL); + } + return s; +} + +static char * +expand_pax_option (struct tar_args *targs, const char *arg) +{ + struct obstack stk; + char *res; + obstack_init (&stk); - s = _("Valid arguments for the --quoting-style option are:"); - obstack_grow (&stk, s, strlen (s)); - obstack_grow (&stk, "\n\n", 2); - tar_list_quoting_styles (&stk, " "); - s = _("\n*This* tar defaults to:\n"); - obstack_grow (&stk, s, strlen (s)); - s = format_default_settings (); - obstack_grow (&stk, s, strlen (s)); - obstack_1grow (&stk, '\n'); + while (*arg) + { + size_t seglen = strcspn (arg, ","); + char *p = memchr (arg, '=', seglen); + if (p) + { + size_t len = p - arg + 1; + obstack_grow (&stk, arg, len); + len = seglen - len; + for (++p; *p && isspace ((unsigned char) *p); p++) + len--; + if (*p == '{' && p[len-1] == '}') + { + struct timespec ts; + char *tmp = xmalloc (len); + memcpy (tmp, p + 1, len-2); + tmp[len-2] = 0; + if (get_date_or_file (targs, "--pax-option", tmp, &ts) == 0) + { + char buf[UINTMAX_STRSIZE_BOUND], *s; + s = umaxtostr (ts.tv_sec, buf); + obstack_grow (&stk, s, strlen (s)); + } + else + obstack_grow (&stk, p, len); + free (tmp); + } + else + obstack_grow (&stk, p, len); + } + else + obstack_grow (&stk, arg, seglen); + + arg += seglen; + if (*arg) + { + obstack_1grow (&stk, *arg); + arg++; + } + } obstack_1grow (&stk, 0); - s = xstrdup (obstack_finish (&stk)); + res = xstrdup (obstack_finish (&stk)); obstack_free (&stk, NULL); - return s; + return res; } + static error_t parse_opt (int key, char *arg, struct argp_state *state) @@ -1381,11 +1459,11 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case 'j': - set_use_compress_program_option ("bzip2"); + set_use_compress_program_option (BZIP2_PROGRAM); break; case 'J': - set_use_compress_program_option ("xz"); + set_use_compress_program_option (XZ_PROGRAM); break; case 'k': @@ -1429,11 +1507,11 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case LZMA_OPTION: - set_use_compress_program_option ("lzma"); + set_use_compress_program_option (LZMA_PROGRAM); break; case LZOP_OPTION: - set_use_compress_program_option ("lzop"); + set_use_compress_program_option (LZOP_PROGRAM); break; case 'm': @@ -1535,8 +1613,7 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case TEST_LABEL_OPTION: - set_subcommand_option (LIST_SUBCOMMAND); - test_label_option = true; + set_subcommand_option (TEST_LABEL_SUBCOMMAND); break; case 'T': @@ -1591,11 +1668,11 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case 'z': - set_use_compress_program_option ("gzip"); + set_use_compress_program_option (GZIP_PROGRAM); break; case 'Z': - set_use_compress_program_option ("compress"); + set_use_compress_program_option (COMPRESS_PROGRAM); break; case ANCHORED_OPTION: @@ -1840,8 +1917,12 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case PAX_OPTION: - args->pax_option = true; - xheader_set_option (arg); + { + char *tmp = expand_pax_option (args, arg); + args->pax_option = true; + xheader_set_option (tmp); + free (tmp); + } break; case POSIX_OPTION: @@ -2356,7 +2437,7 @@ decode_options (int argc, char **argv) old_files_option = UNLINK_FIRST_OLD_FILES; - if (test_label_option) + if (subcommand_option == TEST_LABEL_SUBCOMMAND) { /* --test-label is silent if the user has specified the label name to compare against. */ @@ -2391,6 +2472,7 @@ decode_options (int argc, char **argv) case EXTRACT_SUBCOMMAND: case LIST_SUBCOMMAND: case DIFF_SUBCOMMAND: + case TEST_LABEL_SUBCOMMAND: for (archive_name_cursor = archive_name_array; archive_name_cursor < archive_name_array + archive_names; archive_name_cursor++) @@ -2440,8 +2522,7 @@ decode_options (int argc, char **argv) checkpoint_finish_compile (); - if (verbose_option) - report_textual_dates (&args); + report_textual_dates (&args); } @@ -2452,7 +2533,7 @@ int main (int argc, char **argv) { set_start_time (); - program_name = argv[0]; + set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -2476,7 +2557,7 @@ main (int argc, char **argv) obstack_init (&argv_stk); /* Ensure default behavior for some signals */ - signal (SIGPIPE, SIG_DFL); + signal (SIGPIPE, SIG_IGN); /* System V fork+wait does not work if SIGCHLD is ignored. */ signal (SIGCHLD, SIG_DFL); @@ -2498,7 +2579,7 @@ main (int argc, char **argv) { case UNKNOWN_SUBCOMMAND: USAGE_ERROR ((0, 0, - _("You must specify one of the `-Acdtrux' options"))); + _("You must specify one of the `-Acdtrux' or `--test-label' options"))); case CAT_SUBCOMMAND: case UPDATE_SUBCOMMAND: @@ -2532,6 +2613,9 @@ main (int argc, char **argv) diff_init (); read_and (diff_archive); break; + + case TEST_LABEL_SUBCOMMAND: + test_archive_label (); } if (totals_option)