class DNode(Struct): __ENDIAN__ = 'little' node_type = uint8(enum=constants.ObjectType) indirect_blockshift = uint8() indirect_levels = uint8() num_blockptrs = uint8() bonustype = uint8(enum=constants.ObjectType) checksum_type = uint8(enum=constants.Checksum) compression_type = uint8(enum=constants.Compression) _dnode_flags = uint8() # TODO: dnode flag bitfields used_bytes = BitField(_dnode_flags, 1, 0) userused = BitField(_dnode_flags, 1, 1) spill_blkptr = BitField(_dnode_flags, 1, 3) data_sectors = uint16() bonuslen = uint16() _pad = padding(length=4) max_block_id = uint64() used = uint64() _pad2 = padding(length=4 * 8) blkptr = array(Blockptr(), length=num_blockptrs) def bonus_length(self, o=None): if self.bonuslen != 0 and self.node_type != constants.ObjectType.NONE: return self.bonuslen elif self.node_type == constants.ObjectType.NONE: return 320 else: return self.bonuslen bonus = bytestring(length=bonus_length) # TODO: finish _final_pad = padding(length=64)
class MicroZAPHeader(Struct): __ENDIAN__ = 'little' block_type = uint64(enum=ZapType) salt = uint64() flags = uint64() _pad = padding(length=5 * 8)
class Blockptr(Struct): __ENDIAN__ = 'little' dvas = array(dva(), length=3) _prop = uint64() logical_size = BitField(_prop, 16, 0) physical_size = BitField(_prop, 16, 16) compression = BitField(_prop, 6, 32, enum=constants.Compression) encryption = BitField(_prop, 1, 38) embedded = BitField(_prop, 1, 39) checksum_type = BitField(_prop, 8, 40, enum=constants.Checksum) object_type = BitField(_prop, 8, 48, enum=constants.ObjectType) level = BitField(_prop, 5, 56) dedup = BitField(_prop, 1, 62) endian = BitField(_prop, 1, 63) pad = padding(length=16) phys_birth = uint64() birth = uint64() fill = uint64() checksum = array(uint64(), 4) def to_embedded(self): raw_blkptr = self.pack() return EmbeddedBlockptr(raw_blkptr)
class SystemAttributeMagic(pyndata.Struct): magic = pyndata.bytestring(length=4) layout = pyndata.uint8() unknown1 = pyndata.uint8() unknown2 = pyndata.padding(length=2) unknown3 = pyndata.bytestring( length=lambda s, x=None: 8 if s.unknown1 == 8 else 0)
class ObjsetV15(Struct): __ENDIAN__ = 'little' meta_dnode = DNode() zil_header = ZILHeader() os_type = uint64(enum=constants.ObjectSetType) os_flags = uint64() # TODO: flag values _pad = padding(length=112) userused = DNode() groupused = DNode()
class DSLDir(Struct): __ENDIAN__ = 'little' creation_time = uint64() head_dataset = uint64() parent = uint64() clone_parent = uint64() child_dir_zap = uint64() used_bytes = uint64() compressed_bytes = uint64() uncompressed_bytes = uint64() quota = uint64() props_zap = uint64() _pad = padding(length=21 * 8)
class DSLDataset(Struct): __ENDIAN__ = 'little' dir = uint64() prev_snapshot = uint64() prev_snapshot_txg = uint64() next_snapshot = uint64() snapnames_zap = uint64() num_children = uint64() creation_time = uint64() creation_txg = uint64() deadlist = uint64() used_bytes = uint64() compressed_bytes = uint64() uncompressed_bytes = uint64() unique_bytes = uint64() fsid_guid = uint64() guid = uint64() flags = uint64() bp = Blockptr() _pad = padding(length=8 * 8)
class padded(pyndata.Struct): f = pyndata.uint8(default=0xff) pad = pyndata.padding(3)
class GangBlock(Struct): MAGIC = 0x210da7ab10c7a11 blocks = array(Blockptr(), length=3) _pad = padding(length=88) magic = uint64() checksum = array(uint64(), 4)
class ZILHeader(Struct): claim_txg = uint64() replay_seq = uint64() log = Blockptr() claim_seq = uint64() _pad = padding(length=5 * 8)
class ZNodeACL(pyndata.Struct): external_object = pyndata.uint64() count = pyndata.uint32() version = pyndata.uint16() _padding = pyndata.padding(length=2) aces = pyndata.array(ZNodeACE, length=count)