From 7f6d7043332d3d4029ada9ac8e66e2ef9422046e 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 | 20 +++++++++++----- src/tar.c | 16 ++++--------- tests/Makefile.am | 3 ++- tests/add-file.at | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 2 ++ 6 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 tests/add-file.at diff --git a/src/common.h b/src/common.h index 50c34cc..6fdb622 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 d96ad71..57d97e2 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 }, @@ -177,10 +178,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: @@ -680,6 +681,12 @@ name_list_advance (void) free (elt); } +/* 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 @@ -719,6 +726,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 ba24c43..685fc8e 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)); } @@ -2220,7 +2218,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; @@ -2339,10 +2336,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. */ @@ -2364,7 +2358,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)) @@ -2568,7 +2562,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) @@ -2597,7 +2591,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 diff --git a/tests/Makefile.am b/tests/Makefile.am index 4f3b918..c8fa922 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,6 +42,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac ## ------------ ## TESTSUITE_AT = \ + testsuite.at\ T-cd.at\ T-dir00.at\ T-dir01.at\ @@ -54,7 +55,7 @@ TESTSUITE_AT = \ T-nonl.at\ T-mult.at\ T-nest.at\ - testsuite.at\ + add-file.at\ append.at\ append01.at\ append02.at\ diff --git a/tests/add-file.at b/tests/add-file.at new file mode 100644 index 0000000..97003ff --- /dev/null +++ b/tests/add-file.at @@ -0,0 +1,67 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- +# +# Test suite for GNU tar. +# Copyright 2016 Free Software Foundation, Inc. +# +# This file is part of GNU tar. +# +# GNU tar is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +AT_SETUP([The --add-file option]) +AT_KEYWORDS([add-file]) + +# Version 1.29 would give "tar: Cowardly refusing to create an empty archive" +# if only --add-file arguments were used, and would give "tar: unhandled +# positional option 0" when handling the --add-file if at least one file was +# also given normally. +# +# Reported by: James Clarke +# References: <20161112000246.77013-1-jrtc27@jrtc27.com>, +# http://lists.gnu.org/archive/html/bug-tar/2016-11/msg00013.html + +AT_TAR_CHECK([ +genfile --file -File +genfile --file foo +genfile --file bar + +echo 1: +tar -cvf arc.tar --add-file foo --add-file -File + +echo 2: +tar -cvf arc.tar foo --add-file -File bar + + +AT_DATA([input],[foo +--add-file=-File +bar +]) + +echo 3: +tar -cvf arc.tar -T input +], +[0], +[1: +foo +-File +2: +foo +-File +bar +3: +foo +-File +bar +]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 9493641..e97e5cb 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -213,6 +213,8 @@ m4_include([opcomp04.at]) m4_include([opcomp05.at]) m4_include([opcomp06.at]) +m4_include([add-file.at]) + AT_BANNER([The -T option]) m4_include([T-mult.at]) m4_include([T-nest.at]) -- 2.9.4