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