|
62 | 62 |
|
63 | 63 | #if defined(__APPLE__)
|
64 | 64 | # include <copyfile.h>
|
| 65 | +#elif defined(__linux__) && !defined(FICLONE) |
| 66 | +# include <sys/ioctl.h> |
| 67 | +# define FICLONE _IOW(0x94, 9, int) |
65 | 68 | #endif
|
66 | 69 |
|
67 | 70 | #define INIT(subtype) \
|
@@ -790,6 +793,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
790 | 793 | if (req->flags & UV_FS_COPYFILE_EXCL)
|
791 | 794 | flags |= COPYFILE_EXCL;
|
792 | 795 |
|
| 796 | +#ifdef COPYFILE_CLONE |
| 797 | + if (req->flags & UV_FS_COPYFILE_FICLONE) |
| 798 | + flags |= COPYFILE_CLONE; |
| 799 | +#endif |
| 800 | + |
| 801 | + if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { |
| 802 | +#ifdef COPYFILE_CLONE_FORCE |
| 803 | + flags |= COPYFILE_CLONE_FORCE; |
| 804 | +#else |
| 805 | + return UV_ENOSYS; |
| 806 | +#endif |
| 807 | + } |
| 808 | + |
793 | 809 | return copyfile(req->path, req->new_path, NULL, flags);
|
794 | 810 | #else
|
795 | 811 | uv_fs_t fs_req;
|
@@ -842,6 +858,29 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
842 | 858 | goto out;
|
843 | 859 | }
|
844 | 860 |
|
| 861 | +#ifdef FICLONE |
| 862 | + if (req->flags & UV_FS_COPYFILE_FICLONE || |
| 863 | + req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { |
| 864 | + if (ioctl(dstfd, FICLONE, srcfd) == -1) { |
| 865 | + /* If an error occurred that the sendfile fallback also won't handle, or |
| 866 | + this is a force clone then exit. Otherwise, fall through to try using |
| 867 | + sendfile(). */ |
| 868 | + if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) || |
| 869 | + req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { |
| 870 | + err = -errno; |
| 871 | + goto out; |
| 872 | + } |
| 873 | + } else { |
| 874 | + goto out; |
| 875 | + } |
| 876 | + } |
| 877 | +#else |
| 878 | + if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { |
| 879 | + err = UV_ENOSYS; |
| 880 | + goto out; |
| 881 | + } |
| 882 | +#endif |
| 883 | + |
845 | 884 | bytes_to_send = statsbuf.st_size;
|
846 | 885 | in_offset = 0;
|
847 | 886 | while (bytes_to_send != 0) {
|
@@ -1504,8 +1543,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
|
1504 | 1543 | uv_fs_cb cb) {
|
1505 | 1544 | INIT(COPYFILE);
|
1506 | 1545 |
|
1507 |
| - if (flags & ~UV_FS_COPYFILE_EXCL) |
| 1546 | + if (flags & ~(UV_FS_COPYFILE_EXCL | |
| 1547 | + UV_FS_COPYFILE_FICLONE | |
| 1548 | + UV_FS_COPYFILE_FICLONE_FORCE)) { |
1508 | 1549 | return UV_EINVAL;
|
| 1550 | + } |
1509 | 1551 |
|
1510 | 1552 | PATH2;
|
1511 | 1553 | req->flags = flags;
|
|
0 commit comments