-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathff.cpp
119 lines (119 loc) · 34.3 KB
/
ff.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "ff.h"
#include "diskio.h"
#define ENTER_FF(fs)
#define LEAVE_FF(fs, res) return res
#define ABORT(fs, res) { fp->err = (B)(res); LEAVE_FF(fs, res); }
#define SS(fs) ((UI)_MAX_SS)
#define GET_FATTIME() ((DW)(_NORTC_YEAR - 1980) << 25 | (DW)_NORTC_MON << 21 | (DW)_NORTC_MDAY << 16)
#define _DF1S 0
#define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
#define IsLower(c) (((c)>='a')&&((c)<='z'))
#define IsDigit(c) (((c)>='0')&&((c)<='9'))
#define IsDBCS1(c) 0
#define IsDBCS2(c) 0
#define NSFLAG 11
#define NS_LOSS 0x01
#define NS_LFN 0x02
#define NS_LAST 0x04
#define NS_BODY 0x08
#define NS_EXT 0x10
#define NS_DOT 0x20
#define MIN_FAT16 4086U
#define MIN_FAT32 65526U
#define BPB_BytsPerSec 11
#define BPB_SecPerClus 13
#define BPB_RsvdSecCnt 14
#define BPB_NumFATs 16
#define BPB_RootEntCnt 17
#define BPB_TotSec16 19
#define BPB_FATSz16 22
#define BPB_TotSec32 32
#define BS_FilSysType 54
#define BPB_FATSz32 36
#define BPB_RootClus 44
#define BPB_FSInfo 48
#define BS_FilSysType32 82
#define FSI_LeadSig 0
#define FSI_StrucSig 484
#define FSI_Free_Count 488
#define FSI_Nxt_Free 492
#define MBR_Table 446
#define SZ_PTE 16
#define BS_55AA 510
#define DIR_Name 0
#define DIR_Attr 11
#define DIR_NTres 12
#define DIR_CrtTime 14
#define DIR_LstAccDate 18
#define DIR_FstClusHI 20
#define DIR_WrtTime 22
#define DIR_WrtDate 24
#define DIR_FstClusLO 26
#define DIR_FileSize 28
#define LDIR_Ord 0
#define LDIR_Attr 11
#define LDIR_Type 12
#define LDIR_Chksum 13
#define LDIR_FstClusLO 26
#define SZ_DIRE 32
#define LLEF 0x40
#define DDEM 0xE5
#define RDDEM 0x05
static FATFS *FatFs[_VOLUMES];
static W Fsid;
static WC LfnBuf[_MAX_LFN + 1];
#define DEFINE_NAMEBUF B sfn[12]
#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
#define FREE_BUF()
static const B ExCvt[] = _EXCVT;
static void mem_cpy (void* dst, const void* src, UI cnt) {B *d = (B*)dst; const B *s = (const B*)src; while (cnt--) *d++ = *s++; }
static void mem_set (void* dst, int val, UI cnt) {B *d = (B*)dst; while (cnt--) *d++ = (B)val; }
static int mem_cmp (const void* dst, const void* src, UI cnt) {const B *d = (const B *)dst, *s = (const B *)src; int r = 0; while (cnt-- && (r = *d++ - *s++) == 0) ; return r; }
static int chk_chr (const char* str, int chr) {while (*str && *str != chr) str++; return *str; }
static FRESULT sync_window (FATFS* fs) {DW wsect; UI nf;FRESULT res = FR_OK; if (fs->wflag) {wsect = fs->winsect; if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) {res = FR_DISK_ERR; } else {fs->wflag = 0; if (wsect - fs->fatbase < fs->fsize) { for (nf = fs->n_fats; nf >= 2; nf--) {wsect += fs->fsize; disk_write(fs->drv, fs->win, wsect, 1); } } } } return res; }
static FRESULT move_window (FATFS* fs, DW sector) {FRESULT res = FR_OK; if (sector != fs->winsect) {res = sync_window(fs); if (res == FR_OK) { if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) {sector = 0xFFFFFFFF; res = FR_DISK_ERR; } fs->winsect = sector; } } return res; }
static FRESULT sync_fs (FATFS* fs) {FRESULT res; res = sync_window(fs); if (res == FR_OK) {if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {mem_set(fs->win, 0, SS(fs)); ST_WORD(fs->win + BS_55AA, 0xAA55); ST_DWORD(fs->win + FSI_LeadSig, 0x41615252); ST_DWORD(fs->win + FSI_StrucSig, 0x61417272); ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust); ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust); fs->winsect = fs->volbase + 1; disk_write(fs->drv, fs->win, fs->winsect, 1); fs->fsi_flag = 0; } if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; } return res; }
DW clust2sect (FATFS* fs, DW clst) {clst -= 2; if (clst >= fs->n_fatent - 2) return 0; return clst * fs->csize + fs->database; }
DW get_fat (FATFS* fs, DW clst) {UI wc, bc; B *p; DW val; if (clst < 2 || clst >= fs->n_fatent) {val = 1; } else {val = 0xFFFFFFFF; switch (fs->fs_type) {case FS_FAT12 : bc = (UI)clst; bc += bc / 2; if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; wc = fs->win[bc++ % SS(fs)]; if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; wc |= fs->win[bc % SS(fs)] << 8; val = clst & 1 ? wc >> 4 : (wc & 0xFFF); break; case FS_FAT16 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; p = &fs->win[clst * 2 % SS(fs)]; val = LD_WORD(p); break; case FS_FAT32 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; p = &fs->win[clst * 4 % SS(fs)]; val = LD_DWORD(p) & 0x0FFFFFFF; break; default: val = 1; } } return val; }
FRESULT put_fat (FATFS* fs, DW clst, DW val) {UI bc; B *p;FRESULT res; if (clst < 2 || clst >= fs->n_fatent) {res = FR_INT_ERR; } else {switch (fs->fs_type) {case FS_FAT12 : bc = (UI)clst; bc += bc / 2; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc++ % SS(fs)]; *p = (clst & 1) ? ((*p & 0x0F) | ((B)val << 4)) : (B)val; fs->wflag = 1; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc % SS(fs)]; *p = (clst & 1) ? (B)(val >> 4) : ((*p & 0xF0) | ((B)(val >> 8) & 0x0F)); fs->wflag = 1; break; case FS_FAT16 : res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); if (res != FR_OK) break; p = &fs->win[clst * 2 % SS(fs)]; ST_WORD(p, (W)val); fs->wflag = 1; break; case FS_FAT32 : res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); if (res != FR_OK) break; p = &fs->win[clst * 4 % SS(fs)]; val |= LD_DWORD(p) & 0xF0000000; ST_DWORD(p, val); fs->wflag = 1; break; default : res = FR_INT_ERR; } } return res; }
static FRESULT remove_chain (FATFS* fs, DW clst) {FRESULT res; DW nxt; if (clst < 2 || clst >= fs->n_fatent) {res = FR_INT_ERR; } else {res = FR_OK; while (clst < fs->n_fatent) { nxt = get_fat(fs, clst); if (nxt == 0) break; if (nxt == 1) { res = FR_INT_ERR; break; } if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } res = put_fat(fs, clst, 0); if (res != FR_OK) break; if (fs->free_clust != 0xFFFFFFFF) {fs->free_clust++; fs->fsi_flag |= 1; } clst = nxt; } } return res; }
static DW create_chain (FATFS* fs, DW clst) {DW cs, ncl, scl;FRESULT res; if (clst == 0) { scl = fs->last_clust; if (!scl || scl >= fs->n_fatent) scl = 1; } else { cs = get_fat(fs, clst); if (cs < 2) return 1; if (cs == 0xFFFFFFFF) return cs; if (cs < fs->n_fatent) return cs; scl = clst; } ncl = scl; for (;;) {ncl++; if (ncl >= fs->n_fatent) { ncl = 2; if (ncl > scl) return 0; } cs = get_fat(fs, ncl); if (cs == 0) break; if (cs == 0xFFFFFFFF || cs == 1) return cs; if (ncl == scl) return 0; } res = put_fat(fs, ncl, 0x0FFFFFFF); if (res == FR_OK && clst != 0) {res = put_fat(fs, clst, ncl); } if (res == FR_OK) {fs->last_clust = ncl; if (fs->free_clust != 0xFFFFFFFF) {fs->free_clust--; fs->fsi_flag |= 1; } } else {ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; } return ncl; }
static FRESULT dir_sdi (FATFS_DIR* dp, UI idx) {DW clst, sect; UI ic; dp->index = (W)idx; clst = dp->sclust; if (clst == 1 || clst >= dp->fs->n_fatent) return FR_INT_ERR; if (!clst && dp->fs->fs_type == FS_FAT32) clst = dp->fs->dirbase; if (clst == 0) {if (idx >= dp->fs->n_rootdir) return FR_INT_ERR; sect = dp->fs->dirbase; } else { ic = SS(dp->fs) / SZ_DIRE * dp->fs->csize; while (idx >= ic) {clst = get_fat(dp->fs, clst); if (clst == 0xFFFFFFFF) return FR_DISK_ERR; if (clst < 2 || clst >= dp->fs->n_fatent) return FR_INT_ERR; idx -= ic; } sect = clust2sect(dp->fs, clst); } dp->clust = clst; if (!sect) return FR_INT_ERR; dp->sect = sect + idx / (SS(dp->fs) / SZ_DIRE); dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; return FR_OK; }
static FRESULT dir_next (FATFS_DIR* dp, int stretch) {DW clst; UI i; UI c; i = dp->index + 1; if (!(i & 0xFFFF) || !dp->sect) return FR_NO_FILE; if (!(i % (SS(dp->fs) / SZ_DIRE))) {dp->sect++; if (!dp->clust) { if (i >= dp->fs->n_rootdir) return FR_NO_FILE; } else { if (((i / (SS(dp->fs) / SZ_DIRE)) & (dp->fs->csize - 1)) == 0) {clst = get_fat(dp->fs, dp->clust); if (clst <= 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; if (clst >= dp->fs->n_fatent) { if (!stretch) return FR_NO_FILE; clst = create_chain(dp->fs, dp->clust); if (clst == 0) return FR_DENIED; if (clst == 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; if (sync_window(dp->fs)) return FR_DISK_ERR; mem_set(dp->fs->win, 0, SS(dp->fs)); dp->fs->winsect = clust2sect(dp->fs, clst); for (c = 0; c < dp->fs->csize; c++) { dp->fs->wflag = 1; if (sync_window(dp->fs)) return FR_DISK_ERR; dp->fs->winsect++; } dp->fs->winsect -= c; } dp->clust = clst; dp->sect = clust2sect(dp->fs, clst); } } } dp->index = (W)i; dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; return FR_OK; }
static FRESULT dir_alloc (FATFS_DIR* dp, UI nent) {FRESULT res; UI n; res = dir_sdi(dp, 0); if (res == FR_OK) {n = 0; do {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; if (dp->dir[0] == DDEM || dp->dir[0] == 0) {if (++n == nent) break; } else {n = 0; } res = dir_next(dp, 1); } while (res == FR_OK); } if (res == FR_NO_FILE) res = FR_DENIED; return res; }
static DW ld_clust (FATFS* fs, const B* dir) {DW cl; cl = LD_WORD(dir + DIR_FstClusLO); if (fs->fs_type == FS_FAT32) cl |= (DW)LD_WORD(dir + DIR_FstClusHI) << 16; return cl; }
static void st_clust (B* dir, DW cl) {ST_WORD(dir + DIR_FstClusLO, cl); ST_WORD(dir + DIR_FstClusHI, cl >> 16); }
static const B LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};
static int cmp_lfn (WC* lfnbuf, B* dir) {UI i, s; WC wc, uc; if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; for (wc = 1, s = 0; s < 13; s++) { uc = LD_WORD(dir + LfnOfs[s]); if (wc) {if (i >= _MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) return 0; wc = uc; } else {if (uc != 0xFFFF) return 0; } } if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; return 1; }
static int pick_lfn (WC* lfnbuf, B* dir) {UI i, s; WC wc, uc; if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; for (wc = 1, s = 0; s < 13; s++) { uc = LD_WORD(dir + LfnOfs[s]); if (wc) {if (i >= _MAX_LFN) return 0; lfnbuf[i++] = wc = uc; } else {if (uc != 0xFFFF) return 0; } } if (dir[LDIR_Ord] & LLEF) { if (i >= _MAX_LFN) return 0; lfnbuf[i] = 0; } return 1; }
static void fit_lfn (const WC* lfnbuf, B* dir, B ord, B sum) {UI i, s; WC wc; dir[LDIR_Chksum] = sum; dir[LDIR_Attr] = AM_LFN; dir[LDIR_Type] = 0; ST_WORD(dir + LDIR_FstClusLO, 0); i = (ord - 1) * 13; s = wc = 0; do {if (wc != 0xFFFF) wc = lfnbuf[i++]; ST_WORD(dir+LfnOfs[s], wc); if (!wc) wc = 0xFFFF; } while (++s < 13); if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLEF; dir[LDIR_Ord] = ord; }
static void gen_numname (B* dst, const B* src, const WC* lfn, UI seq) {B ns[8], c; UI i, j; WC wc;DW sr; mem_cpy(dst, src, 11); if (seq > 5) {sr = seq; while (*lfn) {wc = *lfn++; for (i = 0; i < 16; i++) {sr = (sr << 1) + (wc & 1); wc >>= 1; if (sr & 0x10000) sr ^= 0x11021; } } seq = (UI)sr; } i = 7; do {c = (seq % 16) + '0'; if (c > '9') c += 7; ns[i--] = c; seq /= 16; } while (seq); ns[i] = '~'; for (j = 0; j < i && dst[j] != ' '; j++) {if (IsDBCS1(dst[j])) {if (j == i - 1) break; j++; } } do {dst[j++] = (i < 8) ? ns[i++] : ' '; } while (j < 8); }
static B sum_sfn (const B* dir) {B sum = 0; UI n = 11; do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); return sum; }
static FRESULT dir_find (FATFS_DIR* dp) {FRESULT res; B c, *dir; B a, ord, sum; res = dir_sdi(dp, 0); if (res != FR_OK) return res; ord = sum = 0xFF; dp->lfn_idx = 0xFFFF; do {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; dir = dp->dir; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } a = dir[DIR_Attr] & AM_MASK; if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) {ord = 0xFF; dp->lfn_idx = 0xFFFF; } else {if (a == AM_LFN) { if (dp->lfn) {if (c & LLEF) { sum = dir[LDIR_Chksum]; c &= ~LLEF; ord = c; dp->lfn_idx = dp->index; } ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; } } else { if (!ord && sum == sum_sfn(dir)) break; if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break; ord = 0xFF; dp->lfn_idx = 0xFFFF; } } res = dir_next(dp, 0); } while (res == FR_OK); return res; }
static FRESULT dir_read (FATFS_DIR* dp, int vol) {FRESULT res; B a, c, *dir; B ord = 0xFF, sum = 0xFF; res = FR_NO_FILE; while (dp->sect) {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; dir = dp->dir; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } a = dir[DIR_Attr] & AM_MASK; if (c == DDEM || (!_FS_RPATH && c == '.') || (int)((a & ~AM_ARC) == AM_VOL) != vol) {ord = 0xFF; } else {if (a == AM_LFN) { if (c & LLEF) { sum = dir[LDIR_Chksum]; c &= ~LLEF; ord = c; dp->lfn_idx = dp->index; } ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; } else { if (ord || sum != sum_sfn(dir)) dp->lfn_idx = 0xFFFF; break; } } res = dir_next(dp, 0); if (res != FR_OK) break; } if (res != FR_OK) dp->sect = 0; return res; }
static FRESULT dir_register (FATFS_DIR* dp) {FRESULT res; UI n, nent; B sn[12], *fn, sum; WC *lfn; fn = dp->fn; lfn = dp->lfn; mem_cpy(sn, fn, 12); if (_FS_RPATH && (sn[NSFLAG] & NS_DOT)) return FR_INVALID_NAME; if (sn[NSFLAG] & NS_LOSS) { fn[NSFLAG] = 0; dp->lfn = 0; for (n = 1; n < 100; n++) {gen_numname(fn, sn, lfn, n); res = dir_find(dp); if (res != FR_OK) break; } if (n == 100) return FR_DENIED; if (res != FR_NO_FILE) return res; fn[NSFLAG] = sn[NSFLAG]; dp->lfn = lfn; } if (sn[NSFLAG] & NS_LFN) { for (n = 0; lfn[n]; n++) ; nent = (n + 25) / 13; } else { nent = 1; } res = dir_alloc(dp, nent); if (res == FR_OK && --nent) {res = dir_sdi(dp, dp->index - nent); if (res == FR_OK) {sum = sum_sfn(dp->fn); do { res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; fit_lfn(dp->lfn, dp->dir, (B)nent, sum); dp->fs->wflag = 1; res = dir_next(dp, 0); } while (res == FR_OK && --nent); } } if (res == FR_OK) { res = move_window(dp->fs, dp->sect); if (res == FR_OK) {mem_set(dp->dir, 0, SZ_DIRE); mem_cpy(dp->dir, dp->fn, 11); dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); dp->fs->wflag = 1; } } return res; }
static FRESULT dir_remove (FATFS_DIR* dp) {FRESULT res; UI i; i = dp->index; res = dir_sdi(dp, (dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx); if (res == FR_OK) {do {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; mem_set(dp->dir, 0, SZ_DIRE); *dp->dir = DDEM; dp->fs->wflag = 1; if (dp->index >= i) break; res = dir_next(dp, 0); } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR; } return res; }
static void get_fileinfo (FATFS_DIR* dp, FILINFO* fno) {UI i; TCHAR *p, c; B *dir; WC w, *lfn; p = fno->fname; if (dp->sect) { dir = dp->dir; i = 0; while (i < 11) { c = (TCHAR)dir[i++]; if (c == ' ') continue; if (c == RDDEM) c = (TCHAR)DDEM; if (i == 9) *p++ = '.'; if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY))) c += 0x20; *p++ = c; } fno->fattrib = dir[DIR_Attr]; fno->fsize = LD_DWORD(dir + DIR_FileSize); fno->fdate = LD_WORD(dir + DIR_WrtDate); fno->ftime = LD_WORD(dir + DIR_WrtTime); } *p = 0; if (fno->lfname) {i = 0; p = fno->lfname; if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) {lfn = dp->lfn; while ((w = *lfn++) != 0) { if (i >= fno->lfsize - 1) { i = 0; break; } p[i++] = (TCHAR)w; } } p[i] = 0; } }
static FRESULT create_name (FATFS_DIR* dp, const TCHAR** path) {B b, cf; WC w, *lfn; UI i, ni, si, di; const TCHAR *p; for (p = *path; *p == '/' || *p == '\\'; p++) ; lfn = dp->lfn; si = di = 0; for (;;) {w = p[si++]; if (w < ' ' || w == '/' || w == '\\') break; if (di >= _MAX_LFN) return FR_INVALID_NAME; w &= 0xFF; if (IsDBCS1(w)) { b = (B)p[si++]; w = (w << 8) + b; if (!IsDBCS2(b)) return FR_INVALID_NAME; } w = ff_convert(w, 1); if (!w) return FR_INVALID_NAME; if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) return FR_INVALID_NAME; lfn[di++] = w; } *path = &p[si]; cf = (w < ' ') ? NS_LAST : 0; while (di) { w = lfn[di - 1]; if (w != ' ' && w != '.') break; di--; } if (!di) return FR_INVALID_NAME; lfn[di] = 0; mem_set(dp->fn, ' ', 11); for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; if (si) cf |= NS_LOSS | NS_LFN; while (di && lfn[di - 1] != '.') di--; b = i = 0; ni = 8; for (;;) {w = lfn[si++]; if (!w) break; if (w == ' ' || (w == '.' && si != di)) {cf |= NS_LOSS | NS_LFN; continue; } if (i >= ni || si == di) { if (ni == 11) { cf |= NS_LOSS | NS_LFN; break; } if (si != di) cf |= NS_LOSS | NS_LFN; if (si > di) break; si = di; i = 8; ni = 11; b <<= 2; continue; } if (w >= 0x80) { w = ff_convert(w, 0); if (w) w = ExCvt[w - 0x80]; cf |= NS_LFN; } if (_DF1S && w >= 0x100) { if (i >= ni - 1) {cf |= NS_LOSS | NS_LFN; i = ni; continue; } dp->fn[i++] = (B)(w >> 8); } else { if (!w || chk_chr("+,;=[]", w)) {w = '_'; cf |= NS_LOSS | NS_LFN; } else {if (IsUpper(w)) { b |= 2; } else {if (IsLower(w)) {b |= 1; w -= 0x20; } } } } dp->fn[i++] = (B)w; } if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; if (ni == 8) b <<= 2; if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; if (!(cf & NS_LFN)) { if ((b & 0x03) == 0x01) cf |= NS_EXT; if ((b & 0x0C) == 0x04) cf |= NS_BODY; } dp->fn[NSFLAG] = cf; return FR_OK; }
static FRESULT follow_path (FATFS_DIR* dp, const TCHAR* path) {FRESULT res; B *dir, ns; if (*path == '/' || *path == '\\') path++; dp->sclust = 0; if ((UI)*path < ' ') { res = dir_sdi(dp, 0); dp->dir = 0; } else { for (;;) {res = create_name(dp, &path); if (res != FR_OK) break; res = dir_find(dp); ns = dp->fn[NSFLAG]; if (res != FR_OK) { if (res == FR_NO_FILE) {if (_FS_RPATH && (ns & NS_DOT)) {dp->sclust = 0; dp->dir = 0; if (!(ns & NS_LAST)) continue; res = FR_OK; } else { if (!(ns & NS_LAST)) res = FR_NO_PATH; } } break; } if (ns & NS_LAST) break; dir = dp->dir; if (!(dir[DIR_Attr] & AM_DIR)) {res = FR_NO_PATH; break; } dp->sclust = ld_clust(dp->fs, dir); } } return res; }
static int get_ldnumber (const TCHAR** path) {const TCHAR *tp, *tt; UI i; int vol = -1; if (*path) {for (tt = *path; (UI)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; if (*tt == ':') {tp = *path; i = *tp++ - '0'; if (i < 10 && tp == tt) {if (i < _VOLUMES) {vol = (int)i; *path = ++tt; } } return vol; } vol = 0; } return vol; }
static B check_fs (FATFS* fs, DW sect) {fs->wflag = 0; fs->winsect = 0xFFFFFFFF; if (move_window(fs, sect) != FR_OK) return 3; if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) return 2; if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) return 0; if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) return 0; return 1; }
static FRESULT find_volume (FATFS** rfs, const TCHAR** path, B wmode) {B fmt, *pt; int vol; DSTATUS stat;DW bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; W nrsv; FATFS *fs; UI i; *rfs = 0; vol = get_ldnumber(path); if (vol < 0) return FR_INVALID_DRIVE; fs = FatFs[vol]; if (!fs) return FR_NOT_ENABLED; ENTER_FF(fs); *rfs = fs; if (fs->fs_type) { stat = disk_status(fs->drv); if (!(stat & STA_NOINIT)) { if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) return FR_WRITE_PROTECTED; return FR_OK; } } fs->fs_type = 0; fs->drv = LD2PD(vol); stat = disk_initialize(fs->drv); if (stat & STA_NOINIT) return FR_NOT_READY; if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) return FR_WRITE_PROTECTED; bsect = 0; fmt = check_fs(fs, bsect); if (fmt == 1 || (!fmt && (LD2PT(vol)))) {for (i = 0; i < 4; i++) { pt = fs->win + MBR_Table + i * SZ_PTE; br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0; } i = LD2PT(vol); if (i) i--; do { bsect = br[i]; fmt = bsect ? check_fs(fs, bsect) : 2; } while (!LD2PT(vol) && fmt && ++i < 4); } if (fmt == 3) return FR_DISK_ERR; if (fmt) return FR_NO_FILESYSTEM; if (LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; fasize = LD_WORD(fs->win + BPB_FATSz16); if (!fasize) fasize = LD_DWORD(fs->win + BPB_FATSz32); fs->fsize = fasize; fs->n_fats = fs->win[BPB_NumFATs]; if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; fasize *= fs->n_fats; fs->csize = fs->win[BPB_SecPerClus]; if (!fs->csize || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); if (fs->n_rootdir % (SS(fs) / SZ_DIRE)) return FR_NO_FILESYSTEM; tsect = LD_WORD(fs->win + BPB_TotSec16); if (!tsect) tsect = LD_DWORD(fs->win + BPB_TotSec32); nrsv = LD_WORD(fs->win + BPB_RsvdSecCnt); if (!nrsv) return FR_NO_FILESYSTEM; sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIRE); if (tsect < sysect) return FR_NO_FILESYSTEM; nclst = (tsect - sysect) / fs->csize; if (!nclst) return FR_NO_FILESYSTEM; fmt = FS_FAT12; if (nclst >= MIN_FAT16) fmt = FS_FAT16; if (nclst >= MIN_FAT32) fmt = FS_FAT32; fs->n_fatent = nclst + 2; fs->volbase = bsect; fs->fatbase = bsect + nrsv; fs->database = bsect + sysect; if (fmt == FS_FAT32) {if (fs->n_rootdir) return FR_NO_FILESYSTEM; fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); szbfat = fs->n_fatent * 4; } else {if (!fs->n_rootdir) return FR_NO_FILESYSTEM; fs->dirbase = fs->fatbase + fasize; szbfat = (fmt == FS_FAT16) ? fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); } if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; fs->last_clust = fs->free_clust = 0xFFFFFFFF; fs->fsi_flag = 0x80; if (fmt == FS_FAT32 && LD_WORD(fs->win + BPB_FSInfo) == 1&& move_window(fs, bsect + 1) == FR_OK) {fs->fsi_flag = 0; if (LD_WORD(fs->win + BS_55AA) == 0xAA55 && LD_DWORD(fs->win + FSI_LeadSig) == 0x41615252&& LD_DWORD(fs->win + FSI_StrucSig) == 0x61417272) {fs->free_clust = LD_DWORD(fs->win + FSI_Free_Count); fs->last_clust = LD_DWORD(fs->win + FSI_Nxt_Free); } } fs->fs_type = fmt; fs->id = ++Fsid; return FR_OK; }
static FRESULT validate (void* obj) {FIL *fil = (FIL*)obj; if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id || (disk_status(fil->fs->drv) & STA_NOINIT)) return FR_INVALID_OBJECT; ENTER_FF(fil->fs); return FR_OK; }
FRESULT f_mount (FATFS* fs, const TCHAR* path, B opt) {FATFS *cfs; int vol;FRESULT res; const TCHAR *rp = path; vol = get_ldnumber(&rp); if (vol < 0) return FR_INVALID_DRIVE; cfs = FatFs[vol]; if (cfs) {cfs->fs_type = 0; } if (fs) {fs->fs_type = 0; } FatFs[vol] = fs; if (!fs || opt != 1) return FR_OK; res = find_volume(&fs, &path, 0); LEAVE_FF(fs, res); }
FRESULT f_open (FIL* fp, const TCHAR* path, B mode) {FRESULT res; FATFS_DIR dj; B *dir; DEFINE_NAMEBUF;DW dw, cl; if (!fp) return FR_INVALID_OBJECT; fp->fs = 0; mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; res = find_volume(&dj.fs, &path, (B)(mode & ~FA_READ)); if (res == FR_OK) {INIT_BUF(dj); res = follow_path(&dj, path); dir = dj.dir; if (res == FR_OK) {if (!dir) res = FR_INVALID_NAME; } if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {if (res != FR_OK) { if (res == FR_NO_FILE) res = dir_register(&dj); mode |= FA_CREATE_ALWAYS; dir = dj.dir; } else { if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {res = FR_DENIED; } else {if (mode & FA_CREATE_NEW) res = FR_EXIST; } } if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {dw = GET_FATTIME(); ST_DWORD(dir + DIR_CrtTime, dw); ST_DWORD(dir + DIR_WrtTime, dw); dir[DIR_Attr] = 0; ST_DWORD(dir + DIR_FileSize, 0); cl = ld_clust(dj.fs, dir); st_clust(dir, 0); dj.fs->wflag = 1; if (cl) { dw = dj.fs->winsect; res = remove_chain(dj.fs, cl); if (res == FR_OK) {dj.fs->last_clust = cl - 1; res = move_window(dj.fs, dw); } } } } else {if (res == FR_OK) { if (dir[DIR_Attr] & AM_DIR) {res = FR_NO_FILE; } else {if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) res = FR_DENIED; } } } if (res == FR_OK) {if (mode & FA_CREATE_ALWAYS) mode |= FA__WRITTEN; fp->dir_sect = dj.fs->winsect; fp->dir_ptr = dir; } FREE_BUF(); if (res == FR_OK) {fp->flag = mode; fp->err = 0; fp->sclust = ld_clust(dj.fs, dir); fp->fsize = LD_DWORD(dir + DIR_FileSize); fp->fptr = 0; fp->dsect = 0; fp->fs = dj.fs; fp->id = fp->fs->id; } } LEAVE_FF(dj.fs, res); }
FRESULT f_read (FIL* fp, void* buff, UI btr, UI* br) {FRESULT res;DW clst, sect, remain; UI rcnt, cc; B csect, *rbuff = (B*)buff; *br = 0; res = validate(fp); if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->err) LEAVE_FF(fp->fs, (FRESULT)fp->err); if (!(fp->flag & FA_READ)) LEAVE_FF(fp->fs, FR_DENIED); remain = fp->fsize - fp->fptr; if (btr > remain) btr = (UI)remain; for (; btr; rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {if ((fp->fptr % SS(fp->fs)) == 0) { csect = (B)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); if (!csect) { if (fp->fptr == 0) { clst = fp->sclust; } else {clst = get_fat(fp->fs, fp->clust); } if (clst < 2) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->clust = clst; } sect = clust2sect(fp->fs, fp->clust); if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; cc = btr / SS(fp->fs); if (cc) { if (csect + cc > fp->fs->csize) cc = fp->fs->csize - csect; if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); if (fp->fs->wflag && fp->fs->winsect - sect < cc) mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); rcnt = SS(fp->fs) * cc; continue; } fp->dsect = sect; } rcnt = SS(fp->fs) - ((UI)fp->fptr % SS(fp->fs)); if (rcnt > btr) rcnt = btr; if (move_window(fp->fs, fp->dsect) != FR_OK) ABORT(fp->fs, FR_DISK_ERR); mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); } LEAVE_FF(fp->fs, FR_OK); }
FRESULT f_write (FIL* fp, const void *buff, UI btw, UI* bw) {FRESULT res;DW clst, sect; UI wcnt, cc; const B *wbuff = (const B*)buff; B csect; bool need_sync = false; *bw = 0; res = validate(fp); if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->err) LEAVE_FF(fp->fs, (FRESULT)fp->err); if (!(fp->flag & FA_WRITE)) LEAVE_FF(fp->fs, FR_DENIED); if (fp->fptr + btw < fp->fptr) btw = 0; for (; btw; wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {if ((fp->fptr % SS(fp->fs)) == 0) {csect = (B)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); if (!csect) { if (fp->fptr == 0) { clst = fp->sclust; if (clst == 0) clst = create_chain(fp->fs, 0); } else {clst = create_chain(fp->fs, fp->clust); } if (clst == 0) break; if (clst == 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->clust = clst; if (fp->sclust == 0) fp->sclust = clst; } if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); sect = clust2sect(fp->fs, fp->clust); if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; cc = btw / SS(fp->fs); if (cc) { if (csect + cc > fp->fs->csize) cc = fp->fs->csize - csect; if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); if (fp->fs->winsect - sect < cc) {mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); fp->fs->wflag = 0; } wcnt = SS(fp->fs) * cc; need_sync = true; continue; } if (fp->fptr >= fp->fsize) {if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); fp->fs->winsect = sect; } fp->dsect = sect; } wcnt = SS(fp->fs) - ((UI)fp->fptr % SS(fp->fs)); if (wcnt > btw) wcnt = btw; if (move_window(fp->fs, fp->dsect) != FR_OK) ABORT(fp->fs, FR_DISK_ERR); mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); fp->fs->wflag = 1; } if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; fp->flag |= FA__WRITTEN; if (need_sync) {f_sync (fp); } LEAVE_FF(fp->fs, FR_OK); }
FRESULT f_sync (FIL* fp) {FRESULT res;DW tm; B *dir; res = validate(fp); if (res == FR_OK) {if (fp->flag & FA__WRITTEN) { res = move_window(fp->fs, fp->dir_sect); if (res == FR_OK) {dir = fp->dir_ptr; dir[DIR_Attr] |= AM_ARC; ST_DWORD(dir + DIR_FileSize, fp->fsize); st_clust(dir, fp->sclust); tm = GET_FATTIME(); ST_DWORD(dir + DIR_WrtTime, tm); ST_WORD(dir + DIR_LstAccDate, 0); fp->flag &= ~FA__WRITTEN; fp->fs->wflag = 1; res = sync_fs(fp->fs); } } } LEAVE_FF(fp->fs, res); }
FRESULT f_close (FIL *fp) {FRESULT res; res = f_sync(fp); if (res == FR_OK) {res = validate(fp); if (res == FR_OK) {fp->fs = 0; } } return res; }
FRESULT f_lseek (FIL* fp, DW ofs) {FRESULT res;DW clst, bcs, nsect, ifptr; res = validate(fp); if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->err) LEAVE_FF(fp->fs, (FRESULT)fp->err); {if (ofs > fp->fsize && !(fp->flag & FA_WRITE) ) ofs = fp->fsize; ifptr = fp->fptr; fp->fptr = nsect = 0; if (ofs) {bcs = (DW)fp->fs->csize * SS(fp->fs); if (ifptr > 0 && (ofs - 1) / bcs >= (ifptr - 1) / bcs) {fp->fptr = (ifptr - 1) & ~(bcs - 1); ofs -= fp->fptr; clst = fp->clust; } else { clst = fp->sclust; if (clst == 0) { clst = create_chain(fp->fs, 0); if (clst == 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->sclust = clst; } fp->clust = clst; } if (clst != 0) {while (ofs > bcs) {if (fp->flag & FA_WRITE) { clst = create_chain(fp->fs, clst); if (clst == 0) { ofs = bcs; break; } } else clst = get_fat(fp->fs, clst); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); fp->clust = clst; fp->fptr += bcs; ofs -= bcs; } fp->fptr += ofs; if (ofs % SS(fp->fs)) {nsect = clust2sect(fp->fs, clst); if (!nsect) ABORT(fp->fs, FR_INT_ERR); nsect += ofs / SS(fp->fs); } } } if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) {fp->dsect = nsect; } if (fp->fptr > fp->fsize) { fp->fsize = fp->fptr; fp->flag |= FA__WRITTEN; } } LEAVE_FF(fp->fs, res); }
FRESULT f_opendir (FATFS_DIR* dp, const TCHAR* path) {FRESULT res; FATFS* fs; DEFINE_NAMEBUF; if (!dp) return FR_INVALID_OBJECT; res = find_volume(&fs, &path, 0); if (res == FR_OK) {dp->fs = fs; INIT_BUF(*dp); res = follow_path(dp, path); FREE_BUF(); if (res == FR_OK) { if (dp->dir) { if (dp->dir[DIR_Attr] & AM_DIR) dp->sclust = ld_clust(fs, dp->dir); else res = FR_NO_PATH; } if (res == FR_OK) {dp->id = fs->id; res = dir_sdi(dp, 0); } } if (res == FR_NO_FILE) res = FR_NO_PATH; } if (res != FR_OK) dp->fs = 0; LEAVE_FF(fs, res); }
FRESULT f_closedir (FATFS_DIR *dp) {FRESULT res; res = validate(dp); if (res == FR_OK) {dp->fs = 0; } return res; }
FRESULT f_readdir (FATFS_DIR* dp, FILINFO* fno) {FRESULT res; DEFINE_NAMEBUF; res = validate(dp); if (res == FR_OK) {if (!fno) {res = dir_sdi(dp, 0); } else {INIT_BUF(*dp); res = dir_read(dp, 0); if (res == FR_NO_FILE) { dp->sect = 0; res = FR_OK; } if (res == FR_OK) { get_fileinfo(dp, fno); res = dir_next(dp, 0); if (res == FR_NO_FILE) {dp->sect = 0; res = FR_OK; } } FREE_BUF(); } } LEAVE_FF(dp->fs, res); }
FRESULT f_unlink (const TCHAR* path) {FRESULT res; FATFS_DIR dj, sdj; B *dir;DW dclst = 0; DEFINE_NAMEBUF; res = find_volume(&dj.fs, &path, 1); if (res == FR_OK) {INIT_BUF(dj); res = follow_path(&dj, path); if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) res = FR_INVALID_NAME; if (res == FR_OK) { dir = dj.dir; if (!dir) {res = FR_INVALID_NAME; } else {if (dir[DIR_Attr] & AM_RDO) res = FR_DENIED; } if (res == FR_OK) {dclst = ld_clust(dj.fs, dir); if (dclst && (dir[DIR_Attr] & AM_DIR)) {{ mem_cpy(&sdj, &dj, sizeof (FATFS_DIR)); sdj.sclust = dclst; res = dir_sdi(&sdj, 2); if (res == FR_OK) {res = dir_read(&sdj, 0); if (res == FR_OK) res = FR_DENIED; if (res == FR_NO_FILE) res = FR_OK; } } } } if (res == FR_OK) {res = dir_remove(&dj); if (res == FR_OK && dclst) res = remove_chain(dj.fs, dclst); if (res == FR_OK) res = sync_fs(dj.fs); } } FREE_BUF(); } LEAVE_FF(dj.fs, res); }
FRESULT f_mkdir (const TCHAR* path) {FRESULT res; FATFS_DIR dj; B *dir, n;DW dsc, dcl, pcl, tm = GET_FATTIME(); DEFINE_NAMEBUF; res = find_volume(&dj.fs, &path, 1); if (res == FR_OK) {INIT_BUF(dj); res = follow_path(&dj, path); if (res == FR_OK) res = FR_EXIST; if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) res = FR_INVALID_NAME; if (res == FR_NO_FILE) { dcl = create_chain(dj.fs, 0); res = FR_OK; if (dcl == 0) res = FR_DENIED; if (dcl == 1) res = FR_INT_ERR; if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; if (res == FR_OK) res = sync_window(dj.fs); if (res == FR_OK) { dsc = clust2sect(dj.fs, dcl); dir = dj.fs->win; mem_set(dir, 0, SS(dj.fs)); mem_set(dir + DIR_Name, ' ', 11); dir[DIR_Name] = '.'; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir + DIR_WrtTime, tm); st_clust(dir, dcl); mem_cpy(dir + SZ_DIRE, dir, SZ_DIRE); dir[SZ_DIRE + 1] = '.'; pcl = dj.sclust; if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) pcl = 0; st_clust(dir + SZ_DIRE, pcl); for (n = dj.fs->csize; n; n--) {dj.fs->winsect = dsc++; dj.fs->wflag = 1; res = sync_window(dj.fs); if (res != FR_OK) break; mem_set(dir, 0, SS(dj.fs)); } } if (res == FR_OK) res = dir_register(&dj); if (res != FR_OK) {remove_chain(dj.fs, dcl); } else {dir = dj.dir; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir + DIR_WrtTime, tm); st_clust(dir, dcl); dj.fs->wflag = 1; res = sync_fs(dj.fs); } } FREE_BUF(); } LEAVE_FF(dj.fs, res); }
#include <stdarg.h>
typedef struct {FIL* fp; int idx, nchr; B buf[64]; } putbuff;
static void putc_bfd (putbuff* pb, TCHAR c) {UI bw; int i; if (_USE_STRFUNC == 2 && c == '\n') putc_bfd(pb, '\r'); i = pb->idx; if (i < 0) return; pb->buf[i++] = (B)c; if (i >= (int)(sizeof pb->buf) - 3) {f_write(pb->fp, pb->buf, (UI)i, &bw); i = (bw == (UI)i) ? 0 : -1; } pb->idx = i; pb->nchr++; }
int f_printf (FIL* fp, const TCHAR* fmt, ...) {va_list arp; B f, r; UI nw, i, j, w; DW v; TCHAR c, d, s[16], *p; putbuff pb; pb.fp = fp; pb.nchr = pb.idx = 0; va_start(arp, fmt); for (;;) {c = *fmt++; if (c == 0) break; if (c != '%') { putc_bfd(&pb, c); continue; } w = f = 0; c = *fmt++; if (c == '0') { f = 1; c = *fmt++; } else {if (c == '-') { f = 2; c = *fmt++; } } while (IsDigit(c)) { w = w * 10 + c - '0'; c = *fmt++; } if (c == 'l' || c == 'L') {f |= 4; c = *fmt++; } if (!c) break; d = c; if (IsLower(d)) d -= 0x20; switch (d) { case 'S' : p = va_arg(arp, TCHAR*); for (j = 0; p[j]; j++) ; if (!(f & 2)) {while (j++ < w) putc_bfd(&pb, ' '); } while (*p) putc_bfd(&pb, *p++); while (j++ < w) putc_bfd(&pb, ' '); continue; case 'C' : putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; case 'B' : r = 2; break; case 'O' : r = 8; break; case 'D' : case 'U' : r = 10; break; case 'X' : r = 16; break; default: putc_bfd(&pb, c); continue; } v = (f & 4) ? (DW)va_arg(arp, long) : ((d == 'D') ? (DW)(long)va_arg(arp, int) : (DW)va_arg(arp, unsigned int)); if (d == 'D' && (v & 0x80000000)) {v = 0 - v; f |= 8; } i = 0; do {d = (TCHAR)(v % r); v /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; } while (v && i < sizeof s / sizeof s[0]); if (f & 8) s[i++] = '-'; j = i; d = (f & 1) ? '0' : ' '; while (!(f & 2) && j++ < w) putc_bfd(&pb, d); do putc_bfd(&pb, s[--i]); while (i); while (j++ < w) putc_bfd(&pb, d); } va_end(arp); if (pb.idx >= 0&& f_write(pb.fp, pb.buf, (UI)pb.idx, &nw) == FR_OK && (UI)pb.idx == nw) return pb.nchr; return EOF; }