summaryrefslogtreecommitdiff
path: root/deps/uvwasi/src/uvwasi.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uvwasi/src/uvwasi.c')
-rw-r--r--deps/uvwasi/src/uvwasi.c508
1 files changed, 366 insertions, 142 deletions
diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c
index 39a94b6d21..0f7c4c5d3a 100644
--- a/deps/uvwasi/src/uvwasi.c
+++ b/deps/uvwasi/src/uvwasi.c
@@ -19,26 +19,69 @@
#define UVWASI__READDIR_NUM_ENTRIES 1
#include "uvwasi.h"
+#include "uvwasi_alloc.h"
#include "uv.h"
#include "uv_mapping.h"
#include "fd_table.h"
#include "clocks.h"
+static void* default_malloc(size_t size, void* mem_user_data) {
+ return malloc(size);
+}
+
+static void default_free(void* ptr, void* mem_user_data) {
+ free(ptr);
+}
+
+static void* default_calloc(size_t nmemb, size_t size, void* mem_user_data) {
+ return calloc(nmemb, size);
+}
+
+static void* default_realloc(void* ptr, size_t size, void* mem_user_data) {
+ return realloc(ptr, size);
+}
+
+void* uvwasi__malloc(const uvwasi_t* uvwasi, size_t size) {
+ return uvwasi->allocator->malloc(size, uvwasi->allocator->mem_user_data);
+}
+
+void uvwasi__free(const uvwasi_t* uvwasi, void* ptr) {
+ uvwasi->allocator->free(ptr, uvwasi->allocator->mem_user_data);
+}
+
+void* uvwasi__calloc(const uvwasi_t* uvwasi, size_t nmemb, size_t size) {
+ return uvwasi->allocator->calloc(nmemb,
+ size,
+ uvwasi->allocator->mem_user_data);
+}
+
+void* uvwasi__realloc(const uvwasi_t* uvwasi, void* ptr, size_t size) {
+ return uvwasi->allocator->realloc(ptr,
+ size,
+ uvwasi->allocator->mem_user_data);
+}
+
+static const uvwasi_mem_t default_allocator = {
+ NULL,
+ default_malloc,
+ default_free,
+ default_calloc,
+ default_realloc,
+};
+
static int uvwasi__is_absolute_path(const char* path, size_t path_len) {
- /* TODO(cjihrig): Add a Windows implementation. */
- return path != NULL && path_len > 0 && path[0] == SLASH;
+ /* It's expected that only Unix style paths will be generated by WASI. */
+ return path != NULL && path_len > 0 && path[0] == '/';
}
-static uvwasi_errno_t uvwasi__resolve_path(const struct uvwasi_fd_wrap_t* fd,
+static uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi,
+ const struct uvwasi_fd_wrap_t* fd,
const char* path,
size_t path_len,
char* resolved_path,
uvwasi_lookupflags_t flags) {
- /* TODO(cjihrig): path_len is treated as a size. Need to verify if path_len is
- really a string length or a size. Also need to verify if it is null
- terminated. */
uv_fs_t realpath_req;
uvwasi_errno_t err;
char* abs_path;
@@ -58,7 +101,7 @@ static uvwasi_errno_t uvwasi__resolve_path(const struct uvwasi_fd_wrap_t* fd,
if (1 == input_is_absolute) {
/* TODO(cjihrig): Revisit this. Copying is probably not necessary here. */
abs_size = path_len;
- abs_path = malloc(abs_size);
+ abs_path = uvwasi__malloc(uvwasi, abs_size);
if (abs_path == NULL) {
err = UVWASI_ENOMEM;
goto exit;
@@ -68,7 +111,7 @@ static uvwasi_errno_t uvwasi__resolve_path(const struct uvwasi_fd_wrap_t* fd,
} else {
/* Resolve the relative path to fd's real path. */
abs_size = path_len + strlen(fd->real_path) + 2;
- abs_path = malloc(abs_size);
+ abs_path = uvwasi__malloc(uvwasi, abs_size);
if (abs_path == NULL) {
err = UVWASI_ENOMEM;
goto exit;
@@ -146,7 +189,7 @@ static uvwasi_errno_t uvwasi__resolve_path(const struct uvwasi_fd_wrap_t* fd,
}
exit:
- free(abs_path);
+ uvwasi__free(uvwasi, abs_path);
return err;
}
@@ -185,13 +228,17 @@ static uvwasi_errno_t uvwasi__lseek(uv_file fd,
}
-static uvwasi_errno_t uvwasi__setup_iovs(uv_buf_t** buffers,
+static uvwasi_errno_t uvwasi__setup_iovs(const uvwasi_t* uvwasi,
+ uv_buf_t** buffers,
const uvwasi_iovec_t* iovs,
size_t iovs_len) {
uv_buf_t* bufs;
size_t i;
- bufs = malloc(iovs_len * sizeof(*bufs));
+ if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len)
+ return UVWASI_ENOMEM;
+
+ bufs = uvwasi__malloc(uvwasi, iovs_len * sizeof(*bufs));
if (bufs == NULL)
return UVWASI_ENOMEM;
@@ -203,13 +250,17 @@ static uvwasi_errno_t uvwasi__setup_iovs(uv_buf_t** buffers,
}
-static uvwasi_errno_t uvwasi__setup_ciovs(uv_buf_t** buffers,
+static uvwasi_errno_t uvwasi__setup_ciovs(const uvwasi_t* uvwasi,
+ uv_buf_t** buffers,
const uvwasi_ciovec_t* iovs,
size_t iovs_len) {
uv_buf_t* bufs;
size_t i;
- bufs = malloc(iovs_len * sizeof(*bufs));
+ if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len)
+ return UVWASI_ENOMEM;
+
+ bufs = uvwasi__malloc(uvwasi, iovs_len * sizeof(*bufs));
if (bufs == NULL)
return UVWASI_ENOMEM;
@@ -236,6 +287,10 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) {
if (uvwasi == NULL || options == NULL || options->fd_table_size == 0)
return UVWASI_EINVAL;
+ uvwasi->allocator = options->allocator;
+ if (uvwasi->allocator == NULL)
+ uvwasi->allocator = &default_allocator;
+
uvwasi->argv_buf = NULL;
uvwasi->argv = NULL;
uvwasi->env_buf = NULL;
@@ -250,13 +305,13 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) {
uvwasi->argv_buf_size = args_size;
if (args_size > 0) {
- uvwasi->argv_buf = malloc(args_size);
+ uvwasi->argv_buf = uvwasi__malloc(uvwasi, args_size);
if (uvwasi->argv_buf == NULL) {
err = UVWASI_ENOMEM;
goto exit;
}
- uvwasi->argv = calloc(options->argc, sizeof(char*));
+ uvwasi->argv = uvwasi__calloc(uvwasi, options->argc, sizeof(char*));
if (uvwasi->argv == NULL) {
err = UVWASI_ENOMEM;
goto exit;
@@ -284,13 +339,13 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) {
uvwasi->env_buf_size = env_buf_size;
if (env_buf_size > 0) {
- uvwasi->env_buf = malloc(env_buf_size);
+ uvwasi->env_buf = uvwasi__malloc(uvwasi, env_buf_size);
if (uvwasi->env_buf == NULL) {
err = UVWASI_ENOMEM;
goto exit;
}
- uvwasi->env = calloc(env_count, sizeof(char*));
+ uvwasi->env = uvwasi__calloc(uvwasi, env_count, sizeof(char*));
if (uvwasi->env == NULL) {
err = UVWASI_ENOMEM;
goto exit;
@@ -313,7 +368,7 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) {
}
}
- err = uvwasi_fd_table_init(&uvwasi->fds, options->fd_table_size);
+ err = uvwasi_fd_table_init(uvwasi, &uvwasi->fds, options->fd_table_size);
if (err != UVWASI_ESUCCESS)
goto exit;
@@ -336,7 +391,8 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) {
goto exit;
}
- err = uvwasi_fd_table_insert_preopen(&uvwasi->fds,
+ err = uvwasi_fd_table_insert_preopen(uvwasi,
+ &uvwasi->fds,
open_req.result,
options->preopens[i].mapped_path,
realpath_req.ptr);
@@ -359,11 +415,11 @@ void uvwasi_destroy(uvwasi_t* uvwasi) {
if (uvwasi == NULL)
return;
- uvwasi_fd_table_free(&uvwasi->fds);
- free(uvwasi->argv_buf);
- free(uvwasi->argv);
- free(uvwasi->env_buf);
- free(uvwasi->env);
+ uvwasi_fd_table_free(uvwasi, &uvwasi->fds);
+ uvwasi__free(uvwasi, uvwasi->argv_buf);
+ uvwasi__free(uvwasi, uvwasi->argv);
+ uvwasi__free(uvwasi, uvwasi->env_buf);
+ uvwasi__free(uvwasi, uvwasi->env);
uvwasi->argv_buf = NULL;
uvwasi->argv = NULL;
uvwasi->env_buf = NULL;
@@ -385,6 +441,7 @@ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi,
return err;
wrap->fd = new_host_fd;
+ uv_mutex_unlock(&wrap->mutex);
return UVWASI_ESUCCESS;
}
@@ -543,12 +600,15 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
+ err = UVWASI_ESUCCESS;
+
#ifdef POSIX_FADV_NORMAL
r = posix_fadvise(wrap->fd, offset, len, mapped_advice);
if (r != 0)
- return uvwasi__translate_uv_error(uv_translate_sys_error(r));
+ err = uvwasi__translate_uv_error(uv_translate_sys_error(r));
#endif /* POSIX_FADV_NORMAL */
- return UVWASI_ESUCCESS;
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -579,23 +639,32 @@ uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi,
race condition prone combination of fstat() + ftruncate(). */
#if defined(__POSIX__)
r = posix_fallocate(wrap->fd, offset, len);
- if (r != 0)
- return uvwasi__translate_uv_error(uv_translate_sys_error(r));
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(uv_translate_sys_error(r));
+ goto exit;
+ }
#else
r = uv_fs_fstat(NULL, &req, wrap->fd, NULL);
st_size = req.statbuf.st_size;
uv_fs_req_cleanup(&req);
- if (r != 0)
- return uvwasi__translate_uv_error(r);
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
+ }
if (st_size < offset + len) {
r = uv_fs_ftruncate(NULL, &req, wrap->fd, offset + len, NULL);
- if (r != 0)
- return uvwasi__translate_uv_error(r);
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
+ }
}
#endif /* __POSIX__ */
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -613,6 +682,7 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
return err;
r = uv_fs_close(NULL, &req, wrap->fd, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
@@ -640,6 +710,7 @@ uvwasi_errno_t uvwasi_fd_datasync(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
return err;
r = uv_fs_fdatasync(NULL, &req, wrap->fd, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
@@ -672,11 +743,15 @@ uvwasi_errno_t uvwasi_fd_fdstat_get(uvwasi_t* uvwasi,
buf->fs_flags = 0; /* TODO(cjihrig): Missing Windows support. */
#else
r = fcntl(wrap->fd, F_GETFL);
- if (r < 0)
- return uvwasi__translate_uv_error(uv_translate_sys_error(errno));
+ if (r < 0) {
+ err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
+ }
buf->fs_flags = r;
#endif /* _WIN32 */
+ uv_mutex_unlock(&wrap->mutex);
return UVWASI_ESUCCESS;
}
@@ -731,9 +806,12 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi,
r = fcntl(wrap->fd, F_SETFL, mapped_flags);
if (r < 0)
- return uvwasi__translate_uv_error(uv_translate_sys_error(errno));
+ err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
+ else
+ err = UVWASI_ESUCCESS;
- return UVWASI_ESUCCESS;
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
#endif /* _WIN32 */
}
@@ -754,16 +832,23 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_rights(uvwasi_t* uvwasi,
return err;
/* Check for attempts to add new permissions. */
- if ((fs_rights_base | wrap->rights_base) > wrap->rights_base)
- return UVWASI_ENOTCAPABLE;
+ if ((fs_rights_base | wrap->rights_base) > wrap->rights_base) {
+ err = UVWASI_ENOTCAPABLE;
+ goto exit;
+ }
+
if ((fs_rights_inheriting | wrap->rights_inheriting) >
wrap->rights_inheriting) {
- return UVWASI_ENOTCAPABLE;
+ err = UVWASI_ENOTCAPABLE;
+ goto exit;
}
wrap->rights_base = fs_rights_base;
wrap->rights_inheriting = fs_rights_inheriting;
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -788,14 +873,16 @@ uvwasi_errno_t uvwasi_fd_filestat_get(uvwasi_t* uvwasi,
r = uv_fs_fstat(NULL, &req, wrap->fd, NULL);
if (r != 0) {
- uv_fs_req_cleanup(&req);
- return uvwasi__translate_uv_error(r);
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
}
uvwasi__stat_to_filestat(&req.statbuf, buf);
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
-
- return UVWASI_ESUCCESS;
+ return err;
}
@@ -820,6 +907,7 @@ uvwasi_errno_t uvwasi_fd_filestat_set_size(uvwasi_t* uvwasi,
return err;
r = uv_fs_ftruncate(NULL, &req, wrap->fd, st_size, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
@@ -858,6 +946,7 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi,
/* TODO(cjihrig): st_atim and st_mtim should not be unconditionally passed. */
r = uv_fs_futime(NULL, &req, wrap->fd, st_atim, st_mtim, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
@@ -891,14 +980,17 @@ uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__setup_iovs(&bufs, iovs, iovs_len);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__setup_iovs(uvwasi, &bufs, iovs, iovs_len);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_read(NULL, &req, wrap->fd, bufs, iovs_len, offset, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uvread = req.result;
uv_fs_req_cleanup(&req);
- free(bufs);
+ uvwasi__free(uvwasi, bufs);
if (r < 0)
return uvwasi__translate_uv_error(r);
@@ -920,12 +1012,17 @@ uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi,
err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0);
if (err != UVWASI_ESUCCESS)
return err;
- if (wrap->preopen != 1)
- return UVWASI_EINVAL;
+ if (wrap->preopen != 1) {
+ err = UVWASI_EINVAL;
+ goto exit;
+ }
buf->pr_type = UVWASI_PREOPENTYPE_DIR;
buf->u.dir.pr_name_len = strlen(wrap->path) + 1;
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -943,15 +1040,22 @@ uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi,
err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0);
if (err != UVWASI_ESUCCESS)
return err;
- if (wrap->preopen != 1)
- return UVWASI_EBADF;
+ if (wrap->preopen != 1) {
+ err = UVWASI_EBADF;
+ goto exit;
+ }
size = strlen(wrap->path) + 1;
- if (size > path_len)
- return UVWASI_ENOBUFS;
+ if (size > path_len) {
+ err = UVWASI_ENOBUFS;
+ goto exit;
+ }
memcpy(path, wrap->path, size);
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -979,14 +1083,17 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__setup_ciovs(&bufs, iovs, iovs_len);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__setup_ciovs(uvwasi, &bufs, iovs, iovs_len);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_write(NULL, &req, wrap->fd, bufs, iovs_len, offset, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uvwritten = req.result;
uv_fs_req_cleanup(&req);
- free(bufs);
+ uvwasi__free(uvwasi, bufs);
if (r < 0)
return uvwasi__translate_uv_error(r);
@@ -1015,14 +1122,17 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__setup_iovs(&bufs, iovs, iovs_len);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__setup_iovs(uvwasi, &bufs, iovs, iovs_len);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_read(NULL, &req, wrap->fd, bufs, iovs_len, -1, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uvread = req.result;
uv_fs_req_cleanup(&req);
- free(bufs);
+ uvwasi__free(uvwasi, bufs);
if (r < 0)
return uvwasi__translate_uv_error(r);
@@ -1066,8 +1176,10 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
/* Open the directory. */
r = uv_fs_opendir(NULL, &req, wrap->real_path, NULL);
- if (r != 0)
+ if (r != 0) {
+ uv_mutex_unlock(&wrap->mutex);
return uvwasi__translate_uv_error(r);
+ }
/* Setup for reading the directory. */
dir = req.ptr;
@@ -1161,6 +1273,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
exit:
/* Close the directory. */
r = uv_fs_closedir(NULL, &req, dir, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
return uvwasi__translate_uv_error(r);
@@ -1181,22 +1294,31 @@ uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi,
if (uvwasi == NULL)
return UVWASI_EINVAL;
+ if (from == to)
+ return UVWASI_ESUCCESS;
+
err = uvwasi_fd_table_get(&uvwasi->fds, from, &from_wrap, 0, 0);
if (err != UVWASI_ESUCCESS)
return err;
err = uvwasi_fd_table_get(&uvwasi->fds, to, &to_wrap, 0, 0);
- if (err != UVWASI_ESUCCESS)
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&from_wrap->mutex);
return err;
+ }
r = uv_fs_close(NULL, &req, to_wrap->fd, NULL);
uv_fs_req_cleanup(&req);
- if (r != 0)
+ if (r != 0) {
+ uv_mutex_unlock(&from_wrap->mutex);
+ uv_mutex_unlock(&to_wrap->mutex);
return uvwasi__translate_uv_error(r);
+ }
memcpy(to_wrap, from_wrap, sizeof(*to_wrap));
to_wrap->id = to;
-
+ uv_mutex_unlock(&from_wrap->mutex);
+ uv_mutex_unlock(&to_wrap->mutex);
return uvwasi_fd_table_remove(&uvwasi->fds, from);
}
@@ -1216,7 +1338,9 @@ uvwasi_errno_t uvwasi_fd_seek(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- return uvwasi__lseek(wrap->fd, offset, whence, newoffset);
+ err = uvwasi__lseek(wrap->fd, offset, whence, newoffset);
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -1238,6 +1362,7 @@ uvwasi_errno_t uvwasi_fd_sync(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
return err;
r = uv_fs_fsync(NULL, &req, wrap->fd, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
@@ -1260,7 +1385,9 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- return uvwasi__lseek(wrap->fd, 0, UVWASI_WHENCE_CUR, offset);
+ err = uvwasi__lseek(wrap->fd, 0, UVWASI_WHENCE_CUR, offset);
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -1283,14 +1410,17 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__setup_ciovs(&bufs, iovs, iovs_len);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__setup_ciovs(uvwasi, &bufs, iovs, iovs_len);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_write(NULL, &req, wrap->fd, bufs, iovs_len, -1, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uvwritten = req.result;
uv_fs_req_cleanup(&req);
- free(bufs);
+ uvwasi__free(uvwasi, bufs);
if (r < 0)
return uvwasi__translate_uv_error(r);
@@ -1321,17 +1451,22 @@ uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap, path, path_len, resolved_path, 0);
+ err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
r = uv_fs_mkdir(NULL, &req, resolved_path, 0777, NULL);
uv_fs_req_cleanup(&req);
- if (r != 0)
- return uvwasi__translate_uv_error(r);
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
+ }
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -1358,20 +1493,28 @@ uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap, path, path_len, resolved_path, flags);
+ err = uvwasi__resolve_path(uvwasi,
+ wrap,
+ path,
+ path_len,
+ resolved_path,
+ flags);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
r = uv_fs_stat(NULL, &req, resolved_path, NULL);
if (r != 0) {
uv_fs_req_cleanup(&req);
- return uvwasi__translate_uv_error(r);
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
}
uvwasi__stat_to_filestat(&req.statbuf, buf);
uv_fs_req_cleanup(&req);
-
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -1406,18 +1549,28 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap, path, path_len, resolved_path, flags);
+ err = uvwasi__resolve_path(uvwasi,
+ wrap,
+ path,
+ path_len,
+ resolved_path,
+ flags);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
/* TODO(cjihrig): st_atim and st_mtim should not be unconditionally passed. */
r = uv_fs_utime(NULL, &req, resolved_path, st_atim, st_mtim, NULL);
uv_fs_req_cleanup(&req);
- if (r != 0)
- return uvwasi__translate_uv_error(r);
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
+ }
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&wrap->mutex);
+ return err;
}
@@ -1440,44 +1593,68 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi,
if (uvwasi == NULL || old_path == NULL || new_path == NULL)
return UVWASI_EINVAL;
- err = uvwasi_fd_table_get(&uvwasi->fds,
- old_fd,
- &old_wrap,
- UVWASI_RIGHT_PATH_LINK_SOURCE,
- 0);
- if (err != UVWASI_ESUCCESS)
- return err;
+ if (old_fd == new_fd) {
+ err = uvwasi_fd_table_get(&uvwasi->fds,
+ old_fd,
+ &old_wrap,
+ UVWASI_RIGHT_PATH_LINK_SOURCE |
+ UVWASI_RIGHT_PATH_LINK_TARGET,
+ 0);
+ if (err != UVWASI_ESUCCESS)
+ return err;
- err = uvwasi_fd_table_get(&uvwasi->fds,
- new_fd,
- &new_wrap,
- UVWASI_RIGHT_PATH_LINK_TARGET,
- 0);
- if (err != UVWASI_ESUCCESS)
- return err;
+ new_wrap = old_wrap;
+ } else {
+ err = uvwasi_fd_table_get(&uvwasi->fds,
+ old_fd,
+ &old_wrap,
+ UVWASI_RIGHT_PATH_LINK_SOURCE,
+ 0);
+ if (err != UVWASI_ESUCCESS)
+ return err;
+
+ err = uvwasi_fd_table_get(&uvwasi->fds,
+ new_fd,
+ &new_wrap,
+ UVWASI_RIGHT_PATH_LINK_TARGET,
+ 0);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&old_wrap->mutex);
+ return err;
+ }
+ }
- err = uvwasi__resolve_path(old_wrap,
+ err = uvwasi__resolve_path(uvwasi,
+ old_wrap,
old_path,
old_path_len,
resolved_old_path,
old_flags);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
- err = uvwasi__resolve_path(new_wrap,
+ err = uvwasi__resolve_path(uvwasi,
+ new_wrap,
new_path,
new_path_len,
resolved_new_path,
0);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
r = uv_fs_link(NULL, &req, resolved_old_path, resolved_new_path, NULL);
uv_fs_req_cleanup(&req);
- if (r != 0)
- return uvwasi__translate_uv_error(r);
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
+ }
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&old_wrap->mutex);
+ if (old_fd != new_fd)
+ uv_mutex_unlock(&new_wrap->mutex);
+ return err;
}
@@ -1560,39 +1737,49 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(dirfd_wrap,
+ err = uvwasi__resolve_path(uvwasi,
+ dirfd_wrap,
path,
path_len,
resolved_path,
dirflags);
- if (err != UVWASI_ESUCCESS)
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&dirfd_wrap->mutex);
return err;
+ }
r = uv_fs_open(NULL, &req, resolved_path, flags, 0666, NULL);
uv_fs_req_cleanup(&req);
- if (r < 0)
+ if (r < 0) {
+ uv_mutex_unlock(&dirfd_wrap->mutex);
return uvwasi__translate_uv_error(r);
+ }
- err = uvwasi_fd_table_insert_fd(&uvwasi->fds,
+ err = uvwasi_fd_table_insert_fd(uvwasi,
+ &uvwasi->fds,
r,
flags,
resolved_path,
fs_rights_base,
fs_rights_inheriting,
&wrap);
- if (err != UVWASI_ESUCCESS)
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&dirfd_wrap->mutex);
goto close_file_and_error_exit;
+ }
/* Not all platforms support UV_FS_O_DIRECTORY, so enforce it here as well. */
if ((o_flags & UVWASI_O_DIRECTORY) != 0 &&
wrap.type != UVWASI_FILETYPE_DIRECTORY) {
+ uv_mutex_unlock(&dirfd_wrap->mutex);
uvwasi_fd_table_remove(&uvwasi->fds, wrap.id);
err = UVWASI_ENOTDIR;
goto close_file_and_error_exit;
}
*fd = wrap.id;
+ uv_mutex_unlock(&dirfd_wrap->mutex);
return UVWASI_ESUCCESS;
close_file_and_error_exit:
@@ -1627,11 +1814,14 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap, path, path_len, resolved_path, 0);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_readlink(NULL, &req, resolved_path, NULL);
+ uv_mutex_unlock(&wrap->mutex);
if (r != 0) {
uv_fs_req_cleanup(&req);
return uvwasi__translate_uv_error(r);
@@ -1672,11 +1862,14 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap, path, path_len, resolved_path, 0);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_rmdir(NULL, &req, resolved_path, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
@@ -1704,44 +1897,68 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi,
if (uvwasi == NULL || old_path == NULL || new_path == NULL)
return UVWASI_EINVAL;
- err = uvwasi_fd_table_get(&uvwasi->fds,
- old_fd,
- &old_wrap,
- UVWASI_RIGHT_PATH_RENAME_SOURCE,
- 0);
- if (err != UVWASI_ESUCCESS)
- return err;
-
- err = uvwasi_fd_table_get(&uvwasi->fds,
- new_fd,
- &new_wrap,
- UVWASI_RIGHT_PATH_RENAME_TARGET,
- 0);
- if (err != UVWASI_ESUCCESS)
- return err;
+ if (old_fd == new_fd) {
+ err = uvwasi_fd_table_get(&uvwasi->fds,
+ old_fd,
+ &old_wrap,
+ UVWASI_RIGHT_PATH_RENAME_SOURCE |
+ UVWASI_RIGHT_PATH_RENAME_TARGET,
+ 0);
+ if (err != UVWASI_ESUCCESS)
+ return err;
+ new_wrap = old_wrap;
+ } else {
+ err = uvwasi_fd_table_get(&uvwasi->fds,
+ old_fd,
+ &old_wrap,
+ UVWASI_RIGHT_PATH_RENAME_SOURCE,
+ 0);
+ if (err != UVWASI_ESUCCESS)
+ return err;
+
+ err = uvwasi_fd_table_get(&uvwasi->fds,
+ new_fd,
+ &new_wrap,
+ UVWASI_RIGHT_PATH_RENAME_TARGET,
+ 0);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&old_wrap->mutex);
+ return err;
+ }
+ }
- err = uvwasi__resolve_path(old_wrap,
+ err = uvwasi__resolve_path(uvwasi,
+ old_wrap,
old_path,
old_path_len,
resolved_old_path,
0);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
- err = uvwasi__resolve_path(new_wrap,
+ err = uvwasi__resolve_path(uvwasi,
+ new_wrap,
new_path,
new_path_len,
resolved_new_path,
0);
if (err != UVWASI_ESUCCESS)
- return err;
+ goto exit;
r = uv_fs_rename(NULL, &req, resolved_old_path, resolved_new_path, NULL);
uv_fs_req_cleanup(&req);
- if (r != 0)
- return uvwasi__translate_uv_error(r);
+ if (r != 0) {
+ err = uvwasi__translate_uv_error(r);
+ goto exit;
+ }
- return UVWASI_ESUCCESS;
+ err = UVWASI_ESUCCESS;
+exit:
+ uv_mutex_unlock(&old_wrap->mutex);
+ if (old_fd != new_fd)
+ uv_mutex_unlock(&new_wrap->mutex);
+
+ return err;
}
@@ -1768,16 +1985,20 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap,
+ err = uvwasi__resolve_path(uvwasi,
+ wrap,
new_path,
new_path_len,
resolved_new_path,
0);
- if (err != UVWASI_ESUCCESS)
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
/* Windows support may require setting the flags option. */
r = uv_fs_symlink(NULL, &req, old_path, resolved_new_path, 0, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)
return uvwasi__translate_uv_error(r);
@@ -1807,11 +2028,14 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi,
if (err != UVWASI_ESUCCESS)
return err;
- err = uvwasi__resolve_path(wrap, path, path_len, resolved_path, 0);
- if (err != UVWASI_ESUCCESS)
+ err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0);
+ if (err != UVWASI_ESUCCESS) {
+ uv_mutex_unlock(&wrap->mutex);
return err;
+ }
r = uv_fs_unlink(NULL, &req, resolved_path, NULL);
+ uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);
if (r != 0)