Skip to content

Commit de88ab3

Browse files
authored
Merge pull request #1880 from docker/1841-tar-broken-symlinks
Do not break when archiving broken symlinks
2 parents 4ff2962 + 4e34300 commit de88ab3

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

docker/utils/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ def create_archive(root, files=None, fileobj=None, gzip=False):
9898
files = build_file_list(root)
9999
for path in files:
100100
full_path = os.path.join(root, path)
101-
if not os.access(full_path, os.R_OK):
101+
102+
if os.lstat(full_path).st_mode & os.R_OK == 0:
102103
raise IOError(
103104
'Can not access file in context: {}'.format(full_path)
104105
)

tests/unit/utils_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,20 @@ def test_tar_with_empty_directory(self):
948948
tar_data = tarfile.open(fileobj=archive)
949949
self.assertEqual(sorted(tar_data.getnames()), ['bar', 'foo'])
950950

951+
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='No chmod on Windows')
952+
def test_tar_with_inaccessible_file(self):
953+
base = tempfile.mkdtemp()
954+
full_path = os.path.join(base, 'foo')
955+
self.addCleanup(shutil.rmtree, base)
956+
with open(full_path, 'w') as f:
957+
f.write('content')
958+
os.chmod(full_path, 0o222)
959+
with pytest.raises(IOError) as ei:
960+
tar(base)
961+
962+
assert 'Can not access file in context: {}'.format(full_path) in \
963+
ei.exconly()
964+
951965
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='No symlinks on Windows')
952966
def test_tar_with_file_symlinks(self):
953967
base = tempfile.mkdtemp()
@@ -975,6 +989,18 @@ def test_tar_with_directory_symlinks(self):
975989
sorted(tar_data.getnames()), ['bar', 'bar/foo', 'foo']
976990
)
977991

992+
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='No symlinks on Windows')
993+
def test_tar_with_broken_symlinks(self):
994+
base = tempfile.mkdtemp()
995+
self.addCleanup(shutil.rmtree, base)
996+
for d in ['foo', 'bar']:
997+
os.makedirs(os.path.join(base, d))
998+
999+
os.symlink('../baz', os.path.join(base, 'bar/foo'))
1000+
with tar(base) as archive:
1001+
tar_data = tarfile.open(fileobj=archive)
1002+
assert sorted(tar_data.getnames()) == ['bar', 'bar/foo', 'foo']
1003+
9781004
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='No UNIX sockets on Win32')
9791005
def test_tar_socket_file(self):
9801006
base = tempfile.mkdtemp()

0 commit comments

Comments
 (0)