⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ltdl.c

📁 MPI stands for the Message Passing Interface. Written by the MPI Forum (a large committee comprising
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ltdl.c -- system independent dlopen wrapper   Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,		 2007 Free Software Foundation, Inc.   Written by Thomas Tanner, 1998   NOTE: The canonical source of this file is maintained with the   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.GNU Libltdl is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2 of the License, or (at your option) any later version.As a special exception to the GNU Lesser General Public License,if you distribute this file as part of a program or library thatis built using GNU Libtool, you may include this file under thesame distribution terms that you use for the rest of that program.GNU Libltdl is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU Lesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with GNU Libltdl; see the file COPYING.LIB.  If not, acopy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,or obtained by writing to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/#include "lt__private.h"#include "lt_system.h"#include "lt_dlloader.h"/* --- 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  LT_ARCHIVE_EXT#define LT_ARCHIVE_EXT	".la"/* max. filename length */#if !defined(LT_FILENAME_MAX)#  define LT_FILENAME_MAX	1024#endif/* This is the maximum symbol size that won't require malloc/free */#undef	LT_SYMBOL_LENGTH#define LT_SYMBOL_LENGTH	128/* This accounts for the _LTX_ separator */#undef	LT_SYMBOL_OVERHEAD#define LT_SYMBOL_OVERHEAD	5/* Various boolean flags can be stored in the flags field of an   lt_dlhandle... */#define LT_DLIS_RESIDENT(handle)  (((lt__handle*)handle)->info.is_resident)#define LT_DLIS_SYMGLOBAL(handle) (((lt__handle*)handle)->info.is_symglobal)#define LT_DLIS_SYMLOCAL(handle)  (((lt__handle*)handle)->info.is_symlocal)static	const char	objdir[]		= LT_OBJDIR;static	const char	archive_ext[]		= LT_ARCHIVE_EXT;#if defined(LT_MODULE_EXT)static	const char	shlib_ext[]		= LT_MODULE_EXT;#endif#if defined(LT_DLSEARCH_PATH)static	const char	sys_dlsearch_path[]	= LT_DLSEARCH_PATH;#endif/* --- DYNAMIC MODULE LOADING --- *//* The type of a function used at each iteration of  foreach_dirinpath().  */typedef int	foreach_callback_func (char *filename, void *data1,				       void *data2);/* foreachfile_callback itself calls a function of this type: */typedef int	file_worker_func      (const char *filename, void *data);static	int	foreach_dirinpath     (const char *search_path,				       const char *base_name,				       foreach_callback_func *func,				       void *data1, void *data2);static	int	find_file_callback    (char *filename, void *data1,				       void *data2);static	int	find_handle_callback  (char *filename, void *data,				       void *ignored);static	int	foreachfile_callback  (char *filename, void *data1,				       void *data2);static	int     canonicalize_path     (const char *path, char **pcanonical);static	int	argzize_path	      (const char *path,				       char **pargz, size_t *pargz_len);static	FILE   *find_file	      (const char *search_path,				       const char *base_name, char **pdir);static	lt_dlhandle *find_handle      (const char *search_path,				       const char *base_name,				       lt_dlhandle *handle,				       lt_dladvise advise);static	int	find_module	      (lt_dlhandle *handle, const char *dir,				       const char *libdir, const char *dlname,				       const char *old_name, int installed,				       lt_dladvise advise);static  int     has_library_ext       (const char *filename);static	int	load_deplibs	      (lt_dlhandle handle,  char *deplibs);static	int	trim		      (char **dest, const char *str);static	int	try_dlopen	      (lt_dlhandle *handle,				       const char *filename, const char *ext,				       lt_dladvise advise);static	int	tryall_dlopen	      (lt_dlhandle *handle,				       const char *filename,				       lt_dladvise padvise,				       const lt_dlvtable *vtable);static	int	unload_deplibs	      (lt_dlhandle handle);static	int	lt_argz_insert	      (char **pargz, size_t *pargz_len,				       char *before, const char *entry);static	int	lt_argz_insertinorder (char **pargz, size_t *pargz_len,				       const char *entry);static	int	lt_argz_insertdir     (char **pargz, size_t *pargz_len,				       const char *dirnam, struct dirent *dp);static	int	lt_dlpath_insertdir   (char **ppath, char *before,				       const char *dir);static	int	list_files_by_dir     (const char *dirnam,				       char **pargz, size_t *pargz_len);static	int	file_not_found	      (void);#ifdef HAVE_LIBDLLOADERstatic	int	loader_init_callback  (lt_dlhandle handle);#endif /* HAVE_LIBDLLOADER */static	int	loader_init	      (lt_get_vtable *vtable_func,				       lt_user_data data);static	char	       *user_search_path= 0;static	lt_dlhandle	handles	= 0;static	int		initialized	= 0;/* Our memory failure callback sets the error message to be passed back   up to the client, so we must be careful to return from mallocation   callers if allocation fails (as this callback returns!!).  */voidlt__alloc_die_callback (void){  LT__SETERROR (NO_MEMORY);}#ifdef HAVE_LIBDLLOADER/* This function is called to initialise each preloaded module loader,   and hook it into the list of loaders to be used when attempting to   dlopen an application module.  */static intloader_init_callback (lt_dlhandle handle){  lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");  return loader_init (vtable_func, 0);}#endif /* HAVE_LIBDLLOADER */static intloader_init (lt_get_vtable *vtable_func, lt_user_data data){  const lt_dlvtable *vtable = 0;  int errors = 0;  if (vtable_func)    {      vtable = (*vtable_func) (data);    }  /* lt_dlloader_add will LT__SETERROR if it fails.  */  errors += lt_dlloader_add (vtable);  assert (errors || vtable);  if ((!errors) && vtable->dlloader_init)    {      if ((*vtable->dlloader_init) (vtable->dlloader_data))	{	  LT__SETERROR (INIT_LOADER);	  ++errors;	}    }  return errors;}/* Bootstrap the loader loading with the preopening loader.  */#define get_vtable		preopen_LTX_get_vtable#define preloaded_symbols	LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)LT_BEGIN_C_DECLSLT_SCOPE const lt_dlvtable *	get_vtable (lt_user_data data);LT_END_C_DECLS#ifdef HAVE_LIBDLLOADERextern lt_dlsymlist		preloaded_symbols;#endif/* Initialize libltdl. */intlt_dlinit (void){  int	errors	= 0;  /* Initialize only at first call. */  if (++initialized == 1)    {      lt__alloc_die	= lt__alloc_die_callback;      handles		= 0;      user_search_path	= 0; /* empty search path */      /* First set up the statically loaded preload module loader, so	 we can use it to preopen the other loaders we linked in at	 compile time.  */      errors += loader_init (get_vtable, 0);      /* Now open all the preloaded module loaders, so the application	 can use _them_ to lt_dlopen its own modules.  */#ifdef HAVE_LIBDLLOADER      if (!errors)	{	  errors += lt_dlpreload (&preloaded_symbols);	}      if (!errors)	{	  errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);	}#endif /* HAVE_LIBDLLOADER */    }#ifdef LT_DEBUG_LOADERS  lt_dlloader_dump();#endif  return errors;}intlt_dlexit (void){  /* shut down libltdl */  lt_dlloader *loader   = 0;  lt__handle  *handle   = (lt__handle *) handles;  int	       errors   = 0;  if (!initialized)    {      LT__SETERROR (SHUTDOWN);      ++errors;      goto done;    }  /* shut down only at last call. */  if (--initialized == 0)    {      int	level;      while (handles && LT_DLIS_RESIDENT (handles))	{	  handles = ((lt__handle *) handles)->next;	}      /* close all modules */      for (level = 1; handle; ++level)	{	  lt__handle *cur = (lt__handle *) handles;	  int saw_nonresident = 0;	  while (cur)	    {	      lt__handle *tmp = cur;	      cur = cur->next;	      if (!LT_DLIS_RESIDENT (tmp))		{		  saw_nonresident = 1;		  if (tmp->info.ref_count <= level)		    {		      if (lt_dlclose (tmp))			{			  ++errors;			}		      /* Make sure that the handle pointed to by 'cur' still exists.			 lt_dlclose recursively closes dependent libraries which removes			 them from the linked list.  One of these might be the one			 pointed to by 'cur'.  */		      if (cur)			{			  for (tmp = (lt__handle *) handles; tmp; tmp = tmp->next)			    if (tmp == cur)			      break;			  if (! tmp)			    cur = (lt__handle *) handles;			}		    }		}	    }	  /* done if only resident modules are left */	  if (!saw_nonresident)	    break;	}      /* close all loaders */      for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)	{	  lt_dlloader *next   = (lt_dlloader *) lt_dlloader_next (loader);	  lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);	  if ((vtable = lt_dlloader_remove ((char *) vtable->name)))	    {	      FREE (vtable);	    }	  else	    {	      ++errors;	    }	  loader = next;	}      FREE(user_search_path);    } done:  return errors;}/* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.   If the library is not successfully loaded, return non-zero.  Otherwise,   the dlhandle is stored at the address given in PHANDLE.  */static inttryall_dlopen (lt_dlhandle *phandle, const char *filename,	       lt_dladvise padvise, const lt_dlvtable *vtable){  lt__handle *	handle		= (lt__handle *) handles;  const char *	saved_error	= 0;  int		errors		= 0;  lt__advise *  advise		= (lt__advise *) padvise;#ifdef LT_DEBUG_LOADERS  fprintf (stderr, "tryall_dlopen (%s, %s)\n",	   filename ? filename : "(null)",	   vtable ? vtable->name : "(ALL)");#endif  LT__GETERROR (saved_error);  /* check whether the module was already opened */  for (;handle; handle = handle->next)    {      if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */	  || (handle->info.filename && filename	      && streq (handle->info.filename, filename)))	{	  break;	}    }  if (handle)    {      ++handle->info.ref_count;      *phandle = handle;      goto done;    }  handle = (lt__handle *) *phandle;  if (filename)    {      /* Comment out the check of file permissions using access.	 This call seems to always return -1 with error EACCES.      */      /* We need to catch missing file errors early so that	 file_not_found() can detect what happened.      if (access (filename, R_OK) != 0)	{	  LT__SETERROR (FILE_NOT_FOUND);	  ++errors;	  goto done;	} */      handle->info.filename = lt__strdup (filename);      if (!handle->info.filename)	{	  ++errors;	  goto done;	}    }  else    {      handle->info.filename = 0;    }  {    lt_dlloader loader = lt_dlloader_next (0);    const lt_dlvtable *loader_vtable;    do      {	if (vtable)	  loader_vtable = vtable;	else	  loader_vtable = lt_dlloader_get (loader);#ifdef LT_DEBUG_LOADERS	fprintf (stderr, "Calling %s->module_open (%s)\n",		 (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",		 filename ? filename : "(null)");#endif	handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,							filename, advise);#ifdef LT_DEBUG_LOADERS	fprintf (stderr, "  Result: %s\n",		 handle->module ? "Success" : "Failed");#endif	if (handle->module != 0)	  {	    if (advise)	      {		handle->info.is_resident  = advise->is_resident;		handle->info.is_symglobal = advise->is_symglobal;		handle->info.is_symlocal  = advise->is_symlocal;	      }	    break;	  }      }    while (!vtable && (loader = lt_dlloader_next (loader)));    /* If VTABLE was given but couldn't open the module, or VTABLE wasn't       given but we exhausted all loaders without opening the module, bail       out!  */    if ((vtable && !handle->module)	|| (!vtable && !loader))      {	FREE (handle->info.filename);	++errors;	goto done;      }    handle->vtable = loader_vtable;  }  LT__SETERRORSTR (saved_error); done:  return errors;}static inttryall_dlopen_module (lt_dlhandle *handle, const char *prefix,		      const char *dirname, const char *dlname,		      lt_dladvise advise){  int      error	= 0;  char     *filename	= 0;  size_t   filename_len	= 0;  size_t   dirname_len	= LT_STRLEN (dirname);  assert (handle);  assert (dirname);  assert (dlname);#if defined(LT_DIRSEP_CHAR)  /* Only canonicalized names (i.e. with DIRSEP chars already converted)     should make it into this function:  */  assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);#endif  if (dirname_len > 0)    if (dirname[dirname_len -1] == '/')      --dirname_len;  filename_len = dirname_len + 1 + LT_STRLEN (dlname);  /* Allocate memory, and combine DIRNAME and MODULENAME into it.     The PREFIX (if any) is handled below.  */  filename  = MALLOC (char, dirname_len + 1 + filename_len + 1);  if (!filename)    return 1;  sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);  /* Now that we have combined DIRNAME and MODULENAME, if there is     also a PREFIX to contend with, simply recurse with the arguments     shuffled.  Otherwise, attempt to open FILENAME as a module.  */  if (prefix)    {      error += tryall_dlopen_module (handle, (const char *) 0,				     prefix, filename, advise);    }  else if (tryall_dlopen (handle, filename, advise, 0) != 0)    {      ++error;    }  FREE (filename);  return error;}static intfind_module (lt_dlhandle *handle, const char *dir, const char *libdir,	     const char *dlname,  const char *old_name, int installed,	     lt_dladvise advise){  /* Try to open the old library first; if it was dlpreopened,     we want the preopened version of it, even if a dlopenable     module is available.  */  if (old_name && tryall_dlopen (handle, old_name, advise, 0) == 0)    {      return 0;    }  /* Try to open the dynamic library.  */  if (dlname)    {      /* try to open the installed module */      if (installed && libdir)	{	  if (tryall_dlopen_module (handle, (const char *) 0,				    libdir, dlname, advise) == 0)	    return 0;	}      /* try to open the not-installed module */      if (!installed)	{	  if (tryall_dlopen_module (handle, dir, objdir,				    dlname, advise) == 0)	    return 0;	}      /* maybe it was moved to another directory */      {	  if (dir && (tryall_dlopen_module (handle, (const char *) 0,					    dir, dlname, advise) == 0))	    return 0;      }    }  return 1;}static intcanonicalize_path (const char *path, char **pcanonical){  char *canonical = 0;  assert (path && *path);  assert (pcanonical);  canonical = MALLOC (char, 1+ LT_STRLEN (path));  if (!canonical)    return 1;  {    size_t dest = 0;    size_t src;    for (src = 0; path[src] != LT_EOS_CHAR; ++src)      {	/* Path separators are not copied to the beginning or end of	   the destination, or if another separator would follow	   immediately.  */	if (path[src] == LT_PATHSEP_CHAR)	  {	    if ((dest == 0)		|| (path[1+ src] == LT_PATHSEP_CHAR)		|| (path[1+ src] == LT_EOS_CHAR))	      continue;	  }	/* Anything other than a directory separator is copied verbatim.  */	if ((path[src] != '/')#if defined(LT_DIRSEP_CHAR)	    && (path[src] != LT_DIRSEP_CHAR)#endif	    )	  {	    canonical[dest++] = path[src];	  }	/* Directory separators are converted and copied only if they are	   not at the end of a path -- i.e. before a path separator or	   NULL terminator.  */	else if ((path[1+ src] != LT_PATHSEP_CHAR)		 && (path[1+ src] != LT_EOS_CHAR)#if defined(LT_DIRSEP_CHAR)		 && (path[1+ src] != LT_DIRSEP_CHAR)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -