From 5e36c0ce078a65c7dac6ac5ebdfb0cf096856427 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 21 Nov 2021 15:07:18 -0800 Subject: [PATCH] cp: clone on macOS * configure.ac: Check for fclonefileat. * src/copy.c [HAVE_FCLONEFILEAT && !USE_XATTR]: Include . (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 3f7ed72183..61f58b668f 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 3f72068bf2..9b8ea0dde7 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 97cc20d296..0f9aa52447 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 +#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.47.2