Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
FATFileSystem.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2019 ARM Limited 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00020 * SOFTWARE. 00021 */ 00022 #include "features/storage/filesystem/fat/ChaN/diskio.h" 00023 #include "features/storage/filesystem/fat/ChaN/ffconf.h" 00024 #include "features/storage/filesystem/fat/ChaN/ff.h" 00025 #include "platform/mbed_debug.h" 00026 #include "platform/mbed_critical.h" 00027 #include "features/storage/filesystem/mbed_filesystem.h" 00028 #include "FATFileSystem.h" 00029 00030 #include <errno.h> 00031 #include <stdlib.h> 00032 00033 namespace mbed { 00034 00035 using namespace mbed; 00036 00037 static int fat_error_remap(FRESULT res) 00038 { 00039 switch (res) { 00040 case FR_OK: // (0) Succeeded 00041 return 0; 00042 case FR_DISK_ERR: // (1) A hard error occurred in the low level disk I/O layer 00043 return -EIO; 00044 case FR_INT_ERR: // (2) Assertion failed 00045 return -1; 00046 case FR_NOT_READY: // (3) The physical drive cannot work 00047 return -EIO; 00048 case FR_NO_FILE: // (4) Could not find the file 00049 return -ENOENT; 00050 case FR_NO_PATH: // (5) Could not find the path 00051 return -ENOTDIR; 00052 case FR_INVALID_NAME: // (6) The path name format is invalid 00053 return -EINVAL; 00054 case FR_DENIED: // (7) Access denied due to prohibited access or directory full 00055 return -EACCES; 00056 case FR_EXIST: // (8) Access denied due to prohibited access 00057 return -EEXIST; 00058 case FR_INVALID_OBJECT: // (9) The file/directory object is invalid 00059 return -EBADF; 00060 case FR_WRITE_PROTECTED: // (10) The physical drive is write protected 00061 return -EACCES; 00062 case FR_INVALID_DRIVE: // (11) The logical drive number is invalid 00063 return -ENODEV; 00064 case FR_NOT_ENABLED: // (12) The volume has no work area 00065 return -ENODEV; 00066 case FR_NO_FILESYSTEM: // (13) There is no valid FAT volume 00067 return -EINVAL; 00068 case FR_MKFS_ABORTED: // (14) The f_mkfs() aborted due to any problem 00069 return -EIO; 00070 case FR_TIMEOUT: // (15) Could not get a grant to access the volume within defined period 00071 return -ETIMEDOUT; 00072 case FR_LOCKED: // (16) The operation is rejected according to the file sharing policy 00073 return -EBUSY; 00074 case FR_NOT_ENOUGH_CORE: // (17) LFN working buffer could not be allocated 00075 return -ENOMEM; 00076 case FR_TOO_MANY_OPEN_FILES: // (18) Number of open files > FF_FS_LOCK 00077 return -ENFILE; 00078 case FR_INVALID_PARAMETER: // (19) Given parameter is invalid 00079 return -EINVAL; 00080 default: 00081 return -res; 00082 } 00083 } 00084 00085 // Helper class for deferring operations when variable falls out of scope 00086 template <typename T> 00087 class Deferred { 00088 public: 00089 T _t; 00090 Callback<void(T)> _ondefer; 00091 00092 Deferred(const Deferred &); 00093 Deferred &operator=(const Deferred &); 00094 00095 public: 00096 Deferred(T t, Callback<void(T)> ondefer = NULL) 00097 : _t(t), _ondefer(ondefer) 00098 { 00099 } 00100 00101 operator T() 00102 { 00103 return _t; 00104 } 00105 00106 ~Deferred() 00107 { 00108 if (_ondefer) { 00109 _ondefer(_t); 00110 } 00111 } 00112 }; 00113 00114 static void dodelete(const char *data) 00115 { 00116 delete[] data; 00117 } 00118 00119 // Adds prefix needed internally by fatfs, this can be avoided for the first fatfs 00120 // (id 0) otherwise a prefix of "id:/" is inserted in front of the string. 00121 static Deferred<const char *> fat_path_prefix(int id, const char *path) 00122 { 00123 // We can avoid dynamic allocation when only on fatfs is in use 00124 if (id == 0) { 00125 return path; 00126 } 00127 00128 // Prefix path with id, will look something like 2:/hi/hello/filehere.txt 00129 char *buffer = new char[strlen("0:/") + strlen(path) + 1]; 00130 if (!buffer) { 00131 return NULL; 00132 } 00133 00134 buffer[0] = '0' + id; 00135 buffer[1] = ':'; 00136 buffer[2] = '/'; 00137 strcpy(buffer + strlen("0:/"), path); 00138 return Deferred<const char *>(buffer, dodelete); 00139 } 00140 00141 ////// Disk operations ////// 00142 00143 // Global access to block device from FAT driver 00144 static mbed::BlockDevice *_ffs[FF_VOLUMES] = {0}; 00145 static SingletonPtr<PlatformMutex> _ffs_mutex; 00146 00147 // FAT driver functions 00148 extern "C" DWORD get_fattime(void) 00149 { 00150 time_t rawtime; 00151 time(&rawtime); 00152 struct tm *ptm = localtime(&rawtime); 00153 return (DWORD)(ptm->tm_year - 80) << 25 00154 | (DWORD)(ptm->tm_mon + 1) << 21 00155 | (DWORD)(ptm->tm_mday) << 16 00156 | (DWORD)(ptm->tm_hour) << 11 00157 | (DWORD)(ptm->tm_min) << 5 00158 | (DWORD)(ptm->tm_sec / 2); 00159 } 00160 00161 extern "C" void *ff_memalloc(UINT size) 00162 { 00163 return malloc(size); 00164 } 00165 00166 extern "C" void ff_memfree(void *p) 00167 { 00168 free(p); 00169 } 00170 00171 // Implementation of diskio functions (see ChaN/diskio.h) 00172 static WORD disk_get_sector_size(BYTE pdrv) 00173 { 00174 bd_size_t sector_size = _ffs[pdrv]->get_erase_size(); 00175 MBED_ASSERT(sector_size <= WORD(-1)); 00176 00177 WORD ssize = sector_size; 00178 if (ssize < 512) { 00179 ssize = 512; 00180 } 00181 00182 MBED_ASSERT(ssize >= FF_MIN_SS && ssize <= FF_MAX_SS); 00183 MBED_ASSERT(_ffs[pdrv]->get_read_size() <= _ffs[pdrv]->get_erase_size()); 00184 MBED_ASSERT(_ffs[pdrv]->get_program_size() <= _ffs[pdrv]->get_erase_size()); 00185 return ssize; 00186 } 00187 00188 static DWORD disk_get_sector_count(BYTE pdrv) 00189 { 00190 DWORD scount = _ffs[pdrv]->size() / disk_get_sector_size(pdrv); 00191 MBED_ASSERT(scount >= 64); 00192 return scount; 00193 } 00194 00195 extern "C" DSTATUS disk_status(BYTE pdrv) 00196 { 00197 debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv); 00198 return RES_OK; 00199 } 00200 00201 extern "C" DSTATUS disk_initialize(BYTE pdrv) 00202 { 00203 debug_if(FFS_DBG, "disk_initialize on pdrv [%d]\n", pdrv); 00204 return (DSTATUS)_ffs[pdrv]->init(); 00205 } 00206 00207 extern "C" DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) 00208 { 00209 debug_if(FFS_DBG, "disk_read(sector %lu, count %u) on pdrv [%d]\n", sector, count, pdrv); 00210 DWORD ssize = disk_get_sector_size(pdrv); 00211 mbed::bd_addr_t addr = (mbed::bd_addr_t)sector * ssize; 00212 mbed::bd_size_t size = (mbed::bd_size_t)count * ssize; 00213 int err = _ffs[pdrv]->read(buff, addr, size); 00214 return err ? RES_PARERR : RES_OK; 00215 } 00216 00217 extern "C" DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) 00218 { 00219 debug_if(FFS_DBG, "disk_write(sector %lu, count %u) on pdrv [%d]\n", sector, count, pdrv); 00220 DWORD ssize = disk_get_sector_size(pdrv); 00221 mbed::bd_addr_t addr = (mbed::bd_addr_t)sector * ssize; 00222 mbed::bd_size_t size = (mbed::bd_size_t)count * ssize; 00223 00224 int err = _ffs[pdrv]->erase(addr, size); 00225 if (err) { 00226 return RES_PARERR; 00227 } 00228 00229 err = _ffs[pdrv]->program(buff, addr, size); 00230 if (err) { 00231 return RES_PARERR; 00232 } 00233 00234 return RES_OK; 00235 } 00236 00237 extern "C" DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) 00238 { 00239 debug_if(FFS_DBG, "disk_ioctl(%d)\n", cmd); 00240 switch (cmd) { 00241 case CTRL_SYNC: 00242 if (_ffs[pdrv] == NULL) { 00243 return RES_NOTRDY; 00244 } else { 00245 return RES_OK; 00246 } 00247 case GET_SECTOR_COUNT: 00248 if (_ffs[pdrv] == NULL) { 00249 return RES_NOTRDY; 00250 } else { 00251 *((DWORD *)buff) = disk_get_sector_count(pdrv); 00252 return RES_OK; 00253 } 00254 case GET_SECTOR_SIZE: 00255 if (_ffs[pdrv] == NULL) { 00256 return RES_NOTRDY; 00257 } else { 00258 *((WORD *)buff) = disk_get_sector_size(pdrv); 00259 return RES_OK; 00260 } 00261 case GET_BLOCK_SIZE: 00262 *((DWORD *)buff) = 1; // default when not known 00263 return RES_OK; 00264 case CTRL_TRIM: 00265 if (_ffs[pdrv] == NULL) { 00266 return RES_NOTRDY; 00267 } else { 00268 DWORD *sectors = (DWORD *)buff; 00269 DWORD ssize = disk_get_sector_size(pdrv); 00270 mbed::bd_addr_t addr = (mbed::bd_addr_t)sectors[0] * ssize; 00271 mbed::bd_size_t size = (mbed::bd_size_t)(sectors[1] - sectors[0] + 1) * ssize; 00272 int err = _ffs[pdrv]->trim(addr, size); 00273 return err ? RES_PARERR : RES_OK; 00274 } 00275 } 00276 00277 return RES_PARERR; 00278 } 00279 00280 ////// Generic filesystem operations ////// 00281 00282 // Filesystem implementation (See FATFilySystem.h) 00283 FATFileSystem::FATFileSystem(const char *name, BlockDevice *bd) 00284 : FileSystem(name), _fs(), _id(-1) 00285 { 00286 if (bd) { 00287 mount(bd); 00288 } 00289 } 00290 00291 FATFileSystem::~FATFileSystem() 00292 { 00293 // nop if unmounted 00294 unmount(); 00295 } 00296 00297 int FATFileSystem::mount(BlockDevice *bd) 00298 { 00299 // requires duplicate definition to allow virtual overload to work 00300 return mount(bd, true); 00301 } 00302 00303 int FATFileSystem::mount(BlockDevice *bd, bool mount) 00304 { 00305 lock(); 00306 if (_id != -1) { 00307 unlock(); 00308 return -EINVAL; 00309 } 00310 00311 for (int i = 0; i < FF_VOLUMES; i++) { 00312 if (!_ffs[i]) { 00313 _id = i; 00314 _ffs[_id] = bd; 00315 _fsid[0] = '0' + _id; 00316 _fsid[1] = ':'; 00317 _fsid[2] = '\0'; 00318 debug_if(FFS_DBG, "Mounting [%s] on ffs drive [%s]\n", getName(), _fsid); 00319 FRESULT res = f_mount(&_fs, _fsid, mount); 00320 unlock(); 00321 return fat_error_remap(res); 00322 } 00323 } 00324 00325 unlock(); 00326 return -ENOMEM; 00327 } 00328 00329 int FATFileSystem::unmount() 00330 { 00331 lock(); 00332 if (_id == -1) { 00333 unlock(); 00334 return -EINVAL; 00335 } 00336 00337 FRESULT res = f_mount(NULL, _fsid, 0); 00338 _ffs[_id] = NULL; 00339 _id = -1; 00340 unlock(); 00341 return fat_error_remap(res); 00342 } 00343 00344 /* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and 00345 * associated arguments. */ 00346 int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size) 00347 { 00348 FATFileSystem fs; 00349 fs.lock(); 00350 00351 int err = bd->init(); 00352 if (err) { 00353 fs.unlock(); 00354 return err; 00355 } 00356 00357 // erase first handful of blocks 00358 bd_size_t header = 2 * bd->get_erase_size(); 00359 err = bd->erase(0, header); 00360 if (err) { 00361 bd->deinit(); 00362 fs.unlock(); 00363 return err; 00364 } 00365 00366 if (bd->get_erase_value() < 0) { 00367 // erase is unknown, need to write 1s 00368 bd_size_t program_size = bd->get_program_size(); 00369 void *buf = malloc(program_size); 00370 if (!buf) { 00371 bd->deinit(); 00372 fs.unlock(); 00373 return -ENOMEM; 00374 } 00375 00376 memset(buf, 0xff, program_size); 00377 00378 for (bd_addr_t i = 0; i < header; i += program_size) { 00379 err = bd->program(buf, i, program_size); 00380 if (err) { 00381 free(buf); 00382 bd->deinit(); 00383 fs.unlock(); 00384 return err; 00385 } 00386 } 00387 00388 free(buf); 00389 } 00390 00391 // trim entire device to indicate it is unneeded 00392 err = bd->trim(0, bd->size()); 00393 if (err) { 00394 bd->deinit(); 00395 fs.unlock(); 00396 return err; 00397 } 00398 00399 err = bd->deinit(); 00400 if (err) { 00401 fs.unlock(); 00402 return err; 00403 } 00404 00405 err = fs.mount(bd, false); 00406 if (err) { 00407 fs.unlock(); 00408 return err; 00409 } 00410 00411 // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster) 00412 FRESULT res = f_mkfs(fs._fsid, FM_ANY | FM_SFD, cluster_size, NULL, 0); 00413 if (res != FR_OK) { 00414 fs.unmount(); 00415 fs.unlock(); 00416 return fat_error_remap(res); 00417 } 00418 00419 err = fs.unmount(); 00420 if (err) { 00421 fs.unlock(); 00422 return err; 00423 } 00424 00425 fs.unlock(); 00426 return 0; 00427 } 00428 00429 int FATFileSystem::reformat(BlockDevice *bd, int allocation_unit) 00430 { 00431 lock(); 00432 if (_id != -1) { 00433 if (!bd) { 00434 bd = _ffs[_id]; 00435 } 00436 00437 int err = unmount(); 00438 if (err) { 00439 unlock(); 00440 return err; 00441 } 00442 } 00443 00444 if (!bd) { 00445 unlock(); 00446 return -ENODEV; 00447 } 00448 00449 int err = FATFileSystem::format(bd, allocation_unit); 00450 if (err) { 00451 unlock(); 00452 return err; 00453 } 00454 00455 err = mount(bd); 00456 unlock(); 00457 return err; 00458 } 00459 00460 int FATFileSystem::remove(const char *path) 00461 { 00462 Deferred<const char *> fpath = fat_path_prefix(_id, path); 00463 00464 lock(); 00465 FRESULT res = f_unlink(fpath); 00466 unlock(); 00467 00468 if (res != FR_OK) { 00469 debug_if(FFS_DBG, "f_unlink() failed: %d\n", res); 00470 if (res == FR_DENIED) { 00471 return -ENOTEMPTY; 00472 } 00473 } 00474 return fat_error_remap(res); 00475 } 00476 00477 int FATFileSystem::rename(const char *oldpath, const char *newpath) 00478 { 00479 Deferred<const char *> oldfpath = fat_path_prefix(_id, oldpath); 00480 Deferred<const char *> newfpath = fat_path_prefix(_id, newpath); 00481 00482 lock(); 00483 FRESULT res = f_rename(oldfpath, newfpath); 00484 unlock(); 00485 00486 if (res != FR_OK) { 00487 debug_if(FFS_DBG, "f_rename() failed: %d\n", res); 00488 } 00489 return fat_error_remap(res); 00490 } 00491 00492 int FATFileSystem::mkdir(const char *path, mode_t mode) 00493 { 00494 Deferred<const char *> fpath = fat_path_prefix(_id, path); 00495 00496 lock(); 00497 FRESULT res = f_mkdir(fpath); 00498 unlock(); 00499 00500 if (res != FR_OK) { 00501 debug_if(FFS_DBG, "f_mkdir() failed: %d\n", res); 00502 } 00503 return fat_error_remap(res); 00504 } 00505 00506 int FATFileSystem::stat(const char *path, struct stat *st) 00507 { 00508 Deferred<const char *> fpath = fat_path_prefix(_id, path); 00509 00510 lock(); 00511 FILINFO f; 00512 memset(&f, 0, sizeof(f)); 00513 00514 FRESULT res = f_stat(fpath, &f); 00515 if (res != FR_OK) { 00516 unlock(); 00517 return fat_error_remap(res); 00518 } 00519 00520 st->st_size = f.fsize; 00521 st->st_mode = 0; 00522 st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG; 00523 st->st_mode |= (f.fattrib & AM_RDO) ? 00524 (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) : 00525 (S_IRWXU | S_IRWXG | S_IRWXO); 00526 unlock(); 00527 00528 return 0; 00529 } 00530 00531 int FATFileSystem::statvfs(const char *path, struct statvfs *buf) 00532 { 00533 00534 memset(buf, 0, sizeof(struct statvfs)); 00535 FATFS *fs; 00536 DWORD fre_clust; 00537 00538 lock(); 00539 FRESULT res = f_getfree(_fsid, &fre_clust, &fs); 00540 if (res != FR_OK) { 00541 unlock(); 00542 return fat_error_remap(res); 00543 } 00544 00545 buf->f_bsize = fs->ssize; 00546 buf->f_frsize = fs->ssize; 00547 buf->f_blocks = (fs->n_fatent - 2) * fs->csize; 00548 buf->f_bfree = fre_clust * fs->csize; 00549 buf->f_bavail = buf->f_bfree; 00550 #if FF_USE_LFN 00551 buf->f_namemax = FF_LFN_BUF; 00552 #else 00553 buf->f_namemax = FF_SFN_BUF; 00554 #endif 00555 00556 unlock(); 00557 return 0; 00558 } 00559 00560 void FATFileSystem::lock() 00561 { 00562 _ffs_mutex->lock(); 00563 } 00564 00565 void FATFileSystem::unlock() 00566 { 00567 _ffs_mutex->unlock(); 00568 } 00569 00570 00571 ////// File operations ////// 00572 int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) 00573 { 00574 debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%d]\n", path, getName(), _id); 00575 00576 FIL *fh = new FIL; 00577 Deferred<const char *> fpath = fat_path_prefix(_id, path); 00578 00579 /* POSIX flags -> FatFS open mode */ 00580 BYTE openmode; 00581 if (flags & O_RDWR) { 00582 openmode = FA_READ | FA_WRITE; 00583 } else if (flags & O_WRONLY) { 00584 openmode = FA_WRITE; 00585 } else { 00586 openmode = FA_READ; 00587 } 00588 00589 if (flags & O_CREAT) { 00590 if (flags & O_TRUNC) { 00591 openmode |= FA_CREATE_ALWAYS; 00592 } else { 00593 openmode |= FA_OPEN_ALWAYS; 00594 } 00595 } 00596 00597 if (flags & O_APPEND) { 00598 openmode |= FA_OPEN_APPEND; 00599 } 00600 00601 lock(); 00602 FRESULT res = f_open(fh, fpath, openmode); 00603 00604 if (res != FR_OK) { 00605 unlock(); 00606 debug_if(FFS_DBG, "f_open('w') failed: %d\n", res); 00607 delete fh; 00608 return fat_error_remap(res); 00609 } 00610 00611 unlock(); 00612 00613 *file = fh; 00614 return 0; 00615 } 00616 00617 int FATFileSystem::file_close(fs_file_t file) 00618 { 00619 FIL *fh = static_cast<FIL *>(file); 00620 00621 lock(); 00622 FRESULT res = f_close(fh); 00623 unlock(); 00624 00625 delete fh; 00626 return fat_error_remap(res); 00627 } 00628 00629 ssize_t FATFileSystem::file_read(fs_file_t file, void *buffer, size_t len) 00630 { 00631 FIL *fh = static_cast<FIL *>(file); 00632 00633 lock(); 00634 UINT n; 00635 FRESULT res = f_read(fh, buffer, len, &n); 00636 unlock(); 00637 00638 if (res != FR_OK) { 00639 debug_if(FFS_DBG, "f_read() failed: %d\n", res); 00640 return fat_error_remap(res); 00641 } else { 00642 return n; 00643 } 00644 } 00645 00646 ssize_t FATFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) 00647 { 00648 FIL *fh = static_cast<FIL *>(file); 00649 00650 lock(); 00651 UINT n; 00652 FRESULT res = f_write(fh, buffer, len, &n); 00653 unlock(); 00654 00655 if (res != FR_OK) { 00656 debug_if(FFS_DBG, "f_write() failed: %d", res); 00657 return fat_error_remap(res); 00658 } else { 00659 return n; 00660 } 00661 } 00662 00663 int FATFileSystem::file_sync(fs_file_t file) 00664 { 00665 FIL *fh = static_cast<FIL *>(file); 00666 00667 lock(); 00668 FRESULT res = f_sync(fh); 00669 unlock(); 00670 00671 if (res != FR_OK) { 00672 debug_if(FFS_DBG, "f_sync() failed: %d\n", res); 00673 } 00674 return fat_error_remap(res); 00675 } 00676 00677 off_t FATFileSystem::file_seek(fs_file_t file, off_t offset, int whence) 00678 { 00679 FIL *fh = static_cast<FIL *>(file); 00680 00681 lock(); 00682 if (whence == SEEK_END) { 00683 offset += f_size(fh); 00684 } else if (whence == SEEK_CUR) { 00685 offset += f_tell(fh); 00686 } 00687 00688 FRESULT res = f_lseek(fh, offset); 00689 off_t noffset = fh->fptr; 00690 unlock(); 00691 00692 if (res != FR_OK) { 00693 debug_if(FFS_DBG, "lseek failed: %d\n", res); 00694 return fat_error_remap(res); 00695 } else { 00696 return noffset; 00697 } 00698 } 00699 00700 off_t FATFileSystem::file_tell(fs_file_t file) 00701 { 00702 FIL *fh = static_cast<FIL *>(file); 00703 00704 lock(); 00705 off_t res = f_tell(fh); 00706 unlock(); 00707 00708 return res; 00709 } 00710 00711 off_t FATFileSystem::file_size(fs_file_t file) 00712 { 00713 FIL *fh = static_cast<FIL *>(file); 00714 00715 lock(); 00716 off_t res = f_size(fh); 00717 unlock(); 00718 00719 return res; 00720 } 00721 00722 int FATFileSystem::file_truncate(fs_file_t file, off_t length) 00723 { 00724 FIL *fh = static_cast<FIL *>(file); 00725 00726 lock(); 00727 // save current position 00728 FSIZE_t oldoff = f_tell(fh); 00729 00730 // seek to new file size and truncate 00731 FRESULT res = f_lseek(fh, length); 00732 if (res) { 00733 unlock(); 00734 return fat_error_remap(res); 00735 } 00736 00737 res = f_truncate(fh); 00738 if (res) { 00739 unlock(); 00740 return fat_error_remap(res); 00741 } 00742 00743 // restore old position 00744 res = f_lseek(fh, oldoff); 00745 if (res) { 00746 unlock(); 00747 return fat_error_remap(res); 00748 } 00749 00750 return 0; 00751 } 00752 00753 00754 ////// Dir operations ////// 00755 int FATFileSystem::dir_open(fs_dir_t *dir, const char *path) 00756 { 00757 FATFS_DIR *dh = new FATFS_DIR; 00758 Deferred<const char *> fpath = fat_path_prefix(_id, path); 00759 00760 lock(); 00761 FRESULT res = f_opendir(dh, fpath); 00762 unlock(); 00763 00764 if (res != FR_OK) { 00765 debug_if(FFS_DBG, "f_opendir() failed: %d\n", res); 00766 delete dh; 00767 return fat_error_remap(res); 00768 } 00769 00770 *dir = dh; 00771 return 0; 00772 } 00773 00774 int FATFileSystem::dir_close(fs_dir_t dir) 00775 { 00776 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir); 00777 00778 lock(); 00779 FRESULT res = f_closedir(dh); 00780 unlock(); 00781 00782 delete dh; 00783 return fat_error_remap(res); 00784 } 00785 00786 ssize_t FATFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) 00787 { 00788 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir); 00789 FILINFO finfo; 00790 00791 lock(); 00792 FRESULT res = f_readdir(dh, &finfo); 00793 unlock(); 00794 00795 if (res != FR_OK) { 00796 return fat_error_remap(res); 00797 } else if (finfo.fname[0] == 0) { 00798 return 0; 00799 } 00800 00801 ent->d_type = (finfo.fattrib & AM_DIR) ? DT_DIR : DT_REG; 00802 00803 #if FF_USE_LFN 00804 if (ent->d_name[0] == 0) { 00805 // No long filename so use short filename. 00806 strncpy(ent->d_name, finfo.fname, FF_LFN_BUF); 00807 } 00808 #else 00809 strncpy(ent->d_name, finfo.fname, FF_SFN_BUF); 00810 #endif 00811 00812 return 1; 00813 } 00814 00815 void FATFileSystem::dir_seek(fs_dir_t dir, off_t offset) 00816 { 00817 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir); 00818 off_t dptr = static_cast<off_t>(dh->dptr); 00819 00820 lock(); 00821 00822 if (offset < dptr) { 00823 f_rewinddir(dh); 00824 } 00825 while (dptr < offset) { 00826 FILINFO finfo; 00827 FRESULT res; 00828 00829 res = f_readdir(dh, &finfo); 00830 dptr = dh->dptr; 00831 if (res != FR_OK) { 00832 break; 00833 } else if (finfo.fname[0] == 0) { 00834 break; 00835 } 00836 } 00837 unlock(); 00838 } 00839 00840 off_t FATFileSystem::dir_tell(fs_dir_t dir) 00841 { 00842 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir); 00843 00844 lock(); 00845 off_t offset = dh->dptr; 00846 unlock(); 00847 00848 return offset; 00849 } 00850 00851 void FATFileSystem::dir_rewind(fs_dir_t dir) 00852 { 00853 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir); 00854 00855 lock(); 00856 f_rewinddir(dh); 00857 unlock(); 00858 } 00859 00860 } // namespace mbed
Generated on Tue Jul 12 2022 13:54:20 by
