On 17/08/16 12:42, Mark Mitchell wrote:
> Hi,
> 
> I'm writing to report a potential bug with cp.  I don't think the mode bits
> always get properly set on directories created when using the --parents
> option combined with --no-preserve=mode option.  I'm not sure what the
> expected behaviour is supposed to be, but my assumption is that the created
> directories would match process's ~umask (like mkdir -p).
> 
> I've attached a simple script and its output to demonstrate the behaviour.
> I've tested this on the most recent master branch of the coreutils git
> repository (output of git describe is 'v8.25-55-gff2178b').
> 
> Thanks for your efforts on these utilities, it is much appreciated :-).

I agree that's unexpected, especially since cp -r --no-preserve=mode
does not copy the permissions for created dirs.

I think this may have changed with:
http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.92-435-gfdffb6b

I've adjusted things back in the attached.

thanks,
Pádraig.
From bd75118c16d8bca235b61dbb99326c043278a791 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Thu, 18 Aug 2016 13:54:48 +0100
Subject: [PATCH] cp: with --parents --no-preserve=mode don't copy dir perms

* src/cp.c (make_dir_parents_private): Use default permissions for
created directories when --no-preserve=mode is specified.
* tests/cp/cp-parents.sh: Add a test case.
* NEWS: Mention the fix.
Fixes http://bugs.gnu.org/24251
---
 NEWS                   |  4 ++++
 src/cp.c               |  3 ++-
 tests/cp/cp-parents.sh | 27 +++++++++++++++++++--------
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/NEWS b/NEWS
index c0e0d37..34a969e 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   handling ACLs on Cygwin and Solaris platforms. [bug introduced in
   coreutils-8.24]
 
+  cp --parents --no-preserve=mode, no longer copies permissions from source
+  directories, instead using default permissions for created directories.
+  [bug introduced in coreutils-5.93]
+
   chcon, chgrp, chmod, chown, du, and rm, or specifically utilities
   using the FTS interface, now diagnose failures returned by readdir().
   [this bug was inherent in the use of fts: thus, for rm the bug was
diff --git a/src/cp.c b/src/cp.c
index 3b5b6cb..13dc1ea 100644
--- a/src/cp.c
+++ b/src/cp.c
@@ -476,7 +476,8 @@ make_dir_parents_private (char const *const_dir, size_t src_offset,
                  (src_mode & ~S_IRWXUGO) != 0.  However, common practice is
                  to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
                  decide what to do with S_ISUID | S_ISGID | S_ISVTX.  */
-              mkdir_mode = src_mode & CHMOD_MODE_BITS & ~omitted_permissions;
+              mkdir_mode = x->explicit_no_preserve_mode ? S_IRWXUGO : src_mode;
+              mkdir_mode &= CHMOD_MODE_BITS & ~omitted_permissions;
               if (mkdir (dir, mkdir_mode) != 0)
                 {
                   error (0, errno, _("cannot make directory %s"),
diff --git a/tests/cp/cp-parents.sh b/tests/cp/cp-parents.sh
index b0be883..3819e3d 100755
--- a/tests/cp/cp-parents.sh
+++ b/tests/cp/cp-parents.sh
@@ -1,6 +1,4 @@
 #!/bin/sh
-# cp -R --parents dir-specified-with-trailing-slash/ other-dir
-# would get a failed assertion.
 
 # Copyright (C) 2000-2016 Free Software Foundation, Inc.
 
@@ -25,14 +23,15 @@ working_umask_or_skip_
 # Run the setgid check from the just-created directory.
 skip_if_setgid_
 
-mkdir foo bar || framework_failure_
-mkdir -p a/b/c d e g || framework_failure_
-ln -s d/a sym || framework_failure_
-touch f || framework_failure_
-
+{
+  mkdir foo bar
+  mkdir -p a/b/c d e g
+  ln -s d/a sym
+  touch f
+} || framework_failure_
 
 # With 4.0.37 and earlier (back to when?), this would fail
-# with the failed assertion from dirname.c.
+# with the failed assertion from dirname.c due to the trailing slash.
 cp -R --parents foo/ bar || fail=1
 
 # Exercise the make_path and re_protect code in cp.c.
@@ -55,4 +54,16 @@ p=$(ls -ld g/sym|cut -b-10); case $p in drwx-w--w-);; *) fail=1;; esac
 p=$(ls -ld e/d/a/b/c|cut -b-10); case $p in drwxr-xr-x);; *) fail=1;; esac
 p=$(ls -ld g/sym/b/c|cut -b-10); case $p in drwxr-xr-x);; *) fail=1;; esac
 
+# Before 8.25 cp --parents --no-preserve=mode would copy
+# the mode bits from the source directories
+{
+  mkdir -p np/b &&
+  chmod 0700 np &&
+  touch np/b/file &&
+  chmod 775 np/b/file &&
+  mkdir np_dest
+} || framework_failure_
+cp --parents --no-preserve=mode np/b/file np_dest/ || fail=1
+p=$(ls -ld np_dest/np|cut -b-10); case $p in drwxr-xr-x);; *) fail=1;; esac
+
 Exit $fail
-- 
2.5.5

Reply via email to