/* */
This source file includes following definitions.
- lt__alloc_die_callback
- loader_init_callback
- loader_init
- lt_dlinit
- lt_dlexit
- tryall_dlopen
- tryall_dlopen_module
- find_module
- canonicalize_path
- argzize_path
- foreach_dirinpath
- find_file_callback
- find_file
- find_handle_callback
- find_handle
- load_deplibs
- load_deplibs
- unload_deplibs
- trim
- parse_dotla_file
- try_dlopen
- file_not_found
- has_library_ext
- lt_dladvise_init
- lt_dladvise_destroy
- lt_dladvise_ext
- lt_dladvise_resident
- lt_dladvise_local
- lt_dladvise_global
- lt_dladvise_preload
- lt_dlopen
- lt_dlopenext
- lt_dlopenadvise
- lt_argz_insert
- lt_argz_insertinorder
- lt_argz_insertdir
- list_files_by_dir
- foreachfile_callback
- lt_dlforeachfile
- lt_dlclose
- lt_dlsym
- lt_dlerror
- lt_dlpath_insertdir
- lt_dladdsearchdir
- lt_dlinsertsearchdir
- lt_dlsetsearchpath
- lt_dlgetsearchpath
- lt_dlmakeresident
- lt_dlisresident
- lt_dlinterface_register
- lt_dlinterface_free
- lt_dlcaller_set_data
- lt_dlcaller_get_data
- lt_dlgetinfo
- lt_dlhandle_iterate
- lt_dlhandle_fetch
- lt_dlhandle_map
1 /* ltdl.c -- system independent dlopen wrapper
2
3 Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
4 2007, 2008, 2011 Free Software Foundation, Inc.
5 Written by Thomas Tanner, 1998
6
7 NOTE: The canonical source of this file is maintained with the
8 GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9
10 GNU Libltdl is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 As a special exception to the GNU Lesser General Public License,
16 if you distribute this file as part of a program or library that
17 is built using GNU Libtool, you may include this file under the
18 same distribution terms that you use for the rest of that program.
19
20 GNU Libltdl is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with GNU Libltdl; see the file COPYING.LIB. If not, a
27 copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
28 or obtained by writing to the Free Software Foundation, Inc.,
29 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 */
31
32 #include "lt__private.h"
33 #include "lt_system.h"
34 #include "lt_dlloader.h"
35
36
37 /* --- MANIFEST CONSTANTS --- */
38
39
40 /* Standard libltdl search path environment variable name */
41 #undef LTDL_SEARCHPATH_VAR
42 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
43
44 /* Standard libtool archive file extension. */
45 #undef LT_ARCHIVE_EXT
46 #define LT_ARCHIVE_EXT ".la"
47
48 /* max. filename length */
49 #if !defined(LT_FILENAME_MAX)
50 # define LT_FILENAME_MAX 1024
51 #endif
52
53 #if !defined(LT_LIBEXT)
54 # define LT_LIBEXT "a"
55 #endif
56
57 #if !defined(LT_LIBPREFIX)
58 # define LT_LIBPREFIX "lib"
59 #endif
60
61 /* This is the maximum symbol size that won't require malloc/free */
62 #undef LT_SYMBOL_LENGTH
63 #define LT_SYMBOL_LENGTH 128
64
65 /* This accounts for the _LTX_ separator */
66 #undef LT_SYMBOL_OVERHEAD
67 #define LT_SYMBOL_OVERHEAD 5
68
69 /* Various boolean flags can be stored in the flags field of an
70 lt_dlhandle... */
71 #define LT_DLIS_RESIDENT(handle) ((handle)->info.is_resident)
72 #define LT_DLIS_SYMGLOBAL(handle) ((handle)->info.is_symglobal)
73 #define LT_DLIS_SYMLOCAL(handle) ((handle)->info.is_symlocal)
74
75
76 static const char objdir[] = LT_OBJDIR;
77 static const char archive_ext[] = LT_ARCHIVE_EXT;
78 static const char libext[] = LT_LIBEXT;
79 static const char libprefix[] = LT_LIBPREFIX;
80 #if defined(LT_MODULE_EXT)
81 static const char shlib_ext[] = LT_MODULE_EXT;
82 #endif
83 /* If the loadable module suffix is not the same as the linkable
84 * shared library suffix, this will be defined. */
85 #if defined(LT_SHARED_EXT)
86 static const char shared_ext[] = LT_SHARED_EXT;
87 #endif
88 #if defined(LT_DLSEARCH_PATH)
89 static const char sys_dlsearch_path[] = LT_DLSEARCH_PATH;
90 #endif
91
92
93
94
95 /* --- DYNAMIC MODULE LOADING --- */
96
97
98 /* The type of a function used at each iteration of foreach_dirinpath(). */
99 typedef int foreach_callback_func (char *filename, void *data1,
100 void *data2);
101 /* foreachfile_callback itself calls a function of this type: */
102 typedef int file_worker_func (const char *filename, void *data);
103
104
105 static int foreach_dirinpath (const char *search_path,
106 const char *base_name,
107 foreach_callback_func *func,
108 void *data1, void *data2);
109 static int find_file_callback (char *filename, void *data1,
110 void *data2);
111 static int find_handle_callback (char *filename, void *data,
112 void *ignored);
113 static int foreachfile_callback (char *filename, void *data1,
114 void *data2);
115
116
117 static int canonicalize_path (const char *path, char **pcanonical);
118 static int argzize_path (const char *path,
119 char **pargz, size_t *pargz_len);
120 static FILE *find_file (const char *search_path,
121 const char *base_name, char **pdir);
122 static lt_dlhandle *find_handle (const char *search_path,
123 const char *base_name,
124 lt_dlhandle *handle,
125 lt_dladvise advise);
126 static int find_module (lt_dlhandle *handle, const char *dir,
127 const char *libdir, const char *dlname,
128 const char *old_name, int installed,
129 lt_dladvise advise);
130 static int has_library_ext (const char *filename);
131 static int load_deplibs (lt_dlhandle handle, char *deplibs);
132 static int trim (char **dest, const char *str);
133 static int try_dlopen (lt_dlhandle *handle,
134 const char *filename, const char *ext,
135 lt_dladvise advise);
136 static int tryall_dlopen (lt_dlhandle *handle,
137 const char *filename,
138 lt_dladvise padvise,
139 const lt_dlvtable *vtable);
140 static int unload_deplibs (lt_dlhandle handle);
141 static int lt_argz_insert (char **pargz, size_t *pargz_len,
142 char *before, const char *entry);
143 static int lt_argz_insertinorder (char **pargz, size_t *pargz_len,
144 const char *entry);
145 static int lt_argz_insertdir (char **pargz, size_t *pargz_len,
146 const char *dirnam, struct dirent *dp);
147 static int lt_dlpath_insertdir (char **ppath, char *before,
148 const char *dir);
149 static int list_files_by_dir (const char *dirnam,
150 char **pargz, size_t *pargz_len);
151 static int file_not_found (void);
152
153 #ifdef HAVE_LIBDLLOADER
154 static int loader_init_callback (lt_dlhandle handle);
155 #endif /* HAVE_LIBDLLOADER */
156
157 static int loader_init (lt_get_vtable *vtable_func,
158 lt_user_data data);
159
160 static char *user_search_path= 0;
161 static lt_dlhandle handles = 0;
162 static int initialized = 0;
163
164 /* Our memory failure callback sets the error message to be passed back
165 up to the client, so we must be careful to return from mallocation
166 callers if allocation fails (as this callback returns!!). */
167 void
168 lt__alloc_die_callback (void)
169 {
170 LT__SETERROR (NO_MEMORY);
171 }
172
173 #ifdef HAVE_LIBDLLOADER
174 /* This function is called to initialise each preloaded module loader,
175 and hook it into the list of loaders to be used when attempting to
176 dlopen an application module. */
177 static int
178 loader_init_callback (lt_dlhandle handle)
179 {
180 lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
181 return loader_init (vtable_func, 0);
182 }
183 #endif /* HAVE_LIBDLLOADER */
184
185 static int
186 loader_init (lt_get_vtable *vtable_func, lt_user_data data)
187 {
188 const lt_dlvtable *vtable = 0;
189 int errors = 0;
190
191 if (vtable_func)
192 {
193 vtable = (*vtable_func) (data);
194 }
195
196 /* lt_dlloader_add will LT__SETERROR if it fails. */
197 errors += lt_dlloader_add (vtable);
198
199 assert (errors || vtable);
200
201 if ((!errors) && vtable->dlloader_init)
202 {
203 if ((*vtable->dlloader_init) (vtable->dlloader_data))
204 {
205 LT__SETERROR (INIT_LOADER);
206 ++errors;
207 }
208 }
209
210 return errors;
211 }
212
213 /* Bootstrap the loader loading with the preopening loader. */
214 #define get_vtable preopen_LTX_get_vtable
215 #define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
216
217 LT_BEGIN_C_DECLS
218 LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data);
219 LT_END_C_DECLS
220 #ifdef HAVE_LIBDLLOADER
221 extern LT_DLSYM_CONST lt_dlsymlist preloaded_symbols[];
222 #endif
223
224 /* Initialize libltdl. */
225 int
226 lt_dlinit (void)
227 {
228 int errors = 0;
229
230 /* Initialize only at first call. */
231 if (++initialized == 1)
232 {
233 lt__alloc_die = lt__alloc_die_callback;
234 handles = 0;
235 user_search_path = 0; /* empty search path */
236
237 /* First set up the statically loaded preload module loader, so
238 we can use it to preopen the other loaders we linked in at
239 compile time. */
240 errors += loader_init (get_vtable, 0);
241
242 /* Now open all the preloaded module loaders, so the application
243 can use _them_ to lt_dlopen its own modules. */
244 #ifdef HAVE_LIBDLLOADER
245 if (!errors)
246 {
247 errors += lt_dlpreload (preloaded_symbols);
248 }
249
250 if (!errors)
251 {
252 errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
253 }
254 #endif /* HAVE_LIBDLLOADER */
255 }
256
257 #ifdef LT_DEBUG_LOADERS
258 lt_dlloader_dump();
259 #endif
260
261 return errors;
262 }
263
264 int
265 lt_dlexit (void)
266 {
267 /* shut down libltdl */
268 lt_dlloader *loader = 0;
269 lt_dlhandle handle = handles;
270 int errors = 0;
271
272 if (!initialized)
273 {
274 LT__SETERROR (SHUTDOWN);
275 ++errors;
276 goto done;
277 }
278
279 /* shut down only at last call. */
280 if (--initialized == 0)
281 {
282 int level;
283
284 while (handles && LT_DLIS_RESIDENT (handles))
285 {
286 handles = handles->next;
287 }
288
289 /* close all modules */
290 for (level = 1; handle; ++level)
291 {
292 lt_dlhandle cur = handles;
293 int saw_nonresident = 0;
294
295 while (cur)
296 {
297 lt_dlhandle tmp = cur;
298 cur = cur->next;
299 if (!LT_DLIS_RESIDENT (tmp))
300 {
301 saw_nonresident = 1;
302 if (tmp->info.ref_count <= level)
303 {
304 if (lt_dlclose (tmp))
305 {
306 ++errors;
307 }
308 /* Make sure that the handle pointed to by 'cur' still exists.
309 lt_dlclose recursively closes dependent libraries which removes
310 them from the linked list. One of these might be the one
311 pointed to by 'cur'. */
312 if (cur)
313 {
314 for (tmp = handles; tmp; tmp = tmp->next)
315 if (tmp == cur)
316 break;
317 if (! tmp)
318 cur = handles;
319 }
320 }
321 }
322 }
323 /* done if only resident modules are left */
324 if (!saw_nonresident)
325 break;
326 }
327
328 /* When removing loaders, we can only find out failure by testing
329 the error string, so avoid a spurious one from an earlier
330 failed command. */
331 if (!errors)
332 LT__SETERRORSTR (0);
333
334 /* close all loaders */
335 for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
336 {
337 lt_dlloader *next = (lt_dlloader *) lt_dlloader_next (loader);
338 lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
339
340 if ((vtable = lt_dlloader_remove ((char *) vtable->name)))
341 {
342 FREE (vtable);
343 }
344 else
345 {
346 /* ignore errors due to resident modules */
347 const char *err;
348 LT__GETERROR (err);
349 if (err)
350 ++errors;
351 }
352
353 loader = next;
354 }
355
356 FREE(user_search_path);
357 }
358
359 done:
360 return errors;
361 }
362
363
364 /* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
365 If the library is not successfully loaded, return non-zero. Otherwise,
366 the dlhandle is stored at the address given in PHANDLE. */
367 static int
368 tryall_dlopen (lt_dlhandle *phandle, const char *filename,
369 lt_dladvise advise, const lt_dlvtable *vtable)
370 {
371 lt_dlhandle handle = handles;
372 const char * saved_error = 0;
373 int errors = 0;
374
375 #ifdef LT_DEBUG_LOADERS
376 fprintf (stderr, "tryall_dlopen (%s, %s)\n",
377 filename ? filename : "(null)",
378 vtable ? vtable->name : "(ALL)");
379 #endif
380
381 LT__GETERROR (saved_error);
382
383 /* check whether the module was already opened */
384 for (;handle; handle = handle->next)
385 {
386 if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
387 || (handle->info.filename && filename
388 && streq (handle->info.filename, filename)))
389 {
390 break;
391 }
392 }
393
394 if (handle)
395 {
396 ++handle->info.ref_count;
397 *phandle = handle;
398 goto done;
399 }
400
401 handle = *phandle;
402 if (filename)
403 {
404 /* Comment out the check of file permissions using access.
405 This call seems to always return -1 with error EACCES.
406 */
407 /* We need to catch missing file errors early so that
408 file_not_found() can detect what happened.
409 if (access (filename, R_OK) != 0)
410 {
411 LT__SETERROR (FILE_NOT_FOUND);
412 ++errors;
413 goto done;
414 } */
415
416 handle->info.filename = lt__strdup (filename);
417 if (!handle->info.filename)
418 {
419 ++errors;
420 goto done;
421 }
422 }
423 else
424 {
425 handle->info.filename = 0;
426 }
427
428 {
429 lt_dlloader loader = lt_dlloader_next (0);
430 const lt_dlvtable *loader_vtable;
431
432 do
433 {
434 if (vtable)
435 loader_vtable = vtable;
436 else
437 loader_vtable = lt_dlloader_get (loader);
438
439 #ifdef LT_DEBUG_LOADERS
440 fprintf (stderr, "Calling %s->module_open (%s)\n",
441 (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
442 filename ? filename : "(null)");
443 #endif
444 handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
445 filename, advise);
446 #ifdef LT_DEBUG_LOADERS
447 fprintf (stderr, " Result: %s\n",
448 handle->module ? "Success" : "Failed");
449 #endif
450
451 if (handle->module != 0)
452 {
453 if (advise)
454 {
455 handle->info.is_resident = advise->is_resident;
456 handle->info.is_symglobal = advise->is_symglobal;
457 handle->info.is_symlocal = advise->is_symlocal;
458 }
459 break;
460 }
461 }
462 while (!vtable && (loader = lt_dlloader_next (loader)));
463
464 /* If VTABLE was given but couldn't open the module, or VTABLE wasn't
465 given but we exhausted all loaders without opening the module, bail
466 out! */
467 if ((vtable && !handle->module)
468 || (!vtable && !loader))
469 {
470 FREE (handle->info.filename);
471 ++errors;
472 goto done;
473 }
474
475 handle->vtable = loader_vtable;
476 }
477
478 LT__SETERRORSTR (saved_error);
479
480 done:
481 return errors;
482 }
483
484
485 static int
486 tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
487 const char *dirname, const char *dlname,
488 lt_dladvise advise)
489 {
490 int error = 0;
491 char *filename = 0;
492 size_t filename_len = 0;
493 size_t dirname_len = LT_STRLEN (dirname);
494
495 assert (handle);
496 assert (dirname);
497 assert (dlname);
498 #if defined(LT_DIRSEP_CHAR)
499 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
500 should make it into this function: */
501 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
502 #endif
503
504 if (dirname_len > 0)
505 if (dirname[dirname_len -1] == '/')
506 --dirname_len;
507 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
508
509 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
510 The PREFIX (if any) is handled below. */
511 filename = MALLOC (char, filename_len + 1);
512 if (!filename)
513 return 1;
514
515 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
516
517 /* Now that we have combined DIRNAME and MODULENAME, if there is
518 also a PREFIX to contend with, simply recurse with the arguments
519 shuffled. Otherwise, attempt to open FILENAME as a module. */
520 if (prefix)
521 {
522 error += tryall_dlopen_module (handle, (const char *) 0,
523 prefix, filename, advise);
524 }
525 else if (tryall_dlopen (handle, filename, advise, 0) != 0)
526 {
527 ++error;
528 }
529
530 FREE (filename);
531 return error;
532 }
533
534 static int
535 find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
536 const char *dlname, const char *old_name, int installed,
537 lt_dladvise advise)
538 {
539 /* Try to open the old library first; if it was dlpreopened,
540 we want the preopened version of it, even if a dlopenable
541 module is available. */
542 if (old_name && tryall_dlopen (handle, old_name,
543 advise, lt_dlloader_find ("lt_preopen") ) == 0)
544 {
545 return 0;
546 }
547
548 /* Try to open the dynamic library. */
549 if (dlname)
550 {
551 /* try to open the installed module */
552 if (installed && libdir)
553 {
554 if (tryall_dlopen_module (handle, (const char *) 0,
555 libdir, dlname, advise) == 0)
556 return 0;
557 }
558
559 /* try to open the not-installed module */
560 if (!installed)
561 {
562 if (tryall_dlopen_module (handle, dir, objdir,
563 dlname, advise) == 0)
564 return 0;
565 }
566
567 /* maybe it was moved to another directory */
568 {
569 if (dir && (tryall_dlopen_module (handle, (const char *) 0,
570 dir, dlname, advise) == 0))
571 return 0;
572 }
573 }
574
575 return 1;
576 }
577
578
579 static int
580 canonicalize_path (const char *path, char **pcanonical)
581 {
582 char *canonical = 0;
583
584 assert (path && *path);
585 assert (pcanonical);
586
587 canonical = MALLOC (char, 1+ LT_STRLEN (path));
588 if (!canonical)
589 return 1;
590
591 {
592 size_t dest = 0;
593 size_t src;
594 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
595 {
596 /* Path separators are not copied to the beginning or end of
597 the destination, or if another separator would follow
598 immediately. */
599 if (path[src] == LT_PATHSEP_CHAR)
600 {
601 if ((dest == 0)
602 || (path[1+ src] == LT_PATHSEP_CHAR)
603 || (path[1+ src] == LT_EOS_CHAR))
604 continue;
605 }
606
607 /* Anything other than a directory separator is copied verbatim. */
608 if ((path[src] != '/')
609 #if defined(LT_DIRSEP_CHAR)
610 && (path[src] != LT_DIRSEP_CHAR)
611 #endif
612 )
613 {
614 canonical[dest++] = path[src];
615 }
616 /* Directory separators are converted and copied only if they are
617 not at the end of a path -- i.e. before a path separator or
618 NULL terminator. */
619 else if ((path[1+ src] != LT_PATHSEP_CHAR)
620 && (path[1+ src] != LT_EOS_CHAR)
621 #if defined(LT_DIRSEP_CHAR)
622 && (path[1+ src] != LT_DIRSEP_CHAR)
623 #endif
624 && (path[1+ src] != '/'))
625 {
626 canonical[dest++] = '/';
627 }
628 }
629
630 /* Add an end-of-string marker at the end. */
631 canonical[dest] = LT_EOS_CHAR;
632 }
633
634 /* Assign new value. */
635 *pcanonical = canonical;
636
637 return 0;
638 }
639
640 static int
641 argzize_path (const char *path, char **pargz, size_t *pargz_len)
642 {
643 error_t error;
644
645 assert (path);
646 assert (pargz);
647 assert (pargz_len);
648
649 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
650 {
651 switch (error)
652 {
653 case ENOMEM:
654 LT__SETERROR (NO_MEMORY);
655 break;
656 default:
657 LT__SETERROR (UNKNOWN);
658 break;
659 }
660
661 return 1;
662 }
663
664 return 0;
665 }
666
667 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
668 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
669 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
670 it is appended to each SEARCH_PATH element before FUNC is called. */
671 static int
672 foreach_dirinpath (const char *search_path, const char *base_name,
673 foreach_callback_func *func, void *data1, void *data2)
674 {
675 int result = 0;
676 size_t filenamesize = 0;
677 size_t lenbase = LT_STRLEN (base_name);
678 size_t argz_len = 0;
679 char *argz = 0;
680 char *filename = 0;
681 char *canonical = 0;
682
683 if (!search_path || !*search_path)
684 {
685 LT__SETERROR (FILE_NOT_FOUND);
686 goto cleanup;
687 }
688
689 if (canonicalize_path (search_path, &canonical) != 0)
690 goto cleanup;
691
692 if (argzize_path (canonical, &argz, &argz_len) != 0)
693 goto cleanup;
694
695 {
696 char *dir_name = 0;
697 while ((dir_name = argz_next (argz, argz_len, dir_name)))
698 {
699 size_t lendir = LT_STRLEN (dir_name);
700
701 if (1+ lendir + lenbase >= filenamesize)
702 {
703 FREE (filename);
704 filenamesize = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
705 filename = MALLOC (char, filenamesize);
706 if (!filename)
707 goto cleanup;
708 }
709
710 assert (filenamesize > lendir);
711 strcpy (filename, dir_name);
712
713 if (base_name && *base_name)
714 {
715 if (filename[lendir -1] != '/')
716 filename[lendir++] = '/';
717 strcpy (filename +lendir, base_name);
718 }
719
720 if ((result = (*func) (filename, data1, data2)))
721 {
722 break;
723 }
724 }
725 }
726
727 cleanup:
728 FREE (argz);
729 FREE (canonical);
730 FREE (filename);
731
732 return result;
733 }
734
735 /* If FILEPATH can be opened, store the name of the directory component
736 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
737 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
738 static int
739 find_file_callback (char *filename, void *data1, void *data2)
740 {
741 char **pdir = (char **) data1;
742 FILE **pfile = (FILE **) data2;
743 int is_done = 0;
744
745 assert (filename && *filename);
746 assert (pdir);
747 assert (pfile);
748
749 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
750 {
751 char *dirend = strrchr (filename, '/');
752
753 if (dirend > filename)
754 *dirend = LT_EOS_CHAR;
755
756 FREE (*pdir);
757 *pdir = lt__strdup (filename);
758 is_done = (*pdir == 0) ? -1 : 1;
759 }
760
761 return is_done;
762 }
763
764 static FILE *
765 find_file (const char *search_path, const char *base_name, char **pdir)
766 {
767 FILE *file = 0;
768
769 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
770
771 return file;
772 }
773
774 static int
775 find_handle_callback (char *filename, void *data, void *data2)
776 {
777 lt_dlhandle *phandle = (lt_dlhandle *) data;
778 int notfound = access (filename, R_OK);
779 lt_dladvise advise = (lt_dladvise) data2;
780
781 /* Bail out if file cannot be read... */
782 if (notfound)
783 return 0;
784
785 /* Try to dlopen the file, but do not continue searching in any
786 case. */
787 if (tryall_dlopen (phandle, filename, advise, 0) != 0)
788 *phandle = 0;
789
790 return 1;
791 }
792
793 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
794 found but could not be opened, *HANDLE will be set to 0. */
795 static lt_dlhandle *
796 find_handle (const char *search_path, const char *base_name,
797 lt_dlhandle *phandle, lt_dladvise advise)
798 {
799 if (!search_path)
800 return 0;
801
802 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
803 phandle, advise))
804 return 0;
805
806 return phandle;
807 }
808
809 #if !defined(LTDL_DLOPEN_DEPLIBS)
810 static int
811 load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
812 {
813 handle->depcount = 0;
814 return 0;
815 }
816
817 #else /* defined(LTDL_DLOPEN_DEPLIBS) */
818 static int
819 load_deplibs (lt_dlhandle handle, char *deplibs)
820 {
821 char *p, *save_search_path = 0;
822 int depcount = 0;
823 int i;
824 char **names = 0;
825 int errors = 0;
826
827 handle->depcount = 0;
828
829 if (!deplibs)
830 {
831 return errors;
832 }
833 ++errors;
834
835 if (user_search_path)
836 {
837 save_search_path = lt__strdup (user_search_path);
838 if (!save_search_path)
839 goto cleanup;
840 }
841
842 /* extract search paths and count deplibs */
843 p = deplibs;
844 while (*p)
845 {
846 if (!isspace ((unsigned char) *p))
847 {
848 char *end = p+1;
849 while (*end && !isspace((unsigned char) *end))
850 {
851 ++end;
852 }
853
854 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
855 {
856 char save = *end;
857 *end = 0; /* set a temporary string terminator */
858 if (lt_dladdsearchdir(p+2))
859 {
860 goto cleanup;
861 }
862 *end = save;
863 }
864 else
865 {
866 ++depcount;
867 }
868
869 p = end;
870 }
871 else
872 {
873 ++p;
874 }
875 }
876
877
878 if (!depcount)
879 {
880 errors = 0;
881 goto cleanup;
882 }
883
884 names = MALLOC (char *, depcount);
885 if (!names)
886 goto cleanup;
887
888 /* now only extract the actual deplibs */
889 depcount = 0;
890 p = deplibs;
891 while (*p)
892 {
893 if (isspace ((unsigned char) *p))
894 {
895 ++p;
896 }
897 else
898 {
899 char *end = p+1;
900 while (*end && !isspace ((unsigned char) *end))
901 {
902 ++end;
903 }
904
905 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
906 {
907 char *name;
908 char save = *end;
909 *end = 0; /* set a temporary string terminator */
910 if (strncmp(p, "-l", 2) == 0)
911 {
912 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
913 name = MALLOC (char, 1+ name_len);
914 if (name)
915 sprintf (name, "lib%s", p+2);
916 }
917 else
918 name = lt__strdup(p);
919
920 if (!name)
921 goto cleanup_names;
922
923 names[depcount++] = name;
924 *end = save;
925 }
926 p = end;
927 }
928 }
929
930 /* load the deplibs (in reverse order)
931 At this stage, don't worry if the deplibs do not load correctly,
932 they may already be statically linked into the loading application
933 for instance. There will be a more enlightening error message
934 later on if the loaded module cannot resolve all of its symbols. */
935 if (depcount)
936 {
937 lt_dlhandle cur = handle;
938 int j = 0;
939
940 cur->deplibs = MALLOC (lt_dlhandle, depcount);
941 if (!cur->deplibs)
942 goto cleanup_names;
943
944 for (i = 0; i < depcount; ++i)
945 {
946 cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
947 if (cur->deplibs[j])
948 {
949 ++j;
950 }
951 }
952
953 cur->depcount = j; /* Number of successfully loaded deplibs */
954 errors = 0;
955 }
956
957 cleanup_names:
958 for (i = 0; i < depcount; ++i)
959 {
960 FREE (names[i]);
961 }
962
963 cleanup:
964 FREE (names);
965 /* restore the old search path */
966 if (save_search_path) {
967 MEMREASSIGN (user_search_path, save_search_path);
968 }
969
970 return errors;
971 }
972 #endif /* defined(LTDL_DLOPEN_DEPLIBS) */
973
974 static int
975 unload_deplibs (lt_dlhandle handle)
976 {
977 int i;
978 int errors = 0;
979 lt_dlhandle cur = handle;
980
981 if (cur->depcount)
982 {
983 for (i = 0; i < cur->depcount; ++i)
984 {
985 if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
986 {
987 errors += lt_dlclose (cur->deplibs[i]);
988 }
989 }
990 FREE (cur->deplibs);
991 }
992
993 return errors;
994 }
995
996 static int
997 trim (char **dest, const char *str)
998 {
999 /* remove the leading and trailing "'" from str
1000 and store the result in dest */
1001 const char *end = strrchr (str, '\'');
1002 size_t len = LT_STRLEN (str);
1003 char *tmp;
1004
1005 FREE (*dest);
1006
1007 if (!end || end == str)
1008 return 1;
1009
1010 if (len > 3 && str[0] == '\'')
1011 {
1012 tmp = MALLOC (char, end - str);
1013 if (!tmp)
1014 return 1;
1015
1016 memcpy(tmp, &str[1], (end - str) - 1);
1017 tmp[(end - str) - 1] = LT_EOS_CHAR;
1018 *dest = tmp;
1019 }
1020 else
1021 {
1022 *dest = 0;
1023 }
1024
1025 return 0;
1026 }
1027
1028 /* Read the .la file FILE. */
1029 static int
1030 parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
1031 char **old_name, int *installed)
1032 {
1033 int errors = 0;
1034 size_t line_len = LT_FILENAME_MAX;
1035 char * line = MALLOC (char, line_len);
1036
1037 if (!line)
1038 {
1039 LT__SETERROR (FILE_NOT_FOUND);
1040 return 1;
1041 }
1042
1043 while (!feof (file))
1044 {
1045 line[line_len-2] = '\0';
1046 if (!fgets (line, (int) line_len, file))
1047 {
1048 break;
1049 }
1050
1051 /* Handle the case where we occasionally need to read a line
1052 that is longer than the initial buffer size.
1053 Behave even if the file contains NUL bytes due to corruption. */
1054 while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
1055 {
1056 line = REALLOC (char, line, line_len *2);
1057 if (!line)
1058 {
1059 ++errors;
1060 goto cleanup;
1061 }
1062 line[line_len * 2 - 2] = '\0';
1063 if (!fgets (&line[line_len -1], (int) line_len +1, file))
1064 {
1065 break;
1066 }
1067 line_len *= 2;
1068 }
1069
1070 if (line[0] == '\n' || line[0] == '#')
1071 {
1072 continue;
1073 }
1074
1075 #undef STR_DLNAME
1076 #define STR_DLNAME "dlname="
1077 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
1078 {
1079 errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
1080 }
1081
1082 #undef STR_OLD_LIBRARY
1083 #define STR_OLD_LIBRARY "old_library="
1084 else if (strncmp (line, STR_OLD_LIBRARY,
1085 sizeof (STR_OLD_LIBRARY) - 1) == 0)
1086 {
1087 errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
1088 }
1089
1090 /* Windows native tools do not understand the POSIX paths we store
1091 in libdir. */
1092 #undef STR_LIBDIR
1093 #define STR_LIBDIR "libdir="
1094 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
1095 {
1096 errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
1097 #ifdef __WINDOWS__
1098 /* Disallow following unix-style paths on MinGW. */
1099 if (*libdir && (**libdir == '/' || **libdir == '\\'))
1100 **libdir = '\0';
1101 #endif
1102 }
1103
1104 #undef STR_DL_DEPLIBS
1105 #define STR_DL_DEPLIBS "dependency_libs="
1106 else if (strncmp (line, STR_DL_DEPLIBS,
1107 sizeof (STR_DL_DEPLIBS) - 1) == 0)
1108 {
1109 errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
1110 }
1111 else if (streq (line, "installed=yes\n"))
1112 {
1113 *installed = 1;
1114 }
1115 else if (streq (line, "installed=no\n"))
1116 {
1117 *installed = 0;
1118 }
1119
1120 #undef STR_LIBRARY_NAMES
1121 #define STR_LIBRARY_NAMES "library_names="
1122 else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
1123 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
1124 {
1125 char *last_libname;
1126 errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
1127 if (!errors
1128 && *dlname
1129 && (last_libname = strrchr (*dlname, ' ')) != 0)
1130 {
1131 last_libname = lt__strdup (last_libname + 1);
1132 if (!last_libname)
1133 {
1134 ++errors;
1135 goto cleanup;
1136 }
1137 MEMREASSIGN (*dlname, last_libname);
1138 }
1139 }
1140
1141 if (errors)
1142 break;
1143 }
1144 cleanup:
1145 FREE (line);
1146 return errors;
1147 }
1148
1149
1150 /* Try to open FILENAME as a module. */
1151 static int
1152 try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
1153 lt_dladvise advise)
1154 {
1155 const char * saved_error = 0;
1156 char * archive_name = 0;
1157 char * canonical = 0;
1158 char * base_name = 0;
1159 char * dir = 0;
1160 char * name = 0;
1161 char * attempt = 0;
1162 int errors = 0;
1163 lt_dlhandle newhandle;
1164
1165 assert (phandle);
1166 assert (*phandle == 0);
1167
1168 #ifdef LT_DEBUG_LOADERS
1169 fprintf (stderr, "try_dlopen (%s, %s)\n",
1170 filename ? filename : "(null)",
1171 ext ? ext : "(null)");
1172 #endif
1173
1174 LT__GETERROR (saved_error);
1175
1176 /* dlopen self? */
1177 if (!filename)
1178 {
1179 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1180 if (*phandle == 0)
1181 return 1;
1182
1183 newhandle = *phandle;
1184
1185 /* lt_dlclose()ing yourself is very bad! Disallow it. */
1186 newhandle->info.is_resident = 1;
1187
1188 if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1189 {
1190 FREE (*phandle);
1191 return 1;
1192 }
1193
1194 goto register_handle;
1195 }
1196
1197 assert (filename && *filename);
1198
1199 if (ext)
1200 {
1201 attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
1202 if (!attempt)
1203 return 1;
1204
1205 sprintf(attempt, "%s%s", filename, ext);
1206 }
1207 else
1208 {
1209 attempt = lt__strdup (filename);
1210 if (!attempt)
1211 return 1;
1212 }
1213
1214 /* Doing this immediately allows internal functions to safely
1215 assume only canonicalized paths are passed. */
1216 if (canonicalize_path (attempt, &canonical) != 0)
1217 {
1218 ++errors;
1219 goto cleanup;
1220 }
1221
1222 /* If the canonical module name is a path (relative or absolute)
1223 then split it into a directory part and a name part. */
1224 base_name = strrchr (canonical, '/');
1225 if (base_name)
1226 {
1227 size_t dirlen = (1+ base_name) - canonical;
1228
1229 dir = MALLOC (char, 1+ dirlen);
1230 if (!dir)
1231 {
1232 ++errors;
1233 goto cleanup;
1234 }
1235
1236 strncpy (dir, canonical, dirlen);
1237 dir[dirlen] = LT_EOS_CHAR;
1238
1239 ++base_name;
1240 }
1241 else
1242 MEMREASSIGN (base_name, canonical);
1243
1244 assert (base_name && *base_name);
1245
1246 ext = strrchr (base_name, '.');
1247 if (!ext)
1248 {
1249 ext = base_name + LT_STRLEN (base_name);
1250 }
1251
1252 /* extract the module name from the file name */
1253 name = MALLOC (char, ext - base_name + 1);
1254 if (!name)
1255 {
1256 ++errors;
1257 goto cleanup;
1258 }
1259
1260 /* canonicalize the module name */
1261 {
1262 int i;
1263 for (i = 0; i < ext - base_name; ++i)
1264 {
1265 if (isalnum ((unsigned char)(base_name[i])))
1266 {
1267 name[i] = base_name[i];
1268 }
1269 else
1270 {
1271 name[i] = '_';
1272 }
1273 }
1274 name[ext - base_name] = LT_EOS_CHAR;
1275 }
1276
1277 /* Before trawling through the filesystem in search of a module,
1278 check whether we are opening a preloaded module. */
1279 if (!dir)
1280 {
1281 const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1282
1283 if (vtable)
1284 {
1285 /* libprefix + name + "." + libext + NULL */
1286 archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
1287 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1288
1289 if ((*phandle == NULL) || (archive_name == NULL))
1290 {
1291 ++errors;
1292 goto cleanup;
1293 }
1294 newhandle = *phandle;
1295
1296 /* Preloaded modules are always named according to their old
1297 archive name. */
1298 if (strncmp(name, "lib", 3) == 0)
1299 {
1300 sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
1301 }
1302 else
1303 {
1304 sprintf (archive_name, "%s.%s", name, libext);
1305 }
1306
1307 if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
1308 {
1309 goto register_handle;
1310 }
1311
1312 /* If we're still here, there was no matching preloaded module,
1313 so put things back as we found them, and continue searching. */
1314 FREE (*phandle);
1315 newhandle = NULL;
1316 }
1317 }
1318
1319 /* If we are allowing only preloaded modules, and we didn't find
1320 anything yet, give up on the search here. */
1321 if (advise && advise->try_preload_only)
1322 {
1323 goto cleanup;
1324 }
1325
1326 /* Check whether we are opening a libtool module (.la extension). */
1327 if (ext && streq (ext, archive_ext))
1328 {
1329 /* this seems to be a libtool module */
1330 FILE * file = 0;
1331 char * dlname = 0;
1332 char * old_name = 0;
1333 char * libdir = 0;
1334 char * deplibs = 0;
1335
1336 /* if we can't find the installed flag, it is probably an
1337 installed libtool archive, produced with an old version
1338 of libtool */
1339 int installed = 1;
1340
1341 /* Now try to open the .la file. If there is no directory name
1342 component, try to find it first in user_search_path and then other
1343 prescribed paths. Otherwise (or in any case if the module was not
1344 yet found) try opening just the module name as passed. */
1345 if (!dir)
1346 {
1347 const char *search_path = user_search_path;
1348
1349 if (search_path)
1350 file = find_file (user_search_path, base_name, &dir);
1351
1352 if (!file)
1353 {
1354 search_path = getenv (LTDL_SEARCHPATH_VAR);
1355 if (search_path)
1356 file = find_file (search_path, base_name, &dir);
1357 }
1358
1359 #if defined(LT_MODULE_PATH_VAR)
1360 if (!file)
1361 {
1362 search_path = getenv (LT_MODULE_PATH_VAR);
1363 if (search_path)
1364 file = find_file (search_path, base_name, &dir);
1365 }
1366 #endif
1367 #if defined(LT_DLSEARCH_PATH)
1368 if (!file && *sys_dlsearch_path)
1369 {
1370 file = find_file (sys_dlsearch_path, base_name, &dir);
1371 }
1372 #endif
1373 }
1374 else
1375 {
1376 file = fopen (attempt, LT_READTEXT_MODE);
1377 }
1378
1379 /* If we didn't find the file by now, it really isn't there. Set
1380 the status flag, and bail out. */
1381 if (!file)
1382 {
1383 LT__SETERROR (FILE_NOT_FOUND);
1384 ++errors;
1385 goto cleanup;
1386 }
1387
1388 /* read the .la file */
1389 if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1390 &old_name, &installed) != 0)
1391 ++errors;
1392
1393 fclose (file);
1394
1395 /* allocate the handle */
1396 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1397 if (*phandle == 0)
1398 ++errors;
1399
1400 if (errors)
1401 {
1402 FREE (dlname);
1403 FREE (old_name);
1404 FREE (libdir);
1405 FREE (deplibs);
1406 FREE (*phandle);
1407 goto cleanup;
1408 }
1409
1410 assert (*phandle);
1411
1412 if (load_deplibs (*phandle, deplibs) == 0)
1413 {
1414 newhandle = *phandle;
1415 /* find_module may replace newhandle */
1416 if (find_module (&newhandle, dir, libdir, dlname, old_name,
1417 installed, advise))
1418 {
1419 unload_deplibs (*phandle);
1420 ++errors;
1421 }
1422 }
1423 else
1424 {
1425 ++errors;
1426 }
1427
1428 FREE (dlname);
1429 FREE (old_name);
1430 FREE (libdir);
1431 FREE (deplibs);
1432
1433 if (errors)
1434 {
1435 FREE (*phandle);
1436 goto cleanup;
1437 }
1438
1439 if (*phandle != newhandle)
1440 {
1441 unload_deplibs (*phandle);
1442 }
1443 }
1444 else
1445 {
1446 /* not a libtool module */
1447 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1448 if (*phandle == 0)
1449 {
1450 ++errors;
1451 goto cleanup;
1452 }
1453
1454 newhandle = *phandle;
1455
1456 /* If the module has no directory name component, try to find it
1457 first in user_search_path and then other prescribed paths.
1458 Otherwise (or in any case if the module was not yet found) try
1459 opening just the module name as passed. */
1460 if ((dir || (!find_handle (user_search_path, base_name,
1461 &newhandle, advise)
1462 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
1463 &newhandle, advise)
1464 #if defined(LT_MODULE_PATH_VAR)
1465 && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1466 &newhandle, advise)
1467 #endif
1468 #if defined(LT_DLSEARCH_PATH)
1469 && !find_handle (sys_dlsearch_path, base_name,
1470 &newhandle, advise)
1471 #endif
1472 )))
1473 {
1474 if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1475 {
1476 newhandle = NULL;
1477 }
1478 }
1479
1480 if (!newhandle)
1481 {
1482 FREE (*phandle);
1483 ++errors;
1484 goto cleanup;
1485 }
1486 }
1487
1488 register_handle:
1489 MEMREASSIGN (*phandle, newhandle);
1490
1491 if ((*phandle)->info.ref_count == 0)
1492 {
1493 (*phandle)->info.ref_count = 1;
1494 MEMREASSIGN ((*phandle)->info.name, name);
1495
1496 (*phandle)->next = handles;
1497 handles = *phandle;
1498 }
1499
1500 LT__SETERRORSTR (saved_error);
1501
1502 cleanup:
1503 FREE (dir);
1504 FREE (attempt);
1505 FREE (name);
1506 if (!canonical) /* was MEMREASSIGNed */
1507 FREE (base_name);
1508 FREE (canonical);
1509 FREE (archive_name);
1510
1511 return errors;
1512 }
1513
1514
1515 /* If the last error message stored was `FILE_NOT_FOUND', then return
1516 non-zero. */
1517 static int
1518 file_not_found (void)
1519 {
1520 const char *error = 0;
1521
1522 LT__GETERROR (error);
1523 if (error == LT__STRERROR (FILE_NOT_FOUND))
1524 return 1;
1525
1526 return 0;
1527 }
1528
1529
1530 /* Unless FILENAME already bears a suitable library extension, then
1531 return 0. */
1532 static int
1533 has_library_ext (const char *filename)
1534 {
1535 const char * ext = 0;
1536
1537 assert (filename);
1538
1539 ext = strrchr (filename, '.');
1540
1541 if (ext && ((streq (ext, archive_ext))
1542 #if defined(LT_MODULE_EXT)
1543 || (streq (ext, shlib_ext))
1544 #endif
1545 #if defined(LT_SHARED_EXT)
1546 || (streq (ext, shared_ext))
1547 #endif
1548 ))
1549 {
1550 return 1;
1551 }
1552
1553 return 0;
1554 }
1555
1556
1557 /* Initialise and configure a user lt_dladvise opaque object. */
1558
1559 int
1560 lt_dladvise_init (lt_dladvise *padvise)
1561 {
1562 lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
1563 *padvise = advise;
1564 return (advise ? 0 : 1);
1565 }
1566
1567 int
1568 lt_dladvise_destroy (lt_dladvise *padvise)
1569 {
1570 if (padvise)
1571 FREE(*padvise);
1572 return 0;
1573 }
1574
1575 int
1576 lt_dladvise_ext (lt_dladvise *padvise)
1577 {
1578 assert (padvise && *padvise);
1579 (*padvise)->try_ext = 1;
1580 return 0;
1581 }
1582
1583 int
1584 lt_dladvise_resident (lt_dladvise *padvise)
1585 {
1586 assert (padvise && *padvise);
1587 (*padvise)->is_resident = 1;
1588 return 0;
1589 }
1590
1591 int
1592 lt_dladvise_local (lt_dladvise *padvise)
1593 {
1594 assert (padvise && *padvise);
1595 (*padvise)->is_symlocal = 1;
1596 return 0;
1597 }
1598
1599 int
1600 lt_dladvise_global (lt_dladvise *padvise)
1601 {
1602 assert (padvise && *padvise);
1603 (*padvise)->is_symglobal = 1;
1604 return 0;
1605 }
1606
1607 int
1608 lt_dladvise_preload (lt_dladvise *padvise)
1609 {
1610 assert (padvise && *padvise);
1611 (*padvise)->try_preload_only = 1;
1612 return 0;
1613 }
1614
1615 /* Libtool-1.5.x interface for loading a new module named FILENAME. */
1616 lt_dlhandle
1617 lt_dlopen (const char *filename)
1618 {
1619 return lt_dlopenadvise (filename, NULL);
1620 }
1621
1622
1623 /* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to
1624 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
1625 and if a file is still not found try again with MODULE_EXT appended
1626 instead. */
1627 lt_dlhandle
1628 lt_dlopenext (const char *filename)
1629 {
1630 lt_dlhandle handle = 0;
1631 lt_dladvise advise;
1632
1633 if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
1634 handle = lt_dlopenadvise (filename, advise);
1635
1636 lt_dladvise_destroy (&advise);
1637 return handle;
1638 }
1639
1640
1641 lt_dlhandle
1642 lt_dlopenadvise (const char *filename, lt_dladvise advise)
1643 {
1644 lt_dlhandle handle = 0;
1645 int errors = 0;
1646 const char * saved_error = 0;
1647
1648 LT__GETERROR (saved_error);
1649
1650 /* Can't have symbols hidden and visible at the same time! */
1651 if (advise && advise->is_symlocal && advise->is_symglobal)
1652 {
1653 LT__SETERROR (CONFLICTING_FLAGS);
1654 return 0;
1655 }
1656
1657 if (!filename
1658 || !advise
1659 || !advise->try_ext
1660 || has_library_ext (filename))
1661 {
1662 /* Just incase we missed a code path in try_dlopen() that reports
1663 an error, but forgot to reset handle... */
1664 if (try_dlopen (&handle, filename, NULL, advise) != 0)
1665 return 0;
1666
1667 return handle;
1668 }
1669 else if (filename && *filename)
1670 {
1671
1672 /* First try appending ARCHIVE_EXT. */
1673 errors += try_dlopen (&handle, filename, archive_ext, advise);
1674
1675 /* If we found FILENAME, stop searching -- whether we were able to
1676 load the file as a module or not. If the file exists but loading
1677 failed, it is better to return an error message here than to
1678 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
1679 in the module search path. */
1680 if (handle || ((errors > 0) && !file_not_found ()))
1681 return handle;
1682
1683 #if defined(LT_MODULE_EXT)
1684 /* Try appending SHLIB_EXT. */
1685 LT__SETERRORSTR (saved_error);
1686 errors = try_dlopen (&handle, filename, shlib_ext, advise);
1687
1688 /* As before, if the file was found but loading failed, return now
1689 with the current error message. */
1690 if (handle || ((errors > 0) && !file_not_found ()))
1691 return handle;
1692 #endif
1693
1694 #if defined(LT_SHARED_EXT)
1695 /* Try appending SHARED_EXT. */
1696 LT__SETERRORSTR (saved_error);
1697 errors = try_dlopen (&handle, filename, shared_ext, advise);
1698
1699 /* As before, if the file was found but loading failed, return now
1700 with the current error message. */
1701 if (handle || ((errors > 0) && !file_not_found ()))
1702 return handle;
1703 #endif
1704 }
1705
1706 /* Still here? Then we really did fail to locate any of the file
1707 names we tried. */
1708 LT__SETERROR (FILE_NOT_FOUND);
1709 return 0;
1710 }
1711
1712
1713 static int
1714 lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1715 const char *entry)
1716 {
1717 error_t error;
1718
1719 /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1720 pargz_len, NULL, entry) failed with EINVAL. */
1721 if (before)
1722 error = argz_insert (pargz, pargz_len, before, entry);
1723 else
1724 error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1725
1726 if (error)
1727 {
1728 switch (error)
1729 {
1730 case ENOMEM:
1731 LT__SETERROR (NO_MEMORY);
1732 break;
1733 default:
1734 LT__SETERROR (UNKNOWN);
1735 break;
1736 }
1737 return 1;
1738 }
1739
1740 return 0;
1741 }
1742
1743 static int
1744 lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1745 {
1746 char *before = 0;
1747
1748 assert (pargz);
1749 assert (pargz_len);
1750 assert (entry && *entry);
1751
1752 if (*pargz)
1753 while ((before = argz_next (*pargz, *pargz_len, before)))
1754 {
1755 int cmp = strcmp (entry, before);
1756
1757 if (cmp < 0) break;
1758 if (cmp == 0) return 0; /* No duplicates! */
1759 }
1760
1761 return lt_argz_insert (pargz, pargz_len, before, entry);
1762 }
1763
1764 static int
1765 lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1766 struct dirent *dp)
1767 {
1768 char *buf = 0;
1769 size_t buf_len = 0;
1770 char *end = 0;
1771 size_t end_offset = 0;
1772 size_t dir_len = 0;
1773 int errors = 0;
1774
1775 assert (pargz);
1776 assert (pargz_len);
1777 assert (dp);
1778
1779 dir_len = LT_STRLEN (dirnam);
1780 end = dp->d_name + D_NAMLEN(dp);
1781
1782 /* Ignore version numbers. */
1783 {
1784 char *p;
1785 for (p = end; p -1 > dp->d_name; --p)
1786 if (strchr (".0123456789", p[-1]) == 0)
1787 break;
1788
1789 if (*p == '.')
1790 end = p;
1791 }
1792
1793 /* Ignore filename extension. */
1794 {
1795 char *p;
1796 for (p = end -1; p > dp->d_name; --p)
1797 if (*p == '.')
1798 {
1799 end = p;
1800 break;
1801 }
1802 }
1803
1804 /* Prepend the directory name. */
1805 end_offset = end - dp->d_name;
1806 buf_len = dir_len + 1+ end_offset;
1807 buf = MALLOC (char, 1+ buf_len);
1808 if (!buf)
1809 return ++errors;
1810
1811 assert (buf);
1812
1813 strcpy (buf, dirnam);
1814 strcat (buf, "/");
1815 strncat (buf, dp->d_name, end_offset);
1816 buf[buf_len] = LT_EOS_CHAR;
1817
1818 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
1819 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1820 ++errors;
1821
1822 FREE (buf);
1823
1824 return errors;
1825 }
1826
1827 static int
1828 list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1829 {
1830 DIR *dirp = 0;
1831 int errors = 0;
1832
1833 assert (dirnam && *dirnam);
1834 assert (pargz);
1835 assert (pargz_len);
1836 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1837
1838 dirp = opendir (dirnam);
1839 if (dirp)
1840 {
1841 struct dirent *dp = 0;
1842
1843 while ((dp = readdir (dirp)))
1844 if (dp->d_name[0] != '.')
1845 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1846 {
1847 ++errors;
1848 break;
1849 }
1850
1851 closedir (dirp);
1852 }
1853 else
1854 ++errors;
1855
1856 return errors;
1857 }
1858
1859
1860 /* If there are any files in DIRNAME, call the function passed in
1861 DATA1 (with the name of each file and DATA2 as arguments). */
1862 static int
1863 foreachfile_callback (char *dirname, void *data1, void *data2)
1864 {
1865 file_worker_func *func = *(file_worker_func **) data1;
1866
1867 int is_done = 0;
1868 char *argz = 0;
1869 size_t argz_len = 0;
1870
1871 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1872 goto cleanup;
1873 if (!argz)
1874 goto cleanup;
1875
1876 {
1877 char *filename = 0;
1878 while ((filename = argz_next (argz, argz_len, filename)))
1879 if ((is_done = (*func) (filename, data2)))
1880 break;
1881 }
1882
1883 cleanup:
1884 FREE (argz);
1885
1886 return is_done;
1887 }
1888
1889
1890 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
1891 with DATA. The filenames passed to FUNC would be suitable for
1892 passing to lt_dlopenext. The extensions are stripped so that
1893 individual modules do not generate several entries (e.g. libfoo.la,
1894 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
1895 then the same directories that lt_dlopen would search are examined. */
1896 int
1897 lt_dlforeachfile (const char *search_path,
1898 int (*func) (const char *filename, void *data),
1899 void *data)
1900 {
1901 int is_done = 0;
1902 file_worker_func **fpptr = &func;
1903
1904 if (search_path)
1905 {
1906 /* If a specific path was passed, search only the directories
1907 listed in it. */
1908 is_done = foreach_dirinpath (search_path, 0,
1909 foreachfile_callback, fpptr, data);
1910 }
1911 else
1912 {
1913 /* Otherwise search the default paths. */
1914 is_done = foreach_dirinpath (user_search_path, 0,
1915 foreachfile_callback, fpptr, data);
1916 if (!is_done)
1917 {
1918 is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1919 foreachfile_callback, fpptr, data);
1920 }
1921
1922 #if defined(LT_MODULE_PATH_VAR)
1923 if (!is_done)
1924 {
1925 is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1926 foreachfile_callback, fpptr, data);
1927 }
1928 #endif
1929 #if defined(LT_DLSEARCH_PATH)
1930 if (!is_done && *sys_dlsearch_path)
1931 {
1932 is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1933 foreachfile_callback, fpptr, data);
1934 }
1935 #endif
1936 }
1937
1938 return is_done;
1939 }
1940
1941 int
1942 lt_dlclose (lt_dlhandle handle)
1943 {
1944 lt_dlhandle cur, last;
1945 int errors = 0;
1946
1947 /* check whether the handle is valid */
1948 last = cur = handles;
1949 while (cur && handle != cur)
1950 {
1951 last = cur;
1952 cur = cur->next;
1953 }
1954
1955 if (!cur)
1956 {
1957 LT__SETERROR (INVALID_HANDLE);
1958 ++errors;
1959 goto done;
1960 }
1961
1962 cur = handle;
1963 cur->info.ref_count--;
1964
1965 /* Note that even with resident modules, we must track the ref_count
1966 correctly incase the user decides to reset the residency flag
1967 later (even though the API makes no provision for that at the
1968 moment). */
1969 if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1970 {
1971 lt_user_data data = cur->vtable->dlloader_data;
1972
1973 if (cur != handles)
1974 {
1975 last->next = cur->next;
1976 }
1977 else
1978 {
1979 handles = cur->next;
1980 }
1981
1982 errors += cur->vtable->module_close (data, cur->module);
1983 errors += unload_deplibs (handle);
1984
1985 /* It is up to the callers to free the data itself. */
1986 FREE (cur->interface_data);
1987
1988 FREE (cur->info.filename);
1989 FREE (cur->info.name);
1990 FREE (cur);
1991
1992 goto done;
1993 }
1994
1995 if (LT_DLIS_RESIDENT (handle))
1996 {
1997 LT__SETERROR (CLOSE_RESIDENT_MODULE);
1998 ++errors;
1999 }
2000
2001 done:
2002 return errors;
2003 }
2004
2005 void *
2006 lt_dlsym (lt_dlhandle place, const char *symbol)
2007 {
2008 size_t lensym;
2009 char lsym[LT_SYMBOL_LENGTH];
2010 char *sym;
2011 void *address;
2012 lt_user_data data;
2013 lt_dlhandle handle;
2014
2015 if (!place)
2016 {
2017 LT__SETERROR (INVALID_HANDLE);
2018 return 0;
2019 }
2020
2021 handle = place;
2022
2023 if (!symbol)
2024 {
2025 LT__SETERROR (SYMBOL_NOT_FOUND);
2026 return 0;
2027 }
2028
2029 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
2030 + LT_STRLEN (handle->info.name);
2031
2032 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2033 {
2034 sym = lsym;
2035 }
2036 else
2037 {
2038 sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2039 if (!sym)
2040 {
2041 LT__SETERROR (BUFFER_OVERFLOW);
2042 return 0;
2043 }
2044 }
2045
2046 data = handle->vtable->dlloader_data;
2047 if (handle->info.name)
2048 {
2049 const char *saved_error;
2050
2051 LT__GETERROR (saved_error);
2052
2053 /* this is a libtool module */
2054 if (handle->vtable->sym_prefix)
2055 {
2056 strcpy(sym, handle->vtable->sym_prefix);
2057 strcat(sym, handle->info.name);
2058 }
2059 else
2060 {
2061 strcpy(sym, handle->info.name);
2062 }
2063
2064 strcat(sym, "_LTX_");
2065 strcat(sym, symbol);
2066
2067 /* try "modulename_LTX_symbol" */
2068 address = handle->vtable->find_sym (data, handle->module, sym);
2069 if (address)
2070 {
2071 if (sym != lsym)
2072 {
2073 FREE (sym);
2074 }
2075 return address;
2076 }
2077 LT__SETERRORSTR (saved_error);
2078 }
2079
2080 /* otherwise try "symbol" */
2081 if (handle->vtable->sym_prefix)
2082 {
2083 strcpy(sym, handle->vtable->sym_prefix);
2084 strcat(sym, symbol);
2085 }
2086 else
2087 {
2088 strcpy(sym, symbol);
2089 }
2090
2091 address = handle->vtable->find_sym (data, handle->module, sym);
2092 if (sym != lsym)
2093 {
2094 FREE (sym);
2095 }
2096
2097 return address;
2098 }
2099
2100 const char *
2101 lt_dlerror (void)
2102 {
2103 const char *error;
2104
2105 LT__GETERROR (error);
2106 LT__SETERRORSTR (0);
2107
2108 return error;
2109 }
2110
2111 static int
2112 lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2113 {
2114 int errors = 0;
2115 char *canonical = 0;
2116 char *argz = 0;
2117 size_t argz_len = 0;
2118
2119 assert (ppath);
2120 assert (dir && *dir);
2121
2122 if (canonicalize_path (dir, &canonical) != 0)
2123 {
2124 ++errors;
2125 goto cleanup;
2126 }
2127
2128 assert (canonical && *canonical);
2129
2130 /* If *PPATH is empty, set it to DIR. */
2131 if (*ppath == 0)
2132 {
2133 assert (!before); /* BEFORE cannot be set without PPATH. */
2134 assert (dir); /* Without DIR, don't call this function! */
2135
2136 *ppath = lt__strdup (dir);
2137 if (*ppath == 0)
2138 ++errors;
2139
2140 goto cleanup;
2141 }
2142
2143 assert (ppath && *ppath);
2144
2145 if (argzize_path (*ppath, &argz, &argz_len) != 0)
2146 {
2147 ++errors;
2148 goto cleanup;
2149 }
2150
2151 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
2152 if *PPATH is already canonicalized, and hence does not change length
2153 with respect to ARGZ. We canonicalize each entry as it is added to
2154 the search path, and don't call this function with (uncanonicalized)
2155 user paths, so this is a fair assumption. */
2156 if (before)
2157 {
2158 assert (*ppath <= before);
2159 assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2160
2161 before = before - *ppath + argz;
2162 }
2163
2164 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2165 {
2166 ++errors;
2167 goto cleanup;
2168 }
2169
2170 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2171 MEMREASSIGN(*ppath, argz);
2172
2173 cleanup:
2174 FREE (argz);
2175 FREE (canonical);
2176
2177 return errors;
2178 }
2179
2180 int
2181 lt_dladdsearchdir (const char *search_dir)
2182 {
2183 int errors = 0;
2184
2185 if (search_dir && *search_dir)
2186 {
2187 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2188 ++errors;
2189 }
2190
2191 return errors;
2192 }
2193
2194 int
2195 lt_dlinsertsearchdir (const char *before, const char *search_dir)
2196 {
2197 int errors = 0;
2198
2199 if (before)
2200 {
2201 if ((before < user_search_path)
2202 || (before >= user_search_path + LT_STRLEN (user_search_path)))
2203 {
2204 LT__SETERROR (INVALID_POSITION);
2205 return 1;
2206 }
2207 }
2208
2209 if (search_dir && *search_dir)
2210 {
2211 if (lt_dlpath_insertdir (&user_search_path,
2212 (char *) before, search_dir) != 0)
2213 {
2214 ++errors;
2215 }
2216 }
2217
2218 return errors;
2219 }
2220
2221 int
2222 lt_dlsetsearchpath (const char *search_path)
2223 {
2224 int errors = 0;
2225
2226 FREE (user_search_path);
2227
2228 if (!search_path || !LT_STRLEN (search_path))
2229 {
2230 return errors;
2231 }
2232
2233 if (canonicalize_path (search_path, &user_search_path) != 0)
2234 ++errors;
2235
2236 return errors;
2237 }
2238
2239 const char *
2240 lt_dlgetsearchpath (void)
2241 {
2242 const char *saved_path;
2243
2244 saved_path = user_search_path;
2245
2246 return saved_path;
2247 }
2248
2249 int
2250 lt_dlmakeresident (lt_dlhandle handle)
2251 {
2252 int errors = 0;
2253
2254 if (!handle)
2255 {
2256 LT__SETERROR (INVALID_HANDLE);
2257 ++errors;
2258 }
2259 else
2260 {
2261 handle->info.is_resident = 1;
2262 }
2263
2264 return errors;
2265 }
2266
2267 int
2268 lt_dlisresident (lt_dlhandle handle)
2269 {
2270 if (!handle)
2271 {
2272 LT__SETERROR (INVALID_HANDLE);
2273 return -1;
2274 }
2275
2276 return LT_DLIS_RESIDENT (handle);
2277 }
2278
2279
2280
2281 /* --- MODULE INFORMATION --- */
2282
2283 typedef struct {
2284 const char *id_string;
2285 lt_dlhandle_interface *iface;
2286 } lt__interface_id;
2287
2288 lt_dlinterface_id
2289 lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2290 {
2291 lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2292
2293 /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
2294 can then be detected with lt_dlerror() if we return 0. */
2295 if (interface_id)
2296 {
2297 interface_id->id_string = lt__strdup (id_string);
2298 if (!interface_id->id_string)
2299 FREE (interface_id);
2300 else
2301 interface_id->iface = iface;
2302 }
2303
2304 return (lt_dlinterface_id) interface_id;
2305 }
2306
2307 void lt_dlinterface_free (lt_dlinterface_id key)
2308 {
2309 lt__interface_id *interface_id = (lt__interface_id *)key;
2310 FREE (interface_id->id_string);
2311 FREE (interface_id);
2312 }
2313
2314 void *
2315 lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2316 {
2317 int n_elements = 0;
2318 void *stale = (void *) 0;
2319 lt_dlhandle cur = handle;
2320 int i;
2321
2322 if (cur->interface_data)
2323 while (cur->interface_data[n_elements].key)
2324 ++n_elements;
2325
2326 for (i = 0; i < n_elements; ++i)
2327 {
2328 if (cur->interface_data[i].key == key)
2329 {
2330 stale = cur->interface_data[i].data;
2331 break;
2332 }
2333 }
2334
2335 /* Ensure that there is enough room in this handle's interface_data
2336 array to accept a new element (and an empty end marker). */
2337 if (i == n_elements)
2338 {
2339 lt_interface_data *temp
2340 = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2341
2342 if (!temp)
2343 {
2344 stale = 0;
2345 goto done;
2346 }
2347
2348 cur->interface_data = temp;
2349
2350 /* We only need this if we needed to allocate a new interface_data. */
2351 cur->interface_data[i].key = key;
2352 cur->interface_data[1+ i].key = 0;
2353 }
2354
2355 cur->interface_data[i].data = data;
2356
2357 done:
2358 return stale;
2359 }
2360
2361 void *
2362 lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2363 {
2364 void *result = (void *) 0;
2365 lt_dlhandle cur = handle;
2366
2367 /* Locate the index of the element with a matching KEY. */
2368 if (cur->interface_data)
2369 {
2370 int i;
2371 for (i = 0; cur->interface_data[i].key; ++i)
2372 {
2373 if (cur->interface_data[i].key == key)
2374 {
2375 result = cur->interface_data[i].data;
2376 break;
2377 }
2378 }
2379 }
2380
2381 return result;
2382 }
2383
2384 const lt_dlinfo *
2385 lt_dlgetinfo (lt_dlhandle handle)
2386 {
2387 if (!handle)
2388 {
2389 LT__SETERROR (INVALID_HANDLE);
2390 return 0;
2391 }
2392
2393 return &(handle->info);
2394 }
2395
2396
2397 lt_dlhandle
2398 lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2399 {
2400 lt_dlhandle handle = place;
2401 lt__interface_id *iterator = (lt__interface_id *) iface;
2402
2403 assert (iface); /* iface is a required argument */
2404
2405 if (!handle)
2406 handle = handles;
2407 else
2408 handle = handle->next;
2409
2410 /* advance while the interface check fails */
2411 while (handle && iterator->iface
2412 && ((*iterator->iface) (handle, iterator->id_string) != 0))
2413 {
2414 handle = handle->next;
2415 }
2416
2417 return handle;
2418 }
2419
2420
2421 lt_dlhandle
2422 lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2423 {
2424 lt_dlhandle handle = 0;
2425
2426 assert (iface); /* iface is a required argument */
2427
2428 while ((handle = lt_dlhandle_iterate (iface, handle)))
2429 {
2430 lt_dlhandle cur = handle;
2431 if (cur && cur->info.name && streq (cur->info.name, module_name))
2432 break;
2433 }
2434
2435 return handle;
2436 }
2437
2438
2439 int
2440 lt_dlhandle_map (lt_dlinterface_id iface,
2441 int (*func) (lt_dlhandle handle, void *data), void *data)
2442 {
2443 lt__interface_id *iterator = (lt__interface_id *) iface;
2444 lt_dlhandle cur = handles;
2445
2446 assert (iface); /* iface is a required argument */
2447
2448 while (cur)
2449 {
2450 int errorcode = 0;
2451
2452 /* advance while the interface check fails */
2453 while (cur && iterator->iface
2454 && ((*iterator->iface) (cur, iterator->id_string) != 0))
2455 {
2456 cur = cur->next;
2457 }
2458
2459 if ((errorcode = (*func) (cur, data)) != 0)
2460 return errorcode;
2461 }
2462
2463 return 0;
2464 }
/* */