import-tar: fix the dotslash issue, add test

This commit is contained in:
Thomas Waldmann 2025-06-26 20:33:38 +02:00
parent 37aa4b745b
commit 2ecd76b4fc
No known key found for this signature in database
GPG key ID: 243ACFA951F78E01
2 changed files with 31 additions and 1 deletions

View file

@ -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

View file

@ -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 = [