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:
Sergey Poznyakoff
2010-03-17 11:52:40 +02:00
parent 67b4f3519d
commit c1d3d13493
6 changed files with 151 additions and 8 deletions

13
NEWS
View File

@@ -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:

View File

@@ -6,7 +6,6 @@ argmatch
argp
argp-version-etc
backupfile
canonicalize
closeout
configmake
dirname

View File

@@ -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;
}

View File

@@ -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
View 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

View File

@@ -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])