]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
Based on a patch from Marius Vollmer <mvo@zagadka.ping.de>:
authorGary V. Vaughan <gary@gnu.org>
Sun, 2 Sep 2001 17:38:55 +0000 (17:38 +0000)
committerGary V. Vaughan <gary@gnu.org>
Sun, 2 Sep 2001 17:38:55 +0000 (17:38 +0000)
* NEWS: updated.
* ltdl.m4 (AC_LIB_LTDL): Check for unistd.h.
* ltdl.c: Include unistd.h if it exists.
(LTDL_SEARCHPATH_VAR): Macro to prevent hardcoding
"LTDL_LIBRARY_PATH".
(LTDL_ARCHIVE_EXT): Macro to prevent hardcoding ".la".
(archive_ext): Have only one copy of ".la" in the readonly
segment of the compiled library.
(find_handle_callback): Don't bother trying to dlopen the file if
it doesn't exist.
(find_handle): Don't bother searching for files if no search_path
was supplied.
(file_not_found): A new function to determine whether the last
error was due to a file not found condition.
(try_dlopen): Renamed from lt_dlopen() and changed to have the
same footprint as tryall_dlopen.  This involved a minor rewrite of
much of the internals of this function.
(lt_dlopen): A new function wrapped arounf try_dlopen().
(lt_dlopenext): If a file already has a suitable extension, don't
bother adding additional extensions and trying to open those.
Tidy up the rest of the code to prevent continued searching with
an eventual FILE_NOT_FOUND when a genuine failure earlier in the
search process could be legitimately reported.

ChangeLog
NEWS
libltdl/ltdl.c
ltdl.m4

index fe05ca98e218ef90710ecd1c29875c0337ee3b56..8199bccf3ccde9ceb85259735b47b67127096e32 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
 2001-09-02  Gary V. Vaughan  <gary@gnu.org>
 
+       Based on a patch from Marius Vollmer <mvo@zagadka.ping.de>:
+       * NEWS: updated.
+       * ltdl.m4 (AC_LIB_LTDL): Check for unistd.h.
+       * ltdl.c: Include unistd.h if it exists.
+       (LTDL_SEARCHPATH_VAR): Macro to prevent hardcoding
+       "LTDL_LIBRARY_PATH".
+       (LTDL_ARCHIVE_EXT): Macro to prevent hardcoding ".la".
+       (archive_ext): Have only one copy of ".la" in the readonly
+       segment of the compiled library.
+       (find_handle_callback): Don't bother trying to dlopen the file if
+       it doesn't exist.
+       (find_handle): Don't bother searching for files if no search_path
+       was supplied.
+       (file_not_found): A new function to determine whether the last
+       error was due to a file not found condition.
+       (try_dlopen): Renamed from lt_dlopen() and changed to have the
+       same footprint as tryall_dlopen.  This involved a minor rewrite of
+       much of the internals of this function.
+       (lt_dlopen): A new function wrapped arounf try_dlopen().
+       (lt_dlopenext): If a file already has a suitable extension, don't
+       bother adding additional extensions and trying to open those.
+       Tidy up the rest of the code to prevent continued searching with
+       an eventual FILE_NOT_FOUND when a genuine failure earlier in the
+       search process could be legitimately reported.
+
        * demo/Makefile.am (helldl$(EXEEXT)): Automake-1.5 made me change
        this from just `helldl'.
 
diff --git a/NEWS b/NEWS
index 778d794786cd2aa08d675b3bcc296b2c3e83a819..f773355e0c7b0af6b6ac1b2efbdf703d5c3395fa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ NEWS - list of user-visible changes between releases of GNU Libtool
 New in 1.4d: 2001-??-??; CVS version 1.4c, Libtool team:
 * Help strings display correctly again.
 * Better error messages when library linking fails.
+* Better error messages from libltdl when loading fails.
 * Better search path management in libltdl with `lt_dlinsertsearchdir' call.
 * Support /lib/w32api in recent cygwin releases.
 * Support cross compilation to mingw.
index 55dbc2e44a0fae3cf59030ed26fd57d7985341ba..3de6b3ca8b3f10eaef4884f260b7e85e035d01b1 100644 (file)
@@ -29,6 +29,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 #  include <config.h>
 #endif
 
+#if HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
 #if HAVE_STDIO_H
 #  include <stdio.h>
 #endif
@@ -113,6 +117,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 /* --- MANIFEST CONSTANTS --- */
 
 
+/* Standard libltdl search path environment variable name  */
+#undef  LTDL_SEARCHPATH_VAR
+#define LTDL_SEARCHPATH_VAR    "LTDL_LIBRARY_PATH"
+
+/* Standard libtool archive file extension.  */
+#undef  LTDL_ARCHIVE_EXT
+#define LTDL_ARCHIVE_EXT       ".la"
+
 /* max. filename length */
 #ifndef LT_FILENAME_MAX
 #  define LT_FILENAME_MAX      1024
@@ -406,7 +418,7 @@ argz_append (pargz, pargz_len, buf, buf_len)
   assert (pargz);
   assert (pargz_len);
   assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
-  
+
   /* If nothing needs to be appended, no more work is required.  */
   if (buf_len == 0)
     return 0;
@@ -416,7 +428,7 @@ argz_append (pargz, pargz_len, buf, buf_len)
   argz = LT_DLREALLOC (char, *pargz, argz_len);
   if (!argz)
     return ENOMEM;
-  
+
   /* Copy characters from BUF after terminating '\0' in ARGZ.  */
   memcpy (argz + *pargz_len, buf, buf_len);
 
@@ -482,7 +494,7 @@ argz_create_sep (str, delim, pargz, pargz_len)
   /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
   if (!argz_len)
     LT_DLFREE (argz);
-      
+
   /* Assign new values.  */
   *pargz = argz;
   *pargz_len = argz_len;
@@ -548,8 +560,8 @@ argz_insert (pargz, pargz_len, before, entry)
     *pargz = argz;
     *pargz_len = argz_len;
   }
-  
-  return 0;  
+
+  return 0;
 }
 #endif /* !HAVE_ARGZ_INSERT */
 
@@ -693,6 +705,7 @@ struct lt_dlhandle_struct {
 #define LT_DLSTRERROR(name)    lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
 
 static const char      objdir[]                = LTDL_OBJDIR;
+static const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
 #ifdef LTDL_SHLIB_EXT
 static const char      shlib_ext[]             = LTDL_SHLIB_EXT;
 #endif
@@ -706,9 +719,9 @@ static      const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
 /* --- MUTEX LOCKING --- */
 
 
-/* Macros to make it easier to run the lock functions only if they have 
+/* Macros to make it easier to run the lock functions only if they have
    been registered.  The reason for the complicated lock macro is to
-   ensure that the stored error message from the last error is not 
+   ensure that the stored error message from the last error is not
    accidentally erased if the current function doesn't generate an
    error of its own.  */
 #define LT_DLMUTEX_LOCK()                      LT_STMT_START { \
@@ -752,7 +765,7 @@ lt_dlmutex_register (lock, unlock, seterror, geterror)
   /* Lock using the old lock() callback, if any.  */
   LT_DLMUTEX_LOCK ();
 
-  if ((lock && unlock && seterror && geterror) 
+  if ((lock && unlock && seterror && geterror)
       || !(lock || unlock || seterror || geterror))
     {
       lt_dlmutex_lock_func     = lock;
@@ -1052,9 +1065,9 @@ sys_shl_open (loader_data, filename)
 {
   static shl_t self = (shl_t) 0;
   lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
-  
+
   /* Since searching for a symbol against a NULL module handle will also
-     look in everything else that was already loaded and exported with 
+     look in everything else that was already loaded and exported with
      the -E compiler flag, we always cache a handle saved before any
      modules are loaded.  */
   if (!self)
@@ -1062,7 +1075,7 @@ sys_shl_open (loader_data, filename)
       lt_ptr address;
       shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
     }
-  
+
   if (!filename)
     {
       module = self;
@@ -1076,7 +1089,7 @@ sys_shl_open (loader_data, filename)
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
        }
     }
-  
+
   return module;
 }
 
@@ -1116,7 +1129,7 @@ sys_shl_sym (loader_data, module, symbol)
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        }
     }
-  
+
   return address;
 }
 
@@ -1516,7 +1529,7 @@ presym_add_symlist (preloaded)
     {
       ++errors;
     }
-  
+
  done:
   LT_DLMUTEX_UNLOCK ();
   return errors;
@@ -1657,6 +1670,8 @@ static    int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
                                                 char *deplibs));
 static int     trim                  LT_PARAMS((char **dest,
                                                 const char *str));
+static int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
+                                                const char *filename));
 static int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
                                                 const char *filename));
 static int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
@@ -1737,7 +1752,7 @@ lt_dlpreload (preloaded)
   else
     {
       presym_free_symlists();
-  
+
       LT_DLMUTEX_LOCK ();
       if (default_preloaded_symbols)
        {
@@ -1909,7 +1924,7 @@ tryall_dlopen (handle, filename)
 
   cur->loader  = loader;
   LT_DLMUTEX_SETERROR (saved_error);
-  
+
  done:
   LT_DLMUTEX_UNLOCK ();
 
@@ -1936,7 +1951,7 @@ tryall_dlopen_module (handle, prefix, dirname, dlname)
      should make it into this function:  */
   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
 #endif
-  
+
   if (dirname[dirname_len -1] == '/')
     --dirname_len;
   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
@@ -1960,7 +1975,7 @@ tryall_dlopen_module (handle, prefix, dirname, dlname)
     {
       ++error;
     }
-    
+
   LT_DLFREE (filename);
   return error;
 }
@@ -2016,7 +2031,7 @@ canonicalize_path (path, pcanonical)
      char **pcanonical;
 {
   char *canonical = 0;
-  
+
   assert (path && *path);
   assert (pcanonical);
 
@@ -2080,7 +2095,7 @@ argzize_path (path, pargz, pargz_len)
      size_t *pargz_len;
 {
   error_t error;
-  
+
   assert (path);
   assert (pargz);
   assert (pargz_len);
@@ -2159,7 +2174,7 @@ foreach_dirinpath (search_path, base_name, func, data1, data2)
              filename[lendir++] = '/';
            strcpy (filename +lendir, base_name);
          }
-       
+
        if ((result = (*func) (filename, data1, data2)))
          {
            break;
@@ -2173,7 +2188,7 @@ foreach_dirinpath (search_path, base_name, func, data1, data2)
   LT_DLFREE (filename);
 
   LT_DLMUTEX_UNLOCK ();
-  
+
   return result;
 }
 
@@ -2229,22 +2244,31 @@ find_handle_callback (filename, data, ignored)
      lt_ptr ignored;
 {
   lt_dlhandle  *handle = (lt_dlhandle *) data;
-  int          is_done = 0;
+  int          found   = access (filename, R_OK);
 
-  if (tryall_dlopen (handle, filename) == 0)
-    {
-      is_done = 1;
-    }
+  /* Bail out if file cannot be read...  */
+  if (!found)
+    return 0;
 
-  return is_done;
+  /* Try to dlopen the file, but do not continue searching in any
+     case.  */
+  if (tryall_dlopen (handle, filename) != 0)
+    *handle = 0;
+
+  return 1;
 }
 
+/* If HANDLE was found return it, otherwise return 0.  If HANDLE was
+   found but could not be opened, *HANDLE will be set to 0.  */
 static lt_dlhandle *
 find_handle (search_path, base_name, handle)
      const char *search_path;
      const char *base_name;
      lt_dlhandle *handle;
 {
+  if (!search_path)
+    return 0;
+
   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
                          handle, 0))
     return 0;
@@ -2481,45 +2505,57 @@ free_vars (dlname, oldname, libdir, deplibs)
   return 0;
 }
 
-lt_dlhandle
-lt_dlopen (filename)
+int
+try_dlopen (phandle, filename)
+     lt_dlhandle *phandle;
      const char *filename;
 {
-  lt_dlhandle handle = 0, newhandle;
-  const char *ext;
-  const char *saved_error;
-  char *canonical = 0, *base_name = 0, *dir = 0, *name = 0;
+  const char * ext             = 0;
+  const char * saved_error     = 0;
+  char *       canonical       = 0;
+  char *       base_name       = 0;
+  char *       dir             = 0;
+  char *       name            = 0;
+  int          errors          = 0;
+  lt_dlhandle  newhandle;
 
-  /* Doing this immediately allows internal functions to safely
-     assume only canonicalized paths are passed.  */
-  if (filename && (canonicalize_path (filename, &canonical) != 0))
-    return 0;
+  assert (phandle);
+  assert (*phandle == 0);
 
   LT_DLMUTEX_GETERROR (saved_error);
 
   /* dlopen self? */
   if (!filename)
     {
-      handle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
-      if (!handle)
-       return 0;
+      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
+      if (*phandle == 0)
+       return 1;
 
-      memset (handle, 0, 1*sizeof(struct lt_dlhandle_struct));
-      newhandle        = handle;
+      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
+      newhandle        = *phandle;
 
       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
-      LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
+      LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
 
       if (tryall_dlopen (&newhandle, 0) != 0)
        {
-         LT_DLFREE (handle);
-         return 0;
+         LT_DLFREE (*phandle);
+         return 1;
        }
+
       goto register_handle;
     }
 
   assert (filename && *filename);
 
+  /* Doing this immediately allows internal functions to safely
+     assume only canonicalized paths are passed.  */
+  if (canonicalize_path (filename, &canonical) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
   /* If the canonical module name is a path (relative or absolute)
      then split it into a directory part and a name part.  */
   base_name = strrchr (canonical, '/');
@@ -2529,7 +2565,10 @@ lt_dlopen (filename)
 
       dir = LT_EMALLOC (char, 1+ dirlen);
       if (!dir)
-       goto cleanup;
+       {
+         ++errors;
+         goto cleanup;
+       }
 
       strncpy (dir, canonical, dirlen);
       dir[dirlen] = LT_EOS_CHAR;
@@ -2538,21 +2577,22 @@ lt_dlopen (filename)
     }
   else
     LT_DLMEM_REASSIGN (base_name, canonical);
-      
+
   assert (base_name && *base_name);
 
   /* Check whether we are opening a libtool module (.la extension).  */
-  ext = strrchr(base_name, '.');
-  if (ext && strcmp(ext, ".la") == 0)
+  ext = strrchr (base_name, '.');
+  if (ext && strcmp (ext, archive_ext) == 0)
     {
       /* this seems to be a libtool module */
-      FILE     *file = 0;
-      int      i;
-      char     *dlname = 0, *old_name = 0;
-      char     *libdir = 0, *deplibs = 0;
-      char     *line;
+      FILE *   file     = 0;
+      char *   dlname   = 0;
+      char *   old_name = 0;
+      char *   libdir   = 0;
+      char *   deplibs  = 0;
+      char *    line    = 0;
       size_t   line_len;
-      int      error = 0;
+      int      i;
 
       /* if we can't find the installed flag, it is probably an
         installed libtool archive, produced with an old version
@@ -2562,7 +2602,10 @@ lt_dlopen (filename)
       /* extract the module name from the file name */
       name = LT_EMALLOC (char, ext - base_name + 1);
       if (!name)
-       goto cleanup;
+       {
+         ++errors;
+         goto cleanup;
+       }
 
       /* canonicalize the module name */
       for (i = 0; i < ext - base_name; ++i)
@@ -2576,7 +2619,6 @@ lt_dlopen (filename)
              name[i] = '_';
            }
        }
-
       name[ext - base_name] = LT_EOS_CHAR;
 
     /* Now try to open the .la file.  If there is no directory name
@@ -2585,20 +2627,31 @@ lt_dlopen (filename)
        yet found) try opening just the module name as passed.  */
       if (!dir)
        {
-         file = find_file (user_search_path, base_name, &dir);
+         const char *search_path;
+
+         LT_DLMUTEX_LOCK ();
+         search_path = user_search_path;
+         if (search_path)
+           file = find_file (user_search_path, base_name, &dir);
+         LT_DLMUTEX_UNLOCK ();
+
          if (!file)
            {
-             file = find_file (getenv("LTDL_LIBRARY_PATH"), base_name, &dir);
+             search_path = getenv (LTDL_SEARCHPATH_VAR);
+             if (search_path)
+               file = find_file (search_path, base_name, &dir);
            }
 
 #ifdef LTDL_SHLIBPATH_VAR
          if (!file)
            {
-             file = find_file (getenv(LTDL_SHLIBPATH_VAR), base_name, &dir);
+             search_path = getenv (LTDL_SHLIBPATH_VAR);
+             if (search_path)
+               file = find_file (search_path, base_name, &dir);
            }
 #endif
 #ifdef LTDL_SYSSEARCHPATH
-         if (!file)
+         if (!file && sys_search_path)
            {
              file = find_file (sys_search_path, base_name, &dir);
            }
@@ -2608,32 +2661,34 @@ lt_dlopen (filename)
        {
          file = fopen (filename, LT_READTEXT_MODE);
        }
+
+      /* If we didn't find the file by now, it really isn't there.  Set
+        the status flag, and bail out.  */
       if (!file)
        {
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+         ++errors;
+         goto cleanup;
        }
 
-      if (!file)
-       goto cleanup;
-
       line_len = LT_FILENAME_MAX;
       line = LT_EMALLOC (char, line_len);
       if (!line)
        {
          fclose (file);
+         ++errors;
          goto cleanup;
        }
 
       /* read the .la file */
-      while (!feof(file))
+      while (!feof (file))
        {
          if (!fgets (line, line_len, file))
            {
              break;
            }
 
-
-         /* Handle the case where we occasionally need to read a line 
+         /* Handle the case where we occasionally need to read a line
             that is longer than the initial buffer size.  */
          while (line[LT_STRLEN(line) -1] != '\n')
            {
@@ -2654,7 +2709,7 @@ lt_dlopen (filename)
 #define STR_DLNAME     "dlname="
          if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
            {
-             error = trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
+             errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
            }
 
 #undef  STR_OLD_LIBRARY
@@ -2662,13 +2717,13 @@ lt_dlopen (filename)
          else if (strncmp (line, STR_OLD_LIBRARY,
                            sizeof (STR_OLD_LIBRARY) - 1) == 0)
            {
-             error = trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
+             errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
            }
 #undef  STR_LIBDIR
 #define STR_LIBDIR     "libdir="
          else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
            {
-             error = trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
+             errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
            }
 
 #undef  STR_DL_DEPLIBS
@@ -2676,7 +2731,7 @@ lt_dlopen (filename)
          else if (strncmp (line, STR_DL_DEPLIBS,
                            sizeof (STR_DL_DEPLIBS) - 1) == 0)
            {
-             error = trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
+             errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
            }
          else if (strcmp (line, "installed=yes\n") == 0)
            {
@@ -2693,21 +2748,22 @@ lt_dlopen (filename)
                                        sizeof (STR_LIBRARY_NAMES) - 1) == 0)
            {
              char *last_libname;
-             error = trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
-             if (! error && dlname &&
-                 (last_libname = strrchr (dlname, ' ')) != 0)
+             errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
+             if (!errors
+                 && dlname
+                 && (last_libname = strrchr (dlname, ' ')) != 0)
                {
                  last_libname = lt_estrdup (last_libname + 1);
                  if (!last_libname)
                    {
-                     ++error;
+                     ++errors;
                      goto cleanup;
                    }
                  LT_DLMEM_REASSIGN (dlname, last_libname);
                }
            }
 
-         if (error)
+         if (errors)
            break;
        }
 
@@ -2715,63 +2771,66 @@ lt_dlopen (filename)
       LT_DLFREE (line);
 
       /* allocate the handle */
-      handle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
-      if (!handle)
-       ++error;
+      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
+      if (*phandle == 0)
+       ++errors;
 
-      if (error)
+      if (errors)
        {
          free_vars (dlname, old_name, libdir, deplibs);
-         LT_DLFREE (handle);
+         LT_DLFREE (*phandle);
          goto cleanup;
        }
 
-      assert (handle);
+      assert (*phandle);
 
-      memset (handle, 0, sizeof(struct lt_dlhandle_struct));
-      if (load_deplibs (handle, deplibs) == 0)
+      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
+      if (load_deplibs (*phandle, deplibs) == 0)
        {
-         newhandle = handle;
+         newhandle = *phandle;
          /* find_module may replace newhandle */
          if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
            {
-             unload_deplibs (handle);
-             error = 1;
+             unload_deplibs (*phandle);
+             ++errors;
            }
        }
       else
        {
-         error = 1;
+         ++errors;
        }
 
       free_vars (dlname, old_name, libdir, deplibs);
-      if (error)
+      if (errors)
        {
-         LT_DLFREE (handle);
+         LT_DLFREE (*phandle);
          goto cleanup;
        }
 
-      if (handle != newhandle)
+      if (*phandle != newhandle)
        {
-         unload_deplibs (handle);
+         unload_deplibs (*phandle);
        }
     }
   else
     {
       /* not a libtool module */
-      handle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
-      if (!handle)
-       goto cleanup;
+      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
+      if (*phandle == 0)
+       {
+         ++errors;
+         goto cleanup;
+       }
 
-      memset (handle, 0, sizeof(struct lt_dlhandle_struct));
-      newhandle = handle;
+      memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
+      newhandle = *phandle;
 
       /* If the module has no directory name component, try to find it
         first in user_search_path and then other prescribed paths.
         Otherwise (or in any case if the module was not yet found) try
         opening just the module name as passed.  */
       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
-                  && !find_handle (getenv ("LTDL_LIBRARY_PATH"), base_name, 
+                  && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
                                    &newhandle)
 #ifdef LTDL_SHLIBPATH_VAR
                   && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
@@ -2780,24 +2839,30 @@ lt_dlopen (filename)
 #ifdef LTDL_SYSSEARCHPATH
                   && !find_handle (sys_search_path, base_name, &newhandle)
 #endif
-                  )) && tryall_dlopen (&newhandle, filename))
+                  )))
+       {
+         tryall_dlopen (&newhandle, filename);
+       }
+
+      if (!newhandle)
        {
-         LT_DLFREE (handle);
+         LT_DLFREE (*phandle);
+         ++errors;
          goto cleanup;
        }
     }
 
  register_handle:
-  LT_DLMEM_REASSIGN (handle, newhandle);
+  LT_DLMEM_REASSIGN (*phandle, newhandle);
 
-  if (handle->info.ref_count == 0)
+  if ((*phandle)->info.ref_count == 0)
     {
-      handle->info.ref_count   = 1;
-      LT_DLMEM_REASSIGN (handle->info.name, name);
+      (*phandle)->info.ref_count       = 1;
+      LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
 
       LT_DLMUTEX_LOCK ();
-      handle->next             = handles;
-      handles                  = handle;
+      (*phandle)->next         = handles;
+      handles                  = *phandle;
       LT_DLMUTEX_UNLOCK ();
     }
 
@@ -2808,50 +2873,96 @@ lt_dlopen (filename)
   LT_DLFREE (name);
   LT_DLFREE (canonical);
 
+  return errors;
+}
+
+lt_dlhandle
+lt_dlopen (filename)
+     const char *filename;
+{
+  lt_dlhandle handle = 0;
+
+  /* Just incase we missed a code path in try_dlopen() that reports
+     an error, but forgets to reset handle... */
+  if (try_dlopen (&handle, filename) != 0)
+    return 0;
+
   return handle;
 }
 
+/* If the last error messge store was `FILE_NOT_FOUND', then return
+   non-zero.  */
+int
+file_not_found ()
+{
+  const char *error = 0;
+
+  LT_DLMUTEX_GETERROR (error);
+  if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
+    return 1;
+
+  return 0;
+}
+
+/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
+   open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
+   and if a file is still not found try again with SHLIB_EXT appended
+   instead.  */
 lt_dlhandle
 lt_dlopenext (filename)
      const char *filename;
 {
-  lt_dlhandle handle;
-  char *tmp;
-  int  len;
-  const char *saved_error;
-
-  LT_DLMUTEX_GETERROR (saved_error);
+  lt_dlhandle  handle          = 0;
+  char *       tmp             = 0;
+  char *       ext             = 0;
+  int          len;
+  int          errors          = 0;
+  int          file_found      = 1; /* until proven otherwise */
 
   if (!filename)
     {
       return lt_dlopen (filename);
     }
 
+  assert (filename);
+
   len = LT_STRLEN (filename);
-  if (!len)
+  ext = strrchr (filename, '.');
+
+  /* If FILENAME already bears a suitable extension, there is no need
+     to try appending additional extensions.  */
+  if (ext && ((strcmp (ext, archive_ext) == 0)
+#ifdef LTDL_SHLIB_EXT
+             || (strcmp (ext, shlib_ext) == 0)
+#endif
+      ))
     {
-      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
-      return 0;
+      return lt_dlopen (filename);
     }
 
-  /* try "filename.la" */
-  tmp = LT_EMALLOC (char, len+4);
+  /* First try appending ARCHIVE_EXT.  */
+  tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
   if (!tmp)
     return 0;
 
   strcpy (tmp, filename);
-  strcat (tmp, ".la");
-  handle = lt_dlopen (tmp);
-  if (handle)
+  strcat (tmp, archive_ext);
+  errors = try_dlopen (&handle, tmp);
+
+  /* If we found FILENAME, stop searching -- whether we were able to
+     load the file as a module or not.  If the file exists but loading
+     failed, it is better to return an error message here than to
+     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
+     in the module search path.  */
+  if (handle || ((errors > 0) && file_not_found ()))
     {
-      LT_DLMUTEX_SETERROR (saved_error);
       LT_DLFREE (tmp);
       return handle;
     }
 
 #ifdef LTDL_SHLIB_EXT
-  /* try "filename.EXT" */
-  if (LT_STRLEN(shlib_ext) > 3)
+  /* Try appending SHLIB_EXT.   */
+  if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
     {
       LT_DLFREE (tmp);
       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
@@ -2866,22 +2977,19 @@ lt_dlopenext (filename)
     }
 
   strcat(tmp, shlib_ext);
-  handle = lt_dlopen (tmp);
-  if (handle)
+  errors = try_dlopen (&handle, tmp);
+
+  /* As before, if the file was found but loading failed, return now
+     with the current error message.  */
+  if (handle || ((errors > 0) && file_not_found ()))
     {
-      LT_DLMUTEX_SETERROR (saved_error);
       LT_DLFREE (tmp);
       return handle;
     }
 #endif
 
-  /* try the normal file name */
-  handle = lt_dlopen (filename);
-  if (handle)
-    {
-      return handle;
-    }
-
+  /* Still here?  Then we really did fail to locate any of the file
+     names we tried.  */
   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
   LT_DLFREE (tmp);
   return 0;
@@ -2987,7 +3095,7 @@ lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
   buf          = LT_EMALLOC (char, 1+ buf_len);
   if (!buf)
     return ++errors;
-    
+
   assert (buf);
 
   strcpy  (buf, dirnam);
@@ -3001,7 +3109,7 @@ lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
 
   LT_DLFREE (buf);
 
-  return errors; 
+  return errors;
 }
 
 int
@@ -3012,7 +3120,7 @@ list_files_by_dir (dirnam, pargz, pargz_len)
 {
   DIR  *dirp     = 0;
   int    errors          = 0;
-  
+
   assert (dirnam && *dirnam);
   assert (pargz);
   assert (pargz_len);
@@ -3356,7 +3464,7 @@ lt_dlpath_insertdir (ppath, before, dir)
       ++errors;
       goto cleanup;
     }
-  
+
   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
   LT_DLMEM_REASSIGN (*ppath,  argz);
 
@@ -3366,7 +3474,7 @@ lt_dlpath_insertdir (ppath, before, dir)
 
   return errors;
 }
-  
+
 int
 lt_dladdsearchdir (search_dir)
      const char *search_dir;
@@ -3394,7 +3502,7 @@ lt_dlinsertsearchdir (before, search_dir)
   if (before)
     {
       LT_DLMUTEX_LOCK ();
-      if ((before < user_search_path) 
+      if ((before < user_search_path)
          || (before >= user_search_path + LT_STRLEN (user_search_path)))
        {
          LT_DLMUTEX_UNLOCK ();
@@ -3407,7 +3515,7 @@ lt_dlinsertsearchdir (before, search_dir)
   if (search_dir && *search_dir)
     {
       LT_DLMUTEX_LOCK ();
-      if (lt_dlpath_insertdir (&user_search_path, 
+      if (lt_dlpath_insertdir (&user_search_path,
                               (char *) before, search_dir) != 0)
        {
          ++errors;
diff --git a/ltdl.m4 b/ltdl.m4
index b2966b13766e6f79a5cd88ba6602eb717e979c28..4d94d38ba51488823f8d70e60671790aa0a31ce4 100644 (file)
--- a/ltdl.m4
+++ b/ltdl.m4
@@ -45,7 +45,7 @@ AC_REQUIRE([AC_LTDL_DLSYM_USCORE])
 AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS])
 AC_REQUIRE([AC_LTDL_FUNC_ARGZ])
 
-AC_CHECK_HEADERS([ctype.h errno.h malloc.h memory.h stdlib.h stdio.h])
+AC_CHECK_HEADERS([ctype.h errno.h malloc.h memory.h stdlib.h stdio.h unistd.h])
 AC_CHECK_HEADERS([dl.h sys/dl.h dld.h])
 AC_CHECK_HEADERS([string.h strings.h], [break])
 
@@ -246,7 +246,7 @@ AC_DEFUN([AC_LTDL_DLLIB],
 [LIBADD_DL=
 AC_SUBST(LIBADD_DL)
 AC_LANG_PUSH([C])
-AC_CHECK_LIB([dl], [dlopen], 
+AC_CHECK_LIB([dl], [dlopen],
   [AC_DEFINE([HAVE_LIBDL], [1],
      [Define if you have the libdl library or equivalent.])
    LIBADD_DL="-ldl"],
@@ -254,10 +254,10 @@ AC_CHECK_LIB([dl], [dlopen],
 #  include <dlfcn.h>
 #endif
     ],
-    [dlopen();], 
+    [dlopen();],
     [AC_DEFINE(HAVE_LIBDL, 1,
       [Define if you have the libdl library or equivalent.])],
-    [AC_CHECK_LIB(svld, dlopen, 
+    [AC_CHECK_LIB(svld, dlopen,
       [AC_DEFINE(HAVE_LIBDL, 1,
         [Define if you have the libdl library or equivalent.])
       LIBADD_DL="-lsvld"