aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.cpp62
-rw-r--r--kernel/kernel/filesystem/ext2/filesystem.hpp2
-rw-r--r--kernel/kernel/filesystem/ext2/inode.cpp5
-rw-r--r--kernel/kernel/filesystem/ext2/inode.hpp15
4 files changed, 74 insertions, 10 deletions
diff --git a/kernel/kernel/filesystem/ext2/filesystem.cpp b/kernel/kernel/filesystem/ext2/filesystem.cpp
index 7b0bce0e..89f25d42 100644
--- a/kernel/kernel/filesystem/ext2/filesystem.cpp
+++ b/kernel/kernel/filesystem/ext2/filesystem.cpp
@@ -10,6 +10,7 @@
#include <kernel/filesystem/inode.hpp>
#include <kernel/filesystem/type.hpp>
+#include <kstd/cstring.hpp>
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
#include <kstd/system_error.hpp>
@@ -201,11 +202,10 @@ namespace kernel::filesystem::ext2
}
}
- auto filesystem::add_directory_entry(inode * ext2_parent, std::string_view name, uint32_t inode_number, uint16_t mode)
- -> kstd::result<void>
+ auto filesystem::add_directory_entry(inode * ext2_parent, std::string_view name, uint32_t child_inode_number,
+ [[maybe_unused]] uint16_t mode) -> kstd::result<void>
{
- auto block_count = inode_block_count(ext2_parent->data());
- auto const last_block_index = block_count - 1;
+ auto const last_block_index = inode_block_count(ext2_parent->data()) - 1;
auto const global_block_number =
map_inode_block_index_to_global_block_number(last_block_index, ext2_parent->data());
@@ -233,11 +233,59 @@ namespace kernel::filesystem::ext2
offset += entry->rec_len;
}
- auto const * last_entry = reinterpret_cast<linked_directory_entry const *>(buffer.data() + offset);
+ // auto const * last_entry = reinterpret_cast<linked_directory_entry const *>(buffer.data() + offset);
- auto const last_entry_actual_length = 0; // TODO
+ // auto const last_entry_actual_len = static_cast<uint16_t>((8u + last_entry->name_len + 3u) & ~3u);
+ // auto const free_space = last_entry->rec_len - last_entry_actual_len;
- return kstd::success();
+ // auto const last_entry_actual_length = 0; // TODO
+ auto const name_len = static_cast<uint8_t>(name.size());
+ auto const needed_rec_len = static_cast<uint16_t>((8u + name_len + 3u) & ~3u);
+
+ auto * last_entry = reinterpret_cast<linked_directory_entry *>(buffer.data() + offset);
+ auto const last_entry_actual_len = static_cast<uint16_t>((8u + last_entry->name_len + 3u) & ~3u);
+ auto const free_space = last_entry->rec_len - last_entry_actual_len;
+
+ if (free_space >= needed_rec_len)
+ {
+ last_entry->rec_len = last_entry_actual_len;
+ offset += last_entry_actual_len;
+
+ auto * new_entry = reinterpret_cast<linked_directory_entry *>(buffer.data() + offset);
+ new_entry->inode = child_inode_number;
+ new_entry->rec_len = static_cast<uint16_t>(block_size() - offset);
+ new_entry->name_len = name_len;
+ new_entry->file_type = 0x01; // TODO handle mode correctly
+ kstd::libc::memcpy(new_entry->name.data(), name.data(), name_len);
+
+ return write_block(*global_block_number, buffer.data()).transform([](auto) {});
+ }
+
+ if (!ext2_parent->append_blocks(1))
+ {
+ return kstd::failure(ext2_errc::not_enough_free_blocks);
+ }
+
+ auto new_last_block_index = inode_block_count(ext2_parent->data()) - 1;
+
+ auto new_global_block = map_inode_block_index_to_global_block_number(new_last_block_index, ext2_parent->data());
+ if (!new_global_block)
+ {
+ return kstd::failure(new_global_block.error());
+ }
+
+ kstd::libc::memset(buffer.data(), 0, block_size());
+
+ auto * entry = reinterpret_cast<linked_directory_entry *>(buffer.data());
+ entry->inode = child_inode_number;
+ entry->rec_len = static_cast<uint16_t>(block_size());
+ entry->name_len = name_len;
+ entry->file_type = 0x01; // TODO handle mode correctly
+ kstd::libc::memcpy(entry->name.data(), name.data(), name_len);
+
+ return write_block(static_cast<uint32_t>(*new_global_block), buffer.data()).and_then([&](auto) {
+ return write_inode(ext2_parent->number(), ext2_parent->data());
+ });
}
auto filesystem::read_inode(uint32_t inode_number) const -> kstd::result<kstd::shared_ptr<inode>>
diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp
index eaa42d01..b3279e09 100644
--- a/kernel/kernel/filesystem/ext2/filesystem.hpp
+++ b/kernel/kernel/filesystem/ext2/filesystem.hpp
@@ -166,7 +166,7 @@ namespace kernel::filesystem::ext2
[[nodiscard]] auto indirect_levels() const -> std::array<indirect_level, 3>;
auto allocate_inode() -> kstd::result<uint32_t>;
- auto add_directory_entry(inode * ext2_parent, std::string_view name, uint32_t inode_number, uint16_t mode)
+ auto add_directory_entry(inode * ext2_parent, std::string_view name, uint32_t child_inode_number, uint16_t mode)
-> kstd::result<void>;
[[nodiscard]] auto calculate_inode_offset(uint32_t inode_number) const -> kstd::result<size_t>;
diff --git a/kernel/kernel/filesystem/ext2/inode.cpp b/kernel/kernel/filesystem/ext2/inode.cpp
index f95ddaad..0c8da9d0 100644
--- a/kernel/kernel/filesystem/ext2/inode.cpp
+++ b/kernel/kernel/filesystem/ext2/inode.cpp
@@ -212,4 +212,9 @@ namespace kernel::filesystem::ext2
m_data.size = static_cast<uint32_t>(new_size);
}
+ [[nodiscard]] auto inode::number() const -> uint32_t
+ {
+ return m_inode_number;
+ }
+
} // namespace kernel::filesystem::ext2
diff --git a/kernel/kernel/filesystem/ext2/inode.hpp b/kernel/kernel/filesystem/ext2/inode.hpp
index f01b9f1e..ac17e6ab 100644
--- a/kernel/kernel/filesystem/ext2/inode.hpp
+++ b/kernel/kernel/filesystem/ext2/inode.hpp
@@ -68,6 +68,13 @@ namespace kernel::filesystem::ext2
auto write(void const * buffer, size_t offset, size_t size) -> kstd::result<size_t> override;
/**
+ @brief Appends the specified number of blocks to the inode.
+ @param count The number of blocks to append.
+ @return true if the blocks were successfully appended, false otherwise.
+ */
+ auto append_blocks(size_t count) -> bool;
+
+ /**
@brief Get the data associated with this inode.
@return A reference to the inode data.
*/
@@ -103,9 +110,13 @@ namespace kernel::filesystem::ext2
*/
auto set_size(uint64_t new_size) -> void;
- private:
- auto append_blocks(size_t count) -> bool;
+ /**
+ @brief Get the inode number of this inode.
+ @return The inode number.
+ */
+ [[nodiscard]] auto number() const -> uint32_t;
+ private:
filesystem * m_filesystem;
uint32_t m_inode_number{};
inode_data m_data{};