diff --git a/libgphoto2_port/ChangeLog b/libgphoto2_port/ChangeLog index 9207eee2e..c061a53e0 100644 --- a/libgphoto2_port/ChangeLog +++ b/libgphoto2_port/ChangeLog @@ -1,3 +1,8 @@ +2001-12-13 Lutz Müller + + * configure.in: Check if ltdl.h is available and ... + * libgphoto2_port: ... use it. + 2001-12-12 Lutz Müller Remove some error codes, and move some variable names into the diff --git a/libgphoto2_port/acconfig.h b/libgphoto2_port/acconfig.h index e88461ee7..2bf0c3400 100644 --- a/libgphoto2_port/acconfig.h +++ b/libgphoto2_port/acconfig.h @@ -22,3 +22,5 @@ #undef HAVE_LOCKDEV #undef HAVE_GNU_REGEX + +#undef HAVE_LTDL diff --git a/libgphoto2_port/configure.in b/libgphoto2_port/configure.in index 1a534e1d7..05212c598 100644 --- a/libgphoto2_port/configure.in +++ b/libgphoto2_port/configure.in @@ -24,7 +24,6 @@ AC_LIBTOOL_DLOPEN dnl Checks for programs. AC_PROG_CC AC_PROG_CPP -AM_PROG_LIBTOOL AC_PROG_INSTALL dnl The following is a hack to get gphoto2 to build on gettext-0.10.35 @@ -35,10 +34,39 @@ AC_SUBST(BUILD_INCLUDED_LIBINTL) dnl USE_INCLUDED_LIBINTL=no dnl AC_SUBST(USE_INCLUDED_LIBINTL) -dnl Languages +dnl --------------------------------------------------------------------------- +dnl i18n support +dnl --------------------------------------------------------------------------- ALL_LINGUAS="de" AM_GNU_GETTEXT +dnl --------------------------------------------------------------------------- +dnl Check for libtool: lt_dlforeachfile has been introduced in +dnl libtool-1.4. However, there are still systems out +dnl there running libtool-1.3. For those, we will need +dnl dlopen. Note that on some systems (e.g. FreeBSD) +dnl -ldl isn't needed. +dnl --------------------------------------------------------------------------- +AM_PROG_LIBTOOL +no_libtool=true +AC_CHECK_LIB(ltdl, lt_dlforeachfile, + AC_CHECK_HEADER(ltdl.h, + AC_DEFINE(HAVE_LTDL) + LTDL_LIBS="-lltdl" + no_libtool=false + ) +) +if $no_libtool; then + AC_CHECK_FUNC(dlopen,, + AC_CHECK_LIB(dl, dlopen, + LTDL_LIBS="-ldl", + AC_ERROR([ +*** Could not determine how to handle +*** shared libraries! +]))) +fi +AC_SUBST(LTDL_LIBS) + AC_CHECK_FUNC(gettext, gettext_without_libintl=true) # same trick as with libdl in libgphoto2: # if gettext() doesn't require linking against libintl, diff --git a/libgphoto2_port/libgphoto2_port/Makefile.am b/libgphoto2_port/libgphoto2_port/Makefile.am index 0571ed764..cab9bf15f 100644 --- a/libgphoto2_port/libgphoto2_port/Makefile.am +++ b/libgphoto2_port/libgphoto2_port/Makefile.am @@ -9,7 +9,7 @@ LDFLAGS = @LDFLAGS@ -g ## Compile the IO library into a shared library lib_LTLIBRARIES = libgphoto2_port.la libgphoto2_port_la_LDFLAGS = -version-info @LIBGPPORT_VERSION_INFO@ -libgphoto2_port_la_LIBADD = -ldl $(INTLLIBS) +libgphoto2_port_la_LIBADD = $(LTDL_LIBS) $(INTLLIBS) libgphoto2_port_la_SOURCES = \ gphoto2-port-info-list.c \ gphoto2-port-log.c \ diff --git a/libgphoto2_port/libgphoto2_port/gphoto2-port-info-list.c b/libgphoto2_port/libgphoto2_port/gphoto2-port-info-list.c index 56adf058d..90d026e20 100644 --- a/libgphoto2_port/libgphoto2_port/gphoto2-port-info-list.c +++ b/libgphoto2_port/libgphoto2_port/gphoto2-port-info-list.c @@ -26,6 +26,10 @@ #include #include +#if HAVE_LTDL +#include +#endif + #include #include #include @@ -81,6 +85,10 @@ gp_port_info_list_new (GPPortInfoList **list) return (GP_ERROR_NO_MEMORY); memset (*list, 0, sizeof (GPPortInfoList)); +#ifdef HAVE_LTDL + lt_dlinit (); +#endif + return (GP_OK); } @@ -103,6 +111,10 @@ gp_port_info_list_free (GPPortInfoList *list) } list->count = 0; +#ifdef HAVE_LTDL + lt_dlexit (); +#endif + return (GP_OK); } @@ -147,6 +159,32 @@ gp_port_info_list_append (GPPortInfoList *list, GPPortInfo info) return (list->count - 1 - generic); } +#ifdef HAVE_LTDL + +#define MAX_COUNT 8 +typedef struct _LibrariesList LibrariesList; +struct _LibrariesList { + unsigned int count; + char path[MAX_COUNT][1024]; +}; + +static int +foreach_func (const char *filename, lt_ptr data) +{ + LibrariesList *list = data; + + if (list->count >= MAX_COUNT) + return (GP_ERROR_NO_MEMORY); + + strncpy (list->path[list->count], filename, + sizeof (list->path[list->count])); + list->count++; + + return (0); +} + +#endif + /** * gp_port_info_list_load: * @list: a #GPPortInfoList @@ -160,19 +198,81 @@ gp_port_info_list_append (GPPortInfoList *list, GPPortInfo info) int gp_port_info_list_load (GPPortInfoList *list) { + int i, result; + GPPortLibraryType lib_type; + GPPortLibraryList lib_list; + GPPortType type; + unsigned int old_size = list->count; +#ifdef HAVE_LTDL + LibrariesList flist; + lt_dlhandle lh; + int j; +#else GP_SYSTEM_DIR d; GP_SYSTEM_DIRENT de; char path[1024]; void *lh; - GPPortLibraryType lib_type; - GPPortLibraryList lib_list; - GPPortType type; - int i, result; - unsigned int old_size = list->count; const char *filename; +#endif CHECK_NULL (list); + gp_log (GP_LOG_DEBUG, "gp-port-info-list", "Loading io-drivers " + "from '" IOLIBS "'..."); +#ifdef HAVE_LTDL + flist.count = 0; + result = lt_dlforeachfile (IOLIBS, foreach_func, &flist); + if (result < 0) + return (result); + for (i = 0; i < flist.count; i++) { + lh = lt_dlopenext (flist.path[i]); + if (!lh) { + gp_log (GP_LOG_DEBUG, "gp-port-info-list", + "Could not load '%s': '%s'.", flist.path[i], + lt_dlerror ()); + continue; + } + + lib_type = lt_dlsym (lh, "gp_port_library_type"); + lib_list = lt_dlsym (lh, "gp_port_library_list"); + if (!lib_type || !lib_list) { + gp_log (GP_LOG_DEBUG, "gp-port-info-list", + "Could not find some functions in '%s': '%s'.", + flist.path[i], lt_dlerror ()); + lt_dlclose (lh); + continue; + } + + type = lib_type (); + for (j = 0; j < list->count; j++) + if (list->info[j].type == type) + break; + if (j != list->count) { + gp_log (GP_LOG_DEBUG, "gp-port-info-list", + "'%s' already loaded", flist.path[j]); + lt_dlclose (lh); + continue; + } + + result = lib_list (list); + lt_dlclose (lh); + if (result < 0) { + gp_log (GP_LOG_DEBUG, "gp-port-info-list", + "Could not load list: '%s'.", + gp_port_result_as_string (result)); + continue; + } + + for (j = old_size; j < list->count; j++){ + gp_log (GP_LOG_DEBUG, "gp-port-info-list", + "Loaded '%s' ('%s') from '%s'.", + list->info[j].name, list->info[j].path, + flist.path[i]); + strcpy (list->info[j].library_filename, flist.path[i]); + } + old_size = list->count; + } +#else d = GP_SYSTEM_OPENDIR (IOLIBS); if (!d) { gp_log (GP_LOG_ERROR, "gphoto2-port-core", @@ -247,6 +347,7 @@ gp_port_info_list_load (GPPortInfoList *list) } while (1); GP_SYSTEM_CLOSEDIR (d); +#endif return (GP_OK); } diff --git a/libgphoto2_port/libgphoto2_port/gphoto2-port.c b/libgphoto2_port/libgphoto2_port/gphoto2-port.c index 5e9f0abdf..6a5973754 100644 --- a/libgphoto2_port/libgphoto2_port/gphoto2-port.c +++ b/libgphoto2_port/libgphoto2_port/gphoto2-port.c @@ -28,6 +28,10 @@ #include #include +#ifdef HAVE_LTDL +#include +#endif + #include "gphoto2-port-result.h" #include "gphoto2-port-info-list.h" #include "gphoto2-port-library.h" @@ -62,7 +66,11 @@ struct _GPPortPrivateCore { GPPortInfo info; GPPortOperations *ops; +#ifdef HAVE_LTDL + lt_dlhandle lh; +#else void *lh; /* Library handle */ +#endif }; /** @@ -87,6 +95,10 @@ gp_port_new (GPPort **port) return (GP_ERROR_NO_MEMORY); memset (*port, 0, sizeof (GPPort)); +#ifdef HAVE_LTDL + lt_dlinit (); +#endif + (*port)->pc = malloc (sizeof (GPPortPrivateCore)); if (!(*port)->pc) { gp_port_free (*port); @@ -147,10 +159,19 @@ gp_port_set_info (GPPort *port, GPPortInfo info) free (port->pc->ops); port->pc->ops = NULL; } - if (port->pc->lh) + if (port->pc->lh) { +#ifdef HAVE_LTDL + lt_dlclose (port->pc->lh); +#else GP_SYSTEM_DLCLOSE (port->pc->lh); +#endif + } +#ifdef HAVE_LTDL + port->pc->lh = lt_dlopen (info.library_filename); +#else port->pc->lh = GP_SYSTEM_DLOPEN (info.library_filename); +#endif if (!port->pc->lh) { gp_log (GP_LOG_ERROR, "gphoto2-port", "Could not load " "'%s' ('%s')", info.library_filename, @@ -159,12 +180,23 @@ gp_port_set_info (GPPort *port, GPPortInfo info) } /* Load the operations */ +#ifdef HAVE_LTDL + ops_func = lt_dlsym (port->pc->lh, "gp_port_library_operations"); +#else ops_func = GP_SYSTEM_DLSYM (port->pc->lh, "gp_port_library_operations"); +#endif if (!ops_func) { +#ifdef HAVE_LTDL + gp_log (GP_LOG_ERROR, "gphoto2-port", "Could not find " + "'gp_port_library_operations' in '%s' ('%s')", + info.library_filename, lt_dlerror ()); + lt_dlclose (port->pc->lh); +#else gp_log (GP_LOG_ERROR, "gphoto2-port", "Could not find " "'gp_port_library_operations' in '%s' ('%s')", info.library_filename, GP_SYSTEM_DLERROR ()); GP_SYSTEM_DLCLOSE (port->pc->lh); +#endif port->pc->lh = NULL; return (GP_ERROR_LIBRARY); } @@ -293,7 +325,11 @@ gp_port_free (GPPort *port) } if (port->pc->lh) { +#ifdef HAVE_LTDL + lt_dlclose (port->pc->lh); +#else GP_SYSTEM_DLCLOSE (port->pc->lh); +#endif port->pc->lh = NULL; } @@ -303,6 +339,10 @@ gp_port_free (GPPort *port) free (port); +#ifdef HAVE_LTDL + lt_dlexit (); +#endif + return GP_OK; }