diff options
Diffstat (limited to 'kernel/src/filesystem/ext2/inode.cpp')
| -rw-r--r-- | kernel/src/filesystem/ext2/inode.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/kernel/src/filesystem/ext2/inode.cpp b/kernel/src/filesystem/ext2/inode.cpp new file mode 100644 index 0000000..35a32ee --- /dev/null +++ b/kernel/src/filesystem/ext2/inode.cpp @@ -0,0 +1,111 @@ +#include <kernel/filesystem/ext2/inode.hpp> + +#include <kernel/filesystem/ext2/filesystem.hpp> +#include <kernel/filesystem/inode.hpp> + +#include <kapi/system.hpp> + +#include <kstd/cstring> + +#include <algorithm> +#include <cstddef> +#include <cstdint> + +namespace kernel::filesystem::ext2 +{ + inode::inode(filesystem const * fs, inode_data const & data) + : m_filesystem(fs) + , m_data(data) + { + if (!m_filesystem) + { + kapi::system::panic("[EXT2] ext2::inode constructed with filesystem null pointer"); + } + } + + auto inode::read(void * buffer, size_t offset, size_t size) const -> size_t + { + auto const max_readable = this->size() - offset; + auto const requested_size = std::min(size, max_readable); + + if (is_symbolic_link() && this->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->block_size(); + auto in_block_offset = offset % m_filesystem->block_size(); + + auto bytes_read = 0uz; + + while (bytes_read < requested_size) + { + auto const block_number = m_filesystem->map_inode_block_index_to_global_block_number(block_index, m_data); + if (block_number == -1) + { + break; + } + + auto const bytes_to_read = std::min(requested_size - bytes_read, m_filesystem->block_size() - in_block_offset); + if (block_number == 0) + { + kstd::libc::memset(static_cast<uint8_t *>(buffer) + bytes_read, 0, bytes_to_read); + bytes_read += bytes_to_read; + } + else + { + auto const block_start_offset = block_number * m_filesystem->block_size(); + auto const read_offset = block_start_offset + in_block_offset; + + bytes_read += m_filesystem->backing_inode()->read(static_cast<uint8_t *>(buffer) + bytes_read, read_offset, + bytes_to_read); + } + + block_index++; + in_block_offset = 0; // After the first block, we always start at the beginning of the block + } + + return bytes_read; + } + + auto inode::write(void const *, size_t, size_t) -> size_t + { + 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; + } + + auto inode::size() const -> uint64_t + { + uint64_t size = m_data.size; + + if (m_filesystem->revision_level() > constants::good_old_revision && is_regular()) + { + size |= static_cast<uint64_t>(m_data.dir_acl) << 32; + } + + return size; + } + +} // namespace kernel::filesystem::ext2 |
