mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Compare commits
	
		
			6 Commits
		
	
	
		
			v2.4.2
			...
			config-imp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f9324d1443 | ||
|  | a7cdd563f6 | ||
|  | a549413077 | ||
|  | 3f6f88778a | ||
|  | c44427f9ec | ||
|  | ef9ba2d912 | 
							
								
								
									
										25
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -208,6 +208,31 @@ jobs: | ||||
|     script: | ||||
|       - make test TFLAGS+="-k --valgrind" | ||||
|  | ||||
|   # test minimal compilation using static configs | ||||
|   - stage: test | ||||
|     env: | ||||
|       - NAME=littlefs-minimal | ||||
|       - CC="arm-linux-gnueabi-gcc --static -mthumb" | ||||
|       - CFLAGS="-Werror | ||||
|             -DLFS_STATICCFG -DLFS_FILE_STATICCFG | ||||
|             -DLFS_READ_SIZE=16 | ||||
|             -DLFS_PROG_SIZE=16 | ||||
|             -DLFS_BLOCK_SIZE=512 | ||||
|             -DLFS_BLOCK_COUNT=1024 | ||||
|             -DLFS_BLOCK_CYCLES=-1 | ||||
|             -DLFS_CACHE_SIZE=64 | ||||
|             -DLFS_LOOKAHEAD_SIZE=16 | ||||
|             -DLFS_NO_ASSERT -DLFS_NO_DEBUG -DLFS_NO_WARN -DLFS_NO_ERROR" | ||||
|     if: branch !~ -prefix$ | ||||
|     install: | ||||
|       - *install-common | ||||
|       - sudo apt-get install | ||||
|             gcc-arm-linux-gnueabi | ||||
|             libc6-dev-armel-cross | ||||
|       - arm-linux-gnueabi-gcc --version | ||||
|     # report-size will compile littlefs and report the size | ||||
|     script: [*report-size] | ||||
|  | ||||
|   # self-host with littlefs-fuse for fuzz test | ||||
|   - stage: test | ||||
|     env: | ||||
|   | ||||
| @@ -39,7 +39,7 @@ lfs_t lfs; | ||||
| lfs_file_t file; | ||||
|  | ||||
| // configuration of the filesystem is provided by this struct | ||||
| const struct lfs_config cfg = { | ||||
| const struct lfs_cfg cfg = { | ||||
|     // block device operations | ||||
|     .read  = user_provided_block_device_read, | ||||
|     .prog  = user_provided_block_device_prog, | ||||
|   | ||||
							
								
								
									
										107
									
								
								bd/lfs_filebd.c
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								bd/lfs_filebd.c
									
									
									
									
									
								
							| @@ -10,21 +10,18 @@ | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path, | ||||
|         const struct lfs_filebd_config *bdcfg) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_createcfg(%p {.context=%p, " | ||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||
| int lfs_filebd_createcfg(lfs_filebd_t *bd, const char *path, | ||||
|         const struct lfs_filebd_cfg *cfg) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_createcfg(%p, \"%s\", %p {" | ||||
|                 ".read_size=%"PRIu32", .prog_size=%"PRIu32", " | ||||
|                 ".block_size=%"PRIu32", .block_count=%"PRIu32"}, " | ||||
|                 "\"%s\", " | ||||
|                 "%p {.erase_value=%"PRId32"})", | ||||
|             (void*)cfg, cfg->context, | ||||
|             (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, | ||||
|             (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, | ||||
|             cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, | ||||
|             path, (void*)bdcfg, bdcfg->erase_value); | ||||
|     lfs_filebd_t *bd = cfg->context; | ||||
|     bd->cfg = bdcfg; | ||||
|                 ".erase_size=%"PRIu32", .erase_count=%"PRIu32", " | ||||
|                 ".erase_value=%"PRId32"})", | ||||
|             (void*)bd, path, (void*)cfg, | ||||
|             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, | ||||
|             cfg->erase_value); | ||||
|  | ||||
|     // copy over config | ||||
|     bd->cfg = *cfg; | ||||
|  | ||||
|     // open file | ||||
|     bd->fd = open(path, O_RDWR | O_CREAT, 0666); | ||||
| @@ -38,26 +35,8 @@ int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_filebd_create(const struct lfs_config *cfg, const char *path) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_create(%p {.context=%p, " | ||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||
|                 ".read_size=%"PRIu32", .prog_size=%"PRIu32", " | ||||
|                 ".block_size=%"PRIu32", .block_count=%"PRIu32"}, " | ||||
|                 "\"%s\")", | ||||
|             (void*)cfg, cfg->context, | ||||
|             (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, | ||||
|             (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, | ||||
|             cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, | ||||
|             path); | ||||
|     static const struct lfs_filebd_config defaults = {.erase_value=-1}; | ||||
|     int err = lfs_filebd_createcfg(cfg, path, &defaults); | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_create -> %d", err); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| int lfs_filebd_destroy(const struct lfs_config *cfg) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_destroy(%p)", (void*)cfg); | ||||
|     lfs_filebd_t *bd = cfg->context; | ||||
| int lfs_filebd_destroy(lfs_filebd_t *bd) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_destroy(%p)", (void*)bd); | ||||
|     int err = close(bd->fd); | ||||
|     if (err < 0) { | ||||
|         err = -errno; | ||||
| @@ -68,26 +47,25 @@ int lfs_filebd_destroy(const struct lfs_config *cfg) { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_filebd_read(lfs_filebd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_read(%p, " | ||||
|                 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)cfg, block, off, buffer, size); | ||||
|     lfs_filebd_t *bd = cfg->context; | ||||
|             (void*)bd, block, off, buffer, size); | ||||
|  | ||||
|     // check if read is valid | ||||
|     LFS_ASSERT(off  % cfg->read_size == 0); | ||||
|     LFS_ASSERT(size % cfg->read_size == 0); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(off  % bd->cfg.read_size == 0); | ||||
|     LFS_ASSERT(size % bd->cfg.read_size == 0); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // zero for reproducability (in case file is truncated) | ||||
|     if (bd->cfg->erase_value != -1) { | ||||
|         memset(buffer, bd->cfg->erase_value, size); | ||||
|     if (bd->cfg.erase_value != -1) { | ||||
|         memset(buffer, bd->cfg.erase_value, size); | ||||
|     } | ||||
|  | ||||
|     // read | ||||
|     off_t res1 = lseek(bd->fd, | ||||
|             (off_t)block*cfg->block_size + (off_t)off, SEEK_SET); | ||||
|             (off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); | ||||
|     if (res1 < 0) { | ||||
|         int err = -errno; | ||||
|         LFS_FILEBD_TRACE("lfs_filebd_read -> %d", err); | ||||
| @@ -105,21 +83,21 @@ int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_prog(%p, 0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)cfg, block, off, buffer, size); | ||||
|     lfs_filebd_t *bd = cfg->context; | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_prog(%p, " | ||||
|                 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)bd, block, off, buffer, size); | ||||
|  | ||||
|     // check if write is valid | ||||
|     LFS_ASSERT(off  % cfg->prog_size == 0); | ||||
|     LFS_ASSERT(size % cfg->prog_size == 0); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(off  % bd->cfg.prog_size == 0); | ||||
|     LFS_ASSERT(size % bd->cfg.prog_size == 0); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // check that data was erased? only needed for testing | ||||
|     if (bd->cfg->erase_value != -1) { | ||||
|     if (bd->cfg.erase_value != -1) { | ||||
|         off_t res1 = lseek(bd->fd, | ||||
|                 (off_t)block*cfg->block_size + (off_t)off, SEEK_SET); | ||||
|                 (off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); | ||||
|         if (res1 < 0) { | ||||
|             int err = -errno; | ||||
|             LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); | ||||
| @@ -135,13 +113,13 @@ int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
|                 return err; | ||||
|             } | ||||
|  | ||||
|             LFS_ASSERT(c == bd->cfg->erase_value); | ||||
|             LFS_ASSERT(c == bd->cfg.erase_value); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // program data | ||||
|     off_t res1 = lseek(bd->fd, | ||||
|             (off_t)block*cfg->block_size + (off_t)off, SEEK_SET); | ||||
|             (off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); | ||||
|     if (res1 < 0) { | ||||
|         int err = -errno; | ||||
|         LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); | ||||
| @@ -159,24 +137,23 @@ int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)cfg, block); | ||||
|     lfs_filebd_t *bd = cfg->context; | ||||
| int lfs_filebd_erase(lfs_filebd_t *bd, lfs_block_t block) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)bd, block); | ||||
|  | ||||
|     // check if erase is valid | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // erase, only needed for testing | ||||
|     if (bd->cfg->erase_value != -1) { | ||||
|         off_t res1 = lseek(bd->fd, (off_t)block*cfg->block_size, SEEK_SET); | ||||
|     if (bd->cfg.erase_value != -1) { | ||||
|         off_t res1 = lseek(bd->fd, (off_t)block*bd->cfg.erase_size, SEEK_SET); | ||||
|         if (res1 < 0) { | ||||
|             int err = -errno; | ||||
|             LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         for (lfs_off_t i = 0; i < cfg->block_size; i++) { | ||||
|             ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg->erase_value}, 1); | ||||
|         for (lfs_off_t i = 0; i < bd->cfg.erase_size; i++) { | ||||
|             ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg.erase_value}, 1); | ||||
|             if (res2 < 0) { | ||||
|                 int err = -errno; | ||||
|                 LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); | ||||
| @@ -189,10 +166,10 @@ int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_filebd_sync(const struct lfs_config *cfg) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_sync(%p)", (void*)cfg); | ||||
| int lfs_filebd_sync(lfs_filebd_t *bd) { | ||||
|     LFS_FILEBD_TRACE("lfs_filebd_sync(%p)", (void*)bd); | ||||
|  | ||||
|     // file sync | ||||
|     lfs_filebd_t *bd = cfg->context; | ||||
|     int err = fsync(bd->fd); | ||||
|     if (err) { | ||||
|         err = -errno; | ||||
|   | ||||
| @@ -8,11 +8,9 @@ | ||||
| #define LFS_FILEBD_H | ||||
|  | ||||
| #include "lfs.h" | ||||
| #include "lfs_util.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @@ -24,7 +22,21 @@ extern "C" | ||||
| #endif | ||||
|  | ||||
| // filebd config (optional) | ||||
| struct lfs_filebd_config { | ||||
| struct lfs_filebd_cfg { | ||||
|     // Minimum size of block read. All read operations must be a | ||||
|     // multiple of this value. | ||||
|     lfs_size_t read_size; | ||||
|  | ||||
|     // Minimum size of block program. All program operations must be a | ||||
|     // multiple of this value. | ||||
|     lfs_size_t prog_size; | ||||
|  | ||||
|     // Size of an erasable block. | ||||
|     lfs_size_t erase_size; | ||||
|  | ||||
|     // Number of erasable blocks on the device. | ||||
|     lfs_size_t erase_count; | ||||
|  | ||||
|     // 8-bit erase value to use for simulating erases. -1 does not simulate | ||||
|     // erases, which can speed up testing by avoiding all the extra block-device | ||||
|     // operations to store the erase value. | ||||
| @@ -34,40 +46,39 @@ struct lfs_filebd_config { | ||||
| // filebd state | ||||
| typedef struct lfs_filebd { | ||||
|     int fd; | ||||
|     const struct lfs_filebd_config *cfg; | ||||
|     struct lfs_filebd_cfg cfg; | ||||
| } lfs_filebd_t; | ||||
|  | ||||
|  | ||||
| // Create a file block device using the geometry in lfs_config | ||||
| int lfs_filebd_create(const struct lfs_config *cfg, const char *path); | ||||
| int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path, | ||||
|         const struct lfs_filebd_config *bdcfg); | ||||
| // Create a file block device using the geometry in lfs_filebd_cfg | ||||
| int lfs_filebd_createcfg(lfs_filebd_t *bd, const char *path, | ||||
|         const struct lfs_filebd_cfg *cfg); | ||||
|  | ||||
| // Clean up memory associated with block device | ||||
| int lfs_filebd_destroy(const struct lfs_config *cfg); | ||||
| int lfs_filebd_destroy(lfs_filebd_t *bd); | ||||
|  | ||||
| // Read a block | ||||
| int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_filebd_read(lfs_filebd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Program a block | ||||
| // | ||||
| // The block must have previously been erased. | ||||
| int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Erase a block | ||||
| // | ||||
| // A block must be erased before being programmed. The | ||||
| // state of an erased block is undefined. | ||||
| int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block); | ||||
| int lfs_filebd_erase(lfs_filebd_t *bd, lfs_block_t block); | ||||
|  | ||||
| // Sync the block device | ||||
| int lfs_filebd_sync(const struct lfs_config *cfg); | ||||
| int lfs_filebd_sync(lfs_filebd_t *bd); | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										109
									
								
								bd/lfs_rambd.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								bd/lfs_rambd.c
									
									
									
									
									
								
							| @@ -6,26 +6,24 @@ | ||||
|  */ | ||||
| #include "bd/lfs_rambd.h" | ||||
|  | ||||
| int lfs_rambd_createcfg(const struct lfs_config *cfg, | ||||
|         const struct lfs_rambd_config *bdcfg) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_createcfg(%p {.context=%p, " | ||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||
| int lfs_rambd_createcfg(lfs_rambd_t *bd, | ||||
|         const struct lfs_rambd_cfg *cfg) { | ||||
|     LFS_RAMBD_TRACE("lfs_filebd_createcfg(%p, %p {" | ||||
|                 ".read_size=%"PRIu32", .prog_size=%"PRIu32", " | ||||
|                 ".block_size=%"PRIu32", .block_count=%"PRIu32"}, " | ||||
|                 "%p {.erase_value=%"PRId32", .buffer=%p})", | ||||
|             (void*)cfg, cfg->context, | ||||
|             (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, | ||||
|             (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, | ||||
|             cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, | ||||
|             (void*)bdcfg, bdcfg->erase_value, bdcfg->buffer); | ||||
|     lfs_rambd_t *bd = cfg->context; | ||||
|     bd->cfg = bdcfg; | ||||
|                 ".erase_size=%"PRIu32", .erase_count=%"PRIu32", " | ||||
|                 ".erase_value=%"PRId32", .buffer=%p})", | ||||
|             (void*)bd, (void*)cfg, | ||||
|             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, | ||||
|             cfg->erase_value, cfg->buffer); | ||||
|  | ||||
|     // copy over config | ||||
|     bd->cfg = *cfg; | ||||
|  | ||||
|     // allocate buffer? | ||||
|     if (bd->cfg->buffer) { | ||||
|         bd->buffer = bd->cfg->buffer; | ||||
|     if (bd->cfg.buffer) { | ||||
|         bd->buffer = bd->cfg.buffer; | ||||
|     } else { | ||||
|         bd->buffer = lfs_malloc(cfg->block_size * cfg->block_count); | ||||
|         bd->buffer = lfs_malloc(bd->cfg.erase_size * bd->cfg.erase_count); | ||||
|         if (!bd->buffer) { | ||||
|             LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", LFS_ERR_NOMEM); | ||||
|             return LFS_ERR_NOMEM; | ||||
| @@ -33,108 +31,89 @@ int lfs_rambd_createcfg(const struct lfs_config *cfg, | ||||
|     } | ||||
|  | ||||
|     // zero for reproducability? | ||||
|     if (bd->cfg->erase_value != -1) { | ||||
|         memset(bd->buffer, bd->cfg->erase_value, | ||||
|                 cfg->block_size * cfg->block_count); | ||||
|     if (bd->cfg.erase_value != -1) { | ||||
|         memset(bd->buffer, bd->cfg.erase_value, | ||||
|                 bd->cfg.erase_size * bd->cfg.erase_count); | ||||
|     } | ||||
|  | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_rambd_create(const struct lfs_config *cfg) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_create(%p {.context=%p, " | ||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||
|                 ".read_size=%"PRIu32", .prog_size=%"PRIu32", " | ||||
|                 ".block_size=%"PRIu32", .block_count=%"PRIu32"})", | ||||
|             (void*)cfg, cfg->context, | ||||
|             (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, | ||||
|             (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, | ||||
|             cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count); | ||||
|     static const struct lfs_rambd_config defaults = {.erase_value=-1}; | ||||
|     int err = lfs_rambd_createcfg(cfg, &defaults); | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_create -> %d", err); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| int lfs_rambd_destroy(const struct lfs_config *cfg) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_destroy(%p)", (void*)cfg); | ||||
| int lfs_rambd_destroy(lfs_rambd_t *bd) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_destroy(%p)", (void*)bd); | ||||
|     // clean up memory | ||||
|     lfs_rambd_t *bd = cfg->context; | ||||
|     if (!bd->cfg->buffer) { | ||||
|     if (!bd->cfg.buffer) { | ||||
|         lfs_free(bd->buffer); | ||||
|     } | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_destroy -> %d", 0); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_rambd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_rambd_read(lfs_rambd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_read(%p, " | ||||
|                 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)cfg, block, off, buffer, size); | ||||
|     lfs_rambd_t *bd = cfg->context; | ||||
|             (void*)bd, block, off, buffer, size); | ||||
|  | ||||
|     // check if read is valid | ||||
|     LFS_ASSERT(off  % cfg->read_size == 0); | ||||
|     LFS_ASSERT(size % cfg->read_size == 0); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(off  % bd->cfg.read_size == 0); | ||||
|     LFS_ASSERT(size % bd->cfg.read_size == 0); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // read data | ||||
|     memcpy(buffer, &bd->buffer[block*cfg->block_size + off], size); | ||||
|     memcpy(buffer, &bd->buffer[block*bd->cfg.erase_size + off], size); | ||||
|  | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_read -> %d", 0); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_rambd_prog(lfs_rambd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_prog(%p, " | ||||
|                 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)cfg, block, off, buffer, size); | ||||
|     lfs_rambd_t *bd = cfg->context; | ||||
|             (void*)bd, block, off, buffer, size); | ||||
|  | ||||
|     // check if write is valid | ||||
|     LFS_ASSERT(off  % cfg->prog_size == 0); | ||||
|     LFS_ASSERT(size % cfg->prog_size == 0); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(off  % bd->cfg.prog_size == 0); | ||||
|     LFS_ASSERT(size % bd->cfg.prog_size == 0); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // check that data was erased? only needed for testing | ||||
|     if (bd->cfg->erase_value != -1) { | ||||
|     if (bd->cfg.erase_value != -1) { | ||||
|         for (lfs_off_t i = 0; i < size; i++) { | ||||
|             LFS_ASSERT(bd->buffer[block*cfg->block_size + off + i] == | ||||
|                     bd->cfg->erase_value); | ||||
|             LFS_ASSERT(bd->buffer[block*bd->cfg.erase_size + off + i] == | ||||
|                     bd->cfg.erase_value); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // program data | ||||
|     memcpy(&bd->buffer[block*cfg->block_size + off], buffer, size); | ||||
|     memcpy(&bd->buffer[block*bd->cfg.erase_size + off], buffer, size); | ||||
|  | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_prog -> %d", 0); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)cfg, block); | ||||
|     lfs_rambd_t *bd = cfg->context; | ||||
| int lfs_rambd_erase(lfs_rambd_t *bd, lfs_block_t block) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)bd, block); | ||||
|  | ||||
|     // check if erase is valid | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // erase, only needed for testing | ||||
|     if (bd->cfg->erase_value != -1) { | ||||
|         memset(&bd->buffer[block*cfg->block_size], | ||||
|                 bd->cfg->erase_value, cfg->block_size); | ||||
|     if (bd->cfg.erase_value != -1) { | ||||
|         memset(&bd->buffer[block*bd->cfg.erase_size], | ||||
|                 bd->cfg.erase_value, bd->cfg.erase_size); | ||||
|     } | ||||
|  | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_rambd_sync(const struct lfs_config *cfg) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_sync(%p)", (void*)cfg); | ||||
| int lfs_rambd_sync(lfs_rambd_t *bd) { | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_sync(%p)", (void*)bd); | ||||
|     // sync does nothing because we aren't backed by anything real | ||||
|     (void)cfg; | ||||
|     (void)bd; | ||||
|     LFS_RAMBD_TRACE("lfs_rambd_sync -> %d", 0); | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
| @@ -8,11 +8,9 @@ | ||||
| #define LFS_RAMBD_H | ||||
|  | ||||
| #include "lfs.h" | ||||
| #include "lfs_util.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @@ -24,7 +22,21 @@ extern "C" | ||||
| #endif | ||||
|  | ||||
| // rambd config (optional) | ||||
| struct lfs_rambd_config { | ||||
| struct lfs_rambd_cfg { | ||||
|     // Minimum size of block read. All read operations must be a | ||||
|     // multiple of this value. | ||||
|     lfs_size_t read_size; | ||||
|  | ||||
|     // Minimum size of block program. All program operations must be a | ||||
|     // multiple of this value. | ||||
|     lfs_size_t prog_size; | ||||
|  | ||||
|     // Size of an erasable block. | ||||
|     lfs_size_t erase_size; | ||||
|  | ||||
|     // Number of erasable blocks on the device. | ||||
|     lfs_size_t erase_count; | ||||
|  | ||||
|     // 8-bit erase value to simulate erasing with. -1 indicates no erase | ||||
|     // occurs, which is still a valid block device | ||||
|     int32_t erase_value; | ||||
| @@ -36,40 +48,39 @@ struct lfs_rambd_config { | ||||
| // rambd state | ||||
| typedef struct lfs_rambd { | ||||
|     uint8_t *buffer; | ||||
|     const struct lfs_rambd_config *cfg; | ||||
|     struct lfs_rambd_cfg cfg; | ||||
| } lfs_rambd_t; | ||||
|  | ||||
|  | ||||
| // Create a RAM block device using the geometry in lfs_config | ||||
| int lfs_rambd_create(const struct lfs_config *cfg); | ||||
| int lfs_rambd_createcfg(const struct lfs_config *cfg, | ||||
|         const struct lfs_rambd_config *bdcfg); | ||||
| // Create a RAM block device using the geometry in lfs_cfg | ||||
| int lfs_rambd_createcfg(lfs_rambd_t *bd, | ||||
|         const struct lfs_rambd_cfg *cfg); | ||||
|  | ||||
| // Clean up memory associated with block device | ||||
| int lfs_rambd_destroy(const struct lfs_config *cfg); | ||||
| int lfs_rambd_destroy(lfs_rambd_t *bd); | ||||
|  | ||||
| // Read a block | ||||
| int lfs_rambd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_rambd_read(lfs_rambd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Program a block | ||||
| // | ||||
| // The block must have previously been erased. | ||||
| int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_rambd_prog(lfs_rambd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Erase a block | ||||
| // | ||||
| // A block must be erased before being programmed. The | ||||
| // state of an erased block is undefined. | ||||
| int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block); | ||||
| int lfs_rambd_erase(lfs_rambd_t *bd, lfs_block_t block); | ||||
|  | ||||
| // Sync the block device | ||||
| int lfs_rambd_sync(const struct lfs_config *cfg); | ||||
| int lfs_rambd_sync(lfs_rambd_t *bd); | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										204
									
								
								bd/lfs_testbd.c
									
									
									
									
									
								
							
							
						
						
									
										204
									
								
								bd/lfs_testbd.c
									
									
									
									
									
								
							| @@ -10,185 +10,164 @@ | ||||
| #include <stdlib.h> | ||||
|  | ||||
|  | ||||
| int lfs_testbd_createcfg(const struct lfs_config *cfg, const char *path, | ||||
|         const struct lfs_testbd_config *bdcfg) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_createcfg(%p {.context=%p, " | ||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||
| int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, | ||||
|         const struct lfs_testbd_cfg *cfg) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_createcfg(%p, \"%s\", %p {" | ||||
|                 ".read_size=%"PRIu32", .prog_size=%"PRIu32", " | ||||
|                 ".block_size=%"PRIu32", .block_count=%"PRIu32"}, " | ||||
|                 "\"%s\", " | ||||
|                 "%p {.erase_value=%"PRId32", .erase_cycles=%"PRIu32", " | ||||
|                 ".erase_size=%"PRIu32", .erase_count=%"PRIu32", " | ||||
|                 ".erase_value=%"PRId32", .erase_cycles=%"PRIu32", " | ||||
|                 ".badblock_behavior=%"PRIu8", .power_cycles=%"PRIu32", " | ||||
|                 ".buffer=%p, .wear_buffer=%p})", | ||||
|             (void*)cfg, cfg->context, | ||||
|             (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, | ||||
|             (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, | ||||
|             cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, | ||||
|             path, (void*)bdcfg, bdcfg->erase_value, bdcfg->erase_cycles, | ||||
|             bdcfg->badblock_behavior, bdcfg->power_cycles, | ||||
|             bdcfg->buffer, bdcfg->wear_buffer); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     bd->cfg = bdcfg; | ||||
|             (void*)bd, path, (void*)cfg, | ||||
|             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, | ||||
|             cfg->erase_value, cfg->erase_cycles, | ||||
|             cfg->badblock_behavior, cfg->power_cycles, | ||||
|             cfg->buffer, cfg->wear_buffer); | ||||
|  | ||||
|     // copy over config | ||||
|     bd->cfg = *cfg; | ||||
|  | ||||
|     // setup testing things | ||||
|     bd->persist = path; | ||||
|     bd->power_cycles = bd->cfg->power_cycles; | ||||
|     bd->power_cycles = bd->cfg.power_cycles; | ||||
|  | ||||
|     if (bd->cfg->erase_cycles) { | ||||
|         if (bd->cfg->wear_buffer) { | ||||
|             bd->wear = bd->cfg->wear_buffer; | ||||
|     if (bd->cfg.erase_cycles) { | ||||
|         if (bd->cfg.wear_buffer) { | ||||
|             bd->wear = bd->cfg.wear_buffer; | ||||
|         } else { | ||||
|             bd->wear = lfs_malloc(sizeof(lfs_testbd_wear_t)*cfg->block_count); | ||||
|             bd->wear = lfs_malloc(sizeof(lfs_testbd_wear_t)*cfg->erase_count); | ||||
|             if (!bd->wear) { | ||||
|                 LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", LFS_ERR_NOMEM); | ||||
|                 return LFS_ERR_NOMEM; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         memset(bd->wear, 0, sizeof(lfs_testbd_wear_t) * cfg->block_count); | ||||
|         memset(bd->wear, 0, sizeof(lfs_testbd_wear_t) * bd->cfg.erase_count); | ||||
|     } | ||||
|  | ||||
|     // create underlying block device | ||||
|     if (bd->persist) { | ||||
|         bd->u.file.cfg = (struct lfs_filebd_config){ | ||||
|             .erase_value = bd->cfg->erase_value, | ||||
|         }; | ||||
|         int err = lfs_filebd_createcfg(cfg, path, &bd->u.file.cfg); | ||||
|         int err = lfs_filebd_createcfg(&bd->impl.filebd, path, | ||||
|                 &(struct lfs_filebd_cfg){ | ||||
|                     .read_size=bd->cfg.read_size, | ||||
|                     .prog_size=bd->cfg.prog_size, | ||||
|                     .erase_size=bd->cfg.erase_size, | ||||
|                     .erase_count=bd->cfg.erase_count, | ||||
|                     .erase_value=bd->cfg.erase_value}); | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); | ||||
|         return err; | ||||
|     } else { | ||||
|         bd->u.ram.cfg = (struct lfs_rambd_config){ | ||||
|             .erase_value = bd->cfg->erase_value, | ||||
|             .buffer = bd->cfg->buffer, | ||||
|         }; | ||||
|         int err = lfs_rambd_createcfg(cfg, &bd->u.ram.cfg); | ||||
|         int err = lfs_rambd_createcfg(&bd->impl.rambd, | ||||
|                 &(struct lfs_rambd_cfg){ | ||||
|                     .read_size=bd->cfg.read_size, | ||||
|                     .prog_size=bd->cfg.prog_size, | ||||
|                     .erase_size=bd->cfg.erase_size, | ||||
|                     .erase_count=bd->cfg.erase_count, | ||||
|                     .erase_value=bd->cfg.erase_value, | ||||
|                     .buffer=bd->cfg.buffer}); | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); | ||||
|         return err; | ||||
|     } | ||||
| } | ||||
|  | ||||
| int lfs_testbd_create(const struct lfs_config *cfg, const char *path) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_create(%p {.context=%p, " | ||||
|                 ".read=%p, .prog=%p, .erase=%p, .sync=%p, " | ||||
|                 ".read_size=%"PRIu32", .prog_size=%"PRIu32", " | ||||
|                 ".block_size=%"PRIu32", .block_count=%"PRIu32"}, " | ||||
|                 "\"%s\")", | ||||
|             (void*)cfg, cfg->context, | ||||
|             (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, | ||||
|             (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, | ||||
|             cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, | ||||
|             path); | ||||
|     static const struct lfs_testbd_config defaults = {.erase_value=-1}; | ||||
|     int err = lfs_testbd_createcfg(cfg, path, &defaults); | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_create -> %d", err); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| int lfs_testbd_destroy(const struct lfs_config *cfg) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_destroy(%p)", (void*)cfg); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     if (bd->cfg->erase_cycles && !bd->cfg->wear_buffer) { | ||||
| int lfs_testbd_destroy(lfs_testbd_t *bd) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_destroy(%p)", (void*)bd); | ||||
|     if (bd->cfg.erase_cycles && !bd->cfg.wear_buffer) { | ||||
|         lfs_free(bd->wear); | ||||
|     } | ||||
|  | ||||
|     if (bd->persist) { | ||||
|         int err = lfs_filebd_destroy(cfg); | ||||
|         int err = lfs_filebd_destroy(&bd->impl.filebd); | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_destroy -> %d", err); | ||||
|         return err; | ||||
|     } else { | ||||
|         int err = lfs_rambd_destroy(cfg); | ||||
|         int err = lfs_rambd_destroy(&bd->impl.rambd); | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_destroy -> %d", err); | ||||
|         return err; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Internal mapping to block devices /// | ||||
| static int lfs_testbd_rawread(const struct lfs_config *cfg, lfs_block_t block, | ||||
| static int lfs_testbd_rawread(lfs_testbd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size) { | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     if (bd->persist) { | ||||
|         return lfs_filebd_read(cfg, block, off, buffer, size); | ||||
|         return lfs_filebd_read(&bd->impl.filebd, block, off, buffer, size); | ||||
|     } else { | ||||
|         return lfs_rambd_read(cfg, block, off, buffer, size); | ||||
|         return lfs_rambd_read(&bd->impl.rambd, block, off, buffer, size); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int lfs_testbd_rawprog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| static int lfs_testbd_rawprog(lfs_testbd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size) { | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     if (bd->persist) { | ||||
|         return lfs_filebd_prog(cfg, block, off, buffer, size); | ||||
|         return lfs_filebd_prog(&bd->impl.filebd, block, off, buffer, size); | ||||
|     } else { | ||||
|         return lfs_rambd_prog(cfg, block, off, buffer, size); | ||||
|         return lfs_rambd_prog(&bd->impl.rambd, block, off, buffer, size); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int lfs_testbd_rawerase(const struct lfs_config *cfg, | ||||
| static int lfs_testbd_rawerase(lfs_testbd_t *bd, | ||||
|         lfs_block_t block) { | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     if (bd->persist) { | ||||
|         return lfs_filebd_erase(cfg, block); | ||||
|         return lfs_filebd_erase(&bd->impl.filebd, block); | ||||
|     } else { | ||||
|         return lfs_rambd_erase(cfg, block); | ||||
|         return lfs_rambd_erase(&bd->impl.rambd, block); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int lfs_testbd_rawsync(const struct lfs_config *cfg) { | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
| static int lfs_testbd_rawsync(lfs_testbd_t *bd) { | ||||
|     if (bd->persist) { | ||||
|         return lfs_filebd_sync(cfg); | ||||
|         return lfs_filebd_sync(&bd->impl.filebd); | ||||
|     } else { | ||||
|         return lfs_rambd_sync(cfg); | ||||
|         return lfs_rambd_sync(&bd->impl.rambd); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// block device API /// | ||||
| int lfs_testbd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_testbd_read(lfs_testbd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_read(%p, " | ||||
|                 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)cfg, block, off, buffer, size); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|             (void*)bd, block, off, buffer, size); | ||||
|  | ||||
|     // check if read is valid | ||||
|     LFS_ASSERT(off  % cfg->read_size == 0); | ||||
|     LFS_ASSERT(size % cfg->read_size == 0); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(off  % bd->cfg.read_size == 0); | ||||
|     LFS_ASSERT(size % bd->cfg.read_size == 0); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // block bad? | ||||
|     if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles && | ||||
|             bd->cfg->badblock_behavior == LFS_TESTBD_BADBLOCK_READERROR) { | ||||
|     if (bd->cfg.erase_cycles && bd->wear[block] >= bd->cfg.erase_cycles && | ||||
|             bd->cfg.badblock_behavior == LFS_TESTBD_BADBLOCK_READERROR) { | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_read -> %d", LFS_ERR_CORRUPT); | ||||
|         return LFS_ERR_CORRUPT; | ||||
|     } | ||||
|  | ||||
|     // read | ||||
|     int err = lfs_testbd_rawread(cfg, block, off, buffer, size); | ||||
|     int err = lfs_testbd_rawread(bd, block, off, buffer, size); | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_read -> %d", err); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_prog(%p, " | ||||
|                 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", | ||||
|             (void*)cfg, block, off, buffer, size); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|             (void*)bd, block, off, buffer, size); | ||||
|  | ||||
|     // check if write is valid | ||||
|     LFS_ASSERT(off  % cfg->prog_size == 0); | ||||
|     LFS_ASSERT(size % cfg->prog_size == 0); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(off  % bd->cfg.prog_size == 0); | ||||
|     LFS_ASSERT(size % bd->cfg.prog_size == 0); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // block bad? | ||||
|     if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles) { | ||||
|         if (bd->cfg->badblock_behavior == | ||||
|     if (bd->cfg.erase_cycles && bd->wear[block] >= bd->cfg.erase_cycles) { | ||||
|         if (bd->cfg.badblock_behavior == | ||||
|                 LFS_TESTBD_BADBLOCK_PROGERROR) { | ||||
|             LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", LFS_ERR_CORRUPT); | ||||
|             return LFS_ERR_CORRUPT; | ||||
|         } else if (bd->cfg->badblock_behavior == | ||||
|         } else if (bd->cfg.badblock_behavior == | ||||
|                 LFS_TESTBD_BADBLOCK_PROGNOOP || | ||||
|                 bd->cfg->badblock_behavior == | ||||
|                 bd->cfg.badblock_behavior == | ||||
|                 LFS_TESTBD_BADBLOCK_ERASENOOP) { | ||||
|             LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", 0); | ||||
|             return 0; | ||||
| @@ -196,7 +175,7 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
|     } | ||||
|  | ||||
|     // prog | ||||
|     int err = lfs_testbd_rawprog(cfg, block, off, buffer, size); | ||||
|     int err = lfs_testbd_rawprog(bd, block, off, buffer, size); | ||||
|     if (err) { | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err); | ||||
|         return err; | ||||
| @@ -207,7 +186,7 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
|         bd->power_cycles -= 1; | ||||
|         if (bd->power_cycles == 0) { | ||||
|             // sync to make sure we persist the last changes | ||||
|             assert(lfs_testbd_rawsync(cfg) == 0); | ||||
|             assert(lfs_testbd_rawsync(bd) == 0); | ||||
|             // simulate power loss | ||||
|             exit(33); | ||||
|         } | ||||
| @@ -217,21 +196,20 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_erase(%p, 0x%"PRIx32")", (void*)cfg, block); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
| int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_erase(%p, 0x%"PRIx32")", (void*)bd, block); | ||||
|  | ||||
|     // check if erase is valid | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     // block bad? | ||||
|     if (bd->cfg->erase_cycles) { | ||||
|         if (bd->wear[block] >= bd->cfg->erase_cycles) { | ||||
|             if (bd->cfg->badblock_behavior == | ||||
|     if (bd->cfg.erase_cycles) { | ||||
|         if (bd->wear[block] >= bd->cfg.erase_cycles) { | ||||
|             if (bd->cfg.badblock_behavior == | ||||
|                     LFS_TESTBD_BADBLOCK_ERASEERROR) { | ||||
|                 LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", LFS_ERR_CORRUPT); | ||||
|                 return LFS_ERR_CORRUPT; | ||||
|             } else if (bd->cfg->badblock_behavior == | ||||
|             } else if (bd->cfg.badblock_behavior == | ||||
|                     LFS_TESTBD_BADBLOCK_ERASENOOP) { | ||||
|                 LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", 0); | ||||
|                 return 0; | ||||
| @@ -243,7 +221,7 @@ int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|     } | ||||
|  | ||||
|     // erase | ||||
|     int err = lfs_testbd_rawerase(cfg, block); | ||||
|     int err = lfs_testbd_rawerase(bd, block); | ||||
|     if (err) { | ||||
|         LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err); | ||||
|         return err; | ||||
| @@ -254,7 +232,7 @@ int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|         bd->power_cycles -= 1; | ||||
|         if (bd->power_cycles == 0) { | ||||
|             // sync to make sure we persist the last changes | ||||
|             assert(lfs_testbd_rawsync(cfg) == 0); | ||||
|             assert(lfs_testbd_rawsync(bd) == 0); | ||||
|             // simulate power loss | ||||
|             exit(33); | ||||
|         } | ||||
| @@ -264,36 +242,34 @@ int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_testbd_sync(const struct lfs_config *cfg) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_sync(%p)", (void*)cfg); | ||||
|     int err = lfs_testbd_rawsync(cfg); | ||||
| int lfs_testbd_sync(lfs_testbd_t *bd) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_sync(%p)", (void*)bd); | ||||
|     int err = lfs_testbd_rawsync(bd); | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_sync -> %d", err); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
|  | ||||
| /// simulated wear operations /// | ||||
| lfs_testbd_swear_t lfs_testbd_getwear(const struct lfs_config *cfg, | ||||
| lfs_testbd_swear_t lfs_testbd_getwear(lfs_testbd_t *bd, | ||||
|         lfs_block_t block) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_getwear(%p, %"PRIu32")", (void*)cfg, block); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_getwear(%p, %"PRIu32")", (void*)bd, block); | ||||
|  | ||||
|     // check if block is valid | ||||
|     LFS_ASSERT(bd->cfg->erase_cycles); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(bd->cfg.erase_cycles); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_getwear -> %"PRIu32, bd->wear[block]); | ||||
|     return bd->wear[block]; | ||||
| } | ||||
|  | ||||
| int lfs_testbd_setwear(const struct lfs_config *cfg, | ||||
| int lfs_testbd_setwear(lfs_testbd_t *bd, | ||||
|         lfs_block_t block, lfs_testbd_wear_t wear) { | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_setwear(%p, %"PRIu32")", (void*)cfg, block); | ||||
|     lfs_testbd_t *bd = cfg->context; | ||||
|     LFS_TESTBD_TRACE("lfs_testbd_setwear(%p, %"PRIu32")", (void*)bd, block); | ||||
|  | ||||
|     // check if block is valid | ||||
|     LFS_ASSERT(bd->cfg->erase_cycles); | ||||
|     LFS_ASSERT(block < cfg->block_count); | ||||
|     LFS_ASSERT(bd->cfg.erase_cycles); | ||||
|     LFS_ASSERT(block < bd->cfg.erase_count); | ||||
|  | ||||
|     bd->wear[block] = wear; | ||||
|  | ||||
|   | ||||
| @@ -9,13 +9,11 @@ | ||||
| #define LFS_TESTBD_H | ||||
|  | ||||
| #include "lfs.h" | ||||
| #include "lfs_util.h" | ||||
| #include "bd/lfs_rambd.h" | ||||
| #include "bd/lfs_filebd.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @@ -45,7 +43,21 @@ typedef uint32_t lfs_testbd_wear_t; | ||||
| typedef int32_t  lfs_testbd_swear_t; | ||||
|  | ||||
| // testbd config, this is required for testing | ||||
| struct lfs_testbd_config { | ||||
| struct lfs_testbd_cfg { | ||||
|     // Minimum size of block read. All read operations must be a | ||||
|     // multiple of this value. | ||||
|     lfs_size_t read_size; | ||||
|  | ||||
|     // Minimum size of block program. All program operations must be a | ||||
|     // multiple of this value. | ||||
|     lfs_size_t prog_size; | ||||
|  | ||||
|     // Size of an erasable block. | ||||
|     lfs_size_t erase_size; | ||||
|  | ||||
|     // Number of erasable blocks on the device. | ||||
|     lfs_size_t erase_count; | ||||
|  | ||||
|     // 8-bit erase value to use for simulating erases. -1 does not simulate | ||||
|     // erases, which can speed up testing by avoiding all the extra block-device | ||||
|     // operations to store the erase value. | ||||
| @@ -72,70 +84,63 @@ struct lfs_testbd_config { | ||||
| // testbd state | ||||
| typedef struct lfs_testbd { | ||||
|     union { | ||||
|         struct { | ||||
|             lfs_filebd_t bd; | ||||
|             struct lfs_filebd_config cfg; | ||||
|         } file; | ||||
|         struct { | ||||
|             lfs_rambd_t bd; | ||||
|             struct lfs_rambd_config cfg; | ||||
|         } ram; | ||||
|     } u; | ||||
|         lfs_filebd_t filebd; | ||||
|         lfs_rambd_t rambd; | ||||
|     } impl; | ||||
|  | ||||
|     bool persist; | ||||
|     uint32_t power_cycles; | ||||
|     lfs_testbd_wear_t *wear; | ||||
|  | ||||
|     const struct lfs_testbd_config *cfg; | ||||
|     struct lfs_testbd_cfg cfg; | ||||
| } lfs_testbd_t; | ||||
|  | ||||
|  | ||||
| /// Block device API /// | ||||
|  | ||||
| // Create a test block device using the geometry in lfs_config | ||||
| // Create a test block device using the geometry in lfs_cfg | ||||
| // | ||||
| // Note that filebd is used if a path is provided, if path is NULL | ||||
| // testbd will use rambd which can be much faster. | ||||
| int lfs_testbd_create(const struct lfs_config *cfg, const char *path); | ||||
| int lfs_testbd_createcfg(const struct lfs_config *cfg, const char *path, | ||||
|         const struct lfs_testbd_config *bdcfg); | ||||
| int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, | ||||
|         const struct lfs_testbd_cfg *cfg); | ||||
|  | ||||
| // Clean up memory associated with block device | ||||
| int lfs_testbd_destroy(const struct lfs_config *cfg); | ||||
| int lfs_testbd_destroy(lfs_testbd_t *bd); | ||||
|  | ||||
| // Read a block | ||||
| int lfs_testbd_read(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_testbd_read(lfs_testbd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Program a block | ||||
| // | ||||
| // The block must have previously been erased. | ||||
| int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block, | ||||
| int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size); | ||||
|  | ||||
| // Erase a block | ||||
| // | ||||
| // A block must be erased before being programmed. The | ||||
| // state of an erased block is undefined. | ||||
| int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block); | ||||
| int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block); | ||||
|  | ||||
| // Sync the block device | ||||
| int lfs_testbd_sync(const struct lfs_config *cfg); | ||||
| int lfs_testbd_sync(lfs_testbd_t *bd); | ||||
|  | ||||
|  | ||||
| /// Additional extended API for driving test features /// | ||||
|  | ||||
| // Get simulated wear on a given block | ||||
| lfs_testbd_swear_t lfs_testbd_getwear(const struct lfs_config *cfg, | ||||
| lfs_testbd_swear_t lfs_testbd_getwear(lfs_testbd_t *bd, | ||||
|         lfs_block_t block); | ||||
|  | ||||
| // Manually set simulated wear on a given block | ||||
| int lfs_testbd_setwear(const struct lfs_config *cfg, | ||||
| int lfs_testbd_setwear(lfs_testbd_t *bd, | ||||
|         lfs_block_t block, lfs_testbd_wear_t wear); | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										215
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										215
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -7,12 +7,10 @@ | ||||
| #ifndef LFS_H | ||||
| #define LFS_H | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include "lfs_util.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @@ -66,26 +64,6 @@ typedef uint32_t lfs_block_t; | ||||
| #define LFS_ATTR_MAX 1022 | ||||
| #endif | ||||
|  | ||||
| // Possible error codes, these are negative to allow | ||||
| // valid positive return values | ||||
| enum lfs_error { | ||||
|     LFS_ERR_OK          = 0,    // No error | ||||
|     LFS_ERR_IO          = -5,   // Error during device operation | ||||
|     LFS_ERR_CORRUPT     = -84,  // Corrupted | ||||
|     LFS_ERR_NOENT       = -2,   // No directory entry | ||||
|     LFS_ERR_EXIST       = -17,  // Entry already exists | ||||
|     LFS_ERR_NOTDIR      = -20,  // Entry is not a dir | ||||
|     LFS_ERR_ISDIR       = -21,  // Entry is a dir | ||||
|     LFS_ERR_NOTEMPTY    = -39,  // Dir is not empty | ||||
|     LFS_ERR_BADF        = -9,   // Bad file number | ||||
|     LFS_ERR_FBIG        = -27,  // File too large | ||||
|     LFS_ERR_INVAL       = -22,  // Invalid parameter | ||||
|     LFS_ERR_NOSPC       = -28,  // No space left on device | ||||
|     LFS_ERR_NOMEM       = -12,  // No more memory available | ||||
|     LFS_ERR_NOATTR      = -61,  // No data/attr available | ||||
|     LFS_ERR_NAMETOOLONG = -36,  // File name too long | ||||
| }; | ||||
|  | ||||
| // File types | ||||
| enum lfs_type { | ||||
|     // file types | ||||
| @@ -147,32 +125,33 @@ enum lfs_whence_flags { | ||||
| }; | ||||
|  | ||||
|  | ||||
| #if !defined(LFS_STATICCFG) | ||||
| // Configuration provided during initialization of the littlefs | ||||
| struct lfs_config { | ||||
| struct lfs_cfg { | ||||
|     // Opaque user provided context that can be used to pass | ||||
|     // information to the block device operations | ||||
|     void *context; | ||||
|     void *ctx; | ||||
|  | ||||
|     // Read a region in a block. Negative error codes are propogated | ||||
|     // to the user. | ||||
|     int (*read)(const struct lfs_config *c, lfs_block_t block, | ||||
|     int (*read)(void *ctx, lfs_block_t block, | ||||
|             lfs_off_t off, void *buffer, lfs_size_t size); | ||||
|  | ||||
|     // Program a region in a block. The block must have previously | ||||
|     // been erased. Negative error codes are propogated to the user. | ||||
|     // May return LFS_ERR_CORRUPT if the block should be considered bad. | ||||
|     int (*prog)(const struct lfs_config *c, lfs_block_t block, | ||||
|     int (*prog)(void *ctx, lfs_block_t block, | ||||
|             lfs_off_t off, const void *buffer, lfs_size_t size); | ||||
|  | ||||
|     // Erase a block. A block must be erased before being programmed. | ||||
|     // The state of an erased block is undefined. Negative error codes | ||||
|     // are propogated to the user. | ||||
|     // May return LFS_ERR_CORRUPT if the block should be considered bad. | ||||
|     int (*erase)(const struct lfs_config *c, lfs_block_t block); | ||||
|     int (*erase)(void *ctx, lfs_block_t block); | ||||
|  | ||||
|     // Sync the state of the underlying block device. Negative error codes | ||||
|     // are propogated to the user. | ||||
|     int (*sync)(const struct lfs_config *c); | ||||
|     int (*sync)(void *ctx); | ||||
|  | ||||
|     // Minimum size of a block read. All read operations will be a | ||||
|     // multiple of this value. | ||||
| @@ -241,6 +220,90 @@ struct lfs_config { | ||||
|     // LFS_ATTR_MAX when zero. | ||||
|     lfs_size_t attr_max; | ||||
| }; | ||||
| #else | ||||
| // Static configuration if LFS_STATICCFG is defined, there are defaults | ||||
| // for some of these, but some are required. For full documentation, see | ||||
| // the lfs_cfg struct above. | ||||
|  | ||||
| // Block device operations | ||||
| int lfs_read(lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size); | ||||
| int lfs_prog(lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size); | ||||
| int lfs_erase(lfs_block_t block); | ||||
| int lfs_sync(void); | ||||
|  | ||||
| // Required configuration | ||||
| #ifndef LFS_READ_SIZE | ||||
| #error "LFS_STATICCFG requires LFS_READ_SIZE" | ||||
| #endif | ||||
| #ifndef LFS_PROG_SIZE | ||||
| #error "LFS_STATICCFG requires LFS_PROG_SIZE" | ||||
| #endif | ||||
| #ifndef LFS_BLOCK_SIZE | ||||
| #error "LFS_STATICCFG requires LFS_BLOCK_SIZE" | ||||
| #endif | ||||
| #ifndef LFS_BLOCK_COUNT | ||||
| #error "LFS_STATICCFG requires LFS_BLOCK_COUNT" | ||||
| #endif | ||||
| #ifndef LFS_BLOCK_CYCLES | ||||
| #error "LFS_STATICCFG requires LFS_BLOCK_CYCLES" | ||||
| #endif | ||||
| #ifndef LFS_CACHE_SIZE | ||||
| #error "LFS_STATICCFG requires LFS_CACHE_SIZE" | ||||
| #endif | ||||
| #ifndef LFS_LOOKAHEAD_SIZE | ||||
| #error "LFS_STATICCFG requires LFS_LOOKAHEAD_SIZE" | ||||
| #endif | ||||
|  | ||||
| // Optional configuration | ||||
| #ifndef LFS_READ_BUFFER | ||||
| #define LFS_READ_BUFFER NULL | ||||
| #endif | ||||
| #ifndef LFS_PROG_BUFFER | ||||
| #define LFS_PROG_BUFFER NULL | ||||
| #endif | ||||
| #ifndef LFS_LOOKAHEAD_BUFFER | ||||
| #define LFS_LOOKAHEAD_BUFFER NULL | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #if !defined(LFS_FILE_STATICCFG) | ||||
| // Optional configuration provided during lfs_file_opencfg | ||||
| struct lfs_file_cfg { | ||||
|     // Optional statically allocated file buffer. Must be cache_size. | ||||
|     // By default lfs_malloc is used to allocate this buffer. | ||||
|     void *buffer; | ||||
|  | ||||
|     // Optional list of custom attributes related to the file. If the file | ||||
|     // is opened with read access, these attributes will be read from disk | ||||
|     // 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; | ||||
|  | ||||
|     // Number of custom attributes in the list | ||||
|     lfs_size_t attr_count; | ||||
| }; | ||||
| #else | ||||
| // Static configuration if LFS_FILE_STATICCFG is defined. For full | ||||
| // documentation, see the lfs_file_cfg struct above. | ||||
| #ifndef LFS_FILE_BUFFER | ||||
| #define LFS_FILE_BUFFER NULL | ||||
| #endif | ||||
| #ifndef LFS_FILE_ATTRS | ||||
| #define LFS_FILE_ATTRS ((struct lfs_attr*)NULL) | ||||
| #endif | ||||
| #ifndef LFS_FILE_ATTR_COUNT | ||||
| #define LFS_FILE_ATTR_COUNT 0 | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| // File info structure | ||||
| struct lfs_info { | ||||
| @@ -271,29 +334,6 @@ struct lfs_attr { | ||||
|     lfs_size_t size; | ||||
| }; | ||||
|  | ||||
| // Optional configuration provided during lfs_file_opencfg | ||||
| struct lfs_file_config { | ||||
|     // Optional statically allocated file buffer. Must be cache_size. | ||||
|     // By default lfs_malloc is used to allocate this buffer. | ||||
|     void *buffer; | ||||
|  | ||||
|     // Optional list of custom attributes related to the file. If the file | ||||
|     // is opened with read access, these attributes will be read from disk | ||||
|     // 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; | ||||
|  | ||||
|     // Number of custom attributes in the list | ||||
|     lfs_size_t attr_count; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /// internal littlefs data structures /// | ||||
| typedef struct lfs_cache { | ||||
| @@ -343,7 +383,9 @@ typedef struct lfs_file { | ||||
|     lfs_off_t off; | ||||
|     lfs_cache_t cache; | ||||
|  | ||||
|     const struct lfs_file_config *cfg; | ||||
| #ifndef LFS_FILE_STATICCFG | ||||
|     struct lfs_file_cfg cfg; | ||||
| #endif | ||||
| } lfs_file_t; | ||||
|  | ||||
| typedef struct lfs_superblock { | ||||
| @@ -386,10 +428,9 @@ typedef struct lfs { | ||||
|         uint32_t *buffer; | ||||
|     } free; | ||||
|  | ||||
|     const struct lfs_config *cfg; | ||||
|     lfs_size_t name_max; | ||||
|     lfs_size_t file_max; | ||||
|     lfs_size_t attr_max; | ||||
| #ifndef LFS_STATICCFG | ||||
|     struct lfs_cfg cfg; | ||||
| #endif | ||||
|  | ||||
| #ifdef LFS_MIGRATE | ||||
|     struct lfs1 *lfs1; | ||||
| @@ -399,16 +440,38 @@ typedef struct lfs { | ||||
|  | ||||
| /// Filesystem functions /// | ||||
|  | ||||
| // Format a block device with the littlefs | ||||
| #if defined(LFS_STATICCFG) | ||||
| // Format a block device with littlefs | ||||
| // | ||||
| // Requires a littlefs object. This clobbers the littlefs object, and does | ||||
| // not leave the filesystem mounted. | ||||
| // | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_format(lfs_t *lfs); | ||||
| #endif | ||||
|  | ||||
| #if !defined(LFS_STATICCFG) | ||||
| // Format a block device with littlefs with per-filesystem configuration | ||||
| // | ||||
| // Requires a littlefs object and config struct. This clobbers the littlefs | ||||
| // object, and does not leave the filesystem mounted. The config struct must | ||||
| // be zeroed for defaults and backwards compatibility. | ||||
| // | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_format(lfs_t *lfs, const struct lfs_config *config); | ||||
| int lfs_formatcfg(lfs_t *lfs, const struct lfs_cfg *config); | ||||
| #endif | ||||
|  | ||||
| // Mounts a littlefs | ||||
| #if defined(LFS_STATICCFG) | ||||
| // Mounts littlefs | ||||
| // | ||||
| // Requires a littlefs object and static configuration. | ||||
| // | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_mount(lfs_t *lfs); | ||||
| #endif | ||||
|  | ||||
| #if !defined(LFS_STATICCFG) | ||||
| // Mounts a littlefs with per-filesystem configuration | ||||
| // | ||||
| // Requires a littlefs object and config struct. Multiple filesystems | ||||
| // may be mounted simultaneously with multiple littlefs objects. Both | ||||
| @@ -416,7 +479,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config); | ||||
| // be zeroed for defaults and backwards compatibility. | ||||
| // | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_mount(lfs_t *lfs, const struct lfs_config *config); | ||||
| int lfs_mountcfg(lfs_t *lfs, const struct lfs_cfg *config); | ||||
| #endif | ||||
|  | ||||
| // Unmounts a littlefs | ||||
| // | ||||
| @@ -490,7 +554,8 @@ int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type); | ||||
| int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | ||||
|         const char *path, int flags); | ||||
|  | ||||
| // Open a file with extra configuration | ||||
| #if !defined(LFS_FILE_STATICCFG) | ||||
| // Open a file with per-file configuration | ||||
| // | ||||
| // The mode that the file is opened in is determined by the flags, which | ||||
| // are values from the enum lfs_open_flags that are bitwise-ored together. | ||||
| @@ -502,7 +567,8 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | ||||
|         const char *path, int flags, | ||||
|         const struct lfs_file_config *config); | ||||
|         const struct lfs_file_cfg *config); | ||||
| #endif | ||||
|  | ||||
| // Close a file | ||||
| // | ||||
| @@ -632,24 +698,39 @@ 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); | ||||
|  | ||||
| #ifdef LFS_MIGRATE | ||||
| #if defined(LFS_MIGRATE) && defined(LFS_STATICCFG) | ||||
| // Attempts to migrate a previous version of littlefs | ||||
| // | ||||
| // Behaves similarly to the lfs_format function. Attempts to mount | ||||
| // the previous version of littlefs and update the filesystem so it can be | ||||
| // mounted with the current version of littlefs. | ||||
| // | ||||
| // Requires a littlefs object. This clobbers the littlefs object, and does | ||||
| // not leave the filesystem mounted. | ||||
| // | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_migrate(lfs_t *lfs, const struct lfs_cfg *cfg); | ||||
| #endif | ||||
|  | ||||
| #if defined(LFS_MIGRATE) && !defined(LFS_STATICCFG) | ||||
| // Attempts to migrate a previous version of littlefs with per-filesystem | ||||
| // configuration | ||||
| // | ||||
| // Behaves similarly to the lfs_format function. Attempts to mount | ||||
| // the previous version of littlefs and update the filesystem so it can be | ||||
| // mounted with the current version of littlefs. | ||||
| // | ||||
| // Requires a littlefs object and config struct. This clobbers the littlefs | ||||
| // object, and does not leave the filesystem mounted. The config struct must | ||||
| // be zeroed for defaults and backwards compatibility. | ||||
| // | ||||
| // Returns a negative error code on failure. | ||||
| int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg); | ||||
| int lfs_migratecfg(lfs_t *lfs, const struct lfs_cfg *cfg); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
| #include "lfs_util.h" | ||||
|  | ||||
| // Only compile if user does not provide custom config | ||||
| #ifndef LFS_CONFIG | ||||
| #ifndef LFS_UTIL | ||||
|  | ||||
|  | ||||
| // Software CRC implementation with small lookup table | ||||
|   | ||||
							
								
								
									
										48
									
								
								lfs_util.h
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								lfs_util.h
									
									
									
									
									
								
							| @@ -3,20 +3,21 @@ | ||||
|  * | ||||
|  * Copyright (c) 2017, Arm Limited. All rights reserved. | ||||
|  * SPDX-License-Identifier: BSD-3-Clause | ||||
|  * | ||||
|  * Can be overridden by users with their own configuration by defining | ||||
|  * LFS_UTIL as a header file (-DLFS_UTIL=my_lfs_util.h) | ||||
|  * | ||||
|  * If LFS_UTIL is defined, none of the default definitions will be | ||||
|  * emitted and must be provided by the user's header file. To start, I would | ||||
|  * suggest copying lfs_util.h and modifying as needed. | ||||
|  */ | ||||
| #ifndef LFS_UTIL_H | ||||
| #define LFS_UTIL_H | ||||
|  | ||||
| // Users can override lfs_util.h with their own configuration by defining | ||||
| // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). | ||||
| // | ||||
| // If LFS_CONFIG is used, none of the default utils will be emitted and must be | ||||
| // provided by the config file. To start, I would suggest copying lfs_util.h | ||||
| // and modifying as needed. | ||||
| #ifdef LFS_CONFIG | ||||
| #ifdef LFS_UTIL | ||||
| #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) | ||||
| #define LFS_STRINGIZE2(x) #x | ||||
| #include LFS_STRINGIZE(LFS_CONFIG) | ||||
| #include LFS_STRINGIZE(LFS_UTIL) | ||||
| #else | ||||
|  | ||||
| // System includes | ||||
| @@ -39,11 +40,32 @@ | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
|  | ||||
| // Possible error codes, these are negative to allow valid positive | ||||
| // return values. May be redefined to system-specific error codes as long | ||||
| // as they fit in a negative integer. | ||||
| enum lfs_error { | ||||
|     LFS_ERR_OK          = 0,    // No error | ||||
|     LFS_ERR_IO          = -5,   // Error during device operation | ||||
|     LFS_ERR_CORRUPT     = -84,  // Corrupted | ||||
|     LFS_ERR_NOENT       = -2,   // No directory entry | ||||
|     LFS_ERR_EXIST       = -17,  // Entry already exists | ||||
|     LFS_ERR_NOTDIR      = -20,  // Entry is not a dir | ||||
|     LFS_ERR_ISDIR       = -21,  // Entry is a dir | ||||
|     LFS_ERR_NOTEMPTY    = -39,  // Dir is not empty | ||||
|     LFS_ERR_BADF        = -9,   // Bad file number | ||||
|     LFS_ERR_FBIG        = -27,  // File too large | ||||
|     LFS_ERR_INVAL       = -22,  // Invalid parameter | ||||
|     LFS_ERR_NOSPC       = -28,  // No space left on device | ||||
|     LFS_ERR_NOMEM       = -12,  // No more memory available | ||||
|     LFS_ERR_NOATTR      = -61,  // No data/attr available | ||||
|     LFS_ERR_NAMETOOLONG = -36,  // File name too long | ||||
| }; | ||||
|  | ||||
|  | ||||
| // Macros, may be replaced by system specific wrappers. Arguments to these | ||||
| // macros must not have side-effects as the macros can be removed for a smaller | ||||
| // code footprint | ||||
| @@ -150,8 +172,8 @@ static inline uint32_t lfs_popc(uint32_t a) { | ||||
|  | ||||
| // Find the sequence comparison of a and b, this is the distance | ||||
| // between a and b ignoring overflow | ||||
| static inline int lfs_scmp(uint32_t a, uint32_t b) { | ||||
|     return (int)(unsigned)(a - b); | ||||
| static inline int32_t lfs_scmp(uint32_t a, uint32_t b) { | ||||
|     return (int32_t)(uint32_t)(a - b); | ||||
| } | ||||
|  | ||||
| // Convert between 32-bit little-endian and native order | ||||
| @@ -227,7 +249,7 @@ static inline void lfs_free(void *p) { | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -34,13 +34,43 @@ $(foreach target,$(SRC),$(eval $(FLATTEN))) | ||||
| %.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f) | ||||
|     $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ | ||||
| """ | ||||
| GLOBALS = """ | ||||
| BEFORE_MAIN = """ | ||||
| const char *lfs_testbd_path; | ||||
| uint32_t lfs_testbd_cycles; | ||||
|  | ||||
| int lfs_testbd_readctx(void *ctx, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size) { | ||||
|     return lfs_testbd_read((lfs_testbd_t*)ctx, block, off, buffer, size); | ||||
| } | ||||
|  | ||||
| int lfs_testbd_progctx(void *ctx, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size) { | ||||
|     return lfs_testbd_prog((lfs_testbd_t*)ctx, block, off, buffer, size); | ||||
| } | ||||
|  | ||||
| int lfs_testbd_erasectx(void *ctx, lfs_block_t block) { | ||||
|     return lfs_testbd_erase((lfs_testbd_t*)ctx, block); | ||||
| } | ||||
|  | ||||
| int lfs_testbd_syncctx(void *ctx) { | ||||
|     return lfs_testbd_sync((lfs_testbd_t*)ctx); | ||||
| } | ||||
| """ | ||||
| BEFORE_TESTS = """ | ||||
| //////////////// AUTOGENERATED TEST //////////////// | ||||
| #include "lfs.h" | ||||
| #include "bd/lfs_testbd.h" | ||||
| #include <stdio.h> | ||||
|  | ||||
| extern const char *lfs_testbd_path; | ||||
| extern uint32_t lfs_testbd_cycles; | ||||
|  | ||||
| extern int lfs_testbd_readctx(void *ctx, lfs_block_t block, | ||||
|         lfs_off_t off, void *buffer, lfs_size_t size); | ||||
| extern int lfs_testbd_progctx(void *ctx, lfs_block_t block, | ||||
|         lfs_off_t off, const void *buffer, lfs_size_t size); | ||||
| extern int lfs_testbd_erasectx(void *ctx, lfs_block_t block); | ||||
| extern int lfs_testbd_syncctx(void *ctx); | ||||
| """ | ||||
| DEFINES = { | ||||
|     'LFS_READ_SIZE': 16, | ||||
| @@ -66,12 +96,12 @@ PROLOGUE = """ | ||||
|     __attribute__((unused)) lfs_size_t size; | ||||
|     __attribute__((unused)) int err; | ||||
|      | ||||
|     __attribute__((unused)) const struct lfs_config cfg = { | ||||
|         .context        = &bd, | ||||
|         .read           = lfs_testbd_read, | ||||
|         .prog           = lfs_testbd_prog, | ||||
|         .erase          = lfs_testbd_erase, | ||||
|         .sync           = lfs_testbd_sync, | ||||
|     __attribute__((unused)) const struct lfs_cfg cfg = { | ||||
|         .ctx            = &bd, | ||||
|         .read           = lfs_testbd_readctx, | ||||
|         .prog           = lfs_testbd_progctx, | ||||
|         .erase          = lfs_testbd_erasectx, | ||||
|         .sync           = lfs_testbd_syncctx, | ||||
|         .read_size      = LFS_READ_SIZE, | ||||
|         .prog_size      = LFS_PROG_SIZE, | ||||
|         .block_size     = LFS_BLOCK_SIZE, | ||||
| @@ -81,18 +111,22 @@ PROLOGUE = """ | ||||
|         .lookahead_size = LFS_LOOKAHEAD_SIZE, | ||||
|     }; | ||||
|  | ||||
|     __attribute__((unused)) const struct lfs_testbd_config bdcfg = { | ||||
|     __attribute__((unused)) const struct lfs_testbd_cfg bdcfg = { | ||||
|         .read_size          = LFS_READ_SIZE, | ||||
|         .prog_size          = LFS_PROG_SIZE, | ||||
|         .erase_size         = LFS_BLOCK_SIZE, | ||||
|         .erase_count        = LFS_BLOCK_COUNT, | ||||
|         .erase_value        = LFS_ERASE_VALUE, | ||||
|         .erase_cycles       = LFS_ERASE_CYCLES, | ||||
|         .badblock_behavior  = LFS_BADBLOCK_BEHAVIOR, | ||||
|         .power_cycles       = lfs_testbd_cycles, | ||||
|     }; | ||||
|  | ||||
|     lfs_testbd_createcfg(&cfg, lfs_testbd_path, &bdcfg) => 0; | ||||
|     lfs_testbd_createcfg(&bd, lfs_testbd_path, &bdcfg) => 0; | ||||
| """ | ||||
| EPILOGUE = """ | ||||
|     // epilogue | ||||
|     lfs_testbd_destroy(&cfg) => 0; | ||||
|     lfs_testbd_destroy(&bd) => 0; | ||||
| """ | ||||
| PASS = '\033[32m✓\033[0m' | ||||
| FAIL = '\033[31m✗\033[0m' | ||||
| @@ -468,7 +502,7 @@ class TestSuite: | ||||
|     def build(self, **args): | ||||
|         # build test files | ||||
|         tf = open(self.path + '.test.c.t', 'w') | ||||
|         tf.write(GLOBALS) | ||||
|         tf.write(BEFORE_TESTS) | ||||
|         if self.code is not None: | ||||
|             tf.write('#line %d "%s"\n' % (self.code_lineno, self.path)) | ||||
|             tf.write(self.code) | ||||
| @@ -483,14 +517,13 @@ class TestSuite: | ||||
|                     for line in f: | ||||
|                         tfs[case.in_].write(line) | ||||
|                 tfs[case.in_].write('\n') | ||||
|                 tfs[case.in_].write(GLOBALS) | ||||
|                 tfs[case.in_].write(BEFORE_TESTS) | ||||
|  | ||||
|             tfs[case.in_].write('\n') | ||||
|             case.build(tfs[case.in_], **args) | ||||
|  | ||||
|         tf.write(BEFORE_MAIN) | ||||
|         tf.write('\n') | ||||
|         tf.write('const char *lfs_testbd_path;\n') | ||||
|         tf.write('uint32_t lfs_testbd_cycles;\n') | ||||
|         tf.write('int main(int argc, char **argv) {\n') | ||||
|         tf.write(4*' '+'int case_         = (argc > 1) ? atoi(argv[1]) : 0;\n') | ||||
|         tf.write(4*' '+'int perm          = (argc > 2) ? atoi(argv[2]) : 0;\n') | ||||
|   | ||||
| @@ -9,12 +9,12 @@ code = ''' | ||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||
|     lfs_file_t files[FILES]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "breakfast") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int n = 0; n < FILES; n++) { | ||||
|         sprintf(path, "breakfast/%s", names[n]); | ||||
|         lfs_file_open(&lfs, &files[n], path, | ||||
| @@ -31,7 +31,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int n = 0; n < FILES; n++) { | ||||
|         sprintf(path, "breakfast/%s", names[n]); | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
| @@ -51,13 +51,13 @@ define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-6)) / FILES)' | ||||
| code = ''' | ||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "breakfast") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     for (int n = 0; n < FILES; n++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         sprintf(path, "breakfast/%s", names[n]); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||
| @@ -70,7 +70,7 @@ code = ''' | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|     } | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int n = 0; n < FILES; n++) { | ||||
|         sprintf(path, "breakfast/%s", names[n]); | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
| @@ -92,14 +92,14 @@ code = ''' | ||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||
|     lfs_file_t files[FILES]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     for (int c = 0; c < CYCLES; c++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mkdir(&lfs, "breakfast") => 0; | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int n = 0; n < FILES; n++) { | ||||
|             sprintf(path, "breakfast/%s", names[n]); | ||||
|             lfs_file_open(&lfs, &files[n], path, | ||||
| @@ -116,7 +116,7 @@ code = ''' | ||||
|         } | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int n = 0; n < FILES; n++) { | ||||
|             sprintf(path, "breakfast/%s", names[n]); | ||||
|             lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
| @@ -129,7 +129,7 @@ code = ''' | ||||
|         } | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int n = 0; n < FILES; n++) { | ||||
|             sprintf(path, "breakfast/%s", names[n]); | ||||
|             lfs_remove(&lfs, path) => 0; | ||||
| @@ -146,15 +146,15 @@ define.CYCLES = [1, 10] | ||||
| code = ''' | ||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     for (int c = 0; c < CYCLES; c++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mkdir(&lfs, "breakfast") => 0; | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         for (int n = 0; n < FILES; n++) { | ||||
|             lfs_mount(&lfs, &cfg) => 0; | ||||
|             lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|             sprintf(path, "breakfast/%s", names[n]); | ||||
|             lfs_file_open(&lfs, &file, path, | ||||
|                     LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||
| @@ -167,7 +167,7 @@ code = ''' | ||||
|             lfs_unmount(&lfs) => 0; | ||||
|         } | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int n = 0; n < FILES; n++) { | ||||
|             sprintf(path, "breakfast/%s", names[n]); | ||||
|             lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
| @@ -180,7 +180,7 @@ code = ''' | ||||
|         } | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int n = 0; n < FILES; n++) { | ||||
|             sprintf(path, "breakfast/%s", names[n]); | ||||
|             lfs_remove(&lfs, path) => 0; | ||||
| @@ -192,8 +192,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # exhaustion test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); | ||||
|     size = strlen("exhaustion"); | ||||
|     memcpy(buffer, "exhaustion", size); | ||||
| @@ -216,7 +216,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); | ||||
|     size = strlen("exhaustion"); | ||||
|     lfs_file_size(&lfs, &file) => size; | ||||
| @@ -229,8 +229,8 @@ code = ''' | ||||
| [[case]] # exhaustion wraparound test | ||||
| define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / 3)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT); | ||||
|     size = strlen("buffering"); | ||||
| @@ -263,7 +263,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); | ||||
|     size = strlen("exhaustion"); | ||||
|     lfs_file_size(&lfs, &file) => size; | ||||
| @@ -276,8 +276,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # dir exhaustion test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // find out max file size | ||||
|     lfs_mkdir(&lfs, "exhaustiondir") => 0; | ||||
| @@ -328,8 +328,8 @@ in = "lfs.c" | ||||
| define.LFS_ERASE_CYCLES = 0xffffffff | ||||
| define.LFS_BADBLOCK_BEHAVIOR = 'LFS_TESTBD_BADBLOCK_READERROR' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     // first fill to exhaustion to find available space | ||||
|     lfs_file_open(&lfs, &file, "pacman", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     strcpy((char*)buffer, "waka"); | ||||
| @@ -358,11 +358,11 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // remount to force an alloc scan | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // but mark the head of our file as a "bad block", this is force our | ||||
|     // scan to bail early | ||||
|     lfs_testbd_setwear(&cfg, fileblock, 0xffffffff) => 0; | ||||
|     lfs_testbd_setwear(&bd, fileblock, 0xffffffff) => 0; | ||||
|     lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     strcpy((char*)buffer, "chomp"); | ||||
|     size = strlen("chomp"); | ||||
| @@ -377,7 +377,7 @@ code = ''' | ||||
|  | ||||
|     // now reverse the "bad block" and try to write the file again until we | ||||
|     // run out of space | ||||
|     lfs_testbd_setwear(&cfg, fileblock, 0) => 0; | ||||
|     lfs_testbd_setwear(&bd, fileblock, 0) => 0; | ||||
|     lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     strcpy((char*)buffer, "chomp"); | ||||
|     size = strlen("chomp"); | ||||
| @@ -393,7 +393,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // check that the disk isn't hurt | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "pacman", LFS_O_RDONLY) => 0; | ||||
|     strcpy((char*)buffer, "waka"); | ||||
|     size = strlen("waka"); | ||||
| @@ -416,8 +416,8 @@ define.LFS_BLOCK_SIZE = 512 | ||||
| define.LFS_BLOCK_COUNT = 1024 | ||||
| if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // find out max file size | ||||
|     lfs_mkdir(&lfs, "exhaustiondir") => 0; | ||||
| @@ -487,8 +487,8 @@ define.LFS_BLOCK_SIZE = 512 | ||||
| define.LFS_BLOCK_COUNT = 1024 | ||||
| if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // create one block hole for half a directory | ||||
|     lfs_file_open(&lfs, &file, "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
| @@ -510,7 +510,7 @@ code = ''' | ||||
|  | ||||
|     // remount to force reset of lookahead | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // open hole | ||||
|     lfs_remove(&lfs, "bump") => 0; | ||||
| @@ -532,8 +532,8 @@ define.LFS_BLOCK_SIZE = 512 | ||||
| define.LFS_BLOCK_COUNT = 1024 | ||||
| if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // fill completely with two files | ||||
|     lfs_file_open(&lfs, &file, "exhaustion1", | ||||
| @@ -560,7 +560,7 @@ code = ''' | ||||
|  | ||||
|     // remount to force reset of lookahead | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // rewrite one file | ||||
|     lfs_file_open(&lfs, &file, "exhaustion1", | ||||
| @@ -597,8 +597,8 @@ define.LFS_BLOCK_SIZE = 512 | ||||
| define.LFS_BLOCK_COUNT = 1024 | ||||
| if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // fill completely with two files | ||||
|     lfs_file_open(&lfs, &file, "exhaustion1", | ||||
| @@ -625,7 +625,7 @@ code = ''' | ||||
|  | ||||
|     // remount to force reset of lookahead | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // rewrite one file with a hole of one block | ||||
|     lfs_file_open(&lfs, &file, "exhaustion1", | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| [[case]] # set/get attribute | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "hello") => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello"); | ||||
|     lfs_file_close(&lfs, &file); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(buffer, 0, sizeof(buffer)); | ||||
|     lfs_setattr(&lfs, "hello", 'A', "aaaa",   4) => 0; | ||||
|     lfs_setattr(&lfs, "hello", 'B', "bbbbbb", 6) => 0; | ||||
| @@ -60,7 +60,7 @@ code = ''' | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(buffer, 0, sizeof(buffer)); | ||||
|     lfs_getattr(&lfs, "hello", 'A', buffer,    4) => 4; | ||||
|     lfs_getattr(&lfs, "hello", 'B', buffer+4,  9) => 9; | ||||
| @@ -78,15 +78,15 @@ code = ''' | ||||
|  | ||||
| [[case]] # set/get root attribute | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "hello") => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello"); | ||||
|     lfs_file_close(&lfs, &file); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(buffer, 0, sizeof(buffer)); | ||||
|     lfs_setattr(&lfs, "/", 'A', "aaaa",   4) => 0; | ||||
|     lfs_setattr(&lfs, "/", 'B', "bbbbbb", 6) => 0; | ||||
| @@ -137,7 +137,7 @@ code = ''' | ||||
|     lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(buffer, 0, sizeof(buffer)); | ||||
|     lfs_getattr(&lfs, "/", 'A', buffer,    4) => 4; | ||||
|     lfs_getattr(&lfs, "/", 'B', buffer+4,  9) => 9; | ||||
| @@ -155,22 +155,22 @@ code = ''' | ||||
|  | ||||
| [[case]] # set/get file attribute | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "hello") => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello"); | ||||
|     lfs_file_close(&lfs, &file); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(buffer, 0, sizeof(buffer)); | ||||
|     struct lfs_attr attrs1[] = { | ||||
|         {'A', buffer,    4}, | ||||
|         {'B', buffer+4,  6}, | ||||
|         {'C', buffer+10, 5}, | ||||
|     }; | ||||
|     struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3}; | ||||
|     struct lfs_file_cfg cfg1 = {.attrs=attrs1, .attr_count=3}; | ||||
|  | ||||
|     lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|     memcpy(buffer,    "aaaa",   4); | ||||
| @@ -228,7 +228,7 @@ code = ''' | ||||
|         {'B', buffer+4,  9}, | ||||
|         {'C', buffer+13, 5}, | ||||
|     }; | ||||
|     struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3}; | ||||
|     struct lfs_file_cfg cfg2 = {.attrs=attrs2, .attr_count=3}; | ||||
|     lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0; | ||||
|     memcpy(buffer+4,  "fffffffff", 9); | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
| @@ -238,14 +238,14 @@ code = ''' | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(buffer, 0, sizeof(buffer)); | ||||
|     struct lfs_attr attrs3[] = { | ||||
|         {'A', buffer,    4}, | ||||
|         {'B', buffer+4,  9}, | ||||
|         {'C', buffer+13, 5}, | ||||
|     }; | ||||
|     struct lfs_file_config cfg3 = {.attrs=attrs3, .attr_count=3}; | ||||
|     struct lfs_file_cfg cfg3 = {.attrs=attrs3, .attr_count=3}; | ||||
|  | ||||
|     lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg3) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
| @@ -262,15 +262,15 @@ code = ''' | ||||
|  | ||||
| [[case]] # deferred file attributes | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "hello") => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello"); | ||||
|     lfs_file_close(&lfs, &file); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_setattr(&lfs, "hello/hello", 'B', "fffffffff",  9) => 0; | ||||
|     lfs_setattr(&lfs, "hello/hello", 'C', "ccccc",      5) => 0; | ||||
|  | ||||
| @@ -280,7 +280,7 @@ code = ''' | ||||
|         {'C', "",     0}, | ||||
|         {'D', "hhhh", 4}, | ||||
|     }; | ||||
|     struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3}; | ||||
|     struct lfs_file_cfg cfg1 = {.attrs=attrs1, .attr_count=3}; | ||||
|  | ||||
|     lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; | ||||
|  | ||||
|   | ||||
| @@ -16,12 +16,12 @@ define.NAMEMULT = 64 | ||||
| define.FILEMULT = 1 | ||||
| code = ''' | ||||
|     for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) { | ||||
|         lfs_testbd_setwear(&cfg, badblock-1, 0) => 0; | ||||
|         lfs_testbd_setwear(&cfg, badblock, 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, badblock-1, 0) => 0; | ||||
|         lfs_testbd_setwear(&bd, badblock, 0xffffffff) => 0; | ||||
|          | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int i = 1; i < 10; i++) { | ||||
|             for (int j = 0; j < NAMEMULT; j++) { | ||||
|                 buffer[j] = '0'+i; | ||||
| @@ -46,7 +46,7 @@ code = ''' | ||||
|         } | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (int i = 1; i < 10; i++) { | ||||
|             for (int j = 0; j < NAMEMULT; j++) { | ||||
|                 buffer[j] = '0'+i; | ||||
| @@ -90,12 +90,12 @@ define.NAMEMULT = 64 | ||||
| define.FILEMULT = 1 | ||||
| code = ''' | ||||
|     for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) { | ||||
|         lfs_testbd_setwear(&cfg, i+2, 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, i+2, 0xffffffff) => 0; | ||||
|     } | ||||
|      | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 1; i < 10; i++) { | ||||
|         for (int j = 0; j < NAMEMULT; j++) { | ||||
|             buffer[j] = '0'+i; | ||||
| @@ -120,7 +120,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 1; i < 10; i++) { | ||||
|         for (int j = 0; j < NAMEMULT; j++) { | ||||
|             buffer[j] = '0'+i; | ||||
| @@ -163,12 +163,12 @@ define.NAMEMULT = 64 | ||||
| define.FILEMULT = 1 | ||||
| code = ''' | ||||
|     for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) { | ||||
|         lfs_testbd_setwear(&cfg, (2*i) + 2, 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, (2*i) + 2, 0xffffffff) => 0; | ||||
|     } | ||||
|      | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 1; i < 10; i++) { | ||||
|         for (int j = 0; j < NAMEMULT; j++) { | ||||
|             buffer[j] = '0'+i; | ||||
| @@ -193,7 +193,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 1; i < 10; i++) { | ||||
|         for (int j = 0; j < NAMEMULT; j++) { | ||||
|             buffer[j] = '0'+i; | ||||
| @@ -233,9 +233,9 @@ define.LFS_BADBLOCK_BEHAVIOR = [ | ||||
|     'LFS_TESTBD_BADBLOCK_ERASENOOP', | ||||
| ] | ||||
| code = ''' | ||||
|     lfs_testbd_setwear(&cfg, 0, 0xffffffff) => 0; | ||||
|     lfs_testbd_setwear(&cfg, 1, 0xffffffff) => 0; | ||||
|     lfs_testbd_setwear(&bd, 0, 0xffffffff) => 0; | ||||
|     lfs_testbd_setwear(&bd, 1, 0xffffffff) => 0; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => LFS_ERR_NOSPC; | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
|     lfs_formatcfg(&lfs, &cfg) => LFS_ERR_NOSPC; | ||||
|     lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| [[case]] # root | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -17,16 +17,16 @@ code = ''' | ||||
| [[case]] # many directory creation | ||||
| define.N = 'range(0, 100, 3)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "dir%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -48,16 +48,16 @@ code = ''' | ||||
| [[case]] # many directory removal | ||||
| define.N = 'range(3, 100, 11)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -75,14 +75,14 @@ code = ''' | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_remove(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -98,16 +98,16 @@ code = ''' | ||||
| [[case]] # many directory rename | ||||
| define.N = 'range(3, 100, 11)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "test%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -125,7 +125,7 @@ code = ''' | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         char oldpath[128]; | ||||
|         char newpath[128]; | ||||
| @@ -135,7 +135,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -158,10 +158,10 @@ code = ''' | ||||
| define.N = [5, 11] | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
| @@ -237,9 +237,9 @@ code = ''' | ||||
| [[case]] # file creation | ||||
| define.N = 'range(3, 100, 11)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
| @@ -248,7 +248,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -270,9 +270,9 @@ code = ''' | ||||
| [[case]] # file removal | ||||
| define.N = 'range(0, 100, 3)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
| @@ -281,7 +281,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -299,14 +299,14 @@ code = ''' | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_remove(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -322,9 +322,9 @@ code = ''' | ||||
| [[case]] # file rename | ||||
| define.N = 'range(0, 100, 3)' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "test%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
| @@ -333,7 +333,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -351,7 +351,7 @@ code = ''' | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         char oldpath[128]; | ||||
|         char newpath[128]; | ||||
| @@ -361,7 +361,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -384,10 +384,10 @@ code = ''' | ||||
| define.N = [5, 25] | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
| @@ -462,21 +462,21 @@ code = ''' | ||||
|  | ||||
| [[case]] # nested directories | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "potato") => 0; | ||||
|     lfs_file_open(&lfs, &file, "burito", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "potato/baked") => 0; | ||||
|     lfs_mkdir(&lfs, "potato/sweet") => 0; | ||||
|     lfs_mkdir(&lfs, "potato/fried") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "potato") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -498,21 +498,21 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // try removing? | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // try renaming? | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "potato", "coldpotato") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "coldpotato", "warmpotato") => 0; | ||||
|     lfs_rename(&lfs, "warmpotato", "hotpotato") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "potato") => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "warmpotato") => LFS_ERR_NOENT; | ||||
| @@ -520,7 +520,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // try cross-directory renaming | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "coldpotato") => 0; | ||||
|     lfs_rename(&lfs, "hotpotato/baked", "coldpotato/baked") => 0; | ||||
|     lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
| @@ -536,7 +536,7 @@ code = ''' | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "hotpotato") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -558,7 +558,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|      | ||||
|     // final remove | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "hotpotato/baked") => 0; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
| @@ -568,7 +568,7 @@ code = ''' | ||||
|     lfs_remove(&lfs, "hotpotato") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -587,8 +587,8 @@ code = ''' | ||||
| [[case]] # recursive remove | ||||
| define.N = [10, 100] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "prickly-pear") => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "prickly-pear/cactus%03d", i); | ||||
| @@ -611,7 +611,7 @@ code = ''' | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY; | ||||
|  | ||||
|     lfs_dir_open(&lfs, &dir, "prickly-pear") => 0; | ||||
| @@ -636,22 +636,22 @@ code = ''' | ||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # other error cases | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "potato") => 0; | ||||
|     lfs_file_open(&lfs, &file, "burito", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST; | ||||
|     lfs_mkdir(&lfs, "burito") => LFS_ERR_EXIST; | ||||
| @@ -696,7 +696,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // or on disk | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -718,8 +718,8 @@ code = ''' | ||||
| [[case]] # directory seek | ||||
| define.COUNT = [4, 128, 132] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "hello") => 0; | ||||
|     for (int i = 0; i < COUNT; i++) { | ||||
|         sprintf(path, "hello/kitty%03d", i); | ||||
| @@ -728,7 +728,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     for (int j = 2; j < COUNT; j++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         lfs_dir_open(&lfs, &dir, "hello") => 0; | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(strcmp(info.name, ".") == 0); | ||||
| @@ -779,8 +779,8 @@ code = ''' | ||||
| [[case]] # root seek | ||||
| define.COUNT = [4, 128, 132] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < COUNT; i++) { | ||||
|         sprintf(path, "hi%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
| @@ -788,7 +788,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     for (int j = 2; j < COUNT; j++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(strcmp(info.name, ".") == 0); | ||||
|   | ||||
| @@ -10,8 +10,8 @@ code = ''' | ||||
|     uint8_t wbuffer[1024]; | ||||
|     uint8_t rbuffer[1024]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write hi0 20 | ||||
|     sprintf(path, "hi0"); size = 20; | ||||
| @@ -99,8 +99,8 @@ code = ''' | ||||
|     uint8_t wbuffer[1024]; | ||||
|     uint8_t rbuffer[1024]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write hi0 20 | ||||
|     sprintf(path, "hi0"); size = 20; | ||||
| @@ -188,8 +188,8 @@ code = ''' | ||||
|     uint8_t wbuffer[1024]; | ||||
|     uint8_t rbuffer[1024]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write hi0 200 | ||||
|     sprintf(path, "hi0"); size = 200; | ||||
| @@ -261,8 +261,8 @@ code = ''' | ||||
|     uint8_t wbuffer[1024]; | ||||
|     uint8_t rbuffer[1024]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write hi0 200 | ||||
|     sprintf(path, "hi0"); size = 200; | ||||
| @@ -350,8 +350,8 @@ code = ''' | ||||
|     uint8_t wbuffer[1024]; | ||||
|     uint8_t rbuffer[1024]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write hi0 200 | ||||
|     sprintf(path, "hi0"); size = 200; | ||||
| @@ -454,8 +454,8 @@ code = ''' | ||||
|     uint8_t wbuffer[1024]; | ||||
|     uint8_t rbuffer[1024]; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write hi0 200 | ||||
|     sprintf(path, "hi0"); size = 200; | ||||
| @@ -549,9 +549,9 @@ code = ''' | ||||
|  | ||||
| [[case]] # create too big | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(path, 'm', 200); | ||||
|     path[200] = '\0'; | ||||
|  | ||||
| @@ -574,9 +574,9 @@ code = ''' | ||||
|  | ||||
| [[case]] # resize too big | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     memset(path, 'm', 200); | ||||
|     path[200] = '\0'; | ||||
|  | ||||
|   | ||||
| @@ -9,10 +9,10 @@ define.INVALSET = [0x3, 0x1, 0x2] | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // change tail-pointer to invalid pointers | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
|     lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( | ||||
| @@ -23,7 +23,7 @@ code = ''' | ||||
|     lfs_deinit(&lfs) => 0; | ||||
|  | ||||
|     // test that mount fails gracefully | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
|     lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|  | ||||
| [[case]] # invalid dir pointer test | ||||
| @@ -31,14 +31,14 @@ define.INVALSET = [0x3, 0x1, 0x2] | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // make a dir | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "dir_here") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // change the dir pointer to be invalid | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
|     // make sure id 1 == our directory | ||||
| @@ -57,7 +57,7 @@ code = ''' | ||||
|  | ||||
|     // test that accessing our bad dir fails, note there's a number | ||||
|     // of ways to access the dir, some can fail, but some don't | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "dir_here", &info) => 0; | ||||
|     assert(strcmp(info.name, "dir_here") == 0); | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -77,16 +77,16 @@ in = "lfs.c" | ||||
| define.SIZE = [10, 1000, 100000] # faked file size | ||||
| code = ''' | ||||
|     // create littlefs | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // make a file | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "file_here", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // change the file pointer to be invalid | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
|     // make sure id 1 == our file | ||||
| @@ -103,7 +103,7 @@ code = ''' | ||||
|  | ||||
|     // test that accessing our bad file fails, note there's a number | ||||
|     // of ways to access the dir, some can fail, but some don't | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "file_here", &info) => 0; | ||||
|     assert(strcmp(info.name, "file_here") == 0); | ||||
|     assert(info.type == LFS_TYPE_REG); | ||||
| @@ -125,9 +125,9 @@ define.SIZE = ['2*LFS_BLOCK_SIZE', '3*LFS_BLOCK_SIZE', '4*LFS_BLOCK_SIZE'] | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // make a file | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "file_here", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     for (int i = 0; i < SIZE; i++) { | ||||
| @@ -137,7 +137,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     // change pointer in CTZ skip-list to be invalid | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
|     // make sure id 1 == our file and get our CTZ structure | ||||
| @@ -154,17 +154,17 @@ code = ''' | ||||
|     lfs_ctz_fromle32(&ctz); | ||||
|     // rewrite block to contain bad pointer | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     uint32_t bad = lfs_tole32(0xcccccccc); | ||||
|     memcpy(&bbuffer[0], &bad, sizeof(bad)); | ||||
|     memcpy(&bbuffer[4], &bad, sizeof(bad)); | ||||
|     cfg.erase(&cfg, ctz.head) => 0; | ||||
|     cfg.prog(&cfg, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_erase(&bd, ctz.head) => 0; | ||||
|     lfs_testbd_prog(&bd, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_deinit(&lfs) => 0; | ||||
|  | ||||
|     // test that accessing our bad file fails, note there's a number | ||||
|     // of ways to access the dir, some can fail, but some don't | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "file_here", &info) => 0; | ||||
|     assert(strcmp(info.name, "file_here") == 0); | ||||
|     assert(info.type == LFS_TYPE_REG); | ||||
| @@ -187,10 +187,10 @@ define.INVALSET = [0x3, 0x1, 0x2] | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // create an invalid gstate | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
|     lfs_fs_prepmove(&lfs, 1, (lfs_block_t [2]){ | ||||
| @@ -202,7 +202,7 @@ code = ''' | ||||
|     // test that mount fails gracefully | ||||
|     // mount may not fail, but our first alloc should fail when | ||||
|     // we try to fix the gstate | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "should_fail") => LFS_ERR_CORRUPT; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| @@ -213,10 +213,10 @@ code = ''' | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // change tail-pointer to point to ourself | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
|     lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( | ||||
| @@ -225,20 +225,20 @@ code = ''' | ||||
|     lfs_deinit(&lfs) => 0; | ||||
|  | ||||
|     // test that mount fails gracefully | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
|     lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|  | ||||
| [[case]] # metadata-pair threaded-list 2-length loop test | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs with child dir | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "child") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // find child | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_block_t pair[2]; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
| @@ -255,20 +255,20 @@ code = ''' | ||||
|     lfs_deinit(&lfs) => 0; | ||||
|  | ||||
|     // test that mount fails gracefully | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
|     lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|  | ||||
| [[case]] # metadata-pair threaded-list 1-length child loop test | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     // create littlefs with child dir | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "child") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // find child | ||||
|     lfs_init(&lfs, &cfg) => 0; | ||||
|     lfs_initcommon(&lfs, &cfg) => 0; | ||||
|     lfs_mdir_t mdir; | ||||
|     lfs_block_t pair[2]; | ||||
|     lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; | ||||
| @@ -284,5 +284,5 @@ code = ''' | ||||
|     lfs_deinit(&lfs) => 0; | ||||
|  | ||||
|     // test that mount fails gracefully | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
|     lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|   | ||||
| @@ -11,14 +11,14 @@ define.LFS_BADBLOCK_BEHAVIOR = [ | ||||
| ] | ||||
| define.FILES = 10 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "roadrunner") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     uint32_t cycle = 0; | ||||
|     while (true) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (uint32_t i = 0; i < FILES; i++) { | ||||
|             // chose name, roughly random seed, and random 2^n size | ||||
|             sprintf(path, "roadrunner/test%d", i); | ||||
| @@ -71,7 +71,7 @@ code = ''' | ||||
|  | ||||
| exhausted: | ||||
|     // should still be readable | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (uint32_t i = 0; i < FILES; i++) { | ||||
|         // check for errors | ||||
|         sprintf(path, "roadrunner/test%d", i); | ||||
| @@ -96,11 +96,11 @@ define.LFS_BADBLOCK_BEHAVIOR = [ | ||||
| ] | ||||
| define.FILES = 10 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     uint32_t cycle = 0; | ||||
|     while (true) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (uint32_t i = 0; i < FILES; i++) { | ||||
|             // chose name, roughly random seed, and random 2^n size | ||||
|             sprintf(path, "test%d", i); | ||||
| @@ -153,7 +153,7 @@ code = ''' | ||||
|  | ||||
| exhausted: | ||||
|     // should still be readable | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (uint32_t i = 0; i < FILES; i++) { | ||||
|         // check for errors | ||||
|         sprintf(path, "test%d", i); | ||||
| @@ -180,18 +180,18 @@ code = ''' | ||||
|  | ||||
|     for (int run = 0; run < 2; run++) { | ||||
|         for (lfs_block_t b = 0; b < LFS_BLOCK_COUNT; b++) { | ||||
|             lfs_testbd_setwear(&cfg, b, | ||||
|             lfs_testbd_setwear(&bd, b, | ||||
|                     (b < run_block_count[run]) ? 0 : LFS_ERASE_CYCLES) => 0; | ||||
|         } | ||||
|  | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mkdir(&lfs, "roadrunner") => 0; | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         uint32_t cycle = 0; | ||||
|         while (true) { | ||||
|             lfs_mount(&lfs, &cfg) => 0; | ||||
|             lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|             for (uint32_t i = 0; i < FILES; i++) { | ||||
|                 // chose name, roughly random seed, and random 2^n size | ||||
|                 sprintf(path, "roadrunner/test%d", i); | ||||
| @@ -244,7 +244,7 @@ code = ''' | ||||
|  | ||||
| exhausted: | ||||
|         // should still be readable | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (uint32_t i = 0; i < FILES; i++) { | ||||
|             // check for errors | ||||
|             sprintf(path, "roadrunner/test%d", i); | ||||
| @@ -272,15 +272,15 @@ code = ''' | ||||
|  | ||||
|     for (int run = 0; run < 2; run++) { | ||||
|         for (lfs_block_t b = 0; b < LFS_BLOCK_COUNT; b++) { | ||||
|             lfs_testbd_setwear(&cfg, b, | ||||
|             lfs_testbd_setwear(&bd, b, | ||||
|                     (b < run_block_count[run]) ? 0 : LFS_ERASE_CYCLES) => 0; | ||||
|         } | ||||
|  | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|         uint32_t cycle = 0; | ||||
|         while (true) { | ||||
|             lfs_mount(&lfs, &cfg) => 0; | ||||
|             lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|             for (uint32_t i = 0; i < FILES; i++) { | ||||
|                 // chose name, roughly random seed, and random 2^n size | ||||
|                 sprintf(path, "test%d", i); | ||||
| @@ -333,7 +333,7 @@ code = ''' | ||||
|  | ||||
| exhausted: | ||||
|         // should still be readable | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (uint32_t i = 0; i < FILES; i++) { | ||||
|             // check for errors | ||||
|             sprintf(path, "test%d", i); | ||||
| @@ -358,14 +358,14 @@ define.CYCLES = 100 | ||||
| define.FILES = 10 | ||||
| if = 'LFS_BLOCK_CYCLES < CYCLES/10' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "roadrunner") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     uint32_t cycle = 0; | ||||
|     while (cycle < CYCLES) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         for (uint32_t i = 0; i < FILES; i++) { | ||||
|             // chose name, roughly random seed, and random 2^n size | ||||
|             sprintf(path, "roadrunner/test%d", i); | ||||
| @@ -418,7 +418,7 @@ code = ''' | ||||
|  | ||||
| exhausted: | ||||
|     // should still be readable | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (uint32_t i = 0; i < FILES; i++) { | ||||
|         // check for errors | ||||
|         sprintf(path, "roadrunner/test%d", i); | ||||
| @@ -434,7 +434,7 @@ exhausted: | ||||
|     lfs_testbd_wear_t maxwear = 0; | ||||
|     // skip 0 and 1 as superblock movement is intentionally avoided | ||||
|     for (lfs_block_t b = 2; b < LFS_BLOCK_COUNT; b++) { | ||||
|         lfs_testbd_wear_t wear = lfs_testbd_getwear(&cfg, b); | ||||
|         lfs_testbd_wear_t wear = lfs_testbd_getwear(&bd, b); | ||||
|         printf("%08x: wear %d\n", b, wear); | ||||
|         assert(wear >= 0); | ||||
|         if (wear < minwear) { | ||||
| @@ -453,7 +453,7 @@ exhausted: | ||||
|     // find standard deviation^2 | ||||
|     lfs_testbd_wear_t dev2 = 0; | ||||
|     for (lfs_block_t b = 2; b < LFS_BLOCK_COUNT; b++) { | ||||
|         lfs_testbd_wear_t wear = lfs_testbd_getwear(&cfg, b); | ||||
|         lfs_testbd_wear_t wear = lfs_testbd_getwear(&bd, b); | ||||
|         assert(wear >= 0); | ||||
|         lfs_testbd_swear_t diff = wear - avgwear; | ||||
|         dev2 += diff*diff; | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
|  | ||||
| [[case]] # simple file test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     size = strlen("Hello World!")+1; | ||||
| @@ -11,7 +11,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_read(&lfs, &file, buffer, size) => size; | ||||
|     assert(strcmp((char*)buffer, "Hello World!") == 0); | ||||
| @@ -23,10 +23,10 @@ code = ''' | ||||
| define.SIZE = [32, 8192, 262144, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 33, 1, 1023] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
| @@ -41,7 +41,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE; | ||||
|     srand(1); | ||||
| @@ -62,10 +62,10 @@ define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 1] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
| @@ -80,7 +80,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1; | ||||
|     srand(1); | ||||
| @@ -96,7 +96,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // rewrite | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY) => 0; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
| @@ -110,7 +110,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => lfs_max(SIZE1, SIZE2); | ||||
|     srand(2); | ||||
| @@ -144,10 +144,10 @@ define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 1] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
| @@ -162,7 +162,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1; | ||||
|     srand(1); | ||||
| @@ -178,7 +178,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // append | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_APPEND) => 0; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
| @@ -192,7 +192,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1 + SIZE2; | ||||
|     srand(1); | ||||
| @@ -221,10 +221,10 @@ define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 1] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
| @@ -239,7 +239,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1; | ||||
|     srand(1); | ||||
| @@ -255,7 +255,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // truncate | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_TRUNC) => 0; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
| @@ -269,7 +269,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE2; | ||||
|     srand(2); | ||||
| @@ -290,10 +290,10 @@ define.SIZE = [32, 0, 7, 2049] | ||||
| define.CHUNKSIZE = [31, 16, 65] | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); | ||||
| @@ -344,10 +344,10 @@ define = [ | ||||
| ] | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); | ||||
| @@ -406,9 +406,9 @@ code = ''' | ||||
| [[case]] # many files | ||||
| define.N = 300 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // create N files of 7 bytes | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file_%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
| @@ -431,9 +431,9 @@ code = ''' | ||||
| [[case]] # many files with power cycle | ||||
| define.N = 300 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // create N files of 7 bytes | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file_%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
| @@ -446,7 +446,7 @@ code = ''' | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         char rbuffer[1024]; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
|         lfs_file_read(&lfs, &file, rbuffer, size) => size; | ||||
|         assert(strcmp(rbuffer, wbuffer) == 0); | ||||
| @@ -459,10 +459,10 @@ code = ''' | ||||
| define.N = 300 | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     // create N files of 7 bytes | ||||
|     for (int i = 0; i < N; i++) { | ||||
|   | ||||
| @@ -5,8 +5,8 @@ define.FILES = [4, 10, 26] | ||||
| code = ''' | ||||
|     lfs_file_t files[FILES]; | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int j = 0; j < FILES; j++) { | ||||
|         sprintf(path, "%c", alphas[j]); | ||||
|         lfs_file_open(&lfs, &files[j], path, | ||||
| @@ -64,8 +64,8 @@ define.SIZE = [10, 100] | ||||
| define.FILES = [4, 10, 26] | ||||
| code = ''' | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int j = 0; j < FILES; j++) { | ||||
|         sprintf(path, "%c", alphas[j]); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
| @@ -77,7 +77,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "zzz", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     for (int j = 0; j < FILES; j++) { | ||||
|         lfs_file_write(&lfs, &file, (const void*)"~", 1) => 1; | ||||
| @@ -115,8 +115,8 @@ code = ''' | ||||
| [[case]] # remove inconveniently test | ||||
| define.SIZE = [10, 100] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_t files[3]; | ||||
|     lfs_file_open(&lfs, &files[0], "e", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     lfs_file_open(&lfs, &files[1], "f", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
| @@ -180,10 +180,10 @@ code = ''' | ||||
|     lfs_file_t files[FILES]; | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
|  | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int j = 0; j < FILES; j++) { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| [[case]] # move file | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -13,11 +13,11 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -57,8 +57,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # noop move, yes this is legal | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "hi") => 0; | ||||
|     lfs_rename(&lfs, "hi", "hi") => 0; | ||||
|     lfs_mkdir(&lfs, "hi/hi") => 0; | ||||
| @@ -74,8 +74,8 @@ code = ''' | ||||
| [[case]] # move file corrupt source | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -87,28 +87,28 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // corrupt the source | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -150,8 +150,8 @@ code = ''' | ||||
| in = "lfs.c" | ||||
| if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -163,44 +163,44 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // corrupt the source | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     // corrupt the destination | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||
|     block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -242,8 +242,8 @@ code = ''' | ||||
| in = "lfs.c" | ||||
| if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -255,49 +255,49 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // corrupt the source | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     // corrupt the destination | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||
|     block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     // continue move | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -338,10 +338,10 @@ code = ''' | ||||
| [[case]] # simple reentrant move file | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     err = lfs_mkdir(&lfs, "a"); | ||||
|     assert(!err || err == LFS_ERR_EXIST); | ||||
| @@ -354,7 +354,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     while (true) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         // there should never exist _2_ hello files | ||||
|         int count = 0; | ||||
|         if (lfs_stat(&lfs, "a/hello", &info) == 0) { | ||||
| @@ -384,7 +384,7 @@ code = ''' | ||||
|         assert(count <= 1); | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         if (lfs_stat(&lfs, "a/hello", &info) == 0 && info.size > 0) { | ||||
|             lfs_rename(&lfs, "a/hello", "b/hello") => 0; | ||||
|         } else if (lfs_stat(&lfs, "b/hello", &info) == 0) { | ||||
| @@ -407,7 +407,7 @@ code = ''' | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|     } | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -447,8 +447,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # move dir | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -459,11 +459,11 @@ code = ''' | ||||
|     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -513,8 +513,8 @@ code = ''' | ||||
| [[case]] # move dir corrupt source | ||||
| in = "lfs.c" | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -525,28 +525,28 @@ code = ''' | ||||
|     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // corrupt the source | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -597,8 +597,8 @@ code = ''' | ||||
| in = "lfs.c" | ||||
| if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -609,44 +609,44 @@ code = ''' | ||||
|     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // corrupt the source | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     // corrupt the destination | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||
|     block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -697,8 +697,8 @@ code = ''' | ||||
| in = "lfs.c" | ||||
| if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -709,49 +709,49 @@ code = ''' | ||||
|     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // corrupt the source | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     // corrupt the destination | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||
|     block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     // continue move | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -801,10 +801,10 @@ code = ''' | ||||
| [[case]] # simple reentrant move dir | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     err = lfs_mkdir(&lfs, "a"); | ||||
|     assert(!err || err == LFS_ERR_EXIST); | ||||
| @@ -817,7 +817,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     while (true) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         // there should never exist _2_ hi directories | ||||
|         int count = 0; | ||||
|         if (lfs_stat(&lfs, "a/hi", &info) == 0) { | ||||
| @@ -843,7 +843,7 @@ code = ''' | ||||
|         assert(count <= 1); | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         if (lfs_stat(&lfs, "a/hi", &info) == 0) { | ||||
|             lfs_rename(&lfs, "a/hi", "b/hi") => 0; | ||||
|         } else if (lfs_stat(&lfs, "b/hi", &info) == 0) { | ||||
| @@ -868,7 +868,7 @@ code = ''' | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|     } | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
| @@ -917,8 +917,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # move state stealing | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "a") => 0; | ||||
|     lfs_mkdir(&lfs, "b") => 0; | ||||
|     lfs_mkdir(&lfs, "c") => 0; | ||||
| @@ -930,17 +930,17 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "a/hello", "b/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "b/hello", "c/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "c/hello", "d/hello") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||
|     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||
|     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||
| @@ -954,12 +954,12 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "b") => 0; | ||||
|     lfs_remove(&lfs, "c") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "a", &info) => 0; | ||||
|     lfs_stat(&lfs, "b", &info) => LFS_ERR_NOENT; | ||||
|     lfs_stat(&lfs, "c", &info) => LFS_ERR_NOENT; | ||||
| @@ -981,8 +981,8 @@ code = ''' | ||||
| # Other specific corner cases | ||||
| [[case]] # create + delete in same commit with neighbors | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // littlefs keeps files sorted, so we know the order these will be in | ||||
|     lfs_file_open(&lfs, &file, "/1.move_me", | ||||
| @@ -1127,8 +1127,8 @@ code = ''' | ||||
| # Other specific corner cases | ||||
| [[case]] # create + delete + delete in same commit with neighbors | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // littlefs keeps files sorted, so we know the order these will be in | ||||
|     lfs_file_open(&lfs, &file, "/1.move_me", | ||||
| @@ -1283,8 +1283,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # create + delete in different dirs with neighbors | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // littlefs keeps files sorted, so we know the order these will be in | ||||
|     lfs_mkdir(&lfs, "/dir.1") => 0; | ||||
| @@ -1523,8 +1523,8 @@ in = "lfs.c" | ||||
| define.RELOCATIONS = 'range(0x3+1)' | ||||
| define.LFS_ERASE_CYCLES = 0xffffffff | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mkdir(&lfs, "/parent") => 0; | ||||
|     lfs_mkdir(&lfs, "/parent/child") => 0; | ||||
| @@ -1569,14 +1569,14 @@ code = ''' | ||||
|     // force specific directories to relocate | ||||
|     if (RELOCATIONS & 0x1) { | ||||
|         lfs_dir_open(&lfs, &dir, "/parent"); | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_dir_close(&lfs, &dir) => 0; | ||||
|     } | ||||
|     if (RELOCATIONS & 0x2) { | ||||
|         lfs_dir_open(&lfs, &dir, "/parent/child"); | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_dir_close(&lfs, &dir) => 0; | ||||
|     } | ||||
|  | ||||
| @@ -1660,8 +1660,8 @@ in = "lfs.c" | ||||
| define.RELOCATIONS = 'range(0x7+1)' | ||||
| define.LFS_ERASE_CYCLES = 0xffffffff | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mkdir(&lfs, "/parent") => 0; | ||||
|     lfs_mkdir(&lfs, "/parent/child") => 0; | ||||
| @@ -1707,20 +1707,20 @@ code = ''' | ||||
|     // force specific directories to relocate | ||||
|     if (RELOCATIONS & 0x1) { | ||||
|         lfs_dir_open(&lfs, &dir, "/parent"); | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_dir_close(&lfs, &dir) => 0; | ||||
|     } | ||||
|     if (RELOCATIONS & 0x2) { | ||||
|         lfs_dir_open(&lfs, &dir, "/parent/sibling"); | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_dir_close(&lfs, &dir) => 0; | ||||
|     } | ||||
|     if (RELOCATIONS & 0x4) { | ||||
|         lfs_dir_open(&lfs, &dir, "/parent/child"); | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; | ||||
|         lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; | ||||
|         lfs_dir_close(&lfs, &dir) => 0; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
| in = "lfs.c" | ||||
| if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "parent") => 0; | ||||
|     lfs_mkdir(&lfs, "parent/orphan") => 0; | ||||
|     lfs_mkdir(&lfs, "parent/child") => 0; | ||||
| @@ -13,29 +13,29 @@ code = ''' | ||||
|     // corrupt the child's most recent commit, this should be the update | ||||
|     // to the linked-list entry, which should orphan the orphan. Note this | ||||
|     // makes a lot of assumptions about the remove operation. | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "parent/child") => 0; | ||||
|     lfs_block_t block = dir.m.pair[0]; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||
|     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     int off = LFS_BLOCK_SIZE-1; | ||||
|     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||
|         off -= 1; | ||||
|     } | ||||
|     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||
|     cfg.erase(&cfg, block) => 0; | ||||
|     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     cfg.sync(&cfg) => 0; | ||||
|     lfs_testbd_erase(&bd, block) => 0; | ||||
|     lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||
|     lfs_testbd_sync(&bd) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||
|     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||
|     lfs_fs_size(&lfs) => 8; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||
|     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||
|     lfs_fs_size(&lfs) => 8; | ||||
| @@ -48,7 +48,7 @@ code = ''' | ||||
|     lfs_fs_size(&lfs) => 8; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||
|     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||
|     lfs_stat(&lfs, "parent/otherchild", &info) => 0; | ||||
| @@ -66,10 +66,10 @@ define = [ | ||||
|     {FILES=3,  DEPTH=3, CYCLES=20}, | ||||
| ] | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     srand(1); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
|  | ||||
| [[case]] # simple path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "tea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||
| @@ -23,8 +23,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # redundant slashes | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "tea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||
| @@ -47,8 +47,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # dot path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "tea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||
| @@ -73,8 +73,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # dot dot path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "tea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||
| @@ -103,8 +103,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # trailing dot path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "tea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||
| @@ -125,8 +125,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # leading dot path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, ".milk") => 0; | ||||
|     lfs_stat(&lfs, ".milk", &info) => 0; | ||||
|     strcmp(info.name, ".milk") => 0; | ||||
| @@ -137,8 +137,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # root dot dot path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "tea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/hottea") => 0; | ||||
|     lfs_mkdir(&lfs, "tea/warmtea") => 0; | ||||
| @@ -161,8 +161,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # invalid path tests | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg); | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg); | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "dirt", &info) => LFS_ERR_NOENT; | ||||
|     lfs_stat(&lfs, "dirt/ground", &info) => LFS_ERR_NOENT; | ||||
|     lfs_stat(&lfs, "dirt/ground/earth", &info) => LFS_ERR_NOENT; | ||||
| @@ -182,8 +182,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # root operations | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "/", &info) => 0; | ||||
|     assert(strcmp(info.name, "/") == 0); | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -198,8 +198,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # root representations | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "/", &info) => 0; | ||||
|     assert(strcmp(info.name, "/") == 0); | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -223,8 +223,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # superblock conflict test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "littlefs") => LFS_ERR_NOENT; | ||||
|  | ||||
| @@ -239,8 +239,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # max path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "coffee") => 0; | ||||
|     lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; | ||||
|     lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; | ||||
| @@ -263,8 +263,8 @@ code = ''' | ||||
|  | ||||
| [[case]] # really big path test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "coffee") => 0; | ||||
|     lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; | ||||
|     lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; | ||||
|   | ||||
| @@ -4,9 +4,9 @@ define.ITERATIONS = 20 | ||||
| define.COUNT = 10 | ||||
| define.LFS_BLOCK_CYCLES = [8, 1] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // fill up filesystem so only ~16 blocks are left | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|     memset(buffer, 0, 512); | ||||
|     while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { | ||||
| @@ -17,7 +17,7 @@ code = ''' | ||||
|     lfs_mkdir(&lfs, "child") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int j = 0; j < ITERATIONS; j++) { | ||||
|         for (int i = 0; i < COUNT; i++) { | ||||
|             sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); | ||||
| @@ -47,7 +47,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "child") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
| @@ -70,9 +70,9 @@ define.ITERATIONS = 20 | ||||
| define.COUNT = 10 | ||||
| define.LFS_BLOCK_CYCLES = [8, 1] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     // fill up filesystem so only ~16 blocks are left | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|     memset(buffer, 0, 512); | ||||
|     while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { | ||||
| @@ -83,7 +83,7 @@ code = ''' | ||||
|     lfs_mkdir(&lfs, "child") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int j = 0; j < ITERATIONS; j++) { | ||||
|         for (int i = 0; i < COUNT; i++) { | ||||
|             sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); | ||||
| @@ -155,10 +155,10 @@ define = [ | ||||
|     {FILES=3,  DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1}, | ||||
| ] | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     srand(1); | ||||
| @@ -217,10 +217,10 @@ define = [ | ||||
|     {FILES=3,  DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1}, | ||||
| ] | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     srand(1); | ||||
|   | ||||
| @@ -9,8 +9,8 @@ define = [ | ||||
|     {COUNT=4,   SKIP=2}, | ||||
| ] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||
|     size = strlen("kittycatcat"); | ||||
| @@ -21,7 +21,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY) => 0; | ||||
|  | ||||
|     lfs_soff_t pos = -1; | ||||
| @@ -78,8 +78,8 @@ define = [ | ||||
|     {COUNT=4,   SKIP=2}, | ||||
| ] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||
|     size = strlen("kittycatcat"); | ||||
| @@ -90,7 +90,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0; | ||||
|  | ||||
|     lfs_soff_t pos = -1; | ||||
| @@ -133,8 +133,8 @@ code = ''' | ||||
| define.COUNT = 132 | ||||
| define.OFFSETS = '"{512, 1020, 513, 1021, 511, 1019, 1441}"' | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||
|     size = strlen("kittycatcat"); | ||||
| @@ -145,7 +145,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0; | ||||
|  | ||||
|     size = strlen("hedgehoghog"); | ||||
| @@ -193,8 +193,8 @@ define = [ | ||||
|     {COUNT=4,   SKIP=3}, | ||||
| ] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||
|     size = strlen("kittycatcat"); | ||||
| @@ -204,7 +204,7 @@ code = ''' | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0; | ||||
|  | ||||
|     size = strlen("kittycatcat"); | ||||
| @@ -241,8 +241,8 @@ code = ''' | ||||
| [[case]] # inline write and seek | ||||
| define.SIZE = [2, 4, 128, 132] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "tinykitty", | ||||
|             LFS_O_RDWR | LFS_O_CREAT) => 0; | ||||
|     int j = 0; | ||||
| @@ -310,10 +310,10 @@ code = ''' | ||||
| define.COUNT = [4, 64, 128] | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     err = lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY); | ||||
|     assert(!err || err == LFS_ERR_NOENT); | ||||
|   | ||||
| @@ -1,37 +1,37 @@ | ||||
| [[case]] # simple formatting test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # mount/unmount | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # reentrant format | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # invalid mount | ||||
| code = ''' | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
|     lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|  | ||||
| [[case]] # expanding superblock | ||||
| define.LFS_BLOCK_CYCLES = [32, 33, 1] | ||||
| define.N = [10, 100, 1000] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         lfs_file_open(&lfs, &file, "dummy", | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
| @@ -44,7 +44,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // one last check after power-cycle | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "dummy", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
| @@ -58,9 +58,9 @@ code = ''' | ||||
| define.LFS_BLOCK_CYCLES = [32, 33, 1] | ||||
| define.N = [10, 100, 1000] | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|         // remove lingering dummy? | ||||
|         err = lfs_stat(&lfs, "dummy", &info); | ||||
|         assert(err == 0 || (err == LFS_ERR_NOENT && i == 0)); | ||||
| @@ -80,7 +80,7 @@ code = ''' | ||||
|     } | ||||
|  | ||||
|     // one last check after power-cycle | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|     assert(strcmp(info.name, "dummy") == 0); | ||||
|     assert(info.type == LFS_TYPE_REG); | ||||
| @@ -92,10 +92,10 @@ define.LFS_BLOCK_CYCLES = [2, 1] | ||||
| define.N = 24 | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
| @@ -119,7 +119,7 @@ code = ''' | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // one last check after power-cycle | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|     assert(strcmp(info.name, "dummy") == 0); | ||||
|     assert(info.type == LFS_TYPE_REG); | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
| define.MEDIUMSIZE = [32, 2048] | ||||
| define.LARGESIZE = 8192 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldynoop", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|  | ||||
| @@ -17,7 +17,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|      | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDWR) => 0; | ||||
|     lfs_file_size(&lfs, &file) => LARGESIZE; | ||||
|  | ||||
| @@ -27,7 +27,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => MEDIUMSIZE; | ||||
|  | ||||
| @@ -46,8 +46,8 @@ code = ''' | ||||
| define.MEDIUMSIZE = [32, 2048] | ||||
| define.LARGESIZE = 8192 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldyread", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|  | ||||
| @@ -61,7 +61,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDWR) => 0; | ||||
|     lfs_file_size(&lfs, &file) => LARGESIZE; | ||||
|  | ||||
| @@ -78,7 +78,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => MEDIUMSIZE; | ||||
|  | ||||
| @@ -95,12 +95,12 @@ code = ''' | ||||
|  | ||||
| [[case]] # write, truncate, and read | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "sequence", | ||||
|             LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC) => 0; | ||||
|  | ||||
|     size = lfs_min(lfs.cfg->cache_size, sizeof(buffer)/2); | ||||
|     size = lfs_min(lfs.cfg.cache_size, sizeof(buffer)/2); | ||||
|     lfs_size_t qsize = size / 4; | ||||
|     uint8_t *wb = buffer; | ||||
|     uint8_t *rb = buffer + size; | ||||
| @@ -149,8 +149,8 @@ code = ''' | ||||
| define.MEDIUMSIZE = [32, 2048] | ||||
| define.LARGESIZE = 8192 | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldywrite", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|  | ||||
| @@ -164,7 +164,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDWR) => 0; | ||||
|     lfs_file_size(&lfs, &file) => LARGESIZE; | ||||
|  | ||||
| @@ -181,7 +181,7 @@ code = ''' | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => MEDIUMSIZE; | ||||
|  | ||||
| @@ -202,10 +202,10 @@ define.MEDIUMSIZE = [32, 1024] | ||||
| define.LARGESIZE = 2048 | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     err = lfs_mountcfg(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|         lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     err = lfs_file_open(&lfs, &file, "baldy", LFS_O_RDONLY); | ||||
|     assert(!err || err == LFS_ERR_NOENT); | ||||
| @@ -312,8 +312,8 @@ code = ''' | ||||
|     const lfs_off_t *hotsizes   = configs[CONFIG].hotsizes; | ||||
|     const lfs_off_t *coldsizes  = configs[CONFIG].coldsizes; | ||||
|  | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_formatcfg(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     for (unsigned i = 0; i < COUNT; i++) { | ||||
|         sprintf(path, "hairyhead%d", i); | ||||
| @@ -340,7 +340,7 @@ code = ''' | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     for (unsigned i = 0; i < COUNT; i++) { | ||||
|         sprintf(path, "hairyhead%d", i); | ||||
| @@ -367,7 +367,7 @@ code = ''' | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mountcfg(&lfs, &cfg) => 0; | ||||
|  | ||||
|     for (unsigned i = 0; i < COUNT; i++) { | ||||
|         sprintf(path, "hairyhead%d", i); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user