Skip to content

Commit f2e779e

Browse files
committed
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.
1 parent 5ccebd3 commit f2e779e

23 files changed

+442
-49
lines changed

expected/wasm32-wasi/defined-symbols.txt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ __uflow
249249
__unlist_locked_file
250250
__uselocale
251251
__utc
252+
__wasilibc_access
252253
__wasilibc_cwd
253254
__wasilibc_ensure_environ
254255
__wasilibc_environ
@@ -258,12 +259,31 @@ __wasilibc_find_abspath
258259
__wasilibc_find_relpath
259260
__wasilibc_find_relpath_alloc
260261
__wasilibc_initialize_environ
262+
__wasilibc_link
263+
__wasilibc_link_newat
264+
__wasilibc_link_oldat
265+
__wasilibc_nocwd___wasilibc_rmdirat
266+
__wasilibc_nocwd___wasilibc_unlinkat
267+
__wasilibc_nocwd_faccessat
268+
__wasilibc_nocwd_fstatat
269+
__wasilibc_nocwd_linkat
270+
__wasilibc_nocwd_mkdirat_nomode
271+
__wasilibc_nocwd_openat_nomode
272+
__wasilibc_nocwd_opendirat
273+
__wasilibc_nocwd_readlinkat
274+
__wasilibc_nocwd_renameat
275+
__wasilibc_nocwd_scandirat
276+
__wasilibc_nocwd_symlinkat
277+
__wasilibc_nocwd_utimensat
261278
__wasilibc_open_nomode
262-
__wasilibc_openat_nomode
263279
__wasilibc_register_preopened_fd
280+
__wasilibc_rename_newat
281+
__wasilibc_rename_oldat
264282
__wasilibc_rmdirat
283+
__wasilibc_stat
265284
__wasilibc_tell
266285
__wasilibc_unlinkat
286+
__wasilibc_utimens
267287
__wasm_call_dtors
268288
__wcscoll_l
269289
__wcsftime_l

expected/wasm32-wasi/include-all.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
#include <wasi/api.h>
167167
#include <wasi/libc-environ.h>
168168
#include <wasi/libc-find-relpath.h>
169+
#include <wasi/libc-nocwd.h>
169170
#include <wasi/libc.h>
170171
#include <wchar.h>
171172
#include <wctype.h>

expected/wasm32-wasi/predefined-macros.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define ARG_MAX 131072
4747
#define ARMAG "!<arch>\n"
4848
#define AT_EACCESS (0x0)
49+
#define AT_FDCWD (-2)
4950
#define AT_REMOVEDIR (0x4)
5051
#define AT_SYMLINK_FOLLOW (0x2)
5152
#define AT_SYMLINK_NOFOLLOW (0x1)
@@ -3021,6 +3022,7 @@
30213022
#define __wasi_libc_environ_h
30223023
#define __wasi_libc_find_relpath_h
30233024
#define __wasi_libc_h
3025+
#define __wasi_libc_nocwd_h
30243026
#define __wasilibc___errno_h
30253027
#define __wasilibc___errno_values_h
30263028
#define __wasilibc___fd_set_h

libc-bottom-half/cloudlibc/src/libc/dirent/opendirat.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
// SPDX-License-Identifier: BSD-2-Clause
44

55
#include <wasi/libc.h>
6+
#include <wasi/libc-nocwd.h>
67
#include <dirent.h>
78
#include <fcntl.h>
89
#include <stddef.h>
910
#include <unistd.h>
1011

11-
DIR *opendirat(int dir, const char *dirname) {
12+
DIR *__wasilibc_nocwd_opendirat(int dir, const char *dirname) {
1213
// Open directory.
13-
int fd = __wasilibc_openat_nomode(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
14+
int fd = __wasilibc_nocwd_openat_nomode(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
1415
if (fd == -1)
1516
return NULL;
1617

libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <wasi/api.h>
66
#include <wasi/libc.h>
7+
#include <wasi/libc-nocwd.h>
78
#include <dirent.h>
89
#include <errno.h>
910
#include <fcntl.h>
@@ -17,15 +18,15 @@ static int sel_true(const struct dirent *de) {
1718
return 1;
1819
}
1920

20-
int scandirat(int dirfd, const char *dir, struct dirent ***namelist,
21-
int (*sel)(const struct dirent *),
22-
int (*compar)(const struct dirent **, const struct dirent **)) {
21+
int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist,
22+
int (*sel)(const struct dirent *),
23+
int (*compar)(const struct dirent **, const struct dirent **)) {
2324
// Match all files if no select function is provided.
2425
if (sel == NULL)
2526
sel = sel_true;
2627

2728
// Open the directory.
28-
int fd = __wasilibc_openat_nomode(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
29+
int fd = __wasilibc_nocwd_openat_nomode(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
2930
if (fd == -1)
3031
return -1;
3132

libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,14 @@ static_assert(O_DIRECTORY >> 12 == __WASI_OFLAGS_DIRECTORY, "Value mismatch");
2222
static_assert(O_EXCL >> 12 == __WASI_OFLAGS_EXCL, "Value mismatch");
2323
static_assert(O_TRUNC >> 12 == __WASI_OFLAGS_TRUNC, "Value mismatch");
2424

25-
int openat(int fd, const char *path, int oflag, ...) {
26-
return __wasilibc_openat_nomode(fd, path, oflag);
27-
}
28-
29-
int __wasilibc_openat_nomode(int fd, const char *path, int oflag) {
25+
int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) {
3026
// Compute rights corresponding with the access modes provided.
3127
// Attempt to obtain all rights, except the ones that contradict the
3228
// access mode provided to openat().
3329
__wasi_rights_t max =
3430
~(__WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ |
3531
__WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_FD_ALLOCATE |
36-
__WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE |
37-
0);
32+
__WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE);
3833
switch (oflag & O_ACCMODE) {
3934
case O_RDONLY:
4035
case O_RDWR:

libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <stdio.h>
1010
#include <string.h>
1111

12-
int renameat(int oldfd, const char *old, int newfd, const char *new) {
12+
int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char *new) {
1313
__wasi_errno_t error = __wasi_path_rename(oldfd, old, strlen(old),
1414
newfd, new, strlen(new));
1515
if (error != 0) {

libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
#include "stat_impl.h"
1515

16-
int fstatat(int fd, const char *restrict path, struct stat *restrict buf,
17-
int flag) {
16+
int __wasilibc_nocwd_fstatat(int fd, const char *restrict path, struct stat *restrict buf,
17+
int flag) {
1818
// Create lookup properties.
1919
__wasi_lookupflags_t lookup_flags = 0;
2020
if ((flag & AT_SYMLINK_NOFOLLOW) == 0)

libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <errno.h>
1111
#include <string.h>
1212

13-
int mkdirat(int fd, const char *path, mode_t mode) {
13+
int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) {
1414
__wasi_errno_t error = __wasi_path_create_directory(
1515
fd, path, strlen(path));
1616
if (error != 0) {

libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
#include "stat_impl.h"
1515

16-
int utimensat(int fd, const char *path, const struct timespec times[2],
17-
int flag) {
16+
int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec times[2],
17+
int flag) {
1818
// Convert timestamps and extract NOW/OMIT flags.
1919
__wasi_timestamp_t st_atim;
2020
__wasi_timestamp_t st_mtim;

libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <string.h>
1111
#include <unistd.h>
1212

13-
int faccessat(int fd, const char *path, int amode, int flag) {
13+
int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) {
1414
// Validate function parameters.
1515
if ((amode & ~(F_OK | R_OK | W_OK | X_OK)) != 0 ||
1616
(flag & ~AT_EACCESS) != 0) {

libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <string.h>
1111
#include <unistd.h>
1212

13-
int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) {
13+
int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) {
1414
// Create lookup properties.
1515
__wasi_lookupflags_t lookup1_flags = 0;
1616
if ((flag & AT_SYMLINK_FOLLOW) != 0)

libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#include <string.h>
1010
#include <unistd.h>
1111

12-
ssize_t readlinkat(int fd, const char *restrict path, char *restrict buf,
13-
size_t bufsize) {
12+
ssize_t __wasilibc_nocwd_readlinkat(int fd, const char *restrict path, char *restrict buf,
13+
size_t bufsize) {
1414
size_t bufused;
1515
// TODO: Remove the cast on `buf` once the witx is updated with char8 support.
1616
__wasi_errno_t error = __wasi_path_readlink(fd, path, strlen(path),

libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <string.h>
1010
#include <unistd.h>
1111

12-
int symlinkat(const char *path1, int fd, const char *path2) {
12+
int __wasilibc_nocwd_symlinkat(const char *path1, int fd, const char *path2) {
1313
__wasi_errno_t error =
1414
__wasi_path_symlink(path1, strlen(path1), fd, path2, strlen(path2));
1515
if (error != 0) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
#include <_/cdefs.h>
22
int snprintf(char *str, size_t size, const char *format, ...);
3+
int rename(const char *oldpath, const char *newpath);

libc-bottom-half/headers/public/__header_fcntl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,6 @@
5656
#define AT_SYMLINK_FOLLOW (0x2)
5757
#define AT_REMOVEDIR (0x4)
5858

59+
#define AT_FDCWD (-2)
60+
5961
#endif
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#ifndef __wasi_libc_nocwd_h
2+
#define __wasi_libc_nocwd_h
3+
4+
/*
5+
* In order to support AT_FDCWD, we need to wrap the *at functions to handle
6+
* it by calling back into the non-at versions which perform libpreopen
7+
* queries. These __wasilibc_nocwd_* forms are the underlying calls which
8+
* assume AT_FDCWD has already been resolved.
9+
*/
10+
11+
#define __need_size_t
12+
#include <stddef.h>
13+
#include <__typedef_ssize_t.h>
14+
#include <__typedef_mode_t.h>
15+
#include <__typedef_DIR.h>
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
struct timespec;
22+
struct stat;
23+
struct dirent;
24+
25+
int __wasilibc_nocwd___wasilibc_unlinkat(int, const char *)
26+
__attribute__((__warn_unused_result__));
27+
int __wasilibc_nocwd___wasilibc_rmdirat(int, const char *)
28+
__attribute__((__warn_unused_result__));
29+
int __wasilibc_nocwd_linkat(int, const char *, int, const char *, int)
30+
__attribute__((__warn_unused_result__));
31+
int __wasilibc_nocwd_symlinkat(const char *, int, const char *)
32+
__attribute__((__warn_unused_result__));
33+
ssize_t __wasilibc_nocwd_readlinkat(int, const char *__restrict, char *__restrict, size_t)
34+
__attribute__((__warn_unused_result__));
35+
int __wasilibc_nocwd_faccessat(int, const char *, int, int)
36+
__attribute__((__warn_unused_result__));
37+
int __wasilibc_nocwd_renameat(int, const char *, int, const char *)
38+
__attribute__((__warn_unused_result__));
39+
int __wasilibc_nocwd_openat_nomode(int, const char *, int)
40+
__attribute__((__warn_unused_result__));
41+
int __wasilibc_nocwd_fstatat(int, const char *__restrict, struct stat *__restrict, int)
42+
__attribute__((__warn_unused_result__));
43+
int __wasilibc_nocwd_mkdirat_nomode(int, const char *)
44+
__attribute__((__warn_unused_result__));
45+
int __wasilibc_nocwd_utimensat(int, const char *, const struct timespec [2], int)
46+
__attribute__((__warn_unused_result__));
47+
DIR *__wasilibc_nocwd_opendirat(int, const char *)
48+
__attribute__((__warn_unused_result__));
49+
int __wasilibc_nocwd_scandirat(int, const char *, struct dirent ***,
50+
int (*)(const struct dirent *),
51+
int (*)(const struct dirent **, const struct dirent **))
52+
__attribute__((__warn_unused_result__));
53+
54+
#ifdef __cplusplus
55+
}
56+
#endif
57+
58+
#endif

libc-bottom-half/headers/public/wasi/libc.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,32 @@
22
#define __wasi_libc_h
33

44
#include <__typedef_off_t.h>
5+
#include <__struct_timespec.h>
56

67
#ifdef __cplusplus
78
extern "C" {
89
#endif
910

11+
struct stat;
12+
struct timespec;
13+
1014
/// Register the given pre-opened file descriptor under the given path.
1115
///
1216
/// This function does not take ownership of `prefix` (it makes its own copy).
1317
int __wasilibc_register_preopened_fd(int fd, const char *prefix);
1418

1519
/// Renumber `fd` to `newfd`; similar to `dup2` but does a move rather than a
1620
/// copy.
17-
int __wasilibc_fd_renumber(int fd, int newfd);
21+
int __wasilibc_fd_renumber(int fd, int newfd)
22+
__attribute__((__warn_unused_result__));
1823

1924
/// Like `unlinkat`, but without depending on `__wasi_path_remove_directory`.
20-
int __wasilibc_unlinkat(int fd, const char *path);
25+
int __wasilibc_unlinkat(int fd, const char *path)
26+
__attribute__((__warn_unused_result__));
2127

2228
/// An `*at` version of rmdir.
23-
int __wasilibc_rmdirat(int fd, const char *path);
29+
int __wasilibc_rmdirat(int fd, const char *path)
30+
__attribute__((__warn_unused_result__));
2431

2532
/// Like `open`, but without the varargs in the signature.
2633
int __wasilibc_open_nomode(const char *path, int oflag);
@@ -30,7 +37,26 @@ int __wasilibc_openat_nomode(int fd, const char *path, int oflag);
3037

3138
/// Return the current file offset. Like `lseek(fd, 0, SEEK_CUR)`, but without
3239
/// depending on `lseek`.
33-
off_t __wasilibc_tell(int fd);
40+
off_t __wasilibc_tell(int fd)
41+
__attribute__((__warn_unused_result__));
42+
43+
/* Non-`at` forms of various `*at` functions. */
44+
int __wasilibc_access(const char *pathname, int mode, int flags)
45+
__attribute__((__warn_unused_result__));
46+
int __wasilibc_stat(const char *__restrict pathname, struct stat *__restrict statbuf, int flags)
47+
__attribute__((__warn_unused_result__));
48+
int __wasilibc_utimens(const char *pathname, const struct timespec times[2], int flags)
49+
__attribute__((__warn_unused_result__));
50+
int __wasilibc_link(const char *oldpath, const char *newpath, int flags)
51+
__attribute__((__warn_unused_result__));
52+
int __wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, int flags)
53+
__attribute__((__warn_unused_result__));
54+
int __wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, int flags)
55+
__attribute__((__warn_unused_result__));
56+
int __wasilibc_rename_oldat(int olddirfd, const char *oldpath, const char *newpath)
57+
__attribute__((__warn_unused_result__));
58+
int __wasilibc_rename_newat(const char *oldpath, int newdirfd, const char *newpath)
59+
__attribute__((__warn_unused_result__));
3460

3561
#ifdef __cplusplus
3662
}

libc-bottom-half/sources/__wasilibc_rmdirat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <errno.h>
55
#include <string.h>
66

7-
int __wasilibc_rmdirat(int fd, const char *path) {
7+
int __wasilibc_nocwd___wasilibc_rmdirat(int fd, const char *path) {
88
size_t path_len = strlen(path);
99
__wasi_errno_t error = __wasi_path_remove_directory(fd, path, path_len);
1010
if (error != 0) {

libc-bottom-half/sources/__wasilibc_unlinkat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <errno.h>
55
#include <string.h>
66

7-
int __wasilibc_unlinkat(int fd, const char *path) {
7+
int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) {
88
size_t path_len = strlen(path);
99
__wasi_errno_t error = __wasi_path_unlink_file(fd, path, path_len);
1010
if (error != 0) {

0 commit comments

Comments
 (0)