mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Added disk-backed limits on the name/attrs/inline sizes
Being a portable, microcontroller-scale embedded filesystem, littlefs is presented with a relatively unique challenge. The amount of RAM available is on completely different scales from machine to machine, and what is normally a reasonable RAM assumption may break completely on an embedded system. A great example of this is file names. On almost every PC these days, the limit for a file name is 255 bytes. It's a very convenient limit for a number of reasons. However, on microcontrollers, allocating 255 bytes of RAM to do a file search can be unreasonable. The simplest solution (and one that has existing in littlefs for a while), is to let this limit be redefined to a smaller value on devices that need to save RAM. However, this presents an interesting portability issue. If these devices are plugged into a PC with relatively infinite RAM, nothing stops the PC from writing files with full 255-byte file names, which can't be read on the small device. One solution here is to store this limit on the superblock during format time. When mounting a disk, the filesystem implementation is responsible for checking this limit in the superblock. If it's larger than what can be read, raise an error. If it's smaller, respect the limit on the superblock and raise an error if the user attempts to exceed it. In this commit, this strategy is adopted for file names, inline files, and the size of all attributes, since these could impact the memory consumption of the filesystem. (Recording the attribute's limit is iffy, but is the only other arbitrary limit and could be used for disabling support of custom attributes). Note! This changes makes it very important to configure littlefs correctly at format time. If littlefs is formatted on a PC without changing the limits appropriately, it will be rejected by a smaller device.
This commit is contained in:
		
							
								
								
									
										132
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -365,6 +365,9 @@ static void lfs_superblock_fromle32(struct lfs_disk_superblock *d) { | |||||||
|     d->block_size  = lfs_fromle32(d->block_size); |     d->block_size  = lfs_fromle32(d->block_size); | ||||||
|     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->attrs_size  = lfs_fromle32(d->attrs_size); | ||||||
|  |     d->name_size   = lfs_fromle32(d->name_size); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { | static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { | ||||||
| @@ -373,6 +376,9 @@ static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { | |||||||
|     d->block_size  = lfs_tole32(d->block_size); |     d->block_size  = lfs_tole32(d->block_size); | ||||||
|     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->attrs_size  = lfs_tole32(d->attrs_size); | ||||||
|  |     d->name_size   = lfs_tole32(d->name_size); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1018,6 +1024,12 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|         return err ? err : LFS_ERR_EXIST; |         return err ? err : LFS_ERR_EXIST; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // check that name fits | ||||||
|  |     lfs_size_t nlen = strlen(path); | ||||||
|  |     if (nlen > lfs->name_size) { | ||||||
|  |         return LFS_ERR_NAMETOOLONG; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // build up new directory |     // build up new directory | ||||||
|     lfs_alloc_ack(lfs); |     lfs_alloc_ack(lfs); | ||||||
|  |  | ||||||
| @@ -1037,7 +1049,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     entry.d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR; |     entry.d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR; | ||||||
|     entry.d.elen = sizeof(entry.d) - 4; |     entry.d.elen = sizeof(entry.d) - 4; | ||||||
|     entry.d.alen = 0; |     entry.d.alen = 0; | ||||||
|     entry.d.nlen = strlen(path); |     entry.d.nlen = nlen; | ||||||
|     entry.d.u.dir[0] = dir.pair[0]; |     entry.d.u.dir[0] = dir.pair[0]; | ||||||
|     entry.d.u.dir[1] = dir.pair[1]; |     entry.d.u.dir[1] = dir.pair[1]; | ||||||
|     entry.size = 0; |     entry.size = 0; | ||||||
| @@ -1046,7 +1058,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     cwd.d.tail[1] = dir.pair[1]; |     cwd.d.tail[1] = dir.pair[1]; | ||||||
|     err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ |     err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|             {LFS_FROM_MEM, 0, &entry.d, sizeof(entry.d)}, |             {LFS_FROM_MEM, 0, &entry.d, sizeof(entry.d)}, | ||||||
|             {LFS_FROM_MEM, 0, path, entry.d.nlen}}, 2); |             {LFS_FROM_MEM, 0, path, nlen}}, 2); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1427,16 +1439,22 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|             return LFS_ERR_NOENT; |             return LFS_ERR_NOENT; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // check that name fits | ||||||
|  |         lfs_size_t nlen = strlen(path); | ||||||
|  |         if (nlen > lfs->name_size) { | ||||||
|  |             return LFS_ERR_NAMETOOLONG; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // create entry to remember name |         // create entry to remember name | ||||||
|         entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; |         entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; | ||||||
|         entry.d.elen = 0; |         entry.d.elen = 0; | ||||||
|         entry.d.alen = 0; |         entry.d.alen = 0; | ||||||
|         entry.d.nlen = strlen(path); |         entry.d.nlen = nlen; | ||||||
|         entry.size = 0; |         entry.size = 0; | ||||||
|  |  | ||||||
|         err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ |         err = lfs_dir_set(lfs, &cwd, &entry, (struct lfs_region[]){ | ||||||
|                 {LFS_FROM_MEM, 0, &entry.d, 4}, |                 {LFS_FROM_MEM, 0, &entry.d, 4}, | ||||||
|                 {LFS_FROM_MEM, 0, path, entry.d.nlen}}, 2); |                 {LFS_FROM_MEM, 0, path, nlen}}, 2); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -1571,10 +1589,6 @@ relocate:; | |||||||
|  |  | ||||||
| static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     if (file->flags & LFS_F_READING) { |     if (file->flags & LFS_F_READING) { | ||||||
|         if (!(file->flags & LFS_F_INLINE)) { |  | ||||||
|             // just drop read cache |  | ||||||
|             file->cache.block = 0xffffffff; |  | ||||||
|         } |  | ||||||
|         file->flags &= ~LFS_F_READING; |         file->flags &= ~LFS_F_READING; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1807,9 +1821,8 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|     // TODO need to move out if no longer fits in block also |     // TODO need to move out if no longer fits in block also | ||||||
|     // TODO store INLINE_MAX in superblock? |     // TODO store INLINE_MAX in superblock? | ||||||
|     // TODO what if inline files is > block size (ie 128) |     // TODO what if inline files is > block size (ie 128) | ||||||
|     if ((file->flags & LFS_F_INLINE) && ( |     if ((file->flags & LFS_F_INLINE) && | ||||||
|          (file->pos + nsize >= LFS_INLINE_MAX) || |             file->pos + nsize >= lfs->inline_size) { | ||||||
|          (file->pos + nsize >= lfs->cfg->read_size))) { |  | ||||||
|         file->block = 0xfffffffe; |         file->block = 0xfffffffe; | ||||||
|         file->off = file->pos; |         file->off = file->pos; | ||||||
|  |  | ||||||
| @@ -2137,6 +2150,12 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|     bool prevexists = (err != LFS_ERR_NOENT); |     bool prevexists = (err != LFS_ERR_NOENT); | ||||||
|     bool samepair = (lfs_paircmp(oldcwd.pair, newcwd.pair) == 0); |     bool samepair = (lfs_paircmp(oldcwd.pair, newcwd.pair) == 0); | ||||||
|  |  | ||||||
|  |     // check that name fits | ||||||
|  |     lfs_size_t nlen = strlen(newpath); | ||||||
|  |     if (nlen > lfs->name_size) { | ||||||
|  |         return LFS_ERR_NAMETOOLONG; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // must have same type |     // must have same type | ||||||
|     if (prevexists && preventry.d.type != oldentry.d.type) { |     if (prevexists && preventry.d.type != oldentry.d.type) { | ||||||
|         return LFS_ERR_ISDIR; |         return LFS_ERR_ISDIR; | ||||||
| @@ -2174,7 +2193,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|     lfs_entry_t newentry = preventry; |     lfs_entry_t newentry = preventry; | ||||||
|     newentry.d = oldentry.d; |     newentry.d = oldentry.d; | ||||||
|     newentry.d.type &= ~LFS_STRUCT_MOVED; |     newentry.d.type &= ~LFS_STRUCT_MOVED; | ||||||
|     newentry.d.nlen = strlen(newpath); |     newentry.d.nlen = nlen; | ||||||
|     if (!prevexists) { |     if (!prevexists) { | ||||||
|         newentry.size = 0; |         newentry.size = 0; | ||||||
|     } |     } | ||||||
| @@ -2185,8 +2204,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|                 oldcwd.pair[0], oldentry.off, (struct lfs_region[]){ |                 oldcwd.pair[0], oldentry.off, (struct lfs_region[]){ | ||||||
|                     {LFS_FROM_MEM, 0, &newentry.d, 4}, |                     {LFS_FROM_MEM, 0, &newentry.d, 4}, | ||||||
|                     {LFS_FROM_DROP, 0, NULL, -4}, |                     {LFS_FROM_DROP, 0, NULL, -4}, | ||||||
|                     {LFS_FROM_MEM, newsize - newentry.d.nlen, |                     {LFS_FROM_MEM, newsize - nlen, newpath, nlen}}, 3}, | ||||||
|                         newpath, newentry.d.nlen}}, 3}, |  | ||||||
|                 newsize}, |                 newsize}, | ||||||
|             {LFS_FROM_DROP, 0, NULL, -preventry.size}}, prevexists ? 2 : 1); |             {LFS_FROM_DROP, 0, NULL, -preventry.size}}, prevexists ? 2 : 1); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -2272,6 +2290,26 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) |     LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) | ||||||
|             <= lfs->cfg->block_size); |             <= lfs->cfg->block_size); | ||||||
|  |  | ||||||
|  |     // check that the size limits are sane | ||||||
|  |     LFS_ASSERT(lfs->cfg->inline_size <= LFS_INLINE_MAX); | ||||||
|  |     LFS_ASSERT(lfs->cfg->inline_size <= lfs->cfg->read_size); | ||||||
|  |     lfs->inline_size = lfs->cfg->inline_size; | ||||||
|  |     if (!lfs->inline_size) { | ||||||
|  |         lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->read_size); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     LFS_ASSERT(lfs->cfg->attrs_size <= LFS_ATTRS_MAX); | ||||||
|  |     lfs->attrs_size = lfs->cfg->attrs_size; | ||||||
|  |     if (!lfs->attrs_size) { | ||||||
|  |         lfs->attrs_size = LFS_ATTRS_MAX; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     LFS_ASSERT(lfs->cfg->name_size <= LFS_NAME_MAX); | ||||||
|  |     lfs->name_size = lfs->cfg->name_size; | ||||||
|  |     if (!lfs->name_size) { | ||||||
|  |         lfs->name_size = LFS_NAME_MAX; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // setup default state |     // setup default state | ||||||
|     lfs->root[0] = 0xffffffff; |     lfs->root[0] = 0xffffffff; | ||||||
|     lfs->root[1] = 0xffffffff; |     lfs->root[1] = 0xffffffff; | ||||||
| @@ -2336,13 +2374,16 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     superdir.d.tail[0] = lfs->root[0]; |     superdir.d.tail[0] = lfs->root[0]; | ||||||
|     superdir.d.tail[1] = lfs->root[1]; |     superdir.d.tail[1] = lfs->root[1]; | ||||||
|  |  | ||||||
|     // write one superblocks |     // write one superblock | ||||||
|     lfs_superblock_t superblock; |     lfs_superblock_t superblock; | ||||||
|     superblock.d.version = LFS_DISK_VERSION, |     superblock.d.version = LFS_DISK_VERSION, | ||||||
|     superblock.d.root[0] = lfs->root[0]; |     superblock.d.root[0] = lfs->root[0]; | ||||||
|     superblock.d.root[1] = lfs->root[1]; |     superblock.d.root[1] = lfs->root[1]; | ||||||
|     superblock.d.block_size  = lfs->cfg->block_size; |     superblock.d.block_size  = lfs->cfg->block_size; | ||||||
|     superblock.d.block_count = lfs->cfg->block_count; |     superblock.d.block_count = lfs->cfg->block_count; | ||||||
|  |     superblock.d.inline_size = lfs->inline_size; | ||||||
|  |     superblock.d.attrs_size  = lfs->attrs_size; | ||||||
|  |     superblock.d.name_size   = lfs->name_size; | ||||||
|  |  | ||||||
|     lfs_entry_t superentry; |     lfs_entry_t superentry; | ||||||
|     superentry.d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK; |     superentry.d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK; | ||||||
| @@ -2385,33 +2426,41 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|  |  | ||||||
|     // load superblock |     // load superblock | ||||||
|     lfs_dir_t dir; |     lfs_dir_t dir; | ||||||
|  |     lfs_entry_t entry; | ||||||
|     lfs_superblock_t superblock; |     lfs_superblock_t superblock; | ||||||
|     char magic[8]; |     char magic[8]; | ||||||
|  |  | ||||||
|     err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); |     err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); | ||||||
|     if (err && err != LFS_ERR_CORRUPT) { |     if (err) { | ||||||
|  |         if (err == LFS_ERR_CORRUPT) { | ||||||
|  |             LFS_ERROR("Invalid superblock at %d %d", 0, 1); | ||||||
|  |         } | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!err) { |     err = lfs_dir_get(lfs, &dir, sizeof(dir.d), &entry.d, sizeof(entry.d)); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     memset(&superblock.d, 0, sizeof(superblock.d)); | ||||||
|     err = lfs_dir_get(lfs, &dir, |     err = lfs_dir_get(lfs, &dir, | ||||||
|                 sizeof(dir.d)+4, &superblock.d, sizeof(superblock.d)); |             sizeof(dir.d)+4, &superblock.d, | ||||||
|  |             lfs_min(sizeof(superblock.d), entry.d.elen)); | ||||||
|     lfs_superblock_fromle32(&superblock.d); |     lfs_superblock_fromle32(&superblock.d); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_dir_get(lfs, &dir, |     err = lfs_dir_get(lfs, &dir, | ||||||
|                 sizeof(dir.d)+4 + sizeof(superblock.d), magic, sizeof(magic)); |             sizeof(dir.d)+4+entry.d.elen+entry.d.alen, magic, | ||||||
|  |             lfs_min(sizeof(magic), entry.d.nlen)); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         lfs->root[0] = superblock.d.root[0]; |     if (memcmp(magic, "littlefs", 8) != 0) { | ||||||
|         lfs->root[1] = superblock.d.root[1]; |         LFS_ERROR("Invalid superblock at %d %d", 0, 1); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (err || memcmp(magic, "littlefs", 8) != 0) { |  | ||||||
|         LFS_ERROR("Invalid superblock at %d %d", dir.pair[0], dir.pair[1]); |  | ||||||
|         return LFS_ERR_CORRUPT; |         return LFS_ERR_CORRUPT; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2423,6 +2472,39 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|         return LFS_ERR_INVAL; |         return LFS_ERR_INVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (superblock.d.inline_size) { | ||||||
|  |         if (superblock.d.inline_size > lfs->inline_size) { | ||||||
|  |             LFS_ERROR("Unsupported inline size (%d > %d)", | ||||||
|  |                     superblock.d.inline_size, lfs->inline_size); | ||||||
|  |             return LFS_ERR_INVAL; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         lfs->inline_size = superblock.d.inline_size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (superblock.d.attrs_size) { | ||||||
|  |         if (superblock.d.attrs_size > lfs->attrs_size) { | ||||||
|  |             LFS_ERROR("Unsupported attrs size (%d > %d)", | ||||||
|  |                     superblock.d.attrs_size, lfs->attrs_size); | ||||||
|  |             return LFS_ERR_INVAL; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         lfs->attrs_size = superblock.d.attrs_size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (superblock.d.name_size) { | ||||||
|  |         if (superblock.d.name_size > lfs->name_size) { | ||||||
|  |             LFS_ERROR("Unsupported name size (%d > %d)", | ||||||
|  |                     superblock.d.name_size, lfs->name_size); | ||||||
|  |             return LFS_ERR_INVAL; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         lfs->name_size = superblock.d.name_size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     lfs->root[0] = superblock.d.root[0]; | ||||||
|  |     lfs->root[1] = superblock.d.root[1]; | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -50,15 +50,21 @@ typedef int32_t  lfs_soff_t; | |||||||
|  |  | ||||||
| typedef uint32_t lfs_block_t; | typedef uint32_t lfs_block_t; | ||||||
|  |  | ||||||
|  | // Maximum inline file size in bytes | ||||||
|  | #ifndef LFS_INLINE_MAX | ||||||
|  | #define LFS_INLINE_MAX 255 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // Maximum size of all attributes per file in bytes | ||||||
|  | #ifndef LFS_ATTRS_MAX | ||||||
|  | #define LFS_ATTRS_MAX 255 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Max name size in bytes | // Max name size in bytes | ||||||
| #ifndef LFS_NAME_MAX | #ifndef LFS_NAME_MAX | ||||||
| #define LFS_NAME_MAX 255 | #define LFS_NAME_MAX 255 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef LFS_INLINE_MAX |  | ||||||
| #define LFS_INLINE_MAX 255 |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| // Possible error codes, these are negative to allow | // Possible error codes, these are negative to allow | ||||||
| // valid positive return values | // valid positive return values | ||||||
| enum lfs_error { | enum lfs_error { | ||||||
| @@ -74,6 +80,7 @@ enum lfs_error { | |||||||
|     LFS_ERR_INVAL       = -22,  // Invalid parameter |     LFS_ERR_INVAL       = -22,  // Invalid parameter | ||||||
|     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 | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // File types | // File types | ||||||
| @@ -102,10 +109,10 @@ enum lfs_open_flags { | |||||||
|     LFS_O_APPEND = 0x0800,    // Move to end of file on every write |     LFS_O_APPEND = 0x0800,    // Move to end of file on every write | ||||||
|  |  | ||||||
|     // internally used flags |     // internally used flags | ||||||
|     LFS_F_DIRTY   = 0x10000,  // File does not match storage |     LFS_F_DIRTY   = 0x010000, // File does not match storage | ||||||
|     LFS_F_WRITING = 0x20000,  // File has been written since last flush |     LFS_F_WRITING = 0x020000, // File has been written since last flush | ||||||
|     LFS_F_READING = 0x40000,  // File has been read since last flush |     LFS_F_READING = 0x040000, // File has been read since last flush | ||||||
|     LFS_F_ERRED   = 0x80000,  // An error occured during write |     LFS_F_ERRED   = 0x080000, // An error occured during write | ||||||
|     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry |     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -183,6 +190,13 @@ struct lfs_config { | |||||||
|     // Optional, statically allocated buffer for files. Must be program sized. |     // Optional, statically allocated buffer for files. Must be program sized. | ||||||
|     // If enabled, only one file may be opened at a time. |     // If enabled, only one file may be opened at a time. | ||||||
|     void *file_buffer; |     void *file_buffer; | ||||||
|  |  | ||||||
|  |     // Optional, | ||||||
|  |     lfs_size_t inline_size; | ||||||
|  |     // Optional, | ||||||
|  |     lfs_size_t attrs_size; | ||||||
|  |     // Optional, | ||||||
|  |     lfs_size_t name_size; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -258,9 +272,14 @@ typedef struct lfs_dir { | |||||||
| typedef struct lfs_superblock { | typedef struct lfs_superblock { | ||||||
|     struct lfs_disk_superblock { |     struct lfs_disk_superblock { | ||||||
|         lfs_block_t root[2]; |         lfs_block_t root[2]; | ||||||
|         uint32_t block_size; |  | ||||||
|         uint32_t block_count; |         lfs_size_t block_size; | ||||||
|  |         lfs_size_t block_count; | ||||||
|         uint32_t version; |         uint32_t version; | ||||||
|  |  | ||||||
|  |         lfs_size_t inline_size; | ||||||
|  |         lfs_size_t attrs_size; | ||||||
|  |         lfs_size_t name_size; | ||||||
|     } d; |     } d; | ||||||
| } lfs_superblock_t; | } lfs_superblock_t; | ||||||
|  |  | ||||||
| @@ -285,6 +304,10 @@ typedef struct lfs { | |||||||
|  |  | ||||||
|     lfs_free_t free; |     lfs_free_t free; | ||||||
|     bool deorphaned; |     bool deorphaned; | ||||||
|  |  | ||||||
|  |     lfs_size_t inline_size; | ||||||
|  |     lfs_size_t attrs_size; | ||||||
|  |     lfs_size_t name_size; | ||||||
| } lfs_t; | } lfs_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user