Skip to content

Commit

Permalink
Fixed some corner cases with paths
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
geky committed Sep 17, 2017
1 parent 26dd49a commit a8fa5e6
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
21 changes: 15 additions & 6 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,9 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
suffix += sufflen;
}

// update what we've found
*path = pathname;

// find path
while (true) {
int err = lfs_dir_next(lfs, dir, entry);
Expand Down Expand Up @@ -750,8 +753,6 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
if (err) {
return err;
}

*path = pathname;
}

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

lfs_entry_t entry;
err = lfs_dir_find(lfs, &cwd, &entry, &path);
if (err != LFS_ERR_NOENT) {
if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
return err ? err : LFS_ERR_EXISTS;
}

Expand Down Expand Up @@ -817,8 +818,8 @@ 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)) {
// can only be something like '/././../.'
dir->head[0] = dir->pair[0];
dir->head[1] = dir->pair[1];
dir->pos = sizeof(dir->d) - 2;
Expand Down Expand Up @@ -1118,7 +1119,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,

lfs_entry_t entry;
err = lfs_dir_find(lfs, &cwd, &entry, &path);
if (err && err != LFS_ERR_NOENT) {
if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) {
return err;
}

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

/// General fs oprations ///
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) {
Expand Down Expand Up @@ -1640,7 +1649,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {

lfs_entry_t preventry;
err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath);
if (err && err != LFS_ERR_NOENT) {
if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) {
return err;
}
bool prevexists = (err != LFS_ERR_NOENT);
Expand Down
37 changes: 37 additions & 0 deletions tests/test_paths.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ tests/test.py << TEST
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "/tea/hottea", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_mkdir(&lfs, "/milk1") => 0;
lfs_stat(&lfs, "/milk1", &info) => 0;
strcmp(info.name, "milk1") => 0;
lfs_unmount(&lfs) => 0;
TEST

Expand All @@ -43,6 +47,10 @@ tests/test.py << TEST
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "///tea///hottea", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_mkdir(&lfs, "///milk2") => 0;
lfs_stat(&lfs, "///milk2", &info) => 0;
strcmp(info.name, "milk2") => 0;
lfs_unmount(&lfs) => 0;
TEST

Expand All @@ -57,6 +65,10 @@ tests/test.py << TEST
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "/./tea/./hottea", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_mkdir(&lfs, "/./milk3") => 0;
lfs_stat(&lfs, "/./milk3", &info) => 0;
strcmp(info.name, "milk3") => 0;
lfs_unmount(&lfs) => 0;
TEST

Expand All @@ -71,6 +83,10 @@ tests/test.py << TEST
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "coffee/../soda/../tea/hottea", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_mkdir(&lfs, "coffee/../milk4") => 0;
lfs_stat(&lfs, "coffee/../milk4", &info) => 0;
strcmp(info.name, "milk4") => 0;
lfs_unmount(&lfs) => 0;
TEST

Expand All @@ -79,6 +95,27 @@ tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_mkdir(&lfs, "coffee/../../../../../../milk5") => 0;
lfs_stat(&lfs, "coffee/../../../../../../milk5", &info) => 0;
strcmp(info.name, "milk5") => 0;
lfs_unmount(&lfs) => 0;
TEST

echo "--- Root tests ---"
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "/", &info) => 0;
info.type => LFS_TYPE_DIR;
strcmp(info.name, "/") => 0;
lfs_unmount(&lfs) => 0;
TEST

echo "--- Sketchy path tests ---"
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "dirt/ground") => LFS_ERR_NOENT;
lfs_mkdir(&lfs, "dirt/ground/earth") => LFS_ERR_NOENT;
lfs_unmount(&lfs) => 0;
TEST

Expand Down

0 comments on commit a8fa5e6

Please sign in to comment.