in ff_file.c [853:1069]
FF_Error_t FF_Move( FF_IOManager_t * pxIOManager,
const FF_T_WCHAR * szSourceFile,
const FF_T_WCHAR * szDestinationFile,
BaseType_t xDeleteIfExists )
#else
FF_Error_t FF_Move( FF_IOManager_t * pxIOManager,
const char * szSourceFile,
const char * szDestinationFile,
BaseType_t xDeleteIfExists )
#endif
{
FF_Error_t xError;
FF_FILE * pSrcFile, * pxDestFile;
FF_DirEnt_t xMyFile;
uint8_t ucEntryBuffer[ 32 ];
BaseType_t xIndex;
uint32_t ulDirCluster = 0ul;
FF_FetchContext_t xFetchContext;
#if ( ffconfigPATH_CACHE != 0 )
BaseType_t xIsDirectory = pdFALSE;
#endif
memset( &xFetchContext, '\0', sizeof( xFetchContext ) );
if( pxIOManager == NULL )
{
xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_MOVE );
}
#if ( ffconfigREMOVABLE_MEDIA != 0 )
else if( ( pxIOManager->ucFlags & FF_IOMAN_DEVICE_IS_EXTRACTED ) != 0 )
{
xError = ( FF_Error_t ) ( FF_ERR_IOMAN_DRIVER_NOMEDIUM | FF_MOVE );
}
#endif /* ffconfigREMOVABLE_MEDIA */
else
{
/* Check destination file doesn't exist! */
pxDestFile = FF_Open( pxIOManager, szDestinationFile, FF_MODE_READ, &xError );
if( ( pxDestFile != NULL ) || ( FF_GETERROR( xError ) == FF_ERR_FILE_OBJECT_IS_A_DIR ) )
{
xError = ( FF_Error_t ) ( FF_ERR_FILE_DESTINATION_EXISTS | FF_MOVE );
if( pxDestFile != NULL )
{
FF_Close( pxDestFile );
if( xDeleteIfExists != pdFALSE )
{
xError = FF_RmFile( pxIOManager, szDestinationFile );
}
}
}
else
{
/* Discard the error set by FF_Open().
* The target file (or directory) is not found: continue renaming. */
xError = FF_ERR_NONE;
}
}
if( FF_isERR( xError ) == pdFALSE )
{
/* About to move/rename 'szSourceFile'. When opening it with 'FF_MODE_WRITE'
* only succeeds if it has no other open handle to it. */
pSrcFile = FF_Open( pxIOManager, szSourceFile, FF_MODE_WRITE, &xError );
if( FF_GETERROR( xError ) == FF_ERR_FILE_OBJECT_IS_A_DIR )
{
/* Open a directory for moving! */
pSrcFile = FF_Open( pxIOManager, szSourceFile, FF_MODE_DIR, &xError );
#if ( ffconfigPATH_CACHE != 0 )
xIsDirectory = pdTRUE;
#endif
}
if( pSrcFile != NULL )
{
/* Collect information about the current directory entry. */
xError = FF_InitEntryFetch( pxIOManager, pSrcFile->ulDirCluster, &xFetchContext );
if( FF_isERR( xError ) == pdFALSE )
{
xError = FF_FetchEntryWithContext( pxIOManager, pSrcFile->usDirEntry, &xFetchContext, ucEntryBuffer );
if( FF_isERR( xError ) == pdFALSE )
{
xMyFile.ucAttrib = FF_getChar( ucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );
xMyFile.ulFileSize = pSrcFile->ulFileSize;
xMyFile.ulObjectCluster = pSrcFile->ulObjectCluster;
xMyFile.usCurrentItem = 0;
xIndex = ( BaseType_t ) STRLEN( szDestinationFile );
while( xIndex != 0 )
{
if( ( szDestinationFile[ xIndex ] == '\\' ) || ( szDestinationFile[ xIndex ] == '/' ) )
{
break;
}
xIndex--;
}
/* Copy the base name of the destination file. */
STRNCPY( xMyFile.pcFileName, ( szDestinationFile + xIndex + 1 ), ffconfigMAX_FILENAME );
if( xIndex == 0 )
{
xIndex = 1;
}
/* Find the (cluster of the) directory in which the target file will be located.
* It must exist before calling FF_Move(). */
ulDirCluster = FF_FindDir( pxIOManager, szDestinationFile, xIndex, &xError );
}
}
}
if( FF_isERR( xError ) == pdFALSE )
{
if( ulDirCluster != 0ul )
{
FF_FindParams_t xFindParams;
memset( &xFindParams, '\0', sizeof( xFindParams ) );
/* Clean up because FF_CreateDirent might want to write to the same sector. */
xError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
if( FF_isERR( xError ) == pdFALSE )
{
/* Destination directory was found, we can now create the new entry. */
xFindParams.ulDirCluster = ulDirCluster;
xError = FF_CreateDirent( pxIOManager, &xFindParams, &xMyFile );
}
if( FF_isERR( xError ) == pdFALSE )
{
/* Edit the Directory Entry! (So it appears as deleted); */
FF_LockDirectory( pxIOManager );
{
xError = FF_RmLFNs( pxIOManager, pSrcFile->usDirEntry, &xFetchContext );
if( FF_isERR( xError ) == pdFALSE )
{
xError = FF_FetchEntryWithContext( pxIOManager, pSrcFile->usDirEntry, &xFetchContext, ucEntryBuffer );
if( FF_isERR( xError ) == pdFALSE )
{
FF_Error_t xTempError;
ucEntryBuffer[ 0 ] = FF_FAT_DELETED;
FF_putShort( ucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH, ( uint32_t ) 0ul );
FF_putShort( ucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW, ( uint32_t ) 0ul );
xError = FF_PushEntryWithContext( pxIOManager, pSrcFile->usDirEntry, &xFetchContext, ucEntryBuffer );
/* The contents of 'xFetchContext' has changed, flush it to disk now. */
xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
if( FF_isERR( xError ) == pdFALSE )
{
xError = xTempError;
}
}
}
}
FF_UnlockDirectory( pxIOManager );
}
#if ( ffconfigPATH_CACHE != 0 )
{
if( xIsDirectory != 0 )
{
/* We've renamed a directory which might contain
* subdirectories. To avoid having false entries, clear
* the path cache. */
FF_RmPathCache( pxIOManager, szSourceFile );
}
}
#endif
}
else /* ulDirCluster == 0ul */
{
xError = ( FF_Error_t ) ( FF_ERR_FILE_DIR_NOT_FOUND | FF_MOVE );
}
}
if( pSrcFile != NULL )
{
/* The source file was opened in WRITE mode just to lock it.
* Now clear the write flags to avoid writing back any changes. */
pSrcFile->ucMode &= ~( FF_MODE_WRITE | FF_MODE_APPEND | FF_MODE_CREATE );
FF_Close( pSrcFile );
}
}
{
FF_Error_t xTempError;
xTempError = FF_FlushCache( pxIOManager );
if( FF_isERR( xError ) == pdFALSE )
{
xError = xTempError;
}
xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
if( FF_isERR( xError ) == pdFALSE )
{
xError = xTempError;
}
}
return xError;
} /* FF_Move() */