diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-09-22 20:10:13 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-09-22 20:10:13 +0000 |
commit | 6bf8c4eb84101e24cb2cafbebf6aab8d3873de38 (patch) | |
tree | fd81f0505d462116b3597f2b9e8c0646c5324098 | |
parent | 3a018e2d1b57cd25d7c64d4470dc14a26851a239 (diff) | |
download | libextractor-6bf8c4eb84101e24cb2cafbebf6aab8d3873de38.tar.gz libextractor-6bf8c4eb84101e24cb2cafbebf6aab8d3873de38.zip |
-dos2unix
-rw-r--r-- | src/main/extractor_plugpath.c | 1326 |
1 files changed, 663 insertions, 663 deletions
diff --git a/src/main/extractor_plugpath.c b/src/main/extractor_plugpath.c index 157b59c..8bb9a2d 100644 --- a/src/main/extractor_plugpath.c +++ b/src/main/extractor_plugpath.c | |||
@@ -1,663 +1,663 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libextractor. | 2 | This file is part of libextractor. |
3 | (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff | 3 | (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff |
4 | 4 | ||
5 | libextractor is free software; you can redistribute it and/or modify | 5 | libextractor is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
7 | by the Free Software Foundation; either version 3, or (at your | 7 | by the Free Software Foundation; either version 3, or (at your |
8 | option) any later version. | 8 | option) any later version. |
9 | 9 | ||
10 | libextractor is distributed in the hope that it will be useful, but | 10 | libextractor is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU General Public License |
16 | along with libextractor; see the file COPYING. If not, write to the | 16 | along with libextractor; see the file COPYING. If not, write to the |
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 | Boston, MA 02111-1307, USA. | 18 | Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file main/extractor_plugpath.c | 21 | * @file main/extractor_plugpath.c |
22 | * @brief determine path where plugins are installed | 22 | * @brief determine path where plugins are installed |
23 | * @author Christian Grothoff | 23 | * @author Christian Grothoff |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include "platform.h" | 26 | #include "platform.h" |
27 | #include "plibc.h" | 27 | #include "plibc.h" |
28 | #include "extractor.h" | 28 | #include "extractor.h" |
29 | #include <dirent.h> | 29 | #include <dirent.h> |
30 | #include <sys/types.h> | 30 | #include <sys/types.h> |
31 | #include <signal.h> | 31 | #include <signal.h> |
32 | #include <ltdl.h> | 32 | #include <ltdl.h> |
33 | 33 | ||
34 | #include "extractor_plugpath.h" | 34 | #include "extractor_plugpath.h" |
35 | #include "extractor_logging.h" | 35 | #include "extractor_logging.h" |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * Function to call on paths. | 38 | * Function to call on paths. |
39 | * | 39 | * |
40 | * @param cls closure | 40 | * @param cls closure |
41 | * @param path a directory path | 41 | * @param path a directory path |
42 | */ | 42 | */ |
43 | typedef void (*EXTRACTOR_PathProcessor) (void *cls, | 43 | typedef void (*EXTRACTOR_PathProcessor) (void *cls, |
44 | const char *path); | 44 | const char *path); |
45 | 45 | ||
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Remove a trailing '/bin/' from 'in' (if present). | 48 | * Remove a trailing '/bin/' from 'in' (if present). |
49 | * | 49 | * |
50 | * @param in input string, modified | 50 | * @param in input string, modified |
51 | * @return NULL if 'in' is NULL, otherwise 'in' with '/bin/' removed | 51 | * @return NULL if 'in' is NULL, otherwise 'in' with '/bin/' removed |
52 | */ | 52 | */ |
53 | static char * | 53 | static char * |
54 | cut_bin (char * in) | 54 | cut_bin (char * in) |
55 | { | 55 | { |
56 | size_t p; | 56 | size_t p; |
57 | 57 | ||
58 | if (NULL == in) | 58 | if (NULL == in) |
59 | return NULL; | 59 | return NULL; |
60 | p = strlen (in); | 60 | p = strlen (in); |
61 | if (p < 4) | 61 | if (p < 4) |
62 | return in; | 62 | return in; |
63 | if ( ('/' == in[p-1]) || | 63 | if ( ('/' == in[p-1]) || |
64 | ('\\' == in[p-1]) ) | 64 | ('\\' == in[p-1]) ) |
65 | in[--p] = '\0'; | 65 | in[--p] = '\0'; |
66 | if (0 == strcmp (&in[p-4], | 66 | if (0 == strcmp (&in[p-4], |
67 | "/bin")) | 67 | "/bin")) |
68 | { | 68 | { |
69 | in[p-4] = '\0'; | 69 | in[p-4] = '\0'; |
70 | p -= 4; | 70 | p -= 4; |
71 | } | 71 | } |
72 | else if (0 == strcmp (&in[p-4], | 72 | else if (0 == strcmp (&in[p-4], |
73 | "\\bin")) | 73 | "\\bin")) |
74 | { | 74 | { |
75 | in[p-4] = '\0'; | 75 | in[p-4] = '\0'; |
76 | p -= 4; | 76 | p -= 4; |
77 | } | 77 | } |
78 | return in; | 78 | return in; |
79 | } | 79 | } |
80 | 80 | ||
81 | 81 | ||
82 | #if GNU_LINUX | 82 | #if GNU_LINUX |
83 | /** | 83 | /** |
84 | * Try to determine path by reading /proc/PID/exe or | 84 | * Try to determine path by reading /proc/PID/exe or |
85 | * /proc/PID/maps. | 85 | * /proc/PID/maps. |
86 | * | 86 | * |
87 | * Note that this may fail if LE is installed in one directory | 87 | * Note that this may fail if LE is installed in one directory |
88 | * and the binary linking against it sits elsewhere. | 88 | * and the binary linking against it sits elsewhere. |
89 | */ | 89 | */ |
90 | static char * | 90 | static char * |
91 | get_path_from_proc_exe () | 91 | get_path_from_proc_exe () |
92 | { | 92 | { |
93 | char fn[64]; | 93 | char fn[64]; |
94 | char line[1024]; | 94 | char line[1024]; |
95 | char dir[1024]; | 95 | char dir[1024]; |
96 | char *lnk; | 96 | char *lnk; |
97 | char *ret; | 97 | char *ret; |
98 | char *lestr; | 98 | char *lestr; |
99 | ssize_t size; | 99 | ssize_t size; |
100 | FILE *f; | 100 | FILE *f; |
101 | 101 | ||
102 | snprintf (fn, | 102 | snprintf (fn, |
103 | sizeof (fn), | 103 | sizeof (fn), |
104 | "/proc/%u/maps", | 104 | "/proc/%u/maps", |
105 | getpid ()); | 105 | getpid ()); |
106 | if (NULL != (f = FOPEN (fn, "r"))) | 106 | if (NULL != (f = FOPEN (fn, "r"))) |
107 | { | 107 | { |
108 | while (NULL != fgets (line, 1024, f)) | 108 | while (NULL != fgets (line, 1024, f)) |
109 | { | 109 | { |
110 | if ( (1 == sscanf (line, | 110 | if ( (1 == sscanf (line, |
111 | "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s", | 111 | "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s", |
112 | dir)) && | 112 | dir)) && |
113 | (NULL != (lestr = strstr (dir, | 113 | (NULL != (lestr = strstr (dir, |
114 | "libextractor")) ) ) | 114 | "libextractor")) ) ) |
115 | { | 115 | { |
116 | lestr[0] = '\0'; | 116 | lestr[0] = '\0'; |
117 | fclose (f); | 117 | fclose (f); |
118 | return strdup (dir); | 118 | return strdup (dir); |
119 | } | 119 | } |
120 | } | 120 | } |
121 | fclose (f); | 121 | fclose (f); |
122 | } | 122 | } |
123 | snprintf (fn, | 123 | snprintf (fn, |
124 | sizeof (fn), | 124 | sizeof (fn), |
125 | "/proc/%u/exe", | 125 | "/proc/%u/exe", |
126 | getpid ()); | 126 | getpid ()); |
127 | if (NULL == (lnk = malloc (1029))) /* 1024 + 6 for "/lib/" catenation */ | 127 | if (NULL == (lnk = malloc (1029))) /* 1024 + 6 for "/lib/" catenation */ |
128 | return NULL; | 128 | return NULL; |
129 | size = readlink (fn, lnk, 1023); | 129 | size = readlink (fn, lnk, 1023); |
130 | if ( (size <= 0) || (size >= 1024) ) | 130 | if ( (size <= 0) || (size >= 1024) ) |
131 | { | 131 | { |
132 | free (lnk); | 132 | free (lnk); |
133 | return NULL; | 133 | return NULL; |
134 | } | 134 | } |
135 | lnk[size] = '\0'; | 135 | lnk[size] = '\0'; |
136 | while ( ('/' != lnk[size]) && | 136 | while ( ('/' != lnk[size]) && |
137 | (size > 0) ) | 137 | (size > 0) ) |
138 | size--; | 138 | size--; |
139 | if ( (size < 4) || | 139 | if ( (size < 4) || |
140 | ('/' != lnk[size-4]) ) | 140 | ('/' != lnk[size-4]) ) |
141 | { | 141 | { |
142 | /* not installed in "/bin/" -- binary path probably useless */ | 142 | /* not installed in "/bin/" -- binary path probably useless */ |
143 | free (lnk); | 143 | free (lnk); |
144 | return NULL; | 144 | return NULL; |
145 | } | 145 | } |
146 | lnk[size] = '\0'; | 146 | lnk[size] = '\0'; |
147 | lnk = cut_bin (lnk); | 147 | lnk = cut_bin (lnk); |
148 | if (NULL == (ret = realloc (lnk, strlen(lnk) + 6))) | 148 | if (NULL == (ret = realloc (lnk, strlen(lnk) + 6))) |
149 | { | 149 | { |
150 | LOG_STRERROR ("realloc"); | 150 | LOG_STRERROR ("realloc"); |
151 | free (lnk); | 151 | free (lnk); |
152 | return NULL; | 152 | return NULL; |
153 | } | 153 | } |
154 | strcat (ret, "/lib/"); /* guess "lib/" as the library dir */ | 154 | strcat (ret, "/lib/"); /* guess "lib/" as the library dir */ |
155 | return ret; | 155 | return ret; |
156 | } | 156 | } |
157 | #endif | 157 | #endif |
158 | 158 | ||
159 | 159 | ||
160 | #if WINDOWS | 160 | #if WINDOWS |
161 | /** | 161 | /** |
162 | * Try to determine path with win32-specific function | 162 | * Try to determine path with win32-specific function |
163 | */ | 163 | */ |
164 | static char * | 164 | static char * |
165 | get_path_from_module_filename () | 165 | get_path_from_module_filename () |
166 | { | 166 | { |
167 | char *path; | 167 | char *path; |
168 | char *ret; | 168 | char *ret; |
169 | char *idx; | 169 | char *idx; |
170 | 170 | ||
171 | if (NULL == (path = malloc (4103))) /* 4096+nil+6 for "/lib/" catenation */ | 171 | if (NULL == (path = malloc (4103))) /* 4096+nil+6 for "/lib/" catenation */ |
172 | return NULL; | 172 | return NULL; |
173 | GetModuleFileName (NULL, path, 4096); | 173 | GetModuleFileName (NULL, path, 4096); |
174 | idx = path + strlen (path); | 174 | idx = path + strlen (path); |
175 | while ( (idx > path) && | 175 | while ( (idx > path) && |
176 | ('\\' != *idx) && | 176 | ('\\' != *idx) && |
177 | ('/' != *idx) ) | 177 | ('/' != *idx) ) |
178 | idx--; | 178 | idx--; |
179 | *idx = '\0'; | 179 | *idx = '\0'; |
180 | path = cut_bin (path); | 180 | path = cut_bin (path); |
181 | if (NULL == (ret = realloc (path, strlen(path) + 6))) | 181 | if (NULL == (ret = realloc (path, strlen(path) + 6))) |
182 | { | 182 | { |
183 | LOG_STRERROR ("realloc"); | 183 | LOG_STRERROR ("realloc"); |
184 | free (path); | 184 | free (path); |
185 | return NULL; | 185 | return NULL; |
186 | } | 186 | } |
187 | strcat (ret, "/lib/"); /* guess "lib/" as the library dir */ | 187 | strcat (ret, "/lib/"); /* guess "lib/" as the library dir */ |
188 | return ret; | 188 | return ret; |
189 | } | 189 | } |
190 | #endif | 190 | #endif |
191 | 191 | ||
192 | 192 | ||
193 | #if DARWIN | 193 | #if DARWIN |
194 | #include <dlfcn.h> | 194 | #include <dlfcn.h> |
195 | #include <mach-o/dyld.h> | 195 | #include <mach-o/dyld.h> |
196 | 196 | ||
197 | /** | 197 | /** |
198 | * Signature of the '_NSGetExecutablePath" function. | 198 | * Signature of the '_NSGetExecutablePath" function. |
199 | * | 199 | * |
200 | * @param buf where to write the path | 200 | * @param buf where to write the path |
201 | * @param number of bytes available in 'buf' | 201 | * @param number of bytes available in 'buf' |
202 | * @return 0 on success, otherwise desired number of bytes is stored in 'bufsize' | 202 | * @return 0 on success, otherwise desired number of bytes is stored in 'bufsize' |
203 | */ | 203 | */ |
204 | typedef int (*MyNSGetExecutablePathProto) (char *buf, | 204 | typedef int (*MyNSGetExecutablePathProto) (char *buf, |
205 | size_t *bufsize); | 205 | size_t *bufsize); |
206 | 206 | ||
207 | 207 | ||
208 | /** | 208 | /** |
209 | * Try to obtain the path of our executable using '_NSGetExecutablePath'. | 209 | * Try to obtain the path of our executable using '_NSGetExecutablePath'. |
210 | * | 210 | * |
211 | * @return NULL on error | 211 | * @return NULL on error |
212 | */ | 212 | */ |
213 | static char * | 213 | static char * |
214 | get_path_from_NSGetExecutablePath () | 214 | get_path_from_NSGetExecutablePath () |
215 | { | 215 | { |
216 | static char zero; | 216 | static char zero; |
217 | char *path; | 217 | char *path; |
218 | size_t len; | 218 | size_t len; |
219 | MyNSGetExecutablePathProto func; | 219 | MyNSGetExecutablePathProto func; |
220 | 220 | ||
221 | path = NULL; | 221 | path = NULL; |
222 | if (NULL == (func = | 222 | if (NULL == (func = |
223 | (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, | 223 | (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, |
224 | "_NSGetExecutablePath"))) | 224 | "_NSGetExecutablePath"))) |
225 | return NULL; | 225 | return NULL; |
226 | path = &zero; | 226 | path = &zero; |
227 | len = 0; | 227 | len = 0; |
228 | /* get the path len, including the trailing \0 */ | 228 | /* get the path len, including the trailing \0 */ |
229 | (void) func (path, &len); | 229 | (void) func (path, &len); |
230 | if (0 == len) | 230 | if (0 == len) |
231 | return NULL; | 231 | return NULL; |
232 | if (NULL == (path = malloc (len))) | 232 | if (NULL == (path = malloc (len))) |
233 | { | 233 | { |
234 | LOG_STRERROR ("malloc"); | 234 | LOG_STRERROR ("malloc"); |
235 | return NULL; | 235 | return NULL; |
236 | } | 236 | } |
237 | if (0 != func (path, &len)) | 237 | if (0 != func (path, &len)) |
238 | { | 238 | { |
239 | GNUNET_free (path); | 239 | free (path); |
240 | return NULL; | 240 | return NULL; |
241 | } | 241 | } |
242 | len = strlen (path); | 242 | len = strlen (path); |
243 | while ((path[len] != '/') && (len > 0)) | 243 | while ((path[len] != '/') && (len > 0)) |
244 | len--; | 244 | len--; |
245 | path[len] = '\0'; | 245 | path[len] = '\0'; |
246 | return path; | 246 | return path; |
247 | } | 247 | } |
248 | 248 | ||
249 | 249 | ||
250 | /** | 250 | /** |
251 | * Try to obtain the path of our executable using '_dyld_image' API. | 251 | * Try to obtain the path of our executable using '_dyld_image' API. |
252 | * | 252 | * |
253 | * @return NULL on error | 253 | * @return NULL on error |
254 | */ | 254 | */ |
255 | static char * | 255 | static char * |
256 | get_path_from_dyld_image () | 256 | get_path_from_dyld_image () |
257 | { | 257 | { |
258 | const char *path; | 258 | const char *path; |
259 | char *s; | 259 | char *s; |
260 | char *p; | 260 | char *p; |
261 | unsigned int i; | 261 | unsigned int i; |
262 | int c; | 262 | int c; |
263 | 263 | ||
264 | c = _dyld_image_count (); | 264 | c = _dyld_image_count (); |
265 | for (i = 0; i < c; i++) | 265 | for (i = 0; i < c; i++) |
266 | { | 266 | { |
267 | if (((void *) _dyld_get_image_header (i)) != (void *) &_mh_dylib_header) | 267 | if (((void *) _dyld_get_image_header (i)) != (void *) &_mh_dylib_header) |
268 | continue; | 268 | continue; |
269 | path = _dyld_get_image_name (i); | 269 | path = _dyld_get_image_name (i); |
270 | if ( (NULL == path) || (0 == strlen (path)) ) | 270 | if ( (NULL == path) || (0 == strlen (path)) ) |
271 | continue; | 271 | continue; |
272 | if (NULL == (p = strdup (path))) | 272 | if (NULL == (p = strdup (path))) |
273 | { | 273 | { |
274 | LOG_STRERROR ("strdup"); | 274 | LOG_STRERROR ("strdup"); |
275 | return NULL; | 275 | return NULL; |
276 | } | 276 | } |
277 | s = p + strlen (p); | 277 | s = p + strlen (p); |
278 | while ( (s > p) && ('/' != *s) ) | 278 | while ( (s > p) && ('/' != *s) ) |
279 | s--; | 279 | s--; |
280 | s++; | 280 | s++; |
281 | *s = '\0'; | 281 | *s = '\0'; |
282 | return p; | 282 | return p; |
283 | } | 283 | } |
284 | return NULL; | 284 | return NULL; |
285 | } | 285 | } |
286 | #endif | 286 | #endif |
287 | 287 | ||
288 | 288 | ||
289 | /** | 289 | /** |
290 | * Return the actual path to a file found in the current | 290 | * Return the actual path to a file found in the current |
291 | * PATH environment variable. | 291 | * PATH environment variable. |
292 | * | 292 | * |
293 | * @return path to binary, NULL if not found | 293 | * @return path to binary, NULL if not found |
294 | */ | 294 | */ |
295 | static char * | 295 | static char * |
296 | get_path_from_PATH() { | 296 | get_path_from_PATH() { |
297 | struct stat sbuf; | 297 | struct stat sbuf; |
298 | char *path; | 298 | char *path; |
299 | char *pos; | 299 | char *pos; |
300 | char *end; | 300 | char *end; |
301 | char *buf; | 301 | char *buf; |
302 | char *ret; | 302 | char *ret; |
303 | const char *p; | 303 | const char *p; |
304 | 304 | ||
305 | if (NULL == (p = getenv ("PATH"))) | 305 | if (NULL == (p = getenv ("PATH"))) |
306 | return NULL; | 306 | return NULL; |
307 | if (NULL == (path = strdup (p))) /* because we write on it */ | 307 | if (NULL == (path = strdup (p))) /* because we write on it */ |
308 | { | 308 | { |
309 | LOG_STRERROR ("strdup"); | 309 | LOG_STRERROR ("strdup"); |
310 | return NULL; | 310 | return NULL; |
311 | } | 311 | } |
312 | if (NULL == (buf = malloc (strlen (path) + 20))) | 312 | if (NULL == (buf = malloc (strlen (path) + 20))) |
313 | { | 313 | { |
314 | LOG_STRERROR ("malloc"); | 314 | LOG_STRERROR ("malloc"); |
315 | free (path); | 315 | free (path); |
316 | return NULL; | 316 | return NULL; |
317 | } | 317 | } |
318 | pos = path; | 318 | pos = path; |
319 | while (NULL != (end = strchr(pos, ':'))) | 319 | while (NULL != (end = strchr(pos, ':'))) |
320 | { | 320 | { |
321 | *end = '\0'; | 321 | *end = '\0'; |
322 | sprintf (buf, "%s/%s", pos, "extract"); | 322 | sprintf (buf, "%s/%s", pos, "extract"); |
323 | if (0 == stat(buf, &sbuf)) | 323 | if (0 == stat(buf, &sbuf)) |
324 | { | 324 | { |
325 | free (buf); | 325 | free (buf); |
326 | if (NULL == (pos = strdup (pos))) | 326 | if (NULL == (pos = strdup (pos))) |
327 | { | 327 | { |
328 | LOG_STRERROR ("strdup"); | 328 | LOG_STRERROR ("strdup"); |
329 | free (path); | 329 | free (path); |
330 | return NULL; | 330 | return NULL; |
331 | } | 331 | } |
332 | free (path); | 332 | free (path); |
333 | pos = cut_bin (pos); | 333 | pos = cut_bin (pos); |
334 | if (NULL == (ret = realloc (pos, strlen (pos) + 5))) | 334 | if (NULL == (ret = realloc (pos, strlen (pos) + 5))) |
335 | { | 335 | { |
336 | LOG_STRERROR ("realloc"); | 336 | LOG_STRERROR ("realloc"); |
337 | free (pos); | 337 | free (pos); |
338 | return NULL; | 338 | return NULL; |
339 | } | 339 | } |
340 | strcat (ret, "lib/"); | 340 | strcat (ret, "lib/"); |
341 | return ret; | 341 | return ret; |
342 | } | 342 | } |
343 | pos = end + 1; | 343 | pos = end + 1; |
344 | } | 344 | } |
345 | sprintf (buf, "%s/%s", pos, "extract"); | 345 | sprintf (buf, "%s/%s", pos, "extract"); |
346 | if (0 == stat (buf, &sbuf)) | 346 | if (0 == stat (buf, &sbuf)) |
347 | { | 347 | { |
348 | pos = strdup (pos); | 348 | pos = strdup (pos); |
349 | free (buf); | 349 | free (buf); |
350 | free (path); | 350 | free (path); |
351 | if (NULL == pos) | 351 | if (NULL == pos) |
352 | return NULL; | 352 | return NULL; |
353 | pos = cut_bin (pos); | 353 | pos = cut_bin (pos); |
354 | if (NULL == (ret = realloc (pos, strlen (pos) + 5))) | 354 | if (NULL == (ret = realloc (pos, strlen (pos) + 5))) |
355 | { | 355 | { |
356 | LOG_STRERROR ("realloc"); | 356 | LOG_STRERROR ("realloc"); |
357 | free (pos); | 357 | free (pos); |
358 | return NULL; | 358 | return NULL; |
359 | } | 359 | } |
360 | strcat (ret, "lib/"); | 360 | strcat (ret, "lib/"); |
361 | return ret; | 361 | return ret; |
362 | } | 362 | } |
363 | free (buf); | 363 | free (buf); |
364 | free (path); | 364 | free (path); |
365 | return NULL; | 365 | return NULL; |
366 | } | 366 | } |
367 | 367 | ||
368 | 368 | ||
369 | /** | 369 | /** |
370 | * Create a filename by appending 'fname' to 'path'. | 370 | * Create a filename by appending 'fname' to 'path'. |
371 | * | 371 | * |
372 | * @param path the base path | 372 | * @param path the base path |
373 | * @param fname the filename to append | 373 | * @param fname the filename to append |
374 | * @return '$path/$fname', NULL on error | 374 | * @return '$path/$fname', NULL on error |
375 | */ | 375 | */ |
376 | static char * | 376 | static char * |
377 | append_to_dir (const char *path, | 377 | append_to_dir (const char *path, |
378 | const char *fname) | 378 | const char *fname) |
379 | { | 379 | { |
380 | char *ret; | 380 | char *ret; |
381 | size_t slen; | 381 | size_t slen; |
382 | 382 | ||
383 | if (0 == (slen = strlen (path))) | 383 | if (0 == (slen = strlen (path))) |
384 | return NULL; | 384 | return NULL; |
385 | if (DIR_SEPARATOR == fname[0]) | 385 | if (DIR_SEPARATOR == fname[0]) |
386 | fname++; | 386 | fname++; |
387 | ret = malloc (slen + strlen(fname) + 2); | 387 | ret = malloc (slen + strlen(fname) + 2); |
388 | if (NULL == ret) | 388 | if (NULL == ret) |
389 | return NULL; | 389 | return NULL; |
390 | #ifdef MINGW | 390 | #ifdef MINGW |
391 | if ('\\' == path[slen-1]) | 391 | if ('\\' == path[slen-1]) |
392 | sprintf (ret, | 392 | sprintf (ret, |
393 | "%s%s", | 393 | "%s%s", |
394 | path, | 394 | path, |
395 | fname); | 395 | fname); |
396 | else | 396 | else |
397 | sprintf (ret, | 397 | sprintf (ret, |
398 | "%s\\%s", | 398 | "%s\\%s", |
399 | path, | 399 | path, |
400 | fname); | 400 | fname); |
401 | #else | 401 | #else |
402 | if ('/' == path[slen-1]) | 402 | if ('/' == path[slen-1]) |
403 | sprintf (ret, | 403 | sprintf (ret, |
404 | "%s%s", | 404 | "%s%s", |
405 | path, | 405 | path, |
406 | fname); | 406 | fname); |
407 | else | 407 | else |
408 | sprintf (ret, | 408 | sprintf (ret, |
409 | "%s/%s", | 409 | "%s/%s", |
410 | path, | 410 | path, |
411 | fname); | 411 | fname); |
412 | #endif | 412 | #endif |
413 | return ret; | 413 | return ret; |
414 | } | 414 | } |
415 | 415 | ||
416 | 416 | ||
417 | /** | 417 | /** |
418 | * Iterate over all paths where we expect to find GNU libextractor | 418 | * Iterate over all paths where we expect to find GNU libextractor |
419 | * plugins. | 419 | * plugins. |
420 | * | 420 | * |
421 | * @param pp function to call for each path | 421 | * @param pp function to call for each path |
422 | * @param pp_cls cls argument for pp. | 422 | * @param pp_cls cls argument for pp. |
423 | */ | 423 | */ |
424 | static void | 424 | static void |
425 | get_installation_paths (EXTRACTOR_PathProcessor pp, | 425 | get_installation_paths (EXTRACTOR_PathProcessor pp, |
426 | void *pp_cls) | 426 | void *pp_cls) |
427 | { | 427 | { |
428 | const char *p; | 428 | const char *p; |
429 | char *path; | 429 | char *path; |
430 | char *prefix; | 430 | char *prefix; |
431 | char *d; | 431 | char *d; |
432 | char *saveptr; | 432 | char *saveptr; |
433 | 433 | ||
434 | prefix = NULL; | 434 | prefix = NULL; |
435 | if (NULL != (p = getenv ("LIBEXTRACTOR_PREFIX"))) | 435 | if (NULL != (p = getenv ("LIBEXTRACTOR_PREFIX"))) |
436 | { | 436 | { |
437 | if (NULL == (d = strdup (p))) | 437 | if (NULL == (d = strdup (p))) |
438 | { | 438 | { |
439 | LOG_STRERROR ("strdup"); | 439 | LOG_STRERROR ("strdup"); |
440 | return; | 440 | return; |
441 | } | 441 | } |
442 | for (prefix = strtok_r (d, PATH_SEPARATOR_STR, &saveptr); | 442 | for (prefix = strtok_r (d, PATH_SEPARATOR_STR, &saveptr); |
443 | NULL != prefix; | 443 | NULL != prefix; |
444 | prefix = strtok_r (NULL, PATH_SEPARATOR_STR, &saveptr)) | 444 | prefix = strtok_r (NULL, PATH_SEPARATOR_STR, &saveptr)) |
445 | pp (pp_cls, prefix); | 445 | pp (pp_cls, prefix); |
446 | free (d); | 446 | free (d); |
447 | return; | 447 | return; |
448 | } | 448 | } |
449 | #if GNU_LINUX | 449 | #if GNU_LINUX |
450 | if (NULL == prefix) | 450 | if (NULL == prefix) |
451 | prefix = get_path_from_proc_exe (); | 451 | prefix = get_path_from_proc_exe (); |
452 | #endif | 452 | #endif |
453 | #if WINDOWS | 453 | #if WINDOWS |
454 | if (NULL == prefix) | 454 | if (NULL == prefix) |
455 | prefix = get_path_from_module_filename (); | 455 | prefix = get_path_from_module_filename (); |
456 | #endif | 456 | #endif |
457 | #if DARWIN | 457 | #if DARWIN |
458 | if (NULL == prefix) | 458 | if (NULL == prefix) |
459 | prefix = get_path_from_NSGetExecutablePath (); | 459 | prefix = get_path_from_NSGetExecutablePath (); |
460 | if (NULL == prefix) | 460 | if (NULL == prefix) |
461 | prefix = get_path_from_dyld_image (); | 461 | prefix = get_path_from_dyld_image (); |
462 | #endif | 462 | #endif |
463 | if (NULL == prefix) | 463 | if (NULL == prefix) |
464 | prefix = get_path_from_PATH (); | 464 | prefix = get_path_from_PATH (); |
465 | pp (pp_cls, PLUGININSTDIR); | 465 | pp (pp_cls, PLUGININSTDIR); |
466 | if (NULL == prefix) | 466 | if (NULL == prefix) |
467 | return; | 467 | return; |
468 | path = append_to_dir (prefix, PLUGINDIR); | 468 | path = append_to_dir (prefix, PLUGINDIR); |
469 | if (NULL != path) | 469 | if (NULL != path) |
470 | { | 470 | { |
471 | if (0 != strcmp (path, | 471 | if (0 != strcmp (path, |
472 | PLUGININSTDIR)) | 472 | PLUGININSTDIR)) |
473 | pp (pp_cls, path); | 473 | pp (pp_cls, path); |
474 | free (path); | 474 | free (path); |
475 | } | 475 | } |
476 | free (prefix); | 476 | free (prefix); |
477 | } | 477 | } |
478 | 478 | ||
479 | 479 | ||
480 | /** | 480 | /** |
481 | * Closure for 'find_plugin_in_path'. | 481 | * Closure for 'find_plugin_in_path'. |
482 | */ | 482 | */ |
483 | struct SearchContext | 483 | struct SearchContext |
484 | { | 484 | { |
485 | /** | 485 | /** |
486 | * Name of the plugin we are looking for. | 486 | * Name of the plugin we are looking for. |
487 | */ | 487 | */ |
488 | const char *short_name; | 488 | const char *short_name; |
489 | 489 | ||
490 | /** | 490 | /** |
491 | * Location for storing the path to the plugin upon success. | 491 | * Location for storing the path to the plugin upon success. |
492 | */ | 492 | */ |
493 | char *path; | 493 | char *path; |
494 | }; | 494 | }; |
495 | 495 | ||
496 | 496 | ||
497 | /** | 497 | /** |
498 | * Load all plugins from the given directory. | 498 | * Load all plugins from the given directory. |
499 | * | 499 | * |
500 | * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend | 500 | * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend |
501 | * @param path path to a directory with plugins | 501 | * @param path path to a directory with plugins |
502 | */ | 502 | */ |
503 | static void | 503 | static void |
504 | find_plugin_in_path (void *cls, | 504 | find_plugin_in_path (void *cls, |
505 | const char *path) | 505 | const char *path) |
506 | { | 506 | { |
507 | struct SearchContext *sc = cls; | 507 | struct SearchContext *sc = cls; |
508 | DIR *dir; | 508 | DIR *dir; |
509 | struct dirent *ent; | 509 | struct dirent *ent; |
510 | const char *sym_name; | 510 | const char *sym_name; |
511 | char *sym; | 511 | char *sym; |
512 | char *dot; | 512 | char *dot; |
513 | size_t dlen; | 513 | size_t dlen; |
514 | 514 | ||
515 | if (NULL != sc->path) | 515 | if (NULL != sc->path) |
516 | return; | 516 | return; |
517 | if (NULL == (dir = OPENDIR (path))) | 517 | if (NULL == (dir = OPENDIR (path))) |
518 | return; | 518 | return; |
519 | while (NULL != (ent = READDIR (dir))) | 519 | while (NULL != (ent = READDIR (dir))) |
520 | { | 520 | { |
521 | if ('.' == ent->d_name[0]) | 521 | if ('.' == ent->d_name[0]) |
522 | continue; | 522 | continue; |
523 | dlen = strlen (ent->d_name); | 523 | dlen = strlen (ent->d_name); |
524 | if ( (dlen < 4) || | 524 | if ( (dlen < 4) || |
525 | ( (0 != strcmp (&ent->d_name[dlen-3], ".so")) && | 525 | ( (0 != strcmp (&ent->d_name[dlen-3], ".so")) && |
526 | (0 != strcasecmp (&ent->d_name[dlen-4], ".dll")) ) ) | 526 | (0 != strcasecmp (&ent->d_name[dlen-4], ".dll")) ) ) |
527 | continue; /* only load '.so' and '.dll' */ | 527 | continue; /* only load '.so' and '.dll' */ |
528 | if (NULL == (sym_name = strrchr (ent->d_name, '_'))) | 528 | if (NULL == (sym_name = strrchr (ent->d_name, '_'))) |
529 | continue; | 529 | continue; |
530 | sym_name++; | 530 | sym_name++; |
531 | if (NULL == (sym = strdup (sym_name))) | 531 | if (NULL == (sym = strdup (sym_name))) |
532 | { | 532 | { |
533 | LOG_STRERROR ("strdup"); | 533 | LOG_STRERROR ("strdup"); |
534 | CLOSEDIR (dir); | 534 | CLOSEDIR (dir); |
535 | return; | 535 | return; |
536 | } | 536 | } |
537 | dot = strchr (sym, '.'); | 537 | dot = strchr (sym, '.'); |
538 | if (NULL != dot) | 538 | if (NULL != dot) |
539 | *dot = '\0'; | 539 | *dot = '\0'; |
540 | if (0 == strcmp (sym, sc->short_name)) | 540 | if (0 == strcmp (sym, sc->short_name)) |
541 | { | 541 | { |
542 | sc->path = append_to_dir (path, ent->d_name); | 542 | sc->path = append_to_dir (path, ent->d_name); |
543 | free (sym); | 543 | free (sym); |
544 | break; | 544 | break; |
545 | } | 545 | } |
546 | free (sym); | 546 | free (sym); |
547 | } | 547 | } |
548 | CLOSEDIR (dir); | 548 | CLOSEDIR (dir); |
549 | } | 549 | } |
550 | 550 | ||
551 | 551 | ||
552 | /** | 552 | /** |
553 | * Given a short name of a library (i.e. "mime"), find | 553 | * Given a short name of a library (i.e. "mime"), find |
554 | * the full path of the respective plugin. | 554 | * the full path of the respective plugin. |
555 | */ | 555 | */ |
556 | char * | 556 | char * |
557 | EXTRACTOR_find_plugin_ (const char *short_name) | 557 | EXTRACTOR_find_plugin_ (const char *short_name) |
558 | { | 558 | { |
559 | struct SearchContext sc; | 559 | struct SearchContext sc; |
560 | 560 | ||
561 | sc.path = NULL; | 561 | sc.path = NULL; |
562 | sc.short_name = short_name; | 562 | sc.short_name = short_name; |
563 | get_installation_paths (&find_plugin_in_path, | 563 | get_installation_paths (&find_plugin_in_path, |
564 | &sc); | 564 | &sc); |
565 | return sc.path; | 565 | return sc.path; |
566 | } | 566 | } |
567 | 567 | ||
568 | 568 | ||
569 | /** | 569 | /** |
570 | * Closure for 'load_plugins_from_dir'. | 570 | * Closure for 'load_plugins_from_dir'. |
571 | */ | 571 | */ |
572 | struct DefaultLoaderContext | 572 | struct DefaultLoaderContext |
573 | { | 573 | { |
574 | /** | 574 | /** |
575 | * Accumulated result list. | 575 | * Accumulated result list. |
576 | */ | 576 | */ |
577 | struct EXTRACTOR_PluginList *res; | 577 | struct EXTRACTOR_PluginList *res; |
578 | 578 | ||
579 | /** | 579 | /** |
580 | * Flags to use for all plugins. | 580 | * Flags to use for all plugins. |
581 | */ | 581 | */ |
582 | enum EXTRACTOR_Options flags; | 582 | enum EXTRACTOR_Options flags; |
583 | }; | 583 | }; |
584 | 584 | ||
585 | 585 | ||
586 | /** | 586 | /** |
587 | * Load all plugins from the given directory. | 587 | * Load all plugins from the given directory. |
588 | * | 588 | * |
589 | * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend | 589 | * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend |
590 | * @param path path to a directory with plugins | 590 | * @param path path to a directory with plugins |
591 | */ | 591 | */ |
592 | static void | 592 | static void |
593 | load_plugins_from_dir (void *cls, | 593 | load_plugins_from_dir (void *cls, |
594 | const char *path) | 594 | const char *path) |
595 | { | 595 | { |
596 | struct DefaultLoaderContext *dlc = cls; | 596 | struct DefaultLoaderContext *dlc = cls; |
597 | DIR *dir; | 597 | DIR *dir; |
598 | struct dirent *ent; | 598 | struct dirent *ent; |
599 | const char *sym_name; | 599 | const char *sym_name; |
600 | char *sym; | 600 | char *sym; |
601 | char *dot; | 601 | char *dot; |
602 | size_t dlen; | 602 | size_t dlen; |
603 | 603 | ||
604 | if (NULL == (dir = opendir (path))) | 604 | if (NULL == (dir = opendir (path))) |
605 | return; | 605 | return; |
606 | while (NULL != (ent = readdir (dir))) | 606 | while (NULL != (ent = readdir (dir))) |
607 | { | 607 | { |
608 | if (ent->d_name[0] == '.') | 608 | if (ent->d_name[0] == '.') |
609 | continue; | 609 | continue; |
610 | dlen = strlen (ent->d_name); | 610 | dlen = strlen (ent->d_name); |
611 | if ( (dlen < 4) || | 611 | if ( (dlen < 4) || |
612 | ( (0 != strcmp (&ent->d_name[dlen-3], ".so")) && | 612 | ( (0 != strcmp (&ent->d_name[dlen-3], ".so")) && |
613 | (0 != strcasecmp (&ent->d_name[dlen-4], ".dll")) ) ) | 613 | (0 != strcasecmp (&ent->d_name[dlen-4], ".dll")) ) ) |
614 | continue; /* only load '.so' and '.dll' */ | 614 | continue; /* only load '.so' and '.dll' */ |
615 | if (NULL == (sym_name = strrchr (ent->d_name, '_'))) | 615 | if (NULL == (sym_name = strrchr (ent->d_name, '_'))) |
616 | continue; | 616 | continue; |
617 | sym_name++; | 617 | sym_name++; |
618 | if (NULL == (sym = strdup (sym_name))) | 618 | if (NULL == (sym = strdup (sym_name))) |
619 | { | 619 | { |
620 | LOG_STRERROR ("strdup"); | 620 | LOG_STRERROR ("strdup"); |
621 | closedir (dir); | 621 | closedir (dir); |
622 | return; | 622 | return; |
623 | } | 623 | } |
624 | if (NULL != (dot = strchr (sym, '.'))) | 624 | if (NULL != (dot = strchr (sym, '.'))) |
625 | *dot = '\0'; | 625 | *dot = '\0'; |
626 | dlc->res = EXTRACTOR_plugin_add (dlc->res, | 626 | dlc->res = EXTRACTOR_plugin_add (dlc->res, |
627 | sym, | 627 | sym, |
628 | NULL, | 628 | NULL, |
629 | dlc->flags); | 629 | dlc->flags); |
630 | free (sym); | 630 | free (sym); |
631 | } | 631 | } |
632 | closedir (dir); | 632 | closedir (dir); |
633 | } | 633 | } |
634 | 634 | ||
635 | 635 | ||
636 | /** | 636 | /** |
637 | * Load the default set of plugins. The default can be changed | 637 | * Load the default set of plugins. The default can be changed |
638 | * by setting the LIBEXTRACTOR_LIBRARIES environment variable. | 638 | * by setting the LIBEXTRACTOR_LIBRARIES environment variable. |
639 | * If it is set to "env", then this function will return | 639 | * If it is set to "env", then this function will return |
640 | * EXTRACTOR_plugin_add_config (NULL, env, flags). Otherwise, | 640 | * EXTRACTOR_plugin_add_config (NULL, env, flags). Otherwise, |
641 | * it will load all of the installed plugins and return them. | 641 | * it will load all of the installed plugins and return them. |
642 | * | 642 | * |
643 | * @param flags options for all of the plugins loaded | 643 | * @param flags options for all of the plugins loaded |
644 | * @return the default set of plugins, NULL if no plugins were found | 644 | * @return the default set of plugins, NULL if no plugins were found |
645 | */ | 645 | */ |
646 | struct EXTRACTOR_PluginList * | 646 | struct EXTRACTOR_PluginList * |
647 | EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags) | 647 | EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags) |
648 | { | 648 | { |
649 | struct DefaultLoaderContext dlc; | 649 | struct DefaultLoaderContext dlc; |
650 | char *env; | 650 | char *env; |
651 | 651 | ||
652 | env = getenv ("LIBEXTRACTOR_LIBRARIES"); | 652 | env = getenv ("LIBEXTRACTOR_LIBRARIES"); |
653 | if (NULL != env) | 653 | if (NULL != env) |
654 | return EXTRACTOR_plugin_add_config (NULL, env, flags); | 654 | return EXTRACTOR_plugin_add_config (NULL, env, flags); |
655 | dlc.res = NULL; | 655 | dlc.res = NULL; |
656 | dlc.flags = flags; | 656 | dlc.flags = flags; |
657 | get_installation_paths (&load_plugins_from_dir, | 657 | get_installation_paths (&load_plugins_from_dir, |
658 | &dlc); | 658 | &dlc); |
659 | return dlc.res; | 659 | return dlc.res; |
660 | } | 660 | } |
661 | 661 | ||
662 | 662 | ||
663 | /* end of extractor_plugpath.c */ | 663 | /* end of extractor_plugpath.c */ |