mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	WIP added support for inline files up to 1023 bytes
This commit is contained in:
		
							
								
								
									
										103
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -371,6 +371,26 @@ static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { | |||||||
|     d->name_size   = lfs_tole32(d->name_size); |     d->name_size   = lfs_tole32(d->name_size); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Other struct functions /// | ||||||
|  | static inline lfs_size_t lfs_entry_elen(const lfs_entry_t *entry) { | ||||||
|  |     return (lfs_size_t)(entry->d.elen) | | ||||||
|  |         ((lfs_size_t)(entry->d.alen & 0xc0) << 2); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline lfs_size_t lfs_entry_alen(const lfs_entry_t *entry) { | ||||||
|  |     return entry->d.alen & 0x3f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline lfs_size_t lfs_entry_nlen(const lfs_entry_t *entry) { | ||||||
|  |     return entry->d.nlen; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline lfs_size_t lfs_entry_size(const lfs_entry_t *entry) { | ||||||
|  |     return 4 + lfs_entry_elen(entry) + | ||||||
|  |             lfs_entry_alen(entry) + | ||||||
|  |             lfs_entry_nlen(entry); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Metadata pair and directory operations /// | /// Metadata pair and directory operations /// | ||||||
| static inline void lfs_pairswap(lfs_block_t pair[2]) { | static inline void lfs_pairswap(lfs_block_t pair[2]) { | ||||||
| @@ -563,7 +583,7 @@ static int lfs_commit_region(lfs_t *lfs, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dif_commit(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         const struct lfs_region *regions, int count) { |         const struct lfs_region *regions, int count) { | ||||||
|     // state for copying over |     // state for copying over | ||||||
|     const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; |     const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; | ||||||
| @@ -723,7 +743,7 @@ static int lfs_dir_set(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             type |= LFS_STRUCT_MOVED; |             type |= LFS_STRUCT_MOVED; | ||||||
|             err = lfs_dif_commit(lfs, &olddir, (struct lfs_region[]){ |             err = lfs_dir_commit(lfs, &olddir, (struct lfs_region[]){ | ||||||
|                         {LFS_FROM_MEM, oldoff, &type, 1}, |                         {LFS_FROM_MEM, oldoff, &type, 1}, | ||||||
|                         {LFS_FROM_DROP, oldoff, NULL, -1}}, 2); |                         {LFS_FROM_DROP, oldoff, NULL, -1}}, 2); | ||||||
|             if (err) { |             if (err) { | ||||||
| @@ -759,7 +779,7 @@ static int lfs_dir_set(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, | |||||||
|         // writing out new entry |         // writing out new entry | ||||||
|         entry->off = dir->d.size - 4; |         entry->off = dir->d.size - 4; | ||||||
|         entry->size += diff; |         entry->size += diff; | ||||||
|         int err = lfs_dif_commit(lfs, dir, (struct lfs_region[]){ |         int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||||
|                 {LFS_FROM_REGION, entry->off, &(struct lfs_region_region){ |                 {LFS_FROM_REGION, entry->off, &(struct lfs_region_region){ | ||||||
|                     olddir.pair[0], oldoff, |                     olddir.pair[0], oldoff, | ||||||
|                     regions, count}, entry->size}}, 1); |                     regions, count}, entry->size}}, 1); | ||||||
| @@ -773,7 +793,7 @@ static int lfs_dir_set(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, | |||||||
|             pdir.d.tail[0] = dir->pair[0]; |             pdir.d.tail[0] = dir->pair[0]; | ||||||
|             pdir.d.tail[1] = dir->pair[1]; |             pdir.d.tail[1] = dir->pair[1]; | ||||||
|  |  | ||||||
|             err = lfs_dif_commit(lfs, &pdir, NULL, 0); |             err = lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -808,7 +828,7 @@ static int lfs_dir_set(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, | |||||||
|             pdir.d.size &= dir->d.size | 0x7fffffff; |             pdir.d.size &= dir->d.size | 0x7fffffff; | ||||||
|             pdir.d.tail[0] = dir->d.tail[0]; |             pdir.d.tail[0] = dir->d.tail[0]; | ||||||
|             pdir.d.tail[1] = dir->d.tail[1]; |             pdir.d.tail[1] = dir->d.tail[1]; | ||||||
|             int err = lfs_dif_commit(lfs, &pdir, NULL, 0); |             int err = lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -820,7 +840,7 @@ static int lfs_dir_set(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, | |||||||
|         regions[i].off += entry->off; |         regions[i].off += entry->off; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int err = lfs_dif_commit(lfs, dir, regions, count); |     int err = lfs_dir_commit(lfs, dir, regions, count); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -875,7 +895,7 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     entry->off = dir->off; |     entry->off = dir->off; | ||||||
|     entry->size = 4 + entry->d.elen + entry->d.alen + entry->d.nlen; |     entry->size = lfs_entry_size(entry); | ||||||
|     dir->off += entry->size; |     dir->off += entry->size; | ||||||
|     dir->pos += entry->size; |     dir->pos += entry->size; | ||||||
|     return 0; |     return 0; | ||||||
| @@ -1031,7 +1051,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     dir.d.tail[0] = cwd.d.tail[0]; |     dir.d.tail[0] = cwd.d.tail[0]; | ||||||
|     dir.d.tail[1] = cwd.d.tail[1]; |     dir.d.tail[1] = cwd.d.tail[1]; | ||||||
|  |  | ||||||
|     err = lfs_dif_commit(lfs, &dir, NULL, 0); |     err = lfs_dir_commit(lfs, &dir, NULL, 0); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1156,7 +1176,7 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | |||||||
|     if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { |     if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { | ||||||
|         info->size = entry.d.u.file.size; |         info->size = entry.d.u.file.size; | ||||||
|     } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { |     } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { | ||||||
|         info->size = entry.d.elen; |         info->size = lfs_entry_elen(&entry); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int err = lfs_dir_get(lfs, dir, |     int err = lfs_dir_get(lfs, dir, | ||||||
| @@ -1470,29 +1490,22 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO combine these below? |  | ||||||
|     // setup file struct |     // setup file struct | ||||||
|     file->pair[0] = cwd.pair[0]; |     file->pair[0] = cwd.pair[0]; | ||||||
|     file->pair[1] = cwd.pair[1]; |     file->pair[1] = cwd.pair[1]; | ||||||
|     file->poff = entry.off; |     file->poff = entry.off; | ||||||
|     file->head = entry.d.u.file.head; |  | ||||||
|     file->size = entry.d.u.file.size; |  | ||||||
|     file->flags = flags; |     file->flags = flags; | ||||||
|     file->pos = 0; |     file->pos = 0; | ||||||
|  |  | ||||||
|     if (flags & LFS_O_TRUNC) { |     // calculate max inline size based on the size of the entry | ||||||
|         if (file->size != 0) { |     file->inline_size = lfs_min(lfs->inline_size, | ||||||
|             file->flags |= LFS_F_DIRTY; |         lfs->cfg->block_size - (sizeof(cwd.d)+4) - | ||||||
|         } |         (lfs_entry_size(&entry) - lfs_entry_elen(&entry))); | ||||||
|  |  | ||||||
|         entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; |  | ||||||
|         entry.d.elen = 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // load inline files |  | ||||||
|     if ((0x70 & entry.d.type) == LFS_STRUCT_INLINE) { |     if ((0x70 & entry.d.type) == LFS_STRUCT_INLINE) { | ||||||
|  |         // load inline files | ||||||
|         file->head = 0xfffffffe; |         file->head = 0xfffffffe; | ||||||
|         file->size = entry.d.elen; |         file->size = lfs_entry_elen(&entry); | ||||||
|         file->flags |= LFS_F_INLINE; |         file->flags |= LFS_F_INLINE; | ||||||
|         file->cache.block = file->head; |         file->cache.block = file->head; | ||||||
|         file->cache.off = 0; |         file->cache.off = 0; | ||||||
| @@ -1503,6 +1516,23 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|             lfs_free(file->cache.buffer); |             lfs_free(file->cache.buffer); | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |     } else { | ||||||
|  |         // use ctz list from entry | ||||||
|  |         file->head = entry.d.u.file.head; | ||||||
|  |         file->size = entry.d.u.file.size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // truncate if requested | ||||||
|  |     if (flags & LFS_O_TRUNC) { | ||||||
|  |         if (file->size != 0) { | ||||||
|  |             file->flags |= LFS_F_DIRTY; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         file->head = 0xfffffffe; | ||||||
|  |         file->size = 0; | ||||||
|  |         file->flags |= LFS_F_INLINE; | ||||||
|  |         file->cache.block = file->head; | ||||||
|  |         file->cache.off = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // add to list of files |     // add to list of files | ||||||
| @@ -1676,8 +1706,8 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         LFS_ASSERT((0xf & entry.d.type) == LFS_TYPE_REG); |         LFS_ASSERT((0xf & entry.d.type) == LFS_TYPE_REG); | ||||||
|         lfs_size_t oldlen = entry.d.elen; |         lfs_size_t oldlen = lfs_entry_elen(&entry); | ||||||
|         entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; |         entry.size = lfs_entry_size(&entry); | ||||||
|  |  | ||||||
|         // either update the references or inline the whole file |         // either update the references or inline the whole file | ||||||
|         if (!(file->flags & LFS_F_INLINE)) { |         if (!(file->flags & LFS_F_INLINE)) { | ||||||
| @@ -1694,7 +1724,8 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; |             entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; | ||||||
|             entry.d.elen = file->size; |             entry.d.elen = file->size & 0xff; | ||||||
|  |             entry.d.alen = (entry.d.alen & 0x3f) | ((file->size >> 2) & 0xc0); | ||||||
|  |  | ||||||
|             err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ |             err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|                     {LFS_FROM_MEM, 0, &entry.d, 4}, |                     {LFS_FROM_MEM, 0, &entry.d, 4}, | ||||||
| @@ -1812,7 +1843,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|     // TODO store INLINE_MAX in superblock? |     // TODO store INLINE_MAX in superblock? | ||||||
|     // TODO what if inline files is > block size (ie 128) |     // TODO what if inline files is > block size (ie 128) | ||||||
|     if ((file->flags & LFS_F_INLINE) && |     if ((file->flags & LFS_F_INLINE) && | ||||||
|             file->pos + nsize >= lfs->inline_size) { |             file->pos + nsize >= file->inline_size) { | ||||||
|         file->block = 0xfffffffe; |         file->block = 0xfffffffe; | ||||||
|         file->off = file->pos; |         file->off = file->pos; | ||||||
|  |  | ||||||
| @@ -2024,7 +2055,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | |||||||
|     if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { |     if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { | ||||||
|         info->size = entry.d.u.file.size; |         info->size = entry.d.u.file.size; | ||||||
|     } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { |     } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { | ||||||
|         info->size = entry.d.elen; |         info->size = lfs_entry_elen(&entry); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { |     if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { | ||||||
| @@ -2093,7 +2124,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|         cwd.d.tail[0] = dir.d.tail[0]; |         cwd.d.tail[0] = dir.d.tail[0]; | ||||||
|         cwd.d.tail[1] = dir.d.tail[1]; |         cwd.d.tail[1] = dir.d.tail[1]; | ||||||
|  |  | ||||||
|         err = lfs_dif_commit(lfs, &cwd, NULL, 0); |         err = lfs_dir_commit(lfs, &cwd, NULL, 0); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2224,7 +2255,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|         newcwd.d.tail[0] = dir.d.tail[0]; |         newcwd.d.tail[0] = dir.d.tail[0]; | ||||||
|         newcwd.d.tail[1] = dir.d.tail[1]; |         newcwd.d.tail[1] = dir.d.tail[1]; | ||||||
|  |  | ||||||
|         err = lfs_dif_commit(lfs, &newcwd, NULL, 0); |         err = lfs_dir_commit(lfs, &newcwd, NULL, 0); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2354,7 +2385,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_dif_commit(lfs, &root, NULL, 0); |     err = lfs_dir_commit(lfs, &root, NULL, 0); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -2436,14 +2467,14 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     memset(&superblock.d, 0, sizeof(superblock.d)); |     memset(&superblock.d, 0, sizeof(superblock.d)); | ||||||
|     err = lfs_dir_get(lfs, &dir, |     err = lfs_dir_get(lfs, &dir, | ||||||
|             sizeof(dir.d)+4, &superblock.d, |             sizeof(dir.d)+4, &superblock.d, | ||||||
|             lfs_min(sizeof(superblock.d), entry.d.elen)); |             lfs_min(sizeof(superblock.d), lfs_entry_elen(&entry))); | ||||||
|     lfs_superblock_fromle32(&superblock.d); |     lfs_superblock_fromle32(&superblock.d); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_dir_get(lfs, &dir, |     err = lfs_dir_get(lfs, &dir, | ||||||
|             sizeof(dir.d)+4+entry.d.elen+entry.d.alen, magic, |             sizeof(dir.d)+lfs_entry_size(&entry)-entry.d.nlen, magic, | ||||||
|             lfs_min(sizeof(magic), entry.d.nlen)); |             lfs_min(sizeof(magic), entry.d.nlen)); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
| @@ -2536,7 +2567,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             dir.off += 4 + entry.d.elen + entry.d.alen + entry.d.nlen; |             dir.off += lfs_entry_size(&entry); | ||||||
|             if ((0x70 & entry.d.type) == LFS_STRUCT_CTZ) { |             if ((0x70 & entry.d.type) == LFS_STRUCT_CTZ) { | ||||||
|                 err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, |                 err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, | ||||||
|                         entry.d.u.file.head, entry.d.u.file.size, cb, data); |                         entry.d.u.file.head, entry.d.u.file.size, cb, data); | ||||||
| @@ -2720,7 +2751,7 @@ static int lfs_relocate(lfs_t *lfs, | |||||||
|         parent.d.tail[0] = newpair[0]; |         parent.d.tail[0] = newpair[0]; | ||||||
|         parent.d.tail[1] = newpair[1]; |         parent.d.tail[1] = newpair[1]; | ||||||
|  |  | ||||||
|         return lfs_dif_commit(lfs, &parent, NULL, 0); |         return lfs_dir_commit(lfs, &parent, NULL, 0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // couldn't find dir, must be new |     // couldn't find dir, must be new | ||||||
| @@ -2762,7 +2793,7 @@ int lfs_deorphan(lfs_t *lfs) { | |||||||
|                 pdir.d.tail[0] = cwd.d.tail[0]; |                 pdir.d.tail[0] = cwd.d.tail[0]; | ||||||
|                 pdir.d.tail[1] = cwd.d.tail[1]; |                 pdir.d.tail[1] = cwd.d.tail[1]; | ||||||
|  |  | ||||||
|                 err = lfs_dif_commit(lfs, &pdir, NULL, 0); |                 err = lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
| @@ -2778,7 +2809,7 @@ int lfs_deorphan(lfs_t *lfs) { | |||||||
|                 pdir.d.tail[0] = entry.d.u.dir[0]; |                 pdir.d.tail[0] = entry.d.u.dir[0]; | ||||||
|                 pdir.d.tail[1] = entry.d.u.dir[1]; |                 pdir.d.tail[1] = entry.d.u.dir[1]; | ||||||
|  |  | ||||||
|                 err = lfs_dif_commit(lfs, &pdir, NULL, 0); |                 err = lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -52,17 +52,17 @@ typedef uint32_t lfs_block_t; | |||||||
|  |  | ||||||
| // Maximum inline file size in bytes | // Maximum inline file size in bytes | ||||||
| #ifndef LFS_INLINE_MAX | #ifndef LFS_INLINE_MAX | ||||||
| #define LFS_INLINE_MAX 255 | #define LFS_INLINE_MAX 0x3ff | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Maximum size of all attributes per file in bytes | // Maximum size of all attributes per file in bytes | ||||||
| #ifndef LFS_ATTRS_MAX | #ifndef LFS_ATTRS_MAX | ||||||
| #define LFS_ATTRS_MAX 255 | #define LFS_ATTRS_MAX 0x3f | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Max name size in bytes | // Max name size in bytes | ||||||
| #ifndef LFS_NAME_MAX | #ifndef LFS_NAME_MAX | ||||||
| #define LFS_NAME_MAX 255 | #define LFS_NAME_MAX 0xff | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Possible error codes, these are negative to allow | // Possible error codes, these are negative to allow | ||||||
| @@ -248,6 +248,7 @@ typedef struct lfs_file { | |||||||
|     lfs_size_t size; |     lfs_size_t size; | ||||||
|  |  | ||||||
|     uint32_t flags; |     uint32_t flags; | ||||||
|  |     lfs_size_t inline_size; | ||||||
|     lfs_off_t pos; |     lfs_off_t pos; | ||||||
|     lfs_block_t block; |     lfs_block_t block; | ||||||
|     lfs_off_t off; |     lfs_off_t off; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user