1/* 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#ifndef RLD 24#include <stdlib.h> 25#include <stdio.h> 26#include <strings.h> 27#include <unistd.h> 28#include <sys/types.h> 29#include <sys/stat.h> 30#include <sys/param.h> 31#ifndef __OPENSTEP__ 32#include <fts.h> 33#endif 34#include <sys/errno.h> 35#include "stuff/bool.h" 36#include "stuff/SymLoc.h" 37#include "stuff/ofile.h" 38#include "stuff/errors.h" 39#include "stuff/allocate.h" 40#include "stuff/dylib_roots.h" 41 42struct check_block { 43 char *install_name; 44 enum bool check_result; 45}; 46 47static void check_for_dylib( 48 struct ofile *ofile, 49 char *arch_name, 50 void *cookie); 51 52char * 53get_symfile_for_dylib( 54char *install_name, 55char *release_name, 56enum bool *found_project, 57enum bool disablewarnings, 58enum bool no_error_if_missing) 59{ 60 const char *symroot; 61 62 symroot = symLocForDylib(install_name, release_name, found_project, 63 disablewarnings, no_error_if_missing); 64 if(symroot == NULL) 65 return(NULL); 66 return(find_dylib_in_root(install_name, symroot)); 67} 68 69char * 70get_dstfile_for_dylib( 71char *install_name, 72char *release_name, 73enum bool *found_project, 74enum bool disablewarnings, 75enum bool no_error_if_missing) 76{ 77 const char *dstroot; 78 char *image_file_name; 79 struct check_block block; 80 struct stat stat_buf; 81 82 dstroot = dstLocForDylib(install_name, release_name, found_project, 83 disablewarnings, no_error_if_missing); 84 if(dstroot == NULL) 85 return(NULL); 86 87 if(*install_name == '/'){ 88 image_file_name = makestr(dstroot, install_name, NULL); 89 block.install_name = install_name; 90 block.check_result = TRUE; 91 /* 92 * To avoid the error message generated by ofile_process() if the 93 * file does not exist just move on to trying to find it in the 94 * dstroot. 95 */ 96 if(disablewarnings == TRUE){ 97 if(stat(image_file_name, &stat_buf) == -1){ 98 free(image_file_name); 99 goto try_to_find_in_dstroot; 100 } 101 } 102 ofile_process(image_file_name, NULL, 0, TRUE, 103 TRUE, TRUE, FALSE, check_for_dylib, &block); 104 if(block.check_result == TRUE) 105 return(image_file_name); 106 free(image_file_name); 107 } 108try_to_find_in_dstroot: 109 return(find_dylib_in_root(install_name, dstroot)); 110 return(NULL); 111} 112 113char * 114find_dylib_in_root( 115char *install_name, 116const char *root) 117{ 118#ifndef __OPENSTEP__ 119 char *base_name, start[MAXPATHLEN + 1], *image_file_name; 120 char const *paths[2]; 121 FTS *fts; 122 FTSENT *ftsent; 123 struct check_block block; 124 125 block.install_name = install_name; 126 block.check_result = FALSE; 127 128#ifdef BIG_DEBUG 129 printf("In find_dylib_in_root(install_name = %s, root = %s)\n", 130 install_name, root); 131#endif 132 if(realpath(root, start) == NULL){ 133#ifdef DEBUG 134 printf("realpath() failed for: %s (%s, errno = %d)\n", root, 135 strerror(errno), errno); 136#endif 137 return(NULL); 138 } 139#ifdef BIG_DEBUG 140 printf("realpath() = %s for root: %s\n", start, root); 141#endif 142 143 base_name = strrchr(install_name, '/'); 144 if(base_name == NULL || base_name[1] == '\0') 145 base_name = install_name; 146 else 147 base_name = base_name + 1; 148 149 paths[0] = start; 150 paths[1] = NULL; 151 fts = fts_open((char * const *)paths, FTS_PHYSICAL, NULL); 152 if(fts == NULL){ 153#ifdef DEBUG 154 printf("fts_open() failed for: %s (%s, errno = %d)\n", start, 155 strerror(errno), errno); 156#endif 157 return(NULL); 158 } 159 160 while((ftsent = fts_read(fts)) != NULL){ 161#ifdef BIG_DEBUG 162 printf("fts_path = %s fts_name = %s\n", 163 ftsent->fts_path, ftsent->fts_name); 164#endif 165 if(S_ISREG(ftsent->fts_statp->st_mode) && 166 !S_ISLNK(ftsent->fts_statp->st_mode) && 167 strcmp(base_name, ftsent->fts_name) == 0){ 168#ifdef BIG_DEBUG 169 printf("got a match: fts_path = %s fts_name = %s\n", 170 ftsent->fts_path, ftsent->fts_name); 171#endif 172 /* 173 * Now that we found a file with the same base_name in the root 174 * check to see that it is a dynamic library. Assume it is an 175 * if it is not then the routine check_for_dylib() will 176 * reset the check_result in the block passed to 177 * it back to FALSE. 178 */ 179 block.check_result = TRUE; 180 ofile_process(ftsent->fts_path, NULL, 0, TRUE, 181 TRUE, TRUE, FALSE, check_for_dylib,&block); 182 if(block.check_result == TRUE){ 183 image_file_name = allocate(ftsent->fts_pathlen + 1); 184 strcpy(image_file_name, ftsent->fts_path); 185#ifdef BIG_DEBUG 186 printf("returning %s\n", image_file_name); 187#endif 188 if(fts_close(fts) == -1) 189 system_error("fts_close() failed"); 190 return(image_file_name); 191 } 192 } 193 } 194 if(errno != 0){ 195#ifdef DEBUG 196 printf("fts_read() failed for (%s, errno = %d)\n", 197 strerror(errno), errno); 198#endif 199 if(fts_close(fts) == -1) 200 system_error("fts_close() failed"); 201 return(NULL); 202 } 203 if(fts_close(fts) == -1){ 204 system_error("fts_close() failed"); 205 return(NULL); 206 } 207 208#endif /* !defined(__OPENSTEP___) */ 209 210 return(NULL); 211} 212 213static 214void 215check_for_dylib( 216struct ofile *ofile, 217char *arch_name, 218void *cookie) 219{ 220 uint32_t i; 221 struct check_block *block; 222 struct load_command *lc; 223 uint32_t ncmds; 224 225#ifdef BIG_DEBUG 226 printf("In check_for_dylib() ofile->file_name = %s", 227 ofile->file_name); 228 if(arch_name != NULL) 229 printf(" arch_name = %s\n", arch_name); 230 else 231 printf("\n"); 232#endif /* BIG_DEBUG */ 233 234 block = (struct check_block *)cookie; 235 if(ofile->mh != NULL){ 236 ncmds = ofile->mh->ncmds; 237 } else if (ofile->mh64 != NULL) { 238 ncmds = ofile->mh64->ncmds; 239 } else { 240 block->check_result = FALSE; 241 return; 242 } 243 244 lc = ofile->load_commands; 245 for(i = 0; i < ncmds; i++){ 246 if(lc->cmd == LC_ID_DYLIB){ 247 return; 248 } 249 lc = (struct load_command *)((char *)lc + lc->cmdsize); 250 } 251 block->check_result = FALSE; 252 return; 253} 254#endif /* !defined(RLD) */ 255