summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives')
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE7
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE121
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h1508
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h265
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c4072
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h89
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h98
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c98
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h21
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h139
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h100
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h143
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h22
17 files changed, 6782 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c b/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/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h b/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/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