ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/libltdl/ltdl.c
Revision: 10082
Committed: Sat Jun 11 11:40:12 2022 UTC (21 months, 2 weeks ago) by michael
Content type: text/x-csrc
File size: 55335 byte(s)
Log Message:
- autoreconf

File Contents

# User Rev Content
1 michael 945 /* ltdl.c -- system independent dlopen wrapper
2    
3 michael 10082 Copyright (C) 1998-2000, 2004-2008, 2011-2019, 2021-2022 Free
4     Software Foundation, Inc.
5 michael 945 Written by Thomas Tanner, 1998
6    
7     NOTE: The canonical source of this file is maintained with the
8     GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9    
10     GNU Libltdl is free software; you can redistribute it and/or
11     modify it under the terms of the GNU Lesser General Public
12     License as published by the Free Software Foundation; either
13     version 2 of the License, or (at your option) any later version.
14    
15     As a special exception to the GNU Lesser General Public License,
16     if you distribute this file as part of a program or library that
17     is built using GNU Libtool, you may include this file under the
18     same distribution terms that you use for the rest of that program.
19    
20     GNU Libltdl is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23     GNU Lesser General Public License for more details.
24    
25     You should have received a copy of the GNU Lesser General Public
26     License along with GNU Libltdl; see the file COPYING.LIB. If not, a
27     copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
28     or obtained by writing to the Free Software Foundation, Inc.,
29     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30     */
31    
32     #include "lt__private.h"
33     #include "lt_system.h"
34     #include "lt_dlloader.h"
35    
36    
37     /* --- MANIFEST CONSTANTS --- */
38    
39    
40     /* Standard libltdl search path environment variable name */
41     #undef LTDL_SEARCHPATH_VAR
42     #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
43    
44     /* Standard libtool archive file extension. */
45     #undef LT_ARCHIVE_EXT
46     #define LT_ARCHIVE_EXT ".la"
47    
48     /* max. filename length */
49 michael 4901 #if !defined LT_FILENAME_MAX
50 michael 945 # define LT_FILENAME_MAX 1024
51     #endif
52    
53 michael 4901 #if !defined LT_LIBEXT
54 michael 945 # define LT_LIBEXT "a"
55     #endif
56    
57 michael 4901 #if !defined LT_LIBPREFIX
58 michael 1107 # define LT_LIBPREFIX "lib"
59     #endif
60    
61 michael 945 /* This is the maximum symbol size that won't require malloc/free */
62     #undef LT_SYMBOL_LENGTH
63     #define LT_SYMBOL_LENGTH 128
64    
65     /* This accounts for the _LTX_ separator */
66     #undef LT_SYMBOL_OVERHEAD
67     #define LT_SYMBOL_OVERHEAD 5
68    
69     /* Various boolean flags can be stored in the flags field of an
70     lt_dlhandle... */
71     #define LT_DLIS_RESIDENT(handle) ((handle)->info.is_resident)
72     #define LT_DLIS_SYMGLOBAL(handle) ((handle)->info.is_symglobal)
73     #define LT_DLIS_SYMLOCAL(handle) ((handle)->info.is_symlocal)
74    
75    
76     static const char objdir[] = LT_OBJDIR;
77     static const char archive_ext[] = LT_ARCHIVE_EXT;
78     static const char libext[] = LT_LIBEXT;
79 michael 1107 static const char libprefix[] = LT_LIBPREFIX;
80 michael 4901 #if defined LT_MODULE_EXT
81 michael 945 static const char shlib_ext[] = LT_MODULE_EXT;
82     #endif
83 michael 1257 /* If the loadable module suffix is not the same as the linkable
84     * shared library suffix, this will be defined. */
85 michael 4901 #if defined LT_SHARED_EXT
86 michael 1257 static const char shared_ext[] = LT_SHARED_EXT;
87     #endif
88 michael 4901 #if defined LT_DLSEARCH_PATH
89 michael 945 static const char sys_dlsearch_path[] = LT_DLSEARCH_PATH;
90     #endif
91    
92    
93    
94    
95     /* --- DYNAMIC MODULE LOADING --- */
96    
97    
98     /* The type of a function used at each iteration of foreach_dirinpath(). */
99     typedef int foreach_callback_func (char *filename, void *data1,
100     void *data2);
101     /* foreachfile_callback itself calls a function of this type: */
102     typedef int file_worker_func (const char *filename, void *data);
103    
104    
105     static int foreach_dirinpath (const char *search_path,
106     const char *base_name,
107     foreach_callback_func *func,
108     void *data1, void *data2);
109     static int find_file_callback (char *filename, void *data1,
110     void *data2);
111     static int find_handle_callback (char *filename, void *data,
112     void *ignored);
113     static int foreachfile_callback (char *filename, void *data1,
114     void *data2);
115    
116    
117     static int canonicalize_path (const char *path, char **pcanonical);
118     static int argzize_path (const char *path,
119     char **pargz, size_t *pargz_len);
120     static FILE *find_file (const char *search_path,
121     const char *base_name, char **pdir);
122     static lt_dlhandle *find_handle (const char *search_path,
123     const char *base_name,
124     lt_dlhandle *handle,
125     lt_dladvise advise);
126     static int find_module (lt_dlhandle *handle, const char *dir,
127     const char *libdir, const char *dlname,
128     const char *old_name, int installed,
129     lt_dladvise advise);
130     static int has_library_ext (const char *filename);
131     static int load_deplibs (lt_dlhandle handle, char *deplibs);
132     static int trim (char **dest, const char *str);
133     static int try_dlopen (lt_dlhandle *handle,
134     const char *filename, const char *ext,
135     lt_dladvise advise);
136     static int tryall_dlopen (lt_dlhandle *handle,
137     const char *filename,
138     lt_dladvise padvise,
139     const lt_dlvtable *vtable);
140     static int unload_deplibs (lt_dlhandle handle);
141     static int lt_argz_insert (char **pargz, size_t *pargz_len,
142     char *before, const char *entry);
143     static int lt_argz_insertinorder (char **pargz, size_t *pargz_len,
144     const char *entry);
145     static int lt_argz_insertdir (char **pargz, size_t *pargz_len,
146     const char *dirnam, struct dirent *dp);
147     static int lt_dlpath_insertdir (char **ppath, char *before,
148     const char *dir);
149     static int list_files_by_dir (const char *dirnam,
150     char **pargz, size_t *pargz_len);
151     static int file_not_found (void);
152    
153     #ifdef HAVE_LIBDLLOADER
154     static int loader_init_callback (lt_dlhandle handle);
155     #endif /* HAVE_LIBDLLOADER */
156    
157     static int loader_init (lt_get_vtable *vtable_func,
158     lt_user_data data);
159    
160     static char *user_search_path= 0;
161     static lt_dlhandle handles = 0;
162     static int initialized = 0;
163    
164     /* Our memory failure callback sets the error message to be passed back
165     up to the client, so we must be careful to return from mallocation
166     callers if allocation fails (as this callback returns!!). */
167     void
168     lt__alloc_die_callback (void)
169     {
170     LT__SETERROR (NO_MEMORY);
171     }
172    
173     #ifdef HAVE_LIBDLLOADER
174     /* This function is called to initialise each preloaded module loader,
175     and hook it into the list of loaders to be used when attempting to
176     dlopen an application module. */
177     static int
178     loader_init_callback (lt_dlhandle handle)
179     {
180     lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
181     return loader_init (vtable_func, 0);
182     }
183     #endif /* HAVE_LIBDLLOADER */
184    
185     static int
186     loader_init (lt_get_vtable *vtable_func, lt_user_data data)
187     {
188     const lt_dlvtable *vtable = 0;
189     int errors = 0;
190    
191     if (vtable_func)
192     {
193     vtable = (*vtable_func) (data);
194     }
195    
196     /* lt_dlloader_add will LT__SETERROR if it fails. */
197     errors += lt_dlloader_add (vtable);
198    
199     assert (errors || vtable);
200    
201     if ((!errors) && vtable->dlloader_init)
202     {
203     if ((*vtable->dlloader_init) (vtable->dlloader_data))
204     {
205     LT__SETERROR (INIT_LOADER);
206     ++errors;
207     }
208     }
209    
210     return errors;
211     }
212    
213     /* Bootstrap the loader loading with the preopening loader. */
214     #define get_vtable preopen_LTX_get_vtable
215     #define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
216    
217     LT_BEGIN_C_DECLS
218     LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data);
219     LT_END_C_DECLS
220     #ifdef HAVE_LIBDLLOADER
221 michael 1107 extern LT_DLSYM_CONST lt_dlsymlist preloaded_symbols[];
222 michael 945 #endif
223    
224     /* Initialize libltdl. */
225     int
226     lt_dlinit (void)
227     {
228     int errors = 0;
229    
230     /* Initialize only at first call. */
231     if (++initialized == 1)
232     {
233     lt__alloc_die = lt__alloc_die_callback;
234     handles = 0;
235     user_search_path = 0; /* empty search path */
236    
237     /* First set up the statically loaded preload module loader, so
238     we can use it to preopen the other loaders we linked in at
239     compile time. */
240     errors += loader_init (get_vtable, 0);
241    
242     /* Now open all the preloaded module loaders, so the application
243     can use _them_ to lt_dlopen its own modules. */
244     #ifdef HAVE_LIBDLLOADER
245     if (!errors)
246     {
247 michael 1094 errors += lt_dlpreload (preloaded_symbols);
248 michael 945 }
249    
250     if (!errors)
251     {
252     errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
253     }
254     #endif /* HAVE_LIBDLLOADER */
255     }
256    
257     #ifdef LT_DEBUG_LOADERS
258     lt_dlloader_dump();
259     #endif
260    
261     return errors;
262     }
263    
264     int
265     lt_dlexit (void)
266     {
267     /* shut down libltdl */
268     lt_dlloader *loader = 0;
269     lt_dlhandle handle = handles;
270     int errors = 0;
271    
272     if (!initialized)
273     {
274     LT__SETERROR (SHUTDOWN);
275     ++errors;
276     goto done;
277     }
278    
279     /* shut down only at last call. */
280     if (--initialized == 0)
281     {
282     int level;
283    
284     while (handles && LT_DLIS_RESIDENT (handles))
285     {
286     handles = handles->next;
287     }
288    
289     /* close all modules */
290     for (level = 1; handle; ++level)
291     {
292     lt_dlhandle cur = handles;
293     int saw_nonresident = 0;
294    
295     while (cur)
296     {
297     lt_dlhandle tmp = cur;
298     cur = cur->next;
299     if (!LT_DLIS_RESIDENT (tmp))
300     {
301     saw_nonresident = 1;
302     if (tmp->info.ref_count <= level)
303     {
304     if (lt_dlclose (tmp))
305     {
306     ++errors;
307     }
308     /* Make sure that the handle pointed to by 'cur' still exists.
309 michael 4901 lt_dlclose recursively closes dependent libraries, which removes
310 michael 945 them from the linked list. One of these might be the one
311     pointed to by 'cur'. */
312     if (cur)
313     {
314     for (tmp = handles; tmp; tmp = tmp->next)
315     if (tmp == cur)
316     break;
317     if (! tmp)
318     cur = handles;
319     }
320     }
321     }
322     }
323     /* done if only resident modules are left */
324     if (!saw_nonresident)
325     break;
326     }
327    
328     /* When removing loaders, we can only find out failure by testing
329     the error string, so avoid a spurious one from an earlier
330     failed command. */
331     if (!errors)
332     LT__SETERRORSTR (0);
333    
334     /* close all loaders */
335     for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
336     {
337     lt_dlloader *next = (lt_dlloader *) lt_dlloader_next (loader);
338     lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
339    
340     if ((vtable = lt_dlloader_remove ((char *) vtable->name)))
341     {
342     FREE (vtable);
343     }
344     else
345     {
346     /* ignore errors due to resident modules */
347     const char *err;
348     LT__GETERROR (err);
349     if (err)
350     ++errors;
351     }
352    
353     loader = next;
354     }
355    
356     FREE(user_search_path);
357     }
358    
359     done:
360     return errors;
361     }
362    
363    
364     /* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
365     If the library is not successfully loaded, return non-zero. Otherwise,
366     the dlhandle is stored at the address given in PHANDLE. */
367     static int
368     tryall_dlopen (lt_dlhandle *phandle, const char *filename,
369     lt_dladvise advise, const lt_dlvtable *vtable)
370     {
371     lt_dlhandle handle = handles;
372     const char * saved_error = 0;
373     int errors = 0;
374    
375     #ifdef LT_DEBUG_LOADERS
376     fprintf (stderr, "tryall_dlopen (%s, %s)\n",
377     filename ? filename : "(null)",
378     vtable ? vtable->name : "(ALL)");
379     #endif
380    
381     LT__GETERROR (saved_error);
382    
383     /* check whether the module was already opened */
384     for (;handle; handle = handle->next)
385     {
386     if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
387     || (handle->info.filename && filename
388 michael 4901 && STREQ (handle->info.filename, filename)))
389 michael 945 {
390     break;
391     }
392     }
393    
394     if (handle)
395     {
396     ++handle->info.ref_count;
397     *phandle = handle;
398     goto done;
399     }
400    
401     handle = *phandle;
402     if (filename)
403     {
404     /* Comment out the check of file permissions using access.
405     This call seems to always return -1 with error EACCES.
406     */
407     /* We need to catch missing file errors early so that
408     file_not_found() can detect what happened.
409     if (access (filename, R_OK) != 0)
410     {
411     LT__SETERROR (FILE_NOT_FOUND);
412     ++errors;
413     goto done;
414     } */
415    
416     handle->info.filename = lt__strdup (filename);
417     if (!handle->info.filename)
418     {
419     ++errors;
420     goto done;
421     }
422     }
423     else
424     {
425     handle->info.filename = 0;
426     }
427    
428     {
429     lt_dlloader loader = lt_dlloader_next (0);
430     const lt_dlvtable *loader_vtable;
431    
432     do
433     {
434     if (vtable)
435     loader_vtable = vtable;
436     else
437     loader_vtable = lt_dlloader_get (loader);
438    
439     #ifdef LT_DEBUG_LOADERS
440     fprintf (stderr, "Calling %s->module_open (%s)\n",
441     (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
442     filename ? filename : "(null)");
443     #endif
444     handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
445     filename, advise);
446     #ifdef LT_DEBUG_LOADERS
447 michael 4901 if (!handle->module) {
448     char *error;
449     LT__GETERROR(error);
450     fprintf (stderr, " Result: Failed\n"
451     " Error message << %s >>\n",
452     error ? error : "(null)");
453     } else {
454     fprintf (stderr, " Result: Success\n");
455     }
456 michael 945 #endif
457    
458     if (handle->module != 0)
459     {
460     if (advise)
461     {
462     handle->info.is_resident = advise->is_resident;
463     handle->info.is_symglobal = advise->is_symglobal;
464     handle->info.is_symlocal = advise->is_symlocal;
465     }
466     break;
467     }
468     }
469     while (!vtable && (loader = lt_dlloader_next (loader)));
470    
471     /* If VTABLE was given but couldn't open the module, or VTABLE wasn't
472     given but we exhausted all loaders without opening the module, bail
473     out! */
474     if ((vtable && !handle->module)
475     || (!vtable && !loader))
476     {
477     FREE (handle->info.filename);
478     ++errors;
479     goto done;
480     }
481    
482     handle->vtable = loader_vtable;
483     }
484    
485     LT__SETERRORSTR (saved_error);
486    
487     done:
488     return errors;
489     }
490    
491    
492     static int
493     tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
494     const char *dirname, const char *dlname,
495     lt_dladvise advise)
496     {
497     int error = 0;
498     char *filename = 0;
499     size_t filename_len = 0;
500     size_t dirname_len = LT_STRLEN (dirname);
501    
502     assert (handle);
503     assert (dirname);
504     assert (dlname);
505 michael 4901 #if defined LT_DIRSEP_CHAR
506 michael 945 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
507     should make it into this function: */
508     assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
509     #endif
510    
511     if (dirname_len > 0)
512     if (dirname[dirname_len -1] == '/')
513     --dirname_len;
514     filename_len = dirname_len + 1 + LT_STRLEN (dlname);
515    
516     /* Allocate memory, and combine DIRNAME and MODULENAME into it.
517     The PREFIX (if any) is handled below. */
518     filename = MALLOC (char, filename_len + 1);
519     if (!filename)
520     return 1;
521    
522     sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
523    
524     /* Now that we have combined DIRNAME and MODULENAME, if there is
525     also a PREFIX to contend with, simply recurse with the arguments
526     shuffled. Otherwise, attempt to open FILENAME as a module. */
527     if (prefix)
528     {
529     error += tryall_dlopen_module (handle, (const char *) 0,
530     prefix, filename, advise);
531     }
532     else if (tryall_dlopen (handle, filename, advise, 0) != 0)
533     {
534     ++error;
535     }
536    
537     FREE (filename);
538     return error;
539     }
540    
541     static int
542     find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
543     const char *dlname, const char *old_name, int installed,
544     lt_dladvise advise)
545     {
546     /* Try to open the old library first; if it was dlpreopened,
547     we want the preopened version of it, even if a dlopenable
548     module is available. */
549 michael 1037 if (old_name && tryall_dlopen (handle, old_name,
550     advise, lt_dlloader_find ("lt_preopen") ) == 0)
551 michael 945 {
552     return 0;
553     }
554    
555     /* Try to open the dynamic library. */
556     if (dlname)
557     {
558     /* try to open the installed module */
559     if (installed && libdir)
560     {
561     if (tryall_dlopen_module (handle, (const char *) 0,
562     libdir, dlname, advise) == 0)
563     return 0;
564     }
565    
566     /* try to open the not-installed module */
567     if (!installed)
568     {
569     if (tryall_dlopen_module (handle, dir, objdir,
570     dlname, advise) == 0)
571     return 0;
572     }
573    
574     /* maybe it was moved to another directory */
575     {
576     if (dir && (tryall_dlopen_module (handle, (const char *) 0,
577     dir, dlname, advise) == 0))
578     return 0;
579     }
580     }
581    
582     return 1;
583     }
584    
585    
586     static int
587     canonicalize_path (const char *path, char **pcanonical)
588     {
589     char *canonical = 0;
590    
591     assert (path && *path);
592     assert (pcanonical);
593    
594     canonical = MALLOC (char, 1+ LT_STRLEN (path));
595     if (!canonical)
596     return 1;
597    
598     {
599     size_t dest = 0;
600     size_t src;
601     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
602     {
603     /* Path separators are not copied to the beginning or end of
604     the destination, or if another separator would follow
605     immediately. */
606     if (path[src] == LT_PATHSEP_CHAR)
607     {
608     if ((dest == 0)
609     || (path[1+ src] == LT_PATHSEP_CHAR)
610     || (path[1+ src] == LT_EOS_CHAR))
611     continue;
612     }
613    
614     /* Anything other than a directory separator is copied verbatim. */
615     if ((path[src] != '/')
616 michael 4901 #if defined LT_DIRSEP_CHAR
617 michael 945 && (path[src] != LT_DIRSEP_CHAR)
618     #endif
619     )
620     {
621     canonical[dest++] = path[src];
622     }
623     /* Directory separators are converted and copied only if they are
624     not at the end of a path -- i.e. before a path separator or
625     NULL terminator. */
626     else if ((path[1+ src] != LT_PATHSEP_CHAR)
627     && (path[1+ src] != LT_EOS_CHAR)
628 michael 4901 #if defined LT_DIRSEP_CHAR
629 michael 945 && (path[1+ src] != LT_DIRSEP_CHAR)
630     #endif
631     && (path[1+ src] != '/'))
632     {
633     canonical[dest++] = '/';
634     }
635     }
636    
637     /* Add an end-of-string marker at the end. */
638     canonical[dest] = LT_EOS_CHAR;
639     }
640    
641     /* Assign new value. */
642     *pcanonical = canonical;
643    
644     return 0;
645     }
646    
647     static int
648     argzize_path (const char *path, char **pargz, size_t *pargz_len)
649     {
650     error_t error;
651    
652     assert (path);
653     assert (pargz);
654     assert (pargz_len);
655    
656     if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
657     {
658     switch (error)
659     {
660     case ENOMEM:
661     LT__SETERROR (NO_MEMORY);
662     break;
663     default:
664     LT__SETERROR (UNKNOWN);
665     break;
666     }
667    
668     return 1;
669     }
670    
671     return 0;
672     }
673    
674     /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
675     of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
676     non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
677     it is appended to each SEARCH_PATH element before FUNC is called. */
678     static int
679     foreach_dirinpath (const char *search_path, const char *base_name,
680     foreach_callback_func *func, void *data1, void *data2)
681     {
682     int result = 0;
683     size_t filenamesize = 0;
684     size_t lenbase = LT_STRLEN (base_name);
685     size_t argz_len = 0;
686     char *argz = 0;
687     char *filename = 0;
688     char *canonical = 0;
689    
690     if (!search_path || !*search_path)
691     {
692     LT__SETERROR (FILE_NOT_FOUND);
693     goto cleanup;
694     }
695    
696     if (canonicalize_path (search_path, &canonical) != 0)
697     goto cleanup;
698    
699     if (argzize_path (canonical, &argz, &argz_len) != 0)
700     goto cleanup;
701    
702     {
703     char *dir_name = 0;
704     while ((dir_name = argz_next (argz, argz_len, dir_name)))
705     {
706     size_t lendir = LT_STRLEN (dir_name);
707    
708     if (1+ lendir + lenbase >= filenamesize)
709     {
710     FREE (filename);
711     filenamesize = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
712     filename = MALLOC (char, filenamesize);
713     if (!filename)
714     goto cleanup;
715     }
716    
717     assert (filenamesize > lendir);
718     strcpy (filename, dir_name);
719    
720     if (base_name && *base_name)
721     {
722     if (filename[lendir -1] != '/')
723     filename[lendir++] = '/';
724     strcpy (filename +lendir, base_name);
725     }
726    
727     if ((result = (*func) (filename, data1, data2)))
728     {
729     break;
730     }
731     }
732     }
733    
734     cleanup:
735     FREE (argz);
736     FREE (canonical);
737     FREE (filename);
738    
739     return result;
740     }
741    
742     /* If FILEPATH can be opened, store the name of the directory component
743     in DATA1, and the opened FILE* structure address in DATA2. Otherwise
744     DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
745     static int
746     find_file_callback (char *filename, void *data1, void *data2)
747     {
748     char **pdir = (char **) data1;
749     FILE **pfile = (FILE **) data2;
750     int is_done = 0;
751    
752     assert (filename && *filename);
753     assert (pdir);
754     assert (pfile);
755    
756     if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
757     {
758     char *dirend = strrchr (filename, '/');
759    
760     if (dirend > filename)
761     *dirend = LT_EOS_CHAR;
762    
763     FREE (*pdir);
764     *pdir = lt__strdup (filename);
765     is_done = (*pdir == 0) ? -1 : 1;
766     }
767    
768     return is_done;
769     }
770    
771     static FILE *
772     find_file (const char *search_path, const char *base_name, char **pdir)
773     {
774     FILE *file = 0;
775    
776     foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
777    
778     return file;
779     }
780    
781     static int
782     find_handle_callback (char *filename, void *data, void *data2)
783     {
784     lt_dlhandle *phandle = (lt_dlhandle *) data;
785     int notfound = access (filename, R_OK);
786     lt_dladvise advise = (lt_dladvise) data2;
787    
788     /* Bail out if file cannot be read... */
789     if (notfound)
790     return 0;
791    
792     /* Try to dlopen the file, but do not continue searching in any
793     case. */
794     if (tryall_dlopen (phandle, filename, advise, 0) != 0)
795     *phandle = 0;
796    
797     return 1;
798     }
799    
800     /* If HANDLE was found return it, otherwise return 0. If HANDLE was
801     found but could not be opened, *HANDLE will be set to 0. */
802     static lt_dlhandle *
803     find_handle (const char *search_path, const char *base_name,
804     lt_dlhandle *phandle, lt_dladvise advise)
805     {
806     if (!search_path)
807     return 0;
808    
809     if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
810     phandle, advise))
811     return 0;
812    
813     return phandle;
814     }
815    
816 michael 4901 #if !defined LTDL_DLOPEN_DEPLIBS
817 michael 945 static int
818 michael 5394 load_deplibs (lt_dlhandle handle, char * deplibs LT__UNUSED)
819 michael 945 {
820     handle->depcount = 0;
821     return 0;
822     }
823    
824 michael 4901 #else /* defined LTDL_DLOPEN_DEPLIBS */
825 michael 945 static int
826     load_deplibs (lt_dlhandle handle, char *deplibs)
827     {
828     char *p, *save_search_path = 0;
829     int depcount = 0;
830     int i;
831     char **names = 0;
832     int errors = 0;
833    
834     handle->depcount = 0;
835    
836     if (!deplibs)
837     {
838     return errors;
839     }
840     ++errors;
841    
842     if (user_search_path)
843     {
844     save_search_path = lt__strdup (user_search_path);
845     if (!save_search_path)
846     goto cleanup;
847     }
848    
849     /* extract search paths and count deplibs */
850     p = deplibs;
851     while (*p)
852     {
853     if (!isspace ((unsigned char) *p))
854     {
855     char *end = p+1;
856     while (*end && !isspace((unsigned char) *end))
857     {
858     ++end;
859     }
860    
861     if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
862     {
863     char save = *end;
864     *end = 0; /* set a temporary string terminator */
865     if (lt_dladdsearchdir(p+2))
866     {
867     goto cleanup;
868     }
869     *end = save;
870     }
871     else
872     {
873     ++depcount;
874     }
875    
876     p = end;
877     }
878     else
879     {
880     ++p;
881     }
882     }
883    
884    
885     if (!depcount)
886     {
887     errors = 0;
888     goto cleanup;
889     }
890    
891     names = MALLOC (char *, depcount);
892     if (!names)
893     goto cleanup;
894    
895     /* now only extract the actual deplibs */
896     depcount = 0;
897     p = deplibs;
898     while (*p)
899     {
900     if (isspace ((unsigned char) *p))
901     {
902     ++p;
903     }
904     else
905     {
906     char *end = p+1;
907     while (*end && !isspace ((unsigned char) *end))
908     {
909     ++end;
910     }
911    
912     if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
913     {
914     char *name;
915     char save = *end;
916     *end = 0; /* set a temporary string terminator */
917     if (strncmp(p, "-l", 2) == 0)
918     {
919     size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
920     name = MALLOC (char, 1+ name_len);
921     if (name)
922     sprintf (name, "lib%s", p+2);
923     }
924     else
925     name = lt__strdup(p);
926    
927     if (!name)
928     goto cleanup_names;
929    
930     names[depcount++] = name;
931     *end = save;
932     }
933     p = end;
934     }
935     }
936    
937     /* load the deplibs (in reverse order)
938     At this stage, don't worry if the deplibs do not load correctly,
939     they may already be statically linked into the loading application
940     for instance. There will be a more enlightening error message
941     later on if the loaded module cannot resolve all of its symbols. */
942     if (depcount)
943     {
944     lt_dlhandle cur = handle;
945     int j = 0;
946    
947     cur->deplibs = MALLOC (lt_dlhandle, depcount);
948     if (!cur->deplibs)
949     goto cleanup_names;
950    
951     for (i = 0; i < depcount; ++i)
952     {
953     cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
954     if (cur->deplibs[j])
955     {
956     ++j;
957     }
958     }
959    
960     cur->depcount = j; /* Number of successfully loaded deplibs */
961     errors = 0;
962     }
963    
964     cleanup_names:
965     for (i = 0; i < depcount; ++i)
966     {
967     FREE (names[i]);
968     }
969    
970     cleanup:
971     FREE (names);
972     /* restore the old search path */
973     if (save_search_path) {
974     MEMREASSIGN (user_search_path, save_search_path);
975     }
976    
977     return errors;
978     }
979 michael 4901 #endif /* defined LTDL_DLOPEN_DEPLIBS */
980 michael 945
981     static int
982     unload_deplibs (lt_dlhandle handle)
983     {
984     int i;
985     int errors = 0;
986     lt_dlhandle cur = handle;
987    
988     if (cur->depcount)
989     {
990     for (i = 0; i < cur->depcount; ++i)
991     {
992     if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
993     {
994     errors += lt_dlclose (cur->deplibs[i]);
995     }
996     }
997     FREE (cur->deplibs);
998     }
999    
1000     return errors;
1001     }
1002    
1003     static int
1004     trim (char **dest, const char *str)
1005     {
1006     /* remove the leading and trailing "'" from str
1007     and store the result in dest */
1008     const char *end = strrchr (str, '\'');
1009     size_t len = LT_STRLEN (str);
1010     char *tmp;
1011    
1012     FREE (*dest);
1013    
1014 michael 1094 if (!end || end == str)
1015 michael 945 return 1;
1016    
1017     if (len > 3 && str[0] == '\'')
1018     {
1019     tmp = MALLOC (char, end - str);
1020     if (!tmp)
1021     return 1;
1022    
1023     memcpy(tmp, &str[1], (end - str) - 1);
1024     tmp[(end - str) - 1] = LT_EOS_CHAR;
1025     *dest = tmp;
1026     }
1027     else
1028     {
1029     *dest = 0;
1030     }
1031    
1032     return 0;
1033     }
1034    
1035     /* Read the .la file FILE. */
1036     static int
1037     parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
1038     char **old_name, int *installed)
1039     {
1040     int errors = 0;
1041     size_t line_len = LT_FILENAME_MAX;
1042     char * line = MALLOC (char, line_len);
1043    
1044     if (!line)
1045     {
1046     LT__SETERROR (FILE_NOT_FOUND);
1047     return 1;
1048     }
1049    
1050     while (!feof (file))
1051     {
1052     line[line_len-2] = '\0';
1053     if (!fgets (line, (int) line_len, file))
1054     {
1055     break;
1056     }
1057    
1058     /* Handle the case where we occasionally need to read a line
1059     that is longer than the initial buffer size.
1060     Behave even if the file contains NUL bytes due to corruption. */
1061     while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
1062     {
1063     line = REALLOC (char, line, line_len *2);
1064     if (!line)
1065     {
1066     ++errors;
1067     goto cleanup;
1068     }
1069     line[line_len * 2 - 2] = '\0';
1070     if (!fgets (&line[line_len -1], (int) line_len +1, file))
1071     {
1072     break;
1073     }
1074     line_len *= 2;
1075     }
1076    
1077     if (line[0] == '\n' || line[0] == '#')
1078     {
1079     continue;
1080     }
1081    
1082     #undef STR_DLNAME
1083     #define STR_DLNAME "dlname="
1084     if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
1085     {
1086     errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
1087     }
1088    
1089     #undef STR_OLD_LIBRARY
1090     #define STR_OLD_LIBRARY "old_library="
1091     else if (strncmp (line, STR_OLD_LIBRARY,
1092     sizeof (STR_OLD_LIBRARY) - 1) == 0)
1093     {
1094     errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
1095     }
1096 michael 1094
1097     /* Windows native tools do not understand the POSIX paths we store
1098     in libdir. */
1099 michael 945 #undef STR_LIBDIR
1100     #define STR_LIBDIR "libdir="
1101     else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
1102     {
1103     errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
1104 michael 1107 #ifdef __WINDOWS__
1105     /* Disallow following unix-style paths on MinGW. */
1106     if (*libdir && (**libdir == '/' || **libdir == '\\'))
1107     **libdir = '\0';
1108     #endif
1109 michael 945 }
1110    
1111     #undef STR_DL_DEPLIBS
1112     #define STR_DL_DEPLIBS "dependency_libs="
1113     else if (strncmp (line, STR_DL_DEPLIBS,
1114     sizeof (STR_DL_DEPLIBS) - 1) == 0)
1115     {
1116     errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
1117     }
1118 michael 4901 else if (STREQ (line, "installed=yes\n"))
1119 michael 945 {
1120     *installed = 1;
1121     }
1122 michael 4901 else if (STREQ (line, "installed=no\n"))
1123 michael 945 {
1124     *installed = 0;
1125     }
1126    
1127     #undef STR_LIBRARY_NAMES
1128     #define STR_LIBRARY_NAMES "library_names="
1129     else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
1130     sizeof (STR_LIBRARY_NAMES) - 1) == 0)
1131     {
1132     char *last_libname;
1133     errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
1134     if (!errors
1135     && *dlname
1136     && (last_libname = strrchr (*dlname, ' ')) != 0)
1137     {
1138     last_libname = lt__strdup (last_libname + 1);
1139     if (!last_libname)
1140     {
1141     ++errors;
1142     goto cleanup;
1143     }
1144     MEMREASSIGN (*dlname, last_libname);
1145     }
1146     }
1147    
1148     if (errors)
1149     break;
1150     }
1151     cleanup:
1152     FREE (line);
1153     return errors;
1154     }
1155    
1156    
1157     /* Try to open FILENAME as a module. */
1158     static int
1159     try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
1160     lt_dladvise advise)
1161     {
1162     const char * saved_error = 0;
1163     char * archive_name = 0;
1164     char * canonical = 0;
1165     char * base_name = 0;
1166     char * dir = 0;
1167     char * name = 0;
1168     char * attempt = 0;
1169     int errors = 0;
1170     lt_dlhandle newhandle;
1171    
1172     assert (phandle);
1173     assert (*phandle == 0);
1174    
1175     #ifdef LT_DEBUG_LOADERS
1176     fprintf (stderr, "try_dlopen (%s, %s)\n",
1177     filename ? filename : "(null)",
1178     ext ? ext : "(null)");
1179     #endif
1180    
1181     LT__GETERROR (saved_error);
1182    
1183     /* dlopen self? */
1184     if (!filename)
1185     {
1186     *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1187     if (*phandle == 0)
1188     return 1;
1189    
1190     newhandle = *phandle;
1191    
1192     /* lt_dlclose()ing yourself is very bad! Disallow it. */
1193     newhandle->info.is_resident = 1;
1194    
1195     if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1196     {
1197     FREE (*phandle);
1198     return 1;
1199     }
1200    
1201     goto register_handle;
1202     }
1203    
1204     assert (filename && *filename);
1205    
1206     if (ext)
1207     {
1208     attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
1209     if (!attempt)
1210     return 1;
1211    
1212     sprintf(attempt, "%s%s", filename, ext);
1213     }
1214     else
1215     {
1216     attempt = lt__strdup (filename);
1217     if (!attempt)
1218     return 1;
1219     }
1220    
1221     /* Doing this immediately allows internal functions to safely
1222     assume only canonicalized paths are passed. */
1223     if (canonicalize_path (attempt, &canonical) != 0)
1224     {
1225     ++errors;
1226     goto cleanup;
1227     }
1228    
1229     /* If the canonical module name is a path (relative or absolute)
1230     then split it into a directory part and a name part. */
1231     base_name = strrchr (canonical, '/');
1232     if (base_name)
1233     {
1234     size_t dirlen = (1+ base_name) - canonical;
1235    
1236     dir = MALLOC (char, 1+ dirlen);
1237     if (!dir)
1238     {
1239     ++errors;
1240     goto cleanup;
1241     }
1242    
1243 michael 4901 strlcpy (dir, canonical, dirlen);
1244 michael 945 dir[dirlen] = LT_EOS_CHAR;
1245    
1246     ++base_name;
1247     }
1248     else
1249     MEMREASSIGN (base_name, canonical);
1250    
1251     assert (base_name && *base_name);
1252    
1253     ext = strrchr (base_name, '.');
1254     if (!ext)
1255     {
1256     ext = base_name + LT_STRLEN (base_name);
1257     }
1258    
1259     /* extract the module name from the file name */
1260     name = MALLOC (char, ext - base_name + 1);
1261     if (!name)
1262     {
1263     ++errors;
1264     goto cleanup;
1265     }
1266    
1267     /* canonicalize the module name */
1268     {
1269     int i;
1270     for (i = 0; i < ext - base_name; ++i)
1271     {
1272     if (isalnum ((unsigned char)(base_name[i])))
1273     {
1274     name[i] = base_name[i];
1275     }
1276     else
1277     {
1278     name[i] = '_';
1279     }
1280     }
1281     name[ext - base_name] = LT_EOS_CHAR;
1282     }
1283    
1284 michael 4901 /* Before trawling through the file system in search of a module,
1285 michael 945 check whether we are opening a preloaded module. */
1286     if (!dir)
1287     {
1288     const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1289    
1290     if (vtable)
1291     {
1292 michael 1107 /* libprefix + name + "." + libext + NULL */
1293     archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
1294 michael 945 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1295    
1296     if ((*phandle == NULL) || (archive_name == NULL))
1297     {
1298     ++errors;
1299     goto cleanup;
1300     }
1301     newhandle = *phandle;
1302    
1303     /* Preloaded modules are always named according to their old
1304     archive name. */
1305 michael 1107 if (strncmp(name, "lib", 3) == 0)
1306     {
1307     sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
1308     }
1309     else
1310     {
1311     sprintf (archive_name, "%s.%s", name, libext);
1312     }
1313 michael 945
1314     if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
1315     {
1316     goto register_handle;
1317     }
1318    
1319     /* If we're still here, there was no matching preloaded module,
1320     so put things back as we found them, and continue searching. */
1321     FREE (*phandle);
1322     newhandle = NULL;
1323     }
1324     }
1325    
1326     /* If we are allowing only preloaded modules, and we didn't find
1327     anything yet, give up on the search here. */
1328     if (advise && advise->try_preload_only)
1329     {
1330     goto cleanup;
1331     }
1332    
1333     /* Check whether we are opening a libtool module (.la extension). */
1334 michael 4901 if (ext && STREQ (ext, archive_ext))
1335 michael 945 {
1336     /* this seems to be a libtool module */
1337     FILE * file = 0;
1338     char * dlname = 0;
1339     char * old_name = 0;
1340     char * libdir = 0;
1341     char * deplibs = 0;
1342    
1343     /* if we can't find the installed flag, it is probably an
1344     installed libtool archive, produced with an old version
1345     of libtool */
1346     int installed = 1;
1347    
1348     /* Now try to open the .la file. If there is no directory name
1349     component, try to find it first in user_search_path and then other
1350     prescribed paths. Otherwise (or in any case if the module was not
1351     yet found) try opening just the module name as passed. */
1352     if (!dir)
1353     {
1354     const char *search_path = user_search_path;
1355    
1356     if (search_path)
1357     file = find_file (user_search_path, base_name, &dir);
1358    
1359     if (!file)
1360     {
1361     search_path = getenv (LTDL_SEARCHPATH_VAR);
1362     if (search_path)
1363     file = find_file (search_path, base_name, &dir);
1364     }
1365    
1366 michael 4901 #if defined LT_MODULE_PATH_VAR
1367 michael 945 if (!file)
1368     {
1369     search_path = getenv (LT_MODULE_PATH_VAR);
1370     if (search_path)
1371     file = find_file (search_path, base_name, &dir);
1372     }
1373     #endif
1374 michael 4901 #if defined LT_DLSEARCH_PATH
1375 michael 945 if (!file && *sys_dlsearch_path)
1376     {
1377     file = find_file (sys_dlsearch_path, base_name, &dir);
1378     }
1379     #endif
1380     }
1381 michael 1037 else
1382 michael 945 {
1383     file = fopen (attempt, LT_READTEXT_MODE);
1384     }
1385    
1386     /* If we didn't find the file by now, it really isn't there. Set
1387     the status flag, and bail out. */
1388     if (!file)
1389     {
1390     LT__SETERROR (FILE_NOT_FOUND);
1391     ++errors;
1392     goto cleanup;
1393     }
1394    
1395     /* read the .la file */
1396     if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1397     &old_name, &installed) != 0)
1398     ++errors;
1399    
1400     fclose (file);
1401    
1402     /* allocate the handle */
1403     *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1404     if (*phandle == 0)
1405     ++errors;
1406    
1407     if (errors)
1408     {
1409     FREE (dlname);
1410     FREE (old_name);
1411     FREE (libdir);
1412     FREE (deplibs);
1413     FREE (*phandle);
1414     goto cleanup;
1415     }
1416    
1417     assert (*phandle);
1418    
1419     if (load_deplibs (*phandle, deplibs) == 0)
1420     {
1421     newhandle = *phandle;
1422     /* find_module may replace newhandle */
1423     if (find_module (&newhandle, dir, libdir, dlname, old_name,
1424     installed, advise))
1425     {
1426     unload_deplibs (*phandle);
1427     ++errors;
1428     }
1429     }
1430     else
1431     {
1432     ++errors;
1433     }
1434    
1435     FREE (dlname);
1436     FREE (old_name);
1437     FREE (libdir);
1438     FREE (deplibs);
1439    
1440     if (errors)
1441     {
1442     FREE (*phandle);
1443     goto cleanup;
1444     }
1445    
1446     if (*phandle != newhandle)
1447     {
1448     unload_deplibs (*phandle);
1449     }
1450     }
1451     else
1452     {
1453     /* not a libtool module */
1454     *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1455     if (*phandle == 0)
1456     {
1457     ++errors;
1458     goto cleanup;
1459     }
1460    
1461     newhandle = *phandle;
1462    
1463     /* If the module has no directory name component, try to find it
1464     first in user_search_path and then other prescribed paths.
1465     Otherwise (or in any case if the module was not yet found) try
1466     opening just the module name as passed. */
1467     if ((dir || (!find_handle (user_search_path, base_name,
1468     &newhandle, advise)
1469     && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
1470     &newhandle, advise)
1471 michael 4901 #if defined LT_MODULE_PATH_VAR
1472 michael 945 && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1473     &newhandle, advise)
1474     #endif
1475 michael 4901 #if defined LT_DLSEARCH_PATH
1476 michael 945 && !find_handle (sys_dlsearch_path, base_name,
1477     &newhandle, advise)
1478     #endif
1479     )))
1480     {
1481     if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1482     {
1483     newhandle = NULL;
1484     }
1485     }
1486    
1487     if (!newhandle)
1488     {
1489     FREE (*phandle);
1490     ++errors;
1491     goto cleanup;
1492     }
1493     }
1494    
1495     register_handle:
1496     MEMREASSIGN (*phandle, newhandle);
1497    
1498     if ((*phandle)->info.ref_count == 0)
1499     {
1500     (*phandle)->info.ref_count = 1;
1501     MEMREASSIGN ((*phandle)->info.name, name);
1502    
1503     (*phandle)->next = handles;
1504     handles = *phandle;
1505     }
1506    
1507     LT__SETERRORSTR (saved_error);
1508    
1509     cleanup:
1510     FREE (dir);
1511     FREE (attempt);
1512     FREE (name);
1513     if (!canonical) /* was MEMREASSIGNed */
1514     FREE (base_name);
1515     FREE (canonical);
1516     FREE (archive_name);
1517    
1518     return errors;
1519     }
1520    
1521    
1522 michael 4901 /* If the last error message stored was 'FILE_NOT_FOUND', then return
1523 michael 945 non-zero. */
1524     static int
1525     file_not_found (void)
1526     {
1527     const char *error = 0;
1528    
1529     LT__GETERROR (error);
1530     if (error == LT__STRERROR (FILE_NOT_FOUND))
1531     return 1;
1532    
1533     return 0;
1534     }
1535    
1536    
1537     /* Unless FILENAME already bears a suitable library extension, then
1538     return 0. */
1539     static int
1540     has_library_ext (const char *filename)
1541     {
1542 michael 1094 const char * ext = 0;
1543 michael 945
1544     assert (filename);
1545    
1546     ext = strrchr (filename, '.');
1547    
1548 michael 4901 if (ext && ((STREQ (ext, archive_ext))
1549     #if defined LT_MODULE_EXT
1550     || (STREQ (ext, shlib_ext))
1551 michael 945 #endif
1552 michael 4901 #if defined LT_SHARED_EXT
1553     || (STREQ (ext, shared_ext))
1554 michael 1257 #endif
1555 michael 945 ))
1556     {
1557     return 1;
1558     }
1559    
1560     return 0;
1561     }
1562    
1563    
1564     /* Initialise and configure a user lt_dladvise opaque object. */
1565    
1566     int
1567     lt_dladvise_init (lt_dladvise *padvise)
1568     {
1569     lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
1570     *padvise = advise;
1571     return (advise ? 0 : 1);
1572     }
1573    
1574     int
1575     lt_dladvise_destroy (lt_dladvise *padvise)
1576     {
1577     if (padvise)
1578     FREE(*padvise);
1579     return 0;
1580     }
1581    
1582     int
1583     lt_dladvise_ext (lt_dladvise *padvise)
1584     {
1585     assert (padvise && *padvise);
1586     (*padvise)->try_ext = 1;
1587     return 0;
1588     }
1589    
1590     int
1591     lt_dladvise_resident (lt_dladvise *padvise)
1592     {
1593     assert (padvise && *padvise);
1594     (*padvise)->is_resident = 1;
1595     return 0;
1596     }
1597    
1598     int
1599     lt_dladvise_local (lt_dladvise *padvise)
1600     {
1601     assert (padvise && *padvise);
1602     (*padvise)->is_symlocal = 1;
1603     return 0;
1604     }
1605    
1606     int
1607     lt_dladvise_global (lt_dladvise *padvise)
1608     {
1609     assert (padvise && *padvise);
1610     (*padvise)->is_symglobal = 1;
1611     return 0;
1612     }
1613    
1614     int
1615     lt_dladvise_preload (lt_dladvise *padvise)
1616     {
1617     assert (padvise && *padvise);
1618     (*padvise)->try_preload_only = 1;
1619     return 0;
1620     }
1621    
1622     /* Libtool-1.5.x interface for loading a new module named FILENAME. */
1623     lt_dlhandle
1624     lt_dlopen (const char *filename)
1625     {
1626     return lt_dlopenadvise (filename, NULL);
1627     }
1628    
1629    
1630     /* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to
1631     open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
1632     and if a file is still not found try again with MODULE_EXT appended
1633     instead. */
1634     lt_dlhandle
1635     lt_dlopenext (const char *filename)
1636     {
1637     lt_dlhandle handle = 0;
1638     lt_dladvise advise;
1639    
1640     if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
1641     handle = lt_dlopenadvise (filename, advise);
1642    
1643     lt_dladvise_destroy (&advise);
1644     return handle;
1645     }
1646    
1647    
1648     lt_dlhandle
1649     lt_dlopenadvise (const char *filename, lt_dladvise advise)
1650     {
1651     lt_dlhandle handle = 0;
1652     int errors = 0;
1653 michael 1094 const char * saved_error = 0;
1654 michael 945
1655 michael 1094 LT__GETERROR (saved_error);
1656    
1657 michael 945 /* Can't have symbols hidden and visible at the same time! */
1658     if (advise && advise->is_symlocal && advise->is_symglobal)
1659     {
1660     LT__SETERROR (CONFLICTING_FLAGS);
1661     return 0;
1662     }
1663    
1664     if (!filename
1665     || !advise
1666     || !advise->try_ext
1667     || has_library_ext (filename))
1668     {
1669     /* Just incase we missed a code path in try_dlopen() that reports
1670     an error, but forgot to reset handle... */
1671     if (try_dlopen (&handle, filename, NULL, advise) != 0)
1672     return 0;
1673    
1674     return handle;
1675     }
1676     else if (filename && *filename)
1677     {
1678    
1679     /* First try appending ARCHIVE_EXT. */
1680     errors += try_dlopen (&handle, filename, archive_ext, advise);
1681    
1682     /* If we found FILENAME, stop searching -- whether we were able to
1683     load the file as a module or not. If the file exists but loading
1684     failed, it is better to return an error message here than to
1685     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
1686     in the module search path. */
1687     if (handle || ((errors > 0) && !file_not_found ()))
1688     return handle;
1689    
1690 michael 4901 #if defined LT_MODULE_EXT
1691 michael 945 /* Try appending SHLIB_EXT. */
1692 michael 1094 LT__SETERRORSTR (saved_error);
1693 michael 945 errors = try_dlopen (&handle, filename, shlib_ext, advise);
1694    
1695     /* As before, if the file was found but loading failed, return now
1696     with the current error message. */
1697     if (handle || ((errors > 0) && !file_not_found ()))
1698     return handle;
1699     #endif
1700 michael 1257
1701 michael 4901 #if defined LT_SHARED_EXT
1702 michael 1257 /* Try appending SHARED_EXT. */
1703     LT__SETERRORSTR (saved_error);
1704     errors = try_dlopen (&handle, filename, shared_ext, advise);
1705    
1706     /* As before, if the file was found but loading failed, return now
1707     with the current error message. */
1708     if (handle || ((errors > 0) && !file_not_found ()))
1709     return handle;
1710     #endif
1711 michael 945 }
1712    
1713     /* Still here? Then we really did fail to locate any of the file
1714     names we tried. */
1715     LT__SETERROR (FILE_NOT_FOUND);
1716     return 0;
1717     }
1718    
1719    
1720     static int
1721     lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1722     const char *entry)
1723     {
1724     error_t error;
1725    
1726     /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1727     pargz_len, NULL, entry) failed with EINVAL. */
1728     if (before)
1729     error = argz_insert (pargz, pargz_len, before, entry);
1730     else
1731     error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1732    
1733     if (error)
1734     {
1735     switch (error)
1736     {
1737     case ENOMEM:
1738     LT__SETERROR (NO_MEMORY);
1739     break;
1740     default:
1741     LT__SETERROR (UNKNOWN);
1742     break;
1743     }
1744     return 1;
1745     }
1746    
1747     return 0;
1748     }
1749    
1750     static int
1751     lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1752     {
1753     char *before = 0;
1754    
1755     assert (pargz);
1756     assert (pargz_len);
1757     assert (entry && *entry);
1758    
1759     if (*pargz)
1760     while ((before = argz_next (*pargz, *pargz_len, before)))
1761     {
1762     int cmp = strcmp (entry, before);
1763    
1764     if (cmp < 0) break;
1765     if (cmp == 0) return 0; /* No duplicates! */
1766     }
1767    
1768     return lt_argz_insert (pargz, pargz_len, before, entry);
1769     }
1770    
1771     static int
1772     lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1773     struct dirent *dp)
1774     {
1775     char *buf = 0;
1776     size_t buf_len = 0;
1777     char *end = 0;
1778     size_t end_offset = 0;
1779     size_t dir_len = 0;
1780     int errors = 0;
1781    
1782     assert (pargz);
1783     assert (pargz_len);
1784     assert (dp);
1785    
1786     dir_len = LT_STRLEN (dirnam);
1787     end = dp->d_name + D_NAMLEN(dp);
1788    
1789     /* Ignore version numbers. */
1790     {
1791     char *p;
1792     for (p = end; p -1 > dp->d_name; --p)
1793     if (strchr (".0123456789", p[-1]) == 0)
1794     break;
1795    
1796     if (*p == '.')
1797     end = p;
1798     }
1799    
1800     /* Ignore filename extension. */
1801     {
1802     char *p;
1803     for (p = end -1; p > dp->d_name; --p)
1804     if (*p == '.')
1805     {
1806     end = p;
1807     break;
1808     }
1809     }
1810    
1811     /* Prepend the directory name. */
1812     end_offset = end - dp->d_name;
1813     buf_len = dir_len + 1+ end_offset;
1814     buf = MALLOC (char, 1+ buf_len);
1815     if (!buf)
1816     return ++errors;
1817    
1818     assert (buf);
1819    
1820     strcpy (buf, dirnam);
1821     strcat (buf, "/");
1822     strncat (buf, dp->d_name, end_offset);
1823     buf[buf_len] = LT_EOS_CHAR;
1824    
1825     /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
1826     if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1827     ++errors;
1828    
1829     FREE (buf);
1830    
1831     return errors;
1832     }
1833    
1834     static int
1835     list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1836     {
1837     DIR *dirp = 0;
1838     int errors = 0;
1839    
1840     assert (dirnam && *dirnam);
1841     assert (pargz);
1842     assert (pargz_len);
1843     assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1844    
1845     dirp = opendir (dirnam);
1846     if (dirp)
1847     {
1848     struct dirent *dp = 0;
1849    
1850     while ((dp = readdir (dirp)))
1851     if (dp->d_name[0] != '.')
1852     if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1853     {
1854     ++errors;
1855     break;
1856     }
1857    
1858     closedir (dirp);
1859     }
1860     else
1861     ++errors;
1862    
1863     return errors;
1864     }
1865    
1866    
1867     /* If there are any files in DIRNAME, call the function passed in
1868     DATA1 (with the name of each file and DATA2 as arguments). */
1869     static int
1870     foreachfile_callback (char *dirname, void *data1, void *data2)
1871     {
1872     file_worker_func *func = *(file_worker_func **) data1;
1873    
1874     int is_done = 0;
1875     char *argz = 0;
1876     size_t argz_len = 0;
1877    
1878     if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1879     goto cleanup;
1880     if (!argz)
1881     goto cleanup;
1882    
1883     {
1884     char *filename = 0;
1885     while ((filename = argz_next (argz, argz_len, filename)))
1886     if ((is_done = (*func) (filename, data2)))
1887     break;
1888     }
1889    
1890     cleanup:
1891     FREE (argz);
1892    
1893     return is_done;
1894     }
1895    
1896    
1897     /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
1898     with DATA. The filenames passed to FUNC would be suitable for
1899     passing to lt_dlopenext. The extensions are stripped so that
1900     individual modules do not generate several entries (e.g. libfoo.la,
1901     libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
1902     then the same directories that lt_dlopen would search are examined. */
1903     int
1904     lt_dlforeachfile (const char *search_path,
1905     int (*func) (const char *filename, void *data),
1906     void *data)
1907     {
1908     int is_done = 0;
1909     file_worker_func **fpptr = &func;
1910    
1911     if (search_path)
1912     {
1913     /* If a specific path was passed, search only the directories
1914     listed in it. */
1915     is_done = foreach_dirinpath (search_path, 0,
1916     foreachfile_callback, fpptr, data);
1917     }
1918     else
1919     {
1920     /* Otherwise search the default paths. */
1921     is_done = foreach_dirinpath (user_search_path, 0,
1922     foreachfile_callback, fpptr, data);
1923     if (!is_done)
1924     {
1925     is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1926     foreachfile_callback, fpptr, data);
1927     }
1928    
1929 michael 4901 #if defined LT_MODULE_PATH_VAR
1930 michael 945 if (!is_done)
1931     {
1932     is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1933     foreachfile_callback, fpptr, data);
1934     }
1935     #endif
1936 michael 4901 #if defined LT_DLSEARCH_PATH
1937 michael 945 if (!is_done && *sys_dlsearch_path)
1938     {
1939     is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1940     foreachfile_callback, fpptr, data);
1941     }
1942     #endif
1943     }
1944    
1945     return is_done;
1946     }
1947    
1948     int
1949     lt_dlclose (lt_dlhandle handle)
1950     {
1951     lt_dlhandle cur, last;
1952     int errors = 0;
1953    
1954     /* check whether the handle is valid */
1955     last = cur = handles;
1956     while (cur && handle != cur)
1957     {
1958     last = cur;
1959     cur = cur->next;
1960     }
1961    
1962     if (!cur)
1963     {
1964     LT__SETERROR (INVALID_HANDLE);
1965     ++errors;
1966     goto done;
1967     }
1968    
1969     cur = handle;
1970     cur->info.ref_count--;
1971    
1972     /* Note that even with resident modules, we must track the ref_count
1973     correctly incase the user decides to reset the residency flag
1974     later (even though the API makes no provision for that at the
1975     moment). */
1976     if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1977     {
1978     lt_user_data data = cur->vtable->dlloader_data;
1979    
1980     if (cur != handles)
1981     {
1982     last->next = cur->next;
1983     }
1984     else
1985     {
1986     handles = cur->next;
1987     }
1988    
1989     errors += cur->vtable->module_close (data, cur->module);
1990     errors += unload_deplibs (handle);
1991    
1992     /* It is up to the callers to free the data itself. */
1993     FREE (cur->interface_data);
1994    
1995     FREE (cur->info.filename);
1996     FREE (cur->info.name);
1997     FREE (cur);
1998    
1999     goto done;
2000     }
2001    
2002     if (LT_DLIS_RESIDENT (handle))
2003     {
2004     LT__SETERROR (CLOSE_RESIDENT_MODULE);
2005     ++errors;
2006     }
2007    
2008     done:
2009     return errors;
2010     }
2011    
2012     void *
2013     lt_dlsym (lt_dlhandle place, const char *symbol)
2014     {
2015     size_t lensym;
2016     char lsym[LT_SYMBOL_LENGTH];
2017     char *sym;
2018     void *address;
2019     lt_user_data data;
2020     lt_dlhandle handle;
2021    
2022     if (!place)
2023     {
2024     LT__SETERROR (INVALID_HANDLE);
2025     return 0;
2026     }
2027    
2028     handle = place;
2029    
2030     if (!symbol)
2031     {
2032     LT__SETERROR (SYMBOL_NOT_FOUND);
2033     return 0;
2034     }
2035    
2036     lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
2037     + LT_STRLEN (handle->info.name);
2038    
2039     if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2040     {
2041     sym = lsym;
2042     }
2043     else
2044     {
2045     sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2046     if (!sym)
2047     {
2048     LT__SETERROR (BUFFER_OVERFLOW);
2049     return 0;
2050     }
2051     }
2052    
2053     data = handle->vtable->dlloader_data;
2054     if (handle->info.name)
2055     {
2056     const char *saved_error;
2057    
2058     LT__GETERROR (saved_error);
2059    
2060     /* this is a libtool module */
2061     if (handle->vtable->sym_prefix)
2062     {
2063     strcpy(sym, handle->vtable->sym_prefix);
2064     strcat(sym, handle->info.name);
2065     }
2066     else
2067     {
2068     strcpy(sym, handle->info.name);
2069     }
2070    
2071     strcat(sym, "_LTX_");
2072     strcat(sym, symbol);
2073    
2074     /* try "modulename_LTX_symbol" */
2075     address = handle->vtable->find_sym (data, handle->module, sym);
2076     if (address)
2077     {
2078     if (sym != lsym)
2079     {
2080     FREE (sym);
2081     }
2082     return address;
2083     }
2084     LT__SETERRORSTR (saved_error);
2085     }
2086    
2087     /* otherwise try "symbol" */
2088     if (handle->vtable->sym_prefix)
2089     {
2090     strcpy(sym, handle->vtable->sym_prefix);
2091     strcat(sym, symbol);
2092     }
2093     else
2094     {
2095     strcpy(sym, symbol);
2096     }
2097    
2098     address = handle->vtable->find_sym (data, handle->module, sym);
2099     if (sym != lsym)
2100     {
2101     FREE (sym);
2102     }
2103    
2104     return address;
2105     }
2106    
2107     const char *
2108     lt_dlerror (void)
2109     {
2110     const char *error;
2111    
2112     LT__GETERROR (error);
2113     LT__SETERRORSTR (0);
2114    
2115 michael 1094 return error;
2116 michael 945 }
2117    
2118     static int
2119     lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2120     {
2121     int errors = 0;
2122     char *canonical = 0;
2123     char *argz = 0;
2124     size_t argz_len = 0;
2125    
2126     assert (ppath);
2127     assert (dir && *dir);
2128    
2129     if (canonicalize_path (dir, &canonical) != 0)
2130     {
2131     ++errors;
2132     goto cleanup;
2133     }
2134    
2135     assert (canonical && *canonical);
2136    
2137     /* If *PPATH is empty, set it to DIR. */
2138     if (*ppath == 0)
2139     {
2140     assert (!before); /* BEFORE cannot be set without PPATH. */
2141     assert (dir); /* Without DIR, don't call this function! */
2142    
2143     *ppath = lt__strdup (dir);
2144     if (*ppath == 0)
2145     ++errors;
2146    
2147     goto cleanup;
2148     }
2149    
2150     assert (ppath && *ppath);
2151    
2152     if (argzize_path (*ppath, &argz, &argz_len) != 0)
2153     {
2154     ++errors;
2155     goto cleanup;
2156     }
2157    
2158     /* Convert BEFORE into an equivalent offset into ARGZ. This only works
2159     if *PPATH is already canonicalized, and hence does not change length
2160     with respect to ARGZ. We canonicalize each entry as it is added to
2161     the search path, and don't call this function with (uncanonicalized)
2162     user paths, so this is a fair assumption. */
2163     if (before)
2164     {
2165     assert (*ppath <= before);
2166     assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2167    
2168     before = before - *ppath + argz;
2169     }
2170    
2171     if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2172     {
2173     ++errors;
2174     goto cleanup;
2175     }
2176    
2177     argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2178     MEMREASSIGN(*ppath, argz);
2179    
2180     cleanup:
2181     FREE (argz);
2182     FREE (canonical);
2183    
2184     return errors;
2185     }
2186    
2187     int
2188     lt_dladdsearchdir (const char *search_dir)
2189     {
2190     int errors = 0;
2191    
2192     if (search_dir && *search_dir)
2193     {
2194     if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2195     ++errors;
2196     }
2197    
2198     return errors;
2199     }
2200    
2201     int
2202     lt_dlinsertsearchdir (const char *before, const char *search_dir)
2203     {
2204     int errors = 0;
2205    
2206     if (before)
2207     {
2208     if ((before < user_search_path)
2209     || (before >= user_search_path + LT_STRLEN (user_search_path)))
2210     {
2211     LT__SETERROR (INVALID_POSITION);
2212     return 1;
2213     }
2214     }
2215    
2216     if (search_dir && *search_dir)
2217     {
2218     if (lt_dlpath_insertdir (&user_search_path,
2219     (char *) before, search_dir) != 0)
2220     {
2221     ++errors;
2222     }
2223     }
2224    
2225     return errors;
2226     }
2227    
2228     int
2229     lt_dlsetsearchpath (const char *search_path)
2230     {
2231     int errors = 0;
2232    
2233     FREE (user_search_path);
2234    
2235     if (!search_path || !LT_STRLEN (search_path))
2236     {
2237     return errors;
2238     }
2239    
2240     if (canonicalize_path (search_path, &user_search_path) != 0)
2241     ++errors;
2242    
2243     return errors;
2244     }
2245    
2246     const char *
2247     lt_dlgetsearchpath (void)
2248     {
2249     const char *saved_path;
2250    
2251     saved_path = user_search_path;
2252    
2253     return saved_path;
2254     }
2255    
2256     int
2257     lt_dlmakeresident (lt_dlhandle handle)
2258     {
2259     int errors = 0;
2260    
2261     if (!handle)
2262     {
2263     LT__SETERROR (INVALID_HANDLE);
2264     ++errors;
2265     }
2266     else
2267     {
2268     handle->info.is_resident = 1;
2269     }
2270    
2271     return errors;
2272     }
2273    
2274     int
2275     lt_dlisresident (lt_dlhandle handle)
2276     {
2277     if (!handle)
2278     {
2279     LT__SETERROR (INVALID_HANDLE);
2280     return -1;
2281     }
2282    
2283     return LT_DLIS_RESIDENT (handle);
2284     }
2285    
2286    
2287    
2288     /* --- MODULE INFORMATION --- */
2289    
2290     typedef struct {
2291 michael 4901 char *id_string;
2292 michael 945 lt_dlhandle_interface *iface;
2293     } lt__interface_id;
2294    
2295     lt_dlinterface_id
2296     lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2297     {
2298     lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2299    
2300     /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
2301     can then be detected with lt_dlerror() if we return 0. */
2302     if (interface_id)
2303     {
2304     interface_id->id_string = lt__strdup (id_string);
2305     if (!interface_id->id_string)
2306     FREE (interface_id);
2307     else
2308     interface_id->iface = iface;
2309     }
2310    
2311     return (lt_dlinterface_id) interface_id;
2312     }
2313    
2314     void lt_dlinterface_free (lt_dlinterface_id key)
2315     {
2316     lt__interface_id *interface_id = (lt__interface_id *)key;
2317     FREE (interface_id->id_string);
2318     FREE (interface_id);
2319     }
2320    
2321     void *
2322     lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2323     {
2324     int n_elements = 0;
2325     void *stale = (void *) 0;
2326     lt_dlhandle cur = handle;
2327     int i;
2328    
2329     if (cur->interface_data)
2330     while (cur->interface_data[n_elements].key)
2331     ++n_elements;
2332    
2333     for (i = 0; i < n_elements; ++i)
2334     {
2335     if (cur->interface_data[i].key == key)
2336     {
2337     stale = cur->interface_data[i].data;
2338     break;
2339     }
2340     }
2341    
2342     /* Ensure that there is enough room in this handle's interface_data
2343     array to accept a new element (and an empty end marker). */
2344     if (i == n_elements)
2345     {
2346     lt_interface_data *temp
2347     = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2348    
2349     if (!temp)
2350     {
2351     stale = 0;
2352     goto done;
2353     }
2354    
2355     cur->interface_data = temp;
2356    
2357     /* We only need this if we needed to allocate a new interface_data. */
2358     cur->interface_data[i].key = key;
2359     cur->interface_data[1+ i].key = 0;
2360     }
2361    
2362     cur->interface_data[i].data = data;
2363    
2364     done:
2365     return stale;
2366     }
2367    
2368     void *
2369     lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2370     {
2371     void *result = (void *) 0;
2372     lt_dlhandle cur = handle;
2373    
2374     /* Locate the index of the element with a matching KEY. */
2375     if (cur->interface_data)
2376     {
2377     int i;
2378     for (i = 0; cur->interface_data[i].key; ++i)
2379     {
2380     if (cur->interface_data[i].key == key)
2381     {
2382     result = cur->interface_data[i].data;
2383     break;
2384     }
2385     }
2386     }
2387    
2388     return result;
2389     }
2390    
2391     const lt_dlinfo *
2392     lt_dlgetinfo (lt_dlhandle handle)
2393     {
2394     if (!handle)
2395     {
2396     LT__SETERROR (INVALID_HANDLE);
2397     return 0;
2398     }
2399    
2400     return &(handle->info);
2401     }
2402    
2403    
2404     lt_dlhandle
2405     lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2406     {
2407     lt_dlhandle handle = place;
2408     lt__interface_id *iterator = (lt__interface_id *) iface;
2409    
2410     assert (iface); /* iface is a required argument */
2411    
2412     if (!handle)
2413     handle = handles;
2414     else
2415     handle = handle->next;
2416    
2417     /* advance while the interface check fails */
2418     while (handle && iterator->iface
2419     && ((*iterator->iface) (handle, iterator->id_string) != 0))
2420     {
2421     handle = handle->next;
2422     }
2423    
2424     return handle;
2425     }
2426    
2427    
2428     lt_dlhandle
2429     lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2430     {
2431     lt_dlhandle handle = 0;
2432    
2433     assert (iface); /* iface is a required argument */
2434    
2435     while ((handle = lt_dlhandle_iterate (iface, handle)))
2436     {
2437     lt_dlhandle cur = handle;
2438 michael 4901 if (cur && cur->info.name && STREQ (cur->info.name, module_name))
2439 michael 945 break;
2440     }
2441    
2442     return handle;
2443     }
2444    
2445    
2446     int
2447     lt_dlhandle_map (lt_dlinterface_id iface,
2448     int (*func) (lt_dlhandle handle, void *data), void *data)
2449     {
2450     lt__interface_id *iterator = (lt__interface_id *) iface;
2451     lt_dlhandle cur = handles;
2452    
2453     assert (iface); /* iface is a required argument */
2454    
2455     while (cur)
2456     {
2457     int errorcode = 0;
2458    
2459     /* advance while the interface check fails */
2460     while (cur && iterator->iface
2461     && ((*iterator->iface) (cur, iterator->id_string) != 0))
2462     {
2463     cur = cur->next;
2464     }
2465    
2466     if ((errorcode = (*func) (cur, data)) != 0)
2467     return errorcode;
2468     }
2469    
2470     return 0;
2471     }

Properties

Name Value
svn:eol-style native