mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-08-23 07:13:44 +02:00
258 lines
11 KiB
C++
258 lines
11 KiB
C++
/*
|
|
** wasi.h
|
|
**
|
|
** This file is part of mkxp.
|
|
**
|
|
** Copyright (C) 2013 - 2021 Amaryllis Kulla <ancurio@mapleshrine.eu>
|
|
**
|
|
** mkxp is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 2 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** mkxp is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef MKXPZ_SANDBOX_WASI_H
|
|
#define MKXPZ_SANDBOX_WASI_H
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <priority_deque.hpp>
|
|
#include "filesystem.h"
|
|
#include "wasm-types.h"
|
|
#include "binding-base.h"
|
|
|
|
// WASI error numbers
|
|
#define WASI_ESUCCESS 0 // No error occurred. System call completed successfully.
|
|
#define WASI_E2BIG 1 // Argument list too long.
|
|
#define WASI_EACCES 2 // Permission denied.
|
|
#define WASI_EADDRINUSE 3 // Address in use.
|
|
#define WASI_EADDRNOTAVAIL 4 // Address not available.
|
|
#define WASI_EAFNOSUPPORT 5 // Address family not supported.
|
|
#define WASI_EAGAIN 6 // Resource unavailable, or operation would block.
|
|
#define WASI_EALREADY 7 // Connection already in progress.
|
|
#define WASI_EBADF 8 // Bad file descriptor.
|
|
#define WASI_EBADMSG 9 // Bad message.
|
|
#define WASI_EBUSY 10 // Device or resource busy.
|
|
#define WASI_ECANCELED 11 // Operation canceled.
|
|
#define WASI_ECHILD 12 // No child processes.
|
|
#define WASI_ECONNABORTED 13 // Connection aborted.
|
|
#define WASI_ECONNREFUSED 14 // Connection refused.
|
|
#define WASI_ECONNRESET 15 // Connection reset.
|
|
#define WASI_EDEADLK 16 // Resource deadlock would occur.
|
|
#define WASI_EDESTADDRREQ 17 // Destination address required.
|
|
#define WASI_EDOM 18 // Mathematics argument out of domain of function.
|
|
#define WASI_EDQUOT 19 // Reserved.
|
|
#define WASI_EEXIST 20 // File exists.
|
|
#define WASI_EFAULT 21 // Bad address.
|
|
#define WASI_EFBIG 22 // File too large.
|
|
#define WASI_EHOSTUNREACH 23 // Host is unreachable.
|
|
#define WASI_EIDRM 24 // Identifier removed.
|
|
#define WASI_EILSEQ 25 // Illegal byte sequence.
|
|
#define WASI_EINPROGRESS 26 // Operation in progress.
|
|
#define WASI_EINTR 27 // Interrupted function.
|
|
#define WASI_EINVAL 28 // Invalid argument.
|
|
#define WASI_EIO 29 // I/O error.
|
|
#define WASI_EISCONN 30 // Socket is connected.
|
|
#define WASI_EISDIR 31 // Is a directory.
|
|
#define WASI_ELOOP 32 // Too many levels of symbolic links.
|
|
#define WASI_EMFILE 33 // File descriptor value too large.
|
|
#define WASI_EMLINK 34 // Too many links.
|
|
#define WASI_EMSGSIZE 35 // Message too large.
|
|
#define WASI_EMULTIHOP 36 // Reserved.
|
|
#define WASI_ENAMETOOLONG 37 // Filename too long.
|
|
#define WASI_ENETDOWN 38 // Network is down.
|
|
#define WASI_ENETRESET 39 // Connection aborted by network.
|
|
#define WASI_ENETUNREACH 40 // Network unreachable.
|
|
#define WASI_ENFILE 41 // Too many files open in system.
|
|
#define WASI_ENOBUFS 42 // No buffer space available.
|
|
#define WASI_ENODEV 43 // No such device.
|
|
#define WASI_ENOENT 44 // No such file or directory.
|
|
#define WASI_ENOEXEC 45 // Executable file format error.
|
|
#define WASI_ENOLCK 46 // No locks available.
|
|
#define WASI_ENOLINK 47 // Reserved.
|
|
#define WASI_ENOMEM 48 // Not enough space.
|
|
#define WASI_ENOMSG 49 // No message of the desired type.
|
|
#define WASI_ENOPROTOOPT 50 // Protocol not available.
|
|
#define WASI_ENOSPC 51 // No space left on device.
|
|
#define WASI_ENOSYS 52 // Function not supported.
|
|
#define WASI_ENOTCONN 53 // The socket is not connected.
|
|
#define WASI_ENOTDIR 54 // Not a directory or a symbolic link to a directory.
|
|
#define WASI_ENOTEMPTY 55 // Directory not empty.
|
|
#define WASI_ENOTRECOVERABLE 56 // State not recoverable.
|
|
#define WASI_ENOTSOCK 57 // Not a socket.
|
|
#define WASI_ENOTSUP 58 // Not supported, or operation not supported on socket.
|
|
#define WASI_ENOSTDIO 59 // Inappropriate I/O control operation.
|
|
#define WASI_ENXIO 60 // No such device or address.
|
|
#define WASI_EOVERFLOW 61 // Value too large to be stored in data type.
|
|
#define WASI_EOWNERDEAD 62 // Previous owner died.
|
|
#define WASI_EPERM 63 // Operation not permitted.
|
|
#define WASI_EPIPE 64 // Broken pipe.
|
|
#define WASI_EPROTO 65 // Protocol error.
|
|
#define WASI_EPROTONOSUPPORT 66 // Protocol not supported.
|
|
#define WASI_EPROTOTYPE 67 // Protocol wrong type for socket.
|
|
#define WASI_ERANGE 68 // Result too large.
|
|
#define WASI_EROFS 69 // Read-only file system.
|
|
#define WASI_ESPIPE 70 // Invalid seek.
|
|
#define WASI_ESRCH 71 // No such process.
|
|
#define WASI_ESTALE 72 // Reserved.
|
|
#define WASI_ETIMEDOUT 73 // Connection timed out.
|
|
#define WASI_ETXTBSY 74 // Text file busy.
|
|
#define WASI_EXDEV 75 // Cross-device link.
|
|
#define WASI_ENOTCAPABLE 76 // Extension: Capabilities insufficient.
|
|
|
|
// WASI file types
|
|
#define WASI_IFUNK 0 // Unknown
|
|
#define WASI_IFBLK 1 // Block device
|
|
#define WASI_IFCHR 2 // Character device
|
|
#define WASI_IFDIR 3 // Directory
|
|
#define WASI_IFREG 4 // Regular file
|
|
#define WASI_IFSOCKD 5 // Datagram socket
|
|
#define WASI_IFSOCKS 6 // Stream socket
|
|
#define WASI_IFLNK 7 // Symbolic link
|
|
|
|
// WASI file flags
|
|
#define WASI_APPEND (1 << 0)
|
|
#define WASI_DSYNC (1 << 1)
|
|
#define WASI_NONBLOCK (1 << 2)
|
|
#define WASI_RSYNC (1 << 3)
|
|
#define WASI_SYNC (1 << 4)
|
|
|
|
// WASI rights flags
|
|
#define WASI_FD_DATASYNC (1 << 0)
|
|
#define WASI_FD_READ (1 << 1)
|
|
#define WASI_FD_SEEK (1 << 2)
|
|
#define WASI_FD_FDSTAT_SET_FLAGS (1 << 3)
|
|
#define WASI_FD_SYNC (1 << 4)
|
|
#define WASI_FD_TELL (1 << 5)
|
|
#define WASI_FD_WRITE (1 << 6)
|
|
#define WASI_FD_ADVISE (1 << 7)
|
|
#define WASI_FD_ALLOCATE (1 << 8)
|
|
#define WASI_PATH_CREATE_DIRECTORY (1 << 9)
|
|
#define WASI_PATH_CREATE_FILE (1 << 10)
|
|
#define WASI_PATH_LINK_SOURCE (1 << 11)
|
|
#define WASI_PATH_LINK_TARGET (1 << 12)
|
|
#define WASI_PATH_OPEN (1 << 13)
|
|
#define WASI_FD_READDIR (1 << 14)
|
|
#define WASI_PATH_READLINK (1 << 15)
|
|
#define WASI_PATH_RENAME_SOURCE (1 << 16)
|
|
#define WASI_PATH_RENAME_TARGET (1 << 17)
|
|
#define WASI_PATH_FILESTAT_GET (1 << 18)
|
|
#define WASI_PATH_FILESTAT_SET_SIZE (1 << 19)
|
|
#define WASI_PATH_FILESTAT_SET_TIMES (1 << 20)
|
|
#define WASI_FD_FILESTAT_GET (1 << 21)
|
|
#define WASI_FD_FILESTAT_SET_SIZE (1 << 22)
|
|
#define WASI_FD_FILESTAT_SET_TIMES (1 << 23)
|
|
#define WASI_PATH_SYMLINK (1 << 24)
|
|
#define WASI_PATH_REMOVE_DIRECTORY (1 << 25)
|
|
#define WASI_PATH_UNLINK_FILE (1 << 26)
|
|
#define WASI_POLL_FD_READWRITE (1 << 27)
|
|
#define WASI_SOCK_SHUTDOWN (1 << 28)
|
|
#define WASI_SOCK_ACCEPT (1 << 29)
|
|
|
|
typedef std::pair<uint32_t, std::string> path_cache_entry_t;
|
|
|
|
struct fs_dir {
|
|
std::string path; // Path of the directory.
|
|
uint32_t root; // Undefined if this is a preopened directory, otherwise the file descriptor of the preopened directory that contains this directory.
|
|
bool writable; // If true, writes made to this directory handle will be routed into the save directory. Otherwise, writes are disallowed.
|
|
};
|
|
|
|
struct fs_file {
|
|
struct FileSystem::File file;
|
|
uint32_t root; // The file descriptor of the preopened directory that contains this file.
|
|
};
|
|
|
|
enum wasi_fd_type {
|
|
STDIN, // This file descriptor is standard input. The `handle` field is null.
|
|
STDOUT, // This file descriptor is standard output. The `handle` field is null.
|
|
STDERR, // This file descriptor is standard error. The `handle` field is null.
|
|
FS, // This file descriptor is a preopened directory handled by PhysFS. The `handle` field is a `struct fs_dir *`.
|
|
FSDIR, // This file descriptor is a directory handled by PhysFS. The `handle` field is a `struct fs_dir *`.
|
|
FSFILE, // This file descriptor is a file handled by PhysFS. The `handle` field is a `struct fs_file *`.
|
|
VACANT, // Indicates this is a vacant file descriptor that doesn't correspond to a file. The `handle` field is null.
|
|
};
|
|
|
|
struct wasi_file_entry {
|
|
// The file/directory handle that the file descriptor corresponds to. The exact type of this handle depends on the type of file descriptor.
|
|
void *handle;
|
|
|
|
wasi_fd_type type;
|
|
|
|
struct fs_dir *dir_handle() const noexcept;
|
|
struct fs_file *file_handle() const noexcept;
|
|
};
|
|
|
|
typedef struct w2c_wasi__snapshot__preview1 {
|
|
std::shared_ptr<struct w2c_ruby> ruby;
|
|
|
|
// WASI file descriptor table. Maps WASI file descriptors (unsigned 32-bit integers) to file handles.
|
|
std::vector<wasi_file_entry> fdtable;
|
|
|
|
// List of vacant WASI file descriptors so that we can reallocate vacant WASI file descriptors quickly.
|
|
boost::container::priority_deque<uint32_t> vacant_fds;
|
|
|
|
uint64_t prng_state;
|
|
uint8_t prng_buffer[4];
|
|
uint32_t prng_buffer_size;
|
|
|
|
w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby);
|
|
~w2c_wasi__snapshot__preview1();
|
|
uint32_t allocate_file_descriptor(enum wasi_fd_type type, void *handle = nullptr);
|
|
void deallocate_file_descriptor(uint32_t fd);
|
|
|
|
// Gets a pointer to the given address in sandbox memory.
|
|
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
|
template <typename T> void *ptr_unaligned(mkxp_sandbox::wasm_ptr_t address) const noexcept {
|
|
return mkxp_sandbox::sandbox_ptr_unaligned<T>(*ruby, address);
|
|
}
|
|
|
|
// Gets a pointer to the given index in the array at a given address in sandbox memory.
|
|
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
|
template <typename T> void *ptr_unaligned(mkxp_sandbox::wasm_ptr_t array_address, mkxp_sandbox::wasm_size_t array_index) const noexcept {
|
|
return mkxp_sandbox::sandbox_ptr_unaligned<T>(*ruby, array_address, array_index);
|
|
}
|
|
|
|
// Gets a reference to the value stored at a given address in sandbox memory.
|
|
// Make sure the address is aligned, or this function will abort.
|
|
template <typename T> T &ref(mkxp_sandbox::wasm_ptr_t address) const noexcept {
|
|
return mkxp_sandbox::sandbox_ref<T>(*ruby, address);
|
|
}
|
|
|
|
// Gets a reference to the value stored at the given index in the array at a given address in sandbox memory.
|
|
// Make sure the address is aligned, or this function will abort.
|
|
template <typename T> T &ref(mkxp_sandbox::wasm_ptr_t array_address, mkxp_sandbox::wasm_size_t array_index) const noexcept {
|
|
return ref<T>(array_address + array_index * sizeof(T));
|
|
}
|
|
|
|
// Gets a string stored at a given address in sandbox memory.
|
|
struct mkxp_sandbox::sandbox_str_guard str(mkxp_sandbox::wasm_ptr_t address) const noexcept;
|
|
|
|
// Gets the length of a string stored at a given address in sandbox memory.
|
|
mkxp_sandbox::wasm_size_t strlen(mkxp_sandbox::wasm_ptr_t address) const noexcept;
|
|
|
|
// Copies a string into a sandbox memory address.
|
|
void strcpy(mkxp_sandbox::wasm_ptr_t dst_address, const char *src) const noexcept;
|
|
|
|
// Copies a string into a sandbox memory address.
|
|
void strncpy_s(mkxp_sandbox::wasm_ptr_t dst_address, const char *src, mkxp_sandbox::wasm_size_t max_size) const noexcept;
|
|
|
|
// Copies an array of length `num_elements` into a sandbox memory address.
|
|
template <typename T> void arycpy(mkxp_sandbox::wasm_ptr_t dst_address, const T *src, mkxp_sandbox::wasm_size_t num_elements) const noexcept {
|
|
mkxp_sandbox::sandbox_arycpy(*ruby, dst_address, src, num_elements);
|
|
}
|
|
|
|
bool sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
|
|
|
bool sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
|
} wasi_t;
|
|
|
|
#endif /* MKXPZ_SANDBOX_WASI_H */
|