diff options
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.cpp | 62 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.hpp | 2 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/inode.cpp | 5 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/inode.hpp | 15 |
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{}; |
