diff options
author | Shahwat Dalal <sdalal29@bloomberg.net> | 2019-07-05 15:39:31 +0100 |
---|---|---|
committer | Daniel Silverstone <daniel.silverstone@codethink.co.uk> | 2019-09-05 09:09:25 +0000 |
commit | 6f81827dab46f3ae36962784ffe5cd020dd72493 (patch) | |
tree | 0a8fbb2b6ef2c3564f6e51e8e87dd22d8db8c615 | |
parent | 3513a80dd51486048e5421bcd25aafe86e607201 (diff) | |
download | buildstream-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.py | 12 |
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() |