ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

BOOLEAN NTAPI Ext2AddBlockToFile ( PtrExt2IrpContext  PtrIrpContext,
PtrExt2VCB  PtrVCB,
PtrExt2FCB  PtrFCB,
PFILE_OBJECT  PtrFileObject,
BOOLEAN  UpdateFileSize 
)

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 );

        //  Allocate a block...
        NewBlockNo = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 );

        if( NewBlockNo == 0 )
        {
            try_return (RC = FALSE );
        }

        //  No of blocks CURRENTLY allocated...
        NoOfBlocks = (ULONG) PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart / LogicalBlockSize;
        
        
        if( NoOfBlocks < EXT2_NDIR_BLOCKS )
        {
            //
            //  A direct data block will do...
            //
            
            PtrFCB->IBlock[ NoOfBlocks ] = NewBlockNo;
            
            //  Update the inode...
            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)
            {
                //
                //  Caching has been initiated...
                //  Let the Cache manager in on these changes...
                //  
                CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
            }
            
            
            //  Updating the inode...
            if( NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode  ) ) )
            {
                try_return (RC = TRUE);
            }
            else
            {
                try_return (RC = FALSE );
            }
            
        }
        else if( NoOfBlocks < (DirectBlocks + SingleIndirectBlocks) )
        {
            //
            //  A single indirect data block will do...
            Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode  );

            if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] == 0 )
            {
                //  A Single Indirect block should be allocated as well!!
                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 );

                //  Bring in the new block to the cache
                //  Zero it out
                VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize;

                if( !CcPreparePinWrite( 
                    PtrVCB->PtrStreamFileObject,
                    &VolumeByteOffset,
                    LogicalBlockSize,
                    TRUE,           //  Zero out the block...
                    TRUE,           //  Can Wait...
                    &PtrSIBBCB,
                    (PVOID*)&PtrSIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            else
            {
                //   Just bring in the SIB to the cache
                
                VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize;

                if( !CcPinRead( PtrVCB->PtrStreamFileObject,
                            &VolumeByteOffset,
                            LogicalBlockSize,
                            TRUE,           //  Can Wait...
                            &PtrSIBBCB,
                            (PVOID*)&PtrSIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            
            //  Update the inode...
            
            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)
            {
                //
                //  Caching has been initiated...
                //  Let the Cache manager in on these changes...
                //  
                CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
            }

            if( !NT_SUCCESS( Ext2WriteInode( 
                PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode  ) ) )
            {
                try_return (RC = FALSE );
            }

            
            //  Update the SIB...
            PtrSIBBuffer[ NoOfBlocks - DirectBlocks ] = NewBlockNo;
            CcSetDirtyPinnedData( PtrSIBBCB, NULL );
            Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject );

            try_return (RC = TRUE);

        }
        else if( NoOfBlocks < (DirectBlocks + SingleIndirectBlocks + DoubleIndirectBlocks ) )
        {
            //
            //  A double indirect block will do...
            //
            ULONG SBlockNo;
            ULONG BlockNo;

            Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode  );

            if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 )
            {
                //  A double indirect pointer block should be allocated as well!!
                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 );

                //  Bring in the new block to the cache
                //  Zero it out
                VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;

                if( !CcPreparePinWrite( 
                    PtrVCB->PtrStreamFileObject,
                    &VolumeByteOffset,
                    LogicalBlockSize,
                    TRUE,           //  Zero out the block...
                    TRUE,           //  Can Wait...
                    &PtrDIBBCB,
                    (PVOID*)&PtrDIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            else
            {
                //   Just bring in the DIB to the cache
                
                VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;

                if( !CcPinRead( PtrVCB->PtrStreamFileObject,
                            &VolumeByteOffset,
                            LogicalBlockSize,
                            TRUE,           //  Can Wait...
                            &PtrDIBBCB,
                            (PVOID*)&PtrDIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            
            //  See if a single indirect 'pointer' block 
            //  should also be allocated...
            BlockNo = ( NoOfBlocks - DirectBlocks - SingleIndirectBlocks );
            SBlockNo = BlockNo / SingleIndirectBlocks;
            if( BlockNo % SingleIndirectBlocks )
            {
                //  A single indirect 'pointer' block 
                //  should also be allocated...
                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,                   //  Zero out the block...
                    TRUE,                   //  Can Wait...
                    &PtrSIBBCB,
                    (PVOID*)&PtrSIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            else
            {
                VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize;
                if( !CcPinRead( PtrVCB->PtrStreamFileObject,
                            &VolumeByteOffset,
                            LogicalBlockSize,
                            TRUE,               //  Can Wait...
                            &PtrSIBBCB,
                            (PVOID*)&PtrSIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            BlockNo = BlockNo % SingleIndirectBlocks;
            
            //  Update the inode...
            
            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)
            {
                //
                //  Caching has been initiated...
                //  Let the Cache manager in on these changes...
                //  
                CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
            }

            if( !NT_SUCCESS( Ext2WriteInode( 
                PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode  ) ) )
            {
                try_return (RC = FALSE );
            }

            
            //  Update the SIB...
            PtrSIBBuffer[ BlockNo ] = NewBlockNo;
            CcSetDirtyPinnedData( PtrSIBBCB, NULL );
            Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject );
            Ext2SaveBCB( PtrIrpContext, PtrDIBBCB, PtrVCB->PtrStreamFileObject );

            try_return (RC = TRUE);

        }
        else
        {   
            //
            //  A Triple Indirect block is required
            //
            ULONG SBlockNo;
            ULONG BlockNo;

            //  This is not supported as yet...
            try_return (RC = FALSE);

            Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode  );

            if( PtrFCB->IBlock[ EXT2_TIND_BLOCK ] == 0 )
            {
                //  A double indirect pointer block should be allocated as well!!
                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 );

                //  Bring in the new block to the cache
                //  Zero it out
                VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;

                if( !CcPreparePinWrite( 
                    PtrVCB->PtrStreamFileObject,
                    &VolumeByteOffset,
                    LogicalBlockSize,
                    TRUE,           //  Zero out the block...
                    TRUE,           //  Can Wait...
                    &PtrDIBBCB,
                    (PVOID*)&PtrDIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            else
            {
                //   Just bring in the DIB to the cache
                
                VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;

                if( !CcPinRead( PtrVCB->PtrStreamFileObject,
                            &VolumeByteOffset,
                            LogicalBlockSize,
                            TRUE,           //  Can Wait...
                            &PtrDIBBCB,
                            (PVOID*)&PtrDIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            
            //  See if a single indirect 'pointer' block 
            //  should also be allocated...
            BlockNo = ( NoOfBlocks - DirectBlocks - SingleIndirectBlocks );
            SBlockNo = BlockNo / SingleIndirectBlocks;
            if( BlockNo % SingleIndirectBlocks )
            {
                //  A single indirect 'pointer' block 
                //  should also be allocated...
                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,           //  Zero out the block...
                    TRUE,           //  Can Wait...
                    &PtrSIBBCB,
                    (PVOID*)&PtrSIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            else
            {
                VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize;
                if( !CcPinRead( PtrVCB->PtrStreamFileObject,
                            &VolumeByteOffset,
                            LogicalBlockSize,
                            TRUE,           //  Can Wait...
                            &PtrSIBBCB,
                            (PVOID*)&PtrSIBBuffer ) )
                {
                    try_return( RC = FALSE );
                }
            }
            BlockNo = BlockNo % SingleIndirectBlocks;
            
            //  Update the inode...
            
            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)
            {
                //
                //  Caching has been initiated...
                //  Let the Cache manager in on these changes...
                //  
                CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
            }

            if( !NT_SUCCESS( Ext2WriteInode( 
                PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode  ) ) )
            {
                try_return (RC = FALSE );
            }

            
            //  Update the SIB...
            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;
}

Generated on Sun May 27 2012 05:12:54 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.