Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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, (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