]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp: set appropriate default permissions for special files
authorPádraig Brady <P@draigBrady.com>
Tue, 20 Feb 2018 03:10:14 +0000 (19:10 -0800)
committerPádraig Brady <P@draigBrady.com>
Sun, 25 Feb 2018 02:15:26 +0000 (18:15 -0800)
This issue was introduced in commit v8.19-145-g24ebca6

* src/copy.c (copy_internal): When setting default permissions
to use with --no-preserve=mode, only set executable bits for
directories or sockets.
* NEWS: Mention the fix.
* tests/cp/preserve-mode.sh: Add a test case.
Fixes https://bugs.gnu.org/30534

NEWS
src/copy.c
tests/cp/preserve-mode.sh

diff --git a/NEWS b/NEWS
index 8a9e09eb4facf280553d484f3eda87b06d740ed5..5fa69285d7eb440a1b74a030b02654b71ec44167 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,11 @@ GNU coreutils NEWS                                    -*- outline -*-
   that caused -u to sometimes override -n.
   [bug introduced with coreutils-7.1]
 
+  'cp -a --no-preserve=mode' now sets appropriate default permissions
+  for non regular files like fifos and character device nodes etc.
+  Previously it would have set executable bits on created special files.
+  [bug introduced with coreutils-8.20]
+
 
 * Noteworthy changes in release 8.29 (2017-12-27) [stable]
 
index e050d4199bba31e60f03a19bd64ae98bba0c2a6c..4998c83e6a6e37eb5060efca08a08dd3157adbae 100644 (file)
@@ -1353,7 +1353,10 @@ preserve_metadata:
       bool access_changed = false;
 
       if (!(sb.st_mode & S_IWUSR) && geteuid () != ROOT_UID)
-        access_changed = fchmod_or_lchmod (dest_desc, dst_name, 0600) == 0;
+        {
+          access_changed = fchmod_or_lchmod (dest_desc, dst_name,
+                                             S_IRUSR | S_IWUSR) == 0;
+        }
 
       if (!copy_attr (src_name, source_desc, dst_name, dest_desc, x)
           && x->require_preserve_xattr)
@@ -1378,7 +1381,7 @@ preserve_metadata:
     }
   else if (x->explicit_no_preserve_mode)
     {
-      if (set_acl (dst_name, dest_desc, 0666 & ~cached_umask ()) != 0)
+      if (set_acl (dst_name, dest_desc, MODE_RW_UGO & ~cached_umask ()) != 0)
         return_val = false;
     }
   else if (omitted_permissions)
@@ -2860,7 +2863,9 @@ copy_internal (char const *src_name, char const *dst_name,
     }
   else if (x->explicit_no_preserve_mode)
     {
-      if (set_acl (dst_name, -1, 0777 & ~cached_umask ()) != 0)
+      int default_permissions = S_ISDIR (src_mode) || S_ISSOCK (src_mode)
+                                ? S_IRWXUGO : MODE_RW_UGO;
+      if (set_acl (dst_name, -1, default_permissions & ~cached_umask ()) != 0)
         return false;
     }
   else
index 1cd173a6ccaf961b6b6cc76e8c6841614af29470..3b0aca8e77597e7f4c0d800592b435b638e5110f 100755 (executable)
@@ -19,7 +19,7 @@
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 print_ver_ cp
 
-get_mode() { ls -ld "$1" | cut -b-10; }
+get_mode() { stat -c%f "$1"; }
 
 rm -f a b c
 umask 0022
@@ -47,4 +47,12 @@ chmod 600 a
 cp --no-preserve=mode --preserve=all a b || fail=1
 test "$(get_mode a)" = "$(get_mode b)" || fail=1
 
+#fifo test
+if mkfifo fifo; then
+  cp -a --no-preserve=mode fifo fifo_copy || fail=1
+  #ensure default perms set appropriate for non regular files
+  #which wasn't done between v8.20 and 8.29 inclusive
+  test "$(get_mode fifo)" = "$(get_mode fifo_copy)" || fail=1
+fi
+
 Exit $fail