class BonusDataset: def __init__(self, data): (self.ds_dir_obj, self.ds_prev_snap_obj, self.ds_prev_snap_txg, self.ds_prev_next_obj, self.ds_snapnames_zapobj, self.ds_num_children, self.ds_creation_time, self.ds_creation_txg, self.ds_deadlist_obj, self.ds_used_bytes, self.ds_compressed_bytes, self.ds_uncompressed_bytes, self.ds_unique_bytes, self.ds_fsid_guid, self.ds_guid, self.ds_restoring) = struct.unpack("=16Q", data[:16 * 8]) self.bptr = BlockPtr() self.bptr.parse(data[16 * 8:16 * 8 + 128]) def __str__(self): fields = [ 'ds_dir_obj', 'ds_prev_snap_obj', 'ds_prev_snap_txg', 'ds_prev_next_obj', 'ds_snapnames_zapobj', 'ds_num_children', 'ds_creation_time', 'ds_creation_txg', 'ds_deadlist_obj', 'ds_used_bytes', 'ds_compressed_bytes', 'ds_uncompressed_bytes', 'ds_unique_bytes', 'ds_fsid_guid', 'ds_guid', 'ds_restoring', 'ds_bp' ] fmt = ' '.join([f + '={}' for f in fields]) return fmt.format(self.ds_dir_obj, self.ds_prev_snap_obj, self.ds_prev_snap_txg, self.ds_prev_next_obj, self.ds_snapnames_zapobj, self.ds_num_children, self.ds_creation_time, self.ds_creation_txg, self.ds_deadlist_obj, self.ds_used_bytes, self.ds_compressed_bytes, self.ds_uncompressed_bytes, self.ds_unique_bytes, self.ds_fsid_guid, self.ds_guid, self.ds_restoring, self.bptr)
def __init__(self, data): (self.ds_dir_obj, self.ds_prev_snap_obj, self.ds_prev_snap_txg, self.ds_prev_next_obj, self.ds_snapnames_zapobj, self.ds_num_children, self.ds_creation_time, self.ds_creation_txg, self.ds_deadlist_obj, self.ds_used_bytes, self.ds_compressed_bytes, self.ds_uncompressed_bytes, self.ds_unique_bytes, self.ds_fsid_guid, self.ds_guid, self.ds_restoring) = struct.unpack("=16Q", data[:16*8]) self.bptr = BlockPtr() self.bptr.parse(data[16*8:16*8+128])
def parse(self, data): if len(data) < 512: raise ValueError("Data is too small") # Save data for dumping purposes self._data = data[:] (self._type, self._indblkshift, self._nlevels, self._nblkptr, self._bonustype, self._checksum, self._compress, self._datablkszsec, self._bonuslen, self._maxblkid, self._secphys) = struct.unpack("=7Bx2H4xQQ32x", data[:BLKPTR_OFFSET]) if self._type == 0: return # Object type > 100 (or even 53) is probably due to data error elif self._type > 100: self._invalidate() return self._blkptr = [] if self._nblkptr > 3: # More than three block pointers is a sign of data error self._invalidate() return self._datablksize = self._datablkszsec << 9 ptr = BLKPTR_OFFSET for bn in range(self._nblkptr): b = BlockPtr(data=data[ptr:ptr + 128]) self._blkptr.append(b) ptr += 128 bonus_data = data[ptr:ptr + self._bonuslen] if self._bonuslen and self._bonustype == 12: self._bonus = BonusDirectory(bonus_data) elif self._bonuslen and self._bonustype == 16: self._bonus = BonusDataset(bonus_data) elif self._bonuslen and self._bonustype == 17: self._bonus = BonusZnode(bonus_data) else: self._bonus = bonus_data
def parse(self, data): if len(data) < 512: raise ValueError("Data is too small") # Save data for dumping purposes self._data = data[:] (self._type, self._indblkshift, self._nlevels, self._nblkptr, self._bonustype, self._checksum, self._compress, self._flags, self._datablkszsec, self._bonuslen, self._extra_slots, self._maxblkid, self._used) = struct.unpack("=8B2HB3xQQ32x", data[:BLKPTR_OFFSET]) if self._type == 0: return # Object type > 100 (or even 53) is probably due to data error elif self._type > 100: # on linux 196 is "zap with bonustype dataset" if self._type==196: pass else: self._invalidate() return self._blkptr = [] if self._nblkptr > 3: # More than three block pointers is a sign of data error self._invalidate() return self._used = self._used << 9 if not self._flags & DNODE_FLAG_USED_BYTES else self._used; self._datablksize = self._datablkszsec << 9 ptr = BLKPTR_OFFSET for bn in range(self._nblkptr): b = BlockPtr(data=data[ptr:ptr+128]) self._blkptr.append(b) ptr += 128 bonus_data = data[ptr:ptr+self._bonuslen] if self._bonuslen and self._bonustype == 12: self._bonus = BonusDirectory(bonus_data) elif self._bonuslen and self._bonustype == 16: self._bonus = BonusDataset(bonus_data) print("[+] DSL dataset: %s (DSL directory: %d)" %(str(self._bonus), self._bonus.ds_dir_obj)) elif self._bonuslen and self._bonustype == 17: self._bonus = BonusZnode(bonus_data) elif self._bonuslen and self._bonustype == 0x2c: self._bonus = BonusSysAttr(self._objset, bonus_data) else: self._bonus = bonus_data
def parse(self, data): self._data = bytearray(data) (self._magic, self._version, self._txg, self._guid_sum, self._timestamp) = struct.unpack("=QQQQQ", data[:5 * 8]) self._rootbp = BlockPtr(data=data[40:40 + 128]) self._valid = (self._magic == UBLOCK_MAGIC)