diff --git a/lfs.c b/lfs.c index 969d97d8..949524e1 100644 --- a/lfs.c +++ b/lfs.c @@ -587,16 +587,19 @@ enum lfsr_tag_type { LFSR_TAG_CONFIG = 0x0000, LFSR_TAG_MAGIC = 0x0003, LFSR_TAG_VERSION = 0x0004, - LFSR_TAG_FLAGS = 0x0005, - LFSR_TAG_CKSUMTYPE = 0x0006, - LFSR_TAG_REDUNDTYPE = 0x0007, - LFSR_TAG_BLOCKLIMIT = 0x0008, - LFSR_TAG_DISKLIMIT = 0x0009, - LFSR_TAG_MLEAFLIMIT = 0x000a, + LFSR_TAG_RFLAGS = 0x0005, + LFSR_TAG_WFLAGS = 0x0006, + LFSR_TAG_OFLAGS = 0x0007, + LFSR_TAG_BLOCKSIZE = 0x0008, + LFSR_TAG_BLOCKCOUNT = 0x0009, + LFSR_TAG_NAMELIMIT = 0x000a, LFSR_TAG_SIZELIMIT = 0x000b, - LFSR_TAG_NAMELIMIT = 0x000c, - LFSR_TAG_UTAGLIMIT = 0x000d, - LFSR_TAG_UATTRLIMIT = 0x000e, + LFSR_TAG_UTAGLIMIT = 0x000c, + LFSR_TAG_UATTRLIMIT = 0x000d, + LFSR_TAG_STAGLIMIT = 0x000e, + LFSR_TAG_SATTRLIMIT = 0x000f, + LFSR_TAG_MDIRLIMIT = 0x0010, + LFSR_TAG_MTREELIMIT = 0x0011, // global-state tags LFSR_TAG_GSTATE = 0x0100, @@ -7480,197 +7483,109 @@ static int lfsr_mountinited(lfs_t *lfs) { return LFS_ERR_INVAL; } - // check for any flags - err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_FLAGS, + // check for any rflags, we must understand these to read + // the filesystem + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_RFLAGS, NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } - uint32_t flags = 0; - if (err != LFS_ERR_NOENT) { - err = lfsr_data_readleb128(lfs, &data, (int32_t*)&flags); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - flags = -1; - } - } - - if (flags != 0) { - LFS_ERROR("Incompatible flags 0x%"PRIx32, flags); + if (err != LFS_ERR_NOENT && lfsr_data_size(&data) > 0) { + LFS_ERROR("Incompatible rflag 0x%s%"PRIx32, + (lfsr_data_size(&data) > 0) ? "?" : "", + 0); return LFS_ERR_INVAL; } - // check checksum type - err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, - -1, LFSR_TAG_CKSUMTYPE, + // check for any wflags, we must understand these to write + // the filesystem + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_WFLAGS, NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } - uint32_t cksum_type = 0; - if (err != LFS_ERR_NOENT) { - err = lfsr_data_readleb128(lfs, &data, - (int32_t*)&cksum_type); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - cksum_type = -1; - } - } - - if (cksum_type != 0) { - LFS_ERROR("Incompatible cksum type 0x%"PRId32, cksum_type); + if (err != LFS_ERR_NOENT && lfsr_data_size(&data) > 0) { + LFS_ERROR("Incompatible wflag 0x%s%"PRIx32, + (lfsr_data_size(&data) > 0) ? "?" : "", + 0); + // TODO switch to read-only? return LFS_ERR_INVAL; } - // check redundancy type - err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, - -1, LFSR_TAG_REDUNDTYPE, + // check for any oflags, these are optional, if we don't + // understand an oflag we can simply clear it + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_OFLAGS, NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } - uint32_t redund_type = 0; - if (err != LFS_ERR_NOENT) { - err = lfsr_data_readleb128(lfs, &data, - (int32_t*)&redund_type); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - redund_type = -1; - } + if (err != LFS_ERR_NOENT && lfsr_data_size(&data) > 0) { + LFS_DEBUG("Found unknown oflag 0x%s%"PRIx32, + (lfsr_data_size(&data) > 0) ? "?" : "", + 0); + // TODO track and clear oflags in mkconsistent? + LFS_ASSERT(false); } - if (redund_type != 0) { - LFS_ERROR("Incompatible redund type 0x%"PRId32, - redund_type); - return LFS_ERR_INVAL; - } - - // check block limit / block size + // check block size err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, - -1, LFSR_TAG_BLOCKLIMIT, + -1, LFSR_TAG_BLOCKSIZE, NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } - uint32_t block_limit = 0; + uint32_t block_size = 0; if (err != LFS_ERR_NOENT) { err = lfsr_data_readleb128(lfs, &data, - (int32_t*)&block_limit); + (int32_t*)&block_size); if (err && err != LFS_ERR_CORRUPT) { return err; } if (err == LFS_ERR_CORRUPT) { - block_limit = -1; + block_size = -1; } } - if (block_limit != lfs->cfg->block_size-1) { + if (block_size != lfs->cfg->block_size-1) { LFS_ERROR("Incompatible block size %"PRId32" " "(!= %"PRId32")", - block_limit+1, + block_size+1, lfs->cfg->block_size); return LFS_ERR_INVAL; } - // check disk limit / block count + // check block count err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, - -1, LFSR_TAG_DISKLIMIT, + -1, LFSR_TAG_BLOCKCOUNT, NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } - uint32_t disk_limit = 0; + uint32_t block_count = 0; if (err != LFS_ERR_NOENT) { err = lfsr_data_readleb128(lfs, &data, - (int32_t*)&disk_limit); + (int32_t*)&block_count); if (err && err != LFS_ERR_CORRUPT) { return err; } if (err == LFS_ERR_CORRUPT) { - disk_limit = -1; + block_count = -1; } } - if (disk_limit != lfs->cfg->block_count-1) { + if (block_count != lfs->cfg->block_count-1) { LFS_ERROR("Incompatible block count %"PRId32" " "(!= %"PRId32")", - disk_limit+1, + block_count+1, lfs->cfg->block_count); return LFS_ERR_INVAL; } - // read the mleaf limit - err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, - -1, LFSR_TAG_MLEAFLIMIT, - NULL, &data); - if (err) { - if (err == LFS_ERR_NOENT) { - LFS_ERROR("No mleaf limit found"); - return LFS_ERR_INVAL; - } - return err; - } - - uint32_t mleaf_limit; - err = lfsr_data_readleb128(lfs, &data, (int32_t*)&mleaf_limit); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - mleaf_limit = -1; - } - - // we only support power-of-two mleaf weights, this unlikely to - // ever to change since mleaf weights are pretty arbitrary - if (lfs_popc(mleaf_limit+1) != 1) { - LFS_ERROR("Incompatible mleaf weight %"PRId32, - mleaf_limit+1); - return LFS_ERR_INVAL; - } - - lfs->mleaf_bits = lfs_nlog2(mleaf_limit); - - // read the size limit - err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, - -1, LFSR_TAG_SIZELIMIT, - NULL, &data); - if (err) { - if (err == LFS_ERR_NOENT) { - LFS_ERROR("No size limit found"); - return LFS_ERR_INVAL; - } - return err; - } - - uint32_t size_limit; - err = lfsr_data_readleb128(lfs, &data, (int32_t*)&size_limit); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - size_limit = -1; - } - - if (size_limit > lfs->size_limit) { - LFS_ERROR("Incompatible size limit (%"PRId32" > %"PRId32")", - size_limit, - lfs->size_limit); - return LFS_ERR_INVAL; - } - - lfs->size_limit = size_limit; - // read the name limit err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_NAMELIMIT, @@ -7693,7 +7608,8 @@ static int lfsr_mountinited(lfs_t *lfs) { } if (name_limit > lfs->name_limit) { - LFS_ERROR("Incompatible name limit (%"PRId32" > %"PRId32")", + LFS_ERROR("Incompatible name limit " + "(%"PRId32" > %"PRId32")", name_limit, lfs->name_limit); return LFS_ERR_INVAL; @@ -7701,6 +7617,37 @@ static int lfsr_mountinited(lfs_t *lfs) { lfs->name_limit = name_limit; + // read the size limit + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, + -1, LFSR_TAG_SIZELIMIT, + NULL, &data); + if (err) { + if (err == LFS_ERR_NOENT) { + LFS_ERROR("No size limit found"); + return LFS_ERR_INVAL; + } + return err; + } + + uint32_t size_limit; + err = lfsr_data_readleb128(lfs, &data, (int32_t*)&size_limit); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + if (err == LFS_ERR_CORRUPT) { + size_limit = -1; + } + + if (size_limit > lfs->size_limit) { + LFS_ERROR("Incompatible size limit " + "(%"PRId32" > %"PRId32")", + size_limit, + lfs->size_limit); + return LFS_ERR_INVAL; + } + + lfs->size_limit = size_limit; + // check the utag limit err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_UTAGLIMIT, @@ -7730,35 +7677,158 @@ static int lfsr_mountinited(lfs_t *lfs) { } } - // check the uattr limit + // read the uattr limit err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, -1, LFSR_TAG_UATTRLIMIT, NULL, &data); + if (err) { + if (err == LFS_ERR_NOENT) { + LFS_ERROR("No uattr limit found"); + return LFS_ERR_INVAL; + } + return err; + } + + uint32_t uattr_limit; + err = lfsr_data_readleb128(lfs, &data, (int32_t*)&uattr_limit); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + if (err == LFS_ERR_CORRUPT) { + uattr_limit = -1; + } + + if (uattr_limit > lfs->uattr_limit) { + LFS_ERROR("Incompatible uattr limit " + "(%"PRId32" > %"PRId32")", + uattr_limit, + lfs->uattr_limit); + return LFS_ERR_INVAL; + } + + lfs->uattr_limit = uattr_limit; + + // check the stag limit + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, + -1, LFSR_TAG_STAGLIMIT, + NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } if (err != LFS_ERR_NOENT) { - uint32_t uattr_limit; + uint32_t stag_limit; err = lfsr_data_readleb128(lfs, &data, - (int32_t*)&uattr_limit); + (int32_t*)&stag_limit); if (err && err != LFS_ERR_CORRUPT) { return err; } if (err == LFS_ERR_CORRUPT) { - uattr_limit = -1; + stag_limit = -1; } - // only >=block_size uattrs are (implicitly) supported - if (uattr_limit < lfs->cfg->block_size-1) { - LFS_ERROR("Incompatible uattr limit " - "(%"PRId32" < %"PRId32")", - uattr_limit, - lfs->cfg->block_size-1); + // only 7-bit stags are supported + if (stag_limit != 0x7f) { + LFS_ERROR("Incompatible stag limit " + "(%"PRId32" != %"PRId32")", + stag_limit, + 0x7f); return LFS_ERR_INVAL; } } + // read the sattr limit + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, + -1, LFSR_TAG_SATTRLIMIT, + NULL, &data); + if (err) { + if (err == LFS_ERR_NOENT) { + LFS_ERROR("No sattr limit found"); + return LFS_ERR_INVAL; + } + return err; + } + + uint32_t sattr_limit; + err = lfsr_data_readleb128(lfs, &data, (int32_t*)&sattr_limit); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + if (err == LFS_ERR_CORRUPT) { + sattr_limit = -1; + } + + if (sattr_limit > lfs->sattr_limit) { + LFS_ERROR("Incompatible sattr limit " + "(%"PRId32" > %"PRId32")", + sattr_limit, + lfs->sattr_limit); + return LFS_ERR_INVAL; + } + + lfs->sattr_limit = sattr_limit; + + // read the mdir limit + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, + -1, LFSR_TAG_MDIRLIMIT, + NULL, &data); + if (err) { + if (err == LFS_ERR_NOENT) { + LFS_ERROR("No mdir limit found"); + return LFS_ERR_INVAL; + } + return err; + } + + uint32_t mdir_limit; + err = lfsr_data_readleb128(lfs, &data, (int32_t*)&mdir_limit); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + if (err == LFS_ERR_CORRUPT) { + mdir_limit = -1; + } + + // we only support power-of-two-minus-one mdir limits, this is + // unlikely to ever to change since mdir limits are arbitrary + if (lfs_popc(mdir_limit+1) != 1) { + LFS_ERROR("Incompatible mdir limit %"PRId32, + mdir_limit); + return LFS_ERR_INVAL; + } + + lfs->mleaf_bits = lfs_nlog2(mdir_limit+1); + + // read the mtree limit + err = lfsr_mdir_lookup(lfs, &tinfo.u.mdir, + -1, LFSR_TAG_MTREELIMIT, + NULL, &data); + if (err) { + if (err == LFS_ERR_NOENT) { + LFS_ERROR("No mtree limit found"); + return LFS_ERR_INVAL; + } + return err; + } + + uint32_t mtree_limit; + err = lfsr_data_readleb128(lfs, &data, (int32_t*)&mtree_limit); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + if (err == LFS_ERR_CORRUPT) { + mtree_limit = -1; + } + + // TODO should we actually be doing something with mtree_limit? + if (mtree_limit != lfs->size_limit) { + LFS_ERROR("Incompatible mtree limit " + "(%"PRId32" != %"PRId32")", + mtree_limit, + LFS_FILE_MAX); + return LFS_ERR_INVAL; + } + // keep track of the last mroot we see, this is the "real" mroot lfs->mroot = tinfo.u.mdir; @@ -7856,15 +7926,20 @@ static int lfsr_formatinited(lfs_t *lfs) { // - any format-time configuration // - the root's bookmark tag, which reserves did = 0 for the root err = lfsr_rbyd_commit(lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(-1, MAGIC, 0, BUF("littlefs", 8)), - LFSR_ATTR(-1, VERSION, 0, IMM(((const uint8_t[2]){ + LFSR_ATTR(-1, MAGIC, 0, BUF("littlefs", 8)), + LFSR_ATTR(-1, VERSION, 0, IMM(((const uint8_t[2]){ LFS_DISK_VERSION_MAJOR, LFS_DISK_VERSION_MINOR}), 2)), - LFSR_ATTR(-1, BLOCKLIMIT, 0, LEB128(lfs->cfg->block_size-1)), - LFSR_ATTR(-1, DISKLIMIT, 0, LEB128(lfs->cfg->block_count-1)), - LFSR_ATTR(-1, MLEAFLIMIT, 0, LEB128(lfsr_mleafweight(lfs)-1)), - LFSR_ATTR(-1, SIZELIMIT, 0, LEB128(0x7fffffff)), - LFSR_ATTR(-1, NAMELIMIT, 0, LEB128(0xff)), + LFSR_ATTR(-1, BLOCKSIZE, 0, LEB128(lfs->cfg->block_size-1)), + LFSR_ATTR(-1, BLOCKCOUNT, 0, LEB128(lfs->cfg->block_count-1)), + LFSR_ATTR(-1, NAMELIMIT, 0, LEB128(lfs->name_limit)), + LFSR_ATTR(-1, SIZELIMIT, 0, LEB128(lfs->size_limit)), + LFSR_ATTR(-1, UTAGLIMIT, 0, LEB128(0x7f)), + LFSR_ATTR(-1, UATTRLIMIT, 0, LEB128(lfs->uattr_limit)), + LFSR_ATTR(-1, STAGLIMIT, 0, LEB128(0x7f)), + LFSR_ATTR(-1, SATTRLIMIT, 0, LEB128(lfs->sattr_limit)), + LFSR_ATTR(-1, MDIRLIMIT, 0, LEB128(lfsr_mleafweight(lfs)-1)), + LFSR_ATTR(-1, MTREELIMIT, 0, LEB128(lfs->size_limit)), LFSR_ATTR(0, BOOKMARK, +1, LEB128(0)))); if (err) { return err; @@ -14282,6 +14357,18 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->size_limit = LFS_FILE_MAX; } + LFS_ASSERT(lfs->cfg->uattr_limit <= LFS_UATTR_MAX); + lfs->uattr_limit = lfs->cfg->uattr_limit; + if (!lfs->uattr_limit) { + lfs->uattr_limit = LFS_UATTR_MAX; + } + + LFS_ASSERT(lfs->cfg->sattr_limit <= LFS_SATTR_MAX); + lfs->sattr_limit = lfs->cfg->sattr_limit; + if (!lfs->sattr_limit) { + lfs->sattr_limit = LFS_SATTR_MAX; + } + // setup default state lfs->root[0] = LFS_BLOCK_NULL; lfs->root[1] = LFS_BLOCK_NULL; diff --git a/lfs.h b/lfs.h index 186dc6ae..c6dfccf6 100644 --- a/lfs.h +++ b/lfs.h @@ -82,6 +82,16 @@ typedef int32_t lfsr_sdid_t; //#define LFS_ATTR_MAX 1022 //#endif +// TODO document +#ifndef LFS_UATTR_MAX +#define LFS_UATTR_MAX 255 +#endif + +#ifndef LFS_SATTR_MAX +#define LFS_SATTR_MAX 255 +#endif + + // Possible error codes, these are negative to allow // valid positive return values enum lfs_error { @@ -265,6 +275,10 @@ struct lfs_config { // in superblock and must be respected by other littlefs drivers. lfs_size_t size_limit; + // TODO document + lfs_size_t uattr_limit; + lfs_size_t sattr_limit; + // TODO rm me // // Optional upper limit on custom attributes in bytes. No downside for // // larger attributes size but must be <= LFS_ATTR_MAX. Defaults to @@ -610,6 +624,8 @@ typedef struct lfs { const struct lfs_config *cfg; lfs_size_t name_limit; lfs_off_t size_limit; + lfs_size_t uattr_limit; + lfs_size_t sattr_limit; // begin lfsr things lfsr_grm_t grm; diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index bc65f257..db6e5c9d 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -12,16 +12,19 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 -TAG_FLAGS = 0x0005 -TAG_CKSUMTYPE = 0x0006 -TAG_REDUNDTYPE = 0x0007 -TAG_BLOCKLIMIT = 0x0008 -TAG_DISKLIMIT = 0x0009 -TAG_MLEAFLIMIT = 0x000a +TAG_RFLAGS = 0x0005 +TAG_WFLAGS = 0x0006 +TAG_OFLAGS = 0x0007 +TAG_BLOCKSIZE = 0x0008 +TAG_BLOCKCOUNT = 0x0009 +TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_NAMELIMIT = 0x000c -TAG_UTAGLIMIT = 0x000d -TAG_UATTRLIMIT = 0x000e +TAG_UTAGLIMIT = 0x000c +TAG_UATTRLIMIT = 0x000d +TAG_STAGLIMIT = 0x000e +TAG_SATTRLIMIT = 0x000f +TAG_MDIRLIMIT = 0x0010 +TAG_MTREELIMIT = 0x0011 TAG_GSTATE = 0x0100 TAG_GRM = 0x0100 TAG_NAME = 0x0200 @@ -142,16 +145,19 @@ def tagrepr(tag, w, size, off=None): 'shrub' if tag & TAG_SHRUB else '', 'magic' if (tag & 0xfff) == TAG_MAGIC else 'version' if (tag & 0xfff) == TAG_VERSION - else 'flags' if (tag & 0xfff) == TAG_FLAGS - else 'cksumtype' if (tag & 0xfff) == TAG_CKSUMTYPE - else 'redundtype' if (tag & 0xfff) == TAG_REDUNDTYPE - else 'blocklimit' if (tag & 0xfff) == TAG_BLOCKLIMIT - else 'disklimit' if (tag & 0xfff) == TAG_DISKLIMIT - else 'mleaflimit' if (tag & 0xfff) == TAG_MLEAFLIMIT + else 'rflags' if (tag & 0xfff) == TAG_RFLAGS + else 'wflags' if (tag & 0xfff) == TAG_WFLAGS + else 'oflags' if (tag & 0xfff) == TAG_OFLAGS + else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE + else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT else 'utaglimit' if (tag & 0xfff) == TAG_UTAGLIMIT else 'uattrlimit' if (tag & 0xfff) == TAG_UATTRLIMIT + else 'staglimit' if (tag & 0xfff) == TAG_STAGLIMIT + else 'sattrlimit' if (tag & 0xfff) == TAG_SATTRLIMIT + else 'mdirlimit' if (tag & 0xfff) == TAG_MDIRLIMIT + else 'mtreelimit' if (tag & 0xfff) == TAG_MTREELIMIT else 'config 0x%02x' % (tag & 0xff), ' w%d' % w if w else '', size) diff --git a/scripts/dbglfs.py b/scripts/dbglfs.py index f3ce5050..7be1b8c1 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -13,16 +13,19 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 -TAG_FLAGS = 0x0005 -TAG_CKSUMTYPE = 0x0006 -TAG_REDUNDTYPE = 0x0007 -TAG_BLOCKLIMIT = 0x0008 -TAG_DISKLIMIT = 0x0009 -TAG_MLEAFLIMIT = 0x000a +TAG_RFLAGS = 0x0005 +TAG_WFLAGS = 0x0006 +TAG_OFLAGS = 0x0007 +TAG_BLOCKSIZE = 0x0008 +TAG_BLOCKCOUNT = 0x0009 +TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_NAMELIMIT = 0x000c -TAG_UTAGLIMIT = 0x000d -TAG_UATTRLIMIT = 0x000e +TAG_UTAGLIMIT = 0x000c +TAG_UATTRLIMIT = 0x000d +TAG_STAGLIMIT = 0x000e +TAG_SATTRLIMIT = 0x000f +TAG_MDIRLIMIT = 0x0010 +TAG_MTREELIMIT = 0x0011 TAG_GSTATE = 0x0100 TAG_GRM = 0x0100 TAG_NAME = 0x0200 @@ -158,16 +161,19 @@ def tagrepr(tag, w, size, off=None): 'shrub' if tag & TAG_SHRUB else '', 'magic' if (tag & 0xfff) == TAG_MAGIC else 'version' if (tag & 0xfff) == TAG_VERSION - else 'flags' if (tag & 0xfff) == TAG_FLAGS - else 'cksumtype' if (tag & 0xfff) == TAG_CKSUMTYPE - else 'redundtype' if (tag & 0xfff) == TAG_REDUNDTYPE - else 'blocklimit' if (tag & 0xfff) == TAG_BLOCKLIMIT - else 'disklimit' if (tag & 0xfff) == TAG_DISKLIMIT - else 'mleaflimit' if (tag & 0xfff) == TAG_MLEAFLIMIT + else 'rflags' if (tag & 0xfff) == TAG_RFLAGS + else 'wflags' if (tag & 0xfff) == TAG_WFLAGS + else 'oflags' if (tag & 0xfff) == TAG_OFLAGS + else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE + else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT else 'utaglimit' if (tag & 0xfff) == TAG_UTAGLIMIT else 'uattrlimit' if (tag & 0xfff) == TAG_UATTRLIMIT + else 'staglimit' if (tag & 0xfff) == TAG_STAGLIMIT + else 'sattrlimit' if (tag & 0xfff) == TAG_SATTRLIMIT + else 'mdirlimit' if (tag & 0xfff) == TAG_MDIRLIMIT + else 'mtreelimit' if (tag & 0xfff) == TAG_MTREELIMIT else 'config 0x%02x' % (tag & 0xff), ' w%d' % w if w else '', size) @@ -987,65 +993,44 @@ class Config: return (None, None) @ft.cached_property - def flags(self): - if TAG_FLAGS in self.config: - _, data = self.config[TAG_FLAGS] - flags, _ = fromleb128(data) - return flags + def rflags(self): + if TAG_RFLAGS in self.config: + _, data = self.config[TAG_RFLAGS] + return data else: return None @ft.cached_property - def cksum_type(self): - if TAG_CKSUMTYPE in self.config: - _, data = self.config[TAG_CKSUMTYPE] - cksum_type, _ = fromleb128(data) - return cksum_type + def wflags(self): + if TAG_WFLAGS in self.config: + _, data = self.config[TAG_WFLAGS] + return data else: return None @ft.cached_property - def redund_type(self): - if TAG_REDUNDTYPE in self.config: - _, data = self.config[TAG_REDUNDTYPE] - redund_type, _ = fromleb128(data) - return redund_type + def oflags(self): + if TAG_OFLAGS in self.config: + _, data = self.config[TAG_OFLAGS] + return data else: return None @ft.cached_property - def block_limit(self): - if TAG_BLOCKLIMIT in self.config: - _, data = self.config[TAG_BLOCKLIMIT] - block_limit, _ = fromleb128(data) - return block_limit + def block_size(self): + if TAG_BLOCKSIZE in self.config: + _, data = self.config[TAG_BLOCKSIZE] + block_size, _ = fromleb128(data) + return block_size else: return None @ft.cached_property - def disk_limit(self): - if TAG_DISKLIMIT in self.config: - _, data = self.config[TAG_DISKLIMIT] - disk_limit, _ = fromleb128(data) - return disk_limit - else: - return None - - @ft.cached_property - def mleaf_limit(self): - if TAG_MLEAFLIMIT in self.config: - _, data = self.config[TAG_MLEAFLIMIT] - mleaf_limit, _ = fromleb128(data) - return mleaf_limit - else: - return None - - @ft.cached_property - def size_limit(self): - if TAG_SIZELIMIT in self.config: - _, data = self.config[TAG_SIZELIMIT] - size_limit, _ = fromleb128(data) - return size_limit + def block_count(self): + if TAG_BLOCKCOUNT in self.config: + _, data = self.config[TAG_BLOCKCOUNT] + block_count, _ = fromleb128(data) + return block_count else: return None @@ -1058,6 +1043,15 @@ class Config: else: return None + @ft.cached_property + def size_limit(self): + if TAG_SIZELIMIT in self.config: + _, data = self.config[TAG_SIZELIMIT] + size_limit, _ = fromleb128(data) + return size_limit + else: + return None + @ft.cached_property def utag_limit(self): if TAG_UTAGLIMIT in self.config: @@ -1076,6 +1070,42 @@ class Config: else: return None + @ft.cached_property + def stag_limit(self): + if TAG_STAGLIMIT in self.config: + _, data = self.config[TAG_STAGLIMIT] + stag_limit, _ = fromleb128(data) + return stag_limit + else: + return None + + @ft.cached_property + def sattr_limit(self): + if TAG_SATTRLIMIT in self.config: + _, data = self.config[TAG_SATTRLIMIT] + sattr_limit, _ = fromleb128(data) + return sattr_limit + else: + return None + + @ft.cached_property + def mdir_limit(self): + if TAG_MDIRLIMIT in self.config: + _, data = self.config[TAG_MDIRLIMIT] + mdir_limit, _ = fromleb128(data) + return mdir_limit + else: + return None + + @ft.cached_property + def mtree_limit(self): + if TAG_MTREELIMIT in self.config: + _, data = self.config[TAG_MTREELIMIT] + mtree_limit, _ = fromleb128(data) + return mtree_limit + else: + return None + def repr(self): def crepr(tag, data): if tag == TAG_MAGIC: @@ -1084,18 +1114,19 @@ class Config: for b in map(chr, self.magic)) elif tag == TAG_VERSION: return 'version v%d.%d' % self.version - elif tag == TAG_FLAGS: - return 'flags 0x%x' % self.flags - elif tag == TAG_CKSUMTYPE: - return 'cksumtype %d' % self.cksum_type - elif tag == TAG_REDUNDTYPE: - return 'redundtype %d' % self.redund_type - elif tag == TAG_BLOCKLIMIT: - return 'blocklimit %d' % self.block_limit - elif tag == TAG_DISKLIMIT: - return 'disklimit %d' % self.disk_limit - elif tag == TAG_MLEAFLIMIT: - return 'mleaflimit %d' % self.mleaf_limit + elif tag == TAG_RFLAGS: + return 'rflags 0x%s' % ''.join( + '%02x' % f for f in reversed(self.rflags)) + elif tag == TAG_WFLAGS: + return 'wflags 0x%s' % ''.join( + '%02x' % f for f in reversed(self.wflags)) + elif tag == TAG_OFLAGS: + return 'oflags 0x%s' % ''.join( + '%02x' % f for f in reversed(self.oflags)) + elif tag == TAG_BLOCKSIZE: + return 'blocksize %d' % self.block_size + elif tag == TAG_BLOCKCOUNT: + return 'blockcount %d' % self.block_count elif tag == TAG_SIZELIMIT: return 'sizelimit %d' % self.size_limit elif tag == TAG_NAMELIMIT: @@ -1104,6 +1135,14 @@ class Config: return 'utaglimit %d' % self.utag_limit elif tag == TAG_UATTRLIMIT: return 'uattrlimit %d' % self.uattr_limit + elif tag == TAG_STAGLIMIT: + return 'staglimit %d' % self.stag_limit + elif tag == TAG_SATTRLIMIT: + return 'sattrlimit %d' % self.sattr_limit + elif tag == TAG_MDIRLIMIT: + return 'mdirlimit %d' % self.mdir_limit + elif tag == TAG_MTREELIMIT: + return 'mtreelimit %d' % self.mtree_limit else: return 'config 0x%02x %d' % (tag, len(data)) @@ -1850,7 +1889,7 @@ def main(disk, mroots=None, *, config.version[0] if config.version[0] is not None else '?', config.version[1] if config.version[1] is not None else '?', mroot.addr(), mroot.rev, bweight//mleaf_weight, 1*mleaf_weight, - (config.block_limit or -1)+1, (config.disk_limit or -1)+1)) + (config.block_size or -1)+1, (config.block_count or -1)+1)) # dynamically size the id field w_width = max( diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index 1e1a1331..157eefb7 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -12,16 +12,19 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 -TAG_FLAGS = 0x0005 -TAG_CKSUMTYPE = 0x0006 -TAG_REDUNDTYPE = 0x0007 -TAG_BLOCKLIMIT = 0x0008 -TAG_DISKLIMIT = 0x0009 -TAG_MLEAFLIMIT = 0x000a +TAG_RFLAGS = 0x0005 +TAG_WFLAGS = 0x0006 +TAG_OFLAGS = 0x0007 +TAG_BLOCKSIZE = 0x0008 +TAG_BLOCKCOUNT = 0x0009 +TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_NAMELIMIT = 0x000c -TAG_UTAGLIMIT = 0x000d -TAG_UATTRLIMIT = 0x000e +TAG_UTAGLIMIT = 0x000c +TAG_UATTRLIMIT = 0x000d +TAG_STAGLIMIT = 0x000e +TAG_SATTRLIMIT = 0x000f +TAG_MDIRLIMIT = 0x0010 +TAG_MTREELIMIT = 0x0011 TAG_GSTATE = 0x0100 TAG_GRM = 0x0100 TAG_NAME = 0x0200 @@ -157,16 +160,19 @@ def tagrepr(tag, w, size, off=None): 'shrub' if tag & TAG_SHRUB else '', 'magic' if (tag & 0xfff) == TAG_MAGIC else 'version' if (tag & 0xfff) == TAG_VERSION - else 'flags' if (tag & 0xfff) == TAG_FLAGS - else 'cksumtype' if (tag & 0xfff) == TAG_CKSUMTYPE - else 'redundtype' if (tag & 0xfff) == TAG_REDUNDTYPE - else 'blocklimit' if (tag & 0xfff) == TAG_BLOCKLIMIT - else 'disklimit' if (tag & 0xfff) == TAG_DISKLIMIT - else 'mleaflimit' if (tag & 0xfff) == TAG_MLEAFLIMIT + else 'rflags' if (tag & 0xfff) == TAG_RFLAGS + else 'wflags' if (tag & 0xfff) == TAG_WFLAGS + else 'oflags' if (tag & 0xfff) == TAG_OFLAGS + else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE + else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT else 'utaglimit' if (tag & 0xfff) == TAG_UTAGLIMIT else 'uattrlimit' if (tag & 0xfff) == TAG_UATTRLIMIT + else 'staglimit' if (tag & 0xfff) == TAG_STAGLIMIT + else 'sattrlimit' if (tag & 0xfff) == TAG_SATTRLIMIT + else 'mdirlimit' if (tag & 0xfff) == TAG_MDIRLIMIT + else 'mtreelimit' if (tag & 0xfff) == TAG_MTREELIMIT else 'config 0x%02x' % (tag & 0xff), ' w%d' % w if w else '', size) diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index 098afbc9..e3dbd26f 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -21,16 +21,19 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 -TAG_FLAGS = 0x0005 -TAG_CKSUMTYPE = 0x0006 -TAG_REDUNDTYPE = 0x0007 -TAG_BLOCKLIMIT = 0x0008 -TAG_DISKLIMIT = 0x0009 -TAG_MLEAFLIMIT = 0x000a +TAG_RFLAGS = 0x0005 +TAG_WFLAGS = 0x0006 +TAG_OFLAGS = 0x0007 +TAG_BLOCKSIZE = 0x0008 +TAG_BLOCKCOUNT = 0x0009 +TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_NAMELIMIT = 0x000c -TAG_UTAGLIMIT = 0x000d -TAG_UATTRLIMIT = 0x000e +TAG_UTAGLIMIT = 0x000c +TAG_UATTRLIMIT = 0x000d +TAG_STAGLIMIT = 0x000e +TAG_SATTRLIMIT = 0x000f +TAG_MDIRLIMIT = 0x0010 +TAG_MTREELIMIT = 0x0011 TAG_GSTATE = 0x0100 TAG_GRM = 0x0100 TAG_NAME = 0x0200 @@ -144,16 +147,19 @@ def tagrepr(tag, w, size, off=None): 'shrub' if tag & TAG_SHRUB else '', 'magic' if (tag & 0xfff) == TAG_MAGIC else 'version' if (tag & 0xfff) == TAG_VERSION - else 'flags' if (tag & 0xfff) == TAG_FLAGS - else 'cksumtype' if (tag & 0xfff) == TAG_CKSUMTYPE - else 'redundtype' if (tag & 0xfff) == TAG_REDUNDTYPE - else 'blocklimit' if (tag & 0xfff) == TAG_BLOCKLIMIT - else 'disklimit' if (tag & 0xfff) == TAG_DISKLIMIT - else 'mleaflimit' if (tag & 0xfff) == TAG_MLEAFLIMIT + else 'rflags' if (tag & 0xfff) == TAG_RFLAGS + else 'wflags' if (tag & 0xfff) == TAG_WFLAGS + else 'oflags' if (tag & 0xfff) == TAG_OFLAGS + else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE + else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT else 'utaglimit' if (tag & 0xfff) == TAG_UTAGLIMIT else 'uattrlimit' if (tag & 0xfff) == TAG_UATTRLIMIT + else 'staglimit' if (tag & 0xfff) == TAG_STAGLIMIT + else 'sattrlimit' if (tag & 0xfff) == TAG_SATTRLIMIT + else 'mdirlimit' if (tag & 0xfff) == TAG_MDIRLIMIT + else 'mtreelimit' if (tag & 0xfff) == TAG_MTREELIMIT else 'config 0x%02x' % (tag & 0xff), ' w%d' % w if w else '', size)