From: Paul Eggert Date: Sun, 21 Nov 2021 23:07:18 +0000 (-0800) Subject: cp: clone on macOS X-Git-Tag: v9.1~176 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e36c0ce078a65c7dac6ac5ebdfb0cf096856427;p=thirdparty%2Fcoreutils.git 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. --- 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. */