bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Fix preserve_mode when destination directory partially exists


From: Jan Blunck
Subject: [PATCH] Fix preserve_mode when destination directory partially exists
Date: Fri, 4 Jan 2008 17:00:09 +0100
User-agent: Mutt/1.5.17 (2007-11-01)

I found a bug with cp -p --parents when the destination partially exists and
the filesystem isn't mounted with acls.

$ mkdir -p a/b/c a/b/d e
$ touch a/b/c/foo a/b/d/foo
$ cp -p --parent a/b/c e
$ cp -p --parent a/b/d e
$ ls -ld e/a
d--------- 3 jblunck suse 4096 1970-01-01 01:00 e/a

This bug was introduced by commit 811901cb41421e315c4b2e04989fb380ec20cb33 ("A
few more symlink-related fixes. Fix a bug triggered by cp").

I'm not sure if reseting the permissions of the already existing directories
is the right thing to do. At least it is the same behavior that cp had before
the above commit.

This patch always stats the src in make_dir_parents_private() before we test
if we need to create the destination directory. Therefore we always have a
valid st.st_mode which is used in re_protect() if we are running in
preserve_mode.

Regards,
        Jan
---
 src/cp.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

Index: b/src/cp.c
===================================================================
--- a/src/cp.c
+++ b/src/cp.c
@@ -404,6 +404,7 @@ make_dir_parents_private (char const *co
        slash++;
       while ((slash = strchr (slash, '/')))
        {
+         int src_errno;
          /* Add this directory to the list of directories whose modes need
             fixing later. */
          struct dir_attr *new = xmalloc (sizeof *new);
@@ -413,12 +414,22 @@ make_dir_parents_private (char const *co
          *attr_list = new;
 
          *slash = '\0';
+         src_errno = (stat (src, &new->st) != 0
+                      ? errno
+                      : S_ISDIR (new->st.st_mode)
+                      ? 0
+                      : ENOTDIR);
+         if (src_errno)
+           {
+             error (0, src_errno, _("failed to get attributes of %s"),
+                    quote (src));
+             return false;
+           }
          if (stat (dir, &stats) != 0)
            {
              mode_t src_mode;
              mode_t omitted_permissions;
              mode_t mkdir_mode;
-             int src_errno;
 
              /* This component does not exist.  We must set
                 *new_dst and new->st.st_mode inside this loop because,
@@ -426,17 +437,6 @@ make_dir_parents_private (char const *co
                 make_dir_parents_private creates only e_dir/../a if
                 ./b already exists. */
              *new_dst = true;
-             src_errno = (stat (src, &new->st) != 0
-                          ? errno
-                          : S_ISDIR (new->st.st_mode)
-                          ? 0
-                          : ENOTDIR);
-             if (src_errno)
-               {
-                 error (0, src_errno, _("failed to get attributes of %s"),
-                        quote (src));
-                 return false;
-               }
              src_mode = new->st.st_mode;
 
              /* If the ownership or special mode bits might change,




reply via email to

[Prev in Thread] Current Thread [Next in Thread]