Build libtool from source.
[msysgit.git] / share / libtool / libltdl / ltdl.c
blobbd88414df5384ca1591db00a7c7f25c7017e8f62
1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 2007 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_UNISTD_H
33 # include <unistd.h>
34 #endif
36 #if HAVE_STDIO_H
37 # include <stdio.h>
38 #endif
40 /* Include the header defining malloc. On K&R C compilers,
41 that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */
42 #if HAVE_STDLIB_H
43 # include <stdlib.h>
44 #else
45 # if HAVE_MALLOC_H
46 # include <malloc.h>
47 # endif
48 #endif
50 #if HAVE_STRING_H
51 # include <string.h>
52 #else
53 # if HAVE_STRINGS_H
54 # include <strings.h>
55 # endif
56 #endif
58 #if HAVE_CTYPE_H
59 # include <ctype.h>
60 #endif
62 #if HAVE_MEMORY_H
63 # include <memory.h>
64 #endif
66 #if HAVE_ERRNO_H
67 # include <errno.h>
68 #endif
71 #ifndef __WINDOWS__
72 # ifdef __WIN32__
73 # define __WINDOWS__
74 # endif
75 #endif
78 #undef LT_USE_POSIX_DIRENT
79 #ifdef HAVE_CLOSEDIR
80 # ifdef HAVE_OPENDIR
81 # ifdef HAVE_READDIR
82 # ifdef HAVE_DIRENT_H
83 # define LT_USE_POSIX_DIRENT
84 # endif /* HAVE_DIRENT_H */
85 # endif /* HAVE_READDIR */
86 # endif /* HAVE_OPENDIR */
87 #endif /* HAVE_CLOSEDIR */
90 #undef LT_USE_WINDOWS_DIRENT_EMULATION
91 #ifndef LT_USE_POSIX_DIRENT
92 # ifdef __WINDOWS__
93 # define LT_USE_WINDOWS_DIRENT_EMULATION
94 # endif /* __WINDOWS__ */
95 #endif /* LT_USE_POSIX_DIRENT */
98 #ifdef LT_USE_POSIX_DIRENT
99 # include <dirent.h>
100 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
101 #else
102 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
103 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
104 # else
105 # define dirent direct
106 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
107 # if HAVE_SYS_NDIR_H
108 # include <sys/ndir.h>
109 # endif
110 # if HAVE_SYS_DIR_H
111 # include <sys/dir.h>
112 # endif
113 # if HAVE_NDIR_H
114 # include <ndir.h>
115 # endif
116 # endif
117 #endif
119 #if HAVE_ARGZ_H
120 # include <argz.h>
121 #endif
123 #if HAVE_ASSERT_H
124 # include <assert.h>
125 #else
126 # define assert(arg) ((void) 0)
127 #endif
129 #include "ltdl.h"
131 #if WITH_DMALLOC
132 # include <dmalloc.h>
133 #endif
138 /* --- WINDOWS SUPPORT --- */
140 /* DLL building support on win32 hosts; mostly to workaround their
141 ridiculous implementation of data symbol exporting. */
142 #ifndef LT_GLOBAL_DATA
143 # if defined(__WINDOWS__) || defined(__CYGWIN__)
144 # ifdef DLL_EXPORT /* defined by libtool (if required) */
145 # define LT_GLOBAL_DATA __declspec(dllexport)
146 # endif
147 # endif
148 # ifndef LT_GLOBAL_DATA /* static linking or !__WINDOWS__ */
149 # define LT_GLOBAL_DATA
150 # endif
151 #endif
153 /* fopen() mode flags for reading a text file */
154 #undef LT_READTEXT_MODE
155 #if defined(__WINDOWS__) || defined(__CYGWIN__)
156 # define LT_READTEXT_MODE "rt"
157 #else
158 # define LT_READTEXT_MODE "r"
159 #endif
161 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
163 #include <windows.h>
165 #define dirent lt_dirent
166 #define DIR lt_DIR
168 struct dirent
170 char d_name[2048];
171 int d_namlen;
174 typedef struct _DIR
176 HANDLE hSearch;
177 WIN32_FIND_DATA Win32FindData;
178 BOOL firsttime;
179 struct dirent file_info;
180 } DIR;
182 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
185 /* --- MANIFEST CONSTANTS --- */
188 /* Standard libltdl search path environment variable name */
189 #undef LTDL_SEARCHPATH_VAR
190 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
192 /* Standard libtool archive file extension. */
193 #undef LTDL_ARCHIVE_EXT
194 #define LTDL_ARCHIVE_EXT ".la"
196 /* max. filename length */
197 #ifndef LT_FILENAME_MAX
198 # define LT_FILENAME_MAX 1024
199 #endif
201 /* This is the maximum symbol size that won't require malloc/free */
202 #undef LT_SYMBOL_LENGTH
203 #define LT_SYMBOL_LENGTH 128
205 /* This accounts for the _LTX_ separator */
206 #undef LT_SYMBOL_OVERHEAD
207 #define LT_SYMBOL_OVERHEAD 5
212 /* --- MEMORY HANDLING --- */
215 /* These are the functions used internally. In addition to making
216 use of the associated function pointers above, they also perform
217 error handling. */
218 static char *lt_estrdup LT_PARAMS((const char *str));
219 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
220 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
222 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
223 #define rpl_realloc realloc
225 /* These are the pointers that can be changed by the caller: */
226 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
227 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
228 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
229 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
230 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
231 = (void (*) LT_PARAMS((lt_ptr))) free;
233 /* The following macros reduce the amount of typing needed to cast
234 assigned memory. */
235 #if WITH_DMALLOC
237 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
238 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
239 #define LT_DLFREE(p) \
240 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
242 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
243 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
245 #else
247 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
248 #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
249 #define LT_DLFREE(p) \
250 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
252 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
253 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
255 #endif
257 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
258 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
259 } LT_STMT_END
262 /* --- REPLACEMENT FUNCTIONS --- */
265 #undef strdup
266 #define strdup rpl_strdup
268 static char *strdup LT_PARAMS((const char *str));
270 static char *
271 strdup(str)
272 const char *str;
274 char *tmp = 0;
276 if (str)
278 tmp = LT_DLMALLOC (char, 1+ strlen (str));
279 if (tmp)
281 strcpy(tmp, str);
285 return tmp;
289 #if ! HAVE_STRCMP
291 #undef strcmp
292 #define strcmp rpl_strcmp
294 static int strcmp LT_PARAMS((const char *str1, const char *str2));
296 static int
297 strcmp (str1, str2)
298 const char *str1;
299 const char *str2;
301 if (str1 == str2)
302 return 0;
303 if (str1 == 0)
304 return -1;
305 if (str2 == 0)
306 return 1;
308 for (;*str1 && *str2; ++str1, ++str2)
310 if (*str1 != *str2)
311 break;
314 return (int)(*str1 - *str2);
316 #endif
319 #if ! HAVE_STRCHR
321 # if HAVE_INDEX
322 # define strchr index
323 # else
324 # define strchr rpl_strchr
326 static const char *strchr LT_PARAMS((const char *str, int ch));
328 static const char*
329 strchr(str, ch)
330 const char *str;
331 int ch;
333 const char *p;
335 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
336 /*NOWORK*/;
338 return (*p == (char)ch) ? p : 0;
341 # endif
342 #endif /* !HAVE_STRCHR */
345 #if ! HAVE_STRRCHR
347 # if HAVE_RINDEX
348 # define strrchr rindex
349 # else
350 # define strrchr rpl_strrchr
352 static const char *strrchr LT_PARAMS((const char *str, int ch));
354 static const char*
355 strrchr(str, ch)
356 const char *str;
357 int ch;
359 const char *p, *q = 0;
361 for (p = str; *p != LT_EOS_CHAR; ++p)
363 if (*p == (char) ch)
365 q = p;
369 return q;
372 # endif
373 #endif
375 /* NOTE: Neither bcopy nor the memcpy implementation below can
376 reliably handle copying in overlapping areas of memory. Use
377 memmove (for which there is a fallback implmentation below)
378 if you need that behaviour. */
379 #if ! HAVE_MEMCPY
381 # if HAVE_BCOPY
382 # define memcpy(dest, src, size) bcopy (src, dest, size)
383 # else
384 # define memcpy rpl_memcpy
386 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
388 static lt_ptr
389 memcpy (dest, src, size)
390 lt_ptr dest;
391 const lt_ptr src;
392 size_t size;
394 const char * s = src;
395 char * d = dest;
396 size_t i = 0;
398 for (i = 0; i < size; ++i)
400 d[i] = s[i];
403 return dest;
406 # endif /* !HAVE_BCOPY */
407 #endif /* !HAVE_MEMCPY */
409 #if ! HAVE_MEMMOVE
410 # define memmove rpl_memmove
412 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
414 static lt_ptr
415 memmove (dest, src, size)
416 lt_ptr dest;
417 const lt_ptr src;
418 size_t size;
420 const char * s = src;
421 char * d = dest;
422 size_t i;
424 if (d < s)
425 for (i = 0; i < size; ++i)
427 d[i] = s[i];
429 else if (d > s && size > 0)
430 for (i = size -1; ; --i)
432 d[i] = s[i];
433 if (i == 0)
434 break;
437 return dest;
440 #endif /* !HAVE_MEMMOVE */
442 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
444 static void closedir LT_PARAMS((DIR *entry));
446 static void
447 closedir(entry)
448 DIR *entry;
450 assert(entry != (DIR *) NULL);
451 FindClose(entry->hSearch);
452 lt_dlfree((lt_ptr)entry);
456 static DIR * opendir LT_PARAMS((const char *path));
458 static DIR*
459 opendir (path)
460 const char *path;
462 char file_specification[LT_FILENAME_MAX];
463 DIR *entry;
465 assert(path != (char *) NULL);
466 /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
467 (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
468 file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
469 (void) strcat(file_specification,"\\");
470 entry = LT_DLMALLOC (DIR,sizeof(DIR));
471 if (entry != (DIR *) 0)
473 entry->firsttime = TRUE;
474 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
476 if (entry->hSearch == INVALID_HANDLE_VALUE)
478 (void) strcat(file_specification,"\\*.*");
479 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
480 if (entry->hSearch == INVALID_HANDLE_VALUE)
482 LT_DLFREE (entry);
483 return (DIR *) 0;
486 return(entry);
490 static struct dirent *readdir LT_PARAMS((DIR *entry));
492 static struct dirent *readdir(entry)
493 DIR *entry;
496 status;
498 if (entry == (DIR *) 0)
499 return((struct dirent *) 0);
500 if (!entry->firsttime)
502 status = FindNextFile(entry->hSearch,&entry->Win32FindData);
503 if (status == 0)
504 return((struct dirent *) 0);
506 entry->firsttime = FALSE;
507 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
508 LT_FILENAME_MAX-1);
509 entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
510 entry->file_info.d_namlen = strlen(entry->file_info.d_name);
511 return(&entry->file_info);
514 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
516 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
517 ``realloc is not entirely portable''
518 In any case we want to use the allocator supplied by the user without
519 burdening them with an lt_dlrealloc function pointer to maintain.
520 Instead implement our own version (with known boundary conditions)
521 using lt_dlmalloc and lt_dlfree. */
523 /* #undef realloc
524 #define realloc rpl_realloc
526 #if 0
527 /* You can't (re)define realloc unless you also (re)define malloc.
528 Right now, this code uses the size of the *destination* to decide
529 how much to copy. That's not right, but you can't know the size
530 of the source unless you know enough about, or wrote malloc. So
531 this code is disabled... */
533 static lt_ptr
534 realloc (ptr, size)
535 lt_ptr ptr;
536 size_t size;
538 if (size == 0)
540 /* For zero or less bytes, free the original memory */
541 if (ptr != 0)
543 lt_dlfree (ptr);
546 return (lt_ptr) 0;
548 else if (ptr == 0)
550 /* Allow reallocation of a NULL pointer. */
551 return lt_dlmalloc (size);
553 else
555 /* Allocate a new block, copy and free the old block. */
556 lt_ptr mem = lt_dlmalloc (size);
558 if (mem)
560 memcpy (mem, ptr, size);
561 lt_dlfree (ptr);
564 /* Note that the contents of PTR are not damaged if there is
565 insufficient memory to realloc. */
566 return mem;
569 #endif
572 #if ! HAVE_ARGZ_APPEND
573 # define argz_append rpl_argz_append
575 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
576 const char *buf, size_t buf_len));
578 static error_t
579 argz_append (pargz, pargz_len, buf, buf_len)
580 char **pargz;
581 size_t *pargz_len;
582 const char *buf;
583 size_t buf_len;
585 size_t argz_len;
586 char *argz;
588 assert (pargz);
589 assert (pargz_len);
590 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
592 /* If nothing needs to be appended, no more work is required. */
593 if (buf_len == 0)
594 return 0;
596 /* Ensure there is enough room to append BUF_LEN. */
597 argz_len = *pargz_len + buf_len;
598 argz = LT_DLREALLOC (char, *pargz, argz_len);
599 if (!argz)
600 return ENOMEM;
602 /* Copy characters from BUF after terminating '\0' in ARGZ. */
603 memcpy (argz + *pargz_len, buf, buf_len);
605 /* Assign new values. */
606 *pargz = argz;
607 *pargz_len = argz_len;
609 return 0;
611 #endif /* !HAVE_ARGZ_APPEND */
614 #if ! HAVE_ARGZ_CREATE_SEP
615 # define argz_create_sep rpl_argz_create_sep
617 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
618 char **pargz, size_t *pargz_len));
620 static error_t
621 argz_create_sep (str, delim, pargz, pargz_len)
622 const char *str;
623 int delim;
624 char **pargz;
625 size_t *pargz_len;
627 size_t argz_len;
628 char *argz = 0;
630 assert (str);
631 assert (pargz);
632 assert (pargz_len);
634 /* Make a copy of STR, but replacing each occurrence of
635 DELIM with '\0'. */
636 argz_len = 1+ LT_STRLEN (str);
637 if (argz_len)
639 const char *p;
640 char *q;
642 argz = LT_DLMALLOC (char, argz_len);
643 if (!argz)
644 return ENOMEM;
646 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
648 if (*p == delim)
650 /* Ignore leading delimiters, and fold consecutive
651 delimiters in STR into a single '\0' in ARGZ. */
652 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
653 *q++ = LT_EOS_CHAR;
654 else
655 --argz_len;
657 else
658 *q++ = *p;
660 /* Copy terminating LT_EOS_CHAR. */
661 *q = *p;
664 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
665 if (!argz_len)
666 LT_DLFREE (argz);
668 /* Assign new values. */
669 *pargz = argz;
670 *pargz_len = argz_len;
672 return 0;
674 #endif /* !HAVE_ARGZ_CREATE_SEP */
677 #if ! HAVE_ARGZ_INSERT
678 # define argz_insert rpl_argz_insert
680 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
681 char *before, const char *entry));
683 static error_t
684 argz_insert (pargz, pargz_len, before, entry)
685 char **pargz;
686 size_t *pargz_len;
687 char *before;
688 const char *entry;
690 assert (pargz);
691 assert (pargz_len);
692 assert (entry && *entry);
694 /* No BEFORE address indicates ENTRY should be inserted after the
695 current last element. */
696 if (!before)
697 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
699 /* This probably indicates a programmer error, but to preserve
700 semantics, scan back to the start of an entry if BEFORE points
701 into the middle of it. */
702 while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
703 --before;
706 size_t entry_len = 1+ LT_STRLEN (entry);
707 size_t argz_len = *pargz_len + entry_len;
708 size_t offset = before - *pargz;
709 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
711 if (!argz)
712 return ENOMEM;
714 /* Make BEFORE point to the equivalent offset in ARGZ that it
715 used to have in *PARGZ incase realloc() moved the block. */
716 before = argz + offset;
718 /* Move the ARGZ entries starting at BEFORE up into the new
719 space at the end -- making room to copy ENTRY into the
720 resulting gap. */
721 memmove (before + entry_len, before, *pargz_len - offset);
722 memcpy (before, entry, entry_len);
724 /* Assign new values. */
725 *pargz = argz;
726 *pargz_len = argz_len;
729 return 0;
731 #endif /* !HAVE_ARGZ_INSERT */
734 #if ! HAVE_ARGZ_NEXT
735 # define argz_next rpl_argz_next
737 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
738 const char *entry));
740 static char *
741 argz_next (argz, argz_len, entry)
742 char *argz;
743 size_t argz_len;
744 const char *entry;
746 assert ((argz && argz_len) || (!argz && !argz_len));
748 if (entry)
750 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
751 within the ARGZ vector. */
752 assert ((!argz && !argz_len)
753 || ((argz <= entry) && (entry < (argz + argz_len))));
755 /* Move to the char immediately after the terminating
756 '\0' of ENTRY. */
757 entry = 1+ strchr (entry, LT_EOS_CHAR);
759 /* Return either the new ENTRY, or else NULL if ARGZ is
760 exhausted. */
761 return (entry >= argz + argz_len) ? 0 : (char *) entry;
763 else
765 /* This should probably be flagged as a programmer error,
766 since starting an argz_next loop with the iterator set
767 to ARGZ is safer. To preserve semantics, handle the NULL
768 case by returning the start of ARGZ (if any). */
769 if (argz_len > 0)
770 return argz;
771 else
772 return 0;
775 #endif /* !HAVE_ARGZ_NEXT */
779 #if ! HAVE_ARGZ_STRINGIFY
780 # define argz_stringify rpl_argz_stringify
782 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
783 int sep));
785 static void
786 argz_stringify (argz, argz_len, sep)
787 char *argz;
788 size_t argz_len;
789 int sep;
791 assert ((argz && argz_len) || (!argz && !argz_len));
793 if (sep)
795 --argz_len; /* don't stringify the terminating EOS */
796 while (--argz_len > 0)
798 if (argz[argz_len] == LT_EOS_CHAR)
799 argz[argz_len] = sep;
803 #endif /* !HAVE_ARGZ_STRINGIFY */
808 /* --- TYPE DEFINITIONS -- */
811 /* This type is used for the array of caller data sets in each handler. */
812 typedef struct {
813 lt_dlcaller_id key;
814 lt_ptr data;
815 } lt_caller_data;
820 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
823 /* Extract the diagnostic strings from the error table macro in the same
824 order as the enumerated indices in ltdl.h. */
826 static const char *lt_dlerror_strings[] =
828 #define LT_ERROR(name, diagnostic) (diagnostic),
829 lt_dlerror_table
830 #undef LT_ERROR
835 /* This structure is used for the list of registered loaders. */
836 struct lt_dlloader {
837 struct lt_dlloader *next;
838 const char *loader_name; /* identifying name for each loader */
839 const char *sym_prefix; /* prefix for symbols */
840 lt_module_open *module_open;
841 lt_module_close *module_close;
842 lt_find_sym *find_sym;
843 lt_dlloader_exit *dlloader_exit;
844 lt_user_data dlloader_data;
847 struct lt_dlhandle_struct {
848 struct lt_dlhandle_struct *next;
849 lt_dlloader *loader; /* dlopening interface */
850 lt_dlinfo info;
851 int depcount; /* number of dependencies */
852 lt_dlhandle *deplibs; /* dependencies */
853 lt_module module; /* system module handle */
854 lt_ptr system; /* system specific data */
855 lt_caller_data *caller_data; /* per caller associated data */
856 int flags; /* various boolean stats */
859 /* Various boolean flags can be stored in the flags field of an
860 lt_dlhandle_struct... */
861 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
862 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
864 #define LT_DLRESIDENT_FLAG (0x01 << 0)
865 /* ...add more flags here... */
867 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
870 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
872 static const char objdir[] = LTDL_OBJDIR;
873 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
874 #ifdef LTDL_SHLIB_EXT
875 static const char shlib_ext[] = LTDL_SHLIB_EXT;
876 #endif
877 #ifdef LTDL_SYSSEARCHPATH
878 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
879 #endif
884 /* --- MUTEX LOCKING --- */
887 /* Macros to make it easier to run the lock functions only if they have
888 been registered. The reason for the complicated lock macro is to
889 ensure that the stored error message from the last error is not
890 accidentally erased if the current function doesn't generate an
891 error of its own. */
892 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
893 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
894 } LT_STMT_END
895 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
896 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
897 } LT_STMT_END
898 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
899 if (lt_dlmutex_seterror_func) \
900 (*lt_dlmutex_seterror_func) (errormsg); \
901 else lt_dllast_error = (errormsg); } LT_STMT_END
902 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
903 if (lt_dlmutex_geterror_func) \
904 (errormsg) = (*lt_dlmutex_geterror_func) (); \
905 else (errormsg) = lt_dllast_error; } LT_STMT_END
907 /* The mutex functions stored here are global, and are necessarily the
908 same for all threads that wish to share access to libltdl. */
909 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
910 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
911 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
912 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
913 static const char *lt_dllast_error = 0;
916 /* Either set or reset the mutex functions. Either all the arguments must
917 be valid functions, or else all can be NULL to turn off locking entirely.
918 The registered functions should be manipulating a static global lock
919 from the lock() and unlock() callbacks, which needs to be reentrant. */
921 lt_dlmutex_register (lock, unlock, seterror, geterror)
922 lt_dlmutex_lock *lock;
923 lt_dlmutex_unlock *unlock;
924 lt_dlmutex_seterror *seterror;
925 lt_dlmutex_geterror *geterror;
927 lt_dlmutex_unlock *old_unlock = lt_dlmutex_unlock_func;
928 int errors = 0;
930 /* Lock using the old lock() callback, if any. */
931 LT_DLMUTEX_LOCK ();
933 if ((lock && unlock && seterror && geterror)
934 || !(lock || unlock || seterror || geterror))
936 lt_dlmutex_lock_func = lock;
937 lt_dlmutex_unlock_func = unlock;
938 lt_dlmutex_seterror_func = seterror;
939 lt_dlmutex_geterror_func = geterror;
941 else
943 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
944 ++errors;
947 /* Use the old unlock() callback we saved earlier, if any. Otherwise
948 record any errors using internal storage. */
949 if (old_unlock)
950 (*old_unlock) ();
952 /* Return the number of errors encountered during the execution of
953 this function. */
954 return errors;
960 /* --- ERROR HANDLING --- */
963 static const char **user_error_strings = 0;
964 static int errorcount = LT_ERROR_MAX;
967 lt_dladderror (diagnostic)
968 const char *diagnostic;
970 int errindex = 0;
971 int result = -1;
972 const char **temp = (const char **) 0;
974 assert (diagnostic);
976 LT_DLMUTEX_LOCK ();
978 errindex = errorcount - LT_ERROR_MAX;
979 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
980 if (temp)
982 user_error_strings = temp;
983 user_error_strings[errindex] = diagnostic;
984 result = errorcount++;
987 LT_DLMUTEX_UNLOCK ();
989 return result;
993 lt_dlseterror (errindex)
994 int errindex;
996 int errors = 0;
998 LT_DLMUTEX_LOCK ();
1000 if (errindex >= errorcount || errindex < 0)
1002 /* Ack! Error setting the error message! */
1003 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
1004 ++errors;
1006 else if (errindex < LT_ERROR_MAX)
1008 /* No error setting the error message! */
1009 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
1011 else
1013 /* No error setting the error message! */
1014 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
1017 LT_DLMUTEX_UNLOCK ();
1019 return errors;
1022 static lt_ptr
1023 lt_emalloc (size)
1024 size_t size;
1026 lt_ptr mem = lt_dlmalloc (size);
1027 if (size && !mem)
1028 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1029 return mem;
1032 static lt_ptr
1033 lt_erealloc (addr, size)
1034 lt_ptr addr;
1035 size_t size;
1037 lt_ptr mem = lt_dlrealloc (addr, size);
1038 if (size && !mem)
1039 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1040 return mem;
1043 static char *
1044 lt_estrdup (str)
1045 const char *str;
1047 char *copy = strdup (str);
1048 if (LT_STRLEN (str) && !copy)
1049 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1050 return copy;
1056 /* --- DLOPEN() INTERFACE LOADER --- */
1059 #if HAVE_LIBDL
1061 /* dynamic linking with dlopen/dlsym */
1063 #if HAVE_DLFCN_H
1064 # include <dlfcn.h>
1065 #endif
1067 #if HAVE_SYS_DL_H
1068 # include <sys/dl.h>
1069 #endif
1071 #ifdef RTLD_GLOBAL
1072 # define LT_GLOBAL RTLD_GLOBAL
1073 #else
1074 # ifdef DL_GLOBAL
1075 # define LT_GLOBAL DL_GLOBAL
1076 # endif
1077 #endif /* !RTLD_GLOBAL */
1078 #ifndef LT_GLOBAL
1079 # define LT_GLOBAL 0
1080 #endif /* !LT_GLOBAL */
1082 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1083 find out it does not work in some platform. */
1084 #ifndef LT_LAZY_OR_NOW
1085 # ifdef RTLD_LAZY
1086 # define LT_LAZY_OR_NOW RTLD_LAZY
1087 # else
1088 # ifdef DL_LAZY
1089 # define LT_LAZY_OR_NOW DL_LAZY
1090 # endif
1091 # endif /* !RTLD_LAZY */
1092 #endif
1093 #ifndef LT_LAZY_OR_NOW
1094 # ifdef RTLD_NOW
1095 # define LT_LAZY_OR_NOW RTLD_NOW
1096 # else
1097 # ifdef DL_NOW
1098 # define LT_LAZY_OR_NOW DL_NOW
1099 # endif
1100 # endif /* !RTLD_NOW */
1101 #endif
1102 #ifndef LT_LAZY_OR_NOW
1103 # define LT_LAZY_OR_NOW 0
1104 #endif /* !LT_LAZY_OR_NOW */
1106 #if HAVE_DLERROR
1107 # define DLERROR(arg) dlerror ()
1108 #else
1109 # define DLERROR(arg) LT_DLSTRERROR (arg)
1110 #endif
1112 static lt_module
1113 sys_dl_open (loader_data, filename)
1114 lt_user_data loader_data;
1115 const char *filename;
1117 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1119 if (!module)
1121 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1124 return module;
1127 static int
1128 sys_dl_close (loader_data, module)
1129 lt_user_data loader_data;
1130 lt_module module;
1132 int errors = 0;
1134 if (dlclose (module) != 0)
1136 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1137 ++errors;
1140 return errors;
1143 static lt_ptr
1144 sys_dl_sym (loader_data, module, symbol)
1145 lt_user_data loader_data;
1146 lt_module module;
1147 const char *symbol;
1149 lt_ptr address = dlsym (module, symbol);
1151 if (!address)
1153 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1156 return address;
1159 static struct lt_user_dlloader sys_dl =
1161 # ifdef NEED_USCORE
1162 "_",
1163 # else
1165 # endif
1166 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1169 #endif /* HAVE_LIBDL */
1173 /* --- SHL_LOAD() INTERFACE LOADER --- */
1175 #if HAVE_SHL_LOAD
1177 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1179 #ifdef HAVE_DL_H
1180 # include <dl.h>
1181 #endif
1183 /* some flags are missing on some systems, so we provide
1184 * harmless defaults.
1186 * Mandatory:
1187 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1188 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1190 * Optionally:
1191 * BIND_FIRST - Place the library at the head of the symbol search
1192 * order.
1193 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1194 * unsatisfied symbols as fatal. This flag allows
1195 * binding of unsatisfied code symbols to be deferred
1196 * until use.
1197 * [Perl: For certain libraries, like DCE, deferred
1198 * binding often causes run time problems. Adding
1199 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1200 * unresolved references in situations like this.]
1201 * BIND_NOSTART - Do not call the initializer for the shared library
1202 * when the library is loaded, nor on a future call to
1203 * shl_unload().
1204 * BIND_VERBOSE - Print verbose messages concerning possible
1205 * unsatisfied symbols.
1207 * hp9000s700/hp9000s800:
1208 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1209 * present at library load time.
1210 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1211 * library specified by the path argument.
1214 #ifndef DYNAMIC_PATH
1215 # define DYNAMIC_PATH 0
1216 #endif
1217 #ifndef BIND_RESTRICTED
1218 # define BIND_RESTRICTED 0
1219 #endif
1221 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1223 static lt_module
1224 sys_shl_open (loader_data, filename)
1225 lt_user_data loader_data;
1226 const char *filename;
1228 static shl_t self = (shl_t) 0;
1229 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1231 /* Since searching for a symbol against a NULL module handle will also
1232 look in everything else that was already loaded and exported with
1233 the -E compiler flag, we always cache a handle saved before any
1234 modules are loaded. */
1235 if (!self)
1237 lt_ptr address;
1238 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1241 if (!filename)
1243 module = self;
1245 else
1247 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1249 if (!module)
1251 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1255 return module;
1258 static int
1259 sys_shl_close (loader_data, module)
1260 lt_user_data loader_data;
1261 lt_module module;
1263 int errors = 0;
1265 if (module && (shl_unload ((shl_t) (module)) != 0))
1267 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1268 ++errors;
1271 return errors;
1274 static lt_ptr
1275 sys_shl_sym (loader_data, module, symbol)
1276 lt_user_data loader_data;
1277 lt_module module;
1278 const char *symbol;
1280 lt_ptr address = 0;
1282 /* sys_shl_open should never return a NULL module handle */
1283 if (module == (lt_module) 0)
1285 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1287 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1289 if (!address)
1291 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1295 return address;
1298 static struct lt_user_dlloader sys_shl = {
1299 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1302 #endif /* HAVE_SHL_LOAD */
1307 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1309 #ifdef __WINDOWS__
1311 /* dynamic linking for Win32 */
1313 #include <windows.h>
1315 /* Forward declaration; required to implement handle search below. */
1316 static lt_dlhandle handles;
1318 static lt_module
1319 sys_wll_open (loader_data, filename)
1320 lt_user_data loader_data;
1321 const char *filename;
1323 lt_dlhandle cur;
1324 lt_module module = 0;
1325 const char *errormsg = 0;
1326 char *searchname = 0;
1327 char *ext;
1328 char self_name_buf[MAX_PATH];
1330 if (!filename)
1332 /* Get the name of main module */
1333 *self_name_buf = 0;
1334 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1335 filename = ext = self_name_buf;
1337 else
1339 ext = strrchr (filename, '.');
1342 if (ext)
1344 /* FILENAME already has an extension. */
1345 searchname = lt_estrdup (filename);
1347 else
1349 /* Append a `.' to stop Windows from adding an
1350 implicit `.dll' extension. */
1351 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1352 if (searchname)
1353 sprintf (searchname, "%s.", filename);
1355 if (!searchname)
1356 return 0;
1359 /* Silence dialog from LoadLibrary on some failures.
1360 No way to get the error mode, but to set it,
1361 so set it twice to preserve any previous flags. */
1362 UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
1363 SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
1365 #if defined(__CYGWIN__)
1367 char wpath[MAX_PATH];
1368 cygwin_conv_to_full_win32_path (searchname, wpath);
1369 module = LoadLibrary (wpath);
1371 #else
1372 module = LoadLibrary (searchname);
1373 #endif
1375 /* Restore the error mode. */
1376 SetErrorMode(errormode);
1379 LT_DLFREE (searchname);
1381 /* libltdl expects this function to fail if it is unable
1382 to physically load the library. Sadly, LoadLibrary
1383 will search the loaded libraries for a match and return
1384 one of them if the path search load fails.
1386 We check whether LoadLibrary is returning a handle to
1387 an already loaded module, and simulate failure if we
1388 find one. */
1389 LT_DLMUTEX_LOCK ();
1390 cur = handles;
1391 while (cur)
1393 if (!cur->module)
1395 cur = 0;
1396 break;
1399 if (cur->module == module)
1401 break;
1404 cur = cur->next;
1406 LT_DLMUTEX_UNLOCK ();
1408 if (cur || !module)
1410 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1411 module = 0;
1414 return module;
1417 static int
1418 sys_wll_close (loader_data, module)
1419 lt_user_data loader_data;
1420 lt_module module;
1422 int errors = 0;
1424 if (FreeLibrary(module) == 0)
1426 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1427 ++errors;
1430 return errors;
1433 static lt_ptr
1434 sys_wll_sym (loader_data, module, symbol)
1435 lt_user_data loader_data;
1436 lt_module module;
1437 const char *symbol;
1439 lt_ptr address = GetProcAddress (module, symbol);
1441 if (!address)
1443 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1446 return address;
1449 static struct lt_user_dlloader sys_wll = {
1450 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1453 #endif /* __WINDOWS__ */
1458 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1461 #ifdef __BEOS__
1463 /* dynamic linking for BeOS */
1465 #include <kernel/image.h>
1467 static lt_module
1468 sys_bedl_open (loader_data, filename)
1469 lt_user_data loader_data;
1470 const char *filename;
1472 image_id image = 0;
1474 if (filename)
1476 image = load_add_on (filename);
1478 else
1480 image_info info;
1481 int32 cookie = 0;
1482 if (get_next_image_info (0, &cookie, &info) == B_OK)
1483 image = load_add_on (info.name);
1486 if (image <= 0)
1488 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1489 image = 0;
1492 return (lt_module) image;
1495 static int
1496 sys_bedl_close (loader_data, module)
1497 lt_user_data loader_data;
1498 lt_module module;
1500 int errors = 0;
1502 if (unload_add_on ((image_id) module) != B_OK)
1504 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1505 ++errors;
1508 return errors;
1511 static lt_ptr
1512 sys_bedl_sym (loader_data, module, symbol)
1513 lt_user_data loader_data;
1514 lt_module module;
1515 const char *symbol;
1517 lt_ptr address = 0;
1518 image_id image = (image_id) module;
1520 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1522 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1523 address = 0;
1526 return address;
1529 static struct lt_user_dlloader sys_bedl = {
1530 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1533 #endif /* __BEOS__ */
1538 /* --- DLD_LINK() INTERFACE LOADER --- */
1541 #if HAVE_DLD
1543 /* dynamic linking with dld */
1545 #if HAVE_DLD_H
1546 #include <dld.h>
1547 #endif
1549 static lt_module
1550 sys_dld_open (loader_data, filename)
1551 lt_user_data loader_data;
1552 const char *filename;
1554 lt_module module = strdup (filename);
1556 if (dld_link (filename) != 0)
1558 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1559 LT_DLFREE (module);
1560 module = 0;
1563 return module;
1566 static int
1567 sys_dld_close (loader_data, module)
1568 lt_user_data loader_data;
1569 lt_module module;
1571 int errors = 0;
1573 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1575 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1576 ++errors;
1578 else
1580 LT_DLFREE (module);
1583 return errors;
1586 static lt_ptr
1587 sys_dld_sym (loader_data, module, symbol)
1588 lt_user_data loader_data;
1589 lt_module module;
1590 const char *symbol;
1592 lt_ptr address = dld_get_func (symbol);
1594 if (!address)
1596 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1599 return address;
1602 static struct lt_user_dlloader sys_dld = {
1603 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1606 #endif /* HAVE_DLD */
1608 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1609 #if HAVE_DYLD
1612 #if HAVE_MACH_O_DYLD_H
1613 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1614 /* Is this correct? Does it still function properly? */
1615 #define __private_extern__ extern
1616 #endif
1617 # include <mach-o/dyld.h>
1618 #endif
1619 #include <mach-o/getsect.h>
1621 /* We have to put some stuff here that isn't in older dyld.h files */
1622 #ifndef ENUM_DYLD_BOOL
1623 # define ENUM_DYLD_BOOL
1624 # undef FALSE
1625 # undef TRUE
1626 enum DYLD_BOOL {
1627 FALSE,
1628 TRUE
1630 #endif
1631 #ifndef LC_REQ_DYLD
1632 # define LC_REQ_DYLD 0x80000000
1633 #endif
1634 #ifndef LC_LOAD_WEAK_DYLIB
1635 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1636 #endif
1637 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1638 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1639 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1640 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1642 #ifndef NSADDIMAGE_OPTION_NONE
1643 #define NSADDIMAGE_OPTION_NONE 0x0
1644 #endif
1645 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1646 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1647 #endif
1648 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1649 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1650 #endif
1651 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1652 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1653 #endif
1654 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1655 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1656 #endif
1657 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1658 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1659 #endif
1660 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1661 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1662 #endif
1663 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1664 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1665 #endif
1666 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1667 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1668 #endif
1671 static const char *
1672 lt_int_dyld_error(othererror)
1673 char* othererror;
1675 /* return the dyld error string, or the passed in error string if none */
1676 NSLinkEditErrors ler;
1677 int lerno;
1678 const char *errstr;
1679 const char *file;
1680 NSLinkEditError(&ler,&lerno,&file,&errstr);
1681 if (!errstr || !strlen(errstr)) errstr = othererror;
1682 return errstr;
1685 static const struct mach_header *
1686 lt_int_dyld_get_mach_header_from_nsmodule(module)
1687 NSModule module;
1689 /* There should probably be an apple dyld api for this */
1690 int i=_dyld_image_count();
1691 int j;
1692 const char *modname=NSNameOfModule(module);
1693 const struct mach_header *mh=NULL;
1694 if (!modname) return NULL;
1695 for (j = 0; j < i; j++)
1697 if (!strcmp(_dyld_get_image_name(j),modname))
1699 mh=_dyld_get_image_header(j);
1700 break;
1703 return mh;
1706 static const char* lt_int_dyld_lib_install_name(mh)
1707 const struct mach_header *mh;
1709 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1710 is installed, for uninstalled libs we need to check the install_names against
1711 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1712 different lib was loaded as a result
1714 int j;
1715 struct load_command *lc;
1716 unsigned long offset = sizeof(struct mach_header);
1717 const char* retStr=NULL;
1718 for (j = 0; j < mh->ncmds; j++)
1720 lc = (struct load_command*)(((unsigned long)mh) + offset);
1721 if (LC_ID_DYLIB == lc->cmd)
1723 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1724 (unsigned long)lc);
1726 offset += lc->cmdsize;
1728 return retStr;
1731 static const struct mach_header *
1732 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1734 int i=_dyld_image_count();
1735 int j;
1736 const struct mach_header *mh=NULL;
1737 const char *id=NULL;
1738 for (j = 0; j < i; j++)
1740 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1741 if ((id) && (!strcmp(id,name)))
1743 mh=_dyld_get_image_header(j);
1744 break;
1747 return mh;
1750 static NSSymbol
1751 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1752 const char *symbol;
1753 const struct mach_header *mh;
1755 /* Safe to assume our mh is good */
1756 int j;
1757 struct load_command *lc;
1758 unsigned long offset = sizeof(struct mach_header);
1759 NSSymbol retSym = 0;
1760 const struct mach_header *mh1;
1761 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1763 for (j = 0; j < mh->ncmds; j++)
1765 lc = (struct load_command*)(((unsigned long)mh) + offset);
1766 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1768 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1769 (unsigned long)lc));
1770 if (!mh1)
1772 /* Maybe NSAddImage can find it */
1773 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1774 (unsigned long)lc),
1775 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1776 NSADDIMAGE_OPTION_WITH_SEARCHING +
1777 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1779 if (mh1)
1781 retSym = ltdl_NSLookupSymbolInImage(mh1,
1782 symbol,
1783 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1784 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1786 if (retSym) break;
1789 offset += lc->cmdsize;
1792 return retSym;
1795 static int
1796 sys_dyld_init()
1798 int retCode = 0;
1799 int err = 0;
1800 if (!_dyld_present()) {
1801 retCode=1;
1803 else {
1804 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1805 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1806 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1807 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1809 return retCode;
1812 static lt_module
1813 sys_dyld_open (loader_data, filename)
1814 lt_user_data loader_data;
1815 const char *filename;
1817 lt_module module = 0;
1818 NSObjectFileImage ofi = 0;
1819 NSObjectFileImageReturnCode ofirc;
1821 if (!filename)
1822 return (lt_module)-1;
1823 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1824 switch (ofirc)
1826 case NSObjectFileImageSuccess:
1827 module = NSLinkModule(ofi, filename,
1828 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1829 | NSLINKMODULE_OPTION_PRIVATE
1830 | NSLINKMODULE_OPTION_BINDNOW);
1831 NSDestroyObjectFileImage(ofi);
1832 if (module)
1833 ltdl_NSMakePrivateModulePublic(module);
1834 break;
1835 case NSObjectFileImageInappropriateFile:
1836 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1838 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1839 break;
1841 default:
1842 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1843 return 0;
1845 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1846 return module;
1849 static int
1850 sys_dyld_close (loader_data, module)
1851 lt_user_data loader_data;
1852 lt_module module;
1854 int retCode = 0;
1855 int flags = 0;
1856 if (module == (lt_module)-1) return 0;
1857 #ifdef __BIG_ENDIAN__
1858 if (((struct mach_header *)module)->magic == MH_MAGIC)
1859 #else
1860 if (((struct mach_header *)module)->magic == MH_CIGAM)
1861 #endif
1863 LT_DLMUTEX_SETERROR("Can not close a dylib");
1864 retCode = 1;
1866 else
1868 #if 1
1869 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1870 get a segfault in atexit(), due to compiler and dynamic loader differences of
1871 opinion, this works around that.
1873 if ((const struct section *)NULL !=
1874 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1875 "__DATA","__mod_term_func"))
1877 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1879 #endif
1880 #ifdef __ppc__
1881 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1882 #endif
1883 if (!NSUnLinkModule(module,flags))
1885 retCode=1;
1886 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1890 return retCode;
1893 static lt_ptr
1894 sys_dyld_sym (loader_data, module, symbol)
1895 lt_user_data loader_data;
1896 lt_module module;
1897 const char *symbol;
1899 lt_ptr address = 0;
1900 NSSymbol *nssym = 0;
1901 void *unused;
1902 const struct mach_header *mh=NULL;
1903 char saveError[256] = "Symbol not found";
1904 if (module == (lt_module)-1)
1906 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1907 return address;
1909 #ifdef __BIG_ENDIAN__
1910 if (((struct mach_header *)module)->magic == MH_MAGIC)
1911 #else
1912 if (((struct mach_header *)module)->magic == MH_CIGAM)
1913 #endif
1915 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1917 mh=module;
1918 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1920 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1921 symbol,
1922 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1923 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1929 else {
1930 nssym = NSLookupSymbolInModule(module, symbol);
1932 if (!nssym)
1934 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1935 saveError[255] = 0;
1936 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1937 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1939 if (!nssym)
1941 LT_DLMUTEX_SETERROR (saveError);
1942 return NULL;
1944 return NSAddressOfSymbol(nssym);
1947 static struct lt_user_dlloader sys_dyld =
1948 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1951 #endif /* HAVE_DYLD */
1954 /* --- DLPREOPEN() INTERFACE LOADER --- */
1957 /* emulate dynamic linking using preloaded_symbols */
1959 typedef struct lt_dlsymlists_t
1961 struct lt_dlsymlists_t *next;
1962 const lt_dlsymlist *syms;
1963 } lt_dlsymlists_t;
1965 static const lt_dlsymlist *default_preloaded_symbols = 0;
1966 static lt_dlsymlists_t *preloaded_symbols = 0;
1968 static int
1969 presym_init (loader_data)
1970 lt_user_data loader_data;
1972 int errors = 0;
1974 LT_DLMUTEX_LOCK ();
1976 preloaded_symbols = 0;
1977 if (default_preloaded_symbols)
1979 errors = lt_dlpreload (default_preloaded_symbols);
1982 LT_DLMUTEX_UNLOCK ();
1984 return errors;
1987 static int
1988 presym_free_symlists ()
1990 lt_dlsymlists_t *lists;
1992 LT_DLMUTEX_LOCK ();
1994 lists = preloaded_symbols;
1995 while (lists)
1997 lt_dlsymlists_t *tmp = lists;
1999 lists = lists->next;
2000 LT_DLFREE (tmp);
2002 preloaded_symbols = 0;
2004 LT_DLMUTEX_UNLOCK ();
2006 return 0;
2009 static int
2010 presym_exit (loader_data)
2011 lt_user_data loader_data;
2013 presym_free_symlists ();
2014 return 0;
2017 static int
2018 presym_add_symlist (preloaded)
2019 const lt_dlsymlist *preloaded;
2021 lt_dlsymlists_t *tmp;
2022 lt_dlsymlists_t *lists;
2023 int errors = 0;
2025 LT_DLMUTEX_LOCK ();
2027 lists = preloaded_symbols;
2028 while (lists)
2030 if (lists->syms == preloaded)
2032 goto done;
2034 lists = lists->next;
2037 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2038 if (tmp)
2040 memset (tmp, 0, sizeof(lt_dlsymlists_t));
2041 tmp->syms = preloaded;
2042 tmp->next = preloaded_symbols;
2043 preloaded_symbols = tmp;
2045 else
2047 ++errors;
2050 done:
2051 LT_DLMUTEX_UNLOCK ();
2052 return errors;
2055 static lt_module
2056 presym_open (loader_data, filename)
2057 lt_user_data loader_data;
2058 const char *filename;
2060 lt_dlsymlists_t *lists;
2061 lt_module module = (lt_module) 0;
2063 LT_DLMUTEX_LOCK ();
2064 lists = preloaded_symbols;
2066 if (!lists)
2068 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2069 goto done;
2072 /* Can't use NULL as the reflective symbol header, as NULL is
2073 used to mark the end of the entire symbol list. Self-dlpreopened
2074 symbols follow this magic number, chosen to be an unlikely
2075 clash with a real module name. */
2076 if (!filename)
2078 filename = "@PROGRAM@";
2081 while (lists)
2083 const lt_dlsymlist *syms = lists->syms;
2085 while (syms->name)
2087 if (!syms->address && strcmp(syms->name, filename) == 0)
2089 module = (lt_module) syms;
2090 goto done;
2092 ++syms;
2095 lists = lists->next;
2098 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2100 done:
2101 LT_DLMUTEX_UNLOCK ();
2102 return module;
2105 static int
2106 presym_close (loader_data, module)
2107 lt_user_data loader_data;
2108 lt_module module;
2110 /* Just to silence gcc -Wall */
2111 module = 0;
2112 return 0;
2115 static lt_ptr
2116 presym_sym (loader_data, module, symbol)
2117 lt_user_data loader_data;
2118 lt_module module;
2119 const char *symbol;
2121 lt_dlsymlist *syms = (lt_dlsymlist*) module;
2123 ++syms;
2124 while (syms->address)
2126 if (strcmp(syms->name, symbol) == 0)
2128 return syms->address;
2131 ++syms;
2134 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2136 return 0;
2139 static struct lt_user_dlloader presym = {
2140 0, presym_open, presym_close, presym_sym, presym_exit, 0
2147 /* --- DYNAMIC MODULE LOADING --- */
2150 /* The type of a function used at each iteration of foreach_dirinpath(). */
2151 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2152 lt_ptr data2));
2154 static int foreach_dirinpath LT_PARAMS((const char *search_path,
2155 const char *base_name,
2156 foreach_callback_func *func,
2157 lt_ptr data1, lt_ptr data2));
2159 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2160 lt_ptr ignored));
2161 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2162 lt_ptr ignored));
2163 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2164 lt_ptr data2));
2167 static int canonicalize_path LT_PARAMS((const char *path,
2168 char **pcanonical));
2169 static int argzize_path LT_PARAMS((const char *path,
2170 char **pargz,
2171 size_t *pargz_len));
2172 static FILE *find_file LT_PARAMS((const char *search_path,
2173 const char *base_name,
2174 char **pdir));
2175 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2176 const char *base_name,
2177 lt_dlhandle *handle));
2178 static int find_module LT_PARAMS((lt_dlhandle *handle,
2179 const char *dir,
2180 const char *libdir,
2181 const char *dlname,
2182 const char *old_name,
2183 int installed));
2184 static int free_vars LT_PARAMS((char *dlname, char *oldname,
2185 char *libdir, char *deplibs));
2186 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2187 char *deplibs));
2188 static int trim LT_PARAMS((char **dest,
2189 const char *str));
2190 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2191 const char *filename));
2192 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2193 const char *filename));
2194 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2195 static int lt_argz_insert LT_PARAMS((char **pargz,
2196 size_t *pargz_len,
2197 char *before,
2198 const char *entry));
2199 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2200 size_t *pargz_len,
2201 const char *entry));
2202 static int lt_argz_insertdir LT_PARAMS((char **pargz,
2203 size_t *pargz_len,
2204 const char *dirnam,
2205 struct dirent *dp));
2206 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2207 char *before,
2208 const char *dir));
2209 static int list_files_by_dir LT_PARAMS((const char *dirnam,
2210 char **pargz,
2211 size_t *pargz_len));
2212 static int file_not_found LT_PARAMS((void));
2214 static char *user_search_path= 0;
2215 static lt_dlloader *loaders = 0;
2216 static lt_dlhandle handles = 0;
2217 static int initialized = 0;
2219 /* Initialize libltdl. */
2221 lt_dlinit ()
2223 int errors = 0;
2225 LT_DLMUTEX_LOCK ();
2227 /* Initialize only at first call. */
2228 if (++initialized == 1)
2230 handles = 0;
2231 user_search_path = 0; /* empty search path */
2233 #if HAVE_LIBDL
2234 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2235 #endif
2236 #if HAVE_SHL_LOAD
2237 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2238 #endif
2239 #ifdef __WINDOWS__
2240 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2241 #endif
2242 #ifdef __BEOS__
2243 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2244 #endif
2245 #if HAVE_DLD
2246 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2247 #endif
2248 #if HAVE_DYLD
2249 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2250 errors += sys_dyld_init();
2251 #endif
2252 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2254 if (presym_init (presym.dlloader_data))
2256 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2257 ++errors;
2259 else if (errors != 0)
2261 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2262 ++errors;
2266 LT_DLMUTEX_UNLOCK ();
2268 return errors;
2272 lt_dlpreload (preloaded)
2273 const lt_dlsymlist *preloaded;
2275 int errors = 0;
2277 if (preloaded)
2279 errors = presym_add_symlist (preloaded);
2281 else
2283 presym_free_symlists();
2285 LT_DLMUTEX_LOCK ();
2286 if (default_preloaded_symbols)
2288 errors = lt_dlpreload (default_preloaded_symbols);
2290 LT_DLMUTEX_UNLOCK ();
2293 return errors;
2297 lt_dlpreload_default (preloaded)
2298 const lt_dlsymlist *preloaded;
2300 LT_DLMUTEX_LOCK ();
2301 default_preloaded_symbols = preloaded;
2302 LT_DLMUTEX_UNLOCK ();
2303 return 0;
2307 lt_dlexit ()
2309 /* shut down libltdl */
2310 lt_dlloader *loader;
2311 int errors = 0;
2313 LT_DLMUTEX_LOCK ();
2314 loader = loaders;
2316 if (!initialized)
2318 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2319 ++errors;
2320 goto done;
2323 /* shut down only at last call. */
2324 if (--initialized == 0)
2326 int level;
2328 while (handles && LT_DLIS_RESIDENT (handles))
2330 handles = handles->next;
2333 /* close all modules */
2334 for (level = 1; handles; ++level)
2336 lt_dlhandle cur = handles;
2337 int saw_nonresident = 0;
2339 while (cur)
2341 lt_dlhandle tmp = cur;
2342 cur = cur->next;
2343 if (!LT_DLIS_RESIDENT (tmp))
2344 saw_nonresident = 1;
2345 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2347 if (lt_dlclose (tmp))
2349 ++errors;
2351 /* Make sure that the handle pointed to by 'cur' still exists.
2352 lt_dlclose recursively closes dependent libraries which removes
2353 them from the linked list. One of these might be the one
2354 pointed to by 'cur'. */
2355 if (cur)
2357 for (tmp = handles; tmp; tmp = tmp->next)
2358 if (tmp == cur)
2359 break;
2360 if (! tmp)
2361 cur = handles;
2365 /* done if only resident modules are left */
2366 if (!saw_nonresident)
2367 break;
2370 /* close all loaders */
2371 while (loader)
2373 lt_dlloader *next = loader->next;
2374 lt_user_data data = loader->dlloader_data;
2375 if (loader->dlloader_exit && loader->dlloader_exit (data))
2377 ++errors;
2380 LT_DLMEM_REASSIGN (loader, next);
2382 loaders = 0;
2385 done:
2386 LT_DLMUTEX_UNLOCK ();
2387 return errors;
2390 static int
2391 tryall_dlopen (handle, filename)
2392 lt_dlhandle *handle;
2393 const char *filename;
2395 lt_dlhandle cur;
2396 lt_dlloader *loader;
2397 const char *saved_error;
2398 int errors = 0;
2400 LT_DLMUTEX_GETERROR (saved_error);
2401 LT_DLMUTEX_LOCK ();
2403 cur = handles;
2404 loader = loaders;
2406 /* check whether the module was already opened */
2407 while (cur)
2409 /* try to dlopen the program itself? */
2410 if (!cur->info.filename && !filename)
2412 break;
2415 if (cur->info.filename && filename
2416 && strcmp (cur->info.filename, filename) == 0)
2418 break;
2421 cur = cur->next;
2424 if (cur)
2426 ++cur->info.ref_count;
2427 *handle = cur;
2428 goto done;
2431 cur = *handle;
2432 if (filename)
2434 /* Comment out the check of file permissions using access.
2435 This call seems to always return -1 with error EACCES.
2437 /* We need to catch missing file errors early so that
2438 file_not_found() can detect what happened.
2439 if (access (filename, R_OK) != 0)
2441 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2442 ++errors;
2443 goto done;
2444 } */
2446 cur->info.filename = lt_estrdup (filename);
2447 if (!cur->info.filename)
2449 ++errors;
2450 goto done;
2453 else
2455 cur->info.filename = 0;
2458 while (loader)
2460 lt_user_data data = loader->dlloader_data;
2462 cur->module = loader->module_open (data, filename);
2464 if (cur->module != 0)
2466 break;
2468 loader = loader->next;
2471 if (!loader)
2473 LT_DLFREE (cur->info.filename);
2474 ++errors;
2475 goto done;
2478 cur->loader = loader;
2479 LT_DLMUTEX_SETERROR (saved_error);
2481 done:
2482 LT_DLMUTEX_UNLOCK ();
2484 return errors;
2487 static int
2488 tryall_dlopen_module (handle, prefix, dirname, dlname)
2489 lt_dlhandle *handle;
2490 const char *prefix;
2491 const char *dirname;
2492 const char *dlname;
2494 int error = 0;
2495 char *filename = 0;
2496 size_t filename_len = 0;
2497 size_t dirname_len = LT_STRLEN (dirname);
2499 assert (handle);
2500 assert (dirname);
2501 assert (dlname);
2502 #ifdef LT_DIRSEP_CHAR
2503 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2504 should make it into this function: */
2505 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2506 #endif
2508 if (dirname_len > 0)
2509 if (dirname[dirname_len -1] == '/')
2510 --dirname_len;
2511 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2513 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2514 The PREFIX (if any) is handled below. */
2515 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2516 if (!filename)
2517 return 1;
2519 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2521 /* Now that we have combined DIRNAME and MODULENAME, if there is
2522 also a PREFIX to contend with, simply recurse with the arguments
2523 shuffled. Otherwise, attempt to open FILENAME as a module. */
2524 if (prefix)
2526 error += tryall_dlopen_module (handle,
2527 (const char *) 0, prefix, filename);
2529 else if (tryall_dlopen (handle, filename) != 0)
2531 ++error;
2534 LT_DLFREE (filename);
2535 return error;
2538 static int
2539 find_module (handle, dir, libdir, dlname, old_name, installed)
2540 lt_dlhandle *handle;
2541 const char *dir;
2542 const char *libdir;
2543 const char *dlname;
2544 const char *old_name;
2545 int installed;
2547 /* Try to open the old library first; if it was dlpreopened,
2548 we want the preopened version of it, even if a dlopenable
2549 module is available. */
2550 if (old_name && tryall_dlopen (handle, old_name) == 0)
2552 return 0;
2555 /* Try to open the dynamic library. */
2556 if (dlname)
2558 /* try to open the installed module */
2559 if (installed && libdir)
2561 if (tryall_dlopen_module (handle,
2562 (const char *) 0, libdir, dlname) == 0)
2563 return 0;
2566 /* try to open the not-installed module */
2567 if (!installed)
2569 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2570 return 0;
2573 /* maybe it was moved to another directory */
2575 if (dir && (tryall_dlopen_module (handle,
2576 (const char *) 0, dir, dlname) == 0))
2577 return 0;
2581 return 1;
2585 static int
2586 canonicalize_path (path, pcanonical)
2587 const char *path;
2588 char **pcanonical;
2590 char *canonical = 0;
2592 assert (path && *path);
2593 assert (pcanonical);
2595 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2596 if (!canonical)
2597 return 1;
2600 size_t dest = 0;
2601 size_t src;
2602 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2604 /* Path separators are not copied to the beginning or end of
2605 the destination, or if another separator would follow
2606 immediately. */
2607 if (path[src] == LT_PATHSEP_CHAR)
2609 if ((dest == 0)
2610 || (path[1+ src] == LT_PATHSEP_CHAR)
2611 || (path[1+ src] == LT_EOS_CHAR))
2612 continue;
2615 /* Anything other than a directory separator is copied verbatim. */
2616 if ((path[src] != '/')
2617 #ifdef LT_DIRSEP_CHAR
2618 && (path[src] != LT_DIRSEP_CHAR)
2619 #endif
2622 canonical[dest++] = path[src];
2624 /* Directory separators are converted and copied only if they are
2625 not at the end of a path -- i.e. before a path separator or
2626 NULL terminator. */
2627 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2628 && (path[1+ src] != LT_EOS_CHAR)
2629 #ifdef LT_DIRSEP_CHAR
2630 && (path[1+ src] != LT_DIRSEP_CHAR)
2631 #endif
2632 && (path[1+ src] != '/'))
2634 canonical[dest++] = '/';
2638 /* Add an end-of-string marker at the end. */
2639 canonical[dest] = LT_EOS_CHAR;
2642 /* Assign new value. */
2643 *pcanonical = canonical;
2645 return 0;
2648 static int
2649 argzize_path (path, pargz, pargz_len)
2650 const char *path;
2651 char **pargz;
2652 size_t *pargz_len;
2654 error_t error;
2656 assert (path);
2657 assert (pargz);
2658 assert (pargz_len);
2660 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2662 switch (error)
2664 case ENOMEM:
2665 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2666 break;
2667 default:
2668 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2669 break;
2672 return 1;
2675 return 0;
2678 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2679 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2680 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2681 it is appended to each SEARCH_PATH element before FUNC is called. */
2682 static int
2683 foreach_dirinpath (search_path, base_name, func, data1, data2)
2684 const char *search_path;
2685 const char *base_name;
2686 foreach_callback_func *func;
2687 lt_ptr data1;
2688 lt_ptr data2;
2690 int result = 0;
2691 int filenamesize = 0;
2692 size_t lenbase = LT_STRLEN (base_name);
2693 size_t argz_len = 0;
2694 char *argz = 0;
2695 char *filename = 0;
2696 char *canonical = 0;
2698 LT_DLMUTEX_LOCK ();
2700 if (!search_path || !*search_path)
2702 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2703 goto cleanup;
2706 if (canonicalize_path (search_path, &canonical) != 0)
2707 goto cleanup;
2709 if (argzize_path (canonical, &argz, &argz_len) != 0)
2710 goto cleanup;
2713 char *dir_name = 0;
2714 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2716 size_t lendir = LT_STRLEN (dir_name);
2718 if (lendir +1 +lenbase >= filenamesize)
2720 LT_DLFREE (filename);
2721 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2722 filename = LT_EMALLOC (char, filenamesize);
2723 if (!filename)
2724 goto cleanup;
2727 assert (filenamesize > lendir);
2728 strcpy (filename, dir_name);
2730 if (base_name && *base_name)
2732 if (filename[lendir -1] != '/')
2733 filename[lendir++] = '/';
2734 strcpy (filename +lendir, base_name);
2737 if ((result = (*func) (filename, data1, data2)))
2739 break;
2744 cleanup:
2745 LT_DLFREE (argz);
2746 LT_DLFREE (canonical);
2747 LT_DLFREE (filename);
2749 LT_DLMUTEX_UNLOCK ();
2751 return result;
2754 /* If FILEPATH can be opened, store the name of the directory component
2755 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2756 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2757 static int
2758 find_file_callback (filename, data1, data2)
2759 char *filename;
2760 lt_ptr data1;
2761 lt_ptr data2;
2763 char **pdir = (char **) data1;
2764 FILE **pfile = (FILE **) data2;
2765 int is_done = 0;
2767 assert (filename && *filename);
2768 assert (pdir);
2769 assert (pfile);
2771 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2773 char *dirend = strrchr (filename, '/');
2775 if (dirend > filename)
2776 *dirend = LT_EOS_CHAR;
2778 LT_DLFREE (*pdir);
2779 *pdir = lt_estrdup (filename);
2780 is_done = (*pdir == 0) ? -1 : 1;
2783 return is_done;
2786 static FILE *
2787 find_file (search_path, base_name, pdir)
2788 const char *search_path;
2789 const char *base_name;
2790 char **pdir;
2792 FILE *file = 0;
2794 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2796 return file;
2799 static int
2800 find_handle_callback (filename, data, ignored)
2801 char *filename;
2802 lt_ptr data;
2803 lt_ptr ignored;
2805 lt_dlhandle *handle = (lt_dlhandle *) data;
2806 int notfound = access (filename, R_OK);
2808 /* Bail out if file cannot be read... */
2809 if (notfound)
2810 return 0;
2812 /* Try to dlopen the file, but do not continue searching in any
2813 case. */
2814 if (tryall_dlopen (handle, filename) != 0)
2815 *handle = 0;
2817 return 1;
2820 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2821 found but could not be opened, *HANDLE will be set to 0. */
2822 static lt_dlhandle *
2823 find_handle (search_path, base_name, handle)
2824 const char *search_path;
2825 const char *base_name;
2826 lt_dlhandle *handle;
2828 if (!search_path)
2829 return 0;
2831 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2832 handle, 0))
2833 return 0;
2835 return handle;
2838 static int
2839 load_deplibs (handle, deplibs)
2840 lt_dlhandle handle;
2841 char *deplibs;
2843 #if LTDL_DLOPEN_DEPLIBS
2844 char *p, *save_search_path = 0;
2845 int depcount = 0;
2846 int i;
2847 char **names = 0;
2848 #endif
2849 int errors = 0;
2851 handle->depcount = 0;
2853 #if LTDL_DLOPEN_DEPLIBS
2854 if (!deplibs)
2856 return errors;
2858 ++errors;
2860 LT_DLMUTEX_LOCK ();
2861 if (user_search_path)
2863 save_search_path = lt_estrdup (user_search_path);
2864 if (!save_search_path)
2865 goto cleanup;
2868 /* extract search paths and count deplibs */
2869 p = deplibs;
2870 while (*p)
2872 if (!isspace ((int) *p))
2874 char *end = p+1;
2875 while (*end && !isspace((int) *end))
2877 ++end;
2880 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2882 char save = *end;
2883 *end = 0; /* set a temporary string terminator */
2884 if (lt_dladdsearchdir(p+2))
2886 goto cleanup;
2888 *end = save;
2890 else
2892 ++depcount;
2895 p = end;
2897 else
2899 ++p;
2903 if (!depcount)
2905 errors = 0;
2906 goto cleanup;
2909 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2910 if (!names)
2911 goto cleanup;
2913 /* now only extract the actual deplibs */
2914 depcount = 0;
2915 p = deplibs;
2916 while (*p)
2918 if (isspace ((int) *p))
2920 ++p;
2922 else
2924 char *end = p+1;
2925 while (*end && !isspace ((int) *end))
2927 ++end;
2930 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2932 char *name;
2933 char save = *end;
2934 *end = 0; /* set a temporary string terminator */
2935 if (strncmp(p, "-l", 2) == 0)
2937 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2938 name = LT_EMALLOC (char, 1+ name_len);
2939 if (name)
2940 sprintf (name, "lib%s", p+2);
2942 else
2943 name = lt_estrdup(p);
2945 if (!name)
2946 goto cleanup_names;
2948 names[depcount++] = name;
2949 *end = save;
2951 p = end;
2955 /* load the deplibs (in reverse order)
2956 At this stage, don't worry if the deplibs do not load correctly,
2957 they may already be statically linked into the loading application
2958 for instance. There will be a more enlightening error message
2959 later on if the loaded module cannot resolve all of its symbols. */
2960 if (depcount)
2962 int j = 0;
2964 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2965 if (!handle->deplibs)
2966 goto cleanup_names;
2968 for (i = 0; i < depcount; ++i)
2970 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2971 if (handle->deplibs[j])
2973 ++j;
2977 handle->depcount = j; /* Number of successfully loaded deplibs */
2978 errors = 0;
2981 cleanup_names:
2982 for (i = 0; i < depcount; ++i)
2984 LT_DLFREE (names[i]);
2987 cleanup:
2988 LT_DLFREE (names);
2989 /* restore the old search path */
2990 if (user_search_path) {
2991 LT_DLFREE (user_search_path);
2992 user_search_path = save_search_path;
2994 LT_DLMUTEX_UNLOCK ();
2996 #endif
2998 return errors;
3001 static int
3002 unload_deplibs (handle)
3003 lt_dlhandle handle;
3005 int i;
3006 int errors = 0;
3008 if (handle->depcount)
3010 for (i = 0; i < handle->depcount; ++i)
3012 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
3014 errors += lt_dlclose (handle->deplibs[i]);
3017 LT_DLFREE (handle->deplibs);
3020 return errors;
3023 static int
3024 trim (dest, str)
3025 char **dest;
3026 const char *str;
3028 /* remove the leading and trailing "'" from str
3029 and store the result in dest */
3030 const char *end = strrchr (str, '\'');
3031 size_t len = LT_STRLEN (str);
3032 char *tmp;
3034 LT_DLFREE (*dest);
3036 if (!end)
3037 return 1;
3039 if (len > 3 && str[0] == '\'')
3041 tmp = LT_EMALLOC (char, end - str);
3042 if (!tmp)
3043 return 1;
3045 strncpy(tmp, &str[1], (end - str) - 1);
3046 tmp[len-3] = LT_EOS_CHAR;
3047 *dest = tmp;
3049 else
3051 *dest = 0;
3054 return 0;
3057 static int
3058 free_vars (dlname, oldname, libdir, deplibs)
3059 char *dlname;
3060 char *oldname;
3061 char *libdir;
3062 char *deplibs;
3064 LT_DLFREE (dlname);
3065 LT_DLFREE (oldname);
3066 LT_DLFREE (libdir);
3067 LT_DLFREE (deplibs);
3069 return 0;
3072 static int
3073 try_dlopen (phandle, filename)
3074 lt_dlhandle *phandle;
3075 const char *filename;
3077 const char * ext = 0;
3078 const char * saved_error = 0;
3079 char * canonical = 0;
3080 char * base_name = 0;
3081 char * dir = 0;
3082 char * name = 0;
3083 int errors = 0;
3084 lt_dlhandle newhandle;
3086 assert (phandle);
3087 assert (*phandle == 0);
3089 LT_DLMUTEX_GETERROR (saved_error);
3091 /* dlopen self? */
3092 if (!filename)
3094 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3095 if (*phandle == 0)
3096 return 1;
3098 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3099 newhandle = *phandle;
3101 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3102 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3104 if (tryall_dlopen (&newhandle, 0) != 0)
3106 LT_DLFREE (*phandle);
3107 return 1;
3110 goto register_handle;
3113 assert (filename && *filename);
3115 /* Doing this immediately allows internal functions to safely
3116 assume only canonicalized paths are passed. */
3117 if (canonicalize_path (filename, &canonical) != 0)
3119 ++errors;
3120 goto cleanup;
3123 /* If the canonical module name is a path (relative or absolute)
3124 then split it into a directory part and a name part. */
3125 base_name = strrchr (canonical, '/');
3126 if (base_name)
3128 size_t dirlen = (1+ base_name) - canonical;
3130 dir = LT_EMALLOC (char, 1+ dirlen);
3131 if (!dir)
3133 ++errors;
3134 goto cleanup;
3137 strncpy (dir, canonical, dirlen);
3138 dir[dirlen] = LT_EOS_CHAR;
3140 ++base_name;
3142 else
3143 base_name = canonical;
3145 assert (base_name && *base_name);
3147 /* Check whether we are opening a libtool module (.la extension). */
3148 ext = strrchr (base_name, '.');
3149 if (ext && strcmp (ext, archive_ext) == 0)
3151 /* this seems to be a libtool module */
3152 FILE * file = 0;
3153 char * dlname = 0;
3154 char * old_name = 0;
3155 char * libdir = 0;
3156 char * deplibs = 0;
3157 char * line = 0;
3158 size_t line_len;
3160 /* if we can't find the installed flag, it is probably an
3161 installed libtool archive, produced with an old version
3162 of libtool */
3163 int installed = 1;
3165 /* extract the module name from the file name */
3166 name = LT_EMALLOC (char, ext - base_name + 1);
3167 if (!name)
3169 ++errors;
3170 goto cleanup;
3173 /* canonicalize the module name */
3175 size_t i;
3176 for (i = 0; i < ext - base_name; ++i)
3178 if (isalnum ((int)(base_name[i])))
3180 name[i] = base_name[i];
3182 else
3184 name[i] = '_';
3187 name[ext - base_name] = LT_EOS_CHAR;
3190 /* Now try to open the .la file. If there is no directory name
3191 component, try to find it first in user_search_path and then other
3192 prescribed paths. Otherwise (or in any case if the module was not
3193 yet found) try opening just the module name as passed. */
3194 if (!dir)
3196 const char *search_path;
3198 LT_DLMUTEX_LOCK ();
3199 search_path = user_search_path;
3200 if (search_path)
3201 file = find_file (user_search_path, base_name, &dir);
3202 LT_DLMUTEX_UNLOCK ();
3204 if (!file)
3206 search_path = getenv (LTDL_SEARCHPATH_VAR);
3207 if (search_path)
3208 file = find_file (search_path, base_name, &dir);
3211 #ifdef LTDL_SHLIBPATH_VAR
3212 if (!file)
3214 search_path = getenv (LTDL_SHLIBPATH_VAR);
3215 if (search_path)
3216 file = find_file (search_path, base_name, &dir);
3218 #endif
3219 #ifdef LTDL_SYSSEARCHPATH
3220 if (!file && sys_search_path)
3222 file = find_file (sys_search_path, base_name, &dir);
3224 #endif
3226 if (!file)
3228 file = fopen (filename, LT_READTEXT_MODE);
3231 /* If we didn't find the file by now, it really isn't there. Set
3232 the status flag, and bail out. */
3233 if (!file)
3235 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3236 ++errors;
3237 goto cleanup;
3240 line_len = LT_FILENAME_MAX;
3241 line = LT_EMALLOC (char, line_len);
3242 if (!line)
3244 fclose (file);
3245 ++errors;
3246 goto cleanup;
3249 /* read the .la file */
3250 while (!feof (file))
3252 if (!fgets (line, (int) line_len, file))
3254 break;
3257 /* Handle the case where we occasionally need to read a line
3258 that is longer than the initial buffer size. */
3259 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3261 line = LT_DLREALLOC (char, line, line_len *2);
3262 if (!fgets (&line[line_len -1], (int) line_len +1, file))
3264 break;
3266 line_len *= 2;
3269 if (line[0] == '\n' || line[0] == '#')
3271 continue;
3274 #undef STR_DLNAME
3275 #define STR_DLNAME "dlname="
3276 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3278 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3281 #undef STR_OLD_LIBRARY
3282 #define STR_OLD_LIBRARY "old_library="
3283 else if (strncmp (line, STR_OLD_LIBRARY,
3284 sizeof (STR_OLD_LIBRARY) - 1) == 0)
3286 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3288 #undef STR_LIBDIR
3289 #define STR_LIBDIR "libdir="
3290 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3292 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3295 #undef STR_DL_DEPLIBS
3296 #define STR_DL_DEPLIBS "dependency_libs="
3297 else if (strncmp (line, STR_DL_DEPLIBS,
3298 sizeof (STR_DL_DEPLIBS) - 1) == 0)
3300 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3302 else if (strcmp (line, "installed=yes\n") == 0)
3304 installed = 1;
3306 else if (strcmp (line, "installed=no\n") == 0)
3308 installed = 0;
3311 #undef STR_LIBRARY_NAMES
3312 #define STR_LIBRARY_NAMES "library_names="
3313 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3314 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3316 char *last_libname;
3317 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3318 if (!errors
3319 && dlname
3320 && (last_libname = strrchr (dlname, ' ')) != 0)
3322 last_libname = lt_estrdup (last_libname + 1);
3323 if (!last_libname)
3325 ++errors;
3326 goto cleanup;
3328 LT_DLMEM_REASSIGN (dlname, last_libname);
3332 if (errors)
3333 break;
3336 fclose (file);
3337 LT_DLFREE (line);
3339 /* allocate the handle */
3340 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3341 if (*phandle == 0)
3342 ++errors;
3344 if (errors)
3346 free_vars (dlname, old_name, libdir, deplibs);
3347 LT_DLFREE (*phandle);
3348 goto cleanup;
3351 assert (*phandle);
3353 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3354 if (load_deplibs (*phandle, deplibs) == 0)
3356 newhandle = *phandle;
3357 /* find_module may replace newhandle */
3358 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3360 unload_deplibs (*phandle);
3361 ++errors;
3364 else
3366 ++errors;
3369 free_vars (dlname, old_name, libdir, deplibs);
3370 if (errors)
3372 LT_DLFREE (*phandle);
3373 goto cleanup;
3376 if (*phandle != newhandle)
3378 unload_deplibs (*phandle);
3381 else
3383 /* not a libtool module */
3384 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3385 if (*phandle == 0)
3387 ++errors;
3388 goto cleanup;
3391 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3392 newhandle = *phandle;
3394 /* If the module has no directory name component, try to find it
3395 first in user_search_path and then other prescribed paths.
3396 Otherwise (or in any case if the module was not yet found) try
3397 opening just the module name as passed. */
3398 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3399 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3400 &newhandle)
3401 #ifdef LTDL_SHLIBPATH_VAR
3402 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3403 &newhandle)
3404 #endif
3405 #ifdef LTDL_SYSSEARCHPATH
3406 && !find_handle (sys_search_path, base_name, &newhandle)
3407 #endif
3410 if (tryall_dlopen (&newhandle, filename) != 0)
3412 newhandle = NULL;
3416 if (!newhandle)
3418 LT_DLFREE (*phandle);
3419 ++errors;
3420 goto cleanup;
3424 register_handle:
3425 LT_DLMEM_REASSIGN (*phandle, newhandle);
3427 if ((*phandle)->info.ref_count == 0)
3429 (*phandle)->info.ref_count = 1;
3430 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3432 LT_DLMUTEX_LOCK ();
3433 (*phandle)->next = handles;
3434 handles = *phandle;
3435 LT_DLMUTEX_UNLOCK ();
3438 LT_DLMUTEX_SETERROR (saved_error);
3440 cleanup:
3441 LT_DLFREE (dir);
3442 LT_DLFREE (name);
3443 LT_DLFREE (canonical);
3445 return errors;
3448 lt_dlhandle
3449 lt_dlopen (filename)
3450 const char *filename;
3452 lt_dlhandle handle = 0;
3454 /* Just incase we missed a code path in try_dlopen() that reports
3455 an error, but forgets to reset handle... */
3456 if (try_dlopen (&handle, filename) != 0)
3457 return 0;
3459 return handle;
3462 /* If the last error messge store was `FILE_NOT_FOUND', then return
3463 non-zero. */
3464 static int
3465 file_not_found ()
3467 const char *error = 0;
3469 LT_DLMUTEX_GETERROR (error);
3470 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3471 return 1;
3473 return 0;
3476 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3477 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3478 and if a file is still not found try again with SHLIB_EXT appended
3479 instead. */
3480 lt_dlhandle
3481 lt_dlopenext (filename)
3482 const char *filename;
3484 lt_dlhandle handle = 0;
3485 char * tmp = 0;
3486 char * ext = 0;
3487 size_t len;
3488 int errors = 0;
3490 if (!filename)
3492 return lt_dlopen (filename);
3495 assert (filename);
3497 len = LT_STRLEN (filename);
3498 ext = strrchr (filename, '.');
3500 /* If FILENAME already bears a suitable extension, there is no need
3501 to try appending additional extensions. */
3502 if (ext && ((strcmp (ext, archive_ext) == 0)
3503 #ifdef LTDL_SHLIB_EXT
3504 || (strcmp (ext, shlib_ext) == 0)
3505 #endif
3508 return lt_dlopen (filename);
3511 /* First try appending ARCHIVE_EXT. */
3512 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3513 if (!tmp)
3514 return 0;
3516 strcpy (tmp, filename);
3517 strcat (tmp, archive_ext);
3518 errors = try_dlopen (&handle, tmp);
3520 /* If we found FILENAME, stop searching -- whether we were able to
3521 load the file as a module or not. If the file exists but loading
3522 failed, it is better to return an error message here than to
3523 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3524 in the module search path. */
3525 if (handle || ((errors > 0) && !file_not_found ()))
3527 LT_DLFREE (tmp);
3528 return handle;
3531 #ifdef LTDL_SHLIB_EXT
3532 /* Try appending SHLIB_EXT. */
3533 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3535 LT_DLFREE (tmp);
3536 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3537 if (!tmp)
3538 return 0;
3540 strcpy (tmp, filename);
3542 else
3544 tmp[len] = LT_EOS_CHAR;
3547 strcat(tmp, shlib_ext);
3548 errors = try_dlopen (&handle, tmp);
3550 /* As before, if the file was found but loading failed, return now
3551 with the current error message. */
3552 if (handle || ((errors > 0) && !file_not_found ()))
3554 LT_DLFREE (tmp);
3555 return handle;
3557 #endif
3559 /* Still here? Then we really did fail to locate any of the file
3560 names we tried. */
3561 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3562 LT_DLFREE (tmp);
3563 return 0;
3567 static int
3568 lt_argz_insert (pargz, pargz_len, before, entry)
3569 char **pargz;
3570 size_t *pargz_len;
3571 char *before;
3572 const char *entry;
3574 error_t error;
3576 /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3577 pargz_len, NULL, entry) failed with EINVAL. */
3578 if (before)
3579 error = argz_insert (pargz, pargz_len, before, entry);
3580 else
3581 error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
3583 if (error)
3585 switch (error)
3587 case ENOMEM:
3588 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3589 break;
3590 default:
3591 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3592 break;
3594 return 1;
3597 return 0;
3600 static int
3601 lt_argz_insertinorder (pargz, pargz_len, entry)
3602 char **pargz;
3603 size_t *pargz_len;
3604 const char *entry;
3606 char *before = 0;
3608 assert (pargz);
3609 assert (pargz_len);
3610 assert (entry && *entry);
3612 if (*pargz)
3613 while ((before = argz_next (*pargz, *pargz_len, before)))
3615 int cmp = strcmp (entry, before);
3617 if (cmp < 0) break;
3618 if (cmp == 0) return 0; /* No duplicates! */
3621 return lt_argz_insert (pargz, pargz_len, before, entry);
3624 static int
3625 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3626 char **pargz;
3627 size_t *pargz_len;
3628 const char *dirnam;
3629 struct dirent *dp;
3631 char *buf = 0;
3632 size_t buf_len = 0;
3633 char *end = 0;
3634 size_t end_offset = 0;
3635 size_t dir_len = 0;
3636 int errors = 0;
3638 assert (pargz);
3639 assert (pargz_len);
3640 assert (dp);
3642 dir_len = LT_STRLEN (dirnam);
3643 end = dp->d_name + LT_D_NAMLEN(dp);
3645 /* Ignore version numbers. */
3647 char *p;
3648 for (p = end; p -1 > dp->d_name; --p)
3649 if (strchr (".0123456789", p[-1]) == 0)
3650 break;
3652 if (*p == '.')
3653 end = p;
3656 /* Ignore filename extension. */
3658 char *p;
3659 for (p = end -1; p > dp->d_name; --p)
3660 if (*p == '.')
3662 end = p;
3663 break;
3667 /* Prepend the directory name. */
3668 end_offset = end - dp->d_name;
3669 buf_len = dir_len + 1+ end_offset;
3670 buf = LT_EMALLOC (char, 1+ buf_len);
3671 if (!buf)
3672 return ++errors;
3674 assert (buf);
3676 strcpy (buf, dirnam);
3677 strcat (buf, "/");
3678 strncat (buf, dp->d_name, end_offset);
3679 buf[buf_len] = LT_EOS_CHAR;
3681 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3682 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3683 ++errors;
3685 LT_DLFREE (buf);
3687 return errors;
3690 static int
3691 list_files_by_dir (dirnam, pargz, pargz_len)
3692 const char *dirnam;
3693 char **pargz;
3694 size_t *pargz_len;
3696 DIR *dirp = 0;
3697 int errors = 0;
3699 assert (dirnam && *dirnam);
3700 assert (pargz);
3701 assert (pargz_len);
3702 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3704 dirp = opendir (dirnam);
3705 if (dirp)
3707 struct dirent *dp = 0;
3709 while ((dp = readdir (dirp)))
3710 if (dp->d_name[0] != '.')
3711 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3713 ++errors;
3714 break;
3717 closedir (dirp);
3719 else
3720 ++errors;
3722 return errors;
3726 /* If there are any files in DIRNAME, call the function passed in
3727 DATA1 (with the name of each file and DATA2 as arguments). */
3728 static int
3729 foreachfile_callback (dirname, data1, data2)
3730 char *dirname;
3731 lt_ptr data1;
3732 lt_ptr data2;
3734 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3735 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3737 int is_done = 0;
3738 char *argz = 0;
3739 size_t argz_len = 0;
3741 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3742 goto cleanup;
3743 if (!argz)
3744 goto cleanup;
3747 char *filename = 0;
3748 while ((filename = argz_next (argz, argz_len, filename)))
3749 if ((is_done = (*func) (filename, data2)))
3750 break;
3753 cleanup:
3754 LT_DLFREE (argz);
3756 return is_done;
3760 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3761 with DATA. The filenames passed to FUNC would be suitable for
3762 passing to lt_dlopenext. The extensions are stripped so that
3763 individual modules do not generate several entries (e.g. libfoo.la,
3764 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3765 then the same directories that lt_dlopen would search are examined. */
3767 lt_dlforeachfile (search_path, func, data)
3768 const char *search_path;
3769 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3770 lt_ptr data;
3772 int is_done = 0;
3774 if (search_path)
3776 /* If a specific path was passed, search only the directories
3777 listed in it. */
3778 is_done = foreach_dirinpath (search_path, 0,
3779 foreachfile_callback, func, data);
3781 else
3783 /* Otherwise search the default paths. */
3784 is_done = foreach_dirinpath (user_search_path, 0,
3785 foreachfile_callback, func, data);
3786 if (!is_done)
3788 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3789 foreachfile_callback, func, data);
3792 #ifdef LTDL_SHLIBPATH_VAR
3793 if (!is_done)
3795 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3796 foreachfile_callback, func, data);
3798 #endif
3799 #ifdef LTDL_SYSSEARCHPATH
3800 if (!is_done)
3802 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3803 foreachfile_callback, func, data);
3805 #endif
3808 return is_done;
3812 lt_dlclose (handle)
3813 lt_dlhandle handle;
3815 lt_dlhandle cur, last;
3816 int errors = 0;
3818 LT_DLMUTEX_LOCK ();
3820 /* check whether the handle is valid */
3821 last = cur = handles;
3822 while (cur && handle != cur)
3824 last = cur;
3825 cur = cur->next;
3828 if (!cur)
3830 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3831 ++errors;
3832 goto done;
3835 handle->info.ref_count--;
3837 /* Note that even with resident modules, we must track the ref_count
3838 correctly incase the user decides to reset the residency flag
3839 later (even though the API makes no provision for that at the
3840 moment). */
3841 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3843 lt_user_data data = handle->loader->dlloader_data;
3845 if (handle != handles)
3847 last->next = handle->next;
3849 else
3851 handles = handle->next;
3854 errors += handle->loader->module_close (data, handle->module);
3855 errors += unload_deplibs(handle);
3857 /* It is up to the callers to free the data itself. */
3858 LT_DLFREE (handle->caller_data);
3860 LT_DLFREE (handle->info.filename);
3861 LT_DLFREE (handle->info.name);
3862 LT_DLFREE (handle);
3864 goto done;
3867 if (LT_DLIS_RESIDENT (handle))
3869 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3870 ++errors;
3873 done:
3874 LT_DLMUTEX_UNLOCK ();
3876 return errors;
3879 lt_ptr
3880 lt_dlsym (handle, symbol)
3881 lt_dlhandle handle;
3882 const char *symbol;
3884 size_t lensym;
3885 char lsym[LT_SYMBOL_LENGTH];
3886 char *sym;
3887 lt_ptr address;
3888 lt_user_data data;
3890 if (!handle)
3892 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3893 return 0;
3896 if (!symbol)
3898 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3899 return 0;
3902 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3903 + LT_STRLEN (handle->info.name);
3905 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3907 sym = lsym;
3909 else
3911 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3912 if (!sym)
3914 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3915 return 0;
3919 data = handle->loader->dlloader_data;
3920 if (handle->info.name)
3922 const char *saved_error;
3924 LT_DLMUTEX_GETERROR (saved_error);
3926 /* this is a libtool module */
3927 if (handle->loader->sym_prefix)
3929 strcpy(sym, handle->loader->sym_prefix);
3930 strcat(sym, handle->info.name);
3932 else
3934 strcpy(sym, handle->info.name);
3937 strcat(sym, "_LTX_");
3938 strcat(sym, symbol);
3940 /* try "modulename_LTX_symbol" */
3941 address = handle->loader->find_sym (data, handle->module, sym);
3942 if (address)
3944 if (sym != lsym)
3946 LT_DLFREE (sym);
3948 return address;
3950 LT_DLMUTEX_SETERROR (saved_error);
3953 /* otherwise try "symbol" */
3954 if (handle->loader->sym_prefix)
3956 strcpy(sym, handle->loader->sym_prefix);
3957 strcat(sym, symbol);
3959 else
3961 strcpy(sym, symbol);
3964 address = handle->loader->find_sym (data, handle->module, sym);
3965 if (sym != lsym)
3967 LT_DLFREE (sym);
3970 return address;
3973 const char *
3974 lt_dlerror ()
3976 const char *error;
3978 LT_DLMUTEX_GETERROR (error);
3979 LT_DLMUTEX_SETERROR (0);
3981 return error ? error : NULL;
3984 static int
3985 lt_dlpath_insertdir (ppath, before, dir)
3986 char **ppath;
3987 char *before;
3988 const char *dir;
3990 int errors = 0;
3991 char *canonical = 0;
3992 char *argz = 0;
3993 size_t argz_len = 0;
3995 assert (ppath);
3996 assert (dir && *dir);
3998 if (canonicalize_path (dir, &canonical) != 0)
4000 ++errors;
4001 goto cleanup;
4004 assert (canonical && *canonical);
4006 /* If *PPATH is empty, set it to DIR. */
4007 if (*ppath == 0)
4009 assert (!before); /* BEFORE cannot be set without PPATH. */
4010 assert (dir); /* Without DIR, don't call this function! */
4012 *ppath = lt_estrdup (dir);
4013 if (*ppath == 0)
4014 ++errors;
4016 return errors;
4019 assert (ppath && *ppath);
4021 if (argzize_path (*ppath, &argz, &argz_len) != 0)
4023 ++errors;
4024 goto cleanup;
4027 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
4028 if *PPATH is already canonicalized, and hence does not change length
4029 with respect to ARGZ. We canonicalize each entry as it is added to
4030 the search path, and don't call this function with (uncanonicalized)
4031 user paths, so this is a fair assumption. */
4032 if (before)
4034 assert (*ppath <= before);
4035 assert (before - *ppath <= strlen (*ppath));
4037 before = before - *ppath + argz;
4040 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
4042 ++errors;
4043 goto cleanup;
4046 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
4047 LT_DLMEM_REASSIGN (*ppath, argz);
4049 cleanup:
4050 LT_DLFREE (canonical);
4051 LT_DLFREE (argz);
4053 return errors;
4057 lt_dladdsearchdir (search_dir)
4058 const char *search_dir;
4060 int errors = 0;
4062 if (search_dir && *search_dir)
4064 LT_DLMUTEX_LOCK ();
4065 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4066 ++errors;
4067 LT_DLMUTEX_UNLOCK ();
4070 return errors;
4074 lt_dlinsertsearchdir (before, search_dir)
4075 const char *before;
4076 const char *search_dir;
4078 int errors = 0;
4080 if (before)
4082 LT_DLMUTEX_LOCK ();
4083 if ((before < user_search_path)
4084 || (before >= user_search_path + LT_STRLEN (user_search_path)))
4086 LT_DLMUTEX_UNLOCK ();
4087 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4088 return 1;
4090 LT_DLMUTEX_UNLOCK ();
4093 if (search_dir && *search_dir)
4095 LT_DLMUTEX_LOCK ();
4096 if (lt_dlpath_insertdir (&user_search_path,
4097 (char *) before, search_dir) != 0)
4099 ++errors;
4101 LT_DLMUTEX_UNLOCK ();
4104 return errors;
4108 lt_dlsetsearchpath (search_path)
4109 const char *search_path;
4111 int errors = 0;
4113 LT_DLMUTEX_LOCK ();
4114 LT_DLFREE (user_search_path);
4115 LT_DLMUTEX_UNLOCK ();
4117 if (!search_path || !LT_STRLEN (search_path))
4119 return errors;
4122 LT_DLMUTEX_LOCK ();
4123 if (canonicalize_path (search_path, &user_search_path) != 0)
4124 ++errors;
4125 LT_DLMUTEX_UNLOCK ();
4127 return errors;
4130 const char *
4131 lt_dlgetsearchpath ()
4133 const char *saved_path;
4135 LT_DLMUTEX_LOCK ();
4136 saved_path = user_search_path;
4137 LT_DLMUTEX_UNLOCK ();
4139 return saved_path;
4143 lt_dlmakeresident (handle)
4144 lt_dlhandle handle;
4146 int errors = 0;
4148 if (!handle)
4150 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4151 ++errors;
4153 else
4155 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4158 return errors;
4162 lt_dlisresident (handle)
4163 lt_dlhandle handle;
4165 if (!handle)
4167 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4168 return -1;
4171 return LT_DLIS_RESIDENT (handle);
4177 /* --- MODULE INFORMATION --- */
4179 const lt_dlinfo *
4180 lt_dlgetinfo (handle)
4181 lt_dlhandle handle;
4183 if (!handle)
4185 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4186 return 0;
4189 return &(handle->info);
4192 lt_dlhandle
4193 lt_dlhandle_next (place)
4194 lt_dlhandle place;
4196 return place ? place->next : handles;
4200 lt_dlforeach (func, data)
4201 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4202 lt_ptr data;
4204 int errors = 0;
4205 lt_dlhandle cur;
4207 LT_DLMUTEX_LOCK ();
4209 cur = handles;
4210 while (cur)
4212 lt_dlhandle tmp = cur;
4214 cur = cur->next;
4215 if ((*func) (tmp, data))
4217 ++errors;
4218 break;
4222 LT_DLMUTEX_UNLOCK ();
4224 return errors;
4227 lt_dlcaller_id
4228 lt_dlcaller_register ()
4230 static lt_dlcaller_id last_caller_id = 0;
4231 int result;
4233 LT_DLMUTEX_LOCK ();
4234 result = ++last_caller_id;
4235 LT_DLMUTEX_UNLOCK ();
4237 return result;
4240 lt_ptr
4241 lt_dlcaller_set_data (key, handle, data)
4242 lt_dlcaller_id key;
4243 lt_dlhandle handle;
4244 lt_ptr data;
4246 int n_elements = 0;
4247 lt_ptr stale = (lt_ptr) 0;
4248 int i;
4250 /* This needs to be locked so that the caller data can be updated
4251 simultaneously by different threads. */
4252 LT_DLMUTEX_LOCK ();
4254 if (handle->caller_data)
4255 while (handle->caller_data[n_elements].key)
4256 ++n_elements;
4258 for (i = 0; i < n_elements; ++i)
4260 if (handle->caller_data[i].key == key)
4262 stale = handle->caller_data[i].data;
4263 break;
4267 /* Ensure that there is enough room in this handle's caller_data
4268 array to accept a new element (and an empty end marker). */
4269 if (i == n_elements)
4271 lt_caller_data *temp
4272 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4274 if (!temp)
4276 stale = 0;
4277 goto done;
4280 handle->caller_data = temp;
4282 /* We only need this if we needed to allocate a new caller_data. */
4283 handle->caller_data[i].key = key;
4284 handle->caller_data[1+ i].key = 0;
4287 handle->caller_data[i].data = data;
4289 done:
4290 LT_DLMUTEX_UNLOCK ();
4292 return stale;
4295 lt_ptr
4296 lt_dlcaller_get_data (key, handle)
4297 lt_dlcaller_id key;
4298 lt_dlhandle handle;
4300 lt_ptr result = (lt_ptr) 0;
4302 /* This needs to be locked so that the caller data isn't updated by
4303 another thread part way through this function. */
4304 LT_DLMUTEX_LOCK ();
4306 /* Locate the index of the element with a matching KEY. */
4308 int i;
4309 for (i = 0; handle->caller_data[i].key; ++i)
4311 if (handle->caller_data[i].key == key)
4313 result = handle->caller_data[i].data;
4314 break;
4319 LT_DLMUTEX_UNLOCK ();
4321 return result;
4326 /* --- USER MODULE LOADER API --- */
4330 lt_dlloader_add (place, dlloader, loader_name)
4331 lt_dlloader *place;
4332 const struct lt_user_dlloader *dlloader;
4333 const char *loader_name;
4335 int errors = 0;
4336 lt_dlloader *node = 0, *ptr = 0;
4338 if ((dlloader == 0) /* diagnose null parameters */
4339 || (dlloader->module_open == 0)
4340 || (dlloader->module_close == 0)
4341 || (dlloader->find_sym == 0))
4343 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4344 return 1;
4347 /* Create a new dlloader node with copies of the user callbacks. */
4348 node = LT_EMALLOC (lt_dlloader, 1);
4349 if (!node)
4350 return 1;
4352 node->next = 0;
4353 node->loader_name = loader_name;
4354 node->sym_prefix = dlloader->sym_prefix;
4355 node->dlloader_exit = dlloader->dlloader_exit;
4356 node->module_open = dlloader->module_open;
4357 node->module_close = dlloader->module_close;
4358 node->find_sym = dlloader->find_sym;
4359 node->dlloader_data = dlloader->dlloader_data;
4361 LT_DLMUTEX_LOCK ();
4362 if (!loaders)
4364 /* If there are no loaders, NODE becomes the list! */
4365 loaders = node;
4367 else if (!place)
4369 /* If PLACE is not set, add NODE to the end of the
4370 LOADERS list. */
4371 for (ptr = loaders; ptr->next; ptr = ptr->next)
4373 /*NOWORK*/;
4376 ptr->next = node;
4378 else if (loaders == place)
4380 /* If PLACE is the first loader, NODE goes first. */
4381 node->next = place;
4382 loaders = node;
4384 else
4386 /* Find the node immediately preceding PLACE. */
4387 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4389 /*NOWORK*/;
4392 if (ptr->next != place)
4394 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4395 ++errors;
4397 else
4399 /* Insert NODE between PTR and PLACE. */
4400 node->next = place;
4401 ptr->next = node;
4405 LT_DLMUTEX_UNLOCK ();
4407 return errors;
4411 lt_dlloader_remove (loader_name)
4412 const char *loader_name;
4414 lt_dlloader *place = lt_dlloader_find (loader_name);
4415 lt_dlhandle handle;
4416 int errors = 0;
4418 if (!place)
4420 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4421 return 1;
4424 LT_DLMUTEX_LOCK ();
4426 /* Fail if there are any open modules which use this loader. */
4427 for (handle = handles; handle; handle = handle->next)
4429 if (handle->loader == place)
4431 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4432 ++errors;
4433 goto done;
4437 if (place == loaders)
4439 /* PLACE is the first loader in the list. */
4440 loaders = loaders->next;
4442 else
4444 /* Find the loader before the one being removed. */
4445 lt_dlloader *prev;
4446 for (prev = loaders; prev->next; prev = prev->next)
4448 if (!strcmp (prev->next->loader_name, loader_name))
4450 break;
4454 place = prev->next;
4455 prev->next = prev->next->next;
4458 if (place->dlloader_exit)
4460 errors = place->dlloader_exit (place->dlloader_data);
4463 LT_DLFREE (place);
4465 done:
4466 LT_DLMUTEX_UNLOCK ();
4468 return errors;
4471 lt_dlloader *
4472 lt_dlloader_next (place)
4473 lt_dlloader *place;
4475 lt_dlloader *next;
4477 LT_DLMUTEX_LOCK ();
4478 next = place ? place->next : loaders;
4479 LT_DLMUTEX_UNLOCK ();
4481 return next;
4484 const char *
4485 lt_dlloader_name (place)
4486 lt_dlloader *place;
4488 const char *name = 0;
4490 if (place)
4492 LT_DLMUTEX_LOCK ();
4493 name = place ? place->loader_name : 0;
4494 LT_DLMUTEX_UNLOCK ();
4496 else
4498 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4501 return name;
4504 lt_user_data *
4505 lt_dlloader_data (place)
4506 lt_dlloader *place;
4508 lt_user_data *data = 0;
4510 if (place)
4512 LT_DLMUTEX_LOCK ();
4513 data = place ? &(place->dlloader_data) : 0;
4514 LT_DLMUTEX_UNLOCK ();
4516 else
4518 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4521 return data;
4524 lt_dlloader *
4525 lt_dlloader_find (loader_name)
4526 const char *loader_name;
4528 lt_dlloader *place = 0;
4530 LT_DLMUTEX_LOCK ();
4531 for (place = loaders; place; place = place->next)
4533 if (strcmp (place->loader_name, loader_name) == 0)
4535 break;
4538 LT_DLMUTEX_UNLOCK ();
4540 return place;