diff options
Diffstat (limited to 'src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi')
21 files changed, 9213 insertions, 0 deletions
diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript new file mode 100644 index 000000000..6ed3799e0 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript @@ -0,0 +1,34 @@ +# +# Copyright (c) 2021, RT-Thread Development Team +# +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +from building import * +import os + +cwd = GetCurrentDir() + +src = Split(''' +''') + +CPPPATH = [cwd, + cwd+'/sandboxed-system-primitives/include', + cwd+'/sandboxed-system-primitives/src'] + +def addSrcFiles(arr, path): + for f in os.listdir(path): + fpath = os.path.join(path, f); + if os.path.isfile(fpath): + ext = os.path.splitext(fpath)[-1] + if ext == '.c' or ext == '.cpp': + arr += [fpath] + elif os.path.isdir(fpath): + addSrcFiles(arr, fpath) + + +addSrcFiles(src, cwd) + +group = DefineGroup('iwasm_libc_wasi', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake new file mode 100644 index 000000000..d72c42a06 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions (-DWASM_ENABLE_LIBC_WASI=1) + +include_directories(${LIBC_WASI_DIR}/sandboxed-system-primitives/include + ${LIBC_WASI_DIR}/sandboxed-system-primitives/src) + +file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c ) + +set (LIBC_WASI_SOURCE ${source_all}) diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c new file mode 100644 index 000000000..afb11925a --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -0,0 +1,2329 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "libc_wasi_wrapper.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "wasm_runtime_common.h" + +#if WASM_ENABLE_THREAD_MGR != 0 +#include "../../../thread-mgr/thread_manager.h" +#endif + +void +wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); + +/* clang-format off */ +#define get_module_inst(exec_env) \ + wasm_runtime_get_module_inst(exec_env) + +#define get_wasi_ctx(module_inst) \ + wasm_runtime_get_wasi_ctx(module_inst) + +#define validate_app_addr(offset, size) \ + wasm_runtime_validate_app_addr(module_inst, offset, size) + +#define validate_native_addr(addr, size) \ + wasm_runtime_validate_native_addr(module_inst, addr, size) + +#define addr_app_to_native(offset) \ + wasm_runtime_addr_app_to_native(module_inst, offset) + +#define addr_native_to_app(ptr) \ + wasm_runtime_addr_native_to_app(module_inst, ptr) + +#define module_malloc(size, p_native_addr) \ + wasm_runtime_module_malloc(module_inst, size, p_native_addr) + +#define module_free(offset) \ + wasm_runtime_module_free(module_inst, offset) +/* clang-format on */ + +typedef struct wasi_prestat_app { + wasi_preopentype_t pr_type; + uint32 pr_name_len; +} wasi_prestat_app_t; + +typedef struct iovec_app { + uint32 buf_offset; + uint32 buf_len; +} iovec_app_t; + +typedef struct WASIContext *wasi_ctx_t; + +wasi_ctx_t +wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); + +static inline uint64_t +min_uint64(uint64_t a, uint64_t b) +{ + return a > b ? b : a; +} + +static inline uint32_t +min_uint32(uint32_t a, uint32_t b) +{ + return a > b ? b : a; +} + +static inline struct fd_table * +wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +{ + if (!wasi_ctx) + return NULL; + return wasi_ctx->curfds; +} + +static inline struct argv_environ_values * +wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +{ + if (!wasi_ctx) + return NULL; + return wasi_ctx->argv_environ; +} + +static inline struct fd_prestats * +wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +{ + if (!wasi_ctx) + return NULL; + return wasi_ctx->prestats; +} + +static inline struct addr_pool * +wasi_ctx_get_addr_pool(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +{ + if (!wasi_ctx) + return NULL; + return wasi_ctx->addr_pool; +} + +static inline char ** +wasi_ctx_get_ns_lookup_list(wasi_ctx_t wasi_ctx) +{ + if (!wasi_ctx) + return NULL; + return wasi_ctx->ns_lookup_list; +} + +static wasi_errno_t +wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct argv_environ_values *argv_environ = + wasi_ctx_get_argv_environ(module_inst, wasi_ctx); + size_t argc, argv_buf_size, i; + char **argv; + uint64 total_size; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size); + if (err) + return err; + + total_size = sizeof(int32) * ((uint64)argc + 1); + if (total_size >= UINT32_MAX + || !validate_native_addr(argv_offsets, (uint32)total_size) + || argv_buf_size >= UINT32_MAX + || !validate_native_addr(argv_buf, (uint32)argv_buf_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(char *) * ((uint64)argc + 1); + if (total_size >= UINT32_MAX + || !(argv = wasm_runtime_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_args_get(argv_environ, argv, argv_buf); + if (err) { + wasm_runtime_free(argv); + return err; + } + + for (i = 0; i < argc; i++) + argv_offsets[i] = addr_native_to_app(argv[i]); + + wasm_runtime_free(argv); + return 0; +} + +static wasi_errno_t +wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app, + uint32 *argv_buf_size_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct argv_environ_values *argv_environ; + size_t argc, argv_buf_size; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(argc_app, sizeof(uint32)) + || !validate_native_addr(argv_buf_size_app, sizeof(uint32))) + return (wasi_errno_t)-1; + + argv_environ = wasi_ctx->argv_environ; + + err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size); + if (err) + return err; + + *argc_app = (uint32)argc; + *argv_buf_size_app = (uint32)argv_buf_size; + return 0; +} + +static wasi_errno_t +wasi_clock_res_get(wasm_exec_env_t exec_env, + wasi_clockid_t clock_id, /* uint32 clock_id */ + wasi_timestamp_t *resolution /* uint64 *resolution */) +{ + wasm_module_inst_t module_inst = get_module_inst(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); +} + +static wasi_errno_t +wasi_clock_time_get(wasm_exec_env_t exec_env, + wasi_clockid_t clock_id, /* uint32 clock_id */ + wasi_timestamp_t precision, /* uint64 precision */ + wasi_timestamp_t *time /* uint64 *time */) +{ + wasm_module_inst_t module_inst = get_module_inst(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); +} + +static wasi_errno_t +wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, + char *environ_buf) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct argv_environ_values *argv_environ = + wasi_ctx_get_argv_environ(module_inst, wasi_ctx); + size_t environ_count, environ_buf_size, i; + uint64 total_size; + char **environs; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count, + &environ_buf_size); + if (err) + return err; + + total_size = sizeof(int32) * ((uint64)environ_count + 1); + if (total_size >= UINT32_MAX + || !validate_native_addr(environ_offsets, (uint32)total_size) + || environ_buf_size >= UINT32_MAX + || !validate_native_addr(environ_buf, (uint32)environ_buf_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(char *) * (((uint64)environ_count + 1)); + + if (total_size >= UINT32_MAX + || !(environs = wasm_runtime_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_environ_get(argv_environ, environs, environ_buf); + if (err) { + wasm_runtime_free(environs); + return err; + } + + for (i = 0; i < environ_count; i++) + environ_offsets[i] = addr_native_to_app(environs[i]); + + wasm_runtime_free(environs); + return 0; +} + +static wasi_errno_t +wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app, + uint32 *environ_buf_size_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct argv_environ_values *argv_environ = + wasi_ctx_get_argv_environ(module_inst, wasi_ctx); + size_t environ_count, environ_buf_size; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(environ_count_app, sizeof(uint32)) + || !validate_native_addr(environ_buf_size_app, sizeof(uint32))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count, + &environ_buf_size); + if (err) + return err; + + *environ_count_app = (uint32)environ_count; + *environ_buf_size_app = (uint32)environ_buf_size; + + return 0; +} + +static wasi_errno_t +wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_prestat_app_t *prestat_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + wasi_prestat_t prestat; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_prestat_get(prestats, fd, &prestat); + if (err) + return err; + + prestat_app->pr_type = prestat.pr_type; + prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len; + return 0; +} + +static wasi_errno_t +wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path, + uint32 path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_prestat_dir_name(prestats, fd, path, path_len); +} + +static wasi_errno_t +wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_close(curfds, prestats, fd); +} + +static wasi_errno_t +wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_datasync(curfds, fd); +} + +static wasi_errno_t +wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, + uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + wasi_iovec_t *iovec, *iovec_begin; + uint64 total_size; + size_t nread; + uint32 i; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_native_addr(iovec_app, (uint32)total_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(iovec_begin = wasm_runtime_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + iovec = iovec_begin; + + for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); + iovec->buf_len = iovec_app->buf_len; + } + + err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset, + &nread); + if (err) + goto fail; + + *nread_app = (uint32)nread; + + /* success */ + err = 0; + +fail: + wasm_runtime_free(iovec_begin); + return err; +} + +static wasi_errno_t +wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, + wasi_filesize_t offset, uint32 *nwritten_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + wasi_ciovec_t *ciovec, *ciovec_begin; + uint64 total_size; + size_t nwritten; + uint32 i; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + ciovec = ciovec_begin; + + for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf_len = iovec_app->buf_len; + } + + err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset, + &nwritten); + if (err) + goto fail; + + *nwritten_app = (uint32)nwritten; + + /* success */ + err = 0; + +fail: + wasm_runtime_free(ciovec_begin); + return err; +} + +static wasi_errno_t +wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + wasi_iovec_t *iovec, *iovec_begin; + uint64 total_size; + size_t nread; + uint32 i; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(iovec_begin = wasm_runtime_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + iovec = iovec_begin; + + for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); + iovec->buf_len = iovec_app->buf_len; + } + + err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread); + if (err) + goto fail; + + *nread_app = (uint32)nread; + + /* success */ + err = 0; + +fail: + wasm_runtime_free(iovec_begin); + return err; +} + +static wasi_errno_t +wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_renumber(curfds, prestats, from, to); +} + +static wasi_errno_t +wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, + wasi_whence_t whence, wasi_filesize_t *newoffset) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset); +} + +static wasi_errno_t +wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_tell(curfds, fd, newoffset); +} + +static wasi_errno_t +wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_fdstat_t *fdstat_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + wasi_fdstat_t fdstat; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat); + if (err) + return err; + + memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t)); + return 0; +} + +static wasi_errno_t +wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_fdflags_t flags) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags); +} + +static wasi_errno_t +wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_rights_t fs_rights_base, + wasi_rights_t fs_rights_inheriting) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base, + fs_rights_inheriting); +} + +static wasi_errno_t +wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_sync(curfds, fd); +} + +static wasi_errno_t +wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, + uint32 *nwritten_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + wasi_ciovec_t *ciovec, *ciovec_begin; + uint64 total_size; + size_t nwritten; + uint32 i; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + return (wasi_errno_t)-1; + + total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + ciovec = ciovec_begin; + + for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf_len = iovec_app->buf_len; + } + + err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten); + if (err) + goto fail; + + *nwritten_app = (uint32)nwritten; + + /* success */ + err = 0; + +fail: + wasm_runtime_free(ciovec_begin); + return err; +} + +static wasi_errno_t +wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, + wasi_filesize_t len, wasi_advice_t advice) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice); +} + +static wasi_errno_t +wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, + wasi_filesize_t len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_allocate(curfds, fd, offset, len); +} + +static wasi_errno_t +wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, + const char *path, uint32 path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len); +} + +static wasi_errno_t +wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, + wasi_lookupflags_t old_flags, const char *old_path, + uint32 old_path_len, wasi_fd_t new_fd, const char *new_path, + uint32 new_path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path, + old_path_len, new_fd, new_path, new_path_len); +} + +static wasi_errno_t +wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, + wasi_lookupflags_t dirflags, const char *path, uint32 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_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + wasi_fd_t fd = (wasi_fd_t)-1; /* set fd_app -1 if path open failed */ + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len, + oflags, fs_rights_base, fs_rights_inheriting, + fs_flags, &fd); + + *fd_app = fd; + return err; +} + +static wasi_errno_t +wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, + uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + size_t bufused; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(bufused_app, sizeof(uint32))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused); + if (err) + return err; + + *bufused_app = (uint32)bufused; + return 0; +} + +static wasi_errno_t +wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, + uint32 path_len, char *buf, uint32 buf_len, + uint32 *bufused_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + size_t bufused; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(bufused_app, sizeof(uint32))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len, + &bufused); + if (err) + return err; + + *bufused_app = (uint32)bufused; + return 0; +} + +static wasi_errno_t +wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, + const char *old_path, uint32 old_path_len, wasi_fd_t new_fd, + const char *new_path, uint32 new_path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len, + new_fd, new_path, new_path_len); +} + +static wasi_errno_t +wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_filestat_t *filestat) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat); +} + +static wasi_errno_t +wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim, + wasi_fstflags_t fstflags) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim, + fstflags); +} + +static wasi_errno_t +wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_filesize_t st_size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size); +} + +static wasi_errno_t +wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_lookupflags_t flags, const char *path, + uint32 path_len, wasi_filestat_t *filestat) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len, + filestat); +} + +static wasi_errno_t +wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_lookupflags_t flags, const char *path, + uint32 path_len, wasi_timestamp_t st_atim, + wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_filestat_set_times( + curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags); +} + +static wasi_errno_t +wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path, + uint32 old_path_len, wasi_fd_t fd, const char *new_path, + uint32 new_path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len, + fd, new_path, new_path_len); +} + +static wasi_errno_t +wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, + uint32 path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len); +} + +static wasi_errno_t +wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, + const char *path, uint32 path_len) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len); +} + +#if WASM_ENABLE_THREAD_MGR != 0 +static __wasi_timestamp_t +get_timeout_for_poll_oneoff(const wasi_subscription_t *in, + uint32 nsubscriptions) +{ + __wasi_timestamp_t timeout = (__wasi_timestamp_t)-1; + uint32 i = 0; + + for (i = 0; i < nsubscriptions; ++i) { + const __wasi_subscription_t *s = &in[i]; + if (s->u.type == __WASI_EVENTTYPE_CLOCK + && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) { + timeout = min_uint64(timeout, s->u.u.clock.timeout); + } + } + return timeout; +} + +static void +update_clock_subscription_data(wasi_subscription_t *in, uint32 nsubscriptions, + const wasi_timestamp_t new_timeout) +{ + uint32 i = 0; + for (i = 0; i < nsubscriptions; ++i) { + __wasi_subscription_t *s = &in[i]; + if (s->u.type == __WASI_EVENTTYPE_CLOCK) { + s->u.u.clock.timeout = new_timeout; + } + } +} + +static wasi_errno_t +execute_interruptible_poll_oneoff( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, + size_t *nevents, wasm_exec_env_t exec_env) +{ + if (nsubscriptions == 0) { + *nevents = 0; + return __WASI_ESUCCESS; + } + + wasi_errno_t err; + __wasi_timestamp_t elapsed = 0; + bool all_outs_are_type_clock; + uint32 i; + + const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff( + in, nsubscriptions), + time_quant = 1e9; + const uint64 size_to_copy = + nsubscriptions * (uint64)sizeof(wasi_subscription_t); + __wasi_subscription_t *in_copy = NULL; + + if (size_to_copy >= UINT32_MAX + || !(in_copy = (__wasi_subscription_t *)wasm_runtime_malloc( + (uint32)size_to_copy))) { + return __WASI_ENOMEM; + } + + bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy); + + while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) { + /* update timeout for clock subscription events */ + update_clock_subscription_data( + in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed)); + err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions, + nevents); + elapsed += time_quant; + + if (err) { + wasm_runtime_free(in_copy); + return err; + } + + if (wasm_cluster_is_thread_terminated(exec_env)) { + wasm_runtime_free(in_copy); + return EINTR; + } + else if (*nevents > 0) { + all_outs_are_type_clock = true; + for (i = 0; i < *nevents; i++) { + if (out[i].type != __WASI_EVENTTYPE_CLOCK) { + all_outs_are_type_clock = false; + break; + } + } + + if (!all_outs_are_type_clock) { + wasm_runtime_free(in_copy); + return __WASI_ESUCCESS; + } + } + } + + wasm_runtime_free(in_copy); + return __WASI_ESUCCESS; +} +#endif + +static wasi_errno_t +wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, + wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + size_t nevents = 0; + wasi_errno_t err; + + if (!wasi_ctx) + return (wasi_errno_t)-1; + + if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t)) + || !validate_native_addr(out, sizeof(wasi_event_t)) + || !validate_native_addr(nevents_app, sizeof(uint32))) + return (wasi_errno_t)-1; + +#if WASM_ENABLE_THREAD_MGR == 0 + err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents); +#else + err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions, + &nevents, exec_env); +#endif + if (err) + return err; + + *nevents_app = (uint32)nevents; + return 0; +} + +static void +wasi_proc_exit(wasm_exec_env_t exec_env, wasi_exitcode_t rval) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + /* Here throwing exception is just to let wasm app exit, + the upper layer should clear the exception and return + as normal */ + wasm_runtime_set_exception(module_inst, "wasi proc exit"); + wasi_ctx->exit_code = rval; +} + +static wasi_errno_t +wasi_proc_raise(wasm_exec_env_t exec_env, wasi_signal_t sig) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + char buf[32]; + snprintf(buf, sizeof(buf), "%s%d", "wasi proc raise ", sig); + wasm_runtime_set_exception(module_inst, buf); + + return 0; +} + +static wasi_errno_t +wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len) +{ + return wasmtime_ssp_random_get(buf, buf_len); +} + +static wasi_errno_t +wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags, + wasi_fd_t *fd_new) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasi_ssp_sock_accept(curfds, fd, flags, fd_new); +} + +static wasi_errno_t +wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, + __wasi_addr_t *addr) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(addr, sizeof(__wasi_addr_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasi_ssp_sock_addr_local(curfds, fd, addr); +} + +static wasi_errno_t +wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, + __wasi_addr_t *addr) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(addr, sizeof(__wasi_addr_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasi_ssp_sock_addr_remote(curfds, fd, addr); +} + +static wasi_errno_t +wasi_sock_addr_resolve(wasm_exec_env_t exec_env, 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) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + char **ns_lookup_list = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx); + + return wasi_ssp_sock_addr_resolve(curfds, ns_lookup_list, host, service, + hints, addr_info, addr_info_size, + max_info_size); +} + +static wasi_errno_t +wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + struct addr_pool *addr_pool = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); + + return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr); +} + +static wasi_errno_t +wasi_sock_close(wasm_exec_env_t exec_env, wasi_fd_t fd) +{ + return __WASI_ENOSYS; +} + +static wasi_errno_t +wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + struct addr_pool *addr_pool = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); + + return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr); +} + +static wasi_errno_t +wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled, + int *linger_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool)) + || !validate_native_addr(linger_s, sizeof(int))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s); +} + +static wasi_errno_t +wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, + size_t *size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(size, sizeof(wasi_size_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size); +} + +static wasi_errno_t +wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint64_t *timeout_us) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(timeout_us, sizeof(uint64_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us); +} + +static wasi_errno_t +wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, + size_t *size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(size, sizeof(__wasi_size_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size); +} + +static wasi_errno_t +wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint64_t *timeout_us) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(timeout_us, sizeof(uint64_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us); +} + +static wasi_errno_t +wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t *time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(time_s, sizeof(uint32_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t *time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(time_s, sizeof(uint32_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool ipv6, bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6, + is_enabled); +} + +static wasi_errno_t +wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(ttl_s, sizeof(uint8_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint8_t *ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(ttl_s, sizeof(uint8_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasi_ssp_sock_listen(curfds, fd, backlog); +} + +static wasi_errno_t +wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd, + wasi_address_family_t af, wasi_sock_type_t socktype, + wasi_fd_t *sockfd) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd); +} + +static wasi_errno_t +wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled, + int linger_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s); +} + +static wasi_errno_t +wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size); +} + +static wasi_errno_t +wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint64_t timeout_us) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us); +} + +static wasi_errno_t +wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size); +} + +static wasi_errno_t +wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint64_t timeout_us) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us); +} + +static wasi_errno_t +wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool ipv6, bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6, + is_enabled); +} + +static wasi_errno_t +wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr, + imr_interface); +} + +static wasi_errno_t +wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr, + imr_interface); +} + +static wasi_errno_t +wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint8_t ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled); +} + +static wasi_errno_t +allocate_iovec_app_buffer(wasm_module_inst_t module_inst, + const iovec_app_t *data, uint32 data_len, + uint8 **buf_ptr, uint64 *buf_len) +{ + uint64 total_size = 0; + uint32 i; + uint8 *buf_begin = NULL; + + if (data_len == 0) { + return __WASI_EINVAL; + } + + total_size = sizeof(iovec_app_t) * (uint64)data_len; + if (total_size >= UINT32_MAX + || !validate_native_addr((void *)data, (uint32)total_size)) + return __WASI_EINVAL; + + for (total_size = 0, i = 0; i < data_len; i++, data++) { + total_size += data->buf_len; + } + + if (total_size == 0) { + return __WASI_EINVAL; + } + + if (total_size >= UINT32_MAX + || !(buf_begin = wasm_runtime_malloc((uint32)total_size))) { + return __WASI_ENOMEM; + } + + *buf_len = total_size; + *buf_ptr = buf_begin; + + return __WASI_ESUCCESS; +} + +static wasi_errno_t +copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin, + uint32 buf_size, iovec_app_t *data, uint32 data_len, + uint32 size_to_copy) +{ + uint8 *buf = buf_begin; + uint32 i; + uint32 size_to_copy_into_iovec; + + if (buf_size < size_to_copy) { + return __WASI_EINVAL; + } + + for (i = 0; i < data_len; data++, i++) { + char *native_addr; + + if (!validate_app_addr(data->buf_offset, data->buf_len)) { + return __WASI_EINVAL; + } + + if (buf >= buf_begin + buf_size + || buf + data->buf_len < buf /* integer overflow */ + || buf + data->buf_len > buf_begin + buf_size + || size_to_copy == 0) { + break; + } + + /** + * If our app buffer size is smaller than the amount to be copied, + * only copy the amount in the app buffer. Otherwise, we fill the iovec + * buffer and reduce size to copy on the next iteration + */ + size_to_copy_into_iovec = min_uint32(data->buf_len, size_to_copy); + + native_addr = (void *)addr_app_to_native(data->buf_offset); + bh_memcpy_s(native_addr, size_to_copy_into_iovec, buf, + size_to_copy_into_iovec); + buf += size_to_copy_into_iovec; + size_to_copy -= size_to_copy_into_iovec; + } + + return __WASI_ESUCCESS; +} + +static wasi_errno_t +wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock, + iovec_app_t *ri_data, uint32 ri_data_len, + wasi_riflags_t ri_flags, __wasi_addr_t *src_addr, + uint32 *ro_data_len) +{ + /** + * ri_data_len is the length of a list of iovec_app_t, which head is + * ri_data. ro_data_len is the number of bytes received + **/ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + uint64 total_size; + uint8 *buf_begin = NULL; + wasi_errno_t err; + size_t recv_bytes = 0; + + if (!wasi_ctx) { + return __WASI_EINVAL; + } + + if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32))) + return __WASI_EINVAL; + + err = allocate_iovec_app_buffer(module_inst, ri_data, ri_data_len, + &buf_begin, &total_size); + if (err != __WASI_ESUCCESS) { + goto fail; + } + + memset(buf_begin, 0, total_size); + + *ro_data_len = 0; + err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size, + ri_flags, src_addr, &recv_bytes); + if (err != __WASI_ESUCCESS) { + goto fail; + } + *ro_data_len = (uint32)recv_bytes; + + err = copy_buffer_to_iovec_app(module_inst, buf_begin, (uint32)total_size, + ri_data, ri_data_len, (uint32)recv_bytes); + +fail: + if (buf_begin) { + wasm_runtime_free(buf_begin); + } + return err; +} + +static wasi_errno_t +wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data, + uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len, + wasi_roflags_t *ro_flags) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + __wasi_addr_t src_addr; + wasi_errno_t error; + + if (!validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))) + return __WASI_EINVAL; + + error = wasi_sock_recv_from(exec_env, sock, ri_data, ri_data_len, ri_flags, + &src_addr, ro_data_len); + *ro_flags = ri_flags; + + return error; +} + +static wasi_errno_t +convert_iovec_app_to_buffer(wasm_module_inst_t module_inst, + const iovec_app_t *si_data, uint32 si_data_len, + uint8 **buf_ptr, uint64 *buf_len) +{ + uint32 i; + const iovec_app_t *si_data_orig = si_data; + uint8 *buf = NULL; + wasi_errno_t error; + + error = allocate_iovec_app_buffer(module_inst, si_data, si_data_len, + buf_ptr, buf_len); + if (error != __WASI_ESUCCESS) { + return error; + } + + buf = *buf_ptr; + si_data = si_data_orig; + for (i = 0; i < si_data_len; i++, si_data++) { + char *native_addr; + + if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) { + wasm_runtime_free(*buf_ptr); + return __WASI_EINVAL; + } + + native_addr = (char *)addr_app_to_native(si_data->buf_offset); + bh_memcpy_s(buf, si_data->buf_len, native_addr, si_data->buf_len); + buf += si_data->buf_len; + } + + return __WASI_ESUCCESS; +} + +static wasi_errno_t +wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, + const iovec_app_t *si_data, uint32 si_data_len, + wasi_siflags_t si_flags, uint32 *so_data_len) +{ + /** + * si_data_len is the length of a list of iovec_app_t, which head is + * si_data. so_data_len is the number of bytes sent + **/ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + uint64 buf_size = 0; + uint8 *buf = NULL; + wasi_errno_t err; + size_t send_bytes = 0; + + if (!wasi_ctx) { + return __WASI_EINVAL; + } + + if (!validate_native_addr(so_data_len, sizeof(uint32))) + return __WASI_EINVAL; + + err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf, + &buf_size); + if (err != __WASI_ESUCCESS) + return err; + + *so_data_len = 0; + err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes); + *so_data_len = (uint32)send_bytes; + + wasm_runtime_free(buf); + + return err; +} + +static wasi_errno_t +wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock, + const iovec_app_t *si_data, uint32 si_data_len, + wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, + uint32 *so_data_len) +{ + /** + * si_data_len is the length of a list of iovec_app_t, which head is + * si_data. so_data_len is the number of bytes sent + **/ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + uint64 buf_size = 0; + uint8 *buf = NULL; + wasi_errno_t err; + size_t send_bytes = 0; + struct addr_pool *addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); + + if (!wasi_ctx) { + return __WASI_EINVAL; + } + + if (!validate_native_addr(so_data_len, sizeof(uint32))) + return __WASI_EINVAL; + + err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf, + &buf_size); + if (err != __WASI_ESUCCESS) + return err; + + *so_data_len = 0; + err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size, + si_flags, dest_addr, &send_bytes); + *so_data_len = (uint32)send_bytes; + + wasm_runtime_free(buf); + + return err; +} + +static wasi_errno_t +wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + if (!wasi_ctx) + return __WASI_EINVAL; + + return wasmtime_ssp_sock_shutdown(curfds, sock); +} + +static wasi_errno_t +wasi_sched_yield(wasm_exec_env_t exec_env) +{ + return wasmtime_ssp_sched_yield(); +} + +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ + { #func_name, wasi_##func_name, signature, NULL } +/* clang-format on */ + +static NativeSymbol native_symbols_libc_wasi[] = { + REG_NATIVE_FUNC(args_get, "(**)i"), + REG_NATIVE_FUNC(args_sizes_get, "(**)i"), + REG_NATIVE_FUNC(clock_res_get, "(i*)i"), + REG_NATIVE_FUNC(clock_time_get, "(iI*)i"), + REG_NATIVE_FUNC(environ_get, "(**)i"), + REG_NATIVE_FUNC(environ_sizes_get, "(**)i"), + REG_NATIVE_FUNC(fd_prestat_get, "(i*)i"), + REG_NATIVE_FUNC(fd_prestat_dir_name, "(i*~)i"), + REG_NATIVE_FUNC(fd_close, "(i)i"), + REG_NATIVE_FUNC(fd_datasync, "(i)i"), + REG_NATIVE_FUNC(fd_pread, "(i*iI*)i"), + REG_NATIVE_FUNC(fd_pwrite, "(i*iI*)i"), + REG_NATIVE_FUNC(fd_read, "(i*i*)i"), + REG_NATIVE_FUNC(fd_renumber, "(ii)i"), + REG_NATIVE_FUNC(fd_seek, "(iIi*)i"), + REG_NATIVE_FUNC(fd_tell, "(i*)i"), + REG_NATIVE_FUNC(fd_fdstat_get, "(i*)i"), + REG_NATIVE_FUNC(fd_fdstat_set_flags, "(ii)i"), + REG_NATIVE_FUNC(fd_fdstat_set_rights, "(iII)i"), + REG_NATIVE_FUNC(fd_sync, "(i)i"), + REG_NATIVE_FUNC(fd_write, "(i*i*)i"), + REG_NATIVE_FUNC(fd_advise, "(iIIi)i"), + REG_NATIVE_FUNC(fd_allocate, "(iII)i"), + REG_NATIVE_FUNC(path_create_directory, "(i*~)i"), + REG_NATIVE_FUNC(path_link, "(ii*~i*~)i"), + REG_NATIVE_FUNC(path_open, "(ii*~iIIi*)i"), + REG_NATIVE_FUNC(fd_readdir, "(i*~I*)i"), + REG_NATIVE_FUNC(path_readlink, "(i*~*~*)i"), + REG_NATIVE_FUNC(path_rename, "(i*~i*~)i"), + REG_NATIVE_FUNC(fd_filestat_get, "(i*)i"), + REG_NATIVE_FUNC(fd_filestat_set_times, "(iIIi)i"), + REG_NATIVE_FUNC(fd_filestat_set_size, "(iI)i"), + REG_NATIVE_FUNC(path_filestat_get, "(ii*~*)i"), + REG_NATIVE_FUNC(path_filestat_set_times, "(ii*~IIi)i"), + REG_NATIVE_FUNC(path_symlink, "(*~i*~)i"), + REG_NATIVE_FUNC(path_unlink_file, "(i*~)i"), + REG_NATIVE_FUNC(path_remove_directory, "(i*~)i"), + REG_NATIVE_FUNC(poll_oneoff, "(**i*)i"), + REG_NATIVE_FUNC(proc_exit, "(i)"), + REG_NATIVE_FUNC(proc_raise, "(i)i"), + REG_NATIVE_FUNC(random_get, "(*~)i"), + REG_NATIVE_FUNC(sock_accept, "(ii*)i"), + REG_NATIVE_FUNC(sock_addr_local, "(i*)i"), + REG_NATIVE_FUNC(sock_addr_remote, "(i*)i"), + REG_NATIVE_FUNC(sock_addr_resolve, "($$**i*)i"), + REG_NATIVE_FUNC(sock_bind, "(i*)i"), + REG_NATIVE_FUNC(sock_close, "(i)i"), + REG_NATIVE_FUNC(sock_connect, "(i*)i"), + REG_NATIVE_FUNC(sock_get_broadcast, "(i*)i"), + REG_NATIVE_FUNC(sock_get_keep_alive, "(i*)i"), + REG_NATIVE_FUNC(sock_get_linger, "(i**)i"), + REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"), + REG_NATIVE_FUNC(sock_get_recv_timeout, "(i*)i"), + REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"), + REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"), + REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"), + REG_NATIVE_FUNC(sock_get_send_timeout, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_fastopen_connect, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_keep_idle, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_keep_intvl, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_no_delay, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_quick_ack, "(i*)i"), + REG_NATIVE_FUNC(sock_get_ip_multicast_loop, "(ii*)i"), + REG_NATIVE_FUNC(sock_get_ip_multicast_ttl, "(i*)i"), + REG_NATIVE_FUNC(sock_get_ip_ttl, "(i*)i"), + REG_NATIVE_FUNC(sock_get_ipv6_only, "(i*)i"), + REG_NATIVE_FUNC(sock_listen, "(ii)i"), + REG_NATIVE_FUNC(sock_open, "(iii*)i"), + REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"), + REG_NATIVE_FUNC(sock_recv_from, "(i*ii**)i"), + REG_NATIVE_FUNC(sock_send, "(i*ii*)i"), + REG_NATIVE_FUNC(sock_send_to, "(i*ii**)i"), + REG_NATIVE_FUNC(sock_set_broadcast, "(ii)i"), + REG_NATIVE_FUNC(sock_set_keep_alive, "(ii)i"), + REG_NATIVE_FUNC(sock_set_linger, "(iii)i"), + REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"), + REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"), + REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"), + REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"), + REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"), + REG_NATIVE_FUNC(sock_set_send_timeout, "(iI)i"), + REG_NATIVE_FUNC(sock_set_tcp_fastopen_connect, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_keep_idle, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_keep_intvl, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_no_delay, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_quick_ack, "(ii)i"), + REG_NATIVE_FUNC(sock_set_ip_multicast_loop, "(iii)i"), + REG_NATIVE_FUNC(sock_set_ip_multicast_ttl, "(ii)i"), + REG_NATIVE_FUNC(sock_set_ip_add_membership, "(i*i)i"), + REG_NATIVE_FUNC(sock_set_ip_drop_membership, "(i*i)i"), + REG_NATIVE_FUNC(sock_set_ip_ttl, "(ii)i"), + REG_NATIVE_FUNC(sock_set_ipv6_only, "(ii)i"), + REG_NATIVE_FUNC(sock_shutdown, "(ii)i"), + REG_NATIVE_FUNC(sched_yield, "()i"), +}; + +uint32 +get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis) +{ + *p_libc_wasi_apis = native_symbols_libc_wasi; + return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol); +} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h new file mode 100644 index 000000000..be509576b --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _LIBC_WASI_WRAPPER_H +#define _LIBC_WASI_WRAPPER_H + +#include "wasmtime_ssp.h" +#include "posix.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __wasi_address_family_t wasi_address_family_t; +typedef __wasi_addr_t wasi_addr_t; +typedef __wasi_advice_t wasi_advice_t; +typedef __wasi_ciovec_t wasi_ciovec_t; +typedef __wasi_clockid_t wasi_clockid_t; +typedef __wasi_dircookie_t wasi_dircookie_t; +typedef __wasi_errno_t wasi_errno_t; +typedef __wasi_event_t wasi_event_t; +typedef __wasi_exitcode_t wasi_exitcode_t; +typedef __wasi_fdflags_t wasi_fdflags_t; +typedef __wasi_fdstat_t wasi_fdstat_t; +typedef __wasi_fd_t wasi_fd_t; +typedef __wasi_filedelta_t wasi_filedelta_t; +typedef __wasi_filesize_t wasi_filesize_t; +typedef __wasi_filestat_t wasi_filestat_t; +typedef __wasi_filetype_t wasi_filetype_t; +typedef __wasi_fstflags_t wasi_fstflags_t; +typedef __wasi_iovec_t wasi_iovec_t; +typedef __wasi_ip_port_t wasi_ip_port_t; +typedef __wasi_lookupflags_t wasi_lookupflags_t; +typedef __wasi_oflags_t wasi_oflags_t; +typedef __wasi_preopentype_t wasi_preopentype_t; +typedef __wasi_prestat_t wasi_prestat_t; +typedef __wasi_riflags_t wasi_riflags_t; +typedef __wasi_rights_t wasi_rights_t; +typedef __wasi_roflags_t wasi_roflags_t; +typedef __wasi_sdflags_t wasi_sdflags_t; +typedef __wasi_siflags_t wasi_siflags_t; +typedef __wasi_signal_t wasi_signal_t; +typedef __wasi_size_t wasi_size_t; +typedef __wasi_sock_type_t wasi_sock_type_t; +typedef __wasi_subscription_t wasi_subscription_t; +typedef __wasi_timestamp_t wasi_timestamp_t; +typedef __wasi_whence_t wasi_whence_t; + +#ifdef __cplusplus +} +#endif + +#endif /* end of _LIBC_WASI_WRAPPER_H */
\ No newline at end of file diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE new file mode 100644 index 000000000..83386f80a --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE @@ -0,0 +1,7 @@ +Please see the LICENSE file in each top-level directory for the terms applicable to that directory and its relative sub-directories. + +The relevant directories and licenses are: + +src/ - BSD-2-Clause; see src/LICENSE for details +include/ - CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +polyfill/clang/ - MIT; see the header of polyfill/clang/stdatomic.h for details diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE new file mode 100644 index 000000000..0e259d42c --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h new file mode 100644 index 000000000..feadf2f95 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -0,0 +1,1508 @@ +/* + * Part of the Wasmtime Project, under the Apache License v2.0 with + * 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. + */ + +/** + * The defitions of type, macro and structure 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 WASMTIME_SSP_H +#define WASMTIME_SSP_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.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) + +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; + +typedef uint64_t __wasi_linkcount_t __attribute__((aligned(8))); + +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; +// 0 is reserved; POSIX has special semantics for kill(pid, 0). +#define __WASI_SIGHUP (1) +#define __WASI_SIGINT (2) +#define __WASI_SIGQUIT (3) +#define __WASI_SIGILL (4) +#define __WASI_SIGTRAP (5) +#define __WASI_SIGABRT (6) +#define __WASI_SIGBUS (7) +#define __WASI_SIGFPE (8) +#define __WASI_SIGKILL (9) +#define __WASI_SIGUSR1 (10) +#define __WASI_SIGSEGV (11) +#define __WASI_SIGUSR2 (12) +#define __WASI_SIGPIPE (13) +#define __WASI_SIGALRM (14) +#define __WASI_SIGTERM (15) +#define __WASI_SIGCHLD (16) +#define __WASI_SIGCONT (17) +#define __WASI_SIGSTOP (18) +#define __WASI_SIGTSTP (19) +#define __WASI_SIGTTIN (20) +#define __WASI_SIGTTOU (21) +#define __WASI_SIGURG (22) +#define __WASI_SIGXCPU (23) +#define __WASI_SIGXFSZ (24) +#define __WASI_SIGVTALRM (25) +#define __WASI_SIGPROF (26) +#define __WASI_SIGWINCH (27) +#define __WASI_SIGPOLL (28) +#define __WASI_SIGPWR (29) +#define __WASI_SIGSYS (30) + +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 __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))); +_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 __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 __attribute__((aligned(8))); +_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 __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))); +_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 __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 __attribute__((aligned(8))); +_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 __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 __attribute__((aligned(8))); + +_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 __wasi_subscription_u_t { + __wasi_eventtype_t type; + __wasi_subscription_u_u_t u; +} __wasi_subscription_u_t __attribute__((aligned(8))); + +_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 { + 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 } __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) +#else +#define WASMTIME_SSP_SYSCALL_NAME(name) +#endif + +__wasi_errno_t wasmtime_ssp_args_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + char **argv, + char *argv_buf +) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_args_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + size_t *argc, + size_t *argv_buf_size +) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__)); + +__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__)); + +__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__)); + +__wasi_errno_t wasmtime_ssp_environ_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + char **environ, + char *environ_buf +) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_environ_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + size_t *environ_count, + size_t *environ_buf_size +) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_prestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, + __wasi_prestat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, + char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_close( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd +) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__)); + +__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__)); + +__wasi_errno_t wasmtime_ssp_fd_pread( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_pwrite( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_read( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_iovec_t *iovs, + size_t iovs_len, + size_t *nread +) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_renumber( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __wasi_fd_t from, + __wasi_fd_t to +) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_seek( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filedelta_t offset, + __wasi_whence_t whence, + __wasi_filesize_t *newoffset +) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_tell( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t *newoffset +) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_fdstat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_fdstat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_fdflags_t flags +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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__)); + +__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__)); + +__wasi_errno_t wasmtime_ssp_fd_write( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_ciovec_t *iovs, + size_t iovs_len, + size_t *nwritten +) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_advise( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len, + __wasi_advice_t advice +) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_allocate( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len +) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_create_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_link( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_open( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_readdir( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + void *buf, + size_t buf_len, + __wasi_dircookie_t cookie, + size_t *bufused +) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_readlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_rename( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filestat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_filestat_set_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t st_size +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_symlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + 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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_unlink_file( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_remove_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_poll_oneoff( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const __wasi_subscription_t *in, + __wasi_event_t *out, + size_t nsubscriptions, + size_t *nevents +) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__)); + +#if 0 +/** + * We throw exception in libc-wasi wrapper function wasi_proc_exit() + * but not call this function. + */ +_Noreturn void wasmtime_ssp_proc_exit( + __wasi_exitcode_t rval +) WASMTIME_SSP_SYSCALL_NAME(proc_exit); +#endif + +__wasi_errno_t wasmtime_ssp_proc_raise( + __wasi_signal_t sig +) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_random_get( + void *buf, + size_t buf_len +) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_accept( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_addr_local( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_addr_remote( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_open( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, + __wasi_fd_t *sockfd +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_bind( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct addr_pool *addr_pool, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_addr_resolve( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, char **ns_lookup_list, +#endif + 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__)); + +__wasi_errno_t +wasi_ssp_sock_connect( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct addr_pool *addr_pool, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_get_recv_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_size_t *size +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_get_reuse_addr( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, uint8_t *reuse +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_get_reuse_port( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, uint8_t *reuse +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_get_send_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_size_t *size +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_set_recv_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_size_t size +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_set_reuse_addr( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, uint8_t reuse +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_set_reuse_port( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, uint8_t reuse +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_set_send_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_size_t size +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t +wasi_ssp_sock_listen( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_size_t backlog +) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_recv( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + void *buf, + size_t buf_len, + size_t *recv_len +) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_recv_from( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_send( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + const void *buf, + size_t buf_len, + size_t *sent_len +) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_send_to( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct addr_pool *addr_pool, +#endif + __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) __attribute__((__warn_unused_result__)); + +__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__)); + +__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint64_t timeout_us +) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint64_t *timeout_us +) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_send_timeout( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint64_t timeout_us +) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_send_timeout( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint64_t *timeout_us +) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_send_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + size_t bufsiz +) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_send_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + size_t *bufsiz +) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + size_t bufsiz +) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + size_t *bufsiz +) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__)); + + +__wasi_errno_t wasmtime_ssp_sock_set_keep_alive( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_keep_alive( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_reuse_addr( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_reuse_addr( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_reuse_port( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_reuse_port( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_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_set_linger) __attribute__((__warn_unused_result__)); + +__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__)); + +__wasi_errno_t wasmtime_ssp_sock_set_broadcast( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_broadcast( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint32_t time_s +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint32_t *time_s +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint32_t time_s +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint32_t *time_s +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool ipv6, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool ipv6, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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__)); + +__wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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__)); + +__wasi_errno_t wasmtime_ssp_sock_set_ip_ttl( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint8_t ttl_s +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_ip_ttl( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint8_t *ttl_s +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint8_t ttl_s +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + uint8_t *ttl_s +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_set_ipv6_only( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_get_ipv6_only( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + bool *is_enabled +) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sched_yield(void) + WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__)); + +#ifdef __cplusplus +} +#endif + +#undef WASMTIME_SSP_SYSCALL_NAME + +/* clang-format on */ + +#endif /* end of WASMTIME_SSP_H */ diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE new file mode 100644 index 000000000..04c6f48a2 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE @@ -0,0 +1,24 @@ +All code is distributed under the following license: + + Copyright (c) 2015 Nuxi, https://nuxi.nl/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md new file mode 100644 index 000000000..b4d55d803 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md @@ -0,0 +1,14 @@ +This directory consists of selected files copied from the [src/libemulator] +directory in the [cloudabi-utils] repository, with minor modifications, +along with the accompanying LICENSE file from that repository. + +The modifications are marked with `WASMTIME_*` preprocessor macros. + +The files were copied at git revision +223dadc53248552db43e012c67ed08cf416a2b12 +which is dated +Tue Jun 25 17:22:07 2019 -0700 +. + +[libemulator]: https://github.com/NuxiNL/cloudabi-utils/tree/223dadc53248552db43e012c67ed08cf416a2b12/src/libemulator +[cloudabi-utils]: https://github.com/NuxiNL/cloudabi-utils diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h new file mode 100644 index 000000000..70000ae0b --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#if !defined(__GNUC_PREREQ) && (defined(__GNUC__) || defined(__GNUG__)) \ + && !defined(__clang__) && defined(__GNUC_MINOR__) +/* Depending on the platform the macro is defined in sys/features.h or + features.h Given the macro is simple, we re-implement it here instead of + dealing with two different paths. + */ +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h new file mode 100644 index 000000000..40b064b81 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h @@ -0,0 +1,265 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef LOCKING_H +#define LOCKING_H + +#include "ssp_config.h" + +#ifndef __has_extension +#define __has_extension(x) 0 +#endif + +#if __has_extension(c_thread_safety_attributes) +#define LOCK_ANNOTATE(x) __attribute__((x)) +#else +#define LOCK_ANNOTATE(x) +#endif + +/* Lock annotation macros. */ + +#define LOCKABLE LOCK_ANNOTATE(lockable) + +#define LOCKS_EXCLUSIVE(...) LOCK_ANNOTATE(exclusive_lock_function(__VA_ARGS__)) +#define LOCKS_SHARED(...) LOCK_ANNOTATE(shared_lock_function(__VA_ARGS__)) + +#define TRYLOCKS_EXCLUSIVE(...) \ + LOCK_ANNOTATE(exclusive_trylock_function(__VA_ARGS__)) +#define TRYLOCKS_SHARED(...) LOCK_ANNOTATE(shared_trylock_function(__VA_ARGS__)) + +#define UNLOCKS(...) LOCK_ANNOTATE(unlock_function(__VA_ARGS__)) + +#define REQUIRES_EXCLUSIVE(...) \ + LOCK_ANNOTATE(exclusive_locks_required(__VA_ARGS__)) +#define REQUIRES_SHARED(...) LOCK_ANNOTATE(shared_locks_required(__VA_ARGS__)) +#define REQUIRES_UNLOCKED(...) LOCK_ANNOTATE(locks_excluded(__VA_ARGS__)) + +#define NO_LOCK_ANALYSIS LOCK_ANNOTATE(no_thread_safety_analysis) + +/* Mutex that uses the lock annotations. */ + +struct LOCKABLE mutex { + pthread_mutex_t object; +}; + +/* clang-format off */ +#define MUTEX_INITIALIZER \ + { PTHREAD_MUTEX_INITIALIZER } +/* clang-format on */ + +static inline bool +mutex_init(struct mutex *lock) REQUIRES_UNLOCKED(*lock) +{ + return pthread_mutex_init(&lock->object, NULL) == 0 ? true : false; +} + +static inline void +mutex_destroy(struct mutex *lock) REQUIRES_UNLOCKED(*lock) +{ + pthread_mutex_destroy(&lock->object); +} + +static inline void +mutex_lock(struct mutex *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS +{ + pthread_mutex_lock(&lock->object); +} + +static inline void +mutex_unlock(struct mutex *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS +{ + pthread_mutex_unlock(&lock->object); +} + +/* Read-write lock that uses the lock annotations. */ + +struct LOCKABLE rwlock { + pthread_rwlock_t object; +}; + +static inline bool +rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) +{ + return pthread_rwlock_init(&lock->object, NULL) == 0 ? true : false; +} + +static inline void +rwlock_rdlock(struct rwlock *lock) LOCKS_SHARED(*lock) NO_LOCK_ANALYSIS +{ + pthread_rwlock_rdlock(&lock->object); +} + +static inline void +rwlock_wrlock(struct rwlock *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS +{ + pthread_rwlock_wrlock(&lock->object); +} + +static inline void +rwlock_unlock(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS +{ + pthread_rwlock_unlock(&lock->object); +} + +static inline void +rwlock_destroy(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS +{ + pthread_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 + clockid_t clock; +#endif +}; + +static inline bool +cond_init_monotonic(struct cond *cond) +{ + bool ret = false; +#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK + pthread_condattr_t attr; + + if (pthread_condattr_init(&attr) != 0) + return false; + + if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) + goto fail; + + if (pthread_cond_init(&cond->object, &attr) != 0) + goto fail; + + ret = true; +fail: + pthread_condattr_destroy(&attr); +#else + if (pthread_cond_init(&cond->object, NULL) != 0) + return false; + ret = true; +#endif + +#if !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) + return false; +#if !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); +} + +static inline void +cond_signal(struct cond *cond) +{ + pthread_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 +{ + int ret; + struct timespec ts = { + .tv_sec = (time_t)(timeout / 1000000000), + .tv_nsec = (long)(timeout % 1000000000), + }; + + if (abstime) { +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK + /** + * No native support for sleeping on monotonic clocks. Convert the + * timeout to a relative value and then to an absolute value for the + * realtime clock. + */ + if (cond->clock != CLOCK_REALTIME) { + struct timespec ts_monotonic; + struct timespec ts_realtime; + + clock_gettime(cond->clock, &ts_monotonic); + ts.tv_sec -= ts_monotonic.tv_sec; + ts.tv_nsec -= ts_monotonic.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_nsec += 1000000000; + --ts.tv_sec; + } + + clock_gettime(CLOCK_REALTIME, &ts_realtime); + ts.tv_sec += ts_realtime.tv_sec; + ts.tv_nsec += ts_realtime.tv_nsec; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ++ts.tv_sec; + } + } +#endif + } + else { +#if CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + /* Implementation supports relative timeouts. */ + ret = pthread_cond_timedwait_relative_np(&cond->object, &lock->object, + &ts); + bh_assert((ret == 0 || ret == ETIMEDOUT) + && "pthread_cond_timedwait_relative_np() failed"); + return ret == ETIMEDOUT; +#else + /* Convert to absolute timeout. */ + struct timespec ts_now; +#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK + clock_gettime(cond->clock, &ts_now); +#else + clock_gettime(CLOCK_REALTIME, &ts_now); +#endif + ts.tv_sec += ts_now.tv_sec; + ts.tv_nsec += ts_now.tv_nsec; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ++ts.tv_sec; + } +#endif + } + + ret = pthread_cond_timedwait(&cond->object, &lock->object, &ts); + bh_assert((ret == 0 || ret == ETIMEDOUT) + && "pthread_cond_timedwait() failed"); + return ret == ETIMEDOUT; +} +#endif + +static inline void +cond_wait(struct cond *cond, struct mutex *lock) + REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS +{ + pthread_cond_wait(&cond->object, &lock->object); +} + +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c new file mode 100644 index 000000000..61e841836 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -0,0 +1,4072 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/ + +#include "ssp_config.h" +#include "bh_platform.h" +#include "wasmtime_ssp.h" +#include "locking.h" +#include "posix.h" +#include "random.h" +#include "refcount.h" +#include "rights.h" +#include "str.h" + +#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) == + offsetof(__wasi_iovec_t, buf), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_base) == + sizeof(((__wasi_iovec_t *)0)->buf), + "Size mismatch"); +static_assert(offsetof(struct iovec, iov_len) == + offsetof(__wasi_iovec_t, buf_len), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_len) == + sizeof(((__wasi_iovec_t *)0)->buf_len), + "Size mismatch"); +static_assert(sizeof(struct iovec) == sizeof(__wasi_iovec_t), + "Size mismatch"); + +// struct iovec must have the same layout as __wasi_ciovec_t. +static_assert(offsetof(struct iovec, iov_base) == + offsetof(__wasi_ciovec_t, buf), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_base) == + sizeof(((__wasi_ciovec_t *)0)->buf), + "Size mismatch"); +static_assert(offsetof(struct iovec, iov_len) == + offsetof(__wasi_ciovec_t, buf_len), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_len) == + sizeof(((__wasi_ciovec_t *)0)->buf_len), + "Size mismatch"); +static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), + "Size mismatch"); +#endif + +#if defined(WASMTIME_SSP_STATIC_CURFDS) +static __thread struct fd_table *curfds; +static __thread struct fd_prestats *prestats; +static __thread struct argv_environ_values *argv_environ; +static __thread struct addr_pool *addr_pool; +#endif + +// Converts a POSIX error code to a CloudABI error code. +static __wasi_errno_t +convert_errno(int error) +{ + static const __wasi_errno_t errors[] = { +#define X(v) [v] = __WASI_##v + 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), + X(EDQUOT), + 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), + X(EMULTIHOP), + 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), + X(ESTALE), + X(ETIMEDOUT), + X(ETXTBSY), + X(EXDEV), +#undef X +#if EOPNOTSUPP != ENOTSUP + [EOPNOTSUPP] = __WASI_ENOTSUP, +#endif +#if EWOULDBLOCK != EAGAIN + [EWOULDBLOCK] = __WASI_EAGAIN, +#endif + }; + if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0]) + || errors[error] == 0) + return __WASI_ENOSYS; + return errors[error]; +} + +static bool +ns_lookup_list_search(char **list, const char *host) +{ + size_t host_len = strlen(host), suffix_len; + + while (*list) { + if (*list[0] == '*') { + suffix_len = strlen(*list) - 1; + if (suffix_len <= host_len + && strncmp(host + host_len - suffix_len, *list + 1, suffix_len) + == 0) { + return true; + } + } + else { + if (strcmp(*list, host) == 0) { + return true; + } + } + list++; + } + + 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. +static bool +convert_clockid(__wasi_clockid_t in, clockid_t *out) +{ + switch (in) { + case __WASI_CLOCK_MONOTONIC: + *out = CLOCK_MONOTONIC; + return true; +#if defined(CLOCK_PROCESS_CPUTIME_ID) + case __WASI_CLOCK_PROCESS_CPUTIME_ID: + *out = CLOCK_PROCESS_CPUTIME_ID; + return true; +#endif + case __WASI_CLOCK_REALTIME: + *out = CLOCK_REALTIME; + return true; +#if defined(CLOCK_THREAD_CPUTIME_ID) + case __WASI_CLOCK_THREAD_CPUTIME_ID: + *out = CLOCK_THREAD_CPUTIME_ID; + return true; +#endif + default: + return false; + } +} + +static void +wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr, + bh_sockaddr_t *sockaddr) +{ + if (wasi_addr->kind == IPv4) { + sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24) + | (wasi_addr->addr.ip4.addr.n1 << 16) + | (wasi_addr->addr.ip4.addr.n2 << 8) + | wasi_addr->addr.ip4.addr.n3; + sockaddr->is_ipv4 = true; + sockaddr->port = wasi_addr->addr.ip4.port; + } + else { + sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0; + sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1; + sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2; + sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3; + sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0; + sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1; + sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2; + sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3; + sockaddr->is_ipv4 = false; + sockaddr->port = wasi_addr->addr.ip6.port; + } +} + +// Converts an IPv6 binary address object to WASI address object. +static void +bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr, + __wasi_addr_t *wasi_addr) +{ + if (sockaddr->is_ipv4) { + wasi_addr->kind = IPv4; + wasi_addr->addr.ip4.port = sockaddr->port; + wasi_addr->addr.ip4.addr.n0 = + (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24; + wasi_addr->addr.ip4.addr.n1 = + (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16; + wasi_addr->addr.ip4.addr.n2 = + (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8; + wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF); + } + else { + wasi_addr->kind = IPv6; + wasi_addr->addr.ip6.port = sockaddr->port; + wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0]; + wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1]; + wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2]; + wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3]; + wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4]; + wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5]; + wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6]; + wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7]; + } +} + +static void +wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr, + bh_ip_addr_buffer_t *out) +{ + if (addr->kind == IPv4) { + out->ipv4 = htonl((addr->addr.ip4.n0 << 24) | (addr->addr.ip4.n1 << 16) + | (addr->addr.ip4.n2 << 8) | addr->addr.ip4.n3); + } + else { + out->ipv6[0] = htons(addr->addr.ip6.n0); + out->ipv6[1] = htons(addr->addr.ip6.n1); + out->ipv6[2] = htons(addr->addr.ip6.n2); + out->ipv6[3] = htons(addr->addr.ip6.n3); + out->ipv6[4] = htons(addr->addr.ip6.h0); + out->ipv6[5] = htons(addr->addr.ip6.h1); + out->ipv6[6] = htons(addr->addr.ip6.h2); + out->ipv6[7] = htons(addr->addr.ip6.h3); + } +} + +__wasi_errno_t +wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, + __wasi_timestamp_t *resolution) +{ + clockid_t nclock_id; + if (!convert_clockid(clock_id, &nclock_id)) + return __WASI_EINVAL; + struct timespec ts; + if (clock_getres(nclock_id, &ts) < 0) + return convert_errno(errno); + *resolution = convert_timespec(&ts); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, + __wasi_timestamp_t precision, + __wasi_timestamp_t *time) +{ + clockid_t nclock_id; + if (!convert_clockid(clock_id, &nclock_id)) + return __WASI_EINVAL; + struct timespec ts; + if (clock_gettime(nclock_id, &ts) < 0) + return convert_errno(errno); + *time = convert_timespec(&ts); + return 0; +} + +struct fd_prestat { + const char *dir; +}; + +bool +fd_prestats_init(struct fd_prestats *pt) +{ + if (!rwlock_init(&pt->lock)) + return false; + pt->prestats = NULL; + pt->size = 0; + pt->used = 0; +#if defined(WASMTIME_SSP_STATIC_CURFDS) + prestats = pt; +#endif + return true; +} + +// Grows the preopened resource table to a required lower bound and a +// minimum number of free preopened resource table entries. +static bool +fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) + REQUIRES_EXCLUSIVE(pt->lock) +{ + if (pt->size <= min || pt->size < (pt->used + incr) * 2) { + // Keep on doubling the table size until we've met our constraints. + size_t size = pt->size == 0 ? 1 : pt->size; + while (size <= min || size < (pt->used + incr) * 2) + size *= 2; + + // Grow the file descriptor table's allocation. + struct fd_prestat *prestats = + wasm_runtime_malloc((uint32)(sizeof(*prestats) * size)); + if (prestats == NULL) + return false; + + if (pt->prestats && pt->size > 0) { + bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size), + pt->prestats, (uint32)(sizeof(*prestats) * pt->size)); + } + + if (pt->prestats) + wasm_runtime_free(pt->prestats); + + // Mark all new file descriptors as unused. + for (size_t i = pt->size; i < size; ++i) + prestats[i].dir = NULL; + pt->prestats = prestats; + pt->size = size; + } + return true; +} + +// Inserts a preopened resource record into the preopened resource table. +bool +fd_prestats_insert(struct fd_prestats *pt, const char *dir, __wasi_fd_t fd) +{ + // Grow the preopened resource table if needed. + rwlock_wrlock(&pt->lock); + if (!fd_prestats_grow(pt, fd, 1)) { + rwlock_unlock(&pt->lock); + return false; + } + + pt->prestats[fd].dir = bh_strdup(dir); + rwlock_unlock(&pt->lock); + + if (pt->prestats[fd].dir == NULL) + return false; + + return true; +} + +// Looks up a preopened resource table entry by number. +static __wasi_errno_t +fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd, + struct fd_prestat **ret) REQUIRES_SHARED(pt->lock) +{ + // Test for file descriptor existence. + if (fd >= pt->size) + return __WASI_EBADF; + struct fd_prestat *prestat = &pt->prestats[fd]; + if (prestat->dir == NULL) + return __WASI_EBADF; + + *ret = prestat; + return 0; +} + +struct fd_object { + struct refcount refcount; + __wasi_filetype_t type; + int number; + + union { + // Data associated with directory file descriptors. + struct { + struct mutex lock; // Lock to protect members below. + DIR *handle; // Directory handle. + __wasi_dircookie_t offset; // Offset of the directory. + } directory; + }; +}; + +struct fd_entry { + struct fd_object *object; + __wasi_rights_t rights_base; + __wasi_rights_t rights_inheriting; +}; + +bool +fd_table_init(struct fd_table *ft) +{ + if (!rwlock_init(&ft->lock)) + return false; + ft->entries = NULL; + ft->size = 0; + ft->used = 0; +#if defined(WASMTIME_SSP_STATIC_CURFDS) + curfds = ft; +#endif + return true; +} + +// Looks up a file descriptor table entry by number and required rights. +static __wasi_errno_t +fd_table_get_entry(struct fd_table *ft, __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, struct fd_entry **ret) + REQUIRES_SHARED(ft->lock) +{ + // Test for file descriptor existence. + if (fd >= ft->size) + return __WASI_EBADF; + struct fd_entry *fe = &ft->entries[fd]; + if (fe->object == NULL) + return __WASI_EBADF; + + // Validate rights. + if ((~fe->rights_base & rights_base) != 0 + || (~fe->rights_inheriting & rights_inheriting) != 0) + return __WASI_ENOTCAPABLE; + *ret = fe; + return 0; +} + +// Grows the file descriptor table to a required lower bound and a +// minimum number of free file descriptor table entries. +static bool +fd_table_grow(struct fd_table *ft, size_t min, size_t incr) + REQUIRES_EXCLUSIVE(ft->lock) +{ + if (ft->size <= min || ft->size < (ft->used + incr) * 2) { + // Keep on doubling the table size until we've met our constraints. + size_t size = ft->size == 0 ? 1 : ft->size; + while (size <= min || size < (ft->used + incr) * 2) + size *= 2; + + // Grow the file descriptor table's allocation. + struct fd_entry *entries = + wasm_runtime_malloc((uint32)(sizeof(*entries) * size)); + if (entries == NULL) + return false; + + if (ft->entries && ft->size > 0) { + bh_memcpy_s(entries, (uint32)(sizeof(*entries) * size), ft->entries, + (uint32)(sizeof(*entries) * ft->size)); + } + + if (ft->entries) + wasm_runtime_free(ft->entries); + + // Mark all new file descriptors as unused. + for (size_t i = ft->size; i < size; ++i) + entries[i].object = NULL; + ft->entries = entries; + ft->size = size; + } + return true; +} + +// Allocates a new file descriptor object. +static __wasi_errno_t +fd_object_new(__wasi_filetype_t type, struct fd_object **fo) + TRYLOCKS_SHARED(0, (*fo)->refcount) +{ + *fo = wasm_runtime_malloc(sizeof(**fo)); + if (*fo == NULL) + return __WASI_ENOMEM; + refcount_init(&(*fo)->refcount, 1); + (*fo)->type = type; + (*fo)->number = -1; + return 0; +} + +// Attaches a file descriptor to the file descriptor table. +static void +fd_table_attach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object *fo, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting) + REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount) +{ + assert(ft->size > fd && "File descriptor table too small"); + struct fd_entry *fe = &ft->entries[fd]; + assert(fe->object == NULL + && "Attempted to overwrite an existing descriptor"); + fe->object = fo; + fe->rights_base = rights_base; + fe->rights_inheriting = rights_inheriting; + ++ft->used; + assert(ft->size >= ft->used * 2 && "File descriptor too full"); +} + +// Detaches a file descriptor from the file descriptor table. +static void +fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo) + REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount) +{ + assert(ft->size > fd && "File descriptor table too small"); + struct fd_entry *fe = &ft->entries[fd]; + *fo = fe->object; + assert(*fo != NULL && "Attempted to detach nonexistent descriptor"); + fe->object = NULL; + assert(ft->used > 0 && "Reference count mismatch"); + --ft->used; +} + +// 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, + __wasi_rights_t *rights_base, + __wasi_rights_t *rights_inheriting) +{ + 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; + } + + // Strip off read/write bits based on the access mode. + switch (fcntl(fd, F_GETFL) & O_ACCMODE) { + case O_RDONLY: + *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE; + break; + case O_WRONLY: + *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ; + break; + } + return 0; +} + +// 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; +} + +#define CLOSE_NON_STD_FD(fd) \ + do { \ + if (fd > 2) \ + close(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 +fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) +{ + if (refcount_release(&fo->refcount)) { + 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. + mutex_destroy(&fo->directory.lock); + if (fo->directory.handle == NULL) { + CLOSE_NON_STD_FD(fd_number(fo)); + } + else { + closedir(fo->directory.handle); + } + break; + default: + CLOSE_NON_STD_FD(fd_number(fo)); + break; + } + wasm_runtime_free(fo); + } +} + +// 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) +{ + __wasi_filetype_t type; + __wasi_rights_t rights_base, rights_inheriting; + struct fd_object *fo; + __wasi_errno_t error; + + error = + fd_determine_type_rights(out, &type, &rights_base, &rights_inheriting); + 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 + */ + if (error != __WASI_ENOTSUP) + return false; +#else + return false; +#endif + } + + error = fd_object_new(type, &fo); + if (error != 0) + return false; + fo->number = out; + if (type == __WASI_FILETYPE_DIRECTORY) { + if (!mutex_init(&fo->directory.lock)) { + fd_object_release(fo); + return false; + } + fo->directory.handle = NULL; + } + + // Grow the file descriptor table if needed. + rwlock_wrlock(&ft->lock); + if (!fd_table_grow(ft, in, 1)) { + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return false; + } + + fd_table_attach(ft, in, fo, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return true; +} + +// Picks an unused slot from the file descriptor table. +static __wasi_fd_t +fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock) +{ + assert(ft->size > ft->used && "File descriptor table has no free slots"); + for (;;) { + __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size); + if (ft->entries[fd].object == NULL) + return fd; + } +} + +// Inserts a file descriptor object into an unused slot of the file +// descriptor table. +static __wasi_errno_t +fd_table_insert(struct fd_table *ft, struct fd_object *fo, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, + __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) + UNLOCKS(fo->refcount) +{ + // Grow the file descriptor table if needed. + rwlock_wrlock(&ft->lock); + if (!fd_table_grow(ft, 0, 1)) { + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return convert_errno(errno); + } + + *out = fd_table_unused(ft); + fd_table_attach(ft, *out, fo, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return 0; +} + +// Inserts a numerical file descriptor into the file descriptor table. +static __wasi_errno_t +fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, __wasi_fd_t *out) + REQUIRES_UNLOCKED(ft->lock) +{ + struct fd_object *fo; + + __wasi_errno_t error = fd_object_new(type, &fo); + if (error != 0) { + close(in); + return error; + } + + fo->number = in; + if (type == __WASI_FILETYPE_DIRECTORY) { + if (!mutex_init(&fo->directory.lock)) { + fd_object_release(fo); + return (__wasi_errno_t)-1; + } + fo->directory.handle = NULL; + } + return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); +} + +__wasi_errno_t +wasmtime_ssp_fd_prestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, __wasi_prestat_t *buf) +{ + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + if (error != 0) { + rwlock_unlock(&prestats->lock); + return error; + } + + *buf = (__wasi_prestat_t){ + .pr_type = __WASI_PREOPENTYPE_DIR, + }; + + buf->u.dir.pr_name_len = strlen(prestat->dir); + + rwlock_unlock(&prestats->lock); + + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_prestat_dir_name( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, char *path, size_t path_len) +{ + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + if (error != 0) { + rwlock_unlock(&prestats->lock); + return error; + } + if (path_len != strlen(prestat->dir)) { + rwlock_unlock(&prestats->lock); + return EINVAL; + } + + bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); + + rwlock_unlock(&prestats->lock); + + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_close( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct fd_prestats *prestats, +#endif + __wasi_fd_t fd) +{ + // Don't allow closing a pre-opened resource. + // TODO: Eventually, we do want to permit this, once libpreopen in + // userspace is capable of removing entries from its tables as well. + { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + rwlock_unlock(&prestats->lock); + if (error == 0) { + return __WASI_ENOTSUP; + } + } + + // Validate the file descriptor. + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + // Remove it from the file descriptor table. + struct fd_object *fo; + fd_table_detach(ft, fd, &fo); + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return 0; +} + +// Look up a file descriptor object in a locked file descriptor table +// and increases its reference count. +static __wasi_errno_t +fd_object_get_locked(struct fd_object **fo, struct fd_table *ft, __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting) + TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) REQUIRES_EXCLUSIVE(ft->lock) +{ + // Test whether the file descriptor number is valid. + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, rights_base, rights_inheriting, &fe); + if (error != 0) + return error; + + // Increase the reference count on the file descriptor object. A copy + // of the rights are also stored, so callers can still access those if + // needed. + *fo = fe->object; + refcount_acquire(&(*fo)->refcount); + return 0; +} + +// Temporarily locks the file descriptor table to look up a file +// descriptor object, increases its reference count and drops the lock. +static __wasi_errno_t +fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting) + TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) +{ + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + __wasi_errno_t error = + fd_object_get_locked(fo, ft, fd, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return error; +} + +__wasi_errno_t +wasmtime_ssp_fd_datasync( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd) +{ + 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 + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_pread( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nread) +{ + 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 = preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, + (off_t)offset); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = (size_t)len; + return 0; +#else + if (iovcnt == 1) { + ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset); + fd_object_release(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(fo); + return __WASI_ENOMEM; + } + + // Perform a single read operation. + ssize_t len = pread(fd_number(fo), buf, totalsize, offset); + fd_object_release(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 +} + +__wasi_errno_t +wasmtime_ssp_fd_pwrite( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + 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 = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, + (off_t)offset); +#else + if (iovcnt == 1) { + len = pwrite(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(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 = pwrite(fd_number(fo), buf, totalsize, offset); + wasm_runtime_free(buf); + } +#endif + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nwritten = (size_t)len; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_read( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) +{ + 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 = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = (size_t)len; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_renumber( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct fd_prestats *prestats, +#endif + __wasi_fd_t from, __wasi_fd_t to) +{ + // Don't allow renumbering over a pre-opened resource. + // TODO: Eventually, we do want to permit this, once libpreopen in + // userspace is capable of removing entries from its tables as well. + { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); + if (error != 0) { + error = fd_prestats_get_entry(prestats, from, &prestat); + } + rwlock_unlock(&prestats->lock); + if (error == 0) { + return __WASI_ENOTSUP; + } + } + + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe_from; + __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + struct fd_entry *fe_to; + error = fd_table_get_entry(ft, to, 0, 0, &fe_to); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + struct fd_object *fo; + fd_table_detach(ft, to, &fo); + refcount_acquire(&fe_from->object->refcount); + fd_table_attach(ft, to, fe_from->object, fe_from->rights_base, + fe_from->rights_inheriting); + fd_object_release(fo); + + // Remove the old fd from the file descriptor table. + fd_table_detach(ft, from, &fo); + fd_object_release(fo); + --ft->used; + + rwlock_unlock(&ft->lock); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_seek( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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, + offset == 0 && whence == __WASI_WHENCE_CUR + ? __WASI_RIGHT_FD_TELL + : __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_TELL, + 0); + if (error != 0) + return error; + + off_t ret = lseek(fd_number(fo), offset, nwhence); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + *newoffset = (__wasi_filesize_t)ret; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_tell( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_filesize_t *newoffset) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_TELL, 0); + if (error != 0) + return error; + + off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + *newoffset = (__wasi_filesize_t)ret; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_fdstat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_fdstat_t *buf) +{ + 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) { + 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; + } + rwlock_unlock(&ft->lock); + if (ret < 0) + return convert_errno(errno); + + if ((ret & O_APPEND) != 0) + buf->fs_flags |= __WASI_FDFLAG_APPEND; +#ifdef 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 O_RSYNC + if ((ret & O_RSYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_RSYNC; +#endif + if ((ret & O_SYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_SYNC; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_fdstat_set_flags( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_fdflags_t fs_flags) +{ + int noflags = 0; + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) + noflags |= O_APPEND; + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) +#ifdef O_DSYNC + noflags |= O_DSYNC; +#else + noflags |= O_SYNC; +#endif + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + noflags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) +#ifdef O_RSYNC + noflags |= O_RSYNC; +#else + noflags |= O_SYNC; +#endif + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) + noflags |= O_SYNC; + + 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); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_fdstat_set_rights( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting) +{ + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + // Restrict the rights on the file descriptor. + fe->rights_base = fs_rights_base; + fe->rights_inheriting = fs_rights_inheriting; + rwlock_unlock(&ft->lock); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_sync( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd) +{ + 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)); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_write( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) + return error; + +#ifndef BH_VPRINTF + ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); +#else + ssize_t len = 0; + /* redirect stdout/stderr output to BH_VPRINTF function */ + if (fd_number(fo) == 1 || fd_number(fo) == 2) { + 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) { + 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); + } + } + } + else { + len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + } +#endif /* end of BH_VPRINTF */ + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nwritten = (size_t)len; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_advise( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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(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; + } + + // 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 +wasmtime_ssp_fd_allocate( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0); + if (error != 0) + 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 + + fd_object_release(fo); + if (ret != 0) + return convert_errno(ret); + return 0; +} + +// 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) +{ + char *buf = NULL; + size_t len = 32; + size_t len_org = len; + + for (;;) { + char *newbuf = wasm_runtime_malloc((uint32)len); + + if (newbuf == NULL) { + if (buf) + wasm_runtime_free(buf); + return NULL; + } + + if (buf != NULL) { + bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org); + wasm_runtime_free(buf); + } + + buf = newbuf; + ssize_t ret = readlinkat(fd, path, buf, len); + if (ret < 0) { + wasm_runtime_free(buf); + return NULL; + } + if ((size_t)ret + 1 < len) { + buf[ret] = '\0'; + *p_len = len; + return buf; + } + len_org = len; + len *= 2; + } +} + +// Lease to a directory, so a path underneath it can be accessed. +// +// This structure is used by system calls that operate on pathnames. In +// this environment, pathnames always consist of a pair of a file +// descriptor representing the directory where the lookup needs to start +// and the actual pathname string. +struct path_access { + int fd; // Directory file descriptor. + const char *path; // Pathname. + bool follow; // Whether symbolic links should be followed. + char *path_start; // Internal: pathname to free. + struct fd_object *fd_object; // Internal: directory file descriptor object. +}; + +// Creates a lease to a file descriptor and pathname pair. If the +// operating system does not implement Capsicum, it also normalizes the +// 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) + TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) +{ + char *path = str_nullterminate(upath, upathlen); + if (path == NULL) + return convert_errno(errno); + + // Fetch the directory file descriptor. + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting); + if (error != 0) { + wasm_runtime_free(path); + return error; + } + +#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->path = pa->path_start = path; + pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0; + pa->fd_object = fo; + return 0; +#else + // The implementation provides no mechanism to constrain lookups to a + // directory automatically. Emulate this logic by resolving the + // pathname manually. + + // Stack of directory file descriptors. Index 0 always corresponds + // with the directory provided to this function. Entering a directory + // 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); + size_t curfd = 0; + + // Stack of pathname strings used for symlink expansion. By using a + // stack, there is no need to concatenate any pathname strings while + // expanding symlinks. + char *paths[32]; + char *paths_start[32]; + paths[0] = paths_start[0] = path; + size_t curpath = 0; + size_t expansions = 0; + char *symlink; + size_t symlink_len; + + for (;;) { + // Extract the next pathname component from 'paths[curpath]', null + // terminate it and store it in 'file'. 'ends_with_slashes' stores + // 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 == '/'; + *file_end = '\0'; + + // Test for empty pathname strings and absolute paths. + if (file == file_end) { + error = ends_with_slashes ? __WASI_ENOTCAPABLE : __WASI_ENOENT; + goto fail; + } + + if (strcmp(file, ".") == 0) { + // Skip component. + } + else if (strcmp(file, "..") == 0) { + // Pop a directory off the stack. + if (curfd == 0) { + // Attempted to go to parent directory of the directory file + // descriptor. + error = __WASI_ENOTCAPABLE; + goto fail; + } + close(fds[curfd--]); + } + else if (curpath > 0 || *paths[curpath] != '\0' + || (ends_with_slashes && !needs_final_component)) { + // A pathname component whose name we're not interested in that is + // followed by a slash or is followed by other pathname + // components. In other words, a pathname component that must be a + // directory. First attempt to obtain a directory file descriptor + // for it. + 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) { + // Success. Push it onto the directory stack. + if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) { + close(newdir); + error = __WASI_ENAMETOOLONG; + goto fail; + } + fds[++curfd] = newdir; + } + else { + // Failed to open it. Attempt symlink expansion. + if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) { + error = convert_errno(errno); + goto fail; + } + symlink = readlinkat_dup(fds[curfd], file, &symlink_len); + if (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; + + error = convert_errno(errno); + goto fail; + } + } + else { + // The final pathname component. Depending on whether it ends with + // a slash or the symlink-follow flag is set, perform symlink + // expansion. + if (ends_with_slashes + || (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) { + symlink = readlinkat_dup(fds[curfd], file, &symlink_len); + if (symlink != NULL) + goto push_symlink; + if (errno != EINVAL && errno != ENOENT) { + error = convert_errno(errno); + goto fail; + } + } + + // Not a symlink, meaning we're done. Return the filename, + // together with the directory containing this file. + // + // If the file was followed by a trailing slash, we must retain + // it, to ensure system calls properly return ENOTDIR. + // Unfortunately, this opens up a race condition, because this + // means that users of path_get() will perform symlink expansion a + // second time. There is nothing we can do to mitigate this, as + // far as I know. + if (ends_with_slashes) + *file_end = '/'; + pa->path = file; + pa->path_start = paths_start[0]; + goto success; + } + + if (*paths[curpath] == '\0') { + if (curpath == 0) { + // No further pathname components to process. We may end up here + // when called on paths like ".", "a/..", but also if the path + // had trailing slashes and the caller is not interested in the + // name of the pathname component. + wasm_runtime_free(paths_start[0]); + pa->path = "."; + pa->path_start = NULL; + goto success; + } + + // Finished expanding symlink. Continue processing along the + // original path. + wasm_runtime_free(paths_start[curpath--]); + } + continue; + + push_symlink: + // Prevent infinite loops by placing an upper limit on the number of + // symlink expansions. + if (++expansions == 128) { + wasm_runtime_free(symlink); + error = __WASI_ELOOP; + goto fail; + } + + if (*paths[curpath] == '\0') { + // The original path already finished processing. Replace it by + // this symlink entirely. + wasm_runtime_free(paths_start[curpath]); + } + else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) { + // Too many nested symlinks. Stop processing. + wasm_runtime_free(symlink); + error = __WASI_ELOOP; + goto fail; + } + else { + // The original path still has components left. Retain the + // components that remain, so we can process them afterwards. + ++curpath; + } + + // Append a trailing slash to the symlink if the path leading up to + // it also contained one. Otherwise we would not throw ENOTDIR if + // the target is not a directory. + if (ends_with_slashes) + bh_strcat_s(symlink, (uint32)symlink_len, "/"); + paths[curpath] = paths_start[curpath] = symlink; + } + +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]); + pa->fd = fds[curfd]; + pa->follow = false; + pa->fd_object = fo; + return 0; + +fail: + // Failure. Free all resources. + for (size_t i = 1; i <= curfd; ++i) + close(fds[i]); + for (size_t i = 0; i <= curpath; ++i) + wasm_runtime_free(paths_start[i]); + fd_object_release(fo); + return error; +#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, + __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, + rights_inheriting, needs_final_component); +} + +static void +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); + fd_object_release(pa->fd_object); +} + +__wasi_errno_t +wasmtime_ssp_path_create_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const char *path, size_t pathlen) +{ + struct path_access pa; + __wasi_errno_t error = + path_get_nofollow(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); + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +static bool +validate_path(const char *path, struct fd_prestats *pt) +{ + 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))) + /* 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 + can be created or not. */ + return true; + + for (i = 0; i < pt->size; i++) { + if (pt->prestats[i].dir) { + if (!(prestat_dir_real = + realpath(pt->prestats[i].dir, prestat_dir_resolved))) + return false; + if (!strncmp(path_real, prestat_dir_real, strlen(prestat_dir_real))) + return true; + } + } + + return false; +} + +__wasi_errno_t +wasmtime_ssp_path_link( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct fd_prestats *prestats, +#endif + __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) +{ + 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); + 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); + if (error != 0) { + path_put(&old_pa); + return error; + } + + rwlock_rdlock(&prestats->lock); + if (!validate_path(old_pa.path, prestats) + || !validate_path(new_pa.path, prestats)) { + rwlock_unlock(&prestats->lock); + return __WASI_EBADF; + } + 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) { + // 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) { + bh_assert(target[target_len] == '\0'); + rwlock_rdlock(&prestats->lock); + if (!validate_path(target, prestats)) { + rwlock_unlock(&prestats->lock); + wasm_runtime_free(target); + return __WASI_EBADF; + } + rwlock_unlock(&prestats->lock); + ret = symlinkat(target, new_pa.fd, new_pa.path); + wasm_runtime_free(target); + } + } + path_put(&old_pa); + path_put(&new_pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_open( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path, + size_t pathlen, __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) +{ + // 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; + + // Which open() mode should be used to satisfy the needed rights. + bool read = + (rights_base & (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_READDIR)) != 0; + bool write = + (rights_base + & (__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; + + // Which rights are needed on the directory file descriptor. + __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN; + __wasi_rights_t needed_inheriting = rights_base | rights_inheriting; + + // 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 O_DSYNC + noflags |= O_DSYNC; +#else + noflags |= O_SYNC; +#endif + needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; + } + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + noflags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { +#ifdef O_RSYNC + noflags |= O_RSYNC; +#else + noflags |= O_SYNC; +#endif + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { + noflags |= O_SYNC; + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) + 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); + if (error != 0) + return error; + if (!pa.follow) + noflags |= O_NOFOLLOW; + + int nfd = openat(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); + } + path_put(&pa); + + // 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); + return error; + } + + { + struct stat sb; + + if (fstat(nfd, &sb) < 0) { + close(nfd); + return convert_errno(errno); + } + + if (S_ISDIR(sb.st_mode)) + rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE; + else if (S_ISREG(sb.st_mode)) + rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; + } + + return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, + rights_inheriting & max_inheriting, fd); +} + +// Copies out directory entry metadata or filename, potentially +// truncating it in the process. +static void +fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem, + size_t elemsize) +{ + size_t bufavail = bufsize - *bufused; + if (elemsize > bufavail) + elemsize = bufavail; + bh_memcpy_s((char *)buf + *bufused, (uint32)bufavail, elem, + (uint32)elemsize); + *bufused += elemsize; +} + +__wasi_errno_t +wasmtime_ssp_fd_readdir( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie, + size_t *bufused) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0); + if (error != 0) { + return error; + } + + // 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) { + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return convert_errno(errno); + } + fo->directory.handle = dp; + fo->directory.offset = __WASI_DIRCOOKIE_START; + } + + // Seek to the right position if the requested offset does not match + // the current offset. + if (fo->directory.offset != cookie) { + if (cookie == __WASI_DIRCOOKIE_START) + rewinddir(dp); + else + seekdir(dp, (long)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) { + mutex_unlock(&fo->directory.lock); + fd_object_release(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; + } + fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde)); + fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); + } + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_readlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize, + size_t *bufused) +{ + struct path_access pa; + __wasi_errno_t error = path_get_nofollow( + 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); + path_put(&pa); + if (len < 0) + return convert_errno(errno); + *bufused = (size_t)len < bufsize ? (size_t)len : bufsize; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_rename( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) +{ + 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); + 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); + if (error != 0) { + path_put(&old_pa); + return error; + } + + int ret = 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; +} + +// 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), + }; +} + +__wasi_errno_t +wasmtime_ssp_fd_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_filestat_t *buf) +{ + 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; + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +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 +wasmtime_ssp_fd_filestat_set_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_filesize_t st_size) +{ + 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); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) +{ + if ((fstflags + & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW + | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) + != 0) + return __WASI_EINVAL; + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_TIMES, 0); + 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); + + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, + size_t pathlen, __wasi_filestat_t *buf) +{ + struct path_access pa; + __wasi_errno_t error = path_get(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); + + // 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; +} + +__wasi_errno_t +wasmtime_ssp_path_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, + size_t pathlen, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) +{ + if (((fstflags + & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW + | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) + != 0) + /* ATIM & ATIM_NOW can't be set at the same time */ + || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0 + && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) + /* MTIM & MTIM_NOW can't be set at the same time */ + || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0 + && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0)) + return __WASI_EINVAL; + + struct path_access pa; + __wasi_errno_t error = + path_get(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); + + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_symlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct fd_prestats *prestats, +#endif + const char *old_path, size_t old_path_len, __wasi_fd_t fd, + const char *new_path, size_t new_path_len) +{ + 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, + __WASI_RIGHT_PATH_SYMLINK, 0, true); + if (error != 0) { + wasm_runtime_free(target); + return error; + } + + rwlock_rdlock(&prestats->lock); + if (!validate_path(target, prestats)) { + rwlock_unlock(&prestats->lock); + wasm_runtime_free(target); + return __WASI_EBADF; + } + rwlock_unlock(&prestats->lock); + + int ret = symlinkat(target, pa.fd, pa.path); + path_put(&pa); + wasm_runtime_free(target); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_unlink_file( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const char *path, size_t pathlen) +{ + 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) + 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 + path_put(&pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_remove_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, const char *path, size_t pathlen) +{ + struct path_access pa; + __wasi_errno_t error = + path_get_nofollow(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 + path_put(&pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; +} + +__wasi_errno_t +wasmtime_ssp_poll_oneoff( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, + size_t *nevents) NO_LOCK_ANALYSIS +{ + // Sleeping. + if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) { + out[0] = (__wasi_event_t){ + .userdata = in[0].userdata, + .type = in[0].u.type, + }; +#if CONFIG_HAS_CLOCK_NANOSLEEP + clockid_t clock_id; + if (convert_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( + clock_id, + (in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 + ? TIMER_ABSTIME + : 0, + &ts, NULL); + if (ret != 0) + out[0].error = convert_errno(ret); + } + else { + out[0].error = __WASI_ENOTSUP; + } +#else + switch (in[0].u.u.clock.clock_id) { + case __WASI_CLOCK_MONOTONIC: + if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + != 0) { + // TODO(ed): Implement. + fputs("Unimplemented absolute sleep on monotonic clock\n", + stderr); + out[0].error = __WASI_ENOSYS; + } + else { + // Perform relative sleeps on the monotonic clock also using + // nanosleep(). This is incorrect, but good enough for now. + struct timespec ts; + convert_timestamp(in[0].u.u.clock.timeout, &ts); + nanosleep(&ts, NULL); + } + break; + case __WASI_CLOCK_REALTIME: + if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + != 0) { + // Sleeping to an absolute point in time can only be done + // by waiting on a condition variable. + struct mutex mutex; + struct cond cond; + + if (!mutex_init(&mutex)) + return -1; + if (!cond_init_realtime(&cond)) { + mutex_destroy(&mutex); + return -1; + } + mutex_lock(&mutex); + cond_timedwait(&cond, &mutex, in[0].u.u.clock.timeout, + true); + mutex_unlock(&mutex); + mutex_destroy(&mutex); + cond_destroy(&cond); + } + else { + // Relative sleeps can be done using nanosleep(). + struct timespec ts; + convert_timestamp(in[0].u.u.clock.timeout, &ts); + nanosleep(&ts, NULL); + } + break; + default: + out[0].error = __WASI_ENOTSUP; + break; + } +#endif + *nevents = 1; + if (out[0].error != 0) + return convert_errno(out[0].error); + return 0; + } + + // Last option: call into poll(). This can only be done in case all + // subscriptions consist of __WASI_EVENTTYPE_FD_READ and + // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one + // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also + // the subscriptions generate by cloudlibc's poll() and select(). + struct fd_object **fos = + wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos))); + if (fos == NULL) + return __WASI_ENOMEM; + struct pollfd *pfds = + wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds))); + if (pfds == NULL) { + wasm_runtime_free(fos); + return __WASI_ENOMEM; + } + + // Convert subscriptions to pollfd entries. Increase the reference + // count on the file descriptors to ensure they remain valid across + // the call to poll(). + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + *nevents = 0; + const __wasi_subscription_t *clock_subscription = NULL; + for (size_t i = 0; i < nsubscriptions; ++i) { + const __wasi_subscription_t *s = &in[i]; + switch (s->u.type) { + case __WASI_EVENTTYPE_FD_READ: + case __WASI_EVENTTYPE_FD_WRITE: + { + __wasi_errno_t error = + fd_object_get_locked(&fos[i], ft, s->u.u.fd_readwrite.fd, + __WASI_RIGHT_POLL_FD_READWRITE, 0); + if (error == 0) { + // Proper file descriptor on which we can poll(). + pfds[i] = (struct pollfd){ + .fd = fd_number(fos[i]), + .events = s->u.type == __WASI_EVENTTYPE_FD_READ + ? POLLIN + : POLLOUT, + }; + } + else { + // Invalid file descriptor or rights missing. + fos[i] = NULL; + pfds[i] = (struct pollfd){ .fd = -1 }; + out[(*nevents)++] = (__wasi_event_t){ + .userdata = s->userdata, + .error = error, + .type = s->u.type, + }; + } + break; + } + case __WASI_EVENTTYPE_CLOCK: + if (clock_subscription == NULL + && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + == 0) { + // Relative timeout. + fos[i] = NULL; + pfds[i] = (struct pollfd){ .fd = -1 }; + clock_subscription = s; + break; + } + // Fallthrough. + default: + // Unsupported event. + fos[i] = NULL; + pfds[i] = (struct pollfd){ .fd = -1 }; + out[(*nevents)++] = (__wasi_event_t){ + .userdata = s->userdata, + .error = __WASI_ENOSYS, + .type = s->u.type, + }; + break; + } + } + rwlock_unlock(&ft->lock); + + // Use a zero-second timeout in case we've already generated events in + // the loop above. + int timeout; + if (*nevents != 0) { + timeout = 0; + } + else if (clock_subscription != NULL) { + __wasi_timestamp_t ts = clock_subscription->u.u.clock.timeout / 1000000; + timeout = ts > INT_MAX ? -1 : (int)ts; + } + else { + timeout = -1; + } + int ret = poll(pfds, nsubscriptions, timeout); + + __wasi_errno_t error = 0; + if (ret == -1) { + error = convert_errno(errno); + } + else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) { + // No events triggered. Trigger the clock event. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = clock_subscription->userdata, + .type = __WASI_EVENTTYPE_CLOCK, + }; + } + else { + // Events got triggered. Don't trigger the clock event. + for (size_t i = 0; i < nsubscriptions; ++i) { + if (pfds[i].fd >= 0) { + __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) + nbytes = (__wasi_filesize_t)l; + } + if ((pfds[i].revents & POLLNVAL) != 0) { + // Bad file descriptor. This normally cannot occur, as + // referencing the file descriptor object will always ensure + // the descriptor is valid. Still, macOS may sometimes + // return this on FIFOs when reaching end-of-file. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, +#ifdef __APPLE__ + .u.fd_readwrite.nbytes = nbytes, + .u.fd_readwrite.flags = + __WASI_EVENT_FD_READWRITE_HANGUP, +#else + .error = __WASI_EBADF, +#endif + .type = in[i].u.type, + }; + } + else if ((pfds[i].revents & POLLERR) != 0) { + // File descriptor is in an error state. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .error = __WASI_EIO, + .type = in[i].u.type, + }; + } + else if ((pfds[i].revents & POLLHUP) != 0) { + // End-of-file. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .type = in[i].u.type, + .u.fd_readwrite.nbytes = nbytes, + .u.fd_readwrite.flags = + __WASI_EVENT_FD_READWRITE_HANGUP, + }; + } + else if ((pfds[i].revents & (POLLIN | POLLOUT)) != 0) { + // Read or write possible. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .type = in[i].u.type, + .u.fd_readwrite.nbytes = nbytes, + }; + } + } + } + } + + for (size_t i = 0; i < nsubscriptions; ++i) + if (fos[i] != NULL) + fd_object_release(fos[i]); + wasm_runtime_free(fos); + wasm_runtime_free(pfds); + return error; +} + +#if 0 +/** + * We throw exception in libc-wasi wrapper function wasi_proc_exit() + * but not call this function. + */ +void wasmtime_ssp_proc_exit( + __wasi_exitcode_t rval +) { + _Exit((int32)rval); +} +#endif + +__wasi_errno_t +wasmtime_ssp_proc_raise(__wasi_signal_t sig) +{ + static const int signals[] = { +#define X(v) [__WASI_##v] = v +#if defined(SIGABRT) + X(SIGABRT), +#endif +#if defined(SIGALRM) + X(SIGALRM), +#endif +#if defined(SIGBUS) + X(SIGBUS), +#endif +#if defined(SIGCHLD) + X(SIGCHLD), +#endif +#if defined(SIGCONT) + X(SIGCONT), +#endif +#if defined(SIGFPE) + X(SIGFPE), +#endif +#if defined(SIGHUP) + X(SIGHUP), +#endif +#if defined(SIGILL) + X(SIGILL), +#endif +#if defined(SIGINT) + X(SIGINT), +#endif +#if defined(SIGKILL) + X(SIGKILL), +#endif +#if defined(SIGPIPE) + X(SIGPIPE), +#endif +#if defined(SIGQUIT) + X(SIGQUIT), +#endif +#if defined(SIGSYS) + X(SIGSEGV), +#endif +#if defined(SIGSTOP) + X(SIGSTOP), +#endif +#if defined(SIGSYS) + X(SIGSYS), +#endif +#if defined(SIGTERM) + X(SIGTERM), +#endif +#if defined(SIGTRAP) + X(SIGTRAP), +#endif +#if defined(SIGTSTP) + X(SIGTSTP), +#endif +#if defined(SIGTTIN) + X(SIGTTIN), +#endif +#if defined(SIGTTOU) + X(SIGTTOU), +#endif +#if defined(SIGURG) + X(SIGURG), +#endif +#if defined(SIGUSR1) + X(SIGUSR1), +#endif +#if defined(SIGUSR2) + X(SIGUSR2), +#endif +#if defined(SIGVTALRM) + X(SIGVTALRM), +#endif +#if defined(SIGXCPU) + X(SIGXCPU), +#endif +#if defined(SIGXFSZ) + X(SIGXFSZ), +#endif +#undef X + }; + if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0) + return __WASI_EINVAL; + +#if CONFIG_TLS_USE_GSBASE + // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV + // to the default action before raising. + if (sig == __WASI_SIGSEGV) { + struct sigaction sa = { + .sa_handler = SIG_DFL, + }; + sigemptyset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, NULL); + } +#endif + + if (raise(signals[sig]) < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_random_get(void *buf, size_t nbyte) +{ + random_buf(buf, nbyte); + return 0; +} + +__wasi_errno_t +wasi_ssp_sock_accept( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new) +{ + __wasi_filetype_t wasi_type; + __wasi_rights_t max_base, max_inheriting; + struct fd_object *fo; + bh_socket_t new_sock = -1; + int ret; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ACCEPT, 0); + if (error != __WASI_ESUCCESS) { + goto fail; + } + + ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL); + fd_object_release(fo); + if (BHT_OK != ret) { + error = convert_errno(errno); + goto fail; + } + + error = fd_determine_type_rights(new_sock, &wasi_type, &max_base, + &max_inheriting); + if (error != __WASI_ESUCCESS) { + goto fail; + } + + error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base, + max_inheriting, fd_new); + if (error != __WASI_ESUCCESS) { + /* released in fd_table_insert_fd() */ + new_sock = -1; + goto fail; + } + + return __WASI_ESUCCESS; + +fail: + if (-1 != new_sock) { + os_socket_close(new_sock); + } + return error; +} + +__wasi_errno_t +wasi_ssp_sock_addr_local( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr) +{ + struct fd_object *fo; + bh_sockaddr_t bh_addr; + int ret; + + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0); + if (error != __WASI_ESUCCESS) + return error; + + ret = os_socket_addr_local(fd_number(fo), &bh_addr); + fd_object_release(fo); + if (ret != BHT_OK) { + return convert_errno(errno); + } + + bh_sockaddr_to_wasi_addr(&bh_addr, addr); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_addr_remote( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr) +{ + struct fd_object *fo; + bh_sockaddr_t bh_addr; + int ret; + + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0); + if (error != __WASI_ESUCCESS) + return error; + + ret = os_socket_addr_remote(fd_number(fo), &bh_addr); + fd_object_release(fo); + if (ret != BHT_OK) { + return convert_errno(errno); + } + + bh_sockaddr_to_wasi_addr(&bh_addr, addr); + + return __WASI_ESUCCESS; +} + +static bool +wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen) +{ + if (addr->kind == IPv4) { + const char *format = "%u.%u.%u.%u"; + + assert(buflen >= 16); + + snprintf(buf, buflen, format, addr->addr.ip4.addr.n0, + addr->addr.ip4.addr.n1, addr->addr.ip4.addr.n2, + addr->addr.ip4.addr.n3); + + return true; + } + else if (addr->kind == IPv6) { + const char *format = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"; + __wasi_addr_ip6_t ipv6 = addr->addr.ip6.addr; + + assert(buflen >= 40); + + snprintf(buf, buflen, format, ipv6.n0, ipv6.n1, ipv6.n2, ipv6.n3, + ipv6.h0, ipv6.h1, ipv6.h2, ipv6.h3); + + return true; + } + + return false; +} + +__wasi_errno_t +wasi_ssp_sock_bind( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct addr_pool *addr_pool, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr) +{ + char buf[48] = { 0 }; + struct fd_object *fo; + __wasi_errno_t error; + int port = addr->kind == IPv4 ? addr->addr.ip4.port : addr->addr.ip6.port; + int ret; + + if (!wasi_addr_to_string(addr, buf, sizeof(buf))) { + return __WASI_EPROTONOSUPPORT; + } + + if (!addr_pool_search(addr_pool, buf)) { + return __WASI_EACCES; + } + + error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0); + if (error != __WASI_ESUCCESS) + return error; + + ret = os_socket_bind(fd_number(fo), buf, &port); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_addr_resolve( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, char **ns_lookup_list, +#endif + 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) +{ + bh_addr_info_t *wamr_addr_info = + wasm_runtime_malloc(addr_info_size * sizeof(bh_addr_info_t)); + uint8_t hints_is_ipv4 = hints->family == INET4; + uint8_t hints_is_tcp = hints->type == SOCKET_STREAM; + size_t _max_info_size; + size_t actual_info_size; + + if (!wamr_addr_info) { + return __WASI_ENOMEM; + } + + if (!ns_lookup_list_search(ns_lookup_list, host)) { + wasm_runtime_free(wamr_addr_info); + return __WASI_EACCES; + } + + int ret = os_socket_addr_resolve( + host, service, hints->hints_enabled ? &hints_is_tcp : NULL, + hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info, + addr_info_size, &_max_info_size); + + if (ret != BHT_OK) { + wasm_runtime_free(wamr_addr_info); + return convert_errno(errno); + } + + *max_info_size = _max_info_size; + actual_info_size = + addr_info_size < *max_info_size ? addr_info_size : *max_info_size; + + for (size_t i = 0; i < actual_info_size; i++) { + addr_info[i].type = + wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM; + bh_sockaddr_to_wasi_addr(&wamr_addr_info[i].sockaddr, + &addr_info[i].addr); + } + + wasm_runtime_free(wamr_addr_info); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_connect( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct addr_pool *addr_pool, +#endif + __wasi_fd_t fd, __wasi_addr_t *addr) +{ + char buf[48] = { 0 }; + struct fd_object *fo; + __wasi_errno_t error; + int ret; + + if (!wasi_addr_to_string(addr, buf, sizeof(buf))) { + return __WASI_EPROTONOSUPPORT; + } + + if (!addr_pool_search(addr_pool, buf)) { + return __WASI_EACCES; + } + + error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0); + if (error != __WASI_ESUCCESS) + return error; + + ret = os_socket_connect(fd_number(fo), buf, + addr->kind == IPv4 ? addr->addr.ip4.port + : addr->addr.ip6.port); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_get_recv_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __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); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + *size = optval; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_get_reuse_addr( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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); + + ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + *reuse = optval; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_get_reuse_port( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) */ + + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + *reuse = optval; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_get_send_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __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_SNDBUF, &optval, &optlen); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + *size = optval; + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_listen( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __wasi_size_t backlog) +{ + struct fd_object *fo; + int ret; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_LISTEN, 0); + if (error != __WASI_ESUCCESS) + return error; + + ret = os_socket_listen(fd_number(fo), backlog); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_open( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, + __wasi_fd_t *sockfd) +{ + bh_socket_t sock; + bool is_tcp = SOCKET_DGRAM == socktype ? false : true; + bool is_ipv4 = INET6 == af ? false : true; + int ret; + __wasi_filetype_t wasi_type; + __wasi_rights_t max_base, max_inheriting; + __wasi_errno_t error; + + (void)poolfd; + + ret = os_socket_create(&sock, is_ipv4, is_tcp); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + error = + fd_determine_type_rights(sock, &wasi_type, &max_base, &max_inheriting); + if (error != __WASI_ESUCCESS) { + os_socket_close(sock); + return error; + } + + if (SOCKET_DGRAM == socktype) { + assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM); + } + else { + assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM); + } + + // TODO: base rights and inheriting rights ? + error = fd_table_insert_fd(curfds, sock, wasi_type, max_base, + max_inheriting, sockfd); + if (error != __WASI_ESUCCESS) { + return error; + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_set_recv_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __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_RCVBUF, &optval, + sizeof(optval)); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_set_reuse_addr( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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; + + ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, + sizeof(optval)); + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_set_reuse_port( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __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) */ + + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasi_ssp_sock_set_send_buf_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, __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)); + + fd_object_release(fo); + if (BHT_OK != ret) { + return convert_errno(errno); + } + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_recv( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len) +{ + __wasi_addr_t src_addr; + + return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr, + recv_len); +} + +__wasi_errno_t +wasmtime_ssp_sock_recv_from( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags, + __wasi_addr_t *src_addr, size_t *recv_len) +{ + struct fd_object *fo; + __wasi_errno_t error; + bh_sockaddr_t sockaddr; + int ret; + + error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0); + if (error != 0) { + return error; + } + + ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr); + fd_object_release(fo); + if (-1 == ret) { + return convert_errno(errno); + } + + bh_sockaddr_to_wasi_addr(&sockaddr, src_addr); + + *recv_len = (size_t)ret; + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_send( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + + error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) { + return error; + } + + ret = os_socket_send(fd_number(fo), buf, buf_len); + fd_object_release(fo); + if (-1 == ret) { + return convert_errno(errno); + } + + *sent_len = (size_t)ret; + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_send_to( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, struct addr_pool *addr_pool, +#endif + __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) +{ + char addr_buf[48] = { 0 }; + struct fd_object *fo; + __wasi_errno_t error; + int ret; + bh_sockaddr_t sockaddr; + + if (!wasi_addr_to_string(dest_addr, addr_buf, sizeof(addr_buf))) { + return __WASI_EPROTONOSUPPORT; + } + + if (!addr_pool_search(addr_pool, addr_buf)) { + return __WASI_EACCES; + } + + error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) { + return error; + } + + wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr); + + ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr); + fd_object_release(fo); + if (-1 == ret) { + return convert_errno(errno); + } + + *sent_len = (size_t)ret; + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_shutdown( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + ret = os_socket_shutdown(fd_number(fo)); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sched_yield(void) +{ + if (sched_yield() < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_args_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + char **argv, char *argv_buf) +{ + for (size_t i = 0; i < argv_environ->argc; ++i) { + argv[i] = + argv_buf + (argv_environ->argv_list[i] - argv_environ->argv_buf); + } + argv[argv_environ->argc] = NULL; + bh_memcpy_s(argv_buf, (uint32)argv_environ->argv_buf_size, + argv_environ->argv_buf, (uint32)argv_environ->argv_buf_size); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_args_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + size_t *argc, size_t *argv_buf_size) +{ + *argc = argv_environ->argc; + *argv_buf_size = argv_environ->argv_buf_size; + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_environ_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + char **environ, char *environ_buf) +{ + for (size_t i = 0; i < argv_environ->environ_count; ++i) { + environ[i] = + environ_buf + + (argv_environ->environ_list[i] - argv_environ->environ_buf); + } + environ[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); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_environ_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + size_t *environ_count, size_t *environ_buf_size) +{ + *environ_count = argv_environ->environ_count; + *environ_buf_size = argv_environ->environ_buf_size; + return __WASI_ESUCCESS; +} + +bool +argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, + size_t argv_buf_size, char **argv_list, size_t argc, + char *environ_buf, size_t environ_buf_size, + char **environ_list, size_t environ_count) +{ + memset(argv_environ, 0, sizeof(struct argv_environ_values)); + + argv_environ->argv_buf = argv_buf; + argv_environ->argv_buf_size = argv_buf_size; + argv_environ->argv_list = argv_list; + argv_environ->argc = argc; + argv_environ->environ_buf = environ_buf; + argv_environ->environ_buf_size = environ_buf_size; + argv_environ->environ_list = environ_list; + argv_environ->environ_count = environ_count; + return true; +} + +void +argv_environ_destroy(struct argv_environ_values *argv_environ) +{} + +void +fd_table_destroy(struct fd_table *ft) +{ + if (ft->entries) { + for (uint32 i = 0; i < ft->size; i++) { + if (ft->entries[i].object != NULL) { + fd_object_release(ft->entries[i].object); + } + } + rwlock_destroy(&ft->lock); + wasm_runtime_free(ft->entries); + } +} + +void +fd_prestats_destroy(struct fd_prestats *pt) +{ + if (pt->prestats) { + for (uint32 i = 0; i < pt->size; i++) { + if (pt->prestats[i].dir != NULL) { + wasm_runtime_free((void *)pt->prestats[i].dir); + } + } + rwlock_destroy(&pt->lock); + wasm_runtime_free(pt->prestats); + } +} + +bool +addr_pool_init(struct addr_pool *addr_pool) +{ + memset(addr_pool, 0, sizeof(*addr_pool)); + + return true; +} + +bool +addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask) +{ + struct addr_pool *cur = addr_pool; + struct addr_pool *next; + bh_ip_addr_buffer_t target; + + if (!addr_pool) { + return false; + } + + if (!(next = wasm_runtime_malloc(sizeof(struct addr_pool)))) { + return false; + } + + next->next = NULL; + next->mask = mask; + + if (os_socket_inet_network(true, addr, &target) != BHT_OK) { + // If parsing IPv4 fails, try IPv6 + if (os_socket_inet_network(false, addr, &target) != BHT_OK) { + wasm_runtime_free(next); + return false; + } + next->type = IPv6; + bh_memcpy_s(next->addr.ip6, sizeof(next->addr.ip6), target.ipv6, + sizeof(target.ipv6)); + } + else { + next->type = IPv4; + next->addr.ip4 = target.ipv4; + } + + /* attach with */ + while (cur->next) { + cur = cur->next; + } + cur->next = next; + 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) +{ + size_t element_size = sizeof(uint8_t) * 8; + + for (size_t i = 0; i < buflen; i++) { + if (mask <= i * element_size) { + buf[i] = 0; + } + else { + size_t offset = min(mask - i * element_size, element_size); + buf[i] = (~0u) << (element_size - offset); + } + } +} + +/* target must be in network byte order */ +static bool +compare_address(const struct addr_pool *addr_pool_entry, + bh_ip_addr_buffer_t *target) +{ + uint8_t maskbuf[16] = { 0 }; + uint8_t basebuf[16] = { 0 }; + size_t addr_size; + uint8_t max_addr_mask; + + if (addr_pool_entry->type == IPv4) { + uint32_t addr_ip4 = htonl(addr_pool_entry->addr.ip4); + bh_memcpy_s(basebuf, sizeof(addr_ip4), &addr_ip4, sizeof(addr_ip4)); + addr_size = 4; + } + else { + uint16_t partial_addr_ip6; + for (int i = 0; i < 8; i++) { + partial_addr_ip6 = htons(addr_pool_entry->addr.ip6[i]); + bh_memcpy_s(&basebuf[i * sizeof(partial_addr_ip6)], + sizeof(partial_addr_ip6), &partial_addr_ip6, + sizeof(partial_addr_ip6)); + } + addr_size = 16; + } + max_addr_mask = addr_size * 8; + + /* IPv4 0.0.0.0 or IPv6 :: means any address */ + if (basebuf[0] == 0 && !memcmp(basebuf, basebuf + 1, addr_size - 1)) { + return true; + } + + /* No support for invalid mask value */ + if (addr_pool_entry->mask > max_addr_mask) { + return false; + } + + init_address_mask(maskbuf, addr_size, addr_pool_entry->mask); + + for (size_t i = 0; i < addr_size; i++) { + uint8_t addr_mask = target->data[i] & maskbuf[i]; + uint8_t range_mask = basebuf[i] & maskbuf[i]; + if (addr_mask != range_mask) { + return false; + } + } + + return true; +} + +bool +addr_pool_search(struct addr_pool *addr_pool, const char *addr) +{ + struct addr_pool *cur = addr_pool->next; + bh_ip_addr_buffer_t target; + __wasi_addr_type_t addr_type; + + if (os_socket_inet_network(true, addr, &target) != BHT_OK) { + size_t i; + + if (os_socket_inet_network(false, addr, &target) != BHT_OK) { + return false; + } + addr_type = IPv6; + for (i = 0; i < sizeof(target.ipv6) / sizeof(target.ipv6[0]); i++) { + target.ipv6[i] = htons(target.ipv6[i]); + } + } + else { + addr_type = IPv4; + target.ipv4 = htonl(target.ipv4); + } + + while (cur) { + if (cur->type == addr_type && compare_address(cur, &target)) { + return true; + } + + cur = cur->next; + } + + return false; +} + +void +addr_pool_destroy(struct addr_pool *addr_pool) +{ + struct addr_pool *cur = addr_pool->next; + + while (cur) { + struct addr_pool *next = cur->next; + wasm_runtime_free(cur); + cur = next; + } +} + +#ifndef WASMTIME_SSP_STATIC_CURFDS +#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds, +#else +#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE +#endif + +// Defines a function that passes through the socket option to the OS +// implementation +#define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \ + __wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \ + WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \ + OPTION_TYPE option) \ + { \ + struct fd_object *fo; \ + __wasi_errno_t error; \ + int ret; \ + error = fd_object_get(curfds, &fo, sock, 0, 0); \ + if (error != 0) \ + return error; \ + ret = os_socket_##FUNC_NAME(fd_number(fo), option); \ + fd_object_release(fo); \ + if (BHT_OK != ret) \ + return convert_errno(errno); \ + return __WASI_ESUCCESS; \ + } + +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_timeout, uint64) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_timeout, uint64 *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_timeout, uint64) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_timeout, uint64 *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_buf_size, size_t) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_buf_size, size_t *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_buf_size, size_t) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_buf_size, size_t *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_broadcast, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_broadcast, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_keep_alive, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_keep_alive, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_addr, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_addr, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_port, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_port, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_no_delay, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_no_delay, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_quick_ack, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_quick_ack, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_idle, uint32) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_idle, uint32 *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_intvl, uint32) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_intvl, uint32 *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_fastopen_connect, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_fastopen_connect, bool *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_ttl, uint8_t) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_ttl, uint8_t *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_multicast_ttl, uint8_t) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_multicast_ttl, uint8_t *) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ipv6_only, bool) +WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *) + +#undef WASMTIME_SSP_PASSTHROUGH_FD_TABLE +#undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION + +__wasi_errno_t +wasmtime_ssp_sock_set_linger( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, bool is_enabled, int linger_s) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + return __WASI_ESUCCESS; +} + +__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) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_add_membership( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + bh_ip_addr_buffer_t addr_info; + bool is_ipv6; + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + 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, + imr_interface, is_ipv6); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_drop_membership( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + bh_ip_addr_buffer_t addr_info; + bool is_ipv6; + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + 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, + imr_interface, is_ipv6); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_set_ip_multicast_loop( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, bool ipv6, bool is_enabled) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + return __WASI_ESUCCESS; +} + +__wasi_errno_t +wasmtime_ssp_sock_get_ip_multicast_loop( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, bool ipv6, bool *is_enabled) +{ + struct fd_object *fo; + __wasi_errno_t error; + int ret; + error = fd_object_get(curfds, &fo, sock, 0, 0); + if (error != 0) + return error; + + ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); + fd_object_release(fo); + if (BHT_OK != ret) + return convert_errno(errno); + + return __WASI_ESUCCESS; +} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h new file mode 100644 index 000000000..7a593390a --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h @@ -0,0 +1,89 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/ + +#ifndef POSIX_H +#define POSIX_H + +#include "bh_platform.h" +#include "locking.h" + +struct fd_entry; +struct fd_prestat; +struct syscalls; + +struct fd_table { + struct rwlock lock; + struct fd_entry *entries; + size_t size; + size_t used; +}; + +struct fd_prestats { + struct rwlock lock; + struct fd_prestat *prestats; + size_t size; + size_t used; +}; + +struct argv_environ_values { + const char *argv_buf; + size_t argv_buf_size; + char **argv_list; + size_t argc; + char *environ_buf; + size_t environ_buf_size; + char **environ_list; + size_t environ_count; +}; + +struct addr_pool { + /* addr and mask in host order */ + union { + uint32 ip4; + uint16 ip6[8]; + } addr; + struct addr_pool *next; + __wasi_addr_type_t type; + uint8 mask; +}; + +bool +fd_table_init(struct fd_table *); +bool +fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int); +bool +fd_prestats_init(struct fd_prestats *); +bool +fd_prestats_insert(struct fd_prestats *, const char *, __wasi_fd_t); +bool +argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, + size_t argv_buf_size, char **argv_list, size_t argc, + char *environ_buf, size_t environ_buf_size, + char **environ_list, size_t environ_count); +void +argv_environ_destroy(struct argv_environ_values *argv_environ); +void +fd_table_destroy(struct fd_table *ft); +void +fd_prestats_destroy(struct fd_prestats *pt); + +bool +addr_pool_init(struct addr_pool *); +bool +addr_pool_insert(struct addr_pool *, const char *, uint8 mask); +bool +addr_pool_search(struct addr_pool *, const char *); +void +addr_pool_destroy(struct addr_pool *); + +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h new file mode 100644 index 000000000..2d40bc3aa --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h @@ -0,0 +1,98 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef QUEUE_H +#define QUEUE_H + +// LIST: Double-linked list. + +#define LIST_HEAD(name, type) \ + struct name { \ + struct type *l_first; \ + } + +/* clang-format off */ +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } +/* clang-format on */ + +#define LIST_ENTRY(type) \ + struct { \ + struct type *l_next; \ + struct type **l_prev; \ + } + +#define LIST_FOREACH(var, head, field) \ + for ((var) = (head)->l_first; (var) != NULL; (var) = (var)->field.l_next) + +#define LIST_INIT(head) \ + do { \ + (head)->l_first = NULL; \ + } while (0) + +#define LIST_INSERT_HEAD(head, element, field) \ + do { \ + (element)->field.l_next = (head)->l_first; \ + if ((head)->l_first != NULL) \ + (head)->l_first->field.l_prev = &(element)->field.l_next; \ + (head)->l_first = (element); \ + (element)->field.l_prev = &(head)->l_first; \ + } while (0) + +#define LIST_REMOVE(element, field) \ + do { \ + if ((element)->field.l_next != NULL) \ + (element)->field.l_next->field.l_prev = (element)->field.l_prev; \ + *(element)->field.l_prev = (element)->field.l_next; \ + } while (0) + +// TAILQ: Double-linked list with tail pointer. + +#define TAILQ_HEAD(name, type) \ + struct name { \ + struct type *t_first; \ + struct type **t_last; \ + } + +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *t_next; \ + struct type **t_prev; \ + } + +#define TAILQ_EMPTY(head) ((head)->t_first == NULL) +#define TAILQ_FIRST(head) ((head)->t_first) +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = (head)->t_first; (var) != NULL; (var) = (var)->field.t_next) +#define TAILQ_INIT(head) \ + do { \ + (head)->t_first = NULL; \ + (head)->t_last = &(head)->t_first; \ + } while (0) +#define TAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.t_next = NULL; \ + (elm)->field.t_prev = (head)->t_last; \ + *(head)->t_last = (elm); \ + (head)->t_last = &(elm)->field.t_next; \ + } while (0) +#define TAILQ_REMOVE(head, element, field) \ + do { \ + if ((element)->field.t_next != NULL) \ + (element)->field.t_next->field.t_prev = (element)->field.t_prev; \ + else \ + (head)->t_last = (element)->field.t_prev; \ + *(element)->field.t_prev = (element)->field.t_next; \ + } while (0) + +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c new file mode 100644 index 000000000..01a1dab3a --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c @@ -0,0 +1,98 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#include "ssp_config.h" +#include "bh_platform.h" +#include "random.h" + +#if CONFIG_HAS_ARC4RANDOM_BUF + +void +random_buf(void *buf, size_t len) +{ + arc4random_buf(buf, len); +} + +#elif CONFIG_HAS_GETRANDOM + +#ifndef BH_PLATFORM_LINUX_SGX +#include <sys/random.h> +#endif + +void +random_buf(void *buf, size_t len) +{ + for (;;) { + ssize_t x = getrandom(buf, len, 0); + if (x < 0) { + if (errno == EINTR) + continue; + os_printf("getrandom failed: %s", strerror(errno)); + abort(); + } + if ((size_t)x == len) + return; + buf = (void *)((unsigned char *)buf + x); + len -= (size_t)x; + } +} + +#else + +static int urandom; + +static void +open_urandom(void) +{ + urandom = open("/dev/urandom", O_RDONLY); + if (urandom < 0) { + os_printf("Failed to open /dev/urandom\n"); + abort(); + } +} + +void +random_buf(void *buf, size_t len) +{ + static pthread_once_t open_once = PTHREAD_ONCE_INIT; + pthread_once(&open_once, open_urandom); + + if ((size_t)read(urandom, buf, len) != len) { + os_printf("Short read on /dev/urandom\n"); + abort(); + } +} + +#endif + +// Calculates a random number within the range [0, upper - 1] without +// any modulo bias. +// +// The function below repeatedly obtains a random number from +// arc4random() until it lies within the range [2^k % upper, 2^k). As +// this range has length k * upper, we can safely obtain a number +// without any modulo bias. +uintmax_t +random_uniform(uintmax_t upper) +{ + // Compute 2^k % upper + // == (2^k - upper) % upper + // == -upper % upper. + uintmax_t lower = -upper % upper; + for (;;) { + uintmax_t value; + random_buf(&value, sizeof(value)); + if (value >= lower) + return value % upper; + } +} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h new file mode 100644 index 000000000..23c2da4db --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h @@ -0,0 +1,21 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef RANDOM_H +#define RANDOM_H + +void +random_buf(void *, size_t); +uintmax_t random_uniform(uintmax_t); + +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h new file mode 100644 index 000000000..03b4b87ac --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h @@ -0,0 +1,139 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef REFCOUNT_H +#define REFCOUNT_H + +#include "bh_platform.h" +#include "locking.h" +#include "gnuc.h" + +#define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS +#define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS + +#if CONFIG_HAS_STD_ATOMIC != 0 + +#include <stdatomic.h> + +/* Simple reference counter. */ +struct LOCKABLE refcount { + atomic_uint count; +}; + +/* Initialize the reference counter. */ +static inline void +refcount_init(struct refcount *r, unsigned int count) PRODUCES(*r) +{ + atomic_init(&r->count, count); +} + +/* Increment the reference counter. */ +static inline void +refcount_acquire(struct refcount *r) PRODUCES(*r) +{ + atomic_fetch_add_explicit(&r->count, 1, memory_order_acquire); +} + +/* Decrement the reference counter, returning whether the reference + dropped to zero. */ +static inline bool +refcount_release(struct refcount *r) CONSUMES(*r) +{ + int old = + (int)atomic_fetch_sub_explicit(&r->count, 1, memory_order_release); + bh_assert(old != 0 && "Reference count becoming negative"); + return old == 1; +} + +#elif defined(BH_PLATFORM_LINUX_SGX) + +#include <sgx_spinlock.h> + +/* Simple reference counter. */ +struct refcount { + sgx_spinlock_t lock; + unsigned int count; +}; + +/* Initialize the reference counter. */ +static inline void +refcount_init(struct refcount *r, unsigned int count) +{ + r->lock = SGX_SPINLOCK_INITIALIZER; + r->count = count; +} + +/* Increment the reference counter. */ +static inline void +refcount_acquire(struct refcount *r) +{ + sgx_spin_lock(&r->lock); + r->count++; + sgx_spin_unlock(&r->lock); +} + +/* Decrement the reference counter, returning whether the reference + dropped to zero. */ +static inline bool +refcount_release(struct refcount *r) +{ + int old; + sgx_spin_lock(&r->lock); + old = (int)r->count; + r->count--; + sgx_spin_unlock(&r->lock); + bh_assert(old != 0 && "Reference count becoming negative"); + return old == 1; +} + +#elif defined(__GNUC_PREREQ) + +#if __GNUC_PREREQ(4, 7) + +struct refcount { + unsigned int count; +}; + +/* Initialize the reference counter. */ +static inline void +refcount_init(struct refcount *r, unsigned int count) +{ + __atomic_store_n(&r->count, count, __ATOMIC_SEQ_CST); +} + +/* Increment the reference counter. */ +static inline void +refcount_acquire(struct refcount *r) +{ + __atomic_fetch_add(&r->count, 1, __ATOMIC_ACQUIRE); +} + +/* Decrement the reference counter, returning whether the reference + dropped to zero. */ +static inline bool +refcount_release(struct refcount *r) +{ + int old = (int)__atomic_fetch_sub(&r->count, 1, __ATOMIC_RELEASE); + bh_assert(old != 0 && "Reference count becoming negative"); + return old == 1; +} + +#else /* else of __GNUC_PREREQ (4.7) */ +#error "Reference counter isn't implemented" +#endif /* end of __GNUC_PREREQ (4.7) */ + +#else /* else of CONFIG_HAS_STD_ATOMIC */ +#error "Reference counter isn't implemented" +#endif /* end of CONFIG_HAS_STD_ATOMIC */ + +#endif /* end of REFCOUNT_H */ diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h new file mode 100644 index 000000000..4f5838159 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h @@ -0,0 +1,100 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef RIGHTS_H +#define RIGHTS_H + +/* clang-format off */ + +#define RIGHTS_ALL \ + (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \ + __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \ + __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \ + __WASI_RIGHT_PATH_CREATE_DIRECTORY | __WASI_RIGHT_PATH_CREATE_FILE | \ + __WASI_RIGHT_PATH_LINK_SOURCE | __WASI_RIGHT_PATH_LINK_TARGET | \ + __WASI_RIGHT_PATH_OPEN | __WASI_RIGHT_FD_READDIR | \ + __WASI_RIGHT_PATH_READLINK | __WASI_RIGHT_PATH_RENAME_SOURCE | \ + __WASI_RIGHT_PATH_RENAME_TARGET | __WASI_RIGHT_PATH_FILESTAT_GET | \ + __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \ + __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \ + __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \ + __WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \ + __WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \ + __WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \ + __WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \ + __WASI_RIGHT_SOCK_SEND_TO) + + +// Block and character device interaction is outside the scope of +// CloudABI. Simply allow everything. +#define RIGHTS_BLOCK_DEVICE_BASE RIGHTS_ALL +#define RIGHTS_BLOCK_DEVICE_INHERITING RIGHTS_ALL +#define RIGHTS_CHARACTER_DEVICE_BASE RIGHTS_ALL +#define RIGHTS_CHARACTER_DEVICE_INHERITING RIGHTS_ALL + +// Only allow directory operations on directories. Directories can only +// yield file descriptors to other directories and files. +#define RIGHTS_DIRECTORY_BASE \ + (__WASI_RIGHT_FD_FDSTAT_SET_FLAGS | __WASI_RIGHT_FD_SYNC | \ + __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_PATH_CREATE_DIRECTORY | \ + __WASI_RIGHT_PATH_CREATE_FILE | __WASI_RIGHT_PATH_LINK_SOURCE | \ + __WASI_RIGHT_PATH_LINK_TARGET | __WASI_RIGHT_PATH_OPEN | \ + __WASI_RIGHT_FD_READDIR | __WASI_RIGHT_PATH_READLINK | \ + __WASI_RIGHT_PATH_RENAME_SOURCE | __WASI_RIGHT_PATH_RENAME_TARGET | \ + __WASI_RIGHT_PATH_FILESTAT_GET | \ + __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \ + __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \ + __WASI_RIGHT_POLL_FD_READWRITE) +#define RIGHTS_DIRECTORY_INHERITING \ + (RIGHTS_DIRECTORY_BASE | RIGHTS_REGULAR_FILE_BASE) + +// Operations that apply to regular files. +#define RIGHTS_REGULAR_FILE_BASE \ + (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \ + __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \ + __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_FD_FILESTAT_SET_TIMES | __WASI_RIGHT_POLL_FD_READWRITE) +#define RIGHTS_REGULAR_FILE_INHERITING 0 + +// Operations that apply to sockets and socket pairs. +#define RIGHTS_SOCKET_BASE \ + (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \ + __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \ + __WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \ + __WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \ + __WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \ + __WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \ + __WASI_RIGHT_SOCK_SEND_TO) +#define RIGHTS_SOCKET_INHERITING RIGHTS_ALL + +// Operations that apply to TTYs. +#define RIGHTS_TTY_BASE \ + (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \ + __WASI_RIGHT_POLL_FD_READWRITE) +#define RIGHTS_TTY_INHERITING 0 + +/* clang-format on */ + +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h new file mode 100644 index 000000000..7f6e9b941 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -0,0 +1,143 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef SSP_CONFIG_H +#define SSP_CONFIG_H + +#include "gnuc.h" +#include <stdlib.h> + +#if defined(__FreeBSD__) || defined(__APPLE__) \ + || (defined(ANDROID) && __ANDROID_API__ < 28) +#define CONFIG_HAS_ARC4RANDOM_BUF 1 +#else +#define CONFIG_HAS_ARC4RANDOM_BUF 0 +#endif + +// On Linux, prefer to use getrandom, though it isn't available in +// GLIBC before 2.25. +#if (defined(__linux__) || defined(ESP_PLATFORM)) \ + && (!defined(__GLIBC__) || __GLIBC__ > 2 \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +#define CONFIG_HAS_GETRANDOM 1 +#else +#define CONFIG_HAS_GETRANDOM 0 +#endif + +#if defined(__CloudABI__) +#define CONFIG_HAS_CAP_ENTER 1 +#else +#define CONFIG_HAS_CAP_ENTER 0 +#endif + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__) \ + && !defined(ESP_PLATFORM) && !defined(DISABLE_CLOCK_NANOSLEEP) +#define CONFIG_HAS_CLOCK_NANOSLEEP 1 +#else +#define CONFIG_HAS_CLOCK_NANOSLEEP 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) + */ +#ifndef __NuttX__ +#ifndef __CloudABI__ +#define CONFIG_HAS_ISATTY 1 +#else +#define CONFIG_HAS_ISATTY 0 +#endif +#endif + +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#define CONFIG_HAS_POSIX_FALLOCATE 1 +#else +#define CONFIG_HAS_POSIX_FALLOCATE 0 +#endif + +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#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 +#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0 +#endif + +#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) +#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1 +#else +#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0 +#endif + +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#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 + +#ifdef __APPLE__ +#define CONFIG_TLS_USE_GSBASE 1 +#else +#define CONFIG_TLS_USE_GSBASE 0 +#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 */ +#if defined(__clang__) +/* Clang provides stdatomic.h since 3.6.0 +See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */ +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) +#define CONFIG_HAS_STD_ATOMIC 1 +#else +#define CONFIG_HAS_STD_ATOMIC 0 +#endif +#elif defined(__GNUC_PREREQ) +/* Even though older versions of GCC support C11, atomics were +not implemented until 4.9. See +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */ +#if __GNUC_PREREQ(4, 9) +#define CONFIG_HAS_STD_ATOMIC 1 +#else /* else of __GNUC_PREREQ(4, 9) */ +#define CONFIG_HAS_STD_ATOMIC 0 +#endif /* end of __GNUC_PREREQ(4, 9) */ +#else /* else of defined(__GNUC_PREREQ) */ +#define CONFIG_HAS_STD_ATOMIC 1 +#endif /* end of defined(__GNUC_PREREQ) */ +#else /* else of !defined(BH_PLATFORM_LINUX_SGX) */ +#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/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c new file mode 100644 index 000000000..858d8d5e4 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c @@ -0,0 +1,47 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#include "ssp_config.h" +#include "bh_platform.h" +#include "str.h" + +static char * +bh_strndup(const char *s, size_t n) +{ + size_t l = strnlen(s, n); + char *s1 = wasm_runtime_malloc((uint32)(l + 1)); + + if (!s1) + return NULL; + bh_memcpy_s(s1, (uint32)(l + 1), s, (uint32)l); + s1[l] = 0; + return s1; +} + +char * +str_nullterminate(const char *s, size_t len) +{ + /* Copy string */ + char *ret = bh_strndup(s, len); + + if (ret == NULL) + return NULL; + + /* Ensure that it contains no null bytes within */ + if (strlen(ret) != len) { + wasm_runtime_free(ret); + errno = EILSEQ; + return NULL; + } + return ret; +} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h new file mode 100644 index 000000000..7d633e5c8 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h @@ -0,0 +1,22 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef STR_H +#define STR_H + +#include "ssp_config.h" + +char * +str_nullterminate(const char *, size_t); + +#endif |