mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-11-01 00:38:29 +01:00 
			
		
		
		
	WIP made basic tests pass
(format/dirs/files/seek/truncate/interspersed/paths)
This commit is contained in:
		
							
								
								
									
										140
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -475,7 +475,8 @@ struct lfs_commit { | |||||||
|  |  | ||||||
| // TODO predelcare | // TODO predelcare | ||||||
| static int lfs_commit_move_(lfs_t *lfs, struct lfs_commit *commit, | static int lfs_commit_move_(lfs_t *lfs, struct lfs_commit *commit, | ||||||
|         lfs_entry_t entry); |         uint16_t fromid, uint16_t toid, | ||||||
|  |         lfs_dir_t *dir, lfs_entrylist_t *list); | ||||||
|  |  | ||||||
| //static int lfs_commit_compactcheck(lfs_t *lfs, void *p, lfs_entry_t entry) { | //static int lfs_commit_compactcheck(lfs_t *lfs, void *p, lfs_entry_t entry) { | ||||||
| //    struct lfs_commit *commit = p; | //    struct lfs_commit *commit = p; | ||||||
| @@ -499,7 +500,9 @@ static int lfs_commit_commit(lfs_t *lfs, | |||||||
|  |  | ||||||
|     // special cases |     // special cases | ||||||
|     if ((lfs_tag_type(entry.tag) & 0x103) == LFS_FROM_MOVE) { |     if ((lfs_tag_type(entry.tag) & 0x103) == LFS_FROM_MOVE) { | ||||||
|         return lfs_commit_move_(lfs, commit, entry);  |         return lfs_commit_move_(lfs, commit, | ||||||
|  |                 lfs_tag_size(entry.tag), lfs_tag_id(entry.tag), | ||||||
|  |                 entry.u.dir, NULL);  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     uint16_t id = lfs_tag_id(entry.tag) - commit->filter.begin; |     uint16_t id = lfs_tag_id(entry.tag) - commit->filter.begin; | ||||||
| @@ -633,7 +636,7 @@ static int lfs_commit_list(lfs_t *lfs, struct lfs_commit *commit, | |||||||
| // committer for moves | // committer for moves | ||||||
| // TODO rename? | // TODO rename? | ||||||
| struct lfs_commit_move { | struct lfs_commit_move { | ||||||
|     lfs_dir_t *dir; |     lfs_dir_t *dir; // TODO need dir? | ||||||
|     struct { |     struct { | ||||||
|         uint16_t from; |         uint16_t from; | ||||||
|         uint16_t to; |         uint16_t to; | ||||||
| @@ -680,7 +683,8 @@ static int lfs_commit_movescan(lfs_t *lfs, void *p, lfs_entry_t entry) { | |||||||
|                 .stop_at_commit=true}, |                 .stop_at_commit=true}, | ||||||
|             lfs_tag_type(entry.tag) & 0x100 ? 0x7ffff000 : 0x7c1ff000, |             lfs_tag_type(entry.tag) & 0x100 ? 0x7ffff000 : 0x7c1ff000, | ||||||
|             &(lfs_entry_t){ |             &(lfs_entry_t){ | ||||||
|                 lfs_mktag(lfs_tag_type(entry.tag), move->id.to, 0)}); |                 lfs_mktag(lfs_tag_type(entry.tag), | ||||||
|  |                     move->id.to - move->commit->filter.begin, 0)}); // TODO can all these filter adjustments be consolidated? | ||||||
|     if (err && err != LFS_ERR_NOENT) { |     if (err && err != LFS_ERR_NOENT) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -714,15 +718,22 @@ static int lfs_commit_move(lfs_t *lfs, void *p, struct lfs_commit *commit) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_commit_move_(lfs_t *lfs, struct lfs_commit *commit, | static int lfs_commit_move_(lfs_t *lfs, struct lfs_commit *commit, | ||||||
|         lfs_entry_t entry) { |         uint16_t fromid, uint16_t toid, | ||||||
|  |         lfs_dir_t *dir, lfs_entrylist_t *list) { | ||||||
|     struct lfs_commit_move move = { |     struct lfs_commit_move move = { | ||||||
|         .dir = entry.u.dir, |         .id.from = fromid, | ||||||
|         .id.to = lfs_tag_id(entry.tag), |         .id.to = toid, | ||||||
|         .id.from = lfs_tag_size(entry.tag), |  | ||||||
|         .commit = commit, |         .commit = commit, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     int err = lfs_dir_traverse(lfs, entry.u.dir, lfs_commit_movescan, &move); |     for (; list; list = list->next) { | ||||||
|  |         int err = lfs_commit_movescan(lfs, &move, list->e); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     int err = lfs_dir_traverse(lfs, dir, lfs_commit_movescan, &move); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1185,6 +1196,7 @@ static int lfs_dir_compact_(lfs_t *lfs, lfs_dir_t *dir, lfs_entrylist_t *list, | |||||||
|     // save some state in case block is bad |     // save some state in case block is bad | ||||||
|     const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; |     const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; | ||||||
|     bool relocated = false; |     bool relocated = false; | ||||||
|  |     lfs_dir_t tail; | ||||||
|  |  | ||||||
|     // increment revision count |     // increment revision count | ||||||
|     dir->rev += 1; |     dir->rev += 1; | ||||||
| @@ -1236,22 +1248,23 @@ static int lfs_dir_compact_(lfs_t *lfs, lfs_dir_t *dir, lfs_entrylist_t *list, | |||||||
|                 .filter.end = end, |                 .filter.end = end, | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             // commit regions which can't fend for themselves | //            // commit regions which can't fend for themselves | ||||||
|             err = lfs_commit_list(lfs, &commit, list); | //            err = lfs_commit_list(lfs, &commit, list); | ||||||
|             if (err) { | //            if (err) { | ||||||
|                 if (err == LFS_ERR_NOSPC) { | //                if (err == LFS_ERR_NOSPC) { | ||||||
|                     goto split; | //                    goto split; | ||||||
|                 } else if (err == LFS_ERR_CORRUPT) { | //                } else if (err == LFS_ERR_CORRUPT) { | ||||||
|                     goto relocate; | //                    goto relocate; | ||||||
|                 } | //                } | ||||||
|                 return err; | //                return err; | ||||||
|             } | //            } | ||||||
|  | // | ||||||
|             // move over other commits, leaving it up to lfs_commit_move to | //            // move over other commits, leaving it up to lfs_commit_move to | ||||||
|             // filter out duplicates, and the commit filtering to reassign ids | //            // filter out duplicates, and the commit filtering to reassign ids | ||||||
|             for (uint16_t id = begin; id < end; id++) { |             for (uint16_t id = begin; id < end; id++) { | ||||||
|                 err = lfs_commit_commit(lfs, &commit, (lfs_entry_t){ |                 err = lfs_commit_move_(lfs, &commit, id, id, source, list); | ||||||
|                         lfs_mktag(LFS_FROM_MOVE, id, id), .u.dir=source}); | //                err = lfs_commit_commit(lfs, &commit, (lfs_entry_t){ | ||||||
|  | //                        lfs_mktag(LFS_FROM_MOVE, id, id), .u.dir=source}); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     if (err == LFS_ERR_NOSPC) { |                     if (err == LFS_ERR_NOSPC) { | ||||||
|                         goto split; |                         goto split; | ||||||
| @@ -1458,8 +1471,55 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, uint16_t *id) { | |||||||
|  |  | ||||||
| static int lfs_dir_delete(lfs_t *lfs, lfs_dir_t *dir, uint16_t id) { | static int lfs_dir_delete(lfs_t *lfs, lfs_dir_t *dir, uint16_t id) { | ||||||
|     dir->count -= 1; |     dir->count -= 1; | ||||||
|     return lfs_dir_commit_(lfs, dir, &(lfs_entrylist_t){ |  | ||||||
|  |     // check if we should drop the directory block | ||||||
|  |     if (dir->count == 0) { | ||||||
|  |         lfs_dir_t pdir; | ||||||
|  |         int res = lfs_pred(lfs, dir->pair, &pdir); | ||||||
|  |         if (res < 0) { | ||||||
|  |             return res; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (res && pdir.split) { | ||||||
|  |             pdir.split = dir->split; | ||||||
|  |             pdir.tail[0] = dir->tail[0]; | ||||||
|  |             pdir.tail[1] = dir->tail[1]; | ||||||
|  |             int err = lfs_dir_commit(lfs, &pdir, &(lfs_entrylist_t){ | ||||||
|  |                     {lfs_mktag(LFS_TYPE_SOFTTAIL + pdir.split*0x10, | ||||||
|  |                         0x1ff, sizeof(pdir.tail)), | ||||||
|  |                      .u.buffer=pdir.tail}}); | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     int err = lfs_dir_commit_(lfs, dir, &(lfs_entrylist_t){ | ||||||
|             {lfs_mktag(LFS_TYPE_DELETE, id, 0)}}); |             {lfs_mktag(LFS_TYPE_DELETE, id, 0)}}); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // shift over any files that are affected | ||||||
|  |     // TODO move this to dir_commit? | ||||||
|  |     for (lfs_file_t *f = lfs->files; f; f = f->next) { | ||||||
|  |         if (lfs_paircmp(f->pair, dir->pair) == 0) { | ||||||
|  |             if (f->id == id) { | ||||||
|  |                 f->pair[0] = 0xffffffff; | ||||||
|  |                 f->pair[1] = 0xffffffff; | ||||||
|  |             } else if (f->id > id) { | ||||||
|  |                 f->id -= 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | // TODO ? | ||||||
|  | //    for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { | ||||||
|  | //        if (lfs_paircmp(d->pair, dir->pair) == 0) { | ||||||
|  | //            if (d->id > id) { | ||||||
|  | //                d->id -= 1; | ||||||
|  | //                d->pos -= 1; | ||||||
|  | //            } | ||||||
|  | //        } | ||||||
|  | //    } | ||||||
| } | } | ||||||
|  |  | ||||||
| struct lfs_dir_getter { | struct lfs_dir_getter { | ||||||
| @@ -1674,7 +1734,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|  |  | ||||||
|         // find path |         // find path | ||||||
|         while (true) { |         while (true) { | ||||||
|             printf("checking %d %d for %s\n", entry.u.pair[0], entry.u.pair[1], *path); |             //printf("checking %d %d for %s\n", entry.u.pair[0], entry.u.pair[1], *path); | ||||||
|             find.id = -1; |             find.id = -1; | ||||||
|             int err = lfs_dir_fetchwith(lfs, dir, entry.u.pair, |             int err = lfs_dir_fetchwith(lfs, dir, entry.u.pair, | ||||||
|                     lfs_dir_finder, &find); |                     lfs_dir_finder, &find); | ||||||
| @@ -2796,11 +2856,14 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // first two for ./.. |     // first two for ./.. | ||||||
|     dir->id = lfs_min(2 + dir->count, off); |     dir->pos = lfs_min(2, off); | ||||||
|     dir->pos += dir->id; |     off -= dir->pos; | ||||||
|     off -= dir->id; |  | ||||||
|  |  | ||||||
|     while (off != 0) { |     while (off != 0) { | ||||||
|  |         dir->id = lfs_min(dir->count, off); | ||||||
|  |         dir->pos += dir->id; | ||||||
|  |         off -= dir->id; | ||||||
|  |  | ||||||
|         if (dir->id == dir->count) { |         if (dir->id == dir->count) { | ||||||
|             if (!dir->split) { |             if (!dir->split) { | ||||||
|                 return LFS_ERR_INVAL; |                 return LFS_ERR_INVAL; | ||||||
| @@ -2811,10 +2874,6 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) { | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         dir->id = lfs_min(dir->count, off); |  | ||||||
|         dir->pos += dir->id; |  | ||||||
|         off -= dir->id; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -3209,6 +3268,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // TODO do we need to make file registered to list to catch updates from this commit? ie if id/cwd change | ||||||
|         err = lfs_dir_commit_(lfs, &cwd, &(lfs_entrylist_t){ |         err = lfs_dir_commit_(lfs, &cwd, &(lfs_entrylist_t){ | ||||||
|                 {lfs_mktag(LFS_TYPE_NAME, id, nlen), |                 {lfs_mktag(LFS_TYPE_NAME, id, nlen), | ||||||
|                  .u.buffer=(void*)path}, &(lfs_entrylist_t){ |                  .u.buffer=(void*)path}, &(lfs_entrylist_t){ | ||||||
| @@ -3217,9 +3277,19 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // TODO eh | ||||||
|  |         if (id >= cwd.count) { | ||||||
|  |             // catch updates from a compact in the above commit | ||||||
|  |             id -= cwd.count; | ||||||
|  |             cwd.pair[0] = cwd.tail[0]; | ||||||
|  |             cwd.pair[1] = cwd.tail[1]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         entry.tag = lfs_mktag(LFS_TYPE_REG | LFS_STRUCT_INLINE, id, 0); |         entry.tag = lfs_mktag(LFS_TYPE_REG | LFS_STRUCT_INLINE, id, 0); | ||||||
|     } else { |     } else { | ||||||
|         if (flags & LFS_O_EXCL) { |         if (id == -1) { | ||||||
|  |             return LFS_ERR_ISDIR; | ||||||
|  |         } else if (flags & LFS_O_EXCL) { | ||||||
|             return LFS_ERR_EXIST; |             return LFS_ERR_EXIST; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -4502,7 +4572,7 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_dir_t *pdir) { | |||||||
|     pdir->tail[1] = 1; |     pdir->tail[1] = 1; | ||||||
|     while (!lfs_pairisnull(pdir->tail)) { |     while (!lfs_pairisnull(pdir->tail)) { | ||||||
|         if (lfs_paircmp(pdir->tail, pair) == 0) { |         if (lfs_paircmp(pdir->tail, pair) == 0) { | ||||||
|             return true; |             return true; // TODO should we return true only if pred is part of dir? | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int err = lfs_dir_fetch(lfs, pdir, pdir->tail); |         int err = lfs_dir_fetch(lfs, pdir, pdir->tail); | ||||||
|   | |||||||
| @@ -329,7 +329,7 @@ tests/test.py << TEST | |||||||
| TEST | TEST | ||||||
|  |  | ||||||
| echo "--- Multi-block remove ---" | echo "--- Multi-block remove ---" | ||||||
| tests/test.py -s << TEST | tests/test.py << TEST | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|     lfs_remove(&lfs, "cactus") => LFS_ERR_NOTEMPTY; |     lfs_remove(&lfs, "cactus") => LFS_ERR_NOTEMPTY; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user