master
  1// Handle AT_FDCWD and absolute paths for the *at functions.
  2//
  3// In the case of an AT_FDCWD file descriptor or an absolute path, call the
  4// corresponding non-`at` function. This will send it through the libpreopen
  5// wrappers to convert the path into a directory file descriptor and relative
  6// path before translating it into the corresponding `__wasilibc_nocwd_*at`
  7// function, which then calls the appropriate WASI function.
  8
  9#include <fcntl.h>
 10#include <stdio.h>
 11#include <unistd.h>
 12#include <dirent.h>
 13#include <sys/types.h>
 14#include <sys/stat.h>
 15#include <wasi/libc.h>
 16#include <wasi/libc-nocwd.h>
 17
 18// If the platform doesn't define O_TMPFILE, we don't need to worry about it.
 19#ifndef O_TMPFILE
 20#define O_TMPFILE 0
 21#endif
 22
 23int openat(int dirfd, const char *pathname, int flags, ...) {
 24    if (dirfd == AT_FDCWD || pathname[0] == '/') {
 25        return open(pathname, flags);
 26    }
 27
 28    return __wasilibc_nocwd_openat_nomode(dirfd, pathname, flags);
 29}
 30
 31int symlinkat(const char *target, int dirfd, const char *linkpath) {
 32    if (dirfd == AT_FDCWD || linkpath[0] == '/') {
 33        return symlink(target, linkpath);
 34    }
 35
 36    return __wasilibc_nocwd_symlinkat(target, dirfd, linkpath);
 37}
 38
 39ssize_t readlinkat(int dirfd, const char *__restrict pathname, char *__restrict buf, size_t bufsiz) {
 40    if (dirfd == AT_FDCWD || pathname[0] == '/') {
 41        return readlink(pathname, buf, bufsiz);
 42    }
 43
 44    return __wasilibc_nocwd_readlinkat(dirfd, pathname, buf, bufsiz);
 45}
 46
 47int mkdirat(int dirfd, const char *pathname, mode_t mode) {
 48    if (dirfd == AT_FDCWD || pathname[0] == '/') {
 49        return mkdir(pathname, mode);
 50    }
 51
 52    return __wasilibc_nocwd_mkdirat_nomode(dirfd, pathname);
 53}
 54
 55DIR *opendirat(int dirfd, const char *path) {
 56    if (dirfd == AT_FDCWD || path[0] == '/') {
 57        return opendir(path);
 58    }
 59
 60    return __wasilibc_nocwd_opendirat(dirfd, path);
 61}
 62
 63int scandirat(int dirfd, const char *dirp, struct dirent ***namelist,
 64              int (*filter)(const struct dirent *),
 65              int (*compar)(const struct dirent **, const struct dirent **)) {
 66    if (dirfd == AT_FDCWD || dirp[0] == '/') {
 67        return scandir(dirp, namelist, filter, compar);
 68    }
 69
 70    return __wasilibc_nocwd_scandirat(dirfd, dirp, namelist, filter, compar);
 71}
 72
 73int faccessat(int dirfd, const char *pathname, int mode, int flags) {
 74    if (dirfd == AT_FDCWD || pathname[0] == '/') {
 75        return __wasilibc_access(pathname, mode, flags);
 76    }
 77
 78    return __wasilibc_nocwd_faccessat(dirfd, pathname, mode, flags);
 79}
 80
 81int fstatat(int dirfd, const char *__restrict pathname, struct stat *__restrict statbuf, int flags) {
 82    if (dirfd == AT_FDCWD || pathname[0] == '/') {
 83        return __wasilibc_stat(pathname, statbuf, flags);
 84    }
 85
 86    return __wasilibc_nocwd_fstatat(dirfd, pathname, statbuf, flags);
 87}
 88
 89int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) {
 90    if (dirfd == AT_FDCWD || pathname[0] == '/') {
 91        return __wasilibc_utimens(pathname, times, flags);
 92    }
 93
 94    return __wasilibc_nocwd_utimensat(dirfd, pathname, times, flags);
 95}
 96
 97int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) {
 98    if ((olddirfd == AT_FDCWD || oldpath[0] == '/') &&
 99        (newdirfd == AT_FDCWD || newpath[0] == '/')) {
100        return __wasilibc_link(oldpath, newpath, flags);
101    }
102    if (olddirfd == AT_FDCWD || oldpath[0] == '/') {
103        return __wasilibc_link_newat(oldpath, newdirfd, newpath, flags);
104    }
105    if (newdirfd == AT_FDCWD || newpath[0] == '/') {
106        return __wasilibc_link_oldat(olddirfd, oldpath, newpath, flags);
107    }
108
109    return __wasilibc_nocwd_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
110}
111
112int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
113    if ((olddirfd == AT_FDCWD || oldpath[0] == '/') &&
114        (newdirfd == AT_FDCWD || newpath[0] == '/')) {
115        return rename(oldpath, newpath);
116    }
117    if (olddirfd == AT_FDCWD || oldpath[0] == '/') {
118        return __wasilibc_rename_newat(oldpath, newdirfd, newpath);
119    }
120    if (newdirfd == AT_FDCWD || newpath[0] == '/') {
121        return __wasilibc_rename_oldat(olddirfd, oldpath, newpath);
122    }
123
124    return __wasilibc_nocwd_renameat(olddirfd, oldpath, newdirfd, newpath);
125}
126
127int __wasilibc_unlinkat(int dirfd, const char *path) {
128    if (dirfd == AT_FDCWD || path[0] == '/') {
129        return unlink(path);
130    }
131
132    return __wasilibc_nocwd___wasilibc_unlinkat(dirfd, path);
133}
134
135int __wasilibc_rmdirat(int dirfd, const char *path) {
136    if (dirfd == AT_FDCWD || path[0] == '/') {
137        return rmdir(path);
138    }
139
140    return __wasilibc_nocwd___wasilibc_rmdirat(dirfd, path);
141}