mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	WIP adopted lisp-like dsl for more flexibility
This commit is contained in:
		
							
								
								
									
										114
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -474,32 +474,36 @@ static int lfs_dir_fetch(lfs_t *lfs, | ||||
| } | ||||
|  | ||||
| struct lfs_region { | ||||
|     lfs_off_t oldoff; | ||||
|     lfs_size_t oldlen; | ||||
|  | ||||
|     enum lfs_region_source { | ||||
|     enum { | ||||
|         LFS_FROM_MEM, | ||||
|         LFS_FROM_DISK, | ||||
|     } source; | ||||
|  | ||||
|     lfs_off_t oldoff; | ||||
|     lfs_size_t oldlen; | ||||
|     union { | ||||
|         const void *mem; | ||||
|         struct { | ||||
|             const void *data; | ||||
|         } m; | ||||
|         struct { | ||||
|             lfs_block_t block; | ||||
|             lfs_off_t off; | ||||
|         } disk; | ||||
|         } d; | ||||
|     } u; | ||||
|     lfs_size_t newlen; | ||||
|  | ||||
|     struct lfs_region *next; | ||||
| }; | ||||
|  | ||||
| static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | ||||
|         const struct lfs_region *regions, int count) { | ||||
|         struct lfs_region *region) { | ||||
|     // increment revision count | ||||
|     dir->d.rev += 1; | ||||
|  | ||||
|     // keep pairs in order such that pair[0] is most recent | ||||
|     lfs_pairswap(dir->pair); | ||||
|     for (int i = 0; i < count; i++) { | ||||
|         dir->d.size += regions[i].newlen - regions[i].oldlen; | ||||
|     for (struct lfs_region *r = region; r; r = r->next) { | ||||
|         dir->d.size += r->newlen - r->oldlen; | ||||
|     } | ||||
|  | ||||
|     const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; | ||||
| @@ -527,28 +531,27 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | ||||
|                 return err; | ||||
|             } | ||||
|  | ||||
|             int i = 0; | ||||
|             struct lfs_region *r = region; | ||||
|             int j = 0; | ||||
|             lfs_off_t oldoff = sizeof(dir->d); | ||||
|             lfs_off_t newoff = sizeof(dir->d); | ||||
|             while (newoff < (0x7fffffff & dir->d.size)-4) { | ||||
|                 while (i < count && oldoff == regions[i].oldoff && | ||||
|                         j == regions[i].newlen) { | ||||
|                     oldoff += regions[i].oldlen; | ||||
|                     i += 1; | ||||
|                 while (r && r->oldoff == oldoff && r->newlen == j) { | ||||
|                     oldoff += r->oldlen; | ||||
|                     r = r->next; | ||||
|                     j = 0; | ||||
|                 } | ||||
|  | ||||
|                 uint8_t data; | ||||
|                 if (i < count && regions[i].oldoff == oldoff) { | ||||
|                     if (regions[i].source == LFS_FROM_DISK) { | ||||
|                         err = lfs_bd_read(lfs, regions[i].u.disk.block, | ||||
|                                 regions[i].u.disk.off + j, &data, 1); | ||||
|                 if (r && r->oldoff == oldoff) { | ||||
|                     if (r->source == LFS_FROM_DISK) { | ||||
|                         err = lfs_bd_read(lfs, r->u.d.block, | ||||
|                                 r->u.d.off + j, &data, 1); | ||||
|                         if (err) { | ||||
|                             return err; | ||||
|                         } | ||||
|                     } else { | ||||
|                         data = ((const uint8_t *)regions[i].u.mem)[j]; | ||||
|                         data = ((const uint8_t *)r->u.m.data)[j]; | ||||
|                     } | ||||
|  | ||||
|                     j += 1; | ||||
| @@ -650,12 +653,15 @@ relocate: | ||||
| static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | ||||
|         lfs_entry_t *entry, const void *data) { | ||||
|     lfs_entry_tole32(&entry->d); | ||||
|     int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||
|             {entry->off, sizeof(entry->d), | ||||
|                 LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, | ||||
|             {entry->off+sizeof(entry->d), entry->d.nlen, | ||||
|                 LFS_FROM_MEM, {.mem = data}, entry->d.nlen} | ||||
|         }, data ? 2 : 1); | ||||
|     int err = lfs_dir_commit(lfs, dir, | ||||
|             &(struct lfs_region){ | ||||
|                 LFS_FROM_MEM, entry->off, sizeof(entry->d), | ||||
|                 {.m.data = &entry->d}, sizeof(entry->d), | ||||
|             data ? | ||||
|                 &(struct lfs_region){ | ||||
|                     LFS_FROM_MEM, entry->off+sizeof(entry->d), entry->d.nlen, | ||||
|                     {.m.data = data}, entry->d.nlen} | ||||
|                 : NULL}); | ||||
|     lfs_entry_fromle32(&entry->d); | ||||
|     return err; | ||||
| } | ||||
| @@ -668,12 +674,13 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||
|             entry->off = dir->d.size - 4; | ||||
|  | ||||
|             lfs_entry_tole32(&entry->d); | ||||
|             int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||
|                     {entry->off, 0, | ||||
|                         LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, | ||||
|                     {entry->off, 0, | ||||
|                         LFS_FROM_MEM, {.mem = data}, entry->d.nlen} | ||||
|                 }, 2); | ||||
|             int err = lfs_dir_commit(lfs, dir, | ||||
|                     &(struct lfs_region){ | ||||
|                         LFS_FROM_MEM, entry->off, 0, | ||||
|                         {.m.data = &entry->d}, sizeof(entry->d), | ||||
|                     &(struct lfs_region){ | ||||
|                         LFS_FROM_MEM, entry->off, 0, | ||||
|                         {.m.data = data}, entry->d.nlen}}); | ||||
|             lfs_entry_fromle32(&entry->d); | ||||
|             return err; | ||||
|         } | ||||
| @@ -690,12 +697,13 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||
|             dir->d.tail[1] = olddir.d.tail[1]; | ||||
|             entry->off = dir->d.size - 4; | ||||
|             lfs_entry_tole32(&entry->d); | ||||
|             err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||
|                     {entry->off, 0, | ||||
|                         LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, | ||||
|                     {entry->off, 0, | ||||
|                         LFS_FROM_MEM, {.mem = data}, entry->d.nlen} | ||||
|                 }, 2); | ||||
|             err = lfs_dir_commit(lfs, dir, | ||||
|                     &(struct lfs_region){ | ||||
|                         LFS_FROM_MEM, entry->off, 0, | ||||
|                         {.m.data = &entry->d}, sizeof(entry->d), | ||||
|                     &(struct lfs_region){ | ||||
|                         LFS_FROM_MEM, entry->off, 0, | ||||
|                         {.m.data = data}, entry->d.nlen}}); | ||||
|             lfs_entry_fromle32(&entry->d); | ||||
|             if (err) { | ||||
|                 return err; | ||||
| @@ -704,7 +712,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||
|             olddir.d.size |= 0x80000000; | ||||
|             olddir.d.tail[0] = dir->pair[0]; | ||||
|             olddir.d.tail[1] = dir->pair[1]; | ||||
|             return lfs_dir_commit(lfs, &olddir, NULL, 0); | ||||
|             return lfs_dir_commit(lfs, &olddir, NULL); | ||||
|         } | ||||
|  | ||||
|         int err = lfs_dir_fetch(lfs, dir, dir->d.tail); | ||||
| @@ -728,15 +736,14 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | ||||
|             pdir.d.size &= dir->d.size | 0x7fffffff; | ||||
|             pdir.d.tail[0] = dir->d.tail[0]; | ||||
|             pdir.d.tail[1] = dir->d.tail[1]; | ||||
|             return lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||
|             return lfs_dir_commit(lfs, &pdir, NULL); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // shift out the entry | ||||
|     int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||
|             {entry->off, lfs_entry_size(entry), | ||||
|                 LFS_FROM_MEM, {.mem = NULL}, 0}, | ||||
|         }, 1); | ||||
|     int err = lfs_dir_commit(lfs, dir, &(struct lfs_region){ | ||||
|             LFS_FROM_MEM, entry->off, lfs_entry_size(entry), | ||||
|             {.m.data = NULL}, 0}); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -941,7 +948,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | ||||
|     dir.d.tail[0] = cwd.d.tail[0]; | ||||
|     dir.d.tail[1] = cwd.d.tail[1]; | ||||
|  | ||||
|     err = lfs_dir_commit(lfs, &dir, NULL, 0); | ||||
|     err = lfs_dir_commit(lfs, &dir, NULL); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -1911,7 +1918,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | ||||
|         cwd.d.tail[0] = dir.d.tail[0]; | ||||
|         cwd.d.tail[1] = dir.d.tail[1]; | ||||
|  | ||||
|         err = lfs_dir_commit(lfs, &cwd, NULL, 0); | ||||
|         err = lfs_dir_commit(lfs, &cwd, NULL); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
| @@ -2028,7 +2035,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||
|         newcwd.d.tail[0] = dir.d.tail[0]; | ||||
|         newcwd.d.tail[1] = dir.d.tail[1]; | ||||
|  | ||||
|         err = lfs_dir_commit(lfs, &newcwd, NULL, 0); | ||||
|         err = lfs_dir_commit(lfs, &newcwd, NULL); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
| @@ -2138,7 +2145,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     err = lfs_dir_commit(lfs, &root, NULL, 0); | ||||
|     err = lfs_dir_commit(lfs, &root, NULL); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -2166,10 +2173,9 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|     lfs_superblock_tole32(&superblock.d); | ||||
|     bool valid = false; | ||||
|     for (int i = 0; i < 2; i++) { | ||||
|         err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){ | ||||
|                 {sizeof(superdir.d), sizeof(superblock.d), | ||||
|                     LFS_FROM_MEM, {.mem = &superblock.d}, sizeof(superblock.d)} | ||||
|             }, 1); | ||||
|         err = lfs_dir_commit(lfs, &superdir, &(struct lfs_region){ | ||||
|                 LFS_FROM_MEM, sizeof(superdir.d), sizeof(superblock.d), | ||||
|                 {.m.data = &superblock.d}, sizeof(superblock.d)}); | ||||
|         if (err && err != LFS_ERR_CORRUPT) { | ||||
|             return err; | ||||
|         } | ||||
| @@ -2460,7 +2466,7 @@ static int lfs_relocate(lfs_t *lfs, | ||||
|         parent.d.tail[0] = newpair[0]; | ||||
|         parent.d.tail[1] = newpair[1]; | ||||
|  | ||||
|         return lfs_dir_commit(lfs, &parent, NULL, 0); | ||||
|         return lfs_dir_commit(lfs, &parent, NULL); | ||||
|     } | ||||
|  | ||||
|     // couldn't find dir, must be new | ||||
| @@ -2502,7 +2508,7 @@ int lfs_deorphan(lfs_t *lfs) { | ||||
|                 pdir.d.tail[0] = cwd.d.tail[0]; | ||||
|                 pdir.d.tail[1] = cwd.d.tail[1]; | ||||
|  | ||||
|                 err = lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||
|                 err = lfs_dir_commit(lfs, &pdir, NULL); | ||||
|                 if (err) { | ||||
|                     return err; | ||||
|                 } | ||||
| @@ -2518,7 +2524,7 @@ int lfs_deorphan(lfs_t *lfs) { | ||||
|                 pdir.d.tail[0] = entry.d.u.dir[0]; | ||||
|                 pdir.d.tail[1] = entry.d.u.dir[1]; | ||||
|  | ||||
|                 err = lfs_dir_commit(lfs, &pdir, NULL, 0); | ||||
|                 err = lfs_dir_commit(lfs, &pdir, NULL); | ||||
|                 if (err) { | ||||
|                     return err; | ||||
|                 } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user