Class that combined FATFileSystem with a USBMSD device, similar to LocalFileSystem

Dependencies:   USBDevice

Dependents:   SD_USB_FS_HelloWorld S25FL216K_USBFileSystem USBFileSystem_RAMDISK_HelloWorld

Introduction

USBFileSystem is a combination of FATFileSystem and USB-MSD (Mass-Storage Device). This way it allows you to create a filesystem that is both accessible on your PC with the USB cable plugged in, and on the device itself. This is very similar to LocalFileSystem, only you can use any Serial Flash, SD, etc as storage medium.

If your code works with either FATFileSystem or USBMSD it will with very little modification also work with USBFileSystem.

Basic functionality

Since both FATFileSystem and USBMSD write binary data to a the storage medium, if both are writing somewhere at the same time we have a problem. This library makes the medium read only for the local side, if USB is writing, and vice versa. Local is considered to be writing as long as you have opened a file for write. USB is considered writing as soon as a write command comes from USB, and this continues for a short time after the last write command. This is needed because I cannot know when the last sector is written by USB, so I have to wait a little while to see if more data is written.

Reading

You can still read when the other one is writing. This can result in issues. Using the functions given you can easily make sure that won't happen. However regardless if you do that or not, it is a good idea to make sure your program can handle unexpected situations. For example if you open a file locally, and you get a NULL pointer, do not immediatly go into an error condition, but just try it again.

USB MSD on your PC

When you write to / read from a USB drive Windows (and I expect other OS's too) will cache everything. The result is that once you read a file on your PC, it will never change, even if your mbed does change the data. And if you write/delete a file when the mbed is locally using the file system, it will be read only, however your PC will tell you data was succesfully written/removed.

If this is a problem for your device, you can disconnect the USB part when the mbed is writing to the storage medium locally. The library can do this automatically for you.

Required code

The virtual functions that need to be implemented by you are:

virtual int disk_initialize() { return 0; }
virtual int _disk_status() { return 0; }
virtual int disk_read(uint8_t * buffer, uint64_t sector) { return 0;}
virtual int _disk_write(const uint8_t * buffer, uint64_t sector) = 0;
virtual int disk_sync() { return 0; }
virtual uint64_t disk_sectors() = 0;

Some of those are optional, but disk_read, _disk_write and disk_sectors have to be defined in the child class.

Sector size

The sector size must be 512 bytes. In USBMSD this requirement isn't present, but FATFileSystem has this requirement!

Function name

Note the '_' at the beginning of _disk_status and _disk_write. You may not inherit it without the '_', that will break the library. Since the parent libraries made it virtual I cannot block it from happening, so just watch out.

Available functions for the user

The USBFileSystem library allows for some extra functions the user can use. The API documentation lists them, but summarized: You can attach functions which are called once either USB is writing to the storage medium, or when this is done locally. There are two functions which will tell you if currently USB/local is writing to the storage medium, and you can set the usbMode. Set it to mode 0 and USB is read only when the storage is used locally, set it to mode 1 and it is disconnected (default and recommended).

Besides that there are of course the standard USB functions (connect/disconnect for example), and you can use 'fopen', 'mkdir', etc similar to FATFileSystem.

Hello World

Currently available:

RAM-disk for KL25Z and LPC1768 (this one disappeared for some reason, I re-published it, should still work):

Import programUSBFileSystem_RAMDISK_HelloWorld

RAMDisk example for the USBFileSystem

Wi-Go serial flash:

Import programS25FL216K_HelloWorld

Helloworld program for the S25FL216K flash memory in combination with USBFileSystem

SD card (different from others):

Import programSD_USB_FS_HelloWorld

SD USB MSD helloworld

Note that this one is not mine, if you have problems with it check if there are updates for the library.

Committer:
Sissors
Date:
Sun Jan 18 21:31:55 2015 +0000
Revision:
7:da1f3328a496
Updated USBDevice and added count argument

Who changed what in which revision?

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