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