From 8a2078aa9027daa863dc0a3603a1afedd5836cb8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 31 Oct 2021 01:06:27 +0000 Subject: [PATCH] Add `core:sys/wasi` --- core/sys/wasi/wasi.odin | 1819 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1819 insertions(+) create mode 100644 core/sys/wasi/wasi.odin diff --git a/core/sys/wasi/wasi.odin b/core/sys/wasi/wasi.odin new file mode 100644 index 000000000..fde7601a2 --- /dev/null +++ b/core/sys/wasi/wasi.odin @@ -0,0 +1,1819 @@ +//+build wasm32 +package sys_wasi + +foreign import "env" + +DIRCOOKIE_START :: u64(0) +size_t :: uint + +filesize_t :: distinct u64 +timestamp_t :: distinct u64 + +clockid_t :: distinct u32 +CLOCK_MONOTONIC :: clockid_t(0) +CLOCK_PROCESS_CPUTIME_ID :: clockid_t(1) +CLOCK_REALTIME :: clockid_t(2) +CLOCK_THREAD_CPUTIME_ID :: clockid_t(3) + +errno_t :: enum u16 { + // No error occurred. System call completed successfully. + SUCCESS = 0, + // Argument list too long. + TOOBIG = 1, + // Permission denied. + ACCESS = 2, + // Address in use. + ADDRINUSE = 3, + // Address not available. + ADDRNOTAVAIL = 4, + // Address family not supported. + AFNOSUPPORT = 5, + // Resource unavailable, or operation would block. + AGAIN = 6, + // Connection already in progress. + ALREADY = 7, + // Bad file descriptor. + BADF = 8, + // Bad message. + BADMSG = 9, + // Device or resource busy. + BUSY = 10, + // Operation canceled. + CANCELED = 11, + // No child processes. + CHILD = 12, + // Connection aborted. + CONNABORTED = 13, + // Connection refused. + CONNREFUSED = 14, + // Connection reset. + CONNRESET = 15, + // Resource deadlock would occur. + DEADLK = 16, + // Destination address required. + DESTADDRREQ = 17, + // Mathematics argument out of domain of function. + DOM = 18, + // Reserved. + DQUOT = 19, + // File exists. + EXIST = 20, + // Bad address. + FAULT = 21, + // File too large. + FBIG = 22, + // Host is unreachable. + HOSTUNREACH = 23, + // Identifier removed. + IDRM = 24, + // Illegal byte sequence. + ILSEQ = 25, + // Operation in progress. + INPROGRESS = 26, + // Interrupted function. + INTR = 27, + // Invalid argument. + INVAL = 28, + // I/O error. + IO = 29, + // Socket is connected. + ISCONN = 30, + // Is a directory. + ISDIR = 31, + // Too many levels of symbolic links. + LOOP = 32, + // File descriptor value too large. + MFILE = 33, + // Too many links. + MLINK = 34, + // Message too large. + MSGSIZE = 35, + // Reserved. + MULTIHOP = 36, + // Filename too long. + NAMETOOLONG = 37, + // Network is down. + NETDOWN = 38, + // Connection aborted by network. + NETRESET = 39, + // Network unreachable. + NETUNREACH = 40, + // Too many files open in system. + NFILE = 41, + // No buffer space available. + NOBUFS = 42, + // No such device. + NODEV = 43, + // No such file or directory. + NOENT = 44, + // Executable file format error. + NOEXEC = 45, + // No locks available. + NOLCK = 46, + // Reserved. + NOLINK = 47, + // Not enough space. + NOMEM = 48, + // No message of the desired type. + NOMSG = 49, + // Protocol not available. + NOPROTOOPT = 50, + // No space left on device. + NOSPC = 51, + // Function not supported. + NOSYS = 52, + // The socket is not connected. + NOTCONN = 53, + // Not a directory or a symbolic link to a directory. + NOTDIR = 54, + // Directory not empty. + NOTEMPTY = 55, + // State not recoverable. + NOTRECOVERABLE = 56, + // Not a socket. + NOTSOCK = 57, + // Not supported, or operation not supported on socket. + NOTSUP = 58, + // Inappropriate I/O control operation. + NOTTY = 59, + // No such device or address. + NXIO = 60, + // Value too large to be stored in data type. + OVERFLOW = 61, + // Previous owner died. + OWNERDEAD = 62, + // Operation not permitted. + PERM = 63, + // Broken pipe. + PIPE = 64, + // Protocol error. + PROTO = 65, + // Protocol not supported. + PROTONOSUPPORT = 66, + // Protocol wrong type for socket. + PROTOTYPE = 67, + // Result too large. + RANGE = 68, + // Read-only file system. + ROFS = 69, + // Invalid seek. + SPIPE = 70, + // No such process. + SRCH = 71, + // Reserved. + STALE = 72, + // Connection timed out. + TIMEDOUT = 73, + // Text file busy. + TXTBSY = 74, + // Cross-device link. + XDEV = 75, + // Extension: Capabilities insufficient. + NOTCAPABLE = 76, +} + + +rights_flag_t :: enum u64 { + /** + * The right to invoke `fd_datasync`. + * If `path_open` is set, includes the right to invoke + * `path_open` with `fdflags::dsync`. + */ + FD_DATASYNC = 0, + + /** + * The right to invoke `fd_read` and `sock_recv`. + * If `rights::fd_seek` is set, includes the right to invoke `fd_pread`. + */ + FD_READ = 1, + + /** + * The right to invoke `fd_seek`. This flag implies `rights::fd_tell`. + */ + FD_SEEK = 2, + + /** + * The right to invoke `fd_fdstat_set_flags`. + */ + FD_FDSTAT_SET_FLAGS = 3, + + /** + * The right to invoke `fd_sync`. + * If `path_open` is set, includes the right to invoke + * `path_open` with `fdflags::rsync` and `fdflags::dsync`. + */ + FD_SYNC = 4, + + /** + * The right to invoke `fd_seek` in such a way that the file offset + * remains unaltered (i.e., `whence::cur` with offset zero), or to + * invoke `fd_tell`. + */ + FD_TELL = 5, + + /** + * The right to invoke `fd_write` and `sock_send`. + * If `rights::fd_seek` is set, includes the right to invoke `fd_pwrite`. + */ + FD_WRITE = 6, + + /** + * The right to invoke `fd_advise`. + */ + FD_ADVISE = 7, + + /** + * The right to invoke `fd_allocate`. + */ + FD_ALLOCATE = 8, + + /** + * The right to invoke `path_create_directory`. + */ + PATH_CREATE_DIRECTORY = 9, + + /** + * If `path_open` is set, the right to invoke `path_open` with `oflags::creat`. + */ + PATH_CREATE_FILE = 10, + + /** + * The right to invoke `path_link` with the file descriptor as the + * source directory. + */ + PATH_LINK_SOURCE = 11, + + /** + * The right to invoke `path_link` with the file descriptor as the + * target directory. + */ + PATH_LINK_TARGET = 12, + + /** + * The right to invoke `path_open`. + */ + PATH_OPEN = 13, + + /** + * The right to invoke `fd_readdir`. + */ + FD_READDIR = 14, + + /** + * The right to invoke `path_readlink`. + */ + PATH_READLINK = 15, + + /** + * The right to invoke `path_rename` with the file descriptor as the source directory. + */ + PATH_RENAME_SOURCE = 16, + + /** + * The right to invoke `path_rename` with the file descriptor as the target directory. + */ + PATH_RENAME_TARGET = 17, + + /** + * The right to invoke `path_filestat_get`. + */ + PATH_FILESTAT_GET = 18, + + /** + * The right to change a file's size (there is no `path_filestat_set_size`). + * If `path_open` is set, includes the right to invoke `path_open` with `oflags::trunc`. + */ + PATH_FILESTAT_SET_SIZE = 19, + + /** + * The right to invoke `path_filestat_set_times`. + */ + PATH_FILESTAT_SET_TIMES = 20, + + /** + * The right to invoke `fd_filestat_get`. + */ + FD_FILESTAT_GET = 21, + + /** + * The right to invoke `fd_filestat_set_size`. + */ + FD_FILESTAT_SET_SIZE = 22, + + /** + * The right to invoke `fd_filestat_set_times`. + */ + FD_FILESTAT_SET_TIMES = 23, + + /** + * The right to invoke `path_symlink`. + */ + PATH_SYMLINK = 24, + + /** + * The right to invoke `path_remove_directory`. + */ + PATH_REMOVE_DIRECTORY = 25, + + /** + * The right to invoke `path_unlink_file`. + */ + PATH_UNLINK_FILE = 26, + + /** + * If `rights::fd_read` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_read`. + * If `rights::fd_write` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_write`. + */ + POLL_FD_READWRITE = 27, + + /** + * The right to invoke `sock_shutdown`. + */ + SOCK_SHUTDOWN = 28, +} + +rights_t :: distinct bit_set[rights_flag_t; u64] + + +fd_t :: distinct i32 + +// iovec_t :: struct { +// buf: [^]u8, +// buf_len: size_t, +// } +// ciovec_t :: struct { +// buf: [^]u8, +// buf_len: size_t, +// } +iovec_t :: distinct []byte +ciovec_t :: distinct []byte + + +filedelta_t :: distinct i64 + +whence_t :: enum u8 { + SET = 0, + CUR = 1, + END = 2, +} + +dircookie_t :: distinct u64 +dirnamlen_t :: distinct u32 +inode_t :: distinct u64 + +filetype_t :: enum u8 { + /** + * The type of the file descriptor or file is unknown or is different from any of the other types specified. + */ + UNKNOWN = 0, + + /** + * The file descriptor or file refers to a block device inode. + */ + BLOCK_DEVICE = 1, + + /** + * The file descriptor or file refers to a character device inode. + */ + CHARACTER_DEVICE = 2, + + /** + * The file descriptor or file refers to a directory inode. + */ + DIRECTORY = 3, + + /** + * The file descriptor or file refers to a regular file inode. + */ + REGULAR_FILE = 4, + + /** + * The file descriptor or file refers to a datagram socket. + */ + SOCKET_DGRAM = 5, + + /** + * The file descriptor or file refers to a byte-stream socket. + */ + SOCKET_STREAM = 6, + + /** + * The file refers to a symbolic link inode. + */ + SYMBOLIC_LINK = 7, +} + +dirent_t :: struct { + d_next: dircookie_t, + d_ino: inode_t, + d_namlen: dirnamlen_t, + d_type: filetype_t, +} + +advice_t :: enum u8 { + /** + * The application has no advice to give on its behavior with respect to the specified data. + */ + NORMAL = 0, + + /** + * The application expects to access the specified data sequentially from lower offsets to higher offsets. + */ + SEQUENTIAL = 1, + + /** + * The application expects to access the specified data in a random order. + */ + RANDOM = 2, + + /** + * The application expects to access the specified data in the near future. + */ + WILLNEED = 3, + + /** + * The application expects that it will not access the specified data in the near future. + */ + DONTNEED = 4, + + /** + * The application expects to access the specified data once and then not reuse it thereafter. + */ + NOREUSE = 5, +} + +fdflags_t :: distinct bit_set[fdflag_t; u16] +fdflag_t :: enum u16 { + /** + * Append mode: Data written to the file is always appended to the file's end. + */ + APPEND = 0, + + /** + * Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. + */ + DSYNC = 1, + + /** + * Non-blocking mode. + */ + NONBLOCK = 2, + + /** + * Synchronized read I/O operations. + */ + RSYNC = 3, + + /** + * Write according to synchronized I/O file integrity completion. In + * addition to synchronizing the data stored in the file, the implementation + * may also synchronously update the file's metadata. + */ + SYNC = 4, +} + +fdstat_t :: struct { + /** + * File type. + */ + fs_filetype: filetype_t, + + /** + * File descriptor flags. + */ + fs_flags: fdflags_t, + + /** + * Rights that apply to this file descriptor. + */ + fs_rights_base: rights_t, + + /** + * Maximum set of rights that may be installed on new file descriptors that + * are created through this file descriptor, e.g., through `path_open`. + */ + fs_rights_inheriting: rights_t, +} + +device_t :: distinct u64 + + +fstflags_t :: distinct bit_set[fstflag_t; u16] +fstflag_t :: enum u16 { + /** + * Adjust the last data access timestamp to the value stored in `filestat::atim`. + */ + ATIM = 0, + + /** + * Adjust the last data access timestamp to the time of clock `clockid::realtime`. + */ + ATIM_NOW = 1, + + /** + * Adjust the last data modification timestamp to the value stored in `filestat::mtim`. + */ + MTIM = 2, + + /** + * Adjust the last data modification timestamp to the time of clock `clockid::realtime`. + */ + MTIM_NOW = 3, + +} + +lookupflags_t :: distinct bit_set[lookupflag_t; u32] +lookupflag_t :: enum u32 { + /** + * As long as the resolved path corresponds to a symbolic link, it is expanded. + */ + SYMLINK_FOLLOW = 0, +} + +oflags_t :: distinct bit_set[oflag_t; u16] +oflag_t :: enum u16 { + /** + * Create file if it does not exist. + */ + CREATE = 0, + + /** + * Fail if not a directory. + */ + DIRECTORY = 1, + + /** + * Fail if file already exists. + */ + EXCL = 2, + + /** + * Truncate file to size 0. + */ + TRUNC = 3, +} + +linkcount_t :: distinct u64 + +filestat_t :: struct { + /** + * Device ID of device containing the file. + */ + dev: device_t, + + /** + * File serial number. + */ + ino: inode_t, + + /** + * File type. + */ + filetype: filetype_t, + + /** + * Number of hard links to the file. + */ + nlink: linkcount_t, + + /** + * For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. + */ + size: filesize_t, + + /** + * Last data access timestamp. + */ + atim: timestamp_t, + + /** + * Last data modification timestamp. + */ + mtim: timestamp_t, + + /** + * Last file status change timestamp. + */ + ctim: timestamp_t, +} + +userdata_t :: distinct u64 + +eventtype_t :: enum u8 { + /** + * The time value of clock `subscription_clock::id` has + * reached timestamp `subscription_clock::timeout`. + */ + CLOCK = 0, + + /** + * File descriptor `subscription_fd_readwrite::file_descriptor` has data + * available for reading. This event always triggers for regular files. + */ + FD_READ = 1, + + /** + * File descriptor `subscription_fd_readwrite::file_descriptor` has capacity + * available for writing. This event always triggers for regular files. + */ + FD_WRITE = 2, +} + +eventrwflags_t :: distinct bit_set[eventrwflag_t; u16] +eventrwflag_t :: enum u16 { + /** + * The peer of this socket has closed or disconnected. + */ + FD_READWRITE_HANGUP = 0, +} + +event_fd_readwrite_t :: struct { + /** + * The number of bytes available for reading or writing. + */ + nbytes: filesize_t, + + /** + * The state of the file descriptor. + */ + flags: eventrwflags_t, +} + +event_t :: struct { + /** + * User-provided value that got attached to `subscription::userdata`. + */ + userdata: userdata_t, + + /** + * If non-zero, an error that occurred while processing the subscription request. + */ + error: errno_t, + + /** + * The type of event that occured + */ + type: eventtype_t, + + /** + * The contents of the event, if it is an `eventtype::fd_read` or + * `eventtype::fd_write`. `eventtype::clock` events ignore this field. + */ + fd_readwrite: event_fd_readwrite_t, +} + +subclockflags_t :: distinct bit_set[subclockflag_t; u16] +subclockflag_t :: enum u16 { + /** + * If set, treat the timestamp provided in + * `subscription_clock::timeout` as an absolute timestamp of clock + * `subscription_clock::id`. If clear, treat the timestamp + * provided in `subscription_clock::timeout` relative to the + * current time value of clock `subscription_clock::id`. + */ + SUBSCRIPTION_CLOCK_ABSTIME = 0, + +} + +subscription_clock_t :: struct { + /** + * The clock against which to compare the timestamp. + */ + id: clockid_t, + + /** + * The absolute or relative timestamp. + */ + timeout: timestamp_t, + + /** + * The amount of time that the implementation may wait additionally + * to coalesce with other events. + */ + precision: timestamp_t, + + /** + * Flags specifying whether the timeout is absolute or relative + */ + flags: subclockflags_t, +} + +subscription_fd_readwrite_t :: struct { + /** + * The file descriptor on which to wait for it to become ready for reading or writing. + */ + file_descriptor: fd_t, +} + +subscription_t :: struct { + /** + * User-provided value that is attached to the subscription in the + * implementation and returned through `event::userdata`. + */ + userdata: userdata_t, + + /** + * The type of the event to which to subscribe, and its contents + */ + using contents: struct { + tag: u8, + using u: struct #raw_union { + clock: subscription_clock_t, + fd_read: subscription_fd_readwrite_t, + fd_write: subscription_fd_readwrite_t, + }, + }, +} + +exitcode_t :: distinct u32 + +signal_t :: enum u8 { + /** + * No signal. Note that POSIX has special semantics for `kill(pid, 0)`, + * so this value is reserved. + */ + NONE = 0, + + /** + * Hangup. + * Action: Terminates the process. + */ + HUP = 1, + + /** + * Terminate interrupt signal. + * Action: Terminates the process. + */ + INT = 2, + + /** + * Terminal quit signal. + * Action: Terminates the process. + */ + QUIT = 3, + + /** + * Illegal instruction. + * Action: Terminates the process. + */ + ILL = 4, + + /** + * Trace/breakpoint trap. + * Action: Terminates the process. + */ + TRAP = 5, + + /** + * Process abort signal. + * Action: Terminates the process. + */ + ABRT = 6, + + /** + * Access to an undefined portion of a memory object. + * Action: Terminates the process. + */ + BUS = 7, + + /** + * Erroneous arithmetic operation. + * Action: Terminates the process. + */ + FPE = 8, + + /** + * Kill. + * Action: Terminates the process. + */ + KILL = 9, + + /** + * User-defined signal 1. + * Action: Terminates the process. + */ + USR1 = 10, + + /** + * Invalid memory reference. + * Action: Terminates the process. + */ + SEGV = 11, + + /** + * User-defined signal 2. + * Action: Terminates the process. + */ + USR2 = 12, + + /** + * Write on a pipe with no one to read it. + * Action: Ignored. + */ + PIPE = 13, + + /** + * Alarm clock. + * Action: Terminates the process. + */ + ALRM = 14, + + /** + * Termination signal. + * Action: Terminates the process. + */ + TERM = 15, + + /** + * Child process terminated, stopped, or continued. + * Action: Ignored. + */ + CHLD = 16, + + /** + * Continue executing, if stopped. + * Action: Continues executing, if stopped. + */ + CONT = 17, + + /** + * Stop executing. + * Action: Stops executing. + */ + STOP = 18, + + /** + * Terminal stop signal. + * Action: Stops executing. + */ + TSTP = 19, + + /** + * Background process attempting read. + * Action: Stops executing. + */ + TTIN = 20, + + /** + * Background process attempting write. + * Action: Stops executing. + */ + TTOU = 21, + + /** + * High bandwidth data is available at a socket. + * Action: Ignored. + */ + URG = 22, + + /** + * CPU time limit exceeded. + * Action: Terminates the process. + */ + XCPU = 23, + + /** + * File size limit exceeded. + * Action: Terminates the process. + */ + XFSZ = 24, + + /** + * Virtual timer expired. + * Action: Terminates the process. + */ + VTALRM = 25, + + /** + * Profiling timer expired. + * Action: Terminates the process. + */ + PROF = 26, + + /** + * Window changed. + * Action: Ignored. + */ + WINCH = 27, + + /** + * I/O possible. + * Action: Terminates the process. + */ + POLL = 28, + + /** + * Power failure. + * Action: Terminates the process. + */ + PWR = 29, + + /** + * Bad system call. + * Action: Terminates the process. + */ + SYS = 30, +} + + +riflags_t :: distinct bit_set[riflag_t; u16] +riflag_t :: enum u16 { + /** + * Returns the message without removing it from the socket's receive queue. + */ + RECV_PEEK = 0, + + /** + * On byte-stream sockets, block until the full amount of data can be returned. + */ + RECV_WAITALL = 1, +} + +roflags_t :: distinct bit_set[roflag_t; u16] +roflag_t :: enum u16 { + /** + * Returned by `sock_recv`: Message data has been truncated. + */ + RECV_DATA_TRUNCATED = 0, +} + +siflags_t :: distinct bit_set[siflag_t; u16] +siflag_t :: enum u16 { +} + + +sdflags_t :: distinct bit_set[sdflag_t; u8] +sdflag_t :: enum u8 { + /** + * Disables further receive operations. + */ + RD = 0, + + /** + * Disables further send operations. + */ + WR = 1, +} + +preopentype_t :: enum u8 { + DIR = 0, +} + +prestat_dir_t :: struct { + pr_name_len: size_t, +} + +prestat_t :: struct { + tag: u8, + using u: struct { + dir: prestat_dir_t, + }, +} + +@(link_prefix="__wasi_") +foreign env { + /** + * Read command-line argument data. + * The size of the array should match that returned by `args_sizes_get` + */ + args_get :: proc( + argv: [^]cstring, + argv_buf: [^]byte, + ) -> errno_t --- + /** + * Read environment variable data. + * The sizes of the buffers should match that returned by `environ_sizes_get`. + */ + environ_get :: proc( + environ: [^]cstring, + environ_buf: [^]byte, + ) -> errno_t --- + /** + * Provide file advisory information on a file descriptor. + * Note: This is similar to `posix_fadvise` in POSIX. + */ + fd_advise :: proc( + fd: fd_t, + /** + * The offset within the file to which the advisory applies. + */ + offset: filesize_t, + /** + * The length of the region to which the advisory applies. + */ + len: filesize_t, + /** + * The advice. + */ + advice: advice_t, + ) -> errno_t --- + /** + * Force the allocation of space in a file. + * Note: This is similar to `posix_fallocate` in POSIX. + */ + fd_allocate :: proc( + fd: fd_t, + /** + * The offset at which to start the allocation. + */ + offset: filesize_t, + /** + * The length of the area that is allocated. + */ + len: filesize_t, + ) -> errno_t --- + /** + * Close a file descriptor. + * Note: This is similar to `close` in POSIX. + */ + fd_close :: proc( + fd: fd_t, + ) -> errno_t --- + /** + * Synchronize the data of a file to disk. + * Note: This is similar to `fdatasync` in POSIX. + */ + fd_datasync :: proc( + fd: fd_t, + ) -> errno_t --- + /** + * Adjust the flags associated with a file descriptor. + * Note: This is similar to `fcntl(fd, F_SETFL, flags)` in POSIX. + */ + fd_fdstat_set_flags :: proc( + fd: fd_t, + /** + * The desired values of the file descriptor flags. + */ + flags: fdflags_t, + ) -> errno_t --- + /** + * Adjust the rights associated with a file descriptor. + * This can only be used to remove rights, and returns `errno::notcapable` if called in a way that would attempt to add rights + */ + fd_fdstat_set_rights :: proc( + fd: fd_t, + /** + * The desired rights of the file descriptor. + */ + fs_rights_base: rights_t, + fs_rights_inheritin: rights_t, + ) -> errno_t --- + /** + * Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. + * Note: This is similar to `ftruncate` in POSIX. + */ + fd_filestat_set_size :: proc( + fd: fd_t, + /** + * The desired file size. + */ + size: filesize_t, + ) -> errno_t --- + /** + * Adjust the timestamps of an open file or directory. + * Note: This is similar to `futimens` in POSIX. + */ + fd_filestat_set_times :: proc( + fd: fd_t, + /** + * The desired values of the data access timestamp. + */ + atim: timestamp_t, + /** + * The desired values of the data modification timestamp. + */ + mtim: timestamp_t, + /** + * A bitmask indicating which timestamps to adjust. + */ + fst_flags: fstflags_t, + ) -> errno_t --- + /** + * Return a description of the given preopened file descriptor. + */ + fd_prestat_dir_name :: proc( + fd: fd_t, + /** + * A buffer into which to write the preopened directory name. + */ + path: [^]u8, + path_len: size_t, + ) -> errno_t --- + /** + * Atomically replace a file descriptor by renumbering another file descriptor. + * Due to the strong focus on thread safety, this environment does not provide + * a mechanism to duplicate or renumber a file descriptor to an arbitrary + * number, like `dup2()`. This would be prone to race conditions, as an actual + * file descriptor with the same number could be allocated by a different + * thread at the same time. + * This function provides a way to atomically renumber file descriptors, which + * would disappear if `dup2()` were to be removed entirely. + */ + fd_renumber :: proc( + fd: fd_t, + /** + * The file descriptor to overwrite. + */ + to: fd_t, + ) -> errno_t --- + /** + * Synchronize the data and metadata of a file to disk. + * Note: This is similar to `fsync` in POSIX. + */ + fd_sync :: proc( + f: fd_t, + ) -> errno_t --- + /** + * Create a directory. + * Note: This is similar to `mkdirat` in POSIX. + */ + path_create_directory :: proc( + fd: fd_t, + /** + * The path at which to create the directory. + */ + path: cstring, + ) -> errno_t --- + /** + * Adjust the timestamps of a file or directory. + * Note: This is similar to `utimensat` in POSIX. + */ + path_filestat_set_times :: proc( + fd: fd_t, + /** + * Flags determining the method of how the path is resolved. + */ + flags: lookupflags_t, + /** + * The path of the file or directory to operate on. + */ + path: cstring, + /** + * The desired values of the data access timestamp. + */ + atim: timestamp_t, + /** + * The desired values of the data modification timestamp. + */ + mtim: timestamp_t, + /** + * A bitmask indicating which timestamps to adjust. + */ + fst_flags: fstflags_t, + ) -> errno_t --- + /** + * Create a hard link. + * Note: This is similar to `linkat` in POSIX. + */ + path_link :: proc( + old_fd: fd_t, + /** + * Flags determining the method of how the path is resolved. + */ + old_flags: lookupflags_t, + /** + * The source path from which to link. + */ + old_path: cstring, + /** + * The working directory at which the resolution of the new path starts. + */ + new_fd: fd_t, + /** + * The destination path at which to create the hard link. + */ + new_path: cstring, + ) -> errno_t --- + /** + * Remove a directory. + * Return `errno::notempty` if the directory is not empty. + * Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + */ + path_remove_directory :: proc( + fd: fd_t, + /** + * The path to a directory to remove. + */ + path: cstring, + ) -> errno_t --- + /** + * Rename a file or directory. + * Note: This is similar to `renameat` in POSIX. + */ + path_rename :: proc( + fd: fd_t, + /** + * The source path of the file or directory to rename. + */ + old_path: cstring, + /** + * The working directory at which the resolution of the new path starts. + */ + new_fd: fd_t, + /** + * The destination path to which to rename the file or directory. + */ + new_path: cstring, + ) -> errno_t --- + /** + * Create a symbolic link. + * Note: This is similar to `symlinkat` in POSIX. + */ + path_symlink :: proc( + /** + * The contents of the symbolic link. + */ + old_path: cstring, + fd: fd_t, + /** + * The destination path at which to create the symbolic link. + */ + new_path: cstring, + ) -> errno_t --- + /** + * Unlink a file. + * Return `errno::isdir` if the path refers to a directory. + * Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + */ + path_unlink_file :: proc( + fd: fd_t, + /** + * The path to a file to unlink. + */ + path: cstring, + ) -> errno_t --- + /** + * Terminate the process normally. An exit code of 0 indicates successful + * termination of the program. The meanings of other values is dependent on + * the environment. + */ + proc_exit :: proc( + /** + * The exit code returned by the process. + */ + rval: exitcode_t, + ) -> ! --- + /** + * Send a signal to the process of the calling thread. + * Note: This is similar to `raise` in POSIX. + */ + proc_raise :: proc( + /** + * The signal condition to trigger. + */ + sig: signal_t, + ) -> errno_t --- + /** + * Temporarily yield execution of the calling thread. + * Note: This is similar to `sched_yield` in POSIX. + */ + sched_yield :: proc() -> errno_t --- + /** + * Write high-quality random data into a buffer. + * This function blocks when the implementation is unable to immediately + * provide sufficient high-quality random data. + * This function may execute slowly, so when large mounts of random data are + * required, it's advisable to use this function to seed a pseudo-random + * number generator, rather than to provide the random data directly. + */ + random_get :: proc( + /** + * The buffer to fill with random data. + */ + buf: [^]u8, + buf_len: size_t, + ) -> errno_t --- + /** + * Shut down socket send and receive channels. + * Note: This is similar to `shutdown` in POSIX. + */ + sock_shutdown :: proc( + fd: fd_t, + /** + * Which channels on the socket to shut down. + */ + how: sdflags_t, + ) -> errno_t --- +} + + +foreign env { + __wasi_args_sizes_get :: proc( + retptr0: ^size_t, + retptr1: ^size_t, + ) -> errno_t --- + __wasi_environ_sizes_get :: proc( + retptr0: ^size_t, + retptr1: ^size_t, + ) -> errno_t --- + __wasi_clock_res_get :: proc( + id: clockid_t, + retptr0: ^timestamp_t, + ) -> errno_t --- + __wasi_clock_time_get :: proc( + id: clockid_t, + precision: timestamp_t, + retptr0: ^timestamp_t, + ) -> errno_t --- + __wasi_fd_fdstat_get :: proc( + fd: fd_t, + retptr0: ^fdstat_t, + ) -> errno_t --- + __wasi_fd_filestat_get :: proc( + fd: fd_t, + retptr0: ^filestat_t, + ) -> errno_t --- + + + __wasi_fd_pread :: proc( + fd: fd_t, + iovs: [^]iovec_t, + iovs_len: size_t, + offset: filesize_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_fd_prestat_get :: proc( + fd: fd_t, + retptr0: ^prestat_t, + ) -> errno_t --- + __wasi_fd_pwrite :: proc( + fd: fd_t, + iovs: [^]ciovec_t, + iovs_len: size_t, + offset: filesize_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_fd_read :: proc( + fd: fd_t, + iovs: [^]iovec_t, + iovs_len: size_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_fd_readdir :: proc( + fd: fd_t, + buf: [^]u8, + buf_len: size_t, + cookie: dircookie_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_fd_seek :: proc( + fd: fd_t, + offset: filedelta_t, + whence: whence_t, + retptr0: ^filesize_t, + ) -> errno_t --- + __wasi_fd_tell :: proc( + fd: fd_t, + retptr0: ^filesize_t, + ) -> errno_t --- + __wasi_fd_write :: proc( + fd: fd_t, + iovs: [^]ciovec_t, + iovs_len: size_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_path_filestat_get :: proc( + fd: fd_t, + flags: lookupflags_t, + /** + * The path of the file or directory to inspect. + */ + path: cstring, + retptr0: ^filestat_t, + ) -> errno_t --- + __wasi_path_open :: proc( + fd: fd_t, + dirflags: lookupflags_t, + path: cstring, + oflags: oflags_t, + fs_rights_base: rights_t, + fs_rights_inheriting: rights_t, + fdflags: fdflags_t, + retptr: ^fd_t, + ) -> errno_t --- + __wasi_path_readlink :: proc( + fd: fd_t, + path: cstring, + buf: [^]u8, + buf_len: size_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_poll_oneoff :: proc( + subscription_in: ^subscription_t, + event_out: ^event_t, + nsubscriptions: size_t, + retptr0: ^size_t, + ) -> errno_t --- + __wasi_sock_recv :: proc( + fd: fd_t, + ri_data: [^]iovec_t, + ri_data_len: size_t, + ri_flags: riflags_t, + retptr0: ^size_t, + retptr1: ^roflags_t, + ) -> errno_t --- + __wasi_sock_send :: proc( + fd: fd_t, + si_data: [^]ciovec_t, + si_data_len: size_t, + si_flags: siflags_t, + retptr0: ^size_t, + ) -> errno_t --- +} + +/** + * Return command-line argument data sizes. + * @return + * Returns the number of arguments and the size of the argument string + * data, or an error. + */ +args_sizes_get :: proc() -> (num_args, size_of_args: size_t, err: errno_t) { + err = __wasi_args_sizes_get(&num_args, &size_of_args) + return +} +/** + * Return environment variable data sizes. + * @return + * Returns the number of environment variable arguments and the size of the + * environment variable data. + */ +environ_sizes_get :: proc() -> (num_envs, size_of_envs: size_t, err: errno_t) { + err = __wasi_environ_sizes_get(&num_envs, &size_of_envs) + return +} +/** + * Return the resolution of a clock. + * Implementations are required to provide a non-zero value for supported clocks. For unsupported clocks, + * return `errno::inval`. + * Note: This is similar to `clock_getres` in POSIX. + * @return + * The resolution of the clock, or an error if one happened. + */ +clock_res_get :: proc( + /** + * The clock for which to return the resolution. + */ + id: clockid_t, +) -> (ts: timestamp_t, err: errno_t) { + err = __wasi_clock_res_get(id, &ts) + return +} +/** + * Return the time value of a clock. + * Note: This is similar to `clock_gettime` in POSIX. + * @return + * The time value of the clock. + */ +clock_time_get :: proc( + /** + * The clock for which to return the time. + */ + id: clockid_t, + /** + * The maximum lag (exclusive) that the returned time value may have, compared to its actual value. + */ + precision: timestamp_t, +) -> (ts: timestamp_t, err: errno_t) { + err = __wasi_clock_time_get(id, precision, &ts) + return +} +/** + * Get the attributes of a file descriptor. + * Note: This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. + * @return + * The buffer where the file descriptor's attributes are stored. + */ +fd_fdstat_get :: proc( + fd: fd_t, +) -> (stat: fdstat_t, err: errno_t) { + err = __wasi_fd_fdstat_get(fd, &stat) + return +} +/** + * Return the attributes of an open file. + * @return + * The buffer where the file's attributes are stored. + */ +fd_filestat_get :: proc( + fd: fd_t, +) -> (stat: filestat_t, err: errno_t) { + err = __wasi_fd_filestat_get(fd, &stat) + return +} + + + + +/** + * Read from a file descriptor, without using and updating the file descriptor's offset. + * Note: This is similar to `preadv` in POSIX. + * @return + * The number of bytes read. + */ +fd_pread :: proc( + fd: fd_t, + /** + * List of scatter/gather vectors in which to store data. + */ + iovs: [^]iovec_t, + /** + * The length of the array pointed to by `iovs`. + */ + iovs_len: size_t, + /** + * The offset within the file at which to read. + */ + offset: filesize_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_fd_pread(fd, iovs, iovs_len, offset, &n) + return +} +/** + * Return a description of the given preopened file descriptor. + * @return + * The buffer where the description is stored. + */ +fd_prestat_get :: proc( + fd: fd_t, +) -> (desc: prestat_t, err: errno_t) { + err = __wasi_fd_prestat_get(fd, &desc) + return +} +/** + * Write to a file descriptor, without using and updating the file descriptor's offset. + * Note: This is similar to `pwritev` in POSIX. + * @return + * The number of bytes written. + */ +fd_pwrite :: proc( + fd: fd_t, + /** + * List of scatter/gather vectors from which to retrieve data. + */ + iovs: [^]ciovec_t, + /** + * The length of the array pointed to by `iovs`. + */ + iovs_len: size_t, + /** + * The offset within the file at which to write. + */ + offset: filesize_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_fd_pwrite(fd, iovs, iovs_len, offset, &n) + return +} +/** + * Read from a file descriptor. + * Note: This is similar to `readv` in POSIX. + * @return + * The number of bytes read. + */ +fd_read :: proc( + fd: fd_t, + /** + * List of scatter/gather vectors to which to store data. + */ + iovs: [^]iovec_t, + /** + * The length of the array pointed to by `iovs`. + */ + iovs_len: size_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_fd_read(fd, iovs, iovs_len, &n) + return +} +/** + * Read directory entries from a directory. + * When successful, the contents of the output buffer consist of a sequence of + * directory entries. Each directory entry consists of a `dirent` object, + * followed by `dirent::d_namlen` bytes holding the name of the directory + * entry. + * This function fills the output buffer as much as possible, potentially + * truncating the last directory entry. This allows the caller to grow its + * read buffer size in case it's too small to fit a single large directory + * entry, or skip the oversized directory entry. + * @return + * The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. + */ +fd_readdir :: proc( + fd: fd_t, + /** + * The buffer where directory entries are stored + */ + buf: [^]u8, + buf_len: size_t, + /** + * The location within the directory to start reading + */ + cookie: dircookie_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_fd_readdir(fd, buf, buf_len, cookie, &n) + return +} +/** + * Move the offset of a file descriptor. + * Note: This is similar to `lseek` in POSIX. + * @return + * The new offset of the file descriptor, relative to the start of the file. + */ +fd_seek :: proc( + fd: fd_t, + /** + * The number of bytes to move. + */ + offset: filedelta_t, + /** + * The base from which the offset is relative. + */ + whence: whence_t, +) -> (new_offset: filesize_t, err: errno_t) { + err = __wasi_fd_seek(fd, offset, whence, &new_offset) + return +} +/** + * Return the current offset of a file descriptor. + * Note: This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX. + * @return + * The current offset of the file descriptor, relative to the start of the file. + */ +fd_tell :: proc( + fd: fd_t, +) -> (offset: filesize_t, err: errno_t) { + err = __wasi_fd_tell(fd, &offset) + return +} +/** + * Write to a file descriptor. + * Note: This is similar to `writev` in POSIX. + */ +fd_write :: proc( + fd: fd_t, + /** + * List of scatter/gather vectors from which to retrieve data. + */ + iovs: [^]ciovec_t, + /** + * The length of the array pointed to by `iovs`. + */ + iovs_len: size_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_fd_write(fd, iovs, iovs_len, &n) + return +} +/** + * Return the attributes of a file or directory. + * Note: This is similar to `stat` in POSIX. + * @return + * The buffer where the file's attributes are stored. + */ +path_filestat_get :: proc( + fd: fd_t, + /** + * Flags determining the method of how the path is resolved. + */ + flags: lookupflags_t, + /** + * The path of the file or directory to inspect. + */ + path: cstring, +) -> (offset: filestat_t, err: errno_t) { + err = __wasi_path_filestat_get(fd, flags, path, &offset) + return +} +/** + * Open a file or directory. + * The returned file descriptor is not guaranteed to be the lowest-numbered + * file descriptor not currently open; it is randomized to prevent + * applications from depending on making assumptions about indexes, since this + * is error-prone in multi-threaded contexts. The returned file descriptor is + * guaranteed to be less than 2**31. + * Note: This is similar to `openat` in POSIX. + * @return + * The file descriptor of the file that has been opened. + */ +path_open :: proc( + fd: fd_t, + /** + * Flags determining the method of how the path is resolved. + */ + dirflags: lookupflags_t, + /** + * The relative path of the file or directory to open, relative to the + * `path_open::fd` directory. + */ + path: cstring, + /** + * The method by which to open the file. + */ + oflags: oflags_t, + /** + * The initial rights of the newly created file descriptor. The + * implementation is allowed to return a file descriptor with fewer rights + * than specified, if and only if those rights do not apply to the type of + * file being opened. + * The *base* rights are rights that will apply to operations using the file + * descriptor itself, while the *inheriting* rights are rights that apply to + * file descriptors derived from it. + */ + fs_rights_base: rights_t, + fs_rights_inheriting: rights_t, + fdflags: fdflags_t, +) -> (file: fd_t, err: errno_t) { + err = __wasi_path_open(fd, dirflags, path, oflags, fs_rights_base, fs_rights_inheriting, fdflags, &file) + return +} +/** + * Read the contents of a symbolic link. + * Note: This is similar to `readlinkat` in POSIX. + * @return + * The number of bytes placed in the buffer. + */ +path_readlink :: proc( + fd: fd_t, + /** + * The path of the symbolic link from which to read. + */ + path: cstring, + /** + * The buffer to which to write the contents of the symbolic link. + */ + buf: [^]u8, + buf_len: size_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_path_readlink(fd, path, buf, buf_len, &n) + return +} +/** + * Concurrently poll for the occurrence of a set of events. + * @return + * The number of events stored. + */ +poll_oneoff :: proc( + /** + * The events to which to subscribe. + */ + subscription_in: ^subscription_t, + /** + * The events that have occurred. + */ + event_out: ^event_t, + /** + * Both the number of subscriptions and events. + */ + nsubscriptions: size_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_poll_oneoff(subscription_in, event_out, nsubscriptions, &n) + return +} +/** + * Receive a message from a socket. + * Note: This is similar to `recv` in POSIX, though it also supports reading + * the data into multiple buffers in the manner of `readv`. + * @return + * Number of bytes stored in ri_data and message flags. + */ +sock_recv :: proc( + fd: fd_t, + /** + * List of scatter/gather vectors to which to store data. + */ + ri_data: [^]iovec_t, + /** + * The length of the array pointed to by `ri_data`. + */ + ri_data_len: size_t, + /** + * Message flags. + */ + ri_flags: riflags_t, +) -> (n: size_t, flags: roflags_t, err: errno_t) { + err = __wasi_sock_recv(fd, ri_data, ri_data_len, ri_flags, &n, &flags) + return +} +/** + * Send a message on a socket. + * Note: This is similar to `send` in POSIX, though it also supports writing + * the data from multiple buffers in the manner of `writev`. + * @return + * Number of bytes transmitted. + */ +sock_send :: proc( + fd: fd_t, + /** + * List of scatter/gather vectors to which to retrieve data + */ + si_data: [^]ciovec_t, + /** + * The length of the array pointed to by `si_data`. + */ + si_data_len: size_t, + /** + * Message flags. + */ + si_flags: siflags_t, +) -> (n: size_t, err: errno_t) { + err = __wasi_sock_send(fd, si_data, si_data_len, si_flags, &n) + return +} \ No newline at end of file