FCNTL_F_SETFL = 4,
};
+enum {
+ AT_FDCWD = -100,
+};
+
static int path_resolve_user(const char* user_path, char* out, size_t out_sz);
#if defined(__i386__)
return 0;
}
+static int syscall_fstatat_impl(int dirfd, const char* user_path, struct stat* user_st, uint32_t flags) {
+ (void)flags;
+ if (dirfd != AT_FDCWD) return -ENOSYS;
+ return syscall_stat_impl(user_path, user_st);
+}
+
static int syscall_fstat_impl(int fd, struct stat* user_st) {
if (!user_st) return -EFAULT;
if (user_range_ok(user_st, sizeof(*user_st)) == 0) return -EFAULT;
return fd;
}
+static int syscall_openat_impl(int dirfd, const char* user_path, uint32_t flags, uint32_t mode) {
+ (void)mode;
+ if (dirfd != AT_FDCWD) return -ENOSYS;
+ return syscall_open_impl(user_path, flags);
+}
+
static int syscall_fcntl_impl(int fd, int cmd, uint32_t arg) {
struct file* f = fd_get(fd);
if (!f) return -EBADF;
return -ENOSYS;
}
+static int syscall_unlinkat_impl(int dirfd, const char* user_path, uint32_t flags) {
+ (void)flags;
+ if (dirfd != AT_FDCWD) return -ENOSYS;
+ return syscall_unlink_impl(user_path);
+}
+
static int syscall_read_impl(int fd, void* user_buf, uint32_t len) {
if (len > 1024 * 1024) return -EINVAL;
if (user_range_ok(user_buf, (size_t)len) == 0) return -EFAULT;
return;
}
+ if (syscall_no == SYSCALL_OPENAT) {
+ int dirfd = (int)regs->ebx;
+ const char* path = (const char*)regs->ecx;
+ uint32_t flags = (uint32_t)regs->edx;
+ uint32_t mode = (uint32_t)regs->esi;
+ regs->eax = (uint32_t)syscall_openat_impl(dirfd, path, flags, mode);
+ return;
+ }
+
if (syscall_no == SYSCALL_CHDIR) {
const char* path = (const char*)regs->ebx;
regs->eax = (uint32_t)syscall_chdir_impl(path);
if (syscall_no == SYSCALL_STAT) {
const char* path = (const char*)regs->ebx;
- struct stat* st = (struct stat*)regs->ecx;
- regs->eax = (uint32_t)syscall_stat_impl(path, st);
+ struct stat* user_st = (struct stat*)regs->ecx;
+ regs->eax = (uint32_t)syscall_stat_impl(path, user_st);
+ return;
+ }
+
+ if (syscall_no == SYSCALL_FSTATAT) {
+ int dirfd = (int)regs->ebx;
+ const char* path = (const char*)regs->ecx;
+ struct stat* user_st = (struct stat*)regs->edx;
+ uint32_t flags = (uint32_t)regs->esi;
+ regs->eax = (uint32_t)syscall_fstatat_impl(dirfd, path, user_st, flags);
return;
}
return;
}
+ if (syscall_no == SYSCALL_UNLINKAT) {
+ int dirfd = (int)regs->ebx;
+ const char* path = (const char*)regs->ecx;
+ uint32_t flags = (uint32_t)regs->edx;
+ regs->eax = (uint32_t)syscall_unlinkat_impl(dirfd, path, flags);
+ return;
+ }
+
if (syscall_no == SYSCALL_GETDENTS) {
int fd = (int)regs->ebx;
void* buf = (void*)regs->ecx;
SYSCALL_CHDIR = 32,
SYSCALL_GETCWD = 33,
SYSCALL_DUP3 = 35,
+
+ SYSCALL_OPENAT = 36,
+ SYSCALL_FSTATAT = 37,
+ SYSCALL_UNLINKAT = 38,
+};
+
+enum {
+ AT_FDCWD = -100,
};
enum {
return __syscall_fix(ret);
}
+static int sys_openat(int dirfd, const char* path, uint32_t flags, uint32_t mode) {
+ int ret;
+ __asm__ volatile(
+ "int $0x80"
+ : "=a"(ret)
+ : "a"(SYSCALL_OPENAT), "b"(dirfd), "c"(path), "d"(flags), "S"(mode)
+ : "memory"
+ );
+ return __syscall_fix(ret);
+}
+
+static int sys_fstatat(int dirfd, const char* path, struct stat* st, uint32_t flags) {
+ int ret;
+ __asm__ volatile(
+ "int $0x80"
+ : "=a"(ret)
+ : "a"(SYSCALL_FSTATAT), "b"(dirfd), "c"(path), "d"(st), "S"(flags)
+ : "memory"
+ );
+ return __syscall_fix(ret);
+}
+
+static int sys_unlinkat(int dirfd, const char* path, uint32_t flags) {
+ int ret;
+ __asm__ volatile(
+ "int $0x80"
+ : "=a"(ret)
+ : "a"(SYSCALL_UNLINKAT), "b"(dirfd), "c"(path), "d"(flags)
+ : "memory"
+ );
+ return __syscall_fix(ret);
+}
+
static int sys_pipe2(int fds[2], uint32_t flags) {
int ret;
__asm__ volatile(
(uint32_t)(sizeof("[init] chdir/getcwd OK\n") - 1));
}
+ // B8: *at() syscalls smoke (AT_FDCWD)
+ {
+ int fd = sys_openat(AT_FDCWD, "atfile", O_CREAT | O_TRUNC, 0);
+ if (fd < 0) {
+ sys_write(1, "[init] openat failed\n",
+ (uint32_t)(sizeof("[init] openat failed\n") - 1));
+ sys_exit(1);
+ }
+ (void)sys_close(fd);
+
+ struct stat st;
+ if (sys_fstatat(AT_FDCWD, "atfile", &st, 0) < 0) {
+ sys_write(1, "[init] fstatat failed\n",
+ (uint32_t)(sizeof("[init] fstatat failed\n") - 1));
+ sys_exit(1);
+ }
+
+ if (sys_unlinkat(AT_FDCWD, "atfile", 0) < 0) {
+ sys_write(1, "[init] unlinkat failed\n",
+ (uint32_t)(sizeof("[init] unlinkat failed\n") - 1));
+ sys_exit(1);
+ }
+
+ if (sys_stat("atfile", &st) >= 0) {
+ sys_write(1, "[init] unlinkat did not remove file\n",
+ (uint32_t)(sizeof("[init] unlinkat did not remove file\n") - 1));
+ sys_exit(1);
+ }
+
+ sys_write(1, "[init] *at OK\n",
+ (uint32_t)(sizeof("[init] *at OK\n") - 1));
+ }
+
enum { NCHILD = 100 };
int children[NCHILD];
for (int i = 0; i < NCHILD; i++) {