in ff_file.c [1291:1474]
static FF_Error_t FF_ExtendFile( FF_FILE * pxFile,
uint32_t ulSize )
{
FF_IOManager_t * pxIOManager = pxFile->pxIOManager;
uint32_t ulBytesPerCluster = pxIOManager->xPartition.usBlkSize * pxIOManager->xPartition.ulSectorsPerCluster;
uint32_t ulTotalClustersNeeded = ( ulSize + ulBytesPerCluster - 1 ) / ulBytesPerCluster;
uint32_t ulClusterToExtend;
/* Initialise xIndex just for the compiler. */
BaseType_t xIndex = 0;
FF_DirEnt_t xOriginalEntry;
FF_Error_t xError = FF_ERR_NONE;
FF_FATBuffers_t xFATBuffers;
if( ( pxFile->ucMode & FF_MODE_WRITE ) != FF_MODE_WRITE )
{
xError = ( FF_Error_t ) ( FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE | FF_EXTENDFILE );
}
else
{
if( ( pxFile->ulFileSize == 0 ) && ( pxFile->ulObjectCluster == 0 ) )
{
/* If there is no object cluster yet, create it.*/
pxFile->ulAddrCurrentCluster = FF_CreateClusterChain( pxFile->pxIOManager, &xError );
if( FF_isERR( xError ) == pdFALSE )
{
/* The directory denotes the address of the first data cluster of every file.
* Now change it to 'ulAddrCurrentCluster': */
xError = FF_GetEntry( pxIOManager, pxFile->usDirEntry, pxFile->ulDirCluster, &xOriginalEntry );
if( FF_isERR( xError ) == pdFALSE )
{
xOriginalEntry.ulObjectCluster = pxFile->ulAddrCurrentCluster;
xError = FF_PutEntry( pxIOManager, pxFile->usDirEntry, pxFile->ulDirCluster, &xOriginalEntry, NULL );
if( FF_isERR( xError ) == pdFALSE )
{
pxFile->ulObjectCluster = pxFile->ulAddrCurrentCluster;
pxFile->ulChainLength = 1;
pxFile->ulCurrentCluster = 0;
pxFile->ulEndOfChain = pxFile->ulAddrCurrentCluster;
}
}
}
}
else
{
/* This file already has at least one cluster. */
}
}
if( FF_isERR( xError ) == pdFALSE )
{
if( pxFile->ulChainLength == 0 )
{
/* This is the first extension requiring the chain length.
* Calculate it now: */
pxFile->ulChainLength = FF_GetChainLength( pxIOManager, pxFile->ulObjectCluster, &pxFile->ulEndOfChain, &xError );
}
}
if( ( FF_isERR( xError ) == pdFALSE ) && ( ulTotalClustersNeeded > pxFile->ulChainLength ) )
{
uint32_t ulCurrentCluster, ulNextCluster;
ulClusterToExtend = ( ulTotalClustersNeeded - pxFile->ulChainLength );
/* Now the file has at least 1 cluster, but it needs more clusters. */
ulNextCluster = pxFile->ulAddrCurrentCluster;
FF_LockFAT( pxIOManager );
ulCurrentCluster = FF_FindEndOfChain( pxIOManager, ulNextCluster, &xError );
if( FF_isERR( xError ) == pdFALSE )
{
for( xIndex = 0; xIndex < ( BaseType_t ) ulClusterToExtend; xIndex++ )
{
/* In FF_ExtendFile() */
ulNextCluster = FF_FindFreeCluster( pxIOManager, &xError, pdTRUE );
if( ( FF_isERR( xError ) == pdFALSE ) && ( ulNextCluster == 0UL ) )
{
xError = ( FF_Error_t ) ( FF_ERR_FAT_NO_FREE_CLUSTERS | FF_EXTENDFILE );
}
if( FF_isERR( xError ) )
{
break;
}
/* Can not use this buffer earlier because of FF_FindEndOfChain/FF_FindFreeCluster */
FF_InitFATBuffers( &xFATBuffers, FF_MODE_WRITE );
xError = FF_putFATEntry( pxIOManager, ulCurrentCluster, ulNextCluster, &xFATBuffers );
if( FF_isERR( xError ) )
{
break;
}
xError = FF_ReleaseFATBuffers( pxIOManager, &xFATBuffers );
if( FF_isERR( xError ) )
{
break;
}
ulCurrentCluster = ulNextCluster;
}
if( FF_isERR( xError ) == pdFALSE )
{
pxFile->ulEndOfChain = ulCurrentCluster;
}
pxFile->ulChainLength += xIndex;
}
FF_UnlockFAT( pxIOManager );
{
FF_Error_t xTempError;
xTempError = FF_DecreaseFreeClusters( pxIOManager, ( uint32_t ) xIndex ); /* Keep Tab of Numbers for fast FreeSize() */
if( FF_isERR( xError ) == pdFALSE )
{
xError = xTempError;
}
}
/* We must ensure that the ulAddrCurrentCluster is not out-of-sync with the CurrentCluster number.
* This could have occurred in append mode, where the file was opened with a filesize % clustersize == 0
* because of a seek, where the ulAddrCurrentCluster was not updated after extending. This caused the data to
* be written to the previous cluster(s). */
if( ( pxFile->ulCurrentCluster == pxFile->ulChainLength - 1 ) &&
( pxFile->ulAddrCurrentCluster != pxFile->ulEndOfChain ) )
{
pxFile->ulAddrCurrentCluster = pxFile->ulEndOfChain;
}
/* By default, 'ffconfigFILE_EXTEND_FLUSHES_BUFFERS' is
* defined as 1.
* Users may set it to zero in order to increase the
* speed of writing to disk. */
#if ( ffconfigFILE_EXTEND_FLUSHES_BUFFERS != 0 )
{
FF_Error_t xTempError;
xTempError = FF_FlushCache( pxIOManager );
if( FF_isERR( xError ) == pdFALSE )
{
xError = xTempError;
}
}
#endif /* ffconfigFILE_EXTEND_FLUSHES_BUFFERS */
if( pxFile->ulFilePointer == pxFile->ulFileSize )
{
/* Writing at the end of a file, while new clusters have just been added.
* Make sure that the fields 'ulCurrentCluster' and 'ulAddrCurrentCluster' are
* set correctly.
*/
if( ( pxFile->ulValidFlags & FF_VALID_FLAG_EXTENDED ) == 0U )
{
pxFile->ulValidFlags |= FF_VALID_FLAG_EXTENDED;
FF_Error_t xTempError = FF_ERR_NONE;
uint32_t ulNewCluster = FF_getClusterChainNumber( pxIOManager, pxFile->ulFilePointer, 1 );
FF_LockFAT( pxIOManager );
{
pxFile->ulAddrCurrentCluster = FF_TraverseFAT( pxIOManager, pxFile->ulObjectCluster, ulNewCluster, &( xTempError ) );
pxFile->ulCurrentCluster = ulNewCluster;
}
FF_UnlockFAT( pxIOManager );
if( FF_isERR( xError ) == pdFALSE )
{
xError = xTempError;
}
}
}
} /* if( ulTotalClustersNeeded > pxFile->ulChainLength ) */
return xError;
} /* FF_ExtendFile() */