Skip to content

Commit

Permalink
darwin: use runtime check for file cloning
Browse files Browse the repository at this point in the history
Using #ifdef guards is not reliable because libuv may have been compiled
on a newer system than what it runs on, or vice versa.

Fixes: libuv#2088
Fixes: nodejs/node#24521
  • Loading branch information
bnoordhuis committed Nov 24, 2018
1 parent 0813f5b commit 256158e
Showing 1 changed file with 25 additions and 10 deletions.
35 changes: 25 additions & 10 deletions src/unix/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

#if defined(__APPLE__)
# include <copyfile.h>
# include <sys/sysctl.h>
#elif defined(__linux__) && !defined(FICLONE)
# include <sys/ioctl.h>
# define FICLONE _IOW(0x94, 9, int)
Expand Down Expand Up @@ -793,26 +794,40 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
static ssize_t uv__fs_copyfile(uv_fs_t* req) {
#if defined(__APPLE__) && !TARGET_OS_IPHONE
/* On macOS, use the native copyfile(3). */
static int can_clone;
copyfile_flags_t flags;
char buf[64];
size_t len;
int major;

flags = COPYFILE_ALL;

if (req->flags & UV_FS_COPYFILE_EXCL)
flags |= COPYFILE_EXCL;

#ifdef COPYFILE_CLONE
if (req->flags & UV_FS_COPYFILE_FICLONE)
flags |= COPYFILE_CLONE;
#endif
/* Check OS version. Cloning is only supported on macOS >= 10.12. */
if (req->flags & (UV_FS_COPYFILE_FICLONE|UV_FS_COPYFILE_FICLONE_FORCE)) {
if (can_clone == 0) {
len = sizeof(buf);
if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0))
return UV__ERR(errno);

if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
#ifdef COPYFILE_CLONE_FORCE
flags |= COPYFILE_CLONE_FORCE;
#else
return UV_ENOSYS;
#endif
if (1 != sscanf(buf, "%d", &major))
abort();

can_clone = -1 + 2 * (major >= 16); /* macOS >= 10.12 */
}

if (can_clone < 0)
return UV_ENOSYS;
}

if (req->flags & UV_FS_COPYFILE_FICLONE)
flags |= 1 << 24; /* COPYFILE_CLONE */

if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE)
flags |= 1 << 25; /* COPYFILE_CLONE_FORCE */

return copyfile(req->path, req->new_path, NULL, flags);
#else
uv_fs_t fs_req;
Expand Down

0 comments on commit 256158e

Please sign in to comment.