From 97afdf08922956627073d929bcb2529306333313 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 25 Apr 2026 23:29:27 +0200 Subject: add demo code --- kernel/src/main.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'kernel') diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 60b6e6e..9f4ec1e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,64 @@ auto run_test_code() -> void kstd::println("---------------------------------"); } +auto run_demo() -> void +{ + // 1) open a file + auto fd_1 = kapi::filesystem::open("/entrance/tickets.txt"); + if (fd_1 == -1) + { + kstd::os::panic("demo failed"); + } + + // 2) read from the file + kstd::vector buffer_1{10}; + auto bytes_read = kapi::filesystem::read(fd_1, buffer_1.data(), buffer_1.size()); + auto buffer_as_str = std::string_view{reinterpret_cast(buffer_1.data()), static_cast(bytes_read)}; + kstd::println("Read {} bytes from /entrance/tickets.txt: {}", bytes_read, buffer_as_str); + + // 3) show that /entrance/information/info_1.txt is not accessible before mounting + auto fd_before_mount = kapi::filesystem::open("/entrance/information/info_1.txt"); + if (fd_before_mount == -1) + { + kstd::println("/entrance/information/info_1.txt is not accessible before mounting, as expected."); + } + + // 4) mount a new filesystem on top of /entrance + kapi::filesystem::mount("/dev/ram16", "/entrance"); + + // 5) open a file from the new filesystem + auto fd_2 = kapi::filesystem::open("/entrance/information/info_1.txt"); + if (fd_2 == -1) + { + kstd::os::panic("demo failed"); + } + + // 6) read from the new file + kstd::vector buffer_2{10}; + bytes_read = kapi::filesystem::read(fd_2, buffer_2.data(), buffer_2.size()); + buffer_as_str = std::string_view{reinterpret_cast(buffer_2.data()), static_cast(bytes_read)}; + kstd::println("Read {} bytes from /entrance/information/info_1.txt: {}", bytes_read, buffer_as_str); + + // 7) open device as file + auto fd_3 = kapi::filesystem::open("/dev/ram48"); + if (fd_3 == -1) + { + kstd::os::panic("demo failed"); + } + + // 8) read from the device file + kstd::vector buffer_3{2}; + bytes_read = kapi::filesystem::read(fd_3, buffer_3.data(), buffer_3.size()); + kstd::println("Read {} bytes from /dev/ram48: {::#04x}", bytes_read, buffer_3); + + // 9) write to the device file + kstd::vector write_buffer{std::byte{0xAA}, std::byte{0xAA}}; + auto bytes_written = kapi::filesystem::write(fd_3, write_buffer.data(), write_buffer.size()); + kstd::println("Written {} bytes to /dev/ram48: {::#04x}", bytes_written, write_buffer); + + // 10) do memory dump to show that the write to the device file had an effect +} + auto main() -> int { kapi::cio::init(); @@ -221,6 +280,10 @@ auto main() -> int kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); + // TODO BA-FS26 remove demo and test code again? + // run_demo(); + + // TODO BA-FS26 remove demo and test code again? run_test_code(); kstd::println("[TEST] All tests completed."); -- cgit v1.2.3 From 3b82b63aab8dcede2e099b8cbf12e7f3f0407896 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 25 Apr 2026 23:29:54 +0200 Subject: remove unused include --- kernel/include/kernel/filesystem/vfs.hpp | 1 - 1 file changed, 1 deletion(-) (limited to 'kernel') diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index 5b5c868..881f458 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include -- cgit v1.2.3 From c002a6fe53375d8757d43c48c59ac7f327f412b5 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 25 Apr 2026 23:31:26 +0200 Subject: add documentation, refactoring --- kernel/kapi/filesystem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'kernel') diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index c8d4c6d..741875a 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -42,14 +42,14 @@ namespace kapi::filesystem return -1; } - auto close(int fd) -> int + auto close(int file_descriptor) -> int { - return kernel::filesystem::file_descriptor_table::get().remove_file(fd); + return kernel::filesystem::file_descriptor_table::get().remove_file(file_descriptor); } - auto read(int fd, void * buffer, size_t size) -> ssize_t + auto read(int file_descriptor, void * buffer, size_t size) -> ssize_t { - if (auto open_file_description = kernel::filesystem::file_descriptor_table::get().get_file(fd)) + if (auto open_file_description = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) { return open_file_description->read(buffer, size); } @@ -57,9 +57,9 @@ namespace kapi::filesystem return -1; } - auto write(int fd, void const * buffer, size_t size) -> ssize_t + auto write(int file_descriptor, void const * buffer, size_t size) -> ssize_t { - if (auto open_file_description = kernel::filesystem::file_descriptor_table::get().get_file(fd)) + if (auto open_file_description = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) { return open_file_description->write(buffer, size); } -- cgit v1.2.3 From 4e2624b63236fa309c9ecf53a694b6ac9babf4e6 Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 26 Apr 2026 10:11:24 +0200 Subject: rename open_file_description to open_file_descriptor --- kernel/CMakeLists.txt | 4 +- .../kernel/filesystem/file_descriptor_table.hpp | 14 +-- .../kernel/filesystem/open_file_description.hpp | 62 ----------- .../kernel/filesystem/open_file_descriptor.hpp | 62 +++++++++++ kernel/kapi/filesystem.cpp | 14 +-- kernel/src/filesystem/file_descriptor_table.cpp | 12 +-- .../src/filesystem/file_descriptor_table.tests.cpp | 62 +++++------ kernel/src/filesystem/open_file_description.cpp | 41 -------- .../src/filesystem/open_file_description.tests.cpp | 115 --------------------- kernel/src/filesystem/open_file_descriptor.cpp | 40 +++++++ .../src/filesystem/open_file_descriptor.tests.cpp | 114 ++++++++++++++++++++ kernel/src/filesystem/vfs.tests.cpp | 8 +- kernel/src/main.cpp | 16 +-- 13 files changed, 281 insertions(+), 283 deletions(-) delete mode 100644 kernel/include/kernel/filesystem/open_file_description.hpp create mode 100644 kernel/include/kernel/filesystem/open_file_descriptor.hpp delete mode 100644 kernel/src/filesystem/open_file_description.cpp delete mode 100644 kernel/src/filesystem/open_file_description.tests.cpp create mode 100644 kernel/src/filesystem/open_file_descriptor.cpp create mode 100644 kernel/src/filesystem/open_file_descriptor.tests.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index d4484cd..cddec97 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -52,7 +52,7 @@ target_sources("kernel_lib" PRIVATE "src/filesystem/inode.cpp" "src/filesystem/mount_table.cpp" "src/filesystem/mount.cpp" - "src/filesystem/open_file_description.cpp" + "src/filesystem/open_file_descriptor.cpp" "src/filesystem/vfs.cpp" # DevFS Filesystem @@ -195,7 +195,7 @@ if(BUILD_TESTING) "src/filesystem/file_descriptor_table.tests.cpp" "src/filesystem/mount_table.tests.cpp" "src/filesystem/mount.tests.cpp" - "src/filesystem/open_file_description.tests.cpp" + "src/filesystem/open_file_descriptor.tests.cpp" "src/filesystem/vfs.tests.cpp" # Storage Subsystem Tests diff --git a/kernel/include/kernel/filesystem/file_descriptor_table.hpp b/kernel/include/kernel/filesystem/file_descriptor_table.hpp index 293dc36..b0e699b 100644 --- a/kernel/include/kernel/filesystem/file_descriptor_table.hpp +++ b/kernel/include/kernel/filesystem/file_descriptor_table.hpp @@ -1,7 +1,7 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_FILE_DESCRIPTOR_TABLE_HPP #define TEACH_OS_KERNEL_FILESYSTEM_FILE_DESCRIPTOR_TABLE_HPP -#include +#include #include #include @@ -10,7 +10,7 @@ namespace kernel::filesystem { /** @brief A table for managing file descriptors in the filesystem. This class provides methods for adding, retrieving, - and removing open file descriptions. + and removing open file descriptors. */ struct file_descriptor_table { @@ -35,17 +35,17 @@ namespace kernel::filesystem /** @brief Add a file to the descriptor table. - @param f The file description to add. + @param f The file descriptor to add. @return The file descriptor index assigned to the file, or -1 on failure. */ - auto add_file(kstd::shared_ptr const & f) -> int; + auto add_file(kstd::shared_ptr const & f) -> int; /** @brief Get a file from the descriptor table. @param fd The file descriptor index to retrieve. - @return A pointer to the requested file description, or a null pointer if not found. + @return A pointer to the requested file descriptor, or a null pointer if not found. */ - [[nodiscard]] auto get_file(int fd) const -> kstd::shared_ptr; + [[nodiscard]] auto get_file(int fd) const -> kstd::shared_ptr; /** @brief Remove a file from the descriptor table. @@ -57,7 +57,7 @@ namespace kernel::filesystem private: file_descriptor_table() = default; - kstd::vector> m_open_files{}; + kstd::vector> m_open_files{}; }; } // namespace kernel::filesystem diff --git a/kernel/include/kernel/filesystem/open_file_description.hpp b/kernel/include/kernel/filesystem/open_file_description.hpp deleted file mode 100644 index fad41e4..0000000 --- a/kernel/include/kernel/filesystem/open_file_description.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTION_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTION_HPP - -#include - -#include - -#include - -namespace kernel::filesystem -{ - /** - @brief Represents an open file description in the filesystem. This class encapsulates the state of an open file, - including a reference to the associated inode and the current file offset. - */ - struct open_file_description - { - /** - @brief Constructs an open file description for the given @p inode. - @param inode The inode to associate with the open file description. - */ - explicit open_file_description(kstd::shared_ptr const & inode); - - /** - @brief Destructor for the open file description. - */ - ~open_file_description() = default; - - /** - @brief Reads data from the open file description into a @p buffer, starting at the current file offset and for a - given - @p size. The file offset is advanced by the number of bytes read. - @param buffer The buffer to read data into. - @param size The number of bytes to read. - @return The number of bytes read. - */ - auto read(void * buffer, size_t size) -> size_t; - - /** - @brief Writes data to the open file description from a @p buffer, starting at the current file offset and for a - given - @p size. The file offset is advanced by the number of bytes written. - @param buffer The buffer to write data from. - @param size The number of bytes to write. - @return The number of bytes written. - */ - auto write(void const * buffer, size_t size) -> size_t; - - /** - @brief Returns the current file offset for this open file description. - @return The current file offset in bytes. - */ - [[nodiscard]] auto offset() const -> size_t; - - private: - kstd::shared_ptr m_inode; - size_t m_offset; - }; - -} // namespace kernel::filesystem - -#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/open_file_descriptor.hpp b/kernel/include/kernel/filesystem/open_file_descriptor.hpp new file mode 100644 index 0000000..036dcf0 --- /dev/null +++ b/kernel/include/kernel/filesystem/open_file_descriptor.hpp @@ -0,0 +1,62 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTOR_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTOR_HPP + +#include + +#include + +#include + +namespace kernel::filesystem +{ + /** + @brief Represents an open file descriptor in the filesystem. This class encapsulates the state of an open file, + including a reference to the associated inode and the current file offset. + */ + struct open_file_descriptor + { + /** + @brief Constructs an open file descriptor for the given @p inode. + @param inode The inode to associate with the open file descriptor. + */ + explicit open_file_descriptor(kstd::shared_ptr const & inode); + + /** + @brief Destructor for the open file descriptor. + */ + ~open_file_descriptor() = default; + + /** + @brief Reads data from the open file descriptor into a @p buffer, starting at the current file offset and for a + given + @p size. The file offset is advanced by the number of bytes read. + @param buffer The buffer to read data into. + @param size The number of bytes to read. + @return The number of bytes read. + */ + auto read(void * buffer, size_t size) -> size_t; + + /** + @brief Writes data to the open file descriptor from a @p buffer, starting at the current file offset and for a + given + @p size. The file offset is advanced by the number of bytes written. + @param buffer The buffer to write data from. + @param size The number of bytes to write. + @return The number of bytes written. + */ + auto write(void const * buffer, size_t size) -> size_t; + + /** + @brief Returns the current file offset for this open file descriptor. + @return The current file offset in bytes. + */ + [[nodiscard]] auto offset() const -> size_t; + + private: + kstd::shared_ptr m_inode; + size_t m_offset; + }; + +} // namespace kernel::filesystem + +#endif \ No newline at end of file diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index 741875a..8481f20 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include @@ -35,8 +35,8 @@ namespace kapi::filesystem { if (auto dentry = kernel::filesystem::vfs::get().open(path)) { - auto open_file_description = kstd::make_shared(dentry->get_inode()); - return kernel::filesystem::file_descriptor_table::get().add_file(open_file_description); + auto open_file_descriptor = kstd::make_shared(dentry->get_inode()); + return kernel::filesystem::file_descriptor_table::get().add_file(open_file_descriptor); } return -1; @@ -49,9 +49,9 @@ namespace kapi::filesystem auto read(int file_descriptor, void * buffer, size_t size) -> ssize_t { - if (auto open_file_description = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) + if (auto open_file_descriptor = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) { - return open_file_description->read(buffer, size); + return open_file_descriptor->read(buffer, size); } return -1; @@ -59,9 +59,9 @@ namespace kapi::filesystem auto write(int file_descriptor, void const * buffer, size_t size) -> ssize_t { - if (auto open_file_description = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) + if (auto open_file_descriptor = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) { - return open_file_description->write(buffer, size); + return open_file_descriptor->write(buffer, size); } return -1; diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp index db7692b..9361f37 100644 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ b/kernel/src/filesystem/file_descriptor_table.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include @@ -37,9 +37,9 @@ namespace kernel::filesystem return *global_file_descriptor_table; } - auto file_descriptor_table::add_file(kstd::shared_ptr const & file_description) -> int + auto file_descriptor_table::add_file(kstd::shared_ptr const & file_descriptor) -> int { - if (!file_description) + if (!file_descriptor) { return -1; } @@ -47,15 +47,15 @@ namespace kernel::filesystem auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); if (it != m_open_files.end()) { - *it = file_description; + *it = file_descriptor; return static_cast(it - m_open_files.begin()); } - m_open_files.push_back(file_description); + m_open_files.push_back(file_descriptor); return static_cast(m_open_files.size() - 1); } - auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr + auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr { if (fd < 0) { diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp index 86ed7bf..dd04e00 100644 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ b/kernel/src/filesystem/file_descriptor_table.tests.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -11,18 +11,18 @@ SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_table]") { - GIVEN("a file descriptor table and an open file description") + GIVEN("a file descriptor table and an open file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); auto inode = kstd::make_shared(); - auto file_description_1 = kstd::make_shared(inode); - auto file_description_2 = kstd::make_shared(inode); + auto file_descriptor_1 = kstd::make_shared(inode); + auto file_descriptor_2 = kstd::make_shared(inode); - WHEN("adding the open file description to the file descriptor table") + WHEN("adding the open file descriptor to the file descriptor table") { - auto fd_1 = table.add_file(file_description_1); - auto fd_2 = table.add_file(file_description_2); - auto fd_3 = table.add_file(file_description_2); + auto fd_1 = table.add_file(file_descriptor_1); + auto fd_2 = table.add_file(file_descriptor_2); + auto fd_3 = table.add_file(file_descriptor_2); THEN("a valid file descriptor is returned") { @@ -31,67 +31,67 @@ SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_tab REQUIRE(fd_3 == 2); } - THEN("the file description can be retrieved using the returned file descriptor") + THEN("the file descriptor can be retrieved using the returned file descriptor") { - auto retrieved_description = table.get_file(fd_1); - REQUIRE(retrieved_description == file_description_1); + auto retrieved_descriptor = table.get_file(fd_1); + REQUIRE(retrieved_descriptor == file_descriptor_1); } } } - GIVEN("a invalid open file description") + GIVEN("a invalid open file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); - THEN("adding a null file description returns an error code") + THEN("adding a null file descriptor returns an error code") { auto fd = table.add_file(nullptr); REQUIRE(fd == -1); } - THEN("retrieving a file description with a negative file descriptor returns a null pointer") + THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") { - auto retrieved_description = table.get_file(-1); - REQUIRE(retrieved_description == nullptr); + auto retrieved_descriptor = table.get_file(-1); + REQUIRE(retrieved_descriptor == nullptr); } - THEN("retrieving a file description with an out-of-bounds file descriptor returns a null pointer") + THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") { - auto retrieved_description = table.get_file(1000); - REQUIRE(retrieved_description == nullptr); + auto retrieved_descriptor = table.get_file(1000); + REQUIRE(retrieved_descriptor == nullptr); } } } SCENARIO("File descriptor table remove file", "[filesystem][file_descriptor_table]") { - GIVEN("a file descriptor table with an open file description") + GIVEN("a file descriptor table with an open file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); auto inode = kstd::make_shared(); - auto file_description = kstd::make_shared(inode); - auto fd = table.add_file(file_description); + auto file_descriptor = kstd::make_shared(inode); + auto fd = table.add_file(file_descriptor); - WHEN("removing the file description using the file descriptor") + WHEN("removing the file descriptor using the file descriptor") { table.remove_file(fd); - THEN("the file description can no longer be retrieved using the file descriptor") + THEN("the file descriptor can no longer be retrieved using the file descriptor") { - auto retrieved_description = table.get_file(fd); - REQUIRE(retrieved_description == nullptr); + auto retrieved_descriptor = table.get_file(fd); + REQUIRE(retrieved_descriptor == nullptr); } } - WHEN("removing a file description the other file descriptor keep the same index") + WHEN("removing a file descriptor the other file descriptor keep the same index") { - auto fd2 = table.add_file(file_description); + auto fd2 = table.add_file(file_descriptor); table.remove_file(fd); - THEN("the second file description can still be retrieved using its file descriptor") + THEN("the second file descriptor can still be retrieved using its file descriptor") { - auto retrieved_description = table.get_file(fd2); - REQUIRE(retrieved_description == file_description); + auto retrieved_descriptor = table.get_file(fd2); + REQUIRE(retrieved_descriptor == file_descriptor); } } } diff --git a/kernel/src/filesystem/open_file_description.cpp b/kernel/src/filesystem/open_file_description.cpp deleted file mode 100644 index 3033e2b..0000000 --- a/kernel/src/filesystem/open_file_description.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include - -#include -#include - -#include - -namespace kernel::filesystem -{ - open_file_description::open_file_description(kstd::shared_ptr const & inode) - : m_inode(inode) - , m_offset(0) - { - if (!inode) - { - kstd::os::panic("[FILESYSTEM] open_file_description constructed with null inode."); - } - } - - auto open_file_description::read(void * buffer, size_t size) -> size_t - { - auto read_bytes = m_inode->read(buffer, m_offset, size); - m_offset += read_bytes; - return read_bytes; - } - - auto open_file_description::write(void const * buffer, size_t size) -> size_t - { - auto written_bytes = m_inode->write(buffer, m_offset, size); - m_offset += written_bytes; - return written_bytes; - } - - auto open_file_description::offset() const -> size_t - { - return m_offset; - } - -} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_description.tests.cpp b/kernel/src/filesystem/open_file_description.tests.cpp deleted file mode 100644 index ce3c81a..0000000 --- a/kernel/src/filesystem/open_file_description.tests.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - -SCENARIO("Open file description construction", "[filesystem][open_file_description]") -{ - GIVEN("an inode and an open file description for that inode") - { - auto inode = kstd::make_shared(); - auto file_description = kernel::filesystem::open_file_description{inode}; - - THEN("the initial offset is zero") - { - REQUIRE(file_description.offset() == 0); - } - } -} - -SCENARIO("Open file description read/write offset management", "[filesystem][open_file_description]") -{ - GIVEN("an inode that tracks read/write calls and an open file description for that inode") - { - auto inode = kstd::make_shared(); - auto file_description = kernel::filesystem::open_file_description{inode}; - - THEN("the offset is updated correctly after reads") - { - REQUIRE(file_description.read(nullptr, 100) == 100); - REQUIRE(file_description.offset() == 100); - REQUIRE(file_description.read(nullptr, 50) == 50); - REQUIRE(file_description.offset() == 150); - } - - THEN("the offset is updated correctly after writes") - { - REQUIRE(file_description.write(nullptr, 200) == 200); - REQUIRE(file_description.offset() == 200); - REQUIRE(file_description.write(nullptr, 25) == 25); - REQUIRE(file_description.offset() == 225); - } - - THEN("reads and writes both update the same offset") - { - REQUIRE(file_description.read(nullptr, 10) == 10); - REQUIRE(file_description.offset() == 10); - REQUIRE(file_description.write(nullptr, 20) == 20); - REQUIRE(file_description.offset() == 30); - REQUIRE(file_description.read(nullptr, 5) == 5); - REQUIRE(file_description.offset() == 35); - REQUIRE(file_description.write(nullptr, 15) == 15); - REQUIRE(file_description.offset() == 50); - } - } -} - -SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, - "Open file description read with real image", "[filesystem][open_file_description][img]") -{ - auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; - - GIVEN("an open file description for a file in a real image") - { - REQUIRE(std::filesystem::exists(image_path)); - REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); - - auto & vfs = kernel::filesystem::vfs::get(); - auto dentry = vfs.open("/information/info_1.txt"); - REQUIRE(dentry != nullptr); - auto ofd = kstd::make_shared(dentry->get_inode()); - - THEN("the file can be read and the offset is updated") - { - kstd::vector buffer(32); - auto bytes_read = ofd->read(buffer.data(), buffer.size()); - REQUIRE(bytes_read == 32); - REQUIRE(ofd->offset() == 32); - - std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; - auto const content_end = buffer_as_str.find('\0'); - REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); - - for (auto i = content_end; i < buffer_as_str.size(); ++i) - { - REQUIRE(buffer_as_str[i] == '\0'); - } - } - - THEN("the file can be read multiple times") - { - kstd::vector buffer(4); - auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2); - REQUIRE(bytes_read_1 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size() / 2); - - auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); - REQUIRE(bytes_read_2 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size()); - - std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; - REQUIRE(buffer_as_str == "info"); - } - } -} diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp new file mode 100644 index 0000000..25bffbd --- /dev/null +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include +#include + +#include + +namespace kernel::filesystem +{ + open_file_descriptor::open_file_descriptor(kstd::shared_ptr const & inode) + : m_inode(inode) + , m_offset(0) + { + if (!inode) + { + kstd::os::panic("[FILESYSTEM] open_file_descriptor constructed with null inode."); + } + } + + auto open_file_descriptor::read(void * buffer, size_t size) -> size_t + { + auto read_bytes = m_inode->read(buffer, m_offset, size); + m_offset += read_bytes; + return read_bytes; + } + + auto open_file_descriptor::write(void const * buffer, size_t size) -> size_t + { + auto written_bytes = m_inode->write(buffer, m_offset, size); + m_offset += written_bytes; + return written_bytes; + } + + auto open_file_descriptor::offset() const -> size_t + { + return m_offset; + } + +} // namespace kernel::filesystem \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp new file mode 100644 index 0000000..095e203 --- /dev/null +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor]") +{ + GIVEN("an inode and an open file descriptor for that inode") + { + auto inode = kstd::make_shared(); + auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + + THEN("the initial offset is zero") + { + REQUIRE(file_descriptor.offset() == 0); + } + } +} + +SCENARIO("Open file descriptor read/write offset management", "[filesystem][open_file_descriptor]") +{ + GIVEN("an inode that tracks read/write calls and an open file descriptor for that inode") + { + auto inode = kstd::make_shared(); + auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + + THEN("the offset is updated correctly after reads") + { + REQUIRE(file_descriptor.read(nullptr, 100) == 100); + REQUIRE(file_descriptor.offset() == 100); + REQUIRE(file_descriptor.read(nullptr, 50) == 50); + REQUIRE(file_descriptor.offset() == 150); + } + + THEN("the offset is updated correctly after writes") + { + REQUIRE(file_descriptor.write(nullptr, 200) == 200); + REQUIRE(file_descriptor.offset() == 200); + REQUIRE(file_descriptor.write(nullptr, 25) == 25); + REQUIRE(file_descriptor.offset() == 225); + } + + THEN("reads and writes both update the same offset") + { + REQUIRE(file_descriptor.read(nullptr, 10) == 10); + REQUIRE(file_descriptor.offset() == 10); + REQUIRE(file_descriptor.write(nullptr, 20) == 20); + REQUIRE(file_descriptor.offset() == 30); + REQUIRE(file_descriptor.read(nullptr, 5) == 5); + REQUIRE(file_descriptor.offset() == 35); + REQUIRE(file_descriptor.write(nullptr, 15) == 15); + REQUIRE(file_descriptor.offset() == 50); + } + } +} + +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Open file descriptor read with real image", + "[filesystem][open_file_descriptor][img]") +{ + auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + + GIVEN("an open file descriptor for a file in a real image") + { + REQUIRE(std::filesystem::exists(image_path)); + REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); + + auto & vfs = kernel::filesystem::vfs::get(); + auto dentry = vfs.open("/information/info_1.txt"); + REQUIRE(dentry != nullptr); + auto ofd = kstd::make_shared(dentry->get_inode()); + + THEN("the file can be read and the offset is updated") + { + kstd::vector buffer(32); + auto bytes_read = ofd->read(buffer.data(), buffer.size()); + REQUIRE(bytes_read == 32); + REQUIRE(ofd->offset() == 32); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; + auto const content_end = buffer_as_str.find('\0'); + REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); + + for (auto i = content_end; i < buffer_as_str.size(); ++i) + { + REQUIRE(buffer_as_str[i] == '\0'); + } + } + + THEN("the file can be read multiple times") + { + kstd::vector buffer(4); + auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2); + REQUIRE(bytes_read_1 == buffer.size() / 2); + REQUIRE(ofd->offset() == buffer.size() / 2); + + auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); + REQUIRE(bytes_read_2 == buffer.size() / 2); + REQUIRE(ofd->offset() == buffer.size()); + + std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; + REQUIRE(buffer_as_str == "info"); + } + } +} diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 9cadb4d..979ea42 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -185,7 +185,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto dentry = vfs.open("/information/sheep_1.txt"); REQUIRE(dentry != nullptr); - auto sheep_1_ofd = kstd::make_shared(dentry->get_inode()); + auto sheep_1_ofd = kstd::make_shared(dentry->get_inode()); kstd::vector buffer(7); auto bytes_read = sheep_1_ofd->read(buffer.data(), buffer.size()); @@ -210,8 +210,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(sheep_1 != nullptr); REQUIRE(goat_1 != nullptr); - auto sheep_1_ofd = kstd::make_shared(sheep_1->get_inode()); - auto goat_1_ofd = kstd::make_shared(goat_1->get_inode()); + auto sheep_1_ofd = kstd::make_shared(sheep_1->get_inode()); + auto goat_1_ofd = kstd::make_shared(goat_1->get_inode()); kstd::vector sheep_buffer(7); auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), sheep_buffer.size()); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9f4ec1e..9878d20 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include @@ -36,7 +36,7 @@ auto test_device_names() -> void }); } -auto test_file_description_manually() -> void +auto test_file_descriptor_manually() -> void { // setup auto fd_table = kernel::filesystem::file_descriptor_table::get(); @@ -45,7 +45,7 @@ auto test_file_description_manually() -> void auto dev_node = kstd::make_shared(device); - auto ofd = kstd::make_shared(dev_node); + auto ofd = kstd::make_shared(dev_node); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again @@ -71,7 +71,7 @@ auto test_file_description_manually() -> void fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes - auto ofd1 = kstd::make_shared(dev_node); + auto ofd1 = kstd::make_shared(dev_node); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); @@ -96,7 +96,7 @@ auto test_device_with_vfs() -> void } auto fd_table = kernel::filesystem::file_descriptor_table::get(); - auto ofd = kstd::make_shared(dentry->get_inode()); + auto ofd = kstd::make_shared(dentry->get_inode()); auto fd = fd_table.add_file(ofd); kstd::vector buffer{2}; auto file = fd_table.get_file(fd); @@ -122,7 +122,7 @@ auto test_file_lookup() -> void } kstd::vector buffer{32}; - auto ofd = kstd::make_shared(dentry->get_inode()); + auto ofd = kstd::make_shared(dentry->get_inode()); auto number_of_read_bytes = ofd->read(buffer.data(), buffer.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer); @@ -175,8 +175,8 @@ auto run_test_code() -> void test_device_names(); kstd::println("---------------------------------"); - kstd::println("[TEST] file description manually"); - test_file_description_manually(); + kstd::println("[TEST] file descriptor manually"); + test_file_descriptor_manually(); kstd::println("---------------------------------"); kstd::println("[TEST] device with VFS"); -- cgit v1.2.3 From e0854bc0aad9e59d67fbf300cb223b116b127ffc Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sun, 26 Apr 2026 12:36:26 +0200 Subject: rename file_descriptor_table to open_file_table --- kernel/CMakeLists.txt | 4 +- .../kernel/filesystem/file_descriptor_table.hpp | 64 ------------ .../include/kernel/filesystem/open_file_table.hpp | 63 ++++++++++++ .../filesystem/file_descriptor_table.hpp | 10 +- kernel/kapi/filesystem.cpp | 10 +- kernel/src/filesystem/file_descriptor_table.cpp | 98 ------------------ .../src/filesystem/file_descriptor_table.tests.cpp | 113 --------------------- kernel/src/filesystem/open_file_table.cpp | 98 ++++++++++++++++++ kernel/src/filesystem/open_file_table.tests.cpp | 113 +++++++++++++++++++++ kernel/src/main.cpp | 10 +- kernel/src/test_support/state_reset_listener.cpp | 8 +- 11 files changed, 295 insertions(+), 296 deletions(-) delete mode 100644 kernel/include/kernel/filesystem/file_descriptor_table.hpp create mode 100644 kernel/include/kernel/filesystem/open_file_table.hpp delete mode 100644 kernel/src/filesystem/file_descriptor_table.cpp delete mode 100644 kernel/src/filesystem/file_descriptor_table.tests.cpp create mode 100644 kernel/src/filesystem/open_file_table.cpp create mode 100644 kernel/src/filesystem/open_file_table.tests.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index cddec97..909ccf7 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -47,12 +47,12 @@ target_sources("kernel_lib" PRIVATE # Filesystem Subsystem "src/filesystem/dentry.cpp" "src/filesystem/device_inode.cpp" - "src/filesystem/file_descriptor_table.cpp" "src/filesystem/filesystem.cpp" "src/filesystem/inode.cpp" "src/filesystem/mount_table.cpp" "src/filesystem/mount.cpp" "src/filesystem/open_file_descriptor.cpp" + "src/filesystem/open_file_table.cpp" "src/filesystem/vfs.cpp" # DevFS Filesystem @@ -192,10 +192,10 @@ if(BUILD_TESTING) "src/filesystem/rootfs/inode.tests.cpp" "src/filesystem/dentry.tests.cpp" "src/filesystem/device_inode.tests.cpp" - "src/filesystem/file_descriptor_table.tests.cpp" "src/filesystem/mount_table.tests.cpp" "src/filesystem/mount.tests.cpp" "src/filesystem/open_file_descriptor.tests.cpp" + "src/filesystem/open_file_table.tests.cpp" "src/filesystem/vfs.tests.cpp" # Storage Subsystem Tests diff --git a/kernel/include/kernel/filesystem/file_descriptor_table.hpp b/kernel/include/kernel/filesystem/file_descriptor_table.hpp deleted file mode 100644 index b0e699b..0000000 --- a/kernel/include/kernel/filesystem/file_descriptor_table.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef TEACH_OS_KERNEL_FILESYSTEM_FILE_DESCRIPTOR_TABLE_HPP -#define TEACH_OS_KERNEL_FILESYSTEM_FILE_DESCRIPTOR_TABLE_HPP - -#include - -#include -#include - -namespace kernel::filesystem -{ - /** - @brief A table for managing file descriptors in the filesystem. This class provides methods for adding, retrieving, - and removing open file descriptors. - */ - struct file_descriptor_table - { - /** - @brief Initialize the global file descriptor table. This method creates the singleton instance of the file - descriptor table. - @warning Panics if called more than once. - */ - auto static init() -> void; - - /** - @brief Get the global file descriptor table instance. - @return A reference to the global file descriptor table. - @warning Panics if the file descriptor table has not been initialized. - */ - auto static get() -> file_descriptor_table &; - - /** - @brief Destructor for the file descriptor table. - */ - ~file_descriptor_table() = default; - - /** - @brief Add a file to the descriptor table. - @param f The file descriptor to add. - @return The file descriptor index assigned to the file, or -1 on failure. - */ - auto add_file(kstd::shared_ptr const & f) -> int; - - /** - @brief Get a file from the descriptor 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 get_file(int fd) const -> kstd::shared_ptr; - - /** - @brief Remove a file from the descriptor table. - @param fd The file descriptor index to remove. - @return 0 on success, or -1 on failure. - */ - auto remove_file(int fd) -> int; - - private: - file_descriptor_table() = default; - - kstd::vector> m_open_files{}; - }; -} // namespace kernel::filesystem - -#endif \ No newline at end of file diff --git a/kernel/include/kernel/filesystem/open_file_table.hpp b/kernel/include/kernel/filesystem/open_file_table.hpp new file mode 100644 index 0000000..2f9a421 --- /dev/null +++ b/kernel/include/kernel/filesystem/open_file_table.hpp @@ -0,0 +1,63 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_TABLE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_TABLE_HPP + +#include + +#include +#include + +namespace kernel::filesystem +{ + /** + @brief A table for managing file descriptors in the filesystem. This class provides methods for adding, retrieving, + and removing open file descriptors. + */ + struct open_file_table + { + /** + @brief Initialize the global open file table. This method creates the singleton instance of the open file table. + @warning Panics if called more than once. + */ + auto static init() -> void; + + /** + @brief Get the global open file table instance. + @return A reference to the global open file table. + @warning Panics if the open file table has not been initialized. + */ + auto static get() -> open_file_table &; + + /** + @brief Destructor for the open file table. + */ + ~open_file_table() = default; + + /** + @brief Add a file to the open file table. + @param f The file descriptor to add. + @return The file descriptor index assigned to the file, or -1 on failure. + */ + auto add_file(kstd::shared_ptr const & f) -> int; + + /** + @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 get_file(int fd) const -> kstd::shared_ptr; + + /** + @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(int fd) -> int; + + private: + open_file_table() = default; + + kstd::vector> m_open_files{}; + }; +} // namespace kernel::filesystem + +#endif \ No newline at end of file diff --git a/kernel/include/kernel/test_support/filesystem/file_descriptor_table.hpp b/kernel/include/kernel/test_support/filesystem/file_descriptor_table.hpp index bbc0f4a..46b0334 100644 --- a/kernel/include/kernel/test_support/filesystem/file_descriptor_table.hpp +++ b/kernel/include/kernel/test_support/filesystem/file_descriptor_table.hpp @@ -1,10 +1,10 @@ -#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_FILE_DESCRIPTOR_TABLE_HPP -#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_FILE_DESCRIPTOR_TABLE_HPP +#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_OPEN_FILE_TABLE_HPP +#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_OPEN_FILE_TABLE_HPP -namespace kernel::tests::filesystem::file_descriptor_table +namespace kernel::tests::filesystem::open_file_table { - //! Deinitialize the file descriptor table singleton. + //! Deinitialize the open file table singleton. auto deinit() -> void; -} // namespace kernel::tests::filesystem::file_descriptor_table +} // namespace kernel::tests::filesystem::open_file_table #endif \ No newline at end of file diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index 8481f20..4c68f28 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -1,7 +1,7 @@ #include -#include #include +#include #include #include @@ -36,7 +36,7 @@ namespace kapi::filesystem if (auto dentry = kernel::filesystem::vfs::get().open(path)) { auto open_file_descriptor = kstd::make_shared(dentry->get_inode()); - return kernel::filesystem::file_descriptor_table::get().add_file(open_file_descriptor); + return kernel::filesystem::open_file_table::get().add_file(open_file_descriptor); } return -1; @@ -44,12 +44,12 @@ namespace kapi::filesystem auto close(int file_descriptor) -> int { - return kernel::filesystem::file_descriptor_table::get().remove_file(file_descriptor); + return kernel::filesystem::open_file_table::get().remove_file(file_descriptor); } auto read(int file_descriptor, void * buffer, size_t size) -> ssize_t { - if (auto open_file_descriptor = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) + if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().get_file(file_descriptor)) { return open_file_descriptor->read(buffer, size); } @@ -59,7 +59,7 @@ namespace kapi::filesystem auto write(int file_descriptor, void const * buffer, size_t size) -> ssize_t { - if (auto open_file_descriptor = kernel::filesystem::file_descriptor_table::get().get_file(file_descriptor)) + if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().get_file(file_descriptor)) { return open_file_descriptor->write(buffer, size); } diff --git a/kernel/src/filesystem/file_descriptor_table.cpp b/kernel/src/filesystem/file_descriptor_table.cpp deleted file mode 100644 index 9361f37..0000000 --- a/kernel/src/filesystem/file_descriptor_table.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include - -#include - -#include - -#include - -#include -#include -#include - -namespace -{ - constinit auto static global_file_descriptor_table = std::optional{}; -} // namespace - -namespace kernel::filesystem -{ - auto file_descriptor_table::init() -> void - { - if (global_file_descriptor_table) - { - kapi::system::panic("[FILESYSTEM] File descriptor table has already been initialized."); - } - - global_file_descriptor_table.emplace(file_descriptor_table{}); - } - - auto file_descriptor_table::get() -> file_descriptor_table & - { - if (!global_file_descriptor_table) - { - kapi::system::panic("[FILESYSTEM] File descriptor table has not been initialized."); - } - - return *global_file_descriptor_table; - } - - auto file_descriptor_table::add_file(kstd::shared_ptr const & file_descriptor) -> int - { - if (!file_descriptor) - { - return -1; - } - - auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); - if (it != m_open_files.end()) - { - *it = file_descriptor; - return static_cast(it - m_open_files.begin()); - } - - m_open_files.push_back(file_descriptor); - return static_cast(m_open_files.size() - 1); - } - - auto file_descriptor_table::get_file(int fd) const -> kstd::shared_ptr - { - if (fd < 0) - { - return nullptr; - } - - auto const index = static_cast(fd); - if (index >= m_open_files.size()) - { - return nullptr; - } - - return m_open_files.at(index); - } - - auto file_descriptor_table::remove_file(int fd) -> int - { - if (fd < 0) - { - return -1; - } - - auto const index = static_cast(fd); - if (index >= m_open_files.size()) - { - return -1; - } - - m_open_files.at(index) = nullptr; - return 0; - } -} // namespace kernel::filesystem - -namespace kernel::tests::filesystem::file_descriptor_table -{ - auto deinit() -> void - { - global_file_descriptor_table.reset(); - } -} // namespace kernel::tests::filesystem::file_descriptor_table diff --git a/kernel/src/filesystem/file_descriptor_table.tests.cpp b/kernel/src/filesystem/file_descriptor_table.tests.cpp deleted file mode 100644 index dd04e00..0000000 --- a/kernel/src/filesystem/file_descriptor_table.tests.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include - -#include -#include - -#include -#include -#include - -#include - -SCENARIO("File descriptor table add/get file", "[filesystem][file_descriptor_table]") -{ - GIVEN("a file descriptor table and an open file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - auto inode = kstd::make_shared(); - auto file_descriptor_1 = kstd::make_shared(inode); - auto file_descriptor_2 = kstd::make_shared(inode); - - WHEN("adding the open file descriptor to the file descriptor table") - { - auto fd_1 = table.add_file(file_descriptor_1); - auto fd_2 = table.add_file(file_descriptor_2); - auto fd_3 = table.add_file(file_descriptor_2); - - THEN("a valid file descriptor is returned") - { - REQUIRE(fd_1 == 0); - REQUIRE(fd_2 == 1); - REQUIRE(fd_3 == 2); - } - - THEN("the file descriptor can be retrieved using the returned file descriptor") - { - auto retrieved_descriptor = table.get_file(fd_1); - REQUIRE(retrieved_descriptor == file_descriptor_1); - } - } - } - - GIVEN("a invalid open file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - - THEN("adding a null file descriptor returns an error code") - { - auto fd = table.add_file(nullptr); - REQUIRE(fd == -1); - } - - THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") - { - auto retrieved_descriptor = table.get_file(-1); - REQUIRE(retrieved_descriptor == nullptr); - } - - THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") - { - auto retrieved_descriptor = table.get_file(1000); - REQUIRE(retrieved_descriptor == nullptr); - } - } -} - -SCENARIO("File descriptor table remove file", "[filesystem][file_descriptor_table]") -{ - GIVEN("a file descriptor table with an open file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - auto inode = kstd::make_shared(); - auto file_descriptor = kstd::make_shared(inode); - auto fd = table.add_file(file_descriptor); - - WHEN("removing the file descriptor using the file descriptor") - { - table.remove_file(fd); - - THEN("the file descriptor can no longer be retrieved using the file descriptor") - { - auto retrieved_descriptor = table.get_file(fd); - REQUIRE(retrieved_descriptor == nullptr); - } - } - - WHEN("removing a file descriptor the other file descriptor keep the same index") - { - auto fd2 = table.add_file(file_descriptor); - table.remove_file(fd); - - THEN("the second file descriptor can still be retrieved using its file descriptor") - { - auto retrieved_descriptor = table.get_file(fd2); - REQUIRE(retrieved_descriptor == file_descriptor); - } - } - } - - GIVEN("an invalid file descriptor") - { - auto & table = kernel::filesystem::file_descriptor_table::get(); - - THEN("removing a file with a negative file descriptor does nothing") - { - REQUIRE_NOTHROW(table.remove_file(-1)); - } - - THEN("removing a file with an out-of-bounds file descriptor does nothing") - { - REQUIRE_NOTHROW(table.remove_file(1000)); - } - } -} \ No newline at end of file diff --git a/kernel/src/filesystem/open_file_table.cpp b/kernel/src/filesystem/open_file_table.cpp new file mode 100644 index 0000000..e47d229 --- /dev/null +++ b/kernel/src/filesystem/open_file_table.cpp @@ -0,0 +1,98 @@ +#include + +#include + +#include + +#include + +#include +#include +#include + +namespace +{ + constinit auto static global_open_file_table = std::optional{}; +} // namespace + +namespace kernel::filesystem +{ + auto open_file_table::init() -> void + { + if (global_open_file_table) + { + kapi::system::panic("[FILESYSTEM] Open file table has already been initialized."); + } + + global_open_file_table.emplace(open_file_table{}); + } + + auto open_file_table::get() -> open_file_table & + { + if (!global_open_file_table) + { + kapi::system::panic("[FILESYSTEM] Open file table has not been initialized."); + } + + return *global_open_file_table; + } + + auto open_file_table::add_file(kstd::shared_ptr const & file_descriptor) -> int + { + if (!file_descriptor) + { + return -1; + } + + auto it = std::ranges::find_if(m_open_files, [](auto const & open_file) { return open_file == nullptr; }); + if (it != m_open_files.end()) + { + *it = file_descriptor; + return static_cast(it - m_open_files.begin()); + } + + m_open_files.push_back(file_descriptor); + return static_cast(m_open_files.size() - 1); + } + + auto open_file_table::get_file(int fd) const -> kstd::shared_ptr + { + if (fd < 0) + { + return nullptr; + } + + auto const index = static_cast(fd); + if (index >= m_open_files.size()) + { + return nullptr; + } + + return m_open_files.at(index); + } + + auto open_file_table::remove_file(int fd) -> int + { + if (fd < 0) + { + return -1; + } + + auto const index = static_cast(fd); + if (index >= m_open_files.size()) + { + return -1; + } + + m_open_files.at(index) = nullptr; + return 0; + } +} // namespace kernel::filesystem + +namespace kernel::tests::filesystem::open_file_table +{ + auto deinit() -> void + { + global_open_file_table.reset(); + } +} // namespace kernel::tests::filesystem::open_file_table diff --git a/kernel/src/filesystem/open_file_table.tests.cpp b/kernel/src/filesystem/open_file_table.tests.cpp new file mode 100644 index 0000000..a5c791d --- /dev/null +++ b/kernel/src/filesystem/open_file_table.tests.cpp @@ -0,0 +1,113 @@ +#include + +#include +#include + +#include +#include +#include + +#include + +SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") +{ + GIVEN("a open file table and an open file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + auto inode = kstd::make_shared(); + auto file_descriptor_1 = kstd::make_shared(inode); + auto file_descriptor_2 = kstd::make_shared(inode); + + WHEN("adding the open file descriptor to the open file table") + { + auto fd_1 = table.add_file(file_descriptor_1); + auto fd_2 = table.add_file(file_descriptor_2); + auto fd_3 = table.add_file(file_descriptor_2); + + THEN("a valid file descriptor is returned") + { + REQUIRE(fd_1 == 0); + REQUIRE(fd_2 == 1); + REQUIRE(fd_3 == 2); + } + + THEN("the file descriptor can be retrieved using the returned file descriptor") + { + auto retrieved_descriptor = table.get_file(fd_1); + REQUIRE(retrieved_descriptor == file_descriptor_1); + } + } + } + + GIVEN("a invalid open file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + + THEN("adding a null file descriptor returns an error code") + { + auto fd = table.add_file(nullptr); + REQUIRE(fd == -1); + } + + THEN("retrieving a file descriptor with a negative file descriptor returns a null pointer") + { + auto retrieved_descriptor = table.get_file(-1); + REQUIRE(retrieved_descriptor == nullptr); + } + + THEN("retrieving a file descriptor with an out-of-bounds file descriptor returns a null pointer") + { + auto retrieved_descriptor = table.get_file(1000); + REQUIRE(retrieved_descriptor == nullptr); + } + } +} + +SCENARIO("Open file table remove file", "[filesystem][open_file_table]") +{ + GIVEN("a open file table with an open file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + auto inode = kstd::make_shared(); + auto file_descriptor = kstd::make_shared(inode); + auto fd = table.add_file(file_descriptor); + + WHEN("removing the file descriptor using the file descriptor") + { + table.remove_file(fd); + + THEN("the file descriptor can no longer be retrieved using the file descriptor") + { + auto retrieved_descriptor = table.get_file(fd); + REQUIRE(retrieved_descriptor == nullptr); + } + } + + WHEN("removing a file descriptor the other file descriptor keep the same index") + { + auto fd2 = table.add_file(file_descriptor); + table.remove_file(fd); + + THEN("the second file descriptor can still be retrieved using its file descriptor") + { + auto retrieved_descriptor = table.get_file(fd2); + REQUIRE(retrieved_descriptor == file_descriptor); + } + } + } + + GIVEN("an invalid file descriptor") + { + auto & table = kernel::filesystem::open_file_table::get(); + + THEN("removing a file with a negative file descriptor does nothing") + { + REQUIRE_NOTHROW(table.remove_file(-1)); + } + + THEN("removing a file with an out-of-bounds file descriptor does nothing") + { + REQUIRE_NOTHROW(table.remove_file(1000)); + } + } +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9878d20..ffea979 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include @@ -39,7 +39,7 @@ auto test_device_names() -> void auto test_file_descriptor_manually() -> void { // setup - auto fd_table = kernel::filesystem::file_descriptor_table::get(); + auto fd_table = kernel::filesystem::open_file_table::get(); auto storage_mgmt = kernel::devices::storage::management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); @@ -95,7 +95,7 @@ auto test_device_with_vfs() -> void kstd::os::panic("test code failed"); } - auto fd_table = kernel::filesystem::file_descriptor_table::get(); + auto fd_table = kernel::filesystem: