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