mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Fixed issue with trailing dots in file paths
Paths such as the following were causing issues: /tea/hottea/. /tea/hottea/.. Unfortunately the existing structure for path lookup didn't make it very easy to introduce proper handling in this case without duplicating the entire skip logic for paths. So the lfs_dir_find function had to be restructured a bit. One odd side-effect of this is that now lfs_dir_find includes the initial fetch operation. This kinda breaks the fetch -> op pattern of the dir functions, but does come with a nice code size reduction.
This commit is contained in:
		
							
								
								
									
										98
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -783,6 +783,12 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|         lfs_entry_t *entry, const char **path) { |         lfs_entry_t *entry, const char **path) { | ||||||
|     const char *pathname = *path; |     const char *pathname = *path; | ||||||
|     size_t pathlen; |     size_t pathlen; | ||||||
|  |     entry->d.type = LFS_TYPE_DIR; | ||||||
|  |     entry->d.elen = sizeof(entry->d) - 4; | ||||||
|  |     entry->d.alen = 0; | ||||||
|  |     entry->d.nlen = 0; | ||||||
|  |     entry->d.u.dir[0] = lfs->root[0]; | ||||||
|  |     entry->d.u.dir[1] = lfs->root[1]; | ||||||
|  |  | ||||||
|     while (true) { |     while (true) { | ||||||
| nextname: | nextname: | ||||||
| @@ -790,19 +796,6 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|         pathname += strspn(pathname, "/"); |         pathname += strspn(pathname, "/"); | ||||||
|         pathlen = strcspn(pathname, "/"); |         pathlen = strcspn(pathname, "/"); | ||||||
|  |  | ||||||
|         // special case for root dir |  | ||||||
|         if (pathname[0] == '\0') { |  | ||||||
|             *entry = (lfs_entry_t){ |  | ||||||
|                 .d.type = LFS_TYPE_DIR, |  | ||||||
|                 .d.elen = sizeof(entry->d) - 4, |  | ||||||
|                 .d.alen = 0, |  | ||||||
|                 .d.nlen = 0, |  | ||||||
|                 .d.u.dir[0] = lfs->root[0], |  | ||||||
|                 .d.u.dir[1] = lfs->root[1], |  | ||||||
|             }; |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // skip '.' and root '..' |         // skip '.' and root '..' | ||||||
|         if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || |         if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || | ||||||
|             (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { |             (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { | ||||||
| @@ -834,10 +827,25 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             suffix += sufflen; |             suffix += sufflen; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // found path | ||||||
|  |         if (pathname[0] == '\0') { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // update what we've found |         // update what we've found | ||||||
|         *path = pathname; |         *path = pathname; | ||||||
|  |  | ||||||
|         // find path |         // continue on if we hit a directory | ||||||
|  |         if (entry->d.type != LFS_TYPE_DIR) { | ||||||
|  |             return LFS_ERR_NOTDIR; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // find entry matching name | ||||||
|         while (true) { |         while (true) { | ||||||
|             int err = lfs_dir_next(lfs, dir, entry); |             int err = lfs_dir_next(lfs, dir, entry); | ||||||
|             if (err) { |             if (err) { | ||||||
| @@ -873,21 +881,8 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             entry->d.type &= ~0x80; |             entry->d.type &= ~0x80; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // to next name | ||||||
|         pathname += pathlen; |         pathname += pathlen; | ||||||
|         pathname += strspn(pathname, "/"); |  | ||||||
|         if (pathname[0] == '\0') { |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // continue on if we hit a directory |  | ||||||
|         if (entry->d.type != LFS_TYPE_DIR) { |  | ||||||
|             return LFS_ERR_NOTDIR; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -904,13 +899,8 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|  |  | ||||||
|     // fetch parent directory |     // fetch parent directory | ||||||
|     lfs_dir_t cwd; |     lfs_dir_t cwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); |     int err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||||
|     if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) { |     if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) { | ||||||
|         return err ? err : LFS_ERR_EXIST; |         return err ? err : LFS_ERR_EXIST; | ||||||
|     } |     } | ||||||
| @@ -954,13 +944,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | |||||||
|     dir->pair[0] = lfs->root[0]; |     dir->pair[0] = lfs->root[0]; | ||||||
|     dir->pair[1] = lfs->root[1]; |     dir->pair[1] = lfs->root[1]; | ||||||
|  |  | ||||||
|     int err = lfs_dir_fetch(lfs, dir, dir->pair); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, dir, &entry, &path); |     int err = lfs_dir_find(lfs, dir, &entry, &path); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } else if (entry.d.type != LFS_TYPE_DIR) { |     } else if (entry.d.type != LFS_TYPE_DIR) { | ||||||
| @@ -1302,13 +1287,8 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|  |  | ||||||
|     // allocate entry for file if it doesn't exist |     // allocate entry for file if it doesn't exist | ||||||
|     lfs_dir_t cwd; |     lfs_dir_t cwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); |     int err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||||
|     if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) { |     if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1814,13 +1794,8 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) { | |||||||
| /// General fs operations /// | /// General fs operations /// | ||||||
| int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | ||||||
|     lfs_dir_t cwd; |     lfs_dir_t cwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); |     int err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1855,13 +1830,8 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     lfs_dir_t cwd; |     lfs_dir_t cwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); |     int err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1916,24 +1886,14 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|  |  | ||||||
|     // find old entry |     // find old entry | ||||||
|     lfs_dir_t oldcwd; |     lfs_dir_t oldcwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t oldentry; |     lfs_entry_t oldentry; | ||||||
|     err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath); |     int err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // allocate new entry |     // allocate new entry | ||||||
|     lfs_dir_t newcwd; |     lfs_dir_t newcwd; | ||||||
|     err = lfs_dir_fetch(lfs, &newcwd, lfs->root); |  | ||||||
|     if (err) { |  | ||||||
|         return err; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t preventry; |     lfs_entry_t preventry; | ||||||
|     err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath); |     err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath); | ||||||
|     if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) { |     if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) { | ||||||
|   | |||||||
| @@ -90,6 +90,22 @@ tests/test.py << TEST | |||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| TEST | TEST | ||||||
|  |  | ||||||
|  | echo "--- Trailing dot path tests ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 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, "tea") => 0; | ||||||
|  |     lfs_stat(&lfs, "tea/hottea/../.", &info) => 0; | ||||||
|  |     strcmp(info.name, "tea") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
| echo "--- Root dot dot path tests ---" | echo "--- Root dot dot path tests ---" | ||||||
| tests/test.py << TEST | tests/test.py << TEST | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user