Skip to content

Commit

Permalink
AT_FDCWD support.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sunfishcode committed Feb 5, 2021
1 parent 5ccebd3 commit 2493211
Show file tree
Hide file tree
Showing 23 changed files with 442 additions and 49 deletions.
22 changes: 21 additions & 1 deletion expected/wasm32-wasi/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ __uflow
__unlist_locked_file
__uselocale
__utc
__wasilibc_access
__wasilibc_cwd
__wasilibc_ensure_environ
__wasilibc_environ
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions expected/wasm32-wasi/include-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
2 changes: 2 additions & 0 deletions expected/wasm32-wasi/predefined-macros.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions libc-bottom-half/cloudlibc/src/libc/dirent/opendirat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
9 changes: 5 additions & 4 deletions libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;

Expand Down
9 changes: 2 additions & 7 deletions libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions libc-bottom-half/headers/private/stdio.h
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 2 additions & 0 deletions libc-bottom-half/headers/public/__header_fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@
#define AT_SYMLINK_FOLLOW (0x2)
#define AT_REMOVEDIR (0x4)

#define AT_FDCWD (-2)

#endif
58 changes: 58 additions & 0 deletions libc-bottom-half/headers/public/wasi/libc-nocwd.h
Original file line number Diff line number Diff line change
@@ -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
34 changes: 30 additions & 4 deletions libc-bottom-half/headers/public/wasi/libc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,32 @@
#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).
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);
Expand All @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/sources/__wasilibc_rmdirat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/sources/__wasilibc_unlinkat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 2493211

Please sign in to comment.