diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-18 21:57:51 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-18 21:57:51 -0500 |
commit | 534657dd6fc2ee98159e41d2700554fed0da2c4e (patch) | |
tree | d9316757b060d68e5640ea9ecb56b29c62adedfc /rpath.c | |
parent | 3166627f1485e2f05421fe874b2236852fe5d017 (diff) | |
download | spmc-534657dd6fc2ee98159e41d2700554fed0da2c4e.tar.gz |
Refactor project structure
Diffstat (limited to 'rpath.c')
-rw-r--r-- | rpath.c | 233 |
1 files changed, 0 insertions, 233 deletions
diff --git a/rpath.c b/rpath.c deleted file mode 100644 index f499e98..0000000 --- a/rpath.c +++ /dev/null @@ -1,233 +0,0 @@ -#include "spm.h" - -/** - * Wrapper function to execute `patchelf` with arguments - * @param _filename Path of file to modify - * @param _args Arguments to pass to `patchelf` - * @return success=Process struct, failure=NULL - */ -Process *patchelf(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, "&;|"); - strchrdel(filename, "&;|"); - sprintf(sh_cmd, "patchelf %s %s", args, filename); - - 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) - * - * @param _filename path to executable or library - * @return -1=OS error, 0=has rpath, 1=not found - */ -int has_rpath(const char *_filename) { - int result = 1; // default: not found - - char *filename = strdup(_filename); - if (!filename) { - return -1; - } - - Process *proc_info = NULL; - char *rpath = NULL; - - // sanitize input path - strchrdel(filename, "&;|"); - - 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; - } - - free(filename); - shell_free(pe); - return result; -} - -/** - * Returns a RPATH or RUNPATH if one is defined in `_filename` - * - * TODO: Replace with OS-native solution(s) - * - * @param _filename path to executable or library - * @return RPATH string, NULL=error (caller is responsible for freeing memory) - */ -char *rpath_get(const char *_filename) { - if ((has_rpath(_filename)) != 0) { - return NULL; - } - char *filename = strdup(_filename); - if (!filename) { - return NULL; - } - char *path = strdup(filename); - if (!path) { - free(filename); - return NULL; - } - - Process *proc_info = NULL; - char *rpath = NULL; - - // sanitize input path - strchrdel(path, "&;|"); - - Process *pe = patchelf(filename, "--print-rpath"); - 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; -} - -/** - * Generate a RPATH in the form of: - * - * `$ORIGIN/relative/path/to/lib/from/_filename/path` - * - * @param _filename - * @return - */ -char *rpath_generate(const char *_filename) { - const char *origin = "$ORIGIN/"; - char *filename = realpath(_filename, NULL); - if (!filename) { - return NULL; - } - char *nearest_lib = rpath_autodetect(filename); - if (!nearest_lib) { - return NULL; - } - char *result = (char *)calloc(strlen(origin) + strlen(nearest_lib) + 1, sizeof(char)); - if (!result) { - return NULL; - } - sprintf(result, "%s%s", origin, nearest_lib); - free(filename); - free(nearest_lib); - return result; -} - -int rpath_set(const char *filename, char *_rpath) { - int returncode; - - char *rpath_new = rpath_generate(filename); - if (!rpath_new) { - return -1; - } - - char *rpath_orig = rpath_get(filename); - if (!rpath_orig) { - return -1; - } - - // Are the original and new RPATH identical? - if (strcmp(rpath_orig, rpath_new) == 0) { - free(rpath_new); - free(rpath_orig); - return 0; - } - - Process *pe = patchelf(filename, "--set-rpath"); - if (pe) { - returncode = pe->returncode; - } - shell_free(pe); - free(rpath_new); - free(rpath_orig); - return pe->returncode; -} - -/** - * Using `filename` as a starting point, step backward through the filesystem looking for a lib directory - * @param filename path to file (or a directory) - * @return success=relative path from `filename` to nearest lib directory, failure=NULL - */ -char *rpath_autodetect(const char *filename) { - int has_real_libdir = 0; - char *rootdir = dirname(filename); - char *start = realpath(rootdir, NULL); - char *cwd = realpath(".", NULL); - char *result = NULL; - - // Change directory to the requested root - chdir(start); - - char visit[PATH_MAX]; // Current directory - char tmp[PATH_MAX]; // Current directory with lib directory appended - char relative[PATH_MAX]; // Generated relative path to lib directory - char sep[2]; // Holds the platform's directory separator - - // Initialize character arrays; - visit[0] = '\0'; - tmp[0] = '\0'; - relative[0] = '\0'; - sprintf(sep, "%c", DIRSEP); - - while(1) { - // Where are we in the file system? - getcwd(visit, sizeof(visit)); - // Using the current visit path, check if it contains a lib directory - sprintf(tmp, "%s%clib", visit, DIRSEP); - if (access(tmp, F_OK) == 0) { - strcat(relative, "lib"); - has_real_libdir = 1; // gate for memory allocation below - break; - } - // Reaching the top of the file system indicates our search for a lib directory failed - else if (strcmp(visit, "/") == 0) { - break; - } - - // Assemble relative path step for this location - strcat(relative, ".."); - strcat(relative, sep); - - // Step one directory level back - chdir(".."); - } - - // If we found a viable lib directory, allocate memory for it - if (has_real_libdir) { - result = (char *)calloc(strlen(relative) + 1, sizeof(char)); - if (!result) { - chdir(cwd); // return to calling directory - return NULL; - } - // Copy character array data to the result - strncpy(result, relative, strlen(relative)); - } - - chdir(cwd); // return to calling directory - free(rootdir); - free(cwd); - free(start); - return result; -} |