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.
This commit is contained in:
19
NEWS
19
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 <bug-tar@gnu.org>
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -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])
|
||||
|
||||
88
doc/tar.texi
88
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
13
src/tar.c
13
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;
|
||||
{
|
||||
|
||||
@@ -86,6 +86,8 @@ TESTSUITE_AT = \
|
||||
extrac15.at\
|
||||
extrac16.at\
|
||||
extrac17.at\
|
||||
extrac18.at\
|
||||
extrac19.at\
|
||||
filerem01.at\
|
||||
filerem02.at\
|
||||
gzip.at\
|
||||
|
||||
60
tests/extrac18.at
Normal file
60
tests/extrac18.at
Normal file
@@ -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
|
||||
|
||||
44
tests/extrac19.at
Normal file
44
tests/extrac19.at
Normal file
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user