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.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
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 default: return err; 00039 } 00040 } 00041 00042 static int lfs_fromflags(int flags) 00043 { 00044 return ( 00045 (((flags & 3) == O_RDONLY) ? LFS_O_RDONLY : 0) | 00046 (((flags & 3) == O_WRONLY) ? LFS_O_WRONLY : 0) | 00047 (((flags & 3) == O_RDWR) ? LFS_O_RDWR : 0) | 00048 ((flags & O_CREAT) ? LFS_O_CREAT : 0) | 00049 ((flags & O_EXCL) ? LFS_O_EXCL : 0) | 00050 ((flags & O_TRUNC) ? LFS_O_TRUNC : 0) | 00051 ((flags & O_APPEND) ? LFS_O_APPEND : 0)); 00052 } 00053 00054 static int lfs_fromwhence(int whence) 00055 { 00056 switch (whence) { 00057 case SEEK_SET: return LFS_SEEK_SET; 00058 case SEEK_CUR: return LFS_SEEK_CUR; 00059 case SEEK_END: return LFS_SEEK_END; 00060 default: return whence; 00061 } 00062 } 00063 00064 static int lfs_tomode(int type) 00065 { 00066 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 00067 switch (type) { 00068 case LFS_TYPE_DIR: return mode | S_IFDIR; 00069 case LFS_TYPE_REG: return mode | S_IFREG; 00070 default: return 0; 00071 } 00072 } 00073 00074 static int lfs_totype(int type) 00075 { 00076 switch (type) { 00077 case LFS_TYPE_DIR: return DT_DIR; 00078 case LFS_TYPE_REG: return DT_REG; 00079 default: return DT_UNKNOWN; 00080 } 00081 } 00082 00083 00084 ////// Block device operations ////// 00085 static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block, 00086 lfs_off_t off, void *buffer, lfs_size_t size) { 00087 BlockDevice *bd = (BlockDevice *)c->context; 00088 return bd->read(buffer, block*c->block_size + off, size); 00089 } 00090 00091 static int lfs_bd_prog(const struct lfs_config *c, lfs_block_t block, 00092 lfs_off_t off, const void *buffer, lfs_size_t size) { 00093 BlockDevice *bd = (BlockDevice *)c->context; 00094 return bd->program(buffer, block*c->block_size + off, size); 00095 } 00096 00097 static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block) 00098 { 00099 BlockDevice *bd = (BlockDevice *)c->context; 00100 return bd->erase(block*c->block_size, c->block_size); 00101 } 00102 00103 static int lfs_bd_sync(const struct lfs_config *c) 00104 { 00105 return 0; 00106 } 00107 00108 00109 ////// Generic filesystem operations ////// 00110 00111 // Filesystem implementation (See LittleFileSystem.h) 00112 LittleFileSystem::LittleFileSystem(const char *name, BlockDevice *bd, 00113 lfs_size_t read_size, lfs_size_t prog_size, 00114 lfs_size_t block_size, lfs_size_t lookahead) 00115 : FileSystem(name) 00116 , _read_size(read_size) 00117 , _prog_size(prog_size) 00118 , _block_size(block_size) 00119 , _lookahead(lookahead) { 00120 if (bd) { 00121 mount(bd); 00122 } 00123 } 00124 00125 LittleFileSystem::~LittleFileSystem() { 00126 // nop if unmounted 00127 unmount(); 00128 } 00129 00130 int LittleFileSystem::mount(BlockDevice *bd) 00131 { 00132 _mutex.lock(); 00133 LFS_INFO("mount(%p)", bd); 00134 _bd = bd; 00135 int err = _bd->init(); 00136 if (err) { 00137 LFS_INFO("mount -> %d", err); 00138 _mutex.unlock(); 00139 return err; 00140 } 00141 00142 memset(&_config, 0, sizeof(_config)); 00143 _config.context = bd; 00144 _config.read = lfs_bd_read; 00145 _config.prog = lfs_bd_prog; 00146 _config.erase = lfs_bd_erase; 00147 _config.sync = lfs_bd_sync; 00148 _config.read_size = bd->get_read_size(); 00149 if (_config.read_size < _read_size) { 00150 _config.read_size = _read_size; 00151 } 00152 _config.prog_size = bd->get_program_size(); 00153 if (_config.prog_size < _prog_size) { 00154 _config.prog_size = _prog_size; 00155 } 00156 _config.block_size = bd->get_erase_size(); 00157 if (_config.block_size < _block_size) { 00158 _config.block_size = _block_size; 00159 } 00160 _config.block_count = bd->size() / _config.block_size; 00161 _config.lookahead = 32 * ((_config.block_count+31)/32); 00162 if (_config.lookahead > _lookahead) { 00163 _config.lookahead = _lookahead; 00164 } 00165 00166 err = lfs_mount(&_lfs, &_config); 00167 LFS_INFO("mount -> %d", lfs_toerror(err)); 00168 _mutex.unlock(); 00169 return lfs_toerror(err); 00170 } 00171 00172 int LittleFileSystem::unmount() 00173 { 00174 _mutex.lock(); 00175 LFS_INFO("unmount(%s)", ""); 00176 if (_bd) { 00177 int err = lfs_unmount(&_lfs); 00178 if (err) { 00179 LFS_INFO("unmount -> %d", lfs_toerror(err)); 00180 _mutex.unlock(); 00181 return lfs_toerror(err); 00182 } 00183 00184 err = _bd->deinit(); 00185 if (err) { 00186 LFS_INFO("unmount -> %d", err); 00187 _mutex.unlock(); 00188 return err; 00189 } 00190 00191 _bd = NULL; 00192 } 00193 00194 LFS_INFO("unmount -> %d", 0); 00195 _mutex.unlock(); 00196 return 0; 00197 } 00198 00199 int LittleFileSystem::format(BlockDevice *bd, 00200 lfs_size_t read_size, lfs_size_t prog_size, 00201 lfs_size_t block_size, lfs_size_t lookahead) { 00202 LFS_INFO("format(%p, %ld, %ld, %ld, %ld)", 00203 bd, read_size, prog_size, block_size, lookahead); 00204 int err = bd->init(); 00205 if (err) { 00206 LFS_INFO("format -> %d", err); 00207 return err; 00208 } 00209 00210 lfs_t _lfs; 00211 struct lfs_config _config; 00212 00213 memset(&_config, 0, sizeof(_config)); 00214 _config.context = bd; 00215 _config.read = lfs_bd_read; 00216 _config.prog = lfs_bd_prog; 00217 _config.erase = lfs_bd_erase; 00218 _config.sync = lfs_bd_sync; 00219 _config.read_size = bd->get_read_size(); 00220 if (_config.read_size < read_size) { 00221 _config.read_size = read_size; 00222 } 00223 _config.prog_size = bd->get_program_size(); 00224 if (_config.prog_size < prog_size) { 00225 _config.prog_size = prog_size; 00226 } 00227 _config.block_size = bd->get_erase_size(); 00228 if (_config.block_size < block_size) { 00229 _config.block_size = block_size; 00230 } 00231 _config.block_count = bd->size() / _config.block_size; 00232 _config.lookahead = 32 * ((_config.block_count+31)/32); 00233 if (_config.lookahead > lookahead) { 00234 _config.lookahead = lookahead; 00235 } 00236 00237 err = lfs_format(&_lfs, &_config); 00238 if (err) { 00239 LFS_INFO("format -> %d", lfs_toerror(err)); 00240 return lfs_toerror(err); 00241 } 00242 00243 err = bd->deinit(); 00244 if (err) { 00245 LFS_INFO("format -> %d", err); 00246 return err; 00247 } 00248 00249 LFS_INFO("format -> %d", 0); 00250 return 0; 00251 } 00252 00253 int LittleFileSystem::reformat(BlockDevice *bd) 00254 { 00255 _mutex.lock(); 00256 LFS_INFO("reformat(%p)", bd); 00257 if (_bd) { 00258 if (!bd) { 00259 bd = _bd; 00260 } 00261 00262 int err = unmount(); 00263 if (err) { 00264 LFS_INFO("reformat -> %d", err); 00265 _mutex.unlock(); 00266 return err; 00267 } 00268 } 00269 00270 if (!bd) { 00271 LFS_INFO("reformat -> %d", -ENODEV); 00272 _mutex.unlock(); 00273 return -ENODEV; 00274 } 00275 00276 int err = LittleFileSystem::format(bd, 00277 _read_size, _prog_size, _block_size, _lookahead); 00278 if (err) { 00279 LFS_INFO("reformat -> %d", err); 00280 _mutex.unlock(); 00281 return err; 00282 } 00283 00284 err = mount(bd); 00285 if (err) { 00286 LFS_INFO("reformat -> %d", err); 00287 _mutex.unlock(); 00288 return err; 00289 } 00290 00291 LFS_INFO("reformat -> %d", 0); 00292 _mutex.unlock(); 00293 return 0; 00294 } 00295 00296 int LittleFileSystem::remove(const char *filename) 00297 { 00298 _mutex.lock(); 00299 LFS_INFO("remove(\"%s\")", filename); 00300 int err = lfs_remove(&_lfs, filename); 00301 LFS_INFO("remove -> %d", lfs_toerror(err)); 00302 _mutex.unlock(); 00303 return lfs_toerror(err); 00304 } 00305 00306 int LittleFileSystem::rename(const char *oldname, const char *newname) 00307 { 00308 _mutex.lock(); 00309 LFS_INFO("rename(\"%s\", \"%s\")", oldname, newname); 00310 int err = lfs_rename(&_lfs, oldname, newname); 00311 LFS_INFO("rename -> %d", lfs_toerror(err)); 00312 _mutex.unlock(); 00313 return lfs_toerror(err); 00314 } 00315 00316 int LittleFileSystem::mkdir(const char *name, mode_t mode) 00317 { 00318 _mutex.lock(); 00319 LFS_INFO("mkdir(\"%s\", 0x%lx)", name, mode); 00320 int err = lfs_mkdir(&_lfs, name); 00321 LFS_INFO("mkdir -> %d", lfs_toerror(err)); 00322 _mutex.unlock(); 00323 return lfs_toerror(err); 00324 } 00325 00326 int LittleFileSystem::stat(const char *name, struct stat *st) 00327 { 00328 struct lfs_info info; 00329 _mutex.lock(); 00330 LFS_INFO("stat(\"%s\", %p)", name, st); 00331 int err = lfs_stat(&_lfs, name, &info); 00332 LFS_INFO("stat -> %d", lfs_toerror(err)); 00333 _mutex.unlock(); 00334 st->st_size = info.size; 00335 st->st_mode = lfs_tomode(info.type); 00336 return lfs_toerror(err); 00337 } 00338 00339 00340 ////// File operations ////// 00341 int LittleFileSystem::file_open(fs_file_t *file, const char *path, int flags) 00342 { 00343 lfs_file_t *f = new lfs_file_t; 00344 _mutex.lock(); 00345 LFS_INFO("file_open(%p, \"%s\", 0x%x)", *file, path, flags); 00346 int err = lfs_file_open(&_lfs, f, path, lfs_fromflags(flags)); 00347 LFS_INFO("file_open -> %d", lfs_toerror(err)); 00348 _mutex.unlock(); 00349 if (!err) { 00350 *file = f; 00351 } else { 00352 delete f; 00353 } 00354 return lfs_toerror(err); 00355 } 00356 00357 int LittleFileSystem::file_close(fs_file_t file) 00358 { 00359 lfs_file_t *f = (lfs_file_t *)file; 00360 _mutex.lock(); 00361 LFS_INFO("file_close(%p)", file); 00362 int err = lfs_file_close(&_lfs, f); 00363 LFS_INFO("file_close -> %d", lfs_toerror(err)); 00364 _mutex.unlock(); 00365 delete f; 00366 return lfs_toerror(err); 00367 } 00368 00369 ssize_t LittleFileSystem::file_read(fs_file_t file, void *buffer, size_t len) 00370 { 00371 lfs_file_t *f = (lfs_file_t *)file; 00372 _mutex.lock(); 00373 LFS_INFO("file_read(%p, %p, %d)", file, buffer, len); 00374 lfs_ssize_t res = lfs_file_read(&_lfs, f, buffer, len); 00375 LFS_INFO("file_read -> %d", lfs_toerror(res)); 00376 _mutex.unlock(); 00377 return lfs_toerror(res); 00378 } 00379 00380 ssize_t LittleFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) 00381 { 00382 lfs_file_t *f = (lfs_file_t *)file; 00383 _mutex.lock(); 00384 LFS_INFO("file_write(%p, %p, %d)", file, buffer, len); 00385 lfs_ssize_t res = lfs_file_write(&_lfs, f, buffer, len); 00386 LFS_INFO("file_write -> %d", lfs_toerror(res)); 00387 _mutex.unlock(); 00388 return lfs_toerror(res); 00389 } 00390 00391 int LittleFileSystem::file_sync(fs_file_t file) 00392 { 00393 lfs_file_t *f = (lfs_file_t *)file; 00394 _mutex.lock(); 00395 LFS_INFO("file_sync(%p)", file); 00396 int err = lfs_file_sync(&_lfs, f); 00397 LFS_INFO("file_sync -> %d", lfs_toerror(err)); 00398 _mutex.unlock(); 00399 return lfs_toerror(err); 00400 } 00401 00402 off_t LittleFileSystem::file_seek(fs_file_t file, off_t offset, int whence) 00403 { 00404 lfs_file_t *f = (lfs_file_t *)file; 00405 _mutex.lock(); 00406 LFS_INFO("file_seek(%p, %ld, %d)", file, offset, whence); 00407 off_t res = lfs_file_seek(&_lfs, f, offset, lfs_fromwhence(whence)); 00408 LFS_INFO("file_seek -> %d", lfs_toerror(res)); 00409 _mutex.unlock(); 00410 return lfs_toerror(res); 00411 } 00412 00413 off_t LittleFileSystem::file_tell(fs_file_t file) 00414 { 00415 lfs_file_t *f = (lfs_file_t *)file; 00416 _mutex.lock(); 00417 LFS_INFO("file_tell(%p)", file); 00418 off_t res = lfs_file_tell(&_lfs, f); 00419 LFS_INFO("file_tell -> %d", lfs_toerror(res)); 00420 _mutex.unlock(); 00421 return lfs_toerror(res); 00422 } 00423 00424 off_t LittleFileSystem::file_size(fs_file_t file) 00425 { 00426 lfs_file_t *f = (lfs_file_t *)file; 00427 _mutex.lock(); 00428 LFS_INFO("file_size(%p)", file); 00429 off_t res = lfs_file_size(&_lfs, f); 00430 LFS_INFO("file_size -> %d", lfs_toerror(res)); 00431 _mutex.unlock(); 00432 return lfs_toerror(res); 00433 } 00434 00435 00436 ////// Dir operations ////// 00437 int LittleFileSystem::dir_open(fs_dir_t *dir, const char *path) 00438 { 00439 lfs_dir_t *d = new lfs_dir_t; 00440 _mutex.lock(); 00441 LFS_INFO("dir_open(%p, \"%s\")", *dir, path); 00442 int err = lfs_dir_open(&_lfs, d, path); 00443 LFS_INFO("dir_open -> %d", lfs_toerror(err)); 00444 _mutex.unlock(); 00445 if (!err) { 00446 *dir = d; 00447 } else { 00448 delete d; 00449 } 00450 return lfs_toerror(err); 00451 } 00452 00453 int LittleFileSystem::dir_close(fs_dir_t dir) 00454 { 00455 lfs_dir_t *d = (lfs_dir_t *)dir; 00456 _mutex.lock(); 00457 LFS_INFO("dir_close(%p)", dir); 00458 int err = lfs_dir_close(&_lfs, d); 00459 LFS_INFO("dir_close -> %d", lfs_toerror(err)); 00460 _mutex.unlock(); 00461 delete d; 00462 return lfs_toerror(err); 00463 } 00464 00465 ssize_t LittleFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) 00466 { 00467 lfs_dir_t *d = (lfs_dir_t *)dir; 00468 struct lfs_info info; 00469 _mutex.lock(); 00470 LFS_INFO("dir_read(%p, %p)", dir, ent); 00471 int res = lfs_dir_read(&_lfs, d, &info); 00472 LFS_INFO("dir_read -> %d", lfs_toerror(res)); 00473 _mutex.unlock(); 00474 if (res == 1) { 00475 ent->d_type = lfs_totype(info.type); 00476 strcpy(ent->d_name, info.name); 00477 } 00478 return lfs_toerror(res); 00479 } 00480 00481 void LittleFileSystem::dir_seek(fs_dir_t dir, off_t offset) 00482 { 00483 lfs_dir_t *d = (lfs_dir_t *)dir; 00484 _mutex.lock(); 00485 LFS_INFO("dir_seek(%p, %ld)", dir, offset); 00486 lfs_dir_seek(&_lfs, d, offset); 00487 LFS_INFO("dir_seek -> %s", "void"); 00488 _mutex.unlock(); 00489 } 00490 00491 off_t LittleFileSystem::dir_tell(fs_dir_t dir) 00492 { 00493 lfs_dir_t *d = (lfs_dir_t *)dir; 00494 _mutex.lock(); 00495 LFS_INFO("dir_tell(%p)", dir); 00496 lfs_soff_t res = lfs_dir_tell(&_lfs, d); 00497 LFS_INFO("dir_tell -> %d", lfs_toerror(res)); 00498 _mutex.unlock(); 00499 return lfs_toerror(res); 00500 } 00501 00502 void LittleFileSystem::dir_rewind(fs_dir_t dir) 00503 { 00504 lfs_dir_t *d = (lfs_dir_t *)dir; 00505 _mutex.lock(); 00506 LFS_INFO("dir_rewind(%p)", dir); 00507 lfs_dir_rewind(&_lfs, d); 00508 LFS_INFO("dir_rewind -> %s", "void"); 00509 _mutex.unlock(); 00510 } 00511
Generated on Tue Jul 12 2022 13:02:56 by
