mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Fixed handling of root as target for create operations
Before this patch, when calling lfs_mkdir or lfs_file_open with root as the target, littlefs wouldn't find the path properly and happily run into undefined behaviour. The fix is to populate a directory entry for root in the lfs_dir_find function. As an added plus, this allowed several special cases around root to be completely dropped.
This commit is contained in:
		
							
								
								
									
										44
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -780,6 +780,19 @@ 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)) { | ||||||
| @@ -936,15 +949,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // check for root, can only be something like '/././../.' |  | ||||||
|     if (strspn(path, "/.") == strlen(path)) { |  | ||||||
|         dir->head[0] = dir->pair[0]; |  | ||||||
|         dir->head[1] = dir->pair[1]; |  | ||||||
|         dir->pos = sizeof(dir->d) - 2; |  | ||||||
|         dir->off = sizeof(dir->d); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_entry_t entry; |     lfs_entry_t entry; | ||||||
|     err = lfs_dir_find(lfs, dir, &entry, &path); |     err = lfs_dir_find(lfs, dir, &entry, &path); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -1799,14 +1803,6 @@ 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) { | ||||||
|     // check for root, can only be something like '/././../.' |  | ||||||
|     if (strspn(path, "/.") == strlen(path)) { |  | ||||||
|         memset(info, 0, sizeof(*info)); |  | ||||||
|         info->type = LFS_TYPE_DIR; |  | ||||||
|         strcpy(info->name, "/"); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lfs_dir_t cwd; |     lfs_dir_t cwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); |     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -1825,11 +1821,15 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | |||||||
|         info->size = entry.d.u.file.size; |         info->size = entry.d.u.file.size; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_bd_read(lfs, cwd.pair[0], |     if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { | ||||||
|             entry.off + 4+entry.d.elen+entry.d.alen, |         strcpy(info->name, "/"); | ||||||
|             info->name, entry.d.nlen); |     } else { | ||||||
|     if (err) { |         err = lfs_bd_read(lfs, cwd.pair[0], | ||||||
|         return err; |                 entry.off + 4+entry.d.elen+entry.d.alen, | ||||||
|  |                 info->name, entry.d.nlen); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
|   | |||||||
| @@ -108,6 +108,10 @@ tests/test.py << TEST | |||||||
|     lfs_stat(&lfs, "/", &info) => 0; |     lfs_stat(&lfs, "/", &info) => 0; | ||||||
|     info.type => LFS_TYPE_DIR; |     info.type => LFS_TYPE_DIR; | ||||||
|     strcmp(info.name, "/") => 0; |     strcmp(info.name, "/") => 0; | ||||||
|  |  | ||||||
|  |     lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; | ||||||
|  |     lfs_file_open(&lfs, &file[0], "/", LFS_O_WRONLY | LFS_O_CREAT) | ||||||
|  |         => LFS_ERR_ISDIR; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| TEST | TEST | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user