root/ImageMagick/trunk/ltdl/ltdl.c

Revision 617, 52.8 KB (checked in by cristy, 40 hours ago)
Line 
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
10GNU Libltdl is free software; you can redistribute it and/or
11modify it under the terms of the GNU Lesser General Public
12License as published by the Free Software Foundation; either
13version 2 of the License, or (at your option) any later version.
14
15As a special exception to the GNU Lesser General Public License,
16if you distribute this file as part of a program or library that
17is built using GNU Libtool, you may include this file under the
18same distribution terms that you use for the rest of that program.
19
20GNU Libltdl is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23GNU Lesser General Public License for more details.
24
25You should have received a copy of the GNU Lesser General Public
26License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
27copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
28or obtained by writing to the Free Software Foundation, Inc.,
2951 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)
50define LT_FILENAME_MAX       1024
51#endif
52
53#if !defined(LT_LIBEXT)
54define 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
72static  const char      objdir[]                = LT_OBJDIR;
73static  const char      archive_ext[]           = LT_ARCHIVE_EXT;
74static  const char      libext[]                = LT_LIBEXT;
75#if defined(LT_MODULE_EXT)
76static  const char      shlib_ext[]             = LT_MODULE_EXT;
77#endif
78#if defined(LT_DLSEARCH_PATH)
79static  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().  */
89typedef int     foreach_callback_func (char *filename, void *data1,
90                                       void *data2);
91/* foreachfile_callback itself calls a function of this type: */
92typedef int     file_worker_func      (const char *filename, void *data);
93
94
95static  int     foreach_dirinpath     (const char *search_path,
96                                       const char *base_name,
97                                       foreach_callback_func *func,
98                                       void *data1, void *data2);
99static  int     find_file_callback    (char *filename, void *data1,
100                                       void *data2);
101static  int     find_handle_callback  (char *filename, void *data,
102                                       void *ignored);
103static  int     foreachfile_callback  (char *filename, void *data1,
104                                       void *data2);
105
106
107static  int     canonicalize_path     (const char *path, char **pcanonical);
108static  int     argzize_path          (const char *path,
109                                       char **pargz, size_t *pargz_len);
110static  FILE   *find_file             (const char *search_path,
111                                       const char *base_name, char **pdir);
112static  lt_dlhandle *find_handle      (const char *search_path,
113                                       const char *base_name,
114                                       lt_dlhandle *handle,
115                                       lt_dladvise advise);
116static  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);
120static  int     has_library_ext       (const char *filename);
121static  int     load_deplibs          (lt_dlhandle handle,  char *deplibs);
122static  int     trim                  (char **dest, const char *str);
123static  int     try_dlopen            (lt_dlhandle *handle,
124                                       const char *filename, const char *ext,
125                                       lt_dladvise advise);
126static  int     tryall_dlopen         (lt_dlhandle *handle,
127                                       const char *filename,
128                                       lt_dladvise padvise,
129                                       const lt_dlvtable *vtable);
130static  int     unload_deplibs        (lt_dlhandle handle);
131static  int     lt_argz_insert        (char **pargz, size_t *pargz_len,
132                                       char *before, const char *entry);
133static  int     lt_argz_insertinorder (char **pargz, size_t *pargz_len,
134                                       const char *entry);
135static  int     lt_argz_insertdir     (char **pargz, size_t *pargz_len,
136                                       const char *dirnam, struct dirent *dp);
137static  int     lt_dlpath_insertdir   (char **ppath, char *before,
138                                       const char *dir);
139static  int     list_files_by_dir     (const char *dirnam,
140                                       char **pargz, size_t *pargz_len);
141static  int     file_not_found        (void);
142
143#ifdef HAVE_LIBDLLOADER
144static  int     loader_init_callback  (lt_dlhandle handle);
145#endif /* HAVE_LIBDLLOADER */
146
147static  int     loader_init           (lt_get_vtable *vtable_func,
148                                       lt_user_data data);
149
150static  char           *user_search_path= 0;
151static  lt_dlhandle     handles = 0;
152static  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!!).  */
157void
158lt__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.  */
167static int
168loader_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
175static int
176loader_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
207LT_BEGIN_C_DECLS
208LT_SCOPE const lt_dlvtable *    get_vtable (lt_user_data data);
209LT_END_C_DECLS
210#ifdef HAVE_LIBDLLOADER
211extern lt_dlsymlist             preloaded_symbols;
212#endif
213
214/* Initialize libltdl. */
215int
216lt_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
254int
255lt_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.  */
357static int
358tryall_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
475static int
476tryall_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
524static int
525find_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
569static int
570canonicalize_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
630static int
631argzize_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.  */
661static int
662foreach_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.  */
728static int
729find_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
754static FILE *
755find_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
764static int
765find_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.  */
785static lt_dlhandle *
786find_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)
800static int
801load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
802{
803  handle->depcount = 0;
804  return 0;
805}
806
807#else /* defined(LTDL_DLOPEN_DEPLIBS) */
808static int
809load_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
964static int
965unload_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
986static int
987trim (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. */
1019static int
1020parse_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    }
1126cleanup:
1127  FREE (line);
1128  return errors;
1129}
1130
1131
1132/* Try to open FILENAME as a module. */
1133static int
1134try_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) + 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.  */
1492static int
1493file_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.  */
1507static int
1508has_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
1531int
1532lt_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
1539int
1540lt_dladvise_destroy (lt_dladvise *padvise)
1541{
1542  if (padvise)
1543    FREE(*padvise);
1544  return 0;
1545}
1546
1547int
1548lt_dladvise_ext (lt_dladvise *padvise)
1549{
1550  assert (padvise && *padvise);
1551  (*padvise)->try_ext = 1;
1552  return 0;
1553}
1554
1555int
1556lt_dladvise_resident (lt_dladvise *padvise)
1557{
1558  assert (padvise && *padvise);
1559  (*padvise)->is_resident = 1;
1560  return 0;
1561}
1562
1563int
1564lt_dladvise_local (lt_dladvise *padvise)
1565{
1566  assert (padvise && *padvise);
1567  (*padvise)->is_symlocal = 1;
1568  return 0;
1569}
1570
1571int
1572lt_dladvise_global (lt_dladvise *padvise)
1573{
1574  assert (padvise && *padvise);
1575  (*padvise)->is_symglobal = 1;
1576  return 0;
1577}
1578
1579int
1580lt_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.  */
1588lt_dlhandle
1589lt_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.  */
1599lt_dlhandle
1600lt_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
1613lt_dlhandle
1614lt_dlopenadvise (const char *filename, lt_dladvise advise)
1615{
1616  lt_dlhandle   handle  = 0;
1617  int           errors  = 0;
1618  const char *  saved_error     = 0;
1619
1620  LT__GETERROR (saved_error);
1621
1622  /* Can't have symbols hidden and visible at the same time!  */
1623  if (advise && advise->is_symlocal && advise->is_symglobal)
1624    {
1625      LT__SETERROR (CONFLICTING_FLAGS);
1626      return 0;
1627    }
1628
1629  if (!filename
1630      || !advise
1631      || !advise->try_ext
1632      || has_library_ext (filename))
1633    {
1634      /* Just incase we missed a code path in try_dlopen() that reports
1635         an error, but forgot to reset handle... */
1636      if (try_dlopen (&handle, filename, NULL, advise) != 0)
1637        return 0;
1638
1639      return handle;
1640    }
1641  else if (filename && *filename)
1642    {
1643
1644      /* First try appending ARCHIVE_EXT.  */
1645      errors += try_dlopen (&handle, filename, archive_ext, advise);
1646
1647      /* If we found FILENAME, stop searching -- whether we were able to
1648         load the file as a module or not.  If the file exists but loading
1649         failed, it is better to return an error message here than to
1650         report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
1651         in the module search path.  */
1652      if (handle || ((errors > 0) && !file_not_found ()))
1653        return handle;
1654
1655#if defined(LT_MODULE_EXT)
1656      /* Try appending SHLIB_EXT.   */
1657      LT__SETERRORSTR (saved_error);
1658      errors = try_dlopen (&handle, filename, shlib_ext, advise);
1659
1660      /* As before, if the file was found but loading failed, return now
1661         with the current error message.  */
1662      if (handle || ((errors > 0) && !file_not_found ()))
1663        return handle;
1664#endif
1665    }
1666
1667  /* Still here?  Then we really did fail to locate any of the file
1668     names we tried.  */
1669  LT__SETERROR (FILE_NOT_FOUND);
1670  return 0;
1671}
1672
1673
1674static int
1675lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1676                const char *entry)
1677{
1678  error_t error;
1679
1680  /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1681     pargz_len, NULL, entry) failed with EINVAL.  */
1682  if (before)
1683    error = argz_insert (pargz, pargz_len, before, entry);
1684  else
1685    error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1686
1687  if (error)
1688    {
1689      switch (error)
1690        {
1691        case ENOMEM:
1692          LT__SETERROR (NO_MEMORY);
1693          break;
1694        default:
1695          LT__SETERROR (UNKNOWN);
1696          break;
1697        }
1698      return 1;
1699    }
1700
1701  return 0;
1702}
1703
1704static int
1705lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1706{
1707  char *before = 0;
1708
1709  assert (pargz);
1710  assert (pargz_len);
1711  assert (entry && *entry);
1712
1713  if (*pargz)
1714    while ((before = argz_next (*pargz, *pargz_len, before)))
1715      {
1716        int cmp = strcmp (entry, before);
1717
1718        if (cmp < 0)  break;
1719        if (cmp == 0) return 0; /* No duplicates! */
1720      }
1721
1722  return lt_argz_insert (pargz, pargz_len, before, entry);
1723}
1724
1725static int
1726lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1727                   struct dirent *dp)
1728{
1729  char   *buf       = 0;
1730  size_t buf_len    = 0;
1731  char   *end       = 0;
1732  size_t end_offset = 0;
1733  size_t dir_len    = 0;
1734  int    errors     = 0;
1735
1736  assert (pargz);
1737  assert (pargz_len);
1738  assert (dp);
1739
1740  dir_len = LT_STRLEN (dirnam);
1741  end     = dp->d_name + D_NAMLEN(dp);
1742
1743  /* Ignore version numbers.  */
1744  {
1745    char *p;
1746    for (p = end; p -1 > dp->d_name; --p)
1747      if (strchr (".0123456789", p[-1]) == 0)
1748        break;
1749
1750    if (*p == '.')
1751      end = p;
1752  }
1753
1754  /* Ignore filename extension.  */
1755  {
1756    char *p;
1757    for (p = end -1; p > dp->d_name; --p)
1758      if (*p == '.')
1759        {
1760          end = p;
1761          break;
1762        }
1763  }
1764
1765  /* Prepend the directory name.  */
1766  end_offset    = end - dp->d_name;
1767  buf_len       = dir_len + 1+ end_offset;
1768  buf           = MALLOC (char, 1+ buf_len);
1769  if (!buf)
1770    return ++errors;
1771
1772  assert (buf);
1773
1774  strcpy  (buf, dirnam);
1775  strcat  (buf, "/");
1776  strncat (buf, dp->d_name, end_offset);
1777  buf[buf_len] = LT_EOS_CHAR;
1778
1779  /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
1780  if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1781    ++errors;
1782
1783  FREE (buf);
1784
1785  return errors;
1786}
1787
1788static int
1789list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1790{
1791  DIR   *dirp     = 0;
1792  int    errors   = 0;
1793
1794  assert (dirnam && *dirnam);
1795  assert (pargz);
1796  assert (pargz_len);
1797  assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1798
1799  dirp = opendir (dirnam);
1800  if (dirp)
1801    {
1802      struct dirent *dp = 0;
1803
1804      while ((dp = readdir (dirp)))
1805        if (dp->d_name[0] != '.')
1806          if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1807            {
1808              ++errors;
1809              break;
1810            }
1811
1812      closedir (dirp);
1813    }
1814  else
1815    ++errors;
1816
1817  return errors;
1818}
1819
1820
1821/* If there are any files in DIRNAME, call the function passed in
1822   DATA1 (with the name of each file and DATA2 as arguments).  */
1823static int
1824foreachfile_callback (char *dirname, void *data1, void *data2)
1825{
1826  file_worker_func *func = *(file_worker_func **) data1;
1827
1828  int     is_done  = 0;
1829  char   *argz     = 0;
1830  size_t  argz_len = 0;
1831
1832  if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1833    goto cleanup;
1834  if (!argz)
1835    goto cleanup;
1836
1837  {
1838    char *filename = 0;
1839    while ((filename = argz_next (argz, argz_len, filename)))
1840      if ((is_done = (*func) (filename, data2)))
1841        break;
1842  }
1843
1844 cleanup:
1845  FREE (argz);
1846
1847  return is_done;
1848}
1849
1850
1851/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
1852   with DATA.  The filenames passed to FUNC would be suitable for
1853   passing to lt_dlopenext.  The extensions are stripped so that
1854   individual modules do not generate several entries (e.g. libfoo.la,
1855   libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
1856   then the same directories that lt_dlopen would search are examined.  */
1857int
1858lt_dlforeachfile (const char *search_path,
1859                  int (*func) (const char *filename, void *data),
1860                  void *data)
1861{
1862  int is_done = 0;
1863  file_worker_func **fpptr = &func;
1864
1865  if (search_path)
1866    {
1867      /* If a specific path was passed, search only the directories
1868         listed in it.  */
1869      is_done = foreach_dirinpath (search_path, 0,
1870                                   foreachfile_callback, fpptr, data);
1871    }
1872  else
1873    {
1874      /* Otherwise search the default paths.  */
1875      is_done = foreach_dirinpath (user_search_path, 0,
1876                                   foreachfile_callback, fpptr, data);
1877      if (!is_done)
1878        {
1879          is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1880                                       foreachfile_callback, fpptr, data);
1881        }
1882
1883#if defined(LT_MODULE_PATH_VAR)
1884      if (!is_done)
1885        {
1886          is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1887                                       foreachfile_callback, fpptr, data);
1888        }
1889#endif
1890#if defined(LT_DLSEARCH_PATH)
1891      if (!is_done && *sys_dlsearch_path)
1892        {
1893          is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1894                                       foreachfile_callback, fpptr, data);
1895        }
1896#endif
1897    }
1898
1899  return is_done;
1900}
1901
1902int
1903lt_dlclose (lt_dlhandle handle)
1904{
1905  lt_dlhandle cur, last;
1906  int errors = 0;
1907
1908  /* check whether the handle is valid */
1909  last = cur = handles;
1910  while (cur && handle != cur)
1911    {
1912      last = cur;
1913      cur = cur->next;
1914    }
1915
1916  if (!cur)
1917    {
1918      LT__SETERROR (INVALID_HANDLE);
1919      ++errors;
1920      goto done;
1921    }
1922
1923  cur = handle;
1924  cur->info.ref_count--;
1925
1926  /* Note that even with resident modules, we must track the ref_count
1927     correctly incase the user decides to reset the residency flag
1928     later (even though the API makes no provision for that at the
1929     moment).  */
1930  if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1931    {
1932      lt_user_data data = cur->vtable->dlloader_data;
1933
1934      if (cur != handles)
1935        {
1936          last->next = cur->next;
1937        }
1938      else
1939        {
1940          handles = cur->next;
1941        }
1942
1943      errors += cur->vtable->module_close (data, cur->module);
1944      errors += unload_deplibs (handle);
1945
1946      /* It is up to the callers to free the data itself.  */
1947      FREE (cur->interface_data);
1948
1949      FREE (cur->info.filename);
1950      FREE (cur->info.name);
1951      FREE (cur);
1952
1953      goto done;
1954    }
1955
1956  if (LT_DLIS_RESIDENT (handle))
1957    {
1958      LT__SETERROR (CLOSE_RESIDENT_MODULE);
1959      ++errors;
1960    }
1961
1962 done:
1963  return errors;
1964}
1965
1966void *
1967lt_dlsym (lt_dlhandle place, const char *symbol)
1968{
1969  size_t lensym;
1970  char  lsym[LT_SYMBOL_LENGTH];
1971  char  *sym;
1972  void *address;
1973  lt_user_data data;
1974  lt_dlhandle handle;
1975
1976  if (!place)
1977    {
1978      LT__SETERROR (INVALID_HANDLE);
1979      return 0;
1980    }
1981
1982  handle = place;
1983
1984  if (!symbol)
1985    {
1986      LT__SETERROR (SYMBOL_NOT_FOUND);
1987      return 0;
1988    }
1989
1990  lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
1991                                        + LT_STRLEN (handle->info.name);
1992
1993  if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
1994    {
1995      sym = lsym;
1996    }
1997  else
1998    {
1999      sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2000      if (!sym)
2001        {
2002          LT__SETERROR (BUFFER_OVERFLOW);
2003          return 0;
2004        }
2005    }
2006
2007  data = handle->vtable->dlloader_data;
2008  if (handle->info.name)
2009    {
2010      const char *saved_error;
2011
2012      LT__GETERROR (saved_error);
2013
2014      /* this is a libtool module */
2015      if (handle->vtable->sym_prefix)
2016        {
2017          strcpy(sym, handle->vtable->sym_prefix);
2018          strcat(sym, handle->info.name);
2019        }
2020      else
2021        {
2022          strcpy(sym, handle->info.name);
2023        }
2024
2025      strcat(sym, "_LTX_");
2026      strcat(sym, symbol);
2027
2028      /* try "modulename_LTX_symbol" */
2029      address = handle->vtable->find_sym (data, handle->module, sym);
2030      if (address)
2031        {
2032          if (sym != lsym)
2033            {
2034              FREE (sym);
2035            }
2036          return address;
2037        }
2038      LT__SETERRORSTR (saved_error);
2039    }
2040
2041  /* otherwise try "symbol" */
2042  if (handle->vtable->sym_prefix)
2043    {
2044      strcpy(sym, handle->vtable->sym_prefix);
2045      strcat(sym, symbol);
2046    }
2047  else
2048    {
2049      strcpy(sym, symbol);
2050    }
2051
2052  address = handle->vtable->find_sym (data, handle->module, sym);
2053  if (sym != lsym)
2054    {
2055      FREE (sym);
2056    }
2057
2058  return address;
2059}
2060
2061const char *
2062lt_dlerror (void)
2063{
2064  const char *error;
2065
2066  LT__GETERROR (error);
2067  LT__SETERRORSTR (0);
2068
2069  return error ? error : NULL;
2070}
2071
2072static int
2073lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2074{
2075  int    errors         = 0;
2076  char  *canonical      = 0;
2077  char  *argz           = 0;
2078  size_t argz_len       = 0;
2079
2080  assert (ppath);
2081  assert (dir && *dir);
2082
2083  if (canonicalize_path (dir, &canonical) != 0)
2084    {
2085      ++errors;
2086      goto cleanup;
2087    }
2088
2089  assert (canonical && *canonical);
2090
2091  /* If *PPATH is empty, set it to DIR.  */
2092  if (*ppath == 0)
2093    {
2094      assert (!before);         /* BEFORE cannot be set without PPATH.  */
2095      assert (dir);             /* Without DIR, don't call this function!  */
2096
2097      *ppath = lt__strdup (dir);
2098      if (*ppath == 0)
2099        ++errors;
2100
2101      goto cleanup;
2102    }
2103
2104  assert (ppath && *ppath);
2105
2106  if (argzize_path (*ppath, &argz, &argz_len) != 0)
2107    {
2108      ++errors;
2109      goto cleanup;
2110    }
2111
2112  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
2113     if *PPATH is already canonicalized, and hence does not change length
2114     with respect to ARGZ.  We canonicalize each entry as it is added to
2115     the search path, and don't call this function with (uncanonicalized)
2116     user paths, so this is a fair assumption.  */
2117  if (before)
2118    {
2119      assert (*ppath <= before);
2120      assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2121
2122      before = before - *ppath + argz;
2123    }
2124
2125  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2126    {
2127      ++errors;
2128      goto cleanup;
2129    }
2130
2131  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2132  MEMREASSIGN(*ppath, argz);
2133
2134 cleanup:
2135  FREE (argz);
2136  FREE (canonical);
2137
2138  return errors;
2139}
2140
2141int
2142lt_dladdsearchdir (const char *search_dir)
2143{
2144  int errors = 0;
2145
2146  if (search_dir && *search_dir)
2147    {
2148      if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2149        ++errors;
2150    }
2151
2152  return errors;
2153}
2154
2155int
2156lt_dlinsertsearchdir (const char *before, const char *search_dir)
2157{
2158  int errors = 0;
2159
2160  if (before)
2161    {
2162      if ((before < user_search_path)
2163          || (before >= user_search_path + LT_STRLEN (user_search_path)))
2164        {
2165          LT__SETERROR (INVALID_POSITION);
2166          return 1;
2167        }
2168    }
2169
2170  if (search_dir && *search_dir)
2171    {
2172      if (lt_dlpath_insertdir (&user_search_path,
2173                               (char *) before, search_dir) != 0)
2174        {
2175          ++errors;
2176        }
2177    }
2178
2179  return errors;
2180}
2181
2182int
2183lt_dlsetsearchpath (const char *search_path)
2184{
2185  int   errors      = 0;
2186
2187  FREE (user_search_path);
2188
2189  if (!search_path || !LT_STRLEN (search_path))
2190    {
2191      return errors;
2192    }
2193
2194  if (canonicalize_path (search_path, &user_search_path) != 0)
2195    ++errors;
2196
2197  return errors;
2198}
2199
2200const char *
2201lt_dlgetsearchpath (void)
2202{
2203  const char *saved_path;
2204
2205  saved_path = user_search_path;
2206
2207  return saved_path;
2208}
2209
2210int
2211lt_dlmakeresident (lt_dlhandle handle)
2212{
2213  int errors = 0;
2214
2215  if (!handle)
2216    {
2217      LT__SETERROR (INVALID_HANDLE);
2218      ++errors;
2219    }
2220  else
2221    {
2222      handle->info.is_resident = 1;
2223    }
2224
2225  return errors;
2226}
2227
2228int
2229lt_dlisresident (lt_dlhandle handle)
2230{
2231  if (!handle)
2232    {
2233      LT__SETERROR (INVALID_HANDLE);
2234      return -1;
2235    }
2236
2237  return LT_DLIS_RESIDENT (handle);
2238}
2239
2240
2241
2242/* --- MODULE INFORMATION --- */
2243
2244typedef struct {
2245  const char *id_string;
2246  lt_dlhandle_interface *iface;
2247} lt__interface_id;
2248
2249lt_dlinterface_id
2250lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2251{
2252  lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2253
2254  /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
2255     can then be detected with lt_dlerror() if we return 0.  */
2256  if (interface_id)
2257    {
2258      interface_id->id_string = lt__strdup (id_string);
2259      if (!interface_id->id_string)
2260        FREE (interface_id);
2261      else
2262        interface_id->iface = iface;
2263    }
2264
2265  return (lt_dlinterface_id) interface_id;
2266}
2267
2268void lt_dlinterface_free (lt_dlinterface_id key)
2269{
2270  lt__interface_id *interface_id = (lt__interface_id *)key;
2271  FREE (interface_id->id_string);
2272  FREE (interface_id);
2273}
2274
2275void *
2276lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2277{
2278  int n_elements = 0;
2279  void *stale = (void *) 0;
2280  lt_dlhandle cur = handle;
2281  int i;
2282
2283  if (cur->interface_data)
2284    while (cur->interface_data[n_elements].key)
2285      ++n_elements;
2286
2287  for (i = 0; i < n_elements; ++i)
2288    {
2289      if (cur->interface_data[i].key == key)
2290        {
2291          stale = cur->interface_data[i].data;
2292          break;
2293        }
2294    }
2295
2296  /* Ensure that there is enough room in this handle's interface_data
2297     array to accept a new element (and an empty end marker).  */
2298  if (i == n_elements)
2299    {
2300      lt_interface_data *temp
2301        = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2302
2303      if (!temp)
2304        {
2305          stale = 0;
2306          goto done;
2307        }
2308
2309      cur->interface_data = temp;
2310
2311      /* We only need this if we needed to allocate a new interface_data.  */
2312      cur->interface_data[i].key        = key;
2313      cur->interface_data[1+ i].key     = 0;
2314    }
2315
2316  cur->interface_data[i].data = data;
2317
2318 done:
2319  return stale;
2320}
2321
2322void *
2323lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2324{
2325  void *result = (void *) 0;
2326  lt_dlhandle cur = handle;
2327
2328  /* Locate the index of the element with a matching KEY.  */
2329  if (cur->interface_data)
2330    {
2331      int i;
2332      for (i = 0; cur->interface_data[i].key; ++i)
2333        {
2334          if (cur->interface_data[i].key == key)
2335            {
2336              result = cur->interface_data[i].data;
2337              break;
2338            }
2339        }
2340    }
2341
2342  return result;
2343}
2344
2345const lt_dlinfo *
2346lt_dlgetinfo (lt_dlhandle handle)
2347{
2348  if (!handle)
2349    {
2350      LT__SETERROR (INVALID_HANDLE);
2351      return 0;
2352    }
2353
2354  return &(handle->info);
2355}
2356
2357
2358lt_dlhandle
2359lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2360{
2361  lt_dlhandle handle = place;
2362  lt__interface_id *iterator = (lt__interface_id *) iface;
2363
2364  assert (iface); /* iface is a required argument */
2365
2366  if (!handle)
2367    handle = handles;
2368  else
2369    handle = handle->next;
2370
2371  /* advance while the interface check fails */
2372  while (handle && iterator->iface
2373         && ((*iterator->iface) (handle, iterator->id_string) != 0))
2374    {
2375      handle = handle->next;
2376    }
2377
2378  return handle;
2379}
2380
2381
2382lt_dlhandle
2383lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2384{
2385  lt_dlhandle handle = 0;
2386
2387  assert (iface); /* iface is a required argument */
2388
2389  while ((handle = lt_dlhandle_iterate (iface, handle)))
2390    {
2391      lt_dlhandle cur = handle;
2392      if (cur && cur->info.name && streq (cur->info.name, module_name))
2393        break;
2394    }
2395
2396  return handle;
2397}
2398
2399
2400int
2401lt_dlhandle_map (lt_dlinterface_id iface,
2402                 int (*func) (lt_dlhandle handle, void *data), void *data)
2403{
2404  lt__interface_id *iterator = (lt__interface_id *) iface;
2405  lt_dlhandle cur = handles;
2406
2407  assert (iface); /* iface is a required argument */
2408
2409  while (cur)
2410    {
2411      int errorcode = 0;
2412
2413      /* advance while the interface check fails */
2414      while (cur && iterator->iface
2415             && ((*iterator->iface) (cur, iterator->id_string) != 0))
2416        {
2417          cur = cur->next;
2418        }
2419
2420      if ((errorcode = (*func) (cur, data)) != 0)
2421        return errorcode;
2422    }
2423
2424  return 0;
2425}
Note: See TracBrowser for help on using the browser.