Skip to content

Commit d43050a

Browse files
togrueifta-togrue
andauthored
Change the FF_MakeNameCompliant behavior (#63)
* Change the handling of invalid file-names to cause an error. Depending on the entry to create (directory/file), a different error code is returned. Description ----------- This changes the behavior of the FF_CreateDirent function to return an error in case of an invalid path. Filenames with the first character of 0xE5 are still modified. (Which might have some issues. TODO) Note: Invalid directory paths and invalid file paths now result in two different FreeRTOS+ return values. Is this the intended behavior or should only one error code be used? ``` case FF_ERR_FILE_INVALID_PATH: return pdFREERTOS_ERRNO_ENOTDIR; /* The path of the file was not found. */ case FF_ERR_DIR_INVALID_PATH: return pdFREERTOS_ERRNO_EINVAL; /* Could not find the directory specified by the path. */ ``` FF_MakeNameCompliant returns a boolean and not an error-code, because the function would need an additional parameter to select the right error code (FF_ERR_DIR_INVALID_PATH or FF_ERR_FILE_INVALID_PATH). Test Steps ----------- A invalid filepath "test:file.txt" resulted in setting the FF_ERR_FILE_INVALID_PATH. (Tested through breakpoint in prvFFErrorToErrno). Todo: - mkdir with invalid path - handling of names starting with 0xE5 Checklist: ---------- <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [ ] I have tested my changes. No regression in existing tests. - [ ] I have modified and/or added unit-tests to cover the code changes in this Pull Request. Related Issue ----------- <!-- If any, please provide issue ID. --> By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --------- Co-authored-by: Tobias Gruen <[email protected]>
1 parent bfb0357 commit d43050a

File tree

4 files changed

+84
-52
lines changed

4 files changed

+84
-52
lines changed

ff_dir.c

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,6 @@ static BaseType_t FF_ValidShortChar( char cChar );
134134
#endif /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
135135
#endif /* if ( ffconfigLFN_SUPPORT != 0 ) */
136136

137-
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
138-
static void FF_MakeNameCompliant( FF_T_WCHAR * pcName );
139-
#else
140-
static void FF_MakeNameCompliant( char * pcName );
141-
#endif
142-
143137
#if ( FF_NOSTRCASECMP == 0 )
144138
static portINLINE unsigned char prvToLower( unsigned char c )
145139
{
@@ -2875,40 +2869,48 @@ FF_Error_t FF_ExtendDirectory( FF_IOManager_t * pxIOManager,
28752869
} /* FF_ExtendDirectory() */
28762870
/*-----------------------------------------------------------*/
28772871

2878-
static const uint8_t forbiddenChrs[] =
2872+
/* *INDENT-OFF* */
2873+
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
2874+
static const FF_T_WCHAR forbiddenChars[] =
2875+
#else
2876+
static const uint8_t forbiddenChars[] =
2877+
#endif
28792878
{
28802879
/* Windows says: don't use these characters: '\/:*?"<>|'
28812880
* " * / : < > ? '\' ? | */
28822881
0x22, 0x2A, 0x2F, 0x3A, 0x3C, 0x3E, 0x3F, 0x5C, 0x7F, 0x7C
28832882
};
2883+
/* *INDENT-ON* */
28842884

28852885
/* *INDENT-OFF* */
28862886
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
2887-
static void FF_MakeNameCompliant( FF_T_WCHAR * pcName )
2887+
BaseType_t FF_IsNameCompliant( FF_T_WCHAR * pcName )
28882888
#else
2889-
static void FF_MakeNameCompliant( char * pcName )
2889+
BaseType_t FF_IsNameCompliant( char * pcName )
28902890
#endif
28912891
/* *INDENT-ON* */
28922892
{
2893+
BaseType_t xReturn = pdTRUE;
28932894
BaseType_t index;
28942895

2895-
if( ( uint8_t ) pcName[ 0 ] == FF_FAT_DELETED ) /* Support Japanese KANJI symbol0xE5. */
2896+
if( ( uint8_t ) pcName[ 0 ] == FF_FAT_DELETED ) /* Do not create a "deleted" entry 0xE5. */
28962897
{
2897-
pcName[ 0 ] = 0x05;
2898+
xReturn = pdFALSE;
28982899
}
28992900

29002901
for( ; *pcName; pcName++ )
29012902
{
2902-
for( index = 0; index < ( BaseType_t ) sizeof( forbiddenChrs ); index++ )
2903+
for( index = 0; index < ( BaseType_t ) ( sizeof( forbiddenChars ) / sizeof( forbiddenChars[ 0 ] ) ); index++ )
29032904
{
2904-
if( *pcName == forbiddenChrs[ index ] )
2905+
if( *pcName == forbiddenChars[ index ] )
29052906
{
2906-
*pcName = '_';
2907-
break;
2907+
xReturn = pdFALSE;
29082908
}
29092909
}
29102910
}
2911-
} /* FF_MakeNameCompliant() */
2911+
2912+
return xReturn;
2913+
} /* FF_IsNameCompliant() */
29122914
/*-----------------------------------------------------------*/
29132915

29142916
FF_Error_t FF_CreateDirent( FF_IOManager_t * pxIOManager,
@@ -2941,15 +2943,6 @@ FF_Error_t FF_CreateDirent( FF_IOManager_t * pxIOManager,
29412943
/* Round-up the number of LFN's needed: */
29422944
xLFNCount = ( BaseType_t ) ( ( NameLen + 12 ) / 13 );
29432945

2944-
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
2945-
{
2946-
FF_MakeNameCompliant( pxDirEntry->pcFileName ); /* Ensure we don't break the Dir tables. */
2947-
}
2948-
#else
2949-
{
2950-
FF_MakeNameCompliant( pxDirEntry->pcFileName ); /* Ensure we don't break the Dir tables. */
2951-
}
2952-
#endif
29532946
memset( pucEntryBuffer, 0, sizeof( pucEntryBuffer ) );
29542947

29552948
#if ( ffconfigLFN_SUPPORT != 0 )
@@ -3127,7 +3120,15 @@ FF_Error_t FF_CreateDirent( FF_IOManager_t * pxIOManager,
31273120
STRNCPY( xMyFile.pcFileName, pcFileName, ffconfigMAX_FILENAME - 1 );
31283121
xMyFile.pcFileName[ ffconfigMAX_FILENAME - 1 ] = 0;
31293122

3130-
xMyFile.ulObjectCluster = FF_CreateClusterChain( pxIOManager, &xError );
3123+
if( FF_IsNameCompliant( xMyFile.pcFileName ) == pdFALSE )
3124+
{
3125+
xError = FF_createERR( FF_ERR_FILE_INVALID_PATH, FF_CREATEFILE );
3126+
}
3127+
3128+
if( FF_isERR( xError ) == pdFALSE )
3129+
{
3130+
xMyFile.ulObjectCluster = FF_CreateClusterChain( pxIOManager, &xError );
3131+
}
31313132

31323133
if( FF_isERR( xError ) == pdFALSE )
31333134
{
@@ -3269,6 +3270,12 @@ FF_Error_t FF_CreateDirent( FF_IOManager_t * pxIOManager,
32693270
break;
32703271
}
32713272

3273+
if( FF_IsNameCompliant( pcDirName ) == pdFALSE )
3274+
{
3275+
xError = FF_createERR( FF_ERR_DIR_INVALID_PATH, FF_MKDIR );
3276+
break;
3277+
}
3278+
32723279
xFindParams.ulDirCluster = FF_FindDir( pxIOManager, pcPath, ( uint16_t ) xIndex, &xError );
32733280

32743281
if( FF_isERR( xError ) )

ff_file.c

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,7 @@ static FF_FILE * prvAllocFileHandle( FF_IOManager_t * pxIOManager,
868868
* @retval FF_ERR_FILE_DESTINATION_EXISTS if the destination file exists.
869869
* @retval FF_ERR_FILE_COULD_NOT_CREATE_DIRENT if dirent creation failed (fatal error!).
870870
* @retval FF_ERR_FILE_DIR_NOT_FOUND if destination directory was not found.
871+
* @retval FF_ERR_FILE_INVALID_PATH if destination path is invalid.
871872
* @retval FF_ERR_FILE_SOURCE_NOT_FOUND if the source file was not found.
872873
*
873874
**/
@@ -886,11 +887,11 @@ static FF_FILE * prvAllocFileHandle( FF_IOManager_t * pxIOManager,
886887
#endif
887888
/* *INDENT-ON* */
888889
{
889-
FF_Error_t xError;
890+
FF_Error_t xError = FF_ERR_NONE;
890891
FF_FILE * pSrcFile, * pxDestFile;
891892
FF_DirEnt_t xMyFile;
892893
uint8_t ucEntryBuffer[ 32 ];
893-
UBaseType_t xIndex;
894+
size_t uxIndex = 0U;
894895
uint32_t ulDirCluster = 0ul;
895896
FF_FetchContext_t xFetchContext;
896897

@@ -906,12 +907,46 @@ static FF_FILE * prvAllocFileHandle( FF_IOManager_t * pxIOManager,
906907
}
907908

908909
#if ( ffconfigREMOVABLE_MEDIA != 0 )
909-
else if( ( pxIOManager->ucFlags & FF_IOMAN_DEVICE_IS_EXTRACTED ) != 0 )
910+
else if( ( pxIOManager->ucFlags & FF_IOMAN_DEVICE_IS_EXTRACTED ) != 0U )
910911
{
911912
xError = FF_createERR( FF_ERR_IOMAN_DRIVER_NOMEDIUM, FF_MOVE );
912913
}
913914
#endif /* ffconfigREMOVABLE_MEDIA */
914-
else
915+
916+
if( FF_isERR( xError ) == pdFALSE )
917+
{
918+
uxIndex = ( size_t ) STRLEN( szDestinationFile );
919+
920+
/* Find the base name. */
921+
while( uxIndex != 0U )
922+
{
923+
if( ( szDestinationFile[ uxIndex ] == '\\' ) || ( szDestinationFile[ uxIndex ] == '/' ) )
924+
{
925+
break;
926+
}
927+
928+
uxIndex--;
929+
}
930+
931+
/* Copy the base name of the destination file. */
932+
STRNCPY( xMyFile.pcFileName, ( szDestinationFile + uxIndex + 1 ), ffconfigMAX_FILENAME - 1 );
933+
xMyFile.pcFileName[ ffconfigMAX_FILENAME - 1 ] = 0;
934+
935+
/* Now check if the target base name is compliant. */
936+
if( FF_IsNameCompliant( xMyFile.pcFileName ) == pdFALSE )
937+
{
938+
xError = FF_createERR( FF_ERR_FILE_INVALID_PATH, FF_MOVE );
939+
}
940+
941+
if( uxIndex == 0U )
942+
{
943+
/* Give the directory part a minimum
944+
* length of 1, to get '/' at least. */
945+
uxIndex = 1U;
946+
}
947+
}
948+
949+
if( FF_isERR( xError ) == pdFALSE )
915950
{
916951
/* Check destination file doesn't exist! */
917952
pxDestFile = FF_Open( pxIOManager, szDestinationFile, FF_MODE_READ, &xError );
@@ -969,30 +1004,9 @@ static FF_FILE * prvAllocFileHandle( FF_IOManager_t * pxIOManager,
9691004
xMyFile.ulObjectCluster = pSrcFile->ulObjectCluster;
9701005
xMyFile.usCurrentItem = 0;
9711006

972-
xIndex = ( UBaseType_t ) STRLEN( szDestinationFile );
973-
974-
while( xIndex != 0 )
975-
{
976-
if( ( szDestinationFile[ xIndex ] == '\\' ) || ( szDestinationFile[ xIndex ] == '/' ) )
977-
{
978-
break;
979-
}
980-
981-
xIndex--;
982-
}
983-
984-
/* Copy the base name of the destination file. */
985-
STRNCPY( xMyFile.pcFileName, ( szDestinationFile + xIndex + 1 ), ffconfigMAX_FILENAME - 1 );
986-
xMyFile.pcFileName[ ffconfigMAX_FILENAME - 1 ] = 0;
987-
988-
if( xIndex == 0 )
989-
{
990-
xIndex = 1;
991-
}
992-
9931007
/* Find the (cluster of the) directory in which the target file will be located.
9941008
* It must exist before calling FF_Move(). */
995-
ulDirCluster = FF_FindDir( pxIOManager, szDestinationFile, ( uint16_t ) xIndex, &xError );
1009+
ulDirCluster = FF_FindDir( pxIOManager, szDestinationFile, ( uint16_t ) uxIndex, &xError );
9961010
}
9971011
}
9981012
}

include/ff_dir.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ int8_t FF_PushEntry( FF_IOManager_t * pxIOManager,
172172
uint8_t * buffer,
173173
void * pParam );
174174

175+
/*
176+
* FF_IsNameCompliant is a function that checks if a given path name
177+
* contains any legal characters only.
178+
*/
179+
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
180+
BaseType_t FF_IsNameCompliant( FF_T_WCHAR * pcName );
181+
#else
182+
BaseType_t FF_IsNameCompliant( char * pcName );
183+
#endif
184+
175185
static portINLINE BaseType_t FF_isEndOfDir( const uint8_t * pucEntryBuffer )
176186
{
177187
return pucEntryBuffer[ 0 ] == ( uint8_t ) 0;

include/ff_error.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
#define FF_MKDIR ( ( 12 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
119119
#define FF_TRAVERSE ( ( 13 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
120120
#define FF_FINDDIR ( ( 14 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
121+
#define FF_CREATEFILE ( ( 15 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
121122

122123
/*----- FF_FILE - The FreeRTOS+FAT file handling routines. */
123124
#define FF_GETMODEBITS ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )

0 commit comments

Comments
 (0)