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.
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 20:52:42 by
1.7.2