FF_Error_t FF_Move()

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() */