diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/package.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/scripts/package.py b/scripts/package.py new file mode 100755 index 0000000..3de3448 --- /dev/null +++ b/scripts/package.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +import subprocess +import sys +import os +import shutil +import re +import stat +import tarfile + +def get_executable_dynamic_libraries(filepath): + libs = [] + process = subprocess.Popen(["ldd", filepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = process.communicate() + if process.returncode != 0: + raise RuntimeError("Failed to execute ldd on executable %s, error:\n%s" % (filepath, stderr)) + lines = stdout.splitlines() + for line in lines: + s = line.split() + if b"=>" in s: + if len(s) >= 3: + libs.append(os.path.realpath(s[2].decode("UTF-8"))) + return libs + +def make_executable(filepath): + mode = os.stat(filepath).st_mode + os.chmod(filepath, mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) + +def main(): + if len(sys.argv) <= 2: + print("usage: %s executable_path destination_path" % sys.argv[0]) + exit(1) + + os.makedirs(sys.argv[2], exist_ok=True) + libs = get_executable_dynamic_libraries(sys.argv[1]) + + so_loader_pattern = re.compile("ld-[0-9.]+\\.so.*") + so_loader = None + for lib in libs: + lib_filename = os.path.basename(lib) + if so_loader_pattern.match(lib_filename): + if so_loader != None: + print("Unexpected error: found multiple so loaders, unable to recover") + exit(2) + so_loader = lib_filename + + executable_filename = os.path.basename(sys.argv[1]) + new_executable_path = os.path.join(sys.argv[2], executable_filename) + shutil.copyfile(sys.argv[1], new_executable_path) + make_executable(new_executable_path) + + print("Patching executable") + process = subprocess.Popen(["patchelf", "--set-interpreter", so_loader, new_executable_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = process.communicate() + if process.returncode != 0: + print("Failed to execute patchelf --set-interpreter on executable %s, error: %s" % (new_executable_path, stderr)) + exit(3) + + process = subprocess.Popen(["patchelf", "--set-rpath", ".", new_executable_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = process.communicate() + if process.returncode != 0: + print("Failed to execute patchelf --set-rpath on executable %s, error: %s" % (new_executable_path, stderr)) + exit(4) + + package_name = new_executable_path + ".tar.gz" + print("Creating package %s" % os.path.basename(package_name)) + with tarfile.open(package_name, "w:gz") as tar: + for lib in libs: + print("Adding shared library %s to tar" % lib) + tar.add(lib, arcname=os.path.basename(lib)) + print("Adding executable %s to tar" % sys.argv[1]) + tar.add(new_executable_path, arcname=os.path.basename(new_executable_path)) + + print("Removing temporary file %s" % new_executable_path) + os.remove(new_executable_path) + print("Package has been created at %s" % package_name) + +if __name__ == "__main__": + main()
\ No newline at end of file |