// 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
SYSCALL_SIGACTION = 25,
SYSCALL_SIGPROCMASK = 26,
SYSCALL_SIGRETURN = 27,
+
+ SYSCALL_MKDIR = 28,
+ SYSCALL_UNLINK = 29,
};
#endif
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) {
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;
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;
}
SYSCALL_SIGACTION = 25,
SYSCALL_SIGPROCMASK = 26,
SYSCALL_SIGRETURN = 27,
+
+ SYSCALL_MKDIR = 28,
+ SYSCALL_UNLINK = 29,
};
enum {
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(
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++) {