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.1 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, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Alexander Larsson <alexl@redhat.com>
19 */
20
21#include "config.h"
22#include "giomodule.h"
23#include "giomodule-priv.h"
24
25#include <gstdio.h>
26#include <errno.h>
27#include <locale.h>
28
29#include "glib/glib-private.h"
30
31static gboolean
32is_valid_module_name (const gchar *basename)
33{
34#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
35 return
36 g_str_has_prefix (str: basename, prefix: "lib") &&
37 g_str_has_suffix (str: basename, suffix: ".so");
38#else
39 return g_str_has_suffix (basename, ".dll");
40#endif
41}
42
43static void
44query_dir (const char *dirname)
45{
46 GString *data;
47 GDir *dir;
48 GList *list = NULL, *iterator = NULL;
49 const char *name;
50 char *cachename;
51 char **(* query) (void);
52 GError *error;
53 int i;
54
55 if (!g_module_supported ())
56 return;
57
58 error = NULL;
59 dir = g_dir_open (path: dirname, flags: 0, error: &error);
60 if (!dir)
61 {
62 g_printerr (format: "Unable to open directory %s: %s\n", dirname, error->message);
63 g_error_free (error);
64 return;
65 }
66
67 data = g_string_new (init: "");
68
69 while ((name = g_dir_read_name (dir)))
70 list = g_list_prepend (list, data: g_strdup (str: name));
71
72 list = g_list_sort (list, compare_func: (GCompareFunc) g_strcmp0);
73 for (iterator = list; iterator; iterator = iterator->next)
74 {
75 GModule *module;
76 gchar *path;
77 char **extension_points;
78
79 name = iterator->data;
80 if (!is_valid_module_name (basename: name))
81 continue;
82
83 path = g_build_filename (first_element: dirname, name, NULL);
84 module = g_module_open (file_name: path, flags: G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
85 g_free (mem: path);
86
87 if (module)
88 {
89 gchar *modulename;
90 gchar *symname;
91
92 modulename = _g_io_module_extract_name (filename: name);
93 symname = g_strconcat (string1: "g_io_", modulename, "_query", NULL);
94 g_module_symbol (module, symbol_name: symname, symbol: (gpointer) &query);
95 g_free (mem: symname);
96 g_free (mem: modulename);
97
98 if (!query)
99 {
100 /* Fallback to old name */
101 g_module_symbol (module, symbol_name: "g_io_module_query", symbol: (gpointer) &query);
102 }
103
104 if (query)
105 {
106 extension_points = query ();
107
108 if (extension_points)
109 {
110 g_string_append_printf (string: data, format: "%s: ", name);
111
112 for (i = 0; extension_points[i] != NULL; i++)
113 g_string_append_printf (string: data, format: "%s%s", i == 0 ? "" : ",", extension_points[i]);
114
115 g_string_append (string: data, val: "\n");
116 g_strfreev (str_array: extension_points);
117 }
118 }
119
120 g_module_close (module);
121 }
122 }
123
124 g_dir_close (dir);
125 g_list_free_full (list, free_func: g_free);
126
127 cachename = g_build_filename (first_element: dirname, "giomodule.cache", NULL);
128
129 if (data->len > 0)
130 {
131 error = NULL;
132
133 if (!g_file_set_contents (filename: cachename, contents: data->str, length: data->len, error: &error))
134 {
135 g_printerr (format: "Unable to create %s: %s\n", cachename, error->message);
136 g_error_free (error);
137 }
138 }
139 else
140 {
141 if (g_unlink (filename: cachename) != 0 && errno != ENOENT)
142 {
143 int errsv = errno;
144 g_printerr (format: "Unable to unlink %s: %s\n", cachename, g_strerror (errnum: errsv));
145 }
146 }
147
148 g_free (mem: cachename);
149 g_string_free (string: data, TRUE);
150}
151
152int
153main (gint argc,
154 gchar *argv[])
155{
156 int i;
157
158 if (argc == 1)
159 {
160 g_print (format: "Usage: gio-querymodules <directory1> [<directory2> ...]\n");
161 g_print (format: "Will update giomodule.cache in the listed directories\n");
162 return 1;
163 }
164
165 setlocale (LC_ALL, GLIB_DEFAULT_LOCALE);
166
167 /* Be defensive and ensure we're linked to GObject */
168 g_type_ensure (G_TYPE_OBJECT);
169
170 for (i = 1; i < argc; i++)
171 query_dir (dirname: argv[i]);
172
173 return 0;
174}
175

source code of gtk/subprojects/glib/gio/gio-querymodules.c