mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-11-01 00:38:29 +01:00 
			
		
		
		
	WIP custom attributes
This commit is contained in:
		
							
								
								
									
										224
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -913,7 +913,7 @@ 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, | ||||
|         lfs_entry_t *entry, const char **path) { | ||||
|     const char *pathname = *path; | ||||
|     size_t pathlen; | ||||
|     lfs_size_t pathlen; | ||||
|  | ||||
|     while (true) { | ||||
|     nextname: | ||||
| @@ -940,7 +940,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | ||||
|  | ||||
|         // skip if matched by '..' in name | ||||
|         const char *suffix = pathname + pathlen; | ||||
|         size_t sufflen; | ||||
|         lfs_size_t sufflen; | ||||
|         int depth = 1; | ||||
|         while (true) { | ||||
|             suffix += strspn(suffix, "/"); | ||||
| @@ -1019,6 +1019,142 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Internal attribute operations /// | ||||
| static int lfs_dir_getinfo(lfs_t *lfs, | ||||
|         lfs_dir_t *dir, const lfs_entry_t *entry, struct lfs_info *info) { | ||||
|     memset(info, 0, sizeof(*info)); | ||||
|     info->type = 0xf & entry->d.type; | ||||
|     if (entry->d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { | ||||
|         info->size = entry->d.u.file.size; | ||||
|     } else if (entry->d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { | ||||
|         info->size = lfs_entry_elen(entry); | ||||
|     } | ||||
|  | ||||
|     if (lfs_paircmp(entry->d.u.dir, lfs->root) == 0) { | ||||
|         strcpy(info->name, "/"); | ||||
|     } else { | ||||
|         int err = lfs_dir_get(lfs, dir, | ||||
|                 entry->off + entry->size - entry->d.nlen, | ||||
|                 info->name, entry->d.nlen); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int lfs_dir_getattr(lfs_t *lfs, | ||||
|         lfs_dir_t *dir, const lfs_entry_t *entry, | ||||
|         uint8_t type, void *buffer, lfs_size_t size) { | ||||
|     // search for attribute in attribute region | ||||
|     lfs_off_t off = sizeof(dir->d) + lfs_entry_elen(entry); | ||||
|     lfs_off_t i = 0; | ||||
|     while (i < lfs_entry_alen(entry)) { | ||||
|         lfs_attr_t attr; | ||||
|         int err = lfs_dir_get(lfs, dir, | ||||
|                 entry->off+off+i, &attr.d, sizeof(attr.d)); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         if (attr.d.type != type) { | ||||
|             i += attr.d.len; | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         if (attr.d.len > size) { | ||||
|             return LFS_ERR_RANGE; | ||||
|         } | ||||
|  | ||||
|         err = lfs_dir_get(lfs, dir, | ||||
|                 entry->off+off+i+sizeof(attr.d), buffer, attr.d.len); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         return attr.d.len; | ||||
|     } | ||||
|  | ||||
|     return LFS_ERR_NODATA; | ||||
| } | ||||
|  | ||||
| static int lfs_dir_setattr(lfs_t *lfs, | ||||
|         lfs_dir_t *dir, lfs_entry_t *entry, | ||||
|         uint8_t type, const void *buffer, lfs_size_t size) { | ||||
|     // search for attribute in attribute region | ||||
|     lfs_off_t off = sizeof(dir->d) + lfs_entry_elen(entry); | ||||
|     lfs_off_t i = 0; | ||||
|     lfs_size_t oldlen = 0; | ||||
|     while (i < lfs_entry_alen(entry)) { | ||||
|         lfs_attr_t attr; | ||||
|         int err = lfs_dir_get(lfs, dir, | ||||
|                 entry->off+off+i, &attr.d, sizeof(attr.d)); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         if (attr.d.type != type) { | ||||
|             i += attr.d.len; | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         oldlen = attr.d.len; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     // make sure the attribute fits | ||||
|     if (lfs_entry_elen(entry) - oldlen + size > lfs->attrs_size || | ||||
|         (0x7fffffff & dir->d.size) - oldlen + size > lfs->cfg->block_size) { | ||||
|         return LFS_ERR_NOSPC; | ||||
|     } | ||||
|  | ||||
|     lfs_attr_t attr; | ||||
|     attr.d.type = type; | ||||
|     attr.d.len = size; | ||||
|     int err = lfs_dir_set(lfs, dir, entry, (struct lfs_region[]){ | ||||
|             {LFS_FROM_MEM, off+i, &attr.d, sizeof(attr.d)}, | ||||
|             {LFS_FROM_MEM, off+i, buffer, size}, | ||||
|             {LFS_FROM_DROP, off+i, NULL, -oldlen}}, 3); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int lfs_dir_removeattr(lfs_t *lfs, | ||||
|         lfs_dir_t *dir, lfs_entry_t *entry, uint8_t type) { | ||||
|     // search for attribute in attribute region | ||||
|     lfs_off_t off = sizeof(dir->d) + lfs_entry_elen(entry); | ||||
|     lfs_off_t i = 0; | ||||
|     while (i < lfs_entry_alen(entry)) { | ||||
|         lfs_attr_t attr; | ||||
|         int err = lfs_dir_get(lfs, dir, | ||||
|                 entry->off+off+i, &attr.d, sizeof(attr.d)); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         if (attr.d.type != type) { | ||||
|             i += attr.d.len; | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         err = lfs_dir_set(lfs, dir, entry, (struct lfs_region[]){ | ||||
|                 {LFS_FROM_DROP, off+i, | ||||
|                     NULL, -(sizeof(attr.d)+attr.d.len)}}, 1); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     return LFS_ERR_NODATA; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /// Top level directory operations /// | ||||
| int lfs_mkdir(lfs_t *lfs, const char *path) { | ||||
| @@ -1179,16 +1315,7 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     info->type = 0xf & entry.d.type; | ||||
|     if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { | ||||
|         info->size = entry.d.u.file.size; | ||||
|     } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { | ||||
|         info->size = lfs_entry_elen(&entry); | ||||
|     } | ||||
|  | ||||
|     int err = lfs_dir_get(lfs, dir, | ||||
|             entry.off + entry.size - entry.d.nlen, | ||||
|             info->name, entry.d.nlen); | ||||
|     int err = lfs_dir_getinfo(lfs, dir, &entry, info); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -2048,26 +2175,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     memset(info, 0, sizeof(*info)); | ||||
|     info->type = 0xf & entry.d.type; | ||||
|     if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { | ||||
|         info->size = entry.d.u.file.size; | ||||
|     } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { | ||||
|         info->size = lfs_entry_elen(&entry); | ||||
|     } | ||||
|  | ||||
|     if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { | ||||
|         strcpy(info->name, "/"); | ||||
|     } else { | ||||
|         err = lfs_dir_get(lfs, &cwd, | ||||
|                 entry.off + entry.size - entry.d.nlen, | ||||
|                 info->name, entry.d.nlen); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
|     return lfs_dir_getinfo(lfs, &cwd, &entry, info); | ||||
| } | ||||
|  | ||||
| int lfs_remove(lfs_t *lfs, const char *path) { | ||||
| @@ -2263,6 +2371,58 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Attribute operations /// | ||||
| int lfs_getattr(lfs_t *lfs, const char *path, | ||||
|         uint8_t type, void *buffer, lfs_size_t size) { | ||||
|     lfs_dir_t cwd; | ||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     lfs_entry_t entry; | ||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     return lfs_dir_getattr(lfs, &cwd, &entry, type, buffer, size); | ||||
| } | ||||
|  | ||||
| int lfs_setattr(lfs_t *lfs, const char *path, | ||||
|         uint8_t type, const void *buffer, lfs_size_t size) { | ||||
|     lfs_dir_t cwd; | ||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     lfs_entry_t entry; | ||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     return lfs_dir_setattr(lfs, &cwd, &entry, type, buffer, size); | ||||
| } | ||||
|  | ||||
| int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) { | ||||
|     lfs_dir_t cwd; | ||||
|     int err = lfs_dir_fetch(lfs, &cwd, lfs->root); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     lfs_entry_t entry; | ||||
|     err = lfs_dir_find(lfs, &cwd, &entry, &path); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     return lfs_dir_removeattr(lfs, &cwd, &entry, type); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Filesystem operations /// | ||||
| static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|     lfs->cfg = cfg; | ||||
|   | ||||
							
								
								
									
										32
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -89,6 +89,8 @@ enum lfs_error { | ||||
|     LFS_ERR_NOSPC       = -28,  // No space left on device | ||||
|     LFS_ERR_NOMEM       = -12,  // No more memory available | ||||
|     LFS_ERR_NAMETOOLONG = -36,  // File name too long | ||||
|     LFS_ERR_NODATA      = -61,  // No data/attr available | ||||
|     LFS_ERR_RANGE       = -34,  // Result not representable | ||||
| }; | ||||
|  | ||||
| // File types | ||||
| @@ -253,6 +255,13 @@ typedef struct lfs_entry { | ||||
|     } d; | ||||
| } lfs_entry_t; | ||||
|  | ||||
| typedef struct lfs_attr { | ||||
|     struct lfs_disk_attr { | ||||
|         uint8_t type; | ||||
|         uint8_t len; | ||||
|     } d; | ||||
| } lfs_attr_t; | ||||
|  | ||||
| typedef struct lfs_cache { | ||||
|     lfs_block_t block; | ||||
|     lfs_off_t off; | ||||
| @@ -379,6 +388,29 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath); | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info); | ||||
|  | ||||
| // Get a custom attribute | ||||
| // | ||||
| // Attributes are identified by an 8-bit type and are limited to at | ||||
| // most LFS_ATTRS_SIZE bytes. | ||||
| // Returns the size of the attribute, or a negative error code on failure. | ||||
| int lfs_getattr(lfs_t *lfs, const char *path, | ||||
|         uint8_t type, void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Set a custom attribute | ||||
| // | ||||
| // Attributes are identified by an 8-bit type and are limited to at | ||||
| // most LFS_ATTRS_SIZE bytes. | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_setattr(lfs_t *lfs, const char *path, | ||||
|         uint8_t type, const void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Remove a custom attribute | ||||
| // | ||||
| // Attributes are identified by an 8-bit type and are limited to at | ||||
| // most LFS_ATTRS_SIZE bytes. | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type); | ||||
|  | ||||
|  | ||||
| /// File operations /// | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user