Commit | Line | Data |
---|---|---|
1136f72d | 1 | /* |
dda1245a | 2 | * $Id: shlib.c,v 1.6 1993/12/11 11:58:29 jkh Exp $ |
1136f72d PR |
3 | */ |
4 | ||
5 | #include <sys/param.h> | |
6 | #include <stdio.h> | |
7 | #include <stdlib.h> | |
8 | #include <sys/types.h> | |
9 | #include <sys/stat.h> | |
10 | #include <sys/file.h> | |
11 | #include <sys/time.h> | |
12 | #include <fcntl.h> | |
13 | #include <string.h> | |
0f052032 | 14 | #include <ctype.h> |
1136f72d PR |
15 | #include <dirent.h> |
16 | #include <a.out.h> | |
17 | ||
18 | #include "ld.h" | |
19 | ||
0f052032 JH |
20 | #ifdef SUNOS4 |
21 | char *strsep(); | |
22 | #endif | |
23 | ||
1136f72d PR |
24 | /* |
25 | * Standard directories to search for files specified by -l. | |
26 | */ | |
27 | #ifndef STANDARD_SEARCH_DIRS | |
dda1245a | 28 | #define STANDARD_SEARCH_DIRS "/usr/lib" |
1136f72d PR |
29 | #endif |
30 | ||
31 | char *standard_search_dirs[] = { | |
32 | STANDARD_SEARCH_DIRS | |
33 | }; | |
34 | ||
35 | int n_search_dirs; | |
36 | ||
37 | void | |
38 | add_search_dir(name) | |
39 | char *name; | |
40 | { | |
41 | n_search_dirs++; | |
42 | search_dirs = (char **)xrealloc(search_dirs, | |
43 | n_search_dirs * sizeof(char *)); | |
44 | search_dirs[n_search_dirs - 1] = strdup(name); | |
45 | } | |
46 | ||
47 | void | |
48 | std_search_dirs(paths) | |
49 | char *paths; | |
50 | { | |
51 | char *cp; | |
52 | int i, n; | |
53 | ||
54 | if (paths != NULL) | |
55 | /* Add search directories from `paths' */ | |
7fc7155d | 56 | while ((cp = strsep(&paths, ":")) != NULL) { |
1136f72d | 57 | add_search_dir(cp); |
7fc7155d PR |
58 | if (paths) |
59 | *(paths-1) = ':'; | |
1136f72d PR |
60 | } |
61 | ||
62 | /* Append standard search directories */ | |
63 | n = sizeof standard_search_dirs / sizeof standard_search_dirs[0]; | |
64 | for (i = 0; i < n; i++) | |
65 | add_search_dir(standard_search_dirs[i]); | |
66 | } | |
67 | ||
68 | /* | |
69 | * Return true if CP points to a valid dewey number. | |
70 | * Decode and leave the result in the array DEWEY. | |
71 | * Return the number of decoded entries in DEWEY. | |
72 | */ | |
73 | ||
74 | int | |
75 | getdewey(dewey, cp) | |
76 | int dewey[]; | |
77 | char *cp; | |
78 | { | |
79 | int i, n; | |
80 | ||
81 | for (n = 0, i = 0; i < MAXDEWEY; i++) { | |
82 | if (*cp == '\0') | |
83 | break; | |
84 | ||
85 | if (*cp == '.') cp++; | |
86 | if (!isdigit(*cp)) | |
87 | return 0; | |
88 | ||
89 | dewey[n++] = strtol(cp, &cp, 10); | |
90 | } | |
91 | ||
92 | return n; | |
93 | } | |
94 | ||
95 | /* | |
96 | * Compare two dewey arrays. | |
97 | * Return -1 if `d1' represents a smaller value than `d2'. | |
98 | * Return 1 if `d1' represents a greater value than `d2'. | |
99 | * Return 0 if equal. | |
100 | */ | |
101 | int | |
102 | cmpndewey(d1, n1, d2, n2) | |
103 | int d1[], d2[]; | |
104 | int n1, n2; | |
105 | { | |
106 | int i; | |
107 | ||
108 | for (i = 0; i < n1 && i < n2; i++) { | |
109 | if (d1[i] < d2[i]) | |
110 | return -1; | |
111 | if (d1[i] > d2[i]) | |
112 | return 1; | |
113 | } | |
114 | ||
115 | if (n1 == n2) | |
116 | return 0; | |
117 | ||
118 | if (i == n1) | |
119 | return -1; | |
120 | ||
121 | if (i == n2) | |
122 | return 1; | |
123 | } | |
124 | ||
125 | /* | |
126 | * Search directories for a shared library matching the given | |
127 | * major and minor version numbers. | |
128 | * | |
129 | * MAJOR == -1 && MINOR == -1 --> find highest version | |
130 | * MAJOR != -1 && MINOR == -1 --> find highest minor version | |
131 | * MAJOR == -1 && MINOR != -1 --> invalid | |
132 | * MAJOR != -1 && MINOR != -1 --> find highest micro version | |
133 | */ | |
134 | ||
135 | /* Not interested in devices right now... */ | |
136 | #undef major | |
137 | #undef minor | |
138 | ||
139 | char * | |
0f052032 | 140 | findshlib(name, majorp, minorp, do_dot_a) |
1136f72d PR |
141 | char *name; |
142 | int *majorp, *minorp; | |
0f052032 | 143 | int do_dot_a; |
1136f72d PR |
144 | { |
145 | int dewey[MAXDEWEY]; | |
146 | int ndewey; | |
147 | int tmp[MAXDEWEY]; | |
148 | int i; | |
149 | int len; | |
150 | char *lname, *path = NULL; | |
151 | int major = *majorp, minor = *minorp; | |
152 | ||
153 | len = strlen(name); | |
154 | lname = (char *)alloca(len + sizeof("lib")); | |
155 | sprintf(lname, "lib%s", name); | |
156 | len += 3; | |
157 | ||
158 | ndewey = 0; | |
159 | ||
160 | for (i = 0; i < n_search_dirs; i++) { | |
161 | DIR *dd = opendir(search_dirs[i]); | |
162 | struct dirent *dp; | |
0f052032 | 163 | int found_dot_a = 0; |
1136f72d PR |
164 | |
165 | if (dd == NULL) | |
166 | continue; | |
167 | ||
168 | while ((dp = readdir(dd)) != NULL) { | |
169 | int n, j, might_take_it = 0; | |
170 | ||
0f052032 JH |
171 | if (do_dot_a && path == NULL && |
172 | dp->d_namlen == len + 2 && | |
173 | strncmp(dp->d_name, lname, len) == 0 && | |
174 | (dp->d_name+len)[0] == '.' && | |
175 | (dp->d_name+len)[1] == 'a') { | |
176 | ||
177 | path = concat(search_dirs[i], "/", dp->d_name); | |
178 | found_dot_a = 1; | |
179 | } | |
180 | ||
1136f72d PR |
181 | if (dp->d_namlen < len + 4) |
182 | continue; | |
183 | if (strncmp(dp->d_name, lname, len) != 0) | |
184 | continue; | |
185 | if (strncmp(dp->d_name+len, ".so.", 4) != 0) | |
186 | continue; | |
187 | ||
188 | if ((n = getdewey(tmp, dp->d_name+len+4)) == 0) | |
189 | continue; | |
190 | ||
0f052032 JH |
191 | if (major != -1 && found_dot_a) { /* XXX */ |
192 | free(path); | |
193 | path = NULL; | |
194 | found_dot_a = 0; | |
195 | } | |
196 | ||
1136f72d PR |
197 | if (major == -1 && minor == -1) { |
198 | might_take_it = 1; | |
199 | } else if (major != -1 && minor == -1) { | |
200 | if (tmp[0] == major) | |
201 | might_take_it = 1; | |
202 | } else if (major != -1 && minor != -1) { | |
203 | if (tmp[0] == major) | |
204 | if (n == 1 || tmp[1] >= minor) | |
205 | might_take_it = 1; | |
206 | } | |
207 | ||
208 | if (!might_take_it) | |
209 | continue; | |
210 | ||
211 | if (cmpndewey(tmp, n, dewey, ndewey) <= 0) | |
212 | continue; | |
213 | ||
214 | /* We have a better version */ | |
215 | if (path) | |
216 | free(path); | |
217 | path = concat(search_dirs[i], "/", dp->d_name); | |
0f052032 | 218 | found_dot_a = 0; |
1136f72d PR |
219 | bcopy(tmp, dewey, sizeof(dewey)); |
220 | ndewey = n; | |
221 | *majorp = dewey[0]; | |
222 | *minorp = dewey[1]; | |
223 | } | |
224 | closedir(dd); | |
0f052032 JH |
225 | |
226 | if (found_dot_a) | |
227 | /* | |
228 | * There's a .a archive here. | |
229 | */ | |
230 | return path; | |
1136f72d PR |
231 | } |
232 | ||
233 | return path; | |
234 | } |