#!/usr/bin/env python2 import struct import binascii TYPES = { (0x700, 0x400): 'splice', (0x7ff, 0x401): 'create', (0x7ff, 0x4ff): 'delete', (0x700, 0x000): 'name', (0x7ff, 0x001): 'name reg', (0x7ff, 0x002): 'name dir', (0x7ff, 0x0ff): 'name superblock', (0x700, 0x200): 'struct', (0x7ff, 0x200): 'struct dir', (0x7ff, 0x202): 'struct ctz', (0x7ff, 0x201): 'struct inline', (0x700, 0x300): 'userattr', (0x700, 0x600): 'tail', (0x7ff, 0x600): 'tail soft', (0x7ff, 0x601): 'tail hard', (0x700, 0x700): 'gstate', (0x7ff, 0x7ff): 'gstate move', (0x700, 0x500): 'crc', } def typeof(type): for prefix in range(12): mask = 0x7ff & ~((1 << prefix)-1) if (mask, type & mask) in TYPES: return TYPES[mask, type & mask] + ( ' %0*x' % (prefix/4, type & ((1 << prefix)-1)) if prefix else '') else: return '%02x' % type def main(*blocks): # find most recent block file = None rev = None crc = None versions = [] for block in blocks: try: nfile = open(block, 'rb') ndata = nfile.read(4) ncrc = binascii.crc32(ndata) nrev, = struct.unpack('I', data) except struct.error: break tag ^= ntag off += 4 type = (tag & 0x7ff00000) >> 20 id = (tag & 0x000ffc00) >> 10 size = (tag & 0x000003ff) >> 0 iscrc = (type & 0x700) == 0x500 data = file.read(size if size != 0x3ff else 0) if iscrc: crc = binascii.crc32(data[:4], crc) else: crc = binascii.crc32(data, crc) print '%04x: %08x %-15s %3s %4s %-23s %-8s' % ( off, tag, typeof(type) + (' bad!' if iscrc and ~crc else ''), hex(id)[2:] if id != 0x3ff else '.', size if size != 0x3ff else 'x', ' '.join('%02x' % ord(c) for c in data[:8]), ''.join(c if c >= ' ' and c <= '~' else '.' for c in data[:8])) off += size if size != 0x3ff else 0 if iscrc: crc = 0 tag ^= (type & 1) << 31 return 0 if __name__ == "__main__": import sys sys.exit(main(*sys.argv[1:]))