📄 ext2.c
字号:
}
// Make sure it is a directory inode
if ((InodePointer->i_mode & EXT2_S_IFMT) != EXT2_S_IFDIR)
{
FileSystemError("Inode is not a directory.");
return FALSE;
}
// Fill in file info struct so we can call Ext2ReadFile()
RtlZeroMemory(&DirectoryFileInfo, sizeof(EXT2_FILE_INFO));
DirectoryFileInfo.DriveNumber = Ext2DriveNumber;
DirectoryFileInfo.FileBlockList = Ext2ReadBlockPointerList(InodePointer);
DirectoryFileInfo.FilePointer = 0;
DirectoryFileInfo.FileSize = Ext2GetInodeFileSize(InodePointer);
if (DirectoryFileInfo.FileBlockList == NULL)
{
return FALSE;
}
//
// Now allocate the memory to hold the group descriptors
//
*DirectoryBuffer = (PEXT2_DIR_ENTRY)MmAllocateMemory(DirectoryFileInfo.FileSize);
//
// Make sure we got the memory
//
if (*DirectoryBuffer == NULL)
{
MmFreeMemory(DirectoryFileInfo.FileBlockList);
FileSystemError("Out of memory.");
return FALSE;
}
// Now read the root directory data
if (!Ext2ReadFile(&DirectoryFileInfo, DirectoryFileInfo.FileSize, NULL, *DirectoryBuffer))
{
MmFreeMemory(*DirectoryBuffer);
*DirectoryBuffer = NULL;
MmFreeMemory(DirectoryFileInfo.FileBlockList);
return FALSE;
}
MmFreeMemory(DirectoryFileInfo.FileBlockList);
return TRUE;
}
BOOLEAN Ext2ReadBlock(ULONG BlockNumber, PVOID Buffer)
{
CHAR ErrorString[80];
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber, Buffer));
// Make sure its a valid block
if (BlockNumber > Ext2SuperBlock->s_blocks_count)
{
sprintf(ErrorString, "Error reading block %d - block out of range.", (int) BlockNumber);
FileSystemError(ErrorString);
return FALSE;
}
// Check to see if this is a sparse block
if (BlockNumber == 0)
{
DbgPrint((DPRINT_FILESYSTEM, "Block is part of a sparse file. Zeroing input buffer.\n"));
RtlZeroMemory(Buffer, Ext2BlockSizeInBytes);
return TRUE;
}
return Ext2ReadVolumeSectors(Ext2DriveNumber, (ULONGLONG)BlockNumber * Ext2BlockSizeInSectors, Ext2BlockSizeInSectors, Buffer);
}
/*
* Ext2ReadPartialBlock()
* Reads part of a block into memory
*/
BOOLEAN Ext2ReadPartialBlock(ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
{
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadPartialBlock() BlockNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", BlockNumber, StartingOffset, Length, Buffer));
if (!Ext2ReadBlock(BlockNumber, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
memcpy(Buffer, (PVOID)((ULONG_PTR)FILESYSBUFFER + StartingOffset), Length);
return TRUE;
}
ULONG Ext2GetGroupDescBlockNumber(ULONG Group)
{
return (((Group * sizeof(EXT2_GROUP_DESC)) / Ext2GroupDescPerBlock) + Ext2SuperBlock->s_first_data_block + 1);
}
ULONG Ext2GetGroupDescOffsetInBlock(ULONG Group)
{
return ((Group * sizeof(EXT2_GROUP_DESC)) % Ext2GroupDescPerBlock);
}
ULONG Ext2GetInodeGroupNumber(ULONG Inode)
{
return ((Inode - 1) / Ext2SuperBlock->s_inodes_per_group);
}
ULONG Ext2GetInodeBlockNumber(ULONG Inode)
{
return (((Inode - 1) % Ext2SuperBlock->s_inodes_per_group) / Ext2InodesPerBlock);
}
ULONG Ext2GetInodeOffsetInBlock(ULONG Inode)
{
return (((Inode - 1) % Ext2SuperBlock->s_inodes_per_group) % Ext2InodesPerBlock);
}
BOOLEAN Ext2ReadInode(ULONG Inode, PEXT2_INODE InodeBuffer)
{
ULONG InodeGroupNumber;
ULONG InodeBlockNumber;
ULONG InodeOffsetInBlock;
CHAR ErrorString[80];
EXT2_GROUP_DESC GroupDescriptor;
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadInode() Inode = %d\n", Inode));
// Make sure its a valid inode
if ((Inode < 1) || (Inode > Ext2SuperBlock->s_inodes_count))
{
sprintf(ErrorString, "Error reading inode %ld - inode out of range.", Inode);
FileSystemError(ErrorString);
return FALSE;
}
// Get inode group & block number and offset in block
InodeGroupNumber = Ext2GetInodeGroupNumber(Inode);
InodeBlockNumber = Ext2GetInodeBlockNumber(Inode);
InodeOffsetInBlock = Ext2GetInodeOffsetInBlock(Inode);
DbgPrint((DPRINT_FILESYSTEM, "InodeGroupNumber = %d\n", InodeGroupNumber));
DbgPrint((DPRINT_FILESYSTEM, "InodeBlockNumber = %d\n", InodeBlockNumber));
DbgPrint((DPRINT_FILESYSTEM, "InodeOffsetInBlock = %d\n", InodeOffsetInBlock));
// Read the group descriptor
if (!Ext2ReadGroupDescriptor(InodeGroupNumber, &GroupDescriptor))
{
return FALSE;
}
// Add the start block of the inode table to the inode block number
InodeBlockNumber += GroupDescriptor.bg_inode_table;
DbgPrint((DPRINT_FILESYSTEM, "InodeBlockNumber (after group desc correction) = %d\n", InodeBlockNumber));
// Read the block
if (!Ext2ReadBlock(InodeBlockNumber, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
// Copy the data to their buffer
RtlCopyMemory(InodeBuffer, (PVOID)(FILESYSBUFFER + (InodeOffsetInBlock * EXT3_INODE_SIZE(Ext2SuperBlock))), sizeof(EXT2_INODE));
DbgPrint((DPRINT_FILESYSTEM, "Dumping inode information:\n"));
DbgPrint((DPRINT_FILESYSTEM, "i_mode = 0x%x\n", InodeBuffer->i_mode));
DbgPrint((DPRINT_FILESYSTEM, "i_uid = %d\n", InodeBuffer->i_uid));
DbgPrint((DPRINT_FILESYSTEM, "i_size = %d\n", InodeBuffer->i_size));
DbgPrint((DPRINT_FILESYSTEM, "i_atime = %d\n", InodeBuffer->i_atime));
DbgPrint((DPRINT_FILESYSTEM, "i_ctime = %d\n", InodeBuffer->i_ctime));
DbgPrint((DPRINT_FILESYSTEM, "i_mtime = %d\n", InodeBuffer->i_mtime));
DbgPrint((DPRINT_FILESYSTEM, "i_dtime = %d\n", InodeBuffer->i_dtime));
DbgPrint((DPRINT_FILESYSTEM, "i_gid = %d\n", InodeBuffer->i_gid));
DbgPrint((DPRINT_FILESYSTEM, "i_links_count = %d\n", InodeBuffer->i_links_count));
DbgPrint((DPRINT_FILESYSTEM, "i_blocks = %d\n", InodeBuffer->i_blocks));
DbgPrint((DPRINT_FILESYSTEM, "i_flags = 0x%x\n", InodeBuffer->i_flags));
DbgPrint((DPRINT_FILESYSTEM, "i_block[EXT3_N_BLOCKS (%d)] =\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d,\n%d\n", EXT3_N_BLOCKS, InodeBuffer->i_block[0], InodeBuffer->i_block[1], InodeBuffer->i_block[2], InodeBuffer->i_block[3], InodeBuffer->i_block[4], InodeBuffer->i_block[5], InodeBuffer->i_block[6], InodeBuffer->i_block[7], InodeBuffer->i_block[8], InodeBuffer->i_block[9], InodeBuffer->i_block[10], InodeBuffer->i_block[11], InodeBuffer->i_block[12], InodeBuffer->i_block[13], InodeBuffer->i_block[14]));
DbgPrint((DPRINT_FILESYSTEM, "i_generation = %d\n", InodeBuffer->i_generation));
DbgPrint((DPRINT_FILESYSTEM, "i_file_acl = %d\n", InodeBuffer->i_file_acl));
DbgPrint((DPRINT_FILESYSTEM, "i_dir_acl = %d\n", InodeBuffer->i_dir_acl));
DbgPrint((DPRINT_FILESYSTEM, "i_faddr = %d\n", InodeBuffer->i_faddr));
DbgPrint((DPRINT_FILESYSTEM, "l_i_frag = %d\n", InodeBuffer->osd2.linux2.l_i_frag));
DbgPrint((DPRINT_FILESYSTEM, "l_i_fsize = %d\n", InodeBuffer->osd2.linux2.l_i_fsize));
DbgPrint((DPRINT_FILESYSTEM, "l_i_uid_high = %d\n", InodeBuffer->osd2.linux2.l_i_uid_high));
DbgPrint((DPRINT_FILESYSTEM, "l_i_gid_high = %d\n", InodeBuffer->osd2.linux2.l_i_gid_high));
return TRUE;
}
BOOLEAN Ext2ReadGroupDescriptor(ULONG Group, PEXT2_GROUP_DESC GroupBuffer)
{
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadGroupDescriptor()\n"));
/*if (!Ext2ReadBlock(Ext2GetGroupDescBlockNumber(Group), (PVOID)FILESYSBUFFER))
{
return FALSE;
}
RtlCopyMemory(GroupBuffer, (PVOID)(FILESYSBUFFER + Ext2GetGroupDescOffsetInBlock(Group)), sizeof(EXT2_GROUP_DESC));*/
RtlCopyMemory(GroupBuffer, &Ext2GroupDescriptors[Group], sizeof(EXT2_GROUP_DESC));
DbgPrint((DPRINT_FILESYSTEM, "Dumping group descriptor:\n"));
DbgPrint((DPRINT_FILESYSTEM, "bg_block_bitmap = %d\n", GroupBuffer->bg_block_bitmap));
DbgPrint((DPRINT_FILESYSTEM, "bg_inode_bitmap = %d\n", GroupBuffer->bg_inode_bitmap));
DbgPrint((DPRINT_FILESYSTEM, "bg_inode_table = %d\n", GroupBuffer->bg_inode_table));
DbgPrint((DPRINT_FILESYSTEM, "bg_free_blocks_count = %d\n", GroupBuffer->bg_free_blocks_count));
DbgPrint((DPRINT_FILESYSTEM, "bg_free_inodes_count = %d\n", GroupBuffer->bg_free_inodes_count));
DbgPrint((DPRINT_FILESYSTEM, "bg_used_dirs_count = %d\n", GroupBuffer->bg_used_dirs_count));
return TRUE;
}
ULONG* Ext2ReadBlockPointerList(PEXT2_INODE Inode)
{
ULONGLONG FileSize;
ULONG BlockCount;
ULONG* BlockList;
ULONG CurrentBlockInList;
ULONG CurrentBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadBlockPointerList()\n"));
// Get the number of blocks this file occupies
// I would just use Inode->i_blocks but it
// doesn't seem to be the number of blocks
// the file size corresponds to, but instead
// it is much bigger.
//BlockCount = Inode->i_blocks;
FileSize = Ext2GetInodeFileSize(Inode);
FileSize = ROUND_UP(FileSize, Ext2BlockSizeInBytes);
BlockCount = (FileSize / Ext2BlockSizeInBytes);
// Allocate the memory for the block list
BlockList = MmAllocateMemory(BlockCount * sizeof(ULONG));
if (BlockList == NULL)
{
return NULL;
}
RtlZeroMemory(BlockList, BlockCount * sizeof(ULONG));
CurrentBlockInList = 0;
// Copy the direct block pointers
for (CurrentBlock=0; CurrentBlockInList<BlockCount && CurrentBlock<EXT3_NDIR_BLOCKS; CurrentBlock++)
{
BlockList[CurrentBlockInList] = Inode->i_block[CurrentBlock];
CurrentBlockInList++;
}
// Copy the indirect block pointers
if (CurrentBlockInList < BlockCount)
{
if (!Ext2CopyIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->i_block[EXT3_IND_BLOCK]))
{
MmFreeMemory(BlockList);
return FALSE;
}
}
// Copy the double indirect block pointers
if (CurrentBlockInList < BlockCount)
{
if (!Ext2CopyDoubleIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->i_block[EXT3_DIND_BLOCK]))
{
MmFreeMemory(BlockList);
return FALSE;
}
}
// Copy the triple indirect block pointers
if (CurrentBlockInList < BlockCount)
{
if (!Ext2CopyTripleIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->i_block[EXT3_TIND_BLOCK]))
{
MmFreeMemory(BlockList);
return FALSE;
}
}
return BlockList;
}
ULONGLONG Ext2GetInodeFileSize(PEXT2_INODE Inode)
{
if ((Inode->i_mode & EXT2_S_IFMT) == EXT2_S_IFDIR)
{
return (ULONGLONG)(Inode->i_size);
}
else
{
return ((ULONGLONG)(Inode->i_size) | ((ULONGLONG)(Inode->i_dir_acl) << 32));
}
}
BOOLEAN Ext2CopyIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
{
ULONG* BlockBuffer = (ULONG*)FILESYSBUFFER;
ULONG CurrentBlock;
ULONG BlockPointersPerBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyIndirectBlockPointers() BlockCount = %d\n", BlockCount));
BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG);
if (!Ext2ReadBlock(IndirectBlock, BlockBuffer))
{
return FALSE;
}
for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
{
BlockList[(*CurrentBlockInList)] = BlockBuffer[CurrentBlock];
(*CurrentBlockInList)++;
}
return TRUE;
}
BOOLEAN Ext2CopyDoubleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock)
{
ULONG* BlockBuffer;
ULONG CurrentBlock;
ULONG BlockPointersPerBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyDoubleIndirectBlockPointers() BlockCount = %d\n", BlockCount));
BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG);
BlockBuffer = (ULONG*)MmAllocateMemory(Ext2BlockSizeInBytes);
if (BlockBuffer == NULL)
{
return FALSE;
}
if (!Ext2ReadBlock(DoubleIndirectBlock, BlockBuffer))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
{
if (!Ext2CopyIndirectBlockPointers(BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
}
MmFreeMemory(BlockBuffer);
return TRUE;
}
BOOLEAN Ext2CopyTripleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock)
{
ULONG* BlockBuffer;
ULONG CurrentBlock;
ULONG BlockPointersPerBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyTripleIndirectBlockPointers() BlockCount = %d\n", BlockCount));
BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG);
BlockBuffer = (ULONG*)MmAllocateMemory(Ext2BlockSizeInBytes);
if (BlockBuffer == NULL)
{
return FALSE;
}
if (!Ext2ReadBlock(TripleIndirectBlock, BlockBuffer))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
{
if (!Ext2CopyDoubleIndirectBlockPointers(BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
}
MmFreeMemory(BlockBuffer);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -