2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
27 #include <sys/types.h>
30 #include <mach/mach.h>
32 #include "stuff/bool.h"
33 #include "stuff/ofile.h"
34 #include "stuff/errors.h"
35 #include "stuff/allocate.h"
36 #include "stuff/dylib_table.h"
37 /* This may change to "/MacOSX/System" someday */
38 #define SYSTEM_LIBRARY "/System/Library"
41 * parse_dylib_table() opens the file_name passed to it and parses it as a
42 * dylib table. The flag and argument parameters are used for error messages
43 * if there is a problem parsing the file. The file should
44 * contains lines of the form:
45 * <hex address> <short name>
46 * The fields are to be separated by spaces or tabs. Lines with just spaces
47 * and tabs are ignored. This routine returns the parsed table as an
48 * array of dylib_table structs and returns a pointer to the table. The last
49 * entry in the table has a NULL name.
53 char *file_name
,/* file name of dylib table file */
54 char *flag
, /* "-dylib_file" or "default" */
55 char *argument
) /* -dylib_file argument or "dylib table" */
59 uint32_t j
, k
, file_size
, new_dylib_table_size
;
60 char *file_addr
, *endp
;
61 struct dylib_table
*new_dylib_table
;
63 if((fd
= open(file_name
, O_RDONLY
, 0)) == -1)
64 system_fatal("Can't open: %s for %s %s",
65 file_name
, flag
, argument
);
66 if(fstat(fd
, &stat_buf
) == -1)
67 system_fatal("Can't stat file: %s for %s %s",
68 file_name
, flag
, argument
);
70 * For some reason mapping files with zero size fails
71 * so it has to be handled specially.
74 if(stat_buf
.st_size
!= 0){
75 file_addr
= mmap(0, stat_buf
.st_size
, PROT_READ
|PROT_WRITE
,
76 MAP_FILE
|MAP_PRIVATE
, fd
, 0);
77 if((intptr_t)file_addr
== -1)
78 system_error("can't map file: %s for %s %s", file_name
, flag
,
82 fatal("Empty file: %s for %s %s", file_name
, flag
, argument
);
84 file_size
= stat_buf
.st_size
;
87 * Got the file mapped now parse it.
89 if(file_addr
[file_size
- 1] != '\n')
90 fatal("file: %s for %s %s does not end in new line",
91 file_name
, flag
, argument
);
92 new_dylib_table_size
= 0;
93 for(j
= 1; j
< file_size
; j
++){
94 if(file_addr
[j
] == '\n'){
95 new_dylib_table_size
++;
98 new_dylib_table_size
++;
99 new_dylib_table
= allocate(sizeof(struct dylib_table
) *
100 new_dylib_table_size
);
102 for(j
= 0; j
< file_size
; /* no increment expression */ ){
103 /* Skip blank lines */
104 while(file_addr
[j
] == ' ' || file_addr
[j
] == '\t')
106 if(file_addr
[j
] == '\n'){
110 new_dylib_table
[k
].seg1addr
=
111 strtoul(file_addr
+ j
, &endp
, 16);
113 fatal("improper hexadecimal number on line %u in "
114 "file: %s for %s %s", j
, file_name
, flag
, argument
);
115 j
= endp
- file_addr
;
117 fatal("missing library name on line %u in file: "
118 "%s for %s %s", j
, file_name
, flag
, argument
);
120 * Since we checked to see the file ends in a '\n' we can
121 * be assured this won't run off the end of the file.
123 while(file_addr
[j
] == ' ' || file_addr
[j
] == '\t')
125 if(file_addr
[j
] == '\n')
126 fatal("missing library name on line %u in file: "
127 "%s for %s %s", j
, file_name
, flag
, argument
);
128 new_dylib_table
[k
].name
= file_addr
+ j
;
130 while(file_addr
[j
] != '\n')
135 new_dylib_table
[k
].seg1addr
= 0;
136 new_dylib_table
[k
].name
= NULL
;
137 return(new_dylib_table
);
141 * parse_default_dylib_table() opens and parses ~rc/Data/DylibTable .
144 parse_default_dylib_table(
150 *file_name
= allocate(MAXPATHLEN
+1);
151 fp
= popen("/bin/echo ~rc/Data/DylibTable", "r");
153 fatal("must use -dylib_table (popen failed on \"/bin/echo "
154 "~rc/Data/DylibTable\"");
155 if(fgets(*file_name
, MAXPATHLEN
, fp
) == NULL
)
156 fatal("must use -dylib_table (fgets failed from popen of "
157 "\"/bin/echo ~rc/Data/DylibTable\"");
158 i
= strlen(*file_name
);
159 if(i
== 0 || (*file_name
)[i
-1] != '\n')
160 fatal("must use -dylib_table (file name from popen of "
161 "\"/bin/echo ~rc/Data/DylibTable\" greater than "
163 (*file_name
)[i
-1] = '\0';
165 return(parse_dylib_table(*file_name
, "default", "dylib table"));
169 * search_dylib_table() searches the specified dylib table for the specified
170 * name and returns the entry to it if it is found. If it is not found NULL
175 struct dylib_table
*dylib_table
,
178 struct dylib_table
*p
;
180 if(dylib_table
== NULL
)
183 for(p
= dylib_table
; p
->name
!= NULL
; p
++){
184 if(strcmp(p
->name
, name
) == 0)
190 static char *versions
[] = { "A", "B", "C", "0", NULL
};
193 * guess_dylib_install_name() is passed a name from the dylib file and then
194 * the install name is guessed based on the files on the system the program is
195 * running on. This routines makes up conventional install names base on the
196 * name passed in and then sees if there is a file on the system with that
197 * install_name. If it finds one it returns the install_name else it returns
201 guess_dylib_install_name(
206 struct stat stat_buf
;
208 for(i
= 0; versions
[i
] != NULL
; i
++){
210 SYSTEM_LIBRARY
,"/Frameworks/JavaVM.framework/Libraries/lib",
211 name
, ".", versions
[i
], ".dylib", NULL
);
212 if(stat(guess
, &stat_buf
) != -1)
217 for(i
= 0; versions
[i
] != NULL
; i
++){
218 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/", name
,
219 ".framework/Versions/", versions
[i
], "/", name
, NULL
);
220 if(stat(guess
, &stat_buf
) != -1)
225 for(i
= 0; versions
[i
] != NULL
; i
++){
226 guess
= makestr(SYSTEM_LIBRARY
,"/PrivateFrameworks/", name
,
227 ".framework/Versions/", versions
[i
], "/", name
, NULL
);
228 if(stat(guess
, &stat_buf
) != -1)
233 for(i
= 0; versions
[i
] != NULL
; i
++){
234 guess
= makestr(SYSTEM_LIBRARY
,"Printers/", name
, ".",
235 versions
[i
],".dylib", NULL
);
236 if(stat(guess
, &stat_buf
) != -1)
241 for(i
= 0; versions
[i
] != NULL
; i
++){
242 #ifdef __GONZO_BUNSEN_BEAKER__
243 guess
= makestr("/Local/Library/Frameworks/", name
,
244 ".framework/Versions/", versions
[i
], "/", name
, NULL
);
246 guess
= makestr("/MacOSX/Library/Frameworks/", name
,
247 ".framework/Versions/", versions
[i
], "/", name
, NULL
);
249 if(stat(guess
, &stat_buf
) != -1)
254 #ifndef __GONZO_BUNSEN_BEAKER__
255 for(i
= 0; versions
[i
] != NULL
; i
++){
256 guess
= makestr("/AppleInternal/Library/Frameworks/", name
,
257 ".framework/Versions/", versions
[i
], "/", name
, NULL
);
258 if(stat(guess
, &stat_buf
) != -1)
264 for(i
= 0; versions
[i
] != NULL
; i
++){
265 guess
= makestr("/lib/", name
, ".", versions
[i
], ".dylib", NULL
);
266 if(stat(guess
, &stat_buf
) != -1)
271 for(i
= 0; versions
[i
] != NULL
; i
++){
272 guess
= makestr("/usr/lib/", name
, ".", versions
[i
], ".dylib",
274 if(stat(guess
, &stat_buf
) != -1)
279 for(i
= 0; versions
[i
] != NULL
; i
++){
280 guess
= makestr("/usr/lib/java/", name
, ".", versions
[i
],
282 if(stat(guess
, &stat_buf
) != -1)
287 for(i
= 0; versions
[i
] != NULL
; i
++){
288 guess
= makestr("/usr/local/lib/", name
, ".", versions
[i
],
290 if(stat(guess
, &stat_buf
) != -1)
295 for(i
= 0; versions
[i
] != NULL
; i
++){
296 guess
= makestr("/usr/canna/dylib/", name
, ".", versions
[i
],
298 if(stat(guess
, &stat_buf
) != -1)
302 /* From ALLOW_MACOSX_PR1_PATHS */
303 for(i
= 0; versions
[i
] != NULL
; i
++){
304 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/CarbonCore.framework/"
305 "Versions/", versions
[i
], "/Support/", name
,
307 if(stat(guess
, &stat_buf
) != -1)
311 for(i
= 0; versions
[i
] != NULL
; i
++){
312 guess
= makestr(SYSTEM_LIBRARY
,"Frameworks/Carbon.framework/"
313 "Versions/", versions
[i
], "/Libraries/", name
,
315 if(stat(guess
, &stat_buf
) != -1)
319 for(i
= 0; versions
[i
] != NULL
; i
++){
320 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/CoreGraphics.framework/"
321 "Versions/", versions
[i
], "/Libraries/", name
, ".",
322 versions
[i
], ".dylib", NULL
);
323 if(stat(guess
, &stat_buf
) != -1)
327 /* From ALLOW_MACOSX_DP3_PATHS */
328 for(i
= 0; versions
[i
] != NULL
; i
++){
329 guess
= makestr(SYSTEM_LIBRARY
,"/Components/", name
, ".qtx", NULL
);
330 if(stat(guess
, &stat_buf
) != -1)
334 for(i
= 0; versions
[i
] != NULL
; i
++){
335 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/Carbon.framework/"
336 "Versions/", versions
[i
], "/Resources//", name
,
338 if(stat(guess
, &stat_buf
) != -1)
342 for(i
= 0; versions
[i
] != NULL
; i
++){
343 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/CoreGraphics.framework/"
344 "Versions/", versions
[i
], "/Resources/", name
, ".",
345 versions
[i
], ".qtx", NULL
);
346 if(stat(guess
, &stat_buf
) != -1)
350 for(i
= 0; versions
[i
] != NULL
; i
++){
351 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/JavaVM.framework/"
352 "Versions/1.2/Libraries/", name
, ".", versions
[i
],
354 if(stat(guess
, &stat_buf
) != -1)
358 for(i
= 0; versions
[i
] != NULL
; i
++){
359 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/PrintingCore.framework/"
360 "Versions/", versions
[i
], "/Libraries/", name
, ".",
361 versions
[i
], ".dylib", NULL
);
362 if(stat(guess
, &stat_buf
) != -1)
366 for(i
= 0; versions
[i
] != NULL
; i
++){
367 guess
= makestr(SYSTEM_LIBRARY
,"/Frameworks/QuickTime.framework/"
368 "Versions/", versions
[i
], "/", name
, NULL
);
369 if(stat(guess
, &stat_buf
) != -1)
376 #endif /* !defined(RLD) */