FF_Error_t FF_CreateDirent()

in ff_dir.c [2916:3104]


FF_Error_t FF_CreateDirent( FF_IOManager_t * pxIOManager,
                            FF_FindParams_t * pxFindParams,
                            FF_DirEnt_t * pxDirEntry )
{
    uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];

    BaseType_t xLFNCount;
    int32_t lFreeEntry = 0L;
    FF_Error_t xReturn = FF_ERR_NONE;
    BaseType_t xEntryCount;
    FF_FetchContext_t xFetchContext;
    uint32_t ulDirCluster = pxFindParams->ulDirCluster;
    int32_t lFitShort;

    #if ( ffconfigHASH_CACHE != 0 )
        char pcShortName[ 13 ];
    #endif
    #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
        uint16_t NameLen = ( uint16_t ) wcslen( pxDirEntry->pcFileName );
    #else
        uint16_t NameLen = ( uint16_t ) strlen( pxDirEntry->pcFileName );
    #endif

    #if ( ffconfigLFN_SUPPORT != 0 )
        uint8_t ucCheckSum;
    #endif

    /* Round-up the number of LFN's needed: */
    xLFNCount = ( BaseType_t ) ( ( NameLen + 12 ) / 13 );

    #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
        {
            FF_MakeNameCompliant( pxDirEntry->pcFileName ); /* Ensure we don't break the Dir tables. */
        }
    #else
        {
            FF_MakeNameCompliant( pxDirEntry->pcFileName ); /* Ensure we don't break the Dir tables. */
        }
    #endif
    memset( pucEntryBuffer, 0, sizeof( pucEntryBuffer ) );

    #if ( ffconfigLFN_SUPPORT != 0 )
        {
            /* Create and push the LFN's. */
            /* Find enough places for the LFNs and the ShortName. */
            xEntryCount = xLFNCount + 1;
        }
    #else
        {
            xEntryCount = 1;
        }
    #endif

    /* Create the ShortName. */
    FF_LockDirectory( pxIOManager );

    do
    {
        /* Open a do {} while( pdFALSE ) loop to allow the use of break statements. */
        /* As FF_FindShortName( ) can fail, it should be called before finding a free directory entry. */
        if( ( pxFindParams->ulFlags & FIND_FLAG_SHORTNAME_SET ) == 0 )
        {
            FF_CreateShortName( pxFindParams, pxDirEntry->pcFileName );
        }

        lFitShort = FF_FindShortName( pxIOManager, pxFindParams );

        memcpy( pucEntryBuffer, pxFindParams->pcEntryBuffer, sizeof( pucEntryBuffer ) );

        if( FF_isERR( lFitShort ) )
        {
            xReturn = lFitShort;
            break;
        }

        if( lFitShort != 0 )
        {
            /* There is no need to create a LFN entry because the file name
             * fits into a normal 32-byte entry.. */
            xLFNCount = 0;
            xEntryCount = 1;
        }

        lFreeEntry = FF_FindFreeDirent( pxIOManager, pxFindParams, ( uint16_t ) xEntryCount );

        if( FF_isERR( lFreeEntry ) )
        {
            xReturn = lFreeEntry;
            break;
        }

        #if ( ffconfigLFN_SUPPORT != 0 )
            {
                if( xLFNCount > 0 )
                {
                    ucCheckSum = FF_CreateChkSum( pucEntryBuffer );
                    xReturn = FF_CreateLFNs( pxIOManager, ulDirCluster, pxDirEntry->pcFileName, ucCheckSum, ( uint16_t ) lFreeEntry );
                }
            }
        #else
            {
                xLFNCount = 0;
            }
        #endif /* ffconfigLFN_SUPPORT */

        if( FF_isERR( xReturn ) == pdFALSE )
        {
            #if ( ffconfigTIME_SUPPORT != 0 )
                {
                    FF_GetSystemTime( &pxDirEntry->xCreateTime );        /* Date and Time Created. */
                    pxDirEntry->xModifiedTime = pxDirEntry->xCreateTime; /* Date and Time Modified. */
                    pxDirEntry->xAccessedTime = pxDirEntry->xCreateTime; /* Date of Last Access. */
                    FF_PlaceTime( pucEntryBuffer, FF_FAT_DIRENT_CREATE_TIME, &pxDirEntry->xCreateTime );
                    FF_PlaceDate( pucEntryBuffer, FF_FAT_DIRENT_CREATE_DATE, &pxDirEntry->xCreateTime );
                    FF_PlaceTime( pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME, &pxDirEntry->xModifiedTime );
                    FF_PlaceDate( pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE, &pxDirEntry->xModifiedTime );
                }
            #endif /*  ffconfigTIME_SUPPORT */

            FF_putChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB, pxDirEntry->ucAttrib );
            #if ( ffconfigSHORTNAME_CASE != 0 )
                FF_putChar( pucEntryBuffer, FF_FAT_CASE_OFFS, ( uint32_t ) lFitShort & ( FF_FAT_CASE_ATTR_BASE | FF_FAT_CASE_ATTR_EXT ) );
            #endif
            FF_putShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH, ( uint16_t ) ( pxDirEntry->ulObjectCluster >> 16 ) );
            FF_putShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW, ( uint16_t ) ( pxDirEntry->ulObjectCluster ) );
            FF_putLong( pucEntryBuffer, FF_FAT_DIRENT_FILESIZE, pxDirEntry->ulFileSize );

            xReturn = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );

            if( FF_isERR( xReturn ) )
            {
                break;
            }

            xReturn = FF_PushEntryWithContext( pxIOManager, ( uint16_t ) ( lFreeEntry + xLFNCount ), &xFetchContext, pucEntryBuffer );

            {
                FF_Error_t xTempError;

                xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );

                if( FF_isERR( xReturn ) == pdFALSE )
                {
                    xReturn = xTempError;
                }
            }

            if( FF_isERR( xReturn ) )
            {
                break;
            }

            #if ( ffconfigHASH_CACHE != 0 )
                {
                    if( FF_DirHashed( pxIOManager, ulDirCluster ) == pdFALSE )
                    {
                        /* Hash the directory. */
                        FF_HashDir( pxIOManager, ulDirCluster );
                    }

                    memcpy( pcShortName, pucEntryBuffer, 11 );
                    FF_ProcessShortName( pcShortName ); /* Format the shortname to 8.3. */
                    #if ( ffconfigHASH_FUNCTION == CRC16 )
                        {
                            FF_AddDirentHash( pxIOManager, ulDirCluster, ( uint32_t ) FF_GetCRC16( ( uint8_t * ) pcShortName, strlen( pcShortName ) ) );
                        }
                    #elif ( ffconfigHASH_FUNCTION == CRC8 )
                        {
                            FF_AddDirentHash( pxIOManager, ulDirCluster, ( uint32_t ) FF_GetCRC8( ( uint8_t * ) pcShortName, strlen( pcShortName ) ) );
                        }
                    #endif /* ffconfigHASH_FUNCTION */
                }
            #endif /* ffconfigHASH_CACHE*/
        }
    }
    while( pdFALSE );

    FF_UnlockDirectory( pxIOManager );

    if( FF_isERR( xReturn ) == pdFALSE )
    {
        if( pxDirEntry != NULL )
        {
            pxDirEntry->usCurrentItem = ( uint16_t ) ( lFreeEntry + xLFNCount );
        }
    }

    return xReturn;
}   /* FF_CreateDirent() */