From fa5e9d72b0393b74c242e6831dc2f8cade8a2398 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:19:39 +0100 Subject: [PATCH] Abstract POSIX filesystem functions (#2585) To allow non-POSIX platforms such as Windows to support WASI libc filesystem functionality, create a set of wrapper functions which provide a platform-agnostic interface to interact with the host filesystem. For now, the Windows implementation is stubbed but this will be implemented properly in a future PR. There are no functional changes in this change, just a reorganization of code to move any direct POSIX references out of posix.c in the libc implementation into posix_file.c under the shared POSIX sources. See https://github.com/bytecodealliance/wasm-micro-runtime/issues/2495 for a more detailed overview of the plan to port the WASI libc filesystem to Windows. --- core/iwasm/common/wasm_runtime_common.c | 83 +- core/iwasm/common/wasm_runtime_common.h | 8 +- core/iwasm/include/wasm_export.h | 25 +- core/iwasm/interpreter/wasm.h | 2 +- .../libraries/libc-wasi/libc_wasi_wrapper.c | 1 + .../libraries/libc-wasi/libc_wasi_wrapper.h | 1 - .../include/wasmtime_ssp.h | 1759 +++++------------ .../src/blocking_op.c | 160 +- .../src/blocking_op.h | 50 +- .../sandboxed-system-primitives/src/posix.c | 1452 ++++---------- .../sandboxed-system-primitives/src/posix.h | 3 +- .../src/ssp_config.h | 64 - .../shared/platform/alios/platform_internal.h | 4 + .../platform/android/platform_internal.h | 4 + .../platform/common/libc-util/libc_errno.c | 256 +++ .../platform/common/libc-util/libc_errno.h | 15 + .../libc-util/platform_common_libc_util.cmake | 8 + .../common/posix/platform_api_posix.cmake | 7 + .../shared/platform/common/posix/posix_file.c | 1013 ++++++++++ .../platform/cosmopolitan/platform_internal.h | 4 + .../platform/darwin/platform_internal.h | 4 + .../platform/esp-idf/platform_internal.h | 4 + .../platform/freebsd/platform_internal.h | 4 + .../platform/include/platform_api_extension.h | 1 + core/shared/platform/include/platform_wasi.h | 1100 +++++++++++ .../platform/linux-sgx/platform_internal.h | 4 + core/shared/platform/linux-sgx/sgx_ipfs.h | 1 - .../platform/linux-sgx/shared_platform.cmake | 12 +- .../shared/platform/linux/platform_internal.h | 4 + .../shared/platform/nuttx/platform_internal.h | 4 + .../platform/nuttx/shared_platform.cmake | 6 + core/shared/platform/riot/platform_internal.h | 4 + .../platform/rt-thread/platform_internal.h | 4 + .../platform/vxworks/platform_internal.h | 4 + .../platform/windows/platform_internal.h | 8 + .../platform/windows/shared_platform.cmake | 7 + core/shared/platform/windows/win_file.c | 267 +++ .../platform/zephyr/platform_internal.h | 4 + product-mini/platforms/nuttx/wamr.mk | 4 + wamr-compiler/CMakeLists.txt | 6 + 40 files changed, 3805 insertions(+), 2566 deletions(-) create mode 100644 core/shared/platform/common/libc-util/libc_errno.c create mode 100644 core/shared/platform/common/libc-util/libc_errno.h create mode 100644 core/shared/platform/common/libc-util/platform_common_libc_util.cmake create mode 100644 core/shared/platform/common/posix/posix_file.c create mode 100644 core/shared/platform/include/platform_wasi.h create mode 100644 core/shared/platform/windows/win_file.c diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index b70f8233e..59ed016ac 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2778,7 +2778,7 @@ wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, const char *env_list[], uint32 env_count, char *argv[], int argc, - int stdinfd, int stdoutfd, int stderrfd) + int64 stdinfd, int64 stdoutfd, int64 stderrfd) { WASIArguments *wasi_args = get_wasi_args_from_module(module); @@ -2792,9 +2792,9 @@ wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, const char *dir_list[], wasi_args->env_count = env_count; wasi_args->argv = argv; wasi_args->argc = (uint32)argc; - wasi_args->stdio[0] = stdinfd; - wasi_args->stdio[1] = stdoutfd; - wasi_args->stdio[2] = stderrfd; + wasi_args->stdio[0] = (os_raw_file_handle)stdinfd; + wasi_args->stdio[1] = (os_raw_file_handle)stdoutfd; + wasi_args->stdio[2] = (os_raw_file_handle)stderrfd; #if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_INTERP != 0 @@ -2889,8 +2889,9 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *env[], uint32 env_count, const char *addr_pool[], uint32 addr_pool_size, const char *ns_lookup_pool[], uint32 ns_lookup_pool_size, - char *argv[], uint32 argc, int stdinfd, int stdoutfd, - int stderrfd, char *error_buf, uint32 error_buf_size) + char *argv[], uint32 argc, os_raw_file_handle stdinfd, + os_raw_file_handle stdoutfd, os_raw_file_handle stderrfd, + char *error_buf, uint32 error_buf_size) { WASIContext *wasi_ctx; char *argv_buf = NULL; @@ -2908,7 +2909,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, bool argv_environ_inited = false; bool addr_pool_inited = false; __wasi_fd_t wasm_fd = 3; - int32 raw_fd; + os_file_handle file_handle; char *path, resolved_path[PATH_MAX]; uint32 i; @@ -2978,15 +2979,19 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, } addr_pool_inited = true; - /* Prepopulate curfds with stdin, stdout, and stderr file descriptors. - * - * If -1 is given, use STDIN_FILENO (0), STDOUT_FILENO (1), - * STDERR_FILENO (2) respectively. - */ - if (!fd_table_insert_existing(curfds, 0, (stdinfd != -1) ? stdinfd : 0) - || !fd_table_insert_existing(curfds, 1, (stdoutfd != -1) ? stdoutfd : 1) - || !fd_table_insert_existing(curfds, 2, - (stderrfd != -1) ? stderrfd : 2)) { + os_file_handle stdin_file_handle = os_convert_stdin_handle(stdinfd); + os_file_handle stdout_file_handle = os_convert_stdout_handle(stdoutfd); + os_file_handle stderr_file_handle = os_convert_stderr_handle(stderrfd); + + if (!os_is_handle_valid(&stdin_file_handle) + || !os_is_handle_valid(&stdout_file_handle) + || !os_is_handle_valid(&stderr_file_handle)) + goto fail; + + /* Prepopulate curfds with stdin, stdout, and stderr file descriptors. */ + if (!fd_table_insert_existing(curfds, 0, stdin_file_handle, true) + || !fd_table_insert_existing(curfds, 1, stdout_file_handle, true) + || !fd_table_insert_existing(curfds, 2, stderr_file_handle, true)) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: init fd table failed"); goto fail; @@ -2994,11 +2999,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, wasm_fd = 3; for (i = 0; i < dir_count; i++, wasm_fd++) { -#ifdef BH_PLATFORM_WINDOWS - path = _fullpath(resolved_path, dir_list[i], PATH_MAX); -#else - path = realpath(dir_list[i], resolved_path); -#endif + path = os_realpath(dir_list[i], resolved_path); if (!path) { if (error_buf) snprintf(error_buf, error_buf_size, @@ -3006,25 +3007,34 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, dir_list[i], errno); goto fail; } -#ifdef BH_PLATFORM_WINDOWS - if (error_buf) - snprintf( - error_buf, error_buf_size, - "pre-opening directory is not supported on windows platforms"); - goto fail; -#else - raw_fd = open(path, O_RDONLY | O_DIRECTORY, 0); -#endif - if (raw_fd == -1) { + + __wasi_errno_t error = os_open_preopendir(path, &file_handle); + + if (error != __WASI_ESUCCESS) { if (error_buf) snprintf(error_buf, error_buf_size, "error while pre-opening directory %s: %d\n", - dir_list[i], errno); + dir_list[i], error); goto fail; } - fd_table_insert_existing(curfds, wasm_fd, raw_fd); - fd_prestats_insert(prestats, dir_list[i], wasm_fd); + if (!fd_table_insert_existing(curfds, wasm_fd, file_handle, false)) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error inserting preopen fd %u (directory %s) into fd " + "table", + (unsigned int)wasm_fd, dir_list[i]); + goto fail; + } + + if (!fd_prestats_insert(prestats, dir_list[i], wasm_fd)) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error inserting preopen fd %u (directory %s) into " + "prestats table", + (unsigned int)wasm_fd, dir_list[i]); + goto fail; + } } /* addr_pool(textual) -> apool */ @@ -3152,8 +3162,9 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *env[], uint32 env_count, const char *addr_pool[], uint32 addr_pool_size, const char *ns_lookup_pool[], uint32 ns_lookup_pool_size, - char *argv[], uint32 argc, int stdinfd, int stdoutfd, - int stderrfd, char *error_buf, uint32 error_buf_size) + char *argv[], uint32 argc, os_raw_file_handle stdinfd, + os_raw_file_handle stdoutfd, os_raw_file_handle stderrfd, + char *error_buf, uint32 error_buf_size) { WASIContext *ctx; uvwasi_t *uvwasi; diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index a834d67f2..4cfef6fa9 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -14,7 +14,6 @@ #include "../interpreter/wasm.h" #if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_UVWASI == 0 -#include "wasmtime_ssp.h" #include "posix.h" #else #include "uvwasi.h" @@ -853,7 +852,7 @@ wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, const char *env_list[], uint32 env_count, char *argv[], int argc, - int stdinfd, int stdoutfd, int stderrfd); + int64 stdinfd, int64 stdoutfd, int64 stderrfd); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void @@ -881,8 +880,9 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *env[], uint32 env_count, const char *addr_pool[], uint32 addr_pool_size, const char *ns_lookup_pool[], uint32 ns_lookup_pool_size, - char *argv[], uint32 argc, int stdinfd, int stdoutfd, - int stderrfd, char *error_buf, uint32 error_buf_size); + char *argv[], uint32 argc, os_raw_file_handle stdinfd, + os_raw_file_handle stdoutfd, os_raw_file_handle stderrfd, + char *error_buf, uint32 error_buf_size); void wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst); diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2a30ddc93..c554e2005 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -431,26 +431,31 @@ wasm_runtime_get_module_hash(wasm_module_t module); * @param env_count The number of elements in env. * @param argv The list of command line arguments. * @param argc The number of elements in argv. - * @param stdinfd The host file descriptor to back WASI STDIN_FILENO. - * If -1 is specified, STDIN_FILENO is used. - * @param stdoutfd The host file descriptor to back WASI STDOUT_FILENO. - * If -1 is specified, STDOUT_FILENO is used. - * @param stderrfd The host file descriptor to back WASI STDERR_FILENO. - * If -1 is specified, STDERR_FILENO is used. + * @param stdin_handle The raw host handle to back WASI STDIN_FILENO. + * If an invalid handle is specified (e.g. -1 on POSIX, + * INVALID_HANDLE_VALUE on Windows), the platform default + * for STDIN is used. + * @param stdoutfd The raw host handle to back WASI STDOUT_FILENO. + * If an invalid handle is specified (e.g. -1 on POSIX, + * INVALID_HANDLE_VALUE on Windows), the platform default + * for STDOUT is used. + * @param stderrfd The raw host handle to back WASI STDERR_FILENO. + * If an invalid handle is specified (e.g. -1 on POSIX, + * INVALID_HANDLE_VALUE on Windows), the platform default + * for STDERR is used. */ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_wasi_args_ex(wasm_module_t module, const char *dir_list[], uint32_t dir_count, const char *map_dir_list[], uint32_t map_dir_count, const char *env[], uint32_t env_count, - char *argv[], int argc, - int stdinfd, int stdoutfd, int stderrfd); + char *argv[], int argc, int64_t stdinfd, + int64_t stdoutfd, int64_t stderrfd); /** * Set WASI parameters. * - * Same as wasm_runtime_set_wasi_args_ex with stdinfd = -1, stdoutfd = -1, - * stderrfd = -1. + * Same as wasm_runtime_set_wasi_args_ex but with default stdio handles */ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_wasi_args(wasm_module_t module, diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index c7d9f1de9..89b0bc741 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -350,7 +350,7 @@ typedef struct WASIArguments { uint32 ns_lookup_count; char **argv; uint32 argc; - int stdio[3]; + os_raw_file_handle stdio[3]; } WASIArguments; #endif diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 292bd8379..b0666445d 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -7,6 +7,7 @@ #include "bh_platform.h" #include "wasm_export.h" #include "wasm_runtime_common.h" +#include "wasmtime_ssp.h" #if WASM_ENABLE_THREAD_MGR != 0 #include "../../../thread-mgr/thread_manager.h" diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h index be509576b..2d149bc09 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h @@ -6,7 +6,6 @@ #ifndef _LIBC_WASI_WRAPPER_H #define _LIBC_WASI_WRAPPER_H -#include "wasmtime_ssp.h" #include "posix.h" #ifdef __cplusplus diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index 0bdb07361..af1d68e9f 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -3,10 +3,6 @@ * LLVM Exceptions. See * https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE * for license information. - * - * This file declares an interface similar to WASI, but augmented to expose - * some implementation details such as the curfds arguments that we pass - * around to avoid storing them in TLS. */ /** @@ -22,1347 +18,594 @@ #include #include +#include "bh_platform.h" #include "wasm_export.h" -/* clang-format off */ - #ifdef __cplusplus -#ifndef _Static_assert -#define _Static_assert static_assert -#endif /* _Static_assert */ - -#ifndef _Alignof -#define _Alignof alignof -#endif /* _Alignof */ - -#ifndef _Noreturn -#define _Noreturn [[ noreturn ]] -#endif /* _Noreturn */ extern "C" { #endif -_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout"); -_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout"); -_Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); -_Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout"); -_Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout"); -_Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout"); -#if 0 -_Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout"); -_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout"); -#endif - -typedef uint32_t __wasi_size_t; -_Static_assert(_Alignof(__wasi_size_t) == 4, "non-wasi data layout"); - -typedef uint8_t __wasi_advice_t; -#define __WASI_ADVICE_NORMAL (0) -#define __WASI_ADVICE_SEQUENTIAL (1) -#define __WASI_ADVICE_RANDOM (2) -#define __WASI_ADVICE_WILLNEED (3) -#define __WASI_ADVICE_DONTNEED (4) -#define __WASI_ADVICE_NOREUSE (5) - -typedef uint32_t __wasi_clockid_t; -#define __WASI_CLOCK_REALTIME (0) -#define __WASI_CLOCK_MONOTONIC (1) -#define __WASI_CLOCK_PROCESS_CPUTIME_ID (2) -#define __WASI_CLOCK_THREAD_CPUTIME_ID (3) - -typedef uint64_t __wasi_device_t; - -typedef uint64_t __wasi_dircookie_t; -#define __WASI_DIRCOOKIE_START (0) - -typedef uint32_t __wasi_dirnamlen_t; - -typedef uint16_t __wasi_errno_t; -#define __WASI_ESUCCESS (0) -#define __WASI_E2BIG (1) -#define __WASI_EACCES (2) -#define __WASI_EADDRINUSE (3) -#define __WASI_EADDRNOTAVAIL (4) -#define __WASI_EAFNOSUPPORT (5) -#define __WASI_EAGAIN (6) -#define __WASI_EALREADY (7) -#define __WASI_EBADF (8) -#define __WASI_EBADMSG (9) -#define __WASI_EBUSY (10) -#define __WASI_ECANCELED (11) -#define __WASI_ECHILD (12) -#define __WASI_ECONNABORTED (13) -#define __WASI_ECONNREFUSED (14) -#define __WASI_ECONNRESET (15) -#define __WASI_EDEADLK (16) -#define __WASI_EDESTADDRREQ (17) -#define __WASI_EDOM (18) -#define __WASI_EDQUOT (19) -#define __WASI_EEXIST (20) -#define __WASI_EFAULT (21) -#define __WASI_EFBIG (22) -#define __WASI_EHOSTUNREACH (23) -#define __WASI_EIDRM (24) -#define __WASI_EILSEQ (25) -#define __WASI_EINPROGRESS (26) -#define __WASI_EINTR (27) -#define __WASI_EINVAL (28) -#define __WASI_EIO (29) -#define __WASI_EISCONN (30) -#define __WASI_EISDIR (31) -#define __WASI_ELOOP (32) -#define __WASI_EMFILE (33) -#define __WASI_EMLINK (34) -#define __WASI_EMSGSIZE (35) -#define __WASI_EMULTIHOP (36) -#define __WASI_ENAMETOOLONG (37) -#define __WASI_ENETDOWN (38) -#define __WASI_ENETRESET (39) -#define __WASI_ENETUNREACH (40) -#define __WASI_ENFILE (41) -#define __WASI_ENOBUFS (42) -#define __WASI_ENODEV (43) -#define __WASI_ENOENT (44) -#define __WASI_ENOEXEC (45) -#define __WASI_ENOLCK (46) -#define __WASI_ENOLINK (47) -#define __WASI_ENOMEM (48) -#define __WASI_ENOMSG (49) -#define __WASI_ENOPROTOOPT (50) -#define __WASI_ENOSPC (51) -#define __WASI_ENOSYS (52) -#define __WASI_ENOTCONN (53) -#define __WASI_ENOTDIR (54) -#define __WASI_ENOTEMPTY (55) -#define __WASI_ENOTRECOVERABLE (56) -#define __WASI_ENOTSOCK (57) -#define __WASI_ENOTSUP (58) -#define __WASI_ENOTTY (59) -#define __WASI_ENXIO (60) -#define __WASI_EOVERFLOW (61) -#define __WASI_EOWNERDEAD (62) -#define __WASI_EPERM (63) -#define __WASI_EPIPE (64) -#define __WASI_EPROTO (65) -#define __WASI_EPROTONOSUPPORT (66) -#define __WASI_EPROTOTYPE (67) -#define __WASI_ERANGE (68) -#define __WASI_EROFS (69) -#define __WASI_ESPIPE (70) -#define __WASI_ESRCH (71) -#define __WASI_ESTALE (72) -#define __WASI_ETIMEDOUT (73) -#define __WASI_ETXTBSY (74) -#define __WASI_EXDEV (75) -#define __WASI_ENOTCAPABLE (76) - -#if defined(_MSC_VER) -#define ALIGNED_(x) __declspec(align(x)) -#define WARN_UNUSED _Check_return_ -#elif defined(__GNUC__) -#define ALIGNED_(x) __attribute__ ((aligned(x))) -#define WARN_UNUSED __attribute__((__warn_unused_result__)) -#endif - -#define ALIGNED_TYPE(t,x) typedef t ALIGNED_(x) - -typedef uint16_t __wasi_eventrwflags_t; -#define __WASI_EVENT_FD_READWRITE_HANGUP (0x0001) - -typedef uint8_t __wasi_eventtype_t; -#define __WASI_EVENTTYPE_CLOCK (0) -#define __WASI_EVENTTYPE_FD_READ (1) -#define __WASI_EVENTTYPE_FD_WRITE (2) - -typedef uint32_t __wasi_exitcode_t; - -typedef uint32_t __wasi_fd_t; - -typedef uint16_t __wasi_fdflags_t; -#define __WASI_FDFLAG_APPEND (0x0001) -#define __WASI_FDFLAG_DSYNC (0x0002) -#define __WASI_FDFLAG_NONBLOCK (0x0004) -#define __WASI_FDFLAG_RSYNC (0x0008) -#define __WASI_FDFLAG_SYNC (0x0010) - -typedef int64_t __wasi_filedelta_t; - -typedef uint64_t __wasi_filesize_t; - -typedef uint8_t __wasi_filetype_t; -#define __WASI_FILETYPE_UNKNOWN (0) -#define __WASI_FILETYPE_BLOCK_DEVICE (1) -#define __WASI_FILETYPE_CHARACTER_DEVICE (2) -#define __WASI_FILETYPE_DIRECTORY (3) -#define __WASI_FILETYPE_REGULAR_FILE (4) -#define __WASI_FILETYPE_SOCKET_DGRAM (5) -#define __WASI_FILETYPE_SOCKET_STREAM (6) -#define __WASI_FILETYPE_SYMBOLIC_LINK (7) - -typedef uint16_t __wasi_fstflags_t; -#define __WASI_FILESTAT_SET_ATIM (0x0001) -#define __WASI_FILESTAT_SET_ATIM_NOW (0x0002) -#define __WASI_FILESTAT_SET_MTIM (0x0004) -#define __WASI_FILESTAT_SET_MTIM_NOW (0x0008) - -typedef uint64_t __wasi_inode_t; - -ALIGNED_TYPE(uint64_t, 8) __wasi_linkcount_t; - -typedef uint32_t __wasi_lookupflags_t; -#define __WASI_LOOKUP_SYMLINK_FOLLOW (0x00000001) - -typedef uint16_t __wasi_oflags_t; -#define __WASI_O_CREAT (0x0001) -#define __WASI_O_DIRECTORY (0x0002) -#define __WASI_O_EXCL (0x0004) -#define __WASI_O_TRUNC (0x0008) - -typedef uint16_t __wasi_riflags_t; -#define __WASI_SOCK_RECV_PEEK (0x0001) -#define __WASI_SOCK_RECV_WAITALL (0x0002) - -typedef uint64_t __wasi_rights_t; - -/** - * Observe that WASI defines rights in the plural form - * TODO: refactor to use RIGHTS instead of RIGHT - */ -#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(UINT64_C(1) << 0)) -#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(UINT64_C(1) << 1)) -#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(UINT64_C(1) << 2)) -#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(UINT64_C(1) << 3)) -#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(UINT64_C(1) << 4)) -#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(UINT64_C(1) << 5)) -#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(UINT64_C(1) << 6)) -#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(UINT64_C(1) << 7)) -#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(UINT64_C(1) << 8)) -#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 9)) -#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(UINT64_C(1) << 10)) -#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 11)) -#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(UINT64_C(1) << 12)) -#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(UINT64_C(1) << 13)) -#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(UINT64_C(1) << 14)) -#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(UINT64_C(1) << 15)) -#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 16)) -#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(UINT64_C(1) << 17)) -#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 18)) -#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 19)) -#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 20)) -#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 21)) -#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 22)) -#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 23)) -#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(UINT64_C(1) << 24)) -#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 25)) -#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(UINT64_C(1) << 26)) -#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(UINT64_C(1) << 27)) -#define __WASI_RIGHT_SOCK_CONNECT ((__wasi_rights_t)(UINT64_C(1) << 28)) -#define __WASI_RIGHT_SOCK_LISTEN ((__wasi_rights_t)(UINT64_C(1) << 29)) -#define __WASI_RIGHT_SOCK_BIND ((__wasi_rights_t)(UINT64_C(1) << 30)) -#define __WASI_RIGHT_SOCK_ACCEPT ((__wasi_rights_t)(UINT64_C(1) << 31)) -#define __WASI_RIGHT_SOCK_RECV ((__wasi_rights_t)(UINT64_C(1) << 32)) -#define __WASI_RIGHT_SOCK_SEND ((__wasi_rights_t)(UINT64_C(1) << 33)) -#define __WASI_RIGHT_SOCK_ADDR_LOCAL ((__wasi_rights_t)(UINT64_C(1) << 34)) -#define __WASI_RIGHT_SOCK_ADDR_REMOTE ((__wasi_rights_t)(UINT64_C(1) << 35)) -#define __WASI_RIGHT_SOCK_RECV_FROM ((__wasi_rights_t)(UINT64_C(1) << 36)) -#define __WASI_RIGHT_SOCK_SEND_TO ((__wasi_rights_t)(UINT64_C(1) << 37)) - -typedef uint16_t __wasi_roflags_t; -#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001) - -typedef uint8_t __wasi_sdflags_t; -#define __WASI_SHUT_RD (0x01) -#define __WASI_SHUT_WR (0x02) - -typedef uint16_t __wasi_siflags_t; - -typedef uint8_t __wasi_signal_t; - -typedef uint16_t __wasi_subclockflags_t; -#define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001) - -typedef uint64_t __wasi_timestamp_t; - -typedef uint64_t __wasi_userdata_t; - -typedef uint8_t __wasi_whence_t; -#define __WASI_WHENCE_SET (0) -#define __WASI_WHENCE_CUR (1) -#define __WASI_WHENCE_END (2) - -typedef uint8_t __wasi_preopentype_t; -#define __WASI_PREOPENTYPE_DIR (0) - -struct fd_table; -struct fd_prestats; -struct argv_environ_values; -struct addr_pool; - -typedef struct ALIGNED_(8) __wasi_dirent_t { - __wasi_dircookie_t d_next; - __wasi_inode_t d_ino; - __wasi_dirnamlen_t d_namlen; - __wasi_filetype_t d_type; -} __wasi_dirent_t; -_Static_assert(offsetof(__wasi_dirent_t, d_next) == 0, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_dirent_t, d_ino) == 8, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_dirent_t, d_namlen) == 16, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_dirent_t, d_type) == 20, "non-wasi data layout"); -_Static_assert(sizeof(__wasi_dirent_t) == 24, "non-wasi data layout"); -_Static_assert(_Alignof(__wasi_dirent_t) == 8, "non-wasi data layout"); - -typedef struct ALIGNED_(8) __wasi_event_t { - __wasi_userdata_t userdata; - __wasi_errno_t error; - __wasi_eventtype_t type; - uint8_t __paddings[5]; - union __wasi_event_u { - struct __wasi_event_u_fd_readwrite_t { - __wasi_filesize_t nbytes; - __wasi_eventrwflags_t flags; - uint8_t __paddings[6]; - } fd_readwrite; - } u; -} __wasi_event_t; -_Static_assert(offsetof(__wasi_event_t, userdata) == 0, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_event_t, error) == 8, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_event_t, type) == 10, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_event_t, u.fd_readwrite.nbytes) == 16, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_event_t, u.fd_readwrite.flags) == 24, "non-wasi data layout"); -_Static_assert(sizeof(__wasi_event_t) == 32, "non-wasi data layout"); -_Static_assert(_Alignof(__wasi_event_t) == 8, "non-wasi data layout"); - -typedef struct __wasi_prestat_t { - __wasi_preopentype_t pr_type; - union __wasi_prestat_u { - struct __wasi_prestat_u_dir_t { - size_t pr_name_len; - } dir; - } u; -} __wasi_prestat_t; -_Static_assert(offsetof(__wasi_prestat_t, pr_type) == 0, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 4, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 8, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - sizeof(__wasi_prestat_t) == 8, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - sizeof(__wasi_prestat_t) == 16, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - _Alignof(__wasi_prestat_t) == 4, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - _Alignof(__wasi_prestat_t) == 8, "non-wasi data layout"); - -typedef struct ALIGNED_(8) __wasi_fdstat_t { - __wasi_filetype_t fs_filetype; - __wasi_fdflags_t fs_flags; - uint8_t __paddings[4]; - __wasi_rights_t fs_rights_base; - __wasi_rights_t fs_rights_inheriting; -} __wasi_fdstat_t; -_Static_assert( - offsetof(__wasi_fdstat_t, fs_filetype) == 0, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_fdstat_t, fs_flags) == 2, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16, - "non-wasi data layout"); -_Static_assert(sizeof(__wasi_fdstat_t) == 24, "non-wasi data layout"); -_Static_assert(_Alignof(__wasi_fdstat_t) == 8, "non-wasi data layout"); - -typedef struct ALIGNED_(8) __wasi_filestat_t { - __wasi_device_t st_dev; - __wasi_inode_t st_ino; - __wasi_filetype_t st_filetype; - __wasi_linkcount_t st_nlink; - __wasi_filesize_t st_size; - __wasi_timestamp_t st_atim; - __wasi_timestamp_t st_mtim; - __wasi_timestamp_t st_ctim; -} __wasi_filestat_t; -_Static_assert(offsetof(__wasi_filestat_t, st_dev) == 0, "non-wasi data layout"); -_Static_assert(offsetof(__wasi_filestat_t, st_ino) == 8, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_filestat_t, st_filetype) == 16, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_filestat_t, st_nlink) == 24, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_filestat_t, st_size) == 32, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_filestat_t, st_atim) == 40, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_filestat_t, st_mtim) == 48, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_filestat_t, st_ctim) == 56, "non-wasi data layout"); -_Static_assert(sizeof(__wasi_filestat_t) == 64, "non-wasi data layout"); -_Static_assert(_Alignof(__wasi_filestat_t) == 8, "non-wasi data layout"); - -typedef struct __wasi_ciovec_t { - const void *buf; - size_t buf_len; -} __wasi_ciovec_t; -_Static_assert(offsetof(__wasi_ciovec_t, buf) == 0, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - offsetof(__wasi_ciovec_t, buf_len) == 4, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - offsetof(__wasi_ciovec_t, buf_len) == 8, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - sizeof(__wasi_ciovec_t) == 8, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - sizeof(__wasi_ciovec_t) == 16, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - _Alignof(__wasi_ciovec_t) == 4, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - _Alignof(__wasi_ciovec_t) == 8, "non-wasi data layout"); - -typedef struct __wasi_iovec_t { - void *buf; - size_t buf_len; -} __wasi_iovec_t; -_Static_assert(offsetof(__wasi_iovec_t, buf) == 0, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - offsetof(__wasi_iovec_t, buf_len) == 4, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - offsetof(__wasi_iovec_t, buf_len) == 8, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - sizeof(__wasi_iovec_t) == 8, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - sizeof(__wasi_iovec_t) == 16, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 4 || - _Alignof(__wasi_iovec_t) == 4, "non-wasi data layout"); -_Static_assert(sizeof(void *) != 8 || - _Alignof(__wasi_iovec_t) == 8, "non-wasi data layout"); - -/** - * The contents of a `subscription` when type is `eventtype::clock`. - */ -typedef struct ALIGNED_(8) __wasi_subscription_clock_t { - /** - * The clock against which to compare the timestamp. - */ - __wasi_clockid_t clock_id; - - uint8_t __paddings1[4]; - - /** - * The absolute or relative timestamp. - */ - __wasi_timestamp_t timeout; - - /** - * The amount of time that the implementation may wait additionally - * to coalesce with other events. - */ - __wasi_timestamp_t precision; - - /** - * Flags specifying whether the timeout is absolute or relative - */ - __wasi_subclockflags_t flags; - - uint8_t __paddings2[4]; - -} __wasi_subscription_clock_t; - -_Static_assert(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size"); -_Static_assert(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align"); -_Static_assert(offsetof(__wasi_subscription_clock_t, clock_id) == 0, "witx calculated offset"); -_Static_assert(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset"); -_Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset"); -_Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset"); - -/** - * The contents of a `subscription` when type is type is - * `eventtype::fd_read` or `eventtype::fd_write`. - */ -typedef struct __wasi_subscription_fd_readwrite_t { - /** - * The file descriptor on which to wait for it to become ready for reading or writing. - */ - __wasi_fd_t fd; - -} __wasi_subscription_fd_readwrite_t; - -_Static_assert(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size"); -_Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align"); -_Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, fd) == 0, "witx calculated offset"); - -/** - * The contents of a `subscription`. - */ -typedef union __wasi_subscription_u_u_t { - __wasi_subscription_clock_t clock; - __wasi_subscription_fd_readwrite_t fd_readwrite; -} __wasi_subscription_u_u_t ; - -typedef struct ALIGNED_(8) __wasi_subscription_u_t { - __wasi_eventtype_t type; - __wasi_subscription_u_u_t u; -} __wasi_subscription_u_t; - -_Static_assert(sizeof(__wasi_subscription_u_t) == 40, "witx calculated size"); -_Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align"); -_Static_assert(offsetof(__wasi_subscription_u_t, u) == 8, "witx calculated union offset"); -_Static_assert(sizeof(__wasi_subscription_u_u_t) == 32, "witx calculated union size"); -_Static_assert(_Alignof(__wasi_subscription_u_u_t) == 8, "witx calculated union align"); - -/** - * Subscription to an event. - */ -typedef struct __wasi_subscription_t { - /** - * User-provided value that is attached to the subscription in the - * implementation and returned through `event::userdata`. - */ - __wasi_userdata_t userdata; - - /** - * The type of the event to which to subscribe, and its contents - */ - __wasi_subscription_u_t u; - -} __wasi_subscription_t; - -_Static_assert(sizeof(__wasi_subscription_t) == 48, "witx calculated size"); -_Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align"); -_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset"); -_Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset"); - -/* keep syncing with wasi_socket_ext.h */ -typedef enum { - /* Used only for sock_addr_resolve hints */ - SOCKET_ANY = -1, - SOCKET_DGRAM = 0, - SOCKET_STREAM, -} __wasi_sock_type_t; - -typedef uint16_t __wasi_ip_port_t; - -typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t; - -/* n0.n1.n2.n3 */ -typedef struct __wasi_addr_ip4_t { - uint8_t n0; - uint8_t n1; - uint8_t n2; - uint8_t n3; -} __wasi_addr_ip4_t; - -typedef struct __wasi_addr_ip4_port_t { - __wasi_addr_ip4_t addr; - __wasi_ip_port_t port; -} __wasi_addr_ip4_port_t; - -typedef struct __wasi_addr_ip6_t { - uint16_t n0; - uint16_t n1; - uint16_t n2; - uint16_t n3; - uint16_t h0; - uint16_t h1; - uint16_t h2; - uint16_t h3; -} __wasi_addr_ip6_t; - -typedef struct __wasi_addr_ip6_port_t { - __wasi_addr_ip6_t addr; - __wasi_ip_port_t port; -} __wasi_addr_ip6_port_t; - -typedef struct __wasi_addr_ip_t { - __wasi_addr_type_t kind; - union { - __wasi_addr_ip4_t ip4; - __wasi_addr_ip6_t ip6; - } addr; -} __wasi_addr_ip_t; - -typedef struct __wasi_addr_t { - __wasi_addr_type_t kind; - union { - __wasi_addr_ip4_port_t ip4; - __wasi_addr_ip6_port_t ip6; - } addr; -} __wasi_addr_t; - -typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; - -typedef struct __wasi_addr_info_t { - __wasi_addr_t addr; - __wasi_sock_type_t type; -} __wasi_addr_info_t; - -typedef struct __wasi_addr_info_hints_t { - __wasi_sock_type_t type; - __wasi_address_family_t family; - // this is to workaround lack of optional parameters - uint8_t hints_enabled; -} __wasi_addr_info_hints_t; - #if defined(WASMTIME_SSP_WASI_API) -#define WASMTIME_SSP_SYSCALL_NAME(name) \ - asm("__wasi_" #name) +#define WASMTIME_SSP_SYSCALL_NAME(name) asm("__wasi_" #name) #else #define WASMTIME_SSP_SYSCALL_NAME(name) #endif -__wasi_errno_t wasmtime_ssp_args_get( - struct argv_environ_values *arg_environ, - char **argv, - char *argv_buf -) WASMTIME_SSP_SYSCALL_NAME(args_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_args_sizes_get( - struct argv_environ_values *arg_environ, - size_t *argc, - size_t *argv_buf_size -) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_clock_res_get( - __wasi_clockid_t clock_id, - __wasi_timestamp_t *resolution -) WASMTIME_SSP_SYSCALL_NAME(clock_res_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_clock_time_get( - __wasi_clockid_t clock_id, - __wasi_timestamp_t precision, - __wasi_timestamp_t *time -) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_environ_get( - struct argv_environ_values *arg_environ, - char **environ, - char *environ_buf -) WASMTIME_SSP_SYSCALL_NAME(environ_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_environ_sizes_get( - struct argv_environ_values *arg_environ, - size_t *environ_count, - size_t *environ_buf_size -) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_prestat_get( - struct fd_prestats *prestats, - __wasi_fd_t fd, - __wasi_prestat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( - struct fd_prestats *prestats, - __wasi_fd_t fd, - char *path, - size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_close( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - struct fd_prestats *prestats, - __wasi_fd_t fd -) WASMTIME_SSP_SYSCALL_NAME(fd_close) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_datasync( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd -) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_pread( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const __wasi_iovec_t *iovs, - size_t iovs_len, - __wasi_filesize_t offset, - size_t *nread -) WASMTIME_SSP_SYSCALL_NAME(fd_pread) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_pwrite( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const __wasi_ciovec_t *iovs, - size_t iovs_len, - __wasi_filesize_t offset, - size_t *nwritten -) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_read( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const __wasi_iovec_t *iovs, - size_t iovs_len, - size_t *nread -) WASMTIME_SSP_SYSCALL_NAME(fd_read) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_renumber( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - struct fd_prestats *prestats, - __wasi_fd_t from, - __wasi_fd_t to -) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_seek( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_filedelta_t offset, - __wasi_whence_t whence, - __wasi_filesize_t *newoffset -) WASMTIME_SSP_SYSCALL_NAME(fd_seek) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_tell( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_filesize_t *newoffset -) WASMTIME_SSP_SYSCALL_NAME(fd_tell) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_fdstat_get( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_fdstat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_fdflags_t flags -) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting -) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_sync( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd -) WASMTIME_SSP_SYSCALL_NAME(fd_sync) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_write( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const __wasi_ciovec_t *iovs, - size_t iovs_len, - size_t *nwritten -) WASMTIME_SSP_SYSCALL_NAME(fd_write) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_advise( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_filesize_t offset, - __wasi_filesize_t len, - __wasi_advice_t advice -) WASMTIME_SSP_SYSCALL_NAME(fd_advise) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_allocate( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_filesize_t offset, - __wasi_filesize_t len -) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_create_directory( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const char *path, - size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_link( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - struct fd_prestats *prestats, - __wasi_fd_t old_fd, - __wasi_lookupflags_t old_flags, - const char *old_path, - size_t old_path_len, - __wasi_fd_t new_fd, - const char *new_path, - size_t new_path_len -) WASMTIME_SSP_SYSCALL_NAME(path_link) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_open( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t dirfd, - __wasi_lookupflags_t dirflags, - const char *path, - size_t path_len, - __wasi_oflags_t oflags, - __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting, - __wasi_fdflags_t fs_flags, - __wasi_fd_t *fd -) WASMTIME_SSP_SYSCALL_NAME(path_open) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_readdir( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - void *buf, - size_t buf_len, - __wasi_dircookie_t cookie, - size_t *bufused -) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_readlink( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const char *path, - size_t path_len, - char *buf, - size_t buf_len, - size_t *bufused -) WASMTIME_SSP_SYSCALL_NAME(path_readlink) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_rename( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t old_fd, - const char *old_path, - size_t old_path_len, - __wasi_fd_t new_fd, - const char *new_path, - size_t new_path_len -) WASMTIME_SSP_SYSCALL_NAME(path_rename) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_filestat_get( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_filestat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_filestat_set_times( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_timestamp_t st_atim, - __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags -) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_fd_filestat_set_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_filesize_t st_size -) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_filestat_get( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_lookupflags_t flags, - const char *path, - size_t path_len, - __wasi_filestat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_filestat_set_times( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - __wasi_lookupflags_t flags, - const char *path, - size_t path_len, - __wasi_timestamp_t st_atim, - __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags -) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_symlink( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - struct fd_prestats *prestats, - const char *old_path, - size_t old_path_len, - __wasi_fd_t fd, - const char *new_path, - size_t new_path_len -) WASMTIME_SSP_SYSCALL_NAME(path_symlink) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_unlink_file( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const char *path, - size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_path_remove_directory( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, - const char *path, - size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_poll_oneoff( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - const __wasi_subscription_t *in, - __wasi_event_t *out, - size_t nsubscriptions, - size_t *nevents -) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) WARN_UNUSED; - -__wasi_errno_t wasmtime_ssp_random_get( - void *buf, - size_t buf_len -) WASMTIME_SSP_SYSCALL_NAME(random_get) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_args_get(struct argv_environ_values *arg_environ, char **argv, + char *argv_buf) + WASMTIME_SSP_SYSCALL_NAME(args_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_accept( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new -) WARN_UNUSED; +wasmtime_ssp_args_sizes_get(struct argv_environ_values *arg_environ, + size_t *argc, size_t *argv_buf_size) + WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_addr_local( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_addr_t *addr -) WARN_UNUSED; +wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, + __wasi_timestamp_t *resolution) + WASMTIME_SSP_SYSCALL_NAME(clock_res_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_addr_remote( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_addr_t *addr -) WARN_UNUSED; +wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, + __wasi_timestamp_t precision, + __wasi_timestamp_t *time) + WASMTIME_SSP_SYSCALL_NAME(clock_time_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_open( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, - __wasi_fd_t *sockfd -) WARN_UNUSED; +wasmtime_ssp_environ_get(struct argv_environ_values *arg_environ, + char **environs, char *environ_buf) + WASMTIME_SSP_SYSCALL_NAME(environ_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_bind( - wasm_exec_env_t exec_env, - struct fd_table *curfds, struct addr_pool *addr_pool, - __wasi_fd_t fd, __wasi_addr_t *addr -) WARN_UNUSED; +wasmtime_ssp_environ_sizes_get(struct argv_environ_values *arg_environ, + size_t *environ_count, size_t *environ_buf_size) + WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_addr_resolve( - wasm_exec_env_t exec_env, - struct fd_table *curfds, char **ns_lookup_list, - const char *host, const char* service, - __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info, - __wasi_size_t addr_info_size, __wasi_size_t *max_info_size -) WARN_UNUSED; +wasmtime_ssp_fd_prestat_get(struct fd_prestats *prestats, __wasi_fd_t fd, + __wasi_prestat_t *buf) + WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_connect( - wasm_exec_env_t exec_env, - struct fd_table *curfds, struct addr_pool *addr_pool, - __wasi_fd_t fd, __wasi_addr_t *addr -) WARN_UNUSED; +wasmtime_ssp_fd_prestat_dir_name(struct fd_prestats *prestats, __wasi_fd_t fd, + char *path, size_t path_len) + WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_get_recv_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_size_t *size -) WARN_UNUSED; +wasmtime_ssp_fd_close(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t fd) + WASMTIME_SSP_SYSCALL_NAME(fd_close) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_get_reuse_addr( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, uint8_t *reuse -) WARN_UNUSED; +wasmtime_ssp_fd_datasync(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd) + WASMTIME_SSP_SYSCALL_NAME(fd_datasync) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_get_reuse_port( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, uint8_t *reuse -) WARN_UNUSED; +wasmtime_ssp_fd_pread(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_iovec_t *iovs, + size_t iovs_len, __wasi_filesize_t offset, size_t *nread) + WASMTIME_SSP_SYSCALL_NAME(fd_pread) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_get_send_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_size_t *size -) WARN_UNUSED; +wasmtime_ssp_fd_pwrite(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_ciovec_t *iovs, + size_t iovs_len, __wasi_filesize_t offset, + size_t *nwritten) + WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_set_recv_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_size_t size -) WARN_UNUSED; +wasmtime_ssp_fd_read(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_iovec_t *iovs, + size_t iovs_len, size_t *nread) + WASMTIME_SSP_SYSCALL_NAME(fd_read) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_set_reuse_addr( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, uint8_t reuse -) WARN_UNUSED; +wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t from, + __wasi_fd_t to) + WASMTIME_SSP_SYSCALL_NAME(fd_renumber) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_set_reuse_port( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, uint8_t reuse -) WARN_UNUSED; +wasmtime_ssp_fd_seek(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *newoffset) + WASMTIME_SSP_SYSCALL_NAME(fd_seek) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_set_send_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_size_t size -) WARN_UNUSED; +wasmtime_ssp_fd_tell(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t *newoffset) + WASMTIME_SSP_SYSCALL_NAME(fd_tell) WARN_UNUSED; __wasi_errno_t -wasi_ssp_sock_listen( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t fd, __wasi_size_t backlog -) WARN_UNUSED; +wasmtime_ssp_fd_fdstat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_fdstat_t *buf) + WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_recv( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - void *buf, - size_t buf_len, - size_t *recv_len -) WASMTIME_SSP_SYSCALL_NAME(sock_recv) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_fdstat_set_flags(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_fdflags_t flags) + WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_recv_from( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - void *buf, - size_t buf_len, - __wasi_riflags_t ri_flags, - __wasi_addr_t *src_addr, - size_t *recv_len -) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_fdstat_set_rights(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting) + WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_send( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - const void *buf, - size_t buf_len, - size_t *sent_len -) WASMTIME_SSP_SYSCALL_NAME(sock_send) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_sync(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd) + WASMTIME_SSP_SYSCALL_NAME(fd_sync) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_send_to( - wasm_exec_env_t exec_env, - struct fd_table *curfds, struct addr_pool *addr_pool, - __wasi_fd_t sock, - const void *buf, - size_t buf_len, - __wasi_siflags_t si_flags, - const __wasi_addr_t *dest_addr, - size_t *sent_len -) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_ciovec_t *iovs, + size_t iovs_len, size_t *nwritten) + WASMTIME_SSP_SYSCALL_NAME(fd_write) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_shutdown( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock -) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_advise(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t offset, + __wasi_filesize_t len, __wasi_advice_t advice) + WASMTIME_SSP_SYSCALL_NAME(fd_advise) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint64_t timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_allocate(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t offset, + __wasi_filesize_t len) + WASMTIME_SSP_SYSCALL_NAME(fd_allocate) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint64_t *timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_create_directory(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t path_len) + WASMTIME_SSP_SYSCALL_NAME(path_create_directory) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_send_timeout( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint64_t timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_link(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t old_fd, + __wasi_lookupflags_t old_flags, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, + const char *new_path, size_t new_path_len) + WASMTIME_SSP_SYSCALL_NAME(path_link) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_send_timeout( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint64_t *timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, + const char *path, size_t path_len, + __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, + __wasi_fdflags_t fs_flags, __wasi_fd_t *fd) + WASMTIME_SSP_SYSCALL_NAME(path_open) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_send_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - size_t bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_readdir(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, void *buf, size_t buf_len, + __wasi_dircookie_t cookie, size_t *bufused) + WASMTIME_SSP_SYSCALL_NAME(fd_readdir) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_send_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - size_t *bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_readlink(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const char *path, size_t path_len, + char *buf, size_t buf_len, size_t *bufused) + WASMTIME_SSP_SYSCALL_NAME(path_readlink) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - size_t bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_rename(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t old_fd, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, + const char *new_path, size_t new_path_len) + WASMTIME_SSP_SYSCALL_NAME(path_rename) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - size_t *bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_filestat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filestat_t *buf) + WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_filestat_set_times(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) + WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_keep_alive( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_fd_filestat_set_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filesize_t st_size) + WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_keep_alive( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_filestat_get(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_lookupflags_t flags, const char *path, + size_t path_len, __wasi_filestat_t *buf) + WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_reuse_addr( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_filestat_set_times(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, size_t path_len, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) + WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_reuse_addr( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_symlink(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, const char *old_path, + size_t old_path_len, __wasi_fd_t fd, + const char *new_path, size_t new_path_len) + WASMTIME_SSP_SYSCALL_NAME(path_symlink) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_reuse_port( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_unlink_file(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const char *path, size_t path_len) + WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_reuse_port( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_path_remove_directory(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t path_len) + WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_linger( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled, - int linger_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, + const __wasi_subscription_t *in, __wasi_event_t *out, + size_t nsubscriptions, size_t *nevents) + WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_linger( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, bool *is_enabled, int *linger_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_random_get(void *buf, size_t buf_len) + WASMTIME_SSP_SYSCALL_NAME(random_get) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_broadcast( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_accept(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_fdflags_t flags, + __wasi_fd_t *fd_new) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_broadcast( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_addr_local(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_addr_t *addr) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_addr_remote(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_addr_t *addr) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_open(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t poolfd, __wasi_address_family_t af, + __wasi_sock_type_t socktype, + __wasi_fd_t *sockfd) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_bind(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t fd, + __wasi_addr_t *addr) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_addr_resolve(wasm_exec_env_t exec_env, struct fd_table *curfds, + char **ns_lookup_list, const char *host, + const char *service, __wasi_addr_info_hints_t *hints, + __wasi_addr_info_t *addr_info, + __wasi_size_t addr_info_size, + __wasi_size_t *max_info_size) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint32_t time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_connect(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t fd, + __wasi_addr_t *addr) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint32_t *time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_get_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t *size) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint32_t time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_get_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t *reuse) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint32_t *time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_get_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t *reuse) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_get_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t *size) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_set_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t size) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool ipv6, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_set_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t reuse) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool ipv6, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_set_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t reuse) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - __wasi_addr_ip_t *imr_multiaddr, - uint32_t imr_interface -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_set_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t size) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - __wasi_addr_ip_t *imr_multiaddr, - uint32_t imr_interface -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) WARN_UNUSED; +__wasi_errno_t +wasi_ssp_sock_listen(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_size_t backlog) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_ip_ttl( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint8_t ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_sock_recv(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, void *buf, size_t buf_len, + size_t *recv_len) + WASMTIME_SSP_SYSCALL_NAME(sock_recv) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_ip_ttl( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint8_t *ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_sock_recv_from(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, void *buf, size_t buf_len, + __wasi_riflags_t ri_flags, __wasi_addr_t *src_addr, + size_t *recv_len) + WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint8_t ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_sock_send(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, const void *buf, size_t buf_len, + size_t *sent_len) + WASMTIME_SSP_SYSCALL_NAME(sock_send) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - uint8_t *ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_sock_send_to(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t sock, + const void *buf, size_t buf_len, + __wasi_siflags_t si_flags, + const __wasi_addr_t *dest_addr, size_t *sent_len) + WASMTIME_SSP_SYSCALL_NAME(sock_send_to) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_set_ipv6_only( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_sock_shutdown(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock) + WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sock_get_ipv6_only( - wasm_exec_env_t exec_env, - struct fd_table *curfds, - __wasi_fd_t sock, - bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) WARN_UNUSED; +__wasi_errno_t +wasmtime_ssp_sock_set_recv_timeout(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint64_t timeout_us) + WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) WARN_UNUSED; -__wasi_errno_t wasmtime_ssp_sched_yield(void) +__wasi_errno_t +wasmtime_ssp_sock_get_recv_timeout(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint64_t *timeout_us) + WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_send_timeout(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint64_t timeout_us) + WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_send_timeout(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint64_t *timeout_us) + WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + size_t bufsiz) + WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + size_t *bufsiz) + WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + size_t bufsiz) + WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + size_t *bufsiz) + WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_keep_alive(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_keep_alive(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_reuse_addr(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_reuse_addr(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_reuse_port(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_reuse_port(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, bool is_enabled, int linger_s) + WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, bool *is_enabled, int *linger_s) + WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_broadcast(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_broadcast(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint32_t time_s) + WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint32_t *time_s) + WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint32_t time_s) + WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + uint32_t *time_s) + WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, bool ipv6, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, bool ipv6, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_add_membership(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) + WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) + WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_ttl(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, uint8_t ttl_s) + WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_ip_ttl(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, uint8_t *ttl_s) + WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, uint8_t ttl_s) + WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, uint8_t *ttl_s) + WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_set_ipv6_only(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sock_get_ipv6_only(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled) + WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) WARN_UNUSED; + +__wasi_errno_t +wasmtime_ssp_sched_yield(void) WASMTIME_SSP_SYSCALL_NAME(sched_yield) WARN_UNUSED; #ifdef __cplusplus @@ -1371,6 +614,4 @@ __wasi_errno_t wasmtime_ssp_sched_yield(void) #undef WASMTIME_SSP_SYSCALL_NAME -/* clang-format on */ - #endif /* end of WASMTIME_SSP_H */ diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c index 7040037e6..ec1481c2e 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c @@ -8,119 +8,68 @@ #include "ssp_config.h" #include "blocking_op.h" -int -blocking_op_close(wasm_exec_env_t exec_env, int fd) +__wasi_errno_t +blocking_op_close(wasm_exec_env_t exec_env, os_file_handle handle, + bool is_stdio) { if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; + return __WASI_EINTR; } - int ret = close(fd); + __wasi_errno_t error = os_close(handle, is_stdio); + wasm_runtime_end_blocking_op(exec_env); + return error; +} + +__wasi_errno_t +blocking_op_readv(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_iovec_t *iov, int iovcnt, size_t *nread) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + return __WASI_EINTR; + } + __wasi_errno_t error = os_readv(handle, iov, iovcnt, nread); + wasm_runtime_end_blocking_op(exec_env); + return error; +} + +__wasi_errno_t +blocking_op_preadv(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nread) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + return __WASI_EINTR; + } + __wasi_errno_t ret = os_preadv(handle, iov, iovcnt, offset, nread); wasm_runtime_end_blocking_op(exec_env); return ret; } -ssize_t -blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt) +__wasi_errno_t +blocking_op_writev(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_ciovec_t *iov, int iovcnt, + size_t *nwritten) { -#ifdef BH_PLATFORM_WINDOWS - errno = ENOTSUP; - return -1; -#else if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; + return __WASI_EINTR; } - ssize_t ret = readv(fd, iov, iovcnt); + __wasi_errno_t error = os_writev(handle, iov, iovcnt, nwritten); wasm_runtime_end_blocking_op(exec_env); - return ret; -#endif + return error; } -#if CONFIG_HAS_PREADV -ssize_t -blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt, off_t offset) +__wasi_errno_t +blocking_op_pwritev(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten) { if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; + return __WASI_EINTR; } - ssize_t ret = preadv(fd, iov, iovcnt, offset); + __wasi_errno_t error = os_pwritev(handle, iov, iovcnt, offset, nwritten); wasm_runtime_end_blocking_op(exec_env); - return ret; + return error; } -#else /* CONFIG_HAS_PREADV */ -ssize_t -blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb, - off_t offset) -{ -#ifdef BH_PLATFORM_WINDOWS - errno = ENOTSUP; - return -1; -#else - if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; - } - ssize_t ret = pread(fd, p, nb, offset); - wasm_runtime_end_blocking_op(exec_env); - return ret; -#endif -} -#endif /* CONFIG_HAS_PREADV */ - -ssize_t -blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt) -{ -#ifdef BH_PLATFORM_WINDOWS - errno = ENOTSUP; - return -1; -#else - if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; - } - ssize_t ret = writev(fd, iov, iovcnt); - wasm_runtime_end_blocking_op(exec_env); - return ret; -#endif -} - -#if CONFIG_HAS_PWRITEV -ssize_t -blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt, off_t offset) -{ - if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; - } - ssize_t ret = pwritev(fd, iov, iovcnt, offset); - wasm_runtime_end_blocking_op(exec_env); - return ret; -} -#else /* CONFIG_HAS_PWRITEV */ -ssize_t -blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb, - off_t offset) -{ -#ifdef BH_PLATFORM_WINDOWS - errno = ENOTSUP; - return -1; -#else - if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; - } - ssize_t ret = pwrite(fd, p, nb, offset); - wasm_runtime_end_blocking_op(exec_env); - return ret; -#endif -} -#endif /* CONFIG_HAS_PWRITEV */ int blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock, @@ -207,20 +156,17 @@ blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host, return ret; } -int -blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path, - int oflags, mode_t mode) +__wasi_errno_t +blocking_op_openat(wasm_exec_env_t exec_env, os_file_handle handle, + const char *path, __wasi_oflags_t oflags, + __wasi_fdflags_t fd_flags, __wasi_lookupflags_t lookup_flags, + wasi_libc_file_access_mode access_mode, os_file_handle *out) { -#ifdef BH_PLATFORM_WINDOWS - errno = ENOTSUP; - return -1; -#else if (!wasm_runtime_begin_blocking_op(exec_env)) { - errno = EINTR; - return -1; + return __WASI_EINTR; } - int ret = openat(fd, path, oflags, mode); + __wasi_errno_t error = os_openat(handle, path, oflags, fd_flags, + lookup_flags, access_mode, out); wasm_runtime_end_blocking_op(exec_env); - return ret; -#endif + return error; } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h index e816e8472..afaa4a4f0 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h @@ -6,26 +6,24 @@ #include "bh_platform.h" #include "wasm_export.h" -int -blocking_op_close(wasm_exec_env_t exec_env, int fd); -ssize_t -blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt); -ssize_t -blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt, off_t offset); -ssize_t -blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb, - off_t offset); -ssize_t -blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt); -ssize_t -blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, - int iovcnt, off_t offset); -ssize_t -blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb, - off_t offset); +__wasi_errno_t +blocking_op_close(wasm_exec_env_t exec_env, os_file_handle handle, + bool is_stdio); +__wasi_errno_t +blocking_op_readv(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_iovec_t *iov, int iovcnt, size_t *nread); +__wasi_errno_t +blocking_op_preadv(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nread); +__wasi_errno_t +blocking_op_writev(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_ciovec_t *iov, int iovcnt, + size_t *nwritten); +__wasi_errno_t +blocking_op_pwritev(wasm_exec_env_t exec_env, os_file_handle handle, + const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten); int blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock, bh_socket_t *sockp, void *addr, @@ -48,10 +46,8 @@ blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host, bh_addr_info_t *addr_info, size_t addr_info_size, size_t *max_info_size); -#ifdef BH_PLATFORM_WINDOWS -/* TODO to be (re)moved as part of WASI on windows work */ -typedef unsigned mode_t; -#endif -int -blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path, - int oflags, mode_t mode); +__wasi_errno_t +blocking_op_openat(wasm_exec_env_t exec_env, os_file_handle handle, + const char *path, __wasi_oflags_t oflags, + __wasi_fdflags_t fd_flags, __wasi_lookupflags_t lookup_flags, + wasi_libc_file_access_mode access_mode, os_file_handle *out); \ No newline at end of file diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 444e24408..d143f7bef 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -15,6 +15,7 @@ #include "bh_platform.h" #include "blocking_op.h" #include "wasmtime_ssp.h" +#include "libc_errno.h" #include "locking.h" #include "posix.h" #include "random.h" @@ -68,111 +69,6 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), "Size mismatch"); #endif -// Converts a POSIX error code to a CloudABI error code. -static __wasi_errno_t -convert_errno(int error) -{ - __wasi_errno_t code = __WASI_ENOSYS; -#define X(v) \ - case v: \ - code = __WASI_##v; \ - break; - switch (error) { - X(E2BIG) - X(EACCES) - X(EADDRINUSE) - X(EADDRNOTAVAIL) - X(EAFNOSUPPORT) - X(EAGAIN) - X(EALREADY) - X(EBADF) - X(EBADMSG) - X(EBUSY) - X(ECANCELED) - X(ECHILD) - X(ECONNABORTED) - X(ECONNREFUSED) - X(ECONNRESET) - X(EDEADLK) - X(EDESTADDRREQ) - X(EDOM) -#ifdef EDQUOT - X(EDQUOT) -#endif - X(EEXIST) - X(EFAULT) - X(EFBIG) - X(EHOSTUNREACH) - X(EIDRM) - X(EILSEQ) - X(EINPROGRESS) - X(EINTR) - X(EINVAL) - X(EIO) - X(EISCONN) - X(EISDIR) - X(ELOOP) - X(EMFILE) - X(EMLINK) - X(EMSGSIZE) -#ifdef EMULTIHOP - X(EMULTIHOP) -#endif - X(ENAMETOOLONG) - X(ENETDOWN) - X(ENETRESET) - X(ENETUNREACH) - X(ENFILE) - X(ENOBUFS) - X(ENODEV) - X(ENOENT) - X(ENOEXEC) - X(ENOLCK) - X(ENOLINK) - X(ENOMEM) - X(ENOMSG) - X(ENOPROTOOPT) - X(ENOSPC) - X(ENOSYS) -#ifdef ENOTCAPABLE - X(ENOTCAPABLE) -#endif - X(ENOTCONN) - X(ENOTDIR) - X(ENOTEMPTY) - X(ENOTRECOVERABLE) - X(ENOTSOCK) - X(ENOTSUP) - X(ENOTTY) - X(ENXIO) - X(EOVERFLOW) - X(EOWNERDEAD) - X(EPERM) - X(EPIPE) - X(EPROTO) - X(EPROTONOSUPPORT) - X(EPROTOTYPE) - X(ERANGE) - X(EROFS) - X(ESPIPE) - X(ESRCH) -#ifdef ESTALE - X(ESTALE) -#endif - X(ETIMEDOUT) - X(ETXTBSY) - X(EXDEV) - default: - if (error == EOPNOTSUPP) - code = __WASI_ENOTSUP; - else if (code == EWOULDBLOCK) - code = __WASI_EAGAIN; - break; - } -#undef X - return code; -} - static bool ns_lookup_list_search(char **list, const char *host) { @@ -470,15 +366,16 @@ fd_prestats_remove_entry(struct fd_prestats *pt, __wasi_fd_t fd) struct fd_object { struct refcount refcount; __wasi_filetype_t type; - int number; + os_file_handle file_handle; + // Keep track of whether this fd object refers to a stdio stream so we know + // whether to close the underlying file handle when releasing the object. + bool is_stdio; union { // Data associated with directory file descriptors. struct { - struct mutex lock; // Lock to protect members below. -#ifndef BH_PLATFORM_WINDOWS - DIR *handle; // Directory handle. -#endif + struct mutex lock; // Lock to protect members below. + os_dir_stream handle; // Directory handle. __wasi_dircookie_t offset; // Offset of the directory. } directory; }; @@ -560,7 +457,7 @@ fd_table_grow(struct fd_table *ft, size_t min, size_t incr) // Allocates a new file descriptor object. static __wasi_errno_t -fd_object_new(__wasi_filetype_t type, struct fd_object **fo) +fd_object_new(__wasi_filetype_t type, bool is_stdio, struct fd_object **fo) TRYLOCKS_SHARED(0, (*fo)->refcount) { *fo = wasm_runtime_malloc(sizeof(**fo)); @@ -568,7 +465,8 @@ fd_object_new(__wasi_filetype_t type, struct fd_object **fo) return __WASI_ENOMEM; refcount_init(&(*fo)->refcount, 1); (*fo)->type = type; - (*fo)->number = -1; + (*fo)->file_handle = os_get_invalid_handle(); + (*fo)->is_stdio = is_stdio; return 0; } @@ -606,151 +504,119 @@ fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo) // Determines the type of a file descriptor and its maximum set of // rights that should be attached to it. static __wasi_errno_t -fd_determine_type_rights(int fd, __wasi_filetype_t *type, +fd_determine_type_rights(os_file_handle fd, __wasi_filetype_t *type, __wasi_rights_t *rights_base, __wasi_rights_t *rights_inheriting) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else - struct stat sb; - if (fstat(fd, &sb) < 0) - return convert_errno(errno); - if (S_ISBLK(sb.st_mode)) { - *type = __WASI_FILETYPE_BLOCK_DEVICE; - *rights_base = RIGHTS_BLOCK_DEVICE_BASE; - *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING; - } - else if (S_ISCHR(sb.st_mode)) { - *type = __WASI_FILETYPE_CHARACTER_DEVICE; -#if CONFIG_HAS_ISATTY - if (isatty(fd)) { - *rights_base = RIGHTS_TTY_BASE; - *rights_inheriting = RIGHTS_TTY_INHERITING; - } - else -#endif - { - *rights_base = RIGHTS_CHARACTER_DEVICE_BASE; - *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING; - } - } - else if (S_ISDIR(sb.st_mode)) { - *type = __WASI_FILETYPE_DIRECTORY; - *rights_base = RIGHTS_DIRECTORY_BASE; - *rights_inheriting = RIGHTS_DIRECTORY_INHERITING; - } - else if (S_ISREG(sb.st_mode)) { - *type = __WASI_FILETYPE_REGULAR_FILE; - *rights_base = RIGHTS_REGULAR_FILE_BASE; - *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING; - } - else if (S_ISSOCK(sb.st_mode)) { - int socktype; - socklen_t socktypelen = sizeof(socktype); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) < 0) - return convert_errno(errno); - switch (socktype) { - case SOCK_DGRAM: - *type = __WASI_FILETYPE_SOCKET_DGRAM; - break; - case SOCK_STREAM: - *type = __WASI_FILETYPE_SOCKET_STREAM; - break; - default: - return __WASI_EINVAL; - } - *rights_base = RIGHTS_SOCKET_BASE; - *rights_inheriting = RIGHTS_SOCKET_INHERITING; - } - else if (S_ISFIFO(sb.st_mode)) { - *type = __WASI_FILETYPE_SOCKET_STREAM; - *rights_base = RIGHTS_SOCKET_BASE; - *rights_inheriting = RIGHTS_SOCKET_INHERITING; - } - else { - return __WASI_EINVAL; + struct __wasi_filestat_t buf; + __wasi_errno_t error = os_fstat(fd, &buf); + + if (error != __WASI_ESUCCESS) + return error; + + *type = buf.st_filetype; + + switch (buf.st_filetype) { + case __WASI_FILETYPE_BLOCK_DEVICE: + *rights_base = RIGHTS_BLOCK_DEVICE_BASE; + *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING; + break; + case __WASI_FILETYPE_CHARACTER_DEVICE: + error = os_isatty(fd); + + if (error == __WASI_ESUCCESS) { + *rights_base = RIGHTS_TTY_BASE; + *rights_inheriting = RIGHTS_TTY_INHERITING; + } + else { + *rights_base = RIGHTS_CHARACTER_DEVICE_BASE; + *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING; + } + break; + case __WASI_FILETYPE_DIRECTORY: + *rights_base = RIGHTS_DIRECTORY_BASE; + *rights_inheriting = RIGHTS_DIRECTORY_INHERITING; + break; + case __WASI_FILETYPE_REGULAR_FILE: + *rights_base = RIGHTS_REGULAR_FILE_BASE; + *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING; + break; + case __WASI_FILETYPE_SOCKET_DGRAM: + case __WASI_FILETYPE_SOCKET_STREAM: + *rights_base = RIGHTS_SOCKET_BASE; + *rights_inheriting = RIGHTS_SOCKET_INHERITING; + break; + case __WASI_FILETYPE_SYMBOLIC_LINK: + case __WASI_FILETYPE_UNKNOWN: + // If we don't know the type, allow for the maximum set of + // rights + *rights_base = RIGHTS_ALL; + *rights_inheriting = RIGHTS_ALL; + break; + default: + return __WASI_EINVAL; } + wasi_libc_file_access_mode access_mode; + error = os_file_get_access_mode(fd, &access_mode); + + if (error != __WASI_ESUCCESS) + return error; + // Strip off read/write bits based on the access mode. - switch (fcntl(fd, F_GETFL) & O_ACCMODE) { - case O_RDONLY: + switch (access_mode) { + case WASI_LIBC_ACCESS_MODE_READ_ONLY: *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE; break; - case O_WRONLY: + case WASI_LIBC_ACCESS_MODE_WRITE_ONLY: *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ; break; } - return 0; -#endif -} -// Returns the underlying file descriptor number of a file descriptor -// object. This function can only be applied to objects that have an -// underlying file descriptor number. -static int -fd_number(const struct fd_object *fo) -{ - int number = fo->number; - assert(number >= 0 && "fd_number() called on virtual file descriptor"); - return number; + return error; } -// The env == NULL case is for -// fd_table_destroy, path_get, path_put, fd_table_insert_existing -#define CLOSE_NON_STD_FD(env, fd) \ - do { \ - if (fd > 2) { \ - if (env == NULL) { \ - close(fd); \ - } \ - else { \ - blocking_op_close(env, fd); \ - } \ - } \ - } while (0) - // Lowers the reference count on a file descriptor object. When the // reference count reaches zero, its resources are cleaned up. -static void +static __wasi_errno_t fd_object_release(wasm_exec_env_t env, struct fd_object *fo) UNLOCKS(fo->refcount) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else + __wasi_errno_t error = __WASI_ESUCCESS; + if (refcount_release(&fo->refcount)) { int saved_errno = errno; switch (fo->type) { case __WASI_FILETYPE_DIRECTORY: - // For directories we may keep track of a DIR object. Calling - // closedir() on it also closes the underlying file descriptor. + // For directories we may keep track of a DIR object. + // Calling os_closedir() on it also closes the underlying file + // descriptor. mutex_destroy(&fo->directory.lock); - if (fo->directory.handle == NULL) { - CLOSE_NON_STD_FD(env, fd_number(fo)); + if (os_is_dir_stream_valid(&fo->directory.handle)) { + error = os_closedir(fo->directory.handle); + break; } - else { - closedir(fo->directory.handle); - } - break; default: - CLOSE_NON_STD_FD(env, fd_number(fo)); + // The env == NULL case is for + // fd_table_destroy, path_get, path_put, + // fd_table_insert_existing + error = (env == NULL) ? os_close(fo->file_handle, fo->is_stdio) + : blocking_op_close(env, fo->file_handle, + fo->is_stdio); break; } wasm_runtime_free(fo); errno = saved_errno; } -#endif + return error; } // Inserts an already existing file descriptor into the file descriptor // table. bool -fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) +fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, + os_file_handle out, bool is_stdio) { -#ifdef BH_PLATFORM_WINDOWS - return false; -#else __wasi_filetype_t type = __WASI_FILETYPE_UNKNOWN; __wasi_rights_t rights_base = 0, rights_inheriting = 0; struct fd_object *fo; @@ -761,8 +627,8 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) if (error != 0) { #ifdef BH_PLATFORM_EGO /** - * since it is an already opened file and we can assume the opened file - * has all necessary rights no matter how to get + * since it is an already opened file and we can assume the opened + * file has all necessary rights no matter how to get */ if (error != __WASI_ENOTSUP) return false; @@ -771,16 +637,16 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) #endif } - error = fd_object_new(type, &fo); + error = fd_object_new(type, is_stdio, &fo); if (error != 0) return false; - fo->number = out; + fo->file_handle = out; if (type == __WASI_FILETYPE_DIRECTORY) { if (!mutex_init(&fo->directory.lock)) { fd_object_release(NULL, fo); return false; } - fo->directory.handle = NULL; + fo->directory.handle = os_get_invalid_dir_stream(); } // Grow the file descriptor table if needed. @@ -794,7 +660,6 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) fd_table_attach(ft, in, fo, rights_base, rights_inheriting); rwlock_unlock(&ft->lock); return true; -#endif } // Picks an unused slot from the file descriptor table. @@ -833,33 +698,30 @@ fd_table_insert(wasm_exec_env_t exec_env, struct fd_table *ft, // Inserts a numerical file descriptor into the file descriptor table. static __wasi_errno_t -fd_table_insert_fd(wasm_exec_env_t exec_env, struct fd_table *ft, int in, - __wasi_filetype_t type, __wasi_rights_t rights_base, +fd_table_insert_fd(wasm_exec_env_t exec_env, struct fd_table *ft, + os_file_handle in, __wasi_filetype_t type, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; - __wasi_errno_t error = fd_object_new(type, &fo); + __wasi_errno_t error = fd_object_new(type, false, &fo); if (error != 0) { - close(in); + os_close(in, false); return error; } - fo->number = in; + fo->file_handle = in; if (type == __WASI_FILETYPE_DIRECTORY) { if (!mutex_init(&fo->directory.lock)) { fd_object_release(exec_env, fo); return (__wasi_errno_t)-1; } - fo->directory.handle = NULL; + fo->directory.handle = os_get_invalid_dir_stream(); } return fd_table_insert(exec_env, ft, fo, rights_base, rights_inheriting, out); -#endif } __wasi_errno_t @@ -988,25 +850,17 @@ __wasi_errno_t wasmtime_ssp_fd_datasync(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_DATASYNC, 0); if (error != 0) return error; -#if CONFIG_HAS_FDATASYNC - int ret = fdatasync(fd_number(fo)); -#else - int ret = fsync(fd_number(fo)); -#endif + error = os_fdatasync(fo->file_handle); + fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t @@ -1014,77 +868,22 @@ wasmtime_ssp_fd_pread(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, __wasi_filesize_t offset, size_t *nread) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else if (iovcnt == 0) return __WASI_EINVAL; struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0); + if (error != 0) return error; -#if CONFIG_HAS_PREADV - ssize_t len = - blocking_op_preadv(exec_env, fd_number(fo), (const struct iovec *)iov, - (int)iovcnt, (off_t)offset); + error = blocking_op_preadv(exec_env, fo->file_handle, iov, (int)iovcnt, + offset, nread); + fd_object_release(exec_env, fo); - if (len < 0) - return convert_errno(errno); - *nread = (size_t)len; - return 0; -#else - if (iovcnt == 1) { - ssize_t len = blocking_op_pread(exec_env, fd_number(fo), iov->buf, - iov->buf_len, offset); - fd_object_release(exec_env, fo); - if (len < 0) - return convert_errno(errno); - *nread = len; - return 0; - } - else { - // Allocate a single buffer to fit all data. - size_t totalsize = 0; - for (size_t i = 0; i < iovcnt; ++i) - totalsize += iov[i].buf_len; - char *buf = wasm_runtime_malloc(totalsize); - if (buf == NULL) { - fd_object_release(exec_env, fo); - return __WASI_ENOMEM; - } - // Perform a single read operation. - ssize_t len = - blocking_op_pread(exec_env, fd_number(fo), buf, totalsize, offset); - fd_object_release(exec_env, fo); - if (len < 0) { - wasm_runtime_free(buf); - return convert_errno(errno); - } - - // Copy data back to vectors. - size_t bufoff = 0; - for (size_t i = 0; i < iovcnt; ++i) { - if (bufoff + iov[i].buf_len < (size_t)len) { - bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, - iov[i].buf_len); - bufoff += iov[i].buf_len; - } - else { - bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, - len - bufoff); - break; - } - } - wasm_runtime_free(buf); - *nread = len; - return 0; - } -#endif -#endif + return error; } __wasi_errno_t @@ -1093,57 +892,18 @@ wasmtime_ssp_fd_pwrite(wasm_exec_env_t exec_env, struct fd_table *curfds, size_t iovcnt, __wasi_filesize_t offset, size_t *nwritten) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else - if (iovcnt == 0) - return __WASI_EINVAL; - struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) return error; - ssize_t len; -#if CONFIG_HAS_PWRITEV - len = - blocking_op_pwritev(exec_env, fd_number(fo), (const struct iovec *)iov, - (int)iovcnt, (off_t)offset); -#else - if (iovcnt == 1) { - len = blocking_op_pwrite(exec_env, fd_number(fo), iov->buf, - iov->buf_len, offset); - } - else { - // Allocate a single buffer to fit all data. - size_t totalsize = 0; - for (size_t i = 0; i < iovcnt; ++i) - totalsize += iov[i].buf_len; - char *buf = wasm_runtime_malloc(totalsize); - if (buf == NULL) { - fd_object_release(exec_env, fo); - return __WASI_ENOMEM; - } - size_t bufoff = 0; - for (size_t i = 0; i < iovcnt; ++i) { - bh_memcpy_s(buf + bufoff, totalsize - bufoff, iov[i].buf, - iov[i].buf_len); - bufoff += iov[i].buf_len; - } - - // Perform a single write operation. - len = - blocking_op_pwrite(exec_env, fd_number(fo), buf, totalsize, offset); - wasm_runtime_free(buf); - } -#endif + error = blocking_op_pwritev(exec_env, fo->file_handle, iov, (int)iovcnt, + offset, nwritten); fd_object_release(exec_env, fo); - if (len < 0) - return convert_errno(errno); - *nwritten = (size_t)len; - return 0; -#endif + + return error; } __wasi_errno_t @@ -1151,23 +911,19 @@ wasmtime_ssp_fd_read(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0); + if (error != 0) return error; - ssize_t len = blocking_op_readv(exec_env, fd_number(fo), - (const struct iovec *)iov, (int)iovcnt); + error = + blocking_op_readv(exec_env, fo->file_handle, iov, (int)iovcnt, nread); + fd_object_release(exec_env, fo); - if (len < 0) - return convert_errno(errno); - *nread = (size_t)len; - return 0; -#endif + + return error; } __wasi_errno_t @@ -1229,9 +985,9 @@ wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, (void)fd_prestats_remove_entry(prestats, to); } } - // Renumbering from a non-preopened fd to a preopened fd. In this case, we - // can't a keep the destination fd entry in the preopened table so remove - // it entirely. + // Renumbering from a non-preopened fd to a preopened fd. In this case, + // we can't a keep the destination fd entry in the preopened table so + // remove it entirely. else if (prestat_from_error != __WASI_ESUCCESS && prestat_to_error == __WASI_ESUCCESS) { (void)fd_prestats_remove_entry(prestats, to); @@ -1260,21 +1016,6 @@ wasmtime_ssp_fd_seek(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, __wasi_filesize_t *newoffset) { - int nwhence; - switch (whence) { - case __WASI_WHENCE_CUR: - nwhence = SEEK_CUR; - break; - case __WASI_WHENCE_END: - nwhence = SEEK_END; - break; - case __WASI_WHENCE_SET: - nwhence = SEEK_SET; - break; - default: - return __WASI_EINVAL; - } - struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, @@ -1285,12 +1026,11 @@ wasmtime_ssp_fd_seek(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != 0) return error; - off_t ret = lseek(fd_number(fo), offset, nwhence); + error = os_lseek(fo->file_handle, offset, whence, newoffset); + fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - *newoffset = (__wasi_filesize_t)ret; - return 0; + + return error; } __wasi_errno_t @@ -1303,67 +1043,44 @@ wasmtime_ssp_fd_tell(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != 0) return error; - off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); + error = os_lseek(fo->file_handle, 0, __WASI_WHENCE_CUR, newoffset); + fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - *newoffset = (__wasi_filesize_t)ret; - return 0; + + return error; } __wasi_errno_t wasmtime_ssp_fd_fdstat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdstat_t *buf) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_table *ft = curfds; rwlock_rdlock(&ft->lock); struct fd_entry *fe; __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); - if (error != 0) { + if (error != __WASI_ESUCCESS) { rwlock_unlock(&ft->lock); return error; } // Extract file descriptor type and rights. struct fd_object *fo = fe->object; - *buf = (__wasi_fdstat_t){ - .fs_filetype = fo->type, - .fs_rights_base = fe->rights_base, - .fs_rights_inheriting = fe->rights_inheriting, - }; - // Fetch file descriptor flags. - int ret; - switch (fo->type) { - default: - ret = fcntl(fd_number(fo), F_GETFL); - break; + __wasi_fdflags_t flags; + error = os_file_get_fdflags(fo->file_handle, &flags); + + if (error != __WASI_ESUCCESS) { + rwlock_unlock(&ft->lock); + return error; } - rwlock_unlock(&ft->lock); - if (ret < 0) - return convert_errno(errno); - if ((ret & O_APPEND) != 0) - buf->fs_flags |= __WASI_FDFLAG_APPEND; -#ifdef CONFIG_HAS_O_DSYNC - if ((ret & O_DSYNC) != 0) - buf->fs_flags |= __WASI_FDFLAG_DSYNC; -#endif - if ((ret & O_NONBLOCK) != 0) - buf->fs_flags |= __WASI_FDFLAG_NONBLOCK; -#ifdef CONFIG_HAS_O_RSYNC - if ((ret & O_RSYNC) != 0) - buf->fs_flags |= __WASI_FDFLAG_RSYNC; -#endif -#ifdef CONFIG_HAS_O_SYNC - if ((ret & O_SYNC) != 0) - buf->fs_flags |= __WASI_FDFLAG_SYNC; -#endif - return 0; -#endif + *buf = (__wasi_fdstat_t){ .fs_filetype = fo->type, + .fs_rights_base = fe->rights_base, + .fs_rights_inheriting = fe->rights_inheriting, + .fs_flags = flags }; + + rwlock_unlock(&ft->lock); + return error; } __wasi_errno_t @@ -1371,45 +1088,18 @@ wasmtime_ssp_fd_fdstat_set_flags(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdflags_t fs_flags) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else - int noflags = 0; - if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) - noflags |= O_APPEND; - if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) -#ifdef CONFIG_HAS_O_DSYNC - noflags |= O_DSYNC; -#else - return __WASI_ENOTSUP; -#endif - if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) - noflags |= O_NONBLOCK; - if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) -#ifdef CONFIG_HAS_O_RSYNC - noflags |= O_RSYNC; -#else - return __WASI_ENOTSUP; -#endif - if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) -#ifdef CONFIG_HAS_O_SYNC - noflags |= O_SYNC; -#else - return __WASI_ENOTSUP; -#endif - struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS, 0); + if (error != 0) return error; - int ret = fcntl(fd_number(fo), F_SETFL, noflags); + error = os_file_set_fdflags(fo->file_handle, fs_flags); + fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t @@ -1439,21 +1129,18 @@ __wasi_errno_t wasmtime_ssp_fd_sync(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_SYNC, 0); + if (error != 0) return error; - int ret = fsync(fd_number(fo)); + error = os_fsync(fo->file_handle); + fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t @@ -1461,9 +1148,6 @@ wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); @@ -1471,11 +1155,12 @@ wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, return error; #ifndef BH_VPRINTF - ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + error = blocking_op_writev(exec_env, fo->file_handle, iov, (int)iovcnt, + nwritten); #else ssize_t len = 0; /* redirect stdout/stderr output to BH_VPRINTF function */ - if (fd_number(fo) == 1 || fd_number(fo) == 2) { + if (fo->is_stdio) { int i; const struct iovec *iov1 = (const struct iovec *)iov; @@ -1490,15 +1175,13 @@ wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, } } else { - len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + error = blocking_op_writev(exec_env, fo->file_handle, iov, (int)iovcnt, + nwritten); } #endif /* end of BH_VPRINTF */ fd_object_release(exec_env, fo); - if (len < 0) - return convert_errno(errno); - *nwritten = (size_t)len; - return 0; -#endif + + return error; } __wasi_errno_t @@ -1506,65 +1189,17 @@ wasmtime_ssp_fd_advise(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len, __wasi_advice_t advice) { -#ifdef POSIX_FADV_NORMAL - int nadvice; - switch (advice) { - case __WASI_ADVICE_DONTNEED: - nadvice = POSIX_FADV_DONTNEED; - break; - case __WASI_ADVICE_NOREUSE: - nadvice = POSIX_FADV_NOREUSE; - break; - case __WASI_ADVICE_NORMAL: - nadvice = POSIX_FADV_NORMAL; - break; - case __WASI_ADVICE_RANDOM: - nadvice = POSIX_FADV_RANDOM; - break; - case __WASI_ADVICE_SEQUENTIAL: - nadvice = POSIX_FADV_SEQUENTIAL; - break; - case __WASI_ADVICE_WILLNEED: - nadvice = POSIX_FADV_WILLNEED; - break; - default: - return __WASI_EINVAL; - } - struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ADVISE, 0); if (error != 0) return error; - int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice); - fd_object_release(exec_env, fo); - if (ret != 0) - return convert_errno(ret); - return 0; -#else - // Advisory information can safely be ignored if unsupported. - switch (advice) { - case __WASI_ADVICE_DONTNEED: - case __WASI_ADVICE_NOREUSE: - case __WASI_ADVICE_NORMAL: - case __WASI_ADVICE_RANDOM: - case __WASI_ADVICE_SEQUENTIAL: - case __WASI_ADVICE_WILLNEED: - break; - default: - return __WASI_EINVAL; - } + error = os_fadvise(fo->file_handle, offset, len, advice); + + fd_object_release(exec_env, fo); - // At least check for file descriptor existence. - struct fd_table *ft = curfds; - rwlock_rdlock(&ft->lock); - struct fd_entry *fe; - __wasi_errno_t error = - fd_table_get_entry(ft, fd, __WASI_RIGHT_FD_ADVISE, 0, &fe); - rwlock_unlock(&ft->lock); return error; -#endif } __wasi_errno_t @@ -1572,41 +1207,26 @@ wasmtime_ssp_fd_allocate(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0); - if (error != 0) + if (error != __WASI_ESUCCESS) return error; -#if CONFIG_HAS_POSIX_FALLOCATE - int ret = posix_fallocate(fd_number(fo), (off_t)offset, (off_t)len); -#else - // At least ensure that the file is grown to the right size. - // TODO(ed): See if this can somehow be implemented without any race - // conditions. We may end up shrinking the file right now. - struct stat sb; - int ret = fstat(fd_number(fo), &sb); - off_t newsize = (off_t)(offset + len); - if (ret == 0 && sb.st_size < newsize) - ret = ftruncate(fd_number(fo), newsize); -#endif + error = os_fallocate(fo->file_handle, offset, len); fd_object_release(exec_env, fo); - if (ret != 0) - return convert_errno(ret); - return 0; -#endif + + return error; } // Reads the entire contents of a symbolic link, returning the contents // in an allocated buffer. The allocated buffer is large enough to fit // at least one extra byte, so the caller may append a trailing slash to // it. This is needed by path_get(). -static char * -readlinkat_dup(int fd, const char *path, size_t *p_len) +__wasi_errno_t +readlinkat_dup(os_file_handle handle, const char *path, size_t *p_len, + char **out_buf) { char *buf = NULL; size_t len = 32; @@ -1618,7 +1238,8 @@ readlinkat_dup(int fd, const char *path, size_t *p_len) if (newbuf == NULL) { if (buf) wasm_runtime_free(buf); - return NULL; + *out_buf = NULL; + return __WASI_ENOMEM; } if (buf != NULL) { @@ -1627,15 +1248,20 @@ readlinkat_dup(int fd, const char *path, size_t *p_len) } buf = newbuf; - ssize_t ret = readlinkat(fd, path, buf, len); - if (ret < 0) { + size_t bytes_read = 0; + __wasi_errno_t error = + os_readlinkat(handle, path, buf, len, &bytes_read); + if (error != __WASI_ESUCCESS) { wasm_runtime_free(buf); - return NULL; + *out_buf = NULL; + return error; } - if ((size_t)ret + 1 < len) { - buf[ret] = '\0'; + if ((size_t)bytes_read + 1 < len) { + buf[bytes_read] = '\0'; *p_len = len; - return buf; + *out_buf = buf; + + return __WASI_ESUCCESS; } len_org = len; len *= 2; @@ -1649,7 +1275,7 @@ readlinkat_dup(int fd, const char *path, size_t *p_len) // descriptor representing the directory where the lookup needs to start // and the actual pathname string. struct path_access { - int fd; // Directory file descriptor. + os_file_handle fd; // Directory file descriptor. const char *path; // Pathname. bool follow; // Whether symbolic links should be followed. char *path_start; // Internal: pathname to free. @@ -1661,15 +1287,12 @@ struct path_access { // pathname to ensure the target path is placed underneath the // directory. static __wasi_errno_t -path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, - __wasi_lookupflags_t flags, const char *upath, size_t upathlen, - __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, - bool needs_final_component) +path_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct path_access *pa, __wasi_fd_t fd, __wasi_lookupflags_t flags, + const char *upath, size_t upathlen, __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, bool needs_final_component) TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else char *path = str_nullterminate(upath, upathlen); if (path == NULL) return convert_errno(errno); @@ -1686,7 +1309,7 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, #if CONFIG_HAS_CAP_ENTER // Rely on the kernel to constrain access to automatically constrain // access to files stored underneath this directory. - pa->fd = fd_number(fo); + pa->fd = fo->file_handle; pa->path = pa->path_start = path; pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0; pa->fd_object = fo; @@ -1701,8 +1324,8 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, // causes a file descriptor to be pushed, while handling ".." entries // causes an entry to be popped. Index 0 cannot be popped, as this // would imply escaping the base directory. - int fds[128]; - fds[0] = fd_number(fo); + os_file_handle fds[128]; + fds[0] = fo->file_handle; size_t curfd = 0; // Stack of pathname strings used for symlink expansion. By using a @@ -1713,7 +1336,7 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, paths[0] = paths_start[0] = path; size_t curpath = 0; size_t expansions = 0; - char *symlink; + char *symlink = NULL; size_t symlink_len; for (;;) { @@ -1744,7 +1367,10 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, error = __WASI_ENOTCAPABLE; goto fail; } - close(fds[curfd--]); + error = os_close(fds[curfd--], false); + + if (error != __WASI_ESUCCESS) + goto fail; } else if (curpath > 0 || *paths[curpath] != '\0' || (ends_with_slashes && !needs_final_component)) { @@ -1753,19 +1379,14 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, // components. In other words, a pathname component that must be a // directory. First attempt to obtain a directory file descriptor // for it. - // - // Note: we don't bother to use blocking_op_openat here - // because openat with O_DIRECTORY should not block. - int newdir = -#ifdef O_SEARCH - openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW); -#else - openat(fds[curfd], file, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); -#endif - if (newdir != -1) { + os_file_handle newdir; + error = blocking_op_openat( + exec_env, fds[curfd], file, __WASI_O_DIRECTORY, 0, 0, + WASI_LIBC_ACCESS_MODE_READ_ONLY, &newdir); + if (error == __WASI_ESUCCESS) { // Success. Push it onto the directory stack. if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) { - close(newdir); + os_close(newdir, false); error = __WASI_ENAMETOOLONG; goto fail; } @@ -1773,20 +1394,23 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, } else { // Failed to open it. Attempt symlink expansion. - if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) { - error = convert_errno(errno); + if (error != __WASI_ELOOP && error != __WASI_EMLINK + && error != __WASI_ENOTDIR) { goto fail; } - symlink = readlinkat_dup(fds[curfd], file, &symlink_len); - if (symlink != NULL) + error = + readlinkat_dup(fds[curfd], file, &symlink_len, &symlink); + + if (error == __WASI_ESUCCESS) { + bh_assert(symlink != NULL); goto push_symlink; + } // readlink returns EINVAL if the path isn't a symlink. In that // case, it's more informative to return ENOTDIR. - if (errno == EINVAL) - errno = ENOTDIR; + if (error == __WASI_EINVAL) + error = __WASI_ENOTDIR; - error = convert_errno(errno); goto fail; } } @@ -1796,11 +1420,13 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, // expansion. if (ends_with_slashes || (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) { - symlink = readlinkat_dup(fds[curfd], file, &symlink_len); - if (symlink != NULL) + error = + readlinkat_dup(fds[curfd], file, &symlink_len, &symlink); + if (error == __WASI_ESUCCESS) { + bh_assert(symlink != NULL); goto push_symlink; - if (errno != EINVAL && errno != ENOENT) { - error = convert_errno(errno); + } + if (error != __WASI_EINVAL && error != __WASI_ENOENT) { goto fail; } } @@ -1877,7 +1503,7 @@ success: // Return the lease. Close all directories, except the one the caller // needs to use. for (size_t i = 1; i < curfd; ++i) - close(fds[i]); + os_close(fds[i], false); pa->fd = fds[curfd]; pa->follow = false; pa->fd_object = fo; @@ -1886,24 +1512,23 @@ success: fail: // Failure. Free all resources. for (size_t i = 1; i <= curfd; ++i) - close(fds[i]); + os_close(fds[i], false); for (size_t i = 0; i <= curpath; ++i) wasm_runtime_free(paths_start[i]); fd_object_release(NULL, fo); return error; #endif -#endif } static __wasi_errno_t -path_get_nofollow(struct fd_table *curfds, struct path_access *pa, - __wasi_fd_t fd, const char *path, size_t pathlen, - __wasi_rights_t rights_base, +path_get_nofollow(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct path_access *pa, __wasi_fd_t fd, const char *path, + size_t pathlen, __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, bool needs_final_component) TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) { __wasi_lookupflags_t flags = 0; - return path_get(curfds, pa, fd, flags, path, pathlen, rights_base, + return path_get(exec_env, curfds, pa, fd, flags, path, pathlen, rights_base, rights_inheriting, needs_final_component); } @@ -1912,8 +1537,8 @@ path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount) { if (pa->path_start) wasm_runtime_free(pa->path_start); - if (fd_number(pa->fd_object) != pa->fd) - close(pa->fd); + if (pa->fd_object->file_handle != pa->fd) + os_close(pa->fd, false); fd_object_release(NULL, pa->fd_object); } @@ -1922,33 +1547,27 @@ wasmtime_ssp_path_create_directory(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, size_t pathlen) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access pa; __wasi_errno_t error = - path_get_nofollow(curfds, &pa, fd, path, pathlen, + path_get_nofollow(exec_env, curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_CREATE_DIRECTORY, 0, true); if (error != 0) return error; - int ret = mkdirat(pa.fd, pa.path, 0777); + error = os_mkdirat(pa.fd, pa.path); path_put(&pa); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } static bool validate_path(const char *path, struct fd_prestats *pt) { -#ifndef BH_PLATFORM_WINDOWS size_t i; char path_resolved[PATH_MAX], prestat_dir_resolved[PATH_MAX]; char *path_real, *prestat_dir_real; - if (!(path_real = realpath(path, path_resolved))) + if (!(path_real = os_realpath(path, path_resolved))) /* path doesn't exist, creating a link to this file is allowed: if this file is to be created in the future, WASI will strictly check whether it @@ -1958,13 +1577,13 @@ validate_path(const char *path, struct fd_prestats *pt) for (i = 0; i < pt->size; i++) { if (pt->prestats[i].dir) { if (!(prestat_dir_real = - realpath(pt->prestats[i].dir, prestat_dir_resolved))) + os_realpath(pt->prestats[i].dir, prestat_dir_resolved))) return false; if (!strncmp(path_real, prestat_dir_real, strlen(prestat_dir_real))) return true; } } -#endif + return false; } @@ -1975,19 +1594,17 @@ wasmtime_ssp_path_link(wasm_exec_env_t exec_env, struct fd_table *curfds, size_t old_path_len, __wasi_fd_t new_fd, const char *new_path, size_t new_path_len) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access old_pa; __wasi_errno_t error = - path_get(curfds, &old_pa, old_fd, old_flags, old_path, old_path_len, - __WASI_RIGHT_PATH_LINK_SOURCE, 0, false); + path_get(exec_env, curfds, &old_pa, old_fd, old_flags, old_path, + old_path_len, __WASI_RIGHT_PATH_LINK_SOURCE, 0, false); if (error != 0) return error; struct path_access new_pa; - error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, - __WASI_RIGHT_PATH_LINK_TARGET, 0, true); + error = + path_get_nofollow(exec_env, curfds, &new_pa, new_fd, new_path, + new_path_len, __WASI_RIGHT_PATH_LINK_TARGET, 0, true); if (error != 0) { path_put(&old_pa); return error; @@ -2001,14 +1618,18 @@ wasmtime_ssp_path_link(wasm_exec_env_t exec_env, struct fd_table *curfds, } rwlock_unlock(&prestats->lock); - int ret = linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path, - old_pa.follow ? AT_SYMLINK_FOLLOW : 0); - if (ret < 0 && errno == ENOTSUP && !old_pa.follow) { + error = os_linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path, + old_pa.follow ? __WASI_LOOKUP_SYMLINK_FOLLOW : 0); + +#if defined(__APPLE__) + if (error == __WASI_ENOTSUP && !old_pa.follow) { // OS X doesn't allow creating hardlinks to symbolic links. // Duplicate the symbolic link instead. size_t target_len; - char *target = readlinkat_dup(old_pa.fd, old_pa.path, &target_len); - if (target != NULL) { + char *target = NULL; + error = readlinkat_dup(old_pa.fd, old_pa.path, &target_len, &target); + if (error == __WASI_ESUCCESS) { + bh_assert(target != NULL); bh_assert(target[target_len] == '\0'); rwlock_rdlock(&prestats->lock); if (!validate_path(target, prestats)) { @@ -2017,16 +1638,16 @@ wasmtime_ssp_path_link(wasm_exec_env_t exec_env, struct fd_table *curfds, return __WASI_EBADF; } rwlock_unlock(&prestats->lock); - ret = symlinkat(target, new_pa.fd, new_pa.path); + error = os_symlinkat(target, new_pa.fd, new_pa.path); wasm_runtime_free(target); } } +#endif + path_put(&old_pa); path_put(&new_pa); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t @@ -2037,9 +1658,6 @@ wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags, __wasi_fd_t *fd) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else // Rights that should be installed on the new file descriptor. __wasi_rights_t rights_base = fs_rights_base; __wasi_rights_t rights_inheriting = fs_rights_inheriting; @@ -2052,7 +1670,11 @@ wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, & (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_ALLOCATE | __WASI_RIGHT_FD_FILESTAT_SET_SIZE)) != 0; - int noflags = write ? read ? O_RDWR : O_WRONLY : O_RDONLY; + + wasi_libc_file_access_mode access_mode = + write ? read ? WASI_LIBC_ACCESS_MODE_READ_WRITE + : WASI_LIBC_ACCESS_MODE_WRITE_ONLY + : WASI_LIBC_ACCESS_MODE_READ_ONLY; // Which rights are needed on the directory file descriptor. __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN; @@ -2060,106 +1682,59 @@ wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, // Convert open flags. if ((oflags & __WASI_O_CREAT) != 0) { - noflags |= O_CREAT; needed_base |= __WASI_RIGHT_PATH_CREATE_FILE; } - if ((oflags & __WASI_O_DIRECTORY) != 0) - noflags |= O_DIRECTORY; - if ((oflags & __WASI_O_EXCL) != 0) - noflags |= O_EXCL; if ((oflags & __WASI_O_TRUNC) != 0) { - noflags |= O_TRUNC; needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE; } // Convert file descriptor flags. - if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) - noflags |= O_APPEND; - if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { -#ifdef CONFIG_HAS_O_DSYNC - noflags |= O_DSYNC; - needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; -#else - return __WASI_ENOTSUP; -#endif - } - if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) - noflags |= O_NONBLOCK; - if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { -#ifdef CONFIG_HAS_O_RSYNC - noflags |= O_RSYNC; - needed_inheriting |= __WASI_RIGHT_FD_SYNC; -#else - return __WASI_ENOTSUP; -#endif - } if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { -#ifdef CONFIG_HAS_O_SYNC - noflags |= O_SYNC; needed_inheriting |= __WASI_RIGHT_FD_SYNC; -#else - return __WASI_ENOTSUP; -#endif } - if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { + needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; + } + + if (write + && !((fs_flags & __WASI_FDFLAG_APPEND) || (__WASI_O_TRUNC & oflags))) needed_inheriting |= __WASI_RIGHT_FD_SEEK; struct path_access pa; - __wasi_errno_t error = - path_get(curfds, &pa, dirfd, dirflags, path, pathlen, needed_base, - needed_inheriting, (oflags & __WASI_O_CREAT) != 0); + __wasi_errno_t error = path_get( + exec_env, curfds, &pa, dirfd, dirflags, path, pathlen, needed_base, + needed_inheriting, (oflags & __WASI_O_CREAT) != 0); + if (error != 0) return error; - if (!pa.follow) - noflags |= O_NOFOLLOW; - int nfd = blocking_op_openat(exec_env, pa.fd, pa.path, noflags, 0666); - if (nfd < 0) { - int openat_errno = errno; - // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. - if (openat_errno == ENXIO) { - struct stat sb; - int ret = fstatat(pa.fd, pa.path, &sb, - pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); - path_put(&pa); - return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP - : __WASI_ENXIO; - } - // Linux returns ENOTDIR instead of ELOOP when using - // O_NOFOLLOW|O_DIRECTORY on a symlink. - if (openat_errno == ENOTDIR - && (noflags & (O_NOFOLLOW | O_DIRECTORY)) != 0) { - struct stat sb; - int ret = fstatat(pa.fd, pa.path, &sb, AT_SYMLINK_NOFOLLOW); - if (S_ISLNK(sb.st_mode)) { - path_put(&pa); - return __WASI_ELOOP; - } - (void)ret; - } - path_put(&pa); - // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on - // a symlink. - if (!pa.follow && openat_errno == EMLINK) - return __WASI_ELOOP; - return convert_errno(openat_errno); - } + os_file_handle handle; + error = blocking_op_openat(exec_env, pa.fd, pa.path, oflags, fs_flags, + dirflags, access_mode, &handle); + path_put(&pa); + if (error != __WASI_ESUCCESS) + return error; + // Determine the type of the new file descriptor and which rights // contradict with this type. __wasi_filetype_t type; __wasi_rights_t max_base, max_inheriting; - error = fd_determine_type_rights(nfd, &type, &max_base, &max_inheriting); - if (error != 0) { - close(nfd); + + error = fd_determine_type_rights(handle, &type, &max_base, &max_inheriting); + + if (error != __WASI_ESUCCESS) { + os_close(handle, false); return error; } - return fd_table_insert_fd(exec_env, curfds, nfd, type, + return fd_table_insert_fd(exec_env, curfds, handle, type, rights_base & max_base, rights_inheriting & max_inheriting, fd); -#endif } // Copies out directory entry metadata or filename, potentially @@ -2181,9 +1756,6 @@ wasmtime_ssp_fd_readdir(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie, size_t *bufused) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0); @@ -2193,15 +1765,13 @@ wasmtime_ssp_fd_readdir(wasm_exec_env_t exec_env, struct fd_table *curfds, // Create a directory handle if none has been opened yet. mutex_lock(&fo->directory.lock); - DIR *dp = fo->directory.handle; - if (dp == NULL) { - dp = fdopendir(fd_number(fo)); - if (dp == NULL) { + if (!os_is_dir_stream_valid(&fo->directory.handle)) { + error = os_fdopendir(fo->file_handle, &fo->directory.handle); + if (error != __WASI_ESUCCESS) { mutex_unlock(&fo->directory.lock); fd_object_release(exec_env, fo); - return convert_errno(errno); + return error; } - fo->directory.handle = dp; fo->directory.offset = __WASI_DIRCOOKIE_START; } @@ -2209,71 +1779,34 @@ wasmtime_ssp_fd_readdir(wasm_exec_env_t exec_env, struct fd_table *curfds, // the current offset. if (fo->directory.offset != cookie) { if (cookie == __WASI_DIRCOOKIE_START) - rewinddir(dp); + os_rewinddir(fo->directory.handle); else - seekdir(dp, (long)cookie); + os_seekdir(fo->directory.handle, cookie); fo->directory.offset = cookie; } *bufused = 0; while (*bufused < nbyte) { // Read the next directory entry. - errno = 0; - struct dirent *de = readdir(dp); - if (de == NULL) { + __wasi_dirent_t cde; + const char *d_name = NULL; + + error = os_readdir(fo->directory.handle, &cde, &d_name); + if (d_name == NULL) { mutex_unlock(&fo->directory.lock); fd_object_release(exec_env, fo); - return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno); - } - fo->directory.offset = (__wasi_dircookie_t)telldir(dp); - // Craft a directory entry and copy that back. - size_t namlen = strlen(de->d_name); - __wasi_dirent_t cde = { - .d_next = fo->directory.offset, -#if CONFIG_HAS_D_INO - .d_ino = de->d_ino, -#else - .d_ino = 0, -#endif - .d_namlen = (uint32)namlen, - }; - switch (de->d_type) { - case DT_BLK: - cde.d_type = __WASI_FILETYPE_BLOCK_DEVICE; - break; - case DT_CHR: - cde.d_type = __WASI_FILETYPE_CHARACTER_DEVICE; - break; - case DT_DIR: - cde.d_type = __WASI_FILETYPE_DIRECTORY; - break; - case DT_FIFO: - cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; - break; - case DT_LNK: - cde.d_type = __WASI_FILETYPE_SYMBOLIC_LINK; - break; - case DT_REG: - cde.d_type = __WASI_FILETYPE_REGULAR_FILE; - break; -#ifdef DT_SOCK - case DT_SOCK: - // Technically not correct, but good enough. - cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; - break; -#endif - default: - cde.d_type = __WASI_FILETYPE_UNKNOWN; - break; + return *bufused > 0 ? __WASI_ESUCCESS : error; } + + fo->directory.offset = cde.d_next; + fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde)); - fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); + fd_readdir_put(buf, nbyte, bufused, d_name, cde.d_namlen); } mutex_unlock(&fo->directory.lock); fd_object_release(exec_env, fo); - return 0; -#endif + return __WASI_ESUCCESS; } __wasi_errno_t @@ -2281,26 +1814,19 @@ wasmtime_ssp_path_readlink(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize, size_t *bufused) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access pa; - __wasi_errno_t error = path_get_nofollow( - curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_READLINK, 0, false); + __wasi_errno_t error = + path_get_nofollow(exec_env, curfds, &pa, fd, path, pathlen, + __WASI_RIGHT_PATH_READLINK, 0, false); + if (error != 0) return error; - // Linux requires that the buffer size is positive. whereas POSIX does - // not. Use a fake buffer to store the results if the size is zero. - char fakebuf[1]; - ssize_t len = readlinkat(pa.fd, pa.path, bufsize == 0 ? fakebuf : buf, - bufsize == 0 ? sizeof(fakebuf) : bufsize); + error = os_readlinkat(pa.fd, pa.path, buf, bufsize, bufused); + path_put(&pa); - if (len < 0) - return convert_errno(errno); - *bufused = (size_t)len < bufsize ? (size_t)len : bufsize; - return 0; -#endif + + return error; } __wasi_errno_t @@ -2309,80 +1835,46 @@ wasmtime_ssp_path_rename(wasm_exec_env_t exec_env, struct fd_table *curfds, size_t old_path_len, __wasi_fd_t new_fd, const char *new_path, size_t new_path_len) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access old_pa; - __wasi_errno_t error = - path_get_nofollow(curfds, &old_pa, old_fd, old_path, old_path_len, - __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true); + __wasi_errno_t error = path_get_nofollow( + exec_env, curfds, &old_pa, old_fd, old_path, old_path_len, + __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true); if (error != 0) return error; struct path_access new_pa; - error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, - __WASI_RIGHT_PATH_RENAME_TARGET, 0, true); + error = path_get_nofollow(exec_env, curfds, &new_pa, new_fd, new_path, + new_path_len, __WASI_RIGHT_PATH_RENAME_TARGET, 0, + true); if (error != 0) { path_put(&old_pa); return error; } - int ret = renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path); + error = os_renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path); + path_put(&old_pa); path_put(&new_pa); - if (ret < 0) { - return convert_errno(errno); - } - return 0; -#endif -} -#ifndef BH_PLATFORM_WINDOWS -// Converts a POSIX stat structure to a CloudABI filestat structure. -static void -convert_stat(const struct stat *in, __wasi_filestat_t *out) -{ - *out = (__wasi_filestat_t){ - .st_dev = in->st_dev, - .st_ino = in->st_ino, - .st_nlink = (__wasi_linkcount_t)in->st_nlink, - .st_size = (__wasi_filesize_t)in->st_size, - .st_atim = convert_timespec(&in->st_atim), - .st_mtim = convert_timespec(&in->st_mtim), - .st_ctim = convert_timespec(&in->st_ctim), - }; + return error; } -#endif __wasi_errno_t wasmtime_ssp_fd_filestat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filestat_t *buf) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_GET, 0); + if (error != 0) return error; - int ret; - switch (fo->type) { - default: - { - struct stat sb; - ret = fstat(fd_number(fo), &sb); - convert_stat(&sb, buf); - break; - } - } - buf->st_filetype = fo->type; + error = os_fstat(fo->file_handle, buf); + fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } static void @@ -2400,56 +1892,22 @@ convert_timestamp(__wasi_timestamp_t in, struct timespec *out) out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX; } -#ifndef BH_PLATFORM_WINDOWS -// Converts the provided timestamps and flags to a set of arguments for -// futimens() and utimensat(). -static void -convert_utimens_arguments(__wasi_timestamp_t st_atim, - __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags, struct timespec *ts) -{ - if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) { - ts[0].tv_nsec = UTIME_NOW; - } - else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) { - convert_timestamp(st_atim, &ts[0]); - } - else { - ts[0].tv_nsec = UTIME_OMIT; - } - - if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) { - ts[1].tv_nsec = UTIME_NOW; - } - else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) { - convert_timestamp(st_mtim, &ts[1]); - } - else { - ts[1].tv_nsec = UTIME_OMIT; - } -} -#endif - __wasi_errno_t wasmtime_ssp_fd_filestat_set_size(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t st_size) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct fd_object *fo; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_SIZE, 0); + if (error != 0) return error; - int ret = ftruncate(fd_number(fo), (off_t)st_size); + error = os_ftruncate(fo->file_handle, st_size); fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t @@ -2459,9 +1917,6 @@ wasmtime_ssp_fd_filestat_set_times(wasm_exec_env_t exec_env, __wasi_timestamp_t st_mtim, __wasi_fstflags_t fstflags) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) @@ -2474,15 +1929,11 @@ wasmtime_ssp_fd_filestat_set_times(wasm_exec_env_t exec_env, if (error != 0) return error; - struct timespec ts[2]; - convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); - int ret = futimens(fd_number(fo), ts); + error = os_futimens(fo->file_handle, st_atim, st_mtim, fstflags); fd_object_release(exec_env, fo); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t @@ -2491,40 +1942,19 @@ wasmtime_ssp_path_filestat_get(wasm_exec_env_t exec_env, __wasi_lookupflags_t flags, const char *path, size_t pathlen, __wasi_filestat_t *buf) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access pa; - __wasi_errno_t error = path_get(curfds, &pa, fd, flags, path, pathlen, - __WASI_RIGHT_PATH_FILESTAT_GET, 0, false); + __wasi_errno_t error = + path_get(exec_env, curfds, &pa, fd, flags, path, pathlen, + __WASI_RIGHT_PATH_FILESTAT_GET, 0, false); if (error != 0) return error; - struct stat sb; - int ret = fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); - path_put(&pa); - if (ret < 0) - return convert_errno(errno); - convert_stat(&sb, buf); + error = os_fstatat(pa.fd, pa.path, buf, + pa.follow ? __WASI_LOOKUP_SYMLINK_FOLLOW : 0); - // Convert the file type. In the case of sockets there is no way we - // can easily determine the exact socket type. - if (S_ISBLK(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE; - else if (S_ISCHR(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; - else if (S_ISDIR(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_DIRECTORY; - else if (S_ISFIFO(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; - else if (S_ISLNK(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK; - else if (S_ISREG(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_REGULAR_FILE; - else if (S_ISSOCK(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; - return 0; -#endif + path_put(&pa); + + return error; } __wasi_errno_t @@ -2536,9 +1966,6 @@ wasmtime_ssp_path_filestat_set_times(wasm_exec_env_t exec_env, __wasi_timestamp_t st_mtim, __wasi_fstflags_t fstflags) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) @@ -2553,21 +1980,16 @@ wasmtime_ssp_path_filestat_set_times(wasm_exec_env_t exec_env, struct path_access pa; __wasi_errno_t error = - path_get(curfds, &pa, fd, flags, path, pathlen, + path_get(exec_env, curfds, &pa, fd, flags, path, pathlen, __WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0, false); if (error != 0) return error; - struct timespec ts[2]; - convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); - int ret = - utimensat(pa.fd, pa.path, ts, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + error = os_utimensat(pa.fd, pa.path, st_atim, st_mtim, fstflags, + pa.follow ? __WASI_LOOKUP_SYMLINK_FOLLOW : 0); path_put(&pa); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + return error; } __wasi_errno_t @@ -2576,16 +1998,13 @@ wasmtime_ssp_path_symlink(wasm_exec_env_t exec_env, struct fd_table *curfds, size_t old_path_len, __wasi_fd_t fd, const char *new_path, size_t new_path_len) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else char *target = str_nullterminate(old_path, old_path_len); if (target == NULL) return convert_errno(errno); struct path_access pa; __wasi_errno_t error = - path_get_nofollow(curfds, &pa, fd, new_path, new_path_len, + path_get_nofollow(exec_env, curfds, &pa, fd, new_path, new_path_len, __WASI_RIGHT_PATH_SYMLINK, 0, true); if (error != 0) { wasm_runtime_free(target); @@ -2600,51 +2019,30 @@ wasmtime_ssp_path_symlink(wasm_exec_env_t exec_env, struct fd_table *curfds, } rwlock_unlock(&prestats->lock); - int ret = symlinkat(target, pa.fd, pa.path); + error = os_symlinkat(target, pa.fd, pa.path); + path_put(&pa); wasm_runtime_free(target); - if (ret < 0) - return convert_errno(errno); - return 0; -#endif + + return error; } __wasi_errno_t wasmtime_ssp_path_unlink_file(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, size_t pathlen) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access pa; - __wasi_errno_t error = path_get_nofollow( - curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_UNLINK_FILE, 0, true); - if (error != 0) + __wasi_errno_t error = + path_get_nofollow(exec_env, curfds, &pa, fd, path, pathlen, + __WASI_RIGHT_PATH_UNLINK_FILE, 0, true); + if (error != __WASI_ESUCCESS) return error; - int ret = unlinkat(pa.fd, pa.path, 0); -#ifndef __linux__ - // Non-Linux implementations may return EPERM when attempting to remove a - // directory without REMOVEDIR. While that's what POSIX specifies, it's - // less useful. Adjust this to EISDIR. It doesn't matter that this is not - // atomic with the unlinkat, because if the file is removed and a directory - // is created before fstatat sees it, we're racing with that change anyway - // and unlinkat could have legitimately seen the directory if the race had - // turned out differently. - if (ret < 0 && errno == EPERM) { - struct stat statbuf; - if (fstatat(pa.fd, pa.path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0 - && S_ISDIR(statbuf.st_mode)) { - errno = EISDIR; - } - } -#endif + error = os_unlinkat(pa.fd, pa.path, false); + path_put(&pa); - if (ret < 0) { - return convert_errno(errno); - } - return 0; -#endif + + return error; } __wasi_errno_t @@ -2652,30 +2050,18 @@ wasmtime_ssp_path_remove_directory(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, size_t pathlen) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else struct path_access pa; __wasi_errno_t error = - path_get_nofollow(curfds, &pa, fd, path, pathlen, + path_get_nofollow(exec_env, curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0, true); if (error != 0) return error; - int ret = unlinkat(pa.fd, pa.path, AT_REMOVEDIR); -#ifndef __linux__ - // POSIX permits either EEXIST or ENOTEMPTY when the directory is not empty. - // Map it to ENOTEMPTY. - if (ret < 0 && errno == EEXIST) { - errno = ENOTEMPTY; - } -#endif + error = os_unlinkat(pa.fd, pa.path, true); + path_put(&pa); - if (ret < 0) { - return convert_errno(errno); - } - return 0; -#endif + + return error; } __wasi_errno_t @@ -2802,7 +2188,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error == 0) { // Proper file descriptor on which we can poll(). pfds[i] = (struct pollfd){ - .fd = fd_number(fos[i]), + .fd = fos[i]->file_handle, .events = s->u.type == __WASI_EVENTTYPE_FD_READ ? POLLIN : POLLOUT, @@ -2879,7 +2265,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_filesize_t nbytes = 0; if (in[i].u.type == __WASI_EVENTTYPE_FD_READ) { int l; - if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0) + if (ioctl(fos[i]->file_handle, FIONREAD, &l) == 0) nbytes = (__wasi_filesize_t)l; } if ((pfds[i].revents & POLLNVAL) != 0) { @@ -2953,7 +2339,7 @@ wasi_ssp_sock_accept(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_filetype_t wasi_type; __wasi_rights_t max_base, max_inheriting; struct fd_object *fo; - bh_socket_t new_sock = -1; + bh_socket_t new_sock = os_get_invalid_handle(); int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ACCEPT, 0); @@ -2961,7 +2347,7 @@ wasi_ssp_sock_accept(wasm_exec_env_t exec_env, struct fd_table *curfds, goto fail; } - ret = blocking_op_socket_accept(exec_env, fd_number(fo), &new_sock, NULL, + ret = blocking_op_socket_accept(exec_env, fo->file_handle, &new_sock, NULL, NULL); fd_object_release(exec_env, fo); if (BHT_OK != ret) { @@ -2979,14 +2365,14 @@ wasi_ssp_sock_accept(wasm_exec_env_t exec_env, struct fd_table *curfds, max_inheriting, fd_new); if (error != __WASI_ESUCCESS) { /* released in fd_table_insert_fd() */ - new_sock = -1; + new_sock = os_get_invalid_handle(); goto fail; } return __WASI_ESUCCESS; fail: - if (-1 != new_sock) { + if (os_is_handle_valid(&new_sock)) { os_socket_close(new_sock); } return error; @@ -3005,7 +2391,7 @@ wasi_ssp_sock_addr_local(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != __WASI_ESUCCESS) return error; - ret = os_socket_addr_local(fd_number(fo), &bh_addr); + ret = os_socket_addr_local(fo->file_handle, &bh_addr); fd_object_release(exec_env, fo); if (ret != BHT_OK) { return convert_errno(errno); @@ -3029,7 +2415,7 @@ wasi_ssp_sock_addr_remote(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != __WASI_ESUCCESS) return error; - ret = os_socket_addr_remote(fd_number(fo), &bh_addr); + ret = os_socket_addr_remote(fo->file_handle, &bh_addr); fd_object_release(exec_env, fo); if (ret != BHT_OK) { return convert_errno(errno); @@ -3092,7 +2478,7 @@ wasi_ssp_sock_bind(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != __WASI_ESUCCESS) return error; - ret = os_socket_bind(fd_number(fo), buf, &port); + ret = os_socket_bind(fo->file_handle, buf, &port); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); @@ -3175,7 +2561,7 @@ wasi_ssp_sock_connect(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != __WASI_ESUCCESS) return error; - ret = blocking_op_socket_connect(exec_env, fd_number(fo), buf, + ret = blocking_op_socket_connect(exec_env, fo->file_handle, buf, addr->kind == IPv4 ? addr->addr.ip4.port : addr->addr.ip6.port); fd_object_release(exec_env, fo); @@ -3192,21 +2578,18 @@ wasi_ssp_sock_get_recv_buf_size(wasm_exec_env_t exec_env, __wasi_size_t *size) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval; - socklen_t optlen = sizeof(optval); - - ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, &optlen); + size_t bufsize = 0; + int ret = os_socket_get_recv_buf_size(fo->file_handle, &bufsize); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } - *size = optval; + *size = (__wasi_size_t)bufsize; return __WASI_ESUCCESS; } @@ -3215,23 +2598,20 @@ __wasi_errno_t wasi_ssp_sock_get_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t *reuse) { - struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval; - socklen_t optlen = sizeof(optval); + bool enabled = false; - ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); + int ret = os_socket_get_reuse_addr(fo->file_handle, &enabled); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } - *reuse = optval; + *reuse = (uint8_t)enabled; return __WASI_ESUCCESS; } @@ -3241,28 +2621,19 @@ wasi_ssp_sock_get_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t *reuse) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval; - socklen_t optlen = sizeof(optval); - -#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */ - ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEPORT, &optval, &optlen); -#else - errno = ENOTSUP; - ret = BHT_ERROR; - optval = 0; -#endif /* defined(SO_REUSEPORT) */ + bool enabled = false; + int ret = os_socket_get_reuse_port(fo->file_handle, &enabled); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } - *reuse = optval; + *reuse = (uint8_t)enabled; return __WASI_ESUCCESS; } @@ -3273,21 +2644,19 @@ wasi_ssp_sock_get_send_buf_size(wasm_exec_env_t exec_env, __wasi_size_t *size) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval; - socklen_t optlen = sizeof(optval); + size_t bufsize = 0; + int ret = os_socket_get_send_buf_size(fo->file_handle, &bufsize); - ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, &optlen); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } - *size = optval; + *size = (__wasi_size_t)bufsize; return __WASI_ESUCCESS; } @@ -3303,7 +2672,7 @@ wasi_ssp_sock_listen(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != __WASI_ESUCCESS) return error; - ret = os_socket_listen(fd_number(fo), backlog); + ret = os_socket_listen(fo->file_handle, backlog); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); @@ -3362,15 +2731,12 @@ wasi_ssp_sock_set_recv_buf_size(wasm_exec_env_t exec_env, __wasi_size_t size) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval = size; + int ret = os_socket_set_recv_buf_size(fo->file_handle, size); - ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, - sizeof(optval)); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); @@ -3384,15 +2750,12 @@ wasi_ssp_sock_set_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t reuse) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval = reuse; + int ret = os_socket_set_reuse_addr(fo->file_handle, (bool)reuse); - ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, - sizeof(optval)); fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); @@ -3406,20 +2769,11 @@ wasi_ssp_sock_set_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t reuse) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval = reuse; - -#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */ - ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEPORT, &optval, - sizeof(optval)); -#else - errno = ENOTSUP; - ret = BHT_ERROR; -#endif /* defined(SO_REUSEPORT) */ + int ret = os_socket_set_reuse_port(fo->file_handle, (bool)reuse); fd_object_release(exec_env, fo); if (BHT_OK != ret) { @@ -3435,15 +2789,11 @@ wasi_ssp_sock_set_send_buf_size(wasm_exec_env_t exec_env, __wasi_size_t size) { struct fd_object *fo; - int ret; __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0); if (error != __WASI_ESUCCESS) return error; - int optval = size; - - ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, - sizeof(optval)); + int ret = os_socket_set_send_buf_size(fo->file_handle, size); fd_object_release(exec_env, fo); if (BHT_OK != ret) { @@ -3480,8 +2830,8 @@ wasmtime_ssp_sock_recv_from(wasm_exec_env_t exec_env, struct fd_table *curfds, return error; } - ret = blocking_op_socket_recv_from(exec_env, fd_number(fo), buf, buf_len, 0, - &sockaddr); + ret = blocking_op_socket_recv_from(exec_env, fo->file_handle, buf, buf_len, + 0, &sockaddr); fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); @@ -3507,7 +2857,7 @@ wasmtime_ssp_sock_send(wasm_exec_env_t exec_env, struct fd_table *curfds, return error; } - ret = os_socket_send(fd_number(fo), buf, buf_len); + ret = os_socket_send(fo->file_handle, buf, buf_len); fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); @@ -3545,7 +2895,7 @@ wasmtime_ssp_sock_send_to(wasm_exec_env_t exec_env, struct fd_table *curfds, wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr); - ret = blocking_op_socket_send_to(exec_env, fd_number(fo), buf, buf_len, 0, + ret = blocking_op_socket_send_to(exec_env, fo->file_handle, buf, buf_len, 0, &sockaddr); fd_object_release(exec_env, fo); if (-1 == ret) { @@ -3568,7 +2918,7 @@ wasmtime_ssp_sock_shutdown(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != 0) return error; - ret = os_socket_shutdown(fd_number(fo)); + ret = os_socket_shutdown(fo->file_handle); fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3614,14 +2964,14 @@ wasmtime_ssp_args_sizes_get(struct argv_environ_values *argv_environ, __wasi_errno_t wasmtime_ssp_environ_get(struct argv_environ_values *argv_environ, - char **environ, char *environ_buf) + char **environs, char *environ_buf) { for (size_t i = 0; i < argv_environ->environ_count; ++i) { - environ[i] = + environs[i] = environ_buf + (argv_environ->environ_list[i] - argv_environ->environ_buf); } - environ[argv_environ->environ_count] = NULL; + environs[argv_environ->environ_count] = NULL; bh_memcpy_s(environ_buf, (uint32)argv_environ->environ_buf_size, argv_environ->environ_buf, (uint32)argv_environ->environ_buf_size); @@ -3865,7 +3215,7 @@ addr_pool_destroy(struct addr_pool *addr_pool) error = fd_object_get(curfds, &fo, sock, 0, 0); \ if (error != 0) \ return error; \ - ret = os_socket_##FUNC_NAME(fd_number(fo), option); \ + ret = os_socket_##FUNC_NAME(fo->file_handle, option); \ fd_object_release(exec_env, fo); \ if (BHT_OK != ret) \ return convert_errno(errno); \ @@ -3919,7 +3269,7 @@ wasmtime_ssp_sock_set_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != 0) return error; - ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s); + ret = os_socket_set_linger(fo->file_handle, is_enabled, linger_s); fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3937,7 +3287,7 @@ wasmtime_ssp_sock_get_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, if (error != 0) return error; - ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s); + ret = os_socket_get_linger(fo->file_handle, is_enabled, linger_s); fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3963,7 +3313,7 @@ wasmtime_ssp_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info); is_ipv6 = imr_multiaddr->kind == IPv6; - ret = os_socket_set_ip_add_membership(fd_number(fo), &addr_info, + ret = os_socket_set_ip_add_membership(fo->file_handle, &addr_info, imr_interface, is_ipv6); fd_object_release(exec_env, fo); if (BHT_OK != ret) @@ -3989,7 +3339,7 @@ wasmtime_ssp_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info); is_ipv6 = imr_multiaddr->kind == IPv6; - ret = os_socket_set_ip_drop_membership(fd_number(fo), &addr_info, + ret = os_socket_set_ip_drop_membership(fo->file_handle, &addr_info, imr_interface, is_ipv6); fd_object_release(exec_env, fo); if (BHT_OK != ret) @@ -4010,7 +3360,7 @@ wasmtime_ssp_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, if (error != 0) return error; - ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); + ret = os_socket_set_ip_multicast_loop(fo->file_handle, ipv6, is_enabled); fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -4030,7 +3380,7 @@ wasmtime_ssp_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, if (error != 0) return error; - ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); + ret = os_socket_get_ip_multicast_loop(fo->file_handle, ipv6, is_enabled); fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h index 7a593390a..75ed59784 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h @@ -60,7 +60,8 @@ struct addr_pool { bool fd_table_init(struct fd_table *); bool -fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int); +fd_table_insert_existing(struct fd_table *, __wasi_fd_t, os_file_handle, + bool is_stdio); bool fd_prestats_init(struct fd_prestats *); bool diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index 6ddbd54d7..274979c3b 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -47,38 +47,6 @@ #define CONFIG_HAS_CLOCK_NANOSLEEP 0 #endif -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM) \ - && !defined(_WIN32) -#define CONFIG_HAS_FDATASYNC 1 -#else -#define CONFIG_HAS_FDATASYNC 0 -#endif - -/* - * For NuttX, CONFIG_HAS_ISATTY is provided by its platform header. - * (platform_internal.h) - */ -#ifndef __NuttX__ -#ifndef __CloudABI__ -#define CONFIG_HAS_ISATTY 1 -#else -#define CONFIG_HAS_ISATTY 0 -#endif -#endif - -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) \ - && !defined(__COSMOPOLITAN__) -#define CONFIG_HAS_POSIX_FALLOCATE 1 -#else -#define CONFIG_HAS_POSIX_FALLOCATE 0 -#endif - -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) -#define CONFIG_HAS_PREADV 1 -#else -#define CONFIG_HAS_PREADV 0 -#endif - #if defined(__APPLE__) || defined(__CloudABI__) #define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1 #else @@ -92,32 +60,6 @@ #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0 #endif -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) -#define CONFIG_HAS_PWRITEV 1 -#else -#define CONFIG_HAS_PWRITEV 0 -#endif - -#ifdef __APPLE__ -#define st_atim st_atimespec -#define st_ctim st_ctimespec -#define st_mtim st_mtimespec -#endif - -#if defined(O_DSYNC) -#define CONFIG_HAS_O_DSYNC -#endif - -// POSIX requires O_RSYNC to be defined, but Linux explicitly doesn't support -// it. -#if defined(O_RSYNC) && !defined(__linux__) -#define CONFIG_HAS_O_RSYNC -#endif - -#if defined(O_SYNC) -#define CONFIG_HAS_O_SYNC -#endif - #if !defined(BH_PLATFORM_LINUX_SGX) /* Clang's __GNUC_PREREQ macro has a different meaning than GCC one, so we have to handle this case specially */ @@ -145,10 +87,4 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */ #define CONFIG_HAS_STD_ATOMIC 0 #endif /* end of !defined(BH_PLATFORM_LINUX_SGX) */ -#if !defined(__NuttX__) -#define CONFIG_HAS_D_INO 1 -#else -#define CONFIG_HAS_D_INO 0 -#endif - #endif diff --git a/core/shared/platform/alios/platform_internal.h b/core/shared/platform/alios/platform_internal.h index f6a4ba11e..7e9740e6b 100644 --- a/core/shared/platform/alios/platform_internal.h +++ b/core/shared/platform/alios/platform_internal.h @@ -64,4 +64,8 @@ int signbit(double x); int isnan(double x); /* clang-format on */ +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #endif /* end of _BH_PLATFORM_H */ diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index b8574b1aa..d59daf144 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -146,6 +146,10 @@ preadv(int __fd, const struct iovec *__iov, int __count, off_t __offset); ssize_t pwritev(int __fd, const struct iovec *__iov, int __count, off_t __offset); +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/common/libc-util/libc_errno.c b/core/shared/platform/common/libc-util/libc_errno.c new file mode 100644 index 000000000..e6c26c839 --- /dev/null +++ b/core/shared/platform/common/libc-util/libc_errno.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "errno.h" +#include "libc_errno.h" + +__wasi_errno_t +convert_errno(int error) +{ + // The C standard library only requires EDOM, EILSEQ and ERANGE to be + // defined. Other error codes are POSIX-specific and hence may or may + // not be available on non-POSIX platforms. + __wasi_errno_t code = __WASI_ENOSYS; +#define X(v) \ + case v: \ + code = __WASI_##v; \ + break; + switch (error) { + X(EDOM) + X(EILSEQ) + X(ERANGE) +#ifdef E2BIG + X(E2BIG) +#endif +#ifdef EACCES + X(EACCES) +#endif +#ifdef EADDRINUSE + X(EADDRINUSE) +#endif +#ifdef EADDRNOTAVAIL + X(EADDRNOTAVAIL) +#endif +#ifdef EAFNOSUPPORT + X(EAFNOSUPPORT) +#endif +#ifdef EAGAIN + X(EAGAIN) +#endif +#ifdef EALREADY + X(EALREADY) +#endif +#ifdef EBADF + X(EBADF) +#endif +#ifdef EBADMSG + X(EBADMSG) +#endif +#ifdef EBUSY + X(EBUSY) +#endif +#ifdef ECANCELED + X(ECANCELED) +#endif +#ifdef ECHILD + X(ECHILD) +#endif +#ifdef ECONNABORTED + X(ECONNABORTED) +#endif +#ifdef ECONNREFUSED + X(ECONNREFUSED) +#endif +#ifdef ECONNRESET + X(ECONNRESET) +#endif +#ifdef EDEADLK + X(EDEADLK) +#endif +#ifdef EDESTADDRREQ + X(EDESTADDRREQ) +#endif +#ifdef EDQUOT + X(EDQUOT) +#endif +#ifdef EEXIST + X(EEXIST) +#endif +#ifdef EFAULT + X(EFAULT) +#endif +#ifdef EFBIG + X(EFBIG) +#endif +#ifdef EHOSTUNREACH + X(EHOSTUNREACH) +#endif +#ifdef EIDRM + X(EIDRM) +#endif +#ifdef EINPROGRESS + X(EINPROGRESS) +#endif +#ifdef EINTR + X(EINTR) +#endif +#ifdef EINVAL + X(EINVAL) +#endif +#ifdef EIO + X(EIO) +#endif +#ifdef EISCONN + X(EISCONN) +#endif +#ifdef EISDIR + X(EISDIR) +#endif +#ifdef ELOOP + X(ELOOP) +#endif +#ifdef EMFILE + X(EMFILE) +#endif +#ifdef EMLINK + X(EMLINK) +#endif +#ifdef EMSGSIZE + X(EMSGSIZE) +#endif +#ifdef EMULTIHOP + X(EMULTIHOP) +#endif +#ifdef ENAMETOOLONG + X(ENAMETOOLONG) +#endif +#ifdef ENETDOWN + X(ENETDOWN) +#endif +#ifdef ENETRESET + X(ENETRESET) +#endif +#ifdef ENETUNREACH + X(ENETUNREACH) +#endif +#ifdef ENFILE + X(ENFILE) +#endif +#ifdef ENOBUFS + X(ENOBUFS) +#endif +#ifdef ENODEV + X(ENODEV) +#endif +#ifdef ENOENT + X(ENOENT) +#endif +#ifdef ENOEXEC + X(ENOEXEC) +#endif +#ifdef ENOLCK + X(ENOLCK) +#endif +#ifdef ENOLINK + X(ENOLINK) +#endif +#ifdef ENOMEM + X(ENOMEM) +#endif +#ifdef ENOMSG + X(ENOMSG) +#endif +#ifdef ENOPROTOOPT + X(ENOPROTOOPT) +#endif +#ifdef ENOSPC + X(ENOSPC) +#endif +#ifdef ENOSYS + X(ENOSYS) +#endif +#ifdef ENOTCAPABLE + X(ENOTCAPABLE) +#endif +#ifdef ENOTCONN + X(ENOTCONN) +#endif +#ifdef ENOTDIR + X(ENOTDIR) +#endif +#ifdef ENOTEMPTY + X(ENOTEMPTY) +#endif +#ifdef ENOTRECOVERABLE + X(ENOTRECOVERABLE) +#endif +#ifdef ENOTSOCK + X(ENOTSOCK) +#endif +#ifdef ENOTSUP + X(ENOTSUP) +#endif +#ifdef ENOTTY + X(ENOTTY) +#endif +#ifdef ENXIO + X(ENXIO) +#endif +#ifdef EOVERFLOW + X(EOVERFLOW) +#endif +#ifdef EOWNERDEAD + X(EOWNERDEAD) +#endif +#ifdef EPERM + X(EPERM) +#endif +#ifdef EPIPE + X(EPIPE) +#endif +#ifdef EPROTO + X(EPROTO) +#endif +#ifdef EPROTONOSUPPORT + X(EPROTONOSUPPORT) +#endif +#ifdef EPROTOTYPE + X(EPROTOTYPE) +#endif +#ifdef EROFS + X(EROFS) +#endif +#ifdef ESPIPE + X(ESPIPE) +#endif +#ifdef ESRCH + X(ESRCH) +#endif +#ifdef ESTALE + X(ESTALE) +#endif +#ifdef ETIMEDOUT + X(ETIMEDOUT) +#endif +#ifdef ETXTBSY + X(ETXTBSY) +#endif +#ifdef EXDEV + X(EXDEV) +#endif + default: +#ifdef EOPNOTSUPP + if (error == EOPNOTSUPP) + code = __WASI_ENOTSUP; +#endif +#ifdef EWOULDBLOCK + if (error == EWOULDBLOCK) + code = __WASI_EAGAIN; +#endif + break; + } +#undef X + return code; +} \ No newline at end of file diff --git a/core/shared/platform/common/libc-util/libc_errno.h b/core/shared/platform/common/libc-util/libc_errno.h new file mode 100644 index 000000000..d136c0cf3 --- /dev/null +++ b/core/shared/platform/common/libc-util/libc_errno.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_ERRNO_H +#define WASI_ERRNO_H + +#include "platform_wasi.h" + +// Converts an errno error code to a WASI error code. +__wasi_errno_t +convert_errno(int error); + +#endif /* end of WASI_ERRNO_H */ \ No newline at end of file diff --git a/core/shared/platform/common/libc-util/platform_common_libc_util.cmake b/core/shared/platform/common/libc-util/platform_common_libc_util.cmake new file mode 100644 index 000000000..a7c7645ce --- /dev/null +++ b/core/shared/platform/common/libc-util/platform_common_libc_util.cmake @@ -0,0 +1,8 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_COMMON_LIBC_UTIL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${PLATFORM_COMMON_LIBC_UTIL_DIR}) + +file (GLOB_RECURSE PLATFORM_COMMON_LIBC_UTIL_SOURCE ${PLATFORM_COMMON_LIBC_UTIL_DIR}/*.c) \ No newline at end of file diff --git a/core/shared/platform/common/posix/platform_api_posix.cmake b/core/shared/platform/common/posix/platform_api_posix.cmake index 4abefff1e..3de3e189e 100644 --- a/core/shared/platform/common/posix/platform_api_posix.cmake +++ b/core/shared/platform/common/posix/platform_api_posix.cmake @@ -5,4 +5,11 @@ set (PLATFORM_COMMON_POSIX_DIR ${CMAKE_CURRENT_LIST_DIR}) file (GLOB_RECURSE source_all ${PLATFORM_COMMON_POSIX_DIR}/*.c) +if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1) + list(REMOVE_ITEM source_all ${PLATFORM_COMMON_POSIX_DIR}/posix_file.c) +else() + include (${CMAKE_CURRENT_LIST_DIR}/../libc-util/platform_common_libc_util.cmake) + set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) +endif() + set (PLATFORM_COMMON_POSIX_SOURCE ${source_all} ) diff --git a/core/shared/platform/common/posix/posix_file.c b/core/shared/platform/common/posix/posix_file.c new file mode 100644 index 000000000..a0005b592 --- /dev/null +++ b/core/shared/platform/common/posix/posix_file.c @@ -0,0 +1,1013 @@ +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" +#include "libc_errno.h" +#include + +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#define CONFIG_HAS_PWRITEV 1 +#define CONFIG_HAS_PREADV 1 +#else +#define CONFIG_HAS_PWRITEV 0 +#define CONFIG_HAS_PREADV 0 +#endif + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM) +#define CONFIG_HAS_FDATASYNC 1 +#else +#define CONFIG_HAS_FDATASYNC 0 +#endif + +/* + * For NuttX, CONFIG_HAS_ISATTY is provided by its platform header. + * (platform_internal.h) + */ +#if !defined(__NuttX__) +#define CONFIG_HAS_D_INO 1 +#define CONFIG_HAS_ISATTY 1 +#else +#define CONFIG_HAS_D_INO 0 +#endif + +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(__COSMOPOLITAN__) +#define CONFIG_HAS_POSIX_FALLOCATE 1 +#else +#define CONFIG_HAS_POSIX_FALLOCATE 0 +#endif + +#if defined(O_DSYNC) +#define CONFIG_HAS_O_DSYNC +#endif + +// POSIX requires O_RSYNC to be defined, but Linux explicitly doesn't support +// it. +#if defined(O_RSYNC) && !defined(__linux__) +#define CONFIG_HAS_O_RSYNC +#endif + +#if defined(O_SYNC) +#define CONFIG_HAS_O_SYNC +#endif + +// Converts a POSIX timespec to a WASI timestamp. +static __wasi_timestamp_t +convert_timespec(const struct timespec *ts) +{ + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + + (__wasi_timestamp_t)ts->tv_nsec; +} + +// Converts a POSIX stat structure to a WASI filestat structure +static void +convert_stat(os_file_handle handle, const struct stat *in, + __wasi_filestat_t *out) +{ + out->st_dev = in->st_dev; + out->st_ino = in->st_ino; + out->st_nlink = (__wasi_linkcount_t)in->st_nlink; + out->st_size = (__wasi_filesize_t)in->st_size; +#ifdef __APPLE__ + out->st_atim = convert_timespec(&in->st_atimespec); + out->st_mtim = convert_timespec(&in->st_mtimespec); + out->st_ctim = convert_timespec(&in->st_ctimespec); +#else + out->st_atim = convert_timespec(&in->st_atim); + out->st_mtim = convert_timespec(&in->st_mtim); + out->st_ctim = convert_timespec(&in->st_ctim); +#endif + + // Convert the file type. In the case of sockets there is no way we + // can easily determine the exact socket type. + if (S_ISBLK(in->st_mode)) { + out->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE; + } + else if (S_ISCHR(in->st_mode)) { + out->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; + } + else if (S_ISDIR(in->st_mode)) { + out->st_filetype = __WASI_FILETYPE_DIRECTORY; + } + else if (S_ISFIFO(in->st_mode)) { + out->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; + } + else if (S_ISLNK(in->st_mode)) { + out->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK; + } + else if (S_ISREG(in->st_mode)) { + out->st_filetype = __WASI_FILETYPE_REGULAR_FILE; + } + else if (S_ISSOCK(in->st_mode)) { + int socktype; + socklen_t socktypelen = sizeof(socktype); + + if (getsockopt(handle, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) + < 0) { + out->st_filetype = __WASI_FILETYPE_UNKNOWN; + return; + } + + switch (socktype) { + case SOCK_DGRAM: + out->st_filetype = __WASI_FILETYPE_SOCKET_DGRAM; + break; + case SOCK_STREAM: + out->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; + break; + default: + out->st_filetype = __WASI_FILETYPE_UNKNOWN; + return; + } + } + else { + out->st_filetype = __WASI_FILETYPE_UNKNOWN; + } +} + +static void +convert_timestamp(__wasi_timestamp_t in, struct timespec *out) +{ + // Store sub-second remainder. +#if defined(__SYSCALL_SLONG_TYPE) + out->tv_nsec = (__SYSCALL_SLONG_TYPE)(in % 1000000000); +#else + out->tv_nsec = (long)(in % 1000000000); +#endif + in /= 1000000000; + + // Clamp to the maximum in case it would overflow our system's time_t. + out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX; +} + +// Converts the provided timestamps and flags to a set of arguments for +// futimens() and utimensat(). +static void +convert_utimens_arguments(__wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags, struct timespec *ts) +{ + if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) { + ts[0].tv_nsec = UTIME_NOW; + } + else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) { + convert_timestamp(st_atim, &ts[0]); + } + else { + ts[0].tv_nsec = UTIME_OMIT; + } + + if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) { + ts[1].tv_nsec = UTIME_NOW; + } + else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) { + convert_timestamp(st_mtim, &ts[1]); + } + else { + ts[1].tv_nsec = UTIME_OMIT; + } +} + +__wasi_errno_t +os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf) +{ + struct stat stat_buf; + int ret = fstat(handle, &stat_buf); + + if (ret < 0) + return convert_errno(errno); + + convert_stat(handle, &stat_buf, buf); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_fstatat(os_file_handle handle, const char *path, + struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags) +{ + struct stat stat_buf; + int ret = fstatat(handle, path, &stat_buf, + (lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) + ? AT_SYMLINK_FOLLOW + : AT_SYMLINK_NOFOLLOW); + + if (ret < 0) + return convert_errno(errno); + + convert_stat(handle, &stat_buf, buf); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) +{ + int ret = fcntl(handle, F_GETFL); + + if (ret < 0) + return convert_errno(errno); + + *flags = 0; + + if ((ret & O_APPEND) != 0) + *flags |= __WASI_FDFLAG_APPEND; +#ifdef CONFIG_HAS_O_DSYNC + if ((ret & O_DSYNC) != 0) + *flags |= __WASI_FDFLAG_DSYNC; +#endif + if ((ret & O_NONBLOCK) != 0) + *flags |= __WASI_FDFLAG_NONBLOCK; +#ifdef CONFIG_HAS_O_RSYNC + if ((ret & O_RSYNC) != 0) + *flags |= __WASI_FDFLAG_RSYNC; +#endif +#ifdef CONFIG_HAS_O_SYNC + if ((ret & O_SYNC) != 0) + *flags |= __WASI_FDFLAG_SYNC; +#endif + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags) +{ + int fcntl_flags = 0; + + if ((flags & __WASI_FDFLAG_APPEND) != 0) + fcntl_flags |= O_APPEND; + if ((flags & __WASI_FDFLAG_DSYNC) != 0) +#ifdef CONFIG_HAS_O_DSYNC + fcntl_flags |= O_DSYNC; +#else + return __WASI_ENOTSUP; +#endif + if ((flags & __WASI_FDFLAG_NONBLOCK) != 0) + fcntl_flags |= O_NONBLOCK; + if ((flags & __WASI_FDFLAG_RSYNC) != 0) +#ifdef CONFIG_HAS_O_RSYNC + fcntl_flags |= O_RSYNC; +#else + return __WASI_ENOTSUP; +#endif + if ((flags & __WASI_FDFLAG_SYNC) != 0) +#ifdef CONFIG_HAS_O_SYNC + fcntl_flags |= O_SYNC; +#else + return __WASI_ENOTSUP; +#endif + + int ret = fcntl(handle, F_SETFL, fcntl_flags); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_fdatasync(os_file_handle handle) +{ +#if CONFIG_HAS_FDATASYNC + int ret = fdatasync(handle); +#else + int ret = fsync(handle); +#endif + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_fsync(os_file_handle handle) +{ + int ret = fsync(handle); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_open_preopendir(const char *path, os_file_handle *out) +{ + + int fd = open(path, O_RDONLY | O_DIRECTORY, 0); + + if (fd < 0) + return convert_errno(errno); + + *out = fd; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, + __wasi_fdflags_t fs_flags, __wasi_lookupflags_t lookup_flags, + wasi_libc_file_access_mode read_write_mode, os_file_handle *out) +{ + int open_flags = 0; + + // Convert open flags. + if ((oflags & __WASI_O_CREAT) != 0) { + open_flags |= O_CREAT; + } + if ((oflags & __WASI_O_DIRECTORY) != 0) + open_flags |= O_DIRECTORY; + if ((oflags & __WASI_O_EXCL) != 0) + open_flags |= O_EXCL; + if ((oflags & __WASI_O_TRUNC) != 0) { + open_flags |= O_TRUNC; + } + + // Convert file descriptor flags. + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) + open_flags |= O_APPEND; + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { +#ifdef CONFIG_HAS_O_DSYNC + open_flags |= O_DSYNC; +#else + return __WASI_ENOTSUP; +#endif + } + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + open_flags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { +#ifdef CONFIG_HAS_O_RSYNC + open_flags |= O_RSYNC; +#else + return __WASI_ENOTSUP; +#endif + } + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { +#ifdef CONFIG_HAS_O_SYNC + open_flags |= O_SYNC; +#else + return __WASI_ENOTSUP; +#endif + } + + if ((lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) == 0) { + open_flags |= O_NOFOLLOW; + } + + switch (read_write_mode) { + case WASI_LIBC_ACCESS_MODE_READ_WRITE: + open_flags |= O_RDWR; + break; + case WASI_LIBC_ACCESS_MODE_READ_ONLY: + open_flags |= O_RDONLY; + break; + case WASI_LIBC_ACCESS_MODE_WRITE_ONLY: + open_flags |= O_WRONLY; + break; + default: + return __WASI_EINVAL; + } + + int fd = openat(handle, path, open_flags, 0666); + + if (fd < 0) { + int openat_errno = errno; + // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. + if (openat_errno == ENXIO) { + struct stat sb; + int ret = fstatat(fd, path, &sb, + (lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) + ? 0 + : AT_SYMLINK_NOFOLLOW); + return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP + : __WASI_ENXIO; + } + // Linux returns ENOTDIR instead of ELOOP when using + // O_NOFOLLOW|O_DIRECTORY on a symlink. + if (openat_errno == ENOTDIR + && (open_flags & (O_NOFOLLOW | O_DIRECTORY)) != 0) { + struct stat sb; + int ret = fstatat(fd, path, &sb, AT_SYMLINK_NOFOLLOW); + if (S_ISLNK(sb.st_mode)) { + return __WASI_ELOOP; + } + (void)ret; + } + // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on + // a symlink. + if ((lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) == 0 + && openat_errno == EMLINK) + return __WASI_ELOOP; + + return convert_errno(openat_errno); + } + + *out = fd; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_file_get_access_mode(os_file_handle handle, + wasi_libc_file_access_mode *access_mode) +{ + int ret = fcntl(handle, F_GETFL, 0); + + if (ret < 0) + return convert_errno(errno); + + switch (ret & O_ACCMODE) { + case O_RDONLY: + *access_mode = WASI_LIBC_ACCESS_MODE_READ_ONLY; + break; + case O_WRONLY: + *access_mode = WASI_LIBC_ACCESS_MODE_WRITE_ONLY; + break; + case O_RDWR: + *access_mode = WASI_LIBC_ACCESS_MODE_READ_WRITE; + break; + default: + return __WASI_EINVAL; + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_close(os_file_handle handle, bool is_stdio) +{ + if (is_stdio) + return __WASI_ESUCCESS; + + int ret = close(handle); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nread) +{ +#if CONFIG_HAS_PREADV + ssize_t len = + preadv(handle, (const struct iovec *)iov, (int)iovcnt, (off_t)offset); + if (len < 0) + return convert_errno(errno); + + *nread = (size_t)len; + return __WASI_ESUCCESS; +#else + if (iovcnt == 1) { + ssize_t len = pread(handle, iov->buf, iov->buf_len, offset); + + if (len < 0) + return convert_errno(errno); + + *nread = len; + return __WASI_ESUCCESS; + } + + // Allocate a single buffer to fit all data. + size_t totalsize = 0; + for (size_t i = 0; i < iovcnt; ++i) + totalsize += iov[i].buf_len; + + char *buf = BH_MALLOC(totalsize); + + if (buf == NULL) { + return __WASI_ENOMEM; + } + + // Perform a single read operation. + ssize_t len = pread(handle, buf, totalsize, offset); + + if (len < 0) { + BH_FREE(buf); + return convert_errno(errno); + } + + // Copy data back to vectors. + size_t bufoff = 0; + for (size_t i = 0; i < iovcnt; ++i) { + if (bufoff + iov[i].buf_len < (size_t)len) { + memcpy(iov[i].buf, buf + bufoff, iov[i].buf_len); + bufoff += iov[i].buf_len; + } + else { + memcpy(iov[i].buf, buf + bufoff, len - bufoff); + break; + } + } + BH_FREE(buf); + *nread = len; + + return __WASI_ESUCCESS; +#endif +} + +__wasi_errno_t +os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + if (iovcnt == 0) + return __WASI_EINVAL; + + ssize_t len = 0; +#if CONFIG_HAS_PWRITEV + len = + pwritev(handle, (const struct iovec *)iov, (int)iovcnt, (off_t)offset); +#else + if (iovcnt == 1) { + len = pwrite(handle, iov->buf, iov->buf_len, offset); + } + else { + // Allocate a single buffer to fit all data. + size_t totalsize = 0; + for (size_t i = 0; i < iovcnt; ++i) + totalsize += iov[i].buf_len; + char *buf = BH_MALLOC(totalsize); + if (buf == NULL) { + return __WASI_ENOMEM; + } + size_t bufoff = 0; + for (size_t i = 0; i < iovcnt; ++i) { + memcpy(buf + bufoff, iov[i].buf, iov[i].buf_len); + bufoff += iov[i].buf_len; + } + + // Perform a single write operation. + len = pwrite(handle, buf, totalsize, offset); + BH_FREE(buf); + } +#endif + if (len < 0) + return convert_errno(errno); + + *nwritten = (size_t)len; + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + size_t *nread) +{ + ssize_t len = readv(handle, (const struct iovec *)iov, (int)iovcnt); + + if (len < 0) + return convert_errno(errno); + + *nread = (size_t)len; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + size_t *nwritten) +{ + ssize_t len = writev(handle, (const struct iovec *)iov, (int)iovcnt); + + if (len < 0) + return convert_errno(errno); + + *nwritten = (size_t)len; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_fallocate(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length) +{ +#if CONFIG_HAS_POSIX_FALLOCATE + int ret = posix_fallocate(handle, (off_t)offset, (off_t)length); +#else + // At least ensure that the file is grown to the right size. + // TODO(ed): See if this can somehow be implemented without any race + // conditions. We may end up shrinking the file right now. + struct stat sb; + int ret = fstat(handle, &sb); + off_t newsize = (off_t)(offset + length); + + if (ret == 0 && sb.st_size < newsize) + ret = ftruncate(handle, newsize); +#endif + + if (ret != 0) + return convert_errno(ret); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_ftruncate(os_file_handle handle, __wasi_filesize_t size) +{ + int ret = ftruncate(handle, (off_t)size); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags) +{ + struct timespec ts[2]; + convert_utimens_arguments(access_time, modification_time, fstflags, ts); + + int ret = futimens(handle, ts); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_utimensat(os_file_handle handle, const char *path, + __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, + __wasi_lookupflags_t lookup_flags) +{ + struct timespec ts[2]; + convert_utimens_arguments(access_time, modification_time, fstflags, ts); + + int ret = utimensat(handle, path, ts, + (lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) + ? 0 + : AT_SYMLINK_NOFOLLOW); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_readlinkat(os_file_handle handle, const char *path, char *buf, + size_t bufsize, size_t *nread) +{ + // Linux requires that the buffer size is positive. whereas POSIX does + // not. Use a fake buffer to store the results if the size is zero. + char fakebuf[1]; + ssize_t len = readlinkat(handle, path, bufsize == 0 ? fakebuf : buf, + bufsize == 0 ? sizeof(fakebuf) : bufsize); + + if (len < 0) + return convert_errno(errno); + + *nread = (size_t)len < bufsize ? (size_t)len : bufsize; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_linkat(os_file_handle from_handle, const char *from_path, + os_file_handle to_handle, const char *to_path, + __wasi_lookupflags_t lookup_flags) +{ + int ret = linkat( + from_handle, from_path, to_handle, to_path, + (lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) ? AT_SYMLINK_FOLLOW : 0); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path) +{ + int ret = symlinkat(old_path, handle, new_path); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_mkdirat(os_file_handle handle, const char *path) +{ + int ret = mkdirat(handle, path, 0777); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_renameat(os_file_handle old_handle, const char *old_path, + os_file_handle new_handle, const char *new_path) +{ + + int ret = renameat(old_handle, old_path, new_handle, new_path); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_unlinkat(os_file_handle handle, const char *path, bool is_dir) +{ + int ret = unlinkat(handle, path, is_dir ? AT_REMOVEDIR : 0); + +#ifndef __linux__ + if (ret < 0) { + // Non-Linux implementations may return EPERM when attempting to remove + // a directory without REMOVEDIR. While that's what POSIX specifies, + // it's less useful. Adjust this to EISDIR. It doesn't matter that this + // is not atomic with the unlinkat, because if the file is removed and a + // directory is created before fstatat sees it, we're racing with that + // change anyway and unlinkat could have legitimately seen the directory + // if the race had turned out differently. + if (errno == EPERM) { + struct stat statbuf; + if (fstatat(handle, path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0 + && S_ISDIR(statbuf.st_mode)) { + errno = EISDIR; + } + } + // POSIX permits either EEXIST or ENOTEMPTY when the directory is not + // empty. Map it to ENOTEMPTY. + else if (errno == EEXIST) { + errno = ENOTEMPTY; + } + + return convert_errno(errno); + } +#endif + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_lseek(os_file_handle handle, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *new_offset) +{ + int nwhence; + + switch (whence) { + case __WASI_WHENCE_CUR: + nwhence = SEEK_CUR; + break; + case __WASI_WHENCE_END: + nwhence = SEEK_END; + break; + case __WASI_WHENCE_SET: + nwhence = SEEK_SET; + break; + default: + return __WASI_EINVAL; + } + + off_t ret = lseek(handle, offset, nwhence); + + if (ret < 0) + return convert_errno(errno); + + *new_offset = (__wasi_filesize_t)ret; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_fadvise(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length, __wasi_advice_t advice) +{ +#ifdef POSIX_FADV_NORMAL + int nadvice; + switch (advice) { + case __WASI_ADVICE_DONTNEED: + nadvice = POSIX_FADV_DONTNEED; + break; + case __WASI_ADVICE_NOREUSE: + nadvice = POSIX_FADV_NOREUSE; + break; + case __WASI_ADVICE_NORMAL: + nadvice = POSIX_FADV_NORMAL; + break; + case __WASI_ADVICE_RANDOM: + nadvice = POSIX_FADV_RANDOM; + break; + case __WASI_ADVICE_SEQUENTIAL: + nadvice = POSIX_FADV_SEQUENTIAL; + break; + case __WASI_ADVICE_WILLNEED: + nadvice = POSIX_FADV_WILLNEED; + break; + default: + return __WASI_EINVAL; + } + + int ret = posix_fadvise(handle, (off_t)offset, (off_t)length, nadvice); + + if (ret < 0) + return convert_errno(ret); + + return __WASI_ESUCCESS; +#else + // Advisory information can be safely ignored if not supported + switch (advice) { + case __WASI_ADVICE_DONTNEED: + case __WASI_ADVICE_NOREUSE: + case __WASI_ADVICE_NORMAL: + case __WASI_ADVICE_RANDOM: + case __WASI_ADVICE_SEQUENTIAL: + case __WASI_ADVICE_WILLNEED: + return __WASI_ESUCCESS; + default: + return __WASI_EINVAL; + } +#endif +} + +__wasi_errno_t +os_isatty(os_file_handle handle) +{ +#if CONFIG_HAS_ISATTY + int ret = isatty(handle); + + if (ret == 1) + return __WASI_ESUCCESS; + + return __WASI_ENOTTY; +#else + return __WASI_ENOTSUP; +#endif +} + +os_file_handle +os_convert_stdin_handle(os_raw_file_handle raw_stdin) +{ +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + return raw_stdin >= 0 ? raw_stdin : STDIN_FILENO; +} + +os_file_handle +os_convert_stdout_handle(os_raw_file_handle raw_stdout) +{ +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + return raw_stdout >= 0 ? raw_stdout : STDOUT_FILENO; +} + +os_file_handle +os_convert_stderr_handle(os_raw_file_handle raw_stderr) +{ +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + return raw_stderr >= 0 ? raw_stderr : STDERR_FILENO; +} + +__wasi_errno_t +os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream) +{ + *dir_stream = fdopendir(handle); + + if (*dir_stream == NULL) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_rewinddir(os_dir_stream dir_stream) +{ + rewinddir(dir_stream); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) +{ + seekdir(dir_stream, (long)position); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, + const char **d_name) +{ + errno = 0; + + struct dirent *dent = readdir(dir_stream); + + if (dent == NULL) { + *d_name = NULL; + return convert_errno(errno); + } + + long offset = (__wasi_dircookie_t)telldir(dir_stream); + + size_t namlen = strlen(dent->d_name); + + *d_name = dent->d_name; + entry->d_next = offset; + entry->d_namlen = (__wasi_dirnamlen_t)namlen; +#if CONFIG_HAS_D_INO + entry->d_ino = dent->d_ino; +#else + entry->d_ino = 0; +#endif + + switch (dent->d_type) { + case DT_BLK: + entry->d_type = __WASI_FILETYPE_BLOCK_DEVICE; + break; + case DT_CHR: + entry->d_type = __WASI_FILETYPE_CHARACTER_DEVICE; + break; + case DT_DIR: + entry->d_type = __WASI_FILETYPE_DIRECTORY; + break; + case DT_FIFO: + entry->d_type = __WASI_FILETYPE_SOCKET_STREAM; + break; + case DT_LNK: + entry->d_type = __WASI_FILETYPE_SYMBOLIC_LINK; + break; + case DT_REG: + entry->d_type = __WASI_FILETYPE_REGULAR_FILE; + break; +#ifdef DT_SOCK + case DT_SOCK: + // Technically not correct, but good enough. + entry->d_type = __WASI_FILETYPE_SOCKET_STREAM; + break; +#endif + default: + entry->d_type = __WASI_FILETYPE_UNKNOWN; + break; + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +os_closedir(os_dir_stream dir_stream) +{ + int ret = closedir(dir_stream); + + if (ret < 0) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +os_file_handle +os_get_invalid_handle() +{ + return -1; +} + +os_dir_stream +os_get_invalid_dir_stream() +{ + return NULL; +} + +bool +os_is_dir_stream_valid(os_dir_stream *dir_stream) +{ + assert(dir_stream != NULL); + + return *dir_stream != NULL; +} + +bool +os_is_handle_valid(os_file_handle *handle) +{ + assert(handle != NULL); + + return *handle > -1; +} + +char * +os_realpath(const char *path, char *resolved_path) +{ + return realpath(path, resolved_path); +} \ No newline at end of file diff --git a/core/shared/platform/cosmopolitan/platform_internal.h b/core/shared/platform/cosmopolitan/platform_internal.h index ed2545436..02cd78be4 100644 --- a/core/shared/platform/cosmopolitan/platform_internal.h +++ b/core/shared/platform/cosmopolitan/platform_internal.h @@ -63,6 +63,10 @@ typedef sem_t korp_sem; #define bh_socket_t int +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #if WASM_DISABLE_WRITE_GS_BASE == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) #define os_writegsbase(base_addr) \ diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index ea3daf629..8cbaf652e 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -109,6 +109,10 @@ os_sigreturn(); void os_set_signal_number_for_blocking_op(int signo); +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/esp-idf/platform_internal.h b/core/shared/platform/esp-idf/platform_internal.h index 2fe3b0cc9..6c8fa8e62 100644 --- a/core/shared/platform/esp-idf/platform_internal.h +++ b/core/shared/platform/esp-idf/platform_internal.h @@ -109,6 +109,10 @@ typedef unsigned int korp_sem; #define DT_LNK DTYPE_LINK #define DT_SOCK DTYPE_SOCK +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 58292d16a..5f9b54362 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -66,6 +66,10 @@ typedef sem_t korp_sem; #define bh_socket_t int +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 9a666ce51..e40ddfd05 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -7,6 +7,7 @@ #define PLATFORM_API_EXTENSION_H #include "platform_common.h" +#include "platform_wasi.h" /** * The related data structures should be defined * in platform_internal.h diff --git a/core/shared/platform/include/platform_wasi.h b/core/shared/platform/include/platform_wasi.h new file mode 100644 index 000000000..3798a9e76 --- /dev/null +++ b/core/shared/platform/include/platform_wasi.h @@ -0,0 +1,1100 @@ +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/* + * This file declares the WASI interface as well as optional filesystem + * functions which platforms would need to implement to support WASI libc + * filesystem operations. The definitions of types, macros and structures in + * this file should be consistent with those in wasi-libc: + * https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/wasi/api.h + */ + +#ifndef _PLATFORM_WASI_H +#define _PLATFORM_WASI_H + +#include "platform_common.h" +#include "platform_internal.h" + +/* clang-format off */ + +#ifdef __cplusplus +#ifndef _Static_assert +#define _Static_assert static_assert +#endif /* _Static_assert */ + +#ifndef _Alignof +#define _Alignof alignof +#endif /* _Alignof */ + +extern "C" { +#endif + +/* There is no need to check the WASI layout if we're using uvwasi or libc-wasi + * is not enabled at all. */ +#if WASM_ENABLE_UVWASI != 0 || WASM_ENABLE_LIBC_WASI == 0 +#define assert_wasi_layout(expr, message) /* nothing */ +#else +#define assert_wasi_layout(expr, message) _Static_assert(expr, message) +#endif + +assert_wasi_layout(_Alignof(int8_t) == 1, "non-wasi data layout"); +assert_wasi_layout(_Alignof(uint8_t) == 1, "non-wasi data layout"); +assert_wasi_layout(_Alignof(int16_t) == 2, "non-wasi data layout"); +assert_wasi_layout(_Alignof(uint16_t) == 2, "non-wasi data layout"); +assert_wasi_layout(_Alignof(int32_t) == 4, "non-wasi data layout"); +assert_wasi_layout(_Alignof(uint32_t) == 4, "non-wasi data layout"); +#if 0 +assert_wasi_layout(_Alignof(int64_t) == 8, "non-wasi data layout"); +assert_wasi_layout(_Alignof(uint64_t) == 8, "non-wasi data layout"); +#endif + +typedef uint32_t __wasi_size_t; +assert_wasi_layout(_Alignof(__wasi_size_t) == 4, "non-wasi data layout"); + +typedef uint8_t __wasi_advice_t; +#define __WASI_ADVICE_NORMAL (0) +#define __WASI_ADVICE_SEQUENTIAL (1) +#define __WASI_ADVICE_RANDOM (2) +#define __WASI_ADVICE_WILLNEED (3) +#define __WASI_ADVICE_DONTNEED (4) +#define __WASI_ADVICE_NOREUSE (5) + +typedef uint32_t __wasi_clockid_t; +#define __WASI_CLOCK_REALTIME (0) +#define __WASI_CLOCK_MONOTONIC (1) +#define __WASI_CLOCK_PROCESS_CPUTIME_ID (2) +#define __WASI_CLOCK_THREAD_CPUTIME_ID (3) + +typedef uint64_t __wasi_device_t; + +typedef uint64_t __wasi_dircookie_t; +#define __WASI_DIRCOOKIE_START (0) + +typedef uint32_t __wasi_dirnamlen_t; + +typedef uint16_t __wasi_errno_t; +#define __WASI_ESUCCESS (0) +#define __WASI_E2BIG (1) +#define __WASI_EACCES (2) +#define __WASI_EADDRINUSE (3) +#define __WASI_EADDRNOTAVAIL (4) +#define __WASI_EAFNOSUPPORT (5) +#define __WASI_EAGAIN (6) +#define __WASI_EALREADY (7) +#define __WASI_EBADF (8) +#define __WASI_EBADMSG (9) +#define __WASI_EBUSY (10) +#define __WASI_ECANCELED (11) +#define __WASI_ECHILD (12) +#define __WASI_ECONNABORTED (13) +#define __WASI_ECONNREFUSED (14) +#define __WASI_ECONNRESET (15) +#define __WASI_EDEADLK (16) +#define __WASI_EDESTADDRREQ (17) +#define __WASI_EDOM (18) +#define __WASI_EDQUOT (19) +#define __WASI_EEXIST (20) +#define __WASI_EFAULT (21) +#define __WASI_EFBIG (22) +#define __WASI_EHOSTUNREACH (23) +#define __WASI_EIDRM (24) +#define __WASI_EILSEQ (25) +#define __WASI_EINPROGRESS (26) +#define __WASI_EINTR (27) +#define __WASI_EINVAL (28) +#define __WASI_EIO (29) +#define __WASI_EISCONN (30) +#define __WASI_EISDIR (31) +#define __WASI_ELOOP (32) +#define __WASI_EMFILE (33) +#define __WASI_EMLINK (34) +#define __WASI_EMSGSIZE (35) +#define __WASI_EMULTIHOP (36) +#define __WASI_ENAMETOOLONG (37) +#define __WASI_ENETDOWN (38) +#define __WASI_ENETRESET (39) +#define __WASI_ENETUNREACH (40) +#define __WASI_ENFILE (41) +#define __WASI_ENOBUFS (42) +#define __WASI_ENODEV (43) +#define __WASI_ENOENT (44) +#define __WASI_ENOEXEC (45) +#define __WASI_ENOLCK (46) +#define __WASI_ENOLINK (47) +#define __WASI_ENOMEM (48) +#define __WASI_ENOMSG (49) +#define __WASI_ENOPROTOOPT (50) +#define __WASI_ENOSPC (51) +#define __WASI_ENOSYS (52) +#define __WASI_ENOTCONN (53) +#define __WASI_ENOTDIR (54) +#define __WASI_ENOTEMPTY (55) +#define __WASI_ENOTRECOVERABLE (56) +#define __WASI_ENOTSOCK (57) +#define __WASI_ENOTSUP (58) +#define __WASI_ENOTTY (59) +#define __WASI_ENXIO (60) +#define __WASI_EOVERFLOW (61) +#define __WASI_EOWNERDEAD (62) +#define __WASI_EPERM (63) +#define __WASI_EPIPE (64) +#define __WASI_EPROTO (65) +#define __WASI_EPROTONOSUPPORT (66) +#define __WASI_EPROTOTYPE (67) +#define __WASI_ERANGE (68) +#define __WASI_EROFS (69) +#define __WASI_ESPIPE (70) +#define __WASI_ESRCH (71) +#define __WASI_ESTALE (72) +#define __WASI_ETIMEDOUT (73) +#define __WASI_ETXTBSY (74) +#define __WASI_EXDEV (75) +#define __WASI_ENOTCAPABLE (76) + +#if defined(_MSC_VER) +#define ALIGNED_(x) __declspec(align(x)) +#define WARN_UNUSED _Check_return_ +#elif defined(__GNUC__) +#define ALIGNED_(x) __attribute__ ((aligned(x))) +#define WARN_UNUSED __attribute__((__warn_unused_result__)) +#endif + +#define ALIGNED_TYPE(t,x) typedef t ALIGNED_(x) + +typedef uint16_t __wasi_eventrwflags_t; +#define __WASI_EVENT_FD_READWRITE_HANGUP (0x0001) + +typedef uint8_t __wasi_eventtype_t; +#define __WASI_EVENTTYPE_CLOCK (0) +#define __WASI_EVENTTYPE_FD_READ (1) +#define __WASI_EVENTTYPE_FD_WRITE (2) + +typedef uint32_t __wasi_exitcode_t; + +typedef uint32_t __wasi_fd_t; + +typedef uint16_t __wasi_fdflags_t; +#define __WASI_FDFLAG_APPEND (0x0001) +#define __WASI_FDFLAG_DSYNC (0x0002) +#define __WASI_FDFLAG_NONBLOCK (0x0004) +#define __WASI_FDFLAG_RSYNC (0x0008) +#define __WASI_FDFLAG_SYNC (0x0010) + +typedef int64_t __wasi_filedelta_t; + +typedef uint64_t __wasi_filesize_t; + +typedef uint8_t __wasi_filetype_t; +#define __WASI_FILETYPE_UNKNOWN (0) +#define __WASI_FILETYPE_BLOCK_DEVICE (1) +#define __WASI_FILETYPE_CHARACTER_DEVICE (2) +#define __WASI_FILETYPE_DIRECTORY (3) +#define __WASI_FILETYPE_REGULAR_FILE (4) +#define __WASI_FILETYPE_SOCKET_DGRAM (5) +#define __WASI_FILETYPE_SOCKET_STREAM (6) +#define __WASI_FILETYPE_SYMBOLIC_LINK (7) + +typedef uint16_t __wasi_fstflags_t; +#define __WASI_FILESTAT_SET_ATIM (0x0001) +#define __WASI_FILESTAT_SET_ATIM_NOW (0x0002) +#define __WASI_FILESTAT_SET_MTIM (0x0004) +#define __WASI_FILESTAT_SET_MTIM_NOW (0x0008) + +typedef uint64_t __wasi_inode_t; + +ALIGNED_TYPE(uint64_t, 8) __wasi_linkcount_t; + +typedef uint32_t __wasi_lookupflags_t; +#define __WASI_LOOKUP_SYMLINK_FOLLOW (0x00000001) + +typedef uint16_t __wasi_oflags_t; +#define __WASI_O_CREAT (0x0001) +#define __WASI_O_DIRECTORY (0x0002) +#define __WASI_O_EXCL (0x0004) +#define __WASI_O_TRUNC (0x0008) + +typedef uint16_t __wasi_riflags_t; +#define __WASI_SOCK_RECV_PEEK (0x0001) +#define __WASI_SOCK_RECV_WAITALL (0x0002) + +typedef uint64_t __wasi_rights_t; + +/** + * Observe that WASI defines rights in the plural form + * TODO: refactor to use RIGHTS instead of RIGHT + */ +#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(UINT64_C(1) << 0)) +#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(UINT64_C(1) << 1)) +#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(UINT64_C(1) << 2)) +#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(UINT64_C(1) << 3)) +#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(UINT64_C(1) << 4)) +#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(UINT64_C(1) << 5)) +#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(UINT64_C(1) << 6)) +#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(UINT64_C(1) << 7)) +#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(UINT64_C(1) << 8)) +#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 9)) +#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(UINT64_C(1) << 10)) +#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 11)) +#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(UINT64_C(1) << 12)) +#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(UINT64_C(1) << 13)) +#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(UINT64_C(1) << 14)) +#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(UINT64_C(1) << 15)) +#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 16)) +#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(UINT64_C(1) << 17)) +#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 18)) +#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 19)) +#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 20)) +#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 21)) +#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 22)) +#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 23)) +#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(UINT64_C(1) << 24)) +#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 25)) +#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(UINT64_C(1) << 26)) +#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(UINT64_C(1) << 27)) +#define __WASI_RIGHT_SOCK_CONNECT ((__wasi_rights_t)(UINT64_C(1) << 28)) +#define __WASI_RIGHT_SOCK_LISTEN ((__wasi_rights_t)(UINT64_C(1) << 29)) +#define __WASI_RIGHT_SOCK_BIND ((__wasi_rights_t)(UINT64_C(1) << 30)) +#define __WASI_RIGHT_SOCK_ACCEPT ((__wasi_rights_t)(UINT64_C(1) << 31)) +#define __WASI_RIGHT_SOCK_RECV ((__wasi_rights_t)(UINT64_C(1) << 32)) +#define __WASI_RIGHT_SOCK_SEND ((__wasi_rights_t)(UINT64_C(1) << 33)) +#define __WASI_RIGHT_SOCK_ADDR_LOCAL ((__wasi_rights_t)(UINT64_C(1) << 34)) +#define __WASI_RIGHT_SOCK_ADDR_REMOTE ((__wasi_rights_t)(UINT64_C(1) << 35)) +#define __WASI_RIGHT_SOCK_RECV_FROM ((__wasi_rights_t)(UINT64_C(1) << 36)) +#define __WASI_RIGHT_SOCK_SEND_TO ((__wasi_rights_t)(UINT64_C(1) << 37)) + +typedef uint16_t __wasi_roflags_t; +#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001) + +typedef uint8_t __wasi_sdflags_t; +#define __WASI_SHUT_RD (0x01) +#define __WASI_SHUT_WR (0x02) + +typedef uint16_t __wasi_siflags_t; + +typedef uint8_t __wasi_signal_t; + +typedef uint16_t __wasi_subclockflags_t; +#define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001) + +typedef uint64_t __wasi_timestamp_t; + +typedef uint64_t __wasi_userdata_t; + +typedef uint8_t __wasi_whence_t; +#define __WASI_WHENCE_SET (0) +#define __WASI_WHENCE_CUR (1) +#define __WASI_WHENCE_END (2) + +typedef uint8_t __wasi_preopentype_t; +#define __WASI_PREOPENTYPE_DIR (0) + +struct fd_table; +struct fd_prestats; +struct argv_environ_values; +struct addr_pool; + +typedef struct ALIGNED_(8) __wasi_dirent_t { + __wasi_dircookie_t d_next; + __wasi_inode_t d_ino; + __wasi_dirnamlen_t d_namlen; + __wasi_filetype_t d_type; +} __wasi_dirent_t; +assert_wasi_layout(offsetof(__wasi_dirent_t, d_next) == 0, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_dirent_t, d_ino) == 8, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_dirent_t, d_namlen) == 16, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_dirent_t, d_type) == 20, "non-wasi data layout"); +assert_wasi_layout(sizeof(__wasi_dirent_t) == 24, "non-wasi data layout"); +assert_wasi_layout(_Alignof(__wasi_dirent_t) == 8, "non-wasi data layout"); + +typedef struct ALIGNED_(8) __wasi_event_t { + __wasi_userdata_t userdata; + __wasi_errno_t error; + __wasi_eventtype_t type; + uint8_t __paddings[5]; + union __wasi_event_u { + struct __wasi_event_u_fd_readwrite_t { + __wasi_filesize_t nbytes; + __wasi_eventrwflags_t flags; + uint8_t __paddings[6]; + } fd_readwrite; + } u; +} __wasi_event_t; +assert_wasi_layout(offsetof(__wasi_event_t, userdata) == 0, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_event_t, error) == 8, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_event_t, type) == 10, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_event_t, u.fd_readwrite.nbytes) == 16, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_event_t, u.fd_readwrite.flags) == 24, "non-wasi data layout"); +assert_wasi_layout(sizeof(__wasi_event_t) == 32, "non-wasi data layout"); +assert_wasi_layout(_Alignof(__wasi_event_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_prestat_t { + __wasi_preopentype_t pr_type; + union __wasi_prestat_u { + struct __wasi_prestat_u_dir_t { + size_t pr_name_len; + } dir; + } u; +} __wasi_prestat_t; +assert_wasi_layout(offsetof(__wasi_prestat_t, pr_type) == 0, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 4, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 8, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + sizeof(__wasi_prestat_t) == 8, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + sizeof(__wasi_prestat_t) == 16, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + _Alignof(__wasi_prestat_t) == 4, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + _Alignof(__wasi_prestat_t) == 8, "non-wasi data layout"); + +typedef struct ALIGNED_(8) __wasi_fdstat_t { + __wasi_filetype_t fs_filetype; + __wasi_fdflags_t fs_flags; + uint8_t __paddings[4]; + __wasi_rights_t fs_rights_base; + __wasi_rights_t fs_rights_inheriting; +} __wasi_fdstat_t; +assert_wasi_layout( + offsetof(__wasi_fdstat_t, fs_filetype) == 0, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_fdstat_t, fs_flags) == 2, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16, + "non-wasi data layout"); +assert_wasi_layout(sizeof(__wasi_fdstat_t) == 24, "non-wasi data layout"); +assert_wasi_layout(_Alignof(__wasi_fdstat_t) == 8, "non-wasi data layout"); + +typedef struct ALIGNED_(8) __wasi_filestat_t { + __wasi_device_t st_dev; + __wasi_inode_t st_ino; + __wasi_filetype_t st_filetype; + __wasi_linkcount_t st_nlink; + __wasi_filesize_t st_size; + __wasi_timestamp_t st_atim; + __wasi_timestamp_t st_mtim; + __wasi_timestamp_t st_ctim; +} __wasi_filestat_t; +assert_wasi_layout(offsetof(__wasi_filestat_t, st_dev) == 0, "non-wasi data layout"); +assert_wasi_layout(offsetof(__wasi_filestat_t, st_ino) == 8, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_filestat_t, st_filetype) == 16, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_filestat_t, st_nlink) == 24, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_filestat_t, st_size) == 32, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_filestat_t, st_atim) == 40, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_filestat_t, st_mtim) == 48, "non-wasi data layout"); +assert_wasi_layout( + offsetof(__wasi_filestat_t, st_ctim) == 56, "non-wasi data layout"); +assert_wasi_layout(sizeof(__wasi_filestat_t) == 64, "non-wasi data layout"); +assert_wasi_layout(_Alignof(__wasi_filestat_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_ciovec_t { + const void *buf; + size_t buf_len; +} __wasi_ciovec_t; +assert_wasi_layout(offsetof(__wasi_ciovec_t, buf) == 0, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + offsetof(__wasi_ciovec_t, buf_len) == 4, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + offsetof(__wasi_ciovec_t, buf_len) == 8, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + sizeof(__wasi_ciovec_t) == 8, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + sizeof(__wasi_ciovec_t) == 16, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + _Alignof(__wasi_ciovec_t) == 4, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + _Alignof(__wasi_ciovec_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_iovec_t { + void *buf; + size_t buf_len; +} __wasi_iovec_t; +assert_wasi_layout(offsetof(__wasi_iovec_t, buf) == 0, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + offsetof(__wasi_iovec_t, buf_len) == 4, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + offsetof(__wasi_iovec_t, buf_len) == 8, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + sizeof(__wasi_iovec_t) == 8, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + sizeof(__wasi_iovec_t) == 16, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 4 || + _Alignof(__wasi_iovec_t) == 4, "non-wasi data layout"); +assert_wasi_layout(sizeof(void *) != 8 || + _Alignof(__wasi_iovec_t) == 8, "non-wasi data layout"); + +/** + * The contents of a `subscription` when type is `eventtype::clock`. + */ +typedef struct ALIGNED_(8) __wasi_subscription_clock_t { + /** + * The clock against which to compare the timestamp. + */ + __wasi_clockid_t clock_id; + + uint8_t __paddings1[4]; + + /** + * The absolute or relative timestamp. + */ + __wasi_timestamp_t timeout; + + /** + * The amount of time that the implementation may wait additionally + * to coalesce with other events. + */ + __wasi_timestamp_t precision; + + /** + * Flags specifying whether the timeout is absolute or relative + */ + __wasi_subclockflags_t flags; + + uint8_t __paddings2[4]; + +} __wasi_subscription_clock_t; + +assert_wasi_layout(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size"); +assert_wasi_layout(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align"); +assert_wasi_layout(offsetof(__wasi_subscription_clock_t, clock_id) == 0, "witx calculated offset"); +assert_wasi_layout(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset"); +assert_wasi_layout(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset"); +assert_wasi_layout(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset"); + +/** + * The contents of a `subscription` when type is type is + * `eventtype::fd_read` or `eventtype::fd_write`. + */ +typedef struct __wasi_subscription_fd_readwrite_t { + /** + * The file descriptor on which to wait for it to become ready for reading or writing. + */ + __wasi_fd_t fd; + +} __wasi_subscription_fd_readwrite_t; + +assert_wasi_layout(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size"); +assert_wasi_layout(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align"); +assert_wasi_layout(offsetof(__wasi_subscription_fd_readwrite_t, fd) == 0, "witx calculated offset"); + +/** + * The contents of a `subscription`. + */ +typedef union __wasi_subscription_u_u_t { + __wasi_subscription_clock_t clock; + __wasi_subscription_fd_readwrite_t fd_readwrite; +} __wasi_subscription_u_u_t ; + +typedef struct ALIGNED_(8) __wasi_subscription_u_t { + __wasi_eventtype_t type; + __wasi_subscription_u_u_t u; +} __wasi_subscription_u_t; + +assert_wasi_layout(sizeof(__wasi_subscription_u_t) == 40, "witx calculated size"); +assert_wasi_layout(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align"); +assert_wasi_layout(offsetof(__wasi_subscription_u_t, u) == 8, "witx calculated union offset"); +assert_wasi_layout(sizeof(__wasi_subscription_u_u_t) == 32, "witx calculated union size"); +assert_wasi_layout(_Alignof(__wasi_subscription_u_u_t) == 8, "witx calculated union align"); + +/** + * Subscription to an event. + */ +typedef struct __wasi_subscription_t { + /** + * User-provided value that is attached to the subscription in the + * implementation and returned through `event::userdata`. + */ + __wasi_userdata_t userdata; + + /** + * The type of the event to which to subscribe, and its contents + */ + __wasi_subscription_u_t u; + +} __wasi_subscription_t; + +assert_wasi_layout(sizeof(__wasi_subscription_t) == 48, "witx calculated size"); +assert_wasi_layout(_Alignof(__wasi_subscription_t) == 8, "witx calculated align"); +assert_wasi_layout(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset"); +assert_wasi_layout(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset"); + +/* keep syncing with wasi_socket_ext.h */ +typedef enum { + /* Used only for sock_addr_resolve hints */ + SOCKET_ANY = -1, + SOCKET_DGRAM = 0, + SOCKET_STREAM, +} __wasi_sock_type_t; + +typedef uint16_t __wasi_ip_port_t; + +typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t; + +/* n0.n1.n2.n3 */ +typedef struct __wasi_addr_ip4_t { + uint8_t n0; + uint8_t n1; + uint8_t n2; + uint8_t n3; +} __wasi_addr_ip4_t; + +typedef struct __wasi_addr_ip4_port_t { + __wasi_addr_ip4_t addr; + __wasi_ip_port_t port; +} __wasi_addr_ip4_port_t; + +typedef struct __wasi_addr_ip6_t { + uint16_t n0; + uint16_t n1; + uint16_t n2; + uint16_t n3; + uint16_t h0; + uint16_t h1; + uint16_t h2; + uint16_t h3; +} __wasi_addr_ip6_t; + +typedef struct __wasi_addr_ip6_port_t { + __wasi_addr_ip6_t addr; + __wasi_ip_port_t port; +} __wasi_addr_ip6_port_t; + +typedef struct __wasi_addr_ip_t { + __wasi_addr_type_t kind; + union { + __wasi_addr_ip4_t ip4; + __wasi_addr_ip6_t ip6; + } addr; +} __wasi_addr_ip_t; + +typedef struct __wasi_addr_t { + __wasi_addr_type_t kind; + union { + __wasi_addr_ip4_port_t ip4; + __wasi_addr_ip6_port_t ip6; + } addr; +} __wasi_addr_t; + +typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; + +typedef struct __wasi_addr_info_t { + __wasi_addr_t addr; + __wasi_sock_type_t type; +} __wasi_addr_info_t; + +typedef struct __wasi_addr_info_hints_t { + __wasi_sock_type_t type; + __wasi_address_family_t family; + // this is to workaround lack of optional parameters + uint8_t hints_enabled; +} __wasi_addr_info_hints_t; + +#undef assert_wasi_layout + +/* clang-format on */ + +/**************************************************** + * * + * Filesystem interface * + * * + ****************************************************/ + +/** + * NOTES: + * Fileystem APIs are required for WASI libc support. If you don't need to + * support WASI libc, there is no need to implement these APIs. With a + * few exceptions, each filesystem function has been named after the equivalent + * POSIX filesystem function with an os_ prefix. + * + * Filesystem types + * + * os_raw_file_handle: the underlying OS file handle type e.g. int on POSIX + * systems and HANDLE on Windows. This type exists to allow embedders to provide + * custom file handles for stdout/stdin/stderr. + * + * os_file_handle: the file handle type used in the WASI libc fd + * table. Filesystem implementations can use it as a means to store any + * necessary platform-specific information which may not be directly available + * through the raw OS file handle. Similiar to POSIX file descriptors, file + * handles may also refer to sockets, directories, symbolic links or character + * devices and any of the filesystem operations which make sense for these + * resource types should be supported as far as possible. + * + * os_dir_stream: a directory stream type in which fileystem implementations + * can store any necessary state to iterate over the entries in a directory. + */ + +/** + * Obtain information about an open file associated with the given handle. + * + * @param handle the handle for which to obtain file information + * @param buf a buffer in which to store the information + */ +__wasi_errno_t +os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf); + +/** + * Obtain information about an open file or directory. + * @param handle the directory handle from which to resolve the file/directory + * path + * @param path the relative path of the file or directory for which to obtain + * information + * @param buf a buffer in which to store the information + * @param follow_symlink whether to follow symlinks when resolving the path + */ +__wasi_errno_t +os_fstatat(os_file_handle handle, const char *path, + struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags); + +/** + * Obtain the file status flags for the provided handle. This is similiar to the + * POSIX function fcntl called with the F_GETFL command. + * + * @param handle the handle for which to obtain the file status flags + * @param flags a pointer in which to store the output + */ +__wasi_errno_t +os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags); + +/** + * Set the file status flags for the provided handle. This is similiar to the + * POSIX function fcntl called with the F_SETFL command. + * + * @param handle the handle for which to set the file status flags + * @param flags the flags to set + */ +__wasi_errno_t +os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags); + +/** + * Synchronize the data of a file to disk. + * + * @param handle + */ +__wasi_errno_t +os_fdatasync(os_file_handle handle); + +/** + * Synchronize the data and metadata of a file to disk. + * + * @param handle + */ +__wasi_errno_t +os_fsync(os_file_handle handle); + +/** + * Open a preopen directory. The path provided must refer to a directory and the + * returned handle will allow only readonly operations. + * + * @param path the path of the preopen directory to open + * @param out a pointer in which to store the newly opened handle + */ +__wasi_errno_t +os_open_preopendir(const char *path, os_file_handle *out); + +typedef uint8 wasi_libc_file_access_mode; +#define WASI_LIBC_ACCESS_MODE_READ_ONLY 0 +#define WASI_LIBC_ACCESS_MODE_WRITE_ONLY 1 +#define WASI_LIBC_ACCESS_MODE_READ_WRITE 2 + +/** + * Open a file or directory at the given path. + * + * @param handle a handle to the directory in which to open the new file or + * directory + * @param path the relative path of the file or directory to open + * @param oflags the flags to determine how the file or directory is opened + * @param fd_flags the flags to set on the returned handle + * @param lookup_flags whether to follow symlinks when resolving the path + * @param access_mode whether the file is opened as read only, write only or + * both + * @param out a pointer in which to store the newly opened handle + */ +__wasi_errno_t +os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, + __wasi_fdflags_t fd_flags, __wasi_lookupflags_t lookup_flags, + wasi_libc_file_access_mode access_mode, os_file_handle *out); + +/** + * Obtain the file access mode for the provided handle. This is similiar to the + * POSIX function fcntl called with the F_GETFL command combined with the + * O_ACCMODE mask. + * + * @param handle the handle for which to obtain the access mode + * @param access_mode a pointer in which to store the access mode + */ +__wasi_errno_t +os_file_get_access_mode(os_file_handle handle, + wasi_libc_file_access_mode *access_mode); + +/** + * Close the provided handle. If is_stdio is true, the raw file handle + * associated with the given file handle will not be closed. + * + * @param handle the handle to close + * @param is_stdio whether the provided handle refers to a stdio device + */ +__wasi_errno_t +os_close(os_file_handle handle, bool is_stdio); + +/** + * Read data from the provided handle at the given offset into multiple buffers. + * + * @param handle the handle to read from + * @param iov the buffers to read into + * @param iovcnt the number of buffers to read into + * @param offset the offset to read from + * @param nread a pointer in which to store the number of bytes read + */ +__wasi_errno_t +os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nread); + +/** + * Write data from multiple buffers at the given offset to the provided handle. + * + * @param handle the handle to write to + * @param iov the buffers to write from + * @param iovcnt the number of buffers to write from + * @param offset the offset to write from + * @param nwritten a pointer in which to store the number of bytes written + */ +__wasi_errno_t +os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten); + +/** + * Read data from the provided handle into multiple buffers. + * + * @param handle the handle to read from + * @param iov the buffers to read into + * @param iovcnt the number of buffers to read into + * @param nread a pointer in which to store the number of bytes read + */ +__wasi_errno_t +os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + size_t *nread); + +/** + * Write data from multiple buffers to the provided handle. + * + * @param handle the handle to write to + * @param iov the buffers to write from + * @param iovcnt the number of buffers to write from + * @param nwritten a pointer in which to store the number of bytes written + */ +__wasi_errno_t +os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + size_t *nwritten); + +/** + * Allocate storage space for the file associated with the provided handle. This + * is similar to the POSIX function posix_fallocate. + * + * @param handle the handle to allocate space for + * @param offset the offset to allocate space at + * @param length the amount of space to allocate + */ +__wasi_errno_t +os_fallocate(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length); + +/** + * Adjust the size of an open file. + * + * @param handle the associated file handle for which to adjust the size + * @param size the new size of the file + */ +__wasi_errno_t +os_ftruncate(os_file_handle handle, __wasi_filesize_t size); + +/** + * Set file access and modification times on an open file or directory. + * + * @param handle the associated file handle for which to adjust the + * access/modification times + * @param access_time the timestamp for the new access time + * @param modification_time the timestamp for the new modification time + * @param fstflags a bitmask to indicate which timestamps to adjust + */ +__wasi_errno_t +os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags); + +/** + * Set file access and modification times on an open file or directory. + * + * @param handle the directory handle from which to resolve the path + * @param path the relative path of the file or directory for which to adjust + * the access/modification times + * @param access_time the timestamp for the new access time + * @param modification_time the timestamp for the new modification time + * @param fstflags a bitmask to indicate which timestamps to adjust + * @param lookup_flags whether to follow symlinks when resolving the path + */ +__wasi_errno_t +os_utimensat(os_file_handle handle, const char *path, + __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, + __wasi_lookupflags_t lookup_flags); + +/** + * Read the contents of a symbolic link relative to the provided directory + * handle. + * + * @param handle the directory handle + * @param path the relative path of the symbolic link from which to read + * @param buf the buffer to read the link contents into + * @param bufsize the size of the provided buffer + * @param nread a pointer in which to store the number of bytes read into the + * buffer + */ +__wasi_errno_t +os_readlinkat(os_file_handle handle, const char *path, char *buf, + size_t bufsize, size_t *nread); + +/** + * Create a link from one path to another path. + * + * @param from_handle the directory handle from which to resolve the origin path + * @param from_path the origin path to link from + * @param to_handle the directory handle from which to resolve the destination + * path + * @param to_path the destination path at which to create the link + * @param lookup_flags whether to follow symlinks when resolving the origin path + */ +__wasi_errno_t +os_linkat(os_file_handle from_handle, const char *from_path, + os_file_handle to_handle, const char *to_path, + __wasi_lookupflags_t lookup_flags); + +/** + * Create a symbolic link from one path to another path. + * + * @param old_path the symbolic link contents + * @param handle the directory handle from which to resolve the destination path + * @param new_path the destination path at which to create the symbolic link + */ +__wasi_errno_t +os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path); + +/** + * Create a directory relative to the provided directory handle. + * + * @param handle the directory handle + * @param path the relative path of the directory to create + */ +__wasi_errno_t +os_mkdirat(os_file_handle handle, const char *path); + +/** + * Rename a file or directory. + * + * @param old_handle the directory handle from which to resolve the old path + * @param old_path the source path to rename + * @param new_handle the directory handle from which to resolve the destination + * path + * @param new_path the destination path to which to rename the file or directory + */ +__wasi_errno_t +os_renameat(os_file_handle old_handle, const char *old_path, + os_file_handle new_handle, const char *new_path); + +/** + * Unlink a file or directory. + * + * @param handle the directory handle from which to resolve the path + * @param path the relative path of the file or directory to unlink + * @param is_dir whether the provided handle refers to a directory or file + */ +__wasi_errno_t +os_unlinkat(os_file_handle handle, const char *path, bool is_dir); + +/** + * Move the read/write offset of an open file. + * + * @param handle the associated file handle for which to adjust the offset + * @param offset the number of bytes to adjust the offset by + * @param whence the position whence to adjust the offset + * @param new_offset a pointer in which to store the new offset + */ +__wasi_errno_t +os_lseek(os_file_handle handle, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *new_offset); + +/** + * Provide file advisory information for the given handle. This is similar to + * the POSIX function posix_fadvise. + * + * @param handle the associated file handle for which to provide advisory + * information + * @param offset the offset within the file to which the advisory + * information applies + * @param length the length of the region for which the advisory information + * applies + * @param advice the advice to provide + */ +__wasi_errno_t +os_fadvise(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length, __wasi_advice_t advice); + +/** + * Determine if the given handle refers to a terminal device. __WASI_ESUCCESS + * will be returned if the handle is associated with a terminal device, + * otherwise an appropriate error code will be returned. + * + * @param handle + */ +__wasi_errno_t +os_isatty(os_file_handle handle); + +/** + * Converts a raw file handle to STDIN to a corresponding file handle to STDIN. + * If the provided raw file handle is invalid, the platform-default raw handle + * for STDIN will be used. + * + * @param raw_stdin a raw file handle to STDIN + * + * @return a handle to STDIN + */ +os_file_handle +os_convert_stdin_handle(os_raw_file_handle raw_stdin); + +/** + * Converts a raw file handle to STDOUT to a correponding file handle to STDOUT. + * If the provided raw file handle is invalid, the platform-default raw handle + * for STDOUT will be used. + * + * @param raw_stdout a raw file handle to STDOUT + * + * @return a handle to STDOUT + */ +os_file_handle +os_convert_stdout_handle(os_raw_file_handle raw_stdout); + +/** + * Converts a raw file handle to STDERR to a correponding file handle to STDERR. + * If the provided raw file handle is invalid, the platform-default raw handle + * for STDERR will be used. + * + * @param raw_stderr a raw file handle to STDERR + * + * @return a handle to STDERR + */ +os_file_handle +os_convert_stderr_handle(os_raw_file_handle raw_stderr); + +/** + * Open a directory stream for the provided directory handle. The returned + * directory stream will be positioned at the first entry in the directory. + * + * @param handle the directory handle + * @param dir_stream a pointer in which to store the new directory stream + */ +__wasi_errno_t +os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream); + +/** + * Reset the position of a directory stream to the beginning of the directory. + * + * @param dir_stream the directory stream for which to reset the position + */ +__wasi_errno_t +os_rewinddir(os_dir_stream dir_stream); + +/** + * Set the position of the given directory stream. + * + * @param dir_stream the directory stream for which to set the position + * @param position the position to set + */ +__wasi_errno_t +os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position); + +/** + * Read a directory entry from the given directory stream. The directory name + * will be NULL if the end of the directory is reached or an error is + * encountered. + * + * @param dir_stream the directory stream from which to read the entry + * @param entry a pointer in which to store the directory entry + * @param d_name a pointer in which to store the directory entry name + */ +__wasi_errno_t +os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, + const char **d_name); + +/** + * Close the given directory stream. The handle associated with the directory + * stream will also be closed. + * + * @param dir_stream the directory stream to close + */ +__wasi_errno_t +os_closedir(os_dir_stream dir_stream); + +/** + * Returns an invalid directory stream that is guaranteed to cause failure when + * called with any directory filesystem operation. + * + * @return the invalid directory stream + */ +os_dir_stream +os_get_invalid_dir_stream(); + +/** + * Checks whether the given directory stream is valid. An invalid directory + * stream is guaranteed to cause failure when called with any directory + * filesystem operation. + * + * @param dir_stream a pointer to a directory stream + */ +bool +os_is_dir_stream_valid(os_dir_stream *dir_stream); + +/** + * Returns an invalid handle that is guaranteed to cause failure when + * called with any filesystem operation. + * + * @return the invalid handle + */ +os_file_handle +os_get_invalid_handle(); + +/** + * Checks whether the given file handle is valid. An invalid handle is + * guaranteed to cause failure when called with any filesystem operation. + * + * @param handle a pointer to a file handle + */ +bool +os_is_handle_valid(os_file_handle *handle); + +/** + * Resolve a pathname. The generated pathname will be stored as a + * null-terminated string, with a maximum length of PATH_MAX bytes. + * + * @param path the path to resolve + * @param resolved_path the buffer to store the resolved path in + * + * @return the resolved path if success, NULL otherwise + */ +char * +os_realpath(const char *path, char *resolved_path); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_WASI_H */ \ No newline at end of file diff --git a/core/shared/platform/linux-sgx/platform_internal.h b/core/shared/platform/linux-sgx/platform_internal.h index 01bf63e96..0dd730482 100644 --- a/core/shared/platform/linux-sgx/platform_internal.h +++ b/core/shared/platform/linux-sgx/platform_internal.h @@ -69,6 +69,10 @@ strcpy(char *dest, const char *src); #define os_memory_order_seq_cst __ATOMIC_SEQ_CST #define os_atomic_thread_fence __atomic_thread_fence +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/linux-sgx/sgx_ipfs.h b/core/shared/platform/linux-sgx/sgx_ipfs.h index e4de90274..3a911d2b6 100644 --- a/core/shared/platform/linux-sgx/sgx_ipfs.h +++ b/core/shared/platform/linux-sgx/sgx_ipfs.h @@ -7,7 +7,6 @@ #define _LIBC_WASI_SGX_PFS_H #include "bh_hashmap.h" -#include "wasmtime_ssp.h" #ifdef __cplusplus extern "C" { diff --git a/core/shared/platform/linux-sgx/shared_platform.cmake b/core/shared/platform/linux-sgx/shared_platform.cmake index b2de1ab06..1168dedbc 100644 --- a/core/shared/platform/linux-sgx/shared_platform.cmake +++ b/core/shared/platform/linux-sgx/shared_platform.cmake @@ -20,16 +20,20 @@ if (NOT BUILD_UNTRUST_PART EQUAL 1) ${SGX_SDK_DIR}/include/libcxx) endif () -if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1) - add_definitions(-DSGX_DISABLE_WASI) -endif () - if (NOT WAMR_BUILD_THREAD_MGR EQUAL 1) add_definitions(-DSGX_DISABLE_PTHREAD) endif () file (GLOB source_all ${PLATFORM_SHARED_DIR}/*.c) +if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1) + add_definitions(-DSGX_DISABLE_WASI) +else() + list(APPEND source_all ${PLATFORM_SHARED_DIR}/../common/posix/posix_file.c) + include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake) + set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) +endif() + file (GLOB source_all_untrusted ${PLATFORM_SHARED_DIR}/untrusted/*.c) set (PLATFORM_SHARED_SOURCE ${source_all}) diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 0c13116f0..f94c4b689 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -122,6 +122,10 @@ os_sigreturn(); void os_set_signal_number_for_blocking_op(int signo); +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index 204f8c83c..b20c4a2c7 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -130,6 +130,10 @@ fdopendir(int fd); void os_set_signal_number_for_blocking_op(int signo); +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/nuttx/shared_platform.cmake b/core/shared/platform/nuttx/shared_platform.cmake index 7b29b5f09..1cbe2218b 100644 --- a/core/shared/platform/nuttx/shared_platform.cmake +++ b/core/shared/platform/nuttx/shared_platform.cmake @@ -10,5 +10,11 @@ include_directories(${PLATFORM_SHARED_DIR}/../include) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) +if (WAMR_BUILD_LIBC_WASI EQUAL 1) + list(APPEND source_all ${PLATFORM_SHARED_DIR}/../common/posix/posix_file.c) + include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake) + set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) +endif () + set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) diff --git a/core/shared/platform/riot/platform_internal.h b/core/shared/platform/riot/platform_internal.h index 8fec6dd0b..9f29b8fd5 100644 --- a/core/shared/platform/riot/platform_internal.h +++ b/core/shared/platform/riot/platform_internal.h @@ -52,6 +52,10 @@ typedef struct korp_cond { #define os_printf printf #define os_vprintf vprintf +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #if WA_MATH /* clang-format off */ /* math functions which are not provided by os*/ diff --git a/core/shared/platform/rt-thread/platform_internal.h b/core/shared/platform/rt-thread/platform_internal.h index 5f9cc8bc8..6abba7383 100644 --- a/core/shared/platform/rt-thread/platform_internal.h +++ b/core/shared/platform/rt-thread/platform_internal.h @@ -45,4 +45,8 @@ typedef rt_int16_t int16_t; typedef rt_uint64_t uint64_t; typedef rt_int64_t int64_t; +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #endif /* RTTHREAD_PLATFORM_INTERNAL_H */ diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h index dde213f30..a3f7fecc6 100644 --- a/core/shared/platform/vxworks/platform_internal.h +++ b/core/shared/platform/vxworks/platform_internal.h @@ -61,6 +61,10 @@ typedef sem_t korp_sem; #define os_thread_local_attribute __thread +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index b147c5e5b..88ebfec72 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -137,6 +137,14 @@ bh_atomic_thread_fence(int mem_order); #define os_atomic_thread_fence bh_atomic_thread_fence +typedef HANDLE os_file_handle; +typedef void *os_dir_stream; +#if WASM_ENABLE_UVWASI != 1 +typedef HANDLE os_raw_file_handle; +#else +typedef uint32_t os_raw_file_handle; +#endif + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/windows/shared_platform.cmake b/core/shared/platform/windows/shared_platform.cmake index a68d63177..3c531c17c 100644 --- a/core/shared/platform/windows/shared_platform.cmake +++ b/core/shared/platform/windows/shared_platform.cmake @@ -13,6 +13,13 @@ include_directories(${PLATFORM_SHARED_DIR}/../include) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c ${PLATFORM_SHARED_DIR}/*.cpp) +if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1) + list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/win_file.c) +else() + include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake) + set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) +endif() + set (PLATFORM_SHARED_SOURCE ${source_all}) file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c new file mode 100644 index 000000000..73b22cf32 --- /dev/null +++ b/core/shared/platform/windows/win_file.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" +#include "platform_internal.h" + +__wasi_errno_t +os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fstatat(os_file_handle handle, const char *path, + struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_file_get_access_mode(os_file_handle handle, + wasi_libc_file_access_mode *access_mode) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fdatasync(os_file_handle handle) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fsync(os_file_handle handle) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_open_preopendir(const char *path, os_file_handle *out) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, + __wasi_fdflags_t fs_flags, __wasi_lookupflags_t lookup_flags, + wasi_libc_file_access_mode read_write_mode, os_file_handle *out) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_close(os_file_handle handle, bool is_stdio) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nread) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + size_t *nread) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + size_t *nwritten) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fallocate(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_ftruncate(os_file_handle handle, __wasi_filesize_t size) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_utimensat(os_file_handle handle, const char *path, + __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, + __wasi_lookupflags_t lookup_flags) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_readlinkat(os_file_handle handle, const char *path, char *buf, + size_t bufsize, size_t *nread) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_linkat(os_file_handle from_handle, const char *from_path, + os_file_handle to_handle, const char *to_path, + __wasi_lookupflags_t lookup_flags) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_mkdirat(os_file_handle handle, const char *path) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_renameat(os_file_handle old_handle, const char *old_path, + os_file_handle new_handle, const char *new_path) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_unlinkat(os_file_handle handle, const char *path, bool is_dir) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_lseek(os_file_handle handle, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *new_offset) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fadvise(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length, __wasi_advice_t advice) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_isatty(os_file_handle handle) +{ + return __WASI_ENOSYS; +} + +os_file_handle +os_convert_stdin_handle(os_raw_file_handle raw_stdin) +{ + return INVALID_HANDLE_VALUE; +} + +os_file_handle +os_convert_stdout_handle(os_raw_file_handle raw_stdout) +{ + return INVALID_HANDLE_VALUE; +} + +os_file_handle +os_convert_stderr_handle(os_raw_file_handle raw_stderr) +{ + return INVALID_HANDLE_VALUE; +} + +__wasi_errno_t +os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_rewinddir(os_dir_stream dir_stream) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, + const char **d_name) +{ + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_closedir(os_dir_stream dir_stream) +{ + return __WASI_ENOSYS; +} + +os_dir_stream +os_get_invalid_dir_stream() +{ + return NULL; +} + +bool +os_is_dir_stream_valid(os_dir_stream *dir_stream) +{ + return false; +} + +os_file_handle +os_get_invalid_handle() +{ + return INVALID_HANDLE_VALUE; +} + +bool +os_is_handle_valid(os_file_handle *handle) +{ + return false; +} + +char * +os_realpath(const char *path, char *resolved_path) +{ + return NULL; +} \ No newline at end of file diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h index d2a94e4ad..65e0dea0d 100644 --- a/core/shared/platform/zephyr/platform_internal.h +++ b/core/shared/platform/zephyr/platform_internal.h @@ -146,4 +146,8 @@ void set_exec_mem_alloc_func(exec_mem_alloc_func_t alloc_func, exec_mem_free_func_t free_func); +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + #endif diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 04a6db91f..099c5503c 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -246,8 +246,11 @@ ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_WASI),y) CFLAGS += -DWASM_ENABLE_LIBC_WASI=1 CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/include +CFLAGS += -I${SHARED_ROOT}/platform/common/libc-util CSRCS += blocking_op.c CSRCS += posix_socket.c +CSRCS += posix_file.c +CSRCS += libc_errno.c CSRCS += libc_wasi_wrapper.c VPATH += $(IWASM_ROOT)/libraries/libc-wasi CSRCS += posix.c @@ -387,6 +390,7 @@ ASRCS += $(INVOKE_NATIVE) VPATH += $(SHARED_ROOT)/platform/nuttx VPATH += $(SHARED_ROOT)/platform/common/posix +VPATH += $(SHARED_ROOT)/platform/common/libc-util VPATH += $(SHARED_ROOT)/mem-alloc VPATH += $(SHARED_ROOT)/mem-alloc/ems VPATH += $(SHARED_ROOT)/utils diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index ba0902cdf..5fe8fae16 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -198,6 +198,12 @@ include_directories (${SHARED_DIR}/include enable_language (ASM) +if (NOT MINGW AND NOT MSVC) + set(WAMR_BUILD_LIBC_WASI 1) +else() + set(WAMR_BUILD_LIBC_UVWASI 1) +endif() + include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) include (${SHARED_DIR}/utils/shared_utils.cmake)