From 662e38e9b0e7a998b05c459d67b0287da2c418e5 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Thu, 13 Jul 2023 14:02:29 +0100 Subject: [PATCH 01/18] [Partial] Build wasi-libc for Windows (#2338) Build wasi-libc library on Windows since libuv may be not supported. This PR is a first step to make it working, but there's still a number of changes to get it fully working. --- .../include/wasmtime_ssp.h | 236 +++++++++--------- .../sandboxed-system-primitives/src/locking.h | 54 ++-- .../sandboxed-system-primitives/src/random.c | 17 ++ .../src/ssp_config.h | 2 +- .../platform/android/platform_internal.h | 1 + .../platform/common/posix/posix_thread.c | 55 ++++ .../platform/darwin/platform_internal.h | 1 + .../platform/esp-idf/platform_internal.h | 1 + .../platform/freebsd/platform_internal.h | 1 + .../platform/include/platform_api_extension.h | 50 ++++ .../platform/linux-sgx/platform_internal.h | 1 + core/shared/platform/linux-sgx/sgx_thread.c | 65 +++++ .../shared/platform/linux/platform_internal.h | 1 + .../shared/platform/nuttx/platform_internal.h | 1 + .../platform/vxworks/platform_internal.h | 1 + .../platform/windows/platform_internal.h | 5 + core/shared/platform/windows/win_socket.c | 8 + core/shared/platform/windows/win_thread.c | 56 +++++ product-mini/platforms/windows/CMakeLists.txt | 11 +- 19 files changed, 428 insertions(+), 139 deletions(-) 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 586e5816..cefe5726 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 @@ -153,6 +153,16 @@ typedef uint16_t __wasi_errno_t; #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) @@ -194,7 +204,7 @@ typedef uint16_t __wasi_fstflags_t; typedef uint64_t __wasi_inode_t; -typedef uint64_t __wasi_linkcount_t __attribute__((aligned(8))); +ALIGNED_TYPE(uint64_t, 8) __wasi_linkcount_t; typedef uint32_t __wasi_lookupflags_t; #define __WASI_LOOKUP_SYMLINK_FOLLOW (0x00000001) @@ -316,12 +326,12 @@ struct fd_prestats; struct argv_environ_values; struct addr_pool; -typedef struct __wasi_dirent_t { +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 __attribute__((aligned(8))); +} __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"); @@ -329,7 +339,7 @@ _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 __wasi_event_t { +typedef struct ALIGNED_(8) __wasi_event_t { __wasi_userdata_t userdata; __wasi_errno_t error; __wasi_eventtype_t type; @@ -341,7 +351,7 @@ typedef struct __wasi_event_t { uint8_t __paddings[6]; } fd_readwrite; } u; -} __wasi_event_t __attribute__((aligned(8))); +} __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"); @@ -374,13 +384,13 @@ _Static_assert(sizeof(void *) != 4 || _Static_assert(sizeof(void *) != 8 || _Alignof(__wasi_prestat_t) == 8, "non-wasi data layout"); -typedef struct __wasi_fdstat_t { +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 __attribute__((aligned(8))); +} __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"); @@ -392,7 +402,7 @@ _Static_assert( _Static_assert(sizeof(__wasi_fdstat_t) == 24, "non-wasi data layout"); _Static_assert(_Alignof(__wasi_fdstat_t) == 8, "non-wasi data layout"); -typedef struct __wasi_filestat_t { +typedef struct ALIGNED_(8) __wasi_filestat_t { __wasi_device_t st_dev; __wasi_inode_t st_ino; __wasi_filetype_t st_filetype; @@ -401,7 +411,7 @@ typedef struct __wasi_filestat_t { __wasi_timestamp_t st_atim; __wasi_timestamp_t st_mtim; __wasi_timestamp_t st_ctim; -} __wasi_filestat_t __attribute__((aligned(8))); +} __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( @@ -458,7 +468,7 @@ _Static_assert(sizeof(void *) != 8 || /** * The contents of a `subscription` when type is `eventtype::clock`. */ -typedef struct __wasi_subscription_clock_t { +typedef struct ALIGNED_(8) __wasi_subscription_clock_t { /** * The clock against which to compare the timestamp. */ @@ -484,7 +494,7 @@ typedef struct __wasi_subscription_clock_t { uint8_t __paddings2[4]; -} __wasi_subscription_clock_t __attribute__((aligned(8))); +} __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"); @@ -517,10 +527,10 @@ typedef union __wasi_subscription_u_u_t { __wasi_subscription_fd_readwrite_t fd_readwrite; } __wasi_subscription_u_u_t ; -typedef struct __wasi_subscription_u_t { +typedef struct ALIGNED_(8) __wasi_subscription_u_t { __wasi_eventtype_t type; __wasi_subscription_u_u_t u; -} __wasi_subscription_u_t __attribute__((aligned(8))); +} __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"); @@ -634,7 +644,7 @@ __wasi_errno_t wasmtime_ssp_args_get( #endif char **argv, char *argv_buf -) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(args_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_args_sizes_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -642,18 +652,18 @@ __wasi_errno_t wasmtime_ssp_args_sizes_get( #endif size_t *argc, size_t *argv_buf_size -) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__)); +) 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) __attribute__((__warn_unused_result__)); +) 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) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_environ_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -661,7 +671,7 @@ __wasi_errno_t wasmtime_ssp_environ_get( #endif char **environ, char *environ_buf -) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(environ_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_environ_sizes_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -669,7 +679,7 @@ __wasi_errno_t wasmtime_ssp_environ_sizes_get( #endif size_t *environ_count, size_t *environ_buf_size -) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_prestat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -677,7 +687,7 @@ __wasi_errno_t wasmtime_ssp_fd_prestat_get( #endif __wasi_fd_t fd, __wasi_prestat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -686,7 +696,7 @@ __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( __wasi_fd_t fd, char *path, size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_close( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -694,14 +704,14 @@ __wasi_errno_t wasmtime_ssp_fd_close( struct fd_prestats *prestats, #endif __wasi_fd_t fd -) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_close) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_datasync( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif __wasi_fd_t fd -) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_pread( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -712,7 +722,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread( size_t iovs_len, __wasi_filesize_t offset, size_t *nread -) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_pread) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_pwrite( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -723,7 +733,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite( size_t iovs_len, __wasi_filesize_t offset, size_t *nwritten -) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_read( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -733,7 +743,7 @@ __wasi_errno_t wasmtime_ssp_fd_read( const __wasi_iovec_t *iovs, size_t iovs_len, size_t *nread -) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_read) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_renumber( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -742,7 +752,7 @@ __wasi_errno_t wasmtime_ssp_fd_renumber( #endif __wasi_fd_t from, __wasi_fd_t to -) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_seek( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -752,7 +762,7 @@ __wasi_errno_t wasmtime_ssp_fd_seek( __wasi_filedelta_t offset, __wasi_whence_t whence, __wasi_filesize_t *newoffset -) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_seek) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_tell( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -760,7 +770,7 @@ __wasi_errno_t wasmtime_ssp_fd_tell( #endif __wasi_fd_t fd, __wasi_filesize_t *newoffset -) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_tell) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_fdstat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -768,7 +778,7 @@ __wasi_errno_t wasmtime_ssp_fd_fdstat_get( #endif __wasi_fd_t fd, __wasi_fdstat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -776,7 +786,7 @@ __wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( #endif __wasi_fd_t fd, __wasi_fdflags_t flags -) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -785,14 +795,14 @@ __wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( __wasi_fd_t fd, __wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inheriting -) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_sync( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif __wasi_fd_t fd -) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_sync) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_write( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -802,7 +812,7 @@ __wasi_errno_t wasmtime_ssp_fd_write( const __wasi_ciovec_t *iovs, size_t iovs_len, size_t *nwritten -) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_write) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_advise( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -812,7 +822,7 @@ __wasi_errno_t wasmtime_ssp_fd_advise( __wasi_filesize_t offset, __wasi_filesize_t len, __wasi_advice_t advice -) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_advise) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_allocate( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -821,7 +831,7 @@ __wasi_errno_t wasmtime_ssp_fd_allocate( __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len -) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_create_directory( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -830,7 +840,7 @@ __wasi_errno_t wasmtime_ssp_path_create_directory( __wasi_fd_t fd, const char *path, size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_link( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -844,7 +854,7 @@ __wasi_errno_t wasmtime_ssp_path_link( __wasi_fd_t new_fd, const char *new_path, size_t new_path_len -) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_link) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_open( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -859,7 +869,7 @@ __wasi_errno_t wasmtime_ssp_path_open( __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags, __wasi_fd_t *fd -) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_open) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_readdir( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -870,7 +880,7 @@ __wasi_errno_t wasmtime_ssp_fd_readdir( size_t buf_len, __wasi_dircookie_t cookie, size_t *bufused -) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_readlink( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -882,7 +892,7 @@ __wasi_errno_t wasmtime_ssp_path_readlink( char *buf, size_t buf_len, size_t *bufused -) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_readlink) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_rename( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -894,7 +904,7 @@ __wasi_errno_t wasmtime_ssp_path_rename( __wasi_fd_t new_fd, const char *new_path, size_t new_path_len -) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_rename) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_filestat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -902,7 +912,7 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_get( #endif __wasi_fd_t fd, __wasi_filestat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -912,7 +922,7 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, __wasi_fstflags_t fstflags -) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_fd_filestat_set_size( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -920,7 +930,7 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_size( #endif __wasi_fd_t fd, __wasi_filesize_t st_size -) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_filestat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -931,7 +941,7 @@ __wasi_errno_t wasmtime_ssp_path_filestat_get( const char *path, size_t path_len, __wasi_filestat_t *buf -) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_filestat_set_times( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -944,7 +954,7 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times( __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, __wasi_fstflags_t fstflags -) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_symlink( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -956,7 +966,7 @@ __wasi_errno_t wasmtime_ssp_path_symlink( __wasi_fd_t fd, const char *new_path, size_t new_path_len -) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_symlink) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_unlink_file( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -965,7 +975,7 @@ __wasi_errno_t wasmtime_ssp_path_unlink_file( __wasi_fd_t fd, const char *path, size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_path_remove_directory( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -974,7 +984,7 @@ __wasi_errno_t wasmtime_ssp_path_remove_directory( __wasi_fd_t fd, const char *path, size_t path_len -) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_poll_oneoff( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -984,7 +994,7 @@ __wasi_errno_t wasmtime_ssp_poll_oneoff( __wasi_event_t *out, size_t nsubscriptions, size_t *nevents -) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) WARN_UNUSED; #if 0 /** @@ -998,12 +1008,12 @@ _Noreturn void wasmtime_ssp_proc_exit( __wasi_errno_t wasmtime_ssp_proc_raise( __wasi_signal_t sig -) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(proc_raise) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_random_get( void *buf, size_t buf_len -) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(random_get) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_accept( @@ -1011,7 +1021,7 @@ wasi_ssp_sock_accept( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_addr_local( @@ -1019,7 +1029,7 @@ wasi_ssp_sock_addr_local( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_addr_t *addr -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_addr_remote( @@ -1027,7 +1037,7 @@ wasi_ssp_sock_addr_remote( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_addr_t *addr -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_open( @@ -1036,7 +1046,7 @@ wasi_ssp_sock_open( #endif __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, __wasi_fd_t *sockfd -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_bind( @@ -1044,7 +1054,7 @@ wasi_ssp_sock_bind( struct fd_table *curfds, struct addr_pool *addr_pool, #endif __wasi_fd_t fd, __wasi_addr_t *addr -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_addr_resolve( @@ -1054,7 +1064,7 @@ wasi_ssp_sock_addr_resolve( 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 -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_connect( @@ -1062,7 +1072,7 @@ wasi_ssp_sock_connect( struct fd_table *curfds, struct addr_pool *addr_pool, #endif __wasi_fd_t fd, __wasi_addr_t *addr -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_get_recv_buf_size( @@ -1070,7 +1080,7 @@ wasi_ssp_sock_get_recv_buf_size( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_size_t *size -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_get_reuse_addr( @@ -1078,7 +1088,7 @@ wasi_ssp_sock_get_reuse_addr( struct fd_table *curfds, #endif __wasi_fd_t fd, uint8_t *reuse -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_get_reuse_port( @@ -1086,7 +1096,7 @@ wasi_ssp_sock_get_reuse_port( struct fd_table *curfds, #endif __wasi_fd_t fd, uint8_t *reuse -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_get_send_buf_size( @@ -1094,7 +1104,7 @@ wasi_ssp_sock_get_send_buf_size( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_size_t *size -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_set_recv_buf_size( @@ -1102,7 +1112,7 @@ wasi_ssp_sock_set_recv_buf_size( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_size_t size -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_set_reuse_addr( @@ -1110,7 +1120,7 @@ wasi_ssp_sock_set_reuse_addr( struct fd_table *curfds, #endif __wasi_fd_t fd, uint8_t reuse -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_set_reuse_port( @@ -1118,7 +1128,7 @@ wasi_ssp_sock_set_reuse_port( struct fd_table *curfds, #endif __wasi_fd_t fd, uint8_t reuse -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_set_send_buf_size( @@ -1126,7 +1136,7 @@ wasi_ssp_sock_set_send_buf_size( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_size_t size -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasi_ssp_sock_listen( @@ -1134,7 +1144,7 @@ wasi_ssp_sock_listen( struct fd_table *curfds, #endif __wasi_fd_t fd, __wasi_size_t backlog -) __attribute__((__warn_unused_result__)); +) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_recv( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1144,7 +1154,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv( void *buf, size_t buf_len, size_t *recv_len -) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_recv) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_recv_from( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1156,7 +1166,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv_from( __wasi_riflags_t ri_flags, __wasi_addr_t *src_addr, size_t *recv_len -) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_send( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1166,7 +1176,7 @@ __wasi_errno_t wasmtime_ssp_sock_send( const void *buf, size_t buf_len, size_t *sent_len -) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_send) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_send_to( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1178,14 +1188,14 @@ __wasi_errno_t wasmtime_ssp_sock_send_to( __wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len -) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_shutdown( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif __wasi_fd_t sock -) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1193,7 +1203,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( #endif __wasi_fd_t sock, uint64_t timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_recv_timeout( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1201,7 +1211,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_recv_timeout( #endif __wasi_fd_t sock, uint64_t *timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_send_timeout( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1209,7 +1219,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_send_timeout( #endif __wasi_fd_t sock, uint64_t timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_send_timeout( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1217,7 +1227,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_send_timeout( #endif __wasi_fd_t sock, uint64_t *timeout_us -) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_send_buf_size( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1225,7 +1235,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_send_buf_size( #endif __wasi_fd_t sock, size_t bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_send_buf_size( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1233,7 +1243,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_send_buf_size( #endif __wasi_fd_t sock, size_t *bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1241,7 +1251,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size( #endif __wasi_fd_t sock, size_t bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1249,7 +1259,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( #endif __wasi_fd_t sock, size_t *bufsiz -) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_keep_alive( @@ -1258,7 +1268,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_keep_alive( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_keep_alive( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1266,7 +1276,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_keep_alive( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_reuse_addr( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1274,7 +1284,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_reuse_addr( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_reuse_addr( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1282,7 +1292,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_reuse_addr( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_reuse_port( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1290,7 +1300,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_reuse_port( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_reuse_port( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1298,7 +1308,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_reuse_port( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_linger( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1307,14 +1317,14 @@ __wasi_errno_t wasmtime_ssp_sock_set_linger( __wasi_fd_t sock, bool is_enabled, int linger_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_linger( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif __wasi_fd_t sock, bool *is_enabled, int *linger_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_broadcast( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1322,7 +1332,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_broadcast( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_broadcast( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1330,7 +1340,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_broadcast( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1338,7 +1348,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1346,7 +1356,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1354,7 +1364,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1362,7 +1372,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1370,7 +1380,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle( #endif __wasi_fd_t sock, uint32_t time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1378,7 +1388,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle( #endif __wasi_fd_t sock, uint32_t *time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1386,7 +1396,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl( #endif __wasi_fd_t sock, uint32_t time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1394,7 +1404,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl( #endif __wasi_fd_t sock, uint32_t *time_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1402,7 +1412,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1410,7 +1420,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1419,7 +1429,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( __wasi_fd_t sock, bool ipv6, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1428,7 +1438,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( __wasi_fd_t sock, bool ipv6, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1437,7 +1447,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1446,7 +1456,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_ip_ttl( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1454,7 +1464,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_ttl( #endif __wasi_fd_t sock, uint8_t ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_ip_ttl( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1462,7 +1472,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_ip_ttl( #endif __wasi_fd_t sock, uint8_t *ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1470,7 +1480,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl( #endif __wasi_fd_t sock, uint8_t ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1478,7 +1488,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl( #endif __wasi_fd_t sock, uint8_t *ttl_s -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_set_ipv6_only( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1486,7 +1496,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ipv6_only( #endif __wasi_fd_t sock, bool is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sock_get_ipv6_only( #if !defined(WASMTIME_SSP_STATIC_CURFDS) @@ -1494,10 +1504,10 @@ __wasi_errno_t wasmtime_ssp_sock_get_ipv6_only( #endif __wasi_fd_t sock, bool *is_enabled -) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__)); +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) WARN_UNUSED; __wasi_errno_t wasmtime_ssp_sched_yield(void) - WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__)); + WASMTIME_SSP_SYSCALL_NAME(sched_yield) WARN_UNUSED; #ifdef __cplusplus } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h index 40b064b8..5e0778c3 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h @@ -49,7 +49,7 @@ /* Mutex that uses the lock annotations. */ struct LOCKABLE mutex { - pthread_mutex_t object; + korp_mutex object; }; /* clang-format off */ @@ -60,69 +60,71 @@ struct LOCKABLE mutex { static inline bool mutex_init(struct mutex *lock) REQUIRES_UNLOCKED(*lock) { - return pthread_mutex_init(&lock->object, NULL) == 0 ? true : false; + return os_mutex_init(&lock->object) == BHT_OK ? true : false; } static inline void mutex_destroy(struct mutex *lock) REQUIRES_UNLOCKED(*lock) { - pthread_mutex_destroy(&lock->object); + os_mutex_destroy(&lock->object); } static inline void mutex_lock(struct mutex *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { - pthread_mutex_lock(&lock->object); + os_mutex_lock(&lock->object); } static inline void mutex_unlock(struct mutex *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS { - pthread_mutex_unlock(&lock->object); + os_mutex_unlock(&lock->object); } /* Read-write lock that uses the lock annotations. */ struct LOCKABLE rwlock { - pthread_rwlock_t object; + korp_rwlock object; }; static inline bool rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) { - return pthread_rwlock_init(&lock->object, NULL) == 0 ? true : false; + return os_rwlock_init(&lock->object) == 0 ? true : false; } static inline void rwlock_rdlock(struct rwlock *lock) LOCKS_SHARED(*lock) NO_LOCK_ANALYSIS { - pthread_rwlock_rdlock(&lock->object); + os_rwlock_rdlock(&lock->object); } static inline void rwlock_wrlock(struct rwlock *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { - pthread_rwlock_wrlock(&lock->object); + os_rwlock_wrlock(&lock->object); } static inline void rwlock_unlock(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS { - pthread_rwlock_unlock(&lock->object); + os_rwlock_unlock(&lock->object); } static inline void rwlock_destroy(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS { - pthread_rwlock_destroy(&lock->object); + os_rwlock_destroy(&lock->object); } /* Condition variable that uses the lock annotations. */ struct LOCKABLE cond { - pthread_cond_t object; -#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ - || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + korp_cond object; + +#if !CONFIG_HAS_CLOCK_NANOSLEEP \ + && (!CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ + || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) clockid_t clock; #endif }; @@ -147,43 +149,49 @@ cond_init_monotonic(struct cond *cond) fail: pthread_condattr_destroy(&attr); #else - if (pthread_cond_init(&cond->object, NULL) != 0) + if (os_cond_init(&cond->object) != 0) return false; ret = true; #endif -#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ - || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP +#if !CONFIG_HAS_CLOCK_NANOSLEEP \ + && (!CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ + || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) cond->clock = CLOCK_MONOTONIC; #endif + return ret; } static inline bool cond_init_realtime(struct cond *cond) { - if (pthread_cond_init(&cond->object, NULL) != 0) + if (os_cond_init(&cond->object) != 0) return false; -#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ - || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + +#if !CONFIG_HAS_CLOCK_NANOSLEEP \ + && (!CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ + || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) cond->clock = CLOCK_REALTIME; #endif + return true; } static inline void cond_destroy(struct cond *cond) { - pthread_cond_destroy(&cond->object); + os_cond_destroy(&cond->object); } static inline void cond_signal(struct cond *cond) { - pthread_cond_signal(&cond->object); + os_cond_signal(&cond->object); } #if !CONFIG_HAS_CLOCK_NANOSLEEP + static inline bool cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout, bool abstime) REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS @@ -259,7 +267,7 @@ static inline void cond_wait(struct cond *cond, struct mutex *lock) REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { - pthread_cond_wait(&cond->object, &lock->object); + os_cond_wait(&cond->object, &lock->object); } #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c index 01a1dab3..b21aa197 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c @@ -47,6 +47,23 @@ random_buf(void *buf, size_t len) } } +#elif defined(BH_PLATFORM_WINDOWS) + +#include + +void +random_buf(void *buf, size_t len) +{ + static int crypt_initialized = 0; + static HCRYPTPROV provider; + if (!crypt_initialized) { + CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT); + crypt_initialized = 1; + } + CryptGenRandom(provider, len, buf); +} + #else static int urandom; 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 7f6e9b94..7c728728 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 @@ -83,7 +83,7 @@ #define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0 #endif -#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) +#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) && !defined(_WIN32) #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1 #else #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0 diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index d718a2d7..b1e26c22 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -56,6 +56,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 4fb566d6..6066cf11 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -326,6 +326,61 @@ os_cond_broadcast(korp_cond *cond) return BHT_OK; } +int +os_rwlock_init(korp_rwlock *lock) +{ + assert(lock); + + if (pthread_rwlock_init(lock, NULL) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int +os_rwlock_rdlock(korp_rwlock *lock) +{ + assert(lock); + + if (pthread_rwlock_rdlock(lock) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int +os_rwlock_wrlock(korp_rwlock *lock) +{ + assert(lock); + + if (pthread_rwlock_wrlock(lock) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int +os_rwlock_unlock(korp_rwlock *lock) +{ + assert(lock); + + if (pthread_rwlock_unlock(lock) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int +os_rwlock_destroy(korp_rwlock *lock) +{ + assert(lock); + + if (pthread_rwlock_destroy(lock) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + int os_thread_join(korp_tid thread, void **value_ptr) { diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 3fd1c258..a5b0bc8b 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -58,6 +58,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/esp-idf/platform_internal.h b/core/shared/platform/esp-idf/platform_internal.h index 81304ea8..2fe3b0cc 100644 --- a/core/shared/platform/esp-idf/platform_internal.h +++ b/core/shared/platform/esp-idf/platform_internal.h @@ -39,6 +39,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef unsigned int korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 7b4789c9..c9446293 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -57,6 +57,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 7029bb8d..f02fc9db 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -238,6 +238,56 @@ os_cond_signal(korp_cond *cond); int os_cond_broadcast(korp_cond *cond); +/** + * Initialize readwrite lock object + * + * @param cond [OUTPUT] pointer to a lock object variable + * + * @return 0 if success + */ +int +os_rwlock_init(korp_rwlock *lock); + +/** + * Acquire the read lock + * + * @param lock lock variable + * + * @return 0 if success + */ +int +os_rwlock_rdlock(korp_rwlock *lock); + +/** + * Acquire the write lock + * + * @param lock lock variable + * + * @return 0 if success + */ +int +os_rwlock_wrlock(korp_rwlock *lock); + +/** + * Unlocks the lock object + * + * @param lock lock variable + * + * @return 0 if success + */ +int +os_rwlock_unlock(korp_rwlock *lock); + +/** + * Destroy a lock object + * + * @param lock lock variable + * + * @return 0 if success + */ +int +os_rwlock_destroy(korp_rwlock *lock); + /** * Creates a new POSIX-like semaphore or opens an existing * semaphore. The semaphore is identified by name. For details of diff --git a/core/shared/platform/linux-sgx/platform_internal.h b/core/shared/platform/linux-sgx/platform_internal.h index d18f015e..01bf63e9 100644 --- a/core/shared/platform/linux-sgx/platform_internal.h +++ b/core/shared/platform/linux-sgx/platform_internal.h @@ -50,6 +50,7 @@ typedef pthread_t korp_thread; typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; +typedef pthread_rwlock_t korp_rwlock; typedef unsigned int korp_sem; #ifndef SGX_DISABLE_PTHREAD diff --git a/core/shared/platform/linux-sgx/sgx_thread.c b/core/shared/platform/linux-sgx/sgx_thread.c index 1cb2f5d0..c2679275 100644 --- a/core/shared/platform/linux-sgx/sgx_thread.c +++ b/core/shared/platform/linux-sgx/sgx_thread.c @@ -210,3 +210,68 @@ os_thread_get_stack_boundary() /* TODO: get sgx stack boundary */ return NULL; } + +int +os_rwlock_init(korp_rwlock *lock) +{ +#ifndef SGX_DISABLE_PTHREAD + assert(lock); + + if (pthread_rwlock_init(lock, NULL) != BHT_OK) + return BHT_ERROR; +#endif + + return BHT_OK; +} + +int +os_rwlock_rdlock(korp_rwlock *lock) +{ +#ifndef SGX_DISABLE_PTHREAD + assert(lock); + + if (pthread_rwlock_rdlock(lock) != BHT_OK) + return BHT_ERROR; +#endif + + return BHT_OK; +} + +int +os_rwlock_wrlock(korp_rwlock *lock) +{ +#ifndef SGX_DISABLE_PTHREAD + assert(lock); + + if (pthread_rwlock_wrlock(lock) != BHT_OK) + return BHT_ERROR; +#endif + + return BHT_OK; +} + +int +os_rwlock_unlock(korp_rwlock *lock) +{ +#ifndef SGX_DISABLE_PTHREAD + assert(lock); + + if (pthread_rwlock_unlock(lock) != BHT_OK) + return BHT_ERROR; +#endif + + return BHT_OK; +} + +int +os_rwlock_destroy(korp_rwlock *lock) +{ +#ifndef SGX_DISABLE_PTHREAD + assert(lock); + + if (pthread_rwlock_destroy(lock) != BHT_OK) + return BHT_ERROR; +#endif + + return BHT_OK; +} diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 8439f872..c4d722d0 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -55,6 +55,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index b5bbdacd..74d2dc9e 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -41,6 +41,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h index f72f6032..dde213f3 100644 --- a/core/shared/platform/vxworks/platform_internal.h +++ b/core/shared/platform/vxworks/platform_internal.h @@ -54,6 +54,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 500ab200..d98f44eb 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -57,6 +57,11 @@ typedef void *korp_tid; typedef void *korp_mutex; typedef void *korp_sem; +typedef struct { + SRWLOCK lock; + bool exclusive; +} korp_rwlock; + /** * Create the mutex when os_mutex_lock is called, and no need to * CloseHandle() for the static lock's lifetime, since diff --git a/core/shared/platform/windows/win_socket.c b/core/shared/platform/windows/win_socket.c index 9a1c7a3c..f0428269 100644 --- a/core/shared/platform/windows/win_socket.c +++ b/core/shared/platform/windows/win_socket.c @@ -206,6 +206,14 @@ os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out) return BHT_OK; } +int +os_socket_connect(bh_socket_t socket, const char *addr, int port) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + int os_socket_addr_resolve(const char *host, const char *service, uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4, diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index 09cf0c63..ebbd6188 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -541,6 +541,62 @@ os_mutex_unlock(korp_mutex *mutex) return ReleaseMutex(*mutex) ? BHT_OK : BHT_ERROR; } +int +os_rwlock_init(korp_rwlock *lock) +{ + bh_assert(lock); + + InitializeSRWLock(&(lock->lock)); + lock->exclusive = false; + + return BHT_OK; +} + +int +os_rwlock_rdlock(korp_rwlock *lock) +{ + bh_assert(lock); + + AcquireSRWLockShared(&(lock->lock)); + + return BHT_OK; +} + +int +os_rwlock_wrlock(korp_rwlock *lock) +{ + bh_assert(lock); + + AcquireSRWLockExclusive(&(lock->lock)); + lock->exclusive = true; + + return BHT_OK; +} + +int +os_rwlock_unlock(korp_rwlock *lock) +{ + bh_assert(lock); + + if (lock->exclusive) { + lock->exclusive = false; + ReleaseSRWLockExclusive(&(lock->lock)); + } + else { + ReleaseSRWLockShared(&(lock->lock)); + } + + return BHT_OK; +} + +int +os_rwlock_destroy(korp_rwlock *lock) +{ + (void)lock; + + return BHT_OK; +} + int os_cond_init(korp_cond *cond) { diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index db88f42b..5f355666 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -13,8 +13,6 @@ set (WAMR_BUILD_PLATFORM "windows") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -set (CMAKE_C_STANDARD 99) - add_definitions(-DCOMPILING_WASM_RUNTIME_API=1) # Set WAMR_BUILD_TARGET, currently values supported: @@ -96,6 +94,15 @@ if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) set (WAMR_BUILD_SIMD 0) endif () +if (WAMR_BUILD_LIBC_WASI EQUAL 1) + set (CMAKE_C_STANDARD 11) + if (MSVC) + add_compile_options(/experimental:c11atomics) + endif() +else() + set (CMAKE_C_STANDARD 99) +endif() + set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) From a9d008f942efa2a471e48becb60936b34411db22 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Sat, 22 Jul 2023 01:46:10 +0100 Subject: [PATCH 02/18] Use `_fullpath` function on windows to get absolute path of a directory (#2377) There is no standard `realpath` function in the C/C++ standard libraries for Windows, use `_fullpath` function instead to get absolute path of a directory. --- core/iwasm/common/wasm_runtime_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 5467065f..9269cae3 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2895,7 +2895,11 @@ 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 if (!path) { if (error_buf) snprintf(error_buf, error_buf_size, From fe4ee37122dc1a8b534942467805821df29f4791 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Mon, 24 Jul 2023 08:14:52 +0100 Subject: [PATCH 03/18] Add more fixes for wasi libc on windows (#2380) * disable translations of errno codes that aren't defined on Windows * undef `min()` macro if it is defined to not conflict with the `min()` function we define * implement `shed_yield` wasi call * disable some of the features in the config for windows by default --- .../sandboxed-system-primitives/src/posix.c | 29 +++++++++++++++---- .../src/ssp_config.h | 9 +++--- 2 files changed, 28 insertions(+), 10 deletions(-) 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 3038e3d4..cf8c1258 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 @@ -21,6 +21,18 @@ #include "rights.h" #include "str.h" +/* Some platforms (e.g. Windows) already define `min()` macro. + We're undefing it here to make sure the `min` call does exactly + what we want it to do. */ +#ifdef min +#undef min +#endif +static inline size_t +min(size_t a, size_t b) +{ + return a > b ? b : a; +} + #if 0 /* TODO: -std=gnu99 causes compile error, comment them first */ // struct iovec must have the same layout as __wasi_iovec_t. static_assert(offsetof(struct iovec, iov_base) == @@ -86,7 +98,9 @@ convert_errno(int error) X(EDEADLK), X(EDESTADDRREQ), X(EDOM), +#ifdef EDQUOT X(EDQUOT), +#endif X(EEXIST), X(EFAULT), X(EFBIG), @@ -103,7 +117,9 @@ convert_errno(int error) X(EMFILE), X(EMLINK), X(EMSGSIZE), +#ifdef EMULTIHOP X(EMULTIHOP), +#endif X(ENAMETOOLONG), X(ENETDOWN), X(ENETRESET), @@ -142,7 +158,9 @@ convert_errno(int error) X(EROFS), X(ESPIPE), X(ESRCH), +#ifdef ESTALE X(ESTALE), +#endif X(ETIMEDOUT), X(ETXTBSY), X(EXDEV), @@ -3591,8 +3609,13 @@ wasmtime_ssp_sock_shutdown( __wasi_errno_t wasmtime_ssp_sched_yield(void) { +#ifdef BH_PLATFORM_WINDOWS + if (!SwitchToThread()) + return __WASI_EAGAIN; +#else if (sched_yield() < 0) return convert_errno(errno); +#endif return 0; } @@ -3756,12 +3779,6 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask) return true; } -static inline size_t -min(size_t a, size_t b) -{ - return a > b ? b : a; -} - static void init_address_mask(uint8_t *buf, size_t buflen, size_t mask) { 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 7c728728..fb0202f9 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,7 +47,8 @@ #define CONFIG_HAS_CLOCK_NANOSLEEP 0 #endif -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM) \ + && !defined(_WIN32) #define CONFIG_HAS_FDATASYNC 1 #else #define CONFIG_HAS_FDATASYNC 0 @@ -65,13 +66,13 @@ #endif #endif -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) #define CONFIG_HAS_POSIX_FALLOCATE 1 #else #define CONFIG_HAS_POSIX_FALLOCATE 0 #endif -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) #define CONFIG_HAS_PREADV 1 #else #define CONFIG_HAS_PREADV 0 @@ -89,7 +90,7 @@ #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0 #endif -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) #define CONFIG_HAS_PWRITEV 1 #else #define CONFIG_HAS_PWRITEV 0 From 5463ea4a2017d4ceb3cc22fee2bdac4cd5c3f508 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Tue, 25 Jul 2023 03:35:05 +0100 Subject: [PATCH 04/18] Temporarily disable code that does not compile on windows (#2386) And return ENOSYS. We do that so we can at least compile the code on CI. We'll be gradually enabling more and more functions. Also, enabled `proc_raise()` for windows. --- .github/workflows/compilation_on_windows.yml | 4 +- core/iwasm/common/wasm_runtime_common.c | 9 +- .../sandboxed-system-primitives/src/posix.c | 140 +++++++++++++++++- .../platform/windows/platform_internal.h | 1 + 4 files changed, 149 insertions(+), 5 deletions(-) diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 0d38e8ae..416d7609 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -60,12 +60,14 @@ jobs: "-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_DEBUG_INTERP=1", "-DWAMR_BUILD_LIB_PTHREAD=1", - "-DWAMR_BUILD_LIB_WASI_THREADS=1" + "-DWAMR_BUILD_LIB_WASI_THREADS=1", + "-DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1" ] steps: - uses: actions/checkout@v3 - name: clone uvwasi library + if: ${{ !contains(matrix.build_options, '-DWAMR_BUILD_LIBC_UVWASI=0') }} run: | cd core/deps git clone https://github.com/nodejs/uvwasi.git diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 9269cae3..32c65203 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2907,8 +2907,15 @@ 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) { if (error_buf) snprintf(error_buf, error_buf_size, 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 cf8c1258..66869355 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 @@ -216,6 +216,7 @@ convert_timespec(const struct timespec *ts) } // Converts a CloudABI clock identifier to a POSIX clock identifier. +#ifndef BH_PLATFORM_WINDOWS static bool convert_clockid(__wasi_clockid_t in, clockid_t *out) { @@ -240,6 +241,7 @@ convert_clockid(__wasi_clockid_t in, clockid_t *out) return false; } } +#endif static void wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr, @@ -321,6 +323,9 @@ __wasi_errno_t wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) { +#ifdef BH_PLATFORM_WINDOWS + return __WASI_ENOSYS; +#else clockid_t nclock_id; if (!convert_clockid(clock_id, &nclock_id)) return __WASI_EINVAL; @@ -329,6 +334,7 @@ wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, return convert_errno(errno); *resolution = convert_timespec(&ts); return 0; +#endif } __wasi_errno_t @@ -336,6 +342,9 @@ wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, __wasi_timestamp_t *time) { +#ifdef BH_PLATFORM_WINDOWS + return __WASI_ENOSYS; +#else clockid_t nclock_id; if (!convert_clockid(clock_id, &nclock_id)) return __WASI_EINVAL; @@ -344,6 +353,7 @@ wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, return convert_errno(errno); *time = convert_timespec(&ts); return 0; +#endif } struct fd_prestat { @@ -443,8 +453,10 @@ struct fd_object { union { // Data associated with directory file descriptors. struct { - struct mutex lock; // Lock to protect members below. - DIR *handle; // Directory handle. + struct mutex lock; // Lock to protect members below. +#ifndef BH_PLATFORM_WINDOWS + DIR *handle; // Directory handle. +#endif __wasi_dircookie_t offset; // Offset of the directory. } directory; }; @@ -579,6 +591,9 @@ fd_determine_type_rights(int 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); @@ -648,6 +663,7 @@ fd_determine_type_rights(int fd, __wasi_filetype_t *type, break; } return 0; +#endif } // Returns the underlying file descriptor number of a file descriptor @@ -672,6 +688,9 @@ fd_number(const struct fd_object *fo) static void fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) { +#ifdef BH_PLATFORM_WINDOWS + return __WASI_ENOSYS; +#else if (refcount_release(&fo->refcount)) { switch (fo->type) { case __WASI_FILETYPE_DIRECTORY: @@ -691,6 +710,7 @@ fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) } wasm_runtime_free(fo); } +#endif } // Inserts an already existing file descriptor into the file descriptor @@ -698,6 +718,9 @@ fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) bool fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) { +#ifdef BH_PLATFORM_WINDOWS + return false; +#else __wasi_filetype_t type; __wasi_rights_t rights_base, rights_inheriting; struct fd_object *fo; @@ -741,6 +764,7 @@ 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. @@ -784,6 +808,9 @@ fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, __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); @@ -801,6 +828,7 @@ fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, fo->directory.handle = NULL; } return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); +#endif } __wasi_errno_t @@ -938,6 +966,9 @@ wasmtime_ssp_fd_datasync( #endif __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); @@ -953,6 +984,7 @@ wasmtime_ssp_fd_datasync( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -963,6 +995,9 @@ wasmtime_ssp_fd_pread( __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; @@ -1027,6 +1062,7 @@ wasmtime_ssp_fd_pread( return 0; } #endif +#endif } __wasi_errno_t @@ -1037,6 +1073,9 @@ wasmtime_ssp_fd_pwrite( __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, __wasi_filesize_t offset, size_t *nwritten) { +#ifdef BH_PLATFORM_WINDOWS + return __WASI_ENOSYS; +#else if (iovcnt == 0) return __WASI_EINVAL; @@ -1081,6 +1120,7 @@ wasmtime_ssp_fd_pwrite( return convert_errno(errno); *nwritten = (size_t)len; return 0; +#endif } __wasi_errno_t @@ -1090,6 +1130,9 @@ wasmtime_ssp_fd_read( #endif __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); @@ -1102,6 +1145,7 @@ wasmtime_ssp_fd_read( return convert_errno(errno); *nread = (size_t)len; return 0; +#endif } __wasi_errno_t @@ -1227,6 +1271,9 @@ wasmtime_ssp_fd_fdstat_get( #endif __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; @@ -1270,6 +1317,7 @@ wasmtime_ssp_fd_fdstat_get( if ((ret & O_SYNC) != 0) buf->fs_flags |= __WASI_FDFLAG_SYNC; return 0; +#endif } __wasi_errno_t @@ -1279,6 +1327,9 @@ wasmtime_ssp_fd_fdstat_set_flags( #endif __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; @@ -1310,6 +1361,7 @@ wasmtime_ssp_fd_fdstat_set_flags( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -1344,6 +1396,9 @@ wasmtime_ssp_fd_sync( #endif __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); @@ -1355,6 +1410,7 @@ wasmtime_ssp_fd_sync( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -1364,6 +1420,9 @@ wasmtime_ssp_fd_write( #endif __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); @@ -1398,6 +1457,7 @@ wasmtime_ssp_fd_write( return convert_errno(errno); *nwritten = (size_t)len; return 0; +#endif } __wasi_errno_t @@ -1476,6 +1536,9 @@ wasmtime_ssp_fd_allocate( #endif __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); @@ -1499,6 +1562,7 @@ wasmtime_ssp_fd_allocate( if (ret != 0) return convert_errno(ret); return 0; +#endif } // Reads the entire contents of a symbolic link, returning the contents @@ -1567,6 +1631,9 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, 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); @@ -1786,6 +1853,7 @@ fail: fd_object_release(fo); return error; #endif +#endif } static __wasi_errno_t @@ -1817,6 +1885,9 @@ wasmtime_ssp_path_create_directory( #endif __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, @@ -1829,11 +1900,13 @@ wasmtime_ssp_path_create_directory( if (ret < 0) return convert_errno(errno); return 0; +#endif } 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; @@ -1854,7 +1927,7 @@ validate_path(const char *path, struct fd_prestats *pt) return true; } } - +#endif return false; } @@ -1867,6 +1940,9 @@ wasmtime_ssp_path_link( 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, @@ -1915,6 +1991,7 @@ wasmtime_ssp_path_link( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -1927,6 +2004,9 @@ wasmtime_ssp_path_open( __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; @@ -2055,6 +2135,7 @@ wasmtime_ssp_path_open( return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, rights_inheriting & max_inheriting, fd); +#endif } // Copies out directory entry metadata or filename, potentially @@ -2079,6 +2160,9 @@ wasmtime_ssp_fd_readdir( __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); @@ -2168,6 +2252,7 @@ wasmtime_ssp_fd_readdir( mutex_unlock(&fo->directory.lock); fd_object_release(fo); return 0; +#endif } __wasi_errno_t @@ -2178,6 +2263,9 @@ wasmtime_ssp_path_readlink( __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); @@ -2194,6 +2282,7 @@ wasmtime_ssp_path_readlink( return convert_errno(errno); *bufused = (size_t)len < bufsize ? (size_t)len : bufsize; return 0; +#endif } __wasi_errno_t @@ -2204,6 +2293,9 @@ wasmtime_ssp_path_rename( __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) { +#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, @@ -2226,8 +2318,10 @@ wasmtime_ssp_path_rename( 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) @@ -2242,6 +2336,7 @@ convert_stat(const struct stat *in, __wasi_filestat_t *out) .st_ctim = convert_timespec(&in->st_ctim), }; } +#endif __wasi_errno_t wasmtime_ssp_fd_filestat_get( @@ -2250,6 +2345,9 @@ wasmtime_ssp_fd_filestat_get( #endif __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); @@ -2271,6 +2369,7 @@ wasmtime_ssp_fd_filestat_get( if (ret < 0) return convert_errno(errno); return 0; +#endif } static void @@ -2288,6 +2387,7 @@ 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 @@ -2315,6 +2415,7 @@ convert_utimens_arguments(__wasi_timestamp_t st_atim, ts[1].tv_nsec = UTIME_OMIT; } } +#endif __wasi_errno_t wasmtime_ssp_fd_filestat_set_size( @@ -2323,6 +2424,9 @@ wasmtime_ssp_fd_filestat_set_size( #endif __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); @@ -2334,6 +2438,7 @@ wasmtime_ssp_fd_filestat_set_size( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -2344,6 +2449,9 @@ wasmtime_ssp_fd_filestat_set_times( __wasi_fd_t fd, __wasi_timestamp_t st_atim, __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)) @@ -2364,6 +2472,7 @@ wasmtime_ssp_fd_filestat_set_times( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -2374,6 +2483,9 @@ wasmtime_ssp_path_filestat_get( __wasi_fd_t fd, __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); @@ -2404,6 +2516,7 @@ wasmtime_ssp_path_filestat_get( else if (S_ISSOCK(sb.st_mode)) buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; return 0; +#endif } __wasi_errno_t @@ -2415,6 +2528,9 @@ wasmtime_ssp_path_filestat_set_times( size_t pathlen, __wasi_timestamp_t st_atim, __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)) @@ -2443,6 +2559,7 @@ wasmtime_ssp_path_filestat_set_times( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -2453,6 +2570,9 @@ wasmtime_ssp_path_symlink( const char *old_path, 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); @@ -2480,6 +2600,7 @@ wasmtime_ssp_path_symlink( if (ret < 0) return convert_errno(errno); return 0; +#endif } __wasi_errno_t @@ -2489,6 +2610,9 @@ wasmtime_ssp_path_unlink_file( #endif __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); @@ -2517,6 +2641,7 @@ wasmtime_ssp_path_unlink_file( return convert_errno(errno); } return 0; +#endif } __wasi_errno_t @@ -2526,6 +2651,9 @@ wasmtime_ssp_path_remove_directory( #endif __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, @@ -2546,6 +2674,7 @@ wasmtime_ssp_path_remove_directory( return convert_errno(errno); } return 0; +#endif } __wasi_errno_t @@ -2556,6 +2685,9 @@ wasmtime_ssp_poll_oneoff( const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, size_t *nevents) NO_LOCK_ANALYSIS { +#ifdef BH_PLATFORM_WINDOWS + return __WASI_ENOSYS; +#else // Sleeping. if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) { out[0] = (__wasi_event_t){ @@ -2727,6 +2859,7 @@ wasmtime_ssp_poll_oneoff( else { timeout = -1; } + int ret = poll(pfds, nsubscriptions, timeout); __wasi_errno_t error = 0; @@ -2803,6 +2936,7 @@ wasmtime_ssp_poll_oneoff( wasm_runtime_free(fos); wasm_runtime_free(pfds); return error; +#endif } #if 0 diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index d98f44eb..b147c5e5 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { From ea763009b78d2e9cf247fd96af4a342e20a11cba Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Wed, 9 Aug 2023 02:40:59 +0100 Subject: [PATCH 05/18] Enable running spec tests on Windows (#2423) Update wamr-test-suites scripts to enable running spec tests on Windows. We don't enable those tests in CI yet as not all of them are passing. --- core/iwasm/interpreter/wasm_runtime.c | 5 +- product-mini/platforms/windows/main.c | 3 +- .../wamr-test-suites/spec-test-script/all.py | 36 ++++- .../spec-test-script/runtest.py | 151 ++++++++++++------ tests/wamr-test-suites/test_wamr.sh | 25 ++- 5 files changed, 156 insertions(+), 64 deletions(-) diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index eef2e368..88232e79 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -308,8 +308,9 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, } #ifdef BH_PLATFORM_WINDOWS - if (!os_mem_commit(mapped_mem, memory_data_size, - MMAP_PROT_READ | MMAP_PROT_WRITE)) { + if (memory_data_size > 0 + && !os_mem_commit(mapped_mem, memory_data_size, + MMAP_PROT_READ | MMAP_PROT_WRITE)) { set_error_buf(error_buf, error_buf_size, "commit memory failed"); os_munmap(mapped_mem, map_size); goto fail1; diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index b7cf8143..0f7fa0b7 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -142,7 +142,8 @@ app_instance_repl(wasm_module_inst_t module_inst) char *cmd; size_t n; - while ((printf("webassembly> "), cmd = fgets(buffer, sizeof(buffer), stdin)) + while ((printf("webassembly> "), fflush(stdout), + cmd = fgets(buffer, sizeof(buffer), stdin)) != NULL) { bh_assert(cmd); n = strlen(cmd); diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index bd5b89ce..5868b326 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -6,7 +6,7 @@ import argparse import multiprocessing as mp -import os +import platform import pathlib import subprocess import sys @@ -28,12 +28,26 @@ To run a single GC case: --aot-compiler wamrc --gc spec/test/core/xxx.wast """ -PLATFORM_NAME = os.uname().sysname.lower() -IWASM_CMD = "../../../product-mini/platforms/" + PLATFORM_NAME + "/build/iwasm" +def exe_file_path(base_path: str) -> str: + if platform.system().lower() == "windows": + base_path += ".exe" + return base_path + +def get_iwasm_cmd(platform: str) -> str: + build_path = "../../../product-mini/platforms/" + platform + "/build/" + exe_name = "iwasm" + + if platform == "windows": + build_path += "RelWithDebInfo/" + + return exe_file_path(build_path + exe_name) + +PLATFORM_NAME = platform.uname().system.lower() +IWASM_CMD = get_iwasm_cmd(PLATFORM_NAME) IWASM_SGX_CMD = "../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm" IWASM_QEMU_CMD = "iwasm" SPEC_TEST_DIR = "spec/test/core" -WAST2WASM_CMD = "./wabt/out/gcc/Release/wat2wasm" +WAST2WASM_CMD = exe_file_path("./wabt/out/gcc/Release/wat2wasm") SPEC_INTERPRETER_CMD = "spec/interpreter/wasm" WAMRC_CMD = "../../../wamr-compiler/build/wamrc" @@ -133,6 +147,7 @@ def test_case( qemu_flag=False, qemu_firmware='', log='', + no_pty=False ): case_path = pathlib.Path(case_path).resolve() case_name = case_path.stem @@ -151,7 +166,7 @@ def test_case( ): return True - CMD = ["python3", "runtest.py"] + CMD = [sys.executable, "runtest.py"] CMD.append("--wast2wasm") CMD.append(WAST2WASM_CMD if not gc_flag else SPEC_INTERPRETER_CMD) CMD.append("--interpreter") @@ -161,6 +176,8 @@ def test_case( CMD.append(IWASM_QEMU_CMD) else: CMD.append(IWASM_CMD) + if no_pty: + CMD.append("--no-pty") CMD.append("--aot-compiler") CMD.append(WAMRC_CMD) @@ -261,6 +278,7 @@ def test_suite( qemu_flag=False, qemu_firmware='', log='', + no_pty=False ): suite_path = pathlib.Path(SPEC_TEST_DIR).resolve() if not suite_path.exists(): @@ -302,6 +320,7 @@ def test_suite( qemu_flag, qemu_firmware, log, + no_pty, ], ) @@ -339,6 +358,7 @@ def test_suite( qemu_flag, qemu_firmware, log, + no_pty, ) successful_case += 1 except Exception as e: @@ -460,6 +480,8 @@ def main(): nargs="*", help=f"Specify all wanted cases. If not the script will go through all cases under {SPEC_TEST_DIR}", ) + parser.add_argument('--no-pty', action='store_true', + help="Use direct pipes instead of pseudo-tty") options = parser.parse_args() print(options) @@ -490,6 +512,7 @@ def main(): options.qemu_flag, options.qemu_firmware, options.log, + options.no_pty ) end = time.time_ns() print( @@ -512,7 +535,8 @@ def main(): options.gc_flag, options.qemu_flag, options.qemu_firmware, - options.log + options.log, + options.no_pty ) else: ret = True diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index a1e505bd..713a219a 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -5,22 +5,21 @@ from __future__ import print_function import argparse import array import atexit -import fcntl import math import os -# Pseudo-TTY and terminal manipulation -import pty import re import shutil import struct import subprocess import sys import tempfile -import termios import time +import threading import traceback from select import select +from queue import Queue from subprocess import PIPE, STDOUT, Popen +from typing import BinaryIO, Optional, Tuple if sys.version_info[0] == 2: IS_PY_3 = False @@ -52,6 +51,10 @@ def log(data, end='\n'): print(data, end=end) sys.stdout.flush() +def create_tmp_file(suffix: str) -> str: + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp_file: + return tmp_file.name + # TODO: do we need to support '\n' too import platform @@ -62,6 +65,34 @@ else: sep = "\r\n" rundir = None + +class AsyncStreamReader: + def __init__(self, stream: BinaryIO) -> None: + self._queue = Queue() + self._reader_thread = threading.Thread( + daemon=True, + target=AsyncStreamReader._stdout_reader, + args=(self._queue, stream)) + self._reader_thread.start() + + def read(self) -> Optional[bytes]: + return self._queue.get() + + def cleanup(self) -> None: + self._reader_thread.join() + + @staticmethod + def _stdout_reader(queue: Queue, stdout: BinaryIO) -> None: + while True: + try: + queue.put(stdout.read(1)) + except ValueError as e: + if stdout.closed: + queue.put(None) + break + raise e + + class Runner(): def __init__(self, args, no_pty=False): self.no_pty = no_pty @@ -77,11 +108,14 @@ class Runner(): if no_pty: self.process = Popen(args, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=STDOUT, - preexec_fn=os.setsid, env=env) self.stdin = self.process.stdin self.stdout = self.process.stdout else: + import fcntl + # Pseudo-TTY and terminal manipulation + import pty + import termios # Use tty to setup an interactive environment master, slave = pty.openpty() @@ -101,35 +135,53 @@ class Runner(): self.stdin = os.fdopen(master, 'r+b', 0) self.stdout = self.stdin + if platform.system().lower() == "windows": + self._stream_reader = AsyncStreamReader(self.stdout) + else: + self._stream_reader = None + self.buf = "" + def _read_stdout_byte(self) -> Tuple[bool, Optional[bytes]]: + if self._stream_reader: + return True, self._stream_reader.read() + else: + # select doesn't work on file descriptors on Windows. + # however, this method is much faster than using + # queue, so we keep it for non-windows platforms. + [outs,_,_] = select([self.stdout], [], [], 1) + if self.stdout in outs: + return True, self.stdout.read(1) + else: + return False, None + def read_to_prompt(self, prompts, timeout): wait_until = time.time() + timeout while time.time() < wait_until: - [outs,_,_] = select([self.stdout], [], [], 1) - if self.stdout in outs: - read_byte = self.stdout.read(1) - if not read_byte: - # EOF on macOS ends up here. - break - read_byte = read_byte.decode('utf-8') if IS_PY_3 else read_byte + has_value, read_byte = self._read_stdout_byte() + if not has_value: + continue + if not read_byte: + # EOF on macOS ends up here. + break + read_byte = read_byte.decode('utf-8') if IS_PY_3 else read_byte - debug(read_byte) - if self.no_pty: - self.buf += read_byte.replace('\n', '\r\n') - else: - self.buf += read_byte - self.buf = self.buf.replace('\r\r', '\r') + debug(read_byte) + if self.no_pty: + self.buf += read_byte.replace('\n', '\r\n') + else: + self.buf += read_byte + self.buf = self.buf.replace('\r\r', '\r') - # filter the prompts - for prompt in prompts: - pattern = re.compile(prompt) - match = pattern.search(self.buf) - if match: - end = match.end() - buf = self.buf[0:end-len(prompt)] - self.buf = self.buf[end:] - return buf + # filter the prompts + for prompt in prompts: + pattern = re.compile(prompt) + match = pattern.search(self.buf) + if match: + end = match.end() + buf = self.buf[0:end-len(prompt)] + self.buf = self.buf[end:] + return buf return None def writeline(self, str): @@ -140,6 +192,8 @@ class Runner(): self.stdin.write(str_to_write) def cleanup(self): + atexit.unregister(self.cleanup) + if self.process: try: self.writeline("__exit__") @@ -157,6 +211,8 @@ class Runner(): self.stdout = None if not IS_PY_3: sys.exc_clear() + if self._stream_reader: + self._stream_reader.cleanup() def assert_prompt(runner, prompts, timeout, is_need_execute_result): # Wait for the initial prompt @@ -402,9 +458,9 @@ def cast_v128_to_i64x2(numbers, type, lane_type): unpacked = struct.unpack("Q Q", packed) return unpacked, "[{} {}]:{}:v128".format(unpacked[0], unpacked[1], lane_type) - def parse_simple_const_w_type(number, type): number = number.replace('_', '') + number = re.sub(r"nan\((ind|snan)\)", "nan", number) if type in ["i32", "i64"]: number = int(number, 16) if '0x' in number else int(number) return number, "0x{:x}:{}".format(number, type) \ @@ -948,7 +1004,8 @@ def skip_test(form, skip_list): def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): log("Writing WAST module to '%s'" % wast_tempfile) - open(wast_tempfile, 'w').write(form) + with open(wast_tempfile, 'w') as file: + file.write(form) log("Compiling WASM to '%s'" % wasm_tempfile) # default arguments @@ -1070,13 +1127,10 @@ def run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r): def create_tmpfiles(wast_name): tempfiles = [] - (t1fd, wast_tempfile) = tempfile.mkstemp(suffix=".wast") - (t2fd, wasm_tempfile) = tempfile.mkstemp(suffix=".wasm") - tempfiles.append(wast_tempfile) - tempfiles.append(wasm_tempfile) + tempfiles.append(create_tmp_file(".wast")) + tempfiles.append(create_tmp_file(".wasm")) if test_aot: - (t3fd, aot_tempfile) = tempfile.mkstemp(suffix=".aot") - tempfiles.append(aot_tempfile) + tempfiles.append(create_tmp_file(".aot")) # add these temp file to temporal repo, will be deleted when finishing the test temp_file_repo.extend(tempfiles) @@ -1145,10 +1199,10 @@ if __name__ == "__main__": else: SKIP_TESTS = C_SKIP_TESTS - (t1fd, wast_tempfile) = tempfile.mkstemp(suffix=".wast") - (t2fd, wasm_tempfile) = tempfile.mkstemp(suffix=".wasm") + wast_tempfile = create_tmp_file(".wast") + wasm_tempfile = create_tmp_file(".wasm") if test_aot: - (t3fd, aot_tempfile) = tempfile.mkstemp(suffix=".aot") + aot_tempfile = create_tmp_file(".aot") ret_code = 0 try: @@ -1179,17 +1233,16 @@ if __name__ == "__main__": # workaround: spec test changes error message to "malformed" while iwasm still use "invalid" error_msg = m.group(2).replace("malformed", "invalid") log("Testing(malformed)") - f = open(wasm_tempfile, 'wb') - s = m.group(1) - while s: - res = re.match("[^\"]*\"([^\"]*)\"(.*)", s, re.DOTALL) - if IS_PY_3: - context = res.group(1).replace("\\", "\\x").encode("latin1").decode("unicode-escape").encode("latin1") - f.write(context) - else: - f.write(res.group(1).replace("\\", "\\x").decode("string-escape")) - s = res.group(2) - f.close() + with open(wasm_tempfile, 'wb') as f: + s = m.group(1) + while s: + res = re.match("[^\"]*\"([^\"]*)\"(.*)", s, re.DOTALL) + if IS_PY_3: + context = res.group(1).replace("\\", "\\x").encode("latin1").decode("unicode-escape").encode("latin1") + f.write(context) + else: + f.write(res.group(1).replace("\\", "\\x").decode("string-escape")) + s = res.group(2) # compile wasm to aot if test_aot: diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 1448e3e1..b0cb3db2 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -51,7 +51,13 @@ ENABLE_GC_HEAP_VERIFY=0 #unit test case arrary TEST_CASE_ARR=() SGX_OPT="" -PLATFORM=$(uname -s | tr A-Z a-z) +if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then + PLATFORM=windows + PYTHON_EXE=python +else + PLATFORM=$(uname -s | tr A-Z a-z) + PYTHON_EXE=python3 +fi PARALLELISM=0 ENABLE_QEMU=0 QEMU_FIRMWARE="" @@ -385,15 +391,18 @@ function spec_test() darwin) WABT_PLATFORM=macos ;; + windows) + WABT_PLATFORM=windows + ;; *) echo "wabt platform for ${PLATFORM} in unknown" exit 1 ;; esac if [ ! -f /tmp/wabt-1.0.31-${WABT_PLATFORM}.tar.gz ]; then - wget \ + curl -L \ https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ - -P /tmp + -o /tmp/wabt-1.0.31-${WABT_PLATFORM}.tar.gz fi cd /tmp \ @@ -471,12 +480,16 @@ function spec_test() ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} " fi + if [[ ${PLATFORM} == "windows" ]]; then + ARGS_FOR_SPEC_TEST+="--no-pty " + fi + # set log directory ARGS_FOR_SPEC_TEST+="--log ${REPORT_DIR}" cd ${WORK_DIR} - echo "python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt" - python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt + echo "${PYTHON_EXE} ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt" + ${PYTHON_EXE} ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt if [[ ${PIPESTATUS[0]} -ne 0 ]];then echo -e "\nspec tests FAILED" | tee -a ${REPORT_DIR}/spec_test_report.txt exit 1 @@ -645,7 +658,7 @@ function build_iwasm_with_cfg() && if [ -d build ]; then rm -rf build/*; else mkdir build; fi \ && cd build \ && cmake $* .. \ - && make -j 4 + && cmake --build . -j 4 --config RelWithDebInfo fi if [ "$?" != 0 ];then From 3534980c9ed43262be4d601d3239018a00944b33 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Thu, 17 Aug 2023 12:23:27 +0100 Subject: [PATCH 06/18] Fix spec tests on windows, enable spec tests for windows in CI (#2473) --- .github/workflows/compilation_on_windows.yml | 33 ++++++++++++++++++++ core/iwasm/common/wasm_application.c | 19 +++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 416d7609..3805dac3 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -39,6 +39,12 @@ on: # allow to be triggered manually workflow_dispatch: +env: + # For Spec Test + DEFAULT_TEST_OPTIONS: "-s spec -b" + MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M" + THREADS_TEST_OPTIONS: "-s spec -b -p" + # Cancel any in-flight jobs for the same PR/branch so there's only one active # at a time concurrency: @@ -77,3 +83,30 @@ jobs: mkdir build && cd build cmake .. ${{ matrix.build_options }} cmake --build . --config Release --parallel 4 + + test: + runs-on: windows-latest + needs: [build] + strategy: + fail-fast: false + matrix: + running_mode: + [ + "classic-interp", + "fast-interp", + ] + test_option: + [ + $DEFAULT_TEST_OPTIONS, + $MULTI_MODULES_TEST_OPTIONS, + $THREADS_TEST_OPTIONS, + ] + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: run tests + shell: bash + timeout-minutes: 20 + run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} + working-directory: ./tests/wamr-test-suites diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 2ed217e7..a046f2da 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -370,6 +370,18 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, { float32 f32 = strtof(argv[i], &endptr); if (isnan(f32)) { +#ifdef _MSC_VER + /* + * Spec tests require the binary representation of NaN to be + * 0x7fc00000 for float and 0x7ff8000000000000 for float; + * however, in MSVC compiler, strtof doesn't return this + * exact value, causing some of the spec test failures. We + * use the value returned by nan/nanf as it is the one + * expected by spec tests. + * + */ + f32 = nanf(""); +#endif if (argv[i][0] == '-') { union ieee754_float u; u.f = f32; @@ -404,6 +416,9 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, } u; u.val = strtod(argv[i], &endptr); if (isnan(u.val)) { +#ifdef _MSC_VER + u.val = nan(""); +#endif if (argv[i][0] == '-') { union ieee754_double ud; ud.d = u.val; @@ -567,7 +582,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, { #if UINTPTR_MAX == UINT32_MAX if (argv1[k] != 0 && argv1[k] != (uint32)-1) - os_printf("%p:ref.extern", (void *)argv1[k]); + os_printf("0x%" PRIxPTR ":ref.extern", (void *)argv1[k]); else os_printf("extern:ref.null"); k++; @@ -580,7 +595,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, u.parts[1] = argv1[k + 1]; k += 2; if (u.val && u.val != (uintptr_t)-1LL) - os_printf("%p:ref.extern", (void *)u.val); + os_printf("0x%" PRIxPTR ":ref.extern", (void *)u.val); else os_printf("extern:ref.null"); #endif From aefb265b0d0a54563d7996579a1bebc25f39634a Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Fri, 18 Aug 2023 03:37:41 +0100 Subject: [PATCH 07/18] Move commn iwasm code related to WASI to a shared file (#2477) --- product-mini/platforms/common/libc_wasi.c | 155 ++++++++++++++++++++++ product-mini/platforms/posix/main.c | 139 ++++--------------- product-mini/platforms/windows/main.c | 90 ++++--------- 3 files changed, 207 insertions(+), 177 deletions(-) create mode 100644 product-mini/platforms/common/libc_wasi.c diff --git a/product-mini/platforms/common/libc_wasi.c b/product-mini/platforms/common/libc_wasi.c new file mode 100644 index 00000000..0fd2443c --- /dev/null +++ b/product-mini/platforms/common/libc_wasi.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "wasm_export.h" + +typedef struct { + const char *dir_list[8]; + uint32 dir_list_size; + const char *env_list[8]; + uint32 env_list_size; + const char *addr_pool[8]; + uint32 addr_pool_size; + const char *ns_lookup_pool[8]; + uint32 ns_lookup_pool_size; +} libc_wasi_parse_context_t; + +typedef enum { + LIBC_WASI_PARSE_RESULT_OK = 0, + LIBC_WASI_PARSE_RESULT_NEED_HELP, + LIBC_WASI_PARSE_RESULT_BAD_PARAM +} libc_wasi_parse_result_t; + +static void +libc_wasi_print_help() +{ + printf(" --env= Pass wasi environment variables with " + "\"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" " + "--env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host " + "directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); + printf(" --addr-pool= Grant wasi access to the given network " + "addresses in\n"); + printf(" CIRD notation to the program, seperated " + "with ',',\n"); + printf(" for example:\n"); + printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n"); + printf(" --allow-resolve= Allow the lookup of the specific domain " + "name or domain\n"); + printf(" name suffixes using a wildcard, for " + "example:\n"); + printf(" --allow-resolve=example.com # allow the " + "lookup of the specific domain\n"); + printf(" --allow-resolve=*.example.com # allow " + "the lookup of all subdomains\n"); + printf(" --allow-resolve=* # allow any lookup\n"); +} + +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} + +libc_wasi_parse_result_t +libc_wasi_parse(char *arg, libc_wasi_parse_context_t *ctx) +{ + if (!strncmp(arg, "--dir=", 6)) { + if (arg[6] == '\0') + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + if (ctx->dir_list_size >= sizeof(ctx->dir_list) / sizeof(char *)) { + printf("Only allow max dir number %d\n", + (int)(sizeof(ctx->dir_list) / sizeof(char *))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + ctx->dir_list[ctx->dir_list_size++] = arg + 6; + } + else if (!strncmp(arg, "--env=", 6)) { + char *tmp_env; + + if (arg[6] == '\0') + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + if (ctx->env_list_size >= sizeof(ctx->env_list) / sizeof(char *)) { + printf("Only allow max env number %d\n", + (int)(sizeof(ctx->env_list) / sizeof(char *))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + tmp_env = arg + 6; + if (validate_env_str(tmp_env)) + ctx->env_list[ctx->env_list_size++] = tmp_env; + else { + printf("Wasm parse env string failed: expect \"key=value\", " + "got \"%s\"\n", + tmp_env); + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + } + } + /* TODO: parse the configuration file via --addr-pool-file */ + else if (!strncmp(arg, "--addr-pool=", strlen("--addr-pool="))) { + /* like: --addr-pool=100.200.244.255/30 */ + char *token = NULL; + + if ('\0' == arg[12]) + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + + token = strtok(arg + strlen("--addr-pool="), ","); + while (token) { + if (ctx->addr_pool_size + >= sizeof(ctx->addr_pool) / sizeof(char *)) { + printf("Only allow max address number %d\n", + (int)(sizeof(ctx->addr_pool) / sizeof(char *))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + + ctx->addr_pool[ctx->addr_pool_size++] = token; + token = strtok(NULL, ";"); + } + } + else if (!strncmp(arg, "--allow-resolve=", 16)) { + if (arg[16] == '\0') + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + if (ctx->ns_lookup_pool_size + >= sizeof(ctx->ns_lookup_pool) / sizeof(ctx->ns_lookup_pool[0])) { + printf("Only allow max ns lookup number %d\n", + (int)(sizeof(ctx->ns_lookup_pool) + / sizeof(ctx->ns_lookup_pool[0]))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + ctx->ns_lookup_pool[ctx->ns_lookup_pool_size++] = arg + 16; + } + return LIBC_WASI_PARSE_RESULT_OK; +} + +void +libc_wasi_init(wasm_module_t wasm_module, int argc, char **argv, + libc_wasi_parse_context_t *ctx) +{ + wasm_runtime_set_wasi_args(wasm_module, ctx->dir_list, ctx->dir_list_size, + NULL, 0, ctx->env_list, ctx->env_list_size, argv, + argc); + + wasm_runtime_set_wasi_addr_pool(wasm_module, ctx->addr_pool, + ctx->addr_pool_size); + wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ctx->ns_lookup_pool, + ctx->ns_lookup_pool_size); +} diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 45214243..ea4ca7bd 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -14,6 +14,10 @@ #include "bh_read_file.h" #include "wasm_export.h" +#if WASM_ENABLE_LIBC_WASI != 0 +#include "../common/libc_wasi.c" +#endif + #if BH_HAS_DLFCN #include #endif @@ -69,21 +73,7 @@ print_help() printf(" --disable-bounds-checks Disable bounds checks for memory accesses\n"); #endif #if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); - printf(" --addr-pool= Grant wasi access to the given network addresses in\n"); - printf(" CIRD notation to the program, seperated with ',',\n"); - printf(" for example:\n"); - printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n"); - printf(" --allow-resolve= Allow the lookup of the specific domain name or domain\n"); - printf(" name suffixes using a wildcard, for example:\n"); - printf(" --allow-resolve=example.com # allow the lookup of the specific domain\n"); - printf(" --allow-resolve=*.example.com # allow the lookup of all subdomains\n"); - printf(" --allow-resolve=* # allow any lookup\n"); + libc_wasi_print_help(); #endif #if BH_HAS_DLFCN printf(" --native-lib= Register native libraries to the WASM module, which\n"); @@ -262,25 +252,6 @@ resolve_segue_flags(char *str_flags) } #endif /* end of WASM_ENABLE_JIT != 0 */ -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - #if BH_HAS_DLFCN typedef uint32 (*get_native_lib_func)(char **p_module_name, NativeSymbol **p_native_symbols); @@ -493,14 +464,7 @@ main(int argc, char *argv[]) bool disable_bounds_checks = false; #endif #if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; - const char *addr_pool[8] = { NULL }; - uint32 addr_pool_size = 0; - const char *ns_lookup_pool[8] = { NULL }; - uint32 ns_lookup_pool_size = 0; + libc_wasi_parse_context_t wasi_parse_ctx; #endif #if BH_HAS_DLFCN const char *native_lib_list[8] = { NULL }; @@ -516,6 +480,10 @@ main(int argc, char *argv[]) const char *gen_prof_file = NULL; #endif +#if WASM_ENABLE_LIBC_WASI != 0 + memset(&wasi_parse_ctx, 0, sizeof(wasi_parse_ctx)); +#endif + /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { @@ -619,70 +587,6 @@ main(int argc, char *argv[]) return print_help(); } #endif /* end of WASM_ENABLE_JIT != 0 */ -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char *))); - return 1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char *)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char *))); - return 1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", " - "got \"%s\"\n", - tmp_env); - return print_help(); - } - } - /* TODO: parse the configuration file via --addr-pool-file */ - else if (!strncmp(argv[0], "--addr-pool=", strlen("--addr-pool="))) { - /* like: --addr-pool=100.200.244.255/30 */ - char *token = NULL; - - if ('\0' == argv[0][12]) - return print_help(); - - token = strtok(argv[0] + strlen("--addr-pool="), ","); - while (token) { - if (addr_pool_size >= sizeof(addr_pool) / sizeof(char *)) { - printf("Only allow max address number %d\n", - (int)(sizeof(addr_pool) / sizeof(char *))); - return 1; - } - - addr_pool[addr_pool_size++] = token; - token = strtok(NULL, ";"); - } - } - else if (!strncmp(argv[0], "--allow-resolve=", 16)) { - if (argv[0][16] == '\0') - return print_help(); - if (ns_lookup_pool_size - >= sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])) { - printf( - "Only allow max ns lookup number %d\n", - (int)(sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0]))); - return 1; - } - ns_lookup_pool[ns_lookup_pool_size++] = argv[0] + 16; - } -#endif /* WASM_ENABLE_LIBC_WASI */ #if BH_HAS_DLFCN else if (!strncmp(argv[0], "--native-lib=", 13)) { if (argv[0][13] == '\0') @@ -738,8 +642,22 @@ main(int argc, char *argv[]) patch); return 0; } - else + else { +#if WASM_ENABLE_LIBC_WASI != 0 + libc_wasi_parse_result_t result = + libc_wasi_parse(argv[0], &wasi_parse_ctx); + switch (result) { + case LIBC_WASI_PARSE_RESULT_OK: + continue; + case LIBC_WASI_PARSE_RESULT_NEED_HELP: + return print_help(); + case LIBC_WASI_PARSE_RESULT_BAD_PARAM: + return 1; + } +#else return print_help(); +#endif + } } if (argc == 0) @@ -832,12 +750,7 @@ main(int argc, char *argv[]) } #if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); - - wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size); - wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ns_lookup_pool, - ns_lookup_pool_size); + libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx); #endif /* instantiate the module */ diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 0f7fa0b7..ec0647f6 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -10,6 +10,10 @@ #include "bh_read_file.h" #include "wasm_export.h" +#if WASM_ENABLE_LIBC_WASI != 0 +#include "../common/libc_wasi.c" +#endif + static int app_argc; static char **app_argv; @@ -48,12 +52,7 @@ print_help() printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); #if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); + libc_wasi_print_help(); #endif #if WASM_ENABLE_MULTI_MODULE != 0 printf(" --module-path= Indicate a module search path. default is current\n" @@ -172,25 +171,6 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 }; #endif @@ -265,16 +245,17 @@ main(int argc, char *argv[]) bool is_repl_mode = false; bool is_xip_file = false; #if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; + libc_wasi_parse_context_t wasi_parse_ctx; #endif #if WASM_ENABLE_DEBUG_INTERP != 0 char *ip_addr = NULL; int instance_port = 0; #endif +#if WASM_ENABLE_LIBC_WASI != 0 + memset(&wasi_parse_ctx, 0, sizeof(wasi_parse_ctx)); +#endif + /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { @@ -356,38 +337,6 @@ main(int argc, char *argv[]) } } #endif -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char *))); - return 1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char *)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char *))); - return 1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", " - "got \"%s\"\n", - tmp_env); - return print_help(); - } - } -#endif /* WASM_ENABLE_LIBC_WASI */ #if WASM_ENABLE_MULTI_MODULE != 0 else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { module_search_path = handle_module_path(argv[0]); @@ -423,8 +372,22 @@ main(int argc, char *argv[]) patch); return 0; } - else + else { +#if WASM_ENABLE_LIBC_WASI != 0 + libc_wasi_parse_result_t result = + libc_wasi_parse(argv[0], &wasi_parse_ctx); + switch (result) { + case LIBC_WASI_PARSE_RESULT_OK: + continue; + case LIBC_WASI_PARSE_RESULT_NEED_HELP: + return print_help(); + case LIBC_WASI_PARSE_RESULT_BAD_PARAM: + return 1; + } +#else return print_help(); +#endif + } } if (argc == 0) @@ -507,8 +470,7 @@ main(int argc, char *argv[]) } #if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); + libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx); #endif /* instantiate the module */ From 834e0314aac0fb3057f5767e18d8ea3bd0d5ce78 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Wed, 23 Aug 2023 03:51:30 +0100 Subject: [PATCH 08/18] Enable running WASI tests on Windows (#2489) Tests are not passing yet therefore we don't enable them in CI. --- .../wasi-test-script/run_wasi_tests.sh | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 9f13ee08..b5f7fad0 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -9,9 +9,22 @@ readonly MODE=$1 readonly TARGET=$2 readonly WORK_DIR=$PWD -readonly PLATFORM=$(uname -s | tr A-Z a-z) + +if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then + readonly PLATFORM=windows + readonly PYTHON_EXE=python + # see https://github.com/pypa/virtualenv/commit/993ba1316a83b760370f5a3872b3f5ef4dd904c1 + readonly VENV_BIN_DIR=Scripts + readonly IWASM_EXE=$(cygpath -m "${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/RelWithDebInfo/iwasm.exe") +else + readonly PLATFORM=$(uname -s | tr A-Z a-z) + readonly VENV_BIN_DIR=bin + readonly PYTHON_EXE=python3 + readonly IWASM_EXE="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm" +fi + readonly WAMR_DIR="${WORK_DIR}/../../../.." -readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm \ +readonly IWASM_CMD="${IWASM_EXE} \ --allow-resolve=google-public-dns-a.google.com \ --addr-pool=::1/128,127.0.0.1/32" readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=8" @@ -59,11 +72,11 @@ run_aot_tests () { } if [[ $MODE != "aot" ]];then - python3 -m venv wasi-env && source wasi-env/bin/activate - python3 -m pip install -r test-runner/requirements.txt + $PYTHON_EXE -m venv wasi-env && source wasi-env/${VENV_BIN_DIR}/activate + $PYTHON_EXE -m pip install -r test-runner/requirements.txt # Stress test requires max-threads=8 so it's run separately - if [[ -e "${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm" ]]; then + if [[ -e "${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm" ]]; then ${IWASM_CMD_STRESS} ${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm ret=${PIPESTATUS[0]} if [ "${ret}" -ne 0 ]; then @@ -72,7 +85,7 @@ if [[ $MODE != "aot" ]];then fi fi - TEST_RUNTIME_EXE="${IWASM_CMD}" python3 test-runner/wasi_test_runner.py \ + TEST_RUNTIME_EXE="${IWASM_CMD}" $PYTHON_EXE test-runner/wasi_test_runner.py \ -r adapters/wasm-micro-runtime.py \ -t \ ${C_TESTS} \ From 5fd530610a917507137a4ab936c066076174f668 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:42:25 +0100 Subject: [PATCH 09/18] Enable MASM automatically in runtime_lib.cmake (#2634) MASM (Microsoft Macro Assembler) needs to be enabled to successfully compile .asm files on Windows. Without enabling this language automatically in runtime_lib.cmake, Windows cmake projects using WAMR get hard-to-diagnose linker errors about missing symbols as the assembly file is not compiled at all. --- build-scripts/runtime_lib.cmake | 6 +++++- product-mini/platforms/windows/CMakeLists.txt | 1 - samples/basic/CMakeLists.txt | 1 - samples/file/src/CMakeLists.txt | 1 - samples/inst-context-threads/CMakeLists.txt | 1 - samples/inst-context/CMakeLists.txt | 1 - samples/ref-types/CMakeLists.txt | 1 - samples/wasm-c-api/CMakeLists.txt | 1 - 8 files changed, 5 insertions(+), 8 deletions(-) diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 8ac519b7..811009df 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -165,7 +165,11 @@ file (GLOB header ) LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) -enable_language (ASM) +if (WAMR_BUILD_PLATFORM STREQUAL "windows") + enable_language (ASM_MASM) +else() + enable_language (ASM) +endif() include (${SHARED_PLATFORM_CONFIG}) include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index 5f355666..07fe46a6 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -4,7 +4,6 @@ cmake_minimum_required (VERSION 2.9) project (iwasm C ASM CXX) -enable_language(ASM_MASM) # set (CMAKE_VERBOSE_MAKEFILE 1) set (WAMR_BUILD_PLATFORM "windows") diff --git a/samples/basic/CMakeLists.txt b/samples/basic/CMakeLists.txt index 4191ad15..62edf08f 100644 --- a/samples/basic/CMakeLists.txt +++ b/samples/basic/CMakeLists.txt @@ -9,7 +9,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") project (basic) else() project (basic C ASM) - enable_language (ASM_MASM) endif() ################ runtime settings ################ diff --git a/samples/file/src/CMakeLists.txt b/samples/file/src/CMakeLists.txt index 2bc3bec6..1f7a2435 100644 --- a/samples/file/src/CMakeLists.txt +++ b/samples/file/src/CMakeLists.txt @@ -9,7 +9,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") project (iwasm) else() project (iwasm C ASM) - enable_language (ASM_MASM) endif() ################ runtime settings ################ diff --git a/samples/inst-context-threads/CMakeLists.txt b/samples/inst-context-threads/CMakeLists.txt index 7326a543..5ce8696d 100644 --- a/samples/inst-context-threads/CMakeLists.txt +++ b/samples/inst-context-threads/CMakeLists.txt @@ -9,7 +9,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") project (inst-context) else() project (inst-context C ASM) - enable_language (ASM_MASM) endif() ################ runtime settings ################ diff --git a/samples/inst-context/CMakeLists.txt b/samples/inst-context/CMakeLists.txt index b1167d27..af387ca2 100644 --- a/samples/inst-context/CMakeLists.txt +++ b/samples/inst-context/CMakeLists.txt @@ -9,7 +9,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") project (inst-context) else() project (inst-context C ASM) - enable_language (ASM_MASM) endif() ################ runtime settings ################ diff --git a/samples/ref-types/CMakeLists.txt b/samples/ref-types/CMakeLists.txt index 325699b2..fd18e637 100644 --- a/samples/ref-types/CMakeLists.txt +++ b/samples/ref-types/CMakeLists.txt @@ -9,7 +9,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") project(ref-types) else() project (ref-types C ASM) - enable_language (ASM_MASM) endif() ################ runtime settings ################ diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 4dab0185..4189f728 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -9,7 +9,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") project(c-api) else() project (c-api C ASM) - enable_language (ASM_MASM) endif() if(NOT CMAKE_BUILD_TYPE) 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 10/18] 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 b70f8233..59ed016a 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 a834d67f..4cfef6fa 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 2a30ddc9..c554e200 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 c7d9f1de..89b0bc74 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 292bd837..b0666445 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 be509576..2d149bc0 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 0bdb0736..af1d68e9 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 7040037e..ec1481c2 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 e816e847..afaa4a4f 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 444e2440..d143f7be 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 7a593390..75ed5978 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 6ddbd54d..274979c3 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 f6a4ba11..7e9740e6 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 b8574b1a..d59daf14 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 00000000..e6c26c83 --- /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 00000000..d136c0cf --- /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 00000000..a7c7645c --- /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 4abefff1..3de3e189 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 00000000..a0005b59 --- /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 ed254543..02cd78be 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 ea3daf62..8cbaf652 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 2fe3b0cc..6c8fa8e6 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 58292d16..5f9b5436 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 9a666ce5..e40ddfd0 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 00000000..3798a9e7 --- /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 01bf63e9..0dd73048 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 e4de9027..3a911d2b 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 b2de1ab0..1168dedb 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 0c13116f..f94c4b68 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 204f8c83..b20c4a2c 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 7b29b5f0..1cbe2218 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 8fec6dd0..9f29b8fd 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 5f9cc8bc..6abba738 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 dde213f3..a3f7fecc 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 b147c5e5..88ebfec7 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 a68d6317..3c531c17 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 00000000..73b22cf3 --- /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 d2a94e4a..65e0dea0 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 04a6db91..099c5503 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 ba0902cd..5fe8fae1 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) From a874bf0ff8ed267c66ddb0f82a97322655679e3f Mon Sep 17 00:00:00 2001 From: fadumina1 <134293107+fadumina1@users.noreply.github.com> Date: Sun, 22 Oct 2023 14:11:29 +0100 Subject: [PATCH 11/18] Implement wasi clock_time/clock_res get (#2637) Add os_clock_res_get and os_clock_time_get in platform_api_extension.h, and implement them in posix like platforms and windows platform. --- .../sandboxed-system-primitives/src/posix.c | 66 ++++---- .../platform/common/posix/posix_clock.c | 72 ++++++++ .../platform/include/platform_api_extension.h | 20 +++ .../shared/platform/include/platform_common.h | 7 + .../platform/linux-sgx/shared_platform.cmake | 2 + core/shared/platform/windows/win_clock.c | 160 ++++++++++++++++++ product-mini/platforms/nuttx/wamr.mk | 1 + product-mini/platforms/windows/CMakeLists.txt | 6 + 8 files changed, 299 insertions(+), 35 deletions(-) create mode 100644 core/shared/platform/common/posix/posix_clock.c create mode 100644 core/shared/platform/windows/win_clock.c 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 d143f7be..f6479a20 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 @@ -94,22 +94,9 @@ ns_lookup_list_search(char **list, const char *host) return false; } -// Converts a POSIX timespec to a CloudABI 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 CloudABI clock identifier to a POSIX clock identifier. #ifndef BH_PLATFORM_WINDOWS static bool -convert_clockid(__wasi_clockid_t in, clockid_t *out) +wasi_clockid_to_clockid(__wasi_clockid_t in, clockid_t *out) { switch (in) { case __WASI_CLOCK_MONOTONIC: @@ -210,22 +197,37 @@ wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr, } } +static bool +wasi_clockid_to_bh_clockid(__wasi_clockid_t in, bh_clock_id_t *out) +{ + switch (in) { + case __WASI_CLOCK_MONOTONIC: + *out = BH_CLOCK_ID_MONOTONIC; + return true; + case __WASI_CLOCK_PROCESS_CPUTIME_ID: + *out = BH_CLOCK_ID_PROCESS_CPUTIME_ID; + return true; + case __WASI_CLOCK_REALTIME: + *out = BH_CLOCK_ID_REALTIME; + return true; + case __WASI_CLOCK_THREAD_CPUTIME_ID: + *out = BH_CLOCK_ID_THREAD_CPUTIME_ID; + return true; + default: + return false; + } +} + __wasi_errno_t wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else - clockid_t nclock_id; - if (!convert_clockid(clock_id, &nclock_id)) + bh_clock_id_t bh_clockid; + if (!wasi_clockid_to_bh_clockid(clock_id, &bh_clockid)) return __WASI_EINVAL; - struct timespec ts; - if (clock_getres(nclock_id, &ts) < 0) + if (os_clock_res_get(clock_id, resolution) != BHT_OK) return convert_errno(errno); - *resolution = convert_timespec(&ts); - return 0; -#endif + return __WASI_ESUCCESS; } __wasi_errno_t @@ -233,18 +235,12 @@ wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, __wasi_timestamp_t *time) { -#ifdef BH_PLATFORM_WINDOWS - return __WASI_ENOSYS; -#else - clockid_t nclock_id; - if (!convert_clockid(clock_id, &nclock_id)) + bh_clock_id_t bh_clockid; + if (!wasi_clockid_to_bh_clockid(clock_id, &bh_clockid)) return __WASI_EINVAL; - struct timespec ts; - if (clock_gettime(nclock_id, &ts) < 0) + if (os_clock_time_get(clock_id, precision, time) != BHT_OK) return convert_errno(errno); - *time = convert_timespec(&ts); - return 0; -#endif + return __WASI_ESUCCESS; } struct fd_prestat { @@ -2081,7 +2077,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, }; #if CONFIG_HAS_CLOCK_NANOSLEEP clockid_t clock_id; - if (convert_clockid(in[0].u.u.clock.clock_id, &clock_id)) { + if (wasi_clockid_to_clockid(in[0].u.u.clock.clock_id, &clock_id)) { struct timespec ts; convert_timestamp(in[0].u.u.clock.timeout, &ts); int ret = clock_nanosleep( diff --git a/core/shared/platform/common/posix/posix_clock.c b/core/shared/platform/common/posix/posix_clock.c new file mode 100644 index 00000000..3c9f9d56 --- /dev/null +++ b/core/shared/platform/common/posix/posix_clock.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +#define NANOSECONDS_PER_SECOND 1000000000ULL + +static bool +bh_clockid_to_clockid(bh_clock_id_t in, clockid_t *out) +{ + switch (in) { + case BH_CLOCK_ID_MONOTONIC: + *out = CLOCK_MONOTONIC; + return true; +#if defined(CLOCK_PROCESS_CPUTIME_ID) + case BH_CLOCK_ID_PROCESS_CPUTIME_ID: + *out = CLOCK_PROCESS_CPUTIME_ID; + return true; +#endif + case BH_CLOCK_ID_REALTIME: + *out = CLOCK_REALTIME; + return true; +#if defined(CLOCK_THREAD_CPUTIME_ID) + case BH_CLOCK_ID_THREAD_CPUTIME_ID: + *out = CLOCK_THREAD_CPUTIME_ID; + return true; +#endif + default: + errno = EINVAL; + return false; + } +} + +static uint64 +timespec_to_nanoseconds(const struct timespec *ts) +{ + if (ts->tv_sec < 0) + return 0; + if ((uint64)ts->tv_sec >= UINT64_MAX / NANOSECONDS_PER_SECOND) + return UINT64_MAX; + return (uint64)ts->tv_sec * NANOSECONDS_PER_SECOND + (uint64)ts->tv_nsec; +} + +int +os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution) +{ + clockid_t nclock_id; + if (!bh_clockid_to_clockid(clock_id, &nclock_id)) + return BHT_ERROR; + struct timespec ts; + if (clock_getres(nclock_id, &ts) < 0) + return BHT_ERROR; + *resolution = timespec_to_nanoseconds(&ts); + + return BHT_OK; +} + +int +os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) +{ + clockid_t nclock_id; + if (!bh_clockid_to_clockid(clock_id, &nclock_id)) + return BHT_ERROR; + struct timespec ts; + if (clock_gettime(nclock_id, &ts) < 0) + return BHT_ERROR; + *time = timespec_to_nanoseconds(&ts); + + return 0; +} diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index e40ddfd0..381d66fd 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -36,6 +36,26 @@ extern "C" { * 2. To build the app-mgr and app-framework, you must implement it */ +/** + * Get a resolution of the clock + * + * @param clock_id clock identifier + * @param resolution output variable to store the clock resolution + * @return BHT_OK if success; otherwise, BHT_ERROR + */ +int +os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution); + +/** + * Get a current time of the clock + * + * @param clock_id clock identifier + * @param time output variable to store the clock time + * @return BHT_OK if success; otherwise, BHT_ERROR + */ +int +os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time); + /** * Creates a thread * diff --git a/core/shared/platform/include/platform_common.h b/core/shared/platform/include/platform_common.h index 28001af7..62d3e83e 100644 --- a/core/shared/platform/include/platform_common.h +++ b/core/shared/platform/include/platform_common.h @@ -37,6 +37,13 @@ extern "C" { #define BH_TIME_T_MAX LONG_MAX #endif +typedef enum { + BH_CLOCK_ID_REALTIME, + BH_CLOCK_ID_MONOTONIC, + BH_CLOCK_ID_PROCESS_CPUTIME_ID, + BH_CLOCK_ID_THREAD_CPUTIME_ID +} bh_clock_id_t; + #if defined(_MSC_BUILD) #if defined(COMPILING_WASM_RUNTIME_API) __declspec(dllexport) void *BH_MALLOC(unsigned int size); diff --git a/core/shared/platform/linux-sgx/shared_platform.cmake b/core/shared/platform/linux-sgx/shared_platform.cmake index 1168dedb..4fe5d902 100644 --- a/core/shared/platform/linux-sgx/shared_platform.cmake +++ b/core/shared/platform/linux-sgx/shared_platform.cmake @@ -36,6 +36,8 @@ endif() file (GLOB source_all_untrusted ${PLATFORM_SHARED_DIR}/untrusted/*.c) +list(APPEND source_all ${PLATFORM_SHARED_DIR}/../common/posix/posix_clock.c) + set (PLATFORM_SHARED_SOURCE ${source_all}) set (PLATFORM_SHARED_SOURCE_UNTRUSTED ${source_all_untrusted}) diff --git a/core/shared/platform/windows/win_clock.c b/core/shared/platform/windows/win_clock.c new file mode 100644 index 00000000..4e1a5e89 --- /dev/null +++ b/core/shared/platform/windows/win_clock.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include + +#define NANOSECONDS_PER_SECOND 1000000000ULL +#define NANOSECONDS_PER_TICK 100 + +static int +calculate_monotonic_clock_frequency(uint64 *out_frequency) +{ + LARGE_INTEGER frequency; + if (!QueryPerformanceFrequency(&frequency)) { + return BHT_ERROR; + } + else { + *out_frequency = (uint64)frequency.QuadPart; + return BHT_OK; + } +} + +// The implementation below derives from the following source: +// https://github.com/WasmEdge/WasmEdge/blob/b70f48c42922ce5ee7730054b6ac0b1615176285/lib/host/wasi/win.h#L210 +static uint64 +filetime_to_wasi_timestamp(FILETIME filetime) +{ + static const uint64 ntto_unix_epoch = + 134774ULL * 86400ULL * NANOSECONDS_PER_SECOND; + + ULARGE_INTEGER temp = { .LowPart = filetime.dwLowDateTime, + .HighPart = filetime.dwHighDateTime }; + + return (temp.QuadPart * 100ull) - ntto_unix_epoch; +} + +static int +get_performance_counter_value(uint64 *out_counter) +{ + LARGE_INTEGER counter; + if (!QueryPerformanceCounter(&counter)) { + return BHT_ERROR; + } + else { + *out_counter = counter.QuadPart; + return BHT_OK; + } +} + +int +os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution) +{ + switch (clock_id) { + case BH_CLOCK_ID_MONOTONIC: + { + uint64 frequency; + if (calculate_monotonic_clock_frequency(&frequency) == BHT_ERROR) { + return BHT_ERROR; + } + const uint64 result = (uint64)NANOSECONDS_PER_SECOND / frequency; + *resolution = result; + return BHT_OK; + } + case BH_CLOCK_ID_REALTIME: + case BH_CLOCK_ID_PROCESS_CPUTIME_ID: + case BH_CLOCK_ID_THREAD_CPUTIME_ID: + { + PULONG maximum_time; + PULONG minimum_time; + PULONG current_time; + NTSTATUS + status = NtQueryTimerResolution(&maximum_time, &minimum_time, + ¤t_time); + + uint64 result = (uint64)current_time * NANOSECONDS_PER_TICK; + *resolution = result / (uint64)NANOSECONDS_PER_SECOND; + return BHT_OK; + } + default: + errno = EINVAL; + return BHT_ERROR; + } +} + +int +os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) +{ + switch (clock_id) { + case BH_CLOCK_ID_REALTIME: + { + FILETIME sys_now; +#if NTDDI_VERSION >= NTDDI_WIN8 + GetSystemTimePreciseAsFileTime(&sys_now); +#else + GetSystemTimeAsFileTime(&SysNow); +#endif + *time = filetime_to_wasi_timestamp(sys_now); + return BHT_OK; + } + case BH_CLOCK_ID_MONOTONIC: + { + uint64 frequency; + if (calculate_monotonic_clock_frequency(&frequency) == BHT_ERROR) { + return BHT_ERROR; + } + uint64 counter; + if (get_performance_counter_value(&counter) == BHT_ERROR) { + return BHT_ERROR; + } + if (NANOSECONDS_PER_SECOND % frequency == 0) { + *time = counter * NANOSECONDS_PER_SECOND / frequency; + } + else { + uint64 seconds = counter / frequency; + uint64 fractions = counter % frequency; + *time = seconds * NANOSECONDS_PER_SECOND + + (fractions * NANOSECONDS_PER_SECOND) / frequency; + } + return BHT_OK; + } + case BH_CLOCK_ID_PROCESS_CPUTIME_ID: + { + FILETIME creation_time; + FILETIME exit_time; + FILETIME kernel_time; + FILETIME user_time; + + if (!GetProcessTimes(GetCurrentProcess(), &creation_time, + &exit_time, &kernel_time, &user_time)) { + return BHT_ERROR; + } + *time = filetime_to_wasi_timestamp(kernel_time) + + filetime_to_wasi_timestamp(user_time); + + return BHT_OK; + } + case BH_CLOCK_ID_THREAD_CPUTIME_ID: + { + FILETIME creation_time; + FILETIME exit_time; + FILETIME kernel_time; + FILETIME user_time; + + if (!GetProcessTimes(GetCurrentThread(), &creation_time, &exit_time, + &kernel_time, &user_time)) { + return BHT_ERROR; + } + + *time = filetime_to_wasi_timestamp(kernel_time) + + filetime_to_wasi_timestamp(user_time); + + return BHT_OK; + } + default: + errno = EINVAL; + return BHT_ERROR; + } +} \ No newline at end of file diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 099c5503..ec7508e9 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -364,6 +364,7 @@ CSRCS += nuttx_platform.c \ posix_blocking_op.c \ posix_thread.c \ posix_time.c \ + posix_clock.c \ posix_sleep.c \ mem_alloc.c \ ems_kfc.c \ diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index 07fe46a6..02aa3f31 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -153,3 +153,9 @@ target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS}) if (MINGW) target_link_libraries (libiwasm ws2_32) endif () + +if (WIN32) + target_link_libraries(libiwasm ntdll) + + target_link_libraries(iwasm ntdll) +endif() From 75208073c028f860e2539dd40c826437f8161891 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Wed, 25 Oct 2023 01:01:11 +0100 Subject: [PATCH 12/18] Partial windows filesystem implementation (#2657) Implement the necessary os_ filesystem functions to enable successful WASI initialization on Windows. Some small changes were also required to the sockets implementation to use the new windows_handle type. The remaining functions will be implemented in a future PR. --- .../platform/windows/platform_internal.h | 39 +- core/shared/platform/windows/win_clock.c | 33 +- core/shared/platform/windows/win_file.c | 751 +++++++++++++++++- core/shared/platform/windows/win_socket.c | 174 +++- core/shared/platform/windows/win_util.c | 21 + core/shared/platform/windows/win_util.h | 15 + 6 files changed, 972 insertions(+), 61 deletions(-) create mode 100644 core/shared/platform/windows/win_util.c create mode 100644 core/shared/platform/windows/win_util.h diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 88ebfec7..9d1937a4 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -82,8 +83,6 @@ typedef struct korp_cond { struct os_thread_wait_node *thread_wait_list_end; } korp_cond; -#define bh_socket_t SOCKET - unsigned os_getpagesize(); void * @@ -137,14 +136,46 @@ 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; +typedef enum windows_handle_type { + windows_handle_type_socket, + windows_handle_type_file +} windows_handle_type; + +typedef enum windows_access_mode { + windows_access_mode_read = 1 << 0, + windows_access_mode_write = 1 << 1 +} windows_access_mode; + +typedef struct windows_handle { + windows_handle_type type; + windows_access_mode access_mode; + union { + HANDLE handle; + SOCKET socket; + } raw; +} windows_handle; + +typedef struct windows_dir_stream { + // Enough space for the wide filename and the info struct itself + char info_buf[PATH_MAX * sizeof(wchar_t) + sizeof(FILE_ID_BOTH_DIR_INFO)]; + char current_entry_name[PATH_MAX]; + // An offset into info_buf to read the next entry from + DWORD cursor; + int cookie; + windows_handle *handle; +} windows_dir_stream; + +typedef windows_handle *os_file_handle; +typedef windows_dir_stream *os_dir_stream; + #if WASM_ENABLE_UVWASI != 1 typedef HANDLE os_raw_file_handle; #else typedef uint32_t os_raw_file_handle; #endif +#define bh_socket_t windows_handle * + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/windows/win_clock.c b/core/shared/platform/windows/win_clock.c index 4e1a5e89..919debcd 100644 --- a/core/shared/platform/windows/win_clock.c +++ b/core/shared/platform/windows/win_clock.c @@ -5,6 +5,7 @@ #include "platform_api_vmcore.h" #include +#include "win_util.h" #define NANOSECONDS_PER_SECOND 1000000000ULL #define NANOSECONDS_PER_TICK 100 @@ -22,20 +23,6 @@ calculate_monotonic_clock_frequency(uint64 *out_frequency) } } -// The implementation below derives from the following source: -// https://github.com/WasmEdge/WasmEdge/blob/b70f48c42922ce5ee7730054b6ac0b1615176285/lib/host/wasi/win.h#L210 -static uint64 -filetime_to_wasi_timestamp(FILETIME filetime) -{ - static const uint64 ntto_unix_epoch = - 134774ULL * 86400ULL * NANOSECONDS_PER_SECOND; - - ULARGE_INTEGER temp = { .LowPart = filetime.dwLowDateTime, - .HighPart = filetime.dwHighDateTime }; - - return (temp.QuadPart * 100ull) - ntto_unix_epoch; -} - static int get_performance_counter_value(uint64 *out_counter) { @@ -67,9 +54,9 @@ os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution) case BH_CLOCK_ID_PROCESS_CPUTIME_ID: case BH_CLOCK_ID_THREAD_CPUTIME_ID: { - PULONG maximum_time; - PULONG minimum_time; - PULONG current_time; + ULONG maximum_time; + ULONG minimum_time; + ULONG current_time; NTSTATUS status = NtQueryTimerResolution(&maximum_time, &minimum_time, ¤t_time); @@ -94,9 +81,9 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) #if NTDDI_VERSION >= NTDDI_WIN8 GetSystemTimePreciseAsFileTime(&sys_now); #else - GetSystemTimeAsFileTime(&SysNow); + GetSystemTimeAsFileTime(&sys_now); #endif - *time = filetime_to_wasi_timestamp(sys_now); + *time = convert_filetime_to_wasi_timestamp(&sys_now); return BHT_OK; } case BH_CLOCK_ID_MONOTONIC: @@ -131,8 +118,8 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) &exit_time, &kernel_time, &user_time)) { return BHT_ERROR; } - *time = filetime_to_wasi_timestamp(kernel_time) - + filetime_to_wasi_timestamp(user_time); + *time = convert_filetime_to_wasi_timestamp(&kernel_time) + + convert_filetime_to_wasi_timestamp(&user_time); return BHT_OK; } @@ -148,8 +135,8 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) return BHT_ERROR; } - *time = filetime_to_wasi_timestamp(kernel_time) - + filetime_to_wasi_timestamp(user_time); + *time = convert_filetime_to_wasi_timestamp(&kernel_time) + + convert_filetime_to_wasi_timestamp(&user_time); return BHT_OK; } diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 73b22cf3..5120e9a8 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -4,30 +4,586 @@ */ #include "platform_api_extension.h" -#include "platform_internal.h" +#include "libc_errno.h" +#include "win_util.h" + +#define CHECK_VALID_HANDLE_WITH_RETURN_VALUE(win_handle, ret) \ + do { \ + if ((win_handle) == NULL \ + || ((win_handle)->type == windows_handle_type_socket \ + && (win_handle)->raw.socket == INVALID_SOCKET) \ + || ((win_handle)->type == windows_handle_type_file \ + && (win_handle)->raw.handle == INVALID_HANDLE_VALUE)) \ + return (ret); \ + \ + } while (0) + +#define CHECK_VALID_HANDLE(win_handle) \ + CHECK_VALID_HANDLE_WITH_RETURN_VALUE(win_handle, __WASI_EBADF) + +#define CHECK_VALID_FILE_HANDLE(win_handle) \ + do { \ + if ((win_handle) == NULL) \ + return __WASI_EBADF; \ + \ + if ((win_handle)->type == windows_handle_type_socket) \ + return __WASI_EINVAL; \ + \ + if (((win_handle)->type == windows_handle_type_file \ + && (win_handle)->raw.handle == INVALID_HANDLE_VALUE)) \ + return __WASI_EBADF; \ + \ + } while (0) + +#define CHECK_VALID_WIN_DIR_STREAM(win_dir_stream) \ + do { \ + if ((win_dir_stream) == NULL) \ + return __WASI_EINVAL; \ + CHECK_VALID_FILE_HANDLE((win_dir_stream)->handle); \ + } while (0) + +static __wasi_errno_t +convert_winsock_error_code(int error_code) +{ + switch (error_code) { + case WSASYSNOTREADY: + case WSAEWOULDBLOCK: + return __WASI_EAGAIN; + case WSAVERNOTSUPPORTED: + return __WASI_ENOTSUP; + case WSAEINPROGRESS: + return __WASI_EINPROGRESS; + case WSAEPROCLIM: + return __WASI_EBUSY; + case WSAEFAULT: + return __WASI_EFAULT; + case WSAENETDOWN: + return __WASI_ENETDOWN; + case WSAENOTSOCK: + return __WASI_ENOTSOCK; + case WSAEINTR: + return __WASI_EINTR; + case WSAEAFNOSUPPORT: + return __WASI_EAFNOSUPPORT; + case WSAEMFILE: + return __WASI_ENFILE; + case WSAEINVAL: + return __WASI_EINVAL; + case WSAENOBUFS: + return __WASI_ENOBUFS; + case WSAEPROTONOSUPPORT: + return __WASI_EPROTONOSUPPORT; + case WSAEPROTOTYPE: + return __WASI_EPROTOTYPE; + case WSAESOCKTNOSUPPORT: + return __WASI_ENOTSUP; + case WSAEINVALIDPROCTABLE: + case WSAEINVALIDPROVIDER: + case WSAEPROVIDERFAILEDINIT: + case WSANOTINITIALISED: + default: + return __WASI_EINVAL; + } +} + +// Convert a Windows error code to a WASI error code +static __wasi_errno_t +convert_windows_error_code(DWORD windows_error_code) +{ + switch (windows_error_code) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_HANDLE: + case ERROR_NEGATIVE_SEEK: + return __WASI_EINVAL; + case ERROR_SHARING_VIOLATION: + case ERROR_PIPE_BUSY: + return __WASI_EBUSY; + case ERROR_ACCESS_DENIED: + return __WASI_EACCES; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + return __WASI_EEXIST; + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_INVALID_NAME: + return __WASI_ENOENT; + case ERROR_PRIVILEGE_NOT_HELD: + return __WASI_EPERM; + case ERROR_NOT_ENOUGH_MEMORY: + return __WASI_ENOMEM; + case ERROR_NOACCESS: + return __WASI_EFAULT; + case ERROR_DIR_NOT_EMPTY: + return __WASI_ENOTEMPTY; + case ERROR_DIRECTORY: + return __WASI_ENOTDIR; + case ERROR_IO_PENDING: + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_INVALID_FLAGS: + case ERROR_NO_UNICODE_TRANSLATION: + default: + return __WASI_ENOSYS; + } +} + +static __wasi_filetype_t +get_disk_filetype(DWORD attribute) +{ + if (attribute == INVALID_FILE_ATTRIBUTES) + return __WASI_FILETYPE_UNKNOWN; + if (attribute & FILE_ATTRIBUTE_REPARSE_POINT) + return __WASI_FILETYPE_SYMBOLIC_LINK; + if (attribute & FILE_ATTRIBUTE_DIRECTORY) + return __WASI_FILETYPE_DIRECTORY; + + return __WASI_FILETYPE_REGULAR_FILE; +} + +static __wasi_filetype_t +get_socket_filetype(SOCKET socket) +{ + char socket_type = 0; + int size = sizeof(socket_type); + + if (getsockopt(socket, SOL_SOCKET, SO_TYPE, &socket_type, &size) == 0) { + switch (socket_type) { + case SOCK_STREAM: + return __WASI_FILETYPE_SOCKET_STREAM; + case SOCK_DGRAM: + return __WASI_FILETYPE_SOCKET_DGRAM; + } + } + return __WASI_FILETYPE_UNKNOWN; +} + +static __wasi_errno_t +convert_windows_filetype(os_file_handle handle, DWORD filetype, + __wasi_filetype_t *out_filetype) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + + switch (filetype) { + case FILE_TYPE_DISK: + FILE_ATTRIBUTE_TAG_INFO file_info; + + bool success = GetFileInformationByHandleEx( + handle->raw.handle, FileAttributeTagInfo, &file_info, + sizeof(file_info)); + + if (!success + || file_info.FileAttributes == INVALID_FILE_ATTRIBUTES) { + error = convert_windows_error_code(GetLastError()); + break; + } + + *out_filetype = get_disk_filetype(file_info.FileAttributes); + break; + case FILE_TYPE_CHAR: + *out_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; + break; + case FILE_TYPE_PIPE: + if (handle->type == windows_handle_type_socket) + *out_filetype = get_socket_filetype(handle->raw.socket); + else + *out_filetype = __WASI_FILETYPE_BLOCK_DEVICE; + + break; + case FILE_TYPE_REMOTE: + case FILE_TYPE_UNKNOWN: + default: + *out_filetype = __WASI_FILETYPE_UNKNOWN; + } + + return error; +} + +// Converts the input string to a wchar string. +static __wasi_errno_t +convert_to_wchar(const char *str, wchar_t *buf, size_t buf_size) +{ + int converted_chars = + MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, (int)buf_size); + + if (converted_chars == 0) + return convert_windows_error_code(GetLastError()); + + return __WASI_ESUCCESS; +} + +// Get the filepath for a handle. The size of the buffer should be specified in +// terms of wchar. +static __wasi_errno_t +get_handle_filepath(HANDLE handle, wchar_t *buf, DWORD buf_size) +{ + DWORD bufsize_in_chars = buf_size * (sizeof(wchar_t) / sizeof(char)); + DWORD size = GetFinalPathNameByHandleW( + handle, buf, bufsize_in_chars, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE); + + if (size > bufsize_in_chars) + return __WASI_ENAMETOOLONG; + + if (size == 0) + return convert_windows_error_code(GetLastError()); + + return __WASI_ESUCCESS; +} + +static void +init_dir_stream(os_dir_stream dir_stream, os_file_handle handle) +{ + dir_stream->cursor = 0; + dir_stream->handle = handle; + dir_stream->cookie = 0; +} + +// Advances to the next directory entry and optionally reads into to the +// provided buffer if not NULL. +static __wasi_errno_t +read_next_dir_entry(os_dir_stream dir_stream, FILE_ID_BOTH_DIR_INFO **out_entry) +{ + FILE_INFO_BY_HANDLE_CLASS file_info_class; + + if (dir_stream->cookie == 0) + file_info_class = FileIdBothDirectoryRestartInfo; + else + file_info_class = FileIdBothDirectoryInfo; + + if (dir_stream->cursor == 0 + && !GetFileInformationByHandleEx(dir_stream->handle->raw.handle, + file_info_class, dir_stream->info_buf, + sizeof(dir_stream->info_buf))) { + if (out_entry != NULL) + *out_entry = NULL; + DWORD win_error = GetLastError(); + // We've reached the end of the directory - return success + if (win_error == ERROR_NO_MORE_FILES) { + dir_stream->cookie = 0; + dir_stream->cursor = 0; + return __WASI_ESUCCESS; + } + + return convert_windows_error_code(win_error); + } + + FILE_ID_BOTH_DIR_INFO *current_info = + (FILE_ID_BOTH_DIR_INFO *)(dir_stream->info_buf + dir_stream->cursor); + + if (current_info->NextEntryOffset == 0) + dir_stream->cursor = 0; + else + dir_stream->cursor += current_info->NextEntryOffset; + + ++dir_stream->cookie; + + if (out_entry != NULL) + *out_entry = current_info; + else + return __WASI_ESUCCESS; + + // Convert and copy over the wchar filename into the entry_name buf + int ret = WideCharToMultiByte( + CP_UTF8, 0, current_info->FileName, + current_info->FileNameLength / (sizeof(wchar_t) / sizeof(char)), + dir_stream->current_entry_name, sizeof(dir_stream->current_entry_name), + NULL, NULL); + + if (ret == 0) + return convert_windows_error_code(GetLastError()); + + return __WASI_ESUCCESS; +} + +static HANDLE +create_handle(wchar_t *path, bool is_dir, bool follow_symlink, bool readonly) +{ + CREATEFILE2_EXTENDED_PARAMETERS create_params; + + create_params.dwSize = sizeof(create_params); + create_params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + create_params.dwSecurityQosFlags = 0; + create_params.dwFileFlags = 0; + create_params.lpSecurityAttributes = NULL; + create_params.hTemplateFile = NULL; + + if (is_dir) { + create_params.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + create_params.dwFileFlags |= FILE_FLAG_BACKUP_SEMANTICS; + } + + if (!follow_symlink) + create_params.dwFileFlags |= FILE_FLAG_OPEN_REPARSE_POINT; + + DWORD desired_access = GENERIC_READ; + + if (!readonly) { + desired_access |= GENERIC_WRITE; + create_params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY; + } + + return CreateFile2(path, desired_access, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + OPEN_EXISTING, &create_params); +} + +#if WINAPI_PARTITION_DESKTOP +// Modifies the given path in place and replaces it with the filename component +// (including the extension) of the path. +static __wasi_errno_t +extract_filename_from_path(wchar_t *path, size_t buf_size) +{ + wchar_t extension[256]; + wchar_t filename[256]; + __wasi_errno_t error = __WASI_ESUCCESS; + + // Get the filename from the fullpath. + errno_t ret = + _wsplitpath_s(path, NULL, 0, NULL, 0, filename, 256, extension, 256); + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + ret = wcscat_s(filename, 256, extension); + + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + ret = wcscpy_s(path, buf_size, filename); + + if (ret != 0) + error = convert_errno(ret); + + return error; +} + +static __wasi_errno_t +get_handle_to_parent_directory(HANDLE handle, HANDLE *out_dir_handle) +{ + wchar_t path[PATH_MAX]; + __wasi_errno_t error = get_handle_filepath(handle, path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + wchar_t parent_dir_path[PATH_MAX]; + errno_t ret = wcscpy_s(parent_dir_path, PATH_MAX, path); + + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + ret = wcscat_s(parent_dir_path, PATH_MAX, L"/.."); + + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + HANDLE dir_handle = create_handle(parent_dir_path, true, true, true); + + if (dir_handle == INVALID_HANDLE_VALUE) { + error = convert_windows_error_code(GetLastError()); + return error; + } + + *out_dir_handle = dir_handle; + return error; +} + +// The easiest way to get all the necessary file information for files is to +// open a handle to the parent directory and iterate through the entries via +// FileIdBothDirectoryInfo. Other file information classes are only +// available on desktop. +static __wasi_errno_t +get_disk_file_information(HANDLE handle, __wasi_filestat_t *buf) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + HANDLE raw_dir_handle = INVALID_HANDLE_VALUE; + + wchar_t path[PATH_MAX] = L"."; + + if (buf->st_filetype != __WASI_FILETYPE_DIRECTORY) { + error = get_handle_filepath(handle, path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + goto fail; + + error = get_handle_to_parent_directory(handle, &raw_dir_handle); + + if (error != __WASI_ESUCCESS) + goto fail; + + error = extract_filename_from_path(path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + goto fail; + } + else { + raw_dir_handle = handle; + } + + windows_handle dir_handle = { .access_mode = windows_access_mode_read, + .raw = { .handle = raw_dir_handle }, + .type = windows_handle_type_file }; + windows_dir_stream dir_stream; + init_dir_stream(&dir_stream, &dir_handle); + + do { + FILE_ID_BOTH_DIR_INFO *file_id_both_dir_info = NULL; + __wasi_errno_t error = + read_next_dir_entry(&dir_stream, &file_id_both_dir_info); + + if (error != __WASI_ESUCCESS || file_id_both_dir_info == NULL) + goto fail; + + const DWORD filename_length = file_id_both_dir_info->FileNameLength + / (sizeof(wchar_t) / sizeof(char)); + + if (wcsncmp(file_id_both_dir_info->FileName, path, filename_length) + == 0) { + buf->st_ino = + (__wasi_inode_t)(file_id_both_dir_info->FileId.QuadPart); + buf->st_atim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_id_both_dir_info->LastAccessTime.QuadPart); + buf->st_mtim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_id_both_dir_info->LastWriteTime.QuadPart); + buf->st_ctim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_id_both_dir_info->ChangeTime.QuadPart); + buf->st_size = + (__wasi_filesize_t)(file_id_both_dir_info->EndOfFile.QuadPart); + + break; + } + } while (dir_stream.cookie != 0); + + FILE_STANDARD_INFO file_standard_info; + + bool success = GetFileInformationByHandleEx(handle, FileStandardInfo, + &file_standard_info, + sizeof(file_standard_info)); + + if (!success) { + error = convert_windows_error_code(GetLastError()); + goto fail; + } + + buf->st_nlink = (__wasi_linkcount_t)file_standard_info.NumberOfLinks; +fail: + if (buf->st_filetype != __WASI_FILETYPE_DIRECTORY + && raw_dir_handle != INVALID_HANDLE_VALUE) + CloseHandle(raw_dir_handle); + + return error; +} + +#else + +static __wasi_errno_t +get_disk_file_information(HANDLE handle, __wasi_filestat_t *buf) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + FILE_BASIC_INFO file_basic_info; + + int ret = GetFileInformationByHandleEx( + handle, FileBasicInfo, &file_basic_info, sizeof(file_basic_info)); + + if (ret == 0) { + error = convert_windows_error_code(GetLastError()); + return error; + } + + buf->st_atim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_basic_info.LastAccessTime.QuadPart); + buf->st_mtim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_basic_info.LastWriteTime.QuadPart); + buf->st_ctim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_basic_info.ChangeTime.QuadPart); + + BY_HANDLE_FILE_INFORMATION file_info; + ret = GetFileInformationByHandle(handle, &file_info); + + if (ret == 0) { + error = convert_windows_error_code(GetLastError()); + return error; + } + + ULARGE_INTEGER file_size = { .LowPart = file_info.nFileSizeLow, + .HighPart = file_info.nFileSizeHigh }; + buf->st_size = (__wasi_filesize_t)(file_size.QuadPart); + + ULARGE_INTEGER file_id = { .LowPart = file_info.nFileIndexLow, + .HighPart = file_info.nFileIndexHigh }; + buf->st_ino = (__wasi_inode_t)(file_id.QuadPart); + + buf->st_dev = (__wasi_device_t)file_info.dwVolumeSerialNumber; + buf->st_nlink = (__wasi_linkcount_t)file_info.nNumberOfLinks; + + return error; +} + +#endif /* end of !WINAPI_PARTITION_DESKTOP */ + +static __wasi_errno_t +get_file_information(os_file_handle handle, __wasi_filestat_t *buf) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + + DWORD windows_filetype = GetFileType(handle->raw.handle); + error = + convert_windows_filetype(handle, windows_filetype, &buf->st_filetype); + + if (error != __WASI_ESUCCESS) + return error; + + buf->st_dev = 0; + + if (windows_filetype != FILE_TYPE_DISK) { + buf->st_atim = 0; + buf->st_ctim = 0; + buf->st_mtim = 0; + buf->st_nlink = 0; + buf->st_size = 0; + buf->st_ino = 0; + + return error; + } + + return get_disk_file_information(handle->raw.handle, buf); +} __wasi_errno_t os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + return get_file_information(handle, buf); } __wasi_errno_t os_fstatat(os_file_handle handle, const char *path, struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) { + CHECK_VALID_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags) { + CHECK_VALID_HANDLE(handle); + return __WASI_ENOSYS; } @@ -35,52 +591,117 @@ __wasi_errno_t os_file_get_access_mode(os_file_handle handle, wasi_libc_file_access_mode *access_mode) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + if ((handle->access_mode & windows_access_mode_read) != 0 + && (handle->access_mode & windows_access_mode_write) != 0) + *access_mode = WASI_LIBC_ACCESS_MODE_READ_WRITE; + else if ((handle->access_mode & windows_access_mode_write) != 0) + *access_mode = WASI_LIBC_ACCESS_MODE_WRITE_ONLY; + else + *access_mode = WASI_LIBC_ACCESS_MODE_READ_ONLY; + + return __WASI_ESUCCESS; } __wasi_errno_t os_fdatasync(os_file_handle handle) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_fsync(os_file_handle handle) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_open_preopendir(const char *path, os_file_handle *out) { - return __WASI_ENOSYS; + *out = NULL; + + wchar_t wpath[PATH_MAX]; + __wasi_errno_t error = convert_to_wchar(path, wpath, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + HANDLE dir_handle = create_handle(wpath, true, true, true); + + if (dir_handle == INVALID_HANDLE_VALUE) + return convert_windows_error_code(GetLastError()); + + *out = BH_MALLOC(sizeof(windows_handle)); + + if (*out == NULL) { + CloseHandle(dir_handle); + return __WASI_ENOMEM; + } + + (*out)->type = windows_handle_type_file; + (*out)->raw.handle = dir_handle; + (*out)->access_mode = windows_access_mode_read; + + return error; } __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) + wasi_libc_file_access_mode access_mode, os_file_handle *out) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_close(os_file_handle handle, bool is_stdio) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + // We don't own the underlying raw handle so just free the handle and return + // success. + if (is_stdio) { + BH_FREE(handle); + return __WASI_ESUCCESS; + } + + switch (handle->type) { + case windows_handle_type_file: + bool success = CloseHandle(handle->raw.handle); + + if (!success) + return convert_windows_error_code(GetLastError()); + + break; + case windows_handle_type_socket: + int ret = closesocket(handle->raw.socket); + + if (ret != 0) + return convert_winsock_error_code(WSAGetLastError()); + + break; + default: + assert(false && "unreachable"); + } + + BH_FREE(handle); + + 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) { - return __WASI_ENOSYS; -} + CHECK_VALID_FILE_HANDLE(handle); -__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; } @@ -88,6 +709,17 @@ __wasi_errno_t os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, size_t *nread) { + CHECK_VALID_HANDLE(handle); + + 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) +{ + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -95,6 +727,8 @@ __wasi_errno_t os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, size_t *nwritten) { + CHECK_VALID_HANDLE(handle); + return __WASI_ENOSYS; } @@ -102,12 +736,16 @@ __wasi_errno_t os_fallocate(os_file_handle handle, __wasi_filesize_t offset, __wasi_filesize_t length) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_ftruncate(os_file_handle handle, __wasi_filesize_t size) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -115,6 +753,8 @@ __wasi_errno_t os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -124,6 +764,8 @@ os_utimensat(os_file_handle handle, const char *path, __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, __wasi_lookupflags_t lookup_flags) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -131,6 +773,8 @@ __wasi_errno_t os_readlinkat(os_file_handle handle, const char *path, char *buf, size_t bufsize, size_t *nread) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -139,18 +783,25 @@ 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) { + CHECK_VALID_FILE_HANDLE(from_handle); + CHECK_VALID_FILE_HANDLE(to_handle); + return __WASI_ENOSYS; } __wasi_errno_t os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_mkdirat(os_file_handle handle, const char *path) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -158,12 +809,17 @@ __wasi_errno_t os_renameat(os_file_handle old_handle, const char *old_path, os_file_handle new_handle, const char *new_path) { + CHECK_VALID_FILE_HANDLE(old_handle); + CHECK_VALID_FILE_HANDLE(new_handle); + return __WASI_ENOSYS; } __wasi_errno_t os_unlinkat(os_file_handle handle, const char *path, bool is_dir) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -171,6 +827,8 @@ __wasi_errno_t os_lseek(os_file_handle handle, __wasi_filedelta_t offset, __wasi_whence_t whence, __wasi_filesize_t *new_offset) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -178,31 +836,57 @@ __wasi_errno_t os_fadvise(os_file_handle handle, __wasi_filesize_t offset, __wasi_filesize_t length, __wasi_advice_t advice) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_isatty(os_file_handle handle) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + DWORD console_mode; + return GetConsoleMode(handle->raw.handle, &console_mode) ? __WASI_ESUCCESS + : __WASI_ENOTTY; +} + +static os_file_handle +create_stdio_handle(HANDLE raw_stdio_handle, DWORD stdio) +{ + os_file_handle stdio_handle = BH_MALLOC(sizeof(windows_handle)); + + if (stdio_handle == NULL) + return NULL; + + stdio_handle->type = windows_handle_type_file; + stdio_handle->access_mode = + windows_access_mode_read | windows_access_mode_write; + + if (raw_stdio_handle == INVALID_HANDLE_VALUE) + raw_stdio_handle = GetStdHandle(stdio); + + stdio_handle->raw.handle = raw_stdio_handle; + + return stdio_handle; } os_file_handle os_convert_stdin_handle(os_raw_file_handle raw_stdin) { - return INVALID_HANDLE_VALUE; + return create_stdio_handle(raw_stdin, STD_INPUT_HANDLE); } os_file_handle os_convert_stdout_handle(os_raw_file_handle raw_stdout) { - return INVALID_HANDLE_VALUE; + return create_stdio_handle(raw_stdout, STD_OUTPUT_HANDLE); } os_file_handle os_convert_stderr_handle(os_raw_file_handle raw_stderr) { - return INVALID_HANDLE_VALUE; + return create_stdio_handle(raw_stderr, STD_ERROR_HANDLE); } __wasi_errno_t @@ -214,12 +898,16 @@ os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream) __wasi_errno_t os_rewinddir(os_dir_stream dir_stream) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } __wasi_errno_t os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } @@ -227,12 +915,16 @@ __wasi_errno_t os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, const char **d_name) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } __wasi_errno_t os_closedir(os_dir_stream dir_stream) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } @@ -245,23 +937,42 @@ os_get_invalid_dir_stream() bool os_is_dir_stream_valid(os_dir_stream *dir_stream) { - return false; + assert(dir_stream != NULL); + + if (((*dir_stream) == NULL) || ((*dir_stream)->handle == NULL) + || ((*dir_stream)->handle->type != windows_handle_type_file) + || ((*dir_stream)->handle->raw.handle == INVALID_HANDLE_VALUE)) + return false; + + return true; } os_file_handle os_get_invalid_handle() { - return INVALID_HANDLE_VALUE; + return NULL; } bool os_is_handle_valid(os_file_handle *handle) { - return false; + assert(handle != NULL); + + CHECK_VALID_HANDLE_WITH_RETURN_VALUE(*handle, false); + + return true; } char * os_realpath(const char *path, char *resolved_path) { - return NULL; + resolved_path = _fullpath(resolved_path, path, PATH_MAX); + + // Check the file/directory actually exists + DWORD attributes = GetFileAttributesA(resolved_path); + + if (attributes == INVALID_FILE_ATTRIBUTES) + return NULL; + + return resolved_path; } \ No newline at end of file diff --git a/core/shared/platform/windows/win_socket.c b/core/shared/platform/windows/win_socket.c index f0428269..d82cd724 100644 --- a/core/shared/platform/windows/win_socket.c +++ b/core/shared/platform/windows/win_socket.c @@ -11,6 +11,22 @@ static bool is_winsock_inited = false; +#define CHECK_VALID_SOCKET_HANDLE(win_handle) \ + do { \ + if ((win_handle) == NULL) { \ + errno = EBADF; \ + return BHT_ERROR; \ + } \ + if ((win_handle)->type != windows_handle_type_socket) { \ + errno = ENOTSOCK; \ + return BHT_ERROR; \ + } \ + if ((win_handle)->raw.socket == INVALID_SOCKET) { \ + errno = EBADF; \ + return BHT_ERROR; \ + } \ + } while (0) + int init_winsock() { @@ -45,6 +61,16 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) return BHT_ERROR; } + *(sock) = BH_MALLOC(sizeof(windows_handle)); + + if ((*sock) == NULL) { + errno = ENOMEM; + return BHT_ERROR; + } + + (*sock)->type = windows_handle_type_socket; + (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write; + if (is_ipv4) { af = AF_INET; } @@ -54,18 +80,24 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) } if (is_tcp) { - *sock = socket(af, SOCK_STREAM, IPPROTO_TCP); + (*sock)->raw.socket = socket(af, SOCK_STREAM, IPPROTO_TCP); } else { - *sock = socket(af, SOCK_DGRAM, 0); + (*sock)->raw.socket = socket(af, SOCK_DGRAM, 0); } - return (*sock == -1) ? BHT_ERROR : BHT_OK; + if ((*sock)->raw.socket == INVALID_SOCKET) { + BH_FREE(*sock); + return BHT_ERROR; + } + + return BHT_OK; } int os_socket_bind(bh_socket_t socket, const char *host, int *port) { + CHECK_VALID_SOCKET_HANDLE(socket); struct sockaddr_in addr; int socklen, ret; @@ -76,13 +108,13 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port) addr.sin_port = htons(*port); addr.sin_family = AF_INET; - ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr)); + ret = bind(socket->raw.socket, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { goto fail; } socklen = sizeof(addr); - if (getsockname(socket, (void *)&addr, &socklen) == -1) { + if (getsockname(socket->raw.socket, (void *)&addr, &socklen) == -1) { os_printf("getsockname failed with error %d\n", WSAGetLastError()); goto fail; } @@ -98,10 +130,12 @@ fail: int os_socket_settimeout(bh_socket_t socket, uint64 timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + DWORD tv = (DWORD)(timeout_us / 1000UL); - if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, - sizeof(tv)) + if (setsockopt(socket->raw.socket, SOL_SOCKET, SO_RCVTIMEO, + (const char *)&tv, sizeof(tv)) != 0) { return BHT_ERROR; } @@ -112,7 +146,9 @@ os_socket_settimeout(bh_socket_t socket, uint64 timeout_us) int os_socket_listen(bh_socket_t socket, int max_client) { - if (listen(socket, max_client) != 0) { + CHECK_VALID_SOCKET_HANDLE(socket); + + if (listen(socket->raw.socket, max_client) != 0) { os_printf("socket listen failed with error %d\n", WSAGetLastError()); return BHT_ERROR; } @@ -124,12 +160,25 @@ int os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, unsigned int *addrlen) { + CHECK_VALID_SOCKET_HANDLE(server_sock); + struct sockaddr addr_tmp; unsigned int len = sizeof(struct sockaddr); - *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len); + *sock = BH_MALLOC(sizeof(windows_handle)); - if (*sock < 0) { + if (*sock == NULL) { + errno = ENOMEM; + return BHT_ERROR; + } + + (*sock)->type = windows_handle_type_socket; + (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write; + (*sock)->raw.socket = + accept(server_sock->raw.socket, (struct sockaddr *)&addr_tmp, &len); + + if ((*sock)->raw.socket == INVALID_SOCKET) { + BH_FREE(*sock); os_printf("socket accept failed with error %d\n", WSAGetLastError()); return BHT_ERROR; } @@ -140,13 +189,17 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, int os_socket_recv(bh_socket_t socket, void *buf, unsigned int len) { - return recv(socket, buf, len, 0); + CHECK_VALID_SOCKET_HANDLE(socket); + + return recv(socket->raw.socket, buf, len, 0); } int os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, bh_sockaddr_t *src_addr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -155,13 +208,17 @@ os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, int os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) { - return send(socket, buf, len, 0); + CHECK_VALID_SOCKET_HANDLE(socket); + + return send(socket->raw.socket, buf, len, 0); } int os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, int flags, const bh_sockaddr_t *dest_addr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -170,14 +227,21 @@ os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, int os_socket_close(bh_socket_t socket) { - closesocket(socket); + CHECK_VALID_SOCKET_HANDLE(socket); + + closesocket(socket->raw.socket); + + BH_FREE(socket); + return BHT_OK; } int os_socket_shutdown(bh_socket_t socket) { - shutdown(socket, SD_BOTH); + CHECK_VALID_SOCKET_HANDLE(socket); + + shutdown(socket->raw.socket, SD_BOTH); return BHT_OK; } @@ -209,6 +273,8 @@ os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out) int os_socket_connect(bh_socket_t socket, const char *addr, int port) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -228,6 +294,8 @@ os_socket_addr_resolve(const char *host, const char *service, int os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -236,6 +304,8 @@ os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) int os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -244,6 +314,8 @@ os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) int os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -252,6 +324,8 @@ os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) int os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -260,6 +334,8 @@ os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) int os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -268,6 +344,8 @@ os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) int os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -276,6 +354,8 @@ os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) int os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -284,6 +364,8 @@ os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) int os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -292,6 +374,8 @@ os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) int os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -300,6 +384,8 @@ os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) int os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -308,6 +394,8 @@ os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) int os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -316,6 +404,8 @@ os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) int os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -324,6 +414,8 @@ os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) int os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -332,6 +424,8 @@ os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) int os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -340,6 +434,8 @@ os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) int os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -348,6 +444,8 @@ os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) int os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -356,6 +454,8 @@ os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) int os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -364,6 +464,8 @@ os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) int os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -372,6 +474,8 @@ os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) int os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -380,6 +484,8 @@ os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) int os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -388,6 +494,8 @@ os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) int os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -396,6 +504,8 @@ os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) int os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -404,6 +514,8 @@ os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) int os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -412,6 +524,8 @@ os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) int os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -420,6 +534,8 @@ os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) int os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -428,6 +544,8 @@ os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) int os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -436,6 +554,8 @@ os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) int os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -444,6 +564,8 @@ os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) int os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -452,6 +574,8 @@ os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) int os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -460,6 +584,8 @@ os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) int os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -470,6 +596,8 @@ os_socket_set_ip_add_membership(bh_socket_t socket, bh_ip_addr_buffer_t *imr_multiaddr, uint32_t imr_interface, bool is_ipv6) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -480,6 +608,8 @@ os_socket_set_ip_drop_membership(bh_socket_t socket, bh_ip_addr_buffer_t *imr_multiaddr, uint32_t imr_interface, bool is_ipv6) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -488,6 +618,8 @@ os_socket_set_ip_drop_membership(bh_socket_t socket, int os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -496,6 +628,8 @@ os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -504,6 +638,8 @@ os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) int os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -512,6 +648,8 @@ os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -520,6 +658,8 @@ os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) int os_socket_set_ipv6_only(bh_socket_t socket, bool option) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -528,6 +668,8 @@ os_socket_set_ipv6_only(bh_socket_t socket, bool option) int os_socket_get_ipv6_only(bh_socket_t socket, bool *option) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -536,6 +678,8 @@ os_socket_get_ipv6_only(bh_socket_t socket, bool *option) int os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -544,6 +688,8 @@ os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) int os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; } diff --git a/core/shared/platform/windows/win_util.c b/core/shared/platform/windows/win_util.c new file mode 100644 index 00000000..fc01706e --- /dev/null +++ b/core/shared/platform/windows/win_util.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "win_util.h" + +__wasi_timestamp_t +convert_filetime_to_wasi_timestamp(LPFILETIME filetime) +{ + // From 1601-01-01 to 1970-01-01 there are 134774 days. + static const uint64_t NT_to_UNIX_epoch = + 134774ull * 86400ull * 1000ull * 1000ull * 1000ull; + + ULARGE_INTEGER temp = { .HighPart = filetime->dwHighDateTime, + .LowPart = filetime->dwLowDateTime }; + + // WASI timestamps are measured in nanoseconds whereas FILETIME structs are + // represented in terms 100-nanosecond intervals. + return (temp.QuadPart * 100ull) - NT_to_UNIX_epoch; +} \ No newline at end of file diff --git a/core/shared/platform/windows/win_util.h b/core/shared/platform/windows/win_util.h new file mode 100644 index 00000000..10b199f1 --- /dev/null +++ b/core/shared/platform/windows/win_util.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WIN_UTIL_H +#define _WIN_UTIL_H + +#include "platform_wasi.h" +#include "windows.h" + +__wasi_timestamp_t +convert_filetime_to_wasi_timestamp(LPFILETIME filetime); + +#endif /* end of _WIN_UTIL_H */ \ No newline at end of file From e7a62d209996cf27ff9edbebac5df0a4dcfd5c8f Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:06:04 +0100 Subject: [PATCH 13/18] Refactor clock functions to use WASI types (#2666) Refactoring the clock functions to use WASI types so we can simplify the code and remove some unnecessary boilerplate. See https://github.com/bytecodealliance/wasm-micro-runtime/pull/2637#discussion_r1362202879 for details. --- .../libraries/libc-wasi/libc_wasi_wrapper.c | 4 +- .../include/wasmtime_ssp.h | 11 -- .../sandboxed-system-primitives/src/posix.c | 48 +------ .../common/posix/platform_api_posix.cmake | 5 +- .../platform/common/posix/posix_clock.c | 76 ++++++----- .../platform/include/platform_api_extension.h | 20 --- .../shared/platform/include/platform_common.h | 7 - core/shared/platform/include/platform_wasi.h | 27 ++++ .../platform/linux-sgx/shared_platform.cmake | 7 +- core/shared/platform/windows/win_clock.c | 126 +++++++++--------- core/shared/platform/windows/win_file.c | 40 ------ core/shared/platform/windows/win_util.c | 39 ++++++ core/shared/platform/windows/win_util.h | 4 + product-mini/platforms/nuttx/wamr.mk | 2 +- 14 files changed, 188 insertions(+), 228 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index b0666445..9f35b81a 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -193,7 +193,7 @@ wasi_clock_res_get(wasm_exec_env_t exec_env, if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_clock_res_get(clock_id, resolution); + return os_clock_res_get(clock_id, resolution); } static wasi_errno_t @@ -207,7 +207,7 @@ wasi_clock_time_get(wasm_exec_env_t exec_env, if (!validate_native_addr(time, sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_clock_time_get(clock_id, precision, time); + return os_clock_time_get(clock_id, precision, time); } static wasi_errno_t 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 af1d68e9..ed846386 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 @@ -41,17 +41,6 @@ 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 **environs, char *environ_buf) 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 f6479a20..8d9ac11e 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 @@ -94,7 +94,7 @@ ns_lookup_list_search(char **list, const char *host) return false; } -#ifndef BH_PLATFORM_WINDOWS +#if !defined(BH_PLATFORM_WINDOWS) && CONFIG_HAS_CLOCK_NANOSLEEP static bool wasi_clockid_to_clockid(__wasi_clockid_t in, clockid_t *out) { @@ -197,52 +197,6 @@ wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr, } } -static bool -wasi_clockid_to_bh_clockid(__wasi_clockid_t in, bh_clock_id_t *out) -{ - switch (in) { - case __WASI_CLOCK_MONOTONIC: - *out = BH_CLOCK_ID_MONOTONIC; - return true; - case __WASI_CLOCK_PROCESS_CPUTIME_ID: - *out = BH_CLOCK_ID_PROCESS_CPUTIME_ID; - return true; - case __WASI_CLOCK_REALTIME: - *out = BH_CLOCK_ID_REALTIME; - return true; - case __WASI_CLOCK_THREAD_CPUTIME_ID: - *out = BH_CLOCK_ID_THREAD_CPUTIME_ID; - return true; - default: - return false; - } -} - -__wasi_errno_t -wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, - __wasi_timestamp_t *resolution) -{ - bh_clock_id_t bh_clockid; - if (!wasi_clockid_to_bh_clockid(clock_id, &bh_clockid)) - return __WASI_EINVAL; - if (os_clock_res_get(clock_id, resolution) != BHT_OK) - return convert_errno(errno); - return __WASI_ESUCCESS; -} - -__wasi_errno_t -wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, - __wasi_timestamp_t precision, - __wasi_timestamp_t *time) -{ - bh_clock_id_t bh_clockid; - if (!wasi_clockid_to_bh_clockid(clock_id, &bh_clockid)) - return __WASI_EINVAL; - if (os_clock_time_get(clock_id, precision, time) != BHT_OK) - return convert_errno(errno); - return __WASI_ESUCCESS; -} - struct fd_prestat { const char *dir; }; diff --git a/core/shared/platform/common/posix/platform_api_posix.cmake b/core/shared/platform/common/posix/platform_api_posix.cmake index 3de3e189..258be463 100644 --- a/core/shared/platform/common/posix/platform_api_posix.cmake +++ b/core/shared/platform/common/posix/platform_api_posix.cmake @@ -6,7 +6,10 @@ 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) + list(REMOVE_ITEM source_all + ${PLATFORM_COMMON_POSIX_DIR}/posix_file.c + ${PLATFORM_COMMON_POSIX_DIR}/posix_clock.c + ) else() include (${CMAKE_CURRENT_LIST_DIR}/../libc-util/platform_common_libc_util.cmake) set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) diff --git a/core/shared/platform/common/posix/posix_clock.c b/core/shared/platform/common/posix/posix_clock.c index 3c9f9d56..280306c4 100644 --- a/core/shared/platform/common/posix/posix_clock.c +++ b/core/shared/platform/common/posix/posix_clock.c @@ -3,70 +3,84 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "platform_api_vmcore.h" +#include "libc_errno.h" +#include "platform_api_extension.h" #define NANOSECONDS_PER_SECOND 1000000000ULL -static bool -bh_clockid_to_clockid(bh_clock_id_t in, clockid_t *out) +static __wasi_errno_t +wasi_clockid_to_clockid(__wasi_clockid_t in, clockid_t *out) { switch (in) { - case BH_CLOCK_ID_MONOTONIC: + case __WASI_CLOCK_MONOTONIC: *out = CLOCK_MONOTONIC; - return true; -#if defined(CLOCK_PROCESS_CPUTIME_ID) - case BH_CLOCK_ID_PROCESS_CPUTIME_ID: - *out = CLOCK_PROCESS_CPUTIME_ID; - return true; -#endif - case BH_CLOCK_ID_REALTIME: + return __WASI_ESUCCESS; + case __WASI_CLOCK_REALTIME: *out = CLOCK_REALTIME; - return true; + return __WASI_ESUCCESS; + case __WASI_CLOCK_PROCESS_CPUTIME_ID: +#if defined(CLOCK_PROCESS_CPUTIME_ID) + *out = CLOCK_PROCESS_CPUTIME_ID; + return __WASI_ESUCCESS; +#else + return __WASI_ENOTSUP; +#endif + case __WASI_CLOCK_THREAD_CPUTIME_ID: #if defined(CLOCK_THREAD_CPUTIME_ID) - case BH_CLOCK_ID_THREAD_CPUTIME_ID: *out = CLOCK_THREAD_CPUTIME_ID; - return true; + return __WASI_ESUCCESS; +#else + return __WASI_ENOTSUP; #endif default: - errno = EINVAL; - return false; + return __WASI_EINVAL; } } -static uint64 +static __wasi_timestamp_t timespec_to_nanoseconds(const struct timespec *ts) { if (ts->tv_sec < 0) return 0; - if ((uint64)ts->tv_sec >= UINT64_MAX / NANOSECONDS_PER_SECOND) + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / NANOSECONDS_PER_SECOND) return UINT64_MAX; - return (uint64)ts->tv_sec * NANOSECONDS_PER_SECOND + (uint64)ts->tv_nsec; + return (__wasi_timestamp_t)ts->tv_sec * NANOSECONDS_PER_SECOND + + (__wasi_timestamp_t)ts->tv_nsec; } -int -os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution) +__wasi_errno_t +os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) { clockid_t nclock_id; - if (!bh_clockid_to_clockid(clock_id, &nclock_id)) - return BHT_ERROR; + __wasi_errno_t error = wasi_clockid_to_clockid(clock_id, &nclock_id); + + if (error != __WASI_ESUCCESS) + return error; + struct timespec ts; if (clock_getres(nclock_id, &ts) < 0) - return BHT_ERROR; + return convert_errno(errno); + *resolution = timespec_to_nanoseconds(&ts); - return BHT_OK; + return error; } -int -os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) +__wasi_errno_t +os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, + __wasi_timestamp_t *time) { clockid_t nclock_id; - if (!bh_clockid_to_clockid(clock_id, &nclock_id)) - return BHT_ERROR; + __wasi_errno_t error = wasi_clockid_to_clockid(clock_id, &nclock_id); + + if (error != __WASI_ESUCCESS) + return error; + struct timespec ts; if (clock_gettime(nclock_id, &ts) < 0) - return BHT_ERROR; + return convert_errno(errno); + *time = timespec_to_nanoseconds(&ts); - return 0; + return error; } diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 381d66fd..e40ddfd0 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -36,26 +36,6 @@ extern "C" { * 2. To build the app-mgr and app-framework, you must implement it */ -/** - * Get a resolution of the clock - * - * @param clock_id clock identifier - * @param resolution output variable to store the clock resolution - * @return BHT_OK if success; otherwise, BHT_ERROR - */ -int -os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution); - -/** - * Get a current time of the clock - * - * @param clock_id clock identifier - * @param time output variable to store the clock time - * @return BHT_OK if success; otherwise, BHT_ERROR - */ -int -os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time); - /** * Creates a thread * diff --git a/core/shared/platform/include/platform_common.h b/core/shared/platform/include/platform_common.h index 62d3e83e..28001af7 100644 --- a/core/shared/platform/include/platform_common.h +++ b/core/shared/platform/include/platform_common.h @@ -37,13 +37,6 @@ extern "C" { #define BH_TIME_T_MAX LONG_MAX #endif -typedef enum { - BH_CLOCK_ID_REALTIME, - BH_CLOCK_ID_MONOTONIC, - BH_CLOCK_ID_PROCESS_CPUTIME_ID, - BH_CLOCK_ID_THREAD_CPUTIME_ID -} bh_clock_id_t; - #if defined(_MSC_BUILD) #if defined(COMPILING_WASM_RUNTIME_API) __declspec(dllexport) void *BH_MALLOC(unsigned int size); diff --git a/core/shared/platform/include/platform_wasi.h b/core/shared/platform/include/platform_wasi.h index 3798a9e7..23ea0c45 100644 --- a/core/shared/platform/include/platform_wasi.h +++ b/core/shared/platform/include/platform_wasi.h @@ -1093,6 +1093,33 @@ os_is_handle_valid(os_file_handle *handle); char * os_realpath(const char *path, char *resolved_path); +/**************************************************** + * * + * Clock functions * + * * + ****************************************************/ + +/** + * Get the resolution of the specified clock. + * + * @param clock_id clock identifier + * @param resolution output variable to store the clock resolution + */ +__wasi_errno_t +os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution); + +/** + * Get the current time of the specified clock. + * + * @param clock_id clock identifier + * @param precision the maximum lag that the returned time value may have, + * compared to its actual value. + * @param time output variable to store the clock time + */ +__wasi_errno_t +os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, + __wasi_timestamp_t *time); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/linux-sgx/shared_platform.cmake b/core/shared/platform/linux-sgx/shared_platform.cmake index 4fe5d902..e8e16700 100644 --- a/core/shared/platform/linux-sgx/shared_platform.cmake +++ b/core/shared/platform/linux-sgx/shared_platform.cmake @@ -29,15 +29,16 @@ 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) + list(APPEND source_all + ${PLATFORM_SHARED_DIR}/../common/posix/posix_file.c + ${PLATFORM_SHARED_DIR}/../common/posix/posix_clock.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) -list(APPEND source_all ${PLATFORM_SHARED_DIR}/../common/posix/posix_clock.c) - set (PLATFORM_SHARED_SOURCE ${source_all}) set (PLATFORM_SHARED_SOURCE_UNTRUSTED ${source_all_untrusted}) diff --git a/core/shared/platform/windows/win_clock.c b/core/shared/platform/windows/win_clock.c index 919debcd..c96bdfb3 100644 --- a/core/shared/platform/windows/win_clock.c +++ b/core/shared/platform/windows/win_clock.c @@ -3,79 +3,84 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "platform_api_vmcore.h" +#include "platform_api_extension.h" #include #include "win_util.h" #define NANOSECONDS_PER_SECOND 1000000000ULL #define NANOSECONDS_PER_TICK 100 -static int +static __wasi_errno_t calculate_monotonic_clock_frequency(uint64 *out_frequency) { LARGE_INTEGER frequency; - if (!QueryPerformanceFrequency(&frequency)) { - return BHT_ERROR; - } - else { - *out_frequency = (uint64)frequency.QuadPart; - return BHT_OK; - } + if (!QueryPerformanceFrequency(&frequency)) + return convert_windows_error_code(GetLastError()); + + *out_frequency = (uint64)frequency.QuadPart; + return __WASI_ESUCCESS; } -static int +static __wasi_errno_t get_performance_counter_value(uint64 *out_counter) { LARGE_INTEGER counter; - if (!QueryPerformanceCounter(&counter)) { - return BHT_ERROR; - } - else { - *out_counter = counter.QuadPart; - return BHT_OK; - } + if (!QueryPerformanceCounter(&counter)) + return convert_windows_error_code(GetLastError()); + + *out_counter = counter.QuadPart; + return __WASI_ESUCCESS; } -int -os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution) +__wasi_errno_t +os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) { + __wasi_errno_t error = __WASI_ESUCCESS; + switch (clock_id) { - case BH_CLOCK_ID_MONOTONIC: + case __WASI_CLOCK_MONOTONIC: { uint64 frequency; - if (calculate_monotonic_clock_frequency(&frequency) == BHT_ERROR) { - return BHT_ERROR; - } + error = calculate_monotonic_clock_frequency(&frequency); + + if (error != __WASI_ESUCCESS) + return error; + const uint64 result = (uint64)NANOSECONDS_PER_SECOND / frequency; *resolution = result; - return BHT_OK; + return error; } - case BH_CLOCK_ID_REALTIME: - case BH_CLOCK_ID_PROCESS_CPUTIME_ID: - case BH_CLOCK_ID_THREAD_CPUTIME_ID: + case __WASI_CLOCK_REALTIME: + case __WASI_CLOCK_PROCESS_CPUTIME_ID: + case __WASI_CLOCK_THREAD_CPUTIME_ID: { +#if WINAPI_PARTITION_DESKTOP ULONG maximum_time; ULONG minimum_time; ULONG current_time; NTSTATUS status = NtQueryTimerResolution(&maximum_time, &minimum_time, ¤t_time); - uint64 result = (uint64)current_time * NANOSECONDS_PER_TICK; *resolution = result / (uint64)NANOSECONDS_PER_SECOND; - return BHT_OK; + return error; +#else + return __WASI_ENOTSUP; +#endif } default: - errno = EINVAL; - return BHT_ERROR; + return __WASI_EINVAL; } } -int -os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) +__wasi_errno_t +os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, + __wasi_timestamp_t *time) { + __wasi_errno_t error = __WASI_ESUCCESS; + switch (clock_id) { - case BH_CLOCK_ID_REALTIME: + case __WASI_CLOCK_REALTIME: { FILETIME sys_now; #if NTDDI_VERSION >= NTDDI_WIN8 @@ -86,16 +91,20 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) *time = convert_filetime_to_wasi_timestamp(&sys_now); return BHT_OK; } - case BH_CLOCK_ID_MONOTONIC: + case __WASI_CLOCK_MONOTONIC: { uint64 frequency; - if (calculate_monotonic_clock_frequency(&frequency) == BHT_ERROR) { - return BHT_ERROR; - } + error = calculate_monotonic_clock_frequency(&frequency); + + if (error != __WASI_ESUCCESS) + return error; + uint64 counter; - if (get_performance_counter_value(&counter) == BHT_ERROR) { - return BHT_ERROR; - } + error = get_performance_counter_value(&counter); + + if (error != __WASI_ESUCCESS) + return error; + if (NANOSECONDS_PER_SECOND % frequency == 0) { *time = counter * NANOSECONDS_PER_SECOND / frequency; } @@ -105,43 +114,30 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) *time = seconds * NANOSECONDS_PER_SECOND + (fractions * NANOSECONDS_PER_SECOND) / frequency; } - return BHT_OK; + return error; } - case BH_CLOCK_ID_PROCESS_CPUTIME_ID: + case __WASI_CLOCK_PROCESS_CPUTIME_ID: + case __WASI_CLOCK_THREAD_CPUTIME_ID: { FILETIME creation_time; FILETIME exit_time; FILETIME kernel_time; FILETIME user_time; - if (!GetProcessTimes(GetCurrentProcess(), &creation_time, - &exit_time, &kernel_time, &user_time)) { - return BHT_ERROR; - } - *time = convert_filetime_to_wasi_timestamp(&kernel_time) - + convert_filetime_to_wasi_timestamp(&user_time); + HANDLE handle = (clock_id == __WASI_CLOCK_PROCESS_CPUTIME_ID) + ? GetCurrentProcess() + : GetCurrentThread(); - return BHT_OK; - } - case BH_CLOCK_ID_THREAD_CPUTIME_ID: - { - FILETIME creation_time; - FILETIME exit_time; - FILETIME kernel_time; - FILETIME user_time; - - if (!GetProcessTimes(GetCurrentThread(), &creation_time, &exit_time, - &kernel_time, &user_time)) { - return BHT_ERROR; - } + if (!GetProcessTimes(handle, &creation_time, &exit_time, + &kernel_time, &user_time)) + return convert_windows_error_code(GetLastError()); *time = convert_filetime_to_wasi_timestamp(&kernel_time) + convert_filetime_to_wasi_timestamp(&user_time); - return BHT_OK; + return error; } default: - errno = EINVAL; - return BHT_ERROR; + return __WASI_EINVAL; } } \ No newline at end of file diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 5120e9a8..92003fc8 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -86,46 +86,6 @@ convert_winsock_error_code(int error_code) } } -// Convert a Windows error code to a WASI error code -static __wasi_errno_t -convert_windows_error_code(DWORD windows_error_code) -{ - switch (windows_error_code) { - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_HANDLE: - case ERROR_NEGATIVE_SEEK: - return __WASI_EINVAL; - case ERROR_SHARING_VIOLATION: - case ERROR_PIPE_BUSY: - return __WASI_EBUSY; - case ERROR_ACCESS_DENIED: - return __WASI_EACCES; - case ERROR_ALREADY_EXISTS: - case ERROR_FILE_EXISTS: - return __WASI_EEXIST; - case ERROR_NO_MORE_FILES: - case ERROR_FILE_NOT_FOUND: - case ERROR_INVALID_NAME: - return __WASI_ENOENT; - case ERROR_PRIVILEGE_NOT_HELD: - return __WASI_EPERM; - case ERROR_NOT_ENOUGH_MEMORY: - return __WASI_ENOMEM; - case ERROR_NOACCESS: - return __WASI_EFAULT; - case ERROR_DIR_NOT_EMPTY: - return __WASI_ENOTEMPTY; - case ERROR_DIRECTORY: - return __WASI_ENOTDIR; - case ERROR_IO_PENDING: - case ERROR_INSUFFICIENT_BUFFER: - case ERROR_INVALID_FLAGS: - case ERROR_NO_UNICODE_TRANSLATION: - default: - return __WASI_ENOSYS; - } -} - static __wasi_filetype_t get_disk_filetype(DWORD attribute) { diff --git a/core/shared/platform/windows/win_util.c b/core/shared/platform/windows/win_util.c index fc01706e..d24685c9 100644 --- a/core/shared/platform/windows/win_util.c +++ b/core/shared/platform/windows/win_util.c @@ -18,4 +18,43 @@ convert_filetime_to_wasi_timestamp(LPFILETIME filetime) // WASI timestamps are measured in nanoseconds whereas FILETIME structs are // represented in terms 100-nanosecond intervals. return (temp.QuadPart * 100ull) - NT_to_UNIX_epoch; +} + +__wasi_errno_t +convert_windows_error_code(DWORD windows_error_code) +{ + switch (windows_error_code) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_HANDLE: + case ERROR_NEGATIVE_SEEK: + return __WASI_EINVAL; + case ERROR_SHARING_VIOLATION: + case ERROR_PIPE_BUSY: + return __WASI_EBUSY; + case ERROR_ACCESS_DENIED: + return __WASI_EACCES; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + return __WASI_EEXIST; + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_INVALID_NAME: + return __WASI_ENOENT; + case ERROR_PRIVILEGE_NOT_HELD: + return __WASI_EPERM; + case ERROR_NOT_ENOUGH_MEMORY: + return __WASI_ENOMEM; + case ERROR_NOACCESS: + return __WASI_EFAULT; + case ERROR_DIR_NOT_EMPTY: + return __WASI_ENOTEMPTY; + case ERROR_DIRECTORY: + return __WASI_ENOTDIR; + case ERROR_IO_PENDING: + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_INVALID_FLAGS: + case ERROR_NO_UNICODE_TRANSLATION: + default: + return __WASI_EINVAL; + } } \ No newline at end of file diff --git a/core/shared/platform/windows/win_util.h b/core/shared/platform/windows/win_util.h index 10b199f1..197dfce1 100644 --- a/core/shared/platform/windows/win_util.h +++ b/core/shared/platform/windows/win_util.h @@ -12,4 +12,8 @@ __wasi_timestamp_t convert_filetime_to_wasi_timestamp(LPFILETIME filetime); +// Convert a Windows error code to a WASI error code +__wasi_errno_t +convert_windows_error_code(DWORD windows_error_code); + #endif /* end of _WIN_UTIL_H */ \ No newline at end of file diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index ec7508e9..ef90f14d 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -250,6 +250,7 @@ CFLAGS += -I${SHARED_ROOT}/platform/common/libc-util CSRCS += blocking_op.c CSRCS += posix_socket.c CSRCS += posix_file.c +CSRCS += posix_clock.c CSRCS += libc_errno.c CSRCS += libc_wasi_wrapper.c VPATH += $(IWASM_ROOT)/libraries/libc-wasi @@ -364,7 +365,6 @@ CSRCS += nuttx_platform.c \ posix_blocking_op.c \ posix_thread.c \ posix_time.c \ - posix_clock.c \ posix_sleep.c \ mem_alloc.c \ ems_kfc.c \ From 3624895204b6ec61425bbc72662fc90405b6113a Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:47:56 +0100 Subject: [PATCH 14/18] Fix windows compilation on C++20 (#2670) Since C++20, std::memory_order is defined as an enum class so requires explicit casting to an int when adding enum values. See https://en.cppreference.com/w/cpp/atomic/memory_order. --- core/shared/platform/windows/win_atomic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/shared/platform/windows/win_atomic.cpp b/core/shared/platform/windows/win_atomic.cpp index 80e8ef51..4e09405b 100644 --- a/core/shared/platform/windows/win_atomic.cpp +++ b/core/shared/platform/windows/win_atomic.cpp @@ -14,8 +14,8 @@ void bh_atomic_thread_fence(int mem_order) { std::memory_order order = - (std::memory_order)(std::memory_order::memory_order_relaxed + mem_order - - os_memory_order_relaxed); + (std::memory_order)((int)std::memory_order::memory_order_relaxed + + mem_order - os_memory_order_relaxed); std::atomic_thread_fence(order); } From 13875f43c6b6e8a26b73869dd71b3b55918ff9fa Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:24:06 +0000 Subject: [PATCH 15/18] Enable WASI tests on Windows CI (#2699) Most of the WASI filesystem tests require at least creating/deleting a file to test filesystem functionality so some additional filesystem APIs have been implemented on Windows so we can test what has been implemented so far. For those WASI functions which haven't been implemented, we skip the tests. These will be implemented in a future PR after which we can remove the relevant filters. Additionally, in order to run the WASI socket and thread tests, we need to install the wasi-sdk in CI and build the test source code prior to running the tests. --- .github/workflows/compilation_on_windows.yml | 24 + .../libraries/lib-socket/test/manifest.json | 3 + .../sandboxed-system-primitives/src/posix.c | 15 +- .../platform/windows/platform_internal.h | 11 + core/shared/platform/windows/win_file.c | 585 +++++++++++++++++- core/shared/platform/windows/win_socket.c | 2 + .../windows/wasi_filtered_tests.json | 51 ++ tests/wamr-test-suites/test_wamr.sh | 13 +- .../wasi-test-script/run_wasi_tests.sh | 52 +- 9 files changed, 726 insertions(+), 30 deletions(-) create mode 100644 core/iwasm/libraries/lib-socket/test/manifest.json create mode 100644 product-mini/platforms/windows/wasi_filtered_tests.json diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 3805dac3..97a4aaae 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -44,6 +44,10 @@ env: DEFAULT_TEST_OPTIONS: "-s spec -b" MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M" THREADS_TEST_OPTIONS: "-s spec -b -p" + WASI_TEST_OPTIONS: "-s wasi_certification -w" + WASI_TEST_FILTER: ${{ github.workspace }}/product-mini/platforms/windows/wasi_filtered_tests.json + # Used when building the WASI socket and thread tests + CC: ${{ github.workspace }}/wasi-sdk/bin/clang # Cancel any in-flight jobs for the same PR/branch so there's only one active # at a time @@ -100,11 +104,31 @@ jobs: $DEFAULT_TEST_OPTIONS, $MULTI_MODULES_TEST_OPTIONS, $THREADS_TEST_OPTIONS, + $WASI_TEST_OPTIONS, ] steps: - name: checkout uses: actions/checkout@v3 + - name: download and install wasi-sdk + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: | + curl "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0.m-mingw.tar.gz" -o wasi-sdk.tar.gz -L + mkdir wasi-sdk + tar -xzf wasi-sdk.tar.gz -C wasi-sdk --strip-components 1 + + - name: build socket api tests + shell: bash + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: ./build.sh + working-directory: ./core/iwasm/libraries/lib-socket/test/ + + - name: Build WASI thread tests + shell: bash + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: ./build.sh + working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/ + - name: run tests shell: bash timeout-minutes: 20 diff --git a/core/iwasm/libraries/lib-socket/test/manifest.json b/core/iwasm/libraries/lib-socket/test/manifest.json new file mode 100644 index 00000000..b0afd1d6 --- /dev/null +++ b/core/iwasm/libraries/lib-socket/test/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "WAMR lib-socket tests" +} \ 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 8d9ac11e..c43423dc 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 @@ -1288,6 +1288,11 @@ path_get(wasm_exec_env_t exec_env, struct fd_table *curfds, size_t expansions = 0; char *symlink = NULL; size_t symlink_len; +#ifdef BH_PLATFORM_WINDOWS +#define PATH_SEPARATORS "/\\" +#else +#define PATH_SEPARATORS "/" +#endif for (;;) { // Extract the next pathname component from 'paths[curpath]', null @@ -1295,9 +1300,10 @@ path_get(wasm_exec_env_t exec_env, struct fd_table *curfds, // whether the pathname component is followed by one or more // trailing slashes, as this requires it to be a directory. char *file = paths[curpath]; - char *file_end = file + strcspn(file, "/"); - paths[curpath] = file_end + strspn(file_end, "/"); - bool ends_with_slashes = *file_end == '/'; + char *file_end = file + strcspn(file, PATH_SEPARATORS); + paths[curpath] = file_end + strspn(file_end, PATH_SEPARATORS); + bool ends_with_slashes = + (*file_end != '\0' && strchr(PATH_SEPARATORS, *file_end)); *file_end = '\0'; // Test for empty pathname strings and absolute paths. @@ -2880,8 +2886,7 @@ __wasi_errno_t wasmtime_ssp_sched_yield(void) { #ifdef BH_PLATFORM_WINDOWS - if (!SwitchToThread()) - return __WASI_EAGAIN; + SwitchToThread(); #else if (sched_yield() < 0) return convert_errno(errno); diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 9d1937a4..275ea5d3 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -146,8 +146,19 @@ typedef enum windows_access_mode { windows_access_mode_write = 1 << 1 } windows_access_mode; +// These enum values are defined to be the same as the corresponding WASI +// fdflags so they can be used interchangeably. +typedef enum windows_fdflags { + windows_fdflags_append = 1 << 0, + windows_fdflags_dsync = 1 << 1, + windows_fdflags_nonblock = 1 << 2, + windows_fdflags_rsync = 1 << 3, + windows_fdflags_sync = 1 << 4 +} windows_fdflags; + typedef struct windows_handle { windows_handle_type type; + windows_fdflags fdflags; windows_access_mode access_mode; union { HANDLE handle; diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 92003fc8..333e089e 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -7,6 +7,10 @@ #include "libc_errno.h" #include "win_util.h" +#include "PathCch.h" + +#pragma comment(lib, "Pathcch.lib") + #define CHECK_VALID_HANDLE_WITH_RETURN_VALUE(win_handle, ret) \ do { \ if ((win_handle) == NULL \ @@ -188,6 +192,79 @@ get_handle_filepath(HANDLE handle, wchar_t *buf, DWORD buf_size) return __WASI_ESUCCESS; } +static __wasi_errno_t +convert_hresult_error_code(HRESULT error_code) +{ + switch (error_code) { + case E_OUTOFMEMORY: + return __WASI_ENOMEM; + case E_INVALIDARG: + default: + return __WASI_EINVAL; + } +} + +// Returns the absolute filepath from the relative path to the directory +// associated with the provided handle. +static __wasi_errno_t +get_absolute_filepath(HANDLE handle, const char *relative_path, + wchar_t *absolute_path, size_t buf_len) +{ + wchar_t handle_path[PATH_MAX]; + + __wasi_errno_t error = get_handle_filepath(handle, handle_path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + wchar_t relative_wpath[PATH_MAX]; + error = convert_to_wchar(relative_path, relative_wpath, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + HRESULT ret = + PathCchCombine(absolute_path, buf_len, handle_path, relative_wpath); + if (ret != S_OK) + error = convert_hresult_error_code(ret); + + return error; +} + +static bool +has_directory_attribute(DWORD attributes) +{ + if (attributes == INVALID_FILE_ATTRIBUTES) + return false; + + return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +static bool +is_directory(const wchar_t *path) +{ + DWORD attributes = GetFileAttributesW(path); + + return has_directory_attribute(attributes); +} + +static bool +has_symlink_attribute(DWORD attributes) +{ + if (attributes == INVALID_FILE_ATTRIBUTES) + return false; + + return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; +} + +static bool +is_symlink(const wchar_t *path) +{ + DWORD attributes = GetFileAttributesW(path); + + return has_symlink_attribute(attributes); +} + static void init_dir_stream(os_dir_stream dir_stream, os_file_handle handle) { @@ -275,17 +352,17 @@ create_handle(wchar_t *path, bool is_dir, bool follow_symlink, bool readonly) DWORD desired_access = GENERIC_READ; - if (!readonly) { + if (!readonly) desired_access |= GENERIC_WRITE; + else create_params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY; - } return CreateFile2(path, desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, OPEN_EXISTING, &create_params); } -#if WINAPI_PARTITION_DESKTOP +#if WINAPI_PARTITION_DESKTOP == 0 // Modifies the given path in place and replaces it with the filename component // (including the extension) of the path. static __wasi_errno_t @@ -387,6 +464,7 @@ get_disk_file_information(HANDLE handle, __wasi_filestat_t *buf) windows_handle dir_handle = { .access_mode = windows_access_mode_read, .raw = { .handle = raw_dir_handle }, + .fdflags = 0, .type = windows_handle_type_file }; windows_dir_stream dir_stream; init_dir_stream(&dir_stream, &dir_handle); @@ -484,7 +562,7 @@ get_disk_file_information(HANDLE handle, __wasi_filestat_t *buf) return error; } -#endif /* end of !WINAPI_PARTITION_DESKTOP */ +#endif /* end of WINAPI_PARTITION_DESKTOP == 0 */ static __wasi_errno_t get_file_information(os_file_handle handle, __wasi_filestat_t *buf) @@ -536,7 +614,8 @@ os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) { CHECK_VALID_HANDLE(handle); - return __WASI_ENOSYS; + *flags = handle->fdflags; + return __WASI_ESUCCESS; } __wasi_errno_t @@ -605,6 +684,7 @@ os_open_preopendir(const char *path, os_file_handle *out) (*out)->type = windows_handle_type_file; (*out)->raw.handle = dir_handle; + (*out)->fdflags = 0; (*out)->access_mode = windows_access_mode_read; return error; @@ -616,8 +696,135 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, wasi_libc_file_access_mode access_mode, os_file_handle *out) { CHECK_VALID_FILE_HANDLE(handle); + *out = BH_MALLOC(sizeof(windows_handle)); - return __WASI_ENOSYS; + if (*out == NULL) + return __WASI_ENOMEM; + + (*out)->type = windows_handle_type_file; + (*out)->fdflags = fs_flags; + (*out)->raw.handle = INVALID_HANDLE_VALUE; + + DWORD attributes = FILE_FLAG_BACKUP_SEMANTICS; + + if ((fs_flags & (__WASI_FDFLAG_SYNC | __WASI_FDFLAG_RSYNC)) != 0) + attributes |= (FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING); + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) + attributes |= FILE_FLAG_WRITE_THROUGH; + + if ((oflags & __WASI_O_DIRECTORY) != 0) { + attributes |= FILE_ATTRIBUTE_DIRECTORY; + oflags &= ~(__WASI_O_DIRECTORY); + } + // Use async operations on the handle if it's not a directory + else { + attributes |= FILE_FLAG_OVERLAPPED; + } + + __wasi_errno_t error = __WASI_ESUCCESS; + + DWORD access_flags = 0; + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) { + if ((attributes & (FILE_FLAG_NO_BUFFERING)) != 0) { + // FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually + // exclusive - CreateFile2 returns 87 (invalid parameter) when they + // are combined. + error = __WASI_ENOTSUP; + goto fail; + } + access_flags |= FILE_APPEND_DATA; + } + + switch (access_mode) { + case WASI_LIBC_ACCESS_MODE_READ_ONLY: + access_flags |= GENERIC_READ; + (*out)->access_mode = windows_access_mode_read; + break; + case WASI_LIBC_ACCESS_MODE_WRITE_ONLY: + access_flags |= GENERIC_WRITE; + (*out)->access_mode = windows_access_mode_write; + break; + case WASI_LIBC_ACCESS_MODE_READ_WRITE: + access_flags |= GENERIC_WRITE | GENERIC_READ; + (*out)->access_mode = + windows_access_mode_read | windows_access_mode_write; + break; + } + + DWORD creation_disposition = 0; + + switch (oflags) { + case __WASI_O_CREAT | __WASI_O_EXCL: + case __WASI_O_CREAT | __WASI_O_EXCL | __WASI_O_TRUNC: + creation_disposition = CREATE_NEW; + break; + case __WASI_O_CREAT | __WASI_O_TRUNC: + creation_disposition = CREATE_ALWAYS; + break; + case __WASI_O_CREAT: + creation_disposition = OPEN_ALWAYS; + break; + case 0: + case __WASI_O_EXCL: + creation_disposition = OPEN_EXISTING; + break; + case __WASI_O_TRUNC: + case __WASI_O_EXCL | __WASI_O_TRUNC: + creation_disposition = TRUNCATE_EXISTING; + // CreateFile2 requires write access if we truncate the file upon + // opening + access_flags |= GENERIC_WRITE; + break; + } + + wchar_t absolute_path[PATH_MAX]; + error = get_absolute_filepath(handle->raw.handle, path, absolute_path, + PATH_MAX); + + if (error != __WASI_ESUCCESS) + goto fail; + + if ((lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) == 0) + attributes |= FILE_FLAG_OPEN_REPARSE_POINT; + + // Check that we're not trying to open an existing file as a directory. + // Windows doesn't seem to throw an error in this case so add an + // explicit check. + if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 + && creation_disposition == OPEN_EXISTING + && !is_directory(absolute_path)) { + error = __WASI_ENOTDIR; + goto fail; + } + + CREATEFILE2_EXTENDED_PARAMETERS create_params; + create_params.dwSize = sizeof(create_params); + create_params.dwFileAttributes = attributes & 0xFFF; + create_params.dwFileFlags = attributes & 0xFFF00000; + create_params.dwSecurityQosFlags = 0; + create_params.lpSecurityAttributes = NULL; + create_params.hTemplateFile = NULL; + + (*out)->raw.handle = + CreateFile2(absolute_path, access_flags, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + creation_disposition, &create_params); + + if ((*out)->raw.handle == INVALID_HANDLE_VALUE) { + error = convert_windows_error_code(GetLastError()); + goto fail; + } + + return error; +fail: + if (*out != NULL) { + if ((*out)->raw.handle != INVALID_HANDLE_VALUE) + CloseHandle((*out)->raw.handle); + + BH_FREE(*out); + } + + return error; } __wasi_errno_t @@ -656,13 +863,79 @@ os_close(os_file_handle handle, bool is_stdio) return __WASI_ESUCCESS; } +static __wasi_errno_t +read_data_at_offset(HANDLE handle, const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + OVERLAPPED *read_operations = + BH_MALLOC((uint32_t)(sizeof(OVERLAPPED) * (uint32_t)iovcnt)); + + if (read_operations == NULL) + return __WASI_ENOMEM; + + ULARGE_INTEGER query_offset = { .QuadPart = offset }; + __wasi_errno_t error = __WASI_ESUCCESS; + size_t total_bytes_read = 0; + + const __wasi_iovec_t *current = iov; + int successful_read_count = 0; + + for (int i = 0; i < iovcnt; ++i, ++current) { + read_operations[i].Internal = 0; + read_operations[i].InternalHigh = 0; + read_operations[i].Offset = query_offset.LowPart; + read_operations[i].OffsetHigh = query_offset.HighPart; + read_operations[i].hEvent = NULL; + + if (!ReadFileEx(handle, current->buf, (DWORD)current->buf_len, + &read_operations[i], NULL)) { + DWORD win_error = GetLastError(); + if (win_error != ERROR_IO_PENDING) { + error = convert_windows_error_code(win_error); + break; + } + } + ++successful_read_count; + query_offset.QuadPart += (DWORD)current->buf_len; + } + + // Get the result of all the asynchronous read operations + for (int i = 0; i < successful_read_count; ++i) { + DWORD bytes_transferred = 0; + if (!GetOverlappedResult(handle, &read_operations[i], + &bytes_transferred, true)) { + DWORD win_error = GetLastError(); + + if (win_error != ERROR_HANDLE_EOF) + error = convert_windows_error_code(win_error); + else + total_bytes_read += (size_t)bytes_transferred; + + CancelIo(handle); + + for (int j = i + 1; j < iovcnt; ++j) { + GetOverlappedResult(handle, &read_operations[j], + &bytes_transferred, true); + } + break; + } + + total_bytes_read += (size_t)bytes_transferred; + } + + *nwritten = total_bytes_read; + + BH_FREE(read_operations); + return error; +} + __wasi_errno_t os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, __wasi_filesize_t offset, size_t *nread) { CHECK_VALID_FILE_HANDLE(handle); - return __WASI_ENOSYS; + return read_data_at_offset(handle->raw.handle, iov, iovcnt, offset, nread); } __wasi_errno_t @@ -671,7 +944,90 @@ os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, { CHECK_VALID_HANDLE(handle); - return __WASI_ENOSYS; + LARGE_INTEGER current_offset = { .QuadPart = 0 }; + + // Seek to the current offset before reading + int ret = SetFilePointerEx(handle->raw.handle, current_offset, + ¤t_offset, FILE_CURRENT); + if (ret == 0) + return convert_windows_error_code(GetLastError()); + + __wasi_errno_t error = + read_data_at_offset(handle->raw.handle, iov, iovcnt, + (__wasi_filesize_t)current_offset.QuadPart, nread); + + if (error != __WASI_ESUCCESS) + return error; + + current_offset.QuadPart += (LONGLONG)(*nread); + + // Update the current offset to match how many bytes we've read + ret = + SetFilePointerEx(handle->raw.handle, current_offset, NULL, FILE_BEGIN); + + if (ret == 0) + error = convert_windows_error_code(GetLastError()); + + return error; +} + +static __wasi_errno_t +write_data_at_offset(HANDLE handle, const struct __wasi_ciovec_t *iov, + int iovcnt, __wasi_filesize_t offset, size_t *nwritten) +{ + OVERLAPPED *write_operations = + BH_MALLOC((uint32_t)(sizeof(OVERLAPPED) * (uint32_t)iovcnt)); + + if (write_operations == NULL) + return __WASI_ENOMEM; + + ULARGE_INTEGER query_offset = { .QuadPart = offset }; + __wasi_errno_t error = __WASI_ESUCCESS; + size_t total_bytes_written = 0; + + const __wasi_ciovec_t *current = iov; + int successful_write_count = 0; + for (int i = 0; i < iovcnt; ++i, ++current) { + write_operations[i].Internal = 0; + write_operations[i].InternalHigh = 0; + write_operations[i].Offset = query_offset.LowPart; + write_operations[i].OffsetHigh = query_offset.HighPart; + write_operations[i].hEvent = NULL; + + if (!WriteFileEx(handle, current->buf, (DWORD)current->buf_len, + &write_operations[i], NULL)) { + DWORD win_error = GetLastError(); + if (win_error != ERROR_IO_PENDING) { + error = convert_windows_error_code(win_error); + break; + } + } + ++successful_write_count; + query_offset.QuadPart += (DWORD)current->buf_len; + } + + // Get the result of all the asynchronous writes + for (int i = 0; i < successful_write_count; ++i) { + DWORD bytes_transferred = 0; + if (!GetOverlappedResult(handle, &write_operations[i], + &bytes_transferred, true)) { + error = convert_windows_error_code(GetLastError()); + CancelIo(handle); + + for (int j = i + 1; j < iovcnt; ++j) { + GetOverlappedResult(handle, &write_operations[j], + &bytes_transferred, true); + } + break; + } + + total_bytes_written += (size_t)bytes_transferred; + } + + *nwritten = total_bytes_written; + + BH_FREE(write_operations); + return error; } __wasi_errno_t @@ -680,7 +1036,8 @@ os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, { CHECK_VALID_FILE_HANDLE(handle); - return __WASI_ENOSYS; + return write_data_at_offset(handle->raw.handle, iov, iovcnt, offset, + nwritten); } __wasi_errno_t @@ -689,7 +1046,31 @@ os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, { CHECK_VALID_HANDLE(handle); - return __WASI_ENOSYS; + bool append = (handle->fdflags & windows_fdflags_append) != 0; + LARGE_INTEGER write_offset = { .QuadPart = 0 }; + DWORD move_method = append ? FILE_END : FILE_CURRENT; + + int ret = SetFilePointerEx(handle->raw.handle, write_offset, &write_offset, + move_method); + if (ret == 0) + return convert_windows_error_code(GetLastError()); + + __wasi_errno_t error = write_data_at_offset( + handle->raw.handle, iov, iovcnt, + (__wasi_filesize_t)write_offset.QuadPart, nwritten); + + if (error != __WASI_ESUCCESS) + return error; + + write_offset.QuadPart += (LONGLONG)(*nwritten); + + // Update the write offset to match how many bytes we've written + ret = SetFilePointerEx(handle->raw.handle, write_offset, NULL, FILE_BEGIN); + + if (ret == 0) + error = convert_windows_error_code(GetLastError()); + + return error; } __wasi_errno_t @@ -735,7 +1116,151 @@ os_readlinkat(os_file_handle handle, const char *path, char *buf, { CHECK_VALID_FILE_HANDLE(handle); - return __WASI_ENOSYS; + wchar_t symlink_path[PATH_MAX]; + __wasi_errno_t error = + get_absolute_filepath(handle->raw.handle, path, symlink_path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + DWORD symlink_attributes = GetFileAttributesW(symlink_path); + + if (!has_symlink_attribute(symlink_attributes)) + return __WASI_EINVAL; + + HANDLE link_handle = create_handle( + symlink_path, has_directory_attribute(symlink_attributes), false, true); + + if (link_handle == INVALID_HANDLE_VALUE) + return convert_windows_error_code(GetLastError()); + +#if WINAPI_PARTITION_DESKTOP != 0 +// MinGW32 already has a definition for REPARSE_DATA_BUFFER +#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) + // See + // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_reparse_data_buffer + // for more details. + typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; + } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; +#endif + + char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + + REPARSE_DATA_BUFFER *reparse_data = (REPARSE_DATA_BUFFER *)buffer; + + if (!DeviceIoControl(link_handle, FSCTL_GET_REPARSE_POINT, NULL, 0, &buffer, + sizeof(buffer), NULL, NULL)) { + error = convert_windows_error_code(GetLastError()); + goto fail; + } + + int wbufsize = 0; + wchar_t *wbuf = NULL; + + // The following checks are taken from the libuv windows filesystem + // implementation, + // https://github.com/libuv/libuv/blob/v1.x/src/win/fs.c#L181-L244. Real + // symlinks can contain pretty much anything, but the only thing we really + // care about is undoing the implicit conversion to an NT namespaced path + // that CreateSymbolicLink will perform on absolute paths. + if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + wbuf = reparse_data->SymbolicLinkReparseBuffer.PathBuffer + + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset + / sizeof(wchar_t)); + wbufsize = reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength + / sizeof(wchar_t); + + if (wbufsize >= 4 && wbuf[0] == L'\\' && wbuf[1] == L'?' + && wbuf[2] == L'?' && wbuf[3] == L'\\') { + // Starts with \??\ + if (wbufsize >= 6 + && ((wbuf[4] >= L'A' && wbuf[4] <= L'Z') + || (wbuf[4] >= L'a' && wbuf[4] <= L'z')) + && wbuf[5] == L':' && (wbufsize == 6 || wbuf[6] == L'\\')) + { + // \??\:\ + wbuf += 4; + wbufsize -= 4; + } + else if (wbufsize >= 8 && (wbuf[4] == L'U' || wbuf[4] == L'u') + && (wbuf[5] == L'N' || wbuf[5] == L'n') + && (wbuf[6] == L'C' || wbuf[6] == L'c') + && wbuf[7] == L'\\') + { + // \??\UNC\\\ - make sure the final path looks like \\\\ + wbuf += 6; + wbuf[0] = L'\\'; + wbufsize -= 6; + } + } + } + else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + // Junction + wbuf = reparse_data->MountPointReparseBuffer.PathBuffer + + (reparse_data->MountPointReparseBuffer.SubstituteNameOffset + / sizeof(wchar_t)); + wbufsize = reparse_data->MountPointReparseBuffer.SubstituteNameLength + / sizeof(wchar_t); + + // Only treat junctions that look like \??\:\ as a symlink. + if (!(wbufsize >= 6 && wbuf[0] == L'\\' && wbuf[1] == L'?' + && wbuf[2] == L'?' && wbuf[3] == L'\\' + && ((wbuf[4] >= L'A' && wbuf[4] <= L'Z') + || (wbuf[4] >= L'a' && wbuf[4] <= L'z')) + && wbuf[5] == L':' && (wbufsize == 6 || wbuf[6] == L'\\'))) { + error = __WASI_EINVAL; + goto fail; + } + + /* Remove leading \??\ */ + wbuf += 4; + wbufsize -= 4; + } + else { + error = __WASI_EINVAL; + goto fail; + } + + if (wbuf != NULL) + *nread = (size_t)WideCharToMultiByte(CP_UTF8, 0, wbuf, wbufsize, buf, + (int)bufsize, NULL, NULL); + + if (*nread == 0 && wbuf != NULL) { + DWORD win_error = GetLastError(); + if (win_error == ERROR_INSUFFICIENT_BUFFER) + *nread = bufsize; + else + error = convert_windows_error_code(win_error); + } +#else + error = __WASI_ENOTSUP; +#endif +fail: + CloseHandle(link_handle); + return error; } __wasi_errno_t @@ -762,7 +1287,19 @@ os_mkdirat(os_file_handle handle, const char *path) { CHECK_VALID_FILE_HANDLE(handle); - return __WASI_ENOSYS; + wchar_t absolute_path[PATH_MAX]; + __wasi_errno_t error = get_absolute_filepath(handle->raw.handle, path, + absolute_path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + bool success = CreateDirectoryW(absolute_path, NULL); + + if (!success) + error = convert_windows_error_code(GetLastError()); + + return error; } __wasi_errno_t @@ -780,7 +1317,28 @@ os_unlinkat(os_file_handle handle, const char *path, bool is_dir) { CHECK_VALID_FILE_HANDLE(handle); - return __WASI_ENOSYS; + wchar_t absolute_path[PATH_MAX]; + __wasi_errno_t error = get_absolute_filepath(handle->raw.handle, path, + absolute_path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + DWORD attributes = GetFileAttributesW(absolute_path); + + if (has_symlink_attribute(attributes)) { + // Override is_dir for symlinks. A symlink to a directory counts + // as a directory itself in Windows. + is_dir = has_directory_attribute(attributes); + } + + int ret = + is_dir ? RemoveDirectoryW(absolute_path) : DeleteFileW(absolute_path); + + if (ret == 0) + error = convert_windows_error_code(GetLastError()); + + return error; } __wasi_errno_t @@ -822,6 +1380,7 @@ create_stdio_handle(HANDLE raw_stdio_handle, DWORD stdio) stdio_handle->type = windows_handle_type_file; stdio_handle->access_mode = windows_access_mode_read | windows_access_mode_write; + stdio_handle->fdflags = 0; if (raw_stdio_handle == INVALID_HANDLE_VALUE) raw_stdio_handle = GetStdHandle(stdio); diff --git a/core/shared/platform/windows/win_socket.c b/core/shared/platform/windows/win_socket.c index d82cd724..bc05b001 100644 --- a/core/shared/platform/windows/win_socket.c +++ b/core/shared/platform/windows/win_socket.c @@ -70,6 +70,7 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) (*sock)->type = windows_handle_type_socket; (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write; + (*sock)->fdflags = 0; if (is_ipv4) { af = AF_INET; @@ -174,6 +175,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, (*sock)->type = windows_handle_type_socket; (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write; + (*sock)->fdflags = 0; (*sock)->raw.socket = accept(server_sock->raw.socket, (struct sockaddr *)&addr_tmp, &len); diff --git a/product-mini/platforms/windows/wasi_filtered_tests.json b/product-mini/platforms/windows/wasi_filtered_tests.json new file mode 100644 index 00000000..492a746e --- /dev/null +++ b/product-mini/platforms/windows/wasi_filtered_tests.json @@ -0,0 +1,51 @@ +{ + "WASI C tests": { + "fdopendir-with-access": "Not implemented", + "lseek": "Not implemented" + }, + "WASI Rust tests": { + "dangling_symlink": "Not implemented", + "directory_seek": "Not implemented", + "dir_fd_op_failures": "Not implemented", + "fd_advise": "Not implemented", + "fd_fdstat_set_rights": "Not implemented", + "fd_filestat_set": "Not implemented", + "fd_flags_set": "Not implemented", + "fd_readdir": "Not implemented", + "file_allocate": "Not implemented", + "file_seek_tell": "Not implemented", + "file_truncation": "Not implemented", + "nofollow_errors": "Not implemented", + "path_exists": "Not implemented", + "path_filestat": "Not implemented", + "path_link": "Not implemented", + "path_open_preopen": "Not implemented", + "path_rename": "Not implemented", + "path_rename_dir_trailing_slashes": "Not implemented", + "path_symlink_trailing_slashes": "Not implemented", + "poll_oneoff_stdio": "Not implemented", + "readlink": "Not implemented (path_symlink)", + "symlink_create": "Not implemented", + "symlink_filestat": "Not implemented", + "symlink_loop": "Not implemented", + "truncation_rights": "Not implemented" + }, + "WASI threads proposal": { + "wasi_threads_exit_main_wasi_read": "Blocking ops not implemented", + "wasi_threads_exit_nonmain_wasi_read": "Blocking ops not implemented", + "wasi_threads_return_main_wasi_read": "Blocking ops not implemented", + "wasi_threads_return_main_wasi": "Blocking ops not implemented", + "wasi_threads_exit_nonmain_wasi": "Blocking ops not implemented", + "wasi_threads_exit_main_wasi": "Blocking ops not implemented" + }, + "WAMR lib-socket tests": { + "nslookup": "Not implemented", + "tcp_udp": "Not implemented" + }, + "lib-wasi-threads tests": { + "nonmain_proc_exit_sleep": "poll_oneoff not implemented", + "main_proc_exit_sleep": "poll_oneoff not implemented", + "main_trap_sleep": "poll_oneoff not implemented", + "nonmain_trap_sleep": "poll_oneoff not implemented" + } +} \ No newline at end of file diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index e30cf499..e23f7e68 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -566,7 +566,7 @@ function wasi_certification_test() cd wasi-testsuite git reset --hard ${WASI_TESTSUITE_COMMIT} - bash ../../wasi-test-script/run_wasi_tests.sh $1 $TARGET \ + bash ../../wasi-test-script/run_wasi_tests.sh $1 $TARGET $WASI_TEST_FILTER \ | tee -a ${REPORT_DIR}/wasi_test_report.txt ret=${PIPESTATUS[0]} @@ -836,6 +836,17 @@ function trigger() EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_SANITIZER=tsan" fi + # Make sure we're using the builtin WASI libc implementation + # if we're running the wasi certification tests. + if [[ $TEST_CASE_ARR ]]; then + for test in "${TEST_CASE_ARR[@]}"; do + if [[ "$test" == "wasi_certification" ]]; then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1" + break + fi + done + fi + for t in "${TYPE[@]}"; do case $t in "classic-interp") diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index ae53f829..56d0a06b 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -9,6 +9,7 @@ THIS_DIR=$(cd $(dirname $0) && pwd -P) readonly MODE=$1 readonly TARGET=$2 +readonly TEST_FILTER=$3 readonly WORK_DIR=$PWD @@ -41,8 +42,21 @@ readonly THREAD_STRESS_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/ readonly LIB_SOCKET_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-socket/test/" run_aot_tests () { - local tests=("$@") + local -n tests=$1 + local -n excluded_tests=$2 + for test_wasm in ${tests[@]}; do + # get the base file name from the filepath + local test_name=${test_wasm##*/} + test_name=${test_name%.wasm} + + for excluded_test in "${excluded_tests[@]}"; do + if [[ $excluded_test == "\"$test_name\"" ]]; then + echo "Skipping test $test_name" + continue 2 + fi + done + local iwasm="${IWASM_CMD}" if [[ $test_wasm =~ "stress" ]]; then iwasm="${IWASM_CMD_STRESS}" @@ -80,15 +94,21 @@ if [[ $MODE != "aot" ]];then $PYTHON_EXE -m pip install -r test-runner/requirements.txt export TEST_RUNTIME_EXE="${IWASM_CMD}" - $PYTHON_EXE ${THIS_DIR}/pipe.py | $PYTHON_EXE test-runner/wasi_test_runner.py \ - -r adapters/wasm-micro-runtime.py \ - -t \ - ${C_TESTS} \ - ${RUST_TESTS} \ - ${ASSEMBLYSCRIPT_TESTS} \ - ${THREAD_PROPOSAL_TESTS} \ - ${THREAD_INTERNAL_TESTS} \ - ${LIB_SOCKET_TESTS} \ + + TEST_OPTIONS="-r adapters/wasm-micro-runtime.py \ + -t \ + ${C_TESTS} \ + ${RUST_TESTS} \ + ${ASSEMBLYSCRIPT_TESTS} \ + ${THREAD_PROPOSAL_TESTS} \ + ${THREAD_INTERNAL_TESTS} \ + ${LIB_SOCKET_TESTS}" + + if [ -n "$TEST_FILTER" ]; then + TEST_OPTIONS="${TEST_OPTIONS} --exclude-filter ${TEST_FILTER}" + fi + + $PYTHON_EXE ${THIS_DIR}/pipe.py | $PYTHON_EXE test-runner/wasi_test_runner.py $TEST_OPTIONS ret=${PIPESTATUS[1]} @@ -114,7 +134,17 @@ else for testsuite in ${THREAD_STRESS_TESTS} ${THREAD_PROPOSAL_TESTS} ${THREAD_INTERNAL_TESTS}; do tests=$(ls ${testsuite}*.wasm) tests_array=($tests) - run_aot_tests "${tests_array[@]}" + + if [ -n "$TEST_FILTER" ]; then + readarray -t excluded_tests_array < <(jq -c \ + --slurpfile testsuite_manifest $testsuite/manifest.json \ + '.[$testsuite_manifest[0].name] // {} | keys[]' \ + $TEST_FILTER) + else + excluded_tests_array=() + fi + + run_aot_tests tests_array excluded_tests_array done fi From 77b6bce6798de7815d45ac716d91ecf235922eb4 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Tue, 7 Nov 2023 01:39:15 +0000 Subject: [PATCH 16/18] Move WASI types into separate header (#2724) To allow anything to depend on WASI types, including platform-specific data structures, move the WASI libc filesystem/clock interface into `platform_api_extension.h`, which leaves just WASI types in `platform_wasi.h`. And `platform_wasi.h` has been renamed to `platform_wasi_types.h` to reflect that it only defines types now and no function declarations. Finally, these changes allow us to remove the `windows_fdflags` type which was essentially a duplicate of `__wasi_fdflags_t`. --- .../platform/common/libc-util/libc_errno.h | 2 +- .../platform/include/platform_api_extension.h | 522 ++++++++++++++++- ...{platform_wasi.h => platform_wasi_types.h} | 535 +----------------- .../platform/windows/platform_internal.h | 14 +- core/shared/platform/windows/win_file.c | 2 +- core/shared/platform/windows/win_util.h | 2 +- 6 files changed, 536 insertions(+), 541 deletions(-) rename core/shared/platform/include/{platform_wasi.h => platform_wasi_types.h} (54%) diff --git a/core/shared/platform/common/libc-util/libc_errno.h b/core/shared/platform/common/libc-util/libc_errno.h index d136c0cf..b0a8b78c 100644 --- a/core/shared/platform/common/libc-util/libc_errno.h +++ b/core/shared/platform/common/libc-util/libc_errno.h @@ -6,7 +6,7 @@ #ifndef WASI_ERRNO_H #define WASI_ERRNO_H -#include "platform_wasi.h" +#include "platform_wasi_types.h" // Converts an errno error code to a WASI error code. __wasi_errno_t diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index e40ddfd0..2795fc6a 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -7,7 +7,7 @@ #define PLATFORM_API_EXTENSION_H #include "platform_common.h" -#include "platform_wasi.h" +#include "platform_wasi_types.h" /** * The related data structures should be defined * in platform_internal.h @@ -1112,6 +1112,526 @@ os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled); int os_dumps_proc_mem_info(char *out, unsigned int size); +/**************************************************** + * Section 3 * + * Filesystem support * + ****************************************************/ + +/** + * 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); + +/**************************************************** + * Section 4 * + * Clock functions * + ****************************************************/ + +/** + * NOTES: + * Clock functions are required for WASI libc support. If you don't need to + * support WASI libc, there is no need to implement these APIs. + */ + +/** + * Get the resolution of the specified clock. + * + * @param clock_id clock identifier + * @param resolution output variable to store the clock resolution + */ +__wasi_errno_t +os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution); + +/** + * Get the current time of the specified clock. + * + * @param clock_id clock identifier + * @param precision the maximum lag that the returned time value may have, + * compared to its actual value. + * @param time output variable to store the clock time + */ +__wasi_errno_t +os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, + __wasi_timestamp_t *time); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/include/platform_wasi.h b/core/shared/platform/include/platform_wasi_types.h similarity index 54% rename from core/shared/platform/include/platform_wasi.h rename to core/shared/platform/include/platform_wasi_types.h index 23ea0c45..ac1a95ea 100644 --- a/core/shared/platform/include/platform_wasi.h +++ b/core/shared/platform/include/platform_wasi_types.h @@ -4,18 +4,18 @@ */ /* - * 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: + * This file declares the WASI interface. 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 +#ifndef _PLATFORM_WASI_TYPES_H +#define _PLATFORM_WASI_TYPES_H -#include "platform_common.h" -#include "platform_internal.h" +#include "../../../config.h" + +#include +#include /* clang-format off */ @@ -603,525 +603,8 @@ typedef struct __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); - -/**************************************************** - * * - * Clock functions * - * * - ****************************************************/ - -/** - * Get the resolution of the specified clock. - * - * @param clock_id clock identifier - * @param resolution output variable to store the clock resolution - */ -__wasi_errno_t -os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution); - -/** - * Get the current time of the specified clock. - * - * @param clock_id clock identifier - * @param precision the maximum lag that the returned time value may have, - * compared to its actual value. - * @param time output variable to store the clock time - */ -__wasi_errno_t -os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, - __wasi_timestamp_t *time); - #ifdef __cplusplus } #endif -#endif /* end of _PLATFORM_WASI_H */ \ No newline at end of file +#endif /* end of _PLATFORM_WASI_TYPES_H */ \ No newline at end of file diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 275ea5d3..d2d3d41a 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -32,6 +32,8 @@ #include #include +#include "platform_wasi_types.h" + #ifdef __cplusplus extern "C" { #endif @@ -146,19 +148,9 @@ typedef enum windows_access_mode { windows_access_mode_write = 1 << 1 } windows_access_mode; -// These enum values are defined to be the same as the corresponding WASI -// fdflags so they can be used interchangeably. -typedef enum windows_fdflags { - windows_fdflags_append = 1 << 0, - windows_fdflags_dsync = 1 << 1, - windows_fdflags_nonblock = 1 << 2, - windows_fdflags_rsync = 1 << 3, - windows_fdflags_sync = 1 << 4 -} windows_fdflags; - typedef struct windows_handle { windows_handle_type type; - windows_fdflags fdflags; + __wasi_fdflags_t fdflags; windows_access_mode access_mode; union { HANDLE handle; diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 333e089e..6e827118 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -1046,7 +1046,7 @@ os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, { CHECK_VALID_HANDLE(handle); - bool append = (handle->fdflags & windows_fdflags_append) != 0; + bool append = (handle->fdflags & __WASI_FDFLAG_APPEND) != 0; LARGE_INTEGER write_offset = { .QuadPart = 0 }; DWORD move_method = append ? FILE_END : FILE_CURRENT; diff --git a/core/shared/platform/windows/win_util.h b/core/shared/platform/windows/win_util.h index 197dfce1..0733b076 100644 --- a/core/shared/platform/windows/win_util.h +++ b/core/shared/platform/windows/win_util.h @@ -6,7 +6,7 @@ #ifndef _WIN_UTIL_H #define _WIN_UTIL_H -#include "platform_wasi.h" +#include "platform_wasi_types.h" #include "windows.h" __wasi_timestamp_t From 3c9cd40aa6ed7ef26eefffbb6017499dc45eb6d3 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Tue, 7 Nov 2023 12:37:43 +0000 Subject: [PATCH 17/18] Provide default vprintf on UWP (#2725) UWP apps do not have a console attached so any output to stdout/stderr is lost. Therefore, provide a default BH_VPRINTF in that case for debug builds which redirects output to the debugger. --- .../sandboxed-system-primitives/src/posix.c | 12 +++---- .../platform/windows/platform_internal.h | 11 ++++++ core/shared/platform/windows/win_util.c | 35 ++++++++++++++++++- 3 files changed, 50 insertions(+), 8 deletions(-) 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 c43423dc..03b262ca 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 @@ -1108,19 +1108,17 @@ wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, 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 (fo->is_stdio) { int i; - const struct iovec *iov1 = (const struct iovec *)iov; - - for (i = 0; i < (int)iovcnt; i++, iov1++) { - if (iov1->iov_len > 0 && iov1->iov_base) { + *nwritten = 0; + for (i = 0; i < (int)iovcnt; i++) { + if (iov[i].buf_len > 0 && iov[i].buf != NULL) { char format[16]; /* make up format string "%.ns" */ - snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len); - len += (ssize_t)os_printf(format, iov1->iov_base); + snprintf(format, sizeof(format), "%%.%ds", (int)iov[i].buf_len); + *nwritten += (size_t)os_printf(format, iov[i].buf); } } } diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index d2d3d41a..77bf8497 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -179,6 +179,17 @@ typedef uint32_t os_raw_file_handle; #define bh_socket_t windows_handle * +// UWP apps do not have stdout/stderr handles so provide a default +// implementation of vprintf on debug builds so output from WASI libc is sent to +// the debugger and not lost completely. +#if !defined(BH_VPRINTF) && !defined(NDEBUG) && WINAPI_PARTITION_DESKTOP == 0 +int +uwp_print_to_debugger(const char *format, va_list ap); + +#define BH_VPRINTF uwp_print_to_debugger +#define UWP_DEFAULT_VPRINTF +#endif + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/windows/win_util.c b/core/shared/platform/windows/win_util.c index d24685c9..212db6b8 100644 --- a/core/shared/platform/windows/win_util.c +++ b/core/shared/platform/windows/win_util.c @@ -57,4 +57,37 @@ convert_windows_error_code(DWORD windows_error_code) default: return __WASI_EINVAL; } -} \ No newline at end of file +} + +#ifdef UWP_DEFAULT_VPRINTF +int +uwp_print_to_debugger(const char *format, va_list ap) +{ + // Provide a stack buffer which should be large enough for any realistic + // string so we avoid making an allocation on every printf call. + char stack_buf[2048]; + char *buf = stack_buf; + int ret = vsnprintf(stack_buf, sizeof(stack_buf), format, ap); + + if (ret >= sizeof(stack_buf)) { + // Allocate an extra byte for the null terminator. + char *heap_buf = BH_MALLOC(ret + 1); + buf = heap_buf; + + if (heap_buf == NULL) { + errno = ENOMEM; + return -1; + } + + ret = vsnprintf(heap_buf, ret + 1, format, ap); + } + + if (ret >= 0) + OutputDebugStringA(buf); + + if (buf != stack_buf) + BH_FREE(buf); + + return ret; +} +#endif \ No newline at end of file From fa2839a80528639beabf4b43d93da94dbe67d6d3 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Wed, 8 Nov 2023 12:28:34 +0000 Subject: [PATCH 18/18] Fix default vprintf on UWP (#2730) `platform_common.h` already has a declaration for BH_VPRINTF so we can get rid of the one in `platform_internal.h`. Also add some explicit casts to avoid MSVC compiler warnings. --- core/shared/platform/windows/platform_internal.h | 3 --- core/shared/platform/windows/win_util.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 77bf8497..a537161f 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -183,9 +183,6 @@ typedef uint32_t os_raw_file_handle; // implementation of vprintf on debug builds so output from WASI libc is sent to // the debugger and not lost completely. #if !defined(BH_VPRINTF) && !defined(NDEBUG) && WINAPI_PARTITION_DESKTOP == 0 -int -uwp_print_to_debugger(const char *format, va_list ap); - #define BH_VPRINTF uwp_print_to_debugger #define UWP_DEFAULT_VPRINTF #endif diff --git a/core/shared/platform/windows/win_util.c b/core/shared/platform/windows/win_util.c index 212db6b8..50c446d6 100644 --- a/core/shared/platform/windows/win_util.c +++ b/core/shared/platform/windows/win_util.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include "platform_common.h" #include "win_util.h" __wasi_timestamp_t @@ -69,17 +70,19 @@ uwp_print_to_debugger(const char *format, va_list ap) char *buf = stack_buf; int ret = vsnprintf(stack_buf, sizeof(stack_buf), format, ap); - if (ret >= sizeof(stack_buf)) { + if ((size_t)ret >= sizeof(stack_buf)) { // Allocate an extra byte for the null terminator. - char *heap_buf = BH_MALLOC(ret + 1); + char *heap_buf = BH_MALLOC((unsigned int)(ret) + 1); buf = heap_buf; if (heap_buf == NULL) { - errno = ENOMEM; - return -1; + // Output as much as we can to the debugger if allocating a buffer + // fails. + OutputDebugStringA(stack_buf); + return ret; } - ret = vsnprintf(heap_buf, ret + 1, format, ap); + ret = vsnprintf(heap_buf, (size_t)ret + 1, format, ap); } if (ret >= 0)