mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Added support for custom attributes 2
This commit is contained in:
		
							
								
								
									
										74
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -526,13 +526,20 @@ static int32_t lfs_commitget(lfs_t *lfs, lfs_block_t block, lfs_off_t off, | ||||
|     return LFS_ERR_NOENT; | ||||
| } | ||||
|  | ||||
| static int lfs_commitattrs(lfs_t *lfs, struct lfs_commit *commit, | ||||
|         uint16_t id, const struct lfs_attr *attrs); | ||||
|  | ||||
| static int lfs_commitmove(lfs_t *lfs, struct lfs_commit *commit, | ||||
|         uint16_t fromid, uint16_t toid, | ||||
|         const lfs_mdir_t *dir, const lfs_mattr_t *attrs); | ||||
|  | ||||
| static int lfs_commitattr(lfs_t *lfs, struct lfs_commit *commit, | ||||
|         uint32_t tag, const void *buffer) { | ||||
|     if (lfs_tagtype(tag) == LFS_FROM_MOVE) { | ||||
|     if (lfs_tagtype(tag) == LFS_FROM_ATTRS) { | ||||
|         // special case for custom attributes | ||||
|         return lfs_commitattrs(lfs, commit, | ||||
|                 lfs_tagid(tag), buffer); | ||||
|     } else if (lfs_tagtype(tag) == LFS_FROM_MOVE) { | ||||
|         // special case for moves | ||||
|         return lfs_commitmove(lfs, commit, | ||||
|                 lfs_tagsize(tag), lfs_tagid(tag), | ||||
| @@ -586,6 +593,19 @@ static int lfs_commitattr(lfs_t *lfs, struct lfs_commit *commit, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int lfs_commitattrs(lfs_t *lfs, struct lfs_commit *commit, | ||||
|         uint16_t id, const struct lfs_attr *attrs) { | ||||
|     for (const struct lfs_attr *a = attrs; a; a = a->next) { | ||||
|         int err = lfs_commitattr(lfs, commit, | ||||
|                 LFS_MKTAG(0x100 | a->type, id, a->size), a->buffer); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int lfs_commitmove(lfs_t *lfs, struct lfs_commit *commit, | ||||
|         uint16_t fromid, uint16_t toid, | ||||
|         const lfs_mdir_t *dir, const lfs_mattr_t *attrs) { | ||||
| @@ -1865,33 +1885,27 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | ||||
|     file->pos = 0; | ||||
|     file->attrs = NULL; | ||||
|  | ||||
|     if (cfg) { | ||||
|     if (cfg && cfg->attrs) { | ||||
|         // fetch attrs | ||||
|         file->attrs = (lfs_mattr_t*)cfg->attrs; | ||||
|  | ||||
|         for (lfs_mattr_t *b = file->attrs; b; b = (lfs_mattr_t*)b->next) { | ||||
|             struct lfs_attr *a = (struct lfs_attr*)b; | ||||
|             if (a->size > lfs->attr_size) { | ||||
|                 return LFS_ERR_NOSPC; | ||||
|             } | ||||
|  | ||||
|             b->tag = LFS_MKTAG(0x100 | a->type, file->id, a->size); | ||||
|         for (const struct lfs_attr *a = cfg->attrs; a; a = a->next) { | ||||
|             if ((file->flags & 3) != LFS_O_WRONLY) { | ||||
|                 int32_t res = lfs_dir_get(lfs, &cwd, 0x7ffff000, | ||||
|                         b->tag, a->buffer); | ||||
|                         LFS_MKTAG(0x100 | a->type, file->id, a->size), a->buffer); | ||||
|                 if (res < 0 && res != LFS_ERR_NOENT) { | ||||
|                     return res; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             b->buffer = a->buffer; | ||||
|             b->next = (lfs_mattr_t*)a->next; | ||||
|  | ||||
|             if ((file->flags & 3) != LFS_O_RDONLY) { | ||||
|                 // TODO hmm | ||||
|                 if (a->size > lfs->attr_size) { | ||||
|                     return LFS_ERR_NOSPC; | ||||
|                 } | ||||
|  | ||||
|                 file->flags |= LFS_F_DIRTY; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         file->attrs = cfg->attrs; | ||||
|     } | ||||
|  | ||||
|     // allocate buffer if needed | ||||
| @@ -1960,17 +1974,6 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | ||||
|         lfs_free(file->cache.buffer); | ||||
|     } | ||||
|  | ||||
|     // fix attr structures | ||||
|     // TODO this is a hack? | ||||
|     for (struct lfs_attr *b = (struct lfs_attr*)file->attrs; b; b = b->next) { | ||||
|         lfs_mattr_t *a = (lfs_mattr_t*)b; | ||||
|  | ||||
|         b->next = (struct lfs_attr*)a->next; | ||||
|         b->size = lfs_tagsize(a->tag); | ||||
|         b->buffer = (void*)a->buffer; | ||||
|         b->type = 0xff & lfs_tagtype(a->tag); | ||||
|     } | ||||
|  | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| @@ -2112,17 +2115,13 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // update all ids in case we've moved | ||||
|         for (lfs_mattr_t *a = file->attrs; a; a = (lfs_mattr_t*)a->next) { | ||||
|             a->tag = (a->tag & 0xffc00fff) | LFS_MKTAG(0, file->id, 0); | ||||
|         } | ||||
|  | ||||
|         // either update the references or inline the whole file | ||||
|         if (!(file->flags & LFS_F_INLINE)) { | ||||
|             int err = lfs_dir_commit(lfs, &cwd, | ||||
|                     LFS_MKATTR(LFS_TYPE_CTZSTRUCT, file->id, | ||||
|                         &file->ctz.head, sizeof(file->ctz), | ||||
|                     file->attrs)); | ||||
|                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->attrs, 0, | ||||
|                     NULL))); | ||||
|             if (err) { | ||||
|                 return err; | ||||
|             } | ||||
| @@ -2130,7 +2129,8 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | ||||
|             int err = lfs_dir_commit(lfs, &cwd, | ||||
|                     LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, | ||||
|                             file->cache.buffer, file->ctz.size, | ||||
|                     file->attrs)); | ||||
|                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->attrs, 0, | ||||
|                     NULL))); | ||||
|             if (err) { | ||||
|                 return err; | ||||
|             } | ||||
| @@ -2741,9 +2741,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||
|  | ||||
| lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | ||||
|         uint8_t type, void *buffer, lfs_size_t size) { | ||||
|     // TODO need me? | ||||
|     memset(buffer, 0, size); | ||||
|  | ||||
|     lfs_mdir_t cwd; | ||||
|     int32_t res = lfs_dir_lookup(lfs, &cwd, &path); | ||||
|     if (res < 0) { | ||||
| @@ -2782,9 +2779,6 @@ int lfs_setattr(lfs_t *lfs, const char *path, | ||||
|  | ||||
| lfs_ssize_t lfs_fs_getattr(lfs_t *lfs, | ||||
|         uint8_t type, void *buffer, lfs_size_t size) { | ||||
|     // TODO need me? | ||||
|     memset(buffer, 0, size); | ||||
|  | ||||
|     lfs_mdir_t superdir; | ||||
|     int err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1}); | ||||
|     if (err) { | ||||
|   | ||||
							
								
								
									
										7
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -118,6 +118,7 @@ enum lfs_type { | ||||
|     LFS_FROM_REGION         = 0x000, | ||||
|     LFS_FROM_DISK           = 0x200, | ||||
|     LFS_FROM_MOVE           = 0x030, | ||||
|     LFS_FROM_ATTRS          = 0x020, | ||||
| }; | ||||
|  | ||||
| // File open flags | ||||
| @@ -258,7 +259,7 @@ struct lfs_attr { | ||||
|     lfs_size_t size; | ||||
|  | ||||
|     // Pointer to next attribute in linked list | ||||
|     struct lfs_attr *next; | ||||
|     const struct lfs_attr *next; | ||||
| }; | ||||
|  | ||||
| // Optional configuration provided during lfs_file_opencfg | ||||
| @@ -269,7 +270,7 @@ struct lfs_file_config { | ||||
|  | ||||
|     // Optional, custom attributes | ||||
|     // TODO document more | ||||
|     struct lfs_attr *attrs; | ||||
|     const struct lfs_attr *attrs; | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -315,7 +316,7 @@ typedef struct lfs_file { | ||||
|     } ctz; | ||||
|  | ||||
|     const struct lfs_file_config *cfg; | ||||
|     struct lfs_mattr *attrs; | ||||
|     const struct lfs_attr *attrs; | ||||
|     uint32_t flags; | ||||
|     lfs_off_t pos; | ||||
|     lfs_block_t block; | ||||
|   | ||||
| @@ -140,12 +140,10 @@ TEST | ||||
| echo "--- Set/get file attribute ---" | ||||
| tests/test.py << TEST | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     struct lfs_file_config cfg1 = { | ||||
|         .attrs = | ||||
|             &(struct lfs_attr){'A', buffer,    4, | ||||
|             &(struct lfs_attr){'B', buffer+4,  6, | ||||
|             &(struct lfs_attr){'C', buffer+10, 5}}} | ||||
|     }; | ||||
|     struct lfs_attr a1 = {'A', buffer,    4}; | ||||
|     struct lfs_attr b1 = {'B', buffer+4,  6, &a1}; | ||||
|     struct lfs_attr c1 = {'C', buffer+10, 5, &b1}; | ||||
|     struct lfs_file_config cfg1 = {.attrs = &c1}; | ||||
|  | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|     memcpy(buffer,    "aaaa",   4); | ||||
| @@ -159,55 +157,53 @@ tests/test.py << TEST | ||||
|     memcmp(buffer+4,  "bbbbbb", 6) => 0; | ||||
|     memcmp(buffer+10, "ccccc",  5) => 0; | ||||
|  | ||||
|     cfg1.attrs->next->size = 0; | ||||
|     b1.size = 0; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     memset(buffer, 0, 15); | ||||
|     cfg1.attrs->next->size = 6; | ||||
|     b1.size = 6; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg1) => 0; | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     memcmp(buffer,    "aaaa",         4) => 0; | ||||
|     memcmp(buffer+4,  "\0\0\0\0\0\0", 6) => 0; | ||||
|     memcmp(buffer+10, "ccccc",        5) => 0; | ||||
|  | ||||
|     cfg1.attrs->next->size = 6; | ||||
|     b1.size = 6; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|     memcpy(buffer+4,  "dddddd", 6); | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     memset(buffer, 0, 15); | ||||
|     cfg1.attrs->next->size = 6; | ||||
|     b1.size = 6; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg1) => 0; | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     memcmp(buffer,    "aaaa",   4) => 0; | ||||
|     memcmp(buffer+4,  "dddddd", 6) => 0; | ||||
|     memcmp(buffer+10, "ccccc",  5) => 0; | ||||
|  | ||||
|     cfg1.attrs->next->size = 3; | ||||
|     b1.size = 3; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|     memcpy(buffer+4,  "eee", 3); | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     memset(buffer, 0, 15); | ||||
|     cfg1.attrs->next->size = 6; | ||||
|     b1.size = 6; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg1) => 0; | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     memcmp(buffer,    "aaaa",      4) => 0; | ||||
|     memcmp(buffer+4,  "eee\0\0\0", 6) => 0; | ||||
|     memcmp(buffer+10, "ccccc",     5) => 0; | ||||
|  | ||||
|     cfg1.attrs->size = LFS_ATTR_MAX+1; | ||||
|     a1.size = LFS_ATTR_MAX+1; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) | ||||
|         => LFS_ERR_NOSPC; | ||||
|  | ||||
|     struct lfs_file_config cfg2 = { | ||||
|         .attrs = | ||||
|             &(struct lfs_attr){'A', buffer,    4, | ||||
|             &(struct lfs_attr){'B', buffer+4,  9, | ||||
|             &(struct lfs_attr){'C', buffer+13, 5}}} | ||||
|     }; | ||||
|     struct lfs_attr a2 = {'A', buffer,    4}; | ||||
|     struct lfs_attr b2 = {'B', buffer+4,  9, &a2}; | ||||
|     struct lfs_attr c2 = {'C', buffer+13, 5, &b2}; | ||||
|     struct lfs_file_config cfg2 = {.attrs = &c2}; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDWR, &cfg2) => 0; | ||||
|     memcpy(buffer+4,  "fffffffff", 9); | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|     cfg1.attrs->size = 4; | ||||
|     a1.size = 4; | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg1) => 0; | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
|  | ||||
| @@ -215,12 +211,10 @@ tests/test.py << TEST | ||||
| TEST | ||||
| tests/test.py << TEST | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     struct lfs_file_config cfg2 = { | ||||
|         .attrs = | ||||
|             &(struct lfs_attr){'A', buffer,    4, | ||||
|             &(struct lfs_attr){'B', buffer+4,  9, | ||||
|             &(struct lfs_attr){'C', buffer+13, 5}}} | ||||
|     }; | ||||
|     struct lfs_attr a2 = {'A', buffer,    4}; | ||||
|     struct lfs_attr b2 = {'B', buffer+4,  9, &a2}; | ||||
|     struct lfs_attr c2 = {'C', buffer+13, 5, &b2}; | ||||
|     struct lfs_file_config cfg2 = {.attrs = &c2}; | ||||
|  | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg2) => 0; | ||||
|     lfs_file_close(&lfs, &file[0]) => 0; | ||||
| @@ -238,12 +232,10 @@ TEST | ||||
| echo "--- Deferred file attributes ---" | ||||
| tests/test.py << TEST | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     struct lfs_file_config cfg1 = { | ||||
|         .attrs = | ||||
|             &(struct lfs_attr){'B', "gggg", 4, | ||||
|             &(struct lfs_attr){'C', "",     0, | ||||
|             &(struct lfs_attr){'D', "hhhh", 4}}} | ||||
|     }; | ||||
|     struct lfs_attr a1 = {'B', "gggg", 4}; | ||||
|     struct lfs_attr b1 = {'C', "",     0, &a1}; | ||||
|     struct lfs_attr c1 = {'D', "hhhh", 4, &b1}; | ||||
|     struct lfs_file_config cfg1 = {.attrs = &c1}; | ||||
|  | ||||
|     lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user