diff --git a/lfs.c b/lfs.c index 46c769a..0cb5788 100644 --- a/lfs.c +++ b/lfs.c @@ -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, @@ -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, diff --git a/lfs.h b/lfs.h index 088b27f..d63ea78 100644 --- a/lfs.h +++ b/lfs.h @@ -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 @@ -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; @@ -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; }; @@ -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); @@ -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 // @@ -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 diff --git a/tests/test_attrs.sh b/tests/test_attrs.sh index 2fde13e..cb4f4dc 100755 --- a/tests/test_attrs.sh +++ b/tests/test_attrs.sh @@ -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;