giomodule test: force shared library build
[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  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <string.h>
26
27 #include "giomodule.h"
28 #include "giomodule-priv.h"
29 #include "glocalfilemonitor.h"
30 #include "glocaldirectorymonitor.h"
31 #include "gnativevolumemonitor.h"
32 #include "gproxyresolver.h"
33 #include "gproxy.h"
34 #include "gsettingsbackendinternal.h"
35 #include "gsocks4proxy.h"
36 #include "gsocks4aproxy.h"
37 #include "gsocks5proxy.h"
38 #include "gtlsbackend.h"
39 #include "gvfs.h"
40 #include "gnotificationbackend.h"
41 #ifdef G_OS_WIN32
42 #include "gregistrysettingsbackend.h"
43 #endif
44 #include <glib/gstdio.h>
45
46 #ifdef G_OS_UNIX
47 #include "gdesktopappinfo.h"
48 #endif
49
50 /**
51  * SECTION:giomodule
52  * @short_description: Loadable GIO Modules
53  * @include: gio/gio.h
54  *
55  * Provides an interface and default functions for loading and unloading 
56  * modules. This is used internally to make GIO extensible, but can also
57  * be used by others to implement module loading.
58  * 
59  **/
60
61 /**
62  * SECTION:extensionpoints
63  * @short_description: Extension Points
64  * @include: gio.h
65  * @see_also: <link linkend="extending-gio">Extending GIO</link>
66  *
67  * #GIOExtensionPoint provides a mechanism for modules to extend the
68  * functionality of the library or application that loaded it in an 
69  * organized fashion.  
70  *
71  * An extension point is identified by a name, and it may optionally
72  * require that any implementation must be of a certain type (or derived
73  * thereof). Use g_io_extension_point_register() to register an
74  * extension point, and g_io_extension_point_set_required_type() to
75  * set a required type.
76  *
77  * A module can implement an extension point by specifying the #GType 
78  * that implements the functionality. Additionally, each implementation
79  * of an extension point has a name, and a priority. Use
80  * g_io_extension_point_implement() to implement an extension point.
81  * 
82  *  |[
83  *  GIOExtensionPoint *ep;
84  *
85  *  /&ast; Register an extension point &ast;/
86  *  ep = g_io_extension_point_register ("my-extension-point");
87  *  g_io_extension_point_set_required_type (ep, MY_TYPE_EXAMPLE);
88  *  ]|
89  *
90  *  |[
91  *  /&ast; Implement an extension point &ast;/
92  *  G_DEFINE_TYPE (MyExampleImpl, my_example_impl, MY_TYPE_EXAMPLE);
93  *  g_io_extension_point_implement ("my-extension-point",
94  *                                  my_example_impl_get_type (),
95  *                                  "my-example",
96  *                                  10);
97  *  ]|
98  *
99  *  It is up to the code that registered the extension point how
100  *  it uses the implementations that have been associated with it.
101  *  Depending on the use case, it may use all implementations, or
102  *  only the one with the highest priority, or pick a specific
103  *  one by name.
104  *
105  *  To avoid opening all modules just to find out what extension
106  *  points they implement, GIO makes use of a caching mechanism,
107  *  see <link linkend="gio-querymodules">gio-querymodules</link>.
108  *  You are expected to run this command after installing a
109  *  GIO module.
110  *
111  *  The <envar>GIO_EXTRA_MODULES</envar> environment variable can be
112  *  used to specify additional directories to automatically load modules
113  *  from. This environment variable has the same syntax as the
114  *  <envar>PATH</envar>. If two modules have the same base name in different
115  *  directories, then the latter one will be ignored. If additional
116  *  directories are specified GIO will load modules from the built-in
117  *  directory last.
118  */
119
120 /**
121  * GIOModuleScope:
122  *
123  * Represents a scope for loading IO modules. A scope can be used for blocking
124  * duplicate modules, or blocking a module you don't want to load.
125  *
126  * The scope can be used with g_io_modules_load_all_in_directory_with_scope()
127  * or g_io_modules_scan_all_in_directory_with_scope().
128  *
129  * Since: 2.30
130  */
131 struct _GIOModuleScope {
132   GIOModuleScopeFlags flags;
133   GHashTable *basenames;
134 };
135
136 /**
137  * g_io_module_scope_new:
138  * @flags: flags for the new scope
139  *
140  * Create a new scope for loading of IO modules. A scope can be used for
141  * blocking duplicate modules, or blocking a module you don't want to load.
142  *
143  * Specify the %G_IO_MODULE_SCOPE_BLOCK_DUPLICATES flag to block modules
144  * which have the same base name as a module that has already been seen
145  * in this scope.
146  *
147  * Returns: (transfer full): the new module scope
148  *
149  * Since: 2.30
150  */
151 GIOModuleScope *
152 g_io_module_scope_new (GIOModuleScopeFlags flags)
153 {
154   GIOModuleScope *scope = g_new0 (GIOModuleScope, 1);
155   scope->flags = flags;
156   scope->basenames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
157   return scope;
158 }
159
160 /**
161  * g_io_module_scope_free:
162  * @scope: a module loading scope
163  *
164  * Free a module scope.
165  *
166  * Since: 2.30
167  */
168 void
169 g_io_module_scope_free (GIOModuleScope *scope)
170 {
171   if (!scope)
172     return;
173   g_hash_table_destroy (scope->basenames);
174   g_free (scope);
175 }
176
177 /**
178  * g_io_module_scope_block:
179  * @scope: a module loading scope
180  * @basename: the basename to block
181  *
182  * Block modules with the given @basename from being loaded when
183  * this scope is used with g_io_modules_scan_all_in_directory_with_scope()
184  * or g_io_modules_load_all_in_directory_with_scope().
185  *
186  * Since: 2.30
187  */
188 void
189 g_io_module_scope_block (GIOModuleScope *scope,
190                          const gchar    *basename)
191 {
192   gchar *key;
193
194   g_return_if_fail (scope != NULL);
195   g_return_if_fail (basename != NULL);
196
197   key = g_strdup (basename);
198   g_hash_table_insert (scope->basenames, key, key);
199 }
200
201 static gboolean
202 _g_io_module_scope_contains (GIOModuleScope *scope,
203                              const gchar    *basename)
204 {
205   return g_hash_table_lookup (scope->basenames, basename) ? TRUE : FALSE;
206 }
207
208 struct _GIOModule {
209   GTypeModule parent_instance;
210
211   gchar       *filename;
212   GModule     *library;
213   gboolean     initialized; /* The module was loaded at least once */
214
215   void (* load)   (GIOModule *module);
216   void (* unload) (GIOModule *module);
217 };
218
219 struct _GIOModuleClass
220 {
221   GTypeModuleClass parent_class;
222
223 };
224
225 static void      g_io_module_finalize      (GObject      *object);
226 static gboolean  g_io_module_load_module   (GTypeModule  *gmodule);
227 static void      g_io_module_unload_module (GTypeModule  *gmodule);
228
229 struct _GIOExtension {
230   char *name;
231   GType type;
232   gint priority;
233 };
234
235 struct _GIOExtensionPoint {
236   GType required_type;
237   char *name;
238   GList *extensions;
239   GList *lazy_load_modules;
240 };
241
242 static GHashTable *extension_points = NULL;
243 G_LOCK_DEFINE_STATIC(extension_points);
244
245 G_DEFINE_TYPE (GIOModule, g_io_module, G_TYPE_TYPE_MODULE);
246
247 static void
248 g_io_module_class_init (GIOModuleClass *class)
249 {
250   GObjectClass     *object_class      = G_OBJECT_CLASS (class);
251   GTypeModuleClass *type_module_class = G_TYPE_MODULE_CLASS (class);
252
253   object_class->finalize     = g_io_module_finalize;
254
255   type_module_class->load    = g_io_module_load_module;
256   type_module_class->unload  = g_io_module_unload_module;
257 }
258
259 static void
260 g_io_module_init (GIOModule *module)
261 {
262 }
263
264 static void
265 g_io_module_finalize (GObject *object)
266 {
267   GIOModule *module = G_IO_MODULE (object);
268
269   g_free (module->filename);
270
271   G_OBJECT_CLASS (g_io_module_parent_class)->finalize (object);
272 }
273
274 static gboolean
275 g_io_module_load_module (GTypeModule *gmodule)
276 {
277   GIOModule *module = G_IO_MODULE (gmodule);
278
279   if (!module->filename)
280     {
281       g_warning ("GIOModule path not set");
282       return FALSE;
283     }
284
285   module->library = g_module_open (module->filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
286
287   if (!module->library)
288     {
289       g_printerr ("%s\n", g_module_error ());
290       return FALSE;
291     }
292
293   /* Make sure that the loaded library contains the required methods */
294   if (! g_module_symbol (module->library,
295                          "g_io_module_load",
296                          (gpointer) &module->load) ||
297       ! g_module_symbol (module->library,
298                          "g_io_module_unload",
299                          (gpointer) &module->unload))
300     {
301       g_printerr ("%s\n", g_module_error ());
302       g_module_close (module->library);
303
304       return FALSE;
305     }
306
307   /* Initialize the loaded module */
308   module->load (module);
309   module->initialized = TRUE;
310
311   return TRUE;
312 }
313
314 static void
315 g_io_module_unload_module (GTypeModule *gmodule)
316 {
317   GIOModule *module = G_IO_MODULE (gmodule);
318
319   module->unload (module);
320
321   g_module_close (module->library);
322   module->library = NULL;
323
324   module->load   = NULL;
325   module->unload = NULL;
326 }
327
328 /**
329  * g_io_module_new:
330  * @filename: filename of the shared library module.
331  * 
332  * Creates a new GIOModule that will load the specific
333  * shared library when in use.
334  * 
335  * Returns: a #GIOModule from given @filename, 
336  * or %NULL on error.
337  **/
338 GIOModule *
339 g_io_module_new (const gchar *filename)
340 {
341   GIOModule *module;
342
343   g_return_val_if_fail (filename != NULL, NULL);
344
345   module = g_object_new (G_IO_TYPE_MODULE, NULL);
346   module->filename = g_strdup (filename);
347
348   return module;
349 }
350
351 static gboolean
352 is_valid_module_name (const gchar        *basename,
353                       GIOModuleScope     *scope)
354 {
355   gboolean result;
356
357 #if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
358   if (!g_str_has_prefix (basename, "lib") ||
359       !g_str_has_suffix (basename, ".so"))
360     return FALSE;
361 #else
362   if (!g_str_has_suffix (basename, ".dll"))
363     return FALSE;
364 #endif
365
366   result = TRUE;
367   if (scope)
368     {
369       result = _g_io_module_scope_contains (scope, basename) ? FALSE : TRUE;
370       if (result && (scope->flags & G_IO_MODULE_SCOPE_BLOCK_DUPLICATES))
371         g_io_module_scope_block (scope, basename);
372     }
373
374   return result;
375 }
376
377
378 /**
379  * g_io_modules_scan_all_in_directory_with_scope:
380  * @dirname: pathname for a directory containing modules to scan.
381  * @scope: a scope to use when scanning the modules
382  *
383  * Scans all the modules in the specified directory, ensuring that
384  * any extension point implemented by a module is registered.
385  *
386  * This may not actually load and initialize all the types in each
387  * module, some modules may be lazily loaded and initialized when
388  * an extension point it implementes is used with e.g.
389  * g_io_extension_point_get_extensions() or
390  * g_io_extension_point_get_extension_by_name().
391  *
392  * If you need to guarantee that all types are loaded in all the modules,
393  * use g_io_modules_load_all_in_directory().
394  *
395  * Since: 2.30
396  **/
397 void
398 g_io_modules_scan_all_in_directory_with_scope (const char     *dirname,
399                                                GIOModuleScope *scope)
400 {
401   const gchar *name;
402   char *filename;
403   GDir *dir;
404   GStatBuf statbuf;
405   char *data;
406   time_t cache_mtime;
407   GHashTable *cache;
408
409   if (!g_module_supported ())
410     return;
411
412   dir = g_dir_open (dirname, 0, NULL);
413   if (!dir)
414     return;
415
416   filename = g_build_filename (dirname, "giomodule.cache", NULL);
417
418   cache = g_hash_table_new_full (g_str_hash, g_str_equal,
419                                  g_free, (GDestroyNotify)g_strfreev);
420
421   cache_mtime = 0;
422   if (g_stat (filename, &statbuf) == 0 &&
423       g_file_get_contents (filename, &data, NULL, NULL))
424     {
425       char **lines;
426       int i;
427
428       /* Cache mtime is the time the cache file was created, any file
429        * that has a ctime before this was created then and not modified
430        * since then (userspace can't change ctime). Its possible to change
431        * the ctime forward without changing the file content, by e.g.
432        * chmoding the file, but this is uncommon and will only cause us
433        * to not use the cache so will not cause bugs.
434        */
435       cache_mtime = statbuf.st_mtime;
436
437       lines = g_strsplit (data, "\n", -1);
438       g_free (data);
439
440       for (i = 0;  lines[i] != NULL; i++)
441         {
442           char *line = lines[i];
443           char *file;
444           char *colon;
445           char **extension_points;
446
447           if (line[0] == '#')
448             continue;
449
450           colon = strchr (line, ':');
451           if (colon == NULL || line == colon)
452             continue; /* Invalid line, ignore */
453
454           *colon = 0; /* terminate filename */
455           file = g_strdup (line);
456           colon++; /* after colon */
457
458           while (g_ascii_isspace (*colon))
459             colon++;
460
461           extension_points = g_strsplit (colon, ",", -1);
462           g_hash_table_insert (cache, file, extension_points);
463         }
464       g_strfreev (lines);
465     }
466
467   while ((name = g_dir_read_name (dir)))
468     {
469       if (is_valid_module_name (name, scope))
470         {
471           GIOExtensionPoint *extension_point;
472           GIOModule *module;
473           gchar *path;
474           char **extension_points;
475           int i;
476
477           path = g_build_filename (dirname, name, NULL);
478           module = g_io_module_new (path);
479
480           extension_points = g_hash_table_lookup (cache, name);
481           if (extension_points != NULL &&
482               g_stat (path, &statbuf) == 0 &&
483               statbuf.st_ctime <= cache_mtime)
484             {
485               /* Lazy load/init the library when first required */
486               for (i = 0; extension_points[i] != NULL; i++)
487                 {
488                   extension_point =
489                     g_io_extension_point_register (extension_points[i]);
490                   extension_point->lazy_load_modules =
491                     g_list_prepend (extension_point->lazy_load_modules,
492                                     module);
493                 }
494             }
495           else
496             {
497               /* Try to load and init types */
498               if (g_type_module_use (G_TYPE_MODULE (module)))
499                 g_type_module_unuse (G_TYPE_MODULE (module)); /* Unload */
500               else
501                 { /* Failure to load */
502                   g_printerr ("Failed to load module: %s\n", path);
503                   g_object_unref (module);
504                   g_free (path);
505                   continue;
506                 }
507             }
508
509           g_free (path);
510         }
511     }
512
513   g_dir_close (dir);
514
515   g_hash_table_destroy (cache);
516
517   g_free (filename);
518 }
519
520 /**
521  * g_io_modules_scan_all_in_directory:
522  * @dirname: pathname for a directory containing modules to scan.
523  *
524  * Scans all the modules in the specified directory, ensuring that
525  * any extension point implemented by a module is registered.
526  *
527  * This may not actually load and initialize all the types in each
528  * module, some modules may be lazily loaded and initialized when
529  * an extension point it implementes is used with e.g.
530  * g_io_extension_point_get_extensions() or
531  * g_io_extension_point_get_extension_by_name().
532  *
533  * If you need to guarantee that all types are loaded in all the modules,
534  * use g_io_modules_load_all_in_directory().
535  *
536  * Since: 2.24
537  **/
538 void
539 g_io_modules_scan_all_in_directory (const char *dirname)
540 {
541   g_io_modules_scan_all_in_directory_with_scope (dirname, NULL);
542 }
543
544 /**
545  * g_io_modules_load_all_in_directory_with_scope:
546  * @dirname: pathname for a directory containing modules to load.
547  * @scope: a scope to use when scanning the modules.
548  *
549  * Loads all the modules in the specified directory.
550  *
551  * If don't require all modules to be initialized (and thus registering
552  * all gtypes) then you can use g_io_modules_scan_all_in_directory()
553  * which allows delayed/lazy loading of modules.
554  *
555  * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
556  *      from the directory,
557  *      All the modules are loaded into memory, if you want to
558  *      unload them (enabling on-demand loading) you must call
559  *      g_type_module_unuse() on all the modules. Free the list
560  *      with g_list_free().
561  *
562  * Since: 2.30
563  **/
564 GList *
565 g_io_modules_load_all_in_directory_with_scope (const char     *dirname,
566                                                GIOModuleScope *scope)
567 {
568   const gchar *name;
569   GDir        *dir;
570   GList *modules;
571
572   if (!g_module_supported ())
573     return NULL;
574
575   dir = g_dir_open (dirname, 0, NULL);
576   if (!dir)
577     return NULL;
578
579   modules = NULL;
580   while ((name = g_dir_read_name (dir)))
581     {
582       if (is_valid_module_name (name, scope))
583         {
584           GIOModule *module;
585           gchar     *path;
586
587           path = g_build_filename (dirname, name, NULL);
588           module = g_io_module_new (path);
589
590           if (!g_type_module_use (G_TYPE_MODULE (module)))
591             {
592               g_printerr ("Failed to load module: %s\n", path);
593               g_object_unref (module);
594               g_free (path);
595               continue;
596             }
597           
598           g_free (path);
599
600           modules = g_list_prepend (modules, module);
601         }
602     }
603   
604   g_dir_close (dir);
605
606   return modules;
607 }
608
609 /**
610  * g_io_modules_load_all_in_directory:
611  * @dirname: pathname for a directory containing modules to load.
612  *
613  * Loads all the modules in the specified directory.
614  *
615  * If don't require all modules to be initialized (and thus registering
616  * all gtypes) then you can use g_io_modules_scan_all_in_directory()
617  * which allows delayed/lazy loading of modules.
618  *
619  * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
620  *      from the directory,
621  *      All the modules are loaded into memory, if you want to
622  *      unload them (enabling on-demand loading) you must call
623  *      g_type_module_unuse() on all the modules. Free the list
624  *      with g_list_free().
625  **/
626 GList *
627 g_io_modules_load_all_in_directory (const char *dirname)
628 {
629   return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
630 }
631
632 static gpointer
633 try_class (GIOExtension *extension,
634            guint         is_supported_offset)
635 {
636   GType type = g_io_extension_get_type (extension);
637   typedef gboolean (*verify_func) (void);
638   gpointer class;
639
640   class = g_type_class_ref (type);
641   if (!is_supported_offset || (* G_STRUCT_MEMBER(verify_func, class, is_supported_offset)) ())
642     return class;
643
644   g_type_class_unref (class);
645   return NULL;
646 }
647
648 /**
649  * _g_io_module_get_default_type:
650  * @extension_point: the name of an extension point
651  * @envvar: (allow-none): the name of an environment variable to
652  *     override the default implementation.
653  * @is_supported_offset: a vtable offset, or zero
654  *
655  * Retrieves the default class implementing @extension_point.
656  *
657  * If @envvar is not %NULL, and the environment variable with that
658  * name is set, then the implementation it specifies will be tried
659  * first. After that, or if @envvar is not set, all other
660  * implementations will be tried in order of decreasing priority.
661  *
662  * If @is_supported_offset is non-zero, then it is the offset into the
663  * class vtable at which there is a function that takes no arguments and
664  * returns a boolean.  This function will be called on each candidate
665  * implementation to check if it is actually usable or not.
666  *
667  * The result is cached after it is generated the first time, and
668  * the function is thread-safe.
669  *
670  * Return value: (transfer none): an object implementing
671  *     @extension_point, or %NULL if there are no usable
672  *     implementations.
673  */
674 GType
675 _g_io_module_get_default_type (const gchar *extension_point,
676                                const gchar *envvar,
677                                guint        is_supported_offset)
678 {
679   static GRecMutex default_modules_lock;
680   static GHashTable *default_modules;
681   const char *use_this;
682   GList *l;
683   GIOExtensionPoint *ep;
684   GIOExtension *extension, *preferred;
685   gpointer impl;
686
687   g_rec_mutex_lock (&default_modules_lock);
688   if (default_modules)
689     {
690       gpointer key;
691
692       if (g_hash_table_lookup_extended (default_modules, extension_point, &key, &impl))
693         {
694           g_rec_mutex_unlock (&default_modules_lock);
695           return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
696         }
697     }
698   else
699     {
700       default_modules = g_hash_table_new (g_str_hash, g_str_equal);
701     }
702
703   _g_io_modules_ensure_loaded ();
704   ep = g_io_extension_point_lookup (extension_point);
705
706   if (!ep)
707     {
708       g_warn_if_reached ();
709       g_rec_mutex_unlock (&default_modules_lock);
710       return G_TYPE_INVALID;
711     }
712
713   use_this = envvar ? g_getenv (envvar) : NULL;
714   if (use_this)
715     {
716       preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
717       if (preferred)
718         {
719           impl = try_class (preferred, is_supported_offset);
720           if (impl)
721             goto done;
722         }
723       else
724         g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
725     }
726   else
727     preferred = NULL;
728
729   for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
730     {
731       extension = l->data;
732       if (extension == preferred)
733         continue;
734
735       impl = try_class (extension, is_supported_offset);
736       if (impl)
737         goto done;
738     }
739
740   impl = NULL;
741
742  done:
743   g_hash_table_insert (default_modules, g_strdup (extension_point), impl);
744   g_rec_mutex_unlock (&default_modules_lock);
745
746   return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
747 }
748
749 static gpointer
750 try_implementation (GIOExtension         *extension,
751                     GIOModuleVerifyFunc   verify_func)
752 {
753   GType type = g_io_extension_get_type (extension);
754   gpointer impl;
755
756   if (g_type_is_a (type, G_TYPE_INITABLE))
757     return g_initable_new (type, NULL, NULL, NULL);
758   else
759     {
760       impl = g_object_new (type, NULL);
761       if (!verify_func || verify_func (impl))
762         return impl;
763
764       g_object_unref (impl);
765       return NULL;
766     }
767 }
768
769 /**
770  * _g_io_module_get_default:
771  * @extension_point: the name of an extension point
772  * @envvar: (allow-none): the name of an environment variable to
773  *     override the default implementation.
774  * @verify_func: (allow-none): a function to call to verify that
775  *     a given implementation is usable in the current environment.
776  *
777  * Retrieves the default object implementing @extension_point.
778  *
779  * If @envvar is not %NULL, and the environment variable with that
780  * name is set, then the implementation it specifies will be tried
781  * first. After that, or if @envvar is not set, all other
782  * implementations will be tried in order of decreasing priority.
783  *
784  * If an extension point implementation implements #GInitable, then
785  * that implementation will only be used if it initializes
786  * successfully. Otherwise, if @verify_func is not %NULL, then it will
787  * be called on each candidate implementation after construction, to
788  * check if it is actually usable or not.
789  *
790  * The result is cached after it is generated the first time, and
791  * the function is thread-safe.
792  *
793  * Return value: (transfer none): an object implementing
794  *     @extension_point, or %NULL if there are no usable
795  *     implementations.
796  */
797 gpointer
798 _g_io_module_get_default (const gchar         *extension_point,
799                           const gchar         *envvar,
800                           GIOModuleVerifyFunc  verify_func)
801 {
802   static GRecMutex default_modules_lock;
803   static GHashTable *default_modules;
804   const char *use_this;
805   GList *l;
806   GIOExtensionPoint *ep;
807   GIOExtension *extension, *preferred;
808   gpointer impl;
809
810   g_rec_mutex_lock (&default_modules_lock);
811   if (default_modules)
812     {
813       gpointer key;
814
815       if (g_hash_table_lookup_extended (default_modules, extension_point,
816                                         &key, &impl))
817         {
818           g_rec_mutex_unlock (&default_modules_lock);
819           return impl;
820         }
821     }
822   else
823     {
824       default_modules = g_hash_table_new (g_str_hash, g_str_equal);
825     }
826
827   _g_io_modules_ensure_loaded ();
828   ep = g_io_extension_point_lookup (extension_point);
829
830   if (!ep)
831     {
832       g_warn_if_reached ();
833       g_rec_mutex_unlock (&default_modules_lock);
834       return NULL;
835     }
836
837   use_this = envvar ? g_getenv (envvar) : NULL;
838   if (use_this)
839     {
840       preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
841       if (preferred)
842         {
843           impl = try_implementation (preferred, verify_func);
844           if (impl)
845             goto done;
846         }
847       else
848         g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
849     }
850   else
851     preferred = NULL;
852
853   for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
854     {
855       extension = l->data;
856       if (extension == preferred)
857         continue;
858
859       impl = try_implementation (extension, verify_func);
860       if (impl)
861         goto done;
862     }
863
864   impl = NULL;
865
866  done:
867   g_hash_table_insert (default_modules,
868                        g_strdup (extension_point),
869                        impl ? g_object_ref (impl) : NULL);
870   g_rec_mutex_unlock (&default_modules_lock);
871
872   return impl;
873 }
874
875 G_LOCK_DEFINE_STATIC (registered_extensions);
876 G_LOCK_DEFINE_STATIC (loaded_dirs);
877
878 extern GType _g_fen_directory_monitor_get_type (void);
879 extern GType _g_fen_file_monitor_get_type (void);
880 extern GType _g_inotify_directory_monitor_get_type (void);
881 extern GType _g_inotify_file_monitor_get_type (void);
882 extern GType _g_kqueue_directory_monitor_get_type (void);
883 extern GType _g_kqueue_file_monitor_get_type (void);
884 extern GType _g_unix_volume_monitor_get_type (void);
885 extern GType _g_local_vfs_get_type (void);
886
887 extern GType _g_win32_volume_monitor_get_type (void);
888 extern GType g_win32_directory_monitor_get_type (void);
889 extern GType _g_winhttp_vfs_get_type (void);
890
891 extern GType _g_dummy_proxy_resolver_get_type (void);
892 extern GType _g_dummy_tls_backend_get_type (void);
893 extern GType g_network_monitor_base_get_type (void);
894 #ifdef HAVE_NETLINK
895 extern GType _g_network_monitor_netlink_get_type (void);
896 #endif
897
898 #ifdef G_OS_UNIX
899 extern GType g_fdo_notification_backend_get_type (void);
900 extern GType g_gtk_notification_backend_get_type (void);
901 #endif
902
903 #ifdef G_PLATFORM_WIN32
904
905 #include <windows.h>
906
907 static HMODULE gio_dll = NULL;
908
909 #ifdef DLL_EXPORT
910
911 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
912                      DWORD     fdwReason,
913                      LPVOID    lpvReserved);
914
915 BOOL WINAPI
916 DllMain (HINSTANCE hinstDLL,
917          DWORD     fdwReason,
918          LPVOID    lpvReserved)
919 {
920   if (fdwReason == DLL_PROCESS_ATTACH)
921       gio_dll = hinstDLL;
922
923   return TRUE;
924 }
925
926 #endif
927
928 void *
929 _g_io_win32_get_module (void)
930 {
931   if (!gio_dll)
932     GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
933                         (const char *) _g_io_win32_get_module,
934                         &gio_dll);
935   return gio_dll;
936 }
937
938 #undef GIO_MODULE_DIR
939
940 /* GIO_MODULE_DIR is used only in code called just once,
941  * so no problem leaking this
942  */
943 #define GIO_MODULE_DIR \
944   g_build_filename (g_win32_get_package_installation_directory_of_module (gio_dll), \
945                     "lib/gio/modules", \
946                     NULL)
947
948 #endif
949
950 void
951 _g_io_modules_ensure_extension_points_registered (void)
952 {
953   static gboolean registered_extensions = FALSE;
954   GIOExtensionPoint *ep;
955
956   G_LOCK (registered_extensions);
957   
958   if (!registered_extensions)
959     {
960       registered_extensions = TRUE;
961       
962 #ifdef G_OS_UNIX
963 #if !GLIB_CHECK_VERSION (3, 0, 0)
964       ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
965       G_GNUC_BEGIN_IGNORE_DEPRECATIONS
966       g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LOOKUP);
967       G_GNUC_END_IGNORE_DEPRECATIONS
968 #endif
969 #endif
970       
971       ep = g_io_extension_point_register (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
972       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
973       
974       ep = g_io_extension_point_register (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME);
975       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
976       
977       ep = g_io_extension_point_register (G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
978       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
979
980       ep = g_io_extension_point_register (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME);
981       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
982
983       ep = g_io_extension_point_register (G_VOLUME_MONITOR_EXTENSION_POINT_NAME);
984       g_io_extension_point_set_required_type (ep, G_TYPE_VOLUME_MONITOR);
985       
986       ep = g_io_extension_point_register (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME);
987       g_io_extension_point_set_required_type (ep, G_TYPE_NATIVE_VOLUME_MONITOR);
988       
989       ep = g_io_extension_point_register (G_VFS_EXTENSION_POINT_NAME);
990       g_io_extension_point_set_required_type (ep, G_TYPE_VFS);
991
992       ep = g_io_extension_point_register ("gsettings-backend");
993       g_io_extension_point_set_required_type (ep, G_TYPE_OBJECT);
994
995       ep = g_io_extension_point_register (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
996       g_io_extension_point_set_required_type (ep, G_TYPE_PROXY_RESOLVER);
997
998       ep = g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME);
999       g_io_extension_point_set_required_type (ep, G_TYPE_PROXY);
1000
1001       ep = g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
1002       g_io_extension_point_set_required_type (ep, G_TYPE_TLS_BACKEND);
1003
1004       ep = g_io_extension_point_register (G_NETWORK_MONITOR_EXTENSION_POINT_NAME);
1005       g_io_extension_point_set_required_type (ep, G_TYPE_NETWORK_MONITOR);
1006
1007       ep = g_io_extension_point_register (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME);
1008       g_io_extension_point_set_required_type (ep, G_TYPE_NOTIFICATION_BACKEND);
1009     }
1010   
1011   G_UNLOCK (registered_extensions);
1012 }
1013
1014 void
1015 _g_io_modules_ensure_loaded (void)
1016 {
1017   static gboolean loaded_dirs = FALSE;
1018   const char *module_path;
1019   GIOModuleScope *scope;
1020   const gchar *module_dir;
1021
1022   _g_io_modules_ensure_extension_points_registered ();
1023   
1024   G_LOCK (loaded_dirs);
1025
1026   if (!loaded_dirs)
1027     {
1028       loaded_dirs = TRUE;
1029       scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
1030
1031       /* First load any overrides, extras */
1032       module_path = g_getenv ("GIO_EXTRA_MODULES");
1033       if (module_path)
1034         {
1035           gchar **paths;
1036           int i;
1037
1038           paths = g_strsplit (module_path, G_SEARCHPATH_SEPARATOR_S, 0);
1039
1040           for (i = 0; paths[i] != NULL; i++)
1041             {
1042               g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
1043             }
1044
1045           g_strfreev (paths);
1046         }
1047
1048       /* Then load the compiled in path */
1049       module_dir = g_getenv ("GIO_MODULE_DIR");
1050       if (module_dir == NULL)
1051         module_dir = GIO_MODULE_DIR;
1052
1053       g_io_modules_scan_all_in_directory_with_scope (module_dir, scope);
1054
1055       g_io_module_scope_free (scope);
1056
1057       /* Initialize types from built-in "modules" */
1058       g_type_ensure (g_null_settings_backend_get_type ());
1059       g_type_ensure (g_memory_settings_backend_get_type ());
1060 #if defined(HAVE_SYS_INOTIFY_H) || defined(HAVE_LINUX_INOTIFY_H)
1061       g_type_ensure (_g_inotify_directory_monitor_get_type ());
1062       g_type_ensure (_g_inotify_file_monitor_get_type ());
1063 #endif
1064 #if defined(HAVE_KQUEUE)
1065       g_type_ensure (_g_kqueue_directory_monitor_get_type ());
1066       g_type_ensure (_g_kqueue_file_monitor_get_type ());
1067 #endif
1068 #if defined(HAVE_FEN)
1069       g_type_ensure (_g_fen_directory_monitor_get_type ());
1070       g_type_ensure (_g_fen_file_monitor_get_type ());
1071 #endif
1072 #ifdef G_OS_WIN32
1073       g_type_ensure (_g_win32_volume_monitor_get_type ());
1074       g_type_ensure (g_win32_directory_monitor_get_type ());
1075       g_type_ensure (g_registry_backend_get_type ());
1076 #endif
1077 #ifdef HAVE_CARBON
1078       g_nextstep_settings_backend_get_type ();
1079 #endif
1080 #ifdef G_OS_UNIX
1081       g_type_ensure (_g_unix_volume_monitor_get_type ());
1082       g_type_ensure (g_fdo_notification_backend_get_type ());
1083       g_type_ensure (g_gtk_notification_backend_get_type ());
1084 #endif
1085 #ifdef G_OS_WIN32
1086       g_type_ensure (_g_winhttp_vfs_get_type ());
1087 #endif
1088       g_type_ensure (_g_local_vfs_get_type ());
1089       g_type_ensure (_g_dummy_proxy_resolver_get_type ());
1090       g_type_ensure (_g_socks4a_proxy_get_type ());
1091       g_type_ensure (_g_socks4_proxy_get_type ());
1092       g_type_ensure (_g_socks5_proxy_get_type ());
1093       g_type_ensure (_g_dummy_tls_backend_get_type ());
1094       g_type_ensure (g_network_monitor_base_get_type ());
1095 #ifdef HAVE_NETLINK
1096       g_type_ensure (_g_network_monitor_netlink_get_type ());
1097 #endif
1098     }
1099
1100   G_UNLOCK (loaded_dirs);
1101 }
1102
1103 static void
1104 g_io_extension_point_free (GIOExtensionPoint *ep)
1105 {
1106   g_free (ep->name);
1107   g_free (ep);
1108 }
1109
1110 /**
1111  * g_io_extension_point_register:
1112  * @name: The name of the extension point
1113  *
1114  * Registers an extension point.
1115  *
1116  * Returns: (transfer none): the new #GIOExtensionPoint. This object is
1117  *    owned by GIO and should not be freed.
1118  */
1119 GIOExtensionPoint *
1120 g_io_extension_point_register (const char *name)
1121 {
1122   GIOExtensionPoint *ep;
1123   
1124   G_LOCK (extension_points);
1125   if (extension_points == NULL)
1126     extension_points = g_hash_table_new_full (g_str_hash,
1127                                               g_str_equal,
1128                                               NULL,
1129                                               (GDestroyNotify)g_io_extension_point_free);
1130
1131   ep = g_hash_table_lookup (extension_points, name);
1132   if (ep != NULL)
1133     {
1134       G_UNLOCK (extension_points);
1135       return ep;
1136     }
1137
1138   ep = g_new0 (GIOExtensionPoint, 1);
1139   ep->name = g_strdup (name);
1140   
1141   g_hash_table_insert (extension_points, ep->name, ep);
1142   
1143   G_UNLOCK (extension_points);
1144
1145   return ep;
1146 }
1147
1148 /**
1149  * g_io_extension_point_lookup:
1150  * @name: the name of the extension point
1151  *
1152  * Looks up an existing extension point.
1153  *
1154  * Returns: (transfer none): the #GIOExtensionPoint, or %NULL if there
1155  *    is no registered extension point with the given name.
1156  */
1157 GIOExtensionPoint *
1158 g_io_extension_point_lookup (const char *name)
1159 {
1160   GIOExtensionPoint *ep;
1161
1162   G_LOCK (extension_points);
1163   ep = NULL;
1164   if (extension_points != NULL)
1165     ep = g_hash_table_lookup (extension_points, name);
1166   
1167   G_UNLOCK (extension_points);
1168
1169   return ep;
1170   
1171 }
1172
1173 /**
1174  * g_io_extension_point_set_required_type:
1175  * @extension_point: a #GIOExtensionPoint
1176  * @type: the #GType to require
1177  *
1178  * Sets the required type for @extension_point to @type. 
1179  * All implementations must henceforth have this type.
1180  */
1181 void
1182 g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
1183                                         GType              type)
1184 {
1185   extension_point->required_type = type;
1186 }
1187
1188 /**
1189  * g_io_extension_point_get_required_type:
1190  * @extension_point: a #GIOExtensionPoint
1191  *
1192  * Gets the required type for @extension_point.
1193  *
1194  * Returns: the #GType that all implementations must have, 
1195  *     or #G_TYPE_INVALID if the extension point has no required type
1196  */
1197 GType
1198 g_io_extension_point_get_required_type (GIOExtensionPoint *extension_point)
1199 {
1200   return extension_point->required_type;
1201 }
1202
1203 static void
1204 lazy_load_modules (GIOExtensionPoint *extension_point)
1205 {
1206   GIOModule *module;
1207   GList *l;
1208
1209   for (l = extension_point->lazy_load_modules; l != NULL; l = l->next)
1210     {
1211       module = l->data;
1212
1213       if (!module->initialized)
1214         {
1215           if (g_type_module_use (G_TYPE_MODULE (module)))
1216             g_type_module_unuse (G_TYPE_MODULE (module)); /* Unload */
1217           else
1218             g_printerr ("Failed to load module: %s\n",
1219                         module->filename);
1220         }
1221     }
1222 }
1223
1224 /**
1225  * g_io_extension_point_get_extensions:
1226  * @extension_point: a #GIOExtensionPoint
1227  *
1228  * Gets a list of all extensions that implement this extension point.
1229  * The list is sorted by priority, beginning with the highest priority.
1230  *
1231  * Returns: (element-type GIOExtension) (transfer none): a #GList of
1232  * #GIOExtension<!-- -->s. The list is owned by GIO and should not be
1233  * modified.
1234  */
1235 GList *
1236 g_io_extension_point_get_extensions (GIOExtensionPoint *extension_point)
1237 {
1238   lazy_load_modules (extension_point);
1239   return extension_point->extensions;
1240 }
1241
1242 /**
1243  * g_io_extension_point_get_extension_by_name:
1244  * @extension_point: a #GIOExtensionPoint
1245  * @name: the name of the extension to get
1246  *
1247  * Finds a #GIOExtension for an extension point by name.
1248  *
1249  * Returns: (transfer none): the #GIOExtension for @extension_point that has the
1250  *    given name, or %NULL if there is no extension with that name
1251  */
1252 GIOExtension *
1253 g_io_extension_point_get_extension_by_name (GIOExtensionPoint *extension_point,
1254                                             const char        *name)
1255 {
1256   GList *l;
1257
1258   lazy_load_modules (extension_point);
1259   for (l = extension_point->extensions; l != NULL; l = l->next)
1260     {
1261       GIOExtension *e = l->data;
1262
1263       if (e->name != NULL &&
1264           strcmp (e->name, name) == 0)
1265         return e;
1266     }
1267   
1268   return NULL;
1269 }
1270
1271 static gint
1272 extension_prio_compare (gconstpointer  a,
1273                         gconstpointer  b)
1274 {
1275   const GIOExtension *extension_a = a, *extension_b = b;
1276
1277   if (extension_a->priority > extension_b->priority)
1278     return -1;
1279
1280   if (extension_b->priority > extension_a->priority)
1281     return 1;
1282
1283   return 0;
1284 }
1285
1286 /**
1287  * g_io_extension_point_implement:
1288  * @extension_point_name: the name of the extension point
1289  * @type: the #GType to register as extension 
1290  * @extension_name: the name for the extension
1291  * @priority: the priority for the extension
1292  *
1293  * Registers @type as extension for the extension point with name
1294  * @extension_point_name. 
1295  *
1296  * If @type has already been registered as an extension for this 
1297  * extension point, the existing #GIOExtension object is returned.
1298  *
1299  * Returns: (transfer none): a #GIOExtension object for #GType
1300  */
1301 GIOExtension *
1302 g_io_extension_point_implement (const char *extension_point_name,
1303                                 GType       type,
1304                                 const char *extension_name,
1305                                 gint        priority)
1306 {
1307   GIOExtensionPoint *extension_point;
1308   GIOExtension *extension;
1309   GList *l;
1310
1311   g_return_val_if_fail (extension_point_name != NULL, NULL);
1312
1313   extension_point = g_io_extension_point_lookup (extension_point_name);
1314   if (extension_point == NULL)
1315     {
1316       g_warning ("Tried to implement non-registered extension point %s", extension_point_name);
1317       return NULL;
1318     }
1319   
1320   if (extension_point->required_type != 0 &&
1321       !g_type_is_a (type, extension_point->required_type))
1322     {
1323       g_warning ("Tried to register an extension of the type %s to extension point %s. "
1324                  "Expected type is %s.",
1325                  g_type_name (type),
1326                  extension_point_name, 
1327                  g_type_name (extension_point->required_type));
1328       return NULL;
1329     }      
1330
1331   /* It's safe to register the same type multiple times */
1332   for (l = extension_point->extensions; l != NULL; l = l->next)
1333     {
1334       extension = l->data;
1335       if (extension->type == type)
1336         return extension;
1337     }
1338   
1339   extension = g_slice_new0 (GIOExtension);
1340   extension->type = type;
1341   extension->name = g_strdup (extension_name);
1342   extension->priority = priority;
1343   
1344   extension_point->extensions = g_list_insert_sorted (extension_point->extensions,
1345                                                       extension, extension_prio_compare);
1346   
1347   return extension;
1348 }
1349
1350 /**
1351  * g_io_extension_ref_class:
1352  * @extension: a #GIOExtension
1353  *
1354  * Gets a reference to the class for the type that is 
1355  * associated with @extension.
1356  *
1357  * Returns: (transfer full): the #GTypeClass for the type of @extension
1358  */
1359 GTypeClass *
1360 g_io_extension_ref_class (GIOExtension *extension)
1361 {
1362   return g_type_class_ref (extension->type);
1363 }
1364
1365 /**
1366  * g_io_extension_get_type:
1367  * @extension: a #GIOExtension
1368  *
1369  * Gets the type associated with @extension.
1370  *
1371  * Returns: the type of @extension
1372  */
1373 GType
1374 g_io_extension_get_type (GIOExtension *extension)
1375 {
1376   return extension->type;
1377 }
1378
1379 /**
1380  * g_io_extension_get_name:
1381  * @extension: a #GIOExtension
1382  *
1383  * Gets the name under which @extension was registered.
1384  *
1385  * Note that the same type may be registered as extension
1386  * for multiple extension points, under different names.
1387  *
1388  * Returns: the name of @extension.
1389  */
1390 const char *
1391 g_io_extension_get_name (GIOExtension *extension)
1392 {
1393   return extension->name;
1394 }
1395
1396 /**
1397  * g_io_extension_get_priority:
1398  * @extension: a #GIOExtension
1399  *
1400  * Gets the priority with which @extension was registered.
1401  *
1402  * Returns: the priority of @extension
1403  */
1404 gint
1405 g_io_extension_get_priority (GIOExtension *extension)
1406 {
1407   return extension->priority;
1408 }