]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
--no-overwrite-dir no overwrite even temporarily master
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 27 Jul 2025 04:41:23 +0000 (21:41 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 27 Jul 2025 04:49:20 +0000 (21:49 -0700)
Problem and fix reported by Pavel Cahyna in
https://lists.gnu.org/r/bug-tar/2025-01/msg00000.html
* src/extract.c (extract_dir): With --no-overwrite-dir,
skip the chmod if the directory already exists.
* tests/extrac23.at (--no-overwrite-dir on empty directory):
Move the part of the test that looks at a nonempty directory ...
* tests/extrac30.at: ... to this new file, because the test now
must be run as non-root.  Adjust the test to match the new behavior.
* tests/Makefile.am (TESTSUITE_AT), tests/testsuite.at: Add it.

NEWS
src/extract.c
tests/Makefile.am
tests/extrac23.at
tests/extrac30.at [new file with mode: 0644]
tests/testsuite.at

diff --git a/NEWS b/NEWS
index e12fff270d9e0522f0cea7e57ef6f079e67e0ad5..9a10b8b8c2a9dfc6bc086b11f9fd1f76b789301b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU tar NEWS - User visible changes. 2025-07-25
+GNU tar NEWS - User visible changes. 2025-07-26
 Please send GNU tar bug reports to <bug-tar@gnu.org>
 \f
 version TBD
@@ -45,6 +45,10 @@ option.
 ** Transformations that change case (e.g., --transform='s/.*/\L&/')
    now work correctly with multi-byte characters.
 
+** --no-overwrite-dir no longer changes permissions of existing directories,
+   not even temporarily.  This matches the documentation better and avoids
+   some permissions glitches.
+
 ** tar now works better in strict debugging environments that do not
    allow pointer arithmetic to escape from a sub-element of an array.
 
index 304e1f79943295e25e35210ffc7c0cccbc16734a..3b913c54398fe6f31442a9ec125fb4dd197765d9 100644 (file)
@@ -1158,31 +1158,6 @@ extract_dir (char *file_name, char typeflag)
                          repair_delayed_set_stat (file_name, &st);
                          return true;
                        }
-                     else if (old_files_option == NO_OVERWRITE_DIR_OLD_FILES)
-                       {
-                         /* Temporarily change the directory mode to a safe
-                            value, to be able to create files in it, should
-                            the need be.
-                         */
-                         mode = safe_dir_mode (&st);
-                         status = fd_chmod (-1, file_name, mode,
-                                            AT_SYMLINK_NOFOLLOW, DIRTYPE);
-                         if (status == 0)
-                           {
-                             /* Store the actual directory mode, to be restored
-                                later.
-                             */
-                             current_stat_info.stat = st;
-                             current_mode = mode & ~ current_umask;
-                             current_mode_mask = MODE_RWX;
-                             atflag = AT_SYMLINK_NOFOLLOW;
-                             break;
-                           }
-                         else
-                           {
-                             chmod_error_details (file_name, mode);
-                           }
-                       }
                      break;
                    }
                }
index bd13bfb2fa94214428335fca6f1614be9936ea44..cd8793615276dcc7911ccec0e260e123c584bbed 100644 (file)
@@ -139,6 +139,7 @@ TESTSUITE_AT = \
  extrac27.at\
  extrac28.at\
  extrac29.at\
+ extrac30.at\
  filerem01.at\
  filerem02.at\
  grow.at\
index c8943a73b3fdbccd921577b0e7eb1a449168bdd4..9714ba59d35efe8de59c78b89a62d7145b460984 100644 (file)
 #
 # 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([--no-overwrite-dir])
+AT_SETUP([--no-overwrite-dir on empty directory])
 AT_KEYWORDS([extract extrac23 no-overwrite-dir])
 
 # Description: Implementation of the --no-overwrite-dir option was flawed in
 # tar versions up to 1.32.90.  This option is intended to preserve metadata
 # of existing directories.  In fact it worked only for non-empty directories.
-# Moreover, if the actual directory was owned by the user tar runs as and the
-# S_IWUSR bit was not set in its actual permissions, tar failed to create files
-# in it.
 #
 # Reported by: Michael Kaufmann <mail@michael-kaufmann.ch>
 # References: <20200207112934.Horde.anXzYhAj2CHiwUrw5CuT0G-@webmail.michael-kaufmann.ch>,
@@ -38,21 +35,10 @@ chmod 777 dir
 tar -xf a.tar --no-overwrite-dir
 genfile --stat=mode.777 dir
 
-# Test if temporary permissions are set correctly to allow the owner
-# to write to the directory.
-genfile --file dir/file
-tar cf a.tar dir
-rm dir/file
-chmod 400 dir
-tar -xf a.tar --no-overwrite-dir
-genfile --stat=mode.777 dir
-chmod 700 dir
 find dir
 ],
 [0],
 [777
-400
 dir
-dir/file
 ])
 AT_CLEANUP
diff --git a/tests/extrac30.at b/tests/extrac30.at
new file mode 100644 (file)
index 0000000..8c879c9
--- /dev/null
@@ -0,0 +1,47 @@
+# Test suite for GNU tar.                             -*- Autotest -*-
+# Copyright 2020-2025 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/>.
+AT_SETUP([--no-overwrite-dir on unwritable directory])
+AT_KEYWORDS([extract extrac30 no-overwrite-dir])
+
+# Make sure that tar does not change permissions on directories if
+# --no-overwrite-dir tells it not to, not even temporarily.
+
+AT_TAR_CHECK([
+AT_UNPRIVILEGED_PREREQ
+
+# Test that the user cannot write to a unwritable directory
+# if --no-overwrite-dir is used.
+mkdir dir
+chmod 755 dir
+genfile --file dir/file
+tar cf a.tar dir
+rm dir/file
+chmod 555 dir
+tar -xf a.tar --no-overwrite-dir
+genfile --stat=mode.777 dir
+chmod 755 dir
+find dir
+],
+[0],
+[555
+dir
+],
+[tar: dir/file: Cannot open: Permission denied
+tar: Exiting with failure status due to previous errors
+])
+AT_CLEANUP
index 701f03896783d621b756ac8e2566f0f7b3684a76..e7e54f1e2d24590fe056cb0d13baf56548dd7f7a 100644 (file)
@@ -356,6 +356,7 @@ m4_include([extrac26.at])
 m4_include([extrac27.at])
 m4_include([extrac28.at])
 m4_include([extrac29.at])
+m4_include([extrac30.at])
 
 m4_include([backup01.at])