mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Added internal lfs_dir_set, an umbrella to dir append/update/remove operations
This move was surprisingly complex, but offers the ultimate opportunity for code reuse in terms of resizable entries. Instead of needing to provide separate functions for adding and removing entries, adding and removing entries can just be viewed as changing an entry's size to-and-from zero. Unfortunately, it's not _quite_ that simple, since append and remove hide some relatively complex operations for when directory blocks overflow or need to be cleaned up. However, with enough shoehorning, and a new committer type that allows specifying recursive commit lists (is this now a push-down automata?), it does seem to be possible to shove all of the entry update logic into a single function. Sidenote, I switched back to an enum-based DSL, since the addition of a recursive region opcode breaks the consistency of what needs to be passed to the DSL callback functions. It's much simpler to handle each opcode explicitly inside a recursive lfs_commit_region function.
This commit is contained in:
		
							
								
								
									
										579
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										579
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -152,6 +152,7 @@ static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache, | |||||||
|         lfs_off_t off, const void *buffer, lfs_size_t size) { |         lfs_off_t off, const void *buffer, lfs_size_t size) { | ||||||
|     const uint8_t *data = buffer; |     const uint8_t *data = buffer; | ||||||
|     LFS_ASSERT(block != 0xffffffff); |     LFS_ASSERT(block != 0xffffffff); | ||||||
|  |     LFS_ASSERT(off + size <= lfs->cfg->block_size); | ||||||
|  |  | ||||||
|     while (size > 0) { |     while (size > 0) { | ||||||
|         if (block == pcache->block && off >= pcache->off && |         if (block == pcache->block && off >= pcache->off && | ||||||
| @@ -483,83 +484,93 @@ static int lfs_dir_fetch(lfs_t *lfs, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| struct lfs_commit { |  | ||||||
|     uint32_t crc; |  | ||||||
|     lfs_block_t block; |  | ||||||
|     lfs_off_t off; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int lfs_commit(lfs_t *lfs, struct lfs_commit *c, |  | ||||||
|         const void *data, lfs_size_t size) { |  | ||||||
|     lfs_crc(&c->crc, data, size); |  | ||||||
|     int err = lfs_bd_prog(lfs, c->block, c->off, data, size); |  | ||||||
|     c->off += size; |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct lfs_region { | struct lfs_region { | ||||||
|     lfs_off_t off; |     enum { | ||||||
|     lfs_ssize_t diff; |         LFS_FROM_DROP, | ||||||
|  |         LFS_FROM_MEM, | ||||||
|  |         LFS_FROM_REGION, | ||||||
|  |     } type; | ||||||
|  |  | ||||||
|     int (*commit)(lfs_t *lfs, struct lfs_commit *c, |     lfs_off_t off; | ||||||
|             const void *data, lfs_size_t size); |     const void *buffer; | ||||||
|     const void *data; |     lfs_ssize_t size; | ||||||
|     lfs_size_t size; |  | ||||||
|     struct lfs_region *next; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int lfs_commit_mem(lfs_t *lfs, struct lfs_commit *c, | struct lfs_region_region { | ||||||
|         const void *data, lfs_size_t size) { |  | ||||||
|     return lfs_commit(lfs, c, data, size); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct lfs_commit_disk { |  | ||||||
|     lfs_block_t block; |     lfs_block_t block; | ||||||
|     lfs_off_t off; |     lfs_off_t off; | ||||||
|     struct lfs_region *regions; |     struct lfs_region *regions; | ||||||
|  |     int count; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int lfs_commit_disk(lfs_t *lfs, struct lfs_commit *c, | static int lfs_commit_region(lfs_t *lfs, | ||||||
|         const void *p, lfs_size_t size) { |         lfs_block_t oldblock, lfs_off_t oldoff, | ||||||
|     const struct lfs_commit_disk *d = p; |         lfs_block_t newblock, lfs_off_t newoff, | ||||||
|  |         lfs_off_t regionoff, | ||||||
|     struct lfs_region *r = d->regions; |         const struct lfs_region *regions, int count, | ||||||
|     lfs_off_t off = 0; |         lfs_size_t size, uint32_t *crc) { | ||||||
|     while (true) { |     int i = 0; | ||||||
|         if (r && r->off == off) { |     lfs_size_t end = newoff + size; | ||||||
|             lfs_off_t orig = c->off; |     while (newoff < end) { | ||||||
|             int err = r->commit(lfs, c, r->data, r->size); |         // commit from different types of regions | ||||||
|             if (err) { |         if (i < count && regions[i].off == oldoff - regionoff) { | ||||||
|                 return err; |             switch (regions[i].type) { | ||||||
|  |                 case LFS_FROM_DROP: { | ||||||
|  |                     oldoff -= regions[i].size; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case LFS_FROM_MEM: { | ||||||
|  |                     lfs_crc(crc, regions[i].buffer, regions[i].size); | ||||||
|  |                     int err = lfs_bd_prog(lfs, newblock, newoff, | ||||||
|  |                             regions[i].buffer, regions[i].size); | ||||||
|  |                     if (err) { | ||||||
|  |                         return err; | ||||||
|  |                     } | ||||||
|  |                     newoff += regions[i].size; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case LFS_FROM_REGION: { | ||||||
|  |                     const struct lfs_region_region *disk = regions[i].buffer; | ||||||
|  |                     int err = lfs_commit_region(lfs, | ||||||
|  |                             disk->block, disk->off, | ||||||
|  |                             newblock, newoff, | ||||||
|  |                             disk->off, disk->regions, disk->count, | ||||||
|  |                             regions[i].size, crc); | ||||||
|  |                     if (err) { | ||||||
|  |                         return err; | ||||||
|  |                     } | ||||||
|  |                     newoff += regions[i].size; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             off += (c->off - orig) - r->diff; |             i += 1; | ||||||
|             r = r->next; |  | ||||||
|         } else if (off < size) { |  | ||||||
|             uint8_t data; |  | ||||||
|             int err = lfs_bd_read(lfs, d->block, d->off + off, &data, 1); |  | ||||||
|             if (err) { |  | ||||||
|                 return err; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             err = lfs_commit(lfs, c, &data, 1); |  | ||||||
|             if (err) { |  | ||||||
|                 return err; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             off += 1; |  | ||||||
|         } else { |         } else { | ||||||
|             return 0; |             // copy data from old block if not covered by region | ||||||
|  |             uint8_t data; | ||||||
|  |             int err = lfs_bd_read(lfs, oldblock, oldoff, &data, 1); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             lfs_crc(crc, &data, 1); | ||||||
|  |             err = lfs_bd_prog(lfs, newblock, newoff, &data, 1); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             oldoff += 1; | ||||||
|  |             newoff += 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| // TODO handle overflowing reads (zero?) | 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) { | ||||||
|         struct lfs_region *regions) { |  | ||||||
|     // 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]}; | ||||||
|     lfs_size_t oldsize = (0x7fffffff & dir->d.size) - 4; |  | ||||||
|     bool relocated = false; |     bool relocated = false; | ||||||
|  |  | ||||||
|     // increment revision count |     // increment revision count | ||||||
| @@ -567,8 +578,8 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|  |  | ||||||
|     // keep pairs in order such that pair[0] is most recent |     // keep pairs in order such that pair[0] is most recent | ||||||
|     lfs_pairswap(dir->pair); |     lfs_pairswap(dir->pair); | ||||||
|     for (struct lfs_region *r = regions; r; r = r->next) { |     for (int i = 0; i < count; i++) { | ||||||
|         dir->d.size += r->diff; |         dir->d.size += regions[i].size; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     while (true) { |     while (true) { | ||||||
| @@ -581,19 +592,11 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             struct lfs_commit c = { |             // commit header | ||||||
|                 .crc = 0xffffffff, |             uint32_t crc = 0xffffffff; | ||||||
|                 .block = dir->pair[0], |  | ||||||
|                 .off = 0, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             lfs_dir_tole32(&dir->d); |             lfs_dir_tole32(&dir->d); | ||||||
|             err = lfs_commit_disk(lfs, &c, &(struct lfs_commit_disk){ |             lfs_crc(&crc, &dir->d, sizeof(dir->d)); | ||||||
|                     oldpair[1], 0, |             err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d)); | ||||||
|                     &(struct lfs_region){ |  | ||||||
|                         0, 0, |  | ||||||
|                         lfs_commit_mem, &dir->d, sizeof(dir->d), |  | ||||||
|                         regions}}, oldsize); |  | ||||||
|             lfs_dir_fromle32(&dir->d); |             lfs_dir_fromle32(&dir->d); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 if (err == LFS_ERR_CORRUPT) { |                 if (err == LFS_ERR_CORRUPT) { | ||||||
| @@ -602,9 +605,25 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             c.crc = lfs_tole32(c.crc); |             // commit region | ||||||
|             err = lfs_bd_prog(lfs, dir->pair[0], c.off, &c.crc, 4); |             err = lfs_commit_region(lfs, | ||||||
|             c.crc = lfs_fromle32(c.crc); |                     dir->pair[1], sizeof(dir->d), | ||||||
|  |                     dir->pair[0], sizeof(dir->d), | ||||||
|  |                     0, regions, count, | ||||||
|  |                     (0x7fffffff & dir->d.size)-sizeof(dir->d)-4, | ||||||
|  |                     &crc); | ||||||
|  |             if (err) { | ||||||
|  |                 if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                     goto relocate; | ||||||
|  |                 } | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // commit crc | ||||||
|  |             crc = lfs_tole32(crc); | ||||||
|  |             err = lfs_bd_prog(lfs, dir->pair[0], | ||||||
|  |                     (0x7fffffff & dir->d.size)-4, &crc, 4); | ||||||
|  |             crc = lfs_fromle32(crc); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 if (err == LFS_ERR_CORRUPT) { |                 if (err == LFS_ERR_CORRUPT) { | ||||||
|                     goto relocate; |                     goto relocate; | ||||||
| @@ -628,7 +647,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (ncrc != c.crc) { |             if (ncrc != crc) { | ||||||
|                 goto relocate; |                 goto relocate; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -683,61 +702,106 @@ static int lfs_dir_get(lfs_t *lfs, const lfs_dir_t *dir, | |||||||
|     return lfs_bd_read(lfs, dir->pair[0], off, buffer, size); |     return lfs_bd_read(lfs, dir->pair[0], off, buffer, size); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_set(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, | ||||||
|         lfs_entry_t *entry, struct lfs_region *regions) { |         struct lfs_region *regions, int count) { | ||||||
|     // check if we fit, if top bit is set we do not and move on |     lfs_ssize_t diff = 0;  | ||||||
|     while (true) { |     for (int i = 0; i < count; i++) { | ||||||
|         if ((0x7fffffff & dir->d.size) + entry->size <= lfs->cfg->block_size) { |         diff += regions[i].size; | ||||||
|             entry->off = dir->d.size - 4; |     } | ||||||
|             for (struct lfs_region *r = regions; r; r = r->next) { |  | ||||||
|                 r->off += entry->off; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             lfs_entry_tole32(&entry->d); |     lfs_size_t oldsize = entry->size; | ||||||
|             int err = lfs_dir_commit(lfs, dir, regions); |     if (entry->off == 0) { | ||||||
|             lfs_entry_fromle32(&entry->d); |         entry->off = (0x7fffffff & dir->d.size) - 4; | ||||||
|             return err; |     } | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // we need to allocate a new dir block |     if ((0x7fffffff & dir->d.size) + diff > lfs->cfg->block_size) { | ||||||
|         if (!(0x80000000 & dir->d.size)) { |         lfs_dir_t olddir = *dir; | ||||||
|             lfs_dir_t olddir = *dir; |         lfs_off_t oldoff = entry->off; | ||||||
|             int err = lfs_dir_alloc(lfs, dir); |  | ||||||
|  |         if (oldsize) { | ||||||
|  |             // mark as moving | ||||||
|  |             uint8_t type; | ||||||
|  |             int err = lfs_dir_get(lfs, &olddir, oldoff, &type, 1); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             dir->d.tail[0] = olddir.d.tail[0]; |             type |= LFS_STRUCT_MOVED; | ||||||
|             dir->d.tail[1] = olddir.d.tail[1]; |             err = lfs_dif_commit(lfs, &olddir, (struct lfs_region[]){ | ||||||
|             entry->off = dir->d.size - 4; |                         {LFS_FROM_MEM, oldoff, &type, 1}, | ||||||
|             for (struct lfs_region *r = regions; r; r = r->next) { |                         {LFS_FROM_DROP, oldoff, NULL, -1}}, 2); | ||||||
|                 r->off += entry->off; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             lfs_entry_tole32(&entry->d); |  | ||||||
|             err = lfs_dir_commit(lfs, dir, regions); |  | ||||||
|             lfs_entry_fromle32(&entry->d); |  | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             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); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int err = lfs_dir_fetch(lfs, dir, dir->d.tail); |         lfs_dir_t pdir = olddir; | ||||||
|  |  | ||||||
|  |         // find available block or create a new one | ||||||
|  |         while ((0x7fffffff & dir->d.size) + oldsize + diff | ||||||
|  |                 > lfs->cfg->block_size) { | ||||||
|  |             // we need to allocate a new dir block | ||||||
|  |             if (!(0x80000000 & dir->d.size)) { | ||||||
|  |                 pdir = *dir; | ||||||
|  |                 int err = lfs_dir_alloc(lfs, dir); | ||||||
|  |                 if (err) { | ||||||
|  |                     return err; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 dir->d.tail[0] = pdir.d.tail[0]; | ||||||
|  |                 dir->d.tail[1] = pdir.d.tail[1]; | ||||||
|  |  | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int err = lfs_dir_fetch(lfs, dir, dir->d.tail); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // writing out new entry | ||||||
|  |         entry->off = dir->d.size - 4; | ||||||
|  |         entry->size += diff; | ||||||
|  |         int err = lfs_dif_commit(lfs, dir, (struct lfs_region[]){ | ||||||
|  |                 {LFS_FROM_REGION, entry->off, &(struct lfs_region_region){ | ||||||
|  |                     olddir.pair[0], oldoff, | ||||||
|  |                     regions, count}, entry->size}}, 1); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, |         // update pred dir, unless pred == old we can coalesce | ||||||
|         const lfs_entry_t *entry) { |         if (!oldsize || lfs_paircmp(pdir.pair, olddir.pair) != 0) { | ||||||
|     // check if we should just drop the directory block |             pdir.d.size |= 0x80000000; | ||||||
|     if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + entry->size) { |             pdir.d.tail[0] = dir->pair[0]; | ||||||
|  |             pdir.d.tail[1] = dir->pair[1]; | ||||||
|  |  | ||||||
|  |             err = lfs_dif_commit(lfs, &pdir, NULL, 0); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |         } else if (oldsize) { | ||||||
|  |             olddir.d.size |= 0x80000000; | ||||||
|  |             olddir.d.tail[0] = dir->pair[0]; | ||||||
|  |             olddir.d.tail[1] = dir->pair[1]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // remove old entry | ||||||
|  |         if (oldsize) { | ||||||
|  |             lfs_entry_t oldentry; | ||||||
|  |             oldentry.off = oldoff; | ||||||
|  |             err = lfs_dir_set(lfs, &olddir, &oldentry, (struct lfs_region[]){ | ||||||
|  |                     {LFS_FROM_DROP, 0, NULL, -oldsize}}, 1); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         goto shift; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ((0x7fffffff & dir->d.size) + diff == sizeof(dir->d)+4) { | ||||||
|         lfs_dir_t pdir; |         lfs_dir_t pdir; | ||||||
|         int res = lfs_pred(lfs, dir->pair, &pdir); |         int res = lfs_pred(lfs, dir->pair, &pdir); | ||||||
|         if (res < 0) { |         if (res < 0) { | ||||||
| @@ -748,27 +812,34 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             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]; | ||||||
|             return lfs_dir_commit(lfs, &pdir, NULL); |             int err = lfs_dif_commit(lfs, &pdir, NULL, 0); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |             goto shift; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // shift out the entry |     for (int i = 0; i < count; i++) { | ||||||
|     int err = lfs_dir_commit(lfs, dir, |         regions[i].off += entry->off; | ||||||
|             &(struct lfs_region){ |     } | ||||||
|                 entry->off, -entry->size, |  | ||||||
|                 lfs_commit_mem, NULL, 0}); |     int err = lfs_dif_commit(lfs, dir, regions, count); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     entry->size += diff; | ||||||
|  |  | ||||||
|  | shift: | ||||||
|     // shift over any files/directories that are affected |     // shift over any files/directories that are affected | ||||||
|     for (lfs_file_t *f = lfs->files; f; f = f->next) { |     for (lfs_file_t *f = lfs->files; f; f = f->next) { | ||||||
|         if (lfs_paircmp(f->pair, dir->pair) == 0) { |         if (lfs_paircmp(f->pair, dir->pair) == 0) { | ||||||
|             if (f->poff == entry->off) { |             if (f->poff == entry->off && entry->size == 0) { | ||||||
|                 f->pair[0] = 0xffffffff; |                 f->pair[0] = 0xffffffff; | ||||||
|                 f->pair[1] = 0xffffffff; |                 f->pair[1] = 0xffffffff; | ||||||
|             } else if (f->poff > entry->off) { |             } else if (f->poff > entry->off) { | ||||||
|                 f->poff -= entry->size; |                 f->poff += diff; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -776,8 +847,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { |     for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { | ||||||
|         if (lfs_paircmp(d->pair, dir->pair) == 0) { |         if (lfs_paircmp(d->pair, dir->pair) == 0) { | ||||||
|             if (d->off > entry->off) { |             if (d->off > entry->off) { | ||||||
|                 d->off -= entry->size; |                 d->off += diff; | ||||||
|                 d->pos -= entry->size; |                 d->pos += diff; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -785,87 +856,6 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, |  | ||||||
|         lfs_entry_t *entry, struct lfs_region *regions) { |  | ||||||
|     lfs_ssize_t diff = 0; |  | ||||||
|     for (struct lfs_region *r = regions; r; r = r->next) { |  | ||||||
|         diff += r->diff; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // do we still fit? |  | ||||||
|     if ((0x7fffffff & dir->d.size) + diff <= lfs->cfg->block_size) { |  | ||||||
|         for (struct lfs_region *r = regions; r; r = r->next) { |  | ||||||
|             r->off += entry->off; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         lfs_entry_tole32(&entry->d); |  | ||||||
|         int err = lfs_dir_commit(lfs, dir, regions); |  | ||||||
|         lfs_entry_fromle32(&entry->d); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // shift over any files/directories that are affected |  | ||||||
|         for (lfs_file_t *f = lfs->files; f; f = f->next) { |  | ||||||
|             if (lfs_paircmp(f->pair, dir->pair) == 0) { |  | ||||||
|                 if (f->poff > entry->off) { |  | ||||||
|                     f->poff += diff; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { |  | ||||||
|             if (lfs_paircmp(d->pair, dir->pair) == 0) { |  | ||||||
|                 if (d->off > entry->off) { |  | ||||||
|                     d->off += diff; |  | ||||||
|                     d->pos += diff; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         lfs_dir_t olddir = *dir; |  | ||||||
|         lfs_entry_t oldentry = { |  | ||||||
|             .off = entry->off, |  | ||||||
|             .size = entry->size - diff, |  | ||||||
|             .d.type = entry->d.type | LFS_STRUCT_MOVED, // TODO FIXME when changing type?? |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // mark as moving |  | ||||||
|         int err = lfs_dir_commit(lfs, &olddir, |  | ||||||
|                 &(struct lfs_region){ |  | ||||||
|                     oldentry.off, 0, |  | ||||||
|                     lfs_commit_mem, &oldentry.d.type, 1}); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // append updated entry |  | ||||||
|         lfs_entry_tole32(&entry->d); |  | ||||||
|         err = lfs_dir_append(lfs, dir, entry, |  | ||||||
|                 &(struct lfs_region){ |  | ||||||
|                     0, +entry->size, |  | ||||||
|                     lfs_commit_disk, &(struct lfs_commit_disk){ |  | ||||||
|                         olddir.pair[0], entry->off, regions}, oldentry.size}); |  | ||||||
|         lfs_entry_fromle32(&entry->d); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // remove old entry |  | ||||||
|         err = lfs_dir_fetch(lfs, &olddir, olddir.pair); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         err = lfs_dir_remove(lfs, &olddir, &oldentry); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | ||||||
|     while (dir->off >= (0x7fffffff & dir->d.size)-4) { |     while (dir->off >= (0x7fffffff & dir->d.size)-4) { | ||||||
|         if (!(0x80000000 & dir->d.size)) { |         if (!(0x80000000 & dir->d.size)) { | ||||||
| @@ -1039,7 +1029,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_dir_commit(lfs, &dir, NULL); |     err = lfs_dif_commit(lfs, &dir, NULL, 0); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1050,18 +1040,13 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     entry.d.nlen = strlen(path); |     entry.d.nlen = strlen(path); | ||||||
|     entry.d.u.dir[0] = dir.pair[0]; |     entry.d.u.dir[0] = dir.pair[0]; | ||||||
|     entry.d.u.dir[1] = dir.pair[1]; |     entry.d.u.dir[1] = dir.pair[1]; | ||||||
|     entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; |     entry.size = 0; | ||||||
|  |  | ||||||
|     cwd.d.tail[0] = dir.pair[0]; |     cwd.d.tail[0] = dir.pair[0]; | ||||||
|     cwd.d.tail[1] = dir.pair[1]; |     cwd.d.tail[1] = dir.pair[1]; | ||||||
|  |     err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|     err = lfs_dir_append(lfs, &cwd, &entry, |             {LFS_FROM_MEM, 0, &entry.d, sizeof(entry.d)}, | ||||||
|             &(struct lfs_region){ |             {LFS_FROM_MEM, 0, path, entry.d.nlen}}, 2); | ||||||
|                 0, +sizeof(entry.d), |  | ||||||
|                 lfs_commit_mem, &entry.d, sizeof(entry.d), |  | ||||||
|             &(struct lfs_region){ |  | ||||||
|                 0, +entry.d.nlen, |  | ||||||
|                 lfs_commit_mem, path, entry.d.nlen}}); |  | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1447,15 +1432,11 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|         entry.d.elen = 0; |         entry.d.elen = 0; | ||||||
|         entry.d.alen = 0; |         entry.d.alen = 0; | ||||||
|         entry.d.nlen = strlen(path); |         entry.d.nlen = strlen(path); | ||||||
|         entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; |         entry.size = 0; | ||||||
|  |  | ||||||
|         err = lfs_dir_append(lfs, &cwd, &entry, |         err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|                 &(struct lfs_region){ |                 {LFS_FROM_MEM, 0, &entry.d, 4}, | ||||||
|                     0, +4, |                 {LFS_FROM_MEM, 0, path, entry.d.nlen}}, 2); | ||||||
|                     lfs_commit_mem, &entry.d, 4, |  | ||||||
|                 &(struct lfs_region){ |  | ||||||
|                     0, +entry.d.nlen, |  | ||||||
|                     lfs_commit_mem, path, entry.d.nlen}}); |  | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -1684,43 +1665,37 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|  |  | ||||||
|         // TODO entry read function? |         // TODO entry read function? | ||||||
|         lfs_entry_t entry = {.off = file->poff}; |         lfs_entry_t entry = {.off = file->poff}; | ||||||
|         err = lfs_dir_get(lfs, &cwd, |         err = lfs_dir_get(lfs, &cwd, entry.off, &entry.d, sizeof(entry.d)); | ||||||
|                 entry.off, &entry.d, sizeof(entry.d)); |  | ||||||
|         lfs_entry_fromle32(&entry.d); |         lfs_entry_fromle32(&entry.d); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|         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; | ||||||
|  |         entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; | ||||||
|  |  | ||||||
|  |         // either update the references or inline the whole file | ||||||
|         if (!(file->flags & LFS_F_INLINE)) { |         if (!(file->flags & LFS_F_INLINE)) { | ||||||
|             lfs_ssize_t diff = sizeof(entry.d)-4 - entry.d.elen; |  | ||||||
|             entry.d.type = LFS_STRUCT_CTZ | LFS_TYPE_REG; |             entry.d.type = LFS_STRUCT_CTZ | LFS_TYPE_REG; | ||||||
|             entry.d.elen = sizeof(entry.d)-4; |             entry.d.elen = sizeof(entry.d)-4; | ||||||
|             entry.d.u.file.head = file->head; |             entry.d.u.file.head = file->head; | ||||||
|             entry.d.u.file.size = file->size; |             entry.d.u.file.size = file->size; | ||||||
|             entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; |  | ||||||
|  |  | ||||||
|             // TODO combine down? |             err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|             err = lfs_dir_update(lfs, &cwd, &entry, |                     {LFS_FROM_MEM, 0, &entry.d, sizeof(entry.d)}, | ||||||
|                 &(struct lfs_region){ |                     {LFS_FROM_DROP, 0, NULL, -oldlen-4}}, 2); | ||||||
|                     0, diff, |  | ||||||
|                     lfs_commit_mem, &entry.d, sizeof(entry.d)}); |  | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             lfs_ssize_t diff = file->size - entry.d.elen; |  | ||||||
|             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; | ||||||
|             entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; |  | ||||||
|  |  | ||||||
|             err = lfs_dir_update(lfs, &cwd, &entry, |             err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|                 &(struct lfs_region){ |                     {LFS_FROM_MEM, 0, &entry.d, 4}, | ||||||
|                     0, 0, |                     {LFS_FROM_MEM, 0, file->cache.buffer, file->size}, | ||||||
|                     lfs_commit_mem, &entry.d, 4, |                     {LFS_FROM_DROP, 0, NULL, -oldlen-4}}, 3); | ||||||
|                 &(struct lfs_region){ |  | ||||||
|                     4, diff, |  | ||||||
|                     lfs_commit_mem, file->cache.buffer, file->size}}); |  | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -2098,7 +2073,8 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // remove the entry |     // remove the entry | ||||||
|     err = lfs_dir_remove(lfs, &cwd, &entry); |     err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|  |             {LFS_FROM_DROP, 0, NULL, -entry.size}}, 1); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -2114,7 +2090,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_dir_commit(lfs, &cwd, NULL); |         err = lfs_dif_commit(lfs, &cwd, NULL, 0); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2181,10 +2157,9 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|  |  | ||||||
|     // mark as moving |     // mark as moving | ||||||
|     oldentry.d.type |= LFS_STRUCT_MOVED; |     oldentry.d.type |= LFS_STRUCT_MOVED; | ||||||
|     err = lfs_dir_update(lfs, &oldcwd, &oldentry, |     err = lfs_dir_set(lfs, &oldcwd, &oldentry, (struct lfs_region[]){ | ||||||
|             &(struct lfs_region){ |             {LFS_FROM_MEM, 0, &oldentry.d.type, 1}, | ||||||
|                 0, 0, |             {LFS_FROM_DROP, 0, NULL, -1}}, 2); | ||||||
|                 lfs_commit_mem, &oldentry.d.type, 1}); |  | ||||||
|     oldentry.d.type &= ~LFS_STRUCT_MOVED; |     oldentry.d.type &= ~LFS_STRUCT_MOVED; | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
| @@ -2200,42 +2175,22 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|     newentry.d = oldentry.d; |     newentry.d = oldentry.d; | ||||||
|     newentry.d.type &= ~LFS_STRUCT_MOVED; |     newentry.d.type &= ~LFS_STRUCT_MOVED; | ||||||
|     newentry.d.nlen = strlen(newpath); |     newentry.d.nlen = strlen(newpath); | ||||||
|     newentry.size = 4 + newentry.d.elen + newentry.d.alen + newentry.d.nlen; |     if (!prevexists) { | ||||||
|  |         newentry.size = 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (prevexists) { |     lfs_size_t newsize = oldentry.size - oldentry.d.nlen + newentry.d.nlen; | ||||||
|         err = lfs_dir_update(lfs, &newcwd, &newentry, |     err = lfs_dir_set(lfs, &newcwd, &newentry, (struct lfs_region[]){ | ||||||
|                 &(struct lfs_region){ |             {LFS_FROM_REGION, 0, &(struct lfs_region_region){ | ||||||
|                     0, newentry.size - preventry.size, |                 oldcwd.pair[0], oldentry.off, (struct lfs_region[]){ | ||||||
|                     lfs_commit_disk, &(struct lfs_commit_disk){ |                     {LFS_FROM_MEM, 0, &newentry.d, 4}, | ||||||
|                         oldcwd.pair[0], oldentry.off, |                     {LFS_FROM_DROP, 0, NULL, -4}, | ||||||
|                         &(struct lfs_region){ |                     {LFS_FROM_MEM, newsize - newentry.d.nlen, | ||||||
|                             0, 0, |                         newpath, newentry.d.nlen}}, 3}, | ||||||
|                             lfs_commit_mem, &newentry.d, 4, |                 newsize}, | ||||||
|                         &(struct lfs_region){ |             {LFS_FROM_DROP, 0, NULL, -preventry.size}}, prevexists ? 2 : 1); | ||||||
|                             newentry.size - newentry.d.nlen, |     if (err) { | ||||||
|                             +newentry.d.nlen-oldentry.d.nlen, |         return err; | ||||||
|                             lfs_commit_mem, newpath, newentry.d.nlen}}}, |  | ||||||
|                             oldentry.size}); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         err = lfs_dir_append(lfs, &newcwd, &newentry, |  | ||||||
|                 &(struct lfs_region){ |  | ||||||
|                     0, +newentry.size, |  | ||||||
|                     lfs_commit_disk, &(struct lfs_commit_disk){ |  | ||||||
|                         oldcwd.pair[0], oldentry.off, |  | ||||||
|                         &(struct lfs_region){ |  | ||||||
|                             0, 0, |  | ||||||
|                             lfs_commit_mem, &newentry.d, 4, |  | ||||||
|                         &(struct lfs_region){ |  | ||||||
|                             newentry.size - newentry.d.nlen, |  | ||||||
|                             +newentry.d.nlen-oldentry.d.nlen, |  | ||||||
|                             lfs_commit_mem, newpath, newentry.d.nlen}}}, |  | ||||||
|                             oldentry.size}); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // update pair if newcwd == oldcwd |     // update pair if newcwd == oldcwd | ||||||
| @@ -2244,7 +2199,8 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // remove old entry |     // remove old entry | ||||||
|     err = lfs_dir_remove(lfs, &oldcwd, &oldentry); |     err = lfs_dir_set(lfs, &oldcwd, &oldentry, (struct lfs_region[]){ | ||||||
|  |             {LFS_FROM_DROP, 0, NULL, -oldentry.size}}, 1); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -2260,7 +2216,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_dir_commit(lfs, &newcwd, NULL); |         err = lfs_dif_commit(lfs, &newcwd, NULL, 0); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2370,7 +2326,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_dir_commit(lfs, &root, NULL); |     err = lfs_dif_commit(lfs, &root, NULL, 0); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -2394,21 +2350,14 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     superentry.d.alen = 0; |     superentry.d.alen = 0; | ||||||
|     superentry.d.nlen = strlen("littlefs"); |     superentry.d.nlen = strlen("littlefs"); | ||||||
|     superentry.off = sizeof(superdir.d); |     superentry.off = sizeof(superdir.d); | ||||||
|     superentry.size = 4 + superentry.d.elen + |     superentry.size = 0; | ||||||
|             superentry.d.alen + superentry.d.nlen; |  | ||||||
|  |  | ||||||
|     lfs_entry_tole32(&superentry.d); |     lfs_entry_tole32(&superentry.d); | ||||||
|     lfs_superblock_tole32(&superblock.d); |     lfs_superblock_tole32(&superblock.d); | ||||||
|     err = lfs_dir_append(lfs, &superdir, &superentry, |     err = lfs_dir_set(lfs, &superdir, &superentry, (struct lfs_region[]){ | ||||||
|             &(struct lfs_region){ |             {LFS_FROM_MEM, 0, &superentry.d, 4}, | ||||||
|                 0, +4, |             {LFS_FROM_MEM, 0, &superblock.d, sizeof(superblock.d)}, | ||||||
|                 lfs_commit_mem, &superentry.d, 4, |             {LFS_FROM_MEM, 0, "littlefs", superentry.d.nlen}}, 3); | ||||||
|             &(struct lfs_region){ |  | ||||||
|                 0, +sizeof(superblock.d), |  | ||||||
|                 lfs_commit_mem, &superblock.d, sizeof(superblock.d), |  | ||||||
|             &(struct lfs_region){ |  | ||||||
|                 0, +superentry.d.nlen, |  | ||||||
|                 lfs_commit_mem, "littlefs", superentry.d.nlen}}}); |  | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -2452,8 +2401,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         err = lfs_dir_get(lfs, &dir, |         err = lfs_dir_get(lfs, &dir, | ||||||
|                 sizeof(dir.d) + 4 + sizeof(superblock.d), |                 sizeof(dir.d)+4 + sizeof(superblock.d), magic, sizeof(magic)); | ||||||
|                 magic, sizeof(magic)); |  | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2671,11 +2619,9 @@ static int lfs_relocate(lfs_t *lfs, | |||||||
|         // update disk, this creates a desync |         // update disk, this creates a desync | ||||||
|         entry.d.u.dir[0] = newpair[0]; |         entry.d.u.dir[0] = newpair[0]; | ||||||
|         entry.d.u.dir[1] = newpair[1]; |         entry.d.u.dir[1] = newpair[1]; | ||||||
|  |         int err = lfs_dir_set(lfs, &parent, &entry, (struct lfs_region[]){ | ||||||
|         int err = lfs_dir_update(lfs, &parent, &entry, |                 {LFS_FROM_MEM, 0, &entry.d, sizeof(entry.d)}, | ||||||
|                 &(struct lfs_region){ |                 {LFS_FROM_DROP, 0, NULL, (lfs_ssize_t)-sizeof(entry.d)}}, 2); | ||||||
|                     0, 0, |  | ||||||
|                     lfs_commit_mem, &entry.d, sizeof(entry.d)}); |  | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2702,7 +2648,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_dir_commit(lfs, &parent, NULL); |         return lfs_dif_commit(lfs, &parent, NULL, 0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // couldn't find dir, must be new |     // couldn't find dir, must be new | ||||||
| @@ -2744,7 +2690,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_dir_commit(lfs, &pdir, NULL); |                 err = lfs_dif_commit(lfs, &pdir, NULL, 0); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
| @@ -2760,7 +2706,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_dir_commit(lfs, &pdir, NULL); |                 err = lfs_dif_commit(lfs, &pdir, NULL, 0); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
| @@ -2791,7 +2737,8 @@ int lfs_deorphan(lfs_t *lfs) { | |||||||
|                 if (moved) { |                 if (moved) { | ||||||
|                     LFS_DEBUG("Found move %d %d", |                     LFS_DEBUG("Found move %d %d", | ||||||
|                             entry.d.u.dir[0], entry.d.u.dir[1]); |                             entry.d.u.dir[0], entry.d.u.dir[1]); | ||||||
|                     err = lfs_dir_remove(lfs, &cwd, &entry); |                     err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|  |                             {LFS_FROM_DROP, 0, NULL, -entry.size}}, 1); | ||||||
|                     if (err) { |                     if (err) { | ||||||
|                         return err; |                         return err; | ||||||
|                     } |                     } | ||||||
| @@ -2799,10 +2746,10 @@ int lfs_deorphan(lfs_t *lfs) { | |||||||
|                     LFS_DEBUG("Found partial move %d %d", |                     LFS_DEBUG("Found partial move %d %d", | ||||||
|                             entry.d.u.dir[0], entry.d.u.dir[1]); |                             entry.d.u.dir[0], entry.d.u.dir[1]); | ||||||
|                     entry.d.type &= ~LFS_STRUCT_MOVED; |                     entry.d.type &= ~LFS_STRUCT_MOVED; | ||||||
|                     err = lfs_dir_update(lfs, &cwd, &entry, |                     err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|                             &(struct lfs_region){ |                             {LFS_FROM_MEM, 0, &entry.d, sizeof(entry.d)}, | ||||||
|                                 0, 0, |                             {LFS_FROM_DROP, 0, NULL, | ||||||
|                                 lfs_commit_mem, &entry.d, sizeof(entry.d)}); |                                 (lfs_ssize_t)-sizeof(entry.d)}}, 2); | ||||||
|                     if (err) { |                     if (err) { | ||||||
|                         return err; |                         return err; | ||||||
|                     } |                     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user