mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 08:48:31 +01:00
WIP Clumsy setattrs/getattrs
This commit is contained in:
254
lfs.c
254
lfs.c
@@ -515,6 +515,7 @@ struct lfs_region {
|
|||||||
LFS_FROM_DROP,
|
LFS_FROM_DROP,
|
||||||
LFS_FROM_MEM,
|
LFS_FROM_MEM,
|
||||||
LFS_FROM_REGION,
|
LFS_FROM_REGION,
|
||||||
|
LFS_FROM_ATTRS,
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
lfs_off_t off;
|
lfs_off_t off;
|
||||||
@@ -522,6 +523,12 @@ struct lfs_region {
|
|||||||
lfs_ssize_t size;
|
lfs_ssize_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct lfs_attrs_region {
|
||||||
|
const struct lfs_attr *attrs;
|
||||||
|
int count;
|
||||||
|
lfs_size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
struct lfs_region_region {
|
struct lfs_region_region {
|
||||||
lfs_block_t block;
|
lfs_block_t block;
|
||||||
lfs_off_t off;
|
lfs_off_t off;
|
||||||
@@ -568,6 +575,73 @@ static int lfs_commit_region(lfs_t *lfs,
|
|||||||
newoff += regions[i].size;
|
newoff += regions[i].size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LFS_FROM_ATTRS: {
|
||||||
|
const struct lfs_attrs_region *attrs = regions[i].buffer;
|
||||||
|
|
||||||
|
// order doesn't matter, so we write new attrs first. this
|
||||||
|
// is still O(n^2) but only O(n) disk access
|
||||||
|
for (int j = 0; j < attrs->count; j++) {
|
||||||
|
if (attrs->attrs[j].size == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_entry_attr_t attr = {
|
||||||
|
.d.type = attrs->attrs[j].type,
|
||||||
|
.d.len = attrs->attrs[j].size,
|
||||||
|
};
|
||||||
|
|
||||||
|
lfs_crc(crc, &attr.d, sizeof(attr.d));
|
||||||
|
int err = lfs_bd_prog(lfs, newblock, newoff,
|
||||||
|
&attr.d, sizeof(attr.d));
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_crc(crc,
|
||||||
|
attrs->attrs[j].buffer, attrs->attrs[j].size);
|
||||||
|
err = lfs_bd_prog(lfs, newblock, newoff+sizeof(attr.d),
|
||||||
|
attrs->attrs[j].buffer, attrs->attrs[j].size);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
newoff += sizeof(attr.d) + attrs->attrs[j].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy over attributes without updates
|
||||||
|
lfs_entry_attr_t attr;
|
||||||
|
for (lfs_off_t k = 0; k < attrs->len; k += 2+attr.d.len) {
|
||||||
|
int err = lfs_bd_read(lfs, oldblock, oldoff,
|
||||||
|
&attr.d, sizeof(attr.d));
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updating = false;
|
||||||
|
for (int j = 0; j < attrs->count; j++) {
|
||||||
|
if (attr.d.type == attrs->attrs[j].type) {
|
||||||
|
updating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updating) {
|
||||||
|
err = lfs_commit_region(lfs,
|
||||||
|
oldblock, oldoff,
|
||||||
|
newblock, newoff,
|
||||||
|
0, NULL, 0,
|
||||||
|
attr.d.len, crc);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
newoff += 2+attr.d.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldoff += 2+attr.d.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -590,6 +664,8 @@ static int lfs_commit_region(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanity check our commit math
|
||||||
|
LFS_ASSERT(newoff == end);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1044,116 +1120,100 @@ static int lfs_dir_getinfo(lfs_t *lfs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfs_dir_getattr(lfs_t *lfs,
|
static int lfs_dir_getattrs(lfs_t *lfs,
|
||||||
lfs_dir_t *dir, const lfs_entry_t *entry,
|
lfs_dir_t *dir, const lfs_entry_t *entry,
|
||||||
uint8_t type, void *buffer, lfs_size_t size) {
|
const struct lfs_attr *attrs, int count) {
|
||||||
|
// set to zero in case we can't find the attributes or size mismatch
|
||||||
|
for (int j = 0; j < count; j++) {
|
||||||
|
memset(attrs[j].buffer, 0, attrs[j].size);
|
||||||
|
}
|
||||||
|
|
||||||
// search for attribute in attribute region
|
// search for attribute in attribute region
|
||||||
lfs_off_t off = sizeof(dir->d) + lfs_entry_elen(entry);
|
lfs_off_t off = 4+lfs_entry_elen(entry);
|
||||||
lfs_off_t i = 0;
|
lfs_entry_attr_t attr;
|
||||||
while (i < lfs_entry_alen(entry)) {
|
for (lfs_off_t i = 0; i < lfs_entry_alen(entry); i += 2+attr.d.len) {
|
||||||
lfs_attr_t attr;
|
|
||||||
int err = lfs_dir_get(lfs, dir,
|
int err = lfs_dir_get(lfs, dir,
|
||||||
entry->off+off+i, &attr.d, sizeof(attr.d));
|
entry->off+off+i, &attr.d, sizeof(attr.d));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.d.type != type) {
|
for (int j = 0; j < count; j++) {
|
||||||
i += attr.d.len;
|
if (attr.d.type == attrs[j].type) {
|
||||||
continue;
|
if (attr.d.len > attrs[j].size) {
|
||||||
|
return LFS_ERR_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = lfs_dir_get(lfs, dir,
|
||||||
|
entry->off+off+i+sizeof(attr.d),
|
||||||
|
attrs[j].buffer, attr.d.len);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.d.len > size) {
|
|
||||||
return LFS_ERR_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = lfs_dir_get(lfs, dir,
|
|
||||||
entry->off+off+i+sizeof(attr.d), buffer, attr.d.len);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attr.d.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LFS_ERR_NODATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lfs_dir_setattr(lfs_t *lfs,
|
|
||||||
lfs_dir_t *dir, lfs_entry_t *entry,
|
|
||||||
uint8_t type, const void *buffer, lfs_size_t size) {
|
|
||||||
// search for attribute in attribute region
|
|
||||||
lfs_off_t off = sizeof(dir->d) + lfs_entry_elen(entry);
|
|
||||||
lfs_off_t i = 0;
|
|
||||||
lfs_size_t oldlen = 0;
|
|
||||||
while (i < lfs_entry_alen(entry)) {
|
|
||||||
lfs_attr_t attr;
|
|
||||||
int err = lfs_dir_get(lfs, dir,
|
|
||||||
entry->off+off+i, &attr.d, sizeof(attr.d));
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr.d.type != type) {
|
|
||||||
i += attr.d.len;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldlen = attr.d.len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the attribute fits
|
|
||||||
if (lfs_entry_elen(entry) - oldlen + size > lfs->attrs_size ||
|
|
||||||
(0x7fffffff & dir->d.size) - oldlen + size > lfs->cfg->block_size) {
|
|
||||||
return LFS_ERR_NOSPC;
|
|
||||||
}
|
|
||||||
|
|
||||||
lfs_attr_t attr;
|
|
||||||
attr.d.type = type;
|
|
||||||
attr.d.len = size;
|
|
||||||
int err = lfs_dir_set(lfs, dir, entry, (struct lfs_region[]){
|
|
||||||
{LFS_FROM_MEM, off+i, &attr.d, sizeof(attr.d)},
|
|
||||||
{LFS_FROM_MEM, off+i, buffer, size},
|
|
||||||
{LFS_FROM_DROP, off+i, NULL, -oldlen}}, 3);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfs_dir_removeattr(lfs_t *lfs,
|
static lfs_ssize_t lfs_dir_checkattrs(lfs_t *lfs,
|
||||||
lfs_dir_t *dir, lfs_entry_t *entry, uint8_t type) {
|
lfs_dir_t *dir, lfs_entry_t *entry,
|
||||||
// search for attribute in attribute region
|
const struct lfs_attr *attrs, int count) {
|
||||||
lfs_off_t off = sizeof(dir->d) + lfs_entry_elen(entry);
|
// check that attributes fit
|
||||||
lfs_off_t i = 0;
|
lfs_size_t nsize = 0;
|
||||||
while (i < lfs_entry_alen(entry)) {
|
for (int j = 0; j < count; j++) {
|
||||||
lfs_attr_t attr;
|
nsize += 2+attrs[j].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_off_t off = 4+lfs_entry_elen(entry);
|
||||||
|
lfs_entry_attr_t attr;
|
||||||
|
for (lfs_off_t i = 0; i < lfs_entry_alen(entry); i += 2+attr.d.len) {
|
||||||
int err = lfs_dir_get(lfs, dir,
|
int err = lfs_dir_get(lfs, dir,
|
||||||
entry->off+off+i, &attr.d, sizeof(attr.d));
|
entry->off+off+i, &attr.d, sizeof(attr.d));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.d.type != type) {
|
bool updated = false;
|
||||||
i += attr.d.len;
|
for (int j = 0; j < count; j++) {
|
||||||
continue;
|
if (attr.d.type == attrs[j].type) {
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lfs_dir_set(lfs, dir, entry, (struct lfs_region[]){
|
if (!updated) {
|
||||||
{LFS_FROM_DROP, off+i,
|
nsize += 2+attr.d.len;
|
||||||
NULL, -(sizeof(attr.d)+attr.d.len)}}, 1);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return LFS_ERR_NODATA;
|
if (nsize > lfs->attrs_size || (
|
||||||
|
(0x7fffffff & dir->d.size) + lfs_entry_size(entry) -
|
||||||
|
lfs_entry_alen(entry) + nsize > lfs->cfg->block_size)) {
|
||||||
|
return LFS_ERR_NOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lfs_dir_setattrs(lfs_t *lfs,
|
||||||
|
lfs_dir_t *dir, lfs_entry_t *entry,
|
||||||
|
const struct lfs_attr *attrs, int count) {
|
||||||
|
// make sure attributes fit
|
||||||
|
lfs_ssize_t nsize = lfs_dir_checkattrs(lfs, dir, entry, attrs, count);
|
||||||
|
if (nsize < 0) {
|
||||||
|
return nsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// commit to entry, majority of work is in LFS_FROM_ATTRS
|
||||||
|
lfs_size_t oldlen = lfs_entry_alen(entry);
|
||||||
|
entry->d.alen = (0xc0 & entry->d.alen) | nsize;
|
||||||
|
return lfs_dir_set(lfs, dir, entry, (struct lfs_region[]){
|
||||||
|
{LFS_FROM_MEM, 0, &entry->d, 4},
|
||||||
|
{LFS_FROM_DROP, 0, NULL, -4},
|
||||||
|
{LFS_FROM_ATTRS, 4+lfs_entry_elen(entry),
|
||||||
|
&(struct lfs_attrs_region){attrs, count, oldlen}, nsize}}, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Top level directory operations ///
|
/// Top level directory operations ///
|
||||||
@@ -2372,8 +2432,8 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
|||||||
|
|
||||||
|
|
||||||
/// Attribute operations ///
|
/// Attribute operations ///
|
||||||
int lfs_getattr(lfs_t *lfs, const char *path,
|
int lfs_getattrs(lfs_t *lfs, const char *path,
|
||||||
uint8_t type, void *buffer, lfs_size_t size) {
|
const struct lfs_attr *attrs, int count) {
|
||||||
lfs_dir_t cwd;
|
lfs_dir_t cwd;
|
||||||
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -2386,11 +2446,11 @@ int lfs_getattr(lfs_t *lfs, const char *path,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lfs_dir_getattr(lfs, &cwd, &entry, type, buffer, size);
|
return lfs_dir_getattrs(lfs, &cwd, &entry, attrs, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfs_setattr(lfs_t *lfs, const char *path,
|
int lfs_setattrs(lfs_t *lfs, const char *path,
|
||||||
uint8_t type, const void *buffer, lfs_size_t size) {
|
const struct lfs_attr *attrs, int count) {
|
||||||
lfs_dir_t cwd;
|
lfs_dir_t cwd;
|
||||||
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -2403,23 +2463,7 @@ int lfs_setattr(lfs_t *lfs, const char *path,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lfs_dir_setattr(lfs, &cwd, &entry, type, buffer, size);
|
return lfs_dir_setattrs(lfs, &cwd, &entry, attrs, count);
|
||||||
}
|
|
||||||
|
|
||||||
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
|
|
||||||
lfs_dir_t cwd;
|
|
||||||
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
lfs_entry_t entry;
|
|
||||||
err = lfs_dir_find(lfs, &cwd, &entry, &path);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lfs_dir_removeattr(lfs, &cwd, &entry, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
94
lfs.h
94
lfs.h
@@ -234,6 +234,18 @@ struct lfs_info {
|
|||||||
char name[LFS_NAME_MAX+1];
|
char name[LFS_NAME_MAX+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Custom attribute structure
|
||||||
|
struct lfs_attr {
|
||||||
|
// Type of attribute, provided by user and used to identify the attribute
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
|
// Pointer to buffer containing the attribute
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
|
// Size of attribute in bytes, limited to LFS_ATTRS_MAX
|
||||||
|
lfs_size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// littlefs data structures ///
|
/// littlefs data structures ///
|
||||||
typedef struct lfs_entry {
|
typedef struct lfs_entry {
|
||||||
@@ -255,12 +267,12 @@ typedef struct lfs_entry {
|
|||||||
} d;
|
} d;
|
||||||
} lfs_entry_t;
|
} lfs_entry_t;
|
||||||
|
|
||||||
typedef struct lfs_attr {
|
typedef struct lfs_entry_attr {
|
||||||
struct lfs_disk_attr {
|
struct lfs_disk_entry_attr {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
} d;
|
} d;
|
||||||
} lfs_attr_t;
|
} lfs_entry_attr_t;
|
||||||
|
|
||||||
typedef struct lfs_cache {
|
typedef struct lfs_cache {
|
||||||
lfs_block_t block;
|
lfs_block_t block;
|
||||||
@@ -388,28 +400,25 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
|
|||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
||||||
|
|
||||||
// Get a custom attribute
|
// Get custom attributes
|
||||||
//
|
//
|
||||||
// Attributes are identified by an 8-bit type and are limited to at
|
// Attributes are looked up based on the type id. If the stored attribute is
|
||||||
// most LFS_ATTRS_SIZE bytes.
|
// smaller than the buffer, it is padded with zeros. It the stored attribute
|
||||||
// Returns the size of the attribute, or a negative error code on failure.
|
// is larger than the buffer, LFS_ERR_RANGE is returned.
|
||||||
int lfs_getattr(lfs_t *lfs, const char *path,
|
|
||||||
uint8_t type, void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
// Set a custom attribute
|
|
||||||
//
|
//
|
||||||
// Attributes are identified by an 8-bit type and are limited to at
|
|
||||||
// most LFS_ATTRS_SIZE bytes.
|
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_setattr(lfs_t *lfs, const char *path,
|
int lfs_getattrs(lfs_t *lfs, const char *path,
|
||||||
uint8_t type, const void *buffer, lfs_size_t size);
|
const struct lfs_attr *attrs, int count);
|
||||||
|
|
||||||
// Remove a custom attribute
|
// Set custom attributes
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
//
|
//
|
||||||
// Attributes are identified by an 8-bit type and are limited to at
|
|
||||||
// most LFS_ATTRS_SIZE bytes.
|
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
|
int lfs_setattrs(lfs_t *lfs, const char *path,
|
||||||
|
const struct lfs_attr *attrs, int count);
|
||||||
|
|
||||||
|
|
||||||
/// File operations ///
|
/// File operations ///
|
||||||
@@ -484,6 +493,30 @@ 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 ///
|
||||||
|
|
||||||
@@ -532,6 +565,29 @@ lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
|
|||||||
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
||||||
|
|
||||||
|
|
||||||
|
/// Filesystem filesystem operations ///
|
||||||
|
|
||||||
|
// Get custom attributes on the filesystem
|
||||||
|
//
|
||||||
|
// 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_fs_getattrs(lfs_t *lfs, const struct lfs_attr *attrs, int count);
|
||||||
|
|
||||||
|
// Set custom attributes on the filesystem
|
||||||
|
//
|
||||||
|
// 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: Filesystem level attributes are not available for wear-leveling
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_fs_setattrs(lfs_t *lfs, const struct lfs_attr *attrs, int count);
|
||||||
|
|
||||||
|
|
||||||
/// Miscellaneous littlefs specific operations ///
|
/// Miscellaneous littlefs specific operations ///
|
||||||
|
|
||||||
// Traverse through all blocks in use by the filesystem
|
// Traverse through all blocks in use by the filesystem
|
||||||
|
|||||||
Reference in New Issue
Block a user