cctools-port/cctools/libstuff/dylib_roots.c
Keno Fischer 90214560fa Port to musl libc
Mostly make sure not to use a few glibc-isms. I should note that cctools'
ar doesn't work properly when built against musl. I didn't investigate
further because dropping in llvm-ar works just fine. The error you see
with the broken ar is:

```
`x86_64-apple-darwin14-ranlib: archive member: libgcc.a(3) size too large (archive member extends past the end of the file)`
```
2017-10-26 15:25:21 -04:00

257 lines
6.5 KiB
C

/*
* 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>
#if defined(__APPLE__) || defined(__GLIBC__) || defined(__MINGW32__)
#define HAVE_FTS
#include <fts.h>
#endif
#include <sys/errno.h>
#include <errno.h> /* cctools-port */
#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)
{
#ifdef HAVE_FTS
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) */