📄 rfsd.c
字号:
/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: rfsd.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brant閚.
* HOMEPAGE:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "rfsd.h"
// TODO: turn off (turns off warning about returning without return value, so I could easily disable code sections)
#pragma warning(disable : 4716)
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdLoadSuper)
#pragma alloc_text(PAGE, RfsdSaveSuper)
#pragma alloc_text(PAGE, RfsdLoadGroup)
#pragma alloc_text(PAGE, RfsdSaveGroup)
#pragma alloc_text(PAGE, RfsdLoadInode)
#pragma alloc_text(PAGE, RfsdSaveInode)
#pragma alloc_text(PAGE, RfsdLoadBlock)
#pragma alloc_text(PAGE, RfsdSaveBlock)
#pragma alloc_text(PAGE, RfsdSaveBuffer)
#pragma alloc_text(PAGE, RfsdGetBlock)
#pragma alloc_text(PAGE, RfsdBlockMap)
#pragma alloc_text(PAGE, RfsdBuildBDL)
#pragma alloc_text(PAGE, RfsdBuildBDL2)
#pragma alloc_text(PAGE, RfsdNewBlock)
#pragma alloc_text(PAGE, RfsdFreeBlock)
#pragma alloc_text(PAGE, RfsdExpandBlock)
#pragma alloc_text(PAGE, RfsdExpandInode)
#pragma alloc_text(PAGE, RfsdNewInode)
#pragma alloc_text(PAGE, RfsdFreeInode)
#pragma alloc_text(PAGE, RfsdAddEntry)
#pragma alloc_text(PAGE, RfsdRemoveEntry)
#pragma alloc_text(PAGE, RfsdTruncateBlock)
#pragma alloc_text(PAGE, RfsdTruncateInode)
#pragma alloc_text(PAGE, RfsdAddMcbEntry)
#pragma alloc_text(PAGE, RfsdRemoveMcbEntry)
#pragma alloc_text(PAGE, RfsdLookupMcbEntry)
#pragma alloc_text(PAGE, SuperblockContainsMagicKey)
#pragma alloc_text(PAGE, DetermineOnDiskKeyFormat)
#pragma alloc_text(PAGE, FillInMemoryKey)
#pragma alloc_text(PAGE, CompareShortKeys)
#pragma alloc_text(PAGE, CompareKeysWithoutOffset)
#pragma alloc_text(PAGE, CompareKeys)
#pragma alloc_text(PAGE, NavigateToLeafNode)
#pragma alloc_text(PAGE, _NavigateToLeafNode)
#pragma alloc_text(PAGE, RfsdParseFilesystemTree)
#endif
/* FUNCTIONS ***************************************************************/
PRFSD_SUPER_BLOCK
RfsdLoadSuper(IN PRFSD_VCB Vcb,
IN BOOLEAN bVerify )
{
NTSTATUS Status;
PRFSD_SUPER_BLOCK RfsdSb = NULL;
RfsdSb = (PRFSD_SUPER_BLOCK) ExAllocatePool( PagedPool,
SUPER_BLOCK_SIZE);
if (!RfsdSb) {
return NULL;
}
Status = RfsdReadDisk(
Vcb,
(ULONGLONG) SUPER_BLOCK_OFFSET,
SUPER_BLOCK_SIZE,
(PVOID) RfsdSb,
bVerify );
if (!NT_SUCCESS(Status)) {
RfsdPrint((DBG_ERROR, "RfsdReadDisk: Read Block Device error.\n"));
ExFreePool(RfsdSb);
return NULL;
}
return RfsdSb;
}
BOOLEAN
RfsdSaveSuper( IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb )
{
DbgBreak();
#if DISABLED
LONGLONG Offset;
BOOLEAN bRet;
Offset = (LONGLONG) SUPER_BLOCK_OFFSET;
bRet = RfsdSaveBuffer( IrpContext,
Vcb,
Offset,
SUPER_BLOCK_SIZE,
Vcb->SuperBlock );
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
RfsdStartFloppyFlushDpc(Vcb, NULL, NULL);
}
return bRet;
#endif
}
#if DISABLED
BOOLEAN
RfsdLoadGroup(IN PRFSD_VCB Vcb)
{
ULONG Size;
PVOID Buffer;
LONGLONG Lba;
NTSTATUS Status;
PRFSD_SUPER_BLOCK sb;
sb = Vcb->SuperBlock;
Vcb->BlockSize = RFSD_MIN_BLOCK << sb->s_log_block_size;
Vcb->SectorBits = RfsdLog2(SECTOR_SIZE);
ASSERT(BLOCK_BITS == RfsdLog2(BLOCK_SIZE));
Vcb->NumOfGroups = (sb->s_blocks_count - sb->s_first_data_block +
sb->s_blocks_per_group - 1) / sb->s_blocks_per_group;
Size = sizeof(RFSD_GROUP_DESC) * Vcb->NumOfGroups;
if (Vcb->BlockSize == RFSD_MIN_BLOCK) {
Lba = (LONGLONG)2 * Vcb->BlockSize;
}
if (Vcb->BlockSize > RFSD_MIN_BLOCK) {
Lba = (LONGLONG) (Vcb->BlockSize);
}
if (Lba == 0) {
return FALSE;
}
Buffer = ExAllocatePool(PagedPool, Size);
if (!Buffer) {
RfsdPrint((DBG_ERROR, "RfsdLoadSuper: no enough memory.\n"));
return FALSE;
}
RfsdPrint((DBG_USER, "RfsdLoadGroup: Lba=%I64xh Size=%xh\n", Lba, Size));
Status = RfsdReadDisk( Vcb,
Lba,
Size,
Buffer,
FALSE );
if (!NT_SUCCESS(Status)) {
ExFreePool(Buffer);
Buffer = NULL;
return FALSE;
}
/*
bPinned = CcPinRead(
Vcb->StreamObj,
Lba,
Size,
PIN_WAIT,
&(Vcb->GroupDescBcb),
&(Buffer));
if (!bPinned)
{
Vcb->GroupDesc = NULL;
return FALSE;
}
*/
Vcb->GroupDesc = (PRFSD_GROUP_DESC) Buffer;
return TRUE;
}
BOOLEAN
RfsdSaveGroup( IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN ULONG Group )
{
LONGLONG Offset;
BOOLEAN bRet;
if (Vcb->BlockSize == RFSD_MIN_BLOCK) {
Offset = (LONGLONG) (2 * Vcb->BlockSize);
} else {
Offset = (LONGLONG) (Vcb->BlockSize);
}
Offset += ((LONGLONG) sizeof(struct rfsd_group_desc) * Group);
bRet = RfsdSaveBuffer(
IrpContext,
Vcb,
Offset,
sizeof(struct rfsd_group_desc),
&(Vcb->GroupDesc[Group]) );
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
RfsdStartFloppyFlushDpc(Vcb, NULL, NULL);
}
return bRet;
}
#endif
/** Reads an inode structure off disk into the Inode object (which has been allocated, but not filled with any data) */
BOOLEAN
RfsdLoadInode (IN PRFSD_VCB Vcb,
IN PRFSD_KEY_IN_MEMORY pKey,
IN OUT PRFSD_INODE Inode)
{
NTSTATUS Status;
PRFSD_ITEM_HEAD pItemHeader = NULL;
PUCHAR pItemBuffer = NULL;
PUCHAR pBlockBuffer = NULL;
// Crate the target key for the stat item (stat items always have an offset of 0)
RFSD_KEY_IN_MEMORY TargetKey;
TargetKey = *pKey;
TargetKey.k_offset = 0x0;
TargetKey.k_type = RFSD_KEY_TYPE_v2_STAT_DATA;
RfsdPrint((DBG_FUNC, __FUNCTION__ "on %i, %i\n", TargetKey.k_dir_id, TargetKey.k_objectid));
//Load the stat data
Status = RfsdLoadItem(Vcb, &TargetKey,
&(pItemHeader), &(pItemBuffer), &(pBlockBuffer), NULL, //<
&CompareKeys
);
if (!NT_SUCCESS(Status))
{ if (pBlockBuffer) {ExFreePool(pBlockBuffer);} return FALSE; }
// Copy the item into the inode / stat data structure
RtlCopyMemory(Inode, pItemBuffer, sizeof(RFSD_INODE));
// Cleanup
if (pBlockBuffer)
ExFreePool(pBlockBuffer);
return TRUE;
}
BOOLEAN
RfsdSaveInode ( IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN ULONG Inode,
IN PRFSD_INODE RfsdInode)
{
DbgBreak();
#if DISABLED
LONGLONG Offset = 0;
LARGE_INTEGER CurrentTime;
BOOLEAN bRet;
KeQuerySystemTime(&CurrentTime);
RfsdInode->i_mtime = RfsdInode->i_atime =
(ULONG)(RfsdInodeTime(CurrentTime));
RfsdPrint((DBG_INFO, "RfsdSaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
Inode, RfsdInode->i_mode, RfsdInode->i_size));
if (!RfsdGetInodeLba(Vcb, Inode, &Offset)) {
RfsdPrint((DBG_ERROR, "RfsdSaveInode: error get inode(%xh)'s addr.\n", Inode));
return FALSE;
}
bRet = RfsdSaveBuffer(IrpContext, Vcb, Offset, sizeof(RFSD_INODE), RfsdInode);
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
RfsdStartFloppyFlushDpc(Vcb, NULL, NULL);
}
return bRet;
#endif
}
/** Just reads a block into a buffer */
BOOLEAN
RfsdLoadBlock (
IN PRFSD_VCB Vcb,
IN ULONG dwBlk, // A disk block ptr (a disk block number)
IN OUT PVOID Buffer ) // A buffer, which must be allocated to contain at least Vcb->BlockSize
{
IO_STATUS_BLOCK IoStatus;
LONGLONG Offset;
Offset = (LONGLONG) dwBlk;
Offset = Offset * Vcb->BlockSize;
if (!RfsdCopyRead(
Vcb->StreamObj,
(PLARGE_INTEGER)&Offset,
Vcb->BlockSize,
PIN_WAIT,
Buffer,
&IoStatus )) {
return FALSE;
}
if (!NT_SUCCESS(IoStatus.Status)) {
return FALSE;
}
return TRUE;
}
BOOLEAN
RfsdSaveBlock ( IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN ULONG dwBlk,
IN PVOID Buf )
{
DbgBreak();
#if DISABLED
LONGLONG Offset;
BOOLEAN bRet;
Offset = (LONGLONG) dwBlk;
Offset = Offset * Vcb->BlockSize;
bRet = RfsdSaveBuffer(IrpContext, Vcb, Offset, Vcb->BlockSize, Buf);
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
RfsdStartFloppyFlushDpc(Vcb, NULL, NULL);
}
return bRet;
#endif
}
BOOLEAN
RfsdSaveBuffer( IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN LONGLONG Offset,
IN ULONG Size,
IN PVOID Buf )
{
PBCB Bcb;
PVOID Buffer;
BOOLEAN bRet;
if( !CcPinRead( Vcb->StreamObj,
(PLARGE_INTEGER) (&Offset),
Size,
PIN_WAIT,
&Bcb,
&Buffer )) {
RfsdPrint((DBG_ERROR, "RfsdSaveBuffer: PinReading error ...\n"));
return FALSE;
}
__try {
RtlCopyMemory(Buffer, Buf, Size);
CcSetDirtyPinnedData(Bcb, NULL );
RfsdRepinBcb(IrpContext, Bcb);
SetFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
RfsdAddMcbEntry(Vcb, Offset, (LONGLONG)Size);
bRet = TRUE;
} __finally {
if (AbnormalTermination()) {
CcUnpinData(Bcb);
bRet = FALSE;
}
}
CcUnpinData(Bcb);
return bRet;
}
NTSTATUS
RfsdGetBlock(
IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN ULONG dwContent, // A ptr to a disk block (disk block number)
IN ULONG Index,
IN ULONG Layer,
IN BOOLEAN bAlloc,
OUT PULONG pBlock
)
{
DbgBreak();
#if DISABLED
NTSTATUS Status = STATUS_SUCCESS;
ULONG *pData = NULL;
ULONG i = 0, j = 0, temp = 1;
ULONG dwRet = 0;
ULONG dwBlk = 0;
if (Layer == 0) {
dwRet = dwContent;
} else if (Layer <= 3) {
/* allocate memory for pData to contain the block */
pData = (ULONG *)ExAllocatePool(NonPagedPool, Vcb->BlockSize);
if (!pData) {
RfsdPrint((DBG_ERROR, "RfsdGetBlock: no enough memory.\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
/* load the block dwContext into pData buffer */
if (!RfsdLoadBlock(Vcb, dwContent, pData)) {
ExFreePool(pData);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
temp = 1 << ((BLOCK_BITS - 2) * (Layer - 1));
i = Index / temp;
j = Index % temp;
dwBlk = pData[i];
#if DISABLED // WRITE MODE ONLY
if (dwBlk ==0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -