]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp: clone on macOS
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 21 Nov 2021 23:07:18 +0000 (15:07 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 22 Nov 2021 03:13:03 +0000 (19:13 -0800)
* configure.ac: Check for fclonefileat.
* src/copy.c [HAVE_FCLONEFILEAT && !USE_XATTR]:
Include <sys/clonefile.h>.
(copy_reg): If possible, use fclonefileat to clone.

NEWS
configure.ac
src/copy.c

diff --git a/NEWS b/NEWS
index 3f7ed72183688592aaa207035b06e50b6f6db5d6..61f58b668f47fc314b6a02573cd6fcfbbdb9b547 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,11 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Improvements
 
+  On macOS, cp creates a copy-on-write clone if source and destination
+  are regular files on the same APFS file system, the destination does
+  not already exist, and cp is preserving mode and timestamps (e.g.,
+  'cp -p', 'cp -a').
+
   sort --debug now diagnoses issues with --field-separator characters
   that conflict with characters possibly used in numbers.
 
index 3f72068bf2241ff2dda8aab18e0a23bc2adb9670..9b8ea0dde72a95da1484d8d03db6e90f85661cb4 100644 (file)
@@ -320,6 +320,9 @@ if test $utils_cv_localtime_cache = yes; then
   AC_DEFINE([LOCALTIME_CACHE], [1], [FIXME])
 fi
 
+# macOS >= 10.12
+AC_CHECK_FUNCS([fclonefileat])
+
 # Assume that if getattrat exists, it's compatible with Solaris 11.
 AC_CHECK_FUNCS([getattrat])
 if test $ac_cv_func_getattrat = yes; then
index 97cc20d2969b485b81c24fceef9d1671c0814f67..0f9aa524474789bd33ea0f7f04ed238218600bda 100644 (file)
 # define FICLONE _IOW (0x94, 9, int)
 #endif
 
+#if HAVE_FCLONEFILEAT && !USE_XATTR
+# include <sys/clonefile.h>
+#endif
+
 #ifndef HAVE_FCHOWN
 # define HAVE_FCHOWN false
 # define fchown(fd, uid, gid) (-1)
@@ -1245,6 +1249,14 @@ copy_reg (char const *src_name, char const *dst_name,
 
   if (*new_dst)
     {
+#if HAVE_FCLONEFILEAT && !USE_XATTR
+      int clone_flags = x->preserve_ownership ? 0 : CLONE_NOOWNERCOPY;
+      if (data_copy_required && x->reflink_mode
+          && x->preserve_mode && x->preserve_timestamps
+          && fclonefileat (source_desc, AT_FDCWD, dst_name, clone_flags) == 0)
+        goto close_src_desc;
+#endif
+
       /* To allow copying xattrs on read-only files, create with u+w.
          This satisfies an inode permission check done by
          xattr_permission in fs/xattr.c of the GNU/Linux kernel.  */