From 3a283cfe9f8f1f127e8dc5597a5ea1d249985a54 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 12 Nov 2016 11:20:47 +0200 Subject: [PATCH] Fix the --add-file option. * src/common.h (name_more_files): New proto. (files_from_option): Remove. * src/names.c (name_more_files): New file. (names_options): Fix declaration of the add-file option. (names_parse_opt): Handle --add-file. * src/tar.c (struct tar_args): Remove the input_files member. Change all uses: use name_more_files() instead. * tests/Makefile.am: Add new test. * tests/add-file.at: New testcase. * tests/testsuite.at: Add new test. --- src/common.h | 4 +--- src/names.c | 24 ++++++++++++------- src/tar.c | 16 ++++--------- tests/Makefile.am | 3 ++- tests/add-file.at | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 6 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 tests/add-file.at diff --git a/src/common.h b/src/common.h index 50c34cc7c09b..6fdb6225f18b 100644 --- a/src/common.h +++ b/src/common.h @@ -414,9 +414,6 @@ GLOBAL bool show_transformed_names_option; timestamps from archives with an unusual member order. It is automatically set for incremental archives. */ GLOBAL bool delay_directory_restore_option; - -/* When set, tar will not refuse to create empty archives */ -GLOBAL bool files_from_option; /* Declarations for each module. */ @@ -738,6 +735,7 @@ void uid_to_uname (uid_t uid, char **uname); int uname_to_uid (char const *uname, uid_t *puid); void name_init (void); +bool name_more_files (void); void name_add_name (const char *name); void name_term (void); const char *name_next (int change_dirs); diff --git a/src/names.c b/src/names.c index 219aa77a4356..1a9465667cd3 100644 --- a/src/names.c +++ b/src/names.c @@ -32,7 +32,8 @@ static void name_add_file (const char *name); enum { - EXCLUDE_BACKUPS_OPTION = 256, + ADD_FILE_OPTION = 256, + EXCLUDE_BACKUPS_OPTION, EXCLUDE_CACHES_OPTION, EXCLUDE_CACHES_UNDER_OPTION, EXCLUDE_CACHES_ALL_OPTION, @@ -67,7 +68,7 @@ static struct argp_option names_options[] = { {NULL, 0, NULL, 0, N_("Local file name selection:"), GRID }, - {"add-file", ARGP_KEY_ARG, N_("FILE"), 0, + {"add-file", ADD_FILE_OPTION, N_("FILE"), 0, N_("add given FILE to the archive (useful if its name starts with a dash)"), GRID+1 }, {"directory", 'C', N_("DIR"), 0, N_("change to directory DIR"), GRID+1 }, @@ -190,10 +191,10 @@ names_parse_opt (int key, char *arg, struct argp_state *state) case 'T': name_add_file (arg); - /* Indicate we've been given -T option. This is for backward - compatibility only, so that `tar cfT archive /dev/null will - succeed */ - files_from_option = true; + break; + + case ADD_FILE_OPTION: + name_add_name (arg); break; default: @@ -651,8 +652,8 @@ struct name_elt /* A name_array element. */ } v; }; -static struct name_elt *name_head; /* store a list of names */ -size_t name_count; /* how many of the entries are names? */ +static struct name_elt *name_head;/* store a list of names */ +size_t name_count; /* how many of the entries are file names? */ static struct name_elt * name_elt_alloc (void) @@ -784,6 +785,12 @@ name_list_advance (void) } } +/* Return true if there are names or options in the list */ +bool +name_more_files (void) +{ + return name_count > 0; +} /* Add to name_array the file NAME with fnmatch options MATFLAGS */ void @@ -823,6 +830,7 @@ name_add_file (const char *name) ep->v.file.name = name; ep->v.file.line = 0; ep->v.file.fp = NULL; + name_count++; } /* Names from external name file. */ diff --git a/src/tar.c b/src/tar.c index 35bac38c2793..a361fc2c607f 100644 --- a/src/tar.c +++ b/src/tar.c @@ -813,7 +813,6 @@ struct tar_args /* Variables used during option parsing */ bool pax_option; /* True if --pax-option was given */ char const *backup_suffix_string; /* --suffix option argument */ char const *version_control_string; /* --backup option argument */ - bool input_files; /* True if some input files where given */ int compress_autodetect; /* True if compression autodetection should be attempted when creating archives */ }; @@ -1322,7 +1321,6 @@ parse_opt (int key, char *arg, struct argp_state *state) case ARGP_KEY_ARG: /* File name or non-parsed option, because of ARGP_IN_ORDER */ name_add_name (arg); - args->input_files = true; break; case 'A': @@ -2179,7 +2177,7 @@ more_options (int argc, char **argv, struct option_locus *loc) args.loc = loc; if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_EXIT, &idx, &args)) abort (); /* shouldn't happen */ - if (loc->source == OPTS_ENVIRON && args.input_files) + if (loc->source == OPTS_ENVIRON && name_more_files ()) USAGE_ERROR ((0, 0, _("non-option arguments in %s"), loc->name)); } @@ -2221,7 +2219,6 @@ decode_options (int argc, char **argv) args.pax_option = false; args.backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); args.version_control_string = 0; - args.input_files = false; args.compress_autodetect = false; subcommand_option = UNKNOWN_SUBCOMMAND; @@ -2340,10 +2337,7 @@ decode_options (int argc, char **argv) /* Handle operands after any "--" argument. */ for (; idx < argc; idx++) - { - name_add_name (argv[idx]); - args.input_files = true; - } + name_add_name (argv[idx]); /* Derive option values and check option consistency. */ @@ -2365,7 +2359,7 @@ decode_options (int argc, char **argv) if (occurrence_option) { - if (!args.input_files) + if (!name_more_files ()) USAGE_ERROR ((0, 0, _("--occurrence is meaningless without a file list"))); if (!IS_SUBCOMMAND_CLASS (SUBCL_OCCUR)) @@ -2569,7 +2563,7 @@ decode_options (int argc, char **argv) { /* --test-label is silent if the user has specified the label name to compare against. */ - if (!args.input_files) + if (!name_more_files ()) verbose_option++; } else if (utc_option) @@ -2598,7 +2592,7 @@ decode_options (int argc, char **argv) switch (subcommand_option) { case CREATE_SUBCOMMAND: - if (!args.input_files && !files_from_option) + if (!name_more_files ()) USAGE_ERROR ((0, 0, _("Cowardly refusing to create an empty archive"))); if (args.compress_autodetect && archive_names