2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / libltdl / ltdl.c
blob40ed84d417a9e893a97154daddf06eb4dd2bf05e
1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3 Originally by Thomas Tanner <tanner@ffii.org>
4 This file is part of GNU Libtool.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 As a special exception to the GNU Lesser General Public License,
12 if you distribute this file as part of a program or library that
13 is built using GNU libtool, you may include it under the same
14 distribution terms that you use for the rest of that program.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307 USA
28 #if HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #if HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
36 #if HAVE_STDIO_H
37 # include <stdio.h>
38 #endif
40 #if HAVE_STDLIB_H
41 # include <stdlib.h>
42 #endif
44 #if HAVE_STRING_H
45 # include <string.h>
46 #else
47 # if HAVE_STRINGS_H
48 # include <strings.h>
49 # endif
50 #endif
52 #if HAVE_CTYPE_H
53 # include <ctype.h>
54 #endif
56 #if HAVE_MALLOC_H
57 # include <malloc.h>
58 #endif
60 #if HAVE_MEMORY_H
61 # include <memory.h>
62 #endif
64 #if HAVE_ERRNO_H
65 # include <errno.h>
66 #endif
68 #if HAVE_BOEHM_GC
69 #include <gc.h>
70 #endif
73 #ifndef __WINDOWS__
74 # ifdef __WIN32__
75 # define __WINDOWS__
76 # endif
77 #endif
80 #undef LT_USE_POSIX_DIRENT
81 #ifdef HAVE_CLOSEDIR
82 # ifdef HAVE_OPENDIR
83 # ifdef HAVE_READDIR
84 # ifdef HAVE_DIRENT_H
85 # define LT_USE_POSIX_DIRENT
86 # endif /* HAVE_DIRENT_H */
87 # endif /* HAVE_READDIR */
88 # endif /* HAVE_OPENDIR */
89 #endif /* HAVE_CLOSEDIR */
92 #undef LT_USE_WINDOWS_DIRENT_EMULATION
93 #ifndef LT_USE_POSIX_DIRENT
94 # ifdef __WINDOWS__
95 # define LT_USE_WINDOWS_DIRENT_EMULATION
96 # endif /* __WINDOWS__ */
97 #endif /* LT_USE_POSIX_DIRENT */
100 #ifdef LT_USE_POSIX_DIRENT
101 # include <dirent.h>
102 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
103 #else
104 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
105 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
106 # else
107 # define dirent direct
108 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
109 # if HAVE_SYS_NDIR_H
110 # include <sys/ndir.h>
111 # endif
112 # if HAVE_SYS_DIR_H
113 # include <sys/dir.h>
114 # endif
115 # if HAVE_NDIR_H
116 # include <ndir.h>
117 # endif
118 # endif
119 #endif
121 #if HAVE_ARGZ_H
122 # include <argz.h>
123 #endif
125 #if HAVE_ASSERT_H
126 # include <assert.h>
127 #else
128 # define assert(arg) ((void) 0)
129 #endif
131 #include "ltdl.h"
133 #if WITH_DMALLOC
134 # include <dmalloc.h>
135 #endif
140 /* --- WINDOWS SUPPORT --- */
143 #ifdef DLL_EXPORT
144 # define LT_GLOBAL_DATA __declspec(dllexport)
145 #else
146 # define LT_GLOBAL_DATA
147 #endif
149 /* fopen() mode flags for reading a text file */
150 #undef LT_READTEXT_MODE
151 #ifdef __WINDOWS__
152 # define LT_READTEXT_MODE "rt"
153 #else
154 # define LT_READTEXT_MODE "r"
155 #endif
157 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
159 #include <windows.h>
161 #define dirent lt_dirent
162 #define DIR lt_DIR
164 struct dirent
166 char d_name[2048];
167 int d_namlen;
170 typedef struct _DIR
172 HANDLE hSearch;
173 WIN32_FIND_DATA Win32FindData;
174 BOOL firsttime;
175 struct dirent file_info;
176 } DIR;
178 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
181 /* --- MANIFEST CONSTANTS --- */
184 /* Standard libltdl search path environment variable name */
185 #undef LTDL_SEARCHPATH_VAR
186 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
188 /* Standard libtool archive file extension. */
189 #undef LTDL_ARCHIVE_EXT
190 #define LTDL_ARCHIVE_EXT ".la"
192 /* max. filename length */
193 #ifndef LT_FILENAME_MAX
194 # define LT_FILENAME_MAX 1024
195 #endif
197 /* This is the maximum symbol size that won't require malloc/free */
198 #undef LT_SYMBOL_LENGTH
199 #define LT_SYMBOL_LENGTH 128
201 /* This accounts for the _LTX_ separator */
202 #undef LT_SYMBOL_OVERHEAD
203 #define LT_SYMBOL_OVERHEAD 5
208 /* --- MEMORY HANDLING --- */
211 /* These are the functions used internally. In addition to making
212 use of the associated function pointers above, they also perform
213 error handling. */
214 static char *lt_estrdup LT_PARAMS((const char *str));
215 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
216 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
218 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
219 #define rpl_realloc realloc
221 /* These are the pointers that can be changed by the caller: */
222 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
223 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
224 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
225 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
226 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
227 = (void (*) LT_PARAMS((lt_ptr))) free;
229 /* The following macros reduce the amount of typing needed to cast
230 assigned memory. */
231 #if WITH_DMALLOC
233 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
234 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
235 #define LT_DLFREE(p) \
236 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
238 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
239 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
241 #else
243 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
244 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
245 #define LT_DLFREE(p) \
246 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
248 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
249 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
251 #endif
253 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
254 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
255 } LT_STMT_END
258 /* --- REPLACEMENT FUNCTIONS --- */
261 #undef strdup
262 #define strdup rpl_strdup
264 static char *strdup LT_PARAMS((const char *str));
266 static char *
267 strdup(str)
268 const char *str;
270 char *tmp = 0;
272 if (str)
274 tmp = LT_DLMALLOC (char, 1+ strlen (str));
275 if (tmp)
277 strcpy(tmp, str);
281 return tmp;
285 #if ! HAVE_STRCMP
287 #undef strcmp
288 #define strcmp rpl_strcmp
290 static int strcmp LT_PARAMS((const char *str1, const char *str2));
292 static int
293 strcmp (str1, str2)
294 const char *str1;
295 const char *str2;
297 if (str1 == str2)
298 return 0;
299 if (str1 == 0)
300 return -1;
301 if (str2 == 0)
302 return 1;
304 for (;*str1 && *str2; ++str1, ++str2)
306 if (*str1 != *str2)
307 break;
310 return (int)(*str1 - *str2);
312 #endif
315 #if ! HAVE_STRCHR
317 # if HAVE_INDEX
318 # define strchr index
319 # else
320 # define strchr rpl_strchr
322 static const char *strchr LT_PARAMS((const char *str, int ch));
324 static const char*
325 strchr(str, ch)
326 const char *str;
327 int ch;
329 const char *p;
331 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
332 /*NOWORK*/;
334 return (*p == (char)ch) ? p : 0;
337 # endif
338 #endif /* !HAVE_STRCHR */
341 #if ! HAVE_STRRCHR
343 # if HAVE_RINDEX
344 # define strrchr rindex
345 # else
346 # define strrchr rpl_strrchr
348 static const char *strrchr LT_PARAMS((const char *str, int ch));
350 static const char*
351 strrchr(str, ch)
352 const char *str;
353 int ch;
355 const char *p, *q = 0;
357 for (p = str; *p != LT_EOS_CHAR; ++p)
359 if (*p == (char) ch)
361 q = p;
365 return q;
368 # endif
369 #endif
371 /* NOTE: Neither bcopy nor the memcpy implementation below can
372 reliably handle copying in overlapping areas of memory. Use
373 memmove (for which there is a fallback implmentation below)
374 if you need that behaviour. */
375 #if ! HAVE_MEMCPY
377 # if HAVE_BCOPY
378 # define memcpy(dest, src, size) bcopy (src, dest, size)
379 # else
380 # define memcpy rpl_memcpy
382 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
384 static lt_ptr
385 memcpy (dest, src, size)
386 lt_ptr dest;
387 const lt_ptr src;
388 size_t size;
390 size_t i = 0;
392 for (i = 0; i < size; ++i)
394 dest[i] = src[i];
397 return dest;
400 # endif /* !HAVE_BCOPY */
401 #endif /* !HAVE_MEMCPY */
403 #if ! HAVE_MEMMOVE
404 # define memmove rpl_memmove
406 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
408 static lt_ptr
409 memmove (dest, src, size)
410 lt_ptr dest;
411 const lt_ptr src;
412 size_t size;
414 size_t i;
416 if (dest < src)
417 for (i = 0; i < size; ++i)
419 dest[i] = src[i];
421 else if (dest > src)
422 for (i = size -1; i >= 0; --i)
424 dest[i] = src[i];
427 return dest;
430 #endif /* !HAVE_MEMMOVE */
432 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
434 static void closedir LT_PARAMS((DIR *entry));
436 static void
437 closedir(entry)
438 DIR *entry;
440 assert(entry != (DIR *) NULL);
441 FindClose(entry->hSearch);
442 lt_dlfree((lt_ptr)entry);
446 static DIR * opendir LT_PARAMS((const char *path));
448 static DIR*
449 opendir (path)
450 const char *path;
452 char file_specification[LT_FILENAME_MAX];
453 DIR *entry;
455 assert(path != (char *) NULL);
456 (void) strncpy(file_specification,path,LT_FILENAME_MAX-1);
457 (void) strcat(file_specification,"\\");
458 entry = LT_DLMALLOC (DIR,sizeof(DIR));
459 if (entry != (DIR *) 0)
461 entry->firsttime = TRUE;
462 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
464 if (entry->hSearch == INVALID_HANDLE_VALUE)
466 (void) strcat(file_specification,"\\*.*");
467 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
468 if (entry->hSearch == INVALID_HANDLE_VALUE)
470 LT_DLFREE (entry);
471 return (DIR *) 0;
474 return(entry);
478 static struct dirent *readdir LT_PARAMS((DIR *entry));
480 static struct dirent *readdir(entry)
481 DIR *entry;
484 status;
486 if (entry == (DIR *) 0)
487 return((struct dirent *) 0);
488 if (!entry->firsttime)
490 status = FindNextFile(entry->hSearch,&entry->Win32FindData);
491 if (status == 0)
492 return((struct dirent *) 0);
494 entry->firsttime = FALSE;
495 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
496 LT_FILENAME_MAX-1);
497 entry->file_info.d_namlen = strlen(entry->file_info.d_name);
498 return(&entry->file_info);
501 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
503 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
504 ``realloc is not entirely portable''
505 In any case we want to use the allocator supplied by the user without
506 burdening them with an lt_dlrealloc function pointer to maintain.
507 Instead implement our own version (with known boundary conditions)
508 using lt_dlmalloc and lt_dlfree. */
510 /* #undef realloc
511 #define realloc rpl_realloc
513 #if 0
514 /* You can't (re)define realloc unless you also (re)define malloc.
515 Right now, this code uses the size of the *destination* to decide
516 how much to copy. That's not right, but you can't know the size
517 of the source unless you know enough about, or wrote malloc. So
518 this code is disabled... */
520 static lt_ptr
521 realloc (ptr, size)
522 lt_ptr ptr;
523 size_t size;
525 if (size == 0)
527 /* For zero or less bytes, free the original memory */
528 if (ptr != 0)
530 lt_dlfree (ptr);
533 return (lt_ptr) 0;
535 else if (ptr == 0)
537 /* Allow reallocation of a NULL pointer. */
538 return lt_dlmalloc (size);
540 else
542 /* Allocate a new block, copy and free the old block. */
543 lt_ptr mem = lt_dlmalloc (size);
545 if (mem)
547 memcpy (mem, ptr, size);
548 lt_dlfree (ptr);
551 /* Note that the contents of PTR are not damaged if there is
552 insufficient memory to realloc. */
553 return mem;
556 #endif
559 #if ! HAVE_ARGZ_APPEND
560 # define argz_append rpl_argz_append
562 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
563 const char *buf, size_t buf_len));
565 static error_t
566 argz_append (pargz, pargz_len, buf, buf_len)
567 char **pargz;
568 size_t *pargz_len;
569 const char *buf;
570 size_t buf_len;
572 size_t argz_len;
573 char *argz;
575 assert (pargz);
576 assert (pargz_len);
577 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
579 /* If nothing needs to be appended, no more work is required. */
580 if (buf_len == 0)
581 return 0;
583 /* Ensure there is enough room to append BUF_LEN. */
584 argz_len = *pargz_len + buf_len;
585 argz = LT_DLREALLOC (char, *pargz, argz_len);
586 if (!argz)
587 return ENOMEM;
589 /* Copy characters from BUF after terminating '\0' in ARGZ. */
590 memcpy (argz + *pargz_len, buf, buf_len);
592 /* Assign new values. */
593 *pargz = argz;
594 *pargz_len = argz_len;
596 return 0;
598 #endif /* !HAVE_ARGZ_APPEND */
601 #if ! HAVE_ARGZ_CREATE_SEP
602 # define argz_create_sep rpl_argz_create_sep
604 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
605 char **pargz, size_t *pargz_len));
607 static error_t
608 argz_create_sep (str, delim, pargz, pargz_len)
609 const char *str;
610 int delim;
611 char **pargz;
612 size_t *pargz_len;
614 size_t argz_len;
615 char *argz = 0;
617 assert (str);
618 assert (pargz);
619 assert (pargz_len);
621 /* Make a copy of STR, but replacing each occurence of
622 DELIM with '\0'. */
623 argz_len = 1+ LT_STRLEN (str);
624 if (argz_len)
626 const char *p;
627 char *q;
629 argz = LT_DLMALLOC (char, argz_len);
630 if (!argz)
631 return ENOMEM;
633 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
635 if (*p == delim)
637 /* Ignore leading delimiters, and fold consecutive
638 delimiters in STR into a single '\0' in ARGZ. */
639 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
640 *q++ = LT_EOS_CHAR;
641 else
642 --argz_len;
644 else
645 *q++ = *p;
647 /* Copy terminating LT_EOS_CHAR. */
648 *q = *p;
651 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
652 if (!argz_len)
653 LT_DLFREE (argz);
655 /* Assign new values. */
656 *pargz = argz;
657 *pargz_len = argz_len;
659 return 0;
661 #endif /* !HAVE_ARGZ_CREATE_SEP */
664 #if ! HAVE_ARGZ_INSERT
665 # define argz_insert rpl_argz_insert
667 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
668 char *before, const char *entry));
670 static error_t
671 argz_insert (pargz, pargz_len, before, entry)
672 char **pargz;
673 size_t *pargz_len;
674 char *before;
675 const char *entry;
677 assert (pargz);
678 assert (pargz_len);
679 assert (entry && *entry);
681 /* No BEFORE address indicates ENTRY should be inserted after the
682 current last element. */
683 if (!before)
684 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
686 /* This probably indicates a programmer error, but to preserve
687 semantics, scan back to the start of an entry if BEFORE points
688 into the middle of it. */
689 while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
690 --before;
693 size_t entry_len = 1+ LT_STRLEN (entry);
694 size_t argz_len = *pargz_len + entry_len;
695 size_t offset = before - *pargz;
696 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
698 if (!argz)
699 return ENOMEM;
701 /* Make BEFORE point to the equivalent offset in ARGZ that it
702 used to have in *PARGZ incase realloc() moved the block. */
703 before = argz + offset;
705 /* Move the ARGZ entries starting at BEFORE up into the new
706 space at the end -- making room to copy ENTRY into the
707 resulting gap. */
708 memmove (before + entry_len, before, *pargz_len - offset);
709 memcpy (before, entry, entry_len);
711 /* Assign new values. */
712 *pargz = argz;
713 *pargz_len = argz_len;
716 return 0;
718 #endif /* !HAVE_ARGZ_INSERT */
721 #if ! HAVE_ARGZ_NEXT
722 # define argz_next rpl_argz_next
724 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
725 const char *entry));
727 static char *
728 argz_next (argz, argz_len, entry)
729 char *argz;
730 size_t argz_len;
731 const char *entry;
733 assert ((argz && argz_len) || (!argz && !argz_len));
735 if (entry)
737 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
738 within the ARGZ vector. */
739 assert ((!argz && !argz_len)
740 || ((argz <= entry) && (entry < (argz + argz_len))));
742 /* Move to the char immediately after the terminating
743 '\0' of ENTRY. */
744 entry = 1+ strchr (entry, LT_EOS_CHAR);
746 /* Return either the new ENTRY, or else NULL if ARGZ is
747 exhausted. */
748 return (entry >= argz + argz_len) ? 0 : (char *) entry;
750 else
752 /* This should probably be flagged as a programmer error,
753 since starting an argz_next loop with the iterator set
754 to ARGZ is safer. To preserve semantics, handle the NULL
755 case by returning the start of ARGZ (if any). */
756 if (argz_len > 0)
757 return argz;
758 else
759 return 0;
762 #endif /* !HAVE_ARGZ_NEXT */
766 #if ! HAVE_ARGZ_STRINGIFY
767 # define argz_stringify rpl_argz_stringify
769 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
770 int sep));
772 static void
773 argz_stringify (argz, argz_len, sep)
774 char *argz;
775 size_t argz_len;
776 int sep;
778 assert ((argz && argz_len) || (!argz && !argz_len));
780 if (sep)
782 --argz_len; /* don't stringify the terminating EOS */
783 while (--argz_len > 0)
785 if (argz[argz_len] == LT_EOS_CHAR)
786 argz[argz_len] = sep;
790 #endif /* !HAVE_ARGZ_STRINGIFY */
795 /* --- TYPE DEFINITIONS -- */
798 /* This type is used for the array of caller data sets in each handler. */
799 typedef struct {
800 lt_dlcaller_id key;
801 lt_ptr data;
802 } lt_caller_data;
807 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
810 /* Extract the diagnostic strings from the error table macro in the same
811 order as the enumerated indices in ltdl.h. */
813 static const char *lt_dlerror_strings[] =
815 #define LT_ERROR(name, diagnostic) (diagnostic),
816 lt_dlerror_table
817 #undef LT_ERROR
822 /* This structure is used for the list of registered loaders. */
823 struct lt_dlloader {
824 struct lt_dlloader *next;
825 const char *loader_name; /* identifying name for each loader */
826 const char *sym_prefix; /* prefix for symbols */
827 lt_module_open *module_open;
828 lt_module_close *module_close;
829 lt_find_sym *find_sym;
830 lt_dlloader_exit *dlloader_exit;
831 lt_user_data dlloader_data;
834 struct lt_dlhandle_struct {
835 struct lt_dlhandle_struct *next;
836 lt_dlloader *loader; /* dlopening interface */
837 lt_dlinfo info;
838 int depcount; /* number of dependencies */
839 lt_dlhandle *deplibs; /* dependencies */
840 lt_module module; /* system module handle */
841 lt_ptr system; /* system specific data */
842 lt_caller_data *caller_data; /* per caller associated data */
843 int flags; /* various boolean stats */
846 /* Various boolean flags can be stored in the flags field of an
847 lt_dlhandle_struct... */
848 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
849 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
851 #define LT_DLRESIDENT_FLAG (0x01 << 0)
852 /* ...add more flags here... */
854 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
857 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
859 static const char objdir[] = LTDL_OBJDIR;
860 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
861 #ifdef LTDL_SHLIB_EXT
862 static const char shlib_ext[] = LTDL_SHLIB_EXT;
863 #endif
864 #ifdef LTDL_SYSSEARCHPATH
865 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
866 #endif
871 /* --- MUTEX LOCKING --- */
874 /* Macros to make it easier to run the lock functions only if they have
875 been registered. The reason for the complicated lock macro is to
876 ensure that the stored error message from the last error is not
877 accidentally erased if the current function doesn't generate an
878 error of its own. */
879 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
880 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
881 } LT_STMT_END
882 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
883 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
884 } LT_STMT_END
885 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
886 if (lt_dlmutex_seterror_func) \
887 (*lt_dlmutex_seterror_func) (errormsg); \
888 else lt_dllast_error = (errormsg); } LT_STMT_END
889 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
890 if (lt_dlmutex_seterror_func) \
891 (errormsg) = (*lt_dlmutex_geterror_func) (); \
892 else (errormsg) = lt_dllast_error; } LT_STMT_END
894 /* The mutex functions stored here are global, and are necessarily the
895 same for all threads that wish to share access to libltdl. */
896 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
897 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
898 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
899 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
900 static const char *lt_dllast_error = 0;
903 /* Either set or reset the mutex functions. Either all the arguments must
904 be valid functions, or else all can be NULL to turn off locking entirely.
905 The registered functions should be manipulating a static global lock
906 from the lock() and unlock() callbacks, which needs to be reentrant. */
908 lt_dlmutex_register (lock, unlock, seterror, geterror)
909 lt_dlmutex_lock *lock;
910 lt_dlmutex_unlock *unlock;
911 lt_dlmutex_seterror *seterror;
912 lt_dlmutex_geterror *geterror;
914 lt_dlmutex_unlock *old_unlock = unlock;
915 int errors = 0;
917 /* Lock using the old lock() callback, if any. */
918 LT_DLMUTEX_LOCK ();
920 if ((lock && unlock && seterror && geterror)
921 || !(lock || unlock || seterror || geterror))
923 lt_dlmutex_lock_func = lock;
924 lt_dlmutex_unlock_func = unlock;
925 lt_dlmutex_geterror_func = geterror;
927 else
929 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
930 ++errors;
933 /* Use the old unlock() callback we saved earlier, if any. Otherwise
934 record any errors using internal storage. */
935 if (old_unlock)
936 (*old_unlock) ();
938 /* Return the number of errors encountered during the execution of
939 this function. */
940 return errors;
946 /* --- ERROR HANDLING --- */
949 static const char **user_error_strings = 0;
950 static int errorcount = LT_ERROR_MAX;
953 lt_dladderror (diagnostic)
954 const char *diagnostic;
956 int errindex = 0;
957 int result = -1;
958 const char **temp = (const char **) 0;
960 assert (diagnostic);
962 LT_DLMUTEX_LOCK ();
964 errindex = errorcount - LT_ERROR_MAX;
965 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
966 if (temp)
968 user_error_strings = temp;
969 user_error_strings[errindex] = diagnostic;
970 result = errorcount++;
973 LT_DLMUTEX_UNLOCK ();
975 return result;
979 lt_dlseterror (errindex)
980 int errindex;
982 int errors = 0;
984 LT_DLMUTEX_LOCK ();
986 if (errindex >= errorcount || errindex < 0)
988 /* Ack! Error setting the error message! */
989 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
990 ++errors;
992 else if (errindex < LT_ERROR_MAX)
994 /* No error setting the error message! */
995 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
997 else
999 /* No error setting the error message! */
1000 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
1003 LT_DLMUTEX_UNLOCK ();
1005 return errors;
1008 static lt_ptr
1009 lt_emalloc (size)
1010 size_t size;
1012 lt_ptr mem = lt_dlmalloc (size);
1013 if (size && !mem)
1014 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1015 return mem;
1018 static lt_ptr
1019 lt_erealloc (addr, size)
1020 lt_ptr addr;
1021 size_t size;
1023 lt_ptr mem = realloc (addr, size);
1024 if (size && !mem)
1025 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1026 return mem;
1029 static char *
1030 lt_estrdup (str)
1031 const char *str;
1033 char *copy = strdup (str);
1034 if (LT_STRLEN (str) && !copy)
1035 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1036 return copy;
1042 /* --- DLOPEN() INTERFACE LOADER --- */
1045 #if HAVE_LIBDL
1047 /* dynamic linking with dlopen/dlsym */
1049 #if HAVE_DLFCN_H
1050 # include <dlfcn.h>
1051 #endif
1053 #if HAVE_SYS_DL_H
1054 # include <sys/dl.h>
1055 #endif
1057 #ifdef RTLD_GLOBAL
1058 # define LT_GLOBAL RTLD_GLOBAL
1059 #else
1060 # ifdef DL_GLOBAL
1061 # define LT_GLOBAL DL_GLOBAL
1062 # endif
1063 #endif /* !RTLD_GLOBAL */
1064 #ifndef LT_GLOBAL
1065 # define LT_GLOBAL 0
1066 #endif /* !LT_GLOBAL */
1068 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1069 find out it does not work in some platform. */
1070 #ifndef LT_LAZY_OR_NOW
1071 # ifdef RTLD_LAZY
1072 # define LT_LAZY_OR_NOW RTLD_LAZY
1073 # else
1074 # ifdef DL_LAZY
1075 # define LT_LAZY_OR_NOW DL_LAZY
1076 # endif
1077 # endif /* !RTLD_LAZY */
1078 #endif
1079 #ifndef LT_LAZY_OR_NOW
1080 # ifdef RTLD_NOW
1081 # define LT_LAZY_OR_NOW RTLD_NOW
1082 # else
1083 # ifdef DL_NOW
1084 # define LT_LAZY_OR_NOW DL_NOW
1085 # endif
1086 # endif /* !RTLD_NOW */
1087 #endif
1088 #ifndef LT_LAZY_OR_NOW
1089 # define LT_LAZY_OR_NOW 0
1090 #endif /* !LT_LAZY_OR_NOW */
1092 #if HAVE_DLERROR
1093 # define DLERROR(arg) dlerror ()
1094 #else
1095 # define DLERROR(arg) LT_DLSTRERROR (arg)
1096 #endif
1098 static lt_module
1099 sys_dl_open (loader_data, filename)
1100 lt_user_data loader_data;
1101 const char *filename;
1103 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1105 if (!module)
1107 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1110 return module;
1113 static int
1114 sys_dl_close (loader_data, module)
1115 lt_user_data loader_data;
1116 lt_module module;
1118 int errors = 0;
1120 if (dlclose (module) != 0)
1122 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1123 ++errors;
1126 return errors;
1129 static lt_ptr
1130 sys_dl_sym (loader_data, module, symbol)
1131 lt_user_data loader_data;
1132 lt_module module;
1133 const char *symbol;
1135 lt_ptr address = dlsym (module, symbol);
1137 if (!address)
1139 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1142 return address;
1145 static struct lt_user_dlloader sys_dl =
1147 # ifdef NEED_USCORE
1148 "_",
1149 # else
1151 # endif
1152 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1155 #endif /* HAVE_LIBDL */
1159 /* --- SHL_LOAD() INTERFACE LOADER --- */
1161 #if HAVE_SHL_LOAD
1163 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1165 #ifdef HAVE_DL_H
1166 # include <dl.h>
1167 #endif
1169 /* some flags are missing on some systems, so we provide
1170 * harmless defaults.
1172 * Mandatory:
1173 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1174 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1176 * Optionally:
1177 * BIND_FIRST - Place the library at the head of the symbol search
1178 * order.
1179 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1180 * unsatisfied symbols as fatal. This flag allows
1181 * binding of unsatisfied code symbols to be deferred
1182 * until use.
1183 * [Perl: For certain libraries, like DCE, deferred
1184 * binding often causes run time problems. Adding
1185 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1186 * unresolved references in situations like this.]
1187 * BIND_NOSTART - Do not call the initializer for the shared library
1188 * when the library is loaded, nor on a future call to
1189 * shl_unload().
1190 * BIND_VERBOSE - Print verbose messages concerning possible
1191 * unsatisfied symbols.
1193 * hp9000s700/hp9000s800:
1194 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1195 * present at library load time.
1196 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1197 * library specified by the path argument.
1200 #ifndef DYNAMIC_PATH
1201 # define DYNAMIC_PATH 0
1202 #endif
1203 #ifndef BIND_RESTRICTED
1204 # define BIND_RESTRICTED 0
1205 #endif
1207 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1209 static lt_module
1210 sys_shl_open (loader_data, filename)
1211 lt_user_data loader_data;
1212 const char *filename;
1214 static shl_t self = (shl_t) 0;
1215 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1217 /* Since searching for a symbol against a NULL module handle will also
1218 look in everything else that was already loaded and exported with
1219 the -E compiler flag, we always cache a handle saved before any
1220 modules are loaded. */
1221 if (!self)
1223 lt_ptr address;
1224 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1227 if (!filename)
1229 module = self;
1231 else
1233 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1235 if (!module)
1237 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1241 return module;
1244 static int
1245 sys_shl_close (loader_data, module)
1246 lt_user_data loader_data;
1247 lt_module module;
1249 int errors = 0;
1251 if (module && (shl_unload ((shl_t) (module)) != 0))
1253 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1254 ++errors;
1257 return errors;
1260 static lt_ptr
1261 sys_shl_sym (loader_data, module, symbol)
1262 lt_user_data loader_data;
1263 lt_module module;
1264 const char *symbol;
1266 lt_ptr address = 0;
1268 /* sys_shl_open should never return a NULL module handle */
1269 if (module == (lt_module) 0)
1271 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1273 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1275 if (!address)
1277 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1281 return address;
1284 static struct lt_user_dlloader sys_shl = {
1285 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1288 #endif /* HAVE_SHL_LOAD */
1293 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1295 #ifdef __WINDOWS__
1297 /* dynamic linking for Win32 */
1299 #include <windows.h>
1301 /* Forward declaration; required to implement handle search below. */
1302 static lt_dlhandle handles;
1304 static lt_module
1305 sys_wll_open (loader_data, filename)
1306 lt_user_data loader_data;
1307 const char *filename;
1309 lt_dlhandle cur;
1310 lt_module module = 0;
1311 const char *errormsg = 0;
1312 char *searchname = 0;
1313 char *ext;
1314 char self_name_buf[MAX_PATH];
1316 if (!filename)
1318 /* Get the name of main module */
1319 *self_name_buf = 0;
1320 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1321 filename = ext = self_name_buf;
1323 else
1325 ext = strrchr (filename, '.');
1328 if (ext)
1330 /* FILENAME already has an extension. */
1331 searchname = lt_estrdup (filename);
1333 else
1335 /* Append a `.' to stop Windows from adding an
1336 implicit `.dll' extension. */
1337 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1338 if (searchname)
1339 sprintf (searchname, "%s.", filename);
1341 if (!searchname)
1342 return 0;
1344 #if __CYGWIN__
1346 char wpath[MAX_PATH];
1347 cygwin_conv_to_full_win32_path(searchname, wpath);
1348 module = LoadLibrary(wpath);
1350 #else
1351 module = LoadLibrary (searchname);
1352 #endif
1353 LT_DLFREE (searchname);
1355 /* libltdl expects this function to fail if it is unable
1356 to physically load the library. Sadly, LoadLibrary
1357 will search the loaded libraries for a match and return
1358 one of them if the path search load fails.
1360 We check whether LoadLibrary is returning a handle to
1361 an already loaded module, and simulate failure if we
1362 find one. */
1363 LT_DLMUTEX_LOCK ();
1364 cur = handles;
1365 while (cur)
1367 if (!cur->module)
1369 cur = 0;
1370 break;
1373 if (cur->module == module)
1375 break;
1378 cur = cur->next;
1380 LT_DLMUTEX_UNLOCK ();
1382 if (cur || !module)
1384 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1385 module = 0;
1388 return module;
1391 static int
1392 sys_wll_close (loader_data, module)
1393 lt_user_data loader_data;
1394 lt_module module;
1396 int errors = 0;
1398 if (FreeLibrary(module) == 0)
1400 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1401 ++errors;
1404 return errors;
1407 static lt_ptr
1408 sys_wll_sym (loader_data, module, symbol)
1409 lt_user_data loader_data;
1410 lt_module module;
1411 const char *symbol;
1413 lt_ptr address = GetProcAddress (module, symbol);
1415 if (!address)
1417 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1420 return address;
1423 static struct lt_user_dlloader sys_wll = {
1424 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1427 #endif /* __WINDOWS__ */
1432 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1435 #ifdef __BEOS__
1437 /* dynamic linking for BeOS */
1439 #include <kernel/image.h>
1441 static lt_module
1442 sys_bedl_open (loader_data, filename)
1443 lt_user_data loader_data;
1444 const char *filename;
1446 image_id image = 0;
1448 if (filename)
1450 image = load_add_on (filename);
1452 else
1454 image_info info;
1455 int32 cookie = 0;
1456 if (get_next_image_info (0, &cookie, &info) == B_OK)
1457 image = load_add_on (info.name);
1460 if (image <= 0)
1462 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1463 image = 0;
1466 return (lt_module) image;
1469 static int
1470 sys_bedl_close (loader_data, module)
1471 lt_user_data loader_data;
1472 lt_module module;
1474 int errors = 0;
1476 if (unload_add_on ((image_id) module) != B_OK)
1478 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1479 ++errors;
1482 return errors;
1485 static lt_ptr
1486 sys_bedl_sym (loader_data, module, symbol)
1487 lt_user_data loader_data;
1488 lt_module module;
1489 const char *symbol;
1491 lt_ptr address = 0;
1492 image_id image = (image_id) module;
1494 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1496 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1497 address = 0;
1500 return address;
1503 static struct lt_user_dlloader sys_bedl = {
1504 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1507 #endif /* __BEOS__ */
1512 /* --- DLD_LINK() INTERFACE LOADER --- */
1515 #if HAVE_DLD
1517 /* dynamic linking with dld */
1519 #if HAVE_DLD_H
1520 #include <dld.h>
1521 #endif
1523 static lt_module
1524 sys_dld_open (loader_data, filename)
1525 lt_user_data loader_data;
1526 const char *filename;
1528 lt_module module = strdup (filename);
1530 if (dld_link (filename) != 0)
1532 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1533 LT_DLFREE (module);
1534 module = 0;
1537 return module;
1540 static int
1541 sys_dld_close (loader_data, module)
1542 lt_user_data loader_data;
1543 lt_module module;
1545 int errors = 0;
1547 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1549 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1550 ++errors;
1552 else
1554 LT_DLFREE (module);
1557 return errors;
1560 static lt_ptr
1561 sys_dld_sym (loader_data, module, symbol)
1562 lt_user_data loader_data;
1563 lt_module module;
1564 const char *symbol;
1566 lt_ptr address = dld_get_func (symbol);
1568 if (!address)
1570 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1573 return address;
1576 static struct lt_user_dlloader sys_dld = {
1577 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1580 #endif /* HAVE_DLD */
1582 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1583 #if HAVE_DYLD
1586 #if HAVE_MACH_O_DYLD_H
1587 # include <mach-o/dyld.h>
1588 #endif
1589 #include <mach-o/getsect.h>
1591 /* We have to put some stuff here that isn't in older dyld.h files */
1592 #ifndef ENUM_DYLD_BOOL
1593 # define ENUM_DYLD_BOOL
1594 # undef FALSE
1595 # undef TRUE
1596 enum DYLD_BOOL {
1597 FALSE,
1598 TRUE
1600 #endif
1601 #ifndef LC_REQ_DYLD
1602 # define LC_REQ_DYLD 0x80000000
1603 #endif
1604 #ifndef LC_LOAD_WEAK_DYLIB
1605 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1606 #endif
1607 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1608 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1609 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1610 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1612 #ifndef NSADDIMAGE_OPTION_NONE
1613 #define NSADDIMAGE_OPTION_NONE 0x0
1614 #endif
1615 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1616 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1617 #endif
1618 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1619 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1620 #endif
1621 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1622 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1623 #endif
1624 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1625 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1626 #endif
1627 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1628 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1629 #endif
1630 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1631 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1632 #endif
1633 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1634 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1635 #endif
1636 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1637 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1638 #endif
1641 static const char *
1642 lt_int_dyld_error(othererror)
1643 char* othererror;
1645 /* return the dyld error string, or the passed in error string if none */
1646 NSLinkEditErrors ler;
1647 int lerno;
1648 const char *errstr;
1649 const char *file;
1650 NSLinkEditError(&ler,&lerno,&file,&errstr);
1651 if (!errstr || !strlen(errstr)) errstr = othererror;
1652 return errstr;
1655 static const struct mach_header *
1656 lt_int_dyld_get_mach_header_from_nsmodule(module)
1657 NSModule module;
1659 /* There should probably be an apple dyld api for this */
1660 int i=_dyld_image_count();
1661 int j;
1662 const char *modname=NSNameOfModule(module);
1663 const struct mach_header *mh=NULL;
1664 if (!modname) return NULL;
1665 for (j = 0; j < i; j++)
1667 if (!strcmp(_dyld_get_image_name(j),modname))
1669 mh=_dyld_get_image_header(j);
1670 break;
1673 return mh;
1676 static const char* lt_int_dyld_lib_install_name(mh)
1677 const struct mach_header *mh;
1679 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1680 is installed, for uninstalled libs we need to check the install_names against
1681 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1682 different lib was loaded as a result
1684 int j;
1685 struct load_command *lc;
1686 unsigned long offset = sizeof(struct mach_header);
1687 const struct mach_header *mh1;
1688 const char* retStr=NULL;
1689 for (j = 0; j < mh->ncmds; j++)
1691 lc = (struct load_command*)(((unsigned long)mh) + offset);
1692 if (LC_ID_DYLIB == lc->cmd)
1694 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1695 (unsigned long)lc);
1697 offset += lc->cmdsize;
1699 return retStr;
1702 static const struct mach_header *
1703 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1705 int i=_dyld_image_count();
1706 int j;
1707 const struct mach_header *mh=NULL;
1708 const char *id=NULL;
1709 for (j = 0; j < i; j++)
1711 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1712 if ((id) && (!strcmp(id,name)))
1714 mh=_dyld_get_image_header(j);
1715 break;
1718 return mh;
1721 static NSSymbol
1722 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1723 const char *symbol;
1724 const struct mach_header *mh;
1726 /* Safe to assume our mh is good */
1727 int j;
1728 struct load_command *lc;
1729 unsigned long offset = sizeof(struct mach_header);
1730 NSSymbol retSym = 0;
1731 const struct mach_header *mh1;
1732 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1734 for (j = 0; j < mh->ncmds; j++)
1736 lc = (struct load_command*)(((unsigned long)mh) + offset);
1737 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1739 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1740 (unsigned long)lc));
1741 if (!mh1)
1743 /* Maybe NSAddImage can find it */
1744 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1745 (unsigned long)lc),
1746 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1747 NSADDIMAGE_OPTION_WITH_SEARCHING +
1748 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1750 if (mh1)
1752 retSym = ltdl_NSLookupSymbolInImage(mh1,
1753 symbol,
1754 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1755 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1757 if (retSym) break;
1760 offset += lc->cmdsize;
1763 return retSym;
1766 static int
1767 sys_dyld_init()
1769 int retCode = 0;
1770 int err = 0;
1771 if (!_dyld_present()) {
1772 retCode=1;
1774 else {
1775 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1776 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1777 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1778 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1780 return retCode;
1783 static lt_module
1784 sys_dyld_open (loader_data, filename)
1785 lt_user_data loader_data;
1786 const char *filename;
1788 lt_module module = 0;
1789 NSObjectFileImage ofi = 0;
1790 NSObjectFileImageReturnCode ofirc;
1792 if (!filename)
1793 return (lt_module)-1;
1794 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1795 switch (ofirc)
1797 case NSObjectFileImageSuccess:
1798 module = NSLinkModule(ofi, filename,
1799 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1800 | NSLINKMODULE_OPTION_PRIVATE
1801 | NSLINKMODULE_OPTION_BINDNOW);
1802 NSDestroyObjectFileImage(ofi);
1803 if (module)
1804 ltdl_NSMakePrivateModulePublic(module);
1805 break;
1806 case NSObjectFileImageInappropriateFile:
1807 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1809 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1810 break;
1812 default:
1813 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1814 return 0;
1816 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1817 return module;
1820 static int
1821 sys_dyld_close (loader_data, module)
1822 lt_user_data loader_data;
1823 lt_module module;
1825 int retCode = 0;
1826 int flags = 0;
1827 unsigned long size=0;
1828 if (module == (lt_module)-1) return 0;
1829 #ifdef __BIG_ENDIAN__
1830 if (((struct mach_header *)module)->magic == MH_MAGIC)
1831 #else
1832 if (((struct mach_header *)module)->magic == MH_CIGAM)
1833 #endif
1835 LT_DLMUTEX_SETERROR("Can not close a dylib");
1836 retCode = 1;
1838 else
1840 #if 1
1841 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1842 get a segfault in atexit(), due to compiler and dynamic loader differences of
1843 opinion, this works around that.
1845 if ((const struct section *)NULL !=
1846 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1847 "__DATA","__mod_term_func"))
1849 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1851 #endif
1852 #ifdef __ppc__
1853 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1854 #endif
1855 if (!NSUnLinkModule(module,flags))
1857 retCode=1;
1858 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1862 return retCode;
1865 static lt_ptr
1866 sys_dyld_sym (loader_data, module, symbol)
1867 lt_user_data loader_data;
1868 lt_module module;
1869 const char *symbol;
1871 lt_ptr address = 0;
1872 NSSymbol *nssym = 0;
1873 void *unused;
1874 const struct mach_header *mh=NULL;
1875 if (module == (lt_module)-1)
1877 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1878 return address;
1880 #ifdef __BIG_ENDIAN__
1881 if (((struct mach_header *)module)->magic == MH_MAGIC)
1882 #else
1883 if (((struct mach_header *)module)->magic == MH_CIGAM)
1884 #endif
1886 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1888 mh=module;
1889 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1891 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1892 symbol,
1893 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1894 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1900 else {
1901 nssym = NSLookupSymbolInModule(module, symbol);
1903 if (!nssym)
1905 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1906 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1908 if (!nssym)
1910 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)));
1911 return NULL;
1913 return NSAddressOfSymbol(nssym);
1916 static struct lt_user_dlloader sys_dyld =
1917 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1920 #endif /* HAVE_DYLD */
1923 /* --- DLPREOPEN() INTERFACE LOADER --- */
1926 /* emulate dynamic linking using preloaded_symbols */
1928 typedef struct lt_dlsymlists_t
1930 struct lt_dlsymlists_t *next;
1931 const lt_dlsymlist *syms;
1932 } lt_dlsymlists_t;
1934 static const lt_dlsymlist *default_preloaded_symbols = 0;
1935 static lt_dlsymlists_t *preloaded_symbols = 0;
1937 static int
1938 presym_init (loader_data)
1939 lt_user_data loader_data;
1941 int errors = 0;
1943 LT_DLMUTEX_LOCK ();
1945 preloaded_symbols = 0;
1946 if (default_preloaded_symbols)
1948 errors = lt_dlpreload (default_preloaded_symbols);
1951 LT_DLMUTEX_UNLOCK ();
1953 return errors;
1956 static int
1957 presym_free_symlists ()
1959 lt_dlsymlists_t *lists;
1961 LT_DLMUTEX_LOCK ();
1963 lists = preloaded_symbols;
1964 while (lists)
1966 lt_dlsymlists_t *tmp = lists;
1968 lists = lists->next;
1969 LT_DLFREE (tmp);
1971 preloaded_symbols = 0;
1973 LT_DLMUTEX_UNLOCK ();
1975 return 0;
1978 static int
1979 presym_exit (loader_data)
1980 lt_user_data loader_data;
1982 presym_free_symlists ();
1983 return 0;
1986 static int
1987 presym_add_symlist (preloaded)
1988 const lt_dlsymlist *preloaded;
1990 lt_dlsymlists_t *tmp;
1991 lt_dlsymlists_t *lists;
1992 int errors = 0;
1994 LT_DLMUTEX_LOCK ();
1996 lists = preloaded_symbols;
1997 while (lists)
1999 if (lists->syms == preloaded)
2001 goto done;
2003 lists = lists->next;
2006 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2007 if (tmp)
2009 memset (tmp, 0, sizeof(lt_dlsymlists_t));
2010 tmp->syms = preloaded;
2011 tmp->next = preloaded_symbols;
2012 preloaded_symbols = tmp;
2014 else
2016 ++errors;
2019 done:
2020 LT_DLMUTEX_UNLOCK ();
2021 return errors;
2024 static lt_module
2025 presym_open (loader_data, filename)
2026 lt_user_data loader_data;
2027 const char *filename;
2029 lt_dlsymlists_t *lists;
2030 lt_module module = (lt_module) 0;
2032 LT_DLMUTEX_LOCK ();
2033 lists = preloaded_symbols;
2035 if (!lists)
2037 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2038 goto done;
2041 /* Can't use NULL as the reflective symbol header, as NULL is
2042 used to mark the end of the entire symbol list. Self-dlpreopened
2043 symbols follow this magic number, chosen to be an unlikely
2044 clash with a real module name. */
2045 if (!filename)
2047 filename = "@PROGRAM@";
2050 while (lists)
2052 const lt_dlsymlist *syms = lists->syms;
2054 while (syms->name)
2056 if (!syms->address && strcmp(syms->name, filename) == 0)
2058 module = (lt_module) syms;
2059 goto done;
2061 ++syms;
2064 lists = lists->next;
2067 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2069 done:
2070 LT_DLMUTEX_UNLOCK ();
2071 return module;
2074 static int
2075 presym_close (loader_data, module)
2076 lt_user_data loader_data;
2077 lt_module module;
2079 /* Just to silence gcc -Wall */
2080 module = 0;
2081 return 0;
2084 static lt_ptr
2085 presym_sym (loader_data, module, symbol)
2086 lt_user_data loader_data;
2087 lt_module module;
2088 const char *symbol;
2090 lt_dlsymlist *syms = (lt_dlsymlist*) module;
2092 ++syms;
2093 while (syms->address)
2095 if (strcmp(syms->name, symbol) == 0)
2097 return syms->address;
2100 ++syms;
2103 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2105 return 0;
2108 static struct lt_user_dlloader presym = {
2109 0, presym_open, presym_close, presym_sym, presym_exit, 0
2116 /* --- DYNAMIC MODULE LOADING --- */
2119 /* The type of a function used at each iteration of foreach_dirinpath(). */
2120 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2121 lt_ptr data2));
2123 static int foreach_dirinpath LT_PARAMS((const char *search_path,
2124 const char *base_name,
2125 foreach_callback_func *func,
2126 lt_ptr data1, lt_ptr data2));
2128 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2129 lt_ptr ignored));
2130 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2131 lt_ptr ignored));
2132 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2133 lt_ptr data2));
2136 static int canonicalize_path LT_PARAMS((const char *path,
2137 char **pcanonical));
2138 static int argzize_path LT_PARAMS((const char *path,
2139 char **pargz,
2140 size_t *pargz_len));
2141 static FILE *find_file LT_PARAMS((const char *search_path,
2142 const char *base_name,
2143 char **pdir));
2144 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2145 const char *base_name,
2146 lt_dlhandle *handle));
2147 static int find_module LT_PARAMS((lt_dlhandle *handle,
2148 const char *dir,
2149 const char *libdir,
2150 const char *dlname,
2151 const char *old_name,
2152 int installed));
2153 static int free_vars LT_PARAMS((char *dlname, char *oldname,
2154 char *libdir, char *deplibs));
2155 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2156 char *deplibs));
2157 static int trim LT_PARAMS((char **dest,
2158 const char *str));
2159 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2160 const char *filename));
2161 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2162 const char *filename));
2163 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2164 static int lt_argz_insert LT_PARAMS((char **pargz,
2165 size_t *pargz_len,
2166 char *before,
2167 const char *entry));
2168 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2169 size_t *pargz_len,
2170 const char *entry));
2171 static int lt_argz_insertdir LT_PARAMS((char **pargz,
2172 size_t *pargz_len,
2173 const char *dirnam,
2174 struct dirent *dp));
2175 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2176 char *before,
2177 const char *dir));
2178 static int list_files_by_dir LT_PARAMS((const char *dirnam,
2179 char **pargz,
2180 size_t *pargz_len));
2181 static int file_not_found LT_PARAMS((void));
2183 static char *user_search_path= 0;
2184 static lt_dlloader *loaders = 0;
2185 static lt_dlhandle handles = 0;
2186 static int initialized = 0;
2188 /* Initialize libltdl. */
2190 lt_dlinit ()
2192 int errors = 0;
2194 LT_DLMUTEX_LOCK ();
2196 /* Initialize only at first call. */
2197 if (++initialized == 1)
2199 handles = 0;
2200 user_search_path = 0; /* empty search path */
2202 #if HAVE_LIBDL
2203 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2204 #endif
2205 #if HAVE_SHL_LOAD
2206 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2207 #endif
2208 #ifdef __WINDOWS__
2209 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2210 #endif
2211 #ifdef __BEOS__
2212 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2213 #endif
2214 #if HAVE_DLD
2215 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2216 #endif
2217 #if HAVE_DYLD
2218 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2219 errors += sys_dyld_init();
2220 #endif
2221 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2223 if (presym_init (presym.dlloader_data))
2225 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2226 ++errors;
2228 else if (errors != 0)
2230 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2231 ++errors;
2235 LT_DLMUTEX_UNLOCK ();
2237 return errors;
2241 lt_dlpreload (preloaded)
2242 const lt_dlsymlist *preloaded;
2244 int errors = 0;
2246 if (preloaded)
2248 errors = presym_add_symlist (preloaded);
2250 else
2252 presym_free_symlists();
2254 LT_DLMUTEX_LOCK ();
2255 if (default_preloaded_symbols)
2257 errors = lt_dlpreload (default_preloaded_symbols);
2259 LT_DLMUTEX_UNLOCK ();
2262 return errors;
2266 lt_dlpreload_default (preloaded)
2267 const lt_dlsymlist *preloaded;
2269 LT_DLMUTEX_LOCK ();
2270 default_preloaded_symbols = preloaded;
2271 LT_DLMUTEX_UNLOCK ();
2272 return 0;
2276 lt_dlexit ()
2278 /* shut down libltdl */
2279 lt_dlloader *loader;
2280 int errors = 0;
2282 LT_DLMUTEX_LOCK ();
2283 loader = loaders;
2285 if (!initialized)
2287 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2288 ++errors;
2289 goto done;
2292 /* shut down only at last call. */
2293 if (--initialized == 0)
2295 int level;
2297 while (handles && LT_DLIS_RESIDENT (handles))
2299 handles = handles->next;
2302 /* close all modules */
2303 for (level = 1; handles; ++level)
2305 lt_dlhandle cur = handles;
2306 int saw_nonresident = 0;
2308 while (cur)
2310 lt_dlhandle tmp = cur;
2311 cur = cur->next;
2312 if (!LT_DLIS_RESIDENT (tmp))
2313 saw_nonresident = 1;
2314 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2316 if (lt_dlclose (tmp))
2318 ++errors;
2322 /* done if only resident modules are left */
2323 if (!saw_nonresident)
2324 break;
2327 /* close all loaders */
2328 while (loader)
2330 lt_dlloader *next = loader->next;
2331 lt_user_data data = loader->dlloader_data;
2332 if (loader->dlloader_exit && loader->dlloader_exit (data))
2334 ++errors;
2337 LT_DLMEM_REASSIGN (loader, next);
2339 loaders = 0;
2342 done:
2343 LT_DLMUTEX_UNLOCK ();
2344 return errors;
2347 static int
2348 tryall_dlopen (handle, filename)
2349 lt_dlhandle *handle;
2350 const char *filename;
2352 lt_dlhandle cur;
2353 lt_dlloader *loader;
2354 const char *saved_error;
2355 int errors = 0;
2357 LT_DLMUTEX_GETERROR (saved_error);
2358 LT_DLMUTEX_LOCK ();
2360 cur = handles;
2361 loader = loaders;
2363 /* check whether the module was already opened */
2364 while (cur)
2366 /* try to dlopen the program itself? */
2367 if (!cur->info.filename && !filename)
2369 break;
2372 if (cur->info.filename && filename
2373 && strcmp (cur->info.filename, filename) == 0)
2375 break;
2378 cur = cur->next;
2381 if (cur)
2383 ++cur->info.ref_count;
2384 *handle = cur;
2385 goto done;
2388 cur = *handle;
2389 if (filename)
2391 /* Comment out the check of file permissions using access.
2392 This call seems to always return -1 with error EACCES.
2394 /* We need to catch missing file errors early so that
2395 file_not_found() can detect what happened.
2396 if (access (filename, R_OK) != 0)
2398 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2399 ++errors;
2400 goto done;
2401 } */
2403 cur->info.filename = lt_estrdup (filename);
2404 if (!cur->info.filename)
2406 ++errors;
2407 goto done;
2410 else
2412 cur->info.filename = 0;
2415 while (loader)
2417 lt_user_data data = loader->dlloader_data;
2419 cur->module = loader->module_open (data, filename);
2421 if (cur->module != 0)
2423 break;
2425 loader = loader->next;
2428 if (!loader)
2430 LT_DLFREE (cur->info.filename);
2431 ++errors;
2432 goto done;
2435 cur->loader = loader;
2436 LT_DLMUTEX_SETERROR (saved_error);
2438 done:
2439 LT_DLMUTEX_UNLOCK ();
2441 return errors;
2444 static int
2445 tryall_dlopen_module (handle, prefix, dirname, dlname)
2446 lt_dlhandle *handle;
2447 const char *prefix;
2448 const char *dirname;
2449 const char *dlname;
2451 int error = 0;
2452 char *filename = 0;
2453 size_t filename_len = 0;
2454 size_t dirname_len = LT_STRLEN (dirname);
2456 assert (handle);
2457 assert (dirname);
2458 assert (dlname);
2459 #ifdef LT_DIRSEP_CHAR
2460 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2461 should make it into this function: */
2462 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2463 #endif
2465 if (dirname_len > 0)
2466 if (dirname[dirname_len -1] == '/')
2467 --dirname_len;
2468 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2470 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2471 The PREFIX (if any) is handled below. */
2472 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2473 if (!filename)
2474 return 1;
2476 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2478 /* Now that we have combined DIRNAME and MODULENAME, if there is
2479 also a PREFIX to contend with, simply recurse with the arguments
2480 shuffled. Otherwise, attempt to open FILENAME as a module. */
2481 if (prefix)
2483 error += tryall_dlopen_module (handle,
2484 (const char *) 0, prefix, filename);
2486 else if (tryall_dlopen (handle, filename) != 0)
2488 ++error;
2491 LT_DLFREE (filename);
2492 return error;
2495 static int
2496 find_module (handle, dir, libdir, dlname, old_name, installed)
2497 lt_dlhandle *handle;
2498 const char *dir;
2499 const char *libdir;
2500 const char *dlname;
2501 const char *old_name;
2502 int installed;
2504 /* Try to open the old library first; if it was dlpreopened,
2505 we want the preopened version of it, even if a dlopenable
2506 module is available. */
2507 if (old_name && tryall_dlopen (handle, old_name) == 0)
2509 return 0;
2512 /* Try to open the dynamic library. */
2513 if (dlname)
2515 /* try to open the installed module */
2516 if (installed && libdir)
2518 if (tryall_dlopen_module (handle,
2519 (const char *) 0, libdir, dlname) == 0)
2520 return 0;
2523 /* try to open the not-installed module */
2524 if (!installed)
2526 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2527 return 0;
2530 /* maybe it was moved to another directory */
2532 if (tryall_dlopen_module (handle,
2533 (const char *) 0, dir, dlname) == 0)
2534 return 0;
2538 return 1;
2542 static int
2543 canonicalize_path (path, pcanonical)
2544 const char *path;
2545 char **pcanonical;
2547 char *canonical = 0;
2549 assert (path && *path);
2550 assert (pcanonical);
2552 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2553 if (!canonical)
2554 return 1;
2557 size_t dest = 0;
2558 size_t src;
2559 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2561 /* Path separators are not copied to the beginning or end of
2562 the destination, or if another separator would follow
2563 immediately. */
2564 if (path[src] == LT_PATHSEP_CHAR)
2566 if ((dest == 0)
2567 || (path[1+ src] == LT_PATHSEP_CHAR)
2568 || (path[1+ src] == LT_EOS_CHAR))
2569 continue;
2572 /* Anything other than a directory separator is copied verbatim. */
2573 if ((path[src] != '/')
2574 #ifdef LT_DIRSEP_CHAR
2575 && (path[src] != LT_DIRSEP_CHAR)
2576 #endif
2579 canonical[dest++] = path[src];
2581 /* Directory separators are converted and copied only if they are
2582 not at the end of a path -- i.e. before a path separator or
2583 NULL terminator. */
2584 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2585 && (path[1+ src] != LT_EOS_CHAR)
2586 #ifdef LT_DIRSEP_CHAR
2587 && (path[1+ src] != LT_DIRSEP_CHAR)
2588 #endif
2589 && (path[1+ src] != '/'))
2591 canonical[dest++] = '/';
2595 /* Add an end-of-string marker at the end. */
2596 canonical[dest] = LT_EOS_CHAR;
2599 /* Assign new value. */
2600 *pcanonical = canonical;
2602 return 0;
2605 static int
2606 argzize_path (path, pargz, pargz_len)
2607 const char *path;
2608 char **pargz;
2609 size_t *pargz_len;
2611 error_t error;
2613 assert (path);
2614 assert (pargz);
2615 assert (pargz_len);
2617 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2619 switch (error)
2621 case ENOMEM:
2622 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2623 break;
2624 default:
2625 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2626 break;
2629 return 1;
2632 return 0;
2635 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2636 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2637 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2638 it is appended to each SEARCH_PATH element before FUNC is called. */
2639 static int
2640 foreach_dirinpath (search_path, base_name, func, data1, data2)
2641 const char *search_path;
2642 const char *base_name;
2643 foreach_callback_func *func;
2644 lt_ptr data1;
2645 lt_ptr data2;
2647 int result = 0;
2648 int filenamesize = 0;
2649 size_t lenbase = LT_STRLEN (base_name);
2650 size_t argz_len = 0;
2651 char *argz = 0;
2652 char *filename = 0;
2653 char *canonical = 0;
2655 LT_DLMUTEX_LOCK ();
2657 if (!search_path || !*search_path)
2659 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2660 goto cleanup;
2663 if (canonicalize_path (search_path, &canonical) != 0)
2664 goto cleanup;
2666 if (argzize_path (canonical, &argz, &argz_len) != 0)
2667 goto cleanup;
2670 char *dir_name = 0;
2671 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2673 size_t lendir = LT_STRLEN (dir_name);
2675 if (lendir +1 +lenbase >= filenamesize)
2677 LT_DLFREE (filename);
2678 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2679 filename = LT_EMALLOC (char, filenamesize);
2680 if (!filename)
2681 goto cleanup;
2684 assert (filenamesize > lendir);
2685 strcpy (filename, dir_name);
2687 if (base_name && *base_name)
2689 if (filename[lendir -1] != '/')
2690 filename[lendir++] = '/';
2691 strcpy (filename +lendir, base_name);
2694 if ((result = (*func) (filename, data1, data2)))
2696 break;
2701 cleanup:
2702 LT_DLFREE (argz);
2703 LT_DLFREE (canonical);
2704 LT_DLFREE (filename);
2706 LT_DLMUTEX_UNLOCK ();
2708 return result;
2711 /* If FILEPATH can be opened, store the name of the directory component
2712 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2713 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2714 static int
2715 find_file_callback (filename, data1, data2)
2716 char *filename;
2717 lt_ptr data1;
2718 lt_ptr data2;
2720 char **pdir = (char **) data1;
2721 FILE **pfile = (FILE **) data2;
2722 int is_done = 0;
2724 assert (filename && *filename);
2725 assert (pdir);
2726 assert (pfile);
2728 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2730 char *dirend = strrchr (filename, '/');
2732 if (dirend > filename)
2733 *dirend = LT_EOS_CHAR;
2735 LT_DLFREE (*pdir);
2736 *pdir = lt_estrdup (filename);
2737 is_done = (*pdir == 0) ? -1 : 1;
2740 return is_done;
2743 static FILE *
2744 find_file (search_path, base_name, pdir)
2745 const char *search_path;
2746 const char *base_name;
2747 char **pdir;
2749 FILE *file = 0;
2751 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2753 return file;
2756 static int
2757 find_handle_callback (filename, data, ignored)
2758 char *filename;
2759 lt_ptr data;
2760 lt_ptr ignored;
2762 lt_dlhandle *handle = (lt_dlhandle *) data;
2763 int notfound = access (filename, R_OK);
2765 /* Bail out if file cannot be read... */
2766 if (notfound)
2767 return 0;
2769 /* Try to dlopen the file, but do not continue searching in any
2770 case. */
2771 if (tryall_dlopen (handle, filename) != 0)
2772 *handle = 0;
2774 return 1;
2777 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2778 found but could not be opened, *HANDLE will be set to 0. */
2779 static lt_dlhandle *
2780 find_handle (search_path, base_name, handle)
2781 const char *search_path;
2782 const char *base_name;
2783 lt_dlhandle *handle;
2785 if (!search_path)
2786 return 0;
2788 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2789 handle, 0))
2790 return 0;
2792 return handle;
2795 static int
2796 load_deplibs (handle, deplibs)
2797 lt_dlhandle handle;
2798 char *deplibs;
2800 #if LTDL_DLOPEN_DEPLIBS
2801 char *p, *save_search_path = 0;
2802 int depcount = 0;
2803 int i;
2804 char **names = 0;
2805 #endif
2806 int errors = 0;
2808 handle->depcount = 0;
2810 #if LTDL_DLOPEN_DEPLIBS
2811 if (!deplibs)
2813 return errors;
2815 ++errors;
2817 LT_DLMUTEX_LOCK ();
2818 if (user_search_path)
2820 save_search_path = lt_estrdup (user_search_path);
2821 if (!save_search_path)
2822 goto cleanup;
2825 /* extract search paths and count deplibs */
2826 p = deplibs;
2827 while (*p)
2829 if (!isspace ((int) *p))
2831 char *end = p+1;
2832 while (*end && !isspace((int) *end))
2834 ++end;
2837 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2839 char save = *end;
2840 *end = 0; /* set a temporary string terminator */
2841 if (lt_dladdsearchdir(p+2))
2843 goto cleanup;
2845 *end = save;
2847 else
2849 ++depcount;
2852 p = end;
2854 else
2856 ++p;
2860 /* restore the old search path */
2861 LT_DLFREE (user_search_path);
2862 user_search_path = save_search_path;
2864 LT_DLMUTEX_UNLOCK ();
2866 if (!depcount)
2868 errors = 0;
2869 goto cleanup;
2872 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2873 if (!names)
2874 goto cleanup;
2876 /* now only extract the actual deplibs */
2877 depcount = 0;
2878 p = deplibs;
2879 while (*p)
2881 if (isspace ((int) *p))
2883 ++p;
2885 else
2887 char *end = p+1;
2888 while (*end && !isspace ((int) *end))
2890 ++end;
2893 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2895 char *name;
2896 char save = *end;
2897 *end = 0; /* set a temporary string terminator */
2898 if (strncmp(p, "-l", 2) == 0)
2900 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2901 name = LT_EMALLOC (char, 1+ name_len);
2902 if (name)
2903 sprintf (name, "lib%s", p+2);
2905 else
2906 name = lt_estrdup(p);
2908 if (!name)
2909 goto cleanup_names;
2911 names[depcount++] = name;
2912 *end = save;
2914 p = end;
2918 /* load the deplibs (in reverse order)
2919 At this stage, don't worry if the deplibs do not load correctly,
2920 they may already be statically linked into the loading application
2921 for instance. There will be a more enlightening error message
2922 later on if the loaded module cannot resolve all of its symbols. */
2923 if (depcount)
2925 int j = 0;
2927 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2928 if (!handle->deplibs)
2929 goto cleanup;
2931 for (i = 0; i < depcount; ++i)
2933 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2934 if (handle->deplibs[j])
2936 ++j;
2940 handle->depcount = j; /* Number of successfully loaded deplibs */
2941 errors = 0;
2944 cleanup_names:
2945 for (i = 0; i < depcount; ++i)
2947 LT_DLFREE (names[i]);
2950 cleanup:
2951 LT_DLFREE (names);
2952 #endif
2954 return errors;
2957 static int
2958 unload_deplibs (handle)
2959 lt_dlhandle handle;
2961 int i;
2962 int errors = 0;
2964 if (handle->depcount)
2966 for (i = 0; i < handle->depcount; ++i)
2968 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2970 errors += lt_dlclose (handle->deplibs[i]);
2975 return errors;
2978 static int
2979 trim (dest, str)
2980 char **dest;
2981 const char *str;
2983 /* remove the leading and trailing "'" from str
2984 and store the result in dest */
2985 const char *end = strrchr (str, '\'');
2986 size_t len = LT_STRLEN (str);
2987 char *tmp;
2989 LT_DLFREE (*dest);
2991 if (len > 3 && str[0] == '\'')
2993 tmp = LT_EMALLOC (char, end - str);
2994 if (!tmp)
2995 return 1;
2997 strncpy(tmp, &str[1], (end - str) - 1);
2998 tmp[len-3] = LT_EOS_CHAR;
2999 *dest = tmp;
3001 else
3003 *dest = 0;
3006 return 0;
3009 static int
3010 free_vars (dlname, oldname, libdir, deplibs)
3011 char *dlname;
3012 char *oldname;
3013 char *libdir;
3014 char *deplibs;
3016 LT_DLFREE (dlname);
3017 LT_DLFREE (oldname);
3018 LT_DLFREE (libdir);
3019 LT_DLFREE (deplibs);
3021 return 0;
3024 static int
3025 try_dlopen (phandle, filename)
3026 lt_dlhandle *phandle;
3027 const char *filename;
3029 const char * ext = 0;
3030 const char * saved_error = 0;
3031 char * canonical = 0;
3032 char * base_name = 0;
3033 char * dir = 0;
3034 char * name = 0;
3035 int errors = 0;
3036 lt_dlhandle newhandle;
3038 assert (phandle);
3039 assert (*phandle == 0);
3041 LT_DLMUTEX_GETERROR (saved_error);
3043 /* dlopen self? */
3044 if (!filename)
3046 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3047 if (*phandle == 0)
3048 return 1;
3050 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3051 newhandle = *phandle;
3053 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3054 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3056 if (tryall_dlopen (&newhandle, 0) != 0)
3058 LT_DLFREE (*phandle);
3059 return 1;
3062 goto register_handle;
3065 assert (filename && *filename);
3067 /* Doing this immediately allows internal functions to safely
3068 assume only canonicalized paths are passed. */
3069 if (canonicalize_path (filename, &canonical) != 0)
3071 ++errors;
3072 goto cleanup;
3075 /* If the canonical module name is a path (relative or absolute)
3076 then split it into a directory part and a name part. */
3077 base_name = strrchr (canonical, '/');
3078 if (base_name)
3080 size_t dirlen = (1+ base_name) - canonical;
3082 dir = LT_EMALLOC (char, 1+ dirlen);
3083 if (!dir)
3085 ++errors;
3086 goto cleanup;
3089 strncpy (dir, canonical, dirlen);
3090 dir[dirlen] = LT_EOS_CHAR;
3092 ++base_name;
3094 else
3095 LT_DLMEM_REASSIGN (base_name, canonical);
3097 assert (base_name && *base_name);
3099 /* Check whether we are opening a libtool module (.la extension). */
3100 ext = strrchr (base_name, '.');
3101 if (ext && strcmp (ext, archive_ext) == 0)
3103 /* this seems to be a libtool module */
3104 FILE * file = 0;
3105 char * dlname = 0;
3106 char * old_name = 0;
3107 char * libdir = 0;
3108 char * deplibs = 0;
3109 char * line = 0;
3110 size_t line_len;
3112 /* if we can't find the installed flag, it is probably an
3113 installed libtool archive, produced with an old version
3114 of libtool */
3115 int installed = 1;
3117 /* extract the module name from the file name */
3118 name = LT_EMALLOC (char, ext - base_name + 1);
3119 if (!name)
3121 ++errors;
3122 goto cleanup;
3125 /* canonicalize the module name */
3127 size_t i;
3128 for (i = 0; i < ext - base_name; ++i)
3130 if (isalnum ((int)(base_name[i])))
3132 name[i] = base_name[i];
3134 else
3136 name[i] = '_';
3139 name[ext - base_name] = LT_EOS_CHAR;
3142 /* Now try to open the .la file. If there is no directory name
3143 component, try to find it first in user_search_path and then other
3144 prescribed paths. Otherwise (or in any case if the module was not
3145 yet found) try opening just the module name as passed. */
3146 if (!dir)
3148 const char *search_path;
3150 LT_DLMUTEX_LOCK ();
3151 search_path = user_search_path;
3152 if (search_path)
3153 file = find_file (user_search_path, base_name, &dir);
3154 LT_DLMUTEX_UNLOCK ();
3156 if (!file)
3158 search_path = getenv (LTDL_SEARCHPATH_VAR);
3159 if (search_path)
3160 file = find_file (search_path, base_name, &dir);
3163 #ifdef LTDL_SHLIBPATH_VAR
3164 if (!file)
3166 search_path = getenv (LTDL_SHLIBPATH_VAR);
3167 if (search_path)
3168 file = find_file (search_path, base_name, &dir);
3170 #endif
3171 #ifdef LTDL_SYSSEARCHPATH
3172 if (!file && sys_search_path)
3174 file = find_file (sys_search_path, base_name, &dir);
3176 #endif
3178 if (!file)
3180 file = fopen (filename, LT_READTEXT_MODE);
3183 /* If we didn't find the file by now, it really isn't there. Set
3184 the status flag, and bail out. */
3185 if (!file)
3187 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3188 ++errors;
3189 goto cleanup;
3192 line_len = LT_FILENAME_MAX;
3193 line = LT_EMALLOC (char, line_len);
3194 if (!line)
3196 fclose (file);
3197 ++errors;
3198 goto cleanup;
3201 /* read the .la file */
3202 while (!feof (file))
3204 if (!fgets (line, (int) line_len, file))
3206 break;
3209 /* Handle the case where we occasionally need to read a line
3210 that is longer than the initial buffer size. */
3211 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3213 line = LT_DLREALLOC (char, line, line_len *2);
3214 if (!fgets (&line[line_len -1], (int) line_len +1, file))
3216 break;
3218 line_len *= 2;
3221 if (line[0] == '\n' || line[0] == '#')
3223 continue;
3226 #undef STR_DLNAME
3227 #define STR_DLNAME "dlname="
3228 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3230 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3233 #undef STR_OLD_LIBRARY
3234 #define STR_OLD_LIBRARY "old_library="
3235 else if (strncmp (line, STR_OLD_LIBRARY,
3236 sizeof (STR_OLD_LIBRARY) - 1) == 0)
3238 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3240 #undef STR_LIBDIR
3241 #define STR_LIBDIR "libdir="
3242 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3244 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3247 #undef STR_DL_DEPLIBS
3248 #define STR_DL_DEPLIBS "dependency_libs="
3249 else if (strncmp (line, STR_DL_DEPLIBS,
3250 sizeof (STR_DL_DEPLIBS) - 1) == 0)
3252 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3254 else if (strcmp (line, "installed=yes\n") == 0)
3256 installed = 1;
3258 else if (strcmp (line, "installed=no\n") == 0)
3260 installed = 0;
3263 #undef STR_LIBRARY_NAMES
3264 #define STR_LIBRARY_NAMES "library_names="
3265 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3266 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3268 char *last_libname;
3269 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3270 if (!errors
3271 && dlname
3272 && (last_libname = strrchr (dlname, ' ')) != 0)
3274 last_libname = lt_estrdup (last_libname + 1);
3275 if (!last_libname)
3277 ++errors;
3278 goto cleanup;
3280 LT_DLMEM_REASSIGN (dlname, last_libname);
3284 if (errors)
3285 break;
3288 fclose (file);
3289 LT_DLFREE (line);
3291 /* allocate the handle */
3292 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3293 if (*phandle == 0)
3294 ++errors;
3296 if (errors)
3298 free_vars (dlname, old_name, libdir, deplibs);
3299 LT_DLFREE (*phandle);
3300 goto cleanup;
3303 assert (*phandle);
3305 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3306 if (load_deplibs (*phandle, deplibs) == 0)
3308 newhandle = *phandle;
3309 /* find_module may replace newhandle */
3310 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3312 unload_deplibs (*phandle);
3313 ++errors;
3316 else
3318 ++errors;
3321 free_vars (dlname, old_name, libdir, deplibs);
3322 if (errors)
3324 LT_DLFREE (*phandle);
3325 goto cleanup;
3328 if (*phandle != newhandle)
3330 unload_deplibs (*phandle);
3333 else
3335 /* not a libtool module */
3336 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3337 if (*phandle == 0)
3339 ++errors;
3340 goto cleanup;
3343 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3344 newhandle = *phandle;
3346 /* If the module has no directory name component, try to find it
3347 first in user_search_path and then other prescribed paths.
3348 Otherwise (or in any case if the module was not yet found) try
3349 opening just the module name as passed. */
3350 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3351 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3352 &newhandle)
3353 #ifdef LTDL_SHLIBPATH_VAR
3354 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3355 &newhandle)
3356 #endif
3357 #ifdef LTDL_SYSSEARCHPATH
3358 && !find_handle (sys_search_path, base_name, &newhandle)
3359 #endif
3362 if (tryall_dlopen (&newhandle, filename) != 0)
3364 newhandle = NULL;
3368 if (!newhandle)
3370 LT_DLFREE (*phandle);
3371 ++errors;
3372 goto cleanup;
3376 register_handle:
3377 LT_DLMEM_REASSIGN (*phandle, newhandle);
3379 if ((*phandle)->info.ref_count == 0)
3381 (*phandle)->info.ref_count = 1;
3382 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3384 LT_DLMUTEX_LOCK ();
3385 (*phandle)->next = handles;
3386 handles = *phandle;
3387 LT_DLMUTEX_UNLOCK ();
3390 LT_DLMUTEX_SETERROR (saved_error);
3392 cleanup:
3393 LT_DLFREE (dir);
3394 LT_DLFREE (name);
3395 LT_DLFREE (canonical);
3397 return errors;
3400 lt_dlhandle
3401 lt_dlopen (filename)
3402 const char *filename;
3404 lt_dlhandle handle = 0;
3406 /* Just incase we missed a code path in try_dlopen() that reports
3407 an error, but forgets to reset handle... */
3408 if (try_dlopen (&handle, filename) != 0)
3409 return 0;
3411 return handle;
3414 /* If the last error messge store was `FILE_NOT_FOUND', then return
3415 non-zero. */
3416 static int
3417 file_not_found ()
3419 const char *error = 0;
3421 LT_DLMUTEX_GETERROR (error);
3422 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3423 return 1;
3425 return 0;
3428 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3429 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3430 and if a file is still not found try again with SHLIB_EXT appended
3431 instead. */
3432 lt_dlhandle
3433 lt_dlopenext (filename)
3434 const char *filename;
3436 lt_dlhandle handle = 0;
3437 char * tmp = 0;
3438 char * ext = 0;
3439 size_t len;
3440 int errors = 0;
3442 if (!filename)
3444 return lt_dlopen (filename);
3447 assert (filename);
3449 len = LT_STRLEN (filename);
3450 ext = strrchr (filename, '.');
3452 /* If FILENAME already bears a suitable extension, there is no need
3453 to try appending additional extensions. */
3454 if (ext && ((strcmp (ext, archive_ext) == 0)
3455 #ifdef LTDL_SHLIB_EXT
3456 || (strcmp (ext, shlib_ext) == 0)
3457 #endif
3460 return lt_dlopen (filename);
3463 /* First try appending ARCHIVE_EXT. */
3464 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3465 if (!tmp)
3466 return 0;
3468 strcpy (tmp, filename);
3469 strcat (tmp, archive_ext);
3470 errors = try_dlopen (&handle, tmp);
3472 /* If we found FILENAME, stop searching -- whether we were able to
3473 load the file as a module or not. If the file exists but loading
3474 failed, it is better to return an error message here than to
3475 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3476 in the module search path. */
3477 if (handle || ((errors > 0) && !file_not_found ()))
3479 LT_DLFREE (tmp);
3480 return handle;
3483 #ifdef LTDL_SHLIB_EXT
3484 /* Try appending SHLIB_EXT. */
3485 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3487 LT_DLFREE (tmp);
3488 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3489 if (!tmp)
3490 return 0;
3492 strcpy (tmp, filename);
3494 else
3496 tmp[len] = LT_EOS_CHAR;
3499 strcat(tmp, shlib_ext);
3500 errors = try_dlopen (&handle, tmp);
3502 /* As before, if the file was found but loading failed, return now
3503 with the current error message. */
3504 if (handle || ((errors > 0) && !file_not_found ()))
3506 LT_DLFREE (tmp);
3507 return handle;
3509 #endif
3511 /* Still here? Then we really did fail to locate any of the file
3512 names we tried. */
3513 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3514 LT_DLFREE (tmp);
3515 return 0;
3519 static int
3520 lt_argz_insert (pargz, pargz_len, before, entry)
3521 char **pargz;
3522 size_t *pargz_len;
3523 char *before;
3524 const char *entry;
3526 error_t error;
3528 if ((error = argz_insert (pargz, pargz_len, before, entry)))
3530 switch (error)
3532 case ENOMEM:
3533 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3534 break;
3535 default:
3536 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3537 break;
3539 return 1;
3542 return 0;
3545 static int
3546 lt_argz_insertinorder (pargz, pargz_len, entry)
3547 char **pargz;
3548 size_t *pargz_len;
3549 const char *entry;
3551 char *before = 0;
3553 assert (pargz);
3554 assert (pargz_len);
3555 assert (entry && *entry);
3557 if (*pargz)
3558 while ((before = argz_next (*pargz, *pargz_len, before)))
3560 int cmp = strcmp (entry, before);
3562 if (cmp < 0) break;
3563 if (cmp == 0) return 0; /* No duplicates! */
3566 return lt_argz_insert (pargz, pargz_len, before, entry);
3569 static int
3570 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3571 char **pargz;
3572 size_t *pargz_len;
3573 const char *dirnam;
3574 struct dirent *dp;
3576 char *buf = 0;
3577 size_t buf_len = 0;
3578 char *end = 0;
3579 size_t end_offset = 0;
3580 size_t dir_len = 0;
3581 int errors = 0;
3583 assert (pargz);
3584 assert (pargz_len);
3585 assert (dp);
3587 dir_len = LT_STRLEN (dirnam);
3588 end = dp->d_name + LT_D_NAMLEN(dp);
3590 /* Ignore version numbers. */
3592 char *p;
3593 for (p = end; p -1 > dp->d_name; --p)
3594 if (strchr (".0123456789", p[-1]) == 0)
3595 break;
3597 if (*p == '.')
3598 end = p;
3601 /* Ignore filename extension. */
3603 char *p;
3604 for (p = end -1; p > dp->d_name; --p)
3605 if (*p == '.')
3607 end = p;
3608 break;
3612 /* Prepend the directory name. */
3613 end_offset = end - dp->d_name;
3614 buf_len = dir_len + 1+ end_offset;
3615 buf = LT_EMALLOC (char, 1+ buf_len);
3616 if (!buf)
3617 return ++errors;
3619 assert (buf);
3621 strcpy (buf, dirnam);
3622 strcat (buf, "/");
3623 strncat (buf, dp->d_name, end_offset);
3624 buf[buf_len] = LT_EOS_CHAR;
3626 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3627 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3628 ++errors;
3630 LT_DLFREE (buf);
3632 return errors;
3635 static int
3636 list_files_by_dir (dirnam, pargz, pargz_len)
3637 const char *dirnam;
3638 char **pargz;
3639 size_t *pargz_len;
3641 DIR *dirp = 0;
3642 int errors = 0;
3644 assert (dirnam && *dirnam);
3645 assert (pargz);
3646 assert (pargz_len);
3647 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3649 dirp = opendir (dirnam);
3650 if (dirp)
3652 struct dirent *dp = 0;
3654 while ((dp = readdir (dirp)))
3655 if (dp->d_name[0] != '.')
3656 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3658 ++errors;
3659 break;
3662 closedir (dirp);
3664 else
3665 ++errors;
3667 return errors;
3671 /* If there are any files in DIRNAME, call the function passed in
3672 DATA1 (with the name of each file and DATA2 as arguments). */
3673 static int
3674 foreachfile_callback (dirname, data1, data2)
3675 char *dirname;
3676 lt_ptr data1;
3677 lt_ptr data2;
3679 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3680 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3682 int is_done = 0;
3683 char *argz = 0;
3684 size_t argz_len = 0;
3686 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3687 goto cleanup;
3688 if (!argz)
3689 goto cleanup;
3692 char *filename = 0;
3693 while ((filename = argz_next (argz, argz_len, filename)))
3694 if ((is_done = (*func) (filename, data2)))
3695 break;
3698 cleanup:
3699 LT_DLFREE (argz);
3701 return is_done;
3705 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3706 with DATA. The filenames passed to FUNC would be suitable for
3707 passing to lt_dlopenext. The extensions are stripped so that
3708 individual modules do not generate several entries (e.g. libfoo.la,
3709 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3710 then the same directories that lt_dlopen would search are examined. */
3712 lt_dlforeachfile (search_path, func, data)
3713 const char *search_path;
3714 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3715 lt_ptr data;
3717 int is_done = 0;
3719 if (search_path)
3721 /* If a specific path was passed, search only the directories
3722 listed in it. */
3723 is_done = foreach_dirinpath (search_path, 0,
3724 foreachfile_callback, func, data);
3726 else
3728 /* Otherwise search the default paths. */
3729 is_done = foreach_dirinpath (user_search_path, 0,
3730 foreachfile_callback, func, data);
3731 if (!is_done)
3733 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3734 foreachfile_callback, func, data);
3737 #ifdef LTDL_SHLIBPATH_VAR
3738 if (!is_done)
3740 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3741 foreachfile_callback, func, data);
3743 #endif
3744 #ifdef LTDL_SYSSEARCHPATH
3745 if (!is_done)
3747 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3748 foreachfile_callback, func, data);
3750 #endif
3753 return is_done;
3757 lt_dlclose (handle)
3758 lt_dlhandle handle;
3760 lt_dlhandle cur, last;
3761 int errors = 0;
3763 LT_DLMUTEX_LOCK ();
3765 /* check whether the handle is valid */
3766 last = cur = handles;
3767 while (cur && handle != cur)
3769 last = cur;
3770 cur = cur->next;
3773 if (!cur)
3775 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3776 ++errors;
3777 goto done;
3780 handle->info.ref_count--;
3782 /* Note that even with resident modules, we must track the ref_count
3783 correctly incase the user decides to reset the residency flag
3784 later (even though the API makes no provision for that at the
3785 moment). */
3786 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3788 lt_user_data data = handle->loader->dlloader_data;
3790 if (handle != handles)
3792 last->next = handle->next;
3794 else
3796 handles = handle->next;
3799 errors += handle->loader->module_close (data, handle->module);
3800 errors += unload_deplibs(handle);
3802 /* It is up to the callers to free the data itself. */
3803 LT_DLFREE (handle->caller_data);
3805 LT_DLFREE (handle->info.filename);
3806 LT_DLFREE (handle->info.name);
3807 LT_DLFREE (handle);
3809 goto done;
3812 if (LT_DLIS_RESIDENT (handle))
3814 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3815 ++errors;
3818 done:
3819 LT_DLMUTEX_UNLOCK ();
3821 return errors;
3824 lt_ptr
3825 lt_dlsym (handle, symbol)
3826 lt_dlhandle handle;
3827 const char *symbol;
3829 size_t lensym;
3830 char lsym[LT_SYMBOL_LENGTH];
3831 char *sym;
3832 lt_ptr address;
3833 lt_user_data data;
3835 if (!handle)
3837 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3838 return 0;
3841 if (!symbol)
3843 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3844 return 0;
3847 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3848 + LT_STRLEN (handle->info.name);
3850 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3852 sym = lsym;
3854 else
3856 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3857 if (!sym)
3859 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3860 return 0;
3864 data = handle->loader->dlloader_data;
3865 if (handle->info.name)
3867 const char *saved_error;
3869 LT_DLMUTEX_GETERROR (saved_error);
3871 /* this is a libtool module */
3872 if (handle->loader->sym_prefix)
3874 strcpy(sym, handle->loader->sym_prefix);
3875 strcat(sym, handle->info.name);
3877 else
3879 strcpy(sym, handle->info.name);
3882 strcat(sym, "_LTX_");
3883 strcat(sym, symbol);
3885 /* try "modulename_LTX_symbol" */
3886 address = handle->loader->find_sym (data, handle->module, sym);
3887 if (address)
3889 if (sym != lsym)
3891 LT_DLFREE (sym);
3893 return address;
3895 LT_DLMUTEX_SETERROR (saved_error);
3898 /* otherwise try "symbol" */
3899 if (handle->loader->sym_prefix)
3901 strcpy(sym, handle->loader->sym_prefix);
3902 strcat(sym, symbol);
3904 else
3906 strcpy(sym, symbol);
3909 address = handle->loader->find_sym (data, handle->module, sym);
3910 if (sym != lsym)
3912 LT_DLFREE (sym);
3915 return address;
3918 const char *
3919 lt_dlerror ()
3921 const char *error;
3923 LT_DLMUTEX_GETERROR (error);
3924 LT_DLMUTEX_SETERROR (0);
3926 return error ? error : LT_DLSTRERROR (UNKNOWN);
3929 static int
3930 lt_dlpath_insertdir (ppath, before, dir)
3931 char **ppath;
3932 char *before;
3933 const char *dir;
3935 int errors = 0;
3936 char *canonical = 0;
3937 char *argz = 0;
3938 size_t argz_len = 0;
3940 assert (ppath);
3941 assert (dir && *dir);
3943 if (canonicalize_path (dir, &canonical) != 0)
3945 ++errors;
3946 goto cleanup;
3949 assert (canonical && *canonical);
3951 /* If *PPATH is empty, set it to DIR. */
3952 if (*ppath == 0)
3954 assert (!before); /* BEFORE cannot be set without PPATH. */
3955 assert (dir); /* Without DIR, don't call this function! */
3957 *ppath = lt_estrdup (dir);
3958 if (*ppath == 0)
3959 ++errors;
3961 return errors;
3964 assert (ppath && *ppath);
3966 if (argzize_path (*ppath, &argz, &argz_len) != 0)
3968 ++errors;
3969 goto cleanup;
3972 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
3973 if *PPATH is already canonicalized, and hence does not change length
3974 with respect to ARGZ. We canonicalize each entry as it is added to
3975 the search path, and don't call this function with (uncanonicalized)
3976 user paths, so this is a fair assumption. */
3977 if (before)
3979 assert (*ppath <= before);
3980 assert (before - *ppath <= strlen (*ppath));
3982 before = before - *ppath + argz;
3985 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3987 ++errors;
3988 goto cleanup;
3991 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3992 LT_DLMEM_REASSIGN (*ppath, argz);
3994 cleanup:
3995 LT_DLFREE (canonical);
3996 LT_DLFREE (argz);
3998 return errors;
4002 lt_dladdsearchdir (search_dir)
4003 const char *search_dir;
4005 int errors = 0;
4007 if (search_dir && *search_dir)
4009 LT_DLMUTEX_LOCK ();
4010 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4011 ++errors;
4012 LT_DLMUTEX_UNLOCK ();
4015 return errors;
4019 lt_dlinsertsearchdir (before, search_dir)
4020 const char *before;
4021 const char *search_dir;
4023 int errors = 0;
4025 if (before)
4027 LT_DLMUTEX_LOCK ();
4028 if ((before < user_search_path)
4029 || (before >= user_search_path + LT_STRLEN (user_search_path)))
4031 LT_DLMUTEX_UNLOCK ();
4032 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4033 return 1;
4035 LT_DLMUTEX_UNLOCK ();
4038 if (search_dir && *search_dir)
4040 LT_DLMUTEX_LOCK ();
4041 if (lt_dlpath_insertdir (&user_search_path,
4042 (char *) before, search_dir) != 0)
4044 ++errors;
4046 LT_DLMUTEX_UNLOCK ();
4049 return errors;
4053 lt_dlsetsearchpath (search_path)
4054 const char *search_path;
4056 int errors = 0;
4058 LT_DLMUTEX_LOCK ();
4059 LT_DLFREE (user_search_path);
4060 LT_DLMUTEX_UNLOCK ();
4062 if (!search_path || !LT_STRLEN (search_path))
4064 return errors;
4067 LT_DLMUTEX_LOCK ();
4068 if (canonicalize_path (search_path, &user_search_path) != 0)
4069 ++errors;
4070 LT_DLMUTEX_UNLOCK ();
4072 return errors;
4075 const char *
4076 lt_dlgetsearchpath ()
4078 const char *saved_path;
4080 LT_DLMUTEX_LOCK ();
4081 saved_path = user_search_path;
4082 LT_DLMUTEX_UNLOCK ();
4084 return saved_path;
4088 lt_dlmakeresident (handle)
4089 lt_dlhandle handle;
4091 int errors = 0;
4093 if (!handle)
4095 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4096 ++errors;
4098 else
4100 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4103 return errors;
4107 lt_dlisresident (handle)
4108 lt_dlhandle handle;
4110 if (!handle)
4112 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4113 return -1;
4116 return LT_DLIS_RESIDENT (handle);
4122 /* --- MODULE INFORMATION --- */
4124 const lt_dlinfo *
4125 lt_dlgetinfo (handle)
4126 lt_dlhandle handle;
4128 if (!handle)
4130 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4131 return 0;
4134 return &(handle->info);
4137 lt_dlhandle
4138 lt_dlhandle_next (place)
4139 lt_dlhandle place;
4141 return place ? place->next : handles;
4145 lt_dlforeach (func, data)
4146 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4147 lt_ptr data;
4149 int errors = 0;
4150 lt_dlhandle cur;
4152 LT_DLMUTEX_LOCK ();
4154 cur = handles;
4155 while (cur)
4157 lt_dlhandle tmp = cur;
4159 cur = cur->next;
4160 if ((*func) (tmp, data))
4162 ++errors;
4163 break;
4167 LT_DLMUTEX_UNLOCK ();
4169 return errors;
4172 lt_dlcaller_id
4173 lt_dlcaller_register ()
4175 static lt_dlcaller_id last_caller_id = 0;
4176 int result;
4178 LT_DLMUTEX_LOCK ();
4179 result = ++last_caller_id;
4180 LT_DLMUTEX_UNLOCK ();
4182 return result;
4185 lt_ptr
4186 lt_dlcaller_set_data (key, handle, data)
4187 lt_dlcaller_id key;
4188 lt_dlhandle handle;
4189 lt_ptr data;
4191 int n_elements = 0;
4192 lt_ptr stale = (lt_ptr) 0;
4193 int i;
4195 /* This needs to be locked so that the caller data can be updated
4196 simultaneously by different threads. */
4197 LT_DLMUTEX_LOCK ();
4199 if (handle->caller_data)
4200 while (handle->caller_data[n_elements].key)
4201 ++n_elements;
4203 for (i = 0; i < n_elements; ++i)
4205 if (handle->caller_data[i].key == key)
4207 stale = handle->caller_data[i].data;
4208 break;
4212 /* Ensure that there is enough room in this handle's caller_data
4213 array to accept a new element (and an empty end marker). */
4214 if (i == n_elements)
4216 lt_caller_data *temp
4217 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4219 if (!temp)
4221 stale = 0;
4222 goto done;
4225 handle->caller_data = temp;
4227 /* We only need this if we needed to allocate a new caller_data. */
4228 handle->caller_data[i].key = key;
4229 handle->caller_data[1+ i].key = 0;
4232 handle->caller_data[i].data = data;
4234 done:
4235 LT_DLMUTEX_UNLOCK ();
4237 return stale;
4240 lt_ptr
4241 lt_dlcaller_get_data (key, handle)
4242 lt_dlcaller_id key;
4243 lt_dlhandle handle;
4245 lt_ptr result = (lt_ptr) 0;
4247 /* This needs to be locked so that the caller data isn't updated by
4248 another thread part way through this function. */
4249 LT_DLMUTEX_LOCK ();
4251 /* Locate the index of the element with a matching KEY. */
4253 int i;
4254 for (i = 0; handle->caller_data[i].key; ++i)
4256 if (handle->caller_data[i].key == key)
4258 result = handle->caller_data[i].data;
4259 break;
4264 LT_DLMUTEX_UNLOCK ();
4266 return result;
4271 /* --- USER MODULE LOADER API --- */
4275 lt_dlloader_add (place, dlloader, loader_name)
4276 lt_dlloader *place;
4277 const struct lt_user_dlloader *dlloader;
4278 const char *loader_name;
4280 int errors = 0;
4281 lt_dlloader *node = 0, *ptr = 0;
4283 if ((dlloader == 0) /* diagnose null parameters */
4284 || (dlloader->module_open == 0)
4285 || (dlloader->module_close == 0)
4286 || (dlloader->find_sym == 0))
4288 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4289 return 1;
4292 /* Create a new dlloader node with copies of the user callbacks. */
4293 node = LT_EMALLOC (lt_dlloader, 1);
4294 if (!node)
4295 return 1;
4297 node->next = 0;
4298 node->loader_name = loader_name;
4299 node->sym_prefix = dlloader->sym_prefix;
4300 node->dlloader_exit = dlloader->dlloader_exit;
4301 node->module_open = dlloader->module_open;
4302 node->module_close = dlloader->module_close;
4303 node->find_sym = dlloader->find_sym;
4304 node->dlloader_data = dlloader->dlloader_data;
4306 LT_DLMUTEX_LOCK ();
4307 if (!loaders)
4309 /* If there are no loaders, NODE becomes the list! */
4310 loaders = node;
4312 else if (!place)
4314 /* If PLACE is not set, add NODE to the end of the
4315 LOADERS list. */
4316 for (ptr = loaders; ptr->next; ptr = ptr->next)
4318 /*NOWORK*/;
4321 ptr->next = node;
4323 else if (loaders == place)
4325 /* If PLACE is the first loader, NODE goes first. */
4326 node->next = place;
4327 loaders = node;
4329 else
4331 /* Find the node immediately preceding PLACE. */
4332 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4334 /*NOWORK*/;
4337 if (ptr->next != place)
4339 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4340 ++errors;
4342 else
4344 /* Insert NODE between PTR and PLACE. */
4345 node->next = place;
4346 ptr->next = node;
4350 LT_DLMUTEX_UNLOCK ();
4352 return errors;
4356 lt_dlloader_remove (loader_name)
4357 const char *loader_name;
4359 lt_dlloader *place = lt_dlloader_find (loader_name);
4360 lt_dlhandle handle;
4361 int errors = 0;
4363 if (!place)
4365 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4366 return 1;
4369 LT_DLMUTEX_LOCK ();
4371 /* Fail if there are any open modules which use this loader. */
4372 for (handle = handles; handle; handle = handle->next)
4374 if (handle->loader == place)
4376 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4377 ++errors;
4378 goto done;
4382 if (place == loaders)
4384 /* PLACE is the first loader in the list. */
4385 loaders = loaders->next;
4387 else
4389 /* Find the loader before the one being removed. */
4390 lt_dlloader *prev;
4391 for (prev = loaders; prev->next; prev = prev->next)
4393 if (!strcmp (prev->next->loader_name, loader_name))
4395 break;
4399 place = prev->next;
4400 prev->next = prev->next->next;
4403 if (place->dlloader_exit)
4405 errors = place->dlloader_exit (place->dlloader_data);
4408 LT_DLFREE (place);
4410 done:
4411 LT_DLMUTEX_UNLOCK ();
4413 return errors;
4416 lt_dlloader *
4417 lt_dlloader_next (place)
4418 lt_dlloader *place;
4420 lt_dlloader *next;
4422 LT_DLMUTEX_LOCK ();
4423 next = place ? place->next : loaders;
4424 LT_DLMUTEX_UNLOCK ();
4426 return next;
4429 const char *
4430 lt_dlloader_name (place)
4431 lt_dlloader *place;
4433 const char *name = 0;
4435 if (place)
4437 LT_DLMUTEX_LOCK ();
4438 name = place ? place->loader_name : 0;
4439 LT_DLMUTEX_UNLOCK ();
4441 else
4443 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4446 return name;
4449 lt_user_data *
4450 lt_dlloader_data (place)
4451 lt_dlloader *place;
4453 lt_user_data *data = 0;
4455 if (place)
4457 LT_DLMUTEX_LOCK ();
4458 data = place ? &(place->dlloader_data) : 0;
4459 LT_DLMUTEX_UNLOCK ();
4461 else
4463 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4466 return data;
4469 lt_dlloader *
4470 lt_dlloader_find (loader_name)
4471 const char *loader_name;
4473 lt_dlloader *place = 0;
4475 LT_DLMUTEX_LOCK ();
4476 for (place = loaders; place; place = place->next)
4478 if (strcmp (place->loader_name, loader_name) == 0)
4480 break;
4483 LT_DLMUTEX_UNLOCK ();
4485 return place;