summaryrefslogtreecommitdiff
path: root/Utilities/cmlibuv/src/unix/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/unix/fs.c')
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c105
1 files changed, 69 insertions, 36 deletions
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 0a4c183eb6..4545168f29 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -62,21 +62,23 @@
#if defined(__APPLE__)
# include <copyfile.h>
+#elif defined(__linux__) && !defined(FICLONE)
+# include <sys/ioctl.h>
+# define FICLONE _IOW(0x94, 9, int)
#endif
#define INIT(subtype) \
do { \
if (req == NULL) \
- return -EINVAL; \
- req->type = UV_FS; \
- if (cb != NULL) \
- uv__req_init(loop, req, UV_FS); \
+ return UV_EINVAL; \
+ UV_REQ_INIT(req, UV_FS); \
req->fs_type = UV_FS_ ## subtype; \
req->result = 0; \
req->ptr = NULL; \
req->loop = loop; \
req->path = NULL; \
req->new_path = NULL; \
+ req->bufs = NULL; \
req->cb = cb; \
} \
while (0)
@@ -88,10 +90,8 @@
req->path = path; \
} else { \
req->path = uv__strdup(path); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
} \
} \
while (0)
@@ -107,10 +107,8 @@
path_len = strlen(path) + 1; \
new_path_len = strlen(new_path) + 1; \
req->path = uv__malloc(path_len + new_path_len); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
req->new_path = req->path + path_len; \
memcpy((void*) req->path, path, path_len); \
memcpy((void*) req->new_path, new_path, new_path_len); \
@@ -121,6 +119,7 @@
#define POST \
do { \
if (cb != NULL) { \
+ uv__req_register(loop, req); \
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
return 0; \
} \
@@ -804,6 +803,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
if (req->flags & UV_FS_COPYFILE_EXCL)
flags |= COPYFILE_EXCL;
+#ifdef COPYFILE_CLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE)
+ flags |= COPYFILE_CLONE;
+#endif
+
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+#ifdef COPYFILE_CLONE_FORCE
+ flags |= COPYFILE_CLONE_FORCE;
+#else
+ return UV_ENOSYS;
+#endif
+ }
+
return copyfile(req->path, req->new_path, NULL, flags);
#else
uv_fs_t fs_req;
@@ -828,7 +840,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
/* Get the source file's mode. */
if (fstat(srcfd, &statsbuf)) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
@@ -852,9 +864,32 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
}
if (fchmod(dstfd, statsbuf.st_mode) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
+ goto out;
+ }
+
+#ifdef FICLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ if (ioctl(dstfd, FICLONE, srcfd) == -1) {
+ /* If an error occurred that the sendfile fallback also won't handle, or
+ this is a force clone then exit. Otherwise, fall through to try using
+ sendfile(). */
+ if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = -errno;
+ goto out;
+ }
+ } else {
+ goto out;
+ }
+ }
+#else
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = UV_ENOSYS;
goto out;
}
+#endif
bytes_to_send = statsbuf.st_size;
in_offset = 0;
@@ -1117,7 +1152,7 @@ static void uv__fs_work(struct uv__work* w) {
} while (r == -1 && errno == EINTR && retry_on_eintr);
if (r == -1)
- req->result = -errno;
+ req->result = UV__ERR(errno);
else
req->result = r;
@@ -1135,9 +1170,9 @@ static void uv__fs_done(struct uv__work* w, int status) {
req = container_of(w, uv_fs_t, work_req);
uv__req_unregister(req->loop, req);
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->result == 0);
- req->result = -ECANCELED;
+ req->result = UV_ECANCELED;
}
req->cb(req);
@@ -1298,11 +1333,8 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(MKDTEMP);
req->path = uv__strdup(tpl);
- if (req->path == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->path == NULL)
+ return UV_ENOMEM;
POST;
}
@@ -1330,7 +1362,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
INIT(READ);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
@@ -1339,11 +1371,8 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@@ -1469,7 +1498,7 @@ int uv_fs_write(uv_loop_t* loop,
INIT(WRITE);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
@@ -1478,11 +1507,8 @@ int uv_fs_write(uv_loop_t* loop,
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@@ -1509,6 +1535,10 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
uv__fs_scandir_cleanup(req);
+ if (req->bufs != req->bufsml)
+ uv__free(req->bufs);
+ req->bufs = NULL;
+
if (req->ptr != &req->statbuf)
uv__free(req->ptr);
req->ptr = NULL;
@@ -1523,8 +1553,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
- return -EINVAL;
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
+ return UV_EINVAL;
+ }
PATH2;
req->flags = flags;