Imported Upstream version 0.63.0
[hcoop/debian/courier-authlib.git] / libltdl / ltdl.c
CommitLineData
d9898ee8 1/* ltdl.c -- system independent dlopen wrapper
d9898ee8 2
8d138742
CE
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
10GNU Libltdl is free software; you can redistribute it and/or
d9898ee8 11modify it under the terms of the GNU Lesser General Public
12License as published by the Free Software Foundation; either
13version 2 of the License, or (at your option) any later version.
14
15As a special exception to the GNU Lesser General Public License,
16if you distribute this file as part of a program or library that
8d138742
CE
17is built using GNU Libtool, you may include this file under the
18same distribution terms that you use for the rest of that program.
d9898ee8 19
8d138742 20GNU Libltdl is distributed in the hope that it will be useful,
d9898ee8 21but WITHOUT ANY WARRANTY; without even the implied warranty of
8d138742
CE
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23GNU Lesser General Public License for more details.
d9898ee8 24
25You should have received a copy of the GNU Lesser General Public
8d138742
CE
26License along with GNU Libltdl; see the file COPYING.LIB. If not, a
27copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
28or obtained by writing to the Free Software Foundation, Inc.,
2951 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
d9898ee8 30*/
31
8d138742
CE
32#include "lt__private.h"
33#include "lt_system.h"
34#include "lt_dlloader.h"
d9898ee8 35
36
d9898ee8 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. */
8d138742
CE
45#undef LT_ARCHIVE_EXT
46#define LT_ARCHIVE_EXT ".la"
d9898ee8 47
48/* max. filename length */
8d138742 49#if !defined(LT_FILENAME_MAX)
d9898ee8 50# define LT_FILENAME_MAX 1024
51#endif
52
8d138742
CE
53#if !defined(LT_LIBEXT)
54# define LT_LIBEXT "a"
55#endif
56
d9898ee8 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
8d138742
CE
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)
d9898ee8 70
71
8d138742
CE
72static const char objdir[] = LT_OBJDIR;
73static const char archive_ext[] = LT_ARCHIVE_EXT;
74static const char libext[] = LT_LIBEXT;
75#if defined(LT_MODULE_EXT)
76static const char shlib_ext[] = LT_MODULE_EXT;
d9898ee8 77#endif
8d138742
CE
78#if defined(LT_DLSEARCH_PATH)
79static const char sys_dlsearch_path[] = LT_DLSEARCH_PATH;
d9898ee8 80#endif
81
d9898ee8 82
d9898ee8 83
8d138742
CE
84\f
85/* --- DYNAMIC MODULE LOADING --- */
d9898ee8 86
d9898ee8 87
8d138742
CE
88/* The type of a function used at each iteration of foreach_dirinpath(). */
89typedef int foreach_callback_func (char *filename, void *data1,
90 void *data2);
91/* foreachfile_callback itself calls a function of this type: */
92typedef int file_worker_func (const char *filename, void *data);
93
94
95static int foreach_dirinpath (const char *search_path,
96 const char *base_name,
97 foreach_callback_func *func,
98 void *data1, void *data2);
99static int find_file_callback (char *filename, void *data1,
100 void *data2);
101static int find_handle_callback (char *filename, void *data,
102 void *ignored);
103static int foreachfile_callback (char *filename, void *data1,
104 void *data2);
105
106
107static int canonicalize_path (const char *path, char **pcanonical);
108static int argzize_path (const char *path,
109 char **pargz, size_t *pargz_len);
110static FILE *find_file (const char *search_path,
111 const char *base_name, char **pdir);
112static lt_dlhandle *find_handle (const char *search_path,
113 const char *base_name,
114 lt_dlhandle *handle,
115 lt_dladvise advise);
116static 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);
120static int has_library_ext (const char *filename);
121static int load_deplibs (lt_dlhandle handle, char *deplibs);
122static int trim (char **dest, const char *str);
123static int try_dlopen (lt_dlhandle *handle,
124 const char *filename, const char *ext,
125 lt_dladvise advise);
126static int tryall_dlopen (lt_dlhandle *handle,
127 const char *filename,
128 lt_dladvise padvise,
129 const lt_dlvtable *vtable);
130static int unload_deplibs (lt_dlhandle handle);
131static int lt_argz_insert (char **pargz, size_t *pargz_len,
132 char *before, const char *entry);
133static int lt_argz_insertinorder (char **pargz, size_t *pargz_len,
134 const char *entry);
135static int lt_argz_insertdir (char **pargz, size_t *pargz_len,
136 const char *dirnam, struct dirent *dp);
137static int lt_dlpath_insertdir (char **ppath, char *before,
138 const char *dir);
139static int list_files_by_dir (const char *dirnam,
140 char **pargz, size_t *pargz_len);
141static int file_not_found (void);
142
143#ifdef HAVE_LIBDLLOADER
144static int loader_init_callback (lt_dlhandle handle);
145#endif /* HAVE_LIBDLLOADER */
146
147static int loader_init (lt_get_vtable *vtable_func,
148 lt_user_data data);
d9898ee8 149
8d138742
CE
150static char *user_search_path= 0;
151static lt_dlhandle handles = 0;
152static int initialized = 0;
d9898ee8 153
8d138742
CE
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!!). */
157void
158lt__alloc_die_callback (void)
d9898ee8 159{
8d138742 160 LT__SETERROR (NO_MEMORY);
d9898ee8 161}
162
8d138742
CE
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. */
167static int
168loader_init_callback (lt_dlhandle handle)
d9898ee8 169{
8d138742
CE
170 lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
171 return loader_init (vtable_func, 0);
d9898ee8 172}
8d138742 173#endif /* HAVE_LIBDLLOADER */
d9898ee8 174
8d138742
CE
175static int
176loader_init (lt_get_vtable *vtable_func, lt_user_data data)
d9898ee8 177{
8d138742
CE
178 const lt_dlvtable *vtable = 0;
179 int errors = 0;
d9898ee8 180
8d138742 181 if (vtable_func)
d9898ee8 182 {
8d138742 183 vtable = (*vtable_func) (data);
d9898ee8 184 }
d9898ee8 185
8d138742
CE
186 /* lt_dlloader_add will LT__SETERROR if it fails. */
187 errors += lt_dlloader_add (vtable);
d9898ee8 188
8d138742 189 assert (errors || vtable);
d9898ee8 190
8d138742 191 if ((!errors) && vtable->dlloader_init)
d9898ee8 192 {
8d138742 193 if ((*vtable->dlloader_init) (vtable->dlloader_data))
d9898ee8 194 {
8d138742
CE
195 LT__SETERROR (INIT_LOADER);
196 ++errors;
d9898ee8 197 }
d9898ee8 198 }
d9898ee8 199
8d138742 200 return errors;
d9898ee8 201}
d9898ee8 202
8d138742
CE
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)
d9898ee8 206
8d138742
CE
207LT_BEGIN_C_DECLS
208LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data);
209LT_END_C_DECLS
210#ifdef HAVE_LIBDLLOADER
211extern lt_dlsymlist preloaded_symbols;
212#endif
d9898ee8 213
8d138742
CE
214/* Initialize libltdl. */
215int
216lt_dlinit (void)
d9898ee8 217{
8d138742 218 int errors = 0;
d9898ee8 219
8d138742
CE
220 /* Initialize only at first call. */
221 if (++initialized == 1)
d9898ee8 222 {
8d138742
CE
223 lt__alloc_die = lt__alloc_die_callback;
224 handles = 0;
225 user_search_path = 0; /* empty search path */
d9898ee8 226
8d138742
CE
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);
d9898ee8 231
8d138742
CE
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)
d9898ee8 236 {
8d138742 237 errors += lt_dlpreload (&preloaded_symbols);
d9898ee8 238 }
d9898ee8 239
8d138742 240 if (!errors)
d9898ee8 241 {
8d138742 242 errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
d9898ee8 243 }
8d138742 244#endif /* HAVE_LIBDLLOADER */
d9898ee8 245 }
d9898ee8 246
8d138742
CE
247#ifdef LT_DEBUG_LOADERS
248 lt_dlloader_dump();
d9898ee8 249#endif
d9898ee8 250
251 return errors;
252}
253
254int
8d138742 255lt_dlexit (void)
d9898ee8 256{
257 /* shut down libltdl */
8d138742
CE
258 lt_dlloader *loader = 0;
259 lt_dlhandle handle = handles;
d9898ee8 260 int errors = 0;
261
d9898ee8 262 if (!initialized)
263 {
8d138742 264 LT__SETERROR (SHUTDOWN);
d9898ee8 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 */
8d138742 280 for (level = 1; handle; ++level)
d9898ee8 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))
d9898ee8 290 {
8d138742
CE
291 saw_nonresident = 1;
292 if (tmp->info.ref_count <= level)
ac40fd9e 293 {
8d138742
CE
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 }
ac40fd9e 310 }
d9898ee8 311 }
312 }
313 /* done if only resident modules are left */
314 if (!saw_nonresident)
315 break;
316 }
317
8d138742
CE
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
d9898ee8 324 /* close all loaders */
8d138742 325 for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
d9898ee8 326 {
8d138742
CE
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)))
d9898ee8 331 {
8d138742
CE
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;
d9898ee8 341 }
342
8d138742 343 loader = next;
d9898ee8 344 }
8d138742
CE
345
346 FREE(user_search_path);
d9898ee8 347 }
348
349 done:
d9898ee8 350 return errors;
351}
352
8d138742
CE
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. */
d9898ee8 357static int
8d138742
CE
358tryall_dlopen (lt_dlhandle *phandle, const char *filename,
359 lt_dladvise advise, const lt_dlvtable *vtable)
d9898ee8 360{
8d138742
CE
361 lt_dlhandle handle = handles;
362 const char * saved_error = 0;
363 int errors = 0;
d9898ee8 364
8d138742
CE
365#ifdef LT_DEBUG_LOADERS
366 fprintf (stderr, "tryall_dlopen (%s, %s)\n",
367 filename ? filename : "(null)",
368 vtable ? vtable->name : "(ALL)");
369#endif
d9898ee8 370
8d138742 371 LT__GETERROR (saved_error);
d9898ee8 372
373 /* check whether the module was already opened */
8d138742 374 for (;handle; handle = handle->next)
d9898ee8 375 {
8d138742
CE
376 if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
377 || (handle->info.filename && filename
378 && streq (handle->info.filename, filename)))
d9898ee8 379 {
380 break;
381 }
d9898ee8 382 }
383
8d138742 384 if (handle)
d9898ee8 385 {
8d138742
CE
386 ++handle->info.ref_count;
387 *phandle = handle;
d9898ee8 388 goto done;
389 }
390
8d138742 391 handle = *phandle;
d9898ee8 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 {
8d138742 401 LT__SETERROR (FILE_NOT_FOUND);
d9898ee8 402 ++errors;
403 goto done;
404 } */
405
8d138742
CE
406 handle->info.filename = lt__strdup (filename);
407 if (!handle->info.filename)
d9898ee8 408 {
409 ++errors;
410 goto done;
411 }
412 }
413 else
414 {
8d138742 415 handle->info.filename = 0;
d9898ee8 416 }
417
8d138742
CE
418 {
419 lt_dlloader loader = lt_dlloader_next (0);
420 const lt_dlvtable *loader_vtable;
d9898ee8 421
8d138742
CE
422 do
423 {
424 if (vtable)
425 loader_vtable = vtable;
426 else
427 loader_vtable = lt_dlloader_get (loader);
d9898ee8 428
8d138742
CE
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
d9898ee8 440
8d138742
CE
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 }
d9898ee8 464
8d138742
CE
465 handle->vtable = loader_vtable;
466 }
d9898ee8 467
8d138742 468 LT__SETERRORSTR (saved_error);
d9898ee8 469
8d138742 470 done:
d9898ee8 471 return errors;
472}
473
8d138742 474
d9898ee8 475static int
8d138742
CE
476tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
477 const char *dirname, const char *dlname,
478 lt_dladvise advise)
d9898ee8 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);
8d138742 488#if defined(LT_DIRSEP_CHAR)
d9898ee8 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. */
8d138742 501 filename = MALLOC (char, filename_len + 1);
d9898ee8 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 {
8d138742
CE
512 error += tryall_dlopen_module (handle, (const char *) 0,
513 prefix, filename, advise);
d9898ee8 514 }
8d138742 515 else if (tryall_dlopen (handle, filename, advise, 0) != 0)
d9898ee8 516 {
517 ++error;
518 }
519
8d138742 520 FREE (filename);
d9898ee8 521 return error;
522}
523
524static int
8d138742
CE
525find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
526 const char *dlname, const char *old_name, int installed,
527 lt_dladvise advise)
d9898ee8 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. */
8d138742 532 if (old_name && tryall_dlopen (handle, old_name, advise, 0) == 0)
d9898ee8 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 {
8d138742
CE
543 if (tryall_dlopen_module (handle, (const char *) 0,
544 libdir, dlname, advise) == 0)
d9898ee8 545 return 0;
546 }
547
548 /* try to open the not-installed module */
549 if (!installed)
550 {
8d138742
CE
551 if (tryall_dlopen_module (handle, dir, objdir,
552 dlname, advise) == 0)
d9898ee8 553 return 0;
554 }
555
556 /* maybe it was moved to another directory */
557 {
8d138742
CE
558 if (dir && (tryall_dlopen_module (handle, (const char *) 0,
559 dir, dlname, advise) == 0))
d9898ee8 560 return 0;
561 }
562 }
563
564 return 1;
565}
566
567
568static int
8d138742 569canonicalize_path (const char *path, char **pcanonical)
d9898ee8 570{
571 char *canonical = 0;
572
573 assert (path && *path);
574 assert (pcanonical);
575
8d138742 576 canonical = MALLOC (char, 1+ LT_STRLEN (path));
d9898ee8 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] != '/')
8d138742 598#if defined(LT_DIRSEP_CHAR)
d9898ee8 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)
8d138742 610#if defined(LT_DIRSEP_CHAR)
d9898ee8 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
629static int
8d138742 630argzize_path (const char *path, char **pargz, size_t *pargz_len)
d9898ee8 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:
8d138742 643 LT__SETERROR (NO_MEMORY);
d9898ee8 644 break;
645 default:
8d138742 646 LT__SETERROR (UNKNOWN);
d9898ee8 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. */
660static int
8d138742
CE
661foreach_dirinpath (const char *search_path, const char *base_name,
662 foreach_callback_func *func, void *data1, void *data2)
d9898ee8 663{
664 int result = 0;
8d138742 665 size_t filenamesize = 0;
d9898ee8 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
d9898ee8 672 if (!search_path || !*search_path)
673 {
8d138742 674 LT__SETERROR (FILE_NOT_FOUND);
d9898ee8 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
8d138742 690 if (1+ lendir + lenbase >= filenamesize)
d9898ee8 691 {
8d138742
CE
692 FREE (filename);
693 filenamesize = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
694 filename = MALLOC (char, filenamesize);
d9898ee8 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:
8d138742
CE
717 FREE (argz);
718 FREE (canonical);
719 FREE (filename);
d9898ee8 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. */
727static int
8d138742 728find_file_callback (char *filename, void *data1, void *data2)
d9898ee8 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
8d138742
CE
745 FREE (*pdir);
746 *pdir = lt__strdup (filename);
d9898ee8 747 is_done = (*pdir == 0) ? -1 : 1;
748 }
749
750 return is_done;
751}
752
753static FILE *
8d138742 754find_file (const char *search_path, const char *base_name, char **pdir)
d9898ee8 755{
756 FILE *file = 0;
757
758 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
759
760 return file;
761}
762
763static int
8d138742 764find_handle_callback (char *filename, void *data, void *data2)
d9898ee8 765{
8d138742 766 lt_dlhandle *phandle = (lt_dlhandle *) data;
d9898ee8 767 int notfound = access (filename, R_OK);
8d138742 768 lt_dladvise advise = (lt_dladvise) data2;
d9898ee8 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. */
8d138742
CE
776 if (tryall_dlopen (phandle, filename, advise, 0) != 0)
777 *phandle = 0;
d9898ee8 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. */
784static lt_dlhandle *
8d138742
CE
785find_handle (const char *search_path, const char *base_name,
786 lt_dlhandle *phandle, lt_dladvise advise)
d9898ee8 787{
788 if (!search_path)
789 return 0;
790
791 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
8d138742 792 phandle, advise))
d9898ee8 793 return 0;
794
8d138742
CE
795 return phandle;
796}
797
798#if !defined(LTDL_DLOPEN_DEPLIBS)
799static int
800load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
801{
802 handle->depcount = 0;
803 return 0;
d9898ee8 804}
805
8d138742 806#else /* defined(LTDL_DLOPEN_DEPLIBS) */
d9898ee8 807static int
8d138742 808load_deplibs (lt_dlhandle handle, char *deplibs)
d9898ee8 809{
d9898ee8 810 char *p, *save_search_path = 0;
811 int depcount = 0;
812 int i;
813 char **names = 0;
d9898ee8 814 int errors = 0;
815
816 handle->depcount = 0;
817
d9898ee8 818 if (!deplibs)
819 {
820 return errors;
821 }
822 ++errors;
823
d9898ee8 824 if (user_search_path)
825 {
8d138742 826 save_search_path = lt__strdup (user_search_path);
d9898ee8 827 if (!save_search_path)
828 goto cleanup;
829 }
830
831 /* extract search paths and count deplibs */
832 p = deplibs;
833 while (*p)
834 {
8d138742 835 if (!isspace ((unsigned char) *p))
d9898ee8 836 {
837 char *end = p+1;
8d138742 838 while (*end && !isspace((unsigned char) *end))
d9898ee8 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
8d138742 866
d9898ee8 867 if (!depcount)
868 {
869 errors = 0;
870 goto cleanup;
871 }
872
8d138742 873 names = MALLOC (char *, depcount);
d9898ee8 874 if (!names)
875 goto cleanup;
876
877 /* now only extract the actual deplibs */
878 depcount = 0;
879 p = deplibs;
880 while (*p)
881 {
8d138742 882 if (isspace ((unsigned char) *p))
d9898ee8 883 {
884 ++p;
885 }
886 else
887 {
888 char *end = p+1;
8d138742 889 while (*end && !isspace ((unsigned char) *end))
d9898ee8 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);
8d138742 902 name = MALLOC (char, 1+ name_len);
d9898ee8 903 if (name)
904 sprintf (name, "lib%s", p+2);
905 }
906 else
8d138742 907 name = lt__strdup(p);
d9898ee8 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 {
8d138742 926 lt_dlhandle cur = handle;
d9898ee8 927 int j = 0;
928
8d138742
CE
929 cur->deplibs = MALLOC (lt_dlhandle, depcount);
930 if (!cur->deplibs)
ac40fd9e 931 goto cleanup_names;
d9898ee8 932
933 for (i = 0; i < depcount; ++i)
934 {
8d138742
CE
935 cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
936 if (cur->deplibs[j])
d9898ee8 937 {
938 ++j;
939 }
940 }
941
8d138742 942 cur->depcount = j; /* Number of successfully loaded deplibs */
d9898ee8 943 errors = 0;
944 }
945
946 cleanup_names:
947 for (i = 0; i < depcount; ++i)
948 {
8d138742 949 FREE (names[i]);
d9898ee8 950 }
951
952 cleanup:
8d138742 953 FREE (names);
d9898ee8 954 /* restore the old search path */
8d138742
CE
955 if (save_search_path) {
956 MEMREASSIGN (user_search_path, save_search_path);
d9898ee8 957 }
d9898ee8 958
959 return errors;
960}
8d138742 961#endif /* defined(LTDL_DLOPEN_DEPLIBS) */
d9898ee8 962
963static int
8d138742 964unload_deplibs (lt_dlhandle handle)
d9898ee8 965{
966 int i;
967 int errors = 0;
8d138742 968 lt_dlhandle cur = handle;
d9898ee8 969
8d138742 970 if (cur->depcount)
d9898ee8 971 {
8d138742 972 for (i = 0; i < cur->depcount; ++i)
d9898ee8 973 {
8d138742 974 if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
d9898ee8 975 {
8d138742 976 errors += lt_dlclose (cur->deplibs[i]);
d9898ee8 977 }
978 }
8d138742 979 FREE (cur->deplibs);
d9898ee8 980 }
981
982 return errors;
983}
984
985static int
8d138742 986trim (char **dest, const char *str)
d9898ee8 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
8d138742 994 FREE (*dest);
d9898ee8 995
996 if (!end)
997 return 1;
998
999 if (len > 3 && str[0] == '\'')
1000 {
8d138742 1001 tmp = MALLOC (char, end - str);
d9898ee8 1002 if (!tmp)
1003 return 1;
1004
8d138742
CE
1005 memcpy(tmp, &str[1], (end - str) - 1);
1006 tmp[(end - str) - 1] = LT_EOS_CHAR;
d9898ee8 1007 *dest = tmp;
1008 }
1009 else
1010 {
1011 *dest = 0;
1012 }
1013
1014 return 0;
1015}
1016
8d138742 1017/* Read the .la file FILE. */
d9898ee8 1018static int
8d138742
CE
1019parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
1020 char **old_name, int *installed)
d9898ee8 1021{
8d138742
CE
1022 int errors = 0;
1023 size_t line_len = LT_FILENAME_MAX;
1024 char * line = MALLOC (char, line_len);
d9898ee8 1025
8d138742
CE
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 }
1125cleanup:
1126 FREE (line);
1127 return errors;
d9898ee8 1128}
1129
8d138742
CE
1130
1131/* Try to open FILENAME as a module. */
d9898ee8 1132static int
8d138742
CE
1133try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
1134 lt_dladvise advise)
d9898ee8 1135{
d9898ee8 1136 const char * saved_error = 0;
8d138742 1137 char * archive_name = 0;
d9898ee8 1138 char * canonical = 0;
1139 char * base_name = 0;
1140 char * dir = 0;
1141 char * name = 0;
8d138742 1142 char * attempt = 0;
d9898ee8 1143 int errors = 0;
1144 lt_dlhandle newhandle;
1145
1146 assert (phandle);
1147 assert (*phandle == 0);
1148
8d138742
CE
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);
d9898ee8 1156
1157 /* dlopen self? */
1158 if (!filename)
1159 {
8d138742 1160 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
d9898ee8 1161 if (*phandle == 0)
1162 return 1;
1163
d9898ee8 1164 newhandle = *phandle;
1165
1166 /* lt_dlclose()ing yourself is very bad! Disallow it. */
8d138742 1167 newhandle->info.is_resident = 1;
d9898ee8 1168
8d138742 1169 if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
d9898ee8 1170 {
8d138742 1171 FREE (*phandle);
d9898ee8 1172 return 1;
1173 }
1174
1175 goto register_handle;
1176 }
1177
1178 assert (filename && *filename);
1179
8d138742
CE
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
d9898ee8 1195 /* Doing this immediately allows internal functions to safely
1196 assume only canonicalized paths are passed. */
8d138742 1197 if (canonicalize_path (attempt, &canonical) != 0)
d9898ee8 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
8d138742 1210 dir = MALLOC (char, 1+ dirlen);
d9898ee8 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
8d138742 1223 MEMREASSIGN (base_name, canonical);
d9898ee8 1224
1225 assert (base_name && *base_name);
1226
d9898ee8 1227 ext = strrchr (base_name, '.');
8d138742
CE
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))
d9898ee8 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;
d9898ee8 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
d9898ee8 1315 /* Now try to open the .la file. If there is no directory name
8d138742
CE
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. */
d9898ee8 1319 if (!dir)
1320 {
8d138742 1321 const char *search_path = user_search_path;
d9898ee8 1322
d9898ee8 1323 if (search_path)
1324 file = find_file (user_search_path, base_name, &dir);
d9898ee8 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
8d138742 1333#if defined(LT_MODULE_PATH_VAR)
d9898ee8 1334 if (!file)
1335 {
8d138742 1336 search_path = getenv (LT_MODULE_PATH_VAR);
d9898ee8 1337 if (search_path)
1338 file = find_file (search_path, base_name, &dir);
1339 }
1340#endif
8d138742
CE
1341#if defined(LT_DLSEARCH_PATH)
1342 if (!file && *sys_dlsearch_path)
d9898ee8 1343 {
8d138742 1344 file = find_file (sys_dlsearch_path, base_name, &dir);
d9898ee8 1345 }
1346#endif
1347 }
ac40fd9e 1348 if (!file)
d9898ee8 1349 {
8d138742 1350 file = fopen (attempt, LT_READTEXT_MODE);
d9898ee8 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. */
8d138742
CE
1355 if (!file)
1356 {
1357 LT__SETERROR (FILE_NOT_FOUND);
1358 ++errors;
1359 goto cleanup;
d9898ee8 1360 }
1361
8d138742
CE
1362 /* read the .la file */
1363 if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1364 &old_name, &installed) != 0)
1365 ++errors;
1366
d9898ee8 1367 fclose (file);
d9898ee8 1368
1369 /* allocate the handle */
8d138742 1370 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
d9898ee8 1371 if (*phandle == 0)
1372 ++errors;
1373
1374 if (errors)
1375 {
8d138742
CE
1376 FREE (dlname);
1377 FREE (old_name);
1378 FREE (libdir);
1379 FREE (deplibs);
1380 FREE (*phandle);
d9898ee8 1381 goto cleanup;
1382 }
1383
1384 assert (*phandle);
1385
d9898ee8 1386 if (load_deplibs (*phandle, deplibs) == 0)
1387 {
1388 newhandle = *phandle;
1389 /* find_module may replace newhandle */
8d138742
CE
1390 if (find_module (&newhandle, dir, libdir, dlname, old_name,
1391 installed, advise))
d9898ee8 1392 {
1393 unload_deplibs (*phandle);
1394 ++errors;
1395 }
1396 }
1397 else
1398 {
1399 ++errors;
1400 }
1401
8d138742
CE
1402 FREE (dlname);
1403 FREE (old_name);
1404 FREE (libdir);
1405 FREE (deplibs);
1406
d9898ee8 1407 if (errors)
1408 {
8d138742 1409 FREE (*phandle);
d9898ee8 1410 goto cleanup;
1411 }
1412
1413 if (*phandle != newhandle)
1414 {
1415 unload_deplibs (*phandle);
1416 }
1417 }
1418 else
1419 {
1420 /* not a libtool module */
8d138742 1421 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
d9898ee8 1422 if (*phandle == 0)
1423 {
1424 ++errors;
1425 goto cleanup;
1426 }
1427
d9898ee8 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. */
8d138742
CE
1434 if ((dir || (!find_handle (user_search_path, base_name,
1435 &newhandle, advise)
d9898ee8 1436 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
8d138742
CE
1437 &newhandle, advise)
1438#if defined(LT_MODULE_PATH_VAR)
1439 && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1440 &newhandle, advise)
d9898ee8 1441#endif
8d138742
CE
1442#if defined(LT_DLSEARCH_PATH)
1443 && !find_handle (sys_dlsearch_path, base_name,
1444 &newhandle, advise)
d9898ee8 1445#endif
1446 )))
1447 {
8d138742
CE
1448 if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1449 {
1450 newhandle = NULL;
1451 }
d9898ee8 1452 }
1453
1454 if (!newhandle)
1455 {
8d138742 1456 FREE (*phandle);
d9898ee8 1457 ++errors;
1458 goto cleanup;
1459 }
1460 }
1461
1462 register_handle:
8d138742 1463 MEMREASSIGN (*phandle, newhandle);
d9898ee8 1464
1465 if ((*phandle)->info.ref_count == 0)
1466 {
1467 (*phandle)->info.ref_count = 1;
8d138742 1468 MEMREASSIGN ((*phandle)->info.name, name);
d9898ee8 1469
8d138742
CE
1470 (*phandle)->next = handles;
1471 handles = *phandle;
d9898ee8 1472 }
1473
8d138742 1474 LT__SETERRORSTR (saved_error);
d9898ee8 1475
1476 cleanup:
8d138742
CE
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);
d9898ee8 1484
1485 return errors;
1486}
1487
d9898ee8 1488
1489/* If the last error messge store was `FILE_NOT_FOUND', then return
1490 non-zero. */
1491static int
8d138742 1492file_not_found (void)
d9898ee8 1493{
1494 const char *error = 0;
1495
8d138742
CE
1496 LT__GETERROR (error);
1497 if (error == LT__STRERROR (FILE_NOT_FOUND))
d9898ee8 1498 return 1;
1499
1500 return 0;
1501}
1502
d9898ee8 1503
8d138742
CE
1504/* Unless FILENAME already bears a suitable library extension, then
1505 return 0. */
1506static int
1507has_library_ext (const char *filename)
1508{
1509 char * ext = 0;
d9898ee8 1510
1511 assert (filename);
1512
d9898ee8 1513 ext = strrchr (filename, '.');
1514
8d138742
CE
1515 if (ext && ((streq (ext, archive_ext))
1516#if defined(LT_MODULE_EXT)
1517 || (streq (ext, shlib_ext))
d9898ee8 1518#endif
8d138742 1519 ))
d9898ee8 1520 {
8d138742 1521 return 1;
d9898ee8 1522 }
1523
8d138742
CE
1524 return 0;
1525}
1526
1527
1528/* Initialise and configure a user lt_dladvise opaque object. */
1529
1530int
1531lt_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
1538int
1539lt_dladvise_destroy (lt_dladvise *padvise)
1540{
1541 if (padvise)
1542 FREE(*padvise);
1543 return 0;
1544}
1545
1546int
1547lt_dladvise_ext (lt_dladvise *padvise)
1548{
1549 assert (padvise && *padvise);
1550 (*padvise)->try_ext = 1;
1551 return 0;
1552}
1553
1554int
1555lt_dladvise_resident (lt_dladvise *padvise)
1556{
1557 assert (padvise && *padvise);
1558 (*padvise)->is_resident = 1;
1559 return 0;
1560}
1561
1562int
1563lt_dladvise_local (lt_dladvise *padvise)
1564{
1565 assert (padvise && *padvise);
1566 (*padvise)->is_symlocal = 1;
1567 return 0;
1568}
1569
1570int
1571lt_dladvise_global (lt_dladvise *padvise)
1572{
1573 assert (padvise && *padvise);
1574 (*padvise)->is_symglobal = 1;
1575 return 0;
1576}
1577
1578int
1579lt_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. */
1587lt_dlhandle
1588lt_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. */
1598lt_dlhandle
1599lt_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}
d9898ee8 1610
d9898ee8 1611
8d138742
CE
1612lt_dlhandle
1613lt_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)
d9898ee8 1620 {
8d138742
CE
1621 LT__SETERROR (CONFLICTING_FLAGS);
1622 return 0;
d9898ee8 1623 }
1624
8d138742
CE
1625 if (!filename
1626 || !advise
1627 || !advise->try_ext
1628 || has_library_ext (filename))
d9898ee8 1629 {
8d138742
CE
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)
d9898ee8 1633 return 0;
1634
8d138742 1635 return handle;
d9898ee8 1636 }
8d138742 1637 else if (filename && *filename)
d9898ee8 1638 {
d9898ee8 1639
8d138742
CE
1640 /* First try appending ARCHIVE_EXT. */
1641 errors += try_dlopen (&handle, filename, archive_ext, advise);
d9898ee8 1642
8d138742
CE
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;
d9898ee8 1659#endif
8d138742 1660 }
d9898ee8 1661
1662 /* Still here? Then we really did fail to locate any of the file
1663 names we tried. */
8d138742 1664 LT__SETERROR (FILE_NOT_FOUND);
d9898ee8 1665 return 0;
1666}
1667
1668
1669static int
8d138742
CE
1670lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1671 const char *entry)
d9898ee8 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
8d138742 1680 error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
d9898ee8 1681
1682 if (error)
1683 {
1684 switch (error)
1685 {
1686 case ENOMEM:
8d138742 1687 LT__SETERROR (NO_MEMORY);
d9898ee8 1688 break;
1689 default:
8d138742 1690 LT__SETERROR (UNKNOWN);
d9898ee8 1691 break;
1692 }
1693 return 1;
1694 }
1695
1696 return 0;
1697}
1698
1699static int
8d138742 1700lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
d9898ee8 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
1720static int
8d138742
CE
1721lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1722 struct dirent *dp)
d9898ee8 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);
8d138742 1736 end = dp->d_name + D_NAMLEN(dp);
d9898ee8 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;
8d138742 1763 buf = MALLOC (char, 1+ buf_len);
d9898ee8 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
8d138742 1778 FREE (buf);
d9898ee8 1779
1780 return errors;
1781}
1782
1783static int
8d138742 1784list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
d9898ee8 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). */
1818static int
8d138742 1819foreachfile_callback (char *dirname, void *data1, void *data2)
d9898ee8 1820{
8d138742 1821 file_worker_func *func = *(file_worker_func **) data1;
d9898ee8 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:
8d138742 1840 FREE (argz);
d9898ee8 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. */
1852int
8d138742
CE
1853lt_dlforeachfile (const char *search_path,
1854 int (*func) (const char *filename, void *data),
1855 void *data)
d9898ee8 1856{
1857 int is_done = 0;
8d138742 1858 file_worker_func **fpptr = &func;
d9898ee8 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,
8d138742 1865 foreachfile_callback, fpptr, data);
d9898ee8 1866 }
1867 else
1868 {
1869 /* Otherwise search the default paths. */
1870 is_done = foreach_dirinpath (user_search_path, 0,
8d138742 1871 foreachfile_callback, fpptr, data);
d9898ee8 1872 if (!is_done)
1873 {
8d138742
CE
1874 is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1875 foreachfile_callback, fpptr, data);
d9898ee8 1876 }
1877
8d138742 1878#if defined(LT_MODULE_PATH_VAR)
d9898ee8 1879 if (!is_done)
1880 {
8d138742
CE
1881 is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1882 foreachfile_callback, fpptr, data);
d9898ee8 1883 }
1884#endif
8d138742
CE
1885#if defined(LT_DLSEARCH_PATH)
1886 if (!is_done && *sys_dlsearch_path)
d9898ee8 1887 {
8d138742
CE
1888 is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1889 foreachfile_callback, fpptr, data);
d9898ee8 1890 }
1891#endif
1892 }
1893
1894 return is_done;
1895}
1896
1897int
8d138742 1898lt_dlclose (lt_dlhandle handle)
d9898ee8 1899{
1900 lt_dlhandle cur, last;
1901 int errors = 0;
1902
d9898ee8 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 {
8d138742 1913 LT__SETERROR (INVALID_HANDLE);
d9898ee8 1914 ++errors;
1915 goto done;
1916 }
1917
8d138742
CE
1918 cur = handle;
1919 cur->info.ref_count--;
d9898ee8 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). */
8d138742 1925 if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
d9898ee8 1926 {
8d138742 1927 lt_user_data data = cur->vtable->dlloader_data;
d9898ee8 1928
8d138742 1929 if (cur != handles)
d9898ee8 1930 {
8d138742 1931 last->next = cur->next;
d9898ee8 1932 }
1933 else
1934 {
8d138742 1935 handles = cur->next;
d9898ee8 1936 }
1937
8d138742
CE
1938 errors += cur->vtable->module_close (data, cur->module);
1939 errors += unload_deplibs (handle);
d9898ee8 1940
1941 /* It is up to the callers to free the data itself. */
8d138742 1942 FREE (cur->interface_data);
d9898ee8 1943
8d138742
CE
1944 FREE (cur->info.filename);
1945 FREE (cur->info.name);
1946 FREE (cur);
d9898ee8 1947
1948 goto done;
1949 }
1950
1951 if (LT_DLIS_RESIDENT (handle))
1952 {
8d138742 1953 LT__SETERROR (CLOSE_RESIDENT_MODULE);
d9898ee8 1954 ++errors;
1955 }
1956
1957 done:
d9898ee8 1958 return errors;
1959}
1960
8d138742
CE
1961void *
1962lt_dlsym (lt_dlhandle place, const char *symbol)
d9898ee8 1963{
1964 size_t lensym;
1965 char lsym[LT_SYMBOL_LENGTH];
1966 char *sym;
8d138742 1967 void *address;
d9898ee8 1968 lt_user_data data;
8d138742 1969 lt_dlhandle handle;
d9898ee8 1970
8d138742 1971 if (!place)
d9898ee8 1972 {
8d138742 1973 LT__SETERROR (INVALID_HANDLE);
d9898ee8 1974 return 0;
1975 }
1976
8d138742
CE
1977 handle = place;
1978
d9898ee8 1979 if (!symbol)
1980 {
8d138742 1981 LT__SETERROR (SYMBOL_NOT_FOUND);
d9898ee8 1982 return 0;
1983 }
1984
8d138742 1985 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
d9898ee8 1986 + LT_STRLEN (handle->info.name);
1987
1988 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
1989 {
1990 sym = lsym;
1991 }
1992 else
1993 {
8d138742 1994 sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
d9898ee8 1995 if (!sym)
1996 {
8d138742 1997 LT__SETERROR (BUFFER_OVERFLOW);
d9898ee8 1998 return 0;
1999 }
2000 }
2001
8d138742 2002 data = handle->vtable->dlloader_data;
d9898ee8 2003 if (handle->info.name)
2004 {
2005 const char *saved_error;
2006
8d138742 2007 LT__GETERROR (saved_error);
d9898ee8 2008
2009 /* this is a libtool module */
8d138742 2010 if (handle->vtable->sym_prefix)
d9898ee8 2011 {
8d138742 2012 strcpy(sym, handle->vtable->sym_prefix);
d9898ee8 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" */
8d138742 2024 address = handle->vtable->find_sym (data, handle->module, sym);
d9898ee8 2025 if (address)
2026 {
2027 if (sym != lsym)
2028 {
8d138742 2029 FREE (sym);
d9898ee8 2030 }
2031 return address;
2032 }
8d138742 2033 LT__SETERRORSTR (saved_error);
d9898ee8 2034 }
2035
2036 /* otherwise try "symbol" */
8d138742 2037 if (handle->vtable->sym_prefix)
d9898ee8 2038 {
8d138742 2039 strcpy(sym, handle->vtable->sym_prefix);
d9898ee8 2040 strcat(sym, symbol);
2041 }
2042 else
2043 {
2044 strcpy(sym, symbol);
2045 }
2046
8d138742 2047 address = handle->vtable->find_sym (data, handle->module, sym);
d9898ee8 2048 if (sym != lsym)
2049 {
8d138742 2050 FREE (sym);
d9898ee8 2051 }
2052
2053 return address;
2054}
2055
2056const char *
8d138742 2057lt_dlerror (void)
d9898ee8 2058{
2059 const char *error;
2060
8d138742
CE
2061 LT__GETERROR (error);
2062 LT__SETERRORSTR (0);
d9898ee8 2063
2064 return error ? error : NULL;
2065}
2066
2067static int
8d138742 2068lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
d9898ee8 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
8d138742 2092 *ppath = lt__strdup (dir);
d9898ee8 2093 if (*ppath == 0)
2094 ++errors;
2095
8d138742 2096 goto cleanup;
d9898ee8 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);
8d138742 2115 assert ((int) (before - *ppath) <= (int) strlen (*ppath));
d9898ee8 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);
8d138742 2127 MEMREASSIGN(*ppath, argz);
d9898ee8 2128
2129 cleanup:
8d138742
CE
2130 FREE (argz);
2131 FREE (canonical);
d9898ee8 2132
2133 return errors;
2134}
2135
2136int
8d138742 2137lt_dladdsearchdir (const char *search_dir)
d9898ee8 2138{
2139 int errors = 0;
2140
2141 if (search_dir && *search_dir)
2142 {
d9898ee8 2143 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2144 ++errors;
d9898ee8 2145 }
2146
2147 return errors;
2148}
2149
2150int
8d138742 2151lt_dlinsertsearchdir (const char *before, const char *search_dir)
d9898ee8 2152{
2153 int errors = 0;
2154
2155 if (before)
2156 {
d9898ee8 2157 if ((before < user_search_path)
2158 || (before >= user_search_path + LT_STRLEN (user_search_path)))
2159 {
8d138742 2160 LT__SETERROR (INVALID_POSITION);
d9898ee8 2161 return 1;
2162 }
d9898ee8 2163 }
2164
2165 if (search_dir && *search_dir)
2166 {
d9898ee8 2167 if (lt_dlpath_insertdir (&user_search_path,
2168 (char *) before, search_dir) != 0)
2169 {
2170 ++errors;
2171 }
d9898ee8 2172 }
2173
2174 return errors;
2175}
2176
2177int
8d138742 2178lt_dlsetsearchpath (const char *search_path)
d9898ee8 2179{
2180 int errors = 0;
2181
8d138742 2182 FREE (user_search_path);
d9898ee8 2183
2184 if (!search_path || !LT_STRLEN (search_path))
2185 {
2186 return errors;
2187 }
2188
d9898ee8 2189 if (canonicalize_path (search_path, &user_search_path) != 0)
2190 ++errors;
d9898ee8 2191
2192 return errors;
2193}
2194
2195const char *
8d138742 2196lt_dlgetsearchpath (void)
d9898ee8 2197{
2198 const char *saved_path;
2199
d9898ee8 2200 saved_path = user_search_path;
d9898ee8 2201
2202 return saved_path;
2203}
2204
2205int
8d138742 2206lt_dlmakeresident (lt_dlhandle handle)
d9898ee8 2207{
2208 int errors = 0;
2209
2210 if (!handle)
2211 {
8d138742 2212 LT__SETERROR (INVALID_HANDLE);
d9898ee8 2213 ++errors;
2214 }
2215 else
2216 {
8d138742 2217 handle->info.is_resident = 1;
d9898ee8 2218 }
2219
2220 return errors;
2221}
2222
2223int
8d138742 2224lt_dlisresident (lt_dlhandle handle)
d9898ee8 2225{
2226 if (!handle)
2227 {
8d138742 2228 LT__SETERROR (INVALID_HANDLE);
d9898ee8 2229 return -1;
2230 }
2231
2232 return LT_DLIS_RESIDENT (handle);
2233}
2234
2235
2236
d9898ee8 2237/* --- MODULE INFORMATION --- */
2238
8d138742
CE
2239typedef struct {
2240 const char *id_string;
2241 lt_dlhandle_interface *iface;
2242} lt__interface_id;
d9898ee8 2243
8d138742
CE
2244lt_dlinterface_id
2245lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
d9898ee8 2246{
8d138742 2247 lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
d9898ee8 2248
8d138742
CE
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)
d9898ee8 2252 {
8d138742
CE
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;
d9898ee8 2258 }
2259
8d138742 2260 return (lt_dlinterface_id) interface_id;
d9898ee8 2261}
2262
8d138742 2263void lt_dlinterface_free (lt_dlinterface_id key)
d9898ee8 2264{
8d138742
CE
2265 lt__interface_id *interface_id = (lt__interface_id *)key;
2266 FREE (interface_id->id_string);
2267 FREE (interface_id);
d9898ee8 2268}
2269
8d138742
CE
2270void *
2271lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
d9898ee8 2272{
2273 int n_elements = 0;
8d138742
CE
2274 void *stale = (void *) 0;
2275 lt_dlhandle cur = handle;
d9898ee8 2276 int i;
2277
8d138742
CE
2278 if (cur->interface_data)
2279 while (cur->interface_data[n_elements].key)
d9898ee8 2280 ++n_elements;
2281
2282 for (i = 0; i < n_elements; ++i)
2283 {
8d138742 2284 if (cur->interface_data[i].key == key)
d9898ee8 2285 {
8d138742 2286 stale = cur->interface_data[i].data;
d9898ee8 2287 break;
2288 }
2289 }
2290
8d138742 2291 /* Ensure that there is enough room in this handle's interface_data
d9898ee8 2292 array to accept a new element (and an empty end marker). */
2293 if (i == n_elements)
2294 {
8d138742
CE
2295 lt_interface_data *temp
2296 = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
d9898ee8 2297
2298 if (!temp)
2299 {
2300 stale = 0;
2301 goto done;
2302 }
2303
8d138742 2304 cur->interface_data = temp;
d9898ee8 2305
8d138742
CE
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;
d9898ee8 2309 }
2310
8d138742 2311 cur->interface_data[i].data = data;
d9898ee8 2312
2313 done:
d9898ee8 2314 return stale;
2315}
2316
8d138742
CE
2317void *
2318lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
d9898ee8 2319{
8d138742
CE
2320 void *result = (void *) 0;
2321 lt_dlhandle cur = handle;
d9898ee8 2322
2323 /* Locate the index of the element with a matching KEY. */
8d138742 2324 if (cur->interface_data)
d9898ee8 2325 {
8d138742
CE
2326 int i;
2327 for (i = 0; cur->interface_data[i].key; ++i)
d9898ee8 2328 {
8d138742 2329 if (cur->interface_data[i].key == key)
d9898ee8 2330 {
8d138742 2331 result = cur->interface_data[i].data;
d9898ee8 2332 break;
2333 }
2334 }
d9898ee8 2335 }
2336
8d138742 2337 return result;
d9898ee8 2338}
2339
8d138742
CE
2340const lt_dlinfo *
2341lt_dlgetinfo (lt_dlhandle handle)
d9898ee8 2342{
8d138742
CE
2343 if (!handle)
2344 {
2345 LT__SETERROR (INVALID_HANDLE);
2346 return 0;
2347 }
d9898ee8 2348
8d138742 2349 return &(handle->info);
d9898ee8 2350}
2351
8d138742
CE
2352
2353lt_dlhandle
2354lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
d9898ee8 2355{
8d138742
CE
2356 lt_dlhandle handle = place;
2357 lt__interface_id *iterator = (lt__interface_id *) iface;
d9898ee8 2358
8d138742
CE
2359 assert (iface); /* iface is a required argument */
2360
2361 if (!handle)
2362 handle = handles;
d9898ee8 2363 else
8d138742
CE
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))
d9898ee8 2369 {
8d138742 2370 handle = handle->next;
d9898ee8 2371 }
2372
8d138742 2373 return handle;
d9898ee8 2374}
2375
8d138742
CE
2376
2377lt_dlhandle
2378lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
d9898ee8 2379{
8d138742 2380 lt_dlhandle handle = 0;
d9898ee8 2381
8d138742
CE
2382 assert (iface); /* iface is a required argument */
2383
2384 while ((handle = lt_dlhandle_iterate (iface, handle)))
d9898ee8 2385 {
8d138742
CE
2386 lt_dlhandle cur = handle;
2387 if (cur && cur->info.name && streq (cur->info.name, module_name))
2388 break;
d9898ee8 2389 }
2390
8d138742 2391 return handle;
d9898ee8 2392}
2393
8d138742
CE
2394
2395int
2396lt_dlhandle_map (lt_dlinterface_id iface,
2397 int (*func) (lt_dlhandle handle, void *data), void *data)
d9898ee8 2398{
8d138742
CE
2399 lt__interface_id *iterator = (lt__interface_id *) iface;
2400 lt_dlhandle cur = handles;
d9898ee8 2401
8d138742
CE
2402 assert (iface); /* iface is a required argument */
2403
2404 while (cur)
d9898ee8 2405 {
8d138742
CE
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))
d9898ee8 2411 {
8d138742 2412 cur = cur->next;
d9898ee8 2413 }
8d138742
CE
2414
2415 if ((errorcode = (*func) (cur, data)) != 0)
2416 return errorcode;
d9898ee8 2417 }
d9898ee8 2418
8d138742 2419 return 0;
d9898ee8 2420}