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