From 17ffef9b5366e056e0a6725e7bc9b0423687a470 Mon Sep 17 00:00:00 2001 From: alighazi288 <51366992+alighazi288@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:53:29 -0500 Subject: [PATCH] Fix file state tracking with st = None after unlink/rmdir --- src/borg/archive.py | 16 +++++++--------- src/borg/testsuite/archive_test.py | 3 ++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index ea5e1e75e8..7461e8ada1 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -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 @@ -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)]) @@ -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) @@ -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"): diff --git a/src/borg/testsuite/archive_test.py b/src/borg/testsuite/archive_test.py index 93bc9bddc6..3aee648ab4 100644 --- a/src/borg/testsuite/archive_test.py +++ b/src/borg/testsuite/archive_test.py @@ -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()