diff options
Diffstat (limited to 'lib/rpath.c')
-rw-r--r-- | lib/rpath.c | 120 |
1 files changed, 60 insertions, 60 deletions
diff --git a/lib/rpath.c b/lib/rpath.c index 4d4d801..ae73574 100644 --- a/lib/rpath.c +++ b/lib/rpath.c @@ -5,7 +5,7 @@ /** * Wrapper function to execute `patchelf` with arguments - * @param _filename Path of file to modify + * @param _filename Path to file * @param _args Arguments to pass to `patchelf` * @return success=Process struct, failure=NULL */ @@ -32,6 +32,34 @@ Process *patchelf(const char *_filename, const char *_args) { } /** + * Wrapper function to execute `install_name_tool` with arguments + * @param _filename Path to file + * @param _args Arguments to pass to `install_name_tool` + * @return success=Process struct, failure=NULL + */ +Process *install_name_tool(const char *_filename, const char *_args) { + char *filename = strdup(_filename); + char *args = strdup(_args); + Process *proc_info = NULL; + char sh_cmd[PATH_MAX]; + sh_cmd[0] = '\0'; + + strchrdel(args, SHELL_INVALID); + strchrdel(filename, SHELL_INVALID); + sprintf(sh_cmd, "install_name_tool %s %s 2>&1", args, filename); + + if (SPM_GLOBAL.verbose > 1) { + printf(" EXEC : %s\n", sh_cmd); + } + + shell(&proc_info, SHELL_OUTPUT, sh_cmd); + + free(filename); + free(args); + return proc_info; +} + +/** * Determine whether a RPATH or RUNPATH is present in file * * TODO: Replace with OS-native solution(s) @@ -40,30 +68,18 @@ Process *patchelf(const char *_filename, const char *_args) { * @return -1=OS error, 0=has rpath, 1=not found */ int has_rpath(const char *_filename) { - int result = 1; // default: not found + char *rpath = NULL; - char *filename = strdup(_filename); - if (!filename) { + if (_filename == NULL) { + spmerrno = EINVAL; return -1; } - // sanitize input path - strchrdel(filename, SHELL_INVALID); - - Process *pe = patchelf(filename, "--print-rpath"); - strip(pe->output); - if (!isempty(pe->output)) { - result = 0; - } - else { - // something went wrong with patchelf other than - // what we're looking for - result = -1; - } + if ((rpath = shlib_rpath(_filename)) == NULL) { + return 1; + }; - free(filename); - shell_free(pe); - return result; + return 0; } /** @@ -78,42 +94,7 @@ char *rpath_get(const char *_filename) { if ((has_rpath(_filename)) != 0) { return strdup(""); } - char *filename = strdup(_filename); - if (!filename) { - return NULL; - } - char *path = strdup(filename); - if (!path) { - free(filename); - return NULL; - } - - char *rpath = NULL; - - // sanitize input path - strchrdel(path, SHELL_INVALID); - - Process *pe = patchelf(filename, "--print-rpath"); - if (pe->returncode != 0) { - fprintf(stderr, "patchelf error: %s %s\n", path, strip(pe->output)); - return NULL; - } - - rpath = (char *)calloc(strlen(pe->output) + 1, sizeof(char)); - if (!rpath) { - free(filename); - free(path); - shell_free(pe); - return NULL; - } - - strncpy(rpath, pe->output, strlen(pe->output)); - strip(rpath); - - free(filename); - free(path); - shell_free(pe); - return rpath; + return shlib_rpath(_filename); } /** @@ -149,10 +130,19 @@ char *rpath_generate(const char *_filename, FSTree *tree) { int rpath_set(const char *filename, const char *rpath) { int returncode = 0; char args[PATH_MAX]; + Process *pe = NULL; memset(args, '\0', PATH_MAX); - sprintf(args, "--set-rpath '%s'", rpath); // note: rpath requires single-quotes - Process *pe = patchelf(filename, args); +#if OS_LINUX + sprintf(args, "--set-rpath '%s'", rpath); + pe = patchelf(filename, args); +#elif OS_DARWIN + sprintf(args, "-add-rpath '%s'", rpath); + pe = install_name_tool(filename, args); +#elif OS_WINDOWS + // TODO: assuming windows has a mechanism for changing runtime paths, do it here. +#endif + if (pe != NULL) { returncode = pe->returncode; } @@ -203,7 +193,7 @@ FSTree *rpath_libraries_available(const char *root) { * @return success=relative path from `filename` to nearest lib directory, failure=NULL */ char *rpath_autodetect(const char *filename, FSTree *tree) { - const char *origin = "$ORIGIN"; + const char *origin; char *rootdir = dirname(filename); char *start = realpath(rootdir, NULL); char *cwd = realpath(".", NULL); @@ -214,6 +204,14 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { char *relative = _relative; // Pointer to relative path size_t depth_to_root = 0; +#if OS_DARWIN + origin = "@rpath"; +#elif OS_LINUX + origin = "$ORIGIN"; +#else + origin = NULL; +#endif + // BUG: Perl dumps its shared library in a strange place. // This function returns `$ORIGIN/../../../CORE` which is not what we want to see. // TODO: We WANT to see this: `$ORIGIN/../lib/perl5/xx.xx.xx/<arch>/CORE` not just the basename() @@ -256,7 +254,7 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { // Get the shared library name we are going to look for in the tree char *shared_library = strlist_item(libs_wanted, i); - // Is the the shared library in the tree? + // Is the shared library in the tree? char *match = NULL; if ((match = dirname(strstr_array(tree->files, shared_library))) != NULL) { // Begin generating the relative path string @@ -283,12 +281,14 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { } } +#if OS_LINUX // Some programs do not require local libraries provided by SPM (i.e. libc) // Inject "likely" defaults here if (strlist_count(libs) == 0) { strlist_append(libs, "$ORIGIN/../lib"); strlist_append(libs, "$ORIGIN/../lib64"); } +#endif // Populate result string result = join(libs->data, ":"); |