]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
Fix a minor race condition when using cp -p --parents.
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 9 Jan 2008 10:24:12 +0000 (11:24 +0100)
committerJim Meyering <meyering@redhat.com>
Wed, 9 Jan 2008 10:24:12 +0000 (11:24 +0100)
* src/cp.c (make_dir_parents_private): If stat fails on the parent
directory, do not add it to the list of directories whose modes
might need fixing later.  Also, do not bother invoking 'stat'
unless the stat results might be needed later.

ChangeLog
src/cp.c

index e834634c3040f5915e40dcc05250a32577a2c96c..7e543ba622c4b3b4264aa9886658181f8c6b80fb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-01-08  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Fix a minor race condition when using cp -p --parents.
+       * src/cp.c (make_dir_parents_private): If stat fails on the parent
+       directory, do not add it to the list of directories whose modes
+       might need fixing later.  Also, do not bother invoking 'stat'
+       unless the stat results might be needed later.
+
 2008-01-08  Jim Meyering  <meyering@redhat.com>
 
        parent-perm: avoid a bizarre test failure.
index 01d98cc6472d19876fb531e9f38f827fca193725..a46f900bc7c47fa143bf67b326aca1e2cb0ff907 100644 (file)
--- a/src/cp.c
+++ b/src/cp.c
@@ -403,28 +403,39 @@ make_dir_parents_private (char const *const_dir, size_t src_offset,
        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);
-         new->slash_offset = slash - dir;
-         new->restore_mode = false;
-         new->next = *attr_list;
-         *attr_list = new;
+         struct dir_attr *new IF_LINT (= NULL);
+         bool missing_dir;
 
          *slash = '\0';
-         src_errno = (stat (src, &new->st) != 0
-                      ? errno
-                      : S_ISDIR (new->st.st_mode)
-                      ? 0
-                      : ENOTDIR);
-         if (src_errno)
+         missing_dir = (stat (dir, &stats) != 0);
+
+         if (missing_dir | x->preserve_ownership | x->preserve_mode
+             | x->preserve_timestamps)
            {
-             error (0, src_errno, _("failed to get attributes of %s"),
-                    quote (src));
-             return false;
+             /* Add this directory to the list of directories whose
+                modes might need fixing later. */
+             struct stat src_st;
+             int src_errno = (stat (src, &src_st) != 0
+                              ? errno
+                              : S_ISDIR (src_st.st_mode)
+                              ? 0
+                              : ENOTDIR);
+             if (src_errno)
+               {
+                 error (0, src_errno, _("failed to get attributes of %s"),
+                        quote (src));
+                 return false;
+               }
+
+             new = xmalloc (sizeof *new);
+             new->st = src_st;
+             new->slash_offset = slash - dir;
+             new->restore_mode = false;
+             new->next = *attr_list;
+             *attr_list = new;
            }
-         if (stat (dir, &stats) != 0)
+
+         if (missing_dir)
            {
              mode_t src_mode;
              mode_t omitted_permissions;