diff --git a/kernel/src/fs/ext2/FileSystem.h b/kernel/src/fs/ext2/FileSystem.h index f7f424a0..9bc06762 100644 --- a/kernel/src/fs/ext2/FileSystem.h +++ b/kernel/src/fs/ext2/FileSystem.h @@ -81,6 +81,8 @@ namespace Ext2 static_assert(sizeof(BlockGroupDescriptor) == 32); static_assert(sizeof(RawInode) == 128); + class Inode; + class FileSystem : public VFS::FileSystem { public: @@ -149,5 +151,7 @@ namespace Ext2 HashMap> m_inode_cache; HashMap m_block_group_descriptor_cache; + + friend class Inode; }; } diff --git a/kernel/src/fs/ext2/Inode.cpp b/kernel/src/fs/ext2/Inode.cpp index e1af5fd1..96a9d29d 100644 --- a/kernel/src/fs/ext2/Inode.cpp +++ b/kernel/src/fs/ext2/Inode.cpp @@ -6,8 +6,64 @@ namespace Ext2 { } - Result Inode::read(u8* /*buf*/, usize /*offset*/, usize /*length*/) const + Result Inode::read(u8* buf, usize offset, usize length) const { - fail("FIXME: Ext2::Inode::read()"); + if (length == 0) return 0; + + if (offset > size()) return 0; + if (offset + length > size()) length = size() - offset; + + const usize block_size = m_fs->m_block_size; + + usize to_read = length; + + if (offset % block_size) + { + usize block_offset = (offset % block_size); + usize block = find_block(offset / block_size); + usize size_to_read = block_size - block_offset; + + usize host_offset = (block * block_size) + block_offset; + + // FIXME: Cache this data. + TRY(m_fs->m_host_device->read(buf, host_offset, size_to_read)); + + to_read -= size_to_read; + buf += size_to_read; + offset += size_to_read; + } + + while (to_read >= block_size) + { + usize block = find_block(offset / block_size); + + usize host_offset = block * block_size; + + // FIXME: Cache this data. + TRY(m_fs->m_host_device->read(buf, host_offset, block_size)); + + to_read -= block_size; + buf += block_size; + offset += block_size; + } + + if (to_read > 0) + { + usize block = find_block(offset / block_size); + + usize host_offset = block * block_size; + + // FIXME: Cache this data. + TRY(m_fs->m_host_device->read(buf, host_offset, to_read)); + } + + return length; + } + + usize Inode::find_block(usize index) const + { + expect(index < 12, "ext2: Finding blocks in the indirect pointers is not yet supported"); + + return m_raw_inode.direct_pointers[index]; } } diff --git a/kernel/src/fs/ext2/Inode.h b/kernel/src/fs/ext2/Inode.h index 0e69bd33..53cfd2b8 100644 --- a/kernel/src/fs/ext2/Inode.h +++ b/kernel/src/fs/ext2/Inode.h @@ -94,6 +94,8 @@ namespace Ext2 FileSystem* m_fs; ino_t m_inum; + usize find_block(usize index) const; + friend class FileSystem; }; }