diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/relocate.py | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/lib/spack/spack/relocate.py b/lib/spack/spack/relocate.py index a6aea329e1..c8c7947f9c 100644 --- a/lib/spack/spack/relocate.py +++ b/lib/spack/spack/relocate.py @@ -400,8 +400,8 @@ def replace_prefix_text(path_name, old_dir, new_dir): def replace_prefix_bin(path_name, old_dir, new_dir): """ Attempt to replace old install prefix with new install prefix - in binary files by replacing with null terminated string - that is the same length unless the old path is shorter + in binary files by prefixing new install prefix with os.sep + until the lengths of the prefixes are the same. """ def replace(match): @@ -430,6 +430,38 @@ def replace_prefix_bin(path_name, old_dir, new_dir): f.truncate() +def replace_prefix_nullterm(path_name, old_dir, new_dir): + """ + Attempt to replace old install prefix with new install prefix + in binary files by replacing with null terminated string + that is the same length unless the old path is shorter + Used on linux to replace mach-o rpaths + """ + + def replace(match): + occurances = match.group().count(old_dir.encode('utf-8')) + olen = len(old_dir.encode('utf-8')) + nlen = len(new_dir.encode('utf-8')) + padding = (olen - nlen) * occurances + if padding < 0: + return data + return match.group().replace(old_dir.encode('utf-8'), + new_dir.encode('utf-8')) + b'\0' * padding + with open(path_name, 'rb+') as f: + data = f.read() + f.seek(0) + original_data_len = len(data) + pat = re.compile(old_dir.encode('utf-8') + b'([^\0]*?)\0') + if not pat.search(data): + return + ndata = pat.sub(replace, data) + if not len(ndata) == original_data_len: + raise BinaryStringReplacementException( + path_name, original_data_len, len(ndata)) + f.write(ndata) + f.truncate() + + def relocate_macho_binaries(path_names, old_dir, new_dir, allow_root): """ Change old_dir to new_dir in LC_RPATH of mach-o files (on macOS) @@ -467,8 +499,7 @@ def relocate_macho_binaries(path_names, old_dir, new_dir, allow_root): modify_object_macholib(path_name, placeholder, new_dir) modify_object_macholib(path_name, old_dir, new_dir) if len(new_dir) <= len(old_dir): - replace_prefix_bin(path_name, old_dir, - new_dir) + replace_prefix_nullterm(path_name, old_dir, new_dir) else: tty.warn('Cannot do a binary string replacement' ' with padding for %s' |