]> 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 2d05498bab77fbe62ff4069befcfa5758dbb1e08..63d60009a5ef93783942bfd111755b60c0ec360c 100644 (file)
@@ -11,4 +11,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 042cb1ee45cb35fd7687cd85a74badd58611b1cf..5dbddcf4b9f7de2544a4b16e6096630b9c4c101c 100644 (file)
@@ -37,6 +37,9 @@ enum {
     SYSCALL_SIGACTION = 25,
     SYSCALL_SIGPROCMASK = 26,
     SYSCALL_SIGRETURN = 27,
+
+    SYSCALL_MKDIR = 28,
+    SYSCALL_UNLINK = 29,
 };
 
 #endif
index e552d34ecc2b5d6d6f4f0b64b655129df3770ca9..72faa146b5322e76d0ea048e00794932ce635c81 100644 (file)
@@ -522,6 +522,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 c25cbb32eee578011c66dd727d589006f2e5b563..f255edd05a8b0ec76c2eb613424fabd44b1c39f6 100644 (file)
@@ -788,6 +788,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;
@@ -1197,6 +1245,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 b2bed6b233c2e693a06693cc4995d8e5e8d92fbd..bce209b948fe6d8b3c9985a1367dfad3d70d3077 100644 (file)
@@ -62,6 +62,9 @@ enum {
     SYSCALL_SIGACTION = 25,
     SYSCALL_SIGPROCMASK = 26,
     SYSCALL_SIGRETURN = 27,
+
+    SYSCALL_MKDIR = 28,
+    SYSCALL_UNLINK = 29,
 };
 
 enum {
@@ -394,6 +397,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(
@@ -1506,6 +1531,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++) {