From 490b293ba1aa4f65b81b0f4cc7582d85167ecbec Mon Sep 17 00:00:00 2001 From: Edwin Eefting Date: Mon, 21 Feb 2022 14:27:22 +0100 Subject: [PATCH] block compare --- tests/test_check.py | 21 +++++++++++++++++++++ zfs_autobackup/BlockHasher.py | 22 +++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/tests/test_check.py b/tests/test_check.py index 84a7036..ead0f05 100644 --- a/tests/test_check.py +++ b/tests/test_check.py @@ -68,6 +68,27 @@ class TestZfsCheck(unittest2.TestCase): (0, "309ffffba2e1977d12f3b7469971f30d28b94bd8"), #whole_whole2_partial ]) + def test_blockhash_compare(self): + + + block_hasher=BlockHasher(count=1) + generator=block_hasher.generate("tests/data/whole_whole2_partial") + self.assertEqual(3,block_hasher.compare("tests/data/whole_whole2_partial", generator)) + + block_hasher=BlockHasher(count=1) + with self.assertRaisesRegexp(Exception, "^Block 1 mismatched!"): + generator=block_hasher.generate("tests/data/whole_whole2_partial") + self.assertEqual(3,block_hasher.compare("tests/data/whole", generator)) + + block_hasher=BlockHasher(count=10) + generator=block_hasher.generate("tests/data/whole_whole2_partial") + self.assertEqual(1,block_hasher.compare("tests/data/whole_whole2_partial", generator)) + + #different order to make sure seek functions + block_hasher=BlockHasher(count=1) + checksums=list(block_hasher.generate("tests/data/whole_whole2_partial")) + checksums.reverse() + self.assertEqual(3,block_hasher.compare("tests/data/whole_whole2_partial", checksums)) def test_volume(self): prepare_zpools() diff --git a/zfs_autobackup/BlockHasher.py b/zfs_autobackup/BlockHasher.py index c0db08f..487cd86 100644 --- a/zfs_autobackup/BlockHasher.py +++ b/zfs_autobackup/BlockHasher.py @@ -38,8 +38,20 @@ class BlockHasher(): if block_nr % self.count != 0: yield (chunk_nr, hash.hexdigest()) - # def compare(fname, generator): - # """reads from generatos and compares blocks""" - # - # with open(fname, "rb") as f: - # for ( count, bs , chunk_nr, hexdigest) in input_generator: \ No newline at end of file + def compare(self, fname, generator): + """reads from generator and compares blocks, raises exception on error""" + + checked=0 + with open(fname, "rb") as f: + for ( chunk_nr, hexdigest ) in generator: + checked=checked+1 + hash = self.hash_class() + f.seek(chunk_nr * self.bs * self.count) + for block_nr in range(0,self.count): + hash.update(f.read(self.bs)) + + if (hash.hexdigest()!=hexdigest): + raise Exception("Block {} mismatched! Hash is {}, but should be {}".format(chunk_nr, hash.hexdigest(), hexdigest)) + + return checked +