source: squid-ssl/trunk/fuentes/libltdl/ltdl.c

Last change on this file was 5499, checked in by Juanma, 2 years ago

Initial release

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