📄 ffs.c
字号:
}
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 + -