diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-12 21:37:50 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-12 21:37:50 +0200 |
| commit | 3dc0df78f96dae38a54208d78e14f977f085b9bb (patch) | |
| tree | 41418bec535cab0e96ce146617763a1952766f0b /kernel | |
| parent | f54e09351a967da21f863fd2d3b17ffd24d3ee87 (diff) | |
| download | kernel-3dc0df78f96dae38a54208d78e14f977f085b9bb.tar.xz kernel-3dc0df78f96dae38a54208d78e14f977f085b9bb.zip | |
kapi: enforce stricter error handling
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kapi/filesystem.cpp | 58 | ||||
| -rw-r--r-- | kernel/kapi/filesystem.tests.cpp | 72 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/open_file_table.cpp | 20 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/open_file_table.hpp | 9 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/open_file_table.tests.cpp | 21 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/vfs.cpp | 40 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/vfs.hpp | 35 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/vfs.tests.cpp | 185 | ||||
| -rw-r--r-- | kernel/kernel/main.cpp | 15 |
9 files changed, 214 insertions, 241 deletions
diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index 24a3adf3..f84949da 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -6,7 +6,6 @@ #include <kstd/memory.hpp> #include <kstd/system_error.hpp> -#include <kstd/unikstd.h> #include <cstddef> #include <expected> @@ -14,62 +13,45 @@ namespace kapi::filesystem { - auto mount(std::string_view source, std::string_view target) -> kstd::ssize_t + auto mount(std::string_view source, std::string_view target) -> std::expected<void, kstd::error_code> { - if (kernel::filesystem::vfs::get().do_mount(source, target) == kernel::filesystem::vfs::operation_result::success) - { - return 0; - } - return -1; + return kernel::filesystem::vfs::get().do_mount(source, target); } - auto umount(std::string_view target) -> kstd::ssize_t + auto umount(std::string_view target) -> std::expected<void, kstd::error_code> { - if (kernel::filesystem::vfs::get().unmount(target) == kernel::filesystem::vfs::operation_result::success) - { - return 0; - } - return -1; + return kernel::filesystem::vfs::get().unmount(target); } auto open(std::string_view path) -> std::expected<std::size_t, kstd::error_code> { - return kernel::filesystem::vfs::get().open(path).transform([](auto dentry) { + return kernel::filesystem::vfs::get().open(path).and_then([](auto dentry) { auto open_file_descriptor = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); return kernel::filesystem::open_file_table::get().add_file(open_file_descriptor); }); } - auto close(size_t file_descriptor) -> kstd::ssize_t + auto close(size_t file_descriptor) -> std::expected<void, kstd::error_code> { - if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().file(file_descriptor)) - { - if (kernel::filesystem::vfs::get().close(open_file_descriptor->get_dentry()->absolute_path()) == - kernel::filesystem::vfs::operation_result::success) - { - return kernel::filesystem::open_file_table::get().remove_file(file_descriptor); - } - } - return -1; + return kernel::filesystem::open_file_table::get() + .file(file_descriptor) + .transform([](auto file) { return file->get_dentry()->absolute_path(); }) + .and_then([](auto path) { return kernel::filesystem::vfs::get().close(path); }) + .and_then([=]() { return kernel::filesystem::open_file_table::get().remove_file(file_descriptor); }) + .transform([](auto) { return; }); } - auto read(size_t file_descriptor, void * buffer, size_t size) -> kstd::ssize_t + auto read(size_t file_descriptor, void * buffer, size_t size) -> std::expected<std::size_t, kstd::error_code> { - if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().file(file_descriptor)) - { - return open_file_descriptor->read(buffer, size); - } - - return -1; + return kernel::filesystem::open_file_table::get().file(file_descriptor).transform([=](auto descriptor) { + return descriptor->read(buffer, size); + }); } - auto write(size_t file_descriptor, void const * buffer, size_t size) -> kstd::ssize_t + auto write(size_t file_descriptor, void const * buffer, size_t size) -> std::expected<std::size_t, kstd::error_code> { - if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().file(file_descriptor)) - { - return open_file_descriptor->write(buffer, size); - } - - return -1; + return kernel::filesystem::open_file_table::get().file(file_descriptor).transform([=](auto descriptor) { + return descriptor->write(buffer, size); + }); } } // namespace kapi::filesystem
\ No newline at end of file diff --git a/kernel/kapi/filesystem.tests.cpp b/kernel/kapi/filesystem.tests.cpp index 37d0c20d..d1e01db6 100644 --- a/kernel/kapi/filesystem.tests.cpp +++ b/kernel/kapi/filesystem.tests.cpp @@ -2,6 +2,8 @@ #include <kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp> +#include <kstd/system_error.hpp> + #include <catch2/catch_test_macros.hpp> #include <algorithm> @@ -29,12 +31,12 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(6); auto bytes_read = kapi::filesystem::read(fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(*bytes_read)}; REQUIRE(buffer_as_str == "info_1"); - REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::close(fd)); } THEN("files can be opened through absolute symbolic link, read and closed again") @@ -43,12 +45,12 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(6); auto bytes_read = kapi::filesystem::read(fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(*bytes_read)}; REQUIRE(buffer_as_str == "info_1"); - REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::close(fd)); } THEN("files can be opened through relative symbolic link, read and closed again") @@ -57,57 +59,57 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(6); auto bytes_read = kapi::filesystem::read(fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(*bytes_read)}; REQUIRE(buffer_as_str == "info_1"); - REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::close(fd)); } THEN("files can be opened through relative symbolic link over multiple mount points, read and closed again") { - kapi::filesystem::mount("/archiv/2024.img", "/information"); + CHECK(kapi::filesystem::mount("/archiv/2024.img", "/information")); auto fd = kapi::filesystem::open("/information/symlinks/traverse_back_twice/information/sheep_1.txt").value(); auto buffer = std::vector<std::byte>(7); auto bytes_read = kapi::filesystem::read(fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(*bytes_read)}; REQUIRE(buffer_as_str == "sheep_1"); - REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::close(fd)); } THEN("a filesystem can be mounted, files can be opened, read and closed again and unmounted") { - REQUIRE(kapi::filesystem::mount("/dev/ram16", "/information") == 0); + REQUIRE(kapi::filesystem::mount("/dev/ram16", "/information")); auto fd = kapi::filesystem::open("/information/monkey_house/monkey_1.txt").value(); auto buffer = std::vector<std::byte>(8); auto bytes_read = kapi::filesystem::read(fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); - std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)}; + std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(*bytes_read)}; REQUIRE(buffer_as_str == "monkey_1"); - REQUIRE(kapi::filesystem::close(fd) == 0); - REQUIRE(kapi::filesystem::umount("/information") == 0); + REQUIRE(kapi::filesystem::close(fd)); + REQUIRE(kapi::filesystem::umount("/information")); } THEN("a filesystem cannot be unmounted if files are still open and can be unmounted after files are closed") { - REQUIRE(kapi::filesystem::mount("/dev/ram16", "/information") == 0); + REQUIRE(kapi::filesystem::mount("/dev/ram16", "/information")); auto fd = kapi::filesystem::open("/information/monkey_house/monkey_1.txt").value(); - REQUIRE(kapi::filesystem::umount("/information") < 0); + REQUIRE(!kapi::filesystem::umount("/information")); - REQUIRE(kapi::filesystem::close(fd) == 0); - REQUIRE(kapi::filesystem::umount("/information") == 0); + REQUIRE(kapi::filesystem::close(fd)); + REQUIRE(kapi::filesystem::umount("/information")); } THEN("device can be opened as file and read from") @@ -116,9 +118,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(512); auto bytes_read = kapi::filesystem::read(fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); - REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::close(fd)); } THEN("device can be opened as file and written to and read from again") @@ -127,28 +129,28 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap auto buffer = std::vector<std::byte>(512, std::byte{0xAB}); auto bytes_written = kapi::filesystem::write(read_fd, buffer.data(), buffer.size()); - REQUIRE(bytes_written >= 0); + REQUIRE(bytes_written); auto write_fd = kapi::filesystem::open("/dev/ram16").value(); auto read_buffer = std::vector<std::byte>(512); auto bytes_read = kapi::filesystem::read(write_fd, read_buffer.data(), read_buffer.size()); - REQUIRE(bytes_read >= 0); + REQUIRE(bytes_read); REQUIRE(std::equal(buffer.begin(), buffer.end(), read_buffer.begin())); - REQUIRE(kapi::filesystem::close(write_fd) == 0); - REQUIRE(kapi::filesystem::close(read_fd) == 0); + REQUIRE(kapi::filesystem::close(write_fd)); + REQUIRE(kapi::filesystem::close(read_fd)); } THEN("invalid paths cannot be mounted or unmounted") { - REQUIRE(kapi::filesystem::mount("/dev/ram16", "invalid_path") < 0); + REQUIRE(!kapi::filesystem::mount("/dev/ram16", "invalid_path")); } THEN("invalid paths cannot be unmounted") { - REQUIRE(kapi::filesystem::umount("invalid_path") < 0); + REQUIRE(!kapi::filesystem::umount("invalid_path")); } THEN("non existent files cannot be opened") @@ -159,15 +161,15 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap THEN("not opened files cannot closed") { - REQUIRE(kapi::filesystem::close(999) < 0); + REQUIRE(!kapi::filesystem::close(999)); } THEN("same file cannot be closed twice") { auto fd = kapi::filesystem::open("/information/info_1.txt").value(); - REQUIRE(kapi::filesystem::close(fd) == 0); - REQUIRE(kapi::filesystem::close(fd) < 0); + REQUIRE(kapi::filesystem::close(fd)); + REQUIRE(!kapi::filesystem::close(fd)); } THEN("not opened files cannot be read from") @@ -175,7 +177,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap std::vector<std::byte> buffer(10); auto const invalid_fd = 999uz; auto bytes_read = kapi::filesystem::read(invalid_fd, buffer.data(), buffer.size()); - REQUIRE(bytes_read < 0); + REQUIRE(!bytes_read); } THEN("not opened files cannot be written to") @@ -183,7 +185,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap std::vector<std::byte> buffer(10); auto const invalid_fd = 999uz; auto bytes_written = kapi::filesystem::write(invalid_fd, buffer.data(), buffer.size()); - REQUIRE(bytes_written < 0); + REQUIRE(!bytes_written); } } } diff --git a/kernel/kernel/filesystem/open_file_table.cpp b/kernel/kernel/filesystem/open_file_table.cpp index 38bd7a43..df5717a4 100644 --- a/kernel/kernel/filesystem/open_file_table.cpp +++ b/kernel/kernel/filesystem/open_file_table.cpp @@ -5,10 +5,11 @@ #include <kapi/system.hpp> #include <kstd/memory.hpp> -#include <kstd/unikstd.h> +#include <kstd/system_error.hpp> #include <algorithm> #include <cstddef> +#include <expected> #include <optional> namespace @@ -38,11 +39,12 @@ namespace kernel::filesystem return *global_open_file_table; } - auto open_file_table::add_file(kstd::shared_ptr<open_file_descriptor> const & file_descriptor) -> kstd::ssize_t + auto open_file_table::add_file(kstd::shared_ptr<open_file_descriptor> const & file_descriptor) + -> std::expected<std::size_t, kstd::error_code> { if (!file_descriptor) { - return -1; + return std::unexpected{make_error_code(kstd::errc::invalid_argument)}; } auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); @@ -56,21 +58,21 @@ namespace kernel::filesystem return m_open_files.size() - 1; } - auto open_file_table::file(size_t fd) const -> kstd::shared_ptr<open_file_descriptor> + auto open_file_table::file(size_t fd) const -> std::expected<kstd::shared_ptr<open_file_descriptor>, kstd::error_code> { - if (fd >= m_open_files.size()) + if (fd >= m_open_files.size() || m_open_files.at(fd) == nullptr) { - return nullptr; + return std::unexpected{make_error_code(kstd::errc::invalid_argument)}; } return m_open_files.at(fd); } - auto open_file_table::remove_file(size_t fd) -> kstd::ssize_t + auto open_file_table::remove_file(size_t fd) -> std::expected<std::size_t, kstd::error_code> { - if (fd >= m_open_files.size()) + if (fd >= m_open_files.size() || m_open_files.at(fd) == nullptr) { - return -1; + return std::unexpected{make_error_code(kstd::errc::invalid_argument)}; } m_open_files.at(fd) = nullptr; diff --git a/kernel/kernel/filesystem/open_file_table.hpp b/kernel/kernel/filesystem/open_file_table.hpp index a5e6b496..efdaf578 100644 --- a/kernel/kernel/filesystem/open_file_table.hpp +++ b/kernel/kernel/filesystem/open_file_table.hpp @@ -4,10 +4,11 @@ #include <kernel/filesystem/open_file_descriptor.hpp> #include <kstd/memory.hpp> -#include <kstd/unikstd.h> +#include <kstd/system_error.hpp> #include <kstd/vector.hpp> #include <cstddef> +#include <expected> namespace kernel::filesystem { @@ -40,21 +41,21 @@ namespace kernel::filesystem @param fd The file descriptor to add. @return The file descriptor index assigned to the file, or -1 on failure. */ - auto add_file(kstd::shared_ptr<open_file_descriptor> const & fd) -> kstd::ssize_t; + auto add_file(kstd::shared_ptr<open_file_descriptor> const & fd) -> std::expected<std::size_t, kstd::error_code>; /** @brief Get a file from the open file table. @param fd The file descriptor index to retrieve. @return A pointer to the requested file descriptor, or a null pointer if not found. */ - [[nodiscard]] auto file(size_t fd) const -> kstd::shared_ptr<open_file_descriptor>; + [[nodiscard]] auto file(size_t fd) const -> std::expected<kstd::shared_ptr<open_file_descriptor>, kstd::error_code>; /** @brief Remove a file from the open file table. @param fd The file descriptor index to remove. @return 0 on success, or -1 on failure. */ - auto remove_file(size_t fd) -> kstd::ssize_t; + auto remove_file(size_t fd) -> std::expected<std::size_t, kstd::error_code>; private: open_file_table() = default; diff --git a/kernel/kernel/filesystem/open_file_table.tests.cpp b/kernel/kernel/filesystem/open_file_table.tests.cpp index ffb4a650..78afaa6d 100644 --- a/kernel/kernel/filesystem/open_file_table.tests.cpp +++ b/kernel/kernel/filesystem/open_file_table.tests.cpp @@ -6,6 +6,7 @@ #include <kstd/memory.hpp> #include <kstd/print.hpp> +#include <kstd/system_error.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -36,7 +37,7 @@ SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") THEN("the file descriptor can be retrieved using the returned file descriptor") { - auto retrieved_descriptor = table.file(fd_1); + auto retrieved_descriptor = table.file(*fd_1); REQUIRE(retrieved_descriptor == file_descriptor_1); } } @@ -46,16 +47,16 @@ SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") { auto & table = kernel::filesystem::open_file_table::get(); - THEN("adding a null file descriptor returns an error code") + THEN("adding a null file descriptor returns an error") { auto fd = table.add_file(nullptr); - REQUIRE(fd == -1); + REQUIRE(fd.error() == make_error_condition(kstd::errc::invalid_argument)); } - THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") + THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns an error") { auto retrieved_descriptor = table.file(1000); - REQUIRE(retrieved_descriptor == nullptr); + REQUIRE(retrieved_descriptor.error() == make_error_condition(kstd::errc::invalid_argument)); } } } @@ -72,23 +73,23 @@ SCENARIO("Open file table remove file", "[filesystem][open_file_table]") WHEN("removing the file descriptor using the file descriptor") { - table.remove_file(fd); + CHECK(table.remove_file(*fd)); THEN("the file descriptor can no longer be retrieved using the file descriptor") { - auto retrieved_descriptor = table.file(fd); - REQUIRE(retrieved_descriptor == nullptr); + auto retrieved_descriptor = table.file(*fd); + REQUIRE(retrieved_descriptor.error() == make_error_condition(kstd::errc::invalid_argument)); } } WHEN("removing a file descriptor the other file descriptor keep the same index") { auto fd2 = table.add_file(file_descriptor); - table.remove_file(fd); + CHECK(table.remove_file(*fd)); THEN("the second file descriptor can still be retrieved using its file descriptor") { - auto retrieved_descriptor = table.file(fd2); + auto retrieved_descriptor = table.file(*fd2); REQUIRE(retrieved_descriptor == file_descriptor); } } diff --git a/kernel/kernel/filesystem/vfs.cpp b/kernel/kernel/filesystem/vfs.cpp index a5c1593d..55c83ca9 100644 --- a/kernel/kernel/filesystem/vfs.cpp +++ b/kernel/kernel/filesystem/vfs.cpp @@ -65,7 +65,7 @@ namespace kernel::filesystem { if (auto root_dentry = resolve_path("/")) { - do_mount_internal(root_dentry, root_mount, boot_root_fs, boot_device_mount_context); + do_mount_internal(*root_dentry, root_mount, boot_root_fs, boot_device_mount_context); graft_persistent_device_fs(device_fs); } } @@ -95,21 +95,21 @@ namespace kernel::filesystem return dentry; } - auto vfs::close(std::string_view path) -> operation_result + auto vfs::close(std::string_view path) -> std::expected<void, kstd::error_code> { if (auto mount = find_mount(path)) { - mount->decrement_ref_count(); - return operation_result::success; + mount.value()->decrement_ref_count(); + return {}; } - return operation_result::invalid_path; + return std::unexpected{make_error_code(vfs_errc::invalid_path)}; } - auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result + auto vfs::do_mount(std::string_view source, std::string_view target) -> std::expected<void, kstd::error_code> { if (!path::is_valid_path(source) || !path::is_valid_path(target)) { - return operation_result::invalid_path; + return std::unexpected{make_error_code(vfs_errc::invalid_path)}; } auto [mount_point_dentry, mount_context] = resolve_path_internal(target).value_or(std::pair{nullptr, nullptr}); @@ -121,33 +121,33 @@ namespace kernel::filesystem if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { do_mount_internal(mount_point_dentry, mount_context, fs, source_mount_context); - return operation_result::success; + return {}; } - return operation_result::invalid_filesystem; + return std::unexpected{make_error_code(vfs_errc::invalid_filesystem)}; } - return operation_result::non_existent_path; + return std::unexpected{make_error_code(vfs_errc::non_existent_path)}; } - return operation_result::mount_point_not_found; + return std::unexpected{make_error_code(vfs_errc::mount_point_not_found)}; } - auto vfs::unmount(std::string_view path) -> operation_result + auto vfs::unmount(std::string_view path) -> std::expected<void, kstd::error_code> { if (!path::is_valid_path(path)) { - return operation_result::invalid_path; + return std::unexpected{make_error_code(vfs_errc::invalid_path)}; } auto remove_result = m_mount_table.remove_mount(path); if (remove_result == mount_table::operation_result::removed) { - return operation_result::success; + return {}; } else if (remove_result == mount_table::operation_result::mount_not_found) { - return operation_result::mount_point_not_found; + return std::unexpected{make_error_code(vfs_errc::mount_point_not_found)}; } - return operation_result::unmount_failed; + return std::unexpected{make_error_code(vfs_errc::unmount_failed)}; } auto vfs::do_mount_internal(kstd::shared_ptr<dentry> const & mount_point_dentry, @@ -284,14 +284,14 @@ namespace kernel::filesystem return std::pair{current_dentry, current_mount}; } - auto vfs::resolve_path(std::string_view path) const -> kstd::shared_ptr<dentry> + auto vfs::resolve_path(std::string_view path) const -> std::expected<kstd::shared_ptr<dentry>, kstd::error_code> { - return resolve_path_internal(path).transform([](auto result) { return result.first; }).value_or(nullptr); + return resolve_path_internal(path).transform([](auto result) { return result.first; }); } - auto vfs::find_mount(std::string_view path) const -> kstd::shared_ptr<mount> + auto vfs::find_mount(std::string_view path) const -> std::expected<kstd::shared_ptr<mount>, kstd::error_code> { - return resolve_path_internal(path).transform([](auto result) { return result.second; }).value_or(nullptr); + return resolve_path_internal(path).transform([](auto result) { return result.second; }); } } // namespace kernel::filesystem diff --git a/kernel/kernel/filesystem/vfs.hpp b/kernel/kernel/filesystem/vfs.hpp index ef26aa84..3e86eae5 100644 --- a/kernel/kernel/filesystem/vfs.hpp +++ b/kernel/kernel/filesystem/vfs.hpp @@ -19,24 +19,11 @@ namespace kernel::filesystem /** @brief The virtual filesystem (VFS) is responsible for managing mounted filesystems and providing a unified interface for file operations across different filesystem types. The VFS maintains a mount table to keep track of mounted - filesystems and their associated mount points. It provides methods for opening files by path, which involvesresolving + filesystems and their associated mount points. It provides methods for opening files by path, which involves resolving the path to the appropriate mounted filesystem and delegating the file operation to that filesystem's implementation. */ struct vfs { - /** - @brief Results for VFS operations. - */ - enum class operation_result : int - { - success = 0, - invalid_path = -1, - non_existent_path = -2, - mount_point_not_found = -3, - unmount_failed = -4, - invalid_filesystem = -5 - }; - vfs(); /** @@ -67,24 +54,24 @@ namespace kernel::filesystem /** @brief Close a file by its associated @p path. @param path The path to the file to close. - @return The result of the close operation. + @return Nothing on success or an error code on failure. */ - auto close(std::string_view path) -> operation_result; + auto close(std::string_view path) -> std::expected<void, kstd::error_code>; /** @brief Mount a @p source path to a specific @p target path. @param source The source of the filesystem to mount. @param target The path where the filesystem should be mounted. - @return The result of the mount operation. + @return Nothing on success or an error code on failure. */ - auto do_mount(std::string_view source, std::string_view target) -> operation_result; + auto do_mount(std::string_view source, std::string_view target) -> std::expected<void, kstd::error_code>; /** @brief Unmount the filesystem mounted at the specified @p path. @param path The path where the filesystem is mounted. - @return The result of the unmount operation. + @return Nothing on success or an error code on failure. */ - auto unmount(std::string_view path) -> operation_result; + auto unmount(std::string_view path) -> std::expected<void, kstd::error_code>; private: /** @@ -99,8 +86,12 @@ namespace kernel::filesystem */ [[nodiscard]] auto resolve_path_internal(std::string_view path) const -> std::expected<std::pair<kstd::shared_ptr<dentry>, kstd::shared_ptr<mount>>, kstd::error_code>; - [[nodiscard]] auto resolve_path(std::string_view path) const -> kstd::shared_ptr<dentry>; - [[nodiscard]] auto find_mount(std::string_view path) const -> kstd::shared_ptr<mount>; + + [[nodiscard]] auto resolve_path(std::string_view path) const + -> std::expected<kstd::shared_ptr<dentry>, kstd::error_code>; + + [[nodiscard]] auto find_mount(std::string_view path) const + -> std::expected<kstd::shared_ptr<mount>, kstd::error_code>; auto do_mount_internal(kstd::shared_ptr<dentry> const & mount_point_dentry, kstd::shared_ptr<mount> const & parent_mount, kstd::shared_ptr<filesystem> const & fs, diff --git a/kernel/kernel/filesystem/vfs.tests.cpp b/kernel/kernel/filesystem/vfs.tests.cpp index c5130ef4..59589633 100644 --- a/kernel/kernel/filesystem/vfs.tests.cpp +++ b/kernel/kernel/filesystem/vfs.tests.cpp @@ -1,9 +1,11 @@ #include <kernel/filesystem/vfs.hpp> +#include <kernel/filesystem/error.hpp> #include <kernel/filesystem/open_file_descriptor.hpp> #include <kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp> #include <kstd/memory.hpp> +#include <kstd/system_error.hpp> #include <kstd/vector.hpp> #include <catch2/catch_test_macros.hpp> @@ -73,7 +75,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto & vfs = kernel::filesystem::vfs::get(); auto image_1 = vfs.open("/dev/image_1.txt"); - REQUIRE(image_1 == nullptr); + REQUIRE(image_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto dev = vfs.open("/dev/ram0"); REQUIRE(dev != nullptr); @@ -102,16 +104,15 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("second image can be mounted, data retrieved and unmounted again") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1); - REQUIRE(vfs.close(mounted_monkey_1.value()->absolute_path()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_monkey_1.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information")); auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); - REQUIRE(unmounted_monkey_1 == nullptr); + REQUIRE(unmounted_monkey_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); @@ -119,9 +120,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("third image can be mounted in a mounted file system, unmount only if no child mount exists") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/dev/ram32", "/information/monkey_house/infrastructure") == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); + REQUIRE(vfs.do_mount("/dev/ram32", "/information/monkey_house/infrastructure")); auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); auto mounted_fish1 = vfs.open("/information/monkey_house/infrastructure/enclosures/aquarium/tank_1/fish_1.txt"); @@ -129,34 +129,31 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(mounted_monkey_1); REQUIRE(mounted_fish1); - REQUIRE(vfs.close(mounted_monkey_1.value()->absolute_path()) == - kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(mounted_fish1.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_monkey_1.value()->absolute_path())); + REQUIRE(vfs.close(mounted_fish1.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); - REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") == - kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(!vfs.unmount("/information")); + REQUIRE(vfs.unmount("/information/monkey_house/infrastructure")); + REQUIRE(vfs.unmount("/information")); } THEN("image can be mounted, unmount only if no files are open") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); + REQUIRE(!vfs.unmount("/information")); - REQUIRE(vfs.close(mounted_monkey_1.value()->absolute_path()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_monkey_1.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information")); } THEN("file with invalid path or not opened file cannot be closed") { - REQUIRE(vfs.close("invalid_path") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(!vfs.close("invalid_path")); REQUIRE_THROWS_AS(vfs.close("/information/info_1.txt"), std::runtime_error); } @@ -165,27 +162,26 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1); - REQUIRE(vfs.close(info_1.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1.value()->absolute_path())); REQUIRE_THROWS_AS(vfs.close(info_1.value()->absolute_path()), std::runtime_error); } THEN("images can be stacked mounted and correct file system is unmounted again") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/dev/ram32", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); + REQUIRE(vfs.do_mount("/dev/ram32", "/information")); auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets); - REQUIRE(vfs.close(mounted_tickets.value()->absolute_path()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_tickets.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information")); mounted_tickets = vfs.open("/information/entrance/tickets.txt"); - REQUIRE(mounted_tickets == nullptr); + REQUIRE(mounted_tickets.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto mounted_monkey = vfs.open("/information/monkey_house/monkey_1.txt"); - REQUIRE(mounted_monkey != nullptr); + REQUIRE(mounted_monkey); } THEN("image can be mounted on / file opened and unmounted again") @@ -193,17 +189,17 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.do_mount("/dev/ram16", "/") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/")); info_1 = vfs.open("/information/info_1.txt"); - REQUIRE(info_1 == nullptr); + REQUIRE(info_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); - REQUIRE(vfs.close(water.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(water.value()->absolute_path())); - REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/")); info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); @@ -214,22 +210,23 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.do_mount("/dev/ram16", "/") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/")); info_1 = vfs.open("/information/info_1.txt"); - REQUIRE(info_1 == nullptr); + REQUIRE(info_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); - REQUIRE(vfs.close(water.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(water.value()->absolute_path())); auto dev_ram_16 = vfs.open("/dev/ram16"); - REQUIRE(dev_ram_16 == nullptr); + REQUIRE(dev_ram_16.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); - REQUIRE(vfs.do_mount("/dev/ram32", "/") == kernel::filesystem::vfs::operation_result::non_existent_path); + REQUIRE(vfs.do_mount("/dev/ram32", "/").error() == + make_error_code(kernel::filesystem::vfs_errc::non_existent_path)); - REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/")); auto dev_ram_32 = vfs.open("/dev/ram32"); REQUIRE(dev_ram_32 != nullptr); @@ -240,58 +237,59 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); - REQUIRE(vfs.close(info_1.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1.value()->absolute_path())); - REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/dev")); + REQUIRE(vfs.unmount("/")); info_1 = vfs.open("/information/info_1.txt"); - REQUIRE(info_1 == nullptr); + REQUIRE(info_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); - REQUIRE(vfs.do_mount("/dev/ram0", "/") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram0", "/")); info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); auto dev_ram_0 = vfs.open("/dev/ram0"); - REQUIRE(dev_ram_0 == nullptr); + REQUIRE(dev_ram_0.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); } THEN("mount with null file system fails") { - REQUIRE(vfs.do_mount("/closed.txt", "/information") == - kernel::filesystem::vfs::operation_result::invalid_filesystem); + REQUIRE(vfs.do_mount("/closed.txt", "/information").error() == + make_error_code(kernel::filesystem::vfs_errc::invalid_filesystem)); } THEN("mount with invalid path fails") { - REQUIRE(vfs.do_mount("/dev/ram16", "") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.do_mount("/dev/ram16", "information") == - kernel::filesystem::vfs::operation_result::mount_point_not_found); + REQUIRE(vfs.do_mount("/dev/ram16", "").error() == make_error_code(kernel::filesystem::vfs_errc::invalid_path)); + REQUIRE(vfs.do_mount("/dev/ram16", "information").error() == + make_error_code(kernel::filesystem::vfs_errc::mount_point_not_found)); } THEN("mount with non-existent source path fails") { - REQUIRE(vfs.do_mount("/dev/nonexistent", "/information") == - kernel::filesystem::vfs::operation_result::non_existent_path); + REQUIRE(vfs.do_mount("/dev/nonexistent", "/information").error() == + make_error_code(kernel::filesystem::vfs_errc::non_existent_path)); } THEN("mount with non-existent mount point fails") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information/nonexistent") == - kernel::filesystem::vfs::operation_result::mount_point_not_found); + REQUIRE(vfs.do_mount("/dev/ram16", "/information/nonexistent").error() == + make_error_code(kernel::filesystem::vfs_errc::mount_point_not_found)); } THEN("unmount with invalid path fails") { - REQUIRE(vfs.unmount("") == kernel::filesystem::vfs::operation_result::invalid_path); - REQUIRE(vfs.unmount("information") == kernel::filesystem::vfs::operation_result::mount_point_not_found); + REQUIRE(vfs.unmount("").error() == make_error_code(kernel::filesystem::vfs_errc::invalid_path)); + REQUIRE(vfs.unmount("information").error() == + make_error_code(kernel::filesystem::vfs_errc::mount_point_not_found)); } THEN("unmounting non-existent mount point returns expected error code") { - REQUIRE(vfs.unmount("/information/nonexistent") == - kernel::filesystem::vfs::operation_result::mount_point_not_found); + REQUIRE(vfs.unmount("/information/nonexistent").error() == + make_error_code(kernel::filesystem::vfs_errc::mount_point_not_found)); } THEN("a file can be access if . in the path") @@ -311,7 +309,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("a file can be accessed over multiple mounts if path contains .. or . ") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); auto img = vfs.open("/information/monkey_house/caretaker/../../../../../../archiv/2024.img"); REQUIRE(img != nullptr); @@ -325,9 +323,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("a file can be accessed over multiple mounts (device and file) if path contains .. ") { - REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/archiv/2024.img", "/information/monkey_house/infrastructure") == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information/monkey_house/infrastructure")); auto pig_1 = vfs.open("/information/monkey_house/infrastructure/stable/pig_1.txt"); REQUIRE(pig_1 != nullptr); @@ -349,10 +346,10 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("the file-filesystem in the image can be mounted, files can be read and unmounted again") { auto & vfs = kernel::filesystem::vfs::get(); - REQUIRE(vfs.do_mount("/archiv/2024.img", "/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information")); auto info_1 = vfs.open("/information/info_1.txt"); - REQUIRE(info_1 == nullptr); + REQUIRE(info_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto dentry = vfs.open("/information/sheep_1.txt"); REQUIRE(dentry != nullptr); @@ -363,20 +360,19 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); - REQUIRE(vfs.close(dentry.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(dentry.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information")); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); - REQUIRE(unmounted_sheep_1 == nullptr); + REQUIRE(unmounted_sheep_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); } THEN("the file-filesystem in the image can be mounted and in this filesystem can another file-filesystem be " "mounted, files can be read and unmounted again") { auto & vfs = kernel::filesystem::vfs::get(); - REQUIRE(vfs.do_mount("/archiv/2024.img", "/information") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/archiv/2025.img", "/information/stable") == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information")); + REQUIRE(vfs.do_mount("/archiv/2025.img", "/information/stable")); auto sheep_1 = vfs.open("/information/sheep_1.txt"); auto goat_1 = vfs.open("/information/stable/petting_zoo/goat_1.txt"); @@ -396,24 +392,23 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS buffer_as_str = std::string_view{reinterpret_cast<char *>(goat_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "goat_1"); - REQUIRE(vfs.close(sheep_1.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.close(goat_1.value()->absolute_path()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(sheep_1.value()->absolute_path())); + REQUIRE(vfs.close(goat_1.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); + REQUIRE(vfs.unmount("/information").error() == make_error_code(kernel::filesystem::vfs_errc::unmount_failed)); - REQUIRE(vfs.unmount("/information/stable") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information/stable")); auto unmounted_goat_1 = vfs.open("/information/stable/petting_zoo/goat_1.txt"); - REQUIRE(unmounted_goat_1 == nullptr); + REQUIRE(unmounted_goat_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(still_mounted_sheep_1 != nullptr); - REQUIRE(vfs.close(still_mounted_sheep_1.value()->absolute_path()) == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(still_mounted_sheep_1.value()->absolute_path())); - REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information")); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); - REQUIRE(unmounted_sheep_1 == nullptr); + REQUIRE(unmounted_sheep_1.error() == make_error_condition(kstd::errc::no_such_file_or_directory)); } } @@ -428,23 +423,21 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS THEN("cannot unmount a filesystem if files are mounted") { - REQUIRE(vfs.do_mount("/dev/ram16", "/entrance") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/enclosures") == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/entrance")); + REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/enclosures")); - REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::unmount_failed); - REQUIRE(vfs.unmount("/enclosures") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/entrance").error() == make_error_code(kernel::filesystem::vfs_errc::unmount_failed)); + REQUIRE(vfs.unmount("/enclosures")); + REQUIRE(vfs.unmount("/entrance")); } THEN("can mount filesystem onto the directory that contains it") { - REQUIRE(vfs.do_mount("/dev/ram16", "/entrance") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/entrance") == - kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.do_mount("/dev/ram16", "/entrance")); + REQUIRE(vfs.do_mount("/entrance/archiv/2024.img", "/entrance")); - REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); - REQUIRE(vfs.unmount("/entrance") == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/entrance")); + REQUIRE(vfs.unmount("/entrance")); } } @@ -492,21 +485,21 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS { auto & vfs = kernel::filesystem::vfs::get(); auto invalid_symlink = vfs.open("/symlinks/invalid_absolute"); - REQUIRE(invalid_symlink == nullptr); + REQUIRE(invalid_symlink.error() == make_error_code(kernel::filesystem::vfs_errc::non_existent_path)); } THEN("symbolic link containing an invalid relative path is handled correctly") { auto & vfs = kernel::filesystem::vfs::get(); auto invalid_symlink = vfs.open("/symlinks/invalid_relative"); - REQUIRE(invalid_symlink == nullptr); + REQUIRE(invalid_symlink.error() == make_error_code(kernel::filesystem::vfs_errc::non_existent_path)); } THEN("circular symbolic links are detected and handled correctly") { auto & vfs = kernel::filesystem::vfs::get(); auto circular_symlink = vfs.open("/symlinks/symloop_a"); - REQUIRE(circular_symlink == nullptr); + REQUIRE(circular_symlink.error() == make_error_code(kstd::errc::too_many_symbolic_link_levels)); } } @@ -516,7 +509,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1"}, {image_path_1})); auto & vfs = kernel::filesystem::vfs::get(); - vfs.do_mount("/archiv/2024.img", "/information"); + REQUIRE(vfs.do_mount("/archiv/2024.img", "/information")); THEN("file can be opened through symbolic link pointing to the parent filesystem") { @@ -533,7 +526,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS setup_modules_from_img_and_init_vfs({"test_img_module_1", "test_img_module_2"}, {image_path_1, image_path_2})); auto & vfs = kernel::filesystem::vfs::get(); - vfs.do_mount("/dev/ram16", "/information"); + REQUIRE(vfs.do_mount("/dev/ram16", "/information")); THEN("file can be opened through symbolic link pointing to the parent filesystem and back into the mounted " "filesystem again") diff --git a/kernel/kernel/main.cpp b/kernel/kernel/main.cpp index 76c05204..749040ce 100644 --- a/kernel/kernel/main.cpp +++ b/kernel/kernel/main.cpp @@ -15,6 +15,7 @@ #include <kstd/format.hpp> #include <kstd/print.hpp> +#include <kstd/system_error.hpp> #include <kstd/units.hpp> #include <kstd/vector.hpp> @@ -39,22 +40,22 @@ auto run_demo() -> void // 2) read from the file kstd::vector<std::byte> buffer_1{10}; - auto bytes_read = kapi::filesystem::read(fd_1.value(), buffer_1.data(), buffer_1.size()); - auto buffer_as_str = std::string_view{reinterpret_cast<char *>(buffer_1.data()), static_cast<size_t>(bytes_read)}; + auto bytes_read = *kapi::filesystem::read(fd_1.value(), buffer_1.data(), buffer_1.size()); + auto buffer_as_str = std::string_view{reinterpret_cast<char *>(buffer_1.data()), bytes_read}; kstd::println("--> read {} bytes from /entrance/tickets.txt: {}", bytes_read, buffer_as_str); kstd::println(""); // 3) show that /entrance/information/info_1.txt is not accessible before mounting kstd::println("attempting to open /entrance/information/info_1.txt before mounting"); auto fd_before_mount = kapi::filesystem::open("/entrance/information/info_1.txt"); - if (fd_before_mount == -1) + if (!fd_before_mount && fd_before_mount.error() == make_error_condition(kstd::errc::no_such_file_or_directory)) { kstd::println("--> as expected the file could not be opened before mounting"); } // 4) mount a new filesystem on top of /entrance kstd::println("mount /dev/ram16 to /entrance"); - if (kapi::filesystem::mount("/dev/ram16", "/entrance") == 0) + if (kapi::filesystem::mount("/dev/ram16", "/entrance")) { kstd::println("--> successfully mounted /dev/ram16 to /entrance"); } @@ -78,7 +79,7 @@ auto run_demo() -> void // 6) read from the new file kstd::vector<std::byte> buffer_2{10}; - bytes_read = kapi::filesystem::read(fd_2.value(), buffer_2.data(), buffer_2.size()); + bytes_read = *kapi::filesystem::read(fd_2.value(), buffer_2.data(), buffer_2.size()); buffer_as_str = std::string_view{reinterpret_cast<char *>(buffer_2.data()), static_cast<size_t>(bytes_read)}; kstd::println("--> read {} bytes from /entrance/information/info_1.txt: {} ", bytes_read, buffer_as_str); @@ -96,13 +97,13 @@ auto run_demo() -> void // 8) read from the device file kstd::vector<std::byte> buffer_3{2}; - bytes_read = kapi::filesystem::read(fd_3.value(), buffer_3.data(), buffer_3.size()); + bytes_read = *kapi::filesystem::read(fd_3.value(), buffer_3.data(), buffer_3.size()); kstd::println("--> read {} bytes from /dev/ram32: {::#04x} ", bytes_read, buffer_3); // 9) write to the device file auto const default_buffer_value = std::byte{0xAA}; kstd::vector<std::byte> write_buffer{default_buffer_value, default_buffer_value}; - auto bytes_written = kapi::filesystem::write(fd_3.value(), write_buffer.data(), write_buffer.size()); + auto bytes_written = *kapi::filesystem::write(fd_3.value(), write_buffer.data(), write_buffer.size()); kstd::println("--> written {} bytes to /dev/ram32: {::#04x}", bytes_written, write_buffer); // 10) do memory dump to show that the write to the device file had an effect |
