ソースを参照

change(vfs): use c++

greatbridf 2 年 前
コミット
2ef440f8e1

+ 2 - 2
CMakeLists.txt

@@ -33,7 +33,7 @@ add_custom_command(OUTPUT extracted_bootloader
 project(kernel_main)
 
 set(CMAKE_C_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -Werror=implicit-int -Werror=implicit-function-declaration -Werror=strict-aliasing -fverbose-asm -fno-exceptions -fno-pic -fno-stack-protector")
-set(CMAKE_CXX_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -fverbose-asm -fno-use-cxa-atexit -fno-exceptions -fno-pic -fno-stack-protector")
+set(CMAKE_CXX_FLAGS "-nostdinc -m32 -nostdlib -W -Wall -Wextra -Wno-builtin-declaration-mismatch -Wno-format -fverbose-asm -fno-use-cxa-atexit -fno-exceptions -fno-pic -fno-stack-protector -fno-rtti")
 set(CMAKE_CXX_STANDARD 17)
 
 if (CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -75,7 +75,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/kernel/syscall.hpp
                         include/kernel/mem.h
                         include/kernel/mm.hpp
-                        include/kernel/vfs.h
+                        include/kernel/vfs.hpp
                         include/kernel/vga.h
                         include/kernel/hw/ata.hpp
                         include/kernel/hw/keyboard.h

+ 2 - 2
include/kernel/mm.hpp

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <kernel/mem.h>
-#include <kernel/vfs.h>
+#include <kernel/vfs.hpp>
 #include <types/allocator.hpp>
 #include <types/list.hpp>
 #include <types/types.h>
@@ -33,7 +33,7 @@ public:
     struct mm_attr attr;
     page_directory_entry* pd;
     page_arr* pgs;
-    struct inode* mapped_file;
+    fs::inode* mapped_file;
     size_t file_offset;
 
 public:

+ 0 - 134
include/kernel/vfs.h

@@ -1,134 +0,0 @@
-#pragma once
-
-#include <types/stdint.h>
-#include <types/types.h>
-
-#define INODE_FILE (1 << 0)
-#define INODE_DIR (1 << 1)
-#define INODE_MNT (1 << 2)
-#define INODE_NODE (1 << 3)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct inode;
-union inode_flags;
-struct inode_ops;
-struct stat;
-struct dirent;
-union node_t;
-struct special_node_ops;
-
-typedef size_t (*inode_read)(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
-typedef size_t (*inode_write)(struct inode* file, const char* buf, size_t offset, size_t n);
-typedef int (*inode_readdir)(struct inode* dir, struct dirent* entry, size_t i);
-typedef struct inode* (*inode_findinode)(struct inode* dir, const char* filename);
-typedef int (*inode_mkfile)(struct inode* dir, const char* filename);
-typedef int (*inode_mknode)(struct inode* dir, const char* filename, union node_t sn);
-typedef int (*inode_rmfile)(struct inode* dir, const char* filename);
-typedef int (*inode_mkdir)(struct inode* dir, const char* dirname);
-typedef int (*inode_stat)(struct inode* dir, struct stat* stat, const char* dirname);
-
-typedef size_t (*special_node_read)(struct special_node* sn, char* buf, size_t buf_size, size_t offset, size_t n);
-typedef size_t (*special_node_write)(struct special_node* sn, const char* buf, size_t offset, size_t n);
-
-typedef uint32_t ino_t;
-typedef uint32_t blksize_t;
-typedef uint32_t blkcnt_t;
-
-union inode_flags {
-    uint32_t v;
-    struct {
-        uint32_t file : 1;
-        uint32_t directory : 1;
-        uint32_t mount_point : 1;
-        uint32_t special_node : 1;
-    } in;
-};
-
-struct inode_ops {
-    inode_read read;
-    inode_write write;
-    inode_readdir readdir;
-    inode_findinode findinode;
-    inode_mkfile mkfile;
-    inode_mknode mknode;
-    inode_rmfile rmfile;
-    inode_mkdir mkdir;
-    inode_stat stat;
-};
-
-struct fs_info {
-    const struct inode_ops* ops;
-    void* impl;
-};
-
-struct inode {
-    union inode_flags flags;
-    uint32_t perm;
-    void* impl;
-    ino_t ino;
-    struct fs_info* fs;
-};
-
-struct dirent {
-    char name[128];
-    uint32_t ino;
-};
-
-union node_t {
-    uint32_t v;
-    struct {
-        uint32_t major : 16;
-        uint32_t minor : 16;
-    } in;
-};
-
-struct special_node_ops {
-    special_node_read read;
-    special_node_write write;
-};
-
-struct special_node {
-    struct special_node_ops ops;
-    uint32_t data1;
-    uint32_t data2;
-};
-
-struct stat {
-    ino_t st_ino;
-    union node_t st_rdev;
-    blksize_t st_blksize;
-    blkcnt_t st_blocks;
-};
-
-extern struct inode* fs_root;
-
-void init_vfs(void);
-
-void register_special_block(uint16_t major,
-    uint16_t minor,
-    special_node_read read,
-    special_node_write write,
-    uint32_t data1,
-    uint32_t data2);
-
-size_t vfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
-size_t vfs_write(struct inode* file, const char* buf, size_t offset, size_t n);
-int vfs_readdir(struct inode* dir, struct dirent* entry, size_t i);
-struct inode* vfs_findinode(struct inode* dir, const char* filename);
-int vfs_mkfile(struct inode* dir, const char* filename);
-int vfs_mknode(struct inode* dir, const char* filename, union node_t sn);
-int vfs_rmfile(struct inode* dir, const char* filename);
-int vfs_mkdir(struct inode* dir, const char* dirname);
-
-// @return pointer to the inode if found, nullptr if not
-struct inode* vfs_open(const char* path);
-
-// @return GB_OK if succeed, GB_FAILED if failed and set errno
-int vfs_stat(struct stat* stat, const char* path);
-
-#ifdef __cplusplus
-}
-#endif

+ 117 - 0
include/kernel/vfs.hpp

@@ -0,0 +1,117 @@
+#pragma once
+
+#include <types/stdint.h>
+#include <types/types.h>
+
+#define INODE_FILE (1 << 0)
+#define INODE_DIR (1 << 1)
+#define INODE_MNT (1 << 2)
+#define INODE_NODE (1 << 3)
+
+namespace fs {
+using ino_t = size_t;
+using blksize_t = size_t;
+using blkcnt_t = size_t;
+
+class vfs;
+
+union inode_flags {
+    uint32_t v;
+    struct {
+        uint32_t file : 1;
+        uint32_t directory : 1;
+        uint32_t mount_point : 1;
+        uint32_t special_node : 1;
+    } in;
+};
+
+struct inode {
+    inode_flags flags;
+    uint32_t perm;
+    void* impl;
+    ino_t ino;
+    vfs* fs;
+};
+
+struct dirent {
+    char name[128];
+    uint32_t ino;
+};
+
+union node_t {
+    uint32_t v;
+    struct {
+        uint32_t major : 16;
+        uint32_t minor : 16;
+    } in;
+};
+
+struct special_node;
+
+typedef size_t (*special_node_read)(special_node* sn, char* buf, size_t buf_size, size_t offset, size_t n);
+typedef size_t (*special_node_write)(special_node* sn, const char* buf, size_t offset, size_t n);
+
+struct special_node_ops {
+    special_node_read read;
+    special_node_write write;
+};
+
+struct special_node {
+    special_node_ops ops;
+    uint32_t data1;
+    uint32_t data2;
+};
+
+struct stat {
+    ino_t st_ino;
+    node_t st_rdev;
+    blksize_t st_blksize;
+    blkcnt_t st_blocks;
+};
+
+class vfs {
+public:
+    vfs() = default;
+    vfs(const vfs&) = delete;
+    vfs& operator=(const vfs&) = delete;
+    vfs(vfs&&) = delete;
+    vfs& operator=(vfs&&) = delete;
+
+    virtual size_t inode_read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
+    virtual size_t inode_write(inode* file, const char* buf, size_t offset, size_t n);
+    virtual int inode_readdir(inode* dir, dirent* entry, size_t i);
+    virtual inode* inode_findinode(inode* dir, const char* filename);
+    virtual int inode_mkfile(inode* dir, const char* filename);
+    virtual int inode_mknode(inode* dir, const char* filename, union node_t sn);
+    virtual int inode_rmfile(inode* dir, const char* filename);
+    virtual int inode_mkdir(inode* dir, const char* dirname);
+    virtual int inode_stat(inode* dir, stat* stat, const char* dirname);
+};
+
+extern struct inode* fs_root;
+
+void register_special_block(uint16_t major,
+    uint16_t minor,
+    special_node_read read,
+    special_node_write write,
+    uint32_t data1,
+    uint32_t data2);
+
+size_t vfs_read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
+size_t vfs_write(inode* file, const char* buf, size_t offset, size_t n);
+int vfs_readdir(inode* dir, dirent* entry, size_t i);
+inode* vfs_findinode(inode* dir, const char* filename);
+int vfs_mkfile(inode* dir, const char* filename);
+int vfs_mknode(inode* dir, const char* filename, node_t sn);
+int vfs_rmfile(inode* dir, const char* filename);
+int vfs_mkdir(inode* dir, const char* dirname);
+
+// @return pointer to the inode if found, nullptr if not
+struct inode* vfs_open(const char* path);
+
+// @return GB_OK if succeed, GB_FAILED if failed and set errno
+int vfs_stat(struct stat* stat, const char* path);
+
+} // namespace fs
+
+extern "C" void init_vfs(void);

+ 8 - 8
src/kernel/hw/ata.cpp

@@ -3,7 +3,7 @@
 #include <kernel/stdio.h>
 #include <kernel/syscall.hpp>
 #include <kernel/tty.h>
-#include <kernel/vfs.h>
+#include <kernel/vfs.hpp>
 #include <types/allocator.hpp>
 #include <types/status.h>
 #include <types/stdint.h>
@@ -136,9 +136,9 @@ void hw::init_ata(void* data)
     ata_pri->identify();
     ata_pri->select(true);
 
-    register_special_block(
+    fs::register_special_block(
         2, 0,
-        [](char* buf, size_t buf_size, size_t offset, size_t n) -> size_t {
+        [](fs::special_node*, char* buf, size_t buf_size, size_t offset, size_t n) -> size_t {
             // TODO: check buf_size
             char b[512] {};
             char* orig_buf = buf;
@@ -158,12 +158,12 @@ void hw::init_ata(void* data)
             }
             return buf - orig_buf;
         },
-        [](const char* buf, size_t offset, size_t n) -> size_t {
+        [](fs::special_node*, const char* buf, size_t offset, size_t n) -> size_t {
             syscall(0x03);
             return n;
-        });
-    auto* hda = vfs_open("/dev/hda");
+        }, 0, 0);
+    auto* hda = fs::vfs_open("/dev/hda");
     char buf[512] {};
-    vfs_read(hda, buf, 512, 1, 512);
-    vfs_write(hda, buf, 1, 512);
+    fs::vfs_read(hda, buf, 512, 1, 512);
+    fs::vfs_write(hda, buf, 1, 512);
 }

+ 1 - 1
src/kernel/interrupt.cpp

@@ -11,7 +11,7 @@
 #include <kernel/stdio.h>
 #include <kernel/syscall.hpp>
 #include <kernel/tty.h>
-#include <kernel/vfs.h>
+#include <kernel/vfs.hpp>
 #include <kernel/vga.h>
 #include <kernel_main.h>
 #include <types/size.h>

+ 2 - 2
src/kernel/mem.cpp

@@ -476,7 +476,7 @@ static inline int _mmap(
     mm_list* mms,
     void* hint,
     size_t len,
-    struct inode* file,
+    fs::inode* file,
     size_t offset,
     int write,
     int priv)
@@ -508,7 +508,7 @@ static inline int _mmap(
 int mmap(
     void* hint,
     size_t len,
-    struct inode* file,
+    fs::inode* file,
     size_t offset,
     int write,
     int priv)

+ 241 - 296
src/kernel/vfs.cpp

@@ -1,10 +1,12 @@
 #include <kernel/errno.h>
 #include <kernel/mem.h>
 #include <kernel/stdio.h>
+#include <kernel/syscall.hpp>
 #include <kernel/tty.h>
-#include <kernel/vfs.h>
+#include <kernel/vfs.hpp>
 #include <types/allocator.hpp>
 #include <types/list.hpp>
+#include <types/status.h>
 #include <types/stdint.h>
 #include <types/string.hpp>
 #include <types/vector.hpp>
@@ -20,21 +22,66 @@ struct tmpfs_file_entry {
     char filename[128];
 };
 
-class tmpfs {
+size_t fs::vfs::inode_read(inode*, char*, size_t, size_t, size_t)
+{
+    syscall(0x03);
+    return 0xffffffff;
+}
+size_t fs::vfs::inode_write(inode*, const char*, size_t, size_t)
+{
+    syscall(0x03);
+    return 0xffffffff;
+}
+int fs::vfs::inode_readdir(inode*, dirent*, size_t)
+{
+    syscall(0x03);
+    return GB_FAILED;
+}
+fs::inode* fs::vfs::inode_findinode(inode*, const char*)
+{
+    syscall(0x03);
+    return nullptr;
+}
+int fs::vfs::inode_mkfile(inode*, const char*)
+{
+    syscall(0x03);
+    return GB_FAILED;
+}
+int fs::vfs::inode_mknode(inode*, const char*, node_t)
+{
+    syscall(0x03);
+    return GB_FAILED;
+}
+int fs::vfs::inode_rmfile(inode*, const char*)
+{
+    syscall(0x03);
+    return GB_FAILED;
+}
+int fs::vfs::inode_mkdir(inode*, const char*)
+{
+    syscall(0x03);
+    return GB_FAILED;
+}
+int fs::vfs::inode_stat(inode*, stat*, const char*)
+{
+    syscall(0x03);
+    return GB_FAILED;
+}
+
+class tmpfs : public virtual fs::vfs {
 private:
-    using inode_list_type = list<struct inode, kernel_allocator>;
+    using inode_list_type = list<fs::inode, kernel_allocator>;
 
 private:
     size_t m_limit;
     // TODO: hashtable etc.
     inode_list_type m_inodes;
-    struct fs_info m_fs;
-    size_t m_last_inode_no;
+    fs::ino_t m_last_inode_no;
 
 protected:
-    inline vector<struct tmpfs_file_entry>* mk_fe_vector(void)
+    inline vector<tmpfs_file_entry>* mk_fe_vector(void)
     {
-        return allocator_traits<kernel_allocator<vector<struct tmpfs_file_entry>>>::allocate_and_construct();
+        return allocator_traits<kernel_allocator<vector<tmpfs_file_entry>>>::allocate_and_construct();
     }
 
     inline vector<char>* mk_data_vector(void)
@@ -42,340 +89,249 @@ protected:
         return allocator_traits<kernel_allocator<vector<char>>>::allocate_and_construct();
     }
 
-    inline struct inode mk_inode(union inode_flags flags, void* data)
+    inline fs::inode mk_inode(fs::inode_flags flags, void* data)
     {
-        struct inode i { };
+        fs::inode i {};
         i.flags.v = flags.v;
-        i.fs = &m_fs;
         i.impl = data;
         i.ino = m_last_inode_no++;
         i.perm = 0777;
+        i.fs = this;
         return i;
     }
 
-public:
-    explicit tmpfs(size_t limit);
-    void mklink(struct inode* dir, struct inode* inode, const char* filename);
-    void mkfile(struct inode* dir, const char* filename);
-    void mknode(struct inode* dir, const char* filename, union node_t sn);
-    void mkdir(struct inode* dir, const char* dirname);
-    size_t read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
-    size_t write(struct inode* file, const char* buf, size_t offset, size_t n);
-    int readdir(struct inode* dir, struct dirent* entry, size_t i);
-    struct inode* findinode(struct inode* dir, const char* filename);
-    int stat(struct inode* dir, struct stat* stat, const char* filename);
-
-    struct inode* root_inode(void)
+    void mklink(fs::inode* dir, fs::inode* inode, const char* filename)
     {
-        return &*m_inodes.begin();
+        auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
+        struct tmpfs_file_entry ent = {
+            .ino = inode->ino,
+            .filename = { 0 },
+        };
+        snprintf(ent.filename, sizeof(ent.filename), filename);
+        fes->push_back(ent);
     }
-};
 
-size_t tmpfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
-{
-    auto* fs = static_cast<tmpfs*>(file->fs->impl);
-    return fs->read(file, buf, buf_size, offset, n);
-}
-size_t tmpfs_write(struct inode* file, const char* buf, size_t offset, size_t n)
-{
-    auto* fs = static_cast<tmpfs*>(file->fs->impl);
-    return fs->write(file, buf, offset, n);
-}
-int tmpfs_readdir(struct inode* dir, struct dirent* entry, size_t i)
-{
-    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-    return fs->readdir(dir, entry, i);
-}
-struct inode* tmpfs_findinode(struct inode* dir, const char* filename)
-{
-    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-    return fs->findinode(dir, filename);
-}
-int tmpfs_mkfile(struct inode* dir, const char* filename)
-{
-    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-    fs->mkfile(dir, filename);
-    return GB_OK;
-}
-int tmpfs_mknode(struct inode* dir, const char* filename, union node_t sn)
-{
-    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-    fs->mknode(dir, filename, sn);
-    return GB_OK;
-}
-// int tmpfs_rmfile(struct inode* dir, const char* filename)
-// {
-//     auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-//     fs->rmfile(dir, filename);
-//     return GB_OK;
-// }
-int tmpfs_mkdir(struct inode* dir, const char* dirname)
-{
-    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-    fs->mkdir(dir, dirname);
-    return GB_OK;
-}
-int tmpfs_stat(struct inode* dir, struct stat* stat, const char* filename)
-{
-    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
-    return fs->stat(dir, stat, filename);
-}
+public:
+    explicit tmpfs(size_t limit)
+        : m_limit(limit)
+        , m_last_inode_no(0)
+    {
+        auto in = mk_inode({ .v = INODE_DIR | INODE_MNT }, mk_fe_vector());
 
-static const struct inode_ops tmpfs_inode_ops = {
-    .read = tmpfs_read,
-    .write = tmpfs_write,
-    .readdir = tmpfs_readdir,
-    .findinode = tmpfs_findinode,
-    .mkfile = tmpfs_mkfile,
-    .mknode = tmpfs_mknode,
-    .rmfile = 0,
-    .mkdir = tmpfs_mkdir,
-    .stat = tmpfs_stat,
-};
+        mklink(&in, &in, ".");
+        mklink(&in, &in, "..");
 
-tmpfs::tmpfs(size_t limit)
-    : m_limit(limit)
-    , m_fs { .ops = &tmpfs_inode_ops, .impl = this }
-    , m_last_inode_no(0)
-{
-    struct inode in = mk_inode({ .v = INODE_DIR | INODE_MNT }, mk_fe_vector());
-
-    mklink(&in, &in, ".");
-    mklink(&in, &in, "..");
+        m_inodes.push_back(in);
+    }
 
-    m_inodes.push_back(in);
-}
+    virtual int inode_mkfile(fs::inode* dir, const char* filename) override
+    {
+        auto file = mk_inode({ .v = INODE_FILE }, mk_data_vector());
+        m_inodes.push_back(file);
+        mklink(dir, &file, filename);
+        return GB_OK;
+    }
 
-void tmpfs::mklink(struct inode* dir, struct inode* inode, const char* filename)
-{
-    auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
-    struct tmpfs_file_entry ent = {
-        .ino = inode->ino,
-        .filename = { 0 },
-    };
-    snprintf(ent.filename, sizeof(ent.filename), filename);
-    fes->push_back(ent);
-}
+    virtual int inode_mknode(fs::inode* dir, const char* filename, fs::node_t sn) override
+    {
+        auto node = mk_inode({ .v = INODE_NODE }, (void*)sn.v);
+        m_inodes.push_back(node);
+        mklink(dir, &node, filename);
+        return GB_OK;
+    }
 
-void tmpfs::mkfile(struct inode* dir, const char* filename)
-{
-    struct inode file = mk_inode({ .v = INODE_FILE }, mk_data_vector());
-    m_inodes.push_back(file);
-    mklink(dir, &file, filename);
-}
+    virtual int inode_mkdir(fs::inode* dir, const char* dirname) override
+    {
+        auto new_dir = mk_inode({ .v = INODE_DIR }, mk_fe_vector());
+        m_inodes.push_back(new_dir);
+        mklink(&new_dir, &new_dir, ".");
 
-void tmpfs::mknode(struct inode* dir, const char* filename, union node_t sn)
-{
-    struct inode node = mk_inode({ .v = INODE_NODE }, (void*)sn.v);
-    m_inodes.push_back(node);
-    mklink(dir, &node, filename);
-}
+        mklink(dir, &new_dir, dirname);
+        mklink(&new_dir, dir, "..");
+        return GB_OK;
+    }
 
-void tmpfs::mkdir(struct inode* dir, const char* dirname)
-{
-    struct inode new_dir = mk_inode({ .v = INODE_DIR }, mk_fe_vector());
-    m_inodes.push_back(new_dir);
-    mklink(&new_dir, &new_dir, ".");
+    virtual size_t inode_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n) override
+    {
+        if (file->flags.in.file != 1)
+            return 0;
 
-    mklink(dir, &new_dir, dirname);
-    mklink(&new_dir, dir, "..");
-}
+        auto* data = static_cast<vector<char>*>(file->impl);
+        size_t fsize = data->size();
 
-size_t tmpfs::read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
-{
-    if (file->flags.in.file != 1)
-        return 0;
+        if (offset + n > fsize)
+            n = fsize - offset;
 
-    auto* data = static_cast<vector<char>*>(file->impl);
-    size_t fsize = data->size();
+        if (buf_size < n) {
+            n = buf_size;
+        }
 
-    if (offset + n > fsize)
-        n = fsize - offset;
+        memcpy(buf, data->data() + offset, n);
 
-    if (buf_size < n) {
-        n = buf_size;
+        return n;
     }
 
-    memcpy(buf, data->data() + offset, n);
-
-    return n;
-}
+    virtual size_t inode_write(fs::inode* file, const char* buf, size_t offset, size_t n) override
+    {
+        if (file->flags.in.file != 1)
+            return 0;
 
-size_t tmpfs::write(struct inode* file, const char* buf, size_t offset, size_t n)
-{
-    if (file->flags.in.file != 1)
-        return 0;
+        auto* data = static_cast<vector<char>*>(file->impl);
 
-    auto* data = static_cast<vector<char>*>(file->impl);
+        for (size_t i = data->size(); i < offset + n; ++i) {
+            data->push_back(0);
+        }
+        memcpy(data->data() + offset, buf, n);
 
-    for (size_t i = data->size(); i < offset + n; ++i) {
-        data->push_back(0);
+        return n;
     }
-    memcpy(data->data() + offset, buf, n);
 
-    return n;
-}
-
-int tmpfs::readdir(struct inode* dir, struct dirent* entry, size_t i)
-{
-    if (dir->flags.in.directory != 1) {
-        errno = ENOTDIR;
-        return GB_FAILED;
-    }
+    virtual int inode_readdir(fs::inode* dir, fs::dirent* entry, size_t i) override
+    {
+        if (dir->flags.in.directory != 1) {
+            errno = ENOTDIR;
+            return GB_FAILED;
+        }
 
-    auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
+        auto* fes = static_cast<vector<tmpfs_file_entry>*>(dir->impl);
 
-    if (i >= fes->size()) {
-        errno = ENOENT;
-        return GB_FAILED;
-    }
+        if (i >= fes->size()) {
+            errno = ENOENT;
+            return GB_FAILED;
+        }
 
-    entry->ino = fes->at(i).ino;
-    snprintf(entry->name, sizeof(entry->name), fes->at(i).filename);
+        entry->ino = fes->at(i).ino;
+        snprintf(entry->name, sizeof(entry->name), fes->at(i).filename);
 
-    return GB_OK;
-}
+        return GB_OK;
+    }
 
-struct inode* tmpfs::findinode(struct inode* dir, const char* filename)
-{
-    struct dirent ent { };
-    size_t i = 0;
-    while (readdir(dir, &ent, i) == GB_OK) {
-        if (strcmp(ent.name, filename) == 0) {
-            // optimize: use hash table to build an index
-            auto& inodes = static_cast<tmpfs*>(dir->fs->impl)->m_inodes;
-            for (auto iter = inodes.begin(); iter != inodes.end(); ++iter)
-                if (iter->ino == ent.ino)
-                    return iter.ptr();
+    virtual fs::inode* inode_findinode(fs::inode* dir, const char* filename) override
+    {
+        fs::dirent ent {};
+        size_t i = 0;
+        while (inode_readdir(dir, &ent, i) == GB_OK) {
+            if (strcmp(ent.name, filename) == 0) {
+                // TODO: if the inode is a mount point, the ino MIGHT BE THE SAME
+                // optimize: use hash table to build an index
+                for (auto iter = m_inodes.begin(); iter != m_inodes.end(); ++iter)
+                    if (iter->ino == ent.ino)
+                        return iter.ptr();
+            }
+            ++i;
         }
-        ++i;
+        return nullptr;
     }
-    return nullptr;
-}
 
-int tmpfs::stat(struct inode* dir, struct stat* stat, const char* filename)
-{
-    // for later use
-    // auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
+    virtual int inode_stat(fs::inode* dir, fs::stat* stat, const char* filename) override
+    {
+        // for later use
+        // auto* fes = static_cast<vector<struct tmpfs_file_entry>*>(dir->impl);
 
-    auto* file_inode = vfs_findinode(dir, filename);
+        auto* file_inode = vfs_findinode(dir, filename);
 
-    if (!file_inode) {
-        errno = ENOENT;
-        return GB_FAILED;
-    }
+        if (!file_inode) {
+            errno = ENOENT;
+            return GB_FAILED;
+        }
 
-    stat->st_ino = file_inode->ino;
-    if (file_inode->flags.in.file) {
-        stat->st_rdev.v = 0;
-        stat->st_blksize = 1;
-        stat->st_blocks = static_cast<vector<char>*>(file_inode->impl)->size();
-    }
-    if (file_inode->flags.in.directory) {
-        stat->st_rdev.v = 0;
-        stat->st_blksize = sizeof(struct tmpfs_file_entry);
-        stat->st_blocks = static_cast<vector<struct tmpfs_file_entry>*>(file_inode->impl)->size();
-    }
-    if (file_inode->flags.in.special_node) {
-        stat->st_rdev.v = (uint32_t)file_inode->impl;
-        stat->st_blksize = 0;
-        stat->st_blocks = 0;
+        stat->st_ino = file_inode->ino;
+        if (file_inode->flags.in.file) {
+            stat->st_rdev.v = 0;
+            stat->st_blksize = 1;
+            stat->st_blocks = static_cast<vector<char>*>(file_inode->impl)->size();
+        }
+        if (file_inode->flags.in.directory) {
+            stat->st_rdev.v = 0;
+            stat->st_blksize = sizeof(tmpfs_file_entry);
+            stat->st_blocks = static_cast<vector<tmpfs_file_entry>*>(file_inode->impl)->size();
+        }
+        if (file_inode->flags.in.special_node) {
+            stat->st_rdev.v = (uint32_t)file_inode->impl;
+            stat->st_blksize = 0;
+            stat->st_blocks = 0;
+        }
+
+        return GB_OK;
     }
 
-    return GB_OK;
-}
+    fs::inode* root_inode(void)
+    {
+        return m_inodes.begin().ptr();
+    }
+};
 
 // 8 * 8 for now
-static struct special_node sns[8][8];
+static fs::special_node sns[8][8];
 
-size_t vfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
+size_t fs::vfs_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
 {
     if (file->flags.in.special_node) {
-        union node_t sn {
+        fs::node_t sn {
             .v = (uint32_t)file->impl
         };
         auto* ptr = &sns[sn.in.major][sn.in.minor];
         auto* ops = &ptr->ops;
         if (ops && ops->read)
             return ops->read(ptr, buf, buf_size, offset, n);
+        else {
+            errno = EINVAL;
+            return 0xffffffff;
+        }
     } else {
-        if (file->fs->ops->read)
-            return file->fs->ops->read(file, buf, buf_size, offset, n);
+        return file->fs->inode_read(file, buf, buf_size, offset, n);
     }
-    return 0;
 }
-size_t vfs_write(struct inode* file, const char* buf, size_t offset, size_t n)
+size_t fs::vfs_write(fs::inode* file, const char* buf, size_t offset, size_t n)
 {
     if (file->flags.in.special_node) {
-        union node_t sn {
+        fs::node_t sn {
             .v = (uint32_t)file->impl
         };
         auto* ptr = &sns[sn.in.major][sn.in.minor];
         auto* ops = &ptr->ops;
         if (ops && ops->write)
             return ops->write(ptr, buf, offset, n);
+        else {
+            errno = EINVAL;
+            return 0xffffffff;
+        }
     } else {
-        if (file->fs->ops->read)
-            return file->fs->ops->write(file, buf, offset, n);
+        return file->fs->inode_write(file, buf, offset, n);
     }
-    return 0;
 }
-int vfs_readdir(struct inode* dir, struct dirent* entry, size_t i)
+int fs::vfs_readdir(fs::inode* dir, fs::dirent* entry, size_t i)
 {
-    if (dir->fs->ops->readdir) {
-        return dir->fs->ops->readdir(dir, entry, i);
-    } else {
-        return 0;
-    }
+    return dir->fs->inode_readdir(dir, entry, i);
 }
-struct inode* vfs_findinode(struct inode* dir, const char* filename)
+fs::inode* fs::vfs_findinode(fs::inode* dir, const char* filename)
 {
-    if (dir->fs->ops->findinode) {
-        return dir->fs->ops->findinode(dir, filename);
-    } else {
-        return nullptr;
-    }
+    return dir->fs->inode_findinode(dir, filename);
 }
-int vfs_mkfile(struct inode* dir, const char* filename)
+int fs::vfs_mkfile(fs::inode* dir, const char* filename)
 {
-    if (dir->fs->ops->mkfile) {
-        return dir->fs->ops->mkfile(dir, filename);
-    } else {
-        return 0;
-    }
+    return dir->fs->inode_mkfile(dir, filename);
 }
-int vfs_mknode(struct inode* dir, const char* filename, union node_t sn)
+int fs::vfs_mknode(fs::inode* dir, const char* filename, fs::node_t sn)
 {
-    if (dir->fs->ops->mknode) {
-        return dir->fs->ops->mknode(dir, filename, sn);
-    } else {
-        return 0;
-    }
+    return dir->fs->inode_mknode(dir, filename, sn);
 }
-int vfs_rmfile(struct inode* dir, const char* filename)
+int fs::vfs_rmfile(fs::inode* dir, const char* filename)
 {
-    if (dir->fs->ops->rmfile) {
-        return dir->fs->ops->rmfile(dir, filename);
-    } else {
-        return 0;
-    }
+    return dir->fs->inode_rmfile(dir, filename);
 }
-int vfs_mkdir(struct inode* dir, const char* dirname)
+int fs::vfs_mkdir(fs::inode* dir, const char* dirname)
 {
-    if (dir->fs->ops->mkdir) {
-        return dir->fs->ops->mkdir(dir, dirname);
-    } else {
-        return 0;
-    }
+    return dir->fs->inode_mkdir(dir, dirname);
 }
 
-struct inode* vfs_open(const char* path)
+fs::inode* fs::vfs_open(const char* path)
 {
     if (path[0] == '/' && path[1] == 0x00) {
-        return fs_root;
+        return fs::fs_root;
     }
 
-    struct inode* cur = fs_root;
+    auto* cur = fs::fs_root;
     size_t n = 0;
     switch (*(path++)) {
     // absolute path
@@ -412,16 +368,10 @@ struct inode* vfs_open(const char* path)
     return nullptr;
 }
 
-int vfs_stat(struct stat* stat, const char* _path)
+int fs::vfs_stat(struct stat* stat, const char* _path)
 {
-    if (_path[0] == '/' && _path[1] == 0x00) {
-        if (fs_root->fs->ops->stat) {
-            return fs_root->fs->ops->stat(fs_root, stat, ".");
-        } else {
-            errno = EINVAL;
-            return GB_FAILED;
-        }
-    }
+    if (_path[0] == '/' && _path[1] == 0x00)
+        return fs_root->fs->inode_stat(fs_root, stat, ".");
 
     string path(_path);
     auto iter = path.back();
@@ -437,40 +387,35 @@ int vfs_stat(struct stat* stat, const char* _path)
         return GB_FAILED;
     }
 
-    if (dir_inode->fs->ops->stat) {
-        return dir_inode->fs->ops->stat(dir_inode, stat, filename.c_str());
-    } else {
-        errno = EINVAL;
-        return GB_FAILED;
-    }
+    return dir_inode->fs->inode_stat(dir_inode, stat, filename.c_str());
 }
 
-struct inode* fs_root;
+fs::inode* fs::fs_root;
 static tmpfs* rootfs;
 
-void register_special_block(
+void fs::register_special_block(
     uint16_t major,
     uint16_t minor,
-    special_node_read read,
-    special_node_write write,
+    fs::special_node_read read,
+    fs::special_node_write write,
     uint32_t data1,
     uint32_t data2)
 {
-    struct special_node& sn = sns[major][minor];
+    fs::special_node& sn = sns[major][minor];
     sn.ops.read = read;
     sn.ops.write = write;
     sn.data1 = data1;
     sn.data2 = data2;
 }
 
-size_t b_null_read(struct special_node*, char* buf, size_t buf_size, size_t, size_t n)
+size_t b_null_read(fs::special_node*, char* buf, size_t buf_size, size_t, size_t n)
 {
     if (n >= buf_size)
         n = buf_size;
     memset(buf, 0x00, n);
     return n;
 }
-size_t b_null_write(struct special_node*, const char*, size_t, size_t n)
+size_t b_null_write(fs::special_node*, const char*, size_t, size_t n)
 {
     return n;
 }
@@ -478,30 +423,30 @@ size_t b_null_write(struct special_node*, const char*, size_t, size_t n)
 void init_vfs(void)
 {
     // null
-    register_special_block(0, 0, b_null_read, b_null_write, 0, 0);
+    fs::register_special_block(0, 0, b_null_read, b_null_write, 0, 0);
 
     rootfs = allocator_traits<kernel_allocator<tmpfs>>::allocate_and_construct(4096 * 1024);
-    fs_root = rootfs->root_inode();
+    fs::fs_root = rootfs->root_inode();
 
-    vfs_mkdir(fs_root, "dev");
-    vfs_mkdir(fs_root, "root");
-    vfs_mkfile(fs_root, "init");
+    fs::vfs_mkdir(fs::fs_root, "dev");
+    fs::vfs_mkdir(fs::fs_root, "root");
+    fs::vfs_mkfile(fs::fs_root, "init");
 
-    auto* init = vfs_open("/init");
+    auto* init = fs::vfs_open("/init");
     const char* str = "#/bin/sh\nexec /bin/sh\n";
-    vfs_write(init, str, 0, strlen(str));
+    fs::vfs_write(init, str, 0, strlen(str));
 
-    auto* dev = vfs_open("/dev");
-    vfs_mknode(dev, "null", { .in { .major = 0, .minor = 0 } });
-    vfs_mknode(dev, "console", { .in { .major = 1, .minor = 0 } });
-    vfs_mknode(dev, "hda", { .in { .major = 2, .minor = 0 } });
+    auto* dev = fs::vfs_open("/dev");
+    fs::vfs_mknode(dev, "null", { .in { .major = 0, .minor = 0 } });
+    fs::vfs_mknode(dev, "console", { .in { .major = 1, .minor = 0 } });
+    fs::vfs_mknode(dev, "hda", { .in { .major = 2, .minor = 0 } });
 
-    struct stat _stat { };
+    fs::stat _stat {};
 
-    vfs_stat(&_stat, "/init");
-    vfs_stat(&_stat, "/");
-    vfs_stat(&_stat, "/dev");
-    vfs_stat(&_stat, "/dev/null");
-    vfs_stat(&_stat, "/dev/console");
-    vfs_stat(&_stat, "/dev/hda");
+    fs::vfs_stat(&_stat, "/init");
+    fs::vfs_stat(&_stat, "/");
+    fs::vfs_stat(&_stat, "/dev");
+    fs::vfs_stat(&_stat, "/dev/null");
+    fs::vfs_stat(&_stat, "/dev/console");
+    fs::vfs_stat(&_stat, "/dev/hda");
 }

+ 2 - 1
src/kernel_main.c

@@ -13,7 +13,6 @@
 #include <kernel/stdio.h>
 #include <kernel/task.h>
 #include <kernel/tty.h>
-#include <kernel/vfs.h>
 #include <kernel/vga.h>
 #include <types/bitmap.h>
 
@@ -144,6 +143,8 @@ void init_bss_section(void)
 
 static struct tty early_console;
 
+extern void init_vfs();
+
 void NORETURN kernel_main(void)
 {
     // MAKE_BREAK_POINT();