mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Re-add lazy preopen changes
This commit is contained in:
parent
3f4c43b0aa
commit
8a8da49b52
5 changed files with 109 additions and 10 deletions
4
lib/libc/include/wasm-wasi-musl/wasi/libc.h
vendored
4
lib/libc/include/wasm-wasi-musl/wasi/libc.h
vendored
|
|
@ -17,6 +17,10 @@ struct timespec;
|
|||
/// afterward, you should call this before doing so.
|
||||
void __wasilibc_populate_preopens(void);
|
||||
|
||||
/// Reset the preopens table to an uninitialized state, forcing it to be
|
||||
/// reinitialized next time it is needed.
|
||||
void __wasilibc_reset_preopens(void);
|
||||
|
||||
/// Register the given pre-opened file descriptor under the given path.
|
||||
///
|
||||
/// This function does not take ownership of `prefix` (it makes its own copy).
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
#include <unistd.h>
|
||||
|
||||
int __wasilibc_fd_renumber(int fd, int newfd) {
|
||||
// Scan the preopen fds before making any changes.
|
||||
__wasilibc_populate_preopens();
|
||||
|
||||
__wasi_errno_t error = __wasi_fd_renumber(fd, newfd);
|
||||
if (error != 0) {
|
||||
errno = error;
|
||||
|
|
|
|||
111
lib/libc/wasi/libc-bottom-half/sources/preopens.c
vendored
111
lib/libc/wasi/libc-bottom-half/sources/preopens.c
vendored
|
|
@ -25,6 +25,7 @@ typedef struct preopen {
|
|||
} preopen;
|
||||
|
||||
/// A simple growable array of `preopen`.
|
||||
static _Atomic _Bool preopens_populated = false;
|
||||
static preopen *preopens;
|
||||
static size_t num_preopens;
|
||||
static size_t preopen_capacity;
|
||||
|
|
@ -100,12 +101,9 @@ static const char *strip_prefixes(const char *path) {
|
|||
return path;
|
||||
}
|
||||
|
||||
/// Register the given preopened file descriptor under the given path.
|
||||
///
|
||||
/// This function takes ownership of `prefix`.
|
||||
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
|
||||
LOCK(lock);
|
||||
|
||||
/// Similar to `internal_register_preopened_fd_unlocked` but does not
|
||||
/// take a lock.
|
||||
static int internal_register_preopened_fd_unlocked(__wasi_fd_t fd, const char *relprefix) {
|
||||
// Check preconditions.
|
||||
assert_invariants();
|
||||
assert(fd != AT_FDCWD);
|
||||
|
|
@ -113,22 +111,32 @@ static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix)
|
|||
assert(relprefix != NULL);
|
||||
|
||||
if (num_preopens == preopen_capacity && resize() != 0) {
|
||||
UNLOCK(lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *prefix = strdup(strip_prefixes(relprefix));
|
||||
if (prefix == NULL) {
|
||||
UNLOCK(lock);
|
||||
return -1;
|
||||
}
|
||||
preopens[num_preopens++] = (preopen) { prefix, fd, };
|
||||
|
||||
assert_invariants();
|
||||
UNLOCK(lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Register the given preopened file descriptor under the given path.
|
||||
///
|
||||
/// This function takes ownership of `prefix`.
|
||||
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
|
||||
LOCK(lock);
|
||||
|
||||
int r = internal_register_preopened_fd_unlocked(fd, relprefix);
|
||||
|
||||
UNLOCK(lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`?
|
||||
static bool prefix_matches(const char *prefix, size_t prefix_len, const char *path) {
|
||||
// Allow an empty string as a prefix of any relative path.
|
||||
|
|
@ -152,6 +160,8 @@ static bool prefix_matches(const char *prefix, size_t prefix_len, const char *pa
|
|||
|
||||
// See the documentation in libc.h
|
||||
int __wasilibc_register_preopened_fd(int fd, const char *prefix) {
|
||||
__wasilibc_populate_preopens();
|
||||
|
||||
return internal_register_preopened_fd((__wasi_fd_t)fd, prefix);
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +182,8 @@ int __wasilibc_find_relpath(const char *path,
|
|||
int __wasilibc_find_abspath(const char *path,
|
||||
const char **abs_prefix,
|
||||
const char **relative_path) {
|
||||
__wasilibc_populate_preopens();
|
||||
|
||||
// Strip leading `/` characters, the prefixes we're mataching won't have
|
||||
// them.
|
||||
while (*path == '/')
|
||||
|
|
@ -218,3 +230,84 @@ int __wasilibc_find_abspath(const char *path,
|
|||
*relative_path = computed;
|
||||
return fd;
|
||||
}
|
||||
|
||||
__attribute__((constructor(51)))
|
||||
void __wasilibc_populate_preopens(void) {
|
||||
// Fast path: If the preopens are already initialized, do nothing.
|
||||
if (preopens_populated) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK(lock);
|
||||
|
||||
// Check whether another thread initialized the preopens already.
|
||||
if (preopens_populated) {
|
||||
UNLOCK(lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip stdin, stdout, and stderr, and count up until we reach an invalid
|
||||
// file descriptor.
|
||||
for (__wasi_fd_t fd = 3; fd != 0; ++fd) {
|
||||
__wasi_prestat_t prestat;
|
||||
__wasi_errno_t ret = __wasi_fd_prestat_get(fd, &prestat);
|
||||
if (ret == __WASI_ERRNO_BADF)
|
||||
break;
|
||||
if (ret != __WASI_ERRNO_SUCCESS)
|
||||
goto oserr;
|
||||
switch (prestat.tag) {
|
||||
case __WASI_PREOPENTYPE_DIR: {
|
||||
char *prefix = malloc(prestat.u.dir.pr_name_len + 1);
|
||||
if (prefix == NULL)
|
||||
goto software;
|
||||
|
||||
// TODO: Remove the cast on `prefix` once the witx is updated with
|
||||
// char8 support.
|
||||
ret = __wasi_fd_prestat_dir_name(fd, (uint8_t *)prefix,
|
||||
prestat.u.dir.pr_name_len);
|
||||
if (ret != __WASI_ERRNO_SUCCESS)
|
||||
goto oserr;
|
||||
prefix[prestat.u.dir.pr_name_len] = '\0';
|
||||
|
||||
if (internal_register_preopened_fd_unlocked(fd, prefix) != 0)
|
||||
goto software;
|
||||
free(prefix);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Preopens are now initialized.
|
||||
preopens_populated = true;
|
||||
|
||||
UNLOCK(lock);
|
||||
|
||||
return;
|
||||
oserr:
|
||||
_Exit(EX_OSERR);
|
||||
software:
|
||||
_Exit(EX_SOFTWARE);
|
||||
}
|
||||
|
||||
void __wasilibc_reset_preopens(void) {
|
||||
LOCK(lock);
|
||||
|
||||
if (num_preopens) {
|
||||
for (int i = 0; i < num_preopens; ++i) {
|
||||
free((void*) preopens[i].prefix);
|
||||
}
|
||||
free(preopens);
|
||||
}
|
||||
|
||||
preopens_populated = false;
|
||||
preopens = NULL;
|
||||
num_preopens = 0;
|
||||
preopen_capacity = 0;
|
||||
|
||||
assert_invariants();
|
||||
|
||||
UNLOCK(lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -463,7 +463,6 @@ const libc_bottom_half_src_files = [_][]const u8{
|
|||
"wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c",
|
||||
"wasi/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c",
|
||||
"wasi/libc-bottom-half/cloudlibc/src/libc/time/time.c",
|
||||
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/close.c",
|
||||
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c",
|
||||
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c",
|
||||
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue