Dependencies:   mbed

Committer:
emh203
Date:
Thu Feb 16 00:41:26 2012 +0000
Revision:
0:76427232f435

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emh203 0:76427232f435 1
emh203 0:76427232f435 2
emh203 0:76427232f435 3 /*----------------------------------------------------------------------------/
emh203 0:76427232f435 4 / FatFs - FAT file system module R0.09 (C)ChaN, 2011
emh203 0:76427232f435 5 /-----------------------------------------------------------------------------/
emh203 0:76427232f435 6 / FatFs module is a generic FAT file system module for small embedded systems.
emh203 0:76427232f435 7 / This is a free software that opened for education, research and commercial
emh203 0:76427232f435 8 / developments under license policy of following terms.
emh203 0:76427232f435 9 /
emh203 0:76427232f435 10 / Copyright (C) 2011, ChaN, all right reserved.
emh203 0:76427232f435 11 /
emh203 0:76427232f435 12 / * The FatFs module is a free software and there is NO WARRANTY.
emh203 0:76427232f435 13 / * No restriction on use. You can use, modify and redistribute it for
emh203 0:76427232f435 14 / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
emh203 0:76427232f435 15 / * Redistributions of source code must retain the above copyright notice.
emh203 0:76427232f435 16 /
emh203 0:76427232f435 17 /-----------------------------------------------------------------------------/
emh203 0:76427232f435 18 / Feb 26,'06 R0.00 Prototype.
emh203 0:76427232f435 19 /
emh203 0:76427232f435 20 / Apr 29,'06 R0.01 First stable version.
emh203 0:76427232f435 21 /
emh203 0:76427232f435 22 / Jun 01,'06 R0.02 Added FAT12 support.
emh203 0:76427232f435 23 / Removed unbuffered mode.
emh203 0:76427232f435 24 / Fixed a problem on small (<32M) partition.
emh203 0:76427232f435 25 / Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
emh203 0:76427232f435 26 /
emh203 0:76427232f435 27 / Sep 22,'06 R0.03 Added f_rename().
emh203 0:76427232f435 28 / Changed option _FS_MINIMUM to _FS_MINIMIZE.
emh203 0:76427232f435 29 / Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast.
emh203 0:76427232f435 30 / Fixed f_mkdir() creates incorrect directory on FAT32.
emh203 0:76427232f435 31 /
emh203 0:76427232f435 32 / Feb 04,'07 R0.04 Supported multiple drive system.
emh203 0:76427232f435 33 / Changed some interfaces for multiple drive system.
emh203 0:76427232f435 34 / Changed f_mountdrv() to f_mount().
emh203 0:76427232f435 35 / Added f_mkfs().
emh203 0:76427232f435 36 / Apr 01,'07 R0.04a Supported multiple partitions on a physical drive.
emh203 0:76427232f435 37 / Added a capability of extending file size to f_lseek().
emh203 0:76427232f435 38 / Added minimization level 3.
emh203 0:76427232f435 39 / Fixed an endian sensitive code in f_mkfs().
emh203 0:76427232f435 40 / May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
emh203 0:76427232f435 41 / Added FSInfo support.
emh203 0:76427232f435 42 / Fixed DBCS name can result FR_INVALID_NAME.
emh203 0:76427232f435 43 / Fixed short seek (<= csize) collapses the file object.
emh203 0:76427232f435 44 /
emh203 0:76427232f435 45 / Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs().
emh203 0:76427232f435 46 / Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
emh203 0:76427232f435 47 / Fixed f_mkdir() on FAT32 creates incorrect directory.
emh203 0:76427232f435 48 / Feb 03,'08 R0.05a Added f_truncate() and f_utime().
emh203 0:76427232f435 49 / Fixed off by one error at FAT sub-type determination.
emh203 0:76427232f435 50 / Fixed btr in f_read() can be mistruncated.
emh203 0:76427232f435 51 / Fixed cached sector is not flushed when create and close without write.
emh203 0:76427232f435 52 /
emh203 0:76427232f435 53 / Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets().
emh203 0:76427232f435 54 / Improved performance of f_lseek() on moving to the same or following cluster.
emh203 0:76427232f435 55 /
emh203 0:76427232f435 56 / Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY)
emh203 0:76427232f435 57 / Added long file name feature.
emh203 0:76427232f435 58 / Added multiple code page feature.
emh203 0:76427232f435 59 / Added re-entrancy for multitask operation.
emh203 0:76427232f435 60 / Added auto cluster size selection to f_mkfs().
emh203 0:76427232f435 61 / Added rewind option to f_readdir().
emh203 0:76427232f435 62 / Changed result code of critical errors.
emh203 0:76427232f435 63 / Renamed string functions to avoid name collision.
emh203 0:76427232f435 64 / Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg.
emh203 0:76427232f435 65 / Added multiple sector size feature.
emh203 0:76427232f435 66 / Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error.
emh203 0:76427232f435 67 / Fixed wrong cache control in f_lseek().
emh203 0:76427232f435 68 / Added relative path feature.
emh203 0:76427232f435 69 / Added f_chdir() and f_chdrive().
emh203 0:76427232f435 70 / Added proper case conversion to extended char.
emh203 0:76427232f435 71 / Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h.
emh203 0:76427232f435 72 / Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
emh203 0:76427232f435 73 / Fixed name matching error on the 13 char boundary.
emh203 0:76427232f435 74 / Added a configuration option, _LFN_UNICODE.
emh203 0:76427232f435 75 / Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
emh203 0:76427232f435 76 /
emh203 0:76427232f435 77 / May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3)
emh203 0:76427232f435 78 / Added file lock feature. (_FS_SHARE)
emh203 0:76427232f435 79 / Added fast seek feature. (_USE_FASTSEEK)
emh203 0:76427232f435 80 / Changed some types on the API, XCHAR->TCHAR.
emh203 0:76427232f435 81 / Changed fname member in the FILINFO structure on Unicode cfg.
emh203 0:76427232f435 82 / String functions support UTF-8 encoding files on Unicode cfg.
emh203 0:76427232f435 83 / Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
emh203 0:76427232f435 84 / Added sector erase feature. (_USE_ERASE)
emh203 0:76427232f435 85 / Moved file lock semaphore table from fs object to the bss.
emh203 0:76427232f435 86 / Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
emh203 0:76427232f435 87 / Fixed f_mkfs() creates wrong FAT32 volume.
emh203 0:76427232f435 88 / Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
emh203 0:76427232f435 89 / f_lseek() reports required table size on creating CLMP.
emh203 0:76427232f435 90 / Extended format syntax of f_printf function.
emh203 0:76427232f435 91 / Ignores duplicated directory separators in given path names.
emh203 0:76427232f435 92 /
emh203 0:76427232f435 93 / Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
emh203 0:76427232f435 94 / Added f_fdisk(). (_MULTI_PARTITION = 2)
emh203 0:76427232f435 95 /---------------------------------------------------------------------------*/
emh203 0:76427232f435 96
emh203 0:76427232f435 97 #include "ff.h" /* FatFs configurations and declarations */
emh203 0:76427232f435 98 #include "diskio.h" /* Declarations of low level disk I/O functions */
emh203 0:76427232f435 99
emh203 0:76427232f435 100
emh203 0:76427232f435 101 /*--------------------------------------------------------------------------
emh203 0:76427232f435 102
emh203 0:76427232f435 103 Module Private Definitions
emh203 0:76427232f435 104
emh203 0:76427232f435 105 ---------------------------------------------------------------------------*/
emh203 0:76427232f435 106
emh203 0:76427232f435 107 #if _FATFS != 6502 /* Revision ID */
emh203 0:76427232f435 108 #error Wrong include file (ff.h).
emh203 0:76427232f435 109 #endif
emh203 0:76427232f435 110
emh203 0:76427232f435 111
emh203 0:76427232f435 112 /* Definitions on sector size */
emh203 0:76427232f435 113 #if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096
emh203 0:76427232f435 114 #error Wrong sector size.
emh203 0:76427232f435 115 #endif
emh203 0:76427232f435 116 #if _MAX_SS != 512
emh203 0:76427232f435 117 #define SS(fs) ((fs)->ssize) /* Variable sector size */
emh203 0:76427232f435 118 #else
emh203 0:76427232f435 119 #define SS(fs) 512U /* Fixed sector size */
emh203 0:76427232f435 120 #endif
emh203 0:76427232f435 121
emh203 0:76427232f435 122
emh203 0:76427232f435 123 /* Reentrancy related */
emh203 0:76427232f435 124 #if _FS_REENTRANT
emh203 0:76427232f435 125 #if _USE_LFN == 1
emh203 0:76427232f435 126 #error Static LFN work area must not be used in re-entrant configuration.
emh203 0:76427232f435 127 #endif
emh203 0:76427232f435 128 #define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; }
emh203 0:76427232f435 129 #define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
emh203 0:76427232f435 130 #else
emh203 0:76427232f435 131 #define ENTER_FF(fs)
emh203 0:76427232f435 132 #define LEAVE_FF(fs, res) return res
emh203 0:76427232f435 133 #endif
emh203 0:76427232f435 134
emh203 0:76427232f435 135 #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
emh203 0:76427232f435 136
emh203 0:76427232f435 137
emh203 0:76427232f435 138 /* File shareing feature */
emh203 0:76427232f435 139 #if _FS_SHARE
emh203 0:76427232f435 140 #if _FS_READONLY
emh203 0:76427232f435 141 #error _FS_SHARE must be 0 on read-only cfg.
emh203 0:76427232f435 142 #endif
emh203 0:76427232f435 143 typedef struct {
emh203 0:76427232f435 144 FATFS *fs; /* File ID 1, volume (NULL:blank entry) */
emh203 0:76427232f435 145 DWORD clu; /* File ID 2, directory */
emh203 0:76427232f435 146 WORD idx; /* File ID 3, directory index */
emh203 0:76427232f435 147 WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */
emh203 0:76427232f435 148 } FILESEM;
emh203 0:76427232f435 149 #endif
emh203 0:76427232f435 150
emh203 0:76427232f435 151
emh203 0:76427232f435 152 /* Misc definitions */
emh203 0:76427232f435 153 #define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
emh203 0:76427232f435 154 #define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
emh203 0:76427232f435 155
emh203 0:76427232f435 156
emh203 0:76427232f435 157 /* DBCS code ranges and SBCS extend char conversion table */
emh203 0:76427232f435 158
emh203 0:76427232f435 159 #if _CODE_PAGE == 932 /* Japanese Shift-JIS */
emh203 0:76427232f435 160 #define _DF1S 0x81 /* DBC 1st byte range 1 start */
emh203 0:76427232f435 161 #define _DF1E 0x9F /* DBC 1st byte range 1 end */
emh203 0:76427232f435 162 #define _DF2S 0xE0 /* DBC 1st byte range 2 start */
emh203 0:76427232f435 163 #define _DF2E 0xFC /* DBC 1st byte range 2 end */
emh203 0:76427232f435 164 #define _DS1S 0x40 /* DBC 2nd byte range 1 start */
emh203 0:76427232f435 165 #define _DS1E 0x7E /* DBC 2nd byte range 1 end */
emh203 0:76427232f435 166 #define _DS2S 0x80 /* DBC 2nd byte range 2 start */
emh203 0:76427232f435 167 #define _DS2E 0xFC /* DBC 2nd byte range 2 end */
emh203 0:76427232f435 168
emh203 0:76427232f435 169 #elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
emh203 0:76427232f435 170 #define _DF1S 0x81
emh203 0:76427232f435 171 #define _DF1E 0xFE
emh203 0:76427232f435 172 #define _DS1S 0x40
emh203 0:76427232f435 173 #define _DS1E 0x7E
emh203 0:76427232f435 174 #define _DS2S 0x80
emh203 0:76427232f435 175 #define _DS2E 0xFE
emh203 0:76427232f435 176
emh203 0:76427232f435 177 #elif _CODE_PAGE == 949 /* Korean */
emh203 0:76427232f435 178 #define _DF1S 0x81
emh203 0:76427232f435 179 #define _DF1E 0xFE
emh203 0:76427232f435 180 #define _DS1S 0x41
emh203 0:76427232f435 181 #define _DS1E 0x5A
emh203 0:76427232f435 182 #define _DS2S 0x61
emh203 0:76427232f435 183 #define _DS2E 0x7A
emh203 0:76427232f435 184 #define _DS3S 0x81
emh203 0:76427232f435 185 #define _DS3E 0xFE
emh203 0:76427232f435 186
emh203 0:76427232f435 187 #elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
emh203 0:76427232f435 188 #define _DF1S 0x81
emh203 0:76427232f435 189 #define _DF1E 0xFE
emh203 0:76427232f435 190 #define _DS1S 0x40
emh203 0:76427232f435 191 #define _DS1E 0x7E
emh203 0:76427232f435 192 #define _DS2S 0xA1
emh203 0:76427232f435 193 #define _DS2E 0xFE
emh203 0:76427232f435 194
emh203 0:76427232f435 195 #elif _CODE_PAGE == 437 /* U.S. (OEM) */
emh203 0:76427232f435 196 #define _DF1S 0
emh203 0:76427232f435 197 #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, \
emh203 0:76427232f435 198 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, \
emh203 0:76427232f435 199 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, \
emh203 0:76427232f435 200 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}
emh203 0:76427232f435 201
emh203 0:76427232f435 202 #elif _CODE_PAGE == 720 /* Arabic (OEM) */
emh203 0:76427232f435 203 #define _DF1S 0
emh203 0:76427232f435 204 #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, \
emh203 0:76427232f435 205 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, \
emh203 0:76427232f435 206 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, \
emh203 0:76427232f435 207 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}
emh203 0:76427232f435 208
emh203 0:76427232f435 209 #elif _CODE_PAGE == 737 /* Greek (OEM) */
emh203 0:76427232f435 210 #define _DF1S 0
emh203 0:76427232f435 211 #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, \
emh203 0:76427232f435 212 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, \
emh203 0:76427232f435 213 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, \
emh203 0:76427232f435 214 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}
emh203 0:76427232f435 215
emh203 0:76427232f435 216 #elif _CODE_PAGE == 775 /* Baltic (OEM) */
emh203 0:76427232f435 217 #define _DF1S 0
emh203 0:76427232f435 218 #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, \
emh203 0:76427232f435 219 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, \
emh203 0:76427232f435 220 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, \
emh203 0:76427232f435 221 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}
emh203 0:76427232f435 222
emh203 0:76427232f435 223 #elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
emh203 0:76427232f435 224 #define _DF1S 0
emh203 0:76427232f435 225 #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, \
emh203 0:76427232f435 226 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, \
emh203 0:76427232f435 227 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, \
emh203 0:76427232f435 228 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}
emh203 0:76427232f435 229
emh203 0:76427232f435 230 #elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
emh203 0:76427232f435 231 #define _DF1S 0
emh203 0:76427232f435 232 #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, \
emh203 0:76427232f435 233 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, \
emh203 0:76427232f435 234 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, \
emh203 0:76427232f435 235 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}
emh203 0:76427232f435 236
emh203 0:76427232f435 237 #elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
emh203 0:76427232f435 238 #define _DF1S 0
emh203 0:76427232f435 239 #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, \
emh203 0:76427232f435 240 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, \
emh203 0:76427232f435 241 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, \
emh203 0:76427232f435 242 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}
emh203 0:76427232f435 243
emh203 0:76427232f435 244 #elif _CODE_PAGE == 857 /* Turkish (OEM) */
emh203 0:76427232f435 245 #define _DF1S 0
emh203 0:76427232f435 246 #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, \
emh203 0:76427232f435 247 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, \
emh203 0:76427232f435 248 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, \
emh203 0:76427232f435 249 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}
emh203 0:76427232f435 250
emh203 0:76427232f435 251 #elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
emh203 0:76427232f435 252 #define _DF1S 0
emh203 0:76427232f435 253 #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, \
emh203 0:76427232f435 254 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, \
emh203 0:76427232f435 255 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, \
emh203 0:76427232f435 256 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}
emh203 0:76427232f435 257
emh203 0:76427232f435 258 #elif _CODE_PAGE == 862 /* Hebrew (OEM) */
emh203 0:76427232f435 259 #define _DF1S 0
emh203 0:76427232f435 260 #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, \
emh203 0:76427232f435 261 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, \
emh203 0:76427232f435 262 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, \
emh203 0:76427232f435 263 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}
emh203 0:76427232f435 264
emh203 0:76427232f435 265 #elif _CODE_PAGE == 866 /* Russian (OEM) */
emh203 0:76427232f435 266 #define _DF1S 0
emh203 0:76427232f435 267 #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, \
emh203 0:76427232f435 268 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, \
emh203 0:76427232f435 269 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, \
emh203 0:76427232f435 270 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}
emh203 0:76427232f435 271
emh203 0:76427232f435 272 #elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
emh203 0:76427232f435 273 #define _DF1S 0
emh203 0:76427232f435 274 #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, \
emh203 0:76427232f435 275 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, \
emh203 0:76427232f435 276 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, \
emh203 0:76427232f435 277 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}
emh203 0:76427232f435 278
emh203 0:76427232f435 279 #elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
emh203 0:76427232f435 280 #define _DF1S 0
emh203 0:76427232f435 281 #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, \
emh203 0:76427232f435 282 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, \
emh203 0:76427232f435 283 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, \
emh203 0:76427232f435 284 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}
emh203 0:76427232f435 285
emh203 0:76427232f435 286 #elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
emh203 0:76427232f435 287 #define _DF1S 0
emh203 0:76427232f435 288 #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, \
emh203 0:76427232f435 289 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, \
emh203 0:76427232f435 290 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, \
emh203 0:76427232f435 291 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}
emh203 0:76427232f435 292
emh203 0:76427232f435 293 #elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
emh203 0:76427232f435 294 #define _DF1S 0
emh203 0:76427232f435 295 #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, \
emh203 0:76427232f435 296 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, \
emh203 0:76427232f435 297 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, \
emh203 0:76427232f435 298 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}
emh203 0:76427232f435 299
emh203 0:76427232f435 300 #elif _CODE_PAGE == 1253 /* Greek (Windows) */
emh203 0:76427232f435 301 #define _DF1S 0
emh203 0:76427232f435 302 #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, \
emh203 0:76427232f435 303 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, \
emh203 0:76427232f435 304 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, \
emh203 0:76427232f435 305 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}
emh203 0:76427232f435 306
emh203 0:76427232f435 307 #elif _CODE_PAGE == 1254 /* Turkish (Windows) */
emh203 0:76427232f435 308 #define _DF1S 0
emh203 0:76427232f435 309 #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, \
emh203 0:76427232f435 310 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, \
emh203 0:76427232f435 311 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, \
emh203 0:76427232f435 312 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}
emh203 0:76427232f435 313
emh203 0:76427232f435 314 #elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
emh203 0:76427232f435 315 #define _DF1S 0
emh203 0:76427232f435 316 #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, \
emh203 0:76427232f435 317 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, \
emh203 0:76427232f435 318 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, \
emh203 0:76427232f435 319 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}
emh203 0:76427232f435 320
emh203 0:76427232f435 321 #elif _CODE_PAGE == 1256 /* Arabic (Windows) */
emh203 0:76427232f435 322 #define _DF1S 0
emh203 0:76427232f435 323 #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, \
emh203 0:76427232f435 324 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, \
emh203 0:76427232f435 325 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, \
emh203 0:76427232f435 326 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}
emh203 0:76427232f435 327
emh203 0:76427232f435 328 #elif _CODE_PAGE == 1257 /* Baltic (Windows) */
emh203 0:76427232f435 329 #define _DF1S 0
emh203 0:76427232f435 330 #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, \
emh203 0:76427232f435 331 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, \
emh203 0:76427232f435 332 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, \
emh203 0:76427232f435 333 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}
emh203 0:76427232f435 334
emh203 0:76427232f435 335 #elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
emh203 0:76427232f435 336 #define _DF1S 0
emh203 0:76427232f435 337 #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, \
emh203 0:76427232f435 338 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, \
emh203 0:76427232f435 339 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, \
emh203 0:76427232f435 340 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}
emh203 0:76427232f435 341
emh203 0:76427232f435 342 #elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
emh203 0:76427232f435 343 #if _USE_LFN
emh203 0:76427232f435 344 #error Cannot use LFN feature without valid code page.
emh203 0:76427232f435 345 #endif
emh203 0:76427232f435 346 #define _DF1S 0
emh203 0:76427232f435 347
emh203 0:76427232f435 348 #else
emh203 0:76427232f435 349 #error Unknown code page
emh203 0:76427232f435 350
emh203 0:76427232f435 351 #endif
emh203 0:76427232f435 352
emh203 0:76427232f435 353
emh203 0:76427232f435 354 /* Character code support macros */
emh203 0:76427232f435 355 #define IsUpper(c) (((c)>='A')&&((c)<='Z'))
emh203 0:76427232f435 356 #define IsLower(c) (((c)>='a')&&((c)<='z'))
emh203 0:76427232f435 357 #define IsDigit(c) (((c)>='0')&&((c)<='9'))
emh203 0:76427232f435 358
emh203 0:76427232f435 359 #if _DF1S /* Code page is DBCS */
emh203 0:76427232f435 360
emh203 0:76427232f435 361 #ifdef _DF2S /* Two 1st byte areas */
emh203 0:76427232f435 362 #define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
emh203 0:76427232f435 363 #else /* One 1st byte area */
emh203 0:76427232f435 364 #define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
emh203 0:76427232f435 365 #endif
emh203 0:76427232f435 366
emh203 0:76427232f435 367 #ifdef _DS3S /* Three 2nd byte areas */
emh203 0:76427232f435 368 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
emh203 0:76427232f435 369 #else /* Two 2nd byte areas */
emh203 0:76427232f435 370 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
emh203 0:76427232f435 371 #endif
emh203 0:76427232f435 372
emh203 0:76427232f435 373 #else /* Code page is SBCS */
emh203 0:76427232f435 374
emh203 0:76427232f435 375 #define IsDBCS1(c) 0
emh203 0:76427232f435 376 #define IsDBCS2(c) 0
emh203 0:76427232f435 377
emh203 0:76427232f435 378 #endif /* _DF1S */
emh203 0:76427232f435 379
emh203 0:76427232f435 380
emh203 0:76427232f435 381 /* Name status flags */
emh203 0:76427232f435 382 #define NS 11 /* Index of name status byte in fn[] */
emh203 0:76427232f435 383 #define NS_LOSS 0x01 /* Out of 8.3 format */
emh203 0:76427232f435 384 #define NS_LFN 0x02 /* Force to create LFN entry */
emh203 0:76427232f435 385 #define NS_LAST 0x04 /* Last segment */
emh203 0:76427232f435 386 #define NS_BODY 0x08 /* Lower case flag (body) */
emh203 0:76427232f435 387 #define NS_EXT 0x10 /* Lower case flag (ext) */
emh203 0:76427232f435 388 #define NS_DOT 0x20 /* Dot entry */
emh203 0:76427232f435 389
emh203 0:76427232f435 390
emh203 0:76427232f435 391 /* FAT sub-type boundaries */
emh203 0:76427232f435 392 /* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */
emh203 0:76427232f435 393 #define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */
emh203 0:76427232f435 394 #define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */
emh203 0:76427232f435 395
emh203 0:76427232f435 396
emh203 0:76427232f435 397 /* FatFs refers the members in the FAT structures as byte array instead of
emh203 0:76427232f435 398 / structure member because the structure is not binary compatible between
emh203 0:76427232f435 399 / different platforms */
emh203 0:76427232f435 400
emh203 0:76427232f435 401 #define BS_jmpBoot 0 /* Jump instruction (3) */
emh203 0:76427232f435 402 #define BS_OEMName 3 /* OEM name (8) */
emh203 0:76427232f435 403 #define BPB_BytsPerSec 11 /* Sector size [byte] (2) */
emh203 0:76427232f435 404 #define BPB_SecPerClus 13 /* Cluster size [sector] (1) */
emh203 0:76427232f435 405 #define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */
emh203 0:76427232f435 406 #define BPB_NumFATs 16 /* Number of FAT copies (1) */
emh203 0:76427232f435 407 #define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */
emh203 0:76427232f435 408 #define BPB_TotSec16 19 /* Volume size [sector] (2) */
emh203 0:76427232f435 409 #define BPB_Media 21 /* Media descriptor (1) */
emh203 0:76427232f435 410 #define BPB_FATSz16 22 /* FAT size [sector] (2) */
emh203 0:76427232f435 411 #define BPB_SecPerTrk 24 /* Track size [sector] (2) */
emh203 0:76427232f435 412 #define BPB_NumHeads 26 /* Number of heads (2) */
emh203 0:76427232f435 413 #define BPB_HiddSec 28 /* Number of special hidden sectors (4) */
emh203 0:76427232f435 414 #define BPB_TotSec32 32 /* Volume size [sector] (4) */
emh203 0:76427232f435 415 #define BS_DrvNum 36 /* Physical drive number (2) */
emh203 0:76427232f435 416 #define BS_BootSig 38 /* Extended boot signature (1) */
emh203 0:76427232f435 417 #define BS_VolID 39 /* Volume serial number (4) */
emh203 0:76427232f435 418 #define BS_VolLab 43 /* Volume label (8) */
emh203 0:76427232f435 419 #define BS_FilSysType 54 /* File system type (1) */
emh203 0:76427232f435 420 #define BPB_FATSz32 36 /* FAT size [sector] (4) */
emh203 0:76427232f435 421 #define BPB_ExtFlags 40 /* Extended flags (2) */
emh203 0:76427232f435 422 #define BPB_FSVer 42 /* File system version (2) */
emh203 0:76427232f435 423 #define BPB_RootClus 44 /* Root dir first cluster (4) */
emh203 0:76427232f435 424 #define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */
emh203 0:76427232f435 425 #define BPB_BkBootSec 50 /* Offset of backup boot sectot (2) */
emh203 0:76427232f435 426 #define BS_DrvNum32 64 /* Physical drive number (2) */
emh203 0:76427232f435 427 #define BS_BootSig32 66 /* Extended boot signature (1) */
emh203 0:76427232f435 428 #define BS_VolID32 67 /* Volume serial number (4) */
emh203 0:76427232f435 429 #define BS_VolLab32 71 /* Volume label (8) */
emh203 0:76427232f435 430 #define BS_FilSysType32 82 /* File system type (1) */
emh203 0:76427232f435 431 #define FSI_LeadSig 0 /* FSI: Leading signature (4) */
emh203 0:76427232f435 432 #define FSI_StrucSig 484 /* FSI: Structure signature (4) */
emh203 0:76427232f435 433 #define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */
emh203 0:76427232f435 434 #define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */
emh203 0:76427232f435 435 #define MBR_Table 446 /* MBR: Partition table offset (2) */
emh203 0:76427232f435 436 #define SZ_PTE 16 /* MBR: Size of a partition table entry */
emh203 0:76427232f435 437 #define BS_55AA 510 /* Boot sector signature (2) */
emh203 0:76427232f435 438
emh203 0:76427232f435 439 #define DIR_Name 0 /* Short file name (11) */
emh203 0:76427232f435 440 #define DIR_Attr 11 /* Attribute (1) */
emh203 0:76427232f435 441 #define DIR_NTres 12 /* NT flag (1) */
emh203 0:76427232f435 442 #define DIR_CrtTime 14 /* Created time (2) */
emh203 0:76427232f435 443 #define DIR_CrtDate 16 /* Created date (2) */
emh203 0:76427232f435 444 #define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
emh203 0:76427232f435 445 #define DIR_WrtTime 22 /* Modified time (2) */
emh203 0:76427232f435 446 #define DIR_WrtDate 24 /* Modified date (2) */
emh203 0:76427232f435 447 #define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */
emh203 0:76427232f435 448 #define DIR_FileSize 28 /* File size (4) */
emh203 0:76427232f435 449 #define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */
emh203 0:76427232f435 450 #define LDIR_Attr 11 /* LFN attribute (1) */
emh203 0:76427232f435 451 #define LDIR_Type 12 /* LFN type (1) */
emh203 0:76427232f435 452 #define LDIR_Chksum 13 /* Sum of corresponding SFN entry */
emh203 0:76427232f435 453 #define LDIR_FstClusLO 26 /* Filled by zero (0) */
emh203 0:76427232f435 454 #define SZ_DIR 32 /* Size of a directory entry */
emh203 0:76427232f435 455 #define LLE 0x40 /* Last long entry flag in LDIR_Ord */
emh203 0:76427232f435 456 #define DDE 0xE5 /* Deleted directory enrty mark in DIR_Name[0] */
emh203 0:76427232f435 457 #define NDDE 0x05 /* Replacement of a character collides with DDE */
emh203 0:76427232f435 458
emh203 0:76427232f435 459
emh203 0:76427232f435 460 /*------------------------------------------------------------*/
emh203 0:76427232f435 461 /* Module private work area */
emh203 0:76427232f435 462 /*------------------------------------------------------------*/
emh203 0:76427232f435 463 /* Note that uninitialized variables with static duration are
emh203 0:76427232f435 464 / zeroed/nulled at start-up. If not, the compiler or start-up
emh203 0:76427232f435 465 / routine is out of ANSI-C standard.
emh203 0:76427232f435 466 */
emh203 0:76427232f435 467
emh203 0:76427232f435 468 #if _VOLUMES
emh203 0:76427232f435 469 static
emh203 0:76427232f435 470 FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
emh203 0:76427232f435 471 #else
emh203 0:76427232f435 472 #error Number of volumes must not be 0.
emh203 0:76427232f435 473 #endif
emh203 0:76427232f435 474
emh203 0:76427232f435 475 static
emh203 0:76427232f435 476 WORD Fsid; /* File system mount ID */
emh203 0:76427232f435 477
emh203 0:76427232f435 478 #if _FS_RPATH
emh203 0:76427232f435 479 static
emh203 0:76427232f435 480 BYTE CurrVol; /* Current drive */
emh203 0:76427232f435 481 #endif
emh203 0:76427232f435 482
emh203 0:76427232f435 483 #if _FS_SHARE
emh203 0:76427232f435 484 static
emh203 0:76427232f435 485 FILESEM Files[_FS_SHARE]; /* File lock semaphores */
emh203 0:76427232f435 486 #endif
emh203 0:76427232f435 487
emh203 0:76427232f435 488 #if _USE_LFN == 0 /* No LFN feature */
emh203 0:76427232f435 489 #define DEF_NAMEBUF BYTE sfn[12]
emh203 0:76427232f435 490 #define INIT_BUF(dobj) (dobj).fn = sfn
emh203 0:76427232f435 491 #define FREE_BUF()
emh203 0:76427232f435 492
emh203 0:76427232f435 493 #elif _USE_LFN == 1 /* LFN feature with static working buffer */
emh203 0:76427232f435 494 static WCHAR LfnBuf[_MAX_LFN+1];
emh203 0:76427232f435 495 #define DEF_NAMEBUF BYTE sfn[12]
emh203 0:76427232f435 496 #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
emh203 0:76427232f435 497 #define FREE_BUF()
emh203 0:76427232f435 498
emh203 0:76427232f435 499 #elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */
emh203 0:76427232f435 500 #define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
emh203 0:76427232f435 501 #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
emh203 0:76427232f435 502 #define FREE_BUF()
emh203 0:76427232f435 503
emh203 0:76427232f435 504 #elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */
emh203 0:76427232f435 505 #define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
emh203 0:76427232f435 506 #define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
emh203 0:76427232f435 507 if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
emh203 0:76427232f435 508 (dobj).lfn = lfn; (dobj).fn = sfn; }
emh203 0:76427232f435 509 #define FREE_BUF() ff_memfree(lfn)
emh203 0:76427232f435 510
emh203 0:76427232f435 511 #else
emh203 0:76427232f435 512 #error Wrong LFN configuration.
emh203 0:76427232f435 513 #endif
emh203 0:76427232f435 514
emh203 0:76427232f435 515
emh203 0:76427232f435 516
emh203 0:76427232f435 517
emh203 0:76427232f435 518 /*--------------------------------------------------------------------------
emh203 0:76427232f435 519
emh203 0:76427232f435 520 Module Private Functions
emh203 0:76427232f435 521
emh203 0:76427232f435 522 ---------------------------------------------------------------------------*/
emh203 0:76427232f435 523
emh203 0:76427232f435 524
emh203 0:76427232f435 525 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 526 /* String functions */
emh203 0:76427232f435 527 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 528
emh203 0:76427232f435 529 /* Copy memory to memory */
emh203 0:76427232f435 530 static
emh203 0:76427232f435 531 void mem_cpy (void* dst, const void* src, UINT cnt) {
emh203 0:76427232f435 532 BYTE *d = (BYTE*)dst;
emh203 0:76427232f435 533 const BYTE *s = (const BYTE*)src;
emh203 0:76427232f435 534
emh203 0:76427232f435 535 #if _WORD_ACCESS == 1
emh203 0:76427232f435 536 while (cnt >= sizeof(int)) {
emh203 0:76427232f435 537 *(int*)d = *(int*)s;
emh203 0:76427232f435 538 d += sizeof(int); s += sizeof(int);
emh203 0:76427232f435 539 cnt -= sizeof(int);
emh203 0:76427232f435 540 }
emh203 0:76427232f435 541 #endif
emh203 0:76427232f435 542 while (cnt--)
emh203 0:76427232f435 543 *d++ = *s++;
emh203 0:76427232f435 544 }
emh203 0:76427232f435 545
emh203 0:76427232f435 546 /* Fill memory */
emh203 0:76427232f435 547 static
emh203 0:76427232f435 548 void mem_set (void* dst, int val, UINT cnt) {
emh203 0:76427232f435 549 BYTE *d = (BYTE*)dst;
emh203 0:76427232f435 550
emh203 0:76427232f435 551 while (cnt--)
emh203 0:76427232f435 552 *d++ = (BYTE)val;
emh203 0:76427232f435 553 }
emh203 0:76427232f435 554
emh203 0:76427232f435 555 /* Compare memory to memory */
emh203 0:76427232f435 556 static
emh203 0:76427232f435 557 int mem_cmp (const void* dst, const void* src, UINT cnt) {
emh203 0:76427232f435 558 const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
emh203 0:76427232f435 559 int r = 0;
emh203 0:76427232f435 560
emh203 0:76427232f435 561 while (cnt-- && (r = *d++ - *s++) == 0) ;
emh203 0:76427232f435 562 return r;
emh203 0:76427232f435 563 }
emh203 0:76427232f435 564
emh203 0:76427232f435 565 /* Check if chr is contained in the string */
emh203 0:76427232f435 566 static
emh203 0:76427232f435 567 int chk_chr (const char* str, int chr) {
emh203 0:76427232f435 568 while (*str && *str != chr) str++;
emh203 0:76427232f435 569 return *str;
emh203 0:76427232f435 570 }
emh203 0:76427232f435 571
emh203 0:76427232f435 572
emh203 0:76427232f435 573
emh203 0:76427232f435 574 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 575 /* Request/Release grant to access the volume */
emh203 0:76427232f435 576 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 577 #if _FS_REENTRANT
emh203 0:76427232f435 578
emh203 0:76427232f435 579 static
emh203 0:76427232f435 580 int lock_fs (
emh203 0:76427232f435 581 FATFS *fs /* File system object */
emh203 0:76427232f435 582 )
emh203 0:76427232f435 583 {
emh203 0:76427232f435 584 return ff_req_grant(fs->sobj);
emh203 0:76427232f435 585 }
emh203 0:76427232f435 586
emh203 0:76427232f435 587
emh203 0:76427232f435 588 static
emh203 0:76427232f435 589 void unlock_fs (
emh203 0:76427232f435 590 FATFS *fs, /* File system object */
emh203 0:76427232f435 591 FRESULT res /* Result code to be returned */
emh203 0:76427232f435 592 )
emh203 0:76427232f435 593 {
emh203 0:76427232f435 594 if (res != FR_NOT_ENABLED &&
emh203 0:76427232f435 595 res != FR_INVALID_DRIVE &&
emh203 0:76427232f435 596 res != FR_INVALID_OBJECT &&
emh203 0:76427232f435 597 res != FR_TIMEOUT) {
emh203 0:76427232f435 598 ff_rel_grant(fs->sobj);
emh203 0:76427232f435 599 }
emh203 0:76427232f435 600 }
emh203 0:76427232f435 601 #endif
emh203 0:76427232f435 602
emh203 0:76427232f435 603
emh203 0:76427232f435 604
emh203 0:76427232f435 605 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 606 /* File shareing control functions */
emh203 0:76427232f435 607 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 608 #if _FS_SHARE
emh203 0:76427232f435 609
emh203 0:76427232f435 610 static
emh203 0:76427232f435 611 FRESULT chk_lock ( /* Check if the file can be accessed */
emh203 0:76427232f435 612 DIR* dj, /* Directory object pointing the file to be checked */
emh203 0:76427232f435 613 int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
emh203 0:76427232f435 614 )
emh203 0:76427232f435 615 {
emh203 0:76427232f435 616 UINT i, be;
emh203 0:76427232f435 617
emh203 0:76427232f435 618 /* Search file semaphore table */
emh203 0:76427232f435 619 for (i = be = 0; i < _FS_SHARE; i++) {
emh203 0:76427232f435 620 if (Files[i].fs) { /* Existing entry */
emh203 0:76427232f435 621 if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */
emh203 0:76427232f435 622 Files[i].clu == dj->sclust &&
emh203 0:76427232f435 623 Files[i].idx == dj->index) break;
emh203 0:76427232f435 624 } else { /* Blank entry */
emh203 0:76427232f435 625 be++;
emh203 0:76427232f435 626 }
emh203 0:76427232f435 627 }
emh203 0:76427232f435 628 if (i == _FS_SHARE) /* The file is not opened */
emh203 0:76427232f435 629 return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */
emh203 0:76427232f435 630
emh203 0:76427232f435 631 /* The file has been opened. Reject any open against writing file and all write mode open */
emh203 0:76427232f435 632 return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
emh203 0:76427232f435 633 }
emh203 0:76427232f435 634
emh203 0:76427232f435 635
emh203 0:76427232f435 636 static
emh203 0:76427232f435 637 int enq_lock (void) /* Check if an entry is available for a new file */
emh203 0:76427232f435 638 {
emh203 0:76427232f435 639 UINT i;
emh203 0:76427232f435 640
emh203 0:76427232f435 641 for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
emh203 0:76427232f435 642 return (i == _FS_SHARE) ? 0 : 1;
emh203 0:76427232f435 643 }
emh203 0:76427232f435 644
emh203 0:76427232f435 645
emh203 0:76427232f435 646 static
emh203 0:76427232f435 647 UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */
emh203 0:76427232f435 648 DIR* dj, /* Directory object pointing the file to register or increment */
emh203 0:76427232f435 649 int acc /* Desired access mode (0:Read, !0:Write) */
emh203 0:76427232f435 650 )
emh203 0:76427232f435 651 {
emh203 0:76427232f435 652 UINT i;
emh203 0:76427232f435 653
emh203 0:76427232f435 654
emh203 0:76427232f435 655 for (i = 0; i < _FS_SHARE; i++) { /* Find the file */
emh203 0:76427232f435 656 if (Files[i].fs == dj->fs &&
emh203 0:76427232f435 657 Files[i].clu == dj->sclust &&
emh203 0:76427232f435 658 Files[i].idx == dj->index) break;
emh203 0:76427232f435 659 }
emh203 0:76427232f435 660
emh203 0:76427232f435 661 if (i == _FS_SHARE) { /* Not opened. Register it as new. */
emh203 0:76427232f435 662 for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
emh203 0:76427232f435 663 if (i == _FS_SHARE) return 0; /* No space to register (int err) */
emh203 0:76427232f435 664 Files[i].fs = dj->fs;
emh203 0:76427232f435 665 Files[i].clu = dj->sclust;
emh203 0:76427232f435 666 Files[i].idx = dj->index;
emh203 0:76427232f435 667 Files[i].ctr = 0;
emh203 0:76427232f435 668 }
emh203 0:76427232f435 669
emh203 0:76427232f435 670 if (acc && Files[i].ctr) return 0; /* Access violation (int err) */
emh203 0:76427232f435 671
emh203 0:76427232f435 672 Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */
emh203 0:76427232f435 673
emh203 0:76427232f435 674 return i + 1;
emh203 0:76427232f435 675 }
emh203 0:76427232f435 676
emh203 0:76427232f435 677
emh203 0:76427232f435 678 static
emh203 0:76427232f435 679 FRESULT dec_lock ( /* Decrement file open counter */
emh203 0:76427232f435 680 UINT i /* Semaphore index */
emh203 0:76427232f435 681 )
emh203 0:76427232f435 682 {
emh203 0:76427232f435 683 WORD n;
emh203 0:76427232f435 684 FRESULT res;
emh203 0:76427232f435 685
emh203 0:76427232f435 686
emh203 0:76427232f435 687 if (--i < _FS_SHARE) {
emh203 0:76427232f435 688 n = Files[i].ctr;
emh203 0:76427232f435 689 if (n == 0x100) n = 0;
emh203 0:76427232f435 690 if (n) n--;
emh203 0:76427232f435 691 Files[i].ctr = n;
emh203 0:76427232f435 692 if (!n) Files[i].fs = 0;
emh203 0:76427232f435 693 res = FR_OK;
emh203 0:76427232f435 694 } else {
emh203 0:76427232f435 695 res = FR_INT_ERR;
emh203 0:76427232f435 696 }
emh203 0:76427232f435 697 return res;
emh203 0:76427232f435 698 }
emh203 0:76427232f435 699
emh203 0:76427232f435 700
emh203 0:76427232f435 701 static
emh203 0:76427232f435 702 void clear_lock ( /* Clear lock entries of the volume */
emh203 0:76427232f435 703 FATFS *fs
emh203 0:76427232f435 704 )
emh203 0:76427232f435 705 {
emh203 0:76427232f435 706 UINT i;
emh203 0:76427232f435 707
emh203 0:76427232f435 708 for (i = 0; i < _FS_SHARE; i++) {
emh203 0:76427232f435 709 if (Files[i].fs == fs) Files[i].fs = 0;
emh203 0:76427232f435 710 }
emh203 0:76427232f435 711 }
emh203 0:76427232f435 712 #endif
emh203 0:76427232f435 713
emh203 0:76427232f435 714
emh203 0:76427232f435 715
emh203 0:76427232f435 716 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 717 /* Change window offset */
emh203 0:76427232f435 718 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 719
emh203 0:76427232f435 720 static
emh203 0:76427232f435 721 FRESULT move_window (
emh203 0:76427232f435 722 FATFS *fs, /* File system object */
emh203 0:76427232f435 723 DWORD sector /* Sector number to make appearance in the fs->win[] */
emh203 0:76427232f435 724 ) /* Move to zero only writes back dirty window */
emh203 0:76427232f435 725 {
emh203 0:76427232f435 726 DWORD wsect;
emh203 0:76427232f435 727
emh203 0:76427232f435 728
emh203 0:76427232f435 729 wsect = fs->winsect;
emh203 0:76427232f435 730 if (wsect != sector) { /* Changed current window */
emh203 0:76427232f435 731 #if !_FS_READONLY
emh203 0:76427232f435 732 if (fs->wflag) { /* Write back dirty window if needed */
emh203 0:76427232f435 733 if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK)
emh203 0:76427232f435 734 return FR_DISK_ERR;
emh203 0:76427232f435 735 fs->wflag = 0;
emh203 0:76427232f435 736 if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */
emh203 0:76427232f435 737 BYTE nf;
emh203 0:76427232f435 738 for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */
emh203 0:76427232f435 739 wsect += fs->fsize;
emh203 0:76427232f435 740 disk_write(fs->drv, fs->win, wsect, 1);
emh203 0:76427232f435 741 }
emh203 0:76427232f435 742 }
emh203 0:76427232f435 743 }
emh203 0:76427232f435 744 #endif
emh203 0:76427232f435 745 if (sector) {
emh203 0:76427232f435 746 if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK)
emh203 0:76427232f435 747 return FR_DISK_ERR;
emh203 0:76427232f435 748 fs->winsect = sector;
emh203 0:76427232f435 749 }
emh203 0:76427232f435 750 }
emh203 0:76427232f435 751
emh203 0:76427232f435 752 return FR_OK;
emh203 0:76427232f435 753 }
emh203 0:76427232f435 754
emh203 0:76427232f435 755
emh203 0:76427232f435 756
emh203 0:76427232f435 757
emh203 0:76427232f435 758 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 759 /* Clean-up cached data */
emh203 0:76427232f435 760 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 761 #if !_FS_READONLY
emh203 0:76427232f435 762 static
emh203 0:76427232f435 763 FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */
emh203 0:76427232f435 764 FATFS *fs /* File system object */
emh203 0:76427232f435 765 )
emh203 0:76427232f435 766 {
emh203 0:76427232f435 767 FRESULT res;
emh203 0:76427232f435 768
emh203 0:76427232f435 769
emh203 0:76427232f435 770 res = move_window(fs, 0);
emh203 0:76427232f435 771 if (res == FR_OK) {
emh203 0:76427232f435 772 /* Update FSInfo sector if needed */
emh203 0:76427232f435 773 if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {
emh203 0:76427232f435 774 fs->winsect = 0;
emh203 0:76427232f435 775 /* Create FSInfo structure */
emh203 0:76427232f435 776 mem_set(fs->win, 0, 512);
emh203 0:76427232f435 777 ST_WORD(fs->win+BS_55AA, 0xAA55);
emh203 0:76427232f435 778 ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);
emh203 0:76427232f435 779 ST_DWORD(fs->win+FSI_StrucSig, 0x61417272);
emh203 0:76427232f435 780 ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust);
emh203 0:76427232f435 781 ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust);
emh203 0:76427232f435 782 /* Write it into the FSInfo sector */
emh203 0:76427232f435 783 disk_write(fs->drv, fs->win, fs->fsi_sector, 1);
emh203 0:76427232f435 784 fs->fsi_flag = 0;
emh203 0:76427232f435 785 }
emh203 0:76427232f435 786 /* Make sure that no pending write process in the physical drive */
emh203 0:76427232f435 787 if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
emh203 0:76427232f435 788 res = FR_DISK_ERR;
emh203 0:76427232f435 789 }
emh203 0:76427232f435 790
emh203 0:76427232f435 791 return res;
emh203 0:76427232f435 792 }
emh203 0:76427232f435 793 #endif
emh203 0:76427232f435 794
emh203 0:76427232f435 795
emh203 0:76427232f435 796
emh203 0:76427232f435 797
emh203 0:76427232f435 798 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 799 /* Get sector# from cluster# */
emh203 0:76427232f435 800 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 801
emh203 0:76427232f435 802
emh203 0:76427232f435 803 DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
emh203 0:76427232f435 804 FATFS *fs, /* File system object */
emh203 0:76427232f435 805 DWORD clst /* Cluster# to be converted */
emh203 0:76427232f435 806 )
emh203 0:76427232f435 807 {
emh203 0:76427232f435 808 clst -= 2;
emh203 0:76427232f435 809 if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */
emh203 0:76427232f435 810 return clst * fs->csize + fs->database;
emh203 0:76427232f435 811 }
emh203 0:76427232f435 812
emh203 0:76427232f435 813
emh203 0:76427232f435 814
emh203 0:76427232f435 815
emh203 0:76427232f435 816 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 817 /* FAT access - Read value of a FAT entry */
emh203 0:76427232f435 818 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 819
emh203 0:76427232f435 820
emh203 0:76427232f435 821 DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */
emh203 0:76427232f435 822 FATFS *fs, /* File system object */
emh203 0:76427232f435 823 DWORD clst /* Cluster# to get the link information */
emh203 0:76427232f435 824 )
emh203 0:76427232f435 825 {
emh203 0:76427232f435 826 UINT wc, bc;
emh203 0:76427232f435 827 BYTE *p;
emh203 0:76427232f435 828
emh203 0:76427232f435 829
emh203 0:76427232f435 830 if (clst < 2 || clst >= fs->n_fatent) /* Chack range */
emh203 0:76427232f435 831 return 1;
emh203 0:76427232f435 832
emh203 0:76427232f435 833 switch (fs->fs_type) {
emh203 0:76427232f435 834 case FS_FAT12 :
emh203 0:76427232f435 835 bc = (UINT)clst; bc += bc / 2;
emh203 0:76427232f435 836 if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
emh203 0:76427232f435 837 wc = fs->win[bc % SS(fs)]; bc++;
emh203 0:76427232f435 838 if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
emh203 0:76427232f435 839 wc |= fs->win[bc % SS(fs)] << 8;
emh203 0:76427232f435 840 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
emh203 0:76427232f435 841
emh203 0:76427232f435 842 case FS_FAT16 :
emh203 0:76427232f435 843 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break;
emh203 0:76427232f435 844 p = &fs->win[clst * 2 % SS(fs)];
emh203 0:76427232f435 845 return LD_WORD(p);
emh203 0:76427232f435 846
emh203 0:76427232f435 847 case FS_FAT32 :
emh203 0:76427232f435 848 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break;
emh203 0:76427232f435 849 p = &fs->win[clst * 4 % SS(fs)];
emh203 0:76427232f435 850 return LD_DWORD(p) & 0x0FFFFFFF;
emh203 0:76427232f435 851 }
emh203 0:76427232f435 852
emh203 0:76427232f435 853 return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */
emh203 0:76427232f435 854 }
emh203 0:76427232f435 855
emh203 0:76427232f435 856
emh203 0:76427232f435 857
emh203 0:76427232f435 858
emh203 0:76427232f435 859 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 860 /* FAT access - Change value of a FAT entry */
emh203 0:76427232f435 861 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 862 #if !_FS_READONLY
emh203 0:76427232f435 863
emh203 0:76427232f435 864 FRESULT put_fat (
emh203 0:76427232f435 865 FATFS *fs, /* File system object */
emh203 0:76427232f435 866 DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */
emh203 0:76427232f435 867 DWORD val /* New value to mark the cluster */
emh203 0:76427232f435 868 )
emh203 0:76427232f435 869 {
emh203 0:76427232f435 870 UINT bc;
emh203 0:76427232f435 871 BYTE *p;
emh203 0:76427232f435 872 FRESULT res;
emh203 0:76427232f435 873
emh203 0:76427232f435 874
emh203 0:76427232f435 875 if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
emh203 0:76427232f435 876 res = FR_INT_ERR;
emh203 0:76427232f435 877
emh203 0:76427232f435 878 } else {
emh203 0:76427232f435 879 switch (fs->fs_type) {
emh203 0:76427232f435 880 case FS_FAT12 :
emh203 0:76427232f435 881 bc = clst; bc += bc / 2;
emh203 0:76427232f435 882 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
emh203 0:76427232f435 883 if (res != FR_OK) break;
emh203 0:76427232f435 884 p = &fs->win[bc % SS(fs)];
emh203 0:76427232f435 885 *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
emh203 0:76427232f435 886 bc++;
emh203 0:76427232f435 887 fs->wflag = 1;
emh203 0:76427232f435 888 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
emh203 0:76427232f435 889 if (res != FR_OK) break;
emh203 0:76427232f435 890 p = &fs->win[bc % SS(fs)];
emh203 0:76427232f435 891 *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
emh203 0:76427232f435 892 break;
emh203 0:76427232f435 893
emh203 0:76427232f435 894 case FS_FAT16 :
emh203 0:76427232f435 895 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
emh203 0:76427232f435 896 if (res != FR_OK) break;
emh203 0:76427232f435 897 p = &fs->win[clst * 2 % SS(fs)];
emh203 0:76427232f435 898 ST_WORD(p, (WORD)val);
emh203 0:76427232f435 899 break;
emh203 0:76427232f435 900
emh203 0:76427232f435 901 case FS_FAT32 :
emh203 0:76427232f435 902 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
emh203 0:76427232f435 903 if (res != FR_OK) break;
emh203 0:76427232f435 904 p = &fs->win[clst * 4 % SS(fs)];
emh203 0:76427232f435 905 val |= LD_DWORD(p) & 0xF0000000;
emh203 0:76427232f435 906 ST_DWORD(p, val);
emh203 0:76427232f435 907 break;
emh203 0:76427232f435 908
emh203 0:76427232f435 909 default :
emh203 0:76427232f435 910 res = FR_INT_ERR;
emh203 0:76427232f435 911 }
emh203 0:76427232f435 912 fs->wflag = 1;
emh203 0:76427232f435 913 }
emh203 0:76427232f435 914
emh203 0:76427232f435 915 return res;
emh203 0:76427232f435 916 }
emh203 0:76427232f435 917 #endif /* !_FS_READONLY */
emh203 0:76427232f435 918
emh203 0:76427232f435 919
emh203 0:76427232f435 920
emh203 0:76427232f435 921
emh203 0:76427232f435 922 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 923 /* FAT handling - Remove a cluster chain */
emh203 0:76427232f435 924 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 925 #if !_FS_READONLY
emh203 0:76427232f435 926 static
emh203 0:76427232f435 927 FRESULT remove_chain (
emh203 0:76427232f435 928 FATFS *fs, /* File system object */
emh203 0:76427232f435 929 DWORD clst /* Cluster# to remove a chain from */
emh203 0:76427232f435 930 )
emh203 0:76427232f435 931 {
emh203 0:76427232f435 932 FRESULT res;
emh203 0:76427232f435 933 DWORD nxt;
emh203 0:76427232f435 934 #if _USE_ERASE
emh203 0:76427232f435 935 DWORD scl = clst, ecl = clst, resion[2];
emh203 0:76427232f435 936 #endif
emh203 0:76427232f435 937
emh203 0:76427232f435 938 if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
emh203 0:76427232f435 939 res = FR_INT_ERR;
emh203 0:76427232f435 940
emh203 0:76427232f435 941 } else {
emh203 0:76427232f435 942 res = FR_OK;
emh203 0:76427232f435 943 while (clst < fs->n_fatent) { /* Not a last link? */
emh203 0:76427232f435 944 nxt = get_fat(fs, clst); /* Get cluster status */
emh203 0:76427232f435 945 if (nxt == 0) break; /* Empty cluster? */
emh203 0:76427232f435 946 if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */
emh203 0:76427232f435 947 if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */
emh203 0:76427232f435 948 res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */
emh203 0:76427232f435 949 if (res != FR_OK) break;
emh203 0:76427232f435 950 if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */
emh203 0:76427232f435 951 fs->free_clust++;
emh203 0:76427232f435 952 fs->fsi_flag = 1;
emh203 0:76427232f435 953 }
emh203 0:76427232f435 954 #if _USE_ERASE
emh203 0:76427232f435 955 if (ecl + 1 == nxt) { /* Next cluster is contiguous */
emh203 0:76427232f435 956 ecl = nxt;
emh203 0:76427232f435 957 } else { /* End of contiguous clusters */
emh203 0:76427232f435 958 resion[0] = clust2sect(fs, scl); /* Start sector */
emh203 0:76427232f435 959 resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
emh203 0:76427232f435 960 disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */
emh203 0:76427232f435 961 scl = ecl = nxt;
emh203 0:76427232f435 962 }
emh203 0:76427232f435 963 #endif
emh203 0:76427232f435 964 clst = nxt; /* Next cluster */
emh203 0:76427232f435 965 }
emh203 0:76427232f435 966 }
emh203 0:76427232f435 967
emh203 0:76427232f435 968 return res;
emh203 0:76427232f435 969 }
emh203 0:76427232f435 970 #endif
emh203 0:76427232f435 971
emh203 0:76427232f435 972
emh203 0:76427232f435 973
emh203 0:76427232f435 974
emh203 0:76427232f435 975 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 976 /* FAT handling - Stretch or Create a cluster chain */
emh203 0:76427232f435 977 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 978 #if !_FS_READONLY
emh203 0:76427232f435 979 static
emh203 0:76427232f435 980 DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
emh203 0:76427232f435 981 FATFS *fs, /* File system object */
emh203 0:76427232f435 982 DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
emh203 0:76427232f435 983 )
emh203 0:76427232f435 984 {
emh203 0:76427232f435 985 DWORD cs, ncl, scl;
emh203 0:76427232f435 986 FRESULT res;
emh203 0:76427232f435 987
emh203 0:76427232f435 988
emh203 0:76427232f435 989 if (clst == 0) { /* Create a new chain */
emh203 0:76427232f435 990 scl = fs->last_clust; /* Get suggested start point */
emh203 0:76427232f435 991 if (!scl || scl >= fs->n_fatent) scl = 1;
emh203 0:76427232f435 992 }
emh203 0:76427232f435 993 else { /* Stretch the current chain */
emh203 0:76427232f435 994 cs = get_fat(fs, clst); /* Check the cluster status */
emh203 0:76427232f435 995 if (cs < 2) return 1; /* It is an invalid cluster */
emh203 0:76427232f435 996 if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */
emh203 0:76427232f435 997 scl = clst;
emh203 0:76427232f435 998 }
emh203 0:76427232f435 999
emh203 0:76427232f435 1000 ncl = scl; /* Start cluster */
emh203 0:76427232f435 1001 for (;;) {
emh203 0:76427232f435 1002 ncl++; /* Next cluster */
emh203 0:76427232f435 1003 if (ncl >= fs->n_fatent) { /* Wrap around */
emh203 0:76427232f435 1004 ncl = 2;
emh203 0:76427232f435 1005 if (ncl > scl) return 0; /* No free cluster */
emh203 0:76427232f435 1006 }
emh203 0:76427232f435 1007 cs = get_fat(fs, ncl); /* Get the cluster status */
emh203 0:76427232f435 1008 if (cs == 0) break; /* Found a free cluster */
emh203 0:76427232f435 1009 if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
emh203 0:76427232f435 1010 return cs;
emh203 0:76427232f435 1011 if (ncl == scl) return 0; /* No free cluster */
emh203 0:76427232f435 1012 }
emh203 0:76427232f435 1013
emh203 0:76427232f435 1014 res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
emh203 0:76427232f435 1015 if (res == FR_OK && clst != 0) {
emh203 0:76427232f435 1016 res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
emh203 0:76427232f435 1017 }
emh203 0:76427232f435 1018 if (res == FR_OK) {
emh203 0:76427232f435 1019 fs->last_clust = ncl; /* Update FSINFO */
emh203 0:76427232f435 1020 if (fs->free_clust != 0xFFFFFFFF) {
emh203 0:76427232f435 1021 fs->free_clust--;
emh203 0:76427232f435 1022 fs->fsi_flag = 1;
emh203 0:76427232f435 1023 }
emh203 0:76427232f435 1024 } else {
emh203 0:76427232f435 1025 ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
emh203 0:76427232f435 1026 }
emh203 0:76427232f435 1027
emh203 0:76427232f435 1028 return ncl; /* Return new cluster number or error code */
emh203 0:76427232f435 1029 }
emh203 0:76427232f435 1030 #endif /* !_FS_READONLY */
emh203 0:76427232f435 1031
emh203 0:76427232f435 1032
emh203 0:76427232f435 1033
emh203 0:76427232f435 1034 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1035 /* FAT handling - Convert offset into cluster with link map table */
emh203 0:76427232f435 1036 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1037
emh203 0:76427232f435 1038 #if _USE_FASTSEEK
emh203 0:76427232f435 1039 static
emh203 0:76427232f435 1040 DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
emh203 0:76427232f435 1041 FIL* fp, /* Pointer to the file object */
emh203 0:76427232f435 1042 DWORD ofs /* File offset to be converted to cluster# */
emh203 0:76427232f435 1043 )
emh203 0:76427232f435 1044 {
emh203 0:76427232f435 1045 DWORD cl, ncl, *tbl;
emh203 0:76427232f435 1046
emh203 0:76427232f435 1047
emh203 0:76427232f435 1048 tbl = fp->cltbl + 1; /* Top of CLMT */
emh203 0:76427232f435 1049 cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */
emh203 0:76427232f435 1050 for (;;) {
emh203 0:76427232f435 1051 ncl = *tbl++; /* Number of cluters in the fragment */
emh203 0:76427232f435 1052 if (!ncl) return 0; /* End of table? (error) */
emh203 0:76427232f435 1053 if (cl < ncl) break; /* In this fragment? */
emh203 0:76427232f435 1054 cl -= ncl; tbl++; /* Next fragment */
emh203 0:76427232f435 1055 }
emh203 0:76427232f435 1056 return cl + *tbl; /* Return the cluster number */
emh203 0:76427232f435 1057 }
emh203 0:76427232f435 1058 #endif /* _USE_FASTSEEK */
emh203 0:76427232f435 1059
emh203 0:76427232f435 1060
emh203 0:76427232f435 1061
emh203 0:76427232f435 1062 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1063 /* Directory handling - Set directory index */
emh203 0:76427232f435 1064 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1065
emh203 0:76427232f435 1066 static
emh203 0:76427232f435 1067 FRESULT dir_sdi (
emh203 0:76427232f435 1068 eDIR *dj, /* Pointer to directory object */
emh203 0:76427232f435 1069 WORD idx /* Directory index number */
emh203 0:76427232f435 1070 )
emh203 0:76427232f435 1071 {
emh203 0:76427232f435 1072 DWORD clst;
emh203 0:76427232f435 1073 WORD ic;
emh203 0:76427232f435 1074
emh203 0:76427232f435 1075
emh203 0:76427232f435 1076 dj->index = idx;
emh203 0:76427232f435 1077 clst = dj->sclust;
emh203 0:76427232f435 1078 if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */
emh203 0:76427232f435 1079 return FR_INT_ERR;
emh203 0:76427232f435 1080 if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
emh203 0:76427232f435 1081 clst = dj->fs->dirbase;
emh203 0:76427232f435 1082
emh203 0:76427232f435 1083 if (clst == 0) { /* Static table (root-dir in FAT12/16) */
emh203 0:76427232f435 1084 dj->clust = clst;
emh203 0:76427232f435 1085 if (idx >= dj->fs->n_rootdir) /* Index is out of range */
emh203 0:76427232f435 1086 return FR_INT_ERR;
emh203 0:76427232f435 1087 dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */
emh203 0:76427232f435 1088 }
emh203 0:76427232f435 1089 else { /* Dynamic table (sub-dirs or root-dir in FAT32) */
emh203 0:76427232f435 1090 ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */
emh203 0:76427232f435 1091 while (idx >= ic) { /* Follow cluster chain */
emh203 0:76427232f435 1092 clst = get_fat(dj->fs, clst); /* Get next cluster */
emh203 0:76427232f435 1093 if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */
emh203 0:76427232f435 1094 if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */
emh203 0:76427232f435 1095 return FR_INT_ERR;
emh203 0:76427232f435 1096 idx -= ic;
emh203 0:76427232f435 1097 }
emh203 0:76427232f435 1098 dj->clust = clst;
emh203 0:76427232f435 1099 dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */
emh203 0:76427232f435 1100 }
emh203 0:76427232f435 1101
emh203 0:76427232f435 1102 dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */
emh203 0:76427232f435 1103
emh203 0:76427232f435 1104 return FR_OK; /* Seek succeeded */
emh203 0:76427232f435 1105 }
emh203 0:76427232f435 1106
emh203 0:76427232f435 1107
emh203 0:76427232f435 1108
emh203 0:76427232f435 1109
emh203 0:76427232f435 1110 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1111 /* Directory handling - Move directory index next */
emh203 0:76427232f435 1112 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1113
emh203 0:76427232f435 1114 static
emh203 0:76427232f435 1115 FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */
emh203 0:76427232f435 1116 eDIR *dj, /* Pointer to directory object */
emh203 0:76427232f435 1117 int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
emh203 0:76427232f435 1118 )
emh203 0:76427232f435 1119 {
emh203 0:76427232f435 1120 DWORD clst;
emh203 0:76427232f435 1121 WORD i;
emh203 0:76427232f435 1122
emh203 0:76427232f435 1123
emh203 0:76427232f435 1124 stretch = stretch; /* To suppress warning on read-only cfg. */
emh203 0:76427232f435 1125 i = dj->index + 1;
emh203 0:76427232f435 1126 if (!i || !dj->sect) /* Report EOT when index has reached 65535 */
emh203 0:76427232f435 1127 return FR_NO_FILE;
emh203 0:76427232f435 1128
emh203 0:76427232f435 1129 if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */
emh203 0:76427232f435 1130 dj->sect++; /* Next sector */
emh203 0:76427232f435 1131
emh203 0:76427232f435 1132 if (dj->clust == 0) { /* Static table */
emh203 0:76427232f435 1133 if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */
emh203 0:76427232f435 1134 return FR_NO_FILE;
emh203 0:76427232f435 1135 }
emh203 0:76427232f435 1136 else { /* Dynamic table */
emh203 0:76427232f435 1137 if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */
emh203 0:76427232f435 1138 clst = get_fat(dj->fs, dj->clust); /* Get next cluster */
emh203 0:76427232f435 1139 if (clst <= 1) return FR_INT_ERR;
emh203 0:76427232f435 1140 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
emh203 0:76427232f435 1141 if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */
emh203 0:76427232f435 1142 #if !_FS_READONLY
emh203 0:76427232f435 1143 BYTE c;
emh203 0:76427232f435 1144 if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */
emh203 0:76427232f435 1145 clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */
emh203 0:76427232f435 1146 if (clst == 0) return FR_DENIED; /* No free cluster */
emh203 0:76427232f435 1147 if (clst == 1) return FR_INT_ERR;
emh203 0:76427232f435 1148 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
emh203 0:76427232f435 1149 /* Clean-up stretched table */
emh203 0:76427232f435 1150 if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */
emh203 0:76427232f435 1151 mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */
emh203 0:76427232f435 1152 dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */
emh203 0:76427232f435 1153 for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */
emh203 0:76427232f435 1154 dj->fs->wflag = 1;
emh203 0:76427232f435 1155 if (move_window(dj->fs, 0)) return FR_DISK_ERR;
emh203 0:76427232f435 1156 dj->fs->winsect++;
emh203 0:76427232f435 1157 }
emh203 0:76427232f435 1158 dj->fs->winsect -= c; /* Rewind window address */
emh203 0:76427232f435 1159 #else
emh203 0:76427232f435 1160 return FR_NO_FILE; /* Report EOT */
emh203 0:76427232f435 1161 #endif
emh203 0:76427232f435 1162 }
emh203 0:76427232f435 1163 dj->clust = clst; /* Initialize data for new cluster */
emh203 0:76427232f435 1164 dj->sect = clust2sect(dj->fs, clst);
emh203 0:76427232f435 1165 }
emh203 0:76427232f435 1166 }
emh203 0:76427232f435 1167 }
emh203 0:76427232f435 1168
emh203 0:76427232f435 1169 dj->index = i;
emh203 0:76427232f435 1170 dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR;
emh203 0:76427232f435 1171
emh203 0:76427232f435 1172 return FR_OK;
emh203 0:76427232f435 1173 }
emh203 0:76427232f435 1174
emh203 0:76427232f435 1175
emh203 0:76427232f435 1176
emh203 0:76427232f435 1177
emh203 0:76427232f435 1178 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1179 /* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
emh203 0:76427232f435 1180 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1181 #if _USE_LFN
emh203 0:76427232f435 1182 static
emh203 0:76427232f435 1183 const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */
emh203 0:76427232f435 1184
emh203 0:76427232f435 1185
emh203 0:76427232f435 1186 static
emh203 0:76427232f435 1187 int cmp_lfn ( /* 1:Matched, 0:Not matched */
emh203 0:76427232f435 1188 WCHAR *lfnbuf, /* Pointer to the LFN to be compared */
emh203 0:76427232f435 1189 BYTE *dir /* Pointer to the directory entry containing a part of LFN */
emh203 0:76427232f435 1190 )
emh203 0:76427232f435 1191 {
emh203 0:76427232f435 1192 UINT i, s;
emh203 0:76427232f435 1193 WCHAR wc, uc;
emh203 0:76427232f435 1194
emh203 0:76427232f435 1195
emh203 0:76427232f435 1196 i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */
emh203 0:76427232f435 1197 s = 0; wc = 1;
emh203 0:76427232f435 1198 do {
emh203 0:76427232f435 1199 uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */
emh203 0:76427232f435 1200 if (wc) { /* Last char has not been processed */
emh203 0:76427232f435 1201 wc = ff_wtoupper(uc); /* Convert it to upper case */
emh203 0:76427232f435 1202 if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */
emh203 0:76427232f435 1203 return 0; /* Not matched */
emh203 0:76427232f435 1204 } else {
emh203 0:76427232f435 1205 if (uc != 0xFFFF) return 0; /* Check filler */
emh203 0:76427232f435 1206 }
emh203 0:76427232f435 1207 } while (++s < 13); /* Repeat until all chars in the entry are checked */
emh203 0:76427232f435 1208
emh203 0:76427232f435 1209 if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */
emh203 0:76427232f435 1210 return 0;
emh203 0:76427232f435 1211
emh203 0:76427232f435 1212 return 1; /* The part of LFN matched */
emh203 0:76427232f435 1213 }
emh203 0:76427232f435 1214
emh203 0:76427232f435 1215
emh203 0:76427232f435 1216
emh203 0:76427232f435 1217 static
emh203 0:76427232f435 1218 int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
emh203 0:76427232f435 1219 WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */
emh203 0:76427232f435 1220 BYTE *dir /* Pointer to the directory entry */
emh203 0:76427232f435 1221 )
emh203 0:76427232f435 1222 {
emh203 0:76427232f435 1223 UINT i, s;
emh203 0:76427232f435 1224 WCHAR wc, uc;
emh203 0:76427232f435 1225
emh203 0:76427232f435 1226
emh203 0:76427232f435 1227 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
emh203 0:76427232f435 1228
emh203 0:76427232f435 1229 s = 0; wc = 1;
emh203 0:76427232f435 1230 do {
emh203 0:76427232f435 1231 uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */
emh203 0:76427232f435 1232 if (wc) { /* Last char has not been processed */
emh203 0:76427232f435 1233 if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
emh203 0:76427232f435 1234 lfnbuf[i++] = wc = uc; /* Store it */
emh203 0:76427232f435 1235 } else {
emh203 0:76427232f435 1236 if (uc != 0xFFFF) return 0; /* Check filler */
emh203 0:76427232f435 1237 }
emh203 0:76427232f435 1238 } while (++s < 13); /* Read all character in the entry */
emh203 0:76427232f435 1239
emh203 0:76427232f435 1240 if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */
emh203 0:76427232f435 1241 if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
emh203 0:76427232f435 1242 lfnbuf[i] = 0;
emh203 0:76427232f435 1243 }
emh203 0:76427232f435 1244
emh203 0:76427232f435 1245 return 1;
emh203 0:76427232f435 1246 }
emh203 0:76427232f435 1247
emh203 0:76427232f435 1248
emh203 0:76427232f435 1249 #if !_FS_READONLY
emh203 0:76427232f435 1250 static
emh203 0:76427232f435 1251 void fit_lfn (
emh203 0:76427232f435 1252 const WCHAR *lfnbuf, /* Pointer to the LFN buffer */
emh203 0:76427232f435 1253 BYTE *dir, /* Pointer to the directory entry */
emh203 0:76427232f435 1254 BYTE ord, /* LFN order (1-20) */
emh203 0:76427232f435 1255 BYTE sum /* SFN sum */
emh203 0:76427232f435 1256 )
emh203 0:76427232f435 1257 {
emh203 0:76427232f435 1258 UINT i, s;
emh203 0:76427232f435 1259 WCHAR wc;
emh203 0:76427232f435 1260
emh203 0:76427232f435 1261
emh203 0:76427232f435 1262 dir[LDIR_Chksum] = sum; /* Set check sum */
emh203 0:76427232f435 1263 dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
emh203 0:76427232f435 1264 dir[LDIR_Type] = 0;
emh203 0:76427232f435 1265 ST_WORD(dir+LDIR_FstClusLO, 0);
emh203 0:76427232f435 1266
emh203 0:76427232f435 1267 i = (ord - 1) * 13; /* Get offset in the LFN buffer */
emh203 0:76427232f435 1268 s = wc = 0;
emh203 0:76427232f435 1269 do {
emh203 0:76427232f435 1270 if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */
emh203 0:76427232f435 1271 ST_WORD(dir+LfnOfs[s], wc); /* Put it */
emh203 0:76427232f435 1272 if (!wc) wc = 0xFFFF; /* Padding chars following last char */
emh203 0:76427232f435 1273 } while (++s < 13);
emh203 0:76427232f435 1274 if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */
emh203 0:76427232f435 1275 dir[LDIR_Ord] = ord; /* Set the LFN order */
emh203 0:76427232f435 1276 }
emh203 0:76427232f435 1277
emh203 0:76427232f435 1278 #endif
emh203 0:76427232f435 1279 #endif
emh203 0:76427232f435 1280
emh203 0:76427232f435 1281
emh203 0:76427232f435 1282
emh203 0:76427232f435 1283 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1284 /* Create numbered name */
emh203 0:76427232f435 1285 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1286 #if _USE_LFN
emh203 0:76427232f435 1287 void gen_numname (
emh203 0:76427232f435 1288 BYTE *dst, /* Pointer to generated SFN */
emh203 0:76427232f435 1289 const BYTE *src, /* Pointer to source SFN to be modified */
emh203 0:76427232f435 1290 const WCHAR *lfn, /* Pointer to LFN */
emh203 0:76427232f435 1291 WORD seq /* Sequence number */
emh203 0:76427232f435 1292 )
emh203 0:76427232f435 1293 {
emh203 0:76427232f435 1294 BYTE ns[8], c;
emh203 0:76427232f435 1295 UINT i, j;
emh203 0:76427232f435 1296
emh203 0:76427232f435 1297
emh203 0:76427232f435 1298 mem_cpy(dst, src, 11);
emh203 0:76427232f435 1299
emh203 0:76427232f435 1300 if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */
emh203 0:76427232f435 1301 do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn);
emh203 0:76427232f435 1302 }
emh203 0:76427232f435 1303
emh203 0:76427232f435 1304 /* itoa (hexdecimal) */
emh203 0:76427232f435 1305 i = 7;
emh203 0:76427232f435 1306 do {
emh203 0:76427232f435 1307 c = (seq % 16) + '0';
emh203 0:76427232f435 1308 if (c > '9') c += 7;
emh203 0:76427232f435 1309 ns[i--] = c;
emh203 0:76427232f435 1310 seq /= 16;
emh203 0:76427232f435 1311 } while (seq);
emh203 0:76427232f435 1312 ns[i] = '~';
emh203 0:76427232f435 1313
emh203 0:76427232f435 1314 /* Append the number */
emh203 0:76427232f435 1315 for (j = 0; j < i && dst[j] != ' '; j++) {
emh203 0:76427232f435 1316 if (IsDBCS1(dst[j])) {
emh203 0:76427232f435 1317 if (j == i - 1) break;
emh203 0:76427232f435 1318 j++;
emh203 0:76427232f435 1319 }
emh203 0:76427232f435 1320 }
emh203 0:76427232f435 1321 do {
emh203 0:76427232f435 1322 dst[j++] = (i < 8) ? ns[i++] : ' ';
emh203 0:76427232f435 1323 } while (j < 8);
emh203 0:76427232f435 1324 }
emh203 0:76427232f435 1325 #endif
emh203 0:76427232f435 1326
emh203 0:76427232f435 1327
emh203 0:76427232f435 1328
emh203 0:76427232f435 1329
emh203 0:76427232f435 1330 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1331 /* Calculate sum of an SFN */
emh203 0:76427232f435 1332 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1333 #if _USE_LFN
emh203 0:76427232f435 1334 static
emh203 0:76427232f435 1335 BYTE sum_sfn (
emh203 0:76427232f435 1336 const BYTE *dir /* Ptr to directory entry */
emh203 0:76427232f435 1337 )
emh203 0:76427232f435 1338 {
emh203 0:76427232f435 1339 BYTE sum = 0;
emh203 0:76427232f435 1340 UINT n = 11;
emh203 0:76427232f435 1341
emh203 0:76427232f435 1342 do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
emh203 0:76427232f435 1343 return sum;
emh203 0:76427232f435 1344 }
emh203 0:76427232f435 1345 #endif
emh203 0:76427232f435 1346
emh203 0:76427232f435 1347
emh203 0:76427232f435 1348
emh203 0:76427232f435 1349
emh203 0:76427232f435 1350 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1351 /* Directory handling - Find an object in the directory */
emh203 0:76427232f435 1352 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1353
emh203 0:76427232f435 1354 static
emh203 0:76427232f435 1355 FRESULT dir_find (
emh203 0:76427232f435 1356 eDIR *dj /* Pointer to the directory object linked to the file name */
emh203 0:76427232f435 1357 )
emh203 0:76427232f435 1358 {
emh203 0:76427232f435 1359 FRESULT res;
emh203 0:76427232f435 1360 BYTE c, *dir;
emh203 0:76427232f435 1361 #if _USE_LFN
emh203 0:76427232f435 1362 BYTE a, ord, sum;
emh203 0:76427232f435 1363 #endif
emh203 0:76427232f435 1364
emh203 0:76427232f435 1365 res = dir_sdi(dj, 0); /* Rewind directory object */
emh203 0:76427232f435 1366 if (res != FR_OK) return res;
emh203 0:76427232f435 1367
emh203 0:76427232f435 1368 #if _USE_LFN
emh203 0:76427232f435 1369 ord = sum = 0xFF;
emh203 0:76427232f435 1370 #endif
emh203 0:76427232f435 1371 do {
emh203 0:76427232f435 1372 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1373 if (res != FR_OK) break;
emh203 0:76427232f435 1374 dir = dj->dir; /* Ptr to the directory entry of current index */
emh203 0:76427232f435 1375 c = dir[DIR_Name];
emh203 0:76427232f435 1376 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
emh203 0:76427232f435 1377 #if _USE_LFN /* LFN configuration */
emh203 0:76427232f435 1378 a = dir[DIR_Attr] & AM_MASK;
emh203 0:76427232f435 1379 if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
emh203 0:76427232f435 1380 ord = 0xFF;
emh203 0:76427232f435 1381 } else {
emh203 0:76427232f435 1382 if (a == AM_LFN) { /* An LFN entry is found */
emh203 0:76427232f435 1383 if (dj->lfn) {
emh203 0:76427232f435 1384 if (c & LLE) { /* Is it start of LFN sequence? */
emh203 0:76427232f435 1385 sum = dir[LDIR_Chksum];
emh203 0:76427232f435 1386 c &= ~LLE; ord = c; /* LFN start order */
emh203 0:76427232f435 1387 dj->lfn_idx = dj->index;
emh203 0:76427232f435 1388 }
emh203 0:76427232f435 1389 /* Check validity of the LFN entry and compare it with given name */
emh203 0:76427232f435 1390 ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
emh203 0:76427232f435 1391 }
emh203 0:76427232f435 1392 } else { /* An SFN entry is found */
emh203 0:76427232f435 1393 if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */
emh203 0:76427232f435 1394 ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */
emh203 0:76427232f435 1395 if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */
emh203 0:76427232f435 1396 }
emh203 0:76427232f435 1397 }
emh203 0:76427232f435 1398 #else /* Non LFN configuration */
emh203 0:76427232f435 1399 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
emh203 0:76427232f435 1400 break;
emh203 0:76427232f435 1401 #endif
emh203 0:76427232f435 1402 res = dir_next(dj, 0); /* Next entry */
emh203 0:76427232f435 1403 } while (res == FR_OK);
emh203 0:76427232f435 1404
emh203 0:76427232f435 1405 return res;
emh203 0:76427232f435 1406 }
emh203 0:76427232f435 1407
emh203 0:76427232f435 1408
emh203 0:76427232f435 1409
emh203 0:76427232f435 1410
emh203 0:76427232f435 1411 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1412 /* Read an object from the directory */
emh203 0:76427232f435 1413 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1414 #if _FS_MINIMIZE <= 1
emh203 0:76427232f435 1415 static
emh203 0:76427232f435 1416 FRESULT dir_read (
emh203 0:76427232f435 1417 eDIR *dj /* Pointer to the directory object that pointing the entry to be read */
emh203 0:76427232f435 1418 )
emh203 0:76427232f435 1419 {
emh203 0:76427232f435 1420 FRESULT res;
emh203 0:76427232f435 1421 BYTE c, *dir;
emh203 0:76427232f435 1422 #if _USE_LFN
emh203 0:76427232f435 1423 BYTE a, ord = 0xFF, sum = 0xFF;
emh203 0:76427232f435 1424 #endif
emh203 0:76427232f435 1425
emh203 0:76427232f435 1426 res = FR_NO_FILE;
emh203 0:76427232f435 1427 while (dj->sect) {
emh203 0:76427232f435 1428 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1429 if (res != FR_OK) break;
emh203 0:76427232f435 1430 dir = dj->dir; /* Ptr to the directory entry of current index */
emh203 0:76427232f435 1431 c = dir[DIR_Name];
emh203 0:76427232f435 1432 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
emh203 0:76427232f435 1433 #if _USE_LFN /* LFN configuration */
emh203 0:76427232f435 1434 a = dir[DIR_Attr] & AM_MASK;
emh203 0:76427232f435 1435 if (c == DDE || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
emh203 0:76427232f435 1436 ord = 0xFF;
emh203 0:76427232f435 1437 } else {
emh203 0:76427232f435 1438 if (a == AM_LFN) { /* An LFN entry is found */
emh203 0:76427232f435 1439 if (c & LLE) { /* Is it start of LFN sequence? */
emh203 0:76427232f435 1440 sum = dir[LDIR_Chksum];
emh203 0:76427232f435 1441 c &= ~LLE; ord = c;
emh203 0:76427232f435 1442 dj->lfn_idx = dj->index;
emh203 0:76427232f435 1443 }
emh203 0:76427232f435 1444 /* Check LFN validity and capture it */
emh203 0:76427232f435 1445 ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
emh203 0:76427232f435 1446 } else { /* An SFN entry is found */
emh203 0:76427232f435 1447 if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */
emh203 0:76427232f435 1448 dj->lfn_idx = 0xFFFF; /* It has no LFN. */
emh203 0:76427232f435 1449 break;
emh203 0:76427232f435 1450 }
emh203 0:76427232f435 1451 }
emh203 0:76427232f435 1452 #else /* Non LFN configuration */
emh203 0:76427232f435 1453 if (c != DDE && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */
emh203 0:76427232f435 1454 break;
emh203 0:76427232f435 1455 #endif
emh203 0:76427232f435 1456 res = dir_next(dj, 0); /* Next entry */
emh203 0:76427232f435 1457 if (res != FR_OK) break;
emh203 0:76427232f435 1458 }
emh203 0:76427232f435 1459
emh203 0:76427232f435 1460 if (res != FR_OK) dj->sect = 0;
emh203 0:76427232f435 1461
emh203 0:76427232f435 1462 return res;
emh203 0:76427232f435 1463 }
emh203 0:76427232f435 1464 #endif
emh203 0:76427232f435 1465
emh203 0:76427232f435 1466
emh203 0:76427232f435 1467
emh203 0:76427232f435 1468 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1469 /* Register an object to the directory */
emh203 0:76427232f435 1470 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1471 #if !_FS_READONLY
emh203 0:76427232f435 1472 static
emh203 0:76427232f435 1473 FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
emh203 0:76427232f435 1474 eDIR *dj /* Target directory with object name to be created */
emh203 0:76427232f435 1475 )
emh203 0:76427232f435 1476 {
emh203 0:76427232f435 1477 FRESULT res;
emh203 0:76427232f435 1478 BYTE c, *dir;
emh203 0:76427232f435 1479 #if _USE_LFN /* LFN configuration */
emh203 0:76427232f435 1480 WORD n, ne, is;
emh203 0:76427232f435 1481 BYTE sn[12], *fn, sum;
emh203 0:76427232f435 1482 WCHAR *lfn;
emh203 0:76427232f435 1483
emh203 0:76427232f435 1484
emh203 0:76427232f435 1485 fn = dj->fn; lfn = dj->lfn;
emh203 0:76427232f435 1486 mem_cpy(sn, fn, 12);
emh203 0:76427232f435 1487
emh203 0:76427232f435 1488 if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */
emh203 0:76427232f435 1489 return FR_INVALID_NAME;
emh203 0:76427232f435 1490
emh203 0:76427232f435 1491 if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */
emh203 0:76427232f435 1492 fn[NS] = 0; dj->lfn = 0; /* Find only SFN */
emh203 0:76427232f435 1493 for (n = 1; n < 100; n++) {
emh203 0:76427232f435 1494 gen_numname(fn, sn, lfn, n); /* Generate a numbered name */
emh203 0:76427232f435 1495 res = dir_find(dj); /* Check if the name collides with existing SFN */
emh203 0:76427232f435 1496 if (res != FR_OK) break;
emh203 0:76427232f435 1497 }
emh203 0:76427232f435 1498 if (n == 100) return FR_DENIED; /* Abort if too many collisions */
emh203 0:76427232f435 1499 if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */
emh203 0:76427232f435 1500 fn[NS] = sn[NS]; dj->lfn = lfn;
emh203 0:76427232f435 1501 }
emh203 0:76427232f435 1502
emh203 0:76427232f435 1503 if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */
emh203 0:76427232f435 1504 for (ne = 0; lfn[ne]; ne++) ;
emh203 0:76427232f435 1505 ne = (ne + 25) / 13;
emh203 0:76427232f435 1506 } else { /* Otherwise reserve only an SFN entry. */
emh203 0:76427232f435 1507 ne = 1;
emh203 0:76427232f435 1508 }
emh203 0:76427232f435 1509
emh203 0:76427232f435 1510 /* Reserve contiguous entries */
emh203 0:76427232f435 1511 res = dir_sdi(dj, 0);
emh203 0:76427232f435 1512 if (res != FR_OK) return res;
emh203 0:76427232f435 1513 n = is = 0;
emh203 0:76427232f435 1514 do {
emh203 0:76427232f435 1515 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1516 if (res != FR_OK) break;
emh203 0:76427232f435 1517 c = *dj->dir; /* Check the entry status */
emh203 0:76427232f435 1518 if (c == DDE || c == 0) { /* Is it a blank entry? */
emh203 0:76427232f435 1519 if (n == 0) is = dj->index; /* First index of the contiguous entry */
emh203 0:76427232f435 1520 if (++n == ne) break; /* A contiguous entry that required count is found */
emh203 0:76427232f435 1521 } else {
emh203 0:76427232f435 1522 n = 0; /* Not a blank entry. Restart to search */
emh203 0:76427232f435 1523 }
emh203 0:76427232f435 1524 res = dir_next(dj, 1); /* Next entry with table stretch */
emh203 0:76427232f435 1525 } while (res == FR_OK);
emh203 0:76427232f435 1526
emh203 0:76427232f435 1527 if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */
emh203 0:76427232f435 1528 res = dir_sdi(dj, is);
emh203 0:76427232f435 1529 if (res == FR_OK) {
emh203 0:76427232f435 1530 sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */
emh203 0:76427232f435 1531 ne--;
emh203 0:76427232f435 1532 do { /* Store LFN entries in bottom first */
emh203 0:76427232f435 1533 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1534 if (res != FR_OK) break;
emh203 0:76427232f435 1535 fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum);
emh203 0:76427232f435 1536 dj->fs->wflag = 1;
emh203 0:76427232f435 1537 res = dir_next(dj, 0); /* Next entry */
emh203 0:76427232f435 1538 } while (res == FR_OK && --ne);
emh203 0:76427232f435 1539 }
emh203 0:76427232f435 1540 }
emh203 0:76427232f435 1541
emh203 0:76427232f435 1542 #else /* Non LFN configuration */
emh203 0:76427232f435 1543 res = dir_sdi(dj, 0);
emh203 0:76427232f435 1544 if (res == FR_OK) {
emh203 0:76427232f435 1545 do { /* Find a blank entry for the SFN */
emh203 0:76427232f435 1546 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1547 if (res != FR_OK) break;
emh203 0:76427232f435 1548 c = *dj->dir;
emh203 0:76427232f435 1549 if (c == DDE || c == 0) break; /* Is it a blank entry? */
emh203 0:76427232f435 1550 res = dir_next(dj, 1); /* Next entry with table stretch */
emh203 0:76427232f435 1551 } while (res == FR_OK);
emh203 0:76427232f435 1552 }
emh203 0:76427232f435 1553 #endif
emh203 0:76427232f435 1554
emh203 0:76427232f435 1555 if (res == FR_OK) { /* Initialize the SFN entry */
emh203 0:76427232f435 1556 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1557 if (res == FR_OK) {
emh203 0:76427232f435 1558 dir = dj->dir;
emh203 0:76427232f435 1559 mem_set(dir, 0, SZ_DIR); /* Clean the entry */
emh203 0:76427232f435 1560 mem_cpy(dir, dj->fn, 11); /* Put SFN */
emh203 0:76427232f435 1561 #if _USE_LFN
emh203 0:76427232f435 1562 dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */
emh203 0:76427232f435 1563 #endif
emh203 0:76427232f435 1564 dj->fs->wflag = 1;
emh203 0:76427232f435 1565 }
emh203 0:76427232f435 1566 }
emh203 0:76427232f435 1567
emh203 0:76427232f435 1568 return res;
emh203 0:76427232f435 1569 }
emh203 0:76427232f435 1570 #endif /* !_FS_READONLY */
emh203 0:76427232f435 1571
emh203 0:76427232f435 1572
emh203 0:76427232f435 1573
emh203 0:76427232f435 1574
emh203 0:76427232f435 1575 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1576 /* Remove an object from the directory */
emh203 0:76427232f435 1577 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1578 #if !_FS_READONLY && !_FS_MINIMIZE
emh203 0:76427232f435 1579 static
emh203 0:76427232f435 1580 FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
emh203 0:76427232f435 1581 eDIR *dj /* Directory object pointing the entry to be removed */
emh203 0:76427232f435 1582 )
emh203 0:76427232f435 1583 {
emh203 0:76427232f435 1584 FRESULT res;
emh203 0:76427232f435 1585 #if _USE_LFN /* LFN configuration */
emh203 0:76427232f435 1586 WORD i;
emh203 0:76427232f435 1587
emh203 0:76427232f435 1588 i = dj->index; /* SFN index */
emh203 0:76427232f435 1589 res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */
emh203 0:76427232f435 1590 if (res == FR_OK) {
emh203 0:76427232f435 1591 do {
emh203 0:76427232f435 1592 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1593 if (res != FR_OK) break;
emh203 0:76427232f435 1594 *dj->dir = DDE; /* Mark the entry "deleted" */
emh203 0:76427232f435 1595 dj->fs->wflag = 1;
emh203 0:76427232f435 1596 if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */
emh203 0:76427232f435 1597 res = dir_next(dj, 0); /* Next entry */
emh203 0:76427232f435 1598 } while (res == FR_OK);
emh203 0:76427232f435 1599 if (res == FR_NO_FILE) res = FR_INT_ERR;
emh203 0:76427232f435 1600 }
emh203 0:76427232f435 1601
emh203 0:76427232f435 1602 #else /* Non LFN configuration */
emh203 0:76427232f435 1603 res = dir_sdi(dj, dj->index);
emh203 0:76427232f435 1604 if (res == FR_OK) {
emh203 0:76427232f435 1605 res = move_window(dj->fs, dj->sect);
emh203 0:76427232f435 1606 if (res == FR_OK) {
emh203 0:76427232f435 1607 *dj->dir = DDE; /* Mark the entry "deleted" */
emh203 0:76427232f435 1608 dj->fs->wflag = 1;
emh203 0:76427232f435 1609 }
emh203 0:76427232f435 1610 }
emh203 0:76427232f435 1611 #endif
emh203 0:76427232f435 1612
emh203 0:76427232f435 1613 return res;
emh203 0:76427232f435 1614 }
emh203 0:76427232f435 1615 #endif /* !_FS_READONLY */
emh203 0:76427232f435 1616
emh203 0:76427232f435 1617
emh203 0:76427232f435 1618
emh203 0:76427232f435 1619
emh203 0:76427232f435 1620 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1621 /* Pick a segment and create the object name in directory form */
emh203 0:76427232f435 1622 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1623
emh203 0:76427232f435 1624 static
emh203 0:76427232f435 1625 FRESULT create_name (
emh203 0:76427232f435 1626 eDIR *dj, /* Pointer to the directory object */
emh203 0:76427232f435 1627 const TCHAR **path /* Pointer to pointer to the segment in the path string */
emh203 0:76427232f435 1628 )
emh203 0:76427232f435 1629 {
emh203 0:76427232f435 1630 #ifdef _EXCVT
emh203 0:76427232f435 1631 static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */
emh203 0:76427232f435 1632 #endif
emh203 0:76427232f435 1633
emh203 0:76427232f435 1634 #if _USE_LFN /* LFN configuration */
emh203 0:76427232f435 1635 BYTE b, cf;
emh203 0:76427232f435 1636 WCHAR w, *lfn;
emh203 0:76427232f435 1637 UINT i, ni, si, di;
emh203 0:76427232f435 1638 const TCHAR *p;
emh203 0:76427232f435 1639
emh203 0:76427232f435 1640 /* Create LFN in Unicode */
emh203 0:76427232f435 1641 for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
emh203 0:76427232f435 1642 lfn = dj->lfn;
emh203 0:76427232f435 1643 si = di = 0;
emh203 0:76427232f435 1644 for (;;) {
emh203 0:76427232f435 1645 w = p[si++]; /* Get a character */
emh203 0:76427232f435 1646 if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */
emh203 0:76427232f435 1647 if (di >= _MAX_LFN) /* Reject too long name */
emh203 0:76427232f435 1648 return FR_INVALID_NAME;
emh203 0:76427232f435 1649 #if !_LFN_UNICODE
emh203 0:76427232f435 1650 w &= 0xFF;
emh203 0:76427232f435 1651 if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
emh203 0:76427232f435 1652 b = (BYTE)p[si++]; /* Get 2nd byte */
emh203 0:76427232f435 1653 if (!IsDBCS2(b))
emh203 0:76427232f435 1654 return FR_INVALID_NAME; /* Reject invalid sequence */
emh203 0:76427232f435 1655 w = (w << 8) + b; /* Create a DBC */
emh203 0:76427232f435 1656 }
emh203 0:76427232f435 1657 w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */
emh203 0:76427232f435 1658 if (!w) return FR_INVALID_NAME; /* Reject invalid code */
emh203 0:76427232f435 1659 #endif
emh203 0:76427232f435 1660 if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */
emh203 0:76427232f435 1661 return FR_INVALID_NAME;
emh203 0:76427232f435 1662 lfn[di++] = w; /* Store the Unicode char */
emh203 0:76427232f435 1663 }
emh203 0:76427232f435 1664 *path = &p[si]; /* Return pointer to the next segment */
emh203 0:76427232f435 1665 cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
emh203 0:76427232f435 1666 #if _FS_RPATH
emh203 0:76427232f435 1667 if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */
emh203 0:76427232f435 1668 (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) {
emh203 0:76427232f435 1669 lfn[di] = 0;
emh203 0:76427232f435 1670 for (i = 0; i < 11; i++)
emh203 0:76427232f435 1671 dj->fn[i] = (i < di) ? '.' : ' ';
emh203 0:76427232f435 1672 dj->fn[i] = cf | NS_DOT; /* This is a dot entry */
emh203 0:76427232f435 1673 return FR_OK;
emh203 0:76427232f435 1674 }
emh203 0:76427232f435 1675 #endif
emh203 0:76427232f435 1676 while (di) { /* Strip trailing spaces and dots */
emh203 0:76427232f435 1677 w = lfn[di-1];
emh203 0:76427232f435 1678 if (w != ' ' && w != '.') break;
emh203 0:76427232f435 1679 di--;
emh203 0:76427232f435 1680 }
emh203 0:76427232f435 1681 if (!di) return FR_INVALID_NAME; /* Reject nul string */
emh203 0:76427232f435 1682
emh203 0:76427232f435 1683 lfn[di] = 0; /* LFN is created */
emh203 0:76427232f435 1684
emh203 0:76427232f435 1685 /* Create SFN in directory form */
emh203 0:76427232f435 1686 mem_set(dj->fn, ' ', 11);
emh203 0:76427232f435 1687 for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */
emh203 0:76427232f435 1688 if (si) cf |= NS_LOSS | NS_LFN;
emh203 0:76427232f435 1689 while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
emh203 0:76427232f435 1690
emh203 0:76427232f435 1691 b = i = 0; ni = 8;
emh203 0:76427232f435 1692 for (;;) {
emh203 0:76427232f435 1693 w = lfn[si++]; /* Get an LFN char */
emh203 0:76427232f435 1694 if (!w) break; /* Break on end of the LFN */
emh203 0:76427232f435 1695 if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */
emh203 0:76427232f435 1696 cf |= NS_LOSS | NS_LFN; continue;
emh203 0:76427232f435 1697 }
emh203 0:76427232f435 1698
emh203 0:76427232f435 1699 if (i >= ni || si == di) { /* Extension or end of SFN */
emh203 0:76427232f435 1700 if (ni == 11) { /* Long extension */
emh203 0:76427232f435 1701 cf |= NS_LOSS | NS_LFN; break;
emh203 0:76427232f435 1702 }
emh203 0:76427232f435 1703 if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */
emh203 0:76427232f435 1704 if (si > di) break; /* No extension */
emh203 0:76427232f435 1705 si = di; i = 8; ni = 11; /* Enter extension section */
emh203 0:76427232f435 1706 b <<= 2; continue;
emh203 0:76427232f435 1707 }
emh203 0:76427232f435 1708
emh203 0:76427232f435 1709 if (w >= 0x80) { /* Non ASCII char */
emh203 0:76427232f435 1710 #ifdef _EXCVT
emh203 0:76427232f435 1711 w = ff_convert(w, 0); /* Unicode -> OEM code */
emh203 0:76427232f435 1712 if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */
emh203 0:76427232f435 1713 #else
emh203 0:76427232f435 1714 w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */
emh203 0:76427232f435 1715 #endif
emh203 0:76427232f435 1716 cf |= NS_LFN; /* Force create LFN entry */
emh203 0:76427232f435 1717 }
emh203 0:76427232f435 1718
emh203 0:76427232f435 1719 if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */
emh203 0:76427232f435 1720 if (i >= ni - 1) {
emh203 0:76427232f435 1721 cf |= NS_LOSS | NS_LFN; i = ni; continue;
emh203 0:76427232f435 1722 }
emh203 0:76427232f435 1723 dj->fn[i++] = (BYTE)(w >> 8);
emh203 0:76427232f435 1724 } else { /* Single byte char */
emh203 0:76427232f435 1725 if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */
emh203 0:76427232f435 1726 w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
emh203 0:76427232f435 1727 } else {
emh203 0:76427232f435 1728 if (IsUpper(w)) { /* ASCII large capital */
emh203 0:76427232f435 1729 b |= 2;
emh203 0:76427232f435 1730 } else {
emh203 0:76427232f435 1731 if (IsLower(w)) { /* ASCII small capital */
emh203 0:76427232f435 1732 b |= 1; w -= 0x20;
emh203 0:76427232f435 1733 }
emh203 0:76427232f435 1734 }
emh203 0:76427232f435 1735 }
emh203 0:76427232f435 1736 }
emh203 0:76427232f435 1737 dj->fn[i++] = (BYTE)w;
emh203 0:76427232f435 1738 }
emh203 0:76427232f435 1739
emh203 0:76427232f435 1740 if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */
emh203 0:76427232f435 1741
emh203 0:76427232f435 1742 if (ni == 8) b <<= 2;
emh203 0:76427232f435 1743 if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */
emh203 0:76427232f435 1744 cf |= NS_LFN;
emh203 0:76427232f435 1745 if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */
emh203 0:76427232f435 1746 if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */
emh203 0:76427232f435 1747 if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */
emh203 0:76427232f435 1748 }
emh203 0:76427232f435 1749
emh203 0:76427232f435 1750 dj->fn[NS] = cf; /* SFN is created */
emh203 0:76427232f435 1751
emh203 0:76427232f435 1752 return FR_OK;
emh203 0:76427232f435 1753
emh203 0:76427232f435 1754
emh203 0:76427232f435 1755 #else /* Non-LFN configuration */
emh203 0:76427232f435 1756 BYTE b, c, d, *sfn;
emh203 0:76427232f435 1757 UINT ni, si, i;
emh203 0:76427232f435 1758 const char *p;
emh203 0:76427232f435 1759
emh203 0:76427232f435 1760 /* Create file name in directory form */
emh203 0:76427232f435 1761 for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
emh203 0:76427232f435 1762 sfn = dj->fn;
emh203 0:76427232f435 1763 mem_set(sfn, ' ', 11);
emh203 0:76427232f435 1764 si = i = b = 0; ni = 8;
emh203 0:76427232f435 1765 #if _FS_RPATH
emh203 0:76427232f435 1766 if (p[si] == '.') { /* Is this a dot entry? */
emh203 0:76427232f435 1767 for (;;) {
emh203 0:76427232f435 1768 c = (BYTE)p[si++];
emh203 0:76427232f435 1769 if (c != '.' || si >= 3) break;
emh203 0:76427232f435 1770 sfn[i++] = c;
emh203 0:76427232f435 1771 }
emh203 0:76427232f435 1772 if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
emh203 0:76427232f435 1773 *path = &p[si]; /* Return pointer to the next segment */
emh203 0:76427232f435 1774 sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */
emh203 0:76427232f435 1775 return FR_OK;
emh203 0:76427232f435 1776 }
emh203 0:76427232f435 1777 #endif
emh203 0:76427232f435 1778 for (;;) {
emh203 0:76427232f435 1779 c = (BYTE)p[si++];
emh203 0:76427232f435 1780 if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */
emh203 0:76427232f435 1781 if (c == '.' || i >= ni) {
emh203 0:76427232f435 1782 if (ni != 8 || c != '.') return FR_INVALID_NAME;
emh203 0:76427232f435 1783 i = 8; ni = 11;
emh203 0:76427232f435 1784 b <<= 2; continue;
emh203 0:76427232f435 1785 }
emh203 0:76427232f435 1786 if (c >= 0x80) { /* Extended char? */
emh203 0:76427232f435 1787 b |= 3; /* Eliminate NT flag */
emh203 0:76427232f435 1788 #ifdef _EXCVT
emh203 0:76427232f435 1789 c = excvt[c-0x80]; /* Upper conversion (SBCS) */
emh203 0:76427232f435 1790 #else
emh203 0:76427232f435 1791 #if !_DF1S /* ASCII only cfg */
emh203 0:76427232f435 1792 return FR_INVALID_NAME;
emh203 0:76427232f435 1793 #endif
emh203 0:76427232f435 1794 #endif
emh203 0:76427232f435 1795 }
emh203 0:76427232f435 1796 if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
emh203 0:76427232f435 1797 d = (BYTE)p[si++]; /* Get 2nd byte */
emh203 0:76427232f435 1798 if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
emh203 0:76427232f435 1799 return FR_INVALID_NAME;
emh203 0:76427232f435 1800 sfn[i++] = c;
emh203 0:76427232f435 1801 sfn[i++] = d;
emh203 0:76427232f435 1802 } else { /* Single byte code */
emh203 0:76427232f435 1803 if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */
emh203 0:76427232f435 1804 return FR_INVALID_NAME;
emh203 0:76427232f435 1805 if (IsUpper(c)) { /* ASCII large capital? */
emh203 0:76427232f435 1806 b |= 2;
emh203 0:76427232f435 1807 } else {
emh203 0:76427232f435 1808 if (IsLower(c)) { /* ASCII small capital? */
emh203 0:76427232f435 1809 b |= 1; c -= 0x20;
emh203 0:76427232f435 1810 }
emh203 0:76427232f435 1811 }
emh203 0:76427232f435 1812 sfn[i++] = c;
emh203 0:76427232f435 1813 }
emh203 0:76427232f435 1814 }
emh203 0:76427232f435 1815 *path = &p[si]; /* Return pointer to the next segment */
emh203 0:76427232f435 1816 c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
emh203 0:76427232f435 1817
emh203 0:76427232f435 1818 if (!i) return FR_INVALID_NAME; /* Reject nul string */
emh203 0:76427232f435 1819 if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */
emh203 0:76427232f435 1820
emh203 0:76427232f435 1821 if (ni == 8) b <<= 2;
emh203 0:76427232f435 1822 if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */
emh203 0:76427232f435 1823 if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */
emh203 0:76427232f435 1824
emh203 0:76427232f435 1825 sfn[NS] = c; /* Store NT flag, File name is created */
emh203 0:76427232f435 1826
emh203 0:76427232f435 1827 return FR_OK;
emh203 0:76427232f435 1828 #endif
emh203 0:76427232f435 1829 }
emh203 0:76427232f435 1830
emh203 0:76427232f435 1831
emh203 0:76427232f435 1832
emh203 0:76427232f435 1833
emh203 0:76427232f435 1834 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1835 /* Get file information from directory entry */
emh203 0:76427232f435 1836 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1837 #if _FS_MINIMIZE <= 1
emh203 0:76427232f435 1838 static
emh203 0:76427232f435 1839 void get_fileinfo ( /* No return code */
emh203 0:76427232f435 1840 eDIR *dj, /* Pointer to the directory object */
emh203 0:76427232f435 1841 FILINFO *fno /* Pointer to the file information to be filled */
emh203 0:76427232f435 1842 )
emh203 0:76427232f435 1843 {
emh203 0:76427232f435 1844 UINT i;
emh203 0:76427232f435 1845 BYTE nt, *dir;
emh203 0:76427232f435 1846 TCHAR *p, c;
emh203 0:76427232f435 1847
emh203 0:76427232f435 1848
emh203 0:76427232f435 1849 p = fno->fname;
emh203 0:76427232f435 1850 if (dj->sect) {
emh203 0:76427232f435 1851 dir = dj->dir;
emh203 0:76427232f435 1852 nt = dir[DIR_NTres]; /* NT flag */
emh203 0:76427232f435 1853 for (i = 0; i < 8; i++) { /* Copy name body */
emh203 0:76427232f435 1854 c = dir[i];
emh203 0:76427232f435 1855 if (c == ' ') break;
emh203 0:76427232f435 1856 if (c == NDDE) c = (TCHAR)DDE;
emh203 0:76427232f435 1857 if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20;
emh203 0:76427232f435 1858 #if _LFN_UNICODE
emh203 0:76427232f435 1859 if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1]))
emh203 0:76427232f435 1860 c = (c << 8) | dir[++i];
emh203 0:76427232f435 1861 c = ff_convert(c, 1);
emh203 0:76427232f435 1862 if (!c) c = '?';
emh203 0:76427232f435 1863 #endif
emh203 0:76427232f435 1864 *p++ = c;
emh203 0:76427232f435 1865 }
emh203 0:76427232f435 1866 if (dir[8] != ' ') { /* Copy name extension */
emh203 0:76427232f435 1867 *p++ = '.';
emh203 0:76427232f435 1868 for (i = 8; i < 11; i++) {
emh203 0:76427232f435 1869 c = dir[i];
emh203 0:76427232f435 1870 if (c == ' ') break;
emh203 0:76427232f435 1871 if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20;
emh203 0:76427232f435 1872 #if _LFN_UNICODE
emh203 0:76427232f435 1873 if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1]))
emh203 0:76427232f435 1874 c = (c << 8) | dir[++i];
emh203 0:76427232f435 1875 c = ff_convert(c, 1);
emh203 0:76427232f435 1876 if (!c) c = '?';
emh203 0:76427232f435 1877 #endif
emh203 0:76427232f435 1878 *p++ = c;
emh203 0:76427232f435 1879 }
emh203 0:76427232f435 1880 }
emh203 0:76427232f435 1881 fno->fattrib = dir[DIR_Attr]; /* Attribute */
emh203 0:76427232f435 1882 fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */
emh203 0:76427232f435 1883 fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */
emh203 0:76427232f435 1884 fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */
emh203 0:76427232f435 1885 }
emh203 0:76427232f435 1886 *p = 0; /* Terminate SFN str by a \0 */
emh203 0:76427232f435 1887
emh203 0:76427232f435 1888 #if _USE_LFN
emh203 0:76427232f435 1889 if (fno->lfname && fno->lfsize) {
emh203 0:76427232f435 1890 TCHAR *tp = fno->lfname;
emh203 0:76427232f435 1891 WCHAR w, *lfn;
emh203 0:76427232f435 1892
emh203 0:76427232f435 1893 i = 0;
emh203 0:76427232f435 1894 if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */
emh203 0:76427232f435 1895 lfn = dj->lfn;
emh203 0:76427232f435 1896 while ((w = *lfn++) != 0) { /* Get an LFN char */
emh203 0:76427232f435 1897 #if !_LFN_UNICODE
emh203 0:76427232f435 1898 w = ff_convert(w, 0); /* Unicode -> OEM conversion */
emh203 0:76427232f435 1899 if (!w) { i = 0; break; } /* Could not convert, no LFN */
emh203 0:76427232f435 1900 if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */
emh203 0:76427232f435 1901 tp[i++] = (TCHAR)(w >> 8);
emh203 0:76427232f435 1902 #endif
emh203 0:76427232f435 1903 if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */
emh203 0:76427232f435 1904 tp[i++] = (TCHAR)w;
emh203 0:76427232f435 1905 }
emh203 0:76427232f435 1906 }
emh203 0:76427232f435 1907 tp[i] = 0; /* Terminate the LFN str by a \0 */
emh203 0:76427232f435 1908 }
emh203 0:76427232f435 1909 #endif
emh203 0:76427232f435 1910 }
emh203 0:76427232f435 1911 #endif /* _FS_MINIMIZE <= 1 */
emh203 0:76427232f435 1912
emh203 0:76427232f435 1913
emh203 0:76427232f435 1914
emh203 0:76427232f435 1915
emh203 0:76427232f435 1916 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1917 /* Follow a file path */
emh203 0:76427232f435 1918 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1919
emh203 0:76427232f435 1920 static
emh203 0:76427232f435 1921 FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
emh203 0:76427232f435 1922 eDIR *dj, /* Directory object to return last directory and found object */
emh203 0:76427232f435 1923 const TCHAR *path /* Full-path string to find a file or directory */
emh203 0:76427232f435 1924 )
emh203 0:76427232f435 1925 {
emh203 0:76427232f435 1926 FRESULT res;
emh203 0:76427232f435 1927 BYTE *dir, ns;
emh203 0:76427232f435 1928
emh203 0:76427232f435 1929
emh203 0:76427232f435 1930 #if _FS_RPATH
emh203 0:76427232f435 1931 if (*path == '/' || *path == '\\') { /* There is a heading separator */
emh203 0:76427232f435 1932 path++; dj->sclust = 0; /* Strip it and start from the root dir */
emh203 0:76427232f435 1933 } else { /* No heading separator */
emh203 0:76427232f435 1934 dj->sclust = dj->fs->cdir; /* Start from the current dir */
emh203 0:76427232f435 1935 }
emh203 0:76427232f435 1936 #else
emh203 0:76427232f435 1937 if (*path == '/' || *path == '\\') /* Strip heading separator if exist */
emh203 0:76427232f435 1938 path++;
emh203 0:76427232f435 1939 dj->sclust = 0; /* Start from the root dir */
emh203 0:76427232f435 1940 #endif
emh203 0:76427232f435 1941
emh203 0:76427232f435 1942 if ((UINT)*path < ' ') { /* Nul path means the start directory itself */
emh203 0:76427232f435 1943 res = dir_sdi(dj, 0);
emh203 0:76427232f435 1944 dj->dir = 0;
emh203 0:76427232f435 1945
emh203 0:76427232f435 1946 } else { /* Follow path */
emh203 0:76427232f435 1947 for (;;) {
emh203 0:76427232f435 1948 res = create_name(dj, &path); /* Get a segment */
emh203 0:76427232f435 1949 if (res != FR_OK) break;
emh203 0:76427232f435 1950 res = dir_find(dj); /* Find it */
emh203 0:76427232f435 1951 ns = *(dj->fn+NS);
emh203 0:76427232f435 1952 if (res != FR_OK) { /* Failed to find the object */
emh203 0:76427232f435 1953 if (res != FR_NO_FILE) break; /* Abort if any hard error occured */
emh203 0:76427232f435 1954 /* Object not found */
emh203 0:76427232f435 1955 if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */
emh203 0:76427232f435 1956 dj->sclust = 0; dj->dir = 0; /* It is the root dir */
emh203 0:76427232f435 1957 res = FR_OK;
emh203 0:76427232f435 1958 if (!(ns & NS_LAST)) continue;
emh203 0:76427232f435 1959 } else { /* Could not find the object */
emh203 0:76427232f435 1960 if (!(ns & NS_LAST)) res = FR_NO_PATH;
emh203 0:76427232f435 1961 }
emh203 0:76427232f435 1962 break;
emh203 0:76427232f435 1963 }
emh203 0:76427232f435 1964 if (ns & NS_LAST) break; /* Last segment match. Function completed. */
emh203 0:76427232f435 1965 dir = dj->dir; /* There is next segment. Follow the sub directory */
emh203 0:76427232f435 1966 if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
emh203 0:76427232f435 1967 res = FR_NO_PATH; break;
emh203 0:76427232f435 1968 }
emh203 0:76427232f435 1969 dj->sclust = LD_CLUST(dir);
emh203 0:76427232f435 1970 }
emh203 0:76427232f435 1971 }
emh203 0:76427232f435 1972
emh203 0:76427232f435 1973 return res;
emh203 0:76427232f435 1974 }
emh203 0:76427232f435 1975
emh203 0:76427232f435 1976
emh203 0:76427232f435 1977
emh203 0:76427232f435 1978
emh203 0:76427232f435 1979 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1980 /* Load a sector and check if it is an FAT Volume Boot Record */
emh203 0:76427232f435 1981 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 1982
emh203 0:76427232f435 1983 static
emh203 0:76427232f435 1984 BYTE check_fs ( /* 0:FAT-VBR, 1:Valid BR but not FAT, 2:Not a BR, 3:Disk error */
emh203 0:76427232f435 1985 FATFS *fs, /* File system object */
emh203 0:76427232f435 1986 DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
emh203 0:76427232f435 1987 )
emh203 0:76427232f435 1988 {
emh203 0:76427232f435 1989 if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */
emh203 0:76427232f435 1990 return 3;
emh203 0:76427232f435 1991 if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */
emh203 0:76427232f435 1992 return 2;
emh203 0:76427232f435 1993
emh203 0:76427232f435 1994 if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */
emh203 0:76427232f435 1995 return 0;
emh203 0:76427232f435 1996 if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
emh203 0:76427232f435 1997 return 0;
emh203 0:76427232f435 1998
emh203 0:76427232f435 1999 return 1;
emh203 0:76427232f435 2000 }
emh203 0:76427232f435 2001
emh203 0:76427232f435 2002
emh203 0:76427232f435 2003
emh203 0:76427232f435 2004
emh203 0:76427232f435 2005 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2006 /* Check if the file system object is valid or not */
emh203 0:76427232f435 2007 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2008
emh203 0:76427232f435 2009 static
emh203 0:76427232f435 2010 FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
emh203 0:76427232f435 2011 const TCHAR **path, /* Pointer to pointer to the path name (drive number) */
emh203 0:76427232f435 2012 FATFS **rfs, /* Pointer to pointer to the found file system object */
emh203 0:76427232f435 2013 BYTE chk_wp /* !=0: Check media write protection for write access */
emh203 0:76427232f435 2014 )
emh203 0:76427232f435 2015 {
emh203 0:76427232f435 2016 BYTE fmt, b, pi, *tbl;
emh203 0:76427232f435 2017 UINT vol;
emh203 0:76427232f435 2018 DSTATUS stat;
emh203 0:76427232f435 2019 DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
emh203 0:76427232f435 2020 WORD nrsv;
emh203 0:76427232f435 2021 const TCHAR *p = *path;
emh203 0:76427232f435 2022 FATFS *fs;
emh203 0:76427232f435 2023
emh203 0:76427232f435 2024 /* Get logical drive number from the path name */
emh203 0:76427232f435 2025 vol = p[0] - '0'; /* Is there a drive number? */
emh203 0:76427232f435 2026 if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */
emh203 0:76427232f435 2027 p += 2; *path = p; /* Return pointer to the path name */
emh203 0:76427232f435 2028 } else { /* No drive number is given */
emh203 0:76427232f435 2029 #if _FS_RPATH
emh203 0:76427232f435 2030 vol = CurrVol; /* Use current drive */
emh203 0:76427232f435 2031 #else
emh203 0:76427232f435 2032 vol = 0; /* Use drive 0 */
emh203 0:76427232f435 2033 #endif
emh203 0:76427232f435 2034 }
emh203 0:76427232f435 2035
emh203 0:76427232f435 2036 /* Check if the file system object is valid or not */
emh203 0:76427232f435 2037 if (vol >= _VOLUMES) /* Is the drive number valid? */
emh203 0:76427232f435 2038 return FR_INVALID_DRIVE;
emh203 0:76427232f435 2039 *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */
emh203 0:76427232f435 2040 if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
emh203 0:76427232f435 2041
emh203 0:76427232f435 2042 ENTER_FF(fs); /* Lock file system */
emh203 0:76427232f435 2043
emh203 0:76427232f435 2044 if (fs->fs_type) { /* If the logical drive has been mounted */
emh203 0:76427232f435 2045 stat = disk_status(fs->drv);
emh203 0:76427232f435 2046 if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */
emh203 0:76427232f435 2047 if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
emh203 0:76427232f435 2048 return FR_WRITE_PROTECTED;
emh203 0:76427232f435 2049 return FR_OK; /* The file system object is valid */
emh203 0:76427232f435 2050 }
emh203 0:76427232f435 2051 }
emh203 0:76427232f435 2052
emh203 0:76427232f435 2053 /* The file system object is not valid. */
emh203 0:76427232f435 2054 /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
emh203 0:76427232f435 2055
emh203 0:76427232f435 2056 fs->fs_type = 0; /* Clear the file system object */
emh203 0:76427232f435 2057 fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
emh203 0:76427232f435 2058 stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */
emh203 0:76427232f435 2059 if (stat & STA_NOINIT) /* Check if the initialization succeeded */
emh203 0:76427232f435 2060 return FR_NOT_READY; /* Failed to initialize due to no media or hard error */
emh203 0:76427232f435 2061 if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */
emh203 0:76427232f435 2062 return FR_WRITE_PROTECTED;
emh203 0:76427232f435 2063 #if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */
emh203 0:76427232f435 2064 if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
emh203 0:76427232f435 2065 return FR_DISK_ERR;
emh203 0:76427232f435 2066 #endif
emh203 0:76427232f435 2067 /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */
emh203 0:76427232f435 2068 fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */
emh203 0:76427232f435 2069 if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */
emh203 0:76427232f435 2070 if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */
emh203 0:76427232f435 2071 /* Check the partition listed in the partition table */
emh203 0:76427232f435 2072 pi = LD2PT(vol);
emh203 0:76427232f435 2073 if (pi) pi--;
emh203 0:76427232f435 2074 tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
emh203 0:76427232f435 2075 if (tbl[4]) { /* Is the partition existing? */
emh203 0:76427232f435 2076 bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
emh203 0:76427232f435 2077 fmt = check_fs(fs, bsect); /* Check the partition */
emh203 0:76427232f435 2078 }
emh203 0:76427232f435 2079 }
emh203 0:76427232f435 2080 if (fmt == 3) return FR_DISK_ERR;
emh203 0:76427232f435 2081 if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
emh203 0:76427232f435 2082
emh203 0:76427232f435 2083 /* An FAT volume is found. Following code initializes the file system object */
emh203 0:76427232f435 2084
emh203 0:76427232f435 2085 if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
emh203 0:76427232f435 2086 return FR_NO_FILESYSTEM;
emh203 0:76427232f435 2087
emh203 0:76427232f435 2088 fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */
emh203 0:76427232f435 2089 if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32);
emh203 0:76427232f435 2090 fs->fsize = fasize;
emh203 0:76427232f435 2091
emh203 0:76427232f435 2092 fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */
emh203 0:76427232f435 2093 if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
emh203 0:76427232f435 2094 fasize *= b; /* Number of sectors for FAT area */
emh203 0:76427232f435 2095
emh203 0:76427232f435 2096 fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
emh203 0:76427232f435 2097 if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */
emh203 0:76427232f435 2098
emh203 0:76427232f435 2099 fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */
emh203 0:76427232f435 2100 if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */
emh203 0:76427232f435 2101
emh203 0:76427232f435 2102 tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */
emh203 0:76427232f435 2103 if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32);
emh203 0:76427232f435 2104
emh203 0:76427232f435 2105 nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */
emh203 0:76427232f435 2106 if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */
emh203 0:76427232f435 2107
emh203 0:76427232f435 2108 /* Determine the FAT sub type */
emh203 0:76427232f435 2109 sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */
emh203 0:76427232f435 2110 if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
emh203 0:76427232f435 2111 nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
emh203 0:76427232f435 2112 if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
emh203 0:76427232f435 2113 fmt = FS_FAT12;
emh203 0:76427232f435 2114 if (nclst >= MIN_FAT16) fmt = FS_FAT16;
emh203 0:76427232f435 2115 if (nclst >= MIN_FAT32) fmt = FS_FAT32;
emh203 0:76427232f435 2116
emh203 0:76427232f435 2117 /* Boundaries and Limits */
emh203 0:76427232f435 2118 fs->n_fatent = nclst + 2; /* Number of FAT entries */
emh203 0:76427232f435 2119 fs->database = bsect + sysect; /* Data start sector */
emh203 0:76427232f435 2120 fs->fatbase = bsect + nrsv; /* FAT start sector */
emh203 0:76427232f435 2121 if (fmt == FS_FAT32) {
emh203 0:76427232f435 2122 if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
emh203 0:76427232f435 2123 fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */
emh203 0:76427232f435 2124 szbfat = fs->n_fatent * 4; /* (Required FAT size) */
emh203 0:76427232f435 2125 } else {
emh203 0:76427232f435 2126 if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
emh203 0:76427232f435 2127 fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
emh203 0:76427232f435 2128 szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */
emh203 0:76427232f435 2129 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
emh203 0:76427232f435 2130 }
emh203 0:76427232f435 2131 if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */
emh203 0:76427232f435 2132 return FR_NO_FILESYSTEM;
emh203 0:76427232f435 2133
emh203 0:76427232f435 2134 #if !_FS_READONLY
emh203 0:76427232f435 2135 /* Initialize cluster allocation information */
emh203 0:76427232f435 2136 fs->free_clust = 0xFFFFFFFF;
emh203 0:76427232f435 2137 fs->last_clust = 0;
emh203 0:76427232f435 2138
emh203 0:76427232f435 2139 /* Get fsinfo if available */
emh203 0:76427232f435 2140 if (fmt == FS_FAT32) {
emh203 0:76427232f435 2141 fs->fsi_flag = 0;
emh203 0:76427232f435 2142 fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo);
emh203 0:76427232f435 2143 if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK &&
emh203 0:76427232f435 2144 LD_WORD(fs->win+BS_55AA) == 0xAA55 &&
emh203 0:76427232f435 2145 LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 &&
emh203 0:76427232f435 2146 LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) {
emh203 0:76427232f435 2147 fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free);
emh203 0:76427232f435 2148 fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count);
emh203 0:76427232f435 2149 }
emh203 0:76427232f435 2150 }
emh203 0:76427232f435 2151 #endif
emh203 0:76427232f435 2152 fs->fs_type = fmt; /* FAT sub-type */
emh203 0:76427232f435 2153 fs->id = ++Fsid; /* File system mount ID */
emh203 0:76427232f435 2154 fs->winsect = 0; /* Invalidate sector cache */
emh203 0:76427232f435 2155 fs->wflag = 0;
emh203 0:76427232f435 2156 #if _FS_RPATH
emh203 0:76427232f435 2157 fs->cdir = 0; /* Current directory (root dir) */
emh203 0:76427232f435 2158 #endif
emh203 0:76427232f435 2159 #if _FS_SHARE /* Clear file lock semaphores */
emh203 0:76427232f435 2160 clear_lock(fs);
emh203 0:76427232f435 2161 #endif
emh203 0:76427232f435 2162
emh203 0:76427232f435 2163 return FR_OK;
emh203 0:76427232f435 2164 }
emh203 0:76427232f435 2165
emh203 0:76427232f435 2166
emh203 0:76427232f435 2167
emh203 0:76427232f435 2168
emh203 0:76427232f435 2169 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2170 /* Check if the file/dir object is valid or not */
emh203 0:76427232f435 2171 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2172
emh203 0:76427232f435 2173 static
emh203 0:76427232f435 2174 FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
emh203 0:76427232f435 2175 FATFS *fs, /* Pointer to the file system object */
emh203 0:76427232f435 2176 WORD id /* Member id of the target object to be checked */
emh203 0:76427232f435 2177 )
emh203 0:76427232f435 2178 {
emh203 0:76427232f435 2179 if (!fs || !fs->fs_type || fs->id != id)
emh203 0:76427232f435 2180 return FR_INVALID_OBJECT;
emh203 0:76427232f435 2181
emh203 0:76427232f435 2182 ENTER_FF(fs); /* Lock file system */
emh203 0:76427232f435 2183
emh203 0:76427232f435 2184 if (disk_status(fs->drv) & STA_NOINIT)
emh203 0:76427232f435 2185 return FR_NOT_READY;
emh203 0:76427232f435 2186
emh203 0:76427232f435 2187 return FR_OK;
emh203 0:76427232f435 2188 }
emh203 0:76427232f435 2189
emh203 0:76427232f435 2190
emh203 0:76427232f435 2191
emh203 0:76427232f435 2192
emh203 0:76427232f435 2193 /*--------------------------------------------------------------------------
emh203 0:76427232f435 2194
emh203 0:76427232f435 2195 Public Functions
emh203 0:76427232f435 2196
emh203 0:76427232f435 2197 --------------------------------------------------------------------------*/
emh203 0:76427232f435 2198
emh203 0:76427232f435 2199
emh203 0:76427232f435 2200
emh203 0:76427232f435 2201 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2202 /* Mount/Unmount a Logical Drive */
emh203 0:76427232f435 2203 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2204
emh203 0:76427232f435 2205 FRESULT f_mount (
emh203 0:76427232f435 2206 BYTE vol, /* Logical drive number to be mounted/unmounted */
emh203 0:76427232f435 2207 FATFS *fs /* Pointer to new file system object (NULL for unmount)*/
emh203 0:76427232f435 2208 )
emh203 0:76427232f435 2209 {
emh203 0:76427232f435 2210 FATFS *rfs;
emh203 0:76427232f435 2211
emh203 0:76427232f435 2212
emh203 0:76427232f435 2213 if (vol >= _VOLUMES) /* Check if the drive number is valid */
emh203 0:76427232f435 2214 return FR_INVALID_DRIVE;
emh203 0:76427232f435 2215 rfs = FatFs[vol]; /* Get current fs object */
emh203 0:76427232f435 2216
emh203 0:76427232f435 2217 if (rfs) {
emh203 0:76427232f435 2218 #if _FS_SHARE
emh203 0:76427232f435 2219 clear_lock(rfs);
emh203 0:76427232f435 2220 #endif
emh203 0:76427232f435 2221 #if _FS_REENTRANT /* Discard sync object of the current volume */
emh203 0:76427232f435 2222 if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
emh203 0:76427232f435 2223 #endif
emh203 0:76427232f435 2224 rfs->fs_type = 0; /* Clear old fs object */
emh203 0:76427232f435 2225 }
emh203 0:76427232f435 2226
emh203 0:76427232f435 2227 if (fs) {
emh203 0:76427232f435 2228 fs->fs_type = 0; /* Clear new fs object */
emh203 0:76427232f435 2229 #if _FS_REENTRANT /* Create sync object for the new volume */
emh203 0:76427232f435 2230 if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
emh203 0:76427232f435 2231 #endif
emh203 0:76427232f435 2232 }
emh203 0:76427232f435 2233 FatFs[vol] = fs; /* Register new fs object */
emh203 0:76427232f435 2234
emh203 0:76427232f435 2235 return FR_OK;
emh203 0:76427232f435 2236 }
emh203 0:76427232f435 2237
emh203 0:76427232f435 2238
emh203 0:76427232f435 2239
emh203 0:76427232f435 2240
emh203 0:76427232f435 2241 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2242 /* Open or Create a File */
emh203 0:76427232f435 2243 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2244
emh203 0:76427232f435 2245 FRESULT f_open (
emh203 0:76427232f435 2246 FIL *fp, /* Pointer to the blank file object */
emh203 0:76427232f435 2247 const TCHAR *path, /* Pointer to the file name */
emh203 0:76427232f435 2248 BYTE mode /* Access mode and file open mode flags */
emh203 0:76427232f435 2249 )
emh203 0:76427232f435 2250 {
emh203 0:76427232f435 2251 FRESULT res;
emh203 0:76427232f435 2252 eDIR dj;
emh203 0:76427232f435 2253 BYTE *dir;
emh203 0:76427232f435 2254 DEF_NAMEBUF;
emh203 0:76427232f435 2255
emh203 0:76427232f435 2256
emh203 0:76427232f435 2257 fp->fs = 0; /* Clear file object */
emh203 0:76427232f435 2258
emh203 0:76427232f435 2259 #if !_FS_READONLY
emh203 0:76427232f435 2260 mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
emh203 0:76427232f435 2261 res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ));
emh203 0:76427232f435 2262 #else
emh203 0:76427232f435 2263 mode &= FA_READ;
emh203 0:76427232f435 2264 res = chk_mounted(&path, &dj.fs, 0);
emh203 0:76427232f435 2265 #endif
emh203 0:76427232f435 2266 INIT_BUF(dj);
emh203 0:76427232f435 2267 if (res == FR_OK)
emh203 0:76427232f435 2268 res = follow_path(&dj, path); /* Follow the file path */
emh203 0:76427232f435 2269 dir = dj.dir;
emh203 0:76427232f435 2270
emh203 0:76427232f435 2271 #if !_FS_READONLY /* R/W configuration */
emh203 0:76427232f435 2272 if (res == FR_OK) {
emh203 0:76427232f435 2273 if (!dir) /* Current dir itself */
emh203 0:76427232f435 2274 res = FR_INVALID_NAME;
emh203 0:76427232f435 2275 #if _FS_SHARE
emh203 0:76427232f435 2276 else
emh203 0:76427232f435 2277 res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
emh203 0:76427232f435 2278 #endif
emh203 0:76427232f435 2279 }
emh203 0:76427232f435 2280 /* Create or Open a file */
emh203 0:76427232f435 2281 if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
emh203 0:76427232f435 2282 DWORD dw, cl;
emh203 0:76427232f435 2283
emh203 0:76427232f435 2284 if (res != FR_OK) { /* No file, create new */
emh203 0:76427232f435 2285 if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
emh203 0:76427232f435 2286 #if _FS_SHARE
emh203 0:76427232f435 2287 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
emh203 0:76427232f435 2288 #else
emh203 0:76427232f435 2289 res = dir_register(&dj);
emh203 0:76427232f435 2290 #endif
emh203 0:76427232f435 2291 mode |= FA_CREATE_ALWAYS; /* File is created */
emh203 0:76427232f435 2292 dir = dj.dir; /* New entry */
emh203 0:76427232f435 2293 }
emh203 0:76427232f435 2294 else { /* Any object is already existing */
emh203 0:76427232f435 2295 if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
emh203 0:76427232f435 2296 res = FR_DENIED;
emh203 0:76427232f435 2297 } else {
emh203 0:76427232f435 2298 if (mode & FA_CREATE_NEW) /* Cannot create as new file */
emh203 0:76427232f435 2299 res = FR_EXIST;
emh203 0:76427232f435 2300 }
emh203 0:76427232f435 2301 }
emh203 0:76427232f435 2302 if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
emh203 0:76427232f435 2303 dw = get_fattime(); /* Created time */
emh203 0:76427232f435 2304 ST_DWORD(dir+DIR_CrtTime, dw);
emh203 0:76427232f435 2305 dir[DIR_Attr] = 0; /* Reset attribute */
emh203 0:76427232f435 2306 ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
emh203 0:76427232f435 2307 cl = LD_CLUST(dir); /* Get start cluster */
emh203 0:76427232f435 2308 ST_CLUST(dir, 0); /* cluster = 0 */
emh203 0:76427232f435 2309 dj.fs->wflag = 1;
emh203 0:76427232f435 2310 if (cl) { /* Remove the cluster chain if exist */
emh203 0:76427232f435 2311 dw = dj.fs->winsect;
emh203 0:76427232f435 2312 res = remove_chain(dj.fs, cl);
emh203 0:76427232f435 2313 if (res == FR_OK) {
emh203 0:76427232f435 2314 dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
emh203 0:76427232f435 2315 res = move_window(dj.fs, dw);
emh203 0:76427232f435 2316 }
emh203 0:76427232f435 2317 }
emh203 0:76427232f435 2318 }
emh203 0:76427232f435 2319 }
emh203 0:76427232f435 2320 else { /* Open an existing file */
emh203 0:76427232f435 2321 if (res == FR_OK) { /* Follow succeeded */
emh203 0:76427232f435 2322 if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
emh203 0:76427232f435 2323 res = FR_NO_FILE;
emh203 0:76427232f435 2324 } else {
emh203 0:76427232f435 2325 if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
emh203 0:76427232f435 2326 res = FR_DENIED;
emh203 0:76427232f435 2327 }
emh203 0:76427232f435 2328 }
emh203 0:76427232f435 2329 }
emh203 0:76427232f435 2330 if (res == FR_OK) {
emh203 0:76427232f435 2331 if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
emh203 0:76427232f435 2332 mode |= FA__WRITTEN;
emh203 0:76427232f435 2333 fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
emh203 0:76427232f435 2334 fp->dir_ptr = dir;
emh203 0:76427232f435 2335 #if _FS_SHARE
emh203 0:76427232f435 2336 fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
emh203 0:76427232f435 2337 if (!fp->lockid) res = FR_INT_ERR;
emh203 0:76427232f435 2338 #endif
emh203 0:76427232f435 2339 }
emh203 0:76427232f435 2340
emh203 0:76427232f435 2341 #else /* R/O configuration */
emh203 0:76427232f435 2342 if (res == FR_OK) { /* Follow succeeded */
emh203 0:76427232f435 2343 if (!dir) { /* Current dir itself */
emh203 0:76427232f435 2344 res = FR_INVALID_NAME;
emh203 0:76427232f435 2345 } else {
emh203 0:76427232f435 2346 if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
emh203 0:76427232f435 2347 res = FR_NO_FILE;
emh203 0:76427232f435 2348 }
emh203 0:76427232f435 2349 }
emh203 0:76427232f435 2350 #endif
emh203 0:76427232f435 2351 FREE_BUF();
emh203 0:76427232f435 2352
emh203 0:76427232f435 2353 if (res == FR_OK) {
emh203 0:76427232f435 2354 fp->flag = mode; /* File access mode */
emh203 0:76427232f435 2355 fp->sclust = LD_CLUST(dir); /* File start cluster */
emh203 0:76427232f435 2356 fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
emh203 0:76427232f435 2357 fp->fptr = 0; /* File pointer */
emh203 0:76427232f435 2358 fp->dsect = 0;
emh203 0:76427232f435 2359 #if _USE_FASTSEEK
emh203 0:76427232f435 2360 fp->cltbl = 0; /* Normal seek mode */
emh203 0:76427232f435 2361 #endif
emh203 0:76427232f435 2362 fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
emh203 0:76427232f435 2363 }
emh203 0:76427232f435 2364
emh203 0:76427232f435 2365 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 2366 }
emh203 0:76427232f435 2367
emh203 0:76427232f435 2368
emh203 0:76427232f435 2369
emh203 0:76427232f435 2370
emh203 0:76427232f435 2371 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2372 /* Read File */
emh203 0:76427232f435 2373 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2374
emh203 0:76427232f435 2375 FRESULT f_read (
emh203 0:76427232f435 2376 FIL *fp, /* Pointer to the file object */
emh203 0:76427232f435 2377 void *buff, /* Pointer to data buffer */
emh203 0:76427232f435 2378 UINT btr, /* Number of bytes to read */
emh203 0:76427232f435 2379 UINT *br /* Pointer to number of bytes read */
emh203 0:76427232f435 2380 )
emh203 0:76427232f435 2381 {
emh203 0:76427232f435 2382 FRESULT res;
emh203 0:76427232f435 2383 DWORD clst, sect, remain;
emh203 0:76427232f435 2384 UINT rcnt, cc;
emh203 0:76427232f435 2385 BYTE csect, *rbuff = (BYTE *)buff;
emh203 0:76427232f435 2386
emh203 0:76427232f435 2387
emh203 0:76427232f435 2388 *br = 0; /* Initialize byte counter */
emh203 0:76427232f435 2389
emh203 0:76427232f435 2390 res = validate(fp->fs, fp->id); /* Check validity */
emh203 0:76427232f435 2391 if (res != FR_OK) LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 2392 if (fp->flag & FA__ERROR) /* Aborted file? */
emh203 0:76427232f435 2393 LEAVE_FF(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2394 if (!(fp->flag & FA_READ)) /* Check access mode */
emh203 0:76427232f435 2395 LEAVE_FF(fp->fs, FR_DENIED);
emh203 0:76427232f435 2396 remain = fp->fsize - fp->fptr;
emh203 0:76427232f435 2397 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
emh203 0:76427232f435 2398
emh203 0:76427232f435 2399 for ( ; btr; /* Repeat until all data read */
emh203 0:76427232f435 2400 rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
emh203 0:76427232f435 2401 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
emh203 0:76427232f435 2402 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
emh203 0:76427232f435 2403 if (!csect) { /* On the cluster boundary? */
emh203 0:76427232f435 2404 if (fp->fptr == 0) { /* On the top of the file? */
emh203 0:76427232f435 2405 clst = fp->sclust; /* Follow from the origin */
emh203 0:76427232f435 2406 } else { /* Middle or end of the file */
emh203 0:76427232f435 2407 #if _USE_FASTSEEK
emh203 0:76427232f435 2408 if (fp->cltbl)
emh203 0:76427232f435 2409 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
emh203 0:76427232f435 2410 else
emh203 0:76427232f435 2411 #endif
emh203 0:76427232f435 2412 clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
emh203 0:76427232f435 2413 }
emh203 0:76427232f435 2414 if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2415 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2416 fp->clust = clst; /* Update current cluster */
emh203 0:76427232f435 2417 }
emh203 0:76427232f435 2418 sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
emh203 0:76427232f435 2419 if (!sect) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2420 sect += csect;
emh203 0:76427232f435 2421 cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */
emh203 0:76427232f435 2422 if (cc) { /* Read maximum contiguous sectors directly */
emh203 0:76427232f435 2423 if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
emh203 0:76427232f435 2424 cc = fp->fs->csize - csect;
emh203 0:76427232f435 2425 if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
emh203 0:76427232f435 2426 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2427 #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
emh203 0:76427232f435 2428 #if _FS_TINY
emh203 0:76427232f435 2429 if (fp->fs->wflag && fp->fs->winsect - sect < cc)
emh203 0:76427232f435 2430 mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
emh203 0:76427232f435 2431 #else
emh203 0:76427232f435 2432 if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
emh203 0:76427232f435 2433 mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
emh203 0:76427232f435 2434 #endif
emh203 0:76427232f435 2435 #endif
emh203 0:76427232f435 2436 rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
emh203 0:76427232f435 2437 continue;
emh203 0:76427232f435 2438 }
emh203 0:76427232f435 2439 #if !_FS_TINY
emh203 0:76427232f435 2440 if (fp->dsect != sect) { /* Load data sector if not in cache */
emh203 0:76427232f435 2441 #if !_FS_READONLY
emh203 0:76427232f435 2442 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
emh203 0:76427232f435 2443 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
emh203 0:76427232f435 2444 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2445 fp->flag &= ~FA__DIRTY;
emh203 0:76427232f435 2446 }
emh203 0:76427232f435 2447 #endif
emh203 0:76427232f435 2448 if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */
emh203 0:76427232f435 2449 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2450 }
emh203 0:76427232f435 2451 #endif
emh203 0:76427232f435 2452 fp->dsect = sect;
emh203 0:76427232f435 2453 }
emh203 0:76427232f435 2454 rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
emh203 0:76427232f435 2455 if (rcnt > btr) rcnt = btr;
emh203 0:76427232f435 2456 #if _FS_TINY
emh203 0:76427232f435 2457 if (move_window(fp->fs, fp->dsect)) /* Move sector window */
emh203 0:76427232f435 2458 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2459 mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
emh203 0:76427232f435 2460 #else
emh203 0:76427232f435 2461 mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
emh203 0:76427232f435 2462 #endif
emh203 0:76427232f435 2463 }
emh203 0:76427232f435 2464
emh203 0:76427232f435 2465 LEAVE_FF(fp->fs, FR_OK);
emh203 0:76427232f435 2466 }
emh203 0:76427232f435 2467
emh203 0:76427232f435 2468
emh203 0:76427232f435 2469
emh203 0:76427232f435 2470
emh203 0:76427232f435 2471 #if !_FS_READONLY
emh203 0:76427232f435 2472 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2473 /* Write File */
emh203 0:76427232f435 2474 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2475
emh203 0:76427232f435 2476 FRESULT f_write (
emh203 0:76427232f435 2477 FIL *fp, /* Pointer to the file object */
emh203 0:76427232f435 2478 const void *buff, /* Pointer to the data to be written */
emh203 0:76427232f435 2479 UINT btw, /* Number of bytes to write */
emh203 0:76427232f435 2480 UINT *bw /* Pointer to number of bytes written */
emh203 0:76427232f435 2481 )
emh203 0:76427232f435 2482 {
emh203 0:76427232f435 2483 FRESULT res;
emh203 0:76427232f435 2484 DWORD clst, sect;
emh203 0:76427232f435 2485 UINT wcnt, cc;
emh203 0:76427232f435 2486 const BYTE *wbuff = (BYTE *)buff;
emh203 0:76427232f435 2487 BYTE csect;
emh203 0:76427232f435 2488
emh203 0:76427232f435 2489
emh203 0:76427232f435 2490 *bw = 0; /* Initialize byte counter */
emh203 0:76427232f435 2491
emh203 0:76427232f435 2492 res = validate(fp->fs, fp->id); /* Check validity */
emh203 0:76427232f435 2493 if (res != FR_OK) LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 2494 if (fp->flag & FA__ERROR) /* Aborted file? */
emh203 0:76427232f435 2495 LEAVE_FF(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2496 if (!(fp->flag & FA_WRITE)) /* Check access mode */
emh203 0:76427232f435 2497 LEAVE_FF(fp->fs, FR_DENIED);
emh203 0:76427232f435 2498 if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */
emh203 0:76427232f435 2499
emh203 0:76427232f435 2500 for ( ; btw; /* Repeat until all data written */
emh203 0:76427232f435 2501 wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
emh203 0:76427232f435 2502 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
emh203 0:76427232f435 2503 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
emh203 0:76427232f435 2504 if (!csect) { /* On the cluster boundary? */
emh203 0:76427232f435 2505 if (fp->fptr == 0) { /* On the top of the file? */
emh203 0:76427232f435 2506 clst = fp->sclust; /* Follow from the origin */
emh203 0:76427232f435 2507 if (clst == 0) /* When no cluster is allocated, */
emh203 0:76427232f435 2508 fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */
emh203 0:76427232f435 2509 } else { /* Middle or end of the file */
emh203 0:76427232f435 2510 #if _USE_FASTSEEK
emh203 0:76427232f435 2511 if (fp->cltbl)
emh203 0:76427232f435 2512 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
emh203 0:76427232f435 2513 else
emh203 0:76427232f435 2514 #endif
emh203 0:76427232f435 2515 clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */
emh203 0:76427232f435 2516 }
emh203 0:76427232f435 2517 if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
emh203 0:76427232f435 2518 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2519 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2520 fp->clust = clst; /* Update current cluster */
emh203 0:76427232f435 2521 }
emh203 0:76427232f435 2522 #if _FS_TINY
emh203 0:76427232f435 2523 if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write-back sector cache */
emh203 0:76427232f435 2524 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2525 #else
emh203 0:76427232f435 2526 if (fp->flag & FA__DIRTY) { /* Write-back sector cache */
emh203 0:76427232f435 2527 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
emh203 0:76427232f435 2528 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2529 fp->flag &= ~FA__DIRTY;
emh203 0:76427232f435 2530 }
emh203 0:76427232f435 2531 #endif
emh203 0:76427232f435 2532 sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
emh203 0:76427232f435 2533 if (!sect) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2534 sect += csect;
emh203 0:76427232f435 2535 cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
emh203 0:76427232f435 2536 if (cc) { /* Write maximum contiguous sectors directly */
emh203 0:76427232f435 2537 if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
emh203 0:76427232f435 2538 cc = fp->fs->csize - csect;
emh203 0:76427232f435 2539 if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK)
emh203 0:76427232f435 2540 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2541 #if _FS_TINY
emh203 0:76427232f435 2542 if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
emh203 0:76427232f435 2543 mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
emh203 0:76427232f435 2544 fp->fs->wflag = 0;
emh203 0:76427232f435 2545 }
emh203 0:76427232f435 2546 #else
emh203 0:76427232f435 2547 if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
emh203 0:76427232f435 2548 mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
emh203 0:76427232f435 2549 fp->flag &= ~FA__DIRTY;
emh203 0:76427232f435 2550 }
emh203 0:76427232f435 2551 #endif
emh203 0:76427232f435 2552 wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
emh203 0:76427232f435 2553 continue;
emh203 0:76427232f435 2554 }
emh203 0:76427232f435 2555 #if _FS_TINY
emh203 0:76427232f435 2556 if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */
emh203 0:76427232f435 2557 if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2558 fp->fs->winsect = sect;
emh203 0:76427232f435 2559 }
emh203 0:76427232f435 2560 #else
emh203 0:76427232f435 2561 if (fp->dsect != sect) { /* Fill sector cache with file data */
emh203 0:76427232f435 2562 if (fp->fptr < fp->fsize &&
emh203 0:76427232f435 2563 disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
emh203 0:76427232f435 2564 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2565 }
emh203 0:76427232f435 2566 #endif
emh203 0:76427232f435 2567 fp->dsect = sect;
emh203 0:76427232f435 2568 }
emh203 0:76427232f435 2569 wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
emh203 0:76427232f435 2570 if (wcnt > btw) wcnt = btw;
emh203 0:76427232f435 2571 #if _FS_TINY
emh203 0:76427232f435 2572 if (move_window(fp->fs, fp->dsect)) /* Move sector window */
emh203 0:76427232f435 2573 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2574 mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
emh203 0:76427232f435 2575 fp->fs->wflag = 1;
emh203 0:76427232f435 2576 #else
emh203 0:76427232f435 2577 mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
emh203 0:76427232f435 2578 fp->flag |= FA__DIRTY;
emh203 0:76427232f435 2579 #endif
emh203 0:76427232f435 2580 }
emh203 0:76427232f435 2581
emh203 0:76427232f435 2582 if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
emh203 0:76427232f435 2583 fp->flag |= FA__WRITTEN; /* Set file change flag */
emh203 0:76427232f435 2584
emh203 0:76427232f435 2585 LEAVE_FF(fp->fs, FR_OK);
emh203 0:76427232f435 2586 }
emh203 0:76427232f435 2587
emh203 0:76427232f435 2588
emh203 0:76427232f435 2589
emh203 0:76427232f435 2590
emh203 0:76427232f435 2591 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2592 /* Synchronize the File Object */
emh203 0:76427232f435 2593 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2594
emh203 0:76427232f435 2595 FRESULT f_sync (
emh203 0:76427232f435 2596 FIL *fp /* Pointer to the file object */
emh203 0:76427232f435 2597 )
emh203 0:76427232f435 2598 {
emh203 0:76427232f435 2599 FRESULT res;
emh203 0:76427232f435 2600 DWORD tim;
emh203 0:76427232f435 2601 BYTE *dir;
emh203 0:76427232f435 2602
emh203 0:76427232f435 2603
emh203 0:76427232f435 2604 res = validate(fp->fs, fp->id); /* Check validity of the object */
emh203 0:76427232f435 2605 if (res == FR_OK) {
emh203 0:76427232f435 2606 if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
emh203 0:76427232f435 2607 #if !_FS_TINY /* Write-back dirty buffer */
emh203 0:76427232f435 2608 if (fp->flag & FA__DIRTY) {
emh203 0:76427232f435 2609 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
emh203 0:76427232f435 2610 LEAVE_FF(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2611 fp->flag &= ~FA__DIRTY;
emh203 0:76427232f435 2612 }
emh203 0:76427232f435 2613 #endif
emh203 0:76427232f435 2614 /* Update the directory entry */
emh203 0:76427232f435 2615 res = move_window(fp->fs, fp->dir_sect);
emh203 0:76427232f435 2616 if (res == FR_OK) {
emh203 0:76427232f435 2617 dir = fp->dir_ptr;
emh203 0:76427232f435 2618 dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
emh203 0:76427232f435 2619 ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */
emh203 0:76427232f435 2620 ST_CLUST(dir, fp->sclust); /* Update start cluster */
emh203 0:76427232f435 2621 tim = get_fattime(); /* Update updated time */
emh203 0:76427232f435 2622 ST_DWORD(dir+DIR_WrtTime, tim);
emh203 0:76427232f435 2623 fp->flag &= ~FA__WRITTEN;
emh203 0:76427232f435 2624 fp->fs->wflag = 1;
emh203 0:76427232f435 2625 res = sync(fp->fs);
emh203 0:76427232f435 2626 }
emh203 0:76427232f435 2627 }
emh203 0:76427232f435 2628 }
emh203 0:76427232f435 2629
emh203 0:76427232f435 2630 LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 2631 }
emh203 0:76427232f435 2632
emh203 0:76427232f435 2633 #endif /* !_FS_READONLY */
emh203 0:76427232f435 2634
emh203 0:76427232f435 2635
emh203 0:76427232f435 2636
emh203 0:76427232f435 2637
emh203 0:76427232f435 2638 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2639 /* Close File */
emh203 0:76427232f435 2640 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2641
emh203 0:76427232f435 2642 FRESULT f_close (
emh203 0:76427232f435 2643 FIL *fp /* Pointer to the file object to be closed */
emh203 0:76427232f435 2644 )
emh203 0:76427232f435 2645 {
emh203 0:76427232f435 2646 FRESULT res;
emh203 0:76427232f435 2647
emh203 0:76427232f435 2648 #if _FS_READONLY
emh203 0:76427232f435 2649 FATFS *fs = fp->fs;
emh203 0:76427232f435 2650 res = validate(fs, fp->id);
emh203 0:76427232f435 2651 if (res == FR_OK) fp->fs = 0; /* Discard file object */
emh203 0:76427232f435 2652 LEAVE_FF(fs, res);
emh203 0:76427232f435 2653
emh203 0:76427232f435 2654 #else
emh203 0:76427232f435 2655 res = f_sync(fp); /* Flush cached data */
emh203 0:76427232f435 2656 #if _FS_SHARE
emh203 0:76427232f435 2657 if (res == FR_OK) { /* Decrement open counter */
emh203 0:76427232f435 2658 #if _FS_REENTRANT
emh203 0:76427232f435 2659 res = validate(fp->fs, fp->id);
emh203 0:76427232f435 2660 if (res == FR_OK) {
emh203 0:76427232f435 2661 res = dec_lock(fp->lockid);
emh203 0:76427232f435 2662 unlock_fs(fp->fs, FR_OK);
emh203 0:76427232f435 2663 }
emh203 0:76427232f435 2664 #else
emh203 0:76427232f435 2665 res = dec_lock(fp->lockid);
emh203 0:76427232f435 2666 #endif
emh203 0:76427232f435 2667 }
emh203 0:76427232f435 2668 #endif
emh203 0:76427232f435 2669 if (res == FR_OK) fp->fs = 0; /* Discard file object */
emh203 0:76427232f435 2670 return res;
emh203 0:76427232f435 2671 #endif
emh203 0:76427232f435 2672 }
emh203 0:76427232f435 2673
emh203 0:76427232f435 2674
emh203 0:76427232f435 2675
emh203 0:76427232f435 2676
emh203 0:76427232f435 2677 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2678 /* Current Drive/Directory Handlings */
emh203 0:76427232f435 2679 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2680
emh203 0:76427232f435 2681 #if _FS_RPATH >= 1
emh203 0:76427232f435 2682
emh203 0:76427232f435 2683 FRESULT f_chdrive (
emh203 0:76427232f435 2684 BYTE drv /* Drive number */
emh203 0:76427232f435 2685 )
emh203 0:76427232f435 2686 {
emh203 0:76427232f435 2687 if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
emh203 0:76427232f435 2688
emh203 0:76427232f435 2689 CurrVol = drv;
emh203 0:76427232f435 2690
emh203 0:76427232f435 2691 return FR_OK;
emh203 0:76427232f435 2692 }
emh203 0:76427232f435 2693
emh203 0:76427232f435 2694
emh203 0:76427232f435 2695
emh203 0:76427232f435 2696 FRESULT f_chdir (
emh203 0:76427232f435 2697 const TCHAR *path /* Pointer to the directory path */
emh203 0:76427232f435 2698 )
emh203 0:76427232f435 2699 {
emh203 0:76427232f435 2700 FRESULT res;
emh203 0:76427232f435 2701 DIR dj;
emh203 0:76427232f435 2702 DEF_NAMEBUF;
emh203 0:76427232f435 2703
emh203 0:76427232f435 2704
emh203 0:76427232f435 2705 res = chk_mounted(&path, &dj.fs, 0);
emh203 0:76427232f435 2706 if (res == FR_OK) {
emh203 0:76427232f435 2707 INIT_BUF(dj);
emh203 0:76427232f435 2708 res = follow_path(&dj, path); /* Follow the path */
emh203 0:76427232f435 2709 FREE_BUF();
emh203 0:76427232f435 2710 if (res == FR_OK) { /* Follow completed */
emh203 0:76427232f435 2711 if (!dj.dir) {
emh203 0:76427232f435 2712 dj.fs->cdir = dj.sclust; /* Start directory itself */
emh203 0:76427232f435 2713 } else {
emh203 0:76427232f435 2714 if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
emh203 0:76427232f435 2715 dj.fs->cdir = LD_CLUST(dj.dir);
emh203 0:76427232f435 2716 else
emh203 0:76427232f435 2717 res = FR_NO_PATH; /* Reached but a file */
emh203 0:76427232f435 2718 }
emh203 0:76427232f435 2719 }
emh203 0:76427232f435 2720 if (res == FR_NO_FILE) res = FR_NO_PATH;
emh203 0:76427232f435 2721 }
emh203 0:76427232f435 2722
emh203 0:76427232f435 2723 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 2724 }
emh203 0:76427232f435 2725
emh203 0:76427232f435 2726
emh203 0:76427232f435 2727 #if _FS_RPATH >= 2
emh203 0:76427232f435 2728 FRESULT f_getcwd (
emh203 0:76427232f435 2729 TCHAR *path, /* Pointer to the directory path */
emh203 0:76427232f435 2730 UINT sz_path /* Size of path */
emh203 0:76427232f435 2731 )
emh203 0:76427232f435 2732 {
emh203 0:76427232f435 2733 FRESULT res;
emh203 0:76427232f435 2734 DIR dj;
emh203 0:76427232f435 2735 UINT i, n;
emh203 0:76427232f435 2736 DWORD ccl;
emh203 0:76427232f435 2737 TCHAR *tp;
emh203 0:76427232f435 2738 FILINFO fno;
emh203 0:76427232f435 2739 DEF_NAMEBUF;
emh203 0:76427232f435 2740
emh203 0:76427232f435 2741
emh203 0:76427232f435 2742 *path = 0;
emh203 0:76427232f435 2743 res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */
emh203 0:76427232f435 2744 if (res == FR_OK) {
emh203 0:76427232f435 2745 INIT_BUF(dj);
emh203 0:76427232f435 2746 i = sz_path; /* Bottom of buffer (dir stack base) */
emh203 0:76427232f435 2747 dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */
emh203 0:76427232f435 2748 while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */
emh203 0:76427232f435 2749 res = dir_sdi(&dj, 1); /* Get parent dir */
emh203 0:76427232f435 2750 if (res != FR_OK) break;
emh203 0:76427232f435 2751 res = dir_read(&dj);
emh203 0:76427232f435 2752 if (res != FR_OK) break;
emh203 0:76427232f435 2753 dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */
emh203 0:76427232f435 2754 res = dir_sdi(&dj, 0);
emh203 0:76427232f435 2755 if (res != FR_OK) break;
emh203 0:76427232f435 2756 do { /* Find the entry links to the child dir */
emh203 0:76427232f435 2757 res = dir_read(&dj);
emh203 0:76427232f435 2758 if (res != FR_OK) break;
emh203 0:76427232f435 2759 if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */
emh203 0:76427232f435 2760 res = dir_next(&dj, 0);
emh203 0:76427232f435 2761 } while (res == FR_OK);
emh203 0:76427232f435 2762 if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
emh203 0:76427232f435 2763 if (res != FR_OK) break;
emh203 0:76427232f435 2764 #if _USE_LFN
emh203 0:76427232f435 2765 fno.lfname = path;
emh203 0:76427232f435 2766 fno.lfsize = i;
emh203 0:76427232f435 2767 #endif
emh203 0:76427232f435 2768 get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */
emh203 0:76427232f435 2769 tp = fno.fname;
emh203 0:76427232f435 2770 if (_USE_LFN && *path) tp = path;
emh203 0:76427232f435 2771 for (n = 0; tp[n]; n++) ;
emh203 0:76427232f435 2772 if (i < n + 3) {
emh203 0:76427232f435 2773 res = FR_NOT_ENOUGH_CORE; break;
emh203 0:76427232f435 2774 }
emh203 0:76427232f435 2775 while (n) path[--i] = tp[--n];
emh203 0:76427232f435 2776 path[--i] = '/';
emh203 0:76427232f435 2777 }
emh203 0:76427232f435 2778 tp = path;
emh203 0:76427232f435 2779 if (res == FR_OK) {
emh203 0:76427232f435 2780 *tp++ = '0' + CurrVol; /* Put drive number */
emh203 0:76427232f435 2781 *tp++ = ':';
emh203 0:76427232f435 2782 if (i == sz_path) { /* Root-dir */
emh203 0:76427232f435 2783 *tp++ = '/';
emh203 0:76427232f435 2784 } else { /* Sub-dir */
emh203 0:76427232f435 2785 do /* Add stacked path str */
emh203 0:76427232f435 2786 *tp++ = path[i++];
emh203 0:76427232f435 2787 while (i < sz_path);
emh203 0:76427232f435 2788 }
emh203 0:76427232f435 2789 }
emh203 0:76427232f435 2790 *tp = 0;
emh203 0:76427232f435 2791 FREE_BUF();
emh203 0:76427232f435 2792 }
emh203 0:76427232f435 2793
emh203 0:76427232f435 2794 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 2795 }
emh203 0:76427232f435 2796 #endif /* _FS_RPATH >= 2 */
emh203 0:76427232f435 2797 #endif /* _FS_RPATH >= 1 */
emh203 0:76427232f435 2798
emh203 0:76427232f435 2799
emh203 0:76427232f435 2800
emh203 0:76427232f435 2801 #if _FS_MINIMIZE <= 2
emh203 0:76427232f435 2802 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2803 /* Seek File R/W Pointer */
emh203 0:76427232f435 2804 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2805
emh203 0:76427232f435 2806 FRESULT f_lseek (
emh203 0:76427232f435 2807 FIL *fp, /* Pointer to the file object */
emh203 0:76427232f435 2808 DWORD ofs /* File pointer from top of file */
emh203 0:76427232f435 2809 )
emh203 0:76427232f435 2810 {
emh203 0:76427232f435 2811 FRESULT res;
emh203 0:76427232f435 2812
emh203 0:76427232f435 2813
emh203 0:76427232f435 2814 res = validate(fp->fs, fp->id); /* Check validity of the object */
emh203 0:76427232f435 2815 if (res != FR_OK) LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 2816 if (fp->flag & FA__ERROR) /* Check abort flag */
emh203 0:76427232f435 2817 LEAVE_FF(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2818
emh203 0:76427232f435 2819 #if _USE_FASTSEEK
emh203 0:76427232f435 2820 if (fp->cltbl) { /* Fast seek */
emh203 0:76427232f435 2821 DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
emh203 0:76427232f435 2822
emh203 0:76427232f435 2823 if (ofs == CREATE_LINKMAP) { /* Create CLMT */
emh203 0:76427232f435 2824 tbl = fp->cltbl;
emh203 0:76427232f435 2825 tlen = *tbl++; ulen = 2; /* Given table size and required table size */
emh203 0:76427232f435 2826 cl = fp->sclust; /* Top of the chain */
emh203 0:76427232f435 2827 if (cl) {
emh203 0:76427232f435 2828 do {
emh203 0:76427232f435 2829 /* Get a fragment */
emh203 0:76427232f435 2830 tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */
emh203 0:76427232f435 2831 do {
emh203 0:76427232f435 2832 pcl = cl; ncl++;
emh203 0:76427232f435 2833 cl = get_fat(fp->fs, cl);
emh203 0:76427232f435 2834 if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2835 if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2836 } while (cl == pcl + 1);
emh203 0:76427232f435 2837 if (ulen <= tlen) { /* Store the length and top of the fragment */
emh203 0:76427232f435 2838 *tbl++ = ncl; *tbl++ = tcl;
emh203 0:76427232f435 2839 }
emh203 0:76427232f435 2840 } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */
emh203 0:76427232f435 2841 }
emh203 0:76427232f435 2842 *fp->cltbl = ulen; /* Number of items used */
emh203 0:76427232f435 2843 if (ulen <= tlen)
emh203 0:76427232f435 2844 *tbl = 0; /* Terminate table */
emh203 0:76427232f435 2845 else
emh203 0:76427232f435 2846 res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */
emh203 0:76427232f435 2847
emh203 0:76427232f435 2848 } else { /* Fast seek */
emh203 0:76427232f435 2849 if (ofs > fp->fsize) /* Clip offset at the file size */
emh203 0:76427232f435 2850 ofs = fp->fsize;
emh203 0:76427232f435 2851 fp->fptr = ofs; /* Set file pointer */
emh203 0:76427232f435 2852 if (ofs) {
emh203 0:76427232f435 2853 fp->clust = clmt_clust(fp, ofs - 1);
emh203 0:76427232f435 2854 dsc = clust2sect(fp->fs, fp->clust);
emh203 0:76427232f435 2855 if (!dsc) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2856 dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
emh203 0:76427232f435 2857 if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */
emh203 0:76427232f435 2858 #if !_FS_TINY
emh203 0:76427232f435 2859 #if !_FS_READONLY
emh203 0:76427232f435 2860 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
emh203 0:76427232f435 2861 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
emh203 0:76427232f435 2862 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2863 fp->flag &= ~FA__DIRTY;
emh203 0:76427232f435 2864 }
emh203 0:76427232f435 2865 #endif
emh203 0:76427232f435 2866 if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */
emh203 0:76427232f435 2867 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2868 #endif
emh203 0:76427232f435 2869 fp->dsect = dsc;
emh203 0:76427232f435 2870 }
emh203 0:76427232f435 2871 }
emh203 0:76427232f435 2872 }
emh203 0:76427232f435 2873 } else
emh203 0:76427232f435 2874 #endif
emh203 0:76427232f435 2875
emh203 0:76427232f435 2876 /* Normal Seek */
emh203 0:76427232f435 2877 {
emh203 0:76427232f435 2878 DWORD clst, bcs, nsect, ifptr;
emh203 0:76427232f435 2879
emh203 0:76427232f435 2880 if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */
emh203 0:76427232f435 2881 #if !_FS_READONLY
emh203 0:76427232f435 2882 && !(fp->flag & FA_WRITE)
emh203 0:76427232f435 2883 #endif
emh203 0:76427232f435 2884 ) ofs = fp->fsize;
emh203 0:76427232f435 2885
emh203 0:76427232f435 2886 ifptr = fp->fptr;
emh203 0:76427232f435 2887 fp->fptr = nsect = 0;
emh203 0:76427232f435 2888 if (ofs) {
emh203 0:76427232f435 2889 bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */
emh203 0:76427232f435 2890 if (ifptr > 0 &&
emh203 0:76427232f435 2891 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
emh203 0:76427232f435 2892 fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */
emh203 0:76427232f435 2893 ofs -= fp->fptr;
emh203 0:76427232f435 2894 clst = fp->clust;
emh203 0:76427232f435 2895 } else { /* When seek to back cluster, */
emh203 0:76427232f435 2896 clst = fp->sclust; /* start from the first cluster */
emh203 0:76427232f435 2897 #if !_FS_READONLY
emh203 0:76427232f435 2898 if (clst == 0) { /* If no cluster chain, create a new chain */
emh203 0:76427232f435 2899 clst = create_chain(fp->fs, 0);
emh203 0:76427232f435 2900 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2901 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2902 fp->sclust = clst;
emh203 0:76427232f435 2903 }
emh203 0:76427232f435 2904 #endif
emh203 0:76427232f435 2905 fp->clust = clst;
emh203 0:76427232f435 2906 }
emh203 0:76427232f435 2907 if (clst != 0) {
emh203 0:76427232f435 2908 while (ofs > bcs) { /* Cluster following loop */
emh203 0:76427232f435 2909 #if !_FS_READONLY
emh203 0:76427232f435 2910 if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
emh203 0:76427232f435 2911 clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */
emh203 0:76427232f435 2912 if (clst == 0) { /* When disk gets full, clip file size */
emh203 0:76427232f435 2913 ofs = bcs; break;
emh203 0:76427232f435 2914 }
emh203 0:76427232f435 2915 } else
emh203 0:76427232f435 2916 #endif
emh203 0:76427232f435 2917 clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */
emh203 0:76427232f435 2918 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2919 if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2920 fp->clust = clst;
emh203 0:76427232f435 2921 fp->fptr += bcs;
emh203 0:76427232f435 2922 ofs -= bcs;
emh203 0:76427232f435 2923 }
emh203 0:76427232f435 2924 fp->fptr += ofs;
emh203 0:76427232f435 2925 if (ofs % SS(fp->fs)) {
emh203 0:76427232f435 2926 nsect = clust2sect(fp->fs, clst); /* Current sector */
emh203 0:76427232f435 2927 if (!nsect) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 2928 nsect += ofs / SS(fp->fs);
emh203 0:76427232f435 2929 }
emh203 0:76427232f435 2930 }
emh203 0:76427232f435 2931 }
emh203 0:76427232f435 2932 if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */
emh203 0:76427232f435 2933 #if !_FS_TINY
emh203 0:76427232f435 2934 #if !_FS_READONLY
emh203 0:76427232f435 2935 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
emh203 0:76427232f435 2936 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
emh203 0:76427232f435 2937 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2938 fp->flag &= ~FA__DIRTY;
emh203 0:76427232f435 2939 }
emh203 0:76427232f435 2940 #endif
emh203 0:76427232f435 2941 if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */
emh203 0:76427232f435 2942 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 2943 #endif
emh203 0:76427232f435 2944 fp->dsect = nsect;
emh203 0:76427232f435 2945 }
emh203 0:76427232f435 2946 #if !_FS_READONLY
emh203 0:76427232f435 2947 if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */
emh203 0:76427232f435 2948 fp->fsize = fp->fptr;
emh203 0:76427232f435 2949 fp->flag |= FA__WRITTEN;
emh203 0:76427232f435 2950 }
emh203 0:76427232f435 2951 #endif
emh203 0:76427232f435 2952 }
emh203 0:76427232f435 2953
emh203 0:76427232f435 2954 LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 2955 }
emh203 0:76427232f435 2956
emh203 0:76427232f435 2957
emh203 0:76427232f435 2958
emh203 0:76427232f435 2959 #if _FS_MINIMIZE <= 1
emh203 0:76427232f435 2960 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2961 /* Create a Directroy Object */
emh203 0:76427232f435 2962 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 2963
emh203 0:76427232f435 2964 FRESULT f_opendir (
emh203 0:76427232f435 2965 eDIR *dj, /* Pointer to directory object to create */
emh203 0:76427232f435 2966 const TCHAR *path /* Pointer to the directory path */
emh203 0:76427232f435 2967 )
emh203 0:76427232f435 2968 {
emh203 0:76427232f435 2969 FRESULT res;
emh203 0:76427232f435 2970 DEF_NAMEBUF;
emh203 0:76427232f435 2971
emh203 0:76427232f435 2972
emh203 0:76427232f435 2973 res = chk_mounted(&path, &dj->fs, 0);
emh203 0:76427232f435 2974 if (res == FR_OK) {
emh203 0:76427232f435 2975 INIT_BUF(*dj);
emh203 0:76427232f435 2976 res = follow_path(dj, path); /* Follow the path to the directory */
emh203 0:76427232f435 2977 FREE_BUF();
emh203 0:76427232f435 2978 if (res == FR_OK) { /* Follow completed */
emh203 0:76427232f435 2979 if (dj->dir) { /* It is not the root dir */
emh203 0:76427232f435 2980 if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */
emh203 0:76427232f435 2981 dj->sclust = LD_CLUST(dj->dir);
emh203 0:76427232f435 2982 } else { /* The object is not a directory */
emh203 0:76427232f435 2983 res = FR_NO_PATH;
emh203 0:76427232f435 2984 }
emh203 0:76427232f435 2985 }
emh203 0:76427232f435 2986 if (res == FR_OK) {
emh203 0:76427232f435 2987 dj->id = dj->fs->id;
emh203 0:76427232f435 2988 res = dir_sdi(dj, 0); /* Rewind dir */
emh203 0:76427232f435 2989 }
emh203 0:76427232f435 2990 }
emh203 0:76427232f435 2991 if (res == FR_NO_FILE) res = FR_NO_PATH;
emh203 0:76427232f435 2992 }
emh203 0:76427232f435 2993
emh203 0:76427232f435 2994 LEAVE_FF(dj->fs, res);
emh203 0:76427232f435 2995 }
emh203 0:76427232f435 2996
emh203 0:76427232f435 2997
emh203 0:76427232f435 2998
emh203 0:76427232f435 2999
emh203 0:76427232f435 3000 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3001 /* Read Directory Entry in Sequense */
emh203 0:76427232f435 3002 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3003
emh203 0:76427232f435 3004 FRESULT f_readdir (
emh203 0:76427232f435 3005 eDIR *dj, /* Pointer to the open directory object */
emh203 0:76427232f435 3006 FILINFO *fno /* Pointer to file information to return */
emh203 0:76427232f435 3007 )
emh203 0:76427232f435 3008 {
emh203 0:76427232f435 3009 FRESULT res;
emh203 0:76427232f435 3010 DEF_NAMEBUF;
emh203 0:76427232f435 3011
emh203 0:76427232f435 3012
emh203 0:76427232f435 3013 res = validate(dj->fs, dj->id); /* Check validity of the object */
emh203 0:76427232f435 3014 if (res == FR_OK) {
emh203 0:76427232f435 3015 if (!fno) {
emh203 0:76427232f435 3016 res = dir_sdi(dj, 0); /* Rewind the directory object */
emh203 0:76427232f435 3017 } else {
emh203 0:76427232f435 3018 INIT_BUF(*dj);
emh203 0:76427232f435 3019 res = dir_read(dj); /* Read an directory item */
emh203 0:76427232f435 3020 if (res == FR_NO_FILE) { /* Reached end of dir */
emh203 0:76427232f435 3021 dj->sect = 0;
emh203 0:76427232f435 3022 res = FR_OK;
emh203 0:76427232f435 3023 }
emh203 0:76427232f435 3024 if (res == FR_OK) { /* A valid entry is found */
emh203 0:76427232f435 3025 get_fileinfo(dj, fno); /* Get the object information */
emh203 0:76427232f435 3026 res = dir_next(dj, 0); /* Increment index for next */
emh203 0:76427232f435 3027 if (res == FR_NO_FILE) {
emh203 0:76427232f435 3028 dj->sect = 0;
emh203 0:76427232f435 3029 res = FR_OK;
emh203 0:76427232f435 3030 }
emh203 0:76427232f435 3031 }
emh203 0:76427232f435 3032 FREE_BUF();
emh203 0:76427232f435 3033 }
emh203 0:76427232f435 3034 }
emh203 0:76427232f435 3035
emh203 0:76427232f435 3036 LEAVE_FF(dj->fs, res);
emh203 0:76427232f435 3037 }
emh203 0:76427232f435 3038
emh203 0:76427232f435 3039
emh203 0:76427232f435 3040
emh203 0:76427232f435 3041 #if _FS_MINIMIZE == 0
emh203 0:76427232f435 3042 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3043 /* Get File Status */
emh203 0:76427232f435 3044 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3045
emh203 0:76427232f435 3046 FRESULT f_stat (
emh203 0:76427232f435 3047 const TCHAR *path, /* Pointer to the file path */
emh203 0:76427232f435 3048 FILINFO *fno /* Pointer to file information to return */
emh203 0:76427232f435 3049 )
emh203 0:76427232f435 3050 {
emh203 0:76427232f435 3051 FRESULT res;
emh203 0:76427232f435 3052 eDIR dj;
emh203 0:76427232f435 3053 DEF_NAMEBUF;
emh203 0:76427232f435 3054
emh203 0:76427232f435 3055
emh203 0:76427232f435 3056 res = chk_mounted(&path, &dj.fs, 0);
emh203 0:76427232f435 3057 if (res == FR_OK) {
emh203 0:76427232f435 3058 INIT_BUF(dj);
emh203 0:76427232f435 3059 res = follow_path(&dj, path); /* Follow the file path */
emh203 0:76427232f435 3060 if (res == FR_OK) { /* Follow completed */
emh203 0:76427232f435 3061 if (dj.dir) /* Found an object */
emh203 0:76427232f435 3062 get_fileinfo(&dj, fno);
emh203 0:76427232f435 3063 else /* It is root dir */
emh203 0:76427232f435 3064 res = FR_INVALID_NAME;
emh203 0:76427232f435 3065 }
emh203 0:76427232f435 3066 FREE_BUF();
emh203 0:76427232f435 3067 }
emh203 0:76427232f435 3068
emh203 0:76427232f435 3069 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 3070 }
emh203 0:76427232f435 3071
emh203 0:76427232f435 3072
emh203 0:76427232f435 3073
emh203 0:76427232f435 3074 #if !_FS_READONLY
emh203 0:76427232f435 3075 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3076 /* Get Number of Free Clusters */
emh203 0:76427232f435 3077 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3078
emh203 0:76427232f435 3079 FRESULT f_getfree (
emh203 0:76427232f435 3080 const TCHAR *path, /* Pointer to the logical drive number (root dir) */
emh203 0:76427232f435 3081 DWORD *nclst, /* Pointer to the variable to return number of free clusters */
emh203 0:76427232f435 3082 FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */
emh203 0:76427232f435 3083 )
emh203 0:76427232f435 3084 {
emh203 0:76427232f435 3085 FRESULT res;
emh203 0:76427232f435 3086 DWORD n, clst, sect, stat;
emh203 0:76427232f435 3087 UINT i;
emh203 0:76427232f435 3088 BYTE fat, *p;
emh203 0:76427232f435 3089
emh203 0:76427232f435 3090
emh203 0:76427232f435 3091 /* Get drive number */
emh203 0:76427232f435 3092 res = chk_mounted(&path, fatfs, 0);
emh203 0:76427232f435 3093 if (res == FR_OK) {
emh203 0:76427232f435 3094 /* If free_clust is valid, return it without full cluster scan */
emh203 0:76427232f435 3095 if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
emh203 0:76427232f435 3096 *nclst = (*fatfs)->free_clust;
emh203 0:76427232f435 3097 } else {
emh203 0:76427232f435 3098 /* Get number of free clusters */
emh203 0:76427232f435 3099 fat = (*fatfs)->fs_type;
emh203 0:76427232f435 3100 n = 0;
emh203 0:76427232f435 3101 if (fat == FS_FAT12) {
emh203 0:76427232f435 3102 clst = 2;
emh203 0:76427232f435 3103 do {
emh203 0:76427232f435 3104 stat = get_fat(*fatfs, clst);
emh203 0:76427232f435 3105 if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
emh203 0:76427232f435 3106 if (stat == 1) { res = FR_INT_ERR; break; }
emh203 0:76427232f435 3107 if (stat == 0) n++;
emh203 0:76427232f435 3108 } while (++clst < (*fatfs)->n_fatent);
emh203 0:76427232f435 3109 } else {
emh203 0:76427232f435 3110 clst = (*fatfs)->n_fatent;
emh203 0:76427232f435 3111 sect = (*fatfs)->fatbase;
emh203 0:76427232f435 3112 i = 0; p = 0;
emh203 0:76427232f435 3113 do {
emh203 0:76427232f435 3114 if (!i) {
emh203 0:76427232f435 3115 res = move_window(*fatfs, sect++);
emh203 0:76427232f435 3116 if (res != FR_OK) break;
emh203 0:76427232f435 3117 p = (*fatfs)->win;
emh203 0:76427232f435 3118 i = SS(*fatfs);
emh203 0:76427232f435 3119 }
emh203 0:76427232f435 3120 if (fat == FS_FAT16) {
emh203 0:76427232f435 3121 if (LD_WORD(p) == 0) n++;
emh203 0:76427232f435 3122 p += 2; i -= 2;
emh203 0:76427232f435 3123 } else {
emh203 0:76427232f435 3124 if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++;
emh203 0:76427232f435 3125 p += 4; i -= 4;
emh203 0:76427232f435 3126 }
emh203 0:76427232f435 3127 } while (--clst);
emh203 0:76427232f435 3128 }
emh203 0:76427232f435 3129 (*fatfs)->free_clust = n;
emh203 0:76427232f435 3130 if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
emh203 0:76427232f435 3131 *nclst = n;
emh203 0:76427232f435 3132 }
emh203 0:76427232f435 3133 }
emh203 0:76427232f435 3134 LEAVE_FF(*fatfs, res);
emh203 0:76427232f435 3135 }
emh203 0:76427232f435 3136
emh203 0:76427232f435 3137
emh203 0:76427232f435 3138
emh203 0:76427232f435 3139
emh203 0:76427232f435 3140 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3141 /* Truncate File */
emh203 0:76427232f435 3142 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3143
emh203 0:76427232f435 3144 FRESULT f_truncate (
emh203 0:76427232f435 3145 FIL *fp /* Pointer to the file object */
emh203 0:76427232f435 3146 )
emh203 0:76427232f435 3147 {
emh203 0:76427232f435 3148 FRESULT res;
emh203 0:76427232f435 3149 DWORD ncl;
emh203 0:76427232f435 3150
emh203 0:76427232f435 3151
emh203 0:76427232f435 3152 res = validate(fp->fs, fp->id); /* Check validity of the object */
emh203 0:76427232f435 3153 if (res == FR_OK) {
emh203 0:76427232f435 3154 if (fp->flag & FA__ERROR) { /* Check abort flag */
emh203 0:76427232f435 3155 res = FR_INT_ERR;
emh203 0:76427232f435 3156 } else {
emh203 0:76427232f435 3157 if (!(fp->flag & FA_WRITE)) /* Check access mode */
emh203 0:76427232f435 3158 res = FR_DENIED;
emh203 0:76427232f435 3159 }
emh203 0:76427232f435 3160 }
emh203 0:76427232f435 3161 if (res == FR_OK) {
emh203 0:76427232f435 3162 if (fp->fsize > fp->fptr) {
emh203 0:76427232f435 3163 fp->fsize = fp->fptr; /* Set file size to current R/W point */
emh203 0:76427232f435 3164 fp->flag |= FA__WRITTEN;
emh203 0:76427232f435 3165 if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
emh203 0:76427232f435 3166 res = remove_chain(fp->fs, fp->sclust);
emh203 0:76427232f435 3167 fp->sclust = 0;
emh203 0:76427232f435 3168 } else { /* When truncate a part of the file, remove remaining clusters */
emh203 0:76427232f435 3169 ncl = get_fat(fp->fs, fp->clust);
emh203 0:76427232f435 3170 res = FR_OK;
emh203 0:76427232f435 3171 if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
emh203 0:76427232f435 3172 if (ncl == 1) res = FR_INT_ERR;
emh203 0:76427232f435 3173 if (res == FR_OK && ncl < fp->fs->n_fatent) {
emh203 0:76427232f435 3174 res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF);
emh203 0:76427232f435 3175 if (res == FR_OK) res = remove_chain(fp->fs, ncl);
emh203 0:76427232f435 3176 }
emh203 0:76427232f435 3177 }
emh203 0:76427232f435 3178 }
emh203 0:76427232f435 3179 if (res != FR_OK) fp->flag |= FA__ERROR;
emh203 0:76427232f435 3180 }
emh203 0:76427232f435 3181
emh203 0:76427232f435 3182 LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 3183 }
emh203 0:76427232f435 3184
emh203 0:76427232f435 3185
emh203 0:76427232f435 3186
emh203 0:76427232f435 3187
emh203 0:76427232f435 3188 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3189 /* Delete a File or Directory */
emh203 0:76427232f435 3190 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3191
emh203 0:76427232f435 3192 FRESULT f_unlink (
emh203 0:76427232f435 3193 const TCHAR *path /* Pointer to the file or directory path */
emh203 0:76427232f435 3194 )
emh203 0:76427232f435 3195 {
emh203 0:76427232f435 3196 FRESULT res;
emh203 0:76427232f435 3197 eDIR dj, sdj;
emh203 0:76427232f435 3198 BYTE *dir;
emh203 0:76427232f435 3199 DWORD dclst;
emh203 0:76427232f435 3200 DEF_NAMEBUF;
emh203 0:76427232f435 3201
emh203 0:76427232f435 3202
emh203 0:76427232f435 3203 res = chk_mounted(&path, &dj.fs, 1);
emh203 0:76427232f435 3204 if (res == FR_OK) {
emh203 0:76427232f435 3205 INIT_BUF(dj);
emh203 0:76427232f435 3206 res = follow_path(&dj, path); /* Follow the file path */
emh203 0:76427232f435 3207 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
emh203 0:76427232f435 3208 res = FR_INVALID_NAME; /* Cannot remove dot entry */
emh203 0:76427232f435 3209 #if _FS_SHARE
emh203 0:76427232f435 3210 if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */
emh203 0:76427232f435 3211 #endif
emh203 0:76427232f435 3212 if (res == FR_OK) { /* The object is accessible */
emh203 0:76427232f435 3213 dir = dj.dir;
emh203 0:76427232f435 3214 if (!dir) {
emh203 0:76427232f435 3215 res = FR_INVALID_NAME; /* Cannot remove the start directory */
emh203 0:76427232f435 3216 } else {
emh203 0:76427232f435 3217 if (dir[DIR_Attr] & AM_RDO)
emh203 0:76427232f435 3218 res = FR_DENIED; /* Cannot remove R/O object */
emh203 0:76427232f435 3219 }
emh203 0:76427232f435 3220 dclst = LD_CLUST(dir);
emh203 0:76427232f435 3221 if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */
emh203 0:76427232f435 3222 if (dclst < 2) {
emh203 0:76427232f435 3223 res = FR_INT_ERR;
emh203 0:76427232f435 3224 } else {
emh203 0:76427232f435 3225 mem_cpy(&sdj, &dj, sizeof(eDIR)); /* Check if the sub-dir is empty or not */
emh203 0:76427232f435 3226 sdj.sclust = dclst;
emh203 0:76427232f435 3227 res = dir_sdi(&sdj, 2); /* Exclude dot entries */
emh203 0:76427232f435 3228 if (res == FR_OK) {
emh203 0:76427232f435 3229 res = dir_read(&sdj);
emh203 0:76427232f435 3230 if (res == FR_OK /* Not empty dir */
emh203 0:76427232f435 3231 #if _FS_RPATH
emh203 0:76427232f435 3232 || dclst == sdj.fs->cdir /* Current dir */
emh203 0:76427232f435 3233 #endif
emh203 0:76427232f435 3234 ) res = FR_DENIED;
emh203 0:76427232f435 3235 if (res == FR_NO_FILE) res = FR_OK; /* Empty */
emh203 0:76427232f435 3236 }
emh203 0:76427232f435 3237 }
emh203 0:76427232f435 3238 }
emh203 0:76427232f435 3239 if (res == FR_OK) {
emh203 0:76427232f435 3240 res = dir_remove(&dj); /* Remove the directory entry */
emh203 0:76427232f435 3241 if (res == FR_OK) {
emh203 0:76427232f435 3242 if (dclst) /* Remove the cluster chain if exist */
emh203 0:76427232f435 3243 res = remove_chain(dj.fs, dclst);
emh203 0:76427232f435 3244 if (res == FR_OK) res = sync(dj.fs);
emh203 0:76427232f435 3245 }
emh203 0:76427232f435 3246 }
emh203 0:76427232f435 3247 }
emh203 0:76427232f435 3248 FREE_BUF();
emh203 0:76427232f435 3249 }
emh203 0:76427232f435 3250 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 3251 }
emh203 0:76427232f435 3252
emh203 0:76427232f435 3253
emh203 0:76427232f435 3254
emh203 0:76427232f435 3255
emh203 0:76427232f435 3256 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3257 /* Create a Directory */
emh203 0:76427232f435 3258 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3259
emh203 0:76427232f435 3260 FRESULT f_mkdir (
emh203 0:76427232f435 3261 const TCHAR *path /* Pointer to the directory path */
emh203 0:76427232f435 3262 )
emh203 0:76427232f435 3263 {
emh203 0:76427232f435 3264 FRESULT res;
emh203 0:76427232f435 3265 eDIR dj;
emh203 0:76427232f435 3266 BYTE *dir, n;
emh203 0:76427232f435 3267 DWORD dsc, dcl, pcl, tim = get_fattime();
emh203 0:76427232f435 3268 DEF_NAMEBUF;
emh203 0:76427232f435 3269
emh203 0:76427232f435 3270
emh203 0:76427232f435 3271 res = chk_mounted(&path, &dj.fs, 1);
emh203 0:76427232f435 3272 if (res == FR_OK) {
emh203 0:76427232f435 3273 INIT_BUF(dj);
emh203 0:76427232f435 3274 res = follow_path(&dj, path); /* Follow the file path */
emh203 0:76427232f435 3275 if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
emh203 0:76427232f435 3276 if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT))
emh203 0:76427232f435 3277 res = FR_INVALID_NAME;
emh203 0:76427232f435 3278 if (res == FR_NO_FILE) { /* Can create a new directory */
emh203 0:76427232f435 3279 dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */
emh203 0:76427232f435 3280 res = FR_OK;
emh203 0:76427232f435 3281 if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
emh203 0:76427232f435 3282 if (dcl == 1) res = FR_INT_ERR;
emh203 0:76427232f435 3283 if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
emh203 0:76427232f435 3284 if (res == FR_OK) /* Flush FAT */
emh203 0:76427232f435 3285 res = move_window(dj.fs, 0);
emh203 0:76427232f435 3286 if (res == FR_OK) { /* Initialize the new directory table */
emh203 0:76427232f435 3287 dsc = clust2sect(dj.fs, dcl);
emh203 0:76427232f435 3288 dir = dj.fs->win;
emh203 0:76427232f435 3289 mem_set(dir, 0, SS(dj.fs));
emh203 0:76427232f435 3290 mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */
emh203 0:76427232f435 3291 dir[DIR_Name] = '.';
emh203 0:76427232f435 3292 dir[DIR_Attr] = AM_DIR;
emh203 0:76427232f435 3293 ST_DWORD(dir+DIR_WrtTime, tim);
emh203 0:76427232f435 3294 ST_CLUST(dir, dcl);
emh203 0:76427232f435 3295 mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */
emh203 0:76427232f435 3296 dir[33] = '.'; pcl = dj.sclust;
emh203 0:76427232f435 3297 if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
emh203 0:76427232f435 3298 pcl = 0;
emh203 0:76427232f435 3299 ST_CLUST(dir+SZ_DIR, pcl);
emh203 0:76427232f435 3300 for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
emh203 0:76427232f435 3301 dj.fs->winsect = dsc++;
emh203 0:76427232f435 3302 dj.fs->wflag = 1;
emh203 0:76427232f435 3303 res = move_window(dj.fs, 0);
emh203 0:76427232f435 3304 if (res != FR_OK) break;
emh203 0:76427232f435 3305 mem_set(dir, 0, SS(dj.fs));
emh203 0:76427232f435 3306 }
emh203 0:76427232f435 3307 }
emh203 0:76427232f435 3308 if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */
emh203 0:76427232f435 3309 if (res != FR_OK) {
emh203 0:76427232f435 3310 remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */
emh203 0:76427232f435 3311 } else {
emh203 0:76427232f435 3312 dir = dj.dir;
emh203 0:76427232f435 3313 dir[DIR_Attr] = AM_DIR; /* Attribute */
emh203 0:76427232f435 3314 ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */
emh203 0:76427232f435 3315 ST_CLUST(dir, dcl); /* Table start cluster */
emh203 0:76427232f435 3316 dj.fs->wflag = 1;
emh203 0:76427232f435 3317 res = sync(dj.fs);
emh203 0:76427232f435 3318 }
emh203 0:76427232f435 3319 }
emh203 0:76427232f435 3320 FREE_BUF();
emh203 0:76427232f435 3321 }
emh203 0:76427232f435 3322
emh203 0:76427232f435 3323 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 3324 }
emh203 0:76427232f435 3325
emh203 0:76427232f435 3326
emh203 0:76427232f435 3327
emh203 0:76427232f435 3328
emh203 0:76427232f435 3329 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3330 /* Change Attribute */
emh203 0:76427232f435 3331 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3332
emh203 0:76427232f435 3333 FRESULT f_chmod (
emh203 0:76427232f435 3334 const TCHAR *path, /* Pointer to the file path */
emh203 0:76427232f435 3335 BYTE value, /* Attribute bits */
emh203 0:76427232f435 3336 BYTE mask /* Attribute mask to change */
emh203 0:76427232f435 3337 )
emh203 0:76427232f435 3338 {
emh203 0:76427232f435 3339 FRESULT res;
emh203 0:76427232f435 3340 eDIR dj;
emh203 0:76427232f435 3341 BYTE *dir;
emh203 0:76427232f435 3342 DEF_NAMEBUF;
emh203 0:76427232f435 3343
emh203 0:76427232f435 3344
emh203 0:76427232f435 3345 res = chk_mounted(&path, &dj.fs, 1);
emh203 0:76427232f435 3346 if (res == FR_OK) {
emh203 0:76427232f435 3347 INIT_BUF(dj);
emh203 0:76427232f435 3348 res = follow_path(&dj, path); /* Follow the file path */
emh203 0:76427232f435 3349 FREE_BUF();
emh203 0:76427232f435 3350 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
emh203 0:76427232f435 3351 res = FR_INVALID_NAME;
emh203 0:76427232f435 3352 if (res == FR_OK) {
emh203 0:76427232f435 3353 dir = dj.dir;
emh203 0:76427232f435 3354 if (!dir) { /* Is it a root directory? */
emh203 0:76427232f435 3355 res = FR_INVALID_NAME;
emh203 0:76427232f435 3356 } else { /* File or sub directory */
emh203 0:76427232f435 3357 mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
emh203 0:76427232f435 3358 dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
emh203 0:76427232f435 3359 dj.fs->wflag = 1;
emh203 0:76427232f435 3360 res = sync(dj.fs);
emh203 0:76427232f435 3361 }
emh203 0:76427232f435 3362 }
emh203 0:76427232f435 3363 }
emh203 0:76427232f435 3364
emh203 0:76427232f435 3365 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 3366 }
emh203 0:76427232f435 3367
emh203 0:76427232f435 3368
emh203 0:76427232f435 3369
emh203 0:76427232f435 3370
emh203 0:76427232f435 3371 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3372 /* Change Timestamp */
emh203 0:76427232f435 3373 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3374
emh203 0:76427232f435 3375 FRESULT f_utime (
emh203 0:76427232f435 3376 const TCHAR *path, /* Pointer to the file/directory name */
emh203 0:76427232f435 3377 const FILINFO *fno /* Pointer to the time stamp to be set */
emh203 0:76427232f435 3378 )
emh203 0:76427232f435 3379 {
emh203 0:76427232f435 3380 FRESULT res;
emh203 0:76427232f435 3381 eDIR dj;
emh203 0:76427232f435 3382 BYTE *dir;
emh203 0:76427232f435 3383 DEF_NAMEBUF;
emh203 0:76427232f435 3384
emh203 0:76427232f435 3385
emh203 0:76427232f435 3386 res = chk_mounted(&path, &dj.fs, 1);
emh203 0:76427232f435 3387 if (res == FR_OK) {
emh203 0:76427232f435 3388 INIT_BUF(dj);
emh203 0:76427232f435 3389 res = follow_path(&dj, path); /* Follow the file path */
emh203 0:76427232f435 3390 FREE_BUF();
emh203 0:76427232f435 3391 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
emh203 0:76427232f435 3392 res = FR_INVALID_NAME;
emh203 0:76427232f435 3393 if (res == FR_OK) {
emh203 0:76427232f435 3394 dir = dj.dir;
emh203 0:76427232f435 3395 if (!dir) { /* Root directory */
emh203 0:76427232f435 3396 res = FR_INVALID_NAME;
emh203 0:76427232f435 3397 } else { /* File or sub-directory */
emh203 0:76427232f435 3398 ST_WORD(dir+DIR_WrtTime, fno->ftime);
emh203 0:76427232f435 3399 ST_WORD(dir+DIR_WrtDate, fno->fdate);
emh203 0:76427232f435 3400 dj.fs->wflag = 1;
emh203 0:76427232f435 3401 res = sync(dj.fs);
emh203 0:76427232f435 3402 }
emh203 0:76427232f435 3403 }
emh203 0:76427232f435 3404 }
emh203 0:76427232f435 3405
emh203 0:76427232f435 3406 LEAVE_FF(dj.fs, res);
emh203 0:76427232f435 3407 }
emh203 0:76427232f435 3408
emh203 0:76427232f435 3409
emh203 0:76427232f435 3410
emh203 0:76427232f435 3411
emh203 0:76427232f435 3412 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3413 /* Rename File/Directory */
emh203 0:76427232f435 3414 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3415
emh203 0:76427232f435 3416 FRESULT f_rename (
emh203 0:76427232f435 3417 const TCHAR *path_old, /* Pointer to the old name */
emh203 0:76427232f435 3418 const TCHAR *path_new /* Pointer to the new name */
emh203 0:76427232f435 3419 )
emh203 0:76427232f435 3420 {
emh203 0:76427232f435 3421 FRESULT res;
emh203 0:76427232f435 3422 eDIR djo, djn;
emh203 0:76427232f435 3423 BYTE buf[21], *dir;
emh203 0:76427232f435 3424 DWORD dw;
emh203 0:76427232f435 3425 DEF_NAMEBUF;
emh203 0:76427232f435 3426
emh203 0:76427232f435 3427
emh203 0:76427232f435 3428 res = chk_mounted(&path_old, &djo.fs, 1);
emh203 0:76427232f435 3429 if (res == FR_OK) {
emh203 0:76427232f435 3430 djn.fs = djo.fs;
emh203 0:76427232f435 3431 INIT_BUF(djo);
emh203 0:76427232f435 3432 res = follow_path(&djo, path_old); /* Check old object */
emh203 0:76427232f435 3433 if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
emh203 0:76427232f435 3434 res = FR_INVALID_NAME;
emh203 0:76427232f435 3435 #if _FS_SHARE
emh203 0:76427232f435 3436 if (res == FR_OK) res = chk_lock(&djo, 2);
emh203 0:76427232f435 3437 #endif
emh203 0:76427232f435 3438 if (res == FR_OK) { /* Old object is found */
emh203 0:76427232f435 3439 if (!djo.dir) { /* Is root dir? */
emh203 0:76427232f435 3440 res = FR_NO_FILE;
emh203 0:76427232f435 3441 } else {
emh203 0:76427232f435 3442 mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */
emh203 0:76427232f435 3443 mem_cpy(&djn, &djo, sizeof(eDIR)); /* Check new object */
emh203 0:76427232f435 3444 res = follow_path(&djn, path_new);
emh203 0:76427232f435 3445 if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
emh203 0:76427232f435 3446 if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */
emh203 0:76427232f435 3447 /* Start critical section that any interruption or error can cause cross-link */
emh203 0:76427232f435 3448 res = dir_register(&djn); /* Register the new entry */
emh203 0:76427232f435 3449 if (res == FR_OK) {
emh203 0:76427232f435 3450 dir = djn.dir; /* Copy object information except for name */
emh203 0:76427232f435 3451 mem_cpy(dir+13, buf+2, 19);
emh203 0:76427232f435 3452 dir[DIR_Attr] = buf[0] | AM_ARC;
emh203 0:76427232f435 3453 djo.fs->wflag = 1;
emh203 0:76427232f435 3454 if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */
emh203 0:76427232f435 3455 dw = clust2sect(djn.fs, LD_CLUST(dir));
emh203 0:76427232f435 3456 if (!dw) {
emh203 0:76427232f435 3457 res = FR_INT_ERR;
emh203 0:76427232f435 3458 } else {
emh203 0:76427232f435 3459 res = move_window(djn.fs, dw);
emh203 0:76427232f435 3460 dir = djn.fs->win+SZ_DIR; /* .. entry */
emh203 0:76427232f435 3461 if (res == FR_OK && dir[1] == '.') {
emh203 0:76427232f435 3462 dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
emh203 0:76427232f435 3463 ST_CLUST(dir, dw);
emh203 0:76427232f435 3464 djn.fs->wflag = 1;
emh203 0:76427232f435 3465 }
emh203 0:76427232f435 3466 }
emh203 0:76427232f435 3467 }
emh203 0:76427232f435 3468 if (res == FR_OK) {
emh203 0:76427232f435 3469 res = dir_remove(&djo); /* Remove old entry */
emh203 0:76427232f435 3470 if (res == FR_OK)
emh203 0:76427232f435 3471 res = sync(djo.fs);
emh203 0:76427232f435 3472 }
emh203 0:76427232f435 3473 }
emh203 0:76427232f435 3474 /* End critical section */
emh203 0:76427232f435 3475 }
emh203 0:76427232f435 3476 }
emh203 0:76427232f435 3477 }
emh203 0:76427232f435 3478 FREE_BUF();
emh203 0:76427232f435 3479 }
emh203 0:76427232f435 3480 LEAVE_FF(djo.fs, res);
emh203 0:76427232f435 3481 }
emh203 0:76427232f435 3482
emh203 0:76427232f435 3483 #endif /* !_FS_READONLY */
emh203 0:76427232f435 3484 #endif /* _FS_MINIMIZE == 0 */
emh203 0:76427232f435 3485 #endif /* _FS_MINIMIZE <= 1 */
emh203 0:76427232f435 3486 #endif /* _FS_MINIMIZE <= 2 */
emh203 0:76427232f435 3487
emh203 0:76427232f435 3488
emh203 0:76427232f435 3489
emh203 0:76427232f435 3490 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3491 /* Forward data to the stream directly (available on only tiny cfg) */
emh203 0:76427232f435 3492 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3493 #if _USE_FORWARD && _FS_TINY
emh203 0:76427232f435 3494
emh203 0:76427232f435 3495 FRESULT f_forward (
emh203 0:76427232f435 3496 FIL *fp, /* Pointer to the file object */
emh203 0:76427232f435 3497 UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */
emh203 0:76427232f435 3498 UINT btr, /* Number of bytes to forward */
emh203 0:76427232f435 3499 UINT *bf /* Pointer to number of bytes forwarded */
emh203 0:76427232f435 3500 )
emh203 0:76427232f435 3501 {
emh203 0:76427232f435 3502 FRESULT res;
emh203 0:76427232f435 3503 DWORD remain, clst, sect;
emh203 0:76427232f435 3504 UINT rcnt;
emh203 0:76427232f435 3505 BYTE csect;
emh203 0:76427232f435 3506
emh203 0:76427232f435 3507
emh203 0:76427232f435 3508 *bf = 0; /* Initialize byte counter */
emh203 0:76427232f435 3509
emh203 0:76427232f435 3510 res = validate(fp->fs, fp->id); /* Check validity of the object */
emh203 0:76427232f435 3511 if (res != FR_OK) LEAVE_FF(fp->fs, res);
emh203 0:76427232f435 3512 if (fp->flag & FA__ERROR) /* Check error flag */
emh203 0:76427232f435 3513 LEAVE_FF(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 3514 if (!(fp->flag & FA_READ)) /* Check access mode */
emh203 0:76427232f435 3515 LEAVE_FF(fp->fs, FR_DENIED);
emh203 0:76427232f435 3516
emh203 0:76427232f435 3517 remain = fp->fsize - fp->fptr;
emh203 0:76427232f435 3518 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
emh203 0:76427232f435 3519
emh203 0:76427232f435 3520 for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */
emh203 0:76427232f435 3521 fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) {
emh203 0:76427232f435 3522 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
emh203 0:76427232f435 3523 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
emh203 0:76427232f435 3524 if (!csect) { /* On the cluster boundary? */
emh203 0:76427232f435 3525 clst = (fp->fptr == 0) ? /* On the top of the file? */
emh203 0:76427232f435 3526 fp->sclust : get_fat(fp->fs, fp->clust);
emh203 0:76427232f435 3527 if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 3528 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 3529 fp->clust = clst; /* Update current cluster */
emh203 0:76427232f435 3530 }
emh203 0:76427232f435 3531 }
emh203 0:76427232f435 3532 sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */
emh203 0:76427232f435 3533 if (!sect) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 3534 sect += csect;
emh203 0:76427232f435 3535 if (move_window(fp->fs, sect)) /* Move sector window */
emh203 0:76427232f435 3536 ABORT(fp->fs, FR_DISK_ERR);
emh203 0:76427232f435 3537 fp->dsect = sect;
emh203 0:76427232f435 3538 rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */
emh203 0:76427232f435 3539 if (rcnt > btr) rcnt = btr;
emh203 0:76427232f435 3540 rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
emh203 0:76427232f435 3541 if (!rcnt) ABORT(fp->fs, FR_INT_ERR);
emh203 0:76427232f435 3542 }
emh203 0:76427232f435 3543
emh203 0:76427232f435 3544 LEAVE_FF(fp->fs, FR_OK);
emh203 0:76427232f435 3545 }
emh203 0:76427232f435 3546 #endif /* _USE_FORWARD */
emh203 0:76427232f435 3547
emh203 0:76427232f435 3548
emh203 0:76427232f435 3549
emh203 0:76427232f435 3550 #if _USE_MKFS && !_FS_READONLY
emh203 0:76427232f435 3551 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3552 /* Create File System on the Drive */
emh203 0:76427232f435 3553 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3554 #define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */
emh203 0:76427232f435 3555 #define N_FATS 1 /* Number of FAT copies (1 or 2) */
emh203 0:76427232f435 3556
emh203 0:76427232f435 3557
emh203 0:76427232f435 3558 FRESULT f_mkfs (
emh203 0:76427232f435 3559 BYTE drv, /* Logical drive number */
emh203 0:76427232f435 3560 BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */
emh203 0:76427232f435 3561 UINT au /* Allocation unit size [bytes] */
emh203 0:76427232f435 3562 )
emh203 0:76427232f435 3563 {
emh203 0:76427232f435 3564 static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
emh203 0:76427232f435 3565 static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
emh203 0:76427232f435 3566 BYTE fmt, md, sys, *tbl, pdrv, part;
emh203 0:76427232f435 3567 DWORD n_clst, vs, n, wsect;
emh203 0:76427232f435 3568 UINT i;
emh203 0:76427232f435 3569 DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
emh203 0:76427232f435 3570 DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
emh203 0:76427232f435 3571 FATFS *fs;
emh203 0:76427232f435 3572 DSTATUS stat;
emh203 0:76427232f435 3573
emh203 0:76427232f435 3574
emh203 0:76427232f435 3575 /* Check mounted drive and clear work area */
emh203 0:76427232f435 3576 if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
emh203 0:76427232f435 3577 if (sfd > 1) return FR_INVALID_PARAMETER;
emh203 0:76427232f435 3578 if (au & (au - 1)) return FR_INVALID_PARAMETER;
emh203 0:76427232f435 3579 fs = FatFs[drv];
emh203 0:76427232f435 3580 if (!fs) return FR_NOT_ENABLED;
emh203 0:76427232f435 3581 fs->fs_type = 0;
emh203 0:76427232f435 3582 pdrv = LD2PD(drv); /* Physical drive */
emh203 0:76427232f435 3583 part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/
emh203 0:76427232f435 3584
emh203 0:76427232f435 3585 /* Get disk statics */
emh203 0:76427232f435 3586 stat = disk_initialize(pdrv);
emh203 0:76427232f435 3587 if (stat & STA_NOINIT) return FR_NOT_READY;
emh203 0:76427232f435 3588 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
emh203 0:76427232f435 3589 #if _MAX_SS != 512 /* Get disk sector size */
emh203 0:76427232f435 3590 if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
emh203 0:76427232f435 3591 return FR_DISK_ERR;
emh203 0:76427232f435 3592 #endif
emh203 0:76427232f435 3593 if (_MULTI_PARTITION && part) {
emh203 0:76427232f435 3594 /* Get partition information from partition table in the MBR */
emh203 0:76427232f435 3595 if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
emh203 0:76427232f435 3596 if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
emh203 0:76427232f435 3597 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
emh203 0:76427232f435 3598 if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */
emh203 0:76427232f435 3599 b_vol = LD_DWORD(tbl+8); /* Volume start sector */
emh203 0:76427232f435 3600 n_vol = LD_DWORD(tbl+12); /* Volume size */
emh203 0:76427232f435 3601 } else {
emh203 0:76427232f435 3602 /* Create a partition in this function */
emh203 0:76427232f435 3603 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
emh203 0:76427232f435 3604 return FR_DISK_ERR;
emh203 0:76427232f435 3605 b_vol = (sfd) ? 0 : 63; /* Volume start sector */
emh203 0:76427232f435 3606 n_vol -= b_vol; /* Volume size */
emh203 0:76427232f435 3607 }
emh203 0:76427232f435 3608
emh203 0:76427232f435 3609 if (!au) { /* AU auto selection */
emh203 0:76427232f435 3610 vs = n_vol / (2000 / (SS(fs) / 512));
emh203 0:76427232f435 3611 for (i = 0; vs < vst[i]; i++) ;
emh203 0:76427232f435 3612 au = cst[i];
emh203 0:76427232f435 3613 }
emh203 0:76427232f435 3614 au /= SS(fs); /* Number of sectors per cluster */
emh203 0:76427232f435 3615 if (au == 0) au = 1;
emh203 0:76427232f435 3616 if (au > 128) au = 128;
emh203 0:76427232f435 3617
emh203 0:76427232f435 3618 /* Pre-compute number of clusters and FAT syb-type */
emh203 0:76427232f435 3619 n_clst = n_vol / au;
emh203 0:76427232f435 3620 fmt = FS_FAT12;
emh203 0:76427232f435 3621 if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
emh203 0:76427232f435 3622 if (n_clst >= MIN_FAT32) fmt = FS_FAT32;
emh203 0:76427232f435 3623
emh203 0:76427232f435 3624 /* Determine offset and size of FAT structure */
emh203 0:76427232f435 3625 if (fmt == FS_FAT32) {
emh203 0:76427232f435 3626 n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
emh203 0:76427232f435 3627 n_rsv = 32;
emh203 0:76427232f435 3628 n_dir = 0;
emh203 0:76427232f435 3629 } else {
emh203 0:76427232f435 3630 n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
emh203 0:76427232f435 3631 n_fat = (n_fat + SS(fs) - 1) / SS(fs);
emh203 0:76427232f435 3632 n_rsv = 1;
emh203 0:76427232f435 3633 n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs);
emh203 0:76427232f435 3634 }
emh203 0:76427232f435 3635 b_fat = b_vol + n_rsv; /* FAT area start sector */
emh203 0:76427232f435 3636 b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
emh203 0:76427232f435 3637 b_data = b_dir + n_dir; /* Data area start sector */
emh203 0:76427232f435 3638 if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
emh203 0:76427232f435 3639
emh203 0:76427232f435 3640 /* Align data start sector to erase block boundary (for flash memory media) */
emh203 0:76427232f435 3641 if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
emh203 0:76427232f435 3642 n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */
emh203 0:76427232f435 3643 n = (n - b_data) / N_FATS;
emh203 0:76427232f435 3644 if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
emh203 0:76427232f435 3645 n_rsv += n;
emh203 0:76427232f435 3646 b_fat += n;
emh203 0:76427232f435 3647 } else { /* FAT12/16: Expand FAT size */
emh203 0:76427232f435 3648 n_fat += n;
emh203 0:76427232f435 3649 }
emh203 0:76427232f435 3650
emh203 0:76427232f435 3651 /* Determine number of clusters and final check of validity of the FAT sub-type */
emh203 0:76427232f435 3652 n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
emh203 0:76427232f435 3653 if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16)
emh203 0:76427232f435 3654 || (fmt == FS_FAT32 && n_clst < MIN_FAT32))
emh203 0:76427232f435 3655 return FR_MKFS_ABORTED;
emh203 0:76427232f435 3656
emh203 0:76427232f435 3657 switch (fmt) { /* Determine system ID for partition table */
emh203 0:76427232f435 3658 case FS_FAT12: sys = 0x01; break;
emh203 0:76427232f435 3659 case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
emh203 0:76427232f435 3660 default: sys = 0x0C;
emh203 0:76427232f435 3661 }
emh203 0:76427232f435 3662
emh203 0:76427232f435 3663 if (_MULTI_PARTITION && part) {
emh203 0:76427232f435 3664 /* Update system ID in the partition table */
emh203 0:76427232f435 3665 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
emh203 0:76427232f435 3666 tbl[4] = sys;
emh203 0:76427232f435 3667 if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
emh203 0:76427232f435 3668 md = 0xF8;
emh203 0:76427232f435 3669 } else {
emh203 0:76427232f435 3670 if (sfd) { /* No patition table (SFD) */
emh203 0:76427232f435 3671 md = 0xF0;
emh203 0:76427232f435 3672 } else { /* Create partition table (FDISK) */
emh203 0:76427232f435 3673 mem_set(fs->win, 0, SS(fs));
emh203 0:76427232f435 3674 tbl = fs->win+MBR_Table; /* Create partiton table for single partition in the drive */
emh203 0:76427232f435 3675 tbl[1] = 1; /* Partition start head */
emh203 0:76427232f435 3676 tbl[2] = 1; /* Partition start sector */
emh203 0:76427232f435 3677 tbl[3] = 0; /* Partition start cylinder */
emh203 0:76427232f435 3678 tbl[4] = sys; /* System type */
emh203 0:76427232f435 3679 tbl[5] = 254; /* Partition end head */
emh203 0:76427232f435 3680 n = (b_vol + n_vol) / 63 / 255;
emh203 0:76427232f435 3681 tbl[6] = (BYTE)((n >> 2) | 63); /* Partiiton end sector */
emh203 0:76427232f435 3682 tbl[7] = (BYTE)n; /* End cylinder */
emh203 0:76427232f435 3683 ST_DWORD(tbl+8, 63); /* Partition start in LBA */
emh203 0:76427232f435 3684 ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
emh203 0:76427232f435 3685 ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */
emh203 0:76427232f435 3686 if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */
emh203 0:76427232f435 3687 return FR_DISK_ERR;
emh203 0:76427232f435 3688 md = 0xF8;
emh203 0:76427232f435 3689 }
emh203 0:76427232f435 3690 }
emh203 0:76427232f435 3691
emh203 0:76427232f435 3692 /* Create BPB in the VBR */
emh203 0:76427232f435 3693 tbl = fs->win; /* Clear sector */
emh203 0:76427232f435 3694 mem_set(tbl, 0, SS(fs));
emh203 0:76427232f435 3695 mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
emh203 0:76427232f435 3696 i = SS(fs); /* Sector size */
emh203 0:76427232f435 3697 ST_WORD(tbl+BPB_BytsPerSec, i);
emh203 0:76427232f435 3698 tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */
emh203 0:76427232f435 3699 ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */
emh203 0:76427232f435 3700 tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
emh203 0:76427232f435 3701 i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */
emh203 0:76427232f435 3702 ST_WORD(tbl+BPB_RootEntCnt, i);
emh203 0:76427232f435 3703 if (n_vol < 0x10000) { /* Number of total sectors */
emh203 0:76427232f435 3704 ST_WORD(tbl+BPB_TotSec16, n_vol);
emh203 0:76427232f435 3705 } else {
emh203 0:76427232f435 3706 ST_DWORD(tbl+BPB_TotSec32, n_vol);
emh203 0:76427232f435 3707 }
emh203 0:76427232f435 3708 tbl[BPB_Media] = md; /* Media descriptor */
emh203 0:76427232f435 3709 ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */
emh203 0:76427232f435 3710 ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */
emh203 0:76427232f435 3711 ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */
emh203 0:76427232f435 3712 n = get_fattime(); /* Use current time as VSN */
emh203 0:76427232f435 3713 if (fmt == FS_FAT32) {
emh203 0:76427232f435 3714 ST_DWORD(tbl+BS_VolID32, n); /* VSN */
emh203 0:76427232f435 3715 ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */
emh203 0:76427232f435 3716 ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */
emh203 0:76427232f435 3717 ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */
emh203 0:76427232f435 3718 ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */
emh203 0:76427232f435 3719 tbl[BS_DrvNum32] = 0x80; /* Drive number */
emh203 0:76427232f435 3720 tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
emh203 0:76427232f435 3721 mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
emh203 0:76427232f435 3722 } else {
emh203 0:76427232f435 3723 ST_DWORD(tbl+BS_VolID, n); /* VSN */
emh203 0:76427232f435 3724 ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */
emh203 0:76427232f435 3725 tbl[BS_DrvNum] = 0x80; /* Drive number */
emh203 0:76427232f435 3726 tbl[BS_BootSig] = 0x29; /* Extended boot signature */
emh203 0:76427232f435 3727 mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
emh203 0:76427232f435 3728 }
emh203 0:76427232f435 3729 ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
emh203 0:76427232f435 3730 if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
emh203 0:76427232f435 3731 return FR_DISK_ERR;
emh203 0:76427232f435 3732 if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */
emh203 0:76427232f435 3733 disk_write(pdrv, tbl, b_vol + 6, 1);
emh203 0:76427232f435 3734
emh203 0:76427232f435 3735 /* Initialize FAT area */
emh203 0:76427232f435 3736 wsect = b_fat;
emh203 0:76427232f435 3737 for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */
emh203 0:76427232f435 3738 mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */
emh203 0:76427232f435 3739 n = md; /* Media descriptor byte */
emh203 0:76427232f435 3740 if (fmt != FS_FAT32) {
emh203 0:76427232f435 3741 n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
emh203 0:76427232f435 3742 ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */
emh203 0:76427232f435 3743 } else {
emh203 0:76427232f435 3744 n |= 0xFFFFFF00;
emh203 0:76427232f435 3745 ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */
emh203 0:76427232f435 3746 ST_DWORD(tbl+4, 0xFFFFFFFF);
emh203 0:76427232f435 3747 ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */
emh203 0:76427232f435 3748 }
emh203 0:76427232f435 3749 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
emh203 0:76427232f435 3750 return FR_DISK_ERR;
emh203 0:76427232f435 3751 mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
emh203 0:76427232f435 3752 for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */
emh203 0:76427232f435 3753 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
emh203 0:76427232f435 3754 return FR_DISK_ERR;
emh203 0:76427232f435 3755 }
emh203 0:76427232f435 3756 }
emh203 0:76427232f435 3757
emh203 0:76427232f435 3758 /* Initialize root directory */
emh203 0:76427232f435 3759 i = (fmt == FS_FAT32) ? au : n_dir;
emh203 0:76427232f435 3760 do {
emh203 0:76427232f435 3761 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
emh203 0:76427232f435 3762 return FR_DISK_ERR;
emh203 0:76427232f435 3763 } while (--i);
emh203 0:76427232f435 3764
emh203 0:76427232f435 3765 #if _USE_ERASE /* Erase data area if needed */
emh203 0:76427232f435 3766 {
emh203 0:76427232f435 3767 DWORD eb[2];
emh203 0:76427232f435 3768
emh203 0:76427232f435 3769 eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
emh203 0:76427232f435 3770 disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
emh203 0:76427232f435 3771 }
emh203 0:76427232f435 3772 #endif
emh203 0:76427232f435 3773
emh203 0:76427232f435 3774 /* Create FSInfo if needed */
emh203 0:76427232f435 3775 if (fmt == FS_FAT32) {
emh203 0:76427232f435 3776 ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
emh203 0:76427232f435 3777 ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
emh203 0:76427232f435 3778 ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */
emh203 0:76427232f435 3779 ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */
emh203 0:76427232f435 3780 ST_WORD(tbl+BS_55AA, 0xAA55);
emh203 0:76427232f435 3781 disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */
emh203 0:76427232f435 3782 disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */
emh203 0:76427232f435 3783 }
emh203 0:76427232f435 3784
emh203 0:76427232f435 3785 return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
emh203 0:76427232f435 3786 }
emh203 0:76427232f435 3787
emh203 0:76427232f435 3788
emh203 0:76427232f435 3789 #if _MULTI_PARTITION == 2
emh203 0:76427232f435 3790 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3791 /* Divide Physical Drive */
emh203 0:76427232f435 3792 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3793
emh203 0:76427232f435 3794 FRESULT f_fdisk (
emh203 0:76427232f435 3795 BYTE pdrv, /* Physical drive number */
emh203 0:76427232f435 3796 const DWORD szt[], /* Pointer to the size table for each partitions */
emh203 0:76427232f435 3797 void* work /* Pointer to the working buffer */
emh203 0:76427232f435 3798 )
emh203 0:76427232f435 3799 {
emh203 0:76427232f435 3800 UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
emh203 0:76427232f435 3801 BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
emh203 0:76427232f435 3802 DSTATUS stat;
emh203 0:76427232f435 3803 DWORD sz_disk, sz_part, s_part;
emh203 0:76427232f435 3804
emh203 0:76427232f435 3805
emh203 0:76427232f435 3806 stat = disk_initialize(pdrv);
emh203 0:76427232f435 3807 if (stat & STA_NOINIT) return FR_NOT_READY;
emh203 0:76427232f435 3808 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
emh203 0:76427232f435 3809 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
emh203 0:76427232f435 3810
emh203 0:76427232f435 3811 /* Determine CHS in the table regardless of the drive geometry */
emh203 0:76427232f435 3812 for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
emh203 0:76427232f435 3813 if (n == 256) n--;
emh203 0:76427232f435 3814 e_hd = n - 1;
emh203 0:76427232f435 3815 sz_cyl = 63 * n;
emh203 0:76427232f435 3816 tot_cyl = sz_disk / sz_cyl;
emh203 0:76427232f435 3817
emh203 0:76427232f435 3818 /* Create partition table */
emh203 0:76427232f435 3819 mem_set(buf, 0, _MAX_SS);
emh203 0:76427232f435 3820 p = buf + MBR_Table; b_cyl = 0;
emh203 0:76427232f435 3821 for (i = 0; i < 4; i++, p += SZ_PTE) {
emh203 0:76427232f435 3822 p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
emh203 0:76427232f435 3823 if (!p_cyl) continue;
emh203 0:76427232f435 3824 s_part = (DWORD)sz_cyl * b_cyl;
emh203 0:76427232f435 3825 sz_part = (DWORD)sz_cyl * p_cyl;
emh203 0:76427232f435 3826 if (i == 0) { /* Exclude first track of cylinder 0 */
emh203 0:76427232f435 3827 s_hd = 1;
emh203 0:76427232f435 3828 s_part += 63; sz_part -= 63;
emh203 0:76427232f435 3829 } else {
emh203 0:76427232f435 3830 s_hd = 0;
emh203 0:76427232f435 3831 }
emh203 0:76427232f435 3832 e_cyl = b_cyl + p_cyl - 1;
emh203 0:76427232f435 3833 if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
emh203 0:76427232f435 3834
emh203 0:76427232f435 3835 /* Set partition table */
emh203 0:76427232f435 3836 p[1] = s_hd; /* Start head */
emh203 0:76427232f435 3837 p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
emh203 0:76427232f435 3838 p[3] = (BYTE)b_cyl; /* Start cylinder */
emh203 0:76427232f435 3839 p[4] = 0x06; /* System type (temporary setting) */
emh203 0:76427232f435 3840 p[5] = e_hd; /* End head */
emh203 0:76427232f435 3841 p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
emh203 0:76427232f435 3842 p[7] = (BYTE)e_cyl; /* End cylinder */
emh203 0:76427232f435 3843 ST_DWORD(p + 8, s_part); /* Start sector in LBA */
emh203 0:76427232f435 3844 ST_DWORD(p + 12, sz_part); /* Partition size */
emh203 0:76427232f435 3845
emh203 0:76427232f435 3846 /* Next partition */
emh203 0:76427232f435 3847 b_cyl += p_cyl;
emh203 0:76427232f435 3848 }
emh203 0:76427232f435 3849 ST_WORD(p, 0xAA55);
emh203 0:76427232f435 3850
emh203 0:76427232f435 3851 /* Write it to the MBR */
emh203 0:76427232f435 3852 return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
emh203 0:76427232f435 3853 }
emh203 0:76427232f435 3854
emh203 0:76427232f435 3855
emh203 0:76427232f435 3856 #endif /* _MULTI_PARTITION == 2 */
emh203 0:76427232f435 3857 #endif /* _USE_MKFS && !_FS_READONLY */
emh203 0:76427232f435 3858
emh203 0:76427232f435 3859
emh203 0:76427232f435 3860
emh203 0:76427232f435 3861
emh203 0:76427232f435 3862 #if _USE_STRFUNC
emh203 0:76427232f435 3863 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3864 /* Get a string from the file */
emh203 0:76427232f435 3865 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3866 TCHAR* f_gets (
emh203 0:76427232f435 3867 TCHAR* buff, /* Pointer to the string buffer to read */
emh203 0:76427232f435 3868 int len, /* Size of string buffer (characters) */
emh203 0:76427232f435 3869 FIL* fil /* Pointer to the file object */
emh203 0:76427232f435 3870 )
emh203 0:76427232f435 3871 {
emh203 0:76427232f435 3872 int n = 0;
emh203 0:76427232f435 3873 TCHAR c, *p = buff;
emh203 0:76427232f435 3874 BYTE s[2];
emh203 0:76427232f435 3875 UINT rc;
emh203 0:76427232f435 3876
emh203 0:76427232f435 3877
emh203 0:76427232f435 3878 while (n < len - 1) { /* Read bytes until buffer gets filled */
emh203 0:76427232f435 3879 f_read(fil, s, 1, &rc);
emh203 0:76427232f435 3880 if (rc != 1) break; /* Break on EOF or error */
emh203 0:76427232f435 3881 c = s[0];
emh203 0:76427232f435 3882 #if _LFN_UNICODE /* Read a character in UTF-8 encoding */
emh203 0:76427232f435 3883 if (c >= 0x80) {
emh203 0:76427232f435 3884 if (c < 0xC0) continue; /* Skip stray trailer */
emh203 0:76427232f435 3885 if (c < 0xE0) { /* Two-byte sequense */
emh203 0:76427232f435 3886 f_read(fil, s, 1, &rc);
emh203 0:76427232f435 3887 if (rc != 1) break;
emh203 0:76427232f435 3888 c = ((c & 0x1F) << 6) | (s[0] & 0x3F);
emh203 0:76427232f435 3889 if (c < 0x80) c = '?';
emh203 0:76427232f435 3890 } else {
emh203 0:76427232f435 3891 if (c < 0xF0) { /* Three-byte sequense */
emh203 0:76427232f435 3892 f_read(fil, s, 2, &rc);
emh203 0:76427232f435 3893 if (rc != 2) break;
emh203 0:76427232f435 3894 c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F);
emh203 0:76427232f435 3895 if (c < 0x800) c = '?';
emh203 0:76427232f435 3896 } else { /* Reject four-byte sequense */
emh203 0:76427232f435 3897 c = '?';
emh203 0:76427232f435 3898 }
emh203 0:76427232f435 3899 }
emh203 0:76427232f435 3900 }
emh203 0:76427232f435 3901 #endif
emh203 0:76427232f435 3902 #if _USE_STRFUNC >= 2
emh203 0:76427232f435 3903 if (c == '\r') continue; /* Strip '\r' */
emh203 0:76427232f435 3904 #endif
emh203 0:76427232f435 3905 *p++ = c;
emh203 0:76427232f435 3906 n++;
emh203 0:76427232f435 3907 if (c == '\n') break; /* Break on EOL */
emh203 0:76427232f435 3908 }
emh203 0:76427232f435 3909 *p = 0;
emh203 0:76427232f435 3910 return n ? buff : 0; /* When no data read (eof or error), return with error. */
emh203 0:76427232f435 3911 }
emh203 0:76427232f435 3912
emh203 0:76427232f435 3913
emh203 0:76427232f435 3914
emh203 0:76427232f435 3915 #if !_FS_READONLY
emh203 0:76427232f435 3916 #include <stdarg.h>
emh203 0:76427232f435 3917 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3918 /* Put a character to the file */
emh203 0:76427232f435 3919 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3920 int f_putc (
emh203 0:76427232f435 3921 TCHAR c, /* A character to be output */
emh203 0:76427232f435 3922 FIL* fil /* Pointer to the file object */
emh203 0:76427232f435 3923 )
emh203 0:76427232f435 3924 {
emh203 0:76427232f435 3925 UINT bw, btw;
emh203 0:76427232f435 3926 BYTE s[3];
emh203 0:76427232f435 3927
emh203 0:76427232f435 3928
emh203 0:76427232f435 3929 #if _USE_STRFUNC >= 2
emh203 0:76427232f435 3930 if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */
emh203 0:76427232f435 3931 #endif
emh203 0:76427232f435 3932
emh203 0:76427232f435 3933 #if _LFN_UNICODE /* Write the character in UTF-8 encoding */
emh203 0:76427232f435 3934 if (c < 0x80) { /* 7-bit */
emh203 0:76427232f435 3935 s[0] = (BYTE)c;
emh203 0:76427232f435 3936 btw = 1;
emh203 0:76427232f435 3937 } else {
emh203 0:76427232f435 3938 if (c < 0x800) { /* 11-bit */
emh203 0:76427232f435 3939 s[0] = (BYTE)(0xC0 | (c >> 6));
emh203 0:76427232f435 3940 s[1] = (BYTE)(0x80 | (c & 0x3F));
emh203 0:76427232f435 3941 btw = 2;
emh203 0:76427232f435 3942 } else { /* 16-bit */
emh203 0:76427232f435 3943 s[0] = (BYTE)(0xE0 | (c >> 12));
emh203 0:76427232f435 3944 s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F));
emh203 0:76427232f435 3945 s[2] = (BYTE)(0x80 | (c & 0x3F));
emh203 0:76427232f435 3946 btw = 3;
emh203 0:76427232f435 3947 }
emh203 0:76427232f435 3948 }
emh203 0:76427232f435 3949 #else /* Write the character without conversion */
emh203 0:76427232f435 3950 s[0] = (BYTE)c;
emh203 0:76427232f435 3951 btw = 1;
emh203 0:76427232f435 3952 #endif
emh203 0:76427232f435 3953 f_write(fil, s, btw, &bw); /* Write the char to the file */
emh203 0:76427232f435 3954 return (bw == btw) ? 1 : EOF; /* Return the result */
emh203 0:76427232f435 3955 }
emh203 0:76427232f435 3956
emh203 0:76427232f435 3957
emh203 0:76427232f435 3958
emh203 0:76427232f435 3959
emh203 0:76427232f435 3960 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3961 /* Put a string to the file */
emh203 0:76427232f435 3962 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3963 int f_puts (
emh203 0:76427232f435 3964 const TCHAR* str, /* Pointer to the string to be output */
emh203 0:76427232f435 3965 FIL* fil /* Pointer to the file object */
emh203 0:76427232f435 3966 )
emh203 0:76427232f435 3967 {
emh203 0:76427232f435 3968 int n;
emh203 0:76427232f435 3969
emh203 0:76427232f435 3970
emh203 0:76427232f435 3971 for (n = 0; *str; str++, n++) {
emh203 0:76427232f435 3972 if (f_putc(*str, fil) == EOF) return EOF;
emh203 0:76427232f435 3973 }
emh203 0:76427232f435 3974 return n;
emh203 0:76427232f435 3975 }
emh203 0:76427232f435 3976
emh203 0:76427232f435 3977
emh203 0:76427232f435 3978
emh203 0:76427232f435 3979
emh203 0:76427232f435 3980 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3981 /* Put a formatted string to the file */
emh203 0:76427232f435 3982 /*-----------------------------------------------------------------------*/
emh203 0:76427232f435 3983 int f_printf (
emh203 0:76427232f435 3984 FIL* fil, /* Pointer to the file object */
emh203 0:76427232f435 3985 const TCHAR* str, /* Pointer to the format string */
emh203 0:76427232f435 3986 ... /* Optional arguments... */
emh203 0:76427232f435 3987 )
emh203 0:76427232f435 3988 {
emh203 0:76427232f435 3989 va_list arp;
emh203 0:76427232f435 3990 BYTE f, r;
emh203 0:76427232f435 3991 UINT i, j, w;
emh203 0:76427232f435 3992 ULONG v;
emh203 0:76427232f435 3993 TCHAR c, d, s[16], *p;
emh203 0:76427232f435 3994 int res, chc, cc;
emh203 0:76427232f435 3995
emh203 0:76427232f435 3996
emh203 0:76427232f435 3997 va_start(arp, str);
emh203 0:76427232f435 3998
emh203 0:76427232f435 3999 for (cc = res = 0; cc != EOF; res += cc) {
emh203 0:76427232f435 4000 c = *str++;
emh203 0:76427232f435 4001 if (c == 0) break; /* End of string */
emh203 0:76427232f435 4002 if (c != '%') { /* Non escape character */
emh203 0:76427232f435 4003 cc = f_putc(c, fil);
emh203 0:76427232f435 4004 if (cc != EOF) cc = 1;
emh203 0:76427232f435 4005 continue;
emh203 0:76427232f435 4006 }
emh203 0:76427232f435 4007 w = f = 0;
emh203 0:76427232f435 4008 c = *str++;
emh203 0:76427232f435 4009 if (c == '0') { /* Flag: '0' padding */
emh203 0:76427232f435 4010 f = 1; c = *str++;
emh203 0:76427232f435 4011 } else {
emh203 0:76427232f435 4012 if (c == '-') { /* Flag: left justified */
emh203 0:76427232f435 4013 f = 2; c = *str++;
emh203 0:76427232f435 4014 }
emh203 0:76427232f435 4015 }
emh203 0:76427232f435 4016 while (IsDigit(c)) { /* Precision */
emh203 0:76427232f435 4017 w = w * 10 + c - '0';
emh203 0:76427232f435 4018 c = *str++;
emh203 0:76427232f435 4019 }
emh203 0:76427232f435 4020 if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
emh203 0:76427232f435 4021 f |= 4; c = *str++;
emh203 0:76427232f435 4022 }
emh203 0:76427232f435 4023 if (!c) break;
emh203 0:76427232f435 4024 d = c;
emh203 0:76427232f435 4025 if (IsLower(d)) d -= 0x20;
emh203 0:76427232f435 4026 switch (d) { /* Type is... */
emh203 0:76427232f435 4027 case 'S' : /* String */
emh203 0:76427232f435 4028 p = va_arg(arp, TCHAR*);
emh203 0:76427232f435 4029 for (j = 0; p[j]; j++) ;
emh203 0:76427232f435 4030 chc = 0;
emh203 0:76427232f435 4031 if (!(f & 2)) {
emh203 0:76427232f435 4032 while (j++ < w) chc += (cc = f_putc(' ', fil));
emh203 0:76427232f435 4033 }
emh203 0:76427232f435 4034 chc += (cc = f_puts(p, fil));
emh203 0:76427232f435 4035 while (j++ < w) chc += (cc = f_putc(' ', fil));
emh203 0:76427232f435 4036 if (cc != EOF) cc = chc;
emh203 0:76427232f435 4037 continue;
emh203 0:76427232f435 4038 case 'C' : /* Character */
emh203 0:76427232f435 4039 cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
emh203 0:76427232f435 4040 case 'B' : /* Binary */
emh203 0:76427232f435 4041 r = 2; break;
emh203 0:76427232f435 4042 case 'O' : /* Octal */
emh203 0:76427232f435 4043 r = 8; break;
emh203 0:76427232f435 4044 case 'D' : /* Signed decimal */
emh203 0:76427232f435 4045 case 'U' : /* Unsigned decimal */
emh203 0:76427232f435 4046 r = 10; break;
emh203 0:76427232f435 4047 case 'X' : /* Hexdecimal */
emh203 0:76427232f435 4048 r = 16; break;
emh203 0:76427232f435 4049 default: /* Unknown type (passthrough) */
emh203 0:76427232f435 4050 cc = f_putc(c, fil); continue;
emh203 0:76427232f435 4051 }
emh203 0:76427232f435 4052
emh203 0:76427232f435 4053 /* Get an argument and put it in numeral */
emh203 0:76427232f435 4054 v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int));
emh203 0:76427232f435 4055 if (d == 'D' && (v & 0x80000000)) {
emh203 0:76427232f435 4056 v = 0 - v;
emh203 0:76427232f435 4057 f |= 8;
emh203 0:76427232f435 4058 }
emh203 0:76427232f435 4059 i = 0;
emh203 0:76427232f435 4060 do {
emh203 0:76427232f435 4061 d = (TCHAR)(v % r); v /= r;
emh203 0:76427232f435 4062 if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
emh203 0:76427232f435 4063 s[i++] = d + '0';
emh203 0:76427232f435 4064 } while (v && i < sizeof(s) / sizeof(s[0]));
emh203 0:76427232f435 4065 if (f & 8) s[i++] = '-';
emh203 0:76427232f435 4066 j = i; d = (f & 1) ? '0' : ' ';
emh203 0:76427232f435 4067 res = 0;
emh203 0:76427232f435 4068 while (!(f & 2) && j++ < w) res += (cc = f_putc(d, fil));
emh203 0:76427232f435 4069 do res += (cc = f_putc(s[--i], fil)); while(i);
emh203 0:76427232f435 4070 while (j++ < w) res += (cc = f_putc(' ', fil));
emh203 0:76427232f435 4071 if (cc != EOF) cc = res;
emh203 0:76427232f435 4072 }
emh203 0:76427232f435 4073
emh203 0:76427232f435 4074 va_end(arp);
emh203 0:76427232f435 4075 return (cc == EOF) ? cc : res;
emh203 0:76427232f435 4076 }
emh203 0:76427232f435 4077
emh203 0:76427232f435 4078 #endif /* !_FS_READONLY */
emh203 0:76427232f435 4079 #endif /* _USE_STRFUNC */
emh203 0:76427232f435 4080
emh203 0:76427232f435 4081