AT_FDCWD support.

AT_FDCWD is a special constant in POSIX that can be passed to *at
functions to indicate the current working directory. Since the
current working directory is emulated in wasi libc, add emulated
AT_FDCWD support as well.

Fixes #42.
This commit is contained in:
Dan Gohman 2021-02-04 09:29:21 -08:00
parent 5ccebd3130
commit f2e779e5f1
23 changed files with 442 additions and 49 deletions

View File

@ -249,6 +249,7 @@ __uflow
__unlist_locked_file
__uselocale
__utc
__wasilibc_access
__wasilibc_cwd
__wasilibc_ensure_environ
__wasilibc_environ
@ -258,12 +259,31 @@ __wasilibc_find_abspath
__wasilibc_find_relpath
__wasilibc_find_relpath_alloc
__wasilibc_initialize_environ
__wasilibc_link
__wasilibc_link_newat
__wasilibc_link_oldat
__wasilibc_nocwd___wasilibc_rmdirat
__wasilibc_nocwd___wasilibc_unlinkat
__wasilibc_nocwd_faccessat
__wasilibc_nocwd_fstatat
__wasilibc_nocwd_linkat
__wasilibc_nocwd_mkdirat_nomode
__wasilibc_nocwd_openat_nomode
__wasilibc_nocwd_opendirat
__wasilibc_nocwd_readlinkat
__wasilibc_nocwd_renameat
__wasilibc_nocwd_scandirat
__wasilibc_nocwd_symlinkat
__wasilibc_nocwd_utimensat
__wasilibc_open_nomode
__wasilibc_openat_nomode
__wasilibc_register_preopened_fd
__wasilibc_rename_newat
__wasilibc_rename_oldat
__wasilibc_rmdirat
__wasilibc_stat
__wasilibc_tell
__wasilibc_unlinkat
__wasilibc_utimens
__wasm_call_dtors
__wcscoll_l
__wcsftime_l

View File

@ -166,6 +166,7 @@
#include <wasi/api.h>
#include <wasi/libc-environ.h>
#include <wasi/libc-find-relpath.h>
#include <wasi/libc-nocwd.h>
#include <wasi/libc.h>
#include <wchar.h>
#include <wctype.h>

View File

@ -46,6 +46,7 @@
#define ARG_MAX 131072
#define ARMAG "!<arch>\n"
#define AT_EACCESS (0x0)
#define AT_FDCWD (-2)
#define AT_REMOVEDIR (0x4)
#define AT_SYMLINK_FOLLOW (0x2)
#define AT_SYMLINK_NOFOLLOW (0x1)
@ -3021,6 +3022,7 @@
#define __wasi_libc_environ_h
#define __wasi_libc_find_relpath_h
#define __wasi_libc_h
#define __wasi_libc_nocwd_h
#define __wasilibc___errno_h
#define __wasilibc___errno_values_h
#define __wasilibc___fd_set_h

View File

@ -3,14 +3,15 @@
// SPDX-License-Identifier: BSD-2-Clause
#include <wasi/libc.h>
#include <wasi/libc-nocwd.h>
#include <dirent.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
DIR *opendirat(int dir, const char *dirname) {
DIR *__wasilibc_nocwd_opendirat(int dir, const char *dirname) {
// Open directory.
int fd = __wasilibc_openat_nomode(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
int fd = __wasilibc_nocwd_openat_nomode(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
if (fd == -1)
return NULL;

View File

@ -4,6 +4,7 @@
#include <wasi/api.h>
#include <wasi/libc.h>
#include <wasi/libc-nocwd.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@ -17,15 +18,15 @@ static int sel_true(const struct dirent *de) {
return 1;
}
int scandirat(int dirfd, const char *dir, struct dirent ***namelist,
int (*sel)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)) {
int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist,
int (*sel)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)) {
// Match all files if no select function is provided.
if (sel == NULL)
sel = sel_true;
// Open the directory.
int fd = __wasilibc_openat_nomode(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
int fd = __wasilibc_nocwd_openat_nomode(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
if (fd == -1)
return -1;

View File

@ -22,19 +22,14 @@ static_assert(O_DIRECTORY >> 12 == __WASI_OFLAGS_DIRECTORY, "Value mismatch");
static_assert(O_EXCL >> 12 == __WASI_OFLAGS_EXCL, "Value mismatch");
static_assert(O_TRUNC >> 12 == __WASI_OFLAGS_TRUNC, "Value mismatch");
int openat(int fd, const char *path, int oflag, ...) {
return __wasilibc_openat_nomode(fd, path, oflag);
}
int __wasilibc_openat_nomode(int fd, const char *path, int oflag) {
int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) {
// Compute rights corresponding with the access modes provided.
// Attempt to obtain all rights, except the ones that contradict the
// access mode provided to openat().
__wasi_rights_t max =
~(__WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ |
__WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_FD_ALLOCATE |
__WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE |
0);
__WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE);
switch (oflag & O_ACCMODE) {
case O_RDONLY:
case O_RDWR:

View File

@ -9,7 +9,7 @@
#include <stdio.h>
#include <string.h>
int renameat(int oldfd, const char *old, int newfd, const char *new) {
int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char *new) {
__wasi_errno_t error = __wasi_path_rename(oldfd, old, strlen(old),
newfd, new, strlen(new));
if (error != 0) {

View File

@ -13,8 +13,8 @@
#include "stat_impl.h"
int fstatat(int fd, const char *restrict path, struct stat *restrict buf,
int flag) {
int __wasilibc_nocwd_fstatat(int fd, const char *restrict path, struct stat *restrict buf,
int flag) {
// Create lookup properties.
__wasi_lookupflags_t lookup_flags = 0;
if ((flag & AT_SYMLINK_NOFOLLOW) == 0)

View File

@ -10,7 +10,7 @@
#include <errno.h>
#include <string.h>
int mkdirat(int fd, const char *path, mode_t mode) {
int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) {
__wasi_errno_t error = __wasi_path_create_directory(
fd, path, strlen(path));
if (error != 0) {

View File

@ -13,8 +13,8 @@
#include "stat_impl.h"
int utimensat(int fd, const char *path, const struct timespec times[2],
int flag) {
int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec times[2],
int flag) {
// Convert timestamps and extract NOW/OMIT flags.
__wasi_timestamp_t st_atim;
__wasi_timestamp_t st_mtim;

View File

@ -10,7 +10,7 @@
#include <string.h>
#include <unistd.h>
int faccessat(int fd, const char *path, int amode, int flag) {
int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) {
// Validate function parameters.
if ((amode & ~(F_OK | R_OK | W_OK | X_OK)) != 0 ||
(flag & ~AT_EACCESS) != 0) {

View File

@ -10,7 +10,7 @@
#include <string.h>
#include <unistd.h>
int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) {
int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) {
// Create lookup properties.
__wasi_lookupflags_t lookup1_flags = 0;
if ((flag & AT_SYMLINK_FOLLOW) != 0)

View File

@ -9,8 +9,8 @@
#include <string.h>
#include <unistd.h>
ssize_t readlinkat(int fd, const char *restrict path, char *restrict buf,
size_t bufsize) {
ssize_t __wasilibc_nocwd_readlinkat(int fd, const char *restrict path, char *restrict buf,
size_t bufsize) {
size_t bufused;
// TODO: Remove the cast on `buf` once the witx is updated with char8 support.
__wasi_errno_t error = __wasi_path_readlink(fd, path, strlen(path),

View File

@ -9,7 +9,7 @@
#include <string.h>
#include <unistd.h>
int symlinkat(const char *path1, int fd, const char *path2) {
int __wasilibc_nocwd_symlinkat(const char *path1, int fd, const char *path2) {
__wasi_errno_t error =
__wasi_path_symlink(path1, strlen(path1), fd, path2, strlen(path2));
if (error != 0) {

View File

@ -1,2 +1,3 @@
#include <_/cdefs.h>
int snprintf(char *str, size_t size, const char *format, ...);
int rename(const char *oldpath, const char *newpath);

View File

@ -56,4 +56,6 @@
#define AT_SYMLINK_FOLLOW (0x2)
#define AT_REMOVEDIR (0x4)
#define AT_FDCWD (-2)
#endif

View File

@ -0,0 +1,58 @@
#ifndef __wasi_libc_nocwd_h
#define __wasi_libc_nocwd_h
/*
* In order to support AT_FDCWD, we need to wrap the *at functions to handle
* it by calling back into the non-at versions which perform libpreopen
* queries. These __wasilibc_nocwd_* forms are the underlying calls which
* assume AT_FDCWD has already been resolved.
*/
#define __need_size_t
#include <stddef.h>
#include <__typedef_ssize_t.h>
#include <__typedef_mode_t.h>
#include <__typedef_DIR.h>
#ifdef __cplusplus
extern "C" {
#endif
struct timespec;
struct stat;
struct dirent;
int __wasilibc_nocwd___wasilibc_unlinkat(int, const char *)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd___wasilibc_rmdirat(int, const char *)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_linkat(int, const char *, int, const char *, int)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_symlinkat(const char *, int, const char *)
__attribute__((__warn_unused_result__));
ssize_t __wasilibc_nocwd_readlinkat(int, const char *__restrict, char *__restrict, size_t)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_faccessat(int, const char *, int, int)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_renameat(int, const char *, int, const char *)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_openat_nomode(int, const char *, int)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_fstatat(int, const char *__restrict, struct stat *__restrict, int)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_mkdirat_nomode(int, const char *)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_utimensat(int, const char *, const struct timespec [2], int)
__attribute__((__warn_unused_result__));
DIR *__wasilibc_nocwd_opendirat(int, const char *)
__attribute__((__warn_unused_result__));
int __wasilibc_nocwd_scandirat(int, const char *, struct dirent ***,
int (*)(const struct dirent *),
int (*)(const struct dirent **, const struct dirent **))
__attribute__((__warn_unused_result__));
#ifdef __cplusplus
}
#endif
#endif

View File

@ -2,11 +2,15 @@
#define __wasi_libc_h
#include <__typedef_off_t.h>
#include <__struct_timespec.h>
#ifdef __cplusplus
extern "C" {
#endif
struct stat;
struct timespec;
/// Register the given pre-opened file descriptor under the given path.
///
/// This function does not take ownership of `prefix` (it makes its own copy).
@ -14,13 +18,16 @@ int __wasilibc_register_preopened_fd(int fd, const char *prefix);
/// Renumber `fd` to `newfd`; similar to `dup2` but does a move rather than a
/// copy.
int __wasilibc_fd_renumber(int fd, int newfd);
int __wasilibc_fd_renumber(int fd, int newfd)
__attribute__((__warn_unused_result__));
/// Like `unlinkat`, but without depending on `__wasi_path_remove_directory`.
int __wasilibc_unlinkat(int fd, const char *path);
int __wasilibc_unlinkat(int fd, const char *path)
__attribute__((__warn_unused_result__));
/// An `*at` version of rmdir.
int __wasilibc_rmdirat(int fd, const char *path);
int __wasilibc_rmdirat(int fd, const char *path)
__attribute__((__warn_unused_result__));
/// Like `open`, but without the varargs in the signature.
int __wasilibc_open_nomode(const char *path, int oflag);
@ -30,7 +37,26 @@ int __wasilibc_openat_nomode(int fd, const char *path, int oflag);
/// Return the current file offset. Like `lseek(fd, 0, SEEK_CUR)`, but without
/// depending on `lseek`.
off_t __wasilibc_tell(int fd);
off_t __wasilibc_tell(int fd)
__attribute__((__warn_unused_result__));
/* Non-`at` forms of various `*at` functions. */
int __wasilibc_access(const char *pathname, int mode, int flags)
__attribute__((__warn_unused_result__));
int __wasilibc_stat(const char *__restrict pathname, struct stat *__restrict statbuf, int flags)
__attribute__((__warn_unused_result__));
int __wasilibc_utimens(const char *pathname, const struct timespec times[2], int flags)
__attribute__((__warn_unused_result__));
int __wasilibc_link(const char *oldpath, const char *newpath, int flags)
__attribute__((__warn_unused_result__));
int __wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, int flags)
__attribute__((__warn_unused_result__));
int __wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, int flags)
__attribute__((__warn_unused_result__));
int __wasilibc_rename_oldat(int olddirfd, const char *oldpath, const char *newpath)
__attribute__((__warn_unused_result__));
int __wasilibc_rename_newat(const char *oldpath, int newdirfd, const char *newpath)
__attribute__((__warn_unused_result__));
#ifdef __cplusplus
}

View File

@ -4,7 +4,7 @@
#include <errno.h>
#include <string.h>
int __wasilibc_rmdirat(int fd, const char *path) {
int __wasilibc_nocwd___wasilibc_rmdirat(int fd, const char *path) {
size_t path_len = strlen(path);
__wasi_errno_t error = __wasi_path_remove_directory(fd, path, path_len);
if (error != 0) {

View File

@ -4,7 +4,7 @@
#include <errno.h>
#include <string.h>
int __wasilibc_unlinkat(int fd, const char *path) {
int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) {
size_t path_len = strlen(path);
__wasi_errno_t error = __wasi_path_unlink_file(fd, path, path_len);
if (error != 0) {

View File

@ -0,0 +1,141 @@
// Handle AT_FDCWD and absolute paths for the *at functions.
//
// In the case of an AT_FDCWD file descriptor or an absolute path, call the
// corresponding non-`at` function. This will send it through the libpreopen
// wrappers to convert the path into a directory file descriptor and relative
// path before translating it into the corresponding `__wasilibc_nocwd_*at`
// function, which then calls the appropriate WASI function.
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <wasi/libc.h>
#include <wasi/libc-nocwd.h>
// If the platform doesn't define O_TMPFILE, we don't need to worry about it.
#ifndef O_TMPFILE
#define O_TMPFILE 0
#endif
int openat(int dirfd, const char *pathname, int flags, ...) {
if (dirfd == AT_FDCWD || pathname[0] == '/') {
return open(pathname, flags);
}
return __wasilibc_nocwd_openat_nomode(dirfd, pathname, flags);
}
int symlinkat(const char *target, int dirfd, const char *linkpath) {
if (dirfd == AT_FDCWD || linkpath[0] == '/') {
return symlink(target, linkpath);
}
return __wasilibc_nocwd_symlinkat(target, dirfd, linkpath);
}
ssize_t readlinkat(int dirfd, const char *__restrict pathname, char *__restrict buf, size_t bufsiz) {
if (dirfd == AT_FDCWD || pathname[0] == '/') {
return readlink(pathname, buf, bufsiz);
}
return __wasilibc_nocwd_readlinkat(dirfd, pathname, buf, bufsiz);
}
int mkdirat(int dirfd, const char *pathname, mode_t mode) {
if (dirfd == AT_FDCWD || pathname[0] == '/') {
return mkdir(pathname, mode);
}
return __wasilibc_nocwd_mkdirat_nomode(dirfd, pathname);
}
DIR *opendirat(int dirfd, const char *path) {
if (dirfd == AT_FDCWD || path[0] == '/') {
return opendir(path);
}
return __wasilibc_nocwd_opendirat(dirfd, path);
}
int scandirat(int dirfd, const char *dirp, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)) {
if (dirfd == AT_FDCWD || dirp[0] == '/') {
return scandir(dirp, namelist, filter, compar);
}
return __wasilibc_nocwd_scandirat(dirfd, dirp, namelist, filter, compar);
}
int faccessat(int dirfd, const char *pathname, int mode, int flags) {
if (dirfd == AT_FDCWD || pathname[0] == '/') {
return __wasilibc_access(pathname, mode, flags);
}
return __wasilibc_nocwd_faccessat(dirfd, pathname, mode, flags);
}
int fstatat(int dirfd, const char *__restrict pathname, struct stat *__restrict statbuf, int flags) {
if (dirfd == AT_FDCWD || pathname[0] == '/') {
return __wasilibc_stat(pathname, statbuf, flags);
}
return __wasilibc_nocwd_fstatat(dirfd, pathname, statbuf, flags);
}
int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) {
if (dirfd == AT_FDCWD || pathname[0] == '/') {
return __wasilibc_utimens(pathname, times, flags);
}
return __wasilibc_nocwd_utimensat(dirfd, pathname, times, flags);
}
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) {
if ((olddirfd == AT_FDCWD || oldpath[0] == '/') &&
(newdirfd == AT_FDCWD || newpath[0] == '/')) {
return __wasilibc_link(oldpath, newpath, flags);
}
if (olddirfd == AT_FDCWD || oldpath[0] == '/') {
return __wasilibc_link_newat(oldpath, newdirfd, newpath, flags);
}
if (newdirfd == AT_FDCWD || newpath[0] == '/') {
return __wasilibc_link_oldat(olddirfd, oldpath, newpath, flags);
}
return __wasilibc_nocwd_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
}
int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
if ((olddirfd == AT_FDCWD || oldpath[0] == '/') &&
(newdirfd == AT_FDCWD || newpath[0] == '/')) {
return rename(oldpath, newpath);
}
if (olddirfd == AT_FDCWD || oldpath[0] == '/') {
return __wasilibc_rename_newat(oldpath, newdirfd, newpath);
}
if (newdirfd == AT_FDCWD || newpath[0] == '/') {
return __wasilibc_rename_oldat(olddirfd, oldpath, newpath);
}
return __wasilibc_nocwd_renameat(olddirfd, oldpath, newdirfd, newpath);
}
int __wasilibc_unlinkat(int dirfd, const char *path) {
if (dirfd == AT_FDCWD || path[0] == '/') {
return unlink(path);
}
return __wasilibc_nocwd___wasilibc_unlinkat(dirfd, path);
}
int __wasilibc_rmdirat(int dirfd, const char *path) {
if (dirfd == AT_FDCWD || path[0] == '/') {
return rmdir(path);
}
return __wasilibc_nocwd___wasilibc_rmdirat(dirfd, path);
}

View File

@ -10,6 +10,7 @@
#include <utime.h>
#include <wasi/libc.h>
#include <wasi/libc-find-relpath.h>
#include <wasi/libc-nocwd.h>
static int find_relpath2(
const char *path,
@ -59,7 +60,7 @@ int __wasilibc_open_nomode(const char *path, int oflag) {
return -1;
}
return __wasilibc_openat_nomode(dirfd, relative_path, oflag);
return __wasilibc_nocwd_openat_nomode(dirfd, relative_path, oflag);
}
int access(const char *path, int amode) {
@ -72,7 +73,7 @@ int access(const char *path, int amode) {
return -1;
}
return faccessat(dirfd, relative_path, amode, 0);
return __wasilibc_nocwd_faccessat(dirfd, relative_path, amode, 0);
}
ssize_t readlink(
@ -89,7 +90,7 @@ ssize_t readlink(
return -1;
}
return readlinkat(dirfd, relative_path, buf, bufsize);
return __wasilibc_nocwd_readlinkat(dirfd, relative_path, buf, bufsize);
}
int stat(const char *restrict path, struct stat *restrict buf) {
@ -102,7 +103,7 @@ int stat(const char *restrict path, struct stat *restrict buf) {
return -1;
}
return fstatat(dirfd, relative_path, buf, 0);
return __wasilibc_nocwd_fstatat(dirfd, relative_path, buf, 0);
}
int lstat(const char *restrict path, struct stat *restrict buf) {
@ -115,7 +116,7 @@ int lstat(const char *restrict path, struct stat *restrict buf) {
return -1;
}
return fstatat(dirfd, relative_path, buf, AT_SYMLINK_NOFOLLOW);
return __wasilibc_nocwd_fstatat(dirfd, relative_path, buf, AT_SYMLINK_NOFOLLOW);
}
int utime(const char *path, const struct utimbuf *times) {
@ -128,7 +129,8 @@ int utime(const char *path, const struct utimbuf *times) {
return -1;
}
return utimensat(dirfd, relative_path,
return __wasilibc_nocwd_utimensat(
dirfd, relative_path,
times ? ((struct timespec [2]) {
{ .tv_sec = times->actime },
{ .tv_sec = times->modtime }
@ -150,7 +152,7 @@ int unlink(const char *path) {
// `unlinkat` imports `__wasi_path_remove_directory` even when
// `AT_REMOVEDIR` isn't passed. Instead, use a specialized function which
// just imports `__wasi_path_unlink_file`.
return __wasilibc_unlinkat(dirfd, relative_path);
return __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path);
}
int rmdir(const char *path) {
@ -163,7 +165,7 @@ int rmdir(const char *path) {
return -1;
}
return __wasilibc_rmdirat(dirfd, relative_path);
return __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path);
}
int remove(const char *path) {
@ -177,10 +179,10 @@ int remove(const char *path) {
}
// First try to remove it as a file.
int r = __wasilibc_unlinkat(dirfd, relative_path);
int r = __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path);
if (r != 0 && (errno == EISDIR || errno == ENOTCAPABLE)) {
// That failed, but it might be a directory.
r = __wasilibc_rmdirat(dirfd, relative_path);
r = __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path);
// If it isn't a directory, we lack capabilities to remove it as a file.
if (errno == ENOTDIR)
@ -199,7 +201,7 @@ int mkdir(const char *path, mode_t mode) {
return -1;
}
return mkdirat(dirfd, relative_path, mode);
return __wasilibc_nocwd_mkdirat_nomode(dirfd, relative_path);
}
DIR *opendir(const char *dirname) {
@ -212,7 +214,7 @@ DIR *opendir(const char *dirname) {
return NULL;
}
return opendirat(dirfd, relative_path);
return __wasilibc_nocwd_opendirat(dirfd, relative_path);
}
int scandir(
@ -230,7 +232,7 @@ int scandir(
return -1;
}
return scandirat(dirfd, relative_path, namelist, filter, compar);
return __wasilibc_nocwd_scandirat(dirfd, relative_path, namelist, filter, compar);
}
int symlink(const char *target, const char *linkpath) {
@ -243,7 +245,7 @@ int symlink(const char *target, const char *linkpath) {
return -1;
}
return symlinkat(target, dirfd, relative_path);
return __wasilibc_nocwd_symlinkat(target, dirfd, relative_path);
}
int link(const char *old, const char *new) {
@ -255,8 +257,8 @@ int link(const char *old, const char *new) {
int new_dirfd = find_relpath(new, &new_relative_path);
if (new_dirfd != -1)
return linkat(old_dirfd, old_relative_path,
new_dirfd, new_relative_path, 0);
return __wasilibc_nocwd_linkat(old_dirfd, old_relative_path,
new_dirfd, new_relative_path, 0);
}
// We couldn't find a preopen for it; indicate that we lack capabilities.
@ -273,11 +275,149 @@ int rename(const char *old, const char *new) {
int new_dirfd = find_relpath(new, &new_relative_path);
if (new_dirfd != -1)
return renameat(old_dirfd, old_relative_path,
new_dirfd, new_relative_path);
return __wasilibc_nocwd_renameat(old_dirfd, old_relative_path,
new_dirfd, new_relative_path);
}
// We couldn't find a preopen for it; indicate that we lack capabilities.
errno = ENOTCAPABLE;
return -1;
}
// Like `access`, but with `faccessat`'s flags argument.
int
__wasilibc_access(const char *path, int mode, int flags)
{
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) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_faccessat(dirfd, relative_path,
mode, flags);
}
// Like `utimensat`, but without the `at` part.
int
__wasilibc_utimens(const char *path, const struct timespec times[2], int flags)
{
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) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_utimensat(dirfd, relative_path,
times, flags);
}
// Like `stat`, but with `fstatat`'s flags argument.
int
__wasilibc_stat(const char *__restrict path, struct stat *__restrict st, int flags)
{
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) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_fstatat(dirfd, relative_path, st, flags);
}
// Like `link`, but with `linkat`'s flags argument.
int
__wasilibc_link(const char *oldpath, const char *newpath, int flags)
{
char *old_relative_path;
char *new_relative_path;
int old_dirfd = find_relpath(oldpath, &old_relative_path);
int new_dirfd = find_relpath(newpath, &new_relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (old_dirfd == -1 || new_dirfd == -1) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_linkat(old_dirfd, old_relative_path,
new_dirfd, new_relative_path,
flags);
}
// Like `__wasilibc_link`, but oldpath is relative to olddirfd.
int
__wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, int flags)
{
char *new_relative_path;
int new_dirfd = find_relpath(newpath, &new_relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (new_dirfd == -1) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_linkat(olddirfd, oldpath,
new_dirfd, new_relative_path,
flags);
}
// Like `__wasilibc_link`, but newpath is relative to newdirfd.
int
__wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, int flags)
{
char *old_relative_path;
int old_dirfd = find_relpath(oldpath, &old_relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (old_dirfd == -1) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_linkat(old_dirfd, old_relative_path,
newdirfd, newpath,
flags);
}
// Like `rename`, but from is relative to fromdirfd.
int
__wasilibc_rename_oldat(int fromdirfd, const char *from, const char *to)
{
char *to_relative_path;
int to_dirfd = find_relpath(to, &to_relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (to_dirfd == -1) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_renameat(fromdirfd, from, to_dirfd, to_relative_path);
}
// Like `rename`, but to is relative to todirfd.
int
__wasilibc_rename_newat(const char *from, int todirfd, const char *to)
{
char *from_relative_path;
int from_dirfd = find_relpath(from, &from_relative_path);
// If we can't find a preopen for it, indicate that we lack capabilities.
if (from_dirfd == -1) {
errno = ENOTCAPABLE;
return -1;
}
return __wasilibc_nocwd_renameat(from_dirfd, from_relative_path, todirfd, to);
}

View File

@ -8,6 +8,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
@ -96,7 +97,11 @@ static const char *strip_prefixes(const char *path) {
///
/// This function takes ownership of `prefix`.
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
// Check preconditions.
assert_invariants();
assert(fd != AT_FDCWD);
assert(fd != -1);
assert(relprefix != NULL);
if (num_preopens == preopen_capacity && resize() != 0)
return -1;