2.19.0
[platform/upstream/glib.git] / gmodule / gmodule.c
index 25bf18a..1ebb63e 100644 (file)
  * 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
@@ -58,6 +61,9 @@
 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;
@@ -68,7 +74,8 @@ struct _GModule
 
 /* --- 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);
@@ -85,6 +92,8 @@ static inline GModule*        g_module_find_by_name   (const gchar    *name);
 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 --- */
@@ -147,13 +156,16 @@ g_module_set_error (const gchar *error)
 #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;
 }
@@ -193,9 +205,9 @@ g_module_supported (void)
 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;
@@ -203,10 +215,12 @@ parse_libtool_archive (const gchar* libtool_name)
   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  */
@@ -230,7 +244,9 @@ parse_libtool_archive (const gchar* libtool_name)
              (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);
@@ -287,6 +303,29 @@ str_check_suffix (const gchar* string,
     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*
@@ -300,6 +339,13 @@ g_module_open (const gchar    *file_name,
   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)
@@ -309,6 +355,9 @@ g_module_open (const gchar    *file_name,
            {
              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;
@@ -316,6 +365,8 @@ g_module_open (const gchar    *file_name,
              main_module->next = NULL;
            }
        }
+      else
+       main_module->ref_count++;
 
       g_static_rec_mutex_unlock (&g_module_global_lock);
       return main_module;
@@ -332,13 +383,13 @@ g_module_open (const gchar    *file_name,
     }
 
   /* 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;
@@ -348,7 +399,7 @@ g_module_open (const gchar    *file_name,
   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;
@@ -378,14 +429,22 @@ g_module_open (const gchar    *file_name,
          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)
@@ -411,6 +470,10 @@ g_module_open (const gchar    *file_name,
       
       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;
@@ -419,7 +482,7 @@ g_module_open (const gchar    *file_name,
       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. */
@@ -430,7 +493,10 @@ g_module_open (const gchar    *file_name,
        {
          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);
@@ -442,10 +508,32 @@ g_module_open (const gchar    *file_name,
       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)
 {
@@ -492,7 +580,9 @@ 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);
     }
   
@@ -569,6 +659,23 @@ g_module_name (GModule *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)