diff --git a/lfs.c b/lfs.c index 666c5b0c..d01dfebf 100644 --- a/lfs.c +++ b/lfs.c @@ -6549,11 +6549,11 @@ static int lfsr_data_readmptr(lfs_t *lfs, lfsr_data_t *data, // open flags static inline bool lfsr_o_isrdonly(uint32_t flags) { - return (flags & 3) == LFS_O_RDONLY; + return (flags & LFS_O_MODE) == LFS_O_RDONLY; } static inline bool lfsr_o_iswronly(uint32_t flags) { - return (flags & 3) == LFS_O_WRONLY; + return (flags & LFS_O_MODE) == LFS_O_WRONLY; } static inline bool lfsr_o_iscreat(uint32_t flags) { @@ -6607,19 +6607,19 @@ static inline bool lfsr_o_isbshrub(uint32_t flags) { } static inline bool lfsr_o_isunflush(uint32_t flags) { - return flags & LFS_O_UNFLUSH; + return flags & LFS_o_UNFLUSH; } static inline bool lfsr_o_isunsync(uint32_t flags) { - return flags & LFS_O_UNSYNC; + return flags & LFS_o_UNSYNC; } static inline bool lfsr_o_isuncreat(uint32_t flags) { - return flags & LFS_O_UNCREAT; + return flags & LFS_o_UNCREAT; } static inline bool lfsr_o_iszombie(uint32_t flags) { - return flags & LFS_O_ZOMBIE; + return flags & LFS_o_ZOMBIE; } // custom rat flags @@ -6670,11 +6670,11 @@ static inline uint32_t lfsr_t_setbtype(uint32_t flags, uint8_t btype) { } static inline bool lfsr_t_isdirty(uint32_t flags) { - return flags & LFS_T_DIRTY; + return flags & LFS_t_DIRTY; } static inline bool lfsr_t_ismutated(uint32_t flags) { - return flags & LFS_T_MUTATED; + return flags & LFS_t_MUTATED; } static inline uint32_t lfsr_t_swapdirty(uint32_t flags) { @@ -6721,7 +6721,7 @@ static inline bool lfsr_m_issync(uint32_t flags) { // internal fs flags static inline bool lfsr_i_isuntidy(uint32_t flags) { - return flags & LFS_I_UNTIDY; + return flags & LFS_i_UNTIDY; } static inline bool lfsr_i_iscompact(uint32_t flags) { @@ -6804,7 +6804,7 @@ static void lfsr_omdir_clobber(lfs_t *lfs, const lfsr_omdir_t *o, bool dirty) { for (lfsr_omdir_t *o_ = lfs->omdirs; o_; o_ = o_->next) { if (lfsr_o_type(o_->flags) == LFS_TYPE_TRAVERSAL) { - o_->flags |= (dirty) ? LFS_T_DIRTY : 0; + o_->flags |= (dirty) ? LFS_t_DIRTY : 0; if (o && ((lfsr_traversal_t*)o_)->ot == o) { lfsr_traversal_clobber(lfs, (lfsr_traversal_t*)o_); @@ -8744,7 +8744,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, if (o->mdir.mid < mid_ - rats[i].weight) { // we should not be removing opened regular files LFS_ASSERT(lfsr_o_type(o->flags) != LFS_TYPE_REG); - o->flags |= LFS_O_ZOMBIE; + o->flags |= LFS_o_ZOMBIE; o->mdir.mid = mid_; } else { o->mdir.mid += rats[i].weight; @@ -9554,7 +9554,7 @@ dropped:; } // make sure we clear any zombie flags - t->o.o.flags &= ~LFS_O_ZOMBIE; + t->o.o.flags &= ~LFS_o_ZOMBIE; // did this drop our mdir? if (mdir->mid != -1 && mdir->rbyd.weight == 0) { @@ -9623,7 +9623,7 @@ eot:; // was mkconsistent successful? if (lfsr_t_ismkconsistent(t->o.o.flags) && !lfsr_t_isdirty(t->o.o.flags)) { - lfs->flags &= ~LFS_I_UNTIDY; + lfs->flags &= ~LFS_i_UNTIDY; } // was compaction successful? note we may need multiple passes if @@ -10008,9 +10008,9 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { if (exists && lfsr_o_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == mdir.mid) { - o->flags = (o->flags & ~LFS_O_UNCREAT) - | LFS_O_ZOMBIE - | LFS_O_UNSYNC + o->flags = (o->flags & ~LFS_o_UNCREAT) + | LFS_o_ZOMBIE + | LFS_o_UNSYNC | LFS_O_DESYNC; // update dir positions @@ -10158,23 +10158,23 @@ int lfsr_remove(lfs_t *lfs, const char *path) { if (zombie && lfsr_o_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == mdir.mid) { - o->flags |= LFS_O_UNCREAT - | LFS_O_ZOMBIE - | LFS_O_UNSYNC + o->flags |= LFS_o_UNCREAT + | LFS_o_ZOMBIE + | LFS_o_UNSYNC | LFS_O_DESYNC; // mark any removed dirs as zombied } else if (did_ && lfsr_o_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == did_) { - o->flags |= LFS_O_ZOMBIE; + o->flags |= LFS_o_ZOMBIE; // update dir positions } else if (lfsr_o_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == did && o->mdir.mid >= mdir.mid) { if (lfsr_o_iszombie(o->flags)) { - o->flags &= ~LFS_O_ZOMBIE; + o->flags &= ~LFS_o_ZOMBIE; } else { ((lfsr_dir_t*)o)->pos -= 1; } @@ -10182,7 +10182,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) { // clobber entangled traversals } else if (lfsr_o_type(o->flags) == LFS_TYPE_TRAVERSAL) { if (lfsr_o_iszombie(o->flags)) { - o->flags &= ~LFS_O_ZOMBIE; + o->flags &= ~LFS_o_ZOMBIE; o->mdir.mid -= 1; lfsr_traversal_clobber(lfs, (lfsr_traversal_t*)o); } @@ -10324,9 +10324,9 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { if (exists && lfsr_o_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == new_mdir.mid) { - o->flags = (o->flags & ~LFS_O_UNCREAT) - | LFS_O_ZOMBIE - | LFS_O_UNSYNC + o->flags = (o->flags & ~LFS_o_UNCREAT) + | LFS_o_ZOMBIE + | LFS_o_UNSYNC | LFS_O_DESYNC; // update moved files with the new mdir @@ -10338,7 +10338,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { } else if (new_did_ && lfsr_o_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == new_did_) { - o->flags |= LFS_O_ZOMBIE; + o->flags |= LFS_o_ZOMBIE; // update dir positions } else if (lfsr_o_type(o->flags) == LFS_TYPE_DIR) { @@ -10878,7 +10878,7 @@ static int lfsr_file_fetch(lfs_t *lfs, lfsr_file_t *file, bool trunc) { file->buffer.pos = 0; file->buffer.size = 0; // mark as flushed - file->o.o.flags &= ~LFS_O_UNFLUSH; + file->o.o.flags &= ~LFS_o_UNFLUSH; // don't bother reading disk if we're not created or truncating if (!lfsr_o_isuncreat(file->o.o.flags) && !trunc) { @@ -10929,7 +10929,7 @@ static int lfsr_file_fetch(lfs_t *lfs, lfsr_file_t *file, bool trunc) { file->o.bshrub = file->o.bshrub_; // mark as synced - file->o.o.flags &= ~LFS_O_UNSYNC; + file->o.o.flags &= ~LFS_o_UNSYNC; } // if our file is small, try to keep the whole thing in our buffer @@ -10945,7 +10945,7 @@ static int lfsr_file_fetch(lfs_t *lfs, lfsr_file_t *file, bool trunc) { } // small files remain perpetually unflushed - file->o.o.flags |= LFS_O_UNFLUSH; + file->o.o.flags |= LFS_o_UNFLUSH; lfsr_bshrub_init(&file->o.bshrub); file->buffer.pos = 0; file->buffer.size = size; @@ -11051,7 +11051,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, // mounted with LFS_M_FLUSH/SYNC? implies LFS_O_FLUSH/SYNC | (lfs->flags & (LFS_M_FLUSH | LFS_M_SYNC)) // default to unflushed for orphans/truncated files - | LFS_O_UNFLUSH; + | LFS_o_UNFLUSH; file->pos = 0; file->eblock = 0; file->eoff = -1; @@ -11087,7 +11087,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, if (exists && lfsr_o_isexcl(flags) && lfsr_omdir_ismidopen(lfs, file->o.o.mdir.mid, - ~(LFS_O_ZOMBIE | LFS_O_DESYNC))) { + ~(LFS_o_ZOMBIE | LFS_O_DESYNC))) { return LFS_ERR_EXIST; } @@ -11121,7 +11121,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, // mark as uncreated and unsynced, we need to convert to reg file // on first sync - file->o.o.flags |= LFS_O_UNCREAT | LFS_O_UNSYNC; + file->o.o.flags |= LFS_o_UNCREAT | LFS_o_UNSYNC; } else { // wanted to create a new entry? @@ -11204,7 +11204,7 @@ static void lfsr_file_close_(lfs_t *lfs, const lfsr_file_t *file) { // fallback to just marking the filesystem as untidy } else { - lfs->flags |= LFS_I_UNTIDY; + lfs->flags |= LFS_i_UNTIDY; } } } @@ -12287,7 +12287,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, // checkpoint the allocator lfs_alloc_ckpoint(lfs); // mark as unsynced in case we fail - file->o.o.flags |= LFS_O_UNSYNC; + file->o.o.flags |= LFS_o_UNSYNC; // update pos if we are appending lfs_off_t pos = file->pos; @@ -12334,7 +12334,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, lfsr_file_buffersize(lfs, file)); file->buffer.size = lfsr_file_buffersize(lfs, file); - file->o.o.flags &= ~LFS_O_UNFLUSH; + file->o.o.flags &= ~LFS_o_UNFLUSH; written += size; pos += size; buffer_ += size; @@ -12377,7 +12377,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, file->buffer.size, pos+d - file->buffer.pos); - file->o.o.flags |= LFS_O_UNFLUSH; + file->o.o.flags |= LFS_o_UNFLUSH; written += d; pos += d; buffer_ += d; @@ -12391,7 +12391,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, if (err) { goto failed; } - file->o.o.flags &= ~LFS_O_UNFLUSH; + file->o.o.flags &= ~LFS_o_UNFLUSH; } // update our pos @@ -12461,7 +12461,7 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) { } // mark as flushed - file->o.o.flags &= ~LFS_O_UNFLUSH; + file->o.o.flags &= ~LFS_o_UNFLUSH; return 0; failed:; @@ -12635,19 +12635,19 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { && o != &file->o.o) { lfsr_file_t *file_ = (lfsr_file_t*)o; // notify all files of creation - file_->o.o.flags &= ~LFS_O_UNCREAT; + file_->o.o.flags &= ~LFS_o_UNCREAT; // mark desynced files an unsynced if (lfsr_o_isdesync(file_->o.o.flags)) { - file_->o.o.flags |= LFS_O_UNSYNC; + file_->o.o.flags |= LFS_o_UNSYNC; // update synced files } else { - file_->o.o.flags &= ~LFS_O_UNSYNC; + file_->o.o.flags &= ~LFS_o_UNSYNC; if (lfsr_o_isunflush(file->o.o.flags)) { - file_->o.o.flags |= LFS_O_UNFLUSH; + file_->o.o.flags |= LFS_o_UNFLUSH; } else { - file_->o.o.flags &= ~LFS_O_UNFLUSH; + file_->o.o.flags &= ~LFS_o_UNFLUSH; } file_->o.bshrub = file->o.bshrub; file_->buffer.pos = file->buffer.pos; @@ -12699,7 +12699,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { } // mark as synced - file->o.o.flags &= ~(LFS_O_UNSYNC | LFS_O_UNCREAT | LFS_O_DESYNC); + file->o.o.flags &= ~(LFS_o_UNSYNC | LFS_o_UNCREAT | LFS_O_DESYNC); return 0; failed:; @@ -12819,7 +12819,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { // checkpoint the allocator lfs_alloc_ckpoint(lfs); // mark as unsynced in case we fail - file->o.o.flags |= LFS_O_UNSYNC; + file->o.o.flags |= LFS_o_UNSYNC; // does our file become small? if (size_ <= lfsr_file_inlinesize(lfs, file)) { @@ -12854,7 +12854,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { } // small files remain perpetually unflushed - file->o.o.flags |= LFS_O_UNFLUSH; + file->o.o.flags |= LFS_o_UNFLUSH; lfsr_bshrub_init(&file->o.bshrub); file->buffer.pos = 0; file->buffer.size = size_; @@ -12928,7 +12928,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { // checkpoint the allocator lfs_alloc_ckpoint(lfs); // mark as unsynced in case we fail - file->o.o.flags |= LFS_O_UNSYNC; + file->o.o.flags |= LFS_o_UNSYNC; // does our file become small? if (size_ <= lfsr_file_inlinesize(lfs, file)) { @@ -12976,7 +12976,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { } // small files remain perpetually unflushed - file->o.o.flags |= LFS_O_UNFLUSH; + file->o.o.flags |= LFS_o_UNFLUSH; lfsr_bshrub_init(&file->o.bshrub); file->buffer.pos = 0; file->buffer.size = size_; @@ -13201,7 +13201,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, // setup flags lfs->flags = flags // assume we contain orphans until proven otherwise - | LFS_I_UNTIDY + | LFS_i_UNTIDY // default to an empty lookahead | LFS_I_LOOKAHEAD // default to assuming we need compaction somewhere, worst case @@ -13420,16 +13420,16 @@ static int lfs_deinit(lfs_t *lfs) { // note, "understanding" does not necessarily mean support // enum lfsr_rcompat { - LFSR_RCOMPAT_NONSTANDARD = 0x0001, - LFSR_RCOMPAT_MLEAF = 0x0002, - LFSR_RCOMPAT_MTREE = 0x0008, - LFSR_RCOMPAT_BSPROUT = 0x0010, - LFSR_RCOMPAT_BLEAF = 0x0020, - LFSR_RCOMPAT_BSHRUB = 0x0040, - LFSR_RCOMPAT_BTREE = 0x0080, - LFSR_RCOMPAT_GRM = 0x0100, + LFSR_RCOMPAT_NONSTANDARD = 0x0001, // Non-standard filesystem format + LFSR_RCOMPAT_MLEAF = 0x0002, // May use a single mdir pointer + LFSR_RCOMPAT_MTREE = 0x0008, // May use an mtree + LFSR_RCOMPAT_BSPROUT = 0x0010, // Files may use inlined data + LFSR_RCOMPAT_BLEAF = 0x0020, // Files may use single block pointers + LFSR_RCOMPAT_BSHRUB = 0x0040, // Files may use inlined btrees + LFSR_RCOMPAT_BTREE = 0x0080, // Files may use btrees + LFSR_RCOMPAT_GRM = 0x0100, // May use a global-remove // internal - LFSR_RCOMPAT_OVERFLOW = 0x8000, + LFSR_rcompat_OVERFLOW = 0x8000, // Can't represent all flags }; #define LFSR_RCOMPAT_COMPAT \ @@ -13442,17 +13442,17 @@ enum lfsr_rcompat { | LFSR_RCOMPAT_GRM) enum lfsr_wcompat { - LFSR_WCOMPAT_NONSTANDARD = 0x0001, + LFSR_WCOMPAT_NONSTANDARD = 0x0001, // Non-standard filesystem format // internal - LFSR_WCOMPAT_OVERFLOW = 0x8000, + LFSR_wcompat_OVERFLOW = 0x8000, // Can't represent all flags }; #define LFSR_WCOMPAT_COMPAT 0 enum lfsr_ocompat { - LFSR_OCOMPAT_NONSTANDARD = 0x0001, + LFSR_OCOMPAT_NONSTANDARD = 0x0001, // Non-standard filesystem format // internal - LFSR_OCOMPAT_OVERFLOW = 0x8000, + LFSR_ocompat_OVERFLOW = 0x8000, // Can't represent all flags }; #define LFSR_OCOMPAT_COMPAT 0 @@ -14192,7 +14192,7 @@ int lfsr_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) { | LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, 0) | LFS_IFDEF_CKPARITY(LFS_I_CKPARITY, 0) | LFS_IFDEF_CKDATACKSUMS(LFS_I_CKDATACKSUMS, 0) - | LFS_I_MKCONSISTENT // synonym for LFS_I_UNTIDY + | LFS_I_MKCONSISTENT // synonym for LFS_i_UNTIDY | LFS_I_LOOKAHEAD | LFS_I_COMPACT | LFS_I_CKMETA @@ -14451,7 +14451,7 @@ static int lfsr_fs_gc_(lfs_t *lfs, lfsr_traversal_t *t, // do we have any pending work? uint32_t pending = flags & ( (lfs->flags & ( - LFS_I_UNTIDY + LFS_i_UNTIDY | LFS_I_LOOKAHEAD | LFS_I_COMPACT | LFS_I_CKMETA @@ -14505,7 +14505,7 @@ static int lfsr_fs_gc_(lfs_t *lfs, lfsr_traversal_t *t, // clear any pending flags we make progress on pending &= lfs->flags & ( - LFS_I_UNTIDY + LFS_i_UNTIDY | LFS_I_LOOKAHEAD | LFS_I_COMPACT | LFS_I_CKMETA @@ -14772,7 +14772,7 @@ static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) { // reset traversal lfsr_traversal_init(t, - t->o.o.flags & ~(LFS_T_DIRTY | LFS_T_MUTATED | LFS_T_TSTATE)); + t->o.o.flags & ~(LFS_t_DIRTY | LFS_t_MUTATED | LFS_t_TSTATE)); // and clear any pending blocks t->blocks[0] = -1; diff --git a/lfs.h b/lfs.h index 6260c528..264a9709 100644 --- a/lfs.h +++ b/lfs.h @@ -126,6 +126,7 @@ enum lfs_type { }; // File open flags +#define LFS_O_MODE 3 // The file's access mode #define LFS_O_RDONLY 0 // Open a file as read only #define LFS_O_WRONLY 1 // Open a file as write only #define LFS_O_RDWR 2 // Open a file as read and write @@ -140,11 +141,11 @@ enum lfs_type { #define LFS_O_CKDATA 0x00020000 // Check metadata + data checksums // internally used flags, don't use these -#define LFS_O_TYPE 0xff000000 // The file's type -#define LFS_O_UNFLUSH 0x00100000 // File's data does not match disk -#define LFS_O_UNSYNC 0x00200000 // File's metadata does not match disk -#define LFS_O_UNCREAT 0x00400000 // File does not exist yet -#define LFS_O_ZOMBIE 0x00800000 // File has been removed +#define LFS_o_TYPE 0xff000000 // The file's type +#define LFS_o_UNFLUSH 0x00100000 // File's data does not match disk +#define LFS_o_UNSYNC 0x00200000 // File's metadata does not match disk +#define LFS_o_UNCREAT 0x00400000 // File does not exist yet +#define LFS_o_ZOMBIE 0x00800000 // File has been removed // File seek flags #define LFS_SEEK_SET 0 // Seek relative to an absolute position @@ -152,12 +153,14 @@ enum lfs_type { #define LFS_SEEK_END 2 // Seek relative to the end of the file // Custom attribute flags +#define LFS_A_MODE 3 // The attr's access mode #define LFS_A_RDONLY 0 // Open an attr as read only #define LFS_A_WRONLY 1 // Open an attr as write only #define LFS_A_RDWR 2 // Open an attr as read and write #define LFS_A_LAZY 0x04 // Only write attr if file changed // Filesystem format flags +#define LFS_F_MODE 1 // Format's access mode #define LFS_F_RDWR 0 // Format the filesystem as read and write #ifdef LFS_CKPROGS #define LFS_F_CKPROGS 0x00100000 // Check progs by reading back progged data @@ -177,6 +180,7 @@ enum lfs_type { #define LFS_F_CKDATA 0x00020000 // Check metadata + data checksums // Filesystem mount flags +#define LFS_M_MODE 1 // Mount's access mode #define LFS_M_RDWR 0 // Mount the filesystem as read and write #define LFS_M_RDONLY 1 // Mount the filesystem as read only #define LFS_M_FLUSH 0x00000040 // Open all files with LFS_O_FLUSH @@ -228,7 +232,7 @@ enum lfs_type { #define LFS_I_CKDATA 0x00020000 // Data checksums not checked recently // internally used flags, don't use these -#define LFS_I_UNTIDY 0x00001000 // Filesystem may have orphaned stickynotes +#define LFS_i_UNTIDY 0x00001000 // Filesystem may have orphaned stickynotes // Block types @@ -248,10 +252,10 @@ enum lfs_btype { #define LFS_T_CKDATA 0x00020000 // Check metadata + data checksums // internally used flags, don't use these -#define LFS_T_TSTATE 0x0000000f // The current traversal state -#define LFS_T_BTYPE 0x000000f0 // The current traversal btype -#define LFS_T_DIRTY 0x00000100 // Filesystem modified during traversal -#define LFS_T_MUTATED 0x00000200 // Filesystem modified by traversal +#define LFS_t_TSTATE 0x0000000f // The traversal's current tstate +#define LFS_t_BTYPE 0x000000f0 // The traversal's current btype +#define LFS_t_DIRTY 0x00000100 // Filesystem modified during traversal +#define LFS_t_MUTATED 0x00000200 // Filesystem modified by traversal // GC flags #define LFS_GC_MKCONSISTENT \ diff --git a/scripts/dbgerr.py b/scripts/dbgerr.py index b64f7e15..67e355bd 100755 --- a/scripts/dbgerr.py +++ b/scripts/dbgerr.py @@ -31,35 +31,30 @@ def main(errs, *, import builtins list_, list = list, builtins.list + lines = [] # list all known error codes if list_: - # first find the widths - w = [0, 0] for n, e, h in ERRS: - w[0] = max(w[0], len('LFS_ERR_')+len(n)) - w[1] = max(w[1], len(str(e))) - - # print - for n, e, h in ERRS: - print('%-*s %-*s %s' % ( - w[0], 'LFS_ERR_'+n, - w[1], e, - h)) + lines.append(('LFS_ERR_'+n, str(e), h)) # find these errors else: def find_err(err): # find by LFS_ERR_+name for n, e, h in ERRS: - if 'LFS_ERR_'+n == err: + if 'LFS_ERR_'+n == err.upper(): + return n, e, h + # find by ERR_+name + for n, e, h in ERRS: + if 'ERR_'+n == err.upper(): return n, e, h # find by name for n, e, h in ERRS: - if n == err: + if n == err.upper(): return n, e, h # find by E+name for n, e, h in ERRS: - if 'E'+n == err: + if 'E'+n == err.upper(): return n, e, h try: # find by err code @@ -78,9 +73,22 @@ def main(errs, *, for err in errs: try: n, e, h = find_err(err) - print('%s %s %s' % ('LFS_ERR_'+n, e, h)) + lines.append(('LFS_ERR_'+n, str(e), h)) except KeyError: - print('%s ?' % err) + lines.append(('?', err, 'Unknown err code')) + + # first find widths + w = [0, 0] + for l in lines: + w[0] = max(w[0], len(l[0])) + w[1] = max(w[1], len(l[1])) + + # then print results + for l in lines: + print('%-*s %-*s %s' % ( + w[0], l[0], + w[1], l[1], + l[2])) if __name__ == "__main__": diff --git a/scripts/dbgflags.py b/scripts/dbgflags.py new file mode 100755 index 00000000..b2e69617 --- /dev/null +++ b/scripts/dbgflags.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python3 + +# prevent local imports +if __name__ == "__main__": + __import__('sys').path.pop(0) + +import collections as co + + +ALIASES = [ + {'O', 'OPEN'}, + {'A', 'ATTR'}, + {'F', 'FORMAT'}, + {'M', 'MOUNT'}, + {'GC'}, + {'I', 'INFO'}, + {'T', 'TRAVERSAL'}, + {'RC', 'RCOMPAT'}, + {'WC', 'WCOMPAT'}, + {'OC', 'OCOMPAT'} +] + +FLAGS = [ + # File open flags + ('O', 'MODE', 3, "The file's access mode" ), + ('^', 'RDONLY', 0, "Open a file as read only" ), + ('^', 'WRONLY', 1, "Open a file as write only" ), + ('^', 'RDWR', 2, "Open a file as read and write" ), + ('O', 'CREAT', 0x00000004, "Create a file if it does not exist" ), + ('O', 'EXCL', 0x00000008, "Fail if a file already exists" ), + ('O', 'TRUNC', 0x00000010, "Truncate the existing file to zero size" ), + ('O', 'APPEND', 0x00000020, "Move to end of file on every write" ), + ('O', 'FLUSH', 0x00000040, "Flush data on every write" ), + ('O', 'SYNC', 0x00000080, "Sync metadata on every write" ), + ('O', 'DESYNC', 0x00000100, "Do not sync or recieve file updates" ), + ('O', 'CKMETA', 0x00010000, "Check metadata checksums" ), + ('O', 'CKDATA', 0x00020000, "Check metadata + data checksums" ), + + ('o', 'TYPE', 0xff000000, "The file's type" ), + ('^', 'REG', 0x01000000, "Type = regular-file" ), + ('^', 'DIR', 0x02000000, "Type = directory" ), + ('^', 'BOOKMARK', 0x04000000, "Type = bookmark" ), + ('^', 'STICKYNOTE',0x05000000, "Type = stickynote" ), + ('^', 'TRAVERSAL', 0x09000000, "Type = traversal" ), + ('o', 'UNFLUSH', 0x00100000, "File's data does not match disk" ), + ('o', 'UNSYNC', 0x00200000, "File's metadata does not match disk" ), + ('o', 'UNCREAT', 0x00400000, "File does not exist yet" ), + ('o', 'ZOMBIE', 0x00800000, "File has been removed" ), + + # Custom attribute flags + ('A', 'MODE', 3, "The attr's access mode" ), + ('^', 'RDONLY', 0, "Open an attr as read only" ), + ('^', 'WRONLY', 1, "Open an attr as write only" ), + ('^', 'RDWR', 2, "Open an attr as read and write" ), + ('A', 'LAZY', 0x04, "Only write attr if file changed" ), + + # Filesystem format flags + ('F', 'MODE', 1, "Format's access mode" ), + ('^', 'RDWR', 0, "Format the filesystem as read and write" ), + ('F', 'CKPROGS', 0x00100000, "Check progs by reading back progged data" ), + ('F', 'CKFETCHES', 0x00200000, "Check block checksums before first use" ), + ('F', 'CKPARITY', 0x00400000, "Check metadata tag parity bits" ), + ('F', 'CKDATACKSUMS', + 0x08000000, "Check data checksums on reads" ), + + ('F', 'CKMETA', 0x00010000, "Check metadata checksums" ), + ('F', 'CKDATA', 0x00020000, "Check metadata + data checksums" ), + + # Filesystem mount flags + ('M', 'MODE', 1, "Mount's access mode" ), + ('^', 'RDWR', 0, "Mount the filesystem as read and write" ), + ('^', 'RDONLY', 1, "Mount the filesystem as read only" ), + ('M', 'FLUSH', 0x00000040, "Open all files with LFS_O_FLUSH" ), + ('M', 'SYNC', 0x00000080, "Open all files with LFS_O_SYNC" ), + ('M', 'CKPROGS', 0x00100000, "Check progs by reading back progged data" ), + ('M', 'CKFETCHES', 0x00200000, "Check block checksums before first use" ), + ('M', 'CKPARITY', 0x00400000, "Check metadata tag parity bits" ), + ('M', 'CKDATACKSUMS', + 0x08000000, "Check data checksums on reads" ), + + ('M', 'MKCONSISTENT', + 0x00001000, "Make the filesystem consistent" ), + ('M', 'LOOKAHEAD', 0x00002000, "Populate lookahead buffer" ), + ('M', 'COMPACT', 0x00008000, "Compact metadata logs" ), + ('M', 'CKMETA', 0x00010000, "Check metadata checksums" ), + ('M', 'CKDATA', 0x00020000, "Check metadata + data checksums" ), + + ('m', 'UNTIDY', 0x00001000, "Filesystem may have orphaned stickynotes" ), + + # GC flags + ('GC', 'MKCONSISTENT', + 0x00001000, "Make the filesystem consistent" ), + ('GC', 'LOOKAHEAD',0x00002000, "Populate lookahead buffer" ), + ('GC', 'COMPACT', 0x00008000, "Compact metadata logs" ), + ('GC', 'CKMETA', 0x00010000, "Check metadata checksums" ), + ('GC', 'CKDATA', 0x00020000, "Check metadata + data checksums" ), + + # Filesystem info flags + ('I', 'RDONLY', 0x00000001, "Mounted read only" ), + ('I', 'FLUSH', 0x00000040, "Mounted with LFS_M_FLUSH" ), + ('I', 'SYNC', 0x00000080, "Mounted with LFS_M_SYNC" ), + ('I', 'CKPROGS', 0x00100000, "Mounted with LFS_M_CKPROGS" ), + ('I', 'CKFETCHES', 0x00200000, "Mounted with LFS_M_CKFETCHES" ), + ('I', 'CKPARITY', 0x00400000, "Mounted with LFS_M_CKPARITY" ), + ('I', 'CKDATACKSUMS', + 0x08000000, "Mounted with LFS_M_CKDATACKSUMS" ), + + ('I', 'MKCONSISTENT', + 0x00001000, "Filesystem needs mkconsistent to write" ), + ('I', 'LOOKAHEAD', 0x00002000, "Lookahead buffer is not full" ), + ('I', 'COMPACT', 0x00008000, "Filesystem may have uncompacted metadata" ), + ('I', 'CKMETA', 0x00010000, "Metadata checksums not checked recently" ), + ('I', 'CKDATA', 0x00020000, "Data checksums not checked recently" ), + + # Traversal flags + ('T', 'MTREEONLY', 0x00000800, "Only traverse the mtree" ), + ('T', 'MKCONSISTENT', + 0x00001000, "Make the filesystem consistent" ), + ('T', 'LOOKAHEAD', 0x00002000, "Populate lookahead buffer" ), + ('T', 'COMPACT', 0x00008000, "Compact metadata logs" ), + ('T', 'CKMETA', 0x00010000, "Check metadata checksums" ), + ('T', 'CKDATA', 0x00020000, "Check metadata + data checksums" ), + + ('t', 'TSTATE', 0x0000000f, "The traversal's current tstate" ), + ('^', 'MROOTANCHOR', + 0x00000000, "Tstate = mroot-anchor" ), + ('^', 'MROOTCHAIN',0x00000001, "Tstate = mroot-chain" ), + ('^', 'MTREE', 0x00000002, "Tstate = mtree" ), + ('^', 'MDIRS', 0x00000003, "Tstate = mtree-mdirs" ), + ('^', 'MDIR', 0x00000004, "Tstate = mdir" ), + ('^', 'BTREE', 0x00000005, "Tstate = btree" ), + ('^', 'OMDIRS', 0x00000006, "Tstate = open-mdirs" ), + ('^', 'OBTREE', 0x00000007, "Tstate = open-btree" ), + ('^', 'DONE', 0x00000008, "Tstate = done" ), + ('t', 'BTYPE', 0x000000f0, "The traversal's current btype" ), + ('^', 'MDIR', 0x00000010, "Btype = mdir" ), + ('^', 'BTREE', 0x00000020, "Btype = btree" ), + ('^', 'DATA', 0x00000030, "Btype = data" ), + ('t', 'DIRTY', 0x00000100, "Filesystem modified during traversal" ), + ('t', 'MUTATED', 0x00000200, "Filesystem modified by traversal" ), + + # Read-compat flags + ('RCOMPAT', 'NONSTANDARD', + 0x0001, "Non-standard filesystem format" ), + ('RCOMPAT', 'MLEAF', 0x0002, "May use a single mdir pointer" ), + ('RCOMPAT', 'MTREE', 0x0008, "May use an mdir btree" ), + ('RCOMPAT', 'BSPROUT', 0x0010, "Files may use inlined data" ), + ('RCOMPAT', 'BLEAF', 0x0020, "Files may use single block pointers" ), + ('RCOMPAT', 'BSHRUB', 0x0040, "Files may use inlined btrees" ), + ('RCOMPAT', 'BTREE', 0x0080, "Files may use btrees" ), + ('RCOMPAT', 'GRM', 0x0100, "May use a global-remove" ), + + ('rcompat', 'OVERFLOW',0x8000, "Can't represent all flags" ), + + # Write-compat flags + ('WCOMPAT', 'NONSTANDARD', + 0x0001, "Non-standard filesystem format" ), + + ('wcompat', 'OVERFLOW',0x8000, "Can't represent all flags" ), + + # Optional-compat flags + ('OCOMPAT', 'NONSTANDARD', + 0x0001, "Non-standard filesystem format" ), + + ('ocompat', 'OVERFLOW',0x8000, "Can't represent all flags" ), +] + + +def main(flags, *, + list=False, + all=False): + import builtins + list_, list = list, builtins.list + all_, all = all, builtins.all + + # first compile prefixes + prefixes = {} + for a in ALIASES: + for k in a: + prefixes[k] = a + for p, n, f, h in FLAGS: + if p not in prefixes: + prefixes[p] = {p} + + # only look at specific prefix? + flags_ = [] + prefix = set() + for f in flags: + if f.upper() in prefixes: + prefix.update(prefixes[f.upper()]) + else: + flags_.append(f) + + # filter by prefix + flags__ = [] + types__ = co.defaultdict(lambda: set()) + for p, n, f, h in FLAGS: + if p == '^': + p = last_p + t = last_t + types__[p].add(t) + else: + t = None + last_p = p + last_t = f + if not prefix or p.upper() in prefix: + flags__.append((p, t, n, f, h)) + + lines = [] + # list all known flags + if list_: + for p, t, n, f, h in flags__: + if not all_ and (t is not None or p[0].islower()): + continue + lines.append(('LFS_%s_%s' % (p, n), '0x%08x' % f, h)) + + # find flags by name or value + else: + for f_ in flags_: + found = False + # find by LFS_+prefix+_+name + for p, t, n, f, h in flags__: + if 'LFS_%s_%s' % (p, n) == f_.upper(): + lines.append(('LFS_%s_%s' % (p, n), '0x%08x' % f, h)) + found = True + if found: + continue + # find by prefix+_+name + for p, t, n, f, h in flags__: + if '%s_%s' % (p, n) == f_.upper(): + lines.append(('LFS_%s_%s' % (p, n), '0x%08x' % f, h)) + found = True + if found: + continue + # find by name + for p, t, n, f, h in flags__: + if n == f_.upper(): + lines.append(('LFS_%s_%s' % (p, n), '0x%08x' % f, h)) + found = True + if found: + continue + # find by value + try: + f__ = int(f_, 0) + f___ = f__ + for p, t, n, f, h in flags__: + # ignore type masks here + if t is None and f in types__[p]: + continue + # matches flag? + if t is None and (f__ & f) == f: + lines.append(('LFS_%s_%s' % (p, n), '0x%08x' % f, h)) + f___ &= ~f + # matches type? + elif t is not None and (f__ & t) == f: + lines.append(('LFS_%s_%s' % (p, n), '0x%08x' % f, h)) + f___ &= ~t + if f___: + lines.append(('?', '0x%08x' % f___, 'Unknown flags')) + except ValueError: + lines.append(('?', f_, 'Unknown flag')) + + # first find widths + w = [0, 0] + for l in lines: + w[0] = max(w[0], len(l[0])) + w[1] = max(w[1], len(l[1])) + + # then print results + for l in lines: + print('%-*s %-*s %s' % ( + w[0], l[0], + w[1], l[1], + l[2])) + + +if __name__ == "__main__": + import argparse + import sys + parser = argparse.ArgumentParser( + description="Decode littlefs error codes.", + allow_abbrev=False) + class AppendFlags(argparse.Action): + def __call__(self, parser, namespace, value, option): + if getattr(namespace, 'flags', None) is None: + namespace.flags = [] + if value is None: + pass + elif isinstance(value, str): + namespace.flags.append(value) + else: + namespace.flags.extend(value) + parser.add_argument( + 'prefix', + nargs='?', + action=AppendFlags, + help="Flag prefix to consider, defaults to all flags.") + parser.add_argument( + 'flags', + nargs='*', + action=AppendFlags, + help="Flags or names of flags to decode.") + parser.add_argument( + '-l', '--list', + action='store_true', + help="List all known flags.") + parser.add_argument( + '-a', '--all', + action='store_true', + help="Also show internal flags and types.") + sys.exit(main(**{k: v + for k, v in vars(parser.parse_intermixed_args()).items() + if v is not None})) diff --git a/tests/test_forphans.toml b/tests/test_forphans.toml index f5949b5b..5551e231 100644 --- a/tests/test_forphans.toml +++ b/tests/test_forphans.toml @@ -5314,7 +5314,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; @@ -5450,7 +5450,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; @@ -5600,7 +5600,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; @@ -5756,7 +5756,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; diff --git a/tests/test_traversal.toml b/tests/test_traversal.toml index d833f688..4db31ce3 100644 --- a/tests/test_traversal.toml +++ b/tests/test_traversal.toml @@ -6458,7 +6458,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); // which means there shouldn't be that many files left assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits)); @@ -6602,7 +6602,7 @@ code = ''' assert(lfs.grm.mids[1] == -1); // if we introduce actual orphans, me _must not_ clear the orphan flag if (ORPHANS >= 3) { - assert(lfs.flags & LFS_I_UNTIDY); + assert(lfs.flags & LFS_i_UNTIDY); } // if we introduced actual orphans, we _must_ be marked as inconsistent @@ -6759,7 +6759,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); // which means there shouldn't be that many files left assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits)); @@ -6917,7 +6917,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); // which means there shouldn't be that many files left assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits)); @@ -7086,7 +7086,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); // which means there shouldn't be that many files left assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits)); @@ -7253,7 +7253,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); // which means there shouldn't be that many files left assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits)); @@ -7418,7 +7418,7 @@ code = ''' // we should have cleaned up all grms/orphans assert(lfs.grm.mids[0] == -1); assert(lfs.grm.mids[1] == -1); - assert(!(lfs.flags & LFS_I_UNTIDY)); + assert(!(lfs.flags & LFS_i_UNTIDY)); // which means there shouldn't be that many files left assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits)); @@ -7613,7 +7613,7 @@ code = ''' assert(lfs.grm.mids[1] == -1); // if we introduce actual orphans, me _must not_ clear the orphan flag if (ORPHANS >= 3) { - assert(lfs.flags & LFS_I_UNTIDY); + assert(lfs.flags & LFS_i_UNTIDY); } // mdirs should have been compacted