No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | nautilus-module.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * nautilus-module.h - Interface to nautilus extensions
4 *
5 * Copyright (C) 2003 Novell, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Dave Camp <dave@ximian.com>
22 *
23 */
24
25 #include <config.h>
26 #include "nautilus-module.h"
27
28 #include <eel/eel-debug.h>
29 #include <gmodule.h>
30
31 #define NAUTILUS_TYPE_MODULE (nautilus_module_get_type ())
32 #define NAUTILUS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_MODULE, NautilusModule))
33 #define NAUTILUS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_MODULE, NautilusModule))
34 #define NAUTILUS_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_MODULE))
35 #define NAUTILUS_IS_MODULE_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_MODULE))
36
37 typedef struct _NautilusModule NautilusModule;
38 typedef struct _NautilusModuleClass NautilusModuleClass;
39
40 struct _NautilusModule {
41 GTypeModule parent;
42
43 GModule *library;
44
45 char *path;
46
47 void (*initialize) (GTypeModule *module);
48 void (*shutdown) (void);
49
50 void (*list_types) (const GType **types,
51 int *num_types);
52
53 };
54
55 struct _NautilusModuleClass {
56 GTypeModuleClass parent;
57 };
58
59 static GList *module_objects = NULL;
60
61 static GType nautilus_module_get_type (void);
62
63 G_DEFINE_TYPE (NautilusModule, nautilus_module, G_TYPE_TYPE_MODULE);
64
65 static gboolean
66 module_pulls_in_orbit (GModule *module)
67 {
68 gpointer symbol;
69 gboolean res;
70
71 res = g_module_symbol (module, "ORBit_realloc_tcval", &symbol);
72
73 return res;
74 }
75
76 static gboolean
77 nautilus_module_load (GTypeModule *gmodule)
78 {
79 NautilusModule *module;
80
81 module = NAUTILUS_MODULE (gmodule);
82
83 module->library = g_module_open (module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
84
85 if (!module->library) {
86 g_warning ("%s", g_module_error ());
87 return FALSE;
88 }
89
90 /* ORBit installs atexit() handlers, which would get unloaded together
91 * with the module now that the main process doesn't depend on GConf anymore,
92 * causing nautilus to sefgault at exit.
93 * If we detect that an extension would pull in ORBit, we make the
94 * module resident to prevent that.
95 */
96 if (module_pulls_in_orbit (module->library)) {
97 g_module_make_resident (module->library);
98 }
99
100 if (!g_module_symbol (module->library,
101 "nautilus_module_initialize",
102 (gpointer *)&module->initialize) ||
103 !g_module_symbol (module->library,
104 "nautilus_module_shutdown",
105 (gpointer *)&module->shutdown) ||
106 !g_module_symbol (module->library,
107 "nautilus_module_list_types",
108 (gpointer *)&module->list_types)) {
109
110 g_warning ("%s", g_module_error ());
111 g_module_close (module->library);
112
113 return FALSE;
114 }
115
116 module->initialize (gmodule);
117
118 return TRUE;
119 }
120
121 static void
122 nautilus_module_unload (GTypeModule *gmodule)
123 {
124 NautilusModule *module;
125
126 module = NAUTILUS_MODULE (gmodule);
127
128 module->shutdown ();
129
130 g_module_close (module->library);
131
132 module->initialize = NULL;
133 module->shutdown = NULL;
134 module->list_types = NULL;
135 }
136
137 static void
138 nautilus_module_finalize (GObject *object)
139 {
140 NautilusModule *module;
141
142 module = NAUTILUS_MODULE (object);
143
144 g_free (module->path);
145
146 G_OBJECT_CLASS (nautilus_module_parent_class)->finalize (object);
147 }
148
149 static void
150 nautilus_module_init (NautilusModule *module)
151 {
152 }
153
154 static void
155 nautilus_module_class_init (NautilusModuleClass *class)
156 {
157 G_OBJECT_CLASS (class)->finalize = nautilus_module_finalize;
158 G_TYPE_MODULE_CLASS (class)->load = nautilus_module_load;
159 G_TYPE_MODULE_CLASS (class)->unload = nautilus_module_unload;
160 }
161
162 static void
163 module_object_weak_notify (gpointer user_data, GObject *object)
164 {
165 module_objects = g_list_remove (module_objects, object);
166 }
167
168 static void
169 add_module_objects (NautilusModule *module)
170 {
171 const GType *types;
172 int num_types;
173 int i;
174
175 module->list_types (&types, &num_types);
176
177 for (i = 0; i < num_types; i++) {
178 if (types[i] == 0) { /* Work around broken extensions */
179 break;
180 }
181 nautilus_module_add_type (types[i]);
182 }
183 }
184
185 static NautilusModule *
186 nautilus_module_load_file (const char *filename)
187 {
188 NautilusModule *module;
189
190 module = g_object_new (NAUTILUS_TYPE_MODULE, NULL);
191 module->path = g_strdup (filename);
192
193 if (g_type_module_use (G_TYPE_MODULE (module))) {
194 add_module_objects (module);
195 g_type_module_unuse (G_TYPE_MODULE (module));
196 return module;
197 } else {
198 g_object_unref (module);
199 return NULL;
200 }
201 }
202
203 static void
204 load_module_dir (const char *dirname)
205 {
206 GDir *dir;
207
208 dir = g_dir_open (dirname, 0, NULL);
209
210 if (dir) {
211 const char *name;
212
213 while ((name = g_dir_read_name (dir))) {
214 if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) {
215 char *filename;
216
217 filename = g_build_filename (dirname,
218 name,
219 NULL);
220 nautilus_module_load_file (filename);
221 g_free (filename);
222 }
223 }
224
225 g_dir_close (dir);
226 }
227 }
228
229 static void
230 free_module_objects (void)
231 {
232 GList *l, *next;
233
234 for (l = module_objects; l != NULL; l = next) {
235 next = l->next;
236 g_object_unref (l->data);
237 }
238
239 g_list_free (module_objects);
240 }
241
242 void
243 nautilus_module_setup (void)
244 {
245 static gboolean initialized = FALSE;
246
247 if (!initialized) {
248 initialized = TRUE;
249
250 load_module_dir (NAUTILUS_EXTENSIONDIR);
251
252 eel_debug_call_at_shutdown (free_module_objects);
253 }
254 }
255
256 GList *
257 nautilus_module_get_extensions_for_type (GType type)
258 {
259 GList *l;
260 GList *ret = NULL;
261
262 for (l = module_objects; l != NULL; l = l->next) {
263 if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (l->data),
264 type)) {
265 g_object_ref (l->data);
266 ret = g_list_prepend (ret, l->data);
267 }
268 }
269
270 return ret;
271 }
272
273 void
274 nautilus_module_extension_list_free (GList *extensions)
275 {
276 GList *l, *next;
277
278 for (l = extensions; l != NULL; l = next) {
279 next = l->next;
280 g_object_unref (l->data);
281 }
282 g_list_free (extensions);
283 }
284
285 void
286 nautilus_module_add_type (GType type)
287 {
288 GObject *object;
289
290 object = g_object_new (type, NULL);
291 g_object_weak_ref (object,
292 (GWeakNotify)module_object_weak_notify,
293 NULL);
294
295 module_objects = g_list_prepend (module_objects, object);
296 }