Browse Source

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
Christopher Haster 8 năm trước cách đây
mục cha
commit
a8fa5e6571
2 tập tin đã thay đổi với 52 bổ sung6 xóa
  1. 15 6
      lfs.c
  2. 37 0
      tests/test_paths.sh

+ 15 - 6
lfs.c

@@ -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);
@@ -750,8 +753,6 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
         if (err) {
             return err;
         }
-
-        *path = pathname;
     }
 
     return 0;
@@ -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;
     }
 
@@ -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;
@@ -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;
     }
 
@@ -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) {
@@ -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);

+ 37 - 0
tests/test_paths.sh

@@ -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
 
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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