diff options
author | Benji Dial <benji@benjidial.net> | 2024-01-12 20:39:21 -0500 |
---|---|---|
committer | Benji Dial <benji@benjidial.net> | 2024-01-12 20:39:21 -0500 |
commit | 882e74b2191c059a9226cbd8bcb51c97da36247c (patch) | |
tree | 3ecc05882a9097a85749902130849be65911e684 /kernel/entry.cpp | |
parent | c4ab2f6f440f060b1686991b24379a4998aa55a9 (diff) | |
download | hilbert-os-882e74b2191c059a9226cbd8bcb51c97da36247c.tar.gz |
rewrite file system layer
Diffstat (limited to 'kernel/entry.cpp')
-rw-r--r-- | kernel/entry.cpp | 151 |
1 files changed, 70 insertions, 81 deletions
diff --git a/kernel/entry.cpp b/kernel/entry.cpp index aa6568a..445d560 100644 --- a/kernel/entry.cpp +++ b/kernel/entry.cpp @@ -1,9 +1,10 @@ +#include <mercury/kernel/storage/bd/memory.hpp> +#include <mercury/kernel/storage/fs/tarfs.hpp> #include <mercury/kernel/framebuffer.hpp> -#include <mercury/kernel/bd/memory.hpp> -#include <mercury/kernel/fs/tarfs.hpp> #include <mercury/kernel/terminal.hpp> #include <mercury/kernel/limine.hpp> #include <mercury/kernel/paging.hpp> +#include <mercury/kernel/vfile.hpp> using namespace mercury::kernel; @@ -182,78 +183,67 @@ extern "C" [[noreturn]] void entry() { [[noreturn]] static void print_and_halt(const char *msg) { terminal::put_string_sz(msg); while (1) - ; + asm ("hlt"); +} + +static void draw_indent(unsigned indent) { + for (unsigned i = 0; i < indent; ++i) + terminal::put_char(' '); } static void dir_tree( - storage::block_device *bd, storage::node_id_t node, unsigned indent + const vfile::vfile &root, const vfile::vfile &f, unsigned indent ) { - storage::node_id_t child_node; - storage::directory_iter_t dir_iter; - storage::io_result result = - bd->mounted_as->get_first_child(node, child_node, dir_iter); - if (result == storage::io_result::not_found) { - for (unsigned i = 0; i < indent; ++i) - terminal::put_char(' '); - terminal::put_string_sz("[empty]\n"); - return; - } - else if (result) - print_and_halt("error getting first child."); - - while (true) { - - unsigned name_len; - if (bd->mounted_as->get_name_length(child_node, name_len)) - print_and_halt("failed to get name length."); - char *name_buf = new char[name_len]; - if (bd->mounted_as->get_name(child_node, name_buf, name_len)) - print_and_halt("failed to get name."); - - for (unsigned i = 0; i < indent; ++i) - terminal::put_char(' '); - terminal::put_string(name_buf, name_len); - terminal::put_string(":\n", 2); - - delete[] name_buf; - - storage::file_type type; - if (bd->mounted_as->get_file_type(child_node, type)) - print_and_halt("failed to get type."); - - if (type == storage::file_type::directory) - dir_tree(bd, child_node, indent + 2); - - else { - uint64_t len; - if (bd->mounted_as->get_file_length(child_node, len)) - print_and_halt("failed to get length."); - char *contents = new char[len]; - if (bd->mounted_as->read_bytes_from_file(child_node, 0, len, contents)) - print_and_halt("failed to read file."); - - if (contents[len - 1] == '\n') - len--; - - for (unsigned i = 0; i < indent + 2; ++i) - terminal::put_char(' '); - if (len == 0) + draw_indent(indent); + terminal::put_string(f.dir_entry.name); + terminal::put_char('\n'); + + std::optional<vfile::vfile> followed; + utility::vector<vfile::vfile> children; + + switch (f.dir_entry.type) { + + case storage::file_type::regular_file: + draw_indent(indent + 2); + terminal::put_string_sz("type: regular file\n"); + draw_indent(indent + 2); + terminal::put_string_sz("length: "); + terminal::put_int_decimal(f.dir_entry.length); + terminal::put_string_sz(" bytes\n"); + break; + + case storage::file_type::symlink: + draw_indent(indent + 2); + terminal::put_string_sz("type: symlink\n"); + draw_indent(indent + 2); + terminal::put_string_sz("target: "); + terminal::put_string(f.dir_entry.target); + terminal::put_char('\n'); + if (f.follow_symlinks(root, followed) != storage::fs_result::success) + print_and_halt("failed to follow symlink."); + if (!followed) { + draw_indent(indent + 4); + terminal::put_string_sz("[broken]\n"); + } + dir_tree(root, *followed, indent + 4); + break; + + case storage::file_type::directory: + if (f.get_children(children) != storage::fs_result::success) + print_and_halt("failed to get children."); + draw_indent(indent + 2); + terminal::put_string_sz("type: directory\n"); + draw_indent(indent + 2); + terminal::put_string_sz("children:\n"); + if (children.count == 0) { + draw_indent(indent + 4); terminal::put_string_sz("[empty]\n"); - else { - terminal::put_string(contents, len); - terminal::put_char('\n'); } - - delete[] contents; - } - - storage::io_result result - = bd->mounted_as->get_next_child(node, child_node, dir_iter); - if (result == storage::io_result::not_found) - return; - else if (result) - print_and_halt("error getting next child."); + else + for (unsigned i = 0; i < children.count; ++i) + dir_tree(root, children.buffer[i], indent + 4); + break; } @@ -262,16 +252,10 @@ static void dir_tree( [[noreturn]] static void with_kernel_p4() { terminal::init_terminal(); - storage::init_storage(); - - storage::block_device *initfs_bd = new bd::memory(initfs, initfs_len); - storage::block_devices->insert_end(initfs_bd); - storage::canon_path root; - storage::canonize_path("/", 1, root); - - if (storage::mount_device(initfs_bd, root, &fs::tarfs_mounter)) - print_and_halt("failed to mount initfs."); + storage::bd::memory initfs_bd(initfs, initfs_len); + storage::fs::tarfs_instance initfs_fs(&initfs_bd); + initfs_bd.mounted_as = &initfs_fs; terminal::put_string_sz("kernel initialization complete.\n"); @@ -283,12 +267,17 @@ static void dir_tree( terminal::put_int_decimal(free_pram_kib); terminal::put_string_sz(" kiB physical memory free.\n"); - storage::node_id_t root_node; - if (initfs_bd->mounted_as->get_root_node(root_node)) - print_and_halt("failed to get root initfs node."); + vfile::vfile root; + root.bd = &initfs_bd; + root.dir_entry.type = storage::file_type::directory; + root.path.absolute = true; + + if (initfs_fs.get_root_node(root.dir_entry.node) != + storage::fs_result::success) + print_and_halt("failed to get root node."); - terminal::put_string_sz("initfs:\n"); - dir_tree(initfs_bd, root_node, 2); + terminal::put_string_sz("initfs"); + dir_tree(root, root, 0); print_and_halt("halting."); } |