99 #error Wrong include file (ff.h).
104 #if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096
105 #error Wrong sector size.
108 #define SS(fs) ((fs)->ssize)
117 #error Static LFN work area must not be used in re-entrant configuration.
119 #define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; }
120 #define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
123 #define LEAVE_FF(fs, res) return res
126 #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
132 #error _FS_SHARE must be 0 on read-only cfg.
145 #define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
146 #define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
150 #define IsUpper(c) (((c)>='A')&&((c)<='Z'))
151 #define IsLower(c) (((c)>='a')&&((c)<='z'))
152 #define IsDigit(c) (((c)>='0')&&((c)<='9'))
157 #define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
159 #define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
163 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
165 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
188 #define MIN_FAT16 4086
189 #define MIN_FAT32 65526
198 #define BPB_BytsPerSec 11
199 #define BPB_SecPerClus 13
200 #define BPB_RsvdSecCnt 14
201 #define BPB_NumFATs 16
202 #define BPB_RootEntCnt 17
203 #define BPB_TotSec16 19
205 #define BPB_FATSz16 22
206 #define BPB_SecPerTrk 24
207 #define BPB_NumHeads 26
208 #define BPB_HiddSec 28
209 #define BPB_TotSec32 32
211 #define BS_BootSig 38
214 #define BS_FilSysType 54
215 #define BPB_FATSz32 36
216 #define BPB_ExtFlags 40
218 #define BPB_RootClus 44
219 #define BPB_FSInfo 48
220 #define BPB_BkBootSec 50
221 #define BS_DrvNum32 64
222 #define BS_BootSig32 66
223 #define BS_VolID32 67
224 #define BS_VolLab32 71
225 #define BS_FilSysType32 82
226 #define FSI_LeadSig 0
227 #define FSI_StrucSig 484
228 #define FSI_Free_Count 488
229 #define FSI_Nxt_Free 492
230 #define MBR_Table 446
236 #define DIR_CrtTime 14
237 #define DIR_CrtDate 16
238 #define DIR_FstClusHI 20
239 #define DIR_WrtTime 22
240 #define DIR_WrtDate 24
241 #define DIR_FstClusLO 26
242 #define DIR_FileSize 28
246 #define LDIR_Chksum 13
247 #define LDIR_FstClusLO 26
257 #error Number of drives must not be 0.
274 #define DEF_NAMEBUF BYTE sfn[12]
275 #define INIT_BUF(dobj) (dobj).fn = sfn
280 #define DEF_NAMEBUF BYTE sfn[12]
281 #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
285 #define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
286 #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
290 #define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
291 #define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
292 if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
293 (dobj).lfn = lfn; (dobj).fn = sfn; }
294 #define FREE_BUF() ff_memfree(lfn)
297 #error Wrong LFN configuration.
315 NODEBUG
void mem_cpy(
void* dst,
const void* src, UINT cnt )
317 BYTE* d = ( BYTE* )dst;
318 const BYTE* s = (
const BYTE* )src;
320 #if _WORD_ACCESS == 1
321 while ( cnt >=
sizeof(
int ) )
323 *(
int* )d = *(
int* )s;
324 d +=
sizeof( int ); s +=
sizeof( int );
325 cnt -=
sizeof( int );
333 NODEBUG
void str_cpy(
char* Dest ,
const char* Src )
345 NODEBUG
void mem_set(
void* dst,
int val, UINT cnt )
347 BYTE* d = ( BYTE* )dst;
354 NODEBUG
int mem_cmp(
const void* dst,
const void* src, UINT cnt )
356 const BYTE* d = (
const BYTE* )dst, *s = (
const BYTE* )src;
359 while ( cnt-- && ( r = *d++ - *s++ ) == 0 ) ;
364 NODEBUG
int chk_chr(
const char* str,
int chr )
366 while ( *str && *str != chr ) str++;
382 return ff_req_grant( fs->sobj );
392 if ( res != FR_NOT_ENABLED &&
393 res != FR_INVALID_DRIVE &&
394 res != FR_INVALID_OBJECT &&
397 ff_rel_grant( fs->sobj );
422 if ( Files[i].fs == dj->fs &&
423 Files[i].clu == dj->sclust &&
424 Files[i].idx == dj->index )
break;
431 if ( i == _FS_SHARE )
432 return ( be || acc == 2 ) ? FR_OK : FR_TOO_MANY_OPEN_FILES;
435 return ( acc || Files[i].ctr == 0x100 ) ? FR_LOCKED : FR_OK;
446 for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ;
447 return ( i == _FS_SHARE ) ? 0 : 1;
462 if ( Files[i].fs == dj->fs &&
463 Files[i].clu == dj->sclust &&
464 Files[i].idx == dj->index )
break;
467 if ( i == _FS_SHARE )
469 for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ;
470 if ( i == _FS_SHARE )
return 0;
471 Files[i].fs = dj->fs;
472 Files[i].clu = dj->sclust;
473 Files[i].idx = dj->index;
477 if ( acc && Files[i].ctr )
return 0;
479 Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1;
494 if ( --i < _FS_SHARE )
497 if ( n == 0x100 ) n = 0;
500 if ( !n ) Files[i].fs = 0;
520 if ( Files[i].fs == fs ) Files[i].fs = 0;
541 if ( wsect != sector )
546 if (
disk_write( fs->drv, fs->win, wsect, 1 ) != RES_OK )
549 if ( wsect < ( fs->fatbase + fs->fsize ) )
552 for ( nf = fs->n_fats; nf > 1; nf-- )
562 if (
disk_read( fs->drv, fs->win, sector, 1 ) != RES_OK )
564 fs->winsect = sector;
590 if ( fs->fs_type == FS_FAT32 && fs->fsi_flag )
594 ST_WORD( fs->win +
BS_55AA, 0xAA55 );
599 disk_write( fs->drv, fs->win, fs->fsi_sector, 1 );
603 if (
disk_ioctl( fs->drv, CTRL_SYNC, (
void* )0 ) != RES_OK )
625 if ( clst >= ( fs->n_fatent - 2 ) )
return 0;
626 return clst * fs->csize + fs->database;
646 if ( clst < 2 || clst >= fs->n_fatent )
649 switch ( fs->fs_type )
652 bc = ( UINT )clst; bc += bc / 2;
653 if (
move_window( fs, fs->fatbase + ( bc /
SS( fs ) ) ) )
break;
654 wc = fs->win[bc %
SS( fs )]; bc++;
655 if (
move_window( fs, fs->fatbase + ( bc /
SS( fs ) ) ) )
break;
656 wc |= fs->win[bc %
SS( fs )] << 8;
657 return ( clst & 1 ) ? ( wc >> 4 ) : ( wc & 0xFFF );
660 if (
move_window( fs, fs->fatbase + ( clst / (
SS( fs ) / 2 ) ) ) )
break;
661 p = &fs->win[clst * 2 %
SS( fs )];
665 if (
move_window( fs, fs->fatbase + ( clst / (
SS( fs ) / 4 ) ) ) )
break;
666 p = &fs->win[clst * 4 %
SS( fs )];
667 return LD_DWORD( p ) & 0x0FFFFFFF;
692 if ( clst < 2 || clst >= fs->n_fatent )
699 switch ( fs->fs_type )
702 bc = clst; bc += bc / 2;
704 if ( res != FR_OK )
break;
705 p = &fs->win[bc %
SS( fs )];
706 *p = ( clst & 1 ) ? ( ( *p & 0x0F ) | ( ( BYTE )val << 4 ) ) : ( BYTE )val;
710 if ( res != FR_OK )
break;
711 p = &fs->win[bc %
SS( fs )];
712 *p = ( clst & 1 ) ? ( BYTE )( val >> 4 ) : ( ( *p & 0xF0 ) | ( ( BYTE )( val >> 8 ) & 0x0F ) );
716 res =
move_window( fs, fs->fatbase + ( clst / (
SS( fs ) / 2 ) ) );
717 if ( res != FR_OK )
break;
718 p = &fs->win[clst * 2 %
SS( fs )];
719 ST_WORD( p, ( WORD )val );
723 res =
move_window( fs, fs->fatbase + ( clst / (
SS( fs ) / 4 ) ) );
724 if ( res != FR_OK )
break;
725 p = &fs->win[clst * 4 %
SS( fs )];
726 val |= LD_DWORD( p ) & 0xF0000000;
756 DWORD scl = clst, ecl = clst, resion[2];
759 if ( clst < 2 || clst >= fs->n_fatent )
767 while ( clst < fs->n_fatent )
770 if ( nxt == 0 )
break;
771 if ( nxt == 1 ) { res = FR_INT_ERR;
break; }
772 if ( nxt == 0xFFFFFFFF ) { res = FR_DISK_ERR;
break; }
774 if ( res != FR_OK )
break;
775 if ( fs->free_clust != 0xFFFFFFFF )
781 if ( ecl + 1 == nxt )
788 resion[1] =
clust2sect( fs, ecl ) + fs->csize - 1;
789 disk_ioctl( fs->drv, CTRL_ERASE_SECTOR, resion );
820 scl = fs->last_clust;
821 if ( !scl || scl >= fs->n_fatent ) scl = 1;
826 if ( cs < 2 )
return 1;
827 if ( cs < fs->n_fatent )
return cs;
835 if ( ncl >= fs->n_fatent )
838 if ( ncl > scl )
return 0;
841 if ( cs == 0 )
break;
842 if ( cs == 0xFFFFFFFF || cs == 1 )
844 if ( ncl == scl )
return 0;
847 res =
put_fat( fs, ncl, 0x0FFFFFFF );
848 if ( res == FR_OK && clst != 0 )
850 res =
put_fat( fs, clst, ncl );
854 fs->last_clust = ncl;
855 if ( fs->free_clust != 0xFFFFFFFF )
863 ncl = ( res == FR_DISK_ERR ) ? 0xFFFFFFFF : 1;
889 if ( clst == 1 || clst >= dj->fs->n_fatent )
891 if ( !clst && dj->fs->fs_type == FS_FAT32 )
892 clst = dj->fs->dirbase;
897 if ( idx >= dj->fs->n_rootdir )
899 dj->sect = dj->fs->dirbase + idx / (
SS( dj->fs ) / 32 );
903 ic =
SS( dj->fs ) / 32 * dj->fs->csize;
906 clst =
get_fat( dj->fs, clst );
907 if ( clst == 0xFFFFFFFF )
return FR_DISK_ERR;
908 if ( clst < 2 || clst >= dj->fs->n_fatent )
913 dj->sect =
clust2sect( dj->fs, clst ) + idx / (
SS( dj->fs ) / 32 );
916 dj->dir = dj->fs->win + ( idx % (
SS( dj->fs ) / 32 ) ) * 32;
939 if ( !i || !dj->sect )
942 if ( !( i % (
SS( dj->fs ) / 32 ) ) )
946 if ( dj->clust == 0 )
948 if ( i >= dj->fs->n_rootdir )
953 if ( ( ( i / (
SS( dj->fs ) / 32 ) ) & ( dj->fs->csize - 1 ) ) == 0 )
955 clst =
get_fat( dj->fs, dj->clust );
956 if ( clst <= 1 )
return FR_INT_ERR;
957 if ( clst == 0xFFFFFFFF )
return FR_DISK_ERR;
958 if ( clst >= dj->fs->n_fatent )
962 if ( !stretch )
return FR_NO_FILE;
964 if ( clst == 0 )
return FR_DENIED;
965 if ( clst == 1 )
return FR_INT_ERR;
966 if ( clst == 0xFFFFFFFF )
return FR_DISK_ERR;
968 if (
move_window( dj->fs, 0 ) )
return FR_DISK_ERR;
971 for ( c = 0; c < dj->fs->csize; c++ )
974 if (
move_window( dj->fs, 0 ) )
return FR_DISK_ERR;
977 dj->fs->winsect -= c;
989 dj->dir = dj->fs->win + ( i % (
SS( dj->fs ) / 32 ) ) * 32;
1002 const BYTE LfnOfs[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30};
1015 i = ( ( dir[
LDIR_Ord] & 0xBF ) - 1 ) * 13;
1019 uc = LD_WORD( dir + LfnOfs[s] );
1022 wc = ff_wtoupper( uc );
1023 if ( i >=
_MAX_LFN || wc != ff_wtoupper( lfnbuf[i++] ) )
1028 if ( uc != 0xFFFF )
return 0;
1033 if ( ( dir[
LDIR_Ord] & 0x40 ) && wc && lfnbuf[i] )
1051 i = ( ( dir[
LDIR_Ord] & 0x3F ) - 1 ) * 13;
1056 uc = LD_WORD( dir + LfnOfs[s] );
1060 lfnbuf[i++] = wc = uc;
1064 if ( uc != 0xFFFF )
return 0;
1082 const WCHAR* lfnbuf,
1097 i = ( ord - 1 ) * 13;
1101 if ( wc != 0xFFFF ) wc = lfnbuf[i++];
1102 ST_WORD( dir + LfnOfs[s], wc );
1103 if ( !wc ) wc = 0xFFFF;
1106 if ( wc == 0xFFFF || !lfnbuf[i] ) ord |= 0x40;
1119 NODEBUG2
void gen_numname(
1134 do seq = ( seq >> 1 ) + ( seq << 15 ) + ( WORD ) * lfn++;
while ( *lfn );
1141 c = ( seq % 16 ) +
'0';
1142 if ( c >
'9' ) c += 7;
1150 for ( j = 0; j < i && dst[j] !=
' '; j++ )
1154 if ( j == i - 1 )
break;
1160 dst[j++] = ( i < 8 ) ? ns[i++] :
' ';
1181 do sum = ( sum >> 1 ) + ( sum << 7 ) + *dir++;
while ( --n );
1205 if ( res != FR_OK )
return res;
1213 if ( res != FR_OK )
break;
1216 if ( c == 0 ) { res = FR_NO_FILE;
break; }
1219 if ( c == 0xE5 || ( ( a & AM_VOL ) && a != AM_LFN ) )
1233 dj->lfn_idx = dj->index;
1236 ord = ( c == ord && sum == dir[
LDIR_Chksum] && cmp_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF;
1241 if ( !ord && sum == sum_sfn( dir ) )
break;
1242 ord = 0xFF; dj->lfn_idx = 0xFFFF;
1252 while ( res == FR_OK );
1263 #if _FS_MINIMIZE <= 1
1272 BYTE a, ord = 0xFF, sum = 0xFF;
1279 if ( res != FR_OK )
break;
1282 if ( c == 0 ) { res = FR_NO_FILE;
break; }
1285 if ( c == 0xE5 || ( !
_FS_RPATH && c ==
'.' ) || ( ( a & AM_VOL ) && a != AM_LFN ) )
1297 dj->lfn_idx = dj->index;
1300 ord = ( c == ord && sum == dir[
LDIR_Chksum] && pick_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF;
1304 if ( ord || sum != sum_sfn( dir ) )
1305 dj->lfn_idx = 0xFFFF;
1314 if ( res != FR_OK )
break;
1317 if ( res != FR_OK ) dj->sect = 0;
1338 BYTE sn[12], *fn, sum;
1342 fn = dj->fn; lfn = dj->lfn;
1346 return FR_INVALID_NAME;
1350 fn[
NS] = 0; dj->lfn = 0;
1351 for ( n = 1; n < 100; n++ )
1353 gen_numname( fn, sn, lfn, n );
1355 if ( res != FR_OK )
break;
1357 if ( n == 100 )
return FR_DENIED;
1358 if ( res != FR_NO_FILE )
return res;
1359 fn[
NS] = sn[
NS]; dj->lfn = lfn;
1364 for ( ne = 0; lfn[ne]; ne++ ) ;
1365 ne = ( ne + 25 ) / 13;
1374 if ( res != FR_OK )
return res;
1379 if ( res != FR_OK )
break;
1381 if ( c == 0xE5 || c == 0 )
1383 if ( n == 0 ) is = dj->index;
1384 if ( ++n == ne )
break;
1392 while ( res == FR_OK );
1394 if ( res == FR_OK && ne > 1 )
1399 sum = sum_sfn( dj->fn );
1404 if ( res != FR_OK )
break;
1405 fit_lfn( dj->lfn, dj->dir, ( BYTE )ne, sum );
1409 while ( res == FR_OK && --ne );
1420 if ( res != FR_OK )
break;
1422 if ( c == 0xE5 || c == 0 )
break;
1425 while ( res == FR_OK );
1454 #if !_FS_READONLY && !_FS_MINIMIZE
1465 res =
dir_sdi( dj, ( WORD )( ( dj->lfn_idx == 0xFFFF ) ? i : dj->lfn_idx ) );
1471 if ( res != FR_OK )
break;
1474 if ( dj->index >= i )
break;
1477 while ( res == FR_OK );
1478 if ( res == FR_NO_FILE ) res = FR_INT_ERR;
1482 res =
dir_sdi( dj, dj->index );
1512 static const BYTE excvt[] = _EXCVT;
1528 if ( w <
' ' || w ==
'/' || w ==
'\\' )
break;
1530 return FR_INVALID_NAME;
1535 b = ( BYTE )p[si++];
1537 return FR_INVALID_NAME;
1540 w = ff_convert( w, 1 );
1541 if ( !w )
return FR_INVALID_NAME;
1543 if ( w < 0x80 &&
chk_chr(
"\"*:<>\?|\x7F", w ) )
1544 return FR_INVALID_NAME;
1548 cf = ( w <
' ' ) ?
NS_LAST : 0;
1550 if ( ( di == 1 && lfn[di - 1] ==
'.' ) ||
1551 ( di == 2 && lfn[di - 1] ==
'.' && lfn[di - 2] ==
'.' ) )
1554 for ( i = 0; i < 11; i++ )
1555 dj->fn[i] = ( i < di ) ?
'.' :
' ';
1563 if ( w !=
' ' && w !=
'.' )
break;
1566 if ( !di )
return FR_INVALID_NAME;
1572 for ( si = 0; lfn[si] ==
' ' || lfn[si] ==
'.'; si++ ) ;
1574 while ( di && lfn[di - 1] !=
'.' ) di--;
1581 if ( w ==
' ' || ( w ==
'.' && si != di ) )
1586 if ( i >= ni || si == di )
1593 if ( si > di )
break;
1594 si = di; i = 8; ni = 11;
1601 w = ff_convert( w, 0 );
1602 if ( w ) w = excvt[w - 0x80];
1604 w = ff_convert( ff_wtoupper( w ), 0 );
1609 if ( _DF1S && w >= 0x100 )
1615 dj->fn[i++] = ( BYTE )( w >> 8 );
1619 if ( !w ||
chk_chr(
"+,;=[]", w ) )
1638 dj->fn[i++] = ( BYTE )w;
1641 if ( dj->fn[0] == 0xE5 ) dj->fn[0] = 0x05;
1643 if ( ni == 8 ) b <<= 2;
1644 if ( ( b & 0x0C ) == 0x0C || ( b & 0x03 ) == 0x03 )
1648 if ( ( b & 0x03 ) == 0x01 ) cf |=
NS_EXT;
1649 if ( ( b & 0x0C ) == 0x04 ) cf |=
NS_BODY;
1665 si = i = b = 0; ni = 8;
1672 c = ( BYTE )p[si++];
1673 if ( c !=
'.' || si >= 3 )
break;
1676 if ( c !=
'/' && c !=
'\\' && c >
' ' )
return FR_INVALID_NAME;
1684 c = ( BYTE )p[si++];
1685 if ( c <=
' ' || c ==
'/' || c ==
'\\' )
break;
1686 if ( c ==
'.' || i >= ni )
1688 if ( ni != 8 || c !=
'.' )
return FR_INVALID_NAME;
1696 c = excvt[c - 0x80];
1699 return FR_INVALID_NAME;
1705 d = ( BYTE )p[si++];
1706 if ( !
IsDBCS2( d ) || i >= ni - 1 )
1707 return FR_INVALID_NAME;
1713 if (
chk_chr(
"\"*+,:;<=>\?[]|\x7F", c ) )
1714 return FR_INVALID_NAME;
1730 c = ( c <=
' ' ) ?
NS_LAST : 0;
1732 if ( !i )
return FR_INVALID_NAME;
1733 if ( sfn[0] == 0xE5 ) sfn[0] = 0x05;
1735 if ( ni == 8 ) b <<= 2;
1736 if ( ( b & 0x03 ) == 0x01 ) c |=
NS_EXT;
1737 if ( ( b & 0x0C ) == 0x04 ) c |=
NS_BODY;
1751 #if _FS_MINIMIZE <= 1
1768 for ( i = 0; i < 8; i++ )
1771 if ( c ==
' ' )
break;
1772 if ( c == 0x05 ) c = ( TCHAR )0xE5;
1776 c = ( c << 8 ) | dir[++i];
1777 c = ff_convert( c, 1 );
1782 if ( dir[8] !=
' ' )
1785 for ( i = 8; i < 11; i++ )
1788 if ( c ==
' ' )
break;
1792 c = ( c << 8 ) | dir[++i];
1793 c = ff_convert( c, 1 );
1807 if ( fno->lfname && fno->lfsize )
1809 TCHAR* tp = fno->lfname;
1813 if ( dj->sect && dj->lfn_idx != 0xFFFF )
1816 while ( ( w = *lfn++ ) != 0 )
1819 w = ff_convert( w, 0 );
1820 if ( !w ) { i = 0;
break; }
1821 if ( _DF1S && w >= 0x100 )
1822 tp[i++] = ( TCHAR )( w >> 8 );
1824 if ( i >= fno->lfsize - 1 ) { i = 0;
break; }
1825 tp[i++] = ( TCHAR )w;
1852 if ( *path ==
'/' || *path ==
'\\' )
1854 path++; dj->sclust = 0;
1858 dj->sclust = dj->fs->cdir;
1861 if ( *path ==
'/' || *path ==
'\\' )
1866 if ( ( UINT )*path <
' ' )
1877 if ( res != FR_OK )
break;
1879 ns = *( dj->fn +
NS );
1882 if ( res != FR_NO_FILE )
break;
1886 dj->sclust = 0; dj->dir = 0;
1888 if ( !( ns &
NS_LAST ) )
continue;
1892 if ( !( ns &
NS_LAST ) ) res = FR_NO_PATH;
1900 res = FR_NO_PATH;
break;
1922 if (
disk_read( fs->drv, fs->win, sect, 1 ) != RES_OK )
1924 if ( LD_WORD( &fs->win[
BS_55AA] ) != 0xAA55 )
1927 if ( ( LD_DWORD( &fs->win[
BS_FilSysType] ) & 0xFFFFFF ) == 0x544146 )
1929 if ( ( LD_DWORD( &fs->win[
BS_FilSysType32] ) & 0xFFFFFF ) == 0x544146 )
1950 DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
1952 const TCHAR* p = *path;
1957 if ( vol <= 9 && p[1] ==
':' )
1972 return FR_INVALID_DRIVE;
1973 *rfs = fs = FatFs[vol];
1974 if ( !fs )
return FR_NOT_ENABLED;
1981 if ( !( stat & STA_NOINIT ) )
1984 if ( chk_wp && ( stat & STA_PROTECT ) )
1985 return FR_WRITE_PROTECTED;
1995 fs->drv = ( BYTE )LD2PD( vol );
1997 if ( stat & STA_NOINIT )
1998 return FR_NOT_READY;
2000 if (
disk_ioctl( fs->drv, GET_SECTOR_SIZE, &fs->ssize ) != RES_OK )
2004 if ( chk_wp && ( stat & STA_PROTECT ) )
2005 return FR_WRITE_PROTECTED;
2012 tbl = &fs->win[
MBR_Table + LD2PT( vol ) * 16];
2015 bsect = LD_DWORD( &tbl[8] );
2019 if ( fmt == 3 )
return FR_DISK_ERR;
2020 if ( fmt )
return FR_NO_FILESYSTEM;
2025 return FR_NO_FILESYSTEM;
2028 if ( !fasize ) fasize = LD_DWORD( fs->win +
BPB_FATSz32 );
2032 if ( b != 1 && b != 2 )
return FR_NO_FILESYSTEM;
2036 if ( !b || ( b & ( b - 1 ) ) )
return FR_NO_FILESYSTEM;
2039 if ( fs->n_rootdir % (
SS( fs ) / 32 ) )
return FR_NO_FILESYSTEM;
2042 if ( !tsect ) tsect = LD_DWORD( fs->win +
BPB_TotSec32 );
2045 if ( !nrsv )
return FR_NO_FILESYSTEM;
2048 sysect = nrsv + fasize + fs->n_rootdir / (
SS( fs ) / 32 );
2049 if ( tsect < sysect )
return FR_NO_FILESYSTEM;
2050 nclst = ( tsect - sysect ) / fs->csize;
2051 if ( !nclst )
return FR_NO_FILESYSTEM;
2053 if ( nclst >=
MIN_FAT16 ) fmt = FS_FAT16;
2054 if ( nclst >=
MIN_FAT32 ) fmt = FS_FAT32;
2057 fs->n_fatent = nclst + 2;
2058 fs->database = bsect + sysect;
2059 fs->fatbase = bsect + nrsv;
2060 if ( fmt == FS_FAT32 )
2062 if ( fs->n_rootdir )
return FR_NO_FILESYSTEM;
2064 szbfat = fs->n_fatent * 4;
2068 if ( !fs->n_rootdir )
return FR_NO_FILESYSTEM;
2069 fs->dirbase = fs->fatbase + fasize;
2070 szbfat = ( fmt == FS_FAT16 ) ?
2071 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + ( fs->n_fatent & 1 );
2073 if ( fs->fsize < ( szbfat + (
SS( fs ) - 1 ) ) /
SS( fs ) )
2074 return FR_NO_FILESYSTEM;
2078 fs->free_clust = 0xFFFFFFFF;
2082 if ( fmt == FS_FAT32 )
2085 fs->fsi_sector = bsect + LD_WORD( fs->win +
BPB_FSInfo );
2086 if (
disk_read( fs->drv, fs->win, fs->fsi_sector, 1 ) == RES_OK &&
2087 LD_WORD( fs->win +
BS_55AA ) == 0xAA55 &&
2088 LD_DWORD( fs->win +
FSI_LeadSig ) == 0x41615252 &&
2123 if ( !fs || !fs->fs_type || fs->id !=
id )
2124 return FR_INVALID_OBJECT;
2129 return FR_NOT_READY;
2158 return FR_INVALID_DRIVE;
2167 if ( !ff_del_syncobj( rfs->sobj ) )
return FR_INT_ERR;
2176 if ( !ff_cre_syncobj( vol, &fs->sobj ) )
return FR_INT_ERR;
2207 mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
2208 res =
chk_mounted( &path, &dj.fs, ( BYTE )( mode & ~FA_READ ) );
2222 res = FR_INVALID_NAME;
2225 res = chk_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 );
2229 if ( mode & ( FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW ) )
2235 if ( res == FR_NO_FILE )
2237 res = enq_lock( dj.fs ) ?
dir_register( &dj ) : FR_TOO_MANY_OPEN_FILES;
2241 mode |= FA_CREATE_ALWAYS;
2246 if ( mode & FA_CREATE_NEW )
2252 if ( dir[
DIR_Attr] & ( AM_RDO | AM_DIR ) )
2256 if ( res == FR_OK && ( mode & FA_CREATE_ALWAYS ) )
2267 dw = dj.fs->winsect;
2271 dj.fs->last_clust = cl - 1;
2287 if ( ( mode & FA_WRITE ) && ( dir[
DIR_Attr] & AM_RDO ) )
2294 if ( mode & FA_CREATE_ALWAYS )
2295 mode |= FA__WRITTEN;
2296 fp->dir_sect = dj.fs->winsect;
2299 fp->lockid = inc_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 );
2300 if ( !fp->lockid ) res = FR_INT_ERR;
2309 res = FR_INVALID_NAME;
2330 fp->fs = dj.fs; fp->id = dj.fs->id;
2351 DWORD clst, sect, remain;
2353 BYTE csect, *rbuff = buff;
2359 if ( res != FR_OK )
LEAVE_FF( fp->fs, res );
2360 if ( fp->flag & FA__ERROR )
2362 if ( !( fp->flag & FA_READ ) )
2364 remain = fp->fsize - fp->fptr;
2365 if ( btr > remain ) btr = ( UINT )remain;
2368 rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt )
2370 if ( ( fp->fptr %
SS( fp->fs ) ) == 0 )
2372 csect = ( BYTE )( fp->fptr /
SS( fp->fs ) & ( fp->fs->csize - 1 ) );
2375 clst = ( fp->fptr == 0 ) ?
2376 fp->org_clust :
get_fat( fp->fs, fp->curr_clust );
2377 if ( clst <= 1 )
ABORT( fp->fs, FR_INT_ERR );
2378 if ( clst == 0xFFFFFFFF )
ABORT( fp->fs, FR_DISK_ERR );
2379 fp->curr_clust = clst;
2382 if ( !sect )
ABORT( fp->fs, FR_INT_ERR );
2384 cc = btr /
SS( fp->fs );
2387 if ( csect + cc > fp->fs->csize )
2388 cc = fp->fs->csize - csect;
2389 if (
disk_read( fp->fs->drv, rbuff, sect, ( BYTE )cc ) != RES_OK )
2390 ABORT( fp->fs, FR_DISK_ERR );
2391 #if !_FS_READONLY && _FS_MINIMIZE <= 2
2393 if ( fp->fs->wflag && fp->fs->winsect - sect < cc )
2394 mem_cpy( rbuff + ( ( fp->fs->winsect - sect ) *
SS( fp->fs ) ), fp->fs->win,
SS( fp->fs ) );
2396 if ( ( fp->flag & FA__DIRTY ) && fp->dsect - sect < cc )
2397 mem_cpy( rbuff + ( ( fp->dsect - sect ) *
SS( fp->fs ) ), fp->buf,
SS( fp->fs ) );
2400 rcnt =
SS( fp->fs ) * cc;
2405 if ( fp->flag & FA__DIRTY )
2407 if (
disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
2408 ABORT( fp->fs, FR_DISK_ERR );
2409 fp->flag &= ~FA__DIRTY;
2412 if ( fp->dsect != sect )
2414 if (
disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK )
2415 ABORT( fp->fs, FR_DISK_ERR );
2420 rcnt =
SS( fp->fs ) - ( fp->fptr %
SS( fp->fs ) );
2421 if ( rcnt > btr ) rcnt = btr;
2424 ABORT( fp->fs, FR_DISK_ERR );
2425 mem_cpy( rbuff, &fp->fs->win[fp->fptr %
SS( fp->fs )], rcnt );
2427 mem_cpy( rbuff, &fp->buf[fp->fptr %
SS( fp->fs )], rcnt );
2452 const BYTE* wbuff = buff;
2459 if ( res != FR_OK )
LEAVE_FF( fp->fs, res );
2460 if ( fp->flag & FA__ERROR )
2462 if ( !( fp->flag & FA_WRITE ) )
2464 if ( fp->fsize + btw < fp->fsize ) btw = 0;
2467 wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt )
2469 if ( ( fp->fptr %
SS( fp->fs ) ) == 0 )
2471 csect = ( BYTE )( fp->fptr /
SS( fp->fs ) & ( fp->fs->csize - 1 ) );
2474 if ( fp->fptr == 0 )
2476 clst = fp->org_clust;
2484 if ( clst == 0 )
break;
2485 if ( clst == 1 )
ABORT( fp->fs, FR_INT_ERR );
2486 if ( clst == 0xFFFFFFFF )
ABORT( fp->fs, FR_DISK_ERR );
2487 fp->curr_clust = clst;
2490 if ( fp->fs->winsect == fp->dsect &&
move_window( fp->fs, 0 ) )
2491 ABORT( fp->fs, FR_DISK_ERR );
2493 if ( fp->flag & FA__DIRTY )
2495 if (
disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
2496 ABORT( fp->fs, FR_DISK_ERR );
2497 fp->flag &= ~FA__DIRTY;
2501 if ( !sect )
ABORT( fp->fs, FR_INT_ERR );
2503 cc = btw /
SS( fp->fs );
2506 if ( csect + cc > fp->fs->csize )
2507 cc = fp->fs->csize - csect;
2508 if (
disk_write( fp->fs->drv, wbuff, sect, ( BYTE )cc ) != RES_OK )
2509 ABORT( fp->fs, FR_DISK_ERR );
2511 if ( fp->fs->winsect - sect < cc )
2513 mem_cpy( fp->fs->win, wbuff + ( ( fp->fs->winsect - sect ) *
SS( fp->fs ) ),
SS( fp->fs ) );
2517 if ( fp->dsect - sect < cc )
2519 mem_cpy( fp->buf, wbuff + ( ( fp->dsect - sect ) *
SS( fp->fs ) ),
SS( fp->fs ) );
2520 fp->flag &= ~FA__DIRTY;
2523 wcnt =
SS( fp->fs ) * cc;
2527 if ( fp->fptr >= fp->fsize )
2530 fp->fs->winsect = sect;
2533 if ( fp->dsect != sect )
2535 if ( fp->fptr < fp->fsize &&
2536 disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK )
2537 ABORT( fp->fs, FR_DISK_ERR );
2542 wcnt =
SS( fp->fs ) - ( fp->fptr %
SS( fp->fs ) );
2543 if ( wcnt > btw ) wcnt = btw;
2546 ABORT( fp->fs, FR_DISK_ERR );
2547 mem_cpy( &fp->fs->win[fp->fptr %
SS( fp->fs )], wbuff, wcnt );
2550 mem_cpy( &fp->buf[fp->fptr %
SS( fp->fs )], wbuff, wcnt );
2551 fp->flag |= FA__DIRTY;
2555 if ( fp->fptr > fp->fsize ) fp->fsize = fp->fptr;
2556 fp->flag |= FA__WRITTEN;
2580 if ( fp->flag & FA__WRITTEN )
2583 if ( fp->flag & FA__DIRTY )
2585 if (
disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
2587 fp->flag &= ~FA__DIRTY;
2600 fp->flag &= ~FA__WRITTEN;
2602 res =
sync( fp->fs );
2628 if ( res == FR_OK ) fp->fs = 0;
2640 res = dec_lock( fp->lockid );
2641 unlock_fs( fp->fs, FR_OK );
2644 res = dec_lock( fp->lockid );
2648 if ( res == FR_OK ) fp->fs = 0;
2662 NODEBUG FRESULT f_chdrive(
2666 if ( drv >=
_VOLUMES )
return FR_INVALID_DRIVE;
2675 NODEBUG FRESULT f_chdir(
2694 dj.fs->cdir = dj.sclust;
2704 if ( res == FR_NO_FILE ) res = FR_NO_PATH;
2712 NODEBUG FRESULT f_getcwd(
2727 res =
chk_mounted( (
const TCHAR** )&path, &dj.fs, 0 );
2732 dj.sclust = dj.fs->cdir;
2733 while ( ( ccl = dj.sclust ) != 0 )
2736 if ( res != FR_OK )
break;
2738 if ( res != FR_OK )
break;
2741 if ( res != FR_OK )
break;
2745 if ( res != FR_OK )
break;
2746 if ( ccl ==
LD_CLUST( dj.dir ) )
break;
2749 while ( res == FR_OK );
2750 if ( res == FR_NO_FILE ) res = FR_INT_ERR;
2751 if ( res != FR_OK )
break;
2758 if (
_USE_LFN && *path ) tp = path;
2759 for ( n = 0; tp[n]; n++ ) ;
2762 res = FR_NOT_ENOUGH_CORE;
break;
2764 while ( n ) path[--i] = tp[--n];
2770 *tp++ =
'0' + CurrVol;
2780 while ( i < sz_path );
2794 #if _FS_MINIMIZE <= 2
2808 if ( res != FR_OK )
LEAVE_FF( fp->fs, res );
2809 if ( fp->flag & FA__ERROR )
2815 DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl;
2819 if ( ofs == CREATE_LINKMAP )
2828 res = FR_NOT_ENOUGH_CORE;
break;
2835 if ( cl <= 1 )
ABORT( fp->fs, FR_INT_ERR );
2836 if ( cl == 0xFFFFFFFF )
ABORT( fp->fs, FR_DISK_ERR );
2838 while ( cl == pcl + 1 );
2839 *tbl++ = ncl; *tbl++ = tcl;
2842 while ( cl < fp->fs->n_fatent );
2849 if ( ofs > fp->fsize )
2854 dsc = ( ofs - 1 ) /
SS( fp->fs );
2855 cl = dsc / fp->fs->csize;
2859 if ( !ncl )
ABORT( fp->fs, FR_INT_ERR );
2860 if ( cl < ncl )
break;
2863 fp->curr_clust = cl + *tbl;
2864 csc = ( BYTE )( dsc & ( fp->fs->csize - 1 ) );
2866 if ( !dsc )
ABORT( fp->fs, FR_INT_ERR );
2868 if ( fp->fptr %
SS( fp->fs ) && dsc != fp->dsect )
2872 if ( fp->flag & FA__DIRTY )
2874 if (
disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
2875 ABORT( fp->fs, FR_DISK_ERR );
2876 fp->flag &= ~FA__DIRTY;
2879 if (
disk_read( fp->fs->drv, fp->buf, dsc, 1 ) != RES_OK )
2880 ABORT( fp->fs, FR_DISK_ERR );
2892 DWORD clst, bcs, nsect, ifptr;
2894 if ( ofs > fp->fsize
2896 && !( fp->flag & FA_WRITE )
2901 fp->fptr = nsect = 0;
2904 bcs = ( DWORD )fp->fs->csize *
SS( fp->fs );
2906 ( ofs - 1 ) / bcs >= ( ifptr - 1 ) / bcs )
2908 fp->fptr = ( ifptr - 1 ) & ~( bcs - 1 );
2910 clst = fp->curr_clust;
2914 clst = fp->org_clust;
2919 if ( clst == 1 )
ABORT( fp->fs, FR_INT_ERR );
2920 if ( clst == 0xFFFFFFFF )
ABORT( fp->fs, FR_DISK_ERR );
2921 fp->org_clust = clst;
2924 fp->curr_clust = clst;
2931 if ( fp->flag & FA_WRITE )
2941 clst =
get_fat( fp->fs, clst );
2942 if ( clst == 0xFFFFFFFF )
ABORT( fp->fs, FR_DISK_ERR );
2943 if ( clst <= 1 || clst >= fp->fs->n_fatent )
ABORT( fp->fs, FR_INT_ERR );
2944 fp->curr_clust = clst;
2949 if ( ofs %
SS( fp->fs ) )
2952 if ( !nsect )
ABORT( fp->fs, FR_INT_ERR );
2953 nsect += ofs /
SS( fp->fs );
2957 if ( fp->fptr %
SS( fp->fs ) && nsect != fp->dsect )
2961 if ( fp->flag & FA__DIRTY )
2963 if (
disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK )
2964 ABORT( fp->fs, FR_DISK_ERR );
2965 fp->flag &= ~FA__DIRTY;
2968 if (
disk_read( fp->fs->drv, fp->buf, nsect, 1 ) != RES_OK )
2969 ABORT( fp->fs, FR_DISK_ERR );
2974 if ( fp->fptr > fp->fsize )
2976 fp->fsize = fp->fptr;
2977 fp->flag |= FA__WRITTEN;
2987 #if _FS_MINIMIZE <= 1
3022 dj->id = dj->fs->id;
3026 if ( res == FR_NO_FILE ) res = FR_NO_PATH;
3059 if ( res == FR_NO_FILE )
3068 if ( res == FR_NO_FILE )
3083 #if _FS_MINIMIZE == 0
3108 res = FR_INVALID_NAME;
3130 DWORD n, clst, sect, stat;
3140 if ( ( *fatfs )->free_clust <= ( *fatfs )->n_fatent - 2 )
3142 *nclst = ( *fatfs )->free_clust;
3147 fat = ( *fatfs )->fs_type;
3149 if ( fat == FS_FAT12 )
3154 stat =
get_fat( *fatfs, clst );
3155 if ( stat == 0xFFFFFFFF ) { res = FR_DISK_ERR;
break; }
3156 if ( stat == 1 ) { res = FR_INT_ERR;
break; }
3157 if ( stat == 0 ) n++;
3159 while ( ++clst < ( *fatfs )->n_fatent );
3163 clst = ( *fatfs )->n_fatent;
3164 sect = ( *fatfs )->fatbase;
3171 if ( res != FR_OK )
break;
3172 p = ( *fatfs )->win;
3175 if ( fat == FS_FAT16 )
3177 if ( LD_WORD( p ) == 0 ) n++;
3182 if ( ( LD_DWORD( p ) & 0x0FFFFFFF ) == 0 ) n++;
3188 ( *fatfs )->free_clust = n;
3189 if ( fat == FS_FAT32 )( *fatfs )->fsi_flag = 1;
3214 if ( fp->flag & FA__ERROR )
3220 if ( !( fp->flag & FA_WRITE ) )
3226 if ( fp->fsize > fp->fptr )
3228 fp->fsize = fp->fptr;
3229 fp->flag |= FA__WRITTEN;
3230 if ( fp->fptr == 0 )
3237 ncl =
get_fat( fp->fs, fp->curr_clust );
3239 if ( ncl == 0xFFFFFFFF ) res = FR_DISK_ERR;
3240 if ( ncl == 1 ) res = FR_INT_ERR;
3241 if ( res == FR_OK && ncl < fp->fs->n_fatent )
3243 res =
put_fat( fp->fs, fp->curr_clust, 0x0FFFFFFF );
3248 if ( res != FR_OK ) fp->flag |= FA__ERROR;
3278 res = FR_INVALID_NAME;
3280 if ( res == FR_OK ) res = chk_lock( &dj, 2 );
3287 res = FR_INVALID_NAME;
3295 if ( res == FR_OK && ( dir[
DIR_Attr] & AM_DIR ) )
3303 mem_cpy( &sdj, &dj,
sizeof( DIR ) );
3311 || dclst == sdj.fs->cdir
3314 if ( res == FR_NO_FILE ) res = FR_OK;
3325 if ( res == FR_OK ) res =
sync( dj.fs );
3357 if ( res == FR_OK ) res = FR_EXIST;
3359 res = FR_INVALID_NAME;
3360 if ( res == FR_NO_FILE )
3364 if ( dcl == 0 ) res = FR_DENIED;
3365 if ( dcl == 1 ) res = FR_INT_ERR;
3366 if ( dcl == 0xFFFFFFFF ) res = FR_DISK_ERR;
3380 dir[33] =
'.'; pcl = dj.sclust;
3381 if ( dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase )
3384 for ( n = dj.fs->csize; n; n-- )
3386 dj.fs->winsect = dsc++;
3389 if ( res != FR_OK )
break;
3405 res =
sync( dj.fs );
3440 res = FR_INVALID_NAME;
3446 res = FR_INVALID_NAME;
3450 mask &= AM_RDO | AM_HID | AM_SYS | AM_ARC;
3453 res =
sync( dj.fs );
3486 res = FR_INVALID_NAME;
3492 res = FR_INVALID_NAME;
3499 res =
sync( dj.fs );
3515 const TCHAR* path_old,
3516 const TCHAR* path_new
3533 res = FR_INVALID_NAME;
3535 if ( res == FR_OK ) res = chk_lock( &djo, 2 );
3546 mem_cpy( &djn, &djo,
sizeof( DIR ) );
3548 if ( res == FR_OK ) res = FR_EXIST;
3549 if ( res == FR_NO_FILE )
3556 mem_cpy( dir + 13, buf + 2, 19 );
3559 if ( djo.sclust != djn.sclust && ( dir[
DIR_Attr] & AM_DIR ) )
3569 dir = djn.fs->win + 32;
3570 if ( res == FR_OK && dir[1] ==
'.' )
3572 dw = ( djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase ) ? 0 : djn.sclust;
3582 res =
sync( djo.fs );
3604 #if _USE_FORWARD && _FS_TINY
3606 NODEBUG FRESULT f_forward(
3608 UINT( *func )(
const BYTE*, UINT ),
3614 DWORD remain, clst, sect;
3622 if ( res != FR_OK )
LEAVE_FF( fp->fs, res );
3623 if ( fp->flag & FA__ERROR )
3625 if ( !( fp->flag & FA_READ ) )
3628 remain = fp->fsize - fp->fptr;
3629 if ( btr > remain ) btr = ( UINT )remain;
3631 for ( ; btr && ( *func )( 0, 0 );
3632 fp->fptr += rcnt, *bf += rcnt, btr -= rcnt )
3634 csect = ( BYTE )( fp->fptr /
SS( fp->fs ) & ( fp->fs->csize - 1 ) );
3635 if ( ( fp->fptr %
SS( fp->fs ) ) == 0 )
3639 clst = ( fp->fptr == 0 ) ?
3640 fp->org_clust :
get_fat( fp->fs, fp->curr_clust );
3641 if ( clst <= 1 )
ABORT( fp->fs, FR_INT_ERR );
3642 if ( clst == 0xFFFFFFFF )
ABORT( fp->fs, FR_DISK_ERR );
3643 fp->curr_clust = clst;
3647 if ( !sect )
ABORT( fp->fs, FR_INT_ERR );
3650 ABORT( fp->fs, FR_DISK_ERR );
3652 rcnt =
SS( fp->fs ) - ( WORD )( fp->fptr %
SS( fp->fs ) );
3653 if ( rcnt > btr ) rcnt = btr;
3654 rcnt = ( *func )( &fp->fs->win[( WORD )fp->fptr %
SS( fp->fs )], rcnt );
3655 if ( !rcnt )
ABORT( fp->fs, FR_INT_ERR );
3664 #if _USE_MKFS && !_FS_READONLY
3668 #define N_ROOTDIR 512
3672 NODEBUG FRESULT f_mkfs(
3678 static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
3679 static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
3681 DWORD n_clst, vs, n, wsect;
3683 DWORD b_vol, b_fat, b_dir, b_data;
3684 DWORD n_vol, n_rsv, n_fat, n_dir;
3690 if ( drv >=
_VOLUMES )
return FR_INVALID_DRIVE;
3692 if ( !fs )
return FR_NOT_ENABLED;
3698 if ( stat & STA_NOINIT )
return FR_NOT_READY;
3699 if ( stat & STA_PROTECT )
return FR_WRITE_PROTECTED;
3701 if (
disk_ioctl( drv, GET_SECTOR_SIZE, &
SS( fs ) ) != RES_OK )
3704 if (
disk_ioctl( drv, GET_SECTOR_COUNT, &n_vol ) != RES_OK || n_vol < 128 )
3706 b_vol = ( sfd ) ? 0 : 63;
3708 if ( au & ( au - 1 ) ) au = 0;
3711 vs = n_vol / ( 2000 / (
SS( fs ) / 512 ) );
3712 for ( i = 0; vs < vst[i]; i++ ) ;
3716 if ( au == 0 ) au = 1;
3717 if ( au > 128 ) au = 128;
3720 n_clst = n_vol / au;
3722 if ( n_clst >=
MIN_FAT16 ) fmt = FS_FAT16;
3723 if ( n_clst >=
MIN_FAT32 ) fmt = FS_FAT32;
3726 if ( fmt == FS_FAT32 )
3728 n_fat = ( ( n_clst * 4 ) + 8 +
SS( fs ) - 1 ) /
SS( fs );
3734 n_fat = ( fmt == FS_FAT12 ) ? ( n_clst * 3 + 1 ) / 2 + 3 : ( n_clst * 2 ) + 4;
3735 n_fat = ( n_fat +
SS( fs ) - 1 ) /
SS( fs );
3737 n_dir = N_ROOTDIR * 32UL /
SS( fs );
3739 b_fat = b_vol + n_rsv;
3740 b_dir = b_fat + n_fat * N_FATS;
3741 b_data = b_dir + n_dir;
3742 if ( n_vol < b_data + au )
return FR_MKFS_ABORTED;
3745 if (
disk_ioctl( drv, GET_BLOCK_SIZE, &n ) != RES_OK || !n || n > 32768 ) n = 1;
3746 n = ( b_data + n - 1 ) & ~( n - 1 );
3747 n = ( n - b_data ) / N_FATS;
3748 if ( fmt == FS_FAT32 )
3759 n_clst = ( n_vol - n_rsv - n_fat * N_FATS - n_dir ) / au;
3760 if ( ( fmt == FS_FAT16 && n_clst <
MIN_FAT16 )
3761 || ( fmt == FS_FAT32 && n_clst <
MIN_FAT32 ) )
3762 return FR_MKFS_ABORTED;
3771 DWORD n_disk = b_vol + n_vol;
3775 ST_DWORD( tbl, 0x00010180 );
3776 if ( n_disk < 63UL * 255 * 1024 )
3778 n_disk = n_disk / 63 / 255;
3779 tbl[7] = ( BYTE )n_disk;
3780 tbl[6] = ( BYTE )( ( n_disk >> 2 ) | 63 );
3784 ST_WORD( &tbl[6], 0xFFFF );
3787 if ( fmt != FS_FAT32 )
3788 tbl[4] = ( n_vol < 0x10000 ) ? 0x04 : 0x06;
3791 ST_DWORD( tbl + 8, 63 );
3792 ST_DWORD( tbl + 12, n_vol );
3793 ST_WORD( tbl + 64, 0xAA55 );
3794 if (
disk_write( drv, fs->win, 0, 1 ) != RES_OK )
3802 mem_cpy( tbl,
"\xEB\xFE\x90" "MSDOS5.0", 11 );
3808 i = ( fmt == FS_FAT32 ) ? 0 : N_ROOTDIR;
3810 if ( n_vol < 0x10000 )
3823 if ( fmt == FS_FAT32 )
3842 ST_WORD( tbl +
BS_55AA, 0xAA55 );
3843 if (
disk_write( drv, tbl, b_vol, 1 ) != RES_OK )
3845 if ( fmt == FS_FAT32 )
3850 for ( i = 0; i < N_FATS; i++ )
3854 if ( fmt != FS_FAT32 )
3856 n |= ( fmt == FS_FAT12 ) ? 0x00FFFF00 : 0xFFFFFF00;
3857 ST_DWORD( tbl + 0, n );
3862 ST_DWORD( tbl + 0, n );
3863 ST_DWORD( tbl + 4, 0xFFFFFFFF );
3864 ST_DWORD( tbl + 8, 0x0FFFFFFF );
3866 if (
disk_write( drv, tbl, wsect++, 1 ) != RES_OK )
3869 for ( n = 1; n < n_fat; n++ )
3871 if (
disk_write( drv, tbl, wsect++, 1 ) != RES_OK )
3877 i = ( fmt == FS_FAT32 ) ? au : n_dir;
3880 if (
disk_write( drv, tbl, wsect++, 1 ) != RES_OK )
3889 eb[0] = wsect; eb[1] = wsect + n_clst * au - 1;
3895 if ( fmt == FS_FAT32 )
3897 ST_WORD( tbl +
BS_55AA, 0xAA55 );
3906 return (
disk_ioctl( drv, CTRL_SYNC, (
void* )0 ) == RES_OK ) ? FR_OK : FR_DISK_ERR;
3918 NODEBUG TCHAR* f_gets(
3930 while ( n < len - 1 )
3932 f_read( fil, s, 1, &rc );
3933 if ( rc != 1 )
break;
3938 if ( c < 0xC0 )
continue;
3941 f_read( fil, s, 1, &rc );
3942 if ( rc != 1 )
break;
3943 c = ( ( c & 0x1F ) << 6 ) | ( s[0] & 0x3F );
3944 if ( c < 0x80 ) c =
'?';
3950 f_read( fil, s, 2, &rc );
3951 if ( rc != 2 )
break;
3952 c = ( c << 12 ) | ( ( s[0] & 0x3F ) << 6 ) | ( s[1] & 0x3F );
3953 if ( c < 0x800 ) c =
'?';
3962 #if _USE_STRFUNC >= 2
3963 if ( c ==
'\r' )
continue;
3967 if ( c ==
'\n' )
break;
3970 return n ? buff : 0;
3989 #if _USE_STRFUNC >= 2
3990 if ( c ==
'\n' ) f_putc(
'\r', fil );
4003 s[0] = ( BYTE )( 0xC0 | ( c >> 6 ) );
4004 s[1] = ( BYTE )( 0x80 | ( c & 0x3F ) );
4009 s[0] = ( BYTE )( 0xE0 | ( c >> 12 ) );
4010 s[1] = ( BYTE )( 0x80 | ( ( c >> 6 ) & 0x3F ) );
4011 s[2] = ( BYTE )( 0x80 | ( c & 0x3F ) );
4020 return ( bw == btw ) ? 1 : EOF;
4037 for ( n = 0; *str; str++, n++ )
4039 if ( f_putc( *str, fil ) == EOF )
return EOF;
4050 NODEBUG
int f_printf(
4064 va_start( arp, str );
4066 for ( cc = res = 0; cc != EOF; res += cc )
4069 if ( c == 0 )
break;
4072 cc = f_putc( c, fil );
4073 if ( cc != EOF ) cc = 1;
4084 w = w * 10 + c -
'0';
4087 if ( c ==
'l' || c ==
'L' )
4093 if (
IsLower( d ) ) d -= 0x20;
4097 cc = f_puts( va_arg( arp, TCHAR* ), fil );
continue;
4099 cc = f_putc( ( TCHAR )va_arg( arp,
int ), fil );
continue;
4110 cc = f_putc( c, fil );
continue;
4114 val = ( f & 2 ) ? va_arg( arp,
long ) : ( ( d ==
'D' ) ? (
long )va_arg( arp,
int ) : va_arg( arp, unsigned int ) );
4115 if ( d ==
'D' && ( val & 0x80000000 ) )
4124 d = ( TCHAR )( val % r ); val /= r;
4128 if ( c ==
'x' ) d += 0x20;
4132 while ( val && i <
sizeof( s ) /
sizeof( s[0] ) );
4133 if ( f & 4 ) s[i++] =
'-';
4135 while ( i < w-- && cc != EOF )
4137 cc = f_putc( ( TCHAR )( ( f & 1 ) ?
'0' :
' ' ), fil );
4142 cc = f_putc( s[--i], fil );
4145 while ( i && cc != EOF );
4146 if ( cc != EOF ) cc = 0;
4150 return ( cc == EOF ) ? cc : res;