#include #include #include #include #include #include #include #ifndef __OPENSTEP__ #include #endif #include #include "stuff/bool.h" #include "stuff/SymLoc.h" #include "stuff/ofile.h" #include "stuff/errors.h" #include "stuff/allocate.h" #include "stuff/dylib_roots.h" struct check_block { char *install_name; enum bool check_result; }; static void check_for_install_name( struct ofile *ofile, char *arch_name, void *cookie); char * get_symfile_for_dylib( char *install_name, char *release_name, enum bool *found_project, enum bool disablewarnings) { const char *symroot; symroot = symLocForDylib(install_name, release_name, found_project, disablewarnings); if(symroot == NULL) return(NULL); return(find_dylib_in_root(install_name, symroot)); } char * get_dstfile_for_dylib( char *install_name, char *release_name, enum bool *found_project, enum bool disablewarnings) { const char *dstroot; char *image_file_name; struct check_block block; struct stat stat_buf; dstroot = dstLocForDylib(install_name, release_name, found_project, disablewarnings); if(dstroot == NULL) return(NULL); if(*install_name == '/'){ image_file_name = makestr(dstroot, install_name, NULL); block.install_name = install_name; block.check_result = TRUE; /* * To avoid the error message generated by ofile_process() if the * file does not exist just move on to trying to find it in the * dstroot. */ if(disablewarnings == TRUE){ if(stat(image_file_name, &stat_buf) == -1){ free(image_file_name); goto try_to_find_in_dstroot; } } ofile_process(image_file_name, NULL, 0, TRUE, TRUE, TRUE, check_for_install_name, &block); if(block.check_result == TRUE) return(image_file_name); free(image_file_name); } try_to_find_in_dstroot: return(find_dylib_in_root(install_name, dstroot)); return(NULL); } char * find_dylib_in_root( char *install_name, const char *root) { #ifndef __OPENSTEP__ char *base_name, start[MAXPATHLEN + 1], *image_file_name; char const *paths[2]; FTS *fts; FTSENT *ftsent; struct check_block block; block.install_name = install_name; block.check_result = FALSE; #ifdef BIG_DEBUG printf("In find_dylib_in_root(install_name = %s, root = %s)\n", install_name, root); #endif if(realpath(root, start) == NULL){ #ifdef DEBUG printf("realpath() failed for: %s (%s, errno = %d)\n", root, strerror(errno), errno); #endif return(NULL); } #ifdef BIG_DEBUG printf("realpath() = %s for root: %s\n", start, root); #endif base_name = strrchr(install_name, '/'); if(base_name == NULL || base_name[1] == '\0') base_name = install_name; else base_name = base_name + 1; paths[0] = start; paths[1] = NULL; fts = fts_open(paths, FTS_PHYSICAL, NULL); if(fts == NULL){ #ifdef DEBUG printf("fts_open() failed for: %s (%s, errno = %d)\n", start, strerror(errno), errno); #endif return(NULL); } while((ftsent = fts_read(fts)) != NULL){ #ifdef BIG_DEBUG printf("fts_path = %s fts_name = %s\n", ftsent->fts_path, ftsent->fts_name); #endif if(S_ISREG(ftsent->fts_statp->st_mode) && !S_ISLNK(ftsent->fts_statp->st_mode) && strcmp(base_name, ftsent->fts_name) == 0){ #ifdef BIG_DEBUG printf("got a match: fts_path = %s fts_name = %s\n", ftsent->fts_path, ftsent->fts_name); #endif /* * Now that we found a file with the same base_name in the root * check to see that it is a dynamic library with the correct * install name. Assume it is an if it is not then the * routine check_for_install_name() will reset the check_result * in the block passed to it back to FALSE. */ block.check_result = TRUE; ofile_process(ftsent->fts_path, NULL, 0, TRUE, TRUE, TRUE, check_for_install_name, &block); if(block.check_result == TRUE){ image_file_name = allocate(ftsent->fts_pathlen + 1); strcpy(image_file_name, ftsent->fts_path); #ifdef BIG_DEBUG printf("returning %s\n", image_file_name); #endif if(fts_close(fts) == -1) system_error("fts_close() failed"); return(image_file_name); } } } if(errno != 0){ #ifdef DEBUG printf("fts_read() failed for (%s, errno = %d)\n", strerror(errno), errno); #endif if(fts_close(fts) == -1) system_error("fts_close() failed"); return(NULL); } if(fts_close(fts) == -1){ system_error("fts_close() failed"); return(NULL); } #endif /* !defined(__OPENSTEP___) */ return(NULL); } static void check_for_install_name( struct ofile *ofile, char *arch_name, void *cookie) { unsigned long i; struct check_block *block; struct load_command *lc; struct dylib_command *dl; char *name; #ifdef BIG_DEBUG printf("In check_for_install_name() ofile->file_name = %s", ofile->file_name); if(arch_name != NULL) printf(" arch_name = %s\n", arch_name); else printf("\n"); #endif /* BIG_DEBUG */ block = (struct check_block *)cookie; if(ofile->mh == NULL){ block->check_result = FALSE; return; } lc = ofile->load_commands; for(i = 0; i < ofile->mh->ncmds; i++){ if(lc->cmd == LC_ID_DYLIB){ dl = (struct dylib_command *)lc; name = (char *)lc + dl->dylib.name.offset; if(strcmp(name, block->install_name) != 0) block->check_result = FALSE; return; } lc = (struct load_command *)((char *)lc + lc->cmdsize); } block->check_result = FALSE; return; }