Skip to content

Commit a8fa5e6

Browse files
committed
Fixed some corner cases with paths
- Added handling for root to lfs_stat - Corrected lfs_dir_find to update path even on failures - Added more checks for missing directories in path
1 parent 26dd49a commit a8fa5e6

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

lfs.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,9 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
709709
suffix += sufflen;
710710
}
711711

712+
// update what we've found
713+
*path = pathname;
714+
712715
// find path
713716
while (true) {
714717
int err = lfs_dir_next(lfs, dir, entry);
@@ -750,8 +753,6 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
750753
if (err) {
751754
return err;
752755
}
753-
754-
*path = pathname;
755756
}
756757

757758
return 0;
@@ -769,7 +770,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
769770

770771
lfs_entry_t entry;
771772
err = lfs_dir_find(lfs, &cwd, &entry, &path);
772-
if (err != LFS_ERR_NOENT) {
773+
if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
773774
return err ? err : LFS_ERR_EXISTS;
774775
}
775776

@@ -817,8 +818,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
817818
return err;
818819
}
819820

821+
// check for root, can only be something like '/././../.'
820822
if (strspn(path, "/.") == strlen(path)) {
821-
// can only be something like '/././../.'
822823
dir->head[0] = dir->pair[0];
823824
dir->head[1] = dir->pair[1];
824825
dir->pos = sizeof(dir->d) - 2;
@@ -1118,7 +1119,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
11181119

11191120
lfs_entry_t entry;
11201121
err = lfs_dir_find(lfs, &cwd, &entry, &path);
1121-
if (err && err != LFS_ERR_NOENT) {
1122+
if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) {
11221123
return err;
11231124
}
11241125

@@ -1533,6 +1534,14 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
15331534

15341535
/// General fs oprations ///
15351536
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
1537+
// check for root, can only be something like '/././../.'
1538+
if (strspn(path, "/.") == strlen(path)) {
1539+
memset(info, 0, sizeof(*info));
1540+
info->type = LFS_TYPE_DIR;
1541+
strcpy(info->name, "/");
1542+
return 0;
1543+
}
1544+
15361545
lfs_dir_t cwd;
15371546
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
15381547
if (err) {
@@ -1640,7 +1649,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
16401649

16411650
lfs_entry_t preventry;
16421651
err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath);
1643-
if (err && err != LFS_ERR_NOENT) {
1652+
if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) {
16441653
return err;
16451654
}
16461655
bool prevexists = (err != LFS_ERR_NOENT);

tests/test_paths.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ tests/test.py << TEST
3131
strcmp(info.name, "hottea") => 0;
3232
lfs_stat(&lfs, "/tea/hottea", &info) => 0;
3333
strcmp(info.name, "hottea") => 0;
34+
35+
lfs_mkdir(&lfs, "/milk1") => 0;
36+
lfs_stat(&lfs, "/milk1", &info) => 0;
37+
strcmp(info.name, "milk1") => 0;
3438
lfs_unmount(&lfs) => 0;
3539
TEST
3640

@@ -43,6 +47,10 @@ tests/test.py << TEST
4347
strcmp(info.name, "hottea") => 0;
4448
lfs_stat(&lfs, "///tea///hottea", &info) => 0;
4549
strcmp(info.name, "hottea") => 0;
50+
51+
lfs_mkdir(&lfs, "///milk2") => 0;
52+
lfs_stat(&lfs, "///milk2", &info) => 0;
53+
strcmp(info.name, "milk2") => 0;
4654
lfs_unmount(&lfs) => 0;
4755
TEST
4856

@@ -57,6 +65,10 @@ tests/test.py << TEST
5765
strcmp(info.name, "hottea") => 0;
5866
lfs_stat(&lfs, "/./tea/./hottea", &info) => 0;
5967
strcmp(info.name, "hottea") => 0;
68+
69+
lfs_mkdir(&lfs, "/./milk3") => 0;
70+
lfs_stat(&lfs, "/./milk3", &info) => 0;
71+
strcmp(info.name, "milk3") => 0;
6072
lfs_unmount(&lfs) => 0;
6173
TEST
6274

@@ -71,6 +83,10 @@ tests/test.py << TEST
7183
strcmp(info.name, "hottea") => 0;
7284
lfs_stat(&lfs, "coffee/../soda/../tea/hottea", &info) => 0;
7385
strcmp(info.name, "hottea") => 0;
86+
87+
lfs_mkdir(&lfs, "coffee/../milk4") => 0;
88+
lfs_stat(&lfs, "coffee/../milk4", &info) => 0;
89+
strcmp(info.name, "milk4") => 0;
7490
lfs_unmount(&lfs) => 0;
7591
TEST
7692

@@ -79,6 +95,27 @@ tests/test.py << TEST
7995
lfs_mount(&lfs, &cfg) => 0;
8096
lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0;
8197
strcmp(info.name, "hottea") => 0;
98+
99+
lfs_mkdir(&lfs, "coffee/../../../../../../milk5") => 0;
100+
lfs_stat(&lfs, "coffee/../../../../../../milk5", &info) => 0;
101+
strcmp(info.name, "milk5") => 0;
102+
lfs_unmount(&lfs) => 0;
103+
TEST
104+
105+
echo "--- Root tests ---"
106+
tests/test.py << TEST
107+
lfs_mount(&lfs, &cfg) => 0;
108+
lfs_stat(&lfs, "/", &info) => 0;
109+
info.type => LFS_TYPE_DIR;
110+
strcmp(info.name, "/") => 0;
111+
lfs_unmount(&lfs) => 0;
112+
TEST
113+
114+
echo "--- Sketchy path tests ---"
115+
tests/test.py << TEST
116+
lfs_mount(&lfs, &cfg) => 0;
117+
lfs_mkdir(&lfs, "dirt/ground") => LFS_ERR_NOENT;
118+
lfs_mkdir(&lfs, "dirt/ground/earth") => LFS_ERR_NOENT;
82119
lfs_unmount(&lfs) => 0;
83120
TEST
84121

0 commit comments

Comments
 (0)