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.
LittleFileSystem.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "mbed.h" 00017 #include "LittleFileSystem.h" 00018 #include "errno.h" 00019 extern "C" { 00020 #include "lfs.h" 00021 #include "lfs_util.h" 00022 } 00023 00024 00025 ////// Conversion functions ////// 00026 static int lfs_toerror(int err) 00027 { 00028 switch (err) { 00029 case LFS_ERR_OK: return 0; 00030 case LFS_ERR_IO: return -EIO; 00031 case LFS_ERR_NOENT: return -ENOENT; 00032 case LFS_ERR_EXIST: return -EEXIST; 00033 case LFS_ERR_NOTDIR: return -ENOTDIR; 00034 case LFS_ERR_ISDIR: return -EISDIR; 00035 case LFS_ERR_INVAL: return -EINVAL; 00036 case LFS_ERR_NOSPC: return -ENOSPC; 00037 case LFS_ERR_NOMEM: return -ENOMEM; 00038 case LFS_ERR_CORRUPT: return -EILSEQ; 00039 default: return err; 00040 } 00041 } 00042 00043 static int lfs_fromflags(int flags) 00044 { 00045 return ( 00046 (((flags & 3) == O_RDONLY) ? LFS_O_RDONLY : 0) | 00047 (((flags & 3) == O_WRONLY) ? LFS_O_WRONLY : 0) | 00048 (((flags & 3) == O_RDWR) ? LFS_O_RDWR : 0) | 00049 ((flags & O_CREAT) ? LFS_O_CREAT : 0) | 00050 ((flags & O_EXCL) ? LFS_O_EXCL : 0) | 00051 ((flags & O_TRUNC) ? LFS_O_TRUNC : 0) | 00052 ((flags & O_APPEND) ? LFS_O_APPEND : 0)); 00053 } 00054 00055 static int lfs_fromwhence(int whence) 00056 { 00057 switch (whence) { 00058 case SEEK_SET: return LFS_SEEK_SET; 00059 case SEEK_CUR: return LFS_SEEK_CUR; 00060 case SEEK_END: return LFS_SEEK_END; 00061 default: return whence; 00062 } 00063 } 00064 00065 static int lfs_tomode(int type) 00066 { 00067 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 00068 switch (type) { 00069 case LFS_TYPE_DIR: return mode | S_IFDIR; 00070 case LFS_TYPE_REG: return mode | S_IFREG; 00071 default: return 0; 00072 } 00073 } 00074 00075 static int lfs_totype(int type) 00076 { 00077 switch (type) { 00078 case LFS_TYPE_DIR: return DT_DIR; 00079 case LFS_TYPE_REG: return DT_REG; 00080 default: return DT_UNKNOWN; 00081 } 00082 } 00083 00084 00085 ////// Block device operations ////// 00086 static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block, 00087 lfs_off_t off, void *buffer, lfs_size_t size) { 00088 BlockDevice *bd = (BlockDevice *)c->context; 00089 return bd->read(buffer, (bd_addr_t)block*c->block_size + off, size); 00090 } 00091 00092 static int lfs_bd_prog(const struct lfs_config *c, lfs_block_t block, 00093 lfs_off_t off, const void *buffer, lfs_size_t size) { 00094 BlockDevice *bd = (BlockDevice *)c->context; 00095 return bd->program(buffer, (bd_addr_t)block*c->block_size + off, size); 00096 } 00097 00098 static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block) 00099 { 00100 BlockDevice *bd = (BlockDevice *)c->context; 00101 return bd->erase((bd_addr_t)block*c->block_size, c->block_size); 00102 } 00103 00104 static int lfs_bd_sync(const struct lfs_config *c) 00105 { 00106 BlockDevice *bd = (BlockDevice *)c->context; 00107 return bd->sync(); 00108 } 00109 00110 00111 ////// Generic filesystem operations ////// 00112 00113 // Filesystem implementation (See LittleFileSystem.h) 00114 LittleFileSystem::LittleFileSystem(const char *name, BlockDevice *bd, 00115 lfs_size_t read_size, lfs_size_t prog_size, 00116 lfs_size_t block_size, lfs_size_t lookahead) 00117 : FileSystem(name) 00118 , _read_size(read_size) 00119 , _prog_size(prog_size) 00120 , _block_size(block_size) 00121 , _lookahead(lookahead) { 00122 if (bd) { 00123 mount(bd); 00124 } 00125 } 00126 00127 LittleFileSystem::~LittleFileSystem() { 00128 // nop if unmounted 00129 unmount(); 00130 } 00131 00132 int LittleFileSystem::mount(BlockDevice *bd) 00133 { 00134 _mutex.lock(); 00135 LFS_INFO("mount(%p)", bd); 00136 _bd = bd; 00137 int err = _bd->init(); 00138 if (err) { 00139 LFS_INFO("mount -> %d", err); 00140 _mutex.unlock(); 00141 return err; 00142 } 00143 00144 memset(&_config, 0, sizeof(_config)); 00145 _config.context = bd; 00146 _config.read = lfs_bd_read; 00147 _config.prog = lfs_bd_prog; 00148 _config.erase = lfs_bd_erase; 00149 _config.sync = lfs_bd_sync; 00150 _config.read_size = bd->get_read_size(); 00151 if (_config.read_size < _read_size) { 00152 _config.read_size = _read_size; 00153 } 00154 _config.prog_size = bd->get_program_size(); 00155 if (_config.prog_size < _prog_size) { 00156 _config.prog_size = _prog_size; 00157 } 00158 _config.block_size = bd->get_erase_size(); 00159 if (_config.block_size < _block_size) { 00160 _config.block_size = _block_size; 00161 } 00162 _config.block_count = bd->size() / _config.block_size; 00163 _config.lookahead = 32 * ((_config.block_count+31)/32); 00164 if (_config.lookahead > _lookahead) { 00165 _config.lookahead = _lookahead; 00166 } 00167 00168 err = lfs_mount(&_lfs, &_config); 00169 LFS_INFO("mount -> %d", lfs_toerror(err)); 00170 _mutex.unlock(); 00171 return lfs_toerror(err); 00172 } 00173 00174 int LittleFileSystem::unmount() 00175 { 00176 _mutex.lock(); 00177 LFS_INFO("unmount(%s)", ""); 00178 if (_bd) { 00179 int err = lfs_unmount(&_lfs); 00180 if (err) { 00181 LFS_INFO("unmount -> %d", lfs_toerror(err)); 00182 _mutex.unlock(); 00183 return lfs_toerror(err); 00184 } 00185 00186 err = _bd->deinit(); 00187 if (err) { 00188 LFS_INFO("unmount -> %d", err); 00189 _mutex.unlock(); 00190 return err; 00191 } 00192 00193 _bd = NULL; 00194 } 00195 00196 LFS_INFO("unmount -> %d", 0); 00197 _mutex.unlock(); 00198 return 0; 00199 } 00200 00201 int LittleFileSystem::format(BlockDevice *bd, 00202 lfs_size_t read_size, lfs_size_t prog_size, 00203 lfs_size_t block_size, lfs_size_t lookahead) { 00204 LFS_INFO("format(%p, %ld, %ld, %ld, %ld)", 00205 bd, read_size, prog_size, block_size, lookahead); 00206 int err = bd->init(); 00207 if (err) { 00208 LFS_INFO("format -> %d", err); 00209 return err; 00210 } 00211 00212 lfs_t _lfs; 00213 struct lfs_config _config; 00214 00215 memset(&_config, 0, sizeof(_config)); 00216 _config.context = bd; 00217 _config.read = lfs_bd_read; 00218 _config.prog = lfs_bd_prog; 00219 _config.erase = lfs_bd_erase; 00220 _config.sync = lfs_bd_sync; 00221 _config.read_size = bd->get_read_size(); 00222 if (_config.read_size < read_size) { 00223 _config.read_size = read_size; 00224 } 00225 _config.prog_size = bd->get_program_size(); 00226 if (_config.prog_size < prog_size) { 00227 _config.prog_size = prog_size; 00228 } 00229 _config.block_size = bd->get_erase_size(); 00230 if (_config.block_size < block_size) { 00231 _config.block_size = block_size; 00232 } 00233 _config.block_count = bd->size() / _config.block_size; 00234 _config.lookahead = 32 * ((_config.block_count+31)/32); 00235 if (_config.lookahead > lookahead) { 00236 _config.lookahead = lookahead; 00237 } 00238 00239 err = lfs_format(&_lfs, &_config); 00240 if (err) { 00241 LFS_INFO("format -> %d", lfs_toerror(err)); 00242 return lfs_toerror(err); 00243 } 00244 00245 err = bd->deinit(); 00246 if (err) { 00247 LFS_INFO("format -> %d", err); 00248 return err; 00249 } 00250 00251 LFS_INFO("format -> %d", 0); 00252 return 0; 00253 } 00254 00255 int LittleFileSystem::reformat(BlockDevice *bd) 00256 { 00257 _mutex.lock(); 00258 LFS_INFO("reformat(%p)", bd); 00259 if (_bd) { 00260 if (!bd) { 00261 bd = _bd; 00262 } 00263 00264 int err = unmount(); 00265 if (err) { 00266 LFS_INFO("reformat -> %d", err); 00267 _mutex.unlock(); 00268 return err; 00269 } 00270 } 00271 00272 if (!bd) { 00273 LFS_INFO("reformat -> %d", -ENODEV); 00274 _mutex.unlock(); 00275 return -ENODEV; 00276 } 00277 00278 int err = LittleFileSystem::format(bd, 00279 _read_size, _prog_size, _block_size, _lookahead); 00280 if (err) { 00281 LFS_INFO("reformat -> %d", err); 00282 _mutex.unlock(); 00283 return err; 00284 } 00285 00286 err = mount(bd); 00287 if (err) { 00288 LFS_INFO("reformat -> %d", err); 00289 _mutex.unlock(); 00290 return err; 00291 } 00292 00293 LFS_INFO("reformat -> %d", 0); 00294 _mutex.unlock(); 00295 return 0; 00296 } 00297 00298 int LittleFileSystem::remove(const char *filename) 00299 { 00300 _mutex.lock(); 00301 LFS_INFO("remove(\"%s\")", filename); 00302 int err = lfs_remove(&_lfs, filename); 00303 LFS_INFO("remove -> %d", lfs_toerror(err)); 00304 _mutex.unlock(); 00305 return lfs_toerror(err); 00306 } 00307 00308 int LittleFileSystem::rename(const char *oldname, const char *newname) 00309 { 00310 _mutex.lock(); 00311 LFS_INFO("rename(\"%s\", \"%s\")", oldname, newname); 00312 int err = lfs_rename(&_lfs, oldname, newname); 00313 LFS_INFO("rename -> %d", lfs_toerror(err)); 00314 _mutex.unlock(); 00315 return lfs_toerror(err); 00316 } 00317 00318 int LittleFileSystem::mkdir(const char *name, mode_t mode) 00319 { 00320 _mutex.lock(); 00321 LFS_INFO("mkdir(\"%s\", 0x%lx)", name, mode); 00322 int err = lfs_mkdir(&_lfs, name); 00323 LFS_INFO("mkdir -> %d", lfs_toerror(err)); 00324 _mutex.unlock(); 00325 return lfs_toerror(err); 00326 } 00327 00328 int LittleFileSystem::stat(const char *name, struct stat *st) 00329 { 00330 struct lfs_info info; 00331 _mutex.lock(); 00332 LFS_INFO("stat(\"%s\", %p)", name, st); 00333 int err = lfs_stat(&_lfs, name, &info); 00334 LFS_INFO("stat -> %d", lfs_toerror(err)); 00335 _mutex.unlock(); 00336 st->st_size = info.size; 00337 st->st_mode = lfs_tomode(info.type); 00338 return lfs_toerror(err); 00339 } 00340 00341 static int lfs_statvfs_count(void *p, lfs_block_t b) 00342 { 00343 *(lfs_size_t *)p += 1; 00344 return 0; 00345 } 00346 00347 int LittleFileSystem::statvfs(const char *name, struct statvfs *st) 00348 { 00349 memset(st, 0, sizeof(struct statvfs)); 00350 00351 lfs_size_t in_use = 0; 00352 _mutex.lock(); 00353 LFS_INFO("statvfs(\"%s\", %p)", name, st); 00354 int err = lfs_traverse(&_lfs, lfs_statvfs_count, &in_use); 00355 LFS_INFO("statvfs -> %d", lfs_toerror(err)); 00356 _mutex.unlock(); 00357 if (err) { 00358 return err; 00359 } 00360 00361 st->f_bsize = _config.block_size; 00362 st->f_frsize = _config.block_size; 00363 st->f_blocks = _config.block_count; 00364 st->f_bfree = _config.block_count - in_use; 00365 st->f_bavail = _config.block_count - in_use; 00366 st->f_namemax = LFS_NAME_MAX; 00367 return 0; 00368 } 00369 00370 ////// File operations ////// 00371 int LittleFileSystem::file_open(fs_file_t *file, const char *path, int flags) 00372 { 00373 lfs_file_t *f = new lfs_file_t; 00374 _mutex.lock(); 00375 LFS_INFO("file_open(%p, \"%s\", 0x%x)", *file, path, flags); 00376 int err = lfs_file_open(&_lfs, f, path, lfs_fromflags(flags)); 00377 LFS_INFO("file_open -> %d", lfs_toerror(err)); 00378 _mutex.unlock(); 00379 if (!err) { 00380 *file = f; 00381 } else { 00382 delete f; 00383 } 00384 return lfs_toerror(err); 00385 } 00386 00387 int LittleFileSystem::file_close(fs_file_t file) 00388 { 00389 lfs_file_t *f = (lfs_file_t *)file; 00390 _mutex.lock(); 00391 LFS_INFO("file_close(%p)", file); 00392 int err = lfs_file_close(&_lfs, f); 00393 LFS_INFO("file_close -> %d", lfs_toerror(err)); 00394 _mutex.unlock(); 00395 delete f; 00396 return lfs_toerror(err); 00397 } 00398 00399 ssize_t LittleFileSystem::file_read(fs_file_t file, void *buffer, size_t len) 00400 { 00401 lfs_file_t *f = (lfs_file_t *)file; 00402 _mutex.lock(); 00403 LFS_INFO("file_read(%p, %p, %d)", file, buffer, len); 00404 lfs_ssize_t res = lfs_file_read(&_lfs, f, buffer, len); 00405 LFS_INFO("file_read -> %d", lfs_toerror(res)); 00406 _mutex.unlock(); 00407 return lfs_toerror(res); 00408 } 00409 00410 ssize_t LittleFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) 00411 { 00412 lfs_file_t *f = (lfs_file_t *)file; 00413 _mutex.lock(); 00414 LFS_INFO("file_write(%p, %p, %d)", file, buffer, len); 00415 lfs_ssize_t res = lfs_file_write(&_lfs, f, buffer, len); 00416 LFS_INFO("file_write -> %d", lfs_toerror(res)); 00417 _mutex.unlock(); 00418 return lfs_toerror(res); 00419 } 00420 00421 int LittleFileSystem::file_sync(fs_file_t file) 00422 { 00423 lfs_file_t *f = (lfs_file_t *)file; 00424 _mutex.lock(); 00425 LFS_INFO("file_sync(%p)", file); 00426 int err = lfs_file_sync(&_lfs, f); 00427 LFS_INFO("file_sync -> %d", lfs_toerror(err)); 00428 _mutex.unlock(); 00429 return lfs_toerror(err); 00430 } 00431 00432 off_t LittleFileSystem::file_seek(fs_file_t file, off_t offset, int whence) 00433 { 00434 lfs_file_t *f = (lfs_file_t *)file; 00435 _mutex.lock(); 00436 LFS_INFO("file_seek(%p, %ld, %d)", file, offset, whence); 00437 off_t res = lfs_file_seek(&_lfs, f, offset, lfs_fromwhence(whence)); 00438 LFS_INFO("file_seek -> %d", lfs_toerror(res)); 00439 _mutex.unlock(); 00440 return lfs_toerror(res); 00441 } 00442 00443 off_t LittleFileSystem::file_tell(fs_file_t file) 00444 { 00445 lfs_file_t *f = (lfs_file_t *)file; 00446 _mutex.lock(); 00447 LFS_INFO("file_tell(%p)", file); 00448 off_t res = lfs_file_tell(&_lfs, f); 00449 LFS_INFO("file_tell -> %d", lfs_toerror(res)); 00450 _mutex.unlock(); 00451 return lfs_toerror(res); 00452 } 00453 00454 off_t LittleFileSystem::file_size(fs_file_t file) 00455 { 00456 lfs_file_t *f = (lfs_file_t *)file; 00457 _mutex.lock(); 00458 LFS_INFO("file_size(%p)", file); 00459 off_t res = lfs_file_size(&_lfs, f); 00460 LFS_INFO("file_size -> %d", lfs_toerror(res)); 00461 _mutex.unlock(); 00462 return lfs_toerror(res); 00463 } 00464 00465 00466 ////// Dir operations ////// 00467 int LittleFileSystem::dir_open(fs_dir_t *dir, const char *path) 00468 { 00469 lfs_dir_t *d = new lfs_dir_t; 00470 _mutex.lock(); 00471 LFS_INFO("dir_open(%p, \"%s\")", *dir, path); 00472 int err = lfs_dir_open(&_lfs, d, path); 00473 LFS_INFO("dir_open -> %d", lfs_toerror(err)); 00474 _mutex.unlock(); 00475 if (!err) { 00476 *dir = d; 00477 } else { 00478 delete d; 00479 } 00480 return lfs_toerror(err); 00481 } 00482 00483 int LittleFileSystem::dir_close(fs_dir_t dir) 00484 { 00485 lfs_dir_t *d = (lfs_dir_t *)dir; 00486 _mutex.lock(); 00487 LFS_INFO("dir_close(%p)", dir); 00488 int err = lfs_dir_close(&_lfs, d); 00489 LFS_INFO("dir_close -> %d", lfs_toerror(err)); 00490 _mutex.unlock(); 00491 delete d; 00492 return lfs_toerror(err); 00493 } 00494 00495 ssize_t LittleFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) 00496 { 00497 lfs_dir_t *d = (lfs_dir_t *)dir; 00498 struct lfs_info info; 00499 _mutex.lock(); 00500 LFS_INFO("dir_read(%p, %p)", dir, ent); 00501 int res = lfs_dir_read(&_lfs, d, &info); 00502 LFS_INFO("dir_read -> %d", lfs_toerror(res)); 00503 _mutex.unlock(); 00504 if (res == 1) { 00505 ent->d_type = lfs_totype(info.type); 00506 strcpy(ent->d_name, info.name); 00507 } 00508 return lfs_toerror(res); 00509 } 00510 00511 void LittleFileSystem::dir_seek(fs_dir_t dir, off_t offset) 00512 { 00513 lfs_dir_t *d = (lfs_dir_t *)dir; 00514 _mutex.lock(); 00515 LFS_INFO("dir_seek(%p, %ld)", dir, offset); 00516 lfs_dir_seek(&_lfs, d, offset); 00517 LFS_INFO("dir_seek -> %s", "void"); 00518 _mutex.unlock(); 00519 } 00520 00521 off_t LittleFileSystem::dir_tell(fs_dir_t dir) 00522 { 00523 lfs_dir_t *d = (lfs_dir_t *)dir; 00524 _mutex.lock(); 00525 LFS_INFO("dir_tell(%p)", dir); 00526 lfs_soff_t res = lfs_dir_tell(&_lfs, d); 00527 LFS_INFO("dir_tell -> %d", lfs_toerror(res)); 00528 _mutex.unlock(); 00529 return lfs_toerror(res); 00530 } 00531 00532 void LittleFileSystem::dir_rewind(fs_dir_t dir) 00533 { 00534 lfs_dir_t *d = (lfs_dir_t *)dir; 00535 _mutex.lock(); 00536 LFS_INFO("dir_rewind(%p)", dir); 00537 lfs_dir_rewind(&_lfs, d); 00538 LFS_INFO("dir_rewind -> %s", "void"); 00539 _mutex.unlock(); 00540 } 00541
Generated on Tue Jul 12 2022 12:44:27 by
