mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Merge pull request #480 from maximevince/master
Add LFS_READONLY define, to allow smaller builds providing read-only mode
This commit is contained in:
		
							
								
								
									
										16
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -208,6 +208,22 @@ jobs: | |||||||
|     script: |     script: | ||||||
|       - make test TFLAGS+="-k --valgrind" |       - make test TFLAGS+="-k --valgrind" | ||||||
|  |  | ||||||
|  |   # test compilation in read-only mode | ||||||
|  |   - stage: test | ||||||
|  |     env: | ||||||
|  |       - NAME=littlefs-readonly | ||||||
|  |       - CC="arm-linux-gnueabi-gcc --static -mthumb" | ||||||
|  |       - CFLAGS="-Werror -DLFS_READONLY" | ||||||
|  |     if: branch !~ -prefix$ | ||||||
|  |     install: | ||||||
|  |       - *install-common | ||||||
|  |       - sudo apt-get install | ||||||
|  |             gcc-arm-linux-gnueabi | ||||||
|  |             libc6-dev-armel-cross | ||||||
|  |       - arm-linux-gnueabi-gcc --version | ||||||
|  |     # report-size will compile littlefs and report the size | ||||||
|  |     script: [*report-size] | ||||||
|  |  | ||||||
|   # self-host with littlefs-fuse for fuzz test |   # self-host with littlefs-fuse for fuzz test | ||||||
|   - stage: test |   - stage: test | ||||||
|     env: |     env: | ||||||
|   | |||||||
							
								
								
									
										137
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -140,6 +140,7 @@ static int lfs_bd_cmp(lfs_t *lfs, | |||||||
|     return LFS_CMP_EQ; |     return LFS_CMP_EQ; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_bd_flush(lfs_t *lfs, | static int lfs_bd_flush(lfs_t *lfs, | ||||||
|         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { |         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { | ||||||
|     if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) { |     if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) { | ||||||
| @@ -172,7 +173,9 @@ static int lfs_bd_flush(lfs_t *lfs, | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_bd_sync(lfs_t *lfs, | static int lfs_bd_sync(lfs_t *lfs, | ||||||
|         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { |         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { | ||||||
|     lfs_cache_drop(lfs, rcache); |     lfs_cache_drop(lfs, rcache); | ||||||
| @@ -186,7 +189,9 @@ static int lfs_bd_sync(lfs_t *lfs, | |||||||
|     LFS_ASSERT(err <= 0); |     LFS_ASSERT(err <= 0); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_bd_prog(lfs_t *lfs, | static int lfs_bd_prog(lfs_t *lfs, | ||||||
|         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate, |         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate, | ||||||
|         lfs_block_t block, lfs_off_t off, |         lfs_block_t block, lfs_off_t off, | ||||||
| @@ -232,13 +237,16 @@ static int lfs_bd_prog(lfs_t *lfs, | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { | static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { | ||||||
|     LFS_ASSERT(block < lfs->cfg->block_count); |     LFS_ASSERT(block < lfs->cfg->block_count); | ||||||
|     int err = lfs->cfg->erase(lfs->cfg, block); |     int err = lfs->cfg->erase(lfs->cfg, block); | ||||||
|     LFS_ASSERT(err <= 0); |     LFS_ASSERT(err <= 0); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Small type-level utilities /// | /// Small type-level utilities /// | ||||||
| @@ -392,10 +400,12 @@ static void lfs_ctz_fromle32(struct lfs_ctz *ctz) { | |||||||
|     ctz->size = lfs_fromle32(ctz->size); |     ctz->size = lfs_fromle32(ctz->size); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static void lfs_ctz_tole32(struct lfs_ctz *ctz) { | static void lfs_ctz_tole32(struct lfs_ctz *ctz) { | ||||||
|     ctz->head = lfs_tole32(ctz->head); |     ctz->head = lfs_tole32(ctz->head); | ||||||
|     ctz->size = lfs_tole32(ctz->size); |     ctz->size = lfs_tole32(ctz->size); | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) { | static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) { | ||||||
|     superblock->version     = lfs_fromle32(superblock->version); |     superblock->version     = lfs_fromle32(superblock->version); | ||||||
| @@ -442,6 +452,7 @@ static inline void lfs_mlist_append(lfs_t *lfs, struct lfs_mlist *mlist) { | |||||||
|  |  | ||||||
|  |  | ||||||
| /// Internal operations predeclared here /// | /// Internal operations predeclared here /// | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | ||||||
|         const struct lfs_mattr *attrs, int attrcount); |         const struct lfs_mattr *attrs, int attrcount); | ||||||
| static int lfs_dir_compact(lfs_t *lfs, | static int lfs_dir_compact(lfs_t *lfs, | ||||||
| @@ -458,10 +469,13 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2], | |||||||
|         lfs_mdir_t *parent); |         lfs_mdir_t *parent); | ||||||
| static int lfs_fs_relocate(lfs_t *lfs, | static int lfs_fs_relocate(lfs_t *lfs, | ||||||
|         const lfs_block_t oldpair[2], lfs_block_t newpair[2]); |         const lfs_block_t oldpair[2], lfs_block_t newpair[2]); | ||||||
|  | #endif | ||||||
| int lfs_fs_traverseraw(lfs_t *lfs, | int lfs_fs_traverseraw(lfs_t *lfs, | ||||||
|         int (*cb)(void *data, lfs_block_t block), void *data, |         int (*cb)(void *data, lfs_block_t block), void *data, | ||||||
|         bool includeorphans); |         bool includeorphans); | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_forceconsistency(lfs_t *lfs); | static int lfs_fs_forceconsistency(lfs_t *lfs); | ||||||
|  | #endif | ||||||
| static int lfs_deinit(lfs_t *lfs); | static int lfs_deinit(lfs_t *lfs); | ||||||
| #ifdef LFS_MIGRATE | #ifdef LFS_MIGRATE | ||||||
| static int lfs1_traverse(lfs_t *lfs, | static int lfs1_traverse(lfs_t *lfs, | ||||||
| @@ -469,6 +483,7 @@ static int lfs1_traverse(lfs_t *lfs, | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /// Block allocator /// | /// Block allocator /// | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_alloc_lookahead(void *p, lfs_block_t block) { | static int lfs_alloc_lookahead(void *p, lfs_block_t block) { | ||||||
|     lfs_t *lfs = (lfs_t*)p; |     lfs_t *lfs = (lfs_t*)p; | ||||||
|     lfs_block_t off = ((block - lfs->free.off) |     lfs_block_t off = ((block - lfs->free.off) | ||||||
| @@ -480,6 +495,7 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) { | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // indicate allocated blocks have been committed into the filesystem, this | // indicate allocated blocks have been committed into the filesystem, this | ||||||
| // is to prevent blocks from being garbage collected in the middle of a | // is to prevent blocks from being garbage collected in the middle of a | ||||||
| @@ -496,6 +512,7 @@ static void lfs_alloc_drop(lfs_t *lfs) { | |||||||
|     lfs_alloc_ack(lfs); |     lfs_alloc_ack(lfs); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { | static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { | ||||||
|     while (true) { |     while (true) { | ||||||
|         while (lfs->free.i != lfs->free.size) { |         while (lfs->free.i != lfs->free.size) { | ||||||
| @@ -541,6 +558,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /// Metadata pair and directory operations /// | /// Metadata pair and directory operations /// | ||||||
| static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir, | static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir, | ||||||
| @@ -673,6 +691,7 @@ static int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_traverse_filter(void *p, | static int lfs_dir_traverse_filter(void *p, | ||||||
|         lfs_tag_t tag, const void *buffer) { |         lfs_tag_t tag, const void *buffer) { | ||||||
|     lfs_tag_t *filtertag = p; |     lfs_tag_t *filtertag = p; | ||||||
| @@ -700,7 +719,9 @@ static int lfs_dir_traverse_filter(void *p, | |||||||
|  |  | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_traverse(lfs_t *lfs, | static int lfs_dir_traverse(lfs_t *lfs, | ||||||
|         const lfs_mdir_t *dir, lfs_off_t off, lfs_tag_t ptag, |         const lfs_mdir_t *dir, lfs_off_t off, lfs_tag_t ptag, | ||||||
|         const struct lfs_mattr *attrs, int attrcount, |         const struct lfs_mattr *attrs, int attrcount, | ||||||
| @@ -794,6 +815,7 @@ static int lfs_dir_traverse(lfs_t *lfs, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs, | static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs, | ||||||
|         lfs_mdir_t *dir, const lfs_block_t pair[2], |         lfs_mdir_t *dir, const lfs_block_t pair[2], | ||||||
| @@ -1233,6 +1255,7 @@ struct lfs_commit { | |||||||
|     lfs_off_t end; |     lfs_off_t end; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit, | static int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit, | ||||||
|         const void *buffer, lfs_size_t size) { |         const void *buffer, lfs_size_t size) { | ||||||
|     int err = lfs_bd_prog(lfs, |     int err = lfs_bd_prog(lfs, | ||||||
| @@ -1247,7 +1270,9 @@ static int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit, | |||||||
|     commit->off += size; |     commit->off += size; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit, | static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit, | ||||||
|         lfs_tag_t tag, const void *buffer) { |         lfs_tag_t tag, const void *buffer) { | ||||||
|     // check if we fit |     // check if we fit | ||||||
| @@ -1292,7 +1317,9 @@ static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit, | |||||||
|     commit->ptag = tag & 0x7fffffff; |     commit->ptag = tag & 0x7fffffff; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) { | static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) { | ||||||
|     // align to program units |     // align to program units | ||||||
|     const lfs_off_t end = lfs_alignup(commit->off + 2*sizeof(uint32_t), |     const lfs_off_t end = lfs_alignup(commit->off + 2*sizeof(uint32_t), | ||||||
| @@ -1392,7 +1419,9 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) { | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) { | static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) { | ||||||
|     // allocate pair of dir blocks (backwards, so we write block 1 first) |     // allocate pair of dir blocks (backwards, so we write block 1 first) | ||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
| @@ -1430,7 +1459,9 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) { | |||||||
|     // don't write out yet, let caller take care of that |     // don't write out yet, let caller take care of that | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) { | static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) { | ||||||
|     // steal state |     // steal state | ||||||
|     int err = lfs_dir_getgstate(lfs, tail, &lfs->gdelta); |     int err = lfs_dir_getgstate(lfs, tail, &lfs->gdelta); | ||||||
| @@ -1449,7 +1480,9 @@ static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) { | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_split(lfs_t *lfs, | static int lfs_dir_split(lfs_t *lfs, | ||||||
|         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, |         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, | ||||||
|         lfs_mdir_t *source, uint16_t split, uint16_t end) { |         lfs_mdir_t *source, uint16_t split, uint16_t end) { | ||||||
| @@ -1482,7 +1515,9 @@ static int lfs_dir_split(lfs_t *lfs, | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) { | static int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) { | ||||||
|     lfs_size_t *size = p; |     lfs_size_t *size = p; | ||||||
|     (void)buffer; |     (void)buffer; | ||||||
| @@ -1490,17 +1525,23 @@ static int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) { | |||||||
|     *size += lfs_tag_dsize(tag); |     *size += lfs_tag_dsize(tag); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| struct lfs_dir_commit_commit { | struct lfs_dir_commit_commit { | ||||||
|     lfs_t *lfs; |     lfs_t *lfs; | ||||||
|     struct lfs_commit *commit; |     struct lfs_commit *commit; | ||||||
| }; | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commit_commit(void *p, lfs_tag_t tag, const void *buffer) { | static int lfs_dir_commit_commit(void *p, lfs_tag_t tag, const void *buffer) { | ||||||
|     struct lfs_dir_commit_commit *commit = p; |     struct lfs_dir_commit_commit *commit = p; | ||||||
|     return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer); |     return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer); | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_compact(lfs_t *lfs, | static int lfs_dir_compact(lfs_t *lfs, | ||||||
|         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, |         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, | ||||||
|         lfs_mdir_t *source, uint16_t begin, uint16_t end) { |         lfs_mdir_t *source, uint16_t begin, uint16_t end) { | ||||||
| @@ -1755,7 +1796,9 @@ relocate: | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | ||||||
|         const struct lfs_mattr *attrs, int attrcount) { |         const struct lfs_mattr *attrs, int attrcount) { | ||||||
|     // check for any inline files that aren't RAM backed and |     // check for any inline files that aren't RAM backed and | ||||||
| @@ -1943,9 +1986,11 @@ compact: | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Top level directory operations /// | /// Top level directory operations /// | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_mkdir(lfs_t *lfs, const char *path) { | int lfs_mkdir(lfs_t *lfs, const char *path) { | ||||||
|     LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path); |     LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path); | ||||||
|     // deorphan if we haven't yet, needed at most once after poweron |     // deorphan if we haven't yet, needed at most once after poweron | ||||||
| @@ -2044,6 +2089,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     LFS_TRACE("lfs_mkdir -> %d", 0); |     LFS_TRACE("lfs_mkdir -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | 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_TRACE("lfs_dir_open(%p, %p, \"%s\")", (void*)lfs, (void*)dir, path); | ||||||
| @@ -2273,6 +2319,7 @@ static int lfs_ctz_find(lfs_t *lfs, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_ctz_extend(lfs_t *lfs, | static int lfs_ctz_extend(lfs_t *lfs, | ||||||
|         lfs_cache_t *pcache, lfs_cache_t *rcache, |         lfs_cache_t *pcache, lfs_cache_t *rcache, | ||||||
|         lfs_block_t head, lfs_size_t size, |         lfs_block_t head, lfs_size_t size, | ||||||
| @@ -2370,6 +2417,7 @@ relocate: | |||||||
|         lfs_cache_drop(lfs, pcache); |         lfs_cache_drop(lfs, pcache); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static int lfs_ctz_traverse(lfs_t *lfs, | static int lfs_ctz_traverse(lfs_t *lfs, | ||||||
|         const lfs_cache_t *pcache, lfs_cache_t *rcache, |         const lfs_cache_t *pcache, lfs_cache_t *rcache, | ||||||
| @@ -2425,6 +2473,9 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|             (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); |             (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); | ||||||
|     LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file)); |     LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file)); | ||||||
|  |  | ||||||
|  | #ifdef LFS_READONLY | ||||||
|  |     LFS_ASSERT((flags & 3) == LFS_O_RDONLY); | ||||||
|  | #else | ||||||
|     // deorphan if we haven't yet, needed at most once after poweron |     // deorphan if we haven't yet, needed at most once after poweron | ||||||
|     if ((flags & LFS_O_RDWR) != LFS_O_RDONLY) { |     if ((flags & LFS_O_RDWR) != LFS_O_RDONLY) { | ||||||
|         int err = lfs_fs_forceconsistency(lfs); |         int err = lfs_fs_forceconsistency(lfs); | ||||||
| @@ -2433,6 +2484,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     // setup simple file details |     // setup simple file details | ||||||
|     int err; |     int err; | ||||||
| @@ -2453,6 +2505,11 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|     file->type = LFS_TYPE_REG; |     file->type = LFS_TYPE_REG; | ||||||
|     lfs_mlist_append(lfs, (struct lfs_mlist *)file); |     lfs_mlist_append(lfs, (struct lfs_mlist *)file); | ||||||
|  |  | ||||||
|  | #ifdef LFS_READONLY | ||||||
|  |     if (tag == LFS_ERR_NOENT) { | ||||||
|  |         err = LFS_ERR_NOENT; | ||||||
|  |         goto cleanup; | ||||||
|  | #else | ||||||
|     if (tag == LFS_ERR_NOENT) { |     if (tag == LFS_ERR_NOENT) { | ||||||
|         if (!(flags & LFS_O_CREAT)) { |         if (!(flags & LFS_O_CREAT)) { | ||||||
|             err = LFS_ERR_NOENT; |             err = LFS_ERR_NOENT; | ||||||
| @@ -2480,13 +2537,16 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|     } else if (flags & LFS_O_EXCL) { |     } else if (flags & LFS_O_EXCL) { | ||||||
|         err = LFS_ERR_EXIST; |         err = LFS_ERR_EXIST; | ||||||
|         goto cleanup; |         goto cleanup; | ||||||
|  | #endif | ||||||
|     } else if (lfs_tag_type3(tag) != LFS_TYPE_REG) { |     } else if (lfs_tag_type3(tag) != LFS_TYPE_REG) { | ||||||
|         err = LFS_ERR_ISDIR; |         err = LFS_ERR_ISDIR; | ||||||
|         goto cleanup; |         goto cleanup; | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     } else if (flags & LFS_O_TRUNC) { |     } else if (flags & LFS_O_TRUNC) { | ||||||
|         // truncate if requested |         // truncate if requested | ||||||
|         tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0); |         tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0); | ||||||
|         file->flags |= LFS_F_DIRTY; |         file->flags |= LFS_F_DIRTY; | ||||||
|  | #endif | ||||||
|     } else { |     } else { | ||||||
|         // try to load what's on disk, if it's inlined we'll fix it later |         // try to load what's on disk, if it's inlined we'll fix it later | ||||||
|         tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0), |         tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0), | ||||||
| @@ -2500,7 +2560,8 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|  |  | ||||||
|     // fetch attrs |     // fetch attrs | ||||||
|     for (unsigned i = 0; i < file->cfg->attr_count; i++) { |     for (unsigned i = 0; i < file->cfg->attr_count; i++) { | ||||||
|         if ((file->flags & LFS_O_RDWR) != LFS_O_WRONLY) { |         // if opened for read / read-write operations | ||||||
|  |         if ((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY) { | ||||||
|             lfs_stag_t res = lfs_dir_get(lfs, &file->m, |             lfs_stag_t res = lfs_dir_get(lfs, &file->m, | ||||||
|                     LFS_MKTAG(0x7ff, 0x3ff, 0), |                     LFS_MKTAG(0x7ff, 0x3ff, 0), | ||||||
|                     LFS_MKTAG(LFS_TYPE_USERATTR + file->cfg->attrs[i].type, |                     LFS_MKTAG(LFS_TYPE_USERATTR + file->cfg->attrs[i].type, | ||||||
| @@ -2512,7 +2573,9 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if ((file->flags & LFS_O_RDWR) != LFS_O_RDONLY) { | #ifndef LFS_READONLY | ||||||
|  |         // if opened for write / read-write operations | ||||||
|  |         if ((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY) { | ||||||
|             if (file->cfg->attrs[i].size > lfs->attr_max) { |             if (file->cfg->attrs[i].size > lfs->attr_max) { | ||||||
|                 err = LFS_ERR_NOSPC; |                 err = LFS_ERR_NOSPC; | ||||||
|                 goto cleanup; |                 goto cleanup; | ||||||
| @@ -2520,6 +2583,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|  |  | ||||||
|             file->flags |= LFS_F_DIRTY; |             file->flags |= LFS_F_DIRTY; | ||||||
|         } |         } | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // allocate buffer if needed |     // allocate buffer if needed | ||||||
| @@ -2564,7 +2628,9 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|  |  | ||||||
| cleanup: | cleanup: | ||||||
|     // clean up lingering resources |     // clean up lingering resources | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     file->flags |= LFS_F_ERRED; |     file->flags |= LFS_F_ERRED; | ||||||
|  | #endif | ||||||
|     lfs_file_close(lfs, file); |     lfs_file_close(lfs, file); | ||||||
|     LFS_TRACE("lfs_file_opencfg -> %d", err); |     LFS_TRACE("lfs_file_opencfg -> %d", err); | ||||||
|     return err; |     return err; | ||||||
| @@ -2584,7 +2650,11 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file); |     LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file); | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
|  |  | ||||||
|  | #ifdef LFS_READONLY | ||||||
|  |     int err = 0; | ||||||
|  | #else | ||||||
|     int err = lfs_file_sync(lfs, file); |     int err = lfs_file_sync(lfs, file); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     // remove from list of mdirs |     // remove from list of mdirs | ||||||
|     lfs_mlist_remove(lfs, (struct lfs_mlist*)file); |     lfs_mlist_remove(lfs, (struct lfs_mlist*)file); | ||||||
| @@ -2599,6 +2669,8 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { | static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
|  |  | ||||||
| @@ -2669,7 +2741,9 @@ relocate: | |||||||
|         lfs_cache_drop(lfs, &lfs->pcache); |         lfs_cache_drop(lfs, &lfs->pcache); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) { | static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     file->off = file->pos; |     file->off = file->pos; | ||||||
|     lfs_alloc_ack(lfs); |     lfs_alloc_ack(lfs); | ||||||
| @@ -2681,7 +2755,9 @@ static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     file->flags &= ~LFS_F_INLINE; |     file->flags &= ~LFS_F_INLINE; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
|  |  | ||||||
| @@ -2761,7 +2837,9 @@ relocate: | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file); |     LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file); | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
| @@ -2779,6 +2857,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     if ((file->flags & LFS_F_DIRTY) && |     if ((file->flags & LFS_F_DIRTY) && | ||||||
|             !lfs_pair_isnull(file->m.pair)) { |             !lfs_pair_isnull(file->m.pair)) { | ||||||
|         // update dir entry |         // update dir entry | ||||||
| @@ -2818,17 +2897,21 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     LFS_TRACE("lfs_file_sync -> %d", 0); |     LFS_TRACE("lfs_file_sync -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | ||||||
|         void *buffer, lfs_size_t size) { |         void *buffer, lfs_size_t size) { | ||||||
|     LFS_TRACE("lfs_file_read(%p, %p, %p, %"PRIu32")", |     LFS_TRACE("lfs_file_read(%p, %p, %p, %"PRIu32")", | ||||||
|             (void*)lfs, (void*)file, buffer, size); |             (void*)lfs, (void*)file, buffer, size); | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     LFS_ASSERT((file->flags & LFS_O_RDWR) != LFS_O_WRONLY); |     LFS_ASSERT((file->flags & LFS_O_RDWR) != LFS_O_WRONLY); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     uint8_t *data = buffer; |     uint8_t *data = buffer; | ||||||
|     lfs_size_t nsize = size; |     lfs_size_t nsize = size; | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     if (file->flags & LFS_F_WRITING) { |     if (file->flags & LFS_F_WRITING) { | ||||||
|         // flush out any writes |         // flush out any writes | ||||||
|         int err = lfs_file_flush(lfs, file); |         int err = lfs_file_flush(lfs, file); | ||||||
| @@ -2837,6 +2920,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | |||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     if (file->pos >= file->ctz.size) { |     if (file->pos >= file->ctz.size) { | ||||||
|         // eof if past end |         // eof if past end | ||||||
| @@ -2899,6 +2983,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | |||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | ||||||
|         const void *buffer, lfs_size_t size) { |         const void *buffer, lfs_size_t size) { | ||||||
|     LFS_TRACE("lfs_file_write(%p, %p, %p, %"PRIu32")", |     LFS_TRACE("lfs_file_write(%p, %p, %p, %"PRIu32")", | ||||||
| @@ -3029,6 +3114,7 @@ relocate: | |||||||
|     LFS_TRACE("lfs_file_write -> %"PRId32, size); |     LFS_TRACE("lfs_file_write -> %"PRId32, size); | ||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | ||||||
|         lfs_soff_t off, int whence) { |         lfs_soff_t off, int whence) { | ||||||
| @@ -3036,12 +3122,14 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | |||||||
|             (void*)lfs, (void*)file, off, whence); |             (void*)lfs, (void*)file, off, whence); | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     // write out everything beforehand, may be noop if rdonly |     // write out everything beforehand, may be noop if rdonly | ||||||
|     int err = lfs_file_flush(lfs, file); |     int err = lfs_file_flush(lfs, file); | ||||||
|     if (err) { |     if (err) { | ||||||
|         LFS_TRACE("lfs_file_seek -> %d", err); |         LFS_TRACE("lfs_file_seek -> %d", err); | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     // find new pos |     // find new pos | ||||||
|     lfs_off_t npos = file->pos; |     lfs_off_t npos = file->pos; | ||||||
| @@ -3065,6 +3153,7 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | |||||||
|     return npos; |     return npos; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { | int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { | ||||||
|     LFS_TRACE("lfs_file_truncate(%p, %p, %"PRIu32")", |     LFS_TRACE("lfs_file_truncate(%p, %p, %"PRIu32")", | ||||||
|             (void*)lfs, (void*)file, size); |             (void*)lfs, (void*)file, size); | ||||||
| @@ -3128,6 +3217,7 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { | |||||||
|     LFS_TRACE("lfs_file_truncate -> %d", 0); |     LFS_TRACE("lfs_file_truncate -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) { | lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file); |     LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file); | ||||||
| @@ -3153,14 +3243,16 @@ 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_TRACE("lfs_file_size(%p, %p)", (void*)lfs, (void*)file); | ||||||
|     LFS_ASSERT(file->flags & LFS_F_OPENED); |     LFS_ASSERT(file->flags & LFS_F_OPENED); | ||||||
|     (void)lfs; |     (void)lfs; | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     if (file->flags & LFS_F_WRITING) { |     if (file->flags & LFS_F_WRITING) { | ||||||
|         LFS_TRACE("lfs_file_size -> %"PRId32, |         LFS_TRACE("lfs_file_size -> %"PRId32, | ||||||
|                 lfs_max(file->pos, file->ctz.size)); |                 lfs_max(file->pos, file->ctz.size)); | ||||||
|         return lfs_max(file->pos, file->ctz.size); |         return lfs_max(file->pos, file->ctz.size); | ||||||
|     } else { |     } | ||||||
|  | #endif | ||||||
|     LFS_TRACE("lfs_file_size -> %"PRId32, file->ctz.size); |     LFS_TRACE("lfs_file_size -> %"PRId32, file->ctz.size); | ||||||
|     return file->ctz.size; |     return file->ctz.size; | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -3179,8 +3271,10 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | |||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_remove(lfs_t *lfs, const char *path) { | int lfs_remove(lfs_t *lfs, const char *path) { | ||||||
|     LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path); |     LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path); | ||||||
|  |  | ||||||
|     // deorphan if we haven't yet, needed at most once after poweron |     // deorphan if we haven't yet, needed at most once after poweron | ||||||
|     int err = lfs_fs_forceconsistency(lfs); |     int err = lfs_fs_forceconsistency(lfs); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -3259,7 +3353,9 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|     LFS_TRACE("lfs_remove -> %d", 0); |     LFS_TRACE("lfs_remove -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||||
|     LFS_TRACE("lfs_rename(%p, \"%s\", \"%s\")", (void*)lfs, oldpath, newpath); |     LFS_TRACE("lfs_rename(%p, \"%s\", \"%s\")", (void*)lfs, oldpath, newpath); | ||||||
|  |  | ||||||
| @@ -3404,6 +3500,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|     LFS_TRACE("lfs_rename -> %d", 0); |     LFS_TRACE("lfs_rename -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, void *buffer, lfs_size_t size) { |         uint8_t type, void *buffer, lfs_size_t size) { | ||||||
| @@ -3446,6 +3543,7 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | |||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_commitattr(lfs_t *lfs, const char *path, | static int lfs_commitattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, const void *buffer, lfs_size_t size) { |         uint8_t type, const void *buffer, lfs_size_t size) { | ||||||
|     lfs_mdir_t cwd; |     lfs_mdir_t cwd; | ||||||
| @@ -3467,7 +3565,9 @@ static int lfs_commitattr(lfs_t *lfs, const char *path, | |||||||
|     return lfs_dir_commit(lfs, &cwd, LFS_MKATTRS( |     return lfs_dir_commit(lfs, &cwd, LFS_MKATTRS( | ||||||
|             {LFS_MKTAG(LFS_TYPE_USERATTR + type, id, size), buffer})); |             {LFS_MKTAG(LFS_TYPE_USERATTR + type, id, size), buffer})); | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_setattr(lfs_t *lfs, const char *path, | int lfs_setattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, const void *buffer, lfs_size_t size) { |         uint8_t type, const void *buffer, lfs_size_t size) { | ||||||
|     LFS_TRACE("lfs_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", |     LFS_TRACE("lfs_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", | ||||||
| @@ -3481,13 +3581,16 @@ int lfs_setattr(lfs_t *lfs, const char *path, | |||||||
|     LFS_TRACE("lfs_setattr -> %d", err); |     LFS_TRACE("lfs_setattr -> %d", err); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) { | int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) { | ||||||
|     LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type); |     LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type); | ||||||
|     int err = lfs_commitattr(lfs, path, type, NULL, 0x3ff); |     int err = lfs_commitattr(lfs, path, type, NULL, 0x3ff); | ||||||
|     LFS_TRACE("lfs_removeattr -> %d", err); |     LFS_TRACE("lfs_removeattr -> %d", err); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Filesystem operations /// | /// Filesystem operations /// | ||||||
| @@ -3615,6 +3718,7 @@ static int lfs_deinit(lfs_t *lfs) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | ||||||
|     LFS_TRACE("lfs_format(%p, %p {.context=%p, " |     LFS_TRACE("lfs_format(%p, %p {.context=%p, " | ||||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " |                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||||
| @@ -3632,6 +3736,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|             cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, |             cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, | ||||||
|             cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, |             cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, | ||||||
|             cfg->name_max, cfg->file_max, cfg->attr_max); |             cfg->name_max, cfg->file_max, cfg->attr_max); | ||||||
|  |  | ||||||
|     int err = 0; |     int err = 0; | ||||||
|     { |     { | ||||||
|         err = lfs_init(lfs, cfg); |         err = lfs_init(lfs, cfg); | ||||||
| @@ -3694,7 +3799,9 @@ cleanup: | |||||||
|     lfs_deinit(lfs); |     lfs_deinit(lfs); | ||||||
|     LFS_TRACE("lfs_format -> %d", err); |     LFS_TRACE("lfs_format -> %d", err); | ||||||
|     return err; |     return err; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | ||||||
|     LFS_TRACE("lfs_mount(%p, %p {.context=%p, " |     LFS_TRACE("lfs_mount(%p, %p {.context=%p, " | ||||||
| @@ -3921,6 +4028,7 @@ int lfs_fs_traverseraw(lfs_t *lfs, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     // iterate over any open files |     // iterate over any open files | ||||||
|     for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) { |     for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) { | ||||||
|         if (f->type != LFS_TYPE_REG) { |         if (f->type != LFS_TYPE_REG) { | ||||||
| @@ -3943,6 +4051,7 @@ int lfs_fs_traverseraw(lfs_t *lfs, | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| @@ -3956,6 +4065,7 @@ int lfs_fs_traverse(lfs_t *lfs, | |||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_pred(lfs_t *lfs, | static int lfs_fs_pred(lfs_t *lfs, | ||||||
|         const lfs_block_t pair[2], lfs_mdir_t *pdir) { |         const lfs_block_t pair[2], lfs_mdir_t *pdir) { | ||||||
|     // iterate over all directory directory entries |     // iterate over all directory directory entries | ||||||
| @@ -3981,12 +4091,16 @@ static int lfs_fs_pred(lfs_t *lfs, | |||||||
|  |  | ||||||
|     return LFS_ERR_NOENT; |     return LFS_ERR_NOENT; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| struct lfs_fs_parent_match { | struct lfs_fs_parent_match { | ||||||
|     lfs_t *lfs; |     lfs_t *lfs; | ||||||
|     const lfs_block_t pair[2]; |     const lfs_block_t pair[2]; | ||||||
| }; | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_parent_match(void *data, | static int lfs_fs_parent_match(void *data, | ||||||
|         lfs_tag_t tag, const void *buffer) { |         lfs_tag_t tag, const void *buffer) { | ||||||
|     struct lfs_fs_parent_match *find = data; |     struct lfs_fs_parent_match *find = data; | ||||||
| @@ -4005,7 +4119,9 @@ static int lfs_fs_parent_match(void *data, | |||||||
|     lfs_pair_fromle32(child); |     lfs_pair_fromle32(child); | ||||||
|     return (lfs_pair_cmp(child, find->pair) == 0) ? LFS_CMP_EQ : LFS_CMP_LT; |     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], | static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2], | ||||||
|         lfs_mdir_t *parent) { |         lfs_mdir_t *parent) { | ||||||
|     // use fetchmatch with callback to find pairs |     // use fetchmatch with callback to find pairs | ||||||
| @@ -4032,7 +4148,9 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2], | |||||||
|  |  | ||||||
|     return LFS_ERR_NOENT; |     return LFS_ERR_NOENT; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_relocate(lfs_t *lfs, | static int lfs_fs_relocate(lfs_t *lfs, | ||||||
|         const lfs_block_t oldpair[2], lfs_block_t newpair[2]) { |         const lfs_block_t oldpair[2], lfs_block_t newpair[2]) { | ||||||
|     // update internal root |     // update internal root | ||||||
| @@ -4127,14 +4245,18 @@ static int lfs_fs_relocate(lfs_t *lfs, | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) { | static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) { | ||||||
|     LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0 || orphans >= 0); |     LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0 || orphans >= 0); | ||||||
|     lfs->gstate.tag += orphans; |     lfs->gstate.tag += orphans; | ||||||
|     lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) | |     lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) | | ||||||
|             ((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31)); |             ((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31)); | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static void lfs_fs_prepmove(lfs_t *lfs, | static void lfs_fs_prepmove(lfs_t *lfs, | ||||||
|         uint16_t id, const lfs_block_t pair[2]) { |         uint16_t id, const lfs_block_t pair[2]) { | ||||||
|     lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x7ff, 0x3ff, 0)) | |     lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x7ff, 0x3ff, 0)) | | ||||||
| @@ -4142,7 +4264,9 @@ static void lfs_fs_prepmove(lfs_t *lfs, | |||||||
|     lfs->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0; |     lfs->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0; | ||||||
|     lfs->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0; |     lfs->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_demove(lfs_t *lfs) { | static int lfs_fs_demove(lfs_t *lfs) { | ||||||
|     if (!lfs_gstate_hasmove(&lfs->gdisk)) { |     if (!lfs_gstate_hasmove(&lfs->gdisk)) { | ||||||
|         return 0; |         return 0; | ||||||
| @@ -4172,7 +4296,9 @@ static int lfs_fs_demove(lfs_t *lfs) { | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_deorphan(lfs_t *lfs) { | static int lfs_fs_deorphan(lfs_t *lfs) { | ||||||
|     if (!lfs_gstate_hasorphans(&lfs->gstate)) { |     if (!lfs_gstate_hasorphans(&lfs->gstate)) { | ||||||
|         return 0; |         return 0; | ||||||
| @@ -4246,7 +4372,9 @@ static int lfs_fs_deorphan(lfs_t *lfs) { | |||||||
|     lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate)); |     lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate)); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| static int lfs_fs_forceconsistency(lfs_t *lfs) { | static int lfs_fs_forceconsistency(lfs_t *lfs) { | ||||||
|     int err = lfs_fs_demove(lfs); |     int err = lfs_fs_demove(lfs); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -4260,6 +4388,7 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) { | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static int lfs_fs_size_count(void *p, lfs_block_t block) { | static int lfs_fs_size_count(void *p, lfs_block_t block) { | ||||||
|     (void)block; |     (void)block; | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -123,18 +123,24 @@ enum lfs_type { | |||||||
| enum lfs_open_flags { | enum lfs_open_flags { | ||||||
|     // open flags |     // open flags | ||||||
|     LFS_O_RDONLY = 1,         // Open a file as read only |     LFS_O_RDONLY = 1,         // Open a file as read only | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     LFS_O_WRONLY = 2,         // Open a file as write only |     LFS_O_WRONLY = 2,         // Open a file as write only | ||||||
|     LFS_O_RDWR   = 3,         // Open a file as read and write |     LFS_O_RDWR   = 3,         // Open a file as read and write | ||||||
|     LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist |     LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist | ||||||
|     LFS_O_EXCL   = 0x0200,    // Fail if a file already exists |     LFS_O_EXCL   = 0x0200,    // Fail if a file already exists | ||||||
|     LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size |     LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size | ||||||
|     LFS_O_APPEND = 0x0800,    // Move to end of file on every write |     LFS_O_APPEND = 0x0800,    // Move to end of file on every write | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     // internally used flags |     // internally used flags | ||||||
|  | #ifndef LFS_READONLY | ||||||
|     LFS_F_DIRTY   = 0x010000, // File does not match storage |     LFS_F_DIRTY   = 0x010000, // File does not match storage | ||||||
|     LFS_F_WRITING = 0x020000, // File has been written since last flush |     LFS_F_WRITING = 0x020000, // File has been written since last flush | ||||||
|  | #endif | ||||||
|     LFS_F_READING = 0x040000, // File has been read since last flush |     LFS_F_READING = 0x040000, // File has been read since last flush | ||||||
|     LFS_F_ERRED   = 0x080000, // An error occured during write | #ifndef LFS_READONLY | ||||||
|  |     LFS_F_ERRED   = 0x080000, // An error occurred during write | ||||||
|  | #endif | ||||||
|     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry |     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry | ||||||
|     LFS_F_OPENED  = 0x200000, // File has been opened |     LFS_F_OPENED  = 0x200000, // File has been opened | ||||||
| }; | }; | ||||||
| @@ -399,6 +405,7 @@ typedef struct lfs { | |||||||
|  |  | ||||||
| /// Filesystem functions /// | /// Filesystem functions /// | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Format a block device with the littlefs | // Format a block device with the littlefs | ||||||
| // | // | ||||||
| // Requires a littlefs object and config struct. This clobbers the littlefs | // Requires a littlefs object and config struct. This clobbers the littlefs | ||||||
| @@ -407,6 +414,7 @@ typedef struct lfs { | |||||||
| // | // | ||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_format(lfs_t *lfs, const struct lfs_config *config); | int lfs_format(lfs_t *lfs, const struct lfs_config *config); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Mounts a littlefs | // Mounts a littlefs | ||||||
| // | // | ||||||
| @@ -426,12 +434,15 @@ int lfs_unmount(lfs_t *lfs); | |||||||
|  |  | ||||||
| /// General operations /// | /// General operations /// | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Removes a file or directory | // Removes a file or directory | ||||||
| // | // | ||||||
| // If removing a directory, the directory must be empty. | // If removing a directory, the directory must be empty. | ||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_remove(lfs_t *lfs, const char *path); | int lfs_remove(lfs_t *lfs, const char *path); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Rename or move a file or directory | // Rename or move a file or directory | ||||||
| // | // | ||||||
| // If the destination exists, it must match the source in type. | // If the destination exists, it must match the source in type. | ||||||
| @@ -439,6 +450,7 @@ int lfs_remove(lfs_t *lfs, const char *path); | |||||||
| // | // | ||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath); | int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Find info about a file or directory | // Find info about a file or directory | ||||||
| // | // | ||||||
| @@ -461,6 +473,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info); | |||||||
| lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, void *buffer, lfs_size_t size); |         uint8_t type, void *buffer, lfs_size_t size); | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Set custom attributes | // Set custom attributes | ||||||
| // | // | ||||||
| // Custom attributes are uniquely identified by an 8-bit type and limited | // Custom attributes are uniquely identified by an 8-bit type and limited | ||||||
| @@ -470,13 +483,16 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | |||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_setattr(lfs_t *lfs, const char *path, | int lfs_setattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, const void *buffer, lfs_size_t size); |         uint8_t type, const void *buffer, lfs_size_t size); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Removes a custom attribute | // Removes a custom attribute | ||||||
| // | // | ||||||
| // If an attribute is not found, nothing happens. | // If an attribute is not found, nothing happens. | ||||||
| // | // | ||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type); | int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /// File operations /// | /// File operations /// | ||||||
| @@ -525,6 +541,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file); | |||||||
| lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | ||||||
|         void *buffer, lfs_size_t size); |         void *buffer, lfs_size_t size); | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Write data to file | // Write data to file | ||||||
| // | // | ||||||
| // Takes a buffer and size indicating the data to write. The file will not | // Takes a buffer and size indicating the data to write. The file will not | ||||||
| @@ -533,6 +550,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | |||||||
| // Returns the number of bytes written, or a negative error code on failure. | // Returns the number of bytes written, or a negative error code on failure. | ||||||
| lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | ||||||
|         const void *buffer, lfs_size_t size); |         const void *buffer, lfs_size_t size); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Change the position of the file | // Change the position of the file | ||||||
| // | // | ||||||
| @@ -541,10 +559,12 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
| lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | ||||||
|         lfs_soff_t off, int whence); |         lfs_soff_t off, int whence); | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Truncates the size of the file to the specified size | // Truncates the size of the file to the specified size | ||||||
| // | // | ||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size); | int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Return the position of the file | // Return the position of the file | ||||||
| // | // | ||||||
| @@ -567,10 +587,12 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file); | |||||||
|  |  | ||||||
| /// Directory operations /// | /// Directory operations /// | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| // Create a directory | // Create a directory | ||||||
| // | // | ||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_mkdir(lfs_t *lfs, const char *path); | int lfs_mkdir(lfs_t *lfs, const char *path); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Open a directory | // Open a directory | ||||||
| // | // | ||||||
| @@ -632,6 +654,7 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs); | |||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); | int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); | ||||||
|  |  | ||||||
|  | #ifndef LFS_READONLY | ||||||
| #ifdef LFS_MIGRATE | #ifdef LFS_MIGRATE | ||||||
| // Attempts to migrate a previous version of littlefs | // Attempts to migrate a previous version of littlefs | ||||||
| // | // | ||||||
| @@ -646,6 +669,7 @@ int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); | |||||||
| // Returns a negative error code on failure. | // Returns a negative error code on failure. | ||||||
| int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg); | int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg); | ||||||
| #endif | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user