First working version of a FATFileSystem compatible Chan FAT v0.8 implementation. This is intended to use with long file names and RTOS support. For now long file names work but RTOS support is still untested.

Dependents:   USB_MSC USB_CDC_MSD_Hello TFTPServerTest DMXStation ... more

Committer:
NeoBelerophon
Date:
Fri Feb 04 21:14:33 2011 +0000
Revision:
2:629e4be333f3
Parent:
0:8ea634413549
getdir() did not work -> remove

Who changed what in which revision?

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