summaryrefslogtreecommitdiffstatshomepage
path: root/lib
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2020-12-09 11:01:24 +1100
committerDamien George <damien@micropython.org>2020-12-09 11:01:24 +1100
commitd9d761b0572b9b99e97f1b5dd39226173f2e239e (patch)
treebd02d89df4bedfe98fde7c760942a8477d658d91 /lib
parent032e0956200d602dcd1dbee8b1894f2e3227e779 (diff)
downloadmicropython-d9d761b0572b9b99e97f1b5dd39226173f2e239e.tar.gz
micropython-d9d761b0572b9b99e97f1b5dd39226173f2e239e.zip
lib/littlefs: Update littlefs2 to v2.3.0.
At commit 1a59954ec64ca168828a15242cc6de94ac75f9d1 Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/littlefs/README.md4
-rw-r--r--lib/littlefs/lfs2.c1169
-rw-r--r--lib/littlefs/lfs2.h40
3 files changed, 862 insertions, 351 deletions
diff --git a/lib/littlefs/README.md b/lib/littlefs/README.md
index 1f0aacbf98..ca21a05f42 100644
--- a/lib/littlefs/README.md
+++ b/lib/littlefs/README.md
@@ -2,7 +2,7 @@ littlefs library
================
The upstream source for the files in this directory is
-https://github.com/ARMmbed/littlefs
+https://github.com/littlefs-project/littlefs
To generate the separate files with lfs1 and lfs2 prefixes run the following
commands in the top-level directory of the littlefs repository (replace the
@@ -13,7 +13,7 @@ version tags with the latest/desired ones, and set `$MPY_DIR`):
cp lfs1*.[ch] $MPY_DIR/lib/littlefs
git reset --hard HEAD
- git checkout v2.1.3
+ git checkout v2.3.0
python2 ./scripts/prefix.py lfs2
cp lfs2*.[ch] $MPY_DIR/lib/littlefs
git reset --hard HEAD
diff --git a/lib/littlefs/lfs2.c b/lib/littlefs/lfs2.c
index 6bae806ceb..31f3c603e7 100644
--- a/lib/littlefs/lfs2.c
+++ b/lib/littlefs/lfs2.c
@@ -118,24 +118,29 @@ static int lfs2_bd_cmp(lfs2_t *lfs2,
lfs2_block_t block, lfs2_off_t off,
const void *buffer, lfs2_size_t size) {
const uint8_t *data = buffer;
+ lfs2_size_t diff = 0;
- for (lfs2_off_t i = 0; i < size; i++) {
- uint8_t dat;
- int err = lfs2_bd_read(lfs2,
+ for (lfs2_off_t i = 0; i < size; i += diff) {
+ uint8_t dat[8];
+
+ diff = lfs2_min(size-i, sizeof(dat));
+ int res = lfs2_bd_read(lfs2,
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]) ? LFS2_CMP_LT : LFS2_CMP_GT;
+ res = memcmp(dat, data + i, diff);
+ if (res) {
+ return res < 0 ? LFS2_CMP_LT : LFS2_CMP_GT;
}
}
return LFS2_CMP_EQ;
}
+#ifndef LFS2_READONLY
static int lfs2_bd_flush(lfs2_t *lfs2,
lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) {
if (pcache->block != LFS2_BLOCK_NULL && pcache->block != LFS2_BLOCK_INLINE) {
@@ -168,7 +173,9 @@ static int lfs2_bd_flush(lfs2_t *lfs2,
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_bd_sync(lfs2_t *lfs2,
lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) {
lfs2_cache_drop(lfs2, rcache);
@@ -182,7 +189,9 @@ static int lfs2_bd_sync(lfs2_t *lfs2,
LFS2_ASSERT(err <= 0);
return err;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_bd_prog(lfs2_t *lfs2,
lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate,
lfs2_block_t block, lfs2_off_t off,
@@ -228,13 +237,16 @@ static int lfs2_bd_prog(lfs2_t *lfs2,
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) {
LFS2_ASSERT(block < lfs2->cfg->block_count);
int err = lfs2->cfg->erase(lfs2->cfg, block);
LFS2_ASSERT(err <= 0);
return err;
}
+#endif
/// Small type-level utilities ///
@@ -388,10 +400,12 @@ static void lfs2_ctz_fromle32(struct lfs2_ctz *ctz) {
ctz->size = lfs2_fromle32(ctz->size);
}
+#ifndef LFS2_READONLY
static void lfs2_ctz_tole32(struct lfs2_ctz *ctz) {
ctz->head = lfs2_tole32(ctz->head);
ctz->size = lfs2_tole32(ctz->size);
}
+#endif
static inline void lfs2_superblock_fromle32(lfs2_superblock_t *superblock) {
superblock->version = lfs2_fromle32(superblock->version);
@@ -411,15 +425,46 @@ static inline void lfs2_superblock_tole32(lfs2_superblock_t *superblock) {
superblock->attr_max = lfs2_tole32(superblock->attr_max);
}
+static inline bool lfs2_mlist_isopen(struct lfs2_mlist *head,
+ struct lfs2_mlist *node) {
+ for (struct lfs2_mlist **p = &head; *p; p = &(*p)->next) {
+ if (*p == (struct lfs2_mlist*)node) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static inline void lfs2_mlist_remove(lfs2_t *lfs2, struct lfs2_mlist *mlist) {
+ for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) {
+ if (*p == mlist) {
+ *p = (*p)->next;
+ break;
+ }
+ }
+}
+
+static inline void lfs2_mlist_append(lfs2_t *lfs2, struct lfs2_mlist *mlist) {
+ mlist->next = lfs2->mlist;
+ lfs2->mlist = mlist;
+}
+
/// Internal operations predeclared here ///
+#ifndef LFS2_READONLY
static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir,
const struct lfs2_mattr *attrs, int attrcount);
static int lfs2_dir_compact(lfs2_t *lfs2,
lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount,
lfs2_mdir_t *source, uint16_t begin, uint16_t end);
+
+static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file,
+ const void *buffer, lfs2_size_t size);
+static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file);
static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file);
static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file);
+
static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans);
static void lfs2_fs_prepmove(lfs2_t *lfs2,
uint16_t id, const lfs2_block_t pair[2]);
@@ -429,17 +474,32 @@ static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t dir[2],
lfs2_mdir_t *parent);
static int lfs2_fs_relocate(lfs2_t *lfs2,
const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]);
-int lfs2_fs_traverseraw(lfs2_t *lfs2,
- int (*cb)(void *data, lfs2_block_t block), void *data,
- bool includeorphans);
static int lfs2_fs_forceconsistency(lfs2_t *lfs2);
-static int lfs2_deinit(lfs2_t *lfs2);
+#endif
+
#ifdef LFS2_MIGRATE
static int lfs21_traverse(lfs2_t *lfs2,
int (*cb)(void*, lfs2_block_t), void *data);
#endif
+static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir);
+
+static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file,
+ void *buffer, lfs2_size_t size);
+static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file);
+static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file);
+
+static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2);
+static int lfs2_fs_rawtraverse(lfs2_t *lfs2,
+ int (*cb)(void *data, lfs2_block_t block), void *data,
+ bool includeorphans);
+
+static int lfs2_deinit(lfs2_t *lfs2);
+static int lfs2_rawunmount(lfs2_t *lfs2);
+
+
/// Block allocator ///
+#ifndef LFS2_READONLY
static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) {
lfs2_t *lfs2 = (lfs2_t*)p;
lfs2_block_t off = ((block - lfs2->free.off)
@@ -451,20 +511,24 @@ static int lfs2_alloc_lookahead(void *p, lfs2_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 lfs2_alloc_ack(lfs2_t *lfs2) {
lfs2->free.ack = lfs2->cfg->block_count;
}
-// Invalidate the lookahead buffer. This is done during mounting and
-// failed traversals
-static void lfs2_alloc_reset(lfs2_t *lfs2) {
- lfs2->free.off = lfs2->seed % lfs2->cfg->block_size;
+// drop the lookahead buffer, this is done during mounting and failed
+// traversals in order to avoid invalid lookahead state
+static void lfs2_alloc_drop(lfs2_t *lfs2) {
lfs2->free.size = 0;
lfs2->free.i = 0;
lfs2_alloc_ack(lfs2);
}
+#ifndef LFS2_READONLY
static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) {
while (true) {
while (lfs2->free.i != lfs2->free.size) {
@@ -503,13 +567,14 @@ static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) {
// find mask of free blocks from tree
memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size);
- int err = lfs2_fs_traverseraw(lfs2, lfs2_alloc_lookahead, lfs2, true);
+ int err = lfs2_fs_rawtraverse(lfs2, lfs2_alloc_lookahead, lfs2, true);
if (err) {
- lfs2_alloc_reset(lfs2);
+ lfs2_alloc_drop(lfs2);
return err;
}
}
}
+#endif
/// Metadata pair and directory operations ///
static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir,
@@ -642,6 +707,7 @@ static int lfs2_dir_getread(lfs2_t *lfs2, const lfs2_mdir_t *dir,
return 0;
}
+#ifndef LFS2_READONLY
static int lfs2_dir_traverse_filter(void *p,
lfs2_tag_t tag, const void *buffer) {
lfs2_tag_t *filtertag = p;
@@ -669,7 +735,9 @@ static int lfs2_dir_traverse_filter(void *p,
return false;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_traverse(lfs2_t *lfs2,
const lfs2_mdir_t *dir, lfs2_off_t off, lfs2_tag_t ptag,
const struct lfs2_mattr *attrs, int attrcount,
@@ -763,6 +831,7 @@ static int lfs2_dir_traverse(lfs2_t *lfs2,
}
}
}
+#endif
static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2,
lfs2_mdir_t *dir, const lfs2_block_t pair[2],
@@ -870,8 +939,10 @@ static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2,
ptag ^= (lfs2_tag_t)(lfs2_tag_chunk(tag) & 1U) << 31;
// toss our crc into the filesystem seed for
- // pseudorandom numbers
- lfs2->seed ^= crc;
+ // pseudorandom numbers, note we use another crc here
+ // as a collection function because it is sufficiently
+ // random and convenient
+ lfs2->seed = lfs2_crc(lfs2->seed, &crc, sizeof(crc));
// update with what's found so far
besttag = tempbesttag;
@@ -1200,6 +1271,7 @@ struct lfs2_commit {
lfs2_off_t end;
};
+#ifndef LFS2_READONLY
static int lfs2_dir_commitprog(lfs2_t *lfs2, struct lfs2_commit *commit,
const void *buffer, lfs2_size_t size) {
int err = lfs2_bd_prog(lfs2,
@@ -1214,7 +1286,9 @@ static int lfs2_dir_commitprog(lfs2_t *lfs2, struct lfs2_commit *commit,
commit->off += size;
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_commitattr(lfs2_t *lfs2, struct lfs2_commit *commit,
lfs2_tag_t tag, const void *buffer) {
// check if we fit
@@ -1259,14 +1333,17 @@ static int lfs2_dir_commitattr(lfs2_t *lfs2, struct lfs2_commit *commit,
commit->ptag = tag & 0x7fffffff;
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_commit *commit) {
- const lfs2_off_t off1 = commit->off;
- const uint32_t crc1 = commit->crc;
// align to program units
- const lfs2_off_t end = lfs2_alignup(off1 + 2*sizeof(uint32_t),
+ const lfs2_off_t end = lfs2_alignup(commit->off + 2*sizeof(uint32_t),
lfs2->cfg->prog_size);
+ lfs2_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 lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_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)+lfs2_tag_size(tag);
commit->ptag = tag ^ ((lfs2_tag_t)reset << 31);
commit->crc = 0xffffffff; // reset crc for next "commit"
@@ -1315,7 +1398,7 @@ static int lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_commit *commit) {
// successful commit, check checksums to make sure
lfs2_off_t off = commit->begin;
- lfs2_off_t noff = off1 + sizeof(uint32_t);
+ lfs2_off_t noff = off1;
while (off < end) {
uint32_t crc = 0xffffffff;
for (lfs2_off_t i = off; i < noff+sizeof(uint32_t); i++) {
@@ -1352,7 +1435,9 @@ static int lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_commit *commit) {
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_alloc(lfs2_t *lfs2, lfs2_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 lfs2_dir_alloc(lfs2_t *lfs2, lfs2_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 lfs2_dir_compact for why our modulus
+ // is tweaked this way
+ if (lfs2->cfg->block_cycles > 0) {
+ dir->rev = lfs2_alignup(dir->rev, ((lfs2->cfg->block_cycles+1)|1));
+ }
// set defaults
dir->off = sizeof(dir->rev);
@@ -1390,7 +1479,9 @@ static int lfs2_dir_alloc(lfs2_t *lfs2, lfs2_mdir_t *dir) {
// don't write out yet, let caller take care of that
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_drop(lfs2_t *lfs2, lfs2_mdir_t *dir, lfs2_mdir_t *tail) {
// steal state
int err = lfs2_dir_getgstate(lfs2, tail, &lfs2->gdelta);
@@ -1409,7 +1500,9 @@ static int lfs2_dir_drop(lfs2_t *lfs2, lfs2_mdir_t *dir, lfs2_mdir_t *tail) {
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_split(lfs2_t *lfs2,
lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount,
lfs2_mdir_t *source, uint16_t split, uint16_t end) {
@@ -1442,7 +1535,9 @@ static int lfs2_dir_split(lfs2_t *lfs2,
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_commit_size(void *p, lfs2_tag_t tag, const void *buffer) {
lfs2_size_t *size = p;
(void)buffer;
@@ -1450,17 +1545,23 @@ static int lfs2_dir_commit_size(void *p, lfs2_tag_t tag, const void *buffer) {
*size += lfs2_tag_dsize(tag);
return 0;
}
+#endif
+#ifndef LFS2_READONLY
struct lfs2_dir_commit_commit {
lfs2_t *lfs2;
struct lfs2_commit *commit;
};
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_commit_commit(void *p, lfs2_tag_t tag, const void *buffer) {
struct lfs2_dir_commit_commit *commit = p;
return lfs2_dir_commitattr(commit->lfs2, commit->commit, tag, buffer);
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_compact(lfs2_t *lfs2,
lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount,
lfs2_mdir_t *source, uint16_t begin, uint16_t end) {
@@ -1525,7 +1626,7 @@ static int lfs2_dir_compact(lfs2_t *lfs2,
if (lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) {
// oh no! we're writing too much to the superblock,
// should we expand?
- lfs2_ssize_t res = lfs2_fs_size(lfs2);
+ lfs2_ssize_t res = lfs2_fs_rawsize(lfs2);
if (res < 0) {
return res;
}
@@ -1715,7 +1816,9 @@ relocate:
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir,
const struct lfs2_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 lfs2_mkdir(lfs2_t *lfs2, const char *path) {
- LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path);
+#ifndef LFS2_READONLY
+static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
- LFS2_TRACE("lfs2_mkdir -> %d", err);
return err;
}
@@ -1920,14 +2023,12 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
uint16_t id;
err = lfs2_dir_find(lfs2, &cwd.m, &path, &id);
if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) {
- LFS2_TRACE("lfs2_mkdir -> %d", (err < 0) ? err : LFS2_ERR_EXIST);
return (err < 0) ? err : LFS2_ERR_EXIST;
}
// check that name fits
lfs2_size_t nlen = strlen(path);
if (nlen > lfs2->name_max) {
- LFS2_TRACE("lfs2_mkdir -> %d", LFS2_ERR_NAMETOOLONG);
return LFS2_ERR_NAMETOOLONG;
}
@@ -1936,7 +2037,6 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
lfs2_mdir_t dir;
err = lfs2_dir_alloc(lfs2, &dir);
if (err) {
- LFS2_TRACE("lfs2_mkdir -> %d", err);
return err;
}
@@ -1945,7 +2045,6 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
while (pred.split) {
err = lfs2_dir_fetch(lfs2, &pred, pred.tail);
if (err) {
- LFS2_TRACE("lfs2_mkdir -> %d", err);
return err;
}
}
@@ -1956,7 +2055,6 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
{LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pred.tail}));
lfs2_pair_fromle32(pred.tail);
if (err) {
- LFS2_TRACE("lfs2_mkdir -> %d", err);
return err;
}
@@ -1979,7 +2077,6 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
lfs2_pair_fromle32(dir.pair);
if (err) {
lfs2->mlist = cwd.next;
- LFS2_TRACE("lfs2_mkdir -> %d", err);
return err;
}
@@ -1997,24 +2094,20 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
LFS2_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair}));
lfs2_pair_fromle32(dir.pair);
if (err) {
- LFS2_TRACE("lfs2_mkdir -> %d", err);
return err;
}
- LFS2_TRACE("lfs2_mkdir -> %d", 0);
return 0;
}
+#endif
-int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
- LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path);
+static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL);
if (tag < 0) {
- LFS2_TRACE("lfs2_dir_open -> %"PRId32, tag);
return tag;
}
if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
- LFS2_TRACE("lfs2_dir_open -> %d", LFS2_ERR_NOTDIR);
return LFS2_ERR_NOTDIR;
}
@@ -2028,7 +2121,6 @@ int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
lfs2_stag_t res = lfs2_dir_get(lfs2, &dir->m, LFS2_MKTAG(0x700, 0x3ff, 0),
LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair);
if (res < 0) {
- LFS2_TRACE("lfs2_dir_open -> %"PRId32, res);
return res;
}
lfs2_pair_fromle32(pair);
@@ -2037,7 +2129,6 @@ int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
// fetch first pair
int err = lfs2_dir_fetch(lfs2, &dir->m, pair);
if (err) {
- LFS2_TRACE("lfs2_dir_open -> %d", err);
return err;
}
@@ -2049,30 +2140,19 @@ int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
// add to list of mdirs
dir->type = LFS2_TYPE_DIR;
- dir->next = (lfs2_dir_t*)lfs2->mlist;
- lfs2->mlist = (struct lfs2_mlist*)dir;
+ lfs2_mlist_append(lfs2, (struct lfs2_mlist *)dir);
- LFS2_TRACE("lfs2_dir_open -> %d", 0);
return 0;
}
-int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) {
- LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir);
+static int lfs2_dir_rawclose(lfs2_t *lfs2, lfs2_dir_t *dir) {
// remove from list of mdirs
- for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) {
- if (*p == (struct lfs2_mlist*)dir) {
- *p = (*p)->next;
- break;
- }
- }
+ lfs2_mlist_remove(lfs2, (struct lfs2_mlist *)dir);
- LFS2_TRACE("lfs2_dir_close -> %d", 0);
return 0;
}
-int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
- LFS2_TRACE("lfs2_dir_read(%p, %p, %p)",
- (void*)lfs2, (void*)dir, (void*)info);
+static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
memset(info, 0, sizeof(*info));
// special offset for '.' and '..'
@@ -2080,26 +2160,22 @@ int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
info->type = LFS2_TYPE_DIR;
strcpy(info->name, ".");
dir->pos += 1;
- LFS2_TRACE("lfs2_dir_read -> %d", true);
return true;
} else if (dir->pos == 1) {
info->type = LFS2_TYPE_DIR;
strcpy(info->name, "..");
dir->pos += 1;
- LFS2_TRACE("lfs2_dir_read -> %d", true);
return true;
}
while (true) {
if (dir->id == dir->m.count) {
if (!dir->m.split) {
- LFS2_TRACE("lfs2_dir_read -> %d", false);
return false;
}
int err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail);
if (err) {
- LFS2_TRACE("lfs2_dir_read -> %d", err);
return err;
}
@@ -2108,7 +2184,6 @@ int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
int err = lfs2_dir_getinfo(lfs2, &dir->m, dir->id, info);
if (err && err != LFS2_ERR_NOENT) {
- LFS2_TRACE("lfs2_dir_read -> %d", err);
return err;
}
@@ -2119,17 +2194,13 @@ int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
}
dir->pos += 1;
- LFS2_TRACE("lfs2_dir_read -> %d", true);
return true;
}
-int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
- LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")",
- (void*)lfs2, (void*)dir, off);
+static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
// simply walk from head dir
- int err = lfs2_dir_rewind(lfs2, dir);
+ int err = lfs2_dir_rawrewind(lfs2, dir);
if (err) {
- LFS2_TRACE("lfs2_dir_seek -> %d", err);
return err;
}
@@ -2148,13 +2219,11 @@ int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
if (dir->id == dir->m.count) {
if (!dir->m.split) {
- LFS2_TRACE("lfs2_dir_seek -> %d", LFS2_ERR_INVAL);
return LFS2_ERR_INVAL;
}
err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail);
if (err) {
- LFS2_TRACE("lfs2_dir_seek -> %d", err);
return err;
}
@@ -2162,29 +2231,23 @@ int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
}
}
- LFS2_TRACE("lfs2_dir_seek -> %d", 0);
return 0;
}
-lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) {
- LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir);
+static lfs2_soff_t lfs2_dir_rawtell(lfs2_t *lfs2, lfs2_dir_t *dir) {
(void)lfs2;
- LFS2_TRACE("lfs2_dir_tell -> %"PRId32, dir->pos);
return dir->pos;
}
-int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) {
- LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir);
+static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir) {
// reload the head dir
int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head);
if (err) {
- LFS2_TRACE("lfs2_dir_rewind -> %d", err);
return err;
}
dir->id = 0;
dir->pos = 0;
- LFS2_TRACE("lfs2_dir_rewind -> %d", 0);
return 0;
}
@@ -2237,6 +2300,7 @@ static int lfs2_ctz_find(lfs2_t *lfs2,
return 0;
}
+#ifndef LFS2_READONLY
static int lfs2_ctz_extend(lfs2_t *lfs2,
lfs2_cache_t *pcache, lfs2_cache_t *rcache,
lfs2_block_t head, lfs2_size_t size,
@@ -2334,6 +2398,7 @@ relocate:
lfs2_cache_drop(lfs2, pcache);
}
}
+#endif
static int lfs2_ctz_traverse(lfs2_t *lfs2,
const lfs2_cache_t *pcache, lfs2_cache_t *rcache,
@@ -2380,27 +2445,25 @@ static int lfs2_ctz_traverse(lfs2_t *lfs2,
/// Top level file operations ///
-int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
+static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file,
const char *path, int flags,
const struct lfs2_file_config *cfg) {
- LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {"
- ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
- (void*)lfs2, (void*)file, path, flags,
- (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
-
+#ifndef LFS2_READONLY
// deorphan if we haven't yet, needed at most once after poweron
- if ((flags & 3) != LFS2_O_RDONLY) {
+ if ((flags & LFS2_O_WRONLY) == LFS2_O_WRONLY) {
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
- LFS2_TRACE("lfs2_file_opencfg -> %d", err);
return err;
}
}
+#else
+ LFS2_ASSERT((flags & LFS2_O_RDONLY) == LFS2_O_RDONLY);
+#endif
// setup simple file details
int err;
file->cfg = cfg;
- file->flags = flags | LFS2_F_OPENED;
+ file->flags = flags;
file->pos = 0;
file->off = 0;
file->cache.buffer = NULL;
@@ -2414,9 +2477,13 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
// get id, add to list of mdirs to catch update changes
file->type = LFS2_TYPE_REG;
- file->next = (lfs2_file_t*)lfs2->mlist;
- lfs2->mlist = (struct lfs2_mlist*)file;
+ lfs2_mlist_append(lfs2, (struct lfs2_mlist *)file);
+#ifdef LFS2_READONLY
+ if (tag == LFS2_ERR_NOENT) {
+ err = LFS2_ERR_NOENT;
+ goto cleanup;
+#else
if (tag == LFS2_ERR_NOENT) {
if (!(flags & LFS2_O_CREAT)) {
err = LFS2_ERR_NOENT;
@@ -2432,9 +2499,9 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
// get next slot and create entry to remember name
err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS(
- {LFS2_MKTAG(LFS2_TYPE_CREATE, file->id, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, file->id, 0), NULL},
{LFS2_MKTAG(LFS2_TYPE_REG, file->id, nlen), path},
- {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0)}));
+ {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), NULL}));
if (err) {
err = LFS2_ERR_NAMETOOLONG;
goto cleanup;
@@ -2444,13 +2511,16 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
} else if (flags & LFS2_O_EXCL) {
err = LFS2_ERR_EXIST;
goto cleanup;
+#endif
} else if (lfs2_tag_type3(tag) != LFS2_TYPE_REG) {
err = LFS2_ERR_ISDIR;
goto cleanup;
+#ifndef LFS2_READONLY
} else if (flags & LFS2_O_TRUNC) {
// truncate if requested
tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0);
file->flags |= LFS2_F_DIRTY;
+#endif
} else {
// try to load what's on disk, if it's inlined we'll fix it later
tag = lfs2_dir_get(lfs2, &file->m, LFS2_MKTAG(0x700, 0x3ff, 0),
@@ -2464,7 +2534,8 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
// fetch attrs
for (unsigned i = 0; i < file->cfg->attr_count; i++) {
- if ((file->flags & 3) != LFS2_O_WRONLY) {
+ // if opened for read / read-write operations
+ if ((file->flags & LFS2_O_RDONLY) == LFS2_O_RDONLY) {
lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m,
LFS2_MKTAG(0x7ff, 0x3ff, 0),
LFS2_MKTAG(LFS2_TYPE_USERATTR + file->cfg->attrs[i].type,
@@ -2476,7 +2547,9 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
}
}
- if ((file->flags & 3) != LFS2_O_RDONLY) {
+#ifndef LFS2_READONLY
+ // if opened for write / read-write operations
+ if ((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY) {
if (file->cfg->attrs[i].size > lfs2->attr_max) {
err = LFS2_ERR_NOSPC;
goto cleanup;
@@ -2484,6 +2557,7 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
file->flags |= LFS2_F_DIRTY;
}
+#endif
}
// allocate buffer if needed
@@ -2523,54 +2597,45 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
}
}
- LFS2_TRACE("lfs2_file_opencfg -> %d", 0);
return 0;
cleanup:
// clean up lingering resources
+#ifndef LFS2_READONLY
file->flags |= LFS2_F_ERRED;
- lfs2_file_close(lfs2, file);
- LFS2_TRACE("lfs2_file_opencfg -> %d", err);
+#endif
+ lfs2_file_rawclose(lfs2, file);
return err;
}
-int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file,
+static int lfs2_file_rawopen(lfs2_t *lfs2, lfs2_file_t *file,
const char *path, int flags) {
- LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)",
- (void*)lfs2, (void*)file, path, flags);
static const struct lfs2_file_config defaults = {0};
- int err = lfs2_file_opencfg(lfs2, file, path, flags, &defaults);
- LFS2_TRACE("lfs2_file_open -> %d", err);
+ int err = lfs2_file_rawopencfg(lfs2, file, path, flags, &defaults);
return err;
}
-int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
-
- int err = lfs2_file_sync(lfs2, file);
+static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file) {
+#ifndef LFS2_READONLY
+ int err = lfs2_file_rawsync(lfs2, file);
+#else
+ int err = 0;
+#endif
// remove from list of mdirs
- for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) {
- if (*p == (struct lfs2_mlist*)file) {
- *p = (*p)->next;
- break;
- }
- }
+ lfs2_mlist_remove(lfs2, (struct lfs2_mlist*)file);
// clean up memory
if (!file->cfg->buffer) {
lfs2_free(file->cache.buffer);
}
- file->flags &= ~LFS2_F_OPENED;
- LFS2_TRACE("lfs2_file_close -> %d", err);
return err;
}
-static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+#ifndef LFS2_READONLY
+static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) {
while (true) {
// just relocate what exists into new block
lfs2_block_t nblock;
@@ -2638,7 +2703,9 @@ relocate:
lfs2_cache_drop(lfs2, &lfs2->pcache);
}
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) {
file->off = file->pos;
lfs2_alloc_ack(lfs2);
@@ -2650,10 +2717,10 @@ static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) {
file->flags &= ~LFS2_F_INLINE;
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
-
if (file->flags & LFS2_F_READING) {
if (!(file->flags & LFS2_F_INLINE)) {
lfs2_cache_drop(lfs2, &file->cache);
@@ -2669,7 +2736,7 @@ static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) {
lfs2_file_t orig = {
.ctz.head = file->ctz.head,
.ctz.size = file->ctz.size,
- .flags = LFS2_O_RDONLY | LFS2_F_OPENED,
+ .flags = LFS2_O_RDONLY,
.pos = file->pos,
.cache = lfs2->rcache,
};
@@ -2679,12 +2746,12 @@ static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) {
// copy over a byte at a time, leave it up to caching
// to make this efficient
uint8_t data;
- lfs2_ssize_t res = lfs2_file_read(lfs2, &orig, &data, 1);
+ lfs2_ssize_t res = lfs2_file_rawread(lfs2, &orig, &data, 1);
if (res < 0) {
return res;
}
- res = lfs2_file_write(lfs2, file, &data, 1);
+ res = lfs2_file_rawwrite(lfs2, file, &data, 1);
if (res < 0) {
return res;
}
@@ -2730,24 +2797,22 @@ relocate:
return 0;
}
+#endif
-int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
-
+#ifndef LFS2_READONLY
+static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) {
if (file->flags & LFS2_F_ERRED) {
// it's not safe to do anything if our file errored
- LFS2_TRACE("lfs2_file_sync -> %d", 0);
return 0;
}
int err = lfs2_file_flush(lfs2, file);
if (err) {
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_sync -> %d", err);
return err;
}
+
if ((file->flags & LFS2_F_DIRTY) &&
!lfs2_pair_isnull(file->m.pair)) {
// update dir entry
@@ -2777,39 +2842,35 @@ int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) {
file->cfg->attr_count), file->cfg->attrs}));
if (err) {
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_sync -> %d", err);
return err;
}
file->flags &= ~LFS2_F_DIRTY;
}
- LFS2_TRACE("lfs2_file_sync -> %d", 0);
return 0;
}
+#endif
-lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file,
void *buffer, lfs2_size_t size) {
- LFS2_TRACE("lfs2_file_read(%p, %p, %p, %"PRIu32")",
- (void*)lfs2, (void*)file, buffer, size);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
- LFS2_ASSERT((file->flags & 3) != LFS2_O_WRONLY);
+ LFS2_ASSERT((file->flags & LFS2_O_RDONLY) == LFS2_O_RDONLY);
uint8_t *data = buffer;
lfs2_size_t nsize = size;
+#ifndef LFS2_READONLY
if (file->flags & LFS2_F_WRITING) {
// flush out any writes
int err = lfs2_file_flush(lfs2, file);
if (err) {
- LFS2_TRACE("lfs2_file_read -> %d", err);
return err;
}
}
+#endif
if (file->pos >= file->ctz.size) {
// eof if past end
- LFS2_TRACE("lfs2_file_read -> %d", 0);
return 0;
}
@@ -2825,7 +2886,6 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
file->ctz.head, file->ctz.size,
file->pos, &file->block, &file->off);
if (err) {
- LFS2_TRACE("lfs2_file_read -> %d", err);
return err;
}
} else {
@@ -2845,7 +2905,6 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0),
file->off, data, diff);
if (err) {
- LFS2_TRACE("lfs2_file_read -> %d", err);
return err;
}
} else {
@@ -2853,7 +2912,6 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
NULL, &file->cache, lfs2->cfg->block_size,
file->block, file->off, data, diff);
if (err) {
- LFS2_TRACE("lfs2_file_read -> %d", err);
return err;
}
}
@@ -2864,16 +2922,13 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
nsize -= diff;
}
- LFS2_TRACE("lfs2_file_read -> %"PRId32, size);
return size;
}
-lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
+#ifndef LFS2_READONLY
+static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file,
const void *buffer, lfs2_size_t size) {
- LFS2_TRACE("lfs2_file_write(%p, %p, %p, %"PRIu32")",
- (void*)lfs2, (void*)file, buffer, size);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
- LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY);
+ LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY);
const uint8_t *data = buffer;
lfs2_size_t nsize = size;
@@ -2882,7 +2937,6 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
// drop any reads
int err = lfs2_file_flush(lfs2, file);
if (err) {
- LFS2_TRACE("lfs2_file_write -> %d", err);
return err;
}
}
@@ -2893,7 +2947,6 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
if (file->pos + size > lfs2->file_max) {
// Larger than file limit?
- LFS2_TRACE("lfs2_file_write -> %d", LFS2_ERR_FBIG);
return LFS2_ERR_FBIG;
}
@@ -2903,9 +2956,8 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
file->pos = file->ctz.size;
while (file->pos < pos) {
- lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1);
+ lfs2_ssize_t res = lfs2_file_rawwrite(lfs2, file, &(uint8_t){0}, 1);
if (res < 0) {
- LFS2_TRACE("lfs2_file_write -> %"PRId32, res);
return res;
}
}
@@ -2919,7 +2971,6 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
int err = lfs2_file_outline(lfs2, file);
if (err) {
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_write -> %d", err);
return err;
}
}
@@ -2936,7 +2987,6 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
file->pos-1, &file->block, &file->off);
if (err) {
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_write -> %d", err);
return err;
}
@@ -2951,7 +3001,6 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
&file->block, &file->off);
if (err) {
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_write -> %d", err);
return err;
}
} else {
@@ -2972,7 +3021,6 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
goto relocate;
}
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_write -> %d", err);
return err;
}
@@ -2981,7 +3029,6 @@ relocate:
err = lfs2_file_relocate(lfs2, file);
if (err) {
file->flags |= LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_write -> %d", err);
return err;
}
}
@@ -2995,22 +3042,19 @@ relocate:
}
file->flags &= ~LFS2_F_ERRED;
- LFS2_TRACE("lfs2_file_write -> %"PRId32, size);
return size;
}
+#endif
-lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file,
lfs2_soff_t off, int whence) {
- LFS2_TRACE("lfs2_file_seek(%p, %p, %"PRId32", %d)",
- (void*)lfs2, (void*)file, off, whence);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
-
+#ifndef LFS2_READONLY
// write out everything beforehand, may be noop if rdonly
int err = lfs2_file_flush(lfs2, file);
if (err) {
- LFS2_TRACE("lfs2_file_seek -> %d", err);
return err;
}
+#endif
// find new pos
lfs2_off_t npos = file->pos;
@@ -3024,34 +3068,28 @@ lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
if (npos > lfs2->file_max) {
// file position out of range
- LFS2_TRACE("lfs2_file_seek -> %d", LFS2_ERR_INVAL);
return LFS2_ERR_INVAL;
}
// update pos
file->pos = npos;
- LFS2_TRACE("lfs2_file_seek -> %"PRId32, npos);
return npos;
}
-int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
- LFS2_TRACE("lfs2_file_truncate(%p, %p, %"PRIu32")",
- (void*)lfs2, (void*)file, size);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
- LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY);
+#ifndef LFS2_READONLY
+static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
+ LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY);
if (size > LFS2_FILE_MAX) {
- LFS2_TRACE("lfs2_file_truncate -> %d", LFS2_ERR_INVAL);
return LFS2_ERR_INVAL;
}
lfs2_off_t pos = file->pos;
- lfs2_off_t oldsize = lfs2_file_size(lfs2, file);
+ lfs2_off_t oldsize = lfs2_file_rawsize(lfs2, file);
if (size < oldsize) {
// need to flush since directly changing metadata
int err = lfs2_file_flush(lfs2, file);
if (err) {
- LFS2_TRACE("lfs2_file_truncate -> %d", err);
return err;
}
@@ -3060,7 +3098,6 @@ int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
file->ctz.head, file->ctz.size,
size, &file->block, &file->off);
if (err) {
- LFS2_TRACE("lfs2_file_truncate -> %d", err);
return err;
}
@@ -3070,97 +3107,80 @@ int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
} else if (size > oldsize) {
// flush+seek if not already at end
if (file->pos != oldsize) {
- lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END);
+ lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_END);
if (res < 0) {
- LFS2_TRACE("lfs2_file_truncate -> %"PRId32, res);
return (int)res;
}
}
// fill with zeros
while (file->pos < size) {
- lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1);
+ lfs2_ssize_t res = lfs2_file_rawwrite(lfs2, file, &(uint8_t){0}, 1);
if (res < 0) {
- LFS2_TRACE("lfs2_file_truncate -> %"PRId32, res);
return (int)res;
}
}
}
// restore pos
- lfs2_soff_t res = lfs2_file_seek(lfs2, file, pos, LFS2_SEEK_SET);
+ lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, pos, LFS2_SEEK_SET);
if (res < 0) {
- LFS2_TRACE("lfs2_file_truncate -> %"PRId32, res);
return (int)res;
}
- LFS2_TRACE("lfs2_file_truncate -> %d", 0);
return 0;
}
+#endif
-lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+static lfs2_soff_t lfs2_file_rawtell(lfs2_t *lfs2, lfs2_file_t *file) {
(void)lfs2;
- LFS2_TRACE("lfs2_file_tell -> %"PRId32, file->pos);
return file->pos;
}
-int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file);
- lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET);
+static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) {
+ lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET);
if (res < 0) {
- LFS2_TRACE("lfs2_file_rewind -> %"PRId32, res);
return (int)res;
}
- LFS2_TRACE("lfs2_file_rewind -> %d", 0);
return 0;
}
-lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) {
- LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file);
- LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) {
(void)lfs2;
+
+#ifndef LFS2_READONLY
if (file->flags & LFS2_F_WRITING) {
- LFS2_TRACE("lfs2_file_size -> %"PRId32,
- lfs2_max(file->pos, file->ctz.size));
return lfs2_max(file->pos, file->ctz.size);
- } else {
- LFS2_TRACE("lfs2_file_size -> %"PRId32, file->ctz.size);
- return file->ctz.size;
}
+#endif
+
+ return file->ctz.size;
}
/// General fs operations ///
-int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
- LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info);
+static int lfs2_rawstat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
lfs2_mdir_t cwd;
lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
if (tag < 0) {
- LFS2_TRACE("lfs2_stat -> %"PRId32, tag);
return (int)tag;
}
- int err = lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info);
- LFS2_TRACE("lfs2_stat -> %d", err);
- return err;
+ return lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info);
}
-int lfs2_remove(lfs2_t *lfs2, const char *path) {
- LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path);
+#ifndef LFS2_READONLY
+static int lfs2_rawremove(lfs2_t *lfs2, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
- LFS2_TRACE("lfs2_remove -> %d", err);
return err;
}
lfs2_mdir_t cwd;
lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
if (tag < 0 || lfs2_tag_id(tag) == 0x3ff) {
- LFS2_TRACE("lfs2_remove -> %"PRId32, (tag < 0) ? tag : LFS2_ERR_INVAL);
return (tag < 0) ? (int)tag : LFS2_ERR_INVAL;
}
@@ -3172,19 +3192,16 @@ int lfs2_remove(lfs2_t *lfs2, const char *path) {
lfs2_stag_t res = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x700, 0x3ff, 0),
LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair);
if (res < 0) {
- LFS2_TRACE("lfs2_remove -> %"PRId32, res);
return (int)res;
}
lfs2_pair_fromle32(pair);
err = lfs2_dir_fetch(lfs2, &dir.m, pair);
if (err) {
- LFS2_TRACE("lfs2_remove -> %d", err);
return err;
}
if (dir.m.count > 0 || dir.m.split) {
- LFS2_TRACE("lfs2_remove -> %d", LFS2_ERR_NOTEMPTY);
return LFS2_ERR_NOTEMPTY;
}
@@ -3200,10 +3217,9 @@ int lfs2_remove(lfs2_t *lfs2, const char *path) {
// delete the entry
err = lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS(
- {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(tag), 0)}));
+ {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(tag), 0), NULL}));
if (err) {
lfs2->mlist = dir.next;
- LFS2_TRACE("lfs2_remove -> %d", err);
return err;
}
@@ -3214,28 +3230,24 @@ int lfs2_remove(lfs2_t *lfs2, const char *path) {
err = lfs2_fs_pred(lfs2, dir.m.pair, &cwd);
if (err) {
- LFS2_TRACE("lfs2_remove -> %d", err);
return err;
}
err = lfs2_dir_drop(lfs2, &cwd, &dir.m);
if (err) {
- LFS2_TRACE("lfs2_remove -> %d", err);
return err;
}
}
- LFS2_TRACE("lfs2_remove -> %d", 0);
return 0;
}
+#endif
-int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
- LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath);
-
+#ifndef LFS2_READONLY
+static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
- LFS2_TRACE("lfs2_rename -> %d", err);
return err;
}
@@ -3243,8 +3255,6 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
lfs2_mdir_t oldcwd;
lfs2_stag_t oldtag = lfs2_dir_find(lfs2, &oldcwd, &oldpath, NULL);
if (oldtag < 0 || lfs2_tag_id(oldtag) == 0x3ff) {
- LFS2_TRACE("lfs2_rename -> %"PRId32,
- (oldtag < 0) ? oldtag : LFS2_ERR_INVAL);
return (oldtag < 0) ? (int)oldtag : LFS2_ERR_INVAL;
}
@@ -3254,8 +3264,6 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid);
if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) &&
!(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) {
- LFS2_TRACE("lfs2_rename -> %"PRId32,
- (prevtag < 0) ? prevtag : LFS2_ERR_INVAL);
return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL;
}
@@ -3269,7 +3277,6 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
// check that name fits
lfs2_size_t nlen = strlen(newpath);
if (nlen > lfs2->name_max) {
- LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NAMETOOLONG);
return LFS2_ERR_NAMETOOLONG;
}
@@ -3280,11 +3287,9 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
newoldid += 1;
}
} else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) {
- LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_ISDIR);
return LFS2_ERR_ISDIR;
} else if (samepair && newid == newoldid) {
// we're renaming to ourselves??
- LFS2_TRACE("lfs2_rename -> %d", 0);
return 0;
} else if (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) {
// must be empty before removal
@@ -3292,7 +3297,6 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
lfs2_stag_t res = lfs2_dir_get(lfs2, &newcwd, LFS2_MKTAG(0x700, 0x3ff, 0),
LFS2_MKTAG(LFS2_TYPE_STRUCT, newid, 8), prevpair);
if (res < 0) {
- LFS2_TRACE("lfs2_rename -> %"PRId32, res);
return (int)res;
}
lfs2_pair_fromle32(prevpair);
@@ -3300,12 +3304,10 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
// must be empty before removal
err = lfs2_dir_fetch(lfs2, &prevdir.m, prevpair);
if (err) {
- LFS2_TRACE("lfs2_rename -> %d", err);
return err;
}
if (prevdir.m.count > 0 || prevdir.m.split) {
- LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NOTEMPTY);
return LFS2_ERR_NOTEMPTY;
}
@@ -3326,15 +3328,14 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
// move over all attributes
err = lfs2_dir_commit(lfs2, &newcwd, LFS2_MKATTRS(
{LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT,
- LFS2_TYPE_DELETE, newid, 0)},
- {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0)},
+ LFS2_TYPE_DELETE, newid, 0), NULL},
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL},
{LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath},
{LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd},
{LFS2_MKTAG_IF(samepair,
- LFS2_TYPE_DELETE, newoldid, 0)}));
+ LFS2_TYPE_DELETE, newoldid, 0), NULL}));
if (err) {
lfs2->mlist = prevdir.next;
- LFS2_TRACE("lfs2_rename -> %d", err);
return err;
}
@@ -3344,10 +3345,9 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
// prep gstate and delete move id
lfs2_fs_prepmove(lfs2, 0x3ff, NULL);
err = lfs2_dir_commit(lfs2, &oldcwd, LFS2_MKATTRS(
- {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(oldtag), 0)}));
+ {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(oldtag), 0), NULL}));
if (err) {
lfs2->mlist = prevdir.next;
- LFS2_TRACE("lfs2_rename -> %d", err);
return err;
}
}
@@ -3359,29 +3359,24 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
err = lfs2_fs_pred(lfs2, prevdir.m.pair, &newcwd);
if (err) {
- LFS2_TRACE("lfs2_rename -> %d", err);
return err;
}
err = lfs2_dir_drop(lfs2, &newcwd, &prevdir.m);
if (err) {
- LFS2_TRACE("lfs2_rename -> %d", err);
return err;
}
}
- LFS2_TRACE("lfs2_rename -> %d", 0);
return 0;
}
+#endif
-lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
+static lfs2_ssize_t lfs2_rawgetattr(lfs2_t *lfs2, const char *path,
uint8_t type, void *buffer, lfs2_size_t size) {
- LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
- (void*)lfs2, path, type, buffer, size);
lfs2_mdir_t cwd;
lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
if (tag < 0) {
- LFS2_TRACE("lfs2_getattr -> %"PRId32, tag);
return tag;
}
@@ -3391,7 +3386,6 @@ lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
id = 0;
int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root);
if (err) {
- LFS2_TRACE("lfs2_getattr -> %d", err);
return err;
}
}
@@ -3402,19 +3396,16 @@ lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
buffer);
if (tag < 0) {
if (tag == LFS2_ERR_NOENT) {
- LFS2_TRACE("lfs2_getattr -> %d", LFS2_ERR_NOATTR);
return LFS2_ERR_NOATTR;
}
- LFS2_TRACE("lfs2_getattr -> %"PRId32, tag);
return tag;
}
- size = lfs2_tag_size(tag);
- LFS2_TRACE("lfs2_getattr -> %"PRId32, size);
- return size;
+ return lfs2_tag_size(tag);
}
+#ifndef LFS2_READONLY
static int lfs2_commitattr(lfs2_t *lfs2, const char *path,
uint8_t type, const void *buffer, lfs2_size_t size) {
lfs2_mdir_t cwd;
@@ -3436,27 +3427,24 @@ static int lfs2_commitattr(lfs2_t *lfs2, const char *path,
return lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS(
{LFS2_MKTAG(LFS2_TYPE_USERATTR + type, id, size), buffer}));
}
+#endif
-int lfs2_setattr(lfs2_t *lfs2, const char *path,
+#ifndef LFS2_READONLY
+static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path,
uint8_t type, const void *buffer, lfs2_size_t size) {
- LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
- (void*)lfs2, path, type, buffer, size);
if (size > lfs2->attr_max) {
- LFS2_TRACE("lfs2_setattr -> %d", LFS2_ERR_NOSPC);
return LFS2_ERR_NOSPC;
}
- int err = lfs2_commitattr(lfs2, path, type, buffer, size);
- LFS2_TRACE("lfs2_setattr -> %d", err);
- return err;
+ return lfs2_commitattr(lfs2, path, type, buffer, size);
}
+#endif
-int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) {
- LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type);
- int err = lfs2_commitattr(lfs2, path, type, NULL, 0x3ff);
- LFS2_TRACE("lfs2_removeattr -> %d", err);
- return err;
+#ifndef LFS2_READONLY
+static int lfs2_rawremoveattr(lfs2_t *lfs2, const char *path, uint8_t type) {
+ return lfs2_commitattr(lfs2, path, type, NULL, 0x3ff);
}
+#endif
/// Filesystem operations ///
@@ -3584,28 +3572,12 @@ static int lfs2_deinit(lfs2_t *lfs2) {
return 0;
}
-int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
- LFS2_TRACE("lfs2_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*)lfs2, (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 LFS2_READONLY
+static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) {
int err = 0;
{
err = lfs2_init(lfs2, cfg);
if (err) {
- LFS2_TRACE("lfs2_format -> %d", err);
return err;
}
@@ -3636,7 +3608,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
lfs2_superblock_tole32(&superblock);
err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS(
- {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0), NULL},
{LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"},
{LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock}));
@@ -3661,30 +3633,14 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
cleanup:
lfs2_deinit(lfs2);
- LFS2_TRACE("lfs2_format -> %d", err);
return err;
+
}
+#endif
-int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
- LFS2_TRACE("lfs2_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*)lfs2, (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 lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
int err = lfs2_init(lfs2, cfg);
if (err) {
- LFS2_TRACE("lfs2_mount -> %d", err);
return err;
}
@@ -3797,28 +3753,25 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
lfs2->gstate.tag += !lfs2_tag_isvalid(lfs2->gstate.tag);
lfs2->gdisk = lfs2->gstate;
- // setup free lookahead
- lfs2_alloc_reset(lfs2);
+ // setup free lookahead, to distribute allocations uniformly across
+ // boots, we start the allocator at a random location
+ lfs2->free.off = lfs2->seed % lfs2->cfg->block_count;
+ lfs2_alloc_drop(lfs2);
- LFS2_TRACE("lfs2_mount -> %d", 0);
return 0;
cleanup:
- lfs2_unmount(lfs2);
- LFS2_TRACE("lfs2_mount -> %d", err);
+ lfs2_rawunmount(lfs2);
return err;
}
-int lfs2_unmount(lfs2_t *lfs2) {
- LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2);
- int err = lfs2_deinit(lfs2);
- LFS2_TRACE("lfs2_unmount -> %d", err);
- return err;
+static int lfs2_rawunmount(lfs2_t *lfs2) {
+ return lfs2_deinit(lfs2);
}
/// Filesystem filesystem operations ///
-int lfs2_fs_traverseraw(lfs2_t *lfs2,
+int lfs2_fs_rawtraverse(lfs2_t *lfs2,
int (*cb)(void *data, lfs2_block_t block), void *data,
bool includeorphans) {
// iterate over metadata pairs
@@ -3888,6 +3841,7 @@ int lfs2_fs_traverseraw(lfs2_t *lfs2,
}
}
+#ifndef LFS2_READONLY
// iterate over any open files
for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) {
if (f->type != LFS2_TYPE_REG) {
@@ -3910,19 +3864,12 @@ int lfs2_fs_traverseraw(lfs2_t *lfs2,
}
}
}
+#endif
return 0;
}
-int lfs2_fs_traverse(lfs2_t *lfs2,
- int (*cb)(void *data, lfs2_block_t block), void *data) {
- LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)",
- (void*)lfs2, (void*)(uintptr_t)cb, data);
- int err = lfs2_fs_traverseraw(lfs2, cb, data, true);
- LFS2_TRACE("lfs2_fs_traverse -> %d", 0);
- return err;
-}
-
+#ifndef LFS2_READONLY
static int lfs2_fs_pred(lfs2_t *lfs2,
const lfs2_block_t pair[2], lfs2_mdir_t *pdir) {
// iterate over all directory directory entries
@@ -3948,12 +3895,16 @@ static int lfs2_fs_pred(lfs2_t *lfs2,
return LFS2_ERR_NOENT;
}
+#endif
+#ifndef LFS2_READONLY
struct lfs2_fs_parent_match {
lfs2_t *lfs2;
const lfs2_block_t pair[2];
};
+#endif
+#ifndef LFS2_READONLY
static int lfs2_fs_parent_match(void *data,
lfs2_tag_t tag, const void *buffer) {
struct lfs2_fs_parent_match *find = data;
@@ -3972,7 +3923,9 @@ static int lfs2_fs_parent_match(void *data,
lfs2_pair_fromle32(child);
return (lfs2_pair_cmp(child, find->pair) == 0) ? LFS2_CMP_EQ : LFS2_CMP_LT;
}
+#endif
+#ifndef LFS2_READONLY
static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2],
lfs2_mdir_t *parent) {
// use fetchmatch with callback to find pairs
@@ -3999,7 +3952,9 @@ static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2],
return LFS2_ERR_NOENT;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_fs_relocate(lfs2_t *lfs2,
const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]) {
// update internal root
@@ -4050,7 +4005,7 @@ static int lfs2_fs_relocate(lfs2_t *lfs2,
lfs2_pair_tole32(newpair);
int err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS(
{LFS2_MKTAG_IF(moveid != 0x3ff,
- LFS2_TYPE_DELETE, moveid, 0)},
+ LFS2_TYPE_DELETE, moveid, 0), NULL},
{tag, newpair}));
lfs2_pair_fromle32(newpair);
if (err) {
@@ -4084,7 +4039,7 @@ static int lfs2_fs_relocate(lfs2_t *lfs2,
lfs2_pair_tole32(newpair);
err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS(
{LFS2_MKTAG_IF(moveid != 0x3ff,
- LFS2_TYPE_DELETE, moveid, 0)},
+ LFS2_TYPE_DELETE, moveid, 0), NULL},
{LFS2_MKTAG(LFS2_TYPE_TAIL + parent.split, 0x3ff, 8), newpair}));
lfs2_pair_fromle32(newpair);
if (err) {
@@ -4094,14 +4049,18 @@ static int lfs2_fs_relocate(lfs2_t *lfs2,
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans) {
LFS2_ASSERT(lfs2_tag_size(lfs2->gstate.tag) > 0 || orphans >= 0);
lfs2->gstate.tag += orphans;
lfs2->gstate.tag = ((lfs2->gstate.tag & ~LFS2_MKTAG(0x800, 0, 0)) |
((uint32_t)lfs2_gstate_hasorphans(&lfs2->gstate) << 31));
}
+#endif
+#ifndef LFS2_READONLY
static void lfs2_fs_prepmove(lfs2_t *lfs2,
uint16_t id, const lfs2_block_t pair[2]) {
lfs2->gstate.tag = ((lfs2->gstate.tag & ~LFS2_MKTAG(0x7ff, 0x3ff, 0)) |
@@ -4109,7 +4068,9 @@ static void lfs2_fs_prepmove(lfs2_t *lfs2,
lfs2->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0;
lfs2->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_fs_demove(lfs2_t *lfs2) {
if (!lfs2_gstate_hasmove(&lfs2->gdisk)) {
return 0;
@@ -4132,14 +4093,16 @@ static int lfs2_fs_demove(lfs2_t *lfs2) {
uint16_t moveid = lfs2_tag_id(lfs2->gdisk.tag);
lfs2_fs_prepmove(lfs2, 0x3ff, NULL);
err = lfs2_dir_commit(lfs2, &movedir, LFS2_MKATTRS(
- {LFS2_MKTAG(LFS2_TYPE_DELETE, moveid, 0)}));
+ {LFS2_MKTAG(LFS2_TYPE_DELETE, moveid, 0), NULL}));
if (err) {
return err;
}
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_fs_deorphan(lfs2_t *lfs2) {
if (!lfs2_gstate_hasorphans(&lfs2->gstate)) {
return 0;
@@ -4213,7 +4176,9 @@ static int lfs2_fs_deorphan(lfs2_t *lfs2) {
lfs2_fs_preporphans(lfs2, -lfs2_gstate_getorphans(&lfs2->gstate));
return 0;
}
+#endif
+#ifndef LFS2_READONLY
static int lfs2_fs_forceconsistency(lfs2_t *lfs2) {
int err = lfs2_fs_demove(lfs2);
if (err) {
@@ -4227,6 +4192,7 @@ static int lfs2_fs_forceconsistency(lfs2_t *lfs2) {
return 0;
}
+#endif
static int lfs2_fs_size_count(void *p, lfs2_block_t block) {
(void)block;
@@ -4235,16 +4201,13 @@ static int lfs2_fs_size_count(void *p, lfs2_block_t block) {
return 0;
}
-lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) {
- LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2);
+static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) {
lfs2_size_t size = 0;
- int err = lfs2_fs_traverseraw(lfs2, lfs2_fs_size_count, &size, false);
+ int err = lfs2_fs_rawtraverse(lfs2, lfs2_fs_size_count, &size, false);
if (err) {
- LFS2_TRACE("lfs2_fs_size -> %d", err);
return err;
}
- LFS2_TRACE("lfs2_fs_size -> %d", err);
return size;
}
@@ -4669,27 +4632,10 @@ static int lfs21_unmount(lfs2_t *lfs2) {
}
/// v1 migration ///
-int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
- LFS2_TRACE("lfs2_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*)lfs2, (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 lfs2_rawmigrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
struct lfs21 lfs21;
int err = lfs21_mount(lfs2, &lfs21, cfg);
if (err) {
- LFS2_TRACE("lfs2_migrate -> %d", err);
return err;
}
@@ -4906,8 +4852,539 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
cleanup:
lfs21_unmount(lfs2);
- LFS2_TRACE("lfs2_migrate -> %d", err);
return err;
}
#endif
+
+
+/// Public API wrappers ///
+
+// Here we can add tracing/thread safety easily
+
+// Thread-safe wrappers if enabled
+#ifdef LFS2_THREADSAFE
+#define LFS2_LOCK(cfg) cfg->lock(cfg)
+#define LFS2_UNLOCK(cfg) cfg->unlock(cfg)
+#else
+#define LFS2_LOCK(cfg) ((void)cfg, 0)
+#define LFS2_UNLOCK(cfg) ((void)cfg)
+#endif
+
+// Public API
+#ifndef LFS2_READONLY
+int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ int err = LFS2_LOCK(cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_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*)lfs2, (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 = lfs2_rawformat(lfs2, cfg);
+
+ LFS2_TRACE("lfs2_format -> %d", err);
+ LFS2_UNLOCK(cfg);
+ return err;
+}
+#endif
+
+int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ int err = LFS2_LOCK(cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_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*)lfs2, (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 = lfs2_rawmount(lfs2, cfg);
+
+ LFS2_TRACE("lfs2_mount -> %d", err);
+ LFS2_UNLOCK(cfg);
+ return err;
+}
+
+int lfs2_unmount(lfs2_t *lfs2) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2);
+
+ err = lfs2_rawunmount(lfs2);
+
+ LFS2_TRACE("lfs2_unmount -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+#ifndef LFS2_READONLY
+int lfs2_remove(lfs2_t *lfs2, const char *path) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path);
+
+ err = lfs2_rawremove(lfs2, path);
+
+ LFS2_TRACE("lfs2_remove -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+#ifndef LFS2_READONLY
+int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath);
+
+ err = lfs2_rawrename(lfs2, oldpath, newpath);
+
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info);
+
+ err = lfs2_rawstat(lfs2, path, info);
+
+ LFS2_TRACE("lfs2_stat -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, void *buffer, lfs2_size_t size) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
+ (void*)lfs2, path, type, buffer, size);
+
+ lfs2_ssize_t res = lfs2_rawgetattr(lfs2, path, type, buffer, size);
+
+ LFS2_TRACE("lfs2_getattr -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+#ifndef LFS2_READONLY
+int lfs2_setattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, const void *buffer, lfs2_size_t size) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
+ (void*)lfs2, path, type, buffer, size);
+
+ err = lfs2_rawsetattr(lfs2, path, type, buffer, size);
+
+ LFS2_TRACE("lfs2_setattr -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+#ifndef LFS2_READONLY
+int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type);
+
+ err = lfs2_rawremoveattr(lfs2, path, type);
+
+ LFS2_TRACE("lfs2_removeattr -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)",
+ (void*)lfs2, (void*)file, path, flags);
+ LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ err = lfs2_file_rawopen(lfs2, file, path, flags);
+
+ LFS2_TRACE("lfs2_file_open -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
+ const char *path, int flags,
+ const struct lfs2_file_config *cfg) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {"
+ ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
+ (void*)lfs2, (void*)file, path, flags,
+ (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
+ LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ err = lfs2_file_rawopencfg(lfs2, file, path, flags, cfg);
+
+ LFS2_TRACE("lfs2_file_opencfg -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ err = lfs2_file_rawclose(lfs2, file);
+
+ LFS2_TRACE("lfs2_file_close -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+#ifndef LFS2_READONLY
+int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ err = lfs2_file_rawsync(lfs2, file);
+
+ LFS2_TRACE("lfs2_file_sync -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
+ void *buffer, lfs2_size_t size) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_read(%p, %p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)file, buffer, size);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ lfs2_ssize_t res = lfs2_file_rawread(lfs2, file, buffer, size);
+
+ LFS2_TRACE("lfs2_file_read -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+#ifndef LFS2_READONLY
+lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
+ const void *buffer, lfs2_size_t size) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_write(%p, %p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)file, buffer, size);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ lfs2_ssize_t res = lfs2_file_rawwrite(lfs2, file, buffer, size);
+
+ LFS2_TRACE("lfs2_file_write -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+#endif
+
+lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
+ lfs2_soff_t off, int whence) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_seek(%p, %p, %"PRId32", %d)",
+ (void*)lfs2, (void*)file, off, whence);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, off, whence);
+
+ LFS2_TRACE("lfs2_file_seek -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+#ifndef LFS2_READONLY
+int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_truncate(%p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)file, size);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ err = lfs2_file_rawtruncate(lfs2, file, size);
+
+ LFS2_TRACE("lfs2_file_truncate -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ lfs2_soff_t res = lfs2_file_rawtell(lfs2, file);
+
+ LFS2_TRACE("lfs2_file_tell -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file);
+
+ err = lfs2_file_rawrewind(lfs2, file);
+
+ LFS2_TRACE("lfs2_file_rewind -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
+
+ lfs2_soff_t res = lfs2_file_rawsize(lfs2, file);
+
+ LFS2_TRACE("lfs2_file_size -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+#ifndef LFS2_READONLY
+int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path);
+
+ err = lfs2_rawmkdir(lfs2, path);
+
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+#endif
+
+int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path);
+ LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)dir));
+
+ err = lfs2_dir_rawopen(lfs2, dir, path);
+
+ LFS2_TRACE("lfs2_dir_open -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir);
+
+ err = lfs2_dir_rawclose(lfs2, dir);
+
+ LFS2_TRACE("lfs2_dir_close -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_dir_read(%p, %p, %p)",
+ (void*)lfs2, (void*)dir, (void*)info);
+
+ err = lfs2_dir_rawread(lfs2, dir, info);
+
+ LFS2_TRACE("lfs2_dir_read -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)dir, off);
+
+ err = lfs2_dir_rawseek(lfs2, dir, off);
+
+ LFS2_TRACE("lfs2_dir_seek -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir);
+
+ lfs2_soff_t res = lfs2_dir_rawtell(lfs2, dir);
+
+ LFS2_TRACE("lfs2_dir_tell -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir);
+
+ err = lfs2_dir_rawrewind(lfs2, dir);
+
+ LFS2_TRACE("lfs2_dir_rewind -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2);
+
+ lfs2_ssize_t res = lfs2_fs_rawsize(lfs2);
+
+ LFS2_TRACE("lfs2_fs_size -> %"PRId32, res);
+ LFS2_UNLOCK(lfs2->cfg);
+ return res;
+}
+
+int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data) {
+ int err = LFS2_LOCK(lfs2->cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)",
+ (void*)lfs2, (void*)(uintptr_t)cb, data);
+
+ err = lfs2_fs_rawtraverse(lfs2, cb, data, true);
+
+ LFS2_TRACE("lfs2_fs_traverse -> %d", err);
+ LFS2_UNLOCK(lfs2->cfg);
+ return err;
+}
+
+#ifdef LFS2_MIGRATE
+int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ int err = LFS2_LOCK(cfg);
+ if (err) {
+ return err;
+ }
+ LFS2_TRACE("lfs2_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*)lfs2, (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 = lfs2_rawmigrate(lfs2, cfg);
+
+ LFS2_TRACE("lfs2_migrate -> %d", err);
+ LFS2_UNLOCK(cfg);
+ return err;
+}
+#endif
+
diff --git a/lib/littlefs/lfs2.h b/lib/littlefs/lfs2.h
index c89af79cab..e2afc7792c 100644
--- a/lib/littlefs/lfs2.h
+++ b/lib/littlefs/lfs2.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "lfs2_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 LFS2_VERSION 0x00020002
+#define LFS2_VERSION 0x00020003
#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
@@ -123,20 +124,25 @@ enum lfs2_type {
enum lfs2_open_flags {
// open flags
LFS2_O_RDONLY = 1, // Open a file as read only
+#ifndef LFS2_READONLY
LFS2_O_WRONLY = 2, // Open a file as write only
LFS2_O_RDWR = 3, // Open a file as read and write
LFS2_O_CREAT = 0x0100, // Create a file if it does not exist
LFS2_O_EXCL = 0x0200, // Fail if a file already exists
LFS2_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS2_O_APPEND = 0x0800, // Move to end of file on every write
+#endif
// internally used flags
+#ifndef LFS2_READONLY
LFS2_F_DIRTY = 0x010000, // File does not match storage
LFS2_F_WRITING = 0x020000, // File has been written since last flush
+#endif
LFS2_F_READING = 0x040000, // File has been read since last flush
- LFS2_F_ERRED = 0x080000, // An error occured during write
+#ifndef LFS2_READONLY
+ LFS2_F_ERRED = 0x080000, // An error occurred during write
+#endif
LFS2_F_INLINE = 0x100000, // Currently inlined in directory entry
- LFS2_F_OPENED = 0x200000, // File has been opened
};
// File seek flags
@@ -174,6 +180,16 @@ struct lfs2_config {
// are propogated to the user.
int (*sync)(const struct lfs2_config *c);
+#ifdef LFS2_THREADSAFE
+ // Lock the underlying block device. Negative error codes
+ // are propogated to the user.
+ int (*lock)(const struct lfs2_config *c);
+
+ // Unlock the underlying block device. Negative error codes
+ // are propogated to the user.
+ int (*unlock)(const struct lfs2_config *c);
+#endif
+
// Minimum size of a block read. All read operations will be a
// multiple of this value.
lfs2_size_t read_size;
@@ -399,6 +415,7 @@ typedef struct lfs2 {
/// Filesystem functions ///
+#ifndef LFS2_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 lfs2 {
//
// Returns a negative error code on failure.
int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *config);
+#endif
// Mounts a littlefs
//
@@ -426,12 +444,15 @@ int lfs2_unmount(lfs2_t *lfs2);
/// General operations ///
+#ifndef LFS2_READONLY
// Removes a file or directory
//
// If removing a directory, the directory must be empty.
// Returns a negative error code on failure.
int lfs2_remove(lfs2_t *lfs2, const char *path);
+#endif
+#ifndef LFS2_READONLY
// Rename or move a file or directory
//
// If the destination exists, it must match the source in type.
@@ -439,6 +460,7 @@ int lfs2_remove(lfs2_t *lfs2, const char *path);
//
// Returns a negative error code on failure.
int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath);
+#endif
// Find info about a file or directory
//
@@ -461,6 +483,7 @@ int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info);
lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
uint8_t type, void *buffer, lfs2_size_t size);
+#ifndef LFS2_READONLY
// Set custom attributes
//
// Custom attributes are uniquely identified by an 8-bit type and limited
@@ -470,13 +493,16 @@ lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
// Returns a negative error code on failure.
int lfs2_setattr(lfs2_t *lfs2, const char *path,
uint8_t type, const void *buffer, lfs2_size_t size);
+#endif
+#ifndef LFS2_READONLY
// Removes a custom attribute
//
// If an attribute is not found, nothing happens.
//
// Returns a negative error code on failure.
int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type);
+#endif
/// File operations ///
@@ -525,6 +551,7 @@ int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file);
lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
void *buffer, lfs2_size_t size);
+#ifndef LFS2_READONLY
// Write data to file
//
// Takes a buffer and size indicating the data to write. The file will not
@@ -533,6 +560,7 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
// Returns the number of bytes written, or a negative error code on failure.
lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
const void *buffer, lfs2_size_t size);
+#endif
// Change the position of the file
//
@@ -541,10 +569,12 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
lfs2_soff_t off, int whence);
+#ifndef LFS2_READONLY
// Truncates the size of the file to the specified size
//
// Returns a negative error code on failure.
int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size);
+#endif
// Return the position of the file
//
@@ -567,10 +597,12 @@ lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file);
/// Directory operations ///
+#ifndef LFS2_READONLY
// Create a directory
//
// Returns a negative error code on failure.
int lfs2_mkdir(lfs2_t *lfs2, const char *path);
+#endif
// Open a directory
//
@@ -632,6 +664,7 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2);
// Returns a negative error code on failure.
int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data);
+#ifndef LFS2_READONLY
#ifdef LFS2_MIGRATE
// Attempts to migrate a previous version of littlefs
//
@@ -646,6 +679,7 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data);
// Returns a negative error code on failure.
int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg);
#endif
+#endif
#ifdef __cplusplus