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

📄 ffs.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 4 页
字号:
				}
				else
				{
					RecLen = (ULONG)pTarget->d_reclen;
					if (RecLen > FFS_DIR_REC_LEN(FFS_NAME_LEN))
					{
						RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
					}
					else
					{
						RtlZeroMemory(pTarget, RecLen);
					}

					pTarget->d_reclen = (USHORT)RecLen;

					FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, RecLen, FALSE, &dwRet);
				}

				if (FileType == DT_DIR)
				{
					if(((pTarget->d_namlen == 1) && (pTarget->d_name[0] == '.')) ||
							((pTarget->d_namlen == 2) && (pTarget->d_name[0] == '.') && (pTarget->d_name[1] == '.')))
					{
						FFSBreakPoint();
					}
					else
					{
						Dcb->dinode1->di_nlink--;
					}
				}

				/* Update at least mtime/atime if !FFS_FT_DIR. */
				FFSv1SaveInode(IrpContext, Vcb, Dcb->FFSMcb->Inode, Dcb->dinode1);

				bRet = TRUE;

				break;
			}
			else
			{
				RtlCopyMemory(pPrevDir, pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
				PrevRecLen = pTarget->d_reclen;
			}

			dwBytes += pTarget->d_reclen;
		}
	}

	__finally
	{

		Dcb->ReferenceCount--;

		if(MainResourceAcquired)
			ExReleaseResourceForThreadLite(
					&Dcb->MainResource,
					ExGetCurrentResourceThread());

		if (pTarget != NULL)
		{
			ExFreePool(pTarget);
		}

		if (pPrevDir != NULL)
		{
			ExFreePool(pPrevDir);
		}
	}

	return bRet;
}


NTSTATUS
FFSSetParentEntry(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN PFFS_FCB         Dcb,
	IN ULONG            OldParent,
	IN ULONG            NewParent)
{
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;

	PFFS_DIR_ENTRY          pSelf   = NULL;
	PFFS_DIR_ENTRY          pParent = NULL;

	ULONG                   dwBytes = 0;

	BOOLEAN                 MainResourceAcquired = FALSE;

	ULONG                   Offset = 0;

	if (!IsDirectory(Dcb))
	{
		Status = STATUS_INVALID_PARAMETER;
		return Status;
	}

	MainResourceAcquired = 
		ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);

	__try
	{
		Dcb->ReferenceCount++;

		pSelf = (PFFS_DIR_ENTRY)ExAllocatePool(PagedPool,
				FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2));
		if (!pSelf)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		dwBytes = 0;

		// Reading the DCB contents
		Status = FFSv1ReadInode(
					NULL,
					Vcb,
					Dcb->dinode1,
					Offset,
					(PVOID)pSelf,
					FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2),
					&dwBytes);

		if (!NT_SUCCESS(Status))
		{
			FFSPrint((DBG_ERROR, "FFSSetParentEntry: Reading Directory Content error.\n"));
			__leave;
		}

		ASSERT(dwBytes == FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2));

		pParent = (PFFS_DIR_ENTRY)((PUCHAR)pSelf + pSelf->d_reclen);

		if (pParent->d_ino != OldParent)
		{
			FFSBreakPoint();
		}

		pParent->d_ino = NewParent;

		Status = FFSv1WriteInode(IrpContext,
					Vcb, 
					Dcb->dinode1,
					Offset,
					pSelf,
					dwBytes,
					FALSE,
					&dwBytes);
	}

	__finally
	{
		Dcb->ReferenceCount--;

		if(MainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Dcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (pSelf)
		{
			ExFreePool(pSelf);
		}
	}

	return Status;
}


BOOLEAN
FFSTruncateBlock(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN PFFS_FCB         Fcb,
	IN ULONG            dwContent,
	IN ULONG            Index,
	IN ULONG            layer,
	OUT BOOLEAN         *bFreed)
{
	ULONG       *pData = NULL;
	ULONG       i = 0, j = 0, temp = 1;
	BOOLEAN     bDirty = FALSE;
	BOOLEAN     bRet = FALSE;
	ULONG       dwBlk;

	LONGLONG    Offset;

	PBCB        Bcb;

	PFFSv1_INODE dinode1 = Fcb->dinode1;

	*bFreed = FALSE;

	if (layer == 0)
	{
		//if (dwContent > 0 && dwContent < (BLOCKS_PER_GROUP * Vcb->ffs_groups))
		if (dwContent > 0)
		{
			bRet = FFSFreeBlock(IrpContext, Vcb, dwContent);

			if (bRet)
			{
				ASSERT(dinode1->di_blocks >= (Vcb->BlockSize / SECTOR_SIZE));
				dinode1->di_blocks -= (Vcb->BlockSize / SECTOR_SIZE);            
			}
		}
		else
		{
			FFSBreakPoint();
			bRet = FALSE;
		}

		*bFreed = bRet;
	}
	else if (layer <= 3)
	{
		Offset = (LONGLONG)dwContent;
		Offset = Offset * Vcb->BlockSize;

		if(!CcPinRead(Vcb->StreamObj,
					(PLARGE_INTEGER)(&Offset),
					Vcb->BlockSize,
					PIN_WAIT,
					&Bcb,
					&pData))
		{
			FFSPrint((DBG_ERROR, "FFSSaveBuffer: PinReading error ...\n"));
			goto errorout;
		}

		temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));

		i = Index / temp;
		j = Index % temp;

		dwBlk = pData[i];

		if(!FFSTruncateBlock(IrpContext, Vcb, Fcb, dwBlk, j, layer - 1, &bDirty))
		{
			goto errorout;
		}

		if (bDirty)
		{
			pData[i] = 0;
		}

		if (i == 0 && j == 0)
		{
			CcUnpinData(Bcb);
			pData = NULL;

			*bFreed = TRUE;
			bRet = FFSFreeBlock(IrpContext, Vcb, dwContent);

			if (bRet)
			{
				ASSERT(dinode1->di_blocks >= (Vcb->BlockSize / SECTOR_SIZE));
				dinode1->di_blocks -= (Vcb->BlockSize / SECTOR_SIZE);
			}
		}
		else
		{
			CcSetDirtyPinnedData(Bcb, NULL);
			FFSRepinBcb(IrpContext, Bcb);

			FFSAddMcbEntry(Vcb, Offset, (LONGLONG)Vcb->BlockSize);

			bRet = TRUE;
			*bFreed = FALSE;
		}
	}

errorout:

	if (pData)
	{
		CcUnpinData(Bcb);
	}

	return bRet;
}


BOOLEAN
FFSTruncateInode(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN PFFS_FCB         Fcb)
{
	ULONG    dwSizes[FFS_BLOCK_TYPES];
	ULONG    Index = 0;
	ULONG    dwTotal = 0;
	ULONG    dwBlk = 0;

	ULONG    i;
	BOOLEAN  bRet = FALSE;
	BOOLEAN  bFreed = FALSE;

	PFFSv1_INODE dinode1 = Fcb->dinode1;

	Index = (ULONG)(Fcb->Header.AllocationSize.QuadPart >> BLOCK_BITS);

	if (Index > 0) 
	{
		Index--;
	}
	else
	{
		return TRUE;
	}

	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
		dwSizes[i] = Vcb->dwData[i];
		dwTotal += dwSizes[i];
	}

	if (Index >= dwTotal)
	{
		FFSPrint((DBG_ERROR, "FFSTruncateInode: beyond the maxinum size of an inode.\n"));
		return TRUE;
	}

	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
#if 0
		if (Index < dwSizes[i])
		{
			dwBlk = Inode->i_block[i == 0 ? (Index) : (i + NDADDR - 1)];

			bRet = FFSTruncateBlock(IrpContext, Vcb, Fcb, dwBlk, Index , i, &bFreed); 

			if (bRet)
			{
				Fcb->Header.AllocationSize.QuadPart -= Vcb->BlockSize;

				if (bFreed)
				{
					Inode->i_block[i == 0 ? (Index) : (i + NDADDR - 1)] = 0;
				}
			}

			break;
		}
#endif
		Index -= dwSizes[i];
	}

	{
		ASSERT(FFSDataBlocks(Vcb, (ULONG)(dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE)))
				== (Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE));

		ASSERT(FFSTotalBlocks(Vcb, (ULONG)(Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE))
				== (dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE)));

	}

	//
	// Inode struct saving is done externally.
	//

	FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1);


	return bRet;
}


BOOLEAN
FFSAddMcbEntry(
	IN PFFS_VCB Vcb,
	IN LONGLONG Lba,
	IN LONGLONG Length)
{
	BOOLEAN     bRet = FALSE;

	LONGLONG    Offset;

#if DBG
	LONGLONG    DirtyLba;
	LONGLONG    DirtyLen;
#endif


	Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1));

	Length = (Length + Lba - Offset + BLOCK_SIZE - 1) &
		(~((LONGLONG)BLOCK_SIZE - 1));

	ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0);
	ASSERT ((Length & (BLOCK_SIZE - 1)) == 0);

	Offset = (Offset >> BLOCK_BITS) + 1;
	Length = (Length >>BLOCK_BITS);

	ExAcquireResourceExclusiveLite(
			&(Vcb->McbResource),
			TRUE);

	FFSPrint((DBG_INFO, "FFSAddMcbEntry: Lba=%I64xh Length=%I64xh\n",
				Offset, Length));

#if DBG
	bRet = FsRtlLookupLargeMcbEntry(
			&(Vcb->DirtyMcbs),
			Offset,
			&DirtyLba,
			&DirtyLen,
			NULL,
			NULL,
			NULL);

	if (bRet && DirtyLba == Offset && DirtyLen >= Length)
	{
		FFSPrint((DBG_INFO, "FFSAddMcbEntry: this run already exists.\n"));
	}
#endif

	__try
	{
		bRet = FsRtlAddLargeMcbEntry(
				&(Vcb->DirtyMcbs),
				Offset, Offset,
				Length);

	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		FFSBreakPoint();
		bRet = FALSE;
	}

#if DBG
	if (bRet)
	{
		BOOLEAN     bFound = FALSE;
		LONGLONG    RunStart;
		LONGLONG    RunLength;
		ULONG       Index;

		bFound = FsRtlLookupLargeMcbEntry(
				&(Vcb->DirtyMcbs),
				Offset,
				&DirtyLba,
				&DirtyLen,
				&RunStart,
				&RunLength,
				&Index);

		if ((!bFound) || (DirtyLba == -1) ||
				(DirtyLba != Offset) || (DirtyLen < Length))
		{
			LONGLONG            DirtyVba;
			LONGLONG            DirtyLba;
			LONGLONG            DirtyLength;

			FFSBreakPoint();

			for (Index = 0; 
					FsRtlGetNextLargeMcbEntry(&(Vcb->DirtyMcbs),
						Index,
						&DirtyVba,
						&DirtyLba,
						&DirtyLength); 
					Index++)
			{
				FFSPrint((DBG_INFO, "Index = %xh\n", Index));
				FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
				FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
				FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
			}
		}
	}
#endif

	ExReleaseResourceForThreadLite(
			&(Vcb->McbResource),
			ExGetCurrentResourceThread());

	return bRet;
}


VOID
FFSRemoveMcbEntry(
	IN PFFS_VCB Vcb,
	IN LONGLONG Lba,
	IN LONGLONG Length)
{
	LONGLONG Offset;

	Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1));

	Length = (Length + Lba - Offset + BLOCK_SIZE - 1) &
		(~((LONGLONG)BLOCK_SIZE - 1));

	ASSERT(Offset == Lba);

	ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0);
	ASSERT ((Length & (BLOCK_SIZE - 1)) == 0);

	Offset = (Offset >> BLOCK_BITS) + 1;
	Length = (Length >> BLOCK_BITS);

	FFSPrint((DBG_INFO, "FFSRemoveMcbEntry: Lba=%I64xh Length=%I64xh\n",
				Offset, Length));

	ExAcquireResourceExclusiveLite(
			&(Vcb->McbResource),
			TRUE);

	__try
	{
		FsRtlRemoveLargeMcbEntry(
				&(Vcb->DirtyMcbs),
				Offset, Length);

	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		FFSBreakPoint();
	}

#if DBG
	{
		BOOLEAN  bFound = FALSE;
		LONGLONG DirtyLba, DirtyLen;

		bFound = FsRtlLookupLargeMcbEntry(
					&(Vcb->DirtyMcbs),
					Offset,
					&DirtyLba,
					&DirtyLen,
					NULL,
					NULL,
					NULL);

		if (bFound &&(DirtyLba != -1))
		{
			FFSBreakPoint();
		}
	}
#endif

	ExReleaseResourceForThreadLite(
			&(Vcb->McbResource),
			ExGetCurrentResourceThread());
}


BOOLEAN
FFSLookupMcbEntry(
	IN PFFS_VCB     Vcb,
	IN LONGLONG     Lba,
	OUT PLONGLONG   pLba,
	OUT PLONGLONG   pLength,
	OUT PLONGLONG   RunStart,
	OUT PLONGLONG   RunLength,
	OUT PULONG      Index)
{
	BOOLEAN     bRet;
	LONGLONG    Offset;


	Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1));
	ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0);

	ASSERT(Lba == Offset);

	Offset = (Offset >> BLOCK_BITS) + 1;

	ExAcquireResourceExclusiveLite(
			&(Vcb->McbResource),
			TRUE);

	bRet = FsRtlLookupLargeMcbEntry(
			&(Vcb->DirtyMcbs),
			Offset,
			pLba,
			pLength,
			RunStart,
			RunLength,
			Index);

	ExReleaseResourceForThreadLite(
			&(Vcb->McbResource),
			ExGetCurrentResourceThread());

	if (bRet)
	{
		if (pLba && ((*pLba) != -1))
		{
			ASSERT((*pLba) > 0);

			(*pLba) = (((*pLba) - 1) << BLOCK_BITS);
			(*pLba) += ((Lba) & ((LONGLONG)BLOCK_SIZE - 1));
		}

		if (pLength)
		{
			(*pLength) <<= BLOCK_BITS;
			(*pLength)  -= ((Lba) & ((LONGLONG)BLOCK_SIZE - 1));
		}

		if (RunStart && (*RunStart != -1))
		{
			(*RunStart) = (((*RunStart) - 1) << BLOCK_BITS);
		}

		if (RunLength)
		{
			(*RunLength) <<= BLOCK_BITS;
		}
	}

	return bRet;
}


ULONG
FFSDataBlocks(
	PFFS_VCB Vcb,
	ULONG TotalBlocks)
{
	ULONG   dwData[FFS_BLOCK_TYPES];
	ULONG   dwMeta[FFS_BLOCK_TYPES];
	ULONG   DataBlocks = 0;
	ULONG   i, j;

	if (TotalBlocks <= NDADDR)
	{
		return TotalBlocks;
	}

	TotalBlocks -= NDADDR;

	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
		if (i == 0)
		{
			dwData[i] = 1;
		}
		else
		{
			dwData[i] = Vcb->dwData[i];
		}

		dwMeta[i] = Vcb->dwMeta[i];
	}

	for(i = 1; (i < FFS_BLOCK_TYPES) && (TotalBlocks > 0); i++)
	{
		if (TotalBlocks >= (dwData[i] + dwMeta[i]))
		{
			TotalBlocks -= (dwData[i] + dwMeta[i]);
			DataBlocks  += dwData[i];
		}
		else
		{
			ULONG   dwDivide = 0;
			ULONG   dwRemain = 0;

			for (j = i; (j > 0) && (TotalBlocks > 0); j--)
			{
				dwDivide = (TotalBlocks - 1) / (dwData[j - 1] + dwMeta[j - 1]);
				dwRemain = (TotalBlocks - 1) % (dwData[j - 1] + dwMeta[j - 1]);

				DataBlocks += (dwDivide * dwData[j - 1]);
				TotalBlocks = dwRemain;
			}
		}
	}

	return (DataBlocks + NDADDR);
}


ULONG
FFSTotalBlocks(
	PFFS_VCB Vcb,
	ULONG DataBlocks)
{
	ULONG   dwData[FFS_BLOCK_TYPES];
	ULONG   dwMeta[FFS_BLOCK_TYPES];
	ULONG   TotalBlocks = 0;
	ULONG   i, j;

	if (DataBlocks <= NDADDR)
	{
		return DataBlocks;
	}

	DataBlocks -= NDADDR;

	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
		if (i == 0)
		{
			dwData[i] = 1;
		}
		else
		{
			dwData[i] = Vcb->dwData[i];
		}

		dwMeta[i] = Vcb->dwMeta[i];
	}

	for(i = 1; (i < FFS_BLOCK_TYPES) && (DataBlocks > 0); i++)
	{
		if (DataBlocks >= dwData[i])
		{
			DataBlocks  -= dwData[i];
			TotalBlocks += (dwData[i] + dwMeta[i]);
		}
		else
		{
			ULONG   dwDivide = 0;
			ULONG   dwRemain = 0;

			for (j = i; (j > 0) && (DataBlocks > 0); j--)
			{
				dwDivide = (DataBlocks) / (dwData[j - 1]);
				dwRemain = (DataBlocks) % (dwData[j - 1]);

				TotalBlocks += (dwDivide * (dwData[j - 1] + dwMeta[j - 1]) + 1);
				DataBlocks = dwRemain;
			}
		}
	}

	return (TotalBlocks + NDADDR);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -