diff --git a/.travis.yml b/.travis.yml index 0936b29f44..0651efc961 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,14 @@ script: + # make sure example can at least compile + - sed -n '/``` c/,/```/{/```/d; p;}' README.md > test.c && + CFLAGS=' + -Duser_provided_block_device_read=NULL + -Duser_provided_block_device_prog=NULL + -Duser_provided_block_device_erase=NULL + -Duser_provided_block_device_sync=NULL + -include stdio.h -Werror' make all size + + # run tests - CFLAGS="-DLFS_READ_SIZE=16 -DLFS_PROG_SIZE=16" make test - CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test - CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test diff --git a/DESIGN.md b/DESIGN.md index 3381c7919c..dcc469a2d7 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -639,9 +639,9 @@ v '--------' '--------' ``` -Wait, wait, wait, wait, wait, that's not atomic at all! If power is lost after -removing directory B from the root, directory B is still in the linked-list. -We've just created a memory leak! +Wait, wait, wait, that's not atomic at all! If power is lost after removing +directory B from the root, directory B is still in the linked-list. We've +just created a memory leak! And to be honest, I don't have a clever solution for this case. As a side-effect of using multiple pointers in the threaded tree, the littlefs @@ -969,5 +969,5 @@ So, to summarize: 10. Any case where an atomic operation is not possible, it is taken care of by a deorphan step that occurs on the first allocation after boot -Welp, that's the little filesystem. Thanks for reading! +That's the little filesystem. Thanks for reading! diff --git a/README.md b/README.md index 0ae1cc61ea..e9e63b3722 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,6 @@ int main(void) { // update boot count boot_count += 1; - printf("boot_count: %ld\n", boot_count); lfs_file_rewind(&lfs, &file); lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count)); @@ -86,6 +85,9 @@ int main(void) { // release any resources we were using lfs_unmount(&lfs); + + // print the boot count + printf("boot_count: %d\n", boot_count); } ``` diff --git a/lfs.c b/lfs.c index a2d94eec61..b2c0a631aa 100644 --- a/lfs.c +++ b/lfs.c @@ -560,8 +560,7 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, const lfs_entry_t *entry, const void *data) { return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, - {entry->off+sizeof(entry->d), entry->d.len-sizeof(entry->d), - data, entry->d.len-sizeof(entry->d)} + {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen} }, data ? 2 : 1); } @@ -569,11 +568,12 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, const void *data) { // check if we fit, if top bit is set we do not and move on while (true) { - if (dir->d.size + entry->d.len <= lfs->cfg->block_size) { + if (dir->d.size + 4+entry->d.elen+entry->d.alen+entry->d.nlen + <= lfs->cfg->block_size) { entry->off = dir->d.size - 4; return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ {entry->off, 0, &entry->d, sizeof(entry->d)}, - {entry->off, 0, data, entry->d.len - sizeof(entry->d)} + {entry->off, 0, data, entry->d.nlen} }, 2); } @@ -590,7 +590,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, entry->off = newdir.d.size - 4; err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){ {entry->off, 0, &entry->d, sizeof(entry->d)}, - {entry->off, 0, data, entry->d.len - sizeof(entry->d)} + {entry->off, 0, data, entry->d.nlen} }, 2); if (err) { return err; @@ -620,7 +620,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { if (!(pdir.d.size & 0x80000000)) { return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ - {entry->off, entry->d.len, NULL, 0}, + {entry->off, 4+entry->d.elen+entry->d.alen+entry->d.nlen, + NULL, 0}, }, 1); } else { pdir.d.tail[0] = dir->d.tail[0]; @@ -629,7 +630,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { } } else { return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ - {entry->off, entry->d.len, NULL, 0}, + {entry->off, 4+entry->d.elen+entry->d.alen+entry->d.nlen, + NULL, 0}, }, 1); } } @@ -656,9 +658,9 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { return err; } - dir->off += entry->d.len; - dir->pos += entry->d.len; - entry->off = dir->off - entry->d.len; + entry->off = dir->off; + dir->off += 4+entry->d.elen+entry->d.alen+entry->d.nlen; + dir->pos += 4+entry->d.elen+entry->d.alen+entry->d.nlen; return 0; } @@ -713,12 +715,13 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, if ((entry->d.type != LFS_TYPE_REG && entry->d.type != LFS_TYPE_DIR) || - entry->d.name != pathlen) { + entry->d.nlen != pathlen) { continue; } int res = lfs_bd_cmp(lfs, dir->pair[0], - entry->off + sizeof(entry->d), pathname, pathlen); + entry->off + 4+entry->d.elen+entry->d.alen, + pathname, pathlen); if (res < 0) { return res; } @@ -784,8 +787,9 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { } entry.d.type = LFS_TYPE_DIR; - entry.d.name = strlen(path); - entry.d.len = sizeof(entry.d) + entry.d.name; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = 0; + entry.d.nlen = strlen(path); entry.d.u.dir[0] = dir.pair[0]; entry.d.u.dir[1] = dir.pair[1]; @@ -880,8 +884,9 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { info->size = entry.d.u.file.size; } - int err = lfs_bd_read(lfs, dir->pair[0], entry.off + sizeof(entry.d), - info->name, entry.d.name); + int err = lfs_bd_read(lfs, dir->pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); if (err) { return err; } @@ -1117,8 +1122,9 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, // create entry to remember name entry.d.type = LFS_TYPE_REG; - entry.d.name = strlen(path); - entry.d.len = sizeof(entry.d) + entry.d.name; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = 0; + entry.d.nlen = strlen(path); entry.d.u.file.head = -1; entry.d.u.file.size = 0; err = lfs_dir_append(lfs, &cwd, &entry, path); @@ -1537,8 +1543,9 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { info->size = entry.d.u.file.size; } - err = lfs_bd_read(lfs, cwd.pair[0], entry.off + sizeof(entry.d), - info->name, entry.d.name); + err = lfs_bd_read(lfs, cwd.pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); if (err) { return err; } @@ -1585,7 +1592,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { f->pair[0] = 0xffffffff; f->pair[1] = 0xffffffff; } else if (f->poff > entry.off) { - f->poff -= entry.d.len; + f->poff -= 4 + entry.d.elen + entry.d.alen + entry.d.nlen; } } } @@ -1651,8 +1658,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { // move to new location lfs_entry_t newentry = preventry; newentry.d = oldentry.d; - newentry.d.name = strlen(newpath); - newentry.d.len = sizeof(newentry.d) + newentry.d.name; + newentry.d.nlen = strlen(newpath); if (prevexists) { int err = lfs_dir_update(lfs, &newcwd, &newentry, newpath); @@ -1690,7 +1696,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { f->pair[0] = 0xffffffff; f->pair[1] = 0xffffffff; } else if (f->poff > oldentry.off) { - f->poff -= oldentry.d.len; + f->poff -= 4+oldentry.d.elen+oldentry.d.alen+oldentry.d.nlen; } } } @@ -1809,8 +1815,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { lfs_superblock_t superblock = { .off = sizeof(superdir.d), .d.type = LFS_TYPE_SUPERBLOCK, - .d.name = sizeof(superblock.d.magic), - .d.len = sizeof(superblock.d), + .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, + .d.nlen = sizeof(superblock.d.magic), .d.version = 0x00010001, .d.magic = {"littlefs"}, .d.block_size = lfs->cfg->block_size, @@ -1865,8 +1871,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { lfs_superblock_t superblock; err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); if (!err) { - err = lfs_bd_read(lfs, dir.pair[0], - sizeof(dir.d), &superblock.d, sizeof(superblock.d)); + err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d), + &superblock.d, sizeof(superblock.d)); lfs->root[0] = superblock.d.root[0]; lfs->root[1] = superblock.d.root[1]; @@ -1925,7 +1931,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { return err; } - dir.off += entry.d.len; + dir.off += 4+entry.d.elen+entry.d.alen+entry.d.nlen; if ((0xf & entry.d.type) == (0xf & LFS_TYPE_REG)) { int err = lfs_index_traverse(lfs, &lfs->rcache, NULL, entry.d.u.file.head, entry.d.u.file.size, cb, data); diff --git a/lfs.h b/lfs.h index 0133b94aec..1b11ba79cf 100644 --- a/lfs.h +++ b/lfs.h @@ -160,8 +160,9 @@ typedef struct lfs_entry { struct lfs_disk_entry { uint8_t type; - uint8_t name; - uint16_t len; + uint8_t elen; + uint8_t alen; + uint8_t nlen; union { struct { lfs_block_t head; @@ -212,8 +213,9 @@ typedef struct lfs_superblock { struct lfs_disk_superblock { uint8_t type; - uint8_t name; - uint16_t len; + uint8_t elen; + uint8_t alen; + uint8_t nlen; lfs_block_t root[2]; uint32_t block_size; uint32_t block_count;