38#define MAX_DIR 0x200000
39#define MAX_DIR_EX 0x10000000
40#define MAX_FAT12 0xFF5
41#define MAX_FAT16 0xFFF5
42#define MAX_FAT32 0x0FFFFFF5
43#define MAX_EXFAT 0x7FFFFFFD
47#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
48#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
49#define IsDigit(c) ((c) >= '0' && (c) <= '9')
50#define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF)
51#define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF)
52#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
56#define FA_SEEKEND 0x20
57#define FA_MODIFIED 0x40
83#define ET_FILEDIR 0x85
85#define ET_FILENAME 0xC1
93#define BPB_BytsPerSec 11
94#define BPB_SecPerClus 13
95#define BPB_RsvdSecCnt 14
97#define BPB_RootEntCnt 17
98#define BPB_TotSec16 19
100#define BPB_FATSz16 22
101#define BPB_SecPerTrk 24
102#define BPB_NumHeads 26
103#define BPB_HiddSec 28
104#define BPB_TotSec32 32
110#define BS_FilSysType 54
111#define BS_BootCode 62
114#define BPB_FATSz32 36
115#define BPB_ExtFlags32 40
116#define BPB_FSVer32 42
117#define BPB_RootClus32 44
118#define BPB_FSInfo32 48
119#define BPB_BkBootSec32 50
120#define BS_DrvNum32 64
122#define BS_BootSig32 66
124#define BS_VolLab32 71
125#define BS_FilSysType32 82
126#define BS_BootCode32 90
128#define BPB_ZeroedEx 11
129#define BPB_VolOfsEx 64
130#define BPB_TotSecEx 72
131#define BPB_FatOfsEx 80
132#define BPB_FatSzEx 84
133#define BPB_DataOfsEx 88
134#define BPB_NumClusEx 92
135#define BPB_RootClusEx 96
136#define BPB_VolIDEx 100
137#define BPB_FSVerEx 104
138#define BPB_VolFlagEx 106
139#define BPB_BytsPerSecEx 108
140#define BPB_SecPerClusEx 109
141#define BPB_NumFATsEx 110
142#define BPB_DrvNumEx 111
143#define BPB_PercInUseEx 112
144#define BPB_RsvdEx 113
145#define BS_BootCodeEx 120
150#define DIR_CrtTime10 13
151#define DIR_CrtTime 14
152#define DIR_LstAccDate 18
153#define DIR_FstClusHI 20
154#define DIR_ModTime 22
155#define DIR_FstClusLO 26
156#define DIR_FileSize 28
160#define LDIR_Chksum 13
161#define LDIR_FstClusLO 26
163#define XDIR_NumLabel 1
165#define XDIR_CaseSum 4
169#define XDIR_CrtTime 8
170#define XDIR_ModTime 12
171#define XDIR_AccTime 16
172#define XDIR_CrtTime10 20
173#define XDIR_ModTime10 21
177#define XDIR_GenFlags 33
178#define XDIR_NumName 35
179#define XDIR_NameHash 36
180#define XDIR_ValidFileSize 40
181#define XDIR_FstClus 52
182#define XDIR_FileSize 56
189#define FSI_StrucSig 484
190#define FSI_Free_Count 488
191#define FSI_Nxt_Free 492
210#define GPTH_CurLba 24
211#define GPTH_BakLba 32
212#define GPTH_FstLba 40
213#define GPTH_LstLba 48
214#define GPTH_DskGuid 56
217#define GPTH_PteSize 84
221#define GPTE_UpGuid 16
222#define GPTE_FstLba 32
223#define GPTE_LstLba 40
229#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
235#error Static LFN work area cannot be used at thread-safe configuration
237#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
239#define LEAVE_FF(fs, res) return res
244#if FF_MULTI_PARTITION
245#define LD2PD(vol) VolToPart[vol].pd
246#define LD2PT(vol) VolToPart[vol].pt
248#define LD2PD(vol) (BYTE)(vol)
254#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096)
255#error Wrong sector size configuration
257#if FF_MAX_SS == FF_MIN_SS
258#define SS(fs) ((UINT)FF_MAX_SS)
260#define SS(fs) ((fs)->ssize)
266#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31
267#error Invalid FF_FS_NORTC settings
269#define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16)
271#define GET_FATTIME() get_fattime()
277#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
278 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
279 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
280 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
281 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
282 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
283 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
284 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
285#define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
286 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
287 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
288 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
289 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
290 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
291 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
292 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
293#define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
294 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
295 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \
296 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
297 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
298 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
299 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
300 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
301#define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
302 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
303 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
304 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
305 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
306 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \
307 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
308 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF}
309#define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \
310 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
311 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
312 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
313 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
314 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
315 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \
316 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
317#define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \
318 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \
319 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
320 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
321 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
322 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \
323 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \
324 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
325#define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \
326 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \
327 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \
328 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
329 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
330 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
331 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \
332 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
333#define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \
334 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
335 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \
336 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
337 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
338 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
339 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \
340 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
341#define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \
342 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
343 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
344 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
345 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
346 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
347 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \
348 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
349#define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \
350 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
351 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
352 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
353 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
354 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
355 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
356 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
357#define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \
358 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
359 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
360 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
361 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
362 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
363 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
364 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
365#define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
366 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
367 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
368 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
369 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
370 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
371 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
372 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
373#define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \
374 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \
375 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
376 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
377 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
378 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
379 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
380 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
381#define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
382 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
383 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
384 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
385 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
386 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
387 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
388 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
389#define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
390 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
391 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
392 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
393 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
394 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
395 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
396 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
397#define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
398 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
399 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
400 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
401 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
402 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
403 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
404 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
405#define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
406 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \
407 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
408 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
409 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
410 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \
411 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \
412 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF}
417#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00}
418#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00}
419#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE}
420#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00}
424#define MERGE_2STR(a, b) a ## b
425#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp)
444#define CODEPAGE CodePage
446static const BYTE* ExCvt;
447static const BYTE* DbcTbl;
449static const BYTE Ct437[] = TBL_CT437;
450static const BYTE Ct720[] = TBL_CT720;
451static const BYTE Ct737[] = TBL_CT737;
452static const BYTE Ct771[] = TBL_CT771;
453static const BYTE Ct775[] = TBL_CT775;
454static const BYTE Ct850[] = TBL_CT850;
455static const BYTE Ct852[] = TBL_CT852;
456static const BYTE Ct855[] = TBL_CT855;
457static const BYTE Ct857[] = TBL_CT857;
458static const BYTE Ct860[] = TBL_CT860;
459static const BYTE Ct861[] = TBL_CT861;
460static const BYTE Ct862[] = TBL_CT862;
461static const BYTE Ct863[] = TBL_CT863;
462static const BYTE Ct864[] = TBL_CT864;
463static const BYTE Ct865[] = TBL_CT865;
464static const BYTE Ct866[] = TBL_CT866;
465static const BYTE Ct869[] = TBL_CT869;
466static const BYTE Dc932[] = TBL_DC932;
467static const BYTE Dc936[] = TBL_DC936;
468static const BYTE Dc949[] = TBL_DC949;
469static const BYTE Dc950[] = TBL_DC950;
471#elif FF_CODE_PAGE < 900
472#define CODEPAGE FF_CODE_PAGE
473static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE);
476#define CODEPAGE FF_CODE_PAGE
477static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE);
494static WORD ld_word (
const BYTE* ptr)
499 rv = rv << 8 | ptr[0];
503static DWORD ld_dword (
const BYTE* ptr)
508 rv = rv << 8 | ptr[2];
509 rv = rv << 8 | ptr[1];
510 rv = rv << 8 | ptr[0];
515static QWORD ld_qword (
const BYTE* ptr)
520 rv = rv << 8 | ptr[6];
521 rv = rv << 8 | ptr[5];
522 rv = rv << 8 | ptr[4];
523 rv = rv << 8 | ptr[3];
524 rv = rv << 8 | ptr[2];
525 rv = rv << 8 | ptr[1];
526 rv = rv << 8 | ptr[0];
532static void st_word (BYTE* ptr, WORD val)
534 *ptr++ = (BYTE)val; val >>= 8;
538static void st_dword (BYTE* ptr, DWORD val)
540 *ptr++ = (BYTE)val; val >>= 8;
541 *ptr++ = (BYTE)val; val >>= 8;
542 *ptr++ = (BYTE)val; val >>= 8;
547static void st_qword (BYTE* ptr, QWORD val)
549 *ptr++ = (BYTE)val; val >>= 8;
550 *ptr++ = (BYTE)val; val >>= 8;
551 *ptr++ = (BYTE)val; val >>= 8;
552 *ptr++ = (BYTE)val; val >>= 8;
553 *ptr++ = (BYTE)val; val >>= 8;
554 *ptr++ = (BYTE)val; val >>= 8;
555 *ptr++ = (BYTE)val; val >>= 8;
568static void mem_cpy (
void* dst,
const void* src, UINT cnt)
570 BYTE *d = (BYTE*)dst;
571 const BYTE *s = (
const BYTE*)src;
582static void mem_set (
void* dst,
int val, UINT cnt)
584 BYTE *d = (BYTE*)dst;
593static int mem_cmp (
const void* dst,
const void* src, UINT cnt)
595 const BYTE *d = (
const BYTE *)dst, *s = (
const BYTE *)src;
600 }
while (--cnt && r == 0);
607static int chk_chr (
const char* str,
int chr)
609 while (*str && *str != chr) str++;
615static int dbc_1st (BYTE c)
618 if (DbcTbl && c >= DbcTbl[0]) {
619 if (c <= DbcTbl[1])
return 1;
620 if (c >= DbcTbl[2] && c <= DbcTbl[3])
return 1;
622#elif FF_CODE_PAGE >= 900
623 if (c >= DbcTbl[0]) {
624 if (c <= DbcTbl[1])
return 1;
625 if (c >= DbcTbl[2] && c <= DbcTbl[3])
return 1;
628 if (c != 0)
return 0;
635static int dbc_2nd (BYTE c)
638 if (DbcTbl && c >= DbcTbl[4]) {
639 if (c <= DbcTbl[5])
return 1;
640 if (c >= DbcTbl[6] && c <= DbcTbl[7])
return 1;
641 if (c >= DbcTbl[8] && c <= DbcTbl[9])
return 1;
643#elif FF_CODE_PAGE >= 900
644 if (c >= DbcTbl[4]) {
645 if (c <= DbcTbl[5])
return 1;
646 if (c >= DbcTbl[6] && c <= DbcTbl[7])
return 1;
647 if (c >= DbcTbl[8] && c <= DbcTbl[9])
return 1;
650 if (c != 0)
return 0;
659static DWORD tchar2uni (
664 const TCHAR *p = *str;
666#if FF_LFN_UNICODE == 1
670 if (IsSurrogate(uc)) {
672 if (!IsSurrogateH(uc) || !IsSurrogateL(wc))
return 0xFFFFFFFF;
676#elif FF_LFN_UNICODE == 2
682 if ((uc & 0xE0) == 0xC0) {
685 if ((uc & 0xF0) == 0xE0) {
688 if ((uc & 0xF8) == 0xF0) {
697 if ((b & 0xC0) != 0x80)
return 0xFFFFFFFF;
698 uc = uc << 6 | (b & 0x3F);
700 if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000)
return 0xFFFFFFFF;
701 if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF);
704#elif FF_LFN_UNICODE == 3
706 if (uc >= 0x110000 || IsSurrogate(uc))
return 0xFFFFFFFF;
707 if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF);
714 if (dbc_1st((BYTE)wc)) {
716 if (!dbc_2nd(b))
return 0xFFFFFFFF;
720 wc = ff_oem2uni(wc, CODEPAGE);
721 if (wc == 0)
return 0xFFFFFFFF;
738#if FF_LFN_UNICODE == 1
741 hs = (WCHAR)(chr >> 16);
744 if (szb < 1 || IsSurrogate(wc))
return 0;
748 if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc))
return 0;
753#elif FF_LFN_UNICODE == 2
757 if (szb < 1)
return 0;
762 if (szb < 2)
return 0;
763 *buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F));
764 *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
768 if (szb < 3 || IsSurrogate(chr))
return 0;
769 *buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F));
770 *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F));
771 *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
775 if (szb < 4)
return 0;
776 hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6;
777 chr = (chr & 0xFFFF) - 0xDC00;
778 if (hc >= 0x100000 || chr >= 0x400)
return 0;
779 chr = (hc | chr) + 0x10000;
780 *buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07));
781 *buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F));
782 *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F));
783 *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
786#elif FF_LFN_UNICODE == 3
789 if (szb < 1)
return 0;
790 if (chr >= 0x10000) {
791 hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6;
792 chr = (chr & 0xFFFF) - 0xDC00;
793 if (hc >= 0x100000 || chr >= 0x400)
return 0;
794 chr = (hc | chr) + 0x10000;
802 wc = ff_uni2oem(chr, CODEPAGE);
804 if (szb < 2)
return 0;
805 *buf++ = (char)(wc >> 8);
809 if (wc == 0 || szb < 1)
return 0;
825 return ff_req_grant(fs->sobj);
829static void unlock_fs (
834 if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) {
835 ff_rel_grant(fs->sobj);
848 FRESULT FatFs::chk_lock (
857 for (i = 0; i < FF_FS_LOCK; i++) {
859 if (Files[i].fs == dp->obj.fs &&
860 Files[i].clu == dp->obj.sclust &&
861 Files[i].ofs == dp->dptr)
break;
866 if (i == FF_FS_LOCK) {
867 return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK;
871 return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
875 int FatFs::enq_lock (
void)
879 for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
880 return (i == FF_FS_LOCK) ? 0 : 1;
884 UINT FatFs::inc_lock (
892 for (i = 0; i < FF_FS_LOCK; i++) {
893 if (Files[i].fs == dp->obj.fs
894 && Files[i].clu == dp->obj.sclust
895 && Files[i].ofs == dp->dptr)
break;
898 if (i == FF_FS_LOCK) {
899 for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
900 if (i == FF_FS_LOCK)
return 0;
901 Files[i].fs = dp->obj.fs;
902 Files[i].clu = dp->obj.sclust;
903 Files[i].ofs = dp->dptr;
907 if (acc >= 1 && Files[i].ctr)
return 0;
909 Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1;
915 FRESULT FatFs::dec_lock (
923 if (--i < FF_FS_LOCK) {
925 if (n == 0x100) n = 0;
928 if (n == 0) Files[i].fs = 0;
943 for (i = 0; i < FF_FS_LOCK; i++) {
944 if (Files[i].fs == fs) Files[i].fs = 0;
956FRESULT FatFs::sync_window (
964 if (
p_io->disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) {
966 if (fs->winsect - fs->fatbase < fs->fsize) {
967 if (fs->n_fats == 2)
p_io->disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1);
978FRESULT FatFs::move_window (
986 if (sect != fs->winsect) {
988 res = sync_window(fs);
991 if (
p_io->disk_read(fs->pdrv, fs->win, sect, 1) != RES_OK) {
1009FRESULT FatFs::sync_fs (
1016 res = sync_window(fs);
1018 if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {
1020 mem_set(fs->win, 0,
sizeof fs->win);
1021 st_word(fs->win + BS_55AA, 0xAA55);
1022 st_dword(fs->win + FSI_LeadSig, 0x41615252);
1023 st_dword(fs->win + FSI_StrucSig, 0x61417272);
1024 st_dword(fs->win + FSI_Free_Count, fs->free_clst);
1025 st_dword(fs->win + FSI_Nxt_Free, fs->last_clst);
1027 fs->winsect = fs->volbase + 1;
1028 p_io->disk_write(fs->pdrv, fs->win, fs->winsect, 1);
1032 if (
p_io->disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR;
1046static LBA_t clst2sect (
1052 if (clst >= fs->n_fatent - 2)
return 0;
1053 return fs->database + (LBA_t)fs->csize * clst;
1063 DWORD FatFs::get_fat (
1070 FATFS *fs = obj->fs;
1073 if (clst < 2 || clst >= fs->n_fatent) {
1079 switch (fs->fs_type) {
1081 bc = (UINT)clst; bc += bc / 2;
1082 if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK)
break;
1083 wc = fs->win[bc++ % SS(fs)];
1084 if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK)
break;
1085 wc |= fs->win[bc % SS(fs)] << 8;
1086 val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
1090 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK)
break;
1091 val = ld_word(fs->win + clst * 2 % SS(fs));
1095 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK)
break;
1096 val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF;
1100 if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) {
1101 DWORD cofs = clst - obj->sclust;
1102 DWORD clen = (DWORD)((LBA_t)((obj->objsize - 1) / SS(fs)) / fs->csize);
1104 if (obj->stat == 2 && cofs <= clen) {
1105 val = (cofs == clen) ? 0x7FFFFFFF : clst + 1;
1108 if (obj->stat == 3 && cofs < obj->n_cont) {
1112 if (obj->stat != 2) {
1113 if (obj->n_frag != 0) {
1116 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK)
break;
1117 val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF;
1140FRESULT FatFs::put_fat (
1148 FRESULT res = FR_INT_ERR;
1151 if (clst >= 2 && clst < fs->n_fatent) {
1152 switch (fs->fs_type) {
1154 bc = (UINT)clst; bc += bc / 2;
1155 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
1156 if (res != FR_OK)
break;
1157 p = fs->win + bc++ % SS(fs);
1158 *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
1160 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
1161 if (res != FR_OK)
break;
1162 p = fs->win + bc % SS(fs);
1163 *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
1168 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
1169 if (res != FR_OK)
break;
1170 st_word(fs->win + clst * 2 % SS(fs), (WORD)val);
1178 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
1179 if (res != FR_OK)
break;
1180 if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
1181 val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000);
1183 st_dword(fs->win + clst * 4 % SS(fs), val);
1196#if FF_FS_EXFAT && !FF_FS_READONLY
1205DWORD FatFs::find_bitmap (
1213 DWORD val, scl, ctr;
1217 if (clst >= fs->n_fatent - 2) clst = 0;
1218 scl = val = clst; ctr = 0;
1220 if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK)
return 0xFFFFFFFF;
1221 i = val / 8 % SS(fs); bm = 1 << (val % 8);
1224 bv = fs->win[i] & bm; bm <<= 1;
1225 if (++val >= fs->n_fatent - 2) {
1226 val = 0; bm = 0; i = SS(fs);
1229 if (++ctr == ncl)
return scl + 2;
1233 if (val == clst)
return 0;
1236 }
while (++i < SS(fs));
1245FRESULT FatFs::change_bitmap (
1258 sect = fs->bitbase + clst / 8 / SS(fs);
1259 i = clst / 8 % SS(fs);
1260 bm = 1 << (clst % 8);
1262 if (move_window(fs, sect++) != FR_OK)
return FR_DISK_ERR;
1265 if (bv == (
int)((fs->win[i] & bm) != 0))
return FR_INT_ERR;
1268 if (--ncl == 0)
return FR_OK;
1271 }
while (++i < SS(fs));
1281 FRESULT FatFs::fill_first_frag (
1289 if (obj->stat == 3) {
1290 for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) {
1291 res = put_fat(obj->fs, cl, cl + 1);
1292 if (res != FR_OK)
return res;
1304 FRESULT FatFs::fill_last_frag (
1313 while (obj->n_frag > 0) {
1314 res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term);
1315 if (res != FR_OK)
return res;
1330 FRESULT FatFs::remove_chain (
1336 FRESULT res = FR_OK;
1338 FATFS *fs = obj->fs;
1339#if FF_FS_EXFAT || FF_USE_TRIM
1340 DWORD scl = clst, ecl = clst;
1346 if (clst < 2 || clst >= fs->n_fatent)
return FR_INT_ERR;
1349 if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) {
1350 res = put_fat(fs, pclst, 0xFFFFFFFF);
1351 if (res != FR_OK)
return res;
1356 nxt = get_fat(obj, clst);
1357 if (nxt == 0)
break;
1358 if (nxt == 1)
return FR_INT_ERR;
1359 if (nxt == 0xFFFFFFFF)
return FR_DISK_ERR;
1360 if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
1361 res = put_fat(fs, clst, 0);
1362 if (res != FR_OK)
return res;
1364 if (fs->free_clst < fs->n_fatent - 2) {
1368#if FF_FS_EXFAT || FF_USE_TRIM
1369 if (ecl + 1 == nxt) {
1373 if (fs->fs_type == FS_EXFAT) {
1374 res = change_bitmap(fs, scl, ecl - scl + 1, 0);
1375 if (res != FR_OK)
return res;
1379 rt[0] = clst2sect(fs, scl);
1380 rt[1] = clst2sect(fs, ecl) + fs->csize - 1;
1381 p_io->disk_ioctl(fs->pdrv, CTRL_TRIM, rt);
1387 }
while (clst < fs->n_fatent);
1391 if (fs->fs_type == FS_EXFAT) {
1395 if (obj->stat == 0) {
1397 while (clst != pclst) {
1398 nxt = get_fat(obj, clst);
1399 if (nxt < 2)
return FR_INT_ERR;
1400 if (nxt == 0xFFFFFFFF)
return FR_DISK_ERR;
1401 if (nxt != clst + 1)
break;
1404 if (clst == pclst) {
1408 if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {
1425 DWORD FatFs::create_chain (
1432 FATFS *fs = obj->fs;
1436 scl = fs->last_clst;
1437 if (scl == 0 || scl >= fs->n_fatent) scl = 1;
1440 cs = get_fat(obj, clst);
1441 if (cs < 2)
return 1;
1442 if (cs == 0xFFFFFFFF)
return cs;
1443 if (cs < fs->n_fatent)
return cs;
1446 if (fs->free_clst == 0)
return 0;
1449 if (fs->fs_type == FS_EXFAT) {
1450 ncl = find_bitmap(fs, scl, 1);
1451 if (ncl == 0 || ncl == 0xFFFFFFFF)
return ncl;
1452 res = change_bitmap(fs, ncl, 1, 1);
1453 if (res == FR_INT_ERR)
return 1;
1454 if (res == FR_DISK_ERR)
return 0xFFFFFFFF;
1458 if (obj->stat == 2 && ncl != scl + 1) {
1459 obj->n_cont = scl - obj->sclust;
1463 if (obj->stat != 2) {
1464 if (ncl == clst + 1) {
1465 obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2;
1467 if (obj->n_frag == 0) obj->n_frag = 1;
1468 res = fill_last_frag(obj, clst, ncl);
1469 if (res == FR_OK) obj->n_frag = 1;
1478 if (ncl >= fs->n_fatent) ncl = 2;
1479 cs = get_fat(obj, ncl);
1480 if (cs == 1 || cs == 0xFFFFFFFF)
return cs;
1483 if (cs >= 2 && cs < fs->n_fatent) scl = cs;
1491 if (ncl >= fs->n_fatent) {
1493 if (ncl > scl)
return 0;
1495 cs = get_fat(obj, ncl);
1497 if (cs == 1 || cs == 0xFFFFFFFF)
return cs;
1498 if (ncl == scl)
return 0;
1501 res = put_fat(fs, ncl, 0xFFFFFFFF);
1502 if (res == FR_OK && clst != 0) {
1503 res = put_fat(fs, clst, ncl);
1508 fs->last_clst = ncl;
1509 if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--;
1512 ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
1528static DWORD clmt_clust (
1533 DWORD cl, ncl, *tbl;
1534 FATFS *fs = fp->obj.fs;
1537 tbl = fp->cltbl + 1;
1538 cl = (DWORD)(ofs / SS(fs) / fs->csize);
1541 if (ncl == 0)
return 0;
1542 if (cl < ncl)
break;
1558 FRESULT FatFs::dir_clear (
1568 if (sync_window(fs) != FR_OK)
return FR_DISK_ERR;
1569 sect = clst2sect(fs, clst);
1571 mem_set(fs->win, 0,
sizeof fs->win);
1574 for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
1576 mem_set(ibuf, 0, szb);
1578 for (n = 0; n < fs->csize &&
p_io->disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ;
1583 ibuf = fs->win; szb = 1;
1584 for (n = 0; n < fs->csize &&
p_io->disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ;
1586 return (n == fs->csize) ? FR_OK : FR_DISK_ERR;
1597 FRESULT FatFs::dir_sdi (
1603 FATFS *fs = dp->obj.fs;
1606 if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) {
1610 clst = dp->obj.sclust;
1611 if (clst == 0 && fs->fs_type >= FS_FAT32) {
1612 clst = (DWORD)fs->dirbase;
1613 if (FF_FS_EXFAT) dp->obj.stat = 0;
1617 if (ofs / SZDIRE >= fs->n_rootdir)
return FR_INT_ERR;
1618 dp->sect = fs->dirbase;
1621 csz = (DWORD)fs->csize * SS(fs);
1622 while (ofs >= csz) {
1623 clst = get_fat(&dp->obj, clst);
1624 if (clst == 0xFFFFFFFF)
return FR_DISK_ERR;
1625 if (clst < 2 || clst >= fs->n_fatent)
return FR_INT_ERR;
1628 dp->sect = clst2sect(fs, clst);
1631 if (dp->sect == 0)
return FR_INT_ERR;
1632 dp->sect += ofs / SS(fs);
1633 dp->dir = fs->win + (ofs % SS(fs));
1645 FRESULT FatFs::dir_next (
1651 FATFS *fs = dp->obj.fs;
1654 ofs = dp->dptr + SZDIRE;
1655 if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0;
1656 if (dp->sect == 0)
return FR_NO_FILE;
1658 if (ofs % SS(fs) == 0) {
1661 if (dp->clust == 0) {
1662 if (ofs / SZDIRE >= fs->n_rootdir) {
1663 dp->sect = 0;
return FR_NO_FILE;
1667 if ((ofs / SS(fs) & (fs->csize - 1)) == 0) {
1668 clst = get_fat(&dp->obj, dp->clust);
1669 if (clst <= 1)
return FR_INT_ERR;
1670 if (clst == 0xFFFFFFFF)
return FR_DISK_ERR;
1671 if (clst >= fs->n_fatent) {
1674 dp->sect = 0;
return FR_NO_FILE;
1676 clst = create_chain(&dp->obj, dp->clust);
1677 if (clst == 0)
return FR_DENIED;
1678 if (clst == 1)
return FR_INT_ERR;
1679 if (clst == 0xFFFFFFFF)
return FR_DISK_ERR;
1680 if (dir_clear(fs, clst) != FR_OK)
return FR_DISK_ERR;
1681 if (FF_FS_EXFAT) dp->obj.stat |= 4;
1683 if (!stretch) dp->sect = 0;
1684 dp->sect = 0;
return FR_NO_FILE;
1688 dp->sect = clst2sect(fs, clst);
1693 dp->dir = fs->win + ofs % SS(fs);
1706 FRESULT FatFs::dir_alloc (
1713 FATFS *fs = dp->obj.fs;
1716 res = dir_sdi(dp, 0);
1720 res = move_window(fs, dp->sect);
1721 if (res != FR_OK)
break;
1723 if ((fs->fs_type == FS_EXFAT) ? (
int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) {
1725 if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) {
1727 if (++n == nent)
break;
1731 res = dir_next(dp, 1);
1732 }
while (res == FR_OK);
1735 if (res == FR_NO_FILE) res = FR_DENIED;
1748static DWORD ld_clust (
1755 cl = ld_word(dir + DIR_FstClusLO);
1756 if (fs->fs_type == FS_FAT32) {
1757 cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16;
1765static void st_clust (
1771 st_word(dir + DIR_FstClusLO, (WORD)cl);
1772 if (fs->fs_type == FS_FAT32) {
1773 st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16));
1785 int FatFs::cmp_lfn (
1786 const WCHAR* lfnbuf,
1794 if (ld_word(dir + LDIR_FstClusLO) != 0)
return 0;
1796 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13;
1798 for (wc = 1, s = 0; s < 13; s++) {
1799 uc = ld_word(dir +
LfnOfs[s]);
1801 if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) {
1806 if (uc != 0xFFFF)
return 0;
1810 if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i])
return 0;
1816#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT
1821 int FatFs::pick_lfn (
1830 if (ld_word(dir + LDIR_FstClusLO) != 0)
return 0;
1832 i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13;
1834 for (wc = 1, s = 0; s < 13; s++) {
1835 uc = ld_word(dir +
LfnOfs[s]);
1837 if (i >= FF_MAX_LFN + 1)
return 0;
1838 lfnbuf[i++] = wc = uc;
1840 if (uc != 0xFFFF)
return 0;
1844 if (dir[LDIR_Ord] & LLEF && wc != 0) {
1845 if (i >= FF_MAX_LFN + 1)
return 0;
1859 void FatFs::put_lfn (
1870 dir[LDIR_Chksum] = sum;
1871 dir[LDIR_Attr] = AM_LFN;
1873 st_word(dir + LDIR_FstClusLO, 0);
1878 if (wc != 0xFFFF) wc = lfn[i++];
1879 st_word(dir +
LfnOfs[s], wc);
1880 if (wc == 0) wc = 0xFFFF;
1882 if (wc == 0xFFFF || !lfn[i]) ord |= LLEF;
1883 dir[LDIR_Ord] = ord;
1891#if FF_USE_LFN && !FF_FS_READONLY
1896static void gen_numname (
1909 mem_cpy(dst, src, 11);
1915 for (i = 0; i < 16; i++) {
1916 sreg = (sreg << 1) + (wc & 1);
1918 if (sreg & 0x10000) sreg ^= 0x11021;
1927 c = (BYTE)((seq % 16) +
'0');
1928 if (c >
'9') c += 7;
1935 for (j = 0; j < i && dst[j] !=
' '; j++) {
1936 if (dbc_1st(dst[j])) {
1937 if (j == i - 1)
break;
1942 dst[j++] = (i < 8) ? ns[i++] :
' ';
1954static BYTE sum_sfn (
1962 sum = (sum >> 1) + (sum << 7) + *dir++;
1976static WORD xdir_sum (
1984 szblk = (dir[XDIR_NumSec] + 1) * SZDIRE;
1985 for (i = sum = 0; i < szblk; i++) {
1986 if (i == XDIR_SetSum) {
1989 sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i];
1997static WORD xname_sum (
2005 while ((chr = *name++) != 0) {
2006 chr = (WCHAR)ff_wtoupper(chr);
2007 sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF);
2008 sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8);
2014#if !FF_FS_READONLY && FF_USE_MKFS
2015static DWORD xsum32 (
2020 sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat;
2026#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
2031static void get_xfileinfo (
2041 nc = 0; hs = 0; di = 0;
2042 while (nc < dirb[XDIR_NumName]) {
2043 if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0;
break; }
2044 if ((si % SZDIRE) == 0) si += 2;
2045 wc = ld_word(dirb + si); si += 2; nc++;
2046 if (hs == 0 && IsSurrogate(wc)) {
2049 wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di);
2050 if (wc == 0) { di = 0;
break; }
2054 if (hs != 0) di = 0;
2055 if (di == 0) fno->fname[di++] =
'?';
2057 fno->altname[0] = 0;
2059 fno->fattrib = dirb[XDIR_Attr];
2060 fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize);
2061 fno->ftime = ld_word(dirb + XDIR_ModTime + 0);
2062 fno->fdate = ld_word(dirb + XDIR_ModTime + 2);
2072FRESULT FatFs::load_xdir (
2078 BYTE* dirb = dp->obj.fs->dirbuf;
2082 res = move_window(dp->obj.fs, dp->sect);
2083 if (res != FR_OK)
return res;
2084 if (dp->dir[XDIR_Type] != ET_FILEDIR)
return FR_INT_ERR;
2085 mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
2086 sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
2087 if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE)
return FR_INT_ERR;
2090 res = dir_next(dp, 0);
2091 if (res == FR_NO_FILE) res = FR_INT_ERR;
2092 if (res != FR_OK)
return res;
2093 res = move_window(dp->obj.fs, dp->sect);
2094 if (res != FR_OK)
return res;
2095 if (dp->dir[XDIR_Type] != ET_STREAM)
return FR_INT_ERR;
2096 mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
2097 if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent)
return FR_INT_ERR;
2102 res = dir_next(dp, 0);
2103 if (res == FR_NO_FILE) res = FR_INT_ERR;
2104 if (res != FR_OK)
return res;
2105 res = move_window(dp->obj.fs, dp->sect);
2106 if (res != FR_OK)
return res;
2107 if (dp->dir[XDIR_Type] != ET_FILENAME)
return FR_INT_ERR;
2108 if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
2109 }
while ((i += SZDIRE) < sz_ent);
2112 if (i <= MAXDIRB(FF_MAX_LFN)) {
2113 if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum))
return FR_INT_ERR;
2123static void init_alloc_info (
2128 obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus);
2129 obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
2130 obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;
2136#if !FF_FS_READONLY || FF_FS_RPATH != 0
2141 FRESULT FatFs::load_obj_xdir (
2149 dp->obj.fs = obj->fs;
2150 dp->obj.sclust = obj->c_scl;
2151 dp->obj.stat = (BYTE)obj->c_size;
2152 dp->obj.objsize = obj->c_size & 0xFFFFFF00;
2154 dp->blk_ofs = obj->c_ofs;
2156 res = dir_sdi(dp, dp->blk_ofs);
2158 res = load_xdir(dp);
2170FRESULT FatFs::store_xdir (
2176 BYTE* dirb = dp->obj.fs->dirbuf;
2179 st_word(dirb + XDIR_SetSum, xdir_sum(dirb));
2180 nent = dirb[XDIR_NumSec] + 1;
2183 res = dir_sdi(dp, dp->blk_ofs);
2184 while (res == FR_OK) {
2185 res = move_window(dp->obj.fs, dp->sect);
2186 if (res != FR_OK)
break;
2187 mem_cpy(dp->dir, dirb, SZDIRE);
2188 dp->obj.fs->wflag = 1;
2189 if (--nent == 0)
break;
2191 res = dir_next(dp, 0);
2193 return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR;
2202static void create_xdir (
2213 mem_set(dirb, 0, 2 * SZDIRE);
2214 dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
2215 dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
2219 nlen = nc1 = 0; wc = 1;
2221 dirb[i++] = ET_FILENAME; dirb[i++] = 0;
2223 if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++;
2224 st_word(dirb + i, wc);
2226 }
while (i % SZDIRE != 0);
2228 }
while (lfn[nlen]);
2230 dirb[XDIR_NumName] = nlen;
2231 dirb[XDIR_NumSec] = 1 + nc1;
2232 st_word(dirb + XDIR_NameHash, xname_sum(lfn));
2240#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT
2245#define DIR_READ_FILE(dp) dir_read(dp, 0)
2246#define DIR_READ_LABEL(dp) dir_read(dp, 1)
2248 FRESULT FatFs::dir_read (
2253 FRESULT res = FR_NO_FILE;
2254 FATFS *fs = dp->obj.fs;
2257 BYTE ord = 0xFF, sum = 0xFF;
2261 res = move_window(fs, dp->sect);
2262 if (res != FR_OK)
break;
2263 b = dp->dir[DIR_Name];
2265 res = FR_NO_FILE;
break;
2268 if (fs->fs_type == FS_EXFAT) {
2269 if (FF_USE_LABEL && vol) {
2270 if (b == ET_VLABEL)
break;
2272 if (b == ET_FILEDIR) {
2273 dp->blk_ofs = dp->dptr;
2274 res = load_xdir(dp);
2276 dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK;
2284 dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK;
2286 if (b == DDEM || b ==
'.' || (
int)((attr & ~AM_ARC) == AM_VOL) != vol) {
2289 if (attr == AM_LFN) {
2291 sum = dp->dir[LDIR_Chksum];
2292 b &= (BYTE)~LLEF; ord = b;
2293 dp->blk_ofs = dp->dptr;
2296 ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
2298 if (ord != 0 || sum != sum_sfn(dp->dir)) {
2299 dp->blk_ofs = 0xFFFFFFFF;
2305 if (b != DDEM && b !=
'.' && attr != AM_LFN && (
int)((attr & ~AM_ARC) == AM_VOL) == vol) {
2310 res = dir_next(dp, 0);
2311 if (res != FR_OK)
break;
2314 if (res != FR_OK) dp->sect = 0;
2326 FRESULT FatFs::dir_find (
2331 FATFS *fs = dp->obj.fs;
2337 res = dir_sdi(dp, 0);
2338 if (res != FR_OK)
return res;
2340 if (fs->fs_type == FS_EXFAT) {
2343 WORD hash = xname_sum(fs->lfnbuf);
2345 while ((res = DIR_READ_FILE(dp)) == FR_OK) {
2347 if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN)
continue;
2349 if (ld_word(fs->dirbuf + XDIR_NameHash) != hash)
continue;
2350 for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) {
2351 if ((di % SZDIRE) == 0) di += 2;
2352 if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni]))
break;
2354 if (nc == 0 && !fs->lfnbuf[ni])
break;
2361 ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF;
2364 res = move_window(fs, dp->sect);
2365 if (res != FR_OK)
break;
2366 c = dp->dir[DIR_Name];
2367 if (c == 0) { res = FR_NO_FILE;
break; }
2369 dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK;
2370 if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) {
2371 ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF;
2374 if (!(dp->fn[NSFLAG] & NS_NOLFN)) {
2376 sum = dp->dir[LDIR_Chksum];
2377 c &= (BYTE)~LLEF; ord = c;
2378 dp->blk_ofs = dp->dptr;
2381 ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
2384 if (ord == 0 && sum == sum_sfn(dp->dir))
break;
2385 if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11))
break;
2386 ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF;
2390 dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK;
2391 if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11))
break;
2393 res = dir_next(dp, 0);
2394 }
while (res == FR_OK);
2407 FRESULT FatFs::dir_register (
2412 FATFS *fs = dp->obj.fs;
2418 if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME))
return FR_INVALID_NAME;
2419 for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ;
2422 if (fs->fs_type == FS_EXFAT) {
2423 nent = (nlen + 14) / 15 + 2;
2424 res = dir_alloc(dp, nent);
2425 if (res != FR_OK)
return res;
2426 dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1);
2428 if (dp->obj.stat & 4) {
2430 res = fill_first_frag(&dp->obj);
2431 if (res != FR_OK)
return res;
2432 res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF);
2433 if (res != FR_OK)
return res;
2434 if (dp->obj.sclust != 0) {
2437 res = load_obj_xdir(&dj, &dp->obj);
2438 if (res != FR_OK)
return res;
2439 dp->obj.objsize += (DWORD)fs->csize * SS(fs);
2440 st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize);
2441 st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
2442 fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
2443 res = store_xdir(&dj);
2444 if (res != FR_OK)
return res;
2448 create_xdir(fs->dirbuf, fs->lfnbuf);
2453 mem_cpy(sn, dp->fn, 12);
2454 if (sn[NSFLAG] & NS_LOSS) {
2455 dp->fn[NSFLAG] = NS_NOLFN;
2456 for (n = 1; n < 100; n++) {
2457 gen_numname(dp->fn, sn, fs->lfnbuf, n);
2459 if (res != FR_OK)
break;
2461 if (n == 100)
return FR_DENIED;
2462 if (res != FR_NO_FILE)
return res;
2463 dp->fn[NSFLAG] = sn[NSFLAG];
2467 nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1;
2468 res = dir_alloc(dp, nent);
2469 if (res == FR_OK && --nent) {
2470 res = dir_sdi(dp, dp->dptr - nent * SZDIRE);
2472 sum = sum_sfn(dp->fn);
2474 res = move_window(fs, dp->sect);
2475 if (res != FR_OK)
break;
2476 put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum);
2478 res = dir_next(dp, 0);
2479 }
while (res == FR_OK && --nent);
2484 res = dir_alloc(dp, 1);
2490 res = move_window(fs, dp->sect);
2492 mem_set(dp->dir, 0, SZDIRE);
2493 mem_cpy(dp->dir + DIR_Name, dp->fn, 11);
2495 dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT);
2508#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0
2513 FRESULT FatFs::dir_remove (
2518 FATFS *fs = dp->obj.fs;
2520 DWORD last = dp->dptr;
2522 res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs);
2525 res = move_window(fs, dp->sect);
2526 if (res != FR_OK)
break;
2527 if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
2528 dp->dir[XDIR_Type] &= 0x7F;
2530 dp->dir[DIR_Name] = DDEM;
2533 if (dp->dptr >= last)
break;
2534 res = dir_next(dp, 0);
2535 }
while (res == FR_OK);
2536 if (res == FR_NO_FILE) res = FR_INT_ERR;
2540 res = move_window(fs, dp->sect);
2542 dp->dir[DIR_Name] = DDEM;
2554#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
2559static void get_fileinfo (
2568 FATFS *fs = dp->obj.fs;
2575 if (dp->sect == 0)
return;
2579 if (fs->fs_type == FS_EXFAT) {
2580 get_xfileinfo(fs->dirbuf, fno);
2585 if (dp->blk_ofs != 0xFFFFFFFF) {
2587 while (fs->lfnbuf[si] != 0) {
2588 wc = fs->lfnbuf[si++];
2589 if (hs == 0 && IsSurrogate(wc)) {
2592 wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di);
2593 if (wc == 0) { di = 0;
break; }
2597 if (hs != 0) di = 0;
2605 if (wc ==
' ')
continue;
2606 if (wc == RDDEM) wc = DDEM;
2607 if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] =
'.';
2608#if FF_LFN_UNICODE >= 1
2609 if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) {
2610 wc = wc << 8 | dp->dir[si++];
2612 wc = ff_oem2uni(wc, CODEPAGE);
2613 if (wc == 0) { di = 0;
break; }
2614 wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di);
2615 if (wc == 0) { di = 0;
break; }
2618 fno->altname[di++] = (TCHAR)wc;
2621 fno->altname[di] = 0;
2623 if (fno->fname[0] == 0) {
2625 fno->fname[di++] =
'?';
2627 for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) {
2628 wc = (WCHAR)fno->altname[si];
2629 if (wc ==
'.') lcf = NS_EXT;
2630 if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20;
2631 fno->fname[di] = (TCHAR)wc;
2635 if (!dp->dir[DIR_NTres]) fno->altname[0] = 0;
2641 c = (TCHAR)dp->dir[si++];
2642 if (c ==
' ')
continue;
2643 if (c == RDDEM) c = DDEM;
2644 if (si == 9) fno->fname[di++] =
'.';
2645 fno->fname[di++] = c;
2650 fno->fattrib = dp->dir[DIR_Attr];
2651 fno->fsize = ld_dword(dp->dir + DIR_FileSize);
2652 fno->ftime = ld_word(dp->dir + DIR_ModTime + 0);
2653 fno->fdate = ld_word(dp->dir + DIR_ModTime + 2);
2660#if FF_USE_FIND && FF_FS_MINIMIZE <= 1
2665static DWORD get_achar (
2672#if FF_USE_LFN && FF_LFN_UNICODE >= 1
2673 chr = tchar2uni(ptr);
2674 if (chr == 0xFFFFFFFF) chr = 0;
2675 chr = ff_wtoupper(chr);
2678 chr = (BYTE)*(*ptr)++;
2679 if (IsLower(chr)) chr -= 0x20;
2680#if FF_CODE_PAGE == 0
2681 if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80];
2682#elif FF_CODE_PAGE < 900
2683 if (chr >= 0x80) chr = ExCvt[chr - 0x80];
2685#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900
2686 if (dbc_1st((BYTE)chr)) {
2687 chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0;
2696static int pattern_matching (
2703 const TCHAR *pp, *np;
2709 if (!get_achar(&nam))
return 0;
2711 if (*pat == 0 && inf)
return 1;
2716 if (*pp ==
'?' || *pp ==
'*') {
2719 if (*pp++ ==
'?') nm++;
else nx = 1;
2720 }
while (*pp ==
'?' || *pp ==
'*');
2721 if (pattern_matching(pp, np, nm, nx))
return 1;
2724 pc = get_achar(&pp);
2725 nc = get_achar(&np);
2726 if (pc != nc)
break;
2727 if (pc == 0)
return 1;
2730 }
while (inf && nc);
2743static FRESULT create_name (
2757 p = *path; lfn = dp->obj.fs->lfnbuf; di = 0;
2760 if (uc == 0xFFFFFFFF)
return FR_INVALID_NAME;
2761 if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16);
2763 if (wc <
' ' || wc ==
'/' || wc ==
'\\')
break;
2764 if (wc < 0x80 && chk_chr(
"\"*:<>\?|\x7F", wc))
return FR_INVALID_NAME;
2765 if (di >= FF_MAX_LFN)
return FR_INVALID_NAME;
2772 while (*p ==
'/' || *p ==
'\\') p++;
2777 if ((di == 1 && lfn[di - 1] ==
'.') ||
2778 (di == 2 && lfn[di - 1] ==
'.' && lfn[di - 2] ==
'.')) {
2780 for (i = 0; i < 11; i++) {
2781 dp->fn[i] = (i < di) ?
'.' :
' ';
2783 dp->fn[i] = cf | NS_DOT;
2789 if (wc !=
' ' && wc !=
'.')
break;
2793 if (di == 0)
return FR_INVALID_NAME;
2796 for (si = 0; lfn[si] ==
' '; si++) ;
2797 if (si > 0 || lfn[si] ==
'.') cf |= NS_LOSS | NS_LFN;
2798 while (di > 0 && lfn[di - 1] !=
'.') di--;
2800 mem_set(dp->fn,
' ', 11);
2805 if (wc ==
' ' || (wc ==
'.' && si != di)) {
2806 cf |= NS_LOSS | NS_LFN;
2810 if (i >= ni || si == di) {
2812 cf |= NS_LOSS | NS_LFN;
2815 if (si != di) cf |= NS_LOSS | NS_LFN;
2817 si = di; i = 8; ni = 11; b <<= 2;
2823#if FF_CODE_PAGE == 0
2825 wc = ff_uni2oem(wc, CODEPAGE);
2826 if (wc & 0x80) wc = ExCvt[wc & 0x7F];
2828 wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE);
2830#elif FF_CODE_PAGE < 900
2831 wc = ff_uni2oem(wc, CODEPAGE);
2832 if (wc & 0x80) wc = ExCvt[wc & 0x7F];
2834 wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE);
2840 cf |= NS_LOSS | NS_LFN;
2843 dp->fn[i++] = (BYTE)(wc >> 8);
2845 if (wc == 0 || chk_chr(
"+,;=[]", wc)) {
2846 wc =
'_'; cf |= NS_LOSS | NS_LFN;
2856 dp->fn[i++] = (BYTE)wc;
2859 if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM;
2861 if (ni == 8) b <<= 2;
2862 if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN;
2863 if (!(cf & NS_LFN)) {
2864 if (b & 0x01) cf |= NS_EXT;
2865 if (b & 0x04) cf |= NS_BODY;
2868 dp->fn[NSFLAG] = cf;
2879 p = *path; sfn = dp->fn;
2880 mem_set(sfn,
' ', 11);
2886 if (c !=
'.' || si >= 3)
break;
2889 if (c !=
'/' && c !=
'\\' && c >
' ')
return FR_INVALID_NAME;
2891 sfn[NSFLAG] = (c <=
' ') ? NS_LAST | NS_DOT : NS_DOT;
2897 if (c <=
' ')
break;
2898 if (c ==
'/' || c ==
'\\') {
2899 while (p[si] ==
'/' || p[si] ==
'\\') si++;
2902 if (c ==
'.' || i >= ni) {
2903 if (ni == 11 || c !=
'.')
return FR_INVALID_NAME;
2907#if FF_CODE_PAGE == 0
2908 if (ExCvt && c >= 0x80) {
2909 c = ExCvt[c & 0x7F];
2911#elif FF_CODE_PAGE < 900
2913 c = ExCvt[c & 0x7F];
2918 if (!dbc_2nd(d) || i >= ni - 1)
return FR_INVALID_NAME;
2922 if (chk_chr(
"\"*+,:;<=>\?[]|\x7F", c))
return FR_INVALID_NAME;
2923 if (IsLower(c)) c -= 0x20;
2928 if (i == 0)
return FR_INVALID_NAME;
2930 if (sfn[0] == DDEM) sfn[0] = RDDEM;
2931 sfn[NSFLAG] = (c <=
' ') ? NS_LAST : 0;
2944 FRESULT FatFs::follow_path (
2951 FATFS *fs = dp->obj.fs;
2955 if (*path !=
'/' && *path !=
'\\') {
2956 dp->obj.sclust = fs->cdir;
2960 while (*path ==
'/' || *path ==
'\\') path++;
2966 if (fs->fs_type == FS_EXFAT && dp->obj.sclust) {
2969 dp->obj.c_scl = fs->cdc_scl;
2970 dp->obj.c_size = fs->cdc_size;
2971 dp->obj.c_ofs = fs->cdc_ofs;
2972 res = load_obj_xdir(&dj, &dp->obj);
2973 if (res != FR_OK)
return res;
2974 dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize);
2975 dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
2980 if ((UINT)*path <
' ') {
2981 dp->fn[NSFLAG] = NS_NONAME;
2982 res = dir_sdi(dp, 0);
2986 res = create_name(dp, &path);
2987 if (res != FR_OK)
break;
2989 ns = dp->fn[NSFLAG];
2991 if (res == FR_NO_FILE) {
2992 if (FF_FS_RPATH && (ns & NS_DOT)) {
2993 if (!(ns & NS_LAST))
continue;
2994 dp->fn[NSFLAG] = NS_NONAME;
2997 if (!(ns & NS_LAST)) res = FR_NO_PATH;
3002 if (ns & NS_LAST)
break;
3004 if (!(dp->obj.attr & AM_DIR)) {
3005 res = FR_NO_PATH;
break;
3008 if (fs->fs_type == FS_EXFAT) {
3009 dp->obj.c_scl = dp->obj.sclust;
3010 dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
3011 dp->obj.c_ofs = dp->blk_ofs;
3012 init_alloc_info(fs, &dp->obj);
3016 dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs));
3031static int get_ldnumber (
3035 const TCHAR *tp, *tt;
3044 if (!tp)
return vol;
3045 do tc = *tt++;
while ((UINT)tc >= (FF_USE_LFN ?
' ' :
'!') && tc !=
':');
3049 if (IsDigit(*tp) && tp + 2 == tt) {
3052#if FF_STR_VOLUME_ID == 1
3056 sp = VolumeStr[i]; tp = *path;
3058 c = *sp++; tc = *tp++;
3059 if (IsLower(c)) c -= 0x20;
3060 if (IsLower(tc)) tc -= 0x20;
3061 }
while (c && (TCHAR)c == tc);
3062 }
while ((c || tp != tt) && ++i < FF_VOLUMES);
3065 if (i < FF_VOLUMES) {
3071#if FF_STR_VOLUME_ID == 2
3075 sp = VolumeStr[i]; tp = *path;
3077 c = *sp++; tc = *(++tp);
3078 if (IsLower(c)) c -= 0x20;
3079 if (IsLower(tc)) tc -= 0x20;
3080 }
while (c && (TCHAR)c == tc);
3081 }
while ((c || (tc !=
'/' && (UINT)tc >= (FF_USE_LFN ?
' ' :
'!'))) && ++i < FF_VOLUMES);
3082 if (i < FF_VOLUMES) {
3117 for (b = 1; b; b <<= 1) {
3118 crc ^= (d & b) ? 1 : 0;
3119 crc = (crc & 1) ? crc >> 1 ^ 0xEDB88320 : crc >> 1;
3127static int test_gpt_header (
3135 if (mem_cmp(gpth + GPTH_Sign,
"EFI PART" "\0\0\1\0" "\x5C\0\0", 16))
return 0;
3136 for (i = 0, bcc = 0xFFFFFFFF; i < 92; i++) {
3137 bcc = crc32(bcc, i - GPTH_Bcc < 4 ? 0 : gpth[i]);
3139 if (~bcc != ld_dword(gpth + GPTH_Bcc))
return 0;
3140 if (ld_dword(gpth + GPTH_PteSize) != SZ_GPTE)
return 0;
3141 if (ld_dword(gpth + GPTH_PtNum) > 128)
return 0;
3146#if !FF_FS_READONLY && FF_USE_MKFS
3149static DWORD make_rand (
3158 if (seed == 0) seed = 1;
3160 for (r = 0; r < 8; r++) seed = seed & 1 ? seed >> 1 ^ 0xA3000000 : seed >> 1;
3161 *buff++ = (BYTE)seed;
3177 UINT FatFs::check_fs (
3182 fs->wflag = 0; fs->winsect = (LBA_t)0 - 1;
3183 if (move_window(fs, sect) != FR_OK)
return 4;
3185 if (ld_word(fs->win + BS_55AA) != 0xAA55)
return 3;
3187 if (FF_FS_EXFAT && !mem_cmp(fs->win + BS_JmpBoot,
"\xEB\x76\x90" "EXFAT ", 11))
return 1;
3189 if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) {
3190 if (!mem_cmp(fs->win + BS_FilSysType,
"FAT", 3))
return 0;
3191 if (!mem_cmp(fs->win + BS_FilSysType32,
"FAT32", 5))
return 0;
3200 UINT FatFs::find_volume (
3209 fmt = check_fs(fs, 0);
3210 if (fmt != 2 && (fmt >= 3 || part == 0))
return fmt;
3215 if (fs->win[MBR_Table + PTE_System] == 0xEE) {
3216 DWORD n_ent, v_ent, ofs;
3219 if (move_window(fs, 1) != FR_OK)
return 4;
3220 if (!test_gpt_header(fs->win))
return 3;
3221 n_ent = ld_dword(fs->win + GPTH_PtNum);
3222 pt_lba = ld_qword(fs->win + GPTH_PtOfs);
3223 for (v_ent = i = 0; i < n_ent; i++) {
3224 if (move_window(fs, pt_lba + i * SZ_GPTE / SS(fs)) != FR_OK)
return 4;
3225 ofs = i * SZ_GPTE % SS(fs);
3226 if (!mem_cmp(fs->win + ofs + GPTE_PtGuid, GUID_MS_Basic, 16)) {
3228 fmt = check_fs(fs, ld_qword(fs->win + ofs + GPTE_FstLba));
3229 if (part == 0 && fmt <= 1)
return fmt;
3230 if (part != 0 && v_ent == part)
return fmt;
3236 if (FF_MULTI_PARTITION && part > 4)
return 3;
3237 for (i = 0; i < 4; i++) {
3238 mbr_pt[i] = ld_dword(fs->win + MBR_Table + i * SZ_PTE + PTE_StLba);
3240 i = part ? part - 1 : 0;
3242 fmt = mbr_pt[i] ? check_fs(fs, mbr_pt[i]) : 3;
3243 }
while (part == 0 && fmt >= 2 && ++i < 4);
3254 FRESULT FatFs::mount_volume (
3263 DWORD tsect, sysect, fasize, nclst, szbfat;
3271 vol = get_ldnumber(path);
3272 if (vol < 0)
return FR_INVALID_DRIVE;
3276 if (!fs)
return FR_NOT_ENABLED;
3278 if (!lock_fs(fs))
return FR_TIMEOUT;
3282 mode &= (BYTE)~FA_READ;
3283 if (fs->fs_type != 0) {
3284 stat =
p_io->disk_status(fs->pdrv);
3285 if (!(stat & STA_NOINIT)) {
3286 if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) {
3287 return FR_WRITE_PROTECTED;
3297 fs->pdrv = LD2PD(vol);
3298 stat =
p_io->disk_initialize(fs->pdrv);
3299 if (stat & STA_NOINIT) {
3300 return FR_NOT_READY;
3302 if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) {
3303 return FR_WRITE_PROTECTED;
3305#if FF_MAX_SS != FF_MIN_SS
3306 if (
p_io->disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK)
return FR_DISK_ERR;
3307 if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1)))
return FR_DISK_ERR;
3311 fmt = find_volume(fs, LD2PT(vol));
3312 if (fmt == 4)
return FR_DISK_ERR;
3313 if (fmt >= 2)
return FR_NO_FILESYSTEM;
3314 bsect = fs->winsect;
3321 DWORD so, cv, bcl, i;
3323 for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ;
3324 if (i < BPB_ZeroedEx + 53)
return FR_NO_FILESYSTEM;
3326 if (ld_word(fs->win + BPB_FSVerEx) != 0x100)
return FR_NO_FILESYSTEM;
3328 if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) {
3329 return FR_NO_FILESYSTEM;
3332 maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect;
3333 if (!FF_LBA64 && maxlba >= 0x100000000)
return FR_NO_FILESYSTEM;
3335 fs->fsize = ld_dword(fs->win + BPB_FatSzEx);
3337 fs->n_fats = fs->win[BPB_NumFATsEx];
3338 if (fs->n_fats != 1)
return FR_NO_FILESYSTEM;
3340 fs->csize = 1 << fs->win[BPB_SecPerClusEx];
3341 if (fs->csize == 0)
return FR_NO_FILESYSTEM;
3343 nclst = ld_dword(fs->win + BPB_NumClusEx);
3344 if (nclst > MAX_EXFAT)
return FR_NO_FILESYSTEM;
3345 fs->n_fatent = nclst + 2;
3348 fs->volbase = bsect;
3349 fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
3350 fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
3351 if (maxlba < (QWORD)fs->database + nclst * fs->csize)
return FR_NO_FILESYSTEM;
3352 fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
3358 if (so >= fs->csize)
return FR_NO_FILESYSTEM;
3359 if (move_window(fs, clst2sect(fs, (DWORD)fs->dirbase) + so) != FR_OK)
return FR_DISK_ERR;
3362 if (fs->win[i] == ET_BITMAP)
break;
3363 i = (i + SZDIRE) % SS(fs);
3365 bcl = ld_dword(fs->win + i + 20);
3366 if (bcl < 2 || bcl >= fs->n_fatent)
return FR_NO_FILESYSTEM;
3367 fs->bitbase = fs->database + fs->csize * (bcl - 2);
3369 if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK)
return FR_DISK_ERR;
3370 cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
3371 if (cv == 0xFFFFFFFF)
break;
3372 if (cv != ++bcl)
return FR_NO_FILESYSTEM;
3376 fs->last_clst = fs->free_clst = 0xFFFFFFFF;
3382 if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs))
return FR_NO_FILESYSTEM;
3384 fasize = ld_word(fs->win + BPB_FATSz16);
3385 if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
3388 fs->n_fats = fs->win[BPB_NumFATs];
3389 if (fs->n_fats != 1 && fs->n_fats != 2)
return FR_NO_FILESYSTEM;
3390 fasize *= fs->n_fats;
3392 fs->csize = fs->win[BPB_SecPerClus];
3393 if (fs->csize == 0 || (fs->csize & (fs->csize - 1)))
return FR_NO_FILESYSTEM;
3395 fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt);
3396 if (fs->n_rootdir % (SS(fs) / SZDIRE))
return FR_NO_FILESYSTEM;
3398 tsect = ld_word(fs->win + BPB_TotSec16);
3399 if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
3401 nrsv = ld_word(fs->win + BPB_RsvdSecCnt);
3402 if (nrsv == 0)
return FR_NO_FILESYSTEM;
3405 sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);
3406 if (tsect < sysect)
return FR_NO_FILESYSTEM;
3407 nclst = (tsect - sysect) / fs->csize;
3408 if (nclst == 0)
return FR_NO_FILESYSTEM;
3410 if (nclst <= MAX_FAT32) fmt = FS_FAT32;
3411 if (nclst <= MAX_FAT16) fmt = FS_FAT16;
3412 if (nclst <= MAX_FAT12) fmt = FS_FAT12;
3413 if (fmt == 0)
return FR_NO_FILESYSTEM;
3416 fs->n_fatent = nclst + 2;
3417 fs->volbase = bsect;
3418 fs->fatbase = bsect + nrsv;
3419 fs->database = bsect + sysect;
3420 if (fmt == FS_FAT32) {
3421 if (ld_word(fs->win + BPB_FSVer32) != 0)
return FR_NO_FILESYSTEM;
3422 if (fs->n_rootdir != 0)
return FR_NO_FILESYSTEM;
3423 fs->dirbase = ld_dword(fs->win + BPB_RootClus32);
3424 szbfat = fs->n_fatent * 4;
3426 if (fs->n_rootdir == 0)
return FR_NO_FILESYSTEM;
3427 fs->dirbase = fs->fatbase + fasize;
3428 szbfat = (fmt == FS_FAT16) ?
3429 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
3431 if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))
return FR_NO_FILESYSTEM;
3435 fs->last_clst = fs->free_clst = 0xFFFFFFFF;
3436 fs->fsi_flag = 0x80;
3437#if (FF_FS_NOFSINFO & 3) != 3
3439 && ld_word(fs->win + BPB_FSInfo32) == 1
3440 && move_window(fs, bsect + 1) == FR_OK)
3443 if (ld_word(fs->win + BS_55AA) == 0xAA55
3444 && ld_dword(fs->win + FSI_LeadSig) == 0x41615252
3445 && ld_dword(fs->win + FSI_StrucSig) == 0x61417272)
3447#if (FF_FS_NOFSINFO & 1) == 0
3448 fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
3450#if (FF_FS_NOFSINFO & 2) == 0
3451 fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
3459 fs->fs_type = (BYTE)fmt;
3483FRESULT FatFs::validate (
3488 FRESULT res = FR_INVALID_OBJECT;
3491 if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) {
3493 if (lock_fs(obj->fs)) {
3494 if (!(
p_io->disk_status(obj->fs->pdrv) & STA_NOINIT)) {
3497 unlock_fs(obj->fs, FR_OK);
3503 if (!(
p_io->disk_status(obj->fs->pdrv) & STA_NOINIT)) {
3508 *rfs = (res == FR_OK) ? obj->fs : 0;
3536 const TCHAR *rp = path;
3540 vol = get_ldnumber(&rp);
3541 if (vol < 0)
return FR_INVALID_DRIVE;
3549 if (!ff_del_syncobj(cfs->sobj))
return FR_INT_ERR;
3557 if (!ff_cre_syncobj((BYTE)vol, &fs->sobj))
return FR_INT_ERR;
3562 if (opt == 0)
return FR_OK;
3564 res = mount_volume(&path, &fs, 0);
3585 DWORD cl, bcs, clst;
3592 if (!fp)
return FR_INVALID_OBJECT;
3595 mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
3596 res = mount_volume(&path, &fs, mode);
3600 res = follow_path(&dj, path);
3603 if (dj.fn[NSFLAG] & NS_NONAME) {
3604 res = FR_INVALID_NAME;
3608 res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
3613 if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
3615 if (res == FR_NO_FILE) {
3617 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
3619 res = dir_register(&dj);
3622 mode |= FA_CREATE_ALWAYS;
3625 if (dj.obj.attr & (AM_RDO | AM_DIR)) {
3628 if (mode & FA_CREATE_NEW) res = FR_EXIST;
3631 if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {
3633 if (fs->fs_type == FS_EXFAT) {
3636 init_alloc_info(fs, &fp->obj);
3638 mem_set(fs->dirbuf + 2, 0, 30);
3639 mem_set(fs->dirbuf + 38, 0, 26);
3640 fs->dirbuf[XDIR_Attr] = AM_ARC;
3641 st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME());
3642 fs->dirbuf[XDIR_GenFlags] = 1;
3643 res = store_xdir(&dj);
3644 if (res == FR_OK && fp->obj.sclust != 0) {
3645 res = remove_chain(&fp->obj, fp->obj.sclust, 0);
3646 fs->last_clst = fp->obj.sclust - 1;
3652 cl = ld_clust(fs, dj.dir);
3653 st_dword(dj.dir + DIR_CrtTime, GET_FATTIME());
3654 dj.dir[DIR_Attr] = AM_ARC;
3655 st_clust(fs, dj.dir, 0);
3656 st_dword(dj.dir + DIR_FileSize, 0);
3660 res = remove_chain(&dj.obj, cl, 0);
3662 res = move_window(fs, sc);
3663 fs->last_clst = cl - 1;
3671 if (dj.obj.attr & AM_DIR) {
3674 if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) {
3681 if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED;
3682 fp->dir_sect = fs->winsect;
3683 fp->dir_ptr = dj.dir;
3685 fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
3686 if (fp->obj.lockid == 0) res = FR_INT_ERR;
3691 if (dj.fn[NSFLAG] & NS_NONAME) {
3692 res = FR_INVALID_NAME;
3694 if (dj.obj.attr & AM_DIR) {
3703 if (fs->fs_type == FS_EXFAT) {
3704 fp->obj.c_scl = dj.obj.sclust;
3705 fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
3706 fp->obj.c_ofs = dj.blk_ofs;
3707 init_alloc_info(fs, &fp->obj);
3711 fp->obj.sclust = ld_clust(fs, dj.dir);
3712 fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
3718 fp->obj.id = fs->id;
3725 mem_set(fp->buf, 0,
sizeof fp->buf);
3727 if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) {
3728 fp->fptr = fp->obj.objsize;
3729 bcs = (DWORD)fs->csize * SS(fs);
3730 clst = fp->obj.sclust;
3731 for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) {
3732 clst = get_fat(&fp->obj, clst);
3733 if (clst <= 1) res = FR_INT_ERR;
3734 if (clst == 0xFFFFFFFF) res = FR_DISK_ERR;
3737 if (res == FR_OK && ofs % SS(fs)) {
3738 sc = clst2sect(fs, clst);
3742 fp->sect = sc + (DWORD)(ofs / SS(fs));
3744 if (
p_io->disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
3755 if (res != FR_OK) fp->obj.fs = 0;
3779 UINT rcnt, cc, csect;
3780 BYTE *rbuff = (BYTE*)buff;
3784 res = validate(&fp->obj, &fs);
3785 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
3786 if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);
3787 remain = fp->obj.objsize - fp->fptr;
3788 if (btr > remain) btr = (UINT)remain;
3791 btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) {
3792 if (fp->fptr % SS(fs) == 0) {
3793 csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));
3795 if (fp->fptr == 0) {
3796 clst = fp->obj.sclust;
3800 clst = clmt_clust(fp, fp->fptr);
3804 clst = get_fat(&fp->obj, fp->clust);
3807 if (clst < 2) ABORT(fs, FR_INT_ERR);
3808 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
3811 sect = clst2sect(fs, fp->clust);
3812 if (sect == 0) ABORT(fs, FR_INT_ERR);
3816 if (csect + cc > fs->csize) {
3817 cc = fs->csize - csect;
3819 if (
p_io->disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
3820#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2
3822 if (fs->wflag && fs->winsect - sect < cc) {
3823 mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
3826 if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
3827 mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
3835 if (fp->sect != sect) {
3837 if (fp->flag & FA_DIRTY) {
3838 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3839 fp->flag &= (BYTE)~FA_DIRTY;
3842 if (
p_io->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3847 rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);
3848 if (rcnt > btr) rcnt = btr;
3850 if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR);
3851 mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt);
3853 mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt);
3857 LEAVE_FF(fs, FR_OK);
3879 UINT wcnt, cc, csect;
3880 const BYTE *wbuff = (
const BYTE*)buff;
3884 res = validate(&fp->obj, &fs);
3885 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
3886 if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
3889 if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
3890 btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
3894 btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) {
3895 if (fp->fptr % SS(fs) == 0) {
3896 csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1);
3898 if (fp->fptr == 0) {
3899 clst = fp->obj.sclust;
3901 clst = create_chain(&fp->obj, 0);
3906 clst = clmt_clust(fp, fp->fptr);
3910 clst = create_chain(&fp->obj, fp->clust);
3913 if (clst == 0)
break;
3914 if (clst == 1) ABORT(fs, FR_INT_ERR);
3915 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
3917 if (fp->obj.sclust == 0) fp->obj.sclust = clst;
3920 if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
3922 if (fp->flag & FA_DIRTY) {
3923 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3924 fp->flag &= (BYTE)~FA_DIRTY;
3927 sect = clst2sect(fs, fp->clust);
3928 if (sect == 0) ABORT(fs, FR_INT_ERR);
3932 if (csect + cc > fs->csize) {
3933 cc = fs->csize - csect;
3935 if (
p_io->disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
3936#if FF_FS_MINIMIZE <= 2
3938 if (fs->winsect - sect < cc) {
3939 mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
3943 if (fp->sect - sect < cc) {
3944 mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
3945 fp->flag &= (BYTE)~FA_DIRTY;
3953 if (fp->fptr >= fp->obj.objsize) {
3954 if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
3958 if (fp->sect != sect &&
3959 fp->fptr < fp->obj.objsize &&
3960 p_io->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
3961 ABORT(fs, FR_DISK_ERR);
3966 wcnt = SS(fs) - (UINT)fp->fptr % SS(fs);
3967 if (wcnt > btw) wcnt = btw;
3969 if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR);
3970 mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt);
3973 mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt);
3974 fp->flag |= FA_DIRTY;
3978 fp->flag |= FA_MODIFIED;
3980 LEAVE_FF(fs, FR_OK);
4000 res = validate(&fp->obj, &fs);
4002 if (fp->flag & FA_MODIFIED) {
4004 if (fp->flag & FA_DIRTY) {
4005 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
4006 fp->flag &= (BYTE)~FA_DIRTY;
4012 if (fs->fs_type == FS_EXFAT) {
4013 res = fill_first_frag(&fp->obj);
4015 res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);
4022 res = load_obj_xdir(&dj, &fp->obj);
4024 fs->dirbuf[XDIR_Attr] |= AM_ARC;
4025 fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1;
4026 st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust);
4027 st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize);
4028 st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize);
4029 st_dword(fs->dirbuf + XDIR_ModTime, tm);
4030 fs->dirbuf[XDIR_ModTime10] = 0;
4031 st_dword(fs->dirbuf + XDIR_AccTime, 0);
4032 res = store_xdir(&dj);
4035 fp->flag &= (BYTE)~FA_MODIFIED;
4043 res = move_window(fs, fp->dir_sect);
4046 dir[DIR_Attr] |= AM_ARC;
4047 st_clust(fp->obj.fs, dir, fp->obj.sclust);
4048 st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize);
4049 st_dword(dir + DIR_ModTime, tm);
4050 st_word(dir + DIR_LstAccDate, 0);
4053 fp->flag &= (BYTE)~FA_MODIFIED;
4083 res = validate(&fp->obj, &fs);
4086 res = dec_lock(fp->obj.lockid);
4087 if (res == FR_OK) fp->obj.fs = 0;
4092 unlock_fs(fs, FR_OK);
4115 vol = get_ldnumber(&path);
4116 if (vol < 0)
return FR_INVALID_DRIVE;
4117 CurrVol = (BYTE)vol;
4128#if FF_STR_VOLUME_ID == 2
4138 res = mount_volume(&path, &fs, 0);
4142 res = follow_path(&dj, path);
4144 if (dj.fn[NSFLAG] & NS_NONAME) {
4145 fs->cdir = dj.obj.sclust;
4147 if (fs->fs_type == FS_EXFAT) {
4148 fs->cdc_scl = dj.obj.c_scl;
4149 fs->cdc_size = dj.obj.c_size;
4150 fs->cdc_ofs = dj.obj.c_ofs;
4154 if (dj.obj.attr & AM_DIR) {
4156 if (fs->fs_type == FS_EXFAT) {
4157 fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus);
4158 fs->cdc_scl = dj.obj.sclust;
4159 fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
4160 fs->cdc_ofs = dj.blk_ofs;
4164 fs->cdir = ld_clust(fs, dj.dir);
4172 if (res == FR_NO_FILE) res = FR_NO_PATH;
4173#if FF_STR_VOLUME_ID == 2
4175 for (i = FF_VOLUMES - 1; i && fs !=
FatFsDir[i]; i--) ;
4209 res = mount_volume((
const TCHAR**)&buff, &fs, 0);
4216 if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
4217 dj.obj.sclust = fs->cdir;
4218 while ((ccl = dj.obj.sclust) != 0) {
4219 res = dir_sdi(&dj, 1 * SZDIRE);
4220 if (res != FR_OK)
break;
4221 res = move_window(fs, dj.sect);
4222 if (res != FR_OK)
break;
4223 dj.obj.sclust = ld_clust(fs, dj.dir);
4224 res = dir_sdi(&dj, 0);
4225 if (res != FR_OK)
break;
4227 res = DIR_READ_FILE(&dj);
4228 if (res != FR_OK)
break;
4229 if (ccl == ld_clust(fs, dj.dir))
break;
4230 res = dir_next(&dj, 0);
4231 }
while (res == FR_OK);
4232 if (res == FR_NO_FILE) res = FR_INT_ERR;
4233 if (res != FR_OK)
break;
4234 get_fileinfo(&dj, &fno);
4235 for (n = 0; fno.fname[n]; n++) ;
4237 res = FR_NOT_ENOUGH_CORE;
break;
4239 while (n) buff[--i] = fno.fname[--n];
4244 if (i == len) buff[--i] =
'/';
4247#if FF_STR_VOLUME_ID >= 1
4248 for (n = 0, vp = (
const char*)VolumeStr[CurrVol]; vp[n]; n++) ;
4250 if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)
'/';
4251 for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ;
4252 if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)
':';
4257 *tp++ = (TCHAR)
'0' + CurrVol;
4262 if (vl == 0) res = FR_NOT_ENOUGH_CORE;
4266 do *tp++ = buff[i++];
while (i < len);
4281#if FF_FS_MINIMIZE <= 2
4297 DWORD cl, pcl, ncl, tcl, tlen, ulen, *tbl;
4301 res = validate(&fp->obj, &fs);
4302 if (res == FR_OK) res = (FRESULT)fp->err;
4303#if FF_FS_EXFAT && !FF_FS_READONLY
4304 if (res == FR_OK && fs->fs_type == FS_EXFAT) {
4305 res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);
4308 if (res != FR_OK) LEAVE_FF(fs, res);
4312 if (ofs == CREATE_LINKMAP) {
4314 tlen = *tbl++; ulen = 2;
4315 cl = fp->obj.sclust;
4319 tcl = cl; ncl = 0; ulen += 2;
4322 cl = get_fat(&fp->obj, cl);
4323 if (cl <= 1) ABORT(fs, FR_INT_ERR);
4324 if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
4325 }
while (cl == pcl + 1);
4327 *tbl++ = ncl; *tbl++ = tcl;
4329 }
while (cl < fs->n_fatent);
4335 res = FR_NOT_ENOUGH_CORE;
4338 if (ofs > fp->obj.objsize) ofs = fp->obj.objsize;
4341 fp->clust = clmt_clust(fp, ofs - 1);
4342 dsc = clst2sect(fs, fp->clust);
4343 if (dsc == 0) ABORT(fs, FR_INT_ERR);
4344 dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1);
4345 if (fp->fptr % SS(fs) && dsc != fp->sect) {
4348 if (fp->flag & FA_DIRTY) {
4349 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4350 fp->flag &= (BYTE)~FA_DIRTY;
4353 if (
p_io->disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4365 if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF;
4367 if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) {
4368 ofs = fp->obj.objsize;
4371 fp->fptr = nsect = 0;
4373 bcs = (DWORD)fs->csize * SS(fs);
4375 (ofs - 1) / bcs >= (ifptr - 1) / bcs) {
4376 fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1);
4380 clst = fp->obj.sclust;
4383 clst = create_chain(&fp->obj, 0);
4384 if (clst == 1) ABORT(fs, FR_INT_ERR);
4385 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
4386 fp->obj.sclust = clst;
4393 ofs -= bcs; fp->fptr += bcs;
4395 if (fp->flag & FA_WRITE) {
4396 if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) {
4397 fp->obj.objsize = fp->fptr;
4398 fp->flag |= FA_MODIFIED;
4400 clst = create_chain(&fp->obj, clst);
4407 clst = get_fat(&fp->obj, clst);
4409 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
4410 if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
4415 nsect = clst2sect(fs, clst);
4416 if (nsect == 0) ABORT(fs, FR_INT_ERR);
4417 nsect += (DWORD)(ofs / SS(fs));
4421 if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) {
4422 fp->obj.objsize = fp->fptr;
4423 fp->flag |= FA_MODIFIED;
4425 if (fp->fptr % SS(fs) && nsect != fp->sect) {
4428 if (fp->flag & FA_DIRTY) {
4429 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4430 fp->flag &= (BYTE)~FA_DIRTY;
4433 if (
p_io->disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4444#if FF_FS_MINIMIZE <= 1
4459 if (!dp)
return FR_INVALID_OBJECT;
4462 res = mount_volume(&path, &fs, 0);
4466 res = follow_path(dp, path);
4468 if (!(dp->fn[NSFLAG] & NS_NONAME)) {
4469 if (dp->obj.attr & AM_DIR) {
4471 if (fs->fs_type == FS_EXFAT) {
4472 dp->obj.c_scl = dp->obj.sclust;
4473 dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
4474 dp->obj.c_ofs = dp->blk_ofs;
4475 init_alloc_info(fs, &dp->obj);
4479 dp->obj.sclust = ld_clust(fs, dp->dir);
4486 dp->obj.id = fs->id;
4487 res = dir_sdi(dp, 0);
4490 if (dp->obj.sclust != 0) {
4491 dp->obj.lockid = inc_lock(dp, 0);
4492 if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES;
4501 if (res == FR_NO_FILE) res = FR_NO_PATH;
4503 if (res != FR_OK) dp->obj.fs = 0;
4523 res = validate(&dp->obj, &fs);
4526 if (dp->obj.lockid) res = dec_lock(dp->obj.lockid);
4527 if (res == FR_OK) dp->obj.fs = 0;
4532 unlock_fs(fs, FR_OK);
4553 res = validate(&dp->obj, &fs);
4556 res = dir_sdi(dp, 0);
4559 res = DIR_READ_FILE(dp);
4560 if (res == FR_NO_FILE) res = FR_OK;
4562 get_fileinfo(dp, fno);
4563 res = dir_next(dp, 0);
4564 if (res == FR_NO_FILE) res = FR_OK;
4589 if (res != FR_OK || !fno || !fno->fname[0])
break;
4590 if (pattern_matching(dp->pat, fno->fname, 0, 0))
break;
4591#if FF_USE_LFN && FF_USE_FIND == 2
4592 if (pattern_matching(dp->pat, fno->altname, 0, 0))
break;
4608 const TCHAR* pattern
4626#if FF_FS_MINIMIZE == 0
4642 res = mount_volume(&path, &dj.obj.fs, 0);
4644 INIT_NAMBUF(dj.obj.fs);
4645 res = follow_path(&dj, path);
4647 if (dj.fn[NSFLAG] & NS_NONAME) {
4648 res = FR_INVALID_NAME;
4650 if (fno) get_fileinfo(&dj, fno);
4656 LEAVE_FF(dj.obj.fs, res);
4674 DWORD nfree, clst, stat;
4681 res = mount_volume(&path, &fs, 0);
4685 if (fs->free_clst <= fs->n_fatent - 2) {
4686 *nclst = fs->free_clst;
4690 if (fs->fs_type == FS_FAT12) {
4691 clst = 2; obj.fs = fs;
4693 stat = get_fat(&obj, clst);
4694 if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR;
break; }
4695 if (stat == 1) { res = FR_INT_ERR;
break; }
4696 if (stat == 0) nfree++;
4697 }
while (++clst < fs->n_fatent);
4700 if (fs->fs_type == FS_EXFAT) {
4704 clst = fs->n_fatent - 2;
4709 res = move_window(fs, sect++);
4710 if (res != FR_OK)
break;
4712 for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) {
4713 if (!(bm & 1)) nfree++;
4716 i = (i + 1) % SS(fs);
4721 clst = fs->n_fatent;
4726 res = move_window(fs, sect++);
4727 if (res != FR_OK)
break;
4729 if (fs->fs_type == FS_FAT16) {
4730 if (ld_word(fs->win + i) == 0) nfree++;
4733 if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
4741 fs->free_clst = nfree;
4765 res = validate(&fp->obj, &fs);
4766 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
4767 if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
4769 if (fp->fptr < fp->obj.objsize) {
4770 if (fp->fptr == 0) {
4771 res = remove_chain(&fp->obj, fp->obj.sclust, 0);
4774 ncl = get_fat(&fp->obj, fp->clust);
4776 if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
4777 if (ncl == 1) res = FR_INT_ERR;
4778 if (res == FR_OK && ncl < fs->n_fatent) {
4779 res = remove_chain(&fp->obj, ncl, fp->clust);
4782 fp->obj.objsize = fp->fptr;
4783 fp->flag |= FA_MODIFIED;
4785 if (res == FR_OK && (fp->flag & FA_DIRTY)) {
4786 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
4789 fp->flag &= (BYTE)~FA_DIRTY;
4793 if (res != FR_OK) ABORT(fs, res);
4821 res = mount_volume(&path, &fs, FA_WRITE);
4825 res = follow_path(&dj, path);
4826 if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) {
4827 res = FR_INVALID_NAME;
4830 if (res == FR_OK) res = chk_lock(&dj, 2);
4833 if (dj.fn[NSFLAG] & NS_NONAME) {
4834 res = FR_INVALID_NAME;
4836 if (dj.obj.attr & AM_RDO) {
4843 if (fs->fs_type == FS_EXFAT) {
4844 init_alloc_info(fs, &obj);
4849 dclst = ld_clust(fs, dj.dir);
4851 if (dj.obj.attr & AM_DIR) {
4853 if (dclst == fs->cdir) {
4859 sdj.obj.sclust = dclst;
4861 if (fs->fs_type == FS_EXFAT) {
4862 sdj.obj.objsize = obj.objsize;
4863 sdj.obj.stat = obj.stat;
4866 res = dir_sdi(&sdj, 0);
4868 res = DIR_READ_FILE(&sdj);
4869 if (res == FR_OK) res = FR_DENIED;
4870 if (res == FR_NO_FILE) res = FR_OK;
4876 res = dir_remove(&dj);
4877 if (res == FR_OK && dclst != 0) {
4879 res = remove_chain(&obj, dclst, 0);
4881 res = remove_chain(&dj.obj, dclst, 0);
4884 if (res == FR_OK) res = sync_fs(fs);
4912 res = mount_volume(&path, &fs, FA_WRITE);
4916 res = follow_path(&dj, path);
4917 if (res == FR_OK) res = FR_EXIST;
4918 if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {
4919 res = FR_INVALID_NAME;
4921 if (res == FR_NO_FILE) {
4923 dcl = create_chain(&sobj, 0);
4925 if (dcl == 0) res = FR_DENIED;
4926 if (dcl == 1) res = FR_INT_ERR;
4927 if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
4930 res = dir_clear(fs, dcl);
4932 if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
4933 mem_set(fs->win + DIR_Name,
' ', 11);
4934 fs->win[DIR_Name] =
'.';
4935 fs->win[DIR_Attr] = AM_DIR;
4936 st_dword(fs->win + DIR_ModTime, tm);
4937 st_clust(fs, fs->win, dcl);
4938 mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE);
4939 fs->win[SZDIRE + 1] =
'.'; pcl = dj.obj.sclust;
4940 st_clust(fs, fs->win + SZDIRE, pcl);
4943 res = dir_register(&dj);
4948 if (fs->fs_type == FS_EXFAT) {
4949 st_dword(fs->dirbuf + XDIR_ModTime, tm);
4950 st_dword(fs->dirbuf + XDIR_FstClus, dcl);
4951 st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs));
4952 st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
4953 fs->dirbuf[XDIR_GenFlags] = 3;
4954 fs->dirbuf[XDIR_Attr] = AM_DIR;
4955 res = store_xdir(&dj);
4959 st_dword(dj.dir + DIR_ModTime, tm);
4960 st_clust(fs, dj.dir, dcl);
4961 dj.dir[DIR_Attr] = AM_DIR;
4968 remove_chain(&sobj, dcl, 0);
4985 const TCHAR* path_old,
4986 const TCHAR* path_new
4992 BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir;
4997 get_ldnumber(&path_new);
4998 res = mount_volume(&path_old, &fs, FA_WRITE);
5002 res = follow_path(&djo, path_old);
5003 if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;
5006 res = chk_lock(&djo, 2);
5011 if (fs->fs_type == FS_EXFAT) {
5015 mem_cpy(buf, fs->dirbuf, SZDIRE * 2);
5016 mem_cpy(&djn, &djo,
sizeof djo);
5017 res = follow_path(&djn, path_new);
5019 res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
5021 if (res == FR_NO_FILE) {
5022 res = dir_register(&djn);
5024 nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
5025 nh = ld_word(fs->dirbuf + XDIR_NameHash);
5026 mem_cpy(fs->dirbuf, buf, SZDIRE * 2);
5027 fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
5028 st_word(fs->dirbuf + XDIR_NameHash, nh);
5029 if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC;
5031 res = store_xdir(&djn);
5037 mem_cpy(buf, djo.dir, SZDIRE);
5038 mem_cpy(&djn, &djo,
sizeof (
DIR));
5039 res = follow_path(&djn, path_new);
5041 res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
5043 if (res == FR_NO_FILE) {
5044 res = dir_register(&djn);
5047 mem_cpy(dir + 13, buf + 13, SZDIRE - 13);
5048 dir[DIR_Attr] = buf[DIR_Attr];
5049 if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC;
5051 if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) {
5052 sect = clst2sect(fs, ld_clust(fs, dir));
5057 res = move_window(fs, sect);
5058 dir = fs->win + SZDIRE * 1;
5059 if (res == FR_OK && dir[1] ==
'.') {
5060 st_clust(fs, dir, djn.obj.sclust);
5069 res = dir_remove(&djo);
5089#if FF_USE_CHMOD && !FF_FS_READONLY
5106 res = mount_volume(&path, &fs, FA_WRITE);
5110 res = follow_path(&dj, path);
5111 if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;
5113 mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;
5115 if (fs->fs_type == FS_EXFAT) {
5116 fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask);
5117 res = store_xdir(&dj);
5121 dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask);
5152 res = mount_volume(&path, &fs, FA_WRITE);
5156 res = follow_path(&dj, path);
5157 if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;
5160 if (fs->fs_type == FS_EXFAT) {
5161 st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
5162 res = store_xdir(&dj);
5166 st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
5201 res = mount_volume(&path, &fs, 0);
5204 if (res == FR_OK && label) {
5205 dj.obj.fs = fs; dj.obj.sclust = 0;
5206 res = dir_sdi(&dj, 0);
5208 res = DIR_READ_LABEL(&dj);
5211 if (fs->fs_type == FS_EXFAT) {
5214 for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) {
5215 wc = ld_word(dj.dir + XDIR_Label + si * 2);
5216 if (hs == 0 && IsSurrogate(wc)) {
5219 wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4);
5220 if (wc == 0) { di = 0;
break; }
5224 if (hs != 0) di = 0;
5232#if FF_USE_LFN && FF_LFN_UNICODE >= 1
5233 if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++];
5234 wc = ff_oem2uni(wc, CODEPAGE);
5235 if (wc != 0) wc = put_utf(wc, &label[di], 4);
5236 if (wc == 0) { di = 0;
break; }
5239 label[di++] = (TCHAR)wc;
5245 }
while (label[--di] ==
' ');
5249 if (res == FR_NO_FILE) {
5256 if (res == FR_OK && vsn) {
5257 res = move_window(fs, fs->volbase);
5259 switch (fs->fs_type) {
5261 di = BPB_VolIDEx;
break;
5264 di = BS_VolID32;
break;
5269 *vsn = ld_dword(fs->win + di);
5293 static const char badchr[] =
"+.,;=[]/\\\"*:<>\?|\x7F";
5299 res = mount_volume(&label, &fs, FA_WRITE);
5300 if (res != FR_OK) LEAVE_FF(fs, res);
5303 if (fs->fs_type == FS_EXFAT) {
5304 mem_set(dirvn, 0, 22);
5306 while ((UINT)*label >=
' ') {
5307 dc = tchar2uni(&label);
5308 if (dc >= 0x10000) {
5309 if (dc == 0xFFFFFFFF || di >= 10) {
5312 st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++;
5315 if (dc == 0 || chk_chr(badchr + 7, (
int)dc) || di >= 11) {
5316 LEAVE_FF(fs, FR_INVALID_NAME);
5318 st_word(dirvn + di * 2, (WCHAR)dc); di++;
5323 mem_set(dirvn,
' ', 11);
5325 while ((UINT)*label >=
' ') {
5327 dc = tchar2uni(&label);
5328 wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0;
5330 wc = (BYTE)*label++;
5331 if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0;
5332 if (IsLower(wc)) wc -= 0x20;
5333#if FF_CODE_PAGE == 0
5334 if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80];
5335#elif FF_CODE_PAGE < 900
5336 if (wc >= 0x80) wc = ExCvt[wc - 0x80];
5339 if (wc == 0 || chk_chr(badchr + 0, (
int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) {
5340 LEAVE_FF(fs, FR_INVALID_NAME);
5342 if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8);
5343 dirvn[di++] = (BYTE)wc;
5345 if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME);
5346 while (di && dirvn[di - 1] ==
' ') di--;
5350 dj.obj.fs = fs; dj.obj.sclust = 0;
5351 res = dir_sdi(&dj, 0);
5353 res = DIR_READ_LABEL(&dj);
5355 if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
5356 dj.dir[XDIR_NumLabel] = (BYTE)di;
5357 mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
5360 mem_cpy(dj.dir, dirvn, 11);
5362 dj.dir[DIR_Name] = DDEM;
5368 if (res == FR_NO_FILE) {
5371 res = dir_alloc(&dj, 1);
5373 mem_set(dj.dir, 0, SZDIRE);
5374 if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
5375 dj.dir[XDIR_Type] = ET_VLABEL;
5376 dj.dir[XDIR_NumLabel] = (BYTE)di;
5377 mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
5379 dj.dir[DIR_Attr] = AM_VOL;
5380 mem_cpy(dj.dir, dirvn, 11);
5398#if FF_USE_EXPAND && !FF_FS_READONLY
5411 DWORD n, clst, stcl, scl, ncl, tcl, lclst;
5414 res = validate(&fp->obj, &fs);
5415 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
5416 if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
5418 if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED);
5420 n = (DWORD)fs->csize * SS(fs);
5421 tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0);
5422 stcl = fs->last_clst; lclst = 0;
5423 if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2;
5426 if (fs->fs_type == FS_EXFAT) {
5427 scl = find_bitmap(fs, stcl, tcl);
5428 if (scl == 0) res = FR_DENIED;
5429 if (scl == 0xFFFFFFFF) res = FR_DISK_ERR;
5432 res = change_bitmap(fs, scl, tcl, 1);
5433 lclst = scl + tcl - 1;
5441 scl = clst = stcl; ncl = 0;
5443 n = get_fat(&fp->obj, clst);
5444 if (++clst >= fs->n_fatent) clst = 2;
5445 if (n == 1) { res = FR_INT_ERR;
break; }
5446 if (n == 0xFFFFFFFF) { res = FR_DISK_ERR;
break; }
5448 if (++ncl == tcl)
break;
5450 scl = clst; ncl = 0;
5452 if (clst == stcl) { res = FR_DENIED;
break; }
5456 for (clst = scl, n = tcl; n; clst++, n--) {
5457 res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1);
5458 if (res != FR_OK)
break;
5468 fs->last_clst = lclst;
5470 fp->obj.sclust = scl;
5471 fp->obj.objsize = fsz;
5472 if (FF_FS_EXFAT) fp->obj.stat = 2;
5473 fp->flag |= FA_MODIFIED;
5474 if (fs->free_clst <= fs->n_fatent - 2) {
5475 fs->free_clst -= tcl;
5495 UINT (*func)(
const BYTE*,UINT),
5510 res = validate(&fp->obj, &fs);
5511 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
5512 if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);
5514 remain = fp->obj.objsize - fp->fptr;
5515 if (btf > remain) btf = (UINT)remain;
5517 for ( ; btf && (*func)(0, 0);
5518 fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
5519 csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));
5520 if (fp->fptr % SS(fs) == 0) {
5522 clst = (fp->fptr == 0) ?
5523 fp->obj.sclust : get_fat(&fp->obj, fp->clust);
5524 if (clst <= 1) ABORT(fs, FR_INT_ERR);
5525 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
5529 sect = clst2sect(fs, fp->clust);
5530 if (sect == 0) ABORT(fs, FR_INT_ERR);
5533 if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR);
5536 if (fp->sect != sect) {
5538 if (fp->flag & FA_DIRTY) {
5539 if (
p_io->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
5540 fp->flag &= (BYTE)~FA_DIRTY;
5543 if (
p_io->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
5548 rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);
5549 if (rcnt > btf) rcnt = btf;
5550 rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt);
5551 if (rcnt == 0) ABORT(fs, FR_INT_ERR);
5554 LEAVE_FF(fs, FR_OK);
5560#if !FF_FS_READONLY && FF_USE_MKFS
5565#define N_SEC_TRACK 63
5566#define GPT_ALIGN 0x100000
5567#define GPT_ITEMS 128
5572 FRESULT FatFs::create_partition (
5581 DWORD sz_drv32, s_lba32, n_lba32;
5582 BYTE *pte, hd, n_hd, sc, n_sc;
5585 if (
p_io->disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK)
return FR_DISK_ERR;
5588 if (sz_drv >= FF_MIN_GPT) {
5590 UINT sz_pt, pi, si, ofs;
5591 DWORD bcc, rnd, align;
5592 QWORD s_lba64, n_lba64, sz_pool, s_bpt;
5593 static const BYTE gpt_mbr[16] = {0x00, 0x00, 0x02, 0x00, 0xEE, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
5595#if FF_MAX_SS != FF_MIN_SS
5596 if (
p_io->disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK)
return FR_DISK_ERR;
5597 if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1)))
return FR_DISK_ERR;
5601 rnd = GET_FATTIME();
5602 align = GPT_ALIGN / ss;
5603 sz_pt = GPT_ITEMS * SZ_GPTE / ss;
5604 s_bpt = sz_drv - sz_pt - 1;
5605 s_lba64 = 2 + sz_pt;
5606 sz_pool = s_bpt - s_lba64;
5607 bcc = 0xFFFFFFFF; n_lba64 = 1;
5610 if (pi * SZ_GPTE % ss == 0) mem_set(buf, 0, ss);
5612 s_lba64 = (s_lba64 + align - 1) & ((QWORD)0 - align);
5613 n_lba64 = plst[si++];
5614 if (n_lba64 <= 100) {
5615 n_lba64 = sz_pool * n_lba64 / 100;
5616 n_lba64 = (n_lba64 + align - 1) & ((QWORD)0 - align);
5618 if (s_lba64 + n_lba64 > s_bpt) {
5619 n_lba64 = (s_lba64 < s_bpt) ? s_bpt - s_lba64 : 0;
5623 ofs = pi * SZ_GPTE % ss;
5624 mem_cpy(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16);
5625 rnd = make_rand(rnd, buf + ofs + GPTE_UpGuid, 16);
5626 st_qword(buf + ofs + GPTE_FstLba, s_lba64);
5627 st_qword(buf + ofs + GPTE_LstLba, s_lba64 + n_lba64 - 1);
5630 if ((pi + 1) * SZ_GPTE % ss == 0) {
5631 for (i = 0; i < ss; bcc = crc32(bcc, buf[i++])) ;
5632 if (
p_io->disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK)
return FR_DISK_ERR;
5633 if (
p_io->disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK)
return FR_DISK_ERR;
5635 }
while (++pi < GPT_ITEMS);
5638 mem_set(buf, 0, ss);
5639 mem_cpy(buf + GPTH_Sign,
"EFI PART" "\0\0\1\0" "\x5C\0\0", 16);
5640 st_dword(buf + GPTH_PtBcc, ~bcc);
5641 st_qword(buf + GPTH_CurLba, 1);
5642 st_qword(buf + GPTH_BakLba, sz_drv - 1);
5643 st_qword(buf + GPTH_FstLba, 2 + sz_pt);
5644 st_qword(buf + GPTH_LstLba, s_bpt - 1);
5645 st_dword(buf + GPTH_PteSize, SZ_GPTE);
5646 st_dword(buf + GPTH_PtNum, GPT_ITEMS);
5647 st_dword(buf + GPTH_PtOfs, 2);
5648 rnd = make_rand(rnd, buf + GPTH_DskGuid, 16);
5649 for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ;
5650 st_dword(buf + GPTH_Bcc, ~bcc);
5651 if (
p_io->disk_write(drv, buf, 1, 1) != RES_OK)
return FR_DISK_ERR;
5654 st_qword(buf + GPTH_CurLba, sz_drv - 1);
5655 st_qword(buf + GPTH_BakLba, 1);
5656 st_qword(buf + GPTH_PtOfs, s_bpt);
5657 st_dword(buf + GPTH_Bcc, 0);
5658 for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ;
5659 st_dword(buf + GPTH_Bcc, ~bcc);
5660 if (
p_io->disk_write(drv, buf, sz_drv - 1, 1) != RES_OK)
return FR_DISK_ERR;
5663 mem_set(buf, 0, ss);
5664 mem_cpy(buf + MBR_Table, gpt_mbr, 16);
5665 st_word(buf + BS_55AA, 0xAA55);
5666 if (
p_io->disk_write(drv, buf, 0, 1) != RES_OK)
return FR_DISK_ERR;
5671 sz_drv32 = (DWORD)sz_drv;
5673 for (n_hd = 8; n_hd != 0 && sz_drv32 / n_hd / n_sc > 1024; n_hd *= 2) ;
5674 if (n_hd == 0) n_hd = 255;
5676 mem_set(buf, 0, FF_MAX_SS);
5677 pte = buf + MBR_Table;
5678 for (i = 0, s_lba32 = n_sc; i < 4 && s_lba32 != 0 && s_lba32 < sz_drv32; i++, s_lba32 += n_lba32) {
5679 n_lba32 = (DWORD)plst[i];
5680 if (n_lba32 <= 100) n_lba32 = (n_lba32 == 100) ? sz_drv32 : sz_drv32 / 100 * n_lba32;
5681 if (s_lba32 + n_lba32 > sz_drv32 || s_lba32 + n_lba32 < s_lba32) n_lba32 = sz_drv32 - s_lba32;
5682 if (n_lba32 == 0)
break;
5684 st_dword(pte + PTE_StLba, s_lba32);
5685 st_dword(pte + PTE_SizLba, n_lba32);
5686 pte[PTE_System] = (BYTE)sys;
5688 cy = (UINT)(s_lba32 / n_sc / n_hd);
5689 hd = (BYTE)(s_lba32 / n_sc % n_hd);
5690 sc = (BYTE)(s_lba32 % n_sc + 1);
5691 pte[PTE_StHead] = hd;
5692 pte[PTE_StSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
5693 pte[PTE_StCyl] = (BYTE)cy;
5695 cy = (UINT)((s_lba32 + n_lba32 - 1) / n_sc / n_hd);
5696 hd = (BYTE)((s_lba32 + n_lba32 - 1) / n_sc % n_hd);
5697 sc = (BYTE)((s_lba32 + n_lba32 - 1) % n_sc + 1);
5698 pte[PTE_EdHead] = hd;
5699 pte[PTE_EdSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
5700 pte[PTE_EdCyl] = (BYTE)cy;
5705 st_word(buf + BS_55AA, 0xAA55);
5706 if (
p_io->disk_write(drv, buf, 0, 1) != RES_OK)
return FR_DISK_ERR;
5721 static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0};
5722 static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0};
5723 static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0};
5724 BYTE fsopt, fsty, sys, *buf, *pte, pdrv, ipart;
5726 DWORD sz_buf, sz_blk, n_clst, pau, nsect, n;
5727 LBA_t sz_vol, b_vol, b_fat, b_data;
5729 DWORD sz_rsv, sz_fat, sz_dir, sz_au;
5730 UINT n_fat, n_root, i;
5737 vol = get_ldnumber(&path);
5738 if (vol < 0)
return FR_INVALID_DRIVE;
5742 if (!opt) opt = &defopt;
5745 ds =
p_io->disk_initialize(pdrv);
5746 if (ds & STA_NOINIT)
return FR_NOT_READY;
5747 if (ds & STA_PROTECT)
return FR_WRITE_PROTECTED;
5748 sz_blk = opt->align;
5749 if (sz_blk == 0 &&
p_io->disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1;
5750 if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1;
5751#if FF_MAX_SS != FF_MIN_SS
5752 if (
p_io->disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK)
return FR_DISK_ERR;
5753 if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1)))
return FR_DISK_ERR;
5758 fsopt = opt->fmt & (FM_ANY | FM_SFD);
5759 n_fat = (opt->n_fat >= 1 && opt->n_fat <= 2) ? opt->n_fat : 1;
5760 n_root = (opt->n_root >= 1 && opt->n_root <= 32768 && (opt->n_root % (ss / SZDIRE)) == 0) ? opt->n_root : 512;
5761 sz_au = (opt->au_size <= 0x1000000 && (opt->au_size & (opt->au_size - 1)) == 0) ? opt->au_size : 0;
5766 if (sz_buf == 0)
return FR_NOT_ENOUGH_CORE;
5769 if (!buf) buf = ff_memalloc(sz_buf * ss);
5771 if (!buf)
return FR_NOT_ENOUGH_CORE;
5775 if (FF_MULTI_PARTITION && ipart != 0) {
5777 if (
p_io->disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5778 if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED);
5780 if (buf[MBR_Table + PTE_System] == 0xEE) {
5785 if (
p_io->disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5786 if (!test_gpt_header(buf)) LEAVE_MKFS(FR_MKFS_ABORTED);
5787 n_ent = ld_dword(buf + GPTH_PtNum);
5788 pt_lba = ld_qword(buf + GPTH_PtOfs);
5791 if (ofs == 0 &&
p_io->disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5792 if (!mem_cmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) {
5793 b_vol = ld_qword(buf + ofs + GPTE_FstLba);
5794 sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1;
5797 n_ent--; ofs = (ofs + SZ_GPTE) % ss;
5799 if (n_ent == 0) LEAVE_MKFS(FR_MKFS_ABORTED);
5804 pte = buf + (MBR_Table + (ipart - 1) * SZ_PTE);
5805 if (ipart > 4 || pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED);
5806 b_vol = ld_dword(pte + PTE_StLba);
5807 sz_vol = ld_dword(pte + PTE_SizLba);
5810 if (
p_io->disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5811 if (!(fsopt & FM_SFD)) {
5814 if (sz_vol >= FF_MIN_GPT) {
5816 b_vol = GPT_ALIGN / ss; sz_vol -= b_vol + GPT_ITEMS * SZ_GPTE / ss + 1;
5820 if (sz_vol > N_SEC_TRACK) {
5821 b_vol = N_SEC_TRACK; sz_vol -= b_vol;
5826 if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED);
5831 if (FF_FS_EXFAT && (fsopt & FM_EXFAT)) {
5832 if ((fsopt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || sz_au > 128) {
5833 fsty = FS_EXFAT;
break;
5837 if (sz_vol >= 0x100000000) LEAVE_MKFS(FR_MKFS_ABORTED);
5839 if (sz_au > 128) sz_au = 128;
5840 if (fsopt & FM_FAT32) {
5841 if (!(fsopt & FM_FAT)) {
5842 fsty = FS_FAT32;
break;
5845 if (!(fsopt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER);
5850 if (fsty == FS_EXFAT) {
5851 DWORD szb_bit, szb_case, sum, nb, cl, tbl[3];
5856 if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED);
5858 lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1;
5859 p_io->disk_ioctl(pdrv, CTRL_TRIM, lba);
5864 if (sz_vol >= 0x80000) sz_au = 64;
5865 if (sz_vol >= 0x4000000) sz_au = 256;
5868 sz_fat = (DWORD)((sz_vol / sz_au + 2) * 4 + ss - 1) / ss;
5869 b_data = (b_fat + sz_fat + sz_blk - 1) & ~((LBA_t)sz_blk - 1);
5870 if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED);
5871 n_clst = (DWORD)(sz_vol - (b_data - b_vol)) / sz_au;
5872 if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED);
5873 if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED);
5875 szb_bit = (n_clst + 7) / 8;
5876 tbl[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss);
5879 sect = b_data + sz_au * tbl[0];
5881 st = 0; si = 0; i = 0; j = 0; szb_case = 0;
5885 ch = (WCHAR)ff_wtoupper(si);
5889 for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ;
5891 ch = 0xFFFF; st = 2;
break;
5897 if (--j == 0) st = 0;
5901 ch = (WCHAR)j; si += (WCHAR)j;
5904 sum = xsum32(buf[i + 0] = (BYTE)ch, sum);
5905 sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
5906 i += 2; szb_case += 2;
5907 if (si == 0 || i == sz_buf * ss) {
5908 n = (i + ss - 1) / ss;
5909 if (
p_io->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5913 tbl[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss);
5917 sect = b_data; nsect = (szb_bit + ss - 1) / ss;
5918 nb = tbl[0] + tbl[1] + tbl[2];
5920 mem_set(buf, 0, sz_buf * ss);
5921 for (i = 0; nb >= 8 && i < sz_buf * ss; buf[i++] = 0xFF, nb -= 8) ;
5922 for (b = 1; nb != 0 && i < sz_buf * ss; buf[i] |= b, b <<= 1, nb--) ;
5923 n = (nsect > sz_buf) ? sz_buf : nsect;
5924 if (
p_io->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5925 sect += n; nsect -= n;
5929 sect = b_fat; nsect = sz_fat;
5932 mem_set(buf, 0, sz_buf * ss); i = 0;
5934 st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
5935 st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
5938 while (nb != 0 && i < sz_buf * ss) {
5939 st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF);
5942 if (nb == 0 && j < 3) nb = tbl[j++];
5943 }
while (nb != 0 && i < sz_buf * ss);
5944 n = (nsect > sz_buf) ? sz_buf : nsect;
5945 if (
p_io->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5946 sect += n; nsect -= n;
5950 mem_set(buf, 0, sz_buf * ss);
5951 buf[SZDIRE * 0 + 0] = ET_VLABEL;
5952 buf[SZDIRE * 1 + 0] = ET_BITMAP;
5953 st_dword(buf + SZDIRE * 1 + 20, 2);
5954 st_dword(buf + SZDIRE * 1 + 24, szb_bit);
5955 buf[SZDIRE * 2 + 0] = ET_UPCASE;
5956 st_dword(buf + SZDIRE * 2 + 4, sum);
5957 st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]);
5958 st_dword(buf + SZDIRE * 2 + 24, szb_case);
5959 sect = b_data + sz_au * (tbl[0] + tbl[1]); nsect = sz_au;
5961 n = (nsect > sz_buf) ? sz_buf : nsect;
5962 if (
p_io->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5963 mem_set(buf, 0, ss);
5964 sect += n; nsect -= n;
5969 for (n = 0; n < 2; n++) {
5971 mem_set(buf, 0, ss);
5972 mem_cpy(buf + BS_JmpBoot,
"\xEB\x76\x90" "EXFAT ", 11);
5973 st_qword(buf + BPB_VolOfsEx, b_vol);
5974 st_qword(buf + BPB_TotSecEx, sz_vol);
5975 st_dword(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol));
5976 st_dword(buf + BPB_FatSzEx, sz_fat);
5977 st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol));
5978 st_dword(buf + BPB_NumClusEx, n_clst);
5979 st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]);
5980 st_dword(buf + BPB_VolIDEx, GET_FATTIME());
5981 st_word(buf + BPB_FSVerEx, 0x100);
5982 for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ;
5983 for (buf[BPB_SecPerClusEx] = 0, i = sz_au; i >>= 1; buf[BPB_SecPerClusEx]++) ;
5984 buf[BPB_NumFATsEx] = 1;
5985 buf[BPB_DrvNumEx] = 0x80;
5986 st_word(buf + BS_BootCodeEx, 0xFEEB);
5987 st_word(buf + BS_55AA, 0xAA55);
5988 for (i = sum = 0; i < ss; i++) {
5989 if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum);
5991 if (
p_io->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
5993 mem_set(buf, 0, ss);
5994 st_word(buf + ss - 2, 0xAA55);
5995 for (j = 1; j < 9; j++) {
5996 for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;
5997 if (
p_io->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6000 mem_set(buf, 0, ss);
6001 for ( ; j < 11; j++) {
6002 for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;
6003 if (
p_io->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6006 for (i = 0; i < ss; i += 4) st_dword(buf + i, sum);
6007 if (
p_io->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6016 if (fsty == FS_FAT32) {
6018 n = (DWORD)sz_vol / 0x20000;
6019 for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ;
6021 n_clst = (DWORD)sz_vol / pau;
6022 sz_fat = (n_clst * 4 + 8 + ss - 1) / ss;
6025 if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED);
6028 n = (DWORD)sz_vol / 0x1000;
6029 for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ;
6031 n_clst = (DWORD)sz_vol / pau;
6032 if (n_clst > MAX_FAT12) {
6036 n = (n_clst * 3 + 1) / 2 + 3;
6038 sz_fat = (n + ss - 1) / ss;
6040 sz_dir = (DWORD)n_root * SZDIRE / ss;
6042 b_fat = b_vol + sz_rsv;
6043 b_data = b_fat + sz_fat * n_fat + sz_dir;
6046 n = (DWORD)(((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data);
6047 if (fsty == FS_FAT32) {
6048 sz_rsv += n; b_fat += n;
6051 n--; sz_rsv++; b_fat++;
6053 sz_fat += n / n_fat;
6057 if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);
6058 n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau;
6059 if (fsty == FS_FAT32) {
6060 if (n_clst <= MAX_FAT16) {
6061 if (sz_au == 0 && (sz_au = pau / 2) != 0)
continue;
6062 LEAVE_MKFS(FR_MKFS_ABORTED);
6065 if (fsty == FS_FAT16) {
6066 if (n_clst > MAX_FAT16) {
6067 if (sz_au == 0 && (pau * 2) <= 64) {
6068 sz_au = pau * 2;
continue;
6070 if ((fsopt & FM_FAT32)) {
6071 fsty = FS_FAT32;
continue;
6073 if (sz_au == 0 && (sz_au = pau * 2) <= 128)
continue;
6074 LEAVE_MKFS(FR_MKFS_ABORTED);
6076 if (n_clst <= MAX_FAT12) {
6077 if (sz_au == 0 && (sz_au = pau * 2) <= 128)
continue;
6078 LEAVE_MKFS(FR_MKFS_ABORTED);
6081 if (fsty == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED);
6088 lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1;
6089 p_io->disk_ioctl(pdrv, CTRL_TRIM, lba);
6092 mem_set(buf, 0, ss);
6093 mem_cpy(buf + BS_JmpBoot,
"\xEB\xFE\x90" "MSDOS5.0", 11);
6094 st_word(buf + BPB_BytsPerSec, ss);
6095 buf[BPB_SecPerClus] = (BYTE)pau;
6096 st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv);
6097 buf[BPB_NumFATs] = (BYTE)n_fat;
6098 st_word(buf + BPB_RootEntCnt, (WORD)((fsty == FS_FAT32) ? 0 : n_root));
6099 if (sz_vol < 0x10000) {
6100 st_word(buf + BPB_TotSec16, (WORD)sz_vol);
6102 st_dword(buf + BPB_TotSec32, (DWORD)sz_vol);
6104 buf[BPB_Media] = 0xF8;
6105 st_word(buf + BPB_SecPerTrk, 63);
6106 st_word(buf + BPB_NumHeads, 255);
6107 st_dword(buf + BPB_HiddSec, (DWORD)b_vol);
6108 if (fsty == FS_FAT32) {
6109 st_dword(buf + BS_VolID32, GET_FATTIME());
6110 st_dword(buf + BPB_FATSz32, sz_fat);
6111 st_dword(buf + BPB_RootClus32, 2);
6112 st_word(buf + BPB_FSInfo32, 1);
6113 st_word(buf + BPB_BkBootSec32, 6);
6114 buf[BS_DrvNum32] = 0x80;
6115 buf[BS_BootSig32] = 0x29;
6116 mem_cpy(buf + BS_VolLab32,
"NO NAME " "FAT32 ", 19);
6118 st_dword(buf + BS_VolID, GET_FATTIME());
6119 st_word(buf + BPB_FATSz16, (WORD)sz_fat);
6120 buf[BS_DrvNum] = 0x80;
6121 buf[BS_BootSig] = 0x29;
6122 mem_cpy(buf + BS_VolLab,
"NO NAME " "FAT ", 19);
6124 st_word(buf + BS_55AA, 0xAA55);
6125 if (
p_io->disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6128 if (fsty == FS_FAT32) {
6129 p_io->disk_write(pdrv, buf, b_vol + 6, 1);
6130 mem_set(buf, 0, ss);
6131 st_dword(buf + FSI_LeadSig, 0x41615252);
6132 st_dword(buf + FSI_StrucSig, 0x61417272);
6133 st_dword(buf + FSI_Free_Count, n_clst - 1);
6134 st_dword(buf + FSI_Nxt_Free, 2);
6135 st_word(buf + BS_55AA, 0xAA55);
6136 p_io->disk_write(pdrv, buf, b_vol + 7, 1);
6137 p_io->disk_write(pdrv, buf, b_vol + 1, 1);
6141 mem_set(buf, 0, sz_buf * ss);
6143 for (i = 0; i < n_fat; i++) {
6144 if (fsty == FS_FAT32) {
6145 st_dword(buf + 0, 0xFFFFFFF8);
6146 st_dword(buf + 4, 0xFFFFFFFF);
6147 st_dword(buf + 8, 0x0FFFFFFF);
6149 st_dword(buf + 0, (fsty == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8);
6153 n = (nsect > sz_buf) ? sz_buf : nsect;
6154 if (
p_io->disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6155 mem_set(buf, 0, ss);
6156 sect += n; nsect -= n;
6161 nsect = (fsty == FS_FAT32) ? pau : sz_dir;
6163 n = (nsect > sz_buf) ? sz_buf : nsect;
6164 if (
p_io->disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6165 sect += n; nsect -= n;
6172 if (FF_FS_EXFAT && fsty == FS_EXFAT) {
6175 if (fsty == FS_FAT32) {
6178 if (sz_vol >= 0x10000) {
6181 sys = (fsty == FS_FAT16) ? 0x04 : 0x01;
6187 if (FF_MULTI_PARTITION && ipart != 0) {
6188 if (!FF_LBA64 || !(fsopt & 0x80)) {
6190 if (
p_io->disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6191 buf[MBR_Table + (ipart - 1) * SZ_PTE + PTE_System] = sys;
6192 if (
p_io->disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6195 if (!(fsopt & FM_SFD)) {
6196 lba[0] = sz_vol, lba[1] = 0;
6197 fr = create_partition(pdrv, lba, sys, buf);
6198 if (fr != FR_OK) LEAVE_MKFS(fr);
6202 if (
p_io->disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
6210#if FF_MULTI_PARTITION
6221 BYTE *buf = (BYTE*)work;
6225 stat =
p_io->disk_initialize(pdrv);
6226 if (stat & STA_NOINIT)
return FR_NOT_READY;
6227 if (stat & STA_PROTECT)
return FR_WRITE_PROTECTED;
6229 if (!buf) buf = ff_memalloc(FF_MAX_SS);
6231 if (!buf)
return FR_NOT_ENOUGH_CORE;
6233 LEAVE_MKFS(create_partition(pdrv, ptbl, 0x07, buf));
6243#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3)
6244#error Wrong FF_STRF_ENCODE setting
6261#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2
6264#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3
6268#if FF_USE_LFN && FF_LFN_UNICODE
6270 if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2;
6271 if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4;
6272 if (FF_LFN_UNICODE == 3) len -= 1;
6274#if FF_STRF_ENCODE == 0
6278 if (dbc_1st((BYTE)wc)) {
6280 if (rc != 1 || !dbc_2nd(s[0]))
continue;
6281 wc = wc << 8 | s[0];
6283 dc = ff_oem2uni(wc, CODEPAGE);
6284 if (dc == 0)
continue;
6285#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2
6288 dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
6289 if (IsSurrogateL(dc))
continue;
6290 if (IsSurrogateH(dc)) {
6293 wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
6294 if (!IsSurrogateL(wc))
continue;
6295 dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF);
6303 if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; }
6304 if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; }
6305 if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; }
6306 if (ct == 0)
continue;
6308 if (rc != ct)
break;
6311 if ((s[rc] & 0xC0) != 0x80)
break;
6312 dc = dc << 6 | (s[rc] & 0x3F);
6313 }
while (++rc < ct);
6314 if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000)
continue;
6319 if (FF_USE_STRFUNC == 2 && dc ==
'\r')
continue;
6320#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3
6321 if (FF_LFN_UNICODE == 1 && dc >= 0x10000) {
6322 *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++;
6323 dc = 0xDC00 | (dc & 0x3FF);
6325 *p++ = (TCHAR)dc; nc++;
6326 if (dc ==
'\n')
break;
6327#elif FF_LFN_UNICODE == 2
6331 if (dc ==
'\n')
break;
6334 *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F));
6335 *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
6339 *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F));
6340 *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
6341 *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
6344 *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07));
6345 *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F));
6346 *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
6347 *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
6361 if (FF_USE_STRFUNC == 2 && dc ==
'\r')
continue;
6362 *p++ = (TCHAR)dc; nc++;
6363 if (dc ==
'\n')
break;
6368 return nc ? buff : 0;
6384 void FatFs::putc_bfd (
putbuff* pb, TCHAR c)
6388#if FF_USE_LFN && FF_LFN_UNICODE
6390#if FF_LFN_UNICODE == 2
6396 if (FF_USE_STRFUNC == 2 && c ==
'\n') {
6404#if FF_USE_LFN && FF_LFN_UNICODE
6405#if FF_LFN_UNICODE == 1
6406 if (IsSurrogateH(c)) {
6409 hs = pb->hs; pb->hs = 0;
6411 if (!IsSurrogateL(c)) hs = 0;
6413 if (IsSurrogateL(c))
return;
6416#elif FF_LFN_UNICODE == 2
6419 pb->bs[pb->wi = 0] = (BYTE)c;
6420 if ((BYTE)c < 0x80)
break;
6421 if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1;
6422 if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2;
6423 if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3;
6426 if (((BYTE)c & 0xC0) != 0x80) {
6427 pb->ct = 0;
continue;
6429 pb->bs[++pb->wi] = (BYTE)c;
6430 if (--pb->ct == 0)
break;
6434 tp = (TCHAR*)pb->bs;
6435 dc = tchar2uni(&tp);
6436 if (dc == 0xFFFFFFFF)
return;
6438 hs = (WCHAR)(dc >> 16);
6439#elif FF_LFN_UNICODE == 3
6440 if (IsSurrogate(c) || c >= 0x110000)
return;
6442 hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40));
6443 wc = 0xDC00 | (c & 0x3FF);
6451#if FF_STRF_ENCODE == 1
6453 st_word(&pb->buf[i], hs);
6457 st_word(&pb->buf[i], wc);
6459#elif FF_STRF_ENCODE == 2
6461 pb->buf[i++] = (BYTE)(hs >> 8);
6462 pb->buf[i++] = (BYTE)hs;
6465 pb->buf[i++] = (BYTE)(wc >> 8);
6466 pb->buf[i++] = (BYTE)wc;
6467#elif FF_STRF_ENCODE == 3
6470 hs = (hs & 0x3FF) + 0x40;
6471 pb->buf[i++] = (BYTE)(0xF0 | hs >> 8);
6472 pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F));
6473 pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F));
6474 pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F));
6477 pb->buf[i++] = (BYTE)wc;
6481 pb->buf[i++] = (BYTE)(0xC0 | wc >> 6);
6484 pb->buf[i++] = (BYTE)(0xE0 | wc >> 12);
6485 pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F));
6487 pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F));
6491 if (hs != 0)
return;
6492 wc = ff_uni2oem(wc, CODEPAGE);
6493 if (wc == 0)
return;
6495 pb->buf[i++] = (BYTE)(wc >> 8); nc++;
6497 pb->buf[i++] = (BYTE)wc;
6501 pb->buf[i++] = (BYTE)c;
6504 if (i >= (
int)(
sizeof pb->buf) - 4) {
6505 f_write(pb->fp, pb->buf, (UINT)i, &n);
6506 i = (n == (UINT)i) ? 0 : -1;
6515 int FatFs::putc_flush (putbuff* pb)
6520 &&
f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK
6521 && (UINT)pb->idx == nw)
return pb->nchr;
6528static void putc_init (putbuff* pb, FIL* fp)
6530 mem_set(pb, 0,
sizeof (putbuff));
6546 return putc_flush(&pb);
6565 while (*str) putc_bfd(&pb, *str++);
6566 return putc_flush(&pb);
6587 TCHAR c, d, str[32], *p;
6611 w = va_arg(arp,
int);
6614 while (IsDigit(c)) {
6615 w = w * 10 + c -
'0';
6619 if (c ==
'l' || c ==
'L') {
6624 if (IsLower(d)) d -= 0x20;
6627 p = va_arg(arp, TCHAR*);
6628 for (j = 0; p[j]; j++) ;
6630 while (j++ < w) putc_bfd(&pb,
' ') ;
6632 while (*p) putc_bfd(&pb, *p++) ;
6633 while (j++ < w) putc_bfd(&pb,
' ') ;
6637 putc_bfd(&pb, (TCHAR)va_arg(arp,
int));
continue;
6653 putc_bfd(&pb, c);
continue;
6657 v = (f & 4) ? (DWORD)va_arg(arp,
long) : ((d ==
'D') ? (DWORD)(long)va_arg(arp,
int) : (DWORD)va_arg(arp,
unsigned int));
6658 if (d ==
'D' && (v & 0x80000000)) {
6664 d = (TCHAR)(v % r); v /= r;
6665 if (d > 9) d += (c ==
'x') ? 0x27 : 0x07;
6667 }
while (v && i <
sizeof str /
sizeof *str);
6668 if (f & 8) str[i++] =
'-';
6669 j = i; d = (f & 1) ?
'0' :
' ';
6671 while (j++ < w) putc_bfd(&pb, d);
6674 putc_bfd(&pb, str[--i]);
6676 while (j++ < w) putc_bfd(&pb, d);
6681 return putc_flush(&pb);
6689#if FF_CODE_PAGE == 0
6698 static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0};
6699 static const BYTE*
const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0};
6703 for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ;
6704 if (validcp[i] != cp)
return FR_INVALID_PARAMETER;
FRESULT f_readdir(DIR *dp, FILINFO *fno)
Definition ff-inc.h:4543
FRESULT f_close(FIL *fp)
Definition ff-inc.h:4071
FRESULT f_getcwd(TCHAR *buff, UINT len)
FRESULT f_expand(FIL *fp, FSIZE_t fsz, BYTE opt)
FRESULT f_utime(const TCHAR *path, const FILINFO *fno)
Definition ff-inc.h:5141
FRESULT f_mount(FATFS *fs, const TCHAR *path, BYTE opt)
Definition ff-inc.h:3527
BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]
Definition ff.h:208
FRESULT f_findnext(DIR *dp, FILINFO *fno)
FRESULT f_stat(const TCHAR *path, FILINFO *fno)
Definition ff-inc.h:4631
TCHAR * f_gets(TCHAR *buff, int len, FIL *fp)
Definition ff-inc.h:6250
WORD Fsid
Definition ff.h:145
IO * p_io
Definition ff.h:125
int f_puts(const TCHAR *str, FIL *cp)
Definition ff-inc.h:6556
FRESULT f_forward(FIL *fp, UINT(*func)(const BYTE *, UINT), UINT btf, UINT *bf)
FRESULT f_opendir(DIR *dp, const TCHAR *path)
Definition ff-inc.h:4449
FRESULT f_chdrive(const TCHAR *path)
FRESULT f_getlabel(const TCHAR *path, TCHAR *label, DWORD *vsn)
int f_printf(FIL *fp, const TCHAR *str,...)
Definition ff-inc.h:6576
FRESULT f_chmod(const TCHAR *path, BYTE attr, BYTE mask)
Definition ff-inc.h:5094
FRESULT f_unlink(const TCHAR *path)
Definition ff-inc.h:4806
FRESULT f_fdisk(BYTE pdrv, const LBA_t ptbl[], void *work)
FRESULT f_setlabel(const TCHAR *label)
FRESULT f_rename(const TCHAR *path_old, const TCHAR *path_new)
Definition ff-inc.h:4984
FRESULT f_getfree(const TCHAR *path, DWORD *nclst, FATFS **fatfs)
Definition ff-inc.h:4666
WCHAR LfnBuf[FF_MAX_LFN+1]
Definition ff.h:210
FRESULT f_sync(FIL *fp)
Definition ff-inc.h:3990
FRESULT f_mkfs(const TCHAR *path, const MKFS_PARM *opt, void *work, UINT len)
Definition ff-inc.h:5714
FATFS * FatFsDir[FF_VOLUMES]
Definition ff.h:143
FRESULT f_lseek(FIL *fp, FSIZE_t ofs)
Definition ff-inc.h:4286
FRESULT f_write(FIL *fp, const void *buff, UINT btw, UINT *bw)
Definition ff-inc.h:3868
FRESULT f_read(FIL *fp, void *buff, UINT btr, UINT *br)
Definition ff-inc.h:3767
FRESULT f_findfirst(DIR *dp, FILINFO *fno, const TCHAR *path, const TCHAR *pattern)
FRESULT f_chdir(const TCHAR *path)
FRESULT f_mkdir(const TCHAR *path)
Definition ff-inc.h:4900
FRESULT f_closedir(DIR *dp)
Definition ff-inc.h:4515
const BYTE LfnOfs[13]
Definition ff.h:194
int f_putc(TCHAR c, FIL *fp)
Definition ff-inc.h:6536
void clear_lock(FATFS *fs)
FRESULT f_open(FIL *fp, const TCHAR *path, BYTE mode)
Definition ff-inc.h:3575
FRESULT f_truncate(FIL *fp)
Definition ff-inc.h:4756