Imported File#ftype spec from rubyspecs.
[rbx.git] / shotgun / external_libs / libltdl / ltdl.c
blobe3ce820c14219def554edb28e92e6043fb365c6a
1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3 Originally by Thomas Tanner <tanner@ffii.org>
4 This file is part of GNU Libtool.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 As a special exception to the GNU Lesser General Public License,
12 if you distribute this file as part of a program or library that
13 is built using GNU libtool, you may include it under the same
14 distribution terms that you use for the rest of that program.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307 USA
28 #if HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #if HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
36 #if HAVE_STDIO_H
37 # include <stdio.h>
38 #endif
40 #if HAVE_STDLIB_H
41 # include <stdlib.h>
42 #endif
44 #if HAVE_STRING_H
45 # include <string.h>
46 #else
47 # if HAVE_STRINGS_H
48 # include <strings.h>
49 # endif
50 #endif
52 #if HAVE_CTYPE_H
53 # include <ctype.h>
54 #endif
56 #if HAVE_MALLOC_H
57 # include <malloc.h>
58 #endif
60 #if HAVE_MEMORY_H
61 # include <memory.h>
62 #endif
64 #if HAVE_ERRNO_H
65 # include <errno.h>
66 #endif
69 #ifndef __WINDOWS__
70 # ifdef __WIN32__
71 # define __WINDOWS__
72 # endif
73 #endif
76 #undef LT_USE_POSIX_DIRENT
77 #ifdef HAVE_CLOSEDIR
78 # ifdef HAVE_OPENDIR
79 # ifdef HAVE_READDIR
80 # ifdef HAVE_DIRENT_H
81 # define LT_USE_POSIX_DIRENT
82 # endif /* HAVE_DIRENT_H */
83 # endif /* HAVE_READDIR */
84 # endif /* HAVE_OPENDIR */
85 #endif /* HAVE_CLOSEDIR */
88 #undef LT_USE_WINDOWS_DIRENT_EMULATION
89 #ifndef LT_USE_POSIX_DIRENT
90 # ifdef __WINDOWS__
91 # define LT_USE_WINDOWS_DIRENT_EMULATION
92 # endif /* __WINDOWS__ */
93 #endif /* LT_USE_POSIX_DIRENT */
96 #ifdef LT_USE_POSIX_DIRENT
97 # include <dirent.h>
98 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
99 #else
100 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
101 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
102 # else
103 # define dirent direct
104 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
105 # if HAVE_SYS_NDIR_H
106 # include <sys/ndir.h>
107 # endif
108 # if HAVE_SYS_DIR_H
109 # include <sys/dir.h>
110 # endif
111 # if HAVE_NDIR_H
112 # include <ndir.h>
113 # endif
114 # endif
115 #endif
117 #if HAVE_ARGZ_H
118 # include <argz.h>
119 #endif
121 #if HAVE_ASSERT_H
122 # include <assert.h>
123 #else
124 # define assert(arg) ((void) 0)
125 #endif
127 #include "ltdl.h"
129 #if WITH_DMALLOC
130 # include <dmalloc.h>
131 #endif
136 /* --- WINDOWS SUPPORT --- */
139 #ifdef DLL_EXPORT
140 # define LT_GLOBAL_DATA __declspec(dllexport)
141 #else
142 # define LT_GLOBAL_DATA
143 #endif
145 /* fopen() mode flags for reading a text file */
146 #undef LT_READTEXT_MODE
147 #ifdef __WINDOWS__
148 # define LT_READTEXT_MODE "rt"
149 #else
150 # define LT_READTEXT_MODE "r"
151 #endif
153 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
155 #include <windows.h>
157 #define dirent lt_dirent
158 #define DIR lt_DIR
160 struct dirent
162 char d_name[2048];
163 int d_namlen;
166 typedef struct _DIR
168 HANDLE hSearch;
169 WIN32_FIND_DATA Win32FindData;
170 BOOL firsttime;
171 struct dirent file_info;
172 } DIR;
174 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
177 /* --- MANIFEST CONSTANTS --- */
180 /* Standard libltdl search path environment variable name */
181 #undef LTDL_SEARCHPATH_VAR
182 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
184 /* Standard libtool archive file extension. */
185 #undef LTDL_ARCHIVE_EXT
186 #define LTDL_ARCHIVE_EXT ".la"
188 /* max. filename length */
189 #ifndef LT_FILENAME_MAX
190 # define LT_FILENAME_MAX 1024
191 #endif
193 /* This is the maximum symbol size that won't require malloc/free */
194 #undef LT_SYMBOL_LENGTH
195 #define LT_SYMBOL_LENGTH 128
197 /* This accounts for the _LTX_ separator */
198 #undef LT_SYMBOL_OVERHEAD
199 #define LT_SYMBOL_OVERHEAD 5
204 /* --- MEMORY HANDLING --- */
207 /* These are the functions used internally. In addition to making
208 use of the associated function pointers above, they also perform
209 error handling. */
210 static char *lt_estrdup LT_PARAMS((const char *str));
211 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
212 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
214 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
215 #define rpl_realloc realloc
217 /* These are the pointers that can be changed by the caller: */
218 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
219 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
220 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
221 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
222 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
223 = (void (*) LT_PARAMS((lt_ptr))) free;
225 /* The following macros reduce the amount of typing needed to cast
226 assigned memory. */
227 #if WITH_DMALLOC
229 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
230 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
231 #define LT_DLFREE(p) \
232 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
234 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
235 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
237 #else
239 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
240 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
241 #define LT_DLFREE(p) \
242 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
244 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
245 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
247 #endif
249 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
250 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
251 } LT_STMT_END
254 /* --- REPLACEMENT FUNCTIONS --- */
257 #undef strdup
258 #define strdup rpl_strdup
260 static char *strdup LT_PARAMS((const char *str));
262 static char *
263 strdup(str)
264 const char *str;
266 char *tmp = 0;
268 if (str)
270 tmp = LT_DLMALLOC (char, 1+ strlen (str));
271 if (tmp)
273 strcpy(tmp, str);
277 return tmp;
281 #if ! HAVE_STRCMP
283 #undef strcmp
284 #define strcmp rpl_strcmp
286 static int strcmp LT_PARAMS((const char *str1, const char *str2));
288 static int
289 strcmp (str1, str2)
290 const char *str1;
291 const char *str2;
293 if (str1 == str2)
294 return 0;
295 if (str1 == 0)
296 return -1;
297 if (str2 == 0)
298 return 1;
300 for (;*str1 && *str2; ++str1, ++str2)
302 if (*str1 != *str2)
303 break;
306 return (int)(*str1 - *str2);
308 #endif
311 #if ! HAVE_STRCHR
313 # if HAVE_INDEX
314 # define strchr index
315 # else
316 # define strchr rpl_strchr
318 static const char *strchr LT_PARAMS((const char *str, int ch));
320 static const char*
321 strchr(str, ch)
322 const char *str;
323 int ch;
325 const char *p;
327 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
328 /*NOWORK*/;
330 return (*p == (char)ch) ? p : 0;
333 # endif
334 #endif /* !HAVE_STRCHR */
337 #if ! HAVE_STRRCHR
339 # if HAVE_RINDEX
340 # define strrchr rindex
341 # else
342 # define strrchr rpl_strrchr
344 static const char *strrchr LT_PARAMS((const char *str, int ch));
346 static const char*
347 strrchr(str, ch)
348 const char *str;
349 int ch;
351 const char *p, *q = 0;
353 for (p = str; *p != LT_EOS_CHAR; ++p)
355 if (*p == (char) ch)
357 q = p;
361 return q;
364 # endif
365 #endif
367 /* NOTE: Neither bcopy nor the memcpy implementation below can
368 reliably handle copying in overlapping areas of memory. Use
369 memmove (for which there is a fallback implmentation below)
370 if you need that behaviour. */
371 #if ! HAVE_MEMCPY
373 # if HAVE_BCOPY
374 # define memcpy(dest, src, size) bcopy (src, dest, size)
375 # else
376 # define memcpy rpl_memcpy
378 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
380 static lt_ptr
381 memcpy (dest, src, size)
382 lt_ptr dest;
383 const lt_ptr src;
384 size_t size;
386 size_t i = 0;
388 for (i = 0; i < size; ++i)
390 dest[i] = src[i];
393 return dest;
396 # endif /* !HAVE_BCOPY */
397 #endif /* !HAVE_MEMCPY */
399 #if ! HAVE_MEMMOVE
400 # define memmove rpl_memmove
402 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
404 static lt_ptr
405 memmove (dest, src, size)
406 lt_ptr dest;
407 const lt_ptr src;
408 size_t size;
410 size_t i;
412 if (dest < src)
413 for (i = 0; i < size; ++i)
415 dest[i] = src[i];
417 else if (dest > src)
418 for (i = size -1; i >= 0; --i)
420 dest[i] = src[i];
423 return dest;
426 #endif /* !HAVE_MEMMOVE */
428 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
430 static void closedir LT_PARAMS((DIR *entry));
432 static void
433 closedir(entry)
434 DIR *entry;
436 assert(entry != (DIR *) NULL);
437 FindClose(entry->hSearch);
438 lt_dlfree((lt_ptr)entry);
442 static DIR * opendir LT_PARAMS((const char *path));
444 static DIR*
445 opendir (path)
446 const char *path;
448 char file_specification[LT_FILENAME_MAX];
449 DIR *entry;
451 assert(path != (char *) NULL);
452 (void) strncpy(file_specification,path,LT_FILENAME_MAX-1);
453 (void) strcat(file_specification,"\\");
454 entry = LT_DLMALLOC (DIR,sizeof(DIR));
455 if (entry != (DIR *) 0)
457 entry->firsttime = TRUE;
458 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
460 if (entry->hSearch == INVALID_HANDLE_VALUE)
462 (void) strcat(file_specification,"\\*.*");
463 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
464 if (entry->hSearch == INVALID_HANDLE_VALUE)
466 LT_DLFREE (entry);
467 return (DIR *) 0;
470 return(entry);
474 static struct dirent *readdir LT_PARAMS((DIR *entry));
476 static struct dirent *readdir(entry)
477 DIR *entry;
480 status;
482 if (entry == (DIR *) 0)
483 return((struct dirent *) 0);
484 if (!entry->firsttime)
486 status = FindNextFile(entry->hSearch,&entry->Win32FindData);
487 if (status == 0)
488 return((struct dirent *) 0);
490 entry->firsttime = FALSE;
491 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
492 LT_FILENAME_MAX-1);
493 entry->file_info.d_namlen = strlen(entry->file_info.d_name);
494 return(&entry->file_info);
497 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
499 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
500 ``realloc is not entirely portable''
501 In any case we want to use the allocator supplied by the user without
502 burdening them with an lt_dlrealloc function pointer to maintain.
503 Instead implement our own version (with known boundary conditions)
504 using lt_dlmalloc and lt_dlfree. */
506 /* #undef realloc
507 #define realloc rpl_realloc
509 #if 0
510 /* You can't (re)define realloc unless you also (re)define malloc.
511 Right now, this code uses the size of the *destination* to decide
512 how much to copy. That's not right, but you can't know the size
513 of the source unless you know enough about, or wrote malloc. So
514 this code is disabled... */
516 static lt_ptr
517 realloc (ptr, size)
518 lt_ptr ptr;
519 size_t size;
521 if (size == 0)
523 /* For zero or less bytes, free the original memory */
524 if (ptr != 0)
526 lt_dlfree (ptr);
529 return (lt_ptr) 0;
531 else if (ptr == 0)
533 /* Allow reallocation of a NULL pointer. */
534 return lt_dlmalloc (size);
536 else
538 /* Allocate a new block, copy and free the old block. */
539 lt_ptr mem = lt_dlmalloc (size);
541 if (mem)
543 memcpy (mem, ptr, size);
544 lt_dlfree (ptr);
547 /* Note that the contents of PTR are not damaged if there is
548 insufficient memory to realloc. */
549 return mem;
552 #endif
555 #if ! HAVE_ARGZ_APPEND
556 # define argz_append rpl_argz_append
558 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
559 const char *buf, size_t buf_len));
561 static error_t
562 argz_append (pargz, pargz_len, buf, buf_len)
563 char **pargz;
564 size_t *pargz_len;
565 const char *buf;
566 size_t buf_len;
568 size_t argz_len;
569 char *argz;
571 assert (pargz);
572 assert (pargz_len);
573 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
575 /* If nothing needs to be appended, no more work is required. */
576 if (buf_len == 0)
577 return 0;
579 /* Ensure there is enough room to append BUF_LEN. */
580 argz_len = *pargz_len + buf_len;
581 argz = LT_DLREALLOC (char, *pargz, argz_len);
582 if (!argz)
583 return ENOMEM;
585 /* Copy characters from BUF after terminating '\0' in ARGZ. */
586 memcpy (argz + *pargz_len, buf, buf_len);
588 /* Assign new values. */
589 *pargz = argz;
590 *pargz_len = argz_len;
592 return 0;
594 #endif /* !HAVE_ARGZ_APPEND */
597 #if ! HAVE_ARGZ_CREATE_SEP
598 # define argz_create_sep rpl_argz_create_sep
600 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
601 char **pargz, size_t *pargz_len));
603 static error_t
604 argz_create_sep (str, delim, pargz, pargz_len)
605 const char *str;
606 int delim;
607 char **pargz;
608 size_t *pargz_len;
610 size_t argz_len;
611 char *argz = 0;
613 assert (str);
614 assert (pargz);
615 assert (pargz_len);
617 /* Make a copy of STR, but replacing each occurence of
618 DELIM with '\0'. */
619 argz_len = 1+ LT_STRLEN (str);
620 if (argz_len)
622 const char *p;
623 char *q;
625 argz = LT_DLMALLOC (char, argz_len);
626 if (!argz)
627 return ENOMEM;
629 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
631 if (*p == delim)
633 /* Ignore leading delimiters, and fold consecutive
634 delimiters in STR into a single '\0' in ARGZ. */
635 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
636 *q++ = LT_EOS_CHAR;
637 else
638 --argz_len;
640 else
641 *q++ = *p;
643 /* Copy terminating LT_EOS_CHAR. */
644 *q = *p;
647 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
648 if (!argz_len)
649 LT_DLFREE (argz);
651 /* Assign new values. */
652 *pargz = argz;
653 *pargz_len = argz_len;
655 return 0;
657 #endif /* !HAVE_ARGZ_CREATE_SEP */
660 #if ! HAVE_ARGZ_INSERT
661 # define argz_insert rpl_argz_insert
663 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
664 char *before, const char *entry));
666 static error_t
667 argz_insert (pargz, pargz_len, before, entry)
668 char **pargz;
669 size_t *pargz_len;
670 char *before;
671 const char *entry;
673 assert (pargz);
674 assert (pargz_len);
675 assert (entry && *entry);
677 /* No BEFORE address indicates ENTRY should be inserted after the
678 current last element. */
679 if (!before)
680 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
682 /* This probably indicates a programmer error, but to preserve
683 semantics, scan back to the start of an entry if BEFORE points
684 into the middle of it. */
685 while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
686 --before;
689 size_t entry_len = 1+ LT_STRLEN (entry);
690 size_t argz_len = *pargz_len + entry_len;
691 size_t offset = before - *pargz;
692 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
694 if (!argz)
695 return ENOMEM;
697 /* Make BEFORE point to the equivalent offset in ARGZ that it
698 used to have in *PARGZ incase realloc() moved the block. */
699 before = argz + offset;
701 /* Move the ARGZ entries starting at BEFORE up into the new
702 space at the end -- making room to copy ENTRY into the
703 resulting gap. */
704 memmove (before + entry_len, before, *pargz_len - offset);
705 memcpy (before, entry, entry_len);
707 /* Assign new values. */
708 *pargz = argz;
709 *pargz_len = argz_len;
712 return 0;
714 #endif /* !HAVE_ARGZ_INSERT */
717 #if ! HAVE_ARGZ_NEXT
718 # define argz_next rpl_argz_next
720 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
721 const char *entry));
723 static char *
724 argz_next (argz, argz_len, entry)
725 char *argz;
726 size_t argz_len;
727 const char *entry;
729 assert ((argz && argz_len) || (!argz && !argz_len));
731 if (entry)
733 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
734 within the ARGZ vector. */
735 assert ((!argz && !argz_len)
736 || ((argz <= entry) && (entry < (argz + argz_len))));
738 /* Move to the char immediately after the terminating
739 '\0' of ENTRY. */
740 entry = 1+ strchr (entry, LT_EOS_CHAR);
742 /* Return either the new ENTRY, or else NULL if ARGZ is
743 exhausted. */
744 return (entry >= argz + argz_len) ? 0 : (char *) entry;
746 else
748 /* This should probably be flagged as a programmer error,
749 since starting an argz_next loop with the iterator set
750 to ARGZ is safer. To preserve semantics, handle the NULL
751 case by returning the start of ARGZ (if any). */
752 if (argz_len > 0)
753 return argz;
754 else
755 return 0;
758 #endif /* !HAVE_ARGZ_NEXT */
762 #if ! HAVE_ARGZ_STRINGIFY
763 # define argz_stringify rpl_argz_stringify
765 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
766 int sep));
768 static void
769 argz_stringify (argz, argz_len, sep)
770 char *argz;
771 size_t argz_len;
772 int sep;
774 assert ((argz && argz_len) || (!argz && !argz_len));
776 if (sep)
778 --argz_len; /* don't stringify the terminating EOS */
779 while (--argz_len > 0)
781 if (argz[argz_len] == LT_EOS_CHAR)
782 argz[argz_len] = sep;
786 #endif /* !HAVE_ARGZ_STRINGIFY */
791 /* --- TYPE DEFINITIONS -- */
794 /* This type is used for the array of caller data sets in each handler. */
795 typedef struct {
796 lt_dlcaller_id key;
797 lt_ptr data;
798 } lt_caller_data;
803 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
806 /* Extract the diagnostic strings from the error table macro in the same
807 order as the enumerated indices in ltdl.h. */
809 static const char *lt_dlerror_strings[] =
811 #define LT_ERROR(name, diagnostic) (diagnostic),
812 lt_dlerror_table
813 #undef LT_ERROR
818 /* This structure is used for the list of registered loaders. */
819 struct lt_dlloader {
820 struct lt_dlloader *next;
821 const char *loader_name; /* identifying name for each loader */
822 const char *sym_prefix; /* prefix for symbols */
823 lt_module_open *module_open;
824 lt_module_close *module_close;
825 lt_find_sym *find_sym;
826 lt_dlloader_exit *dlloader_exit;
827 lt_user_data dlloader_data;
830 struct lt_dlhandle_struct {
831 struct lt_dlhandle_struct *next;
832 lt_dlloader *loader; /* dlopening interface */
833 lt_dlinfo info;
834 int depcount; /* number of dependencies */
835 lt_dlhandle *deplibs; /* dependencies */
836 lt_module module; /* system module handle */
837 lt_ptr system; /* system specific data */
838 lt_caller_data *caller_data; /* per caller associated data */
839 int flags; /* various boolean stats */
842 /* Various boolean flags can be stored in the flags field of an
843 lt_dlhandle_struct... */
844 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
845 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
847 #define LT_DLRESIDENT_FLAG (0x01 << 0)
848 /* ...add more flags here... */
850 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
853 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
855 static const char objdir[] = LTDL_OBJDIR;
856 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
857 #ifdef LTDL_SHLIB_EXT
858 static const char shlib_ext[] = LTDL_SHLIB_EXT;
859 #endif
860 #ifdef LTDL_SYSSEARCHPATH
861 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
862 #endif
867 /* --- MUTEX LOCKING --- */
870 /* Macros to make it easier to run the lock functions only if they have
871 been registered. The reason for the complicated lock macro is to
872 ensure that the stored error message from the last error is not
873 accidentally erased if the current function doesn't generate an
874 error of its own. */
875 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
876 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
877 } LT_STMT_END
878 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
879 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
880 } LT_STMT_END
881 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
882 if (lt_dlmutex_seterror_func) \
883 (*lt_dlmutex_seterror_func) (errormsg); \
884 else lt_dllast_error = (errormsg); } LT_STMT_END
885 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
886 if (lt_dlmutex_seterror_func) \
887 (errormsg) = (*lt_dlmutex_geterror_func) (); \
888 else (errormsg) = lt_dllast_error; } LT_STMT_END
890 /* The mutex functions stored here are global, and are necessarily the
891 same for all threads that wish to share access to libltdl. */
892 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
893 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
894 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
895 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
896 static const char *lt_dllast_error = 0;
899 /* Either set or reset the mutex functions. Either all the arguments must
900 be valid functions, or else all can be NULL to turn off locking entirely.
901 The registered functions should be manipulating a static global lock
902 from the lock() and unlock() callbacks, which needs to be reentrant. */
904 lt_dlmutex_register (lock, unlock, seterror, geterror)
905 lt_dlmutex_lock *lock;
906 lt_dlmutex_unlock *unlock;
907 lt_dlmutex_seterror *seterror;
908 lt_dlmutex_geterror *geterror;
910 lt_dlmutex_unlock *old_unlock = unlock;
911 int errors = 0;
913 /* Lock using the old lock() callback, if any. */
914 LT_DLMUTEX_LOCK ();
916 if ((lock && unlock && seterror && geterror)
917 || !(lock || unlock || seterror || geterror))
919 lt_dlmutex_lock_func = lock;
920 lt_dlmutex_unlock_func = unlock;
921 lt_dlmutex_geterror_func = geterror;
923 else
925 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
926 ++errors;
929 /* Use the old unlock() callback we saved earlier, if any. Otherwise
930 record any errors using internal storage. */
931 if (old_unlock)
932 (*old_unlock) ();
934 /* Return the number of errors encountered during the execution of
935 this function. */
936 return errors;
942 /* --- ERROR HANDLING --- */
945 static const char **user_error_strings = 0;
946 static int errorcount = LT_ERROR_MAX;
949 lt_dladderror (diagnostic)
950 const char *diagnostic;
952 int errindex = 0;
953 int result = -1;
954 const char **temp = (const char **) 0;
956 assert (diagnostic);
958 LT_DLMUTEX_LOCK ();
960 errindex = errorcount - LT_ERROR_MAX;
961 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
962 if (temp)
964 user_error_strings = temp;
965 user_error_strings[errindex] = diagnostic;
966 result = errorcount++;
969 LT_DLMUTEX_UNLOCK ();
971 return result;
975 lt_dlseterror (errindex)
976 int errindex;
978 int errors = 0;
980 LT_DLMUTEX_LOCK ();
982 if (errindex >= errorcount || errindex < 0)
984 /* Ack! Error setting the error message! */
985 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
986 ++errors;
988 else if (errindex < LT_ERROR_MAX)
990 /* No error setting the error message! */
991 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
993 else
995 /* No error setting the error message! */
996 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
999 LT_DLMUTEX_UNLOCK ();
1001 return errors;
1004 static lt_ptr
1005 lt_emalloc (size)
1006 size_t size;
1008 lt_ptr mem = lt_dlmalloc (size);
1009 if (size && !mem)
1010 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1011 return mem;
1014 static lt_ptr
1015 lt_erealloc (addr, size)
1016 lt_ptr addr;
1017 size_t size;
1019 lt_ptr mem = realloc (addr, size);
1020 if (size && !mem)
1021 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1022 return mem;
1025 static char *
1026 lt_estrdup (str)
1027 const char *str;
1029 char *copy = strdup (str);
1030 if (LT_STRLEN (str) && !copy)
1031 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1032 return copy;
1038 /* --- DLOPEN() INTERFACE LOADER --- */
1041 #if HAVE_LIBDL
1043 /* dynamic linking with dlopen/dlsym */
1045 #if HAVE_DLFCN_H
1046 # include <dlfcn.h>
1047 #endif
1049 #if HAVE_SYS_DL_H
1050 # include <sys/dl.h>
1051 #endif
1053 #ifdef RTLD_GLOBAL
1054 # define LT_GLOBAL RTLD_GLOBAL
1055 #else
1056 # ifdef DL_GLOBAL
1057 # define LT_GLOBAL DL_GLOBAL
1058 # endif
1059 #endif /* !RTLD_GLOBAL */
1060 #ifndef LT_GLOBAL
1061 # define LT_GLOBAL 0
1062 #endif /* !LT_GLOBAL */
1064 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1065 find out it does not work in some platform. */
1066 #ifndef LT_LAZY_OR_NOW
1067 # ifdef RTLD_LAZY
1068 # define LT_LAZY_OR_NOW RTLD_LAZY
1069 # else
1070 # ifdef DL_LAZY
1071 # define LT_LAZY_OR_NOW DL_LAZY
1072 # endif
1073 # endif /* !RTLD_LAZY */
1074 #endif
1075 #ifndef LT_LAZY_OR_NOW
1076 # ifdef RTLD_NOW
1077 # define LT_LAZY_OR_NOW RTLD_NOW
1078 # else
1079 # ifdef DL_NOW
1080 # define LT_LAZY_OR_NOW DL_NOW
1081 # endif
1082 # endif /* !RTLD_NOW */
1083 #endif
1084 #ifndef LT_LAZY_OR_NOW
1085 # define LT_LAZY_OR_NOW 0
1086 #endif /* !LT_LAZY_OR_NOW */
1088 #if HAVE_DLERROR
1089 # define DLERROR(arg) dlerror ()
1090 #else
1091 # define DLERROR(arg) LT_DLSTRERROR (arg)
1092 #endif
1094 static lt_module
1095 sys_dl_open (loader_data, filename)
1096 lt_user_data loader_data;
1097 const char *filename;
1099 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1101 if (!module)
1103 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1106 return module;
1109 static int
1110 sys_dl_close (loader_data, module)
1111 lt_user_data loader_data;
1112 lt_module module;
1114 int errors = 0;
1116 if (dlclose (module) != 0)
1118 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1119 ++errors;
1122 return errors;
1125 static lt_ptr
1126 sys_dl_sym (loader_data, module, symbol)
1127 lt_user_data loader_data;
1128 lt_module module;
1129 const char *symbol;
1131 lt_ptr address = dlsym (module, symbol);
1133 if (!address)
1135 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1138 return address;
1141 static struct lt_user_dlloader sys_dl =
1143 # ifdef NEED_USCORE
1144 "_",
1145 # else
1147 # endif
1148 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1151 #endif /* HAVE_LIBDL */
1155 /* --- SHL_LOAD() INTERFACE LOADER --- */
1157 #if HAVE_SHL_LOAD
1159 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1161 #ifdef HAVE_DL_H
1162 # include <dl.h>
1163 #endif
1165 /* some flags are missing on some systems, so we provide
1166 * harmless defaults.
1168 * Mandatory:
1169 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1170 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1172 * Optionally:
1173 * BIND_FIRST - Place the library at the head of the symbol search
1174 * order.
1175 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1176 * unsatisfied symbols as fatal. This flag allows
1177 * binding of unsatisfied code symbols to be deferred
1178 * until use.
1179 * [Perl: For certain libraries, like DCE, deferred
1180 * binding often causes run time problems. Adding
1181 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1182 * unresolved references in situations like this.]
1183 * BIND_NOSTART - Do not call the initializer for the shared library
1184 * when the library is loaded, nor on a future call to
1185 * shl_unload().
1186 * BIND_VERBOSE - Print verbose messages concerning possible
1187 * unsatisfied symbols.
1189 * hp9000s700/hp9000s800:
1190 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1191 * present at library load time.
1192 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1193 * library specified by the path argument.
1196 #ifndef DYNAMIC_PATH
1197 # define DYNAMIC_PATH 0
1198 #endif
1199 #ifndef BIND_RESTRICTED
1200 # define BIND_RESTRICTED 0
1201 #endif
1203 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1205 static lt_module
1206 sys_shl_open (loader_data, filename)
1207 lt_user_data loader_data;
1208 const char *filename;
1210 static shl_t self = (shl_t) 0;
1211 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1213 /* Since searching for a symbol against a NULL module handle will also
1214 look in everything else that was already loaded and exported with
1215 the -E compiler flag, we always cache a handle saved before any
1216 modules are loaded. */
1217 if (!self)
1219 lt_ptr address;
1220 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1223 if (!filename)
1225 module = self;
1227 else
1229 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1231 if (!module)
1233 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1237 return module;
1240 static int
1241 sys_shl_close (loader_data, module)
1242 lt_user_data loader_data;
1243 lt_module module;
1245 int errors = 0;
1247 if (module && (shl_unload ((shl_t) (module)) != 0))
1249 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1250 ++errors;
1253 return errors;
1256 static lt_ptr
1257 sys_shl_sym (loader_data, module, symbol)
1258 lt_user_data loader_data;
1259 lt_module module;
1260 const char *symbol;
1262 lt_ptr address = 0;
1264 /* sys_shl_open should never return a NULL module handle */
1265 if (module == (lt_module) 0)
1267 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1269 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1271 if (!address)
1273 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1277 return address;
1280 static struct lt_user_dlloader sys_shl = {
1281 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1284 #endif /* HAVE_SHL_LOAD */
1289 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1291 #ifdef __WINDOWS__
1293 /* dynamic linking for Win32 */
1295 #include <windows.h>
1297 /* Forward declaration; required to implement handle search below. */
1298 static lt_dlhandle handles;
1300 static lt_module
1301 sys_wll_open (loader_data, filename)
1302 lt_user_data loader_data;
1303 const char *filename;
1305 lt_dlhandle cur;
1306 lt_module module = 0;
1307 const char *errormsg = 0;
1308 char *searchname = 0;
1309 char *ext;
1310 char self_name_buf[MAX_PATH];
1312 if (!filename)
1314 /* Get the name of main module */
1315 *self_name_buf = 0;
1316 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1317 filename = ext = self_name_buf;
1319 else
1321 ext = strrchr (filename, '.');
1324 if (ext)
1326 /* FILENAME already has an extension. */
1327 searchname = lt_estrdup (filename);
1329 else
1331 /* Append a `.' to stop Windows from adding an
1332 implicit `.dll' extension. */
1333 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1334 if (searchname)
1335 sprintf (searchname, "%s.", filename);
1337 if (!searchname)
1338 return 0;
1340 #if __CYGWIN__
1342 char wpath[MAX_PATH];
1343 cygwin_conv_to_full_win32_path(searchname, wpath);
1344 module = LoadLibrary(wpath);
1346 #else
1347 module = LoadLibrary (searchname);
1348 #endif
1349 LT_DLFREE (searchname);
1351 /* libltdl expects this function to fail if it is unable
1352 to physically load the library. Sadly, LoadLibrary
1353 will search the loaded libraries for a match and return
1354 one of them if the path search load fails.
1356 We check whether LoadLibrary is returning a handle to
1357 an already loaded module, and simulate failure if we
1358 find one. */
1359 LT_DLMUTEX_LOCK ();
1360 cur = handles;
1361 while (cur)
1363 if (!cur->module)
1365 cur = 0;
1366 break;
1369 if (cur->module == module)
1371 break;
1374 cur = cur->next;
1376 LT_DLMUTEX_UNLOCK ();
1378 if (cur || !module)
1380 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1381 module = 0;
1384 return module;
1387 static int
1388 sys_wll_close (loader_data, module)
1389 lt_user_data loader_data;
1390 lt_module module;
1392 int errors = 0;
1394 if (FreeLibrary(module) == 0)
1396 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1397 ++errors;
1400 return errors;
1403 static lt_ptr
1404 sys_wll_sym (loader_data, module, symbol)
1405 lt_user_data loader_data;
1406 lt_module module;
1407 const char *symbol;
1409 lt_ptr address = GetProcAddress (module, symbol);
1411 if (!address)
1413 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1416 return address;
1419 static struct lt_user_dlloader sys_wll = {
1420 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1423 #endif /* __WINDOWS__ */
1428 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1431 #ifdef __BEOS__
1433 /* dynamic linking for BeOS */
1435 #include <kernel/image.h>
1437 static lt_module
1438 sys_bedl_open (loader_data, filename)
1439 lt_user_data loader_data;
1440 const char *filename;
1442 image_id image = 0;
1444 if (filename)
1446 image = load_add_on (filename);
1448 else
1450 image_info info;
1451 int32 cookie = 0;
1452 if (get_next_image_info (0, &cookie, &info) == B_OK)
1453 image = load_add_on (info.name);
1456 if (image <= 0)
1458 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1459 image = 0;
1462 return (lt_module) image;
1465 static int
1466 sys_bedl_close (loader_data, module)
1467 lt_user_data loader_data;
1468 lt_module module;
1470 int errors = 0;
1472 if (unload_add_on ((image_id) module) != B_OK)
1474 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1475 ++errors;
1478 return errors;
1481 static lt_ptr
1482 sys_bedl_sym (loader_data, module, symbol)
1483 lt_user_data loader_data;
1484 lt_module module;
1485 const char *symbol;
1487 lt_ptr address = 0;
1488 image_id image = (image_id) module;
1490 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1492 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1493 address = 0;
1496 return address;
1499 static struct lt_user_dlloader sys_bedl = {
1500 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1503 #endif /* __BEOS__ */
1508 /* --- DLD_LINK() INTERFACE LOADER --- */
1511 #if HAVE_DLD
1513 /* dynamic linking with dld */
1515 #if HAVE_DLD_H
1516 #include <dld.h>
1517 #endif
1519 static lt_module
1520 sys_dld_open (loader_data, filename)
1521 lt_user_data loader_data;
1522 const char *filename;
1524 lt_module module = strdup (filename);
1526 if (dld_link (filename) != 0)
1528 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1529 LT_DLFREE (module);
1530 module = 0;
1533 return module;
1536 static int
1537 sys_dld_close (loader_data, module)
1538 lt_user_data loader_data;
1539 lt_module module;
1541 int errors = 0;
1543 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1545 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1546 ++errors;
1548 else
1550 LT_DLFREE (module);
1553 return errors;
1556 static lt_ptr
1557 sys_dld_sym (loader_data, module, symbol)
1558 lt_user_data loader_data;
1559 lt_module module;
1560 const char *symbol;
1562 lt_ptr address = dld_get_func (symbol);
1564 if (!address)
1566 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1569 return address;
1572 static struct lt_user_dlloader sys_dld = {
1573 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1576 #endif /* HAVE_DLD */
1578 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1579 #if HAVE_DYLD
1582 #if HAVE_MACH_O_DYLD_H
1583 # include <mach-o/dyld.h>
1584 #endif
1585 #include <mach-o/getsect.h>
1587 /* We have to put some stuff here that isn't in older dyld.h files */
1588 #ifndef ENUM_DYLD_BOOL
1589 # define ENUM_DYLD_BOOL
1590 # undef FALSE
1591 # undef TRUE
1592 enum DYLD_BOOL {
1593 FALSE,
1594 TRUE
1596 #endif
1597 #ifndef LC_REQ_DYLD
1598 # define LC_REQ_DYLD 0x80000000
1599 #endif
1600 #ifndef LC_LOAD_WEAK_DYLIB
1601 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1602 #endif
1603 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1604 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1605 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1606 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1608 #ifndef NSADDIMAGE_OPTION_NONE
1609 #define NSADDIMAGE_OPTION_NONE 0x0
1610 #endif
1611 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1612 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1613 #endif
1614 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1615 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1616 #endif
1617 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1618 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1619 #endif
1620 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1621 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1622 #endif
1623 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1624 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1625 #endif
1626 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1627 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1628 #endif
1629 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1630 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1631 #endif
1632 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1633 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1634 #endif
1637 static const char *
1638 lt_int_dyld_error(othererror)
1639 char* othererror;
1641 /* return the dyld error string, or the passed in error string if none */
1642 NSLinkEditErrors ler;
1643 int lerno;
1644 const char *errstr;
1645 const char *file;
1646 NSLinkEditError(&ler,&lerno,&file,&errstr);
1647 if (!errstr || !strlen(errstr)) errstr = othererror;
1648 return errstr;
1651 static const struct mach_header *
1652 lt_int_dyld_get_mach_header_from_nsmodule(module)
1653 NSModule module;
1655 /* There should probably be an apple dyld api for this */
1656 int i=_dyld_image_count();
1657 int j;
1658 const char *modname=NSNameOfModule(module);
1659 const struct mach_header *mh=NULL;
1660 if (!modname) return NULL;
1661 for (j = 0; j < i; j++)
1663 if (!strcmp(_dyld_get_image_name(j),modname))
1665 mh=_dyld_get_image_header(j);
1666 break;
1669 return mh;
1672 static const char* lt_int_dyld_lib_install_name(mh)
1673 const struct mach_header *mh;
1675 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1676 is installed, for uninstalled libs we need to check the install_names against
1677 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1678 different lib was loaded as a result
1680 int j;
1681 struct load_command *lc;
1682 unsigned long offset = sizeof(struct mach_header);
1683 const struct mach_header *mh1;
1684 const char* retStr=NULL;
1685 for (j = 0; j < mh->ncmds; j++)
1687 lc = (struct load_command*)(((unsigned long)mh) + offset);
1688 if (LC_ID_DYLIB == lc->cmd)
1690 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1691 (unsigned long)lc);
1693 offset += lc->cmdsize;
1695 return retStr;
1698 static const struct mach_header *
1699 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1701 int i=_dyld_image_count();
1702 int j;
1703 const struct mach_header *mh=NULL;
1704 const char *id=NULL;
1705 for (j = 0; j < i; j++)
1707 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1708 if ((id) && (!strcmp(id,name)))
1710 mh=_dyld_get_image_header(j);
1711 break;
1714 return mh;
1717 static NSSymbol
1718 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1719 const char *symbol;
1720 const struct mach_header *mh;
1722 /* Safe to assume our mh is good */
1723 int j;
1724 struct load_command *lc;
1725 unsigned long offset = sizeof(struct mach_header);
1726 NSSymbol retSym = 0;
1727 const struct mach_header *mh1;
1728 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1730 for (j = 0; j < mh->ncmds; j++)
1732 lc = (struct load_command*)(((unsigned long)mh) + offset);
1733 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1735 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1736 (unsigned long)lc));
1737 if (!mh1)
1739 /* Maybe NSAddImage can find it */
1740 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1741 (unsigned long)lc),
1742 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1743 NSADDIMAGE_OPTION_WITH_SEARCHING +
1744 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1746 if (mh1)
1748 retSym = ltdl_NSLookupSymbolInImage(mh1,
1749 symbol,
1750 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1751 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1753 if (retSym) break;
1756 offset += lc->cmdsize;
1759 return retSym;
1762 static int
1763 sys_dyld_init()
1765 int retCode = 0;
1766 int err = 0;
1767 if (!_dyld_present()) {
1768 retCode=1;
1770 else {
1771 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1772 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1773 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1774 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1776 return retCode;
1779 static lt_module
1780 sys_dyld_open (loader_data, filename)
1781 lt_user_data loader_data;
1782 const char *filename;
1784 lt_module module = 0;
1785 NSObjectFileImage ofi = 0;
1786 NSObjectFileImageReturnCode ofirc;
1788 if (!filename)
1789 return (lt_module)-1;
1790 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1791 switch (ofirc)
1793 case NSObjectFileImageSuccess:
1794 module = NSLinkModule(ofi, filename,
1795 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1796 | NSLINKMODULE_OPTION_PRIVATE
1797 | NSLINKMODULE_OPTION_BINDNOW);
1798 NSDestroyObjectFileImage(ofi);
1799 if (module)
1800 ltdl_NSMakePrivateModulePublic(module);
1801 break;
1802 case NSObjectFileImageInappropriateFile:
1803 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1805 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1806 break;
1808 default:
1809 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1810 return 0;
1812 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1813 return module;
1816 static int
1817 sys_dyld_close (loader_data, module)
1818 lt_user_data loader_data;
1819 lt_module module;
1821 int retCode = 0;
1822 int flags = 0;
1823 unsigned long size=0;
1824 if (module == (lt_module)-1) return 0;
1825 #ifdef __BIG_ENDIAN__
1826 if (((struct mach_header *)module)->magic == MH_MAGIC)
1827 #else
1828 if (((struct mach_header *)module)->magic == MH_CIGAM)
1829 #endif
1831 LT_DLMUTEX_SETERROR("Can not close a dylib");
1832 retCode = 1;
1834 else
1836 #if 1
1837 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1838 get a segfault in atexit(), due to compiler and dynamic loader differences of
1839 opinion, this works around that.
1841 if ((const struct section *)NULL !=
1842 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1843 "__DATA","__mod_term_func"))
1845 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1847 #endif
1848 #ifdef __ppc__
1849 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1850 #endif
1851 if (!NSUnLinkModule(module,flags))
1853 retCode=1;
1854 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1858 return retCode;
1861 static lt_ptr
1862 sys_dyld_sym (loader_data, module, symbol)
1863 lt_user_data loader_data;
1864 lt_module module;
1865 const char *symbol;
1867 lt_ptr address = 0;
1868 NSSymbol *nssym = 0;
1869 void *unused;
1870 const struct mach_header *mh=NULL;
1871 if (module == (lt_module)-1)
1873 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1874 return address;
1876 #ifdef __BIG_ENDIAN__
1877 if (((struct mach_header *)module)->magic == MH_MAGIC)
1878 #else
1879 if (((struct mach_header *)module)->magic == MH_CIGAM)
1880 #endif
1882 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1884 mh=module;
1885 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1887 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1888 symbol,
1889 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1890 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1896 else {
1897 nssym = NSLookupSymbolInModule(module, symbol);
1899 if (!nssym)
1901 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1902 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1904 if (!nssym)
1906 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)));
1907 return NULL;
1909 return NSAddressOfSymbol(nssym);
1912 static struct lt_user_dlloader sys_dyld =
1913 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1916 #endif /* HAVE_DYLD */
1919 /* --- DLPREOPEN() INTERFACE LOADER --- */
1922 /* emulate dynamic linking using preloaded_symbols */
1924 typedef struct lt_dlsymlists_t
1926 struct lt_dlsymlists_t *next;
1927 const lt_dlsymlist *syms;
1928 } lt_dlsymlists_t;
1930 static const lt_dlsymlist *default_preloaded_symbols = 0;
1931 static lt_dlsymlists_t *preloaded_symbols = 0;
1933 static int
1934 presym_init (loader_data)
1935 lt_user_data loader_data;
1937 int errors = 0;
1939 LT_DLMUTEX_LOCK ();
1941 preloaded_symbols = 0;
1942 if (default_preloaded_symbols)
1944 errors = lt_dlpreload (default_preloaded_symbols);
1947 LT_DLMUTEX_UNLOCK ();
1949 return errors;
1952 static int
1953 presym_free_symlists ()
1955 lt_dlsymlists_t *lists;
1957 LT_DLMUTEX_LOCK ();
1959 lists = preloaded_symbols;
1960 while (lists)
1962 lt_dlsymlists_t *tmp = lists;
1964 lists = lists->next;
1965 LT_DLFREE (tmp);
1967 preloaded_symbols = 0;
1969 LT_DLMUTEX_UNLOCK ();
1971 return 0;
1974 static int
1975 presym_exit (loader_data)
1976 lt_user_data loader_data;
1978 presym_free_symlists ();
1979 return 0;
1982 static int
1983 presym_add_symlist (preloaded)
1984 const lt_dlsymlist *preloaded;
1986 lt_dlsymlists_t *tmp;
1987 lt_dlsymlists_t *lists;
1988 int errors = 0;
1990 LT_DLMUTEX_LOCK ();
1992 lists = preloaded_symbols;
1993 while (lists)
1995 if (lists->syms == preloaded)
1997 goto done;
1999 lists = lists->next;
2002 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2003 if (tmp)
2005 memset (tmp, 0, sizeof(lt_dlsymlists_t));
2006 tmp->syms = preloaded;
2007 tmp->next = preloaded_symbols;
2008 preloaded_symbols = tmp;
2010 else
2012 ++errors;
2015 done:
2016 LT_DLMUTEX_UNLOCK ();
2017 return errors;
2020 static lt_module
2021 presym_open (loader_data, filename)
2022 lt_user_data loader_data;
2023 const char *filename;
2025 lt_dlsymlists_t *lists;
2026 lt_module module = (lt_module) 0;
2028 LT_DLMUTEX_LOCK ();
2029 lists = preloaded_symbols;
2031 if (!lists)
2033 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2034 goto done;
2037 /* Can't use NULL as the reflective symbol header, as NULL is
2038 used to mark the end of the entire symbol list. Self-dlpreopened
2039 symbols follow this magic number, chosen to be an unlikely
2040 clash with a real module name. */
2041 if (!filename)
2043 filename = "@PROGRAM@";
2046 while (lists)
2048 const lt_dlsymlist *syms = lists->syms;
2050 while (syms->name)
2052 if (!syms->address && strcmp(syms->name, filename) == 0)
2054 module = (lt_module) syms;
2055 goto done;
2057 ++syms;
2060 lists = lists->next;
2063 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2065 done:
2066 LT_DLMUTEX_UNLOCK ();
2067 return module;
2070 static int
2071 presym_close (loader_data, module)
2072 lt_user_data loader_data;
2073 lt_module module;
2075 /* Just to silence gcc -Wall */
2076 module = 0;
2077 return 0;
2080 static lt_ptr
2081 presym_sym (loader_data, module, symbol)
2082 lt_user_data loader_data;
2083 lt_module module;
2084 const char *symbol;
2086 lt_dlsymlist *syms = (lt_dlsymlist*) module;
2088 ++syms;
2089 while (syms->address)
2091 if (strcmp(syms->name, symbol) == 0)
2093 return syms->address;
2096 ++syms;
2099 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2101 return 0;
2104 static struct lt_user_dlloader presym = {
2105 0, presym_open, presym_close, presym_sym, presym_exit, 0
2112 /* --- DYNAMIC MODULE LOADING --- */
2115 /* The type of a function used at each iteration of foreach_dirinpath(). */
2116 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2117 lt_ptr data2));
2119 static int foreach_dirinpath LT_PARAMS((const char *search_path,
2120 const char *base_name,
2121 foreach_callback_func *func,
2122 lt_ptr data1, lt_ptr data2));
2124 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2125 lt_ptr ignored));
2126 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2127 lt_ptr ignored));
2128 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2129 lt_ptr data2));
2132 static int canonicalize_path LT_PARAMS((const char *path,
2133 char **pcanonical));
2134 static int argzize_path LT_PARAMS((const char *path,
2135 char **pargz,
2136 size_t *pargz_len));
2137 static FILE *find_file LT_PARAMS((const char *search_path,
2138 const char *base_name,
2139 char **pdir));
2140 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2141 const char *base_name,
2142 lt_dlhandle *handle));
2143 static int find_module LT_PARAMS((lt_dlhandle *handle,
2144 const char *dir,
2145 const char *libdir,
2146 const char *dlname,
2147 const char *old_name,
2148 int installed));
2149 static int free_vars LT_PARAMS((char *dlname, char *oldname,
2150 char *libdir, char *deplibs));
2151 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2152 char *deplibs));
2153 static int trim LT_PARAMS((char **dest,
2154 const char *str));
2155 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2156 const char *filename));
2157 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2158 const char *filename));
2159 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2160 static int lt_argz_insert LT_PARAMS((char **pargz,
2161 size_t *pargz_len,
2162 char *before,
2163 const char *entry));
2164 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2165 size_t *pargz_len,
2166 const char *entry));
2167 static int lt_argz_insertdir LT_PARAMS((char **pargz,
2168 size_t *pargz_len,
2169 const char *dirnam,
2170 struct dirent *dp));
2171 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2172 char *before,
2173 const char *dir));
2174 static int list_files_by_dir LT_PARAMS((const char *dirnam,
2175 char **pargz,
2176 size_t *pargz_len));
2177 static int file_not_found LT_PARAMS((void));
2179 static char *user_search_path= 0;
2180 static lt_dlloader *loaders = 0;
2181 static lt_dlhandle handles = 0;
2182 static int initialized = 0;
2184 /* Initialize libltdl. */
2186 lt_dlinit ()
2188 int errors = 0;
2190 LT_DLMUTEX_LOCK ();
2192 /* Initialize only at first call. */
2193 if (++initialized == 1)
2195 handles = 0;
2196 user_search_path = 0; /* empty search path */
2198 #if HAVE_LIBDL
2199 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2200 #endif
2201 #if HAVE_SHL_LOAD
2202 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2203 #endif
2204 #ifdef __WINDOWS__
2205 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2206 #endif
2207 #ifdef __BEOS__
2208 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2209 #endif
2210 #if HAVE_DLD
2211 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2212 #endif
2213 #if HAVE_DYLD
2214 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2215 errors += sys_dyld_init();
2216 #endif
2217 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2219 if (presym_init (presym.dlloader_data))
2221 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2222 ++errors;
2224 else if (errors != 0)
2226 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2227 ++errors;
2231 LT_DLMUTEX_UNLOCK ();
2233 return errors;
2237 lt_dlpreload (preloaded)
2238 const lt_dlsymlist *preloaded;
2240 int errors = 0;
2242 if (preloaded)
2244 errors = presym_add_symlist (preloaded);
2246 else
2248 presym_free_symlists();
2250 LT_DLMUTEX_LOCK ();
2251 if (default_preloaded_symbols)
2253 errors = lt_dlpreload (default_preloaded_symbols);
2255 LT_DLMUTEX_UNLOCK ();
2258 return errors;
2262 lt_dlpreload_default (preloaded)
2263 const lt_dlsymlist *preloaded;
2265 LT_DLMUTEX_LOCK ();
2266 default_preloaded_symbols = preloaded;
2267 LT_DLMUTEX_UNLOCK ();
2268 return 0;
2272 lt_dlexit ()
2274 /* shut down libltdl */
2275 lt_dlloader *loader;
2276 int errors = 0;
2278 LT_DLMUTEX_LOCK ();
2279 loader = loaders;
2281 if (!initialized)
2283 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2284 ++errors;
2285 goto done;
2288 /* shut down only at last call. */
2289 if (--initialized == 0)
2291 int level;
2293 while (handles && LT_DLIS_RESIDENT (handles))
2295 handles = handles->next;
2298 /* close all modules */
2299 for (level = 1; handles; ++level)
2301 lt_dlhandle cur = handles;
2302 int saw_nonresident = 0;
2304 while (cur)
2306 lt_dlhandle tmp = cur;
2307 cur = cur->next;
2308 if (!LT_DLIS_RESIDENT (tmp))
2309 saw_nonresident = 1;
2310 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2312 if (lt_dlclose (tmp))
2314 ++errors;
2318 /* done if only resident modules are left */
2319 if (!saw_nonresident)
2320 break;
2323 /* close all loaders */
2324 while (loader)
2326 lt_dlloader *next = loader->next;
2327 lt_user_data data = loader->dlloader_data;
2328 if (loader->dlloader_exit && loader->dlloader_exit (data))
2330 ++errors;
2333 LT_DLMEM_REASSIGN (loader, next);
2335 loaders = 0;
2338 done:
2339 LT_DLMUTEX_UNLOCK ();
2340 return errors;
2343 static int
2344 tryall_dlopen (handle, filename)
2345 lt_dlhandle *handle;
2346 const char *filename;
2348 lt_dlhandle cur;
2349 lt_dlloader *loader;
2350 const char *saved_error;
2351 int errors = 0;
2353 LT_DLMUTEX_GETERROR (saved_error);
2354 LT_DLMUTEX_LOCK ();
2356 cur = handles;
2357 loader = loaders;
2359 /* check whether the module was already opened */
2360 while (cur)
2362 /* try to dlopen the program itself? */
2363 if (!cur->info.filename && !filename)
2365 break;
2368 if (cur->info.filename && filename
2369 && strcmp (cur->info.filename, filename) == 0)
2371 break;
2374 cur = cur->next;
2377 if (cur)
2379 ++cur->info.ref_count;
2380 *handle = cur;
2381 goto done;
2384 cur = *handle;
2385 if (filename)
2387 /* Comment out the check of file permissions using access.
2388 This call seems to always return -1 with error EACCES.
2390 /* We need to catch missing file errors early so that
2391 file_not_found() can detect what happened.
2392 if (access (filename, R_OK) != 0)
2394 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2395 ++errors;
2396 goto done;
2397 } */
2399 cur->info.filename = lt_estrdup (filename);
2400 if (!cur->info.filename)
2402 ++errors;
2403 goto done;
2406 else
2408 cur->info.filename = 0;
2411 while (loader)
2413 lt_user_data data = loader->dlloader_data;
2415 cur->module = loader->module_open (data, filename);
2417 if (cur->module != 0)
2419 break;
2421 loader = loader->next;
2424 if (!loader)
2426 LT_DLFREE (cur->info.filename);
2427 ++errors;
2428 goto done;
2431 cur->loader = loader;
2432 LT_DLMUTEX_SETERROR (saved_error);
2434 done:
2435 LT_DLMUTEX_UNLOCK ();
2437 return errors;
2440 static int
2441 tryall_dlopen_module (handle, prefix, dirname, dlname)
2442 lt_dlhandle *handle;
2443 const char *prefix;
2444 const char *dirname;
2445 const char *dlname;
2447 int error = 0;
2448 char *filename = 0;
2449 size_t filename_len = 0;
2450 size_t dirname_len = LT_STRLEN (dirname);
2452 assert (handle);
2453 assert (dirname);
2454 assert (dlname);
2455 #ifdef LT_DIRSEP_CHAR
2456 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2457 should make it into this function: */
2458 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2459 #endif
2461 if (dirname_len > 0)
2462 if (dirname[dirname_len -1] == '/')
2463 --dirname_len;
2464 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2466 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2467 The PREFIX (if any) is handled below. */
2468 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2469 if (!filename)
2470 return 1;
2472 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2474 /* Now that we have combined DIRNAME and MODULENAME, if there is
2475 also a PREFIX to contend with, simply recurse with the arguments
2476 shuffled. Otherwise, attempt to open FILENAME as a module. */
2477 if (prefix)
2479 error += tryall_dlopen_module (handle,
2480 (const char *) 0, prefix, filename);
2482 else if (tryall_dlopen (handle, filename) != 0)
2484 ++error;
2487 LT_DLFREE (filename);
2488 return error;
2491 static int
2492 find_module (handle, dir, libdir, dlname, old_name, installed)
2493 lt_dlhandle *handle;
2494 const char *dir;
2495 const char *libdir;
2496 const char *dlname;
2497 const char *old_name;
2498 int installed;
2500 /* Try to open the old library first; if it was dlpreopened,
2501 we want the preopened version of it, even if a dlopenable
2502 module is available. */
2503 if (old_name && tryall_dlopen (handle, old_name) == 0)
2505 return 0;
2508 /* Try to open the dynamic library. */
2509 if (dlname)
2511 /* try to open the installed module */
2512 if (installed && libdir)
2514 if (tryall_dlopen_module (handle,
2515 (const char *) 0, libdir, dlname) == 0)
2516 return 0;
2519 /* try to open the not-installed module */
2520 if (!installed)
2522 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2523 return 0;
2526 /* maybe it was moved to another directory */
2528 if (tryall_dlopen_module (handle,
2529 (const char *) 0, dir, dlname) == 0)
2530 return 0;
2534 return 1;
2538 static int
2539 canonicalize_path (path, pcanonical)
2540 const char *path;
2541 char **pcanonical;
2543 char *canonical = 0;
2545 assert (path && *path);
2546 assert (pcanonical);
2548 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2549 if (!canonical)
2550 return 1;
2553 size_t dest = 0;
2554 size_t src;
2555 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2557 /* Path separators are not copied to the beginning or end of
2558 the destination, or if another separator would follow
2559 immediately. */
2560 if (path[src] == LT_PATHSEP_CHAR)
2562 if ((dest == 0)
2563 || (path[1+ src] == LT_PATHSEP_CHAR)
2564 || (path[1+ src] == LT_EOS_CHAR))
2565 continue;
2568 /* Anything other than a directory separator is copied verbatim. */
2569 if ((path[src] != '/')
2570 #ifdef LT_DIRSEP_CHAR
2571 && (path[src] != LT_DIRSEP_CHAR)
2572 #endif
2575 canonical[dest++] = path[src];
2577 /* Directory separators are converted and copied only if they are
2578 not at the end of a path -- i.e. before a path separator or
2579 NULL terminator. */
2580 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2581 && (path[1+ src] != LT_EOS_CHAR)
2582 #ifdef LT_DIRSEP_CHAR
2583 && (path[1+ src] != LT_DIRSEP_CHAR)
2584 #endif
2585 && (path[1+ src] != '/'))
2587 canonical[dest++] = '/';
2591 /* Add an end-of-string marker at the end. */
2592 canonical[dest] = LT_EOS_CHAR;
2595 /* Assign new value. */
2596 *pcanonical = canonical;
2598 return 0;
2601 static int
2602 argzize_path (path, pargz, pargz_len)
2603 const char *path;
2604 char **pargz;
2605 size_t *pargz_len;
2607 error_t error;
2609 assert (path);
2610 assert (pargz);
2611 assert (pargz_len);
2613 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2615 switch (error)
2617 case ENOMEM:
2618 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2619 break;
2620 default:
2621 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2622 break;
2625 return 1;
2628 return 0;
2631 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2632 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2633 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2634 it is appended to each SEARCH_PATH element before FUNC is called. */
2635 static int
2636 foreach_dirinpath (search_path, base_name, func, data1, data2)
2637 const char *search_path;
2638 const char *base_name;
2639 foreach_callback_func *func;
2640 lt_ptr data1;
2641 lt_ptr data2;
2643 int result = 0;
2644 int filenamesize = 0;
2645 size_t lenbase = LT_STRLEN (base_name);
2646 size_t argz_len = 0;
2647 char *argz = 0;
2648 char *filename = 0;
2649 char *canonical = 0;
2651 LT_DLMUTEX_LOCK ();
2653 if (!search_path || !*search_path)
2655 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2656 goto cleanup;
2659 if (canonicalize_path (search_path, &canonical) != 0)
2660 goto cleanup;
2662 if (argzize_path (canonical, &argz, &argz_len) != 0)
2663 goto cleanup;
2666 char *dir_name = 0;
2667 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2669 size_t lendir = LT_STRLEN (dir_name);
2671 if (lendir +1 +lenbase >= filenamesize)
2673 LT_DLFREE (filename);
2674 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2675 filename = LT_EMALLOC (char, filenamesize);
2676 if (!filename)
2677 goto cleanup;
2680 assert (filenamesize > lendir);
2681 strcpy (filename, dir_name);
2683 if (base_name && *base_name)
2685 if (filename[lendir -1] != '/')
2686 filename[lendir++] = '/';
2687 strcpy (filename +lendir, base_name);
2690 if ((result = (*func) (filename, data1, data2)))
2692 break;
2697 cleanup:
2698 LT_DLFREE (argz);
2699 LT_DLFREE (canonical);
2700 LT_DLFREE (filename);
2702 LT_DLMUTEX_UNLOCK ();
2704 return result;
2707 /* If FILEPATH can be opened, store the name of the directory component
2708 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2709 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2710 static int
2711 find_file_callback (filename, data1, data2)
2712 char *filename;
2713 lt_ptr data1;
2714 lt_ptr data2;
2716 char **pdir = (char **) data1;
2717 FILE **pfile = (FILE **) data2;
2718 int is_done = 0;
2720 assert (filename && *filename);
2721 assert (pdir);
2722 assert (pfile);
2724 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2726 char *dirend = strrchr (filename, '/');
2728 if (dirend > filename)
2729 *dirend = LT_EOS_CHAR;
2731 LT_DLFREE (*pdir);
2732 *pdir = lt_estrdup (filename);
2733 is_done = (*pdir == 0) ? -1 : 1;
2736 return is_done;
2739 static FILE *
2740 find_file (search_path, base_name, pdir)
2741 const char *search_path;
2742 const char *base_name;
2743 char **pdir;
2745 FILE *file = 0;
2747 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2749 return file;
2752 static int
2753 find_handle_callback (filename, data, ignored)
2754 char *filename;
2755 lt_ptr data;
2756 lt_ptr ignored;
2758 lt_dlhandle *handle = (lt_dlhandle *) data;
2759 int notfound = access (filename, R_OK);
2761 /* Bail out if file cannot be read... */
2762 if (notfound)
2763 return 0;
2765 /* Try to dlopen the file, but do not continue searching in any
2766 case. */
2767 if (tryall_dlopen (handle, filename) != 0)
2768 *handle = 0;
2770 return 1;
2773 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2774 found but could not be opened, *HANDLE will be set to 0. */
2775 static lt_dlhandle *
2776 find_handle (search_path, base_name, handle)
2777 const char *search_path;
2778 const char *base_name;
2779 lt_dlhandle *handle;
2781 if (!search_path)
2782 return 0;
2784 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2785 handle, 0))
2786 return 0;
2788 return handle;
2791 static int
2792 load_deplibs (handle, deplibs)
2793 lt_dlhandle handle;
2794 char *deplibs;
2796 #if LTDL_DLOPEN_DEPLIBS
2797 char *p, *save_search_path = 0;
2798 int depcount = 0;
2799 int i;
2800 char **names = 0;
2801 #endif
2802 int errors = 0;
2804 handle->depcount = 0;
2806 #if LTDL_DLOPEN_DEPLIBS
2807 if (!deplibs)
2809 return errors;
2811 ++errors;
2813 LT_DLMUTEX_LOCK ();
2814 if (user_search_path)
2816 save_search_path = lt_estrdup (user_search_path);
2817 if (!save_search_path)
2818 goto cleanup;
2821 /* extract search paths and count deplibs */
2822 p = deplibs;
2823 while (*p)
2825 if (!isspace ((int) *p))
2827 char *end = p+1;
2828 while (*end && !isspace((int) *end))
2830 ++end;
2833 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2835 char save = *end;
2836 *end = 0; /* set a temporary string terminator */
2837 if (lt_dladdsearchdir(p+2))
2839 goto cleanup;
2841 *end = save;
2843 else
2845 ++depcount;
2848 p = end;
2850 else
2852 ++p;
2856 /* restore the old search path */
2857 LT_DLFREE (user_search_path);
2858 user_search_path = save_search_path;
2860 LT_DLMUTEX_UNLOCK ();
2862 if (!depcount)
2864 errors = 0;
2865 goto cleanup;
2868 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2869 if (!names)
2870 goto cleanup;
2872 /* now only extract the actual deplibs */
2873 depcount = 0;
2874 p = deplibs;
2875 while (*p)
2877 if (isspace ((int) *p))
2879 ++p;
2881 else
2883 char *end = p+1;
2884 while (*end && !isspace ((int) *end))
2886 ++end;
2889 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2891 char *name;
2892 char save = *end;
2893 *end = 0; /* set a temporary string terminator */
2894 if (strncmp(p, "-l", 2) == 0)
2896 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2897 name = LT_EMALLOC (char, 1+ name_len);
2898 if (name)
2899 sprintf (name, "lib%s", p+2);
2901 else
2902 name = lt_estrdup(p);
2904 if (!name)
2905 goto cleanup_names;
2907 names[depcount++] = name;
2908 *end = save;
2910 p = end;
2914 /* load the deplibs (in reverse order)
2915 At this stage, don't worry if the deplibs do not load correctly,
2916 they may already be statically linked into the loading application
2917 for instance. There will be a more enlightening error message
2918 later on if the loaded module cannot resolve all of its symbols. */
2919 if (depcount)
2921 int j = 0;
2923 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2924 if (!handle->deplibs)
2925 goto cleanup;
2927 for (i = 0; i < depcount; ++i)
2929 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2930 if (handle->deplibs[j])
2932 ++j;
2936 handle->depcount = j; /* Number of successfully loaded deplibs */
2937 errors = 0;
2940 cleanup_names:
2941 for (i = 0; i < depcount; ++i)
2943 LT_DLFREE (names[i]);
2946 cleanup:
2947 LT_DLFREE (names);
2948 #endif
2950 return errors;
2953 static int
2954 unload_deplibs (handle)
2955 lt_dlhandle handle;
2957 int i;
2958 int errors = 0;
2960 if (handle->depcount)
2962 for (i = 0; i < handle->depcount; ++i)
2964 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2966 errors += lt_dlclose (handle->deplibs[i]);
2971 return errors;
2974 static int
2975 trim (dest, str)
2976 char **dest;
2977 const char *str;
2979 /* remove the leading and trailing "'" from str
2980 and store the result in dest */
2981 const char *end = strrchr (str, '\'');
2982 size_t len = LT_STRLEN (str);
2983 char *tmp;
2985 LT_DLFREE (*dest);
2987 if (len > 3 && str[0] == '\'')
2989 tmp = LT_EMALLOC (char, end - str);
2990 if (!tmp)
2991 return 1;
2993 strncpy(tmp, &str[1], (end - str) - 1);
2994 tmp[len-3] = LT_EOS_CHAR;
2995 *dest = tmp;
2997 else
2999 *dest = 0;
3002 return 0;
3005 static int
3006 free_vars (dlname, oldname, libdir, deplibs)
3007 char *dlname;
3008 char *oldname;
3009 char *libdir;
3010 char *deplibs;
3012 LT_DLFREE (dlname);
3013 LT_DLFREE (oldname);
3014 LT_DLFREE (libdir);
3015 LT_DLFREE (deplibs);
3017 return 0;
3020 static int
3021 try_dlopen (phandle, filename)
3022 lt_dlhandle *phandle;
3023 const char *filename;
3025 const char * ext = 0;
3026 const char * saved_error = 0;
3027 char * canonical = 0;
3028 char * base_name = 0;
3029 char * dir = 0;
3030 char * name = 0;
3031 int errors = 0;
3032 lt_dlhandle newhandle;
3034 assert (phandle);
3035 assert (*phandle == 0);
3037 LT_DLMUTEX_GETERROR (saved_error);
3039 /* dlopen self? */
3040 if (!filename)
3042 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3043 if (*phandle == 0)
3044 return 1;
3046 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3047 newhandle = *phandle;
3049 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3050 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3052 if (tryall_dlopen (&newhandle, 0) != 0)
3054 LT_DLFREE (*phandle);
3055 return 1;
3058 goto register_handle;
3061 assert (filename && *filename);
3063 /* Doing this immediately allows internal functions to safely
3064 assume only canonicalized paths are passed. */
3065 if (canonicalize_path (filename, &canonical) != 0)
3067 ++errors;
3068 goto cleanup;
3071 /* If the canonical module name is a path (relative or absolute)
3072 then split it into a directory part and a name part. */
3073 base_name = strrchr (canonical, '/');
3074 if (base_name)
3076 size_t dirlen = (1+ base_name) - canonical;
3078 dir = LT_EMALLOC (char, 1+ dirlen);
3079 if (!dir)
3081 ++errors;
3082 goto cleanup;
3085 strncpy (dir, canonical, dirlen);
3086 dir[dirlen] = LT_EOS_CHAR;
3088 ++base_name;
3090 else
3091 LT_DLMEM_REASSIGN (base_name, canonical);
3093 assert (base_name && *base_name);
3095 /* Check whether we are opening a libtool module (.la extension). */
3096 ext = strrchr (base_name, '.');
3097 if (ext && strcmp (ext, archive_ext) == 0)
3099 /* this seems to be a libtool module */
3100 FILE * file = 0;
3101 char * dlname = 0;
3102 char * old_name = 0;
3103 char * libdir = 0;
3104 char * deplibs = 0;
3105 char * line = 0;
3106 size_t line_len;
3108 /* if we can't find the installed flag, it is probably an
3109 installed libtool archive, produced with an old version
3110 of libtool */
3111 int installed = 1;
3113 /* extract the module name from the file name */
3114 name = LT_EMALLOC (char, ext - base_name + 1);
3115 if (!name)
3117 ++errors;
3118 goto cleanup;
3121 /* canonicalize the module name */
3123 size_t i;
3124 for (i = 0; i < ext - base_name; ++i)
3126 if (isalnum ((int)(base_name[i])))
3128 name[i] = base_name[i];
3130 else
3132 name[i] = '_';
3135 name[ext - base_name] = LT_EOS_CHAR;
3138 /* Now try to open the .la file. If there is no directory name
3139 component, try to find it first in user_search_path and then other
3140 prescribed paths. Otherwise (or in any case if the module was not
3141 yet found) try opening just the module name as passed. */
3142 if (!dir)
3144 const char *search_path;
3146 LT_DLMUTEX_LOCK ();
3147 search_path = user_search_path;
3148 if (search_path)
3149 file = find_file (user_search_path, base_name, &dir);
3150 LT_DLMUTEX_UNLOCK ();
3152 if (!file)
3154 search_path = getenv (LTDL_SEARCHPATH_VAR);
3155 if (search_path)
3156 file = find_file (search_path, base_name, &dir);
3159 #ifdef LTDL_SHLIBPATH_VAR
3160 if (!file)
3162 search_path = getenv (LTDL_SHLIBPATH_VAR);
3163 if (search_path)
3164 file = find_file (search_path, base_name, &dir);
3166 #endif
3167 #ifdef LTDL_SYSSEARCHPATH
3168 if (!file && sys_search_path)
3170 file = find_file (sys_search_path, base_name, &dir);
3172 #endif
3174 if (!file)
3176 file = fopen (filename, LT_READTEXT_MODE);
3179 /* If we didn't find the file by now, it really isn't there. Set
3180 the status flag, and bail out. */
3181 if (!file)
3183 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3184 ++errors;
3185 goto cleanup;
3188 line_len = LT_FILENAME_MAX;
3189 line = LT_EMALLOC (char, line_len);
3190 if (!line)
3192 fclose (file);
3193 ++errors;
3194 goto cleanup;
3197 /* read the .la file */
3198 while (!feof (file))
3200 if (!fgets (line, (int) line_len, file))
3202 break;
3205 /* Handle the case where we occasionally need to read a line
3206 that is longer than the initial buffer size. */
3207 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3209 line = LT_DLREALLOC (char, line, line_len *2);
3210 if (!fgets (&line[line_len -1], (int) line_len +1, file))
3212 break;
3214 line_len *= 2;
3217 if (line[0] == '\n' || line[0] == '#')
3219 continue;
3222 #undef STR_DLNAME
3223 #define STR_DLNAME "dlname="
3224 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3226 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3229 #undef STR_OLD_LIBRARY
3230 #define STR_OLD_LIBRARY "old_library="
3231 else if (strncmp (line, STR_OLD_LIBRARY,
3232 sizeof (STR_OLD_LIBRARY) - 1) == 0)
3234 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3236 #undef STR_LIBDIR
3237 #define STR_LIBDIR "libdir="
3238 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3240 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3243 #undef STR_DL_DEPLIBS
3244 #define STR_DL_DEPLIBS "dependency_libs="
3245 else if (strncmp (line, STR_DL_DEPLIBS,
3246 sizeof (STR_DL_DEPLIBS) - 1) == 0)
3248 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3250 else if (strcmp (line, "installed=yes\n") == 0)
3252 installed = 1;
3254 else if (strcmp (line, "installed=no\n") == 0)
3256 installed = 0;
3259 #undef STR_LIBRARY_NAMES
3260 #define STR_LIBRARY_NAMES "library_names="
3261 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3262 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3264 char *last_libname;
3265 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3266 if (!errors
3267 && dlname
3268 && (last_libname = strrchr (dlname, ' ')) != 0)
3270 last_libname = lt_estrdup (last_libname + 1);
3271 if (!last_libname)
3273 ++errors;
3274 goto cleanup;
3276 LT_DLMEM_REASSIGN (dlname, last_libname);
3280 if (errors)
3281 break;
3284 fclose (file);
3285 LT_DLFREE (line);
3287 /* allocate the handle */
3288 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3289 if (*phandle == 0)
3290 ++errors;
3292 if (errors)
3294 free_vars (dlname, old_name, libdir, deplibs);
3295 LT_DLFREE (*phandle);
3296 goto cleanup;
3299 assert (*phandle);
3301 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3302 if (load_deplibs (*phandle, deplibs) == 0)
3304 newhandle = *phandle;
3305 /* find_module may replace newhandle */
3306 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3308 unload_deplibs (*phandle);
3309 ++errors;
3312 else
3314 ++errors;
3317 free_vars (dlname, old_name, libdir, deplibs);
3318 if (errors)
3320 LT_DLFREE (*phandle);
3321 goto cleanup;
3324 if (*phandle != newhandle)
3326 unload_deplibs (*phandle);
3329 else
3331 /* not a libtool module */
3332 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3333 if (*phandle == 0)
3335 ++errors;
3336 goto cleanup;
3339 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3340 newhandle = *phandle;
3342 /* If the module has no directory name component, try to find it
3343 first in user_search_path and then other prescribed paths.
3344 Otherwise (or in any case if the module was not yet found) try
3345 opening just the module name as passed. */
3346 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3347 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3348 &newhandle)
3349 #ifdef LTDL_SHLIBPATH_VAR
3350 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3351 &newhandle)
3352 #endif
3353 #ifdef LTDL_SYSSEARCHPATH
3354 && !find_handle (sys_search_path, base_name, &newhandle)
3355 #endif
3358 if (tryall_dlopen (&newhandle, filename) != 0)
3360 newhandle = NULL;
3364 if (!newhandle)
3366 LT_DLFREE (*phandle);
3367 ++errors;
3368 goto cleanup;
3372 register_handle:
3373 LT_DLMEM_REASSIGN (*phandle, newhandle);
3375 if ((*phandle)->info.ref_count == 0)
3377 (*phandle)->info.ref_count = 1;
3378 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3380 LT_DLMUTEX_LOCK ();
3381 (*phandle)->next = handles;
3382 handles = *phandle;
3383 LT_DLMUTEX_UNLOCK ();
3386 LT_DLMUTEX_SETERROR (saved_error);
3388 cleanup:
3389 LT_DLFREE (dir);
3390 LT_DLFREE (name);
3391 LT_DLFREE (canonical);
3393 return errors;
3396 lt_dlhandle
3397 lt_dlopen (filename)
3398 const char *filename;
3400 lt_dlhandle handle = 0;
3402 /* Just incase we missed a code path in try_dlopen() that reports
3403 an error, but forgets to reset handle... */
3404 if (try_dlopen (&handle, filename) != 0)
3405 return 0;
3407 return handle;
3410 /* If the last error messge store was `FILE_NOT_FOUND', then return
3411 non-zero. */
3412 static int
3413 file_not_found ()
3415 const char *error = 0;
3417 LT_DLMUTEX_GETERROR (error);
3418 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3419 return 1;
3421 return 0;
3424 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3425 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3426 and if a file is still not found try again with SHLIB_EXT appended
3427 instead. */
3428 lt_dlhandle
3429 lt_dlopenext (filename)
3430 const char *filename;
3432 lt_dlhandle handle = 0;
3433 char * tmp = 0;
3434 char * ext = 0;
3435 size_t len;
3436 int errors = 0;
3438 if (!filename)
3440 return lt_dlopen (filename);
3443 assert (filename);
3445 len = LT_STRLEN (filename);
3446 ext = strrchr (filename, '.');
3448 /* If FILENAME already bears a suitable extension, there is no need
3449 to try appending additional extensions. */
3450 if (ext && ((strcmp (ext, archive_ext) == 0)
3451 #ifdef LTDL_SHLIB_EXT
3452 || (strcmp (ext, shlib_ext) == 0)
3453 #endif
3456 return lt_dlopen (filename);
3459 /* First try appending ARCHIVE_EXT. */
3460 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3461 if (!tmp)
3462 return 0;
3464 strcpy (tmp, filename);
3465 strcat (tmp, archive_ext);
3466 errors = try_dlopen (&handle, tmp);
3468 /* If we found FILENAME, stop searching -- whether we were able to
3469 load the file as a module or not. If the file exists but loading
3470 failed, it is better to return an error message here than to
3471 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3472 in the module search path. */
3473 if (handle || ((errors > 0) && !file_not_found ()))
3475 LT_DLFREE (tmp);
3476 return handle;
3479 #ifdef LTDL_SHLIB_EXT
3480 /* Try appending SHLIB_EXT. */
3481 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3483 LT_DLFREE (tmp);
3484 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3485 if (!tmp)
3486 return 0;
3488 strcpy (tmp, filename);
3490 else
3492 tmp[len] = LT_EOS_CHAR;
3495 strcat(tmp, shlib_ext);
3496 errors = try_dlopen (&handle, tmp);
3498 /* As before, if the file was found but loading failed, return now
3499 with the current error message. */
3500 if (handle || ((errors > 0) && !file_not_found ()))
3502 LT_DLFREE (tmp);
3503 return handle;
3505 #endif
3507 /* Still here? Then we really did fail to locate any of the file
3508 names we tried. */
3509 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3510 LT_DLFREE (tmp);
3511 return 0;
3515 static int
3516 lt_argz_insert (pargz, pargz_len, before, entry)
3517 char **pargz;
3518 size_t *pargz_len;
3519 char *before;
3520 const char *entry;
3522 error_t error;
3524 if ((error = argz_insert (pargz, pargz_len, before, entry)))
3526 switch (error)
3528 case ENOMEM:
3529 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3530 break;
3531 default:
3532 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3533 break;
3535 return 1;
3538 return 0;
3541 static int
3542 lt_argz_insertinorder (pargz, pargz_len, entry)
3543 char **pargz;
3544 size_t *pargz_len;
3545 const char *entry;
3547 char *before = 0;
3549 assert (pargz);
3550 assert (pargz_len);
3551 assert (entry && *entry);
3553 if (*pargz)
3554 while ((before = argz_next (*pargz, *pargz_len, before)))
3556 int cmp = strcmp (entry, before);
3558 if (cmp < 0) break;
3559 if (cmp == 0) return 0; /* No duplicates! */
3562 return lt_argz_insert (pargz, pargz_len, before, entry);
3565 static int
3566 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3567 char **pargz;
3568 size_t *pargz_len;
3569 const char *dirnam;
3570 struct dirent *dp;
3572 char *buf = 0;
3573 size_t buf_len = 0;
3574 char *end = 0;
3575 size_t end_offset = 0;
3576 size_t dir_len = 0;
3577 int errors = 0;
3579 assert (pargz);
3580 assert (pargz_len);
3581 assert (dp);
3583 dir_len = LT_STRLEN (dirnam);
3584 end = dp->d_name + LT_D_NAMLEN(dp);
3586 /* Ignore version numbers. */
3588 char *p;
3589 for (p = end; p -1 > dp->d_name; --p)
3590 if (strchr (".0123456789", p[-1]) == 0)
3591 break;
3593 if (*p == '.')
3594 end = p;
3597 /* Ignore filename extension. */
3599 char *p;
3600 for (p = end -1; p > dp->d_name; --p)
3601 if (*p == '.')
3603 end = p;
3604 break;
3608 /* Prepend the directory name. */
3609 end_offset = end - dp->d_name;
3610 buf_len = dir_len + 1+ end_offset;
3611 buf = LT_EMALLOC (char, 1+ buf_len);
3612 if (!buf)
3613 return ++errors;
3615 assert (buf);
3617 strcpy (buf, dirnam);
3618 strcat (buf, "/");
3619 strncat (buf, dp->d_name, end_offset);
3620 buf[buf_len] = LT_EOS_CHAR;
3622 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3623 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3624 ++errors;
3626 LT_DLFREE (buf);
3628 return errors;
3631 static int
3632 list_files_by_dir (dirnam, pargz, pargz_len)
3633 const char *dirnam;
3634 char **pargz;
3635 size_t *pargz_len;
3637 DIR *dirp = 0;
3638 int errors = 0;
3640 assert (dirnam && *dirnam);
3641 assert (pargz);
3642 assert (pargz_len);
3643 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3645 dirp = opendir (dirnam);
3646 if (dirp)
3648 struct dirent *dp = 0;
3650 while ((dp = readdir (dirp)))
3651 if (dp->d_name[0] != '.')
3652 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3654 ++errors;
3655 break;
3658 closedir (dirp);
3660 else
3661 ++errors;
3663 return errors;
3667 /* If there are any files in DIRNAME, call the function passed in
3668 DATA1 (with the name of each file and DATA2 as arguments). */
3669 static int
3670 foreachfile_callback (dirname, data1, data2)
3671 char *dirname;
3672 lt_ptr data1;
3673 lt_ptr data2;
3675 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3676 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3678 int is_done = 0;
3679 char *argz = 0;
3680 size_t argz_len = 0;
3682 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3683 goto cleanup;
3684 if (!argz)
3685 goto cleanup;
3688 char *filename = 0;
3689 while ((filename = argz_next (argz, argz_len, filename)))
3690 if ((is_done = (*func) (filename, data2)))
3691 break;
3694 cleanup:
3695 LT_DLFREE (argz);
3697 return is_done;
3701 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3702 with DATA. The filenames passed to FUNC would be suitable for
3703 passing to lt_dlopenext. The extensions are stripped so that
3704 individual modules do not generate several entries (e.g. libfoo.la,
3705 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3706 then the same directories that lt_dlopen would search are examined. */
3708 lt_dlforeachfile (search_path, func, data)
3709 const char *search_path;
3710 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3711 lt_ptr data;
3713 int is_done = 0;
3715 if (search_path)
3717 /* If a specific path was passed, search only the directories
3718 listed in it. */
3719 is_done = foreach_dirinpath (search_path, 0,
3720 foreachfile_callback, func, data);
3722 else
3724 /* Otherwise search the default paths. */
3725 is_done = foreach_dirinpath (user_search_path, 0,
3726 foreachfile_callback, func, data);
3727 if (!is_done)
3729 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3730 foreachfile_callback, func, data);
3733 #ifdef LTDL_SHLIBPATH_VAR
3734 if (!is_done)
3736 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3737 foreachfile_callback, func, data);
3739 #endif
3740 #ifdef LTDL_SYSSEARCHPATH
3741 if (!is_done)
3743 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3744 foreachfile_callback, func, data);
3746 #endif
3749 return is_done;
3753 lt_dlclose (handle)
3754 lt_dlhandle handle;
3756 lt_dlhandle cur, last;
3757 int errors = 0;
3759 LT_DLMUTEX_LOCK ();
3761 /* check whether the handle is valid */
3762 last = cur = handles;
3763 while (cur && handle != cur)
3765 last = cur;
3766 cur = cur->next;
3769 if (!cur)
3771 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3772 ++errors;
3773 goto done;
3776 handle->info.ref_count--;
3778 /* Note that even with resident modules, we must track the ref_count
3779 correctly incase the user decides to reset the residency flag
3780 later (even though the API makes no provision for that at the
3781 moment). */
3782 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3784 lt_user_data data = handle->loader->dlloader_data;
3786 if (handle != handles)
3788 last->next = handle->next;
3790 else
3792 handles = handle->next;
3795 errors += handle->loader->module_close (data, handle->module);
3796 errors += unload_deplibs(handle);
3798 /* It is up to the callers to free the data itself. */
3799 LT_DLFREE (handle->caller_data);
3801 LT_DLFREE (handle->info.filename);
3802 LT_DLFREE (handle->info.name);
3803 LT_DLFREE (handle);
3805 goto done;
3808 if (LT_DLIS_RESIDENT (handle))
3810 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3811 ++errors;
3814 done:
3815 LT_DLMUTEX_UNLOCK ();
3817 return errors;
3820 lt_ptr
3821 lt_dlsym (handle, symbol)
3822 lt_dlhandle handle;
3823 const char *symbol;
3825 size_t lensym;
3826 char lsym[LT_SYMBOL_LENGTH];
3827 char *sym;
3828 lt_ptr address;
3829 lt_user_data data;
3831 if (!handle)
3833 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3834 return 0;
3837 if (!symbol)
3839 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3840 return 0;
3843 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3844 + LT_STRLEN (handle->info.name);
3846 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3848 sym = lsym;
3850 else
3852 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3853 if (!sym)
3855 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3856 return 0;
3860 data = handle->loader->dlloader_data;
3861 if (handle->info.name)
3863 const char *saved_error;
3865 LT_DLMUTEX_GETERROR (saved_error);
3867 /* this is a libtool module */
3868 if (handle->loader->sym_prefix)
3870 strcpy(sym, handle->loader->sym_prefix);
3871 strcat(sym, handle->info.name);
3873 else
3875 strcpy(sym, handle->info.name);
3878 strcat(sym, "_LTX_");
3879 strcat(sym, symbol);
3881 /* try "modulename_LTX_symbol" */
3882 address = handle->loader->find_sym (data, handle->module, sym);
3883 if (address)
3885 if (sym != lsym)
3887 LT_DLFREE (sym);
3889 return address;
3891 LT_DLMUTEX_SETERROR (saved_error);
3894 /* otherwise try "symbol" */
3895 if (handle->loader->sym_prefix)
3897 strcpy(sym, handle->loader->sym_prefix);
3898 strcat(sym, symbol);
3900 else
3902 strcpy(sym, symbol);
3905 address = handle->loader->find_sym (data, handle->module, sym);
3906 if (sym != lsym)
3908 LT_DLFREE (sym);
3911 return address;
3914 const char *
3915 lt_dlerror ()
3917 const char *error;
3919 LT_DLMUTEX_GETERROR (error);
3920 LT_DLMUTEX_SETERROR (0);
3922 return error ? error : LT_DLSTRERROR (UNKNOWN);
3925 static int
3926 lt_dlpath_insertdir (ppath, before, dir)
3927 char **ppath;
3928 char *before;
3929 const char *dir;
3931 int errors = 0;
3932 char *canonical = 0;
3933 char *argz = 0;
3934 size_t argz_len = 0;
3936 assert (ppath);
3937 assert (dir && *dir);
3939 if (canonicalize_path (dir, &canonical) != 0)
3941 ++errors;
3942 goto cleanup;
3945 assert (canonical && *canonical);
3947 /* If *PPATH is empty, set it to DIR. */
3948 if (*ppath == 0)
3950 assert (!before); /* BEFORE cannot be set without PPATH. */
3951 assert (dir); /* Without DIR, don't call this function! */
3953 *ppath = lt_estrdup (dir);
3954 if (*ppath == 0)
3955 ++errors;
3957 return errors;
3960 assert (ppath && *ppath);
3962 if (argzize_path (*ppath, &argz, &argz_len) != 0)
3964 ++errors;
3965 goto cleanup;
3968 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
3969 if *PPATH is already canonicalized, and hence does not change length
3970 with respect to ARGZ. We canonicalize each entry as it is added to
3971 the search path, and don't call this function with (uncanonicalized)
3972 user paths, so this is a fair assumption. */
3973 if (before)
3975 assert (*ppath <= before);
3976 assert (before - *ppath <= strlen (*ppath));
3978 before = before - *ppath + argz;
3981 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3983 ++errors;
3984 goto cleanup;
3987 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3988 LT_DLMEM_REASSIGN (*ppath, argz);
3990 cleanup:
3991 LT_DLFREE (canonical);
3992 LT_DLFREE (argz);
3994 return errors;
3998 lt_dladdsearchdir (search_dir)
3999 const char *search_dir;
4001 int errors = 0;
4003 if (search_dir && *search_dir)
4005 LT_DLMUTEX_LOCK ();
4006 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4007 ++errors;
4008 LT_DLMUTEX_UNLOCK ();
4011 return errors;
4015 lt_dlinsertsearchdir (before, search_dir)
4016 const char *before;
4017 const char *search_dir;
4019 int errors = 0;
4021 if (before)
4023 LT_DLMUTEX_LOCK ();
4024 if ((before < user_search_path)
4025 || (before >= user_search_path + LT_STRLEN (user_search_path)))
4027 LT_DLMUTEX_UNLOCK ();
4028 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4029 return 1;
4031 LT_DLMUTEX_UNLOCK ();
4034 if (search_dir && *search_dir)
4036 LT_DLMUTEX_LOCK ();
4037 if (lt_dlpath_insertdir (&user_search_path,
4038 (char *) before, search_dir) != 0)
4040 ++errors;
4042 LT_DLMUTEX_UNLOCK ();
4045 return errors;
4049 lt_dlsetsearchpath (search_path)
4050 const char *search_path;
4052 int errors = 0;
4054 LT_DLMUTEX_LOCK ();
4055 LT_DLFREE (user_search_path);
4056 LT_DLMUTEX_UNLOCK ();
4058 if (!search_path || !LT_STRLEN (search_path))
4060 return errors;
4063 LT_DLMUTEX_LOCK ();
4064 if (canonicalize_path (search_path, &user_search_path) != 0)
4065 ++errors;
4066 LT_DLMUTEX_UNLOCK ();
4068 return errors;
4071 const char *
4072 lt_dlgetsearchpath ()
4074 const char *saved_path;
4076 LT_DLMUTEX_LOCK ();
4077 saved_path = user_search_path;
4078 LT_DLMUTEX_UNLOCK ();
4080 return saved_path;
4084 lt_dlmakeresident (handle)
4085 lt_dlhandle handle;
4087 int errors = 0;
4089 if (!handle)
4091 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4092 ++errors;
4094 else
4096 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4099 return errors;
4103 lt_dlisresident (handle)
4104 lt_dlhandle handle;
4106 if (!handle)
4108 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4109 return -1;
4112 return LT_DLIS_RESIDENT (handle);
4118 /* --- MODULE INFORMATION --- */
4120 const lt_dlinfo *
4121 lt_dlgetinfo (handle)
4122 lt_dlhandle handle;
4124 if (!handle)
4126 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4127 return 0;
4130 return &(handle->info);
4133 lt_dlhandle
4134 lt_dlhandle_next (place)
4135 lt_dlhandle place;
4137 return place ? place->next : handles;
4141 lt_dlforeach (func, data)
4142 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4143 lt_ptr data;
4145 int errors = 0;
4146 lt_dlhandle cur;
4148 LT_DLMUTEX_LOCK ();
4150 cur = handles;
4151 while (cur)
4153 lt_dlhandle tmp = cur;
4155 cur = cur->next;
4156 if ((*func) (tmp, data))
4158 ++errors;
4159 break;
4163 LT_DLMUTEX_UNLOCK ();
4165 return errors;
4168 lt_dlcaller_id
4169 lt_dlcaller_register ()
4171 static lt_dlcaller_id last_caller_id = 0;
4172 int result;
4174 LT_DLMUTEX_LOCK ();
4175 result = ++last_caller_id;
4176 LT_DLMUTEX_UNLOCK ();
4178 return result;
4181 lt_ptr
4182 lt_dlcaller_set_data (key, handle, data)
4183 lt_dlcaller_id key;
4184 lt_dlhandle handle;
4185 lt_ptr data;
4187 int n_elements = 0;
4188 lt_ptr stale = (lt_ptr) 0;
4189 int i;
4191 /* This needs to be locked so that the caller data can be updated
4192 simultaneously by different threads. */
4193 LT_DLMUTEX_LOCK ();
4195 if (handle->caller_data)
4196 while (handle->caller_data[n_elements].key)
4197 ++n_elements;
4199 for (i = 0; i < n_elements; ++i)
4201 if (handle->caller_data[i].key == key)
4203 stale = handle->caller_data[i].data;
4204 break;
4208 /* Ensure that there is enough room in this handle's caller_data
4209 array to accept a new element (and an empty end marker). */
4210 if (i == n_elements)
4212 lt_caller_data *temp
4213 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4215 if (!temp)
4217 stale = 0;
4218 goto done;
4221 handle->caller_data = temp;
4223 /* We only need this if we needed to allocate a new caller_data. */
4224 handle->caller_data[i].key = key;
4225 handle->caller_data[1+ i].key = 0;
4228 handle->caller_data[i].data = data;
4230 done:
4231 LT_DLMUTEX_UNLOCK ();
4233 return stale;
4236 lt_ptr
4237 lt_dlcaller_get_data (key, handle)
4238 lt_dlcaller_id key;
4239 lt_dlhandle handle;
4241 lt_ptr result = (lt_ptr) 0;
4243 /* This needs to be locked so that the caller data isn't updated by
4244 another thread part way through this function. */
4245 LT_DLMUTEX_LOCK ();
4247 /* Locate the index of the element with a matching KEY. */
4249 int i;
4250 for (i = 0; handle->caller_data[i].key; ++i)
4252 if (handle->caller_data[i].key == key)
4254 result = handle->caller_data[i].data;
4255 break;
4260 LT_DLMUTEX_UNLOCK ();
4262 return result;
4267 /* --- USER MODULE LOADER API --- */
4271 lt_dlloader_add (place, dlloader, loader_name)
4272 lt_dlloader *place;
4273 const struct lt_user_dlloader *dlloader;
4274 const char *loader_name;
4276 int errors = 0;
4277 lt_dlloader *node = 0, *ptr = 0;
4279 if ((dlloader == 0) /* diagnose null parameters */
4280 || (dlloader->module_open == 0)
4281 || (dlloader->module_close == 0)
4282 || (dlloader->find_sym == 0))
4284 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4285 return 1;
4288 /* Create a new dlloader node with copies of the user callbacks. */
4289 node = LT_EMALLOC (lt_dlloader, 1);
4290 if (!node)
4291 return 1;
4293 node->next = 0;
4294 node->loader_name = loader_name;
4295 node->sym_prefix = dlloader->sym_prefix;
4296 node->dlloader_exit = dlloader->dlloader_exit;
4297 node->module_open = dlloader->module_open;
4298 node->module_close = dlloader->module_close;
4299 node->find_sym = dlloader->find_sym;
4300 node->dlloader_data = dlloader->dlloader_data;
4302 LT_DLMUTEX_LOCK ();
4303 if (!loaders)
4305 /* If there are no loaders, NODE becomes the list! */
4306 loaders = node;
4308 else if (!place)
4310 /* If PLACE is not set, add NODE to the end of the
4311 LOADERS list. */
4312 for (ptr = loaders; ptr->next; ptr = ptr->next)
4314 /*NOWORK*/;
4317 ptr->next = node;
4319 else if (loaders == place)
4321 /* If PLACE is the first loader, NODE goes first. */
4322 node->next = place;
4323 loaders = node;
4325 else
4327 /* Find the node immediately preceding PLACE. */
4328 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4330 /*NOWORK*/;
4333 if (ptr->next != place)
4335 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4336 ++errors;
4338 else
4340 /* Insert NODE between PTR and PLACE. */
4341 node->next = place;
4342 ptr->next = node;
4346 LT_DLMUTEX_UNLOCK ();
4348 return errors;
4352 lt_dlloader_remove (loader_name)
4353 const char *loader_name;
4355 lt_dlloader *place = lt_dlloader_find (loader_name);
4356 lt_dlhandle handle;
4357 int errors = 0;
4359 if (!place)
4361 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4362 return 1;
4365 LT_DLMUTEX_LOCK ();
4367 /* Fail if there are any open modules which use this loader. */
4368 for (handle = handles; handle; handle = handle->next)
4370 if (handle->loader == place)
4372 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4373 ++errors;
4374 goto done;
4378 if (place == loaders)
4380 /* PLACE is the first loader in the list. */
4381 loaders = loaders->next;
4383 else
4385 /* Find the loader before the one being removed. */
4386 lt_dlloader *prev;
4387 for (prev = loaders; prev->next; prev = prev->next)
4389 if (!strcmp (prev->next->loader_name, loader_name))
4391 break;
4395 place = prev->next;
4396 prev->next = prev->next->next;
4399 if (place->dlloader_exit)
4401 errors = place->dlloader_exit (place->dlloader_data);
4404 LT_DLFREE (place);
4406 done:
4407 LT_DLMUTEX_UNLOCK ();
4409 return errors;
4412 lt_dlloader *
4413 lt_dlloader_next (place)
4414 lt_dlloader *place;
4416 lt_dlloader *next;
4418 LT_DLMUTEX_LOCK ();
4419 next = place ? place->next : loaders;
4420 LT_DLMUTEX_UNLOCK ();
4422 return next;
4425 const char *
4426 lt_dlloader_name (place)
4427 lt_dlloader *place;
4429 const char *name = 0;
4431 if (place)
4433 LT_DLMUTEX_LOCK ();
4434 name = place ? place->loader_name : 0;
4435 LT_DLMUTEX_UNLOCK ();
4437 else
4439 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4442 return name;
4445 lt_user_data *
4446 lt_dlloader_data (place)
4447 lt_dlloader *place;
4449 lt_user_data *data = 0;
4451 if (place)
4453 LT_DLMUTEX_LOCK ();
4454 data = place ? &(place->dlloader_data) : 0;
4455 LT_DLMUTEX_UNLOCK ();
4457 else
4459 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4462 return data;
4465 lt_dlloader *
4466 lt_dlloader_find (loader_name)
4467 const char *loader_name;
4469 lt_dlloader *place = 0;
4471 LT_DLMUTEX_LOCK ();
4472 for (place = loaders; place; place = place->next)
4474 if (strcmp (place->loader_name, loader_name) == 0)
4476 break;
4479 LT_DLMUTEX_UNLOCK ();
4481 return place;