Blame SOURCES/tar-1.26-add-skip-old-files-option.patch

a4d85a
diff --git a/doc/tar.texi b/doc/tar.texi
a4d85a
index d70d113..a0e3d5f 100644
a4d85a
--- a/doc/tar.texi
a4d85a
+++ b/doc/tar.texi
a4d85a
@@ -1881,6 +1881,7 @@ The other operations of @command{tar} (@option{--list},
a4d85a
 @option{--extract}, @option{--compare}, and @option{--update})
a4d85a
 will act on the entire contents of the archive.
a4d85a
 
a4d85a
+@anchor{exit status}
a4d85a
 @cindex exit status
a4d85a
 @cindex return status
a4d85a
 Besides successful exits, @GNUTAR{} may fail for
a4d85a
@@ -2815,7 +2816,10 @@ when extracting files from an archive.
a4d85a
 @item --keep-old-files
a4d85a
 @itemx -k
a4d85a
 
a4d85a
-Do not overwrite existing files when extracting files from an archive.
a4d85a
+Do not overwrite existing files when extracting files from an
a4d85a
+archive.  Return error if such files exist.  See also
a4d85a
+@ref{--skip-old-files}.
a4d85a
+
a4d85a
 @xref{Keep Old Files}.
a4d85a
 
a4d85a
 @opsummary{label}
a4d85a
@@ -3268,6 +3272,20 @@ the archive creation operations it instructs @command{tar} to list the
a4d85a
 member names stored in the archive, as opposed to the actual file
a4d85a
 names.  @xref{listing member and file names}.
a4d85a
 
a4d85a
+@opsummary{skip-old-files}
a4d85a
+@item --skip-old-files
a4d85a
+
a4d85a
+Do not overwrite existing files when extracting files from an
a4d85a
+archive.  @xref{Keep Old Files}.
a4d85a
+
a4d85a
+This option differs from @option{--keep-old-files} in that it does not
a4d85a
+treat such files as an error, instead it just silently avoids
a4d85a
+overwriting them.
a4d85a
+
a4d85a
+The @option{--warning=existing-file} option can be used together with
a4d85a
+this option to produce warning messages about existing old files
a4d85a
+(@pxref{warnings}).
a4d85a
+
a4d85a
 @opsummary{sparse}
a4d85a
 @item --sparse
a4d85a
 @itemx -S
a4d85a
@@ -4443,11 +4461,11 @@ in the archive; the most recently archived members will be extracted
a4d85a
 last.  Additionally, an extracted member will @emph{replace} a file of
a4d85a
 the same name which existed in the directory already, and @command{tar}
a4d85a
 will not prompt you about this@footnote{Unless you give it
a4d85a
-@option{--keep-old-files} option, or the disk copy is newer than
a4d85a
-the one in the archive and you invoke @command{tar} with
a4d85a
-@option{--keep-newer-files} option.}.  Thus, only the most recently archived
a4d85a
-member will end up being extracted, as it will replace the one
a4d85a
-extracted before it, and so on.
a4d85a
+@option{--keep-old-files} (or @option{--skip-old-files}) option, or
a4d85a
+the disk copy is newer than the one in the archive and you invoke
a4d85a
+@command{tar} with @option{--keep-newer-files} option.}.  Thus, only
a4d85a
+the most recently archived member will end up being extracted, as it
a4d85a
+will replace the one extracted before it, and so on.
a4d85a
 
a4d85a
 @cindex extracting @var{n}th copy of the file
a4d85a
 @xopindex{occurrence, described}
a4d85a
@@ -5123,10 +5141,25 @@ such a directory, use the @option{--no-overwrite-dir} option.
a4d85a
 @cindex Overwriting old files, prevention
a4d85a
 @xopindex{keep-old-files, introduced}
a4d85a
 To be even more cautious and prevent existing files from being replaced, use
a4d85a
-the @option{--keep-old-files} (@option{-k}) option.  It causes @command{tar} to refuse
a4d85a
-to replace or update a file that already exists, i.e., a file with the
a4d85a
-same name as an archive member prevents extraction of that archive
a4d85a
-member.  Instead, it reports an error.
a4d85a
+the @option{--keep-old-files} (@option{-k}) option.  It causes
a4d85a
+@command{tar} to refuse to replace or update a file that already
a4d85a
+exists, i.e., a file with the same name as an archive member prevents
a4d85a
+extraction of that archive member.  Instead, it reports an error.  For
a4d85a
+example:
a4d85a
+
a4d85a
+@example
a4d85a
+$ @kbd{ls}
a4d85a
+blues
a4d85a
+$ @kbd{tar -x -k -f archive.tar}
a4d85a
+tar: blues: Cannot open: File exists
a4d85a
+tar: Exiting with failure status due to previous errors
a4d85a
+@end example
a4d85a
+
a4d85a
+@xopindex{skip-old-files, introduced}
a4d85a
+If you wish to preserve old files untouched, but don't want
a4d85a
+@command{tar} to treat them as errors, use the
a4d85a
+@option{--skip-old-files} option.  This option causes @command{tar} to
a4d85a
+silently skip extracting over existing files.
a4d85a
 
a4d85a
 @xopindex{overwrite, introduced}
a4d85a
 To be more aggressive about altering existing files, use the
a4d85a
@@ -5192,16 +5225,24 @@ archive, but remove other files before extracting.
a4d85a
 @node Keep Old Files
a4d85a
 @unnumberedsubsubsec Keep Old Files
a4d85a
 
a4d85a
+@GNUTAR{} provides two options to control its actions in a situation
a4d85a
+when it is about to extract a file which already exists on disk.
a4d85a
+
a4d85a
 @table @option
a4d85a
 @opindex keep-old-files
a4d85a
 @item --keep-old-files
a4d85a
 @itemx -k
a4d85a
-Do not replace existing files from archive.  The
a4d85a
-@option{--keep-old-files} (@option{-k}) option prevents @command{tar}
a4d85a
-from replacing existing files with files with the same name from the
a4d85a
-archive. The @option{--keep-old-files} option is meaningless with
a4d85a
-@option{--list} (@option{-t}).  Prevents @command{tar} from replacing
a4d85a
-files in the file system during extraction.
a4d85a
+Do not replace existing files from archive.  When such a file is
a4d85a
+encountered, @command{tar} issues an error message.  Upon end of
a4d85a
+extraction, @command{tar} exits with code 2 (@pxref{exit status}).
a4d85a
+
a4d85a
+@item --skip-old-files
a4d85a
+Do not replace existing files from archive, but do not treat that
a4d85a
+as error.  Such files are silently skipped and do not affect
a4d85a
+@command{tar} exit status.
a4d85a
+
a4d85a
+Additional verbosity can be obtained using @option{--warning=existing-file}
a4d85a
+together with that option (@pxref{warnings}).
a4d85a
 @end table
a4d85a
 
a4d85a
 @node Keep Newer Files
a4d85a
diff --git a/src/common.h b/src/common.h
a4d85a
index 0b9bd7a..2409413 100644
a4d85a
--- a/src/common.h
a4d85a
+++ b/src/common.h
a4d85a
@@ -182,6 +182,7 @@ enum old_files
a4d85a
   OVERWRITE_OLD_FILES,        /* --overwrite */
a4d85a
   UNLINK_FIRST_OLD_FILES,     /* --unlink-first */
a4d85a
   KEEP_OLD_FILES,             /* --keep-old-files */
a4d85a
+  SKIP_OLD_FILES,             /* --skip-old-files */
a4d85a
   KEEP_NEWER_FILES	      /* --keep-newer-files */
a4d85a
 };
a4d85a
 GLOBAL enum old_files old_files_option;
a4d85a
@@ -807,11 +808,12 @@ void checkpoint_run (bool do_write);
a4d85a
 #define WARN_UNKNOWN_KEYWORD     0x00020000
a4d85a
 #define WARN_XDEV                0x00040000
a4d85a
 #define WARN_DECOMPRESS_PROGRAM  0x00080000
a4d85a
+#define WARN_EXISTING_FILE       0x00100000
a4d85a
 
a4d85a
 /* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
a4d85a
    in verbose mode */
a4d85a
 #define WARN_VERBOSE_WARNINGS    (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
a4d85a
-				  WARN_DECOMPRESS_PROGRAM)
a4d85a
+				  WARN_DECOMPRESS_PROGRAM|WARN_EXISTING_FILE)
a4d85a
 #define WARN_ALL                 (~WARN_VERBOSE_WARNINGS)
a4d85a
 
a4d85a
 void set_warning_option (const char *arg);
a4d85a
diff --git a/src/extract.c b/src/extract.c
a4d85a
index aaea56e..662ea0b 100644
a4d85a
--- a/src/extract.c
a4d85a
+++ b/src/extract.c
a4d85a
@@ -639,9 +639,14 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
a4d85a
 
a4d85a
       switch (old_files_option)
a4d85a
 	{
a4d85a
-	case KEEP_OLD_FILES:
a4d85a
+	case SKIP_OLD_FILES:
a4d85a
+	  WARNOPT (WARN_EXISTING_FILE,
a4d85a
+		   (0, 0, _("%s: skipping existing file"), file_name));
a4d85a
 	  return RECOVER_SKIP;
a4d85a
 
a4d85a
+	case KEEP_OLD_FILES:
a4d85a
+	  return RECOVER_NO;
a4d85a
+
a4d85a
 	case KEEP_NEWER_FILES:
a4d85a
 	  if (file_newer_p (file_name, stp, &current_stat_info))
a4d85a
 	    break;
a4d85a
diff --git a/src/tar.c b/src/tar.c
a4d85a
index 7b62996..7a673e0 100644
a4d85a
--- a/src/tar.c
a4d85a
+++ b/src/tar.c
a4d85a
@@ -328,6 +328,7 @@ enum
a4d85a
   SHOW_DEFAULTS_OPTION,
a4d85a
   SHOW_OMITTED_DIRS_OPTION,
a4d85a
   SHOW_TRANSFORMED_NAMES_OPTION,
a4d85a
+  SKIP_OLD_FILES_OPTION,
a4d85a
   SPARSE_VERSION_OPTION,
a4d85a
   STRIP_COMPONENTS_OPTION,
a4d85a
   SUFFIX_OPTION,
a4d85a
@@ -452,7 +453,11 @@ static struct argp_option options[] = {
a4d85a
   {"remove-files", REMOVE_FILES_OPTION, 0, 0,
a4d85a
    N_("remove files after adding them to the archive"), GRID+1 },
a4d85a
   {"keep-old-files", 'k', 0, 0,
a4d85a
-   N_("don't replace existing files when extracting"), GRID+1 },
a4d85a
+   N_("don't replace existing files when extracting, "
a4d85a
+      "treat them as errors"), GRID+1 },
a4d85a
+  {"skip-old-files", SKIP_OLD_FILES_OPTION, 0, 0,
a4d85a
+   N_("don't replace existing files when extracting, silently skip over them"),
a4d85a
+   GRID+1 },
a4d85a
   {"keep-newer-files", KEEP_NEWER_FILES_OPTION, 0, 0,
a4d85a
    N_("don't replace existing files that are newer than their archive copies"), GRID+1 },
a4d85a
   {"overwrite", OVERWRITE_OPTION, 0, 0,
a4d85a
@@ -1618,6 +1623,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
a4d85a
       sparse_option = true;
a4d85a
       break;
a4d85a
 
a4d85a
+    case SKIP_OLD_FILES_OPTION:
a4d85a
+      old_files_option = SKIP_OLD_FILES;
a4d85a
+      break;
a4d85a
+
a4d85a
     case SPARSE_VERSION_OPTION:
a4d85a
       sparse_option = true;
a4d85a
       {
a4d85a
diff --git a/src/warning.c b/src/warning.c
a4d85a
index 5d1bcab..ee9d684 100644
a4d85a
--- a/src/warning.c
a4d85a
+++ b/src/warning.c
a4d85a
@@ -42,6 +42,7 @@ static char const *const warning_args[] = {
a4d85a
   "unknown-keyword",
a4d85a
   "xdev",
a4d85a
   "decompress-program",
a4d85a
+  "existing-file",
a4d85a
   NULL
a4d85a
 };
a4d85a
 
a4d85a
@@ -66,7 +67,8 @@ static int warning_types[] = {
a4d85a
   WARN_UNKNOWN_CAST,
a4d85a
   WARN_UNKNOWN_KEYWORD,
a4d85a
   WARN_XDEV,
a4d85a
-  WARN_DECOMPRESS_PROGRAM
a4d85a
+  WARN_DECOMPRESS_PROGRAM,
a4d85a
+  WARN_EXISTING_FILE,
a4d85a
 };
a4d85a
 
a4d85a
 ARGMATCH_VERIFY (warning_args, warning_types);
a4d85a
diff --git a/tests/Makefile.am b/tests/Makefile.am
a4d85a
index 119f1f3..3d78ea2 100644
a4d85a
--- a/tests/Makefile.am
a4d85a
+++ b/tests/Makefile.am
a4d85a
@@ -77,6 +77,8 @@ TESTSUITE_AT = \
a4d85a
  extrac07.at\
a4d85a
  extrac08.at\
a4d85a
  extrac09.at\
a4d85a
+ extrac18.at\
a4d85a
+ extrac19.at\
a4d85a
  extrac10.at\
a4d85a
  extrac11.at\
a4d85a
  extrac12.at\
a4d85a
diff --git a/tests/extrac18.at b/tests/extrac18.at
a4d85a
new file mode 100644
a4d85a
index 0000000..8b42ef7
a4d85a
--- /dev/null
a4d85a
+++ b/tests/extrac18.at
a4d85a
@@ -0,0 +1,60 @@
a4d85a
+# Process this file with autom4te to create testsuite. -*- Autotest -*-
a4d85a
+#
a4d85a
+# Test suite for GNU tar.
a4d85a
+# Copyright (C) 2011 Free Software Foundation, Inc.
a4d85a
+#
a4d85a
+# This program is free software; you can redistribute it and/or modify
a4d85a
+# it under the terms of the GNU General Public License as published by
a4d85a
+# the Free Software Foundation; either version 3, or (at your option)
a4d85a
+# any later version.
a4d85a
+#
a4d85a
+# This program is distributed in the hope that it will be useful,
a4d85a
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
a4d85a
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
a4d85a
+# GNU General Public License for more details.
a4d85a
+#
a4d85a
+# You should have received a copy of the GNU General Public License
a4d85a
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
a4d85a
+
a4d85a
+# Description: Check the functionality of the --keep-old-files option.
a4d85a
+# It should report an error and cause tar to exit with status 2.
a4d85a
+#
a4d85a
+# There was a regression in versions 1.23 to 1.26 inclusive, where
a4d85a
+# this option silently skipped such files.
a4d85a
+# Reported by: Doug McLaren <dougmc@frenzied.us>,
a4d85a
+#              Gary Partis <gary@partis.co.uk>,
a4d85a
+#              Jim Meyering <jim@meyering.net>
a4d85a
+#              
a4d85a
+# References: <20111117045433.GA8245@algol.frenzied.us>,
a4d85a
+#             <4F3D824717847C4487F77228F83329A3514CBB@server.Partis.local>,
a4d85a
+#             <87wrar6zzz.fsf@rho.meyering.net>
a4d85a
+
a4d85a
+AT_SETUP([keep-old-files])
a4d85a
+AT_KEYWORDS([extract extrac18 old-files keep-old-files])
a4d85a
+
a4d85a
+AT_TAR_CHECK([
a4d85a
+mkdir dir
a4d85a
+cd dir
a4d85a
+echo 'Old file a' > a
a4d85a
+echo 'Old file b' > b
a4d85a
+
a4d85a
+tar cf ../archive .
a4d85a
+
a4d85a
+rm b
a4d85a
+echo 'File a' > a
a4d85a
+
a4d85a
+tar -x -k -f ../archive
a4d85a
+echo status=$?
a4d85a
+
a4d85a
+cat a
a4d85a
+],
a4d85a
+[0],
a4d85a
+[status=2
a4d85a
+File a
a4d85a
+],
a4d85a
+[tar: ./a: Cannot open: File exists
a4d85a
+tar: Exiting with failure status due to previous errors
a4d85a
+])
a4d85a
+
a4d85a
+AT_CLEANUP
a4d85a
+
a4d85a
diff --git a/tests/extrac19.at b/tests/extrac19.at
a4d85a
new file mode 100644
a4d85a
index 0000000..43c4c50
a4d85a
--- /dev/null
a4d85a
+++ b/tests/extrac19.at
a4d85a
@@ -0,0 +1,44 @@
a4d85a
+# Process this file with autom4te to create testsuite. -*- Autotest -*-
a4d85a
+#
a4d85a
+# Test suite for GNU tar.
a4d85a
+# Copyright (C) 2011 Free Software Foundation, Inc.
a4d85a
+#
a4d85a
+# This program is free software; you can redistribute it and/or modify
a4d85a
+# it under the terms of the GNU General Public License as published by
a4d85a
+# the Free Software Foundation; either version 3, or (at your option)
a4d85a
+# any later version.
a4d85a
+#
a4d85a
+# This program is distributed in the hope that it will be useful,
a4d85a
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
a4d85a
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
a4d85a
+# GNU General Public License for more details.
a4d85a
+#
a4d85a
+# You should have received a copy of the GNU General Public License
a4d85a
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
a4d85a
+
a4d85a
+AT_SETUP([skip-old-files])
a4d85a
+AT_KEYWORDS([extract extrac19 old-files skip-old-files])
a4d85a
+
a4d85a
+AT_TAR_CHECK([
a4d85a
+mkdir dir
a4d85a
+cd dir
a4d85a
+echo 'Old file a' > a
a4d85a
+echo 'Old file b' > b
a4d85a
+
a4d85a
+tar cf ../archive .
a4d85a
+
a4d85a
+rm b
a4d85a
+echo 'File a' > a
a4d85a
+
a4d85a
+tar -x --skip-old-files -f ../archive
a4d85a
+echo status=$?
a4d85a
+
a4d85a
+cat a
a4d85a
+],
a4d85a
+[0],
a4d85a
+[status=0
a4d85a
+File a
a4d85a
+])
a4d85a
+
a4d85a
+AT_CLEANUP
a4d85a
+
a4d85a
diff --git a/tests/testsuite.at b/tests/testsuite.at
a4d85a
index d1dab36..e43653e 100644
a4d85a
--- a/tests/testsuite.at
a4d85a
+++ b/tests/testsuite.at
a4d85a
@@ -166,6 +166,9 @@ m4_include([extrac15.at])
a4d85a
 m4_include([extrac16.at])
a4d85a
 m4_include([extrac17.at])
a4d85a
 
a4d85a
+m4_include([extrac18.at])
a4d85a
+m4_include([extrac19.at])
a4d85a
+
a4d85a
 m4_include([label01.at])
a4d85a
 m4_include([label02.at])
a4d85a
 m4_include([label03.at])