Эх сурвалжийг харах

paths: Fixed dots followed by dotdots

Unlike normal files, dots (".") should not change the depth when
attempting to skip dotdot ("..") entries.

A weird nuance in the path parser, but at least it had a relatively easy
fix.

Added test_paths_dot_dotdots to prevent a regression.
Christopher Haster 1 жил өмнө
parent
commit
815f0d85a5
2 өөрчлөгдсөн 195 нэмэгдсэн , 1 устгасан
  1. 3 1
      lfs.c
  2. 192 0
      tests/test_paths.toml

+ 3 - 1
lfs.c

@@ -1522,7 +1522,9 @@ nextname:
                 break;
             }
 
-            if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
+            if (sufflen == 1 && memcmp(suffix, ".", 1) == 0) {
+                // noop
+            } else if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
                 depth -= 1;
                 if (depth == 0) {
                     name = suffix + sufflen;

+ 192 - 0
tests/test_paths.toml

@@ -1845,6 +1845,198 @@ code = '''
     lfs_unmount(&lfs) => 0;
 '''
 
+# dot dot dot path tests
+[cases.test_paths_dot_dotdots]
+defines.DIR = [false, true]
+code = '''
+    lfs_t lfs;
+    lfs_format(&lfs, cfg) => 0;
+    lfs_mount(&lfs, cfg) => 0;
+
+    // create paths
+    lfs_mkdir(&lfs, "no") => 0;
+    lfs_mkdir(&lfs, "no/no") => 0;
+    lfs_mkdir(&lfs, "coffee") => 0;
+    lfs_mkdir(&lfs, "coffee/no") => 0;
+    if (DIR) {
+        lfs_mkdir(&lfs, "/coffee/drip") => 0;
+        lfs_mkdir(&lfs, "/no/./../coffee/coldbrew") => 0;
+        lfs_mkdir(&lfs, "/coffee/no/./../turkish") => 0;
+        lfs_mkdir(&lfs, "/no/no/./.././../coffee/tubruk") => 0;
+        lfs_mkdir(&lfs, "/no/no/./.././../coffee/no/./../vietnamese") => 0;
+        lfs_mkdir(&lfs, "/no/no/./.././../no/no/./.././../coffee/thai") => 0;
+    } else {
+        lfs_file_t file;
+        lfs_file_open(&lfs, &file, "/coffee/drip",
+                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew",
+                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/coffee/no/./../turkish",
+                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk",
+                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese",
+                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai",
+                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+    }
+
+    // stat paths
+    struct lfs_info info;
+    lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../coffee/drip", &info) => 0;
+    assert(strcmp(info.name, "drip") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/no/no/./.././../coffee/no/./../coldbrew", &info) => 0;
+    assert(strcmp(info.name, "coldbrew") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/no/no/./.././../coffee/turkish", &info) => 0;
+    assert(strcmp(info.name, "turkish") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/coffee/no/./../tubruk", &info) => 0;
+    assert(strcmp(info.name, "tubruk") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/no/./../coffee/vietnamese", &info) => 0;
+    assert(strcmp(info.name, "vietnamese") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/coffee/thai", &info) => 0;
+    assert(strcmp(info.name, "thai") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+
+    // file open paths, only works on files!
+    if (DIR) {
+        lfs_file_t file;
+        lfs_file_open(&lfs, &file, "/coffee/drip",
+                LFS_O_RDONLY) => LFS_ERR_ISDIR;
+        lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew",
+                LFS_O_RDONLY) => LFS_ERR_ISDIR;
+        lfs_file_open(&lfs, &file, "/coffee/no/./../turkish",
+                LFS_O_RDONLY) => LFS_ERR_ISDIR;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk",
+                LFS_O_RDONLY) => LFS_ERR_ISDIR;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese",
+                LFS_O_RDONLY) => LFS_ERR_ISDIR;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai",
+                LFS_O_RDONLY) => LFS_ERR_ISDIR;
+    } else {
+        lfs_file_t file;
+        lfs_file_open(&lfs, &file, "/coffee/drip",
+                LFS_O_RDONLY) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew",
+                LFS_O_RDONLY) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/coffee/no/./../turkish",
+                LFS_O_RDONLY) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk",
+                LFS_O_RDONLY) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese",
+                LFS_O_RDONLY) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+        lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai",
+                LFS_O_RDONLY) => 0;
+        lfs_file_close(&lfs, &file) => 0;
+    }
+
+    // dir open paths, only works on dirs!
+    if (DIR) {
+        lfs_dir_t dir;
+        lfs_dir_open(&lfs, &dir, "/coffee/drip") => 0;
+        lfs_dir_close(&lfs, &dir) => 0;
+        lfs_dir_open(&lfs, &dir, "/no/./../coffee/coldbrew") => 0;
+        lfs_dir_close(&lfs, &dir) => 0;
+        lfs_dir_open(&lfs, &dir, "/coffee/no/./../turkish") => 0;
+        lfs_dir_close(&lfs, &dir) => 0;
+        lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/tubruk") => 0;
+        lfs_dir_close(&lfs, &dir) => 0;
+        lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/no/./../vietnamese") => 0;
+        lfs_dir_close(&lfs, &dir) => 0;
+        lfs_dir_open(&lfs, &dir, "/no/no/./.././../no/no/./.././../coffee/thai") => 0;
+        lfs_dir_close(&lfs, &dir) => 0;
+    } else {
+        lfs_dir_t dir;
+        lfs_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR;
+        lfs_dir_open(&lfs, &dir, "/no/./../coffee/coldbrew") => LFS_ERR_NOTDIR;
+        lfs_dir_open(&lfs, &dir, "/coffee/no/./../turkish") => LFS_ERR_NOTDIR;
+        lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/tubruk") => LFS_ERR_NOTDIR;
+        lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/no/./../vietnamese") => LFS_ERR_NOTDIR;
+        lfs_dir_open(&lfs, &dir, "/no/no/./.././../no/no/./.././../coffee/thai") => LFS_ERR_NOTDIR;
+    }
+
+    // rename paths
+    lfs_mkdir(&lfs, "espresso") => 0;
+    lfs_rename(&lfs,
+            "/no/no/./.././../no/no/./.././../coffee/drip",
+            "/espresso/espresso") => 0;
+    lfs_rename(&lfs,
+            "/no/no/./.././../coffee/no/./../coldbrew",
+            "/no/./../espresso/americano") => 0;
+    lfs_rename(&lfs,
+            "/no/no/./.././../coffee/turkish",
+            "/espresso/no/./../macchiato") => 0;
+    lfs_rename(&lfs,
+            "/coffee/no/./../tubruk",
+            "/no/no/./.././../espresso/latte") => 0;
+    lfs_rename(&lfs,
+            "/no/./../coffee/vietnamese",
+            "/no/no/./.././../espresso/no/./../cappuccino") => 0;
+    lfs_rename(&lfs,
+            "/coffee/thai",
+            "/no/no/./.././../no/no/./.././../espresso/mocha") => 0;
+
+    // stat paths
+    lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../espresso/espresso", &info) => 0;
+    assert(strcmp(info.name, "espresso") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/no/no/./.././../espresso/no/./../americano", &info) => 0;
+    assert(strcmp(info.name, "americano") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/no/no/./.././../espresso/macchiato", &info) => 0;
+    assert(strcmp(info.name, "macchiato") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/espresso/no/./../latte", &info) => 0;
+    assert(strcmp(info.name, "latte") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/no/./../espresso/cappuccino", &info) => 0;
+    assert(strcmp(info.name, "cappuccino") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+    lfs_stat(&lfs, "/espresso/mocha", &info) => 0;
+    assert(strcmp(info.name, "mocha") == 0);
+    assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG));
+
+    lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../coffee/drip", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/no/no/./.././../coffee/no/./../coldbrew", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/no/no/./.././../coffee/turkish", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/coffee/no/./../tubruk", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/no/./../coffee/vietnamese", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT;
+
+    // remove paths
+    lfs_remove(&lfs, "/espresso/espresso") => 0;
+    lfs_remove(&lfs, "/no/./../espresso/americano") => 0;
+    lfs_remove(&lfs, "/espresso/no/./../macchiato") => 0;
+    lfs_remove(&lfs, "/no/no/./.././../espresso/latte") => 0;
+    lfs_remove(&lfs, "/no/no/./.././../espresso/no/./../cappuccino") => 0;
+    lfs_remove(&lfs, "/no/no/./.././../no/no/./.././../espresso/mocha") => 0;
+
+    // stat paths
+    lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../espresso/espresso", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/no/no/./.././../espresso/no/./../americano", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/no/no/./.././../espresso/macchiato", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/espresso/no/./../latte", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/no/./../espresso/cappuccino", &info) => LFS_ERR_NOENT;
+    lfs_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT;
+
+    lfs_unmount(&lfs) => 0;
+'''
+
 # dot dot dot path tests
 [cases.test_paths_dotdotdots]
 defines.DIR = [false, true]