Ben Evans University Second Year Project. Game Called Defender.

Dependencies:   mbed

https://os.mbed.com/media/uploads/evanso/84bc1a30759fd6a1e3f1fd1fae3e97c2.png

Hello, soldier, you have been specially selected as the defender of planet earth.

Your mission, if you choose to accept it. Fly around the planet and pulverise invading alien ships for as long as you can. Stop the aliens abducting the innocent people on the ground. Be warned if an alien ship manages to abduct a person and take them to top of the screen, they will no longer move randomly and will begin to hunt you down. This sounds like a challenge you were trained for.

But don’t worry soldier you’re not going into battle empty-handed. Your ship is equipped with a state of the art laser beam that has unlimited ammo and four smart bombs that will destroy anything on the screen. The ship also has three lives so use them wisely.

As time goes on more alien ships will arrive on planet earth increasing the difficulty of your mission. And remember the landscape bellow loops around so if you continually fly in the same direction you go to your original position. Good luck soldier.

Committer:
evanso
Date:
Tue May 19 15:13:47 2020 +0000
Revision:
48:e308067cfea5
Added sd card class folder to project folder

Who changed what in which revision?

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