From 146d586b3b31fba57bb5c1987606c362f345dc10 Mon Sep 17 00:00:00 2001 From: Marian Beermann Date: Wed, 30 Nov 2016 01:43:01 +0100 Subject: [PATCH] check: skip corrupted chunks during manifest rebuild --- borg/archive.py | 7 ++++++- borg/testsuite/archiver.py | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/borg/archive.py b/borg/archive.py index 3c27c45d5..ebfa091f9 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -912,7 +912,12 @@ def valid_archive(obj): archive_keys_serialized = [msgpack.packb(name) for name in ARCHIVE_KEYS] for chunk_id, _ in self.chunks.iteritems(): cdata = self.repository.get(chunk_id) - data = self.key.decrypt(chunk_id, cdata) + try: + data = self.key.decrypt(chunk_id, cdata) + except IntegrityError as exc: + logger.error('Skipping corrupted chunk: %s', exc) + self.error_found = True + continue if not valid_msgpacked_dict(data, archive_keys_serialized): continue if b'cmdline' not in data or b'\xa7version\x01' not in data: diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index b493be534..67b5e581b 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -1446,6 +1446,22 @@ def test_corrupted_manifest(self): self.assert_in('archive2', output) self.cmd('check', self.repository_location, exit_code=0) + def test_manifest_rebuild_corrupted_chunk(self): + archive, repository = self.open_archive('archive1') + with repository: + manifest = repository.get(Manifest.MANIFEST_ID) + corrupted_manifest = manifest + b'corrupted!' + repository.put(Manifest.MANIFEST_ID, corrupted_manifest) + + chunk = repository.get(archive.id) + corrupted_chunk = chunk + b'corrupted!' + repository.put(archive.id, corrupted_chunk) + repository.commit() + self.cmd('check', self.repository_location, exit_code=1) + output = self.cmd('check', '-v', '--repair', self.repository_location, exit_code=0) + self.assert_in('archive2', output) + self.cmd('check', self.repository_location, exit_code=0) + def test_extra_chunks(self): self.cmd('check', self.repository_location, exit_code=0) with Repository(self.repository_location, exclusive=True) as repository: