Skip to content

Commit

Permalink
mkdir
Browse files Browse the repository at this point in the history
Fix #122

`AT_REMOVEDIR` on RISC-V/Spike differs between MacOS and Linux:

  * Spike/MacOS: 0x080
  * Spike/Linux: 0x200

This cannot distinguish naively,
so define implicit macro.
  • Loading branch information
tyfkda committed Nov 2, 2024
1 parent 39f6845 commit f3d9646
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 4 deletions.
11 changes: 11 additions & 0 deletions include/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@

#define AT_SYMLINK_NOFOLLOW 0x100
#define AT_SYMLINK_FOLLOW 0x400

/* Flag for faccessat(2). */
#define AT_EACCESS 0x200

/* Flag for unlinkat(2). */
#if defined(__AT_REMOVEDIR)
#define AT_REMOVEDIR __AT_REMOVEDIR
#elif defined(__APPLE__)
#define AT_REMOVEDIR 0x080
#else
#define AT_REMOVEDIR 0x200
#endif

int open(const char *fn, int flag, ...);
int openat(int dirfd, const char *fn, int flag, ...);
3 changes: 3 additions & 0 deletions include/sys/stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ struct stat {
};
#endif

int mkdir(const char *pathname, mode_t mode);
int mkdirat(int dirfd, const char *pathname, mode_t mode);

int chmod(const char *pathname, mode_t mode);
int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);

Expand Down
1 change: 1 addition & 0 deletions include/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ int close(int fd);
ssize_t read(int fd, void *buf, size_t size);
off_t lseek(int fd, off_t offset, int whence);
int unlink(const char *pathname);
int rmdir(const char *pathname);
char *getcwd(char *buffer, size_t size);

int brk(void *addr);
Expand Down
38 changes: 38 additions & 0 deletions libsrc/_wasm/unistd/mkdir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "sys/stat.h"
#include "string.h" // memset, strncmp
#include "../wasi.h"

extern int __max_preopen_fd;

int mkdir(const char *fn, mode_t mode) {
size_t fnlen = strlen(fn);
for (int base_fd = 3; base_fd < __max_preopen_fd; ++base_fd) {
Prestat prestat;
fd_prestat_get(base_fd, &prestat);
size_t l = prestat.u.dir.pr_name_len; // Includes '\0' or not, depending on the environment,
char buf[256];
fd_prestat_dir_name(base_fd, buf, l);
buf[l] = '\0';

if ((*fn == '/' && *buf != '/') ||
(*fn != '/' && strcmp(buf, ".") != 0))
continue;

const char *fn2 = fn;
size_t fnlen2 = fnlen;

if (strncmp(fn, buf, l) == 0 && fn[l] == '/') {
fn2 = fn + (l + 1);
fnlen2 = fnlen - (l + 1);
} else if (l == 1 && *buf == '/' && *fn == '/') {
fn2 = fn + 1;
fnlen2 = fnlen - 1;
}

Filestat fs;
uint32_t result = path_create_directory(base_fd, fn2, fnlen2);
if (result == 0)
return 0;
}
return -1;
}
40 changes: 40 additions & 0 deletions libsrc/_wasm/unistd/rmdir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "unistd.h"
#include "errno.h"
#include "string.h"
#include "../wasi.h"

extern int __max_preopen_fd;

int rmdir(const char *fn) {
// Search from preopens
size_t fnlen = strlen(fn);
for (int base_fd = 3; base_fd < __max_preopen_fd; ++base_fd) {
Prestat prestat;
if (fd_prestat_get(base_fd, &prestat) != 0)
break;

size_t l = prestat.u.dir.pr_name_len; // Includes '\0' or not, depending on the environment,
char buf[256];
fd_prestat_dir_name(base_fd, buf, l);
buf[l] = '\0';

if ((*fn == '/' && *buf != '/') ||
(*fn != '/' && strcmp(buf, ".") != 0))
continue;

const char *fn2 = fn;
size_t fnlen2 = fnlen;

if (strncmp(fn, buf, l) == 0 && fn[l] == '/') {
fn2 = fn + (l + 1);
fnlen2 = fnlen - (l + 1);
} else if (l == 1 && *buf == '/' && *fn == '/') {
fn2 = fn + 1;
fnlen2 = fnlen - 1;
}
int result = path_remove_directory(base_fd, fn2, fnlen2);
if (result == 0)
return 0;
}
return -1;
}
2 changes: 2 additions & 0 deletions libsrc/_wasm/wasi.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ WASI_MODULE int path_open(int fd, int dirflags, const char *path, size_t path_le
uint64_t fs_rights_base, uint64_t fs_rights_inherting, uint16_t fdflags,
uint32_t *opend_fd);
WASI_MODULE int path_unlink_file(int fd, const char *path, size_t path_len);
WASI_MODULE int path_create_directory(int fd, const char *path, size_t path_len);
WASI_MODULE int path_remove_directory(int fd, const char *path, size_t path_len);
WASI_MODULE int path_filestat_get(int fd, int flags, const char *path, size_t path_len, Filestat *out);

WASI_MODULE int fd_read(int fd, const void *iov, int count, size_t *out);
Expand Down
17 changes: 13 additions & 4 deletions libsrc/tests/file_test.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#include <string.h>

Expand Down Expand Up @@ -44,6 +45,17 @@ TEST(basic_access) {

// remove
EXPECT_EQ(0, remove(fn));

// mkdir
{
const char dn[] = "tmp_ddd";
int r;
EXPECT_EQ(0, r = mkdir(dn, 0755));
if (r == 0) {
// rmdir
EXPECT_EQ(0, rmdir(dn));
}
}
}

TEST(stat) {
Expand All @@ -63,13 +75,11 @@ TEST(stat) {
EXPECT_FALSE(S_ISDIR(st.st_mode));
}

// remove(fn);
remove(fn);
}

// Test directory.
// TODO: Add `mkdir`
const char dn[] = "tests";
// EXPECT_EQ(0, mkdir(dn, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));
{
struct stat st;
int r;
Expand All @@ -79,7 +89,6 @@ TEST(stat) {
EXPECT_FALSE(S_ISREG(st.st_mode));
}
}
// EXPECT_EQ(0, rmdir());
}

TEST(ungetc) {
Expand Down
5 changes: 5 additions & 0 deletions libsrc/unistd/_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@
#define __NR_kill 62
#define __NR_getcwd 79
#define __NR_chdir 80
#define __NR_mkdir 83
#define __NR_rmdir 84
#define __NR_unlink 87
#define __NR_chmod 90
#define __NR_time 201
#define __NR_clock_gettime 228
#define __NR_mkdirat 258
#define __NR_newfstatat 262

#elif defined(__aarch64__)
Expand Down Expand Up @@ -77,6 +80,7 @@
#define __NR_unlinkat 35
#define __NR_fchmodat 53
#define __NR_clock_gettime 113
#define __NR_mkdirat 34
#define __NR_newfstatat 79

#elif defined(__riscv)
Expand Down Expand Up @@ -107,6 +111,7 @@
#define __NR_wait4 260
#define __NR_fstat 80
#define __NR_fstatat 79
#define __NR_mkdirat 34
#define __NR_unlinkat 35

#else
Expand Down
22 changes: 22 additions & 0 deletions libsrc/unistd/mkdir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "sys/stat.h"
#include "_syscall.h"
#include "errno.h"

#if defined(__NR_mkdir)
int mkdir(const char *pathname, mode_t mode) {
int ret;
SYSCALL_RET(__NR_mkdir, ret);
if (ret < 0) {
errno = -ret;
ret = -1;
}
return ret;
}

#elif defined(__NR_mkdirat)
#include "fcntl.h"

int mkdir(const char *pathname, mode_t mode) {
return mkdirat(AT_FDCWD, pathname, mode);
}
#endif
15 changes: 15 additions & 0 deletions libsrc/unistd/mkdirat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "sys/stat.h"
#include "_syscall.h"
#include "errno.h"

#if defined(__NR_mkdirat)
int mkdirat(int dirfd, const char *pathname, mode_t mode) {
int ret;
SYSCALL_RET(__NR_mkdirat, ret);
if (ret < 0) {
errno = -ret;
ret = -1;
}
return ret;
}
#endif
23 changes: 23 additions & 0 deletions libsrc/unistd/rmdir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "sys/stat.h"
#include "_syscall.h"
#include "errno.h"

#if defined(__NR_rmdir)
int rmdir(const char *pathname) {
int ret;
SYSCALL_RET(__NR_rmdir, ret);
if (ret < 0) {
errno = -ret;
ret = -1;
}
return ret;
}

#elif defined(__NR_unlinkat)
#include "unistd.h"
#include "fcntl.h"

int rmdir(const char *pathname) {
return unlinkat(AT_FDCWD, pathname, AT_REMOVEDIR);
}
#endif
9 changes: 9 additions & 0 deletions src/xcc/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

#include "util.h"

// Hack: AT_REMOVEDIR defined in riscv-gnu-toolchain differs on MacOS and Linux?
#if defined(__APPLE__) && !defined(__AT_REMOVEDIR)
#define __AT_REMOVEDIR 0x080
#endif

static pid_t fork1(void) {
pid_t pid = fork();
if (pid < 0)
Expand Down Expand Up @@ -635,6 +640,10 @@ static void append_predefined_macros(Vector *cpp_cmd) {
#if defined(__NO_WCHAR)
vec_push(cpp_cmd, "-D__NO_WCHAR");
#endif

#if defined(__AT_REMOVEDIR)
vec_push(cpp_cmd, "-D__AT_REMOVEDIR=" STR(__AT_REMOVEDIR));
#endif
}

int main(int argc, char *argv[]) {
Expand Down

0 comments on commit f3d9646

Please sign in to comment.