summaryrefslogtreecommitdiff
path: root/buildstream/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'buildstream/utils.py')
-rw-r--r--buildstream/utils.py46
1 files changed, 44 insertions, 2 deletions
diff --git a/buildstream/utils.py b/buildstream/utils.py
index ae5da34d7..fc496154e 100644
--- a/buildstream/utils.py
+++ b/buildstream/utils.py
@@ -787,6 +787,48 @@ def _ensure_real_directory(root, destpath):
return destpath_resolved
+@functools.lru_cache(maxsize=1)
+def _symloop_max():
+ if hasattr(os, 'sysconf'):
+ try:
+ ret = os.sysconf('_SC_SYMLOOP_MAX')
+ if ret != -1:
+ return ret
+ except ValueError:
+ pass
+ return 8
+
+
+@functools.lru_cache(maxsize=64)
+def _sysroot_realpath(path, sysroot):
+ assert not os.path.isabs(path)
+ assert os.path.isabs(sysroot)
+
+ loop_count = _symloop_max()
+ while True:
+ full_path = os.path.join(sysroot, path)
+ st = os.lstat(full_path)
+ mode = st.st_mode
+ if not stat.S_ISLNK(mode):
+ break
+ loop_count = loop_count - 1
+ if loop_count < 0:
+ raise UtilError("Symlink loop detected: {}".format(os.path.join(sysroot, path)))
+ link_path = os.readlink(full_path)
+ if not os.path.isabs(link_path):
+ link_path = os.path.join('/', os.path.dirname(path), link_path)
+ path = os.path.relpath(os.path.normpath(link_path), '/')
+
+ parent = os.path.dirname(path)
+ if parent != '':
+ parent = _sysroot_realpath(parent, sysroot)
+ full_parent = os.path.join(sysroot, parent)
+ if not os.path.isdir(full_parent):
+ raise UtilError("Path is not a directory: {}".format(full_parent))
+
+ return os.path.join(parent, os.path.basename(path))
+
+
# _process_list()
#
# Internal helper for copying/moving/linking file lists
@@ -817,10 +859,10 @@ def _process_list(srcdir, destdir, filelist, actionfunc, result,
# those directories.
if not presorted:
resolved = []
+ _sysroot_realpath.cache_clear()
for f in filelist:
dirname = os.path.dirname(f)
- dirname = os.path.realpath(os.path.join(srcdir, dirname))
- dirname = os.path.relpath(dirname, srcdir)
+ dirname = _sysroot_realpath(dirname, srcdir)
if dirname == '.':
resolved.append(os.path.basename(f))
else: