From 2ecd76b4fc1a05644faecb717297ca7e2c4004c3 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 26 Jun 2025 20:33:38 +0200 Subject: [PATCH] import-tar: fix the dotslash issue, add test --- src/borg/archive.py | 5 ++++- src/borg/testsuite/archiver.py | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index 359c55053..0ceb548e7 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -1493,7 +1493,10 @@ class TarfileObjectProcessors: @contextmanager def create_helper(self, tarinfo, status=None, type=None): - item = Item(path=make_path_safe(tarinfo.name), mode=tarinfo.mode | type, + # if the tar has names starting with "./", normalize them like borg create also does. + # ./dir/file must become dir/file in the borg archive. + normalized_path = os.path.normpath(tarinfo.name) + item = Item(path=make_path_safe(normalized_path), mode=tarinfo.mode | type, uid=tarinfo.uid, gid=tarinfo.gid, user=tarinfo.uname or None, group=tarinfo.gname or None, mtime=safe_ns(int(tarinfo.mtime * 1000**3))) yield item, status diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index aed31024e..4eb0599bd 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -3663,6 +3663,33 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02 # due to zero-filled block marker. self.assert_equal(os.listdir('output'), ['file1']) + @requires_gnutar + def test_import_tar_with_dotslash_paths(self): + """Test that paths starting with './' are normalized during import-tar.""" + # Create a simple directory structure + os.makedirs('input/dir', exist_ok=True) + self.create_regular_file('dir/file') + + # Create a tar file with paths starting with './' + with changedir('input'): + # Directly use a path that starts with './' + subprocess.check_call(['tar', 'cf', 'dotslash.tar', './dir']) + + # Verify the tar file contains paths with './' prefix + tar_content = subprocess.check_output(['tar', 'tf', 'dotslash.tar']).decode() + assert './dir' in tar_content + assert './dir/file' in tar_content + + # Import the tar file into a Borg repository + self.cmd('init', '--encryption=none', self.repository_location) + self.cmd('import-tar', self.repository_location + '::dotslash', 'input/dotslash.tar') + + # List the archive contents and verify no paths start with './' + output = self.cmd('list', '--format={path}{NL}', self.repository_location + '::dotslash') + assert './dir' not in output + assert 'dir' in output + assert 'dir/file' in output + def test_detect_attic_repo(self): path = make_attic_repo(self.repository_path) cmds = [