ff.c 158 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839
  1. /*----------------------------------------------------------------------------/
  2. / FatFs - FAT file system module R0.08a (C)ChaN, 2010
  3. /-----------------------------------------------------------------------------/
  4. / FatFs module is a generic FAT file system module for small embedded systems.
  5. / This is a free software that opened for education, research and commercial
  6. / developments under license policy of following terms.
  7. /
  8. / Copyright (C) 2010, ChaN, all right reserved.
  9. /
  10. / * The FatFs module is a free software and there is NO WARRANTY.
  11. / * No restriction on use. You can use, modify and redistribute it for
  12. / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
  13. / * Redistributions of source code must retain the above copyright notice.
  14. /
  15. /-----------------------------------------------------------------------------/
  16. / Feb 26,'06 R0.00 Prototype.
  17. /
  18. / Apr 29,'06 R0.01 First stable version.
  19. /
  20. / Jun 01,'06 R0.02 Added FAT12 support.
  21. / Removed unbuffered mode.
  22. / Fixed a problem on small (<32M) partition.
  23. / Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
  24. /
  25. / Sep 22,'06 R0.03 Added f_rename().
  26. / Changed option _FS_MINIMUM to _FS_MINIMIZE.
  27. / Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast.
  28. / Fixed f_mkdir() creates incorrect directory on FAT32.
  29. /
  30. / Feb 04,'07 R0.04 Supported multiple drive system.
  31. / Changed some interfaces for multiple drive system.
  32. / Changed f_mountdrv() to f_mount().
  33. / Added f_mkfs().
  34. / Apr 01,'07 R0.04a Supported multiple partitions on a physical drive.
  35. / Added a capability of extending file size to f_lseek().
  36. / Added minimization level 3.
  37. / Fixed an endian sensitive code in f_mkfs().
  38. / May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
  39. / Added FSInfo support.
  40. / Fixed DBCS name can result FR_INVALID_NAME.
  41. / Fixed short seek (<= csize) collapses the file object.
  42. /
  43. / Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs().
  44. / Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
  45. / Fixed f_mkdir() on FAT32 creates incorrect directory.
  46. / Feb 03,'08 R0.05a Added f_truncate() and f_utime().
  47. / Fixed off by one error at FAT sub-type determination.
  48. / Fixed btr in f_read() can be mistruncated.
  49. / Fixed cached sector is not flushed when create and close without write.
  50. /
  51. / Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets().
  52. / Improved performance of f_lseek() on moving to the same or following cluster.
  53. /
  54. / Apr 01,'09 R0.07 Merged Tiny-FatFs as a buffer configuration option. (_FS_TINY)
  55. / Added long file name support.
  56. / Added multiple code page support.
  57. / Added re-entrancy for multitask operation.
  58. / Added auto cluster size selection to f_mkfs().
  59. / Added rewind option to f_readdir().
  60. / Changed result code of critical errors.
  61. / Renamed string functions to avoid name collision.
  62. / Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg.
  63. / Added multiple sector size support.
  64. / Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error.
  65. / Fixed wrong cache control in f_lseek().
  66. / Added relative path feature.
  67. / Added f_chdir() and f_chdrive().
  68. / Added proper case conversion to extended char.
  69. / Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h.
  70. / Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
  71. / Fixed name matching error on the 13 char boundary.
  72. / Added a configuration option, _LFN_UNICODE.
  73. / Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
  74. /
  75. / May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3)
  76. / Added file lock feature. (_FS_SHARE)
  77. / Added fast seek feature. (_USE_FASTSEEK)
  78. / Changed some types on the API, XCHAR->TCHAR.
  79. / Changed fname member in the FILINFO structure on Unicode cfg.
  80. / String functions support UTF-8 encoding files on Unicode cfg.
  81. / Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
  82. / Added sector erase feature. (_USE_ERASE)
  83. / Moved file lock semaphore table from fs object to the bss.
  84. / Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
  85. / Fixed f_mkfs() creates wrong FAT32 volume.
  86. /---------------------------------------------------------------------------*/
  87. #include "ff.h" /* FatFs configurations and declarations */
  88. #include "diskio.h" /* Declarations of low level disk I/O functions */
  89. #include "config.h"
  90. #include "uart.h"
  91. /*--------------------------------------------------------------------------
  92. Module Private Definitions
  93. ---------------------------------------------------------------------------*/
  94. #if _FATFS != 8255
  95. #error Wrong include file (ff.h).
  96. #endif
  97. /* Definitions on sector size */
  98. #if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096
  99. #error Wrong sector size.
  100. #endif
  101. #if _MAX_SS != 512
  102. #define SS(fs) ((fs)->ssize) /* Multiple sector size */
  103. #else
  104. #define SS(fs) 512U /* Fixed sector size */
  105. #endif
  106. /* Reentrancy related */
  107. #if _FS_REENTRANT
  108. #if _USE_LFN == 1
  109. #error Static LFN work area must not be used in re-entrant configuration.
  110. #endif
  111. #define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; }
  112. #define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
  113. #else
  114. #define ENTER_FF(fs)
  115. #define LEAVE_FF(fs, res) return res
  116. #endif
  117. #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
  118. /* File shareing feature */
  119. #if _FS_SHARE
  120. #if _FS_READONLY
  121. #error _FS_SHARE must be 0 on read-only cfg.
  122. #endif
  123. typedef struct
  124. {
  125. FATFS *fs; /* File ID 1, volume (NULL:blank entry) */
  126. DWORD clu; /* File ID 2, directory */
  127. WORD idx; /* File ID 3, directory index */
  128. WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */
  129. } FILESEM;
  130. #endif
  131. /* Misc definitions */
  132. #define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
  133. #define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
  134. /* Character code support macros */
  135. #define IsUpper(c) (((c)>='A')&&((c)<='Z'))
  136. #define IsLower(c) (((c)>='a')&&((c)<='z'))
  137. #define IsDigit(c) (((c)>='0')&&((c)<='9'))
  138. #if _DF1S /* Code page is DBCS */
  139. #ifdef _DF2S /* Two 1st byte areas */
  140. #define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
  141. #else /* One 1st byte area */
  142. #define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
  143. #endif
  144. #ifdef _DS3S /* Three 2nd byte areas */
  145. #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
  146. #else /* Two 2nd byte areas */
  147. #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
  148. #endif
  149. #else /* Code page is SBCS */
  150. #define IsDBCS1(c) 0
  151. #define IsDBCS2(c) 0
  152. #endif /* _DF1S */
  153. /* Name status flags */
  154. #define NS 11 /* Offset of name status byte */
  155. #define NS_LOSS 0x01 /* Out of 8.3 format */
  156. #define NS_LFN 0x02 /* Force to create LFN entry */
  157. #define NS_LAST 0x04 /* Last segment */
  158. #define NS_BODY 0x08 /* Lower case flag (body) */
  159. #define NS_EXT 0x10 /* Lower case flag (ext) */
  160. #define NS_DOT 0x20 /* Dot entry */
  161. /* FAT sub-type boundaries */
  162. /* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */
  163. #define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */
  164. #define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */
  165. /* FatFs refers the members in the FAT structures as byte array instead of
  166. / structure member because there are incompatibility of the packing option
  167. / between compilers. */
  168. #define BS_jmpBoot 0
  169. #define BS_OEMName 3
  170. #define BPB_BytsPerSec 11
  171. #define BPB_SecPerClus 13
  172. #define BPB_RsvdSecCnt 14
  173. #define BPB_NumFATs 16
  174. #define BPB_RootEntCnt 17
  175. #define BPB_TotSec16 19
  176. #define BPB_Media 21
  177. #define BPB_FATSz16 22
  178. #define BPB_SecPerTrk 24
  179. #define BPB_NumHeads 26
  180. #define BPB_HiddSec 28
  181. #define BPB_TotSec32 32
  182. #define BS_DrvNum 36
  183. #define BS_BootSig 38
  184. #define BS_VolID 39
  185. #define BS_VolLab 43
  186. #define BS_FilSysType 54
  187. #define BPB_FATSz32 36
  188. #define BPB_ExtFlags 40
  189. #define BPB_FSVer 42
  190. #define BPB_RootClus 44
  191. #define BPB_FSInfo 48
  192. #define BPB_BkBootSec 50
  193. #define BS_DrvNum32 64
  194. #define BS_BootSig32 66
  195. #define BS_VolID32 67
  196. #define BS_VolLab32 71
  197. #define BS_FilSysType32 82
  198. #define FSI_LeadSig 0
  199. #define FSI_StrucSig 484
  200. #define FSI_Free_Count 488
  201. #define FSI_Nxt_Free 492
  202. #define MBR_Table 446
  203. #define BS_55AA 510
  204. #define DIR_Name 0
  205. #define DIR_Attr 11
  206. #define DIR_NTres 12
  207. #define DIR_CrtTime 14
  208. #define DIR_CrtDate 16
  209. #define DIR_FstClusHI 20
  210. #define DIR_WrtTime 22
  211. #define DIR_WrtDate 24
  212. #define DIR_FstClusLO 26
  213. #define DIR_FileSize 28
  214. #define LDIR_Ord 0
  215. #define LDIR_Attr 11
  216. #define LDIR_Type 12
  217. #define LDIR_Chksum 13
  218. #define LDIR_FstClusLO 26
  219. /*------------------------------------------------------------*/
  220. /* Work area */
  221. #if _VOLUMES
  222. static
  223. FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
  224. #else
  225. #error Number of drives must not be 0.
  226. #endif
  227. static
  228. WORD Fsid; /* File system mount ID */
  229. #if _FS_RPATH
  230. static
  231. BYTE CurrVol; /* Current drive */
  232. #endif
  233. #if _FS_SHARE
  234. static
  235. FILESEM Files[_FS_SHARE]; /* File lock semaphores */
  236. #endif
  237. #if _USE_LFN == 0 /* No LFN */
  238. #define DEF_NAMEBUF BYTE sfn[12]
  239. #define INIT_BUF(dobj) (dobj).fn = sfn
  240. #define FREE_BUF()
  241. #elif _USE_LFN == 1 /* LFN with static LFN working buffer */
  242. static WCHAR LfnBuf[_MAX_LFN + 1];
  243. #define DEF_NAMEBUF BYTE sfn[12]
  244. #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
  245. #define FREE_BUF()
  246. #elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */
  247. #define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
  248. #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
  249. #define FREE_BUF()
  250. #elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */
  251. #define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
  252. #define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
  253. if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
  254. (dobj).lfn = lfn; (dobj).fn = sfn; }
  255. #define FREE_BUF() ff_memfree(lfn)
  256. #else
  257. #error Wrong LFN configuration.
  258. #endif
  259. /*--------------------------------------------------------------------------
  260. Module Private Functions
  261. ---------------------------------------------------------------------------*/
  262. /*-----------------------------------------------------------------------*/
  263. /* String functions */
  264. /*-----------------------------------------------------------------------*/
  265. /* Copy memory to memory */
  266. static void mem_cpy ( void *dst, const void *src, UINT cnt )
  267. {
  268. BYTE *d = ( BYTE * )dst;
  269. const BYTE *s = ( const BYTE * )src;
  270. #if _WORD_ACCESS == 1
  271. while ( cnt >= sizeof( int ) )
  272. {
  273. *( int * )d = *( int * )s;
  274. d += sizeof( int ); s += sizeof( int );
  275. cnt -= sizeof( int );
  276. }
  277. #endif
  278. while ( cnt-- )
  279. {
  280. *d++ = *s++;
  281. }
  282. }
  283. /* Fill memory */
  284. static void mem_set ( void *dst, int val, UINT cnt )
  285. {
  286. BYTE *d = ( BYTE * )dst;
  287. while ( cnt-- )
  288. {
  289. *d++ = ( BYTE )val;
  290. }
  291. }
  292. /* Compare memory to memory */
  293. static int mem_cmp ( const void *dst, const void *src, UINT cnt )
  294. {
  295. const BYTE *d = ( const BYTE * )dst, *s = ( const BYTE * )src;
  296. int r = 0;
  297. while ( cnt-- && ( r = *d++ - *s++ ) == 0 ) ;
  298. return r;
  299. }
  300. /* Check if chr is contained in the string */
  301. static
  302. int chk_chr ( const char *str, int chr )
  303. {
  304. while ( *str && *str != chr )
  305. {
  306. str++;
  307. }
  308. return *str;
  309. }
  310. /*-----------------------------------------------------------------------*/
  311. /* Request/Release grant to access the volume */
  312. /*-----------------------------------------------------------------------*/
  313. #if _FS_REENTRANT
  314. static
  315. int lock_fs (
  316. FATFS *fs /* File system object */
  317. )
  318. {
  319. return ff_req_grant( fs->sobj );
  320. }
  321. static
  322. void unlock_fs (
  323. FATFS *fs, /* File system object */
  324. FRESULT res /* Result code to be returned */
  325. )
  326. {
  327. if ( res != FR_NOT_ENABLED &&
  328. res != FR_INVALID_DRIVE &&
  329. res != FR_INVALID_OBJECT &&
  330. res != FR_TIMEOUT )
  331. {
  332. ff_rel_grant( fs->sobj );
  333. }
  334. }
  335. #endif
  336. /*-----------------------------------------------------------------------*/
  337. /* File shareing control functions */
  338. /*-----------------------------------------------------------------------*/
  339. #if _FS_SHARE
  340. static
  341. FRESULT chk_lock ( /* Check if the file can be accessed */
  342. DIR *dj, /* Directory object pointing the file to be checked */
  343. int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
  344. )
  345. {
  346. UINT i, be;
  347. /* Search file semaphore table */
  348. for ( i = be = 0; i < _FS_SHARE; i++ )
  349. {
  350. if ( Files[i].fs ) /* Existing entry */
  351. {
  352. if ( Files[i].fs == dj->fs && /* Check if the file matched with an open file */
  353. Files[i].clu == dj->sclust &&
  354. Files[i].idx == dj->index )
  355. {
  356. break;
  357. }
  358. }
  359. else /* Blank entry */
  360. {
  361. be++;
  362. }
  363. }
  364. if ( i == _FS_SHARE ) /* The file is not opened */
  365. {
  366. return ( be || acc == 2 ) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */
  367. }
  368. /* The file has been opened. Reject any open against writing file and all write mode open */
  369. return ( acc || Files[i].ctr == 0x100 ) ? FR_LOCKED : FR_OK;
  370. }
  371. static
  372. int enq_lock ( /* Check if an entry is available for a new file */
  373. FATFS *fs /* File system object */
  374. )
  375. {
  376. UINT i;
  377. for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ;
  378. return ( i == _FS_SHARE ) ? 0 : 1;
  379. }
  380. static
  381. UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */
  382. DIR *dj, /* Directory object pointing the file to register or increment */
  383. int acc /* Desired access mode (0:Read, !0:Write) */
  384. )
  385. {
  386. UINT i;
  387. for ( i = 0; i < _FS_SHARE; i++ ) /* Find the file */
  388. {
  389. if ( Files[i].fs == dj->fs &&
  390. Files[i].clu == dj->sclust &&
  391. Files[i].idx == dj->index )
  392. {
  393. break;
  394. }
  395. }
  396. if ( i == _FS_SHARE ) /* Not opened. Register it as new. */
  397. {
  398. for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ;
  399. if ( i == _FS_SHARE )
  400. {
  401. return 0; /* No space to register (int err) */
  402. }
  403. Files[i].fs = dj->fs;
  404. Files[i].clu = dj->sclust;
  405. Files[i].idx = dj->index;
  406. Files[i].ctr = 0;
  407. }
  408. if ( acc && Files[i].ctr )
  409. {
  410. return 0; /* Access violation (int err) */
  411. }
  412. Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */
  413. return i + 1;
  414. }
  415. static
  416. FRESULT dec_lock ( /* Decrement file open counter */
  417. UINT i /* Semaphore index */
  418. )
  419. {
  420. WORD n;
  421. FRESULT res;
  422. if ( --i < _FS_SHARE )
  423. {
  424. n = Files[i].ctr;
  425. if ( n == 0x100 )
  426. {
  427. n = 0;
  428. }
  429. if ( n )
  430. {
  431. n--;
  432. }
  433. Files[i].ctr = n;
  434. if ( !n )
  435. {
  436. Files[i].fs = 0;
  437. }
  438. res = FR_OK;
  439. }
  440. else
  441. {
  442. res = FR_INT_ERR;
  443. }
  444. return res;
  445. }
  446. static
  447. void clear_lock ( /* Clear lock entries of the volume */
  448. FATFS *fs
  449. )
  450. {
  451. UINT i;
  452. for ( i = 0; i < _FS_SHARE; i++ )
  453. {
  454. if ( Files[i].fs == fs )
  455. {
  456. Files[i].fs = 0;
  457. }
  458. }
  459. }
  460. #endif
  461. /*-----------------------------------------------------------------------*/
  462. /* Change window offset */
  463. /*-----------------------------------------------------------------------*/
  464. static
  465. FRESULT move_window (
  466. FATFS *fs, /* File system object */
  467. DWORD sector /* Sector number to make appearance in the fs->win[] */
  468. ) /* Move to zero only writes back dirty window */
  469. {
  470. DWORD wsect;
  471. wsect = fs->winsect;
  472. if ( wsect != sector ) /* Changed current window */
  473. {
  474. #if !_FS_READONLY
  475. if ( fs->wflag ) /* Write back dirty window if needed */
  476. {
  477. if ( disk_write( fs->drv, fs->win, wsect, 1 ) != RES_OK )
  478. {
  479. return FR_DISK_ERR;
  480. }
  481. fs->wflag = 0;
  482. if ( wsect < ( fs->fatbase + fs->fsize ) ) /* In FAT area */
  483. {
  484. BYTE nf;
  485. for ( nf = fs->n_fats; nf > 1; nf-- ) /* Reflect the change to all FAT copies */
  486. {
  487. wsect += fs->fsize;
  488. disk_write( fs->drv, fs->win, wsect, 1 );
  489. }
  490. }
  491. }
  492. #endif
  493. if ( sector )
  494. {
  495. if ( disk_read( fs->drv, fs->win, sector, 1 ) != RES_OK )
  496. {
  497. return FR_DISK_ERR;
  498. }
  499. fs->winsect = sector;
  500. }
  501. }
  502. return FR_OK;
  503. }
  504. /*-----------------------------------------------------------------------*/
  505. /* Clean-up cached data */
  506. /*-----------------------------------------------------------------------*/
  507. #if !_FS_READONLY
  508. static
  509. FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */
  510. FATFS *fs /* File system object */
  511. )
  512. {
  513. FRESULT res;
  514. res = move_window( fs, 0 );
  515. if ( res == FR_OK )
  516. {
  517. /* Update FSInfo sector if needed */
  518. if ( fs->fs_type == FS_FAT32 && fs->fsi_flag )
  519. {
  520. fs->winsect = 0;
  521. mem_set( fs->win, 0, 512 );
  522. ST_WORD( fs->win + BS_55AA, 0xAA55 );
  523. ST_DWORD( fs->win + FSI_LeadSig, 0x41615252 );
  524. ST_DWORD( fs->win + FSI_StrucSig, 0x61417272 );
  525. ST_DWORD( fs->win + FSI_Free_Count, fs->free_clust );
  526. ST_DWORD( fs->win + FSI_Nxt_Free, fs->last_clust );
  527. disk_write( fs->drv, fs->win, fs->fsi_sector, 1 );
  528. fs->fsi_flag = 0;
  529. }
  530. /* Make sure that no pending write process in the physical drive */
  531. if ( disk_ioctl( fs->drv, CTRL_SYNC, ( void * )0 ) != RES_OK )
  532. {
  533. res = FR_DISK_ERR;
  534. }
  535. }
  536. return res;
  537. }
  538. #endif
  539. /*-----------------------------------------------------------------------*/
  540. /* Get sector# from cluster# */
  541. /*-----------------------------------------------------------------------*/
  542. DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
  543. FATFS *fs, /* File system object */
  544. DWORD clst /* Cluster# to be converted */
  545. )
  546. {
  547. clst -= 2;
  548. if ( clst >= ( fs->n_fatent - 2 ) )
  549. {
  550. return 0; /* Invalid cluster# */
  551. }
  552. return clst * fs->csize + fs->database;
  553. }
  554. /*-----------------------------------------------------------------------*/
  555. /* FAT access - Read value of a FAT entry */
  556. /*-----------------------------------------------------------------------*/
  557. DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */
  558. FATFS *fs, /* File system object */
  559. DWORD clst /* Cluster# to get the link information */
  560. )
  561. {
  562. UINT wc, bc;
  563. BYTE *p;
  564. if ( clst < 2 || clst >= fs->n_fatent ) /* Chack range */
  565. {
  566. return 1;
  567. }
  568. switch ( fs->fs_type )
  569. {
  570. case FS_FAT12 :
  571. bc = ( UINT )clst; bc += bc / 2;
  572. if ( move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ) )
  573. {
  574. break;
  575. }
  576. wc = fs->win[bc % SS( fs )]; bc++;
  577. if ( move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ) )
  578. {
  579. break;
  580. }
  581. wc |= fs->win[bc % SS( fs )] << 8;
  582. return ( clst & 1 ) ? ( wc >> 4 ) : ( wc & 0xFFF );
  583. case FS_FAT16 :
  584. if ( move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 2 ) ) ) )
  585. {
  586. break;
  587. }
  588. p = &fs->win[clst * 2 % SS( fs )];
  589. return LD_WORD( p );
  590. case FS_FAT32 :
  591. if ( move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 4 ) ) ) )
  592. {
  593. break;
  594. }
  595. p = &fs->win[clst * 4 % SS( fs )];
  596. return LD_DWORD( p ) & 0x0FFFFFFF;
  597. }
  598. return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */
  599. }
  600. /*-----------------------------------------------------------------------*/
  601. /* FAT access - Change value of a FAT entry */
  602. /*-----------------------------------------------------------------------*/
  603. #if !_FS_READONLY
  604. FRESULT put_fat (
  605. FATFS *fs, /* File system object */
  606. DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */
  607. DWORD val /* New value to mark the cluster */
  608. )
  609. {
  610. UINT bc;
  611. BYTE *p;
  612. FRESULT res;
  613. if ( clst < 2 || clst >= fs->n_fatent ) /* Check range */
  614. {
  615. res = FR_INT_ERR;
  616. }
  617. else
  618. {
  619. switch ( fs->fs_type )
  620. {
  621. case FS_FAT12 :
  622. bc = clst; bc += bc / 2;
  623. res = move_window( fs, fs->fatbase + ( bc / SS( fs ) ) );
  624. if ( res != FR_OK )
  625. {
  626. break;
  627. }
  628. p = &fs->win[bc % SS( fs )];
  629. *p = ( clst & 1 ) ? ( ( *p & 0x0F ) | ( ( BYTE )val << 4 ) ) : ( BYTE )val;
  630. bc++;
  631. fs->wflag = 1;
  632. res = move_window( fs, fs->fatbase + ( bc / SS( fs ) ) );
  633. if ( res != FR_OK )
  634. {
  635. break;
  636. }
  637. p = &fs->win[bc % SS( fs )];
  638. *p = ( clst & 1 ) ? ( BYTE )( val >> 4 ) : ( ( *p & 0xF0 ) | ( ( BYTE )( val >> 8 ) & 0x0F ) );
  639. break;
  640. case FS_FAT16 :
  641. res = move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 2 ) ) );
  642. if ( res != FR_OK )
  643. {
  644. break;
  645. }
  646. p = &fs->win[clst * 2 % SS( fs )];
  647. ST_WORD( p, ( WORD )val );
  648. break;
  649. case FS_FAT32 :
  650. res = move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 4 ) ) );
  651. if ( res != FR_OK )
  652. {
  653. break;
  654. }
  655. p = &fs->win[clst * 4 % SS( fs )];
  656. val |= LD_DWORD( p ) & 0xF0000000;
  657. ST_DWORD( p, val );
  658. break;
  659. default :
  660. res = FR_INT_ERR;
  661. }
  662. fs->wflag = 1;
  663. }
  664. return res;
  665. }
  666. #endif /* !_FS_READONLY */
  667. /*-----------------------------------------------------------------------*/
  668. /* FAT handling - Remove a cluster chain */
  669. /*-----------------------------------------------------------------------*/
  670. #if !_FS_READONLY
  671. static
  672. FRESULT remove_chain (
  673. FATFS *fs, /* File system object */
  674. DWORD clst /* Cluster# to remove a chain from */
  675. )
  676. {
  677. FRESULT res;
  678. DWORD nxt;
  679. #if _USE_ERASE
  680. DWORD scl = clst, ecl = clst, resion[2];
  681. #endif
  682. if ( clst < 2 || clst >= fs->n_fatent ) /* Check range */
  683. {
  684. res = FR_INT_ERR;
  685. }
  686. else
  687. {
  688. res = FR_OK;
  689. while ( clst < fs->n_fatent ) /* Not a last link? */
  690. {
  691. nxt = get_fat( fs, clst ); /* Get cluster status */
  692. if ( nxt == 0 )
  693. {
  694. break; /* Empty cluster? */
  695. }
  696. if ( nxt == 1 )
  697. {
  698. res = FR_INT_ERR; /* Internal error? */
  699. break;
  700. }
  701. if ( nxt == 0xFFFFFFFF )
  702. {
  703. res = FR_DISK_ERR; /* Disk error? */
  704. break;
  705. }
  706. res = put_fat( fs, clst, 0 ); /* Mark the cluster "empty" */
  707. if ( res != FR_OK )
  708. {
  709. break;
  710. }
  711. if ( fs->free_clust != 0xFFFFFFFF ) /* Update FSInfo */
  712. {
  713. fs->free_clust++;
  714. fs->fsi_flag = 1;
  715. }
  716. #if _USE_ERASE
  717. if ( ecl + 1 == nxt ) /* Next cluster is contiguous */
  718. {
  719. ecl = nxt;
  720. }
  721. else /* End of contiguous clusters */
  722. {
  723. resion[0] = clust2sect( fs, scl ); /* Start sector */
  724. resion[1] = clust2sect( fs, ecl ) + fs->csize - 1; /* End sector */
  725. disk_ioctl( fs->drv, CTRL_ERASE_SECTOR, resion ); /* Erase the block */
  726. scl = ecl = nxt;
  727. }
  728. #endif
  729. clst = nxt; /* Next cluster */
  730. }
  731. }
  732. return res;
  733. }
  734. #endif
  735. /*-----------------------------------------------------------------------*/
  736. /* FAT handling - Stretch or Create a cluster chain */
  737. /*-----------------------------------------------------------------------*/
  738. #if !_FS_READONLY
  739. static
  740. DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
  741. FATFS *fs, /* File system object */
  742. DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
  743. )
  744. {
  745. DWORD cs, ncl, scl;
  746. FRESULT res;
  747. if ( clst == 0 ) /* Create a new chain */
  748. {
  749. scl = fs->last_clust; /* Get suggested start point */
  750. if ( !scl || scl >= fs->n_fatent )
  751. {
  752. scl = 1;
  753. }
  754. }
  755. else /* Stretch the current chain */
  756. {
  757. cs = get_fat( fs, clst ); /* Check the cluster status */
  758. if ( cs < 2 )
  759. {
  760. return 1; /* It is an invalid cluster */
  761. }
  762. if ( cs < fs->n_fatent )
  763. {
  764. return cs; /* It is already followed by next cluster */
  765. }
  766. scl = clst;
  767. }
  768. ncl = scl; /* Start cluster */
  769. for ( ;; )
  770. {
  771. ncl++; /* Next cluster */
  772. if ( ncl >= fs->n_fatent ) /* Wrap around */
  773. {
  774. ncl = 2;
  775. if ( ncl > scl )
  776. {
  777. return 0; /* No free cluster */
  778. }
  779. }
  780. cs = get_fat( fs, ncl ); /* Get the cluster status */
  781. if ( cs == 0 )
  782. {
  783. break; /* Found a free cluster */
  784. }
  785. if ( cs == 0xFFFFFFFF || cs == 1 ) /* An error occurred */
  786. {
  787. return cs;
  788. }
  789. if ( ncl == scl )
  790. {
  791. return 0; /* No free cluster */
  792. }
  793. }
  794. res = put_fat( fs, ncl, 0x0FFFFFFF ); /* Mark the new cluster "last link" */
  795. if ( res == FR_OK && clst != 0 )
  796. {
  797. res = put_fat( fs, clst, ncl ); /* Link it to the previous one if needed */
  798. }
  799. if ( res == FR_OK )
  800. {
  801. fs->last_clust = ncl; /* Update FSINFO */
  802. if ( fs->free_clust != 0xFFFFFFFF )
  803. {
  804. fs->free_clust--;
  805. fs->fsi_flag = 1;
  806. }
  807. }
  808. else
  809. {
  810. ncl = ( res == FR_DISK_ERR ) ? 0xFFFFFFFF : 1;
  811. }
  812. return ncl; /* Return new cluster number or error code */
  813. }
  814. #endif /* !_FS_READONLY */
  815. /*-----------------------------------------------------------------------*/
  816. /* Directory handling - Set directory index */
  817. /*-----------------------------------------------------------------------*/
  818. static
  819. FRESULT dir_sdi (
  820. DIR *dj, /* Pointer to directory object */
  821. WORD idx /* Directory index number */
  822. )
  823. {
  824. DWORD clst;
  825. WORD ic;
  826. dj->index = idx;
  827. clst = dj->sclust;
  828. if ( clst == 1 || clst >= dj->fs->n_fatent ) /* Check start cluster range */
  829. {
  830. return FR_INT_ERR;
  831. }
  832. if ( !clst && dj->fs->fs_type == FS_FAT32 ) /* Replace cluster# 0 with root cluster# if in FAT32 */
  833. {
  834. clst = dj->fs->dirbase;
  835. }
  836. if ( clst == 0 ) /* Static table (root-dir in FAT12/16) */
  837. {
  838. dj->clust = clst;
  839. if ( idx >= dj->fs->n_rootdir ) /* Index is out of range */
  840. {
  841. return FR_INT_ERR;
  842. }
  843. dj->sect = dj->fs->dirbase + idx / ( SS( dj->fs ) / 32 ); /* Sector# */
  844. }
  845. else /* Dynamic table (sub-dirs or root-dir in FAT32) */
  846. {
  847. ic = SS( dj->fs ) / 32 * dj->fs->csize; /* Entries per cluster */
  848. while ( idx >= ic ) /* Follow cluster chain */
  849. {
  850. clst = get_fat( dj->fs, clst ); /* Get next cluster */
  851. if ( clst == 0xFFFFFFFF )
  852. {
  853. return FR_DISK_ERR; /* Disk error */
  854. }
  855. if ( clst < 2 || clst >= dj->fs->n_fatent ) /* Reached to end of table or int error */
  856. {
  857. return FR_INT_ERR;
  858. }
  859. idx -= ic;
  860. }
  861. dj->clust = clst;
  862. dj->sect = clust2sect( dj->fs, clst ) + idx / ( SS( dj->fs ) / 32 ); /* Sector# */
  863. }
  864. dj->dir = dj->fs->win + ( idx % ( SS( dj->fs ) / 32 ) ) * 32; /* Ptr to the entry in the sector */
  865. return FR_OK; /* Seek succeeded */
  866. }
  867. /*-----------------------------------------------------------------------*/
  868. /* Directory handling - Move directory index next */
  869. /*-----------------------------------------------------------------------*/
  870. static
  871. FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */
  872. DIR *dj, /* Pointer to directory object */
  873. int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
  874. )
  875. {
  876. DWORD clst;
  877. WORD i;
  878. i = dj->index + 1;
  879. if ( !i || !dj->sect ) /* Report EOT when index has reached 65535 */
  880. {
  881. return FR_NO_FILE;
  882. }
  883. if ( !( i % ( SS( dj->fs ) / 32 ) ) ) /* Sector changed? */
  884. {
  885. dj->sect++; /* Next sector */
  886. if ( dj->clust == 0 ) /* Static table */
  887. {
  888. if ( i >= dj->fs->n_rootdir ) /* Report EOT when end of table */
  889. {
  890. return FR_NO_FILE;
  891. }
  892. }
  893. else /* Dynamic table */
  894. {
  895. if ( ( ( i / ( SS( dj->fs ) / 32 ) ) & ( dj->fs->csize - 1 ) ) == 0 ) /* Cluster changed? */
  896. {
  897. clst = get_fat( dj->fs, dj->clust ); /* Get next cluster */
  898. if ( clst <= 1 )
  899. {
  900. return FR_INT_ERR;
  901. }
  902. if ( clst == 0xFFFFFFFF )
  903. {
  904. return FR_DISK_ERR;
  905. }
  906. if ( clst >= dj->fs->n_fatent ) /* When it reached end of dynamic table */
  907. {
  908. #if !_FS_READONLY
  909. BYTE c;
  910. if ( !stretch )
  911. {
  912. return FR_NO_FILE; /* When do not stretch, report EOT */
  913. }
  914. clst = create_chain( dj->fs, dj->clust ); /* Stretch cluster chain */
  915. if ( clst == 0 )
  916. {
  917. return FR_DENIED; /* No free cluster */
  918. }
  919. if ( clst == 1 )
  920. {
  921. return FR_INT_ERR;
  922. }
  923. if ( clst == 0xFFFFFFFF )
  924. {
  925. return FR_DISK_ERR;
  926. }
  927. /* Clean-up stretched table */
  928. if ( move_window( dj->fs, 0 ) )
  929. {
  930. return FR_DISK_ERR; /* Flush active window */
  931. }
  932. mem_set( dj->fs->win, 0, SS( dj->fs ) ); /* Clear window buffer */
  933. dj->fs->winsect = clust2sect( dj->fs, clst ); /* Cluster start sector */
  934. for ( c = 0; c < dj->fs->csize; c++ ) /* Fill the new cluster with 0 */
  935. {
  936. dj->fs->wflag = 1;
  937. if ( move_window( dj->fs, 0 ) )
  938. {
  939. return FR_DISK_ERR;
  940. }
  941. dj->fs->winsect++;
  942. }
  943. dj->fs->winsect -= c; /* Rewind window address */
  944. #else
  945. return FR_NO_FILE; /* Report EOT */
  946. #endif
  947. }
  948. dj->clust = clst; /* Initialize data for new cluster */
  949. dj->sect = clust2sect( dj->fs, clst );
  950. }
  951. }
  952. }
  953. dj->index = i;
  954. dj->dir = dj->fs->win + ( i % ( SS( dj->fs ) / 32 ) ) * 32;
  955. return FR_OK;
  956. }
  957. /*-----------------------------------------------------------------------*/
  958. /* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
  959. /*-----------------------------------------------------------------------*/
  960. #if _USE_LFN
  961. static
  962. const BYTE LfnOfs[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; /* Offset of LFN chars in the directory entry */
  963. static
  964. int cmp_lfn ( /* 1:Matched, 0:Not matched */
  965. WCHAR *lfnbuf, /* Pointer to the LFN to be compared */
  966. BYTE *dir /* Pointer to the directory entry containing a part of LFN */
  967. )
  968. {
  969. UINT i, s;
  970. WCHAR wc, uc;
  971. i = ( ( dir[LDIR_Ord] & 0xBF ) - 1 ) * 13; /* Get offset in the LFN buffer */
  972. s = 0; wc = 1;
  973. do
  974. {
  975. uc = LD_WORD( dir + LfnOfs[s] ); /* Pick an LFN character from the entry */
  976. if ( wc ) /* Last char has not been processed */
  977. {
  978. wc = ff_wtoupper( uc ); /* Convert it to upper case */
  979. if ( i >= _MAX_LFN || wc != ff_wtoupper( lfnbuf[i++] ) ) /* Compare it */
  980. {
  981. return 0; /* Not matched */
  982. }
  983. }
  984. else
  985. {
  986. if ( uc != 0xFFFF )
  987. {
  988. return 0; /* Check filler */
  989. }
  990. }
  991. }
  992. while ( ++s < 13 ); /* Repeat until all chars in the entry are checked */
  993. if ( ( dir[LDIR_Ord] & 0x40 ) && wc && lfnbuf[i] ) /* Last segment matched but different length */
  994. {
  995. return 0;
  996. }
  997. return 1; /* The part of LFN matched */
  998. }
  999. static
  1000. int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
  1001. WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */
  1002. BYTE *dir /* Pointer to the directory entry */
  1003. )
  1004. {
  1005. UINT i, s;
  1006. WCHAR wc, uc;
  1007. i = ( ( dir[LDIR_Ord] & 0x3F ) - 1 ) * 13; /* Offset in the LFN buffer */
  1008. s = 0; wc = 1;
  1009. do
  1010. {
  1011. uc = LD_WORD( dir + LfnOfs[s] ); /* Pick an LFN character from the entry */
  1012. if ( wc ) /* Last char has not been processed */
  1013. {
  1014. if ( i >= _MAX_LFN )
  1015. {
  1016. return 0; /* Buffer overflow? */
  1017. }
  1018. lfnbuf[i++] = wc = uc; /* Store it */
  1019. }
  1020. else
  1021. {
  1022. if ( uc != 0xFFFF )
  1023. {
  1024. return 0; /* Check filler */
  1025. }
  1026. }
  1027. }
  1028. while ( ++s < 13 ); /* Read all character in the entry */
  1029. if ( dir[LDIR_Ord] & 0x40 ) /* Put terminator if it is the last LFN part */
  1030. {
  1031. if ( i >= _MAX_LFN )
  1032. {
  1033. return 0; /* Buffer overflow? */
  1034. }
  1035. lfnbuf[i] = 0;
  1036. }
  1037. return 1;
  1038. }
  1039. #if !_FS_READONLY
  1040. static
  1041. void fit_lfn (
  1042. const WCHAR *lfnbuf, /* Pointer to the LFN buffer */
  1043. BYTE *dir, /* Pointer to the directory entry */
  1044. BYTE ord, /* LFN order (1-20) */
  1045. BYTE sum /* SFN sum */
  1046. )
  1047. {
  1048. UINT i, s;
  1049. WCHAR wc;
  1050. dir[LDIR_Chksum] = sum; /* Set check sum */
  1051. dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
  1052. dir[LDIR_Type] = 0;
  1053. ST_WORD( dir + LDIR_FstClusLO, 0 );
  1054. i = ( ord - 1 ) * 13; /* Get offset in the LFN buffer */
  1055. s = wc = 0;
  1056. do
  1057. {
  1058. if ( wc != 0xFFFF )
  1059. {
  1060. wc = lfnbuf[i++]; /* Get an effective char */
  1061. }
  1062. ST_WORD( dir + LfnOfs[s], wc ); /* Put it */
  1063. if ( !wc )
  1064. {
  1065. wc = 0xFFFF; /* Padding chars following last char */
  1066. }
  1067. }
  1068. while ( ++s < 13 );
  1069. if ( wc == 0xFFFF || !lfnbuf[i] )
  1070. {
  1071. ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */
  1072. }
  1073. dir[LDIR_Ord] = ord; /* Set the LFN order */
  1074. }
  1075. #endif
  1076. #endif
  1077. /*-----------------------------------------------------------------------*/
  1078. /* Create numbered name */
  1079. /*-----------------------------------------------------------------------*/
  1080. #if _USE_LFN
  1081. void gen_numname (
  1082. BYTE *dst, /* Pointer to generated SFN */
  1083. const BYTE *src, /* Pointer to source SFN to be modified */
  1084. const WCHAR *lfn, /* Pointer to LFN */
  1085. WORD seq /* Sequence number */
  1086. )
  1087. {
  1088. BYTE ns[8], c;
  1089. UINT i, j;
  1090. mem_cpy( dst, src, 11 );
  1091. if ( seq > 5 ) /* On many collisions, generate a hash number instead of sequential number */
  1092. {
  1093. do
  1094. {
  1095. seq = ( seq >> 1 ) + ( seq << 15 ) + ( WORD ) * lfn++;
  1096. }
  1097. while ( *lfn );
  1098. }
  1099. /* itoa */
  1100. i = 7;
  1101. do
  1102. {
  1103. c = ( seq % 16 ) + '0';
  1104. if ( c > '9' )
  1105. {
  1106. c += 7;
  1107. }
  1108. ns[i--] = c;
  1109. seq /= 16;
  1110. }
  1111. while ( seq );
  1112. ns[i] = '~';
  1113. /* Append the number */
  1114. for ( j = 0; j < i && dst[j] != ' '; j++ )
  1115. {
  1116. if ( IsDBCS1( dst[j] ) )
  1117. {
  1118. if ( j == i - 1 )
  1119. {
  1120. break;
  1121. }
  1122. j++;
  1123. }
  1124. }
  1125. do
  1126. {
  1127. dst[j++] = ( i < 8 ) ? ns[i++] : ' ';
  1128. }
  1129. while ( j < 8 );
  1130. }
  1131. #endif
  1132. /*-----------------------------------------------------------------------*/
  1133. /* Calculate sum of an SFN */
  1134. /*-----------------------------------------------------------------------*/
  1135. #if _USE_LFN
  1136. static
  1137. BYTE sum_sfn (
  1138. const BYTE *dir /* Ptr to directory entry */
  1139. )
  1140. {
  1141. BYTE sum = 0;
  1142. UINT n = 11;
  1143. do
  1144. {
  1145. sum = ( sum >> 1 ) + ( sum << 7 ) + *dir++;
  1146. }
  1147. while ( --n );
  1148. return sum;
  1149. }
  1150. #endif
  1151. /*-----------------------------------------------------------------------*/
  1152. /* Directory handling - Find an object in the directory */
  1153. /*-----------------------------------------------------------------------*/
  1154. static
  1155. FRESULT dir_find (
  1156. DIR *dj /* Pointer to the directory object linked to the file name */
  1157. )
  1158. {
  1159. FRESULT res;
  1160. BYTE c, *dir;
  1161. #if _USE_LFN
  1162. BYTE a, ord, sum;
  1163. #endif
  1164. res = dir_sdi( dj, 0 ); /* Rewind directory object */
  1165. if ( res != FR_OK )
  1166. {
  1167. return res;
  1168. }
  1169. #if _USE_LFN
  1170. ord = sum = 0xFF;
  1171. #endif
  1172. do
  1173. {
  1174. res = move_window( dj->fs, dj->sect );
  1175. if ( res != FR_OK )
  1176. {
  1177. break;
  1178. }
  1179. dir = dj->dir; /* Ptr to the directory entry of current index */
  1180. c = dir[DIR_Name];
  1181. if ( c == 0 )
  1182. {
  1183. res = FR_NO_FILE; /* Reached to end of table */
  1184. break;
  1185. }
  1186. #if _USE_LFN /* LFN configuration */
  1187. a = dir[DIR_Attr] & AM_MASK;
  1188. if ( c == 0xE5 || ( ( a & AM_VOL ) && a != AM_LFN ) ) /* An entry without valid data */
  1189. {
  1190. ord = 0xFF;
  1191. }
  1192. else
  1193. {
  1194. if ( a == AM_LFN ) /* An LFN entry is found */
  1195. {
  1196. if ( dj->lfn )
  1197. {
  1198. if ( c & 0x40 ) /* Is it start of LFN sequence? */
  1199. {
  1200. sum = dir[LDIR_Chksum];
  1201. c &= 0xBF; ord = c; /* LFN start order */
  1202. dj->lfn_idx = dj->index;
  1203. }
  1204. /* Check validity of the LFN entry and compare it with given name */
  1205. ord = ( c == ord && sum == dir[LDIR_Chksum] && cmp_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF;
  1206. }
  1207. }
  1208. else /* An SFN entry is found */
  1209. {
  1210. if ( !ord && sum == sum_sfn( dir ) )
  1211. {
  1212. break; /* LFN matched? */
  1213. }
  1214. ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */
  1215. if ( !( dj->fn[NS] & NS_LOSS ) && !mem_cmp( dir, dj->fn, 11 ) )
  1216. {
  1217. break; /* SFN matched? */
  1218. }
  1219. }
  1220. }
  1221. #else /* Non LFN configuration */
  1222. if ( !( dir[DIR_Attr] & AM_VOL ) && !mem_cmp( dir, dj->fn, 11 ) ) /* Is it a valid entry? */
  1223. {
  1224. break;
  1225. }
  1226. #endif
  1227. res = dir_next( dj, 0 ); /* Next entry */
  1228. }
  1229. while ( res == FR_OK );
  1230. return res;
  1231. }
  1232. /*-----------------------------------------------------------------------*/
  1233. /* Read an object from the directory */
  1234. /*-----------------------------------------------------------------------*/
  1235. #if _FS_MINIMIZE <= 1
  1236. static
  1237. FRESULT dir_read (
  1238. DIR *dj /* Pointer to the directory object that pointing the entry to be read */
  1239. )
  1240. {
  1241. FRESULT res;
  1242. BYTE c, *dir;
  1243. #if _USE_LFN
  1244. BYTE a, ord = 0xFF, sum = 0xFF;
  1245. #endif
  1246. res = FR_NO_FILE;
  1247. while ( dj->sect )
  1248. {
  1249. res = move_window( dj->fs, dj->sect );
  1250. if ( res != FR_OK )
  1251. {
  1252. break;
  1253. }
  1254. dir = dj->dir; /* Ptr to the directory entry of current index */
  1255. c = dir[DIR_Name];
  1256. if ( c == 0 )
  1257. {
  1258. res = FR_NO_FILE; /* Reached to end of table */
  1259. break;
  1260. }
  1261. #if _USE_LFN /* LFN configuration */
  1262. a = dir[DIR_Attr] & AM_MASK;
  1263. if ( c == 0xE5 || ( !_FS_RPATH && c == '.' ) || ( ( a & AM_VOL ) && a != AM_LFN ) ) /* An entry without valid data */
  1264. {
  1265. ord = 0xFF;
  1266. }
  1267. else
  1268. {
  1269. if ( a == AM_LFN ) /* An LFN entry is found */
  1270. {
  1271. if ( c & 0x40 ) /* Is it start of LFN sequence? */
  1272. {
  1273. sum = dir[LDIR_Chksum];
  1274. c &= 0xBF; ord = c;
  1275. dj->lfn_idx = dj->index;
  1276. }
  1277. /* Check LFN validity and capture it */
  1278. ord = ( c == ord && sum == dir[LDIR_Chksum] && pick_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF;
  1279. }
  1280. else /* An SFN entry is found */
  1281. {
  1282. if ( ord || sum != sum_sfn( dir ) ) /* Is there a valid LFN? */
  1283. {
  1284. dj->lfn_idx = 0xFFFF; /* It has no LFN. */
  1285. }
  1286. break;
  1287. }
  1288. }
  1289. #else /* Non LFN configuration */
  1290. if ( c != 0xE5 && ( _FS_RPATH || c != '.' ) && !( dir[DIR_Attr] & AM_VOL ) ) /* Is it a valid entry? */
  1291. {
  1292. break;
  1293. }
  1294. #endif
  1295. res = dir_next( dj, 0 ); /* Next entry */
  1296. if ( res != FR_OK )
  1297. {
  1298. break;
  1299. }
  1300. }
  1301. if ( res != FR_OK )
  1302. {
  1303. dj->sect = 0;
  1304. }
  1305. return res;
  1306. }
  1307. #endif
  1308. /*-----------------------------------------------------------------------*/
  1309. /* Register an object to the directory */
  1310. /*-----------------------------------------------------------------------*/
  1311. #if !_FS_READONLY
  1312. static
  1313. FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
  1314. DIR *dj /* Target directory with object name to be created */
  1315. )
  1316. {
  1317. FRESULT res;
  1318. BYTE c, *dir;
  1319. #if _USE_LFN /* LFN configuration */
  1320. WORD n, ne, is;
  1321. BYTE sn[12], *fn, sum;
  1322. WCHAR *lfn;
  1323. fn = dj->fn; lfn = dj->lfn;
  1324. mem_cpy( sn, fn, 12 );
  1325. if ( _FS_RPATH && ( sn[NS] & NS_DOT ) ) /* Cannot create dot entry */
  1326. {
  1327. return FR_INVALID_NAME;
  1328. }
  1329. if ( sn[NS] & NS_LOSS ) /* When LFN is out of 8.3 format, generate a numbered name */
  1330. {
  1331. fn[NS] = 0; dj->lfn = 0; /* Find only SFN */
  1332. for ( n = 1; n < 100; n++ )
  1333. {
  1334. gen_numname( fn, sn, lfn, n ); /* Generate a numbered name */
  1335. res = dir_find( dj ); /* Check if the name collides with existing SFN */
  1336. if ( res != FR_OK )
  1337. {
  1338. break;
  1339. }
  1340. }
  1341. if ( n == 100 )
  1342. {
  1343. return FR_DENIED; /* Abort if too many collisions */
  1344. }
  1345. if ( res != FR_NO_FILE )
  1346. {
  1347. return res; /* Abort if the result is other than 'not collided' */
  1348. }
  1349. fn[NS] = sn[NS]; dj->lfn = lfn;
  1350. }
  1351. if ( sn[NS] & NS_LFN ) /* When LFN is to be created, reserve an SFN + LFN entries. */
  1352. {
  1353. for ( ne = 0; lfn[ne]; ne++ ) ;
  1354. ne = ( ne + 25 ) / 13;
  1355. }
  1356. else /* Otherwise reserve only an SFN entry. */
  1357. {
  1358. ne = 1;
  1359. }
  1360. /* Reserve contiguous entries */
  1361. res = dir_sdi( dj, 0 );
  1362. if ( res != FR_OK )
  1363. {
  1364. return res;
  1365. }
  1366. n = is = 0;
  1367. do
  1368. {
  1369. res = move_window( dj->fs, dj->sect );
  1370. if ( res != FR_OK )
  1371. {
  1372. break;
  1373. }
  1374. c = *dj->dir; /* Check the entry status */
  1375. if ( c == 0xE5 || c == 0 ) /* Is it a blank entry? */
  1376. {
  1377. if ( n == 0 )
  1378. {
  1379. is = dj->index; /* First index of the contiguous entry */
  1380. }
  1381. if ( ++n == ne )
  1382. {
  1383. break; /* A contiguous entry that required count is found */
  1384. }
  1385. }
  1386. else
  1387. {
  1388. n = 0; /* Not a blank entry. Restart to search */
  1389. }
  1390. res = dir_next( dj, 1 ); /* Next entry with table stretch */
  1391. }
  1392. while ( res == FR_OK );
  1393. if ( res == FR_OK && ne > 1 ) /* Initialize LFN entry if needed */
  1394. {
  1395. res = dir_sdi( dj, is );
  1396. if ( res == FR_OK )
  1397. {
  1398. sum = sum_sfn( dj->fn ); /* Sum of the SFN tied to the LFN */
  1399. ne--;
  1400. do /* Store LFN entries in bottom first */
  1401. {
  1402. res = move_window( dj->fs, dj->sect );
  1403. if ( res != FR_OK )
  1404. {
  1405. break;
  1406. }
  1407. fit_lfn( dj->lfn, dj->dir, ( BYTE )ne, sum );
  1408. dj->fs->wflag = 1;
  1409. res = dir_next( dj, 0 ); /* Next entry */
  1410. }
  1411. while ( res == FR_OK && --ne );
  1412. }
  1413. }
  1414. #else /* Non LFN configuration */
  1415. res = dir_sdi( dj, 0 );
  1416. if ( res == FR_OK )
  1417. {
  1418. do /* Find a blank entry for the SFN */
  1419. {
  1420. res = move_window( dj->fs, dj->sect );
  1421. if ( res != FR_OK )
  1422. {
  1423. break;
  1424. }
  1425. c = *dj->dir;
  1426. if ( c == 0xE5 || c == 0 )
  1427. {
  1428. break; /* Is it a blank entry? */
  1429. }
  1430. res = dir_next( dj, 1 ); /* Next entry with table stretch */
  1431. }
  1432. while ( res == FR_OK );
  1433. }
  1434. #endif
  1435. if ( res == FR_OK ) /* Initialize the SFN entry */
  1436. {
  1437. res = move_window( dj->fs, dj->sect );
  1438. if ( res == FR_OK )
  1439. {
  1440. dir = dj->dir;
  1441. mem_set( dir, 0, 32 ); /* Clean the entry */
  1442. mem_cpy( dir, dj->fn, 11 ); /* Put SFN */
  1443. #if _USE_LFN
  1444. dir[DIR_NTres] = *( dj->fn + NS ) & ( NS_BODY | NS_EXT ); /* Put NT flag */
  1445. #endif
  1446. dj->fs->wflag = 1;
  1447. }
  1448. }
  1449. return res;
  1450. }
  1451. #endif /* !_FS_READONLY */
  1452. /*-----------------------------------------------------------------------*/
  1453. /* Remove an object from the directory */
  1454. /*-----------------------------------------------------------------------*/
  1455. #if !_FS_READONLY && !_FS_MINIMIZE
  1456. static
  1457. FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
  1458. DIR *dj /* Directory object pointing the entry to be removed */
  1459. )
  1460. {
  1461. FRESULT res;
  1462. #if _USE_LFN /* LFN configuration */
  1463. WORD i;
  1464. i = dj->index; /* SFN index */
  1465. res = dir_sdi( dj, ( WORD )( ( dj->lfn_idx == 0xFFFF ) ? i :
  1466. dj->lfn_idx ) ); /* Goto the SFN or top of the LFN entries */
  1467. if ( res == FR_OK )
  1468. {
  1469. do
  1470. {
  1471. res = move_window( dj->fs, dj->sect );
  1472. if ( res != FR_OK )
  1473. {
  1474. break;
  1475. }
  1476. *dj->dir = 0xE5; /* Mark the entry "deleted" */
  1477. dj->fs->wflag = 1;
  1478. if ( dj->index >= i )
  1479. {
  1480. break; /* When reached SFN, all entries of the object has been deleted. */
  1481. }
  1482. res = dir_next( dj, 0 ); /* Next entry */
  1483. }
  1484. while ( res == FR_OK );
  1485. if ( res == FR_NO_FILE )
  1486. {
  1487. res = FR_INT_ERR;
  1488. }
  1489. }
  1490. #else /* Non LFN configuration */
  1491. res = dir_sdi( dj, dj->index );
  1492. if ( res == FR_OK )
  1493. {
  1494. res = move_window( dj->fs, dj->sect );
  1495. if ( res == FR_OK )
  1496. {
  1497. *dj->dir = 0xE5; /* Mark the entry "deleted" */
  1498. dj->fs->wflag = 1;
  1499. }
  1500. }
  1501. #endif
  1502. return res;
  1503. }
  1504. #endif /* !_FS_READONLY */
  1505. /*-----------------------------------------------------------------------*/
  1506. /* Pick a segment and create the object name in directory form */
  1507. /*-----------------------------------------------------------------------*/
  1508. static
  1509. FRESULT create_name (
  1510. DIR *dj, /* Pointer to the directory object */
  1511. const TCHAR **path /* Pointer to pointer to the segment in the path string */
  1512. )
  1513. {
  1514. #ifdef _EXCVT
  1515. static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */
  1516. #endif
  1517. #if _USE_LFN /* LFN configuration */
  1518. BYTE b, cf;
  1519. WCHAR w, *lfn;
  1520. UINT i, ni, si, di;
  1521. const TCHAR *p;
  1522. /* Create LFN in Unicode */
  1523. si = di = 0;
  1524. p = *path;
  1525. lfn = dj->lfn;
  1526. for ( ;; )
  1527. {
  1528. w = p[si++]; /* Get a character */
  1529. if ( w < ' ' || w == '/' || w == '\\' )
  1530. {
  1531. break; /* Break on end of segment */
  1532. }
  1533. if ( di >= _MAX_LFN ) /* Reject too long name */
  1534. {
  1535. return FR_INVALID_NAME;
  1536. }
  1537. #if !_LFN_UNICODE
  1538. w &= 0xFF;
  1539. if ( IsDBCS1( w ) ) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
  1540. {
  1541. b = ( BYTE )p[si++]; /* Get 2nd byte */
  1542. if ( !IsDBCS2( b ) )
  1543. {
  1544. return FR_INVALID_NAME; /* Reject invalid sequence */
  1545. }
  1546. w = ( w << 8 ) + b; /* Create a DBC */
  1547. }
  1548. w = ff_convert( w, 1 ); /* Convert ANSI/OEM to Unicode */
  1549. if ( !w )
  1550. {
  1551. return FR_INVALID_NAME; /* Reject invalid code */
  1552. }
  1553. #endif
  1554. if ( w < 0x80 && chk_chr( "\"*:<>\?|\x7F", w ) ) /* Reject illegal chars for LFN */
  1555. {
  1556. return FR_INVALID_NAME;
  1557. }
  1558. lfn[di++] = w; /* Store the Unicode char */
  1559. }
  1560. *path = &p[si]; /* Return pointer to the next segment */
  1561. cf = ( w < ' ' ) ? NS_LAST : 0; /* Set last segment flag if end of path */
  1562. #if _FS_RPATH
  1563. if ( ( di == 1 && lfn[di - 1] == '.' ) || /* Is this a dot entry? */
  1564. ( di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.' ) )
  1565. {
  1566. lfn[di] = 0;
  1567. for ( i = 0; i < 11; i++ )
  1568. {
  1569. dj->fn[i] = ( i < di ) ? '.' : ' ';
  1570. }
  1571. dj->fn[i] = cf | NS_DOT; /* This is a dot entry */
  1572. return FR_OK;
  1573. }
  1574. #endif
  1575. while ( di ) /* Strip trailing spaces and dots */
  1576. {
  1577. w = lfn[di - 1];
  1578. if ( w != ' ' && w != '.' )
  1579. {
  1580. break;
  1581. }
  1582. di--;
  1583. }
  1584. if ( !di )
  1585. {
  1586. return FR_INVALID_NAME; /* Reject nul string */
  1587. }
  1588. lfn[di] = 0; /* LFN is created */
  1589. /* Create SFN in directory form */
  1590. mem_set( dj->fn, ' ', 11 );
  1591. for ( si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++ ) ; /* Strip leading spaces and dots */
  1592. if ( si )
  1593. {
  1594. cf |= NS_LOSS | NS_LFN;
  1595. }
  1596. while ( di && lfn[di - 1] != '.' )
  1597. {
  1598. di--; /* Find extension (di<=si: no extension) */
  1599. }
  1600. b = i = 0; ni = 8;
  1601. for ( ;; )
  1602. {
  1603. w = lfn[si++]; /* Get an LFN char */
  1604. if ( !w )
  1605. {
  1606. break; /* Break on end of the LFN */
  1607. }
  1608. if ( w == ' ' || ( w == '.' && si != di ) ) /* Remove spaces and dots */
  1609. {
  1610. cf |= NS_LOSS | NS_LFN; continue;
  1611. }
  1612. if ( i >= ni || si == di ) /* Extension or end of SFN */
  1613. {
  1614. if ( ni == 11 ) /* Long extension */
  1615. {
  1616. cf |= NS_LOSS | NS_LFN; break;
  1617. }
  1618. if ( si != di )
  1619. {
  1620. cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */
  1621. }
  1622. if ( si > di )
  1623. {
  1624. break; /* No extension */
  1625. }
  1626. si = di; i = 8; ni = 11; /* Enter extension section */
  1627. b <<= 2; continue;
  1628. }
  1629. if ( w >= 0x80 ) /* Non ASCII char */
  1630. {
  1631. #ifdef _EXCVT
  1632. w = ff_convert( w, 0 ); /* Unicode -> OEM code */
  1633. if ( w )
  1634. {
  1635. w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */
  1636. }
  1637. #else
  1638. w = ff_convert( ff_wtoupper( w ), 0 ); /* Upper converted Unicode -> OEM code */
  1639. #endif
  1640. cf |= NS_LFN; /* Force create LFN entry */
  1641. }
  1642. if ( _DF1S && w >= 0x100 ) /* Double byte char (always false on SBCS cfg) */
  1643. {
  1644. if ( i >= ni - 1 )
  1645. {
  1646. cf |= NS_LOSS | NS_LFN; i = ni; continue;
  1647. }
  1648. dj->fn[i++] = ( BYTE )( w >> 8 );
  1649. }
  1650. else /* Single byte char */
  1651. {
  1652. if ( !w || chk_chr( "+,;=[]", w ) ) /* Replace illegal chars for SFN */
  1653. {
  1654. w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
  1655. }
  1656. else
  1657. {
  1658. if ( IsUpper( w ) ) /* ASCII large capital */
  1659. {
  1660. b |= 2;
  1661. }
  1662. else
  1663. {
  1664. if ( IsLower( w ) ) /* ASCII small capital */
  1665. {
  1666. b |= 1; w -= 0x20;
  1667. }
  1668. }
  1669. }
  1670. }
  1671. dj->fn[i++] = ( BYTE )w;
  1672. }
  1673. if ( dj->fn[0] == 0xE5 )
  1674. {
  1675. dj->fn[0] = 0x05; /* If the first char collides with deleted mark, replace it with 0x05 */
  1676. }
  1677. if ( ni == 8 )
  1678. {
  1679. b <<= 2;
  1680. }
  1681. if ( ( b & 0x0C ) == 0x0C || ( b & 0x03 ) == 0x03 ) /* Create LFN entry when there are composite capitals */
  1682. {
  1683. cf |= NS_LFN;
  1684. }
  1685. if ( !( cf & NS_LFN ) ) /* When LFN is in 8.3 format without extended char, NT flags are created */
  1686. {
  1687. if ( ( b & 0x03 ) == 0x01 )
  1688. {
  1689. cf |= NS_EXT; /* NT flag (Extension has only small capital) */
  1690. }
  1691. if ( ( b & 0x0C ) == 0x04 )
  1692. {
  1693. cf |= NS_BODY; /* NT flag (Filename has only small capital) */
  1694. }
  1695. }
  1696. dj->fn[NS] = cf; /* SFN is created */
  1697. return FR_OK;
  1698. #else /* Non-LFN configuration */
  1699. BYTE b, c, d, *sfn;
  1700. UINT ni, si, i;
  1701. const char *p;
  1702. /* Create file name in directory form */
  1703. sfn = dj->fn;
  1704. mem_set( sfn, ' ', 11 );
  1705. si = i = b = 0; ni = 8;
  1706. p = *path;
  1707. #if _FS_RPATH
  1708. if ( p[si] == '.' ) /* Is this a dot entry? */
  1709. {
  1710. for ( ;; )
  1711. {
  1712. c = ( BYTE )p[si++];
  1713. if ( c != '.' || si >= 3 )
  1714. {
  1715. break;
  1716. }
  1717. sfn[i++] = c;
  1718. }
  1719. if ( c != '/' && c != '\\' && c > ' ' )
  1720. {
  1721. return FR_INVALID_NAME;
  1722. }
  1723. *path = &p[si]; /* Return pointer to the next segment */
  1724. sfn[NS] = ( c <= ' ' ) ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */
  1725. return FR_OK;
  1726. }
  1727. #endif
  1728. for ( ;; )
  1729. {
  1730. c = ( BYTE )p[si++];
  1731. if ( c <= ' ' || c == '/' || c == '\\' )
  1732. {
  1733. break; /* Break on end of segment */
  1734. }
  1735. if ( c == '.' || i >= ni )
  1736. {
  1737. if ( ni != 8 || c != '.' )
  1738. {
  1739. return FR_INVALID_NAME;
  1740. }
  1741. i = 8; ni = 11;
  1742. b <<= 2; continue;
  1743. }
  1744. if ( c >= 0x80 ) /* Extended char? */
  1745. {
  1746. b |= 3; /* Eliminate NT flag */
  1747. #ifdef _EXCVT
  1748. c = excvt[c - 0x80]; /* Upper conversion (SBCS) */
  1749. #else
  1750. #if !_DF1S /* ASCII only cfg */
  1751. return FR_INVALID_NAME;
  1752. #endif
  1753. #endif
  1754. }
  1755. if ( IsDBCS1( c ) ) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
  1756. {
  1757. d = ( BYTE )p[si++]; /* Get 2nd byte */
  1758. if ( !IsDBCS2( d ) || i >= ni - 1 ) /* Reject invalid DBC */
  1759. {
  1760. return FR_INVALID_NAME;
  1761. }
  1762. sfn[i++] = c;
  1763. sfn[i++] = d;
  1764. }
  1765. else /* Single byte code */
  1766. {
  1767. if ( chk_chr( "\"*+,:;<=>\?[]|\x7F", c ) ) /* Reject illegal chrs for SFN */
  1768. {
  1769. return FR_INVALID_NAME;
  1770. }
  1771. if ( IsUpper( c ) ) /* ASCII large capital? */
  1772. {
  1773. b |= 2;
  1774. }
  1775. else
  1776. {
  1777. if ( IsLower( c ) ) /* ASCII small capital? */
  1778. {
  1779. b |= 1; c -= 0x20;
  1780. }
  1781. }
  1782. sfn[i++] = c;
  1783. }
  1784. }
  1785. *path = &p[si]; /* Return pointer to the next segment */
  1786. c = ( c <= ' ' ) ? NS_LAST : 0; /* Set last segment flag if end of path */
  1787. if ( !i )
  1788. {
  1789. return FR_INVALID_NAME; /* Reject nul string */
  1790. }
  1791. if ( sfn[0] == 0xE5 )
  1792. {
  1793. sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */
  1794. }
  1795. if ( ni == 8 )
  1796. {
  1797. b <<= 2;
  1798. }
  1799. if ( ( b & 0x03 ) == 0x01 )
  1800. {
  1801. c |= NS_EXT; /* NT flag (Name extension has only small capital) */
  1802. }
  1803. if ( ( b & 0x0C ) == 0x04 )
  1804. {
  1805. c |= NS_BODY; /* NT flag (Name body has only small capital) */
  1806. }
  1807. sfn[NS] = c; /* Store NT flag, File name is created */
  1808. return FR_OK;
  1809. #endif
  1810. }
  1811. /*-----------------------------------------------------------------------*/
  1812. /* Get file information from directory entry */
  1813. /*-----------------------------------------------------------------------*/
  1814. #if _FS_MINIMIZE <= 1
  1815. static
  1816. void get_fileinfo ( /* No return code */
  1817. DIR *dj, /* Pointer to the directory object */
  1818. FILINFO *fno /* Pointer to the file information to be filled */
  1819. )
  1820. {
  1821. UINT i;
  1822. BYTE nt, *dir;
  1823. TCHAR *p, c;
  1824. p = fno->fname;
  1825. if ( dj->sect )
  1826. {
  1827. dir = dj->dir;
  1828. nt = dir[DIR_NTres]; /* NT flag */
  1829. for ( i = 0; i < 8; i++ ) /* Copy name body */
  1830. {
  1831. c = dir[i];
  1832. if ( c == ' ' )
  1833. {
  1834. break;
  1835. }
  1836. if ( c == 0x05 )
  1837. {
  1838. c = ( TCHAR )0xE5;
  1839. }
  1840. if ( _USE_LFN && ( nt & NS_BODY ) && IsUpper( c ) )
  1841. {
  1842. c += 0x20;
  1843. }
  1844. #if _LFN_UNICODE
  1845. if ( IsDBCS1( c ) && i < 7 && IsDBCS2( dir[i + 1] ) )
  1846. {
  1847. c = ( c << 8 ) | dir[++i];
  1848. }
  1849. c = ff_convert( c, 1 );
  1850. if ( !c )
  1851. {
  1852. c = '?';
  1853. }
  1854. #endif
  1855. *p++ = c;
  1856. }
  1857. if ( dir[8] != ' ' ) /* Copy name extension */
  1858. {
  1859. *p++ = '.';
  1860. for ( i = 8; i < 11; i++ )
  1861. {
  1862. c = dir[i];
  1863. if ( c == ' ' )
  1864. {
  1865. break;
  1866. }
  1867. if ( _USE_LFN && ( nt & NS_EXT ) && IsUpper( c ) )
  1868. {
  1869. c += 0x20;
  1870. }
  1871. #if _LFN_UNICODE
  1872. if ( IsDBCS1( c ) && i < 10 && IsDBCS2( dir[i + 1] ) )
  1873. {
  1874. c = ( c << 8 ) | dir[++i];
  1875. }
  1876. c = ff_convert( c, 1 );
  1877. if ( !c )
  1878. {
  1879. c = '?';
  1880. }
  1881. #endif
  1882. *p++ = c;
  1883. }
  1884. }
  1885. fno->fattrib = dir[DIR_Attr]; /* Attribute */
  1886. fno->fsize = LD_DWORD( dir + DIR_FileSize ); /* Size */
  1887. fno->fdate = LD_WORD( dir + DIR_WrtDate ); /* Date */
  1888. fno->ftime = LD_WORD( dir + DIR_WrtTime ); /* Time */
  1889. fno->clust = ( ( DWORD )LD_WORD( dir + DIR_FstClusHI ) << 16 )
  1890. | LD_WORD( dir + DIR_FstClusLO );
  1891. }
  1892. *p = 0; /* Terminate SFN str by a \0 */
  1893. #if _USE_LFN
  1894. if ( fno->lfname && fno->lfsize )
  1895. {
  1896. TCHAR *tp = fno->lfname;
  1897. WCHAR w, *lfn;
  1898. i = 0;
  1899. if ( dj->sect && dj->lfn_idx != 0xFFFF ) /* Get LFN if available */
  1900. {
  1901. lfn = dj->lfn;
  1902. while ( ( w = *lfn++ ) != 0 ) /* Get an LFN char */
  1903. {
  1904. #if !_LFN_UNICODE
  1905. w = ff_convert( w, 0 ); /* Unicode -> OEM conversion */
  1906. if ( !w )
  1907. {
  1908. i = 0; /* Could not convert, no LFN */
  1909. break;
  1910. }
  1911. if ( _DF1S && w >= 0x100 ) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */
  1912. {
  1913. tp[i++] = ( TCHAR )( w >> 8 );
  1914. }
  1915. #endif
  1916. if ( i >= fno->lfsize - 1 )
  1917. {
  1918. i = 0; /* Buffer overflow, no LFN */
  1919. break;
  1920. }
  1921. tp[i++] = ( TCHAR )w;
  1922. }
  1923. }
  1924. tp[i] = 0; /* Terminate the LFN str by a \0 */
  1925. }
  1926. #endif
  1927. }
  1928. #endif /* _FS_MINIMIZE <= 1 */
  1929. /*-----------------------------------------------------------------------*/
  1930. /* Follow a file path */
  1931. /*-----------------------------------------------------------------------*/
  1932. static
  1933. FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
  1934. DIR *dj, /* Directory object to return last directory and found object */
  1935. const TCHAR *path /* Full-path string to find a file or directory */
  1936. )
  1937. {
  1938. FRESULT res;
  1939. BYTE *dir, ns;
  1940. #if _FS_RPATH
  1941. if ( *path == '/' || *path == '\\' ) /* There is a heading separator */
  1942. {
  1943. path++; dj->sclust = 0; /* Strip it and start from the root dir */
  1944. }
  1945. else /* No heading separator */
  1946. {
  1947. dj->sclust = dj->fs->cdir; /* Start from the current dir */
  1948. }
  1949. #else
  1950. if ( *path == '/' || *path == '\\' ) /* Strip heading separator if exist */
  1951. {
  1952. path++;
  1953. }
  1954. dj->sclust = 0; /* Start from the root dir */
  1955. #endif
  1956. if ( ( UINT )*path < ' ' ) /* Nul path means the start directory itself */
  1957. {
  1958. res = dir_sdi( dj, 0 );
  1959. dj->dir = 0;
  1960. }
  1961. else /* Follow path */
  1962. {
  1963. for ( ;; )
  1964. {
  1965. res = create_name( dj, &path ); /* Get a segment */
  1966. if ( res != FR_OK )
  1967. {
  1968. break;
  1969. }
  1970. res = dir_find( dj ); /* Find it */
  1971. ns = *( dj->fn + NS );
  1972. if ( res != FR_OK ) /* Failed to find the object */
  1973. {
  1974. if ( res != FR_NO_FILE )
  1975. {
  1976. break; /* Abort if any hard error occured */
  1977. }
  1978. /* Object not found */
  1979. if ( _FS_RPATH && ( ns & NS_DOT ) ) /* If dot entry is not exit */
  1980. {
  1981. dj->sclust = 0; dj->dir = 0; /* It is the root dir */
  1982. res = FR_OK;
  1983. if ( !( ns & NS_LAST ) )
  1984. {
  1985. continue;
  1986. }
  1987. }
  1988. else /* Could not find the object */
  1989. {
  1990. if ( !( ns & NS_LAST ) )
  1991. {
  1992. res = FR_NO_PATH;
  1993. }
  1994. }
  1995. break;
  1996. }
  1997. if ( ns & NS_LAST )
  1998. {
  1999. break; /* Last segment match. Function completed. */
  2000. }
  2001. dir = dj->dir; /* There is next segment. Follow the sub directory */
  2002. if ( !( dir[DIR_Attr] & AM_DIR ) ) /* Cannot follow because it is a file */
  2003. {
  2004. res = FR_NO_PATH; break;
  2005. }
  2006. dj->sclust = LD_CLUST( dir );
  2007. }
  2008. }
  2009. return res;
  2010. }
  2011. /*-----------------------------------------------------------------------*/
  2012. /* Load boot record and check if it is an FAT boot record */
  2013. /*-----------------------------------------------------------------------*/
  2014. static
  2015. BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
  2016. FATFS *fs, /* File system object */
  2017. DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
  2018. )
  2019. {
  2020. if ( disk_read( fs->drv, fs->win, sect, 1 ) != RES_OK ) /* Load boot record */
  2021. {
  2022. return 3;
  2023. }
  2024. if ( LD_WORD( &fs->win[BS_55AA] ) !=
  2025. 0xAA55 ) /* Check record signature (always placed at offset 510 even if the sector size is >512) */
  2026. {
  2027. return 2;
  2028. }
  2029. if ( ( LD_DWORD( &fs->win[BS_FilSysType] ) & 0xFFFFFF ) == 0x544146 ) /* Check "FAT" string */
  2030. {
  2031. return 0;
  2032. }
  2033. if ( ( LD_DWORD( &fs->win[BS_FilSysType32] ) & 0xFFFFFF ) == 0x544146 )
  2034. {
  2035. return 0;
  2036. }
  2037. return 1;
  2038. }
  2039. /*-----------------------------------------------------------------------*/
  2040. /* Check if the file system object is valid or not */
  2041. /*-----------------------------------------------------------------------*/
  2042. static
  2043. FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
  2044. const TCHAR **path, /* Pointer to pointer to the path name (drive number) */
  2045. FATFS **rfs, /* Pointer to pointer to the found file system object */
  2046. BYTE chk_wp /* !=0: Check media write protection for write access */
  2047. )
  2048. {
  2049. BYTE fmt, b, *tbl;
  2050. UINT vol;
  2051. DSTATUS stat;
  2052. DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
  2053. WORD nrsv;
  2054. const TCHAR *p = *path;
  2055. FATFS *fs;
  2056. /* Get logical drive number from the path name */
  2057. vol = p[0] - '0'; /* Is there a drive number? */
  2058. if ( vol <= 9 && p[1] == ':' ) /* Found a drive number, get and strip it */
  2059. {
  2060. p += 2; *path = p; /* Return pointer to the path name */
  2061. }
  2062. else /* No drive number is given */
  2063. {
  2064. #if _FS_RPATH
  2065. vol = CurrVol; /* Use current drive */
  2066. #else
  2067. vol = 0; /* Use drive 0 */
  2068. #endif
  2069. }
  2070. /* Check if the logical drive is valid or not */
  2071. if ( vol >= _VOLUMES ) /* Is the drive number valid? */
  2072. {
  2073. return FR_INVALID_DRIVE;
  2074. }
  2075. *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */
  2076. if ( !fs )
  2077. {
  2078. return FR_NOT_ENABLED; /* Is the file system object available? */
  2079. }
  2080. ENTER_FF( fs ); /* Lock file system */
  2081. if ( fs->fs_type ) /* If the logical drive has been mounted */
  2082. {
  2083. stat = disk_status( fs->drv );
  2084. if ( !( stat & STA_NOINIT ) ) /* and the physical drive is kept initialized (has not been changed), */
  2085. {
  2086. #if !_FS_READONLY
  2087. if ( chk_wp && ( stat & STA_PROTECT ) ) /* Check write protection if needed */
  2088. {
  2089. return FR_WRITE_PROTECTED;
  2090. }
  2091. #endif
  2092. return FR_OK; /* The file system object is valid */
  2093. }
  2094. }
  2095. /* The logical drive must be mounted. */
  2096. /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */
  2097. fs->fs_type = 0; /* Clear the file system object */
  2098. fs->drv = ( BYTE )LD2PD( vol ); /* Bind the logical drive and a physical drive */
  2099. stat = disk_initialize( fs->drv ); /* Initialize low level disk I/O layer */
  2100. if ( stat & STA_NOINIT ) /* Check if the initialization succeeded */
  2101. {
  2102. return FR_NOT_READY; /* Failed to initialize due to no media or hard error */
  2103. }
  2104. #if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */
  2105. if ( disk_ioctl( fs->drv, GET_SECTOR_SIZE, &fs->ssize ) != RES_OK )
  2106. {
  2107. return FR_DISK_ERR;
  2108. }
  2109. #endif
  2110. #if !_FS_READONLY
  2111. if ( chk_wp && ( stat & STA_PROTECT ) ) /* Check disk write protection if needed */
  2112. {
  2113. return FR_WRITE_PROTECTED;
  2114. }
  2115. #endif
  2116. /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */
  2117. fmt = check_fs( fs, bsect = 0 ); /* Check sector 0 if it is a VBR */
  2118. if ( fmt == 1 ) /* Not an FAT-VBR, the disk may be partitioned */
  2119. {
  2120. /* Check the partition listed in top of the partition table */
  2121. tbl = &fs->win[MBR_Table + LD2PT( vol ) * 16]; /* Partition table */
  2122. if ( tbl[4] ) /* Is the partition existing? */
  2123. {
  2124. bsect = LD_DWORD( &tbl[8] ); /* Partition offset in LBA */
  2125. fmt = check_fs( fs, bsect ); /* Check the partition */
  2126. }
  2127. }
  2128. if ( fmt == 3 )
  2129. {
  2130. return FR_DISK_ERR;
  2131. }
  2132. if ( fmt )
  2133. {
  2134. return FR_NO_FILESYSTEM; /* No FAT volume is found */
  2135. }
  2136. /* Following code initializes the file system object */
  2137. if ( LD_WORD( fs->win + BPB_BytsPerSec ) != SS( fs ) ) /* (BPB_BytsPerSec must be equal to the physical sector size) */
  2138. {
  2139. return FR_NO_FILESYSTEM;
  2140. }
  2141. fasize = LD_WORD( fs->win + BPB_FATSz16 ); /* Number of sectors per FAT */
  2142. if ( !fasize )
  2143. {
  2144. fasize = LD_DWORD( fs->win + BPB_FATSz32 );
  2145. }
  2146. fs->fsize = fasize;
  2147. fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */
  2148. if ( b != 1 && b != 2 )
  2149. {
  2150. return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
  2151. }
  2152. fasize *= b; /* Number of sectors for FAT area */
  2153. fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
  2154. if ( !b || ( b & ( b - 1 ) ) )
  2155. {
  2156. return FR_NO_FILESYSTEM; /* (Must be power of 2) */
  2157. }
  2158. fs->n_rootdir = LD_WORD( fs->win + BPB_RootEntCnt ); /* Number of root directory entries */
  2159. if ( fs->n_rootdir % ( SS( fs ) / 32 ) )
  2160. {
  2161. return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */
  2162. }
  2163. tsect = LD_WORD( fs->win + BPB_TotSec16 ); /* Number of sectors on the volume */
  2164. if ( !tsect )
  2165. {
  2166. tsect = LD_DWORD( fs->win + BPB_TotSec32 );
  2167. }
  2168. nrsv = LD_WORD( fs->win + BPB_RsvdSecCnt ); /* Number of reserved sectors */
  2169. if ( !nrsv )
  2170. {
  2171. return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */
  2172. }
  2173. /* Determine the FAT sub type */
  2174. sysect = nrsv + fasize + fs->n_rootdir / ( SS( fs ) / 32 ); /* RSV+FAT+DIR */
  2175. if ( tsect < sysect )
  2176. {
  2177. return FR_NO_FILESYSTEM; /* (Invalid volume size) */
  2178. }
  2179. nclst = ( tsect - sysect ) / fs->csize; /* Number of clusters */
  2180. if ( !nclst )
  2181. {
  2182. return FR_NO_FILESYSTEM; /* (Invalid volume size) */
  2183. }
  2184. fmt = FS_FAT12;
  2185. if ( nclst >= MIN_FAT16 )
  2186. {
  2187. fmt = FS_FAT16;
  2188. }
  2189. if ( nclst >= MIN_FAT32 )
  2190. {
  2191. fmt = FS_FAT32;
  2192. }
  2193. /* Boundaries and Limits */
  2194. fs->n_fatent = nclst + 2; /* Number of FAT entries */
  2195. fs->database = bsect + sysect; /* Data start sector */
  2196. fs->fatbase = bsect + nrsv; /* FAT start sector */
  2197. if ( fmt == FS_FAT32 )
  2198. {
  2199. if ( fs->n_rootdir )
  2200. {
  2201. return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
  2202. }
  2203. fs->dirbase = LD_DWORD( fs->win + BPB_RootClus ); /* Root directory start cluster */
  2204. szbfat = fs->n_fatent * 4; /* (Required FAT size) */
  2205. }
  2206. else
  2207. {
  2208. if ( !fs->n_rootdir )
  2209. {
  2210. return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
  2211. }
  2212. fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
  2213. szbfat = ( fmt == FS_FAT16 ) ? /* (Required FAT size) */
  2214. fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + ( fs->n_fatent & 1 );
  2215. }
  2216. if ( fs->fsize < ( szbfat + ( SS( fs ) - 1 ) ) / SS( fs ) ) /* (FAT size must not be less than FAT sectors */
  2217. {
  2218. return FR_NO_FILESYSTEM;
  2219. }
  2220. #if !_FS_READONLY
  2221. /* Initialize cluster allocation information */
  2222. fs->free_clust = 0xFFFFFFFF;
  2223. fs->last_clust = 0;
  2224. /* Get fsinfo if available */
  2225. if ( fmt == FS_FAT32 )
  2226. {
  2227. fs->fsi_flag = 0;
  2228. fs->fsi_sector = bsect + LD_WORD( fs->win + BPB_FSInfo );
  2229. if ( disk_read( fs->drv, fs->win, fs->fsi_sector, 1 ) == RES_OK &&
  2230. LD_WORD( fs->win + BS_55AA ) == 0xAA55 &&
  2231. LD_DWORD( fs->win + FSI_LeadSig ) == 0x41615252 &&
  2232. LD_DWORD( fs->win + FSI_StrucSig ) == 0x61417272 )
  2233. {
  2234. fs->last_clust = LD_DWORD( fs->win + FSI_Nxt_Free );
  2235. fs->free_clust = LD_DWORD( fs->win + FSI_Free_Count );
  2236. }
  2237. }
  2238. #endif
  2239. fs->fs_type = fmt; /* FAT sub-type */
  2240. fs->id = ++Fsid; /* File system mount ID */
  2241. fs->winsect = 0; /* Invalidate sector cache */
  2242. fs->wflag = 0;
  2243. #if _FS_RPATH
  2244. fs->cdir = 0; /* Current directory (root dir) */
  2245. #endif
  2246. #if _FS_SHARE /* Clear file lock semaphores */
  2247. clear_lock( fs );
  2248. #endif
  2249. return FR_OK;
  2250. }
  2251. /*-----------------------------------------------------------------------*/
  2252. /* Check if the file/dir object is valid or not */
  2253. /*-----------------------------------------------------------------------*/
  2254. static
  2255. FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
  2256. FATFS *fs, /* Pointer to the file system object */
  2257. WORD id /* Member id of the target object to be checked */
  2258. )
  2259. {
  2260. // printf("fs=%p fs->fs_type=%d fs->id=%d id=%d\n", fs, fs->fs_type, fs->id, id);
  2261. if ( !fs || !fs->fs_type || fs->id != id )
  2262. {
  2263. return FR_INVALID_OBJECT;
  2264. }
  2265. ENTER_FF( fs ); /* Lock file system */
  2266. if ( disk_status( fs->drv ) & STA_NOINIT )
  2267. {
  2268. return FR_NOT_READY;
  2269. }
  2270. return FR_OK;
  2271. }
  2272. /*--------------------------------------------------------------------------
  2273. Public Functions
  2274. --------------------------------------------------------------------------*/
  2275. /*-----------------------------------------------------------------------*/
  2276. /* Mount/Unmount a Logical Drive */
  2277. /*-----------------------------------------------------------------------*/
  2278. FRESULT f_mount (
  2279. BYTE vol, /* Logical drive number to be mounted/unmounted */
  2280. FATFS *fs /* Pointer to new file system object (NULL for unmount)*/
  2281. )
  2282. {
  2283. FATFS *rfs;
  2284. if ( vol >= _VOLUMES ) /* Check if the drive number is valid */
  2285. {
  2286. return FR_INVALID_DRIVE;
  2287. }
  2288. rfs = FatFs[vol]; /* Get current fs object */
  2289. if ( rfs )
  2290. {
  2291. #if _FS_SHARE
  2292. clear_lock( rfs );
  2293. #endif
  2294. #if _FS_REENTRANT /* Discard sync object of the current volume */
  2295. if ( !ff_del_syncobj( rfs->sobj ) )
  2296. {
  2297. return FR_INT_ERR;
  2298. }
  2299. #endif
  2300. rfs->fs_type = 0; /* Clear old fs object */
  2301. }
  2302. if ( fs )
  2303. {
  2304. fs->fs_type = 0; /* Clear new fs object */
  2305. #if _FS_REENTRANT /* Create sync object for the new volume */
  2306. if ( !ff_cre_syncobj( vol, &fs->sobj ) )
  2307. {
  2308. return FR_INT_ERR;
  2309. }
  2310. #endif
  2311. }
  2312. FatFs[vol] = fs; /* Register new fs object */
  2313. return FR_OK;
  2314. }
  2315. /*-----------------------------------------------------------------------*/
  2316. /* Open or Create a File */
  2317. /*-----------------------------------------------------------------------*/
  2318. FRESULT f_open (
  2319. FIL *fp, /* Pointer to the blank file object */
  2320. const TCHAR *path, /* Pointer to the file name */
  2321. BYTE mode /* Access mode and file open mode flags */
  2322. )
  2323. {
  2324. FRESULT res;
  2325. DIR dj;
  2326. BYTE *dir;
  2327. DEF_NAMEBUF;
  2328. fp->fs = 0; /* Clear file object */
  2329. #if !_FS_READONLY
  2330. mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
  2331. res = chk_mounted( &path, &dj.fs, ( BYTE )( mode & ~FA_READ ) );
  2332. #else
  2333. mode &= FA_READ;
  2334. res = chk_mounted( &path, &dj.fs, 0 );
  2335. #endif
  2336. INIT_BUF( dj );
  2337. if ( res == FR_OK )
  2338. {
  2339. res = follow_path( &dj, path ); /* Follow the file path */
  2340. }
  2341. dir = dj.dir;
  2342. #if !_FS_READONLY /* R/W configuration */
  2343. if ( res == FR_OK )
  2344. {
  2345. if ( !dir ) /* Current dir itself */
  2346. {
  2347. res = FR_INVALID_NAME;
  2348. }
  2349. #if _FS_SHARE
  2350. else
  2351. {
  2352. res = chk_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 );
  2353. }
  2354. #endif
  2355. }
  2356. /* Create or Open a file */
  2357. if ( mode & ( FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW ) )
  2358. {
  2359. DWORD dw, cl;
  2360. if ( res != FR_OK ) /* No file, create new */
  2361. {
  2362. if ( res == FR_NO_FILE ) /* There is no file to open, create a new entry */
  2363. #if _FS_SHARE
  2364. res = enq_lock( dj.fs ) ? dir_register( &dj ) : FR_TOO_MANY_OPEN_FILES;
  2365. #else
  2366. res = dir_register( &dj );
  2367. #endif
  2368. mode |= FA_CREATE_ALWAYS; /* File is created */
  2369. dir = dj.dir; /* New entry */
  2370. }
  2371. else /* Any object is already existing */
  2372. {
  2373. if ( mode & FA_CREATE_NEW ) /* Cannot create new */
  2374. {
  2375. res = FR_EXIST;
  2376. }
  2377. else
  2378. {
  2379. if ( dir[DIR_Attr] & ( AM_RDO | AM_DIR ) ) /* Cannot overwrite it (R/O or DIR) */
  2380. {
  2381. res = FR_DENIED;
  2382. }
  2383. }
  2384. }
  2385. if ( res == FR_OK && ( mode & FA_CREATE_ALWAYS ) ) /* Truncate it if overwrite mode */
  2386. {
  2387. dw = get_fattime(); /* Created time */
  2388. ST_DWORD( dir + DIR_CrtTime, dw );
  2389. dir[DIR_Attr] = 0; /* Reset attribute */
  2390. ST_DWORD( dir + DIR_FileSize, 0 ); /* size = 0 */
  2391. cl = LD_CLUST( dir ); /* Get start cluster */
  2392. ST_CLUST( dir, 0 ); /* cluster = 0 */
  2393. dj.fs->wflag = 1;
  2394. if ( cl ) /* Remove the cluster chain if exist */
  2395. {
  2396. dw = dj.fs->winsect;
  2397. res = remove_chain( dj.fs, cl );
  2398. if ( res == FR_OK )
  2399. {
  2400. dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
  2401. res = move_window( dj.fs, dw );
  2402. }
  2403. }
  2404. }
  2405. }
  2406. else /* Open an existing file */
  2407. {
  2408. if ( res == FR_OK ) /* Follow succeeded */
  2409. {
  2410. if ( dir[DIR_Attr] & AM_DIR ) /* It is a directory */
  2411. {
  2412. res = FR_NO_FILE;
  2413. }
  2414. else
  2415. {
  2416. if ( ( mode & FA_WRITE ) && ( dir[DIR_Attr] & AM_RDO ) ) /* R/O violation */
  2417. {
  2418. res = FR_DENIED;
  2419. }
  2420. }
  2421. }
  2422. }
  2423. if ( res == FR_OK )
  2424. {
  2425. if ( mode & FA_CREATE_ALWAYS ) /* Set file change flag if created or overwritten */
  2426. {
  2427. mode |= FA__WRITTEN;
  2428. }
  2429. fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
  2430. fp->dir_ptr = dir;
  2431. #if _FS_SHARE
  2432. fp->lockid = inc_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 );
  2433. if ( !fp->lockid )
  2434. {
  2435. res = FR_INT_ERR;
  2436. }
  2437. #endif
  2438. }
  2439. #else /* R/O configuration */
  2440. if ( res == FR_OK ) /* Follow succeeded */
  2441. {
  2442. if ( !dir ) /* Current dir itself */
  2443. {
  2444. res = FR_INVALID_NAME;
  2445. }
  2446. else
  2447. {
  2448. if ( dir[DIR_Attr] & AM_DIR ) /* It is a directory */
  2449. {
  2450. res = FR_NO_FILE;
  2451. }
  2452. }
  2453. }
  2454. #endif
  2455. FREE_BUF();
  2456. if ( res == FR_OK )
  2457. {
  2458. fp->flag = mode; /* File access mode */
  2459. fp->org_clust = LD_CLUST( dir ); /* File start cluster */
  2460. fp->fsize = LD_DWORD( dir + DIR_FileSize ); /* File size */
  2461. fp->fptr = 0; /* File pointer */
  2462. fp->dsect = 0;
  2463. #if _USE_FASTSEEK
  2464. fp->cltbl = 0; /* No cluster link map table */
  2465. #endif
  2466. fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
  2467. }
  2468. LEAVE_FF( dj.fs, res );
  2469. }
  2470. /*-----------------------------------------------------------------------*/
  2471. /* Read File */
  2472. /*-----------------------------------------------------------------------*/
  2473. FRESULT f_read (
  2474. FIL *fp, /* Pointer to the file object */
  2475. void *buff, /* Pointer to data buffer */
  2476. UINT btr, /* Number of bytes to read */
  2477. UINT *br /* Pointer to number of bytes read */
  2478. )
  2479. {
  2480. FRESULT res;
  2481. DWORD clst, sect, remain;
  2482. UINT rcnt, cc;
  2483. BYTE csect, *rbuff = buff;
  2484. if ( btr > 512 && !ff_sd_offload )
  2485. {
  2486. printf( "WARNING: read >512 bytes but offloading is inactive!!\n" );
  2487. }
  2488. *br = 0; /* Initialize byte counter */
  2489. res = validate( fp->fs, fp->id ); /* Check validity of the object */
  2490. if ( res != FR_OK )
  2491. {
  2492. LEAVE_FF( fp->fs, res );
  2493. }
  2494. if ( fp->flag & FA__ERROR ) /* Check abort flag */
  2495. {
  2496. LEAVE_FF( fp->fs, FR_INT_ERR );
  2497. }
  2498. if ( !( fp->flag & FA_READ ) ) /* Check access mode */
  2499. {
  2500. LEAVE_FF( fp->fs, FR_DENIED );
  2501. }
  2502. remain = fp->fsize - fp->fptr;
  2503. if ( btr > remain )
  2504. {
  2505. btr = ( UINT )remain; /* Truncate btr by remaining bytes */
  2506. }
  2507. for ( ; btr; /* Repeat until all data transferred */
  2508. rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt )
  2509. {
  2510. if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */
  2511. {
  2512. csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */
  2513. if ( !csect ) /* On the cluster boundary? */
  2514. {
  2515. clst = ( fp->fptr == 0 ) ? /* On the top of the file? */
  2516. fp->org_clust : get_fat( fp->fs, fp->curr_clust );
  2517. if ( clst <= 1 )
  2518. {
  2519. ABORT( fp->fs, FR_INT_ERR );
  2520. }
  2521. if ( clst == 0xFFFFFFFF )
  2522. {
  2523. ABORT( fp->fs, FR_DISK_ERR );
  2524. }
  2525. fp->curr_clust = clst; /* Update current cluster */
  2526. }
  2527. sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current sector */
  2528. if ( !sect )
  2529. {
  2530. ABORT( fp->fs, FR_INT_ERR );
  2531. }
  2532. sect += csect;
  2533. cc = btr / SS( fp->fs ); /* When remaining bytes >= sector size, */
  2534. if ( cc ) /* Read maximum contiguous sectors directly */
  2535. {
  2536. if ( csect + cc > fp->fs->csize ) /* Clip at cluster boundary */
  2537. {
  2538. cc = fp->fs->csize - csect;
  2539. }
  2540. /* XXX OFFLOAD GOES HERE */
  2541. if ( ff_sd_offload )
  2542. {
  2543. sd_offload = 1;
  2544. }
  2545. if ( disk_read( fp->fs->drv, rbuff, sect, ( BYTE )cc ) != RES_OK )
  2546. {
  2547. ABORT( fp->fs, FR_DISK_ERR );
  2548. }
  2549. sd_offload = 0;
  2550. #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
  2551. #if _FS_TINY
  2552. if ( fp->fs->wflag && fp->fs->winsect - sect < cc )
  2553. {
  2554. mem_cpy( rbuff + ( ( fp->fs->winsect - sect ) * SS( fp->fs ) ), fp->fs->win, SS( fp->fs ) );
  2555. }
  2556. #else
  2557. if ( ( fp->flag & FA__DIRTY ) && fp->dsect - sect < cc )
  2558. {
  2559. mem_cpy( rbuff + ( ( fp->dsect - sect ) * SS( fp->fs ) ), fp->buf, SS( fp->fs ) ); uart_putc( 'Y' );
  2560. }
  2561. #endif
  2562. #endif
  2563. rcnt = SS( fp->fs ) * cc; /* Number of bytes transferred */
  2564. continue;
  2565. }
  2566. #if !_FS_TINY
  2567. #if !_FS_READONLY
  2568. if ( fp->flag & FA__DIRTY ) /* Write sector I/O buffer if needed */
  2569. {
  2570. if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
  2571. {
  2572. ABORT( fp->fs, FR_DISK_ERR );
  2573. }
  2574. fp->flag &= ~FA__DIRTY;
  2575. }
  2576. #endif
  2577. if ( fp->dsect != sect ) /* Fill sector buffer with file data */
  2578. {
  2579. if ( !ff_sd_offload )
  2580. {
  2581. if ( disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK )
  2582. {
  2583. ABORT( fp->fs, FR_DISK_ERR );
  2584. }
  2585. }
  2586. }
  2587. #endif
  2588. fp->dsect = sect;
  2589. }
  2590. rcnt = SS( fp->fs ) - ( fp->fptr % SS( fp->fs ) ); /* Get partial sector data from sector buffer */
  2591. if ( rcnt > btr )
  2592. {
  2593. rcnt = btr;
  2594. }
  2595. if ( !ff_sd_offload )
  2596. {
  2597. #if _FS_TINY
  2598. if ( move_window( fp->fs, fp->dsect ) ) /* Move sector window */
  2599. {
  2600. ABORT( fp->fs, FR_DISK_ERR );
  2601. }
  2602. mem_cpy( rbuff, &fp->fs->win[fp->fptr % SS( fp->fs )], rcnt ); /* Pick partial sector */
  2603. #else
  2604. mem_cpy( rbuff, &fp->buf[fp->fptr % SS( fp->fs )], rcnt ); /* Pick partial sector */
  2605. }
  2606. else
  2607. {
  2608. sd_offload_partial_start = fp->fptr % SS( fp->fs );
  2609. sd_offload_partial_end = sd_offload_partial_start + rcnt;
  2610. // printf("partial dma. sect=%08lx start=%d end=%d\n", fp->dsect, sd_offload_partial_start, sd_offload_partial_end);
  2611. /* set start + end */
  2612. sd_offload = 1;
  2613. sd_offload_partial = 1;
  2614. if ( disk_read( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
  2615. {
  2616. sd_offload = 0;
  2617. ABORT( fp->fs, FR_DISK_ERR );
  2618. }
  2619. sd_offload = 0;
  2620. #endif
  2621. }
  2622. }
  2623. ff_sd_offload = 0;
  2624. LEAVE_FF( fp->fs, FR_OK );
  2625. }
  2626. #if !_FS_READONLY
  2627. /*-----------------------------------------------------------------------*/
  2628. /* Write File */
  2629. /*-----------------------------------------------------------------------*/
  2630. FRESULT f_write (
  2631. FIL *fp, /* Pointer to the file object */
  2632. const void *buff, /* Pointer to the data to be written */
  2633. UINT btw, /* Number of bytes to write */
  2634. UINT *bw /* Pointer to number of bytes written */
  2635. )
  2636. {
  2637. FRESULT res;
  2638. DWORD clst, sect;
  2639. UINT wcnt, cc;
  2640. const BYTE *wbuff = buff;
  2641. BYTE csect;
  2642. *bw = 0; /* Initialize byte counter */
  2643. res = validate( fp->fs, fp->id ); /* Check validity of the object */
  2644. if ( res != FR_OK )
  2645. {
  2646. LEAVE_FF( fp->fs, res );
  2647. }
  2648. if ( fp->flag & FA__ERROR ) /* Check abort flag */
  2649. {
  2650. LEAVE_FF( fp->fs, FR_INT_ERR );
  2651. }
  2652. if ( !( fp->flag & FA_WRITE ) ) /* Check access mode */
  2653. {
  2654. LEAVE_FF( fp->fs, FR_DENIED );
  2655. }
  2656. if ( fp->fsize + btw < fp->fsize )
  2657. {
  2658. btw = 0; /* File size cannot reach 4GB */
  2659. }
  2660. for ( ; btw; /* Repeat until all data transferred */
  2661. wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt )
  2662. {
  2663. if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */
  2664. {
  2665. csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */
  2666. if ( !csect ) /* On the cluster boundary? */
  2667. {
  2668. if ( fp->fptr == 0 ) /* On the top of the file? */
  2669. {
  2670. clst = fp->org_clust; /* Follow from the origin */
  2671. if ( clst == 0 ) /* When there is no cluster chain, */
  2672. {
  2673. fp->org_clust = clst = create_chain( fp->fs, 0 ); /* Create a new cluster chain */
  2674. }
  2675. }
  2676. else /* Middle or end of the file */
  2677. {
  2678. clst = create_chain( fp->fs, fp->curr_clust ); /* Follow or stretch cluster chain */
  2679. }
  2680. if ( clst == 0 )
  2681. {
  2682. break; /* Could not allocate a new cluster (disk full) */
  2683. }
  2684. if ( clst == 1 )
  2685. {
  2686. ABORT( fp->fs, FR_INT_ERR );
  2687. }
  2688. if ( clst == 0xFFFFFFFF )
  2689. {
  2690. ABORT( fp->fs, FR_DISK_ERR );
  2691. }
  2692. fp->curr_clust = clst; /* Update current cluster */
  2693. }
  2694. #if _FS_TINY
  2695. if ( fp->fs->winsect == fp->dsect
  2696. && move_window( fp->fs, 0 ) ) /* Write back data buffer prior to following direct transfer */
  2697. {
  2698. ABORT( fp->fs, FR_DISK_ERR );
  2699. }
  2700. #else
  2701. if ( fp->flag & FA__DIRTY ) /* Write back data buffer prior to following direct transfer */
  2702. {
  2703. if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
  2704. {
  2705. ABORT( fp->fs, FR_DISK_ERR );
  2706. }
  2707. fp->flag &= ~FA__DIRTY;
  2708. }
  2709. #endif
  2710. sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current sector */
  2711. if ( !sect )
  2712. {
  2713. ABORT( fp->fs, FR_INT_ERR );
  2714. }
  2715. sect += csect;
  2716. cc = btw / SS( fp->fs ); /* When remaining bytes >= sector size, */
  2717. if ( cc ) /* Write maximum contiguous sectors directly */
  2718. {
  2719. if ( csect + cc > fp->fs->csize ) /* Clip at cluster boundary */
  2720. {
  2721. cc = fp->fs->csize - csect;
  2722. }
  2723. if ( disk_write( fp->fs->drv, wbuff, sect, ( BYTE )cc ) != RES_OK )
  2724. {
  2725. ABORT( fp->fs, FR_DISK_ERR );
  2726. }
  2727. #if _FS_TINY
  2728. if ( fp->fs->winsect - sect < cc ) /* Refill sector cache if it gets dirty by the direct write */
  2729. {
  2730. mem_cpy( fp->fs->win, wbuff + ( ( fp->fs->winsect - sect ) * SS( fp->fs ) ), SS( fp->fs ) );
  2731. fp->fs->wflag = 0;
  2732. }
  2733. #else
  2734. if ( fp->dsect - sect < cc ) /* Refill sector cache if it gets dirty by the direct write */
  2735. {
  2736. mem_cpy( fp->buf, wbuff + ( ( fp->dsect - sect ) * SS( fp->fs ) ), SS( fp->fs ) );
  2737. fp->flag &= ~FA__DIRTY;
  2738. }
  2739. #endif
  2740. wcnt = SS( fp->fs ) * cc; /* Number of bytes transferred */
  2741. continue;
  2742. }
  2743. #if _FS_TINY
  2744. if ( fp->fptr >= fp->fsize ) /* Avoid silly buffer filling at growing edge */
  2745. {
  2746. if ( move_window( fp->fs, 0 ) )
  2747. {
  2748. ABORT( fp->fs, FR_DISK_ERR );
  2749. }
  2750. fp->fs->winsect = sect;
  2751. }
  2752. #else
  2753. if ( fp->dsect != sect ) /* Fill sector buffer with file data */
  2754. {
  2755. if ( fp->fptr < fp->fsize &&
  2756. disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK )
  2757. {
  2758. ABORT( fp->fs, FR_DISK_ERR );
  2759. }
  2760. }
  2761. #endif
  2762. fp->dsect = sect;
  2763. }
  2764. wcnt = SS( fp->fs ) - ( fp->fptr % SS( fp->fs ) ); /* Put partial sector into file I/O buffer */
  2765. if ( wcnt > btw )
  2766. {
  2767. wcnt = btw;
  2768. }
  2769. #if _FS_TINY
  2770. if ( move_window( fp->fs, fp->dsect ) ) /* Move sector window */
  2771. {
  2772. ABORT( fp->fs, FR_DISK_ERR );
  2773. }
  2774. mem_cpy( &fp->fs->win[fp->fptr % SS( fp->fs )], wbuff, wcnt ); /* Fit partial sector */
  2775. fp->fs->wflag = 1;
  2776. #else
  2777. mem_cpy( &fp->buf[fp->fptr % SS( fp->fs )], wbuff, wcnt ); /* Fit partial sector */
  2778. fp->flag |= FA__DIRTY;
  2779. #endif
  2780. }
  2781. if ( fp->fptr > fp->fsize )
  2782. {
  2783. fp->fsize = fp->fptr; /* Update file size if needed */
  2784. }
  2785. fp->flag |= FA__WRITTEN; /* Set file change flag */
  2786. LEAVE_FF( fp->fs, FR_OK );
  2787. }
  2788. /*-----------------------------------------------------------------------*/
  2789. /* Synchronize the File Object */
  2790. /*-----------------------------------------------------------------------*/
  2791. FRESULT f_sync (
  2792. FIL *fp /* Pointer to the file object */
  2793. )
  2794. {
  2795. FRESULT res;
  2796. DWORD tim;
  2797. BYTE *dir;
  2798. res = validate( fp->fs, fp->id ); /* Check validity of the object */
  2799. if ( res == FR_OK )
  2800. {
  2801. if ( fp->flag & FA__WRITTEN ) /* Has the file been written? */
  2802. {
  2803. #if !_FS_TINY /* Write-back dirty buffer */
  2804. if ( fp->flag & FA__DIRTY )
  2805. {
  2806. if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
  2807. {
  2808. LEAVE_FF( fp->fs, FR_DISK_ERR );
  2809. }
  2810. fp->flag &= ~FA__DIRTY;
  2811. }
  2812. #endif
  2813. /* Update the directory entry */
  2814. res = move_window( fp->fs, fp->dir_sect );
  2815. if ( res == FR_OK )
  2816. {
  2817. dir = fp->dir_ptr;
  2818. dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
  2819. ST_DWORD( dir + DIR_FileSize, fp->fsize ); /* Update file size */
  2820. ST_CLUST( dir, fp->org_clust ); /* Update start cluster */
  2821. tim = get_fattime(); /* Update updated time */
  2822. ST_DWORD( dir + DIR_WrtTime, tim );
  2823. fp->flag &= ~FA__WRITTEN;
  2824. fp->fs->wflag = 1;
  2825. res = sync( fp->fs );
  2826. }
  2827. }
  2828. }
  2829. LEAVE_FF( fp->fs, res );
  2830. }
  2831. #endif /* !_FS_READONLY */
  2832. /*-----------------------------------------------------------------------*/
  2833. /* Close File */
  2834. /*-----------------------------------------------------------------------*/
  2835. FRESULT f_close (
  2836. FIL *fp /* Pointer to the file object to be closed */
  2837. )
  2838. {
  2839. FRESULT res;
  2840. #if _FS_READONLY
  2841. FATFS *fs = fp->fs;
  2842. res = validate( fs, fp->id );
  2843. if ( res == FR_OK )
  2844. {
  2845. fp->fs = 0; /* Discard file object */
  2846. }
  2847. LEAVE_FF( fs, res );
  2848. #else
  2849. res = f_sync( fp ); /* Flush cached data */
  2850. #if _FS_SHARE
  2851. if ( res == FR_OK ) /* Decrement open counter */
  2852. {
  2853. #if _FS_REENTRANT
  2854. res = validate( fp->fs, fp->id );
  2855. if ( res == FR_OK )
  2856. {
  2857. res = dec_lock( fp->lockid );
  2858. unlock_fs( fp->fs, FR_OK );
  2859. }
  2860. #else
  2861. res = dec_lock( fp->lockid );
  2862. #endif
  2863. }
  2864. #endif
  2865. if ( res == FR_OK )
  2866. {
  2867. fp->fs = 0; /* Discard file object */
  2868. }
  2869. return res;
  2870. #endif
  2871. }
  2872. /*-----------------------------------------------------------------------*/
  2873. /* Current Drive/Directory Handlings */
  2874. /*-----------------------------------------------------------------------*/
  2875. #if _FS_RPATH >= 1
  2876. FRESULT f_chdrive (
  2877. BYTE drv /* Drive number */
  2878. )
  2879. {
  2880. if ( drv >= _VOLUMES )
  2881. {
  2882. return FR_INVALID_DRIVE;
  2883. }
  2884. CurrVol = drv;
  2885. return FR_OK;
  2886. }
  2887. FRESULT f_chdir (
  2888. const TCHAR *path /* Pointer to the directory path */
  2889. )
  2890. {
  2891. FRESULT res;
  2892. DIR dj;
  2893. DEF_NAMEBUF;
  2894. res = chk_mounted( &path, &dj.fs, 0 );
  2895. if ( res == FR_OK )
  2896. {
  2897. INIT_BUF( dj );
  2898. res = follow_path( &dj, path ); /* Follow the path */
  2899. FREE_BUF();
  2900. if ( res == FR_OK ) /* Follow completed */
  2901. {
  2902. if ( !dj.dir )
  2903. {
  2904. dj.fs->cdir = dj.sclust; /* Start directory itself */
  2905. }
  2906. else
  2907. {
  2908. if ( dj.dir[DIR_Attr] & AM_DIR ) /* Reached to the directory */
  2909. {
  2910. dj.fs->cdir = LD_CLUST( dj.dir );
  2911. }
  2912. else
  2913. {
  2914. res = FR_NO_PATH; /* Reached but a file */
  2915. }
  2916. }
  2917. }
  2918. if ( res == FR_NO_FILE )
  2919. {
  2920. res = FR_NO_PATH;
  2921. }
  2922. }
  2923. LEAVE_FF( dj.fs, res );
  2924. }
  2925. #if _FS_RPATH >= 2
  2926. FRESULT f_getcwd (
  2927. TCHAR *path, /* Pointer to the directory path */
  2928. UINT sz_path /* Size of path */
  2929. )
  2930. {
  2931. FRESULT res;
  2932. DIR dj;
  2933. UINT i, n;
  2934. DWORD ccl;
  2935. TCHAR *tp;
  2936. FILINFO fno;
  2937. DEF_NAMEBUF;
  2938. *path = 0;
  2939. res = chk_mounted( ( const TCHAR ** )&path, &dj.fs, 0 ); /* Get current volume */
  2940. if ( res == FR_OK )
  2941. {
  2942. INIT_BUF( dj );
  2943. i = sz_path; /* Bottom of buffer (dir stack base) */
  2944. dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */
  2945. while ( ( ccl = dj.sclust ) != 0 ) /* Repeat while current dir is a sub-dir */
  2946. {
  2947. res = dir_sdi( &dj, 1 ); /* Get parent dir */
  2948. if ( res != FR_OK )
  2949. {
  2950. break;
  2951. }
  2952. res = dir_read( &dj );
  2953. if ( res != FR_OK )
  2954. {
  2955. break;
  2956. }
  2957. dj.sclust = LD_CLUST( dj.dir ); /* Goto parent dir */
  2958. res = dir_sdi( &dj, 0 );
  2959. if ( res != FR_OK )
  2960. {
  2961. break;
  2962. }
  2963. do /* Find the entry links to the child dir */
  2964. {
  2965. res = dir_read( &dj );
  2966. if ( res != FR_OK )
  2967. {
  2968. break;
  2969. }
  2970. if ( ccl == LD_CLUST( dj.dir ) )
  2971. {
  2972. break; /* Found the entry */
  2973. }
  2974. res = dir_next( &dj, 0 );
  2975. }
  2976. while ( res == FR_OK );
  2977. if ( res == FR_NO_FILE )
  2978. {
  2979. res = FR_INT_ERR; /* It cannot be 'not found'. */
  2980. }
  2981. if ( res != FR_OK )
  2982. {
  2983. break;
  2984. }
  2985. #if _USE_LFN
  2986. fno.lfname = path;
  2987. fno.lfsize = i;
  2988. #endif
  2989. get_fileinfo( &dj, &fno ); /* Get the dir name and push it to the buffer */
  2990. tp = fno.fname;
  2991. if ( _USE_LFN && *path )
  2992. {
  2993. tp = path;
  2994. }
  2995. for ( n = 0; tp[n]; n++ ) ;
  2996. if ( i < n + 3 )
  2997. {
  2998. res = FR_NOT_ENOUGH_CORE; break;
  2999. }
  3000. while ( n )
  3001. {
  3002. path[--i] = tp[--n];
  3003. }
  3004. path[--i] = '/';
  3005. }
  3006. tp = path;
  3007. if ( res == FR_OK )
  3008. {
  3009. *tp++ = '0' + CurrVol; /* Put drive number */
  3010. *tp++ = ':';
  3011. if ( i == sz_path ) /* Root-dir */
  3012. {
  3013. *tp++ = '/';
  3014. }
  3015. else /* Sub-dir */
  3016. {
  3017. do /* Add stacked path str */
  3018. {
  3019. *tp++ = path[i++];
  3020. }
  3021. while ( i < sz_path );
  3022. }
  3023. }
  3024. *tp = 0;
  3025. FREE_BUF();
  3026. }
  3027. LEAVE_FF( dj.fs, res );
  3028. }
  3029. #endif /* _FS_RPATH >= 2 */
  3030. #endif /* _FS_RPATH >= 1 */
  3031. #if _FS_MINIMIZE <= 2
  3032. /*-----------------------------------------------------------------------*/
  3033. /* Seek File R/W Pointer */
  3034. /*-----------------------------------------------------------------------*/
  3035. FRESULT f_lseek (
  3036. FIL *fp, /* Pointer to the file object */
  3037. DWORD ofs /* File pointer from top of file */
  3038. )
  3039. {
  3040. FRESULT res;
  3041. res = validate( fp->fs, fp->id ); /* Check validity of the object */
  3042. if ( res != FR_OK )
  3043. {
  3044. LEAVE_FF( fp->fs, res );
  3045. }
  3046. if ( fp->flag & FA__ERROR ) /* Check abort flag */
  3047. {
  3048. LEAVE_FF( fp->fs, FR_INT_ERR );
  3049. }
  3050. #if _USE_FASTSEEK
  3051. if ( fp->cltbl ) /* Fast seek */
  3052. {
  3053. DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl;
  3054. BYTE csc;
  3055. tlen = *tbl++;
  3056. if ( ofs == CREATE_LINKMAP ) /* Create link map table */
  3057. {
  3058. cl = fp->org_clust;
  3059. if ( cl )
  3060. {
  3061. do
  3062. {
  3063. if ( tlen < 4 ) /* Not enough table items */
  3064. {
  3065. res = FR_NOT_ENOUGH_CORE; break;
  3066. }
  3067. tcl = cl; ncl = 0;
  3068. do /* Get a fragment and store the top and length */
  3069. {
  3070. pcl = cl; ncl++;
  3071. cl = get_fat( fp->fs, cl );
  3072. if ( cl <= 1 )
  3073. {
  3074. ABORT( fp->fs, FR_INT_ERR );
  3075. }
  3076. if ( cl == 0xFFFFFFFF )
  3077. {
  3078. ABORT( fp->fs, FR_DISK_ERR );
  3079. }
  3080. }
  3081. while ( cl == pcl + 1 );
  3082. *tbl++ = ncl; *tbl++ = tcl;
  3083. tlen -= 2;
  3084. }
  3085. while ( cl < fp->fs->n_fatent );
  3086. }
  3087. *tbl = 0; /* Terminate table */
  3088. }
  3089. else /* Fast seek */
  3090. {
  3091. if ( ofs > fp->fsize ) /* Clip offset at the file size */
  3092. {
  3093. ofs = fp->fsize;
  3094. }
  3095. fp->fptr = ofs; /* Set file pointer */
  3096. if ( ofs )
  3097. {
  3098. dsc = ( ofs - 1 ) / SS( fp->fs );
  3099. cl = dsc / fp->fs->csize;
  3100. for ( ;; )
  3101. {
  3102. ncl = *tbl++;
  3103. if ( !ncl )
  3104. {
  3105. ABORT( fp->fs, FR_INT_ERR );
  3106. }
  3107. if ( cl < ncl )
  3108. {
  3109. break;
  3110. }
  3111. cl -= ncl; tbl++;
  3112. }
  3113. fp->curr_clust = cl + *tbl;
  3114. csc = ( BYTE )( dsc & ( fp->fs->csize - 1 ) );
  3115. dsc = clust2sect( fp->fs, fp->curr_clust );
  3116. if ( !dsc )
  3117. {
  3118. ABORT( fp->fs, FR_INT_ERR );
  3119. }
  3120. dsc += csc;
  3121. if ( fp->fptr % SS( fp->fs ) && dsc != fp->dsect )
  3122. {
  3123. #if !_FS_TINY
  3124. #if !_FS_READONLY
  3125. if ( fp->flag & FA__DIRTY ) /* Flush dirty buffer if needed */
  3126. {
  3127. if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
  3128. {
  3129. ABORT( fp->fs, FR_DISK_ERR );
  3130. }
  3131. fp->flag &= ~FA__DIRTY;
  3132. }
  3133. #endif
  3134. if ( !ff_sd_offload )
  3135. {
  3136. sd_offload_partial = 0;
  3137. if ( disk_read( fp->fs->drv, fp->buf, dsc, 1 ) != RES_OK )
  3138. {
  3139. ABORT( fp->fs, FR_DISK_ERR );
  3140. }
  3141. }
  3142. else
  3143. {
  3144. sd_offload_partial = 1;
  3145. sd_offload_partial_start = fp->fptr % SS( fp->fs );
  3146. }
  3147. // if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK)
  3148. // ABORT(fp->fs, FR_DISK_ERR);
  3149. #endif
  3150. fp->dsect = dsc;
  3151. }
  3152. }
  3153. }
  3154. }
  3155. else
  3156. #endif
  3157. /* Normal Seek */
  3158. {
  3159. DWORD clst, bcs, nsect, ifptr;
  3160. if ( ofs > fp->fsize /* In read-only mode, clip offset with the file size */
  3161. #if !_FS_READONLY
  3162. && !( fp->flag & FA_WRITE )
  3163. #endif
  3164. )
  3165. {
  3166. ofs = fp->fsize;
  3167. }
  3168. ifptr = fp->fptr;
  3169. fp->fptr = nsect = 0;
  3170. if ( ofs )
  3171. {
  3172. bcs = ( DWORD )fp->fs->csize * SS( fp->fs ); /* Cluster size (byte) */
  3173. if ( ifptr > 0 &&
  3174. ( ofs - 1 ) / bcs >= ( ifptr - 1 ) / bcs ) /* When seek to same or following cluster, */
  3175. {
  3176. fp->fptr = ( ifptr - 1 ) & ~( bcs - 1 ); /* start from the current cluster */
  3177. ofs -= fp->fptr;
  3178. clst = fp->curr_clust;
  3179. }
  3180. else /* When seek to back cluster, */
  3181. {
  3182. clst = fp->org_clust; /* start from the first cluster */
  3183. #if !_FS_READONLY
  3184. if ( clst == 0 ) /* If no cluster chain, create a new chain */
  3185. {
  3186. clst = create_chain( fp->fs, 0 );
  3187. if ( clst == 1 )
  3188. {
  3189. ABORT( fp->fs, FR_INT_ERR );
  3190. }
  3191. if ( clst == 0xFFFFFFFF )
  3192. {
  3193. ABORT( fp->fs, FR_DISK_ERR );
  3194. }
  3195. fp->org_clust = clst;
  3196. }
  3197. #endif
  3198. fp->curr_clust = clst;
  3199. }
  3200. if ( clst != 0 )
  3201. {
  3202. while ( ofs > bcs ) /* Cluster following loop */
  3203. {
  3204. #if !_FS_READONLY
  3205. if ( fp->flag & FA_WRITE ) /* Check if in write mode or not */
  3206. {
  3207. clst = create_chain( fp->fs, clst ); /* Force stretch if in write mode */
  3208. if ( clst == 0 ) /* When disk gets full, clip file size */
  3209. {
  3210. ofs = bcs; break;
  3211. }
  3212. }
  3213. else
  3214. #endif
  3215. clst = get_fat( fp->fs, clst ); /* Follow cluster chain if not in write mode */
  3216. if ( clst == 0xFFFFFFFF )
  3217. {
  3218. ABORT( fp->fs, FR_DISK_ERR );
  3219. }
  3220. if ( clst <= 1 || clst >= fp->fs->n_fatent )
  3221. {
  3222. ABORT( fp->fs, FR_INT_ERR );
  3223. }
  3224. fp->curr_clust = clst;
  3225. fp->fptr += bcs;
  3226. ofs -= bcs;
  3227. }
  3228. fp->fptr += ofs;
  3229. if ( ofs % SS( fp->fs ) )
  3230. {
  3231. nsect = clust2sect( fp->fs, clst ); /* Current sector */
  3232. if ( !nsect )
  3233. {
  3234. ABORT( fp->fs, FR_INT_ERR );
  3235. }
  3236. nsect += ofs / SS( fp->fs );
  3237. }
  3238. }
  3239. }
  3240. if ( fp->fptr % SS( fp->fs ) && nsect != fp->dsect )
  3241. {
  3242. #if !_FS_TINY
  3243. #if !_FS_READONLY
  3244. if ( fp->flag & FA__DIRTY ) /* Flush dirty buffer if needed */
  3245. {
  3246. if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
  3247. {
  3248. ABORT( fp->fs, FR_DISK_ERR );
  3249. }
  3250. fp->flag &= ~FA__DIRTY;
  3251. }
  3252. #endif
  3253. if ( !ff_sd_offload )
  3254. {
  3255. sd_offload_partial = 0;
  3256. if ( disk_read( fp->fs->drv, fp->buf, nsect, 1 ) != RES_OK )
  3257. {
  3258. ABORT( fp->fs, FR_DISK_ERR );
  3259. }
  3260. }
  3261. else
  3262. {
  3263. sd_offload_partial = 1;
  3264. sd_offload_partial_start = fp->fptr % SS( fp->fs );
  3265. }
  3266. #endif
  3267. fp->dsect = nsect;
  3268. }
  3269. #if !_FS_READONLY
  3270. if ( fp->fptr > fp->fsize ) /* Set change flag if the file size is extended */
  3271. {
  3272. fp->fsize = fp->fptr;
  3273. fp->flag |= FA__WRITTEN;
  3274. }
  3275. #endif
  3276. }
  3277. ff_sd_offload = 0;
  3278. LEAVE_FF( fp->fs, res );
  3279. }
  3280. #if _FS_MINIMIZE <= 1
  3281. /*-----------------------------------------------------------------------*/
  3282. /* Create a Directroy Object */
  3283. /*-----------------------------------------------------------------------*/
  3284. FRESULT f_opendir (
  3285. DIR *dj, /* Pointer to directory object to create */
  3286. const TCHAR *path /* Pointer to the directory path */
  3287. )
  3288. {
  3289. FRESULT res;
  3290. DEF_NAMEBUF;
  3291. res = chk_mounted( &path, &dj->fs, 0 );
  3292. if ( res == FR_OK )
  3293. {
  3294. INIT_BUF( *dj );
  3295. res = follow_path( dj, path ); /* Follow the path to the directory */
  3296. FREE_BUF();
  3297. if ( res == FR_OK ) /* Follow completed */
  3298. {
  3299. if ( dj->dir ) /* It is not the root dir */
  3300. {
  3301. if ( dj->dir[DIR_Attr] & AM_DIR ) /* The object is a directory */
  3302. {
  3303. dj->sclust = LD_CLUST( dj->dir );
  3304. }
  3305. else /* The object is not a directory */
  3306. {
  3307. res = FR_NO_PATH;
  3308. }
  3309. }
  3310. if ( res == FR_OK )
  3311. {
  3312. dj->id = dj->fs->id;
  3313. res = dir_sdi( dj, 0 ); /* Rewind dir */
  3314. }
  3315. }
  3316. if ( res == FR_NO_FILE )
  3317. {
  3318. res = FR_NO_PATH;
  3319. }
  3320. }
  3321. LEAVE_FF( dj->fs, res );
  3322. }
  3323. /*-----------------------------------------------------------------------*/
  3324. /* Read Directory Entry in Sequense */
  3325. /*-----------------------------------------------------------------------*/
  3326. FRESULT f_readdir (
  3327. DIR *dj, /* Pointer to the open directory object */
  3328. FILINFO *fno /* Pointer to file information to return */
  3329. )
  3330. {
  3331. FRESULT res;
  3332. DEF_NAMEBUF;
  3333. res = validate( dj->fs, dj->id ); /* Check validity of the object */
  3334. if ( res == FR_OK )
  3335. {
  3336. if ( !fno )
  3337. {
  3338. res = dir_sdi( dj, 0 ); /* Rewind the directory object */
  3339. }
  3340. else
  3341. {
  3342. INIT_BUF( *dj );
  3343. res = dir_read( dj ); /* Read an directory item */
  3344. if ( res == FR_NO_FILE ) /* Reached end of dir */
  3345. {
  3346. dj->sect = 0;
  3347. res = FR_OK;
  3348. }
  3349. if ( res == FR_OK ) /* A valid entry is found */
  3350. {
  3351. get_fileinfo( dj, fno ); /* Get the object information */
  3352. res = dir_next( dj, 0 ); /* Increment index for next */
  3353. if ( res == FR_NO_FILE )
  3354. {
  3355. dj->sect = 0;
  3356. res = FR_OK;
  3357. }
  3358. }
  3359. FREE_BUF();
  3360. }
  3361. }
  3362. LEAVE_FF( dj->fs, res );
  3363. }
  3364. FRESULT l_opendirbycluster (
  3365. FATFS *fs,
  3366. DIR *dj,
  3367. const TCHAR *path,
  3368. DWORD clust
  3369. )
  3370. {
  3371. FRESULT res;
  3372. res = chk_mounted( &path, &fs, 0 );
  3373. DEF_NAMEBUF;
  3374. INIT_BUF( *dj );
  3375. dj->sclust = clust;
  3376. dj->fs = fs;
  3377. dj->id = fs->id;
  3378. dj->dir = 0;
  3379. res = dir_sdi( dj, 0 );
  3380. FREE_BUF();
  3381. return res;
  3382. }
  3383. FRESULT l_openfilebycluster (
  3384. FATFS *fs, /* Pointer to file system object */
  3385. FIL *fp, /* Pointer to the blank file object */
  3386. const TCHAR *path,
  3387. DWORD clust, /* Cluster number to be opened */
  3388. DWORD fsize /* File size to be assumed */
  3389. )
  3390. {
  3391. chk_mounted( &path, &fs, 0 );
  3392. fp->flag = FA_READ;
  3393. fp->org_clust = clust;
  3394. fp->fsize = fsize;
  3395. fp->fptr = 0;
  3396. fp->dsect = 0;
  3397. fp->fs = fs;
  3398. return FR_OK;
  3399. }
  3400. #if _FS_MINIMIZE == 0
  3401. /*-----------------------------------------------------------------------*/
  3402. /* Get File Status */
  3403. /*-----------------------------------------------------------------------*/
  3404. FRESULT f_stat (
  3405. const TCHAR *path, /* Pointer to the file path */
  3406. FILINFO *fno /* Pointer to file information to return */
  3407. )
  3408. {
  3409. FRESULT res;
  3410. DIR dj;
  3411. DEF_NAMEBUF;
  3412. res = chk_mounted( &path, &dj.fs, 0 );
  3413. if ( res == FR_OK )
  3414. {
  3415. INIT_BUF( dj );
  3416. res = follow_path( &dj, path ); /* Follow the file path */
  3417. if ( res == FR_OK ) /* Follow completed */
  3418. {
  3419. if ( dj.dir ) /* Found an object */
  3420. {
  3421. get_fileinfo( &dj, fno );
  3422. }
  3423. else /* It is root dir */
  3424. {
  3425. res = FR_INVALID_NAME;
  3426. }
  3427. }
  3428. FREE_BUF();
  3429. }
  3430. LEAVE_FF( dj.fs, res );
  3431. }
  3432. #if !_FS_READONLY
  3433. /*-----------------------------------------------------------------------*/
  3434. /* Get Number of Free Clusters */
  3435. /*-----------------------------------------------------------------------*/
  3436. FRESULT f_getfree (
  3437. const TCHAR *path, /* Pointer to the logical drive number (root dir) */
  3438. DWORD *nclst, /* Pointer to the variable to return number of free clusters */
  3439. FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */
  3440. )
  3441. {
  3442. FRESULT res;
  3443. DWORD n, clst, sect, stat;
  3444. UINT i;
  3445. BYTE fat, *p;
  3446. /* Get drive number */
  3447. res = chk_mounted( &path, fatfs, 0 );
  3448. if ( res == FR_OK )
  3449. {
  3450. /* If free_clust is valid, return it without full cluster scan */
  3451. if ( ( *fatfs )->free_clust <= ( *fatfs )->n_fatent - 2 )
  3452. {
  3453. *nclst = ( *fatfs )->free_clust;
  3454. }
  3455. else
  3456. {
  3457. /* Get number of free clusters */
  3458. fat = ( *fatfs )->fs_type;
  3459. n = 0;
  3460. if ( fat == FS_FAT12 )
  3461. {
  3462. clst = 2;
  3463. do
  3464. {
  3465. stat = get_fat( *fatfs, clst );
  3466. if ( stat == 0xFFFFFFFF )
  3467. {
  3468. res = FR_DISK_ERR;
  3469. break;
  3470. }
  3471. if ( stat == 1 )
  3472. {
  3473. res = FR_INT_ERR;
  3474. break;
  3475. }
  3476. if ( stat == 0 )
  3477. {
  3478. n++;
  3479. }
  3480. }
  3481. while ( ++clst < ( *fatfs )->n_fatent );
  3482. }
  3483. else
  3484. {
  3485. clst = ( *fatfs )->n_fatent;
  3486. sect = ( *fatfs )->fatbase;
  3487. i = 0; p = 0;
  3488. do
  3489. {
  3490. if ( !i )
  3491. {
  3492. res = move_window( *fatfs, sect++ );
  3493. if ( res != FR_OK )
  3494. {
  3495. break;
  3496. }
  3497. p = ( *fatfs )->win;
  3498. i = SS( *fatfs );
  3499. }
  3500. if ( fat == FS_FAT16 )
  3501. {
  3502. if ( LD_WORD( p ) == 0 )
  3503. {
  3504. n++;
  3505. }
  3506. p += 2; i -= 2;
  3507. }
  3508. else
  3509. {
  3510. if ( ( LD_DWORD( p ) & 0x0FFFFFFF ) == 0 )
  3511. {
  3512. n++;
  3513. }
  3514. p += 4; i -= 4;
  3515. }
  3516. }
  3517. while ( --clst );
  3518. }
  3519. ( *fatfs )->free_clust = n;
  3520. if ( fat == FS_FAT32 )
  3521. {
  3522. ( *fatfs )->fsi_flag = 1;
  3523. }
  3524. *nclst = n;
  3525. }
  3526. }
  3527. LEAVE_FF( *fatfs, res );
  3528. }
  3529. /*-----------------------------------------------------------------------*/
  3530. /* Truncate File */
  3531. /*-----------------------------------------------------------------------*/
  3532. FRESULT f_truncate (
  3533. FIL *fp /* Pointer to the file object */
  3534. )
  3535. {
  3536. FRESULT res;
  3537. DWORD ncl;
  3538. res = validate( fp->fs, fp->id ); /* Check validity of the object */
  3539. if ( res == FR_OK )
  3540. {
  3541. if ( fp->flag & FA__ERROR ) /* Check abort flag */
  3542. {
  3543. res = FR_INT_ERR;
  3544. }
  3545. else
  3546. {
  3547. if ( !( fp->flag & FA_WRITE ) ) /* Check access mode */
  3548. {
  3549. res = FR_DENIED;
  3550. }
  3551. }
  3552. }
  3553. if ( res == FR_OK )
  3554. {
  3555. if ( fp->fsize > fp->fptr )
  3556. {
  3557. fp->fsize = fp->fptr; /* Set file size to current R/W point */
  3558. fp->flag |= FA__WRITTEN;
  3559. if ( fp->fptr == 0 ) /* When set file size to zero, remove entire cluster chain */
  3560. {
  3561. res = remove_chain( fp->fs, fp->org_clust );
  3562. fp->org_clust = 0;
  3563. }
  3564. else /* When truncate a part of the file, remove remaining clusters */
  3565. {
  3566. ncl = get_fat( fp->fs, fp->curr_clust );
  3567. res = FR_OK;
  3568. if ( ncl == 0xFFFFFFFF )
  3569. {
  3570. res = FR_DISK_ERR;
  3571. }
  3572. if ( ncl == 1 )
  3573. {
  3574. res = FR_INT_ERR;
  3575. }
  3576. if ( res == FR_OK && ncl < fp->fs->n_fatent )
  3577. {
  3578. res = put_fat( fp->fs, fp->curr_clust, 0x0FFFFFFF );
  3579. if ( res == FR_OK )
  3580. {
  3581. res = remove_chain( fp->fs, ncl );
  3582. }
  3583. }
  3584. }
  3585. }
  3586. if ( res != FR_OK )
  3587. {
  3588. fp->flag |= FA__ERROR;
  3589. }
  3590. }
  3591. LEAVE_FF( fp->fs, res );
  3592. }
  3593. /*-----------------------------------------------------------------------*/
  3594. /* Delete a File or Directory */
  3595. /*-----------------------------------------------------------------------*/
  3596. FRESULT f_unlink (
  3597. const TCHAR *path /* Pointer to the file or directory path */
  3598. )
  3599. {
  3600. FRESULT res;
  3601. DIR dj, sdj;
  3602. BYTE *dir;
  3603. DWORD dclst;
  3604. DEF_NAMEBUF;
  3605. res = chk_mounted( &path, &dj.fs, 1 );
  3606. if ( res == FR_OK )
  3607. {
  3608. INIT_BUF( dj );
  3609. res = follow_path( &dj, path ); /* Follow the file path */
  3610. if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) )
  3611. {
  3612. res = FR_INVALID_NAME; /* Cannot remove dot entry */
  3613. }
  3614. #if _FS_SHARE
  3615. if ( res == FR_OK )
  3616. {
  3617. res = chk_lock( &dj, 2 ); /* Cannot remove open file */
  3618. }
  3619. #endif
  3620. if ( res == FR_OK ) /* The object is accessible */
  3621. {
  3622. dir = dj.dir;
  3623. if ( !dir )
  3624. {
  3625. res = FR_INVALID_NAME; /* Cannot remove the start directory */
  3626. }
  3627. else
  3628. {
  3629. if ( dir[DIR_Attr] & AM_RDO )
  3630. {
  3631. res = FR_DENIED; /* Cannot remove R/O object */
  3632. }
  3633. }
  3634. dclst = LD_CLUST( dir );
  3635. if ( res == FR_OK && ( dir[DIR_Attr] & AM_DIR ) ) /* Is it a sub-dir? */
  3636. {
  3637. if ( dclst < 2 )
  3638. {
  3639. res = FR_INT_ERR;
  3640. }
  3641. else
  3642. {
  3643. mem_cpy( &sdj, &dj, sizeof( DIR ) ); /* Check if the sub-dir is empty or not */
  3644. sdj.sclust = dclst;
  3645. res = dir_sdi( &sdj, 2 ); /* Exclude dot entries */
  3646. if ( res == FR_OK )
  3647. {
  3648. res = dir_read( &sdj );
  3649. if ( res == FR_OK /* Not empty dir */
  3650. #if _FS_RPATH
  3651. || dclst == sdj.fs->cdir /* Current dir */
  3652. #endif
  3653. )
  3654. {
  3655. res = FR_DENIED;
  3656. }
  3657. if ( res == FR_NO_FILE )
  3658. {
  3659. res = FR_OK; /* Empty */
  3660. }
  3661. }
  3662. }
  3663. }
  3664. if ( res == FR_OK )
  3665. {
  3666. res = dir_remove( &dj ); /* Remove the directory entry */
  3667. if ( res == FR_OK )
  3668. {
  3669. if ( dclst ) /* Remove the cluster chain if exist */
  3670. {
  3671. res = remove_chain( dj.fs, dclst );
  3672. }
  3673. if ( res == FR_OK )
  3674. {
  3675. res = sync( dj.fs );
  3676. }
  3677. }
  3678. }
  3679. }
  3680. FREE_BUF();
  3681. }
  3682. LEAVE_FF( dj.fs, res );
  3683. }
  3684. /*-----------------------------------------------------------------------*/
  3685. /* Create a Directory */
  3686. /*-----------------------------------------------------------------------*/
  3687. FRESULT f_mkdir (
  3688. const TCHAR *path /* Pointer to the directory path */
  3689. )
  3690. {
  3691. FRESULT res;
  3692. DIR dj;
  3693. BYTE *dir, n;
  3694. DWORD dsc, dcl, pcl, tim = get_fattime();
  3695. DEF_NAMEBUF;
  3696. res = chk_mounted( &path, &dj.fs, 1 );
  3697. if ( res == FR_OK )
  3698. {
  3699. INIT_BUF( dj );
  3700. res = follow_path( &dj, path ); /* Follow the file path */
  3701. if ( res == FR_OK )
  3702. {
  3703. res = FR_EXIST; /* Any object with same name is already existing */
  3704. }
  3705. if ( _FS_RPATH && res == FR_NO_FILE && ( dj.fn[NS] & NS_DOT ) )
  3706. {
  3707. res = FR_INVALID_NAME;
  3708. }
  3709. if ( res == FR_NO_FILE ) /* Can create a new directory */
  3710. {
  3711. dcl = create_chain( dj.fs, 0 ); /* Allocate a cluster for the new directory table */
  3712. res = FR_OK;
  3713. if ( dcl == 0 )
  3714. {
  3715. res = FR_DENIED; /* No space to allocate a new cluster */
  3716. }
  3717. if ( dcl == 1 )
  3718. {
  3719. res = FR_INT_ERR;
  3720. }
  3721. if ( dcl == 0xFFFFFFFF )
  3722. {
  3723. res = FR_DISK_ERR;
  3724. }
  3725. if ( res == FR_OK ) /* Flush FAT */
  3726. {
  3727. res = move_window( dj.fs, 0 );
  3728. }
  3729. if ( res == FR_OK ) /* Initialize the new directory table */
  3730. {
  3731. dsc = clust2sect( dj.fs, dcl );
  3732. dir = dj.fs->win;
  3733. mem_set( dir, 0, SS( dj.fs ) );
  3734. mem_set( dir + DIR_Name, ' ', 8 + 3 ); /* Create "." entry */
  3735. dir[DIR_Name] = '.';
  3736. dir[DIR_Attr] = AM_DIR;
  3737. ST_DWORD( dir + DIR_WrtTime, tim );
  3738. ST_CLUST( dir, dcl );
  3739. mem_cpy( dir + 32, dir, 32 ); /* Create ".." entry */
  3740. dir[33] = '.'; pcl = dj.sclust;
  3741. if ( dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase )
  3742. {
  3743. pcl = 0;
  3744. }
  3745. ST_CLUST( dir + 32, pcl );
  3746. for ( n = dj.fs->csize; n; n-- ) /* Write dot entries and clear following sectors */
  3747. {
  3748. dj.fs->winsect = dsc++;
  3749. dj.fs->wflag = 1;
  3750. res = move_window( dj.fs, 0 );
  3751. if ( res != FR_OK )
  3752. {
  3753. break;
  3754. }
  3755. mem_set( dir, 0, SS( dj.fs ) );
  3756. }
  3757. }
  3758. if ( res == FR_OK )
  3759. {
  3760. res = dir_register( &dj ); /* Register the object to the directoy */
  3761. }
  3762. if ( res != FR_OK )
  3763. {
  3764. remove_chain( dj.fs, dcl ); /* Could not register, remove cluster chain */
  3765. }
  3766. else
  3767. {
  3768. dir = dj.dir;
  3769. dir[DIR_Attr] = AM_DIR; /* Attribute */
  3770. ST_DWORD( dir + DIR_WrtTime, tim ); /* Created time */
  3771. ST_CLUST( dir, dcl ); /* Table start cluster */
  3772. dj.fs->wflag = 1;
  3773. res = sync( dj.fs );
  3774. }
  3775. }
  3776. FREE_BUF();
  3777. }
  3778. LEAVE_FF( dj.fs, res );
  3779. }
  3780. /*-----------------------------------------------------------------------*/
  3781. /* Change Attribute */
  3782. /*-----------------------------------------------------------------------*/
  3783. FRESULT f_chmod (
  3784. const TCHAR *path, /* Pointer to the file path */
  3785. BYTE value, /* Attribute bits */
  3786. BYTE mask /* Attribute mask to change */
  3787. )
  3788. {
  3789. FRESULT res;
  3790. DIR dj;
  3791. BYTE *dir;
  3792. DEF_NAMEBUF;
  3793. res = chk_mounted( &path, &dj.fs, 1 );
  3794. if ( res == FR_OK )
  3795. {
  3796. INIT_BUF( dj );
  3797. res = follow_path( &dj, path ); /* Follow the file path */
  3798. FREE_BUF();
  3799. if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) )
  3800. {
  3801. res = FR_INVALID_NAME;
  3802. }
  3803. if ( res == FR_OK )
  3804. {
  3805. dir = dj.dir;
  3806. if ( !dir ) /* Is it a root directory? */
  3807. {
  3808. res = FR_INVALID_NAME;
  3809. }
  3810. else /* File or sub directory */
  3811. {
  3812. mask &= AM_RDO | AM_HID | AM_SYS | AM_ARC; /* Valid attribute mask */
  3813. dir[DIR_Attr] = ( value & mask ) | ( dir[DIR_Attr] & ( BYTE )~mask ); /* Apply attribute change */
  3814. dj.fs->wflag = 1;
  3815. res = sync( dj.fs );
  3816. }
  3817. }
  3818. }
  3819. LEAVE_FF( dj.fs, res );
  3820. }
  3821. /*-----------------------------------------------------------------------*/
  3822. /* Change Timestamp */
  3823. /*-----------------------------------------------------------------------*/
  3824. FRESULT f_utime (
  3825. const TCHAR *path, /* Pointer to the file/directory name */
  3826. const FILINFO *fno /* Pointer to the time stamp to be set */
  3827. )
  3828. {
  3829. FRESULT res;
  3830. DIR dj;
  3831. BYTE *dir;
  3832. DEF_NAMEBUF;
  3833. res = chk_mounted( &path, &dj.fs, 1 );
  3834. if ( res == FR_OK )
  3835. {
  3836. INIT_BUF( dj );
  3837. res = follow_path( &dj, path ); /* Follow the file path */
  3838. FREE_BUF();
  3839. if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) )
  3840. {
  3841. res = FR_INVALID_NAME;
  3842. }
  3843. if ( res == FR_OK )
  3844. {
  3845. dir = dj.dir;
  3846. if ( !dir ) /* Root directory */
  3847. {
  3848. res = FR_INVALID_NAME;
  3849. }
  3850. else /* File or sub-directory */
  3851. {
  3852. ST_WORD( dir + DIR_WrtTime, fno->ftime );
  3853. ST_WORD( dir + DIR_WrtDate, fno->fdate );
  3854. dj.fs->wflag = 1;
  3855. res = sync( dj.fs );
  3856. }
  3857. }
  3858. }
  3859. LEAVE_FF( dj.fs, res );
  3860. }
  3861. /*-----------------------------------------------------------------------*/
  3862. /* Rename File/Directory */
  3863. /*-----------------------------------------------------------------------*/
  3864. FRESULT f_rename (
  3865. const TCHAR *path_old, /* Pointer to the old name */
  3866. const TCHAR *path_new /* Pointer to the new name */
  3867. )
  3868. {
  3869. FRESULT res;
  3870. DIR djo, djn;
  3871. BYTE buf[21], *dir;
  3872. DWORD dw;
  3873. DEF_NAMEBUF;
  3874. res = chk_mounted( &path_old, &djo.fs, 1 );
  3875. if ( res == FR_OK )
  3876. {
  3877. djn.fs = djo.fs;
  3878. INIT_BUF( djo );
  3879. res = follow_path( &djo, path_old ); /* Check old object */
  3880. if ( _FS_RPATH && res == FR_OK && ( djo.fn[NS] & NS_DOT ) )
  3881. {
  3882. res = FR_INVALID_NAME;
  3883. }
  3884. #if _FS_SHARE
  3885. if ( res == FR_OK )
  3886. {
  3887. res = chk_lock( &djo, 2 );
  3888. }
  3889. #endif
  3890. if ( res == FR_OK ) /* Old object is found */
  3891. {
  3892. if ( !djo.dir ) /* Is root dir? */
  3893. {
  3894. res = FR_NO_FILE;
  3895. }
  3896. else
  3897. {
  3898. mem_cpy( buf, djo.dir + DIR_Attr, 21 ); /* Save the object information except for name */
  3899. mem_cpy( &djn, &djo, sizeof( DIR ) ); /* Check new object */
  3900. res = follow_path( &djn, path_new );
  3901. if ( res == FR_OK )
  3902. {
  3903. res = FR_EXIST; /* The new object name is already existing */
  3904. }
  3905. if ( res == FR_NO_FILE ) /* Is it a valid path and no name collision? */
  3906. {
  3907. /* Start critical section that any interruption or error can cause cross-link */
  3908. res = dir_register( &djn ); /* Register the new entry */
  3909. if ( res == FR_OK )
  3910. {
  3911. dir = djn.dir; /* Copy object information except for name */
  3912. mem_cpy( dir + 13, buf + 2, 19 );
  3913. dir[DIR_Attr] = buf[0] | AM_ARC;
  3914. djo.fs->wflag = 1;
  3915. if ( djo.sclust != djn.sclust && ( dir[DIR_Attr] & AM_DIR ) ) /* Update .. entry in the directory if needed */
  3916. {
  3917. dw = clust2sect( djn.fs, LD_CLUST( dir ) );
  3918. if ( !dw )
  3919. {
  3920. res = FR_INT_ERR;
  3921. }
  3922. else
  3923. {
  3924. res = move_window( djn.fs, dw );
  3925. dir = djn.fs->win + 32; /* .. entry */
  3926. if ( res == FR_OK && dir[1] == '.' )
  3927. {
  3928. dw = ( djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase ) ? 0 : djn.sclust;
  3929. ST_CLUST( dir, dw );
  3930. djn.fs->wflag = 1;
  3931. }
  3932. }
  3933. }
  3934. if ( res == FR_OK )
  3935. {
  3936. res = dir_remove( &djo ); /* Remove old entry */
  3937. if ( res == FR_OK )
  3938. {
  3939. res = sync( djo.fs );
  3940. }
  3941. }
  3942. }
  3943. /* End critical section */
  3944. }
  3945. }
  3946. }
  3947. FREE_BUF();
  3948. }
  3949. LEAVE_FF( djo.fs, res );
  3950. }
  3951. #endif /* !_FS_READONLY */
  3952. #endif /* _FS_MINIMIZE == 0 */
  3953. #endif /* _FS_MINIMIZE <= 1 */
  3954. #endif /* _FS_MINIMIZE <= 2 */
  3955. /*-----------------------------------------------------------------------*/
  3956. /* Forward data to the stream directly (available on only tiny cfg) */
  3957. /*-----------------------------------------------------------------------*/
  3958. #if _USE_FORWARD && _FS_TINY
  3959. FRESULT f_forward (
  3960. FIL *fp, /* Pointer to the file object */
  3961. UINT ( *func )( const BYTE *, UINT ), /* Pointer to the streaming function */
  3962. UINT btr, /* Number of bytes to forward */
  3963. UINT *bf /* Pointer to number of bytes forwarded */
  3964. )
  3965. {
  3966. FRESULT res;
  3967. DWORD remain, clst, sect;
  3968. UINT rcnt;
  3969. BYTE csect;
  3970. *bf = 0; /* Initialize byte counter */
  3971. res = validate( fp->fs, fp->id ); /* Check validity of the object */
  3972. if ( res != FR_OK )
  3973. {
  3974. LEAVE_FF( fp->fs, res );
  3975. }
  3976. if ( fp->flag & FA__ERROR ) /* Check error flag */
  3977. {
  3978. LEAVE_FF( fp->fs, FR_INT_ERR );
  3979. }
  3980. if ( !( fp->flag & FA_READ ) ) /* Check access mode */
  3981. {
  3982. LEAVE_FF( fp->fs, FR_DENIED );
  3983. }
  3984. remain = fp->fsize - fp->fptr;
  3985. if ( btr > remain )
  3986. {
  3987. btr = ( UINT )remain; /* Truncate btr by remaining bytes */
  3988. }
  3989. for ( ; btr && ( *func )( 0, 0 ); /* Repeat until all data transferred or stream becomes busy */
  3990. fp->fptr += rcnt, *bf += rcnt, btr -= rcnt )
  3991. {
  3992. csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */
  3993. if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */
  3994. {
  3995. if ( !csect ) /* On the cluster boundary? */
  3996. {
  3997. clst = ( fp->fptr == 0 ) ? /* On the top of the file? */
  3998. fp->org_clust : get_fat( fp->fs, fp->curr_clust );
  3999. if ( clst <= 1 )
  4000. {
  4001. ABORT( fp->fs, FR_INT_ERR );
  4002. }
  4003. if ( clst == 0xFFFFFFFF )
  4004. {
  4005. ABORT( fp->fs, FR_DISK_ERR );
  4006. }
  4007. fp->curr_clust = clst; /* Update current cluster */
  4008. }
  4009. }
  4010. sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current data sector */
  4011. if ( !sect )
  4012. {
  4013. ABORT( fp->fs, FR_INT_ERR );
  4014. }
  4015. sect += csect;
  4016. if ( move_window( fp->fs, sect ) ) /* Move sector window */
  4017. {
  4018. ABORT( fp->fs, FR_DISK_ERR );
  4019. }
  4020. fp->dsect = sect;
  4021. rcnt = SS( fp->fs ) - ( WORD )( fp->fptr % SS( fp->fs ) ); /* Forward data from sector window */
  4022. if ( rcnt > btr )
  4023. {
  4024. rcnt = btr;
  4025. }
  4026. rcnt = ( *func )( &fp->fs->win[( WORD )fp->fptr % SS( fp->fs )], rcnt );
  4027. if ( !rcnt )
  4028. {
  4029. ABORT( fp->fs, FR_INT_ERR );
  4030. }
  4031. }
  4032. LEAVE_FF( fp->fs, FR_OK );
  4033. }
  4034. #endif /* _USE_FORWARD */
  4035. #if _USE_MKFS && !_FS_READONLY
  4036. /*-----------------------------------------------------------------------*/
  4037. /* Create File System on the Drive */
  4038. /*-----------------------------------------------------------------------*/
  4039. #define N_ROOTDIR 512 /* Multiple of 32 */
  4040. #define N_FATS 1 /* 1 or 2 */
  4041. FRESULT f_mkfs (
  4042. BYTE drv, /* Logical drive number */
  4043. BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */
  4044. UINT au /* Allocation unit size [bytes] */
  4045. )
  4046. {
  4047. static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
  4048. static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
  4049. BYTE fmt, md, *tbl;
  4050. DWORD n_clst, vs, n, wsect;
  4051. UINT i;
  4052. DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */
  4053. DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
  4054. FATFS *fs;
  4055. DSTATUS stat;
  4056. /* Check mounted drive and clear work area */
  4057. if ( drv >= _VOLUMES )
  4058. {
  4059. return FR_INVALID_DRIVE;
  4060. }
  4061. fs = FatFs[drv];
  4062. if ( !fs )
  4063. {
  4064. return FR_NOT_ENABLED;
  4065. }
  4066. fs->fs_type = 0;
  4067. drv = LD2PD( drv );
  4068. /* Get disk statics */
  4069. stat = disk_initialize( drv );
  4070. if ( stat & STA_NOINIT )
  4071. {
  4072. return FR_NOT_READY;
  4073. }
  4074. if ( stat & STA_PROTECT )
  4075. {
  4076. return FR_WRITE_PROTECTED;
  4077. }
  4078. #if _MAX_SS != 512 /* Get disk sector size */
  4079. if ( disk_ioctl( drv, GET_SECTOR_SIZE, &SS( fs ) ) != RES_OK )
  4080. {
  4081. return FR_DISK_ERR;
  4082. }
  4083. #endif
  4084. if ( disk_ioctl( drv, GET_SECTOR_COUNT, &n_vol ) != RES_OK || n_vol < 128 )
  4085. {
  4086. return FR_DISK_ERR;
  4087. }
  4088. b_vol = ( sfd ) ? 0 : 63; /* Volume start sector */
  4089. n_vol -= b_vol;
  4090. if ( au & ( au - 1 ) )
  4091. {
  4092. au = 0; /* Check validity of the allocation unit size */
  4093. }
  4094. if ( !au ) /* AU auto selection */
  4095. {
  4096. vs = n_vol / ( 2000 / ( SS( fs ) / 512 ) );
  4097. for ( i = 0; vs < vst[i]; i++ ) ;
  4098. au = cst[i];
  4099. }
  4100. au /= SS( fs ); /* Number of sectors per cluster */
  4101. if ( au == 0 )
  4102. {
  4103. au = 1;
  4104. }
  4105. if ( au > 128 )
  4106. {
  4107. au = 128;
  4108. }
  4109. /* Pre-compute number of clusters and FAT syb-type */
  4110. n_clst = n_vol / au;
  4111. fmt = FS_FAT12;
  4112. if ( n_clst >= MIN_FAT16 )
  4113. {
  4114. fmt = FS_FAT16;
  4115. }
  4116. if ( n_clst >= MIN_FAT32 )
  4117. {
  4118. fmt = FS_FAT32;
  4119. }
  4120. /* Determine offset and size of FAT structure */
  4121. if ( fmt == FS_FAT32 )
  4122. {
  4123. n_fat = ( ( n_clst * 4 ) + 8 + SS( fs ) - 1 ) / SS( fs );
  4124. n_rsv = 32;
  4125. n_dir = 0;
  4126. }
  4127. else
  4128. {
  4129. n_fat = ( fmt == FS_FAT12 ) ? ( n_clst * 3 + 1 ) / 2 + 3 : ( n_clst * 2 ) + 4;
  4130. n_fat = ( n_fat + SS( fs ) - 1 ) / SS( fs );
  4131. n_rsv = 1;
  4132. n_dir = N_ROOTDIR * 32UL / SS( fs );
  4133. }
  4134. b_fat = b_vol + n_rsv; /* FAT area start sector */
  4135. b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
  4136. b_data = b_dir + n_dir; /* Data area start sector */
  4137. if ( n_vol < b_data + au )
  4138. {
  4139. return FR_MKFS_ABORTED; /* Too small volume */
  4140. }
  4141. /* Align data start sector to erase block boundary (for flash memory media) */
  4142. if ( disk_ioctl( drv, GET_BLOCK_SIZE, &n ) != RES_OK || !n || n > 32768 )
  4143. {
  4144. n = 1;
  4145. }
  4146. n = ( b_data + n - 1 ) & ~( n - 1 ); /* Next nearest erase block from current data start */
  4147. n = ( n - b_data ) / N_FATS;
  4148. if ( fmt == FS_FAT32 ) /* FAT32: Move FAT offset */
  4149. {
  4150. n_rsv += n;
  4151. b_fat += n;
  4152. }
  4153. else /* FAT12/16: Expand FAT size */
  4154. {
  4155. n_fat += n;
  4156. }
  4157. /* Determine number of cluster and final check of validity of the FAT sub-type */
  4158. n_clst = ( n_vol - n_rsv - n_fat * N_FATS - n_dir ) / au;
  4159. if ( ( fmt == FS_FAT16 && n_clst < MIN_FAT16 )
  4160. || ( fmt == FS_FAT32 && n_clst < MIN_FAT32 ) )
  4161. {
  4162. return FR_MKFS_ABORTED;
  4163. }
  4164. /* Create partition table if required */
  4165. if ( sfd )
  4166. {
  4167. md = 0xF0;
  4168. }
  4169. else
  4170. {
  4171. DWORD n_disk = b_vol + n_vol;
  4172. mem_set( fs->win, 0, SS( fs ) );
  4173. tbl = fs->win + MBR_Table;
  4174. ST_DWORD( tbl, 0x00010180 ); /* Partition start in CHS */
  4175. if ( n_disk < 63UL * 255 * 1024 ) /* Partition end in CHS */
  4176. {
  4177. n_disk = n_disk / 63 / 255;
  4178. tbl[7] = ( BYTE )n_disk;
  4179. tbl[6] = ( BYTE )( ( n_disk >> 2 ) | 63 );
  4180. }
  4181. else
  4182. {
  4183. ST_WORD( &tbl[6], 0xFFFF );
  4184. }
  4185. tbl[5] = 254;
  4186. if ( fmt != FS_FAT32 ) /* System ID */
  4187. {
  4188. tbl[4] = ( n_vol < 0x10000 ) ? 0x04 : 0x06;
  4189. }
  4190. else
  4191. {
  4192. tbl[4] = 0x0c;
  4193. }
  4194. ST_DWORD( tbl + 8, 63 ); /* Partition start in LBA */
  4195. ST_DWORD( tbl + 12, n_vol ); /* Partition size in LBA */
  4196. ST_WORD( tbl + 64, 0xAA55 ); /* Signature */
  4197. if ( disk_write( drv, fs->win, 0, 1 ) != RES_OK )
  4198. {
  4199. return FR_DISK_ERR;
  4200. }
  4201. md = 0xF8;
  4202. }
  4203. /* Create volume boot record */
  4204. tbl = fs->win; /* Clear sector */
  4205. mem_set( tbl, 0, SS( fs ) );
  4206. mem_cpy( tbl, "\xEB\xFE\x90" "MSDOS5.0", 11 ); /* Boot code, OEM name */
  4207. i = SS( fs ); /* Sector size */
  4208. ST_WORD( tbl + BPB_BytsPerSec, i );
  4209. tbl[BPB_SecPerClus] = ( BYTE )au; /* Sectors per cluster */
  4210. ST_WORD( tbl + BPB_RsvdSecCnt, n_rsv ); /* Reserved sectors */
  4211. tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
  4212. i = ( fmt == FS_FAT32 ) ? 0 : N_ROOTDIR; /* Number of rootdir entries */
  4213. ST_WORD( tbl + BPB_RootEntCnt, i );
  4214. if ( n_vol < 0x10000 ) /* Number of total sectors */
  4215. {
  4216. ST_WORD( tbl + BPB_TotSec16, n_vol );
  4217. }
  4218. else
  4219. {
  4220. ST_DWORD( tbl + BPB_TotSec32, n_vol );
  4221. }
  4222. tbl[BPB_Media] = md; /* Media descriptor */
  4223. ST_WORD( tbl + BPB_SecPerTrk, 63 ); /* Number of sectors per track */
  4224. ST_WORD( tbl + BPB_NumHeads, 255 ); /* Number of heads */
  4225. ST_DWORD( tbl + BPB_HiddSec, b_vol ); /* Hidden sectors */
  4226. n = get_fattime(); /* Use current time as VSN */
  4227. if ( fmt == FS_FAT32 )
  4228. {
  4229. ST_DWORD( tbl + BS_VolID32, n ); /* VSN */
  4230. ST_DWORD( tbl + BPB_FATSz32, n_fat ); /* Number of sectors per FAT */
  4231. ST_DWORD( tbl + BPB_RootClus, 2 ); /* Root directory start cluster (2) */
  4232. ST_WORD( tbl + BPB_FSInfo, 1 ); /* FSInfo record offset (VBR+1) */
  4233. ST_WORD( tbl + BPB_BkBootSec, 6 ); /* Backup boot record offset (VBR+6) */
  4234. tbl[BS_DrvNum32] = 0x80; /* Drive number */
  4235. tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
  4236. mem_cpy( tbl + BS_VolLab32, "NO NAME " "FAT32 ", 19 ); /* Volume label, FAT signature */
  4237. }
  4238. else
  4239. {
  4240. ST_DWORD( tbl + BS_VolID, n ); /* VSN */
  4241. ST_WORD( tbl + BPB_FATSz16, n_fat ); /* Number of sectors per FAT */
  4242. tbl[BS_DrvNum] = 0x80; /* Drive number */
  4243. tbl[BS_BootSig] = 0x29; /* Extended boot signature */
  4244. mem_cpy( tbl + BS_VolLab, "NO NAME " "FAT ", 19 ); /* Volume label, FAT signature */
  4245. }
  4246. ST_WORD( tbl + BS_55AA, 0xAA55 ); /* Signature (Offset is fixed here regardless of sector size) */
  4247. if ( disk_write( drv, tbl, b_vol, 1 ) != RES_OK ) /* Write original (VBR) */
  4248. {
  4249. return FR_DISK_ERR;
  4250. }
  4251. if ( fmt == FS_FAT32 ) /* Write backup (VBR+6) */
  4252. {
  4253. disk_write( drv, tbl, b_vol + 6, 1 );
  4254. }
  4255. /* Initialize FAT area */
  4256. wsect = b_fat;
  4257. for ( i = 0; i < N_FATS; i++ )
  4258. {
  4259. mem_set( tbl, 0, SS( fs ) ); /* 1st sector of the FAT */
  4260. n = md; /* Media descriptor byte */
  4261. if ( fmt != FS_FAT32 )
  4262. {
  4263. n |= ( fmt == FS_FAT12 ) ? 0x00FFFF00 : 0xFFFFFF00;
  4264. ST_DWORD( tbl + 0, n ); /* Reserve cluster #0-1 (FAT12/16) */
  4265. }
  4266. else
  4267. {
  4268. n |= 0xFFFFFF00;
  4269. ST_DWORD( tbl + 0, n ); /* Reserve cluster #0-1 (FAT32) */
  4270. ST_DWORD( tbl + 4, 0xFFFFFFFF );
  4271. ST_DWORD( tbl + 8, 0x0FFFFFFF ); /* Reserve cluster #2 for root dir */
  4272. }
  4273. if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK )
  4274. {
  4275. return FR_DISK_ERR;
  4276. }
  4277. mem_set( tbl, 0, SS( fs ) ); /* Fill following FAT entries with zero */
  4278. for ( n = 1; n < n_fat; n++ ) /* This loop may take a time on FAT32 volume due to many single sector write */
  4279. {
  4280. if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK )
  4281. {
  4282. return FR_DISK_ERR;
  4283. }
  4284. }
  4285. }
  4286. /* Initialize root directory */
  4287. i = ( fmt == FS_FAT32 ) ? au : n_dir;
  4288. do
  4289. {
  4290. if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK )
  4291. {
  4292. return FR_DISK_ERR;
  4293. }
  4294. }
  4295. while ( --i );
  4296. #if _USE_ERASE /* Erase data area if needed */
  4297. {
  4298. DWORD eb[2];
  4299. eb[0] = wsect; eb[1] = wsect + n_clst * au - 1;
  4300. disk_ioctl( drv, CTRL_ERASE_SECTOR, eb );
  4301. }
  4302. #endif
  4303. /* Create FSInfo if needed */
  4304. if ( fmt == FS_FAT32 )
  4305. {
  4306. ST_WORD( tbl + BS_55AA, 0xAA55 );
  4307. ST_DWORD( tbl + FSI_LeadSig, 0x41615252 );
  4308. ST_DWORD( tbl + FSI_StrucSig, 0x61417272 );
  4309. ST_DWORD( tbl + FSI_Free_Count, n_clst - 1 );
  4310. ST_DWORD( tbl + FSI_Nxt_Free, 0xFFFFFFFF );
  4311. disk_write( drv, tbl, b_vol + 1, 1 ); /* Write original (VBR+1) */
  4312. disk_write( drv, tbl, b_vol + 7, 1 ); /* Write backup (VBR+7) */
  4313. }
  4314. return ( disk_ioctl( drv, CTRL_SYNC, ( void * )0 ) == RES_OK ) ? FR_OK : FR_DISK_ERR;
  4315. }
  4316. #endif /* _USE_MKFS && !_FS_READONLY */
  4317. #if _USE_STRFUNC
  4318. /*-----------------------------------------------------------------------*/
  4319. /* Get a string from the file */
  4320. /*-----------------------------------------------------------------------*/
  4321. TCHAR *f_gets (
  4322. TCHAR *buff, /* Pointer to the string buffer to read */
  4323. int len, /* Size of string buffer (characters) */
  4324. FIL *fil /* Pointer to the file object */
  4325. )
  4326. {
  4327. int n = 0;
  4328. TCHAR c, *p = buff;
  4329. BYTE s[2];
  4330. UINT rc;
  4331. while ( n < len - 1 ) /* Read bytes until buffer gets filled */
  4332. {
  4333. f_read( fil, s, 1, &rc );
  4334. if ( rc != 1 )
  4335. {
  4336. break; /* Break on EOF or error */
  4337. }
  4338. c = s[0];
  4339. #if _LFN_UNICODE /* Read a character in UTF-8 encoding */
  4340. if ( c >= 0x80 )
  4341. {
  4342. if ( c < 0xC0 )
  4343. {
  4344. continue; /* Skip stray trailer */
  4345. }
  4346. if ( c < 0xE0 ) /* Two-byte sequense */
  4347. {
  4348. f_read( fil, s, 1, &rc );
  4349. if ( rc != 1 )
  4350. {
  4351. break;
  4352. }
  4353. c = ( ( c & 0x1F ) << 6 ) | ( s[0] & 0x3F );
  4354. if ( c < 0x80 )
  4355. {
  4356. c = '?';
  4357. }
  4358. }
  4359. else
  4360. {
  4361. if ( c < 0xF0 ) /* Three-byte sequense */
  4362. {
  4363. f_read( fil, s, 2, &rc );
  4364. if ( rc != 2 )
  4365. {
  4366. break;
  4367. }
  4368. c = ( c << 12 ) | ( ( s[0] & 0x3F ) << 6 ) | ( s[1] & 0x3F );
  4369. if ( c < 0x800 )
  4370. {
  4371. c = '?';
  4372. }
  4373. }
  4374. else /* Reject four-byte sequense */
  4375. {
  4376. c = '?';
  4377. }
  4378. }
  4379. }
  4380. #endif
  4381. #if _USE_STRFUNC >= 2
  4382. if ( c == '\r' )
  4383. {
  4384. continue; /* Strip '\r' */
  4385. }
  4386. #endif
  4387. *p++ = c;
  4388. n++;
  4389. if ( c == '\n' )
  4390. {
  4391. break; /* Break on EOL */
  4392. }
  4393. if ( c == 0 )
  4394. {
  4395. break; /* Break on NUL */
  4396. }
  4397. }
  4398. *p = 0;
  4399. return n ? buff : 0; /* When no data read (eof or error), return with error. */
  4400. }
  4401. #if !_FS_READONLY
  4402. #include <stdarg.h>
  4403. /*-----------------------------------------------------------------------*/
  4404. /* Put a character to the file */
  4405. /*-----------------------------------------------------------------------*/
  4406. int f_putc (
  4407. TCHAR c, /* A character to be output */
  4408. FIL *fil /* Pointer to the file object */
  4409. )
  4410. {
  4411. UINT bw, btw;
  4412. BYTE s[3];
  4413. #if _USE_STRFUNC >= 2
  4414. if ( c == '\n' )
  4415. {
  4416. f_putc ( '\r', fil ); /* LF -> CRLF conversion */
  4417. }
  4418. #endif
  4419. #if _LFN_UNICODE /* Write the character in UTF-8 encoding */
  4420. if ( c < 0x80 ) /* 7-bit */
  4421. {
  4422. s[0] = ( BYTE )c;
  4423. btw = 1;
  4424. }
  4425. else
  4426. {
  4427. if ( c < 0x800 ) /* 11-bit */
  4428. {
  4429. s[0] = ( BYTE )( 0xC0 | ( c >> 6 ) );
  4430. s[1] = ( BYTE )( 0x80 | ( c & 0x3F ) );
  4431. btw = 2;
  4432. }
  4433. else /* 16-bit */
  4434. {
  4435. s[0] = ( BYTE )( 0xE0 | ( c >> 12 ) );
  4436. s[1] = ( BYTE )( 0x80 | ( ( c >> 6 ) & 0x3F ) );
  4437. s[2] = ( BYTE )( 0x80 | ( c & 0x3F ) );
  4438. btw = 3;
  4439. }
  4440. }
  4441. #else /* Write the character without conversion */
  4442. s[0] = ( BYTE )c;
  4443. btw = 1;
  4444. #endif
  4445. f_write( fil, s, btw, &bw ); /* Write the char to the file */
  4446. return ( bw == btw ) ? 1 : EOF; /* Return the result */
  4447. }
  4448. /*-----------------------------------------------------------------------*/
  4449. /* Put a string to the file */
  4450. /*-----------------------------------------------------------------------*/
  4451. int f_puts (
  4452. const TCHAR *str, /* Pointer to the string to be output */
  4453. FIL *fil /* Pointer to the file object */
  4454. )
  4455. {
  4456. int n;
  4457. for ( n = 0; *str; str++, n++ )
  4458. {
  4459. if ( f_putc( *str, fil ) == EOF )
  4460. {
  4461. return EOF;
  4462. }
  4463. }
  4464. return n;
  4465. }
  4466. /*-----------------------------------------------------------------------*/
  4467. /* Put a formatted string to the file */
  4468. /*-----------------------------------------------------------------------*/
  4469. int f_printf (
  4470. FIL *fil, /* Pointer to the file object */
  4471. const TCHAR *str, /* Pointer to the format string */
  4472. ... /* Optional arguments... */
  4473. )
  4474. {
  4475. va_list arp;
  4476. BYTE f, r;
  4477. UINT i, w;
  4478. ULONG val;
  4479. TCHAR c, d, s[16];
  4480. int res, cc;
  4481. va_start( arp, str );
  4482. for ( cc = res = 0; cc != EOF; res += cc )
  4483. {
  4484. c = *str++;
  4485. if ( c == 0 )
  4486. {
  4487. break; /* End of string */
  4488. }
  4489. if ( c != '%' ) /* Non escape character */
  4490. {
  4491. cc = f_putc( c, fil );
  4492. if ( cc != EOF )
  4493. {
  4494. cc = 1;
  4495. }
  4496. continue;
  4497. }
  4498. w = f = 0;
  4499. c = *str++;
  4500. if ( c == '0' ) /* Flag: '0' padding */
  4501. {
  4502. f = 1; c = *str++;
  4503. }
  4504. while ( IsDigit( c ) ) /* Precision */
  4505. {
  4506. w = w * 10 + c - '0';
  4507. c = *str++;
  4508. }
  4509. if ( c == 'l' || c == 'L' ) /* Prefix: Size is long int */
  4510. {
  4511. f |= 2; c = *str++;
  4512. }
  4513. if ( !c )
  4514. {
  4515. break;
  4516. }
  4517. d = c;
  4518. if ( IsLower( d ) )
  4519. {
  4520. d -= 0x20;
  4521. }
  4522. switch ( d ) /* Type is... */
  4523. {
  4524. case 'S' : /* String */
  4525. cc = f_puts( va_arg( arp, TCHAR * ), fil ); continue;
  4526. case 'C' : /* Character */
  4527. cc = f_putc( ( TCHAR )va_arg( arp, int ), fil ); continue;
  4528. case 'B' : /* Binary */
  4529. r = 2; break;
  4530. case 'O' : /* Octal */
  4531. r = 8; break;
  4532. case 'D' : /* Signed decimal */
  4533. case 'U' : /* Unsigned decimal */
  4534. r = 10; break;
  4535. case 'X' : /* Hexdecimal */
  4536. r = 16; break;
  4537. default: /* Unknown */
  4538. cc = f_putc( c, fil ); continue;
  4539. }
  4540. /* Get an argument */
  4541. val = ( f & 2 ) ? va_arg( arp, long ) : ( ( d == 'D' ) ? ( long )va_arg( arp, int ) : va_arg( arp, unsigned int ) );
  4542. if ( d == 'D' && ( val & 0x80000000 ) )
  4543. {
  4544. val = 0 - val;
  4545. f |= 4;
  4546. }
  4547. /* Put it in numeral string */
  4548. i = 0;
  4549. do
  4550. {
  4551. d = ( TCHAR )( val % r ); val /= r;
  4552. if ( d > 9 )
  4553. {
  4554. d += 7;
  4555. if ( c == 'x' )
  4556. {
  4557. d += 0x20;
  4558. }
  4559. }
  4560. s[i++] = d + '0';
  4561. }
  4562. while ( val && i < sizeof( s ) / sizeof( s[0] ) );
  4563. if ( f & 4 )
  4564. {
  4565. s[i++] = '-';
  4566. }
  4567. cc = 0;
  4568. while ( i < w-- && cc != EOF )
  4569. {
  4570. cc = f_putc( ( TCHAR )( ( f & 1 ) ? '0' : ' ' ), fil );
  4571. res++;
  4572. }
  4573. do
  4574. {
  4575. cc = f_putc( s[--i], fil );
  4576. res++;
  4577. }
  4578. while ( i && cc != EOF );
  4579. if ( cc != EOF )
  4580. {
  4581. cc = 0;
  4582. }
  4583. }
  4584. va_end( arp );
  4585. return ( cc == EOF ) ? cc : res;
  4586. }
  4587. #endif /* !_FS_READONLY */
  4588. #endif /* _USE_STRFUNC */