• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GMODULE - GLIB wrapper code for dynamic module loading
2  * Copyright (C) 1998 Tim Janik
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GLib Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GLib at ftp://ftp.gtk.org/pub/gtk/.
23  */
24 
25 /*
26  * MT safe
27  */
28 
29 #include "config.h"
30 
31 #include "glib.h"
32 #include "gmodule.h"
33 
34 #include <errno.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #ifdef G_OS_UNIX
40 #include <unistd.h>
41 #endif
42 #ifdef G_OS_WIN32
43 #include <io.h>		/* For open() and close() prototypes. */
44 #endif
45 
46 #include "gmoduleconf.h"
47 #include "gstdio.h"
48 
49 /**
50  * SECTION:modules
51  * @title: Dynamic Loading of Modules
52  * @short_description: portable method for dynamically loading 'plug-ins'
53  *
54  * These functions provide a portable way to dynamically load object files
55  * (commonly known as 'plug-ins'). The current implementation supports all
56  * systems that provide an implementation of dlopen() (e.g. Linux/Sun), as
57  * well as Windows platforms via DLLs.
58  *
59  * A program which wants to use these functions must be linked to the
60  * libraries output by the command `pkg-config --libs gmodule-2.0`.
61  *
62  * To use them you must first determine whether dynamic loading
63  * is supported on the platform by calling g_module_supported().
64  * If it is, you can open a module with g_module_open(),
65  * find the module's symbols (e.g. function names) with g_module_symbol(),
66  * and later close the module with g_module_close().
67  * g_module_name() will return the file name of a currently opened module.
68  *
69  * If any of the above functions fail, the error status can be found with
70  * g_module_error().
71  *
72  * The #GModule implementation features reference counting for opened modules,
73  * and supports hook functions within a module which are called when the
74  * module is loaded and unloaded (see #GModuleCheckInit and #GModuleUnload).
75  *
76  * If your module introduces static data to common subsystems in the running
77  * program, e.g. through calling
78  * `g_quark_from_static_string ("my-module-stuff")`,
79  * it must ensure that it is never unloaded, by calling g_module_make_resident().
80  *
81  * Example: Calling a function defined in a GModule
82  * |[<!-- language="C" -->
83  * // the function signature for 'say_hello'
84  * typedef void (* SayHelloFunc) (const char *message);
85  *
86  * gboolean
87  * just_say_hello (const char *filename, GError **error)
88  * {
89  *   SayHelloFunc  say_hello;
90  *   GModule      *module;
91  *
92  *   module = g_module_open (filename, G_MODULE_BIND_LAZY);
93  *   if (!module)
94  *     {
95  *       g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
96  *                    "%s", g_module_error ());
97  *       return FALSE;
98  *     }
99  *
100  *   if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello))
101  *     {
102  *       g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
103  *                    "%s: %s", filename, g_module_error ());
104  *       if (!g_module_close (module))
105  *         g_warning ("%s: %s", filename, g_module_error ());
106  *       return FALSE;
107  *     }
108  *
109  *   if (say_hello == NULL)
110  *     {
111  *       g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
112  *                    "symbol say_hello is NULL");
113  *       if (!g_module_close (module))
114  *         g_warning ("%s: %s", filename, g_module_error ());
115  *       return FALSE;
116  *     }
117  *
118  *   // call our function in the module
119  *   say_hello ("Hello world!");
120  *
121  *   if (!g_module_close (module))
122  *     g_warning ("%s: %s", filename, g_module_error ());
123  *   return TRUE;
124  *  }
125  * ]|
126  */
127 
128 /**
129  * GModule:
130  *
131  * The #GModule struct is an opaque data structure to represent a
132  * [dynamically-loaded module][glib-Dynamic-Loading-of-Modules].
133  * It should only be accessed via the following functions.
134  */
135 
136 /**
137  * GModuleCheckInit:
138  * @module: the #GModule corresponding to the module which has just been loaded
139  *
140  * Specifies the type of the module initialization function.
141  * If a module contains a function named g_module_check_init() it is called
142  * automatically when the module is loaded. It is passed the #GModule structure
143  * and should return %NULL on success or a string describing the initialization
144  * error.
145  *
146  * Returns: %NULL on success, or a string describing the initialization error
147  */
148 
149 /**
150  * GModuleUnload:
151  * @module: the #GModule about to be unloaded
152  *
153  * Specifies the type of the module function called when it is unloaded.
154  * If a module contains a function named g_module_unload() it is called
155  * automatically when the module is unloaded.
156  * It is passed the #GModule structure.
157  */
158 
159 /**
160  * G_MODULE_SUFFIX:
161  *
162  * Expands to the proper shared library suffix for the current platform
163  * without the leading dot. For most Unices and Linux this is "so", and
164  * for Windows this is "dll".
165  */
166 
167 /**
168  * G_MODULE_EXPORT:
169  *
170  * Used to declare functions exported by libraries or modules.
171  *
172  * When compiling for Windows, it marks the symbol as `dllexport`.
173  *
174  * When compiling for Linux and Unices, it marks the symbol as having `default`
175  * visibility. This is no-op unless the code is being compiled with a
176  * non-default
177  * [visibility flag](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility-1260)
178  * such as `hidden`.
179  */
180 
181 /**
182  * G_MODULE_IMPORT:
183  *
184  * Used to declare functions imported from modules.
185  */
186 
187 /* We maintain a list of modules, so we can reference count them.
188  * That's needed because some platforms don't support references counts on
189  * modules. Also, the module for the program itself is kept separately for
190  * faster access and because it has special semantics.
191  */
192 
193 
194 /* --- structures --- */
195 struct _GModule
196 {
197   gchar	*file_name;
198   gpointer handle;
199   guint ref_count : 31;
200   guint is_resident : 1;
201   GModuleUnload unload;
202   GModule *next;
203 };
204 
205 
206 /* --- prototypes --- */
207 static gpointer		_g_module_open		(const gchar	*file_name,
208 						 gboolean	 bind_lazy,
209 						 gboolean	 bind_local);
210 static void		_g_module_close		(gpointer	 handle);
211 static gpointer		_g_module_self		(void);
212 static gpointer		_g_module_symbol	(gpointer	 handle,
213 						 const gchar	*symbol_name);
214 static gchar*		_g_module_build_path	(const gchar	*directory,
215 						 const gchar	*module_name);
216 static inline void	g_module_set_error	(const gchar	*error);
217 static inline GModule*	g_module_find_by_handle (gpointer	 handle);
218 static inline GModule*	g_module_find_by_name	(const gchar	*name);
219 
220 
221 /* --- variables --- */
222 static GModule	     *modules = NULL;
223 static GModule	     *main_module = NULL;
224 static GPrivate       module_error_private = G_PRIVATE_INIT (g_free);
225 static gboolean	      module_debug_initialized = FALSE;
226 static guint	      module_debug_flags = 0;
227 
228 
229 /* --- inline functions --- */
230 static inline GModule*
g_module_find_by_handle(gpointer handle)231 g_module_find_by_handle (gpointer handle)
232 {
233   GModule *module;
234   GModule *retval = NULL;
235 
236   if (main_module && main_module->handle == handle)
237     retval = main_module;
238   else
239     for (module = modules; module; module = module->next)
240       if (handle == module->handle)
241 	{
242 	  retval = module;
243 	  break;
244 	}
245 
246   return retval;
247 }
248 
249 static inline GModule*
g_module_find_by_name(const gchar * name)250 g_module_find_by_name (const gchar *name)
251 {
252   GModule *module;
253   GModule *retval = NULL;
254 
255   for (module = modules; module; module = module->next)
256     if (strcmp (name, module->file_name) == 0)
257 	{
258 	  retval = module;
259 	  break;
260 	}
261 
262   return retval;
263 }
264 
265 static inline void
g_module_set_error_unduped(gchar * error)266 g_module_set_error_unduped (gchar *error)
267 {
268   g_private_replace (&module_error_private, error);
269   errno = 0;
270 }
271 
272 static inline void
g_module_set_error(const gchar * error)273 g_module_set_error (const gchar *error)
274 {
275   g_module_set_error_unduped (g_strdup (error));
276 }
277 
278 
279 /* --- include platform specific code --- */
280 #define	SUPPORT_OR_RETURN(rv)	{ g_module_set_error (NULL); }
281 #if	(G_MODULE_IMPL == G_MODULE_IMPL_DL)
282 #include "gmodule-dl.c"
283 #elif	(G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
284 #include "gmodule-win32.c"
285 #elif	(G_MODULE_IMPL == G_MODULE_IMPL_AR)
286 #include "gmodule-ar.c"
287 #else
288 #undef	SUPPORT_OR_RETURN
289 #define	SUPPORT_OR_RETURN(rv)	{ g_module_set_error ("dynamic modules are " \
290                                               "not supported by this system"); return rv; }
291 static gpointer
_g_module_open(const gchar * file_name,gboolean bind_lazy,gboolean bind_local)292 _g_module_open (const gchar	*file_name,
293 		gboolean	 bind_lazy,
294 		gboolean	 bind_local)
295 {
296   return NULL;
297 }
298 static void
_g_module_close(gpointer handle)299 _g_module_close (gpointer handle)
300 {
301 }
302 static gpointer
_g_module_self(void)303 _g_module_self (void)
304 {
305   return NULL;
306 }
307 static gpointer
_g_module_symbol(gpointer handle,const gchar * symbol_name)308 _g_module_symbol (gpointer	 handle,
309 		  const gchar	*symbol_name)
310 {
311   return NULL;
312 }
313 static gchar*
_g_module_build_path(const gchar * directory,const gchar * module_name)314 _g_module_build_path (const gchar *directory,
315 		      const gchar *module_name)
316 {
317   return NULL;
318 }
319 #endif	/* no implementation */
320 
321 /* --- functions --- */
322 
323 /**
324  * g_module_supported:
325  *
326  * Checks if modules are supported on the current platform.
327  *
328  * Returns: %TRUE if modules are supported
329  */
330 gboolean
g_module_supported(void)331 g_module_supported (void)
332 {
333   SUPPORT_OR_RETURN (FALSE);
334 
335   return TRUE;
336 }
337 
338 static gchar*
parse_libtool_archive(const gchar * libtool_name)339 parse_libtool_archive (const gchar* libtool_name)
340 {
341   const guint TOKEN_DLNAME = G_TOKEN_LAST + 1;
342   const guint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
343   const guint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
344   gchar *lt_dlname = NULL;
345   gboolean lt_installed = TRUE;
346   gchar *lt_libdir = NULL;
347   gchar *name;
348   GTokenType token;
349   GScanner *scanner;
350 
351   int fd = g_open (libtool_name, O_RDONLY, 0);
352   if (fd < 0)
353     {
354       gchar *display_libtool_name = g_filename_display_name (libtool_name);
355       g_module_set_error_unduped (g_strdup_printf ("failed to open libtool archive \"%s\"", display_libtool_name));
356       g_free (display_libtool_name);
357       return NULL;
358     }
359   /* search libtool's dlname specification  */
360   scanner = g_scanner_new (NULL);
361   g_scanner_input_file (scanner, fd);
362   scanner->config->symbol_2_token = TRUE;
363   g_scanner_scope_add_symbol (scanner, 0, "dlname",
364 			      GUINT_TO_POINTER (TOKEN_DLNAME));
365   g_scanner_scope_add_symbol (scanner, 0, "installed",
366 			      GUINT_TO_POINTER (TOKEN_INSTALLED));
367   g_scanner_scope_add_symbol (scanner, 0, "libdir",
368 			      GUINT_TO_POINTER (TOKEN_LIBDIR));
369   while (!g_scanner_eof (scanner))
370     {
371       token = g_scanner_get_next_token (scanner);
372       if (token == TOKEN_DLNAME || token == TOKEN_INSTALLED ||
373 	  token == TOKEN_LIBDIR)
374 	{
375 	  if (g_scanner_get_next_token (scanner) != '=' ||
376 	      g_scanner_get_next_token (scanner) !=
377 	      (token == TOKEN_INSTALLED ?
378 	       G_TOKEN_IDENTIFIER : G_TOKEN_STRING))
379 	    {
380 	      gchar *display_libtool_name = g_filename_display_name (libtool_name);
381 	      g_module_set_error_unduped (g_strdup_printf ("unable to parse libtool archive \"%s\"", display_libtool_name));
382 	      g_free (display_libtool_name);
383 
384 	      g_free (lt_dlname);
385 	      g_free (lt_libdir);
386 	      g_scanner_destroy (scanner);
387 	      close (fd);
388 
389 	      return NULL;
390 	    }
391 	  else
392 	    {
393 	      if (token == TOKEN_DLNAME)
394 		{
395 		  g_free (lt_dlname);
396 		  lt_dlname = g_strdup (scanner->value.v_string);
397 		}
398 	      else if (token == TOKEN_INSTALLED)
399 		lt_installed =
400 		  strcmp (scanner->value.v_identifier, "yes") == 0;
401 	      else /* token == TOKEN_LIBDIR */
402 		{
403 		  g_free (lt_libdir);
404 		  lt_libdir = g_strdup (scanner->value.v_string);
405 		}
406 	    }
407 	}
408     }
409 
410   if (!lt_installed)
411     {
412       gchar *dir = g_path_get_dirname (libtool_name);
413       g_free (lt_libdir);
414       lt_libdir = g_strconcat (dir, G_DIR_SEPARATOR_S ".libs", NULL);
415       g_free (dir);
416     }
417 
418   name = g_strconcat (lt_libdir, G_DIR_SEPARATOR_S, lt_dlname, NULL);
419 
420   g_free (lt_dlname);
421   g_free (lt_libdir);
422   g_scanner_destroy (scanner);
423   close (fd);
424 
425   return name;
426 }
427 
428 static inline gboolean
str_check_suffix(const gchar * string,const gchar * suffix)429 str_check_suffix (const gchar* string,
430 		  const gchar* suffix)
431 {
432   gsize string_len = strlen (string);
433   gsize suffix_len = strlen (suffix);
434 
435   return string_len >= suffix_len &&
436     strcmp (string + string_len - suffix_len, suffix) == 0;
437 }
438 
439 enum
440 {
441   G_MODULE_DEBUG_RESIDENT_MODULES = 1 << 0,
442   G_MODULE_DEBUG_BIND_NOW_MODULES = 1 << 1
443 };
444 
445 static void
_g_module_debug_init(void)446 _g_module_debug_init (void)
447 {
448   const GDebugKey keys[] = {
449     { "resident-modules", G_MODULE_DEBUG_RESIDENT_MODULES },
450     { "bind-now-modules", G_MODULE_DEBUG_BIND_NOW_MODULES }
451   };
452   const gchar *env;
453 
454   env = g_getenv ("G_DEBUG");
455 
456   module_debug_flags =
457     !env ? 0 : g_parse_debug_string (env, keys, G_N_ELEMENTS (keys));
458 
459   module_debug_initialized = TRUE;
460 }
461 
462 static GRecMutex g_module_global_lock;
463 
464 /**
465  * g_module_open:
466  * @file_name: (nullable): the name of the file containing the module, or %NULL
467  *     to obtain a #GModule representing the main program itself
468  * @flags: the flags used for opening the module. This can be the
469  *     logical OR of any of the #GModuleFlags
470  *
471  * Opens a module. If the module has already been opened,
472  * its reference count is incremented.
473  *
474  * First of all g_module_open() tries to open @file_name as a module.
475  * If that fails and @file_name has the ".la"-suffix (and is a libtool
476  * archive) it tries to open the corresponding module. If that fails
477  * and it doesn't have the proper module suffix for the platform
478  * (#G_MODULE_SUFFIX), this suffix will be appended and the corresponding
479  * module will be opened. If that fails and @file_name doesn't have the
480  * ".la"-suffix, this suffix is appended and g_module_open() tries to open
481  * the corresponding module. If eventually that fails as well, %NULL is
482  * returned.
483  *
484  * Returns: a #GModule on success, or %NULL on failure
485  */
486 GModule*
g_module_open(const gchar * file_name,GModuleFlags flags)487 g_module_open (const gchar    *file_name,
488 	       GModuleFlags    flags)
489 {
490   GModule *module;
491   gpointer handle = NULL;
492   gchar *name = NULL;
493 
494   SUPPORT_OR_RETURN (NULL);
495 
496   g_rec_mutex_lock (&g_module_global_lock);
497 
498   if (G_UNLIKELY (!module_debug_initialized))
499     _g_module_debug_init ();
500 
501   if (module_debug_flags & G_MODULE_DEBUG_BIND_NOW_MODULES)
502     flags &= ~G_MODULE_BIND_LAZY;
503 
504   if (!file_name)
505     {
506       if (!main_module)
507 	{
508 	  handle = _g_module_self ();
509 /* On Android 64 bit, RTLD_DEFAULT is (void *)0x0
510  * so it always fails to create main_module if file_name is NULL */
511 #if !defined(__BIONIC__) || !defined(__LP64__)
512 	  if (handle)
513 #endif
514 	    {
515 	      main_module = g_new (GModule, 1);
516 	      main_module->file_name = NULL;
517 	      main_module->handle = handle;
518 	      main_module->ref_count = 1;
519 	      main_module->is_resident = TRUE;
520 	      main_module->unload = NULL;
521 	      main_module->next = NULL;
522 	    }
523 	}
524       else
525 	main_module->ref_count++;
526 
527       g_rec_mutex_unlock (&g_module_global_lock);
528       return main_module;
529     }
530 
531   /* we first search the module list by name */
532   module = g_module_find_by_name (file_name);
533   if (module)
534     {
535       module->ref_count++;
536 
537       g_rec_mutex_unlock (&g_module_global_lock);
538       return module;
539     }
540 
541   /* check whether we have a readable file right away */
542   if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
543     name = g_strdup (file_name);
544   /* try completing file name with standard library suffix */
545   if (!name)
546     {
547       name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
548       if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
549 	{
550 	  g_free (name);
551 	  name = NULL;
552 	}
553     }
554   /* try completing by appending libtool suffix */
555   if (!name)
556     {
557       name = g_strconcat (file_name, ".la", NULL);
558       if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
559 	{
560 	  g_free (name);
561 	  name = NULL;
562 	}
563     }
564   /* we can't access() the file, lets hope the platform backends finds
565    * it via library paths
566    */
567   if (!name)
568     {
569       gchar *dot = strrchr (file_name, '.');
570       gchar *slash = strrchr (file_name, G_DIR_SEPARATOR);
571 
572       /* make sure the name has a suffix */
573       if (!dot || dot < slash)
574 	name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
575       else
576 	name = g_strdup (file_name);
577     }
578 
579   /* ok, try loading the module */
580   if (name)
581     {
582       /* if it's a libtool archive, figure library file to load */
583       if (str_check_suffix (name, ".la")) /* libtool archive? */
584 	{
585 	  gchar *real_name = parse_libtool_archive (name);
586 
587 	  /* real_name might be NULL, but then module error is already set */
588 	  if (real_name)
589 	    {
590 	      g_free (name);
591 	      name = real_name;
592             }
593 	}
594       if (name)
595 	handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0,
596 			(flags & G_MODULE_BIND_LOCAL) != 0);
597     }
598   else
599     {
600       gchar *display_file_name = g_filename_display_name (file_name);
601       g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", display_file_name));
602       g_free (display_file_name);
603     }
604   g_free (name);
605 
606   if (handle)
607     {
608       gchar *saved_error;
609       GModuleCheckInit check_init;
610       const gchar *check_failed = NULL;
611 
612       /* search the module list by handle, since file names are not unique */
613       module = g_module_find_by_handle (handle);
614       if (module)
615 	{
616 	  _g_module_close (module->handle);
617 	  module->ref_count++;
618 	  g_module_set_error (NULL);
619 
620 	  g_rec_mutex_unlock (&g_module_global_lock);
621 	  return module;
622 	}
623 
624       saved_error = g_strdup (g_module_error ());
625       g_module_set_error (NULL);
626 
627       module = g_new (GModule, 1);
628       module->file_name = g_strdup (file_name);
629       module->handle = handle;
630       module->ref_count = 1;
631       module->is_resident = FALSE;
632       module->unload = NULL;
633       module->next = modules;
634       modules = module;
635 
636       /* check initialization */
637       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init) && check_init != NULL)
638 	check_failed = check_init (module);
639 
640       /* we don't call unload() if the initialization check failed. */
641       if (!check_failed)
642 	g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
643 
644       if (check_failed)
645 	{
646 	  gchar *error;
647 
648 	  error = g_strconcat ("GModule (", file_name, ") ",
649                                "initialization check failed: ",
650                                check_failed, NULL);
651 	  g_module_close (module);
652 	  module = NULL;
653 	  g_module_set_error (error);
654 	  g_free (error);
655 	}
656       else
657 	g_module_set_error (saved_error);
658 
659       g_free (saved_error);
660     }
661 
662   if (module != NULL &&
663       (module_debug_flags & G_MODULE_DEBUG_RESIDENT_MODULES))
664     g_module_make_resident (module);
665 
666   g_rec_mutex_unlock (&g_module_global_lock);
667   return module;
668 }
669 
670 /**
671  * g_module_close:
672  * @module: a #GModule to close
673  *
674  * Closes a module.
675  *
676  * Returns: %TRUE on success
677  */
678 gboolean
g_module_close(GModule * module)679 g_module_close (GModule *module)
680 {
681   SUPPORT_OR_RETURN (FALSE);
682 
683   g_return_val_if_fail (module != NULL, FALSE);
684   g_return_val_if_fail (module->ref_count > 0, FALSE);
685 
686   g_rec_mutex_lock (&g_module_global_lock);
687 
688   module->ref_count--;
689 
690   if (!module->ref_count && !module->is_resident && module->unload)
691     {
692       GModuleUnload unload;
693 
694       unload = module->unload;
695       module->unload = NULL;
696       unload (module);
697     }
698 
699   if (!module->ref_count && !module->is_resident)
700     {
701       GModule *last;
702       GModule *node;
703 
704       last = NULL;
705 
706       node = modules;
707       while (node)
708 	{
709 	  if (node == module)
710 	    {
711 	      if (last)
712 		last->next = node->next;
713 	      else
714 		modules = node->next;
715 	      break;
716 	    }
717 	  last = node;
718 	  node = last->next;
719 	}
720       module->next = NULL;
721 
722       _g_module_close (module->handle);
723       g_free (module->file_name);
724       g_free (module);
725     }
726 
727   g_rec_mutex_unlock (&g_module_global_lock);
728   return g_module_error() == NULL;
729 }
730 
731 /**
732  * g_module_make_resident:
733  * @module: a #GModule to make permanently resident
734  *
735  * Ensures that a module will never be unloaded.
736  * Any future g_module_close() calls on the module will be ignored.
737  */
738 void
g_module_make_resident(GModule * module)739 g_module_make_resident (GModule *module)
740 {
741   g_return_if_fail (module != NULL);
742 
743   module->is_resident = TRUE;
744 }
745 
746 /**
747  * g_module_error:
748  *
749  * Gets a string describing the last module error.
750  *
751  * Returns: a string describing the last module error
752  */
753 const gchar *
g_module_error(void)754 g_module_error (void)
755 {
756   return g_private_get (&module_error_private);
757 }
758 
759 /**
760  * g_module_symbol:
761  * @module: a #GModule
762  * @symbol_name: the name of the symbol to find
763  * @symbol: (out): returns the pointer to the symbol value
764  *
765  * Gets a symbol pointer from a module, such as one exported
766  * by #G_MODULE_EXPORT. Note that a valid symbol can be %NULL.
767  *
768  * Returns: %TRUE on success
769  */
770 gboolean
g_module_symbol(GModule * module,const gchar * symbol_name,gpointer * symbol)771 g_module_symbol (GModule     *module,
772                  const gchar *symbol_name,
773                  gpointer    *symbol)
774 {
775   const gchar *module_error;
776 
777   if (symbol)
778     *symbol = NULL;
779   SUPPORT_OR_RETURN (FALSE);
780 
781   g_return_val_if_fail (module != NULL, FALSE);
782   g_return_val_if_fail (symbol_name != NULL, FALSE);
783   g_return_val_if_fail (symbol != NULL, FALSE);
784 
785   g_rec_mutex_lock (&g_module_global_lock);
786 
787 #ifdef	G_MODULE_NEED_USCORE
788   {
789     gchar *name;
790 
791     name = g_strconcat ("_", symbol_name, NULL);
792     *symbol = _g_module_symbol (module->handle, name);
793     g_free (name);
794   }
795 #else	/* !G_MODULE_NEED_USCORE */
796   *symbol = _g_module_symbol (module->handle, symbol_name);
797 #endif	/* !G_MODULE_NEED_USCORE */
798 
799   module_error = g_module_error ();
800   if (module_error)
801     {
802       gchar *error;
803 
804       error = g_strconcat ("'", symbol_name, "': ", module_error, NULL);
805       g_module_set_error (error);
806       g_free (error);
807       *symbol = NULL;
808     }
809 
810   g_rec_mutex_unlock (&g_module_global_lock);
811   return !module_error;
812 }
813 
814 /**
815  * g_module_name:
816  * @module: a #GModule
817  *
818  * Returns the filename that the module was opened with.
819  *
820  * If @module refers to the application itself, "main" is returned.
821  *
822  * Returns: (transfer none): the filename of the module
823  */
824 const gchar *
g_module_name(GModule * module)825 g_module_name (GModule *module)
826 {
827   g_return_val_if_fail (module != NULL, NULL);
828 
829   if (module == main_module)
830     return "main";
831 
832   return module->file_name;
833 }
834 
835 /**
836  * g_module_build_path:
837  * @directory: (nullable): the directory where the module is. This can be
838  *     %NULL or the empty string to indicate that the standard platform-specific
839  *     directories will be used, though that is not recommended
840  * @module_name: the name of the module
841  *
842  * A portable way to build the filename of a module. The platform-specific
843  * prefix and suffix are added to the filename, if needed, and the result
844  * is added to the directory, using the correct separator character.
845  *
846  * The directory should specify the directory where the module can be found.
847  * It can be %NULL or an empty string to indicate that the module is in a
848  * standard platform-specific directory, though this is not recommended
849  * since the wrong module may be found.
850  *
851  * For example, calling g_module_build_path() on a Linux system with a
852  * @directory of `/lib` and a @module_name of "mylibrary" will return
853  * `/lib/libmylibrary.so`. On a Windows system, using `\Windows` as the
854  * directory it will return `\Windows\mylibrary.dll`.
855  *
856  * Returns: the complete path of the module, including the standard library
857  *     prefix and suffix. This should be freed when no longer needed
858  */
859 gchar *
g_module_build_path(const gchar * directory,const gchar * module_name)860 g_module_build_path (const gchar *directory,
861                      const gchar *module_name)
862 {
863   g_return_val_if_fail (module_name != NULL, NULL);
864 
865   return _g_module_build_path (directory, module_name);
866 }
867 
868 
869 #ifdef G_OS_WIN32
870 
871 /* Binary compatibility versions. Not for newly compiled code. */
872 
873 _GLIB_EXTERN GModule *    g_module_open_utf8 (const gchar  *file_name,
874                                               GModuleFlags  flags);
875 
876 _GLIB_EXTERN const gchar *g_module_name_utf8 (GModule      *module);
877 
878 GModule*
g_module_open_utf8(const gchar * file_name,GModuleFlags flags)879 g_module_open_utf8 (const gchar    *file_name,
880                     GModuleFlags    flags)
881 {
882   return g_module_open (file_name, flags);
883 }
884 
885 const gchar *
g_module_name_utf8(GModule * module)886 g_module_name_utf8 (GModule *module)
887 {
888   return g_module_name (module);
889 }
890 
891 #endif
892