[glib] GIOModule: Use unique names for load/unload symbols



commit 7f69b828fcf952fac9cb27da1e74b2fdffa997d0
Author: Xavier Claessens <xavier claessens collabora com>
Date:   Thu Nov 30 15:36:21 2017 -0500

    GIOModule: Use unique names for load/unload symbols
    
    GIO modules should include their name into their exported symbols to
    make them unique. This avoids symbol clash when building modules
    statically.
    
    extract_name() function is copied from GStreamer which recently
    switched to the same symbol naming scheme.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=684282

 gio/Makefile.am        |    3 +-
 gio/gio-querymodules.c |   16 ++++++++++-
 gio/giomodule-priv.c   |   69 ++++++++++++++++++++++++++++++++++++++++++++++++
 gio/giomodule-priv.h   |    3 ++
 gio/giomodule.c        |   44 ++++++++++++++++++++++++++----
 gio/giomodule.h        |   24 ++++++++++++++++
 gio/meson.build        |    3 +-
 7 files changed, 153 insertions(+), 9 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 0cfda50..9b3d04e 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -476,6 +476,7 @@ gio_base_sources =          \
        gioenums.h              \
        gioerror.c              \
        giomodule.c             \
+       giomodule-priv.c        \
        giomodule-priv.h        \
        gioscheduler.c          \
        giostream.c             \
@@ -815,7 +816,7 @@ glib_compile_resources_SOURCES = \
        gvdb/gvdb-builder.c             \
        glib-compile-resources.c
 
-gio_querymodules_SOURCES = gio-querymodules.c
+gio_querymodules_SOURCES = gio-querymodules.c giomodule-priv.c
 gio_querymodules_LDADD  = libgio-2.0.la                \
        $(top_builddir)/gobject/libgobject-2.0.la       \
        $(top_builddir)/gmodule/libgmodule-2.0.la       \
diff --git a/gio/gio-querymodules.c b/gio/gio-querymodules.c
index 7abfe07..74c6594 100644
--- a/gio/gio-querymodules.c
+++ b/gio/gio-querymodules.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include "giomodule.h"
+#include "giomodule-priv.h"
 
 #include <gstdio.h>
 #include <errno.h>
@@ -83,7 +84,20 @@ query_dir (const char *dirname)
 
       if (module)
        {
-         g_module_symbol (module, "g_io_module_query", (gpointer) &query);
+         gchar *modulename;
+         gchar *symname;
+
+         modulename = _g_io_module_extract_name (name);
+         symname = g_strconcat ("g_io_", modulename, "_query", NULL);
+         g_module_symbol (module, symname, (gpointer) &query);
+         g_free (symname);
+         g_free (modulename);
+
+         if (!query)
+           {
+             /* Fallback to old name */
+             g_module_symbol (module, "g_io_module_query", (gpointer) &query);
+           }
 
          if (query)
            {
diff --git a/gio/giomodule-priv.c b/gio/giomodule-priv.c
new file mode 100644
index 0000000..41afa54
--- /dev/null
+++ b/gio/giomodule-priv.c
@@ -0,0 +1,69 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2017 Collabora Inc.
+ *
+ * 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.1 of the License, or (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavier Claessens <xavier claessens collabora com>
+ */
+
+#include "config.h"
+#include "giomodule.h"
+#include "giomodule-priv.h"
+
+#include <string.h>
+
+/**
+ * _g_io_module_extract_name:
+ * @filename: filename of a GIOModule
+ *
+ * Extract the plugin name from its filename. It removes optional "lib" or
+ * "libgio" prefix, and removes everything after the first dot. For example:
+ * "libgiognutls.so" -> "gnutls".
+ *
+ * Returns: (transfer full): the module's name
+ */
+gchar *
+_g_io_module_extract_name (const char *filename)
+{
+  gchar *bname, *name;
+  const gchar *dot;
+  gsize prefix_len, len;
+  gsize i;
+
+  bname = g_path_get_basename (filename);
+  for (i = 0; bname[i]; ++i)
+    {
+      if (bname[i] == '-')
+        bname[i] = '_';
+    }
+
+  if (g_str_has_prefix (bname, "libgio"))
+    prefix_len = 6;
+  else if (g_str_has_prefix (bname, "lib"))
+    prefix_len = 3;
+  else
+    prefix_len = 0; /* use whole name (minus suffix) as plugin name */
+
+  dot = strchr (bname, '.');
+  if (dot != NULL)
+    len = dot - bname - prefix_len;
+  else
+    len = strlen (bname + prefix_len);
+
+  name = g_strndup (bname + prefix_len, len);
+  g_free (bname);
+
+  return name;
+}
diff --git a/gio/giomodule-priv.h b/gio/giomodule-priv.h
index e480593..68d46f2 100644
--- a/gio/giomodule-priv.h
+++ b/gio/giomodule-priv.h
@@ -41,6 +41,9 @@ GType    _g_io_module_get_default_type (const gchar *extension_point,
 void *_g_io_win32_get_module (void);
 #endif
 
+gchar *_g_io_module_extract_name (const char *filename);
+
+
 G_END_DECLS
 
 #endif /* __G_IO_MODULE_PRIV_H__ */
diff --git a/gio/giomodule.c b/gio/giomodule.c
index 4047695..1adfd93 100644
--- a/gio/giomodule.c
+++ b/gio/giomodule.c
@@ -291,6 +291,43 @@ g_io_module_finalize (GObject *object)
 }
 
 static gboolean
+load_symbols (GIOModule *module)
+{
+  gchar *name;
+  gchar *load_symname;
+  gchar *unload_symname;
+  gboolean ret;
+
+  name = _g_io_module_extract_name (module->filename);
+  load_symname = g_strconcat ("g_io_", name, "_load", NULL);
+  unload_symname = g_strconcat ("g_io_", name, "_unload", NULL);
+
+  ret = g_module_symbol (module->library,
+                         load_symname,
+                         (gpointer) &module->load) &&
+        g_module_symbol (module->library,
+                         unload_symname,
+                         (gpointer) &module->unload);
+
+  if (!ret)
+    {
+      /* Fallback to old names */
+      ret = g_module_symbol (module->library,
+                             "g_io_module_load",
+                             (gpointer) &module->load) &&
+            g_module_symbol (module->library,
+                             "g_io_module_unload",
+                             (gpointer) &module->unload);
+    }
+
+  g_free (name);
+  g_free (load_symname);
+  g_free (unload_symname);
+
+  return ret;
+}
+
+static gboolean
 g_io_module_load_module (GTypeModule *gmodule)
 {
   GIOModule *module = G_IO_MODULE (gmodule);
@@ -310,12 +347,7 @@ g_io_module_load_module (GTypeModule *gmodule)
     }
 
   /* Make sure that the loaded library contains the required methods */
-  if (! g_module_symbol (module->library,
-                         "g_io_module_load",
-                         (gpointer) &module->load) ||
-      ! g_module_symbol (module->library,
-                         "g_io_module_unload",
-                         (gpointer) &module->unload))
+  if (!load_symbols (module))
     {
       g_printerr ("%s\n", g_module_error ());
       g_module_close (module->library);
diff --git a/gio/giomodule.h b/gio/giomodule.h
index 485f5eb..e94b809 100644
--- a/gio/giomodule.h
+++ b/gio/giomodule.h
@@ -112,6 +112,14 @@ GTypeClass*        g_io_extension_ref_class                   (GIOExtension
  * This function is run after the module has been loaded into GIO,
  * to initialize the module. Typically, this function will call
  * g_io_extension_point_implement().
+ *
+ * Since 2.56, this function should be named `g_io_<modulename>_load`, where
+ * `modulename` is the plugin’s filename with the `lib` or `libgio` prefix and
+ * everything after the first dot removed, and with `-` replaced with `_`
+ * throughout. For example, `libgiognutls-helper.so` becomes `gnutls_helper`.
+ * Using the new symbol names avoids name clashes when building modules
+ * statically. The old symbol names continue to be supported, but cannot be used
+ * for static builds.
  **/
 GLIB_AVAILABLE_IN_ALL
 void   g_io_module_load   (GIOModule *module);
@@ -124,6 +132,14 @@ void   g_io_module_load   (GIOModule *module);
  *
  * This function is run when the module is being unloaded from GIO,
  * to finalize the module.
+ *
+ * Since 2.56, this function should be named `g_io_<modulename>_unload`, where
+ * `modulename` is the plugin’s filename with the `lib` or `libgio` prefix and
+ * everything after the first dot removed, and with `-` replaced with `_`
+ * throughout. For example, `libgiognutls-helper.so` becomes `gnutls_helper`.
+ * Using the new symbol names avoids name clashes when building modules
+ * statically. The old symbol names continue to be supported, but cannot be used
+ * for static builds.
  **/
 GLIB_AVAILABLE_IN_ALL
 void   g_io_module_unload (GIOModule *module);
@@ -155,6 +171,14 @@ void   g_io_module_unload (GIOModule *module);
  * run gio-querymodules in order to build the cache files required for
  * lazy loading.
  *
+ * Since 2.56, this function should be named `g_io_<modulename>_query`, where
+ * `modulename` is the plugin’s filename with the `lib` or `libgio` prefix and
+ * everything after the first dot removed, and with `-` replaced with `_`
+ * throughout. For example, `libgiognutls-helper.so` becomes `gnutls_helper`.
+ * Using the new symbol names avoids name clashes when building modules
+ * statically. The old symbol names continue to be supported, but cannot be used
+ * for static builds.
+ *
  * Returns: (transfer full): A %NULL-terminated array of strings,
  *     listing the supported extension points of the module. The array
  *     must be suitable for freeing with g_strfreev().
diff --git a/gio/meson.build b/gio/meson.build
index d7dcfa5..61a79d4 100644
--- a/gio/meson.build
+++ b/gio/meson.build
@@ -441,6 +441,7 @@ gio_sources = files(
   'ginputstream.c',
   'gioerror.c',
   'giomodule.c',
+  'giomodule-priv.c',
   'gioscheduler.c',
   'giostream.c',
   'gloadableicon.c',
@@ -803,7 +804,7 @@ executable('gresource', 'gresource-tool.c',
   link_args : noseh_link_args,
   dependencies : [libelf, libintl, libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep])
 
-executable('gio-querymodules', 'gio-querymodules.c',
+executable('gio-querymodules', 'gio-querymodules.c', 'giomodule-priv.c',
   install : true,
   c_args : ['-DHAVE_CONFIG_H=1'] + gio_c_args,
   # intl.lib is not compatible with SAFESEH


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]