aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/unix/fs.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/unix/fs.c b/src/unix/fs.c
index ea1d305f..9c8ef6cc 100644
--- a/src/unix/fs.c
+++ b/src/unix/fs.c
@@ -65,6 +65,7 @@
#endif
#if defined(__APPLE__)
+# include <copyfile.h>
# include <sys/sysctl.h>
#elif defined(__linux__) && !defined(FICLONE)
# include <sys/ioctl.h>
@@ -1240,6 +1241,32 @@ done:
}
static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+#if defined(__APPLE__) && !TARGET_OS_IPHONE
+ /* On macOS, use the native copyfile(3). */
+ copyfile_flags_t flags;
+
+ /* Don't overwrite the destination if its permissions disallow it. */
+ if (faccessat(AT_FDCWD, req->new_path, R_OK | W_OK, AT_EACCESS)) {
+ if (errno != ENOENT)
+ return UV__ERR(errno);
+ }
+
+ flags = COPYFILE_ALL;
+
+ if (req->flags & UV_FS_COPYFILE_FICLONE)
+ flags |= COPYFILE_CLONE;
+
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE)
+ flags |= COPYFILE_CLONE_FORCE;
+
+ if (req->flags & UV_FS_COPYFILE_EXCL)
+ flags |= COPYFILE_EXCL;
+
+ if (copyfile(req->path, req->new_path, NULL, flags))
+ return UV__ERR(errno);
+
+ return 0;
+#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */
uv_fs_t fs_req;
uv_file srcfd;
uv_file dstfd;
@@ -1415,6 +1442,7 @@ out:
errno = UV__ERR(result);
return -1;
+#endif /* defined(__APPLE__) && !TARGET_OS_IPHONE */
}
static void uv__to_stat(struct stat* src, uv_stat_t* dst) {