* extends mkdirs with permissions for intermediate folders

Does not use os.makedirs mode parameter because its behavior is changed
with Python 3.7 (it ignores it for intermediate dirs), and moreover it
was not possible to set different modes for newly-created folders
and leaf folder.

reference:
- https://bugs.python.org/issue19930
- https://docs.python.org/3.7/library/os.html#os.makedirs

* comment mkdirp step easing code understanding

* revert mkdir to default for package metapath

since metapath is nested in package folder, there is no need
to specify permissions for intermediate folders because the prefix
already exists.

* comment create_install_directory package modes
This commit is contained in:
albestro 2019-07-19 17:13:29 +02:00 committed by Greg Becker
parent cadff917c7
commit 3a026f1412
2 changed files with 37 additions and 1 deletions

View File

@ -423,14 +423,39 @@ def mkdirp(*paths, **kwargs):
Keyword Aguments: Keyword Aguments:
mode (permission bits or None, optional): optional permissions to mode (permission bits or None, optional): optional permissions to
set on the created directory -- use OS default if not provided set on the created directory -- use OS default if not provided
mode_intermediate (permission bits or None, optional):
same as mode, but for newly-created intermediate directories
""" """
mode = kwargs.get('mode', None) mode = kwargs.get('mode', None)
mode_intermediate = kwargs.get('mode_intermediate', None)
for path in paths: for path in paths:
if not os.path.exists(path): if not os.path.exists(path):
try: try:
intermediate_folders = []
if mode_intermediate is not None:
# detect missing intermediate folders
intermediate_path = os.path.dirname(path)
while intermediate_path:
if os.path.exists(intermediate_path):
break
intermediate_folders.append(intermediate_path)
intermediate_path = os.path.dirname(intermediate_path)
# create folders
os.makedirs(path) os.makedirs(path)
# leaf folder permissions
if mode is not None: if mode is not None:
os.chmod(path, mode) os.chmod(path, mode)
# for intermediate folders, change mode just for newly created
# ones and if mode_intermediate has been specified, otherwise
# intermediate folders list is not populated at all and default
# OS mode will be used
for intermediate_path in reversed(intermediate_folders):
os.chmod(intermediate_path, mode_intermediate)
except OSError as e: except OSError as e:
if e.errno != errno.EEXIST or not os.path.isdir(path): if e.errno != errno.EEXIST or not os.path.isdir(path):
raise e raise e

View File

@ -254,15 +254,26 @@ def create_install_directory(self, spec):
# Cannot import at top of file # Cannot import at top of file
from spack.package_prefs import get_package_dir_permissions from spack.package_prefs import get_package_dir_permissions
from spack.package_prefs import get_package_group from spack.package_prefs import get_package_group
# Each package folder can have its own specific permissions, while
# intermediate folders (arch/compiler) are set with full access to
# everyone (0o777) and install_tree root folder is the chokepoint
# for restricting global access.
# So, whoever has access to the install_tree is allowed to install
# packages for same arch/compiler and since no data is stored in
# intermediate folders, it does not represent a security threat.
group = get_package_group(spec) group = get_package_group(spec)
perms = get_package_dir_permissions(spec) perms = get_package_dir_permissions(spec)
mkdirp(spec.prefix, mode=perms) perms_intermediate = 0o777
mkdirp(spec.prefix, mode=perms, mode_intermediate=perms_intermediate)
if group: if group:
chgrp(spec.prefix, group) chgrp(spec.prefix, group)
# Need to reset the sticky group bit after chgrp # Need to reset the sticky group bit after chgrp
os.chmod(spec.prefix, perms) os.chmod(spec.prefix, perms)
mkdirp(self.metadata_path(spec), mode=perms) mkdirp(self.metadata_path(spec), mode=perms)
self.write_spec(spec, self.spec_file_path(spec)) self.write_spec(spec, self.spec_file_path(spec))
def check_installed(self, spec): def check_installed(self, spec):