archive check: detect and fix missing all-zero replacement chunks, fixes #2180

# Conflicts:
#	borg/archive.py
This commit is contained in:
Marian Beermann 2017-03-10 18:54:01 +01:00
parent 29613938d5
commit 6e27c8b6cf
1 changed files with 16 additions and 5 deletions

View File

@ -984,6 +984,13 @@ class ArchiveChecker:
Missing file chunks will be replaced with new chunks of the same length containing all zeros. Missing file chunks will be replaced with new chunks of the same length containing all zeros.
If a previously missing file chunk re-appears, the replacement chunk is replaced by the correct one. If a previously missing file chunk re-appears, the replacement chunk is replaced by the correct one.
""" """
def replacement_chunk(size):
data = bytes(size)
chunk_id = self.key.id_hash(data)
cdata = self.key.encrypt(data)
csize = len(cdata)
return chunk_id, size, csize, cdata
offset = 0 offset = 0
chunk_list = [] chunk_list = []
chunks_replaced = False chunks_replaced = False
@ -1000,17 +1007,21 @@ class ArchiveChecker:
'Replacing with all-zero chunk.'.format( 'Replacing with all-zero chunk.'.format(
item[b'path'].decode('utf-8', 'surrogateescape'), offset, offset + size)) item[b'path'].decode('utf-8', 'surrogateescape'), offset, offset + size))
self.error_found = chunks_replaced = True self.error_found = chunks_replaced = True
data = bytes(size) chunk_id, size, csize, cdata = replacement_chunk(size)
chunk_id = self.key.id_hash(data)
cdata = self.key.encrypt(data)
csize = len(cdata)
add_reference(chunk_id, size, csize, cdata) add_reference(chunk_id, size, csize, cdata)
else: else:
logger.info('{}: Previously missing file chunk is still missing (Byte {}-{}). ' logger.info('{}: Previously missing file chunk is still missing (Byte {}-{}). '
'It has a all-zero replacement chunk already.'.format( 'It has a all-zero replacement chunk already.'.format(
item[b'path'].decode('utf-8', 'surrogateescape'), offset, offset + size)) item[b'path'].decode('utf-8', 'surrogateescape'), offset, offset + size))
chunk_id, size, csize = chunk_current chunk_id, size, csize = chunk_current
if chunk_id in self.chunks:
add_reference(chunk_id, size, csize) add_reference(chunk_id, size, csize)
else:
logger.warning('{}: Missing all-zero replacement chunk detected (Byte {}-{}). '
'Generating new replacement chunk.'.format(item.path, offset, offset + size))
self.error_found = chunks_replaced = True
chunk_id, size, csize, cdata = replacement_chunk(size)
add_reference(chunk_id, size, csize, cdata)
else: else:
if chunk_current == chunk_healthy: if chunk_current == chunk_healthy:
# normal case, all fine. # normal case, all fine.