From: Tulio A M Mendes Date: Tue, 10 Feb 2026 01:50:22 +0000 (-0300) Subject: posix: add openat, fstatat, unlinkat syscalls (AT_FDCWD) X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=8e4edac8f54464c043630744db15a991bdf9c07e;p=AdrOS.git posix: add openat, fstatat, unlinkat syscalls (AT_FDCWD) --- diff --git a/include/syscall.h b/include/syscall.h index 62464b0..28e5e5e 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -49,6 +49,10 @@ enum { SYSCALL_CHDIR = 32, SYSCALL_GETCWD = 33, SYSCALL_DUP3 = 35, + + SYSCALL_OPENAT = 36, + SYSCALL_FSTATAT = 37, + SYSCALL_UNLINKAT = 38, }; #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index a146fad..a04a685 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -30,6 +30,10 @@ enum { 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__) @@ -759,6 +763,12 @@ static int syscall_stat_impl(const char* user_path, struct stat* user_st) { 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; @@ -839,6 +849,12 @@ static int syscall_open_impl(const char* user_path, uint32_t flags) { 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; @@ -1029,6 +1045,12 @@ static int syscall_unlink_impl(const char* user_path) { 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; @@ -1286,6 +1308,15 @@ static void syscall_handler(struct registers* regs) { 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); @@ -1381,8 +1412,17 @@ static void syscall_handler(struct registers* regs) { 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; } @@ -1525,6 +1565,14 @@ static void syscall_handler(struct registers* regs) { 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; diff --git a/user/init.c b/user/init.c index 15fe228..4b1e73d 100644 --- a/user/init.c +++ b/user/init.c @@ -74,6 +74,14 @@ enum { SYSCALL_CHDIR = 32, SYSCALL_GETCWD = 33, SYSCALL_DUP3 = 35, + + SYSCALL_OPENAT = 36, + SYSCALL_FSTATAT = 37, + SYSCALL_UNLINKAT = 38, +}; + +enum { + AT_FDCWD = -100, }; enum { @@ -162,6 +170,39 @@ static int sys_write(int fd, const void* buf, uint32_t len) { 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( @@ -1921,6 +1962,39 @@ void _start(void) { (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++) {