Fixed #26494 -- Made Archive.extract() preserve file permissions.

This commit is contained in:
Anton Samarchyan 2016-12-01 11:05:08 -05:00 committed by Tim Graham
parent dd99e69fa8
commit d0112cf930
6 changed files with 15 additions and 0 deletions

View File

@ -164,6 +164,7 @@ class TarArchive(BaseArchive):
os.makedirs(dirname)
with open(filename, 'wb') as outfile:
shutil.copyfileobj(extracted, outfile)
os.chmod(filename, member.mode)
finally:
if extracted:
extracted.close()
@ -185,6 +186,7 @@ class ZipArchive(BaseArchive):
leading = self.has_leading_dir(namelist)
for name in namelist:
data = self._archive.read(name)
info = self._archive.getinfo(name)
if leading:
name = self.split_leading_dir(name)[1]
filename = os.path.join(to_path, name)
@ -198,6 +200,9 @@ class ZipArchive(BaseArchive):
else:
with open(filename, 'wb') as outfile:
outfile.write(data)
# convert ZipInfo.external_attr to mode
mode = info.external_attr >> 16
os.chmod(filename, mode)
def close(self):
self._archive.close()

View File

@ -1,5 +1,7 @@
import os
import shutil
import stat
import sys
import tempfile
import unittest
@ -42,6 +44,14 @@ class ArchiveTester(object):
extract(self.archive_path, self.tmpdir)
self.check_files(self.tmpdir)
@unittest.skipIf(sys.platform == 'win32', 'Python on Windows has a limited os.chmod().')
def test_extract_file_permissions(self):
"""Archive.extract() preserves file permissions."""
extract(self.archive_path, self.tmpdir)
filepath = os.path.join(self.tmpdir, 'executable')
# The file has executable permission.
self.assertTrue(os.stat(filepath).st_mode & stat.S_IXOTH)
def test_extract_function_with_leadpath(self):
extract(self.archive_lead_path, self.tmpdir)
self.check_files(self.tmpdir)