Skip to content

Commit f67a795

Browse files
committed
littlefs: 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.
1 parent d9cb00d commit f67a795

File tree

2 files changed

+26
-22
lines changed

2 files changed

+26
-22
lines changed

features/filesystem/littlefs/littlefs/lfs.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,19 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
724724
pathname += strspn(pathname, "/");
725725
pathlen = strcspn(pathname, "/");
726726

727+
// special case for root dir
728+
if (pathname[0] == '\0') {
729+
*entry = (lfs_entry_t){
730+
.d.type = LFS_TYPE_DIR,
731+
.d.elen = sizeof(entry->d) - 4,
732+
.d.alen = 0,
733+
.d.nlen = 0,
734+
.d.u.dir[0] = lfs->root[0],
735+
.d.u.dir[1] = lfs->root[1],
736+
};
737+
return 0;
738+
}
739+
727740
// skip '.' and root '..'
728741
if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
729742
(pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
@@ -880,15 +893,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
880893
return err;
881894
}
882895

883-
// check for root, can only be something like '/././../.'
884-
if (strspn(path, "/.") == strlen(path)) {
885-
dir->head[0] = dir->pair[0];
886-
dir->head[1] = dir->pair[1];
887-
dir->pos = sizeof(dir->d) - 2;
888-
dir->off = sizeof(dir->d);
889-
return 0;
890-
}
891-
892896
lfs_entry_t entry;
893897
err = lfs_dir_find(lfs, dir, &entry, &path);
894898
if (err) {
@@ -1671,14 +1675,6 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
16711675

16721676
/// General fs oprations ///
16731677
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
1674-
// check for root, can only be something like '/././../.'
1675-
if (strspn(path, "/.") == strlen(path)) {
1676-
memset(info, 0, sizeof(*info));
1677-
info->type = LFS_TYPE_DIR;
1678-
strcpy(info->name, "/");
1679-
return 0;
1680-
}
1681-
16821678
lfs_dir_t cwd;
16831679
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
16841680
if (err) {
@@ -1697,11 +1693,15 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
16971693
info->size = entry.d.u.file.size;
16981694
}
16991695

1700-
err = lfs_bd_read(lfs, cwd.pair[0],
1701-
entry.off + 4+entry.d.elen+entry.d.alen,
1702-
info->name, entry.d.nlen);
1703-
if (err) {
1704-
return err;
1696+
if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) {
1697+
strcpy(info->name, "/");
1698+
} else {
1699+
err = lfs_bd_read(lfs, cwd.pair[0],
1700+
entry.off + 4+entry.d.elen+entry.d.alen,
1701+
info->name, entry.d.nlen);
1702+
if (err) {
1703+
return err;
1704+
}
17051705
}
17061706

17071707
return 0;

features/filesystem/littlefs/littlefs/tests/test_paths.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ tests/test.py << TEST
108108
lfs_stat(&lfs, "/", &info) => 0;
109109
info.type => LFS_TYPE_DIR;
110110
strcmp(info.name, "/") => 0;
111+
112+
lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
113+
lfs_file_open(&lfs, &file[0], "/", LFS_O_WRONLY | LFS_O_CREAT)
114+
=> LFS_ERR_ISDIR;
111115
lfs_unmount(&lfs) => 0;
112116
TEST
113117

0 commit comments

Comments
 (0)