diff --git a/lfs.c b/lfs.c index cdc5767b..e6025d1d 100644 --- a/lfs.c +++ b/lfs.c @@ -586,18 +586,13 @@ enum lfsr_tag { LFSR_TAG_CONFIG = 0x0000, LFSR_TAG_MAGIC = 0x0003, LFSR_TAG_VERSION = 0x0004, + LFSR_TAG_OCOMPATFLAGS = 0x0005, LFSR_TAG_RCOMPATFLAGS = 0x0006, LFSR_TAG_WCOMPATFLAGS = 0x0007, LFSR_TAG_BLOCKSIZE = 0x0008, LFSR_TAG_BLOCKCOUNT = 0x0009, LFSR_TAG_NAMELIMIT = 0x000a, LFSR_TAG_SIZELIMIT = 0x000b, - 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_GDELTA = 0x0100, @@ -7912,171 +7907,18 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) { lfs->size_limit = size_limit; - // check the utag limit - err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_UTAGLIMIT, - NULL, &data); + // check for unknown configs + lfsr_tag_t tag; + err = lfsr_mdir_lookupnext(lfs, mroot, -1, LFSR_TAG_SIZELIMIT+1, + &tag, NULL); if (err && err != LFS_ERR_NOENT) { return err; } - if (err != LFS_ERR_NOENT) { - uint32_t utag_limit; - err = lfsr_data_readleb128(lfs, &data, (int32_t*)&utag_limit); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - utag_limit = -1; - } - - // only 7-bit utags are supported - if (utag_limit != 0x7f) { - LFS_ERROR("Incompatible utag limit (%"PRId32" != %"PRId32")", - utag_limit, - 0x7f); - return LFS_ERR_INVAL; - } - } - - // read the uattr limit - err = lfsr_mdir_lookup(lfs, mroot, -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, mroot, -1, LFSR_TAG_STAGLIMIT, - NULL, &data); - if (err && err != LFS_ERR_NOENT) { - return err; - } - - if (err != LFS_ERR_NOENT) { - uint32_t stag_limit; - err = lfsr_data_readleb128(lfs, &data, (int32_t*)&stag_limit); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - if (err == LFS_ERR_CORRUPT) { - stag_limit = -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, mroot, -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, mroot, -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->mbits = lfs_nlog2(mdir_limit+1); - - // read the mtree limit - err = lfsr_mdir_lookup(lfs, mroot, -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); + if (err != LFS_ERR_NOENT + && lfsr_tag_suptype(tag) == LFSR_TAG_CONFIG) { + LFS_ERROR("Unknown config 0x%04"PRIx16, + tag); return LFS_ERR_INVAL; } @@ -8234,12 +8076,6 @@ static int lfsr_formatinited(lfs_t *lfs) { 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_mweight(lfs)-1)), - LFSR_ATTR(-1, MTREELIMIT, 0, LEB128(lfs->size_limit)), LFSR_ATTR(0, BOOKMARK, +1, LEB128(0)))); if (err) { return err; diff --git a/scripts/dbgbmap.py b/scripts/dbgbmap.py index de2611fb..8f464633 100755 --- a/scripts/dbgbmap.py +++ b/scripts/dbgbmap.py @@ -14,18 +14,13 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 +TAG_OCOMPATFLAGS = 0x0005 TAG_RCOMPATFLAGS = 0x0006 TAG_WCOMPATFLAGS = 0x0007 TAG_BLOCKSIZE = 0x0008 TAG_BLOCKCOUNT = 0x0009 TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_UTAGLIMIT = 0x000c -TAG_UATTRLIMIT = 0x000d -TAG_STAGLIMIT = 0x000e -TAG_SATTRLIMIT = 0x000f -TAG_MDIRLIMIT = 0x0010 -TAG_MTREELIMIT = 0x0011 TAG_GDELTA = 0x0100 TAG_GRMDELTA = 0x0100 TAG_NAME = 0x0200 diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index 24bbbd6a..ffb4875d 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -12,18 +12,13 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 +TAG_OCOMPATFLAGS = 0x0005 TAG_RCOMPATFLAGS = 0x0006 TAG_WCOMPATFLAGS = 0x0007 TAG_BLOCKSIZE = 0x0008 TAG_BLOCKCOUNT = 0x0009 TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_UTAGLIMIT = 0x000c -TAG_UATTRLIMIT = 0x000d -TAG_STAGLIMIT = 0x000e -TAG_SATTRLIMIT = 0x000f -TAG_MDIRLIMIT = 0x0010 -TAG_MTREELIMIT = 0x0011 TAG_GDELTA = 0x0100 TAG_GRMDELTA = 0x0100 TAG_NAME = 0x0200 @@ -168,18 +163,13 @@ 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 'ocompatflags' if (tag & 0xfff) == TAG_OCOMPATFLAGS else 'rcompatflags' if (tag & 0xfff) == TAG_RCOMPATFLAGS else 'wcompatflags' if (tag & 0xfff) == TAG_WCOMPATFLAGS 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 b09e4909..b064c002 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -13,18 +13,13 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 +TAG_OCOMPATFLAGS = 0x0005 TAG_RCOMPATFLAGS = 0x0006 TAG_WCOMPATFLAGS = 0x0007 TAG_BLOCKSIZE = 0x0008 TAG_BLOCKCOUNT = 0x0009 TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_UTAGLIMIT = 0x000c -TAG_UATTRLIMIT = 0x000d -TAG_STAGLIMIT = 0x000e -TAG_SATTRLIMIT = 0x000f -TAG_MDIRLIMIT = 0x0010 -TAG_MTREELIMIT = 0x0011 TAG_GDELTA = 0x0100 TAG_GRMDELTA = 0x0100 TAG_NAME = 0x0200 @@ -197,18 +192,13 @@ 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 'ocompatflags' if (tag & 0xfff) == TAG_OCOMPATFLAGS else 'rcompatflags' if (tag & 0xfff) == TAG_RCOMPATFLAGS else 'wcompatflags' if (tag & 0xfff) == TAG_WCOMPATFLAGS 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) @@ -1033,6 +1023,14 @@ class Config: else: return (None, None) + @ft.cached_property + def ocompatflags(self): + if TAG_OCOMPATFLAGS in self.config: + _, data = self.config[TAG_OCOMPATFLAGS] + return data + else: + return None + @ft.cached_property def rcompatflags(self): if TAG_RCOMPATFLAGS in self.config: @@ -1085,60 +1083,6 @@ class Config: else: return None - @ft.cached_property - def utag_limit(self): - if TAG_UTAGLIMIT in self.config: - _, data = self.config[TAG_UTAGLIMIT] - utag_limit, _ = fromleb128(data) - return utag_limit - else: - return None - - @ft.cached_property - def uattr_limit(self): - if TAG_UATTRLIMIT in self.config: - _, data = self.config[TAG_UATTRLIMIT] - uattr_limit, _ = fromleb128(data) - return uattr_limit - 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: @@ -1147,6 +1091,9 @@ class Config: for b in map(chr, self.magic)) elif tag == TAG_VERSION: return 'version v%d.%d' % self.version + elif tag == TAG_OCOMPATFLAGS: + return 'ocompatflags 0x%s' % ''.join( + '%02x' % f for f in reversed(self.ocompatflags)) elif tag == TAG_RCOMPATFLAGS: return 'rcompatflags 0x%s' % ''.join( '%02x' % f for f in reversed(self.rcompatflags)) @@ -1161,18 +1108,6 @@ class Config: return 'sizelimit %d' % self.size_limit elif tag == TAG_NAMELIMIT: return 'namelimit %d' % self.name_limit - elif tag == TAG_UTAGLIMIT: - 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)) @@ -1976,9 +1911,9 @@ def main(disk, mroots=None, *, # print gdeltas? if args.get('gdelta'): for mbid, mw, mdir, j, d, data in gstate.gdelta[tag]: - print('%s{%s}: %*s %-*s %s%s' % ( + print('%s%12s %*s %-*s %s%s' % ( '\x1b[90m' if color else '', - ','.join('%04x' % block + '{%s}:' % ','.join('%04x' % block for block in it.chain([mdir.block], mdir.redund_blocks)), 2*w_width+1, '%d.%d' % (mbid//mleaf_weight, -1), diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index 0e4fa231..dce964c3 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -12,18 +12,13 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 +TAG_OCOMPATFLAGS = 0x0005 TAG_RCOMPATFLAGS = 0x0006 TAG_WCOMPATFLAGS = 0x0007 TAG_BLOCKSIZE = 0x0008 TAG_BLOCKCOUNT = 0x0009 TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_UTAGLIMIT = 0x000c -TAG_UATTRLIMIT = 0x000d -TAG_STAGLIMIT = 0x000e -TAG_SATTRLIMIT = 0x000f -TAG_MDIRLIMIT = 0x0010 -TAG_MTREELIMIT = 0x0011 TAG_GDELTA = 0x0100 TAG_GRMDELTA = 0x0100 TAG_NAME = 0x0200 @@ -183,18 +178,13 @@ 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 'ocompatflags' if (tag & 0xfff) == TAG_OCOMPATFLAGS else 'rcompatflags' if (tag & 0xfff) == TAG_RCOMPATFLAGS else 'wcompatflags' if (tag & 0xfff) == TAG_WCOMPATFLAGS 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 cca01f77..447d62fd 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -21,18 +21,13 @@ TAG_NULL = 0x0000 TAG_CONFIG = 0x0000 TAG_MAGIC = 0x0003 TAG_VERSION = 0x0004 +TAG_OCOMPATFLAGS = 0x0005 TAG_RCOMPATFLAGS = 0x0006 TAG_WCOMPATFLAGS = 0x0007 TAG_BLOCKSIZE = 0x0008 TAG_BLOCKCOUNT = 0x0009 TAG_NAMELIMIT = 0x000a TAG_SIZELIMIT = 0x000b -TAG_UTAGLIMIT = 0x000c -TAG_UATTRLIMIT = 0x000d -TAG_STAGLIMIT = 0x000e -TAG_SATTRLIMIT = 0x000f -TAG_MDIRLIMIT = 0x0010 -TAG_MTREELIMIT = 0x0011 TAG_GDELTA = 0x0100 TAG_GRMDELTA = 0x0100 TAG_NAME = 0x0200 @@ -170,18 +165,13 @@ 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 'ocompatflags' if (tag & 0xfff) == TAG_OCOMPATFLAGS else 'rcompatflags' if (tag & 0xfff) == TAG_RCOMPATFLAGS else 'wcompatflags' if (tag & 0xfff) == TAG_WCOMPATFLAGS 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)