| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731 |
- /*
- * FreeRTOS+FAT V2.3.3
- * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * https://www.FreeRTOS.org
- * https://github.com/FreeRTOS
- *
- */
- /**
- * @file ff_dir.c
- * @ingroup DIR
- *
- * @defgroup DIR Handles Directory Traversal
- * @brief Handles DIR access and traversal.
- *
- * Provides FindFirst() and FindNext() Interfaces
- **/
- #include "ff_headers.h"
- #include <stdio.h>
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- #include <wchar.h>
- #endif
- #if defined( WIN32 )
- #define wcsicmp _wcsicmp
- #else
- #define wcsicmp wcscasecmp
- #include <ctype.h>
- #endif
- /* Calculate a simple LFN checmsum. */
- static uint8_t FF_CreateChkSum( const uint8_t * pa_pShortName );
- static BaseType_t FF_ShortNameExists( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- char * pcShortName,
- FF_Error_t * pxError );
- #if ( ffconfigSHORTNAME_CASE != 0 )
- /* For short-name entries, NT/XP etc store case information in byte 0x0c
- * Use this to show proper case of "README.txt" or "source.H".
- */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- static void FF_CaseShortName( FF_T_WCHAR * pcName,
- uint8_t attrib );
- #else
- static void FF_CaseShortName( char * pcName,
- uint8_t attrib );
- #endif
- #endif /* ffconfigSHORTNAME_CASE */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- /* For unicode, the short name can be expanded to wchar
- * by inserting zero's.
- */
- static void FF_ShortNameExpand( FF_T_WCHAR * );
- #endif
- /*
- * Transform a name as stored on disk "README__TXT"
- * to a nul-terminated string: "README.TXT", "FILE001".
- * A dot is only added if an extension is present.
- */
- static void FF_ProcessShortName( char * pcName );
- #if ( ffconfigTIME_SUPPORT != 0 )
- static void FF_PlaceTime( uint8_t * pucEntryBuffer,
- uint32_t Offset,
- FF_SystemTime_t * pxTime );
- static void FF_PlaceDate( uint8_t * pucEntryBuffer,
- uint32_t Offset,
- FF_SystemTime_t * pxTime );
- static void FF_GetTime( FF_SystemTime_t * pxTime,
- const uint8_t * pucEntryBuffer,
- uint32_t ulOffset );
- static void FF_GetDate( FF_SystemTime_t * pxTime,
- const uint8_t * pucEntryBuffer,
- uint32_t ulOffset );
- #endif /* ffconfigTIME_SUPPORT */
- static FF_Error_t FF_Traverse( FF_IOManager_t * pxIOManager,
- uint32_t ulEntry,
- FF_FetchContext_t * pxContext );
- static int32_t FF_FindFreeDirent( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams,
- uint16_t usSequential );
- #if ( ffconfigLFN_SUPPORT != 0 )
- static int8_t FF_CreateLFNEntry( uint8_t * pucEntryBuffer,
- uint8_t * pcName,
- UBaseType_t uxNameLength,
- UBaseType_t uxLFN,
- uint8_t ucCheckSum );
- #endif /* ffconfigLFN_SUPPORT */
- static BaseType_t FF_ValidShortChar( char cChar );
- #if ( ffconfigLFN_SUPPORT != 0 )
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- static FF_Error_t FF_CreateLFNs( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- FF_T_WCHAR * pcName,
- uint8_t ucCheckSum,
- uint16_t usEntry );
- #else
- static FF_Error_t FF_CreateLFNs( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- char * pcName,
- uint8_t ucCheckSum,
- uint16_t usEntry );
- #endif /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
- #endif /* if ( ffconfigLFN_SUPPORT != 0 ) */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- static void FF_MakeNameCompliant( FF_T_WCHAR * pcName );
- #else
- static void FF_MakeNameCompliant( char * pcName );
- #endif
- #if ( FF_NOSTRCASECMP == 0 )
- static portINLINE unsigned char prvToLower( unsigned char c )
- {
- unsigned char cReturnChar;
- if( ( c >= 'A' ) && ( c <= 'Z' ) )
- {
- cReturnChar = c + 0x20;
- }
- else
- {
- cReturnChar = c;
- }
- return cReturnChar;
- }
- int strcasecmp( const char * pcString1,
- const char * pcString2 )
- {
- unsigned char c1, c2;
- do
- {
- c1 = *pcString1++;
- c2 = *pcString2++;
- c1 = ( unsigned char ) prvToLower( ( unsigned char ) c1 );
- c2 = ( unsigned char ) prvToLower( ( unsigned char ) c2 );
- }
- while( ( c1 == c2 ) && ( c1 != '\0' ) );
- return ( int ) c1 - c2;
- } /* strcasecmp() */
- #endif /* if ( FF_NOSTRCASECMP == 0 ) */
- /*-----------------------------------------------------------*/
- static uint8_t FF_CreateChkSum( const uint8_t * pa_pShortName )
- {
- uint8_t cNameLen;
- uint8_t ChkSum = 0;
- for( cNameLen = 11; cNameLen != 0; cNameLen-- )
- {
- ChkSum = ( uint8_t )
- ( ( ( ChkSum & 1 ) ? 0x80 : 0 ) + ( ChkSum >> 1 ) + *( pa_pShortName++ ) );
- }
- return ChkSum;
- } /* FF_CreateChkSum() */
- /*-----------------------------------------------------------*/
- /* _HT_ Does not need a wchar version because a short name is treated a normal string of bytes */
- static BaseType_t FF_ShortNameExists( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- char * pcShortName,
- FF_Error_t * pxError )
- {
- BaseType_t xIndex;
- const uint8_t * pucEntryBuffer = NULL; /* initialisation not necessary, just for the compiler */
- uint8_t ucAttrib;
- FF_FetchContext_t xFetchContext;
- char pcMyShortName[ FF_SIZEOF_DIRECTORY_ENTRY ];
- BaseType_t xResult = -1;
- #if ( ffconfigHASH_CACHE != 0 )
- uint32_t ulHash;
- #endif
- *pxError = FF_ERR_NONE;
- #if ( ffconfigHASH_CACHE != 0 )
- {
- if( !FF_DirHashed( pxIOManager, ulDirCluster ) )
- {
- /* Hash the directory. */
- FF_HashDir( pxIOManager, ulDirCluster );
- }
- #if ffconfigHASH_FUNCTION == CRC16
- {
- ulHash = ( uint32_t ) FF_GetCRC16( ( uint8_t * ) pcShortName, strlen( pcShortName ) );
- }
- #else /* ffconfigHASH_FUNCTION == CRC8 */
- {
- ulHash = ( uint32_t ) FF_GetCRC8( ( uint8_t * ) pcShortName, strlen( pcShortName ) );
- }
- #endif
- {
- /* FF_CheckDirentHash result: 0 not found, 1 found, -1 directory not hashed */
- xResult = FF_CheckDirentHash( pxIOManager, ulDirCluster, ulHash );
- }
- }
- #endif /* if ( ffconfigHASH_CACHE != 0 ) */
- if( xResult < 0 )
- {
- xResult = pdFALSE;
- *pxError = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );
- if( FF_isERR( *pxError ) == pdFALSE )
- {
- for( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ )
- {
- /* Call FF_FetchEntryWithContext only once for every block (usually 512 bytes) */
- if( ( xIndex == 0 ) ||
- ( pucEntryBuffer >= xFetchContext.pxBuffer->pucBuffer + ( pxIOManager->usSectorSize - FF_SIZEOF_DIRECTORY_ENTRY ) ) )
- {
- *pxError = FF_FetchEntryWithContext( pxIOManager, ( uint32_t ) xIndex, &xFetchContext, NULL );
- if( FF_isERR( *pxError ) )
- {
- break;
- }
- pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer;
- }
- else
- {
- /* Advance 32 bytes to get the next directory entry. */
- pucEntryBuffer += FF_SIZEOF_DIRECTORY_ENTRY;
- }
- if( FF_isEndOfDir( pucEntryBuffer ) )
- {
- break;
- }
- if( FF_isDeleted( pucEntryBuffer ) == pdFALSE )
- {
- ucAttrib = FF_getChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB );
- if( ( ucAttrib & FF_FAT_ATTR_LFN ) != FF_FAT_ATTR_LFN )
- {
- memcpy( pcMyShortName, pucEntryBuffer, sizeof( pcMyShortName ) );
- FF_ProcessShortName( pcMyShortName );
- if( strcmp( ( const char * ) pcShortName, ( const char * ) pcMyShortName ) == 0 )
- {
- xResult = pdTRUE;
- break;
- }
- }
- }
- } /* for ( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ ) */
- }
- *pxError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- }
- return xResult;
- } /* FF_ShortNameExists() */
- /*-----------------------------------------------------------*/
- /* _HT_ When adding many files to a single directory, FF_FindEntryInDir was sometimes */
- /* _HT_ called 3 times before inserting a single file. With these changes it is called one time only */
- /* _HT_ pxFindParams caches some information: */
- /* _HT_ 1: the first free entry 2: whether the short-name version already exists */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- uint32_t FF_FindEntryInDir( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams,
- const FF_T_WCHAR * pcName,
- uint8_t pa_Attrib,
- FF_DirEnt_t * pxDirEntry,
- FF_Error_t * pxError )
- #else
- uint32_t FF_FindEntryInDir( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams,
- const char * pcName,
- uint8_t pa_Attrib,
- FF_DirEnt_t * pxDirEntry,
- FF_Error_t * pxError )
- #endif /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
- {
- FF_FetchContext_t xFetchContext;
- /* const pointer to read from pBuffer */
- const uint8_t * src = NULL;
- /* As we're walking through a directory, we might as well
- * find the first free entry to help FF_FindFreeDirent( )
- * The result will be stored in 'pxFindParams->lFreeEntry' */
- BaseType_t entriesNeeded;
- BaseType_t freeCount = 0;
- FF_Error_t xError;
- /* If the file name fits into a short file name
- * then the existence of that short file name will be checked as well. */
- BaseType_t testShortname;
- uint32_t xResult = 0ul;
- #if ( ffconfigUNICODE_UTF8_SUPPORT == 1 )
- int32_t utf8Error;
- #endif
- #if ( ffconfigLFN_SUPPORT != 0 )
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_T_WCHAR * pcCurPtr; /* Pointer to store a LFN. */
- FF_T_WCHAR * pcLastPtr = pxDirEntry->pcFileName + sizeof( pxDirEntry->pcFileName );
- #else
- char * pcCurPtr; /* Pointer to store a LFN. */
- char * pcLastPtr = pxDirEntry->pcFileName + sizeof( pxDirEntry->pcFileName );
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- uint16_t lfnItem = 0;
- uint8_t ucCheckSum = 0;
- BaseType_t xLFNCount = 0;
- BaseType_t xLFNTotal = 0;
- uint8_t lastAttrib;
- BaseType_t xIndex;
- #endif /* ffconfigLFN_SUPPORT */
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- BaseType_t NameLen = ( BaseType_t ) wcslen( ( const char * ) pcName );
- #else
- BaseType_t NameLen = ( BaseType_t ) strlen( ( const char * ) pcName );
- #endif
- /* Find enough places for the LFNs and the ShortName. */
- entriesNeeded = ( uint8_t ) ( ( NameLen + 12 ) / 13 ) + 1;
- }
- #else
- {
- entriesNeeded = 1;
- }
- #endif /* ffconfigLFN_SUPPORT */
- if( ( pxFindParams->ulFlags & FIND_FLAG_FITS_SHORT_OK ) == FIND_FLAG_FITS_SHORT_OK )
- {
- testShortname = pdTRUE;
- }
- else
- {
- testShortname = pdFALSE;
- }
- pxDirEntry->ucAttrib = 0;
- if( ( pxFindParams->ulFlags & FIND_FLAG_CREATE_FLAG ) != 0 )
- {
- /* A file is to be created: keep track of the first free entry big enough
- * to hold this file name. */
- pxFindParams->lFreeEntry = -1;
- }
- else
- {
- pxFindParams->lFreeEntry = 0;
- }
- xError = FF_InitEntryFetch( pxIOManager, pxFindParams->ulDirCluster, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- for( pxDirEntry->usCurrentItem = 0; pxDirEntry->usCurrentItem < FF_MAX_ENTRIES_PER_DIRECTORY; pxDirEntry->usCurrentItem++ )
- {
- if( ( src == NULL ) ||
- ( src >= xFetchContext.pxBuffer->pucBuffer + ( pxIOManager->usSectorSize - FF_SIZEOF_DIRECTORY_ENTRY ) ) )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, pxDirEntry->usCurrentItem, &xFetchContext, NULL );
- if( FF_isERR( xError ) != pdFALSE )
- {
- break;
- }
- src = xFetchContext.pxBuffer->pucBuffer;
- }
- else
- {
- /* Advance 32 bytes. */
- src += FF_SIZEOF_DIRECTORY_ENTRY;
- }
- if( FF_isEndOfDir( src ) )
- {
- /* 0x00 end-of-dir. */
- break;
- }
- if( FF_isDeleted( src ) )
- {
- /* Entry not used or deleted. */
- pxDirEntry->ucAttrib = 0;
- if( ( pxFindParams->lFreeEntry < 0 ) && ( ++freeCount == entriesNeeded ) )
- {
- /* Remember the beginning entry in the sequential sequence. */
- pxFindParams->lFreeEntry = ( pxDirEntry->usCurrentItem - ( entriesNeeded - 1 ) );
- }
- continue;
- }
- /* The current entry is in use, so reset the free-entry-counter */
- freeCount = 0;
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- lastAttrib = pxDirEntry->ucAttrib;
- }
- #endif
- pxDirEntry->ucAttrib = FF_getChar( src, FF_FAT_DIRENT_ATTRIB );
- if( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_LFN ) == FF_FAT_ATTR_LFN )
- {
- /* LFN Processing. */
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- if( ( xLFNCount == 0 ) || ( ( lastAttrib & FF_FAT_ATTR_LFN ) != FF_FAT_ATTR_LFN ) )
- {
- xLFNTotal = xLFNCount = ( BaseType_t ) ( src[ 0 ] & ~0x40 );
- lfnItem = pxDirEntry->usCurrentItem;
- ucCheckSum = FF_getChar( src, FF_FAT_LFN_CHECKSUM );
- pcLastPtr[ -1 ] = '\0';
- }
- if( xLFNCount != 0 )
- {
- xLFNCount--;
- pcCurPtr = pxDirEntry->pcFileName + ( xLFNCount * 13 );
- /*
- * This section needs to extract the name and do the comparison
- * dependent on UNICODE settings in the FreeRTOSFATConfig.h file.
- */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- /* Add UTF-16 Routine here. */
- /* Copy first 5 UTF-16 chars ( 10 bytes ). */
- memcpy( pcCurPtr, &src[ FF_FAT_LFN_NAME_1 ], 10 );
- /* Increment Filename pointer 5 utf16 chars. */
- pcCurPtr += 5;
- /* Copy next 6 chars ( 12 bytes ). */
- memcpy( pcCurPtr, &src[ FF_FAT_LFN_NAME_2 ], 12 );
- pcCurPtr += 6;
- /* You're getting the idea by now! */
- memcpy( pcCurPtr, &src[ FF_FAT_LFN_NAME_3 ], 4 );
- pcCurPtr += 2;
- } /* ffconfigUNICODE_UTF16_SUPPORT */
- #elif ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- /* UTF-8 Routine here. */
- for( xIndex = 0; ( xIndex < 5 ) && ( pcCurPtr < pcLastPtr ); xIndex++ )
- {
- /* Was there a surrogate sequence? -- Add handling here. */
- utf8Error = FF_Utf16ctoUtf8c( ( uint8_t * ) pcCurPtr, ( uint16_t * ) &src[ FF_FAT_LFN_NAME_1 + ( 2 * xIndex ) ], pcLastPtr - pcCurPtr );
- if( utf8Error > 0 )
- {
- pcCurPtr += utf8Error;
- }
- else
- {
- if( FF_GETERROR( utf8Error ) == FF_ERR_UNICODE_INVALID_SEQUENCE )
- {
- /* Handle potential surrogate sequence across entries. */
- }
- }
- }
- for( xIndex = 0; xIndex < 6 && pcCurPtr < pcLastPtr; xIndex++ )
- {
- /* Was there a surrogate sequence? -- To add handling here. */
- utf8Error = FF_Utf16ctoUtf8c( ( uint8_t * ) pcCurPtr, ( uint16_t * ) &src[ FF_FAT_LFN_NAME_2 + ( 2 * xIndex ) ], pcLastPtr - pcCurPtr );
- if( utf8Error > 0 )
- {
- pcCurPtr += utf8Error;
- }
- else
- {
- if( FF_GETERROR( utf8Error ) == FF_ERR_UNICODE_INVALID_SEQUENCE )
- {
- /* Handle potential surrogate sequence across entries. */
- }
- }
- }
- for( xIndex = 0; xIndex < 2 && pcCurPtr < pcLastPtr; xIndex++ )
- {
- /* Was there a surrogate sequence? -- To add handling here. */
- utf8Error = FF_Utf16ctoUtf8c( ( uint8_t * ) pcCurPtr, ( uint16_t * ) &src[ FF_FAT_LFN_NAME_3 + ( 2 * xIndex ) ], pcLastPtr - pcCurPtr );
- if( utf8Error > 0 )
- {
- pcCurPtr += utf8Error;
- }
- else
- {
- if( FF_GETERROR( utf8Error ) == FF_ERR_UNICODE_INVALID_SEQUENCE )
- {
- /* Handle potential surrogate sequence across entries. */
- }
- }
- }
- } /* ffconfigUNICODE_UTF8_SUPPORT */
- #else /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
- { /* use ASCII notation. */
- for( xIndex = 0; ( xIndex < 10 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
- {
- *( pcCurPtr++ ) = src[ FF_FAT_LFN_NAME_1 + xIndex ];
- }
- for( xIndex = 0; ( xIndex < 12 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
- {
- *( pcCurPtr++ ) = src[ FF_FAT_LFN_NAME_2 + xIndex ];
- }
- for( xIndex = 0; ( xIndex < 4 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
- {
- *( pcCurPtr++ ) = src[ FF_FAT_LFN_NAME_3 + xIndex ];
- }
- }
- #endif /* ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && !( ffconfigUNICODE_UTF8_SUPPORT == 0 ) */
- if( ( xLFNCount == xLFNTotal - 1 ) && ( pcCurPtr < pcLastPtr ) )
- {
- *pcCurPtr = '\0'; /* Important when name len is multiple of 13. */
- }
- } /* if( xLFNCount ) */
- }
- #endif /* ffconfigLFN_SUPPORT */
- continue;
- }
- if( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_VOLID ) == FF_FAT_ATTR_VOLID )
- {
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- xLFNTotal = 0;
- }
- #endif /* ffconfigLFN_SUPPORT */
- continue;
- }
- #if ( ffconfigLFN_SUPPORT != 0 )
- if( ( xLFNTotal == 0 ) || ( ucCheckSum != FF_CreateChkSum( src ) ) )
- #endif /* ffconfigLFN_SUPPORT */
- {
- /* This entry has only a short name, or the checksum isn't correct
- * Use the short name for comparison */
- memcpy( pxDirEntry->pcFileName, src, 11 );
- FF_ProcessShortName( ( char * ) pxDirEntry->pcFileName );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- /* FileName now contains a 8-bit short name
- * Expand it to a FF_T_WCHAR string. */
- FF_ShortNameExpand( pxDirEntry->pcFileName );
- }
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- xLFNTotal = 0;
- }
- #endif /* ffconfigLFN_SUPPORT */
- }
- /* This function FF_FindEntryInDir( ) is either called with
- * pa_Attrib==0 or with pa_Attrib==FF_FAT_ATTR_DIR
- * In the last case the caller is looking for a directory */
- if( ( pxDirEntry->ucAttrib & pa_Attrib ) == pa_Attrib )
- {
- if( testShortname )
- {
- /* Both strings are stored in the directory format
- * e.g. "README TXT", without a dot */
- if( memcmp( src, pxFindParams->pcEntryBuffer, 11 ) == 0 )
- {
- pxFindParams->ulFlags |= FIND_FLAG_SHORTNAME_CHECKED | FIND_FLAG_SHORTNAME_FOUND;
- }
- }
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- if( wcsicmp( ( const char * ) pcName, ( const char * ) pxDirEntry->pcFileName ) == 0 )
- #else
- if( FF_stricmp( ( const char * ) pcName, ( const char * ) pxDirEntry->pcFileName ) == 0 )
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- {
- /* Finally get the complete information. */
- #if ( ffconfigLFN_SUPPORT != 0 )
- if( xLFNTotal )
- {
- xError = FF_PopulateLongDirent( pxIOManager, pxDirEntry, ( uint16_t ) lfnItem, &xFetchContext );
- if( FF_isERR( xError ) )
- {
- break;
- }
- }
- else
- #endif /* ffconfigLFN_SUPPORT */
- {
- FF_PopulateShortDirent( pxIOManager, pxDirEntry, src );
- /* HT: usCurrentItem wasn't increased here. */
- pxDirEntry->usCurrentItem++;
- }
- /* Object found, the cluster number will be returned. */
- xResult = pxDirEntry->ulObjectCluster;
- break;
- }
- }
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- xLFNTotal = 0;
- }
- #endif
- } /* for( ; pxDirEntry->usCurrentItem < FF_MAX_ENTRIES_PER_DIRECTORY; pxDirEntry->usCurrentItem++ ) */
- {
- FF_Error_t xTempError;
- xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- } /* if( FF_isERR( xError ) == pdFALSE ) */
- if( FF_isERR( xError ) == pdFALSE )
- {
- /* If a free entry wasn't found yet, put it to the current (last) item */
- if( pxFindParams->lFreeEntry < 0 )
- {
- pxFindParams->lFreeEntry = pxDirEntry->usCurrentItem;
- }
- /* If we were checking the existence of the short-name
- * set the Checked flag now */
- if( testShortname )
- {
- pxFindParams->ulFlags |= FIND_FLAG_SHORTNAME_CHECKED;
- }
- }
- if( pxError != NULL )
- {
- *pxError = xError;
- }
- return xResult;
- } /* FF_FindEntryInDir() */
- /*-----------------------------------------------------------*/
- /**
- * @private
- **/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- uint32_t FF_FindDir( FF_IOManager_t * pxIOManager,
- const FF_T_WCHAR * pcPath,
- uint16_t pathLen,
- FF_Error_t * pxError )
- #else
- uint32_t FF_FindDir( FF_IOManager_t * pxIOManager,
- const char * pcPath,
- uint16_t pathLen,
- FF_Error_t * pxError )
- #endif
- {
- uint16_t it = 0; /* Re-entrancy Variables for FF_strtok( ). */
- BaseType_t last = pdFALSE;
- FF_DirEnt_t xMyDirectory;
- FF_FindParams_t xFindParams;
- FF_Error_t xError;
- BaseType_t xFound;
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_T_WCHAR mytoken[ ffconfigMAX_FILENAME ];
- FF_T_WCHAR * pcToken;
- #else
- char mytoken[ ffconfigMAX_FILENAME ];
- char * pcToken;
- #endif
- #if ( ffconfigPATH_CACHE != 0 )
- BaseType_t xIndex;
- #endif
- memset( &xFindParams, '\0', sizeof( xFindParams ) );
- xFindParams.ulDirCluster = pxIOManager->xPartition.ulRootDirCluster;
- xError = FF_ERR_NONE;
- if( pathLen <= 1 )
- {
- /* Must be the root directory.
- * 'xFindParams.ulDirCluster' will be returned containing 'pxIOManager->xPartition.ulRootDirCluster'. */
- xFound = pdTRUE;
- }
- else
- {
- /* Only the root directory '/' shall have a trailing slash in its name. */
- if( ( pcPath[ pathLen - 1 ] == '\\' ) || ( pcPath[ pathLen - 1 ] == '/' ) )
- {
- pathLen--;
- }
- xFound = pdFALSE;
- #if ( ffconfigPATH_CACHE != 0 ) /* Is the requested pcPath in the PATH CACHE? */
- {
- FF_PendSemaphore( pxIOManager->pvSemaphore ); /* Thread safety on shared object! */
- {
- for( xIndex = 0; xIndex < ffconfigPATH_CACHE_DEPTH; xIndex++ )
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- if( wcslen( pxIOManager->xPartition.pxPathCache[ xIndex ].pcPath ) == ( size_t ) pathLen )
- #else
- if( strlen( pxIOManager->xPartition.pxPathCache[ xIndex ].pcPath ) == ( size_t ) pathLen )
- #endif
- {
- if( FF_strmatch( pxIOManager->xPartition.pxPathCache[ xIndex ].pcPath, pcPath, pathLen ) )
- {
- xFindParams.ulDirCluster = pxIOManager->xPartition.pxPathCache[ xIndex ].ulDirCluster;
- xFound = pdTRUE;
- break;
- }
- }
- }
- }
- FF_ReleaseSemaphore( pxIOManager->pvSemaphore );
- }
- #endif /* ffconfigPATH_CACHE */
- }
- if( xFound == pdFALSE )
- {
- pcToken = FF_strtok( pcPath, mytoken, &it, &last, pathLen );
- do
- {
- xMyDirectory.usCurrentItem = 0;
- xFindParams.ulDirCluster = FF_FindEntryInDir( pxIOManager, &xFindParams, pcToken, ( uint8_t ) FF_FAT_ATTR_DIR, &xMyDirectory, &xError );
- if( xFindParams.ulDirCluster == 0ul )
- {
- break;
- }
- pcToken = FF_strtok( pcPath, mytoken, &it, &last, pathLen );
- } while( pcToken != NULL );
- if( ( pcToken != NULL ) &&
- ( ( FF_isERR( xError ) == pdFALSE ) || ( FF_GETERROR( xError ) == FF_ERR_DIR_END_OF_DIR ) ) )
- {
- xError = ( FF_Error_t ) ( FF_FINDDIR | FF_ERR_FILE_INVALID_PATH );
- }
- #if ( ffconfigPATH_CACHE != 0 ) /* Update the PATH CACHE with a new PATH. */
- {
- /* Only cache if the dir was actually found! */
- if( ( FF_isERR( xError ) == pdFALSE ) && ( xFindParams.ulDirCluster != 0ul ) )
- {
- FF_PendSemaphore( pxIOManager->pvSemaphore );
- {
- if( pathLen < ffconfigMAX_FILENAME ) /* Ensure the PATH won't cause a buffer overrun. */
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- memcpy( pxIOManager->xPartition.pxPathCache[ pxIOManager->xPartition.ulPCIndex ].pcPath, pcPath, pathLen * sizeof( FF_T_WCHAR ) );
- }
- #else
- {
- memcpy( pxIOManager->xPartition.pxPathCache[ pxIOManager->xPartition.ulPCIndex ].pcPath, pcPath, pathLen );
- }
- #endif
- pxIOManager->xPartition.pxPathCache[ pxIOManager->xPartition.ulPCIndex ].pcPath[ pathLen ] = '\0';
- pxIOManager->xPartition.pxPathCache[ pxIOManager->xPartition.ulPCIndex ].ulDirCluster = xFindParams.ulDirCluster;
- pxIOManager->xPartition.ulPCIndex += 1;
- if( pxIOManager->xPartition.ulPCIndex >= ffconfigPATH_CACHE_DEPTH )
- {
- pxIOManager->xPartition.ulPCIndex = 0;
- }
- }
- }
- FF_ReleaseSemaphore( pxIOManager->pvSemaphore );
- }
- }
- #endif /* ffconfigPATH_CACHE */
- } /* if( pathLen > 1 ) */
- if( pxError != NULL )
- {
- *pxError = xError;
- }
- return xFindParams.ulDirCluster;
- } /* FF_FindDir() */
- /*-----------------------------------------------------------*/
- #if ( ffconfigSHORTNAME_CASE != 0 )
- /**
- * @private
- * For short-name entries, NT/XP etc store case information in byte 0x0c
- * Use this to show proper case of "README.txt" or "source.H"
- **/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- static void FF_CaseShortName( FF_T_WCHAR * pcName,
- uint8_t attrib )
- #else
- static void FF_CaseShortName( char * pcName,
- uint8_t attrib )
- #endif
- {
- uint8_t testAttrib = FF_FAT_CASE_ATTR_BASE;
- for( ; *pcName != '\0'; pcName++ )
- {
- if( *pcName == '.' )
- {
- testAttrib = FF_FAT_CASE_ATTR_EXT;
- }
- else if( ( attrib & testAttrib ) != 0 )
- {
- if( ( *pcName >= 'A' ) && ( *pcName <= 'Z' ) )
- {
- *pcName += 0x20;
- }
- }
- else if( ( *pcName >= 'a' ) && ( *pcName <= 'z' ) )
- {
- *pcName -= 0x20;
- }
- }
- }
- #endif /* ffconfigSHORTNAME_CASE */
- /*-----------------------------------------------------------*/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- /**
- * @private
- * Expand a short-name, adding a zero after each character
- **/
- static void FF_ShortNameExpand( FF_T_WCHAR * pFileName )
- {
- int8_t * pSource = ( ( int8_t * ) pFileName ) + 13;
- int8_t * pTarget = ( ( int8_t * ) pFileName ) + 26;
- /* "aaaaaaaa.eee": 12 characters plus a zero makes 13
- * Copy from the right to the left */
- while( pTarget > ( int8_t * ) pFileName )
- {
- pTarget[ -1 ] = 0;
- pTarget[ -2 ] = *( --pSource );
- pTarget -= 2;
- }
- }
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- /*-----------------------------------------------------------*/
- /**
- * @private
- **/
- static void FF_ProcessShortName( char * pcName )
- {
- char pcShortName[ 13 ];
- char * pcTarget = pcName;
- int iSource;
- memcpy( pcShortName, pcName, 11 );
- for( iSource = 0; iSource < 11; iSource++ )
- {
- if( pcShortName[ iSource ] == 0x20 )
- {
- if( iSource >= 8 )
- {
- break;
- }
- iSource = 7;
- }
- else
- {
- if( iSource == 8 )
- {
- *( pcTarget++ ) = '.';
- }
- *( pcTarget++ ) = pcShortName[ iSource ];
- }
- }
- *pcTarget = '\0';
- }
- /*-----------------------------------------------------------*/
- #if ( ffconfigTIME_SUPPORT != 0 )
- static void FF_PlaceTime( uint8_t * pucEntryBuffer,
- uint32_t Offset,
- FF_SystemTime_t * pxTime )
- {
- uint16_t myShort;
- /* HT time changes:
- * E.g. Unzip needs to use original time rather than
- * the result of FF_GetSystemTime */
- myShort = 0;
- myShort |= ( ( pxTime->Hour << 11 ) & 0xF800 );
- myShort |= ( ( pxTime->Minute << 5 ) & 0x07E0 );
- myShort |= ( ( pxTime->Second / 2 ) & 0x001F );
- FF_putShort( pucEntryBuffer, ( uint16_t ) Offset, myShort );
- }
- #endif /* ffconfigTIME_SUPPORT */
- /*-----------------------------------------------------------*/
- #if ( ffconfigTIME_SUPPORT != 0 )
- static void FF_PlaceDate( uint8_t * pucEntryBuffer,
- uint32_t Offset,
- FF_SystemTime_t * pxTime )
- {
- uint16_t myShort;
- /* HT time changes:
- * Unzip needs to use original date rather than
- * the current date, so make it a parameter. */
- myShort = 0;
- myShort |= ( ( ( pxTime->Year - 1980 ) << 9 ) & 0xFE00 );
- myShort |= ( ( pxTime->Month << 5 ) & 0x01E0 );
- myShort |= ( pxTime->Day & 0x001F );
- FF_putShort( pucEntryBuffer, ( uint16_t ) Offset, myShort );
- }
- #endif /* ffconfigTIME_SUPPORT */
- /*-----------------------------------------------------------*/
- #if ( ffconfigTIME_SUPPORT != 0 )
- static void FF_GetTime( FF_SystemTime_t * pxTime,
- const uint8_t * pucEntryBuffer,
- uint32_t Offset )
- {
- uint16_t myShort;
- myShort = FF_getShort( pucEntryBuffer, ( uint16_t ) Offset );
- pxTime->Hour = ( ( ( myShort & 0xF800 ) >> 11 ) & 0x001F );
- pxTime->Minute = ( ( ( myShort & 0x07E0 ) >> 5 ) & 0x003F );
- pxTime->Second = 2 * ( myShort & 0x01F );
- }
- #endif /* ffconfigTIME_SUPPORT */
- /*-----------------------------------------------------------*/
- #if ( ffconfigTIME_SUPPORT != 0 )
- static void FF_GetDate( FF_SystemTime_t * pxTime,
- const uint8_t * pucEntryBuffer,
- uint32_t Offset )
- {
- uint16_t myShort;
- myShort = FF_getShort( pucEntryBuffer, ( uint16_t ) Offset );
- pxTime->Year = 1980 + ( ( ( myShort & 0xFE00 ) >> 9 ) & 0x07F );
- pxTime->Month = ( ( ( myShort & 0x01E0 ) >> 5 ) & 0x000F );
- pxTime->Day = myShort & 0x01F;
- }
- #endif /* ffconfigTIME_SUPPORT */
- /*-----------------------------------------------------------*/
- void FF_PopulateShortDirent( FF_IOManager_t * pxIOManager,
- FF_DirEnt_t * pxDirEntry,
- const uint8_t * pucEntryBuffer )
- {
- memcpy( pxDirEntry->pcFileName, pucEntryBuffer, 11 ); /* Copy the filename into the Dirent object. */
- #if ( ffconfigLFN_SUPPORT != 0 ) && ( ffconfigINCLUDE_SHORT_NAME != 0 )
- memcpy( pxDirEntry->pcShortName, pucEntryBuffer, 11 );
- pxDirEntry->pcShortName[ 11 ] = '\0';
- FF_ProcessShortName( pxDirEntry->pcShortName ); /* For debuggers only. */
- #endif
- FF_ProcessShortName( ( char * ) pxDirEntry->pcFileName ); /* Format the shortname, for pleasant viewing. */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- /* FileName contains a 8-bit short name
- * Expand it to a FF_T_WCHAR string */
- FF_ShortNameExpand( pxDirEntry->pcFileName );
- #endif
- ( void ) pxIOManager; /* Silence a compiler warning, about not referencing pxIOManager. */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_tolower( pxDirEntry->pcFileName, ( uint32_t ) wcslen( pxDirEntry->pcFileName ) );
- #else
- FF_tolower( pxDirEntry->pcFileName, ( uint32_t ) strlen( pxDirEntry->pcFileName ) );
- #endif
- /* Get the item's Cluster address. */
- pxDirEntry->ulObjectCluster =
- ( ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH ) << 16 ) |
- ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW );
- #if ( ffconfigTIME_SUPPORT != 0 )
- /* Get the creation Time & Date. */
- FF_GetTime( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_TIME );
- FF_GetDate( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_DATE );
- /* Get the modified Time & Date
- * HT Here xCreateTime became xModifiedTime: */
- FF_GetTime( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME );
- FF_GetDate( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE );
- /* Get the last accessed Date. */
- FF_GetDate( &pxDirEntry->xAccessedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTACC_DATE );
- pxDirEntry->xAccessedTime.Hour = 0;
- pxDirEntry->xAccessedTime.Minute = 0;
- pxDirEntry->xAccessedTime.Second = 0;
- #endif /* if ( ffconfigTIME_SUPPORT != 0 ) */
- /* Get the filesize. */
- pxDirEntry->ulFileSize = FF_getLong( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_FILESIZE ) );
- /* Get the attribute. */
- pxDirEntry->ucAttrib = FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );
- }
- /*-----------------------------------------------------------*/
- /* Initialises a context object for FF_FetchEntryWithContext( */
- FF_Error_t FF_InitEntryFetch( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- FF_FetchContext_t * pxContext )
- {
- FF_Error_t xError;
- memset( pxContext, 0, sizeof( FF_FetchContext_t ) );
- /* Get the total length of the chain. */
- pxContext->ulChainLength = FF_GetChainLength( pxIOManager, ulDirCluster, NULL, &xError );
- if( FF_isERR( xError ) == pdFALSE )
- {
- pxContext->ulDirCluster = ulDirCluster;
- pxContext->ulCurrentClusterLCN = ulDirCluster;
- if( pxIOManager->xPartition.ucType != FF_T_FAT32 )
- {
- /* Handle Root Dirs that don't have cluster chains! */
- if( pxContext->ulDirCluster == pxIOManager->xPartition.ulRootDirCluster )
- {
- /* This is a RootDIR, special consideration needs to be made, because it doesn't have a Cluster chain! */
- pxContext->ulChainLength = pxIOManager->xPartition.ulRootDirSectors / pxIOManager->xPartition.ulSectorsPerCluster;
- if( pxContext->ulChainLength == 0 ) /* Some media has ulRootDirSectors < ulSectorsPerCluster. This is wrong, as it should be atleast 1 cluster! */
- {
- pxContext->ulChainLength = 1;
- }
- }
- }
- }
- return xError;
- } /* FF_InitEntryFetch() */
- /*-----------------------------------------------------------*/
- FF_Error_t FF_CleanupEntryFetch( FF_IOManager_t * pxIOManager,
- FF_FetchContext_t * pxContext )
- {
- FF_Error_t xError = FF_ERR_NONE;
- if( pxContext->pxBuffer )
- {
- xError = FF_ReleaseBuffer( pxIOManager, pxContext->pxBuffer );
- pxContext->pxBuffer = NULL;
- }
- return xError;
- } /* FF_CleanupEntryFetch() */
- /*-----------------------------------------------------------*/
- /**
- * @private
- * @brief Find the cluster for a given Entry within a directory
- * @brief Make an exception for the root directory ( non FAT32 only ):
- * @brief Just calculate the cluster ( don't consult the actual FAT )
- *
- * @param pxIOManager FF_IOManager_t object that was created by FF_CreateIOManger( ).
- * @param ulEntry The sequence number of the entry of interest
- * @param pxContext Context of current search
- *
- * @Return FF_ERR_NONE on success
- * @Return Possible error returned by FF_TraverseFAT( ) or END_OF_DIR
- *
- * Side effects:
- * - pxContext->ulCurrentClusterNum : relative cluster number ( 0 <= Num < ulChainLength )
- * - pxContext->ulCurrentClusterLCN : fysical cluster on the partition
- **/
- static FF_Error_t FF_Traverse( FF_IOManager_t * pxIOManager,
- uint32_t ulEntry,
- FF_FetchContext_t * pxContext )
- {
- uint32_t ulClusterNum = FF_getClusterChainNumber( pxIOManager, ulEntry, ( uint16_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- FF_Error_t xError = FF_ERR_NONE;
- /* Check if we're past the last cluster ( ulChainLength is also valid for root sectors ). */
- if( ( ulClusterNum + 1 ) > pxContext->ulChainLength )
- {
- xError = FF_ERR_DIR_END_OF_DIR | FF_TRAVERSE; /* End of Dir was reached! */
- }
- else if( ( pxIOManager->xPartition.ucType != FF_T_FAT32 ) &&
- ( pxContext->ulDirCluster == pxIOManager->xPartition.ulRootDirCluster ) )
- {
- /* Double-check if the entry number isn't too high. */
- if( ulEntry > ( ( pxIOManager->xPartition.ulRootDirSectors * pxIOManager->xPartition.usBlkSize ) / FF_SIZEOF_DIRECTORY_ENTRY ) )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_END_OF_DIR | FF_FETCHENTRYWITHCONTEXT );
- }
- else
- {
- pxContext->ulCurrentClusterLCN = pxContext->ulDirCluster;
- }
- }
- else if( ulClusterNum != pxContext->ulCurrentClusterNum )
- {
- /* Traverse the fat gently! */
- if( ulClusterNum > pxContext->ulCurrentClusterNum )
- {
- /* Start traverse from the current entry. */
- pxContext->ulCurrentClusterLCN = FF_TraverseFAT( pxIOManager, pxContext->ulCurrentClusterLCN, ( ulClusterNum - pxContext->ulCurrentClusterNum ), &xError );
- }
- else
- {
- /* Start traverse from the beginning. */
- pxContext->ulCurrentClusterLCN = FF_TraverseFAT( pxIOManager, pxContext->ulDirCluster, ulClusterNum, &xError );
- }
- }
- if( FF_isERR( xError ) == pdFALSE )
- {
- pxContext->ulCurrentClusterNum = ulClusterNum;
- }
- return xError;
- } /* FF_Traverse() */
- /*-----------------------------------------------------------*/
- FF_Error_t FF_FetchEntryWithContext( FF_IOManager_t * pxIOManager,
- uint32_t ulEntry,
- FF_FetchContext_t * pxContext,
- uint8_t * pEntryBuffer )
- {
- uint32_t ulItemLBA;
- uint32_t ulRelItem;
- FF_Error_t xError;
- xError = FF_Traverse( pxIOManager, ulEntry, pxContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- ulRelItem = FF_getMinorBlockEntry( pxIOManager, ulEntry, ( uint32_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- ulItemLBA = FF_Cluster2LBA( pxIOManager, pxContext->ulCurrentClusterLCN ) +
- FF_getMajorBlockNumber( pxIOManager, ulEntry, ( uint32_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- if( ( pxIOManager->xPartition.ucType != FF_T_FAT32 ) &&
- ( pxContext->ulDirCluster == pxIOManager->xPartition.ulRootDirCluster ) )
- {
- ulItemLBA += ( ulEntry / ( ( pxIOManager->xPartition.usBlkSize * pxIOManager->xPartition.ulSectorsPerCluster ) /
- FF_SIZEOF_DIRECTORY_ENTRY ) * pxIOManager->xPartition.ulSectorsPerCluster );
- }
- ulItemLBA = FF_getRealLBA( pxIOManager, ulItemLBA ) + FF_getMinorBlockNumber( pxIOManager, ulRelItem, ( uint32_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- if( ( pxContext->pxBuffer == NULL ) ||
- ( pxContext->pxBuffer->ulSector != ulItemLBA ) ||
- ( ( pxContext->pxBuffer->ucMode & FF_MODE_WRITE ) != 0 ) )
- {
- if( pxContext->pxBuffer != NULL )
- {
- xError = FF_ReleaseBuffer( pxIOManager, pxContext->pxBuffer );
- pxContext->pxBuffer = NULL;
- }
- if( FF_isERR( xError ) == pdFALSE )
- {
- pxContext->pxBuffer = FF_GetBuffer( pxIOManager, ulItemLBA, FF_MODE_READ );
- if( pxContext->pxBuffer == NULL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DEVICE_DRIVER_FAILED | FF_FETCHENTRYWITHCONTEXT );
- }
- }
- }
- if( ( pEntryBuffer != NULL ) && ( pxContext->pxBuffer != NULL ) )
- {
- memcpy( pEntryBuffer, pxContext->pxBuffer->pucBuffer + ( ulRelItem * FF_SIZEOF_DIRECTORY_ENTRY ), FF_SIZEOF_DIRECTORY_ENTRY );
- }
- }
- return xError;
- } /* FF_FetchEntryWithContext() */
- /*-----------------------------------------------------------*/
- FF_Error_t FF_PushEntryWithContext( FF_IOManager_t * pxIOManager,
- uint32_t ulEntry,
- FF_FetchContext_t * pxContext,
- uint8_t * pEntryBuffer )
- {
- uint32_t ulItemLBA;
- uint32_t ulRelItem;
- FF_Error_t xError;
- xError = FF_Traverse( pxIOManager, ulEntry, pxContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- ulRelItem = FF_getMinorBlockEntry( pxIOManager, ulEntry, ( uint32_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- ulItemLBA = FF_Cluster2LBA( pxIOManager, pxContext->ulCurrentClusterLCN ) + FF_getMajorBlockNumber( pxIOManager, ulEntry, ( uint32_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- if( ( pxIOManager->xPartition.ucType != FF_T_FAT32 ) &&
- ( pxContext->ulDirCluster == pxIOManager->xPartition.ulRootDirCluster ) )
- {
- ulItemLBA += ( ulEntry /
- ( ( pxIOManager->xPartition.usBlkSize * pxIOManager->xPartition.ulSectorsPerCluster ) / FF_SIZEOF_DIRECTORY_ENTRY ) * pxIOManager->xPartition.ulSectorsPerCluster );
- }
- ulItemLBA = FF_getRealLBA( pxIOManager, ulItemLBA ) + FF_getMinorBlockNumber( pxIOManager, ulRelItem, ( uint32_t ) FF_SIZEOF_DIRECTORY_ENTRY );
- if( ( pxContext->pxBuffer == NULL ) ||
- ( pxContext->pxBuffer->ulSector != ulItemLBA ) ||
- ( ( pxContext->pxBuffer->ucMode & FF_MODE_WRITE ) == 0 ) )
- {
- if( pxContext->pxBuffer != NULL )
- {
- xError = FF_ReleaseBuffer( pxIOManager, pxContext->pxBuffer );
- pxContext->pxBuffer = NULL;
- }
- if( FF_isERR( xError ) == pdFALSE )
- {
- pxContext->pxBuffer = FF_GetBuffer( pxIOManager, ulItemLBA, FF_MODE_WRITE );
- if( pxContext->pxBuffer == NULL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DEVICE_DRIVER_FAILED | FF_FETCHENTRYWITHCONTEXT );
- }
- }
- }
- /* Now change the entry: */
- if( pxContext->pxBuffer != NULL )
- {
- memcpy( pxContext->pxBuffer->pucBuffer + ( ulRelItem * FF_SIZEOF_DIRECTORY_ENTRY ), pEntryBuffer, FF_SIZEOF_DIRECTORY_ENTRY );
- }
- }
- return xError;
- } /* FF_PushEntryWithContext() */
- /*-----------------------------------------------------------*/
- /**
- * @private
- **/
- FF_Error_t FF_GetEntry( FF_IOManager_t * pxIOManager,
- uint16_t usEntry,
- uint32_t ulDirCluster,
- FF_DirEnt_t * pxDirEntry )
- {
- /* A 32 byte directory entry. */
- uint8_t ucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- FF_FetchContext_t xFetchContext;
- FF_Error_t xError;
- #if ( ffconfigLFN_SUPPORT == 0 )
- BaseType_t xLFNCount;
- #endif
- xError = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, usEntry, &xFetchContext, ucEntryBuffer );
- if( ( FF_isERR( xError ) == pdFALSE ) &&
- ( FF_isDeleted( ucEntryBuffer ) == pdFALSE ) )
- {
- if( FF_isEndOfDir( ucEntryBuffer ) != pdFALSE )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_END_OF_DIR | FF_GETENTRY );
- }
- else
- {
- pxDirEntry->ucAttrib = FF_getChar( ucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );
- if( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_LFN ) == FF_FAT_ATTR_LFN )
- {
- #if ( ffconfigLFN_SUPPORT != 0 )
- xError = FF_PopulateLongDirent( pxIOManager, pxDirEntry, usEntry, &xFetchContext );
- #else
- /* LFN Processing. */
- xLFNCount = ( BaseType_t ) ( ucEntryBuffer[ 0 ] & ~0x40 );
- pxDirEntry->usCurrentItem += ( xLFNCount - 1 );
- #endif
- }
- else if( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_VOLID ) != FF_FAT_ATTR_VOLID )
- {
- FF_PopulateShortDirent( pxIOManager, pxDirEntry, ucEntryBuffer );
- pxDirEntry->usCurrentItem += 1;
- }
- }
- }
- {
- FF_Error_t xTempError;
- xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- }
- return xError;
- } /* FF_GetEntry() */
- /*-----------------------------------------------------------*/
- FF_Error_t FF_PopulateLongDirent( FF_IOManager_t * pxIOManager,
- FF_DirEnt_t * pxDirEntry,
- uint16_t usEntry,
- FF_FetchContext_t * pxFetchContext )
- {
- /* First get the entire name as UTF-16 from the LFN's.
- * Then transform into the API's native string format. */
- FF_Error_t xError;
- BaseType_t xNumLFNs;
- uint8_t ucCheckSum;
- /* A 32 byte directory entry. */
- uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- char pcShortName[ 13 ];
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- UBaseType_t uiLfnLength = 0;
- #endif
- #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
- BaseType_t xIndex, y;
- #endif
- #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 )
- char * pcLastPtr = pxDirEntry->pcFileName + sizeof( pxDirEntry->pcFileName );
- char * pcCurPtr;
- #endif
- #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- uint16_t nLfnBegin;
- uint16_t usUtf8Len = 0;
- #endif /* ffconfigUNICODE_UTF8_SUPPORT */
- do
- {
- xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- /* After breaking from this do {} while ( pdFALSE ) loop, xResult will be returned. */
- break;
- }
- xNumLFNs = ( BaseType_t ) ( pucEntryBuffer[ 0 ] & ~0x40 );
- ucCheckSum = FF_getChar( pucEntryBuffer, FF_FAT_LFN_CHECKSUM );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- /* UTF-16 Can simply get segments of the UTF-16 sequence
- * going forward in the directory entries ( but reversed order ). */
- while( xNumLFNs > 0 )
- {
- /* Avoid stack intensive use of a UTF-16 buffer. Stream direct to FileName dirent field in correct format. */
- /* memcpy direct! -UTF-16 support. */
- memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 0, &( pucEntryBuffer[ FF_FAT_LFN_NAME_1 ] ), 10 );
- memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 5, &( pucEntryBuffer[ FF_FAT_LFN_NAME_2 ] ), 12 );
- memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 11, &( pucEntryBuffer[ FF_FAT_LFN_NAME_3 ] ), 4 );
- uiLfnLength += 13;
- xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- xNumLFNs--;
- }
- if( FF_isERR( xError ) )
- {
- break;
- }
- pxDirEntry->pcFileName[ uiLfnLength ] = '\0';
- }
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- /* UTF-8 Sequence, we can only convert this from the beginning, must receive entries in reverse. */
- nLfnBegin = usEntry - 1;
- for( xIndex = 0; xIndex < xNumLFNs; xIndex++ )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, ( nLfnBegin + ( xNumLFNs - 1 ) - xIndex ), pxFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- /* Now have the first part of the UTF-16 sequence. Stream into a UTF-8 sequence. */
- for( y = 0; y < 5; y++ )
- {
- xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
- ( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_1 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );
- if( xError > 0 )
- {
- usUtf8Len += ( uint16_t ) xError;
- }
- }
- for( y = 0; y < 6; y++ )
- {
- xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
- ( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_2 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );
- if( xError > 0 )
- {
- usUtf8Len += ( uint16_t ) xError;
- }
- }
- for( y = 0; y < 2; y++ )
- {
- xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
- ( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_3 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );
- if( xError > 0 )
- {
- usUtf8Len += ( uint16_t ) xError;
- }
- }
- usEntry++;
- }
- if( FF_isERR( xError ) )
- {
- break;
- }
- pxDirEntry->pcFileName[ usUtf8Len ] = '\0';
- /* Put Entry context to correct position. */
- xError = FF_FetchEntryWithContext( pxIOManager, usEntry - 1, pxFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- }
- #endif /* ( ffconfigUNICODE_UTF8_SUPPORT != 0 ) */
- #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 ) /* No Unicode, simple ASCII. */
- {
- pcLastPtr[ -1 ] = '\0';
- y = xNumLFNs;
- while( xNumLFNs-- )
- {
- pcCurPtr = pxDirEntry->pcFileName + ( xNumLFNs * 13 );
- for( xIndex = 0; ( xIndex < 10 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
- {
- *( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_1 + xIndex ];
- }
- for( xIndex = 0; ( xIndex < 12 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
- {
- *( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_2 + xIndex ];
- }
- for( xIndex = 0; ( xIndex < 4 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
- {
- *( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_3 + xIndex ];
- }
- if( ( xNumLFNs == ( y - 1 ) ) && ( pcCurPtr < pcLastPtr ) )
- {
- *pcCurPtr = '\0';
- }
- xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- }
- if( FF_isERR( xError ) )
- {
- break;
- }
- }
- #endif /* ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 ) */
- /* Process the Shortname. -- LFN Transformation is now complete.
- * Process the ShortName Entry. */
- /* if SHORTNAMES must be included, simple byte copy into shortname buffer. */
- #if ( ffconfigLFN_SUPPORT != 0 ) && ( ffconfigINCLUDE_SHORT_NAME != 0 )
- {
- memcpy( pxDirEntry->pcShortName, pucEntryBuffer, 11 );
- pxDirEntry->pcShortName[ 11 ] = '\0';
- FF_ProcessShortName( pxDirEntry->pcShortName );
- }
- #endif /* ( != 0 ffconfigLFN_SUPPORT ) && ( ffconfigINCLUDE_SHORT_NAME != 0 ) */
- memcpy( pcShortName, pucEntryBuffer, 11 );
- FF_ProcessShortName( pcShortName );
- if( ucCheckSum != FF_CreateChkSum( pucEntryBuffer ) )
- {
- strcpy( pxDirEntry->pcFileName, pcShortName );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- FF_ShortNameExpand( pxDirEntry->pcFileName );
- }
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- }
- /* Finally fill in the other details. */
- pxDirEntry->ulObjectCluster =
- ( ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH ) << 16 ) |
- ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW );
- #if ( ffconfigTIME_SUPPORT != 0 )
- {
- /* Get the creation Time & Date. */
- FF_GetTime( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_TIME );
- FF_GetDate( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_DATE );
- /* Get the modified Time & Date. */
- /* HT Here xCreateTime has become xModifiedTime, as it should: */
- FF_GetTime( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME );
- FF_GetDate( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE );
- /* Get the last accessed Date. */
- FF_GetDate( &pxDirEntry->xAccessedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTACC_DATE );
- /* HT Why should these times be zero'd ? */
- pxDirEntry->xAccessedTime.Hour = 0;
- pxDirEntry->xAccessedTime.Minute = 0;
- pxDirEntry->xAccessedTime.Second = 0;
- }
- #endif /* ffconfigTIME_SUPPORT */
- /* Get the filesize. */
- pxDirEntry->ulFileSize = FF_getLong( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_FILESIZE ) );
- /* Get the attribute. */
- pxDirEntry->ucAttrib = FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );
- pxDirEntry->usCurrentItem = usEntry;
- }
- while( pdFALSE );
- return xError;
- } /* FF_PopulateLongDirent() */
- /*-----------------------------------------------------------*/
- /**
- * @public
- * @brief Find's the first directory entry for the provided path.
- *
- * All values recorded in pxDirEntry must be preserved to and between calls to
- * FF_FindNext( ).
- *
- * If ffconfigFINDAPI_ALLOW_WILDCARDS is defined, then path will have the following behaviour:
- *
- * path = "\" - Open the root dir, and iterate through all items.
- * path = "\*.c" - Open the root dir, showing only files matching *.c wildcard.
- * path = "\sub1\newdir" - Get the DIRENT for the newdir directory in /sub1/ if one exists.
- * path = "\sub1\newdir\" - Open the directory /sub1/newdir/ and iterate through all items.
- * path = "\sub1\newdir\*.c" - Open the directory /sub1/newdir/ and iterate through all items matching the *.c wildcard.
- *
- * It is important to distinguish the differences in behaviour between opening a Find operation
- * on a path like /sub1 and /sub1/. ( /sub1 gets the sub1 dirent from the / dir, whereas /sub/ opens the sub1 dir ).
- *
- * Note, as compatible with other similar APIs, FreeRTOS+FAT also accepts \sub1\* for the same behaviour as
- * /sub1/.
- *
- * @param pxIOManager FF_IOManager_t object that was created by FF_CreateIOManger( ).
- * @param pxDirEntry FF_DirEnt_t object to store the entry information.
- * @param path String to of the path to the Dir being listed.
- *
- * @Return 0 on success
- * @Return FF_ERR_DEVICE_DRIVER_FAILED if device access failed.
- * @Return -2 if Dir was not found.
- *
- **/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_Error_t FF_FindFirst( FF_IOManager_t * pxIOManager,
- FF_DirEnt_t * pxDirEntry,
- const FF_T_WCHAR * pcPath )
- #else
- FF_Error_t FF_FindFirst( FF_IOManager_t * pxIOManager,
- FF_DirEnt_t * pxDirEntry,
- const char * pcPath )
- #endif
- {
- FF_Error_t xError;
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- uint16_t PathLen = ( uint16_t ) wcslen( pcPath );
- #else
- uint16_t PathLen = ( uint16_t ) strlen( pcPath );
- #endif
- #if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 )
- BaseType_t xIndex = 0;
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- const FF_T_WCHAR * pcWildCard; /* Check for a Wild-card. */
- #else
- const char * pcWildCard; /* Check for a Wild-card. */
- #endif
- #endif
- memset( pxDirEntry, 0, sizeof( FF_DirEnt_t ) );
- if( pxIOManager == NULL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_FINDFIRST );
- }
- #if ( ffconfigREMOVABLE_MEDIA != 0 )
- else if( ( pxIOManager->ucFlags & FF_IOMAN_DEVICE_IS_EXTRACTED ) != 0 )
- {
- xError = ( FF_Error_t ) ( FF_ERR_IOMAN_DRIVER_NOMEDIUM | FF_FINDFIRST );
- }
- #endif /* ffconfigREMOVABLE_MEDIA */
- else
- {
- #if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 )
- {
- pxDirEntry->pcWildCard[ 0 ] = '\0'; /* WildCard blank if its not a wildCard. */
- pcWildCard = &pcPath[ PathLen - 1 ];
- if( PathLen != 0 )
- {
- /* Open the dir of the last token. */
- while( ( *pcWildCard != '\\' ) && ( *pcWildCard != '/' ) )
- {
- xIndex++;
- pcWildCard--;
- if( PathLen == xIndex )
- {
- break;
- }
- }
- }
- pxDirEntry->ulDirCluster = FF_FindDir( pxIOManager, pcPath, PathLen - xIndex, &xError );
- if( FF_isERR( xError ) == pdFALSE )
- {
- if( pxDirEntry->ulDirCluster != 0 )
- {
- /* Valid Dir found, copy the wildCard to filename! */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- wcsncpy( pxDirEntry->pcWildCard, ++pcWildCard, ffconfigMAX_FILENAME );
- #else
- strncpy( pxDirEntry->pcWildCard, ++pcWildCard, ffconfigMAX_FILENAME );
- #endif
- if( pxDirEntry->pcWildCard[ xIndex - 1 ] == ':' )
- {
- pxDirEntry->xInvertWildCard = pdTRUE;
- pxDirEntry->pcWildCard[ xIndex - 1 ] = '\0';
- }
- }
- }
- }
- #else /* ffconfigFINDAPI_ALLOW_WILDCARDS */
- {
- /* Get the directory cluster, if it exists. */
- pxDirEntry->ulDirCluster = FF_FindDir( pxIOManager, pcPath, PathLen, &xError );
- }
- #endif /* ffconfigFINDAPI_ALLOW_WILDCARDS */
- if( FF_isERR( xError ) == pdFALSE )
- {
- if( pxDirEntry->ulDirCluster == 0 )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_INVALID_PATH | FF_FINDFIRST );
- }
- else
- {
- /* Initialise the Fetch Context. */
- xError = FF_InitEntryFetch( pxIOManager, pxDirEntry->ulDirCluster, &( pxDirEntry->xFetchContext ) );
- if( FF_isERR( xError ) == pdFALSE )
- {
- pxDirEntry->usCurrentItem = 0;
- xError = FF_FindNext( pxIOManager, pxDirEntry );
- }
- }
- }
- }
- return xError;
- } /* FF_FindFirst() */
- /*-----------------------------------------------------------*/
- /**
- * @public
- * @brief Get's the next Entry based on the data recorded in the FF_DirEnt_t object.
- *
- * All values recorded in pxDirEntry must be preserved to and between calls to
- * FF_FindNext( ). Please see @see FF_FindFirst( ) for find initialisation.
- *
- * @param pxIOManager FF_IOManager_t object that was created by FF_CreateIOManger( ).
- * @param pxDirEntry FF_DirEnt_t object to store the entry information. ( As initialised by FF_FindFirst( )).
- *
- * @Return FF_ERR_DEVICE_DRIVER_FAILED is device access failed.
- *
- **/
- FF_Error_t FF_FindNext( FF_IOManager_t * pxIOManager,
- FF_DirEnt_t * pxDirEntry )
- {
- FF_Error_t xError;
- BaseType_t xLFNCount;
- const uint8_t * pucEntryBuffer = NULL;
- #if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 )
- BaseType_t b;
- #endif
- if( pxIOManager == NULL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_FINDNEXT );
- }
- #if ( ffconfigREMOVABLE_MEDIA != 0 )
- else if( ( pxIOManager->ucFlags & FF_IOMAN_DEVICE_IS_EXTRACTED ) != 0 )
- {
- xError = ( FF_Error_t ) ( FF_ERR_IOMAN_DRIVER_NOMEDIUM | FF_FINDNEXT );
- }
- #endif /* ffconfigREMOVABLE_MEDIA */
- else
- {
- xError = FF_ERR_NONE;
- for( ; pxDirEntry->usCurrentItem < FF_MAX_ENTRIES_PER_DIRECTORY; pxDirEntry->usCurrentItem++ )
- {
- if( ( pucEntryBuffer == NULL ) ||
- ( pucEntryBuffer >= ( pxDirEntry->xFetchContext.pxBuffer->pucBuffer + ( pxIOManager->usSectorSize - FF_SIZEOF_DIRECTORY_ENTRY ) ) ) )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, pxDirEntry->usCurrentItem, &( pxDirEntry->xFetchContext ), NULL );
- if( FF_isERR( xError ) )
- {
- break;
- }
- if( pucEntryBuffer == NULL )
- {
- pucEntryBuffer = pxDirEntry->xFetchContext.pxBuffer->pucBuffer +
- ( FF_SIZEOF_DIRECTORY_ENTRY * ( pxDirEntry->usCurrentItem % ( pxIOManager->usSectorSize / FF_SIZEOF_DIRECTORY_ENTRY ) ) );
- }
- else
- {
- pucEntryBuffer = pxDirEntry->xFetchContext.pxBuffer->pucBuffer;
- }
- }
- else
- {
- pucEntryBuffer += FF_SIZEOF_DIRECTORY_ENTRY;
- }
- if( FF_isDeleted( pucEntryBuffer ) != pdFALSE )
- {
- /* The entry is not in use or deleted. */
- continue;
- }
- if( FF_isEndOfDir( pucEntryBuffer ) )
- {
- /* End of directory, generate a pseudo error 'DIR_END_OF_DIR'. */
- xError = ( FF_Error_t ) ( FF_ERR_DIR_END_OF_DIR | FF_FINDNEXT );
- break;
- }
- pxDirEntry->ucAttrib = FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );
- if( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_LFN ) == FF_FAT_ATTR_LFN )
- {
- /* LFN Processing. */
- xLFNCount = ( BaseType_t ) ( pucEntryBuffer[ 0 ] & ~0x40 );
- /* Get the shortname and check if it is marked deleted. */
- #if ( ffconfigLFN_SUPPORT != 0 )
- {
- /* Reserve 32 bytes to hold one directory entry. */
- uint8_t Buffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- /* Fetch the shortname, and get it's checksum, or for a deleted item with
- * orphaned LFN entries. */
- xError = FF_FetchEntryWithContext( pxIOManager, ( uint32_t ) ( pxDirEntry->usCurrentItem + xLFNCount ), &pxDirEntry->xFetchContext, Buffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- if( FF_isDeleted( Buffer ) == pdFALSE )
- {
- xError = FF_PopulateLongDirent( pxIOManager, pxDirEntry, pxDirEntry->usCurrentItem, &pxDirEntry->xFetchContext );
- if( FF_isERR( xError ) )
- {
- break;
- }
- #if ( ffconfigINCLUDE_SHORT_NAME != 0 )
- {
- pxDirEntry->ucAttrib |= FF_FAT_ATTR_IS_LFN;
- }
- #endif
- #if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 )
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- if( wcscmp( pxDirEntry->pcWildCard, L"" ) )
- #else
- if( pxDirEntry->pcWildCard[ 0 ] )
- #endif
- {
- b = FF_wildcompare( pxDirEntry->pcWildCard, pxDirEntry->pcFileName );
- if( pxDirEntry->xInvertWildCard != pdFALSE )
- {
- b = !b;
- }
- if( b != 0 )
- {
- break;
- }
- /* 'usCurrentItem' has already incremented by FF_PopulateLongDirent(),
- * this loop will incremente it again. */
- pxDirEntry->usCurrentItem -= 1;
- /* xFetchContext/usCurrentItem have changed. Update
- * 'pucEntryBuffer' to point to the current buffer position. */
- pucEntryBuffer = pxDirEntry->xFetchContext.pxBuffer->pucBuffer +
- ( FF_SIZEOF_DIRECTORY_ENTRY * ( pxDirEntry->usCurrentItem % ( pxIOManager->usSectorSize / FF_SIZEOF_DIRECTORY_ENTRY ) ) );
- }
- else
- {
- break;
- }
- }
- #else /* ffconfigFINDAPI_ALLOW_WILDCARDS == 0 */
- {
- /* usCurrentItem has been incremented by FF_PopulateLongDirent().
- * Entry will be returned. */
- break;
- }
- #endif /* if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 ) */
- }
- }
- #else /* ffconfigLFN_SUPPORT */
- {
- /* Increment 'usCurrentItem' with (xLFNCount-1),
- * the loop will do an extra increment. */
- pxDirEntry->usCurrentItem += ( xLFNCount - 1 );
- }
- #endif /* ffconfigLFN_SUPPORT */
- } /* ( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_LFN ) == FF_FAT_ATTR_LFN ) */
- else if( ( pxDirEntry->ucAttrib & FF_FAT_ATTR_VOLID ) != FF_FAT_ATTR_VOLID )
- {
- /* If it's not a LFN entry, neither a Volume ID, it is a normal short name entry. */
- FF_PopulateShortDirent( pxIOManager, pxDirEntry, pucEntryBuffer );
- #if ( ffconfigSHORTNAME_CASE != 0 )
- {
- /* Apply NT/XP+ bits to get correct case. */
- FF_CaseShortName( pxDirEntry->pcFileName, FF_getChar( pucEntryBuffer, FF_FAT_CASE_OFFS ) );
- }
- #endif
- #if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 )
- {
- if( pxDirEntry->pcWildCard[ 0 ] )
- {
- b = FF_wildcompare( pxDirEntry->pcWildCard, pxDirEntry->pcFileName );
- if( pxDirEntry->xInvertWildCard != pdFALSE )
- {
- b = !b;
- }
- if( b != 0 )
- {
- pxDirEntry->usCurrentItem += 1;
- break;
- }
- }
- else
- {
- pxDirEntry->usCurrentItem += 1;
- break;
- }
- }
- #else /* ffconfigFINDAPI_ALLOW_WILDCARDS */
- {
- pxDirEntry->usCurrentItem += 1;
- break;
- }
- #endif /* if ( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 ) */
- }
- } /* for ( ; pxDirEntry->usCurrentItem < FF_MAX_ENTRIES_PER_DIRECTORY; pxDirEntry->usCurrentItem++ ) */
- if( pxDirEntry->usCurrentItem == FF_MAX_ENTRIES_PER_DIRECTORY )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_END_OF_DIR | FF_FINDNEXT );
- }
- {
- FF_Error_t xTempError;
- xTempError = FF_CleanupEntryFetch( pxIOManager, &pxDirEntry->xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- }
- return xError;
- } /* FF_FindNext() */
- /*-----------------------------------------------------------*/
- /*
- * Returns >= 0 for a free dirent entry.
- * Returns < 0 with and xError code if anything goes wrong.
- */
- static int32_t FF_FindFreeDirent( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams,
- uint16_t usSequential )
- {
- const uint8_t * pucEntryBuffer = NULL;
- uint16_t freeCount = 0;
- UBaseType_t uxEntry = 0;
- BaseType_t xEntryFound = pdFALSE;
- FF_Error_t xError;
- uint32_t DirLength;
- FF_FetchContext_t xFetchContext;
- uint32_t ulDirCluster = pxFindParams->ulDirCluster;
- xError = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- uxEntry = pxFindParams->lFreeEntry >= 0 ? pxFindParams->lFreeEntry : 0;
- for( ; uxEntry < FF_MAX_ENTRIES_PER_DIRECTORY; uxEntry++ )
- {
- if( ( pucEntryBuffer == NULL ) ||
- ( pucEntryBuffer >= xFetchContext.pxBuffer->pucBuffer + ( pxIOManager->usSectorSize - FF_SIZEOF_DIRECTORY_ENTRY ) ) )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, uxEntry, &xFetchContext, NULL );
- if( FF_GETERROR( xError ) == FF_ERR_DIR_END_OF_DIR )
- {
- xError = FF_ExtendDirectory( pxIOManager, ulDirCluster );
- /* The value of xEntryFound will be ignored in case there was an error. */
- xEntryFound = pdTRUE;
- break;
- }
- else if( FF_isERR( xError ) )
- {
- break;
- }
- if( pucEntryBuffer == NULL )
- {
- pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer +
- ( FF_SIZEOF_DIRECTORY_ENTRY * ( uxEntry % ( pxIOManager->usSectorSize / FF_SIZEOF_DIRECTORY_ENTRY ) ) );
- }
- else
- {
- pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer;
- }
- }
- else
- {
- /* Advance 32 bytes to point to the next directory entry. */
- pucEntryBuffer += FF_SIZEOF_DIRECTORY_ENTRY;
- }
- if( FF_isEndOfDir( pucEntryBuffer ) ) /* If its the end of the Dir, then FreeDirents from here. */
- {
- /* Check if the directory has enough space */
- DirLength = xFetchContext.ulChainLength;
- if( ( uxEntry + usSequential ) >
- ( ( DirLength * ( ( UBaseType_t ) pxIOManager->xPartition.ulSectorsPerCluster * pxIOManager->xPartition.usBlkSize ) ) / FF_SIZEOF_DIRECTORY_ENTRY ) )
- {
- xError = FF_ExtendDirectory( pxIOManager, ulDirCluster );
- }
- xEntryFound = pdTRUE;
- break;
- }
- if( FF_isDeleted( pucEntryBuffer ) )
- {
- if( ++freeCount == usSequential )
- {
- xError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- xEntryFound = pdTRUE;
- uxEntry = ( uxEntry - ( usSequential - 1 ) ); /* Return the beginning entry in the sequential sequence. */
- break;
- }
- }
- else
- {
- freeCount = 0;
- }
- } /* for ( uxEntry = 0; uxEntry < FF_MAX_ENTRIES_PER_DIRECTORY; uxEntry++ ) */
- {
- FF_Error_t xTempError;
- xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- }
- if( FF_isERR( xError ) == pdFALSE )
- {
- if( xEntryFound != pdFALSE )
- {
- /* No error has occurred and a free directory entry has been found. */
- xError = uxEntry;
- }
- else
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_DIRECTORY_FULL | FF_FINDFREEDIRENT );
- }
- }
- return xError;
- } /* FF_FindFreeDirent() */
- /*-----------------------------------------------------------*/
- /* _HT_ Now FF_PutEntry has a new optional parameter *pucContents */
- /* _HT_ so it can be used FF_MkDir( ) to save some code when adding . and .. entries */
- FF_Error_t FF_PutEntry( FF_IOManager_t * pxIOManager,
- uint16_t usEntry,
- uint32_t ulDirCluster,
- FF_DirEnt_t * pxDirEntry,
- uint8_t * pucContents )
- {
- FF_Error_t xError;
- /* Reserve 32 bytes to hold one directory entry. */
- uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- FF_FetchContext_t xFetchContext;
- /* HT: use the standard access routine to get the same logic for root dirs. */
- xError = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, usEntry, &xFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) == pdFALSE )
- {
- /* Cleanup probably not necessary here?
- * FF_PushEntryWithContext checks for R/W flag. */
- xError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- if( pucContents != NULL )
- {
- memcpy( pucEntryBuffer, pucContents, sizeof( pucEntryBuffer ) );
- }
- FF_putChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB, ( uint32_t ) pxDirEntry->ucAttrib );
- FF_putShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH, ( uint32_t ) ( pxDirEntry->ulObjectCluster >> 16 ) );
- FF_putShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW, ( uint32_t ) ( pxDirEntry->ulObjectCluster ) );
- FF_putLong( pucEntryBuffer, FF_FAT_DIRENT_FILESIZE, pxDirEntry->ulFileSize );
- #if ( ffconfigTIME_SUPPORT != 0 )
- {
- FF_GetSystemTime( &pxDirEntry->xAccessedTime ); /*/< Date of Last Access. */
- FF_PlaceTime( pucEntryBuffer, FF_FAT_DIRENT_LASTACC_DATE, &pxDirEntry->xAccessedTime );
- FF_PlaceDate( pucEntryBuffer, FF_FAT_DIRENT_LASTACC_DATE, &pxDirEntry->xAccessedTime ); /* Last accessed date. */
- 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 */
- xError = FF_PushEntryWithContext( pxIOManager, usEntry, &xFetchContext, pucEntryBuffer );
- }
- }
- }
- FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- return xError;
- } /* FF_PutEntry() */
- /*-----------------------------------------------------------*/
- static BaseType_t FF_ValidShortChar( char cChar )
- {
- return ( cChar >= 'A' && cChar <= 'Z' ) ||
- ( cChar >= 'a' && cChar <= 'z' ) || /* lower-case can be stored using NT/XP attribute. */
- ( cChar >= '0' && cChar <= '9' ) ||
- strchr( "$%-_@~`!(){}^#&", cChar ) != NULL;
- } /* FF_ValidShortChar() */
- /*-----------------------------------------------------------*/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- void FF_CreateShortName( FF_FindParams_t * pxFindParams,
- const FF_T_WCHAR * pcLongName )
- #else
- void FF_CreateShortName( FF_FindParams_t * pxFindParams,
- const char * pcLongName )
- #endif
- {
- BaseType_t xIndex, xPosition, xLastDot;
- uint16_t NameLen;
- #if ( ffconfigSHORTNAME_CASE != 0 )
- uint8_t testAttrib = FF_FAT_CASE_ATTR_BASE;
- #endif
- /* Examples:
- * "readme.TXT" will get the attribute FF_FAT_CASE_ATTR_BASE
- * "README.txt" will get the attribute FF_FAT_CASE_ATTR_EXT
- * "Readme.txt" can not be store as a short name */
- pxFindParams->ucCaseAttrib = 0; /* May get the value FF_FAT_CASE_ATTR_BASE or FF_FAT_CASE_ATTR_EXT */
- pxFindParams->ucFirstTilde = 6; /* The numerical position of the ~ */
- pxFindParams->ulFlags |= FIND_FLAG_SHORTNAME_SET | FIND_FLAG_FITS_SHORT | FIND_FLAG_SIZE_OK;
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- NameLen = ( uint16_t ) wcslen( pcLongName );
- }
- #else
- {
- NameLen = ( uint16_t ) strlen( pcLongName );
- }
- #endif
- /* Does pcLongName fit a shortname? */
- for( xIndex = 0, xPosition = 0, xLastDot = NameLen; xIndex < NameLen; xIndex++ )
- {
- if( pcLongName[ xIndex ] != '.' )
- {
- xPosition++;
- }
- else
- {
- xLastDot = xIndex;
- }
- }
- /* For example:
- * "FILENAME.EXT": NameLen = 12, xLastDot = 8, xPosition = 11
- * ".cproject" : NameLen = 9, xLastDot = 0, xPosition = 8
- */
- if( ( NameLen > 12 ) || /* If name is longer than 12 characters (8.3). */
- ( NameLen - xPosition > 1 ) || /* If it contains more than 1 dot. */
- ( NameLen - xLastDot > 4 ) || /* If the file name extension is longer than 3 characters. */
- ( xLastDot > 8 ) ) /* If the file name base is too long. */
- {
- pxFindParams->ulFlags &= ~FIND_FLAG_SIZE_OK;
- }
- for( xIndex = 0, xPosition = 0; xIndex < 11; xPosition++ )
- {
- char ch = pcLongName[ xPosition ];
- if( !ch )
- {
- break;
- }
- if( ( xIndex == 0 ) && ( ch == '.' ) )
- {
- pxFindParams->ulFlags &= ~FIND_FLAG_FITS_SHORT;
- continue;
- }
- if( xPosition == xLastDot )
- {
- /* Remember where we put the first space. */
- if( pxFindParams->ucFirstTilde > xIndex )
- {
- pxFindParams->ucFirstTilde = xIndex;
- }
- while( xIndex < 8 )
- {
- pxFindParams->pcEntryBuffer[ xIndex++ ] = 0x20;
- }
- #if ( ffconfigSHORTNAME_CASE != 0 )
- {
- testAttrib = FF_FAT_CASE_ATTR_EXT;
- }
- #endif
- }
- else
- {
- if( xIndex == 8 )
- {
- if( xPosition <= xLastDot )
- {
- xPosition = xLastDot;
- ch = ( int8_t ) pcLongName[ xPosition ];
- if( ch == '\0' )
- {
- break;
- }
- ch = ( int8_t ) pcLongName[ ++xPosition ];
- #if ( ffconfigSHORTNAME_CASE != 0 )
- {
- testAttrib = FF_FAT_CASE_ATTR_EXT;
- }
- #endif
- }
- }
- if( !FF_ValidShortChar( ch ) )
- {
- pxFindParams->ulFlags &= ~FIND_FLAG_FITS_SHORT;
- continue;
- }
- #if ( ffconfigSHORTNAME_CASE != 0 )
- {
- if( ( ch >= 'a' ) && ( ch <= 'z' ) )
- {
- ch -= 0x20;
- if( testAttrib )
- {
- pxFindParams->ucCaseAttrib |= testAttrib;
- }
- else
- {
- pxFindParams->ulFlags &= ~FIND_FLAG_FITS_SHORT; /* We had capital: does not fit. */
- }
- }
- else if( ( ch >= 'A' ) && ( ch <= 'Z' ) )
- {
- if( ( pxFindParams->ucCaseAttrib & testAttrib ) != 0 )
- {
- pxFindParams->ulFlags &= ~FIND_FLAG_FITS_SHORT; /* We had lower-case: does not fit. */
- }
- testAttrib = 0;
- }
- }
- #else /* if ( ffconfigSHORTNAME_CASE != 0 ) */
- {
- if( ( ch >= 'a' ) && ( ch <= 'z' ) )
- {
- ch -= 0x20;
- }
- }
- #endif /* ffconfigSHORTNAME_CASE */
- pxFindParams->pcEntryBuffer[ xIndex++ ] = ch;
- }
- }
- if( ( xLastDot == 0 ) && ( xIndex < 6 ) )
- {
- /* This is a file name like ".info" or ".root" */
- pxFindParams->ucFirstTilde = xIndex;
- }
- while( xIndex < 11 )
- {
- pxFindParams->pcEntryBuffer[ xIndex++ ] = 0x20;
- }
- if( ( xLastDot < pxFindParams->ucFirstTilde ) && ( xLastDot > 0 ) )
- {
- pxFindParams->ucFirstTilde = xLastDot;
- }
- if( NameLen < pxFindParams->ucFirstTilde ) /* Names like "Abc" will become "~Abc". */
- {
- pxFindParams->ucFirstTilde = ( uint8_t ) NameLen;
- }
- } /* FF_CreateShortName() */
- /*-----------------------------------------------------------*/
- int32_t FF_FindShortName( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams )
- {
- char pcMyShortName[ 13 ];
- FF_DirEnt_t xMyDirectory;
- FF_Error_t xResult = 0;
- BaseType_t xIndex, x, y;
- uint16_t NameLen;
- char pcNumberBuf[ 12 ];
- uint32_t ulCluster;
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_T_WCHAR pcFileName[ 13 ];
- #else
- char * pcFileName = pcMyShortName;
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- #if ( ipconfigQUICK_SHORT_FILENAME_CREATION != 0 )
- uint16_t usShortHash;
- uint32_t ulRand = 0ul;
- #endif
- memcpy( pcMyShortName, pxFindParams->pcEntryBuffer, 11 );
- FF_ProcessShortName( pcMyShortName );
- if( ( pxFindParams->ulFlags & FIND_FLAG_FITS_SHORT_OK ) == FIND_FLAG_FITS_SHORT_OK )
- {
- /* This entry will not get a LFN entry because it fits
- * perfectly into a host name */
- if( ( pxFindParams->ulFlags & FIND_FLAG_SHORTNAME_CHECKED ) != 0 )
- {
- if( ( pxFindParams->ulFlags & FIND_FLAG_SHORTNAME_FOUND ) != 0 )
- {
- xResult = ( FF_Error_t ) ( FF_ERR_DIR_OBJECT_EXISTS | FF_CREATESHORTNAME );
- }
- else
- {
- xResult = pxFindParams->ucCaseAttrib | 0x01;
- }
- }
- else
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- memcpy( pcFileName, pcMyShortName, sizeof( pcMyShortName ) );
- FF_ShortNameExpand( pcFileName );
- }
- #endif
- ulCluster = FF_FindEntryInDir( pxIOManager, pxFindParams, pcFileName, 0x00, &xMyDirectory, &xResult );
- /* END_OF_DIR is not a fatal error, it only means that the entry was not found. */
- if( ( FF_isERR( xResult ) == pdFALSE ) || ( FF_GETERROR( xResult ) == FF_ERR_DIR_END_OF_DIR ) )
- {
- if( ulCluster == 0UL )
- {
- xResult = pxFindParams->ucCaseAttrib | 0x01;
- }
- else
- {
- xResult = ( FF_Error_t ) ( FF_ERR_DIR_OBJECT_EXISTS | FF_CREATESHORTNAME );
- }
- }
- else
- {
- /* There was an error, which will be returned. */
- }
- }
- }
- else
- {
- for( xIndex = ( ( pxFindParams->ulFlags & FIND_FLAG_SIZE_OK ) ? 0 : 1 ); ; xIndex++ )
- {
- if( xIndex != 0 )
- {
- #if ( ipconfigQUICK_SHORT_FILENAME_CREATION != 0 )
- {
- /* In the first round, check if the original name can be used
- * Makefile will be stored as "makefile" and not as "makefi~1". */
- /* This method saves a lot of time when creating directories with
- * many similar file names: when the short name version of a LFN already
- * exists, try at most 3 entries with a tilde:
- * README~1.TXT
- * README~2.TXT
- * README~3.TXT
- * After that create entries with pseudo-random 4-digit hex digits:
- * REA~E7BB.TXT
- * REA~BA32.TXT
- * REA~D394.TXT
- */
- if( xIndex <= 4 )
- {
- snprintf( pcNumberBuf, sizeof( pcNumberBuf ), "%d", ( int ) xIndex );
- }
- else
- {
- if( ulRand == 0ul )
- {
- ulRand = pxIOManager->xPartition.ulLastFreeCluster;
- usShortHash = FF_GetCRC16( ( uint8_t * ) &ulRand, sizeof( ulRand ) );
- }
- else
- {
- usShortHash = FF_GetCRC16( ( uint8_t * ) &usShortHash, sizeof( usShortHash ) );
- }
- snprintf( pcNumberBuf, sizeof( pcNumberBuf ), "%04X", ( int ) usShortHash );
- }
- }
- #else /* if ( ipconfigQUICK_SHORT_FILENAME_CREATION != 0 ) */
- {
- snprintf( pcNumberBuf, sizeof( pcNumberBuf ), "%d", ( int ) xIndex );
- }
- #endif /* if ( ipconfigQUICK_SHORT_FILENAME_CREATION != 0 ) */
- NameLen = ( uint16_t ) strlen( pcNumberBuf );
- x = 7 - NameLen;
- if( x > pxFindParams->ucFirstTilde )
- {
- x = pxFindParams->ucFirstTilde;
- }
- pxFindParams->pcEntryBuffer[ x++ ] = '~';
- for( y = 0; y < NameLen; y++ )
- {
- pxFindParams->pcEntryBuffer[ x + y ] = pcNumberBuf[ y ];
- }
- }
- memcpy( pcMyShortName, pxFindParams->pcEntryBuffer, 11 );
- FF_ProcessShortName( pcMyShortName );
- if( FF_ShortNameExists( pxIOManager, pxFindParams->ulDirCluster, pcMyShortName, &xResult ) == pdFALSE )
- {
- break;
- }
- if( xIndex >= FF_MAX_ENTRIES_PER_DIRECTORY )
- {
- xResult = ( FF_Error_t ) ( FF_ERR_DIR_DIRECTORY_FULL | FF_CREATESHORTNAME );
- break;
- }
- }
- /* Add a tail and special number until we're happy :D. */
- }
- return xResult;
- } /* FF_FindShortName () */
- /*-----------------------------------------------------------*/
- #if ( ffconfigLFN_SUPPORT != 0 )
- static int8_t FF_CreateLFNEntry( uint8_t * pucEntryBuffer,
- uint8_t * pcName,
- UBaseType_t uxNameLength,
- UBaseType_t uxLFN,
- uint8_t ucCheckSum )
- {
- /*
- * HT for JW:
- * Changed *pcName from 16- to of 8-bits
- * The caller of this function doesn't need an expensive
- * uint16_t usUtf16Name[ffconfigMAX_FILENAME + 1];
- * in case UNICODE isn't used
- * Also did quite a bit of optimisation here
- * and tested well
- */
- UBaseType_t uxIndex, x;
- memset( pucEntryBuffer, 0, FF_SIZEOF_DIRECTORY_ENTRY );
- FF_putChar( pucEntryBuffer, FF_FAT_LFN_ORD, ( uint8_t ) ( ( uxLFN & ~0x40 ) ) );
- FF_putChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB, ( uint8_t ) FF_FAT_ATTR_LFN );
- FF_putChar( pucEntryBuffer, FF_FAT_LFN_CHECKSUM, ( uint8_t ) ucCheckSum );
- /* Name_1. */
- uxIndex = 0;
- for( x = FF_FAT_LFN_NAME_1; uxIndex < 5u; uxIndex++, x += 2 )
- {
- if( uxIndex < uxNameLength )
- {
- pucEntryBuffer[ x ] = *( pcName++ );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- pucEntryBuffer[ x + 1 ] = *( pcName++ );
- }
- #endif
- }
- else if( uxIndex > uxNameLength )
- {
- pucEntryBuffer[ x ] = 0xFF;
- pucEntryBuffer[ x + 1 ] = 0xFF;
- }
- }
- /* Name_2. */
- for( x = FF_FAT_LFN_NAME_2; uxIndex < 11u; uxIndex++, x += 2 )
- {
- if( uxIndex < uxNameLength )
- {
- pucEntryBuffer[ x ] = *( pcName++ );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- pucEntryBuffer[ x + 1 ] = *( pcName++ );
- }
- #endif
- }
- else if( uxIndex > uxNameLength )
- {
- pucEntryBuffer[ x ] = 0xFF;
- pucEntryBuffer[ x + 1 ] = 0xFF;
- }
- }
- /* Name_3. */
- for( x = FF_FAT_LFN_NAME_3; uxIndex < 13u; uxIndex++, x += 2 )
- {
- if( uxIndex < uxNameLength )
- {
- pucEntryBuffer[ x ] = *( pcName++ );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- pucEntryBuffer[ x + 1 ] = *( pcName++ );
- }
- #endif
- }
- else if( uxIndex > uxNameLength )
- {
- pucEntryBuffer[ x ] = 0xFF;
- pucEntryBuffer[ x + 1 ] = 0xFF;
- }
- }
- return FF_ERR_NONE;
- } /* FF_CreateLFNEntry() */
- #endif /* ffconfigLFN_SUPPORT */
- /*-----------------------------------------------------------*/
- #if ( ffconfigLFN_SUPPORT != 0 )
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- static FF_Error_t FF_CreateLFNs( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- FF_T_WCHAR * pcName,
- uint8_t ucCheckSum,
- uint16_t usEntry )
- #else
- static FF_Error_t FF_CreateLFNs( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- char * pcName,
- uint8_t ucCheckSum,
- uint16_t usEntry )
- #endif /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
- {
- FF_Error_t xError = FF_ERR_NONE;
- BaseType_t xNumLFNs;
- BaseType_t xEndPos;
- BaseType_t xIndex, y;
- FF_FetchContext_t xFetchContext;
- uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- int32_t slRetVal;
- #endif
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- uint16_t usUtf16Name[ ffconfigMAX_FILENAME + 1 ];
- #endif
- #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
- char * NamePtr;
- #else
- int16_t * NamePtr;
- #endif
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- #if WCHAR_MAX <= 0xFFFF
- {
- y = wcslen( pcName );
- if( y > ffconfigMAX_FILENAME )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_NAME_TOO_LONG | FF_CREATELFNS );
- }
- else
- {
- wcsncpy( usUtf16Name, pcName, ffconfigMAX_FILENAME );
- }
- }
- #else /* if WCHAR_MAX <= 0xFFFF */
- {
- xIndex = 0;
- y = 0;
- while( pcName[ xIndex ] )
- {
- FF_Utf32ctoUtf16c( &usUtf16Name[ y ], ( uint32_t ) pcName[ xIndex ], ffconfigMAX_FILENAME - xIndex );
- y += FF_GetUtf16SequenceLen( usUtf16Name[ y ] );
- xIndex++;
- if( y > ffconfigMAX_FILENAME )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_NAME_TOO_LONG | FF_CREATELFNS );
- break;
- }
- }
- }
- #endif /* if WCHAR_MAX <= 0xFFFF */
- }
- #endif /* ffconfigUNICODE_UTF16_SUPPORT */
- /* Convert the name into UTF-16 format. */
- #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- /* Simply convert the UTF8 to UTF16 and be done with it. */
- xIndex = 0;
- y = 0;
- while( pcName[ xIndex ] != 0 )
- {
- slRetVal = FF_Utf8ctoUtf16c( &( usUtf16Name[ y ] ), ( uint8_t * ) &( pcName[ xIndex ] ), ffconfigMAX_FILENAME - xIndex );
- if( slRetVal > 0 )
- {
- xIndex += slRetVal;
- }
- else
- {
- break; /* No more space in the UTF-16 buffer, simply truncate for safety. */
- }
- y += FF_GetUtf16SequenceLen( usUtf16Name[ y ] );
- if( y > ffconfigMAX_FILENAME )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_NAME_TOO_LONG | FF_CREATELFNS );
- break;
- }
- }
- }
- #elif ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
- {
- /* Just check the length. */
- y = strlen( pcName );
- if( y > ffconfigMAX_FILENAME )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_NAME_TOO_LONG | FF_CREATELFNS );
- }
- }
- #endif /* if ( ffconfigUNICODE_UTF8_SUPPORT != 0 ) */
- /* Whole name is now in a valid UTF-16 format. Lets go make thos LFN's.
- * At this point, it should a be the length of the name. */
- if( FF_isERR( xError ) == pdFALSE )
- {
- xNumLFNs = y / 13; /* Number of LFNs is the total number of UTF-16 units, divided by 13 ( 13 units per LFN ). */
- xEndPos = y % 13; /* The ending position in an LFN, of the last LFN UTF-16 character. */
- if( xEndPos )
- {
- xNumLFNs++;
- }
- else
- {
- xEndPos = 13;
- }
- xError = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- NamePtr = ( int16_t * ) ( usUtf16Name + 13 * ( xNumLFNs - 1 ) );
- }
- #elif ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
- {
- NamePtr = ( char * ) ( usUtf16Name + 13 * ( xNumLFNs - 1 ) );
- }
- #else
- {
- NamePtr = pcName + 13 * ( xNumLFNs - 1 );
- }
- #endif /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
- /* After this point, xIndex is no longer the length of the Filename in UTF-16 units. */
- for( xIndex = xNumLFNs; xIndex > 0; xIndex-- )
- {
- if( xIndex == xNumLFNs )
- {
- FF_CreateLFNEntry( pucEntryBuffer, ( uint8_t * ) NamePtr, ( UBaseType_t ) xEndPos, ( UBaseType_t ) xIndex, ucCheckSum );
- pucEntryBuffer[ 0 ] |= 0x40;
- }
- else
- {
- FF_CreateLFNEntry( pucEntryBuffer, ( uint8_t * ) NamePtr, ( UBaseType_t ) 13u, ( UBaseType_t ) xIndex, ucCheckSum );
- }
- NamePtr -= 13;
- xError = FF_PushEntryWithContext( pxIOManager, ( uint32_t ) ( usEntry + ( xNumLFNs - xIndex ) ), &xFetchContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- }
- {
- FF_Error_t xTempError;
- /* Release any buffers that were used. */
- xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- if( FF_isERR( xTempError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- }
- }
- return xError;
- } /* FF_CreateLFNs() */
- #endif /* ffconfigLFN_SUPPORT */
- /*-----------------------------------------------------------*/
- FF_Error_t FF_ExtendDirectory( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster )
- {
- uint32_t xCurrentCluster;
- uint32_t xNextCluster = 0UL;
- FF_Error_t xError = FF_ERR_NONE;
- FF_FATBuffers_t xFATBuffers;
- if( ( ulDirCluster == pxIOManager->xPartition.ulRootDirCluster ) &&
- ( pxIOManager->xPartition.ucType != FF_T_FAT32 ) )
- {
- /* root directories on FAT12 and FAT16 can not be extended. */
- xError = ( FF_Error_t ) ( FF_ERR_DIR_CANT_EXTEND_ROOT_DIR | FF_EXTENDDIRECTORY );
- }
- else if( pxIOManager->xPartition.ulFreeClusterCount == 0UL )
- {
- /* The number of free clusters was not yet calculated or equal to zero. */
- pxIOManager->xPartition.ulFreeClusterCount = FF_CountFreeClusters( pxIOManager, &xError );
- }
- if( FF_isERR( xError ) == pdFALSE )
- {
- if( pxIOManager->xPartition.ulFreeClusterCount == 0UL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_FAT_NO_FREE_CLUSTERS | FF_EXTENDDIRECTORY );
- }
- else
- {
- FF_LockFAT( pxIOManager );
- {
- xCurrentCluster = FF_FindEndOfChain( pxIOManager, ulDirCluster, &xError );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xNextCluster = FF_FindFreeCluster( pxIOManager, &xError, pdTRUE );
- if( FF_isERR( xError ) == pdFALSE )
- {
- FF_InitFATBuffers( &xFATBuffers, FF_MODE_WRITE );
- /* xNextCluster already has been set to 0xFFFFFFFF,
- * now let xCurrentCluster point to xNextCluster. */
- xError = FF_putFATEntry( pxIOManager, xCurrentCluster, xNextCluster, &xFATBuffers );
- {
- FF_Error_t xTempError;
- xTempError = FF_ReleaseFATBuffers( pxIOManager, &xFATBuffers );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- xTempError = FF_DecreaseFreeClusters( pxIOManager, 1 );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- }
- }
- }
- FF_UnlockFAT( pxIOManager );
- if( FF_isERR( xError ) == pdFALSE )
- {
- /* The entire cluster will be filled with zero's,
- * because it will contain directory data. */
- xError = FF_ClearCluster( pxIOManager, xNextCluster );
- }
- }
- }
- return xError;
- } /* FF_ExtendDirectory() */
- /*-----------------------------------------------------------*/
- static const uint8_t forbiddenChrs[] =
- {
- /* Windows says: don't use these characters: '\/:*?"<>|'
- * " * / : < > ? '\' ? | */
- 0x22, 0x2A, 0x2F, 0x3A, 0x3C, 0x3E, 0x3F, 0x5C, 0x7F, 0x7C
- };
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- static void FF_MakeNameCompliant( FF_T_WCHAR * pcName )
- #else
- static void FF_MakeNameCompliant( char * pcName )
- #endif
- {
- BaseType_t index;
- if( ( uint8_t ) pcName[ 0 ] == FF_FAT_DELETED ) /* Support Japanese KANJI symbol0xE5. */
- {
- pcName[ 0 ] = 0x05;
- }
- for( ; *pcName; pcName++ )
- {
- for( index = 0; index < ( BaseType_t ) sizeof( forbiddenChrs ); index++ )
- {
- if( *pcName == forbiddenChrs[ index ] )
- {
- *pcName = '_';
- break;
- }
- }
- }
- } /* FF_MakeNameCompliant() */
- /*-----------------------------------------------------------*/
- 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() */
- /*-----------------------------------------------------------*/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- uint32_t FF_CreateFile( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams,
- FF_T_WCHAR * pcFileName,
- FF_DirEnt_t * pxDirEntry,
- FF_Error_t * pxError )
- #else
- uint32_t FF_CreateFile( FF_IOManager_t * pxIOManager,
- FF_FindParams_t * pxFindParams,
- char * pcFileName,
- FF_DirEnt_t * pxDirEntry,
- FF_Error_t * pxError )
- #endif /* if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) */
- {
- FF_DirEnt_t xMyFile;
- FF_Error_t xTempError, xError = FF_ERR_NONE;
- uint32_t ulResult;
- memset( &xMyFile, '\0', sizeof( xMyFile ) );
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- wcsncpy( xMyFile.pcFileName, pcFileName, ffconfigMAX_FILENAME );
- }
- #else
- {
- strncpy( xMyFile.pcFileName, pcFileName, ffconfigMAX_FILENAME );
- }
- #endif
- xMyFile.ulObjectCluster = FF_CreateClusterChain( pxIOManager, &xError );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = FF_CreateDirent( pxIOManager, pxFindParams, &xMyFile );
- if( FF_isERR( xError ) == pdFALSE )
- {
- /* The new file now has a cluster chain and it has an entry
- * in its directory. Copy data to a pointer provided by caller: */
- if( pxDirEntry != NULL )
- {
- memcpy( pxDirEntry, &xMyFile, sizeof( FF_DirEnt_t ) );
- }
- }
- else
- {
- /* An error occurred in FF_CreateDirent().
- * Unlink the file's cluster chain: */
- FF_LockFAT( pxIOManager );
- {
- FF_UnlinkClusterChain( pxIOManager, xMyFile.ulObjectCluster, 0 );
- xMyFile.ulObjectCluster = 0ul;
- }
- FF_UnlockFAT( pxIOManager );
- }
- /* Now flush all buffers to disk. */
- xTempError = FF_FlushCache( pxIOManager );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- *pxError = xError;
- if( FF_isERR( xError ) == pdFALSE )
- {
- ulResult = xMyFile.ulObjectCluster;
- }
- else
- {
- ulResult = 0;
- }
- return ulResult;
- } /* FF_CreateFile() */
- /*-----------------------------------------------------------*/
- /**
- * @brief Creates a Directory of the specified path.
- *
- * @param pxIOManager Pointer to the FF_IOManager_t object.
- * @param pcPath Path of the directory to create.
- *
- * @Return FF_ERR_NULL_POINTER if pxIOManager was NULL.
- * @Return FF_ERR_DIR_OBJECT_EXISTS if the object specified by path already exists.
- * @Return FF_ERR_DIR_INVALID_PATH
- * @Return FF_ERR_NONE on success.
- **/
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_Error_t FF_MkDir( FF_IOManager_t * pxIOManager,
- const FF_T_WCHAR * pcPath )
- #else
- FF_Error_t FF_MkDir( FF_IOManager_t * pxIOManager,
- const char * pcPath )
- #endif
- {
- FF_DirEnt_t xMyDirectory;
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- const FF_T_WCHAR * pcDirName;
- #else
- const char * pcDirName;
- #endif
- uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- uint32_t ulObjectCluster;
- BaseType_t xIndex;
- FF_Error_t xError = FF_ERR_NONE;
- FF_FindParams_t xFindParams;
- memset( &xFindParams, '\0', sizeof( xFindParams ) );
- /* Inform the functions that the entry will be created if not found */
- xFindParams.ulFlags |= FIND_FLAG_CREATE_FLAG;
- /* Open a do {} while ( pdFALSE ) loop */
- do
- {
- if( pxIOManager == NULL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_MKDIR );
- break;
- }
- #if ( ffconfigREMOVABLE_MEDIA != 0 )
- if( ( pxIOManager->ucFlags & FF_IOMAN_DEVICE_IS_EXTRACTED ) != 0 )
- {
- xError = ( FF_Error_t ) ( FF_ERR_IOMAN_DRIVER_NOMEDIUM | FF_MKDIR );
- break;
- }
- #endif /* ffconfigREMOVABLE_MEDIA */
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- xIndex = ( BaseType_t ) wcslen( pcPath );
- }
- #else
- {
- xIndex = ( BaseType_t ) strlen( pcPath );
- }
- #endif
- /* Find the last slash in the path. */
- while( xIndex != 0 )
- {
- if( ( pcPath[ xIndex ] == '\\' ) || ( pcPath[ xIndex ] == '/' ) )
- {
- break;
- }
- xIndex--;
- }
- pcDirName = pcPath + xIndex + 1;
- if( xIndex == 0 )
- {
- xIndex = 1;
- }
- if( pcDirName[ 0 ] == '\0' )
- {
- xError = ( FF_ERR_DIR_OBJECT_EXISTS | FF_MKDIR );
- break;
- }
- xFindParams.ulDirCluster = FF_FindDir( pxIOManager, pcPath, ( uint16_t ) xIndex, &xError );
- if( FF_isERR( xError ) )
- {
- break;
- }
- if( xFindParams.ulDirCluster == 0UL )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_INVALID_PATH | FF_MKDIR );
- break;
- }
- memset( &xMyDirectory, '\0', sizeof( xMyDirectory ) );
- /* Will set flags FIND_FLAG_FITS_SHORT and FIND_FLAG_SIZE_OK */
- FF_CreateShortName( &xFindParams, pcDirName );
- if( FF_FindEntryInDir( pxIOManager, &xFindParams, pcDirName, 0x00, &xMyDirectory, &xError ) )
- {
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = ( FF_Error_t ) ( FF_ERR_DIR_OBJECT_EXISTS | FF_MKDIR );
- }
- break;
- }
- if( ( FF_isERR( xError ) ) && ( FF_GETERROR( xError ) != FF_ERR_DIR_END_OF_DIR ) )
- {
- break;
- }
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- {
- wcsncpy( xMyDirectory.pcFileName, pcDirName, ffconfigMAX_FILENAME );
- }
- #else
- {
- strncpy( xMyDirectory.pcFileName, pcDirName, ffconfigMAX_FILENAME );
- }
- #endif
- xMyDirectory.ulFileSize = 0;
- xMyDirectory.ucAttrib = FF_FAT_ATTR_DIR;
- xMyDirectory.ulObjectCluster = FF_CreateClusterChain( pxIOManager, &xError );
- /* Give all entries a proper time stamp, looks nicer than 1 Jan 1970 */
- #if ( ffconfigTIME_SUPPORT != 0 )
- {
- FF_GetSystemTime( &xMyDirectory.xCreateTime );
- FF_GetSystemTime( &xMyDirectory.xModifiedTime );
- }
- #endif
- if( FF_isERR( xError ) )
- {
- break;
- }
- if( xMyDirectory.ulObjectCluster == 0UL )
- {
- /* Couldn't allocate any space for the dir! */
- xError = ( FF_Error_t ) ( FF_ERR_DIR_EXTEND_FAILED | FF_MKDIR );
- break;
- }
- xError = FF_ClearCluster( pxIOManager, xMyDirectory.ulObjectCluster );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = FF_CreateDirent( pxIOManager, &xFindParams, &xMyDirectory );
- }
- if( FF_isERR( xError ) )
- {
- FF_LockFAT( pxIOManager );
- {
- FF_UnlinkClusterChain( pxIOManager, xMyDirectory.ulObjectCluster, 0 );
- }
- FF_UnlockFAT( pxIOManager );
- FF_FlushCache( pxIOManager ); /* Don't override error. */
- break;
- }
- /* Write 8.3 entry "." */
- pucEntryBuffer[ 0 ] = '.';
- /* folowed by 10 spaces: */
- memset( pucEntryBuffer + 1, ' ', 10 );
- /* Clear the rest of the structure. */
- memset( pucEntryBuffer + 11, 0, FF_SIZEOF_DIRECTORY_ENTRY - 11 );
- ulObjectCluster = xMyDirectory.ulObjectCluster;
- xError = FF_PutEntry( pxIOManager, ( uint16_t ) 0u, ulObjectCluster, &xMyDirectory, pucEntryBuffer );
- if( FF_isERR( xError ) == pdFALSE )
- {
- pucEntryBuffer[ 1 ] = '.';
- if( xFindParams.ulDirCluster == pxIOManager->xPartition.ulRootDirCluster )
- {
- xMyDirectory.ulObjectCluster = 0;
- }
- else
- {
- xMyDirectory.ulObjectCluster = xFindParams.ulDirCluster;
- }
- xError = FF_PutEntry( pxIOManager, 1u, ulObjectCluster, &xMyDirectory, pucEntryBuffer );
- xMyDirectory.ulObjectCluster = ulObjectCluster;
- }
- if( FF_isERR( xError ) )
- {
- FF_LockFAT( pxIOManager );
- {
- FF_UnlinkClusterChain( pxIOManager, xMyDirectory.ulObjectCluster, 0 );
- }
- FF_UnlockFAT( pxIOManager );
- }
- FF_FlushCache( pxIOManager );
- }
- while( pdFALSE );
- return xError;
- } /* FF_MkDir() */
- /*-----------------------------------------------------------*/
- FF_Error_t FF_RmLFNs( FF_IOManager_t * pxIOManager,
- uint16_t usDirEntry,
- FF_FetchContext_t * pxContext )
- {
- FF_Error_t xError = FF_ERR_NONE;
- uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
- if( usDirEntry != 0 )
- {
- usDirEntry--;
- do
- {
- xError = FF_FetchEntryWithContext( pxIOManager, usDirEntry, pxContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- if( FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) ) == FF_FAT_ATTR_LFN )
- {
- FF_putChar( pucEntryBuffer, ( uint16_t ) 0, ( uint8_t ) FF_FAT_DELETED );
- xError = FF_PushEntryWithContext( pxIOManager, usDirEntry, pxContext, pucEntryBuffer );
- if( FF_isERR( xError ) )
- {
- break;
- }
- }
- if( usDirEntry == 0 )
- {
- break;
- }
- usDirEntry--;
- } while( FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) ) == FF_FAT_ATTR_LFN );
- }
- return xError;
- } /* FF_RmLFNs() */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- FF_Error_t FF_HashDir( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster )
- {
- /* Find most suitable Hash Table to replace! */
- BaseType_t xIndex;
- FF_HashTable_t * pxHashCache = NULL;
- FF_FetchContext_t xFetchContext;
- const uint8_t * pucEntryBuffer = NULL;
- uint8_t ucAttrib;
- uint32_t ulHash;
- FF_Error_t xError;
- for( xIndex = 0; xIndex < ffconfigHASH_CACHE_DEPTH; xIndex++ )
- {
- if( pxIOManager->xHashCache[ xIndex ].ulNumHandles == 0 )
- {
- if( pxHashCache == NULL )
- {
- pxHashCache = &pxIOManager->xHashCache[ xIndex ];
- }
- else
- {
- if( ( pxIOManager->xHashCache[ xIndex ].ulMisses > pxHashCache->ulMisses ) )
- {
- pxHashCache = &pxIOManager->xHashCache[ xIndex ];
- }
- }
- }
- }
- if( pxHashCache != NULL )
- {
- #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
- FF_T_WCHAR pcMyShortName[ 13 ];
- #else
- char pcMyShortName[ 13 ];
- #endif
- /* Clear the hash table! */
- memset( pxHashCache, '\0', sizeof( *pxHashCache ) );
- pxHashCache->ulDirCluster = ulDirCluster;
- pxHashCache->ulMisses = 0;
- /* Hash the directory! */
- xError = FF_InitEntryFetch( pxIOManager, ulDirCluster, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- for( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ )
- {
- if( ( pucEntryBuffer == NULL ) ||
- ( pucEntryBuffer >= xFetchContext.pxBuffer->pucBuffer + ( pxIOManager->usSectorSize - FF_SIZEOF_DIRECTORY_ENTRY ) ) )
- {
- xError = FF_FetchEntryWithContext( pxIOManager, ( uint32_t ) xIndex, &xFetchContext, NULL );
- if( FF_isERR( xError ) )
- {
- break;
- }
- pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer;
- }
- else
- {
- /* Advance the pointer 32 bytes to the next directory entry. */
- pucEntryBuffer += FF_SIZEOF_DIRECTORY_ENTRY;
- }
- if( FF_isDeleted( pucEntryBuffer ) == pdFALSE )
- {
- ucAttrib = FF_getChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB );
- if( ( ( ucAttrib & FF_FAT_ATTR_LFN ) != FF_FAT_ATTR_LFN ) &&
- ( ( ucAttrib & FF_FAT_ATTR_VOLID ) != FF_FAT_ATTR_VOLID ) )
- {
- memcpy( pcMyShortName, pucEntryBuffer, 11 );
- FF_ProcessShortName( pcMyShortName );
- if( FF_isEndOfDir( pucEntryBuffer ) )
- {
- break;
- }
- /* Generate the Hash. */
- #if ( ffconfigHASH_FUNCTION == CRC16 )
- {
- ulHash = FF_GetCRC16( ( uint8_t * ) pcMyShortName, strlen( pcMyShortName ) );
- }
- #else /* ffconfigHASH_FUNCTION == CRC8 */
- {
- ulHash = FF_GetCRC8( pcMyShortName, strlen( pcMyShortName ) );
- }
- #endif
- FF_SetHash( pxHashCache, ulHash );
- }
- }
- } /* for( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ ) */
- {
- FF_Error_t xTempError;
- xTempError = FF_CleanupEntryFetch( pxIOManager, &xFetchContext );
- if( FF_isERR( xError ) == pdFALSE )
- {
- xError = xTempError;
- }
- }
- }
- } /* if( pxHashCache != NULL ) */
- else
- {
- xError = -1;
- }
- return xError;
- } /* FF_HashDir() */
- #endif /* ffconfigHASH_CACHE != 0 */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- /* FF_UnHashDir() : invalidate the hash tables of a given directory.
- * It is called when a file or sub-directory is removed or when the
- * directory itself is removed. */
- void FF_UnHashDir( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster )
- {
- FF_HashTable_t * pxHash = pxIOManager->xHashCache;
- FF_HashTable_t * pxLast = pxIOManager->xHashCache + ffconfigHASH_CACHE_DEPTH;
- for( ; pxHash < pxLast; pxHash++ )
- {
- if( pxHash->ulDirCluster == ulDirCluster )
- {
- pxHash->ulDirCluster = 0;
- break;
- }
- }
- } /* FF_UnHashDir() */
- #endif /* ffconfigHASH_CACHE */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- /**
- *
- *
- **/
- void FF_SetHash( FF_HashTable_t * pxHash,
- uint32_t ulHash )
- {
- uint32_t tblIndex = ( ulHash / 32 ) % FF_HASH_TABLE_ENTRY_COUNT;
- uint32_t tblBit = ulHash % 32;
- pxHash->ulBitTable[ tblIndex ] |= ( 0x80000000ul >> tblBit );
- } /* FF_SetHash() */
- #endif /* ffconfigHASH_CACHE */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- void FF_ClearHash( FF_HashTable_t * pxHash,
- uint32_t ulHash )
- {
- if( pxHash != NULL )
- {
- uint32_t tblIndex = ( ulHash / 32 ) % FF_HASH_TABLE_ENTRY_COUNT;
- uint32_t tblBit = ulHash % 32;
- pxHash->ulBitTable[ tblIndex ] &= ~( 0x80000000ul >> tblBit );
- }
- } /* FF_ClearHash() */
- #endif /* ffconfigHASH_CACHE */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- BaseType_t FF_isHashSet( FF_HashTable_t * pxHash,
- uint32_t ulHash )
- {
- FF_Error_t xResult;
- xResult = pdFALSE;
- if( pxHash != NULL )
- {
- uint32_t tblIndex = ( ulHash / 32 ) % FF_HASH_TABLE_ENTRY_COUNT;
- uint32_t tblBit = ulHash % 32;
- if( pxHash->ulBitTable[ tblIndex ] & ( 0x80000000ul >> tblBit ) )
- {
- xResult = pdTRUE;
- }
- }
- return xResult;
- } /* FF_isHashSet() */
- #endif /* ffconfigHASH_CACHE */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- void FF_AddDirentHash( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- uint32_t ulHash )
- {
- FF_HashTable_t * pxHash = pxIOManager->xHashCache;
- FF_HashTable_t * pxLast = pxIOManager->xHashCache + ffconfigHASH_CACHE_DEPTH;
- for( ; pxHash < pxLast; pxHash++ )
- {
- if( pxHash->ulDirCluster == ulDirCluster )
- {
- FF_SetHash( pxHash, ulHash );
- break;
- }
- }
- } /* FF_AddDirentHash() */
- #endif /* ffconfigHASH_CACHE*/
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- BaseType_t FF_CheckDirentHash( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster,
- uint32_t ulHash )
- {
- FF_HashTable_t * pxHash = pxIOManager->xHashCache;
- FF_HashTable_t * pxLast = pxIOManager->xHashCache + ffconfigHASH_CACHE_DEPTH;
- BaseType_t xResult;
- for( ; ; )
- {
- if( pxHash->ulDirCluster == ulDirCluster )
- {
- xResult = FF_isHashSet( pxHash, ulHash );
- break;
- }
- pxHash++;
- if( pxHash >= pxLast )
- {
- xResult = -1;
- break;
- }
- }
- return xResult;
- } /* FF_CheckDirentHash() */
- #endif /* ffconfigHASH_CACHE */
- /*-----------------------------------------------------------*/
- #if ( ffconfigHASH_CACHE != 0 )
- BaseType_t FF_DirHashed( FF_IOManager_t * pxIOManager,
- uint32_t ulDirCluster )
- {
- FF_HashTable_t * pxHash = pxIOManager->xHashCache;
- FF_HashTable_t * pxLast = pxIOManager->xHashCache + ffconfigHASH_CACHE_DEPTH;
- BaseType_t xResult;
- for( ; ; )
- {
- if( pxHash->ulDirCluster == ulDirCluster )
- {
- xResult = pdTRUE;
- break;
- }
- pxHash++;
- if( pxHash >= pxLast )
- {
- xResult = pdFALSE;
- break;
- }
- }
- return xResult;
- } /* FF_DirHashed() */
- #endif /* ffconfigHASH_CACHE */
- /*-----------------------------------------------------------*/
|