]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp: preserve existing permissions with --no-preserve=mode
authorPádraig Brady <P@draigBrady.com>
Sun, 3 Jun 2018 23:19:20 +0000 (16:19 -0700)
committerPádraig Brady <P@draigBrady.com>
Sun, 3 Jun 2018 23:27:37 +0000 (16:27 -0700)
This issue was introduced in commit v8.19-145-g24ebca6

* src/copy.c (copy_internal): With --no-preserve=mode,
only reset permissions for newly created files.
(copy_reg): Likewise.
* NEWS: Mention the fix.
* tests/cp/preserve-mode.sh: Add a test case.
Fixes https://bugs.gnu.org/31675

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

diff --git a/NEWS b/NEWS
index 4c63b6d7cbea821e34dce23a821b6b500c0ebdb8..101afc08099e406ee546d8b0a1db37654c466f42 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,8 +17,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   [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.
+  for non regular files like fifos and character device nodes etc.,
+  and leaves mode bits of existing files unchanged.
+  Previously it would have set executable bits on created special files,
+  and set mode bits for existing files as if they had been created.
   [bug introduced with coreutils-8.20]
 
   'cp --remove-destination file symlink' now removes the symlink
index f4c92d7d7fcd7b73f55371076b9c22314a1d5954..eccf67cdb2570e40ed4008fd5cf8e7cc374e7f9b 100644 (file)
@@ -1379,7 +1379,7 @@ preserve_metadata:
       if (set_acl (dst_name, dest_desc, x->mode) != 0)
         return_val = false;
     }
-  else if (x->explicit_no_preserve_mode)
+  else if (x->explicit_no_preserve_mode && *new_dst)
     {
       if (set_acl (dst_name, dest_desc, MODE_RW_UGO & ~cached_umask ()) != 0)
         return_val = false;
@@ -2862,7 +2862,7 @@ copy_internal (char const *src_name, char const *dst_name,
       if (set_acl (dst_name, -1, x->mode) != 0)
         return false;
     }
-  else if (x->explicit_no_preserve_mode)
+  else if (x->explicit_no_preserve_mode && new_dst)
     {
       int default_permissions = S_ISDIR (src_mode) || S_ISSOCK (src_mode)
                                 ? S_IRWXUGO : MODE_RW_UGO;
index 3b0aca8e77597e7f4c0d800592b435b638e5110f..f5bf9d2cc212f8523d2a9bc4bfdc68c36650057c 100755 (executable)
@@ -21,29 +21,29 @@ print_ver_ cp
 
 get_mode() { stat -c%f "$1"; }
 
-rm -f a b c
-umask 0022
-touch a
-touch b
-chmod 600 b
+umask 0022 || framework_failure_
 
 #regular file test
+touch a b || framework_failure_
+chmod 600 b || framework_failure_
 cp --no-preserve=mode b c || fail=1
 test "$(get_mode a)" = "$(get_mode c)" || fail=1
 
-rm -rf d1 d2 d3
-mkdir d1 d2
-chmod 705 d2
+#existing destination test
+chmod 600 c || framework_failure_
+cp --no-preserve=mode a b || fail=1
+test "$(get_mode b)" = "$(get_mode c)" || fail=1
 
 #directory test
+mkdir d1 d2 || framework_failure_
+chmod 705 d2 || framework_failure_
 cp --no-preserve=mode -r d2 d3 || fail=1
 test "$(get_mode d1)" = "$(get_mode d3)" || fail=1
 
-rm -f a b c
-touch a
-chmod 600 a
-
 #contradicting options test
+rm -f a b || framework_failure_
+touch a || framework_failure_
+chmod 600 a || framework_failure_
 cp --no-preserve=mode --preserve=all a b || fail=1
 test "$(get_mode a)" = "$(get_mode b)" || fail=1