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