Fix the --delay-directory-restore option
* src/extract.c (find_direct_ancestor): New function. (create_placeholder_file): Set after_links member on delayed_set_stat entries starting from the direct ancestor of the placeholder file. * tests/extrac21.at: New testcase. * tests/testsuite.at: Add extrac21 * tests/Makefile.am: Likewise. * NEWS: Update.
This commit is contained in:
7
NEWS
7
NEWS
@@ -1,4 +1,4 @@
|
||||
GNU tar NEWS - User visible changes. 2017-04-06
|
||||
GNU tar NEWS - User visible changes. 2017-11-16
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ issued the following error message
|
||||
* --numeric-owner now affects private headers too.
|
||||
This helps the output of 'tar' to be more deterministic.
|
||||
|
||||
* Fixed the --delay-directory-restore option
|
||||
|
||||
In some cases tar would restore the directory permissions too early,
|
||||
causing subsequent link extractions in that directory to fail.
|
||||
|
||||
|
||||
version 1.29 - Sergey Poznyakoff, 2016-05-16
|
||||
|
||||
|
||||
@@ -393,6 +393,24 @@ set_stat (char const *file_name,
|
||||
xattrs_selinux_set (st, file_name, typeflag);
|
||||
}
|
||||
|
||||
/* Find the direct ancestor of FILE_NAME in the delayed_set_stat list.
|
||||
*/
|
||||
static struct delayed_set_stat *
|
||||
find_direct_ancestor (char const *file_name)
|
||||
{
|
||||
struct delayed_set_stat *h = delayed_set_stat_head;
|
||||
while (h)
|
||||
{
|
||||
if (h && ! h->after_links
|
||||
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
|
||||
&& ISSLASH (file_name[h->file_name_len])
|
||||
&& (last_component (file_name) == file_name + h->file_name_len + 1))
|
||||
break;
|
||||
h = h->next;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/* For each entry H in the leading prefix of entries in HEAD that do
|
||||
not have after_links marked, mark H and fill in its dev and ino
|
||||
members. Assume HEAD && ! HEAD->after_links. */
|
||||
@@ -1304,11 +1322,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
|
||||
xheader_xattr_copy (¤t_stat_info, &p->xattr_map, &p->xattr_map_size);
|
||||
strcpy (p->target, current_stat_info.link_name);
|
||||
|
||||
h = delayed_set_stat_head;
|
||||
if (h && ! h->after_links
|
||||
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
|
||||
&& ISSLASH (file_name[h->file_name_len])
|
||||
&& (last_component (file_name) == file_name + h->file_name_len + 1))
|
||||
if ((h = find_direct_ancestor (file_name)) != NULL)
|
||||
mark_after_links (h);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -109,6 +109,7 @@ TESTSUITE_AT = \
|
||||
extrac18.at\
|
||||
extrac19.at\
|
||||
extrac20.at\
|
||||
extrac21.at\
|
||||
filerem01.at\
|
||||
filerem02.at\
|
||||
dirrem01.at\
|
||||
|
||||
59
tests/extrac21.at
Normal file
59
tests/extrac21.at
Normal file
@@ -0,0 +1,59 @@
|
||||
# Test suite for GNU tar. -*- Autotest -*-
|
||||
# Copyright 2017 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU tar.
|
||||
#
|
||||
# GNU tar 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GNU tar 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/>.
|
||||
|
||||
# When called with the --delay-directory-restore option, tar would
|
||||
# in some cases restore the directory permissions too early, before
|
||||
# attempting to replace softlink placeholders with the actual link.
|
||||
# This caused failure if the permissions forbade writing.
|
||||
#
|
||||
# The bug was caused by incorrect assumption about delayed_set_stat
|
||||
# ordering in create_placeholder_file.
|
||||
#
|
||||
# Reported by: Giuseppe Scrivano <gscrivano@gnu.org>
|
||||
# References: <878tfa17ti.fsf@redhat.com>,
|
||||
# <http://lists.gnu.org/archive/html/bug-tar/2017-11/msg00009.html>
|
||||
|
||||
AT_SETUP([delay-directory-restore])
|
||||
AT_KEYWORDS([extract extract21 read-only symlink delay-directory-restore])
|
||||
AT_TAR_CHECK([
|
||||
AT_UNPRIVILEGED_PREREQ
|
||||
|
||||
mkdir a a/b a/c
|
||||
genfile --file a/b/D
|
||||
genfile --file a/c/A
|
||||
cd a/b
|
||||
ln -sf ../c/A
|
||||
cd ../..
|
||||
chmod a-w a/b
|
||||
tar --no-recurs -c -f A.tar a a/b a/b/D a/c a/b/A a/c/A
|
||||
mkdir out
|
||||
tar -C out -v -x -f A.tar --delay-directory-restore
|
||||
],
|
||||
[0],
|
||||
[a/
|
||||
a/b/
|
||||
a/b/D
|
||||
a/c/
|
||||
a/b/A
|
||||
a/c/A
|
||||
],
|
||||
[],[],[],[ustar]) # Testing one format is enough
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
@@ -308,6 +308,8 @@ m4_include([extrac17.at])
|
||||
m4_include([extrac18.at])
|
||||
m4_include([extrac19.at])
|
||||
m4_include([extrac20.at])
|
||||
m4_include([extrac21.at])
|
||||
|
||||
m4_include([backup01.at])
|
||||
|
||||
AT_BANNER([Comparing])
|
||||
|
||||
Reference in New Issue
Block a user