def __getitem__(self, item): if item < 0: return None if self._levels == 1: return self._root if item == 0 else None indices = self._get_level_indices(item) bpa = self._root for (l, i) in enumerate(indices[:-1]): level_cache = self._cache.get(l) if level_cache is None: level_cache = {} self._cache[l] = level_cache if i in level_cache: next_bpa = level_cache[i] else: b = bpa[i] bpa_data = None for dva in range(3): bpa_data = self._vdev.read_block(b, dva=dva) if bpa_data: break next_bpa = None if bpa_data is not None: next_bpa = BlockPtrArray(bpa_data) else: print("[-] Block tree is broken at", b) level_cache[i] = next_bpa bpa = next_bpa if bpa is None: return None return bpa[indices[-1]]
def _indirect_zap_factory(vdev, bptr, dbsize, nblocks): data,c = vdev.read_block(bptr) if data is None: return None # Data contains first indirection block bpa = BlockPtrArray(data) return _blockptrar_zap_factory(vdev, bpa, dbsize, nblocks)
def __getitem__(self, item): if item < 0: return None if self._levels == 1: return self._root if item == 0 else None indices = self._get_level_indices(item) bpa = self._root _cache = self._cache for (l, i) in enumerate(indices[:-1]): if not i in _cache: _cache[i] = {'b': None, 'n': {}} # generate a graph if not _cache[i]['b'] is None: next_bpa = _cache[i]['b'] else: b = bpa[i] bpa_data = None for dva in range(3): bpa_data, c = self._vdev.read_block(b, dva=dva) if bpa_data and c: break next_bpa = None if bpa_data is not None: next_bpa = BlockPtrArray(bpa_data) else: print("[-] Block tree is broken at", b) _cache[i]['b'] = next_bpa bpa = next_bpa self.printidx(indices, l, str(bpa)) if bpa is None: return None _cache = _cache[i]['n'] b = bpa[indices[-1]] print(("[t-%d] " % (item)) + color.GREEN + str(indices) + color.END + " : " + str(b) + " : " + str(bpa)) return b
def _load_from_bptr(self, bptr): block_data = None for dva in range(3): block_data = self._vdev.read_block(bptr, dva=dva) if block_data: break if block_data is None: return None return BlockPtrArray(block_data)
def zap_factory(vdev, dnode): bptr = dnode.blkptrs[0] dbsize = dnode.datablksize if dnode.levels == 1: nblocks = dnode._nblkptr bpa = BlockPtrArray(dnode._data[BLKPTR_OFFSET:BLKPTR_OFFSET+nblocks*128]) return _blockptrar_zap_factory(vdev, bpa, dbsize, nblocks) elif dnode.levels == 2: return _indirect_zap_factory(vdev, bptr, dbsize, dnode.maxblkid+1) # TODO: Implement Fat Zap with BlockTree raise NotImplementedError("Deeper ZAPs not supported yet")
def _indirect_zap_factory(vdev, bptr, dbsize, nblocks): data = vdev.read_block(bptr) if data is None: return None # Data contains first indirection block bpa = BlockPtrArray(data) data = bytearray() for i in range(nblocks): data += vdev.read_block(bpa[i]) (block_type, ) = struct.unpack("=Q", data[:8]) if block_type == ZBT_MICRO: zap = MicroZap() elif block_type == ZBT_HEADER: zap = FatZap(dbsize) else: print("[-] Data is not a ZAP object: type={}".format(hex(block_type))) return None zap.parse(data) return zap