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