Just assert on LFS_O_SYNC + lfsr_file_desync

This is the only way I can think of resolving the weirdness that is
LFS_O_SYNC + LFS_O_DESYNC. Just don't allow it.

LFS_O_SYNC and LFS_O_DESYNC are pretty much opposite behaviors, so an
LFS_O_SYNC + LFS_O_DESYNC file seems like a contradiction.

---

This does limit a little bit what's possible with the API, but hey that
just means fewer tests/smaller API surface area for users to stub their
toes on.

Saves a tiny bit of code:

           code          stack          ctx
  before: 35824           2480          640
  after:  35816 (-0.0%)   2480 (+0.0%)  640 (+0.0%)
This commit is contained in:
Christopher Haster
2025-04-26 02:39:46 -05:00
parent 7b81f01db4
commit 78f9dac162
2 changed files with 153 additions and 207 deletions
+11 -3
View File
@@ -11331,6 +11331,13 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
LFS_ASSERT(!lfsr_o_isrdonly(flags) || !lfsr_o_iscreat(flags));
LFS_ASSERT(!lfsr_o_isrdonly(flags) || !lfsr_o_isexcl(flags));
LFS_ASSERT(!lfsr_o_isrdonly(flags) || !lfsr_o_istrunc(flags));
// these flags are incompatible
LFS_ASSERT(lfsr_o_isrdonly(flags)
|| !lfsr_o_issync(flags)
|| !lfsr_o_isdesync(flags));
LFS_ASSERT(lfsr_o_isrdonly(flags)
|| !lfsr_o_issync(lfs->flags)
|| !lfsr_o_isdesync(flags));
for (lfs_size_t i = 0; i < cfg->attr_count; i++) {
// these flags require a writable attr
LFS_ASSERT(!lfsr_o_isrdonly(cfg->attrs[i].flags)
@@ -11461,9 +11468,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
lfsr_omdir_open(lfs, &file->b.o);
// sync if requested
if (!lfsr_o_isrdonly(file->b.o.flags)
&& lfsr_o_issync(file->b.o.flags)
&& lfsr_o_isunsync(file->b.o.flags)) {
if (lfsr_o_issync(file->b.o.flags)
&& !lfsr_o_isrdonly(file->b.o.flags)) {
err = lfsr_file_sync(lfs, file);
if (err) {
lfsr_omdir_close(lfs, &file->b.o);
@@ -12946,6 +12952,8 @@ failed:;
int lfsr_file_desync(lfs_t *lfs, lfsr_file_t *file) {
(void)lfs;
LFS_ASSERT(lfsr_omdir_isopen(lfs, &file->b.o));
// desyncing LFS_O_SYNC files is not allowed
LFS_ASSERT(!lfsr_o_issync(file->b.o.flags));
// mark as desynced
file->b.o.flags |= LFS_O_DESYNC;
+142 -204
View File
@@ -2480,7 +2480,7 @@ code = '''
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
# SYNC=3 => sync via LFS_M_SYNC
defines.SYNC = [2, 3]
defines.SYNC = [2]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH
@@ -2496,7 +2496,7 @@ code = '''
CFG) => 0;
// a - desynced writer
// b - writer
// b - synced writer
// c - reader kept open, recvs updates from a
// d - reader kept closed, checks disk state
lfsr_file_t a;
@@ -2504,44 +2504,40 @@ code = '''
lfsr_file_t c;
lfsr_file_t d;
uint8_t rbuf[256];
// LFS_O_SYNC/LFS_M_SYNC should immediately create the file
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| LFS_O_CREAT
| LFS_O_EXCL
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
struct lfs_info info;
lfsr_stat(&lfs, "jello", &info) => 0;
assert(strcmp(info.name, "jello") == 0);
assert(info.type == LFS_TYPE_REG);
assert(info.size == 0);
// create the other files
lfsr_file_open(&lfs, &b, "jello",
LFS_O_WRONLY
| LFS_O_CREAT
| LFS_O_EXCL
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0;
lfsr_file_open(&lfs, &c, "jello", LFS_O_RDONLY) => 0;
// write to b
lfsr_file_write(&lfs, &b, "hello!", strlen("hello!"))
// write to a
lfsr_file_write(&lfs, &a, "hello!", strlen("hello!"))
=> strlen("hello!");
// write to b
lfsr_file_write(&lfs, &b, "bonjour!", strlen("bonjour!"))
=> strlen("bonjour!");
// our write should show up in c
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should still have b, this may be surprising, but the implicit
// sync in open+O_CREAT clears the desync flag
// c should revert to a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
@@ -2551,17 +2547,44 @@ code = '''
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// reopen with LFS_O_TRUNC
// reopen a with LFS_O_TRUNC
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| LFS_O_TRUNC
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
// c should still have a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "ohayo!", strlen("ohayo!"))
=> strlen("ohayo!");
// should immediately show up in c
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should revert to a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => 0;
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
@@ -2573,86 +2596,18 @@ code = '''
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
lfsr_file_write(&lfs, &a, "bonjour!", strlen("bonjour!"))
=> strlen("bonjour!");
// should immediately show up in c
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync b
lfsr_file_sync(&lfs, &b) => 0;
// should still have a
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// reopen a
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "ohayo!", strlen("ohayo!"))
=> strlen("ohayo!");
// should immediately show up in c
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should revert to a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// rewrite a
lfsr_file_rewind(&lfs, &a) => 0;
lfsr_file_write(&lfs, &a, "zdrasti!", strlen("zdrasti!"))
=> strlen("zdrasti!");
// should immediately show up in c
// c should still have a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("zdrasti!");
assert(memcmp(rbuf, "zdrasti!", strlen("zdrasti!")) == 0);
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => 0;
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("zdrasti!");
assert(memcmp(rbuf, "zdrasti!", strlen("zdrasti!")) == 0);
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => 0;
lfsr_file_close(&lfs, &d) => 0;
// desync a
lfsr_file_desync(&lfs, &a) => 0;
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "annyeong!", strlen("annyeong!"))
@@ -2681,9 +2636,12 @@ code = '''
assert(memcmp(rbuf, "zdrasti!", strlen("zdrasti!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// lets rewrite a one last time
// lets rewrite a and b one last time
lfsr_file_rewind(&lfs, &a) => 0;
lfsr_file_write(&lfs, &a, "czesc!", strlen("czesc!"))
lfsr_file_write(&lfs, &a, "moshimoshi!", strlen("moshimoshi!"))
=> strlen("moshimoshi!");
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "czesc!", strlen("czesc!"))
=> strlen("czesc!");
// should immediately show up in c
@@ -2700,7 +2658,7 @@ code = '''
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_close(&lfs, &b) => 0;
// should still have a
// should still have b
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("czesc!i!");
assert(memcmp(rbuf, "czesc!i!", strlen("czesc!i!")) == 0);
@@ -3063,7 +3021,7 @@ defines.R = 4
# SYNC=0 => no sync, readers not updated
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
defines.SYNC = [0, 1, 2]
defines.SYNC = [0, 1]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH
@@ -3156,7 +3114,7 @@ defines.R = 4
# SYNC=0 => no sync, readers not updated
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
defines.SYNC = [0, 1, 2]
defines.SYNC = [0, 1]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH
@@ -3451,7 +3409,7 @@ defines.RW = 4
# SYNC=0 => no sync, readers not updated
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
defines.SYNC = [0, 1, 2]
defines.SYNC = [0, 1]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH
@@ -3559,7 +3517,7 @@ defines.RW = 4
# SYNC=0 => no sync, readers not updated
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
defines.SYNC = [0, 1, 2]
defines.SYNC = [0, 1]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH
@@ -4344,7 +4302,7 @@ code = '''
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
# SYNC=3 => sync via LFS_M_SYNC
defines.SYNC = [2, 3]
defines.SYNC = [2]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH
@@ -4360,7 +4318,7 @@ code = '''
CFG) => 0;
// a - desynced writer
// b - writer
// b - synced writer
// c - reader kept open, recvs updates from a
// d - reader kept closed, checks disk state
lfsr_file_t a;
@@ -4368,66 +4326,42 @@ code = '''
lfsr_file_t c;
lfsr_file_t d;
uint8_t rbuf[256];
// LFS_O_SYNC/LFS_M_SYNC should immediately create the file
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| LFS_O_CREAT
| LFS_O_EXCL
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
struct lfs_info info;
lfsr_stat(&lfs, "jello", &info) => 0;
assert(strcmp(info.name, "jello") == 0);
assert(info.type == LFS_TYPE_REG);
assert(info.size == 0);
// create the other files
lfsr_file_open(&lfs, &b, "jello",
LFS_O_WRONLY
| LFS_O_CREAT
| LFS_O_EXCL
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0;
lfsr_file_open(&lfs, &c, "jello", LFS_O_RDONLY) => 0;
// write to b
lfsr_file_write(&lfs, &b, "hello!", strlen("hello!"))
// write to a
lfsr_file_write(&lfs, &a, "hello!", strlen("hello!"))
=> strlen("hello!");
// our write should show up in c
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should still have b, this may be surprising, but the implicit
// sync in open+O_CREAT clears the desync flag
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// reopen a
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
// write to b
lfsr_file_write(&lfs, &b, "bonjour!", strlen("bonjour!"))
=> strlen("bonjour!");
// should immediately show up in c
// our write should show up in c
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// resync a
lfsr_file_resync(&lfs, &a) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should still have b's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
@@ -4437,26 +4371,24 @@ code = '''
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should revert to a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("hello!");
assert(memcmp(rbuf, "hello!", strlen("hello!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// reopen a
// reopen a with LFS_O_TRUNC
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| LFS_O_TRUNC
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| ((SYNC == 2) ? LFS_O_SYNC : 0)
| LFS_O_DESYNC) => 0;
// c should still have b's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("bonjour!");
assert(memcmp(rbuf, "bonjour!", strlen("bonjour!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "ohayo!", strlen("ohayo!"))
@@ -4464,12 +4396,12 @@ code = '''
// should immediately show up in c
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// resync a
@@ -4477,49 +4409,38 @@ code = '''
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should still show b's changes
// c should still have b's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// desync a
lfsr_file_desync(&lfs, &a) => 0;
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "zdrasti!", strlen("zdrasti!"))
// reopen LFS_O_WRONLY and rewrite a
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_open(&lfs, &a, "jello",
LFS_O_WRONLY
| ((FLUSH == 2) ? LFS_O_FLUSH : 0)
| LFS_O_DESYNC) => 0;
lfsr_file_write(&lfs, &a, "zdrasti!", strlen("zdrasti!"))
=> strlen("zdrasti!");
// should immediately show up in c
// c should still have b's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("zdrasti!");
assert(memcmp(rbuf, "zdrasti!", strlen("zdrasti!")) == 0);
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("zdrasti!");
assert(memcmp(rbuf, "zdrasti!", strlen("zdrasti!")) == 0);
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!r!");
assert(memcmp(rbuf, "ohayo!r!", strlen("ohayo!r!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should revert to a's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("ohayo!");
assert(memcmp(rbuf, "ohayo!", strlen("ohayo!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// rewrite a
lfsr_file_rewind(&lfs, &a) => 0;
lfsr_file_write(&lfs, &a, "annyeong!", strlen("annyeong!"))
// rewrite b
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "annyeong!", strlen("annyeong!"))
=> strlen("annyeong!");
// should immediately show up in c
@@ -4532,14 +4453,32 @@ code = '''
assert(memcmp(rbuf, "annyeong!", strlen("annyeong!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// desync b
lfsr_file_desync(&lfs, &b) => 0;
// resync b
lfsr_file_resync(&lfs, &b) => 0;
// rewrite b
// resync a
lfsr_file_resync(&lfs, &a) => 0;
// sync a
lfsr_file_sync(&lfs, &a) => 0;
// c should still have b's contents
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("annyeong!");
assert(memcmp(rbuf, "annyeong!", strlen("annyeong!")) == 0);
// and on disk
lfsr_file_open(&lfs, &d, "jello", LFS_O_RDONLY) => 0;
lfsr_file_read(&lfs, &d, rbuf, sizeof(rbuf)) => strlen("annyeong!");
assert(memcmp(rbuf, "annyeong!", strlen("annyeong!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// desync a
lfsr_file_desync(&lfs, &a) => 0;
// lets rewrite a and b one last time
lfsr_file_rewind(&lfs, &a) => 0;
lfsr_file_write(&lfs, &a, "moshimoshi!", strlen("moshimoshi!"))
=> strlen("moshimoshi!");
lfsr_file_rewind(&lfs, &b) => 0;
lfsr_file_write(&lfs, &b, "czesc!", strlen("czesc!"))
=> strlen("czesc!");
// resync a
lfsr_file_resync(&lfs, &a) => 0;
// should immediately show up in c
lfsr_file_rewind(&lfs, &c) => 0;
@@ -4551,12 +4490,11 @@ code = '''
assert(memcmp(rbuf, "czesc!ng!", strlen("czesc!ng!")) == 0);
lfsr_file_close(&lfs, &d) => 0;
// close b
lfsr_file_close(&lfs, &b) => 0;
// close a
// close a and b
lfsr_file_close(&lfs, &a) => 0;
lfsr_file_close(&lfs, &b) => 0;
// c should still show b's changes
// should still have b
lfsr_file_rewind(&lfs, &c) => 0;
lfsr_file_read(&lfs, &c, rbuf, sizeof(rbuf)) => strlen("czesc!ng!");
assert(memcmp(rbuf, "czesc!ng!", strlen("czesc!ng!")) == 0);
@@ -4900,7 +4838,7 @@ defines.R = 4
# SYNC=0 => no sync, readers not updated
# SYNC=1 => sync via lfsr_file_sync
# SYNC=2 => sync via LFS_O_SYNC
defines.SYNC = [0, 1, 2]
defines.SYNC = [0, 1]
# FLUSH=0 => no flush
# FLUSH=1 => flush via lfsr_file_flush
# FLUSH=2 => flush via LFS_O_FLUSH