119ea8026Sopenharmony_ci#!/usr/bin/env python3 219ea8026Sopenharmony_ci 319ea8026Sopenharmony_ciimport struct 419ea8026Sopenharmony_ciimport binascii 519ea8026Sopenharmony_ciimport sys 619ea8026Sopenharmony_ciimport itertools as it 719ea8026Sopenharmony_ci 819ea8026Sopenharmony_ciTAG_TYPES = { 919ea8026Sopenharmony_ci 'splice': (0x700, 0x400), 1019ea8026Sopenharmony_ci 'create': (0x7ff, 0x401), 1119ea8026Sopenharmony_ci 'delete': (0x7ff, 0x4ff), 1219ea8026Sopenharmony_ci 'name': (0x700, 0x000), 1319ea8026Sopenharmony_ci 'reg': (0x7ff, 0x001), 1419ea8026Sopenharmony_ci 'dir': (0x7ff, 0x002), 1519ea8026Sopenharmony_ci 'superblock': (0x7ff, 0x0ff), 1619ea8026Sopenharmony_ci 'struct': (0x700, 0x200), 1719ea8026Sopenharmony_ci 'dirstruct': (0x7ff, 0x200), 1819ea8026Sopenharmony_ci 'ctzstruct': (0x7ff, 0x202), 1919ea8026Sopenharmony_ci 'inlinestruct': (0x7ff, 0x201), 2019ea8026Sopenharmony_ci 'userattr': (0x700, 0x300), 2119ea8026Sopenharmony_ci 'tail': (0x700, 0x600), 2219ea8026Sopenharmony_ci 'softtail': (0x7ff, 0x600), 2319ea8026Sopenharmony_ci 'hardtail': (0x7ff, 0x601), 2419ea8026Sopenharmony_ci 'gstate': (0x700, 0x700), 2519ea8026Sopenharmony_ci 'movestate': (0x7ff, 0x7ff), 2619ea8026Sopenharmony_ci 'crc': (0x700, 0x500), 2719ea8026Sopenharmony_ci 'ccrc': (0x780, 0x500), 2819ea8026Sopenharmony_ci 'fcrc': (0x7ff, 0x5ff), 2919ea8026Sopenharmony_ci} 3019ea8026Sopenharmony_ci 3119ea8026Sopenharmony_ciclass Tag: 3219ea8026Sopenharmony_ci def __init__(self, *args): 3319ea8026Sopenharmony_ci if len(args) == 1: 3419ea8026Sopenharmony_ci self.tag = args[0] 3519ea8026Sopenharmony_ci elif len(args) == 3: 3619ea8026Sopenharmony_ci if isinstance(args[0], str): 3719ea8026Sopenharmony_ci type = TAG_TYPES[args[0]][1] 3819ea8026Sopenharmony_ci else: 3919ea8026Sopenharmony_ci type = args[0] 4019ea8026Sopenharmony_ci 4119ea8026Sopenharmony_ci if isinstance(args[1], str): 4219ea8026Sopenharmony_ci id = int(args[1], 0) if args[1] not in 'x.' else 0x3ff 4319ea8026Sopenharmony_ci else: 4419ea8026Sopenharmony_ci id = args[1] 4519ea8026Sopenharmony_ci 4619ea8026Sopenharmony_ci if isinstance(args[2], str): 4719ea8026Sopenharmony_ci size = int(args[2], str) if args[2] not in 'x.' else 0x3ff 4819ea8026Sopenharmony_ci else: 4919ea8026Sopenharmony_ci size = args[2] 5019ea8026Sopenharmony_ci 5119ea8026Sopenharmony_ci self.tag = (type << 20) | (id << 10) | size 5219ea8026Sopenharmony_ci else: 5319ea8026Sopenharmony_ci assert False 5419ea8026Sopenharmony_ci 5519ea8026Sopenharmony_ci @property 5619ea8026Sopenharmony_ci def isvalid(self): 5719ea8026Sopenharmony_ci return not bool(self.tag & 0x80000000) 5819ea8026Sopenharmony_ci 5919ea8026Sopenharmony_ci @property 6019ea8026Sopenharmony_ci def isattr(self): 6119ea8026Sopenharmony_ci return not bool(self.tag & 0x40000000) 6219ea8026Sopenharmony_ci 6319ea8026Sopenharmony_ci @property 6419ea8026Sopenharmony_ci def iscompactable(self): 6519ea8026Sopenharmony_ci return bool(self.tag & 0x20000000) 6619ea8026Sopenharmony_ci 6719ea8026Sopenharmony_ci @property 6819ea8026Sopenharmony_ci def isunique(self): 6919ea8026Sopenharmony_ci return not bool(self.tag & 0x10000000) 7019ea8026Sopenharmony_ci 7119ea8026Sopenharmony_ci @property 7219ea8026Sopenharmony_ci def type(self): 7319ea8026Sopenharmony_ci return (self.tag & 0x7ff00000) >> 20 7419ea8026Sopenharmony_ci 7519ea8026Sopenharmony_ci @property 7619ea8026Sopenharmony_ci def type1(self): 7719ea8026Sopenharmony_ci return (self.tag & 0x70000000) >> 20 7819ea8026Sopenharmony_ci 7919ea8026Sopenharmony_ci @property 8019ea8026Sopenharmony_ci def type3(self): 8119ea8026Sopenharmony_ci return (self.tag & 0x7ff00000) >> 20 8219ea8026Sopenharmony_ci 8319ea8026Sopenharmony_ci @property 8419ea8026Sopenharmony_ci def id(self): 8519ea8026Sopenharmony_ci return (self.tag & 0x000ffc00) >> 10 8619ea8026Sopenharmony_ci 8719ea8026Sopenharmony_ci @property 8819ea8026Sopenharmony_ci def size(self): 8919ea8026Sopenharmony_ci return (self.tag & 0x000003ff) >> 0 9019ea8026Sopenharmony_ci 9119ea8026Sopenharmony_ci @property 9219ea8026Sopenharmony_ci def dsize(self): 9319ea8026Sopenharmony_ci return 4 + (self.size if self.size != 0x3ff else 0) 9419ea8026Sopenharmony_ci 9519ea8026Sopenharmony_ci @property 9619ea8026Sopenharmony_ci def chunk(self): 9719ea8026Sopenharmony_ci return self.type & 0xff 9819ea8026Sopenharmony_ci 9919ea8026Sopenharmony_ci @property 10019ea8026Sopenharmony_ci def schunk(self): 10119ea8026Sopenharmony_ci return struct.unpack('b', struct.pack('B', self.chunk))[0] 10219ea8026Sopenharmony_ci 10319ea8026Sopenharmony_ci def is_(self, type): 10419ea8026Sopenharmony_ci try: 10519ea8026Sopenharmony_ci if ' ' in type: 10619ea8026Sopenharmony_ci type1, type3 = type.split() 10719ea8026Sopenharmony_ci return (self.is_(type1) and 10819ea8026Sopenharmony_ci (self.type & ~TAG_TYPES[type1][0]) == int(type3, 0)) 10919ea8026Sopenharmony_ci 11019ea8026Sopenharmony_ci return self.type == int(type, 0) 11119ea8026Sopenharmony_ci 11219ea8026Sopenharmony_ci except (ValueError, KeyError): 11319ea8026Sopenharmony_ci return (self.type & TAG_TYPES[type][0]) == TAG_TYPES[type][1] 11419ea8026Sopenharmony_ci 11519ea8026Sopenharmony_ci def mkmask(self): 11619ea8026Sopenharmony_ci return Tag( 11719ea8026Sopenharmony_ci 0x700 if self.isunique else 0x7ff, 11819ea8026Sopenharmony_ci 0x3ff if self.isattr else 0, 11919ea8026Sopenharmony_ci 0) 12019ea8026Sopenharmony_ci 12119ea8026Sopenharmony_ci def chid(self, nid): 12219ea8026Sopenharmony_ci ntag = Tag(self.type, nid, self.size) 12319ea8026Sopenharmony_ci if hasattr(self, 'off'): ntag.off = self.off 12419ea8026Sopenharmony_ci if hasattr(self, 'data'): ntag.data = self.data 12519ea8026Sopenharmony_ci if hasattr(self, 'ccrc'): ntag.crc = self.crc 12619ea8026Sopenharmony_ci if hasattr(self, 'erased'): ntag.erased = self.erased 12719ea8026Sopenharmony_ci return ntag 12819ea8026Sopenharmony_ci 12919ea8026Sopenharmony_ci def typerepr(self): 13019ea8026Sopenharmony_ci if (self.is_('ccrc') 13119ea8026Sopenharmony_ci and getattr(self, 'ccrc', 0xffffffff) != 0xffffffff): 13219ea8026Sopenharmony_ci crc_status = ' (bad)' 13319ea8026Sopenharmony_ci elif self.is_('fcrc') and getattr(self, 'erased', False): 13419ea8026Sopenharmony_ci crc_status = ' (era)' 13519ea8026Sopenharmony_ci else: 13619ea8026Sopenharmony_ci crc_status = '' 13719ea8026Sopenharmony_ci 13819ea8026Sopenharmony_ci reverse_types = {v: k for k, v in TAG_TYPES.items()} 13919ea8026Sopenharmony_ci for prefix in range(12): 14019ea8026Sopenharmony_ci mask = 0x7ff & ~((1 << prefix)-1) 14119ea8026Sopenharmony_ci if (mask, self.type & mask) in reverse_types: 14219ea8026Sopenharmony_ci type = reverse_types[mask, self.type & mask] 14319ea8026Sopenharmony_ci if prefix > 0: 14419ea8026Sopenharmony_ci return '%s %#x%s' % ( 14519ea8026Sopenharmony_ci type, self.type & ((1 << prefix)-1), crc_status) 14619ea8026Sopenharmony_ci else: 14719ea8026Sopenharmony_ci return '%s%s' % (type, crc_status) 14819ea8026Sopenharmony_ci else: 14919ea8026Sopenharmony_ci return '%02x%s' % (self.type, crc_status) 15019ea8026Sopenharmony_ci 15119ea8026Sopenharmony_ci def idrepr(self): 15219ea8026Sopenharmony_ci return repr(self.id) if self.id != 0x3ff else '.' 15319ea8026Sopenharmony_ci 15419ea8026Sopenharmony_ci def sizerepr(self): 15519ea8026Sopenharmony_ci return repr(self.size) if self.size != 0x3ff else 'x' 15619ea8026Sopenharmony_ci 15719ea8026Sopenharmony_ci def __repr__(self): 15819ea8026Sopenharmony_ci return 'Tag(%r, %d, %d)' % (self.typerepr(), self.id, self.size) 15919ea8026Sopenharmony_ci 16019ea8026Sopenharmony_ci def __lt__(self, other): 16119ea8026Sopenharmony_ci return (self.id, self.type) < (other.id, other.type) 16219ea8026Sopenharmony_ci 16319ea8026Sopenharmony_ci def __bool__(self): 16419ea8026Sopenharmony_ci return self.isvalid 16519ea8026Sopenharmony_ci 16619ea8026Sopenharmony_ci def __int__(self): 16719ea8026Sopenharmony_ci return self.tag 16819ea8026Sopenharmony_ci 16919ea8026Sopenharmony_ci def __index__(self): 17019ea8026Sopenharmony_ci return self.tag 17119ea8026Sopenharmony_ci 17219ea8026Sopenharmony_ciclass MetadataPair: 17319ea8026Sopenharmony_ci def __init__(self, blocks): 17419ea8026Sopenharmony_ci if len(blocks) > 1: 17519ea8026Sopenharmony_ci self.pair = [MetadataPair([block]) for block in blocks] 17619ea8026Sopenharmony_ci self.pair = sorted(self.pair, reverse=True) 17719ea8026Sopenharmony_ci 17819ea8026Sopenharmony_ci self.data = self.pair[0].data 17919ea8026Sopenharmony_ci self.rev = self.pair[0].rev 18019ea8026Sopenharmony_ci self.tags = self.pair[0].tags 18119ea8026Sopenharmony_ci self.ids = self.pair[0].ids 18219ea8026Sopenharmony_ci self.log = self.pair[0].log 18319ea8026Sopenharmony_ci self.all_ = self.pair[0].all_ 18419ea8026Sopenharmony_ci return 18519ea8026Sopenharmony_ci 18619ea8026Sopenharmony_ci self.pair = [self] 18719ea8026Sopenharmony_ci self.data = blocks[0] 18819ea8026Sopenharmony_ci block = self.data 18919ea8026Sopenharmony_ci 19019ea8026Sopenharmony_ci self.rev, = struct.unpack('<I', block[0:4]) 19119ea8026Sopenharmony_ci crc = binascii.crc32(block[0:4]) 19219ea8026Sopenharmony_ci fcrctag = None 19319ea8026Sopenharmony_ci fcrcdata = None 19419ea8026Sopenharmony_ci 19519ea8026Sopenharmony_ci # parse tags 19619ea8026Sopenharmony_ci corrupt = False 19719ea8026Sopenharmony_ci tag = Tag(0xffffffff) 19819ea8026Sopenharmony_ci off = 4 19919ea8026Sopenharmony_ci self.log = [] 20019ea8026Sopenharmony_ci self.all_ = [] 20119ea8026Sopenharmony_ci while len(block) - off >= 4: 20219ea8026Sopenharmony_ci ntag, = struct.unpack('>I', block[off:off+4]) 20319ea8026Sopenharmony_ci 20419ea8026Sopenharmony_ci tag = Tag((int(tag) ^ ntag) & 0x7fffffff) 20519ea8026Sopenharmony_ci tag.off = off + 4 20619ea8026Sopenharmony_ci tag.data = block[off+4:off+tag.dsize] 20719ea8026Sopenharmony_ci if tag.is_('ccrc'): 20819ea8026Sopenharmony_ci crc = binascii.crc32(block[off:off+2*4], crc) 20919ea8026Sopenharmony_ci else: 21019ea8026Sopenharmony_ci crc = binascii.crc32(block[off:off+tag.dsize], crc) 21119ea8026Sopenharmony_ci tag.crc = crc 21219ea8026Sopenharmony_ci off += tag.dsize 21319ea8026Sopenharmony_ci 21419ea8026Sopenharmony_ci self.all_.append(tag) 21519ea8026Sopenharmony_ci 21619ea8026Sopenharmony_ci if tag.is_('fcrc') and len(tag.data) == 8: 21719ea8026Sopenharmony_ci fcrctag = tag 21819ea8026Sopenharmony_ci fcrcdata = struct.unpack('<II', tag.data) 21919ea8026Sopenharmony_ci elif tag.is_('ccrc'): 22019ea8026Sopenharmony_ci # is valid commit? 22119ea8026Sopenharmony_ci if crc != 0xffffffff: 22219ea8026Sopenharmony_ci corrupt = True 22319ea8026Sopenharmony_ci if not corrupt: 22419ea8026Sopenharmony_ci self.log = self.all_.copy() 22519ea8026Sopenharmony_ci # end of commit? 22619ea8026Sopenharmony_ci if fcrcdata: 22719ea8026Sopenharmony_ci fcrcsize, fcrc = fcrcdata 22819ea8026Sopenharmony_ci fcrc_ = 0xffffffff ^ binascii.crc32( 22919ea8026Sopenharmony_ci block[off:off+fcrcsize]) 23019ea8026Sopenharmony_ci if fcrc_ == fcrc: 23119ea8026Sopenharmony_ci fcrctag.erased = True 23219ea8026Sopenharmony_ci corrupt = True 23319ea8026Sopenharmony_ci 23419ea8026Sopenharmony_ci # reset tag parsing 23519ea8026Sopenharmony_ci crc = 0 23619ea8026Sopenharmony_ci tag = Tag(int(tag) ^ ((tag.type & 1) << 31)) 23719ea8026Sopenharmony_ci fcrctag = None 23819ea8026Sopenharmony_ci fcrcdata = None 23919ea8026Sopenharmony_ci 24019ea8026Sopenharmony_ci # find active ids 24119ea8026Sopenharmony_ci self.ids = list(it.takewhile( 24219ea8026Sopenharmony_ci lambda id: Tag('name', id, 0) in self, 24319ea8026Sopenharmony_ci it.count())) 24419ea8026Sopenharmony_ci 24519ea8026Sopenharmony_ci # find most recent tags 24619ea8026Sopenharmony_ci self.tags = [] 24719ea8026Sopenharmony_ci for tag in self.log: 24819ea8026Sopenharmony_ci if tag.is_('crc') or tag.is_('splice'): 24919ea8026Sopenharmony_ci continue 25019ea8026Sopenharmony_ci elif tag.id == 0x3ff: 25119ea8026Sopenharmony_ci if tag in self and self[tag] is tag: 25219ea8026Sopenharmony_ci self.tags.append(tag) 25319ea8026Sopenharmony_ci else: 25419ea8026Sopenharmony_ci # id could have change, I know this is messy and slow 25519ea8026Sopenharmony_ci # but it works 25619ea8026Sopenharmony_ci for id in self.ids: 25719ea8026Sopenharmony_ci ntag = tag.chid(id) 25819ea8026Sopenharmony_ci if ntag in self and self[ntag] is tag: 25919ea8026Sopenharmony_ci self.tags.append(ntag) 26019ea8026Sopenharmony_ci 26119ea8026Sopenharmony_ci self.tags = sorted(self.tags) 26219ea8026Sopenharmony_ci 26319ea8026Sopenharmony_ci def __bool__(self): 26419ea8026Sopenharmony_ci return bool(self.log) 26519ea8026Sopenharmony_ci 26619ea8026Sopenharmony_ci def __lt__(self, other): 26719ea8026Sopenharmony_ci # corrupt blocks don't count 26819ea8026Sopenharmony_ci if not self or not other: 26919ea8026Sopenharmony_ci return bool(other) 27019ea8026Sopenharmony_ci 27119ea8026Sopenharmony_ci # use sequence arithmetic to avoid overflow 27219ea8026Sopenharmony_ci return not ((other.rev - self.rev) & 0x80000000) 27319ea8026Sopenharmony_ci 27419ea8026Sopenharmony_ci def __contains__(self, args): 27519ea8026Sopenharmony_ci try: 27619ea8026Sopenharmony_ci self[args] 27719ea8026Sopenharmony_ci return True 27819ea8026Sopenharmony_ci except KeyError: 27919ea8026Sopenharmony_ci return False 28019ea8026Sopenharmony_ci 28119ea8026Sopenharmony_ci def __getitem__(self, args): 28219ea8026Sopenharmony_ci if isinstance(args, tuple): 28319ea8026Sopenharmony_ci gmask, gtag = args 28419ea8026Sopenharmony_ci else: 28519ea8026Sopenharmony_ci gmask, gtag = args.mkmask(), args 28619ea8026Sopenharmony_ci 28719ea8026Sopenharmony_ci gdiff = 0 28819ea8026Sopenharmony_ci for tag in reversed(self.log): 28919ea8026Sopenharmony_ci if (gmask.id != 0 and tag.is_('splice') and 29019ea8026Sopenharmony_ci tag.id <= gtag.id - gdiff): 29119ea8026Sopenharmony_ci if tag.is_('create') and tag.id == gtag.id - gdiff: 29219ea8026Sopenharmony_ci # creation point 29319ea8026Sopenharmony_ci break 29419ea8026Sopenharmony_ci 29519ea8026Sopenharmony_ci gdiff += tag.schunk 29619ea8026Sopenharmony_ci 29719ea8026Sopenharmony_ci if ((int(gmask) & int(tag)) == 29819ea8026Sopenharmony_ci (int(gmask) & int(gtag.chid(gtag.id - gdiff)))): 29919ea8026Sopenharmony_ci if tag.size == 0x3ff: 30019ea8026Sopenharmony_ci # deleted 30119ea8026Sopenharmony_ci break 30219ea8026Sopenharmony_ci 30319ea8026Sopenharmony_ci return tag 30419ea8026Sopenharmony_ci 30519ea8026Sopenharmony_ci raise KeyError(gmask, gtag) 30619ea8026Sopenharmony_ci 30719ea8026Sopenharmony_ci def _dump_tags(self, tags, f=sys.stdout, truncate=True): 30819ea8026Sopenharmony_ci f.write("%-8s %-8s %-13s %4s %4s" % ( 30919ea8026Sopenharmony_ci 'off', 'tag', 'type', 'id', 'len')) 31019ea8026Sopenharmony_ci if truncate: 31119ea8026Sopenharmony_ci f.write(' data (truncated)') 31219ea8026Sopenharmony_ci f.write('\n') 31319ea8026Sopenharmony_ci 31419ea8026Sopenharmony_ci for tag in tags: 31519ea8026Sopenharmony_ci f.write("%08x: %08x %-14s %3s %4s" % ( 31619ea8026Sopenharmony_ci tag.off, tag, 31719ea8026Sopenharmony_ci tag.typerepr(), tag.idrepr(), tag.sizerepr())) 31819ea8026Sopenharmony_ci if truncate: 31919ea8026Sopenharmony_ci f.write(" %-23s %-8s\n" % ( 32019ea8026Sopenharmony_ci ' '.join('%02x' % c for c in tag.data[:8]), 32119ea8026Sopenharmony_ci ''.join(c if c >= ' ' and c <= '~' else '.' 32219ea8026Sopenharmony_ci for c in map(chr, tag.data[:8])))) 32319ea8026Sopenharmony_ci else: 32419ea8026Sopenharmony_ci f.write("\n") 32519ea8026Sopenharmony_ci for i in range(0, len(tag.data), 16): 32619ea8026Sopenharmony_ci f.write(" %08x: %-47s %-16s\n" % ( 32719ea8026Sopenharmony_ci tag.off+i, 32819ea8026Sopenharmony_ci ' '.join('%02x' % c for c in tag.data[i:i+16]), 32919ea8026Sopenharmony_ci ''.join(c if c >= ' ' and c <= '~' else '.' 33019ea8026Sopenharmony_ci for c in map(chr, tag.data[i:i+16])))) 33119ea8026Sopenharmony_ci 33219ea8026Sopenharmony_ci def dump_tags(self, f=sys.stdout, truncate=True): 33319ea8026Sopenharmony_ci self._dump_tags(self.tags, f=f, truncate=truncate) 33419ea8026Sopenharmony_ci 33519ea8026Sopenharmony_ci def dump_log(self, f=sys.stdout, truncate=True): 33619ea8026Sopenharmony_ci self._dump_tags(self.log, f=f, truncate=truncate) 33719ea8026Sopenharmony_ci 33819ea8026Sopenharmony_ci def dump_all(self, f=sys.stdout, truncate=True): 33919ea8026Sopenharmony_ci self._dump_tags(self.all_, f=f, truncate=truncate) 34019ea8026Sopenharmony_ci 34119ea8026Sopenharmony_cidef main(args): 34219ea8026Sopenharmony_ci blocks = [] 34319ea8026Sopenharmony_ci with open(args.disk, 'rb') as f: 34419ea8026Sopenharmony_ci for block in [args.block1, args.block2]: 34519ea8026Sopenharmony_ci if block is None: 34619ea8026Sopenharmony_ci continue 34719ea8026Sopenharmony_ci f.seek(block * args.block_size) 34819ea8026Sopenharmony_ci blocks.append(f.read(args.block_size) 34919ea8026Sopenharmony_ci .ljust(args.block_size, b'\xff')) 35019ea8026Sopenharmony_ci 35119ea8026Sopenharmony_ci # find most recent pair 35219ea8026Sopenharmony_ci mdir = MetadataPair(blocks) 35319ea8026Sopenharmony_ci 35419ea8026Sopenharmony_ci try: 35519ea8026Sopenharmony_ci mdir.tail = mdir[Tag('tail', 0, 0)] 35619ea8026Sopenharmony_ci if mdir.tail.size != 8 or mdir.tail.data == 8*b'\xff': 35719ea8026Sopenharmony_ci mdir.tail = None 35819ea8026Sopenharmony_ci except KeyError: 35919ea8026Sopenharmony_ci mdir.tail = None 36019ea8026Sopenharmony_ci 36119ea8026Sopenharmony_ci print("mdir {%s} rev %d%s%s%s" % ( 36219ea8026Sopenharmony_ci ', '.join('%#x' % b 36319ea8026Sopenharmony_ci for b in [args.block1, args.block2] 36419ea8026Sopenharmony_ci if b is not None), 36519ea8026Sopenharmony_ci mdir.rev, 36619ea8026Sopenharmony_ci ' (was %s)' % ', '.join('%d' % m.rev for m in mdir.pair[1:]) 36719ea8026Sopenharmony_ci if len(mdir.pair) > 1 else '', 36819ea8026Sopenharmony_ci ' (corrupted!)' if not mdir else '', 36919ea8026Sopenharmony_ci ' -> {%#x, %#x}' % struct.unpack('<II', mdir.tail.data) 37019ea8026Sopenharmony_ci if mdir.tail else '')) 37119ea8026Sopenharmony_ci if args.all: 37219ea8026Sopenharmony_ci mdir.dump_all(truncate=not args.no_truncate) 37319ea8026Sopenharmony_ci elif args.log: 37419ea8026Sopenharmony_ci mdir.dump_log(truncate=not args.no_truncate) 37519ea8026Sopenharmony_ci else: 37619ea8026Sopenharmony_ci mdir.dump_tags(truncate=not args.no_truncate) 37719ea8026Sopenharmony_ci 37819ea8026Sopenharmony_ci return 0 if mdir else 1 37919ea8026Sopenharmony_ci 38019ea8026Sopenharmony_ciif __name__ == "__main__": 38119ea8026Sopenharmony_ci import argparse 38219ea8026Sopenharmony_ci import sys 38319ea8026Sopenharmony_ci parser = argparse.ArgumentParser( 38419ea8026Sopenharmony_ci description="Dump useful info about metadata pairs in littlefs.") 38519ea8026Sopenharmony_ci parser.add_argument('disk', 38619ea8026Sopenharmony_ci help="File representing the block device.") 38719ea8026Sopenharmony_ci parser.add_argument('block_size', type=lambda x: int(x, 0), 38819ea8026Sopenharmony_ci help="Size of a block in bytes.") 38919ea8026Sopenharmony_ci parser.add_argument('block1', type=lambda x: int(x, 0), 39019ea8026Sopenharmony_ci help="First block address for finding the metadata pair.") 39119ea8026Sopenharmony_ci parser.add_argument('block2', nargs='?', type=lambda x: int(x, 0), 39219ea8026Sopenharmony_ci help="Second block address for finding the metadata pair.") 39319ea8026Sopenharmony_ci parser.add_argument('-l', '--log', action='store_true', 39419ea8026Sopenharmony_ci help="Show tags in log.") 39519ea8026Sopenharmony_ci parser.add_argument('-a', '--all', action='store_true', 39619ea8026Sopenharmony_ci help="Show all tags in log, included tags in corrupted commits.") 39719ea8026Sopenharmony_ci parser.add_argument('-T', '--no-truncate', action='store_true', 39819ea8026Sopenharmony_ci help="Don't truncate large amounts of data.") 39919ea8026Sopenharmony_ci sys.exit(main(parser.parse_args())) 400