Skip to content

Commit

Permalink
Fix file state tracking with st = None after unlink/rmdir
Browse files Browse the repository at this point in the history
  • Loading branch information
alighazi288 committed Jan 20, 2025
1 parent 1019f36 commit 17ffef9
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 10 deletions.
16 changes: 7 additions & 9 deletions src/borg/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,9 +719,9 @@ def extract_helper(self, item, path, hlm, *, dry_run=False):
# In this case, we *want* to extract twice, because there is no other way.
pass

def compare_and_extract_chunks(self, item, fs_path, *, pi=None, sparse=False):
def compare_and_extract_chunks(self, item, fs_path, *, st, pi=None):
"""Compare file chunks and patch if needed. Returns True if patching succeeded."""
if not os.path.exists(fs_path):
if st is None:
return False
try:
# First pass: Build fs chunks list
Expand Down Expand Up @@ -755,12 +755,8 @@ def compare_and_extract_chunks(self, item, fs_path, *, pi=None, sparse=False):
else:
chunk_data = next(chunk_data_iter)

with backup_io("seek"):
fs_file.seek(fs_file.tell())

with backup_io("write"):
data = b"\0" * len(chunk_data) if sparse and not chunk_data.strip(b"\0") else chunk_data
fs_file.write(data)
fs_file.write(chunk_data)
if pi:
pi.show(increase=len(chunk_data), info=[remove_surrogates(item.path)])

Expand Down Expand Up @@ -863,12 +859,14 @@ def same_item(item, st):
return # done! we already have fully extracted this file in a previous run.
elif stat.S_ISDIR(st.st_mode):
os.rmdir(path)
st = None
else:
os.unlink(path)
st = None
except UnicodeEncodeError:
raise self.IncompatibleFilesystemEncodingError(path, sys.getfilesystemencoding()) from None
except OSError:
pass
st = None

def make_parent(path):
parent_dir = os.path.dirname(path)
Expand All @@ -882,7 +880,7 @@ def make_parent(path):
with self.extract_helper(item, path, hlm) as hardlink_set:
if hardlink_set:
return
if self.compare_and_extract_chunks(item, path, pi=pi, sparse=sparse):
if self.compare_and_extract_chunks(item, path, st=st, pi=pi):
return

with backup_io("open"):
Expand Down
3 changes: 2 additions & 1 deletion src/borg/testsuite/archive_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,8 @@ def test_compare_and_extract_chunks(setup_extractor, name, item_data, fs_data, e
with open(target_path, "wb") as f:
f.write(fs_data)

result = extractor.compare_and_extract_chunks(item, target_path)
st = os.stat(target_path)
result = extractor.compare_and_extract_chunks(item, target_path, st=st)
assert result

fetched_chunks = get_fetched_chunks()
Expand Down

0 comments on commit 17ffef9

Please sign in to comment.