]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
diskfs: add mkdir/unlink syscalls
authorTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 00:41:56 +0000 (21:41 -0300)
committerTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 00:41:56 +0000 (21:41 -0300)
include/diskfs.h
include/syscall.h
src/kernel/diskfs.c
src/kernel/syscall.c
user/init.c

index 455ec95af6d7f8ee247bf8e437eccd7f19804542..bcbe635e7e25f751d1fc280caa76445888e5c2c5 100644 (file)
@@ -20,4 +20,7 @@ fs_node_t* diskfs_create_root(void);
 // flags: supports O_CREAT (0x40) and O_TRUNC (0x200) semantics (minimal).
 int diskfs_open_file(const char* rel_path, uint32_t flags, fs_node_t** out_node);
 
+int diskfs_mkdir(const char* rel_path);
+int diskfs_unlink(const char* rel_path);
+
 #endif
index 7983ea61630fe2cf16d1f029b2e814ec97d958c3..f85dd00dd586b41daecf4e80ff143a780214f4d4 100644 (file)
@@ -46,6 +46,9 @@ enum {
     SYSCALL_SIGACTION = 25,
     SYSCALL_SIGPROCMASK = 26,
     SYSCALL_SIGRETURN = 27,
+
+    SYSCALL_MKDIR = 28,
+    SYSCALL_UNLINK = 29,
 };
 
 #endif
index 133ff2ac2875ca8caeeb38630fb3f3f275e0fdb3..e9c062954e365295b5a33e7fe090271f21b2f1b9 100644 (file)
@@ -531,6 +531,62 @@ int diskfs_open_file(const char* rel_path, uint32_t flags, fs_node_t** out_node)
     return 0;
 }
 
+int diskfs_mkdir(const char* rel_path) {
+    if (!g_ready) return -ENODEV;
+    if (!rel_path || rel_path[0] == 0) return -EINVAL;
+
+    struct diskfs_super sb;
+    if (diskfs_super_load(&sb) < 0) return -EIO;
+
+    uint16_t ino = 0;
+    uint16_t parent = 0;
+    char last[DISKFS_NAME_MAX];
+    last[0] = 0;
+    int rc = diskfs_lookup_path(&sb, rel_path, &ino, &parent, last, sizeof(last));
+    if (rc == 0) {
+        return -EEXIST;
+    }
+    if (rc != -ENOENT) return rc;
+    if (last[0] == 0) return -EINVAL;
+
+    if (parent >= DISKFS_MAX_INODES) return -EIO;
+    if (sb.inodes[parent].type != DISKFS_INODE_DIR) return -ENOTDIR;
+
+    for (uint16_t i = 1; i < DISKFS_MAX_INODES; i++) {
+        if (sb.inodes[i].type != DISKFS_INODE_FREE) continue;
+        sb.inodes[i].type = DISKFS_INODE_DIR;
+        sb.inodes[i].parent = parent;
+        memset(sb.inodes[i].name, 0, sizeof(sb.inodes[i].name));
+        diskfs_strlcpy(sb.inodes[i].name, last, sizeof(sb.inodes[i].name));
+        sb.inodes[i].start_lba = 0;
+        sb.inodes[i].size_bytes = 0;
+        sb.inodes[i].cap_sectors = 0;
+        return diskfs_super_store(&sb);
+    }
+
+    return -ENOSPC;
+}
+
+int diskfs_unlink(const char* rel_path) {
+    if (!g_ready) return -ENODEV;
+    if (!rel_path || rel_path[0] == 0) return -EINVAL;
+
+    struct diskfs_super sb;
+    if (diskfs_super_load(&sb) < 0) return -EIO;
+
+    uint16_t ino = 0;
+    int rc = diskfs_lookup_path(&sb, rel_path, &ino, 0, 0, 0);
+    if (rc < 0) return rc;
+    if (ino == 0) return -EPERM;
+    if (ino >= DISKFS_MAX_INODES) return -EIO;
+
+    if (sb.inodes[ino].type == DISKFS_INODE_DIR) return -EISDIR;
+    if (sb.inodes[ino].type != DISKFS_INODE_FILE) return -ENOENT;
+
+    memset(&sb.inodes[ino], 0, sizeof(sb.inodes[ino]));
+    return diskfs_super_store(&sb);
+}
+
 fs_node_t* diskfs_create_root(void) {
     if (!g_ready) {
         if (ata_pio_init_primary_master() == 0) {
index 18710c6ae6ffe65f546a97c7014bb6ac18dc6eaa..de21a550532424b8db39e9178dc4365a4635a5c0 100644 (file)
@@ -797,6 +797,54 @@ static int syscall_open_impl(const char* user_path, uint32_t flags) {
     return fd;
 }
 
+static int syscall_mkdir_impl(const char* user_path) {
+    if (!user_path) return -EFAULT;
+
+    char path[128];
+    for (size_t i = 0; i < sizeof(path); i++) {
+        if (copy_from_user(&path[i], &user_path[i], 1) < 0) {
+            return -EFAULT;
+        }
+        if (path[i] == 0) break;
+        if (i + 1 == sizeof(path)) {
+            path[sizeof(path) - 1] = 0;
+            break;
+        }
+    }
+
+    if (path[0] == '/' && path[1] == 'd' && path[2] == 'i' && path[3] == 's' && path[4] == 'k' && path[5] == '/') {
+        const char* rel = path + 6;
+        if (rel[0] == 0) return -EINVAL;
+        return diskfs_mkdir(rel);
+    }
+
+    return -ENOSYS;
+}
+
+static int syscall_unlink_impl(const char* user_path) {
+    if (!user_path) return -EFAULT;
+
+    char path[128];
+    for (size_t i = 0; i < sizeof(path); i++) {
+        if (copy_from_user(&path[i], &user_path[i], 1) < 0) {
+            return -EFAULT;
+        }
+        if (path[i] == 0) break;
+        if (i + 1 == sizeof(path)) {
+            path[sizeof(path) - 1] = 0;
+            break;
+        }
+    }
+
+    if (path[0] == '/' && path[1] == 'd' && path[2] == 'i' && path[3] == 's' && path[4] == 'k' && path[5] == '/') {
+        const char* rel = path + 6;
+        if (rel[0] == 0) return -EINVAL;
+        return diskfs_unlink(rel);
+    }
+
+    return -ENOSYS;
+}
+
 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;
@@ -1206,6 +1254,18 @@ static void syscall_handler(struct registers* regs) {
         return;
     }
 
+    if (syscall_no == SYSCALL_MKDIR) {
+        const char* path = (const char*)regs->ebx;
+        regs->eax = (uint32_t)syscall_mkdir_impl(path);
+        return;
+    }
+
+    if (syscall_no == SYSCALL_UNLINK) {
+        const char* path = (const char*)regs->ebx;
+        regs->eax = (uint32_t)syscall_unlink_impl(path);
+        return;
+    }
+
     regs->eax = (uint32_t)-ENOSYS;
 }
 
index c2608d0427e3d610f48d003d0a29c9e9c881dcac..d2d48264757a84924853ae6017faef9fef47d52b 100644 (file)
@@ -71,6 +71,9 @@ enum {
     SYSCALL_SIGACTION = 25,
     SYSCALL_SIGPROCMASK = 26,
     SYSCALL_SIGRETURN = 27,
+
+    SYSCALL_MKDIR = 28,
+    SYSCALL_UNLINK = 29,
 };
 
 enum {
@@ -403,6 +406,28 @@ static int sys_open(const char* path, uint32_t flags) {
     return __syscall_fix(ret);
 }
 
+static int sys_mkdir(const char* path) {
+    int ret;
+    __asm__ volatile(
+        "int $0x80"
+        : "=a"(ret)
+        : "a"(SYSCALL_MKDIR), "b"(path)
+        : "memory"
+    );
+    return __syscall_fix(ret);
+}
+
+static int sys_unlink(const char* path) {
+    int ret;
+    __asm__ volatile(
+        "int $0x80"
+        : "=a"(ret)
+        : "a"(SYSCALL_UNLINK), "b"(path)
+        : "memory"
+    );
+    return __syscall_fix(ret);
+}
+
 static int sys_read(int fd, void* buf, uint32_t len) {
     int ret;
     __asm__ volatile(
@@ -1515,6 +1540,47 @@ void _start(void) {
         sys_write(1, " OK\n", (uint32_t)(sizeof(" OK\n") - 1));
     }
 
+    // B3: diskfs mkdir/unlink smoke
+    {
+        int r = sys_mkdir("/disk/dir");
+        if (r < 0 && r != -17) {
+            sys_write(1, "[init] mkdir /disk/dir failed\n",
+                      (uint32_t)(sizeof("[init] mkdir /disk/dir failed\n") - 1));
+            sys_exit(1);
+        }
+
+        int fd = sys_open("/disk/dir/file", O_CREAT | O_TRUNC);
+        if (fd < 0) {
+            sys_write(1, "[init] open /disk/dir/file failed\n",
+                      (uint32_t)(sizeof("[init] open /disk/dir/file failed\n") - 1));
+            sys_exit(1);
+        }
+        static const char msg2[] = "ok";
+        if (sys_write(fd, msg2, 2) != 2) {
+            sys_write(1, "[init] write /disk/dir/file failed\n",
+                      (uint32_t)(sizeof("[init] write /disk/dir/file failed\n") - 1));
+            sys_exit(1);
+        }
+        (void)sys_close(fd);
+
+        r = sys_unlink("/disk/dir/file");
+        if (r < 0) {
+            sys_write(1, "[init] unlink /disk/dir/file failed\n",
+                      (uint32_t)(sizeof("[init] unlink /disk/dir/file failed\n") - 1));
+            sys_exit(1);
+        }
+
+        fd = sys_open("/disk/dir/file", 0);
+        if (fd >= 0) {
+            sys_write(1, "[init] unlink did not remove file\n",
+                      (uint32_t)(sizeof("[init] unlink did not remove file\n") - 1));
+            sys_exit(1);
+        }
+
+        sys_write(1, "[init] diskfs mkdir/unlink OK\n",
+                  (uint32_t)(sizeof("[init] diskfs mkdir/unlink OK\n") - 1));
+    }
+
     enum { NCHILD = 100 };
     int children[NCHILD];
     for (int i = 0; i < NCHILD; i++) {