diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-22 16:02:50 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-22 16:02:50 +0200 |
| commit | d027d60f364e4e6345d26bc5f90eaedcc7793fc7 (patch) | |
| tree | 0d24db962a34289a6cff443c12983f71d94efde6 | |
| parent | 984d20ec8cb734cb47fb1ff5d34861eaf9f4aa32 (diff) | |
| download | kernel-d027d60f364e4e6345d26bc5f90eaedcc7793fc7.tar.xz kernel-d027d60f364e4e6345d26bc5f90eaedcc7793fc7.zip | |
kapi/fs: implement status and raw_device
| -rw-r--r-- | kapi/kapi/filesystem.hpp | 6 | ||||
| -rw-r--r-- | kernel/kapi/filesystem.cpp | 5 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/device_inode.cpp | 15 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/device_inode.hpp | 5 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/device_inode.tests.cpp | 51 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/inode.cpp | 32 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/inode.hpp | 7 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/inode.cpp | 46 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/inode.hpp | 14 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/vfs.cpp | 11 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/vfs.hpp | 5 | ||||
| -rw-r--r-- | kernel/kernel/test_support/filesystem/filesystem.cpp | 5 | ||||
| -rw-r--r-- | kernel/kernel/test_support/filesystem/filesystem.hpp | 5 |
13 files changed, 203 insertions, 4 deletions
diff --git a/kapi/kapi/filesystem.hpp b/kapi/kapi/filesystem.hpp index 2b5dc827..56bb295f 100644 --- a/kapi/kapi/filesystem.hpp +++ b/kapi/kapi/filesystem.hpp @@ -80,6 +80,12 @@ namespace kapi::filesystem //! @return Nothing on success, an error on failure. auto create(std::string_view path) -> kstd::result<void>; + //! Get the status information for the file at a given path. + //! + //! @param path The path to the file to query information for. + //! @return A populated file status object on success, an error otherwise. + auto status(std::string_view path) -> kstd::result<file_status>; + //! @} } // namespace kapi::filesystem diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index b2f94747..10c9835a 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -68,4 +68,9 @@ namespace kapi::filesystem return kernel::filesystem::vfs::get().create(path); } + auto status(std::string_view path) -> kstd::result<file_status> + { + return kernel::filesystem::vfs::get().status(path); + } + } // namespace kapi::filesystem
\ No newline at end of file diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp index 464c5ea9..5ac18019 100644 --- a/kernel/kernel/filesystem/device_inode.cpp +++ b/kernel/kernel/filesystem/device_inode.cpp @@ -1,16 +1,21 @@ #include <kernel/filesystem/device_inode.hpp> #include <kernel/devices/block_device_utils.hpp> +#include <kernel/filesystem/device_number_registry.hpp> #include <kernel/filesystem/error.hpp> +#include <kernel/filesystem/inode.hpp> #include <kapi/devices.hpp> #include <kapi/devices/device.hpp> +#include <kapi/filesystem.hpp> #include <kapi/system.hpp> #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/units.hpp> +#include <optional> + namespace kernel::filesystem { device_inode::device_inode(kstd::shared_ptr<kapi::devices::device> const & device) @@ -54,4 +59,14 @@ namespace kernel::filesystem return true; } + auto device_inode::raw_device() const -> std::optional<kapi::filesystem::device_number> + { + if (auto number = device_number_registry::get().number_of(*m_device)) + { + return *number; + } + + return std::nullopt; + } + } // namespace kernel::filesystem
\ No newline at end of file diff --git a/kernel/kernel/filesystem/device_inode.hpp b/kernel/kernel/filesystem/device_inode.hpp index be9fc577..698124f2 100644 --- a/kernel/kernel/filesystem/device_inode.hpp +++ b/kernel/kernel/filesystem/device_inode.hpp @@ -4,11 +4,14 @@ #include <kernel/filesystem/inode.hpp> #include <kapi/devices/device.hpp> +#include <kapi/filesystem.hpp> #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/units.hpp> +#include <optional> + namespace kernel::filesystem { /** @@ -58,6 +61,8 @@ namespace kernel::filesystem */ [[nodiscard]] auto is_block_device() const -> bool override; + [[nodiscard]] auto raw_device() const -> std::optional<kapi::filesystem::device_number> override; + private: kstd::shared_ptr<kapi::devices::device> m_device; }; diff --git a/kernel/kernel/filesystem/device_inode.tests.cpp b/kernel/kernel/filesystem/device_inode.tests.cpp index e821ce1d..4c6e0338 100644 --- a/kernel/kernel/filesystem/device_inode.tests.cpp +++ b/kernel/kernel/filesystem/device_inode.tests.cpp @@ -1,11 +1,18 @@ #include <kernel/filesystem/device_inode.hpp> +#include <kernel/filesystem/device_number_registry.hpp> +#include <kernel/filesystem/inode.hpp> #include <kernel/test_support/cpu.hpp> #include <kernel/test_support/devices/block_device.hpp> #include <kernel/test_support/devices/character_device.hpp> +#include <kernel/test_support/filesystem/device_number_registry.hpp> + +#include <kapi/devices.hpp> +#include <kapi/filesystem.hpp> #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/result.hpp> #include <kstd/system_error.hpp> #include <kstd/units.hpp> #include <kstd/vector.hpp> @@ -17,6 +24,17 @@ using namespace kstd::units_literals; +namespace +{ + struct registry_reset_guard + { + ~registry_reset_guard() + { + kernel::tests::filesystem::device_number_registry::deinit(); + } + }; +} // namespace + SCENARIO("Device inode construction", "[filesystem][device_inode]") { GIVEN("a block device") @@ -117,3 +135,36 @@ SCENARIO("Device inode read/write with a non-block device", "[filesystem][device } } } + +SCENARIO("Device inode raw_device()", "[filesystem][device-inode]") +{ + auto resetter = registry_reset_guard{}; + + GIVEN("A block device that has been published and numbered") + { + auto device = kstd::make_shared<kernel::tests::devices::block_device>("ram0", 512_B); + REQUIRE(kapi::devices::interface_registry::get().publish<kapi::devices::block_device>(device, "ram0")); + + auto inode = kernel::filesystem::device_inode{device}; + + THEN("raw_device() return the number assigned to the device") + { + auto expected = kernel::filesystem::device_number_registry::get().number_of(*device); + REQUIRE(expected); + + auto actual = inode.raw_device(); + REQUIRE(actual == expected); + } + } + + GIVEN("a block device that has never been published") + { + auto device = kstd::make_shared<kernel::tests::devices::block_device>("never_published", 512_B); + auto inode = kernel::filesystem::device_inode{device}; + + THEN("raw_device() is nullopt, not a stale or default number") + { + REQUIRE_FALSE(inode.raw_device()); + } + } +} diff --git a/kernel/kernel/filesystem/ext2/inode.cpp b/kernel/kernel/filesystem/ext2/inode.cpp index f42e2c0c..89e52232 100644 --- a/kernel/kernel/filesystem/ext2/inode.cpp +++ b/kernel/kernel/filesystem/ext2/inode.cpp @@ -3,6 +3,7 @@ #include <kernel/filesystem/ext2/filesystem.hpp> #include <kernel/filesystem/inode.hpp> +#include <kapi/filesystem.hpp> #include <kapi/system.hpp> #include <kstd/cstring.hpp> @@ -12,6 +13,7 @@ #include <algorithm> #include <cstddef> #include <cstdint> +#include <optional> using namespace kstd::units_literals; @@ -201,6 +203,36 @@ namespace kernel::filesystem::ext2 return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link; } + auto inode::status() const -> kstd::result<kapi::filesystem::file_status> + { + auto result = kernel::filesystem::inode::status(); + if (!result) + { + return result; + } + + result->size = size(); + result->inode_number = m_inode_number; + result->link_count = m_data.links_count; + + return result; + } + + auto inode::raw_device() const -> std::optional<kapi::filesystem::device_number> + { + if (!is_device()) + { + return std::nullopt; + } + + auto const raw_device_number = m_data.block[0]; + + return kapi::filesystem::device_number{ + .major = static_cast<std::uint8_t>((raw_device_number >> 8) & 0xff), + .minor = static_cast<std::uint8_t>(raw_device_number & 0xff), + }; + } + auto inode::size() const -> kstd::units::bytes { uint64_t size = m_data.size; diff --git a/kernel/kernel/filesystem/ext2/inode.hpp b/kernel/kernel/filesystem/ext2/inode.hpp index 1d364a54..a15532b0 100644 --- a/kernel/kernel/filesystem/ext2/inode.hpp +++ b/kernel/kernel/filesystem/ext2/inode.hpp @@ -3,6 +3,8 @@ #include <kernel/filesystem/inode.hpp> +#include <kapi/filesystem.hpp> + #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/units.hpp> @@ -10,6 +12,7 @@ #include <array> #include <cstddef> #include <cstdint> +#include <optional> namespace kernel::filesystem::ext2 { @@ -107,6 +110,10 @@ namespace kernel::filesystem::ext2 */ [[nodiscard]] auto is_symbolic_link() const -> bool override; + [[nodiscard]] auto status() const -> kstd::result<kapi::filesystem::file_status> override; + + [[nodiscard]] auto raw_device() const -> std::optional<kapi::filesystem::device_number> override; + /** @brief Get the size of the file represented by this inode. @return The size of the file in bytes. diff --git a/kernel/kernel/filesystem/inode.cpp b/kernel/kernel/filesystem/inode.cpp index e564ab38..d0762472 100644 --- a/kernel/kernel/filesystem/inode.cpp +++ b/kernel/kernel/filesystem/inode.cpp @@ -1,5 +1,12 @@ #include <kernel/filesystem/inode.hpp> +#include <kapi/filesystem.hpp> + +#include <kstd/result.hpp> + +#include <optional> +#include <utility> + namespace kernel::filesystem { auto inode::is_directory() const -> bool @@ -31,4 +38,43 @@ namespace kernel::filesystem { return false; } + + auto inode::status() const -> kstd::result<kapi::filesystem::file_status> + { + auto result = kapi::filesystem::file_status{}; + + if (is_directory()) + { + result.mode = std::to_underlying(kapi::filesystem::file_type::directory); + } + else if (is_regular()) + { + result.mode = std::to_underlying(kapi::filesystem::file_type::regular); + } + else if (is_block_device()) + { + result.mode = std::to_underlying(kapi::filesystem::file_type::block_device); + } + else if (is_character_device()) + { + result.mode = std::to_underlying(kapi::filesystem::file_type::character_device); + } + else if (is_symbolic_link()) + { + result.mode = std::to_underlying(kapi::filesystem::file_type::symbolic_link); + } + + if (auto const number = raw_device()) + { + result.raw_device = *number; + } + + return result; + } + + auto inode::raw_device() const -> std::optional<kapi::filesystem::device_number> + { + return std::nullopt; + } + } // namespace kernel::filesystem
\ No newline at end of file diff --git a/kernel/kernel/filesystem/inode.hpp b/kernel/kernel/filesystem/inode.hpp index 005dc57b..25e5df31 100644 --- a/kernel/kernel/filesystem/inode.hpp +++ b/kernel/kernel/filesystem/inode.hpp @@ -1,9 +1,13 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_INODE_HPP +#include <kapi/filesystem.hpp> + #include <kstd/result.hpp> #include <kstd/units.hpp> +#include <optional> + namespace kernel::filesystem { //! Represents an inode in the filesystem. @@ -62,6 +66,16 @@ namespace kernel::filesystem //! //! @return true iff. this inode is a symbolic link, false otherwise. [[nodiscard]] virtual auto is_symbolic_link() const -> bool; + + //! Get POSIX status information for this inode. + //! + //! @return a populated status information object, or an error or failure. + [[nodiscard]] virtual auto status() const -> kstd::result<kapi::filesystem::file_status>; + + //! Get the raw device, if any, this inode refers to. + //! + //! @return a device number if this inode refers to a device, an empty optional otherwise. + [[nodiscard]] virtual auto raw_device() const -> std::optional<kapi::filesystem::device_number>; }; } // namespace kernel::filesystem diff --git a/kernel/kernel/filesystem/vfs.cpp b/kernel/kernel/filesystem/vfs.cpp index 6533e027..c1a36856 100644 --- a/kernel/kernel/filesystem/vfs.cpp +++ b/kernel/kernel/filesystem/vfs.cpp @@ -186,6 +186,17 @@ namespace kernel::filesystem return create_inode(path, vfs_types::inode_type::regular); } + auto vfs::status(std::string_view path) const -> kstd::result<kapi::filesystem::file_status> + { + auto resolved = resolve_path(path); + if (!resolved) + { + return kstd::failure(resolved.error()); + } + + return (*resolved)->get_inode()->status(); + } + auto vfs::create_inode(std::string_view path, vfs_types::inode_type type, std::optional<kapi::filesystem::device_number> raw_device) -> kstd::result<void> { diff --git a/kernel/kernel/filesystem/vfs.hpp b/kernel/kernel/filesystem/vfs.hpp index b965e426..6ab67ef8 100644 --- a/kernel/kernel/filesystem/vfs.hpp +++ b/kernel/kernel/filesystem/vfs.hpp @@ -96,6 +96,11 @@ namespace kernel::filesystem // TODO remove again after the open method supports an optional create flag auto create(std::string_view path) -> kstd::result<void>; + //! Get the status of the file at a given path. + //! + //! @return A populated file status object on success, an error otherwise. + [[nodiscard]] auto status(std::string_view path) const -> kstd::result<kapi::filesystem::file_status>; + private: /** * Note: Resolving a dentry requires traversing mount points; since the diff --git a/kernel/kernel/test_support/filesystem/filesystem.cpp b/kernel/kernel/test_support/filesystem/filesystem.cpp index 4dd69668..3acedd5f 100644 --- a/kernel/kernel/test_support/filesystem/filesystem.cpp +++ b/kernel/kernel/test_support/filesystem/filesystem.cpp @@ -1,10 +1,11 @@ #include <kernel/test_support/filesystem/filesystem.hpp> -#include <kernel/filesystem/device_number.hpp> #include <kernel/filesystem/inode.hpp> #include <kernel/filesystem/vfs_types.hpp> #include <kernel/test_support/filesystem/inode.hpp> +#include <kapi/filesystem.hpp> + #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/system_error.hpp> @@ -22,7 +23,7 @@ namespace kernel::tests::filesystem auto filesystem::create_inode(kstd::shared_ptr<kernel::filesystem::inode> const &, std::string_view, kernel::filesystem::vfs_types::inode_type, - std::optional<kernel::filesystem::device_number>) + std::optional<kapi::filesystem::device_number>) -> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>> { return kstd::make_shared<inode>(); diff --git a/kernel/kernel/test_support/filesystem/filesystem.hpp b/kernel/kernel/test_support/filesystem/filesystem.hpp index 0f51499e..2b61aea3 100644 --- a/kernel/kernel/test_support/filesystem/filesystem.hpp +++ b/kernel/kernel/test_support/filesystem/filesystem.hpp @@ -1,11 +1,12 @@ #ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_FILESYSTEM_HPP #define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_FILESYSTEM_HPP -#include <kernel/filesystem/device_number.hpp> #include <kernel/filesystem/filesystem.hpp> #include <kernel/filesystem/inode.hpp> #include <kernel/filesystem/vfs_types.hpp> +#include <kapi/filesystem.hpp> + #include <kstd/memory.hpp> #include <kstd/result.hpp> #include <kstd/system_error.hpp> @@ -24,7 +25,7 @@ namespace kernel::tests::filesystem [[nodiscard]] auto create_inode(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name, kernel::filesystem::vfs_types::inode_type inode_type, - std::optional<kernel::filesystem::device_number> = std::nullopt) + std::optional<kapi::filesystem::device_number> = std::nullopt) -> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>> override; }; } // namespace kernel::tests::filesystem |
