⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext2.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	}

	// 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 + -