summaryrefslogtreecommitdiff
path: root/na/kernel/sys_fs.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
commite90b72ec3082588b296956730bd2930cf8d5d671 (patch)
tree36ff6916af9b4176ea5a9662219d11e721f0b691 /na/kernel/sys_fs.cc
parent1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff)
downloadlume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz
lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'na/kernel/sys_fs.cc')
-rw-r--r--na/kernel/sys_fs.cc679
1 files changed, 0 insertions, 679 deletions
diff --git a/na/kernel/sys_fs.cc b/na/kernel/sys_fs.cc
deleted file mode 100644
index 1d26fdd..0000000
--- a/na/kernel/sys_fs.cc
+++ /dev/null
@@ -1,679 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * sys_fs.cc — Filesystem-related syscall handlers
- *
- * Implements: openat, close, read, write, lseek, fstat, getdents64,
- * dup, dup3, getcwd, chdir, mkdirat, unlinkat
- */
-
-#include <lume/syscall.h>
-#include <lume/syscall_nr.h>
-#include <lume/errno.h>
-#include <lume/console.h>
-#include <lume/task.h>
-#include <lume/fs.h>
-#include <lume/file.h>
-#include <lume/dcache.h>
-#include <lume/namei.h>
-#include <lume/fdtable.h>
-#include <lume/fs_struct.h>
-#include <lume/mount.h>
-#include <lume/fs_types.h>
-#include <lume/klog.h>
-
-/* ================================================================== */
-/* Helpers */
-/* ================================================================== */
-
-static files_struct* current_files()
-{
- TaskControlBlock* t = current_task();
- return t ? t->files : nullptr;
-}
-
-static fs_struct* current_fs()
-{
- TaskControlBlock* t = current_task();
- return t ? t->fs : nullptr;
-}
-
-/* ================================================================== */
-/* sys_openat(dirfd, pathname, flags, mode) */
-/* ================================================================== */
-
-int64 sys_openat(uint64 a0, uint64 a1, uint64 a2,
- uint64 a3, uint64 /*a4*/, uint64 /*a5*/)
-{
- int dirfd = static_cast<int>(a0);
- const char* pathname = reinterpret_cast<const char*>(a1);
- int flags = static_cast<int>(a2);
- uint32 mode = static_cast<uint32>(a3);
-
- files_struct* files = current_files();
- if (!files) return -EMFILE;
-
-
- /* Pathname lookup */
- path p{};
- int err = filename_lookup(dirfd, pathname, 0, &p);
-
- if (err == -ENOENT && (flags & O_CREAT)) {
- /* Create: look up the parent directory */
- /* Find last '/' to split parent path / filename */
- const char* last_slash = nullptr;
- for (const char* s = pathname; *s; s++) {
- if (*s == '/') last_slash = s;
- }
-
- if (!last_slash || last_slash == pathname) {
- /* File in root or current directory */
- path parent{};
- if (last_slash == pathname) {
- /* Absolute: parent is root */
- parent.de = g_root_dentry;
- parent.mnt = g_root_mnt;
- } else {
- /* Relative: parent is cwd */
- fs_struct* fs = current_fs();
- if (!fs) return -ENOENT;
- parent = fs->pwd;
- }
-
- const char* name = last_slash ? last_slash + 1 : pathname;
- inode* dir_ip = parent.de->d_inode;
- if (!dir_ip || !dir_ip->i_op || !dir_ip->i_op->create) {
- return -EACCES;
- }
-
- /* Create the inode via the directory's i_op->create */
- qstr q{};
- q.name = name;
- q.len = 0;
- for (const char* s = name; *s; s++) q.len++;
- dentry* new_de = d_alloc(parent.de, &q);
- if (!new_de) return -ENOMEM;
-
-
- err = dir_ip->i_op->create(dir_ip, new_de, mode & ~S_IFMT, false);
- if (err) {
- /* TODO: free new_de */
- return err;
- }
-
- p.de = new_de;
- p.mnt = parent.mnt;
- } else {
- /* TODO: multi-component parent lookup */
- return -ENOENT;
- }
- } else if (err) {
- return err;
- }
-
- /* Allocate fd */
- int fd = alloc_fd(files, 0);
- if (fd < 0) {
- return fd;
- }
-
- /* Allocate file object */
- file* fp = alloc_empty_file(flags);
- if (!fp) {
- /* TODO: release fd */
- return -ENFILE;
- }
-
- fp->f_inode = p.de->d_inode;
- fp->f_path = p;
- fp->f_op = p.de->d_inode->i_fop;
- fp->f_pos = 0;
-
- /* Chardev: look up cdev by i_rdev and replace f_op */
- if (S_ISCHR(fp->f_inode->i_mode)) {
- extern int devfs_chrdev_open(inode* ip, file* fp);
- err = devfs_chrdev_open(fp->f_inode, fp);
- if (err) {
- fput(fp);
- return err;
- }
- } else if (fp->f_op && fp->f_op->open) {
- err = fp->f_op->open(fp->f_inode, fp);
- if (err) {
- fput(fp);
- return err;
- }
- }
-
- /* O_TRUNC for regular files */
- if ((flags & O_TRUNC) && S_ISREG(fp->f_inode->i_mode)) {
- fp->f_inode->i_size = 0;
- }
-
- fd_install(files, fd, fp);
- return fd;
-}
-
-/* ================================================================== */
-/* sys_close(fd) */
-/* ================================================================== */
-
-int64 sys_close(uint64 a0, uint64 /*a1*/, uint64 /*a2*/,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- files_struct* files = current_files();
- if (!files) return -EBADF;
- return close_fd(files, fd);
-}
-
-/* ================================================================== */
-/* sys_read(fd, buf, count) */
-/* ================================================================== */
-
-int64 sys_read(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- char* buf = reinterpret_cast<char*>(a1);
- uint64 count = a2;
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
-
- if (!(fp->f_mode & FMODE_READ)) return -EBADF;
-
- return vfs_read(fp, buf, count, &fp->f_pos);
-}
-
-/* ================================================================== */
-/* sys_write(fd, buf, count) */
-/* ================================================================== */
-
-int64 sys_write(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- const char* buf = reinterpret_cast<const char*>(a1);
- uint64 count = a2;
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
-
- if (!(fp->f_mode & FMODE_WRITE)) return -EBADF;
-
- return vfs_write(fp, buf, count, &fp->f_pos);
-}
-
-/* ================================================================== */
-/* sys_lseek(fd, offset, whence) */
-/* ================================================================== */
-
-int64 sys_lseek(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- int64 offset = static_cast<int64>(a1);
- int whence = static_cast<int>(a2);
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
-
- return vfs_llseek(fp, offset, whence);
-}
-
-/* ================================================================== */
-/* sys_fstat(fd, statbuf) */
-/* ================================================================== */
-
-int64 sys_fstat_wrapper(uint64 a0, uint64 a1, uint64 /*a2*/,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- auto* statbuf = reinterpret_cast<kstat*>(a1);
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
-
- return vfs_fstat(fp, statbuf);
-}
-
-/* ================================================================== */
-/* sys_getdents64(fd, dirp, count) */
-/* ================================================================== */
-
-struct linux_dirent64 {
- uint64 d_ino;
- int64 d_off;
- uint16 d_reclen;
- uint8 d_type;
- char d_name[];
-};
-
-struct getdents_ctx {
- dir_context ctx;
- char* buf;
- int count;
- int written;
- int error;
-};
-
-static bool filldir64(dir_context* ctx, const char* name, int namelen,
- int64 offset, uint64 ino, unsigned int d_type)
-{
- auto* gctx = container_of(ctx, getdents_ctx, ctx);
-
- /* Calculate record length (rounded up to 8 bytes) */
- int reclen = static_cast<int>(
- (sizeof(linux_dirent64) + namelen + 1 + 7) & ~7ULL);
-
- if (gctx->written + reclen > gctx->count) {
- return false; /* Buffer full */
- }
-
- auto* dirent = reinterpret_cast<linux_dirent64*>(
- gctx->buf + gctx->written);
-
- dirent->d_ino = ino;
- dirent->d_off = offset + 1;
- dirent->d_reclen = static_cast<uint16>(reclen);
- dirent->d_type = static_cast<uint8>(d_type);
-
- /* Copy name */
- for (int i = 0; i < namelen; i++) {
- dirent->d_name[i] = name[i];
- }
- dirent->d_name[namelen] = '\0';
-
- gctx->written += reclen;
- return true;
-}
-
-int64 sys_getdents64(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- char* buf = reinterpret_cast<char*>(a1);
- int count = static_cast<int>(a2);
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
-
- if (!fp->f_op || !fp->f_op->iterate_shared) {
- return -ENOTDIR;
- }
-
- getdents_ctx gctx{};
- gctx.ctx.actor = filldir64;
- gctx.ctx.pos = fp->f_pos;
- gctx.buf = buf;
- gctx.count = count;
- gctx.written = 0;
- gctx.error = 0;
-
- fp->f_op->iterate_shared(fp, &gctx.ctx);
- fp->f_pos = gctx.ctx.pos;
-
- return gctx.written;
-}
-
-/* ================================================================== */
-/* sys_dup(oldfd) */
-/* ================================================================== */
-
-int64 sys_dup(uint64 a0, uint64 /*a1*/, uint64 /*a2*/,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int oldfd = static_cast<int>(a0);
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, oldfd);
- if (!fp) return -EBADF;
-
- int newfd = alloc_fd(files, 0);
- if (newfd < 0) return newfd;
-
- get_file(fp);
- fd_install(files, newfd, fp);
- return newfd;
-}
-
-/* ================================================================== */
-/* sys_dup3(oldfd, newfd, flags) */
-/* ================================================================== */
-
-int64 sys_dup3(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int oldfd = static_cast<int>(a0);
- int newfd = static_cast<int>(a1);
- int flags = static_cast<int>(a2);
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- return do_dup2(files, oldfd, newfd, flags);
-}
-
-/* ================================================================== */
-/* sys_getcwd(buf, size) */
-/* ================================================================== */
-
-int64 sys_getcwd(uint64 a0, uint64 a1, uint64 /*a2*/,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- char* buf = reinterpret_cast<char*>(a0);
- uint64 size = a1;
-
- if (!buf || size == 0) return -EINVAL;
-
- fs_struct* fs = current_fs();
- if (!fs) return -ENOENT;
-
- char tmp[256];
- char* result = d_path(&fs->pwd, tmp, sizeof(tmp));
- if (!result) return -ERANGE;
-
- /* Calculate length */
- int len = 0;
- for (const char* s = result; *s; s++) len++;
- len++; /* Include NUL */
-
- if (static_cast<uint64>(len) > size) return -ERANGE;
-
- for (int i = 0; i < len; i++) {
- buf[i] = result[i];
- }
-
- return len;
-}
-
-/* ================================================================== */
-/* sys_chdir(pathname) */
-/* ================================================================== */
-
-int64 sys_chdir(uint64 a0, uint64 /*a1*/, uint64 /*a2*/,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- const char* pathname = reinterpret_cast<const char*>(a0);
-
- path p{};
- int err = filename_lookup(AT_FDCWD, pathname, LOOKUP_DIRECTORY, &p);
- if (err) return err;
-
- if (!S_ISDIR(p.de->d_inode->i_mode)) {
- path_put(&p);
- return -ENOTDIR;
- }
-
- fs_struct* fs = current_fs();
- if (!fs) {
- path_put(&p);
- return -ENOENT;
- }
-
- set_fs_pwd(fs, &p);
- path_put(&p);
- return 0;
-}
-
-/* ================================================================== */
-/* sys_mkdirat(dirfd, pathname, mode) */
-/* ================================================================== */
-
-int64 sys_mkdirat(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int dirfd = static_cast<int>(a0);
- const char* pathname = reinterpret_cast<const char*>(a1);
- uint32 mode = static_cast<uint32>(a2);
-
- /* Walk to the parent directory */
- /* For simplicity, support only "single component" paths for now */
- path parent{};
- int err;
-
- if (pathname[0] == '/') {
- parent.de = g_root_dentry;
- parent.mnt = g_root_mnt;
- pathname++; /* skip leading / */
- } else {
- fs_struct* fs = current_fs();
- if (!fs) return -ENOENT;
- parent = fs->pwd;
- (void)dirfd; /* TODO: respect dirfd for AT_FDCWD check */
- }
-
- inode* dir_ip = parent.de->d_inode;
- if (!dir_ip || !dir_ip->i_op || !dir_ip->i_op->mkdir) {
- return -EPERM;
- }
-
- qstr q{};
- q.name = pathname;
- q.len = 0;
- for (const char* s = pathname; *s; s++) q.len++;
- dentry* new_de = d_alloc(parent.de, &q);
- if (!new_de) return -ENOMEM;
-
- err = dir_ip->i_op->mkdir(dir_ip, new_de, mode | S_IFDIR);
- if (err) {
- return err;
- }
-
- return 0;
-}
-
-/* ================================================================== */
-/* sys_unlinkat(dirfd, pathname, flags) */
-/* ================================================================== */
-
-int64 sys_unlinkat(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- (void)a0; (void)a1; (void)a2;
- /* TODO: implement unlink/rmdir */
- return -ENOSYS;
-}
-
-/* ================================================================== */
-/* sys_writev(fd, iov, iovcnt) */
-/* ================================================================== */
-
-struct iovec {
- void* iov_base;
- uint64 iov_len;
-};
-
-int64 sys_writev(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- const iovec* iov = reinterpret_cast<const iovec*>(a1);
- int iovcnt = static_cast<int>(a2);
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
- if (!(fp->f_mode & FMODE_WRITE)) return -EBADF;
-
- int64 total = 0;
- for (int i = 0; i < iovcnt; i++) {
- if (iov[i].iov_len == 0) continue;
- int64 ret = vfs_write(fp, static_cast<const char*>(iov[i].iov_base),
- iov[i].iov_len, &fp->f_pos);
- if (ret < 0) {
- return total > 0 ? total : ret;
- }
- total += ret;
- if (static_cast<uint64>(ret) < iov[i].iov_len) break;
- }
- return total;
-}
-
-/* ================================================================== */
-/* sys_ioctl — dispatch to file_operations */
-/* ================================================================== */
-
-int64 sys_ioctl(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- unsigned int cmd = static_cast<unsigned int>(a1);
- uint64 arg = a2;
-
- TaskControlBlock* curr = current_task();
- if (!curr || !curr->files) return -EBADF;
-
- file* fp = fcheck(curr->files, fd);
- if (!fp) return -EBADF;
-
- if (fp->f_op && fp->f_op->unlocked_ioctl)
- return fp->f_op->unlocked_ioctl(fp, cmd, arg);
-
- return -ENOTTY;
-}
-
-/* ================================================================== */
-/* sys_pipe2(fds, flags) */
-/* ================================================================== */
-
-#include <lume/pipe.h>
-
-int64 sys_pipe2(uint64 a0, uint64 a1, uint64 /*a2*/,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int* user_fds = reinterpret_cast<int*>(a0);
- int flags = static_cast<int>(a1);
-
- files_struct* files = current_files();
- if (!files) return -EMFILE;
-
- int fds[2];
- int err = do_pipe2(files, fds, flags);
- if (err) return err;
-
- user_fds[0] = fds[0];
- user_fds[1] = fds[1];
- return 0;
-}
-
-/* ================================================================== */
-/* sys_fcntl(fd, cmd, arg) */
-/* ================================================================== */
-
-/* fcntl commands — Linux ABI values */
-inline constexpr int F_DUPFD = 0;
-inline constexpr int F_GETFD = 1;
-inline constexpr int F_SETFD = 2;
-inline constexpr int F_GETFL = 3;
-inline constexpr int F_SETFL = 4;
-inline constexpr int F_DUPFD_CLOEXEC = 1030;
-
-inline constexpr int FD_CLOEXEC = 1;
-
-/* Bitmap helpers (duplicated from fd.cc — TODO: move to shared header) */
-static inline bool fcntl_bit_test(const uint64* bmap, int bit) {
- return (bmap[bit / 64] >> (bit % 64)) & 1;
-}
-static inline void fcntl_bit_set(uint64* bmap, int bit) {
- bmap[bit / 64] |= (1ULL << (bit % 64));
-}
-static inline void fcntl_bit_clear(uint64* bmap, int bit) {
- bmap[bit / 64] &= ~(1ULL << (bit % 64));
-}
-
-int64 sys_fcntl(uint64 a0, uint64 a1, uint64 a2,
- uint64 /*a3*/, uint64 /*a4*/, uint64 /*a5*/)
-{
- int fd = static_cast<int>(a0);
- int cmd = static_cast<int>(a1);
- uint64 arg = a2;
-
- files_struct* files = current_files();
- if (!files) return -EBADF;
-
- file* fp = fcheck(files, fd);
- if (!fp) return -EBADF;
-
- switch (cmd) {
- case F_DUPFD:
- case F_DUPFD_CLOEXEC: {
- int new_fd = alloc_fd(files, static_cast<unsigned int>(arg));
- if (new_fd < 0) return new_fd;
- get_file(fp);
- fd_install(files, new_fd, fp);
- if (cmd == F_DUPFD_CLOEXEC) {
- LockGuard guard(files->file_lock);
- fcntl_bit_set(files->close_on_exec_init, new_fd);
- }
- return new_fd;
- }
-
- case F_GETFD: {
- LockGuard guard(files->file_lock);
- return fcntl_bit_test(files->close_on_exec_init, fd) ? FD_CLOEXEC : 0;
- }
-
- case F_SETFD: {
- LockGuard guard(files->file_lock);
- if (arg & FD_CLOEXEC)
- fcntl_bit_set(files->close_on_exec_init, fd);
- else
- fcntl_bit_clear(files->close_on_exec_init, fd);
- return 0;
- }
-
- case F_GETFL:
- return fp->f_flags;
-
- case F_SETFL:
- /* Only allow changing O_APPEND, O_NONBLOCK, O_ASYNC */
- fp->f_flags = (fp->f_flags & ~(O_APPEND | O_NONBLOCK)) |
- (static_cast<unsigned int>(arg) & (O_APPEND | O_NONBLOCK));
- return 0;
-
- default:
- return -EINVAL;
- }
-}
-
-/* ================================================================== */
-/* sys_socket (SYS_socket = 198) & sys_sendto (SYS_sendto = 206) */
-/* ================================================================== */
-
-int64 sys_socket(uint64, uint64, uint64, uint64, uint64, uint64)
-{
- /*
- * COMPATIBILITY STUB:
- * LumeOS currently lacks a networking stack and Unix Domain Sockets (AF_UNIX).
- * We return -EAFNOSUPPORT (Address family not supported by protocol) as expected
- * by Linux applications (like BusyBox syslogd connecting to /dev/log).
- */
- return -EAFNOSUPPORT;
-}
-
-int64 sys_sendto(uint64, uint64, uint64, uint64, uint64, uint64)
-{
- /* COMPATIBILITY STUB */
- return -EAFNOSUPPORT;
-}