mirror of https://github.com/borgbackup/borg.git
Merge pull request #5329 from ThomasWaldmann/fix-recover-segment-master
check --repair: fix potential data loss (master)
This commit is contained in:
commit
f928747ff7
|
@ -1486,23 +1486,21 @@ class LoggedIO:
|
||||||
logger.info('attempting to recover ' + filename)
|
logger.info('attempting to recover ' + filename)
|
||||||
if segment in self.fds:
|
if segment in self.fds:
|
||||||
del self.fds[segment]
|
del self.fds[segment]
|
||||||
backup_filename = filename + '.beforerecover'
|
if os.path.getsize(filename) < MAGIC_LEN + self.header_fmt.size:
|
||||||
os.rename(filename, backup_filename)
|
|
||||||
if os.path.getsize(backup_filename) < MAGIC_LEN + self.header_fmt.size:
|
|
||||||
# this is either a zero-byte file (which would crash mmap() below) or otherwise
|
# this is either a zero-byte file (which would crash mmap() below) or otherwise
|
||||||
# just too small to be a valid non-empty segment file, so do a shortcut here:
|
# just too small to be a valid non-empty segment file, so do a shortcut here:
|
||||||
with open(filename, 'wb') as fd:
|
with SaveFile(filename, binary=True) as fd:
|
||||||
fd.write(MAGIC)
|
fd.write(MAGIC)
|
||||||
return
|
return
|
||||||
with open(backup_filename, 'rb') as backup_fd:
|
with SaveFile(filename, binary=True) as dst_fd:
|
||||||
|
with open(filename, 'rb') as src_fd:
|
||||||
# note: file must not be 0 size or mmap() will crash.
|
# note: file must not be 0 size or mmap() will crash.
|
||||||
with mmap.mmap(backup_fd.fileno(), 0, access=mmap.ACCESS_READ) as mm:
|
with mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ) as mm:
|
||||||
# memoryview context manager is problematic, see https://bugs.python.org/issue35686
|
# memoryview context manager is problematic, see https://bugs.python.org/issue35686
|
||||||
data = memoryview(mm)
|
data = memoryview(mm)
|
||||||
d = data
|
d = data
|
||||||
try:
|
try:
|
||||||
with open(filename, 'wb') as fd:
|
dst_fd.write(MAGIC)
|
||||||
fd.write(MAGIC)
|
|
||||||
while len(d) >= self.header_fmt.size:
|
while len(d) >= self.header_fmt.size:
|
||||||
crc, size, tag = self.header_fmt.unpack(d[:self.header_fmt.size])
|
crc, size, tag = self.header_fmt.unpack(d[:self.header_fmt.size])
|
||||||
if size < self.header_fmt.size or size > len(d):
|
if size < self.header_fmt.size or size > len(d):
|
||||||
|
@ -1511,7 +1509,7 @@ class LoggedIO:
|
||||||
if crc32(d[4:size]) & 0xffffffff != crc:
|
if crc32(d[4:size]) & 0xffffffff != crc:
|
||||||
d = d[1:]
|
d = d[1:]
|
||||||
continue
|
continue
|
||||||
fd.write(d[:size])
|
dst_fd.write(d[:size])
|
||||||
d = d[size:]
|
d = d[size:]
|
||||||
finally:
|
finally:
|
||||||
del d
|
del d
|
||||||
|
|
Loading…
Reference in New Issue