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