in ff_file.c [2219:2449]
int32_t FF_Write( FF_FILE * pxFile,
uint32_t ulElementSize,
uint32_t ulCount,
uint8_t * pucBuffer )
{
uint32_t ulBytesLeft = ulElementSize * ulCount;
uint32_t nBytesWritten = 0;
uint32_t nBytesToWrite;
FF_IOManager_t * pxIOManager;
uint32_t ulRelBlockPos;
uint32_t ulItemLBA;
int32_t lResult;
uint32_t ulSectors;
uint32_t ulRelClusterPos;
uint32_t ulBytesPerCluster;
FF_Error_t xError;
if( pxFile == NULL )
{
xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_READ );
}
else
{
/* Check validity of the handle and the current position within the file. */
xError = FF_CheckValid( pxFile );
if( FF_isERR( xError ) == pdFALSE )
{
if( ( pxFile->ucMode & FF_MODE_WRITE ) == 0 )
{
xError = ( FF_Error_t ) ( FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE | FF_WRITE );
}
/* Make sure a write is after the append point. */
else if( ( pxFile->ucMode & FF_MODE_APPEND ) != 0 )
{
if( pxFile->ulFilePointer < pxFile->ulFileSize )
{
xError = FF_Seek( pxFile, 0, FF_SEEK_END );
}
}
}
}
if( FF_isERR( xError ) == pdFALSE )
{
pxIOManager = pxFile->pxIOManager;
/* Open a do{} while( 0 ) loop to allow the use of breaks */
do
{
/* Extend File for at least ulBytesLeft!
* Handle file-space allocation
+ 1 byte because the code assumes there is always a next cluster */
xError = FF_ExtendFile( pxFile, pxFile->ulFilePointer + ulBytesLeft + 1 );
if( FF_isERR( xError ) )
{
/* On every error, break from the while( 0 ) loop. */
break;
}
ulRelBlockPos = FF_getMinorBlockEntry( pxIOManager, pxFile->ulFilePointer, 1 ); /* Get the position within a block. */
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
if( ( ulRelBlockPos + ulBytesLeft ) <= ( uint32_t ) pxIOManager->usSectorSize )
{
/* Bytes to write are within a block and and do not go passed the current block. */
nBytesWritten = FF_WritePartial( pxFile, ulItemLBA, ulRelBlockPos, ulBytesLeft, pucBuffer, &xError );
break;
}
/*---------- Write (memcpy) to a Sector Boundary. */
if( ulRelBlockPos != 0 )
{
/* Not writing on a sector boundary, at this point the LBA is known. */
nBytesToWrite = pxIOManager->usSectorSize - ulRelBlockPos;
nBytesWritten = FF_WritePartial( pxFile, ulItemLBA, ulRelBlockPos, nBytesToWrite, pucBuffer, &xError );
if( FF_isERR( xError ) )
{
break;
}
ulBytesLeft -= nBytesWritten;
pucBuffer += nBytesWritten;
}
/*---------- Write sectors, up to a Cluster Boundary. */
ulBytesPerCluster = ( pxIOManager->xPartition.ulSectorsPerCluster * pxIOManager->usSectorSize );
ulRelClusterPos = FF_getClusterPosition( pxIOManager, pxFile->ulFilePointer, 1 );
if( ( ulRelClusterPos != 0 ) && ( ( ulRelClusterPos + ulBytesLeft ) >= ulBytesPerCluster ) )
{
/* Need to get to cluster boundary */
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
ulSectors = pxIOManager->xPartition.ulSectorsPerCluster - ( ulRelClusterPos / pxIOManager->usSectorSize );
xError = FF_BlockWrite( pxIOManager, ulItemLBA, ulSectors, pucBuffer, pdFALSE );
if( FF_isERR( xError ) )
{
break;
}
nBytesToWrite = ulSectors * pxIOManager->usSectorSize;
ulBytesLeft -= nBytesToWrite;
pucBuffer += nBytesToWrite;
nBytesWritten += nBytesToWrite;
pxFile->ulFilePointer += nBytesToWrite;
if( pxFile->ulFilePointer > pxFile->ulFileSize )
{
pxFile->ulFileSize = pxFile->ulFilePointer;
}
}
/*---------- Write entire Clusters. */
if( ulBytesLeft >= ulBytesPerCluster )
{
uint32_t ulClusters;
FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
ulClusters = ( ulBytesLeft / ulBytesPerCluster );
xError = FF_WriteClusters( pxFile, ulClusters, pucBuffer );
if( FF_isERR( xError ) )
{
break;
}
nBytesToWrite = ulBytesPerCluster * ulClusters;
ulBytesLeft -= nBytesToWrite;
pucBuffer += nBytesToWrite;
nBytesWritten += nBytesToWrite;
pxFile->ulFilePointer += nBytesToWrite;
if( pxFile->ulFilePointer > pxFile->ulFileSize )
{
pxFile->ulFileSize = pxFile->ulFilePointer;
}
}
/*---------- Write Remaining Blocks */
while( ulBytesLeft >= ( uint32_t ) pxIOManager->usSectorSize )
{
ulSectors = ulBytesLeft / pxIOManager->usSectorSize;
{
/* HT: I'd leave these pPart/ulOffset for readability... */
FF_Partition_t * pPart = &( pxIOManager->xPartition );
uint32_t ulOffset = ( pxFile->ulFilePointer / pxIOManager->usSectorSize ) % pPart->ulSectorsPerCluster;
uint32_t ulRemain = pPart->ulSectorsPerCluster - ulOffset;
if( ulSectors > ulRemain )
{
ulSectors = ulRemain;
}
}
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
xError = FF_BlockWrite( pxIOManager, ulItemLBA, ulSectors, pucBuffer, pdFALSE );
if( FF_isERR( xError ) )
{
break;
}
nBytesToWrite = ulSectors * pxIOManager->usSectorSize;
ulBytesLeft -= nBytesToWrite;
pucBuffer += nBytesToWrite;
nBytesWritten += nBytesToWrite;
pxFile->ulFilePointer += nBytesToWrite;
if( pxFile->ulFilePointer > pxFile->ulFileSize )
{
pxFile->ulFileSize = pxFile->ulFilePointer;
}
}
/*---------- Write (memcpy) Remaining Bytes */
if( ulBytesLeft == 0 )
{
break;
}
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
FF_WritePartial( pxFile, ulItemLBA, 0, ulBytesLeft, pucBuffer, &xError );
nBytesWritten += ulBytesLeft;
}
while( pdFALSE );
}
if( FF_isERR( xError ) )
{
lResult = xError;
}
else
{
lResult = ( int32_t ) ( nBytesWritten / ulElementSize );
}
return lResult;
} /* FF_Write() */