mirror of
https://github.com/littlefs-project/littlefs.git
synced 2025-12-01 12:20:02 +00:00
scripts: Ignore errors with compat-disabled gstate
The gbmap introduces quite a bit of complexity with how it interacts with config: block_count => gbmap weight, and wcompat => gbmap enabled. On one hand this means fewer sources of truth, on the other hand it makes the gbmap logic cross subsystems and a bit messy. To avoid trying to parse a bunch of disabled/garbage gstate, this adds wcompat/rcompat checks to our Gstate class, exposed via __bool__. This also means we actually need to parse wcompat/rcompat/ocompat flags, but that wasn't to difficult (though currently only supports 32-bits). --- I added conditional repr logic for the grm and gbmap, but didn't bother with the gcksum. The gcksum is used too many other places in these scripts to expect a nice rendering when disabled.
This commit is contained in:
@ -80,6 +80,24 @@ TAG_NOTE = 0x3100 ## 0x3100 v-11 ---1 ---- ----
|
|||||||
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
||||||
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
||||||
|
|
||||||
|
RCOMPAT_NONSTANDARD = 0x00000001 # Non-standard filesystem format
|
||||||
|
RCOMPAT_WRONLY = 0x00000002 # Reading is disallowed
|
||||||
|
RCOMPAT_BMOSS = 0x00000010 # Files may use inlined data
|
||||||
|
RCOMPAT_BSPROUT = 0x00000020 # Files may use block pointers
|
||||||
|
RCOMPAT_BSHRUB = 0x00000040 # Files may use inlined btrees
|
||||||
|
RCOMPAT_BTREE = 0x00000080 # Files may use btrees
|
||||||
|
RCOMPAT_MMOSS = 0x00000100 # May use an inlined mdir
|
||||||
|
RCOMPAT_MSPROUT = 0x00000200 # May use an mdir pointer
|
||||||
|
RCOMPAT_MSHRUB = 0x00000400 # May use an inlined mtree
|
||||||
|
RCOMPAT_MTREE = 0x00000800 # May use an mdir btree
|
||||||
|
RCOMPAT_GRM = 0x00001000 # Global-remove in use
|
||||||
|
|
||||||
|
WCOMPAT_NONSTANDARD = 0x00000001 # Non-standard filesystem format
|
||||||
|
WCOMPAT_RDONLY = 0x00000002 # Writing is disallowed
|
||||||
|
WCOMPAT_DIR = 0x00000010 # Directory file types in use
|
||||||
|
WCOMPAT_GCKSUM = 0x00001000 # Global-checksum in use
|
||||||
|
WCOMPAT_GBMAP = 0x00002000 # Global on-disk block-map in use
|
||||||
|
|
||||||
|
|
||||||
# assign chars/colors to specific filesystem objects
|
# assign chars/colors to specific filesystem objects
|
||||||
CHARS = {
|
CHARS = {
|
||||||
@ -2544,6 +2562,13 @@ class Config:
|
|||||||
class Rcompat(Config):
|
class Rcompat(Config):
|
||||||
tag = TAG_RCOMPAT
|
tag = TAG_RCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'rcompat 0x%s' % (
|
return 'rcompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2551,6 +2576,13 @@ class Config:
|
|||||||
class Wcompat(Config):
|
class Wcompat(Config):
|
||||||
tag = TAG_WCOMPAT
|
tag = TAG_WCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'wcompat 0x%s' % (
|
return 'wcompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2558,6 +2590,13 @@ class Config:
|
|||||||
class Ocompat(Config):
|
class Ocompat(Config):
|
||||||
tag = TAG_OCOMPAT
|
tag = TAG_OCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'ocompat 0x%s' % (
|
return 'ocompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2707,6 +2746,9 @@ class Gstate:
|
|||||||
class Gstate:
|
class Gstate:
|
||||||
tag = None
|
tag = None
|
||||||
mask = None
|
mask = None
|
||||||
|
rcompat = None
|
||||||
|
wcompat = None
|
||||||
|
ocompat = None
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
# replace tag with what we find
|
# replace tag with what we find
|
||||||
@ -2723,11 +2765,31 @@ class Gstate:
|
|||||||
fillvalue=0))
|
fillvalue=0))
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
|
# check compat flags while we can access config
|
||||||
|
if self.rcompat is not None:
|
||||||
|
self.rcompat = self.rcompat & (
|
||||||
|
int(config.rcompat) if config.rcompat is not None
|
||||||
|
else 0)
|
||||||
|
if self.wcompat is not None:
|
||||||
|
self.wcompat = self.wcompat & (
|
||||||
|
int(config.wcompat) if config.wcompat is not None
|
||||||
|
else 0)
|
||||||
|
if self.ocompat is not None:
|
||||||
|
self.ocompat = self.ocompat & (
|
||||||
|
int(config.ocompat) if config.ocompat is not None
|
||||||
|
else 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def blocks(self):
|
def blocks(self):
|
||||||
return tuple(it.chain.from_iterable(
|
return tuple(it.chain.from_iterable(
|
||||||
gdelta.blocks for _, gdelta in self.gdeltas))
|
gdelta.blocks for _, gdelta in self.gdeltas))
|
||||||
|
|
||||||
|
# true unless compat flags are missing
|
||||||
|
def __bool__(self):
|
||||||
|
return (self.rcompat != 0
|
||||||
|
and self.wcompat != 0
|
||||||
|
and self.ocompat != 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
return len(self.data)
|
return len(self.data)
|
||||||
@ -2762,6 +2824,7 @@ class Gstate:
|
|||||||
# the global-checksum, cubed
|
# the global-checksum, cubed
|
||||||
class Gcksum(Gstate):
|
class Gcksum(Gstate):
|
||||||
tag = TAG_GCKSUMDELTA
|
tag = TAG_GCKSUMDELTA
|
||||||
|
wcompat = WCOMPAT_GCKSUM
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2776,6 +2839,7 @@ class Gstate:
|
|||||||
# any global-removes
|
# any global-removes
|
||||||
class Grm(Gstate):
|
class Grm(Gstate):
|
||||||
tag = TAG_GRMDELTA
|
tag = TAG_GRMDELTA
|
||||||
|
rcompat = RCOMPAT_GRM
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2794,11 +2858,16 @@ class Gstate:
|
|||||||
self.queue = queue
|
self.queue = queue
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'grm [%s]' % ', '.join(mid.repr() for mid in self.queue)
|
if self:
|
||||||
|
return 'grm [%s]' % ', '.join(
|
||||||
|
mid.repr() for mid in self.queue)
|
||||||
|
else:
|
||||||
|
return 'grm (unused)'
|
||||||
|
|
||||||
# the global block map
|
# the global block map
|
||||||
class Gbmap(Gstate):
|
class Gbmap(Gstate):
|
||||||
tag = TAG_GBMAPDELTA
|
tag = TAG_GBMAPDELTA
|
||||||
|
wcompat = WCOMPAT_GBMAP
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2813,9 +2882,12 @@ class Gstate:
|
|||||||
cksum)
|
cksum)
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
|
if self:
|
||||||
return 'gbmap %s 0x%x %d' % (
|
return 'gbmap %s 0x%x %d' % (
|
||||||
self.btree.addr(),
|
self.btree.addr(),
|
||||||
self.window, self.known)
|
self.window, self.known)
|
||||||
|
else:
|
||||||
|
return 'gbmap (unused)'
|
||||||
|
|
||||||
# keep track of known gstate
|
# keep track of known gstate
|
||||||
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
||||||
@ -3325,7 +3397,7 @@ class Lfs3:
|
|||||||
# traverse any gstate
|
# traverse any gstate
|
||||||
if not mtree_only and gstate:
|
if not mtree_only and gstate:
|
||||||
for gstate_ in self.gstate:
|
for gstate_ in self.gstate:
|
||||||
if getattr(gstate_, 'btree', None) is None:
|
if not gstate_ or getattr(gstate_, 'btree', None) is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for r in gstate_.btree.traverse(
|
for r in gstate_.btree.traverse(
|
||||||
|
|||||||
@ -78,6 +78,24 @@ TAG_NOTE = 0x3100 ## 0x3100 v-11 ---1 ---- ----
|
|||||||
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
||||||
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
||||||
|
|
||||||
|
RCOMPAT_NONSTANDARD = 0x00000001 # Non-standard filesystem format
|
||||||
|
RCOMPAT_WRONLY = 0x00000002 # Reading is disallowed
|
||||||
|
RCOMPAT_BMOSS = 0x00000010 # Files may use inlined data
|
||||||
|
RCOMPAT_BSPROUT = 0x00000020 # Files may use block pointers
|
||||||
|
RCOMPAT_BSHRUB = 0x00000040 # Files may use inlined btrees
|
||||||
|
RCOMPAT_BTREE = 0x00000080 # Files may use btrees
|
||||||
|
RCOMPAT_MMOSS = 0x00000100 # May use an inlined mdir
|
||||||
|
RCOMPAT_MSPROUT = 0x00000200 # May use an mdir pointer
|
||||||
|
RCOMPAT_MSHRUB = 0x00000400 # May use an inlined mtree
|
||||||
|
RCOMPAT_MTREE = 0x00000800 # May use an mdir btree
|
||||||
|
RCOMPAT_GRM = 0x00001000 # Global-remove in use
|
||||||
|
|
||||||
|
WCOMPAT_NONSTANDARD = 0x00000001 # Non-standard filesystem format
|
||||||
|
WCOMPAT_RDONLY = 0x00000002 # Writing is disallowed
|
||||||
|
WCOMPAT_DIR = 0x00000010 # Directory file types in use
|
||||||
|
WCOMPAT_GCKSUM = 0x00001000 # Global-checksum in use
|
||||||
|
WCOMPAT_GBMAP = 0x00002000 # Global on-disk block-map in use
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# assign colors to specific filesystem objects
|
# assign colors to specific filesystem objects
|
||||||
@ -2574,6 +2592,13 @@ class Config:
|
|||||||
class Rcompat(Config):
|
class Rcompat(Config):
|
||||||
tag = TAG_RCOMPAT
|
tag = TAG_RCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'rcompat 0x%s' % (
|
return 'rcompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2581,6 +2606,13 @@ class Config:
|
|||||||
class Wcompat(Config):
|
class Wcompat(Config):
|
||||||
tag = TAG_WCOMPAT
|
tag = TAG_WCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'wcompat 0x%s' % (
|
return 'wcompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2588,6 +2620,13 @@ class Config:
|
|||||||
class Ocompat(Config):
|
class Ocompat(Config):
|
||||||
tag = TAG_OCOMPAT
|
tag = TAG_OCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'ocompat 0x%s' % (
|
return 'ocompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2737,6 +2776,9 @@ class Gstate:
|
|||||||
class Gstate:
|
class Gstate:
|
||||||
tag = None
|
tag = None
|
||||||
mask = None
|
mask = None
|
||||||
|
rcompat = None
|
||||||
|
wcompat = None
|
||||||
|
ocompat = None
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
# replace tag with what we find
|
# replace tag with what we find
|
||||||
@ -2753,11 +2795,31 @@ class Gstate:
|
|||||||
fillvalue=0))
|
fillvalue=0))
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
|
# check compat flags while we can access config
|
||||||
|
if self.rcompat is not None:
|
||||||
|
self.rcompat = self.rcompat & (
|
||||||
|
int(config.rcompat) if config.rcompat is not None
|
||||||
|
else 0)
|
||||||
|
if self.wcompat is not None:
|
||||||
|
self.wcompat = self.wcompat & (
|
||||||
|
int(config.wcompat) if config.wcompat is not None
|
||||||
|
else 0)
|
||||||
|
if self.ocompat is not None:
|
||||||
|
self.ocompat = self.ocompat & (
|
||||||
|
int(config.ocompat) if config.ocompat is not None
|
||||||
|
else 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def blocks(self):
|
def blocks(self):
|
||||||
return tuple(it.chain.from_iterable(
|
return tuple(it.chain.from_iterable(
|
||||||
gdelta.blocks for _, gdelta in self.gdeltas))
|
gdelta.blocks for _, gdelta in self.gdeltas))
|
||||||
|
|
||||||
|
# true unless compat flags are missing
|
||||||
|
def __bool__(self):
|
||||||
|
return (self.rcompat != 0
|
||||||
|
and self.wcompat != 0
|
||||||
|
and self.ocompat != 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
return len(self.data)
|
return len(self.data)
|
||||||
@ -2792,6 +2854,7 @@ class Gstate:
|
|||||||
# the global-checksum, cubed
|
# the global-checksum, cubed
|
||||||
class Gcksum(Gstate):
|
class Gcksum(Gstate):
|
||||||
tag = TAG_GCKSUMDELTA
|
tag = TAG_GCKSUMDELTA
|
||||||
|
wcompat = WCOMPAT_GCKSUM
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2806,6 +2869,7 @@ class Gstate:
|
|||||||
# any global-removes
|
# any global-removes
|
||||||
class Grm(Gstate):
|
class Grm(Gstate):
|
||||||
tag = TAG_GRMDELTA
|
tag = TAG_GRMDELTA
|
||||||
|
rcompat = RCOMPAT_GRM
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2824,11 +2888,16 @@ class Gstate:
|
|||||||
self.queue = queue
|
self.queue = queue
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'grm [%s]' % ', '.join(mid.repr() for mid in self.queue)
|
if self:
|
||||||
|
return 'grm [%s]' % ', '.join(
|
||||||
|
mid.repr() for mid in self.queue)
|
||||||
|
else:
|
||||||
|
return 'grm (unused)'
|
||||||
|
|
||||||
# the global block map
|
# the global block map
|
||||||
class Gbmap(Gstate):
|
class Gbmap(Gstate):
|
||||||
tag = TAG_GBMAPDELTA
|
tag = TAG_GBMAPDELTA
|
||||||
|
wcompat = WCOMPAT_GBMAP
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2843,9 +2912,12 @@ class Gstate:
|
|||||||
cksum)
|
cksum)
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
|
if self:
|
||||||
return 'gbmap %s 0x%x %d' % (
|
return 'gbmap %s 0x%x %d' % (
|
||||||
self.btree.addr(),
|
self.btree.addr(),
|
||||||
self.window, self.known)
|
self.window, self.known)
|
||||||
|
else:
|
||||||
|
return 'gbmap (unused)'
|
||||||
|
|
||||||
# keep track of known gstate
|
# keep track of known gstate
|
||||||
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
||||||
@ -3355,7 +3427,7 @@ class Lfs3:
|
|||||||
# traverse any gstate
|
# traverse any gstate
|
||||||
if not mtree_only and gstate:
|
if not mtree_only and gstate:
|
||||||
for gstate_ in self.gstate:
|
for gstate_ in self.gstate:
|
||||||
if getattr(gstate_, 'btree', None) is None:
|
if not gstate_ or getattr(gstate_, 'btree', None) is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for r in gstate_.btree.traverse(
|
for r in gstate_.btree.traverse(
|
||||||
|
|||||||
@ -70,6 +70,24 @@ TAG_NOTE = 0x3100 ## 0x3100 v-11 ---1 ---- ----
|
|||||||
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
||||||
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
||||||
|
|
||||||
|
RCOMPAT_NONSTANDARD = 0x00000001 # Non-standard filesystem format
|
||||||
|
RCOMPAT_WRONLY = 0x00000002 # Reading is disallowed
|
||||||
|
RCOMPAT_BMOSS = 0x00000010 # Files may use inlined data
|
||||||
|
RCOMPAT_BSPROUT = 0x00000020 # Files may use block pointers
|
||||||
|
RCOMPAT_BSHRUB = 0x00000040 # Files may use inlined btrees
|
||||||
|
RCOMPAT_BTREE = 0x00000080 # Files may use btrees
|
||||||
|
RCOMPAT_MMOSS = 0x00000100 # May use an inlined mdir
|
||||||
|
RCOMPAT_MSPROUT = 0x00000200 # May use an mdir pointer
|
||||||
|
RCOMPAT_MSHRUB = 0x00000400 # May use an inlined mtree
|
||||||
|
RCOMPAT_MTREE = 0x00000800 # May use an mdir btree
|
||||||
|
RCOMPAT_GRM = 0x00001000 # Global-remove in use
|
||||||
|
|
||||||
|
WCOMPAT_NONSTANDARD = 0x00000001 # Non-standard filesystem format
|
||||||
|
WCOMPAT_RDONLY = 0x00000002 # Writing is disallowed
|
||||||
|
WCOMPAT_DIR = 0x00000010 # Directory file types in use
|
||||||
|
WCOMPAT_GCKSUM = 0x00001000 # Global-checksum in use
|
||||||
|
WCOMPAT_GBMAP = 0x00002000 # Global on-disk block-map in use
|
||||||
|
|
||||||
|
|
||||||
# some ways of block geometry representations
|
# some ways of block geometry representations
|
||||||
# 512 -> 512
|
# 512 -> 512
|
||||||
@ -2469,6 +2487,13 @@ class Config:
|
|||||||
class Rcompat(Config):
|
class Rcompat(Config):
|
||||||
tag = TAG_RCOMPAT
|
tag = TAG_RCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'rcompat 0x%s' % (
|
return 'rcompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2476,6 +2501,13 @@ class Config:
|
|||||||
class Wcompat(Config):
|
class Wcompat(Config):
|
||||||
tag = TAG_WCOMPAT
|
tag = TAG_WCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'wcompat 0x%s' % (
|
return 'wcompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2483,6 +2515,13 @@ class Config:
|
|||||||
class Ocompat(Config):
|
class Ocompat(Config):
|
||||||
tag = TAG_OCOMPAT
|
tag = TAG_OCOMPAT
|
||||||
|
|
||||||
|
def __init__(self, mroot, tag, rattr):
|
||||||
|
super().__init__(mroot, tag, rattr)
|
||||||
|
self.flags = fromle32(self.data)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.flags
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'ocompat 0x%s' % (
|
return 'ocompat 0x%s' % (
|
||||||
''.join('%02x' % f for f in reversed(self.data)))
|
''.join('%02x' % f for f in reversed(self.data)))
|
||||||
@ -2632,6 +2671,9 @@ class Gstate:
|
|||||||
class Gstate:
|
class Gstate:
|
||||||
tag = None
|
tag = None
|
||||||
mask = None
|
mask = None
|
||||||
|
rcompat = None
|
||||||
|
wcompat = None
|
||||||
|
ocompat = None
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
# replace tag with what we find
|
# replace tag with what we find
|
||||||
@ -2648,11 +2690,31 @@ class Gstate:
|
|||||||
fillvalue=0))
|
fillvalue=0))
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
|
# check compat flags while we can access config
|
||||||
|
if self.rcompat is not None:
|
||||||
|
self.rcompat = self.rcompat & (
|
||||||
|
int(config.rcompat) if config.rcompat is not None
|
||||||
|
else 0)
|
||||||
|
if self.wcompat is not None:
|
||||||
|
self.wcompat = self.wcompat & (
|
||||||
|
int(config.wcompat) if config.wcompat is not None
|
||||||
|
else 0)
|
||||||
|
if self.ocompat is not None:
|
||||||
|
self.ocompat = self.ocompat & (
|
||||||
|
int(config.ocompat) if config.ocompat is not None
|
||||||
|
else 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def blocks(self):
|
def blocks(self):
|
||||||
return tuple(it.chain.from_iterable(
|
return tuple(it.chain.from_iterable(
|
||||||
gdelta.blocks for _, gdelta in self.gdeltas))
|
gdelta.blocks for _, gdelta in self.gdeltas))
|
||||||
|
|
||||||
|
# true unless compat flags are missing
|
||||||
|
def __bool__(self):
|
||||||
|
return (self.rcompat != 0
|
||||||
|
and self.wcompat != 0
|
||||||
|
and self.ocompat != 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
return len(self.data)
|
return len(self.data)
|
||||||
@ -2687,6 +2749,7 @@ class Gstate:
|
|||||||
# the global-checksum, cubed
|
# the global-checksum, cubed
|
||||||
class Gcksum(Gstate):
|
class Gcksum(Gstate):
|
||||||
tag = TAG_GCKSUMDELTA
|
tag = TAG_GCKSUMDELTA
|
||||||
|
wcompat = WCOMPAT_GCKSUM
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2701,6 +2764,7 @@ class Gstate:
|
|||||||
# any global-removes
|
# any global-removes
|
||||||
class Grm(Gstate):
|
class Grm(Gstate):
|
||||||
tag = TAG_GRMDELTA
|
tag = TAG_GRMDELTA
|
||||||
|
rcompat = RCOMPAT_GRM
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2719,11 +2783,16 @@ class Gstate:
|
|||||||
self.queue = queue
|
self.queue = queue
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
return 'grm [%s]' % ', '.join(mid.repr() for mid in self.queue)
|
if self:
|
||||||
|
return 'grm [%s]' % ', '.join(
|
||||||
|
mid.repr() for mid in self.queue)
|
||||||
|
else:
|
||||||
|
return 'grm (unused)'
|
||||||
|
|
||||||
# the global block map
|
# the global block map
|
||||||
class Gbmap(Gstate):
|
class Gbmap(Gstate):
|
||||||
tag = TAG_GBMAPDELTA
|
tag = TAG_GBMAPDELTA
|
||||||
|
wcompat = WCOMPAT_GBMAP
|
||||||
|
|
||||||
def __init__(self, mtree, config, tag, gdeltas):
|
def __init__(self, mtree, config, tag, gdeltas):
|
||||||
super().__init__(mtree, config, tag, gdeltas)
|
super().__init__(mtree, config, tag, gdeltas)
|
||||||
@ -2738,9 +2807,12 @@ class Gstate:
|
|||||||
cksum)
|
cksum)
|
||||||
|
|
||||||
def repr(self):
|
def repr(self):
|
||||||
|
if self:
|
||||||
return 'gbmap %s 0x%x %d' % (
|
return 'gbmap %s 0x%x %d' % (
|
||||||
self.btree.addr(),
|
self.btree.addr(),
|
||||||
self.window, self.known)
|
self.window, self.known)
|
||||||
|
else:
|
||||||
|
return 'gbmap (unused)'
|
||||||
|
|
||||||
# keep track of known gstate
|
# keep track of known gstate
|
||||||
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
||||||
@ -3250,7 +3322,7 @@ class Lfs3:
|
|||||||
# traverse any gstate
|
# traverse any gstate
|
||||||
if not mtree_only and gstate:
|
if not mtree_only and gstate:
|
||||||
for gstate_ in self.gstate:
|
for gstate_ in self.gstate:
|
||||||
if getattr(gstate_, 'btree', None) is None:
|
if not gstate_ or getattr(gstate_, 'btree', None) is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for r in gstate_.btree.traverse(
|
for r in gstate_.btree.traverse(
|
||||||
@ -4141,6 +4213,9 @@ def dbg_gstate(lfs, *,
|
|||||||
|
|
||||||
# print gstate structures
|
# print gstate structures
|
||||||
def dbg_gstruct(gstate):
|
def dbg_gstruct(gstate):
|
||||||
|
# not in use?
|
||||||
|
if not gstate:
|
||||||
|
return
|
||||||
# no tree?
|
# no tree?
|
||||||
if getattr(gstate, 'btree', None) is None:
|
if getattr(gstate, 'btree', None) is None:
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user