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

📄 ffs.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -