mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
WIP Added support for custom attributes 1
This commit is contained in:
6
Makefile
6
Makefile
@@ -33,9 +33,9 @@ size: $(OBJ)
|
|||||||
$(SIZE) -t $^
|
$(SIZE) -t $^
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
test: test_format test_dirs test_files test_seek test_truncate test_entries \
|
test: test_format test_dirs test_files test_seek test_truncate \
|
||||||
test_interspersed test_alloc test_paths test_attrs \
|
test_entries test_interspersed test_alloc test_paths test_attrs \
|
||||||
test_orphan test_move test_corrupt
|
test_move test_orphan test_corrupt
|
||||||
test_%: tests/test_%.sh
|
test_%: tests/test_%.sh
|
||||||
ifdef QUIET
|
ifdef QUIET
|
||||||
@./$< | sed -n '/^[-=]/p'
|
@./$< | sed -n '/^[-=]/p'
|
||||||
|
|||||||
181
lfs.c
181
lfs.c
@@ -364,7 +364,7 @@ static void lfs_alloc_ack(lfs_t *lfs) {
|
|||||||
// d->block_count = lfs_fromle32(d->block_count);
|
// d->block_count = lfs_fromle32(d->block_count);
|
||||||
// d->version = lfs_fromle32(d->version);
|
// d->version = lfs_fromle32(d->version);
|
||||||
// d->inline_size = lfs_fromle32(d->inline_size);
|
// d->inline_size = lfs_fromle32(d->inline_size);
|
||||||
// d->attrs_size = lfs_fromle32(d->attrs_size);
|
// d->attr_size = lfs_fromle32(d->attr_size);
|
||||||
// d->name_size = lfs_fromle32(d->name_size);
|
// d->name_size = lfs_fromle32(d->name_size);
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
@@ -375,7 +375,7 @@ static void lfs_alloc_ack(lfs_t *lfs) {
|
|||||||
// d->block_count = lfs_tole32(d->block_count);
|
// d->block_count = lfs_tole32(d->block_count);
|
||||||
// d->version = lfs_tole32(d->version);
|
// d->version = lfs_tole32(d->version);
|
||||||
// d->inline_size = lfs_tole32(d->inline_size);
|
// d->inline_size = lfs_tole32(d->inline_size);
|
||||||
// d->attrs_size = lfs_tole32(d->attrs_size);
|
// d->attr_size = lfs_tole32(d->attr_size);
|
||||||
// d->name_size = lfs_tole32(d->name_size);
|
// d->name_size = lfs_tole32(d->name_size);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -430,7 +430,7 @@ static inline bool lfs_pairsync(
|
|||||||
(((uint32_t)(type) << 22) | ((uint32_t)(id) << 12) | (uint32_t)(size))
|
(((uint32_t)(type) << 22) | ((uint32_t)(id) << 12) | (uint32_t)(size))
|
||||||
|
|
||||||
#define LFS_MKATTR(type, id, buffer, size, next) \
|
#define LFS_MKATTR(type, id, buffer, size, next) \
|
||||||
&(const lfs_mattr_t){(next), LFS_MKTAG(type, id, size), (buffer)}
|
&(const lfs_mattr_t){LFS_MKTAG(type, id, size), (buffer), (next)}
|
||||||
|
|
||||||
static inline bool lfs_tagisvalid(uint32_t tag) {
|
static inline bool lfs_tagisvalid(uint32_t tag) {
|
||||||
return !(tag & 0x80000000);
|
return !(tag & 0x80000000);
|
||||||
@@ -1378,9 +1378,6 @@ static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
info->type = lfs_tagtype(tag);
|
info->type = lfs_tagtype(tag);
|
||||||
if (lfs_tagsize(tag) > lfs->name_size) {
|
|
||||||
return LFS_ERR_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lfs_ctz ctz;
|
struct lfs_ctz ctz;
|
||||||
tag = lfs_dir_get(lfs, dir, 0x7c3ff000,
|
tag = lfs_dir_get(lfs, dir, 0x7c3ff000,
|
||||||
@@ -1410,7 +1407,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
|
|||||||
|
|
||||||
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 != LFS_ERR_NOENT || !path) {
|
if (!(res == LFS_ERR_NOENT && path)) {
|
||||||
return (res < 0) ? res : LFS_ERR_EXIST;
|
return (res < 0) ? res : LFS_ERR_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1792,8 +1789,9 @@ static int lfs_ctztraverse(lfs_t *lfs,
|
|||||||
|
|
||||||
|
|
||||||
/// Top level file operations ///
|
/// Top level file operations ///
|
||||||
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
||||||
const char *path, int flags) {
|
const char *path, int flags,
|
||||||
|
const struct lfs_file_config *cfg) {
|
||||||
// deorphan if we haven't yet, needed at most once after poweron
|
// deorphan if we haven't yet, needed at most once after poweron
|
||||||
if ((flags & 3) != LFS_O_RDONLY && !lfs->deorphaned) {
|
if ((flags & 3) != LFS_O_RDONLY && !lfs->deorphaned) {
|
||||||
int err = lfs_deorphan(lfs);
|
int err = lfs_deorphan(lfs);
|
||||||
@@ -1805,7 +1803,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|||||||
// allocate entry for file if it doesn't exist
|
// allocate entry for file if it doesn't exist
|
||||||
lfs_mdir_t cwd;
|
lfs_mdir_t cwd;
|
||||||
int32_t tag = lfs_dir_lookup(lfs, &cwd, &path);
|
int32_t tag = lfs_dir_lookup(lfs, &cwd, &path);
|
||||||
if (tag < 0 && (tag != LFS_ERR_NOENT || !path)) {
|
if (tag < 0 && !(tag == LFS_ERR_NOENT && path)) {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1859,6 +1857,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup file struct
|
// setup file struct
|
||||||
|
file->cfg = cfg;
|
||||||
file->pair[0] = cwd.pair[0];
|
file->pair[0] = cwd.pair[0];
|
||||||
file->pair[1] = cwd.pair[1];
|
file->pair[1] = cwd.pair[1];
|
||||||
file->id = lfs_tagid(tag);
|
file->id = lfs_tagid(tag);
|
||||||
@@ -1866,9 +1865,40 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|||||||
file->pos = 0;
|
file->pos = 0;
|
||||||
file->attrs = NULL;
|
file->attrs = NULL;
|
||||||
|
|
||||||
|
if (cfg) {
|
||||||
|
// 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);
|
||||||
|
if ((file->flags & 3) != LFS_O_WRONLY) {
|
||||||
|
int32_t res = lfs_dir_get(lfs, &cwd, 0x7ffff000,
|
||||||
|
b->tag, 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
|
||||||
|
file->flags |= LFS_F_DIRTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// allocate buffer if needed
|
// allocate buffer if needed
|
||||||
file->cache.block = 0xffffffff;
|
file->cache.block = 0xffffffff;
|
||||||
if (lfs->cfg->file_buffer) {
|
if (file->cfg && file->cfg->buffer) {
|
||||||
|
file->cache.buffer = file->cfg->buffer;
|
||||||
|
} else if (lfs->cfg->file_buffer) {
|
||||||
file->cache.buffer = lfs->cfg->file_buffer;
|
file->cache.buffer = lfs->cfg->file_buffer;
|
||||||
} else if ((file->flags & 3) == LFS_O_RDONLY) {
|
} else if ((file->flags & 3) == LFS_O_RDONLY) {
|
||||||
file->cache.buffer = lfs_malloc(lfs->cfg->read_size);
|
file->cache.buffer = lfs_malloc(lfs->cfg->read_size);
|
||||||
@@ -1909,6 +1939,11 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
||||||
|
const char *path, int flags) {
|
||||||
|
return lfs_file_opencfg(lfs, file, path, flags, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
||||||
int err = lfs_file_sync(lfs, file);
|
int err = lfs_file_sync(lfs, file);
|
||||||
|
|
||||||
@@ -1921,10 +1956,21 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clean up memory
|
// clean up memory
|
||||||
if (!lfs->cfg->file_buffer) {
|
if (!(file->cfg && file->cfg->buffer) && !lfs->cfg->file_buffer) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2066,6 +2112,11 @@ 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,
|
||||||
@@ -2688,7 +2739,91 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//int lfs_getattrs(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) {
|
||||||
|
// TODO need me?
|
||||||
|
memset(buffer, 0, size);
|
||||||
|
|
||||||
|
lfs_mdir_t cwd;
|
||||||
|
int32_t res = lfs_dir_lookup(lfs, &cwd, &path);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = lfs_dir_get(lfs, &cwd, 0x7ffff000,
|
||||||
|
LFS_MKTAG(0x100 | type, lfs_tagid(res),
|
||||||
|
lfs_min(size, lfs->attr_size)), buffer);
|
||||||
|
if (res < 0) {
|
||||||
|
if (res == LFS_ERR_NOENT) {
|
||||||
|
return LFS_ERR_NOATTR;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lfs_tagsize(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lfs_setattr(lfs_t *lfs, const char *path,
|
||||||
|
uint8_t type, const void *buffer, lfs_size_t size) {
|
||||||
|
if (size > lfs->attr_size) {
|
||||||
|
return LFS_ERR_NOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_mdir_t cwd;
|
||||||
|
int32_t res = lfs_dir_lookup(lfs, &cwd, &path);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lfs_dir_commit(lfs, &cwd,
|
||||||
|
LFS_MKATTR(0x100 | type, lfs_tagid(res), buffer, size,
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
|
||||||
|
LFS_MKTAG(0x100 | type, 0,
|
||||||
|
lfs_min(size, lfs->attr_size)), buffer);
|
||||||
|
if (res < 0) {
|
||||||
|
if (res == LFS_ERR_NOENT) {
|
||||||
|
return LFS_ERR_NOATTR;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lfs_tagsize(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lfs_fs_setattr(lfs_t *lfs,
|
||||||
|
uint8_t type, const void *buffer, lfs_size_t size) {
|
||||||
|
if (size > lfs->attr_size) {
|
||||||
|
return LFS_ERR_NOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_mdir_t superdir;
|
||||||
|
int err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lfs_dir_commit(lfs, &superdir,
|
||||||
|
LFS_MKATTR(0x100 | type, 0, buffer, size,
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
// const struct lfs_attr *attrs, int count) {
|
// const struct lfs_attr *attrs, int count) {
|
||||||
// lfs_mdir_t cwd;
|
// lfs_mdir_t cwd;
|
||||||
// int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
// int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
||||||
@@ -2777,10 +2912,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->read_size);
|
lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->read_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
LFS_ASSERT(lfs->cfg->attrs_size <= LFS_ATTRS_MAX);
|
LFS_ASSERT(lfs->cfg->attr_size <= LFS_ATTR_MAX);
|
||||||
lfs->attrs_size = lfs->cfg->attrs_size;
|
lfs->attr_size = lfs->cfg->attr_size;
|
||||||
if (!lfs->attrs_size) {
|
if (!lfs->attr_size) {
|
||||||
lfs->attrs_size = LFS_ATTRS_MAX;
|
lfs->attr_size = LFS_ATTR_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
LFS_ASSERT(lfs->cfg->name_size <= LFS_NAME_MAX);
|
LFS_ASSERT(lfs->cfg->name_size <= LFS_NAME_MAX);
|
||||||
@@ -2873,7 +3008,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
.block_size = lfs->cfg->block_size,
|
.block_size = lfs->cfg->block_size,
|
||||||
.block_count = lfs->cfg->block_count,
|
.block_count = lfs->cfg->block_count,
|
||||||
.inline_size = lfs->inline_size,
|
.inline_size = lfs->inline_size,
|
||||||
.attrs_size = lfs->attrs_size,
|
.attr_size = lfs->attr_size,
|
||||||
.name_size = lfs->name_size,
|
.name_size = lfs->name_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2954,14 +3089,14 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
lfs->inline_size = superblock.inline_size;
|
lfs->inline_size = superblock.inline_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superblock.attrs_size) {
|
if (superblock.attr_size) {
|
||||||
if (superblock.attrs_size > lfs->attrs_size) {
|
if (superblock.attr_size > lfs->attr_size) {
|
||||||
LFS_ERROR("Unsupported attrs size (%d > %d)",
|
LFS_ERROR("Unsupported attr size (%d > %d)",
|
||||||
superblock.attrs_size, lfs->attrs_size);
|
superblock.attr_size, lfs->attr_size);
|
||||||
return LFS_ERR_INVAL;
|
return LFS_ERR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lfs->attrs_size = superblock.attrs_size;
|
lfs->attr_size = superblock.attr_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superblock.name_size) {
|
if (superblock.name_size) {
|
||||||
|
|||||||
112
lfs.h
112
lfs.h
@@ -52,18 +52,18 @@ typedef uint32_t lfs_block_t;
|
|||||||
|
|
||||||
// Maximum inline file size in bytes. Large inline files require a larger
|
// Maximum inline file size in bytes. Large inline files require a larger
|
||||||
// read and prog cache, but if a file can be inline it does not need its own
|
// read and prog cache, but if a file can be inline it does not need its own
|
||||||
// data block. LFS_ATTRS_MAX + LFS_INLINE_MAX must be <= 0xffff. Stored in
|
// data block. LFS_ATTR_MAX + LFS_INLINE_MAX must be <= 0xffff. Stored in
|
||||||
// superblock and must be respected by other littlefs drivers.
|
// superblock and must be respected by other littlefs drivers.
|
||||||
#ifndef LFS_INLINE_MAX
|
#ifndef LFS_INLINE_MAX
|
||||||
#define LFS_INLINE_MAX 0x3ff
|
#define LFS_INLINE_MAX 0x3ff
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Maximum size of all attributes per file in bytes, may be redefined but a
|
// Maximum size of all attributes per file in bytes, may be redefined but a
|
||||||
// a smaller LFS_ATTRS_MAX has no benefit. LFS_ATTRS_MAX + LFS_INLINE_MAX
|
// a smaller LFS_ATTR_MAX has no benefit. LFS_ATTR_MAX + LFS_INLINE_MAX
|
||||||
// must be <= 0xffff. Stored in superblock and must be respected by other
|
// must be <= 0xffff. Stored in superblock and must be respected by other
|
||||||
// littlefs drivers.
|
// littlefs drivers.
|
||||||
#ifndef LFS_ATTRS_MAX
|
#ifndef LFS_ATTR_MAX
|
||||||
#define LFS_ATTRS_MAX 0x3f
|
#define LFS_ATTR_MAX 0x3f
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Max name size in bytes, may be redefined to reduce the size of the
|
// Max name size in bytes, may be redefined to reduce the size of the
|
||||||
@@ -89,8 +89,7 @@ enum lfs_error {
|
|||||||
LFS_ERR_NOSPC = -28, // No space left on device
|
LFS_ERR_NOSPC = -28, // No space left on device
|
||||||
LFS_ERR_NOMEM = -12, // No more memory available
|
LFS_ERR_NOMEM = -12, // No more memory available
|
||||||
LFS_ERR_NAMETOOLONG = -36, // File name too long
|
LFS_ERR_NAMETOOLONG = -36, // File name too long
|
||||||
LFS_ERR_NODATA = -61, // No data/attr available
|
LFS_ERR_NOATTR = -61, // No data/attr available
|
||||||
LFS_ERR_RANGE = -34, // Result not representable
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// File types
|
// File types
|
||||||
@@ -223,10 +222,10 @@ struct lfs_config {
|
|||||||
lfs_size_t inline_size;
|
lfs_size_t inline_size;
|
||||||
|
|
||||||
// Optional upper limit on attributes per file in bytes. No downside for
|
// Optional upper limit on attributes per file in bytes. No downside for
|
||||||
// larger attributes size but must be less than LFS_ATTRS_MAX. Defaults to
|
// larger attributes size but must be less than LFS_ATTR_MAX. Defaults to
|
||||||
// LFS_ATTRS_MAX when zero.Stored in superblock and must be respected by
|
// LFS_ATTR_MAX when zero.Stored in superblock and must be respected by
|
||||||
// other littlefs drivers.
|
// other littlefs drivers.
|
||||||
lfs_size_t attrs_size;
|
lfs_size_t attr_size;
|
||||||
|
|
||||||
// Optional upper limit on length of file names in bytes. No downside for
|
// Optional upper limit on length of file names in bytes. No downside for
|
||||||
// larger names except the size of the info struct which is controlled by
|
// larger names except the size of the info struct which is controlled by
|
||||||
@@ -235,7 +234,6 @@ struct lfs_config {
|
|||||||
lfs_size_t name_size;
|
lfs_size_t name_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// File info structure
|
// File info structure
|
||||||
struct lfs_info {
|
struct lfs_info {
|
||||||
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
|
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
|
||||||
@@ -256,16 +254,30 @@ struct lfs_attr {
|
|||||||
// Pointer to buffer containing the attribute
|
// Pointer to buffer containing the attribute
|
||||||
void *buffer;
|
void *buffer;
|
||||||
|
|
||||||
// Size of attribute in bytes, limited to LFS_ATTRS_MAX
|
// Size of attribute in bytes, limited to LFS_ATTR_MAX
|
||||||
lfs_size_t size;
|
lfs_size_t size;
|
||||||
|
|
||||||
|
// Pointer to next attribute in linked list
|
||||||
|
struct lfs_attr *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optional configuration provided during lfs_file_opencfg
|
||||||
|
struct lfs_file_config {
|
||||||
|
// Optional, statically allocated buffer for files. Must be program sized.
|
||||||
|
// If NULL, malloc will be used by default.
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
|
// Optional, custom attributes
|
||||||
|
// TODO document more
|
||||||
|
struct lfs_attr *attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// littlefs data structures ///
|
/// littlefs data structures ///
|
||||||
typedef struct lfs_mattr {
|
typedef struct lfs_mattr {
|
||||||
const struct lfs_mattr *next;
|
|
||||||
int32_t tag;
|
int32_t tag;
|
||||||
const void *buffer;
|
const void *buffer;
|
||||||
|
const struct lfs_mattr *next;
|
||||||
} lfs_mattr_t;
|
} lfs_mattr_t;
|
||||||
|
|
||||||
typedef struct lfs_globals {
|
typedef struct lfs_globals {
|
||||||
@@ -302,13 +314,13 @@ typedef struct lfs_file {
|
|||||||
lfs_size_t size;
|
lfs_size_t size;
|
||||||
} ctz;
|
} ctz;
|
||||||
|
|
||||||
|
const struct lfs_file_config *cfg;
|
||||||
|
struct lfs_mattr *attrs;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
lfs_off_t pos;
|
lfs_off_t pos;
|
||||||
lfs_block_t block;
|
lfs_block_t block;
|
||||||
lfs_off_t off;
|
lfs_off_t off;
|
||||||
lfs_cache_t cache;
|
lfs_cache_t cache;
|
||||||
|
|
||||||
lfs_mattr_t *attrs;
|
|
||||||
} lfs_file_t;
|
} lfs_file_t;
|
||||||
|
|
||||||
typedef struct lfs_dir {
|
typedef struct lfs_dir {
|
||||||
@@ -328,7 +340,7 @@ typedef struct lfs_superblock {
|
|||||||
lfs_size_t block_count;
|
lfs_size_t block_count;
|
||||||
|
|
||||||
lfs_size_t inline_size;
|
lfs_size_t inline_size;
|
||||||
lfs_size_t attrs_size;
|
lfs_size_t attr_size;
|
||||||
lfs_size_t name_size;
|
lfs_size_t name_size;
|
||||||
} lfs_superblock_t;
|
} lfs_superblock_t;
|
||||||
|
|
||||||
@@ -358,7 +370,7 @@ typedef struct lfs {
|
|||||||
lfs_globals_t diff;
|
lfs_globals_t diff;
|
||||||
|
|
||||||
lfs_size_t inline_size;
|
lfs_size_t inline_size;
|
||||||
lfs_size_t attrs_size;
|
lfs_size_t attr_size;
|
||||||
lfs_size_t name_size;
|
lfs_size_t name_size;
|
||||||
} lfs_t;
|
} lfs_t;
|
||||||
|
|
||||||
@@ -368,7 +380,8 @@ typedef struct lfs {
|
|||||||
// Format a block device with the littlefs
|
// Format a block device with the littlefs
|
||||||
//
|
//
|
||||||
// Requires a littlefs object and config struct. This clobbers the littlefs
|
// Requires a littlefs object and config struct. This clobbers the littlefs
|
||||||
// object, and does not leave the filesystem mounted.
|
// object, and does not leave the filesystem mounted. The config struct must
|
||||||
|
// be zeroed for defaults and backwards compatibility.
|
||||||
//
|
//
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
||||||
@@ -377,7 +390,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
|||||||
//
|
//
|
||||||
// Requires a littlefs object and config struct. Multiple filesystems
|
// Requires a littlefs object and config struct. Multiple filesystems
|
||||||
// may be mounted simultaneously with multiple littlefs objects. Both
|
// may be mounted simultaneously with multiple littlefs objects. Both
|
||||||
// lfs and config must be allocated while mounted.
|
// lfs and config must be allocated while mounted. The config struct must
|
||||||
|
// be zeroed for defaults and backwards compatibility.
|
||||||
//
|
//
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
||||||
@@ -416,9 +430,10 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
|||||||
// smaller than the buffer, it is padded with zeros. It the stored attribute
|
// smaller than the buffer, it is padded with zeros. It the stored attribute
|
||||||
// is larger than the buffer, LFS_ERR_RANGE is returned.
|
// is larger than the buffer, LFS_ERR_RANGE is returned.
|
||||||
//
|
//
|
||||||
|
// TODO doc
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_getattrs(lfs_t *lfs, const char *path,
|
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
|
||||||
const struct lfs_attr *attrs, int count);
|
uint8_t type, void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
// Set custom attributes
|
// Set custom attributes
|
||||||
//
|
//
|
||||||
@@ -426,23 +441,38 @@ int lfs_getattrs(lfs_t *lfs, const char *path,
|
|||||||
// disk based on their type id. Unspecified attributes are left unmodified.
|
// disk based on their type id. Unspecified attributes are left unmodified.
|
||||||
// Specifying an attribute with zero size deletes the attribute.
|
// Specifying an attribute with zero size deletes the attribute.
|
||||||
//
|
//
|
||||||
|
// TODO doc
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_setattrs(lfs_t *lfs, const char *path,
|
int lfs_setattr(lfs_t *lfs, const char *path,
|
||||||
const struct lfs_attr *attrs, int count);
|
uint8_t type, const void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
|
|
||||||
/// File operations ///
|
/// File operations ///
|
||||||
|
|
||||||
// Open a file
|
// Open a file
|
||||||
//
|
//
|
||||||
// The mode that the file is opened in is determined
|
// The mode that the file is opened in is determined by the flags, which
|
||||||
// by the flags, which are values from the enum lfs_open_flags
|
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||||
// that are bitwise-ored together.
|
|
||||||
//
|
//
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
||||||
const char *path, int flags);
|
const char *path, int flags);
|
||||||
|
|
||||||
|
|
||||||
|
// Open a file with extra configuration
|
||||||
|
//
|
||||||
|
// The mode that the file is opened in is determined by the flags, which
|
||||||
|
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||||
|
//
|
||||||
|
// The config struct provides additional config options per file as described
|
||||||
|
// above. The config struct must be allocated while the file is open, and the
|
||||||
|
// config struct must be zeroed for defaults and backwards compatibility.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
||||||
|
const char *path, int flags,
|
||||||
|
const struct lfs_file_config *config);
|
||||||
|
|
||||||
// Close a file
|
// Close a file
|
||||||
//
|
//
|
||||||
// Any pending writes are written out to storage as though
|
// Any pending writes are written out to storage as though
|
||||||
@@ -503,30 +533,6 @@ int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
|
|||||||
// Returns the size of the file, or a negative error code on failure.
|
// Returns the size of the file, or a negative error code on failure.
|
||||||
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
|
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
|
||||||
// Get custom attributes attached to a file
|
|
||||||
//
|
|
||||||
// Attributes are looked up based on the type id. If the stored attribute is
|
|
||||||
// smaller than the buffer, it is padded with zeros. It the stored attribute
|
|
||||||
// is larger than the buffer, LFS_ERR_RANGE is returned.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_getattrs(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
const struct lfs_attr *attrs, int count);
|
|
||||||
|
|
||||||
// Set custom attributes on a file
|
|
||||||
//
|
|
||||||
// The array of attributes will be used to update the attributes stored on
|
|
||||||
// disk based on their type id. Unspecified attributes are left unmodified.
|
|
||||||
// Specifying an attribute with zero size deletes the attribute.
|
|
||||||
//
|
|
||||||
// Note: Attributes are not written out until a call to lfs_file_sync
|
|
||||||
// or lfs_file_close and must be allocated until the file is closed or
|
|
||||||
// lfs_file_setattrs is called with a count of zero.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_setattrs(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
const struct lfs_attr *attrs, int count);
|
|
||||||
|
|
||||||
|
|
||||||
/// Directory operations ///
|
/// Directory operations ///
|
||||||
|
|
||||||
@@ -583,8 +589,10 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
|||||||
// smaller than the buffer, it is padded with zeros. It the stored attribute
|
// smaller than the buffer, it is padded with zeros. It the stored attribute
|
||||||
// is larger than the buffer, LFS_ERR_RANGE is returned.
|
// is larger than the buffer, LFS_ERR_RANGE is returned.
|
||||||
//
|
//
|
||||||
|
// TODO doc
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_fs_getattrs(lfs_t *lfs, const struct lfs_attr *attrs, int count);
|
lfs_ssize_t lfs_fs_getattr(lfs_t *lfs,
|
||||||
|
uint8_t type, void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
// Set custom attributes on the filesystem
|
// Set custom attributes on the filesystem
|
||||||
//
|
//
|
||||||
@@ -594,8 +602,10 @@ int lfs_fs_getattrs(lfs_t *lfs, const struct lfs_attr *attrs, int count);
|
|||||||
//
|
//
|
||||||
// Note: Filesystem level attributes are not available for wear-leveling
|
// Note: Filesystem level attributes are not available for wear-leveling
|
||||||
//
|
//
|
||||||
|
// TODO doc
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_fs_setattrs(lfs_t *lfs, const struct lfs_attr *attrs, int count);
|
int lfs_fs_setattr(lfs_t *lfs,
|
||||||
|
uint8_t type, const void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
// Finds the current size of the filesystem
|
// Finds the current size of the filesystem
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -19,65 +19,53 @@ TEST
|
|||||||
echo "--- Set/get attribute ---"
|
echo "--- Set/get attribute ---"
|
||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_setattr(&lfs, "hello", 'A', "aaaa", 4) => 0;
|
||||||
{'A', "aaaa", 4},
|
lfs_setattr(&lfs, "hello", 'B', "bbbbbb", 6) => 0;
|
||||||
{'B', "bbbbbb", 6},
|
lfs_setattr(&lfs, "hello", 'C', "ccccc", 5) => 0;
|
||||||
{'C', "ccccc", 5}}, 3) => 0;
|
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
||||||
lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
|
||||||
{'A', buffer, 4},
|
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 0;
|
|
||||||
memcmp(buffer, "aaaa", 4) => 0;
|
memcmp(buffer, "aaaa", 4) => 0;
|
||||||
memcmp(buffer+4, "bbbbbb", 6) => 0;
|
memcmp(buffer+4, "bbbbbb", 6) => 0;
|
||||||
memcmp(buffer+10, "ccccc", 5) => 0;
|
memcmp(buffer+10, "ccccc", 5) => 0;
|
||||||
|
|
||||||
lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_setattr(&lfs, "hello", 'B', "", 0) => 0;
|
||||||
{'B', "", 0}}, 1) => 0;
|
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
||||||
lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 0;
|
||||||
{'A', buffer, 4},
|
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 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;
|
||||||
|
|
||||||
lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_setattr(&lfs, "hello", 'B', "dddddd", 6) => 0;
|
||||||
{'B', "dddddd", 6}}, 1) => 0;
|
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
||||||
lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
|
||||||
{'A', buffer, 4},
|
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 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;
|
||||||
|
|
||||||
lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_setattr(&lfs, "hello", 'B', "eee", 3) => 0;
|
||||||
{'B', "eee", 3}}, 1) => 0;
|
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
||||||
lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 3;
|
||||||
{'A', buffer, 4},
|
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 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;
|
||||||
|
|
||||||
lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_setattr(&lfs, "hello", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC;
|
||||||
{'A', buffer, LFS_ATTRS_MAX+1}}, 1) => LFS_ERR_NOSPC;
|
lfs_setattr(&lfs, "hello", 'B', "fffffffff", 9) => 0;
|
||||||
lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
||||||
{'B', "fffffffff", 9}}, 1) => 0;
|
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 9;
|
||||||
lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
||||||
{'A', buffer, 4},
|
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => LFS_ERR_RANGE;
|
|
||||||
|
|
||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
TEST
|
TEST
|
||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
||||||
{'A', buffer, 4},
|
lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9;
|
||||||
{'B', buffer+4, 9},
|
lfs_getattr(&lfs, "hello", 'C', buffer+13, 5) => 5;
|
||||||
{'C', buffer+13, 5}}, 3) => 0;
|
|
||||||
memcmp(buffer, "aaaa", 4) => 0;
|
memcmp(buffer, "aaaa", 4) => 0;
|
||||||
memcmp(buffer+4, "fffffffff", 9) => 0;
|
memcmp(buffer+4, "fffffffff", 9) => 0;
|
||||||
memcmp(buffer+13, "ccccc", 5) => 0;
|
memcmp(buffer+13, "ccccc", 5) => 0;
|
||||||
@@ -92,64 +80,52 @@ TEST
|
|||||||
echo "--- Set/get fs attribute ---"
|
echo "--- Set/get fs attribute ---"
|
||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_setattr(&lfs, 'A', "aaaa", 4) => 0;
|
||||||
{'A', "aaaa", 4},
|
lfs_fs_setattr(&lfs, 'B', "bbbbbb", 6) => 0;
|
||||||
{'B', "bbbbbb", 6},
|
lfs_fs_setattr(&lfs, 'C', "ccccc", 5) => 0;
|
||||||
{'C', "ccccc", 5}}, 3) => 0;
|
lfs_fs_getattr(&lfs, 'A', buffer, 4) => 4;
|
||||||
lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'B', buffer+4, 6) => 6;
|
||||||
{'A', buffer, 4},
|
lfs_fs_getattr(&lfs, 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 0;
|
|
||||||
memcmp(buffer, "aaaa", 4) => 0;
|
memcmp(buffer, "aaaa", 4) => 0;
|
||||||
memcmp(buffer+4, "bbbbbb", 6) => 0;
|
memcmp(buffer+4, "bbbbbb", 6) => 0;
|
||||||
memcmp(buffer+10, "ccccc", 5) => 0;
|
memcmp(buffer+10, "ccccc", 5) => 0;
|
||||||
|
|
||||||
lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_setattr(&lfs, 'B', "", 0) => 0;
|
||||||
{'B', "", 0}}, 1) => 0;
|
lfs_fs_getattr(&lfs, 'A', buffer, 4) => 4;
|
||||||
lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'B', buffer+4, 6) => 0;
|
||||||
{'A', buffer, 4},
|
lfs_fs_getattr(&lfs, 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 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;
|
||||||
|
|
||||||
lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_setattr(&lfs, 'B', "dddddd", 6) => 0;
|
||||||
{'B', "dddddd", 6}}, 1) => 0;
|
lfs_fs_getattr(&lfs, 'A', buffer, 4) => 4;
|
||||||
lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'B', buffer+4, 6) => 6;
|
||||||
{'A', buffer, 4},
|
lfs_fs_getattr(&lfs, 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 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;
|
||||||
|
|
||||||
lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_setattr(&lfs, 'B', "eee", 3) => 0;
|
||||||
{'B', "eee", 3}}, 1) => 0;
|
lfs_fs_getattr(&lfs, 'A', buffer, 4) => 4;
|
||||||
lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'B', buffer+4, 6) => 3;
|
||||||
{'A', buffer, 4},
|
lfs_fs_getattr(&lfs, 'C', buffer+10, 5) => 5;
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => 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;
|
||||||
|
|
||||||
lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_setattr(&lfs, 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC;
|
||||||
{'A', buffer, LFS_ATTRS_MAX+1}}, 1) => LFS_ERR_NOSPC;
|
lfs_fs_setattr(&lfs, 'B', "fffffffff", 9) => 0;
|
||||||
lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'A', buffer, 4) => 4;
|
||||||
{'B', "fffffffff", 9}}, 1) => 0;
|
lfs_fs_getattr(&lfs, 'B', buffer+4, 6) => 9;
|
||||||
lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'C', buffer+10, 5) => 5;
|
||||||
{'A', buffer, 4},
|
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => LFS_ERR_RANGE;
|
|
||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
TEST
|
TEST
|
||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
|
lfs_fs_getattr(&lfs, 'A', buffer, 4) => 4;
|
||||||
{'A', buffer, 4},
|
lfs_fs_getattr(&lfs, 'B', buffer+4, 9) => 9;
|
||||||
{'B', buffer+4, 9},
|
lfs_fs_getattr(&lfs, 'C', buffer+13, 5) => 5;
|
||||||
{'C', buffer+13, 5}}, 3) => 0;
|
|
||||||
memcmp(buffer, "aaaa", 4) => 0;
|
memcmp(buffer, "aaaa", 4) => 0;
|
||||||
memcmp(buffer+4, "fffffffff", 9) => 0;
|
memcmp(buffer+4, "fffffffff", 9) => 0;
|
||||||
memcmp(buffer+13, "ccccc", 5) => 0;
|
memcmp(buffer+13, "ccccc", 5) => 0;
|
||||||
@@ -164,78 +140,90 @@ 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;
|
||||||
lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_WRONLY) => 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 attr[3];
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
||||||
attr[0] = (struct lfs_attr){'A', "aaaa", 4};
|
memcpy(buffer, "aaaa", 4);
|
||||||
attr[1] = (struct lfs_attr){'B', "bbbbbb", 6};
|
memcpy(buffer+4, "bbbbbb", 6);
|
||||||
attr[2] = (struct lfs_attr){'C', "ccccc", 5};
|
memcpy(buffer+10, "ccccc", 5);
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 3) => 0;
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
memset(buffer, 0, 15);
|
||||||
{'A', buffer, 4},
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
||||||
{'B', buffer+4, 6},
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
{'C', buffer+10, 5}}, 3) => 0;
|
|
||||||
memcmp(buffer, "aaaa", 4) => 0;
|
memcmp(buffer, "aaaa", 4) => 0;
|
||||||
memcmp(buffer+4, "bbbbbb", 6) => 0;
|
memcmp(buffer+4, "bbbbbb", 6) => 0;
|
||||||
memcmp(buffer+10, "ccccc", 5) => 0;
|
memcmp(buffer+10, "ccccc", 5) => 0;
|
||||||
lfs_file_sync(&lfs, &file[0]) => 0;
|
|
||||||
|
|
||||||
attr[0] = (struct lfs_attr){'B', "", 0};
|
cfg1.attrs->next->size = 0;
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 1) => 0;
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
{'A', buffer, 4},
|
memset(buffer, 0, 15);
|
||||||
{'B', buffer+4, 6},
|
cfg1.attrs->next->size = 6;
|
||||||
{'C', buffer+10, 5}}, 3) => 0;
|
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, "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;
|
||||||
lfs_file_sync(&lfs, &file[0]) => 0;
|
|
||||||
|
|
||||||
attr[0] = (struct lfs_attr){'B', "dddddd", 6};
|
cfg1.attrs->next->size = 6;
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 1) => 0;
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
memcpy(buffer+4, "dddddd", 6);
|
||||||
{'A', buffer, 4},
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
{'B', buffer+4, 6},
|
memset(buffer, 0, 15);
|
||||||
{'C', buffer+10, 5}}, 3) => 0;
|
cfg1.attrs->next->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, "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;
|
||||||
lfs_file_sync(&lfs, &file[0]) => 0;
|
|
||||||
|
|
||||||
attr[0] = (struct lfs_attr){'B', "eee", 3};
|
cfg1.attrs->next->size = 3;
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 1);
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
memcpy(buffer+4, "eee", 3);
|
||||||
{'A', buffer, 4},
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
{'B', buffer+4, 6},
|
memset(buffer, 0, 15);
|
||||||
{'C', buffer+10, 5}}, 3) => 0;
|
cfg1.attrs->next->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, "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;
|
||||||
lfs_file_sync(&lfs, &file[0]) => 0;
|
|
||||||
|
|
||||||
attr[0] = (struct lfs_attr){'A', buffer, LFS_ATTRS_MAX+1};
|
cfg1.attrs->size = LFS_ATTR_MAX+1;
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 1) => LFS_ERR_NOSPC;
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1)
|
||||||
attr[0] = (struct lfs_attr){'B', "fffffffff", 9};
|
=> LFS_ERR_NOSPC;
|
||||||
lfs_file_open(&lfs, &file[1], "hello/hello", LFS_O_RDONLY) => 0;
|
|
||||||
lfs_file_setattrs(&lfs, &file[1], attr, 1) => LFS_ERR_BADF;
|
|
||||||
lfs_file_close(&lfs, &file[1]) => 0;
|
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 1) => 0;
|
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
|
||||||
{'A', buffer, 4},
|
|
||||||
{'B', buffer+4, 6},
|
|
||||||
{'C', buffer+10, 5}}, 3) => LFS_ERR_RANGE;
|
|
||||||
|
|
||||||
|
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}}}
|
||||||
|
};
|
||||||
|
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;
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
cfg1.attrs->size = 4;
|
||||||
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
|
||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
TEST
|
TEST
|
||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDONLY) => 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}}}
|
||||||
|
};
|
||||||
|
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_RDONLY, &cfg2) => 0;
|
||||||
{'A', buffer, 4},
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
{'B', buffer+4, 9},
|
|
||||||
{'C', buffer+13, 5}}, 3) => 0;
|
|
||||||
memcmp(buffer, "aaaa", 4) => 0;
|
memcmp(buffer, "aaaa", 4) => 0;
|
||||||
memcmp(buffer+4, "fffffffff", 9) => 0;
|
memcmp(buffer+4, "fffffffff", 9) => 0;
|
||||||
memcmp(buffer+13, "ccccc", 5) => 0;
|
memcmp(buffer+13, "ccccc", 5) => 0;
|
||||||
@@ -250,36 +238,26 @@ 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;
|
||||||
lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDWR) => 0;
|
struct lfs_file_config cfg1 = {
|
||||||
|
.attrs =
|
||||||
struct lfs_attr attr[] = {
|
&(struct lfs_attr){'B', "gggg", 4,
|
||||||
{'B', "gggg", 4},
|
&(struct lfs_attr){'C', "", 0,
|
||||||
{'C', "", 0},
|
&(struct lfs_attr){'D', "hhhh", 4}}}
|
||||||
{'D', "hhhh", 4},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lfs_file_setattrs(&lfs, &file[0], attr, 3) => 0;
|
lfs_file_opencfg(&lfs, &file[0], "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
||||||
lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
|
|
||||||
{'B', buffer, 9},
|
|
||||||
{'C', buffer+9, 9},
|
|
||||||
{'D', buffer+18, 9}}, 3) => 0;
|
|
||||||
memcmp(buffer, "gggg\0\0\0\0\0", 9) => 0;
|
|
||||||
memcmp(buffer+9, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
|
||||||
memcmp(buffer+18, "hhhh\0\0\0\0\0", 9) => 0;
|
|
||||||
|
|
||||||
lfs_getattrs(&lfs, "hello/hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9;
|
||||||
{'B', buffer, 9},
|
lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5;
|
||||||
{'C', buffer+9, 9},
|
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR;
|
||||||
{'D', buffer+18, 9}}, 3) => 0;
|
|
||||||
memcmp(buffer, "fffffffff", 9) => 0;
|
memcmp(buffer, "fffffffff", 9) => 0;
|
||||||
memcmp(buffer+9, "ccccc\0\0\0\0", 9) => 0;
|
memcmp(buffer+9, "ccccc\0\0\0\0", 9) => 0;
|
||||||
memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
||||||
|
|
||||||
lfs_file_sync(&lfs, &file[0]) => 0;
|
lfs_file_sync(&lfs, &file[0]) => 0;
|
||||||
lfs_getattrs(&lfs, "hello/hello", (struct lfs_attr[]){
|
lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 4;
|
||||||
{'B', buffer, 9},
|
lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 0;
|
||||||
{'C', buffer+9, 9},
|
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 4;
|
||||||
{'D', buffer+18, 9}}, 3) => 0;
|
|
||||||
memcmp(buffer, "gggg\0\0\0\0\0", 9) => 0;
|
memcmp(buffer, "gggg\0\0\0\0\0", 9) => 0;
|
||||||
memcmp(buffer+9, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
memcmp(buffer+9, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
||||||
memcmp(buffer+18, "hhhh\0\0\0\0\0", 9) => 0;
|
memcmp(buffer+18, "hhhh\0\0\0\0\0", 9) => 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user