#include #include #include #include #include #include #include #include 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(m_data.block.data()); kstd::libc::memcpy(static_cast(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(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(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(m_data.dir_acl) << 32; } return size; } } // namespace kernel::filesystem::ext2