Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Haster <chaster@utexas.edu>2020-12-08 05:50:31 +0300
committerGitHub <noreply@github.com>2020-12-08 05:50:31 +0300
commit1a59954ec64ca168828a15242cc6de94ac75f9d1 (patch)
tree98f9b1592ae6870845d314311a8319c2c211b2a9
parent4c9146ea539f72749d6cc3ea076372a81b12cb11 (diff)
parent6a7012774d8bf750f08f13fee43200b9d44df9f3 (diff)
Merge pull request #495 from littlefs-project/develv2.3.0
Minor release: v2.3
-rw-r--r--.travis.yml32
-rw-r--r--README.md6
-rw-r--r--bd/lfs_testbd.c4
-rw-r--r--lfs.c1147
-rw-r--r--lfs.h40
-rwxr-xr-xscripts/readtree.py2
6 files changed, 890 insertions, 341 deletions
diff --git a/.travis.yml b/.travis.yml
index 78d964a..4b59af8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -208,6 +208,38 @@ jobs:
script:
- make test TFLAGS+="-k --valgrind"
+ # test compilation in read-only mode
+ - stage: test
+ env:
+ - NAME=littlefs-readonly
+ - CC="arm-linux-gnueabi-gcc --static -mthumb"
+ - CFLAGS="-Werror -DLFS_READONLY"
+ if: branch !~ -prefix$
+ install:
+ - *install-common
+ - sudo apt-get install
+ gcc-arm-linux-gnueabi
+ libc6-dev-armel-cross
+ - arm-linux-gnueabi-gcc --version
+ # report-size will compile littlefs and report the size
+ script: [*report-size]
+
+ # test compilation in thread-safe mode
+ - stage: test
+ env:
+ - NAME=littlefs-threadsafe
+ - CC="arm-linux-gnueabi-gcc --static -mthumb"
+ - CFLAGS="-Werror -DLFS_THREADSAFE"
+ if: branch !~ -prefix$
+ install:
+ - *install-common
+ - sudo apt-get install
+ gcc-arm-linux-gnueabi
+ libc6-dev-armel-cross
+ - arm-linux-gnueabi-gcc --version
+ # report-size will compile littlefs and report the size
+ script: [*report-size]
+
# self-host with littlefs-fuse for fuzz test
- stage: test
env:
diff --git a/README.md b/README.md
index f900674..a30d43d 100644
--- a/README.md
+++ b/README.md
@@ -221,6 +221,11 @@ License Identifiers that are here available: http://spdx.org/licenses/
- [littlefs-js] - A javascript wrapper for littlefs. I'm not sure why you would
want this, but it is handy for demos. You can see it in action
[here][littlefs-js-demo].
+
+- [littlefs-python] - A Python wrapper for littlefs. The project allows you
+ to create images of the filesystem on your PC. Check if littlefs will fit
+ your needs, create images for a later download to the target memory or
+ inspect the content of a binary image of the target memory.
- [mklfs] - A command line tool built by the [Lua RTOS] guys for making
littlefs images from a host PC. Supports Windows, Mac OS, and Linux.
@@ -250,3 +255,4 @@ License Identifiers that are here available: http://spdx.org/licenses/
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/v5.12/apis/littlefilesystem.html
[SPIFFS]: https://github.com/pellepl/spiffs
[Dhara]: https://github.com/dlbeer/dhara
+[littlefs-python]: https://pypi.org/project/littlefs-python/
diff --git a/bd/lfs_testbd.c b/bd/lfs_testbd.c
index 1ec6fb9..9d3f40c 100644
--- a/bd/lfs_testbd.c
+++ b/bd/lfs_testbd.c
@@ -207,7 +207,7 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
bd->power_cycles -= 1;
if (bd->power_cycles == 0) {
// sync to make sure we persist the last changes
- assert(lfs_testbd_rawsync(cfg) == 0);
+ LFS_ASSERT(lfs_testbd_rawsync(cfg) == 0);
// simulate power loss
exit(33);
}
@@ -254,7 +254,7 @@ int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) {
bd->power_cycles -= 1;
if (bd->power_cycles == 0) {
// sync to make sure we persist the last changes
- assert(lfs_testbd_rawsync(cfg) == 0);
+ LFS_ASSERT(lfs_testbd_rawsync(cfg) == 0);
// simulate power loss
exit(33);
}
diff --git a/lfs.c b/lfs.c
index eb832fa..d7439fe 100644
--- a/lfs.c
+++ b/lfs.c
@@ -118,24 +118,29 @@ static int lfs_bd_cmp(lfs_t *lfs,
lfs_block_t block, lfs_off_t off,
const void *buffer, lfs_size_t size) {
const uint8_t *data = buffer;
+ lfs_size_t diff = 0;
- for (lfs_off_t i = 0; i < size; i++) {
- uint8_t dat;
- int err = lfs_bd_read(lfs,
+ for (lfs_off_t i = 0; i < size; i += diff) {
+ uint8_t dat[8];
+
+ diff = lfs_min(size-i, sizeof(dat));
+ int res = lfs_bd_read(lfs,
pcache, rcache, hint-i,
- block, off+i, &dat, 1);
- if (err) {
- return err;
+ block, off+i, &dat, diff);
+ if (res) {
+ return res;
}
- if (dat != data[i]) {
- return (dat < data[i]) ? LFS_CMP_LT : LFS_CMP_GT;
+ res = memcmp(dat, data + i, diff);
+ if (res) {
+ return res < 0 ? LFS_CMP_LT : LFS_CMP_GT;
}
}
return LFS_CMP_EQ;
}
+#ifndef LFS_READONLY
static int lfs_bd_flush(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {
if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) {
@@ -168,7 +173,9 @@ static int lfs_bd_flush(lfs_t *lfs,
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_bd_sync(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {
lfs_cache_drop(lfs, rcache);
@@ -182,7 +189,9 @@ static int lfs_bd_sync(lfs_t *lfs,
LFS_ASSERT(err <= 0);
return err;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_bd_prog(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate,
lfs_block_t block, lfs_off_t off,
@@ -228,13 +237,16 @@ static int lfs_bd_prog(lfs_t *lfs,
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
LFS_ASSERT(block < lfs->cfg->block_count);
int err = lfs->cfg->erase(lfs->cfg, block);
LFS_ASSERT(err <= 0);
return err;
}
+#endif
/// Small type-level utilities ///
@@ -388,10 +400,12 @@ static void lfs_ctz_fromle32(struct lfs_ctz *ctz) {
ctz->size = lfs_fromle32(ctz->size);
}
+#ifndef LFS_READONLY
static void lfs_ctz_tole32(struct lfs_ctz *ctz) {
ctz->head = lfs_tole32(ctz->head);
ctz->size = lfs_tole32(ctz->size);
}
+#endif
static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) {
superblock->version = lfs_fromle32(superblock->version);
@@ -411,15 +425,46 @@ static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) {
superblock->attr_max = lfs_tole32(superblock->attr_max);
}
+static inline bool lfs_mlist_isopen(struct lfs_mlist *head,
+ struct lfs_mlist *node) {
+ for (struct lfs_mlist **p = &head; *p; p = &(*p)->next) {
+ if (*p == (struct lfs_mlist*)node) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static inline void lfs_mlist_remove(lfs_t *lfs, struct lfs_mlist *mlist) {
+ for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {
+ if (*p == mlist) {
+ *p = (*p)->next;
+ break;
+ }
+ }
+}
+
+static inline void lfs_mlist_append(lfs_t *lfs, struct lfs_mlist *mlist) {
+ mlist->next = lfs->mlist;
+ lfs->mlist = mlist;
+}
+
/// Internal operations predeclared here ///
+#ifndef LFS_READONLY
static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
const struct lfs_mattr *attrs, int attrcount);
static int lfs_dir_compact(lfs_t *lfs,
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t begin, uint16_t end);
+
+static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
+ const void *buffer, lfs_size_t size);
+static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file);
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
+
static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);
static void lfs_fs_prepmove(lfs_t *lfs,
uint16_t id, const lfs_block_t pair[2]);
@@ -429,17 +474,32 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2],
lfs_mdir_t *parent);
static int lfs_fs_relocate(lfs_t *lfs,
const lfs_block_t oldpair[2], lfs_block_t newpair[2]);
-int lfs_fs_traverseraw(lfs_t *lfs,
- int (*cb)(void *data, lfs_block_t block), void *data,
- bool includeorphans);
static int lfs_fs_forceconsistency(lfs_t *lfs);
-static int lfs_deinit(lfs_t *lfs);
+#endif
+
#ifdef LFS_MIGRATE
static int lfs1_traverse(lfs_t *lfs,
int (*cb)(void*, lfs_block_t), void *data);
#endif
+static int lfs_dir_rawrewind(lfs_t *lfs, lfs_dir_t *dir);
+
+static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
+ void *buffer, lfs_size_t size);
+static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file);
+static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file);
+
+static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs);
+static int lfs_fs_rawtraverse(lfs_t *lfs,
+ int (*cb)(void *data, lfs_block_t block), void *data,
+ bool includeorphans);
+
+static int lfs_deinit(lfs_t *lfs);
+static int lfs_rawunmount(lfs_t *lfs);
+
+
/// Block allocator ///
+#ifndef LFS_READONLY
static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
lfs_t *lfs = (lfs_t*)p;
lfs_block_t off = ((block - lfs->free.off)
@@ -451,20 +511,24 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
return 0;
}
+#endif
+// indicate allocated blocks have been committed into the filesystem, this
+// is to prevent blocks from being garbage collected in the middle of a
+// commit operation
static void lfs_alloc_ack(lfs_t *lfs) {
lfs->free.ack = lfs->cfg->block_count;
}
-// Invalidate the lookahead buffer. This is done during mounting and
-// failed traversals
-static void lfs_alloc_reset(lfs_t *lfs) {
- lfs->free.off = lfs->seed % lfs->cfg->block_size;
+// drop the lookahead buffer, this is done during mounting and failed
+// traversals in order to avoid invalid lookahead state
+static void lfs_alloc_drop(lfs_t *lfs) {
lfs->free.size = 0;
lfs->free.i = 0;
lfs_alloc_ack(lfs);
}
+#ifndef LFS_READONLY
static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
while (true) {
while (lfs->free.i != lfs->free.size) {
@@ -503,13 +567,14 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
// find mask of free blocks from tree
memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
- int err = lfs_fs_traverseraw(lfs, lfs_alloc_lookahead, lfs, true);
+ int err = lfs_fs_rawtraverse(lfs, lfs_alloc_lookahead, lfs, true);
if (err) {
- lfs_alloc_reset(lfs);
+ lfs_alloc_drop(lfs);
return err;
}
}
}
+#endif
/// Metadata pair and directory operations ///
static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,
@@ -642,6 +707,7 @@ static int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir,
return 0;
}
+#ifndef LFS_READONLY
static int lfs_dir_traverse_filter(void *p,
lfs_tag_t tag, const void *buffer) {
lfs_tag_t *filtertag = p;
@@ -669,7 +735,9 @@ static int lfs_dir_traverse_filter(void *p,
return false;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_traverse(lfs_t *lfs,
const lfs_mdir_t *dir, lfs_off_t off, lfs_tag_t ptag,
const struct lfs_mattr *attrs, int attrcount,
@@ -763,6 +831,7 @@ static int lfs_dir_traverse(lfs_t *lfs,
}
}
}
+#endif
static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
lfs_mdir_t *dir, const lfs_block_t pair[2],
@@ -870,8 +939,10 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
ptag ^= (lfs_tag_t)(lfs_tag_chunk(tag) & 1U) << 31;
// toss our crc into the filesystem seed for
- // pseudorandom numbers
- lfs->seed ^= crc;
+ // pseudorandom numbers, note we use another crc here
+ // as a collection function because it is sufficiently
+ // random and convenient
+ lfs->seed = lfs_crc(lfs->seed, &crc, sizeof(crc));
// update with what's found so far
besttag = tempbesttag;
@@ -1200,6 +1271,7 @@ struct lfs_commit {
lfs_off_t end;
};
+#ifndef LFS_READONLY
static int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit,
const void *buffer, lfs_size_t size) {
int err = lfs_bd_prog(lfs,
@@ -1214,7 +1286,9 @@ static int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit,
commit->off += size;
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit,
lfs_tag_t tag, const void *buffer) {
// check if we fit
@@ -1259,14 +1333,17 @@ static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit,
commit->ptag = tag & 0x7fffffff;
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
- const lfs_off_t off1 = commit->off;
- const uint32_t crc1 = commit->crc;
// align to program units
- const lfs_off_t end = lfs_alignup(off1 + 2*sizeof(uint32_t),
+ const lfs_off_t end = lfs_alignup(commit->off + 2*sizeof(uint32_t),
lfs->cfg->prog_size);
+ lfs_off_t off1 = 0;
+ uint32_t crc1 = 0;
+
// create crc tags to fill up remainder of commit, note that
// padding is not crced, which lets fetches skip padding but
// makes committing a bit more complicated
@@ -1302,6 +1379,12 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
return err;
}
+ // keep track of non-padding checksum to verify
+ if (off1 == 0) {
+ off1 = commit->off + sizeof(uint32_t);
+ crc1 = commit->crc;
+ }
+
commit->off += sizeof(tag)+lfs_tag_size(tag);
commit->ptag = tag ^ ((lfs_tag_t)reset << 31);
commit->crc = 0xffffffff; // reset crc for next "commit"
@@ -1315,7 +1398,7 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
// successful commit, check checksums to make sure
lfs_off_t off = commit->begin;
- lfs_off_t noff = off1 + sizeof(uint32_t);
+ lfs_off_t noff = off1;
while (off < end) {
uint32_t crc = 0xffffffff;
for (lfs_off_t i = off; i < noff+sizeof(uint32_t); i++) {
@@ -1352,7 +1435,9 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
// allocate pair of dir blocks (backwards, so we write block 1 first)
for (int i = 0; i < 2; i++) {
@@ -1375,8 +1460,12 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
return err;
}
- // make sure we don't immediately evict
- dir->rev += dir->rev & 1;
+ // to make sure we don't immediately evict, align the new revision count
+ // to our block_cycles modulus, see lfs_dir_compact for why our modulus
+ // is tweaked this way
+ if (lfs->cfg->block_cycles > 0) {
+ dir->rev = lfs_alignup(dir->rev, ((lfs->cfg->block_cycles+1)|1));
+ }
// set defaults
dir->off = sizeof(dir->rev);
@@ -1390,7 +1479,9 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
// don't write out yet, let caller take care of that
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) {
// steal state
int err = lfs_dir_getgstate(lfs, tail, &lfs->gdelta);
@@ -1409,7 +1500,9 @@ static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) {
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_split(lfs_t *lfs,
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t split, uint16_t end) {
@@ -1442,7 +1535,9 @@ static int lfs_dir_split(lfs_t *lfs,
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) {
lfs_size_t *size = p;
(void)buffer;
@@ -1450,17 +1545,23 @@ static int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) {
*size += lfs_tag_dsize(tag);
return 0;
}
+#endif
+#ifndef LFS_READONLY
struct lfs_dir_commit_commit {
lfs_t *lfs;
struct lfs_commit *commit;
};
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_commit_commit(void *p, lfs_tag_t tag, const void *buffer) {
struct lfs_dir_commit_commit *commit = p;
return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer);
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_compact(lfs_t *lfs,
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t begin, uint16_t end) {
@@ -1525,7 +1626,7 @@ static int lfs_dir_compact(lfs_t *lfs,
if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
// oh no! we're writing too much to the superblock,
// should we expand?
- lfs_ssize_t res = lfs_fs_size(lfs);
+ lfs_ssize_t res = lfs_fs_rawsize(lfs);
if (res < 0) {
return res;
}
@@ -1715,7 +1816,9 @@ relocate:
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
const struct lfs_mattr *attrs, int attrcount) {
// check for any inline files that aren't RAM backed and
@@ -1903,15 +2006,15 @@ compact:
return 0;
}
+#endif
/// Top level directory operations ///
-int lfs_mkdir(lfs_t *lfs, const char *path) {
- LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path);
+#ifndef LFS_READONLY
+static int lfs_rawmkdir(lfs_t *lfs, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs_fs_forceconsistency(lfs);
if (err) {
- LFS_TRACE("lfs_mkdir -> %d", err);
return err;
}
@@ -1920,14 +2023,12 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
uint16_t id;
err = lfs_dir_find(lfs, &cwd.m, &path, &id);
if (!(err == LFS_ERR_NOENT && id != 0x3ff)) {
- LFS_TRACE("lfs_mkdir -> %d", (err < 0) ? err : LFS_ERR_EXIST);
return (err < 0) ? err : LFS_ERR_EXIST;
}
// check that name fits
lfs_size_t nlen = strlen(path);
if (nlen > lfs->name_max) {
- LFS_TRACE("lfs_mkdir -> %d", LFS_ERR_NAMETOOLONG);
return LFS_ERR_NAMETOOLONG;
}
@@ -1936,7 +2037,6 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
lfs_mdir_t dir;
err = lfs_dir_alloc(lfs, &dir);
if (err) {
- LFS_TRACE("lfs_mkdir -> %d", err);
return err;
}
@@ -1945,7 +2045,6 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
while (pred.split) {
err = lfs_dir_fetch(lfs, &pred, pred.tail);
if (err) {
- LFS_TRACE("lfs_mkdir -> %d", err);
return err;
}
}
@@ -1956,7 +2055,6 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
{LFS_MKTAG(LFS_TYPE_SOFTTAIL, 0x3ff, 8), pred.tail}));
lfs_pair_fromle32(pred.tail);
if (err) {
- LFS_TRACE("lfs_mkdir -> %d", err);
return err;
}
@@ -1979,7 +2077,6 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
lfs_pair_fromle32(dir.pair);
if (err) {
lfs->mlist = cwd.next;
- LFS_TRACE("lfs_mkdir -> %d", err);
return err;
}
@@ -1997,24 +2094,20 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
LFS_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair}));
lfs_pair_fromle32(dir.pair);
if (err) {
- LFS_TRACE("lfs_mkdir -> %d", err);
return err;
}
- LFS_TRACE("lfs_mkdir -> %d", 0);
return 0;
}
+#endif
-int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
- LFS_TRACE("lfs_dir_open(%p, %p, \"%s\")", (void*)lfs, (void*)dir, path);
+static int lfs_dir_rawopen(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL);
if (tag < 0) {
- LFS_TRACE("lfs_dir_open -> %"PRId32, tag);
return tag;
}
if (lfs_tag_type3(tag) != LFS_TYPE_DIR) {
- LFS_TRACE("lfs_dir_open -> %d", LFS_ERR_NOTDIR);
return LFS_ERR_NOTDIR;
}
@@ -2028,7 +2121,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
lfs_stag_t res = lfs_dir_get(lfs, &dir->m, LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);
if (res < 0) {
- LFS_TRACE("lfs_dir_open -> %"PRId32, res);
return res;
}
lfs_pair_fromle32(pair);
@@ -2037,7 +2129,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
// fetch first pair
int err = lfs_dir_fetch(lfs, &dir->m, pair);
if (err) {
- LFS_TRACE("lfs_dir_open -> %d", err);
return err;
}
@@ -2049,30 +2140,19 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
// add to list of mdirs
dir->type = LFS_TYPE_DIR;
- dir->next = (lfs_dir_t*)lfs->mlist;
- lfs->mlist = (struct lfs_mlist*)dir;
+ lfs_mlist_append(lfs, (struct lfs_mlist *)dir);
- LFS_TRACE("lfs_dir_open -> %d", 0);
return 0;
}
-int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
- LFS_TRACE("lfs_dir_close(%p, %p)", (void*)lfs, (void*)dir);
+static int lfs_dir_rawclose(lfs_t *lfs, lfs_dir_t *dir) {
// remove from list of mdirs
- for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {
- if (*p == (struct lfs_mlist*)dir) {
- *p = (*p)->next;
- break;
- }
- }
+ lfs_mlist_remove(lfs, (struct lfs_mlist *)dir);
- LFS_TRACE("lfs_dir_close -> %d", 0);
return 0;
}
-int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
- LFS_TRACE("lfs_dir_read(%p, %p, %p)",
- (void*)lfs, (void*)dir, (void*)info);
+static int lfs_dir_rawread(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
memset(info, 0, sizeof(*info));
// special offset for '.' and '..'
@@ -2080,26 +2160,22 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
info->type = LFS_TYPE_DIR;
strcpy(info->name, ".");
dir->pos += 1;
- LFS_TRACE("lfs_dir_read -> %d", true);
return true;
} else if (dir->pos == 1) {
info->type = LFS_TYPE_DIR;
strcpy(info->name, "..");
dir->pos += 1;
- LFS_TRACE("lfs_dir_read -> %d", true);
return true;
}
while (true) {
if (dir->id == dir->m.count) {
if (!dir->m.split) {
- LFS_TRACE("lfs_dir_read -> %d", false);
return false;
}
int err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail);
if (err) {
- LFS_TRACE("lfs_dir_read -> %d", err);
return err;
}
@@ -2108,7 +2184,6 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
int err = lfs_dir_getinfo(lfs, &dir->m, dir->id, info);
if (err && err != LFS_ERR_NOENT) {
- LFS_TRACE("lfs_dir_read -> %d", err);
return err;
}
@@ -2119,17 +2194,13 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
}
dir->pos += 1;
- LFS_TRACE("lfs_dir_read -> %d", true);
return true;
}
-int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
- LFS_TRACE("lfs_dir_seek(%p, %p, %"PRIu32")",
- (void*)lfs, (void*)dir, off);
+static int lfs_dir_rawseek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
// simply walk from head dir
- int err = lfs_dir_rewind(lfs, dir);
+ int err = lfs_dir_rawrewind(lfs, dir);
if (err) {
- LFS_TRACE("lfs_dir_seek -> %d", err);
return err;
}
@@ -2148,13 +2219,11 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
if (dir->id == dir->m.count) {
if (!dir->m.split) {
- LFS_TRACE("lfs_dir_seek -> %d", LFS_ERR_INVAL);
return LFS_ERR_INVAL;
}
err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail);
if (err) {
- LFS_TRACE("lfs_dir_seek -> %d", err);
return err;
}
@@ -2162,29 +2231,23 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
}
}
- LFS_TRACE("lfs_dir_seek -> %d", 0);
return 0;
}
-lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) {
- LFS_TRACE("lfs_dir_tell(%p, %p)", (void*)lfs, (void*)dir);
+static lfs_soff_t lfs_dir_rawtell(lfs_t *lfs, lfs_dir_t *dir) {
(void)lfs;
- LFS_TRACE("lfs_dir_tell -> %"PRId32, dir->pos);
return dir->pos;
}
-int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
- LFS_TRACE("lfs_dir_rewind(%p, %p)", (void*)lfs, (void*)dir);
+static int lfs_dir_rawrewind(lfs_t *lfs, lfs_dir_t *dir) {
// reload the head dir
int err = lfs_dir_fetch(lfs, &dir->m, dir->head);
if (err) {
- LFS_TRACE("lfs_dir_rewind -> %d", err);
return err;
}
dir->id = 0;
dir->pos = 0;
- LFS_TRACE("lfs_dir_rewind -> %d", 0);
return 0;
}
@@ -2237,6 +2300,7 @@ static int lfs_ctz_find(lfs_t *lfs,
return 0;
}
+#ifndef LFS_READONLY
static int lfs_ctz_extend(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache,
lfs_block_t head, lfs_size_t size,
@@ -2334,6 +2398,7 @@ relocate:
lfs_cache_drop(lfs, pcache);
}
}
+#endif
static int lfs_ctz_traverse(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_cache_t *rcache,
@@ -2380,27 +2445,25 @@ static int lfs_ctz_traverse(lfs_t *lfs,
/// Top level file operations ///
-int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
+static int lfs_file_rawopencfg(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags,
const struct lfs_file_config *cfg) {
- LFS_TRACE("lfs_file_opencfg(%p, %p, \"%s\", %x, %p {"
- ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
- (void*)lfs, (void*)file, path, flags,
- (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
-
+#ifndef LFS_READONLY
// deorphan if we haven't yet, needed at most once after poweron
- if ((flags & 3) != LFS_O_RDONLY) {
+ if ((flags & LFS_O_WRONLY) == LFS_O_WRONLY) {
int err = lfs_fs_forceconsistency(lfs);
if (err) {
- LFS_TRACE("lfs_file_opencfg -> %d", err);
return err;
}
}
+#else
+ LFS_ASSERT((flags & LFS_O_RDONLY) == LFS_O_RDONLY);
+#endif
// setup simple file details
int err;
file->cfg = cfg;
- file->flags = flags | LFS_F_OPENED;
+ file->flags = flags;
file->pos = 0;
file->off = 0;
file->cache.buffer = NULL;
@@ -2414,9 +2477,13 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
// get id, add to list of mdirs to catch update changes
file->type = LFS_TYPE_REG;
- file->next = (lfs_file_t*)lfs->mlist;
- lfs->mlist = (struct lfs_mlist*)file;
+ lfs_mlist_append(lfs, (struct lfs_mlist *)file);
+#ifdef LFS_READONLY
+ if (tag == LFS_ERR_NOENT) {
+ err = LFS_ERR_NOENT;
+ goto cleanup;
+#else
if (tag == LFS_ERR_NOENT) {
if (!(flags & LFS_O_CREAT)) {
err = LFS_ERR_NOENT;
@@ -2444,13 +2511,16 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
} else if (flags & LFS_O_EXCL) {
err = LFS_ERR_EXIST;
goto cleanup;
+#endif
} else if (lfs_tag_type3(tag) != LFS_TYPE_REG) {
err = LFS_ERR_ISDIR;
goto cleanup;
+#ifndef LFS_READONLY
} else if (flags & LFS_O_TRUNC) {
// truncate if requested
tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0);
file->flags |= LFS_F_DIRTY;
+#endif
} else {
// try to load what's on disk, if it's inlined we'll fix it later
tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0),
@@ -2464,7 +2534,8 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
// fetch attrs
for (unsigned i = 0; i < file->cfg->attr_count; i++) {
- if ((file->flags & 3) != LFS_O_WRONLY) {
+ // if opened for read / read-write operations
+ if ((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY) {
lfs_stag_t res = lfs_dir_get(lfs, &file->m,
LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_USERATTR + file->cfg->attrs[i].type,
@@ -2476,7 +2547,9 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
}
}
- if ((file->flags & 3) != LFS_O_RDONLY) {
+#ifndef LFS_READONLY
+ // if opened for write / read-write operations
+ if ((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY) {
if (file->cfg->attrs[i].size > lfs->attr_max) {
err = LFS_ERR_NOSPC;
goto cleanup;
@@ -2484,6 +2557,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
file->flags |= LFS_F_DIRTY;
}
+#endif
}
// allocate buffer if needed
@@ -2523,54 +2597,45 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
}
}
- LFS_TRACE("lfs_file_opencfg -> %d", 0);
return 0;
cleanup:
// clean up lingering resources
+#ifndef LFS_READONLY
file->flags |= LFS_F_ERRED;
- lfs_file_close(lfs, file);
- LFS_TRACE("lfs_file_opencfg -> %d", err);
+#endif
+ lfs_file_rawclose(lfs, file);
return err;
}
-int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
+static int lfs_file_rawopen(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags) {
- LFS_TRACE("lfs_file_open(%p, %p, \"%s\", %x)",
- (void*)lfs, (void*)file, path, flags);
static const struct lfs_file_config defaults = {0};
- int err = lfs_file_opencfg(lfs, file, path, flags, &defaults);
- LFS_TRACE("lfs_file_open -> %d", err);
+ int err = lfs_file_rawopencfg(lfs, file, path, flags, &defaults);
return err;
}
-int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
- LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
-
- int err = lfs_file_sync(lfs, file);
+static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file) {
+#ifndef LFS_READONLY
+ int err = lfs_file_rawsync(lfs, file);
+#else
+ int err = 0;
+#endif
// remove from list of mdirs
- for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {
- if (*p == (struct lfs_mlist*)file) {
- *p = (*p)->next;
- break;
- }
- }
+ lfs_mlist_remove(lfs, (struct lfs_mlist*)file);
// clean up memory
if (!file->cfg->buffer) {
lfs_free(file->cache.buffer);
}
- file->flags &= ~LFS_F_OPENED;
- LFS_TRACE("lfs_file_close -> %d", err);
return err;
}
-static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
- LFS_ASSERT(file->flags & LFS_F_OPENED);
+#ifndef LFS_READONLY
+static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
while (true) {
// just relocate what exists into new block
lfs_block_t nblock;
@@ -2638,7 +2703,9 @@ relocate:
lfs_cache_drop(lfs, &lfs->pcache);
}
}
+#endif
+#ifndef LFS_READONLY
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
file->off = file->pos;
lfs_alloc_ack(lfs);
@@ -2650,10 +2717,10 @@ static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
file->flags &= ~LFS_F_INLINE;
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
- LFS_ASSERT(file->flags & LFS_F_OPENED);
-
if (file->flags & LFS_F_READING) {
if (!(file->flags & LFS_F_INLINE)) {
lfs_cache_drop(lfs, &file->cache);
@@ -2669,7 +2736,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
lfs_file_t orig = {
.ctz.head = file->ctz.head,
.ctz.size = file->ctz.size,
- .flags = LFS_O_RDONLY | LFS_F_OPENED,
+ .flags = LFS_O_RDONLY,
.pos = file->pos,
.cache = lfs->rcache,
};
@@ -2679,12 +2746,12 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
// copy over a byte at a time, leave it up to caching
// to make this efficient
uint8_t data;
- lfs_ssize_t res = lfs_file_read(lfs, &orig, &data, 1);
+ lfs_ssize_t res = lfs_file_rawread(lfs, &orig, &data, 1);
if (res < 0) {
return res;
}
- res = lfs_file_write(lfs, file, &data, 1);
+ res = lfs_file_rawwrite(lfs, file, &data, 1);
if (res < 0) {
return res;
}
@@ -2730,24 +2797,22 @@ relocate:
return 0;
}
+#endif
-int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
- LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
-
+#ifndef LFS_READONLY
+static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) {
if (file->flags & LFS_F_ERRED) {
// it's not safe to do anything if our file errored
- LFS_TRACE("lfs_file_sync -> %d", 0);
return 0;
}
int err = lfs_file_flush(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_sync -> %d", err);
return err;
}
+
if ((file->flags & LFS_F_DIRTY) &&
!lfs_pair_isnull(file->m.pair)) {
// update dir entry
@@ -2777,39 +2842,35 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
file->cfg->attr_count), file->cfg->attrs}));
if (err) {
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_sync -> %d", err);
return err;
}
file->flags &= ~LFS_F_DIRTY;
}
- LFS_TRACE("lfs_file_sync -> %d", 0);
return 0;
}
+#endif
-lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
+static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
void *buffer, lfs_size_t size) {
- LFS_TRACE("lfs_file_read(%p, %p, %p, %"PRIu32")",
- (void*)lfs, (void*)file, buffer, size);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
- LFS_ASSERT((file->flags & 3) != LFS_O_WRONLY);
+ LFS_ASSERT((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY);
uint8_t *data = buffer;
lfs_size_t nsize = size;
+#ifndef LFS_READONLY
if (file->flags & LFS_F_WRITING) {
// flush out any writes
int err = lfs_file_flush(lfs, file);
if (err) {
- LFS_TRACE("lfs_file_read -> %d", err);
return err;
}
}
+#endif
if (file->pos >= file->ctz.size) {
// eof if past end
- LFS_TRACE("lfs_file_read -> %d", 0);
return 0;
}
@@ -2825,7 +2886,6 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
file->ctz.head, file->ctz.size,
file->pos, &file->block, &file->off);
if (err) {
- LFS_TRACE("lfs_file_read -> %d", err);
return err;
}
} else {
@@ -2845,7 +2905,6 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0),
file->off, data, diff);
if (err) {
- LFS_TRACE("lfs_file_read -> %d", err);
return err;
}
} else {
@@ -2853,7 +2912,6 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
NULL, &file->cache, lfs->cfg->block_size,
file->block, file->off, data, diff);
if (err) {
- LFS_TRACE("lfs_file_read -> %d", err);
return err;
}
}
@@ -2864,16 +2922,13 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
nsize -= diff;
}
- LFS_TRACE("lfs_file_read -> %"PRId32, size);
return size;
}
-lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
+#ifndef LFS_READONLY
+static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size) {
- LFS_TRACE("lfs_file_write(%p, %p, %p, %"PRIu32")",
- (void*)lfs, (void*)file, buffer, size);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
- LFS_ASSERT((file->flags & 3) != LFS_O_RDONLY);
+ LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
const uint8_t *data = buffer;
lfs_size_t nsize = size;
@@ -2882,7 +2937,6 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
// drop any reads
int err = lfs_file_flush(lfs, file);
if (err) {
- LFS_TRACE("lfs_file_write -> %d", err);
return err;
}
}
@@ -2893,7 +2947,6 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
if (file->pos + size > lfs->file_max) {
// Larger than file limit?
- LFS_TRACE("lfs_file_write -> %d", LFS_ERR_FBIG);
return LFS_ERR_FBIG;
}
@@ -2903,9 +2956,8 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
file->pos = file->ctz.size;
while (file->pos < pos) {
- lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1);
+ lfs_ssize_t res = lfs_file_rawwrite(lfs, file, &(uint8_t){0}, 1);
if (res < 0) {
- LFS_TRACE("lfs_file_write -> %"PRId32, res);
return res;
}
}
@@ -2919,7 +2971,6 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
int err = lfs_file_outline(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_write -> %d", err);
return err;
}
}
@@ -2936,7 +2987,6 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
file->pos-1, &file->block, &file->off);
if (err) {
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_write -> %d", err);
return err;
}
@@ -2951,7 +3001,6 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
&file->block, &file->off);
if (err) {
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_write -> %d", err);
return err;
}
} else {
@@ -2972,7 +3021,6 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
goto relocate;
}
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_write -> %d", err);
return err;
}
@@ -2981,7 +3029,6 @@ relocate:
err = lfs_file_relocate(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
- LFS_TRACE("lfs_file_write -> %d", err);
return err;
}
}
@@ -2995,22 +3042,19 @@ relocate:
}
file->flags &= ~LFS_F_ERRED;
- LFS_TRACE("lfs_file_write -> %"PRId32, size);
return size;
}
+#endif
-lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
+static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t off, int whence) {
- LFS_TRACE("lfs_file_seek(%p, %p, %"PRId32", %d)",
- (void*)lfs, (void*)file, off, whence);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
-
+#ifndef LFS_READONLY
// write out everything beforehand, may be noop if rdonly
int err = lfs_file_flush(lfs, file);
if (err) {
- LFS_TRACE("lfs_file_seek -> %d", err);
return err;
}
+#endif
// find new pos
lfs_off_t npos = file->pos;
@@ -3024,34 +3068,28 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
if (npos > lfs->file_max) {
// file position out of range
- LFS_TRACE("lfs_file_seek -> %d", LFS_ERR_INVAL);
return LFS_ERR_INVAL;
}
// update pos
file->pos = npos;
- LFS_TRACE("lfs_file_seek -> %"PRId32, npos);
return npos;
}
-int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
- LFS_TRACE("lfs_file_truncate(%p, %p, %"PRIu32")",
- (void*)lfs, (void*)file, size);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
- LFS_ASSERT((file->flags & 3) != LFS_O_RDONLY);
+#ifndef LFS_READONLY
+static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
+ LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
if (size > LFS_FILE_MAX) {
- LFS_TRACE("lfs_file_truncate -> %d", LFS_ERR_INVAL);
return LFS_ERR_INVAL;
}
lfs_off_t pos = file->pos;
- lfs_off_t oldsize = lfs_file_size(lfs, file);
+ lfs_off_t oldsize = lfs_file_rawsize(lfs, file);
if (size < oldsize) {
// need to flush since directly changing metadata
int err = lfs_file_flush(lfs, file);
if (err) {
- LFS_TRACE("lfs_file_truncate -> %d", err);
return err;
}
@@ -3060,7 +3098,6 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
file->ctz.head, file->ctz.size,
size, &file->block, &file->off);
if (err) {
- LFS_TRACE("lfs_file_truncate -> %d", err);
return err;
}
@@ -3070,97 +3107,80 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
} else if (size > oldsize) {
// flush+seek if not already at end
if (file->pos != oldsize) {
- lfs_soff_t res = lfs_file_seek(lfs, file, 0, LFS_SEEK_END);
+ lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_END);
if (res < 0) {
- LFS_TRACE("lfs_file_truncate -> %"PRId32, res);
return (int)res;
}
}
// fill with zeros
while (file->pos < size) {
- lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1);
+ lfs_ssize_t res = lfs_file_rawwrite(lfs, file, &(uint8_t){0}, 1);
if (res < 0) {
- LFS_TRACE("lfs_file_truncate -> %"PRId32, res);
return (int)res;
}
}
}
// restore pos
- lfs_soff_t res = lfs_file_seek(lfs, file, pos, LFS_SEEK_SET);
+ lfs_soff_t res = lfs_file_rawseek(lfs, file, pos, LFS_SEEK_SET);
if (res < 0) {
- LFS_TRACE("lfs_file_truncate -> %"PRId32, res);
return (int)res;
}
- LFS_TRACE("lfs_file_truncate -> %d", 0);
return 0;
}
+#endif
-lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
- LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
+static lfs_soff_t lfs_file_rawtell(lfs_t *lfs, lfs_file_t *file) {
(void)lfs;
- LFS_TRACE("lfs_file_tell -> %"PRId32, file->pos);
return file->pos;
}
-int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
- LFS_TRACE("lfs_file_rewind(%p, %p)", (void*)lfs, (void*)file);
- lfs_soff_t res = lfs_file_seek(lfs, file, 0, LFS_SEEK_SET);
+static int lfs_file_rawrewind(lfs_t *lfs, lfs_file_t *file) {
+ lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
if (res < 0) {
- LFS_TRACE("lfs_file_rewind -> %"PRId32, res);
return (int)res;
}
- LFS_TRACE("lfs_file_rewind -> %d", 0);
return 0;
}
-lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
- LFS_TRACE("lfs_file_size(%p, %p)", (void*)lfs, (void*)file);
- LFS_ASSERT(file->flags & LFS_F_OPENED);
+static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file) {
(void)lfs;
+
+#ifndef LFS_READONLY
if (file->flags & LFS_F_WRITING) {
- LFS_TRACE("lfs_file_size -> %"PRId32,
- lfs_max(file->pos, file->ctz.size));
return lfs_max(file->pos, file->ctz.size);
- } else {
- LFS_TRACE("lfs_file_size -> %"PRId32, file->ctz.size);
- return file->ctz.size;
}
+#endif
+
+ return file->ctz.size;
}
/// General fs operations ///
-int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
- LFS_TRACE("lfs_stat(%p, \"%s\", %p)", (void*)lfs, path, (void*)info);
+static int lfs_rawstat(lfs_t *lfs, const char *path, struct lfs_info *info) {
lfs_mdir_t cwd;
lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
if (tag < 0) {
- LFS_TRACE("lfs_stat -> %"PRId32, tag);
return (int)tag;
}
- int err = lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info);
- LFS_TRACE("lfs_stat -> %d", err);
- return err;
+ return lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info);
}
-int lfs_remove(lfs_t *lfs, const char *path) {
- LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path);
+#ifndef LFS_READONLY
+static int lfs_rawremove(lfs_t *lfs, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs_fs_forceconsistency(lfs);
if (err) {
- LFS_TRACE("lfs_remove -> %d", err);
return err;
}
lfs_mdir_t cwd;
lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
if (tag < 0 || lfs_tag_id(tag) == 0x3ff) {
- LFS_TRACE("lfs_remove -> %"PRId32, (tag < 0) ? tag : LFS_ERR_INVAL);
return (tag < 0) ? (int)tag : LFS_ERR_INVAL;
}
@@ -3172,19 +3192,16 @@ int lfs_remove(lfs_t *lfs, const char *path) {
lfs_stag_t res = lfs_dir_get(lfs, &cwd, LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);
if (res < 0) {
- LFS_TRACE("lfs_remove -> %"PRId32, res);
return (int)res;
}
lfs_pair_fromle32(pair);
err = lfs_dir_fetch(lfs, &dir.m, pair);
if (err) {
- LFS_TRACE("lfs_remove -> %d", err);
return err;
}
if (dir.m.count > 0 || dir.m.split) {
- LFS_TRACE("lfs_remove -> %d", LFS_ERR_NOTEMPTY);
return LFS_ERR_NOTEMPTY;
}
@@ -3203,7 +3220,6 @@ int lfs_remove(lfs_t *lfs, const char *path) {
{LFS_MKTAG(LFS_TYPE_DELETE, lfs_tag_id(tag), 0), NULL}));
if (err) {
lfs->mlist = dir.next;
- LFS_TRACE("lfs_remove -> %d", err);
return err;
}
@@ -3214,28 +3230,24 @@ int lfs_remove(lfs_t *lfs, const char *path) {
err = lfs_fs_pred(lfs, dir.m.pair, &cwd);
if (err) {
- LFS_TRACE("lfs_remove -> %d", err);
return err;
}
err = lfs_dir_drop(lfs, &cwd, &dir.m);
if (err) {
- LFS_TRACE("lfs_remove -> %d", err);
return err;
}
}
- LFS_TRACE("lfs_remove -> %d", 0);
return 0;
}
+#endif
-int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
- LFS_TRACE("lfs_rename(%p, \"%s\", \"%s\")", (void*)lfs, oldpath, newpath);
-
+#ifndef LFS_READONLY
+static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs_fs_forceconsistency(lfs);
if (err) {
- LFS_TRACE("lfs_rename -> %d", err);
return err;
}
@@ -3243,8 +3255,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
lfs_mdir_t oldcwd;
lfs_stag_t oldtag = lfs_dir_find(lfs, &oldcwd, &oldpath, NULL);
if (oldtag < 0 || lfs_tag_id(oldtag) == 0x3ff) {
- LFS_TRACE("lfs_rename -> %"PRId32,
- (oldtag < 0) ? oldtag : LFS_ERR_INVAL);
return (oldtag < 0) ? (int)oldtag : LFS_ERR_INVAL;
}
@@ -3254,8 +3264,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
lfs_stag_t prevtag = lfs_dir_find(lfs, &newcwd, &newpath, &newid);
if ((prevtag < 0 || lfs_tag_id(prevtag) == 0x3ff) &&
!(prevtag == LFS_ERR_NOENT && newid != 0x3ff)) {
- LFS_TRACE("lfs_rename -> %"PRId32,
- (prevtag < 0) ? prevtag : LFS_ERR_INVAL);
return (prevtag < 0) ? (int)prevtag : LFS_ERR_INVAL;
}
@@ -3269,7 +3277,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
// check that name fits
lfs_size_t nlen = strlen(newpath);
if (nlen > lfs->name_max) {
- LFS_TRACE("lfs_rename -> %d", LFS_ERR_NAMETOOLONG);
return LFS_ERR_NAMETOOLONG;
}
@@ -3280,11 +3287,9 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
newoldid += 1;
}
} else if (lfs_tag_type3(prevtag) != lfs_tag_type3(oldtag)) {
- LFS_TRACE("lfs_rename -> %d", LFS_ERR_ISDIR);
return LFS_ERR_ISDIR;
} else if (samepair && newid == newoldid) {
// we're renaming to ourselves??
- LFS_TRACE("lfs_rename -> %d", 0);
return 0;
} else if (lfs_tag_type3(prevtag) == LFS_TYPE_DIR) {
// must be empty before removal
@@ -3292,7 +3297,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
lfs_stag_t res = lfs_dir_get(lfs, &newcwd, LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), prevpair);
if (res < 0) {
- LFS_TRACE("lfs_rename -> %"PRId32, res);
return (int)res;
}
lfs_pair_fromle32(prevpair);
@@ -3300,12 +3304,10 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
// must be empty before removal
err = lfs_dir_fetch(lfs, &prevdir.m, prevpair);
if (err) {
- LFS_TRACE("lfs_rename -> %d", err);
return err;
}
if (prevdir.m.count > 0 || prevdir.m.split) {
- LFS_TRACE("lfs_rename -> %d", LFS_ERR_NOTEMPTY);
return LFS_ERR_NOTEMPTY;
}
@@ -3334,7 +3336,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
LFS_TYPE_DELETE, newoldid, 0), NULL}));
if (err) {
lfs->mlist = prevdir.next;
- LFS_TRACE("lfs_rename -> %d", err);
return err;
}
@@ -3347,7 +3348,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
{LFS_MKTAG(LFS_TYPE_DELETE, lfs_tag_id(oldtag), 0), NULL}));
if (err) {
lfs->mlist = prevdir.next;
- LFS_TRACE("lfs_rename -> %d", err);
return err;
}
}
@@ -3359,29 +3359,24 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
err = lfs_fs_pred(lfs, prevdir.m.pair, &newcwd);
if (err) {
- LFS_TRACE("lfs_rename -> %d", err);
return err;
}
err = lfs_dir_drop(lfs, &newcwd, &prevdir.m);
if (err) {
- LFS_TRACE("lfs_rename -> %d", err);
return err;
}
}
- LFS_TRACE("lfs_rename -> %d", 0);
return 0;
}
+#endif
-lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
+static lfs_ssize_t lfs_rawgetattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size) {
- LFS_TRACE("lfs_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
- (void*)lfs, path, type, buffer, size);
lfs_mdir_t cwd;
lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
if (tag < 0) {
- LFS_TRACE("lfs_getattr -> %"PRId32, tag);
return tag;
}
@@ -3391,7 +3386,6 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
id = 0;
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
if (err) {
- LFS_TRACE("lfs_getattr -> %d", err);
return err;
}
}
@@ -3402,19 +3396,16 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
buffer);
if (tag < 0) {
if (tag == LFS_ERR_NOENT) {
- LFS_TRACE("lfs_getattr -> %d", LFS_ERR_NOATTR);
return LFS_ERR_NOATTR;
}
- LFS_TRACE("lfs_getattr -> %"PRId32, tag);
return tag;
}
- size = lfs_tag_size(tag);
- LFS_TRACE("lfs_getattr -> %"PRId32, size);
- return size;
+ return lfs_tag_size(tag);
}
+#ifndef LFS_READONLY
static int lfs_commitattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size) {
lfs_mdir_t cwd;
@@ -3436,27 +3427,24 @@ static int lfs_commitattr(lfs_t *lfs, const char *path,
return lfs_dir_commit(lfs, &cwd, LFS_MKATTRS(
{LFS_MKTAG(LFS_TYPE_USERATTR + type, id, size), buffer}));
}
+#endif
-int lfs_setattr(lfs_t *lfs, const char *path,
+#ifndef LFS_READONLY
+static int lfs_rawsetattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size) {
- LFS_TRACE("lfs_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
- (void*)lfs, path, type, buffer, size);
if (size > lfs->attr_max) {
- LFS_TRACE("lfs_setattr -> %d", LFS_ERR_NOSPC);
return LFS_ERR_NOSPC;
}
- int err = lfs_commitattr(lfs, path, type, buffer, size);
- LFS_TRACE("lfs_setattr -> %d", err);
- return err;
+ return lfs_commitattr(lfs, path, type, buffer, size);
}
+#endif
-int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
- LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type);
- int err = lfs_commitattr(lfs, path, type, NULL, 0x3ff);
- LFS_TRACE("lfs_removeattr -> %d", err);
- return err;
+#ifndef LFS_READONLY
+static int lfs_rawremoveattr(lfs_t *lfs, const char *path, uint8_t type) {
+ return lfs_commitattr(lfs, path, type, NULL, 0x3ff);
}
+#endif
/// Filesystem operations ///
@@ -3584,28 +3572,12 @@ static int lfs_deinit(lfs_t *lfs) {
return 0;
}
-int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
- LFS_TRACE("lfs_format(%p, %p {.context=%p, "
- ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
- ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
- ".block_size=%"PRIu32", .block_count=%"PRIu32", "
- ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
- ".lookahead_size=%"PRIu32", .read_buffer=%p, "
- ".prog_buffer=%p, .lookahead_buffer=%p, "
- ".name_max=%"PRIu32", .file_max=%"PRIu32", "
- ".attr_max=%"PRIu32"})",
- (void*)lfs, (void*)cfg, cfg->context,
- (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
- (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
- cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
- cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
- cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
- cfg->name_max, cfg->file_max, cfg->attr_max);
+#ifndef LFS_READONLY
+static int lfs_rawformat(lfs_t *lfs, const struct lfs_config *cfg) {
int err = 0;
{
err = lfs_init(lfs, cfg);
if (err) {
- LFS_TRACE("lfs_format -> %d", err);
return err;
}
@@ -3661,30 +3633,14 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
cleanup:
lfs_deinit(lfs);
- LFS_TRACE("lfs_format -> %d", err);
return err;
+
}
+#endif
-int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
- LFS_TRACE("lfs_mount(%p, %p {.context=%p, "
- ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
- ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
- ".block_size=%"PRIu32", .block_count=%"PRIu32", "
- ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
- ".lookahead_size=%"PRIu32", .read_buffer=%p, "
- ".prog_buffer=%p, .lookahead_buffer=%p, "
- ".name_max=%"PRIu32", .file_max=%"PRIu32", "
- ".attr_max=%"PRIu32"})",
- (void*)lfs, (void*)cfg, cfg->context,
- (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
- (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
- cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
- cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
- cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
- cfg->name_max, cfg->file_max, cfg->attr_max);
+static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
int err = lfs_init(lfs, cfg);
if (err) {
- LFS_TRACE("lfs_mount -> %d", err);
return err;
}
@@ -3797,28 +3753,25 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->gstate.tag += !lfs_tag_isvalid(lfs->gstate.tag);
lfs->gdisk = lfs->gstate;
- // setup free lookahead
- lfs_alloc_reset(lfs);
+ // setup free lookahead, to distribute allocations uniformly across
+ // boots, we start the allocator at a random location
+ lfs->free.off = lfs->seed % lfs->cfg->block_count;
+ lfs_alloc_drop(lfs);
- LFS_TRACE("lfs_mount -> %d", 0);
return 0;
cleanup:
- lfs_unmount(lfs);
- LFS_TRACE("lfs_mount -> %d", err);
+ lfs_rawunmount(lfs);
return err;
}
-int lfs_unmount(lfs_t *lfs) {
- LFS_TRACE("lfs_unmount(%p)", (void*)lfs);
- int err = lfs_deinit(lfs);
- LFS_TRACE("lfs_unmount -> %d", err);
- return err;
+static int lfs_rawunmount(lfs_t *lfs) {
+ return lfs_deinit(lfs);
}
/// Filesystem filesystem operations ///
-int lfs_fs_traverseraw(lfs_t *lfs,
+int lfs_fs_rawtraverse(lfs_t *lfs,
int (*cb)(void *data, lfs_block_t block), void *data,
bool includeorphans) {
// iterate over metadata pairs
@@ -3888,6 +3841,7 @@ int lfs_fs_traverseraw(lfs_t *lfs,
}
}
+#ifndef LFS_READONLY
// iterate over any open files
for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) {
if (f->type != LFS_TYPE_REG) {
@@ -3910,19 +3864,12 @@ int lfs_fs_traverseraw(lfs_t *lfs,
}
}
}
+#endif
return 0;
}
-int lfs_fs_traverse(lfs_t *lfs,
- int (*cb)(void *data, lfs_block_t block), void *data) {
- LFS_TRACE("lfs_fs_traverse(%p, %p, %p)",
- (void*)lfs, (void*)(uintptr_t)cb, data);
- int err = lfs_fs_traverseraw(lfs, cb, data, true);
- LFS_TRACE("lfs_fs_traverse -> %d", 0);
- return err;
-}
-
+#ifndef LFS_READONLY
static int lfs_fs_pred(lfs_t *lfs,
const lfs_block_t pair[2], lfs_mdir_t *pdir) {
// iterate over all directory directory entries
@@ -3948,12 +3895,16 @@ static int lfs_fs_pred(lfs_t *lfs,
return LFS_ERR_NOENT;
}
+#endif
+#ifndef LFS_READONLY
struct lfs_fs_parent_match {
lfs_t *lfs;
const lfs_block_t pair[2];
};
+#endif
+#ifndef LFS_READONLY
static int lfs_fs_parent_match(void *data,
lfs_tag_t tag, const void *buffer) {
struct lfs_fs_parent_match *find = data;
@@ -3972,7 +3923,9 @@ static int lfs_fs_parent_match(void *data,
lfs_pair_fromle32(child);
return (lfs_pair_cmp(child, find->pair) == 0) ? LFS_CMP_EQ : LFS_CMP_LT;
}
+#endif
+#ifndef LFS_READONLY
static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],
lfs_mdir_t *parent) {
// use fetchmatch with callback to find pairs
@@ -3999,7 +3952,9 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],
return LFS_ERR_NOENT;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_fs_relocate(lfs_t *lfs,
const lfs_block_t oldpair[2], lfs_block_t newpair[2]) {
// update internal root
@@ -4094,14 +4049,18 @@ static int lfs_fs_relocate(lfs_t *lfs,
return 0;
}
+#endif
+#ifndef LFS_READONLY
static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) {
LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0 || orphans >= 0);
lfs->gstate.tag += orphans;
lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) |
((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31));
}
+#endif
+#ifndef LFS_READONLY
static void lfs_fs_prepmove(lfs_t *lfs,
uint16_t id, const lfs_block_t pair[2]) {
lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x7ff, 0x3ff, 0)) |
@@ -4109,7 +4068,9 @@ static void lfs_fs_prepmove(lfs_t *lfs,
lfs->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0;
lfs->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_fs_demove(lfs_t *lfs) {
if (!lfs_gstate_hasmove(&lfs->gdisk)) {
return 0;
@@ -4139,7 +4100,9 @@ static int lfs_fs_demove(lfs_t *lfs) {
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_fs_deorphan(lfs_t *lfs) {
if (!lfs_gstate_hasorphans(&lfs->gstate)) {
return 0;
@@ -4213,7 +4176,9 @@ static int lfs_fs_deorphan(lfs_t *lfs) {
lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate));
return 0;
}
+#endif
+#ifndef LFS_READONLY
static int lfs_fs_forceconsistency(lfs_t *lfs) {
int err = lfs_fs_demove(lfs);
if (err) {
@@ -4227,6 +4192,7 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
return 0;
}
+#endif
static int lfs_fs_size_count(void *p, lfs_block_t block) {
(void)block;
@@ -4235,16 +4201,13 @@ static int lfs_fs_size_count(void *p, lfs_block_t block) {
return 0;
}
-lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
- LFS_TRACE("lfs_fs_size(%p)", (void*)lfs);
+static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs) {
lfs_size_t size = 0;
- int err = lfs_fs_traverseraw(lfs, lfs_fs_size_count, &size, false);
+ int err = lfs_fs_rawtraverse(lfs, lfs_fs_size_count, &size, false);
if (err) {
- LFS_TRACE("lfs_fs_size -> %d", err);
return err;
}
- LFS_TRACE("lfs_fs_size -> %d", err);
return size;
}
@@ -4669,27 +4632,10 @@ static int lfs1_unmount(lfs_t *lfs) {
}
/// v1 migration ///
-int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
- LFS_TRACE("lfs_migrate(%p, %p {.context=%p, "
- ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
- ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
- ".block_size=%"PRIu32", .block_count=%"PRIu32", "
- ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
- ".lookahead_size=%"PRIu32", .read_buffer=%p, "
- ".prog_buffer=%p, .lookahead_buffer=%p, "
- ".name_max=%"PRIu32", .file_max=%"PRIu32", "
- ".attr_max=%"PRIu32"})",
- (void*)lfs, (void*)cfg, cfg->context,
- (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
- (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
- cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
- cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
- cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
- cfg->name_max, cfg->file_max, cfg->attr_max);
+static int lfs_rawmigrate(lfs_t *lfs, const struct lfs_config *cfg) {
struct lfs1 lfs1;
int err = lfs1_mount(lfs, &lfs1, cfg);
if (err) {
- LFS_TRACE("lfs_migrate -> %d", err);
return err;
}
@@ -4906,8 +4852,539 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
cleanup:
lfs1_unmount(lfs);
- LFS_TRACE("lfs_migrate -> %d", err);
return err;
}
#endif
+
+
+/// Public API wrappers ///
+
+// Here we can add tracing/thread safety easily
+
+// Thread-safe wrappers if enabled
+#ifdef LFS_THREADSAFE
+#define LFS_LOCK(cfg) cfg->lock(cfg)
+#define LFS_UNLOCK(cfg) cfg->unlock(cfg)
+#else
+#define LFS_LOCK(cfg) ((void)cfg, 0)
+#define LFS_UNLOCK(cfg) ((void)cfg)
+#endif
+
+// Public API
+#ifndef LFS_READONLY
+int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
+ int err = LFS_LOCK(cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_format(%p, %p {.context=%p, "
+ ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
+ ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
+ ".block_size=%"PRIu32", .block_count=%"PRIu32", "
+ ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".lookahead_size=%"PRIu32", .read_buffer=%p, "
+ ".prog_buffer=%p, .lookahead_buffer=%p, "
+ ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+ ".attr_max=%"PRIu32"})",
+ (void*)lfs, (void*)cfg, cfg->context,
+ (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
+ (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
+ cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
+ cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
+ cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
+ cfg->name_max, cfg->file_max, cfg->attr_max);
+
+ err = lfs_rawformat(lfs, cfg);
+
+ LFS_TRACE("lfs_format -> %d", err);
+ LFS_UNLOCK(cfg);
+ return err;
+}
+#endif
+
+int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
+ int err = LFS_LOCK(cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_mount(%p, %p {.context=%p, "
+ ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
+ ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
+ ".block_size=%"PRIu32", .block_count=%"PRIu32", "
+ ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".lookahead_size=%"PRIu32", .read_buffer=%p, "
+ ".prog_buffer=%p, .lookahead_buffer=%p, "
+ ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+ ".attr_max=%"PRIu32"})",
+ (void*)lfs, (void*)cfg, cfg->context,
+ (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
+ (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
+ cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
+ cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
+ cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
+ cfg->name_max, cfg->file_max, cfg->attr_max);
+
+ err = lfs_rawmount(lfs, cfg);
+
+ LFS_TRACE("lfs_mount -> %d", err);
+ LFS_UNLOCK(cfg);
+ return err;
+}
+
+int lfs_unmount(lfs_t *lfs) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_unmount(%p)", (void*)lfs);
+
+ err = lfs_rawunmount(lfs);
+
+ LFS_TRACE("lfs_unmount -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+#ifndef LFS_READONLY
+int lfs_remove(lfs_t *lfs, const char *path) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path);
+
+ err = lfs_rawremove(lfs, path);
+
+ LFS_TRACE("lfs_remove -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+#ifndef LFS_READONLY
+int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_rename(%p, \"%s\", \"%s\")", (void*)lfs, oldpath, newpath);
+
+ err = lfs_rawrename(lfs, oldpath, newpath);
+
+ LFS_TRACE("lfs_rename -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_stat(%p, \"%s\", %p)", (void*)lfs, path, (void*)info);
+
+ err = lfs_rawstat(lfs, path, info);
+
+ LFS_TRACE("lfs_stat -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
+ uint8_t type, void *buffer, lfs_size_t size) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
+ (void*)lfs, path, type, buffer, size);
+
+ lfs_ssize_t res = lfs_rawgetattr(lfs, path, type, buffer, size);
+
+ LFS_TRACE("lfs_getattr -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+#ifndef LFS_READONLY
+int lfs_setattr(lfs_t *lfs, const char *path,
+ uint8_t type, const void *buffer, lfs_size_t size) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
+ (void*)lfs, path, type, buffer, size);
+
+ err = lfs_rawsetattr(lfs, path, type, buffer, size);
+
+ LFS_TRACE("lfs_setattr -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+#ifndef LFS_READONLY
+int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type);
+
+ err = lfs_rawremoveattr(lfs, path, type);
+
+ LFS_TRACE("lfs_removeattr -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_open(%p, %p, \"%s\", %x)",
+ (void*)lfs, (void*)file, path, flags);
+ LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ err = lfs_file_rawopen(lfs, file, path, flags);
+
+ LFS_TRACE("lfs_file_open -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
+ const char *path, int flags,
+ const struct lfs_file_config *cfg) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_opencfg(%p, %p, \"%s\", %x, %p {"
+ ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
+ (void*)lfs, (void*)file, path, flags,
+ (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
+ LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ err = lfs_file_rawopencfg(lfs, file, path, flags, cfg);
+
+ LFS_TRACE("lfs_file_opencfg -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ err = lfs_file_rawclose(lfs, file);
+
+ LFS_TRACE("lfs_file_close -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+#ifndef LFS_READONLY
+int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ err = lfs_file_rawsync(lfs, file);
+
+ LFS_TRACE("lfs_file_sync -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
+ void *buffer, lfs_size_t size) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_read(%p, %p, %p, %"PRIu32")",
+ (void*)lfs, (void*)file, buffer, size);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ lfs_ssize_t res = lfs_file_rawread(lfs, file, buffer, size);
+
+ LFS_TRACE("lfs_file_read -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+#ifndef LFS_READONLY
+lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
+ const void *buffer, lfs_size_t size) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_write(%p, %p, %p, %"PRIu32")",
+ (void*)lfs, (void*)file, buffer, size);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ lfs_ssize_t res = lfs_file_rawwrite(lfs, file, buffer, size);
+
+ LFS_TRACE("lfs_file_write -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+#endif
+
+lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
+ lfs_soff_t off, int whence) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_seek(%p, %p, %"PRId32", %d)",
+ (void*)lfs, (void*)file, off, whence);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ lfs_soff_t res = lfs_file_rawseek(lfs, file, off, whence);
+
+ LFS_TRACE("lfs_file_seek -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+#ifndef LFS_READONLY
+int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_truncate(%p, %p, %"PRIu32")",
+ (void*)lfs, (void*)file, size);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ err = lfs_file_rawtruncate(lfs, file, size);
+
+ LFS_TRACE("lfs_file_truncate -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ lfs_soff_t res = lfs_file_rawtell(lfs, file);
+
+ LFS_TRACE("lfs_file_tell -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_rewind(%p, %p)", (void*)lfs, (void*)file);
+
+ err = lfs_file_rawrewind(lfs, file);
+
+ LFS_TRACE("lfs_file_rewind -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_file_size(%p, %p)", (void*)lfs, (void*)file);
+ LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+ lfs_soff_t res = lfs_file_rawsize(lfs, file);
+
+ LFS_TRACE("lfs_file_size -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+#ifndef LFS_READONLY
+int lfs_mkdir(lfs_t *lfs, const char *path) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path);
+
+ err = lfs_rawmkdir(lfs, path);
+
+ LFS_TRACE("lfs_mkdir -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+#endif
+
+int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_dir_open(%p, %p, \"%s\")", (void*)lfs, (void*)dir, path);
+ LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)dir));
+
+ err = lfs_dir_rawopen(lfs, dir, path);
+
+ LFS_TRACE("lfs_dir_open -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_dir_close(%p, %p)", (void*)lfs, (void*)dir);
+
+ err = lfs_dir_rawclose(lfs, dir);
+
+ LFS_TRACE("lfs_dir_close -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_dir_read(%p, %p, %p)",
+ (void*)lfs, (void*)dir, (void*)info);
+
+ err = lfs_dir_rawread(lfs, dir, info);
+
+ LFS_TRACE("lfs_dir_read -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_dir_seek(%p, %p, %"PRIu32")",
+ (void*)lfs, (void*)dir, off);
+
+ err = lfs_dir_rawseek(lfs, dir, off);
+
+ LFS_TRACE("lfs_dir_seek -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_dir_tell(%p, %p)", (void*)lfs, (void*)dir);
+
+ lfs_soff_t res = lfs_dir_rawtell(lfs, dir);
+
+ LFS_TRACE("lfs_dir_tell -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_dir_rewind(%p, %p)", (void*)lfs, (void*)dir);
+
+ err = lfs_dir_rawrewind(lfs, dir);
+
+ LFS_TRACE("lfs_dir_rewind -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_fs_size(%p)", (void*)lfs);
+
+ lfs_ssize_t res = lfs_fs_rawsize(lfs);
+
+ LFS_TRACE("lfs_fs_size -> %"PRId32, res);
+ LFS_UNLOCK(lfs->cfg);
+ return res;
+}
+
+int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data) {
+ int err = LFS_LOCK(lfs->cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_fs_traverse(%p, %p, %p)",
+ (void*)lfs, (void*)(uintptr_t)cb, data);
+
+ err = lfs_fs_rawtraverse(lfs, cb, data, true);
+
+ LFS_TRACE("lfs_fs_traverse -> %d", err);
+ LFS_UNLOCK(lfs->cfg);
+ return err;
+}
+
+#ifdef LFS_MIGRATE
+int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
+ int err = LFS_LOCK(cfg);
+ if (err) {
+ return err;
+ }
+ LFS_TRACE("lfs_migrate(%p, %p {.context=%p, "
+ ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
+ ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
+ ".block_size=%"PRIu32", .block_count=%"PRIu32", "
+ ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".lookahead_size=%"PRIu32", .read_buffer=%p, "
+ ".prog_buffer=%p, .lookahead_buffer=%p, "
+ ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+ ".attr_max=%"PRIu32"})",
+ (void*)lfs, (void*)cfg, cfg->context,
+ (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
+ (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
+ cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
+ cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
+ cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
+ cfg->name_max, cfg->file_max, cfg->attr_max);
+
+ err = lfs_rawmigrate(lfs, cfg);
+
+ LFS_TRACE("lfs_migrate -> %d", err);
+ LFS_UNLOCK(cfg);
+ return err;
+}
+#endif
+
diff --git a/lfs.h b/lfs.h
index 35bbbab..3b02b6a 100644
--- a/lfs.h
+++ b/lfs.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "lfs_util.h"
#ifdef __cplusplus
extern "C"
@@ -21,7 +22,7 @@ extern "C"
// Software library version
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
-#define LFS_VERSION 0x00020002
+#define LFS_VERSION 0x00020003
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
@@ -123,20 +124,25 @@ enum lfs_type {
enum lfs_open_flags {
// open flags
LFS_O_RDONLY = 1, // Open a file as read only
+#ifndef LFS_READONLY
LFS_O_WRONLY = 2, // Open a file as write only
LFS_O_RDWR = 3, // Open a file as read and write
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS_O_APPEND = 0x0800, // Move to end of file on every write
+#endif
// internally used flags
+#ifndef LFS_READONLY
LFS_F_DIRTY = 0x010000, // File does not match storage
LFS_F_WRITING = 0x020000, // File has been written since last flush
+#endif
LFS_F_READING = 0x040000, // File has been read since last flush
- LFS_F_ERRED = 0x080000, // An error occured during write
+#ifndef LFS_READONLY
+ LFS_F_ERRED = 0x080000, // An error occurred during write
+#endif
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
- LFS_F_OPENED = 0x200000, // File has been opened
};
// File seek flags
@@ -174,6 +180,16 @@ struct lfs_config {
// are propogated to the user.
int (*sync)(const struct lfs_config *c);
+#ifdef LFS_THREADSAFE
+ // Lock the underlying block device. Negative error codes
+ // are propogated to the user.
+ int (*lock)(const struct lfs_config *c);
+
+ // Unlock the underlying block device. Negative error codes
+ // are propogated to the user.
+ int (*unlock)(const struct lfs_config *c);
+#endif
+
// Minimum size of a block read. All read operations will be a
// multiple of this value.
lfs_size_t read_size;
@@ -399,6 +415,7 @@ typedef struct lfs {
/// Filesystem functions ///
+#ifndef LFS_READONLY
// Format a block device with the littlefs
//
// Requires a littlefs object and config struct. This clobbers the littlefs
@@ -407,6 +424,7 @@ typedef struct lfs {
//
// Returns a negative error code on failure.
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
+#endif
// Mounts a littlefs
//
@@ -426,12 +444,15 @@ int lfs_unmount(lfs_t *lfs);
/// General operations ///
+#ifndef LFS_READONLY
// Removes a file or directory
//
// If removing a directory, the directory must be empty.
// Returns a negative error code on failure.
int lfs_remove(lfs_t *lfs, const char *path);
+#endif
+#ifndef LFS_READONLY
// Rename or move a file or directory
//
// If the destination exists, it must match the source in type.
@@ -439,6 +460,7 @@ int lfs_remove(lfs_t *lfs, const char *path);
//
// Returns a negative error code on failure.
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
+#endif
// Find info about a file or directory
//
@@ -461,6 +483,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size);
+#ifndef LFS_READONLY
// Set custom attributes
//
// Custom attributes are uniquely identified by an 8-bit type and limited
@@ -470,13 +493,16 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
// Returns a negative error code on failure.
int lfs_setattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size);
+#endif
+#ifndef LFS_READONLY
// Removes a custom attribute
//
// If an attribute is not found, nothing happens.
//
// Returns a negative error code on failure.
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
+#endif
/// File operations ///
@@ -525,6 +551,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
void *buffer, lfs_size_t size);
+#ifndef LFS_READONLY
// Write data to file
//
// Takes a buffer and size indicating the data to write. The file will not
@@ -533,6 +560,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
// Returns the number of bytes written, or a negative error code on failure.
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size);
+#endif
// Change the position of the file
//
@@ -541,10 +569,12 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t off, int whence);
+#ifndef LFS_READONLY
// Truncates the size of the file to the specified size
//
// Returns a negative error code on failure.
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
+#endif
// Return the position of the file
//
@@ -567,10 +597,12 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
/// Directory operations ///
+#ifndef LFS_READONLY
// Create a directory
//
// Returns a negative error code on failure.
int lfs_mkdir(lfs_t *lfs, const char *path);
+#endif
// Open a directory
//
@@ -632,6 +664,7 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
+#ifndef LFS_READONLY
#ifdef LFS_MIGRATE
// Attempts to migrate a previous version of littlefs
//
@@ -646,6 +679,7 @@ int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
// Returns a negative error code on failure.
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
#endif
+#endif
#ifdef __cplusplus
diff --git a/scripts/readtree.py b/scripts/readtree.py
index 36135ab..be514e3 100755
--- a/scripts/readtree.py
+++ b/scripts/readtree.py
@@ -106,7 +106,7 @@ def main(args):
struct.unpack('<HH', superblock[1].data[0:4].ljust(4, b'\xff'))))
print("%-47s%s" % ("littlefs v%s.%s" % version,
"data (truncated, if it fits)"
- if not any([args.no_truncate, args.tags, args.log, args.all]) else ""))
+ if not any([args.no_truncate, args.log, args.all]) else ""))
# print gstate
print("gstate 0x%s" % ''.join('%02x' % c for c in gstate))