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:
Wed Oct 23 20:32:07 2013 +0000
Revision:
2:9af05743d551
FATFileSystem 'Tiny' option enabled -> Primary to solve a buffering issue when USB writes a file, also reduces RAM consumed
;
; USBDevice back to main branch
;
; USBMode 1 is default now

Who changed what in which revision?

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