diff options
author | Valentin David <valentin.david@codethink.co.uk> | 2018-08-07 16:22:26 +0200 |
---|---|---|
committer | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2018-08-12 05:54:36 +0000 |
commit | d08699bdfa17e9b5a4d3046af126a60058f8c7f6 (patch) | |
tree | 129629072fdc4ed367153411111445ee84a3f00b /buildstream | |
parent | 322cab58e255916da10e0a59ae91e92f50898504 (diff) | |
download | buildstream-d08699bdfa17e9b5a4d3046af126a60058f8c7f6.tar.gz |
buildstream/plugins/sources/zip.py: Fix non-determism in staging.
Staging could end-up with file with different rights depending on the
umask. The extracted files need to get their access rights fixed.
Diffstat (limited to 'buildstream')
-rw-r--r-- | buildstream/plugins/sources/zip.py | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/buildstream/plugins/sources/zip.py b/buildstream/plugins/sources/zip.py index 9b47d7f78..d3ce0f16d 100644 --- a/buildstream/plugins/sources/zip.py +++ b/buildstream/plugins/sources/zip.py @@ -49,10 +49,17 @@ zip - stage files from zip archives # To extract the root of the archive directly, this can be set # to an empty string. base-dir: '*' + +.. attention:: + + File permissions are not preserved. All extracted directories have + permissions 0755 and all extracted files have permissions 0644. + """ import os import zipfile +import stat from buildstream import SourceError from buildstream import utils @@ -74,6 +81,9 @@ class ZipSource(DownloadableFileSource): return super().get_unique_key() + [self.base_dir] def stage(self, directory): + exec_rights = (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) & ~(stat.S_IWGRP | stat.S_IWOTH) + noexec_rights = exec_rights & ~(stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) + try: with zipfile.ZipFile(self._get_mirror_file()) as archive: base_dir = None @@ -81,9 +91,27 @@ class ZipSource(DownloadableFileSource): base_dir = self._find_base_dir(archive, self.base_dir) if base_dir: - archive.extractall(path=directory, members=self._extract_members(archive, base_dir)) + members = self._extract_members(archive, base_dir) else: - archive.extractall(path=directory) + members = archive.namelist() + + for member in members: + written = archive.extract(member, path=directory) + + # zipfile.extract might create missing directories + rel = os.path.relpath(written, start=directory) + assert not os.path.isabs(rel) + rel = os.path.dirname(rel) + while rel: + os.chmod(os.path.join(directory, rel), exec_rights) + rel = os.path.dirname(rel) + + if os.path.islink(written): + pass + elif os.path.isdir(written): + os.chmod(written, exec_rights) + else: + os.chmod(written, noexec_rights) except (zipfile.BadZipFile, zipfile.LargeZipFile, OSError) as e: raise SourceError("{}: Error staging source: {}".format(self, e)) from e |