diff options
Diffstat (limited to 'Projects/Webserver/Lib/FATFs')
-rw-r--r-- | Projects/Webserver/Lib/FATFs/00readme.txt | 21 | ||||
-rw-r--r-- | Projects/Webserver/Lib/FATFs/diskio.h | 25 | ||||
-rw-r--r-- | Projects/Webserver/Lib/FATFs/ff.c | 1336 | ||||
-rw-r--r-- | Projects/Webserver/Lib/FATFs/ff.h | 353 | ||||
-rw-r--r-- | Projects/Webserver/Lib/FATFs/ffconf.h | 64 | ||||
-rw-r--r-- | Projects/Webserver/Lib/FATFs/integer.h | 2 |
6 files changed, 970 insertions, 831 deletions
diff --git a/Projects/Webserver/Lib/FATFs/00readme.txt b/Projects/Webserver/Lib/FATFs/00readme.txt index 97951fc3d..c78da3186 100644 --- a/Projects/Webserver/Lib/FATFs/00readme.txt +++ b/Projects/Webserver/Lib/FATFs/00readme.txt @@ -1,4 +1,4 @@ -FatFs Module Source Files R0.08 (C)ChaN, 2010 +FatFs Module Source Files R0.08b (C)ChaN, 2011 FILES @@ -7,7 +7,6 @@ FILES ff.h Common include file for FatFs and application module. ff.c FatFs module. diskio.h Common include file for FatFs and disk I/O module. - diskio.c Skeleton of low level disk I/O module. integer.h Alternative type definitions for integer variables. option Optional external functions. @@ -24,7 +23,7 @@ AGREEMENTS small embedded systems. This is a free software and is opened for education, research and commercial developments under license policy of following trems. - Copyright (C) 2010, ChaN, all right reserved. + Copyright (C) 2011, ChaN, all right reserved. * The FatFs module is a free software and there is NO WARRANTY. * No restriction on use. You can use, modify and redistribute it for @@ -41,14 +40,14 @@ REVISION HISTORY Jun 01, 2006 R0.02 Added FAT12. Removed unbuffered mode. - Fixed a problem on small (<32M) partition. + Fixed a problem on small (<32M) patition. Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM. Sep 22, 2006 R0.03 Added f_rename. Changed option _FS_MINIMUM to _FS_MINIMIZE. - Dec 11, 2006 R0.03a Improved cluster scan algorithm to write files fast. + Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast. Fixed f_mkdir creates incorrect directory on FAT32. Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs) @@ -56,7 +55,7 @@ REVISION HISTORY Added f_mkfs. (FatFs) Added _USE_FAT32 option. (Tiny-FatFs) - Apr 01, 2007 R0.04a Supported multiple partitions on a physical drive. (FatFs) + Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs) Fixed an endian sensitive code in f_mkfs. (FatFs) Added a capability of extending the file size to f_lseek. Added minimization level 3. @@ -116,3 +115,13 @@ REVISION HISTORY Changed fname member in the FILINFO structure on Unicode cfg. String functions support UTF-8 encoding files on Unicode cfg. + Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) + Added sector erase feature. (_USE_ERASE) + Moved file lock semaphore table from fs object to the bss. + Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. + Fixed f_mkfs() creates wrong FAT32 volume. + + Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). + f_lseek() reports required table size on creating CLMP. + Extended format syntax of f_printf function. + Ignores duplicated directory separators in given path names. diff --git a/Projects/Webserver/Lib/FATFs/diskio.h b/Projects/Webserver/Lib/FATFs/diskio.h index fc18b9a50..0d3454366 100644 --- a/Projects/Webserver/Lib/FATFs/diskio.h +++ b/Projects/Webserver/Lib/FATFs/diskio.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------- -/ Low level disk interface module include file R0.07 (C)ChaN, 2010 +/ Low level disk interface module include file /-----------------------------------------------------------------------*/ #ifndef _DISKIO @@ -29,7 +29,6 @@ typedef enum { /*---------------------------------------*/ /* Prototypes for disk control functions */ -BOOL assign_drives (int argc, char *argv[]); DSTATUS disk_initialize (BYTE); DSTATUS disk_status (BYTE); DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); @@ -46,28 +45,6 @@ DRESULT disk_ioctl (BYTE, BYTE, void*); #define STA_PROTECT 0x04 /* Write protected */ -/* Command code for disk_ioctrl() */ - -/* Generic command */ -#define CTRL_SYNC 0 /* Mandatory for write functions */ -#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */ -#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */ -#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */ -#define CTRL_POWER 4 -#define CTRL_LOCK 5 -#define CTRL_EJECT 6 -/* MMC/SDC command */ -#define MMC_GET_TYPE 10 -#define MMC_GET_CSD 11 -#define MMC_GET_CID 12 -#define MMC_GET_OCR 13 -#define MMC_GET_SDSTAT 14 -/* ATA/CF command */ -#define ATA_GET_REV 20 -#define ATA_GET_MODEL 21 -#define ATA_GET_SN 22 - - #define _DISKIO #endif diff --git a/Projects/Webserver/Lib/FATFs/ff.c b/Projects/Webserver/Lib/FATFs/ff.c index cb2b42508..4f76915b6 100644 --- a/Projects/Webserver/Lib/FATFs/ff.c +++ b/Projects/Webserver/Lib/FATFs/ff.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.08 (C)ChaN, 2010 +/ FatFs - FAT file system module R0.08b (C)ChaN, 2011 /-----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2010, ChaN, all right reserved. +/ Copyright (C) 2011, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -46,23 +46,21 @@ / Feb 03,'08 R0.05a Added f_truncate() and f_utime(). / Fixed off by one error at FAT sub-type determination. / Fixed btr in f_read() can be mistruncated. -/ Fixed cached sector is not flushed when create and close -/ without write. +/ Fixed cached sector is not flushed when create and close without write. / / Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). -/ Improved performance of f_lseek() on moving to the same -/ or following cluster. +/ Improved performance of f_lseek() on moving to the same or following cluster. / -/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a buffer configuration option. -/ Added long file name support. -/ Added multiple code page support. +/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) +/ Added long file name feature. +/ Added multiple code page feature. / Added re-entrancy for multitask operation. / Added auto cluster size selection to f_mkfs(). / Added rewind option to f_readdir(). / Changed result code of critical errors. / Renamed string functions to avoid name collision. / Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. -/ Added multiple sector size support. +/ Added multiple sector size feature. / Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. / Fixed wrong cache control in f_lseek(). / Added relative path feature. @@ -72,15 +70,23 @@ / Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. / Fixed name matching error on the 13 char boundary. / Added a configuration option, _LFN_UNICODE. -/ Changed f_readdir() to return the SFN with always upper -/ case on non-LFN cfg. +/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. / -/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN) +/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) / Added file lock feature. (_FS_SHARE) / Added fast seek feature. (_USE_FASTSEEK) / Changed some types on the API, XCHAR->TCHAR. / Changed fname member in the FILINFO structure on Unicode cfg. / String functions support UTF-8 encoding files on Unicode cfg. +/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) +/ Added sector erase feature. (_USE_ERASE) +/ Moved file lock semaphore table from fs object to the bss. +/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. +/ Fixed f_mkfs() creates wrong FAT32 volume. +/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). +/ f_lseek() reports required table size on creating CLMP. +/ Extended format syntax of f_printf function. +/ Ignores duplicated directory separators in given path names. /---------------------------------------------------------------------------*/ #include "ff.h" /* FatFs configurations and declarations */ @@ -93,44 +99,253 @@ ---------------------------------------------------------------------------*/ -#if _FATFS != 8085 +#if _FATFS != 8237 #error Wrong include file (ff.h). #endif -/* FAT sub-type boundaries */ -/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ -#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ -#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ - - -/* Definitions corresponds to multiple sector size */ -#if _MAX_SS == 512 /* Single sector size */ -#define SS(fs) 512U -#elif _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096 /* Multiple sector size */ -#define SS(fs) ((fs)->ssize) -#else +/* Definitions on sector size */ +#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 #error Wrong sector size. #endif +#if _MAX_SS != 512 +#define SS(fs) ((fs)->ssize) /* Multiple sector size */ +#else +#define SS(fs) 512U /* Fixed sector size */ +#endif -/* Re-entrancy related */ +/* Reentrancy related */ #if _FS_REENTRANT #if _USE_LFN == 1 #error Static LFN work area must not be used in re-entrant configuration. #endif #define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } #define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } - #else #define ENTER_FF(fs) #define LEAVE_FF(fs, res) return res - #endif #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } +/* File shareing feature */ +#if _FS_SHARE +#if _FS_READONLY +#error _FS_SHARE must be 0 on read-only cfg. +#endif +typedef struct { + FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ + DWORD clu; /* File ID 2, directory */ + WORD idx; /* File ID 3, directory index */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* Misc definitions */ +#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) +#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} + + +/* DBCS code ranges and SBCS extend char conversion table */ + +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ + +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE + +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + +#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1253 /* Greek (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + +#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#if _USE_LFN +#error Cannot use LFN feature without valid code page. +#endif +#define _DF1S 0 + +#else +#error Unknown code page + +#endif + + /* Character code support macros */ #define IsUpper(c) (((c)>='A')&&((c)<='Z')) #define IsLower(c) (((c)>='a')&&((c)<='z')) @@ -159,7 +374,7 @@ /* Name status flags */ -#define NS 11 /* Offset of name status byte */ +#define NS 11 /* Index of name status byte in fn[] */ #define NS_LOSS 0x01 /* Out of 8.3 format */ #define NS_LFN 0x02 /* Force to create LFN entry */ #define NS_LAST 0x04 /* Last segment */ @@ -168,23 +383,97 @@ #define NS_DOT 0x20 /* Dot entry */ +/* FAT sub-type boundaries */ +/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ + + +/* FatFs refers the members in the FAT structures as byte array instead of +/ structure member because the structure is not binary compatible between +/ different platforms */ + +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root dir first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sectot (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Boot sector signature (2) */ + +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ +#define DIR_FileSize 28 /* File size (4) */ +#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +#define LDIR_FstClusLO 26 /* Filled by zero (0) */ +#define SZ_DIR 32 /* Size of a directory entry */ +#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ +#define DDE 0xE5 /* Deleted directory enrty mark in DIR_Name[0] */ +#define NDDE 0x05 /* Replacement of a character collides with DDE */ + /*------------------------------------------------------------*/ /* Work area */ -#if !_DRIVES +#if _VOLUMES +static +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +#else #error Number of drives must not be 0. #endif + static WORD Fsid; /* File system mount ID */ -static -FATFS *FatFs[_DRIVES]; /* Pointer to the file system objects (logical drives) */ #if _FS_RPATH static -BYTE Drive; /* Current drive */ +BYTE CurrVol; /* Current drive */ #endif +#if _FS_SHARE +static +FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +#endif #if _USE_LFN == 0 /* No LFN */ #define DEF_NAMEBUF BYTE sfn[12] @@ -192,13 +481,13 @@ BYTE Drive; /* Current drive */ #define FREE_BUF() #elif _USE_LFN == 1 /* LFN with static LFN working buffer */ -static WCHAR LfnBuf[_MAX_LFN + 1]; +static WCHAR LfnBuf[_MAX_LFN+1]; #define DEF_NAMEBUF BYTE sfn[12] #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } #define FREE_BUF() #elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN + 1] +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } #define FREE_BUF() @@ -229,7 +518,7 @@ static WCHAR LfnBuf[_MAX_LFN + 1]; /* Copy memory to memory */ static -void mem_cpy (void* dst, const void* src, int cnt) { +void mem_cpy (void* dst, const void* src, UINT cnt) { BYTE *d = (BYTE*)dst; const BYTE *s = (const BYTE*)src; @@ -246,7 +535,7 @@ void mem_cpy (void* dst, const void* src, int cnt) { /* Fill memory */ static -void mem_set (void* dst, int val, int cnt) { +void mem_set (void* dst, int val, UINT cnt) { BYTE *d = (BYTE*)dst; while (cnt--) @@ -255,7 +544,7 @@ void mem_set (void* dst, int val, int cnt) { /* Compare memory to memory */ static -int mem_cmp (const void* dst, const void* src, int cnt) { +int mem_cmp (const void* dst, const void* src, UINT cnt) { const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; int r = 0; @@ -304,7 +593,7 @@ void unlock_fs ( /*-----------------------------------------------------------------------*/ -/* File sharing control functions */ +/* File shareing control functions */ /*-----------------------------------------------------------------------*/ #if _FS_SHARE @@ -318,18 +607,19 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ /* Search file semaphore table */ for (i = be = 0; i < _FS_SHARE; i++) { - if (dj->fs->flsem[i].ctr) { /* Existing entry */ - if (dj->fs->flsem[i].clu == dj->sclust && /* The file is found (identified with its location) */ - dj->fs->flsem[i].idx == dj->index) break; - } else { /* Blank entry */ + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } else { /* Blank entry */ be++; } } - if (i == _FS_SHARE) /* The file has not been opened */ - return (be || acc != 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + if (i == _FS_SHARE) /* The file is not opened */ + return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ /* The file has been opened. Reject any open against writing file and all write mode open */ - return (acc || dj->fs->flsem[i].ctr == 0x100) ? FR_LOCKED : FR_OK; + return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; } @@ -340,7 +630,7 @@ int enq_lock ( /* Check if an entry is available for a new file */ { UINT i; - for (i = 0; i < _FS_SHARE && fs->flsem[i].ctr; i++) ; + for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; return (i == _FS_SHARE) ? 0 : 1; } @@ -355,21 +645,23 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ - if (dj->fs->flsem[i].ctr && - dj->fs->flsem[i].clu == dj->sclust && - dj->fs->flsem[i].idx == dj->index) break; + if (Files[i].fs == dj->fs && + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; } if (i == _FS_SHARE) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_SHARE && dj->fs->flsem[i].ctr; i++) ; + for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; if (i == _FS_SHARE) return 0; /* No space to register (int err) */ - dj->fs->flsem[i].clu = dj->sclust; - dj->fs->flsem[i].idx = dj->index; + Files[i].fs = dj->fs; + Files[i].clu = dj->sclust; + Files[i].idx = dj->index; + Files[i].ctr = 0; } - if (acc && dj->fs->flsem[i].ctr) return 0; /* Access violation (int err) */ + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ - dj->fs->flsem[i].ctr = acc ? 0x100 : dj->fs->flsem[i].ctr + 1; /* Set semaphore value */ + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ return i + 1; } @@ -377,7 +669,6 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro static FRESULT dec_lock ( /* Decrement file open counter */ - FATFS* fs, /* File system object */ UINT i /* Semaphore index */ ) { @@ -386,10 +677,11 @@ FRESULT dec_lock ( /* Decrement file open counter */ if (--i < _FS_SHARE) { - n = fs->flsem[i].ctr; - if (n >= 0x100) n = 0; + n = Files[i].ctr; + if (n == 0x100) n = 0; if (n) n--; - fs->flsem[i].ctr = n; + Files[i].ctr = n; + if (!n) Files[i].fs = 0; res = FR_OK; } else { res = FR_INT_ERR; @@ -397,6 +689,18 @@ FRESULT dec_lock ( /* Decrement file open counter */ return res; } + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < _FS_SHARE; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} #endif @@ -460,12 +764,14 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ /* Update FSInfo sector if needed */ if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { fs->winsect = 0; + /* Create FSInfo structure */ mem_set(fs->win, 0, 512); 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); + /* Write it into the FSInfo sector */ disk_write(fs->drv, fs->win, fs->fsi_sector, 1); fs->fsi_flag = 0; } @@ -482,6 +788,24 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ /*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ + + +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; + if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ + return clst * fs->csize + fs->database; +} + + + + +/*-----------------------------------------------------------------------*/ /* FAT access - Read value of a FAT entry */ /*-----------------------------------------------------------------------*/ @@ -495,7 +819,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status BYTE *p; - if (clst < 2 || clst >= fs->n_fatent) /* Check range */ + if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ return 1; switch (fs->fs_type) { @@ -599,7 +923,9 @@ FRESULT remove_chain ( { FRESULT res; DWORD nxt; - +#if _USE_ERASE + DWORD scl = clst, ecl = clst, resion[2]; +#endif if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ res = FR_INT_ERR; @@ -617,6 +943,16 @@ FRESULT remove_chain ( fs->free_clust++; fs->fsi_flag = 1; } +#if _USE_ERASE + if (ecl + 1 == nxt) { /* Next cluster is contiguous */ + ecl = nxt; + } else { /* End of contiguous clusters */ + resion[0] = clust2sect(fs, scl); /* Start sector */ + resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ + scl = ecl = nxt; + } +#endif clst = nxt; /* Next cluster */ } } @@ -639,6 +975,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err ) { DWORD cs, ncl, scl; + FRESULT res; if (clst == 0) { /* Create a new chain */ @@ -666,41 +1003,51 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err if (ncl == scl) return 0; /* No free cluster */ } - if (put_fat(fs, ncl, 0x0FFFFFFF)) /* Mark the new cluster "last link" */ - return 0xFFFFFFFF; - if (clst != 0) { /* Link it to the previous one if needed */ - if (put_fat(fs, clst, ncl)) - return 0xFFFFFFFF; + res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ } - - fs->last_clust = ncl; /* Update FSINFO */ - if (fs->free_clust != 0xFFFFFFFF) { - fs->free_clust--; - fs->fsi_flag = 1; + if (res == FR_OK) { + fs->last_clust = ncl; /* Update FSINFO */ + if (fs->free_clust != 0xFFFFFFFF) { + fs->free_clust--; + fs->fsi_flag = 1; + } + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; } - return ncl; /* Return new cluster number */ + return ncl; /* Return new cluster number or error code */ } #endif /* !_FS_READONLY */ - /*-----------------------------------------------------------------------*/ -/* Get sector# from cluster# */ +/* FAT handling - Convert offset into cluster with link map table */ /*-----------------------------------------------------------------------*/ - -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to be converted */ +#if _USE_FASTSEEK +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + DWORD ofs /* File offset to be converted to cluster# */ ) { - clst -= 2; - if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ - return clst * fs->csize + fs->database; -} + DWORD cl, ncl, *tbl; + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (!ncl) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} +#endif /* _USE_FASTSEEK */ @@ -725,14 +1072,14 @@ FRESULT dir_sdi ( if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ clst = dj->fs->dirbase; - if (clst == 0) { /* Static table */ + if (clst == 0) { /* Static table (root-dir in FAT12/16) */ dj->clust = clst; if (idx >= dj->fs->n_rootdir) /* Index is out of range */ return FR_INT_ERR; - dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32); /* Sector# */ + dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ } - else { /* Dynamic table */ - ic = SS(dj->fs) / 32 * dj->fs->csize; /* Entries per cluster */ + else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ + ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */ while (idx >= ic) { /* Follow cluster chain */ clst = get_fat(dj->fs, clst); /* Get next cluster */ if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ @@ -741,10 +1088,10 @@ FRESULT dir_sdi ( idx -= ic; } dj->clust = clst; - dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32); /* Sector# */ + dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ } - dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32; /* Ptr to the entry in the sector */ + dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ return FR_OK; /* Seek succeeded */ } @@ -770,7 +1117,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ return FR_NO_FILE; - if (!(i % (SS(dj->fs) / 32))) { /* Sector changed? */ + if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */ dj->sect++; /* Next sector */ if (dj->clust == 0) { /* Static table */ @@ -778,7 +1125,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an return FR_NO_FILE; } else { /* Dynamic table */ - if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ + if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ if (clst <= 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; @@ -811,7 +1158,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an } dj->index = i; - dj->dir = dj->fs->win + (i % (SS(dj->fs) / 32)) * 32; + dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; return FR_OK; } @@ -833,11 +1180,11 @@ int cmp_lfn ( /* 1:Matched, 0:Not matched */ BYTE *dir /* Pointer to the directory entry containing a part of LFN */ ) { - int i, s; + UINT i, s; WCHAR wc, uc; - i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13; /* Get offset in the LFN buffer */ + i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ s = 0; wc = 1; do { uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ @@ -850,7 +1197,7 @@ int cmp_lfn ( /* 1:Matched, 0:Not matched */ } } while (++s < 13); /* Repeat until all chars in the entry are checked */ - if ((dir[LDIR_Ord] & 0x40) && wc && lfnbuf[i]) /* Last segment matched but different length */ + if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ return 0; return 1; /* The part of LFN matched */ @@ -864,7 +1211,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ BYTE *dir /* Pointer to the directory entry */ ) { - int i, s; + UINT i, s; WCHAR wc, uc; @@ -881,7 +1228,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ } } while (++s < 13); /* Read all character in the entry */ - if (dir[LDIR_Ord] & 0x40) { /* Put terminator if it is the last LFN part */ + if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ lfnbuf[i] = 0; } @@ -899,7 +1246,7 @@ void fit_lfn ( BYTE sum /* SFN sum */ ) { - int i, s; + UINT i, s; WCHAR wc; @@ -915,7 +1262,7 @@ void fit_lfn ( ST_WORD(dir+LfnOfs[s], wc); /* Put it */ if (!wc) wc = 0xFFFF; /* Padding chars following last char */ } while (++s < 13); - if (wc == 0xFFFF || !lfnbuf[i]) ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */ + if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ dir[LDIR_Ord] = ord; /* Set the LFN order */ } @@ -936,7 +1283,7 @@ void gen_numname ( ) { BYTE ns[8], c; - int i, j; + UINT i, j; mem_cpy(dst, src, 11); @@ -945,7 +1292,7 @@ void gen_numname ( do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); } - /* itoa */ + /* itoa (hexdecimal) */ i = 7; do { c = (seq % 16) + '0'; @@ -981,7 +1328,7 @@ BYTE sum_sfn ( ) { BYTE sum = 0; - int n = 11; + UINT n = 11; do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); return sum; @@ -1020,14 +1367,14 @@ FRESULT dir_find ( if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ #if _USE_LFN /* LFN configuration */ a = dir[DIR_Attr] & AM_MASK; - if (c == 0xE5 || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ ord = 0xFF; } else { if (a == AM_LFN) { /* An LFN entry is found */ if (dj->lfn) { - if (c & 0x40) { /* Is it start of LFN sequence? */ + if (c & LLE) { /* Is it start of LFN sequence? */ sum = dir[LDIR_Chksum]; - c &= 0xBF; ord = c; /* LFN start order */ + c &= ~LLE; ord = c; /* LFN start order */ dj->lfn_idx = dj->index; } /* Check validity of the LFN entry and compare it with given name */ @@ -1076,13 +1423,13 @@ FRESULT dir_read ( if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ #if _USE_LFN /* LFN configuration */ a = dir[DIR_Attr] & AM_MASK; - if (c == 0xE5 || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + if (c == DDE || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ ord = 0xFF; } else { if (a == AM_LFN) { /* An LFN entry is found */ - if (c & 0x40) { /* Is it start of LFN sequence? */ + if (c & LLE) { /* Is it start of LFN sequence? */ sum = dir[LDIR_Chksum]; - c &= 0xBF; ord = c; + c &= ~LLE; ord = c; dj->lfn_idx = dj->index; } /* Check LFN validity and capture it */ @@ -1094,7 +1441,7 @@ FRESULT dir_read ( } } #else /* Non LFN configuration */ - if (c != 0xE5 && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ + if (c != DDE && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ break; #endif res = dir_next(dj, 0); /* Next entry */ @@ -1129,7 +1476,8 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many fn = dj->fn; lfn = dj->lfn; mem_cpy(sn, fn, 12); - if (_FS_RPATH && (sn[NS] & NS_DOT)) return FR_INVALID_NAME; /* Cannot create dot entry */ + if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ + return FR_INVALID_NAME; if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ @@ -1158,7 +1506,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; c = *dj->dir; /* Check the entry status */ - if (c == 0xE5 || c == 0) { /* Is it a blank entry? */ + if (c == DDE || c == 0) { /* Is it a blank entry? */ if (n == 0) is = dj->index; /* First index of the contiguous entry */ if (++n == ne) break; /* A contiguous entry that required count is found */ } else { @@ -1189,7 +1537,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; c = *dj->dir; - if (c == 0xE5 || c == 0) break; /* Is it a blank entry? */ + if (c == DDE || c == 0) break; /* Is it a blank entry? */ res = dir_next(dj, 1); /* Next entry with table stretch */ } while (res == FR_OK); } @@ -1199,7 +1547,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many res = move_window(dj->fs, dj->sect); if (res == FR_OK) { dir = dj->dir; - mem_set(dir, 0, 32); /* Clean the entry */ + mem_set(dir, 0, SZ_DIR); /* Clean the entry */ mem_cpy(dir, dj->fn, 11); /* Put SFN */ #if _USE_LFN dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ @@ -1234,7 +1582,7 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ do { res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; - *dj->dir = 0xE5; /* Mark the entry "deleted" */ + *dj->dir = DDE; /* Mark the entry "deleted" */ dj->fs->wflag = 1; if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ res = dir_next(dj, 0); /* Next entry */ @@ -1247,7 +1595,7 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ if (res == FR_OK) { res = move_window(dj->fs, dj->sect); if (res == FR_OK) { - *dj->dir = 0xE5; /* Mark the entry "deleted" */ + *dj->dir = DDE; /* Mark the entry "deleted" */ dj->fs->wflag = 1; } } @@ -1277,13 +1625,13 @@ FRESULT create_name ( #if _USE_LFN /* LFN configuration */ BYTE b, cf; WCHAR w, *lfn; - int i, ni, si, di; + UINT i, ni, si, di; const TCHAR *p; /* Create LFN in Unicode */ - si = di = 0; - p = *path; + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ lfn = dj->lfn; + si = di = 0; for (;;) { w = p[si++]; /* Get a character */ if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ @@ -1291,13 +1639,13 @@ FRESULT create_name ( return FR_INVALID_NAME; #if !_LFN_UNICODE w &= 0xFF; - if (IsDBCS1(w)) { /* If it is a DBC 1st byte */ - b = p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(b)) /* Reject invalid code for DBC */ - return FR_INVALID_NAME; - w = (w << 8) + b; + if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + b = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(b)) + return FR_INVALID_NAME; /* Reject invalid sequence */ + w = (w << 8) + b; /* Create a DBC */ } - w = ff_convert(w, 1); /* Convert OEM to Unicode */ + w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ if (!w) return FR_INVALID_NAME; /* Reject invalid code */ #endif if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ @@ -1307,8 +1655,8 @@ FRESULT create_name ( *path = &p[si]; /* Return pointer to the next segment */ cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ #if _FS_RPATH - if ((di == 1 && lfn[di - 1] == '.') || /* Is this a dot entry? */ - (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { + if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ + (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { lfn[di] = 0; for (i = 0; i < 11; i++) dj->fn[i] = (i < di) ? '.' : ' '; @@ -1317,11 +1665,11 @@ FRESULT create_name ( } #endif while (di) { /* Strip trailing spaces and dots */ - w = lfn[di - 1]; + w = lfn[di-1]; if (w != ' ' && w != '.') break; di--; } - if (!di) return FR_INVALID_NAME; /* Reject null string */ + if (!di) return FR_INVALID_NAME; /* Reject nul string */ lfn[di] = 0; /* LFN is created */ @@ -1359,14 +1707,14 @@ FRESULT create_name ( cf |= NS_LFN; /* Force create LFN entry */ } - if (_DF1S && w >= 0x100) { /* Double byte char */ + if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ if (i >= ni - 1) { cf |= NS_LOSS | NS_LFN; i = ni; continue; } dj->fn[i++] = (BYTE)(w >> 8); } else { /* Single byte char */ - if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ - w = '_'; cf |= NS_LOSS | NS_LFN; /* Lossy conversion */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ } else { if (IsUpper(w)) { /* ASCII large capital */ b |= 2; @@ -1380,7 +1728,7 @@ FRESULT create_name ( dj->fn[i++] = (BYTE)w; } - if (dj->fn[0] == 0xE5) dj->fn[0] = 0x05; /* If the first char collides with deleted mark, replace it with 0x05 */ + if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */ if (ni == 8) b <<= 2; if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ @@ -1397,14 +1745,14 @@ FRESULT create_name ( #else /* Non-LFN configuration */ BYTE b, c, d, *sfn; - int ni, si, i; + UINT ni, si, i; const char *p; /* Create file name in directory form */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ sfn = dj->fn; mem_set(sfn, ' ', 11); si = i = b = 0; ni = 8; - p = *path; #if _FS_RPATH if (p[si] == '.') { /* Is this a dot entry? */ for (;;) { @@ -1426,24 +1774,24 @@ FRESULT create_name ( i = 8; ni = 11; b <<= 2; continue; } - if (c >= 0x80) { /* Extended char */ + if (c >= 0x80) { /* Extended char? */ + b |= 3; /* Eliminate NT flag */ #ifdef _EXCVT - c = excvt[c - 0x80]; /* Convert extend char (SBCS) */ + c = excvt[c-0x80]; /* Upper conversion (SBCS) */ #else - b |= 3; /* Eliminate NT flag if extended char is exist */ #if !_DF1S /* ASCII only cfg */ return FR_INVALID_NAME; #endif #endif } - if (IsDBCS1(c)) { /* DBC 1st byte? */ + if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ d = (BYTE)p[si++]; /* Get 2nd byte */ if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ return FR_INVALID_NAME; sfn[i++] = c; sfn[i++] = d; } else { /* Single byte code */ - if (chk_chr("\"*+,:<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ return FR_INVALID_NAME; if (IsUpper(c)) { /* ASCII large capital? */ b |= 2; @@ -1458,8 +1806,8 @@ FRESULT create_name ( *path = &p[si]; /* Return pointer to the next segment */ c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ - if (!i) return FR_INVALID_NAME; /* Reject null string */ - if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ + if (!i) return FR_INVALID_NAME; /* Reject nul string */ + if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */ if (ni == 8) b <<= 2; if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ @@ -1484,7 +1832,7 @@ void get_fileinfo ( /* No return code */ FILINFO *fno /* Pointer to the file information to be filled */ ) { - int i; + UINT i; BYTE nt, *dir; TCHAR *p, c; @@ -1496,10 +1844,10 @@ void get_fileinfo ( /* No return code */ for (i = 0; i < 8; i++) { /* Copy name body */ c = dir[i]; if (c == ' ') break; - if (c == 0x05) c = (TCHAR)0xE5; + if (c == NDDE) c = (TCHAR)DDE; if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; #if _LFN_UNICODE - if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i + 1])) + if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) c = (c << 8) | dir[++i]; c = ff_convert(c, 1); if (!c) c = '?'; @@ -1513,7 +1861,7 @@ void get_fileinfo ( /* No return code */ if (c == ' ') break; if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; #if _LFN_UNICODE - if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i + 1])) + if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) c = (c << 8) | dir[++i]; c = ff_convert(c, 1); if (!c) c = '?'; @@ -1526,10 +1874,10 @@ void get_fileinfo ( /* No return code */ fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ } - *p = 0; + *p = 0; /* Terminate SFN str by a \0 */ #if _USE_LFN - if (fno->lfname) { + if (fno->lfname && fno->lfsize) { TCHAR *tp = fno->lfname; WCHAR w, *lfn; @@ -1540,14 +1888,14 @@ void get_fileinfo ( /* No return code */ #if !_LFN_UNICODE w = ff_convert(w, 0); /* Unicode -> OEM conversion */ if (!w) { i = 0; break; } /* Could not convert, no LFN */ - if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC */ + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ tp[i++] = (TCHAR)(w >> 8); #endif - if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overrun, no LFN */ + if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ tp[i++] = (TCHAR)w; } } - tp[i] = 0; /* Terminator */ + tp[i] = 0; /* Terminate the LFN str by a \0 */ } #endif } @@ -1582,7 +1930,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ dj->sclust = 0; /* Start from the root dir */ #endif - if ((UINT)*path < ' ') { /* Null path means the start directory itself */ + if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ res = dir_sdi(dj, 0); dj->dir = 0; @@ -1593,7 +1941,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ res = dir_find(dj); /* Find it */ ns = *(dj->fn+NS); if (res != FR_OK) { /* Failed to find the object */ - if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */ + if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ /* Object not found */ if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ dj->sclust = 0; dj->dir = 0; /* It is the root dir */ @@ -1609,7 +1957,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ res = FR_NO_PATH; break; } - dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + dj->sclust = LD_CLUST(dir); } } @@ -1646,7 +1994,7 @@ BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk e /*-----------------------------------------------------------------------*/ -/* Make sure that the file system is valid */ +/* Check if the file system object is valid or not */ /*-----------------------------------------------------------------------*/ static @@ -1665,56 +2013,57 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ FATFS *fs; /* Get logical drive number from the path name */ - vol = p[0] - '0'; /* Is there a drive number? */ - if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ - p += 2; *path = p; /* Return pointer to the path name */ - } else { /* No drive number is given */ + vol = p[0] - '0'; /* Is there a drive number? */ + if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ + p += 2; *path = p; /* Return pointer to the path name */ + } else { /* No drive number is given */ #if _FS_RPATH - vol = Drive; /* Use current drive */ + vol = CurrVol; /* Use current drive */ #else - vol = 0; /* Use drive 0 */ + vol = 0; /* Use drive 0 */ #endif } /* Check if the logical drive is valid or not */ - if (vol >= _DRIVES) /* Is the drive number valid? */ + if (vol >= _VOLUMES) /* Is the drive number valid? */ return FR_INVALID_DRIVE; - *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ - ENTER_FF(fs); /* Lock file system */ + ENTER_FF(fs); /* Lock file system */ - if (fs->fs_type) { /* If the logical drive has been mounted */ + if (fs->fs_type) { /* If the logical drive has been mounted */ stat = disk_status(fs->drv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ #if !_FS_READONLY if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED; #endif - return FR_OK; /* The file system object is valid */ + return FR_OK; /* The file system object is valid */ } } - /* The logical drive must be mounted. Following code attempts to mount the volume (initialize the file system object) */ + /* The logical drive must be mounted. */ + /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ fs->fs_type = 0; /* Clear the file system object */ fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ - if (stat & STA_NOINIT) /* Check if the drive is ready */ - return FR_NOT_READY; -#if _MAX_SS != 512 /* Get disk sector size if needed */ - if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) - return FR_NO_FILESYSTEM; + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ +#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) + return FR_DISK_ERR; #endif #if !_FS_READONLY if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ return FR_WRITE_PROTECTED; #endif - /* Search FAT partition on the drive (Supports only generic partitions, FDISK and SFD) */ + /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */ if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */ /* Check the partition listed in top of the partition table */ - tbl = &fs->win[MBR_Table + LD2PT(vol) * 16]; /* Partition table */ + tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */ if (tbl[4]) { /* Is the partition existing? */ bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ fmt = check_fs(fs, bsect); /* Check the partition */ @@ -1737,10 +2086,10 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ fasize *= b; /* Number of sectors for FAT area */ fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be 1,2,4...128) */ + if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / 32)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); @@ -1749,7 +2098,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / 32); /* RSV+FAT+DIR */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */ if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ @@ -1771,7 +2120,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (FAT size must not be less than FAT sectors */ + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ return FR_NO_FILESYSTEM; #if !_FS_READONLY @@ -1800,8 +2149,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ fs->cdir = 0; /* Current directory (root dir) */ #endif #if _FS_SHARE /* Clear file lock semaphores */ - for (vol = 0; vol < _FS_SHARE; vol++) - fs->flsem[vol].ctr = 0; + clear_lock(fs); #endif return FR_OK; @@ -1854,11 +2202,14 @@ FRESULT f_mount ( FATFS *rfs; - if (vol >= _DRIVES) /* Check if the drive number is valid */ + if (vol >= _VOLUMES) /* Check if the drive number is valid */ return FR_INVALID_DRIVE; rfs = FatFs[vol]; /* Get current fs object */ if (rfs) { +#if _FS_SHARE + clear_lock(rfs); +#endif #if _FS_REENTRANT /* Discard sync object of the current volume */ if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; #endif @@ -1922,32 +2273,31 @@ FRESULT f_open ( if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { DWORD dw, cl; - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ #if _FS_SHARE res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; #else res = dir_register(&dj); #endif - mode |= FA_CREATE_ALWAYS; - dir = dj.dir; /* New entry */ + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ } - else { /* Any object is already existing */ - if (mode & FA_CREATE_NEW) { /* Cannot create new */ - res = FR_EXIST; + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; } else { - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; } } if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ + dw = get_fattime(); /* Created time */ ST_DWORD(dir+DIR_CrtTime, dw); dir[DIR_Attr] = 0; /* Reset attribute */ ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); /* Get start cluster */ - ST_WORD(dir+DIR_FstClusHI, 0); /* cluster = 0 */ - ST_WORD(dir+DIR_FstClusLO, 0); + cl = LD_CLUST(dir); /* Get start cluster */ + ST_CLUST(dir, 0); /* cluster = 0 */ dj.fs->wflag = 1; if (cl) { /* Remove the cluster chain if exist */ dw = dj.fs->winsect; @@ -1970,8 +2320,8 @@ FRESULT f_open ( } } if (res == FR_OK) { - if (mode & (FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) - mode |= FA__WRITTEN; /* Set file changed flag */ + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ fp->dir_ptr = dir; #if _FS_SHARE @@ -1994,13 +2344,12 @@ FRESULT f_open ( if (res == FR_OK) { fp->flag = mode; /* File access mode */ - fp->org_clust = /* File start cluster */ - ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + fp->sclust = LD_CLUST(dir); /* File start cluster */ fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ fp->fptr = 0; /* File pointer */ fp->dsect = 0; #if _USE_FASTSEEK - fp->cltbl = 0; /* No cluster link map table */ + fp->cltbl = 0; /* Normal seek mode */ #endif fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ } @@ -2030,36 +2379,44 @@ FRESULT f_read ( *br = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp->fs, fp->id); /* Check validity */ if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ + if (fp->flag & FA__ERROR) /* Aborted file? */ LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ + if (!(fp->flag & FA_READ)) /* Check access mode */ LEAVE_FF(fp->fs, FR_DENIED); remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - for ( ; btr; /* Repeat until all data transferred */ + for ( ; btr; /* Repeat until all data read */ rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_fat(fp->fs, fp->curr_clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ + } + if (clst < 2) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ + fp->clust = clst; /* Update current cluster */ } - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; - cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ cc = fp->fs->csize - csect; if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); -#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if _FS_TINY 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)); @@ -2068,19 +2425,19 @@ FRESULT f_read ( mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); #endif #endif - rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ continue; } #if !_FS_TINY + if (fp->dsect != sect) { /* Load data sector if not in cache */ #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } #endif - if (fp->dsect != sect) { /* Fill sector buffer with file data */ - if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) + if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ ABORT(fp->fs, FR_DISK_ERR); } #endif @@ -2089,7 +2446,7 @@ FRESULT f_read ( rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; #if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ ABORT(fp->fs, FR_DISK_ERR); mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ #else @@ -2124,71 +2481,76 @@ FRESULT f_write ( *bw = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp->fs, fp->id); /* Check validity */ if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ + if (fp->flag & FA__ERROR) /* Aborted file? */ LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ + if (!(fp->flag & FA_WRITE)) /* Check access mode */ LEAVE_FF(fp->fs, FR_DENIED); - if (fp->fsize + btw < fp->fsize) btw = 0; /* File size cannot reach 4GB */ + if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */ - for ( ; btw; /* Repeat until all data transferred */ + for ( ; btw; /* Repeat until all data written */ wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->org_clust; /* Follow from the origin */ - if (clst == 0) /* When there is no cluster chain, */ - fp->org_clust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ - } else { /* Middle or end of the file */ - clst = create_chain(fp->fs, fp->curr_clust); /* Follow or stretch cluster chain */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + if (clst == 0) /* When no cluster is allocated, */ + fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ } - if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ if (clst == 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ + fp->clust = clst; /* Update current cluster */ } #if _FS_TINY - if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write back data buffer prior to following direct transfer */ + if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write-back sector cache */ ABORT(fp->fs, FR_DISK_ERR); #else - if (fp->flag & FA__DIRTY) { /* Write back data buffer prior to following direct transfer */ + if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); fp->flag &= ~FA__DIRTY; } #endif - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; - cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ cc = fp->fs->csize - csect; if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); #if _FS_TINY - if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ + if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); fp->fs->wflag = 0; } #else - if (fp->dsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ + if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); fp->flag &= ~FA__DIRTY; } #endif - wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ continue; } #if _FS_TINY - if (fp->fptr >= fp->fsize) { /* Avoid silly buffer filling at growing edge */ + if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR); fp->fs->winsect = sect; } #else - if (fp->dsect != sect) { /* Fill sector buffer with file data */ + if (fp->dsect != sect) { /* Fill sector cache with file data */ if (fp->fptr < fp->fsize && disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); @@ -2196,10 +2558,10 @@ FRESULT f_write ( #endif fp->dsect = sect; } - wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Put partial sector into file I/O buffer */ + wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ if (wcnt > btw) wcnt = btw; #if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ ABORT(fp->fs, FR_DISK_ERR); mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ fp->fs->wflag = 1; @@ -2210,7 +2572,7 @@ FRESULT f_write ( } if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ - fp->flag |= FA__WRITTEN; /* Set file changed flag */ + fp->flag |= FA__WRITTEN; /* Set file change flag */ LEAVE_FF(fp->fs, FR_OK); } @@ -2247,8 +2609,7 @@ FRESULT f_sync ( dir = fp->dir_ptr; dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - ST_WORD(dir+DIR_FstClusLO, fp->org_clust); /* Update start cluster */ - ST_WORD(dir+DIR_FstClusHI, fp->org_clust >> 16); + ST_CLUST(dir, fp->sclust); /* Update start cluster */ tim = get_fattime(); /* Update updated time */ ST_DWORD(dir+DIR_WrtTime, tim); fp->flag &= ~FA__WRITTEN; @@ -2289,11 +2650,11 @@ FRESULT f_close ( #if _FS_REENTRANT res = validate(fp->fs, fp->id); if (res == FR_OK) { - res = dec_lock(fp->fs, fp->lockid); + res = dec_lock(fp->lockid); unlock_fs(fp->fs, FR_OK); } #else - res = dec_lock(fp->fs, fp->lockid); + res = dec_lock(fp->lockid); #endif } #endif @@ -2306,32 +2667,30 @@ FRESULT f_close ( /*-----------------------------------------------------------------------*/ -/* Change Current Drive/Directory */ +/* Current Drive/Directory Handlings */ /*-----------------------------------------------------------------------*/ -#if _FS_RPATH +#if _FS_RPATH >= 1 FRESULT f_chdrive ( BYTE drv /* Drive number */ ) { - if (drv >= _DRIVES) return FR_INVALID_DRIVE; + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; - Drive = drv; + CurrVol = drv; return FR_OK; } - FRESULT f_chdir ( const TCHAR *path /* Pointer to the directory path */ ) { FRESULT res; DIR dj; - BYTE *dir; DEF_NAMEBUF; @@ -2341,12 +2700,11 @@ FRESULT f_chdir ( res = follow_path(&dj, path); /* Follow the path */ FREE_BUF(); if (res == FR_OK) { /* Follow completed */ - dir = dj.dir; /* Pointer to the entry */ - if (!dir) { + if (!dj.dir) { dj.fs->cdir = dj.sclust; /* Start directory itself */ } else { - if (dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ + dj.fs->cdir = LD_CLUST(dj.dir); else res = FR_NO_PATH; /* Reached but a file */ } @@ -2357,7 +2715,78 @@ FRESULT f_chdir ( LEAVE_FF(dj.fs, res); } -#endif + +#if _FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR *path, /* Pointer to the directory path */ + UINT sz_path /* Size of path */ +) +{ + FRESULT res; + DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; + + + *path = 0; + res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */ + if (res == FR_OK) { + INIT_BUF(dj); + i = sz_path; /* Bottom of buffer (dir stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ + while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ + res = dir_sdi(&dj, 1); /* Get parent dir */ + if (res != FR_OK) break; + res = dir_read(&dj); + if (res != FR_OK) break; + dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child dir */ + res = dir_read(&dj); + if (res != FR_OK) break; + if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; +#if _USE_LFN + fno.lfname = path; + fno.lfsize = i; +#endif + get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ + tp = fno.fname; + if (_USE_LFN && *path) tp = path; + for (n = 0; tp[n]; n++) ; + if (i < n + 3) { + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) path[--i] = tp[--n]; + path[--i] = '/'; + } + tp = path; + if (res == FR_OK) { + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; + if (i == sz_path) { /* Root-dir */ + *tp++ = '/'; + } else { /* Sub-dir */ + do /* Add stacked path str */ + *tp++ = path[i++]; + while (i < sz_path); + } + } + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} +#endif /* _FS_RPATH >= 2 */ +#endif /* _FS_RPATH >= 1 */ @@ -2381,58 +2810,52 @@ FRESULT f_lseek ( #if _USE_FASTSEEK if (fp->cltbl) { /* Fast seek */ - DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl; - BYTE csc; + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; - tlen = *tbl++; - if (ofs == CREATE_LINKMAP) { /* Create link map table */ - cl = fp->org_clust; + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->sclust; /* Top of the chain */ if (cl) { do { - if (tlen < 4) { /* Not enough table items */ - res = FR_NOT_ENOUGH_CORE; break; - } - tcl = cl; ncl = 0; - do { /* Get a fragment and store the top and length */ + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { pcl = cl; ncl++; cl = get_fat(fp->fs, cl); if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); } while (cl == pcl + 1); - *tbl++ = ncl; *tbl++ = tcl; - tlen -= 2; - } while (cl < fp->fs->n_fatent); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ } - *tbl = 0; /* Terminate table */ + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) + *tbl = 0; /* Terminate table */ + else + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ } else { /* Fast seek */ if (ofs > fp->fsize) /* Clip offset at the file size */ ofs = fp->fsize; fp->fptr = ofs; /* Set file pointer */ if (ofs) { - dsc = (ofs - 1) / SS(fp->fs); - cl = dsc / fp->fs->csize; - for (;;) { - ncl = *tbl++; - if (!ncl) ABORT(fp->fs, FR_INT_ERR); - if (cl < ncl) break; - cl -= ncl; tbl++; - } - fp->curr_clust = cl + *tbl; - csc = (BYTE)(dsc & (fp->fs->csize - 1)); - dsc = clust2sect(fp->fs, fp->curr_clust); + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clust2sect(fp->fs, fp->clust); if (!dsc) ABORT(fp->fs, FR_INT_ERR); - dsc += csc; - if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { + dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); + if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); fp->flag &= ~FA__DIRTY; } #endif - if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) + if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ ABORT(fp->fs, FR_DISK_ERR); #endif fp->dsect = dsc; @@ -2460,18 +2883,18 @@ FRESULT f_lseek ( (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ ofs -= fp->fptr; - clst = fp->curr_clust; + clst = fp->clust; } else { /* When seek to back cluster, */ - clst = fp->org_clust; /* start from the first cluster */ + clst = fp->sclust; /* start from the first cluster */ #if !_FS_READONLY if (clst == 0) { /* If no cluster chain, create a new chain */ 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->org_clust = clst; + fp->sclust = clst; } #endif - fp->curr_clust = clst; + fp->clust = clst; } if (clst != 0) { while (ofs > bcs) { /* Cluster following loop */ @@ -2486,7 +2909,7 @@ FRESULT f_lseek ( clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); - fp->curr_clust = clst; + fp->clust = clst; fp->fptr += bcs; ofs -= bcs; } @@ -2498,22 +2921,22 @@ FRESULT f_lseek ( } } } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); fp->flag &= ~FA__DIRTY; } #endif - if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) + if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ ABORT(fp->fs, FR_DISK_ERR); #endif fp->dsect = nsect; } #if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set changed flag if the file size is extended */ + if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ fp->fsize = fp->fptr; fp->flag |= FA__WRITTEN; } @@ -2527,7 +2950,7 @@ FRESULT f_lseek ( #if _FS_MINIMIZE <= 1 /*-----------------------------------------------------------------------*/ -/* Create a Directory Object */ +/* Create a Directroy Object */ /*-----------------------------------------------------------------------*/ FRESULT f_opendir ( @@ -2536,7 +2959,6 @@ FRESULT f_opendir ( ) { FRESULT res; - BYTE *dir; DEF_NAMEBUF; @@ -2546,10 +2968,9 @@ FRESULT f_opendir ( res = follow_path(dj, path); /* Follow the path to the directory */ FREE_BUF(); if (res == FR_OK) { /* Follow completed */ - dir = dj->dir; - if (dir) { /* It is not the current dir */ - if (dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + if (dj->dir) { /* It is not the root dir */ + if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ + dj->sclust = LD_CLUST(dj->dir); } else { /* The object is not a directory */ res = FR_NO_PATH; } @@ -2569,7 +2990,7 @@ FRESULT f_opendir ( /*-----------------------------------------------------------------------*/ -/* Read Directory Entry in Sequence */ +/* Read Directory Entry in Sequense */ /*-----------------------------------------------------------------------*/ FRESULT f_readdir ( @@ -2584,11 +3005,11 @@ FRESULT f_readdir ( res = validate(dj->fs, dj->id); /* Check validity of the object */ if (res == FR_OK) { if (!fno) { - res = dir_sdi(dj, 0); + res = dir_sdi(dj, 0); /* Rewind the directory object */ } else { INIT_BUF(*dj); - res = dir_read(dj); - if (res == FR_NO_FILE) { + res = dir_read(dj); /* Read an directory item */ + if (res == FR_NO_FILE) { /* Reached end of dir */ dj->sect = 0; res = FR_OK; } @@ -2734,15 +3155,15 @@ FRESULT f_truncate ( fp->fsize = fp->fptr; /* Set file size to current R/W point */ fp->flag |= FA__WRITTEN; if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->org_clust); - fp->org_clust = 0; + res = remove_chain(fp->fs, fp->sclust); + fp->sclust = 0; } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->curr_clust); + ncl = get_fat(fp->fs, fp->clust); res = FR_OK; if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; if (ncl == 1) res = FR_INT_ERR; if (res == FR_OK && ncl < fp->fs->n_fatent) { - res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF); + res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); if (res == FR_OK) res = remove_chain(fp->fs, ncl); } } @@ -2788,7 +3209,7 @@ FRESULT f_unlink ( if (dir[DIR_Attr] & AM_RDO) res = FR_DENIED; /* Cannot remove R/O object */ } - dclst = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + dclst = LD_CLUST(dir); if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ if (dclst < 2) { res = FR_INT_ERR; @@ -2862,14 +3283,12 @@ FRESULT f_mkdir ( dir[DIR_Name] = '.'; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir+DIR_WrtTime, tim); - ST_WORD(dir+DIR_FstClusLO, dcl); - ST_WORD(dir+DIR_FstClusHI, dcl >> 16); - mem_cpy(dir+32, dir, 32); /* Create ".." entry */ + ST_CLUST(dir, dcl); + mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ dir[33] = '.'; pcl = dj.sclust; if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) pcl = 0; - ST_WORD(dir+32+DIR_FstClusLO, pcl); - ST_WORD(dir+32+DIR_FstClusHI, pcl >> 16); + ST_CLUST(dir+SZ_DIR, pcl); for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ dj.fs->winsect = dsc++; dj.fs->wflag = 1; @@ -2878,15 +3297,14 @@ FRESULT f_mkdir ( mem_set(dir, 0, SS(dj.fs)); } } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directory */ + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ if (res != FR_OK) { - remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ + remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ } else { dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ - ST_WORD(dir+DIR_FstClusLO, dcl); /* Table start cluster */ - ST_WORD(dir+DIR_FstClusHI, dcl >> 16); + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ + ST_CLUST(dir, dcl); /* Table start cluster */ dj.fs->wflag = 1; res = sync(dj.fs); } @@ -2943,7 +3361,7 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ -/* Change Time-stamp */ +/* Change Timestamp */ /*-----------------------------------------------------------------------*/ FRESULT f_utime ( @@ -3016,8 +3434,8 @@ FRESULT f_rename ( mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ res = follow_path(&djn, path_new); - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ + if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ + if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ /* Start critical section that any interruption or error can cause cross-link */ res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { @@ -3026,16 +3444,15 @@ FRESULT f_rename ( dir[DIR_Attr] = buf[0] | AM_ARC; djo.fs->wflag = 1; if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djn.fs, (DWORD)LD_WORD(dir+DIR_FstClusHI) | LD_WORD(dir+DIR_FstClusLO)); + dw = clust2sect(djn.fs, LD_CLUST(dir)); if (!dw) { res = FR_INT_ERR; } else { res = move_window(djn.fs, dw); - dir = djn.fs->win+32; /* .. entry */ + dir = djn.fs->win+SZ_DIR; /* .. entry */ if (res == FR_OK && dir[1] == '.') { dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; - ST_WORD(dir+DIR_FstClusLO, dw); - ST_WORD(dir+DIR_FstClusHI, dw >> 16); + ST_CLUST(dir, dw); djn.fs->wflag = 1; } } @@ -3098,13 +3515,13 @@ FRESULT f_forward ( if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ if (!csect) { /* On the cluster boundary? */ clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_fat(fp->fs, fp->curr_clust); + fp->sclust : get_fat(fp->fs, fp->clust); if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ + fp->clust = clst; /* Update current cluster */ } } - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current data sector */ + sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; if (move_window(fp->fs, sect)) /* Move sector window */ @@ -3126,8 +3543,8 @@ FRESULT f_forward ( /*-----------------------------------------------------------------------*/ /* Create File System on the Drive */ /*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Multiple of 32 */ -#define N_FATS 1 /* 1 or 2 */ +#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */ +#define N_FATS 1 /* Number of FAT copies (1 or 2) */ FRESULT f_mkfs ( @@ -3139,16 +3556,16 @@ FRESULT f_mkfs ( static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; BYTE fmt, md, *tbl; - DWORD n_clst, vs, n; - UINT as, i; - DWORD b_vol, b_fat, b_dir, b_data; /* Area offset (LBA) */ - DWORD n_vol, n_rsv, n_fat, n_dir; /* Area size */ + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ FATFS *fs; DSTATUS stat; /* Check mounted drive and clear work area */ - if (drv >= _DRIVES) return FR_INVALID_DRIVE; + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; fs = FatFs[drv]; if (!fs) return FR_NOT_ENABLED; fs->fs_type = 0; @@ -3159,25 +3576,24 @@ FRESULT f_mkfs ( if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; #endif if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) return FR_DISK_ERR; - b_vol = (sfd == 1) ? 0 : 63; /* Volume start sector */ + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ n_vol -= b_vol; - if (au & (au - 1)) au = 0; /* Check validity of the allocation unit size */ - if (!au) { /* AU auto selection */ + if (au & (au - 1)) au = 0; /* Check validity of the AU size */ + if (!au) { /* AU auto selection */ vs = n_vol / (2000 / (SS(fs) / 512)); for (i = 0; vs < vst[i]; i++) ; au = cst[i]; } - if (_MAX_SS != 512 && au < SS(fs)) au = SS(fs); au /= SS(fs); /* Number of sectors per cluster */ if (au == 0) au = 1; if (au > 128) au = 128; - /* Pre-compute number of clusters and FAT sub-type */ + /* Pre-compute number of clusters and FAT syb-type */ n_clst = n_vol / au; fmt = FS_FAT12; if (n_clst >= MIN_FAT16) fmt = FS_FAT16; @@ -3192,7 +3608,7 @@ FRESULT f_mkfs ( n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; n_fat = (n_fat + SS(fs) - 1) / SS(fs); n_rsv = 1; - n_dir = N_ROOTDIR * 32UL / SS(fs); + n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); } b_fat = b_vol + n_rsv; /* FAT area start sector */ b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ @@ -3200,134 +3616,142 @@ FRESULT f_mkfs ( if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */ /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK) return FR_DISK_ERR; - if (!n || n > 32768) return FR_MKFS_ABORTED; - n = (b_data + n - 1) & ~(n - 1); /* Next nearest boundary from current data start */ + if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ n = (n - b_data) / N_FATS; - if (fmt == FS_FAT32) { /* FAT32: Move FAT start */ + if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ n_rsv += n; b_fat += n; } else { /* FAT12/16: Expand FAT size */ n_fat += n; } - /* b_dir and b_data are no longer used below */ - /* Determine number of cluster and final check of validity of the FAT sub-type */ + /* Determine number of clusters and final check of validity of the FAT sub-type */ n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) return FR_MKFS_ABORTED; /* Create partition table if required */ - if (sfd == 1) { + if (sfd) { /* No patition table (SFD) */ md = 0xF0; - } else { + } else { /* With patition table (FDISK) */ DWORD n_disk = b_vol + n_vol; mem_set(fs->win, 0, SS(fs)); tbl = fs->win+MBR_Table; - ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ + ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */ n_disk = n_disk / 63 / 255; tbl[7] = (BYTE)n_disk; tbl[6] = (BYTE)((n_disk >> 2) | 63); } else { - ST_WORD(&tbl[6], 0xFFFF); + ST_WORD(&tbl[6], 0xFFFF); /* CHS saturated */ } tbl[5] = 254; - if (fmt != FS_FAT32) /* System ID */ + if (fmt != FS_FAT32) /* System ID */ tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06; else tbl[4] = 0x0c; - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(tbl+64, 0xAA55); /* Signature */ - if (disk_write(drv, fs->win, 0, 1) != RES_OK) + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(drv, fs->win, 0, 1) != RES_OK) /* Put the MBR into first physical sector */ return FR_DISK_ERR; md = 0xF8; } - /* Create VBR */ - tbl = fs->win; /* Clear buffer */ + /* Create volume boot record */ + tbl = fs->win; /* Clear sector */ mem_set(tbl, 0, SS(fs)); - ST_DWORD(tbl+BS_jmpBoot, 0x90FEEB); /* Boot code (jmp $, nop) */ - as = SS(fs); /* Sector size */ - ST_WORD(tbl+BPB_BytsPerSec, as); - tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ - ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ - tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - as = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ - ST_WORD(tbl+BPB_RootEntCnt, as); - if (n_vol < 0x10000) { /* Number of total sectors */ + mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ + i = SS(fs); /* Sector size */ + ST_WORD(tbl+BPB_BytsPerSec, i); + tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ + ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD(tbl+BPB_RootEntCnt, i); + if (n_vol < 0x10000) { /* Number of total sectors */ ST_WORD(tbl+BPB_TotSec16, n_vol); } else { ST_DWORD(tbl+BPB_TotSec32, n_vol); } - tbl[BPB_Media] = md; /* Media descriptor */ - ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ - ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ - n = get_fattime(); /* Use current time as VSN */ + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ + ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ + ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ if (fmt == FS_FAT32) { - ST_DWORD(tbl+BS_VolID32, n); /* VSN */ - ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ - ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ - ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ - ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ - tbl[BS_DrvNum32] = 0x80; /* Drive number */ - tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab32, "NO NAME FAT32 ", 19); /* Volume label, FAT signature */ + ST_DWORD(tbl+BS_VolID32, n); /* VSN */ + ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ + ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ + ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ + ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ } else { - ST_DWORD(tbl+BS_VolID, n); /* VSN */ - ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab, "NO NAME FAT ", 19); /* Volume label, FAT signature */ - } - ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Original (VBR) */ + ST_DWORD(tbl+BS_VolID, n); /* VSN */ + ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ + if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Write VBR */ return FR_DISK_ERR; - if (fmt == FS_FAT32) /* Backup (VBR+6) */ + if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ disk_write(drv, tbl, b_vol + 6, 1); /* Initialize FAT area */ - for (i = 0; i < N_FATS; i++) { + wsect = b_fat; + for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ n = md; /* Media descriptor byte */ if (fmt != FS_FAT32) { n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ } else { - n |= 0x0FFFFF00; + n |= 0xFFFFFF00; ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl+4, 0x0FFFFFFF); + ST_DWORD(tbl+4, 0xFFFFFFFF); ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ } - if (disk_write(drv, tbl, b_fat++, 1) != RES_OK) + if (disk_write(drv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ - for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector write */ - if (disk_write(drv, tbl, b_fat++, 1) != RES_OK) + mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ + for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ + if (disk_write(drv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; } } /* Initialize root directory */ - n = (fmt == FS_FAT32) ? as : n_dir; - while (n--) { - if (disk_write(drv, tbl, b_fat++, 1) != RES_OK) + i = (fmt == FS_FAT32) ? au : n_dir; + do { + if (disk_write(drv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; + } while (--i); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; + disk_ioctl(drv, CTRL_ERASE_SECTOR, eb); } +#endif - /* Create FSInfo record if needed */ + /* Create FSInfo if needed */ if (fmt == FS_FAT32) { - ST_WORD(tbl+BS_55AA, 0xAA55); ST_DWORD(tbl+FSI_LeadSig, 0x41615252); ST_DWORD(tbl+FSI_StrucSig, 0x61417272); - ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); - ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF); - disk_write(drv, tbl, b_vol + 1, 1); /* Original (VBR+1) */ - disk_write(drv, tbl, b_vol + 7, 1); /* Backup (VBR+7) */ + ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ + ST_WORD(tbl+BS_55AA, 0xAA55); + disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ } return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR; @@ -3361,18 +3785,18 @@ TCHAR* f_gets ( #if _LFN_UNICODE /* Read a character in UTF-8 encoding */ if (c >= 0x80) { if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequence */ + if (c < 0xE0) { /* Two-byte sequense */ f_read(fil, s, 1, &rc); if (rc != 1) break; c = ((c & 0x1F) << 6) | (s[0] & 0x3F); if (c < 0x80) c = '?'; } else { - if (c < 0xF0) { /* Three-byte sequence */ + if (c < 0xF0) { /* Three-byte sequense */ f_read(fil, s, 2, &rc); if (rc != 2) break; c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequence */ + } else { /* Reject four-byte sequense */ c = '?'; } } @@ -3467,9 +3891,9 @@ int f_printf ( { va_list arp; BYTE f, r; - UINT i, w; - ULONG val; - TCHAR c, d, s[16]; + UINT i, j, w; + ULONG v; + TCHAR c, d, s[16], *p; int res, cc; @@ -3487,20 +3911,31 @@ int f_printf ( c = *str++; if (c == '0') { /* Flag: '0' padding */ f = 1; c = *str++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *str++; + } } while (IsDigit(c)) { /* Precision */ w = w * 10 + c - '0'; c = *str++; } if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 2; c = *str++; + f |= 4; c = *str++; } if (!c) break; d = c; if (IsLower(d)) d -= 0x20; switch (d) { /* Type is... */ case 'S' : /* String */ - cc = f_puts(va_arg(arp, TCHAR*), fil); continue; + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + res = 0; + while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil)); + res += (cc = f_puts(p, fil)); + while (j++ < w) res += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = res; + continue; case 'C' : /* Character */ cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; case 'B' : /* Binary */ @@ -3510,39 +3945,31 @@ int f_printf ( case 'D' : /* Signed decimal */ case 'U' : /* Unsigned decimal */ r = 10; break; - case 'X' : /* Hexadecimal */ + case 'X' : /* Hexdecimal */ r = 16; break; - default: /* Unknown */ + default: /* Unknown type (passthrough) */ cc = f_putc(c, fil); continue; } - /* Get an argument */ - val = (f & 2) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); - if (d == 'D' && (val & 0x80000000)) { - val = 0 - val; - f |= 4; + /* Get an argument and put it in numeral */ + v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; } - /* Put it in numeral string */ i = 0; do { - d = (TCHAR)(val % r); val /= r; - if (d > 9) { - d += 7; - if (c == 'x') d += 0x20; - } + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; - } while (val && i < sizeof(s) / sizeof(s[0])); - if (f & 4) s[i++] = '-'; - cc = 0; - while (i < w-- && cc != EOF) { - cc = f_putc((TCHAR)((f & 1) ? '0' : ' '), fil); - res++; - } - do { - cc = f_putc(s[--i], fil); - res++; - } while (i && cc != EOF); - if (cc != EOF) cc = 0; + } while (v && i < sizeof(s) / sizeof(s[0])); + if (f & 8) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + res = 0; + while (!(f & 2) && j++ < w) res += (cc = f_putc(d, fil)); + do res += (cc = f_putc(s[--i], fil)); while(i); + while (j++ < w) res += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = res; } va_end(arp); @@ -3551,4 +3978,3 @@ int f_printf ( #endif /* !_FS_READONLY */ #endif /* _USE_STRFUNC */ - diff --git a/Projects/Webserver/Lib/FATFs/ff.h b/Projects/Webserver/Lib/FATFs/ff.h index c5a6a0b5e..a3aad840a 100644 --- a/Projects/Webserver/Lib/FATFs/ff.h +++ b/Projects/Webserver/Lib/FATFs/ff.h @@ -1,11 +1,11 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.08 (C)ChaN, 2010 +/ FatFs - FAT file system module include file R0.08b (C)ChaN, 2011 /----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. +/ developments under license policy of following trems. / -/ Copyright (C) 2010, ChaN, all right reserved. +/ Copyright (C) 2011, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -15,7 +15,7 @@ /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS 8085 /* Revision ID */ +#define _FATFS 8237 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -29,215 +29,21 @@ extern "C" { #endif -/* DBCS code ranges and SBCS extend char conversion table */ - -#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ -#define _DF1S 0x81 /* DBC 1st byte range 1 start */ -#define _DF1E 0x9F /* DBC 1st byte range 1 end */ -#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ -#define _DF2E 0xFC /* DBC 1st byte range 2 end */ -#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ -#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ -#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ -#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ - -#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0x80 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 949 /* Korean */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x41 -#define _DS1E 0x5A -#define _DS2S 0x61 -#define _DS2E 0x7A -#define _DS3S 0x81 -#define _DS3E 0xFE - -#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0xA1 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 437 /* U.S. (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 720 /* Arabic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 737 /* Greek (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 775 /* Baltic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} - -#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 857 /* Turkish (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 866 /* Russian (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} - -#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1253 /* Greek (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ - 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} - -#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} - -#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ -#define _DF1S 0 - -#else -#error Unknown code page - -#endif - - -/* Definitions corresponds to volume management */ +/* Definitions of volume management */ #if _MULTI_PARTITION /* Multiple partition configuration */ -#define LD2PD(drv) (Drives[drv].pd) /* Get physical drive# */ -#define LD2PT(drv) (Drives[drv].pt) /* Get partition# */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ typedef struct { BYTE pd; /* Physical drive# */ BYTE pt; /* Partition # (0-3) */ } PARTITION; -extern const PARTITION Drives[]; /* Logical drive# to physical location conversion table */ +extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ #else /* Single partition configuration */ -#define LD2PD(drv) (drv) /* Physical drive# is equal to the logical drive# */ -#define LD2PT(drv) 0 /* Always mounts the 1st partition */ +#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition */ #endif @@ -266,21 +72,6 @@ typedef char TCHAR; -/* Definitions corresponds to file sharing feature */ - -#if _FS_SHARE -#if _FS_READONLY -#error _FS_SHARE must be 0 on R/O cfg. -#endif -typedef struct { - DWORD clu; /* File ID 1, directory */ - WORD idx; /* File ID 2, index in the directory */ - WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:in write open */ -} FILESEM; -#endif - - - /* File system object structure (FATFS) */ typedef struct { @@ -313,9 +104,6 @@ typedef struct { DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ -#if _FS_SHARE - FILESEM flsem[_FS_SHARE]; /* File lock semaphores */ -#endif } FATFS; @@ -327,20 +115,20 @@ typedef struct { WORD id; /* Owner file system mount ID */ BYTE flag; /* File status flags */ BYTE pad1; - DWORD fptr; /* File read/write pointer */ + DWORD fptr; /* File read/write pointer (0 on file open) */ DWORD fsize; /* File size */ - DWORD org_clust; /* File start cluster (0 when fsize==0) */ - DWORD curr_clust; /* Current cluster */ + DWORD sclust; /* File start cluster (0 when fsize==0) */ + DWORD clust; /* Current cluster */ DWORD dsect; /* Current data sector */ #if !_FS_READONLY DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Pointer to the directory entry in the window */ + BYTE* dir_ptr; /* Ponter to the directory entry in the window */ #endif #if _USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table */ + DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ #endif #if _FS_SHARE - UINT lockid; /* File lock ID */ + UINT lockid; /* File lock ID (index of file semaphore table) */ #endif #if !_FS_TINY BYTE buf[_MAX_SS]; /* File data read/write buffer */ @@ -378,7 +166,7 @@ typedef struct { TCHAR fname[13]; /* Short file name (8.3 format) */ #if _USE_LFN TCHAR* lfname; /* Pointer to the LFN buffer */ - int lfsize; /* Size of LFN buffer [chrs] */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ #endif } FILINFO; @@ -388,14 +176,14 @@ typedef struct { typedef enum { FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Acces denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ @@ -403,7 +191,7 @@ typedef enum { FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ } FRESULT; @@ -421,38 +209,34 @@ FRESULT f_close (FIL*); /* Close an open file object */ FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */ FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ -#if !_FS_READONLY FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ FRESULT f_truncate (FIL*); /* Truncate file */ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ -FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change time-stamp of the file/dir */ +FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ +FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ -#endif -#if _USE_FORWARD FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ -#endif -#if _USE_MKFS FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ -#endif -#if _FS_RPATH -FRESULT f_chdir (const TCHAR*); /* Change current directory */ FRESULT f_chdrive (BYTE); /* Change current drive */ -#endif -#if _USE_STRFUNC +FRESULT f_chdir (const TCHAR*); /* Change current directory */ +FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ int f_putc (TCHAR, FIL*); /* Put a character to the file */ int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ -#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) -#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) + #ifndef EOF #define EOF (-1) #endif -#endif + +#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) +#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->fsize) + @@ -477,9 +261,9 @@ void ff_memfree (void*); /* Free memory block */ /* Sync functions */ #if _FS_REENTRANT int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ -int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ int ff_req_grant (_SYNC_t); /* Lock sync object */ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ +int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ #endif @@ -528,68 +312,6 @@ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ #define CREATE_LINKMAP 0xFFFFFFFF -/* FatFs refers the members in the FAT structures with byte offset instead of -/ structure member because there are incompatibility of the packing option -/ between various compilers. */ - -#define BS_jmpBoot 0 -#define BS_OEMName 3 -#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_Media 21 -#define BPB_FATSz16 22 -#define BPB_SecPerTrk 24 -#define BPB_NumHeads 26 -#define BPB_HiddSec 28 -#define BPB_TotSec32 32 -#define BS_55AA 510 - -#define BS_DrvNum 36 -#define BS_BootSig 38 -#define BS_VolID 39 -#define BS_VolLab 43 -#define BS_FilSysType 54 - -#define BPB_FATSz32 36 -#define BPB_ExtFlags 40 -#define BPB_FSVer 42 -#define BPB_RootClus 44 -#define BPB_FSInfo 48 -#define BPB_BkBootSec 50 -#define BS_DrvNum32 64 -#define BS_BootSig32 66 -#define BS_VolID32 67 -#define BS_VolLab32 71 -#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 DIR_Name 0 -#define DIR_Attr 11 -#define DIR_NTres 12 -#define DIR_CrtTime 14 -#define DIR_CrtDate 16 -#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 - - /*--------------------------------*/ /* Multi-byte word access macros */ @@ -600,10 +322,10 @@ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ #define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) #define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) #else /* Use byte-by-byte access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) +#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) #endif #ifdef __cplusplus @@ -611,4 +333,3 @@ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ #endif #endif /* _FATFS */ - diff --git a/Projects/Webserver/Lib/FATFs/ffconf.h b/Projects/Webserver/Lib/FATFs/ffconf.h index 491a97b1e..37ea9e4a7 100644 --- a/Projects/Webserver/Lib/FATFs/ffconf.h +++ b/Projects/Webserver/Lib/FATFs/ffconf.h @@ -1,5 +1,5 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module configuration file R0.08 (C)ChaN, 2010 +/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011 /----------------------------------------------------------------------------/ / / CAUTION! Do not forget to make clean the project after any changes to @@ -7,7 +7,7 @@ / /----------------------------------------------------------------------------*/ #ifndef _FFCONF -#define _FFCONF 8085 /* Revision ID */ +#define _FFCONF 8237 /* Revision ID */ /*---------------------------------------------------------------------------/ @@ -26,14 +26,14 @@ / f_truncate and useless f_getfree. */ -#define _FS_MINIMIZE 2 /* 0, 1, 2 or 3 */ +#define _FS_MINIMIZE 2 /* 0 to 3 */ /* The _FS_MINIMIZE option defines minimization level to remove some functions. / / 0: Full function. / 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename / are removed. -/ 2: f_opendir and f_readdir are removed in addition to level 1. -/ 3: f_lseek is removed in addition to level 2. */ +/ 2: f_opendir and f_readdir are removed in addition to 1. +/ 3: f_lseek is removed in addition to 2. */ #define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ @@ -94,12 +94,12 @@ #define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ /* The _USE_LFN option switches the LFN support. / -/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect. -/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT. +/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. / 2: Enable LFN with dynamic working buffer on the STACK. / 3: Enable LFN with dynamic working buffer on the HEAP. / -/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN, +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, / Unicode handling functions ff_convert() and ff_wtoupper() must be added / to the project. When enable to use heap, memory control functions / ff_memalloc() and ff_memfree() must be added to the project. */ @@ -110,10 +110,14 @@ / enable LFN feature and set _LFN_UNICODE to 1. */ -#define _FS_RPATH 0 /* 0:Disable or 1:Enable */ -/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir, -/ f_chdrive function are available. -/ Note that output of the f_readdir function is affected by this option. */ +#define _FS_RPATH 0 /* 0 to 2 */ +/* The _FS_RPATH option configures relative path feature. +/ +/ 0: Disable relative path feature and remove related functions. +/ 1: Enable relative path. f_chdrive() and f_chdir() are available. +/ 2: f_getcwd() is available in addition to 1. +/ +/ Note that output of the f_readdir fnction is affected by this option. */ @@ -121,22 +125,27 @@ / Physical Drive Configurations /----------------------------------------------------------------------------*/ -#define _DRIVES 1 +#define _VOLUMES 1 /* Number of volumes (logical drives) to be used. */ #define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ /* Maximum sector size to be handled. / Always set 512 for memory card and hard disk but a larger value may be -/ required for floppy disk (512/1024) and optical disk (512/2048). -/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implemented -/ to the disk_ioctl function. */ +/ required for on-board flash memory, floppy disk and optical disk. +/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size +/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ #define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ -/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical -/ drive number and can mount only first primary partition. When it is set to 1, -/ each volume is tied to the partitions listed in Drives[]. */ +/* When set to 0, each volume is bound to the same physical drive number and +/ it can mount only first primaly partition. When it is set to 1, each volume +/ is tied to the partitions listed in VolToPart[]. */ + + +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command +/ should be added to the disk_ioctl functio. */ @@ -157,25 +166,24 @@ / performance and code size. */ +/* A header file that defines sync object types on the O/S, such as +/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ + #define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ #define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ #define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ -/* Include a header file here to define O/S system calls */ -/* #include <windows.h>, <ucos_ii.h.h>, <semphr.h> or others. */ -/* The _FS_REENTRANT option switches the re-entrancy of the FatFs module. +/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. / -/ 0: Disable re-entrancy. _SYNC_t and _FS_TIMEOUT have no effect. -/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, / ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj / function must be added to the project. */ #define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ -/* To enable file sharing feature, set _FS_SHARE to >= 1 and also user - provided memory handlers, ff_memalloc and ff_memfree function must be - added to the project. The value defines number of files can be opened - per volume. */ +/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value + defines how many files can be opened simultaneously. */ #endif /* _FFCONFIG */ diff --git a/Projects/Webserver/Lib/FATFs/integer.h b/Projects/Webserver/Lib/FATFs/integer.h index c27d79d35..5408fe6b3 100644 --- a/Projects/Webserver/Lib/FATFs/integer.h +++ b/Projects/Webserver/Lib/FATFs/integer.h @@ -32,8 +32,6 @@ typedef long LONG; typedef unsigned long ULONG; typedef unsigned long DWORD; -typedef unsigned char BOOL; - #endif #endif |