Преглед на файлове

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.
Sergey Poznyakoff преди 7 години
родител
ревизия
3ae075a51a
променени са 5 файла, в които са добавени 87 реда и са изтрити 6 реда
  1. 6 1
      NEWS
  2. 19 5
      src/extract.c
  3. 1 0
      tests/Makefile.am
  4. 59 0
      tests/extrac21.at
  5. 2 0
      tests/testsuite.at

+ 6 - 1
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 <[email protected]>
 
 
@@ -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
 

+ 19 - 5
src/extract.c

@@ -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 (&current_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;

+ 1 - 0
tests/Makefile.am

@@ -109,6 +109,7 @@ TESTSUITE_AT = \
  extrac18.at\
  extrac19.at\
  extrac20.at\
+ extrac21.at\
  filerem01.at\
  filerem02.at\
  dirrem01.at\

+ 59 - 0
tests/extrac21.at

@@ -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 <[email protected]>
+# References: <[email protected]>,
+#    <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
+
+

+ 2 - 0
tests/testsuite.at

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