diff options
-rw-r--r-- | src/unix/fs.c | 28 |
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) { |