diff --git a/lfs.c b/lfs.c index ae8b4c5..03c4b81 100644 --- a/lfs.c +++ b/lfs.c @@ -3255,6 +3255,12 @@ int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { } */ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *pdir) { + if (lfs_pairisnull(lfs->root)) { + // TODO best place for this? + // TODO needed for relocate + return LFS_ERR_NOENT; + } + // iterate over all directory directory entries pdir->tail[0] = 0; pdir->tail[1] = 1; @@ -3275,6 +3281,11 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *pdir) { static int32_t lfs_parent(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *parent) { + if (lfs_pairisnull(lfs->root)) { + // TODO best place for this? + return LFS_ERR_NOENT; + } + // search for both orderings so we can reuse the find function lfs_block_t child[2] = {pair[0], pair[1]}; @@ -3531,18 +3542,19 @@ int lfs_deorphan(lfs_t *lfs) { // return lfs_dir_setattrs(lfs, &dir, &entry, attrs, count); //} -//static int lfs_fs_size_count(void *p, lfs_block_t block) { -// lfs_size_t *size = p; -// *size += 1; -// return 0; -//} -// -//lfs_ssize_t lfs_fs_size(lfs_t *lfs) { -// lfs_size_t size = 0; -// int err = lfs_fs_traverse(lfs, lfs_fs_size_count, &size); -// if (err) { -// return err; -// } -// -// return size; -//} +// TODO need lfs? +static int lfs_fs_size_count(lfs_t *lfs, void *p, lfs_block_t block) { + lfs_size_t *size = p; + *size += 1; + return 0; +} + +lfs_ssize_t lfs_fs_size(lfs_t *lfs) { + lfs_size_t size = 0; + int err = lfs_fs_traverse(lfs, lfs_fs_size_count, &size); + if (err) { + return err; + } + + return size; +} diff --git a/lfs.h b/lfs.h index b83a25c..b384ed3 100644 --- a/lfs.h +++ b/lfs.h @@ -249,7 +249,8 @@ struct lfs_info { // Custom attribute structure struct lfs_attr { - // Type of attribute, provided by user and used to identify the attribute + // 8-bit Type of attribute, provided by user and used to + // identify the attribute uint8_t type; // Pointer to buffer containing the attribute @@ -259,7 +260,7 @@ struct lfs_attr { lfs_size_t size; // Pointer to next attribute in linked list - const struct lfs_attr *next; + struct lfs_attr *next; }; // Optional configuration provided during lfs_file_opencfg @@ -268,9 +269,9 @@ struct lfs_file_config { // If NULL, malloc will be used by default. void *buffer; - // Optional, custom attributes + // Optional, linked list of custom attributes. // TODO document more - const struct lfs_attr *attrs; + struct lfs_attr *attrs; }; @@ -582,7 +583,8 @@ lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir); int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir); -/// Filesystem filesystem operations /// +/// Filesystem filesystem operations /// TODO choose one +/// Miscellaneous littlefs specific operations /// TODO choose one // Get custom attributes on the filesystem // @@ -616,9 +618,6 @@ int lfs_fs_setattr(lfs_t *lfs, // Returns the number of allocated blocks, or a negative error code on failure. lfs_ssize_t lfs_fs_size(lfs_t *lfs); - -/// Miscellaneous littlefs specific operations /// - // Traverse through all blocks in use by the filesystem // // The provided callback will be called with each block address that is @@ -626,16 +625,8 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs); // blocks are in use or how much of the storage is available. // // Returns a negative error code on failure. -int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); - -// Prunes any recoverable errors that may have occured in the filesystem -// -// Not needed to be called by user unless an operation is interrupted -// but the filesystem is still mounted. This is already called on first -// allocation. -// -// Returns a negative error code on failure. -int lfs_deorphan(lfs_t *lfs); +// TODO don't pass lfs_t? +int lfs_fs_traverse(lfs_t *lfs, int (*cb)(lfs_t*, void*, lfs_block_t), void *data); #endif diff --git a/tests/test_corrupt.sh b/tests/test_corrupt.sh index 1491dac..faa6f7e 100755 --- a/tests/test_corrupt.sh +++ b/tests/test_corrupt.sh @@ -78,8 +78,11 @@ do rm -rf blocks mkdir blocks ln -s /dev/zero blocks/$(printf '%x' $i) + echo $i 1i lfs_mktree + echo $i 2i lfs_chktree + echo $i 3i done echo "--- Block persistance ---" diff --git a/tests/test_orphan.sh b/tests/test_orphan.sh index 71d6d4f..a76088b 100755 --- a/tests/test_orphan.sh +++ b/tests/test_orphan.sh @@ -15,25 +15,29 @@ tests/test.py << TEST lfs_mkdir(&lfs, "parent/child") => 0; lfs_remove(&lfs, "parent/orphan") => 0; TEST -# remove most recent file, this should be the update to the previous +# corrupt most recent commit, this should be the update to the previous # linked-list entry and should orphan the child -rm -v blocks/8 -tests/test.py << TEST +truncate -s-14 blocks/8 +tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - unsigned before = 0; - lfs_traverse(&lfs, test_count, &before) => 0; - test_log("before", before); - - lfs_deorphan(&lfs) => 0; lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - unsigned after = 0; - lfs_traverse(&lfs, test_count, &after) => 0; - test_log("after", after); + lfs_ssize_t before = lfs_fs_size(&lfs); + before => 10; + + lfs_unmount(&lfs) => 0; + lfs_mount(&lfs, &cfg) => 0; + + lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; + lfs_ssize_t orphaned = lfs_fs_size(&lfs); + orphaned => 10; + + lfs_mkdir(&lfs, "parent/otherchild") => 0; + + lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; + lfs_ssize_t deorphaned = lfs_fs_size(&lfs); + deorphaned => 10; - int diff = before - after; - diff => 2; lfs_unmount(&lfs) => 0; TEST