summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShahwat Dalal <sdalal29@bloomberg.net>2019-07-05 15:39:31 +0100
committerDaniel Silverstone <daniel.silverstone@codethink.co.uk>2019-09-05 09:09:25 +0000
commit6f81827dab46f3ae36962784ffe5cd020dd72493 (patch)
tree0a8fbb2b6ef2c3564f6e51e8e87dd22d8db8c615
parent3513a80dd51486048e5421bcd25aafe86e607201 (diff)
downloadbuildstream-6f81827dab46f3ae36962784ffe5cd020dd72493.tar.gz
utils.py: Ensure dest copy directory is writable
In the case we are copying something to a read-only directory, `_copy_directories` fails. Copying should work regardless. Now when we are copying something to a read-only directory, we reset the permissions of the directory to writable, and then revert to the directory's original permissions after copying is completed. An example where this is nessesary is when extracting Docker layers. If one layer adds a read-only directory `/a` and the following layers adds `/a/foo`, we must be able to copy `foo` into the otherwise read-only directory, whilst still ensuring `/a` is read-only once the layer is staged.
-rw-r--r--src/buildstream/utils.py12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/buildstream/utils.py b/src/buildstream/utils.py
index c9b64aa52..32d23d27c 100644
--- a/src/buildstream/utils.py
+++ b/src/buildstream/utils.py
@@ -765,12 +765,12 @@ def _force_rmtree(rootpath, **kwargs):
def _copy_directories(srcdir, destdir, target):
this_dir = os.path.dirname(target)
new_dir = os.path.join(destdir, this_dir)
+ old_dir = os.path.join(srcdir, this_dir)
if not os.path.lexists(new_dir):
if this_dir:
yield from _copy_directories(srcdir, destdir, this_dir)
- old_dir = os.path.join(srcdir, this_dir)
if os.path.lexists(old_dir):
dir_stat = os.lstat(old_dir)
mode = dir_stat.st_mode
@@ -781,6 +781,16 @@ def _copy_directories(srcdir, destdir, target):
else:
raise UtilError('Source directory tree has file where '
'directory expected: {}'.format(old_dir))
+ else:
+ if not os.access(new_dir, os.W_OK):
+ # If the destination directory is not writable, change permissions to make it
+ # writable. Callers of this method (like `_process_list`) must
+ # restore the original permissions towards the end of their processing.
+ try:
+ os.chmod(new_dir, 0o755)
+ yield (new_dir, os.lstat(old_dir).st_mode)
+ except PermissionError:
+ raise UtilError("Directory {} is not writable".format(destdir))
# _ensure_real_directory()