diff --git a/lfs.c b/lfs.c index ae5f2b6..ae8b4c5 100644 --- a/lfs.c +++ b/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) { diff --git a/lfs.h b/lfs.h index cbb499c..b83a25c 100644 --- a/lfs.h +++ b/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; diff --git a/tests/test_attrs.sh b/tests/test_attrs.sh index 2af05e1..2fde13e 100755 --- a/tests/test_attrs.sh +++ b/tests/test_attrs.sh @@ -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;