1 /* GMODULE - GLIB wrapper code for dynamic module loading
2 * Copyright (C) 1998 Tim Janik
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 of the License, or (at your option) any later version.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GLib Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GLib at ftp://ftp.gtk.org/pub/gtk/.
38 #include <sys/types.h>
45 #include <io.h> /* For open() and close() prototypes. */
48 #include "gmoduleconf.h"
51 /* We maintain a list of modules, so we can reference count them.
52 * That's needed because some platforms don't support refernce counts on
53 * modules e.g. the shl_* implementation of HP-UX
54 * (http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html).
55 * Also, the module for the program itself is kept seperatedly for
56 * faster access and because it has special semantics.
60 /* --- structures --- */
64 #if defined (G_OS_WIN32) && !defined(_WIN64)
69 guint is_resident
: 1;
75 /* --- prototypes --- */
76 static gpointer
_g_module_open (const gchar
*file_name
,
79 static void _g_module_close (gpointer handle
,
81 static gpointer
_g_module_self (void);
82 static gpointer
_g_module_symbol (gpointer handle
,
83 const gchar
*symbol_name
);
84 static gchar
* _g_module_build_path (const gchar
*directory
,
85 const gchar
*module_name
);
86 static inline void g_module_set_error (const gchar
*error
);
87 static inline GModule
* g_module_find_by_handle (gpointer handle
);
88 static inline GModule
* g_module_find_by_name (const gchar
*name
);
91 /* --- variables --- */
92 static GModule
*modules
= NULL
;
93 static GModule
*main_module
= NULL
;
94 static GStaticPrivate module_error_private
= G_STATIC_PRIVATE_INIT
;
95 static gboolean module_debug_initialized
= FALSE
;
96 static guint module_debug_flags
= 0;
99 /* --- inline functions --- */
100 static inline GModule
*
101 g_module_find_by_handle (gpointer handle
)
104 GModule
*retval
= NULL
;
106 if (main_module
&& main_module
->handle
== handle
)
107 retval
= main_module
;
109 for (module
= modules
; module
; module
= module
->next
)
110 if (handle
== module
->handle
)
119 static inline GModule
*
120 g_module_find_by_name (const gchar
*name
)
123 GModule
*retval
= NULL
;
125 for (module
= modules
; module
; module
= module
->next
)
126 if (strcmp (name
, module
->file_name
) == 0)
136 g_module_set_error_unduped (gchar
*error
)
138 g_static_private_set (&module_error_private
, error
, g_free
);
143 g_module_set_error (const gchar
*error
)
145 g_module_set_error_unduped (g_strdup (error
));
149 /* --- include platform specifc code --- */
150 #define SUPPORT_OR_RETURN(rv) { g_module_set_error (NULL); }
151 #if (G_MODULE_IMPL == G_MODULE_IMPL_DL)
152 #include "gmodule-dl.c"
153 #elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
154 #include "gmodule-dld.c"
155 #elif (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
156 #include "gmodule-win32.c"
157 #elif (G_MODULE_IMPL == G_MODULE_IMPL_DYLD)
158 #include "gmodule-dyld.c"
159 #elif (G_MODULE_IMPL == G_MODULE_IMPL_AR)
160 #include "gmodule-ar.c"
162 #undef SUPPORT_OR_RETURN
163 #define SUPPORT_OR_RETURN(rv) { g_module_set_error ("dynamic modules are " \
164 "not supported by this system"); return rv; }
166 _g_module_open (const gchar
*file_name
,
173 _g_module_close (gpointer handle
,
178 _g_module_self (void)
183 _g_module_symbol (gpointer handle
,
184 const gchar
*symbol_name
)
189 _g_module_build_path (const gchar
*directory
,
190 const gchar
*module_name
)
194 #endif /* no implementation */
196 /* --- functions --- */
198 g_module_supported (void)
200 SUPPORT_OR_RETURN (FALSE
);
206 parse_libtool_archive (const gchar
* libtool_name
)
208 const guint TOKEN_DLNAME
= G_TOKEN_LAST
+ 1;
209 const guint TOKEN_INSTALLED
= G_TOKEN_LAST
+ 2;
210 const guint TOKEN_LIBDIR
= G_TOKEN_LAST
+ 3;
211 gchar
*lt_dlname
= NULL
;
212 gboolean lt_installed
= TRUE
;
213 gchar
*lt_libdir
= NULL
;
218 int fd
= g_open (libtool_name
, O_RDONLY
, 0);
221 gchar
*display_libtool_name
= g_filename_display_name (libtool_name
);
222 g_module_set_error_unduped (g_strdup_printf ("failed to open libtool archive \"%s\"", display_libtool_name
));
223 g_free (display_libtool_name
);
226 /* search libtool's dlname specification */
227 scanner
= g_scanner_new (NULL
);
228 g_scanner_input_file (scanner
, fd
);
229 scanner
->config
->symbol_2_token
= TRUE
;
230 g_scanner_scope_add_symbol (scanner
, 0, "dlname",
231 GUINT_TO_POINTER (TOKEN_DLNAME
));
232 g_scanner_scope_add_symbol (scanner
, 0, "installed",
233 GUINT_TO_POINTER (TOKEN_INSTALLED
));
234 g_scanner_scope_add_symbol (scanner
, 0, "libdir",
235 GUINT_TO_POINTER (TOKEN_LIBDIR
));
236 while (!g_scanner_eof (scanner
))
238 token
= g_scanner_get_next_token (scanner
);
239 if (token
== TOKEN_DLNAME
|| token
== TOKEN_INSTALLED
||
240 token
== TOKEN_LIBDIR
)
242 if (g_scanner_get_next_token (scanner
) != '=' ||
243 g_scanner_get_next_token (scanner
) !=
244 (token
== TOKEN_INSTALLED
?
245 G_TOKEN_IDENTIFIER
: G_TOKEN_STRING
))
247 gchar
*display_libtool_name
= g_filename_display_name (libtool_name
);
248 g_module_set_error_unduped (g_strdup_printf ("unable to parse libtool archive \"%s\"", display_libtool_name
));
249 g_free (display_libtool_name
);
253 g_scanner_destroy (scanner
);
260 if (token
== TOKEN_DLNAME
)
263 lt_dlname
= g_strdup (scanner
->value
.v_string
);
265 else if (token
== TOKEN_INSTALLED
)
267 strcmp (scanner
->value
.v_identifier
, "yes") == 0;
268 else /* token == TOKEN_LIBDIR */
271 lt_libdir
= g_strdup (scanner
->value
.v_string
);
279 gchar
*dir
= g_path_get_dirname (libtool_name
);
281 lt_libdir
= g_strconcat (dir
, G_DIR_SEPARATOR_S
".libs", NULL
);
285 name
= g_strconcat (lt_libdir
, G_DIR_SEPARATOR_S
, lt_dlname
, NULL
);
289 g_scanner_destroy (scanner
);
295 static inline gboolean
296 str_check_suffix (const gchar
* string
,
299 gsize string_len
= strlen (string
);
300 gsize suffix_len
= strlen (suffix
);
302 return string_len
>= suffix_len
&&
303 strcmp (string
+ string_len
- suffix_len
, suffix
) == 0;
308 G_MODULE_DEBUG_RESIDENT_MODULES
= 1 << 0,
309 G_MODULE_DEBUG_BIND_NOW_MODULES
= 1 << 1
313 _g_module_debug_init (void)
315 const GDebugKey keys
[] = {
316 { "resident-modules", G_MODULE_DEBUG_RESIDENT_MODULES
},
317 { "bind-now-modules", G_MODULE_DEBUG_BIND_NOW_MODULES
}
321 env
= g_getenv ("G_DEBUG");
324 !env
? 0 : g_parse_debug_string (env
, keys
, G_N_ELEMENTS (keys
));
326 module_debug_initialized
= TRUE
;
329 static GStaticRecMutex g_module_global_lock
= G_STATIC_REC_MUTEX_INIT
;
332 g_module_open (const gchar
*file_name
,
336 gpointer handle
= NULL
;
339 SUPPORT_OR_RETURN (NULL
);
341 g_static_rec_mutex_lock (&g_module_global_lock
);
343 if (G_UNLIKELY (!module_debug_initialized
))
344 _g_module_debug_init ();
346 if (module_debug_flags
& G_MODULE_DEBUG_BIND_NOW_MODULES
)
347 flags
&= ~G_MODULE_BIND_LAZY
;
353 handle
= _g_module_self ();
356 main_module
= g_new (GModule
, 1);
357 main_module
->file_name
= NULL
;
358 #if defined (G_OS_WIN32) && !defined(_WIN64)
359 main_module
->cp_file_name
= NULL
;
361 main_module
->handle
= handle
;
362 main_module
->ref_count
= 1;
363 main_module
->is_resident
= TRUE
;
364 main_module
->unload
= NULL
;
365 main_module
->next
= NULL
;
369 main_module
->ref_count
++;
371 g_static_rec_mutex_unlock (&g_module_global_lock
);
375 /* we first search the module list by name */
376 module
= g_module_find_by_name (file_name
);
381 g_static_rec_mutex_unlock (&g_module_global_lock
);
385 /* check whether we have a readable file right away */
386 if (g_file_test (file_name
, G_FILE_TEST_IS_REGULAR
))
387 name
= g_strdup (file_name
);
388 /* try completing file name with standard library suffix */
391 name
= g_strconcat (file_name
, "." G_MODULE_SUFFIX
, NULL
);
392 if (!g_file_test (name
, G_FILE_TEST_IS_REGULAR
))
398 /* try completing by appending libtool suffix */
401 name
= g_strconcat (file_name
, ".la", NULL
);
402 if (!g_file_test (name
, G_FILE_TEST_IS_REGULAR
))
408 /* we can't access() the file, lets hope the platform backends finds
409 * it via library paths
413 gchar
*dot
= strrchr (file_name
, '.');
414 gchar
*slash
= strrchr (file_name
, G_DIR_SEPARATOR
);
416 /* make sure the name has a suffix */
417 if (!dot
|| dot
< slash
)
418 name
= g_strconcat (file_name
, "." G_MODULE_SUFFIX
, NULL
);
420 name
= g_strdup (file_name
);
423 /* ok, try loading the module */
426 /* if it's a libtool archive, figure library file to load */
427 if (str_check_suffix (name
, ".la")) /* libtool archive? */
429 gchar
*real_name
= parse_libtool_archive (name
);
431 /* real_name might be NULL, but then module error is already set */
439 handle
= _g_module_open (name
, (flags
& G_MODULE_BIND_LAZY
) != 0,
440 (flags
& G_MODULE_BIND_LOCAL
) != 0);
444 gchar
*display_file_name
= g_filename_display_name (file_name
);
445 g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", display_file_name
));
446 g_free (display_file_name
);
453 GModuleCheckInit check_init
;
454 const gchar
*check_failed
= NULL
;
456 /* search the module list by handle, since file names are not unique */
457 module
= g_module_find_by_handle (handle
);
460 _g_module_close (module
->handle
, TRUE
);
462 g_module_set_error (NULL
);
464 g_static_rec_mutex_unlock (&g_module_global_lock
);
468 saved_error
= g_strdup (g_module_error ());
469 g_module_set_error (NULL
);
471 module
= g_new (GModule
, 1);
472 module
->file_name
= g_strdup (file_name
);
473 #if defined (G_OS_WIN32) && !defined(_WIN64)
474 module
->cp_file_name
= g_locale_from_utf8 (file_name
, -1,
477 module
->handle
= handle
;
478 module
->ref_count
= 1;
479 module
->is_resident
= FALSE
;
480 module
->unload
= NULL
;
481 module
->next
= modules
;
484 /* check initialization */
485 if (g_module_symbol (module
, "g_module_check_init", (gpointer
) &check_init
) && check_init
!= NULL
)
486 check_failed
= check_init (module
);
488 /* we don't call unload() if the initialization check failed. */
490 g_module_symbol (module
, "g_module_unload", (gpointer
) &module
->unload
);
496 error
= g_strconcat ("GModule (",
497 file_name
? file_name
: "NULL",
498 ") initialization check failed: ",
500 g_module_close (module
);
502 g_module_set_error (error
);
506 g_module_set_error (saved_error
);
508 g_free (saved_error
);
511 if (module
!= NULL
&&
512 (module_debug_flags
& G_MODULE_DEBUG_RESIDENT_MODULES
))
513 g_module_make_resident (module
);
515 g_static_rec_mutex_unlock (&g_module_global_lock
);
519 #if defined (G_OS_WIN32) && !defined(_WIN64)
524 g_module_open (const gchar
*file_name
,
527 gchar
*utf8_file_name
= g_locale_to_utf8 (file_name
, -1, NULL
, NULL
, NULL
);
528 GModule
*retval
= g_module_open_utf8 (utf8_file_name
, flags
);
530 g_free (utf8_file_name
);
538 g_module_close (GModule
*module
)
540 SUPPORT_OR_RETURN (FALSE
);
542 g_return_val_if_fail (module
!= NULL
, FALSE
);
543 g_return_val_if_fail (module
->ref_count
> 0, FALSE
);
545 g_static_rec_mutex_lock (&g_module_global_lock
);
549 if (!module
->ref_count
&& !module
->is_resident
&& module
->unload
)
551 GModuleUnload unload
;
553 unload
= module
->unload
;
554 module
->unload
= NULL
;
558 if (!module
->ref_count
&& !module
->is_resident
)
571 last
->next
= node
->next
;
573 modules
= node
->next
;
581 _g_module_close (module
->handle
, FALSE
);
582 g_free (module
->file_name
);
583 #if defined (G_OS_WIN32) && !defined(_WIN64)
584 g_free (module
->cp_file_name
);
589 g_static_rec_mutex_unlock (&g_module_global_lock
);
590 return g_module_error() == NULL
;
594 g_module_make_resident (GModule
*module
)
596 g_return_if_fail (module
!= NULL
);
598 module
->is_resident
= TRUE
;
601 G_CONST_RETURN gchar
*
602 g_module_error (void)
604 return g_static_private_get (&module_error_private
);
608 g_module_symbol (GModule
*module
,
609 const gchar
*symbol_name
,
612 const gchar
*module_error
;
616 SUPPORT_OR_RETURN (FALSE
);
618 g_return_val_if_fail (module
!= NULL
, FALSE
);
619 g_return_val_if_fail (symbol_name
!= NULL
, FALSE
);
620 g_return_val_if_fail (symbol
!= NULL
, FALSE
);
622 g_static_rec_mutex_lock (&g_module_global_lock
);
624 #ifdef G_MODULE_NEED_USCORE
628 name
= g_strconcat ("_", symbol_name
, NULL
);
629 *symbol
= _g_module_symbol (module
->handle
, name
);
632 #else /* !G_MODULE_NEED_USCORE */
633 *symbol
= _g_module_symbol (module
->handle
, symbol_name
);
634 #endif /* !G_MODULE_NEED_USCORE */
636 module_error
= g_module_error ();
641 error
= g_strconcat ("`", symbol_name
, "': ", module_error
, NULL
);
642 g_module_set_error (error
);
647 g_static_rec_mutex_unlock (&g_module_global_lock
);
648 return !module_error
;
651 G_CONST_RETURN gchar
*
652 g_module_name (GModule
*module
)
654 g_return_val_if_fail (module
!= NULL
, NULL
);
656 if (module
== main_module
)
659 return module
->file_name
;
662 #if defined (G_OS_WIN32) && !defined(_WIN64)
666 G_CONST_RETURN gchar
*
667 g_module_name (GModule
*module
)
669 g_return_val_if_fail (module
!= NULL
, NULL
);
671 if (module
== main_module
)
674 return module
->cp_file_name
;
680 g_module_build_path (const gchar
*directory
,
681 const gchar
*module_name
)
683 g_return_val_if_fail (module_name
!= NULL
, NULL
);
685 return _g_module_build_path (directory
, module_name
);