瀏覽代碼

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.
Sergey Poznyakoff 8 年之前
父節點
當前提交
3a283cfe9f
共有 6 個文件被更改,包括 92 次插入23 次删除
  1. 1 3
      src/common.h
  2. 16 8
      src/names.c
  3. 5 11
      src/tar.c
  4. 2 1
      tests/Makefile.am
  5. 67 0
      tests/add-file.at
  6. 1 0
      tests/testsuite.at

+ 1 - 3
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);

+ 16 - 8
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.  */

+ 5 - 11
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

+ 2 - 1
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\

+ 67 - 0
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 <http://www.gnu.org/licenses/>.
+
+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 <[email protected]>
+# References: <[email protected]>,
+#             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

+ 1 - 0
tests/testsuite.at

@@ -218,6 +218,7 @@ AT_BANNER([Positional options])
 m4_include([positional01.at])
 m4_include([positional02.at])
 m4_include([positional03.at])
+m4_include([add-file.at])
 
 AT_BANNER([The -T option])
 m4_include([T-mult.at])