tests: Fix for non-GCC
[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                                     g_object_ref (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 /* Failure to load */
501                 g_printerr ("Failed to load module: %s\n", path);
502             }
503
504           g_object_unref (module);
505           g_free (path);
506         }
507     }
508
509   g_dir_close (dir);
510
511   g_hash_table_destroy (cache);
512
513   g_free (filename);
514 }
515
516 /**
517  * g_io_modules_scan_all_in_directory:
518  * @dirname: pathname for a directory containing modules to scan.
519  *
520  * Scans all the modules in the specified directory, ensuring that
521  * any extension point implemented by a module is registered.
522  *
523  * This may not actually load and initialize all the types in each
524  * module, some modules may be lazily loaded and initialized when
525  * an extension point it implementes is used with e.g.
526  * g_io_extension_point_get_extensions() or
527  * g_io_extension_point_get_extension_by_name().
528  *
529  * If you need to guarantee that all types are loaded in all the modules,
530  * use g_io_modules_load_all_in_directory().
531  *
532  * Since: 2.24
533  **/
534 void
535 g_io_modules_scan_all_in_directory (const char *dirname)
536 {
537   g_io_modules_scan_all_in_directory_with_scope (dirname, NULL);
538 }
539
540 /**
541  * g_io_modules_load_all_in_directory_with_scope:
542  * @dirname: pathname for a directory containing modules to load.
543  * @scope: a scope to use when scanning the modules.
544  *
545  * Loads all the modules in the specified directory.
546  *
547  * If don't require all modules to be initialized (and thus registering
548  * all gtypes) then you can use g_io_modules_scan_all_in_directory()
549  * which allows delayed/lazy loading of modules.
550  *
551  * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
552  *      from the directory,
553  *      All the modules are loaded into memory, if you want to
554  *      unload them (enabling on-demand loading) you must call
555  *      g_type_module_unuse() on all the modules. Free the list
556  *      with g_list_free().
557  *
558  * Since: 2.30
559  **/
560 GList *
561 g_io_modules_load_all_in_directory_with_scope (const char     *dirname,
562                                                GIOModuleScope *scope)
563 {
564   const gchar *name;
565   GDir        *dir;
566   GList *modules;
567
568   if (!g_module_supported ())
569     return NULL;
570
571   dir = g_dir_open (dirname, 0, NULL);
572   if (!dir)
573     return NULL;
574
575   modules = NULL;
576   while ((name = g_dir_read_name (dir)))
577     {
578       if (is_valid_module_name (name, scope))
579         {
580           GIOModule *module;
581           gchar     *path;
582
583           path = g_build_filename (dirname, name, NULL);
584           module = g_io_module_new (path);
585
586           if (!g_type_module_use (G_TYPE_MODULE (module)))
587             {
588               g_printerr ("Failed to load module: %s\n", path);
589               g_object_unref (module);
590               g_free (path);
591               continue;
592             }
593           
594           g_free (path);
595
596           modules = g_list_prepend (modules, module);
597         }
598     }
599   
600   g_dir_close (dir);
601
602   return modules;
603 }
604
605 /**
606  * g_io_modules_load_all_in_directory:
607  * @dirname: pathname for a directory containing modules to load.
608  *
609  * Loads all the modules in the specified directory.
610  *
611  * If don't require all modules to be initialized (and thus registering
612  * all gtypes) then you can use g_io_modules_scan_all_in_directory()
613  * which allows delayed/lazy loading of modules.
614  *
615  * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
616  *      from the directory,
617  *      All the modules are loaded into memory, if you want to
618  *      unload them (enabling on-demand loading) you must call
619  *      g_type_module_unuse() on all the modules. Free the list
620  *      with g_list_free().
621  **/
622 GList *
623 g_io_modules_load_all_in_directory (const char *dirname)
624 {
625   return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
626 }
627
628 static gpointer
629 try_class (GIOExtension *extension,
630            guint         is_supported_offset)
631 {
632   GType type = g_io_extension_get_type (extension);
633   typedef gboolean (*verify_func) (void);
634   gpointer class;
635
636   class = g_type_class_ref (type);
637   if (!is_supported_offset || (* G_STRUCT_MEMBER(verify_func, class, is_supported_offset)) ())
638     return class;
639
640   g_type_class_unref (class);
641   return NULL;
642 }
643
644 /**
645  * _g_io_module_get_default_type:
646  * @extension_point: the name of an extension point
647  * @envvar: (allow-none): the name of an environment variable to
648  *     override the default implementation.
649  * @is_supported_offset: a vtable offset, or zero
650  *
651  * Retrieves the default class implementing @extension_point.
652  *
653  * If @envvar is not %NULL, and the environment variable with that
654  * name is set, then the implementation it specifies will be tried
655  * first. After that, or if @envvar is not set, all other
656  * implementations will be tried in order of decreasing priority.
657  *
658  * If @is_supported_offset is non-zero, then it is the offset into the
659  * class vtable at which there is a function that takes no arguments and
660  * returns a boolean.  This function will be called on each candidate
661  * implementation to check if it is actually usable or not.
662  *
663  * The result is cached after it is generated the first time, and
664  * the function is thread-safe.
665  *
666  * Return value: (transfer none): an object implementing
667  *     @extension_point, or %NULL if there are no usable
668  *     implementations.
669  */
670 GType
671 _g_io_module_get_default_type (const gchar *extension_point,
672                                const gchar *envvar,
673                                guint        is_supported_offset)
674 {
675   static GRecMutex default_modules_lock;
676   static GHashTable *default_modules;
677   const char *use_this;
678   GList *l;
679   GIOExtensionPoint *ep;
680   GIOExtension *extension, *preferred;
681   gpointer impl;
682
683   g_rec_mutex_lock (&default_modules_lock);
684   if (default_modules)
685     {
686       gpointer key;
687
688       if (g_hash_table_lookup_extended (default_modules, extension_point, &key, &impl))
689         {
690           g_rec_mutex_unlock (&default_modules_lock);
691           return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
692         }
693     }
694   else
695     {
696       default_modules = g_hash_table_new (g_str_hash, g_str_equal);
697     }
698
699   _g_io_modules_ensure_loaded ();
700   ep = g_io_extension_point_lookup (extension_point);
701
702   if (!ep)
703     {
704       g_warn_if_reached ();
705       g_rec_mutex_unlock (&default_modules_lock);
706       return G_TYPE_INVALID;
707     }
708
709   use_this = envvar ? g_getenv (envvar) : NULL;
710   if (use_this)
711     {
712       preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
713       if (preferred)
714         {
715           impl = try_class (preferred, is_supported_offset);
716           if (impl)
717             goto done;
718         }
719       else
720         g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
721     }
722   else
723     preferred = NULL;
724
725   for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
726     {
727       extension = l->data;
728       if (extension == preferred)
729         continue;
730
731       impl = try_class (extension, is_supported_offset);
732       if (impl)
733         goto done;
734     }
735
736   impl = NULL;
737
738  done:
739   g_hash_table_insert (default_modules, g_strdup (extension_point), impl);
740   g_rec_mutex_unlock (&default_modules_lock);
741
742   return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
743 }
744
745 static gpointer
746 try_implementation (GIOExtension         *extension,
747                     GIOModuleVerifyFunc   verify_func)
748 {
749   GType type = g_io_extension_get_type (extension);
750   gpointer impl;
751
752   if (g_type_is_a (type, G_TYPE_INITABLE))
753     return g_initable_new (type, NULL, NULL, NULL);
754   else
755     {
756       impl = g_object_new (type, NULL);
757       if (!verify_func || verify_func (impl))
758         return impl;
759
760       g_object_unref (impl);
761       return NULL;
762     }
763 }
764
765 /**
766  * _g_io_module_get_default:
767  * @extension_point: the name of an extension point
768  * @envvar: (allow-none): the name of an environment variable to
769  *     override the default implementation.
770  * @verify_func: (allow-none): a function to call to verify that
771  *     a given implementation is usable in the current environment.
772  *
773  * Retrieves the default object implementing @extension_point.
774  *
775  * If @envvar is not %NULL, and the environment variable with that
776  * name is set, then the implementation it specifies will be tried
777  * first. After that, or if @envvar is not set, all other
778  * implementations will be tried in order of decreasing priority.
779  *
780  * If an extension point implementation implements #GInitable, then
781  * that implementation will only be used if it initializes
782  * successfully. Otherwise, if @verify_func is not %NULL, then it will
783  * be called on each candidate implementation after construction, to
784  * check if it is actually usable or not.
785  *
786  * The result is cached after it is generated the first time, and
787  * the function is thread-safe.
788  *
789  * Return value: (transfer none): an object implementing
790  *     @extension_point, or %NULL if there are no usable
791  *     implementations.
792  */
793 gpointer
794 _g_io_module_get_default (const gchar         *extension_point,
795                           const gchar         *envvar,
796                           GIOModuleVerifyFunc  verify_func)
797 {
798   static GRecMutex default_modules_lock;
799   static GHashTable *default_modules;
800   const char *use_this;
801   GList *l;
802   GIOExtensionPoint *ep;
803   GIOExtension *extension, *preferred;
804   gpointer impl;
805
806   g_rec_mutex_lock (&default_modules_lock);
807   if (default_modules)
808     {
809       gpointer key;
810
811       if (g_hash_table_lookup_extended (default_modules, extension_point,
812                                         &key, &impl))
813         {
814           g_rec_mutex_unlock (&default_modules_lock);
815           return impl;
816         }
817     }
818   else
819     {
820       default_modules = g_hash_table_new (g_str_hash, g_str_equal);
821     }
822
823   _g_io_modules_ensure_loaded ();
824   ep = g_io_extension_point_lookup (extension_point);
825
826   if (!ep)
827     {
828       g_warn_if_reached ();
829       g_rec_mutex_unlock (&default_modules_lock);
830       return NULL;
831     }
832
833   use_this = envvar ? g_getenv (envvar) : NULL;
834   if (use_this)
835     {
836       preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
837       if (preferred)
838         {
839           impl = try_implementation (preferred, verify_func);
840           if (impl)
841             goto done;
842         }
843       else
844         g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
845     }
846   else
847     preferred = NULL;
848
849   for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
850     {
851       extension = l->data;
852       if (extension == preferred)
853         continue;
854
855       impl = try_implementation (extension, verify_func);
856       if (impl)
857         goto done;
858     }
859
860   impl = NULL;
861
862  done:
863   g_hash_table_insert (default_modules,
864                        g_strdup (extension_point), impl);
865   g_rec_mutex_unlock (&default_modules_lock);
866
867   return impl;
868 }
869
870 G_LOCK_DEFINE_STATIC (registered_extensions);
871 G_LOCK_DEFINE_STATIC (loaded_dirs);
872
873 extern GType _g_fen_directory_monitor_get_type (void);
874 extern GType _g_fen_file_monitor_get_type (void);
875 extern GType _g_inotify_directory_monitor_get_type (void);
876 extern GType _g_inotify_file_monitor_get_type (void);
877 extern GType _g_kqueue_directory_monitor_get_type (void);
878 extern GType _g_kqueue_file_monitor_get_type (void);
879 extern GType _g_unix_volume_monitor_get_type (void);
880 extern GType _g_local_vfs_get_type (void);
881
882 extern GType _g_win32_volume_monitor_get_type (void);
883 extern GType g_win32_directory_monitor_get_type (void);
884 extern GType _g_winhttp_vfs_get_type (void);
885
886 extern GType _g_dummy_proxy_resolver_get_type (void);
887 extern GType _g_dummy_tls_backend_get_type (void);
888 extern GType g_network_monitor_base_get_type (void);
889 #ifdef HAVE_NETLINK
890 extern GType _g_network_monitor_netlink_get_type (void);
891 #endif
892
893 #ifdef G_OS_UNIX
894 extern GType g_fdo_notification_backend_get_type (void);
895 extern GType g_gtk_notification_backend_get_type (void);
896 #endif
897
898 #ifdef G_PLATFORM_WIN32
899
900 #include <windows.h>
901
902 static HMODULE gio_dll = NULL;
903
904 #ifdef DLL_EXPORT
905
906 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
907                      DWORD     fdwReason,
908                      LPVOID    lpvReserved);
909
910 BOOL WINAPI
911 DllMain (HINSTANCE hinstDLL,
912          DWORD     fdwReason,
913          LPVOID    lpvReserved)
914 {
915   if (fdwReason == DLL_PROCESS_ATTACH)
916       gio_dll = hinstDLL;
917
918   return TRUE;
919 }
920
921 #endif
922
923 void *
924 _g_io_win32_get_module (void)
925 {
926   if (!gio_dll)
927     GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
928                         (const char *) _g_io_win32_get_module,
929                         &gio_dll);
930   return gio_dll;
931 }
932
933 #undef GIO_MODULE_DIR
934
935 /* GIO_MODULE_DIR is used only in code called just once,
936  * so no problem leaking this
937  */
938 #define GIO_MODULE_DIR \
939   g_build_filename (g_win32_get_package_installation_directory_of_module (gio_dll), \
940                     "lib/gio/modules", \
941                     NULL)
942
943 #endif
944
945 void
946 _g_io_modules_ensure_extension_points_registered (void)
947 {
948   static gboolean registered_extensions = FALSE;
949   GIOExtensionPoint *ep;
950
951   G_LOCK (registered_extensions);
952   
953   if (!registered_extensions)
954     {
955       registered_extensions = TRUE;
956       
957 #ifdef G_OS_UNIX
958 #if !GLIB_CHECK_VERSION (3, 0, 0)
959       ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
960       G_GNUC_BEGIN_IGNORE_DEPRECATIONS
961       g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LOOKUP);
962       G_GNUC_END_IGNORE_DEPRECATIONS
963 #endif
964 #endif
965       
966       ep = g_io_extension_point_register (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
967       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
968       
969       ep = g_io_extension_point_register (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME);
970       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
971       
972       ep = g_io_extension_point_register (G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
973       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
974
975       ep = g_io_extension_point_register (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME);
976       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
977
978       ep = g_io_extension_point_register (G_VOLUME_MONITOR_EXTENSION_POINT_NAME);
979       g_io_extension_point_set_required_type (ep, G_TYPE_VOLUME_MONITOR);
980       
981       ep = g_io_extension_point_register (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME);
982       g_io_extension_point_set_required_type (ep, G_TYPE_NATIVE_VOLUME_MONITOR);
983       
984       ep = g_io_extension_point_register (G_VFS_EXTENSION_POINT_NAME);
985       g_io_extension_point_set_required_type (ep, G_TYPE_VFS);
986
987       ep = g_io_extension_point_register ("gsettings-backend");
988       g_io_extension_point_set_required_type (ep, G_TYPE_OBJECT);
989
990       ep = g_io_extension_point_register (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
991       g_io_extension_point_set_required_type (ep, G_TYPE_PROXY_RESOLVER);
992
993       ep = g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME);
994       g_io_extension_point_set_required_type (ep, G_TYPE_PROXY);
995
996       ep = g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
997       g_io_extension_point_set_required_type (ep, G_TYPE_TLS_BACKEND);
998
999       ep = g_io_extension_point_register (G_NETWORK_MONITOR_EXTENSION_POINT_NAME);
1000       g_io_extension_point_set_required_type (ep, G_TYPE_NETWORK_MONITOR);
1001
1002       ep = g_io_extension_point_register (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME);
1003       g_io_extension_point_set_required_type (ep, G_TYPE_NOTIFICATION_BACKEND);
1004     }
1005   
1006   G_UNLOCK (registered_extensions);
1007 }
1008
1009 void
1010 _g_io_modules_ensure_loaded (void)
1011 {
1012   static gboolean loaded_dirs = FALSE;
1013   const char *module_path;
1014   GIOModuleScope *scope;
1015
1016   _g_io_modules_ensure_extension_points_registered ();
1017   
1018   G_LOCK (loaded_dirs);
1019
1020   if (!loaded_dirs)
1021     {
1022       loaded_dirs = TRUE;
1023       scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
1024
1025       /* First load any overrides, extras */
1026       module_path = g_getenv ("GIO_EXTRA_MODULES");
1027       if (module_path)
1028         {
1029           gchar **paths;
1030           int i;
1031
1032           paths = g_strsplit (module_path, G_SEARCHPATH_SEPARATOR_S, 0);
1033
1034           for (i = 0; paths[i] != NULL; i++)
1035             {
1036               g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
1037             }
1038
1039           g_strfreev (paths);
1040         }
1041
1042       /* Then load the compiled in path */
1043       g_io_modules_scan_all_in_directory_with_scope (GIO_MODULE_DIR, scope);
1044
1045       g_io_module_scope_free (scope);
1046
1047       /* Initialize types from built-in "modules" */
1048       g_type_ensure (g_null_settings_backend_get_type ());
1049       g_type_ensure (g_memory_settings_backend_get_type ());
1050 #if defined(HAVE_SYS_INOTIFY_H) || defined(HAVE_LINUX_INOTIFY_H)
1051       g_type_ensure (_g_inotify_directory_monitor_get_type ());
1052       g_type_ensure (_g_inotify_file_monitor_get_type ());
1053 #endif
1054 #if defined(HAVE_KQUEUE)
1055       g_type_ensure (_g_kqueue_directory_monitor_get_type ());
1056       g_type_ensure (_g_kqueue_file_monitor_get_type ());
1057 #endif
1058 #if defined(HAVE_FEN)
1059       g_type_ensure (_g_fen_directory_monitor_get_type ());
1060       g_type_ensure (_g_fen_file_monitor_get_type ());
1061 #endif
1062 #ifdef G_OS_WIN32
1063       g_type_ensure (_g_win32_volume_monitor_get_type ());
1064       g_type_ensure (g_win32_directory_monitor_get_type ());
1065       g_type_ensure (g_registry_backend_get_type ());
1066 #endif
1067 #ifdef HAVE_CARBON
1068       g_nextstep_settings_backend_get_type ();
1069 #endif
1070 #ifdef G_OS_UNIX
1071       g_type_ensure (_g_unix_volume_monitor_get_type ());
1072       g_type_ensure (g_fdo_notification_backend_get_type ());
1073       g_type_ensure (g_gtk_notification_backend_get_type ());
1074 #endif
1075 #ifdef G_OS_WIN32
1076       g_type_ensure (_g_winhttp_vfs_get_type ());
1077 #endif
1078       g_type_ensure (_g_local_vfs_get_type ());
1079       g_type_ensure (_g_dummy_proxy_resolver_get_type ());
1080       g_type_ensure (_g_socks4a_proxy_get_type ());
1081       g_type_ensure (_g_socks4_proxy_get_type ());
1082       g_type_ensure (_g_socks5_proxy_get_type ());
1083       g_type_ensure (_g_dummy_tls_backend_get_type ());
1084       g_type_ensure (g_network_monitor_base_get_type ());
1085 #ifdef HAVE_NETLINK
1086       g_type_ensure (_g_network_monitor_netlink_get_type ());
1087 #endif
1088     }
1089
1090   G_UNLOCK (loaded_dirs);
1091 }
1092
1093 static void
1094 g_io_extension_point_free (GIOExtensionPoint *ep)
1095 {
1096   GList *walk;
1097
1098   g_free (ep->name);
1099
1100   for (walk = ep->extensions; walk != NULL; walk = walk->next)
1101     {
1102       GIOExtension *extension = walk->data;
1103
1104       g_free (extension->name);
1105       g_slice_free (GIOExtension, extension);
1106     }
1107   g_list_free_full (ep->lazy_load_modules, g_object_unref);
1108   g_list_free (ep->extensions);
1109
1110   g_free (ep);
1111 }
1112
1113 /**
1114  * g_io_extension_point_register:
1115  * @name: The name of the extension point
1116  *
1117  * Registers an extension point.
1118  *
1119  * Returns: (transfer none): the new #GIOExtensionPoint. This object is
1120  *    owned by GIO and should not be freed.
1121  */
1122 GIOExtensionPoint *
1123 g_io_extension_point_register (const char *name)
1124 {
1125   GIOExtensionPoint *ep;
1126   
1127   G_LOCK (extension_points);
1128   if (extension_points == NULL)
1129     extension_points = g_hash_table_new_full (g_str_hash,
1130                                               g_str_equal,
1131                                               NULL,
1132                                               (GDestroyNotify)g_io_extension_point_free);
1133
1134   ep = g_hash_table_lookup (extension_points, name);
1135   if (ep != NULL)
1136     {
1137       G_UNLOCK (extension_points);
1138       return ep;
1139     }
1140
1141   ep = g_new0 (GIOExtensionPoint, 1);
1142   ep->name = g_strdup (name);
1143   
1144   g_hash_table_insert (extension_points, ep->name, ep);
1145   
1146   G_UNLOCK (extension_points);
1147
1148   return ep;
1149 }
1150
1151 /**
1152  * g_io_extension_point_lookup:
1153  * @name: the name of the extension point
1154  *
1155  * Looks up an existing extension point.
1156  *
1157  * Returns: (transfer none): the #GIOExtensionPoint, or %NULL if there
1158  *    is no registered extension point with the given name.
1159  */
1160 GIOExtensionPoint *
1161 g_io_extension_point_lookup (const char *name)
1162 {
1163   GIOExtensionPoint *ep;
1164
1165   G_LOCK (extension_points);
1166   ep = NULL;
1167   if (extension_points != NULL)
1168     ep = g_hash_table_lookup (extension_points, name);
1169   
1170   G_UNLOCK (extension_points);
1171
1172   return ep;
1173   
1174 }
1175
1176 /**
1177  * g_io_extension_point_set_required_type:
1178  * @extension_point: a #GIOExtensionPoint
1179  * @type: the #GType to require
1180  *
1181  * Sets the required type for @extension_point to @type. 
1182  * All implementations must henceforth have this type.
1183  */
1184 void
1185 g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
1186                                         GType              type)
1187 {
1188   extension_point->required_type = type;
1189 }
1190
1191 /**
1192  * g_io_extension_point_get_required_type:
1193  * @extension_point: a #GIOExtensionPoint
1194  *
1195  * Gets the required type for @extension_point.
1196  *
1197  * Returns: the #GType that all implementations must have, 
1198  *     or #G_TYPE_INVALID if the extension point has no required type
1199  */
1200 GType
1201 g_io_extension_point_get_required_type (GIOExtensionPoint *extension_point)
1202 {
1203   return extension_point->required_type;
1204 }
1205
1206 static void
1207 lazy_load_modules (GIOExtensionPoint *extension_point)
1208 {
1209   GIOModule *module;
1210   GList *l;
1211
1212   for (l = extension_point->lazy_load_modules; l != NULL; l = l->next)
1213     {
1214       module = l->data;
1215
1216       if (!module->initialized)
1217         {
1218           if (g_type_module_use (G_TYPE_MODULE (module)))
1219             g_type_module_unuse (G_TYPE_MODULE (module)); /* Unload */
1220           else
1221             g_printerr ("Failed to load module: %s\n",
1222                         module->filename);
1223         }
1224     }
1225 }
1226
1227 /**
1228  * g_io_extension_point_get_extensions:
1229  * @extension_point: a #GIOExtensionPoint
1230  *
1231  * Gets a list of all extensions that implement this extension point.
1232  * The list is sorted by priority, beginning with the highest priority.
1233  *
1234  * Returns: (element-type GIOExtension) (transfer none): a #GList of
1235  * #GIOExtension<!-- -->s. The list is owned by GIO and should not be
1236  * modified.
1237  */
1238 GList *
1239 g_io_extension_point_get_extensions (GIOExtensionPoint *extension_point)
1240 {
1241   lazy_load_modules (extension_point);
1242   return extension_point->extensions;
1243 }
1244
1245 /**
1246  * g_io_extension_point_get_extension_by_name:
1247  * @extension_point: a #GIOExtensionPoint
1248  * @name: the name of the extension to get
1249  *
1250  * Finds a #GIOExtension for an extension point by name.
1251  *
1252  * Returns: (transfer none): the #GIOExtension for @extension_point that has the
1253  *    given name, or %NULL if there is no extension with that name
1254  */
1255 GIOExtension *
1256 g_io_extension_point_get_extension_by_name (GIOExtensionPoint *extension_point,
1257                                             const char        *name)
1258 {
1259   GList *l;
1260
1261   lazy_load_modules (extension_point);
1262   for (l = extension_point->extensions; l != NULL; l = l->next)
1263     {
1264       GIOExtension *e = l->data;
1265
1266       if (e->name != NULL &&
1267           strcmp (e->name, name) == 0)
1268         return e;
1269     }
1270   
1271   return NULL;
1272 }
1273
1274 static gint
1275 extension_prio_compare (gconstpointer  a,
1276                         gconstpointer  b)
1277 {
1278   const GIOExtension *extension_a = a, *extension_b = b;
1279
1280   if (extension_a->priority > extension_b->priority)
1281     return -1;
1282
1283   if (extension_b->priority > extension_a->priority)
1284     return 1;
1285
1286   return 0;
1287 }
1288
1289 /**
1290  * g_io_extension_point_implement:
1291  * @extension_point_name: the name of the extension point
1292  * @type: the #GType to register as extension 
1293  * @extension_name: the name for the extension
1294  * @priority: the priority for the extension
1295  *
1296  * Registers @type as extension for the extension point with name
1297  * @extension_point_name. 
1298  *
1299  * If @type has already been registered as an extension for this 
1300  * extension point, the existing #GIOExtension object is returned.
1301  *
1302  * Returns: (transfer none): a #GIOExtension object for #GType
1303  */
1304 GIOExtension *
1305 g_io_extension_point_implement (const char *extension_point_name,
1306                                 GType       type,
1307                                 const char *extension_name,
1308                                 gint        priority)
1309 {
1310   GIOExtensionPoint *extension_point;
1311   GIOExtension *extension;
1312   GList *l;
1313
1314   g_return_val_if_fail (extension_point_name != NULL, NULL);
1315
1316   extension_point = g_io_extension_point_lookup (extension_point_name);
1317   if (extension_point == NULL)
1318     {
1319       g_warning ("Tried to implement non-registered extension point %s", extension_point_name);
1320       return NULL;
1321     }
1322   
1323   if (extension_point->required_type != 0 &&
1324       !g_type_is_a (type, extension_point->required_type))
1325     {
1326       g_warning ("Tried to register an extension of the type %s to extension point %s. "
1327                  "Expected type is %s.",
1328                  g_type_name (type),
1329                  extension_point_name, 
1330                  g_type_name (extension_point->required_type));
1331       return NULL;
1332     }      
1333
1334   /* It's safe to register the same type multiple times */
1335   for (l = extension_point->extensions; l != NULL; l = l->next)
1336     {
1337       extension = l->data;
1338       if (extension->type == type)
1339         return extension;
1340     }
1341   
1342   extension = g_slice_new0 (GIOExtension);
1343   extension->type = type;
1344   extension->name = g_strdup (extension_name);
1345   extension->priority = priority;
1346   
1347   extension_point->extensions = g_list_insert_sorted (extension_point->extensions,
1348                                                       extension, extension_prio_compare);
1349   
1350   return extension;
1351 }
1352
1353 /**
1354  * g_io_extension_ref_class:
1355  * @extension: a #GIOExtension
1356  *
1357  * Gets a reference to the class for the type that is 
1358  * associated with @extension.
1359  *
1360  * Returns: (transfer full): the #GTypeClass for the type of @extension
1361  */
1362 GTypeClass *
1363 g_io_extension_ref_class (GIOExtension *extension)
1364 {
1365   return g_type_class_ref (extension->type);
1366 }
1367
1368 /**
1369  * g_io_extension_get_type:
1370  * @extension: a #GIOExtension
1371  *
1372  * Gets the type associated with @extension.
1373  *
1374  * Returns: the type of @extension
1375  */
1376 GType
1377 g_io_extension_get_type (GIOExtension *extension)
1378 {
1379   return extension->type;
1380 }
1381
1382 /**
1383  * g_io_extension_get_name:
1384  * @extension: a #GIOExtension
1385  *
1386  * Gets the name under which @extension was registered.
1387  *
1388  * Note that the same type may be registered as extension
1389  * for multiple extension points, under different names.
1390  *
1391  * Returns: the name of @extension.
1392  */
1393 const char *
1394 g_io_extension_get_name (GIOExtension *extension)
1395 {
1396   return extension->name;
1397 }
1398
1399 /**
1400  * g_io_extension_get_priority:
1401  * @extension: a #GIOExtension
1402  *
1403  * Gets the priority with which @extension was registered.
1404  *
1405  * Returns: the priority of @extension
1406  */
1407 gint
1408 g_io_extension_get_priority (GIOExtension *extension)
1409 {
1410   return extension->priority;
1411 }