2013-11-14 19:36:34 +00:00
|
|
|
/*
|
|
|
|
* 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 <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/param.h>
|
2017-10-25 20:58:12 +00:00
|
|
|
#if defined(__APPLE__) || defined(__GLIBC__) || defined(__MINGW32__)
|
|
|
|
#define HAVE_FTS
|
2013-11-14 19:36:34 +00:00
|
|
|
#include <fts.h>
|
|
|
|
#endif
|
|
|
|
#include <sys/errno.h>
|
2015-07-11 06:45:49 +00:00
|
|
|
#include <errno.h> /* cctools-port */
|
2013-11-14 19:36:34 +00:00
|
|
|
#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)
|
|
|
|
{
|
2017-10-25 20:58:12 +00:00
|
|
|
#ifdef HAVE_FTS
|
2013-11-14 19:36:34 +00:00
|
|
|
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) */
|