Compare commits

...

4 Commits

Author SHA1 Message Date
Christopher Haster
aea032a834 Reduced the scope of LFS3_REVDBG/REVNOISE
LFS3_REVDBG introduced a lot of overhead for something I'm not sure
anyone will actually use (I have enough tooling that the state of an
rbyd is rarely a mystery, see dbgbmap.py). That, and we're running out
of flags!

So this reduces LFS3_REVDBG to just store one of "himb" in the first
(lowest) byte of the revision count; information that is easily
available:

  vvvv---- -------- -------- --------
  vvvvrrrr rrrrrr-- -------- --------
  vvvvrrrr rrrrrrnn nnnnnnnn nnnnnnnn
  vvvvrrrr rrrrrrnn nnnnnnnn dddddddd
  '-.''----.----''----.- - - '---.--'
    '------|----------|----------|---- 4-bit relocation revision
           '----------|----------|---- recycle-bits recycle counter
                      '----------|---- pseudorandom noise (if revnoise)
                                 '---- h, i, m, or b (if revdbg)
                             -11-1---  - h = mroot anchor
                             -11-1--1  - i = mroot
                             -11-11-1  - m = mdir
                             -11---1-  - b = btree node

Some other notes:

- Enabled LFS3_REVDBG and LFS3_REVNOISE to work together, now that
  LFS3_REVDBG doesn't consume all unused rev bits.

  Note that LFS3_REVDBG has priority over LFS3_REVNOISE, but _not_
  recycle-bits, etc. Otherwise problems would happen for recycle-bits
  >2^20 (though do we care?).

- Fixed an issue where using the gcksum as a noise source results in
  noise=0 when there is only an mroot. This is due to how we xor out
  the current mdir cksum during an mdir commit.

  Fixed by using gcksum_p instead of gcksum.

- Added missing LFS3_I_REVDBG/REVNOISE flags in the tests, so now you
  can actually run the tests with LFS3_REVDBG/REVNOISE (this probably
  just fell out-of-date at some point).

---

Curiously, despite LFS3_REVDBG/REVNOISE being disabled by default, this
did save some code. I'm guessing the non-tail-call mtree/gbmap commit
functions prevented some level of inlining?:

                 code          stack          ctx
  before:       35964           2280          660
  after:        35964 (+0.0%)   2280 (+0.0%)  660 (+0.0%)

                 code          stack          ctx
  gbmap before: 38940           2296          772
  gbmap after:  38828 (-0.3%)   2296 (+0.0%)  772 (+0.0%)
2025-11-12 16:09:09 -06:00
Christopher Haster
e196be53df Adopted LFS3_ERR_BUSY for root-related errors
Now that we use LFS3_ERR_BUSY for traversals, we no longer have an
excuse for not returning LFS3_ERR_BUSY on root-related errors:

- lfs3_remove(&lfs3, "/") => LFS3_ERR_BUSY
- lfs3_rename(&lfs3, "/", *) => LFS3_ERR_BUSY
- lfs3_rename(&lfs3, *, "/") => LFS3_ERR_BUSY

This better aligns with POSIX. Arguably we should have defined
LFS3_ERR_BUSY for this case anyways, it's not like additional error
codes cost much.

No code changes.
2025-11-12 13:40:59 -06:00
Christopher Haster
4010afeafd trv: Reintroduced LFS3_T_EXCL
With the relaxation of traversal behavior under mutation, I think it
makes sense to bring back LFS3_T_EXCL. If only to allow traversals to
gaurantee termination under mutation. Now that traversals no longer
guarantee forward progress, it's possible to get stuck looping
indefinitely if the filesystem is constantly being mutated.

Non-excl traversals are probably still useful for GC work and debugging
threads, but LFS3_T_EXCL now allows traversals to terminate immediately
with LFS3_ERR_BUSY at the first sign of unrelated filesystem mutation:

  LFS3_T_EXCL  0x00000008  Error if filesystem modified

Internally, we already track unrelated mutation to avoid corrupt state
(LFS3_t_DIRTY), so this is a very low-cost feature:

                 code          stack          ctx
  before:       35944           2280          660
  after:        35964 (+0.1%)   2280 (+0.0%)  660 (+0.0%)

                 code          stack          ctx
  gbmap before: 38916           2296          772
  gbmap after:  38940 (+0.1%)   2296 (+0.0%)  772 (+0.0%)

                 code          stack          ctx
  gc before:    36016           2280          768
  gc after:     36036 (+0.1%)   2280 (+0.0%)  768 (+0.0%)
2025-11-12 13:30:11 -06:00
Christopher Haster
8bb43ac4b2 Dropped switch-case from lfs3_rbyd_appendrattr_
Now that lfs3_mtree_traverse_ uses a sort of state matrix,
lfs3_rbyd_appendrattr_ is the only function still relying on a big
switch-case statement. Replacing it with a series of if-else statements
leaves the codebase switch-case free (ignoring test/bench runners, etc).

Switch-case statements are extremely error prone in C, with the shared
scope, implicit fallthrough, etc. And, with today's compilers, the
result still ends up the same, so switch-case statements offer no
benefit except maybe a more enjoyable syntax for masochists.

Avoiding switch-case statements in code where we care about correctness
is probably a good idea.

No code changes
2025-11-12 13:26:59 -06:00
12 changed files with 817 additions and 325 deletions

247
lfs3.c
View File

@@ -3551,30 +3551,26 @@ static int lfs3_rbyd_appendrattr_(lfs3_t *lfs3, lfs3_rbyd_t *rbyd,
} u;
} ctx;
switch (rattr.from) {
// direct buffer?
case LFS3_FROM_BUF:;
if (rattr.from == LFS3_FROM_BUF) {
ctx.u.data = LFS3_DATA_BUF(rattr.u.buffer, rattr.count);
datas = &ctx.u.data;
data_count = 1;
break;
// indirect concatenated data?
case LFS3_FROM_DATA:;
} else if (rattr.from == LFS3_FROM_DATA) {
datas = rattr.u.datas;
data_count = rattr.count;
break;
// le32?
case LFS3_FROM_LE32:;
} else if (rattr.from == LFS3_FROM_LE32) {
ctx.u.le32.data = lfs3_data_fromle32(rattr.u.le32,
ctx.u.le32.buf);
datas = &ctx.u.le32.data;
data_count = 1;
break;
// leb128?
case LFS3_FROM_LEB128:;
} else if (rattr.from == LFS3_FROM_LEB128) {
// leb128s should not exceed 31-bits
LFS3_ASSERT(rattr.u.leb128 <= 0x7fffffff);
// little-leb128s should not exceed 28-bits
@@ -3584,43 +3580,38 @@ static int lfs3_rbyd_appendrattr_(lfs3_t *lfs3, lfs3_rbyd_t *rbyd,
ctx.u.leb128.buf);
datas = &ctx.u.leb128.data;
data_count = 1;
break;
// name?
case LFS3_FROM_NAME:;
} else if (rattr.from == LFS3_FROM_NAME) {
const lfs3_name_t *name = rattr.u.etc;
ctx.u.name.datas[0] = lfs3_data_fromleb128(name->did, ctx.u.name.buf);
ctx.u.name.datas[1] = LFS3_DATA_BUF(name->name, name->name_len);
datas = ctx.u.name.datas;
data_count = 2;
break;
// bptr?
case LFS3_FROM_BPTR:;
} else if (rattr.from == LFS3_FROM_BPTR) {
ctx.u.bptr.data = lfs3_data_frombptr(rattr.u.etc,
ctx.u.bptr.buf);
datas = &ctx.u.bptr.data;
data_count = 1;
break;
// ecksum?
case LFS3_FROM_ECKSUM:;
} else if (rattr.from == LFS3_FROM_ECKSUM) {
ctx.u.ecksum.data = lfs3_data_fromecksum(rattr.u.etc,
ctx.u.ecksum.buf);
datas = &ctx.u.ecksum.data;
data_count = 1;
break;
// btree?
case LFS3_FROM_BTREE:;
} else if (rattr.from == LFS3_FROM_BTREE) {
ctx.u.btree.data = lfs3_data_frombtree(rattr.u.etc,
ctx.u.btree.buf);
datas = &ctx.u.btree.data;
data_count = 1;
break;
// shrub trunk?
case LFS3_FROM_SHRUB:;
} else if (rattr.from == LFS3_FROM_SHRUB) {
// note unlike the other lazy tags, we _need_ to lazily encode
// shrub trunks, since they change underneath us during mdir
// compactions, relocations, etc
@@ -3628,25 +3619,22 @@ static int lfs3_rbyd_appendrattr_(lfs3_t *lfs3, lfs3_rbyd_t *rbyd,
ctx.u.shrub.buf);
datas = &ctx.u.shrub.data;
data_count = 1;
break;
// mptr?
case LFS3_FROM_MPTR:;
} else if (rattr.from == LFS3_FROM_MPTR) {
ctx.u.mptr.data = lfs3_data_frommptr(rattr.u.etc,
ctx.u.mptr.buf);
datas = &ctx.u.mptr.data;
data_count = 1;
break;
// geometry?
case LFS3_FROM_GEOMETRY:;
} else if (rattr.from == LFS3_FROM_GEOMETRY) {
ctx.u.geometry.data = lfs3_data_fromgeometry(rattr.u.etc,
ctx.u.geometry.buf);
datas = &ctx.u.geometry.data;
data_count = 1;
break;
default:;
} else {
LFS3_UNREACHABLE();
}
@@ -7367,6 +7355,10 @@ static inline bool lfs3_t_ismtreeonly(uint32_t flags) {
return flags & LFS3_T_MTREEONLY;
}
static inline bool lfs3_t_isexcl(uint32_t flags) {
return flags & LFS3_T_EXCL;
}
static inline bool lfs3_t_ismkconsistent(uint32_t flags) {
(void)flags;
#ifndef LFS3_RDONLY
@@ -7534,19 +7526,6 @@ static inline bool lfs3_f_isgbmap(uint32_t flags) {
}
#endif
// other internal flags
#ifdef LFS3_REVDBG
static inline bool lfs3_i_isinmtree(uint32_t flags) {
return (flags & LFS3_i_INMODE) == LFS3_i_INMTREE;
}
#endif
#ifdef LFS3_REVDBG
static inline bool lfs3_i_isingbmap(uint32_t flags) {
return (flags & LFS3_i_INMODE) == LFS3_i_INGBMAP;
}
#endif
/// Handles - opened mdir things ///
@@ -7954,24 +7933,21 @@ static int lfs3_fs_consumegdelta(lfs3_t *lfs3, const lfs3_mdir_t *mdir) {
/// Revision count things ///
// in mdirs, our revision count is broken down into three parts:
// in mdirs, our revision count is broken down into 1-4 parts:
//
// vvvv---- -------- -------- --------
// vvvvrrrr rrrrrr-- -------- --------
// vvvvrrrr rrrrrrnn nnnnnnnn nnnnnnnn
// '-.''----.----''---------.--------'
// '------|---------------|---------- 4-bit relocation revision
// '---------------|---------- recycle-bits recycle counter
// '---------- pseudorandom noise (if revnoise)
//
// in revdbg mode, the bottom 24 bits are initialized with a hint based
// on rbyd type, though it may be overwritten by the recycle counter if
// it overlaps:
//
// vvvv---- --1----1 -11-1--1 -11-1--- (68 69 21 v0 hi!r) mroot anchor
// vvvv---- -111111- -111--1- -11-11-1 (6d 72 7e v0 mr~r) mroot
// vvvv---- -111111- -11--1-- -11-11-1 (6d 64 7e v0 md~r) mdir
// vvvv---- -111111- -111-1-- -11---1- (62 74 7e v0 bt~r) file btree node
// vvvv---- -111111- -11-11-1 -11---1- (62 6d 7e v0 bm~r) mtree node
// vvvv---- -111111- -11---1- -11---1- (62 62 7e v0 bb~r) gbmap node
// vvvvrrrr rrrrrrnn nnnnnnnn dddddddd
// '-.''----.----''----.- - - '---.--'
// '------|----------|----------|---- 4-bit relocation revision
// '----------|----------|---- recycle-bits recycle counter
// '----------|---- pseudorandom noise (if revnoise)
// '---- h, i, m, or b (if revdbg)
// -11-1--- - h = mroot anchor
// -11-1--1 - i = mroot
// -11-11-1 - m = mdir
// -11---1- - b = btree node
//
// needed in lfs3_rev_init
@@ -7987,24 +7963,32 @@ static inline uint32_t lfs3_rev_init(lfs3_t *lfs3, const lfs3_mdir_t *mdir,
rev &= ~((1 << 28)-1);
// increment revision
rev += 1 << 28;
// xor in pseudorandom noise?
#ifdef LFS3_REVNOISE
if (lfs3_m_isrevnoise(lfs3->flags)) {
rev ^= ((1 << (28-lfs3_smax(lfs3->recycle_bits, 0)))-1)
// we need to use gcksum_p because we have be in the
// middle of updating the gcksum
& lfs3->gcksum_p;
}
#endif
// include debug bits?
#ifdef LFS3_REVDBG
if (lfs3_m_isrevdbg(lfs3->flags)) {
uint32_t mask = (1 << (28-lfs3_smax(lfs3->recycle_bits, 0)))-1;
// mroot anchor?
if (lfs3_mdir_ismrootanchor(mdir)) {
rev = (rev & ~(mask & 0xff)) | (mask & 0x68);
// mroot?
if (mdir->mid <= -1 || lfs3_mdir_cmp(mdir, &lfs3->mroot) == 0) {
rev |= 0x007e726d; // mr~r
} else if (mdir->mid <= -1
|| lfs3_mdir_cmp(mdir, &lfs3->mroot) == 0) {
rev = (rev & ~(mask & 0xff)) | (mask & 0x69);
// mdir?
} else {
rev |= 0x007e646d; // md~r
rev = (rev & ~(mask & 0xff)) | (mask & 0x6d);
}
}
#endif
// xor in pseudorandom noise
#ifdef LFS3_REVNOISE
if (lfs3_m_isrevnoise(lfs3->flags)) {
rev ^= ((1 << (28-lfs3_smax(lfs3->recycle_bits, 0)))-1) & lfs3->gcksum;
}
#endif
return rev;
}
#endif
@@ -8015,26 +7999,20 @@ static inline uint32_t lfs3_rev_init(lfs3_t *lfs3, const lfs3_mdir_t *mdir,
static inline uint32_t lfs3_rev_btree(lfs3_t *lfs3) {
(void)lfs3;
uint32_t rev = 0;
// include debug bits?
#ifdef LFS3_REVDBG
if (lfs3_m_isrevdbg(lfs3->flags)) {
// mtree?
if (lfs3_i_isinmtree(lfs3->flags)) {
rev |= 0x007e6d62; // bm~r
// gbmap?
} else if (lfs3_i_isingbmap(lfs3->flags)) {
rev |= 0x007e6262; // bb~r
// file btree?
} else {
rev |= 0x007e7462; // bt~r
}
}
#endif
// xor in pseudorandom noise
// xor in pseudorandom noise?
#ifdef LFS3_REVNOISE
if (lfs3_m_isrevnoise(lfs3->flags)) {
// keep the top nibble zero
rev ^= 0x0fffffff & lfs3->gcksum;
rev ^= 0x0fffffff
// we need to use gcksum_p because we have be in the
// middle of updating the gcksum
& lfs3->gcksum_p;
}
#endif
// include debug bits?
#ifdef LFS3_REVDBG
if (lfs3_m_isrevdbg(lfs3->flags)) {
rev = (rev & ~0xff) | 0x62;
}
#endif
return rev;
@@ -8054,13 +8032,35 @@ static inline bool lfs3_rev_needsrelocation(lfs3_t *lfs3, uint32_t rev) {
#endif
#ifndef LFS3_RDONLY
static inline uint32_t lfs3_rev_inc(lfs3_t *lfs3, uint32_t rev) {
static inline uint32_t lfs3_rev_inc(lfs3_t *lfs3, const lfs3_mdir_t *mdir,
uint32_t rev) {
(void)mdir;
// increment recycle counter/revision
rev += 1 << (28-lfs3_smax(lfs3->recycle_bits, 0));
// xor in pseudorandom noise
// xor in pseudorandom noise?
#ifdef LFS3_REVNOISE
if (lfs3_m_isrevnoise(lfs3->flags)) {
rev ^= ((1 << (28-lfs3_smax(lfs3->recycle_bits, 0)))-1) & lfs3->gcksum;
rev ^= ((1 << (28-lfs3_smax(lfs3->recycle_bits, 0)))-1)
// we need to use gcksum_p because we have be in the
// middle of updating the gcksum
& lfs3->gcksum_p;
}
#endif
// include debug bits?
#ifdef LFS3_REVDBG
if (lfs3_m_isrevdbg(lfs3->flags)) {
uint32_t mask = (1 << (28-lfs3_smax(lfs3->recycle_bits, 0)))-1;
// mroot anchor?
if (lfs3_mdir_ismrootanchor(mdir)) {
rev = (rev & ~(mask & 0xff)) | (mask & 0x68);
// mroot?
} else if (mdir->mid <= -1
|| lfs3_mdir_cmp(mdir, &lfs3->mroot) == 0) {
rev = (rev & ~(mask & 0xff)) | (mask & 0x69);
// mdir?
} else {
rev = (rev & ~(mask & 0xff)) | (mask & 0x6d);
}
}
#endif
return rev;
@@ -8301,30 +8301,10 @@ static int lfs3_mtree_lookup(lfs3_t *lfs3, lfs3_smid_t mid,
}
}
// this is the same as lfs3_btree_commit, but we set the inmtree flag
// for debugging reasons
#ifndef LFS3_RDONLY
static int lfs3_mtree_commit(lfs3_t *lfs3, lfs3_btree_t *mtree,
lfs3_bid_t bid, const lfs3_rattr_t *rattrs, lfs3_size_t rattr_count) {
#ifdef LFS3_REVDBG
lfs3->flags |= LFS3_i_INMTREE;
#endif
int err = lfs3_btree_commit(lfs3, mtree, bid, rattrs, rattr_count);
if (err) {
goto failed;
}
#ifdef LFS3_REVDBG
lfs3->flags &= ~LFS3_i_INMTREE;
#endif
return 0;
failed:;
#ifdef LFS3_REVDBG
lfs3->flags &= ~LFS3_i_INMTREE;
#endif
return err;
return lfs3_btree_commit(lfs3, mtree, bid, rattrs, rattr_count);
}
#endif
@@ -8417,7 +8397,7 @@ static int lfs3_mdir_swap___(lfs3_t *lfs3, lfs3_mdir_t *mdir_,
// note we allow corrupt errors here, as long as they are consistent
rev = (err != LFS3_ERR_CORRUPT) ? lfs3_fromle32(&rev) : 0;
// increment our revision count
rev = lfs3_rev_inc(lfs3, rev);
rev = lfs3_rev_inc(lfs3, mdir_, rev);
// decide if we need to relocate
if (!force && lfs3_rev_needsrelocation(lfs3, rev)) {
@@ -10721,30 +10701,10 @@ static lfs3_stag_t lfs3_gbmap_lookupnext(lfs3_t *lfs3, lfs3_btree_t *gbmap,
}
#endif
// this is the same as lfs3_btree_commit, but we set the ingbmap flag
// for debugging reasons
#if !defined(LFS3_RDONLY) && defined(LFS3_GBMAP)
static int lfs3_gbmap_commit(lfs3_t *lfs3, lfs3_btree_t *gbmap,
lfs3_bid_t bid, const lfs3_rattr_t *rattrs, lfs3_size_t rattr_count) {
#ifdef LFS3_REVDBG
lfs3->flags |= LFS3_i_INGBMAP;
#endif
int err = lfs3_btree_commit(lfs3, gbmap, bid, rattrs, rattr_count);
if (err) {
goto failed;
}
#ifdef LFS3_REVDBG
lfs3->flags &= ~LFS3_i_INGBMAP;
#endif
return 0;
failed:;
#ifdef LFS3_REVDBG
lfs3->flags &= ~LFS3_i_INGBMAP;
#endif
return err;
return lfs3_btree_commit(lfs3, gbmap, bid, rattrs, rattr_count);
}
#endif
@@ -11643,7 +11603,7 @@ int lfs3_remove(lfs3_t *lfs3, const char *path) {
// trying to remove the root dir?
if (mdir.mid == -1) {
return LFS3_ERR_INVAL;
return LFS3_ERR_BUSY;
}
// if we're removing a directory, we need to also remove the
@@ -11764,7 +11724,7 @@ int lfs3_rename(lfs3_t *lfs3, const char *old_path, const char *new_path) {
// trying to rename the root?
if (old_mdir.mid == -1) {
return LFS3_ERR_INVAL;
return LFS3_ERR_BUSY;
}
// lookup new entry
@@ -11794,7 +11754,7 @@ int lfs3_rename(lfs3_t *lfs3, const char *old_path, const char *new_path) {
} else {
// trying to rename the root?
if (new_mdir.mid == -1) {
return LFS3_ERR_INVAL;
return LFS3_ERR_BUSY;
}
// we allow reg <-> stickynote renaming, but renaming a non-dir
@@ -14976,11 +14936,6 @@ static int lfs3_init(lfs3_t *lfs3, uint32_t flags,
| LFS3_IFDEF_CKMETAPARITY(LFS3_M_CKMETAPARITY, 0)
| LFS3_IFDEF_CKDATACKSUMS(LFS3_M_CKDATACKSUMS, 0)
| LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, 0))) == 0);
// LFS3_M_REVDBG and LFS3_M_REVNOISE are incompatible
#if defined(LFS3_REVNOISE) && defined(LFS3_REVDBG)
LFS3_ASSERT(!lfs3_m_isrevdbg(flags) || !lfs3_m_isrevnoise(flags));
#endif
// TODO this all needs to be cleaned up
lfs3->cfg = cfg;
int err = 0;
@@ -16040,10 +15995,6 @@ int lfs3_unmount(lfs3_t *lfs3) {
#if !defined(LFS3_RDONLY) && defined(LFS3_GBMAP)
static int lfs3_formatgbmap(lfs3_t *lfs3) {
#ifdef LFS3_REVDBG
lfs3->flags |= LFS3_i_INGBMAP;
#endif
// TODO should we try multiple blocks?
//
// TODO if we try multiple blocks we should update test_badblocks
@@ -16060,14 +16011,14 @@ static int lfs3_formatgbmap(lfs3_t *lfs3) {
int err = lfs3_bd_erase(lfs3, lfs3->gbmap.b.r.blocks[0]);
if (err) {
goto failed;
return err;
}
#if defined(LFS3_REVDBG) || defined(LFS3_REVNOISE)
// append a revision count?
err = lfs3_rbyd_appendrev(lfs3, &lfs3->gbmap.b.r, lfs3_rev_btree(lfs3));
if (err) {
goto failed;
return err;
}
#endif
@@ -16079,19 +16030,10 @@ static int lfs3_formatgbmap(lfs3_t *lfs3) {
? LFS3_RATTR(LFS3_TAG_BMFREE, +(lfs3->block_count - 3))
: LFS3_RATTR_NOOP()));
if (err) {
goto failed;
return err;
}
#ifdef LFS3_REVDBG
lfs3->flags &= ~LFS3_i_INGBMAP;
#endif
return 0;
failed:;
#ifdef LFS3_REVDBG
lfs3->flags &= ~LFS3_i_INGBMAP;
#endif
return err;
}
#endif
@@ -16926,6 +16868,7 @@ int lfs3_trv_open(lfs3_t *lfs3, lfs3_trv_t *trv, uint32_t flags) {
LFS3_IFDEF_RDONLY(0, LFS3_T_RDWR)
| LFS3_T_RDONLY
| LFS3_T_MTREEONLY
| LFS3_T_EXCL
| LFS3_IFDEF_RDONLY(0, LFS3_T_MKCONSISTENT)
| LFS3_IFDEF_RDONLY(0, LFS3_T_RELOOKAHEAD)
| LFS3_IFDEF_RDONLY(0,
@@ -16971,6 +16914,12 @@ int lfs3_trv_read(lfs3_t *lfs3, lfs3_trv_t *trv,
struct lfs3_tinfo *tinfo) {
LFS3_ASSERT(lfs3_handle_isopen(lfs3, &trv->gc.t.h));
// filesystem modified? excl? terminate early
if (lfs3_t_isexcl(trv->gc.t.h.flags)
&& lfs3_t_isdirty(trv->gc.t.h.flags)) {
return LFS3_ERR_BUSY;
}
// check for pending grms every step, just in case some other
// operation introduced new grms
#ifndef LFS3_RDONLY

9
lfs3.h
View File

@@ -77,6 +77,7 @@ enum lfs3_err {
LFS3_ERR_UNKNOWN = -1, // Unknown error
LFS3_ERR_INVAL = -22, // Invalid parameter
LFS3_ERR_NOTSUP = -95, // Operation not supported
LFS3_ERR_BUSY = -16, // Device or resource busy
LFS3_ERR_IO = -5, // Error during device operation
LFS3_ERR_CORRUPT = -84, // Corrupted
LFS3_ERR_NOENT = -2, // No directory entry
@@ -295,13 +296,6 @@ enum lfs3_type {
#define LFS3_I_GBMAP 0x01000000 // Global on-disk block-map in use
#endif
// internally used flags, don't use these
#ifdef LFS3_REVDBG
#define LFS3_i_INMODE 0x00030000 // Btree commit mode
#define LFS3_i_INMTREE 0x00010000 // Committing to mtree
#define LFS3_i_INGBMAP 0x00020000 // Committing to gbmap
#endif
// Block types
enum lfs3_btype {
@@ -318,6 +312,7 @@ enum lfs3_btype {
#define LFS3_T_RDONLY 1 // Open traversal as read only
#define LFS3_T_MTREEONLY \
0x00000002 // Only traverse the mtree
#define LFS3_T_EXCL 0x00000008 // Error if filesystem modified
#ifndef LFS3_RDONLY
#define LFS3_T_MKCONSISTENT \
0x00000100 // Make the filesystem consistent

View File

@@ -215,12 +215,24 @@
#define LFS3_IFDEF_REVDBG(a, b) (b)
#endif
#ifdef LFS3_YES_REVDBG
#define LFS3_IFDEF_YES_REVDBG(a, b) (a)
#else
#define LFS3_IFDEF_YES_REVDBG(a, b) (b)
#endif
#ifdef LFS3_REVNOISE
#define LFS3_IFDEF_REVNOISE(a, b) (a)
#else
#define LFS3_IFDEF_REVNOISE(a, b) (b)
#endif
#ifdef LFS3_YES_REVNOISE
#define LFS3_IFDEF_YES_REVNOISE(a, b) (a)
#else
#define LFS3_IFDEF_YES_REVNOISE(a, b) (b)
#endif
#ifdef LFS3_CKPROGS
#define LFS3_IFDEF_CKPROGS(a, b) (a)
#else

View File

@@ -12,6 +12,7 @@ ERR_OK = 0 # No error
ERR_UNKNOWN = -1 # Unknown error
ERR_INVAL = -22 # Invalid parameter
ERR_NOTSUP = -95 # Operation not supported
ERR_BUSY = -16 # Device or resource busy
ERR_IO = -5 # Error during device operation
ERR_CORRUPT = -84 # Corrupted
ERR_NOENT = -2 # No directory entry

View File

@@ -139,6 +139,7 @@ T_MODE = 1 # -m The traversal's access mode
T_RDWR = 0 # -^ Open traversal as read and write
T_RDONLY = 1 # -^ Open traversal as read only
T_MTREEONLY = 0x00000002 # -- Only traverse the mtree
T_EXCL = 0x00000008 # -- Error if filesystem modified
T_MKCONSISTENT = 0x00000100 # -- Make the filesystem consistent
T_RELOOKAHEAD = 0x00000200 # -- Repopulate lookahead buffer
T_REGBMAP = 0x00000400 # -- Repopulate the gbmap

View File

@@ -2595,7 +2595,7 @@ code = '''
}
// try to remove root, which doesn't really make sense
lfs3_remove(&lfs3, "/") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "/") => LFS3_ERR_BUSY;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
@@ -2605,7 +2605,7 @@ code = '''
//
// it doesn't really matter which error returns first, so accept both
err = lfs3_remove(&lfs3, "/");
assert(err == LFS3_ERR_NOTEMPTY || err == LFS3_ERR_INVAL);
assert(err == LFS3_ERR_NOTEMPTY || err == LFS3_ERR_BUSY);
for (int remount = 0; remount < 2; remount++) {
// remount?
@@ -4830,14 +4830,14 @@ code = '''
}
// try to rename root, which doesn't really make sense
lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_BUSY;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to rename root, which doesn't really make sense
lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_BUSY;
for (int remount = 0; remount < 2; remount++) {
// remount?

View File

@@ -523,7 +523,7 @@ code = '''
lfs3_file_write(&lfs3, &file, wbuf, wsize) => wsize;
lfs3_file_close(&lfs3, &file) => 0;
lfs3_rename(&lfs3, "not_hello", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "not_hello", "/") => LFS3_ERR_BUSY;
for (int remount = 0; remount < 2; remount++) {
// remount?
@@ -2247,7 +2247,7 @@ code = '''
}
// rename the file
lfs3_rename(&lfs3, "amethyst", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "amethyst", "/") => LFS3_ERR_BUSY;
for (int remount = 0; remount < 2; remount++) {
// remount?

View File

@@ -1885,7 +1885,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| ((GBMAP)
? (LFS3_IFDEF_GBMAP(LFS3_I_REGBMAP, -1)
@@ -2028,7 +2030,9 @@ code = '''
// did these clear the right flags?
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
((!MKCONSISTENT) ? LFS3_I_MKCONSISTENT : 0)
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| ((!MKCONSISTENT) ? LFS3_I_MKCONSISTENT : 0)
| ((!RELOOKAHEAD) ? LFS3_I_RELOOKAHEAD : 0)
| ((!REGBMAP)
? ((GBMAP)
@@ -2116,7 +2120,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| ((GBMAP)
? (LFS3_IFDEF_GBMAP(LFS3_I_REGBMAP, -1)
@@ -2259,7 +2265,9 @@ code = '''
// did these clear the right flags?
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
((!MKCONSISTENT) ? LFS3_I_MKCONSISTENT : 0)
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| ((!MKCONSISTENT) ? LFS3_I_MKCONSISTENT : 0)
| ((!RELOOKAHEAD) ? LFS3_I_RELOOKAHEAD : 0)
| ((!REGBMAP)
? ((GBMAP)
@@ -2279,7 +2287,9 @@ code = '''
// check that flags were reset
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| ((REGBMAP)
? LFS3_IFDEF_GBMAP(LFS3_I_REGBMAP, -1U)
@@ -2426,7 +2436,9 @@ code = '''
// did these clear the right flags?
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
((!MKCONSISTENT) ? LFS3_I_MKCONSISTENT : 0)
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| ((!MKCONSISTENT) ? LFS3_I_MKCONSISTENT : 0)
| ((!RELOOKAHEAD) ? LFS3_I_RELOOKAHEAD : 0)
| ((!REGBMAP)
? ((GBMAP)

View File

@@ -30,9 +30,8 @@ defines.COMPACTMETA = [false, true]
defines.CKMETA = [false, true]
defines.CKDATA = [false, true]
if = [
'LFS3_IFDEF_REVDBG(true, !REVDBG)',
'LFS3_IFDEF_REVNOISE(true, !REVNOISE)',
'!REVDBG || !REVNOISE',
'LFS3_IFDEF_YES_REVDBG(REVDBG, LFS3_IFDEF_REVDBG(true, !REVDBG))',
'LFS3_IFDEF_YES_REVNOISE(REVNOISE, LFS3_IFDEF_REVNOISE(true, !REVNOISE))',
'LFS3_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS3_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS3_IFDEF_CKMETAPARITY(true, !CKMETAPARITY)',
@@ -77,8 +76,8 @@ code = '''
((RDONLY) ? LFS3_I_RDONLY : 0)
| ((FLUSH) ? LFS3_I_FLUSH : 0)
| ((SYNC) ? LFS3_I_SYNC : 0)
| ((REVDBG) ? LFS3_IFDEF_REVDBG(LFS3_M_REVDBG, -1) : 0)
| ((REVNOISE) ? LFS3_IFDEF_REVNOISE(LFS3_M_REVNOISE, -1) : 0)
| ((REVDBG) ? LFS3_IFDEF_REVDBG(LFS3_I_REVDBG, -1) : 0)
| ((REVNOISE) ? LFS3_IFDEF_REVNOISE(LFS3_I_REVNOISE, -1) : 0)
| ((CKPROGS) ? LFS3_IFDEF_CKPROGS(LFS3_I_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS3_IFDEF_CKFETCHES(LFS3_I_CKFETCHES, -1) : 0)
| ((CKMETAPARITY)
@@ -112,9 +111,8 @@ defines.CKMETA = [false, true]
defines.CKDATA = [false, true]
defines.GBMAP = [false, true]
if = [
'LFS3_IFDEF_REVDBG(true, !REVDBG)',
'LFS3_IFDEF_REVNOISE(true, !REVNOISE)',
'!REVDBG || !REVNOISE',
'LFS3_IFDEF_YES_REVDBG(REVDBG, LFS3_IFDEF_REVDBG(true, !REVDBG))',
'LFS3_IFDEF_YES_REVNOISE(REVNOISE, LFS3_IFDEF_REVNOISE(true, !REVNOISE))',
'LFS3_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS3_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS3_IFDEF_CKMETAPARITY(true, !CKMETAPARITY)',
@@ -145,7 +143,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| LFS3_I_COMPACTMETA
| LFS3_I_CKMETA
@@ -172,7 +172,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| LFS3_I_COMPACTMETA
| LFS3_I_CKMETA
@@ -189,7 +191,9 @@ code = '''
CFG) => 0;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_COMPACTMETA
// note ckdata implies ckmeta
| ((!CKMETA && !CKDATA) ? LFS3_I_CKMETA : 0)
@@ -219,7 +223,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| LFS3_I_COMPACTMETA
| LFS3_I_CKMETA
@@ -241,7 +247,9 @@ code = '''
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| LFS3_I_REGBMAP
| LFS3_I_COMPACTMETA
@@ -260,7 +268,9 @@ code = '''
CFG) => 0;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_COMPACTMETA
// note ckdata implies ckmeta
| ((!CKMETA && !CKDATA) ? LFS3_I_CKMETA : 0)
@@ -316,7 +326,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| LFS3_IFDEF_YES_GBMAP(
(SIZE >= BLOCK_SIZE/4) ? LFS3_I_REGBMAP : 0,
@@ -337,7 +349,9 @@ code = '''
CFG) => 0;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| ((!RELOOKAHEAD) ? LFS3_I_RELOOKAHEAD : 0)
| LFS3_IFDEF_YES_GBMAP(
(SIZE >= BLOCK_SIZE/4) ? LFS3_I_REGBMAP : 0,
@@ -426,7 +440,9 @@ code = '''
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS3_I_MKCONSISTENT
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| LFS3_I_MKCONSISTENT
| LFS3_I_RELOOKAHEAD
| LFS3_IFDEF_YES_GBMAP(
(ORPHANS >= 100) ? LFS3_I_REGBMAP : 0,
@@ -448,7 +464,9 @@ code = '''
CFG) => 0;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags == (
((!RELOOKAHEAD) ? LFS3_I_RELOOKAHEAD : 0)
LFS3_IFDEF_YES_REVDBG(LFS3_I_REVDBG, 0)
| LFS3_IFDEF_YES_REVNOISE(LFS3_I_REVNOISE, 0)
| ((!RELOOKAHEAD) ? LFS3_I_RELOOKAHEAD : 0)
| LFS3_IFDEF_YES_GBMAP(
(ORPHANS >= 100) ? LFS3_I_REGBMAP : 0,
0)

View File

@@ -2170,7 +2170,7 @@ code = '''
"espresso/latte") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/vietnamese/../..",
"espresso/cappuccino") => LFS3_ERR_INVAL;
"espresso/cappuccino") => LFS3_ERR_BUSY;
// this one works
lfs3_rename(&lfs3,
"coffee/thai/..",
@@ -2195,7 +2195,7 @@ code = '''
}
lfs3_rename(&lfs3,
"coffee/coldbrew",
"espresso/americano/../..") => LFS3_ERR_INVAL;
"espresso/americano/../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/turkish",
"espresso/macchiato/../../..") => LFS3_ERR_INVAL;
@@ -2224,14 +2224,14 @@ code = '''
"espresso/latte/../../../..") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/vietnamese/../..",
"espresso/cappuccino/../../../../..") => LFS3_ERR_INVAL;
"espresso/cappuccino/../../../../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/thai/..",
"espresso/mocha/../../../../../..") => LFS3_ERR_INVAL;
// remove paths
lfs3_remove(&lfs3, "coffee/drip/..") => LFS3_ERR_NOTEMPTY;
lfs3_remove(&lfs3, "coffee/coldbrew/../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/coldbrew/../..") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "coffee/turkish/../../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/tubruk/../../../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/vietnamese/../../../../..") => LFS3_ERR_INVAL;
@@ -4441,7 +4441,7 @@ code = '''
"espresso/latte") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/_vietnamese/../..",
"espresso/cappuccino") => LFS3_ERR_INVAL;
"espresso/cappuccino") => LFS3_ERR_BUSY;
// this one works
lfs3_rename(&lfs3,
"coffee/thai_/..",
@@ -4485,7 +4485,7 @@ code = '''
"espresso/latte/../../../..") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/_vietnamese/../..",
"espresso/cappuccino/../../../../..") => LFS3_ERR_INVAL;
"espresso/cappuccino/../../../../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/thai_/..",
"espresso/mocha/../../../../../..") => LFS3_ERR_INVAL;
@@ -4505,14 +4505,14 @@ code = '''
"coffee/tub_uk/../../..") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/_vietnamese/../..",
"coffee/_vietnamese/../..") => LFS3_ERR_INVAL;
"coffee/_vietnamese/../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/thai_/..",
"coffee/thai_/..") => 0;
// remove paths
lfs3_remove(&lfs3, "coffee/_rip/..") => LFS3_ERR_NOTEMPTY;
lfs3_remove(&lfs3, "coffee/c_ldbrew/../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/c_ldbrew/../..") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "coffee/tu_kish/../../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/tub_uk/../../../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/_vietnamese/../../../../..") => LFS3_ERR_INVAL;
@@ -5621,7 +5621,7 @@ code = '''
"espresso/latte") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/vietnamese/../..",
"espresso/cappuccino") => LFS3_ERR_INVAL;
"espresso/cappuccino") => LFS3_ERR_BUSY;
// this one works
lfs3_rename(&lfs3,
"coffee/thai/..",
@@ -5636,7 +5636,7 @@ code = '''
"espresso/espresso/..") => LFS3_ERR_ISDIR;
lfs3_rename(&lfs3,
"coffee/coldbrew",
"espresso/americano/../..") => LFS3_ERR_INVAL;
"espresso/americano/../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/turkish",
"espresso/macchiato/../../..") => LFS3_ERR_INVAL;
@@ -5665,7 +5665,7 @@ code = '''
"espresso/latte/../../../..") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/vietnamese/../..",
"espresso/cappuccino/../../../../..") => LFS3_ERR_INVAL;
"espresso/cappuccino/../../../../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/thai/..",
"espresso/mocha/../../../../../..") => LFS3_ERR_INVAL;
@@ -5685,14 +5685,14 @@ code = '''
"coffee/tubruk/../../..") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3,
"coffee/vietnamese/../..",
"coffee/vietnamese/../..") => LFS3_ERR_INVAL;
"coffee/vietnamese/../..") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3,
"coffee/thai/..",
"coffee/thai/..") => 0;
// remove paths
lfs3_remove(&lfs3, "coffee/drip/..") => LFS3_ERR_NOTEMPTY;
lfs3_remove(&lfs3, "coffee/coldbrew/../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/coldbrew/../..") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "coffee/turkish/../../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/tubruk/../../../..") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "coffee/vietnamese/../../../../..") => LFS3_ERR_INVAL;
@@ -5833,13 +5833,13 @@ code = '''
lfs3_dir_close(&lfs3, &dir) => 0;
// rename root, this should error
lfs3_rename(&lfs3, "/", "coffee") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/", "coffee") => LFS3_ERR_BUSY;
lfs3_mkdir(&lfs3, "coffee") => 0;
lfs3_rename(&lfs3, "coffee", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "coffee", "/") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "coffee") => 0;
lfs3_rename(&lfs3, "/", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/", "/") => LFS3_ERR_BUSY;
// stat root
lfs3_stat(&lfs3, "/", &info) => 0;
@@ -5847,7 +5847,7 @@ code = '''
assert(info.type == LFS3_TYPE_DIR);
// remove root, this should error
lfs3_remove(&lfs3, "/") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "/") => LFS3_ERR_BUSY;
// stat root
lfs3_stat(&lfs3, "/", &info) => 0;
@@ -5953,26 +5953,26 @@ code = '''
lfs3_dir_close(&lfs3, &dir) => 0;
// rename root, this should error
lfs3_rename(&lfs3, "/", "coffee") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, ".", "coffee") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "./", "coffee") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/.", "coffee") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "//", "coffee") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/", "coffee") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, ".", "coffee") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "./", "coffee") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "/.", "coffee") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "//", "coffee") => LFS3_ERR_BUSY;
lfs3_mkdir(&lfs3, "coffee") => 0;
lfs3_rename(&lfs3, "coffee", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "coffee", ".") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "coffee", "./") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "coffee", "/.") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "coffee", "//") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "coffee", "/") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "coffee", ".") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "coffee", "./") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "coffee", "/.") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "coffee", "//") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "coffee") => 0;
lfs3_rename(&lfs3, "/", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, ".", ".") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/", "/") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, ".", ".") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "..", "..") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "./", "./") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "/.", "/.") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "//", "//") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "./", "./") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "/.", "/.") => LFS3_ERR_BUSY;
lfs3_rename(&lfs3, "//", "//") => LFS3_ERR_BUSY;
// stat root
lfs3_stat(&lfs3, "/", &info) => 0;
@@ -5992,11 +5992,11 @@ code = '''
assert(info.type == LFS3_TYPE_DIR);
// remove root, this should error
lfs3_remove(&lfs3, "/") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, ".") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "./") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "/.") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "//") => LFS3_ERR_INVAL;
lfs3_remove(&lfs3, "/") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, ".") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "./") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "/.") => LFS3_ERR_BUSY;
lfs3_remove(&lfs3, "//") => LFS3_ERR_BUSY;
// stat root
lfs3_stat(&lfs3, "/", &info) => 0;

View File

@@ -2447,7 +2447,7 @@ code = '''
// well, because of the root really, but also because of the
// stickynote
//
lfs3_rename(&lfs3, "batman", "/") => LFS3_ERR_INVAL;
lfs3_rename(&lfs3, "batman", "/") => LFS3_ERR_BUSY;
// we should still be able to read our uncreat
lfs3_file_rewind(&lfs3, &uncreat) => 0;

File diff suppressed because it is too large Load Diff