]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp: streamline cloning by skipping fstat
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 21 Nov 2021 20:31:07 +0000 (12:31 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 21 Nov 2021 20:32:46 +0000 (12:32 -0800)
* src/copy.c (copy_reg): Attempt clone_file before fstat of dest,
so that if clone_file succeeds we can skip the fstat.

src/copy.c

index 9f20a34b91d323ce5b04857787b146d75b49ce6e..97cc20d2969b485b81c24fceef9d1671c0814f67 100644 (file)
@@ -1093,7 +1093,7 @@ union scan_inference
 };
 
 /* Return how to scan a file with descriptor FD and stat buffer SB.
-   Store any information gathered into *SCAN.  */
+   Store any information gathered into *SCAN_INFERENCE.  */
 static enum scantype
 infer_scantype (int fd, struct stat const *sb,
                 union scan_inference *scan_inference)
@@ -1307,7 +1307,23 @@ copy_reg (char const *src_name, char const *dst_name,
       goto close_src_desc;
     }
 
-  if (fstat (dest_desc, &sb) != 0)
+  /* --attributes-only overrides --reflink.  */
+  if (data_copy_required && x->reflink_mode)
+    {
+      if (clone_file (dest_desc, source_desc) == 0)
+        data_copy_required = false;
+      else if (x->reflink_mode == REFLINK_ALWAYS)
+        {
+          error (0, errno, _("failed to clone %s from %s"),
+                 quoteaf_n (0, dst_name), quoteaf_n (1, src_name));
+          return_val = false;
+          goto close_src_and_dst_desc;
+        }
+    }
+
+  if (! (data_copy_required | x->preserve_ownership | extra_permissions))
+    sb.st_mode = 0;
+  else if (fstat (dest_desc, &sb) != 0)
     {
       error (0, errno, _("cannot fstat %s"), quoteaf (dst_name));
       return_val = false;
@@ -1322,23 +1338,6 @@ copy_reg (char const *src_name, char const *dst_name,
       && fchmod_or_lchmod (dest_desc, dst_name, temporary_mode) != 0)
     extra_permissions = 0;
 
-  /* --attributes-only overrides --reflink.  */
-  if (data_copy_required && x->reflink_mode)
-    {
-      bool clone_ok = clone_file (dest_desc, source_desc) == 0;
-      if (clone_ok || x->reflink_mode == REFLINK_ALWAYS)
-        {
-          if (!clone_ok)
-            {
-              error (0, errno, _("failed to clone %s from %s"),
-                     quoteaf_n (0, dst_name), quoteaf_n (1, src_name));
-              return_val = false;
-              goto close_src_and_dst_desc;
-            }
-          data_copy_required = false;
-        }
-    }
-
   if (data_copy_required)
     {
       /* Choose a suitable buffer size; it may be adjusted later.  */