/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef RLD #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_dylib( 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, enum bool no_error_if_missing) { const char *symroot; symroot = symLocForDylib(install_name, release_name, found_project, disablewarnings, no_error_if_missing); 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, enum bool no_error_if_missing) { const char *dstroot; char *image_file_name; struct check_block block; struct stat stat_buf; dstroot = dstLocForDylib(install_name, release_name, found_project, disablewarnings, no_error_if_missing); 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, FALSE, check_for_dylib, &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((char * const *)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. Assume it is an * if it is not then the routine check_for_dylib() 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, FALSE, check_for_dylib,&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_dylib( struct ofile *ofile, char *arch_name, void *cookie) { uint32_t i; struct check_block *block; struct load_command *lc; uint32_t ncmds; #ifdef BIG_DEBUG printf("In check_for_dylib() 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){ ncmds = ofile->mh->ncmds; } else if (ofile->mh64 != NULL) { ncmds = ofile->mh64->ncmds; } else { block->check_result = FALSE; return; } lc = ofile->load_commands; for(i = 0; i < ncmds; i++){ if(lc->cmd == LC_ID_DYLIB){ return; } lc = (struct load_command *)((char *)lc + lc->cmdsize); } block->check_result = FALSE; return; } #endif /* !defined(RLD) */