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 | |
31 | static gboolean |
32 | is_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 | |
43 | static void |
44 | query_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 | |
152 | int |
153 | main (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 | |