Skip to content

Commit

Permalink
Updated custom attribute documentation and tweaked nonexistant attrib…
Browse files Browse the repository at this point in the history
…utes

Because of limitations in how littlefs manages attributes on disk,
littlefs views zero-length attributes and missing attributes as the same
thing. The simpliest implementation of attributes mirrors this behaviour
transparently for the user.
  • Loading branch information
geky committed Oct 16, 2018
1 parent f369f80 commit a88230a
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 50 deletions.
12 changes: 3 additions & 9 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2651,14 +2651,11 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
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;
}
if (res < 0 && res != LFS_ERR_NOENT) {
return res;
}

return lfs_tagsize(res);
return (res == LFS_ERR_NOENT) ? 0 : lfs_tagsize(res);
}

int lfs_setattr(lfs_t *lfs, const char *path,
Expand Down Expand Up @@ -3270,13 +3267,10 @@ lfs_ssize_t lfs_fs_getattr(lfs_t *lfs,
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);
return (res == LFS_ERR_NOENT) ? 0 : lfs_tagsize(res);
}

int lfs_fs_setattr(lfs_t *lfs,
Expand Down
95 changes: 55 additions & 40 deletions lfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ enum lfs_error {
LFS_ERR_NOSPC = -28, // No space left on device
LFS_ERR_NOMEM = -12, // No more memory available
LFS_ERR_NAMETOOLONG = -36, // File name too long
LFS_ERR_NOATTR = -61, // No data/attr available
};

// File types
Expand Down Expand Up @@ -248,7 +247,7 @@ struct lfs_info {

// Custom attribute structure
struct lfs_attr {
// 8-bit Type of attribute, provided by user and used to
// 8-bit type of attribute, provided by user and used to
// identify the attribute
uint8_t type;

Expand All @@ -268,8 +267,17 @@ struct lfs_file_config {
// If NULL, malloc will be used by default.
void *buffer;

// Optional, linked list of custom attributes.
// TODO document more
// Optional, linked list of custom attributes related to the file. If the
// file is opened with read access, the attributes will be read from
// during the open call. If the file is opened with write access, the
// attributes will be written to disk every file sync or close. This
// write occurs atomically with update to the file's contents.
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller
// than the buffer, it will be padded with zeros. If the stored attribute
// is larger, then it will be silently truncated. If the attribute is not
// found, it will be created implicitly.
struct lfs_attr *attrs;
};

Expand Down Expand Up @@ -436,24 +444,27 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
// Returns a negative error code on failure.
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);

// Get custom attributes
// Get a custom attribute
//
// 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.
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
// the buffer, it will be padded with zeros. If the stored attribute is larger,
// then it will be silently truncated.
//
// TODO doc
// Returns a negative error code on failure.
// Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective
// of the size of the buffer. This can be used to dynamically allocate a buffer
// or check for existance.
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size);

// 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.
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
// implicitly created, and setting the size of an attribute to zero deletes
// the attribute.
//
// TODO doc
// Returns a negative error code on failure.
int lfs_setattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size);
Expand Down Expand Up @@ -593,32 +604,7 @@ lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);


/// Filesystem filesystem operations /// TODO choose one
/// Miscellaneous littlefs specific operations /// TODO choose one

// 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.
//
// TODO doc
// Returns a negative error code on failure.
lfs_ssize_t lfs_fs_getattr(lfs_t *lfs,
uint8_t type, void *buffer, lfs_size_t size);

// 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
//
// TODO doc
// Returns a negative error code on failure.
int lfs_fs_setattr(lfs_t *lfs,
uint8_t type, const void *buffer, lfs_size_t size);
/// Filesystem-level filesystem operations

// Finds the current size of the filesystem
//
Expand All @@ -637,5 +623,34 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);

// Get custom attributes on the filesystem
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
// the buffer, it will be padded with zeros. If the stored attribute is larger,
// then it will be silently truncated.
//
// Note, filesystem-level attributes are not available for wear-leveling
//
// Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective
// of the size of the buffer. This can be used to dynamically allocate a buffer
// or check for existance.
lfs_ssize_t lfs_fs_getattr(lfs_t *lfs,
uint8_t type, void *buffer, lfs_size_t size);

// Set custom attributes on the filesystem
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
// implicitly created, and setting the size of an attribute to zero deletes
// the attribute.
//
// Note, filesystem-level attributes are not available for wear-leveling
//
// Returns a negative error code on failure.
int lfs_fs_setattr(lfs_t *lfs,
uint8_t type, const void *buffer, lfs_size_t size);


#endif
2 changes: 1 addition & 1 deletion tests/test_attrs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ tests/test.py << TEST
lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9;
lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5;
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR;
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 0;
memcmp(buffer, "fffffffff", 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;
Expand Down

0 comments on commit a88230a

Please sign in to comment.