* MT safe
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include "gmodule.h"
-#include "gmoduleconf.h"
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include "config.h"
+
+#include "glib.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#ifdef HAVE_UNISTD_H
-# include <unistd.h>
+#include <unistd.h>
#endif
-#if defined (G_OS_WIN32)
-# include <io.h> /* For open() and close() prototypes. */
+#ifdef G_OS_WIN32
+#include <io.h> /* For open() and close() prototypes. */
#endif
+#include "gmoduleconf.h"
+#include "gstdio.h"
+#include "gmodule.h"
+
/* We maintain a list of modules, so we can reference count them.
* That's needed because some platforms don't support refernce counts on
* modules e.g. the shl_* implementation of HP-UX
struct _GModule
{
gchar *file_name;
+#if defined (G_OS_WIN32) && !defined(_WIN64)
+ gchar *cp_file_name;
+#endif
gpointer handle;
guint ref_count : 31;
guint is_resident : 1;
/* --- prototypes --- */
static gpointer _g_module_open (const gchar *file_name,
- gboolean bind_lazy);
+ gboolean bind_lazy,
+ gboolean bind_local);
static void _g_module_close (gpointer handle,
gboolean is_unref);
static gpointer _g_module_self (void);
static GModule *modules = NULL;
static GModule *main_module = NULL;
static GStaticPrivate module_error_private = G_STATIC_PRIVATE_INIT;
+static gboolean module_debug_initialized = FALSE;
+static guint module_debug_flags = 0;
/* --- inline functions --- */
#include "gmodule-win32.c"
#elif (G_MODULE_IMPL == G_MODULE_IMPL_DYLD)
#include "gmodule-dyld.c"
+#elif (G_MODULE_IMPL == G_MODULE_IMPL_AR)
+#include "gmodule-ar.c"
#else
#undef SUPPORT_OR_RETURN
#define SUPPORT_OR_RETURN(rv) { g_module_set_error ("dynamic modules are " \
"not supported by this system"); return rv; }
static gpointer
_g_module_open (const gchar *file_name,
- gboolean bind_lazy)
+ gboolean bind_lazy,
+ gboolean bind_local)
{
return NULL;
}
static gchar*
parse_libtool_archive (const gchar* libtool_name)
{
- const gint TOKEN_DLNAME = G_TOKEN_LAST + 1;
- const gint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
- const gint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
+ const guint TOKEN_DLNAME = G_TOKEN_LAST + 1;
+ const guint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
+ const guint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
gchar *lt_dlname = NULL;
gboolean lt_installed = TRUE;
gchar *lt_libdir = NULL;
GTokenType token;
GScanner *scanner;
- int fd = open (libtool_name, O_RDONLY, 0);
+ int fd = g_open (libtool_name, O_RDONLY, 0);
if (fd < 0)
{
- g_module_set_error_unduped (g_strdup_printf ("failed to open libtool archive \"%s\"", libtool_name));
+ gchar *display_libtool_name = g_filename_display_name (libtool_name);
+ g_module_set_error_unduped (g_strdup_printf ("failed to open libtool archive \"%s\"", display_libtool_name));
+ g_free (display_libtool_name);
return NULL;
}
/* search libtool's dlname specification */
(token == TOKEN_INSTALLED ?
G_TOKEN_IDENTIFIER : G_TOKEN_STRING))
{
- g_module_set_error_unduped (g_strdup_printf ("unable to parse libtool archive \"%s\"", libtool_name));
+ gchar *display_libtool_name = g_filename_display_name (libtool_name);
+ g_module_set_error_unduped (g_strdup_printf ("unable to parse libtool archive \"%s\"", display_libtool_name));
+ g_free (display_libtool_name);
g_free (lt_dlname);
g_free (lt_libdir);
strcmp (string + string_len - suffix_len, suffix) == 0;
}
+enum
+{
+ G_MODULE_DEBUG_RESIDENT_MODULES = 1 << 0,
+ G_MODULE_DEBUG_BIND_NOW_MODULES = 1 << 1
+};
+
+static void
+_g_module_debug_init (void)
+{
+ const GDebugKey keys[] = {
+ { "resident-modules", G_MODULE_DEBUG_RESIDENT_MODULES },
+ { "bind-now-modules", G_MODULE_DEBUG_BIND_NOW_MODULES }
+ };
+ const gchar *env;
+
+ env = g_getenv ("G_DEBUG");
+
+ module_debug_flags =
+ !env ? 0 : g_parse_debug_string (env, keys, G_N_ELEMENTS (keys));
+
+ module_debug_initialized = TRUE;
+}
+
static GStaticRecMutex g_module_global_lock = G_STATIC_REC_MUTEX_INIT;
GModule*
SUPPORT_OR_RETURN (NULL);
g_static_rec_mutex_lock (&g_module_global_lock);
+
+ if (G_UNLIKELY (!module_debug_initialized))
+ _g_module_debug_init ();
+
+ if (module_debug_flags & G_MODULE_DEBUG_BIND_NOW_MODULES)
+ flags &= ~G_MODULE_BIND_LAZY;
+
if (!file_name)
{
if (!main_module)
{
main_module = g_new (GModule, 1);
main_module->file_name = NULL;
+#if defined (G_OS_WIN32) && !defined(_WIN64)
+ main_module->cp_file_name = NULL;
+#endif
main_module->handle = handle;
main_module->ref_count = 1;
main_module->is_resident = TRUE;
main_module->next = NULL;
}
}
+ else
+ main_module->ref_count++;
g_static_rec_mutex_unlock (&g_module_global_lock);
return main_module;
}
/* check whether we have a readable file right away */
- if (g_file_test (file_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+ if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
name = g_strdup (file_name);
/* try completing file name with standard library suffix */
if (!name)
{
name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
- if (!g_file_test (file_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+ if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
{
g_free (name);
name = NULL;
if (!name)
{
name = g_strconcat (file_name, ".la", NULL);
- if (!g_file_test (name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+ if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
{
g_free (name);
name = NULL;
gchar *real_name = parse_libtool_archive (name);
/* real_name might be NULL, but then module error is already set */
- g_free (name);
- name = real_name;
+ if (real_name)
+ {
+ g_free (name);
+ name = real_name;
+ }
}
if (name)
- handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+ handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0,
+ (flags & G_MODULE_BIND_LOCAL) != 0);
}
else
- g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", file_name));
+ {
+ gchar *display_file_name = g_filename_display_name (file_name);
+ g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", display_file_name));
+ g_free (display_file_name);
+ }
g_free (name);
if (handle)
module = g_new (GModule, 1);
module->file_name = g_strdup (file_name);
+#if defined (G_OS_WIN32) && !defined(_WIN64)
+ module->cp_file_name = g_locale_from_utf8 (file_name, -1,
+ NULL, NULL, NULL);
+#endif
module->handle = handle;
module->ref_count = 1;
module->is_resident = FALSE;
modules = module;
/* check initialization */
- if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
+ if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init) && check_init != NULL)
check_failed = check_init (module);
/* we don't call unload() if the initialization check failed. */
{
gchar *error;
- error = g_strconcat ("GModule initialization check failed: ", check_failed, NULL);
+ error = g_strconcat ("GModule (",
+ file_name ? file_name : "NULL",
+ ") initialization check failed: ",
+ check_failed, NULL);
g_module_close (module);
module = NULL;
g_module_set_error (error);
g_free (saved_error);
}
+ if (module != NULL &&
+ (module_debug_flags & G_MODULE_DEBUG_RESIDENT_MODULES))
+ g_module_make_resident (module);
+
g_static_rec_mutex_unlock (&g_module_global_lock);
return module;
}
+#if defined (G_OS_WIN32) && !defined(_WIN64)
+
+#undef g_module_open
+
+GModule*
+g_module_open (const gchar *file_name,
+ GModuleFlags flags)
+{
+ gchar *utf8_file_name = g_locale_to_utf8 (file_name, -1, NULL, NULL, NULL);
+ GModule *retval = g_module_open_utf8 (utf8_file_name, flags);
+
+ g_free (utf8_file_name);
+
+ return retval;
+}
+
+#endif
+
gboolean
g_module_close (GModule *module)
{
_g_module_close (module->handle, FALSE);
g_free (module->file_name);
-
+#if defined (G_OS_WIN32) && !defined(_WIN64)
+ g_free (module->cp_file_name);
+#endif
g_free (module);
}
return module->file_name;
}
+#if defined (G_OS_WIN32) && !defined(_WIN64)
+
+#undef g_module_name
+
+G_CONST_RETURN gchar*
+g_module_name (GModule *module)
+{
+ g_return_val_if_fail (module != NULL, NULL);
+
+ if (module == main_module)
+ return "main";
+
+ return module->cp_file_name;
+}
+
+#endif
+
gchar*
g_module_build_path (const gchar *directory,
const gchar *module_name)