mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Added dir navigation without needing parent entries
This should be the last step to removing the need for parent entries. Parent entries cause all sort of problems with atomic directory updates, especially related to moving/deleting directories. I couldn't figure out a parser for '..' entries without, O(n^2) runtime, a stack, or modifying the path itself. Since the goal is constant memory consumption, I went with the O(n^2) runtime solution, but this may need to be optimized later.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -31,7 +31,7 @@ size: $(OBJ) | |||||||
| 	$(SIZE) -t $^ | 	$(SIZE) -t $^ | ||||||
|  |  | ||||||
| .SUFFIXES: | .SUFFIXES: | ||||||
| test: test_format test_dirs test_files test_alloc test_orphan | test: test_format test_dirs test_files test_alloc test_orphan test_paths | ||||||
| test_%: tests/test_%.sh | test_%: tests/test_%.sh | ||||||
| 	./$< | 	./$< | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -627,9 +627,47 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|  |  | ||||||
| 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) { | ||||||
|  |     const char *pathname = *path; | ||||||
|  |     size_t pathlen; | ||||||
|  |  | ||||||
|     while (true) { |     while (true) { | ||||||
|         const char *pathname = *path; |     nextname: | ||||||
|         lfs_size_t pathlen = strcspn(pathname, "/"); |         // skip slashes | ||||||
|  |         pathname += strspn(pathname, "/"); | ||||||
|  |         pathlen = strcspn(pathname, "/"); | ||||||
|  |  | ||||||
|  |         // skip '.' and root '..' | ||||||
|  |         if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || | ||||||
|  |             (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { | ||||||
|  |             pathname += pathlen; | ||||||
|  |             goto nextname; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // skip if matched by '..' in name | ||||||
|  |         const char *suffix = pathname + pathlen; | ||||||
|  |         size_t sufflen; | ||||||
|  |         int depth = 1; | ||||||
|  |         while (true) { | ||||||
|  |             suffix += strspn(suffix, "/"); | ||||||
|  |             sufflen = strcspn(suffix, "/"); | ||||||
|  |             if (sufflen == 0) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { | ||||||
|  |                 depth -= 1; | ||||||
|  |                 if (depth == 0) { | ||||||
|  |                     pathname = suffix + sufflen; | ||||||
|  |                     goto nextname; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 depth += 1; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             suffix += sufflen; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // find path | ||||||
|         while (true) { |         while (true) { | ||||||
|             int err = lfs_dir_next(lfs, dir, entry); |             int err = lfs_dir_next(lfs, dir, entry); | ||||||
|             if (err) { |             if (err) { | ||||||
| @@ -658,6 +696,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // continue on if we hit a directory | ||||||
|         if (entry->d.type != LFS_TYPE_DIR) { |         if (entry->d.type != LFS_TYPE_DIR) { | ||||||
|             return LFS_ERROR_NOT_DIR; |             return LFS_ERROR_NOT_DIR; | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user