Lines Matching +full:4 +full:- +full:byte

1 /*----------------------------------------------------------------------------/
2 / FatFs - Generic FAT file system module R0.12b /
3 /-----------------------------------------------------------------------------/
18 /----------------------------------------------------------------------------*/
25 /*--------------------------------------------------------------------------
29 ---------------------------------------------------------------------------*/
36 #define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
42 #error Static LFN work area cannot be used at thread-safe configuration
60 #define SS(fs) ((fs)->ssize) /* Variable sector size */
69 #define GET_FATTIME() ((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_…
78 #error _FS_LOCK must be 0 at read-only configuration
92 #if _CODE_PAGE == 932 /* Japanese Shift-JIS */
93 #define _DF1S 0x81 /* DBC 1st byte range 1 start */
94 #define _DF1E 0x9F /* DBC 1st byte range 1 end */
95 #define _DF2S 0xE0 /* DBC 1st byte range 2 start */
96 #define _DF2E 0xFC /* DBC 1st byte range 2 end */
97 #define _DS1S 0x40 /* DBC 2nd byte range 1 start */
98 #define _DS1E 0x7E /* DBC 2nd byte range 1 end */
99 #define _DS2S 0x80 /* DBC 2nd byte range 2 start */
100 #define _DS2E 0xFC /* DBC 2nd byte range 2 end */
260 #elif _CODE_PAGE == 863 /* Canadian-French */
315 #elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
334 #ifdef _DF2S /* Two 1st byte areas */
335 #define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) …
336 #else /* One 1st byte area */
337 #define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
340 #ifdef _DS3S /* Three 2nd byte areas */
341 …ne IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _…
342 #else /* Two 2nd byte areas */
343 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) …
363 #define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
367 #define NSFLAG 11 /* Index of name status byte in fn[] */
387 /* FatFs refers the members in the FAT structures as byte array instead of
391 #define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */
392 #define BS_OEMName 3 /* OEM name (8-byte) */
393 #define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */
394 #define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */
396 #define BPB_NumFATs 16 /* Number of FATs (BYTE) */
398 #define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */
399 #define BPB_Media 21 /* Media descriptor byte (BYTE) */
400 #define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */
404 #define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */
405 #define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */
406 #define BS_NTres 37 /* Error flag (BYTE) */
407 #define BS_BootSig 38 /* Extended boot signature (BYTE) */
409 #define BS_VolLab 43 /* Volume label string (8-byte) */
410 #define BS_FilSysType 54 /* File system type string (8-byte) */
411 #define BS_BootCode 62 /* Boot code (448-byte) */
420 #define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */
421 #define BS_NTres32 65 /* FAT32: Error flag (BYTE) */
422 #define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */
424 #define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */
425 #define BS_FilSysType32 82 /* FAT32: File system type string (8-byte) */
426 #define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */
428 #define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */
438 #define BPB_VolFlagEx 106 /* exFAT: Volume flags (BYTE) */
439 #define BPB_ActFatEx 107 /* exFAT: Active FAT flags (BYTE) */
440 #define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in byte (BYTE) */
441 #define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in sector (BYTE) */
442 #define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */
443 #define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */
444 #define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */
445 #define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */
446 #define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */
459 #define PTE_System 4 /* MBR PTE: System ID */
466 #define DIR_Name 0 /* Short file name (11-byte) */
467 #define DIR_Attr 11 /* Attribute (BYTE) */
468 #define DIR_NTres 12 /* Lower case flag (BYTE) */
469 #define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */
472 #define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */
474 #define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */
476 #define LDIR_Ord 0 /* LFN entry order and LLE flag (BYTE) */
477 #define LDIR_Attr 11 /* LFN attribute (BYTE) */
478 #define LDIR_Type 12 /* LFN type (BYTE) */
479 #define LDIR_Chksum 13 /* Checksum of the SFN entry (BYTE) */
481 #define XDIR_Type 0 /* Type of exFAT directory entry (BYTE) */
482 #define XDIR_NumLabel 1 /* Number of volume label characters (BYTE) */
483 #define XDIR_Label 2 /* Volume label (11-WORD) */
484 #define XDIR_CaseSum 4 /* Sum of case conversion table (DWORD) */
485 #define XDIR_NumSec 1 /* Number of secondary entries (BYTE) */
487 #define XDIR_Attr 4 /* File attribute (WORD) */
491 #define XDIR_CrtTime10 20 /* Created time subsecond (BYTE) */
492 #define XDIR_ModTime10 21 /* Modified time subsecond (BYTE) */
493 #define XDIR_CrtTZ 22 /* Created timezone (BYTE) */
494 #define XDIR_ModTZ 23 /* Modified timezone (BYTE) */
495 #define XDIR_AccTZ 24 /* Last accessed timezone (BYTE) */
497 #define XDIR_NumName 35 /* Number of file name characters (BYTE) */
512 /*--------------------------------------------------------------------------
516 ---------------------------------------------------------------------------*/
519 / at start-up. If not, either the linker or start-up routine being used is
529 static BYTE CurrVol; /* Current drive */
536 #if _USE_LFN == 0 /* Non-LFN configuration */
547 static BYTE DirBuf[SZDIRE*19]; /* Directory entry block scratchpad buffer (19 entries in size) */
556 #define DEF_NAMBUF WCHAR lbuf[_MAX_LFN+1]; BYTE dbuf[SZDIRE*19];
557 #define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; }
561 #define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; }
568 …DIRE*19); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(l…
572 …fn = ff_memalloc((_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; }
582 static const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for SBCS extended characters */
590 /*--------------------------------------------------------------------------
594 ---------------------------------------------------------------------------*/
597 /*-----------------------------------------------------------------------*/
598 /* Load/Store multi-byte word in the FAT structure */
599 /*-----------------------------------------------------------------------*/
602 WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ in ld_word()
612 DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ in ld_dword()
625 QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ in ld_qword()
632 rv = rv << 8 | ptr[4]; in ld_qword()
643 void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ in st_word()
645 *ptr++ = (BYTE)val; val >>= 8; in st_word()
646 *ptr++ = (BYTE)val; in st_word()
650 void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ in st_dword()
652 *ptr++ = (BYTE)val; val >>= 8; in st_dword()
653 *ptr++ = (BYTE)val; val >>= 8; in st_dword()
654 *ptr++ = (BYTE)val; val >>= 8; in st_dword()
655 *ptr++ = (BYTE)val; in st_dword()
660 void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ in st_qword()
662 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
663 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
664 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
665 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
666 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
667 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
668 *ptr++ = (BYTE)val; val >>= 8; in st_qword()
669 *ptr++ = (BYTE)val; in st_qword()
676 /*-----------------------------------------------------------------------*/
678 /*-----------------------------------------------------------------------*/
683 BYTE *d = (BYTE*)dst; in mem_cpy()
684 const BYTE *s = (const BYTE*)src; in mem_cpy()
687 do *d++ = *s++; while (--cnt); in mem_cpy()
694 BYTE *d = (BYTE*)dst; in mem_set()
696 do *d++ = (BYTE)val; while (--cnt); in mem_set()
702 const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; in mem_cmp()
706 r = *d++ - *s++; in mem_cmp()
707 } while (--cnt && r == 0); in mem_cmp()
723 /*-----------------------------------------------------------------------*/
725 /*-----------------------------------------------------------------------*/
731 return ff_req_grant(fs->sobj); in lock_fs()
742 ff_rel_grant(fs->sobj); in unlock_fs()
751 /*-----------------------------------------------------------------------*/
753 /*-----------------------------------------------------------------------*/
766 if (Files[i].fs == dp->obj.fs && /* Check if the object matched with an open object */ in chk_lock()
767 Files[i].clu == dp->obj.sclust && in chk_lock()
768 Files[i].ofs == dp->dptr) break; in chk_lock()
802 if (Files[i].fs == dp->obj.fs && in inc_lock()
803 Files[i].clu == dp->obj.sclust && in inc_lock()
804 Files[i].ofs == dp->dptr) break; in inc_lock()
810 Files[i].fs = dp->obj.fs; in inc_lock()
811 Files[i].clu = dp->obj.sclust; in inc_lock()
812 Files[i].ofs = dp->dptr; in inc_lock()
833 if (--i < _FS_LOCK) { /* Shift index number origin from 0 */ in dec_lock()
836 if (n > 0) n--; /* Decrement read mode open count */ in dec_lock()
863 /*-----------------------------------------------------------------------*/
865 /*-----------------------------------------------------------------------*/
877 if (fs->wflag) { /* Write back the sector if it is dirty */ in sync_window()
878 wsect = fs->winsect; /* Current sector number */ in sync_window()
879 if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) { in sync_window()
882 fs->wflag = 0; in sync_window()
883 if (wsect - fs->fatbase < fs->fsize) { /* Is it in the FAT area? */ in sync_window()
884 for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */ in sync_window()
885 wsect += fs->fsize; in sync_window()
886 disk_write(fs->drv, fs->win, wsect, 1); in sync_window()
899 DWORD sector /* Sector number to make appearance in the fs->win[] */ in move_window()
905 if (sector != fs->winsect) { /* Window offset changed? */ in move_window()
907 res = sync_window(fs); /* Write-back changes */ in move_window()
910 if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) { in move_window()
914 fs->winsect = sector; in move_window()
924 /*-----------------------------------------------------------------------*/
926 /*-----------------------------------------------------------------------*/
939 if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { in sync_fs()
941 mem_set(fs->win, 0, SS(fs)); in sync_fs()
942 st_word(fs->win + BS_55AA, 0xAA55); in sync_fs()
943 st_dword(fs->win + FSI_LeadSig, 0x41615252); in sync_fs()
944 st_dword(fs->win + FSI_StrucSig, 0x61417272); in sync_fs()
945 st_dword(fs->win + FSI_Free_Count, fs->free_clst); in sync_fs()
946 st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); in sync_fs()
948 fs->winsect = fs->volbase + 1; in sync_fs()
949 disk_write(fs->drv, fs->win, fs->winsect, 1); in sync_fs()
950 fs->fsi_flag = 0; in sync_fs()
953 if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; in sync_fs()
963 /*-----------------------------------------------------------------------*/
965 /*-----------------------------------------------------------------------*/
973 clst -= 2; in clust2sect()
974 if (clst >= fs->n_fatent - 2) return 0; /* Invalid cluster# */ in clust2sect()
975 return clst * fs->csize + fs->database; in clust2sect()
981 /*-----------------------------------------------------------------------*/
982 /* FAT access - Read value of a FAT entry */
983 /*-----------------------------------------------------------------------*/
993 FATFS *fs = obj->fs; in get_fat()
996 if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ in get_fat()
1002 switch (fs->fs_type) { in get_fat()
1005 if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; in get_fat()
1006 wc = fs->win[bc++ % SS(fs)]; in get_fat()
1007 if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; in get_fat()
1008 wc |= fs->win[bc % SS(fs)] << 8; in get_fat()
1009 val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); in get_fat()
1013 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; in get_fat()
1014 val = ld_word(fs->win + clst * 2 % SS(fs)); in get_fat()
1018 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; in get_fat()
1019 val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; in get_fat()
1023 if (obj->objsize) { in get_fat()
1024 DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ in get_fat()
1025 DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ in get_fat()
1027 if (obj->stat == 2) { /* Is there no valid chain on the FAT? */ in get_fat()
1033 if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the contiguous part? */ in get_fat()
1037 if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ in get_fat()
1038 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; in get_fat()
1039 val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; in get_fat()
1057 /*-----------------------------------------------------------------------*/
1058 /* FAT access - Change value of a FAT entry */
1059 /*-----------------------------------------------------------------------*/
1069 BYTE *p; in put_fat()
1073 if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ in put_fat()
1074 switch (fs->fs_type) { in put_fat()
1077 res = move_window(fs, fs->fatbase + (bc / SS(fs))); in put_fat()
1079 p = fs->win + bc++ % SS(fs); in put_fat()
1080 *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; in put_fat()
1081 fs->wflag = 1; in put_fat()
1082 res = move_window(fs, fs->fatbase + (bc / SS(fs))); in put_fat()
1084 p = fs->win + bc % SS(fs); in put_fat()
1085 *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); in put_fat()
1086 fs->wflag = 1; in put_fat()
1090 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); in put_fat()
1092 st_word(fs->win + clst * 2 % SS(fs), (WORD)val); in put_fat()
1093 fs->wflag = 1; in put_fat()
1100 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); in put_fat()
1102 if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) { in put_fat()
1103 val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); in put_fat()
1105 st_dword(fs->win + clst * 4 % SS(fs), val); in put_fat()
1106 fs->wflag = 1; in put_fat()
1119 /*-----------------------------------------------------------------------*/
1121 /*-----------------------------------------------------------------------*/
1123 /*---------------------------------------------*/
1125 /*---------------------------------------------*/
1134 BYTE bm, bv; in find_bitmap()
1139 clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ in find_bitmap()
1140 if (clst >= fs->n_fatent - 2) clst = 0; in find_bitmap()
1143 …if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bit… in find_bitmap()
1147 bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ in find_bitmap()
1148 if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ in find_bitmap()
1164 /*------------------------------------*/
1166 /*------------------------------------*/
1176 BYTE bm; in change_bitmap()
1181 clst -= 2; /* The first bit corresponds to cluster #2 */ in change_bitmap()
1182 …sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the … in change_bitmap()
1183 i = clst / 8 % SS(fs); /* Byte offset in the sector */ in change_bitmap()
1184 bm = 1 << (clst % 8); /* Bit mask in the byte */ in change_bitmap()
1189 if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ in change_bitmap()
1190 fs->win[i] ^= bm; /* Flip the bit */ in change_bitmap()
1191 fs->wflag = 1; in change_bitmap()
1192 if (--ncl == 0) return FR_OK; /* All bits processed? */ in change_bitmap()
1195 } while (++i < SS(fs)); /* Next byte */ in change_bitmap()
1201 /*---------------------------------------------*/
1203 /*---------------------------------------------*/
1213 if (obj->stat == 3) { /* Has the object been changed 'fragmented'? */ in fill_fat_chain()
1214 for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ in fill_fat_chain()
1215 res = put_fat(obj->fs, cl, cl + 1); in fill_fat_chain()
1218 obj->stat = 0; /* Change status 'FAT chain is valid' */ in fill_fat_chain()
1228 /*-----------------------------------------------------------------------*/
1229 /* FAT handling - Remove a cluster chain */
1230 /*-----------------------------------------------------------------------*/
1240 FATFS *fs = obj->fs; in remove_chain()
1248 if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ in remove_chain()
1251 if (pclst && (!_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { in remove_chain()
1262 if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) { in remove_chain()
1266 if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ in remove_chain()
1267 fs->free_clst++; in remove_chain()
1268 fs->fsi_flag |= 1; in remove_chain()
1275 if (fs->fs_type == FS_EXFAT) { in remove_chain()
1276 … res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ in remove_chain()
1282 rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ in remove_chain()
1283 disk_ioctl(fs->drv, CTRL_TRIM, rt); /* Inform device the block can be erased */ in remove_chain()
1289 } while (clst < fs->n_fatent); /* Repeat while not the last link */ in remove_chain()
1292 if (fs->fs_type == FS_EXFAT) { in remove_chain()
1294 obj->stat = 0; /* Change the object status 'initial' */ in remove_chain()
1296 …if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Did the cha… in remove_chain()
1297 obj->stat = 2; /* Change the object status 'contiguous' */ in remove_chain()
1308 /*-----------------------------------------------------------------------*/
1309 /* FAT handling - Stretch a chain or Create a new chain */
1310 /*-----------------------------------------------------------------------*/
1319 FATFS *fs = obj->fs; in create_chain()
1323 scl = fs->last_clst; /* Get suggested cluster to start from */ in create_chain()
1324 if (scl == 0 || scl >= fs->n_fatent) scl = 1; in create_chain()
1330 if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ in create_chain()
1335 if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ in create_chain()
1342 obj->stat = 2; /* Set status 'contiguous chain' */ in create_chain()
1344 if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ in create_chain()
1345 obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ in create_chain()
1346 obj->stat = 3; /* Change status 'just fragmented' */ in create_chain()
1355 if (ncl >= fs->n_fatent) { /* Check wrap-around */ in create_chain()
1366 if (_FS_EXFAT && fs->fs_type == FS_EXFAT && obj->stat == 2) { /* Is it a contiguous chain? */ in create_chain()
1376 fs->last_clst = ncl; in create_chain()
1377 if (fs->free_clst < fs->n_fatent - 2) fs->free_clst--; in create_chain()
1378 fs->fsi_flag |= 1; in create_chain()
1392 /*-----------------------------------------------------------------------*/
1393 /* FAT handling - Convert offset into cluster with link map table */
1394 /*-----------------------------------------------------------------------*/
1403 FATFS *fs = fp->obj.fs; in clmt_clust()
1406 tbl = fp->cltbl + 1; /* Top of CLMT */ in clmt_clust()
1407 cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ in clmt_clust()
1412 cl -= ncl; tbl++; /* Next fragment */ in clmt_clust()
1422 /*-----------------------------------------------------------------------*/
1423 /* Directory handling - Set directory index */
1424 /*-----------------------------------------------------------------------*/
1433 FATFS *fs = dp->obj.fs; in dir_sdi()
1436 …if (ofs >= (DWORD)((_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE)… in dir_sdi()
1439 dp->dptr = ofs; /* Set current offset */ in dir_sdi()
1440 clst = dp->obj.sclust; /* Table start cluster (0:root) */ in dir_sdi()
1441 if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ in dir_sdi()
1442 clst = fs->dirbase; in dir_sdi()
1443 if (_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ in dir_sdi()
1446 if (clst == 0) { /* Static table (root-directory in FAT12/16) */ in dir_sdi()
1447 if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ in dir_sdi()
1448 dp->sect = fs->dirbase; in dir_sdi()
1450 } else { /* Dynamic table (sub-directory or root-directory in FAT32+) */ in dir_sdi()
1451 csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ in dir_sdi()
1453 clst = get_fat(&dp->obj, clst); /* Get next cluster */ in dir_sdi()
1455 …if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal er… in dir_sdi()
1456 ofs -= csz; in dir_sdi()
1458 dp->sect = clust2sect(fs, clst); in dir_sdi()
1460 dp->clust = clst; /* Current cluster# */ in dir_sdi()
1461 if (!dp->sect) return FR_INT_ERR; in dir_sdi()
1462 dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ in dir_sdi()
1463 dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ in dir_sdi()
1471 /*-----------------------------------------------------------------------*/
1472 /* Directory handling - Move directory table index next */
1473 /*-----------------------------------------------------------------------*/
1482 FATFS *fs = dp->obj.fs; in dir_next()
1487 ofs = dp->dptr + SZDIRE; /* Next entry */ in dir_next()
1488 …if (!dp->sect || ofs >= (DWORD)((_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) re… in dir_next()
1491 dp->sect++; /* Next sector */ in dir_next()
1493 if (!dp->clust) { /* Static table */ in dir_next()
1494 if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ in dir_next()
1495 dp->sect = 0; return FR_NO_FILE; in dir_next()
1499 if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ in dir_next()
1500 clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ in dir_next()
1503 if (clst >= fs->n_fatent) { /* Reached end of dynamic table */ in dir_next()
1506 dp->sect = 0; return FR_NO_FILE; in dir_next()
1508 clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ in dir_next()
1512 /* Clean-up the stretched table */ in dir_next()
1513 if (_FS_EXFAT) dp->obj.stat |= 4; /* The directory needs to be updated */ in dir_next()
1515 mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */ in dir_next()
1516 …for (n = 0, fs->winsect = clust2sect(fs, clst); n < fs->csize; n++, fs->winsect++) { /* Fill the n… in dir_next()
1517 fs->wflag = 1; in dir_next()
1520 fs->winsect -= n; /* Restore window offset */ in dir_next()
1522 if (!stretch) dp->sect = 0; /* If no stretch, report EOT (this is to suppress warning) */ in dir_next()
1523 dp->sect = 0; return FR_NO_FILE; /* Report EOT */ in dir_next()
1526 dp->clust = clst; /* Initialize data for new cluster */ in dir_next()
1527 dp->sect = clust2sect(fs, clst); in dir_next()
1531 dp->dptr = ofs; /* Current entry */ in dir_next()
1532 dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ in dir_next()
1541 /*-----------------------------------------------------------------------*/
1542 /* Directory handling - Reserve a block of directory entries */
1543 /*-----------------------------------------------------------------------*/
1553 FATFS *fs = dp->obj.fs;
1560 res = move_window(fs, dp->sect);
1563 …if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] …
1565 if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) {
1584 /*-----------------------------------------------------------------------*/
1585 /* FAT: Directory handling - Load/Store start cluster number */
1586 /*-----------------------------------------------------------------------*/
1591 const BYTE* dir /* Pointer to the key entry */
1597 if (fs->fs_type == FS_FAT32) {
1609 BYTE* dir, /* Pointer to the key entry */
1614 if (fs->fs_type == FS_FAT32) {
1623 /*------------------------------------------------------------------------*/
1624 /* FAT-LFN: LFN handling */
1625 /*------------------------------------------------------------------------*/
1627 const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN characters in the direc…
1630 /*--------------------------------------------------------*/
1631 /* FAT-LFN: Compare a part of file name with an LFN entry */
1632 /*--------------------------------------------------------*/
1636 BYTE* dir /* Pointer to the directory entry containing the part of LFN */
1645 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
1666 /*-----------------------------------------------------*/
1667 /* FAT-LFN: Pick a part of file name from an LFN entry */
1668 /*-----------------------------------------------------*/
1672 BYTE* dir /* Pointer to the LFN entry */
1681 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
1704 /*-----------------------------------------*/
1705 /* FAT-LFN: Create an entry of LFN entries */
1706 /*-----------------------------------------*/
1710 BYTE* dir, /* Pointer to the LFN entry to be created */
1711 BYTE ord, /* LFN order (1-20) */
1712 BYTE sum /* Checksum of the corresponding SFN */
1724 i = (ord - 1) * 13; /* Get offset in the LFN working buffer */
1741 /*-----------------------------------------------------------------------*/
1742 /* FAT-LFN: Create a Numbered SFN */
1743 /*-----------------------------------------------------------------------*/
1747 BYTE* dst, /* Pointer to the buffer to store numbered SFN */
1748 const BYTE* src, /* Pointer to SFN */
1753 BYTE ns[8], c;
1777 c = (BYTE)((seq % 16) + '0');
1779 ns[i--] = c;
1787 if (j == i - 1) break;
1800 /*-----------------------------------------------------------------------*/
1801 /* FAT-LFN: Calculate checksum of an SFN entry */
1802 /*-----------------------------------------------------------------------*/
1805 BYTE sum_sfn (
1806 const BYTE* dir /* Pointer to the SFN entry */
1809 BYTE sum = 0;
1812 do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
1821 /*-----------------------------------------------------------------------*/
1823 /*-----------------------------------------------------------------------*/
1827 const BYTE* dir /* Directory entry block to be calculated */
1868 BYTE dat, /* Data to be sumed */
1879 /*------------------------------------------------------*/
1881 /*------------------------------------------------------*/
1885 BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */
1901 fno->fname[di] = w; /* Store it */
1910 w = ff_convert(w, 0); /* Unicode -> OEM */
1912 if (_DF1S && w >= 0x100) { /* Put 1st byte if it is a DBC (always false at SBCS cfg) */
1913 fno->fname[di++] = (char)(w >> 8);
1916 fno->fname[di++] = (char)w;
1919 if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object? */
1920 fno->fname[di] = 0; /* Terminate file name */
1922 fno->altname[0] = 0; /* No SFN */
1923 fno->fattrib = dirb[XDIR_Attr]; /* Attribute */
1924 fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */
1925 fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */
1926 fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */
1932 /*-----------------------------------*/
1934 /*-----------------------------------*/
1943 BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
1947 res = move_window(dp->obj.fs, dp->sect);
1949 if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR;
1950 mem_cpy(dirb, dp->dir, SZDIRE);
1956 res = move_window(dp->obj.fs, dp->sect);
1958 if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR;
1959 mem_cpy(dirb + SZDIRE, dp->dir, SZDIRE);
1967 res = move_window(dp->obj.fs, dp->sect);
1969 if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR;
1970 mem_cpy(dirb + i, dp->dir, SZDIRE);
1982 /*------------------------------------------------*/
1984 /*------------------------------------------------*/
1995 dp->obj.fs = obj->fs;
1996 dp->obj.sclust = obj->c_scl;
1997 dp->obj.stat = (BYTE)obj->c_size;
1998 dp->obj.objsize = obj->c_size & 0xFFFFFF00;
1999 dp->blk_ofs = obj->c_ofs;
2001 res = dir_sdi(dp, dp->blk_ofs); /* Goto the block location */
2011 /*-----------------------------------------------*/
2013 /*-----------------------------------------------*/
2021 BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */
2028 res = dir_sdi(dp, dp->blk_ofs);
2030 res = move_window(dp->obj.fs, dp->sect);
2032 mem_cpy(dp->dir, dirb, SZDIRE);
2033 dp->obj.fs->wflag = 1;
2034 if (--nent == 0) break;
2043 /*-------------------------------------------*/
2045 /*-------------------------------------------*/
2049 BYTE* dirb, /* Pointer to the direcotry entry block buffer */
2054 BYTE nb, nc;
2084 /*-----------------------------------------------------------------------*/
2086 /*-----------------------------------------------------------------------*/
2095 FATFS *fs = dp->obj.fs;
2096 BYTE a, c;
2098 BYTE ord = 0xFF, sum = 0xFF;
2101 while (dp->sect) {
2102 res = move_window(fs, dp->sect);
2104 c = dp->dir[DIR_Name]; /* Test for the entry type */
2107 if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
2112 dp->blk_ofs = dp->dptr; /* Get location of the block */
2115 dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */
2123 dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
2130 sum = dp->dir[LDIR_Chksum];
2131 c &= (BYTE)~LLEF; ord = c;
2132 dp->blk_ofs = dp->dptr;
2135 … ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
2137 if (ord || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
2138 dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
2153 if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */
2161 /*-----------------------------------------------------------------------*/
2162 /* Directory handling - Find an object in the directory */
2163 /*-----------------------------------------------------------------------*/
2171 FATFS *fs = dp->obj.fs;
2172 BYTE c;
2174 BYTE a, ord, sum;
2180 if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
2181 BYTE nc;
2183 WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
2186 …if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip the comparison if hash value mi…
2187 …for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare…
2189 if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break;
2191 if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */
2198 ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */
2201 res = move_window(fs, dp->sect);
2203 c = dp->dir[DIR_Name];
2206 dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK;
2208 ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */
2211 if (!(dp->fn[NSFLAG] & NS_NOLFN)) {
2213 sum = dp->dir[LDIR_Chksum];
2214 c &= (BYTE)~LLEF; ord = c; /* LFN start order */
2215 dp->blk_ofs = dp->dptr; /* Start offset of LFN */
2218 … ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
2221 if (!ord && sum == sum_sfn(dp->dir)) break; /* LFN matched? */
2222 if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */
2223 ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */
2227 dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK;
2228 …if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry?…
2240 /*-----------------------------------------------------------------------*/
2242 /*-----------------------------------------------------------------------*/
2250 FATFS *fs = dp->obj.fs;
2253 BYTE sn[12], sum;
2256 if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */
2257 for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */
2260 if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
2266 dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set block position */
2268 if (dp->obj.sclust != 0 && (dp->obj.stat & 4)) { /* Has the sub-directory been stretched? */
2269 dp->obj.stat &= 3;
2270 dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase object size by cluster size */
2271 res = fill_fat_chain(&dp->obj); /* Complement FAT chain if needed */
2273 res = load_obj_dir(&dj, &dp->obj);
2275 st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */
2276 st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
2277 fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
2282 create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */
2287 mem_cpy(sn, dp->fn, 12);
2289 dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */
2291 gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */
2297 dp->fn[NSFLAG] = sn[NSFLAG];
2303 if (res == FR_OK && --nent) { /* Set LFN entry if needed */
2304 res = dir_sdi(dp, dp->dptr - nent * SZDIRE);
2306 sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */
2308 res = move_window(fs, dp->sect);
2310 put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum);
2311 fs->wflag = 1;
2313 } while (res == FR_OK && --nent);
2324 res = move_window(fs, dp->sect);
2326 mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */
2327 mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */
2329 dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */
2331 fs->wflag = 1;
2343 /*-----------------------------------------------------------------------*/
2345 /*-----------------------------------------------------------------------*/
2353 FATFS *fs = dp->obj.fs;
2355 DWORD last = dp->dptr;
2357 …res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry blo…
2360 res = move_window(fs, dp->sect);
2363 if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
2364 dp->dir[XDIR_Type] &= 0x7F;
2366 dp->dir[DIR_Name] = DDEM;
2368 fs->wflag = 1;
2369 …if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been dele…
2376 res = move_window(fs, dp->sect);
2378 dp->dir[DIR_Name] = DDEM;
2379 fs->wflag = 1;
2391 /*-----------------------------------------------------------------------*/
2393 /*-----------------------------------------------------------------------*/
2406 FATFS *fs = dp->obj.fs;
2410 fno->fname[0] = 0; /* Invaidate file info */
2411 if (!dp->sect) return; /* Exit if read pointer has reached end of directory */
2415 if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
2416 get_xdir_info(fs->dirbuf, fno);
2421 if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */
2423 while ((w = fs->lfnbuf[j++]) != 0) { /* Get an LFN character */
2425 w = ff_convert(w, 0); /* Unicode -> OEM */
2427 if (_DF1S && w >= 0x100) { /* Put 1st byte if it is a DBC (always false at SBCS cfg) */
2428 fno->fname[i++] = (char)(w >> 8);
2432 fno->fname[i++] = (TCHAR)w;
2434 fno->fname[i] = 0; /* Terminate the LFN */
2439 lfv = fno->fname[i]; /* LFN is exist if non-zero */
2441 c = (TCHAR)dp->dir[i++];
2445 if (!lfv) fno->fname[j] = '.';
2446 fno->altname[j++] = '.';
2449 if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dp->dir[i])) {
2450 c = c << 8 | dp->dir[i++];
2452 c = ff_convert(c, 1); /* OEM -> Unicode */
2455 fno->altname[j] = c;
2457 if (IsUpper(c) && (dp->dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY))) {
2460 fno->fname[j] = c;
2465 fno->fname[j] = 0;
2466 …if (!dp->dir[DIR_NTres]) j = 0; /* Altname is no longer needed if neither LFN nor case info is exi…
2468 fno->altname[j] = 0; /* Terminate the SFN */
2470 #else /* Non-LFN configuration */
2473 c = (TCHAR)dp->dir[i++];
2476 if (i == 9) fno->fname[j++] = '.'; /* Insert a . if extension is exist */
2477 fno->fname[j++] = c;
2479 fno->fname[j] = 0;
2482 fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */
2483 fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */
2484 tm = ld_dword(dp->dir + DIR_ModTime); /* Timestamp */
2485 fno->ftime = (WORD)tm; fno->fdate = (WORD)(tm >> 16);
2493 /*-----------------------------------------------------------------------*/
2495 /*-----------------------------------------------------------------------*/
2505 chr = (BYTE)*(*ptr)++; /* Get a byte */
2506 if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */
2508 if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */
2510 if (IsDBCS1(chr) && IsDBCS2(**ptr)) { /* Get DBC 2nd byte if needed */
2511 chr = chr << 8 | (BYTE)*(*ptr)++;
2525 int skip, /* Number of pre-skip chars (number of ?s) */
2534 while (skip--) { /* Pre-skip name chars */
2565 /*-----------------------------------------------------------------------*/
2567 /*-----------------------------------------------------------------------*/
2576 BYTE b, cf;
2582 p = *path; lfn = dp->obj.fs->lfnbuf; si = di = 0;
2593 if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
2594 b = (BYTE)p[si++]; /* Get 2nd byte */
2607 if ((di == 1 && lfn[di - 1] == '.') ||
2608 (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */
2611 dp->fn[i] = (i < di) ? '.' : ' ';
2612 dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
2617 w = lfn[di - 1];
2619 di--;
2625 mem_set(dp->fn, ' ', 11);
2628 while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
2650 w = ff_convert(w, 0); /* Unicode -> OEM code */
2651 if (w) w = ExCvt[w - 0x80]; /* Convert extended character to upper (SBCS) */
2653 w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */
2659 if (i >= ni - 1) {
2662 dp->fn[i++] = (BYTE)(w >> 8);
2671 b |= 1; w -= 0x20;
2676 dp->fn[i++] = (BYTE)w;
2679 …if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it…
2688 dp->fn[NSFLAG] = cf; /* SFN is created */
2693 #else /* _USE_LFN != 0 : Non-LFN configuration */
2694 BYTE c, d, *sfn;
2699 p = *path; sfn = dp->fn;
2705 c = (BYTE)p[si++];
2716 c = (BYTE)p[si++];
2729 c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */
2736 if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false at SBCS cfg.) */
2737 d = (BYTE)p[si++]; /* Get 2nd byte */
2738 if (!IsDBCS2(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */
2743 if (IsLower(c)) c -= 0x20; /* To upper */
2760 /*-----------------------------------------------------------------------*/
2762 /*-----------------------------------------------------------------------*/
2767 const TCHAR* path /* Full-path string to find a file or directory */
2771 BYTE ns;
2772 _FDID *obj = &dp->obj;
2773 FATFS *fs = obj->fs;
2778 obj->sclust = fs->cdir; /* Start from the current directory */
2783 obj->sclust = 0; /* Start from the root directory */
2786 if (fs->fs_type == FS_EXFAT && obj->sclust) { /* Retrieve the sub-directory status if needed */
2789 obj->c_scl = fs->cdc_scl;
2790 obj->c_size = fs->cdc_size;
2791 obj->c_ofs = fs->cdc_ofs;
2794 obj->objsize = ld_dword(fs->dirbuf + XDIR_FileSize);
2795 obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;
2800 dp->fn[NSFLAG] = NS_NONAME;
2808 ns = dp->fn[NSFLAG];
2813 dp->fn[NSFLAG] = NS_NONAME;
2822 /* Get into the sub-directory */
2823 if (!(obj->attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */
2827 if (fs->fs_type == FS_EXFAT) {
2828 obj->c_scl = obj->sclust; /* Save containing directory information for next dir */
2829 obj->c_size = ((DWORD)obj->objsize & 0xFFFFFF00) | obj->stat;
2830 obj->c_ofs = dp->blk_ofs;
2831 obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Open next directory */
2832 obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;
2833 obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
2837 obj->sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */
2848 /*-----------------------------------------------------------------------*/
2850 /*-----------------------------------------------------------------------*/
2853 int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */
2859 int vol = -1;
2872 i = *tp++ - '0';
2886 if (IsLower(tc)) tc -= 0x20;
2909 /*-----------------------------------------------------------------------*/
2911 /*-----------------------------------------------------------------------*/
2914 BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */
2916 DWORD sect /* Sector# (lba) to check if it is an FAT-VBR or not */
2919 fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */
2920 if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */
2922 …if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always placed …
2924 …if (fs->win[BS_JmpBoot] == 0xE9 || (fs->win[BS_JmpBoot] == 0xEB && fs->win[BS_JmpBoot + 2] == 0x90…
2925 if ((ld_dword(fs->win + BS_FilSysType) & 0xFFFFFF) == 0x544146) return 0; /* Check "FAT" string */
2926 if (ld_dword(fs->win + BS_FilSysType32) == 0x33544146) return 0; /* Check "FAT3" string */
2929 if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1;
2937 /*-----------------------------------------------------------------------*/
2939 /*-----------------------------------------------------------------------*/
2945 BYTE mode /* !=0: Check write protection for write access */
2948 BYTE fmt, *pt;
2951 DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
2969 mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */
2970 if (fs->fs_type) { /* If the volume has been mounted */
2971 stat = disk_status(fs->drv);
2983 fs->fs_type = 0; /* Clear the file system object */
2984 fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
2985 stat = disk_initialize(fs->drv); /* Initialize the physical drive */
2993 if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
2994 if (SS(fs) > _MAX_SS || SS(fs) < _MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
2998 fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
2999 if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
3000 for (i = 0; i < 4; i++) { /* Get partition offset */
3001 pt = fs->win + (MBR_Table + i * SZ_PTE);
3004 i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */
3005 if (i) i--;
3009 } while (!LD2PT(vol) && fmt >= 2 && ++i < 4);
3011 if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */
3020 for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
3023 …if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT revision (Mus…
3025 …if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) /* (BPB_BytsPerSecEx must be equal to the physical s…
3028 maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
3029 if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
3031 fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
3033 fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */
3034 if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
3036 fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
3037 if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
3039 nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
3041 fs->n_fatent = nclst + 2;
3044 fs->volbase = bsect;
3045 fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
3046 fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
3047 …if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size mus…
3048 fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
3051 if (move_window(fs, clust2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR;
3053 if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
3057 fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
3059 fmt = FS_EXFAT; /* FAT sub-type */
3063 …if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must …
3065 fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
3066 if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
3067 fs->fsize = fasize;
3069 fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
3070 if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
3071 fasize *= fs->n_fats; /* Number of sectors for FAT area */
3073 fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
3074 …if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of…
3076 fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
3077 if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
3079 tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
3080 if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
3082 nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
3086 sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
3088 nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
3095 fs->n_fatent = nclst + 2; /* Number of FAT entries */
3096 fs->volbase = bsect; /* Volume start sector */
3097 fs->fatbase = bsect + nrsv; /* FAT start sector */
3098 fs->database = bsect + sysect; /* Data start sector */
3100 …if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) …
3101 if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
3102 fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
3103 szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
3105 if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM;/* (BPB_RootEntCnt must not be 0) */
3106 fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
3108 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
3110 …if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not …
3114 fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
3115 fs->fsi_flag = 0x80;
3118 && ld_word(fs->win + BPB_FSInfo32) == 1
3121 fs->fsi_flag = 0;
3122 if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSINFO data if available */
3123 && ld_dword(fs->win + FSI_LeadSig) == 0x41615252
3124 && ld_dword(fs->win + FSI_StrucSig) == 0x61417272)
3127 fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
3130 fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
3138 fs->fs_type = fmt; /* FAT sub-type */
3139 fs->id = ++Fsid; /* File system mount ID */
3141 fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
3143 fs->dirbuf = DirBuf; /* Static directory block working buuffer */
3147 fs->cdir = 0; /* Initialize current directory */
3158 /*-----------------------------------------------------------------------*/
3160 /*-----------------------------------------------------------------------*/
3171 …if (!obj || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) …
3175 *fs = obj->fs; /* Owner file sytem object */
3176 ENTER_FF(obj->fs); /* Lock file system */
3185 /*---------------------------------------------------------------------------
3189 ----------------------------------------------------------------------------*/
3193 /*-----------------------------------------------------------------------*/
3195 /*-----------------------------------------------------------------------*/
3200 BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */
3219 if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
3221 cfs->fs_type = 0; /* Clear old fs object */
3225 fs->fs_type = 0; /* Clear new fs object */
3227 if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
3241 /*-----------------------------------------------------------------------*/
3243 /*-----------------------------------------------------------------------*/
3248 BYTE mode /* Access mode and file open mode flags */
3302 if (fs->fs_type == FS_EXFAT) {
3304 fp->obj.fs = fs;
3305 fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus);
3306 fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
3307 fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
3309 st_dword(fs->dirbuf + XDIR_CrtTime, dw); /* Set created time */
3310 fs->dirbuf[XDIR_CrtTime10] = 0;
3311 st_dword(fs->dirbuf + XDIR_ModTime, dw); /* Set modified time */
3312 fs->dirbuf[XDIR_ModTime10] = 0;
3313 fs->dirbuf[XDIR_Attr] = AM_ARC; /* Reset attribute */
3314 st_dword(fs->dirbuf + XDIR_FstClus, 0); /* Reset file allocation info */
3315 st_qword(fs->dirbuf + XDIR_FileSize, 0);
3316 st_qword(fs->dirbuf + XDIR_ValidFileSize, 0);
3317 fs->dirbuf[XDIR_GenFlags] = 1;
3319 if (res == FR_OK && fp->obj.sclust) { /* Remove the cluster chain if exist */
3320 res = remove_chain(&fp->obj, fp->obj.sclust, 0);
3321 fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */
3333 fs->wflag = 1;
3336 dw = fs->winsect;
3340 fs->last_clst = cl - 1; /* Reuse the cluster hole */
3360 fp->dir_sect = fs->winsect; /* Pointer to the directory entry */
3361 fp->dir_ptr = dj.dir;
3363 fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
3364 if (!fp->obj.lockid) res = FR_INT_ERR;
3381 if (fs->fs_type == FS_EXFAT) {
3382 fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Get allocation info */
3383 fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
3384 fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
3385 fp->obj.c_scl = dj.obj.sclust;
3386 fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
3387 fp->obj.c_ofs = dj.blk_ofs;
3391 fp->obj.sclust = ld_clust(fs, dj.dir); /* Get allocation info */
3392 fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
3395 fp->cltbl = 0; /* Disable fast seek mode */
3397 fp->obj.fs = fs; /* Validate the file object */
3398 fp->obj.id = fs->id;
3399 fp->flag = mode; /* Set file access mode */
3400 fp->err = 0; /* Clear error flag */
3401 fp->sect = 0; /* Invalidate current data sector */
3402 fp->fptr = 0; /* Set file pointer top of the file */
3405 mem_set(fp->buf, 0, _MAX_SS); /* Clear sector buffer */
3407 …if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is spec…
3408 fp->fptr = fp->obj.objsize; /* Offset to seek */
3409 bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */
3410 clst = fp->obj.sclust; /* Follow the cluster chain */
3411 for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) {
3412 clst = get_fat(&fp->obj, clst);
3416 fp->clust = clst;
3421 fp->sect = sc + (DWORD)(ofs / SS(fs));
3423 if (disk_read(fs->drv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
3434 if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */
3442 /*-----------------------------------------------------------------------*/
3444 /*-----------------------------------------------------------------------*/
3458 BYTE *rbuff = (BYTE*)buff;
3461 *br = 0; /* Clear read byte counter */
3462 res = validate(&fp->obj, &fs); /* Check validity of the file object */
3463 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
3464 if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
3465 remain = fp->obj.objsize - fp->fptr;
3469 rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
3470 if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
3471 csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */
3473 if (fp->fptr == 0) { /* On the top of the file? */
3474 clst = fp->obj.sclust; /* Follow cluster chain from the origin */
3477 if (fp->cltbl) {
3478 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
3482 clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */
3487 fp->clust = clst; /* Update current cluster */
3489 sect = clust2sect(fs, fp->clust); /* Get current sector */
3494 if (csect + cc > fs->csize) { /* Clip at cluster boundary */
3495 cc = fs->csize - csect;
3497 if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
3500 if (fs->wflag && fs->winsect - sect < cc) {
3501 mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
3504 if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
3505 mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
3513 if (fp->sect != sect) { /* Load data sector if not in cache */
3515 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
3516 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3517 fp->flag &= (BYTE)~FA_DIRTY;
3520 …if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
3523 fp->sect = sect;
3525 rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */
3528 if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
3529 mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
3531 mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
3542 /*-----------------------------------------------------------------------*/
3544 /*-----------------------------------------------------------------------*/
3557 const BYTE *wbuff = (const BYTE*)buff;
3560 *bw = 0; /* Clear write byte counter */
3561 res = validate(&fp->obj, &fs); /* Check validity of the file object */
3562 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
3563 if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
3565 /* Check fptr wrap-around (file size cannot reach 4GiB on FATxx) */
3566 if ((!_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
3567 btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
3571 …wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->o…
3572 if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
3573 csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */
3575 if (fp->fptr == 0) { /* On the top of the file? */
3576 clst = fp->obj.sclust; /* Follow from the origin */
3578 clst = create_chain(&fp->obj, 0); /* create a new cluster chain */
3582 if (fp->cltbl) {
3583 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
3587 clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */
3593 fp->clust = clst; /* Update current cluster */
3594 if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */
3597 …if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sec…
3599 if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
3600 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3601 fp->flag &= (BYTE)~FA_DIRTY;
3604 sect = clust2sect(fs, fp->clust); /* Get current sector */
3609 if (csect + cc > fs->csize) { /* Clip at cluster boundary */
3610 cc = fs->csize - csect;
3612 if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
3615 …if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
3616 mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
3617 fs->wflag = 0;
3620 if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
3621 mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
3622 fp->flag &= (BYTE)~FA_DIRTY;
3630 if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */
3632 fs->winsect = sect;
3635 if (fp->sect != sect && /* Fill sector cache with file data */
3636 fp->fptr < fp->obj.objsize &&
3637 disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) {
3641 fp->sect = sect;
3643 wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */
3646 if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
3647 mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
3648 fs->wflag = 1;
3650 mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
3651 fp->flag |= FA_DIRTY;
3655 fp->flag |= FA_MODIFIED; /* Set file change flag */
3663 /*-----------------------------------------------------------------------*/
3665 /*-----------------------------------------------------------------------*/
3674 BYTE *dir;
3679 res = validate(&fp->obj, &fs); /* Check validity of the file object */
3681 if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */
3683 if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */
3684 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
3685 fp->flag &= (BYTE)~FA_DIRTY;
3691 if (fs->fs_type == FS_EXFAT) {
3692 res = fill_fat_chain(&fp->obj); /* Create FAT chain if needed */
3697 res = load_obj_dir(&dj, &fp->obj); /* Load directory entry block */
3699 fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive bit */
3700 fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation info */
3701 st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust);
3702 st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize);
3703 st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize);
3704 st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */
3705 fs->dirbuf[XDIR_ModTime10] = 0;
3706 st_dword(fs->dirbuf + XDIR_AccTime, 0);
3710 fp->flag &= (BYTE)~FA_MODIFIED;
3718 res = move_window(fs, fp->dir_sect);
3720 dir = fp->dir_ptr;
3722 st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation info */
3723 st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */
3726 fs->wflag = 1;
3728 fp->flag &= (BYTE)~FA_MODIFIED;
3742 /*-----------------------------------------------------------------------*/
3744 /*-----------------------------------------------------------------------*/
3758 res = validate(&fp->obj, &fs); /* Lock volume */
3761 res = dec_lock(fp->obj.lockid); /* Decrement file open counter */
3765 fp->obj.fs = 0; /* Invalidate file object */
3779 /*-----------------------------------------------------------------------*/
3781 /*-----------------------------------------------------------------------*/
3795 CurrVol = (BYTE)vol; /* Set it as current volume */
3819 fs->cdir = dj.obj.sclust; /* It is the start directory itself */
3821 if (fs->fs_type == FS_EXFAT) {
3822 fs->cdc_scl = dj.obj.c_scl;
3823 fs->cdc_size = dj.obj.c_size;
3824 fs->cdc_ofs = dj.obj.c_ofs;
3828 if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */
3830 if (fs->fs_type == FS_EXFAT) {
3831 fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */
3832 fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */
3833 fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
3834 fs->cdc_ofs = dj.blk_ofs;
3838 fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */
3876 …if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) …
3877 dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */
3878 while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */
3899 while (n) buff[--i] = fno.fname[--n];
3900 buff[--i] = '/';
3909 if (i == len) { /* Root-directory */
3911 } else { /* Sub-directroy */
3930 /*-----------------------------------------------------------------------*/
3932 /*-----------------------------------------------------------------------*/
3947 res = validate(&fp->obj, &fs); /* Check validity of the file object */
3948 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
3950 if (fp->cltbl) { /* Fast seek */
3952 tbl = fp->cltbl;
3954 cl = fp->obj.sclust; /* Origin of the chain */
3961 cl = get_fat(&fp->obj, cl);
3968 } while (cl < fs->n_fatent); /* Repeat until end of chain */
3970 *fp->cltbl = ulen; /* Number of items used */
3977 if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */
3978 fp->fptr = ofs; /* Set file pointer */
3980 fp->clust = clmt_clust(fp, ofs - 1);
3981 dsc = clust2sect(fs, fp->clust);
3983 dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1);
3984 if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */
3987 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
3988 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3989 fp->flag &= (BYTE)~FA_DIRTY;
3992 …if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector …
3994 fp->sect = dsc;
4004 …if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4GiB-1 if at FATxx…
4006 …if (ofs > fp->obj.objsize && (_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, cli…
4007 ofs = fp->obj.objsize;
4009 ifptr = fp->fptr;
4010 fp->fptr = nsect = 0;
4012 bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */
4014 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
4015 fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */
4016 ofs -= fp->fptr;
4017 clst = fp->clust;
4019 clst = fp->obj.sclust; /* start from the first cluster */
4022 clst = create_chain(&fp->obj, 0);
4025 fp->obj.sclust = clst;
4028 fp->clust = clst;
4032 ofs -= bcs; fp->fptr += bcs;
4034 if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
4035 …if (_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to gen…
4036 fp->obj.objsize = fp->fptr;
4037 fp->flag |= FA_MODIFIED;
4039 clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */
4046 clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */
4049 if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
4050 fp->clust = clst;
4052 fp->fptr += ofs;
4060 …if (!_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is ex…
4061 fp->obj.objsize = fp->fptr;
4062 fp->flag |= FA_MODIFIED;
4064 if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */
4067 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
4068 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4069 fp->flag &= (BYTE)~FA_DIRTY;
4072 …if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache …
4074 fp->sect = nsect;
4084 /*-----------------------------------------------------------------------*/
4086 /*-----------------------------------------------------------------------*/
4102 obj = &dp->obj;
4105 obj->fs = fs;
4109 if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */
4110 if (obj->attr & AM_DIR) { /* This object is a sub-directory */
4112 if (fs->fs_type == FS_EXFAT) {
4113 obj->c_scl = obj->sclust; /* Save containing directory inforamation */
4114 obj->c_size = ((DWORD)obj->objsize & 0xFFFFFF00) | obj->stat;
4115 obj->c_ofs = dp->blk_ofs;
4116 obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Get object location and status */
4117 obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
4118 obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;
4122 obj->sclust = ld_clust(fs, dp->dir); /* Get object location */
4129 obj->id = fs->id;
4133 if (obj->sclust) {
4134 obj->lockid = inc_lock(dp, 0); /* Lock the sub directory */
4135 if (!obj->lockid) res = FR_TOO_MANY_OPEN_FILES;
4137 obj->lockid = 0; /* Root directory need not to be locked */
4146 if (res != FR_OK) obj->fs = 0; /* Invalidate the directory object if function faild */
4154 /*-----------------------------------------------------------------------*/
4156 /*-----------------------------------------------------------------------*/
4166 res = validate(&dp->obj, &fs); /* Check validity of the file object */
4169 if (dp->obj.lockid) { /* Decrement sub-directory open counter */
4170 res = dec_lock(dp->obj.lockid);
4175 dp->obj.fs = 0; /* Invalidate directory object */
4187 /*-----------------------------------------------------------------------*/
4189 /*-----------------------------------------------------------------------*/
4201 res = validate(&dp->obj, &fs); /* Check validity of the directory object */
4240 /*-----------------------------------------------------------------------*/
4242 /*-----------------------------------------------------------------------*/
4254 …if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */
4255 if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */
4257 if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */
4265 /*-----------------------------------------------------------------------*/
4267 /*-----------------------------------------------------------------------*/
4279 dp->pat = pattern; /* Save pointer to pattern string */
4292 /*-----------------------------------------------------------------------*/
4294 /*-----------------------------------------------------------------------*/
4327 /*-----------------------------------------------------------------------*/
4329 /*-----------------------------------------------------------------------*/
4341 BYTE *p;
4350 if (fs->free_clst <= fs->n_fatent - 2) {
4351 *nclst = fs->free_clst;
4355 if (fs->fs_type == FS_FAT12) { /* FAT12: Sector unalighed FAT entries */
4362 } while (++clst < fs->n_fatent);
4365 if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan bitmap table */
4366 BYTE bm;
4369 clst = fs->n_fatent - 2;
4370 sect = fs->database;
4374 for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) {
4383 clst = fs->n_fatent; sect = fs->fatbase;
4389 p = fs->win;
4392 if (fs->fs_type == FS_FAT16) {
4394 p += 2; i -= 2;
4397 p += 4; i -= 4;
4399 } while (--clst);
4403 fs->free_clst = nfree; /* Now free_clst is valid */
4404 fs->fsi_flag |= 1; /* FSInfo is to be updated */
4414 /*-----------------------------------------------------------------------*/
4416 /*-----------------------------------------------------------------------*/
4427 res = validate(&fp->obj, &fs); /* Check validity of the file object */
4428 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
4429 if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
4431 if (fp->obj.objsize > fp->fptr) {
4432 if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
4433 res = remove_chain(&fp->obj, fp->obj.sclust, 0);
4434 fp->obj.sclust = 0;
4436 ncl = get_fat(&fp->obj, fp->clust);
4440 if (res == FR_OK && ncl < fs->n_fatent) {
4441 res = remove_chain(&fp->obj, ncl, fp->clust);
4444 fp->obj.objsize = fp->fptr; /* Set file size to current R/W point */
4445 fp->flag |= FA_MODIFIED;
4447 if (res == FR_OK && (fp->flag & FA_DIRTY)) {
4448 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) {
4451 fp->flag &= (BYTE)~FA_DIRTY;
4464 /*-----------------------------------------------------------------------*/
4466 /*-----------------------------------------------------------------------*/
4505 if (fs->fs_type == FS_EXFAT) {
4506 obj.sclust = dclst = ld_dword(fs->dirbuf + XDIR_FstClus);
4507 obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
4508 obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
4514 if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory ? */
4516 if (dclst == fs->cdir) { /* Is it the current directory? */
4521 sdj.obj.fs = fs; /* Open the sub-directory */
4524 if (fs->fs_type == FS_EXFAT) {
4559 /*-----------------------------------------------------------------------*/
4561 /*-----------------------------------------------------------------------*/
4570 BYTE *dir;
4588 dj.obj.objsize = (DWORD)fs->csize * SS(fs);
4597 dir = fs->win;
4599 if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) {
4607 if (fs->fs_type == FS_FAT32 && pcl == fs->dirbase) pcl = 0;
4610 for (n = fs->csize; n; n--) { /* Write dot entries and clear following sectors */
4611 fs->winsect = dsc++;
4612 fs->wflag = 1;
4621 if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
4622 st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
4623 st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
4624 st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */
4625 st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize);
4626 fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag (contiguous) */
4627 fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
4636 fs->wflag = 1;
4652 /*-----------------------------------------------------------------------*/
4654 /*-----------------------------------------------------------------------*/
4664 BYTE buf[_FS_EXFAT ? SZDIRE * 2 : 24], *dir;
4681 if (fs->fs_type == FS_EXFAT) { /* At exFAT */
4682 BYTE nf, nn;
4685 mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */
4694 nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
4695 nh = ld_word(fs->dirbuf + XDIR_NameHash);
4696 mem_cpy(fs->dirbuf, buf, SZDIRE * 2);
4697 fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
4698 st_word(fs->dirbuf + XDIR_NameHash, nh);
4699 /* Start of critical section where any interruption can cause a cross-link */
4718 fs->wflag = 1;
4719 …AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */
4724 /* Start of critical section where any interruption can cause a cross-link */
4726 dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */
4729 fs->wflag = 1;
4758 /*-----------------------------------------------------------------------*/
4760 /*-----------------------------------------------------------------------*/
4764 BYTE attr, /* Attribute bits */
4765 BYTE mask /* Attribute mask to change */
4783 if (fs->fs_type == FS_EXFAT) {
4784 …fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute …
4789 … dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
4790 fs->wflag = 1;
4803 /*-----------------------------------------------------------------------*/
4805 /*-----------------------------------------------------------------------*/
4826 if (fs->fs_type == FS_EXFAT) {
4827 st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
4832 st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
4833 fs->wflag = 1;
4848 /*-----------------------------------------------------------------------*/
4850 /*-----------------------------------------------------------------------*/
4877 if (fs->fs_type == FS_EXFAT) {
4883 w = ff_convert(w, 0); /* Unicode -> OEM */
4900 label[di++] = ff_convert(w, 1); /* OEM -> Unicode */
4908 } while (label[--di] == ' ');
4920 res = move_window(fs, fs->volbase);
4922 switch (fs->fs_type) {
4927 *vsn = ld_dword(fs->win + di);
4937 /*-----------------------------------------------------------------------*/
4939 /*-----------------------------------------------------------------------*/
4948 BYTE dirvn[22];
4963 if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
4968 w = (i < slen && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
4981 for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */
4988 w = (BYTE)label[i++];
4990 w = (j < 10 && i < slen && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
4995 if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */
4997 if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */
5006 if (w >= 0x100) dirvn[j++] = (BYTE)(w >> 8);
5007 dirvn[j++] = (BYTE)w;
5020 if (_FS_EXFAT && fs->fs_type == FS_EXFAT) {
5021 dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); /* Change the volume label */
5030 fs->wflag = 1;
5039 if (_FS_EXFAT && fs->fs_type == FS_EXFAT) {
5041 dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2);
5047 fs->wflag = 1;
5064 /*-----------------------------------------------------------------------*/
5066 /*-----------------------------------------------------------------------*/
5071 BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */
5079 res = validate(&fp->obj, &fs); /* Check validity of the file object */
5080 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
5081 if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
5083 …if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size li…
5085 n = (DWORD)fs->csize * SS(fs); /* Cluster size */
5086 tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */
5087 stcl = fs->last_clst; lclst = 0;
5088 if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2;
5091 if (fs->fs_type == FS_EXFAT) {
5098 lclst = scl + tcl - 1;
5100 lclst = scl - 1;
5108 n = get_fat(&fp->obj, clst);
5109 if (++clst >= fs->n_fatent) clst = 2;
5121 for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */
5127 lclst = scl - 1;
5133 fs->last_clst = lclst; /* Set suggested start cluster to start next */
5135 fp->obj.sclust = scl; /* Update object allocation information */
5136 fp->obj.objsize = fsz;
5137 if (_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */
5138 fp->flag |= FA_MODIFIED;
5139 if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */
5140 fs->free_clst -= tcl;
5141 fs->fsi_flag |= 1;
5154 /*-----------------------------------------------------------------------*/
5156 /*-----------------------------------------------------------------------*/
5160 UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ argument
5170 BYTE *dbuf;
5173 *bf = 0; /* Clear transfer byte counter */
5174 res = validate(&fp->obj, &fs); /* Check validity of the file object */
5175 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
5176 if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
5178 remain = fp->obj.objsize - fp->fptr;
5182 fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
5183 csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */
5184 if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
5186 clst = (fp->fptr == 0) ? /* On the top of the file? */
5187 fp->obj.sclust : get_fat(&fp->obj, fp->clust);
5190 fp->clust = clst; /* Update current cluster */
5193 sect = clust2sect(fs, fp->clust); /* Get current data sector */
5198 dbuf = fs->win;
5200 if (fp->sect != sect) { /* Fill sector cache with file data */
5202 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
5203 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
5204 fp->flag &= (BYTE)~FA_DIRTY;
5207 if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
5209 dbuf = fp->buf;
5211 fp->sect = sect;
5212 rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */
5214 rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */
5225 /*-----------------------------------------------------------------------*/
5227 /*-----------------------------------------------------------------------*/
5231 BYTE opt, /* Format option */
5232 DWORD au, /* Size of allocation unit [byte] */
5239 …static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT12/16 volum…
5240 …static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (12…
5241 BYTE fmt, sys, *buf, *pte, pdrv, part;
5257 if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear mounted volume */
5259 part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */
5265 …_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* …
5268 if (ss > _MAX_SS || ss < _MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
5272 …if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Che…
5276 buf = (BYTE*)work; /* Working buffer */
5278 szb_buf = sz_buf * ss; /* Size of working buffer (byte) */
5286 pte = buf + (MBR_Table + (part - 1) * SZ_PTE);
5291 /* Create a single-partition in this function */
5295 sz_vol -= b_vol; /* Volume size */
5299 /* Pre-determine the FAT type */
5308 if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */
5312 if (!(opt & FM_FAT)) return FR_INVALID_PARAMETER; /* no-FAT? */
5321 BYTE b;
5325 tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */
5329 if (!au) { /* au auto-selection */
5335 sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
5336 …b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boun…
5338 n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
5343 tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */
5345 /* Create a compressed up-case table */
5352 ch = ff_wtoupper(si); /* Get an up-case char */
5354 si++; break; /* Store the up-case char if exist */
5356 …j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */
5358 ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */
5364 if (--j == 0) st = 0;
5370 sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */
5371 sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
5374 n = (i + ss - 1) / ss;
5379 tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */
5383 sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */
5384 nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */
5387 for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ;
5388 for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ;
5391 sect += n; nsect -= n;
5400 st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
5401 st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
5403 do { /* Create chains of bitmap, up-case and root dir */
5406 i += 4; cl++; nb--;
5412 sect += n; nsect -= n;
5421 buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */
5422 st_dword(buf + SZDIRE * 2 + 4, sum);
5430 sect += n; nsect -= n;
5441 st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */
5443 st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */
5448 …BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */
5460 st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */
5472 for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */
5481 /* Pre-determine number of clusters and FAT sub-type */
5483 if (!pau) { /* au auto-selection */
5488 sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */
5493 if (!pau) { /* au auto-selection */
5494 n = sz_vol / 0x1000; /* Volume size in unit of 4KS */
5499 n = n_clst * 2 + 4; /* FAT size [byte] */
5502 n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */
5504 sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */
5512 …n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current dat…
5519 /* Determine number of clusters and final check of validity of the FAT sub-type */
5520 if (sz_vol < b_data + pau * 16 - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
5521 n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau;
5551 tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */
5557 st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
5558 buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
5560 buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */
5563 st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */
5565 st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */
5567 buf[BPB_Media] = 0xF8; /* Media descriptor byte */
5596 st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
5609 st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */
5619 sect += n; nsect -= n;
5628 sect += n; nsect -= n;
5650 buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system type */
5665 pte[PTE_EdSec] = (BYTE)(n >> 2 | 63); /* End sector */
5666 pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */
5681 /*-----------------------------------------------------------------------*/
5683 /*-----------------------------------------------------------------------*/
5686 BYTE pdrv, /* Physical drive number */
5692 BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
5704 if (n == 256) n--;
5705 e_hd = n - 1;
5712 for (i = 0; i < 4; i++, p += SZ_PTE) {
5719 s_part += 63; sz_part -= 63;
5723 e_cyl = b_cyl + p_cyl - 1;
5728 p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
5729 p[3] = (BYTE)b_cyl; /* Start cylinder */
5730 p[4] = 0x06; /* System type (temporary setting) */
5732 p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
5733 p[7] = (BYTE)e_cyl; /* End cylinder */
5753 /*-----------------------------------------------------------------------*/
5755 /*-----------------------------------------------------------------------*/
5765 BYTE s[2];
5769 while (n < len - 1) { /* Read characters until buffer gets filled */
5771 #if _STRF_ENCODE == 3 /* Read a character in UTF-8 */
5777 if (c < 0xE0) { /* Two-byte sequence */
5783 if (c < 0xF0) { /* Three-byte sequence */
5788 } else { /* Reject four-byte sequence */
5793 #elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */
5797 #elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */
5810 c = ff_convert(c, 1); /* OEM -> Unicode */
5832 /*-----------------------------------------------------------------------*/
5834 /*-----------------------------------------------------------------------*/
5838 int idx, nchr; /* Write index of buf[] (-1:error), number of chars written */
5839 BYTE buf[64]; /* Write buffer */
5853 if (_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */
5857 i = pb->idx; /* Write index of pb->buf[] */
5861 #if _STRF_ENCODE == 3 /* Write a character in UTF-8 */
5862 if (c < 0x80) { /* 7-bit */
5863 pb->buf[i++] = (BYTE)c;
5865 if (c < 0x800) { /* 11-bit */
5866 pb->buf[i++] = (BYTE)(0xC0 | c >> 6);
5867 } else { /* 16-bit */
5868 pb->buf[i++] = (BYTE)(0xE0 | c >> 12);
5869 pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F));
5871 pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F));
5873 #elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */
5874 pb->buf[i++] = (BYTE)(c >> 8);
5875 pb->buf[i++] = (BYTE)c;
5876 #elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */
5877 pb->buf[i++] = (BYTE)c;
5878 pb->buf[i++] = (BYTE)(c >> 8);
5880 c = ff_convert(c, 0); /* Unicode -> OEM */
5883 pb->buf[i++] = (BYTE)(c >> 8);
5884 pb->buf[i++] = (BYTE)c;
5887 pb->buf[i++] = (BYTE)c;
5890 if (i >= (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */
5891 f_write(pb->fp, pb->buf, (UINT)i, &bw);
5892 i = (bw == (UINT)i) ? 0 : -1;
5894 pb->idx = i;
5895 pb->nchr++;
5906 if ( pb->idx >= 0 /* Flush buffered characters to the file */
5907 && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK
5908 && (UINT)pb->idx == nw) return pb->nchr;
5919 pb->fp = fp;
5920 pb->nchr = pb->idx = 0;
5941 /*-----------------------------------------------------------------------*/
5943 /*-----------------------------------------------------------------------*/
5961 /*-----------------------------------------------------------------------*/
5963 /*-----------------------------------------------------------------------*/
5973 BYTE f, r;
5995 if (c == '-') { /* Flag: left justified */
6000 w = w * 10 + c - '0';
6004 f |= 4; c = *fmt++;
6008 if (IsLower(d)) d -= 0x20;
6030 default: /* Unknown type (pass-through) */
6035 …v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_a…
6037 v = 0 - v;
6046 if (f & 8) str[i++] = '-';
6049 do putc_bfd(&pb, str[--i]); while (i);
6072 return -1;