EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LittleFileSystem.cpp Source File

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