Skip to content

Commit 015b86b

Browse files
committed
Fixed issue with trailing dots in file paths
Paths such as the following were causing issues: /tea/hottea/. /tea/hottea/.. Unfortunately the existing structure for path lookup didn't make it very easy to introduce proper handling in this case without duplicating the entire skip logic for paths. So the lfs_dir_find function had to be restructured a bit. One odd side-effect of this is that now lfs_dir_find includes the initial fetch operation. This kinda breaks the fetch -> op pattern of the dir functions, but does come with a nice code size reduction.
1 parent 9637b96 commit 015b86b

File tree

2 files changed

+46
-70
lines changed

2 files changed

+46
-70
lines changed

lfs.c

Lines changed: 30 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -783,26 +783,19 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
783783
lfs_entry_t *entry, const char **path) {
784784
const char *pathname = *path;
785785
size_t pathlen;
786+
entry->d.type = LFS_TYPE_DIR;
787+
entry->d.elen = sizeof(entry->d) - 4;
788+
entry->d.alen = 0;
789+
entry->d.nlen = 0;
790+
entry->d.u.dir[0] = lfs->root[0];
791+
entry->d.u.dir[1] = lfs->root[1];
786792

787793
while (true) {
788-
nextname:
794+
nextname:
789795
// skip slashes
790796
pathname += strspn(pathname, "/");
791797
pathlen = strcspn(pathname, "/");
792798

793-
// special case for root dir
794-
if (pathname[0] == '\0') {
795-
*entry = (lfs_entry_t){
796-
.d.type = LFS_TYPE_DIR,
797-
.d.elen = sizeof(entry->d) - 4,
798-
.d.alen = 0,
799-
.d.nlen = 0,
800-
.d.u.dir[0] = lfs->root[0],
801-
.d.u.dir[1] = lfs->root[1],
802-
};
803-
return 0;
804-
}
805-
806799
// skip '.' and root '..'
807800
if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
808801
(pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
@@ -834,10 +827,25 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
834827
suffix += sufflen;
835828
}
836829

830+
// found path
831+
if (pathname[0] == '\0') {
832+
return 0;
833+
}
834+
837835
// update what we've found
838836
*path = pathname;
839837

840-
// find path
838+
// continue on if we hit a directory
839+
if (entry->d.type != LFS_TYPE_DIR) {
840+
return LFS_ERR_NOTDIR;
841+
}
842+
843+
int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir);
844+
if (err) {
845+
return err;
846+
}
847+
848+
// find entry matching name
841849
while (true) {
842850
int err = lfs_dir_next(lfs, dir, entry);
843851
if (err) {
@@ -873,21 +881,8 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
873881
entry->d.type &= ~0x80;
874882
}
875883

884+
// to next name
876885
pathname += pathlen;
877-
pathname += strspn(pathname, "/");
878-
if (pathname[0] == '\0') {
879-
return 0;
880-
}
881-
882-
// continue on if we hit a directory
883-
if (entry->d.type != LFS_TYPE_DIR) {
884-
return LFS_ERR_NOTDIR;
885-
}
886-
887-
int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir);
888-
if (err) {
889-
return err;
890-
}
891886
}
892887
}
893888

@@ -904,13 +899,8 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
904899

905900
// fetch parent directory
906901
lfs_dir_t cwd;
907-
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
908-
if (err) {
909-
return err;
910-
}
911-
912902
lfs_entry_t entry;
913-
err = lfs_dir_find(lfs, &cwd, &entry, &path);
903+
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
914904
if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
915905
return err ? err : LFS_ERR_EXIST;
916906
}
@@ -954,13 +944,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
954944
dir->pair[0] = lfs->root[0];
955945
dir->pair[1] = lfs->root[1];
956946

957-
int err = lfs_dir_fetch(lfs, dir, dir->pair);
958-
if (err) {
959-
return err;
960-
}
961-
962947
lfs_entry_t entry;
963-
err = lfs_dir_find(lfs, dir, &entry, &path);
948+
int err = lfs_dir_find(lfs, dir, &entry, &path);
964949
if (err) {
965950
return err;
966951
} else if (entry.d.type != LFS_TYPE_DIR) {
@@ -1302,13 +1287,8 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
13021287

13031288
// allocate entry for file if it doesn't exist
13041289
lfs_dir_t cwd;
1305-
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
1306-
if (err) {
1307-
return err;
1308-
}
1309-
13101290
lfs_entry_t entry;
1311-
err = lfs_dir_find(lfs, &cwd, &entry, &path);
1291+
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
13121292
if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) {
13131293
return err;
13141294
}
@@ -1814,13 +1794,8 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
18141794
/// General fs operations ///
18151795
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
18161796
lfs_dir_t cwd;
1817-
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
1818-
if (err) {
1819-
return err;
1820-
}
1821-
18221797
lfs_entry_t entry;
1823-
err = lfs_dir_find(lfs, &cwd, &entry, &path);
1798+
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
18241799
if (err) {
18251800
return err;
18261801
}
@@ -1855,13 +1830,8 @@ int lfs_remove(lfs_t *lfs, const char *path) {
18551830
}
18561831

18571832
lfs_dir_t cwd;
1858-
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
1859-
if (err) {
1860-
return err;
1861-
}
1862-
18631833
lfs_entry_t entry;
1864-
err = lfs_dir_find(lfs, &cwd, &entry, &path);
1834+
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
18651835
if (err) {
18661836
return err;
18671837
}
@@ -1916,24 +1886,14 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
19161886

19171887
// find old entry
19181888
lfs_dir_t oldcwd;
1919-
int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root);
1920-
if (err) {
1921-
return err;
1922-
}
1923-
19241889
lfs_entry_t oldentry;
1925-
err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
1890+
int err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
19261891
if (err) {
19271892
return err;
19281893
}
19291894

19301895
// allocate new entry
19311896
lfs_dir_t newcwd;
1932-
err = lfs_dir_fetch(lfs, &newcwd, lfs->root);
1933-
if (err) {
1934-
return err;
1935-
}
1936-
19371897
lfs_entry_t preventry;
19381898
err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath);
19391899
if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) {

tests/test_paths.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@ tests/test.py << TEST
9090
lfs_unmount(&lfs) => 0;
9191
TEST
9292

93+
echo "--- Trailing dot path tests ---"
94+
tests/test.py << TEST
95+
lfs_mount(&lfs, &cfg) => 0;
96+
lfs_stat(&lfs, "tea/hottea/", &info) => 0;
97+
strcmp(info.name, "hottea") => 0;
98+
lfs_stat(&lfs, "tea/hottea/.", &info) => 0;
99+
strcmp(info.name, "hottea") => 0;
100+
lfs_stat(&lfs, "tea/hottea/./.", &info) => 0;
101+
strcmp(info.name, "hottea") => 0;
102+
lfs_stat(&lfs, "tea/hottea/..", &info) => 0;
103+
strcmp(info.name, "tea") => 0;
104+
lfs_stat(&lfs, "tea/hottea/../.", &info) => 0;
105+
strcmp(info.name, "tea") => 0;
106+
lfs_unmount(&lfs) => 0;
107+
TEST
108+
93109
echo "--- Root dot dot path tests ---"
94110
tests/test.py << TEST
95111
lfs_mount(&lfs, &cfg) => 0;

0 commit comments

Comments
 (0)