init
Embed:
(wiki syntax)
Show/hide line numbers
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 if (res != FR_OK) { 00728 break; 00729 } else if (finfo.fname[0] == 0) { 00730 break; 00731 } 00732 } 00733 unlock(); 00734 } 00735 00736 off_t FATFileSystem::dir_tell(fs_dir_t dir) 00737 { 00738 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00739 00740 lock(); 00741 off_t offset = dh->dptr; 00742 unlock(); 00743 00744 return offset; 00745 } 00746 00747 void FATFileSystem::dir_rewind(fs_dir_t dir) 00748 { 00749 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00750 00751 lock(); 00752 f_rewinddir(dh); 00753 unlock(); 00754 } 00755
Generated on Tue Jul 12 2022 13:24:40 by
1.7.2