Marco Zecchini
/
Example_RTOS
Rtos API example
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[_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 >= _MIN_SS && ssize <= _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 int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize); 00200 return err ? RES_PARERR : RES_OK; 00201 } 00202 00203 DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) 00204 { 00205 debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); 00206 DWORD ssize = disk_get_sector_size(pdrv); 00207 int err = _ffs[pdrv]->erase(sector*ssize, count*ssize); 00208 if (err) { 00209 return RES_PARERR; 00210 } 00211 00212 err = _ffs[pdrv]->program(buff, sector*ssize, count*ssize); 00213 if (err) { 00214 return RES_PARERR; 00215 } 00216 00217 return RES_OK; 00218 } 00219 00220 DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) 00221 { 00222 debug_if(FFS_DBG, "disk_ioctl(%d)\n", cmd); 00223 switch (cmd) { 00224 case CTRL_SYNC: 00225 if (_ffs[pdrv] == NULL) { 00226 return RES_NOTRDY; 00227 } else { 00228 return RES_OK; 00229 } 00230 case GET_SECTOR_COUNT: 00231 if (_ffs[pdrv] == NULL) { 00232 return RES_NOTRDY; 00233 } else { 00234 *((DWORD*)buff) = disk_get_sector_count(pdrv); 00235 return RES_OK; 00236 } 00237 case GET_SECTOR_SIZE: 00238 if (_ffs[pdrv] == NULL) { 00239 return RES_NOTRDY; 00240 } else { 00241 *((WORD*)buff) = disk_get_sector_size(pdrv); 00242 return RES_OK; 00243 } 00244 case GET_BLOCK_SIZE: 00245 *((DWORD*)buff) = 1; // default when not known 00246 return RES_OK; 00247 case CTRL_TRIM: 00248 if (_ffs[pdrv] == NULL) { 00249 return RES_NOTRDY; 00250 } else { 00251 DWORD *sectors = (DWORD*)buff; 00252 DWORD ssize = disk_get_sector_size(pdrv); 00253 int err = _ffs[pdrv]->trim(sectors[0]*ssize, (sectors[1]-sectors[0]+1)*ssize); 00254 return err ? RES_PARERR : RES_OK; 00255 } 00256 } 00257 00258 return RES_PARERR; 00259 } 00260 00261 00262 ////// Generic filesystem operations ////// 00263 00264 // Filesystem implementation (See FATFilySystem.h) 00265 FATFileSystem::FATFileSystem(const char *name, BlockDevice *bd) 00266 : FileSystem(name), _id(-1) { 00267 if (bd) { 00268 mount(bd); 00269 } 00270 } 00271 00272 FATFileSystem::~FATFileSystem() 00273 { 00274 // nop if unmounted 00275 unmount(); 00276 } 00277 00278 int FATFileSystem::mount(BlockDevice *bd) { 00279 // requires duplicate definition to allow virtual overload to work 00280 return mount(bd, true); 00281 } 00282 00283 int FATFileSystem::mount(BlockDevice *bd, bool mount) { 00284 lock(); 00285 if (_id != -1) { 00286 unlock(); 00287 return -EINVAL; 00288 } 00289 00290 for (int i = 0; i < _VOLUMES; i++) { 00291 if (!_ffs[i]) { 00292 _id = i; 00293 _ffs[_id] = bd; 00294 _fsid[0] = '0' + _id; 00295 _fsid[1] = ':'; 00296 _fsid[2] = '\0'; 00297 debug_if(FFS_DBG, "Mounting [%s] on ffs drive [%s]\n", getName(), _fsid); 00298 FRESULT res = f_mount(&_fs, _fsid, mount); 00299 unlock(); 00300 return fat_error_remap(res); 00301 } 00302 } 00303 00304 unlock(); 00305 return -ENOMEM; 00306 } 00307 00308 int FATFileSystem::unmount() 00309 { 00310 lock(); 00311 if (_id == -1) { 00312 unlock(); 00313 return -EINVAL; 00314 } 00315 00316 FRESULT res = f_mount(NULL, _fsid, 0); 00317 _ffs[_id] = NULL; 00318 _id = -1; 00319 unlock(); 00320 return fat_error_remap(res); 00321 } 00322 00323 /* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and 00324 * associated arguments. */ 00325 int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size) { 00326 FATFileSystem fs; 00327 int err = fs.mount(bd, false); 00328 if (err) { 00329 return err; 00330 } 00331 00332 // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster) 00333 fs.lock(); 00334 FRESULT res = f_mkfs(fs._fsid, 1, cluster_size); 00335 fs.unlock(); 00336 if (res != FR_OK) { 00337 return fat_error_remap(res); 00338 } 00339 00340 err = fs.unmount(); 00341 if (err) { 00342 return err; 00343 } 00344 00345 return 0; 00346 } 00347 00348 int FATFileSystem::reformat(BlockDevice *bd, int allocation_unit) { 00349 lock(); 00350 if (_id != -1) { 00351 if (!bd) { 00352 bd = _ffs[_id]; 00353 } 00354 00355 int err = unmount(); 00356 if (err) { 00357 unlock(); 00358 return err; 00359 } 00360 } 00361 00362 if (!bd) { 00363 unlock(); 00364 return -ENODEV; 00365 } 00366 00367 int err = FATFileSystem::format(bd, allocation_unit); 00368 if (err) { 00369 unlock(); 00370 return err; 00371 } 00372 00373 err = mount(bd); 00374 unlock(); 00375 return err; 00376 } 00377 00378 int FATFileSystem::remove(const char *path) { 00379 Deferred<const char*> fpath = fat_path_prefix(_id, path); 00380 00381 lock(); 00382 FRESULT res = f_unlink(fpath); 00383 unlock(); 00384 00385 if (res != FR_OK) { 00386 debug_if(FFS_DBG, "f_unlink() failed: %d\n", res); 00387 } 00388 return fat_error_remap(res); 00389 } 00390 00391 int FATFileSystem::rename(const char *oldpath, const char *newpath) { 00392 Deferred<const char*> oldfpath = fat_path_prefix(_id, oldpath); 00393 Deferred<const char*> newfpath = fat_path_prefix(_id, newpath); 00394 00395 lock(); 00396 FRESULT res = f_rename(oldfpath, newfpath); 00397 unlock(); 00398 00399 if (res != FR_OK) { 00400 debug_if(FFS_DBG, "f_rename() failed: %d\n", res); 00401 } 00402 return fat_error_remap(res); 00403 } 00404 00405 int FATFileSystem::mkdir(const char *path, mode_t mode) { 00406 Deferred<const char*> fpath = fat_path_prefix(_id, path); 00407 00408 lock(); 00409 FRESULT res = f_mkdir(fpath); 00410 unlock(); 00411 00412 if (res != FR_OK) { 00413 debug_if(FFS_DBG, "f_mkdir() failed: %d\n", res); 00414 } 00415 return fat_error_remap(res); 00416 } 00417 00418 int FATFileSystem::stat(const char *path, struct stat *st) { 00419 Deferred<const char*> fpath = fat_path_prefix(_id, path); 00420 00421 lock(); 00422 FILINFO f; 00423 memset(&f, 0, sizeof(f)); 00424 00425 FRESULT res = f_stat(fpath, &f); 00426 if (res != FR_OK) { 00427 unlock(); 00428 return fat_error_remap(res); 00429 } 00430 00431 /* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain. */ 00432 #ifdef TOOLCHAIN_GCC 00433 st->st_size = f.fsize; 00434 st->st_mode = 0; 00435 st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG; 00436 st->st_mode |= (f.fattrib & AM_RDO) ? 00437 (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) : 00438 (S_IRWXU | S_IRWXG | S_IRWXO); 00439 #endif /* TOOLCHAIN_GCC */ 00440 unlock(); 00441 00442 return 0; 00443 } 00444 00445 void FATFileSystem::lock() { 00446 _ffs_mutex->lock(); 00447 } 00448 00449 void FATFileSystem::unlock() { 00450 _ffs_mutex->unlock(); 00451 } 00452 00453 00454 ////// File operations ////// 00455 int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) { 00456 debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", path, getName(), _id); 00457 00458 FIL *fh = new FIL; 00459 Deferred<const char*> fpath = fat_path_prefix(_id, path); 00460 00461 /* POSIX flags -> FatFS open mode */ 00462 BYTE openmode; 00463 if (flags & O_RDWR) { 00464 openmode = FA_READ | FA_WRITE; 00465 } else if (flags & O_WRONLY) { 00466 openmode = FA_WRITE; 00467 } else { 00468 openmode = FA_READ; 00469 } 00470 if (flags & O_CREAT) { 00471 if (flags & O_TRUNC) { 00472 openmode |= FA_CREATE_ALWAYS; 00473 } else { 00474 openmode |= FA_OPEN_ALWAYS; 00475 } 00476 } 00477 00478 lock(); 00479 FRESULT res = f_open(fh, fpath, openmode); 00480 00481 if (res != FR_OK) { 00482 unlock(); 00483 debug_if(FFS_DBG, "f_open('w') failed: %d\n", res); 00484 delete fh; 00485 return fat_error_remap(res); 00486 } 00487 00488 if (flags & O_APPEND) { 00489 f_lseek(fh, fh->fsize); 00490 } 00491 unlock(); 00492 00493 *file = fh; 00494 return 0; 00495 } 00496 00497 int FATFileSystem::file_close(fs_file_t file) { 00498 FIL *fh = static_cast<FIL*>(file); 00499 00500 lock(); 00501 FRESULT res = f_close(fh); 00502 unlock(); 00503 00504 delete fh; 00505 return fat_error_remap(res); 00506 } 00507 00508 ssize_t FATFileSystem::file_read(fs_file_t file, void *buffer, size_t len) { 00509 FIL *fh = static_cast<FIL*>(file); 00510 00511 lock(); 00512 UINT n; 00513 FRESULT res = f_read(fh, buffer, len, &n); 00514 unlock(); 00515 00516 if (res != FR_OK) { 00517 debug_if(FFS_DBG, "f_read() failed: %d\n", res); 00518 return fat_error_remap(res); 00519 } else { 00520 return n; 00521 } 00522 } 00523 00524 ssize_t FATFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) { 00525 FIL *fh = static_cast<FIL*>(file); 00526 00527 lock(); 00528 UINT n; 00529 FRESULT res = f_write(fh, buffer, len, &n); 00530 unlock(); 00531 00532 if (res != FR_OK) { 00533 debug_if(FFS_DBG, "f_write() failed: %d", res); 00534 return fat_error_remap(res); 00535 } else { 00536 return n; 00537 } 00538 } 00539 00540 int FATFileSystem::file_sync(fs_file_t file) { 00541 FIL *fh = static_cast<FIL*>(file); 00542 00543 lock(); 00544 FRESULT res = f_sync(fh); 00545 unlock(); 00546 00547 if (res != FR_OK) { 00548 debug_if(FFS_DBG, "f_sync() failed: %d\n", res); 00549 } 00550 return fat_error_remap(res); 00551 } 00552 00553 off_t FATFileSystem::file_seek(fs_file_t file, off_t offset, int whence) { 00554 FIL *fh = static_cast<FIL*>(file); 00555 00556 lock(); 00557 if (whence == SEEK_END) { 00558 offset += fh->fsize; 00559 } else if(whence==SEEK_CUR) { 00560 offset += fh->fptr; 00561 } 00562 00563 FRESULT res = f_lseek(fh, offset); 00564 off_t noffset = fh->fptr; 00565 unlock(); 00566 00567 if (res != FR_OK) { 00568 debug_if(FFS_DBG, "lseek failed: %d\n", res); 00569 return fat_error_remap(res); 00570 } else { 00571 return noffset; 00572 } 00573 } 00574 00575 off_t FATFileSystem::file_tell(fs_file_t file) { 00576 FIL *fh = static_cast<FIL*>(file); 00577 00578 lock(); 00579 off_t res = fh->fptr; 00580 unlock(); 00581 00582 return res; 00583 } 00584 00585 off_t FATFileSystem::file_size(fs_file_t file) { 00586 FIL *fh = static_cast<FIL*>(file); 00587 00588 lock(); 00589 off_t res = fh->fsize; 00590 unlock(); 00591 00592 return res; 00593 } 00594 00595 00596 ////// Dir operations ////// 00597 int FATFileSystem::dir_open(fs_dir_t *dir, const char *path) { 00598 FATFS_DIR *dh = new FATFS_DIR; 00599 Deferred<const char*> fpath = fat_path_prefix(_id, path); 00600 00601 lock(); 00602 FRESULT res = f_opendir(dh, fpath); 00603 unlock(); 00604 00605 if (res != FR_OK) { 00606 debug_if(FFS_DBG, "f_opendir() failed: %d\n", res); 00607 delete dh; 00608 return fat_error_remap(res); 00609 } 00610 00611 *dir = dh; 00612 return 0; 00613 } 00614 00615 int FATFileSystem::dir_close(fs_dir_t dir) { 00616 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00617 00618 lock(); 00619 FRESULT res = f_closedir(dh); 00620 unlock(); 00621 00622 delete dh; 00623 return fat_error_remap(res); 00624 } 00625 00626 ssize_t FATFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) { 00627 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00628 FILINFO finfo; 00629 00630 #if _USE_LFN 00631 finfo.lfname = ent->d_name; 00632 finfo.lfsize = NAME_MAX; 00633 #endif // _USE_LFN 00634 00635 lock(); 00636 FRESULT res = f_readdir(dh, &finfo); 00637 unlock(); 00638 00639 if (res != FR_OK) { 00640 return fat_error_remap(res); 00641 } else if (finfo.fname[0] == 0) { 00642 return 0; 00643 } 00644 00645 ent->d_type = (finfo.fattrib & AM_DIR) ? DT_DIR : DT_REG; 00646 00647 #if _USE_LFN 00648 if (ent->d_name[0] == 0) { 00649 // No long filename so use short filename. 00650 strncpy(ent->d_name, finfo.fname, NAME_MAX); 00651 } 00652 #else 00653 strncpy(end->d_name, finfo.fname, len); 00654 #endif 00655 00656 return 1; 00657 } 00658 00659 void FATFileSystem::dir_seek(fs_dir_t dir, off_t offset) { 00660 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00661 00662 lock(); 00663 if (offset < dh->index) { 00664 f_rewinddir(dh); 00665 } 00666 while (dh->index < offset) { 00667 FILINFO finfo; 00668 FRESULT res; 00669 #if _USE_LFN 00670 char lfname[NAME_MAX]; 00671 finfo.lfname = lfname; 00672 finfo.lfsize = NAME_MAX; 00673 #endif // _USE_LFN 00674 res = f_readdir(dh, &finfo); 00675 if (res != FR_OK) { 00676 break; 00677 } else if (finfo.fname[0] == 0) { 00678 break; 00679 } 00680 } 00681 unlock(); 00682 } 00683 00684 off_t FATFileSystem::dir_tell(fs_dir_t dir) { 00685 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00686 00687 lock(); 00688 off_t offset = dh->index; 00689 unlock(); 00690 00691 return offset; 00692 } 00693 00694 void FATFileSystem::dir_rewind(fs_dir_t dir) { 00695 FATFS_DIR *dh = static_cast<FATFS_DIR*>(dir); 00696 00697 lock(); 00698 f_rewinddir(dh); 00699 unlock(); 00700 } 00701
Generated on Sun Jul 17 2022 08:25:22 by 1.7.2