📄 ffs.c
字号:
for (i = 0; i < FFS_BLOCK_TYPES; i++)
{
if (Index < dwSizes[i])
{
if (i == 0)
dwBlk = (ULONGLONG)dinode2->di_db[Index]; /* 流立 */
else
dwBlk = (ULONGLONG)dinode2->di_ib[i - 1]; /* 埃立 */
#if 0
{
ULONGLONG dwRet = FFSv2GetBlock(Vcb, dwBlk, Index , i);
KdPrint(("FFSv2BlockMap: i : %d, Index : %d, dwBlk : %x, Data Block : %X\n", i, Index, dwRet, (dwRet * 0x400)));
return dwRet;
}
#else
return FFSv2GetBlock(Vcb, dwBlk, Index , i);
#endif
}
Index -= dwSizes[i];
}
return 0;
}
ULONG
FFSv1BuildBDL(
IN PFFS_IRP_CONTEXT IrpContext,
IN PFFS_VCB Vcb,
IN PFFSv1_INODE dinode1,
IN ULONGLONG Offset,
IN ULONG Size,
OUT PFFS_BDL *ffs_bdl)
{
ULONG nBeg, nEnd, nBlocks;
ULONG dwBlk, i;
ULONG dwBytes = 0;
LONGLONG Lba;
LONGLONG AllocSize;
ULONG Totalblocks;
PFFS_BDL ffsbdl;
*ffs_bdl = NULL;
Totalblocks = (dinode1->di_blocks);
AllocSize = FFSDataBlocks(Vcb, Totalblocks);
AllocSize = (AllocSize << BLOCK_BITS);
if ((LONGLONG)Offset >= AllocSize)
{
FFSPrint((DBG_ERROR, "FFSv1BuildBDL: beyond the file range.\n"));
return 0;
}
if ((LONGLONG)(Offset + Size) > AllocSize)
{
Size = (ULONG)(AllocSize - Offset);
}
nBeg = (ULONG)(Offset >> BLOCK_BITS);
nEnd = (ULONG)((Size + Offset + Vcb->BlockSize - 1) >> BLOCK_BITS);
#if DBG
KdPrint(("FFSv1BuildBDL() Offset : %x\n", Offset));
KdPrint(("FFSv1BuildBDL() Size : %x\n", Size));
KdPrint(("FFSv1BuildBDL() nBeg : %d, nEnd : %d\n", nBeg, nEnd));
#endif
nBlocks = 0;
if ((nEnd - nBeg) > 0)
{
ffsbdl = ExAllocatePool(PagedPool, sizeof(FFS_BDL) * (nEnd - nBeg));
if (ffsbdl)
{
RtlZeroMemory(ffsbdl, sizeof(FFS_BDL) * (nEnd - nBeg));
for (i = nBeg; i < nEnd; i++)
{
dwBlk = FFSv1BlockMap(Vcb, dinode1, i);
if (dwBlk > 0)
{
Lba = (LONGLONG)dwBlk;
Lba = Lba * SUPER_BLOCK->fs_fsize; // fragment size
if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1)
{
dwBytes = Size;
ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
ffsbdl[nBlocks].Length = dwBytes;
ffsbdl[nBlocks].Offset = 0;
nBlocks++;
}
else
{
if (i == nBeg)
{
dwBytes = Vcb->BlockSize - (ULONG)(Offset % (Vcb->BlockSize));
ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
ffsbdl[nBlocks].Length = dwBytes;
ffsbdl[nBlocks].Offset = 0;
nBlocks++;
}
else if (i == nEnd - 1)
{
if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
{
ffsbdl[nBlocks - 1].Length += Size - dwBytes;
}
else
{
ffsbdl[nBlocks].Lba = Lba;
ffsbdl[nBlocks].Length = Size - dwBytes;
ffsbdl[nBlocks].Offset = dwBytes;
nBlocks++;
}
dwBytes = Size;
}
else
{
if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
{
ffsbdl[nBlocks - 1].Length += Vcb->BlockSize;
}
else
{
ffsbdl[nBlocks].Lba = Lba;
ffsbdl[nBlocks].Length = Vcb->BlockSize;
ffsbdl[nBlocks].Offset = dwBytes;
nBlocks++;
}
dwBytes += Vcb->BlockSize;
}
}
}
else
{
break;
}
}
*ffs_bdl = ffsbdl;
return nBlocks;
}
}
// Error
return 0;
}
ULONG
FFSv2BuildBDL(
IN PFFS_IRP_CONTEXT IrpContext,
IN PFFS_VCB Vcb,
IN PFFSv2_INODE dinode2,
IN ULONGLONG Offset,
IN ULONG Size,
OUT PFFS_BDL *ffs_bdl)
{
ULONG nBeg, nEnd, nBlocks;
ULONGLONG dwBlk;
ULONG dwBytes = 0, i;
LONGLONG Lba;
LONGLONG AllocSize;
ULONG Totalblocks;
PFFS_BDL ffsbdl;
*ffs_bdl = NULL;
Totalblocks = (ULONG)(dinode2->di_blocks);
AllocSize = FFSDataBlocks(Vcb, Totalblocks);
AllocSize = (AllocSize << BLOCK_BITS);
if ((LONGLONG)Offset >= AllocSize)
{
FFSPrint((DBG_ERROR, "FFSv2BuildBDL: beyond the file range.\n"));
return 0;
}
if ((LONGLONG)(Offset + Size) > AllocSize)
{
Size = (ULONG)(AllocSize - Offset);
}
nBeg = (ULONG)(Offset >> BLOCK_BITS);
nEnd = (ULONG)((Size + Offset + Vcb->BlockSize - 1) >> BLOCK_BITS);
#if 0
KdPrint(("FFSv2BuildBDL() Offset : %x\n", Offset));
KdPrint(("FFSv2BuildBDL() Size : %x\n", Size));
KdPrint(("FFSv2BuildBDL() nBeg : %d, nEnd : %d\n", nBeg, nEnd));
#endif
nBlocks = 0;
if ((nEnd - nBeg) > 0)
{
ffsbdl = ExAllocatePool(PagedPool, sizeof(FFS_BDL) * (nEnd - nBeg));
if (ffsbdl)
{
RtlZeroMemory(ffsbdl, sizeof(FFS_BDL) * (nEnd - nBeg));
for (i = nBeg; i < nEnd; i++)
{
dwBlk = FFSv2BlockMap(Vcb, dinode2, i);
if (dwBlk > 0)
{
Lba = (LONGLONG)dwBlk;
Lba = Lba * SUPER_BLOCK->fs_fsize; // fragment size
Lba += FFSGlobal->FSOffset[FFSGlobal->PartitionNumber];
if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1)
{
dwBytes = Size;
ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
ffsbdl[nBlocks].Length = dwBytes;
ffsbdl[nBlocks].Offset = 0;
nBlocks++;
}
else
{
if (i == nBeg)
{
dwBytes = Vcb->BlockSize - (ULONG)(Offset % (Vcb->BlockSize));
ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
ffsbdl[nBlocks].Length = dwBytes;
ffsbdl[nBlocks].Offset = 0;
nBlocks++;
}
else if (i == nEnd - 1)
{
if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
{
ffsbdl[nBlocks - 1].Length += Size - dwBytes;
}
else
{
ffsbdl[nBlocks].Lba = Lba;
ffsbdl[nBlocks].Length = Size - dwBytes;
ffsbdl[nBlocks].Offset = dwBytes;
nBlocks++;
}
dwBytes = Size;
}
else
{
if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
{
ffsbdl[nBlocks - 1].Length += Vcb->BlockSize;
}
else
{
ffsbdl[nBlocks].Lba = Lba;
ffsbdl[nBlocks].Length = Vcb->BlockSize;
ffsbdl[nBlocks].Offset = dwBytes;
nBlocks++;
}
dwBytes += Vcb->BlockSize;
}
}
}
else
{
break;
}
}
*ffs_bdl = ffsbdl;
return nBlocks;
}
}
// Error
return 0;
}
BOOLEAN
FFSNewBlock(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
ULONG GroupHint,
ULONG BlockHint,
PULONG dwRet)
{
#if 0
RTL_BITMAP BlockBitmap;
LARGE_INTEGER Offset;
ULONG Length;
PBCB BitmapBcb;
PVOID BitmapCache;
ULONG Group = 0, dwBlk, dwHint = 0;
*dwRet = 0;
dwBlk = 0XFFFFFFFF;
if (GroupHint > Vcb->ffs_groups)
GroupHint = Vcb->ffs_groups - 1;
if (BlockHint != 0)
{
GroupHint = (BlockHint - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
dwHint = (BlockHint - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
}
ScanBitmap:
// Perform Prefered Group
if (Vcb->ffs_group_desc[GroupHint].bg_free_blocks_count)
{
Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
Offset.QuadPart = Offset.QuadPart *
Vcb->ffs_group_desc[GroupHint].bg_block_bitmap;
if (GroupHint == Vcb->ffs_groups - 1)
{
Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
/* s_blocks_count is integer multiple of s_blocks_per_group */
if (Length == 0)
{
Length = BLOCKS_PER_GROUP;
}
}
else
{
Length = BLOCKS_PER_GROUP;
}
if (!CcPinRead(Vcb->StreamObj,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache))
{
FFSPrint((DBG_ERROR, "FFSNewBlock: PinReading error ...\n"));
return FALSE;
}
RtlInitializeBitMap(&BlockBitmap,
BitmapCache,
Length);
Group = GroupHint;
if (RtlCheckBit(&BlockBitmap, dwHint) == 0)
{
dwBlk = dwHint;
}
else
{
dwBlk = RtlFindClearBits(&BlockBitmap, 1, dwHint);
}
// We could not get new block in the prefered group.
if (dwBlk == 0xFFFFFFFF)
{
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
}
}
if (dwBlk == 0xFFFFFFFF)
{
for(Group = 0; Group < Vcb->ffs_groups; Group++)
if (Vcb->ffs_group_desc[Group].bg_free_blocks_count)
{
if (Group == GroupHint)
continue;
Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;
if (Vcb->ffs_groups == 1)
{
Length = TOTAL_BLOCKS;
}
else
{
if (Group == Vcb->ffs_groups - 1)
{
Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
/* s_blocks_count is integer multiple of s_blocks_per_group */
if (Length == 0)
{
Length = BLOCKS_PER_GROUP;
}
}
else
{
Length = BLOCKS_PER_GROUP;
}
}
if (!CcPinRead(Vcb->StreamObj,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache))
{
FFSPrint((DBG_ERROR, "FFSNewBlock: PinReading error ...\n"));
return FALSE;
}
RtlInitializeBitMap(&BlockBitmap,
BitmapCache,
Length);
dwBlk = RtlFindClearBits(&BlockBitmap, 1, 0);
if (dwBlk != 0xFFFFFFFF)
{
break;
}
else
{
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
}
}
}
if (dwBlk < Length)
{
RtlSetBits(&BlockBitmap, dwBlk, 1);
CcSetDirtyPinnedData(BitmapBcb, NULL);
FFSRepinBcb(IrpContext, BitmapBcb);
CcUnpinData(BitmapBcb);
FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
*dwRet = dwBlk + FFS_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP;
//Updating Group Desc / Superblock
Vcb->ffs_group_desc[Group].bg_free_blocks_count--;
FFSSaveGroup(IrpContext, Vcb);
Vcb->ffs_super_block->s_free_blocks_count--;
FFSSaveSuper(IrpContext, Vcb);
{
ULONG i = 0;
for (i = 0; i < Vcb->ffs_groups; i++)
{
if ((Vcb->ffs_group_desc[i].bg_block_bitmap == *dwRet) ||
(Vcb->ffs_group_desc[i].bg_inode_bitmap == *dwRet) ||
(Vcb->ffs_group_desc[i].bg_inode_table == *dwRet))
{
FFSBreakPoint();
GroupHint = Group;
goto ScanBitmap;
}
}
}
return TRUE;
}
#endif
return FALSE;
}
BOOLEAN
FFSFreeBlock(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
ULONG Block)
{
#if 0
RTL_BITMAP BlockBitmap;
LARGE_INTEGER Offset;
ULONG Length;
PBCB BitmapBcb;
PVOID BitmapCache;
ULONG Group, dwBlk;
BOOLEAN bModified = FALSE;
if (Block < FFS_FIRST_DATA_BLOCK || Block > (BLOCKS_PER_GROUP * Vcb->ffs_groups))
{
FFSBreakPoint();
return TRUE;
}
FFSPrint((DBG_INFO, "FFSFreeBlock: Block %xh to be freed.\n", Block));
Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
{
Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;
if (Group == Vcb->ffs_groups - 1)
{
Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
/* s_blocks_count is integer multiple of s_blocks_per_group */
if (Length == 0)
{
Length = BLOCKS_PER_GROUP;
}
}
else
{
Length = BLOCKS_PER_GROUP;
}
if (!CcPinRead(Vcb->StreamObj,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache))
{
FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n"));
return FALSE;
}
RtlInitializeBitMap(&BlockBitmap,
BitmapCache,
Length);
if (RtlCheckBit(&BlockBitmap, dwBlk) == 0)
{
}
else
{
RtlClearBits(&BlockBitmap, dwBlk, 1);
bModified = TRUE;
}
if (!bModified)
{
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
}
}
if (bModified)
{
CcSetDirtyPinnedData(BitmapBcb, NULL);
FFSRepinBcb(IrpContext, BitmapBcb);
CcUnpinData(BitmapBcb);
FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
//Updating Group Desc / Superblock
Vcb->ffs_group_desc[Group].bg_free_blocks_count++;
FFSSaveGroup(IrpContext, Vcb);
Vcb->ffs_super_block->s_free_blocks_count++;
FFSSaveSuper(IrpContext, Vcb);
return TRUE;
}
#endif
return FALSE;
}
BOOLEAN
FFSExpandBlock(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb,
ULONG dwContent,
ULONG Index,
ULONG layer,
BOOLEAN bNew,
ULONG *dwRet)
{
ULONG *pData = NULL;
ULONG i = 0, j = 0, temp = 1;
ULONG dwNewBlk = 0, dwBlk = 0;
BOOLEAN bDirty = FALSE;
BOOLEAN bRet = TRUE;
PFFSv1_INODE dinode1 = Fcb->dinode1;
PFFS_SUPER_BLOCK FFSSb = Vcb->ffs_super_block;
pData = (ULONG *)ExAllocatePool(PagedPool, Vcb->BlockSize);
if (!pData)
{
return FALSE;
}
RtlZeroMemory(pData, Vcb->BlockSize);
if (bNew)
{
if (layer == 0)
{
if (IsDirectory(Fcb))
{
PFFS_DIR_ENTRY pEntry;
pEntry = (PFFS_DIR_ENTRY) pData;
pEntry->d_reclen = (USHORT)(Vcb->BlockSize);
if (!FFSSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData))
{
bRet = FALSE;
goto errorout;
}
}
else
{
LARGE_INTEGER Offset;
Offset.QuadPart = (LONGLONG)dwContent;
Offset.QuadPart = Offset.QuadPart * Vcb->BlockSize;
FFSRemoveMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
}
}
else
{
if (!FFSSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData))
{
bRet = FALSE;
goto errorout;
}
}
}
if (layer == 0)
{
dwNewBlk = dwContent;
}
else if (layer <= 3)
{
if (!bNew)
{
bRet = FFSv1LoadBlock(Vcb, dwContent, (void *)pData);
if (!bRet) goto errorout;
}
temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));
i = Index / temp;
j = Index % temp;
dwBlk = pData[i];
if (dwBlk == 0)
{
if (!FFSNewBlock(IrpContext,
Vcb, 0,
dwContent,
&dwBlk))
{
bRet = FALSE;
FFSPrint((DBG_ERROR, "FFSExpandBlock: get new block error.\n"));
goto errorout;
}
dinode1->di_blocks += (Vcb->BlockSize / SECTOR_SIZE);
pData[i] = dwBlk;
bDirty = TRUE;
}
if (!FFSExpandBlock(IrpContext,
Vcb, Fcb,
dwBlk, j,
layer - 1,
bDirty,
&dwNewBlk))
{
bRet = FALSE;
FFSPrint((DBG_ERROR, "FFSExpandBlockk: ... error recuise...\n"));
goto errorout;
}
if (bDirty)
{
bRet = FFSSaveBlock(IrpContext,
Vcb, dwContent,
(void *)pData);
}
}
errorout:
if (pData)
ExFreePool(pData);
if (bRet && dwRet)
*dwRet = dwNewBlk;
return bRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -