|
|
@@ -118,28 +118,25 @@ 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 += diff) {
|
|
|
- uint8_t dat[8];
|
|
|
-
|
|
|
- diff = lfs_min(size-i, sizeof(dat));
|
|
|
- int res = lfs_bd_read(lfs,
|
|
|
+ for (lfs_off_t i = 0; i < size; i++) {
|
|
|
+ uint8_t dat;
|
|
|
+ int err = lfs_bd_read(lfs,
|
|
|
pcache, rcache, hint-i,
|
|
|
- block, off+i, &dat, diff);
|
|
|
- if (res) {
|
|
|
- return res;
|
|
|
+ block, off+i, &dat, 1);
|
|
|
+ if (err) {
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
- res = memcmp(dat, data + i, diff);
|
|
|
- if (res) {
|
|
|
- return res < 0 ? LFS_CMP_LT : LFS_CMP_GT;
|
|
|
+ if (dat != data[i]) {
|
|
|
+ return (dat < data[i]) ? 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) {
|
|
|
@@ -172,7 +169,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);
|
|
|
@@ -186,7 +185,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,
|
|
|
@@ -232,13 +233,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 ///
|
|
|
@@ -392,10 +396,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);
|
|
|
@@ -415,33 +421,9 @@ 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,
|
|
|
@@ -458,10 +440,13 @@ 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]);
|
|
|
+#endif
|
|
|
int lfs_fs_traverseraw(lfs_t *lfs,
|
|
|
int (*cb)(void *data, lfs_block_t block), void *data,
|
|
|
bool includeorphans);
|
|
|
+#ifndef LFS_READONLY
|
|
|
static int lfs_fs_forceconsistency(lfs_t *lfs);
|
|
|
+#endif
|
|
|
static int lfs_deinit(lfs_t *lfs);
|
|
|
#ifdef LFS_MIGRATE
|
|
|
static int lfs1_traverse(lfs_t *lfs,
|
|
|
@@ -469,6 +454,7 @@ static int lfs1_traverse(lfs_t *lfs,
|
|
|
#endif
|
|
|
|
|
|
/// 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)
|
|
|
@@ -480,22 +466,22 @@ 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;
|
|
|
}
|
|
|
|
|
|
-// 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) {
|
|
|
+// 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;
|
|
|
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) {
|
|
|
@@ -536,11 +522,12 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
|
|
|
memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
|
|
|
int err = lfs_fs_traverseraw(lfs, lfs_alloc_lookahead, lfs, true);
|
|
|
if (err) {
|
|
|
- lfs_alloc_drop(lfs);
|
|
|
+ lfs_alloc_reset(lfs);
|
|
|
return err;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
/// Metadata pair and directory operations ///
|
|
|
static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,
|
|
|
@@ -673,6 +660,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;
|
|
|
@@ -700,7 +688,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,
|
|
|
@@ -794,6 +784,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],
|
|
|
@@ -901,10 +892,8 @@ 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, 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));
|
|
|
+ // pseudorandom numbers
|
|
|
+ lfs->seed ^= crc;
|
|
|
|
|
|
// update with what's found so far
|
|
|
besttag = tempbesttag;
|
|
|
@@ -1233,6 +1222,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,
|
|
|
@@ -1247,7 +1237,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
|
|
|
@@ -1292,15 +1284,16 @@ 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(commit->off + 2*sizeof(uint32_t),
|
|
|
+ const lfs_off_t end = lfs_alignup(off1 + 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
|
|
|
@@ -1336,12 +1329,6 @@ 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"
|
|
|
@@ -1355,7 +1342,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;
|
|
|
+ lfs_off_t noff = off1 + sizeof(uint32_t);
|
|
|
while (off < end) {
|
|
|
uint32_t crc = 0xffffffff;
|
|
|
for (lfs_off_t i = off; i < noff+sizeof(uint32_t); i++) {
|
|
|
@@ -1392,7 +1379,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++) {
|
|
|
@@ -1430,7 +1419,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);
|
|
|
@@ -1449,7 +1440,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) {
|
|
|
@@ -1482,7 +1475,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;
|
|
|
@@ -1490,17 +1485,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) {
|
|
|
@@ -1755,7 +1756,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
|
|
|
@@ -1943,10 +1946,14 @@ compact:
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
/// Top level directory operations ///
|
|
|
int lfs_mkdir(lfs_t *lfs, const char *path) {
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path);
|
|
|
// deorphan if we haven't yet, needed at most once after poweron
|
|
|
int err = lfs_fs_forceconsistency(lfs);
|
|
|
@@ -2043,12 +2050,11 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
|
|
|
|
|
|
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);
|
|
|
- LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)dir));
|
|
|
-
|
|
|
lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL);
|
|
|
if (tag < 0) {
|
|
|
LFS_TRACE("lfs_dir_open -> %"PRId32, tag);
|
|
|
@@ -2091,7 +2097,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
|
|
|
|
|
// add to list of mdirs
|
|
|
dir->type = LFS_TYPE_DIR;
|
|
|
- lfs_mlist_append(lfs, (struct lfs_mlist *)dir);
|
|
|
+ dir->next = (lfs_dir_t*)lfs->mlist;
|
|
|
+ lfs->mlist = (struct lfs_mlist*)dir;
|
|
|
|
|
|
LFS_TRACE("lfs_dir_open -> %d", 0);
|
|
|
return 0;
|
|
|
@@ -2100,7 +2107,12 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
|
|
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
|
|
|
LFS_TRACE("lfs_dir_close(%p, %p)", (void*)lfs, (void*)dir);
|
|
|
// remove from list of mdirs
|
|
|
- lfs_mlist_remove(lfs, (struct lfs_mlist *)dir);
|
|
|
+ for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {
|
|
|
+ if (*p == (struct lfs_mlist*)dir) {
|
|
|
+ *p = (*p)->next;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
LFS_TRACE("lfs_dir_close -> %d", 0);
|
|
|
return 0;
|
|
|
@@ -2273,6 +2285,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,
|
|
|
@@ -2370,6 +2383,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,
|
|
|
@@ -2423,15 +2437,18 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
|
|
".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));
|
|
|
|
|
|
// deorphan if we haven't yet, needed at most once after poweron
|
|
|
- if ((flags & LFS_O_RDWR) != LFS_O_RDONLY) {
|
|
|
+ if ((flags & 3) != LFS_O_RDONLY) {
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_INVAL;
|
|
|
+#else
|
|
|
int err = lfs_fs_forceconsistency(lfs);
|
|
|
if (err) {
|
|
|
LFS_TRACE("lfs_file_opencfg -> %d", err);
|
|
|
return err;
|
|
|
}
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
// setup simple file details
|
|
|
@@ -2451,9 +2468,14 @@ 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;
|
|
|
- lfs_mlist_append(lfs, (struct lfs_mlist *)file);
|
|
|
+ file->next = (lfs_file_t*)lfs->mlist;
|
|
|
+ lfs->mlist = (struct lfs_mlist*)file;
|
|
|
|
|
|
if (tag == LFS_ERR_NOENT) {
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ err = LFS_ERR_NOENT;
|
|
|
+ goto cleanup;
|
|
|
+#else
|
|
|
if (!(flags & LFS_O_CREAT)) {
|
|
|
err = LFS_ERR_NOENT;
|
|
|
goto cleanup;
|
|
|
@@ -2477,6 +2499,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
|
|
}
|
|
|
|
|
|
tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, 0);
|
|
|
+#endif
|
|
|
} else if (flags & LFS_O_EXCL) {
|
|
|
err = LFS_ERR_EXIST;
|
|
|
goto cleanup;
|
|
|
@@ -2500,7 +2523,7 @@ 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 & LFS_O_RDWR) != LFS_O_WRONLY) {
|
|
|
+ if ((file->flags & 3) != LFS_O_WRONLY) {
|
|
|
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,
|
|
|
@@ -2512,7 +2535,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if ((file->flags & LFS_O_RDWR) != LFS_O_RDONLY) {
|
|
|
+ if ((file->flags & 3) != LFS_O_RDONLY) {
|
|
|
if (file->cfg->attrs[i].size > lfs->attr_max) {
|
|
|
err = LFS_ERR_NOSPC;
|
|
|
goto cleanup;
|
|
|
@@ -2587,7 +2610,12 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
|
|
int err = lfs_file_sync(lfs, file);
|
|
|
|
|
|
// remove from list of mdirs
|
|
|
- lfs_mlist_remove(lfs, (struct lfs_mlist*)file);
|
|
|
+ for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {
|
|
|
+ if (*p == (struct lfs_mlist*)file) {
|
|
|
+ *p = (*p)->next;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// clean up memory
|
|
|
if (!file->cfg->buffer) {
|
|
|
@@ -2599,6 +2627,8 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+#ifndef LFS_READONLY
|
|
|
static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
|
|
|
LFS_ASSERT(file->flags & LFS_F_OPENED);
|
|
|
|
|
|
@@ -2669,7 +2699,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);
|
|
|
@@ -2681,6 +2713,7 @@ static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
|
|
|
file->flags &= ~LFS_F_INLINE;
|
|
|
return 0;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
|
|
|
LFS_ASSERT(file->flags & LFS_F_OPENED);
|
|
|
@@ -2692,6 +2725,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
|
|
|
file->flags &= ~LFS_F_READING;
|
|
|
}
|
|
|
|
|
|
+#ifndef LFS_READONLY
|
|
|
if (file->flags & LFS_F_WRITING) {
|
|
|
lfs_off_t pos = file->pos;
|
|
|
|
|
|
@@ -2758,6 +2792,7 @@ relocate:
|
|
|
|
|
|
file->pos = pos;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -2779,6 +2814,8 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+#ifndef LFS_READONLY
|
|
|
if ((file->flags & LFS_F_DIRTY) &&
|
|
|
!lfs_pair_isnull(file->m.pair)) {
|
|
|
// update dir entry
|
|
|
@@ -2814,6 +2851,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
|
|
|
|
|
file->flags &= ~LFS_F_DIRTY;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
LFS_TRACE("lfs_file_sync -> %d", 0);
|
|
|
return 0;
|
|
|
@@ -2824,11 +2862,12 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
|
|
|
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 & LFS_O_RDWR) != LFS_O_WRONLY);
|
|
|
+ LFS_ASSERT((file->flags & 3) != LFS_O_WRONLY);
|
|
|
|
|
|
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);
|
|
|
@@ -2837,6 +2876,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
|
|
|
return err;
|
|
|
}
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
if (file->pos >= file->ctz.size) {
|
|
|
// eof if past end
|
|
|
@@ -2904,8 +2944,12 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
|
|
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 & LFS_O_RDWR) != LFS_O_RDONLY);
|
|
|
+ LFS_ASSERT((file->flags & 3) != LFS_O_RDONLY);
|
|
|
|
|
|
+
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
const uint8_t *data = buffer;
|
|
|
lfs_size_t nsize = size;
|
|
|
|
|
|
@@ -3028,6 +3072,7 @@ 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,
|
|
|
@@ -3069,13 +3114,16 @@ 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 & LFS_O_RDWR) != LFS_O_RDONLY);
|
|
|
+ LFS_ASSERT((file->flags & 3) != LFS_O_RDONLY);
|
|
|
|
|
|
if (size > LFS_FILE_MAX) {
|
|
|
LFS_TRACE("lfs_file_truncate -> %d", LFS_ERR_INVAL);
|
|
|
return LFS_ERR_INVAL;
|
|
|
}
|
|
|
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
lfs_off_t pos = file->pos;
|
|
|
lfs_off_t oldsize = lfs_file_size(lfs, file);
|
|
|
if (size < oldsize) {
|
|
|
@@ -3127,6 +3175,7 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
|
|
|
|
|
LFS_TRACE("lfs_file_truncate -> %d", 0);
|
|
|
return 0;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
|
|
|
@@ -3153,11 +3202,15 @@ 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);
|
|
|
(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 {
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+ {
|
|
|
LFS_TRACE("lfs_file_size -> %"PRId32, file->ctz.size);
|
|
|
return file->ctz.size;
|
|
|
}
|
|
|
@@ -3181,6 +3234,10 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
|
|
|
|
|
int lfs_remove(lfs_t *lfs, const char *path) {
|
|
|
LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path);
|
|
|
+
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
// deorphan if we haven't yet, needed at most once after poweron
|
|
|
int err = lfs_fs_forceconsistency(lfs);
|
|
|
if (err) {
|
|
|
@@ -3258,11 +3315,15 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
|
|
|
|
|
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);
|
|
|
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
// deorphan if we haven't yet, needed at most once after poweron
|
|
|
int err = lfs_fs_forceconsistency(lfs);
|
|
|
if (err) {
|
|
|
@@ -3403,6 +3464,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
|
|
|
|
|
LFS_TRACE("lfs_rename -> %d", 0);
|
|
|
return 0;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
|
|
|
@@ -3446,6 +3508,7 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
|
|
|
return size;
|
|
|
}
|
|
|
|
|
|
+#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;
|
|
|
@@ -3467,11 +3530,15 @@ 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,
|
|
|
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);
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
if (size > lfs->attr_max) {
|
|
|
LFS_TRACE("lfs_setattr -> %d", LFS_ERR_NOSPC);
|
|
|
return LFS_ERR_NOSPC;
|
|
|
@@ -3480,13 +3547,18 @@ int lfs_setattr(lfs_t *lfs, const char *path,
|
|
|
int err = lfs_commitattr(lfs, path, type, buffer, size);
|
|
|
LFS_TRACE("lfs_setattr -> %d", err);
|
|
|
return err;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
|
|
|
LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type);
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
int err = lfs_commitattr(lfs, path, type, NULL, 0x3ff);
|
|
|
LFS_TRACE("lfs_removeattr -> %d", err);
|
|
|
return err;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -3632,6 +3704,10 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
|
|
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);
|
|
|
+
|
|
|
+#ifdef LFS_READONLY
|
|
|
+ return LFS_ERR_NOSYS;
|
|
|
+#else
|
|
|
int err = 0;
|
|
|
{
|
|
|
err = lfs_init(lfs, cfg);
|
|
|
@@ -3694,6 +3770,8 @@ cleanup:
|
|
|
lfs_deinit(lfs);
|
|
|
LFS_TRACE("lfs_format -> %d", err);
|
|
|
return err;
|
|
|
+
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|
|
@@ -3828,10 +3906,8 @@ 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, 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);
|
|
|
+ // setup free lookahead
|
|
|
+ lfs_alloc_reset(lfs);
|
|
|
|
|
|
LFS_TRACE("lfs_mount -> %d", 0);
|
|
|
return 0;
|
|
|
@@ -3935,6 +4011,7 @@ int lfs_fs_traverseraw(lfs_t *lfs,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#ifndef LFS_READONLY
|
|
|
if ((f->flags & LFS_F_WRITING) && !(f->flags & LFS_F_INLINE)) {
|
|
|
int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache,
|
|
|
f->block, f->pos, cb, data);
|
|
|
@@ -3942,6 +4019,7 @@ int lfs_fs_traverseraw(lfs_t *lfs,
|
|
|
return err;
|
|
|
}
|
|
|
}
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
@@ -3956,6 +4034,7 @@ int lfs_fs_traverse(lfs_t *lfs,
|
|
|
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
|
|
|
@@ -3981,12 +4060,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;
|
|
|
@@ -4005,7 +4088,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
|
|
|
@@ -4032,7 +4117,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
|
|
|
@@ -4127,14 +4214,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)) |
|
|
|
@@ -4142,7 +4233,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;
|
|
|
@@ -4172,7 +4265,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;
|
|
|
@@ -4246,7 +4341,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) {
|
|
|
@@ -4260,6 +4357,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;
|