From: Sergey Poznyakoff Date: Sat, 26 Nov 2011 13:41:43 +0000 (+0200) Subject: Fix --keep-old-files option. X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=7a5a3708cb8b33494cd6ac64bfe163f631a33edf;p=chaz%2Ftar Fix --keep-old-files option. The regression was introduced by 8f390db9. This patch implements additional option --skip-old-files, which silently skips members which would cause writing over existing files, and restores --keep-old-files to its traditional behavior. * NEWS: Update. * configure.ac: Update. * doc/tar.texi: Document the changes. * src/common.h (SKIP_OLD_FILES): New old_files mode. * src/extract.c (maybe_recoverable): Restore KEEP_OLD_FILES behavior. Handle SKIP_OLD_FILES. * src/tar.c: New option --skip-old-files. * tests/extrac18.at: New file. * tests/extrac19.at: New file. * tests/Makefile.am: Add new test cases. * tests/testsuite.at: Likewise. --- diff --git a/NEWS b/NEWS index 06955f4..6226d07 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,8 @@ -GNU tar NEWS - User visible changes. 2011-08-13 +GNU tar NEWS - User visible changes. 2011-11-26 Please send GNU tar bug reports to -version ?.? - ?, 201?-??-?? +version 1.26.90 (Git) * New features @@ -13,6 +13,21 @@ NAME:NUM, so that you can specify both symbolic name and numeric ID for owner and group. In these options, NAME no longer needs to be present in the current host's user and group databases. +* The --keep-old-files and --skip-old-files options. + +This release restores the traditional functionality of the +--keep-old-files. This option causes tar to avoid replacing +existing files while extracting and to treat such files as errors. +Tar will emit a prominent error message upon encountering such files +and will exit with code 2 when finished extracting the archive. + +A new option --skip-old-files is introduced, which acts exactly as +--keep-old-files, except that it does not treat existing files as +errors. Instead it just silently skips them. An additional level of +verbosity can be obtained by using the option --warning=existing-file +together with this option. + + version 1.26 - Sergey Poznyakoff, 2011-03-12 * Bugfixes diff --git a/configure.ac b/configure.ac index db69cb8..b4dc871 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. -AC_INIT([GNU tar], [1.26], [bug-tar@gnu.org]) +AC_INIT([GNU tar], [1.26.90], [bug-tar@gnu.org]) AC_CONFIG_SRCDIR([src/tar.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/doc/tar.texi b/doc/tar.texi index cf30592..1a28cb2 100644 --- a/doc/tar.texi +++ b/doc/tar.texi @@ -1877,6 +1877,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 @@ -2808,7 +2809,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} @@ -3261,6 +3265,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 @@ -4436,11 +4454,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} @@ -5131,10 +5149,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 @@ -5200,16 +5233,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 @@ -11937,11 +11978,16 @@ lets the archive overwrite any file in your system that you can write, the @option{--absolute-names} (@option{-P}) option should be used only for trusted archives. -Conversely, with the @option{--keep-old-files} (@option{-k}) option, -@command{tar} refuses to replace existing files when extracting; and -with the @option{--no-overwrite-dir} option, @command{tar} refuses to -replace the permissions or ownership of already-existing directories. -These options may help when extracting from untrusted archives. +Conversely, with the @option{--keep-old-files} (@option{-k}) and +@option{--skip-old-files} options, @command{tar} refuses to replace +existing files when extracting. The difference between the two +options is that the former treats existing files as errors whereas the +latter just silently ignores them. + +Finally, with the @option{--no-overwrite-dir} option, @command{tar} +refuses to replace the permissions or ownership of already-existing +directories. These options may help when extracting from untrusted +archives. @node Live untrusted data @subsection Dealing with Live Untrusted Data diff --git a/src/common.h b/src/common.h index b60c4a0..1429b22 100644 --- a/src/common.h +++ b/src/common.h @@ -183,6 +183,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; diff --git a/src/extract.c b/src/extract.c index 60ec747..6c38492 100644 --- a/src/extract.c +++ b/src/extract.c @@ -642,11 +642,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 f0d8f5b..21d9910 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, @@ -1544,7 +1549,7 @@ parse_opt (int key, char *arg, struct argp_state *state) /* Don't replace existing files. */ old_files_option = KEEP_OLD_FILES; break; - + case 'K': starting_file_option = true; addname (arg, 0, true, NULL); @@ -1674,6 +1679,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/tests/Makefile.am b/tests/Makefile.am index 7acc9d6..4601e0e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -86,6 +86,8 @@ TESTSUITE_AT = \ extrac15.at\ extrac16.at\ extrac17.at\ + extrac18.at\ + extrac19.at\ filerem01.at\ filerem02.at\ gzip.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 . + +# 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 , +# Gary Partis , +# Jim Meyering +# +# 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 . + +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 35f8c2f..97f5e41 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -166,6 +166,8 @@ m4_include([extrac14.at]) 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])