coreutils
[Top][All Lists]
Advanced

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

[PATCH] cp: clone on macOS


From: Paul Eggert
Subject: [PATCH] cp: clone on macOS
Date: Sun, 21 Nov 2021 19:13:37 -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         |  5 +++++
 configure.ac |  3 +++
 src/copy.c   | 12 ++++++++++++
 3 files changed, 20 insertions(+)

diff --git a/NEWS b/NEWS
index 3f7ed7218..61f58b668 100644
--- 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.
 
diff --git a/configure.ac b/configure.ac
index 3f72068bf..9b8ea0dde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/src/copy.c b/src/copy.c
index 97cc20d29..0f9aa5244 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -90,6 +90,10 @@
 # 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.  */
-- 
2.33.1




reply via email to

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