root/ImageMagick/trunk/ltdl/ltdl.c

Revision 650, 52.7 KB (checked in by cristy, 4 months 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) + 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.  */
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
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
1670static int
1671lt_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
1700static int
1701lt_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
1721static int
1722lt_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
1784static int
1785list_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).  */
1819static int
1820foreachfile_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.  */
1853int
1854lt_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
1898int
1899lt_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
1962void *
1963lt_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
2057const char *
2058lt_dlerror (void)
2059{
2060  const char *error;
2061
2062  LT__GETERROR (error);
2063  LT__SETERRORSTR (0);
2064
2065  return error ? error : NULL;
2066}
2067
2068static int
2069lt_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
2076  assert (ppath);
2077  assert (dir && *dir);
2078
2079  if (canonicalize_path (dir, &canonical) != 0)
2080    {
2081      ++errors;
2082      goto cleanup;
2083    }
2084
2085  assert (canonical && *canonical);
2086
2087  /* If *PPATH is empty, set it to DIR.  */
2088  if (*ppath == 0)
2089    {
2090      assert (!before);         /* BEFORE cannot be set without PPATH.  */
2091      assert (dir);             /* Without DIR, don't call this function!  */
2092
2093      *ppath = lt__strdup (dir);
2094      if (*ppath == 0)
2095        ++errors;
2096
2097      goto cleanup;
2098    }
2099
2100  assert (ppath && *ppath);
2101
2102  if (argzize_path (*ppath, &argz, &argz_len) != 0)
2103    {
2104      ++errors;
2105      goto cleanup;
2106    }
2107
2108  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
2109     if *PPATH is already canonicalized, and hence does not change length
2110     with respect to ARGZ.  We canonicalize each entry as it is added to
2111     the search path, and don't call this function with (uncanonicalized)
2112     user paths, so this is a fair assumption.  */
2113  if (before)
2114    {
2115      assert (*ppath <= before);
2116      assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2117
2118      before = before - *ppath + argz;
2119    }
2120
2121  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2122    {
2123      ++errors;
2124      goto cleanup;
2125    }
2126
2127  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2128  MEMREASSIGN(*ppath, argz);
2129
2130 cleanup:
2131  FREE (argz);
2132  FREE (canonical);
2133
2134  return errors;
2135}
2136
2137int
2138lt_dladdsearchdir (const char *search_dir)
2139{
2140  int errors = 0;
2141
2142  if (search_dir && *search_dir)
2143    {
2144      if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2145        ++errors;
2146    }
2147
2148  return errors;
2149}
2150
2151int
2152lt_dlinsertsearchdir (const char *before, const char *search_dir)
2153{
2154  int errors = 0;
2155
2156  if (before)
2157    {
2158      if ((before < user_search_path)
2159          || (before >= user_search_path + LT_STRLEN (user_search_path)))
2160        {
2161          LT__SETERROR (INVALID_POSITION);
2162          return 1;
2163        }
2164    }
2165
2166  if (search_dir && *search_dir)
2167    {
2168      if (lt_dlpath_insertdir (&user_search_path,
2169                               (char *) before, search_dir) != 0)
2170        {
2171          ++errors;
2172        }
2173    }
2174
2175  return errors;
2176}
2177
2178int
2179lt_dlsetsearchpath (const char *search_path)
2180{
2181  int   errors      = 0;
2182
2183  FREE (user_search_path);
2184
2185  if (!search_path || !LT_STRLEN (search_path))
2186    {
2187      return errors;
2188    }
2189
2190  if (canonicalize_path (search_path, &user_search_path) != 0)
2191    ++errors;
2192
2193  return errors;
2194}
2195
2196const char *
2197lt_dlgetsearchpath (void)
2198{
2199  const char *saved_path;
2200
2201  saved_path = user_search_path;
2202
2203  return saved_path;
2204}
2205
2206int
2207lt_dlmakeresident (lt_dlhandle handle)
2208{
2209  int errors = 0;
2210
2211  if (!handle)
2212    {
2213      LT__SETERROR (INVALID_HANDLE);
2214      ++errors;
2215    }
2216  else
2217    {
2218      handle->info.is_resident = 1;
2219    }
2220
2221  return errors;
2222}
2223
2224int
2225lt_dlisresident (lt_dlhandle handle)
2226{
2227  if (!handle)
2228    {
2229      LT__SETERROR (INVALID_HANDLE);
2230      return -1;
2231    }
2232
2233  return LT_DLIS_RESIDENT (handle);
2234}
2235
2236
2237
2238/* --- MODULE INFORMATION --- */
2239
2240typedef struct {
2241  const char *id_string;
2242  lt_dlhandle_interface *iface;
2243} lt__interface_id;
2244
2245lt_dlinterface_id
2246lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2247{
2248  lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2249
2250  /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
2251     can then be detected with lt_dlerror() if we return 0.  */
2252  if (interface_id)
2253    {
2254      interface_id->id_string = lt__strdup (id_string);
2255      if (!interface_id->id_string)
2256        FREE (interface_id);
2257      else
2258        interface_id->iface = iface;
2259    }
2260
2261  return (lt_dlinterface_id) interface_id;
2262}
2263
2264void lt_dlinterface_free (lt_dlinterface_id key)
2265{
2266  lt__interface_id *interface_id = (lt__interface_id *)key;
2267  FREE (interface_id->id_string);
2268  FREE (interface_id);
2269}
2270
2271void *
2272lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2273{
2274  int n_elements = 0;
2275  void *stale = (void *) 0;
2276  lt_dlhandle cur = handle;
2277  int i;
2278
2279  if (cur->interface_data)
2280    while (cur->interface_data[n_elements].key)
2281      ++n_elements;
2282
2283  for (i = 0; i < n_elements; ++i)
2284    {
2285      if (cur->interface_data[i].key == key)
2286        {
2287          stale = cur->interface_data[i].data;
2288          break;
2289        }
2290    }
2291
2292  /* Ensure that there is enough room in this handle's interface_data
2293     array to accept a new element (and an empty end marker).  */
2294  if (i == n_elements)
2295    {
2296      lt_interface_data *temp
2297        = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2298
2299      if (!temp)
2300        {
2301          stale = 0;
2302          goto done;
2303        }
2304
2305      cur->interface_data = temp;
2306
2307      /* We only need this if we needed to allocate a new interface_data.  */
2308      cur->interface_data[i].key        = key;
2309      cur->interface_data[1+ i].key     = 0;
2310    }
2311
2312  cur->interface_data[i].data = data;
2313
2314 done:
2315  return stale;
2316}
2317
2318void *
2319lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2320{
2321  void *result = (void *) 0;
2322  lt_dlhandle cur = handle;
2323
2324  /* Locate the index of the element with a matching KEY.  */
2325  if (cur->interface_data)
2326    {
2327      int i;
2328      for (i = 0; cur->interface_data[i].key; ++i)
2329        {
2330          if (cur->interface_data[i].key == key)
2331            {
2332              result = cur->interface_data[i].data;
2333              break;
2334            }
2335        }
2336    }
2337
2338  return result;
2339}
2340
2341const lt_dlinfo *
2342lt_dlgetinfo (lt_dlhandle handle)
2343{
2344  if (!handle)
2345    {
2346      LT__SETERROR (INVALID_HANDLE);
2347      return 0;
2348    }
2349
2350  return &(handle->info);
2351}
2352
2353
2354lt_dlhandle
2355lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2356{
2357  lt_dlhandle handle = place;
2358  lt__interface_id *iterator = (lt__interface_id *) iface;
2359
2360  assert (iface); /* iface is a required argument */
2361
2362  if (!handle)
2363    handle = handles;
2364  else
2365    handle = handle->next;
2366
2367  /* advance while the interface check fails */
2368  while (handle && iterator->iface
2369         && ((*iterator->iface) (handle, iterator->id_string) != 0))
2370    {
2371      handle = handle->next;
2372    }
2373
2374  return handle;
2375}
2376
2377
2378lt_dlhandle
2379lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2380{
2381  lt_dlhandle handle = 0;
2382
2383  assert (iface); /* iface is a required argument */
2384
2385  while ((handle = lt_dlhandle_iterate (iface, handle)))
2386    {
2387      lt_dlhandle cur = handle;
2388      if (cur && cur->info.name && streq (cur->info.name, module_name))
2389        break;
2390    }
2391
2392  return handle;
2393}
2394
2395
2396int
2397lt_dlhandle_map (lt_dlinterface_id iface,
2398                 int (*func) (lt_dlhandle handle, void *data), void *data)
2399{
2400  lt__interface_id *iterator = (lt__interface_id *) iface;
2401  lt_dlhandle cur = handles;
2402
2403  assert (iface); /* iface is a required argument */
2404
2405  while (cur)
2406    {
2407      int errorcode = 0;
2408
2409      /* advance while the interface check fails */
2410      while (cur && iterator->iface
2411             && ((*iterator->iface) (cur, iterator->id_string) != 0))
2412        {
2413          cur = cur->next;
2414        }
2415
2416      if ((errorcode = (*func) (cur, data)) != 0)
2417        return errorcode;
2418    }
2419
2420  return 0;
2421}
Note: See TracBrowser for help on using the browser.