2023-07-05 22:56:08 -07:00
|
|
|
#include "fs/ext2/ext2_driver.h"
|
|
|
|
|
2023-07-06 10:40:55 -07:00
|
|
|
#include <glacier/string/string.h>
|
2023-07-05 22:56:08 -07:00
|
|
|
#include <mammoth/debug.h>
|
2023-07-06 10:40:55 -07:00
|
|
|
|
2023-07-05 23:19:25 -07:00
|
|
|
glcr::ErrorOr<Ext2Driver> Ext2Driver::Init(ScopedDenaliClient&& denali) {
|
|
|
|
ASSIGN_OR_RETURN(Ext2BlockReader reader,
|
|
|
|
Ext2BlockReader::Init(glcr::Move(denali)));
|
2023-07-06 09:39:17 -07:00
|
|
|
Superblock* superblock = reader.GetSuperblock();
|
2023-07-05 23:19:25 -07:00
|
|
|
return Ext2Driver(glcr::Move(reader));
|
|
|
|
}
|
2023-07-05 22:56:08 -07:00
|
|
|
|
|
|
|
glcr::ErrorCode Ext2Driver::ProbePartition() {
|
2023-07-05 23:19:25 -07:00
|
|
|
Superblock* superblock = ext2_reader_.GetSuperblock();
|
|
|
|
if (superblock->magic != 0xEF53) {
|
2023-07-05 22:56:08 -07:00
|
|
|
dbgln("Invalid EXT2 magic code: %x");
|
|
|
|
return glcr::INVALID_ARGUMENT;
|
|
|
|
}
|
2023-07-05 23:19:25 -07:00
|
|
|
dbgln("Block size: 0x%x", 1024 << superblock->log_block_size);
|
2023-07-05 22:56:08 -07:00
|
|
|
|
2023-07-05 23:19:25 -07:00
|
|
|
dbgln("Blocks: 0x%x (0x%x per group)", superblock->blocks_count,
|
|
|
|
superblock->blocks_per_group);
|
|
|
|
dbgln("Inodes: 0x%x (0x%x per group)", superblock->inodes_count,
|
|
|
|
superblock->inodes_per_group);
|
2023-07-06 09:39:17 -07:00
|
|
|
dbgln("Inode size: 0x%x", superblock->inode_size);
|
2023-07-05 22:56:08 -07:00
|
|
|
|
2023-07-05 23:19:25 -07:00
|
|
|
dbgln("Mounts: 0x%x out of 0x%x", superblock->mnt_count,
|
|
|
|
superblock->max_mnt_count);
|
|
|
|
dbgln("State: %x", superblock->state);
|
2023-07-05 22:56:08 -07:00
|
|
|
|
2023-07-05 23:19:25 -07:00
|
|
|
dbgln("Created by: %x", superblock->creator_os);
|
2023-07-05 22:56:08 -07:00
|
|
|
|
|
|
|
ASSIGN_OR_RETURN(MappedMemoryRegion bgdt,
|
2023-07-06 09:58:26 -07:00
|
|
|
ext2_reader_.ReadBlocks(ext2_reader_.BgdtBlockNum(),
|
|
|
|
ext2_reader_.BgdtBlockSize()));
|
2023-07-05 22:56:08 -07:00
|
|
|
BlockGroupDescriptor* bgds =
|
|
|
|
reinterpret_cast<BlockGroupDescriptor*>(bgdt.vaddr());
|
|
|
|
|
2023-07-06 09:58:26 -07:00
|
|
|
uint64_t num_block_groups = ext2_reader_.NumberOfBlockGroups();
|
2023-07-05 22:56:08 -07:00
|
|
|
for (uint64_t i = 0; i < num_block_groups; i++) {
|
|
|
|
dbgln("BGD %x", i);
|
|
|
|
dbgln("Block Bitmap: %x", bgds[i].block_bitmap);
|
|
|
|
dbgln("Inode Bitmap: %x", bgds[i].inode_bitmap);
|
|
|
|
dbgln("Inode Table: %x", bgds[i].inode_table);
|
|
|
|
dbgln("Free blocks: %x", bgds[i].free_blocks_count);
|
|
|
|
dbgln("Free inodes: %x", bgds[i].free_inodes_count);
|
|
|
|
}
|
|
|
|
|
2023-07-06 09:39:17 -07:00
|
|
|
// FIXME: Move this to initialization.
|
|
|
|
inode_table_ =
|
|
|
|
glcr::UniquePtr<InodeTable>(new InodeTable(ext2_reader_, bgds));
|
|
|
|
|
|
|
|
ASSIGN_OR_RETURN(Inode * root, inode_table_->GetInode(2));
|
|
|
|
dbgln("Inode %lx", root);
|
|
|
|
dbgln("Mode: %x", root->mode);
|
|
|
|
dbgln("Blocks: %x", root->blocks);
|
|
|
|
dbgln("Size: %x", root->size);
|
|
|
|
|
2023-07-06 10:40:55 -07:00
|
|
|
return ProbeDirectory(root);
|
|
|
|
}
|
|
|
|
|
|
|
|
glcr::ErrorCode Ext2Driver::ProbeDirectory(Inode* inode) {
|
|
|
|
if (!(inode->mode & 0x4000)) {
|
|
|
|
dbgln("Probing non-directory");
|
|
|
|
return glcr::INVALID_ARGUMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This calculation is cursed.
|
|
|
|
uint64_t real_block_cnt =
|
|
|
|
(inode->blocks - 1) / (ext2_reader_.BlockSize() / 512) + 1;
|
|
|
|
|
|
|
|
if (real_block_cnt > 12) {
|
|
|
|
dbgln("Cant handle indirect blocks yet");
|
|
|
|
return glcr::FAILED_PRECONDITION;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint64_t i = 0; i < real_block_cnt; i++) {
|
|
|
|
dbgln("Getting block %lx", inode->block[i]);
|
|
|
|
ASSIGN_OR_RETURN(MappedMemoryRegion block,
|
|
|
|
ext2_reader_.ReadBlock(inode->block[i]));
|
|
|
|
uint64_t addr = block.vaddr();
|
|
|
|
while (addr < block.vaddr() + ext2_reader_.BlockSize()) {
|
|
|
|
DirEntry* entry = reinterpret_cast<DirEntry*>(addr);
|
2023-07-31 23:42:42 -07:00
|
|
|
dbgln("Entry: inode: %x, rec_len %x, name_len %x, file_type: %x",
|
|
|
|
entry->inode, entry->record_length, entry->name_len,
|
|
|
|
entry->file_type);
|
2023-07-06 10:40:55 -07:00
|
|
|
// FIXME: We need a method to construct a string that is *up to* a certain
|
|
|
|
// length. As illustrated below the provided name_len is 0x2e but the
|
|
|
|
// first character is \0 since this is the self-referencial inode.
|
|
|
|
glcr::String name(entry->name, entry->name_len);
|
|
|
|
dbgln("%s", name.cstr());
|
|
|
|
addr += entry->record_length;
|
|
|
|
}
|
|
|
|
}
|
2023-07-05 22:56:08 -07:00
|
|
|
return glcr::OK;
|
|
|
|
}
|