Browse Source

Add basic emulation of getcwd/chdir (#214)

* Add basic emulation of getcwd/chdir

This commit adds basic emulation of a current working directory to
wasi-libc. The `getcwd` and `chdir` symbols are now implemented and
available for use. The `getcwd` implementation is pretty simple in that
it just copies out of a new global, `__wasilibc_cwd`, which defaults to
`"/"`. The `chdir` implementation is much more involved and has more
ramification, however.

A new function, `make_absolute`, was added to the preopens object. Paths
stored in the preopen table are now always stored as absolute paths
instead of relative paths, and initial relative paths are interpreted as
being relative to `/`. Looking up a path to preopen now always turns it
into an absolute path, relative to the current working directory, and an
appropriate path is then returned.

The signature of `__wasilibc_find_relpath` has changed as well. It now
returns two path components, one for the absolute part and one for the
relative part. Additionally the relative part is always dynamically
allocated since it may no longer be a substring of the original input
path.

This has been tested lightly against the Rust standard library so far,
but I'm not a regular C developer so there's likely a few things to
improve!

* Amortize mallocs made in syscalls

* Avoid size bloat on programs that don't use `chdir`

* Add threading compat

* Collect `link`/`renameat` second path lookup

* Update comments about chdir.c in makefile

* Move definition of `__wasilibc_find_relpath_alloc` to header

* Expand comments

* Document the format of strings a bit more

* Fixup a few issues in path logic

* Fix GitHub Actions
pull/225/head
Alex Crichton 4 years ago
committed by GitHub
parent
commit
5b148b6131
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/workflows/main.yml
  2. 8
      Makefile
  3. 5
      expected/wasm32-wasi/defined-symbols.txt
  4. 65
      libc-bottom-half/headers/public/wasi/libc-find-relpath.h
  5. 151
      libc-bottom-half/sources/chdir.c
  6. 30
      libc-bottom-half/sources/getcwd.c
  7. 102
      libc-bottom-half/sources/posix.c
  8. 75
      libc-bottom-half/sources/preopens.c
  9. 6
      libc-top-half/musl/include/unistd.h

2
.github/workflows/main.yml

@ -28,7 +28,7 @@ jobs:
rustup update stable
rustup default stable
rustup component add llvm-tools-preview
echo "::set-env name=WASM_NM::$(rustc --print sysroot|sed 's|C:|/c|'|sed 's|\\|/|g')/lib/rustlib/x86_64-pc-windows-msvc/bin/llvm-nm.exe"
echo "WASM_NM=$(rustc --print sysroot|sed 's|C:|/c|'|sed 's|\\|/|g')/lib/rustlib/x86_64-pc-windows-msvc/bin/llvm-nm.exe" >> $GITHUB_ENV
if: matrix.os == 'windows-latest'
- name: Install clang (MacOS)

8
Makefile

@ -44,6 +44,14 @@ LIBC_BOTTOM_HALF_SOURCES = $(LIBC_BOTTOM_HALF_DIR)/sources
LIBC_BOTTOM_HALF_ALL_SOURCES = \
$(shell find $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) -name \*.c) \
$(shell find $(LIBC_BOTTOM_HALF_SOURCES) -name \*.c)
# FIXME(https://reviews.llvm.org/D85567) - due to a bug in LLD the weak
# references to a function defined in `chdir.c` only work if `chdir.c` is at the
# end of the archive, but once that LLD review lands and propagates into LLVM
# then we don't have to do this.
LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_SOURCES)/chdir.c,$(LIBC_BOTTOM_HALF_ALL_SOURCES))
LIBC_BOTTOM_HALF_ALL_SOURCES := $(LIBC_BOTTOM_HALF_ALL_SOURCES) $(LIBC_BOTTOM_HALF_SOURCES)/chdir.c
LIBWASI_EMULATED_MMAN_SOURCES = \
$(shell find $(LIBC_BOTTOM_HALF_DIR)/mman -name \*.c)
LIBWASI_EMULATED_SIGNAL_SOURCES = \

5
expected/wasm32-wasi/defined-symbols.txt

@ -250,11 +250,14 @@ __uflow
__unlist_locked_file
__uselocale
__utc
__wasilibc_cwd
__wasilibc_ensure_environ
__wasilibc_environ
__wasilibc_environ
__wasilibc_fd_renumber
__wasilibc_find_abspath
__wasilibc_find_relpath
__wasilibc_find_relpath_alloc
__wasilibc_initialize_environ
__wasilibc_open_nomode
__wasilibc_openat_nomode
@ -368,6 +371,7 @@ ceill
cexp
cexpf
cexpl
chdir
cimag
cimagf
cimagl
@ -579,6 +583,7 @@ getc
getc_unlocked
getchar
getchar_unlocked
getcwd
getdate
getdate_err
getdelim

65
libc-bottom-half/headers/public/wasi/libc-find-relpath.h

@ -6,15 +6,72 @@ extern "C" {
#endif
/**
* Look up the given path in the preopened directory map. If a suitable
* entry is found, return its directory file descriptor, and store the
* computed relative path in *relative_path.
* Look up the given `path`, relative to the cwd, in the preopened directory
* map. If a suitable entry is found, then the file descriptor for that entry
* is returned. Additionally the absolute path of the directory's file
* descriptor is returned in `abs_prefix` and the relative portion that needs
* to be opened is stored in `*relative_path`.
*
* Returns -1 if no directories were suitable.
* The `relative_path` argument must be a pointer to a buffer valid for
* `relative_path_len` bytes, and this may be used as storage for the relative
* portion of the path being returned through `*relative_path`.
*
* See documentation on `__wasilibc_find_abspath` for more info about what the
* paths look like.
*
* Returns -1 on failure. Errno is set to either:
*
* * ENOMEM - failed to allocate memory for internal routines.
* * ENOENT - the `path` could not be found relative to any preopened dir.
* * ERANGE - the `relative_path` buffer is too small to hold the relative path.
*/
int __wasilibc_find_relpath(const char *path,
const char **__restrict__ abs_prefix,
char **relative_path,
size_t relative_path_len);
/**
* Look up the given `path`, which is interpreted as absolute, in the preopened
* directory map. If a suitable entry is found, then the file descriptor for
* that entry is returned. Additionally the relative portion of the path to
* where the fd is opened is returned through `relative_path`, the absolute
* prefix which was matched is stored to `abs_prefix`, and `relative_path` may
* be an interior pointer to the `abspath` string.
*
* The `abs_prefix` returned string will not contain a leading `/`. Note that
* this may be the empty string. Additionally the returned `relative_path` will
* not contain a leading `/`. The `relative_path` return will not return an
* empty string, it will return `"."` instead if it would otherwise do so.
*
* Returns -1 on failure. Errno is set to either:
*
* * ENOMEM - failed to allocate memory for internal routines.
* * ENOENT - the `path` could not be found relative to any preopened dir.
*/
int __wasilibc_find_abspath(const char *abspath,
const char **__restrict__ abs_prefix,
const char **__restrict__ relative_path);
/**
* Same as `__wasilibc_find_relpath`, except that this function will interpret
* `relative` as a malloc'd buffer that will be `realloc`'d to the appropriate
* size to contain the relative path.
*
* Note that this is a weak symbol and if it's not defined you can use
* `__wasilibc_find_relpath`. The weak-nature of this symbols means that if it's
* not otherwise included in the compilation then `chdir` wasn't used an there's
* no need for this symbol.
*
* See documentation on `__wasilibc_find_relpath` for more information.
*/
int __wasilibc_find_relpath_alloc(
const char *path,
const char **abs,
char **relative,
size_t *relative_len,
int can_realloc
) __attribute__((weak));
#ifdef __cplusplus
}
#endif

151
libc-bottom-half/sources/chdir.c

@ -0,0 +1,151 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wasi/libc-find-relpath.h>
#include <wasi/libc.h>
#ifdef _REENTRANT
#error "chdir doesn't yet support multiple threads"
#endif
extern char *__wasilibc_cwd;
static int __wasilibc_cwd_mallocd = 0;
int chdir(const char *path)
{
static char *relative_buf = NULL;
static size_t relative_buf_len = 0;
// Find a preopen'd directory as well as a relative path we're anchored
// from which we're changing directories to.
const char *abs;
int parent_fd = __wasilibc_find_relpath_alloc(path, &abs, &relative_buf, &relative_buf_len, 1);
if (parent_fd == -1)
return -1;
// Make sure that this directory we're accessing is indeed a directory.
struct stat dirinfo;
int ret = fstatat(parent_fd, relative_buf, &dirinfo, 0);
if (ret == -1)
return -1;
if (!S_ISDIR(dirinfo.st_mode)) {
errno = ENOTDIR;
return -1;
}
// Create a string that looks like:
//
// __wasilibc_cwd = "/" + abs + "/" + relative_buf
//
// If `relative_buf` is equal to "." or `abs` is equal to the empty string,
// however, we skip that part and the middle slash.
size_t len = strlen(abs) + 1;
int copy_relative = strcmp(relative_buf, ".") != 0;
int mid = copy_relative && abs[0] != 0;
char *new_cwd = malloc(len + (copy_relative ? strlen(relative_buf) + mid: 0));
if (new_cwd == NULL) {
errno = ENOMEM;
return -1;
}
new_cwd[0] = '/';
strcpy(new_cwd + 1, abs);
if (mid)
new_cwd[strlen(abs) + 1] = '/';
if (copy_relative)
strcpy(new_cwd + 1 + mid + strlen(abs), relative_buf);
// And set our new malloc'd buffer into the global cwd, freeing the
// previous one if necessary.
char *prev_cwd = __wasilibc_cwd;
__wasilibc_cwd = new_cwd;
if (__wasilibc_cwd_mallocd)
free(prev_cwd);
__wasilibc_cwd_mallocd = 1;
return 0;
}
static const char *make_absolute(const char *path) {
static char *make_absolute_buf = NULL;
static size_t make_absolute_len = 0;
// If this path is absolute, then we return it as-is.
if (path[0] == '/') {
return path;
}
// If the path is empty, or points to the current directory, then return
// the current directory.
if (path[0] == 0 || !strcmp(path, ".") || !strcmp(path, "./")) {
return __wasilibc_cwd;
}
// If the path starts with `./` then we won't be appending that to the cwd.
if (path[0] == '.' && path[1] == '/')
path += 2;
// Otherwise we'll take the current directory, add a `/`, and then add the
// input `path`. Note that this doesn't do any normalization (like removing
// `/./`).
size_t cwd_len = strlen(__wasilibc_cwd);
size_t path_len = strlen(path);
int need_slash = __wasilibc_cwd[cwd_len - 1] == '/' ? 0 : 1;
size_t alloc_len = cwd_len + path_len + 1 + need_slash;
if (alloc_len > make_absolute_len) {
make_absolute_buf = realloc(make_absolute_buf, alloc_len);
if (make_absolute_buf == NULL)
return NULL;
make_absolute_len = alloc_len;
}
strcpy(make_absolute_buf, __wasilibc_cwd);
if (need_slash)
strcpy(make_absolute_buf + cwd_len, "/");
strcpy(make_absolute_buf + cwd_len + need_slash, path);
return make_absolute_buf;
}
// Helper function defined only in this object file and weakly referenced from
// `preopens.c` and `posix.c` This function isn't necessary unless `chdir` is
// pulled in because all paths are otherwise absolute or relative to the root.
int __wasilibc_find_relpath_alloc(
const char *path,
const char **abs_prefix,
char **relative_buf,
size_t *relative_buf_len,
int can_realloc
) {
// First, make our path absolute taking the cwd into account.
const char *abspath = make_absolute(path);
if (abspath == NULL) {
errno = ENOMEM;
return -1;
}
// Next use our absolute path and split it. Find the preopened `fd` parent
// directory and set `abs_prefix`. Next up we'll be trying to fit `rel`
// into `relative_buf`.
const char *rel;
int fd = __wasilibc_find_abspath(abspath, abs_prefix, &rel);
if (fd == -1)
return -1;
size_t rel_len = strlen(rel);
if (*relative_buf_len < rel_len + 1) {
if (!can_realloc) {
errno = ERANGE;
return -1;
}
char *tmp = realloc(*relative_buf, rel_len + 1);
if (tmp == NULL) {
errno = ENOMEM;
return -1;
}
*relative_buf = tmp;
*relative_buf_len = rel_len + 1;
}
strcpy(*relative_buf, rel);
return fd;
}

30
libc-bottom-half/sources/getcwd.c

@ -0,0 +1,30 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
// For threads this needs to synchronize with chdir
#ifdef _REENTRANT
#error "getcwd doesn't yet support multiple threads"
#endif
char *__wasilibc_cwd = "/";
char *getcwd(char *buf, size_t size)
{
if (!buf) {
buf = strdup(__wasilibc_cwd);
if (!buf) {
errno = ENOMEM;
return NULL;
}
} else {
size_t len = strlen(__wasilibc_cwd);
if (size < strlen(__wasilibc_cwd) + 1) {
errno = ERANGE;
return NULL;
}
strcpy(buf, __wasilibc_cwd);
}
return buf;
}

102
libc-bottom-half/sources/posix.c

@ -4,12 +4,44 @@
#include <errno.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include <sys/stat.h>
#include <wasi/libc.h>
#include <wasi/libc-find-relpath.h>
static int find_relpath2(
const char *path,
char **relative,
size_t *relative_len
) {
// See comments in `preopens.c` for what this trick is doing.
const char *abs;
if (__wasilibc_find_relpath_alloc)
return __wasilibc_find_relpath_alloc(path, &abs, relative, relative_len, 1);
return __wasilibc_find_relpath(path, &abs, relative, *relative_len);
}
// Helper to call `__wasilibc_find_relpath` and return an already-managed
// pointer for the `relative` path. This function is not reentrant since the
// `relative` pointer will point to static data that cannot be reused until
// `relative` is no longer used.
static int find_relpath(const char *path, char **relative) {
static __thread char *relative_buf = NULL;
static __thread size_t relative_buf_len = 0;
*relative = relative_buf;
return find_relpath2(path, relative, &relative_buf_len);
}
// same as `find_relpath`, but uses another set of static variables to cache
static int find_relpath_alt(const char *path, char **relative) {
static __thread char *relative_buf = NULL;
static __thread size_t relative_buf_len = 0;
*relative = relative_buf;
return find_relpath2(path, relative, &relative_buf_len);
}
int open(const char *path, int oflag, ...) {
// WASI libc's `openat` ignores the mode argument, so call a special
// entrypoint which avoids the varargs calling convention.
@ -18,8 +50,8 @@ int open(const char *path, int oflag, ...) {
// See the documentation in libc.h
int __wasilibc_open_nomode(const char *path, int oflag) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -31,8 +63,8 @@ int __wasilibc_open_nomode(const char *path, int oflag) {
}
int access(const char *path, int amode) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -48,8 +80,8 @@ ssize_t readlink(
char *restrict buf,
size_t bufsize)
{
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -61,8 +93,8 @@ ssize_t readlink(
}
int stat(const char *restrict path, struct stat *restrict buf) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -74,8 +106,8 @@ int stat(const char *restrict path, struct stat *restrict buf) {
}
int lstat(const char *restrict path, struct stat *restrict buf) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -87,8 +119,8 @@ int lstat(const char *restrict path, struct stat *restrict buf) {
}
int utime(const char *path, const struct utimbuf *times) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -106,8 +138,8 @@ int utime(const char *path, const struct utimbuf *times) {
}
int unlink(const char *path) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -122,8 +154,8 @@ int unlink(const char *path) {
}
int rmdir(const char *path) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -135,8 +167,8 @@ int rmdir(const char *path) {
}
int remove(const char *path) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -158,8 +190,8 @@ int remove(const char *path) {
}
int mkdir(const char *path, mode_t mode) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(path, &relative_path);
char *relative_path;
int dirfd = find_relpath(path, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -171,8 +203,8 @@ int mkdir(const char *path, mode_t mode) {
}
DIR *opendir(const char *dirname) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(dirname, &relative_path);
char *relative_path;
int dirfd = find_relpath(dirname, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -189,8 +221,8 @@ int scandir(
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)
) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(dir, &relative_path);
char *relative_path;
int dirfd = find_relpath(dir, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -202,8 +234,8 @@ int scandir(
}
int symlink(const char *target, const char *linkpath) {
const char *relative_path;
int dirfd = __wasilibc_find_relpath(linkpath, &relative_path);
char *relative_path;
int dirfd = find_relpath(linkpath, &relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (dirfd == -1) {
@ -215,12 +247,12 @@ int symlink(const char *target, const char *linkpath) {
}
int link(const char *old, const char *new) {
const char *old_relative_path;
int old_dirfd = __wasilibc_find_relpath(old, &old_relative_path);
char *old_relative_path;
int old_dirfd = find_relpath_alt(old, &old_relative_path);
if (old_dirfd != -1) {
const char *new_relative_path;
int new_dirfd = __wasilibc_find_relpath(new, &new_relative_path);
char *new_relative_path;
int new_dirfd = find_relpath(new, &new_relative_path);
if (new_dirfd != -1)
return linkat(old_dirfd, old_relative_path,
@ -233,12 +265,12 @@ int link(const char *old, const char *new) {
}
int rename(const char *old, const char *new) {
const char *old_relative_path;
int old_dirfd = __wasilibc_find_relpath(old, &old_relative_path);
char *old_relative_path;
int old_dirfd = find_relpath_alt(old, &old_relative_path);
if (old_dirfd != -1) {
const char *new_relative_path;
int new_dirfd = __wasilibc_find_relpath(new, &new_relative_path);
char *new_relative_path;
int new_dirfd = find_relpath(new, &new_relative_path);
if (new_dirfd != -1)
return renameat(old_dirfd, old_relative_path,

75
libc-bottom-half/sources/preopens.c

@ -7,14 +7,15 @@
#endif
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <wasi/api.h>
#include <wasi/libc.h>
#include <wasi/libc-find-relpath.h>
#include <wasi/libc.h>
/// A name and file descriptor pair.
typedef struct preopen {
@ -71,15 +72,38 @@ static int resize(void) {
return 0;
}
// Normalize an absolute path. Removes leading `/` and leading `./`, so the
// first character is the start of a directory name. This works because our
// process always starts with a working directory of `/`. Additionally translate
// `.` to the empty string.
static const char *strip_prefixes(const char *path) {
while (1) {
if (path[0] == '/') {
path++;
} else if (path[0] == '.' && path[1] == '/') {
path += 2;
} else if (path[0] == '.' && path[1] == 0) {
path++;
} else {
break;
}
}
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 *prefix) {
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
assert_invariants();
if (num_preopens == preopen_capacity && resize() != 0)
return -1;
char *prefix = strdup(strip_prefixes(relprefix));
if (prefix == NULL)
return -1;
preopens[num_preopens++] = (preopen) { prefix, fd, };
assert_invariants();
@ -109,16 +133,30 @@ 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) {
prefix = strdup(prefix);
return prefix == NULL ? -1 :
internal_register_preopened_fd((__wasi_fd_t)fd, prefix);
return internal_register_preopened_fd((__wasi_fd_t)fd, prefix);
}
// See the documentation in libc-find-relpath.h.
int __wasilibc_find_relpath(const char *path,
const char **restrict relative_path) {
assert_invariants();
const char **abs_prefix,
char **relative_path,
size_t relative_path_len) {
// If `chdir` is linked, whose object file defines this symbol, then we
// call that. Otherwise if the program can't `chdir` then `path` is
// absolute (or relative to the root dir), so we delegate to `find_abspath`
if (__wasilibc_find_relpath_alloc)
return __wasilibc_find_relpath_alloc(path, abs_prefix, relative_path, &relative_path_len, 0);
return __wasilibc_find_abspath(path, abs_prefix, (const char**) relative_path);
}
// See the documentation in libc-find-relpath.h.
int __wasilibc_find_abspath(const char *path,
const char **abs_prefix,
const char **relative_path) {
// Strip leading `/` characters, the prefixes we're mataching won't have
// them.
while (*path == '/')
path++;
// Search through the preopens table. Iterate in reverse so that more
// recently added preopens take precedence over less recently addded ones.
size_t match_len = 0;
@ -128,22 +166,6 @@ int __wasilibc_find_relpath(const char *path,
const char *prefix = pre->prefix;
size_t len = strlen(prefix);
if (path[0] != '/' &&
(path[0] != '.' || (path[1] != '/' && path[1] != '\0')))
{
// We're matching a relative path that doesn't start with "./" and
// isn't ".".
if (len >= 2 && prefix[0] == '.' && prefix[1] == '/') {
// The preopen starts with "./", so skip that prefix.
prefix += 2;
len -= 2;
} else if (len == 1 && prefix[0] == '.') {
// The preopen is ".", so match it as an empty string.
prefix += 1;
len -= 1;
}
}
// If we haven't had a match yet, or the candidate path is longer than
// our current best match's path, and the candidate path is a prefix of
// the requested path, take that as the new best path.
@ -152,9 +174,15 @@ int __wasilibc_find_relpath(const char *path,
{
fd = pre->fd;
match_len = len;
*abs_prefix = prefix;
}
}
if (fd == -1) {
errno = ENOENT;
return -1;
}
// The relative path is the substring after the portion that was matched.
const char *computed = path + match_len;
@ -202,6 +230,7 @@ static void __wasilibc_populate_preopens(void) {
if (internal_register_preopened_fd(fd, prefix) != 0)
goto software;
free(prefix);
break;
}

6
libc-top-half/musl/include/unistd.h

@ -118,11 +118,11 @@ int ftruncate(int, off_t);
int access(const char *, int);
int faccessat(int, const char *, int, int);
#ifdef __wasilibc_unmodified_upstream /* WASI has no cwd */
int chdir(const char *);
#ifdef __wasilibc_unmodified_upstream /* WASI has no fchdir */
int fchdir(int);
char *getcwd(char *, size_t);
#endif
int chdir(const char *);
char *getcwd(char *, size_t);
#ifdef __wasilibc_unmodified_upstream /* WASI has no signals */
unsigned alarm(unsigned);

Loading…
Cancel
Save