mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Updated custom attribute documentation and tweaked nonexistant attributes
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.
This commit is contained in:
		
							
								
								
									
										12
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -2651,14 +2651,11 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | |||||||
|     res = lfs_dir_get(lfs, &cwd, 0x7ffff000, |     res = lfs_dir_get(lfs, &cwd, 0x7ffff000, | ||||||
|             LFS_MKTAG(0x100 | type, lfs_tagid(res), |             LFS_MKTAG(0x100 | type, lfs_tagid(res), | ||||||
|                 lfs_min(size, lfs->attr_size)), buffer); |                 lfs_min(size, lfs->attr_size)), buffer); | ||||||
|     if (res < 0) { |     if (res < 0 && res != LFS_ERR_NOENT) { | ||||||
|         if (res == LFS_ERR_NOENT) { |  | ||||||
|             return LFS_ERR_NOATTR; |  | ||||||
|         } |  | ||||||
|         return res; |         return res; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return lfs_tagsize(res); |     return (res == LFS_ERR_NOENT) ? 0 : lfs_tagsize(res); | ||||||
| } | } | ||||||
|  |  | ||||||
| int lfs_setattr(lfs_t *lfs, const char *path, | 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_MKTAG(0x100 | type, 0, | ||||||
|                 lfs_min(size, lfs->attr_size)), buffer); |                 lfs_min(size, lfs->attr_size)), buffer); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
|         if (res == LFS_ERR_NOENT) { |  | ||||||
|             return LFS_ERR_NOATTR; |  | ||||||
|         } |  | ||||||
|         return res; |         return res; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return lfs_tagsize(res); |     return (res == LFS_ERR_NOENT) ? 0 : lfs_tagsize(res); | ||||||
| } | } | ||||||
|  |  | ||||||
| int lfs_fs_setattr(lfs_t *lfs, | int lfs_fs_setattr(lfs_t *lfs, | ||||||
|   | |||||||
							
								
								
									
										95
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -89,7 +89,6 @@ 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_NOATTR      = -61,  // No data/attr available |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // File types | // File types | ||||||
| @@ -248,7 +247,7 @@ struct lfs_info { | |||||||
|  |  | ||||||
| // Custom attribute structure | // Custom attribute structure | ||||||
| struct lfs_attr { | 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 |     // identify the attribute | ||||||
|     uint8_t type; |     uint8_t type; | ||||||
|  |  | ||||||
| @@ -268,8 +267,17 @@ struct lfs_file_config { | |||||||
|     // If NULL, malloc will be used by default. |     // If NULL, malloc will be used by default. | ||||||
|     void *buffer; |     void *buffer; | ||||||
|  |  | ||||||
|     // Optional, linked list of custom attributes. |     // Optional, linked list of custom attributes related to the file. If the | ||||||
|     // TODO document more |     // 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; |     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. | // 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 custom attributes | // Get a custom attribute | ||||||
| // | // | ||||||
| // Attributes are looked up based on the type id. If the stored attribute is | // Custom attributes are uniquely identified by an 8-bit type and limited | ||||||
| // smaller than the buffer, it is padded with zeros. It the stored attribute | // to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than | ||||||
| // is larger than the buffer, LFS_ERR_RANGE is returned. | // the buffer, it will be padded with zeros. If the stored attribute is larger, | ||||||
|  | // then it will be silently truncated. | ||||||
| // | // | ||||||
| // TODO doc | // Returns the size of the attribute, or a negative error code on failure. | ||||||
| // Returns 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, | lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, void *buffer, lfs_size_t size); |         uint8_t type, void *buffer, lfs_size_t size); | ||||||
|  |  | ||||||
| // Set custom attributes | // Set custom attributes | ||||||
| // | // | ||||||
| // The array of attributes will be used to update the attributes stored on | // Custom attributes are uniquely identified by an 8-bit type and limited | ||||||
| // disk based on their type id. Unspecified attributes are left unmodified. | // to LFS_ATTR_MAX bytes. If an attribute is not found, it will be | ||||||
| // Specifying an attribute with zero size deletes the attribute. | // implicitly created, and setting the size of an attribute to zero deletes | ||||||
|  | // the attribute. | ||||||
| // | // | ||||||
| // TODO doc |  | ||||||
| // 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_setattr(lfs_t *lfs, const char *path, | ||||||
|         uint8_t type, const void *buffer, lfs_size_t size); |         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); | int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir); | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Filesystem filesystem operations /// TODO choose one | /// Filesystem-level filesystem operations | ||||||
| /// 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); |  | ||||||
|  |  | ||||||
| // Finds the current size of the filesystem | // 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. | // Returns a negative error code on failure. | ||||||
| int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); | 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 | #endif | ||||||
|   | |||||||
| @@ -241,7 +241,7 @@ tests/test.py << TEST | |||||||
|  |  | ||||||
|     lfs_getattr(&lfs, "hello/hello", 'B', buffer,    9) => 9; |     lfs_getattr(&lfs, "hello/hello", 'B', buffer,    9) => 9; | ||||||
|     lfs_getattr(&lfs, "hello/hello", 'C', buffer+9,  9) => 5; |     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,    "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; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user