Nicolas Borla
/
BBR_1Ebene
BBR 1 Ebene
mbed-os/features/filesystem/fat/FATFileSystem.cpp@0:fbdae7e6d805, 2018-05-14 (annotated)
- Committer:
- borlanic
- Date:
- Mon May 14 11:29:06 2018 +0000
- Revision:
- 0:fbdae7e6d805
BBR
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
borlanic | 0:fbdae7e6d805 | 1 | /* mbed Microcontroller Library |
borlanic | 0:fbdae7e6d805 | 2 | * Copyright (c) 2006-2012 ARM Limited |
borlanic | 0:fbdae7e6d805 | 3 | * |
borlanic | 0:fbdae7e6d805 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
borlanic | 0:fbdae7e6d805 | 5 | * of this software and associated documentation files (the "Software"), to deal |
borlanic | 0:fbdae7e6d805 | 6 | * in the Software without restriction, including without limitation the rights |
borlanic | 0:fbdae7e6d805 | 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
borlanic | 0:fbdae7e6d805 | 8 | * copies of the Software, and to permit persons to whom the Software is |
borlanic | 0:fbdae7e6d805 | 9 | * furnished to do so, subject to the following conditions: |
borlanic | 0:fbdae7e6d805 | 10 | * |
borlanic | 0:fbdae7e6d805 | 11 | * The above copyright notice and this permission notice shall be included in |
borlanic | 0:fbdae7e6d805 | 12 | * all copies or substantial portions of the Software. |
borlanic | 0:fbdae7e6d805 | 13 | * |
borlanic | 0:fbdae7e6d805 | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
borlanic | 0:fbdae7e6d805 | 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
borlanic | 0:fbdae7e6d805 | 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
borlanic | 0:fbdae7e6d805 | 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
borlanic | 0:fbdae7e6d805 | 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
borlanic | 0:fbdae7e6d805 | 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
borlanic | 0:fbdae7e6d805 | 20 | * SOFTWARE. |
borlanic | 0:fbdae7e6d805 | 21 | */ |
borlanic | 0:fbdae7e6d805 | 22 | #include "mbed.h" |
borlanic | 0:fbdae7e6d805 | 23 | |
borlanic | 0:fbdae7e6d805 | 24 | #include "diskio.h" |
borlanic | 0:fbdae7e6d805 | 25 | #include "ffconf.h" |
borlanic | 0:fbdae7e6d805 | 26 | #include "mbed_debug.h" |
borlanic | 0:fbdae7e6d805 | 27 | #include "mbed_critical.h" |
borlanic | 0:fbdae7e6d805 | 28 | #include <errno.h> |
borlanic | 0:fbdae7e6d805 | 29 | |
borlanic | 0:fbdae7e6d805 | 30 | #include "FATFileSystem.h" |
borlanic | 0:fbdae7e6d805 | 31 | |
borlanic | 0:fbdae7e6d805 | 32 | |
borlanic | 0:fbdae7e6d805 | 33 | ////// Error handling ///// |
borlanic | 0:fbdae7e6d805 | 34 | |
borlanic | 0:fbdae7e6d805 | 35 | static int fat_error_remap(FRESULT res) |
borlanic | 0:fbdae7e6d805 | 36 | { |
borlanic | 0:fbdae7e6d805 | 37 | switch(res) { |
borlanic | 0:fbdae7e6d805 | 38 | case FR_OK: /* (0) Succeeded */ |
borlanic | 0:fbdae7e6d805 | 39 | return 0; /* no error */ |
borlanic | 0:fbdae7e6d805 | 40 | case FR_DISK_ERR: /* (1) A hard error occurred in the low level disk I/O layer */ |
borlanic | 0:fbdae7e6d805 | 41 | case FR_NOT_READY: /* (3) The physical drive cannot work */ |
borlanic | 0:fbdae7e6d805 | 42 | return -EIO; /* I/O error */ |
borlanic | 0:fbdae7e6d805 | 43 | case FR_NO_FILE: /* (4) Could not find the file */ |
borlanic | 0:fbdae7e6d805 | 44 | case FR_NO_PATH: /* (5) Could not find the path */ |
borlanic | 0:fbdae7e6d805 | 45 | case FR_INVALID_NAME: /* (6) The path name format is invalid */ |
borlanic | 0:fbdae7e6d805 | 46 | case FR_INVALID_DRIVE: /* (11) The logical drive number is invalid */ |
borlanic | 0:fbdae7e6d805 | 47 | case FR_NO_FILESYSTEM: /* (13) There is no valid FAT volume */ |
borlanic | 0:fbdae7e6d805 | 48 | return -ENOENT; /* No such file or directory */ |
borlanic | 0:fbdae7e6d805 | 49 | case FR_DENIED: /* (7) Access denied due to prohibited access or directory full */ |
borlanic | 0:fbdae7e6d805 | 50 | return -EACCES; /* Permission denied */ |
borlanic | 0:fbdae7e6d805 | 51 | case FR_EXIST: /* (8) Access denied due to prohibited access */ |
borlanic | 0:fbdae7e6d805 | 52 | return -EEXIST; /* File exists */ |
borlanic | 0:fbdae7e6d805 | 53 | case FR_WRITE_PROTECTED: /* (10) The physical drive is write protected */ |
borlanic | 0:fbdae7e6d805 | 54 | case FR_LOCKED: /* (16) The operation is rejected according to the file sharing policy */ |
borlanic | 0:fbdae7e6d805 | 55 | return -EACCES; /* Permission denied */ |
borlanic | 0:fbdae7e6d805 | 56 | case FR_INVALID_OBJECT: /* (9) The file/directory object is invalid */ |
borlanic | 0:fbdae7e6d805 | 57 | return -EFAULT; /* Bad address */ |
borlanic | 0:fbdae7e6d805 | 58 | case FR_NOT_ENABLED: /* (12) The volume has no work area */ |
borlanic | 0:fbdae7e6d805 | 59 | return -ENXIO; /* No such device or address */ |
borlanic | 0:fbdae7e6d805 | 60 | case FR_NOT_ENOUGH_CORE: /* (17) LFN working buffer could not be allocated */ |
borlanic | 0:fbdae7e6d805 | 61 | return -ENOMEM; /* Not enough space */ |
borlanic | 0:fbdae7e6d805 | 62 | case FR_TOO_MANY_OPEN_FILES: /* (18) Number of open files > _FS_LOCK */ |
borlanic | 0:fbdae7e6d805 | 63 | return -ENFILE; /* Too many open files in system */ |
borlanic | 0:fbdae7e6d805 | 64 | case FR_INVALID_PARAMETER: /* (19) Given parameter is invalid */ |
borlanic | 0:fbdae7e6d805 | 65 | return -ENOEXEC; /* Exec format error */ |
borlanic | 0:fbdae7e6d805 | 66 | case FR_INT_ERR: /* (2) Assertion failed */ |
borlanic | 0:fbdae7e6d805 | 67 | case FR_MKFS_ABORTED: /* (14) The f_mkfs() aborted due to any parameter error */ |
borlanic | 0:fbdae7e6d805 | 68 | case FR_TIMEOUT: /* (15) Could not get a grant to access the volume within defined period */ |
borlanic | 0:fbdae7e6d805 | 69 | default: /* Bad file number */ |
borlanic | 0:fbdae7e6d805 | 70 | return -EBADF; |
borlanic | 0:fbdae7e6d805 | 71 | } |
borlanic | 0:fbdae7e6d805 | 72 | } |
borlanic | 0:fbdae7e6d805 | 73 | |
borlanic | 0:fbdae7e6d805 | 74 | // Helper class for deferring operations when variable falls out of scope |
borlanic | 0:fbdae7e6d805 | 75 | template <typename T> |
borlanic | 0:fbdae7e6d805 | 76 | class Deferred { |
borlanic | 0:fbdae7e6d805 | 77 | public: |
borlanic | 0:fbdae7e6d805 | 78 | T _t; |
borlanic | 0:fbdae7e6d805 | 79 | Callback<void(T)> _ondefer; |
borlanic | 0:fbdae7e6d805 | 80 | |
borlanic | 0:fbdae7e6d805 | 81 | Deferred(const Deferred&); |
borlanic | 0:fbdae7e6d805 | 82 | Deferred &operator=(const Deferred&); |
borlanic | 0:fbdae7e6d805 | 83 | |
borlanic | 0:fbdae7e6d805 | 84 | public: |
borlanic | 0:fbdae7e6d805 | 85 | Deferred(T t, Callback<void(T)> ondefer = NULL) |
borlanic | 0:fbdae7e6d805 | 86 | : _t(t), _ondefer(ondefer) |
borlanic | 0:fbdae7e6d805 | 87 | { |
borlanic | 0:fbdae7e6d805 | 88 | } |
borlanic | 0:fbdae7e6d805 | 89 | |
borlanic | 0:fbdae7e6d805 | 90 | operator T() |
borlanic | 0:fbdae7e6d805 | 91 | { |
borlanic | 0:fbdae7e6d805 | 92 | return _t; |
borlanic | 0:fbdae7e6d805 | 93 | } |
borlanic | 0:fbdae7e6d805 | 94 | |
borlanic | 0:fbdae7e6d805 | 95 | ~Deferred() |
borlanic | 0:fbdae7e6d805 | 96 | { |
borlanic | 0:fbdae7e6d805 | 97 | if (_ondefer) { |
borlanic | 0:fbdae7e6d805 | 98 | _ondefer(_t); |
borlanic | 0:fbdae7e6d805 | 99 | } |
borlanic | 0:fbdae7e6d805 | 100 | } |
borlanic | 0:fbdae7e6d805 | 101 | }; |
borlanic | 0:fbdae7e6d805 | 102 | |
borlanic | 0:fbdae7e6d805 | 103 | static void dodelete(const char *data) |
borlanic | 0:fbdae7e6d805 | 104 | { |
borlanic | 0:fbdae7e6d805 | 105 | delete[] data; |
borlanic | 0:fbdae7e6d805 | 106 | } |
borlanic | 0:fbdae7e6d805 | 107 | |
borlanic | 0:fbdae7e6d805 | 108 | // Adds prefix needed internally by fatfs, this can be avoided for the first fatfs |
borlanic | 0:fbdae7e6d805 | 109 | // (id 0) otherwise a prefix of "id:/" is inserted in front of the string. |
borlanic | 0:fbdae7e6d805 | 110 | static Deferred<const char*> fat_path_prefix(int id, const char *path) |
borlanic | 0:fbdae7e6d805 | 111 | { |
borlanic | 0:fbdae7e6d805 | 112 | // We can avoid dynamic allocation when only on fatfs is in use |
borlanic | 0:fbdae7e6d805 | 113 | if (id == 0) { |
borlanic | 0:fbdae7e6d805 | 114 | return path; |
borlanic | 0:fbdae7e6d805 | 115 | } |
borlanic | 0:fbdae7e6d805 | 116 | |
borlanic | 0:fbdae7e6d805 | 117 | // Prefix path with id, will look something like 2:/hi/hello/filehere.txt |
borlanic | 0:fbdae7e6d805 | 118 | char *buffer = new char[strlen("0:/") + strlen(path) + 1]; |
borlanic | 0:fbdae7e6d805 | 119 | if (!buffer) { |
borlanic | 0:fbdae7e6d805 | 120 | return NULL; |
borlanic | 0:fbdae7e6d805 | 121 | } |
borlanic | 0:fbdae7e6d805 | 122 | |
borlanic | 0:fbdae7e6d805 | 123 | buffer[0] = '0' + id; |
borlanic | 0:fbdae7e6d805 | 124 | buffer[1] = ':'; |
borlanic | 0:fbdae7e6d805 | 125 | buffer[2] = '/'; |
borlanic | 0:fbdae7e6d805 | 126 | strcpy(buffer + strlen("0:/"), path); |
borlanic | 0:fbdae7e6d805 | 127 | return Deferred<const char*>(buffer, dodelete); |
borlanic | 0:fbdae7e6d805 | 128 | } |
borlanic | 0:fbdae7e6d805 | 129 | |
borlanic | 0:fbdae7e6d805 | 130 | |
borlanic | 0:fbdae7e6d805 | 131 | ////// Disk operations ////// |
borlanic | 0:fbdae7e6d805 | 132 | |
borlanic | 0:fbdae7e6d805 | 133 | // Global access to block device from FAT driver |
borlanic | 0:fbdae7e6d805 | 134 | static BlockDevice *_ffs[FF_VOLUMES] = {0}; |
borlanic | 0:fbdae7e6d805 | 135 | static SingletonPtr<PlatformMutex> _ffs_mutex; |
borlanic | 0:fbdae7e6d805 | 136 | |
borlanic | 0:fbdae7e6d805 | 137 | |
borlanic | 0:fbdae7e6d805 | 138 | // FAT driver functions |
borlanic | 0:fbdae7e6d805 | 139 | DWORD get_fattime(void) |
borlanic | 0:fbdae7e6d805 | 140 | { |
borlanic | 0:fbdae7e6d805 | 141 | time_t rawtime; |
borlanic | 0:fbdae7e6d805 | 142 | time(&rawtime); |
borlanic | 0:fbdae7e6d805 | 143 | struct tm *ptm = localtime(&rawtime); |
borlanic | 0:fbdae7e6d805 | 144 | return (DWORD)(ptm->tm_year - 80) << 25 |
borlanic | 0:fbdae7e6d805 | 145 | | (DWORD)(ptm->tm_mon + 1 ) << 21 |
borlanic | 0:fbdae7e6d805 | 146 | | (DWORD)(ptm->tm_mday ) << 16 |
borlanic | 0:fbdae7e6d805 | 147 | | (DWORD)(ptm->tm_hour ) << 11 |
borlanic | 0:fbdae7e6d805 | 148 | | (DWORD)(ptm->tm_min ) << 5 |
borlanic | 0:fbdae7e6d805 | 149 | | (DWORD)(ptm->tm_sec/2 ); |
borlanic | 0:fbdae7e6d805 | 150 | } |
borlanic | 0:fbdae7e6d805 | 151 | |
borlanic | 0:fbdae7e6d805 | 152 | void *ff_memalloc(UINT size) |
borlanic | 0:fbdae7e6d805 | 153 | { |
borlanic | 0:fbdae7e6d805 | 154 | return malloc(size); |
borlanic | 0:fbdae7e6d805 | 155 | } |
borlanic | 0:fbdae7e6d805 | 156 | |
borlanic | 0:fbdae7e6d805 | 157 | void ff_memfree(void *p) |
borlanic | 0:fbdae7e6d805 | 158 | { |
borlanic | 0:fbdae7e6d805 | 159 | free(p); |
borlanic | 0:fbdae7e6d805 | 160 | } |
borlanic | 0:fbdae7e6d805 | 161 | |
borlanic | 0:fbdae7e6d805 | 162 | // Implementation of diskio functions (see ChaN/diskio.h) |
borlanic | 0:fbdae7e6d805 | 163 | static WORD disk_get_sector_size(BYTE pdrv) |
borlanic | 0:fbdae7e6d805 | 164 | { |
borlanic | 0:fbdae7e6d805 | 165 | WORD ssize = _ffs[pdrv]->get_erase_size(); |
borlanic | 0:fbdae7e6d805 | 166 | if (ssize < 512) { |
borlanic | 0:fbdae7e6d805 | 167 | ssize = 512; |
borlanic | 0:fbdae7e6d805 | 168 | } |
borlanic | 0:fbdae7e6d805 | 169 | |
borlanic | 0:fbdae7e6d805 | 170 | MBED_ASSERT(ssize >= FF_MIN_SS && ssize <= FF_MAX_SS); |
borlanic | 0:fbdae7e6d805 | 171 | MBED_ASSERT(_ffs[pdrv]->get_read_size() <= _ffs[pdrv]->get_erase_size()); |
borlanic | 0:fbdae7e6d805 | 172 | MBED_ASSERT(_ffs[pdrv]->get_program_size() <= _ffs[pdrv]->get_erase_size()); |
borlanic | 0:fbdae7e6d805 | 173 | return ssize; |
borlanic | 0:fbdae7e6d805 | 174 | } |
borlanic | 0:fbdae7e6d805 | 175 | |
borlanic | 0:fbdae7e6d805 | 176 | static DWORD disk_get_sector_count(BYTE pdrv) |
borlanic | 0:fbdae7e6d805 | 177 | { |
borlanic | 0:fbdae7e6d805 | 178 | DWORD scount = _ffs[pdrv]->size() / disk_get_sector_size(pdrv); |
borlanic | 0:fbdae7e6d805 | 179 | MBED_ASSERT(scount >= 64); |
borlanic | 0:fbdae7e6d805 | 180 | return scount; |
borlanic | 0:fbdae7e6d805 | 181 | } |
borlanic | 0:fbdae7e6d805 | 182 | |
borlanic | 0:fbdae7e6d805 | 183 | DSTATUS disk_status(BYTE pdrv) |
borlanic | 0:fbdae7e6d805 | 184 | { |
borlanic | 0:fbdae7e6d805 | 185 | debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv); |
borlanic | 0:fbdae7e6d805 | 186 | return RES_OK; |
borlanic | 0:fbdae7e6d805 | 187 | } |
borlanic | 0:fbdae7e6d805 | 188 | |
borlanic | 0:fbdae7e6d805 | 189 | DSTATUS disk_initialize(BYTE pdrv) |
borlanic | 0:fbdae7e6d805 | 190 | { |
borlanic | 0:fbdae7e6d805 | 191 | debug_if(FFS_DBG, "disk_initialize on pdrv [%d]\n", pdrv); |
borlanic | 0:fbdae7e6d805 | 192 | return (DSTATUS)_ffs[pdrv]->init(); |
borlanic | 0:fbdae7e6d805 | 193 | } |
borlanic | 0:fbdae7e6d805 | 194 | |
borlanic | 0:fbdae7e6d805 | 195 | DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) |
borlanic | 0:fbdae7e6d805 | 196 | { |
borlanic | 0:fbdae7e6d805 | 197 | debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); |
borlanic | 0:fbdae7e6d805 | 198 | DWORD ssize = disk_get_sector_size(pdrv); |
borlanic | 0:fbdae7e6d805 | 199 | bd_addr_t addr = (bd_addr_t)sector*ssize; |
borlanic | 0:fbdae7e6d805 | 200 | bd_size_t size = (bd_size_t)count*ssize; |
borlanic | 0:fbdae7e6d805 | 201 | int err = _ffs[pdrv]->read(buff, addr, size); |
borlanic | 0:fbdae7e6d805 | 202 | return err ? RES_PARERR : RES_OK; |
borlanic | 0:fbdae7e6d805 | 203 | } |
borlanic | 0:fbdae7e6d805 | 204 | |
borlanic | 0:fbdae7e6d805 | 205 | DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) |
borlanic | 0:fbdae7e6d805 | 206 | { |
borlanic | 0:fbdae7e6d805 | 207 | debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); |
borlanic | 0:fbdae7e6d805 | 208 | DWORD ssize = disk_get_sector_size(pdrv); |
borlanic | 0:fbdae7e6d805 | 209 | bd_addr_t addr = (bd_addr_t)sector*ssize; |
borlanic | 0:fbdae7e6d805 | 210 | bd_size_t size = (bd_size_t)count*ssize; |
borlanic | 0:fbdae7e6d805 | 211 | int err = _ffs[pdrv]->erase(addr, size); |
borlanic | 0:fbdae7e6d805 | 212 | if (err) { |
borlanic | 0:fbdae7e6d805 | 213 | return RES_PARERR; |
borlanic | 0:fbdae7e6d805 | 214 | } |
borlanic | 0:fbdae7e6d805 | 215 | |
borlanic | 0:fbdae7e6d805 | 216 | err = _ffs[pdrv]->program(buff, addr, size); |
borlanic | 0:fbdae7e6d805 | 217 | if (err) { |
borlanic | 0:fbdae7e6d805 | 218 | return RES_PARERR; |
borlanic | 0:fbdae7e6d805 | 219 | } |
borlanic | 0:fbdae7e6d805 | 220 | |
borlanic | 0:fbdae7e6d805 | 221 | return RES_OK; |
borlanic | 0:fbdae7e6d805 | 222 | } |
borlanic | 0:fbdae7e6d805 | 223 | |
borlanic | 0:fbdae7e6d805 | 224 | DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) |
borlanic | 0:fbdae7e6d805 | 225 | { |
borlanic | 0:fbdae7e6d805 | 226 | debug_if(FFS_DBG, "disk_ioctl(%d)\n", cmd); |
borlanic | 0:fbdae7e6d805 | 227 | switch (cmd) { |
borlanic | 0:fbdae7e6d805 | 228 | case CTRL_SYNC: |
borlanic | 0:fbdae7e6d805 | 229 | if (_ffs[pdrv] == NULL) { |
borlanic | 0:fbdae7e6d805 | 230 | return RES_NOTRDY; |
borlanic | 0:fbdae7e6d805 | 231 | } else { |
borlanic | 0:fbdae7e6d805 | 232 | return RES_OK; |
borlanic | 0:fbdae7e6d805 | 233 | } |
borlanic | 0:fbdae7e6d805 | 234 | case GET_SECTOR_COUNT: |
borlanic | 0:fbdae7e6d805 | 235 | if (_ffs[pdrv] == NULL) { |
borlanic | 0:fbdae7e6d805 | 236 | return RES_NOTRDY; |
borlanic | 0:fbdae7e6d805 | 237 | } else { |
borlanic | 0:fbdae7e6d805 | 238 | *((DWORD*)buff) = disk_get_sector_count(pdrv); |
borlanic | 0:fbdae7e6d805 | 239 | return RES_OK; |
borlanic | 0:fbdae7e6d805 | 240 | } |
borlanic | 0:fbdae7e6d805 | 241 | case GET_SECTOR_SIZE: |
borlanic | 0:fbdae7e6d805 | 242 | if (_ffs[pdrv] == NULL) { |
borlanic | 0:fbdae7e6d805 | 243 | return RES_NOTRDY; |
borlanic | 0:fbdae7e6d805 | 244 | } else { |
borlanic | 0:fbdae7e6d805 | 245 | *((WORD*)buff) = disk_get_sector_size(pdrv); |
borlanic | 0:fbdae7e6d805 | 246 | return RES_OK; |
borlanic | 0:fbdae7e6d805 | 247 | } |
borlanic | 0:fbdae7e6d805 | 248 | case GET_BLOCK_SIZE: |
borlanic | 0:fbdae7e6d805 | 249 | *((DWORD*)buff) = 1; // default when not known |
borlanic | 0:fbdae7e6d805 | 250 | return RES_OK; |
borlanic | 0:fbdae7e6d805 | 251 | case CTRL_TRIM: |
borlanic | 0:fbdae7e6d805 | 252 | if (_ffs[pdrv] == NULL) { |
borlanic | 0:fbdae7e6d805 | 253 | return RES_NOTRDY; |
borlanic | 0:fbdae7e6d805 | 254 | } else { |
borlanic | 0:fbdae7e6d805 | 255 | DWORD *sectors = (DWORD*)buff; |
borlanic | 0:fbdae7e6d805 | 256 | DWORD ssize = disk_get_sector_size(pdrv); |
borlanic | 0:fbdae7e6d805 | 257 | bd_addr_t addr = (bd_addr_t)sectors[0]*ssize; |
borlanic | 0:fbdae7e6d805 | 258 | bd_size_t size = (bd_size_t)(sectors[1]-sectors[0]+1)*ssize; |
borlanic | 0:fbdae7e6d805 | 259 | int err = _ffs[pdrv]->trim(addr, size); |
borlanic | 0:fbdae7e6d805 | 260 | return err ? RES_PARERR : RES_OK; |
borlanic | 0:fbdae7e6d805 | 261 | } |
borlanic | 0:fbdae7e6d805 | 262 | } |
borlanic | 0:fbdae7e6d805 | 263 | |
borlanic | 0:fbdae7e6d805 | 264 | return RES_PARERR; |
borlanic | 0:fbdae7e6d805 | 265 | } |
borlanic | 0:fbdae7e6d805 | 266 | |
borlanic | 0:fbdae7e6d805 | 267 | |
borlanic | 0:fbdae7e6d805 | 268 | ////// Generic filesystem operations ////// |
borlanic | 0:fbdae7e6d805 | 269 | |
borlanic | 0:fbdae7e6d805 | 270 | // Filesystem implementation (See FATFilySystem.h) |
borlanic | 0:fbdae7e6d805 | 271 | FATFileSystem::FATFileSystem(const char *name, BlockDevice *bd) |
borlanic | 0:fbdae7e6d805 | 272 | : FileSystem(name), _id(-1) { |
borlanic | 0:fbdae7e6d805 | 273 | if (bd) { |
borlanic | 0:fbdae7e6d805 | 274 | mount(bd); |
borlanic | 0:fbdae7e6d805 | 275 | } |
borlanic | 0:fbdae7e6d805 | 276 | } |
borlanic | 0:fbdae7e6d805 | 277 | |
borlanic | 0:fbdae7e6d805 | 278 | FATFileSystem::~FATFileSystem() |
borlanic | 0:fbdae7e6d805 | 279 | { |
borlanic | 0:fbdae7e6d805 | 280 | // nop if unmounted |
borlanic | 0:fbdae7e6d805 | 281 | unmount(); |
borlanic | 0:fbdae7e6d805 | 282 | } |
borlanic | 0:fbdae7e6d805 | 283 | |
borlanic | 0:fbdae7e6d805 | 284 | int FATFileSystem::mount(BlockDevice *bd) |
borlanic | 0:fbdae7e6d805 | 285 | { |
borlanic | 0:fbdae7e6d805 | 286 | // requires duplicate definition to allow virtual overload to work |
borlanic | 0:fbdae7e6d805 | 287 | return mount(bd, true); |
borlanic | 0:fbdae7e6d805 | 288 | } |
borlanic | 0:fbdae7e6d805 | 289 | |
borlanic | 0:fbdae7e6d805 | 290 | int FATFileSystem::mount(BlockDevice *bd, bool mount) |
borlanic | 0:fbdae7e6d805 | 291 | { |
borlanic | 0:fbdae7e6d805 | 292 | lock(); |
borlanic | 0:fbdae7e6d805 | 293 | if (_id != -1) { |
borlanic | 0:fbdae7e6d805 | 294 | unlock(); |
borlanic | 0:fbdae7e6d805 | 295 | return -EINVAL; |
borlanic | 0:fbdae7e6d805 | 296 | } |
borlanic | 0:fbdae7e6d805 | 297 | |
borlanic | 0:fbdae7e6d805 | 298 | for (int i = 0; i < FF_VOLUMES; i++) { |
borlanic | 0:fbdae7e6d805 | 299 | if (!_ffs[i]) { |
borlanic | 0:fbdae7e6d805 | 300 | _id = i; |
borlanic | 0:fbdae7e6d805 | 301 | _ffs[_id] = bd; |
borlanic | 0:fbdae7e6d805 | 302 | _fsid[0] = '0' + _id; |
borlanic | 0:fbdae7e6d805 | 303 | _fsid[1] = ':'; |
borlanic | 0:fbdae7e6d805 | 304 | _fsid[2] = '\0'; |
borlanic | 0:fbdae7e6d805 | 305 | debug_if(FFS_DBG, "Mounting [%s] on ffs drive [%s]\n", getName(), _fsid); |
borlanic | 0:fbdae7e6d805 | 306 | FRESULT res = f_mount(&_fs, _fsid, mount); |
borlanic | 0:fbdae7e6d805 | 307 | unlock(); |
borlanic | 0:fbdae7e6d805 | 308 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 309 | } |
borlanic | 0:fbdae7e6d805 | 310 | } |
borlanic | 0:fbdae7e6d805 | 311 | |
borlanic | 0:fbdae7e6d805 | 312 | unlock(); |
borlanic | 0:fbdae7e6d805 | 313 | return -ENOMEM; |
borlanic | 0:fbdae7e6d805 | 314 | } |
borlanic | 0:fbdae7e6d805 | 315 | |
borlanic | 0:fbdae7e6d805 | 316 | int FATFileSystem::unmount() |
borlanic | 0:fbdae7e6d805 | 317 | { |
borlanic | 0:fbdae7e6d805 | 318 | lock(); |
borlanic | 0:fbdae7e6d805 | 319 | if (_id == -1) { |
borlanic | 0:fbdae7e6d805 | 320 | unlock(); |
borlanic | 0:fbdae7e6d805 | 321 | return -EINVAL; |
borlanic | 0:fbdae7e6d805 | 322 | } |
borlanic | 0:fbdae7e6d805 | 323 | |
borlanic | 0:fbdae7e6d805 | 324 | FRESULT res = f_mount(NULL, _fsid, 0); |
borlanic | 0:fbdae7e6d805 | 325 | _ffs[_id] = NULL; |
borlanic | 0:fbdae7e6d805 | 326 | _id = -1; |
borlanic | 0:fbdae7e6d805 | 327 | unlock(); |
borlanic | 0:fbdae7e6d805 | 328 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 329 | } |
borlanic | 0:fbdae7e6d805 | 330 | |
borlanic | 0:fbdae7e6d805 | 331 | /* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and |
borlanic | 0:fbdae7e6d805 | 332 | * associated arguments. */ |
borlanic | 0:fbdae7e6d805 | 333 | int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size) |
borlanic | 0:fbdae7e6d805 | 334 | { |
borlanic | 0:fbdae7e6d805 | 335 | FATFileSystem fs; |
borlanic | 0:fbdae7e6d805 | 336 | int err = fs.mount(bd, false); |
borlanic | 0:fbdae7e6d805 | 337 | if (err) { |
borlanic | 0:fbdae7e6d805 | 338 | return err; |
borlanic | 0:fbdae7e6d805 | 339 | } |
borlanic | 0:fbdae7e6d805 | 340 | |
borlanic | 0:fbdae7e6d805 | 341 | // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster) |
borlanic | 0:fbdae7e6d805 | 342 | fs.lock(); |
borlanic | 0:fbdae7e6d805 | 343 | FRESULT res = f_mkfs(fs._fsid, FM_ANY | FM_SFD, cluster_size, NULL, 0); |
borlanic | 0:fbdae7e6d805 | 344 | fs.unlock(); |
borlanic | 0:fbdae7e6d805 | 345 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 346 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 347 | } |
borlanic | 0:fbdae7e6d805 | 348 | |
borlanic | 0:fbdae7e6d805 | 349 | err = fs.unmount(); |
borlanic | 0:fbdae7e6d805 | 350 | if (err) { |
borlanic | 0:fbdae7e6d805 | 351 | return err; |
borlanic | 0:fbdae7e6d805 | 352 | } |
borlanic | 0:fbdae7e6d805 | 353 | |
borlanic | 0:fbdae7e6d805 | 354 | return 0; |
borlanic | 0:fbdae7e6d805 | 355 | } |
borlanic | 0:fbdae7e6d805 | 356 | |
borlanic | 0:fbdae7e6d805 | 357 | int FATFileSystem::reformat(BlockDevice *bd, int allocation_unit) |
borlanic | 0:fbdae7e6d805 | 358 | { |
borlanic | 0:fbdae7e6d805 | 359 | lock(); |
borlanic | 0:fbdae7e6d805 | 360 | if (_id != -1) { |
borlanic | 0:fbdae7e6d805 | 361 | if (!bd) { |
borlanic | 0:fbdae7e6d805 | 362 | bd = _ffs[_id]; |
borlanic | 0:fbdae7e6d805 | 363 | } |
borlanic | 0:fbdae7e6d805 | 364 | |
borlanic | 0:fbdae7e6d805 | 365 | int err = unmount(); |
borlanic | 0:fbdae7e6d805 | 366 | if (err) { |
borlanic | 0:fbdae7e6d805 | 367 | unlock(); |
borlanic | 0:fbdae7e6d805 | 368 | return err; |
borlanic | 0:fbdae7e6d805 | 369 | } |
borlanic | 0:fbdae7e6d805 | 370 | } |
borlanic | 0:fbdae7e6d805 | 371 | |
borlanic | 0:fbdae7e6d805 | 372 | if (!bd) { |
borlanic | 0:fbdae7e6d805 | 373 | unlock(); |
borlanic | 0:fbdae7e6d805 | 374 | return -ENODEV; |
borlanic | 0:fbdae7e6d805 | 375 | } |
borlanic | 0:fbdae7e6d805 | 376 | |
borlanic | 0:fbdae7e6d805 | 377 | int err = FATFileSystem::format(bd, allocation_unit); |
borlanic | 0:fbdae7e6d805 | 378 | if (err) { |
borlanic | 0:fbdae7e6d805 | 379 | unlock(); |
borlanic | 0:fbdae7e6d805 | 380 | return err; |
borlanic | 0:fbdae7e6d805 | 381 | } |
borlanic | 0:fbdae7e6d805 | 382 | |
borlanic | 0:fbdae7e6d805 | 383 | err = mount(bd); |
borlanic | 0:fbdae7e6d805 | 384 | unlock(); |
borlanic | 0:fbdae7e6d805 | 385 | return err; |
borlanic | 0:fbdae7e6d805 | 386 | } |
borlanic | 0:fbdae7e6d805 | 387 | |
borlanic | 0:fbdae7e6d805 | 388 | int FATFileSystem::remove(const char *path) |
borlanic | 0:fbdae7e6d805 | 389 | { |
borlanic | 0:fbdae7e6d805 | 390 | Deferred<const char*> fpath = fat_path_prefix(_id, path); |
borlanic | 0:fbdae7e6d805 | 391 | |
borlanic | 0:fbdae7e6d805 | 392 | lock(); |
borlanic | 0:fbdae7e6d805 | 393 | FRESULT res = f_unlink(fpath); |
borlanic | 0:fbdae7e6d805 | 394 | unlock(); |
borlanic | 0:fbdae7e6d805 | 395 | |
borlanic | 0:fbdae7e6d805 | 396 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 397 | debug_if(FFS_DBG, "f_unlink() failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 398 | } |
borlanic | 0:fbdae7e6d805 | 399 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 400 | } |
borlanic | 0:fbdae7e6d805 | 401 | |
borlanic | 0:fbdae7e6d805 | 402 | int FATFileSystem::rename(const char *oldpath, const char *newpath) |
borlanic | 0:fbdae7e6d805 | 403 | { |
borlanic | 0:fbdae7e6d805 | 404 | Deferred<const char*> oldfpath = fat_path_prefix(_id, oldpath); |
borlanic | 0:fbdae7e6d805 | 405 | Deferred<const char*> newfpath = fat_path_prefix(_id, newpath); |
borlanic | 0:fbdae7e6d805 | 406 | |
borlanic | 0:fbdae7e6d805 | 407 | lock(); |
borlanic | 0:fbdae7e6d805 | 408 | FRESULT res = f_rename(oldfpath, newfpath); |
borlanic | 0:fbdae7e6d805 | 409 | unlock(); |
borlanic | 0:fbdae7e6d805 | 410 | |
borlanic | 0:fbdae7e6d805 | 411 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 412 | debug_if(FFS_DBG, "f_rename() failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 413 | } |
borlanic | 0:fbdae7e6d805 | 414 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 415 | } |
borlanic | 0:fbdae7e6d805 | 416 | |
borlanic | 0:fbdae7e6d805 | 417 | int FATFileSystem::mkdir(const char *path, mode_t mode) |
borlanic | 0:fbdae7e6d805 | 418 | { |
borlanic | 0:fbdae7e6d805 | 419 | Deferred<const char*> fpath = fat_path_prefix(_id, path); |
borlanic | 0:fbdae7e6d805 | 420 | |
borlanic | 0:fbdae7e6d805 | 421 | lock(); |
borlanic | 0:fbdae7e6d805 | 422 | FRESULT res = f_mkdir(fpath); |
borlanic | 0:fbdae7e6d805 | 423 | unlock(); |
borlanic | 0:fbdae7e6d805 | 424 | |
borlanic | 0:fbdae7e6d805 | 425 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 426 | debug_if(FFS_DBG, "f_mkdir() failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 427 | } |
borlanic | 0:fbdae7e6d805 | 428 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 429 | } |
borlanic | 0:fbdae7e6d805 | 430 | |
borlanic | 0:fbdae7e6d805 | 431 | int FATFileSystem::stat(const char *path, struct stat *st) |
borlanic | 0:fbdae7e6d805 | 432 | { |
borlanic | 0:fbdae7e6d805 | 433 | Deferred<const char*> fpath = fat_path_prefix(_id, path); |
borlanic | 0:fbdae7e6d805 | 434 | |
borlanic | 0:fbdae7e6d805 | 435 | lock(); |
borlanic | 0:fbdae7e6d805 | 436 | FILINFO f; |
borlanic | 0:fbdae7e6d805 | 437 | memset(&f, 0, sizeof(f)); |
borlanic | 0:fbdae7e6d805 | 438 | |
borlanic | 0:fbdae7e6d805 | 439 | FRESULT res = f_stat(fpath, &f); |
borlanic | 0:fbdae7e6d805 | 440 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 441 | unlock(); |
borlanic | 0:fbdae7e6d805 | 442 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 443 | } |
borlanic | 0:fbdae7e6d805 | 444 | |
borlanic | 0:fbdae7e6d805 | 445 | /* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain. */ |
borlanic | 0:fbdae7e6d805 | 446 | #ifdef TOOLCHAIN_GCC |
borlanic | 0:fbdae7e6d805 | 447 | st->st_size = f.fsize; |
borlanic | 0:fbdae7e6d805 | 448 | st->st_mode = 0; |
borlanic | 0:fbdae7e6d805 | 449 | st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG; |
borlanic | 0:fbdae7e6d805 | 450 | st->st_mode |= (f.fattrib & AM_RDO) ? |
borlanic | 0:fbdae7e6d805 | 451 | (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) : |
borlanic | 0:fbdae7e6d805 | 452 | (S_IRWXU | S_IRWXG | S_IRWXO); |
borlanic | 0:fbdae7e6d805 | 453 | #endif /* TOOLCHAIN_GCC */ |
borlanic | 0:fbdae7e6d805 | 454 | unlock(); |
borlanic | 0:fbdae7e6d805 | 455 | |
borlanic | 0:fbdae7e6d805 | 456 | return 0; |
borlanic | 0:fbdae7e6d805 | 457 | } |
borlanic | 0:fbdae7e6d805 | 458 | |
borlanic | 0:fbdae7e6d805 | 459 | int FATFileSystem::statvfs(const char *path, struct statvfs *buf) |
borlanic | 0:fbdae7e6d805 | 460 | { |
borlanic | 0:fbdae7e6d805 | 461 | |
borlanic | 0:fbdae7e6d805 | 462 | memset(buf, 0, sizeof(struct statvfs)); |
borlanic | 0:fbdae7e6d805 | 463 | FATFS *fs; |
borlanic | 0:fbdae7e6d805 | 464 | DWORD fre_clust; |
borlanic | 0:fbdae7e6d805 | 465 | |
borlanic | 0:fbdae7e6d805 | 466 | lock(); |
borlanic | 0:fbdae7e6d805 | 467 | FRESULT res = f_getfree(_fsid, &fre_clust, &fs); |
borlanic | 0:fbdae7e6d805 | 468 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 469 | unlock(); |
borlanic | 0:fbdae7e6d805 | 470 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 471 | } |
borlanic | 0:fbdae7e6d805 | 472 | |
borlanic | 0:fbdae7e6d805 | 473 | buf->f_bsize = fs->ssize; |
borlanic | 0:fbdae7e6d805 | 474 | buf->f_frsize = fs->ssize; |
borlanic | 0:fbdae7e6d805 | 475 | buf->f_blocks = (fs->n_fatent - 2) * fs->csize; |
borlanic | 0:fbdae7e6d805 | 476 | buf->f_bfree = fre_clust * fs->csize; |
borlanic | 0:fbdae7e6d805 | 477 | buf->f_bavail = buf->f_bfree; |
borlanic | 0:fbdae7e6d805 | 478 | #if FF_USE_LFN |
borlanic | 0:fbdae7e6d805 | 479 | buf->f_namemax = FF_LFN_BUF; |
borlanic | 0:fbdae7e6d805 | 480 | #else |
borlanic | 0:fbdae7e6d805 | 481 | buf->f_namemax = FF_SFN_BUF; |
borlanic | 0:fbdae7e6d805 | 482 | #endif |
borlanic | 0:fbdae7e6d805 | 483 | |
borlanic | 0:fbdae7e6d805 | 484 | unlock(); |
borlanic | 0:fbdae7e6d805 | 485 | return 0; |
borlanic | 0:fbdae7e6d805 | 486 | } |
borlanic | 0:fbdae7e6d805 | 487 | |
borlanic | 0:fbdae7e6d805 | 488 | void FATFileSystem::lock() |
borlanic | 0:fbdae7e6d805 | 489 | { |
borlanic | 0:fbdae7e6d805 | 490 | _ffs_mutex->lock(); |
borlanic | 0:fbdae7e6d805 | 491 | } |
borlanic | 0:fbdae7e6d805 | 492 | |
borlanic | 0:fbdae7e6d805 | 493 | void FATFileSystem::unlock() |
borlanic | 0:fbdae7e6d805 | 494 | { |
borlanic | 0:fbdae7e6d805 | 495 | _ffs_mutex->unlock(); |
borlanic | 0:fbdae7e6d805 | 496 | } |
borlanic | 0:fbdae7e6d805 | 497 | |
borlanic | 0:fbdae7e6d805 | 498 | |
borlanic | 0:fbdae7e6d805 | 499 | ////// File operations ////// |
borlanic | 0:fbdae7e6d805 | 500 | int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) |
borlanic | 0:fbdae7e6d805 | 501 | { |
borlanic | 0:fbdae7e6d805 | 502 | debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", path, getName(), _id); |
borlanic | 0:fbdae7e6d805 | 503 | |
borlanic | 0:fbdae7e6d805 | 504 | FIL *fh = new FIL; |
borlanic | 0:fbdae7e6d805 | 505 | Deferred<const char*> fpath = fat_path_prefix(_id, path); |
borlanic | 0:fbdae7e6d805 | 506 | |
borlanic | 0:fbdae7e6d805 | 507 | /* POSIX flags -> FatFS open mode */ |
borlanic | 0:fbdae7e6d805 | 508 | BYTE openmode; |
borlanic | 0:fbdae7e6d805 | 509 | if (flags & O_RDWR) { |
borlanic | 0:fbdae7e6d805 | 510 | openmode = FA_READ | FA_WRITE; |
borlanic | 0:fbdae7e6d805 | 511 | } else if (flags & O_WRONLY) { |
borlanic | 0:fbdae7e6d805 | 512 | openmode = FA_WRITE; |
borlanic | 0:fbdae7e6d805 | 513 | } else { |
borlanic | 0:fbdae7e6d805 | 514 | openmode = FA_READ; |
borlanic | 0:fbdae7e6d805 | 515 | } |
borlanic | 0:fbdae7e6d805 | 516 | |
borlanic | 0:fbdae7e6d805 | 517 | if (flags & O_CREAT) { |
borlanic | 0:fbdae7e6d805 | 518 | if (flags & O_TRUNC) { |
borlanic | 0:fbdae7e6d805 | 519 | openmode |= FA_CREATE_ALWAYS; |
borlanic | 0:fbdae7e6d805 | 520 | } else { |
borlanic | 0:fbdae7e6d805 | 521 | openmode |= FA_OPEN_ALWAYS; |
borlanic | 0:fbdae7e6d805 | 522 | } |
borlanic | 0:fbdae7e6d805 | 523 | } |
borlanic | 0:fbdae7e6d805 | 524 | |
borlanic | 0:fbdae7e6d805 | 525 | if (flags & O_APPEND) { |
borlanic | 0:fbdae7e6d805 | 526 | openmode |= FA_OPEN_APPEND; |
borlanic | 0:fbdae7e6d805 | 527 | } |
borlanic | 0:fbdae7e6d805 | 528 | |
borlanic | 0:fbdae7e6d805 | 529 | lock(); |
borlanic | 0:fbdae7e6d805 | 530 | FRESULT res = f_open(fh, fpath, openmode); |
borlanic | 0:fbdae7e6d805 | 531 | |
borlanic | 0:fbdae7e6d805 | 532 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 533 | unlock(); |
borlanic | 0:fbdae7e6d805 | 534 | debug_if(FFS_DBG, "f_open('w') failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 535 | delete fh; |
borlanic | 0:fbdae7e6d805 | 536 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 537 | } |
borlanic | 0:fbdae7e6d805 | 538 | |
borlanic | 0:fbdae7e6d805 | 539 | unlock(); |
borlanic | 0:fbdae7e6d805 | 540 | |
borlanic | 0:fbdae7e6d805 | 541 | *file = fh; |
borlanic | 0:fbdae7e6d805 | 542 | return 0; |
borlanic | 0:fbdae7e6d805 | 543 | } |
borlanic | 0:fbdae7e6d805 | 544 | |
borlanic | 0:fbdae7e6d805 | 545 | int FATFileSystem::file_close(fs_file_t file) |
borlanic | 0:fbdae7e6d805 | 546 | { |
borlanic | 0:fbdae7e6d805 | 547 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 548 | |
borlanic | 0:fbdae7e6d805 | 549 | lock(); |
borlanic | 0:fbdae7e6d805 | 550 | FRESULT res = f_close(fh); |
borlanic | 0:fbdae7e6d805 | 551 | unlock(); |
borlanic | 0:fbdae7e6d805 | 552 | |
borlanic | 0:fbdae7e6d805 | 553 | delete fh; |
borlanic | 0:fbdae7e6d805 | 554 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 555 | } |
borlanic | 0:fbdae7e6d805 | 556 | |
borlanic | 0:fbdae7e6d805 | 557 | ssize_t FATFileSystem::file_read(fs_file_t file, void *buffer, size_t len) |
borlanic | 0:fbdae7e6d805 | 558 | { |
borlanic | 0:fbdae7e6d805 | 559 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 560 | |
borlanic | 0:fbdae7e6d805 | 561 | lock(); |
borlanic | 0:fbdae7e6d805 | 562 | UINT n; |
borlanic | 0:fbdae7e6d805 | 563 | FRESULT res = f_read(fh, buffer, len, &n); |
borlanic | 0:fbdae7e6d805 | 564 | unlock(); |
borlanic | 0:fbdae7e6d805 | 565 | |
borlanic | 0:fbdae7e6d805 | 566 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 567 | debug_if(FFS_DBG, "f_read() failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 568 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 569 | } else { |
borlanic | 0:fbdae7e6d805 | 570 | return n; |
borlanic | 0:fbdae7e6d805 | 571 | } |
borlanic | 0:fbdae7e6d805 | 572 | } |
borlanic | 0:fbdae7e6d805 | 573 | |
borlanic | 0:fbdae7e6d805 | 574 | ssize_t FATFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) |
borlanic | 0:fbdae7e6d805 | 575 | { |
borlanic | 0:fbdae7e6d805 | 576 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 577 | |
borlanic | 0:fbdae7e6d805 | 578 | lock(); |
borlanic | 0:fbdae7e6d805 | 579 | UINT n; |
borlanic | 0:fbdae7e6d805 | 580 | FRESULT res = f_write(fh, buffer, len, &n); |
borlanic | 0:fbdae7e6d805 | 581 | unlock(); |
borlanic | 0:fbdae7e6d805 | 582 | |
borlanic | 0:fbdae7e6d805 | 583 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 584 | debug_if(FFS_DBG, "f_write() failed: %d", res); |
borlanic | 0:fbdae7e6d805 | 585 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 586 | } else { |
borlanic | 0:fbdae7e6d805 | 587 | return n; |
borlanic | 0:fbdae7e6d805 | 588 | } |
borlanic | 0:fbdae7e6d805 | 589 | } |
borlanic | 0:fbdae7e6d805 | 590 | |
borlanic | 0:fbdae7e6d805 | 591 | int FATFileSystem::file_sync(fs_file_t file) |
borlanic | 0:fbdae7e6d805 | 592 | { |
borlanic | 0:fbdae7e6d805 | 593 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 594 | |
borlanic | 0:fbdae7e6d805 | 595 | lock(); |
borlanic | 0:fbdae7e6d805 | 596 | FRESULT res = f_sync(fh); |
borlanic | 0:fbdae7e6d805 | 597 | unlock(); |
borlanic | 0:fbdae7e6d805 | 598 | |
borlanic | 0:fbdae7e6d805 | 599 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 600 | debug_if(FFS_DBG, "f_sync() failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 601 | } |
borlanic | 0:fbdae7e6d805 | 602 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 603 | } |
borlanic | 0:fbdae7e6d805 | 604 | |
borlanic | 0:fbdae7e6d805 | 605 | off_t FATFileSystem::file_seek(fs_file_t file, off_t offset, int whence) |
borlanic | 0:fbdae7e6d805 | 606 | { |
borlanic | 0:fbdae7e6d805 | 607 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 608 | |
borlanic | 0:fbdae7e6d805 | 609 | lock(); |
borlanic | 0:fbdae7e6d805 | 610 | if (whence == SEEK_END) { |
borlanic | 0:fbdae7e6d805 | 611 | offset += f_size(fh); |
borlanic | 0:fbdae7e6d805 | 612 | } else if(whence==SEEK_CUR) { |
borlanic | 0:fbdae7e6d805 | 613 | offset += f_tell(fh); |
borlanic | 0:fbdae7e6d805 | 614 | } |
borlanic | 0:fbdae7e6d805 | 615 | |
borlanic | 0:fbdae7e6d805 | 616 | FRESULT res = f_lseek(fh, offset); |
borlanic | 0:fbdae7e6d805 | 617 | off_t noffset = fh->fptr; |
borlanic | 0:fbdae7e6d805 | 618 | unlock(); |
borlanic | 0:fbdae7e6d805 | 619 | |
borlanic | 0:fbdae7e6d805 | 620 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 621 | debug_if(FFS_DBG, "lseek failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 622 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 623 | } else { |
borlanic | 0:fbdae7e6d805 | 624 | return noffset; |
borlanic | 0:fbdae7e6d805 | 625 | } |
borlanic | 0:fbdae7e6d805 | 626 | } |
borlanic | 0:fbdae7e6d805 | 627 | |
borlanic | 0:fbdae7e6d805 | 628 | off_t FATFileSystem::file_tell(fs_file_t file) |
borlanic | 0:fbdae7e6d805 | 629 | { |
borlanic | 0:fbdae7e6d805 | 630 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 631 | |
borlanic | 0:fbdae7e6d805 | 632 | lock(); |
borlanic | 0:fbdae7e6d805 | 633 | off_t res = f_tell(fh); |
borlanic | 0:fbdae7e6d805 | 634 | unlock(); |
borlanic | 0:fbdae7e6d805 | 635 | |
borlanic | 0:fbdae7e6d805 | 636 | return res; |
borlanic | 0:fbdae7e6d805 | 637 | } |
borlanic | 0:fbdae7e6d805 | 638 | |
borlanic | 0:fbdae7e6d805 | 639 | off_t FATFileSystem::file_size(fs_file_t file) |
borlanic | 0:fbdae7e6d805 | 640 | { |
borlanic | 0:fbdae7e6d805 | 641 | FIL *fh = static_cast<FIL*>(file); |
borlanic | 0:fbdae7e6d805 | 642 | |
borlanic | 0:fbdae7e6d805 | 643 | lock(); |
borlanic | 0:fbdae7e6d805 | 644 | off_t res = f_size(fh); |
borlanic | 0:fbdae7e6d805 | 645 | unlock(); |
borlanic | 0:fbdae7e6d805 | 646 | |
borlanic | 0:fbdae7e6d805 | 647 | return res; |
borlanic | 0:fbdae7e6d805 | 648 | } |
borlanic | 0:fbdae7e6d805 | 649 | |
borlanic | 0:fbdae7e6d805 | 650 | |
borlanic | 0:fbdae7e6d805 | 651 | ////// Dir operations ////// |
borlanic | 0:fbdae7e6d805 | 652 | int FATFileSystem::dir_open(fs_dir_t *dir, const char *path) |
borlanic | 0:fbdae7e6d805 | 653 | { |
borlanic | 0:fbdae7e6d805 | 654 | FATFS_DIR *dh = new FATFS_DIR; |
borlanic | 0:fbdae7e6d805 | 655 | Deferred<const char*> fpath = fat_path_prefix(_id, path); |
borlanic | 0:fbdae7e6d805 | 656 | |
borlanic | 0:fbdae7e6d805 | 657 | lock(); |
borlanic | 0:fbdae7e6d805 | 658 | FRESULT res = f_opendir(dh, fpath); |
borlanic | 0:fbdae7e6d805 | 659 | unlock(); |
borlanic | 0:fbdae7e6d805 | 660 | |
borlanic | 0:fbdae7e6d805 | 661 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 662 | debug_if(FFS_DBG, "f_opendir() failed: %d\n", res); |
borlanic | 0:fbdae7e6d805 | 663 | delete dh; |
borlanic | 0:fbdae7e6d805 | 664 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 665 | } |
borlanic | 0:fbdae7e6d805 | 666 | |
borlanic | 0:fbdae7e6d805 | 667 | *dir = dh; |
borlanic | 0:fbdae7e6d805 | 668 | return 0; |
borlanic | 0:fbdae7e6d805 | 669 | } |
borlanic | 0:fbdae7e6d805 | 670 | |
borlanic | 0:fbdae7e6d805 | 671 | int FATFileSystem::dir_close(fs_dir_t dir) |
borlanic | 0:fbdae7e6d805 | 672 | { |
borlanic | 0:fbdae7e6d805 | 673 | FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); |
borlanic | 0:fbdae7e6d805 | 674 | |
borlanic | 0:fbdae7e6d805 | 675 | lock(); |
borlanic | 0:fbdae7e6d805 | 676 | FRESULT res = f_closedir(dh); |
borlanic | 0:fbdae7e6d805 | 677 | unlock(); |
borlanic | 0:fbdae7e6d805 | 678 | |
borlanic | 0:fbdae7e6d805 | 679 | delete dh; |
borlanic | 0:fbdae7e6d805 | 680 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 681 | } |
borlanic | 0:fbdae7e6d805 | 682 | |
borlanic | 0:fbdae7e6d805 | 683 | ssize_t FATFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) |
borlanic | 0:fbdae7e6d805 | 684 | { |
borlanic | 0:fbdae7e6d805 | 685 | FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); |
borlanic | 0:fbdae7e6d805 | 686 | FILINFO finfo; |
borlanic | 0:fbdae7e6d805 | 687 | |
borlanic | 0:fbdae7e6d805 | 688 | lock(); |
borlanic | 0:fbdae7e6d805 | 689 | FRESULT res = f_readdir(dh, &finfo); |
borlanic | 0:fbdae7e6d805 | 690 | unlock(); |
borlanic | 0:fbdae7e6d805 | 691 | |
borlanic | 0:fbdae7e6d805 | 692 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 693 | return fat_error_remap(res); |
borlanic | 0:fbdae7e6d805 | 694 | } else if (finfo.fname[0] == 0) { |
borlanic | 0:fbdae7e6d805 | 695 | return 0; |
borlanic | 0:fbdae7e6d805 | 696 | } |
borlanic | 0:fbdae7e6d805 | 697 | |
borlanic | 0:fbdae7e6d805 | 698 | ent->d_type = (finfo.fattrib & AM_DIR) ? DT_DIR : DT_REG; |
borlanic | 0:fbdae7e6d805 | 699 | |
borlanic | 0:fbdae7e6d805 | 700 | #if FF_USE_LFN |
borlanic | 0:fbdae7e6d805 | 701 | if (ent->d_name[0] == 0) { |
borlanic | 0:fbdae7e6d805 | 702 | // No long filename so use short filename. |
borlanic | 0:fbdae7e6d805 | 703 | strncpy(ent->d_name, finfo.fname, FF_LFN_BUF); |
borlanic | 0:fbdae7e6d805 | 704 | } |
borlanic | 0:fbdae7e6d805 | 705 | #else |
borlanic | 0:fbdae7e6d805 | 706 | strncpy(ent->d_name, finfo.fname, FF_SFN_BUF); |
borlanic | 0:fbdae7e6d805 | 707 | #endif |
borlanic | 0:fbdae7e6d805 | 708 | |
borlanic | 0:fbdae7e6d805 | 709 | return 1; |
borlanic | 0:fbdae7e6d805 | 710 | } |
borlanic | 0:fbdae7e6d805 | 711 | |
borlanic | 0:fbdae7e6d805 | 712 | void FATFileSystem::dir_seek(fs_dir_t dir, off_t offset) |
borlanic | 0:fbdae7e6d805 | 713 | { |
borlanic | 0:fbdae7e6d805 | 714 | FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); |
borlanic | 0:fbdae7e6d805 | 715 | off_t dptr = static_cast<off_t>(dh->dptr); |
borlanic | 0:fbdae7e6d805 | 716 | |
borlanic | 0:fbdae7e6d805 | 717 | lock(); |
borlanic | 0:fbdae7e6d805 | 718 | |
borlanic | 0:fbdae7e6d805 | 719 | if (offset < dptr) { |
borlanic | 0:fbdae7e6d805 | 720 | f_rewinddir(dh); |
borlanic | 0:fbdae7e6d805 | 721 | } |
borlanic | 0:fbdae7e6d805 | 722 | while (dptr < offset) { |
borlanic | 0:fbdae7e6d805 | 723 | FILINFO finfo; |
borlanic | 0:fbdae7e6d805 | 724 | FRESULT res; |
borlanic | 0:fbdae7e6d805 | 725 | |
borlanic | 0:fbdae7e6d805 | 726 | res = f_readdir(dh, &finfo); |
borlanic | 0:fbdae7e6d805 | 727 | dptr = dh->dptr; |
borlanic | 0:fbdae7e6d805 | 728 | if (res != FR_OK) { |
borlanic | 0:fbdae7e6d805 | 729 | break; |
borlanic | 0:fbdae7e6d805 | 730 | } else if (finfo.fname[0] == 0) { |
borlanic | 0:fbdae7e6d805 | 731 | break; |
borlanic | 0:fbdae7e6d805 | 732 | } |
borlanic | 0:fbdae7e6d805 | 733 | } |
borlanic | 0:fbdae7e6d805 | 734 | unlock(); |
borlanic | 0:fbdae7e6d805 | 735 | } |
borlanic | 0:fbdae7e6d805 | 736 | |
borlanic | 0:fbdae7e6d805 | 737 | off_t FATFileSystem::dir_tell(fs_dir_t dir) |
borlanic | 0:fbdae7e6d805 | 738 | { |
borlanic | 0:fbdae7e6d805 | 739 | FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); |
borlanic | 0:fbdae7e6d805 | 740 | |
borlanic | 0:fbdae7e6d805 | 741 | lock(); |
borlanic | 0:fbdae7e6d805 | 742 | off_t offset = dh->dptr; |
borlanic | 0:fbdae7e6d805 | 743 | unlock(); |
borlanic | 0:fbdae7e6d805 | 744 | |
borlanic | 0:fbdae7e6d805 | 745 | return offset; |
borlanic | 0:fbdae7e6d805 | 746 | } |
borlanic | 0:fbdae7e6d805 | 747 | |
borlanic | 0:fbdae7e6d805 | 748 | void FATFileSystem::dir_rewind(fs_dir_t dir) |
borlanic | 0:fbdae7e6d805 | 749 | { |
borlanic | 0:fbdae7e6d805 | 750 | FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); |
borlanic | 0:fbdae7e6d805 | 751 | |
borlanic | 0:fbdae7e6d805 | 752 | lock(); |
borlanic | 0:fbdae7e6d805 | 753 | f_rewinddir(dh); |
borlanic | 0:fbdae7e6d805 | 754 | unlock(); |
borlanic | 0:fbdae7e6d805 | 755 | } |
borlanic | 0:fbdae7e6d805 | 756 |