* config/xtensa/xtensa.md (entry): Do not emit .frame directive.
[official-gcc.git] / libjava / libltdl / ltdl.c
blob6b5d8890efa77113e8f033ecdee9e24692c48cee
1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301 USA
28 #if HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #if HAVE_BOEHM_GC
33 # include <gc.h>
34 #endif
36 #if HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
40 #if HAVE_STDIO_H
41 # include <stdio.h>
42 #endif
44 /* Include the header defining malloc. On K&R C compilers,
45 that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */
46 #if HAVE_STDLIB_H
47 # include <stdlib.h>
48 #else
49 # if HAVE_MALLOC_H
50 # include <malloc.h>
51 # endif
52 #endif
54 #if HAVE_STRING_H
55 # include <string.h>
56 #else
57 # if HAVE_STRINGS_H
58 # include <strings.h>
59 # endif
60 #endif
62 #if HAVE_CTYPE_H
63 # include <ctype.h>
64 #endif
66 #if HAVE_MEMORY_H
67 # include <memory.h>
68 #endif
70 #if HAVE_ERRNO_H
71 # include <errno.h>
72 #endif
75 #ifndef __WINDOWS__
76 # ifdef __WIN32__
77 # define __WINDOWS__
78 # endif
79 #endif
82 #undef LT_USE_POSIX_DIRENT
83 #ifdef HAVE_CLOSEDIR
84 # ifdef HAVE_OPENDIR
85 # ifdef HAVE_READDIR
86 # ifdef HAVE_DIRENT_H
87 # define LT_USE_POSIX_DIRENT
88 # endif /* HAVE_DIRENT_H */
89 # endif /* HAVE_READDIR */
90 # endif /* HAVE_OPENDIR */
91 #endif /* HAVE_CLOSEDIR */
94 #undef LT_USE_WINDOWS_DIRENT_EMULATION
95 #ifndef LT_USE_POSIX_DIRENT
96 # ifdef __WINDOWS__
97 # define LT_USE_WINDOWS_DIRENT_EMULATION
98 # endif /* __WINDOWS__ */
99 #endif /* LT_USE_POSIX_DIRENT */
102 #ifdef LT_USE_POSIX_DIRENT
103 # include <dirent.h>
104 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
105 #else
106 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
107 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
108 # else
109 # define dirent direct
110 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
111 # if HAVE_SYS_NDIR_H
112 # include <sys/ndir.h>
113 # endif
114 # if HAVE_SYS_DIR_H
115 # include <sys/dir.h>
116 # endif
117 # if HAVE_NDIR_H
118 # include <ndir.h>
119 # endif
120 # endif
121 #endif
123 #if HAVE_ARGZ_H
124 # include <argz.h>
125 #endif
127 #if HAVE_ASSERT_H
128 # include <assert.h>
129 #else
130 # define assert(arg) ((void) 0)
131 #endif
133 #include "ltdl.h"
135 #if WITH_DMALLOC
136 # include <dmalloc.h>
137 #endif
142 /* --- WINDOWS SUPPORT --- */
145 #ifdef DLL_EXPORT
146 # define LT_GLOBAL_DATA __declspec(dllexport)
147 #else
148 # define LT_GLOBAL_DATA
149 #endif
151 /* fopen() mode flags for reading a text file */
152 #undef LT_READTEXT_MODE
153 #ifdef __WINDOWS__
154 # define LT_READTEXT_MODE "rt"
155 #else
156 # define LT_READTEXT_MODE "r"
157 #endif
159 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
161 #include <windows.h>
163 #define dirent lt_dirent
164 #define DIR lt_DIR
166 struct dirent
168 char d_name[2048];
169 int d_namlen;
172 typedef struct _DIR
174 HANDLE hSearch;
175 WIN32_FIND_DATA Win32FindData;
176 BOOL firsttime;
177 struct dirent file_info;
178 } DIR;
180 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
183 /* --- MANIFEST CONSTANTS --- */
186 /* Standard libltdl search path environment variable name */
187 #undef LTDL_SEARCHPATH_VAR
188 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
190 /* Standard libtool archive file extension. */
191 #undef LTDL_ARCHIVE_EXT
192 #define LTDL_ARCHIVE_EXT ".la"
194 /* max. filename length */
195 #ifndef LT_FILENAME_MAX
196 # define LT_FILENAME_MAX 1024
197 #endif
199 /* This is the maximum symbol size that won't require malloc/free */
200 #undef LT_SYMBOL_LENGTH
201 #define LT_SYMBOL_LENGTH 128
203 /* This accounts for the _LTX_ separator */
204 #undef LT_SYMBOL_OVERHEAD
205 #define LT_SYMBOL_OVERHEAD 5
210 /* --- MEMORY HANDLING --- */
213 /* These are the functions used internally. In addition to making
214 use of the associated function pointers above, they also perform
215 error handling. */
216 static char *lt_estrdup LT_PARAMS((const char *str));
217 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
218 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
220 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
221 #define rpl_realloc realloc
223 /* These are the pointers that can be changed by the caller: */
224 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
225 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
226 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
227 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
228 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
229 = (void (*) LT_PARAMS((lt_ptr))) free;
231 /* The following macros reduce the amount of typing needed to cast
232 assigned memory. */
233 #if WITH_DMALLOC
235 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
236 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
237 #define LT_DLFREE(p) \
238 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
240 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
241 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
243 #else
245 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
246 #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
247 #define LT_DLFREE(p) \
248 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
250 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
251 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
253 #endif
255 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
256 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
257 } LT_STMT_END
260 /* --- REPLACEMENT FUNCTIONS --- */
263 #undef strdup
264 #define strdup rpl_strdup
266 static char *strdup LT_PARAMS((const char *str));
268 static char *
269 strdup(str)
270 const char *str;
272 char *tmp = 0;
274 if (str)
276 tmp = LT_DLMALLOC (char, 1+ strlen (str));
277 if (tmp)
279 strcpy(tmp, str);
283 return tmp;
287 #if ! HAVE_STRCMP
289 #undef strcmp
290 #define strcmp rpl_strcmp
292 static int strcmp LT_PARAMS((const char *str1, const char *str2));
294 static int
295 strcmp (str1, str2)
296 const char *str1;
297 const char *str2;
299 if (str1 == str2)
300 return 0;
301 if (str1 == 0)
302 return -1;
303 if (str2 == 0)
304 return 1;
306 for (;*str1 && *str2; ++str1, ++str2)
308 if (*str1 != *str2)
309 break;
312 return (int)(*str1 - *str2);
314 #endif
317 #if ! HAVE_STRCHR
319 # if HAVE_INDEX
320 # define strchr index
321 # else
322 # define strchr rpl_strchr
324 static const char *strchr LT_PARAMS((const char *str, int ch));
326 static const char*
327 strchr(str, ch)
328 const char *str;
329 int ch;
331 const char *p;
333 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
334 /*NOWORK*/;
336 return (*p == (char)ch) ? p : 0;
339 # endif
340 #endif /* !HAVE_STRCHR */
343 #if ! HAVE_STRRCHR
345 # if HAVE_RINDEX
346 # define strrchr rindex
347 # else
348 # define strrchr rpl_strrchr
350 static const char *strrchr LT_PARAMS((const char *str, int ch));
352 static const char*
353 strrchr(str, ch)
354 const char *str;
355 int ch;
357 const char *p, *q = 0;
359 for (p = str; *p != LT_EOS_CHAR; ++p)
361 if (*p == (char) ch)
363 q = p;
367 return q;
370 # endif
371 #endif
373 /* NOTE: Neither bcopy nor the memcpy implementation below can
374 reliably handle copying in overlapping areas of memory. Use
375 memmove (for which there is a fallback implmentation below)
376 if you need that behaviour. */
377 #if ! HAVE_MEMCPY
379 # if HAVE_BCOPY
380 # define memcpy(dest, src, size) bcopy (src, dest, size)
381 # else
382 # define memcpy rpl_memcpy
384 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
386 static lt_ptr
387 memcpy (dest, src, size)
388 lt_ptr dest;
389 const lt_ptr src;
390 size_t size;
392 const char * s = src;
393 char * d = dest;
394 size_t i = 0;
396 for (i = 0; i < size; ++i)
398 d[i] = s[i];
401 return dest;
404 # endif /* !HAVE_BCOPY */
405 #endif /* !HAVE_MEMCPY */
407 #if ! HAVE_MEMMOVE
408 # define memmove rpl_memmove
410 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
412 static lt_ptr
413 memmove (dest, src, size)
414 lt_ptr dest;
415 const lt_ptr src;
416 size_t size;
418 const char * s = src;
419 char * d = dest;
420 size_t i;
422 if (d < s)
423 for (i = 0; i < size; ++i)
425 d[i] = s[i];
427 else if (d > s && size > 0)
428 for (i = size -1; ; --i)
430 d[i] = s[i];
431 if (i == 0)
432 break;
435 return dest;
438 #endif /* !HAVE_MEMMOVE */
440 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
442 static void closedir LT_PARAMS((DIR *entry));
444 static void
445 closedir(entry)
446 DIR *entry;
448 assert(entry != (DIR *) NULL);
449 FindClose(entry->hSearch);
450 lt_dlfree((lt_ptr)entry);
454 static DIR * opendir LT_PARAMS((const char *path));
456 static DIR*
457 opendir (path)
458 const char *path;
460 char file_specification[LT_FILENAME_MAX];
461 DIR *entry;
463 assert(path != (char *) NULL);
464 /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
465 (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
466 file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
467 (void) strcat(file_specification,"\\");
468 entry = LT_DLMALLOC (DIR,sizeof(DIR));
469 if (entry != (DIR *) 0)
471 entry->firsttime = TRUE;
472 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
474 if (entry->hSearch == INVALID_HANDLE_VALUE)
476 (void) strcat(file_specification,"\\*.*");
477 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
478 if (entry->hSearch == INVALID_HANDLE_VALUE)
480 LT_DLFREE (entry);
481 return (DIR *) 0;
484 return(entry);
488 static struct dirent *readdir LT_PARAMS((DIR *entry));
490 static struct dirent *readdir(entry)
491 DIR *entry;
494 status;
496 if (entry == (DIR *) 0)
497 return((struct dirent *) 0);
498 if (!entry->firsttime)
500 status = FindNextFile(entry->hSearch,&entry->Win32FindData);
501 if (status == 0)
502 return((struct dirent *) 0);
504 entry->firsttime = FALSE;
505 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
506 LT_FILENAME_MAX-1);
507 entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
508 entry->file_info.d_namlen = strlen(entry->file_info.d_name);
509 return(&entry->file_info);
512 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
514 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
515 ``realloc is not entirely portable''
516 In any case we want to use the allocator supplied by the user without
517 burdening them with an lt_dlrealloc function pointer to maintain.
518 Instead implement our own version (with known boundary conditions)
519 using lt_dlmalloc and lt_dlfree. */
521 /* #undef realloc
522 #define realloc rpl_realloc
524 #if 0
525 /* You can't (re)define realloc unless you also (re)define malloc.
526 Right now, this code uses the size of the *destination* to decide
527 how much to copy. That's not right, but you can't know the size
528 of the source unless you know enough about, or wrote malloc. So
529 this code is disabled... */
531 static lt_ptr
532 realloc (ptr, size)
533 lt_ptr ptr;
534 size_t size;
536 if (size == 0)
538 /* For zero or less bytes, free the original memory */
539 if (ptr != 0)
541 lt_dlfree (ptr);
544 return (lt_ptr) 0;
546 else if (ptr == 0)
548 /* Allow reallocation of a NULL pointer. */
549 return lt_dlmalloc (size);
551 else
553 /* Allocate a new block, copy and free the old block. */
554 lt_ptr mem = lt_dlmalloc (size);
556 if (mem)
558 memcpy (mem, ptr, size);
559 lt_dlfree (ptr);
562 /* Note that the contents of PTR are not damaged if there is
563 insufficient memory to realloc. */
564 return mem;
567 #endif
570 #if ! HAVE_ARGZ_APPEND
571 # define argz_append rpl_argz_append
573 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
574 const char *buf, size_t buf_len));
576 static error_t
577 argz_append (pargz, pargz_len, buf, buf_len)
578 char **pargz;
579 size_t *pargz_len;
580 const char *buf;
581 size_t buf_len;
583 size_t argz_len;
584 char *argz;
586 assert (pargz);
587 assert (pargz_len);
588 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
590 /* If nothing needs to be appended, no more work is required. */
591 if (buf_len == 0)
592 return 0;
594 /* Ensure there is enough room to append BUF_LEN. */
595 argz_len = *pargz_len + buf_len;
596 argz = LT_DLREALLOC (char, *pargz, argz_len);
597 if (!argz)
598 return ENOMEM;
600 /* Copy characters from BUF after terminating '\0' in ARGZ. */
601 memcpy (argz + *pargz_len, buf, buf_len);
603 /* Assign new values. */
604 *pargz = argz;
605 *pargz_len = argz_len;
607 return 0;
609 #endif /* !HAVE_ARGZ_APPEND */
612 #if ! HAVE_ARGZ_CREATE_SEP
613 # define argz_create_sep rpl_argz_create_sep
615 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
616 char **pargz, size_t *pargz_len));
618 static error_t
619 argz_create_sep (str, delim, pargz, pargz_len)
620 const char *str;
621 int delim;
622 char **pargz;
623 size_t *pargz_len;
625 size_t argz_len;
626 char *argz = 0;
628 assert (str);
629 assert (pargz);
630 assert (pargz_len);
632 /* Make a copy of STR, but replacing each occurence of
633 DELIM with '\0'. */
634 argz_len = 1+ LT_STRLEN (str);
635 if (argz_len)
637 const char *p;
638 char *q;
640 argz = LT_DLMALLOC (char, argz_len);
641 if (!argz)
642 return ENOMEM;
644 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
646 if (*p == delim)
648 /* Ignore leading delimiters, and fold consecutive
649 delimiters in STR into a single '\0' in ARGZ. */
650 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
651 *q++ = LT_EOS_CHAR;
652 else
653 --argz_len;
655 else
656 *q++ = *p;
658 /* Copy terminating LT_EOS_CHAR. */
659 *q = *p;
662 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
663 if (!argz_len)
664 LT_DLFREE (argz);
666 /* Assign new values. */
667 *pargz = argz;
668 *pargz_len = argz_len;
670 return 0;
672 #endif /* !HAVE_ARGZ_CREATE_SEP */
675 #if ! HAVE_ARGZ_INSERT
676 # define argz_insert rpl_argz_insert
678 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
679 char *before, const char *entry));
681 static error_t
682 argz_insert (pargz, pargz_len, before, entry)
683 char **pargz;
684 size_t *pargz_len;
685 char *before;
686 const char *entry;
688 assert (pargz);
689 assert (pargz_len);
690 assert (entry && *entry);
692 /* No BEFORE address indicates ENTRY should be inserted after the
693 current last element. */
694 if (!before)
695 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
697 /* This probably indicates a programmer error, but to preserve
698 semantics, scan back to the start of an entry if BEFORE points
699 into the middle of it. */
700 while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
701 --before;
704 size_t entry_len = 1+ LT_STRLEN (entry);
705 size_t argz_len = *pargz_len + entry_len;
706 size_t offset = before - *pargz;
707 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
709 if (!argz)
710 return ENOMEM;
712 /* Make BEFORE point to the equivalent offset in ARGZ that it
713 used to have in *PARGZ incase realloc() moved the block. */
714 before = argz + offset;
716 /* Move the ARGZ entries starting at BEFORE up into the new
717 space at the end -- making room to copy ENTRY into the
718 resulting gap. */
719 memmove (before + entry_len, before, *pargz_len - offset);
720 memcpy (before, entry, entry_len);
722 /* Assign new values. */
723 *pargz = argz;
724 *pargz_len = argz_len;
727 return 0;
729 #endif /* !HAVE_ARGZ_INSERT */
732 #if ! HAVE_ARGZ_NEXT
733 # define argz_next rpl_argz_next
735 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
736 const char *entry));
738 static char *
739 argz_next (argz, argz_len, entry)
740 char *argz;
741 size_t argz_len;
742 const char *entry;
744 assert ((argz && argz_len) || (!argz && !argz_len));
746 if (entry)
748 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
749 within the ARGZ vector. */
750 assert ((!argz && !argz_len)
751 || ((argz <= entry) && (entry < (argz + argz_len))));
753 /* Move to the char immediately after the terminating
754 '\0' of ENTRY. */
755 entry = 1+ strchr (entry, LT_EOS_CHAR);
757 /* Return either the new ENTRY, or else NULL if ARGZ is
758 exhausted. */
759 return (entry >= argz + argz_len) ? 0 : (char *) entry;
761 else
763 /* This should probably be flagged as a programmer error,
764 since starting an argz_next loop with the iterator set
765 to ARGZ is safer. To preserve semantics, handle the NULL
766 case by returning the start of ARGZ (if any). */
767 if (argz_len > 0)
768 return argz;
769 else
770 return 0;
773 #endif /* !HAVE_ARGZ_NEXT */
777 #if ! HAVE_ARGZ_STRINGIFY
778 # define argz_stringify rpl_argz_stringify
780 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
781 int sep));
783 static void
784 argz_stringify (argz, argz_len, sep)
785 char *argz;
786 size_t argz_len;
787 int sep;
789 assert ((argz && argz_len) || (!argz && !argz_len));
791 if (sep)
793 --argz_len; /* don't stringify the terminating EOS */
794 while (--argz_len > 0)
796 if (argz[argz_len] == LT_EOS_CHAR)
797 argz[argz_len] = sep;
801 #endif /* !HAVE_ARGZ_STRINGIFY */
806 /* --- TYPE DEFINITIONS -- */
809 /* This type is used for the array of caller data sets in each handler. */
810 typedef struct {
811 lt_dlcaller_id key;
812 lt_ptr data;
813 } lt_caller_data;
818 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
821 /* Extract the diagnostic strings from the error table macro in the same
822 order as the enumerated indices in ltdl.h. */
824 static const char *lt_dlerror_strings[] =
826 #define LT_ERROR(name, diagnostic) (diagnostic),
827 lt_dlerror_table
828 #undef LT_ERROR
833 /* This structure is used for the list of registered loaders. */
834 struct lt_dlloader {
835 struct lt_dlloader *next;
836 const char *loader_name; /* identifying name for each loader */
837 const char *sym_prefix; /* prefix for symbols */
838 lt_module_open *module_open;
839 lt_module_close *module_close;
840 lt_find_sym *find_sym;
841 lt_dlloader_exit *dlloader_exit;
842 lt_user_data dlloader_data;
845 struct lt_dlhandle_struct {
846 struct lt_dlhandle_struct *next;
847 lt_dlloader *loader; /* dlopening interface */
848 lt_dlinfo info;
849 int depcount; /* number of dependencies */
850 lt_dlhandle *deplibs; /* dependencies */
851 lt_module module; /* system module handle */
852 lt_ptr system; /* system specific data */
853 lt_caller_data *caller_data; /* per caller associated data */
854 int flags; /* various boolean stats */
857 /* Various boolean flags can be stored in the flags field of an
858 lt_dlhandle_struct... */
859 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
860 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
862 #define LT_DLRESIDENT_FLAG (0x01 << 0)
863 /* ...add more flags here... */
865 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
868 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
870 static const char objdir[] = LTDL_OBJDIR;
871 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
872 #ifdef LTDL_SHLIB_EXT
873 static const char shlib_ext[] = LTDL_SHLIB_EXT;
874 #endif
875 #ifdef LTDL_SYSSEARCHPATH
876 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
877 #endif
882 /* --- MUTEX LOCKING --- */
885 /* Macros to make it easier to run the lock functions only if they have
886 been registered. The reason for the complicated lock macro is to
887 ensure that the stored error message from the last error is not
888 accidentally erased if the current function doesn't generate an
889 error of its own. */
890 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
891 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
892 } LT_STMT_END
893 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
894 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
895 } LT_STMT_END
896 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
897 if (lt_dlmutex_seterror_func) \
898 (*lt_dlmutex_seterror_func) (errormsg); \
899 else lt_dllast_error = (errormsg); } LT_STMT_END
900 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
901 if (lt_dlmutex_seterror_func) \
902 (errormsg) = (*lt_dlmutex_geterror_func) (); \
903 else (errormsg) = lt_dllast_error; } LT_STMT_END
905 /* The mutex functions stored here are global, and are necessarily the
906 same for all threads that wish to share access to libltdl. */
907 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
908 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
909 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
910 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
911 static const char *lt_dllast_error = 0;
914 /* Either set or reset the mutex functions. Either all the arguments must
915 be valid functions, or else all can be NULL to turn off locking entirely.
916 The registered functions should be manipulating a static global lock
917 from the lock() and unlock() callbacks, which needs to be reentrant. */
919 lt_dlmutex_register (lock, unlock, seterror, geterror)
920 lt_dlmutex_lock *lock;
921 lt_dlmutex_unlock *unlock;
922 lt_dlmutex_seterror *seterror;
923 lt_dlmutex_geterror *geterror;
925 lt_dlmutex_unlock *old_unlock = unlock;
926 int errors = 0;
928 /* Lock using the old lock() callback, if any. */
929 LT_DLMUTEX_LOCK ();
931 if ((lock && unlock && seterror && geterror)
932 || !(lock || unlock || seterror || geterror))
934 lt_dlmutex_lock_func = lock;
935 lt_dlmutex_unlock_func = unlock;
936 lt_dlmutex_geterror_func = geterror;
938 else
940 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
941 ++errors;
944 /* Use the old unlock() callback we saved earlier, if any. Otherwise
945 record any errors using internal storage. */
946 if (old_unlock)
947 (*old_unlock) ();
949 /* Return the number of errors encountered during the execution of
950 this function. */
951 return errors;
957 /* --- ERROR HANDLING --- */
960 static const char **user_error_strings = 0;
961 static int errorcount = LT_ERROR_MAX;
964 lt_dladderror (diagnostic)
965 const char *diagnostic;
967 int errindex = 0;
968 int result = -1;
969 const char **temp = (const char **) 0;
971 assert (diagnostic);
973 LT_DLMUTEX_LOCK ();
975 errindex = errorcount - LT_ERROR_MAX;
976 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
977 if (temp)
979 user_error_strings = temp;
980 user_error_strings[errindex] = diagnostic;
981 result = errorcount++;
984 LT_DLMUTEX_UNLOCK ();
986 return result;
990 lt_dlseterror (errindex)
991 int errindex;
993 int errors = 0;
995 LT_DLMUTEX_LOCK ();
997 if (errindex >= errorcount || errindex < 0)
999 /* Ack! Error setting the error message! */
1000 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
1001 ++errors;
1003 else if (errindex < LT_ERROR_MAX)
1005 /* No error setting the error message! */
1006 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
1008 else
1010 /* No error setting the error message! */
1011 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
1014 LT_DLMUTEX_UNLOCK ();
1016 return errors;
1019 static lt_ptr
1020 lt_emalloc (size)
1021 size_t size;
1023 lt_ptr mem = lt_dlmalloc (size);
1024 if (size && !mem)
1025 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1026 return mem;
1029 static lt_ptr
1030 lt_erealloc (addr, size)
1031 lt_ptr addr;
1032 size_t size;
1034 lt_ptr mem = lt_dlrealloc (addr, size);
1035 if (size && !mem)
1036 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1037 return mem;
1040 static char *
1041 lt_estrdup (str)
1042 const char *str;
1044 char *copy = strdup (str);
1045 if (LT_STRLEN (str) && !copy)
1046 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1047 return copy;
1053 /* --- DLOPEN() INTERFACE LOADER --- */
1056 #if HAVE_LIBDL
1058 /* dynamic linking with dlopen/dlsym */
1060 #if HAVE_DLFCN_H
1061 # include <dlfcn.h>
1062 #endif
1064 #if HAVE_SYS_DL_H
1065 # include <sys/dl.h>
1066 #endif
1068 #ifdef RTLD_GLOBAL
1069 # define LT_GLOBAL RTLD_GLOBAL
1070 #else
1071 # ifdef DL_GLOBAL
1072 # define LT_GLOBAL DL_GLOBAL
1073 # endif
1074 #endif /* !RTLD_GLOBAL */
1075 #ifndef LT_GLOBAL
1076 # define LT_GLOBAL 0
1077 #endif /* !LT_GLOBAL */
1079 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1080 find out it does not work in some platform. */
1081 #ifndef LT_LAZY_OR_NOW
1082 # ifdef RTLD_LAZY
1083 # define LT_LAZY_OR_NOW RTLD_LAZY
1084 # else
1085 # ifdef DL_LAZY
1086 # define LT_LAZY_OR_NOW DL_LAZY
1087 # endif
1088 # endif /* !RTLD_LAZY */
1089 #endif
1090 #ifndef LT_LAZY_OR_NOW
1091 # ifdef RTLD_NOW
1092 # define LT_LAZY_OR_NOW RTLD_NOW
1093 # else
1094 # ifdef DL_NOW
1095 # define LT_LAZY_OR_NOW DL_NOW
1096 # endif
1097 # endif /* !RTLD_NOW */
1098 #endif
1099 #ifndef LT_LAZY_OR_NOW
1100 # define LT_LAZY_OR_NOW 0
1101 #endif /* !LT_LAZY_OR_NOW */
1103 #if HAVE_DLERROR
1104 # define DLERROR(arg) dlerror ()
1105 #else
1106 # define DLERROR(arg) LT_DLSTRERROR (arg)
1107 #endif
1109 static lt_module
1110 sys_dl_open (loader_data, filename)
1111 lt_user_data loader_data;
1112 const char *filename;
1114 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1116 if (!module)
1118 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1121 return module;
1124 static int
1125 sys_dl_close (loader_data, module)
1126 lt_user_data loader_data;
1127 lt_module module;
1129 int errors = 0;
1131 if (dlclose (module) != 0)
1133 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1134 ++errors;
1137 return errors;
1140 static lt_ptr
1141 sys_dl_sym (loader_data, module, symbol)
1142 lt_user_data loader_data;
1143 lt_module module;
1144 const char *symbol;
1146 lt_ptr address = dlsym (module, symbol);
1148 if (!address)
1150 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1153 return address;
1156 static struct lt_user_dlloader sys_dl =
1158 # ifdef NEED_USCORE
1159 "_",
1160 # else
1162 # endif
1163 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1166 #endif /* HAVE_LIBDL */
1170 /* --- SHL_LOAD() INTERFACE LOADER --- */
1172 #if HAVE_SHL_LOAD
1174 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1176 #ifdef HAVE_DL_H
1177 # include <dl.h>
1178 #endif
1180 /* some flags are missing on some systems, so we provide
1181 * harmless defaults.
1183 * Mandatory:
1184 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1185 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1187 * Optionally:
1188 * BIND_FIRST - Place the library at the head of the symbol search
1189 * order.
1190 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1191 * unsatisfied symbols as fatal. This flag allows
1192 * binding of unsatisfied code symbols to be deferred
1193 * until use.
1194 * [Perl: For certain libraries, like DCE, deferred
1195 * binding often causes run time problems. Adding
1196 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1197 * unresolved references in situations like this.]
1198 * BIND_NOSTART - Do not call the initializer for the shared library
1199 * when the library is loaded, nor on a future call to
1200 * shl_unload().
1201 * BIND_VERBOSE - Print verbose messages concerning possible
1202 * unsatisfied symbols.
1204 * hp9000s700/hp9000s800:
1205 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1206 * present at library load time.
1207 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1208 * library specified by the path argument.
1211 #ifndef DYNAMIC_PATH
1212 # define DYNAMIC_PATH 0
1213 #endif
1214 #ifndef BIND_RESTRICTED
1215 # define BIND_RESTRICTED 0
1216 #endif
1218 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1220 static lt_module
1221 sys_shl_open (loader_data, filename)
1222 lt_user_data loader_data;
1223 const char *filename;
1225 static shl_t self = (shl_t) 0;
1226 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1228 /* Since searching for a symbol against a NULL module handle will also
1229 look in everything else that was already loaded and exported with
1230 the -E compiler flag, we always cache a handle saved before any
1231 modules are loaded. */
1232 if (!self)
1234 lt_ptr address;
1235 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1238 if (!filename)
1240 module = self;
1242 else
1244 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1246 if (!module)
1248 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1252 return module;
1255 static int
1256 sys_shl_close (loader_data, module)
1257 lt_user_data loader_data;
1258 lt_module module;
1260 int errors = 0;
1262 if (module && (shl_unload ((shl_t) (module)) != 0))
1264 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1265 ++errors;
1268 return errors;
1271 static lt_ptr
1272 sys_shl_sym (loader_data, module, symbol)
1273 lt_user_data loader_data;
1274 lt_module module;
1275 const char *symbol;
1277 lt_ptr address = 0;
1279 /* sys_shl_open should never return a NULL module handle */
1280 if (module == (lt_module) 0)
1282 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1284 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1286 if (!address)
1288 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1292 return address;
1295 static struct lt_user_dlloader sys_shl = {
1296 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1299 #endif /* HAVE_SHL_LOAD */
1304 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1306 #ifdef __WINDOWS__
1308 /* dynamic linking for Win32 */
1310 #include <windows.h>
1312 /* Forward declaration; required to implement handle search below. */
1313 static lt_dlhandle handles;
1315 static lt_module
1316 sys_wll_open (loader_data, filename)
1317 lt_user_data loader_data;
1318 const char *filename;
1320 lt_dlhandle cur;
1321 lt_module module = 0;
1322 const char *errormsg = 0;
1323 char *searchname = 0;
1324 char *ext;
1325 char self_name_buf[MAX_PATH];
1327 if (!filename)
1329 /* Get the name of main module */
1330 *self_name_buf = 0;
1331 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1332 filename = ext = self_name_buf;
1334 else
1336 ext = strrchr (filename, '.');
1339 if (ext)
1341 /* FILENAME already has an extension. */
1342 searchname = lt_estrdup (filename);
1344 else
1346 /* Append a `.' to stop Windows from adding an
1347 implicit `.dll' extension. */
1348 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1349 if (searchname)
1350 sprintf (searchname, "%s.", filename);
1352 if (!searchname)
1353 return 0;
1355 #if __CYGWIN__
1357 char wpath[MAX_PATH];
1358 cygwin_conv_to_full_win32_path(searchname, wpath);
1359 module = LoadLibrary(wpath);
1361 #else
1362 module = LoadLibrary (searchname);
1363 #endif
1364 LT_DLFREE (searchname);
1366 /* libltdl expects this function to fail if it is unable
1367 to physically load the library. Sadly, LoadLibrary
1368 will search the loaded libraries for a match and return
1369 one of them if the path search load fails.
1371 We check whether LoadLibrary is returning a handle to
1372 an already loaded module, and simulate failure if we
1373 find one. */
1374 LT_DLMUTEX_LOCK ();
1375 cur = handles;
1376 while (cur)
1378 if (!cur->module)
1380 cur = 0;
1381 break;
1384 if (cur->module == module)
1386 break;
1389 cur = cur->next;
1391 LT_DLMUTEX_UNLOCK ();
1393 if (cur || !module)
1395 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1396 module = 0;
1399 return module;
1402 static int
1403 sys_wll_close (loader_data, module)
1404 lt_user_data loader_data;
1405 lt_module module;
1407 int errors = 0;
1409 if (FreeLibrary(module) == 0)
1411 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1412 ++errors;
1415 return errors;
1418 static lt_ptr
1419 sys_wll_sym (loader_data, module, symbol)
1420 lt_user_data loader_data;
1421 lt_module module;
1422 const char *symbol;
1424 lt_ptr address = GetProcAddress (module, symbol);
1426 if (!address)
1428 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1431 return address;
1434 static struct lt_user_dlloader sys_wll = {
1435 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1438 #endif /* __WINDOWS__ */
1443 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1446 #ifdef __BEOS__
1448 /* dynamic linking for BeOS */
1450 #include <kernel/image.h>
1452 static lt_module
1453 sys_bedl_open (loader_data, filename)
1454 lt_user_data loader_data;
1455 const char *filename;
1457 image_id image = 0;
1459 if (filename)
1461 image = load_add_on (filename);
1463 else
1465 image_info info;
1466 int32 cookie = 0;
1467 if (get_next_image_info (0, &cookie, &info) == B_OK)
1468 image = load_add_on (info.name);
1471 if (image <= 0)
1473 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1474 image = 0;
1477 return (lt_module) image;
1480 static int
1481 sys_bedl_close (loader_data, module)
1482 lt_user_data loader_data;
1483 lt_module module;
1485 int errors = 0;
1487 if (unload_add_on ((image_id) module) != B_OK)
1489 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1490 ++errors;
1493 return errors;
1496 static lt_ptr
1497 sys_bedl_sym (loader_data, module, symbol)
1498 lt_user_data loader_data;
1499 lt_module module;
1500 const char *symbol;
1502 lt_ptr address = 0;
1503 image_id image = (image_id) module;
1505 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1507 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1508 address = 0;
1511 return address;
1514 static struct lt_user_dlloader sys_bedl = {
1515 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1518 #endif /* __BEOS__ */
1523 /* --- DLD_LINK() INTERFACE LOADER --- */
1526 #if HAVE_DLD
1528 /* dynamic linking with dld */
1530 #if HAVE_DLD_H
1531 #include <dld.h>
1532 #endif
1534 static lt_module
1535 sys_dld_open (loader_data, filename)
1536 lt_user_data loader_data;
1537 const char *filename;
1539 lt_module module = strdup (filename);
1541 if (dld_link (filename) != 0)
1543 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1544 LT_DLFREE (module);
1545 module = 0;
1548 return module;
1551 static int
1552 sys_dld_close (loader_data, module)
1553 lt_user_data loader_data;
1554 lt_module module;
1556 int errors = 0;
1558 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1560 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1561 ++errors;
1563 else
1565 LT_DLFREE (module);
1568 return errors;
1571 static lt_ptr
1572 sys_dld_sym (loader_data, module, symbol)
1573 lt_user_data loader_data;
1574 lt_module module;
1575 const char *symbol;
1577 lt_ptr address = dld_get_func (symbol);
1579 if (!address)
1581 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1584 return address;
1587 static struct lt_user_dlloader sys_dld = {
1588 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1591 #endif /* HAVE_DLD */
1593 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1594 #if HAVE_DYLD
1597 #if HAVE_MACH_O_DYLD_H
1598 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1599 /* Is this correct? Does it still function properly? */
1600 #define __private_extern__ extern
1601 #endif
1602 # include <mach-o/dyld.h>
1603 #endif
1604 #include <mach-o/getsect.h>
1606 /* We have to put some stuff here that isn't in older dyld.h files */
1607 #ifndef ENUM_DYLD_BOOL
1608 # define ENUM_DYLD_BOOL
1609 # undef FALSE
1610 # undef TRUE
1611 enum DYLD_BOOL {
1612 FALSE,
1613 TRUE
1615 #endif
1616 #ifndef LC_REQ_DYLD
1617 # define LC_REQ_DYLD 0x80000000
1618 #endif
1619 #ifndef LC_LOAD_WEAK_DYLIB
1620 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1621 #endif
1622 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1623 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1624 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1625 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1627 #ifndef NSADDIMAGE_OPTION_NONE
1628 #define NSADDIMAGE_OPTION_NONE 0x0
1629 #endif
1630 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1631 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1632 #endif
1633 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1634 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1635 #endif
1636 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1637 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1638 #endif
1639 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1640 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1641 #endif
1642 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1643 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1644 #endif
1645 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1646 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1647 #endif
1648 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1649 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1650 #endif
1651 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1652 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1653 #endif
1656 static const char *
1657 lt_int_dyld_error(othererror)
1658 char* othererror;
1660 /* return the dyld error string, or the passed in error string if none */
1661 NSLinkEditErrors ler;
1662 int lerno;
1663 const char *errstr;
1664 const char *file;
1665 NSLinkEditError(&ler,&lerno,&file,&errstr);
1666 if (!errstr || !strlen(errstr)) errstr = othererror;
1667 return errstr;
1670 static const struct mach_header *
1671 lt_int_dyld_get_mach_header_from_nsmodule(module)
1672 NSModule module;
1674 /* There should probably be an apple dyld api for this */
1675 int i=_dyld_image_count();
1676 int j;
1677 const char *modname=NSNameOfModule(module);
1678 const struct mach_header *mh=NULL;
1679 if (!modname) return NULL;
1680 for (j = 0; j < i; j++)
1682 if (!strcmp(_dyld_get_image_name(j),modname))
1684 mh=_dyld_get_image_header(j);
1685 break;
1688 return mh;
1691 static const char* lt_int_dyld_lib_install_name(mh)
1692 const struct mach_header *mh;
1694 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1695 is installed, for uninstalled libs we need to check the install_names against
1696 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1697 different lib was loaded as a result
1699 int j;
1700 struct load_command *lc;
1701 unsigned long offset = sizeof(struct mach_header);
1702 const char* retStr=NULL;
1703 for (j = 0; j < mh->ncmds; j++)
1705 lc = (struct load_command*)(((unsigned long)mh) + offset);
1706 if (LC_ID_DYLIB == lc->cmd)
1708 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1709 (unsigned long)lc);
1711 offset += lc->cmdsize;
1713 return retStr;
1716 static const struct mach_header *
1717 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1719 int i=_dyld_image_count();
1720 int j;
1721 const struct mach_header *mh=NULL;
1722 const char *id=NULL;
1723 for (j = 0; j < i; j++)
1725 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1726 if ((id) && (!strcmp(id,name)))
1728 mh=_dyld_get_image_header(j);
1729 break;
1732 return mh;
1735 static NSSymbol
1736 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1737 const char *symbol;
1738 const struct mach_header *mh;
1740 /* Safe to assume our mh is good */
1741 int j;
1742 struct load_command *lc;
1743 unsigned long offset = sizeof(struct mach_header);
1744 NSSymbol retSym = 0;
1745 const struct mach_header *mh1;
1746 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1748 for (j = 0; j < mh->ncmds; j++)
1750 lc = (struct load_command*)(((unsigned long)mh) + offset);
1751 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1753 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1754 (unsigned long)lc));
1755 if (!mh1)
1757 /* Maybe NSAddImage can find it */
1758 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1759 (unsigned long)lc),
1760 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1761 NSADDIMAGE_OPTION_WITH_SEARCHING +
1762 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1764 if (mh1)
1766 retSym = ltdl_NSLookupSymbolInImage(mh1,
1767 symbol,
1768 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1769 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1771 if (retSym) break;
1774 offset += lc->cmdsize;
1777 return retSym;
1780 static int
1781 sys_dyld_init()
1783 int retCode = 0;
1784 int err = 0;
1785 if (!_dyld_present()) {
1786 retCode=1;
1788 else {
1789 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1790 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1791 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1792 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1794 return retCode;
1797 static lt_module
1798 sys_dyld_open (loader_data, filename)
1799 lt_user_data loader_data;
1800 const char *filename;
1802 lt_module module = 0;
1803 NSObjectFileImage ofi = 0;
1804 NSObjectFileImageReturnCode ofirc;
1806 if (!filename)
1807 return (lt_module)-1;
1808 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1809 switch (ofirc)
1811 case NSObjectFileImageSuccess:
1812 module = NSLinkModule(ofi, filename,
1813 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1814 | NSLINKMODULE_OPTION_PRIVATE
1815 | NSLINKMODULE_OPTION_BINDNOW);
1816 NSDestroyObjectFileImage(ofi);
1817 if (module)
1818 ltdl_NSMakePrivateModulePublic(module);
1819 break;
1820 case NSObjectFileImageInappropriateFile:
1821 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1823 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1824 break;
1826 default:
1827 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1828 return 0;
1830 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1831 return module;
1834 static int
1835 sys_dyld_close (loader_data, module)
1836 lt_user_data loader_data;
1837 lt_module module;
1839 int retCode = 0;
1840 int flags = 0;
1841 if (module == (lt_module)-1) return 0;
1842 #ifdef __BIG_ENDIAN__
1843 if (((struct mach_header *)module)->magic == MH_MAGIC)
1844 #else
1845 if (((struct mach_header *)module)->magic == MH_CIGAM)
1846 #endif
1848 LT_DLMUTEX_SETERROR("Can not close a dylib");
1849 retCode = 1;
1851 else
1853 #if 1
1854 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1855 get a segfault in atexit(), due to compiler and dynamic loader differences of
1856 opinion, this works around that.
1858 if ((const struct section *)NULL !=
1859 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1860 "__DATA","__mod_term_func"))
1862 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1864 #endif
1865 #ifdef __ppc__
1866 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1867 #endif
1868 if (!NSUnLinkModule(module,flags))
1870 retCode=1;
1871 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1875 return retCode;
1878 static lt_ptr
1879 sys_dyld_sym (loader_data, module, symbol)
1880 lt_user_data loader_data;
1881 lt_module module;
1882 const char *symbol;
1884 lt_ptr address = 0;
1885 NSSymbol *nssym = 0;
1886 void *unused;
1887 const struct mach_header *mh=NULL;
1888 char saveError[256] = "Symbol not found";
1889 if (module == (lt_module)-1)
1891 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1892 return address;
1894 #ifdef __BIG_ENDIAN__
1895 if (((struct mach_header *)module)->magic == MH_MAGIC)
1896 #else
1897 if (((struct mach_header *)module)->magic == MH_CIGAM)
1898 #endif
1900 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1902 mh=module;
1903 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1905 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1906 symbol,
1907 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1908 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1914 else {
1915 nssym = NSLookupSymbolInModule(module, symbol);
1917 if (!nssym)
1919 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1920 saveError[255] = 0;
1921 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1922 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1924 if (!nssym)
1926 LT_DLMUTEX_SETERROR (saveError);
1927 return NULL;
1929 return NSAddressOfSymbol(nssym);
1932 static struct lt_user_dlloader sys_dyld =
1933 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1936 #endif /* HAVE_DYLD */
1939 /* --- DLPREOPEN() INTERFACE LOADER --- */
1942 /* emulate dynamic linking using preloaded_symbols */
1944 typedef struct lt_dlsymlists_t
1946 struct lt_dlsymlists_t *next;
1947 const lt_dlsymlist *syms;
1948 } lt_dlsymlists_t;
1950 static const lt_dlsymlist *default_preloaded_symbols = 0;
1951 static lt_dlsymlists_t *preloaded_symbols = 0;
1953 static int
1954 presym_init (loader_data)
1955 lt_user_data loader_data;
1957 int errors = 0;
1959 LT_DLMUTEX_LOCK ();
1961 preloaded_symbols = 0;
1962 if (default_preloaded_symbols)
1964 errors = lt_dlpreload (default_preloaded_symbols);
1967 LT_DLMUTEX_UNLOCK ();
1969 return errors;
1972 static int
1973 presym_free_symlists ()
1975 lt_dlsymlists_t *lists;
1977 LT_DLMUTEX_LOCK ();
1979 lists = preloaded_symbols;
1980 while (lists)
1982 lt_dlsymlists_t *tmp = lists;
1984 lists = lists->next;
1985 LT_DLFREE (tmp);
1987 preloaded_symbols = 0;
1989 LT_DLMUTEX_UNLOCK ();
1991 return 0;
1994 static int
1995 presym_exit (loader_data)
1996 lt_user_data loader_data;
1998 presym_free_symlists ();
1999 return 0;
2002 static int
2003 presym_add_symlist (preloaded)
2004 const lt_dlsymlist *preloaded;
2006 lt_dlsymlists_t *tmp;
2007 lt_dlsymlists_t *lists;
2008 int errors = 0;
2010 LT_DLMUTEX_LOCK ();
2012 lists = preloaded_symbols;
2013 while (lists)
2015 if (lists->syms == preloaded)
2017 goto done;
2019 lists = lists->next;
2022 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2023 if (tmp)
2025 memset (tmp, 0, sizeof(lt_dlsymlists_t));
2026 tmp->syms = preloaded;
2027 tmp->next = preloaded_symbols;
2028 preloaded_symbols = tmp;
2030 else
2032 ++errors;
2035 done:
2036 LT_DLMUTEX_UNLOCK ();
2037 return errors;
2040 static lt_module
2041 presym_open (loader_data, filename)
2042 lt_user_data loader_data;
2043 const char *filename;
2045 lt_dlsymlists_t *lists;
2046 lt_module module = (lt_module) 0;
2048 LT_DLMUTEX_LOCK ();
2049 lists = preloaded_symbols;
2051 if (!lists)
2053 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2054 goto done;
2057 /* Can't use NULL as the reflective symbol header, as NULL is
2058 used to mark the end of the entire symbol list. Self-dlpreopened
2059 symbols follow this magic number, chosen to be an unlikely
2060 clash with a real module name. */
2061 if (!filename)
2063 filename = "@PROGRAM@";
2066 while (lists)
2068 const lt_dlsymlist *syms = lists->syms;
2070 while (syms->name)
2072 if (!syms->address && strcmp(syms->name, filename) == 0)
2074 module = (lt_module) syms;
2075 goto done;
2077 ++syms;
2080 lists = lists->next;
2083 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2085 done:
2086 LT_DLMUTEX_UNLOCK ();
2087 return module;
2090 static int
2091 presym_close (loader_data, module)
2092 lt_user_data loader_data;
2093 lt_module module;
2095 /* Just to silence gcc -Wall */
2096 module = 0;
2097 return 0;
2100 static lt_ptr
2101 presym_sym (loader_data, module, symbol)
2102 lt_user_data loader_data;
2103 lt_module module;
2104 const char *symbol;
2106 lt_dlsymlist *syms = (lt_dlsymlist*) module;
2108 ++syms;
2109 while (syms->address)
2111 if (strcmp(syms->name, symbol) == 0)
2113 return syms->address;
2116 ++syms;
2119 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2121 return 0;
2124 static struct lt_user_dlloader presym = {
2125 0, presym_open, presym_close, presym_sym, presym_exit, 0
2132 /* --- DYNAMIC MODULE LOADING --- */
2135 /* The type of a function used at each iteration of foreach_dirinpath(). */
2136 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2137 lt_ptr data2));
2139 static int foreach_dirinpath LT_PARAMS((const char *search_path,
2140 const char *base_name,
2141 foreach_callback_func *func,
2142 lt_ptr data1, lt_ptr data2));
2144 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2145 lt_ptr ignored));
2146 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2147 lt_ptr ignored));
2148 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2149 lt_ptr data2));
2152 static int canonicalize_path LT_PARAMS((const char *path,
2153 char **pcanonical));
2154 static int argzize_path LT_PARAMS((const char *path,
2155 char **pargz,
2156 size_t *pargz_len));
2157 static FILE *find_file LT_PARAMS((const char *search_path,
2158 const char *base_name,
2159 char **pdir));
2160 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2161 const char *base_name,
2162 lt_dlhandle *handle));
2163 static int find_module LT_PARAMS((lt_dlhandle *handle,
2164 const char *dir,
2165 const char *libdir,
2166 const char *dlname,
2167 const char *old_name,
2168 int installed));
2169 static int free_vars LT_PARAMS((char *dlname, char *oldname,
2170 char *libdir, char *deplibs));
2171 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2172 char *deplibs));
2173 static int trim LT_PARAMS((char **dest,
2174 const char *str));
2175 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2176 const char *filename));
2177 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2178 const char *filename));
2179 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2180 static int lt_argz_insert LT_PARAMS((char **pargz,
2181 size_t *pargz_len,
2182 char *before,
2183 const char *entry));
2184 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2185 size_t *pargz_len,
2186 const char *entry));
2187 static int lt_argz_insertdir LT_PARAMS((char **pargz,
2188 size_t *pargz_len,
2189 const char *dirnam,
2190 struct dirent *dp));
2191 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2192 char *before,
2193 const char *dir));
2194 static int list_files_by_dir LT_PARAMS((const char *dirnam,
2195 char **pargz,
2196 size_t *pargz_len));
2197 static int file_not_found LT_PARAMS((void));
2199 static char *user_search_path= 0;
2200 static lt_dlloader *loaders = 0;
2201 static lt_dlhandle handles = 0;
2202 static int initialized = 0;
2204 /* Initialize libltdl. */
2206 lt_dlinit ()
2208 int errors = 0;
2210 LT_DLMUTEX_LOCK ();
2212 /* Initialize only at first call. */
2213 if (++initialized == 1)
2215 handles = 0;
2216 user_search_path = 0; /* empty search path */
2218 #if HAVE_LIBDL
2219 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2220 #endif
2221 #if HAVE_SHL_LOAD
2222 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2223 #endif
2224 #ifdef __WINDOWS__
2225 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2226 #endif
2227 #ifdef __BEOS__
2228 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2229 #endif
2230 #if HAVE_DLD
2231 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2232 #endif
2233 #if HAVE_DYLD
2234 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2235 errors += sys_dyld_init();
2236 #endif
2237 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2239 if (presym_init (presym.dlloader_data))
2241 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2242 ++errors;
2244 else if (errors != 0)
2246 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2247 ++errors;
2251 LT_DLMUTEX_UNLOCK ();
2253 return errors;
2257 lt_dlpreload (preloaded)
2258 const lt_dlsymlist *preloaded;
2260 int errors = 0;
2262 if (preloaded)
2264 errors = presym_add_symlist (preloaded);
2266 else
2268 presym_free_symlists();
2270 LT_DLMUTEX_LOCK ();
2271 if (default_preloaded_symbols)
2273 errors = lt_dlpreload (default_preloaded_symbols);
2275 LT_DLMUTEX_UNLOCK ();
2278 return errors;
2282 lt_dlpreload_default (preloaded)
2283 const lt_dlsymlist *preloaded;
2285 LT_DLMUTEX_LOCK ();
2286 default_preloaded_symbols = preloaded;
2287 LT_DLMUTEX_UNLOCK ();
2288 return 0;
2292 lt_dlexit ()
2294 /* shut down libltdl */
2295 lt_dlloader *loader;
2296 int errors = 0;
2298 LT_DLMUTEX_LOCK ();
2299 loader = loaders;
2301 if (!initialized)
2303 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2304 ++errors;
2305 goto done;
2308 /* shut down only at last call. */
2309 if (--initialized == 0)
2311 int level;
2313 while (handles && LT_DLIS_RESIDENT (handles))
2315 handles = handles->next;
2318 /* close all modules */
2319 for (level = 1; handles; ++level)
2321 lt_dlhandle cur = handles;
2322 int saw_nonresident = 0;
2324 while (cur)
2326 lt_dlhandle tmp = cur;
2327 cur = cur->next;
2328 if (!LT_DLIS_RESIDENT (tmp))
2329 saw_nonresident = 1;
2330 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2332 if (lt_dlclose (tmp))
2334 ++errors;
2338 /* done if only resident modules are left */
2339 if (!saw_nonresident)
2340 break;
2343 /* close all loaders */
2344 while (loader)
2346 lt_dlloader *next = loader->next;
2347 lt_user_data data = loader->dlloader_data;
2348 if (loader->dlloader_exit && loader->dlloader_exit (data))
2350 ++errors;
2353 LT_DLMEM_REASSIGN (loader, next);
2355 loaders = 0;
2358 done:
2359 LT_DLMUTEX_UNLOCK ();
2360 return errors;
2363 static int
2364 tryall_dlopen (handle, filename)
2365 lt_dlhandle *handle;
2366 const char *filename;
2368 lt_dlhandle cur;
2369 lt_dlloader *loader;
2370 const char *saved_error;
2371 int errors = 0;
2373 LT_DLMUTEX_GETERROR (saved_error);
2374 LT_DLMUTEX_LOCK ();
2376 cur = handles;
2377 loader = loaders;
2379 /* check whether the module was already opened */
2380 while (cur)
2382 /* try to dlopen the program itself? */
2383 if (!cur->info.filename && !filename)
2385 break;
2388 if (cur->info.filename && filename
2389 && strcmp (cur->info.filename, filename) == 0)
2391 break;
2394 cur = cur->next;
2397 if (cur)
2399 ++cur->info.ref_count;
2400 *handle = cur;
2401 goto done;
2404 cur = *handle;
2405 if (filename)
2407 /* Comment out the check of file permissions using access.
2408 This call seems to always return -1 with error EACCES.
2410 /* We need to catch missing file errors early so that
2411 file_not_found() can detect what happened.
2412 if (access (filename, R_OK) != 0)
2414 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2415 ++errors;
2416 goto done;
2417 } */
2419 cur->info.filename = lt_estrdup (filename);
2420 if (!cur->info.filename)
2422 ++errors;
2423 goto done;
2426 else
2428 cur->info.filename = 0;
2431 while (loader)
2433 lt_user_data data = loader->dlloader_data;
2435 cur->module = loader->module_open (data, filename);
2437 if (cur->module != 0)
2439 break;
2441 loader = loader->next;
2444 if (!loader)
2446 LT_DLFREE (cur->info.filename);
2447 ++errors;
2448 goto done;
2451 cur->loader = loader;
2452 LT_DLMUTEX_SETERROR (saved_error);
2454 done:
2455 LT_DLMUTEX_UNLOCK ();
2457 return errors;
2460 static int
2461 tryall_dlopen_module (handle, prefix, dirname, dlname)
2462 lt_dlhandle *handle;
2463 const char *prefix;
2464 const char *dirname;
2465 const char *dlname;
2467 int error = 0;
2468 char *filename = 0;
2469 size_t filename_len = 0;
2470 size_t dirname_len = LT_STRLEN (dirname);
2472 assert (handle);
2473 assert (dirname);
2474 assert (dlname);
2475 #ifdef LT_DIRSEP_CHAR
2476 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2477 should make it into this function: */
2478 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2479 #endif
2481 if (dirname_len > 0)
2482 if (dirname[dirname_len -1] == '/')
2483 --dirname_len;
2484 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2486 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2487 The PREFIX (if any) is handled below. */
2488 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2489 if (!filename)
2490 return 1;
2492 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2494 /* Now that we have combined DIRNAME and MODULENAME, if there is
2495 also a PREFIX to contend with, simply recurse with the arguments
2496 shuffled. Otherwise, attempt to open FILENAME as a module. */
2497 if (prefix)
2499 error += tryall_dlopen_module (handle,
2500 (const char *) 0, prefix, filename);
2502 else if (tryall_dlopen (handle, filename) != 0)
2504 ++error;
2507 LT_DLFREE (filename);
2508 return error;
2511 static int
2512 find_module (handle, dir, libdir, dlname, old_name, installed)
2513 lt_dlhandle *handle;
2514 const char *dir;
2515 const char *libdir;
2516 const char *dlname;
2517 const char *old_name;
2518 int installed;
2520 /* Try to open the old library first; if it was dlpreopened,
2521 we want the preopened version of it, even if a dlopenable
2522 module is available. */
2523 if (old_name && tryall_dlopen (handle, old_name) == 0)
2525 return 0;
2528 /* Try to open the dynamic library. */
2529 if (dlname)
2531 /* try to open the installed module */
2532 if (installed && libdir)
2534 if (tryall_dlopen_module (handle,
2535 (const char *) 0, libdir, dlname) == 0)
2536 return 0;
2539 /* try to open the not-installed module */
2540 if (!installed)
2542 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2543 return 0;
2546 /* maybe it was moved to another directory */
2548 if (tryall_dlopen_module (handle,
2549 (const char *) 0, dir, dlname) == 0)
2550 return 0;
2554 return 1;
2558 static int
2559 canonicalize_path (path, pcanonical)
2560 const char *path;
2561 char **pcanonical;
2563 char *canonical = 0;
2565 assert (path && *path);
2566 assert (pcanonical);
2568 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2569 if (!canonical)
2570 return 1;
2573 size_t dest = 0;
2574 size_t src;
2575 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2577 /* Path separators are not copied to the beginning or end of
2578 the destination, or if another separator would follow
2579 immediately. */
2580 if (path[src] == LT_PATHSEP_CHAR)
2582 if ((dest == 0)
2583 || (path[1+ src] == LT_PATHSEP_CHAR)
2584 || (path[1+ src] == LT_EOS_CHAR))
2585 continue;
2588 /* Anything other than a directory separator is copied verbatim. */
2589 if ((path[src] != '/')
2590 #ifdef LT_DIRSEP_CHAR
2591 && (path[src] != LT_DIRSEP_CHAR)
2592 #endif
2595 canonical[dest++] = path[src];
2597 /* Directory separators are converted and copied only if they are
2598 not at the end of a path -- i.e. before a path separator or
2599 NULL terminator. */
2600 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2601 && (path[1+ src] != LT_EOS_CHAR)
2602 #ifdef LT_DIRSEP_CHAR
2603 && (path[1+ src] != LT_DIRSEP_CHAR)
2604 #endif
2605 && (path[1+ src] != '/'))
2607 canonical[dest++] = '/';
2611 /* Add an end-of-string marker at the end. */
2612 canonical[dest] = LT_EOS_CHAR;
2615 /* Assign new value. */
2616 *pcanonical = canonical;
2618 return 0;
2621 static int
2622 argzize_path (path, pargz, pargz_len)
2623 const char *path;
2624 char **pargz;
2625 size_t *pargz_len;
2627 error_t error;
2629 assert (path);
2630 assert (pargz);
2631 assert (pargz_len);
2633 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2635 switch (error)
2637 case ENOMEM:
2638 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2639 break;
2640 default:
2641 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2642 break;
2645 return 1;
2648 return 0;
2651 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2652 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2653 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2654 it is appended to each SEARCH_PATH element before FUNC is called. */
2655 static int
2656 foreach_dirinpath (search_path, base_name, func, data1, data2)
2657 const char *search_path;
2658 const char *base_name;
2659 foreach_callback_func *func;
2660 lt_ptr data1;
2661 lt_ptr data2;
2663 int result = 0;
2664 int filenamesize = 0;
2665 size_t lenbase = LT_STRLEN (base_name);
2666 size_t argz_len = 0;
2667 char *argz = 0;
2668 char *filename = 0;
2669 char *canonical = 0;
2671 LT_DLMUTEX_LOCK ();
2673 if (!search_path || !*search_path)
2675 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2676 goto cleanup;
2679 if (canonicalize_path (search_path, &canonical) != 0)
2680 goto cleanup;
2682 if (argzize_path (canonical, &argz, &argz_len) != 0)
2683 goto cleanup;
2686 char *dir_name = 0;
2687 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2689 size_t lendir = LT_STRLEN (dir_name);
2691 if (lendir +1 +lenbase >= filenamesize)
2693 LT_DLFREE (filename);
2694 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2695 filename = LT_EMALLOC (char, filenamesize);
2696 if (!filename)
2697 goto cleanup;
2700 assert (filenamesize > lendir);
2701 strcpy (filename, dir_name);
2703 if (base_name && *base_name)
2705 if (filename[lendir -1] != '/')
2706 filename[lendir++] = '/';
2707 strcpy (filename +lendir, base_name);
2710 if ((result = (*func) (filename, data1, data2)))
2712 break;
2717 cleanup:
2718 LT_DLFREE (argz);
2719 LT_DLFREE (canonical);
2720 LT_DLFREE (filename);
2722 LT_DLMUTEX_UNLOCK ();
2724 return result;
2727 /* If FILEPATH can be opened, store the name of the directory component
2728 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2729 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2730 static int
2731 find_file_callback (filename, data1, data2)
2732 char *filename;
2733 lt_ptr data1;
2734 lt_ptr data2;
2736 char **pdir = (char **) data1;
2737 FILE **pfile = (FILE **) data2;
2738 int is_done = 0;
2740 assert (filename && *filename);
2741 assert (pdir);
2742 assert (pfile);
2744 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2746 char *dirend = strrchr (filename, '/');
2748 if (dirend > filename)
2749 *dirend = LT_EOS_CHAR;
2751 LT_DLFREE (*pdir);
2752 *pdir = lt_estrdup (filename);
2753 is_done = (*pdir == 0) ? -1 : 1;
2756 return is_done;
2759 static FILE *
2760 find_file (search_path, base_name, pdir)
2761 const char *search_path;
2762 const char *base_name;
2763 char **pdir;
2765 FILE *file = 0;
2767 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2769 return file;
2772 static int
2773 find_handle_callback (filename, data, ignored)
2774 char *filename;
2775 lt_ptr data;
2776 lt_ptr ignored;
2778 lt_dlhandle *handle = (lt_dlhandle *) data;
2779 int notfound = access (filename, R_OK);
2781 /* Bail out if file cannot be read... */
2782 if (notfound)
2783 return 0;
2785 /* Try to dlopen the file, but do not continue searching in any
2786 case. */
2787 if (tryall_dlopen (handle, filename) != 0)
2788 *handle = 0;
2790 return 1;
2793 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2794 found but could not be opened, *HANDLE will be set to 0. */
2795 static lt_dlhandle *
2796 find_handle (search_path, base_name, handle)
2797 const char *search_path;
2798 const char *base_name;
2799 lt_dlhandle *handle;
2801 if (!search_path)
2802 return 0;
2804 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2805 handle, 0))
2806 return 0;
2808 return handle;
2811 static int
2812 load_deplibs (handle, deplibs)
2813 lt_dlhandle handle;
2814 char *deplibs;
2816 #if LTDL_DLOPEN_DEPLIBS
2817 char *p, *save_search_path = 0;
2818 int depcount = 0;
2819 int i;
2820 char **names = 0;
2821 #endif
2822 int errors = 0;
2824 handle->depcount = 0;
2826 #if LTDL_DLOPEN_DEPLIBS
2827 if (!deplibs)
2829 return errors;
2831 ++errors;
2833 LT_DLMUTEX_LOCK ();
2834 if (user_search_path)
2836 save_search_path = lt_estrdup (user_search_path);
2837 if (!save_search_path)
2838 goto cleanup;
2841 /* extract search paths and count deplibs */
2842 p = deplibs;
2843 while (*p)
2845 if (!isspace ((int) *p))
2847 char *end = p+1;
2848 while (*end && !isspace((int) *end))
2850 ++end;
2853 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2855 char save = *end;
2856 *end = 0; /* set a temporary string terminator */
2857 if (lt_dladdsearchdir(p+2))
2859 goto cleanup;
2861 *end = save;
2863 else
2865 ++depcount;
2868 p = end;
2870 else
2872 ++p;
2876 /* restore the old search path */
2877 LT_DLFREE (user_search_path);
2878 user_search_path = save_search_path;
2880 LT_DLMUTEX_UNLOCK ();
2882 if (!depcount)
2884 errors = 0;
2885 goto cleanup;
2888 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2889 if (!names)
2890 goto cleanup;
2892 /* now only extract the actual deplibs */
2893 depcount = 0;
2894 p = deplibs;
2895 while (*p)
2897 if (isspace ((int) *p))
2899 ++p;
2901 else
2903 char *end = p+1;
2904 while (*end && !isspace ((int) *end))
2906 ++end;
2909 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2911 char *name;
2912 char save = *end;
2913 *end = 0; /* set a temporary string terminator */
2914 if (strncmp(p, "-l", 2) == 0)
2916 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2917 name = LT_EMALLOC (char, 1+ name_len);
2918 if (name)
2919 sprintf (name, "lib%s", p+2);
2921 else
2922 name = lt_estrdup(p);
2924 if (!name)
2925 goto cleanup_names;
2927 names[depcount++] = name;
2928 *end = save;
2930 p = end;
2934 /* load the deplibs (in reverse order)
2935 At this stage, don't worry if the deplibs do not load correctly,
2936 they may already be statically linked into the loading application
2937 for instance. There will be a more enlightening error message
2938 later on if the loaded module cannot resolve all of its symbols. */
2939 if (depcount)
2941 int j = 0;
2943 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2944 if (!handle->deplibs)
2945 goto cleanup;
2947 for (i = 0; i < depcount; ++i)
2949 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2950 if (handle->deplibs[j])
2952 ++j;
2956 handle->depcount = j; /* Number of successfully loaded deplibs */
2957 errors = 0;
2960 cleanup_names:
2961 for (i = 0; i < depcount; ++i)
2963 LT_DLFREE (names[i]);
2966 cleanup:
2967 LT_DLFREE (names);
2968 #endif
2970 return errors;
2973 static int
2974 unload_deplibs (handle)
2975 lt_dlhandle handle;
2977 int i;
2978 int errors = 0;
2980 if (handle->depcount)
2982 for (i = 0; i < handle->depcount; ++i)
2984 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2986 errors += lt_dlclose (handle->deplibs[i]);
2991 return errors;
2994 static int
2995 trim (dest, str)
2996 char **dest;
2997 const char *str;
2999 /* remove the leading and trailing "'" from str
3000 and store the result in dest */
3001 const char *end = strrchr (str, '\'');
3002 size_t len = LT_STRLEN (str);
3003 char *tmp;
3005 LT_DLFREE (*dest);
3007 if (!end)
3008 return 1;
3010 if (len > 3 && str[0] == '\'')
3012 tmp = LT_EMALLOC (char, end - str);
3013 if (!tmp)
3014 return 1;
3016 strncpy(tmp, &str[1], (end - str) - 1);
3017 tmp[len-3] = LT_EOS_CHAR;
3018 *dest = tmp;
3020 else
3022 *dest = 0;
3025 return 0;
3028 static int
3029 free_vars (dlname, oldname, libdir, deplibs)
3030 char *dlname;
3031 char *oldname;
3032 char *libdir;
3033 char *deplibs;
3035 LT_DLFREE (dlname);
3036 LT_DLFREE (oldname);
3037 LT_DLFREE (libdir);
3038 LT_DLFREE (deplibs);
3040 return 0;
3043 static int
3044 try_dlopen (phandle, filename)
3045 lt_dlhandle *phandle;
3046 const char *filename;
3048 const char * ext = 0;
3049 const char * saved_error = 0;
3050 char * canonical = 0;
3051 char * base_name = 0;
3052 char * dir = 0;
3053 char * name = 0;
3054 int errors = 0;
3055 lt_dlhandle newhandle;
3057 assert (phandle);
3058 assert (*phandle == 0);
3060 LT_DLMUTEX_GETERROR (saved_error);
3062 /* dlopen self? */
3063 if (!filename)
3065 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3066 if (*phandle == 0)
3067 return 1;
3069 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3070 newhandle = *phandle;
3072 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3073 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3075 if (tryall_dlopen (&newhandle, 0) != 0)
3077 LT_DLFREE (*phandle);
3078 return 1;
3081 goto register_handle;
3084 assert (filename && *filename);
3086 /* Doing this immediately allows internal functions to safely
3087 assume only canonicalized paths are passed. */
3088 if (canonicalize_path (filename, &canonical) != 0)
3090 ++errors;
3091 goto cleanup;
3094 /* If the canonical module name is a path (relative or absolute)
3095 then split it into a directory part and a name part. */
3096 base_name = strrchr (canonical, '/');
3097 if (base_name)
3099 size_t dirlen = (1+ base_name) - canonical;
3101 dir = LT_EMALLOC (char, 1+ dirlen);
3102 if (!dir)
3104 ++errors;
3105 goto cleanup;
3108 strncpy (dir, canonical, dirlen);
3109 dir[dirlen] = LT_EOS_CHAR;
3111 ++base_name;
3113 else
3114 base_name = canonical;
3116 assert (base_name && *base_name);
3118 /* Check whether we are opening a libtool module (.la extension). */
3119 ext = strrchr (base_name, '.');
3120 if (ext && strcmp (ext, archive_ext) == 0)
3122 /* this seems to be a libtool module */
3123 FILE * file = 0;
3124 char * dlname = 0;
3125 char * old_name = 0;
3126 char * libdir = 0;
3127 char * deplibs = 0;
3128 char * line = 0;
3129 size_t line_len;
3131 /* if we can't find the installed flag, it is probably an
3132 installed libtool archive, produced with an old version
3133 of libtool */
3134 int installed = 1;
3136 /* extract the module name from the file name */
3137 name = LT_EMALLOC (char, ext - base_name + 1);
3138 if (!name)
3140 ++errors;
3141 goto cleanup;
3144 /* canonicalize the module name */
3146 size_t i;
3147 for (i = 0; i < ext - base_name; ++i)
3149 if (isalnum ((int)(base_name[i])))
3151 name[i] = base_name[i];
3153 else
3155 name[i] = '_';
3158 name[ext - base_name] = LT_EOS_CHAR;
3161 /* Now try to open the .la file. If there is no directory name
3162 component, try to find it first in user_search_path and then other
3163 prescribed paths. Otherwise (or in any case if the module was not
3164 yet found) try opening just the module name as passed. */
3165 if (!dir)
3167 const char *search_path;
3169 LT_DLMUTEX_LOCK ();
3170 search_path = user_search_path;
3171 if (search_path)
3172 file = find_file (user_search_path, base_name, &dir);
3173 LT_DLMUTEX_UNLOCK ();
3175 if (!file)
3177 search_path = getenv (LTDL_SEARCHPATH_VAR);
3178 if (search_path)
3179 file = find_file (search_path, base_name, &dir);
3182 #ifdef LTDL_SHLIBPATH_VAR
3183 if (!file)
3185 search_path = getenv (LTDL_SHLIBPATH_VAR);
3186 if (search_path)
3187 file = find_file (search_path, base_name, &dir);
3189 #endif
3190 #ifdef LTDL_SYSSEARCHPATH
3191 if (!file && sys_search_path)
3193 file = find_file (sys_search_path, base_name, &dir);
3195 #endif
3197 if (!file)
3199 file = fopen (filename, LT_READTEXT_MODE);
3202 /* If we didn't find the file by now, it really isn't there. Set
3203 the status flag, and bail out. */
3204 if (!file)
3206 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3207 ++errors;
3208 goto cleanup;
3211 line_len = LT_FILENAME_MAX;
3212 line = LT_EMALLOC (char, line_len);
3213 if (!line)
3215 fclose (file);
3216 ++errors;
3217 goto cleanup;
3220 /* read the .la file */
3221 while (!feof (file))
3223 if (!fgets (line, (int) line_len, file))
3225 break;
3228 /* Handle the case where we occasionally need to read a line
3229 that is longer than the initial buffer size. */
3230 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3232 line = LT_DLREALLOC (char, line, line_len *2);
3233 if (!fgets (&line[line_len -1], (int) line_len +1, file))
3235 break;
3237 line_len *= 2;
3240 if (line[0] == '\n' || line[0] == '#')
3242 continue;
3245 #undef STR_DLNAME
3246 #define STR_DLNAME "dlname="
3247 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3249 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3252 #undef STR_OLD_LIBRARY
3253 #define STR_OLD_LIBRARY "old_library="
3254 else if (strncmp (line, STR_OLD_LIBRARY,
3255 sizeof (STR_OLD_LIBRARY) - 1) == 0)
3257 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3259 #undef STR_LIBDIR
3260 #define STR_LIBDIR "libdir="
3261 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3263 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3266 #undef STR_DL_DEPLIBS
3267 #define STR_DL_DEPLIBS "dependency_libs="
3268 else if (strncmp (line, STR_DL_DEPLIBS,
3269 sizeof (STR_DL_DEPLIBS) - 1) == 0)
3271 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3273 else if (strcmp (line, "installed=yes\n") == 0)
3275 installed = 1;
3277 else if (strcmp (line, "installed=no\n") == 0)
3279 installed = 0;
3282 #undef STR_LIBRARY_NAMES
3283 #define STR_LIBRARY_NAMES "library_names="
3284 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3285 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3287 char *last_libname;
3288 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3289 if (!errors
3290 && dlname
3291 && (last_libname = strrchr (dlname, ' ')) != 0)
3293 last_libname = lt_estrdup (last_libname + 1);
3294 if (!last_libname)
3296 ++errors;
3297 goto cleanup;
3299 LT_DLMEM_REASSIGN (dlname, last_libname);
3303 if (errors)
3304 break;
3307 fclose (file);
3308 LT_DLFREE (line);
3310 /* allocate the handle */
3311 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3312 if (*phandle == 0)
3313 ++errors;
3315 if (errors)
3317 free_vars (dlname, old_name, libdir, deplibs);
3318 LT_DLFREE (*phandle);
3319 goto cleanup;
3322 assert (*phandle);
3324 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3325 if (load_deplibs (*phandle, deplibs) == 0)
3327 newhandle = *phandle;
3328 /* find_module may replace newhandle */
3329 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3331 unload_deplibs (*phandle);
3332 ++errors;
3335 else
3337 ++errors;
3340 free_vars (dlname, old_name, libdir, deplibs);
3341 if (errors)
3343 LT_DLFREE (*phandle);
3344 goto cleanup;
3347 if (*phandle != newhandle)
3349 unload_deplibs (*phandle);
3352 else
3354 /* not a libtool module */
3355 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3356 if (*phandle == 0)
3358 ++errors;
3359 goto cleanup;
3362 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3363 newhandle = *phandle;
3365 /* If the module has no directory name component, try to find it
3366 first in user_search_path and then other prescribed paths.
3367 Otherwise (or in any case if the module was not yet found) try
3368 opening just the module name as passed. */
3369 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3370 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3371 &newhandle)
3372 #ifdef LTDL_SHLIBPATH_VAR
3373 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3374 &newhandle)
3375 #endif
3376 #ifdef LTDL_SYSSEARCHPATH
3377 && !find_handle (sys_search_path, base_name, &newhandle)
3378 #endif
3381 if (tryall_dlopen (&newhandle, filename) != 0)
3383 newhandle = NULL;
3387 if (!newhandle)
3389 LT_DLFREE (*phandle);
3390 ++errors;
3391 goto cleanup;
3395 register_handle:
3396 LT_DLMEM_REASSIGN (*phandle, newhandle);
3398 if ((*phandle)->info.ref_count == 0)
3400 (*phandle)->info.ref_count = 1;
3401 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3403 LT_DLMUTEX_LOCK ();
3404 (*phandle)->next = handles;
3405 handles = *phandle;
3406 LT_DLMUTEX_UNLOCK ();
3409 LT_DLMUTEX_SETERROR (saved_error);
3411 cleanup:
3412 LT_DLFREE (dir);
3413 LT_DLFREE (name);
3414 LT_DLFREE (canonical);
3416 return errors;
3419 lt_dlhandle
3420 lt_dlopen (filename)
3421 const char *filename;
3423 lt_dlhandle handle = 0;
3425 /* Just incase we missed a code path in try_dlopen() that reports
3426 an error, but forgets to reset handle... */
3427 if (try_dlopen (&handle, filename) != 0)
3428 return 0;
3430 return handle;
3433 /* If the last error messge store was `FILE_NOT_FOUND', then return
3434 non-zero. */
3435 static int
3436 file_not_found ()
3438 const char *error = 0;
3440 LT_DLMUTEX_GETERROR (error);
3441 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3442 return 1;
3444 return 0;
3447 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3448 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3449 and if a file is still not found try again with SHLIB_EXT appended
3450 instead. */
3451 lt_dlhandle
3452 lt_dlopenext (filename)
3453 const char *filename;
3455 lt_dlhandle handle = 0;
3456 char * tmp = 0;
3457 char * ext = 0;
3458 size_t len;
3459 int errors = 0;
3461 if (!filename)
3463 return lt_dlopen (filename);
3466 assert (filename);
3468 len = LT_STRLEN (filename);
3469 ext = strrchr (filename, '.');
3471 /* If FILENAME already bears a suitable extension, there is no need
3472 to try appending additional extensions. */
3473 if (ext && ((strcmp (ext, archive_ext) == 0)
3474 #ifdef LTDL_SHLIB_EXT
3475 || (strcmp (ext, shlib_ext) == 0)
3476 #endif
3479 return lt_dlopen (filename);
3482 /* First try appending ARCHIVE_EXT. */
3483 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3484 if (!tmp)
3485 return 0;
3487 strcpy (tmp, filename);
3488 strcat (tmp, archive_ext);
3489 errors = try_dlopen (&handle, tmp);
3491 /* If we found FILENAME, stop searching -- whether we were able to
3492 load the file as a module or not. If the file exists but loading
3493 failed, it is better to return an error message here than to
3494 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3495 in the module search path. */
3496 if (handle || ((errors > 0) && !file_not_found ()))
3498 LT_DLFREE (tmp);
3499 return handle;
3502 #ifdef LTDL_SHLIB_EXT
3503 /* Try appending SHLIB_EXT. */
3504 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3506 LT_DLFREE (tmp);
3507 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3508 if (!tmp)
3509 return 0;
3511 strcpy (tmp, filename);
3513 else
3515 tmp[len] = LT_EOS_CHAR;
3518 strcat(tmp, shlib_ext);
3519 errors = try_dlopen (&handle, tmp);
3521 /* As before, if the file was found but loading failed, return now
3522 with the current error message. */
3523 if (handle || ((errors > 0) && !file_not_found ()))
3525 LT_DLFREE (tmp);
3526 return handle;
3528 #endif
3530 /* Still here? Then we really did fail to locate any of the file
3531 names we tried. */
3532 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3533 LT_DLFREE (tmp);
3534 return 0;
3538 static int
3539 lt_argz_insert (pargz, pargz_len, before, entry)
3540 char **pargz;
3541 size_t *pargz_len;
3542 char *before;
3543 const char *entry;
3545 error_t error;
3547 if ((error = argz_insert (pargz, pargz_len, before, entry)))
3549 switch (error)
3551 case ENOMEM:
3552 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3553 break;
3554 default:
3555 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3556 break;
3558 return 1;
3561 return 0;
3564 static int
3565 lt_argz_insertinorder (pargz, pargz_len, entry)
3566 char **pargz;
3567 size_t *pargz_len;
3568 const char *entry;
3570 char *before = 0;
3572 assert (pargz);
3573 assert (pargz_len);
3574 assert (entry && *entry);
3576 if (*pargz)
3577 while ((before = argz_next (*pargz, *pargz_len, before)))
3579 int cmp = strcmp (entry, before);
3581 if (cmp < 0) break;
3582 if (cmp == 0) return 0; /* No duplicates! */
3585 return lt_argz_insert (pargz, pargz_len, before, entry);
3588 static int
3589 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3590 char **pargz;
3591 size_t *pargz_len;
3592 const char *dirnam;
3593 struct dirent *dp;
3595 char *buf = 0;
3596 size_t buf_len = 0;
3597 char *end = 0;
3598 size_t end_offset = 0;
3599 size_t dir_len = 0;
3600 int errors = 0;
3602 assert (pargz);
3603 assert (pargz_len);
3604 assert (dp);
3606 dir_len = LT_STRLEN (dirnam);
3607 end = dp->d_name + LT_D_NAMLEN(dp);
3609 /* Ignore version numbers. */
3611 char *p;
3612 for (p = end; p -1 > dp->d_name; --p)
3613 if (strchr (".0123456789", p[-1]) == 0)
3614 break;
3616 if (*p == '.')
3617 end = p;
3620 /* Ignore filename extension. */
3622 char *p;
3623 for (p = end -1; p > dp->d_name; --p)
3624 if (*p == '.')
3626 end = p;
3627 break;
3631 /* Prepend the directory name. */
3632 end_offset = end - dp->d_name;
3633 buf_len = dir_len + 1+ end_offset;
3634 buf = LT_EMALLOC (char, 1+ buf_len);
3635 if (!buf)
3636 return ++errors;
3638 assert (buf);
3640 strcpy (buf, dirnam);
3641 strcat (buf, "/");
3642 strncat (buf, dp->d_name, end_offset);
3643 buf[buf_len] = LT_EOS_CHAR;
3645 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3646 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3647 ++errors;
3649 LT_DLFREE (buf);
3651 return errors;
3654 static int
3655 list_files_by_dir (dirnam, pargz, pargz_len)
3656 const char *dirnam;
3657 char **pargz;
3658 size_t *pargz_len;
3660 DIR *dirp = 0;
3661 int errors = 0;
3663 assert (dirnam && *dirnam);
3664 assert (pargz);
3665 assert (pargz_len);
3666 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3668 dirp = opendir (dirnam);
3669 if (dirp)
3671 struct dirent *dp = 0;
3673 while ((dp = readdir (dirp)))
3674 if (dp->d_name[0] != '.')
3675 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3677 ++errors;
3678 break;
3681 closedir (dirp);
3683 else
3684 ++errors;
3686 return errors;
3690 /* If there are any files in DIRNAME, call the function passed in
3691 DATA1 (with the name of each file and DATA2 as arguments). */
3692 static int
3693 foreachfile_callback (dirname, data1, data2)
3694 char *dirname;
3695 lt_ptr data1;
3696 lt_ptr data2;
3698 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3699 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3701 int is_done = 0;
3702 char *argz = 0;
3703 size_t argz_len = 0;
3705 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3706 goto cleanup;
3707 if (!argz)
3708 goto cleanup;
3711 char *filename = 0;
3712 while ((filename = argz_next (argz, argz_len, filename)))
3713 if ((is_done = (*func) (filename, data2)))
3714 break;
3717 cleanup:
3718 LT_DLFREE (argz);
3720 return is_done;
3724 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3725 with DATA. The filenames passed to FUNC would be suitable for
3726 passing to lt_dlopenext. The extensions are stripped so that
3727 individual modules do not generate several entries (e.g. libfoo.la,
3728 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3729 then the same directories that lt_dlopen would search are examined. */
3731 lt_dlforeachfile (search_path, func, data)
3732 const char *search_path;
3733 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3734 lt_ptr data;
3736 int is_done = 0;
3738 if (search_path)
3740 /* If a specific path was passed, search only the directories
3741 listed in it. */
3742 is_done = foreach_dirinpath (search_path, 0,
3743 foreachfile_callback, func, data);
3745 else
3747 /* Otherwise search the default paths. */
3748 is_done = foreach_dirinpath (user_search_path, 0,
3749 foreachfile_callback, func, data);
3750 if (!is_done)
3752 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3753 foreachfile_callback, func, data);
3756 #ifdef LTDL_SHLIBPATH_VAR
3757 if (!is_done)
3759 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3760 foreachfile_callback, func, data);
3762 #endif
3763 #ifdef LTDL_SYSSEARCHPATH
3764 if (!is_done)
3766 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3767 foreachfile_callback, func, data);
3769 #endif
3772 return is_done;
3776 lt_dlclose (handle)
3777 lt_dlhandle handle;
3779 lt_dlhandle cur, last;
3780 int errors = 0;
3782 LT_DLMUTEX_LOCK ();
3784 /* check whether the handle is valid */
3785 last = cur = handles;
3786 while (cur && handle != cur)
3788 last = cur;
3789 cur = cur->next;
3792 if (!cur)
3794 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3795 ++errors;
3796 goto done;
3799 handle->info.ref_count--;
3801 /* Note that even with resident modules, we must track the ref_count
3802 correctly incase the user decides to reset the residency flag
3803 later (even though the API makes no provision for that at the
3804 moment). */
3805 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3807 lt_user_data data = handle->loader->dlloader_data;
3809 if (handle != handles)
3811 last->next = handle->next;
3813 else
3815 handles = handle->next;
3818 errors += handle->loader->module_close (data, handle->module);
3819 errors += unload_deplibs(handle);
3821 /* It is up to the callers to free the data itself. */
3822 LT_DLFREE (handle->caller_data);
3824 LT_DLFREE (handle->info.filename);
3825 LT_DLFREE (handle->info.name);
3826 LT_DLFREE (handle);
3828 goto done;
3831 if (LT_DLIS_RESIDENT (handle))
3833 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3834 ++errors;
3837 done:
3838 LT_DLMUTEX_UNLOCK ();
3840 return errors;
3843 lt_ptr
3844 lt_dlsym (handle, symbol)
3845 lt_dlhandle handle;
3846 const char *symbol;
3848 size_t lensym;
3849 char lsym[LT_SYMBOL_LENGTH];
3850 char *sym;
3851 lt_ptr address;
3852 lt_user_data data;
3854 if (!handle)
3856 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3857 return 0;
3860 if (!symbol)
3862 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3863 return 0;
3866 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3867 + LT_STRLEN (handle->info.name);
3869 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3871 sym = lsym;
3873 else
3875 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3876 if (!sym)
3878 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3879 return 0;
3883 data = handle->loader->dlloader_data;
3884 if (handle->info.name)
3886 const char *saved_error;
3888 LT_DLMUTEX_GETERROR (saved_error);
3890 /* this is a libtool module */
3891 if (handle->loader->sym_prefix)
3893 strcpy(sym, handle->loader->sym_prefix);
3894 strcat(sym, handle->info.name);
3896 else
3898 strcpy(sym, handle->info.name);
3901 strcat(sym, "_LTX_");
3902 strcat(sym, symbol);
3904 /* try "modulename_LTX_symbol" */
3905 address = handle->loader->find_sym (data, handle->module, sym);
3906 if (address)
3908 if (sym != lsym)
3910 LT_DLFREE (sym);
3912 return address;
3914 LT_DLMUTEX_SETERROR (saved_error);
3917 /* otherwise try "symbol" */
3918 if (handle->loader->sym_prefix)
3920 strcpy(sym, handle->loader->sym_prefix);
3921 strcat(sym, symbol);
3923 else
3925 strcpy(sym, symbol);
3928 address = handle->loader->find_sym (data, handle->module, sym);
3929 if (sym != lsym)
3931 LT_DLFREE (sym);
3934 return address;
3937 const char *
3938 lt_dlerror ()
3940 const char *error;
3942 LT_DLMUTEX_GETERROR (error);
3943 LT_DLMUTEX_SETERROR (0);
3945 return error ? error : NULL;
3948 static int
3949 lt_dlpath_insertdir (ppath, before, dir)
3950 char **ppath;
3951 char *before;
3952 const char *dir;
3954 int errors = 0;
3955 char *canonical = 0;
3956 char *argz = 0;
3957 size_t argz_len = 0;
3959 assert (ppath);
3960 assert (dir && *dir);
3962 if (canonicalize_path (dir, &canonical) != 0)
3964 ++errors;
3965 goto cleanup;
3968 assert (canonical && *canonical);
3970 /* If *PPATH is empty, set it to DIR. */
3971 if (*ppath == 0)
3973 assert (!before); /* BEFORE cannot be set without PPATH. */
3974 assert (dir); /* Without DIR, don't call this function! */
3976 *ppath = lt_estrdup (dir);
3977 if (*ppath == 0)
3978 ++errors;
3980 return errors;
3983 assert (ppath && *ppath);
3985 if (argzize_path (*ppath, &argz, &argz_len) != 0)
3987 ++errors;
3988 goto cleanup;
3991 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
3992 if *PPATH is already canonicalized, and hence does not change length
3993 with respect to ARGZ. We canonicalize each entry as it is added to
3994 the search path, and don't call this function with (uncanonicalized)
3995 user paths, so this is a fair assumption. */
3996 if (before)
3998 assert (*ppath <= before);
3999 assert (before - *ppath <= strlen (*ppath));
4001 before = before - *ppath + argz;
4004 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
4006 ++errors;
4007 goto cleanup;
4010 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
4011 LT_DLMEM_REASSIGN (*ppath, argz);
4013 cleanup:
4014 LT_DLFREE (canonical);
4015 LT_DLFREE (argz);
4017 return errors;
4021 lt_dladdsearchdir (search_dir)
4022 const char *search_dir;
4024 int errors = 0;
4026 if (search_dir && *search_dir)
4028 LT_DLMUTEX_LOCK ();
4029 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4030 ++errors;
4031 LT_DLMUTEX_UNLOCK ();
4034 return errors;
4038 lt_dlinsertsearchdir (before, search_dir)
4039 const char *before;
4040 const char *search_dir;
4042 int errors = 0;
4044 if (before)
4046 LT_DLMUTEX_LOCK ();
4047 if ((before < user_search_path)
4048 || (before >= user_search_path + LT_STRLEN (user_search_path)))
4050 LT_DLMUTEX_UNLOCK ();
4051 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4052 return 1;
4054 LT_DLMUTEX_UNLOCK ();
4057 if (search_dir && *search_dir)
4059 LT_DLMUTEX_LOCK ();
4060 if (lt_dlpath_insertdir (&user_search_path,
4061 (char *) before, search_dir) != 0)
4063 ++errors;
4065 LT_DLMUTEX_UNLOCK ();
4068 return errors;
4072 lt_dlsetsearchpath (search_path)
4073 const char *search_path;
4075 int errors = 0;
4077 LT_DLMUTEX_LOCK ();
4078 LT_DLFREE (user_search_path);
4079 LT_DLMUTEX_UNLOCK ();
4081 if (!search_path || !LT_STRLEN (search_path))
4083 return errors;
4086 LT_DLMUTEX_LOCK ();
4087 if (canonicalize_path (search_path, &user_search_path) != 0)
4088 ++errors;
4089 LT_DLMUTEX_UNLOCK ();
4091 return errors;
4094 const char *
4095 lt_dlgetsearchpath ()
4097 const char *saved_path;
4099 LT_DLMUTEX_LOCK ();
4100 saved_path = user_search_path;
4101 LT_DLMUTEX_UNLOCK ();
4103 return saved_path;
4107 lt_dlmakeresident (handle)
4108 lt_dlhandle handle;
4110 int errors = 0;
4112 if (!handle)
4114 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4115 ++errors;
4117 else
4119 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4122 return errors;
4126 lt_dlisresident (handle)
4127 lt_dlhandle handle;
4129 if (!handle)
4131 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4132 return -1;
4135 return LT_DLIS_RESIDENT (handle);
4141 /* --- MODULE INFORMATION --- */
4143 const lt_dlinfo *
4144 lt_dlgetinfo (handle)
4145 lt_dlhandle handle;
4147 if (!handle)
4149 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4150 return 0;
4153 return &(handle->info);
4156 lt_dlhandle
4157 lt_dlhandle_next (place)
4158 lt_dlhandle place;
4160 return place ? place->next : handles;
4164 lt_dlforeach (func, data)
4165 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4166 lt_ptr data;
4168 int errors = 0;
4169 lt_dlhandle cur;
4171 LT_DLMUTEX_LOCK ();
4173 cur = handles;
4174 while (cur)
4176 lt_dlhandle tmp = cur;
4178 cur = cur->next;
4179 if ((*func) (tmp, data))
4181 ++errors;
4182 break;
4186 LT_DLMUTEX_UNLOCK ();
4188 return errors;
4191 lt_dlcaller_id
4192 lt_dlcaller_register ()
4194 static lt_dlcaller_id last_caller_id = 0;
4195 int result;
4197 LT_DLMUTEX_LOCK ();
4198 result = ++last_caller_id;
4199 LT_DLMUTEX_UNLOCK ();
4201 return result;
4204 lt_ptr
4205 lt_dlcaller_set_data (key, handle, data)
4206 lt_dlcaller_id key;
4207 lt_dlhandle handle;
4208 lt_ptr data;
4210 int n_elements = 0;
4211 lt_ptr stale = (lt_ptr) 0;
4212 int i;
4214 /* This needs to be locked so that the caller data can be updated
4215 simultaneously by different threads. */
4216 LT_DLMUTEX_LOCK ();
4218 if (handle->caller_data)
4219 while (handle->caller_data[n_elements].key)
4220 ++n_elements;
4222 for (i = 0; i < n_elements; ++i)
4224 if (handle->caller_data[i].key == key)
4226 stale = handle->caller_data[i].data;
4227 break;
4231 /* Ensure that there is enough room in this handle's caller_data
4232 array to accept a new element (and an empty end marker). */
4233 if (i == n_elements)
4235 lt_caller_data *temp
4236 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4238 if (!temp)
4240 stale = 0;
4241 goto done;
4244 handle->caller_data = temp;
4246 /* We only need this if we needed to allocate a new caller_data. */
4247 handle->caller_data[i].key = key;
4248 handle->caller_data[1+ i].key = 0;
4251 handle->caller_data[i].data = data;
4253 done:
4254 LT_DLMUTEX_UNLOCK ();
4256 return stale;
4259 lt_ptr
4260 lt_dlcaller_get_data (key, handle)
4261 lt_dlcaller_id key;
4262 lt_dlhandle handle;
4264 lt_ptr result = (lt_ptr) 0;
4266 /* This needs to be locked so that the caller data isn't updated by
4267 another thread part way through this function. */
4268 LT_DLMUTEX_LOCK ();
4270 /* Locate the index of the element with a matching KEY. */
4272 int i;
4273 for (i = 0; handle->caller_data[i].key; ++i)
4275 if (handle->caller_data[i].key == key)
4277 result = handle->caller_data[i].data;
4278 break;
4283 LT_DLMUTEX_UNLOCK ();
4285 return result;
4290 /* --- USER MODULE LOADER API --- */
4294 lt_dlloader_add (place, dlloader, loader_name)
4295 lt_dlloader *place;
4296 const struct lt_user_dlloader *dlloader;
4297 const char *loader_name;
4299 int errors = 0;
4300 lt_dlloader *node = 0, *ptr = 0;
4302 if ((dlloader == 0) /* diagnose null parameters */
4303 || (dlloader->module_open == 0)
4304 || (dlloader->module_close == 0)
4305 || (dlloader->find_sym == 0))
4307 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4308 return 1;
4311 /* Create a new dlloader node with copies of the user callbacks. */
4312 node = LT_EMALLOC (lt_dlloader, 1);
4313 if (!node)
4314 return 1;
4316 node->next = 0;
4317 node->loader_name = loader_name;
4318 node->sym_prefix = dlloader->sym_prefix;
4319 node->dlloader_exit = dlloader->dlloader_exit;
4320 node->module_open = dlloader->module_open;
4321 node->module_close = dlloader->module_close;
4322 node->find_sym = dlloader->find_sym;
4323 node->dlloader_data = dlloader->dlloader_data;
4325 LT_DLMUTEX_LOCK ();
4326 if (!loaders)
4328 /* If there are no loaders, NODE becomes the list! */
4329 loaders = node;
4331 else if (!place)
4333 /* If PLACE is not set, add NODE to the end of the
4334 LOADERS list. */
4335 for (ptr = loaders; ptr->next; ptr = ptr->next)
4337 /*NOWORK*/;
4340 ptr->next = node;
4342 else if (loaders == place)
4344 /* If PLACE is the first loader, NODE goes first. */
4345 node->next = place;
4346 loaders = node;
4348 else
4350 /* Find the node immediately preceding PLACE. */
4351 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4353 /*NOWORK*/;
4356 if (ptr->next != place)
4358 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4359 ++errors;
4361 else
4363 /* Insert NODE between PTR and PLACE. */
4364 node->next = place;
4365 ptr->next = node;
4369 LT_DLMUTEX_UNLOCK ();
4371 return errors;
4375 lt_dlloader_remove (loader_name)
4376 const char *loader_name;
4378 lt_dlloader *place = lt_dlloader_find (loader_name);
4379 lt_dlhandle handle;
4380 int errors = 0;
4382 if (!place)
4384 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4385 return 1;
4388 LT_DLMUTEX_LOCK ();
4390 /* Fail if there are any open modules which use this loader. */
4391 for (handle = handles; handle; handle = handle->next)
4393 if (handle->loader == place)
4395 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4396 ++errors;
4397 goto done;
4401 if (place == loaders)
4403 /* PLACE is the first loader in the list. */
4404 loaders = loaders->next;
4406 else
4408 /* Find the loader before the one being removed. */
4409 lt_dlloader *prev;
4410 for (prev = loaders; prev->next; prev = prev->next)
4412 if (!strcmp (prev->next->loader_name, loader_name))
4414 break;
4418 place = prev->next;
4419 prev->next = prev->next->next;
4422 if (place->dlloader_exit)
4424 errors = place->dlloader_exit (place->dlloader_data);
4427 LT_DLFREE (place);
4429 done:
4430 LT_DLMUTEX_UNLOCK ();
4432 return errors;
4435 lt_dlloader *
4436 lt_dlloader_next (place)
4437 lt_dlloader *place;
4439 lt_dlloader *next;
4441 LT_DLMUTEX_LOCK ();
4442 next = place ? place->next : loaders;
4443 LT_DLMUTEX_UNLOCK ();
4445 return next;
4448 const char *
4449 lt_dlloader_name (place)
4450 lt_dlloader *place;
4452 const char *name = 0;
4454 if (place)
4456 LT_DLMUTEX_LOCK ();
4457 name = place ? place->loader_name : 0;
4458 LT_DLMUTEX_UNLOCK ();
4460 else
4462 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4465 return name;
4468 lt_user_data *
4469 lt_dlloader_data (place)
4470 lt_dlloader *place;
4472 lt_user_data *data = 0;
4474 if (place)
4476 LT_DLMUTEX_LOCK ();
4477 data = place ? &(place->dlloader_data) : 0;
4478 LT_DLMUTEX_UNLOCK ();
4480 else
4482 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4485 return data;
4488 lt_dlloader *
4489 lt_dlloader_find (loader_name)
4490 const char *loader_name;
4492 lt_dlloader *place = 0;
4494 LT_DLMUTEX_LOCK ();
4495 for (place = loaders; place; place = place->next)
4497 if (strcmp (place->loader_name, loader_name) == 0)
4499 break;
4502 LT_DLMUTEX_UNLOCK ();
4504 return place;