aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem/ext2
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/filesystem/ext2')
-rw-r--r--kernel/src/filesystem/ext2/filesystem.cpp36
-rw-r--r--kernel/src/filesystem/ext2/inode.cpp42
-rw-r--r--kernel/src/filesystem/ext2/inode.tests.cpp65
3 files changed, 94 insertions, 49 deletions
diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp
index 41572ee..47e54fe 100644
--- a/kernel/src/filesystem/ext2/filesystem.cpp
+++ b/kernel/src/filesystem/ext2/filesystem.cpp
@@ -16,19 +16,6 @@
namespace kernel::filesystem::ext2
{
- namespace
- {
- auto S_ISREG(uint16_t mode) -> bool
- {
- return (mode & constants::mode_mask) == constants::mode_regular;
- }
-
- auto S_ISDIR(uint16_t mode) -> bool
- {
- return (mode & constants::mode_mask) == constants::mode_directory;
- }
- } // namespace
-
auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const & backing_inode) -> operation_result
{
kernel::filesystem::filesystem::mount(backing_inode);
@@ -74,7 +61,7 @@ namespace kernel::filesystem::ext2
}
auto const block_size = get_block_size();
- auto const & inode_data = ext2_parent->m_data;
+ auto const & inode_data = ext2_parent->data();
kstd::vector<uint8_t> buffer(block_size);
for (uint32_t i = 0; i < get_inode_block_count(inode_data); ++i)
@@ -119,25 +106,10 @@ namespace kernel::filesystem::ext2
auto const inode_table_offset = static_cast<size_t>(inode_table_start_block) * block_size;
auto const inode_offset = inode_table_offset + inode_index_within_group * get_inode_size();
- auto new_inode = kstd::make_shared<inode>(this);
- m_backing_inode->read(&new_inode->m_data, inode_offset, sizeof(inode_data));
-
- // TODO BA-FS26 improve inode_kind really needed? or just map it to the mode bits?
- if (S_ISREG(new_inode->m_data.mode))
- {
- new_inode->m_kind = inode::inode_kind::regular;
- }
- else if (S_ISDIR(new_inode->m_data.mode))
- {
- new_inode->m_kind = inode::inode_kind::directory;
- }
- else
- {
- // TODO BA-FS26 really correct??
- return nullptr;
- }
+ auto new_inode_data = inode_data{};
+ m_backing_inode->read(&new_inode_data, inode_offset, sizeof(inode_data));
- return new_inode;
+ return kstd::make_shared<inode>(this, new_inode_data);
}
auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t
diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp
index c45c41e..1914c70 100644
--- a/kernel/src/filesystem/ext2/inode.cpp
+++ b/kernel/src/filesystem/ext2/inode.cpp
@@ -5,15 +5,17 @@
#include <kapi/system.hpp>
+#include <kstd/cstring>
+
#include <algorithm>
#include <cstddef>
#include <cstdint>
namespace kernel::filesystem::ext2
{
- inode::inode(filesystem * fs)
- : kernel::filesystem::inode(inode_kind::regular)
- , m_filesystem(fs)
+ inode::inode(filesystem * fs, inode_data const & data)
+ : m_filesystem(fs)
+ , m_data(data)
{
if (!m_filesystem)
{
@@ -23,6 +25,17 @@ namespace kernel::filesystem::ext2
auto inode::read(void * buffer, size_t offset, size_t size) const -> size_t
{
+ // TODO BA-FS26 use revision 1 size
+ auto const max_readable = static_cast<size_t>(m_data.size) - offset;
+ auto const requested_size = std::min(size, max_readable);
+
+ if (is_symbolic_link() && m_data.size <= sizeof(m_data.block))
+ {
+ auto inline_target = reinterpret_cast<uint8_t const *>(m_data.block.data());
+ kstd::libc::memcpy(static_cast<uint8_t *>(buffer), inline_target + offset, requested_size);
+ return requested_size;
+ }
+
auto block_index = offset / m_filesystem->get_block_size();
auto in_block_offset = offset % m_filesystem->get_block_size();
@@ -40,7 +53,8 @@ namespace kernel::filesystem::ext2
auto const block_start_offset = block_number * m_filesystem->get_block_size();
auto const read_offset = block_start_offset + in_block_offset;
- auto const bytes_to_read = std::min(size - bytes_read, m_filesystem->get_block_size() - in_block_offset);
+ auto const bytes_to_read =
+ std::min(requested_size - bytes_read, m_filesystem->get_block_size() - in_block_offset);
bytes_read +=
m_filesystem->backing_inode()->read(static_cast<uint8_t *>(buffer) + bytes_read, read_offset, bytes_to_read);
@@ -57,4 +71,24 @@ namespace kernel::filesystem::ext2
kapi::system::panic("[EXT2] inode::write is not implemented yet");
return 0;
}
+
+ [[nodiscard]] auto inode::data() const -> inode_data const &
+ {
+ return m_data;
+ }
+
+ auto inode::is_regular() const -> bool
+ {
+ return (m_data.mode & constants::mode_mask) == constants::mode_regular;
+ }
+
+ auto inode::is_directory() const -> bool
+ {
+ return (m_data.mode & constants::mode_mask) == constants::mode_directory;
+ }
+
+ auto inode::is_symbolic_link() const -> bool
+ {
+ return (m_data.mode & constants::mode_mask) == constants::mode_symbolic_link;
+ }
} // namespace kernel::filesystem::ext2
diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp
index 4d61790..49ba21b 100644
--- a/kernel/src/filesystem/ext2/inode.tests.cpp
+++ b/kernel/src/filesystem/ext2/inode.tests.cpp
@@ -23,13 +23,50 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]"
GIVEN("an ext2 filesystem")
{
auto fs = kernel::filesystem::ext2::filesystem{};
+ auto data = kernel::filesystem::ext2::inode_data{};
- THEN("the inode is initialized and has the kind regular")
+ THEN("the inode is initialized with regular file mode in data and has the kind regular")
{
- auto inode = kernel::filesystem::ext2::inode{&fs};
+ data.mode = kernel::filesystem::ext2::constants::mode_regular;
+ auto inode = kernel::filesystem::ext2::inode(&fs, data);
+
REQUIRE(inode.is_regular());
- REQUIRE(!inode.is_directory());
- REQUIRE(!inode.is_device());
+ REQUIRE_FALSE(inode.is_directory());
+ REQUIRE_FALSE(inode.is_device());
+ REQUIRE_FALSE(inode.is_symbolic_link());
+ }
+
+ THEN("the inode is initialized with directory mode in data and has the kind directory")
+ {
+ data.mode = kernel::filesystem::ext2::constants::mode_directory;
+ auto inode = kernel::filesystem::ext2::inode(&fs, data);
+
+ REQUIRE_FALSE(inode.is_regular());
+ REQUIRE(inode.is_directory());
+ REQUIRE_FALSE(inode.is_device());
+ REQUIRE_FALSE(inode.is_symbolic_link());
+ }
+
+ THEN("the inode is initialized with symbolic link mode in data and has the kind symbolic link")
+ {
+ data.mode = kernel::filesystem::ext2::constants::mode_symbolic_link;
+ auto inode = kernel::filesystem::ext2::inode(&fs, data);
+
+ REQUIRE_FALSE(inode.is_regular());
+ REQUIRE_FALSE(inode.is_directory());
+ REQUIRE_FALSE(inode.is_device());
+ REQUIRE(inode.is_symbolic_link());
+ }
+
+ THEN("the inode is initialized with zero mode in data and has no specific kind")
+ {
+ data.mode = 0;
+ auto inode = kernel::filesystem::ext2::inode(&fs, data);
+
+ REQUIRE_FALSE(inode.is_regular());
+ REQUIRE_FALSE(inode.is_directory());
+ REQUIRE_FALSE(inode.is_device());
+ REQUIRE_FALSE(inode.is_symbolic_link());
}
}
@@ -37,7 +74,7 @@ SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]"
{
THEN("constructing an inode with a null filesystem pointer panics")
{
- REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode{nullptr}, kernel::tests::cpu::halt);
+ REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode(nullptr, {}), kernel::tests::cpu::halt);
}
}
}
@@ -102,9 +139,10 @@ SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesyst
auto fs = kernel::filesystem::ext2::filesystem{};
REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
- auto inode = kernel::filesystem::ext2::inode{&fs};
- inode.m_data.blocks = 2;
- inode.m_data.block[0] = 0;
+ auto data = kernel::filesystem::ext2::inode_data{};
+ data.blocks = 2;
+ data.block[0] = 0;
+ auto inode = kernel::filesystem::ext2::inode{&fs, data};
auto buffer = kstd::vector<std::byte>(32, std::byte{0xAB});
@@ -130,12 +168,13 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]")
auto fs = kernel::filesystem::ext2::filesystem{};
REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
- auto inode = kernel::filesystem::ext2::inode{&fs};
- inode.m_data.blocks = 2;
- inode.m_data.block[0] = 20;
+ auto inode_data = kernel::filesystem::ext2::inode_data{};
+ inode_data.blocks = 2;
+ inode_data.block[0] = 20;
kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6);
- inode.m_data.block[1] = 21;
+ inode_data.block[1] = 21;
kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6);
+ auto inode = kernel::filesystem::ext2::inode{&fs, inode_data};
auto buffer = kstd::vector<std::byte>(12, std::byte{0x00});
@@ -155,7 +194,7 @@ SCENARIO("Ext2 inode write is not implemented", "[filesystem][ext2][inode]")
GIVEN("an ext2 inode")
{
auto fs = kernel::filesystem::ext2::filesystem{};
- auto inode = kernel::filesystem::ext2::inode{&fs};
+ auto inode = kernel::filesystem::ext2::inode{&fs, kernel::filesystem::ext2::inode_data{}};
THEN("writing to the inode panics")
{