mirror of
https://git.proxmox.com/git/wasi-libc
synced 2025-08-12 10:44:53 +00:00
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:
parent
5ccebd3130
commit
f2e779e5f1
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -56,4 +56,6 @@
|
||||
#define AT_SYMLINK_FOLLOW (0x2)
|
||||
#define AT_REMOVEDIR (0x4)
|
||||
|
||||
#define AT_FDCWD (-2)
|
||||
|
||||
#endif
|
||||
|
58
libc-bottom-half/headers/public/wasi/libc-nocwd.h
Normal file
58
libc-bottom-half/headers/public/wasi/libc-nocwd.h
Normal 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
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
141
libc-bottom-half/sources/at_fdcwd.c
Normal file
141
libc-bottom-half/sources/at_fdcwd.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user