|
|
Definition at line 1190 of file metadata.c.
Referenced by Ext2CommonCreate(), Ext2CommonWrite(), Ext2MakeNewDirectoryEntry(), and Ext2SetAllocationInformation().
{
BOOLEAN RC = TRUE;
ULONG NewBlockNo = 0;
LARGE_INTEGER VolumeByteOffset;
ULONG LogicalBlockSize = 0;
ULONG NoOfBlocks = 0;
EXT2_INODE Inode;
ULONG DirectBlocks = 0;
ULONG SingleIndirectBlocks = 0;
ULONG DoubleIndirectBlocks = 0;
ULONG TripleIndirectBlocks = 0;
ULONG *PtrSIBBuffer = NULL;
PBCB PtrSIBBCB = NULL;
ULONG *PtrDIBBuffer = NULL;
PBCB PtrDIBBCB = NULL;
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
DirectBlocks = EXT2_NDIR_BLOCKS ;
SingleIndirectBlocks = LogicalBlockSize / sizeof( ULONG );
DoubleIndirectBlocks = SingleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
TripleIndirectBlocks = DoubleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
try
{
if( PtrFCB && PtrFCB->FCBName->ObjectName.Length )
{
DebugTrace( DEBUG_TRACE_SPECIAL, "Adding Blocks to file %S", PtrFCB->FCBName->ObjectName.Buffer );
}
Ext2InitializeFCBInodeInfo( PtrFCB );
NewBlockNo = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );
if( NewBlockNo == 0 )
{
try_return (RC = FALSE );
}
NoOfBlocks = (ULONG) PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart / LogicalBlockSize;
if( NoOfBlocks < EXT2_NDIR_BLOCKS )
{
PtrFCB->IBlock[ NoOfBlocks ] = NewBlockNo;
Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode );
Inode.i_block[ NoOfBlocks ] = NewBlockNo;
Inode.i_blocks += ( LogicalBlockSize / 512 );
PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize;
if( UpdateFileSize )
{
Inode.i_size += LogicalBlockSize;
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize;
}
if( PtrFileObject->PrivateCacheMap != NULL)
{
CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
}
if( NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
try_return (RC = TRUE);
}
else
{
try_return (RC = FALSE );
}
}
else if( NoOfBlocks < (DirectBlocks + SingleIndirectBlocks) )
{
Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode );
if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] == 0 )
{
PtrFCB->IBlock[ EXT2_IND_BLOCK ] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );
if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] == 0 )
{
try_return (RC = FALSE );
}
Inode.i_blocks += ( LogicalBlockSize / 512 );
VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize;
if( !CcPreparePinWrite(
PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
TRUE,
&PtrSIBBCB,
(PVOID*)&PtrSIBBuffer ) )
{
try_return( RC = FALSE );
}
}
else
{
VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize;
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
&PtrSIBBCB,
(PVOID*)&PtrSIBBuffer ) )
{
try_return( RC = FALSE );
}
}
Inode.i_block[ EXT2_IND_BLOCK ] = PtrFCB->IBlock[ EXT2_IND_BLOCK ];
Inode.i_blocks += ( LogicalBlockSize / 512 );
PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize;
if( UpdateFileSize )
{
Inode.i_size += LogicalBlockSize;
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize;
}
if( PtrFileObject->PrivateCacheMap != NULL)
{
CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
}
if( !NT_SUCCESS( Ext2WriteInode(
PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
try_return (RC = FALSE );
}
PtrSIBBuffer[ NoOfBlocks - DirectBlocks ] = NewBlockNo;
CcSetDirtyPinnedData( PtrSIBBCB, NULL );
Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject );
try_return (RC = TRUE);
}
else if( NoOfBlocks < (DirectBlocks + SingleIndirectBlocks + DoubleIndirectBlocks ) )
{
ULONG SBlockNo;
ULONG BlockNo;
Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode );
if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 )
{
PtrFCB->IBlock[ EXT2_DIND_BLOCK ] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );
if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 )
{
try_return (RC = FALSE );
}
Inode.i_blocks += ( LogicalBlockSize / 512 );
VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
if( !CcPreparePinWrite(
PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
TRUE,
&PtrDIBBCB,
(PVOID*)&PtrDIBBuffer ) )
{
try_return( RC = FALSE );
}
}
else
{
VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
&PtrDIBBCB,
(PVOID*)&PtrDIBBuffer ) )
{
try_return( RC = FALSE );
}
}
BlockNo = ( NoOfBlocks - DirectBlocks - SingleIndirectBlocks );
SBlockNo = BlockNo / SingleIndirectBlocks;
if( BlockNo % SingleIndirectBlocks )
{
PtrDIBBuffer[SBlockNo] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );
CcSetDirtyPinnedData( PtrDIBBCB, NULL );
VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize;
Inode.i_blocks += ( LogicalBlockSize / 512 );
if( !CcPreparePinWrite(
PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
TRUE,
&PtrSIBBCB,
(PVOID*)&PtrSIBBuffer ) )
{
try_return( RC = FALSE );
}
}
else
{
VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize;
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
&PtrSIBBCB,
(PVOID*)&PtrSIBBuffer ) )
{
try_return( RC = FALSE );
}
}
BlockNo = BlockNo % SingleIndirectBlocks;
Inode.i_block[ EXT2_DIND_BLOCK ] = PtrFCB->IBlock[ EXT2_DIND_BLOCK ];
Inode.i_blocks += ( LogicalBlockSize / 512 );
PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize;
if( UpdateFileSize )
{
Inode.i_size += LogicalBlockSize;
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize;
}
if( PtrFileObject->PrivateCacheMap != NULL)
{
CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
}
if( !NT_SUCCESS( Ext2WriteInode(
PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
try_return (RC = FALSE );
}
PtrSIBBuffer[ BlockNo ] = NewBlockNo;
CcSetDirtyPinnedData( PtrSIBBCB, NULL );
Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject );
Ext2SaveBCB( PtrIrpContext, PtrDIBBCB, PtrVCB->PtrStreamFileObject );
try_return (RC = TRUE);
}
else
{
ULONG SBlockNo;
ULONG BlockNo;
try_return (RC = FALSE);
Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode );
if( PtrFCB->IBlock[ EXT2_TIND_BLOCK ] == 0 )
{
PtrFCB->IBlock[ EXT2_DIND_BLOCK ] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );
if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 )
{
try_return (RC = FALSE );
}
Inode.i_blocks += ( LogicalBlockSize / 512 );
VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
if( !CcPreparePinWrite(
PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
TRUE,
&PtrDIBBCB,
(PVOID*)&PtrDIBBuffer ) )
{
try_return( RC = FALSE );
}
}
else
{
VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
&PtrDIBBCB,
(PVOID*)&PtrDIBBuffer ) )
{
try_return( RC = FALSE );
}
}
BlockNo = ( NoOfBlocks - DirectBlocks - SingleIndirectBlocks );
SBlockNo = BlockNo / SingleIndirectBlocks;
if( BlockNo % SingleIndirectBlocks )
{
PtrDIBBuffer[SBlockNo] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );
CcSetDirtyPinnedData( PtrDIBBCB, NULL );
VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize;
Inode.i_blocks += ( LogicalBlockSize / 512 );
if( !CcPreparePinWrite(
PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
TRUE,
&PtrSIBBCB,
(PVOID*)&PtrSIBBuffer ) )
{
try_return( RC = FALSE );
}
}
else
{
VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize;
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
LogicalBlockSize,
TRUE,
&PtrSIBBCB,
(PVOID*)&PtrSIBBuffer ) )
{
try_return( RC = FALSE );
}
}
BlockNo = BlockNo % SingleIndirectBlocks;
Inode.i_block[ EXT2_DIND_BLOCK ] = PtrFCB->IBlock[ EXT2_DIND_BLOCK ];
Inode.i_blocks += ( LogicalBlockSize / 512 );
PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize;
if( UpdateFileSize )
{
Inode.i_size += LogicalBlockSize;
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize;
}
if( PtrFileObject->PrivateCacheMap != NULL)
{
CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
}
if( !NT_SUCCESS( Ext2WriteInode(
PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
try_return (RC = FALSE );
}
PtrSIBBuffer[ BlockNo ] = NewBlockNo;
CcSetDirtyPinnedData( PtrSIBBCB, NULL );
Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject );
Ext2SaveBCB( PtrIrpContext, PtrDIBBCB, PtrVCB->PtrStreamFileObject );
try_return (RC = TRUE);
}
try_exit: NOTHING;
}
finally
{
if( PtrSIBBCB )
{
CcUnpinData( PtrSIBBCB );
PtrSIBBCB = NULL;
}
if( PtrDIBBCB )
{
CcUnpinData( PtrDIBBCB );
PtrDIBBCB = NULL;
}
}
return RC;
}
|