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