diff options
Diffstat (limited to 'kernel/filesystem')
| -rw-r--r-- | kernel/filesystem/include/filesystem/filesystem.hpp | 4 | ||||
| -rw-r--r-- | kernel/filesystem/include/filesystem/inode.hpp | 15 | ||||
| -rw-r--r-- | kernel/filesystem/include/filesystem/vfs.hpp | 15 | ||||
| -rw-r--r-- | kernel/filesystem/src/ext2/ext2_filesystem.cpp | 4 | ||||
| -rw-r--r-- | kernel/filesystem/src/filesystem.cpp | 2 | ||||
| -rw-r--r-- | kernel/filesystem/src/inode.cpp | 56 | ||||
| -rw-r--r-- | kernel/filesystem/src/vfs.cpp | 77 |
7 files changed, 156 insertions, 17 deletions
diff --git a/kernel/filesystem/include/filesystem/filesystem.hpp b/kernel/filesystem/include/filesystem/filesystem.hpp index a5a1047..2077ed6 100644 --- a/kernel/filesystem/include/filesystem/filesystem.hpp +++ b/kernel/filesystem/include/filesystem/filesystem.hpp @@ -12,10 +12,10 @@ namespace filesystem virtual auto mount(devices::device * device) -> int = 0; - [[nodiscard]] auto root_inode() const -> inode *; + [[nodiscard]] auto root_inode() const -> inode const &; protected: - inode * m_root_inode{}; // TODO BA-FS26 set during mount? + inode m_root_inode{}; // TODO BA-FS26 set during mount? }; } // namespace filesystem diff --git a/kernel/filesystem/include/filesystem/inode.hpp b/kernel/filesystem/include/filesystem/inode.hpp index 44ec09a..eb8440f 100644 --- a/kernel/filesystem/include/filesystem/inode.hpp +++ b/kernel/filesystem/include/filesystem/inode.hpp @@ -1,13 +1,28 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP +#include "devices/device.hpp" + #include <cstddef> + namespace filesystem { struct inode { + inode() = default; + explicit inode(devices::device * device); + + [[nodiscard]] auto is_device() const -> bool; + [[nodiscard]] auto is_block_device() const -> bool; + [[nodiscard]] auto major_device() const -> size_t; + [[nodiscard]] auto minor_device() const -> size_t; + [[nodiscard]] auto backing_device() const -> devices::device *; + auto read(void * buffer, size_t offset, size_t size) const -> size_t; auto write(void const * buffer, size_t offset, size_t size) -> size_t; + + private: + devices::device * m_device{}; }; } // namespace filesystem diff --git a/kernel/filesystem/include/filesystem/vfs.hpp b/kernel/filesystem/include/filesystem/vfs.hpp index 182666d..a881241 100644 --- a/kernel/filesystem/include/filesystem/vfs.hpp +++ b/kernel/filesystem/include/filesystem/vfs.hpp @@ -2,10 +2,14 @@ #define TEACH_OS_KERNEL_FILESYSTEM_VFS_HPP #include "devices/device.hpp" +#include "filesystem/custody.hpp" +#include "filesystem/inode.hpp" #include "filesystem/mount.hpp" +#include "filesystem/open_file_description.hpp" #include <array> #include <optional> +#include <string_view> namespace filesystem { @@ -16,13 +20,22 @@ namespace filesystem ~vfs() = default; - auto make_device_node(devices::device * device) -> void; + auto open(std::string_view path) -> std::optional<open_file_description>; private: + struct device_node_entry + { + std::string_view name; + inode node; + }; + vfs() = default; + auto make_device_node(devices::device * device) -> void; + [[nodiscard]] auto resolve_path(std::string_view path) -> std::optional<custody>; std::optional<mount> m_root_mount; std::array<mount, 10> m_mounts; // TODO BA-FS26 remove when kstd::vector is available and used + std::array<std::optional<device_node_entry>, 10> m_device_nodes; // TODO BA-FS26 use kstd::vector }; } // namespace filesystem diff --git a/kernel/filesystem/src/ext2/ext2_filesystem.cpp b/kernel/filesystem/src/ext2/ext2_filesystem.cpp index 7111d13..97257a2 100644 --- a/kernel/filesystem/src/ext2/ext2_filesystem.cpp +++ b/kernel/filesystem/src/ext2/ext2_filesystem.cpp @@ -1,6 +1,7 @@ #include "filesystem/ext2/ext2_filesystem.hpp" #include "devices/device.hpp" +#include "filesystem/inode.hpp" namespace filesystem::ext2 { @@ -10,6 +11,9 @@ namespace filesystem::ext2 { return -1; // TODO BA-FS26 panic or errorcode? } + + m_root_inode = inode{}; // TODO BA-FS26 set properly during mount? + // TODO BA-FS26 implement return 0; } diff --git a/kernel/filesystem/src/filesystem.cpp b/kernel/filesystem/src/filesystem.cpp index 2c63766..cdfe7f8 100644 --- a/kernel/filesystem/src/filesystem.cpp +++ b/kernel/filesystem/src/filesystem.cpp @@ -4,7 +4,7 @@ namespace filesystem { - auto filesystem::root_inode() const -> inode * + auto filesystem::root_inode() const -> inode const & { return m_root_inode; } diff --git a/kernel/filesystem/src/inode.cpp b/kernel/filesystem/src/inode.cpp index 7bca507..a1427e2 100644 --- a/kernel/filesystem/src/inode.cpp +++ b/kernel/filesystem/src/inode.cpp @@ -2,18 +2,74 @@ #include "kapi/system.hpp" +#include "devices/device.hpp" + #include <cstddef> namespace filesystem { + inode::inode(devices::device * device) + : m_device(device) + { + if (!m_device) + { + kapi::system::panic("[FILESYSTEM] inode constructed with null device."); + } + } + + auto inode::is_device() const -> bool + { + return m_device != nullptr; + } + + auto inode::is_block_device() const -> bool + { + return is_device() && m_device->is_block_device(); + } + + auto inode::major_device() const -> size_t + { + if (!is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::major_device called on non-device inode."); + } + + return m_device->major(); + } + + auto inode::minor_device() const -> size_t + { + if (!is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::minor_device called on non-device inode."); + } + + return m_device->minor(); + } + + auto inode::backing_device() const -> devices::device * + { + return m_device; + } + auto inode::read(void * /*buffer*/, size_t /*offset*/, size_t /*size*/) const -> size_t { + if (is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::read called on device inode. Open it as a device file first."); + } + // TODO BA-FS26 return 0; } auto inode::write(void const *, size_t, size_t) -> size_t { + if (is_device()) + { + kapi::system::panic("[FILESYSTEM] inode::write called on device inode. Open it as a device file first."); + } + kapi::system::panic("[FILESYSTEM] inode::write is not implemented yet"); return 0; } diff --git a/kernel/filesystem/src/vfs.cpp b/kernel/filesystem/src/vfs.cpp index 573994a..2ecf847 100644 --- a/kernel/filesystem/src/vfs.cpp +++ b/kernel/filesystem/src/vfs.cpp @@ -4,13 +4,17 @@ #include "devices/device.hpp" #include "devices/storage/storage_management.hpp" +#include "filesystem/custody.hpp" +#include "filesystem/device_file.hpp" #include "filesystem/ext2/ext2_filesystem.hpp" +#include "filesystem/inode.hpp" +#include "filesystem/inode_file.hpp" #include "filesystem/mount.hpp" +#include "filesystem/open_file_description.hpp" #include <kstd/cstring> #include <algorithm> -#include <array> #include <optional> #include <string_view> @@ -23,12 +27,11 @@ namespace filesystem // TODO BA-FS26 @Felix better solution? while dynamic memory not available? // TODO BA-FS26 remove when dynamic memory available; constinit auto static root_fs = std::optional<ext2::ext2_filesystem>{}; - // TODO BA-FS26 use kstd::vector when available - constinit auto static filesystems = std::array<std::optional<ext2::ext2_filesystem>, 1>{}; - // TODO BA-FS26 @Felix - // TODO BA-FS26 depends on the length of ram_disk_device name - constinit std::array<char, 10> device_mount_path = {'/', 'd', 'e', 'v', '/', 'x', 'x', 'x', 'x', '\0'}; + // TODO BA-FS26 remove when dynamic memory available; + constinit auto static temp_device_file = std::optional<device_file>{}; + // TODO BA-FS26 remove when dynamic memory available; + constinit auto static temp_inode_file = std::optional<inode_file>{}; } // namespace auto vfs::init() -> void @@ -71,19 +74,67 @@ namespace filesystem return *active_vfs; } + auto vfs::open(std::string_view path) -> std::optional<open_file_description> + { + if (auto custody = resolve_path(path)) + { + auto * node = custody->get_inode(); + if (node->is_device()) + { + temp_device_file.emplace(node->backing_device()); + temp_device_file->open(); + return open_file_description{&*temp_device_file}; + } + + temp_inode_file.emplace(node); + temp_inode_file->open(); + return open_file_description{&*temp_inode_file}; + } + + return std::nullopt; + } + auto vfs::make_device_node(devices::device * device) -> void { - auto device_name = device->name(); - kstd::libc::memcpy(&device_mount_path[5], device_name.data(), device_name.size()); + if (!device) + { + kapi::system::panic("[FILESYSTEM] make_device_node called with null device."); + } + + auto const device_name = device->name(); + + // TODO BA-FS26 this logic isn't needed anymore when kstd::vector available, just use push_back + auto const slot = std::ranges::find_if(m_device_nodes, [](auto const & entry) { return !entry.has_value(); }); + if (slot == m_device_nodes.end()) + { + kapi::system::panic("[FILESYSTEM] No free slot available for device nodes."); + } + + slot->emplace(device_node_entry{device_name, inode{device}}); + } + + auto vfs::resolve_path(std::string_view path) -> std::optional<custody> + { + // TODO BA-FS26 implement real path resolution with mounts and directories etc. + // For now, just support device nodes at /dev/<device_name>. - // TODO BA-FS26 use kstd::vector and push_back when available - filesystems[0].emplace(ext2::ext2_filesystem{}); - if (filesystems[0]->mount(device) != 0) + constexpr auto device_prefix = std::string_view{"/dev/"}; + if (path.starts_with(device_prefix)) { - kapi::system::panic("[FILESYSTEM] Failed to mount device filesystem."); + auto const device_name = path.substr(device_prefix.size()); + auto entry = std::ranges::find_if(m_device_nodes, [&](auto const & device_entry) { + return device_entry.has_value() && device_entry->name == device_name; + }); + + if (entry != m_device_nodes.end()) + { + return custody{nullptr, &entry->value().node}; + } + + return std::nullopt; } - m_mounts[0] = mount{std::string_view{device_mount_path.data()}, &*filesystems[0]}; + return std::nullopt; } } // namespace filesystem
\ No newline at end of file |
