mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Pulled in fixes for additional path corner cases
Pulled in 015b86b. Merging this now avoids duplicate effort restructuring
the path lookup logic.
			
			
This commit is contained in:
		
							
								
								
									
										75
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -1273,21 +1273,19 @@ static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir, | |||||||
| } | } | ||||||
|  |  | ||||||
| static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) { | static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) { | ||||||
|     lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]}; |     // we reduce path to a single name if we can find it | ||||||
|     const char *name = *path; |     const char *name = *path; | ||||||
|     lfs_size_t namelen; |     *path = NULL; | ||||||
|     int32_t tag; |  | ||||||
|  |     // default to root dir | ||||||
|  |     int32_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0); | ||||||
|  |     lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]}; | ||||||
|  |  | ||||||
|     while (true) { |     while (true) { | ||||||
|     nextname: | nextname: | ||||||
|         // skip slashes |         // skip slashes | ||||||
|         name += strspn(name, "/"); |         name += strspn(name, "/"); | ||||||
|         namelen = strcspn(name, "/"); |         lfs_size_t namelen = strcspn(name, "/"); | ||||||
|  |  | ||||||
|         if (name[0] == '\0') { |  | ||||||
|             // special case for root dir |  | ||||||
|             return LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // skip '.' and root '..' |         // skip '.' and root '..' | ||||||
|         if ((namelen == 1 && memcmp(name, ".", 1) == 0) || |         if ((namelen == 1 && memcmp(name, ".", 1) == 0) || | ||||||
| @@ -1320,10 +1318,31 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) { | |||||||
|             suffix += sufflen; |             suffix += sufflen; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // update what we've found |         // found path | ||||||
|         *path = name; |         if (name[0] == '\0') { | ||||||
|  |             return tag; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // find path |         // update what we've found if path is only a name | ||||||
|  |         if (strchr(name, '/') == NULL) { | ||||||
|  |             *path = name; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // only continue if we hit a directory | ||||||
|  |         if (lfs_tagtype(tag) != LFS_TYPE_DIR) { | ||||||
|  |             return LFS_ERR_NOTDIR; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // grab the entry data | ||||||
|  |         if (lfs_tagid(tag) != 0x3ff) { | ||||||
|  |             int32_t res = lfs_dir_get(lfs, dir, 0x7c3ff000, | ||||||
|  |                     LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tagid(tag), 8), pair); | ||||||
|  |             if (res < 0) { | ||||||
|  |                 return res; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // find entry matching name | ||||||
|         while (true) { |         while (true) { | ||||||
|             tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff, |             tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff, | ||||||
|                     LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name); |                     LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name); | ||||||
| @@ -1337,6 +1356,7 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (!dir->split) { |             if (!dir->split) { | ||||||
|  |                 // couldn't find it | ||||||
|                 return LFS_ERR_NOENT; |                 return LFS_ERR_NOENT; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -1344,26 +1364,8 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) { | |||||||
|             pair[1] = dir->tail[1]; |             pair[1] = dir->tail[1]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // to next name | ||||||
|         name += namelen; |         name += namelen; | ||||||
|         name += strspn(name, "/"); |  | ||||||
|         if (name[0] == '\0') { |  | ||||||
|             return tag; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // don't continue on if we didn't hit a directory |  | ||||||
|         // TODO update with what's on master? |  | ||||||
|         if (lfs_tagtype(tag) != LFS_TYPE_DIR) { |  | ||||||
|             return LFS_ERR_NOTDIR; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // TODO optimize grab for inline files and like? |  | ||||||
|         // TODO would this mean more code? |  | ||||||
|         // grab the entry data |  | ||||||
|         int32_t res = lfs_dir_get(lfs, dir, 0x7c3ff000, |  | ||||||
|                 LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tagid(tag), 8), pair); |  | ||||||
|         if (res < 0) { |  | ||||||
|             return res; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1408,11 +1410,8 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|  |  | ||||||
|     lfs_mdir_t cwd; |     lfs_mdir_t cwd; | ||||||
|     int32_t res = lfs_dir_lookup(lfs, &cwd, &path); |     int32_t res = lfs_dir_lookup(lfs, &cwd, &path); | ||||||
|     if (res != LFS_ERR_NOENT || strchr(path, '/') != NULL) { |     if (res != LFS_ERR_NOENT || !path) { | ||||||
|         if (res >= 0) { |         return (res < 0) ? res : LFS_ERR_EXIST; | ||||||
|             return LFS_ERR_EXIST; |  | ||||||
|         } |  | ||||||
|         return res; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // check that name fits |     // check that name fits | ||||||
| @@ -1806,7 +1805,7 @@ 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_mdir_t cwd; |     lfs_mdir_t cwd; | ||||||
|     int32_t tag = lfs_dir_lookup(lfs, &cwd, &path); |     int32_t tag = lfs_dir_lookup(lfs, &cwd, &path); | ||||||
|     if (tag < 0 && (tag != LFS_ERR_NOENT || strchr(path, '/') != NULL)) { |     if (tag < 0 && (tag != LFS_ERR_NOENT || !path)) { | ||||||
|         return tag; |         return tag; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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