Compare commits

..

5 Commits

Author SHA1 Message Date
Christopher Haster
0aba71d0d6 Fixed single unchecked bit during commit verification
This bug was exposed by the bad-block tests due to changes to block
allocation, but could have been hit before these changes.

In flash, when blocks fail, they don't fail in a predictable manner. To
account for this, the bad-block tests check a number of failure
behaviors. The interesting one here is "LFS_TESTBD_BADBLOCK_ERASENOOP",
in which bad blocks can not be erased or programmed, and are stuck with
the data written at the time the blocks go bad.

This is actually a pretty realistic failure behavior, since flash needs a
large voltage to force the electrons of the floating gates. Though
realistically, such a failure would like corrupt the data a bit, not leave the
underlying data perfectly intact.

LFS_TESTBD_BADBLOCK_ERASENOOP is rather interesting to test for because it
means bad blocks can end up with perfectly valid CRCs after a failed write,
confusing littlefs.

---

In this case, we had the perfect series of operations such that a test
was repeatedly writing the same sequence of metadata commits to the same
block, which eventually goes bad, leaving the block stuck with metadata
that occurs later in the sequence.

What this means is that after the first commit, the metadata block
contained both the first and second commits, even though the loop in the
test hadn't reached that point yet.

expected       actual
.----------.  .----------.
| commit 1 |  | commit 1 |
| crc 1    |  | crc 1    |
|          |  | commit 2 <-- (from previous iteration)
|          |  | crc 2    |
'----------'  '----------'

To protect against this, littlefs normally compares the written CRC
against the expected CRC, but because this was the exact same data that
it was going to write, this CRCs end up the same.

Ah! But doesn't littlefs also encode the state of the next page to keep
track of if the next page has been erased or not? Wouldn't that change
between iterations?

It does! In a single bit in the CRC-tag. But thanks to some incorrect
logic attempting to avoid an extra condition in the loop for writing out
padding commits, the CRC that littlefs checked against was the CRC
immediately before we include the "is-next-page-erased" bit.

Changing the verification check to use the same CRC as what is used to
verify commits on fetch solves this problem.
2020-11-22 15:07:16 -06:00
Christopher Haster
0ea2871e24 Fixed typo in scripts/readtree.py
Not sure how this went unnoticed, I guess this is the first bug that
needed in-depth inspection after the a last-minute argument cleanup
in the debug scripts.
2020-11-22 15:05:22 -06:00
Christopher Haster
f215027fd4 Switched to CRC as seed collection function instead of xor
As noted by gtaska, we are sitting on a better hash-combining function
than xor: CRC. Previous issues with xor were solvable, but relying on
xor for this isn't really worth the risk when we already have a CRC
function readily available.

To quote a study found by gtaska:

https://michiel.buddingh.eu/distribution-of-hash-values

> CRC32 seems to score really well, but its graph is skewed by the results
> of Dataset 5 (binary numbers), which may or may not be too synthetic to
> be considered a fair benchmark. But even if you substract the results
> from that test, it does not fare significantly worse than other,
> cryptographic hash functions.
2020-11-20 00:38:41 -06:00
Christopher Haster
1ae4b36f2a Removed unnecessary randomization of offsets in lfs_alloc_reset
On first read, randomizing the allocators offset may seem appropriate
for lfs_alloc_reset. However, it ends up using the filesystem-fed
pseudorandom seed in situations it wasn't designed for.

As noted by gtaska, the combination of using xors for feeding the seed
and multiple traverses of the same CRCs can cause the seed to flip to
zeros with concerning frequency.

Removed the randomization from lfs_alloc_reset, leaving it in only
lfs_mount.

Found by gtaska
2020-11-20 00:18:13 -06:00
Christopher Haster
480cdd9f81 Fixed incorrect modulus in lfs_alloc_reset
Modulus of the offset by block_size was clearly a typo, and should be
block_count. Interesting to note that later moduluses during alloc
calculations prevents this from breaking anything, but as gtaska notes it
could skew the wear-leveling distribution.

Found by guiserle and gtaska
2020-11-20 00:02:19 -06:00
30 changed files with 1123 additions and 1386 deletions

View File

@@ -208,31 +208,6 @@ jobs:
script: script:
- make test TFLAGS+="-k --valgrind" - 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 # self-host with littlefs-fuse for fuzz test
- stage: test - stage: test
env: env:

View File

@@ -39,7 +39,7 @@ lfs_t lfs;
lfs_file_t file; lfs_file_t file;
// configuration of the filesystem is provided by this struct // configuration of the filesystem is provided by this struct
const struct lfs_cfg cfg = { const struct lfs_config cfg = {
// block device operations // block device operations
.read = user_provided_block_device_read, .read = user_provided_block_device_read,
.prog = user_provided_block_device_prog, .prog = user_provided_block_device_prog,

View File

@@ -10,18 +10,21 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
int lfs_filebd_createcfg(lfs_filebd_t *bd, const char *path, int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path,
const struct lfs_filebd_cfg *cfg) { const struct lfs_filebd_config *bdcfg) {
LFS_FILEBD_TRACE("lfs_filebd_createcfg(%p, \"%s\", %p {" LFS_FILEBD_TRACE("lfs_filebd_createcfg(%p {.context=%p, "
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".erase_size=%"PRIu32", .erase_count=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
".erase_value=%"PRId32"})", "\"%s\", "
(void*)bd, path, (void*)cfg, "%p {.erase_value=%"PRId32"})",
cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, (void*)cfg, cfg->context,
cfg->erase_value); (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
(void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
// copy over config cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
bd->cfg = *cfg; path, (void*)bdcfg, bdcfg->erase_value);
lfs_filebd_t *bd = cfg->context;
bd->cfg = bdcfg;
// open file // open file
bd->fd = open(path, O_RDWR | O_CREAT, 0666); bd->fd = open(path, O_RDWR | O_CREAT, 0666);
@@ -35,8 +38,26 @@ int lfs_filebd_createcfg(lfs_filebd_t *bd, const char *path,
return 0; return 0;
} }
int lfs_filebd_destroy(lfs_filebd_t *bd) { int lfs_filebd_create(const struct lfs_config *cfg, const char *path) {
LFS_FILEBD_TRACE("lfs_filebd_destroy(%p)", (void*)bd); 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 err = close(bd->fd); int err = close(bd->fd);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
@@ -47,25 +68,26 @@ int lfs_filebd_destroy(lfs_filebd_t *bd) {
return 0; return 0;
} }
int lfs_filebd_read(lfs_filebd_t *bd, lfs_block_t block, int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_off_t off, void *buffer, lfs_size_t size) {
LFS_FILEBD_TRACE("lfs_filebd_read(%p, " LFS_FILEBD_TRACE("lfs_filebd_read(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)bd, block, off, buffer, size); (void*)cfg, block, off, buffer, size);
lfs_filebd_t *bd = cfg->context;
// check if read is valid // check if read is valid
LFS_ASSERT(off % bd->cfg.read_size == 0); LFS_ASSERT(off % cfg->read_size == 0);
LFS_ASSERT(size % bd->cfg.read_size == 0); LFS_ASSERT(size % cfg->read_size == 0);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// zero for reproducability (in case file is truncated) // zero for reproducability (in case file is truncated)
if (bd->cfg.erase_value != -1) { if (bd->cfg->erase_value != -1) {
memset(buffer, bd->cfg.erase_value, size); memset(buffer, bd->cfg->erase_value, size);
} }
// read // read
off_t res1 = lseek(bd->fd, off_t res1 = lseek(bd->fd,
(off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); (off_t)block*cfg->block_size + (off_t)off, SEEK_SET);
if (res1 < 0) { if (res1 < 0) {
int err = -errno; int err = -errno;
LFS_FILEBD_TRACE("lfs_filebd_read -> %d", err); LFS_FILEBD_TRACE("lfs_filebd_read -> %d", err);
@@ -83,21 +105,21 @@ int lfs_filebd_read(lfs_filebd_t *bd, lfs_block_t block,
return 0; return 0;
} }
int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block, int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size) { lfs_off_t off, const void *buffer, lfs_size_t size) {
LFS_FILEBD_TRACE("lfs_filebd_prog(%p, " LFS_FILEBD_TRACE("lfs_filebd_prog(%p, 0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", (void*)cfg, block, off, buffer, size);
(void*)bd, block, off, buffer, size); lfs_filebd_t *bd = cfg->context;
// check if write is valid // check if write is valid
LFS_ASSERT(off % bd->cfg.prog_size == 0); LFS_ASSERT(off % cfg->prog_size == 0);
LFS_ASSERT(size % bd->cfg.prog_size == 0); LFS_ASSERT(size % cfg->prog_size == 0);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// check that data was erased? only needed for testing // 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 res1 = lseek(bd->fd,
(off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); (off_t)block*cfg->block_size + (off_t)off, SEEK_SET);
if (res1 < 0) { if (res1 < 0) {
int err = -errno; int err = -errno;
LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err);
@@ -113,13 +135,13 @@ int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block,
return err; return err;
} }
LFS_ASSERT(c == bd->cfg.erase_value); LFS_ASSERT(c == bd->cfg->erase_value);
} }
} }
// program data // program data
off_t res1 = lseek(bd->fd, off_t res1 = lseek(bd->fd,
(off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); (off_t)block*cfg->block_size + (off_t)off, SEEK_SET);
if (res1 < 0) { if (res1 < 0) {
int err = -errno; int err = -errno;
LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err);
@@ -137,23 +159,24 @@ int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block,
return 0; return 0;
} }
int lfs_filebd_erase(lfs_filebd_t *bd, lfs_block_t block) { int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block) {
LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)bd, block); LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)cfg, block);
lfs_filebd_t *bd = cfg->context;
// check if erase is valid // check if erase is valid
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// erase, only needed for testing // erase, 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*bd->cfg.erase_size, SEEK_SET); off_t res1 = lseek(bd->fd, (off_t)block*cfg->block_size, SEEK_SET);
if (res1 < 0) { if (res1 < 0) {
int err = -errno; int err = -errno;
LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err);
return err; return err;
} }
for (lfs_off_t i = 0; i < bd->cfg.erase_size; i++) { for (lfs_off_t i = 0; i < cfg->block_size; i++) {
ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg.erase_value}, 1); ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg->erase_value}, 1);
if (res2 < 0) { if (res2 < 0) {
int err = -errno; int err = -errno;
LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err);
@@ -166,10 +189,10 @@ int lfs_filebd_erase(lfs_filebd_t *bd, lfs_block_t block) {
return 0; return 0;
} }
int lfs_filebd_sync(lfs_filebd_t *bd) { int lfs_filebd_sync(const struct lfs_config *cfg) {
LFS_FILEBD_TRACE("lfs_filebd_sync(%p)", (void*)bd); LFS_FILEBD_TRACE("lfs_filebd_sync(%p)", (void*)cfg);
// file sync // file sync
lfs_filebd_t *bd = cfg->context;
int err = fsync(bd->fd); int err = fsync(bd->fd);
if (err) { if (err) {
err = -errno; err = -errno;

View File

@@ -8,9 +8,11 @@
#define LFS_FILEBD_H #define LFS_FILEBD_H
#include "lfs.h" #include "lfs.h"
#include "lfs_util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
@@ -22,21 +24,7 @@ extern "C" {
#endif #endif
// filebd config (optional) // filebd config (optional)
struct lfs_filebd_cfg { struct lfs_filebd_config {
// 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 // 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 // erases, which can speed up testing by avoiding all the extra block-device
// operations to store the erase value. // operations to store the erase value.
@@ -46,39 +34,40 @@ struct lfs_filebd_cfg {
// filebd state // filebd state
typedef struct lfs_filebd { typedef struct lfs_filebd {
int fd; int fd;
struct lfs_filebd_cfg cfg; const struct lfs_filebd_config *cfg;
} lfs_filebd_t; } lfs_filebd_t;
// Create a file block device using the geometry in lfs_filebd_cfg // Create a file block device using the geometry in lfs_config
int lfs_filebd_createcfg(lfs_filebd_t *bd, const char *path, int lfs_filebd_create(const struct lfs_config *cfg, const char *path);
const struct lfs_filebd_cfg *cfg); int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path,
const struct lfs_filebd_config *bdcfg);
// Clean up memory associated with block device // Clean up memory associated with block device
int lfs_filebd_destroy(lfs_filebd_t *bd); int lfs_filebd_destroy(const struct lfs_config *cfg);
// Read a block // Read a block
int lfs_filebd_read(lfs_filebd_t *bd, lfs_block_t block, int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size); lfs_off_t off, void *buffer, lfs_size_t size);
// Program a block // Program a block
// //
// The block must have previously been erased. // The block must have previously been erased.
int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block, int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size); lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block // Erase a block
// //
// A block must be erased before being programmed. The // A block must be erased before being programmed. The
// state of an erased block is undefined. // state of an erased block is undefined.
int lfs_filebd_erase(lfs_filebd_t *bd, lfs_block_t block); int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block);
// Sync the block device // Sync the block device
int lfs_filebd_sync(lfs_filebd_t *bd); int lfs_filebd_sync(const struct lfs_config *cfg);
#ifdef __cplusplus #ifdef __cplusplus
} } /* extern "C" */
#endif #endif
#endif #endif

View File

@@ -6,24 +6,26 @@
*/ */
#include "bd/lfs_rambd.h" #include "bd/lfs_rambd.h"
int lfs_rambd_createcfg(lfs_rambd_t *bd, int lfs_rambd_createcfg(const struct lfs_config *cfg,
const struct lfs_rambd_cfg *cfg) { const struct lfs_rambd_config *bdcfg) {
LFS_RAMBD_TRACE("lfs_filebd_createcfg(%p, %p {" LFS_RAMBD_TRACE("lfs_rambd_createcfg(%p {.context=%p, "
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".erase_size=%"PRIu32", .erase_count=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
".erase_value=%"PRId32", .buffer=%p})", "%p {.erase_value=%"PRId32", .buffer=%p})",
(void*)bd, (void*)cfg, (void*)cfg, cfg->context,
cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
cfg->erase_value, cfg->buffer); (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
// copy over config (void*)bdcfg, bdcfg->erase_value, bdcfg->buffer);
bd->cfg = *cfg; lfs_rambd_t *bd = cfg->context;
bd->cfg = bdcfg;
// allocate buffer? // allocate buffer?
if (bd->cfg.buffer) { if (bd->cfg->buffer) {
bd->buffer = bd->cfg.buffer; bd->buffer = bd->cfg->buffer;
} else { } else {
bd->buffer = lfs_malloc(bd->cfg.erase_size * bd->cfg.erase_count); bd->buffer = lfs_malloc(cfg->block_size * cfg->block_count);
if (!bd->buffer) { if (!bd->buffer) {
LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", LFS_ERR_NOMEM); LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", LFS_ERR_NOMEM);
return LFS_ERR_NOMEM; return LFS_ERR_NOMEM;
@@ -31,89 +33,108 @@ int lfs_rambd_createcfg(lfs_rambd_t *bd,
} }
// zero for reproducability? // zero for reproducability?
if (bd->cfg.erase_value != -1) { if (bd->cfg->erase_value != -1) {
memset(bd->buffer, bd->cfg.erase_value, memset(bd->buffer, bd->cfg->erase_value,
bd->cfg.erase_size * bd->cfg.erase_count); cfg->block_size * cfg->block_count);
} }
LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0);
return 0; return 0;
} }
int lfs_rambd_destroy(lfs_rambd_t *bd) { int lfs_rambd_create(const struct lfs_config *cfg) {
LFS_RAMBD_TRACE("lfs_rambd_destroy(%p)", (void*)bd); 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);
// clean up memory // clean up memory
if (!bd->cfg.buffer) { lfs_rambd_t *bd = cfg->context;
if (!bd->cfg->buffer) {
lfs_free(bd->buffer); lfs_free(bd->buffer);
} }
LFS_RAMBD_TRACE("lfs_rambd_destroy -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_destroy -> %d", 0);
return 0; return 0;
} }
int lfs_rambd_read(lfs_rambd_t *bd, lfs_block_t block, int lfs_rambd_read(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_off_t off, void *buffer, lfs_size_t size) {
LFS_RAMBD_TRACE("lfs_rambd_read(%p, " LFS_RAMBD_TRACE("lfs_rambd_read(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)bd, block, off, buffer, size); (void*)cfg, block, off, buffer, size);
lfs_rambd_t *bd = cfg->context;
// check if read is valid // check if read is valid
LFS_ASSERT(off % bd->cfg.read_size == 0); LFS_ASSERT(off % cfg->read_size == 0);
LFS_ASSERT(size % bd->cfg.read_size == 0); LFS_ASSERT(size % cfg->read_size == 0);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// read data // read data
memcpy(buffer, &bd->buffer[block*bd->cfg.erase_size + off], size); memcpy(buffer, &bd->buffer[block*cfg->block_size + off], size);
LFS_RAMBD_TRACE("lfs_rambd_read -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_read -> %d", 0);
return 0; return 0;
} }
int lfs_rambd_prog(lfs_rambd_t *bd, lfs_block_t block, int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size) { lfs_off_t off, const void *buffer, lfs_size_t size) {
LFS_RAMBD_TRACE("lfs_rambd_prog(%p, " LFS_RAMBD_TRACE("lfs_rambd_prog(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)bd, block, off, buffer, size); (void*)cfg, block, off, buffer, size);
lfs_rambd_t *bd = cfg->context;
// check if write is valid // check if write is valid
LFS_ASSERT(off % bd->cfg.prog_size == 0); LFS_ASSERT(off % cfg->prog_size == 0);
LFS_ASSERT(size % bd->cfg.prog_size == 0); LFS_ASSERT(size % cfg->prog_size == 0);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// check that data was erased? only needed for testing // 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++) { for (lfs_off_t i = 0; i < size; i++) {
LFS_ASSERT(bd->buffer[block*bd->cfg.erase_size + off + i] == LFS_ASSERT(bd->buffer[block*cfg->block_size + off + i] ==
bd->cfg.erase_value); bd->cfg->erase_value);
} }
} }
// program data // program data
memcpy(&bd->buffer[block*bd->cfg.erase_size + off], buffer, size); memcpy(&bd->buffer[block*cfg->block_size + off], buffer, size);
LFS_RAMBD_TRACE("lfs_rambd_prog -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_prog -> %d", 0);
return 0; return 0;
} }
int lfs_rambd_erase(lfs_rambd_t *bd, lfs_block_t block) { int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block) {
LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)bd, block); LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)cfg, block);
lfs_rambd_t *bd = cfg->context;
// check if erase is valid // check if erase is valid
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// erase, only needed for testing // erase, only needed for testing
if (bd->cfg.erase_value != -1) { if (bd->cfg->erase_value != -1) {
memset(&bd->buffer[block*bd->cfg.erase_size], memset(&bd->buffer[block*cfg->block_size],
bd->cfg.erase_value, bd->cfg.erase_size); bd->cfg->erase_value, cfg->block_size);
} }
LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0);
return 0; return 0;
} }
int lfs_rambd_sync(lfs_rambd_t *bd) { int lfs_rambd_sync(const struct lfs_config *cfg) {
LFS_RAMBD_TRACE("lfs_rambd_sync(%p)", (void*)bd); LFS_RAMBD_TRACE("lfs_rambd_sync(%p)", (void*)cfg);
// sync does nothing because we aren't backed by anything real // sync does nothing because we aren't backed by anything real
(void)bd; (void)cfg;
LFS_RAMBD_TRACE("lfs_rambd_sync -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_sync -> %d", 0);
return 0; return 0;
} }

View File

@@ -8,9 +8,11 @@
#define LFS_RAMBD_H #define LFS_RAMBD_H
#include "lfs.h" #include "lfs.h"
#include "lfs_util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
@@ -22,21 +24,7 @@ extern "C" {
#endif #endif
// rambd config (optional) // rambd config (optional)
struct lfs_rambd_cfg { struct lfs_rambd_config {
// 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 // 8-bit erase value to simulate erasing with. -1 indicates no erase
// occurs, which is still a valid block device // occurs, which is still a valid block device
int32_t erase_value; int32_t erase_value;
@@ -48,39 +36,40 @@ struct lfs_rambd_cfg {
// rambd state // rambd state
typedef struct lfs_rambd { typedef struct lfs_rambd {
uint8_t *buffer; uint8_t *buffer;
struct lfs_rambd_cfg cfg; const struct lfs_rambd_config *cfg;
} lfs_rambd_t; } lfs_rambd_t;
// Create a RAM block device using the geometry in lfs_cfg // Create a RAM block device using the geometry in lfs_config
int lfs_rambd_createcfg(lfs_rambd_t *bd, int lfs_rambd_create(const struct lfs_config *cfg);
const struct lfs_rambd_cfg *cfg); int lfs_rambd_createcfg(const struct lfs_config *cfg,
const struct lfs_rambd_config *bdcfg);
// Clean up memory associated with block device // Clean up memory associated with block device
int lfs_rambd_destroy(lfs_rambd_t *bd); int lfs_rambd_destroy(const struct lfs_config *cfg);
// Read a block // Read a block
int lfs_rambd_read(lfs_rambd_t *bd, lfs_block_t block, int lfs_rambd_read(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size); lfs_off_t off, void *buffer, lfs_size_t size);
// Program a block // Program a block
// //
// The block must have previously been erased. // The block must have previously been erased.
int lfs_rambd_prog(lfs_rambd_t *bd, lfs_block_t block, int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size); lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block // Erase a block
// //
// A block must be erased before being programmed. The // A block must be erased before being programmed. The
// state of an erased block is undefined. // state of an erased block is undefined.
int lfs_rambd_erase(lfs_rambd_t *bd, lfs_block_t block); int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block);
// Sync the block device // Sync the block device
int lfs_rambd_sync(lfs_rambd_t *bd); int lfs_rambd_sync(const struct lfs_config *cfg);
#ifdef __cplusplus #ifdef __cplusplus
} } /* extern "C" */
#endif #endif
#endif #endif

View File

@@ -10,164 +10,185 @@
#include <stdlib.h> #include <stdlib.h>
int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, int lfs_testbd_createcfg(const struct lfs_config *cfg, const char *path,
const struct lfs_testbd_cfg *cfg) { const struct lfs_testbd_config *bdcfg) {
LFS_TESTBD_TRACE("lfs_testbd_createcfg(%p, \"%s\", %p {" LFS_TESTBD_TRACE("lfs_testbd_createcfg(%p {.context=%p, "
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".erase_size=%"PRIu32", .erase_count=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
".erase_value=%"PRId32", .erase_cycles=%"PRIu32", " "\"%s\", "
"%p {.erase_value=%"PRId32", .erase_cycles=%"PRIu32", "
".badblock_behavior=%"PRIu8", .power_cycles=%"PRIu32", " ".badblock_behavior=%"PRIu8", .power_cycles=%"PRIu32", "
".buffer=%p, .wear_buffer=%p})", ".buffer=%p, .wear_buffer=%p})",
(void*)bd, path, (void*)cfg, (void*)cfg, cfg->context,
cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
cfg->erase_value, cfg->erase_cycles, (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
cfg->badblock_behavior, cfg->power_cycles, cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
cfg->buffer, cfg->wear_buffer); path, (void*)bdcfg, bdcfg->erase_value, bdcfg->erase_cycles,
bdcfg->badblock_behavior, bdcfg->power_cycles,
// copy over config bdcfg->buffer, bdcfg->wear_buffer);
bd->cfg = *cfg; lfs_testbd_t *bd = cfg->context;
bd->cfg = bdcfg;
// setup testing things // setup testing things
bd->persist = path; 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->erase_cycles) {
if (bd->cfg.wear_buffer) { if (bd->cfg->wear_buffer) {
bd->wear = bd->cfg.wear_buffer; bd->wear = bd->cfg->wear_buffer;
} else { } else {
bd->wear = lfs_malloc(sizeof(lfs_testbd_wear_t)*cfg->erase_count); bd->wear = lfs_malloc(sizeof(lfs_testbd_wear_t)*cfg->block_count);
if (!bd->wear) { if (!bd->wear) {
LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", LFS_ERR_NOMEM); LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", LFS_ERR_NOMEM);
return LFS_ERR_NOMEM; return LFS_ERR_NOMEM;
} }
} }
memset(bd->wear, 0, sizeof(lfs_testbd_wear_t) * bd->cfg.erase_count); memset(bd->wear, 0, sizeof(lfs_testbd_wear_t) * cfg->block_count);
} }
// create underlying block device // create underlying block device
if (bd->persist) { if (bd->persist) {
int err = lfs_filebd_createcfg(&bd->impl.filebd, path, bd->u.file.cfg = (struct lfs_filebd_config){
&(struct lfs_filebd_cfg){ .erase_value = bd->cfg->erase_value,
.read_size=bd->cfg.read_size, };
.prog_size=bd->cfg.prog_size, int err = lfs_filebd_createcfg(cfg, path, &bd->u.file.cfg);
.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); LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err);
return err; return err;
} else { } else {
int err = lfs_rambd_createcfg(&bd->impl.rambd, bd->u.ram.cfg = (struct lfs_rambd_config){
&(struct lfs_rambd_cfg){ .erase_value = bd->cfg->erase_value,
.read_size=bd->cfg.read_size, .buffer = bd->cfg->buffer,
.prog_size=bd->cfg.prog_size, };
.erase_size=bd->cfg.erase_size, int err = lfs_rambd_createcfg(cfg, &bd->u.ram.cfg);
.erase_count=bd->cfg.erase_count,
.erase_value=bd->cfg.erase_value,
.buffer=bd->cfg.buffer});
LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err);
return err; return err;
} }
} }
int lfs_testbd_destroy(lfs_testbd_t *bd) { int lfs_testbd_create(const struct lfs_config *cfg, const char *path) {
LFS_TESTBD_TRACE("lfs_testbd_destroy(%p)", (void*)bd); LFS_TESTBD_TRACE("lfs_testbd_create(%p {.context=%p, "
if (bd->cfg.erase_cycles && !bd->cfg.wear_buffer) { ".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) {
lfs_free(bd->wear); lfs_free(bd->wear);
} }
if (bd->persist) { if (bd->persist) {
int err = lfs_filebd_destroy(&bd->impl.filebd); int err = lfs_filebd_destroy(cfg);
LFS_TESTBD_TRACE("lfs_testbd_destroy -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_destroy -> %d", err);
return err; return err;
} else { } else {
int err = lfs_rambd_destroy(&bd->impl.rambd); int err = lfs_rambd_destroy(cfg);
LFS_TESTBD_TRACE("lfs_testbd_destroy -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_destroy -> %d", err);
return err; return err;
} }
} }
/// Internal mapping to block devices /// /// Internal mapping to block devices ///
static int lfs_testbd_rawread(lfs_testbd_t *bd, lfs_block_t block, static int lfs_testbd_rawread(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_off_t off, void *buffer, lfs_size_t size) {
lfs_testbd_t *bd = cfg->context;
if (bd->persist) { if (bd->persist) {
return lfs_filebd_read(&bd->impl.filebd, block, off, buffer, size); return lfs_filebd_read(cfg, block, off, buffer, size);
} else { } else {
return lfs_rambd_read(&bd->impl.rambd, block, off, buffer, size); return lfs_rambd_read(cfg, block, off, buffer, size);
} }
} }
static int lfs_testbd_rawprog(lfs_testbd_t *bd, lfs_block_t block, static int lfs_testbd_rawprog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size) { lfs_off_t off, const void *buffer, lfs_size_t size) {
lfs_testbd_t *bd = cfg->context;
if (bd->persist) { if (bd->persist) {
return lfs_filebd_prog(&bd->impl.filebd, block, off, buffer, size); return lfs_filebd_prog(cfg, block, off, buffer, size);
} else { } else {
return lfs_rambd_prog(&bd->impl.rambd, block, off, buffer, size); return lfs_rambd_prog(cfg, block, off, buffer, size);
} }
} }
static int lfs_testbd_rawerase(lfs_testbd_t *bd, static int lfs_testbd_rawerase(const struct lfs_config *cfg,
lfs_block_t block) { lfs_block_t block) {
lfs_testbd_t *bd = cfg->context;
if (bd->persist) { if (bd->persist) {
return lfs_filebd_erase(&bd->impl.filebd, block); return lfs_filebd_erase(cfg, block);
} else { } else {
return lfs_rambd_erase(&bd->impl.rambd, block); return lfs_rambd_erase(cfg, block);
} }
} }
static int lfs_testbd_rawsync(lfs_testbd_t *bd) { static int lfs_testbd_rawsync(const struct lfs_config *cfg) {
lfs_testbd_t *bd = cfg->context;
if (bd->persist) { if (bd->persist) {
return lfs_filebd_sync(&bd->impl.filebd); return lfs_filebd_sync(cfg);
} else { } else {
return lfs_rambd_sync(&bd->impl.rambd); return lfs_rambd_sync(cfg);
} }
} }
/// block device API /// /// block device API ///
int lfs_testbd_read(lfs_testbd_t *bd, lfs_block_t block, int lfs_testbd_read(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_off_t off, void *buffer, lfs_size_t size) {
LFS_TESTBD_TRACE("lfs_testbd_read(%p, " LFS_TESTBD_TRACE("lfs_testbd_read(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)bd, block, off, buffer, size); (void*)cfg, block, off, buffer, size);
lfs_testbd_t *bd = cfg->context;
// check if read is valid // check if read is valid
LFS_ASSERT(off % bd->cfg.read_size == 0); LFS_ASSERT(off % cfg->read_size == 0);
LFS_ASSERT(size % bd->cfg.read_size == 0); LFS_ASSERT(size % cfg->read_size == 0);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// block bad? // block bad?
if (bd->cfg.erase_cycles && bd->wear[block] >= bd->cfg.erase_cycles && if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles &&
bd->cfg.badblock_behavior == LFS_TESTBD_BADBLOCK_READERROR) { bd->cfg->badblock_behavior == LFS_TESTBD_BADBLOCK_READERROR) {
LFS_TESTBD_TRACE("lfs_testbd_read -> %d", LFS_ERR_CORRUPT); LFS_TESTBD_TRACE("lfs_testbd_read -> %d", LFS_ERR_CORRUPT);
return LFS_ERR_CORRUPT; return LFS_ERR_CORRUPT;
} }
// read // read
int err = lfs_testbd_rawread(bd, block, off, buffer, size); int err = lfs_testbd_rawread(cfg, block, off, buffer, size);
LFS_TESTBD_TRACE("lfs_testbd_read -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_read -> %d", err);
return err; return err;
} }
int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block, int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size) { lfs_off_t off, const void *buffer, lfs_size_t size) {
LFS_TESTBD_TRACE("lfs_testbd_prog(%p, " LFS_TESTBD_TRACE("lfs_testbd_prog(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")", "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)bd, block, off, buffer, size); (void*)cfg, block, off, buffer, size);
lfs_testbd_t *bd = cfg->context;
// check if write is valid // check if write is valid
LFS_ASSERT(off % bd->cfg.prog_size == 0); LFS_ASSERT(off % cfg->prog_size == 0);
LFS_ASSERT(size % bd->cfg.prog_size == 0); LFS_ASSERT(size % cfg->prog_size == 0);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// block bad? // block bad?
if (bd->cfg.erase_cycles && bd->wear[block] >= bd->cfg.erase_cycles) { if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles) {
if (bd->cfg.badblock_behavior == if (bd->cfg->badblock_behavior ==
LFS_TESTBD_BADBLOCK_PROGERROR) { LFS_TESTBD_BADBLOCK_PROGERROR) {
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", LFS_ERR_CORRUPT); LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", LFS_ERR_CORRUPT);
return LFS_ERR_CORRUPT; return LFS_ERR_CORRUPT;
} else if (bd->cfg.badblock_behavior == } else if (bd->cfg->badblock_behavior ==
LFS_TESTBD_BADBLOCK_PROGNOOP || LFS_TESTBD_BADBLOCK_PROGNOOP ||
bd->cfg.badblock_behavior == bd->cfg->badblock_behavior ==
LFS_TESTBD_BADBLOCK_ERASENOOP) { LFS_TESTBD_BADBLOCK_ERASENOOP) {
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", 0); LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", 0);
return 0; return 0;
@@ -175,7 +196,7 @@ int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block,
} }
// prog // prog
int err = lfs_testbd_rawprog(bd, block, off, buffer, size); int err = lfs_testbd_rawprog(cfg, block, off, buffer, size);
if (err) { if (err) {
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err);
return err; return err;
@@ -186,7 +207,7 @@ int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block,
bd->power_cycles -= 1; bd->power_cycles -= 1;
if (bd->power_cycles == 0) { if (bd->power_cycles == 0) {
// sync to make sure we persist the last changes // sync to make sure we persist the last changes
assert(lfs_testbd_rawsync(bd) == 0); assert(lfs_testbd_rawsync(cfg) == 0);
// simulate power loss // simulate power loss
exit(33); exit(33);
} }
@@ -196,20 +217,21 @@ int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block,
return 0; return 0;
} }
int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block) { int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) {
LFS_TESTBD_TRACE("lfs_testbd_erase(%p, 0x%"PRIx32")", (void*)bd, block); LFS_TESTBD_TRACE("lfs_testbd_erase(%p, 0x%"PRIx32")", (void*)cfg, block);
lfs_testbd_t *bd = cfg->context;
// check if erase is valid // check if erase is valid
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
// block bad? // block bad?
if (bd->cfg.erase_cycles) { if (bd->cfg->erase_cycles) {
if (bd->wear[block] >= bd->cfg.erase_cycles) { if (bd->wear[block] >= bd->cfg->erase_cycles) {
if (bd->cfg.badblock_behavior == if (bd->cfg->badblock_behavior ==
LFS_TESTBD_BADBLOCK_ERASEERROR) { LFS_TESTBD_BADBLOCK_ERASEERROR) {
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", LFS_ERR_CORRUPT); LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", LFS_ERR_CORRUPT);
return 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_BADBLOCK_ERASENOOP) {
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", 0); LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", 0);
return 0; return 0;
@@ -221,7 +243,7 @@ int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block) {
} }
// erase // erase
int err = lfs_testbd_rawerase(bd, block); int err = lfs_testbd_rawerase(cfg, block);
if (err) { if (err) {
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err);
return err; return err;
@@ -232,7 +254,7 @@ int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block) {
bd->power_cycles -= 1; bd->power_cycles -= 1;
if (bd->power_cycles == 0) { if (bd->power_cycles == 0) {
// sync to make sure we persist the last changes // sync to make sure we persist the last changes
assert(lfs_testbd_rawsync(bd) == 0); assert(lfs_testbd_rawsync(cfg) == 0);
// simulate power loss // simulate power loss
exit(33); exit(33);
} }
@@ -242,34 +264,36 @@ int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block) {
return 0; return 0;
} }
int lfs_testbd_sync(lfs_testbd_t *bd) { int lfs_testbd_sync(const struct lfs_config *cfg) {
LFS_TESTBD_TRACE("lfs_testbd_sync(%p)", (void*)bd); LFS_TESTBD_TRACE("lfs_testbd_sync(%p)", (void*)cfg);
int err = lfs_testbd_rawsync(bd); int err = lfs_testbd_rawsync(cfg);
LFS_TESTBD_TRACE("lfs_testbd_sync -> %d", err); LFS_TESTBD_TRACE("lfs_testbd_sync -> %d", err);
return err; return err;
} }
/// simulated wear operations /// /// simulated wear operations ///
lfs_testbd_swear_t lfs_testbd_getwear(lfs_testbd_t *bd, lfs_testbd_swear_t lfs_testbd_getwear(const struct lfs_config *cfg,
lfs_block_t block) { lfs_block_t block) {
LFS_TESTBD_TRACE("lfs_testbd_getwear(%p, %"PRIu32")", (void*)bd, block); LFS_TESTBD_TRACE("lfs_testbd_getwear(%p, %"PRIu32")", (void*)cfg, block);
lfs_testbd_t *bd = cfg->context;
// check if block is valid // check if block is valid
LFS_ASSERT(bd->cfg.erase_cycles); LFS_ASSERT(bd->cfg->erase_cycles);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
LFS_TESTBD_TRACE("lfs_testbd_getwear -> %"PRIu32, bd->wear[block]); LFS_TESTBD_TRACE("lfs_testbd_getwear -> %"PRIu32, bd->wear[block]);
return bd->wear[block]; return bd->wear[block];
} }
int lfs_testbd_setwear(lfs_testbd_t *bd, int lfs_testbd_setwear(const struct lfs_config *cfg,
lfs_block_t block, lfs_testbd_wear_t wear) { lfs_block_t block, lfs_testbd_wear_t wear) {
LFS_TESTBD_TRACE("lfs_testbd_setwear(%p, %"PRIu32")", (void*)bd, block); LFS_TESTBD_TRACE("lfs_testbd_setwear(%p, %"PRIu32")", (void*)cfg, block);
lfs_testbd_t *bd = cfg->context;
// check if block is valid // check if block is valid
LFS_ASSERT(bd->cfg.erase_cycles); LFS_ASSERT(bd->cfg->erase_cycles);
LFS_ASSERT(block < bd->cfg.erase_count); LFS_ASSERT(block < cfg->block_count);
bd->wear[block] = wear; bd->wear[block] = wear;

View File

@@ -9,11 +9,13 @@
#define LFS_TESTBD_H #define LFS_TESTBD_H
#include "lfs.h" #include "lfs.h"
#include "lfs_util.h"
#include "bd/lfs_rambd.h" #include "bd/lfs_rambd.h"
#include "bd/lfs_filebd.h" #include "bd/lfs_filebd.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
@@ -43,21 +45,7 @@ typedef uint32_t lfs_testbd_wear_t;
typedef int32_t lfs_testbd_swear_t; typedef int32_t lfs_testbd_swear_t;
// testbd config, this is required for testing // testbd config, this is required for testing
struct lfs_testbd_cfg { struct lfs_testbd_config {
// 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 // 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 // erases, which can speed up testing by avoiding all the extra block-device
// operations to store the erase value. // operations to store the erase value.
@@ -84,63 +72,70 @@ struct lfs_testbd_cfg {
// testbd state // testbd state
typedef struct lfs_testbd { typedef struct lfs_testbd {
union { union {
lfs_filebd_t filebd; struct {
lfs_rambd_t rambd; lfs_filebd_t bd;
} impl; struct lfs_filebd_config cfg;
} file;
struct {
lfs_rambd_t bd;
struct lfs_rambd_config cfg;
} ram;
} u;
bool persist; bool persist;
uint32_t power_cycles; uint32_t power_cycles;
lfs_testbd_wear_t *wear; lfs_testbd_wear_t *wear;
struct lfs_testbd_cfg cfg; const struct lfs_testbd_config *cfg;
} lfs_testbd_t; } lfs_testbd_t;
/// Block device API /// /// Block device API ///
// Create a test block device using the geometry in lfs_cfg // Create a test block device using the geometry in lfs_config
// //
// Note that filebd is used if a path is provided, if path is NULL // Note that filebd is used if a path is provided, if path is NULL
// testbd will use rambd which can be much faster. // testbd will use rambd which can be much faster.
int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, int lfs_testbd_create(const struct lfs_config *cfg, const char *path);
const struct lfs_testbd_cfg *cfg); int lfs_testbd_createcfg(const struct lfs_config *cfg, const char *path,
const struct lfs_testbd_config *bdcfg);
// Clean up memory associated with block device // Clean up memory associated with block device
int lfs_testbd_destroy(lfs_testbd_t *bd); int lfs_testbd_destroy(const struct lfs_config *cfg);
// Read a block // Read a block
int lfs_testbd_read(lfs_testbd_t *bd, lfs_block_t block, int lfs_testbd_read(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size); lfs_off_t off, void *buffer, lfs_size_t size);
// Program a block // Program a block
// //
// The block must have previously been erased. // The block must have previously been erased.
int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block, int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size); lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block // Erase a block
// //
// A block must be erased before being programmed. The // A block must be erased before being programmed. The
// state of an erased block is undefined. // state of an erased block is undefined.
int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block); int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block);
// Sync the block device // Sync the block device
int lfs_testbd_sync(lfs_testbd_t *bd); int lfs_testbd_sync(const struct lfs_config *cfg);
/// Additional extended API for driving test features /// /// Additional extended API for driving test features ///
// Get simulated wear on a given block // Get simulated wear on a given block
lfs_testbd_swear_t lfs_testbd_getwear(lfs_testbd_t *bd, lfs_testbd_swear_t lfs_testbd_getwear(const struct lfs_config *cfg,
lfs_block_t block); lfs_block_t block);
// Manually set simulated wear on a given block // Manually set simulated wear on a given block
int lfs_testbd_setwear(lfs_testbd_t *bd, int lfs_testbd_setwear(const struct lfs_config *cfg,
lfs_block_t block, lfs_testbd_wear_t wear); lfs_block_t block, lfs_testbd_wear_t wear);
#ifdef __cplusplus #ifdef __cplusplus
} } /* extern "C" */
#endif #endif
#endif #endif

619
lfs.c

File diff suppressed because it is too large Load Diff

215
lfs.h
View File

@@ -7,10 +7,12 @@
#ifndef LFS_H #ifndef LFS_H
#define LFS_H #define LFS_H
#include "lfs_util.h" #include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
@@ -64,6 +66,26 @@ typedef uint32_t lfs_block_t;
#define LFS_ATTR_MAX 1022 #define LFS_ATTR_MAX 1022
#endif #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 // File types
enum lfs_type { enum lfs_type {
// file types // file types
@@ -125,33 +147,32 @@ enum lfs_whence_flags {
}; };
#if !defined(LFS_STATICCFG)
// Configuration provided during initialization of the littlefs // Configuration provided during initialization of the littlefs
struct lfs_cfg { struct lfs_config {
// Opaque user provided context that can be used to pass // Opaque user provided context that can be used to pass
// information to the block device operations // information to the block device operations
void *ctx; void *context;
// Read a region in a block. Negative error codes are propogated // Read a region in a block. Negative error codes are propogated
// to the user. // to the user.
int (*read)(void *ctx, lfs_block_t block, int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size); lfs_off_t off, void *buffer, lfs_size_t size);
// Program a region in a block. The block must have previously // Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user. // been erased. Negative error codes are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad. // May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(void *ctx, lfs_block_t block, int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size); lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block. A block must be erased before being programmed. // Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes // The state of an erased block is undefined. Negative error codes
// are propogated to the user. // are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad. // May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(void *ctx, lfs_block_t block); int (*erase)(const struct lfs_config *c, lfs_block_t block);
// Sync the state of the underlying block device. Negative error codes // Sync the state of the underlying block device. Negative error codes
// are propogated to the user. // are propogated to the user.
int (*sync)(void *ctx); int (*sync)(const struct lfs_config *c);
// Minimum size of a block read. All read operations will be a // Minimum size of a block read. All read operations will be a
// multiple of this value. // multiple of this value.
@@ -220,90 +241,6 @@ struct lfs_cfg {
// LFS_ATTR_MAX when zero. // LFS_ATTR_MAX when zero.
lfs_size_t attr_max; 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 // File info structure
struct lfs_info { struct lfs_info {
@@ -334,6 +271,29 @@ struct lfs_attr {
lfs_size_t size; 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 /// /// internal littlefs data structures ///
typedef struct lfs_cache { typedef struct lfs_cache {
@@ -383,9 +343,7 @@ typedef struct lfs_file {
lfs_off_t off; lfs_off_t off;
lfs_cache_t cache; lfs_cache_t cache;
#ifndef LFS_FILE_STATICCFG const struct lfs_file_config *cfg;
struct lfs_file_cfg cfg;
#endif
} lfs_file_t; } lfs_file_t;
typedef struct lfs_superblock { typedef struct lfs_superblock {
@@ -428,9 +386,10 @@ typedef struct lfs {
uint32_t *buffer; uint32_t *buffer;
} free; } free;
#ifndef LFS_STATICCFG const struct lfs_config *cfg;
struct lfs_cfg cfg; lfs_size_t name_max;
#endif lfs_size_t file_max;
lfs_size_t attr_max;
#ifdef LFS_MIGRATE #ifdef LFS_MIGRATE
struct lfs1 *lfs1; struct lfs1 *lfs1;
@@ -440,38 +399,16 @@ typedef struct lfs {
/// Filesystem functions /// /// Filesystem functions ///
#if defined(LFS_STATICCFG) // Format a block device with the littlefs
// 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 // Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must // object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility. // be zeroed for defaults and backwards compatibility.
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_formatcfg(lfs_t *lfs, const struct lfs_cfg *config); int lfs_format(lfs_t *lfs, const struct lfs_config *config);
#endif
#if defined(LFS_STATICCFG) // Mounts a littlefs
// 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 // Requires a littlefs object and config struct. Multiple filesystems
// may be mounted simultaneously with multiple littlefs objects. Both // may be mounted simultaneously with multiple littlefs objects. Both
@@ -479,8 +416,7 @@ int lfs_mount(lfs_t *lfs);
// be zeroed for defaults and backwards compatibility. // be zeroed for defaults and backwards compatibility.
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_mountcfg(lfs_t *lfs, const struct lfs_cfg *config); int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
#endif
// Unmounts a littlefs // Unmounts a littlefs
// //
@@ -554,8 +490,7 @@ int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
int lfs_file_open(lfs_t *lfs, lfs_file_t *file, int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags); const char *path, int flags);
#if !defined(LFS_FILE_STATICCFG) // Open a file with extra configuration
// Open a file with per-file configuration
// //
// The mode that the file is opened in is determined by the flags, which // 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. // are values from the enum lfs_open_flags that are bitwise-ored together.
@@ -567,8 +502,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags, const char *path, int flags,
const struct lfs_file_cfg *config); const struct lfs_file_config *config);
#endif
// Close a file // Close a file
// //
@@ -698,39 +632,24 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
#if defined(LFS_MIGRATE) && defined(LFS_STATICCFG) #ifdef LFS_MIGRATE
// Attempts to migrate a previous version of littlefs // Attempts to migrate a previous version of littlefs
// //
// Behaves similarly to the lfs_format function. Attempts to mount // Behaves similarly to the lfs_format function. Attempts to mount
// the previous version of littlefs and update the filesystem so it can be // the previous version of littlefs and update the filesystem so it can be
// mounted with the current version of littlefs. // 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 // Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must // object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility. // be zeroed for defaults and backwards compatibility.
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_migratecfg(lfs_t *lfs, const struct lfs_cfg *cfg); int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} } /* extern "C" */
#endif #endif
#endif #endif

View File

@@ -7,7 +7,7 @@
#include "lfs_util.h" #include "lfs_util.h"
// Only compile if user does not provide custom config // Only compile if user does not provide custom config
#ifndef LFS_UTIL #ifndef LFS_CONFIG
// Software CRC implementation with small lookup table // Software CRC implementation with small lookup table

View File

@@ -3,21 +3,20 @@
* *
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * 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 #ifndef LFS_UTIL_H
#define LFS_UTIL_H #define LFS_UTIL_H
#ifdef LFS_UTIL // 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
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x #define LFS_STRINGIZE2(x) #x
#include LFS_STRINGIZE(LFS_UTIL) #include LFS_STRINGIZE(LFS_CONFIG)
#else #else
// System includes // System includes
@@ -40,32 +39,11 @@
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #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, 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 // macros must not have side-effects as the macros can be removed for a smaller
// code footprint // code footprint
@@ -172,8 +150,8 @@ static inline uint32_t lfs_popc(uint32_t a) {
// Find the sequence comparison of a and b, this is the distance // Find the sequence comparison of a and b, this is the distance
// between a and b ignoring overflow // between a and b ignoring overflow
static inline int32_t lfs_scmp(uint32_t a, uint32_t b) { static inline int lfs_scmp(uint32_t a, uint32_t b) {
return (int32_t)(uint32_t)(a - b); return (int)(unsigned)(a - b);
} }
// Convert between 32-bit little-endian and native order // Convert between 32-bit little-endian and native order
@@ -249,7 +227,7 @@ static inline void lfs_free(void *p) {
#ifdef __cplusplus #ifdef __cplusplus
} } /* extern "C" */
#endif #endif
#endif #endif

View File

@@ -106,7 +106,7 @@ def main(args):
struct.unpack('<HH', superblock[1].data[0:4].ljust(4, b'\xff')))) struct.unpack('<HH', superblock[1].data[0:4].ljust(4, b'\xff'))))
print("%-47s%s" % ("littlefs v%s.%s" % version, print("%-47s%s" % ("littlefs v%s.%s" % version,
"data (truncated, if it fits)" "data (truncated, if it fits)"
if not any([args.no_truncate, args.tags, args.log, args.all]) else "")) if not any([args.no_truncate, args.log, args.all]) else ""))
# print gstate # print gstate
print("gstate 0x%s" % ''.join('%02x' % c for c in gstate)) print("gstate 0x%s" % ''.join('%02x' % c for c in gstate))

View File

@@ -34,43 +34,13 @@ $(foreach target,$(SRC),$(eval $(FLATTEN)))
%.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f) %.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f)
$(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
""" """
BEFORE_MAIN = """ GLOBALS = """
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 //////////////// //////////////// AUTOGENERATED TEST ////////////////
#include "lfs.h" #include "lfs.h"
#include "bd/lfs_testbd.h" #include "bd/lfs_testbd.h"
#include <stdio.h> #include <stdio.h>
extern const char *lfs_testbd_path; extern const char *lfs_testbd_path;
extern uint32_t lfs_testbd_cycles; 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 = { DEFINES = {
'LFS_READ_SIZE': 16, 'LFS_READ_SIZE': 16,
@@ -96,12 +66,12 @@ PROLOGUE = """
__attribute__((unused)) lfs_size_t size; __attribute__((unused)) lfs_size_t size;
__attribute__((unused)) int err; __attribute__((unused)) int err;
__attribute__((unused)) const struct lfs_cfg cfg = { __attribute__((unused)) const struct lfs_config cfg = {
.ctx = &bd, .context = &bd,
.read = lfs_testbd_readctx, .read = lfs_testbd_read,
.prog = lfs_testbd_progctx, .prog = lfs_testbd_prog,
.erase = lfs_testbd_erasectx, .erase = lfs_testbd_erase,
.sync = lfs_testbd_syncctx, .sync = lfs_testbd_sync,
.read_size = LFS_READ_SIZE, .read_size = LFS_READ_SIZE,
.prog_size = LFS_PROG_SIZE, .prog_size = LFS_PROG_SIZE,
.block_size = LFS_BLOCK_SIZE, .block_size = LFS_BLOCK_SIZE,
@@ -111,22 +81,18 @@ PROLOGUE = """
.lookahead_size = LFS_LOOKAHEAD_SIZE, .lookahead_size = LFS_LOOKAHEAD_SIZE,
}; };
__attribute__((unused)) const struct lfs_testbd_cfg bdcfg = { __attribute__((unused)) const struct lfs_testbd_config 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_value = LFS_ERASE_VALUE,
.erase_cycles = LFS_ERASE_CYCLES, .erase_cycles = LFS_ERASE_CYCLES,
.badblock_behavior = LFS_BADBLOCK_BEHAVIOR, .badblock_behavior = LFS_BADBLOCK_BEHAVIOR,
.power_cycles = lfs_testbd_cycles, .power_cycles = lfs_testbd_cycles,
}; };
lfs_testbd_createcfg(&bd, lfs_testbd_path, &bdcfg) => 0; lfs_testbd_createcfg(&cfg, lfs_testbd_path, &bdcfg) => 0;
""" """
EPILOGUE = """ EPILOGUE = """
// epilogue // epilogue
lfs_testbd_destroy(&bd) => 0; lfs_testbd_destroy(&cfg) => 0;
""" """
PASS = '\033[32m✓\033[0m' PASS = '\033[32m✓\033[0m'
FAIL = '\033[31m✗\033[0m' FAIL = '\033[31m✗\033[0m'
@@ -502,7 +468,7 @@ class TestSuite:
def build(self, **args): def build(self, **args):
# build test files # build test files
tf = open(self.path + '.test.c.t', 'w') tf = open(self.path + '.test.c.t', 'w')
tf.write(BEFORE_TESTS) tf.write(GLOBALS)
if self.code is not None: if self.code is not None:
tf.write('#line %d "%s"\n' % (self.code_lineno, self.path)) tf.write('#line %d "%s"\n' % (self.code_lineno, self.path))
tf.write(self.code) tf.write(self.code)
@@ -517,13 +483,14 @@ class TestSuite:
for line in f: for line in f:
tfs[case.in_].write(line) tfs[case.in_].write(line)
tfs[case.in_].write('\n') tfs[case.in_].write('\n')
tfs[case.in_].write(BEFORE_TESTS) tfs[case.in_].write(GLOBALS)
tfs[case.in_].write('\n') tfs[case.in_].write('\n')
case.build(tfs[case.in_], **args) case.build(tfs[case.in_], **args)
tf.write(BEFORE_MAIN)
tf.write('\n') 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('int main(int argc, char **argv) {\n')
tf.write(4*' '+'int case_ = (argc > 1) ? atoi(argv[1]) : 0;\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') tf.write(4*' '+'int perm = (argc > 2) ? atoi(argv[2]) : 0;\n')

View File

@@ -9,12 +9,12 @@ code = '''
const char *names[FILES] = {"bacon", "eggs", "pancakes"}; const char *names[FILES] = {"bacon", "eggs", "pancakes"};
lfs_file_t files[FILES]; lfs_file_t files[FILES];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "breakfast") => 0; lfs_mkdir(&lfs, "breakfast") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &files[n], path, lfs_file_open(&lfs, &files[n], path,
@@ -31,7 +31,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 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 = ''' code = '''
const char *names[FILES] = {"bacon", "eggs", "pancakes"}; const char *names[FILES] = {"bacon", "eggs", "pancakes"};
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "breakfast") => 0; lfs_mkdir(&lfs, "breakfast") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
@@ -70,7 +70,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
} }
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0;
@@ -92,14 +92,14 @@ code = '''
const char *names[FILES] = {"bacon", "eggs", "pancakes"}; const char *names[FILES] = {"bacon", "eggs", "pancakes"};
lfs_file_t files[FILES]; lfs_file_t files[FILES];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
for (int c = 0; c < CYCLES; c++) { for (int c = 0; c < CYCLES; c++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "breakfast") => 0; lfs_mkdir(&lfs, "breakfast") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &files[n], path, lfs_file_open(&lfs, &files[n], path,
@@ -116,7 +116,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0;
@@ -129,7 +129,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_remove(&lfs, path) => 0; lfs_remove(&lfs, path) => 0;
@@ -146,15 +146,15 @@ define.CYCLES = [1, 10]
code = ''' code = '''
const char *names[FILES] = {"bacon", "eggs", "pancakes"}; const char *names[FILES] = {"bacon", "eggs", "pancakes"};
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
for (int c = 0; c < CYCLES; c++) { for (int c = 0; c < CYCLES; c++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "breakfast") => 0; lfs_mkdir(&lfs, "breakfast") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
@@ -167,7 +167,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
} }
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0;
@@ -180,7 +180,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int n = 0; n < FILES; n++) { for (int n = 0; n < FILES; n++) {
sprintf(path, "breakfast/%s", names[n]); sprintf(path, "breakfast/%s", names[n]);
lfs_remove(&lfs, path) => 0; lfs_remove(&lfs, path) => 0;
@@ -192,8 +192,8 @@ code = '''
[[case]] # exhaustion test [[case]] # exhaustion test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
size = strlen("exhaustion"); size = strlen("exhaustion");
memcpy(buffer, "exhaustion", size); memcpy(buffer, "exhaustion", size);
@@ -216,7 +216,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
size = strlen("exhaustion"); size = strlen("exhaustion");
lfs_file_size(&lfs, &file) => size; lfs_file_size(&lfs, &file) => size;
@@ -229,8 +229,8 @@ code = '''
[[case]] # exhaustion wraparound test [[case]] # exhaustion wraparound test
define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / 3)' define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / 3)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT); lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT);
size = strlen("buffering"); size = strlen("buffering");
@@ -263,7 +263,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
size = strlen("exhaustion"); size = strlen("exhaustion");
lfs_file_size(&lfs, &file) => size; lfs_file_size(&lfs, &file) => size;
@@ -276,8 +276,8 @@ code = '''
[[case]] # dir exhaustion test [[case]] # dir exhaustion test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// find out max file size // find out max file size
lfs_mkdir(&lfs, "exhaustiondir") => 0; lfs_mkdir(&lfs, "exhaustiondir") => 0;
@@ -328,8 +328,8 @@ in = "lfs.c"
define.LFS_ERASE_CYCLES = 0xffffffff define.LFS_ERASE_CYCLES = 0xffffffff
define.LFS_BADBLOCK_BEHAVIOR = 'LFS_TESTBD_BADBLOCK_READERROR' define.LFS_BADBLOCK_BEHAVIOR = 'LFS_TESTBD_BADBLOCK_READERROR'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// first fill to exhaustion to find available space // first fill to exhaustion to find available space
lfs_file_open(&lfs, &file, "pacman", LFS_O_WRONLY | LFS_O_CREAT) => 0; lfs_file_open(&lfs, &file, "pacman", LFS_O_WRONLY | LFS_O_CREAT) => 0;
strcpy((char*)buffer, "waka"); strcpy((char*)buffer, "waka");
@@ -358,11 +358,11 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// remount to force an alloc scan // remount to force an alloc scan
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// but mark the head of our file as a "bad block", this is force our // but mark the head of our file as a "bad block", this is force our
// scan to bail early // scan to bail early
lfs_testbd_setwear(&bd, fileblock, 0xffffffff) => 0; lfs_testbd_setwear(&cfg, fileblock, 0xffffffff) => 0;
lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0; lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0;
strcpy((char*)buffer, "chomp"); strcpy((char*)buffer, "chomp");
size = strlen("chomp"); size = strlen("chomp");
@@ -377,7 +377,7 @@ code = '''
// now reverse the "bad block" and try to write the file again until we // now reverse the "bad block" and try to write the file again until we
// run out of space // run out of space
lfs_testbd_setwear(&bd, fileblock, 0) => 0; lfs_testbd_setwear(&cfg, fileblock, 0) => 0;
lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0; lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0;
strcpy((char*)buffer, "chomp"); strcpy((char*)buffer, "chomp");
size = strlen("chomp"); size = strlen("chomp");
@@ -393,7 +393,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// check that the disk isn't hurt // check that the disk isn't hurt
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "pacman", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "pacman", LFS_O_RDONLY) => 0;
strcpy((char*)buffer, "waka"); strcpy((char*)buffer, "waka");
size = strlen("waka"); size = strlen("waka");
@@ -416,8 +416,8 @@ define.LFS_BLOCK_SIZE = 512
define.LFS_BLOCK_COUNT = 1024 define.LFS_BLOCK_COUNT = 1024
if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// find out max file size // find out max file size
lfs_mkdir(&lfs, "exhaustiondir") => 0; lfs_mkdir(&lfs, "exhaustiondir") => 0;
@@ -487,8 +487,8 @@ define.LFS_BLOCK_SIZE = 512
define.LFS_BLOCK_COUNT = 1024 define.LFS_BLOCK_COUNT = 1024
if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// create one block hole for half a directory // create one block hole for half a directory
lfs_file_open(&lfs, &file, "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0; lfs_file_open(&lfs, &file, "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0;
@@ -510,7 +510,7 @@ code = '''
// remount to force reset of lookahead // remount to force reset of lookahead
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// open hole // open hole
lfs_remove(&lfs, "bump") => 0; lfs_remove(&lfs, "bump") => 0;
@@ -532,8 +532,8 @@ define.LFS_BLOCK_SIZE = 512
define.LFS_BLOCK_COUNT = 1024 define.LFS_BLOCK_COUNT = 1024
if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// fill completely with two files // fill completely with two files
lfs_file_open(&lfs, &file, "exhaustion1", lfs_file_open(&lfs, &file, "exhaustion1",
@@ -560,7 +560,7 @@ code = '''
// remount to force reset of lookahead // remount to force reset of lookahead
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// rewrite one file // rewrite one file
lfs_file_open(&lfs, &file, "exhaustion1", lfs_file_open(&lfs, &file, "exhaustion1",
@@ -597,8 +597,8 @@ define.LFS_BLOCK_SIZE = 512
define.LFS_BLOCK_COUNT = 1024 define.LFS_BLOCK_COUNT = 1024
if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024' if = 'LFS_BLOCK_SIZE == 512 && LFS_BLOCK_COUNT == 1024'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// fill completely with two files // fill completely with two files
lfs_file_open(&lfs, &file, "exhaustion1", lfs_file_open(&lfs, &file, "exhaustion1",
@@ -625,7 +625,7 @@ code = '''
// remount to force reset of lookahead // remount to force reset of lookahead
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// rewrite one file with a hole of one block // rewrite one file with a hole of one block
lfs_file_open(&lfs, &file, "exhaustion1", lfs_file_open(&lfs, &file, "exhaustion1",

View File

@@ -1,14 +1,14 @@
[[case]] # set/get attribute [[case]] # set/get attribute
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "hello") => 0; lfs_mkdir(&lfs, "hello") => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 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_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
lfs_setattr(&lfs, "hello", 'A', "aaaa", 4) => 0; lfs_setattr(&lfs, "hello", 'A', "aaaa", 4) => 0;
lfs_setattr(&lfs, "hello", 'B', "bbbbbb", 6) => 0; lfs_setattr(&lfs, "hello", 'B', "bbbbbb", 6) => 0;
@@ -60,7 +60,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9; lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9;
@@ -78,15 +78,15 @@ code = '''
[[case]] # set/get root attribute [[case]] # set/get root attribute
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "hello") => 0; lfs_mkdir(&lfs, "hello") => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 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_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
lfs_setattr(&lfs, "/", 'A', "aaaa", 4) => 0; lfs_setattr(&lfs, "/", 'A', "aaaa", 4) => 0;
lfs_setattr(&lfs, "/", 'B', "bbbbbb", 6) => 0; lfs_setattr(&lfs, "/", 'B', "bbbbbb", 6) => 0;
@@ -137,7 +137,7 @@ code = '''
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 9) => 9; lfs_getattr(&lfs, "/", 'B', buffer+4, 9) => 9;
@@ -155,22 +155,22 @@ code = '''
[[case]] # set/get file attribute [[case]] # set/get file attribute
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "hello") => 0; lfs_mkdir(&lfs, "hello") => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 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_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
struct lfs_attr attrs1[] = { struct lfs_attr attrs1[] = {
{'A', buffer, 4}, {'A', buffer, 4},
{'B', buffer+4, 6}, {'B', buffer+4, 6},
{'C', buffer+10, 5}, {'C', buffer+10, 5},
}; };
struct lfs_file_cfg cfg1 = {.attrs=attrs1, .attr_count=3}; struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3};
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
memcpy(buffer, "aaaa", 4); memcpy(buffer, "aaaa", 4);
@@ -228,7 +228,7 @@ code = '''
{'B', buffer+4, 9}, {'B', buffer+4, 9},
{'C', buffer+13, 5}, {'C', buffer+13, 5},
}; };
struct lfs_file_cfg cfg2 = {.attrs=attrs2, .attr_count=3}; struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3};
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0;
memcpy(buffer+4, "fffffffff", 9); memcpy(buffer+4, "fffffffff", 9);
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
@@ -238,14 +238,14 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
struct lfs_attr attrs3[] = { struct lfs_attr attrs3[] = {
{'A', buffer, 4}, {'A', buffer, 4},
{'B', buffer+4, 9}, {'B', buffer+4, 9},
{'C', buffer+13, 5}, {'C', buffer+13, 5},
}; };
struct lfs_file_cfg cfg3 = {.attrs=attrs3, .attr_count=3}; struct lfs_file_config cfg3 = {.attrs=attrs3, .attr_count=3};
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg3) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg3) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
@@ -262,15 +262,15 @@ code = '''
[[case]] # deferred file attributes [[case]] # deferred file attributes
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "hello") => 0; lfs_mkdir(&lfs, "hello") => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 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_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_setattr(&lfs, "hello/hello", 'B', "fffffffff", 9) => 0; lfs_setattr(&lfs, "hello/hello", 'B', "fffffffff", 9) => 0;
lfs_setattr(&lfs, "hello/hello", 'C', "ccccc", 5) => 0; lfs_setattr(&lfs, "hello/hello", 'C', "ccccc", 5) => 0;
@@ -280,7 +280,7 @@ code = '''
{'C', "", 0}, {'C', "", 0},
{'D', "hhhh", 4}, {'D', "hhhh", 4},
}; };
struct lfs_file_cfg cfg1 = {.attrs=attrs1, .attr_count=3}; struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3};
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;

View File

@@ -16,12 +16,12 @@ define.NAMEMULT = 64
define.FILEMULT = 1 define.FILEMULT = 1
code = ''' code = '''
for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) { for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) {
lfs_testbd_setwear(&bd, badblock-1, 0) => 0; lfs_testbd_setwear(&cfg, badblock-1, 0) => 0;
lfs_testbd_setwear(&bd, badblock, 0xffffffff) => 0; lfs_testbd_setwear(&cfg, badblock, 0xffffffff) => 0;
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
for (int j = 0; j < NAMEMULT; j++) { for (int j = 0; j < NAMEMULT; j++) {
buffer[j] = '0'+i; buffer[j] = '0'+i;
@@ -46,7 +46,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
for (int j = 0; j < NAMEMULT; j++) { for (int j = 0; j < NAMEMULT; j++) {
buffer[j] = '0'+i; buffer[j] = '0'+i;
@@ -90,12 +90,12 @@ define.NAMEMULT = 64
define.FILEMULT = 1 define.FILEMULT = 1
code = ''' code = '''
for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) { for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) {
lfs_testbd_setwear(&bd, i+2, 0xffffffff) => 0; lfs_testbd_setwear(&cfg, i+2, 0xffffffff) => 0;
} }
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
for (int j = 0; j < NAMEMULT; j++) { for (int j = 0; j < NAMEMULT; j++) {
buffer[j] = '0'+i; buffer[j] = '0'+i;
@@ -120,7 +120,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
for (int j = 0; j < NAMEMULT; j++) { for (int j = 0; j < NAMEMULT; j++) {
buffer[j] = '0'+i; buffer[j] = '0'+i;
@@ -163,12 +163,12 @@ define.NAMEMULT = 64
define.FILEMULT = 1 define.FILEMULT = 1
code = ''' code = '''
for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) { for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) {
lfs_testbd_setwear(&bd, (2*i) + 2, 0xffffffff) => 0; lfs_testbd_setwear(&cfg, (2*i) + 2, 0xffffffff) => 0;
} }
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
for (int j = 0; j < NAMEMULT; j++) { for (int j = 0; j < NAMEMULT; j++) {
buffer[j] = '0'+i; buffer[j] = '0'+i;
@@ -193,7 +193,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
for (int j = 0; j < NAMEMULT; j++) { for (int j = 0; j < NAMEMULT; j++) {
buffer[j] = '0'+i; buffer[j] = '0'+i;
@@ -233,9 +233,9 @@ define.LFS_BADBLOCK_BEHAVIOR = [
'LFS_TESTBD_BADBLOCK_ERASENOOP', 'LFS_TESTBD_BADBLOCK_ERASENOOP',
] ]
code = ''' code = '''
lfs_testbd_setwear(&bd, 0, 0xffffffff) => 0; lfs_testbd_setwear(&cfg, 0, 0xffffffff) => 0;
lfs_testbd_setwear(&bd, 1, 0xffffffff) => 0; lfs_testbd_setwear(&cfg, 1, 0xffffffff) => 0;
lfs_formatcfg(&lfs, &cfg) => LFS_ERR_NOSPC; lfs_format(&lfs, &cfg) => LFS_ERR_NOSPC;
lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
''' '''

View File

@@ -1,7 +1,7 @@
[[case]] # root [[case]] # root
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -17,16 +17,16 @@ code = '''
[[case]] # many directory creation [[case]] # many directory creation
define.N = 'range(0, 100, 3)' define.N = 'range(0, 100, 3)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "dir%03d", i); sprintf(path, "dir%03d", i);
lfs_mkdir(&lfs, path) => 0; lfs_mkdir(&lfs, path) => 0;
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -48,16 +48,16 @@ code = '''
[[case]] # many directory removal [[case]] # many directory removal
define.N = 'range(3, 100, 11)' define.N = 'range(3, 100, 11)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "removeme%03d", i); sprintf(path, "removeme%03d", i);
lfs_mkdir(&lfs, path) => 0; lfs_mkdir(&lfs, path) => 0;
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -75,14 +75,14 @@ code = '''
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "removeme%03d", i); sprintf(path, "removeme%03d", i);
lfs_remove(&lfs, path) => 0; lfs_remove(&lfs, path) => 0;
} }
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -98,16 +98,16 @@ code = '''
[[case]] # many directory rename [[case]] # many directory rename
define.N = 'range(3, 100, 11)' define.N = 'range(3, 100, 11)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "test%03d", i); sprintf(path, "test%03d", i);
lfs_mkdir(&lfs, path) => 0; lfs_mkdir(&lfs, path) => 0;
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -125,7 +125,7 @@ code = '''
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
char oldpath[128]; char oldpath[128];
char newpath[128]; char newpath[128];
@@ -135,7 +135,7 @@ code = '''
} }
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -158,10 +158,10 @@ code = '''
define.N = [5, 11] define.N = [5, 11]
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
@@ -237,9 +237,9 @@ code = '''
[[case]] # file creation [[case]] # file creation
define.N = 'range(3, 100, 11)' define.N = 'range(3, 100, 11)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "file%03d", i); sprintf(path, "file%03d", i);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
@@ -248,7 +248,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -270,9 +270,9 @@ code = '''
[[case]] # file removal [[case]] # file removal
define.N = 'range(0, 100, 3)' define.N = 'range(0, 100, 3)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "removeme%03d", i); sprintf(path, "removeme%03d", i);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
@@ -281,7 +281,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -299,14 +299,14 @@ code = '''
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "removeme%03d", i); sprintf(path, "removeme%03d", i);
lfs_remove(&lfs, path) => 0; lfs_remove(&lfs, path) => 0;
} }
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -322,9 +322,9 @@ code = '''
[[case]] # file rename [[case]] # file rename
define.N = 'range(0, 100, 3)' define.N = 'range(0, 100, 3)'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "test%03d", i); sprintf(path, "test%03d", i);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
@@ -333,7 +333,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -351,7 +351,7 @@ code = '''
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
char oldpath[128]; char oldpath[128];
char newpath[128]; char newpath[128];
@@ -361,7 +361,7 @@ code = '''
} }
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -384,10 +384,10 @@ code = '''
define.N = [5, 25] define.N = [5, 25]
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
@@ -462,21 +462,21 @@ code = '''
[[case]] # nested directories [[case]] # nested directories
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "potato") => 0; lfs_mkdir(&lfs, "potato") => 0;
lfs_file_open(&lfs, &file, "burito", lfs_file_open(&lfs, &file, "burito",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "potato/baked") => 0; lfs_mkdir(&lfs, "potato/baked") => 0;
lfs_mkdir(&lfs, "potato/sweet") => 0; lfs_mkdir(&lfs, "potato/sweet") => 0;
lfs_mkdir(&lfs, "potato/fried") => 0; lfs_mkdir(&lfs, "potato/fried") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "potato") => 0; lfs_dir_open(&lfs, &dir, "potato") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -498,21 +498,21 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// try removing? // try removing?
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY; lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// try renaming? // try renaming?
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "potato", "coldpotato") => 0; lfs_rename(&lfs, "potato", "coldpotato") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "coldpotato", "warmpotato") => 0; lfs_rename(&lfs, "coldpotato", "warmpotato") => 0;
lfs_rename(&lfs, "warmpotato", "hotpotato") => 0; lfs_rename(&lfs, "warmpotato", "hotpotato") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_remove(&lfs, "potato") => LFS_ERR_NOENT; lfs_remove(&lfs, "potato") => LFS_ERR_NOENT;
lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT; lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT;
lfs_remove(&lfs, "warmpotato") => LFS_ERR_NOENT; lfs_remove(&lfs, "warmpotato") => LFS_ERR_NOENT;
@@ -520,7 +520,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// try cross-directory renaming // try cross-directory renaming
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "coldpotato") => 0; lfs_mkdir(&lfs, "coldpotato") => 0;
lfs_rename(&lfs, "hotpotato/baked", "coldpotato/baked") => 0; lfs_rename(&lfs, "hotpotato/baked", "coldpotato/baked") => 0;
lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY; lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY;
@@ -536,7 +536,7 @@ code = '''
lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "hotpotato") => 0; lfs_dir_open(&lfs, &dir, "hotpotato") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -558,7 +558,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// final remove // final remove
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
lfs_remove(&lfs, "hotpotato/baked") => 0; lfs_remove(&lfs, "hotpotato/baked") => 0;
lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
@@ -568,7 +568,7 @@ code = '''
lfs_remove(&lfs, "hotpotato") => 0; lfs_remove(&lfs, "hotpotato") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -587,8 +587,8 @@ code = '''
[[case]] # recursive remove [[case]] # recursive remove
define.N = [10, 100] define.N = [10, 100]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "prickly-pear") => 0; lfs_mkdir(&lfs, "prickly-pear") => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "prickly-pear/cactus%03d", i); sprintf(path, "prickly-pear/cactus%03d", i);
@@ -611,7 +611,7 @@ code = '''
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs); lfs_unmount(&lfs);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY; lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY;
lfs_dir_open(&lfs, &dir, "prickly-pear") => 0; lfs_dir_open(&lfs, &dir, "prickly-pear") => 0;
@@ -636,22 +636,22 @@ code = '''
lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
[[case]] # other error cases [[case]] # other error cases
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "potato") => 0; lfs_mkdir(&lfs, "potato") => 0;
lfs_file_open(&lfs, &file, "burito", lfs_file_open(&lfs, &file, "burito",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST;
lfs_mkdir(&lfs, "burito") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "burito") => LFS_ERR_EXIST;
@@ -696,7 +696,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// or on disk // or on disk
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -718,8 +718,8 @@ code = '''
[[case]] # directory seek [[case]] # directory seek
define.COUNT = [4, 128, 132] define.COUNT = [4, 128, 132]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "hello") => 0; lfs_mkdir(&lfs, "hello") => 0;
for (int i = 0; i < COUNT; i++) { for (int i = 0; i < COUNT; i++) {
sprintf(path, "hello/kitty%03d", i); sprintf(path, "hello/kitty%03d", i);
@@ -728,7 +728,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
for (int j = 2; j < COUNT; j++) { for (int j = 2; j < COUNT; j++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "hello") => 0; lfs_dir_open(&lfs, &dir, "hello") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -779,8 +779,8 @@ code = '''
[[case]] # root seek [[case]] # root seek
define.COUNT = [4, 128, 132] define.COUNT = [4, 128, 132]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < COUNT; i++) { for (int i = 0; i < COUNT; i++) {
sprintf(path, "hi%03d", i); sprintf(path, "hi%03d", i);
lfs_mkdir(&lfs, path) => 0; lfs_mkdir(&lfs, path) => 0;
@@ -788,7 +788,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
for (int j = 2; j < COUNT; j++) { for (int j = 2; j < COUNT; j++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);

View File

@@ -10,8 +10,8 @@ code = '''
uint8_t wbuffer[1024]; uint8_t wbuffer[1024];
uint8_t rbuffer[1024]; uint8_t rbuffer[1024];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// write hi0 20 // write hi0 20
sprintf(path, "hi0"); size = 20; sprintf(path, "hi0"); size = 20;
@@ -99,8 +99,8 @@ code = '''
uint8_t wbuffer[1024]; uint8_t wbuffer[1024];
uint8_t rbuffer[1024]; uint8_t rbuffer[1024];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// write hi0 20 // write hi0 20
sprintf(path, "hi0"); size = 20; sprintf(path, "hi0"); size = 20;
@@ -188,8 +188,8 @@ code = '''
uint8_t wbuffer[1024]; uint8_t wbuffer[1024];
uint8_t rbuffer[1024]; uint8_t rbuffer[1024];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// write hi0 200 // write hi0 200
sprintf(path, "hi0"); size = 200; sprintf(path, "hi0"); size = 200;
@@ -261,8 +261,8 @@ code = '''
uint8_t wbuffer[1024]; uint8_t wbuffer[1024];
uint8_t rbuffer[1024]; uint8_t rbuffer[1024];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// write hi0 200 // write hi0 200
sprintf(path, "hi0"); size = 200; sprintf(path, "hi0"); size = 200;
@@ -350,8 +350,8 @@ code = '''
uint8_t wbuffer[1024]; uint8_t wbuffer[1024];
uint8_t rbuffer[1024]; uint8_t rbuffer[1024];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// write hi0 200 // write hi0 200
sprintf(path, "hi0"); size = 200; sprintf(path, "hi0"); size = 200;
@@ -454,8 +454,8 @@ code = '''
uint8_t wbuffer[1024]; uint8_t wbuffer[1024];
uint8_t rbuffer[1024]; uint8_t rbuffer[1024];
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// write hi0 200 // write hi0 200
sprintf(path, "hi0"); size = 200; sprintf(path, "hi0"); size = 200;
@@ -549,9 +549,9 @@ code = '''
[[case]] # create too big [[case]] # create too big
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(path, 'm', 200); memset(path, 'm', 200);
path[200] = '\0'; path[200] = '\0';
@@ -574,9 +574,9 @@ code = '''
[[case]] # resize too big [[case]] # resize too big
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
memset(path, 'm', 200); memset(path, 'm', 200);
path[200] = '\0'; path[200] = '\0';

View File

@@ -9,10 +9,10 @@ define.INVALSET = [0x3, 0x1, 0x2]
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
// create littlefs // create littlefs
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// change tail-pointer to invalid pointers // change tail-pointer to invalid pointers
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
@@ -23,7 +23,7 @@ code = '''
lfs_deinit(&lfs) => 0; lfs_deinit(&lfs) => 0;
// test that mount fails gracefully // test that mount fails gracefully
lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
''' '''
[[case]] # invalid dir pointer test [[case]] # invalid dir pointer test
@@ -31,14 +31,14 @@ define.INVALSET = [0x3, 0x1, 0x2]
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
// create littlefs // create littlefs
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// make a dir // make a dir
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "dir_here") => 0; lfs_mkdir(&lfs, "dir_here") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// change the dir pointer to be invalid // change the dir pointer to be invalid
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
// make sure id 1 == our directory // make sure id 1 == our directory
@@ -57,7 +57,7 @@ code = '''
// test that accessing our bad dir fails, note there's a number // 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 // of ways to access the dir, some can fail, but some don't
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "dir_here", &info) => 0; lfs_stat(&lfs, "dir_here", &info) => 0;
assert(strcmp(info.name, "dir_here") == 0); assert(strcmp(info.name, "dir_here") == 0);
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -77,16 +77,16 @@ in = "lfs.c"
define.SIZE = [10, 1000, 100000] # faked file size define.SIZE = [10, 1000, 100000] # faked file size
code = ''' code = '''
// create littlefs // create littlefs
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// make a file // make a file
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "file_here", lfs_file_open(&lfs, &file, "file_here",
LFS_O_WRONLY | LFS_O_CREAT) => 0; LFS_O_WRONLY | LFS_O_CREAT) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// change the file pointer to be invalid // change the file pointer to be invalid
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
// make sure id 1 == our file // make sure id 1 == our file
@@ -103,7 +103,7 @@ code = '''
// test that accessing our bad file fails, note there's a number // 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 // of ways to access the dir, some can fail, but some don't
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "file_here", &info) => 0; lfs_stat(&lfs, "file_here", &info) => 0;
assert(strcmp(info.name, "file_here") == 0); assert(strcmp(info.name, "file_here") == 0);
assert(info.type == LFS_TYPE_REG); 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" in = "lfs.c"
code = ''' code = '''
// create littlefs // create littlefs
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// make a file // make a file
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "file_here", lfs_file_open(&lfs, &file, "file_here",
LFS_O_WRONLY | LFS_O_CREAT) => 0; LFS_O_WRONLY | LFS_O_CREAT) => 0;
for (int i = 0; i < SIZE; i++) { for (int i = 0; i < SIZE; i++) {
@@ -137,7 +137,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// change pointer in CTZ skip-list to be invalid // change pointer in CTZ skip-list to be invalid
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
// make sure id 1 == our file and get our CTZ structure // make sure id 1 == our file and get our CTZ structure
@@ -154,17 +154,17 @@ code = '''
lfs_ctz_fromle32(&ctz); lfs_ctz_fromle32(&ctz);
// rewrite block to contain bad pointer // rewrite block to contain bad pointer
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
uint32_t bad = lfs_tole32(0xcccccccc); uint32_t bad = lfs_tole32(0xcccccccc);
memcpy(&bbuffer[0], &bad, sizeof(bad)); memcpy(&bbuffer[0], &bad, sizeof(bad));
memcpy(&bbuffer[4], &bad, sizeof(bad)); memcpy(&bbuffer[4], &bad, sizeof(bad));
lfs_testbd_erase(&bd, ctz.head) => 0; cfg.erase(&cfg, ctz.head) => 0;
lfs_testbd_prog(&bd, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_deinit(&lfs) => 0; lfs_deinit(&lfs) => 0;
// test that accessing our bad file fails, note there's a number // 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 // of ways to access the dir, some can fail, but some don't
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "file_here", &info) => 0; lfs_stat(&lfs, "file_here", &info) => 0;
assert(strcmp(info.name, "file_here") == 0); assert(strcmp(info.name, "file_here") == 0);
assert(info.type == LFS_TYPE_REG); assert(info.type == LFS_TYPE_REG);
@@ -187,10 +187,10 @@ define.INVALSET = [0x3, 0x1, 0x2]
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
// create littlefs // create littlefs
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// create an invalid gstate // create an invalid gstate
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
lfs_fs_prepmove(&lfs, 1, (lfs_block_t [2]){ lfs_fs_prepmove(&lfs, 1, (lfs_block_t [2]){
@@ -202,7 +202,7 @@ code = '''
// test that mount fails gracefully // test that mount fails gracefully
// mount may not fail, but our first alloc should fail when // mount may not fail, but our first alloc should fail when
// we try to fix the gstate // we try to fix the gstate
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "should_fail") => LFS_ERR_CORRUPT; lfs_mkdir(&lfs, "should_fail") => LFS_ERR_CORRUPT;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -213,10 +213,10 @@ code = '''
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
// create littlefs // create littlefs
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// change tail-pointer to point to ourself // change tail-pointer to point to ourself
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
@@ -225,20 +225,20 @@ code = '''
lfs_deinit(&lfs) => 0; lfs_deinit(&lfs) => 0;
// test that mount fails gracefully // test that mount fails gracefully
lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
''' '''
[[case]] # metadata-pair threaded-list 2-length loop test [[case]] # metadata-pair threaded-list 2-length loop test
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
// create littlefs with child dir // create littlefs with child dir
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "child") => 0; lfs_mkdir(&lfs, "child") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// find child // find child
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_block_t pair[2]; lfs_block_t pair[2];
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
@@ -255,20 +255,20 @@ code = '''
lfs_deinit(&lfs) => 0; lfs_deinit(&lfs) => 0;
// test that mount fails gracefully // test that mount fails gracefully
lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
''' '''
[[case]] # metadata-pair threaded-list 1-length child loop test [[case]] # metadata-pair threaded-list 1-length child loop test
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
// create littlefs with child dir // create littlefs with child dir
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "child") => 0; lfs_mkdir(&lfs, "child") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// find child // find child
lfs_initcommon(&lfs, &cfg) => 0; lfs_init(&lfs, &cfg) => 0;
lfs_mdir_t mdir; lfs_mdir_t mdir;
lfs_block_t pair[2]; lfs_block_t pair[2];
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
@@ -284,5 +284,5 @@ code = '''
lfs_deinit(&lfs) => 0; lfs_deinit(&lfs) => 0;
// test that mount fails gracefully // test that mount fails gracefully
lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
''' '''

View File

@@ -11,14 +11,14 @@ define.LFS_BADBLOCK_BEHAVIOR = [
] ]
define.FILES = 10 define.FILES = 10
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "roadrunner") => 0; lfs_mkdir(&lfs, "roadrunner") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint32_t cycle = 0; uint32_t cycle = 0;
while (true) { while (true) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// chose name, roughly random seed, and random 2^n size // chose name, roughly random seed, and random 2^n size
sprintf(path, "roadrunner/test%d", i); sprintf(path, "roadrunner/test%d", i);
@@ -71,7 +71,7 @@ code = '''
exhausted: exhausted:
// should still be readable // should still be readable
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// check for errors // check for errors
sprintf(path, "roadrunner/test%d", i); sprintf(path, "roadrunner/test%d", i);
@@ -96,11 +96,11 @@ define.LFS_BADBLOCK_BEHAVIOR = [
] ]
define.FILES = 10 define.FILES = 10
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
uint32_t cycle = 0; uint32_t cycle = 0;
while (true) { while (true) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// chose name, roughly random seed, and random 2^n size // chose name, roughly random seed, and random 2^n size
sprintf(path, "test%d", i); sprintf(path, "test%d", i);
@@ -153,7 +153,7 @@ code = '''
exhausted: exhausted:
// should still be readable // should still be readable
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// check for errors // check for errors
sprintf(path, "test%d", i); sprintf(path, "test%d", i);
@@ -180,18 +180,18 @@ code = '''
for (int run = 0; run < 2; run++) { for (int run = 0; run < 2; run++) {
for (lfs_block_t b = 0; b < LFS_BLOCK_COUNT; b++) { for (lfs_block_t b = 0; b < LFS_BLOCK_COUNT; b++) {
lfs_testbd_setwear(&bd, b, lfs_testbd_setwear(&cfg, b,
(b < run_block_count[run]) ? 0 : LFS_ERASE_CYCLES) => 0; (b < run_block_count[run]) ? 0 : LFS_ERASE_CYCLES) => 0;
} }
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "roadrunner") => 0; lfs_mkdir(&lfs, "roadrunner") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint32_t cycle = 0; uint32_t cycle = 0;
while (true) { while (true) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// chose name, roughly random seed, and random 2^n size // chose name, roughly random seed, and random 2^n size
sprintf(path, "roadrunner/test%d", i); sprintf(path, "roadrunner/test%d", i);
@@ -244,7 +244,7 @@ code = '''
exhausted: exhausted:
// should still be readable // should still be readable
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// check for errors // check for errors
sprintf(path, "roadrunner/test%d", i); sprintf(path, "roadrunner/test%d", i);
@@ -272,15 +272,15 @@ code = '''
for (int run = 0; run < 2; run++) { for (int run = 0; run < 2; run++) {
for (lfs_block_t b = 0; b < LFS_BLOCK_COUNT; b++) { for (lfs_block_t b = 0; b < LFS_BLOCK_COUNT; b++) {
lfs_testbd_setwear(&bd, b, lfs_testbd_setwear(&cfg, b,
(b < run_block_count[run]) ? 0 : LFS_ERASE_CYCLES) => 0; (b < run_block_count[run]) ? 0 : LFS_ERASE_CYCLES) => 0;
} }
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
uint32_t cycle = 0; uint32_t cycle = 0;
while (true) { while (true) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// chose name, roughly random seed, and random 2^n size // chose name, roughly random seed, and random 2^n size
sprintf(path, "test%d", i); sprintf(path, "test%d", i);
@@ -333,7 +333,7 @@ code = '''
exhausted: exhausted:
// should still be readable // should still be readable
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// check for errors // check for errors
sprintf(path, "test%d", i); sprintf(path, "test%d", i);
@@ -358,14 +358,14 @@ define.CYCLES = 100
define.FILES = 10 define.FILES = 10
if = 'LFS_BLOCK_CYCLES < CYCLES/10' if = 'LFS_BLOCK_CYCLES < CYCLES/10'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "roadrunner") => 0; lfs_mkdir(&lfs, "roadrunner") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint32_t cycle = 0; uint32_t cycle = 0;
while (cycle < CYCLES) { while (cycle < CYCLES) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// chose name, roughly random seed, and random 2^n size // chose name, roughly random seed, and random 2^n size
sprintf(path, "roadrunner/test%d", i); sprintf(path, "roadrunner/test%d", i);
@@ -418,7 +418,7 @@ code = '''
exhausted: exhausted:
// should still be readable // should still be readable
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (uint32_t i = 0; i < FILES; i++) { for (uint32_t i = 0; i < FILES; i++) {
// check for errors // check for errors
sprintf(path, "roadrunner/test%d", i); sprintf(path, "roadrunner/test%d", i);
@@ -434,7 +434,7 @@ exhausted:
lfs_testbd_wear_t maxwear = 0; lfs_testbd_wear_t maxwear = 0;
// skip 0 and 1 as superblock movement is intentionally avoided // skip 0 and 1 as superblock movement is intentionally avoided
for (lfs_block_t b = 2; b < LFS_BLOCK_COUNT; b++) { for (lfs_block_t b = 2; b < LFS_BLOCK_COUNT; b++) {
lfs_testbd_wear_t wear = lfs_testbd_getwear(&bd, b); lfs_testbd_wear_t wear = lfs_testbd_getwear(&cfg, b);
printf("%08x: wear %d\n", b, wear); printf("%08x: wear %d\n", b, wear);
assert(wear >= 0); assert(wear >= 0);
if (wear < minwear) { if (wear < minwear) {
@@ -453,7 +453,7 @@ exhausted:
// find standard deviation^2 // find standard deviation^2
lfs_testbd_wear_t dev2 = 0; lfs_testbd_wear_t dev2 = 0;
for (lfs_block_t b = 2; b < LFS_BLOCK_COUNT; b++) { for (lfs_block_t b = 2; b < LFS_BLOCK_COUNT; b++) {
lfs_testbd_wear_t wear = lfs_testbd_getwear(&bd, b); lfs_testbd_wear_t wear = lfs_testbd_getwear(&cfg, b);
assert(wear >= 0); assert(wear >= 0);
lfs_testbd_swear_t diff = wear - avgwear; lfs_testbd_swear_t diff = wear - avgwear;
dev2 += diff*diff; dev2 += diff*diff;

View File

@@ -1,8 +1,8 @@
[[case]] # simple file test [[case]] # simple file test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "hello", lfs_file_open(&lfs, &file, "hello",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
size = strlen("Hello World!")+1; size = strlen("Hello World!")+1;
@@ -11,7 +11,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0;
lfs_file_read(&lfs, &file, buffer, size) => size; lfs_file_read(&lfs, &file, buffer, size) => size;
assert(strcmp((char*)buffer, "Hello World!") == 0); assert(strcmp((char*)buffer, "Hello World!") == 0);
@@ -23,10 +23,10 @@ code = '''
define.SIZE = [32, 8192, 262144, 0, 7, 8193] define.SIZE = [32, 8192, 262144, 0, 7, 8193]
define.CHUNKSIZE = [31, 16, 33, 1, 1023] define.CHUNKSIZE = [31, 16, 33, 1, 1023]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// write // write
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", lfs_file_open(&lfs, &file, "avacado",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
srand(1); srand(1);
@@ -41,7 +41,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => SIZE; lfs_file_size(&lfs, &file) => SIZE;
srand(1); srand(1);
@@ -62,10 +62,10 @@ define.SIZE1 = [32, 8192, 131072, 0, 7, 8193]
define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] define.SIZE2 = [32, 8192, 131072, 0, 7, 8193]
define.CHUNKSIZE = [31, 16, 1] define.CHUNKSIZE = [31, 16, 1]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// write // write
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", lfs_file_open(&lfs, &file, "avacado",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
srand(1); srand(1);
@@ -80,7 +80,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => SIZE1; lfs_file_size(&lfs, &file) => SIZE1;
srand(1); srand(1);
@@ -96,7 +96,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// rewrite // rewrite
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY) => 0;
srand(2); srand(2);
for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) {
@@ -110,7 +110,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => lfs_max(SIZE1, SIZE2); lfs_file_size(&lfs, &file) => lfs_max(SIZE1, SIZE2);
srand(2); srand(2);
@@ -144,10 +144,10 @@ define.SIZE1 = [32, 8192, 131072, 0, 7, 8193]
define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] define.SIZE2 = [32, 8192, 131072, 0, 7, 8193]
define.CHUNKSIZE = [31, 16, 1] define.CHUNKSIZE = [31, 16, 1]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// write // write
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", lfs_file_open(&lfs, &file, "avacado",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
srand(1); srand(1);
@@ -162,7 +162,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => SIZE1; lfs_file_size(&lfs, &file) => SIZE1;
srand(1); srand(1);
@@ -178,7 +178,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// append // append
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_APPEND) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_APPEND) => 0;
srand(2); srand(2);
for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) {
@@ -192,7 +192,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => SIZE1 + SIZE2; lfs_file_size(&lfs, &file) => SIZE1 + SIZE2;
srand(1); srand(1);
@@ -221,10 +221,10 @@ define.SIZE1 = [32, 8192, 131072, 0, 7, 8193]
define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] define.SIZE2 = [32, 8192, 131072, 0, 7, 8193]
define.CHUNKSIZE = [31, 16, 1] define.CHUNKSIZE = [31, 16, 1]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// write // write
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", lfs_file_open(&lfs, &file, "avacado",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
srand(1); srand(1);
@@ -239,7 +239,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => SIZE1; lfs_file_size(&lfs, &file) => SIZE1;
srand(1); srand(1);
@@ -255,7 +255,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// truncate // truncate
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_TRUNC) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_TRUNC) => 0;
srand(2); srand(2);
for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) {
@@ -269,7 +269,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// read // read
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => SIZE2; lfs_file_size(&lfs, &file) => SIZE2;
srand(2); srand(2);
@@ -290,10 +290,10 @@ define.SIZE = [32, 0, 7, 2049]
define.CHUNKSIZE = [31, 16, 65] define.CHUNKSIZE = [31, 16, 65]
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY);
@@ -344,10 +344,10 @@ define = [
] ]
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY);
@@ -406,9 +406,9 @@ code = '''
[[case]] # many files [[case]] # many files
define.N = 300 define.N = 300
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// create N files of 7 bytes // create N files of 7 bytes
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "file_%03d", i); sprintf(path, "file_%03d", i);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
@@ -431,9 +431,9 @@ code = '''
[[case]] # many files with power cycle [[case]] # many files with power cycle
define.N = 300 define.N = 300
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// create N files of 7 bytes // create N files of 7 bytes
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
sprintf(path, "file_%03d", i); sprintf(path, "file_%03d", i);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
@@ -446,7 +446,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
char rbuffer[1024]; char rbuffer[1024];
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0;
lfs_file_read(&lfs, &file, rbuffer, size) => size; lfs_file_read(&lfs, &file, rbuffer, size) => size;
assert(strcmp(rbuffer, wbuffer) == 0); assert(strcmp(rbuffer, wbuffer) == 0);
@@ -459,10 +459,10 @@ code = '''
define.N = 300 define.N = 300
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
// create N files of 7 bytes // create N files of 7 bytes
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {

View File

@@ -5,8 +5,8 @@ define.FILES = [4, 10, 26]
code = ''' code = '''
lfs_file_t files[FILES]; lfs_file_t files[FILES];
const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int j = 0; j < FILES; j++) { for (int j = 0; j < FILES; j++) {
sprintf(path, "%c", alphas[j]); sprintf(path, "%c", alphas[j]);
lfs_file_open(&lfs, &files[j], path, lfs_file_open(&lfs, &files[j], path,
@@ -64,8 +64,8 @@ define.SIZE = [10, 100]
define.FILES = [4, 10, 26] define.FILES = [4, 10, 26]
code = ''' code = '''
const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int j = 0; j < FILES; j++) { for (int j = 0; j < FILES; j++) {
sprintf(path, "%c", alphas[j]); sprintf(path, "%c", alphas[j]);
lfs_file_open(&lfs, &file, path, lfs_file_open(&lfs, &file, path,
@@ -77,7 +77,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "zzz", LFS_O_WRONLY | LFS_O_CREAT) => 0; lfs_file_open(&lfs, &file, "zzz", LFS_O_WRONLY | LFS_O_CREAT) => 0;
for (int j = 0; j < FILES; j++) { for (int j = 0; j < FILES; j++) {
lfs_file_write(&lfs, &file, (const void*)"~", 1) => 1; lfs_file_write(&lfs, &file, (const void*)"~", 1) => 1;
@@ -115,8 +115,8 @@ code = '''
[[case]] # remove inconveniently test [[case]] # remove inconveniently test
define.SIZE = [10, 100] define.SIZE = [10, 100]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_t files[3]; lfs_file_t files[3];
lfs_file_open(&lfs, &files[0], "e", LFS_O_WRONLY | LFS_O_CREAT) => 0; 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; lfs_file_open(&lfs, &files[1], "f", LFS_O_WRONLY | LFS_O_CREAT) => 0;
@@ -180,10 +180,10 @@ code = '''
lfs_file_t files[FILES]; lfs_file_t files[FILES];
const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
for (int j = 0; j < FILES; j++) { for (int j = 0; j < FILES; j++) {

View File

@@ -1,7 +1,7 @@
[[case]] # move file [[case]] # move file
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -13,11 +13,11 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hello", "c/hello") => 0; lfs_rename(&lfs, "a/hello", "c/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -57,8 +57,8 @@ code = '''
[[case]] # noop move, yes this is legal [[case]] # noop move, yes this is legal
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "hi") => 0; lfs_mkdir(&lfs, "hi") => 0;
lfs_rename(&lfs, "hi", "hi") => 0; lfs_rename(&lfs, "hi", "hi") => 0;
lfs_mkdir(&lfs, "hi/hi") => 0; lfs_mkdir(&lfs, "hi/hi") => 0;
@@ -74,8 +74,8 @@ code = '''
[[case]] # move file corrupt source [[case]] # move file corrupt source
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -87,28 +87,28 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hello", "c/hello") => 0; lfs_rename(&lfs, "a/hello", "c/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// corrupt the source // corrupt the source
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -150,8 +150,8 @@ code = '''
in = "lfs.c" in = "lfs.c"
if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -163,44 +163,44 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hello", "c/hello") => 0; lfs_rename(&lfs, "a/hello", "c/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// corrupt the source // corrupt the source
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
// corrupt the destination // corrupt the destination
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "c") => 0; lfs_dir_open(&lfs, &dir, "c") => 0;
block = dir.m.pair[0]; block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
off = LFS_BLOCK_SIZE-1; off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -242,8 +242,8 @@ code = '''
in = "lfs.c" in = "lfs.c"
if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -255,49 +255,49 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hello", "c/hello") => 0; lfs_rename(&lfs, "a/hello", "c/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// corrupt the source // corrupt the source
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
// corrupt the destination // corrupt the destination
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "c") => 0; lfs_dir_open(&lfs, &dir, "c") => 0;
block = dir.m.pair[0]; block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
off = LFS_BLOCK_SIZE-1; off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
// continue move // continue move
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hello", "c/hello") => 0; lfs_rename(&lfs, "a/hello", "c/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -338,10 +338,10 @@ code = '''
[[case]] # simple reentrant move file [[case]] # simple reentrant move file
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
err = lfs_mkdir(&lfs, "a"); err = lfs_mkdir(&lfs, "a");
assert(!err || err == LFS_ERR_EXIST); assert(!err || err == LFS_ERR_EXIST);
@@ -354,7 +354,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
while (true) { while (true) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// there should never exist _2_ hello files // there should never exist _2_ hello files
int count = 0; int count = 0;
if (lfs_stat(&lfs, "a/hello", &info) == 0) { if (lfs_stat(&lfs, "a/hello", &info) == 0) {
@@ -384,7 +384,7 @@ code = '''
assert(count <= 1); assert(count <= 1);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
if (lfs_stat(&lfs, "a/hello", &info) == 0 && info.size > 0) { if (lfs_stat(&lfs, "a/hello", &info) == 0 && info.size > 0) {
lfs_rename(&lfs, "a/hello", "b/hello") => 0; lfs_rename(&lfs, "a/hello", "b/hello") => 0;
} else if (lfs_stat(&lfs, "b/hello", &info) == 0) { } else if (lfs_stat(&lfs, "b/hello", &info) == 0) {
@@ -407,7 +407,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
} }
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -447,8 +447,8 @@ code = '''
[[case]] # move dir [[case]] # move dir
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -459,11 +459,11 @@ code = '''
lfs_mkdir(&lfs, "a/hi/ohayo") => 0; lfs_mkdir(&lfs, "a/hi/ohayo") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hi", "c/hi") => 0; lfs_rename(&lfs, "a/hi", "c/hi") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -513,8 +513,8 @@ code = '''
[[case]] # move dir corrupt source [[case]] # move dir corrupt source
in = "lfs.c" in = "lfs.c"
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -525,28 +525,28 @@ code = '''
lfs_mkdir(&lfs, "a/hi/ohayo") => 0; lfs_mkdir(&lfs, "a/hi/ohayo") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hi", "c/hi") => 0; lfs_rename(&lfs, "a/hi", "c/hi") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// corrupt the source // corrupt the source
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -597,8 +597,8 @@ code = '''
in = "lfs.c" in = "lfs.c"
if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -609,44 +609,44 @@ code = '''
lfs_mkdir(&lfs, "a/hi/ohayo") => 0; lfs_mkdir(&lfs, "a/hi/ohayo") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hi", "c/hi") => 0; lfs_rename(&lfs, "a/hi", "c/hi") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// corrupt the source // corrupt the source
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
// corrupt the destination // corrupt the destination
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "c") => 0; lfs_dir_open(&lfs, &dir, "c") => 0;
block = dir.m.pair[0]; block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
off = LFS_BLOCK_SIZE-1; off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -697,8 +697,8 @@ code = '''
in = "lfs.c" in = "lfs.c"
if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -709,49 +709,49 @@ code = '''
lfs_mkdir(&lfs, "a/hi/ohayo") => 0; lfs_mkdir(&lfs, "a/hi/ohayo") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hi", "c/hi") => 0; lfs_rename(&lfs, "a/hi", "c/hi") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// corrupt the source // corrupt the source
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
// corrupt the destination // corrupt the destination
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "c") => 0; lfs_dir_open(&lfs, &dir, "c") => 0;
block = dir.m.pair[0]; block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
off = LFS_BLOCK_SIZE-1; off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
// continue move // continue move
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hi", "c/hi") => 0; lfs_rename(&lfs, "a/hi", "c/hi") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -801,10 +801,10 @@ code = '''
[[case]] # simple reentrant move dir [[case]] # simple reentrant move dir
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
err = lfs_mkdir(&lfs, "a"); err = lfs_mkdir(&lfs, "a");
assert(!err || err == LFS_ERR_EXIST); assert(!err || err == LFS_ERR_EXIST);
@@ -817,7 +817,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
while (true) { while (true) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// there should never exist _2_ hi directories // there should never exist _2_ hi directories
int count = 0; int count = 0;
if (lfs_stat(&lfs, "a/hi", &info) == 0) { if (lfs_stat(&lfs, "a/hi", &info) == 0) {
@@ -843,7 +843,7 @@ code = '''
assert(count <= 1); assert(count <= 1);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
if (lfs_stat(&lfs, "a/hi", &info) == 0) { if (lfs_stat(&lfs, "a/hi", &info) == 0) {
lfs_rename(&lfs, "a/hi", "b/hi") => 0; lfs_rename(&lfs, "a/hi", "b/hi") => 0;
} else if (lfs_stat(&lfs, "b/hi", &info) == 0) { } else if (lfs_stat(&lfs, "b/hi", &info) == 0) {
@@ -868,7 +868,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
} }
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "a") => 0; lfs_dir_open(&lfs, &dir, "a") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
assert(strcmp(info.name, ".") == 0); assert(strcmp(info.name, ".") == 0);
@@ -917,8 +917,8 @@ code = '''
[[case]] # move state stealing [[case]] # move state stealing
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "a") => 0; lfs_mkdir(&lfs, "a") => 0;
lfs_mkdir(&lfs, "b") => 0; lfs_mkdir(&lfs, "b") => 0;
lfs_mkdir(&lfs, "c") => 0; lfs_mkdir(&lfs, "c") => 0;
@@ -930,17 +930,17 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "a/hello", "b/hello") => 0; lfs_rename(&lfs, "a/hello", "b/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "b/hello", "c/hello") => 0; lfs_rename(&lfs, "b/hello", "c/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_rename(&lfs, "c/hello", "d/hello") => 0; lfs_rename(&lfs, "c/hello", "d/hello") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; 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, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT;
lfs_file_open(&lfs, &file, "c/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_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_remove(&lfs, "b") => 0; lfs_remove(&lfs, "b") => 0;
lfs_remove(&lfs, "c") => 0; lfs_remove(&lfs, "c") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "a", &info) => 0; lfs_stat(&lfs, "a", &info) => 0;
lfs_stat(&lfs, "b", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "b", &info) => LFS_ERR_NOENT;
lfs_stat(&lfs, "c", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "c", &info) => LFS_ERR_NOENT;
@@ -981,8 +981,8 @@ code = '''
# Other specific corner cases # Other specific corner cases
[[case]] # create + delete in same commit with neighbors [[case]] # create + delete in same commit with neighbors
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// littlefs keeps files sorted, so we know the order these will be in // littlefs keeps files sorted, so we know the order these will be in
lfs_file_open(&lfs, &file, "/1.move_me", lfs_file_open(&lfs, &file, "/1.move_me",
@@ -1127,8 +1127,8 @@ code = '''
# Other specific corner cases # Other specific corner cases
[[case]] # create + delete + delete in same commit with neighbors [[case]] # create + delete + delete in same commit with neighbors
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// littlefs keeps files sorted, so we know the order these will be in // littlefs keeps files sorted, so we know the order these will be in
lfs_file_open(&lfs, &file, "/1.move_me", lfs_file_open(&lfs, &file, "/1.move_me",
@@ -1283,8 +1283,8 @@ code = '''
[[case]] # create + delete in different dirs with neighbors [[case]] # create + delete in different dirs with neighbors
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// littlefs keeps files sorted, so we know the order these will be in // littlefs keeps files sorted, so we know the order these will be in
lfs_mkdir(&lfs, "/dir.1") => 0; lfs_mkdir(&lfs, "/dir.1") => 0;
@@ -1523,8 +1523,8 @@ in = "lfs.c"
define.RELOCATIONS = 'range(0x3+1)' define.RELOCATIONS = 'range(0x3+1)'
define.LFS_ERASE_CYCLES = 0xffffffff define.LFS_ERASE_CYCLES = 0xffffffff
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "/parent") => 0; lfs_mkdir(&lfs, "/parent") => 0;
lfs_mkdir(&lfs, "/parent/child") => 0; lfs_mkdir(&lfs, "/parent/child") => 0;
@@ -1569,14 +1569,14 @@ code = '''
// force specific directories to relocate // force specific directories to relocate
if (RELOCATIONS & 0x1) { if (RELOCATIONS & 0x1) {
lfs_dir_open(&lfs, &dir, "/parent"); lfs_dir_open(&lfs, &dir, "/parent");
lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0;
lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0;
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
} }
if (RELOCATIONS & 0x2) { if (RELOCATIONS & 0x2) {
lfs_dir_open(&lfs, &dir, "/parent/child"); lfs_dir_open(&lfs, &dir, "/parent/child");
lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0;
lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0;
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
} }
@@ -1660,8 +1660,8 @@ in = "lfs.c"
define.RELOCATIONS = 'range(0x7+1)' define.RELOCATIONS = 'range(0x7+1)'
define.LFS_ERASE_CYCLES = 0xffffffff define.LFS_ERASE_CYCLES = 0xffffffff
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "/parent") => 0; lfs_mkdir(&lfs, "/parent") => 0;
lfs_mkdir(&lfs, "/parent/child") => 0; lfs_mkdir(&lfs, "/parent/child") => 0;
@@ -1707,20 +1707,20 @@ code = '''
// force specific directories to relocate // force specific directories to relocate
if (RELOCATIONS & 0x1) { if (RELOCATIONS & 0x1) {
lfs_dir_open(&lfs, &dir, "/parent"); lfs_dir_open(&lfs, &dir, "/parent");
lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0;
lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0;
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
} }
if (RELOCATIONS & 0x2) { if (RELOCATIONS & 0x2) {
lfs_dir_open(&lfs, &dir, "/parent/sibling"); lfs_dir_open(&lfs, &dir, "/parent/sibling");
lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0;
lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0;
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
} }
if (RELOCATIONS & 0x4) { if (RELOCATIONS & 0x4) {
lfs_dir_open(&lfs, &dir, "/parent/child"); lfs_dir_open(&lfs, &dir, "/parent/child");
lfs_testbd_setwear(&bd, dir.m.pair[0], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[0], 0xffffffff) => 0;
lfs_testbd_setwear(&bd, dir.m.pair[1], 0xffffffff) => 0; lfs_testbd_setwear(&cfg, dir.m.pair[1], 0xffffffff) => 0;
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
} }

View File

@@ -2,8 +2,8 @@
in = "lfs.c" in = "lfs.c"
if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit if = 'LFS_PROG_SIZE <= 0x3fe' # only works with one crc per commit
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "parent") => 0; lfs_mkdir(&lfs, "parent") => 0;
lfs_mkdir(&lfs, "parent/orphan") => 0; lfs_mkdir(&lfs, "parent/orphan") => 0;
lfs_mkdir(&lfs, "parent/child") => 0; lfs_mkdir(&lfs, "parent/child") => 0;
@@ -13,29 +13,29 @@ code = '''
// corrupt the child's most recent commit, this should be the update // corrupt the child's most recent commit, this should be the update
// to the linked-list entry, which should orphan the orphan. Note this // to the linked-list entry, which should orphan the orphan. Note this
// makes a lot of assumptions about the remove operation. // makes a lot of assumptions about the remove operation.
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "parent/child") => 0; lfs_dir_open(&lfs, &dir, "parent/child") => 0;
lfs_block_t block = dir.m.pair[0]; lfs_block_t block = dir.m.pair[0];
lfs_dir_close(&lfs, &dir) => 0; lfs_dir_close(&lfs, &dir) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
uint8_t bbuffer[LFS_BLOCK_SIZE]; uint8_t bbuffer[LFS_BLOCK_SIZE];
lfs_testbd_read(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
int off = LFS_BLOCK_SIZE-1; int off = LFS_BLOCK_SIZE-1;
while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) {
off -= 1; off -= 1;
} }
memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3);
lfs_testbd_erase(&bd, block) => 0; cfg.erase(&cfg, block) => 0;
lfs_testbd_prog(&bd, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
lfs_testbd_sync(&bd) => 0; cfg.sync(&cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
lfs_stat(&lfs, "parent/child", &info) => 0; lfs_stat(&lfs, "parent/child", &info) => 0;
lfs_fs_size(&lfs) => 8; lfs_fs_size(&lfs) => 8;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
lfs_stat(&lfs, "parent/child", &info) => 0; lfs_stat(&lfs, "parent/child", &info) => 0;
lfs_fs_size(&lfs) => 8; lfs_fs_size(&lfs) => 8;
@@ -48,7 +48,7 @@ code = '''
lfs_fs_size(&lfs) => 8; lfs_fs_size(&lfs) => 8;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
lfs_stat(&lfs, "parent/child", &info) => 0; lfs_stat(&lfs, "parent/child", &info) => 0;
lfs_stat(&lfs, "parent/otherchild", &info) => 0; lfs_stat(&lfs, "parent/otherchild", &info) => 0;
@@ -66,10 +66,10 @@ define = [
{FILES=3, DEPTH=3, CYCLES=20}, {FILES=3, DEPTH=3, CYCLES=20},
] ]
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
srand(1); srand(1);

View File

@@ -1,8 +1,8 @@
[[case]] # simple path test [[case]] # simple path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "tea") => 0; lfs_mkdir(&lfs, "tea") => 0;
lfs_mkdir(&lfs, "tea/hottea") => 0; lfs_mkdir(&lfs, "tea/hottea") => 0;
lfs_mkdir(&lfs, "tea/warmtea") => 0; lfs_mkdir(&lfs, "tea/warmtea") => 0;
@@ -23,8 +23,8 @@ code = '''
[[case]] # redundant slashes [[case]] # redundant slashes
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "tea") => 0; lfs_mkdir(&lfs, "tea") => 0;
lfs_mkdir(&lfs, "tea/hottea") => 0; lfs_mkdir(&lfs, "tea/hottea") => 0;
lfs_mkdir(&lfs, "tea/warmtea") => 0; lfs_mkdir(&lfs, "tea/warmtea") => 0;
@@ -47,8 +47,8 @@ code = '''
[[case]] # dot path test [[case]] # dot path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "tea") => 0; lfs_mkdir(&lfs, "tea") => 0;
lfs_mkdir(&lfs, "tea/hottea") => 0; lfs_mkdir(&lfs, "tea/hottea") => 0;
lfs_mkdir(&lfs, "tea/warmtea") => 0; lfs_mkdir(&lfs, "tea/warmtea") => 0;
@@ -73,8 +73,8 @@ code = '''
[[case]] # dot dot path test [[case]] # dot dot path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "tea") => 0; lfs_mkdir(&lfs, "tea") => 0;
lfs_mkdir(&lfs, "tea/hottea") => 0; lfs_mkdir(&lfs, "tea/hottea") => 0;
lfs_mkdir(&lfs, "tea/warmtea") => 0; lfs_mkdir(&lfs, "tea/warmtea") => 0;
@@ -103,8 +103,8 @@ code = '''
[[case]] # trailing dot path test [[case]] # trailing dot path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "tea") => 0; lfs_mkdir(&lfs, "tea") => 0;
lfs_mkdir(&lfs, "tea/hottea") => 0; lfs_mkdir(&lfs, "tea/hottea") => 0;
lfs_mkdir(&lfs, "tea/warmtea") => 0; lfs_mkdir(&lfs, "tea/warmtea") => 0;
@@ -125,8 +125,8 @@ code = '''
[[case]] # leading dot path test [[case]] # leading dot path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, ".milk") => 0; lfs_mkdir(&lfs, ".milk") => 0;
lfs_stat(&lfs, ".milk", &info) => 0; lfs_stat(&lfs, ".milk", &info) => 0;
strcmp(info.name, ".milk") => 0; strcmp(info.name, ".milk") => 0;
@@ -137,8 +137,8 @@ code = '''
[[case]] # root dot dot path test [[case]] # root dot dot path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "tea") => 0; lfs_mkdir(&lfs, "tea") => 0;
lfs_mkdir(&lfs, "tea/hottea") => 0; lfs_mkdir(&lfs, "tea/hottea") => 0;
lfs_mkdir(&lfs, "tea/warmtea") => 0; lfs_mkdir(&lfs, "tea/warmtea") => 0;
@@ -161,8 +161,8 @@ code = '''
[[case]] # invalid path tests [[case]] # invalid path tests
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg); lfs_format(&lfs, &cfg);
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "dirt", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "dirt", &info) => LFS_ERR_NOENT;
lfs_stat(&lfs, "dirt/ground", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "dirt/ground", &info) => LFS_ERR_NOENT;
lfs_stat(&lfs, "dirt/ground/earth", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "dirt/ground/earth", &info) => LFS_ERR_NOENT;
@@ -182,8 +182,8 @@ code = '''
[[case]] # root operations [[case]] # root operations
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "/", &info) => 0; lfs_stat(&lfs, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0); assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -198,8 +198,8 @@ code = '''
[[case]] # root representations [[case]] # root representations
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "/", &info) => 0; lfs_stat(&lfs, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0); assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR); assert(info.type == LFS_TYPE_DIR);
@@ -223,8 +223,8 @@ code = '''
[[case]] # superblock conflict test [[case]] # superblock conflict test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT;
lfs_remove(&lfs, "littlefs") => LFS_ERR_NOENT; lfs_remove(&lfs, "littlefs") => LFS_ERR_NOENT;
@@ -239,8 +239,8 @@ code = '''
[[case]] # max path test [[case]] # max path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "coffee") => 0; lfs_mkdir(&lfs, "coffee") => 0;
lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; lfs_mkdir(&lfs, "coffee/hotcoffee") => 0;
lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; lfs_mkdir(&lfs, "coffee/warmcoffee") => 0;
@@ -263,8 +263,8 @@ code = '''
[[case]] # really big path test [[case]] # really big path test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, "coffee") => 0; lfs_mkdir(&lfs, "coffee") => 0;
lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; lfs_mkdir(&lfs, "coffee/hotcoffee") => 0;
lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; lfs_mkdir(&lfs, "coffee/warmcoffee") => 0;

View File

@@ -4,9 +4,9 @@ define.ITERATIONS = 20
define.COUNT = 10 define.COUNT = 10
define.LFS_BLOCK_CYCLES = [8, 1] define.LFS_BLOCK_CYCLES = [8, 1]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// fill up filesystem so only ~16 blocks are left // fill up filesystem so only ~16 blocks are left
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0;
memset(buffer, 0, 512); memset(buffer, 0, 512);
while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) {
@@ -17,7 +17,7 @@ code = '''
lfs_mkdir(&lfs, "child") => 0; lfs_mkdir(&lfs, "child") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int j = 0; j < ITERATIONS; j++) { for (int j = 0; j < ITERATIONS; j++) {
for (int i = 0; i < COUNT; i++) { for (int i = 0; i < COUNT; i++) {
sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); sprintf(path, "child/test%03d_loooooooooooooooooong_name", i);
@@ -47,7 +47,7 @@ code = '''
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "child") => 0; lfs_dir_open(&lfs, &dir, "child") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1; lfs_dir_read(&lfs, &dir, &info) => 1;
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.COUNT = 10
define.LFS_BLOCK_CYCLES = [8, 1] define.LFS_BLOCK_CYCLES = [8, 1]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
// fill up filesystem so only ~16 blocks are left // fill up filesystem so only ~16 blocks are left
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0;
memset(buffer, 0, 512); memset(buffer, 0, 512);
while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) {
@@ -83,7 +83,7 @@ code = '''
lfs_mkdir(&lfs, "child") => 0; lfs_mkdir(&lfs, "child") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int j = 0; j < ITERATIONS; j++) { for (int j = 0; j < ITERATIONS; j++) {
for (int i = 0; i < COUNT; i++) { for (int i = 0; i < COUNT; i++) {
sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); sprintf(path, "child/test%03d_loooooooooooooooooong_name", i);
@@ -155,10 +155,10 @@ define = [
{FILES=3, DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1}, {FILES=3, DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1},
] ]
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
srand(1); srand(1);
@@ -217,10 +217,10 @@ define = [
{FILES=3, DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1}, {FILES=3, DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1},
] ]
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
srand(1); srand(1);

View File

@@ -9,8 +9,8 @@ define = [
{COUNT=4, SKIP=2}, {COUNT=4, SKIP=2},
] ]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", lfs_file_open(&lfs, &file, "kitty",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
size = strlen("kittycatcat"); size = strlen("kittycatcat");
@@ -21,7 +21,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY) => 0;
lfs_soff_t pos = -1; lfs_soff_t pos = -1;
@@ -78,8 +78,8 @@ define = [
{COUNT=4, SKIP=2}, {COUNT=4, SKIP=2},
] ]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", lfs_file_open(&lfs, &file, "kitty",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
size = strlen("kittycatcat"); size = strlen("kittycatcat");
@@ -90,7 +90,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
lfs_soff_t pos = -1; lfs_soff_t pos = -1;
@@ -133,8 +133,8 @@ code = '''
define.COUNT = 132 define.COUNT = 132
define.OFFSETS = '"{512, 1020, 513, 1021, 511, 1019, 1441}"' define.OFFSETS = '"{512, 1020, 513, 1021, 511, 1019, 1441}"'
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", lfs_file_open(&lfs, &file, "kitty",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
size = strlen("kittycatcat"); size = strlen("kittycatcat");
@@ -145,7 +145,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
size = strlen("hedgehoghog"); size = strlen("hedgehoghog");
@@ -193,8 +193,8 @@ define = [
{COUNT=4, SKIP=3}, {COUNT=4, SKIP=3},
] ]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", lfs_file_open(&lfs, &file, "kitty",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
size = strlen("kittycatcat"); size = strlen("kittycatcat");
@@ -204,7 +204,7 @@ code = '''
} }
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
size = strlen("kittycatcat"); size = strlen("kittycatcat");
@@ -241,8 +241,8 @@ code = '''
[[case]] # inline write and seek [[case]] # inline write and seek
define.SIZE = [2, 4, 128, 132] define.SIZE = [2, 4, 128, 132]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "tinykitty", lfs_file_open(&lfs, &file, "tinykitty",
LFS_O_RDWR | LFS_O_CREAT) => 0; LFS_O_RDWR | LFS_O_CREAT) => 0;
int j = 0; int j = 0;
@@ -310,10 +310,10 @@ code = '''
define.COUNT = [4, 64, 128] define.COUNT = [4, 64, 128]
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
err = lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY); err = lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY);
assert(!err || err == LFS_ERR_NOENT); assert(!err || err == LFS_ERR_NOENT);

View File

@@ -1,37 +1,37 @@
[[case]] # simple formatting test [[case]] # simple formatting test
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
''' '''
[[case]] # mount/unmount [[case]] # mount/unmount
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
[[case]] # reentrant format [[case]] # reentrant format
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
[[case]] # invalid mount [[case]] # invalid mount
code = ''' code = '''
lfs_mountcfg(&lfs, &cfg) => LFS_ERR_CORRUPT; lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
''' '''
[[case]] # expanding superblock [[case]] # expanding superblock
define.LFS_BLOCK_CYCLES = [32, 33, 1] define.LFS_BLOCK_CYCLES = [32, 33, 1]
define.N = [10, 100, 1000] define.N = [10, 100, 1000]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
lfs_file_open(&lfs, &file, "dummy", lfs_file_open(&lfs, &file, "dummy",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
@@ -44,7 +44,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// one last check after power-cycle // one last check after power-cycle
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "dummy", lfs_file_open(&lfs, &file, "dummy",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
@@ -58,9 +58,9 @@ code = '''
define.LFS_BLOCK_CYCLES = [32, 33, 1] define.LFS_BLOCK_CYCLES = [32, 33, 1]
define.N = [10, 100, 1000] define.N = [10, 100, 1000]
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
// remove lingering dummy? // remove lingering dummy?
err = lfs_stat(&lfs, "dummy", &info); err = lfs_stat(&lfs, "dummy", &info);
assert(err == 0 || (err == LFS_ERR_NOENT && i == 0)); assert(err == 0 || (err == LFS_ERR_NOENT && i == 0));
@@ -80,7 +80,7 @@ code = '''
} }
// one last check after power-cycle // one last check after power-cycle
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "dummy", &info) => 0; lfs_stat(&lfs, "dummy", &info) => 0;
assert(strcmp(info.name, "dummy") == 0); assert(strcmp(info.name, "dummy") == 0);
assert(info.type == LFS_TYPE_REG); assert(info.type == LFS_TYPE_REG);
@@ -92,10 +92,10 @@ define.LFS_BLOCK_CYCLES = [2, 1]
define.N = 24 define.N = 24
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
@@ -119,7 +119,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
// one last check after power-cycle // one last check after power-cycle
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "dummy", &info) => 0; lfs_stat(&lfs, "dummy", &info) => 0;
assert(strcmp(info.name, "dummy") == 0); assert(strcmp(info.name, "dummy") == 0);
assert(info.type == LFS_TYPE_REG); assert(info.type == LFS_TYPE_REG);

View File

@@ -2,8 +2,8 @@
define.MEDIUMSIZE = [32, 2048] define.MEDIUMSIZE = [32, 2048]
define.LARGESIZE = 8192 define.LARGESIZE = 8192
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldynoop", lfs_file_open(&lfs, &file, "baldynoop",
LFS_O_WRONLY | LFS_O_CREAT) => 0; LFS_O_WRONLY | LFS_O_CREAT) => 0;
@@ -17,7 +17,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDWR) => 0;
lfs_file_size(&lfs, &file) => LARGESIZE; lfs_file_size(&lfs, &file) => LARGESIZE;
@@ -27,7 +27,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => MEDIUMSIZE; lfs_file_size(&lfs, &file) => MEDIUMSIZE;
@@ -46,8 +46,8 @@ code = '''
define.MEDIUMSIZE = [32, 2048] define.MEDIUMSIZE = [32, 2048]
define.LARGESIZE = 8192 define.LARGESIZE = 8192
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldyread", lfs_file_open(&lfs, &file, "baldyread",
LFS_O_WRONLY | LFS_O_CREAT) => 0; LFS_O_WRONLY | LFS_O_CREAT) => 0;
@@ -61,7 +61,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDWR) => 0;
lfs_file_size(&lfs, &file) => LARGESIZE; lfs_file_size(&lfs, &file) => LARGESIZE;
@@ -78,7 +78,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => MEDIUMSIZE; lfs_file_size(&lfs, &file) => MEDIUMSIZE;
@@ -95,12 +95,12 @@ code = '''
[[case]] # write, truncate, and read [[case]] # write, truncate, and read
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "sequence", lfs_file_open(&lfs, &file, "sequence",
LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC) => 0; 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; lfs_size_t qsize = size / 4;
uint8_t *wb = buffer; uint8_t *wb = buffer;
uint8_t *rb = buffer + size; uint8_t *rb = buffer + size;
@@ -149,8 +149,8 @@ code = '''
define.MEDIUMSIZE = [32, 2048] define.MEDIUMSIZE = [32, 2048]
define.LARGESIZE = 8192 define.LARGESIZE = 8192
code = ''' code = '''
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldywrite", lfs_file_open(&lfs, &file, "baldywrite",
LFS_O_WRONLY | LFS_O_CREAT) => 0; LFS_O_WRONLY | LFS_O_CREAT) => 0;
@@ -164,7 +164,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDWR) => 0;
lfs_file_size(&lfs, &file) => LARGESIZE; lfs_file_size(&lfs, &file) => LARGESIZE;
@@ -181,7 +181,7 @@ code = '''
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file) => MEDIUMSIZE; lfs_file_size(&lfs, &file) => MEDIUMSIZE;
@@ -202,10 +202,10 @@ define.MEDIUMSIZE = [32, 1024]
define.LARGESIZE = 2048 define.LARGESIZE = 2048
reentrant = true reentrant = true
code = ''' code = '''
err = lfs_mountcfg(&lfs, &cfg); err = lfs_mount(&lfs, &cfg);
if (err) { if (err) {
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
} }
err = lfs_file_open(&lfs, &file, "baldy", LFS_O_RDONLY); err = lfs_file_open(&lfs, &file, "baldy", LFS_O_RDONLY);
assert(!err || err == LFS_ERR_NOENT); assert(!err || err == LFS_ERR_NOENT);
@@ -312,8 +312,8 @@ code = '''
const lfs_off_t *hotsizes = configs[CONFIG].hotsizes; const lfs_off_t *hotsizes = configs[CONFIG].hotsizes;
const lfs_off_t *coldsizes = configs[CONFIG].coldsizes; const lfs_off_t *coldsizes = configs[CONFIG].coldsizes;
lfs_formatcfg(&lfs, &cfg) => 0; lfs_format(&lfs, &cfg) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned i = 0; i < COUNT; i++) { for (unsigned i = 0; i < COUNT; i++) {
sprintf(path, "hairyhead%d", i); sprintf(path, "hairyhead%d", i);
@@ -340,7 +340,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned i = 0; i < COUNT; i++) { for (unsigned i = 0; i < COUNT; i++) {
sprintf(path, "hairyhead%d", i); sprintf(path, "hairyhead%d", i);
@@ -367,7 +367,7 @@ code = '''
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
lfs_mountcfg(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned i = 0; i < COUNT; i++) { for (unsigned i = 0; i < COUNT; i++) {
sprintf(path, "hairyhead%d", i); sprintf(path, "hairyhead%d", i);