Added support for custom attributes 2

This commit is contained in:
Christopher Haster
2018-07-29 16:39:26 -05:00
parent 3a70619f41
commit c3c15d7636
3 changed files with 62 additions and 75 deletions

74
lfs.c
View File

@@ -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
View File

@@ -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;

View File

@@ -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;