From d9c36371e710bb8561e3493d156927d5e55a8a0d Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 22 Feb 2018 15:24:17 -0600 Subject: [PATCH] Fixed handling of root as target for create operations Before this patch, when calling lfs_mkdir or lfs_file_open with root as the target, littlefs wouldn't find the path properly and happily run into undefined behaviour. The fix is to populate a directory entry for root in the lfs_dir_find function. As an added plus, this allowed several special cases around root to be completely dropped. --- lfs.c | 44 ++++++++++++++++++++++---------------------- tests/test_paths.sh | 4 ++++ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/lfs.c b/lfs.c index a0e0b0f5..96344197 100644 --- a/lfs.c +++ b/lfs.c @@ -780,6 +780,19 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, pathname += strspn(pathname, "/"); pathlen = strcspn(pathname, "/"); + // special case for root dir + if (pathname[0] == '\0') { + *entry = (lfs_entry_t){ + .d.type = LFS_TYPE_DIR, + .d.elen = sizeof(entry->d) - 4, + .d.alen = 0, + .d.nlen = 0, + .d.u.dir[0] = lfs->root[0], + .d.u.dir[1] = lfs->root[1], + }; + return 0; + } + // skip '.' and root '..' if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { @@ -936,15 +949,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { return err; } - // check for root, can only be something like '/././../.' - if (strspn(path, "/.") == strlen(path)) { - dir->head[0] = dir->pair[0]; - dir->head[1] = dir->pair[1]; - dir->pos = sizeof(dir->d) - 2; - dir->off = sizeof(dir->d); - return 0; - } - lfs_entry_t entry; err = lfs_dir_find(lfs, dir, &entry, &path); if (err) { @@ -1799,14 +1803,6 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) { /// General fs operations /// int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { - // check for root, can only be something like '/././../.' - if (strspn(path, "/.") == strlen(path)) { - memset(info, 0, sizeof(*info)); - info->type = LFS_TYPE_DIR; - strcpy(info->name, "/"); - return 0; - } - lfs_dir_t cwd; int err = lfs_dir_fetch(lfs, &cwd, lfs->root); if (err) { @@ -1825,11 +1821,15 @@ 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 + 4+entry.d.elen+entry.d.alen, - info->name, entry.d.nlen); - if (err) { - return err; + if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { + strcpy(info->name, "/"); + } else { + 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; + } } return 0; diff --git a/tests/test_paths.sh b/tests/test_paths.sh index 9bc1f5b1..f277e451 100755 --- a/tests/test_paths.sh +++ b/tests/test_paths.sh @@ -108,6 +108,10 @@ tests/test.py << TEST lfs_stat(&lfs, "/", &info) => 0; info.type => LFS_TYPE_DIR; strcmp(info.name, "/") => 0; + + lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file[0], "/", LFS_O_WRONLY | LFS_O_CREAT) + => LFS_ERR_ISDIR; lfs_unmount(&lfs) => 0; TEST