init
Embed:
(wiki syntax)
Show/hide line numbers
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, (bd_addr_t)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, (bd_addr_t)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((bd_addr_t)block*c->block_size, c->block_size); 00101 } 00102 00103 static int lfs_bd_sync(const struct lfs_config *c) 00104 { 00105 BlockDevice *bd = (BlockDevice *)c->context; 00106 return bd->sync(); 00107 } 00108 00109 00110 ////// Generic filesystem operations ////// 00111 00112 // Filesystem implementation (See LittleFileSystem.h) 00113 LittleFileSystem::LittleFileSystem(const char *name, BlockDevice *bd, 00114 lfs_size_t read_size, lfs_size_t prog_size, 00115 lfs_size_t block_size, lfs_size_t lookahead) 00116 : FileSystem(name) 00117 , _read_size(read_size) 00118 , _prog_size(prog_size) 00119 , _block_size(block_size) 00120 , _lookahead(lookahead) { 00121 if (bd) { 00122 mount(bd); 00123 } 00124 } 00125 00126 LittleFileSystem::~LittleFileSystem() { 00127 // nop if unmounted 00128 unmount(); 00129 } 00130 00131 int LittleFileSystem::mount(BlockDevice *bd) 00132 { 00133 _mutex.lock(); 00134 LFS_INFO("mount(%p)", bd); 00135 _bd = bd; 00136 int err = _bd->init(); 00137 if (err) { 00138 LFS_INFO("mount -> %d", err); 00139 _mutex.unlock(); 00140 return err; 00141 } 00142 00143 memset(&_config, 0, sizeof(_config)); 00144 _config.context = bd; 00145 _config.read = lfs_bd_read; 00146 _config.prog = lfs_bd_prog; 00147 _config.erase = lfs_bd_erase; 00148 _config.sync = lfs_bd_sync; 00149 _config.read_size = bd->get_read_size(); 00150 if (_config.read_size < _read_size) { 00151 _config.read_size = _read_size; 00152 } 00153 _config.prog_size = bd->get_program_size(); 00154 if (_config.prog_size < _prog_size) { 00155 _config.prog_size = _prog_size; 00156 } 00157 _config.block_size = bd->get_erase_size(); 00158 if (_config.block_size < _block_size) { 00159 _config.block_size = _block_size; 00160 } 00161 _config.block_count = bd->size() / _config.block_size; 00162 _config.lookahead = 32 * ((_config.block_count+31)/32); 00163 if (_config.lookahead > _lookahead) { 00164 _config.lookahead = _lookahead; 00165 } 00166 00167 err = lfs_mount(&_lfs, &_config); 00168 LFS_INFO("mount -> %d", lfs_toerror(err)); 00169 _mutex.unlock(); 00170 return lfs_toerror(err); 00171 } 00172 00173 int LittleFileSystem::unmount() 00174 { 00175 _mutex.lock(); 00176 LFS_INFO("unmount(%s)", ""); 00177 if (_bd) { 00178 int err = lfs_unmount(&_lfs); 00179 if (err) { 00180 LFS_INFO("unmount -> %d", lfs_toerror(err)); 00181 _mutex.unlock(); 00182 return lfs_toerror(err); 00183 } 00184 00185 err = _bd->deinit(); 00186 if (err) { 00187 LFS_INFO("unmount -> %d", err); 00188 _mutex.unlock(); 00189 return err; 00190 } 00191 00192 _bd = NULL; 00193 } 00194 00195 LFS_INFO("unmount -> %d", 0); 00196 _mutex.unlock(); 00197 return 0; 00198 } 00199 00200 int LittleFileSystem::format(BlockDevice *bd, 00201 lfs_size_t read_size, lfs_size_t prog_size, 00202 lfs_size_t block_size, lfs_size_t lookahead) { 00203 LFS_INFO("format(%p, %ld, %ld, %ld, %ld)", 00204 bd, read_size, prog_size, block_size, lookahead); 00205 int err = bd->init(); 00206 if (err) { 00207 LFS_INFO("format -> %d", err); 00208 return err; 00209 } 00210 00211 lfs_t _lfs; 00212 struct lfs_config _config; 00213 00214 memset(&_config, 0, sizeof(_config)); 00215 _config.context = bd; 00216 _config.read = lfs_bd_read; 00217 _config.prog = lfs_bd_prog; 00218 _config.erase = lfs_bd_erase; 00219 _config.sync = lfs_bd_sync; 00220 _config.read_size = bd->get_read_size(); 00221 if (_config.read_size < read_size) { 00222 _config.read_size = read_size; 00223 } 00224 _config.prog_size = bd->get_program_size(); 00225 if (_config.prog_size < prog_size) { 00226 _config.prog_size = prog_size; 00227 } 00228 _config.block_size = bd->get_erase_size(); 00229 if (_config.block_size < block_size) { 00230 _config.block_size = block_size; 00231 } 00232 _config.block_count = bd->size() / _config.block_size; 00233 _config.lookahead = 32 * ((_config.block_count+31)/32); 00234 if (_config.lookahead > lookahead) { 00235 _config.lookahead = lookahead; 00236 } 00237 00238 err = lfs_format(&_lfs, &_config); 00239 if (err) { 00240 LFS_INFO("format -> %d", lfs_toerror(err)); 00241 return lfs_toerror(err); 00242 } 00243 00244 err = bd->deinit(); 00245 if (err) { 00246 LFS_INFO("format -> %d", err); 00247 return err; 00248 } 00249 00250 LFS_INFO("format -> %d", 0); 00251 return 0; 00252 } 00253 00254 int LittleFileSystem::reformat(BlockDevice *bd) 00255 { 00256 _mutex.lock(); 00257 LFS_INFO("reformat(%p)", bd); 00258 if (_bd) { 00259 if (!bd) { 00260 bd = _bd; 00261 } 00262 00263 int err = unmount(); 00264 if (err) { 00265 LFS_INFO("reformat -> %d", err); 00266 _mutex.unlock(); 00267 return err; 00268 } 00269 } 00270 00271 if (!bd) { 00272 LFS_INFO("reformat -> %d", -ENODEV); 00273 _mutex.unlock(); 00274 return -ENODEV; 00275 } 00276 00277 int err = LittleFileSystem::format(bd, 00278 _read_size, _prog_size, _block_size, _lookahead); 00279 if (err) { 00280 LFS_INFO("reformat -> %d", err); 00281 _mutex.unlock(); 00282 return err; 00283 } 00284 00285 err = mount(bd); 00286 if (err) { 00287 LFS_INFO("reformat -> %d", err); 00288 _mutex.unlock(); 00289 return err; 00290 } 00291 00292 LFS_INFO("reformat -> %d", 0); 00293 _mutex.unlock(); 00294 return 0; 00295 } 00296 00297 int LittleFileSystem::remove(const char *filename) 00298 { 00299 _mutex.lock(); 00300 LFS_INFO("remove(\"%s\")", filename); 00301 int err = lfs_remove(&_lfs, filename); 00302 LFS_INFO("remove -> %d", lfs_toerror(err)); 00303 _mutex.unlock(); 00304 return lfs_toerror(err); 00305 } 00306 00307 int LittleFileSystem::rename(const char *oldname, const char *newname) 00308 { 00309 _mutex.lock(); 00310 LFS_INFO("rename(\"%s\", \"%s\")", oldname, newname); 00311 int err = lfs_rename(&_lfs, oldname, newname); 00312 LFS_INFO("rename -> %d", lfs_toerror(err)); 00313 _mutex.unlock(); 00314 return lfs_toerror(err); 00315 } 00316 00317 int LittleFileSystem::mkdir(const char *name, mode_t mode) 00318 { 00319 _mutex.lock(); 00320 LFS_INFO("mkdir(\"%s\", 0x%lx)", name, mode); 00321 int err = lfs_mkdir(&_lfs, name); 00322 LFS_INFO("mkdir -> %d", lfs_toerror(err)); 00323 _mutex.unlock(); 00324 return lfs_toerror(err); 00325 } 00326 00327 int LittleFileSystem::stat(const char *name, struct stat *st) 00328 { 00329 struct lfs_info info; 00330 _mutex.lock(); 00331 LFS_INFO("stat(\"%s\", %p)", name, st); 00332 int err = lfs_stat(&_lfs, name, &info); 00333 LFS_INFO("stat -> %d", lfs_toerror(err)); 00334 _mutex.unlock(); 00335 st->st_size = info.size; 00336 st->st_mode = lfs_tomode(info.type); 00337 return lfs_toerror(err); 00338 } 00339 00340 static int lfs_statvfs_count(void *p, lfs_block_t b) 00341 { 00342 *(lfs_size_t *)p += 1; 00343 return 0; 00344 } 00345 00346 int LittleFileSystem::statvfs(const char *name, struct statvfs *st) 00347 { 00348 memset(st, 0, sizeof(struct statvfs)); 00349 00350 lfs_size_t in_use = 0; 00351 _mutex.lock(); 00352 LFS_INFO("statvfs(\"%s\", %p)", name, st); 00353 int err = lfs_traverse(&_lfs, lfs_statvfs_count, &in_use); 00354 LFS_INFO("statvfs -> %d", lfs_toerror(err)); 00355 _mutex.unlock(); 00356 if (err) { 00357 return err; 00358 } 00359 00360 st->f_bsize = _config.block_size; 00361 st->f_frsize = _config.block_size; 00362 st->f_blocks = _config.block_count; 00363 st->f_bfree = _config.block_count - in_use; 00364 st->f_bavail = _config.block_count - in_use; 00365 st->f_namemax = LFS_NAME_MAX; 00366 return 0; 00367 } 00368 00369 ////// File operations ////// 00370 int LittleFileSystem::file_open(fs_file_t *file, const char *path, int flags) 00371 { 00372 lfs_file_t *f = new lfs_file_t; 00373 _mutex.lock(); 00374 LFS_INFO("file_open(%p, \"%s\", 0x%x)", *file, path, flags); 00375 int err = lfs_file_open(&_lfs, f, path, lfs_fromflags(flags)); 00376 LFS_INFO("file_open -> %d", lfs_toerror(err)); 00377 _mutex.unlock(); 00378 if (!err) { 00379 *file = f; 00380 } else { 00381 delete f; 00382 } 00383 return lfs_toerror(err); 00384 } 00385 00386 int LittleFileSystem::file_close(fs_file_t file) 00387 { 00388 lfs_file_t *f = (lfs_file_t *)file; 00389 _mutex.lock(); 00390 LFS_INFO("file_close(%p)", file); 00391 int err = lfs_file_close(&_lfs, f); 00392 LFS_INFO("file_close -> %d", lfs_toerror(err)); 00393 _mutex.unlock(); 00394 delete f; 00395 return lfs_toerror(err); 00396 } 00397 00398 ssize_t LittleFileSystem::file_read(fs_file_t file, void *buffer, size_t len) 00399 { 00400 lfs_file_t *f = (lfs_file_t *)file; 00401 _mutex.lock(); 00402 LFS_INFO("file_read(%p, %p, %d)", file, buffer, len); 00403 lfs_ssize_t res = lfs_file_read(&_lfs, f, buffer, len); 00404 LFS_INFO("file_read -> %d", lfs_toerror(res)); 00405 _mutex.unlock(); 00406 return lfs_toerror(res); 00407 } 00408 00409 ssize_t LittleFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) 00410 { 00411 lfs_file_t *f = (lfs_file_t *)file; 00412 _mutex.lock(); 00413 LFS_INFO("file_write(%p, %p, %d)", file, buffer, len); 00414 lfs_ssize_t res = lfs_file_write(&_lfs, f, buffer, len); 00415 LFS_INFO("file_write -> %d", lfs_toerror(res)); 00416 _mutex.unlock(); 00417 return lfs_toerror(res); 00418 } 00419 00420 int LittleFileSystem::file_sync(fs_file_t file) 00421 { 00422 lfs_file_t *f = (lfs_file_t *)file; 00423 _mutex.lock(); 00424 LFS_INFO("file_sync(%p)", file); 00425 int err = lfs_file_sync(&_lfs, f); 00426 LFS_INFO("file_sync -> %d", lfs_toerror(err)); 00427 _mutex.unlock(); 00428 return lfs_toerror(err); 00429 } 00430 00431 off_t LittleFileSystem::file_seek(fs_file_t file, off_t offset, int whence) 00432 { 00433 lfs_file_t *f = (lfs_file_t *)file; 00434 _mutex.lock(); 00435 LFS_INFO("file_seek(%p, %ld, %d)", file, offset, whence); 00436 off_t res = lfs_file_seek(&_lfs, f, offset, lfs_fromwhence(whence)); 00437 LFS_INFO("file_seek -> %d", lfs_toerror(res)); 00438 _mutex.unlock(); 00439 return lfs_toerror(res); 00440 } 00441 00442 off_t LittleFileSystem::file_tell(fs_file_t file) 00443 { 00444 lfs_file_t *f = (lfs_file_t *)file; 00445 _mutex.lock(); 00446 LFS_INFO("file_tell(%p)", file); 00447 off_t res = lfs_file_tell(&_lfs, f); 00448 LFS_INFO("file_tell -> %d", lfs_toerror(res)); 00449 _mutex.unlock(); 00450 return lfs_toerror(res); 00451 } 00452 00453 off_t LittleFileSystem::file_size(fs_file_t file) 00454 { 00455 lfs_file_t *f = (lfs_file_t *)file; 00456 _mutex.lock(); 00457 LFS_INFO("file_size(%p)", file); 00458 off_t res = lfs_file_size(&_lfs, f); 00459 LFS_INFO("file_size -> %d", lfs_toerror(res)); 00460 _mutex.unlock(); 00461 return lfs_toerror(res); 00462 } 00463 00464 00465 ////// Dir operations ////// 00466 int LittleFileSystem::dir_open(fs_dir_t *dir, const char *path) 00467 { 00468 lfs_dir_t *d = new lfs_dir_t; 00469 _mutex.lock(); 00470 LFS_INFO("dir_open(%p, \"%s\")", *dir, path); 00471 int err = lfs_dir_open(&_lfs, d, path); 00472 LFS_INFO("dir_open -> %d", lfs_toerror(err)); 00473 _mutex.unlock(); 00474 if (!err) { 00475 *dir = d; 00476 } else { 00477 delete d; 00478 } 00479 return lfs_toerror(err); 00480 } 00481 00482 int LittleFileSystem::dir_close(fs_dir_t dir) 00483 { 00484 lfs_dir_t *d = (lfs_dir_t *)dir; 00485 _mutex.lock(); 00486 LFS_INFO("dir_close(%p)", dir); 00487 int err = lfs_dir_close(&_lfs, d); 00488 LFS_INFO("dir_close -> %d", lfs_toerror(err)); 00489 _mutex.unlock(); 00490 delete d; 00491 return lfs_toerror(err); 00492 } 00493 00494 ssize_t LittleFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) 00495 { 00496 lfs_dir_t *d = (lfs_dir_t *)dir; 00497 struct lfs_info info; 00498 _mutex.lock(); 00499 LFS_INFO("dir_read(%p, %p)", dir, ent); 00500 int res = lfs_dir_read(&_lfs, d, &info); 00501 LFS_INFO("dir_read -> %d", lfs_toerror(res)); 00502 _mutex.unlock(); 00503 if (res == 1) { 00504 ent->d_type = lfs_totype(info.type); 00505 strcpy(ent->d_name, info.name); 00506 } 00507 return lfs_toerror(res); 00508 } 00509 00510 void LittleFileSystem::dir_seek(fs_dir_t dir, off_t offset) 00511 { 00512 lfs_dir_t *d = (lfs_dir_t *)dir; 00513 _mutex.lock(); 00514 LFS_INFO("dir_seek(%p, %ld)", dir, offset); 00515 lfs_dir_seek(&_lfs, d, offset); 00516 LFS_INFO("dir_seek -> %s", "void"); 00517 _mutex.unlock(); 00518 } 00519 00520 off_t LittleFileSystem::dir_tell(fs_dir_t dir) 00521 { 00522 lfs_dir_t *d = (lfs_dir_t *)dir; 00523 _mutex.lock(); 00524 LFS_INFO("dir_tell(%p)", dir); 00525 lfs_soff_t res = lfs_dir_tell(&_lfs, d); 00526 LFS_INFO("dir_tell -> %d", lfs_toerror(res)); 00527 _mutex.unlock(); 00528 return lfs_toerror(res); 00529 } 00530 00531 void LittleFileSystem::dir_rewind(fs_dir_t dir) 00532 { 00533 lfs_dir_t *d = (lfs_dir_t *)dir; 00534 _mutex.lock(); 00535 LFS_INFO("dir_rewind(%p)", dir); 00536 lfs_dir_rewind(&_lfs, d); 00537 LFS_INFO("dir_rewind -> %s", "void"); 00538 _mutex.unlock(); 00539 } 00540
Generated on Tue Jul 12 2022 13:24:47 by
1.7.2