Split lt_dlloader management into a separate file, and factor

`loaders' list management into a new SList ADT.  In the process,
the API for writing loaders is a little cleaner, so all the
existing loaders were tweaked to take advantage of that:

* libltdl/slist.h, libltdl/slist.c: New files implementing a
generic singly linked list container ADT.  The ADT is purely
internal, and none of its API's are visible from an installed
libltdl.
* libltdl/lt_dlloader.h (lt_dlloader): Removed next field again
:-) Renamed to lt_dlvtable for API.  Changed all callers.
(lt_dlloader_get): New function to turn an lt_dlloader into its
associated lt_dlvtable.
(lt_dlloader_add): Removed unused data parameter.  The caller
data belongs to (and is set by) the loader itself, not the
loader's client.  Changed all callers.
(lt_dlloader_name, lt_dlloader_data): Removed.  Use
lt_dlloader_get instead!
* libltdl/lt__private.h: Include slist.h.
(lt__alloc_die_callback): Add missing LT_SCOPE to declaration.
(lt_dlhandle_struct): Use lt_dlvtable instead of opaque
lt_dlloader.
* libltdl/ltdl.c (lt_dlexit): Rewritten for the new loader API.
(loaders, lt_dlloader_add, lt_dlloader_remove, lt_dlloader_next,
lt_dlloader_find): Moved from here...
* libltdl/lt_dlloader.c ((loaders, lt_dlloader_add,
lt_dlloader_remove, lt_dlloader_next, lt_dlloader_find): ...to
here.  And rewritten in terms of new SList interface.
* libltdl/ltdl.c (lt_dlexit, tryall_dlopen): Rewritten in terms of
new lt_dlloader interface.
* libltdl/Makefile.am (libdlloader_la_SOURCES): Add slist.h and
slist.c.  Move lt_dlloader.h from here...
(pkginclude_HEADERS): ...to here.
(libltdl_la_SOURCES): Add lt_dlloader.c and lt_dlloader.h.
This commit is contained in:
Gary V. Vaughan 2004-07-15 12:33:20 +00:00
parent 52de761d29
commit 5451db06bd
16 changed files with 606 additions and 300 deletions

View File

@ -1,3 +1,40 @@
2004-07-15 Gary V. Vaughan <gary@gnu.org>
Split lt_dlloader management into a separate file, and factor
`loaders' list management into a new SList ADT. In the process,
the API for writing loaders is a little cleaner, so all the
existing loaders were tweaked to take advantage of that:
* libltdl/slist.h, libltdl/slist.c: New files implementing a
generic singly linked list container ADT. The ADT is purely
internal, and none of its API's are visible from an installed
libltdl.
* libltdl/lt_dlloader.h (lt_dlloader): Removed next field again
:-) Renamed to lt_dlvtable for API. Changed all callers.
(lt_dlloader_get): New function to turn an lt_dlloader into its
associated lt_dlvtable.
(lt_dlloader_add): Removed unused data parameter. The caller
data belongs to (and is set by) the loader itself, not the
loader's client. Changed all callers.
(lt_dlloader_name, lt_dlloader_data): Removed. Use
lt_dlloader_get instead!
* libltdl/lt__private.h: Include slist.h.
(lt__alloc_die_callback): Add missing LT_SCOPE to declaration.
(lt_dlhandle_struct): Use lt_dlvtable instead of opaque
lt_dlloader.
* libltdl/ltdl.c (lt_dlexit): Rewritten for the new loader API.
(loaders, lt_dlloader_add, lt_dlloader_remove, lt_dlloader_next,
lt_dlloader_find): Moved from here...
* libltdl/lt_dlloader.c ((loaders, lt_dlloader_add,
lt_dlloader_remove, lt_dlloader_next, lt_dlloader_find): ...to
here. And rewritten in terms of new SList interface.
* libltdl/ltdl.c (lt_dlexit, tryall_dlopen): Rewritten in terms of
new lt_dlloader interface.
* libltdl/Makefile.am (libdlloader_la_SOURCES): Add slist.h and
slist.c. Move lt_dlloader.h from here...
(pkginclude_HEADERS): ...to here.
(libltdl_la_SOURCES): Add lt_dlloader.c and lt_dlloader.h.
2004-07-15 Gary V. Vaughan <gary@gnu.org>
Collapse two almost identical structures into one:

View File

@ -35,16 +35,17 @@ pkgincludedir = $(includedir)/libltdl
lib_LTLIBRARIES = libdlloader.la
libdlloader_la_SOURCES = lt_error.h lt_error.c \
lt__private.h lt_dlloader.h \
lt__private.h lt_system.h \
lt__alloc.h lt__alloc.c \
lt__glibc.h lt_system.h
lt__glibc.h \
slist.h slist.c
libdlloader_la_LDFLAGS = $(VERSION_INFO)
libdlloader_la_LIBADD = $(LTLIBOBJS)
## Libltdl brings it all together:
if INSTALL_LTDL
include_HEADERS = ltdl.h
pkginclude_HEADERS = lt_system.h lt_error.h
pkginclude_HEADERS = lt_system.h lt_error.h lt_dlloader.h
lib_LTLIBRARIES += libltdl.la
endif
@ -52,7 +53,8 @@ if CONVENIENCE_LTDL
noinst_LTLIBRARIES = libltdlc.la
endif
libltdl_la_SOURCES = ltdl.h ltdl.c loaders/preopen.c
libltdl_la_SOURCES = ltdl.h ltdl.c \
lt_dlloader.h lt_dlloader.c loaders/preopen.c
libltdl_la_CPPFLAGS = -DLTDLOPEN=libltdl $(AM_CPPFLAGS)
libltdl_la_LDFLAGS = $(VERSION_INFO) $(LT_DLPREOPEN)
libltdl_la_LIBADD = libdlloader.la

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable dld_link_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
static lt_dlvtable *vtable = 0;
if (!vtable)
{
vtable = lt__zalloc (sizeof *vtable);
}
if (!vtable->name)
if (vtable && !vtable->name)
{
vtable->name = "lt_dld_link";
vtable->module_open = vm_open;
@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data)
vtable->priority = LT_DLLOADER_APPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable dlopen_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
static lt_dlvtable *vtable = 0;
if (!vtable)
{
vtable = lt__zalloc (sizeof *vtable);
}
if (!vtable->name)
if (vtable && !vtable->name)
{
vtable->name = "lt_dlopen";
#if defined(NEED_USCORE)
@ -72,7 +72,7 @@ get_vtable (lt_user_data loader_data)
vtable->priority = LT_DLLOADER_PREPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable dyld_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -51,17 +51,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
static lt_dlvtable *vtable = 0;
if (!vtable)
{
vtable = lt__zalloc (sizeof *vtable);
}
if (!vtable->name)
if (vtable && !vtable->name)
{
vtable->name = "lt_dyld";
vtable->sym_prefix = "_";
@ -73,7 +73,7 @@ get_vtable (lt_user_data loader_data)
vtable->priority = LT_DLLOADER_APPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable load_add_on_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
static lt_dlvtable *vtable = 0;
if (!vtable)
{
vtable = lt__zalloc (sizeof *vtable);
}
if (!vtable->name)
if (vtable && !vtable->name)
{
vtable->name = "lt_load_add_on";
vtable->module_open = vm_open;
@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data)
vtable->priority = LT_DLLOADER_APPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable loadlibrary_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -49,7 +49,7 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
@ -59,7 +59,7 @@ get_vtable (lt_user_data loader_data)
vtable = lt__zalloc (sizeof *vtable);
}
if (!vtable->name)
if (vtable && !vtable->name)
{
vtable->name = "lt_loadlibrary";
vtable->module_open = vm_open;
@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data)
vtable->priority = LT_DLLOADER_APPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable preopen_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -51,30 +51,30 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
static lt_dlvtable *vtable = 0;
if (!vtable)
{
vtable = lt__malloc (sizeof *vtable);
}
if (!vtable->name)
if (vtable && !vtable->name)
{
vtable->name = "lt_preopen";
vtable->sym_prefix = 0;
vtable->dlloader_init = vl_init;
vtable->dlloader_exit = vl_exit;
vtable->module_open = vm_open;
vtable->module_close = vm_close;
vtable->find_sym = vm_sym;
vtable->dlloader_init = vl_init;
vtable->dlloader_exit = vl_exit;
vtable->dlloader_data = loader_data;
vtable->priority = LT_DLLOADER_PREPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
be fetched from the preloaded symbol list by lt_dlsym(): */
#define get_vtable shl_load_LTX_get_vtable
extern lt_dlloader *get_vtable (lt_user_data loader_data);
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
/* Boilerplate code to set up the vtable for hooking this loader into
@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module,
/* Return the vtable for this loader, only the name and sym_prefix
attributes (plus the virtual function implementations, obviously)
change between loaders. */
lt_dlloader *
lt_dlvtable *
get_vtable (lt_user_data loader_data)
{
static lt_dlloader *vtable = 0;
static lt_dlvtable *vtable = 0;
if (!vtable)
{
vtable = lt__zalloc (sizeof *vtable);
}
if (!vtable->name)
if (table && !vtable->name)
{
vtable->name = "lt_shl_load";
vtable->module_open = vm_open;
@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data)
vtable->priority = LT_DLLOADER_APPEND;
}
if (vtable->dlloader_data != loader_data)
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;

View File

@ -58,6 +58,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
#include "lt__alloc.h"
#include "lt__dirent.h"
#include "lt__glibc.h"
#include "slist.h"
/* ...and all exported interfaces. */
#include "ltdl.h"
@ -79,7 +80,7 @@ LT_BEGIN_C_DECLS
extern int errno;
#endif
void lt__alloc_die_callback (void);
LT_SCOPE void lt__alloc_die_callback (void);
/* For readability: */
@ -98,13 +99,13 @@ typedef struct {
struct lt_dlhandle_struct {
struct lt_dlhandle_struct *next;
lt_dlloader *loader; /* dlopening interface */
const lt_dlvtable * vtable; /* dlopening interface */
lt_dlinfo info; /* user visible fields */
int depcount; /* number of dependencies */
lt_dlhandle *deplibs; /* dependencies */
lt_dlhandle * deplibs; /* dependencies */
lt_module module; /* system module handle */
void * system; /* system specific data */
lt_caller_data *caller_data; /* per caller associated data */
lt_caller_data * caller_data; /* per caller associated data */
int flags; /* various boolean stats */
};

156
libltdl/lt_dlloader.c Normal file
View File

@ -0,0 +1,156 @@
/* lt_dlloader.c -- dynamic library loader interface
Copyright (C) 2004 Free Software Foundation, Inc.
Originally by Gary V. Vaughan <gary@gnu.org>
NOTE: The canonical source of this file is maintained with the
GNU Libtool package. Report bugs to bug-libtool@gnu.org.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 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 that
is built using GNU libtool, you may include it under the same
distribution terms that you use for the rest of that program.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include "lt_dlloader.h"
#include "lt__private.h"
#define RETURN_SUCCESS 0
#define RETURN_FAILURE 1
static void * loader_cmp (const SList *node, const void *userdata);
/* A list of all the dlloaders we know about, each stored in the
USERDATA field of an SList node: */
static SList *loaders = 0;
/* Return NULL, unless the loader in this NODE has a matching name,
in which case we return the vtable from matching node so that its
address is passed back out (for possible freeing) by slist_remove. */
static void *
loader_cmp (const SList *node, const void *userdata)
{
const lt_dlvtable *vtable = node->userdata;
const char * name = userdata;
assert (vtable);
return streq (vtable->name, name) ? (void *) vtable : 0;
}
/* Hook VTABLE into our global LOADERS list according to its own
PRIORITY field value. */
int
lt_dlloader_add (const lt_dlvtable *vtable)
{
if ((vtable == 0) /* diagnose null parameters */
|| (vtable->module_open == 0)
|| (vtable->module_close == 0)
|| (vtable->find_sym == 0))
{
LT__SETERROR (INVALID_LOADER);
return RETURN_FAILURE;
}
switch (vtable->priority)
{
case LT_DLLOADER_PREPEND:
loaders = slist_cons (slist_new (vtable), loaders);
break;
case LT_DLLOADER_APPEND:
loaders = slist_concat (loaders, slist_new (vtable));
break;
default:
LT__SETERROR (INVALID_LOADER);
return RETURN_FAILURE;
/*NOTREACHED*/
}
return RETURN_SUCCESS;
}
/* An iterator for the global loader list: if LOADER is NULL, then
return the first element, otherwise the following element. */
lt_dlloader
lt_dlloader_next (lt_dlloader loader)
{
SList *node = (SList *) loader;
return (lt_dlloader) (node ? node->next : loaders);
}
const lt_dlvtable *
lt_dlloader_get (lt_dlloader loader)
{
return ((SList *) loader)->userdata;
}
/* Return the contents of the first item in the global loader list
with a matching NAME after removing it from that list. If there
was no match, return NULL; if there is an error, return NULL and
set an error for lt_dlerror; in either case the loader list is
not changed. */
const lt_dlvtable *
lt_dlloader_remove (const char *name)
{
const lt_dlvtable * vtable = lt_dlloader_find (name);
lt_dlhandle handle = 0;
int errors = 0;
if (!vtable)
{
LT__SETERROR (INVALID_LOADER);
return 0;
}
/* Fail if there are any open modules which use this loader. */
while (handle = lt_dlhandle_next (handle))
{
if (handle->vtable == vtable)
{
LT__SETERROR (REMOVE_LOADER);
return 0;
}
}
/* Call the loader finalisation function. */
if (vtable && vtable->dlloader_exit)
{
if (vtable->dlloader_exit (vtable->dlloader_data) != 0)
{
/* If there is an exit function, and it returns non-zero
then it must set an error, and we will not remove it
from the list. */
return 0;
}
}
/* If we got this far, remove the loader from our global list. */
return slist_remove (&loaders, name, loader_cmp);
}
const lt_dlvtable *
lt_dlloader_find (const char *name)
{
return slist_find (loaders, name, loader_cmp);
}

View File

@ -31,26 +31,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
#define LT_DLLOADER_H 1
#include <libltdl/lt_system.h>
#include <libltdl/lt_error.h>
LT_BEGIN_C_DECLS
typedef struct lt_dlloader lt_dlloader;
typedef void * lt_user_data;
typedef void * lt_module;
/* Type of a function to get a loader's vtable: */
typedef lt_dlloader *lt_get_vtable (lt_user_data loader_data);
typedef void * lt_dlloader;
typedef void * lt_module;
typedef void * lt_user_data;
/* Function pointer types for module loader vtable entries: */
typedef int lt_dlloader_init (lt_user_data loader_data);
typedef int lt_dlloader_exit (lt_user_data loader_data);
typedef lt_module lt_module_open (lt_user_data loader_data,
typedef lt_module lt_module_open (lt_user_data data,
const char *filename);
typedef int lt_module_close (lt_user_data loader_data,
lt_module handle);
typedef void * lt_find_sym (lt_user_data loader_data,
lt_module handle, const char *symbol);
typedef int lt_module_close (lt_user_data data,
lt_module module);
typedef void * lt_find_sym (lt_user_data data, lt_module module,
const char *symbolname);
typedef int lt_dlloader_init (lt_user_data data);
typedef int lt_dlloader_exit (lt_user_data data);
/* Default priority is LT_DLLOADER_PREPEND if none is explicitly given. */
typedef enum {
@ -59,8 +55,7 @@ typedef enum {
/* This structure defines a module loader, as populated by the get_vtable
entry point of each loader. */
struct lt_dlloader {
lt_dlloader * next;
typedef struct {
const char * name;
const char * sym_prefix;
lt_module_open * module_open;
@ -70,22 +65,18 @@ struct lt_dlloader {
lt_dlloader_exit * dlloader_exit;
lt_user_data dlloader_data;
lt_dlloader_priority priority;
};
} lt_dlvtable;
LT_SCOPE lt_dlloader * lt_dlloader_next (lt_dlloader *place);
LT_SCOPE lt_dlloader * lt_dlloader_find (const char *name);
LT_SCOPE const char * lt_dlloader_name (lt_dlloader *place);
LT_SCOPE lt_user_data * lt_dlloader_data (lt_dlloader *place);
LT_SCOPE int lt_dlloader_add (lt_dlloader *dlloader,
lt_user_data data);
LT_SCOPE int lt_dlloader_remove (const char *name);
LT_SCOPE int lt_dlloader_add (const lt_dlvtable *vtable);
LT_SCOPE lt_dlloader lt_dlloader_next (const lt_dlloader loader);
LT_SCOPE const lt_dlvtable *lt_dlloader_remove (const char *name);
LT_SCOPE const lt_dlvtable *lt_dlloader_find (const char *name);
LT_SCOPE const lt_dlvtable *lt_dlloader_get (lt_dlloader loader);
/* --- Backwards source compatibility --- */
#define lt_user_dlloader lt_dlloader
/* Type of a function to get a loader's vtable: */
typedef const lt_dlvtable *lt_get_vtable (lt_user_data data);
LT_END_C_DECLS

View File

@ -58,7 +58,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
/* Various boolean flags can be stored in the flags field of an
lt_dlhandle_struct... */
lt_dlhandle... */
#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
@ -135,7 +135,6 @@ static int loader_init (lt_get_vtable *vtable_func,
lt_user_data data);
static char *user_search_path= 0;
static lt_dlloader *loaders = 0;
static lt_dlhandle handles = 0;
static int initialized = 0;
@ -160,7 +159,7 @@ loader_init_callback (lt_dlhandle handle)
static int
loader_init (lt_get_vtable *vtable_func, lt_user_data data)
{
lt_dlloader *vtable = 0;
const lt_dlvtable *vtable = 0;
int errors = 0;
if (vtable_func)
@ -176,7 +175,7 @@ loader_init (lt_get_vtable *vtable_func, lt_user_data data)
if (!errors)
{
if (lt_dlloader_add (vtable, data))
if (lt_dlloader_add (vtable))
{
LT__SETERROR (DLOPEN_NOT_SUPPORTED);
++errors;
@ -199,14 +198,14 @@ loader_init (lt_get_vtable *vtable_func, lt_user_data data)
#define get_vtable preopen_LTX_get_vtable
#define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
extern lt_dlloader * get_vtable (lt_user_data data);
extern lt_dlsymlist preloaded_symbols;
LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data);
LT_SCOPE lt_dlsymlist preloaded_symbols;
/* Initialize libltdl. */
int
lt_dlinit (void)
{
int errors = 0;
int errors = 0;
/* Initialize only at first call. */
if (++initialized == 1)
@ -221,11 +220,12 @@ lt_dlinit (void)
errors += loader_init (get_vtable, 0);
/* Now open all the preloaded module loaders, so the application
can use them to lt_dlopen their own modules. */
can use _them_ to lt_dlopen its own modules. */
if (!errors)
{
errors += lt_dlpreload (&preloaded_symbols);
}
if (!errors)
{
errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
@ -239,11 +239,9 @@ int
lt_dlexit (void)
{
/* shut down libltdl */
lt_dlloader *loader;
lt_dlloader *loader = 0;
int errors = 0;
loader = loaders;
if (!initialized)
{
LT__SETERROR (SHUTDOWN);
@ -287,18 +285,19 @@ lt_dlexit (void)
}
/* close all loaders */
while (loader)
while (loader = lt_dlloader_next (loader))
{
lt_dlloader *next = loader->next;
lt_user_data data = loader->dlloader_data;
if (loader->dlloader_exit && loader->dlloader_exit (data))
const lt_dlvtable *vtable = lt_dlloader_get (loader);
if ((vtable = lt_dlloader_remove (vtable->name)))
{
FREE ((void *) vtable);
}
else
{
++errors;
}
MEMREASSIGN (loader, next);
}
loaders = 0;
}
done:
@ -306,44 +305,33 @@ lt_dlexit (void)
}
static int
tryall_dlopen (lt_dlhandle *handle, const char *filename)
tryall_dlopen (lt_dlhandle *phandle, const char *filename)
{
lt_dlhandle cur;
lt_dlloader *loader;
const char *saved_error;
int errors = 0;
lt_dlhandle handle = 0;
const char * saved_error = 0;
int errors = 0;
LT__GETERROR (saved_error);
cur = handles;
loader = loaders;
/* check whether the module was already opened */
while (cur)
while (handle = lt_dlhandle_next (handle))
{
/* try to dlopen the program itself? */
if (!cur->info.filename && !filename)
if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
|| (handle->info.filename && filename
&& streq (handle->info.filename, filename)))
{
break;
}
if (cur->info.filename && filename
&& streq (cur->info.filename, filename))
{
break;
}
cur = cur->next;
}
if (cur)
if (handle)
{
++cur->info.ref_count;
*handle = cur;
++handle->info.ref_count;
*phandle = handle;
goto done;
}
cur = *handle;
handle = *phandle;
if (filename)
{
/* Comment out the check of file permissions using access.
@ -358,8 +346,8 @@ tryall_dlopen (lt_dlhandle *handle, const char *filename)
goto done;
} */
cur->info.filename = lt__strdup (filename);
if (!cur->info.filename)
handle->info.filename = lt__strdup (filename);
if (!handle->info.filename)
{
++errors;
goto done;
@ -367,36 +355,41 @@ tryall_dlopen (lt_dlhandle *handle, const char *filename)
}
else
{
cur->info.filename = 0;
handle->info.filename = 0;
}
while (loader)
{
lt_user_data data = loader->dlloader_data;
{
const lt_dlvtable *vtable = 0;
lt_dlloader *loader = 0;
cur->module = loader->module_open (data, filename);
while (loader = lt_dlloader_next (loader))
{
vtable = lt_dlloader_get (loader);
handle->module = vtable->module_open (vtable->dlloader_data, filename);
if (cur->module != 0)
{
break;
}
loader = loader->next;
}
if (handle->module != 0)
{
break;
}
}
if (!loader)
{
FREE (cur->info.filename);
++errors;
goto done;
}
if (!loader)
{
FREE (handle->info.filename);
++errors;
goto done;
}
handle->vtable = vtable;
}
cur->loader = loader;
LT__SETERRORSTR (saved_error);
done:
return errors;
}
static int
tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
const char *dirname, const char *dlname)
@ -1673,7 +1666,7 @@ lt_dlclose (lt_dlhandle handle)
moment). */
if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
{
lt_user_data data = handle->loader->dlloader_data;
lt_user_data data = handle->vtable->dlloader_data;
if (handle != handles)
{
@ -1684,7 +1677,7 @@ lt_dlclose (lt_dlhandle handle)
handles = handle->next;
}
errors += handle->loader->module_close (data, handle->module);
errors += handle->vtable->module_close (data, handle->module);
errors += unload_deplibs(handle);
/* It is up to the callers to free the data itself. */
@ -1728,7 +1721,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol)
return 0;
}
lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
+ LT_STRLEN (handle->info.name);
if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
@ -1745,7 +1738,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol)
}
}
data = handle->loader->dlloader_data;
data = handle->vtable->dlloader_data;
if (handle->info.name)
{
const char *saved_error;
@ -1753,9 +1746,9 @@ lt_dlsym (lt_dlhandle handle, const char *symbol)
LT__GETERROR (saved_error);
/* this is a libtool module */
if (handle->loader->sym_prefix)
if (handle->vtable->sym_prefix)
{
strcpy(sym, handle->loader->sym_prefix);
strcpy(sym, handle->vtable->sym_prefix);
strcat(sym, handle->info.name);
}
else
@ -1767,7 +1760,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol)
strcat(sym, symbol);
/* try "modulename_LTX_symbol" */
address = handle->loader->find_sym (data, handle->module, sym);
address = handle->vtable->find_sym (data, handle->module, sym);
if (address)
{
if (sym != lsym)
@ -1780,9 +1773,9 @@ lt_dlsym (lt_dlhandle handle, const char *symbol)
}
/* otherwise try "symbol" */
if (handle->loader->sym_prefix)
if (handle->vtable->sym_prefix)
{
strcpy(sym, handle->loader->sym_prefix);
strcpy(sym, handle->vtable->sym_prefix);
strcat(sym, symbol);
}
else
@ -1790,7 +1783,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol)
strcpy(sym, symbol);
}
address = handle->loader->find_sym (data, handle->module, sym);
address = handle->vtable->find_sym (data, handle->module, sym);
if (sym != lsym)
{
FREE (sym);
@ -1995,12 +1988,14 @@ lt_dlgetinfo (lt_dlhandle handle)
return &(handle->info);
}
lt_dlhandle
lt_dlhandle_next (lt_dlhandle place)
{
return place ? place->next : handles;
}
lt_dlhandle
lt_dlhandle_find (const char *module_name)
{
@ -2116,161 +2111,6 @@ lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle)
}
/* --- USER MODULE LOADER API --- */
int
lt_dlloader_add (lt_dlloader *dlloader, lt_user_data data)
{
int errors = 0;
lt_dlloader *ptr = 0;
if ((dlloader == 0) /* diagnose null parameters */
|| (dlloader->module_open == 0)
|| (dlloader->module_close == 0)
|| (dlloader->find_sym == 0))
{
LT__SETERROR (INVALID_LOADER);
return 1;
}
switch (dlloader->priority)
{
case LT_DLLOADER_PREPEND:
/* Tack NODE on the front of the LOADERS list. */
dlloader->next = loaders;
loaders = dlloader;
break;
case LT_DLLOADER_APPEND:
/* Add NODE to the end of the LOADERS list. */
for (ptr = loaders; ptr->next; ptr = ptr->next)
/*NOWORK*/;
ptr->next = dlloader;
break;
default:
LT__SETERROR (INVALID_LOADER);
++errors;
break;
}
return errors;
}
int
lt_dlloader_remove (const char *name)
{
lt_dlloader *place = lt_dlloader_find (name);
lt_dlhandle handle;
int errors = 0;
if (!place)
{
LT__SETERROR (INVALID_LOADER);
return 1;
}
/* Fail if there are any open modules which use this loader. */
for (handle = handles; handle; handle = handle->next)
{
if (handle->loader == place)
{
LT__SETERROR (REMOVE_LOADER);
return ++errors;
}
}
if (place == loaders)
{
/* PLACE is the first loader in the list. */
loaders = loaders->next;
}
else
{
/* Find the loader before the one being removed. */
lt_dlloader *prev;
for (prev = loaders; prev->next; prev = prev->next)
{
if (streq (prev->next->name, name))
{
break;
}
}
place = prev->next;
prev->next = prev->next->next;
}
if (place->dlloader_exit)
{
errors = place->dlloader_exit (place->dlloader_data);
}
FREE (place);
return errors;
}
lt_dlloader *
lt_dlloader_next (lt_dlloader *place)
{
return place ? place->next : loaders;
}
const char *
lt_dlloader_name (lt_dlloader *place)
{
const char *name = 0;
if (place)
{
name = place ? place->name : 0;
}
else
{
LT__SETERROR (INVALID_LOADER);
}
return name;
}
lt_user_data *
lt_dlloader_data (lt_dlloader *place)
{
lt_user_data *data = 0;
if (place)
{
data = place ? &(place->dlloader_data) : 0;
}
else
{
LT__SETERROR (INVALID_LOADER);
}
return data;
}
lt_dlloader *
lt_dlloader_find (const char *name)
{
lt_dlloader *place = 0;
for (place = loaders; place; place = place->next)
{
if (streq (place->name, name))
{
break;
}
}
return place;
}
/* These symbols are part of the published interface to libltdl,
although they are no longer used. */

View File

@ -153,7 +153,7 @@ LT_SCOPE int lt_dlmutex_register (lt_dlmutex_lock *lock,
lt_dlmutex_seterror *seterror,
lt_dlmutex_geterror *geterror);
# define lt_ptr void *
# define lt_ptr void *

206
libltdl/slist.c Normal file
View File

@ -0,0 +1,206 @@
/* slist.h -- generalised singly linked lists
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
Originally by Gary V. Vaughan <gary@gnu.org>
NOTE: The canonical source of this file is maintained with the
GNU Libtool package. Report bugs to bug-libtool@gnu.org.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 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 that
is built using GNU libtool, you may include it under the same
distribution terms that you use for the rest of that program.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include <assert.h>
#include "slist.h"
SList *
slist_new (const void *userdata)
{
SList *node = malloc (sizeof *node);
node->next = 0;
node->userdata = userdata;
return node;
}
SList *
slist_delete (SList *head, void (*delete) (void *data))
{
assert (delete);
while (head)
{
SList *next = head->next;
(*delete) (head);
head = next;
}
return 0;
}
/* Call Find repeatedly with MATCH and each element of *PHEAD, until
FIND returns non-NULL, or the list is exhausted. If a match is found
the matching element is removed from *PHEAD, and the value returned
by the matching call to FIND is returned.
To avoid memory leaks, unless you already have the address of the
stale element, you should probably return that from FIND if it makes
a successful match. */
void *
slist_remove (SList **phead, const void *match, SListCompare *find)
{
SList *stale = 0;
void *result = 0;
assert (find);
if (!phead || !*phead)
return 0;
/* Does the head of the passed list match? */
result = (*find) (*phead, match);
if (result)
{
stale = *phead;
*phead = stale->next;
}
/* what about the rest of the elements? */
else
{
SList *head;
for (head = *phead; head->next; head = head->next)
{
result = (*find) (head->next, match);
if (result)
{
stale = head->next;
head->next = stale->next;
}
}
}
return result;
}
SList *
slist_concat (SList *head, SList *tail)
{
if (!head)
{
return tail;
}
while (head->next)
head = head->next;
head->next = tail;
return head;
}
SList *
slist_cons (SList *head, SList *tail)
{
if (!head)
{
return tail;
}
head->next = tail;
return head;
}
SList *
slist_tail (SList *head)
{
return head ? head->next : 0;
}
SList *
slist_nth (SList *head, size_t n)
{
for (;n > 1 && head; n--)
head = head->next;
return head;
}
/* Call FIND repeatedly with SEARCH and each element of HEAD, until
FIND returns non-NULL, or the list is exhausted. If a match is found
the value returned by the matching call to FIND is returned. */
void *
slist_find (SList *head, const void *match, SListCompare *find)
{
void *result = 0;
assert (find);
for (; head; head = head->next)
{
result = (*find) (head, match);
if (result)
break;
}
return result;
}
size_t
slist_length (SList *head)
{
size_t n;
for (n = 0; head; ++n)
head = head->next;
return n;
}
SList *
slist_reverse (SList *head)
{
SList *result = 0;
SList *next;
while (head)
{
next = head->next;
head->next = result;
result = head;
head = next;
}
return result;
}
int
slist_foreach (SList *head, SListCallback *foreach, const void *userdata)
{
assert (foreach);
for (; head; head = head->next)
if ((*foreach) (head, userdata) < 0)
return -1;
return 0;
}

73
libltdl/slist.h Normal file
View File

@ -0,0 +1,73 @@
/* slist.h -- generalised singly linked lists
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
Originally by Gary V. Vaughan <gary@gnu.org>
NOTE: The canonical source of this file is maintained with the
GNU Libtool package. Report bugs to bug-libtool@gnu.org.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 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 that
is built using GNU libtool, you may include it under the same
distribution terms that you use for the rest of that program.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
/* A generalised list. This is deliberately transparent so that you
can make the NEXT field of all your chained data structures first,
and then cast them to `(SList *)' so that they can be manipulated
by this API.
Alternatively, you can generate raw SList elements using slist_new(),
and put the element data in the USERDATA field. Either way you
get to manage the memory involved by yourself.
*/
#if !defined(SLIST_H)
#define SLIST_H 1
#include <libltdl/lt_system.h>
LT_BEGIN_C_DECLS
typedef struct slist {
struct slist *next; /* chain forward pointer*/
const void * userdata; /* incase you want to use raw `SList's */
} SList;
typedef void * SListCompare (const SList *node, const void *userdata);
typedef int SListCallback (const SList *node, const *userdata);
LT_SCOPE SList *slist_new (const void *userdata);
LT_SCOPE SList *slist_delete (SList *head, void (*delete) (void *data));
LT_SCOPE void * slist_remove (SList **phead, const void *match,
SListCompare *find);
LT_SCOPE SList *slist_concat (SList *head, SList *tail);
LT_SCOPE SList *slist_cons (SList *head, SList *tail);
LT_SCOPE SList *slist_tail (SList *head);
LT_SCOPE SList *slist_nth (SList *head, size_t n);
LT_SCOPE void * slist_find (SList *head, const void *match,
SListCompare *find);
LT_SCOPE size_t slist_length (SList *head);
LT_SCOPE SList *slist_reverse (SList *head);
LT_SCOPE int slist_foreach (SList *head, SListCallback *foreach,
const void *userdata);
LT_END_C_DECLS
#endif /*!defined(SLIST_H)*/