00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 #include "ff.h"
00119 #include "diskio.h"
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 #if _FATFS != 8051
00131 #error Wrong include file (ff.h).
00132 #endif
00133
00134
00135
00136 #if _FS_REENTRANT
00137 #if _USE_LFN == 1
00138 #error Static LFN work area cannot be used at thread-safe configuration.
00139 #endif
00140 #define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; }
00141 #define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
00142 #else
00143 #define ENTER_FF(fs)
00144 #define LEAVE_FF(fs, res) return res
00145 #endif
00146
00147 #define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
00148
00149
00150
00151 #if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096)
00152 #error Wrong sector size configuration.
00153 #endif
00154 #if _MAX_SS == _MIN_SS
00155 #define SS(fs) ((UINT)_MAX_SS)
00156 #else
00157 #define SS(fs) ((fs)->ssize)
00158 #endif
00159
00160
00161
00162 #if _FS_LOCK
00163 #if _FS_READONLY
00164 #error _FS_LOCK must be 0 at read-only cfg.
00165 #endif
00166 typedef struct {
00167 FATFS *fs;
00168 DWORD clu;
00169 WORD idx;
00170 WORD ctr;
00171 } FILESEM;
00172 #endif
00173
00174
00175
00176
00177
00178 #if _CODE_PAGE == 932
00179 #define _DF1S 0x81
00180 #define _DF1E 0x9F
00181 #define _DF2S 0xE0
00182 #define _DF2E 0xFC
00183 #define _DS1S 0x40
00184 #define _DS1E 0x7E
00185 #define _DS2S 0x80
00186 #define _DS2E 0xFC
00187
00188 #elif _CODE_PAGE == 936
00189 #define _DF1S 0x81
00190 #define _DF1E 0xFE
00191 #define _DS1S 0x40
00192 #define _DS1E 0x7E
00193 #define _DS2S 0x80
00194 #define _DS2E 0xFE
00195
00196 #elif _CODE_PAGE == 949
00197 #define _DF1S 0x81
00198 #define _DF1E 0xFE
00199 #define _DS1S 0x41
00200 #define _DS1E 0x5A
00201 #define _DS2S 0x61
00202 #define _DS2E 0x7A
00203 #define _DS3S 0x81
00204 #define _DS3E 0xFE
00205
00206 #elif _CODE_PAGE == 950
00207 #define _DF1S 0x81
00208 #define _DF1E 0xFE
00209 #define _DS1S 0x40
00210 #define _DS1E 0x7E
00211 #define _DS2S 0xA1
00212 #define _DS2E 0xFE
00213
00214 #elif _CODE_PAGE == 437
00215 #define _DF1S 0
00216 #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, \
00217 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, \
00218 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, \
00219 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}
00220
00221 #elif _CODE_PAGE == 720
00222 #define _DF1S 0
00223 #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, \
00224 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, \
00225 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, \
00226 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}
00227
00228 #elif _CODE_PAGE == 737
00229 #define _DF1S 0
00230 #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, \
00231 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, \
00232 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, \
00233 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}
00234
00235 #elif _CODE_PAGE == 775
00236 #define _DF1S 0
00237 #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, \
00238 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, \
00239 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, \
00240 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}
00241
00242 #elif _CODE_PAGE == 850
00243 #define _DF1S 0
00244 #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, \
00245 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, \
00246 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, \
00247 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}
00248
00249 #elif _CODE_PAGE == 852
00250 #define _DF1S 0
00251 #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, \
00252 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, \
00253 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, \
00254 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}
00255
00256 #elif _CODE_PAGE == 855
00257 #define _DF1S 0
00258 #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, \
00259 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, \
00260 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, \
00261 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}
00262
00263 #elif _CODE_PAGE == 857
00264 #define _DF1S 0
00265 #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, \
00266 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, \
00267 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, \
00268 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}
00269
00270 #elif _CODE_PAGE == 858
00271 #define _DF1S 0
00272 #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, \
00273 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, \
00274 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, \
00275 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}
00276
00277 #elif _CODE_PAGE == 862
00278 #define _DF1S 0
00279 #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, \
00280 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, \
00281 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, \
00282 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}
00283
00284 #elif _CODE_PAGE == 866
00285 #define _DF1S 0
00286 #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, \
00287 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, \
00288 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, \
00289 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}
00290
00291 #elif _CODE_PAGE == 874
00292 #define _DF1S 0
00293 #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, \
00294 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, \
00295 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, \
00296 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}
00297
00298 #elif _CODE_PAGE == 1250
00299 #define _DF1S 0
00300 #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, \
00301 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, \
00302 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, \
00303 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}
00304
00305 #elif _CODE_PAGE == 1251
00306 #define _DF1S 0
00307 #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, \
00308 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, \
00309 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, \
00310 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}
00311
00312 #elif _CODE_PAGE == 1252
00313 #define _DF1S 0
00314 #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, \
00315 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, \
00316 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, \
00317 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}
00318
00319 #elif _CODE_PAGE == 1253
00320 #define _DF1S 0
00321 #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, \
00322 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, \
00323 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, \
00324 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}
00325
00326 #elif _CODE_PAGE == 1254
00327 #define _DF1S 0
00328 #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, \
00329 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, \
00330 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, \
00331 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}
00332
00333 #elif _CODE_PAGE == 1255
00334 #define _DF1S 0
00335 #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, \
00336 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, \
00337 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, \
00338 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}
00339
00340 #elif _CODE_PAGE == 1256
00341 #define _DF1S 0
00342 #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, \
00343 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, \
00344 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, \
00345 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}
00346
00347 #elif _CODE_PAGE == 1257
00348 #define _DF1S 0
00349 #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, \
00350 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, \
00351 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, \
00352 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}
00353
00354 #elif _CODE_PAGE == 1258
00355 #define _DF1S 0
00356 #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, \
00357 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, \
00358 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, \
00359 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}
00360
00361 #elif _CODE_PAGE == 1
00362 #if _USE_LFN
00363 #error Cannot use LFN feature without valid code page.
00364 #endif
00365 #define _DF1S 0
00366
00367 #else
00368 #error Unknown code page
00369
00370 #endif
00371
00372
00373
00374 #define IsUpper(c) (((c)>='A')&&((c)<='Z'))
00375 #define IsLower(c) (((c)>='a')&&((c)<='z'))
00376 #define IsDigit(c) (((c)>='0')&&((c)<='9'))
00377
00378 #if _DF1S
00379
00380 #ifdef _DF2S
00381 #define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
00382 #else
00383 #define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
00384 #endif
00385
00386 #ifdef _DS3S
00387 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
00388 #else
00389 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
00390 #endif
00391
00392 #else
00393
00394 #define IsDBCS1(c) 0
00395 #define IsDBCS2(c) 0
00396
00397 #endif
00398
00399
00400
00401 #define NS 11
00402 #define NS_LOSS 0x01
00403 #define NS_LFN 0x02
00404 #define NS_LAST 0x04
00405 #define NS_BODY 0x08
00406 #define NS_EXT 0x10
00407 #define NS_DOT 0x20
00408
00409
00410
00411 #define MIN_FAT16 4086U
00412 #define MIN_FAT32 65526U
00413
00414
00415
00416
00417
00418
00419 #define BS_jmpBoot 0
00420 #define BS_OEMName 3
00421 #define BPB_BytsPerSec 11
00422 #define BPB_SecPerClus 13
00423 #define BPB_RsvdSecCnt 14
00424 #define BPB_NumFATs 16
00425 #define BPB_RootEntCnt 17
00426 #define BPB_TotSec16 19
00427 #define BPB_Media 21
00428 #define BPB_FATSz16 22
00429 #define BPB_SecPerTrk 24
00430 #define BPB_NumHeads 26
00431 #define BPB_HiddSec 28
00432 #define BPB_TotSec32 32
00433 #define BS_DrvNum 36
00434 #define BS_BootSig 38
00435 #define BS_VolID 39
00436 #define BS_VolLab 43
00437 #define BS_FilSysType 54
00438 #define BPB_FATSz32 36
00439 #define BPB_ExtFlags 40
00440 #define BPB_FSVer 42
00441 #define BPB_RootClus 44
00442 #define BPB_FSInfo 48
00443 #define BPB_BkBootSec 50
00444 #define BS_DrvNum32 64
00445 #define BS_BootSig32 66
00446 #define BS_VolID32 67
00447 #define BS_VolLab32 71
00448 #define BS_FilSysType32 82
00449 #define FSI_LeadSig 0
00450 #define FSI_StrucSig 484
00451 #define FSI_Free_Count 488
00452 #define FSI_Nxt_Free 492
00453 #define MBR_Table 446
00454 #define SZ_PTE 16
00455 #define BS_55AA 510
00456
00457 #define DIR_Name 0
00458 #define DIR_Attr 11
00459 #define DIR_NTres 12
00460 #define DIR_CrtTimeTenth 13
00461 #define DIR_CrtTime 14
00462 #define DIR_CrtDate 16
00463 #define DIR_LstAccDate 18
00464 #define DIR_FstClusHI 20
00465 #define DIR_WrtTime 22
00466 #define DIR_WrtDate 24
00467 #define DIR_FstClusLO 26
00468 #define DIR_FileSize 28
00469 #define LDIR_Ord 0
00470 #define LDIR_Attr 11
00471 #define LDIR_Type 12
00472 #define LDIR_Chksum 13
00473 #define LDIR_FstClusLO 26
00474 #define SZ_DIR 32
00475 #define LLE 0x40
00476 #define DDE 0xE5
00477 #define NDDE 0x05
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 #if _VOLUMES >= 1 || _VOLUMES <= 10
00491 static
00492 FATFS *FatFs[_VOLUMES];
00493 #else
00494 #error Number of volumes must be 1 to 10.
00495 #endif
00496
00497 static
00498 WORD Fsid;
00499
00500 #if _FS_RPATH && _VOLUMES >= 2
00501 static
00502 BYTE CurrVol;
00503 #endif
00504
00505 #if _FS_LOCK
00506 static
00507 FILESEM Files[_FS_LOCK];
00508 #endif
00509
00510 #if _USE_LFN == 0
00511 #define DEF_NAMEBUF BYTE sfn[12]
00512 #define INIT_BUF(dobj) (dobj).fn = sfn
00513 #define FREE_BUF()
00514
00515 #elif _USE_LFN == 1
00516 static
00517 WCHAR LfnBuf[_MAX_LFN+1];
00518 #define DEF_NAMEBUF BYTE sfn[12]
00519 #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
00520 #define FREE_BUF()
00521
00522 #elif _USE_LFN == 2
00523 #define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
00524 #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
00525 #define FREE_BUF()
00526
00527 #elif _USE_LFN == 3
00528 #define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
00529 #define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
00530 if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
00531 (dobj).lfn = lfn; (dobj).fn = sfn; }
00532 #define FREE_BUF() ff_memfree(lfn)
00533
00534 #else
00535 #error Wrong LFN configuration.
00536 #endif
00537
00538
00539 #ifdef _EXCVT
00540 static
00541 const BYTE ExCvt[] = _EXCVT;
00542 #endif
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 static
00562 void mem_cpy (void* dst, const void* src, UINT cnt) {
00563 BYTE *d = (BYTE*)dst;
00564 const BYTE *s = (const BYTE*)src;
00565
00566 #if _WORD_ACCESS == 1
00567 while (cnt >= sizeof (int)) {
00568 *(int*)d = *(int*)s;
00569 d += sizeof (int); s += sizeof (int);
00570 cnt -= sizeof (int);
00571 }
00572 #endif
00573 while (cnt--)
00574 *d++ = *s++;
00575 }
00576
00577
00578 static
00579 void mem_set (void* dst, int val, UINT cnt) {
00580 BYTE *d = (BYTE*)dst;
00581
00582 while (cnt--)
00583 *d++ = (BYTE)val;
00584 }
00585
00586
00587 static
00588 int mem_cmp (const void* dst, const void* src, UINT cnt) {
00589 const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
00590 int r = 0;
00591
00592 while (cnt-- && (r = *d++ - *s++) == 0) ;
00593 return r;
00594 }
00595
00596
00597 static
00598 int chk_chr (const char* str, int chr) {
00599 while (*str && *str != chr) str++;
00600 return *str;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609 #if _FS_REENTRANT
00610 static
00611 int lock_fs (
00612 FATFS* fs
00613 )
00614 {
00615 return ff_req_grant(fs->sobj);
00616 }
00617
00618
00619 static
00620 void unlock_fs (
00621 FATFS* fs,
00622 FRESULT res
00623 )
00624 {
00625 if (fs &&
00626 res != FR_NOT_ENABLED &&
00627 res != FR_INVALID_DRIVE &&
00628 res != FR_INVALID_OBJECT &&
00629 res != FR_TIMEOUT) {
00630 ff_rel_grant(fs->sobj);
00631 }
00632 }
00633 #endif
00634
00635
00636
00637
00638
00639
00640
00641 #if _FS_LOCK
00642
00643 static
00644 FRESULT chk_lock (
00645 DIR* dp,
00646 int acc
00647 )
00648 {
00649 UINT i, be;
00650
00651
00652 for (i = be = 0; i < _FS_LOCK; i++) {
00653 if (Files[i].fs) {
00654 if (Files[i].fs == dp->fs &&
00655 Files[i].clu == dp->sclust &&
00656 Files[i].idx == dp->index) break;
00657 } else {
00658 be = 1;
00659 }
00660 }
00661 if (i == _FS_LOCK)
00662 return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES;
00663
00664
00665 return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
00666 }
00667
00668
00669 static
00670 int enq_lock (void)
00671 {
00672 UINT i;
00673
00674 for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
00675 return (i == _FS_LOCK) ? 0 : 1;
00676 }
00677
00678
00679 static
00680 UINT inc_lock (
00681 DIR* dp,
00682 int acc
00683 )
00684 {
00685 UINT i;
00686
00687
00688 for (i = 0; i < _FS_LOCK; i++) {
00689 if (Files[i].fs == dp->fs &&
00690 Files[i].clu == dp->sclust &&
00691 Files[i].idx == dp->index) break;
00692 }
00693
00694 if (i == _FS_LOCK) {
00695 for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
00696 if (i == _FS_LOCK) return 0;
00697 Files[i].fs = dp->fs;
00698 Files[i].clu = dp->sclust;
00699 Files[i].idx = dp->index;
00700 Files[i].ctr = 0;
00701 }
00702
00703 if (acc && Files[i].ctr) return 0;
00704
00705 Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1;
00706
00707 return i + 1;
00708 }
00709
00710
00711 static
00712 FRESULT dec_lock (
00713 UINT i
00714 )
00715 {
00716 WORD n;
00717 FRESULT res;
00718
00719
00720 if (--i < _FS_LOCK) {
00721 n = Files[i].ctr;
00722 if (n == 0x100) n = 0;
00723 if (n) n--;
00724 Files[i].ctr = n;
00725 if (!n) Files[i].fs = 0;
00726 res = FR_OK;
00727 } else {
00728 res = FR_INT_ERR;
00729 }
00730 return res;
00731 }
00732
00733
00734 static
00735 void clear_lock (
00736 FATFS *fs
00737 )
00738 {
00739 UINT i;
00740
00741 for (i = 0; i < _FS_LOCK; i++) {
00742 if (Files[i].fs == fs) Files[i].fs = 0;
00743 }
00744 }
00745 #endif
00746
00747
00748
00749
00750
00751
00752
00753 #if !_FS_READONLY
00754 static
00755 FRESULT sync_window (
00756 FATFS* fs
00757 )
00758 {
00759 DWORD wsect;
00760 UINT nf;
00761
00762
00763 if (fs->wflag) {
00764 wsect = fs->winsect;
00765 if (disk_write(fs->drv, fs->win, wsect, 1))
00766 return FR_DISK_ERR;
00767 fs->wflag = 0;
00768 if (wsect - fs->fatbase < fs->fsize) {
00769 for (nf = fs->n_fats; nf >= 2; nf--) {
00770 wsect += fs->fsize;
00771 disk_write(fs->drv, fs->win, wsect, 1);
00772 }
00773 }
00774 }
00775 return FR_OK;
00776 }
00777 #endif
00778
00779
00780 static
00781 FRESULT move_window (
00782 FATFS* fs,
00783 DWORD sector
00784 )
00785 {
00786 if (sector != fs->winsect) {
00787 #if !_FS_READONLY
00788 if (sync_window(fs) != FR_OK)
00789 return FR_DISK_ERR;
00790 #endif
00791 if (disk_read(fs->drv, fs->win, sector, 1))
00792 return FR_DISK_ERR;
00793 fs->winsect = sector;
00794 }
00795
00796 return FR_OK;
00797 }
00798
00799
00800
00801
00802
00803
00804
00805 #if !_FS_READONLY
00806 static
00807 FRESULT sync_fs (
00808 FATFS* fs
00809 )
00810 {
00811 FRESULT res;
00812
00813
00814 res = sync_window(fs);
00815 if (res == FR_OK) {
00816
00817 if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {
00818
00819 mem_set(fs->win, 0, SS(fs));
00820 ST_WORD(fs->win+BS_55AA, 0xAA55);
00821 ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);
00822 ST_DWORD(fs->win+FSI_StrucSig, 0x61417272);
00823 ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust);
00824 ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust);
00825
00826 fs->winsect = fs->volbase + 1;
00827 disk_write(fs->drv, fs->win, fs->winsect, 1);
00828 fs->fsi_flag = 0;
00829 }
00830
00831 if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
00832 res = FR_DISK_ERR;
00833 }
00834
00835 return res;
00836 }
00837 #endif
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 static DWORD clust2sect (
00848 FATFS* fs,
00849 DWORD clst
00850 )
00851 {
00852 clst -= 2;
00853 if (clst >= (fs->n_fatent - 2)) return 0;
00854 return clst * fs->csize + fs->database;
00855 }
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static DWORD get_fat (
00866 FATFS* fs,
00867 DWORD clst
00868 )
00869 {
00870 UINT wc, bc;
00871 BYTE *p;
00872
00873
00874 if (clst < 2 || clst >= fs->n_fatent)
00875 return 1;
00876
00877 switch (fs->fs_type) {
00878 case FS_FAT12 :
00879 bc = (UINT)clst; bc += bc / 2;
00880 if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
00881 wc = fs->win[bc % SS(fs)]; bc++;
00882 if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
00883 wc |= fs->win[bc % SS(fs)] << 8;
00884 return clst & 1 ? wc >> 4 : (wc & 0xFFF);
00885
00886 case FS_FAT16 :
00887 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break;
00888 p = &fs->win[clst * 2 % SS(fs)];
00889 return LD_WORD(p);
00890
00891 case FS_FAT32 :
00892 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break;
00893 p = &fs->win[clst * 4 % SS(fs)];
00894 return LD_DWORD(p) & 0x0FFFFFFF;
00895
00896 default:
00897 return 1;
00898 }
00899
00900 return 0xFFFFFFFF;
00901 }
00902
00903
00904
00905
00906
00907
00908
00909 #if !_FS_READONLY
00910
00911 static FRESULT put_fat (
00912 FATFS* fs,
00913 DWORD clst,
00914 DWORD val
00915 )
00916 {
00917 UINT bc;
00918 BYTE *p;
00919 FRESULT res;
00920
00921
00922 if (clst < 2 || clst >= fs->n_fatent) {
00923 res = FR_INT_ERR;
00924
00925 } else {
00926 switch (fs->fs_type) {
00927 case FS_FAT12 :
00928 bc = (UINT)clst; bc += bc / 2;
00929 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
00930 if (res != FR_OK) break;
00931 p = &fs->win[bc % SS(fs)];
00932 *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
00933 bc++;
00934 fs->wflag = 1;
00935 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
00936 if (res != FR_OK) break;
00937 p = &fs->win[bc % SS(fs)];
00938 *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
00939 break;
00940
00941 case FS_FAT16 :
00942 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
00943 if (res != FR_OK) break;
00944 p = &fs->win[clst * 2 % SS(fs)];
00945 ST_WORD(p, (WORD)val);
00946 break;
00947
00948 case FS_FAT32 :
00949 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
00950 if (res != FR_OK) break;
00951 p = &fs->win[clst * 4 % SS(fs)];
00952 val |= LD_DWORD(p) & 0xF0000000;
00953 ST_DWORD(p, val);
00954 break;
00955
00956 default :
00957 res = FR_INT_ERR;
00958 }
00959 fs->wflag = 1;
00960 }
00961
00962 return res;
00963 }
00964 #endif
00965
00966
00967
00968
00969
00970
00971
00972 #if !_FS_READONLY
00973 static
00974 FRESULT remove_chain (
00975 FATFS* fs,
00976 DWORD clst
00977 )
00978 {
00979 FRESULT res;
00980 DWORD nxt;
00981 #if _USE_ERASE
00982 DWORD scl = clst, ecl = clst, rt[2];
00983 #endif
00984
00985 if (clst < 2 || clst >= fs->n_fatent) {
00986 res = FR_INT_ERR;
00987
00988 } else {
00989 res = FR_OK;
00990 while (clst < fs->n_fatent) {
00991 nxt = get_fat(fs, clst);
00992 if (nxt == 0) break;
00993 if (nxt == 1) { res = FR_INT_ERR; break; }
00994 if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
00995 res = put_fat(fs, clst, 0);
00996 if (res != FR_OK) break;
00997 if (fs->free_clust != 0xFFFFFFFF) {
00998 fs->free_clust++;
00999 fs->fsi_flag |= 1;
01000 }
01001 #if _USE_ERASE
01002 if (ecl + 1 == nxt) {
01003 ecl = nxt;
01004 } else {
01005 rt[0] = clust2sect(fs, scl);
01006 rt[1] = clust2sect(fs, ecl) + fs->csize - 1;
01007 disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt);
01008 scl = ecl = nxt;
01009 }
01010 #endif
01011 clst = nxt;
01012 }
01013 }
01014
01015 return res;
01016 }
01017 #endif
01018
01019
01020
01021
01022
01023
01024
01025 #if !_FS_READONLY
01026 static
01027 DWORD create_chain (
01028 FATFS* fs,
01029 DWORD clst
01030 )
01031 {
01032 DWORD cs, ncl, scl;
01033 FRESULT res;
01034
01035
01036 if (clst == 0) {
01037 scl = fs->last_clust;
01038 if (!scl || scl >= fs->n_fatent) scl = 1;
01039 }
01040 else {
01041 cs = get_fat(fs, clst);
01042 if (cs < 2) return 1;
01043 if (cs == 0xFFFFFFFF) return cs;
01044 if (cs < fs->n_fatent) return cs;
01045 scl = clst;
01046 }
01047
01048 ncl = scl;
01049 for (;;) {
01050 ncl++;
01051 if (ncl >= fs->n_fatent) {
01052 ncl = 2;
01053 if (ncl > scl) return 0;
01054 }
01055 cs = get_fat(fs, ncl);
01056 if (cs == 0) break;
01057 if (cs == 0xFFFFFFFF || cs == 1)
01058 return cs;
01059 if (ncl == scl) return 0;
01060 }
01061
01062 res = put_fat(fs, ncl, 0x0FFFFFFF);
01063 if (res == FR_OK && clst != 0) {
01064 res = put_fat(fs, clst, ncl);
01065 }
01066 if (res == FR_OK) {
01067 fs->last_clust = ncl;
01068 if (fs->free_clust != 0xFFFFFFFF) {
01069 fs->free_clust--;
01070 fs->fsi_flag |= 1;
01071 }
01072 } else {
01073 ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
01074 }
01075
01076 return ncl;
01077 }
01078 #endif
01079
01080
01081
01082
01083
01084
01085
01086
01087 #if _USE_FASTSEEK
01088 static
01089 DWORD clmt_clust (
01090 FIL* fp,
01091 DWORD ofs
01092 )
01093 {
01094 DWORD cl, ncl, *tbl;
01095
01096
01097 tbl = fp->cltbl + 1;
01098 cl = ofs / SS(fp->fs) / fp->fs->csize;
01099 for (;;) {
01100 ncl = *tbl++;
01101 if (!ncl) return 0;
01102 if (cl < ncl) break;
01103 cl -= ncl; tbl++;
01104 }
01105 return cl + *tbl;
01106 }
01107 #endif
01108
01109
01110
01111
01112
01113
01114
01115
01116 static
01117 FRESULT dir_sdi (
01118 DIR* dp,
01119 UINT idx
01120 )
01121 {
01122 DWORD clst, sect;
01123 UINT ic;
01124
01125
01126 dp->index = (WORD)idx;
01127 clst = dp->sclust;
01128 if (clst == 1 || clst >= dp->fs->n_fatent)
01129 return FR_INT_ERR;
01130 if (!clst && dp->fs->fs_type == FS_FAT32)
01131 clst = dp->fs->dirbase;
01132
01133 if (clst == 0) {
01134 if (idx >= dp->fs->n_rootdir)
01135 return FR_INT_ERR;
01136 sect = dp->fs->dirbase;
01137 }
01138 else {
01139 ic = SS(dp->fs) / SZ_DIR * dp->fs->csize;
01140 while (idx >= ic) {
01141 clst = get_fat(dp->fs, clst);
01142 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
01143 if (clst < 2 || clst >= dp->fs->n_fatent)
01144 return FR_INT_ERR;
01145 idx -= ic;
01146 }
01147 sect = clust2sect(dp->fs, clst);
01148 }
01149 dp->clust = clst;
01150 if (!sect) return FR_INT_ERR;
01151 dp->sect = sect + idx / (SS(dp->fs) / SZ_DIR);
01152 dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIR)) * SZ_DIR;
01153
01154 return FR_OK;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164 static
01165 FRESULT dir_next (
01166 DIR* dp,
01167 int stretch
01168 )
01169 {
01170 DWORD clst;
01171 UINT i;
01172
01173
01174 i = dp->index + 1;
01175 if (!(i & 0xFFFF) || !dp->sect)
01176 return FR_NO_FILE;
01177
01178 if (!(i % (SS(dp->fs) / SZ_DIR))) {
01179 dp->sect++;
01180
01181 if (!dp->clust) {
01182 if (i >= dp->fs->n_rootdir)
01183 return FR_NO_FILE;
01184 }
01185 else {
01186 if (((i / (SS(dp->fs) / SZ_DIR)) & (dp->fs->csize - 1)) == 0) {
01187 clst = get_fat(dp->fs, dp->clust);
01188 if (clst <= 1) return FR_INT_ERR;
01189 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
01190 if (clst >= dp->fs->n_fatent) {
01191 #if !_FS_READONLY
01192 UINT c;
01193 if (!stretch) return FR_NO_FILE;
01194 clst = create_chain(dp->fs, dp->clust);
01195 if (clst == 0) return FR_DENIED;
01196 if (clst == 1) return FR_INT_ERR;
01197 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
01198
01199 if (sync_window(dp->fs)) return FR_DISK_ERR;
01200 mem_set(dp->fs->win, 0, SS(dp->fs));
01201 dp->fs->winsect = clust2sect(dp->fs, clst);
01202 for (c = 0; c < dp->fs->csize; c++) {
01203 dp->fs->wflag = 1;
01204 if (sync_window(dp->fs)) return FR_DISK_ERR;
01205 dp->fs->winsect++;
01206 }
01207 dp->fs->winsect -= c;
01208 #else
01209 if (!stretch) return FR_NO_FILE;
01210 return FR_NO_FILE;
01211 #endif
01212 }
01213 dp->clust = clst;
01214 dp->sect = clust2sect(dp->fs, clst);
01215 }
01216 }
01217 }
01218
01219 dp->index = (WORD)i;
01220 dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIR)) * SZ_DIR;
01221
01222 return FR_OK;
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232 #if !_FS_READONLY
01233 static
01234 FRESULT dir_alloc (
01235 DIR* dp,
01236 UINT nent
01237 )
01238 {
01239 FRESULT res;
01240 UINT n;
01241
01242
01243 res = dir_sdi(dp, 0);
01244 if (res == FR_OK) {
01245 n = 0;
01246 do {
01247 res = move_window(dp->fs, dp->sect);
01248 if (res != FR_OK) break;
01249 if (dp->dir[0] == DDE || dp->dir[0] == 0) {
01250 if (++n == nent) break;
01251 } else {
01252 n = 0;
01253 }
01254 res = dir_next(dp, 1);
01255 } while (res == FR_OK);
01256 }
01257 if (res == FR_NO_FILE) res = FR_DENIED;
01258 return res;
01259 }
01260 #endif
01261
01262
01263
01264
01265
01266
01267
01268
01269 static
01270 DWORD ld_clust (
01271 FATFS* fs,
01272 BYTE* dir
01273 )
01274 {
01275 DWORD cl;
01276
01277 cl = LD_WORD(dir+DIR_FstClusLO);
01278 if (fs->fs_type == FS_FAT32)
01279 cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
01280
01281 return cl;
01282 }
01283
01284
01285 #if !_FS_READONLY
01286 static
01287 void st_clust (
01288 BYTE* dir,
01289 DWORD cl
01290 )
01291 {
01292 ST_WORD(dir+DIR_FstClusLO, cl);
01293 ST_WORD(dir+DIR_FstClusHI, cl >> 16);
01294 }
01295 #endif
01296
01297
01298
01299
01300
01301
01302
01303 #if _USE_LFN
01304 static
01305 const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};
01306
01307
01308 static
01309 int cmp_lfn (
01310 WCHAR* lfnbuf,
01311 BYTE* dir
01312 )
01313 {
01314 UINT i, s;
01315 WCHAR wc, uc;
01316
01317
01318 i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13;
01319 s = 0; wc = 1;
01320 do {
01321 uc = LD_WORD(dir+LfnOfs[s]);
01322 if (wc) {
01323 wc = ff_wtoupper(uc);
01324 if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++]))
01325 return 0;
01326 } else {
01327 if (uc != 0xFFFF) return 0;
01328 }
01329 } while (++s < 13);
01330
01331 if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i])
01332 return 0;
01333
01334 return 1;
01335 }
01336
01337
01338
01339 static
01340 int pick_lfn (
01341 WCHAR* lfnbuf,
01342 BYTE* dir
01343 )
01344 {
01345 UINT i, s;
01346 WCHAR wc, uc;
01347
01348
01349 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13;
01350
01351 s = 0; wc = 1;
01352 do {
01353 uc = LD_WORD(dir+LfnOfs[s]);
01354 if (wc) {
01355 if (i >= _MAX_LFN) return 0;
01356 lfnbuf[i++] = wc = uc;
01357 } else {
01358 if (uc != 0xFFFF) return 0;
01359 }
01360 } while (++s < 13);
01361
01362 if (dir[LDIR_Ord] & LLE) {
01363 if (i >= _MAX_LFN) return 0;
01364 lfnbuf[i] = 0;
01365 }
01366
01367 return 1;
01368 }
01369
01370
01371 #if !_FS_READONLY
01372 static
01373 void fit_lfn (
01374 const WCHAR* lfnbuf,
01375 BYTE* dir,
01376 BYTE ord,
01377 BYTE sum
01378 )
01379 {
01380 UINT i, s;
01381 WCHAR wc;
01382
01383
01384 dir[LDIR_Chksum] = sum;
01385 dir[LDIR_Attr] = AM_LFN;
01386 dir[LDIR_Type] = 0;
01387 ST_WORD(dir+LDIR_FstClusLO, 0);
01388
01389 i = (ord - 1) * 13;
01390 s = wc = 0;
01391 do {
01392 if (wc != 0xFFFF) wc = lfnbuf[i++];
01393 ST_WORD(dir+LfnOfs[s], wc);
01394 if (!wc) wc = 0xFFFF;
01395 } while (++s < 13);
01396 if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE;
01397 dir[LDIR_Ord] = ord;
01398 }
01399
01400 #endif
01401 #endif
01402
01403
01404
01405
01406
01407
01408
01409 #if _USE_LFN
01410 static
01411 void gen_numname (
01412 BYTE* dst,
01413 const BYTE* src,
01414 const WCHAR* lfn,
01415 UINT seq
01416 )
01417 {
01418 BYTE ns[8], c;
01419 UINT i, j;
01420
01421
01422 mem_cpy(dst, src, 11);
01423
01424 if (seq > 5) {
01425 WCHAR wc;
01426 DWORD sr = seq;
01427
01428 while (*lfn) {
01429 wc = *lfn++;
01430 for (i = 0; i < 16; i++) {
01431 sr = (sr << 1) + (wc & 1);
01432 wc >>= 1;
01433 if (sr & 0x10000) sr ^= 0x11021;
01434 }
01435 }
01436 seq = (UINT)sr;
01437 }
01438
01439
01440 i = 7;
01441 do {
01442 c = (seq % 16) + '0';
01443 if (c > '9') c += 7;
01444 ns[i--] = c;
01445 seq /= 16;
01446 } while (seq);
01447 ns[i] = '~';
01448
01449
01450 for (j = 0; j < i && dst[j] != ' '; j++) {
01451 if (IsDBCS1(dst[j])) {
01452 if (j == i - 1) break;
01453 j++;
01454 }
01455 }
01456 do {
01457 dst[j++] = (i < 8) ? ns[i++] : ' ';
01458 } while (j < 8);
01459 }
01460 #endif
01461
01462
01463
01464
01465
01466
01467
01468 #if _USE_LFN
01469 static
01470 BYTE sum_sfn (
01471 const BYTE* dir
01472 )
01473 {
01474 BYTE sum = 0;
01475 UINT n = 11;
01476
01477 do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
01478 return sum;
01479 }
01480 #endif
01481
01482
01483
01484
01485
01486
01487
01488
01489 static
01490 FRESULT dir_find (
01491 DIR* dp
01492 )
01493 {
01494 FRESULT res;
01495 BYTE c, *dir;
01496 #if _USE_LFN
01497 BYTE a, ord, sum;
01498 #endif
01499
01500 res = dir_sdi(dp, 0);
01501 if (res != FR_OK) return res;
01502
01503 #if _USE_LFN
01504 ord = sum = 0xFF; dp->lfn_idx = 0xFFFF;
01505 #endif
01506 do {
01507 res = move_window(dp->fs, dp->sect);
01508 if (res != FR_OK) break;
01509 dir = dp->dir;
01510 c = dir[DIR_Name];
01511 if (c == 0) { res = FR_NO_FILE; break; }
01512 #if _USE_LFN
01513 a = dir[DIR_Attr] & AM_MASK;
01514 if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) {
01515 ord = 0xFF; dp->lfn_idx = 0xFFFF;
01516 } else {
01517 if (a == AM_LFN) {
01518 if (dp->lfn) {
01519 if (c & LLE) {
01520 sum = dir[LDIR_Chksum];
01521 c &= ~LLE; ord = c;
01522 dp->lfn_idx = dp->index;
01523 }
01524
01525 ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF;
01526 }
01527 } else {
01528 if (!ord && sum == sum_sfn(dir)) break;
01529 if (!(dp->fn[NS] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break;
01530 ord = 0xFF; dp->lfn_idx = 0xFFFF;
01531 }
01532 }
01533 #else
01534 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dp->fn, 11))
01535 break;
01536 #endif
01537 res = dir_next(dp, 0);
01538 } while (res == FR_OK);
01539
01540 return res;
01541 }
01542
01543
01544
01545
01546
01547
01548
01549 #if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2
01550 static
01551 FRESULT dir_read (
01552 DIR* dp,
01553 int vol
01554 )
01555 {
01556 FRESULT res;
01557 BYTE a, c, *dir;
01558 #if _USE_LFN
01559 BYTE ord = 0xFF, sum = 0xFF;
01560 #endif
01561
01562 res = FR_NO_FILE;
01563 while (dp->sect) {
01564 res = move_window(dp->fs, dp->sect);
01565 if (res != FR_OK) break;
01566 dir = dp->dir;
01567 c = dir[DIR_Name];
01568 if (c == 0) { res = FR_NO_FILE; break; }
01569 a = dir[DIR_Attr] & AM_MASK;
01570 #if _USE_LFN
01571 if (c == DDE || (!_FS_RPATH && c == '.') || (int)(a == AM_VOL) != vol) {
01572 ord = 0xFF;
01573 } else {
01574 if (a == AM_LFN) {
01575 if (c & LLE) {
01576 sum = dir[LDIR_Chksum];
01577 c &= ~LLE; ord = c;
01578 dp->lfn_idx = dp->index;
01579 }
01580
01581 ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF;
01582 } else {
01583 if (ord || sum != sum_sfn(dir))
01584 dp->lfn_idx = 0xFFFF;
01585 break;
01586 }
01587 }
01588 #else
01589 if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (int)(a == AM_VOL) == vol)
01590 break;
01591 #endif
01592 res = dir_next(dp, 0);
01593 if (res != FR_OK) break;
01594 }
01595
01596 if (res != FR_OK) dp->sect = 0;
01597
01598 return res;
01599 }
01600 #endif
01601
01602
01603
01604
01605
01606
01607
01608 #if !_FS_READONLY
01609 static
01610 FRESULT dir_register (
01611 DIR* dp
01612 )
01613 {
01614 FRESULT res;
01615 #if _USE_LFN
01616 UINT n, nent;
01617 BYTE sn[12], *fn, sum;
01618 WCHAR *lfn;
01619
01620
01621 fn = dp->fn; lfn = dp->lfn;
01622 mem_cpy(sn, fn, 12);
01623
01624 if (_FS_RPATH && (sn[NS] & NS_DOT))
01625 return FR_INVALID_NAME;
01626
01627 if (sn[NS] & NS_LOSS) {
01628 fn[NS] = 0; dp->lfn = 0;
01629 for (n = 1; n < 100; n++) {
01630 gen_numname(fn, sn, lfn, n);
01631 res = dir_find(dp);
01632 if (res != FR_OK) break;
01633 }
01634 if (n == 100) return FR_DENIED;
01635 if (res != FR_NO_FILE) return res;
01636 fn[NS] = sn[NS]; dp->lfn = lfn;
01637 }
01638
01639 if (sn[NS] & NS_LFN) {
01640 for (n = 0; lfn[n]; n++) ;
01641 nent = (n + 25) / 13;
01642 } else {
01643 nent = 1;
01644 }
01645 res = dir_alloc(dp, nent);
01646
01647 if (res == FR_OK && --nent) {
01648 res = dir_sdi(dp, dp->index - nent);
01649 if (res == FR_OK) {
01650 sum = sum_sfn(dp->fn);
01651 do {
01652 res = move_window(dp->fs, dp->sect);
01653 if (res != FR_OK) break;
01654 fit_lfn(dp->lfn, dp->dir, (BYTE)nent, sum);
01655 dp->fs->wflag = 1;
01656 res = dir_next(dp, 0);
01657 } while (res == FR_OK && --nent);
01658 }
01659 }
01660 #else
01661 res = dir_alloc(dp, 1);
01662 #endif
01663
01664 if (res == FR_OK) {
01665 res = move_window(dp->fs, dp->sect);
01666 if (res == FR_OK) {
01667 mem_set(dp->dir, 0, SZ_DIR);
01668 mem_cpy(dp->dir, dp->fn, 11);
01669 #if _USE_LFN
01670 dp->dir[DIR_NTres] = dp->fn[NS] & (NS_BODY | NS_EXT);
01671 #endif
01672 dp->fs->wflag = 1;
01673 }
01674 }
01675
01676 return res;
01677 }
01678 #endif
01679
01680
01681
01682
01683
01684
01685
01686 #if !_FS_READONLY && !_FS_MINIMIZE
01687 static
01688 FRESULT dir_remove (
01689 DIR* dp
01690 )
01691 {
01692 FRESULT res;
01693 #if _USE_LFN
01694 UINT i;
01695
01696 i = dp->index;
01697 res = dir_sdi(dp, (dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx);
01698 if (res == FR_OK) {
01699 do {
01700 res = move_window(dp->fs, dp->sect);
01701 if (res != FR_OK) break;
01702 mem_set(dp->dir, 0, SZ_DIR);
01703 *dp->dir = DDE;
01704 dp->fs->wflag = 1;
01705 if (dp->index >= i) break;
01706 res = dir_next(dp, 0);
01707 } while (res == FR_OK);
01708 if (res == FR_NO_FILE) res = FR_INT_ERR;
01709 }
01710
01711 #else
01712 res = dir_sdi(dp, dp->index);
01713 if (res == FR_OK) {
01714 res = move_window(dp->fs, dp->sect);
01715 if (res == FR_OK) {
01716 mem_set(dp->dir, 0, SZ_DIR);
01717 *dp->dir = DDE;
01718 dp->fs->wflag = 1;
01719 }
01720 }
01721 #endif
01722
01723 return res;
01724 }
01725 #endif
01726
01727
01728
01729
01730
01731
01732
01733 #if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2
01734 static
01735 void get_fileinfo (
01736 DIR* dp,
01737 FILINFO* fno
01738 )
01739 {
01740 UINT i;
01741 TCHAR *p, c;
01742
01743
01744 p = fno->fname;
01745 if (dp->sect) {
01746 BYTE *dir = dp->dir;
01747
01748 i = 0;
01749 while (i < 11) {
01750 c = (TCHAR)dir[i++];
01751 if (c == ' ') continue;
01752 if (c == NDDE) c = (TCHAR)DDE;
01753 if (i == 9) *p++ = '.';
01754 #if _USE_LFN
01755 if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY)))
01756 c += 0x20;
01757 #if _LFN_UNICODE
01758 if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i]))
01759 c = c << 8 | dir[i++];
01760 c = ff_convert(c, 1);
01761 if (!c) c = '?';
01762 #endif
01763 #endif
01764 *p++ = c;
01765 }
01766 fno->fattrib = dir[DIR_Attr];
01767 fno->fsize = LD_DWORD(dir+DIR_FileSize);
01768 fno->fdate = LD_WORD(dir+DIR_WrtDate);
01769 fno->ftime = LD_WORD(dir+DIR_WrtTime);
01770 }
01771 *p = 0;
01772
01773 #if _USE_LFN
01774 if (fno->lfname) {
01775 WCHAR w, *lfn;
01776
01777 i = 0; p = fno->lfname;
01778 if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) {
01779 lfn = dp->lfn;
01780 while ((w = *lfn++) != 0) {
01781 #if !_LFN_UNICODE
01782 w = ff_convert(w, 0);
01783 if (!w) { i = 0; break; }
01784 if (_DF1S && w >= 0x100)
01785 p[i++] = (TCHAR)(w >> 8);
01786 #endif
01787 if (i >= fno->lfsize - 1) { i = 0; break; }
01788 p[i++] = (TCHAR)w;
01789 }
01790 }
01791 p[i] = 0;
01792 }
01793 #endif
01794 }
01795 #endif
01796
01797
01798
01799
01800
01801
01802
01803
01804 static
01805 FRESULT create_name (
01806 DIR* dp,
01807 const TCHAR** path
01808 )
01809 {
01810 #if _USE_LFN
01811 BYTE b, cf;
01812 WCHAR w, *lfn;
01813 UINT i, ni, si, di;
01814 const TCHAR *p;
01815
01816
01817 for (p = *path; *p == '/' || *p == '\\'; p++) ;
01818 lfn = dp->lfn;
01819 si = di = 0;
01820 for (;;) {
01821 w = p[si++];
01822 if (w < ' ' || w == '/' || w == '\\') break;
01823 if (di >= _MAX_LFN)
01824 return FR_INVALID_NAME;
01825 #if !_LFN_UNICODE
01826 w &= 0xFF;
01827 if (IsDBCS1(w)) {
01828 b = (BYTE)p[si++];
01829 if (!IsDBCS2(b))
01830 return FR_INVALID_NAME;
01831 w = (w << 8) + b;
01832 }
01833 w = ff_convert(w, 1);
01834 if (!w) return FR_INVALID_NAME;
01835 #endif
01836 if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w))
01837 return FR_INVALID_NAME;
01838 lfn[di++] = w;
01839 }
01840 *path = &p[si];
01841 cf = (w < ' ') ? NS_LAST : 0;
01842 #if _FS_RPATH
01843 if ((di == 1 && lfn[di-1] == '.') ||
01844 (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) {
01845 lfn[di] = 0;
01846 for (i = 0; i < 11; i++)
01847 dp->fn[i] = (i < di) ? '.' : ' ';
01848 dp->fn[i] = cf | NS_DOT;
01849 return FR_OK;
01850 }
01851 #endif
01852 while (di) {
01853 w = lfn[di-1];
01854 if (w != ' ' && w != '.') break;
01855 di--;
01856 }
01857 if (!di) return FR_INVALID_NAME;
01858
01859 lfn[di] = 0;
01860
01861
01862 mem_set(dp->fn, ' ', 11);
01863 for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ;
01864 if (si) cf |= NS_LOSS | NS_LFN;
01865 while (di && lfn[di - 1] != '.') di--;
01866
01867 b = i = 0; ni = 8;
01868 for (;;) {
01869 w = lfn[si++];
01870 if (!w) break;
01871 if (w == ' ' || (w == '.' && si != di)) {
01872 cf |= NS_LOSS | NS_LFN; continue;
01873 }
01874
01875 if (i >= ni || si == di) {
01876 if (ni == 11) {
01877 cf |= NS_LOSS | NS_LFN; break;
01878 }
01879 if (si != di) cf |= NS_LOSS | NS_LFN;
01880 if (si > di) break;
01881 si = di; i = 8; ni = 11;
01882 b <<= 2; continue;
01883 }
01884
01885 if (w >= 0x80) {
01886 #ifdef _EXCVT
01887 w = ff_convert(w, 0);
01888 if (w) w = ExCvt[w - 0x80];
01889 #else
01890 w = ff_convert(ff_wtoupper(w), 0);
01891 #endif
01892 cf |= NS_LFN;
01893 }
01894
01895 if (_DF1S && w >= 0x100) {
01896 if (i >= ni - 1) {
01897 cf |= NS_LOSS | NS_LFN; i = ni; continue;
01898 }
01899 dp->fn[i++] = (BYTE)(w >> 8);
01900 } else {
01901 if (!w || chk_chr("+,;=[]", w)) {
01902 w = '_'; cf |= NS_LOSS | NS_LFN;
01903 } else {
01904 if (IsUpper(w)) {
01905 b |= 2;
01906 } else {
01907 if (IsLower(w)) {
01908 b |= 1; w -= 0x20;
01909 }
01910 }
01911 }
01912 }
01913 dp->fn[i++] = (BYTE)w;
01914 }
01915
01916 if (dp->fn[0] == DDE) dp->fn[0] = NDDE;
01917
01918 if (ni == 8) b <<= 2;
01919 if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03)
01920 cf |= NS_LFN;
01921 if (!(cf & NS_LFN)) {
01922 if ((b & 0x03) == 0x01) cf |= NS_EXT;
01923 if ((b & 0x0C) == 0x04) cf |= NS_BODY;
01924 }
01925
01926 dp->fn[NS] = cf;
01927
01928 return FR_OK;
01929
01930
01931 #else
01932 BYTE b, c, d, *sfn;
01933 UINT ni, si, i;
01934 const char *p;
01935
01936
01937 for (p = *path; *p == '/' || *p == '\\'; p++) ;
01938 sfn = dp->fn;
01939 mem_set(sfn, ' ', 11);
01940 si = i = b = 0; ni = 8;
01941 #if _FS_RPATH
01942 if (p[si] == '.') {
01943 for (;;) {
01944 c = (BYTE)p[si++];
01945 if (c != '.' || si >= 3) break;
01946 sfn[i++] = c;
01947 }
01948 if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
01949 *path = &p[si];
01950 sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT;
01951 return FR_OK;
01952 }
01953 #endif
01954 for (;;) {
01955 c = (BYTE)p[si++];
01956 if (c <= ' ' || c == '/' || c == '\\') break;
01957 if (c == '.' || i >= ni) {
01958 if (ni != 8 || c != '.') return FR_INVALID_NAME;
01959 i = 8; ni = 11;
01960 b <<= 2; continue;
01961 }
01962 if (c >= 0x80) {
01963 b |= 3;
01964 #ifdef _EXCVT
01965 c = ExCvt[c - 0x80];
01966 #else
01967 #if !_DF1S
01968 return FR_INVALID_NAME;
01969 #endif
01970 #endif
01971 }
01972 if (IsDBCS1(c)) {
01973 d = (BYTE)p[si++];
01974 if (!IsDBCS2(d) || i >= ni - 1)
01975 return FR_INVALID_NAME;
01976 sfn[i++] = c;
01977 sfn[i++] = d;
01978 } else {
01979 if (chk_chr("\"*+,:;<=>\?[]|\x7F", c))
01980 return FR_INVALID_NAME;
01981 if (IsUpper(c)) {
01982 b |= 2;
01983 } else {
01984 if (IsLower(c)) {
01985 b |= 1; c -= 0x20;
01986 }
01987 }
01988 sfn[i++] = c;
01989 }
01990 }
01991 *path = &p[si];
01992 c = (c <= ' ') ? NS_LAST : 0;
01993
01994 if (!i) return FR_INVALID_NAME;
01995 if (sfn[0] == DDE) sfn[0] = NDDE;
01996
01997 if (ni == 8) b <<= 2;
01998 if ((b & 0x03) == 0x01) c |= NS_EXT;
01999 if ((b & 0x0C) == 0x04) c |= NS_BODY;
02000
02001 sfn[NS] = c;
02002
02003 return FR_OK;
02004 #endif
02005 }
02006
02007
02008
02009
02010
02011
02012
02013
02014 static
02015 FRESULT follow_path (
02016 DIR* dp,
02017 const TCHAR* path
02018 )
02019 {
02020 FRESULT res;
02021 BYTE *dir, ns;
02022
02023
02024 #if _FS_RPATH
02025 if (*path == '/' || *path == '\\') {
02026 path++; dp->sclust = 0;
02027 } else {
02028 dp->sclust = dp->fs->cdir;
02029 }
02030 #else
02031 if (*path == '/' || *path == '\\')
02032 path++;
02033 dp->sclust = 0;
02034 #endif
02035
02036 if ((UINT)*path < ' ') {
02037 res = dir_sdi(dp, 0);
02038 dp->dir = 0;
02039 } else {
02040 for (;;) {
02041 res = create_name(dp, &path);
02042 if (res != FR_OK) break;
02043 res = dir_find(dp);
02044 ns = dp->fn[NS];
02045 if (res != FR_OK) {
02046 if (res == FR_NO_FILE) {
02047 if (_FS_RPATH && (ns & NS_DOT)) {
02048 dp->sclust = 0; dp->dir = 0;
02049 if (!(ns & NS_LAST)) continue;
02050 res = FR_OK;
02051 } else {
02052 if (!(ns & NS_LAST)) res = FR_NO_PATH;
02053 }
02054 }
02055 break;
02056 }
02057 if (ns & NS_LAST) break;
02058 dir = dp->dir;
02059 if (!(dir[DIR_Attr] & AM_DIR)) {
02060 res = FR_NO_PATH; break;
02061 }
02062 dp->sclust = ld_clust(dp->fs, dir);
02063 }
02064 }
02065
02066 return res;
02067 }
02068
02069
02070
02071
02072
02073
02074
02075
02076 static
02077 int get_ldnumber (
02078 const TCHAR** path
02079 )
02080 {
02081 const TCHAR *tp, *tt;
02082 UINT i;
02083 int vol = -1;
02084
02085
02086 if (*path) {
02087 for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ;
02088 if (*tt == ':') {
02089 tp = *path;
02090 i = *tp++ - '0';
02091 if (i < 10 && tp == tt) {
02092 if (i < _VOLUMES) {
02093 vol = (int)i;
02094 *path = ++tt;
02095 }
02096 } else {
02097 #if _STR_VOLUME_ID
02098 static const char* const str[] = {_VOLUME_STRS};
02099 const char *sp;
02100 char c;
02101 TCHAR tc;
02102
02103 i = 0; tt++;
02104 do {
02105 sp = str[i]; tp = *path;
02106 do {
02107 c = *sp++; tc = *tp++;
02108 if (IsLower(tc)) tc -= 0x20;
02109 } while (c && (TCHAR)c == tc);
02110 } while ((c || tp != tt) && ++i < _VOLUMES);
02111 if (i < _VOLUMES) {
02112 vol = (int)i;
02113 *path = tt;
02114 }
02115 #endif
02116 }
02117 return vol;
02118 }
02119 #if _FS_RPATH && _VOLUMES >= 2
02120 vol = CurrVol;
02121 #else
02122 vol = 0;
02123 #endif
02124 }
02125 return vol;
02126 }
02127
02128
02129
02130
02131
02132
02133
02134
02135 static
02136 BYTE check_fs (
02137 FATFS* fs,
02138 DWORD sect
02139 )
02140 {
02141 fs->wflag = 0; fs->winsect = 0xFFFFFFFF;
02142 if (move_window(fs, sect) != FR_OK)
02143 return 3;
02144
02145 if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)
02146 return 2;
02147
02148 if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
02149 return 0;
02150 if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
02151 return 0;
02152
02153 return 1;
02154 }
02155
02156
02157
02158
02159
02160
02161
02162
02163 static
02164 FRESULT find_volume (
02165 FATFS** rfs,
02166 const TCHAR** path,
02167 BYTE wmode
02168 )
02169 {
02170 BYTE fmt;
02171 int vol;
02172 DSTATUS stat;
02173 DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
02174 WORD nrsv;
02175 FATFS *fs;
02176
02177
02178
02179 *rfs = 0;
02180 vol = get_ldnumber(path);
02181 if (vol < 0) return FR_INVALID_DRIVE;
02182
02183
02184 fs = FatFs[vol];
02185 if (!fs) return FR_NOT_ENABLED;
02186
02187 ENTER_FF(fs);
02188 *rfs = fs;
02189
02190 if (fs->fs_type) {
02191 stat = disk_status(fs->drv);
02192 if (!(stat & STA_NOINIT)) {
02193 if (!_FS_READONLY && wmode && (stat & STA_PROTECT))
02194 return FR_WRITE_PROTECTED;
02195 return FR_OK;
02196 }
02197 }
02198
02199
02200
02201
02202 fs->fs_type = 0;
02203 fs->drv = LD2PD(vol);
02204 stat = disk_initialize(fs->drv);
02205 if (stat & STA_NOINIT)
02206 return FR_NOT_READY;
02207 if (!_FS_READONLY && wmode && (stat & STA_PROTECT))
02208 return FR_WRITE_PROTECTED;
02209 #if _MAX_SS != _MIN_SS
02210 if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK
02211 || SS(fs) < _MIN_SS || SS(fs) > _MAX_SS) return FR_DISK_ERR;
02212 #endif
02213
02214 bsect = 0;
02215 fmt = check_fs(fs, bsect);
02216 if (fmt == 1 || (!fmt && (LD2PT(vol)))) {
02217 UINT i;
02218 DWORD br[4];
02219
02220 for (i = 0; i < 4; i++) {
02221 BYTE *pt = fs->win+MBR_Table + i * SZ_PTE;
02222 br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0;
02223 }
02224 i = LD2PT(vol);
02225 if (i) i--;
02226 do {
02227 bsect = br[i];
02228 fmt = bsect ? check_fs(fs, bsect) : 2;
02229 } while (!LD2PT(vol) && fmt && ++i < 4);
02230 }
02231 if (fmt == 3) return FR_DISK_ERR;
02232 if (fmt) return FR_NO_FILESYSTEM;
02233
02234
02235
02236 if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs))
02237 return FR_NO_FILESYSTEM;
02238
02239 fasize = LD_WORD(fs->win+BPB_FATSz16);
02240 if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32);
02241 fs->fsize = fasize;
02242
02243 fs->n_fats = fs->win[BPB_NumFATs];
02244 if (fs->n_fats != 1 && fs->n_fats != 2)
02245 return FR_NO_FILESYSTEM;
02246 fasize *= fs->n_fats;
02247
02248 fs->csize = fs->win[BPB_SecPerClus];
02249 if (!fs->csize || (fs->csize & (fs->csize - 1)))
02250 return FR_NO_FILESYSTEM;
02251
02252 fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt);
02253 if (fs->n_rootdir % (SS(fs) / SZ_DIR))
02254 return FR_NO_FILESYSTEM;
02255
02256 tsect = LD_WORD(fs->win+BPB_TotSec16);
02257 if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32);
02258
02259 nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt);
02260 if (!nrsv) return FR_NO_FILESYSTEM;
02261
02262
02263 sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR);
02264 if (tsect < sysect) return FR_NO_FILESYSTEM;
02265 nclst = (tsect - sysect) / fs->csize;
02266 if (!nclst) return FR_NO_FILESYSTEM;
02267 fmt = FS_FAT12;
02268 if (nclst >= MIN_FAT16) fmt = FS_FAT16;
02269 if (nclst >= MIN_FAT32) fmt = FS_FAT32;
02270
02271
02272 fs->n_fatent = nclst + 2;
02273 fs->volbase = bsect;
02274 fs->fatbase = bsect + nrsv;
02275 fs->database = bsect + sysect;
02276 if (fmt == FS_FAT32) {
02277 if (fs->n_rootdir) return FR_NO_FILESYSTEM;
02278 fs->dirbase = LD_DWORD(fs->win+BPB_RootClus);
02279 szbfat = fs->n_fatent * 4;
02280 } else {
02281 if (!fs->n_rootdir) return FR_NO_FILESYSTEM;
02282 fs->dirbase = fs->fatbase + fasize;
02283 szbfat = (fmt == FS_FAT16) ?
02284 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
02285 }
02286 if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))
02287 return FR_NO_FILESYSTEM;
02288
02289 #if !_FS_READONLY
02290
02291 fs->last_clust = fs->free_clust = 0xFFFFFFFF;
02292
02293
02294 fs->fsi_flag = 0x80;
02295 #if (_FS_NOFSINFO & 3) != 3
02296 if (fmt == FS_FAT32
02297 && LD_WORD(fs->win+BPB_FSInfo) == 1
02298 && move_window(fs, bsect + 1) == FR_OK)
02299 {
02300 fs->fsi_flag = 0;
02301 if (LD_WORD(fs->win+BS_55AA) == 0xAA55
02302 && LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252
02303 && LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272)
02304 {
02305 #if (_FS_NOFSINFO & 1) == 0
02306 fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count);
02307 #endif
02308 #if (_FS_NOFSINFO & 2) == 0
02309 fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free);
02310 #endif
02311 }
02312 }
02313 #endif
02314 #endif
02315 fs->fs_type = fmt;
02316 fs->id = ++Fsid;
02317 #if _FS_RPATH
02318 fs->cdir = 0;
02319 #endif
02320 #if _FS_LOCK
02321 clear_lock(fs);
02322 #endif
02323
02324 return FR_OK;
02325 }
02326
02327
02328
02329
02330
02331
02332
02333
02334 static
02335 FRESULT validate (
02336 void* obj
02337 )
02338 {
02339 FIL *fil = (FIL*)obj;
02340
02341
02342 if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
02343 return FR_INVALID_OBJECT;
02344
02345 ENTER_FF(fil->fs);
02346
02347 if (disk_status(fil->fs->drv) & STA_NOINIT)
02348 return FR_NOT_READY;
02349
02350 return FR_OK;
02351 }
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368 FRESULT f_mount (
02369 FATFS* fs,
02370 const TCHAR* path,
02371 BYTE opt
02372 )
02373 {
02374 FATFS *cfs;
02375 int vol;
02376 FRESULT res;
02377 const TCHAR *rp = path;
02378
02379
02380 vol = get_ldnumber(&rp);
02381 if (vol < 0) return FR_INVALID_DRIVE;
02382 cfs = FatFs[vol];
02383
02384 if (cfs) {
02385 #if _FS_LOCK
02386 clear_lock(cfs);
02387 #endif
02388 #if _FS_REENTRANT
02389 if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
02390 #endif
02391 cfs->fs_type = 0;
02392 }
02393
02394 if (fs) {
02395 fs->fs_type = 0;
02396 #if _FS_REENTRANT
02397 if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
02398 #endif
02399 }
02400 FatFs[vol] = fs;
02401
02402 if (!fs || opt != 1) return FR_OK;
02403
02404 res = find_volume(&fs, &path, 0);
02405 LEAVE_FF(fs, res);
02406 }
02407
02408
02409
02410
02411
02412
02413
02414
02415 FRESULT f_open (
02416 FIL* fp,
02417 const TCHAR* path,
02418 BYTE mode
02419 )
02420 {
02421 FRESULT res;
02422 DIR dj;
02423 BYTE *dir;
02424 DEF_NAMEBUF;
02425
02426
02427 if (!fp) return FR_INVALID_OBJECT;
02428 fp->fs = 0;
02429
02430
02431 #if !_FS_READONLY
02432 mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
02433 res = find_volume(&dj.fs, &path, (BYTE)(mode & ~FA_READ));
02434 #else
02435 mode &= FA_READ;
02436 res = find_volume(&dj.fs, &path, 0);
02437 #endif
02438 if (res == FR_OK) {
02439 INIT_BUF(dj);
02440 res = follow_path(&dj, path);
02441 dir = dj.dir;
02442 #if !_FS_READONLY
02443 if (res == FR_OK) {
02444 if (!dir)
02445 res = FR_INVALID_NAME;
02446 #if _FS_LOCK
02447 else
02448 res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
02449 #endif
02450 }
02451
02452 if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
02453 DWORD dw, cl;
02454
02455 if (res != FR_OK) {
02456 if (res == FR_NO_FILE)
02457 #if _FS_LOCK
02458 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
02459 #else
02460 res = dir_register(&dj);
02461 #endif
02462 mode |= FA_CREATE_ALWAYS;
02463 dir = dj.dir;
02464 }
02465 else {
02466 if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {
02467 res = FR_DENIED;
02468 } else {
02469 if (mode & FA_CREATE_NEW)
02470 res = FR_EXIST;
02471 }
02472 }
02473 if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {
02474 dw = get_fattime();
02475 ST_DWORD(dir+DIR_CrtTime, dw);
02476 dir[DIR_Attr] = 0;
02477 ST_DWORD(dir+DIR_FileSize, 0);
02478 cl = ld_clust(dj.fs, dir);
02479 st_clust(dir, 0);
02480 dj.fs->wflag = 1;
02481 if (cl) {
02482 dw = dj.fs->winsect;
02483 res = remove_chain(dj.fs, cl);
02484 if (res == FR_OK) {
02485 dj.fs->last_clust = cl - 1;
02486 res = move_window(dj.fs, dw);
02487 }
02488 }
02489 }
02490 }
02491 else {
02492 if (res == FR_OK) {
02493 if (dir[DIR_Attr] & AM_DIR) {
02494 res = FR_NO_FILE;
02495 } else {
02496 if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO))
02497 res = FR_DENIED;
02498 }
02499 }
02500 }
02501 if (res == FR_OK) {
02502 if (mode & FA_CREATE_ALWAYS)
02503 mode |= FA__WRITTEN;
02504 fp->dir_sect = dj.fs->winsect;
02505 fp->dir_ptr = dir;
02506 #if _FS_LOCK
02507 fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
02508 if (!fp->lockid) res = FR_INT_ERR;
02509 #endif
02510 }
02511
02512 #else
02513 if (res == FR_OK) {
02514 dir = dj.dir;
02515 if (!dir) {
02516 res = FR_INVALID_NAME;
02517 } else {
02518 if (dir[DIR_Attr] & AM_DIR)
02519 res = FR_NO_FILE;
02520 }
02521 }
02522 #endif
02523 FREE_BUF();
02524
02525 if (res == FR_OK) {
02526 fp->flag = mode;
02527 fp->err = 0;
02528 fp->sclust = ld_clust(dj.fs, dir);
02529 fp->fsize = LD_DWORD(dir+DIR_FileSize);
02530 fp->fptr = 0;
02531 fp->dsect = 0;
02532 #if _USE_FASTSEEK
02533 fp->cltbl = 0;
02534 #endif
02535 fp->fs = dj.fs;
02536 fp->id = fp->fs->id;
02537 }
02538 }
02539
02540 LEAVE_FF(dj.fs, res);
02541 }
02542
02543
02544
02545
02546
02547
02548
02549
02550 FRESULT f_read (
02551 FIL* fp,
02552 void* buff,
02553 UINT btr,
02554 UINT* br
02555 )
02556 {
02557 FRESULT res;
02558 DWORD clst, sect, remain;
02559 UINT rcnt, cc;
02560 BYTE csect, *rbuff = (BYTE*)buff;
02561
02562
02563 *br = 0;
02564
02565 res = validate(fp);
02566 if (res != FR_OK) LEAVE_FF(fp->fs, res);
02567 if (fp->err)
02568 LEAVE_FF(fp->fs, (FRESULT)fp->err);
02569 if (!(fp->flag & FA_READ))
02570 LEAVE_FF(fp->fs, FR_DENIED);
02571 remain = fp->fsize - fp->fptr;
02572 if (btr > remain) btr = (UINT)remain;
02573
02574 for ( ; btr;
02575 rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
02576 if ((fp->fptr % SS(fp->fs)) == 0) {
02577 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));
02578 if (!csect) {
02579 if (fp->fptr == 0) {
02580 clst = fp->sclust;
02581 } else {
02582 #if _USE_FASTSEEK
02583 if (fp->cltbl)
02584 clst = clmt_clust(fp, fp->fptr);
02585 else
02586 #endif
02587 clst = get_fat(fp->fs, fp->clust);
02588 }
02589 if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
02590 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
02591 fp->clust = clst;
02592 }
02593 sect = clust2sect(fp->fs, fp->clust);
02594 if (!sect) ABORT(fp->fs, FR_INT_ERR);
02595 sect += csect;
02596 cc = btr / SS(fp->fs);
02597 if (cc) {
02598 if (csect + cc > fp->fs->csize)
02599 cc = fp->fs->csize - csect;
02600 if (disk_read(fp->fs->drv, rbuff, sect, cc))
02601 ABORT(fp->fs, FR_DISK_ERR);
02602 #if !_FS_READONLY && _FS_MINIMIZE <= 2
02603 #if _FS_TINY
02604 if (fp->fs->wflag && fp->fs->winsect - sect < cc)
02605 mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
02606 #else
02607 if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
02608 mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
02609 #endif
02610 #endif
02611 rcnt = SS(fp->fs) * cc;
02612 continue;
02613 }
02614 #if !_FS_TINY
02615 if (fp->dsect != sect) {
02616 #if !_FS_READONLY
02617 if (fp->flag & FA__DIRTY) {
02618 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))
02619 ABORT(fp->fs, FR_DISK_ERR);
02620 fp->flag &= ~FA__DIRTY;
02621 }
02622 #endif
02623 if (disk_read(fp->fs->drv, fp->buf, sect, 1))
02624 ABORT(fp->fs, FR_DISK_ERR);
02625 }
02626 #endif
02627 fp->dsect = sect;
02628 }
02629 rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));
02630 if (rcnt > btr) rcnt = btr;
02631 #if _FS_TINY
02632 if (move_window(fp->fs, fp->dsect))
02633 ABORT(fp->fs, FR_DISK_ERR);
02634 mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt);
02635 #else
02636 mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt);
02637 #endif
02638 }
02639
02640 LEAVE_FF(fp->fs, FR_OK);
02641 }
02642
02643
02644
02645
02646 #if !_FS_READONLY
02647
02648
02649
02650
02651 FRESULT f_write (
02652 FIL* fp,
02653 const void *buff,
02654 UINT btw,
02655 UINT* bw
02656 )
02657 {
02658 FRESULT res;
02659 DWORD clst, sect;
02660 UINT wcnt, cc;
02661 const BYTE *wbuff = (const BYTE*)buff;
02662 BYTE csect;
02663
02664
02665 *bw = 0;
02666
02667 res = validate(fp);
02668 if (res != FR_OK) LEAVE_FF(fp->fs, res);
02669 if (fp->err)
02670 LEAVE_FF(fp->fs, (FRESULT)fp->err);
02671 if (!(fp->flag & FA_WRITE))
02672 LEAVE_FF(fp->fs, FR_DENIED);
02673 if (fp->fptr + btw < fp->fptr) btw = 0;
02674
02675 for ( ; btw;
02676 wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
02677 if ((fp->fptr % SS(fp->fs)) == 0) {
02678 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));
02679 if (!csect) {
02680 if (fp->fptr == 0) {
02681 clst = fp->sclust;
02682 if (clst == 0)
02683 clst = create_chain(fp->fs, 0);
02684 } else {
02685 #if _USE_FASTSEEK
02686 if (fp->cltbl)
02687 clst = clmt_clust(fp, fp->fptr);
02688 else
02689 #endif
02690 clst = create_chain(fp->fs, fp->clust);
02691 }
02692 if (clst == 0) break;
02693 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
02694 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
02695 fp->clust = clst;
02696 if (fp->sclust == 0) fp->sclust = clst;
02697 }
02698 #if _FS_TINY
02699 if (fp->fs->winsect == fp->dsect && sync_window(fp->fs))
02700 ABORT(fp->fs, FR_DISK_ERR);
02701 #else
02702 if (fp->flag & FA__DIRTY) {
02703 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))
02704 ABORT(fp->fs, FR_DISK_ERR);
02705 fp->flag &= ~FA__DIRTY;
02706 }
02707 #endif
02708 sect = clust2sect(fp->fs, fp->clust);
02709 if (!sect) ABORT(fp->fs, FR_INT_ERR);
02710 sect += csect;
02711 cc = btw / SS(fp->fs);
02712 if (cc) {
02713 if (csect + cc > fp->fs->csize)
02714 cc = fp->fs->csize - csect;
02715 if (disk_write(fp->fs->drv, wbuff, sect, cc))
02716 ABORT(fp->fs, FR_DISK_ERR);
02717 #if _FS_MINIMIZE <= 2
02718 #if _FS_TINY
02719 if (fp->fs->winsect - sect < cc) {
02720 mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
02721 fp->fs->wflag = 0;
02722 }
02723 #else
02724 if (fp->dsect - sect < cc) {
02725 mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
02726 fp->flag &= ~FA__DIRTY;
02727 }
02728 #endif
02729 #endif
02730 wcnt = SS(fp->fs) * cc;
02731 continue;
02732 }
02733 #if _FS_TINY
02734 if (fp->fptr >= fp->fsize) {
02735 if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR);
02736 fp->fs->winsect = sect;
02737 }
02738 #else
02739 if (fp->dsect != sect) {
02740 if (fp->fptr < fp->fsize &&
02741 disk_read(fp->fs->drv, fp->buf, sect, 1))
02742 ABORT(fp->fs, FR_DISK_ERR);
02743 }
02744 #endif
02745 fp->dsect = sect;
02746 }
02747 wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));
02748 if (wcnt > btw) wcnt = btw;
02749 #if _FS_TINY
02750 if (move_window(fp->fs, fp->dsect))
02751 ABORT(fp->fs, FR_DISK_ERR);
02752 mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt);
02753 fp->fs->wflag = 1;
02754 #else
02755 mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt);
02756 fp->flag |= FA__DIRTY;
02757 #endif
02758 }
02759
02760 if (fp->fptr > fp->fsize) fp->fsize = fp->fptr;
02761 fp->flag |= FA__WRITTEN;
02762
02763 LEAVE_FF(fp->fs, FR_OK);
02764 }
02765
02766
02767
02768
02769
02770
02771
02772
02773 FRESULT f_sync (
02774 FIL* fp
02775 )
02776 {
02777 FRESULT res;
02778 DWORD tm;
02779 BYTE *dir;
02780
02781
02782 res = validate(fp);
02783 if (res == FR_OK) {
02784 if (fp->flag & FA__WRITTEN) {
02785
02786 #if !_FS_TINY
02787 if (fp->flag & FA__DIRTY) {
02788 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))
02789 LEAVE_FF(fp->fs, FR_DISK_ERR);
02790 fp->flag &= ~FA__DIRTY;
02791 }
02792 #endif
02793
02794 res = move_window(fp->fs, fp->dir_sect);
02795 if (res == FR_OK) {
02796 dir = fp->dir_ptr;
02797 dir[DIR_Attr] |= AM_ARC;
02798 ST_DWORD(dir+DIR_FileSize, fp->fsize);
02799 st_clust(dir, fp->sclust);
02800 tm = get_fattime();
02801 ST_DWORD(dir+DIR_WrtTime, tm);
02802 ST_WORD(dir+DIR_LstAccDate, 0);
02803 fp->flag &= ~FA__WRITTEN;
02804 fp->fs->wflag = 1;
02805 res = sync_fs(fp->fs);
02806 }
02807 }
02808 }
02809
02810 LEAVE_FF(fp->fs, res);
02811 }
02812
02813 #endif
02814
02815
02816
02817
02818
02819
02820
02821
02822 FRESULT f_close (
02823 FIL *fp
02824 )
02825 {
02826 FRESULT res;
02827
02828
02829 #if !_FS_READONLY
02830 res = f_sync(fp);
02831 if (res == FR_OK)
02832 #endif
02833 {
02834 res = validate(fp);
02835 if (res == FR_OK) {
02836 #if _FS_REENTRANT
02837 FATFS *fs = fp->fs;
02838 #endif
02839 #if _FS_LOCK
02840 res = dec_lock(fp->lockid);
02841 if (res == FR_OK)
02842 #endif
02843 fp->fs = 0;
02844 #if _FS_REENTRANT
02845 unlock_fs(fs, FR_OK);
02846 #endif
02847 }
02848 }
02849 return res;
02850 }
02851
02852
02853
02854
02855
02856
02857
02858
02859 #if _FS_RPATH >= 1
02860 #if _VOLUMES >= 2
02861 FRESULT f_chdrive (
02862 const TCHAR* path
02863 )
02864 {
02865 int vol;
02866
02867
02868 vol = get_ldnumber(&path);
02869 if (vol < 0) return FR_INVALID_DRIVE;
02870
02871 CurrVol = (BYTE)vol;
02872
02873 return FR_OK;
02874 }
02875 #endif
02876
02877
02878 FRESULT f_chdir (
02879 const TCHAR* path
02880 )
02881 {
02882 FRESULT res;
02883 DIR dj;
02884 DEF_NAMEBUF;
02885
02886
02887
02888 res = find_volume(&dj.fs, &path, 0);
02889 if (res == FR_OK) {
02890 INIT_BUF(dj);
02891 res = follow_path(&dj, path);
02892 FREE_BUF();
02893 if (res == FR_OK) {
02894 if (!dj.dir) {
02895 dj.fs->cdir = dj.sclust;
02896 } else {
02897 if (dj.dir[DIR_Attr] & AM_DIR)
02898 dj.fs->cdir = ld_clust(dj.fs, dj.dir);
02899 else
02900 res = FR_NO_PATH;
02901 }
02902 }
02903 if (res == FR_NO_FILE) res = FR_NO_PATH;
02904 }
02905
02906 LEAVE_FF(dj.fs, res);
02907 }
02908
02909
02910 #if _FS_RPATH >= 2
02911 FRESULT f_getcwd (
02912 TCHAR* buff,
02913 UINT len
02914 )
02915 {
02916 FRESULT res;
02917 DIR dj;
02918 UINT i, n;
02919 DWORD ccl;
02920 TCHAR *tp;
02921 FILINFO fno;
02922 DEF_NAMEBUF;
02923
02924
02925 *buff = 0;
02926
02927 res = find_volume(&dj.fs, (const TCHAR**)&buff, 0);
02928 if (res == FR_OK) {
02929 INIT_BUF(dj);
02930 i = len;
02931 dj.sclust = dj.fs->cdir;
02932 while ((ccl = dj.sclust) != 0) {
02933 res = dir_sdi(&dj, 1);
02934 if (res != FR_OK) break;
02935 res = dir_read(&dj, 0);
02936 if (res != FR_OK) break;
02937 dj.sclust = ld_clust(dj.fs, dj.dir);
02938 res = dir_sdi(&dj, 0);
02939 if (res != FR_OK) break;
02940 do {
02941 res = dir_read(&dj, 0);
02942 if (res != FR_OK) break;
02943 if (ccl == ld_clust(dj.fs, dj.dir)) break;
02944 res = dir_next(&dj, 0);
02945 } while (res == FR_OK);
02946 if (res == FR_NO_FILE) res = FR_INT_ERR;
02947 if (res != FR_OK) break;
02948 #if _USE_LFN
02949 fno.lfname = buff;
02950 fno.lfsize = i;
02951 #endif
02952 get_fileinfo(&dj, &fno);
02953 tp = fno.fname;
02954 #if _USE_LFN
02955 if (*buff) tp = buff;
02956 #endif
02957 for (n = 0; tp[n]; n++) ;
02958 if (i < n + 3) {
02959 res = FR_NOT_ENOUGH_CORE; break;
02960 }
02961 while (n) buff[--i] = tp[--n];
02962 buff[--i] = '/';
02963 }
02964 tp = buff;
02965 if (res == FR_OK) {
02966 #if _VOLUMES >= 2
02967 *tp++ = '0' + CurrVol;
02968 *tp++ = ':';
02969 #endif
02970 if (i == len) {
02971 *tp++ = '/';
02972 } else {
02973 do
02974 *tp++ = buff[i++];
02975 while (i < len);
02976 }
02977 }
02978 *tp = 0;
02979 FREE_BUF();
02980 }
02981
02982 LEAVE_FF(dj.fs, res);
02983 }
02984 #endif
02985 #endif
02986
02987
02988
02989 #if _FS_MINIMIZE <= 2
02990
02991
02992
02993
02994 FRESULT f_lseek (
02995 FIL* fp,
02996 DWORD ofs
02997 )
02998 {
02999 FRESULT res;
03000
03001
03002 res = validate(fp);
03003 if (res != FR_OK) LEAVE_FF(fp->fs, res);
03004 if (fp->err)
03005 LEAVE_FF(fp->fs, (FRESULT)fp->err);
03006
03007 #if _USE_FASTSEEK
03008 if (fp->cltbl) {
03009 DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
03010
03011 if (ofs == CREATE_LINKMAP) {
03012 tbl = fp->cltbl;
03013 tlen = *tbl++; ulen = 2;
03014 cl = fp->sclust;
03015 if (cl) {
03016 do {
03017
03018 tcl = cl; ncl = 0; ulen += 2;
03019 do {
03020 pcl = cl; ncl++;
03021 cl = get_fat(fp->fs, cl);
03022 if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
03023 if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
03024 } while (cl == pcl + 1);
03025 if (ulen <= tlen) {
03026 *tbl++ = ncl; *tbl++ = tcl;
03027 }
03028 } while (cl < fp->fs->n_fatent);
03029 }
03030 *fp->cltbl = ulen;
03031 if (ulen <= tlen)
03032 *tbl = 0;
03033 else
03034 res = FR_NOT_ENOUGH_CORE;
03035
03036 } else {
03037 if (ofs > fp->fsize)
03038 ofs = fp->fsize;
03039 fp->fptr = ofs;
03040 if (ofs) {
03041 fp->clust = clmt_clust(fp, ofs - 1);
03042 dsc = clust2sect(fp->fs, fp->clust);
03043 if (!dsc) ABORT(fp->fs, FR_INT_ERR);
03044 dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
03045 if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) {
03046 #if !_FS_TINY
03047 #if !_FS_READONLY
03048 if (fp->flag & FA__DIRTY) {
03049 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))
03050 ABORT(fp->fs, FR_DISK_ERR);
03051 fp->flag &= ~FA__DIRTY;
03052 }
03053 #endif
03054 if (disk_read(fp->fs->drv, fp->buf, dsc, 1))
03055 ABORT(fp->fs, FR_DISK_ERR);
03056 #endif
03057 fp->dsect = dsc;
03058 }
03059 }
03060 }
03061 } else
03062 #endif
03063
03064
03065 {
03066 DWORD clst, bcs, nsect, ifptr;
03067
03068 if (ofs > fp->fsize
03069 #if !_FS_READONLY
03070 && !(fp->flag & FA_WRITE)
03071 #endif
03072 ) ofs = fp->fsize;
03073
03074 ifptr = fp->fptr;
03075 fp->fptr = nsect = 0;
03076 if (ofs) {
03077 bcs = (DWORD)fp->fs->csize * SS(fp->fs);
03078 if (ifptr > 0 &&
03079 (ofs - 1) / bcs >= (ifptr - 1) / bcs) {
03080 fp->fptr = (ifptr - 1) & ~(bcs - 1);
03081 ofs -= fp->fptr;
03082 clst = fp->clust;
03083 } else {
03084 clst = fp->sclust;
03085 #if !_FS_READONLY
03086 if (clst == 0) {
03087 clst = create_chain(fp->fs, 0);
03088 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
03089 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
03090 fp->sclust = clst;
03091 }
03092 #endif
03093 fp->clust = clst;
03094 }
03095 if (clst != 0) {
03096 while (ofs > bcs) {
03097 #if !_FS_READONLY
03098 if (fp->flag & FA_WRITE) {
03099 clst = create_chain(fp->fs, clst);
03100 if (clst == 0) {
03101 ofs = bcs; break;
03102 }
03103 } else
03104 #endif
03105 clst = get_fat(fp->fs, clst);
03106 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
03107 if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
03108 fp->clust = clst;
03109 fp->fptr += bcs;
03110 ofs -= bcs;
03111 }
03112 fp->fptr += ofs;
03113 if (ofs % SS(fp->fs)) {
03114 nsect = clust2sect(fp->fs, clst);
03115 if (!nsect) ABORT(fp->fs, FR_INT_ERR);
03116 nsect += ofs / SS(fp->fs);
03117 }
03118 }
03119 }
03120 if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) {
03121 #if !_FS_TINY
03122 #if !_FS_READONLY
03123 if (fp->flag & FA__DIRTY) {
03124 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))
03125 ABORT(fp->fs, FR_DISK_ERR);
03126 fp->flag &= ~FA__DIRTY;
03127 }
03128 #endif
03129 if (disk_read(fp->fs->drv, fp->buf, nsect, 1))
03130 ABORT(fp->fs, FR_DISK_ERR);
03131 #endif
03132 fp->dsect = nsect;
03133 }
03134 #if !_FS_READONLY
03135 if (fp->fptr > fp->fsize) {
03136 fp->fsize = fp->fptr;
03137 fp->flag |= FA__WRITTEN;
03138 }
03139 #endif
03140 }
03141
03142 LEAVE_FF(fp->fs, res);
03143 }
03144
03145
03146
03147 #if _FS_MINIMIZE <= 1
03148
03149
03150
03151
03152 FRESULT f_opendir (
03153 DIR* dp,
03154 const TCHAR* path
03155 )
03156 {
03157 FRESULT res;
03158 FATFS* fs;
03159 DEF_NAMEBUF;
03160
03161
03162 if (!dp) return FR_INVALID_OBJECT;
03163
03164
03165 res = find_volume(&fs, &path, 0);
03166 if (res == FR_OK) {
03167 dp->fs = fs;
03168 INIT_BUF(*dp);
03169 res = follow_path(dp, path);
03170 FREE_BUF();
03171 if (res == FR_OK) {
03172 if (dp->dir) {
03173 if (dp->dir[DIR_Attr] & AM_DIR)
03174 dp->sclust = ld_clust(fs, dp->dir);
03175 else
03176 res = FR_NO_PATH;
03177 }
03178 if (res == FR_OK) {
03179 dp->id = fs->id;
03180 res = dir_sdi(dp, 0);
03181 #if _FS_LOCK
03182 if (res == FR_OK) {
03183 if (dp->sclust) {
03184 dp->lockid = inc_lock(dp, 0);
03185 if (!dp->lockid)
03186 res = FR_TOO_MANY_OPEN_FILES;
03187 } else {
03188 dp->lockid = 0;
03189 }
03190 }
03191 #endif
03192 }
03193 }
03194 if (res == FR_NO_FILE) res = FR_NO_PATH;
03195 }
03196 if (res != FR_OK) dp->fs = 0;
03197
03198 LEAVE_FF(fs, res);
03199 }
03200
03201
03202
03203
03204
03205
03206
03207
03208 FRESULT f_closedir (
03209 DIR *dp
03210 )
03211 {
03212 FRESULT res;
03213
03214
03215 res = validate(dp);
03216 if (res == FR_OK) {
03217 #if _FS_REENTRANT
03218 FATFS *fs = dp->fs;
03219 #endif
03220 #if _FS_LOCK
03221 if (dp->lockid)
03222 res = dec_lock(dp->lockid);
03223 if (res == FR_OK)
03224 #endif
03225 dp->fs = 0;
03226 #if _FS_REENTRANT
03227 unlock_fs(fs, FR_OK);
03228 #endif
03229 }
03230 return res;
03231 }
03232
03233
03234
03235
03236
03237
03238
03239
03240 FRESULT f_readdir (
03241 DIR* dp,
03242 FILINFO* fno
03243 )
03244 {
03245 FRESULT res;
03246 DEF_NAMEBUF;
03247
03248
03249 res = validate(dp);
03250 if (res == FR_OK) {
03251 if (!fno) {
03252 res = dir_sdi(dp, 0);
03253 } else {
03254 INIT_BUF(*dp);
03255 res = dir_read(dp, 0);
03256 if (res == FR_NO_FILE) {
03257 dp->sect = 0;
03258 res = FR_OK;
03259 }
03260 if (res == FR_OK) {
03261 get_fileinfo(dp, fno);
03262 res = dir_next(dp, 0);
03263 if (res == FR_NO_FILE) {
03264 dp->sect = 0;
03265 res = FR_OK;
03266 }
03267 }
03268 FREE_BUF();
03269 }
03270 }
03271
03272 LEAVE_FF(dp->fs, res);
03273 }
03274
03275
03276
03277 #if _FS_MINIMIZE == 0
03278
03279
03280
03281
03282 FRESULT f_stat (
03283 const TCHAR* path,
03284 FILINFO* fno
03285 )
03286 {
03287 FRESULT res;
03288 DIR dj;
03289 DEF_NAMEBUF;
03290
03291
03292
03293 res = find_volume(&dj.fs, &path, 0);
03294 if (res == FR_OK) {
03295 INIT_BUF(dj);
03296 res = follow_path(&dj, path);
03297 if (res == FR_OK) {
03298 if (dj.dir) {
03299 if (fno) get_fileinfo(&dj, fno);
03300 } else {
03301 res = FR_INVALID_NAME;
03302 }
03303 }
03304 FREE_BUF();
03305 }
03306
03307 LEAVE_FF(dj.fs, res);
03308 }
03309
03310
03311
03312 #if !_FS_READONLY
03313
03314
03315
03316
03317 FRESULT f_getfree (
03318 const TCHAR* path,
03319 DWORD* nclst,
03320 FATFS** fatfs
03321 )
03322 {
03323 FRESULT res;
03324 FATFS *fs;
03325 DWORD n, clst, sect, stat;
03326 UINT i;
03327 BYTE fat, *p;
03328
03329
03330
03331 res = find_volume(fatfs, &path, 0);
03332 fs = *fatfs;
03333 if (res == FR_OK) {
03334
03335 if (fs->free_clust <= fs->n_fatent - 2) {
03336 *nclst = fs->free_clust;
03337 } else {
03338
03339 fat = fs->fs_type;
03340 n = 0;
03341 if (fat == FS_FAT12) {
03342 clst = 2;
03343 do {
03344 stat = get_fat(fs, clst);
03345 if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
03346 if (stat == 1) { res = FR_INT_ERR; break; }
03347 if (stat == 0) n++;
03348 } while (++clst < fs->n_fatent);
03349 } else {
03350 clst = fs->n_fatent;
03351 sect = fs->fatbase;
03352 i = 0; p = 0;
03353 do {
03354 if (!i) {
03355 res = move_window(fs, sect++);
03356 if (res != FR_OK) break;
03357 p = fs->win;
03358 i = SS(fs);
03359 }
03360 if (fat == FS_FAT16) {
03361 if (LD_WORD(p) == 0) n++;
03362 p += 2; i -= 2;
03363 } else {
03364 if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++;
03365 p += 4; i -= 4;
03366 }
03367 } while (--clst);
03368 }
03369 fs->free_clust = n;
03370 fs->fsi_flag |= 1;
03371 *nclst = n;
03372 }
03373 }
03374 LEAVE_FF(fs, res);
03375 }
03376
03377
03378
03379
03380
03381
03382
03383
03384 FRESULT f_truncate (
03385 FIL* fp
03386 )
03387 {
03388 FRESULT res;
03389 DWORD ncl;
03390
03391
03392 res = validate(fp);
03393 if (res == FR_OK) {
03394 if (fp->err) {
03395 res = (FRESULT)fp->err;
03396 } else {
03397 if (!(fp->flag & FA_WRITE))
03398 res = FR_DENIED;
03399 }
03400 }
03401 if (res == FR_OK) {
03402 if (fp->fsize > fp->fptr) {
03403 fp->fsize = fp->fptr;
03404 fp->flag |= FA__WRITTEN;
03405 if (fp->fptr == 0) {
03406 res = remove_chain(fp->fs, fp->sclust);
03407 fp->sclust = 0;
03408 } else {
03409 ncl = get_fat(fp->fs, fp->clust);
03410 res = FR_OK;
03411 if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
03412 if (ncl == 1) res = FR_INT_ERR;
03413 if (res == FR_OK && ncl < fp->fs->n_fatent) {
03414 res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF);
03415 if (res == FR_OK) res = remove_chain(fp->fs, ncl);
03416 }
03417 }
03418 #if !_FS_TINY
03419 if (res == FR_OK && (fp->flag & FA__DIRTY)) {
03420 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))
03421 res = FR_DISK_ERR;
03422 else
03423 fp->flag &= ~FA__DIRTY;
03424 }
03425 #endif
03426 }
03427 if (res != FR_OK) fp->err = (FRESULT)res;
03428 }
03429
03430 LEAVE_FF(fp->fs, res);
03431 }
03432
03433
03434
03435
03436
03437
03438
03439
03440 FRESULT f_unlink (
03441 const TCHAR* path
03442 )
03443 {
03444 FRESULT res;
03445 DIR dj, sdj;
03446 BYTE *dir;
03447 DWORD dclst;
03448 DEF_NAMEBUF;
03449
03450
03451
03452 res = find_volume(&dj.fs, &path, 1);
03453 if (res == FR_OK) {
03454 INIT_BUF(dj);
03455 res = follow_path(&dj, path);
03456 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
03457 res = FR_INVALID_NAME;
03458 #if _FS_LOCK
03459 if (res == FR_OK) res = chk_lock(&dj, 2);
03460 #endif
03461 if (res == FR_OK) {
03462 dir = dj.dir;
03463 if (!dir) {
03464 res = FR_INVALID_NAME;
03465 } else {
03466 if (dir[DIR_Attr] & AM_RDO)
03467 res = FR_DENIED;
03468 }
03469 dclst = ld_clust(dj.fs, dir);
03470 if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) {
03471 if (dclst < 2) {
03472 res = FR_INT_ERR;
03473 } else {
03474 mem_cpy(&sdj, &dj, sizeof (DIR));
03475 sdj.sclust = dclst;
03476 res = dir_sdi(&sdj, 2);
03477 if (res == FR_OK) {
03478 res = dir_read(&sdj, 0);
03479 if (res == FR_OK
03480 #if _FS_RPATH
03481 || dclst == dj.fs->cdir
03482 #endif
03483 ) res = FR_DENIED;
03484 if (res == FR_NO_FILE) res = FR_OK;
03485 }
03486 }
03487 }
03488 if (res == FR_OK) {
03489 res = dir_remove(&dj);
03490 if (res == FR_OK) {
03491 if (dclst)
03492 res = remove_chain(dj.fs, dclst);
03493 if (res == FR_OK) res = sync_fs(dj.fs);
03494 }
03495 }
03496 }
03497 FREE_BUF();
03498 }
03499
03500 LEAVE_FF(dj.fs, res);
03501 }
03502
03503
03504
03505
03506
03507
03508
03509
03510 FRESULT f_mkdir (
03511 const TCHAR* path
03512 )
03513 {
03514 FRESULT res;
03515 DIR dj;
03516 BYTE *dir, n;
03517 DWORD dsc, dcl, pcl, tm = get_fattime();
03518 DEF_NAMEBUF;
03519
03520
03521
03522 res = find_volume(&dj.fs, &path, 1);
03523 if (res == FR_OK) {
03524 INIT_BUF(dj);
03525 res = follow_path(&dj, path);
03526 if (res == FR_OK) res = FR_EXIST;
03527 if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT))
03528 res = FR_INVALID_NAME;
03529 if (res == FR_NO_FILE) {
03530 dcl = create_chain(dj.fs, 0);
03531 res = FR_OK;
03532 if (dcl == 0) res = FR_DENIED;
03533 if (dcl == 1) res = FR_INT_ERR;
03534 if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
03535 if (res == FR_OK)
03536 res = sync_window(dj.fs);
03537 if (res == FR_OK) {
03538 dsc = clust2sect(dj.fs, dcl);
03539 dir = dj.fs->win;
03540 mem_set(dir, 0, SS(dj.fs));
03541 mem_set(dir+DIR_Name, ' ', 11);
03542 dir[DIR_Name] = '.';
03543 dir[DIR_Attr] = AM_DIR;
03544 ST_DWORD(dir+DIR_WrtTime, tm);
03545 st_clust(dir, dcl);
03546 mem_cpy(dir+SZ_DIR, dir, SZ_DIR);
03547 dir[SZ_DIR+1] = '.'; pcl = dj.sclust;
03548 if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
03549 pcl = 0;
03550 st_clust(dir+SZ_DIR, pcl);
03551 for (n = dj.fs->csize; n; n--) {
03552 dj.fs->winsect = dsc++;
03553 dj.fs->wflag = 1;
03554 res = sync_window(dj.fs);
03555 if (res != FR_OK) break;
03556 mem_set(dir, 0, SS(dj.fs));
03557 }
03558 }
03559 if (res == FR_OK) res = dir_register(&dj);
03560 if (res != FR_OK) {
03561 remove_chain(dj.fs, dcl);
03562 } else {
03563 dir = dj.dir;
03564 dir[DIR_Attr] = AM_DIR;
03565 ST_DWORD(dir+DIR_WrtTime, tm);
03566 st_clust(dir, dcl);
03567 dj.fs->wflag = 1;
03568 res = sync_fs(dj.fs);
03569 }
03570 }
03571 FREE_BUF();
03572 }
03573
03574 LEAVE_FF(dj.fs, res);
03575 }
03576
03577
03578
03579
03580
03581
03582
03583
03584 FRESULT f_chmod (
03585 const TCHAR* path,
03586 BYTE value,
03587 BYTE mask
03588 )
03589 {
03590 FRESULT res;
03591 DIR dj;
03592 BYTE *dir;
03593 DEF_NAMEBUF;
03594
03595
03596
03597 res = find_volume(&dj.fs, &path, 1);
03598 if (res == FR_OK) {
03599 INIT_BUF(dj);
03600 res = follow_path(&dj, path);
03601 FREE_BUF();
03602 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
03603 res = FR_INVALID_NAME;
03604 if (res == FR_OK) {
03605 dir = dj.dir;
03606 if (!dir) {
03607 res = FR_INVALID_NAME;
03608 } else {
03609 mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;
03610 dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask);
03611 dj.fs->wflag = 1;
03612 res = sync_fs(dj.fs);
03613 }
03614 }
03615 }
03616
03617 LEAVE_FF(dj.fs, res);
03618 }
03619
03620
03621
03622
03623
03624
03625
03626
03627 FRESULT f_utime (
03628 const TCHAR* path,
03629 const FILINFO* fno
03630 )
03631 {
03632 FRESULT res;
03633 DIR dj;
03634 BYTE *dir;
03635 DEF_NAMEBUF;
03636
03637
03638
03639 res = find_volume(&dj.fs, &path, 1);
03640 if (res == FR_OK) {
03641 INIT_BUF(dj);
03642 res = follow_path(&dj, path);
03643 FREE_BUF();
03644 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
03645 res = FR_INVALID_NAME;
03646 if (res == FR_OK) {
03647 dir = dj.dir;
03648 if (!dir) {
03649 res = FR_INVALID_NAME;
03650 } else {
03651 ST_WORD(dir+DIR_WrtTime, fno->ftime);
03652 ST_WORD(dir+DIR_WrtDate, fno->fdate);
03653 dj.fs->wflag = 1;
03654 res = sync_fs(dj.fs);
03655 }
03656 }
03657 }
03658
03659 LEAVE_FF(dj.fs, res);
03660 }
03661
03662
03663
03664
03665
03666
03667
03668
03669 FRESULT f_rename (
03670 const TCHAR* path_old,
03671 const TCHAR* path_new
03672 )
03673 {
03674 FRESULT res;
03675 DIR djo, djn;
03676 BYTE buf[21], *dir;
03677 DWORD dw;
03678 DEF_NAMEBUF;
03679
03680
03681
03682 res = find_volume(&djo.fs, &path_old, 1);
03683 if (res == FR_OK) {
03684 djn.fs = djo.fs;
03685 INIT_BUF(djo);
03686 res = follow_path(&djo, path_old);
03687 if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
03688 res = FR_INVALID_NAME;
03689 #if _FS_LOCK
03690 if (res == FR_OK) res = chk_lock(&djo, 2);
03691 #endif
03692 if (res == FR_OK) {
03693 if (!djo.dir) {
03694 res = FR_NO_FILE;
03695 } else {
03696 mem_cpy(buf, djo.dir+DIR_Attr, 21);
03697 mem_cpy(&djn, &djo, sizeof (DIR));
03698 if (get_ldnumber(&path_new) >= 0)
03699 res = follow_path(&djn, path_new);
03700 else
03701 res = FR_INVALID_DRIVE;
03702 if (res == FR_OK) res = FR_EXIST;
03703 if (res == FR_NO_FILE) {
03704
03705 res = dir_register(&djn);
03706 if (res == FR_OK) {
03707 dir = djn.dir;
03708 mem_cpy(dir+13, buf+2, 19);
03709 dir[DIR_Attr] = buf[0] | AM_ARC;
03710 djo.fs->wflag = 1;
03711 if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) {
03712 dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
03713 if (!dw) {
03714 res = FR_INT_ERR;
03715 } else {
03716 res = move_window(djo.fs, dw);
03717 dir = djo.fs->win+SZ_DIR;
03718 if (res == FR_OK && dir[1] == '.') {
03719 dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
03720 st_clust(dir, dw);
03721 djo.fs->wflag = 1;
03722 }
03723 }
03724 }
03725 if (res == FR_OK) {
03726 res = dir_remove(&djo);
03727 if (res == FR_OK)
03728 res = sync_fs(djo.fs);
03729 }
03730 }
03731
03732 }
03733 }
03734 }
03735 FREE_BUF();
03736 }
03737
03738 LEAVE_FF(djo.fs, res);
03739 }
03740
03741 #endif
03742 #endif
03743 #endif
03744 #endif
03745
03746
03747
03748 #if _USE_LABEL
03749
03750
03751
03752
03753 FRESULT f_getlabel (
03754 const TCHAR* path,
03755 TCHAR* label,
03756 DWORD* vsn
03757 )
03758 {
03759 FRESULT res;
03760 DIR dj;
03761 UINT i, j;
03762
03763
03764
03765 res = find_volume(&dj.fs, &path, 0);
03766
03767
03768 if (res == FR_OK && label) {
03769 dj.sclust = 0;
03770 res = dir_sdi(&dj, 0);
03771 if (res == FR_OK) {
03772 res = dir_read(&dj, 1);
03773 if (res == FR_OK) {
03774 #if _USE_LFN && _LFN_UNICODE
03775 WCHAR w;
03776 i = j = 0;
03777 do {
03778 w = (i < 11) ? dj.dir[i++] : ' ';
03779 if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i]))
03780 w = w << 8 | dj.dir[i++];
03781 label[j++] = ff_convert(w, 1);
03782 } while (j < 11);
03783 #else
03784 mem_cpy(label, dj.dir, 11);
03785 #endif
03786 j = 11;
03787 do {
03788 label[j] = 0;
03789 if (!j) break;
03790 } while (label[--j] == ' ');
03791 }
03792 if (res == FR_NO_FILE) {
03793 label[0] = 0;
03794 res = FR_OK;
03795 }
03796 }
03797 }
03798
03799
03800 if (res == FR_OK && vsn) {
03801 res = move_window(dj.fs, dj.fs->volbase);
03802 if (res == FR_OK) {
03803 i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID;
03804 *vsn = LD_DWORD(&dj.fs->win[i]);
03805 }
03806 }
03807
03808 LEAVE_FF(dj.fs, res);
03809 }
03810
03811
03812
03813 #if !_FS_READONLY
03814
03815
03816
03817
03818 FRESULT f_setlabel (
03819 const TCHAR* label
03820 )
03821 {
03822 FRESULT res;
03823 DIR dj;
03824 BYTE vn[11];
03825 UINT i, j, sl;
03826 WCHAR w;
03827 DWORD tm;
03828
03829
03830
03831 res = find_volume(&dj.fs, &label, 1);
03832 if (res) LEAVE_FF(dj.fs, res);
03833
03834
03835 vn[0] = 0;
03836 for (sl = 0; label[sl]; sl++) ;
03837 for ( ; sl && label[sl-1] == ' '; sl--) ;
03838 if (sl) {
03839 i = j = 0;
03840 do {
03841 #if _USE_LFN && _LFN_UNICODE
03842 w = ff_convert(ff_wtoupper(label[i++]), 0);
03843 #else
03844 w = (BYTE)label[i++];
03845 if (IsDBCS1(w))
03846 w = (j < 10 && i < sl && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
03847 #if _USE_LFN
03848 w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0);
03849 #else
03850 if (IsLower(w)) w -= 0x20;
03851 #ifdef _EXCVT
03852 if (w >= 0x80) w = ExCvt[w - 0x80];
03853 #else
03854 if (!_DF1S && w >= 0x80) w = 0;
03855 #endif
03856 #endif
03857 #endif
03858 if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11))
03859 LEAVE_FF(dj.fs, FR_INVALID_NAME);
03860 if (w >= 0x100) vn[j++] = (BYTE)(w >> 8);
03861 vn[j++] = (BYTE)w;
03862 } while (i < sl);
03863 while (j < 11) vn[j++] = ' ';
03864 }
03865
03866
03867 dj.sclust = 0;
03868 res = dir_sdi(&dj, 0);
03869 if (res == FR_OK) {
03870 res = dir_read(&dj, 1);
03871 if (res == FR_OK) {
03872 if (vn[0]) {
03873 mem_cpy(dj.dir, vn, 11);
03874 tm = get_fattime();
03875 ST_DWORD(dj.dir+DIR_WrtTime, tm);
03876 } else {
03877 dj.dir[0] = DDE;
03878 }
03879 dj.fs->wflag = 1;
03880 res = sync_fs(dj.fs);
03881 } else {
03882 if (res == FR_NO_FILE) {
03883 res = FR_OK;
03884 if (vn[0]) {
03885 res = dir_alloc(&dj, 1);
03886 if (res == FR_OK) {
03887 mem_set(dj.dir, 0, SZ_DIR);
03888 mem_cpy(dj.dir, vn, 11);
03889 dj.dir[DIR_Attr] = AM_VOL;
03890 tm = get_fattime();
03891 ST_DWORD(dj.dir+DIR_WrtTime, tm);
03892 dj.fs->wflag = 1;
03893 res = sync_fs(dj.fs);
03894 }
03895 }
03896 }
03897 }
03898 }
03899
03900 LEAVE_FF(dj.fs, res);
03901 }
03902
03903 #endif
03904 #endif
03905
03906
03907
03908
03909
03910
03911 #if _USE_FORWARD && _FS_TINY
03912
03913 FRESULT f_forward (
03914 FIL* fp,
03915 UINT (*func)(const BYTE*,UINT),
03916 UINT btf,
03917 UINT* bf
03918 )
03919 {
03920 FRESULT res;
03921 DWORD remain, clst, sect;
03922 UINT rcnt;
03923 BYTE csect;
03924
03925
03926 *bf = 0;
03927
03928 res = validate(fp);
03929 if (res != FR_OK) LEAVE_FF(fp->fs, res);
03930 if (fp->err)
03931 LEAVE_FF(fp->fs, (FRESULT)fp->err);
03932 if (!(fp->flag & FA_READ))
03933 LEAVE_FF(fp->fs, FR_DENIED);
03934
03935 remain = fp->fsize - fp->fptr;
03936 if (btf > remain) btf = (UINT)remain;
03937
03938 for ( ; btf && (*func)(0, 0);
03939 fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
03940 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));
03941 if ((fp->fptr % SS(fp->fs)) == 0) {
03942 if (!csect) {
03943 clst = (fp->fptr == 0) ?
03944 fp->sclust : get_fat(fp->fs, fp->clust);
03945 if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
03946 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
03947 fp->clust = clst;
03948 }
03949 }
03950 sect = clust2sect(fp->fs, fp->clust);
03951 if (!sect) ABORT(fp->fs, FR_INT_ERR);
03952 sect += csect;
03953 if (move_window(fp->fs, sect))
03954 ABORT(fp->fs, FR_DISK_ERR);
03955 fp->dsect = sect;
03956 rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs));
03957 if (rcnt > btf) rcnt = btf;
03958 rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
03959 if (!rcnt) ABORT(fp->fs, FR_INT_ERR);
03960 }
03961
03962 LEAVE_FF(fp->fs, FR_OK);
03963 }
03964 #endif
03965
03966
03967
03968 #if _USE_MKFS && !_FS_READONLY
03969
03970
03971
03972 #define N_ROOTDIR 512
03973 #define N_FATS 1
03974
03975
03976 FRESULT f_mkfs (
03977 const TCHAR* path,
03978 BYTE sfd,
03979 UINT au
03980 )
03981 {
03982 static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
03983 static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
03984 int vol;
03985 BYTE fmt, md, sys, *tbl, pdrv, part;
03986 DWORD n_clst, vs, n, wsect;
03987 UINT i;
03988 DWORD b_vol, b_fat, b_dir, b_data;
03989 DWORD n_vol, n_rsv, n_fat, n_dir;
03990 FATFS *fs;
03991 DSTATUS stat;
03992
03993
03994
03995 vol = get_ldnumber(&path);
03996 if (vol < 0) return FR_INVALID_DRIVE;
03997 if (sfd > 1) return FR_INVALID_PARAMETER;
03998 if (au & (au - 1)) return FR_INVALID_PARAMETER;
03999 fs = FatFs[vol];
04000 if (!fs) return FR_NOT_ENABLED;
04001 fs->fs_type = 0;
04002 pdrv = LD2PD(vol);
04003 part = LD2PT(vol);
04004
04005
04006 stat = disk_initialize(pdrv);
04007 if (stat & STA_NOINIT) return FR_NOT_READY;
04008 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
04009 #if _MAX_SS != _MIN_SS
04010 if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS || SS(fs) < _MIN_SS)
04011 return FR_DISK_ERR;
04012 #endif
04013 if (_MULTI_PARTITION && part) {
04014
04015 if (disk_read(pdrv, fs->win, 0, 1)) return FR_DISK_ERR;
04016 if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
04017 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
04018 if (!tbl[4]) return FR_MKFS_ABORTED;
04019 b_vol = LD_DWORD(tbl+8);
04020 n_vol = LD_DWORD(tbl+12);
04021 } else {
04022
04023 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
04024 return FR_DISK_ERR;
04025 b_vol = (sfd) ? 0 : 63;
04026 n_vol -= b_vol;
04027 }
04028
04029 if (!au) {
04030 vs = n_vol / (2000 / (SS(fs) / 512));
04031 for (i = 0; vs < vst[i]; i++) ;
04032 au = cst[i];
04033 }
04034 au /= SS(fs);
04035 if (au == 0) au = 1;
04036 if (au > 128) au = 128;
04037
04038
04039 n_clst = n_vol / au;
04040 fmt = FS_FAT12;
04041 if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
04042 if (n_clst >= MIN_FAT32) fmt = FS_FAT32;
04043
04044
04045 if (fmt == FS_FAT32) {
04046 n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
04047 n_rsv = 32;
04048 n_dir = 0;
04049 } else {
04050 n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
04051 n_fat = (n_fat + SS(fs) - 1) / SS(fs);
04052 n_rsv = 1;
04053 n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs);
04054 }
04055 b_fat = b_vol + n_rsv;
04056 b_dir = b_fat + n_fat * N_FATS;
04057 b_data = b_dir + n_dir;
04058 if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED;
04059
04060
04061 if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
04062 n = (b_data + n - 1) & ~(n - 1);
04063 n = (n - b_data) / N_FATS;
04064 if (fmt == FS_FAT32) {
04065 n_rsv += n;
04066 b_fat += n;
04067 } else {
04068 n_fat += n;
04069 }
04070
04071
04072 n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
04073 if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16)
04074 || (fmt == FS_FAT32 && n_clst < MIN_FAT32))
04075 return FR_MKFS_ABORTED;
04076
04077
04078 if (fmt == FS_FAT32) {
04079 sys = 0x0C;
04080 } else {
04081 if (fmt == FS_FAT12 && n_vol < 0x10000) {
04082 sys = 0x01;
04083 } else {
04084 sys = (n_vol < 0x10000) ? 0x04 : 0x06;
04085 }
04086 }
04087
04088 if (_MULTI_PARTITION && part) {
04089
04090 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
04091 tbl[4] = sys;
04092 if (disk_write(pdrv, fs->win, 0, 1))
04093 return FR_DISK_ERR;
04094 md = 0xF8;
04095 } else {
04096 if (sfd) {
04097 md = 0xF0;
04098 } else {
04099 mem_set(fs->win, 0, SS(fs));
04100 tbl = fs->win+MBR_Table;
04101 tbl[1] = 1;
04102 tbl[2] = 1;
04103 tbl[3] = 0;
04104 tbl[4] = sys;
04105 tbl[5] = 254;
04106 n = (b_vol + n_vol) / 63 / 255;
04107 tbl[6] = (BYTE)(n >> 2 | 63);
04108 tbl[7] = (BYTE)n;
04109 ST_DWORD(tbl+8, 63);
04110 ST_DWORD(tbl+12, n_vol);
04111 ST_WORD(fs->win+BS_55AA, 0xAA55);
04112 if (disk_write(pdrv, fs->win, 0, 1))
04113 return FR_DISK_ERR;
04114 md = 0xF8;
04115 }
04116 }
04117
04118
04119 tbl = fs->win;
04120 mem_set(tbl, 0, SS(fs));
04121 mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);
04122 i = SS(fs);
04123 ST_WORD(tbl+BPB_BytsPerSec, i);
04124 tbl[BPB_SecPerClus] = (BYTE)au;
04125 ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv);
04126 tbl[BPB_NumFATs] = N_FATS;
04127 i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR;
04128 ST_WORD(tbl+BPB_RootEntCnt, i);
04129 if (n_vol < 0x10000) {
04130 ST_WORD(tbl+BPB_TotSec16, n_vol);
04131 } else {
04132 ST_DWORD(tbl+BPB_TotSec32, n_vol);
04133 }
04134 tbl[BPB_Media] = md;
04135 ST_WORD(tbl+BPB_SecPerTrk, 63);
04136 ST_WORD(tbl+BPB_NumHeads, 255);
04137 ST_DWORD(tbl+BPB_HiddSec, b_vol);
04138 n = get_fattime();
04139 if (fmt == FS_FAT32) {
04140 ST_DWORD(tbl+BS_VolID32, n);
04141 ST_DWORD(tbl+BPB_FATSz32, n_fat);
04142 ST_DWORD(tbl+BPB_RootClus, 2);
04143 ST_WORD(tbl+BPB_FSInfo, 1);
04144 ST_WORD(tbl+BPB_BkBootSec, 6);
04145 tbl[BS_DrvNum32] = 0x80;
04146 tbl[BS_BootSig32] = 0x29;
04147 mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19);
04148 } else {
04149 ST_DWORD(tbl+BS_VolID, n);
04150 ST_WORD(tbl+BPB_FATSz16, n_fat);
04151 tbl[BS_DrvNum] = 0x80;
04152 tbl[BS_BootSig] = 0x29;
04153 mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19);
04154 }
04155 ST_WORD(tbl+BS_55AA, 0xAA55);
04156 if (disk_write(pdrv, tbl, b_vol, 1))
04157 return FR_DISK_ERR;
04158 if (fmt == FS_FAT32)
04159 disk_write(pdrv, tbl, b_vol + 6, 1);
04160
04161
04162 wsect = b_fat;
04163 for (i = 0; i < N_FATS; i++) {
04164 mem_set(tbl, 0, SS(fs));
04165 n = md;
04166 if (fmt != FS_FAT32) {
04167 n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
04168 ST_DWORD(tbl+0, n);
04169 } else {
04170 n |= 0xFFFFFF00;
04171 ST_DWORD(tbl+0, n);
04172 ST_DWORD(tbl+4, 0xFFFFFFFF);
04173 ST_DWORD(tbl+8, 0x0FFFFFFF);
04174 }
04175 if (disk_write(pdrv, tbl, wsect++, 1))
04176 return FR_DISK_ERR;
04177 mem_set(tbl, 0, SS(fs));
04178 for (n = 1; n < n_fat; n++) {
04179 if (disk_write(pdrv, tbl, wsect++, 1))
04180 return FR_DISK_ERR;
04181 }
04182 }
04183
04184
04185 i = (fmt == FS_FAT32) ? au : (UINT)n_dir;
04186 do {
04187 if (disk_write(pdrv, tbl, wsect++, 1))
04188 return FR_DISK_ERR;
04189 } while (--i);
04190
04191 #if _USE_ERASE
04192 {
04193 DWORD eb[2];
04194
04195 eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
04196 disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
04197 }
04198 #endif
04199
04200
04201 if (fmt == FS_FAT32) {
04202 ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
04203 ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
04204 ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);
04205 ST_DWORD(tbl+FSI_Nxt_Free, 2);
04206 ST_WORD(tbl+BS_55AA, 0xAA55);
04207 disk_write(pdrv, tbl, b_vol + 1, 1);
04208 disk_write(pdrv, tbl, b_vol + 7, 1);
04209 }
04210
04211 return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
04212 }
04213
04214
04215
04216 #if _MULTI_PARTITION
04217
04218
04219
04220
04221 FRESULT f_fdisk (
04222 BYTE pdrv,
04223 const DWORD szt[],
04224 void* work
04225 )
04226 {
04227 UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
04228 BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
04229 DSTATUS stat;
04230 DWORD sz_disk, sz_part, s_part;
04231
04232
04233 stat = disk_initialize(pdrv);
04234 if (stat & STA_NOINIT) return FR_NOT_READY;
04235 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
04236 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
04237
04238
04239 for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
04240 if (n == 256) n--;
04241 e_hd = n - 1;
04242 sz_cyl = 63 * n;
04243 tot_cyl = sz_disk / sz_cyl;
04244
04245
04246 mem_set(buf, 0, _MAX_SS);
04247 p = buf + MBR_Table; b_cyl = 0;
04248 for (i = 0; i < 4; i++, p += SZ_PTE) {
04249 p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
04250 if (!p_cyl) continue;
04251 s_part = (DWORD)sz_cyl * b_cyl;
04252 sz_part = (DWORD)sz_cyl * p_cyl;
04253 if (i == 0) {
04254 s_hd = 1;
04255 s_part += 63; sz_part -= 63;
04256 } else {
04257 s_hd = 0;
04258 }
04259 e_cyl = b_cyl + p_cyl - 1;
04260 if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
04261
04262
04263 p[1] = s_hd;
04264 p[2] = (BYTE)((b_cyl >> 2) + 1);
04265 p[3] = (BYTE)b_cyl;
04266 p[4] = 0x06;
04267 p[5] = e_hd;
04268 p[6] = (BYTE)((e_cyl >> 2) + 63);
04269 p[7] = (BYTE)e_cyl;
04270 ST_DWORD(p + 8, s_part);
04271 ST_DWORD(p + 12, sz_part);
04272
04273
04274 b_cyl += p_cyl;
04275 }
04276 ST_WORD(p, 0xAA55);
04277
04278
04279 return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
04280 }
04281
04282
04283 #endif
04284 #endif
04285
04286
04287
04288
04289 #if _USE_STRFUNC
04290
04291
04292
04293
04294 TCHAR* f_gets (
04295 TCHAR* buff,
04296 int len,
04297 FIL* fp
04298 )
04299 {
04300 int n = 0;
04301 TCHAR c, *p = buff;
04302 BYTE s[2];
04303 UINT rc;
04304
04305
04306 while (n < len - 1) {
04307 #if _USE_LFN && _LFN_UNICODE
04308 #if _STRF_ENCODE == 3
04309 f_read(fp, s, 1, &rc);
04310 if (rc != 1) break;
04311 c = s[0];
04312 if (c >= 0x80) {
04313 if (c < 0xC0) continue;
04314 if (c < 0xE0) {
04315 f_read(fp, s, 1, &rc);
04316 if (rc != 1) break;
04317 c = (c & 0x1F) << 6 | (s[0] & 0x3F);
04318 if (c < 0x80) c = '?';
04319 } else {
04320 if (c < 0xF0) {
04321 f_read(fp, s, 2, &rc);
04322 if (rc != 2) break;
04323 c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F);
04324 if (c < 0x800) c = '?';
04325 } else {
04326 c = '?';
04327 }
04328 }
04329 }
04330 #elif _STRF_ENCODE == 2
04331 f_read(fp, s, 2, &rc);
04332 if (rc != 2) break;
04333 c = s[1] + (s[0] << 8);
04334 #elif _STRF_ENCODE == 1
04335 f_read(fp, s, 2, &rc);
04336 if (rc != 2) break;
04337 c = s[0] + (s[1] << 8);
04338 #else
04339 f_read(fp, s, 1, &rc);
04340 if (rc != 1) break;
04341 c = s[0];
04342 if (IsDBCS1(c)) {
04343 f_read(fp, s, 1, &rc);
04344 if (rc != 1) break;
04345 c = (c << 8) + s[0];
04346 }
04347 c = ff_convert(c, 1);
04348 if (!c) c = '?';
04349 #endif
04350 #else
04351 f_read(fp, s, 1, &rc);
04352 if (rc != 1) break;
04353 c = s[0];
04354 #endif
04355 if (_USE_STRFUNC == 2 && c == '\r') continue;
04356 *p++ = c;
04357 n++;
04358 if (c == '\n') break;
04359 }
04360 *p = 0;
04361 return n ? buff : 0;
04362 }
04363
04364
04365
04366 #if !_FS_READONLY
04367 #include <stdarg.h>
04368
04369
04370
04371
04372 typedef struct {
04373 FIL* fp;
04374 int idx, nchr;
04375 BYTE buf[64];
04376 } putbuff;
04377
04378
04379 static
04380 void putc_bfd (
04381 putbuff* pb,
04382 TCHAR c
04383 )
04384 {
04385 UINT bw;
04386 int i;
04387
04388
04389 if (_USE_STRFUNC == 2 && c == '\n')
04390 putc_bfd(pb, '\r');
04391
04392 i = pb->idx;
04393 if (i < 0) return;
04394
04395 #if _USE_LFN && _LFN_UNICODE
04396 #if _STRF_ENCODE == 3
04397 if (c < 0x80) {
04398 pb->buf[i++] = (BYTE)c;
04399 } else {
04400 if (c < 0x800) {
04401 pb->buf[i++] = (BYTE)(0xC0 | c >> 6);
04402 } else {
04403 pb->buf[i++] = (BYTE)(0xE0 | c >> 12);
04404 pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F));
04405 }
04406 pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F));
04407 }
04408 #elif _STRF_ENCODE == 2
04409 pb->buf[i++] = (BYTE)(c >> 8);
04410 pb->buf[i++] = (BYTE)c;
04411 #elif _STRF_ENCODE == 1
04412 pb->buf[i++] = (BYTE)c;
04413 pb->buf[i++] = (BYTE)(c >> 8);
04414 #else
04415 c = ff_convert(c, 0);
04416 if (!c) c = '?';
04417 if (c >= 0x100)
04418 pb->buf[i++] = (BYTE)(c >> 8);
04419 pb->buf[i++] = (BYTE)c;
04420 #endif
04421 #else
04422 pb->buf[i++] = (BYTE)c;
04423 #endif
04424
04425 if (i >= (int)(sizeof pb->buf) - 3) {
04426 f_write(pb->fp, pb->buf, (UINT)i, &bw);
04427 i = (bw == (UINT)i) ? 0 : -1;
04428 }
04429 pb->idx = i;
04430 pb->nchr++;
04431 }
04432
04433
04434
04435 int f_putc (
04436 TCHAR c,
04437 FIL* fp
04438 )
04439 {
04440 putbuff pb;
04441 UINT nw;
04442
04443
04444 pb.fp = fp;
04445 pb.nchr = pb.idx = 0;
04446
04447 putc_bfd(&pb, c);
04448
04449 if ( pb.idx >= 0
04450 && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK
04451 && (UINT)pb.idx == nw) return pb.nchr;
04452 return EOF;
04453 }
04454
04455
04456
04457
04458
04459
04460
04461
04462 int f_puts (
04463 const TCHAR* str,
04464 FIL* fp
04465 )
04466 {
04467 putbuff pb;
04468 UINT nw;
04469
04470
04471 pb.fp = fp;
04472 pb.nchr = pb.idx = 0;
04473
04474 while (*str)
04475 putc_bfd(&pb, *str++);
04476
04477 if ( pb.idx >= 0
04478 && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK
04479 && (UINT)pb.idx == nw) return pb.nchr;
04480 return EOF;
04481 }
04482
04483
04484
04485
04486
04487
04488
04489
04490 int f_printf (
04491 FIL* fp,
04492 const TCHAR* fmt,
04493 ...
04494 )
04495 {
04496 va_list arp;
04497 BYTE f, r;
04498 UINT nw, i, j, w;
04499 DWORD v;
04500 TCHAR c, d, s[16], *p;
04501 putbuff pb;
04502
04503
04504 pb.fp = fp;
04505 pb.nchr = pb.idx = 0;
04506
04507 va_start(arp, fmt);
04508
04509 for (;;) {
04510 c = *fmt++;
04511 if (c == 0) break;
04512 if (c != '%') {
04513 putc_bfd(&pb, c);
04514 continue;
04515 }
04516 w = f = 0;
04517 c = *fmt++;
04518 if (c == '0') {
04519 f = 1; c = *fmt++;
04520 } else {
04521 if (c == '-') {
04522 f = 2; c = *fmt++;
04523 }
04524 }
04525 while (IsDigit(c)) {
04526 w = w * 10 + c - '0';
04527 c = *fmt++;
04528 }
04529 if (c == 'l' || c == 'L') {
04530 f |= 4; c = *fmt++;
04531 }
04532 if (!c) break;
04533 d = c;
04534 if (IsLower(d)) d -= 0x20;
04535 switch (d) {
04536 case 'S' :
04537 p = va_arg(arp, TCHAR*);
04538 for (j = 0; p[j]; j++) ;
04539 if (!(f & 2)) {
04540 while (j++ < w) putc_bfd(&pb, ' ');
04541 }
04542 while (*p) putc_bfd(&pb, *p++);
04543 while (j++ < w) putc_bfd(&pb, ' ');
04544 continue;
04545 case 'C' :
04546 putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
04547 case 'B' :
04548 r = 2; break;
04549 case 'O' :
04550 r = 8; break;
04551 case 'D' :
04552 case 'U' :
04553 r = 10; break;
04554 case 'X' :
04555 r = 16; break;
04556 default:
04557 putc_bfd(&pb, c); continue;
04558 }
04559
04560
04561 v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int));
04562 if (d == 'D' && (v & 0x80000000)) {
04563 v = 0 - v;
04564 f |= 8;
04565 }
04566 i = 0;
04567 do {
04568 d = (TCHAR)(v % r); v /= r;
04569 if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
04570 s[i++] = d + '0';
04571 } while (v && i < sizeof s / sizeof s[0]);
04572 if (f & 8) s[i++] = '-';
04573 j = i; d = (f & 1) ? '0' : ' ';
04574 while (!(f & 2) && j++ < w) putc_bfd(&pb, d);
04575 do putc_bfd(&pb, s[--i]); while (i);
04576 while (j++ < w) putc_bfd(&pb, d);
04577 }
04578
04579 va_end(arp);
04580
04581 if ( pb.idx >= 0
04582 && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK
04583 && (UINT)pb.idx == nw) return pb.nchr;
04584 return EOF;
04585 }
04586
04587 #endif
04588 #endif