Fix --remove-files.
Tar --remove-files relied on canonicalize_file_name, which replaces symlinks in file name components with the directories they point to. Due to this, tar effectively ignored existence of symbolic links and was unable to remove a directory that contained any (Alexander Kozlov <akozlov@nada.kth.se>, 2010-03-15). * gnulib.modules: Remove canonicalize. * src/misc.c (normalize_filename): Rewrite from scratch. The function operates only on its input string, it makes no attempt to test components for existence or to resolve symbolic links. * tests/Makefile.am (TESTSUITE_AT): Add remfiles03.at. * tests/testsuite.at: Likewise. * tests/remfiles03.at: New test case. * NEWS: Update.
This commit is contained in:
13
NEWS
13
NEWS
@@ -1,9 +1,16 @@
|
||||
GNU tar NEWS - User visible changes. 2010-03-11
|
||||
GNU tar NEWS - User visible changes. 2010-03-17
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
|
||||
* --test-label behavior
|
||||
* Bugfixes.
|
||||
|
||||
** --remove-files
|
||||
|
||||
Tar --remove-files failed to remove a directory which contained
|
||||
symlinks to another files within that directory.
|
||||
|
||||
** --test-label behavior
|
||||
|
||||
In case of a mismatch, `tar --test-label LABEL' exits with code 1,
|
||||
not 2 as it did in previous versions.
|
||||
@@ -18,7 +25,7 @@ Several volume labels may be specified in a command line, e.g.:
|
||||
In this case, tar exits with code 0 if any one of the arguments
|
||||
matches the actual volume label.
|
||||
|
||||
* --label used with --update
|
||||
** --label used with --update
|
||||
|
||||
The `--label' option can be used with `--update' to prevent accidental
|
||||
update of an archive:
|
||||
|
||||
@@ -6,7 +6,6 @@ argmatch
|
||||
argp
|
||||
argp-version-etc
|
||||
backupfile
|
||||
canonicalize
|
||||
closeout
|
||||
configmake
|
||||
dirname
|
||||
|
||||
98
src/misc.c
98
src/misc.c
@@ -25,7 +25,6 @@
|
||||
#include <xgetcwd.h>
|
||||
#include <unlinkdir.h>
|
||||
#include <utimens.h>
|
||||
#include <canonicalize.h>
|
||||
|
||||
#if HAVE_STROPTS_H
|
||||
# include <stropts.h>
|
||||
@@ -34,6 +33,10 @@
|
||||
# include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Handling strings. */
|
||||
|
||||
@@ -230,10 +233,99 @@ zap_slashes (char *name)
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Normalize NAME by resolving any relative references and
|
||||
removing trailing slashes. Destructive version: modifies its argument. */
|
||||
int
|
||||
normalize_filename_x (char *name)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = name;
|
||||
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && ISSLASH (*p))
|
||||
p++;
|
||||
|
||||
/* Remove /./, resolve /../ and compress sequences of slashes */
|
||||
for (q = p; *q; )
|
||||
{
|
||||
if (ISSLASH (*q))
|
||||
{
|
||||
*p++ = *q++;
|
||||
while (ISSLASH (*q))
|
||||
q++;
|
||||
continue;
|
||||
}
|
||||
else if (p == name)
|
||||
{
|
||||
if (*q == '.')
|
||||
{
|
||||
if (ISSLASH (q[1]))
|
||||
{
|
||||
q += 2;
|
||||
continue;
|
||||
}
|
||||
if (q[1] == '.' && ISSLASH (q[2]))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*q == '.' && ISSLASH (p[-1]))
|
||||
{
|
||||
if (ISSLASH (q[1]))
|
||||
{
|
||||
q += 2;
|
||||
while (ISSLASH (*q))
|
||||
q++;
|
||||
continue;
|
||||
}
|
||||
else if (q[1] == '.' && ISSLASH (q[2]))
|
||||
{
|
||||
do
|
||||
{
|
||||
--p;
|
||||
}
|
||||
while (p > name && !ISSLASH (p[-1]));
|
||||
q += 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p++ = *q++;
|
||||
}
|
||||
|
||||
/* Remove trailing slashes */
|
||||
while (p - 1 > name && ISSLASH (p[-1]))
|
||||
p--;
|
||||
|
||||
*p = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Normalize NAME by resolving any relative references, removing trailing
|
||||
slashes, and converting it to absolute file name. Return the normalized
|
||||
name, or NULL in case of error. */
|
||||
|
||||
char *
|
||||
normalize_filename (const char *name)
|
||||
{
|
||||
return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
|
||||
char *copy;
|
||||
|
||||
if (name[0] != '/')
|
||||
{
|
||||
copy = xgetcwd ();
|
||||
copy = xrealloc (copy, strlen (copy) + strlen (name) + 2);
|
||||
|
||||
strcat (copy, "/");
|
||||
strcat (copy, name);
|
||||
}
|
||||
else
|
||||
copy = xstrdup (name);
|
||||
if (normalize_filename_x (copy))
|
||||
{
|
||||
free (copy);
|
||||
return NULL;
|
||||
}
|
||||
return xrealloc (copy, strlen (copy) + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -870,5 +962,3 @@ namebuf_name (namebuf_t buf, const char *name)
|
||||
return buf->buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ TESTSUITE_AT = \
|
||||
rename05.at\
|
||||
remfiles01.at\
|
||||
remfiles02.at\
|
||||
remfiles03.at\
|
||||
same-order01.at\
|
||||
same-order02.at\
|
||||
shortfile.at\
|
||||
|
||||
45
tests/remfiles03.at
Normal file
45
tests/remfiles03.at
Normal file
@@ -0,0 +1,45 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2009 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Description: Called with --remove-files, tar 1.23 failed
|
||||
# to remove a directory if it contained symlinks to another files
|
||||
# within that directory.
|
||||
# Reported-by: Alexander Kozlov <akozlov@nada.kth.se>
|
||||
# References: http://lists.gnu.org/archive/html/bug-tar/2010-03/msg00028.html
|
||||
# <Pine.SOC.4.64.1003150951060.28948@faun.nada.kth.se>
|
||||
|
||||
AT_SETUP([remove-files with symbolic links])
|
||||
AT_KEYWORDS([create remove-files remfiles03])
|
||||
|
||||
AT_CHECK([
|
||||
mkdir a
|
||||
mkdir a/b
|
||||
ln -s b a/c || AT_SKIP_TEST
|
||||
tar --remove-files -cf a.tar a
|
||||
genfile --stat a
|
||||
],
|
||||
[0],
|
||||
[],
|
||||
[genfile: stat(a) failed: No such file or directory
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
@@ -229,6 +229,7 @@ m4_include([grow.at])
|
||||
|
||||
m4_include([remfiles01.at])
|
||||
m4_include([remfiles02.at])
|
||||
m4_include([remfiles03.at])
|
||||
|
||||
m4_include([star/gtarfail.at])
|
||||
m4_include([star/gtarfail2.at])
|
||||
|
||||
Reference in New Issue
Block a user