diff options
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.cpp | 87 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/ext2/filesystem.hpp | 19 |
2 files changed, 100 insertions, 6 deletions
diff --git a/kernel/kernel/filesystem/ext2/filesystem.cpp b/kernel/kernel/filesystem/ext2/filesystem.cpp index 8860f213..7b0bce0e 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.cpp +++ b/kernel/kernel/filesystem/ext2/filesystem.cpp @@ -153,6 +153,93 @@ namespace kernel::filesystem::ext2 return kstd::failure(vfs_errc::no_such_file_or_directory); } + auto filesystem::create_inode(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) + -> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>> + { + if (!parent) + { + return kstd::failure(vfs_errc::invalid_inode); + } + + if (!parent->is_directory()) + { + return kstd::failure(vfs_errc::not_a_directory); + } + + auto maybe_inode_number = allocate_inode(); + if (!maybe_inode_number) + { + return kstd::failure(maybe_inode_number.error()); + } + + auto inode_number = maybe_inode_number.value(); + + inode_data new_inode_data{}; + + // TODO set mode depending on type/mode + new_inode_data.mode = 0x8000; + new_inode_data.size = 0; + new_inode_data.dir_acl = 0; + new_inode_data.links_count = 1; + new_inode_data.blocks = 0; + new_inode_data.block.fill(0); + + if (auto write_result = write_inode(inode_number, new_inode_data); !write_result) + { + return kstd::failure(write_result.error()); + } + + // add directory entry to parent + if (auto * ext2_parent = static_cast<inode *>(parent.get())) + { + if (auto result = add_directory_entry(ext2_parent, name, inode_number, new_inode_data.mode); + !result) // TODO handle mode correctly + { + return kstd::failure(result.error()); + } + // TODO + } + } + + auto filesystem::add_directory_entry(inode * ext2_parent, std::string_view name, uint32_t inode_number, 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 global_block_number = + map_inode_block_index_to_global_block_number(last_block_index, ext2_parent->data()); + + if (!global_block_number) + { + return kstd::failure(global_block_number.error()); + } + + kstd::vector<uint8_t> buffer(block_size()); + if (auto read_result = read_block(*global_block_number, buffer.data()); !read_result) + { + return kstd::failure(read_result.error()); + } + + auto offset = 0uz; + while (true) + { + auto const * entry = reinterpret_cast<linked_directory_entry const *>(buffer.data() + offset); + + if (offset + entry->rec_len >= block_size()) + { + break; + } + + offset += entry->rec_len; + } + + auto const * last_entry = reinterpret_cast<linked_directory_entry const *>(buffer.data() + offset); + + auto const last_entry_actual_length = 0; // TODO + + return kstd::success(); + } + auto filesystem::read_inode(uint32_t inode_number) const -> kstd::result<kstd::shared_ptr<inode>> { if (auto inode_offset = calculate_inode_offset(inode_number)) diff --git a/kernel/kernel/filesystem/ext2/filesystem.hpp b/kernel/kernel/filesystem/ext2/filesystem.hpp index 33b7b95c..eaa42d01 100644 --- a/kernel/kernel/filesystem/ext2/filesystem.hpp +++ b/kernel/kernel/filesystem/ext2/filesystem.hpp @@ -68,6 +68,15 @@ namespace kernel::filesystem::ext2 -> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>> override; /** + @brief Creates a new inode with @p name within a @p parent directory. + @param parent The parent directory inode. + @param name The name of the inode to create. + @return A pointer to the created inode, or a null pointer if creation failed. + */ + [[nodiscard]] auto create_inode(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) + -> kstd::result<kstd::shared_ptr<kernel::filesystem::inode>>; // TODO move into base class and override + + /** @brief Gets the size of a block in the filesystem. @return The size of a block in bytes. */ @@ -103,12 +112,6 @@ namespace kernel::filesystem::ext2 auto allocate_blocks(size_t count) -> kstd::result<kstd::vector<uint32_t>>; /** - @brief Allocates a new inode. - @return The inode number within the filesystem. - */ - auto allocate_inode() -> kstd::result<uint32_t>; - - /** @brief Gets the size of an inode in the filesystem. @return The size of an inode in bytes. */ @@ -162,6 +165,10 @@ 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) + -> kstd::result<void>; + [[nodiscard]] auto calculate_inode_offset(uint32_t inode_number) const -> kstd::result<size_t>; [[nodiscard]] auto read_inode(uint32_t inode_number) const -> kstd::result<kstd::shared_ptr<inode>>; [[nodiscard]] auto read_block_number_at_index(uint32_t block_number, size_t index) const -> kstd::result<uint32_t>; |
