mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Added path iteration and chained directories
All path iteration all goes through the lfs_dir_find function, which manages the syntax of paths and updates the path pointer to just the name stored in the dir entry. Also added directory chaining, which allows more than one block per directory. This is a simple linked list.
This commit is contained in:
		
							
								
								
									
										176
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -310,7 +310,7 @@ static int lfs_pair_commit(lfs_t *lfs, lfs_block_t pair[2], | |||||||
|  |  | ||||||
| /// Directory operations /// | /// Directory operations /// | ||||||
|  |  | ||||||
| static int lfs_dir_create(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) { | static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) { | ||||||
|     // Allocate pair of dir blocks |     // Allocate pair of dir blocks | ||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
|         int err = lfs_alloc(lfs, &dir->pair[i]); |         int err = lfs_alloc(lfs, &dir->pair[i]); | ||||||
| @@ -328,7 +328,7 @@ static int lfs_dir_create(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) { | |||||||
|     dir->d.rev += 1; |     dir->d.rev += 1; | ||||||
|  |  | ||||||
|     // Calculate total size |     // Calculate total size | ||||||
|     dir->d.size = sizeof(dir->d) + 2*sizeof(struct lfs_disk_entry) + 3; |     dir->d.size = sizeof(dir->d); | ||||||
|     dir->off = sizeof(dir->d); |     dir->off = sizeof(dir->d); | ||||||
|  |  | ||||||
|     // Other defaults |     // Other defaults | ||||||
| @@ -337,27 +337,35 @@ static int lfs_dir_create(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) { | |||||||
|     dir->d.free = lfs->free; |     dir->d.free = lfs->free; | ||||||
|  |  | ||||||
|     // Write out to memory |     // Write out to memory | ||||||
|     return lfs_pair_commit(lfs, dir->pair, |     if (!parent) { | ||||||
|         5, (struct lfs_commit_region[]){ |         return lfs_pair_commit(lfs, dir->pair, | ||||||
|             {0, sizeof(dir->d), &dir->d}, |             1, (struct lfs_commit_region[]){ | ||||||
|             {sizeof(dir->d), sizeof(struct lfs_disk_entry), |                 {0, sizeof(dir->d), &dir->d} | ||||||
|              &(struct lfs_disk_entry){ |             }); | ||||||
|                 .type     = LFS_TYPE_DIR, |     } else { | ||||||
|                 .len      = sizeof(struct lfs_disk_entry)+1, |         dir->d.size += 2*sizeof(struct lfs_disk_entry) + 3; | ||||||
|                 .u.dir[0] = dir->pair[0], |         return lfs_pair_commit(lfs, dir->pair, | ||||||
|                 .u.dir[1] = dir->pair[1], |             5, (struct lfs_commit_region[]){ | ||||||
|             }}, |                 {0, sizeof(dir->d), &dir->d}, | ||||||
|             {sizeof(dir->d)+sizeof(struct lfs_disk_entry), 1, "."}, |                 {sizeof(dir->d), sizeof(struct lfs_disk_entry), | ||||||
|             {sizeof(dir->d)+sizeof(struct lfs_disk_entry)+1, |                  &(struct lfs_disk_entry){ | ||||||
|              sizeof(struct lfs_disk_entry), |                     .type     = LFS_TYPE_DIR, | ||||||
|              &(struct lfs_disk_entry){ |                     .len      = sizeof(struct lfs_disk_entry)+1, | ||||||
|                 .type     = LFS_TYPE_DIR, |                     .u.dir[0] = dir->pair[0], | ||||||
|                 .len      = sizeof(struct lfs_disk_entry)+2, |                     .u.dir[1] = dir->pair[1], | ||||||
|                 .u.dir[0] = parent ? parent[0] : dir->pair[0], |                 }}, | ||||||
|                 .u.dir[1] = parent ? parent[1] : dir->pair[1], |                 {sizeof(dir->d)+sizeof(struct lfs_disk_entry), 1, "."}, | ||||||
|             }}, |                 {sizeof(dir->d)+sizeof(struct lfs_disk_entry)+1, | ||||||
|             {sizeof(dir->d)+2*sizeof(struct lfs_disk_entry)+1, 2, ".."}, |                  sizeof(struct lfs_disk_entry), | ||||||
|         }); |                  &(struct lfs_disk_entry){ | ||||||
|  |                     .type     = LFS_TYPE_DIR, | ||||||
|  |                     .len      = sizeof(struct lfs_disk_entry)+2, | ||||||
|  |                     .u.dir[0] = parent[0] ? parent[0] : dir->pair[0], | ||||||
|  |                     .u.dir[1] = parent[1] ? parent[1] : dir->pair[1], | ||||||
|  |                 }}, | ||||||
|  |                 {sizeof(dir->d)+2*sizeof(struct lfs_disk_entry)+1, 2, ".."}, | ||||||
|  |             }); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_fetch(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t pair[2]) { | static int lfs_dir_fetch(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t pair[2]) { | ||||||
| @@ -373,13 +381,20 @@ static int lfs_dir_fetch(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t pair[2]) { | |||||||
|  |  | ||||||
| static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | ||||||
|     while (true) { |     while (true) { | ||||||
|         // TODO iterate down list |  | ||||||
|         entry->dir[0] = dir->pair[0]; |  | ||||||
|         entry->dir[1] = dir->pair[1]; |  | ||||||
|         entry->off = dir->off; |  | ||||||
|  |  | ||||||
|         if (dir->d.size - dir->off < sizeof(entry->d)) { |         if (dir->d.size - dir->off < sizeof(entry->d)) { | ||||||
|             return LFS_ERROR_NO_ENTRY; |             if (!dir->d.tail[0]) { | ||||||
|  |                 entry->dir[0] = dir->pair[0]; | ||||||
|  |                 entry->dir[1] = dir->pair[1]; | ||||||
|  |                 entry->off = dir->off; | ||||||
|  |                 return LFS_ERROR_NO_ENTRY; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int err = lfs_dir_fetch(lfs, dir, dir->d.tail); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             dir->off = sizeof(dir->d); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int err = lfs_bd_read(lfs, dir->pair[0], dir->off, |         int err = lfs_bd_read(lfs, dir->pair[0], dir->off, | ||||||
| @@ -389,51 +404,92 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         dir->off += entry->d.len; |         dir->off += entry->d.len; | ||||||
|  |         if (entry->d.type == LFS_TYPE_REG || entry->d.type == LFS_TYPE_DIR) { | ||||||
|         // Skip any unknown entries |             entry->dir[0] = dir->pair[0]; | ||||||
|         if ((entry->d.type & 0xf) == 1 || (entry->d.type & 0xf) == 2) { |             entry->dir[1] = dir->pair[1]; | ||||||
|  |             entry->off = dir->off - entry->d.len; | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         const char *path, lfs_entry_t *entry) { |         const char **path, lfs_entry_t *entry) { | ||||||
|     // TODO follow directories |  | ||||||
|     lfs_size_t pathlen = strcspn(path, "/"); |  | ||||||
|     while (true) { |     while (true) { | ||||||
|         int err = lfs_dir_next(lfs, dir, entry); |         const char *pathname = *path; | ||||||
|  |         lfs_size_t pathlen = strcspn(pathname, "/"); | ||||||
|  |         while (true) { | ||||||
|  |             int err = lfs_dir_next(lfs, dir, entry); | ||||||
|  |             if (err) { | ||||||
|  |                 return err; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (entry->d.len - sizeof(entry->d) != pathlen) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int ret = lfs_bd_cmp(lfs, entry->dir[0], | ||||||
|  |                     entry->off + sizeof(entry->d), pathlen, pathname); | ||||||
|  |             if (ret < 0) { | ||||||
|  |                 return ret; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Found match | ||||||
|  |             if (ret == true) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         pathname += pathlen; | ||||||
|  |         pathname += strspn(pathname, "/"); | ||||||
|  |         if (pathname[0] == '\0') { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (entry->d.type != LFS_TYPE_DIR) { | ||||||
|  |             return LFS_ERROR_NOT_DIR; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (entry->d.len - sizeof(entry->d) != pathlen) { |         *path = pathname; | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         int ret = lfs_bd_cmp(lfs, entry->dir[0], |  | ||||||
|                 entry->off + sizeof(entry->d), pathlen, path); |  | ||||||
|         if (ret < 0) { |  | ||||||
|             return ret; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // Found match |  | ||||||
|         if (ret == true) { |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         const char *path, lfs_entry_t *entry) { |         const char **path, lfs_entry_t *entry) { | ||||||
|     int err = lfs_dir_find(lfs, dir, path, entry); |     int err = lfs_dir_find(lfs, dir, path, entry); | ||||||
|     if (err != LFS_ERROR_NO_ENTRY) { |     if (err != LFS_ERROR_NO_ENTRY) { | ||||||
|         return err ? err : LFS_ERROR_EXISTS; |         return err ? err : LFS_ERROR_EXISTS; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Check if we fit |     // Check if we fit | ||||||
|     if (dir->d.size + strlen(path) > lfs->block_size - 4) { |     if (dir->d.size + sizeof(entry->d) + strlen(*path) > lfs->block_size - 4) { | ||||||
|         return -1; // TODO make fit |         lfs_dir_t olddir; | ||||||
|  |         memcpy(&olddir, dir, sizeof(olddir)); | ||||||
|  |  | ||||||
|  |         int err = lfs_dir_alloc(lfs, dir, 0); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         entry->dir[0] = dir->pair[0]; | ||||||
|  |         entry->dir[1] = dir->pair[1]; | ||||||
|  |         entry->off = dir->off; | ||||||
|  |  | ||||||
|  |         olddir.d.rev += 1; | ||||||
|  |         olddir.d.tail[0] = dir->pair[0]; | ||||||
|  |         olddir.d.tail[1] = dir->pair[1]; | ||||||
|  |         olddir.d.free = lfs->free; | ||||||
|  |         return lfs_pair_commit(lfs, olddir.pair, | ||||||
|  |             1, (struct lfs_commit_region[]){ | ||||||
|  |                 {0, sizeof(olddir.d), &olddir.d} | ||||||
|  |             }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -448,14 +504,14 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_append(lfs, &cwd, path, &entry); |     err = lfs_dir_append(lfs, &cwd, &path, &entry); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Build up new directory |     // Build up new directory | ||||||
|     lfs_dir_t dir; |     lfs_dir_t dir; | ||||||
|     err = lfs_dir_create(lfs, &dir, cwd.pair); |     err = lfs_dir_alloc(lfs, &dir, cwd.pair); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -494,7 +550,7 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, dir, path, &entry); |     err = lfs_dir_find(lfs, dir, &path, &entry); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } else if (entry.d.type != LFS_TYPE_DIR) { |     } else if (entry.d.type != LFS_TYPE_DIR) { | ||||||
| @@ -546,12 +602,12 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (flags & LFS_O_CREAT) { |     if (flags & LFS_O_CREAT) { | ||||||
|         err = lfs_dir_append(lfs, &cwd, path, &file->entry); |         err = lfs_dir_append(lfs, &cwd, &path, &file->entry); | ||||||
|         if (err && err != LFS_ERROR_EXISTS) { |         if (err && err != LFS_ERROR_EXISTS) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         err = lfs_dir_find(lfs, &cwd, path, &file->entry); |         err = lfs_dir_find(lfs, &cwd, &path, &file->entry); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -789,11 +845,11 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) { | |||||||
|  |  | ||||||
|     // Create free list |     // Create free list | ||||||
|     lfs->free.begin = 2; |     lfs->free.begin = 2; | ||||||
|     lfs->free.end = lfs->block_count; |     lfs->free.end = lfs->block_count-1; | ||||||
|  |  | ||||||
|     // Write root directory |     // Write root directory | ||||||
|     lfs_dir_t root; |     lfs_dir_t root; | ||||||
|     err = lfs_dir_create(lfs, &root, 0); |     err = lfs_dir_alloc(lfs, &root, (lfs_block_t[2]){0, 0}); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -10,9 +10,8 @@ def generate(test): | |||||||
|         template = file.read() |         template = file.read() | ||||||
|  |  | ||||||
|     lines = [] |     lines = [] | ||||||
|  |  | ||||||
|     for line in re.split('(?<=[;{}])\n', test.read()): |     for line in re.split('(?<=[;{}])\n', test.read()): | ||||||
|         match = re.match('( *)(.*)=>(.*);', line, re.MULTILINE) |         match = re.match('(?: *\n)*( *)(.*)=>(.*);', line, re.MULTILINE) | ||||||
|         if match: |         if match: | ||||||
|             tab, test, expect = match.groups() |             tab, test, expect = match.groups() | ||||||
|             lines.append(tab+'res = {test};'.format(test=test.strip())) |             lines.append(tab+'res = {test};'.format(test=test.strip())) | ||||||
| @@ -33,13 +32,17 @@ def execute(): | |||||||
|     subprocess.check_call(["./lfs"]) |     subprocess.check_call(["./lfs"]) | ||||||
|  |  | ||||||
| def main(test=None): | def main(test=None): | ||||||
|     if test: |     if test and not test.startswith('-'): | ||||||
|         with open(test) as file: |         with open(test) as file: | ||||||
|             generate(file) |             generate(file) | ||||||
|     else: |     else: | ||||||
|         generate(sys.stdin) |         generate(sys.stdin) | ||||||
|  |  | ||||||
|     compile() |     compile() | ||||||
|  |  | ||||||
|  |     if test == '-s': | ||||||
|  |         sys.exit(1) | ||||||
|  |  | ||||||
|     execute() |     execute() | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
| set -eu | set -eu | ||||||
|  |  | ||||||
|  | LARGESIZE=128 | ||||||
|  |  | ||||||
| echo "=== Directory tests ===" | echo "=== Directory tests ===" | ||||||
| rm -rf blocks | rm -rf blocks | ||||||
| tests/test.py << TEST | tests/test.py << TEST | ||||||
| @@ -62,5 +64,65 @@ tests/test.py << TEST | |||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| TEST | TEST | ||||||
|  |  | ||||||
|  | echo "--- Nested directories ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "potato/baked") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "potato/sweet") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "potato/fried") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir[0], "potato") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, ".") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "..") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "baked") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "sweet") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "fried") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Multi-block directory ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "cactus") => 0; | ||||||
|  |     for (int i = 0; i < $LARGESIZE; i++) { | ||||||
|  |         sprintf((char*)buffer, "cactus/test%d", i); | ||||||
|  |         lfs_mkdir(&lfs, (char*)buffer) => 0; | ||||||
|  |     } | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir[0], "cactus") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, ".") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "..") => 0; | ||||||
|  |     info.type => LFS_TYPE_DIR; | ||||||
|  |     for (int i = 0; i < $LARGESIZE; i++) { | ||||||
|  |         sprintf((char*)buffer, "test%d", i); | ||||||
|  |         lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |         strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |         info.type => LFS_TYPE_DIR; | ||||||
|  |     } | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
| echo "--- Results ---" | echo "--- Results ---" | ||||||
| tests/stats.py | tests/stats.py | ||||||
|   | |||||||
							
								
								
									
										86
									
								
								tests/test_paths.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										86
									
								
								tests/test_paths.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | set -eu | ||||||
|  |  | ||||||
|  | echo "=== Path tests ===" | ||||||
|  | rm -rf blocks | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_format(&lfs, &config) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "tea") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "coffee") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "soda") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "tea/coldtea") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "soda/hotsoda") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "soda/warmsoda") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "soda/coldsoda") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Root path tests ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_stat(&lfs, "tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "/tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Redundant slash path tests ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_stat(&lfs, "/tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "//tea//hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "///tea///hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Dot path tests ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_stat(&lfs, "./tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "/./tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "/././tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "/./tea/./hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Dot dot path tests ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_stat(&lfs, "coffee/../tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "tea/coldtea/../hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "coffee/coldcoffee/../../tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_stat(&lfs, "coffee/../soda/../tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Root dot dot path tests ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &config) => 0; | ||||||
|  |     lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0; | ||||||
|  |     strcmp(info.name, "hottea") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Results ---" | ||||||
|  | tests/stats.py | ||||||
		Reference in New Issue
	
	Block a user