/[svn]/ircd-hybrid-7.2/libltdl/ltdl.c
ViewVC logotype

Contents of /ircd-hybrid-7.2/libltdl/ltdl.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 945 - (show annotations)
Mon Jul 20 15:48:27 2009 UTC (10 years, 2 months ago) by michael
File MIME type: text/x-chdr
File size: 53895 byte(s)
- fixed some configure mess and imported latest libtool sources

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

Properties

Name Value
svn:eol-style native

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.26