From 0a7c874e9c3cb5da99c88ab46e33a648f0b909d2 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 1 Dec 2019 01:28:52 +0100 Subject: deps: update uvwasi PR-URL: https://github.com/nodejs/node/pull/30745 Refs: https://github.com/nodejs/quic/blob/34ee0bc96f804c73cb22b2945a1a78f780938492/src/node_mem.h Refs: https://github.com/nodejs/quic/pull/126 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Rich Trott --- deps/uvwasi/src/uvwasi.c | 508 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 366 insertions(+), 142 deletions(-) (limited to 'deps/uvwasi/src/uvwasi.c') 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) -- cgit v1.2.3