Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / gio / giomodule.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include "config.h"
24
25 /* For the #GDesktopAppInfoLookup macros; since macro deprecation is implemented
26  * in the preprocessor, we need to define this before including glib.h*/
27 #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
28 #define GLIB_DISABLE_DEPRECATION_WARNINGS
29 #endif
30
31 #include <string.h>
32
33 #include "giomodule.h"
34 #include "giomodule-priv.h"
35 #include "glib-private.h"
36 #include "glocalfilemonitor.h"
37 #include "gnativevolumemonitor.h"
38 #include "gproxyresolver.h"
39 #include "gproxy.h"
40 #include "gsettingsbackendinternal.h"
41 #include "ghttpproxy.h"
42 #include "gsocks4proxy.h"
43 #include "gsocks4aproxy.h"
44 #include "gsocks5proxy.h"
45 #include "gtlsbackend.h"
46 #include "gvfs.h"
47 #include "gnotificationbackend.h"
48 #include "ginitable.h"
49 #include "gnetworkmonitor.h"
50 #include "gdebugcontroller.h"
51 #include "gdebugcontrollerdbus.h"
52 #include "gmemorymonitor.h"
53 #include "gmemorymonitorportal.h"
54 #include "gmemorymonitordbus.h"
55 #include "gpowerprofilemonitor.h"
56 #include "gpowerprofilemonitordbus.h"
57 #include "gpowerprofilemonitorportal.h"
58 #ifdef G_OS_WIN32
59 #include "gregistrysettingsbackend.h"
60 #include "giowin32-priv.h"
61 #endif
62 #include <glib/gstdio.h>
63
64 #if defined(G_OS_UNIX) && !defined(__APPLE__)
65 #include "gdesktopappinfo.h"
66 #endif
67 #ifdef HAVE_COCOA
68 #include "gosxappinfo.h"
69 #endif
70
71 #ifdef __APPLE__
72 #include <AvailabilityMacros.h>
73 #endif
74
75 #define __GLIB_H_INSIDE__
76 #include "gconstructor.h"
77 #undef __GLIB_H_INSIDE__
78
79 /**
80  * SECTION:giomodule
81  * @short_description: Loadable GIO Modules
82  * @include: gio/gio.h
83  *
84  * Provides an interface and default functions for loading and unloading 
85  * modules. This is used internally to make GIO extensible, but can also
86  * be used by others to implement module loading.
87  * 
88  **/
89
90 /**
91  * SECTION:extensionpoints
92  * @short_description: Extension Points
93  * @include: gio.h
94  * @see_also: [Extending GIO][extending-gio]
95  *
96  * #GIOExtensionPoint provides a mechanism for modules to extend the
97  * functionality of the library or application that loaded it in an 
98  * organized fashion.  
99  *
100  * An extension point is identified by a name, and it may optionally
101  * require that any implementation must be of a certain type (or derived
102  * thereof). Use g_io_extension_point_register() to register an
103  * extension point, and g_io_extension_point_set_required_type() to
104  * set a required type.
105  *
106  * A module can implement an extension point by specifying the #GType 
107  * that implements the functionality. Additionally, each implementation
108  * of an extension point has a name, and a priority. Use
109  * g_io_extension_point_implement() to implement an extension point.
110  * 
111  *  |[<!-- language="C" -->
112  *  GIOExtensionPoint *ep;
113  *
114  *  // Register an extension point
115  *  ep = g_io_extension_point_register ("my-extension-point");
116  *  g_io_extension_point_set_required_type (ep, MY_TYPE_EXAMPLE);
117  *  ]|
118  *
119  *  |[<!-- language="C" -->
120  *  // Implement an extension point
121  *  G_DEFINE_TYPE (MyExampleImpl, my_example_impl, MY_TYPE_EXAMPLE)
122  *  g_io_extension_point_implement ("my-extension-point",
123  *                                  my_example_impl_get_type (),
124  *                                  "my-example",
125  *                                  10);
126  *  ]|
127  *
128  *  It is up to the code that registered the extension point how
129  *  it uses the implementations that have been associated with it.
130  *  Depending on the use case, it may use all implementations, or
131  *  only the one with the highest priority, or pick a specific
132  *  one by name.
133  *
134  *  To avoid opening all modules just to find out what extension
135  *  points they implement, GIO makes use of a caching mechanism,
136  *  see [gio-querymodules][gio-querymodules].
137  *  You are expected to run this command after installing a
138  *  GIO module.
139  *
140  *  The `GIO_EXTRA_MODULES` environment variable can be used to
141  *  specify additional directories to automatically load modules
142  *  from. This environment variable has the same syntax as the
143  *  `PATH`. If two modules have the same base name in different
144  *  directories, then the latter one will be ignored. If additional
145  *  directories are specified GIO will load modules from the built-in
146  *  directory last.
147  */
148
149 /**
150  * GIOModuleScope:
151  *
152  * Represents a scope for loading IO modules. A scope can be used for blocking
153  * duplicate modules, or blocking a module you don't want to load.
154  *
155  * The scope can be used with g_io_modules_load_all_in_directory_with_scope()
156  * or g_io_modules_scan_all_in_directory_with_scope().
157  *
158  * Since: 2.30
159  */
160 struct _GIOModuleScope {
161   GIOModuleScopeFlags flags;
162   GHashTable *basenames;
163 };
164
165 /**
166  * g_io_module_scope_new:
167  * @flags: flags for the new scope
168  *
169  * Create a new scope for loading of IO modules. A scope can be used for
170  * blocking duplicate modules, or blocking a module you don't want to load.
171  *
172  * Specify the %G_IO_MODULE_SCOPE_BLOCK_DUPLICATES flag to block modules
173  * which have the same base name as a module that has already been seen
174  * in this scope.
175  *
176  * Returns: (transfer full): the new module scope
177  *
178  * Since: 2.30
179  */
180 GIOModuleScope *
181 g_io_module_scope_new (GIOModuleScopeFlags flags)
182 {
183   GIOModuleScope *scope = g_new0 (GIOModuleScope, 1);
184   scope->flags = flags;
185   scope->basenames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
186   return scope;
187 }
188
189 /**
190  * g_io_module_scope_free:
191  * @scope: a module loading scope
192  *
193  * Free a module scope.
194  *
195  * Since: 2.30
196  */
197 void
198 g_io_module_scope_free (GIOModuleScope *scope)
199 {
200   if (!scope)
201     return;
202   g_hash_table_destroy (scope->basenames);
203   g_free (scope);
204 }
205
206 /**
207  * g_io_module_scope_block:
208  * @scope: a module loading scope
209  * @basename: the basename to block
210  *
211  * Block modules with the given @basename from being loaded when
212  * this scope is used with g_io_modules_scan_all_in_directory_with_scope()
213  * or g_io_modules_load_all_in_directory_with_scope().
214  *
215  * Since: 2.30
216  */
217 void
218 g_io_module_scope_block (GIOModuleScope *scope,
219                          const gchar    *basename)
220 {
221   gchar *key;
222
223   g_return_if_fail (scope != NULL);
224   g_return_if_fail (basename != NULL);
225
226   key = g_strdup (basename);
227   g_hash_table_add (scope->basenames, key);
228 }
229
230 static gboolean
231 _g_io_module_scope_contains (GIOModuleScope *scope,
232                              const gchar    *basename)
233 {
234   return g_hash_table_contains (scope->basenames, basename);
235 }
236
237 struct _GIOModule {
238   GTypeModule parent_instance;
239
240   gchar       *filename;
241   GModule     *library;
242   gboolean     initialized; /* The module was loaded at least once */
243
244   void (* load)   (GIOModule *module);
245   void (* unload) (GIOModule *module);
246 };
247
248 struct _GIOModuleClass
249 {
250   GTypeModuleClass parent_class;
251
252 };
253
254 static void      g_io_module_finalize      (GObject      *object);
255 static gboolean  g_io_module_load_module   (GTypeModule  *gmodule);
256 static void      g_io_module_unload_module (GTypeModule  *gmodule);
257
258 /**
259  * GIOExtension:
260  *
261  * #GIOExtension is an opaque data structure and can only be accessed
262  * using the following functions.
263  */
264 struct _GIOExtension {
265   char *name;
266   GType type;
267   gint priority;
268 };
269
270 /**
271  * GIOExtensionPoint:
272  *
273  * #GIOExtensionPoint is an opaque data structure and can only be accessed
274  * using the following functions.
275  */
276 struct _GIOExtensionPoint {
277   GType required_type;
278   char *name;
279   GList *extensions;
280   GList *lazy_load_modules;
281 };
282
283 static GHashTable *extension_points = NULL;
284 G_LOCK_DEFINE_STATIC(extension_points);
285
286 G_DEFINE_TYPE (GIOModule, g_io_module, G_TYPE_TYPE_MODULE)
287
288 static void
289 g_io_module_class_init (GIOModuleClass *class)
290 {
291   GObjectClass     *object_class      = G_OBJECT_CLASS (class);
292   GTypeModuleClass *type_module_class = G_TYPE_MODULE_CLASS (class);
293
294   object_class->finalize     = g_io_module_finalize;
295
296   type_module_class->load    = g_io_module_load_module;
297   type_module_class->unload  = g_io_module_unload_module;
298 }
299
300 static void
301 g_io_module_init (GIOModule *module)
302 {
303 }
304
305 static void
306 g_io_module_finalize (GObject *object)
307 {
308   GIOModule *module = G_IO_MODULE (object);
309
310   g_free (module->filename);
311
312   G_OBJECT_CLASS (g_io_module_parent_class)->finalize (object);
313 }
314
315 static gboolean
316 load_symbols (GIOModule *module)
317 {
318   gchar *name;
319   gchar *load_symname;
320   gchar *unload_symname;
321   gboolean ret;
322
323   name = _g_io_module_extract_name (module->filename);
324   load_symname = g_strconcat ("g_io_", name, "_load", NULL);
325   unload_symname = g_strconcat ("g_io_", name, "_unload", NULL);
326
327   ret = g_module_symbol (module->library,
328                          load_symname,
329                          (gpointer) &module->load) &&
330         g_module_symbol (module->library,
331                          unload_symname,
332                          (gpointer) &module->unload);
333
334   if (!ret)
335     {
336       /* Fallback to old names */
337       ret = g_module_symbol (module->library,
338                              "g_io_module_load",
339                              (gpointer) &module->load) &&
340             g_module_symbol (module->library,
341                              "g_io_module_unload",
342                              (gpointer) &module->unload);
343     }
344
345   g_free (name);
346   g_free (load_symname);
347   g_free (unload_symname);
348
349   return ret;
350 }
351
352 static gboolean
353 g_io_module_load_module (GTypeModule *gmodule)
354 {
355   GIOModule *module = G_IO_MODULE (gmodule);
356   GError *error = NULL;
357
358   if (!module->filename)
359     {
360       g_warning ("GIOModule path not set");
361       return FALSE;
362     }
363
364   module->library = g_module_open_full (module->filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL, &error);
365
366   if (!module->library)
367     {
368       g_printerr ("%s\n", error->message);
369       g_clear_error (&error);
370       return FALSE;
371     }
372
373   /* Make sure that the loaded library contains the required methods */
374   if (!load_symbols (module))
375     {
376       g_printerr ("%s\n", g_module_error ());
377       g_module_close (module->library);
378
379       return FALSE;
380     }
381
382   /* Initialize the loaded module */
383   module->load (module);
384   module->initialized = TRUE;
385
386   return TRUE;
387 }
388
389 static void
390 g_io_module_unload_module (GTypeModule *gmodule)
391 {
392   GIOModule *module = G_IO_MODULE (gmodule);
393
394   module->unload (module);
395
396   g_module_close (module->library);
397   module->library = NULL;
398
399   module->load   = NULL;
400   module->unload = NULL;
401 }
402
403 /**
404  * g_io_module_new:
405  * @filename: (type filename): filename of the shared library module.
406  * 
407  * Creates a new GIOModule that will load the specific
408  * shared library when in use.
409  * 
410  * Returns: a #GIOModule from given @filename, 
411  * or %NULL on error.
412  **/
413 GIOModule *
414 g_io_module_new (const gchar *filename)
415 {
416   GIOModule *module;
417
418   g_return_val_if_fail (filename != NULL, NULL);
419
420   module = g_object_new (G_IO_TYPE_MODULE, NULL);
421   module->filename = g_strdup (filename);
422
423   return module;
424 }
425
426 static gboolean
427 is_valid_module_name (const gchar        *basename,
428                       GIOModuleScope     *scope)
429 {
430   gboolean result;
431
432 #if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
433   #if defined(__APPLE__)
434   if (!g_str_has_prefix (basename, "lib") ||
435       !(g_str_has_suffix (basename, ".so") ||
436         g_str_has_suffix (basename, ".dylib")))
437     return FALSE;
438   #else
439   if (!g_str_has_prefix (basename, "lib") ||
440       !g_str_has_suffix (basename, ".so"))
441     return FALSE;
442   #endif
443 #else
444   if (!g_str_has_suffix (basename, ".dll"))
445     return FALSE;
446 #endif
447
448   result = TRUE;
449   if (scope)
450     {
451       result = _g_io_module_scope_contains (scope, basename) ? FALSE : TRUE;
452       if (result && (scope->flags & G_IO_MODULE_SCOPE_BLOCK_DUPLICATES))
453         g_io_module_scope_block (scope, basename);
454     }
455
456   return result;
457 }
458
459
460 /**
461  * g_io_modules_scan_all_in_directory_with_scope:
462  * @dirname: (type filename): pathname for a directory containing modules
463  *     to scan.
464  * @scope: a scope to use when scanning the modules
465  *
466  * Scans all the modules in the specified directory, ensuring that
467  * any extension point implemented by a module is registered.
468  *
469  * This may not actually load and initialize all the types in each
470  * module, some modules may be lazily loaded and initialized when
471  * an extension point it implements is used with e.g.
472  * g_io_extension_point_get_extensions() or
473  * g_io_extension_point_get_extension_by_name().
474  *
475  * If you need to guarantee that all types are loaded in all the modules,
476  * use g_io_modules_load_all_in_directory().
477  *
478  * Since: 2.30
479  **/
480 void
481 g_io_modules_scan_all_in_directory_with_scope (const char     *dirname,
482                                                GIOModuleScope *scope)
483 {
484   const gchar *name;
485   char *filename;
486   GDir *dir;
487   GStatBuf statbuf;
488   char *data;
489   time_t cache_time;
490   GHashTable *cache;
491
492   if (!g_module_supported ())
493     return;
494
495   dir = g_dir_open (dirname, 0, NULL);
496   if (!dir)
497     return;
498
499   filename = g_build_filename (dirname, "giomodule.cache", NULL);
500
501   cache = NULL;
502   cache_time = 0;
503   if (g_stat (filename, &statbuf) == 0 &&
504       g_file_get_contents (filename, &data, NULL, NULL))
505     {
506       char **lines;
507       int i;
508
509       /* cache_time is the time the cache file was created; we also take
510        * into account the change time because in ostree based systems, all
511        * system file have mtime equal to epoch 0.
512        *
513        * Any file that has a ctime before this was created then and not modified
514        * since then (userspace can't change ctime). Its possible to change the
515        * ctime forward without changing the file content, by e.g.  chmoding the
516        * file, but this is uncommon and will only cause us to not use the cache
517        * so will not cause bugs.
518        */
519       cache_time = MAX(statbuf.st_mtime, statbuf.st_ctime);
520
521       lines = g_strsplit (data, "\n", -1);
522       g_free (data);
523
524       for (i = 0;  lines[i] != NULL; i++)
525         {
526           char *line = lines[i];
527           char *file;
528           char *colon;
529           char **strv_extension_points;
530
531           if (line[0] == '#')
532             continue;
533
534           colon = strchr (line, ':');
535           if (colon == NULL || line == colon)
536             continue; /* Invalid line, ignore */
537
538           *colon = 0; /* terminate filename */
539           file = g_strdup (line);
540           colon++; /* after colon */
541
542           while (g_ascii_isspace (*colon))
543             colon++;
544
545           if (G_UNLIKELY (!cache))
546             cache = g_hash_table_new_full (g_str_hash, g_str_equal,
547                                            g_free, (GDestroyNotify)g_strfreev);
548
549           strv_extension_points = g_strsplit (colon, ",", -1);
550           g_hash_table_insert (cache, file, strv_extension_points);
551         }
552       g_strfreev (lines);
553     }
554
555   while ((name = g_dir_read_name (dir)))
556     {
557       if (is_valid_module_name (name, scope))
558         {
559           GIOExtensionPoint *extension_point;
560           GIOModule *module;
561           gchar *path;
562           char **strv_extension_points = NULL;
563           int i;
564
565           path = g_build_filename (dirname, name, NULL);
566           module = g_io_module_new (path);
567
568           if (cache)
569             strv_extension_points = g_hash_table_lookup (cache, name);
570
571           if (strv_extension_points != NULL &&
572               g_stat (path, &statbuf) == 0 &&
573               statbuf.st_ctime <= cache_time)
574             {
575               /* Lazy load/init the library when first required */
576               for (i = 0; strv_extension_points[i] != NULL; i++)
577                 {
578                   extension_point =
579                     g_io_extension_point_register (strv_extension_points[i]);
580                   extension_point->lazy_load_modules =
581                     g_list_prepend (extension_point->lazy_load_modules,
582                                     module);
583                 }
584             }
585           else
586             {
587               /* Try to load and init types */
588               if (g_type_module_use (G_TYPE_MODULE (module)))
589                 {
590                   g_type_module_unuse (G_TYPE_MODULE (module)); /* Unload */
591                   /* module must remain alive, because the type system keeps weak refs */
592                   g_ignore_leak (module);
593                 }
594               else
595                 {
596                   g_printerr ("Failed to load module: %s\n", path);
597                   g_object_unref (module);
598                 }
599             }
600
601           g_free (path);
602         }
603     }
604
605   g_dir_close (dir);
606
607   if (cache)
608     g_hash_table_destroy (cache);
609
610   g_free (filename);
611 }
612
613 /**
614  * g_io_modules_scan_all_in_directory:
615  * @dirname: (type filename): pathname for a directory containing modules
616  *     to scan.
617  *
618  * Scans all the modules in the specified directory, ensuring that
619  * any extension point implemented by a module is registered.
620  *
621  * This may not actually load and initialize all the types in each
622  * module, some modules may be lazily loaded and initialized when
623  * an extension point it implements is used with e.g.
624  * g_io_extension_point_get_extensions() or
625  * g_io_extension_point_get_extension_by_name().
626  *
627  * If you need to guarantee that all types are loaded in all the modules,
628  * use g_io_modules_load_all_in_directory().
629  *
630  * Since: 2.24
631  **/
632 void
633 g_io_modules_scan_all_in_directory (const char *dirname)
634 {
635   g_io_modules_scan_all_in_directory_with_scope (dirname, NULL);
636 }
637
638 /**
639  * g_io_modules_load_all_in_directory_with_scope:
640  * @dirname: (type filename): pathname for a directory containing modules
641  *     to load.
642  * @scope: a scope to use when scanning the modules.
643  *
644  * Loads all the modules in the specified directory.
645  *
646  * If don't require all modules to be initialized (and thus registering
647  * all gtypes) then you can use g_io_modules_scan_all_in_directory()
648  * which allows delayed/lazy loading of modules.
649  *
650  * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
651  *      from the directory,
652  *      All the modules are loaded into memory, if you want to
653  *      unload them (enabling on-demand loading) you must call
654  *      g_type_module_unuse() on all the modules. Free the list
655  *      with g_list_free().
656  *
657  * Since: 2.30
658  **/
659 GList *
660 g_io_modules_load_all_in_directory_with_scope (const char     *dirname,
661                                                GIOModuleScope *scope)
662 {
663   const gchar *name;
664   GDir        *dir;
665   GList *modules;
666
667   if (!g_module_supported ())
668     return NULL;
669
670   dir = g_dir_open (dirname, 0, NULL);
671   if (!dir)
672     return NULL;
673
674   modules = NULL;
675   while ((name = g_dir_read_name (dir)))
676     {
677       if (is_valid_module_name (name, scope))
678         {
679           GIOModule *module;
680           gchar     *path;
681
682           path = g_build_filename (dirname, name, NULL);
683           module = g_io_module_new (path);
684
685           if (!g_type_module_use (G_TYPE_MODULE (module)))
686             {
687               g_printerr ("Failed to load module: %s\n", path);
688               g_object_unref (module);
689               g_free (path);
690               continue;
691             }
692           
693           g_free (path);
694
695           modules = g_list_prepend (modules, module);
696         }
697     }
698   
699   g_dir_close (dir);
700
701   return modules;
702 }
703
704 /**
705  * g_io_modules_load_all_in_directory:
706  * @dirname: (type filename): pathname for a directory containing modules
707  *     to load.
708  *
709  * Loads all the modules in the specified directory.
710  *
711  * If don't require all modules to be initialized (and thus registering
712  * all gtypes) then you can use g_io_modules_scan_all_in_directory()
713  * which allows delayed/lazy loading of modules.
714  *
715  * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
716  *      from the directory,
717  *      All the modules are loaded into memory, if you want to
718  *      unload them (enabling on-demand loading) you must call
719  *      g_type_module_unuse() on all the modules. Free the list
720  *      with g_list_free().
721  **/
722 GList *
723 g_io_modules_load_all_in_directory (const char *dirname)
724 {
725   return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
726 }
727
728 static gpointer
729 try_class (GIOExtension *extension,
730            guint         is_supported_offset)
731 {
732   GType type = g_io_extension_get_type (extension);
733   typedef gboolean (*verify_func) (void);
734   gpointer class;
735
736   class = g_type_class_ref (type);
737   if (!is_supported_offset || (* G_STRUCT_MEMBER(verify_func, class, is_supported_offset)) ())
738     return class;
739
740   g_type_class_unref (class);
741   return NULL;
742 }
743
744 static void
745 print_help (const char        *envvar,
746             GIOExtensionPoint *ep)
747 {
748   g_print ("Supported arguments for %s environment variable:\n", envvar);
749
750   if (g_io_extension_point_get_extensions (ep) == NULL)
751     g_print (" (none)\n");
752   else
753     {
754       GList *l;
755       GIOExtension *extension;
756       gsize width = 0;
757
758       for (l = g_io_extension_point_get_extensions (ep); l; l = l->next)
759         {
760           extension = l->data;
761           width = MAX (width, strlen (g_io_extension_get_name (extension)));
762         }
763
764       for (l = g_io_extension_point_get_extensions (ep); l; l = l->next)
765         {
766           extension = l->data;
767
768           g_print (" %*s - %d\n", (int) MIN (width, G_MAXINT),
769                    g_io_extension_get_name (extension),
770                    g_io_extension_get_priority (extension));
771         }
772     }
773 }
774
775 /**
776  * _g_io_module_get_default_type:
777  * @extension_point: the name of an extension point
778  * @envvar: (nullable): the name of an environment variable to
779  *     override the default implementation.
780  * @is_supported_offset: a vtable offset, or zero
781  *
782  * Retrieves the default class implementing @extension_point.
783  *
784  * If @envvar is not %NULL, and the environment variable with that
785  * name is set, then the implementation it specifies will be tried
786  * first. After that, or if @envvar is not set, all other
787  * implementations will be tried in order of decreasing priority.
788  *
789  * If @is_supported_offset is non-zero, then it is the offset into the
790  * class vtable at which there is a function that takes no arguments and
791  * returns a boolean.  This function will be called on each candidate
792  * implementation to check if it is actually usable or not.
793  *
794  * The result is cached after it is generated the first time, and
795  * the function is thread-safe.
796  *
797  * Returns: (transfer none): the type to instantiate to implement
798  *     @extension_point, or %G_TYPE_INVALID if there are no usable
799  *     implementations.
800  */
801 GType
802 _g_io_module_get_default_type (const gchar *extension_point,
803                                const gchar *envvar,
804                                guint        is_supported_offset)
805 {
806   static GRecMutex default_modules_lock;
807   static GHashTable *default_modules;
808   const char *use_this;
809   GList *l;
810   GIOExtensionPoint *ep;
811   GIOExtension *extension, *preferred;
812   gpointer impl;
813
814   g_rec_mutex_lock (&default_modules_lock);
815   if (default_modules)
816     {
817       gpointer key;
818
819       if (g_hash_table_lookup_extended (default_modules, extension_point, &key, &impl))
820         {
821           g_rec_mutex_unlock (&default_modules_lock);
822           return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
823         }
824     }
825   else
826     {
827       default_modules = g_hash_table_new (g_str_hash, g_str_equal);
828     }
829
830   _g_io_modules_ensure_loaded ();
831   ep = g_io_extension_point_lookup (extension_point);
832
833   if (!ep)
834     {
835       g_warn_if_reached ();
836       g_rec_mutex_unlock (&default_modules_lock);
837       return G_TYPE_INVALID;
838     }
839
840   /* It’s OK to query the environment here, even when running as setuid, because
841    * it only allows a choice between existing already-loaded modules. No new
842    * code is loaded based on the environment variable value. */
843   use_this = envvar ? g_getenv (envvar) : NULL;
844   if (g_strcmp0 (use_this, "help") == 0)
845     {
846       print_help (envvar, ep);
847       use_this = NULL;
848     }
849
850   if (use_this)
851     {
852       preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
853       if (preferred)
854         {
855           impl = try_class (preferred, is_supported_offset);
856           if (impl)
857             goto done;
858         }
859       else
860         g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
861     }
862   else
863     preferred = NULL;
864
865   for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
866     {
867       extension = l->data;
868       if (extension == preferred)
869         continue;
870
871       impl = try_class (extension, is_supported_offset);
872       if (impl)
873         goto done;
874     }
875
876   impl = NULL;
877
878  done:
879   g_hash_table_insert (default_modules, g_strdup (extension_point), impl);
880   g_rec_mutex_unlock (&default_modules_lock);
881
882   return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
883 }
884
885 static gpointer
886 try_implementation (const char           *extension_point,
887                     GIOExtension         *extension,
888                     GIOModuleVerifyFunc   verify_func)
889 {
890   GType type = g_io_extension_get_type (extension);
891   gpointer impl;
892
893   if (g_type_is_a (type, G_TYPE_INITABLE))
894     {
895       GError *error = NULL;
896
897       impl = g_initable_new (type, NULL, &error, NULL);
898       if (impl)
899         return impl;
900
901       g_debug ("Failed to initialize %s (%s) for %s: %s",
902                g_io_extension_get_name (extension),
903                g_type_name (type),
904                extension_point,
905                error ? error->message : "");
906       g_clear_error (&error);
907       return NULL;
908     }
909   else
910     {
911       impl = g_object_new (type, NULL);
912       if (!verify_func || verify_func (impl))
913         return impl;
914
915       g_object_unref (impl);
916       return NULL;
917     }
918 }
919
920 static void
921 weak_ref_free (GWeakRef *weak_ref)
922 {
923   g_weak_ref_clear (weak_ref);
924   g_free (weak_ref);
925 }
926
927 /**
928  * _g_io_module_get_default:
929  * @extension_point: the name of an extension point
930  * @envvar: (nullable): the name of an environment variable to
931  *     override the default implementation.
932  * @verify_func: (nullable): a function to call to verify that
933  *     a given implementation is usable in the current environment.
934  *
935  * Retrieves the default object implementing @extension_point.
936  *
937  * If @envvar is not %NULL, and the environment variable with that
938  * name is set, then the implementation it specifies will be tried
939  * first. After that, or if @envvar is not set, all other
940  * implementations will be tried in order of decreasing priority.
941  *
942  * If an extension point implementation implements #GInitable, then
943  * that implementation will only be used if it initializes
944  * successfully. Otherwise, if @verify_func is not %NULL, then it will
945  * be called on each candidate implementation after construction, to
946  * check if it is actually usable or not.
947  *
948  * The result is cached after it is generated the first time (but the cache does
949  * not keep a strong reference to the object), and
950  * the function is thread-safe.
951  *
952  * Returns: (transfer full) (nullable): an object implementing
953  *     @extension_point, or %NULL if there are no usable
954  *     implementations.
955  */
956 gpointer
957 _g_io_module_get_default (const gchar         *extension_point,
958                           const gchar         *envvar,
959                           GIOModuleVerifyFunc  verify_func)
960 {
961   static GRecMutex default_modules_lock;
962   static GHashTable *default_modules;
963   const char *use_this;
964   GList *l;
965   GIOExtensionPoint *ep;
966   GIOExtension *extension = NULL, *preferred;
967   gpointer impl, value;
968   GWeakRef *impl_weak_ref = NULL;
969
970   g_rec_mutex_lock (&default_modules_lock);
971   if (default_modules)
972     {
973       if (g_hash_table_lookup_extended (default_modules, extension_point,
974                                         NULL, &value))
975         {
976           /* Don’t debug here, since we’re returning a cached object which was
977            * already printed earlier. */
978           impl_weak_ref = value;
979           impl = g_weak_ref_get (impl_weak_ref);
980
981           /* If the object has been finalised (impl == NULL), fall through and
982            * instantiate a new one. */
983           if (impl != NULL)
984             {
985               g_rec_mutex_unlock (&default_modules_lock);
986               return g_steal_pointer (&impl);
987             }
988         }
989     }
990   else
991     {
992       default_modules = g_hash_table_new_full (g_str_hash, g_str_equal,
993                                                g_free, (GDestroyNotify) weak_ref_free);
994     }
995
996   _g_io_modules_ensure_loaded ();
997   ep = g_io_extension_point_lookup (extension_point);
998
999   if (!ep)
1000     {
1001       g_debug ("%s: Failed to find extension point â€˜%s’",
1002                G_STRFUNC, extension_point);
1003       g_warn_if_reached ();
1004       g_rec_mutex_unlock (&default_modules_lock);
1005       return NULL;
1006     }
1007
1008   /* It’s OK to query the environment here, even when running as setuid, because
1009    * it only allows a choice between existing already-loaded modules. No new
1010    * code is loaded based on the environment variable value. */
1011   use_this = envvar ? g_getenv (envvar) : NULL;
1012   if (g_strcmp0 (use_this, "help") == 0)
1013     {
1014       print_help (envvar, ep);
1015       use_this = NULL;
1016     }
1017
1018   if (use_this)
1019     {
1020       preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
1021       if (preferred)
1022         {
1023           impl = try_implementation (extension_point, preferred, verify_func);
1024           extension = preferred;
1025           if (impl)
1026             goto done;
1027         }
1028       else
1029         g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
1030     }
1031   else
1032     preferred = NULL;
1033
1034   for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
1035     {
1036       extension = l->data;
1037       if (extension == preferred)
1038         continue;
1039
1040       impl = try_implementation (extension_point, extension, verify_func);
1041       if (impl)
1042         goto done;
1043     }
1044
1045   impl = NULL;
1046
1047  done:
1048   if (impl_weak_ref == NULL)
1049     {
1050       impl_weak_ref = g_new0 (GWeakRef, 1);
1051       g_weak_ref_init (impl_weak_ref, impl);
1052       g_hash_table_insert (default_modules, g_strdup (extension_point),
1053                            g_steal_pointer (&impl_weak_ref));
1054     }
1055   else
1056     {
1057       g_weak_ref_set (impl_weak_ref, impl);
1058     }
1059
1060   g_rec_mutex_unlock (&default_modules_lock);
1061
1062   if (impl != NULL)
1063     {
1064       g_assert (extension != NULL);
1065       g_debug ("%s: Found default implementation %s (%s) for â€˜%s’",
1066                G_STRFUNC, g_io_extension_get_name (extension),
1067                G_OBJECT_TYPE_NAME (impl), extension_point);
1068     }
1069   else
1070     g_debug ("%s: Failed to find default implementation for â€˜%s’",
1071              G_STRFUNC, extension_point);
1072
1073   return g_steal_pointer (&impl);
1074 }
1075
1076 extern GType g_inotify_file_monitor_get_type (void);
1077 extern GType g_kqueue_file_monitor_get_type (void);
1078 extern GType g_win32_file_monitor_get_type (void);
1079
1080 extern GType _g_unix_volume_monitor_get_type (void);
1081 extern GType _g_local_vfs_get_type (void);
1082
1083 extern GType _g_win32_volume_monitor_get_type (void);
1084 extern GType _g_winhttp_vfs_get_type (void);
1085
1086 extern GType _g_dummy_proxy_resolver_get_type (void);
1087 extern GType _g_dummy_tls_backend_get_type (void);
1088 extern GType g_network_monitor_base_get_type (void);
1089 #ifdef HAVE_NETLINK
1090 extern GType _g_network_monitor_netlink_get_type (void);
1091 extern GType _g_network_monitor_nm_get_type (void);
1092 #endif
1093
1094 extern GType g_debug_controller_dbus_get_type (void);
1095 extern GType g_memory_monitor_dbus_get_type (void);
1096 extern GType g_memory_monitor_portal_get_type (void);
1097 extern GType g_memory_monitor_win32_get_type (void);
1098 extern GType g_power_profile_monitor_dbus_get_type (void);
1099
1100 #ifdef G_OS_UNIX
1101 extern GType g_fdo_notification_backend_get_type (void);
1102 extern GType g_gtk_notification_backend_get_type (void);
1103 extern GType g_portal_notification_backend_get_type (void);
1104 extern GType g_proxy_resolver_portal_get_type (void);
1105 extern GType g_network_monitor_portal_get_type (void);
1106 #endif
1107
1108 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1109 extern GType g_cocoa_notification_backend_get_type (void);
1110 #endif
1111
1112 #ifdef G_PLATFORM_WIN32
1113 extern GType g_win32_notification_backend_get_type (void);
1114
1115 #include <windows.h>
1116 extern GType _g_win32_network_monitor_get_type (void);
1117
1118 static HMODULE gio_dll = NULL;
1119
1120 #ifndef GLIB_STATIC_COMPILATION
1121
1122 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
1123                      DWORD     fdwReason,
1124                      LPVOID    lpvReserved);
1125
1126 BOOL WINAPI
1127 DllMain (HINSTANCE hinstDLL,
1128          DWORD     fdwReason,
1129          LPVOID    lpvReserved)
1130 {
1131   if (fdwReason == DLL_PROCESS_ATTACH)
1132     {
1133       gio_dll = hinstDLL;
1134       gio_win32_appinfo_init (FALSE);
1135     }
1136
1137   return TRUE;
1138 }
1139
1140 #elif defined(G_HAS_CONSTRUCTORS) /* && G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION */
1141 extern void glib_win32_init (void);
1142 extern void gobject_win32_init (void);
1143
1144 #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
1145 #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(giomodule_init_ctor)
1146 #endif
1147
1148 G_DEFINE_CONSTRUCTOR (giomodule_init_ctor)
1149
1150 static void
1151 giomodule_init_ctor (void)
1152 {
1153   /* When built dynamically, module initialization is done through DllMain
1154    * function which is called when the dynamic library is loaded by the glib
1155    * module AFTER loading gobject. So, in dynamic configuration glib and
1156    * gobject are always initialized BEFORE gio.
1157    *
1158    * When built statically, initialization mechanism relies on hooking
1159    * functions to the CRT section directly at compilation time. As we don't
1160    * control how each compilation unit will be built and in which order, we
1161    * obtain the same kind of issue as the "static initialization order fiasco".
1162    * In this case, we must ensure explicitly that glib and gobject are always
1163    * well initialized BEFORE gio.
1164    */
1165   glib_win32_init ();
1166   gobject_win32_init ();
1167   gio_win32_appinfo_init (FALSE);
1168 }
1169
1170 #else /* G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION && !G_HAS_CONSTRUCTORS */
1171 #error Your platform/compiler is missing constructor support
1172 #endif /* GLIB_STATIC_COMPILATION */
1173
1174 void *
1175 _g_io_win32_get_module (void)
1176 {
1177   if (!gio_dll)
1178     GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
1179                         GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
1180                         (const char *) _g_io_win32_get_module,
1181                         &gio_dll);
1182   return gio_dll;
1183 }
1184
1185 #endif /* G_PLATFORM_WIN32 */
1186
1187 void
1188 _g_io_modules_ensure_extension_points_registered (void)
1189 {
1190   static gsize registered_extensions = FALSE;
1191   GIOExtensionPoint *ep;
1192
1193   if (g_once_init_enter (&registered_extensions))
1194     {
1195 #if defined(G_OS_UNIX) && !defined(__APPLE__)
1196 #if !GLIB_CHECK_VERSION (3, 0, 0)
1197       ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
1198       g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LOOKUP);
1199 #endif
1200 #endif
1201
1202       ep = g_io_extension_point_register (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME);
1203       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
1204
1205       ep = g_io_extension_point_register (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME);
1206       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
1207
1208       ep = g_io_extension_point_register (G_VOLUME_MONITOR_EXTENSION_POINT_NAME);
1209       g_io_extension_point_set_required_type (ep, G_TYPE_VOLUME_MONITOR);
1210       
1211       ep = g_io_extension_point_register (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME);
1212       g_io_extension_point_set_required_type (ep, G_TYPE_NATIVE_VOLUME_MONITOR);
1213       
1214       ep = g_io_extension_point_register (G_VFS_EXTENSION_POINT_NAME);
1215       g_io_extension_point_set_required_type (ep, G_TYPE_VFS);
1216
1217       ep = g_io_extension_point_register ("gsettings-backend");
1218       g_io_extension_point_set_required_type (ep, G_TYPE_OBJECT);
1219
1220       ep = g_io_extension_point_register (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
1221       g_io_extension_point_set_required_type (ep, G_TYPE_PROXY_RESOLVER);
1222
1223       ep = g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME);
1224       g_io_extension_point_set_required_type (ep, G_TYPE_PROXY);
1225
1226       ep = g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
1227       g_io_extension_point_set_required_type (ep, G_TYPE_TLS_BACKEND);
1228
1229       ep = g_io_extension_point_register (G_NETWORK_MONITOR_EXTENSION_POINT_NAME);
1230       g_io_extension_point_set_required_type (ep, G_TYPE_NETWORK_MONITOR);
1231
1232       ep = g_io_extension_point_register (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME);
1233       g_io_extension_point_set_required_type (ep, G_TYPE_NOTIFICATION_BACKEND);
1234
1235       ep = g_io_extension_point_register (G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME);
1236       g_io_extension_point_set_required_type (ep, G_TYPE_DEBUG_CONTROLLER);
1237
1238       ep = g_io_extension_point_register (G_MEMORY_MONITOR_EXTENSION_POINT_NAME);
1239       g_io_extension_point_set_required_type (ep, G_TYPE_MEMORY_MONITOR);
1240
1241       ep = g_io_extension_point_register (G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME);
1242       g_io_extension_point_set_required_type (ep, G_TYPE_POWER_PROFILE_MONITOR);
1243
1244       g_once_init_leave (&registered_extensions, TRUE);
1245     }
1246 }
1247
1248 static gchar *
1249 get_gio_module_dir (void)
1250 {
1251   gchar *module_dir;
1252   gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
1253
1254   /* If running as setuid, loading modules from an arbitrary directory
1255    * controlled by the unprivileged user who is running the program could allow
1256    * for execution of arbitrary code (in constructors in modules).
1257    * Don’t allow it.
1258    *
1259    * If a setuid program somehow needs to load additional GIO modules, it should
1260    * explicitly call g_io_modules_scan_all_in_directory(). */
1261   module_dir = !is_setuid ? g_strdup (g_getenv ("GIO_MODULE_DIR")) : NULL;
1262   if (module_dir == NULL)
1263     {
1264 #ifdef G_OS_WIN32
1265       gchar *install_dir;
1266
1267       install_dir = g_win32_get_package_installation_directory_of_module (gio_dll);
1268       module_dir = g_build_filename (install_dir,
1269                                      "lib", "gio", "modules",
1270                                      NULL);
1271       g_free (install_dir);
1272 #else
1273       module_dir = g_strdup (GIO_MODULE_DIR);
1274 #ifdef __APPLE__
1275 #include "TargetConditionals.h"
1276 /* Only auto-relocate on macOS, not watchOS etc; older macOS SDKs only define TARGET_OS_MAC */
1277 #if (defined (TARGET_OS_OSX) && TARGET_OS_OSX) || \
1278      (!defined (TARGET_OS_OSX) && defined (TARGET_OS_MAC) && TARGET_OS_MAC)
1279 #include <dlfcn.h>
1280       {
1281         g_autofree gchar *path = NULL;
1282         g_autofree gchar *possible_dir = NULL;
1283         Dl_info info;
1284
1285         if (dladdr (get_gio_module_dir, &info))
1286           {
1287             /* Gets path to the PREFIX/lib directory */
1288             path = g_path_get_dirname (info.dli_fname);
1289             possible_dir = g_build_filename (path, "gio", "modules", NULL);
1290             if (g_file_test (possible_dir, G_FILE_TEST_IS_DIR))
1291               {
1292                 g_free (module_dir);
1293                 module_dir = g_steal_pointer (&possible_dir);
1294               }
1295           }
1296       }
1297 #endif
1298 #endif
1299 #endif
1300     }
1301
1302   return module_dir;
1303 }
1304
1305 void
1306 _g_io_modules_ensure_loaded (void)
1307 {
1308   static gsize loaded_dirs = FALSE;
1309   const char *module_path;
1310   GIOModuleScope *scope;
1311
1312   _g_io_modules_ensure_extension_points_registered ();
1313
1314   if (g_once_init_enter (&loaded_dirs))
1315     {
1316       gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
1317       gchar *module_dir;
1318
1319       scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
1320
1321       /* First load any overrides, extras (but not if running as setuid!) */
1322       module_path = !is_setuid ? g_getenv ("GIO_EXTRA_MODULES") : NULL;
1323       if (module_path)
1324         {
1325           gchar **paths;
1326           int i;
1327
1328           paths = g_strsplit (module_path, G_SEARCHPATH_SEPARATOR_S, 0);
1329
1330           for (i = 0; paths[i] != NULL; i++)
1331             {
1332               g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
1333             }
1334
1335           g_strfreev (paths);
1336         }
1337
1338       /* Then load the compiled in path */
1339       module_dir = get_gio_module_dir ();
1340
1341       g_io_modules_scan_all_in_directory_with_scope (module_dir, scope);
1342       g_free (module_dir);
1343
1344       g_io_module_scope_free (scope);
1345
1346       /* Initialize types from built-in "modules" */
1347       g_type_ensure (g_null_settings_backend_get_type ());
1348       g_type_ensure (g_memory_settings_backend_get_type ());
1349       g_type_ensure (g_keyfile_settings_backend_get_type ());
1350       g_type_ensure (g_power_profile_monitor_dbus_get_type ());
1351 #if defined(HAVE_INOTIFY_INIT1)
1352       g_type_ensure (g_inotify_file_monitor_get_type ());
1353 #endif
1354 #if defined(HAVE_KQUEUE)
1355       g_type_ensure (g_kqueue_file_monitor_get_type ());
1356 #endif
1357 #ifdef G_OS_WIN32
1358       g_type_ensure (_g_win32_volume_monitor_get_type ());
1359       g_type_ensure (g_win32_file_monitor_get_type ());
1360       g_type_ensure (g_registry_settings_backend_get_type ());
1361 #endif
1362 #ifdef HAVE_COCOA
1363       g_type_ensure (g_nextstep_settings_backend_get_type ());
1364       g_type_ensure (g_osx_app_info_get_type ());
1365 #endif
1366 #ifdef G_OS_UNIX
1367       g_type_ensure (_g_unix_volume_monitor_get_type ());
1368       g_type_ensure (g_debug_controller_dbus_get_type ());
1369       g_type_ensure (g_fdo_notification_backend_get_type ());
1370       g_type_ensure (g_gtk_notification_backend_get_type ());
1371       g_type_ensure (g_portal_notification_backend_get_type ());
1372       g_type_ensure (g_memory_monitor_dbus_get_type ());
1373       g_type_ensure (g_memory_monitor_portal_get_type ());
1374       g_type_ensure (g_network_monitor_portal_get_type ());
1375       g_type_ensure (g_power_profile_monitor_portal_get_type ());
1376       g_type_ensure (g_proxy_resolver_portal_get_type ());
1377 #endif
1378 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1379       g_type_ensure (g_cocoa_notification_backend_get_type ());
1380 #endif
1381 #ifdef G_OS_WIN32
1382       g_type_ensure (g_win32_notification_backend_get_type ());
1383       g_type_ensure (_g_winhttp_vfs_get_type ());
1384       g_type_ensure (g_memory_monitor_win32_get_type ());
1385 #endif
1386       g_type_ensure (_g_local_vfs_get_type ());
1387       g_type_ensure (_g_dummy_proxy_resolver_get_type ());
1388       g_type_ensure (_g_http_proxy_get_type ());
1389       g_type_ensure (_g_https_proxy_get_type ());
1390       g_type_ensure (_g_socks4a_proxy_get_type ());
1391       g_type_ensure (_g_socks4_proxy_get_type ());
1392       g_type_ensure (_g_socks5_proxy_get_type ());
1393       g_type_ensure (_g_dummy_tls_backend_get_type ());
1394       g_type_ensure (g_network_monitor_base_get_type ());
1395 #ifdef HAVE_NETLINK
1396       g_type_ensure (_g_network_monitor_netlink_get_type ());
1397       g_type_ensure (_g_network_monitor_nm_get_type ());
1398 #endif
1399 #ifdef G_OS_WIN32
1400       g_type_ensure (_g_win32_network_monitor_get_type ());
1401 #endif
1402
1403       g_once_init_leave (&loaded_dirs, TRUE);
1404     }
1405 }
1406
1407 static void
1408 g_io_extension_point_free (GIOExtensionPoint *ep)
1409 {
1410   g_free (ep->name);
1411   g_free (ep);
1412 }
1413
1414 /**
1415  * g_io_extension_point_register:
1416  * @name: The name of the extension point
1417  *
1418  * Registers an extension point.
1419  *
1420  * Returns: (transfer none): the new #GIOExtensionPoint. This object is
1421  *    owned by GIO and should not be freed.
1422  */
1423 GIOExtensionPoint *
1424 g_io_extension_point_register (const char *name)
1425 {
1426   GIOExtensionPoint *ep;
1427   
1428   G_LOCK (extension_points);
1429   if (extension_points == NULL)
1430     extension_points = g_hash_table_new_full (g_str_hash,
1431                                               g_str_equal,
1432                                               NULL,
1433                                               (GDestroyNotify)g_io_extension_point_free);
1434
1435   ep = g_hash_table_lookup (extension_points, name);
1436   if (ep != NULL)
1437     {
1438       G_UNLOCK (extension_points);
1439       return ep;
1440     }
1441
1442   ep = g_new0 (GIOExtensionPoint, 1);
1443   ep->name = g_strdup (name);
1444   
1445   g_hash_table_insert (extension_points, ep->name, ep);
1446   
1447   G_UNLOCK (extension_points);
1448
1449   return ep;
1450 }
1451
1452 /**
1453  * g_io_extension_point_lookup:
1454  * @name: the name of the extension point
1455  *
1456  * Looks up an existing extension point.
1457  *
1458  * Returns: (transfer none): the #GIOExtensionPoint, or %NULL if there
1459  *    is no registered extension point with the given name.
1460  */
1461 GIOExtensionPoint *
1462 g_io_extension_point_lookup (const char *name)
1463 {
1464   GIOExtensionPoint *ep;
1465
1466   G_LOCK (extension_points);
1467   ep = NULL;
1468   if (extension_points != NULL)
1469     ep = g_hash_table_lookup (extension_points, name);
1470   
1471   G_UNLOCK (extension_points);
1472
1473   return ep;
1474   
1475 }
1476
1477 /**
1478  * g_io_extension_point_set_required_type:
1479  * @extension_point: a #GIOExtensionPoint
1480  * @type: the #GType to require
1481  *
1482  * Sets the required type for @extension_point to @type. 
1483  * All implementations must henceforth have this type.
1484  */
1485 void
1486 g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
1487                                         GType              type)
1488 {
1489   extension_point->required_type = type;
1490 }
1491
1492 /**
1493  * g_io_extension_point_get_required_type:
1494  * @extension_point: a #GIOExtensionPoint
1495  *
1496  * Gets the required type for @extension_point.
1497  *
1498  * Returns: the #GType that all implementations must have, 
1499  *   or %G_TYPE_INVALID if the extension point has no required type
1500  */
1501 GType
1502 g_io_extension_point_get_required_type (GIOExtensionPoint *extension_point)
1503 {
1504   return extension_point->required_type;
1505 }
1506
1507 static void
1508 lazy_load_modules (GIOExtensionPoint *extension_point)
1509 {
1510   GIOModule *module;
1511   GList *l;
1512
1513   for (l = extension_point->lazy_load_modules; l != NULL; l = l->next)
1514     {
1515       module = l->data;
1516
1517       if (!module->initialized)
1518         {
1519           if (g_type_module_use (G_TYPE_MODULE (module)))
1520             g_type_module_unuse (G_TYPE_MODULE (module)); /* Unload */
1521           else
1522             g_printerr ("Failed to load module: %s\n",
1523                         module->filename);
1524         }
1525     }
1526 }
1527
1528 /**
1529  * g_io_extension_point_get_extensions:
1530  * @extension_point: a #GIOExtensionPoint
1531  *
1532  * Gets a list of all extensions that implement this extension point.
1533  * The list is sorted by priority, beginning with the highest priority.
1534  *
1535  * Returns: (element-type GIOExtension) (transfer none): a #GList of
1536  *     #GIOExtensions. The list is owned by GIO and should not be
1537  *     modified.
1538  */
1539 GList *
1540 g_io_extension_point_get_extensions (GIOExtensionPoint *extension_point)
1541 {
1542   g_return_val_if_fail (extension_point != NULL, NULL);
1543
1544   lazy_load_modules (extension_point);
1545   return extension_point->extensions;
1546 }
1547
1548 /**
1549  * g_io_extension_point_get_extension_by_name:
1550  * @extension_point: a #GIOExtensionPoint
1551  * @name: the name of the extension to get
1552  *
1553  * Finds a #GIOExtension for an extension point by name.
1554  *
1555  * Returns: (transfer none): the #GIOExtension for @extension_point that has the
1556  *    given name, or %NULL if there is no extension with that name
1557  */
1558 GIOExtension *
1559 g_io_extension_point_get_extension_by_name (GIOExtensionPoint *extension_point,
1560                                             const char        *name)
1561 {
1562   GList *l;
1563
1564   g_return_val_if_fail (name != NULL, NULL);
1565
1566   lazy_load_modules (extension_point);
1567   for (l = extension_point->extensions; l != NULL; l = l->next)
1568     {
1569       GIOExtension *e = l->data;
1570
1571       if (e->name != NULL &&
1572           strcmp (e->name, name) == 0)
1573         return e;
1574     }
1575   
1576   return NULL;
1577 }
1578
1579 static gint
1580 extension_prio_compare (gconstpointer  a,
1581                         gconstpointer  b)
1582 {
1583   const GIOExtension *extension_a = a, *extension_b = b;
1584
1585   if (extension_a->priority > extension_b->priority)
1586     return -1;
1587
1588   if (extension_b->priority > extension_a->priority)
1589     return 1;
1590
1591   return 0;
1592 }
1593
1594 /**
1595  * g_io_extension_point_implement:
1596  * @extension_point_name: the name of the extension point
1597  * @type: the #GType to register as extension 
1598  * @extension_name: the name for the extension
1599  * @priority: the priority for the extension
1600  *
1601  * Registers @type as extension for the extension point with name
1602  * @extension_point_name. 
1603  *
1604  * If @type has already been registered as an extension for this 
1605  * extension point, the existing #GIOExtension object is returned.
1606  *
1607  * Returns: (transfer none): a #GIOExtension object for #GType
1608  */
1609 GIOExtension *
1610 g_io_extension_point_implement (const char *extension_point_name,
1611                                 GType       type,
1612                                 const char *extension_name,
1613                                 gint        priority)
1614 {
1615   GIOExtensionPoint *extension_point;
1616   GIOExtension *extension;
1617   GList *l;
1618
1619   g_return_val_if_fail (extension_point_name != NULL, NULL);
1620
1621   extension_point = g_io_extension_point_lookup (extension_point_name);
1622   if (extension_point == NULL)
1623     {
1624       g_warning ("Tried to implement non-registered extension point %s", extension_point_name);
1625       return NULL;
1626     }
1627   
1628   if (extension_point->required_type != 0 &&
1629       !g_type_is_a (type, extension_point->required_type))
1630     {
1631       g_warning ("Tried to register an extension of the type %s to extension point %s. "
1632                  "Expected type is %s.",
1633                  g_type_name (type),
1634                  extension_point_name, 
1635                  g_type_name (extension_point->required_type));
1636       return NULL;
1637     }      
1638
1639   /* It's safe to register the same type multiple times */
1640   for (l = extension_point->extensions; l != NULL; l = l->next)
1641     {
1642       extension = l->data;
1643       if (extension->type == type)
1644         return extension;
1645     }
1646   
1647   extension = g_slice_new0 (GIOExtension);
1648   extension->type = type;
1649   extension->name = g_strdup (extension_name);
1650   extension->priority = priority;
1651   
1652   extension_point->extensions = g_list_insert_sorted (extension_point->extensions,
1653                                                       extension, extension_prio_compare);
1654   
1655   return extension;
1656 }
1657
1658 /**
1659  * g_io_extension_ref_class:
1660  * @extension: a #GIOExtension
1661  *
1662  * Gets a reference to the class for the type that is 
1663  * associated with @extension.
1664  *
1665  * Returns: (transfer full): the #GTypeClass for the type of @extension
1666  */
1667 GTypeClass *
1668 g_io_extension_ref_class (GIOExtension *extension)
1669 {
1670   return g_type_class_ref (extension->type);
1671 }
1672
1673 /**
1674  * g_io_extension_get_type:
1675  * @extension: a #GIOExtension
1676  *
1677  * Gets the type associated with @extension.
1678  *
1679  * Returns: the type of @extension
1680  */
1681 GType
1682 g_io_extension_get_type (GIOExtension *extension)
1683 {
1684   return extension->type;
1685 }
1686
1687 /**
1688  * g_io_extension_get_name:
1689  * @extension: a #GIOExtension
1690  *
1691  * Gets the name under which @extension was registered.
1692  *
1693  * Note that the same type may be registered as extension
1694  * for multiple extension points, under different names.
1695  *
1696  * Returns: the name of @extension.
1697  */
1698 const char *
1699 g_io_extension_get_name (GIOExtension *extension)
1700 {
1701   return extension->name;
1702 }
1703
1704 /**
1705  * g_io_extension_get_priority:
1706  * @extension: a #GIOExtension
1707  *
1708  * Gets the priority with which @extension was registered.
1709  *
1710  * Returns: the priority of @extension
1711  */
1712 gint
1713 g_io_extension_get_priority (GIOExtension *extension)
1714 {
1715   return extension->priority;
1716 }