No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | tracker-miner-files-index.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include <libtracker-common/tracker-dbus.h>
23 #include <libtracker-sparql/tracker-sparql.h>
24 #include <libtracker-miner/tracker-miner-dbus.h>
25
26 #include "tracker-miner-files-index.h"
27 #include "tracker-marshal.h"
28
29
30 static const gchar introspection_xml[] =
31 "<node>"
32 " <interface name='org.freedesktop.Tracker1.Miner.Files.Index'>"
33 " <method name='ReindexMimeTypes'>"
34 " <arg type='as' name='mime_types' direction='in' />"
35 " </method>"
36 " <method name='IndexFile'>"
37 " <arg type='s' name='file_uri' direction='in' />"
38 " </method>"
39 " </interface>"
40 "</node>";
41
42 /* If defined, then a file provided to be indexed MUST be a child in
43 * an configured path. if undefined, any file can be indexed, however
44 * it is up to applications to maintain files outside the configured
45 * locations.
46 */
47 #undef REQUIRE_LOCATION_IN_CONFIG
48
49 typedef struct {
50 TrackerDBusRequest *request;
51 GDBusMethodInvocation *invocation;
52 TrackerSparqlConnection *connection;
53 TrackerMinerFiles *miner_files;
54 } MimeTypesData;
55
56 typedef struct {
57 TrackerMinerFiles *files_miner;
58 GDBusConnection *d_connection;
59 GDBusNodeInfo *introspection_data;
60 guint registration_id;
61 gchar *full_name;
62 gchar *full_path;
63 } TrackerMinerFilesIndexPrivate;
64
65 enum {
66 PROP_0,
67 PROP_FILES_MINER
68 };
69
70 #define TRACKER_MINER_FILES_INDEX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_FILES_INDEX, TrackerMinerFilesIndexPrivate))
71
72 static void index_set_property (GObject *object,
73 guint param_id,
74 const GValue *value,
75 GParamSpec *pspec);
76 static void index_get_property (GObject *object,
77 guint param_id,
78 GValue *value,
79 GParamSpec *pspec);
80 static void index_finalize (GObject *object);
81
82 G_DEFINE_TYPE(TrackerMinerFilesIndex, tracker_miner_files_index, G_TYPE_OBJECT)
83
84 static void
85 tracker_miner_files_index_class_init (TrackerMinerFilesIndexClass *klass)
86 {
87 GObjectClass *object_class;
88
89 object_class = G_OBJECT_CLASS (klass);
90
91 object_class->finalize = index_finalize;
92 object_class->set_property = index_set_property;
93 object_class->get_property = index_get_property;
94
95 g_object_class_install_property (object_class,
96 PROP_FILES_MINER,
97 g_param_spec_object ("files_miner",
98 "files_miner",
99 "The FS Miner",
100 TRACKER_TYPE_MINER_FILES,
101 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
102
103 g_type_class_add_private (klass, sizeof (TrackerMinerFilesIndexPrivate));
104 }
105
106 static void
107 index_set_property (GObject *object,
108 guint param_id,
109 const GValue *value,
110 GParamSpec *pspec)
111 {
112 TrackerMinerFilesIndexPrivate *priv;
113
114 priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (object);
115
116 switch (param_id) {
117 case PROP_FILES_MINER:
118 priv->files_miner = g_value_dup_object (value);
119 break;
120 default:
121 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
122 break;
123 }
124 }
125
126
127 static void
128 index_get_property (GObject *object,
129 guint param_id,
130 GValue *value,
131 GParamSpec *pspec)
132 {
133 TrackerMinerFilesIndexPrivate *priv;
134
135 priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (object);
136
137 switch (param_id) {
138 case PROP_FILES_MINER:
139 g_value_set_object (value, priv->files_miner);
140 break;
141 default:
142 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
143 break;
144 }
145 }
146
147 static void
148 index_finalize (GObject *object)
149 {
150 TrackerMinerFilesIndexPrivate *priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (object);
151
152 if (priv->registration_id != 0) {
153 g_dbus_connection_unregister_object (priv->d_connection,
154 priv->registration_id);
155 }
156
157 if (priv->introspection_data) {
158 g_dbus_node_info_unref (priv->introspection_data);
159 }
160
161 if (priv->d_connection) {
162 g_object_unref (priv->d_connection);
163 }
164
165 g_free (priv->full_name);
166 g_free (priv->full_path);
167
168 g_object_unref (priv->files_miner);
169 }
170
171 static MimeTypesData *
172 mime_types_data_new (TrackerDBusRequest *request,
173 GDBusMethodInvocation *invocation,
174 TrackerSparqlConnection *connection,
175 TrackerMinerFiles *miner_files)
176 {
177 MimeTypesData *mtd;
178
179 mtd = g_slice_new0 (MimeTypesData);
180
181 mtd->miner_files = g_object_ref (miner_files);
182 mtd->request = request;
183 mtd->invocation = invocation;
184 mtd->connection = g_object_ref (connection);
185
186 return mtd;
187 }
188
189 static void
190 mime_types_data_destroy (gpointer data)
191 {
192 MimeTypesData *mtd;
193
194 mtd = data;
195
196 g_object_unref (mtd->miner_files);
197 g_object_unref (mtd->connection);
198
199 g_slice_free (MimeTypesData, mtd);
200 }
201
202 static void
203 mime_types_cb (GObject *object,
204 GAsyncResult *result,
205 gpointer user_data)
206 {
207 MimeTypesData *mtd = user_data;
208 TrackerSparqlCursor *cursor;
209 GError *error = NULL;
210
211 cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (object),
212 result,
213 &error);
214
215 if (cursor) {
216 tracker_dbus_request_comment (mtd->request,
217 "Found files that will need reindexing");
218
219 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
220 GFile *file;
221 const gchar *url;
222
223 url = tracker_sparql_cursor_get_string (cursor, 0, NULL);
224 file = g_file_new_for_uri (url);
225 tracker_miner_fs_check_file (TRACKER_MINER_FS (mtd->miner_files), file, FALSE);
226 g_object_unref (file);
227 }
228
229 tracker_dbus_request_end (mtd->request, NULL);
230 g_dbus_method_invocation_return_value (mtd->invocation, NULL);
231 } else {
232 tracker_dbus_request_end (mtd->request, error);
233 g_dbus_method_invocation_return_gerror (mtd->invocation, error);
234 }
235
236 mime_types_data_destroy (user_data);
237 }
238
239 static void
240 tracker_miner_files_index_reindex_mime_types (TrackerMinerFilesIndex *miner,
241 GDBusMethodInvocation *invocation,
242 GVariant *parameters)
243 {
244 TrackerMinerFilesIndexPrivate *priv;
245 GString *query;
246 GError *inner_error = NULL;
247 TrackerSparqlConnection *connection;
248 TrackerDBusRequest *request;
249 gint len, i;
250 GStrv mime_types = NULL;
251
252 priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (miner);
253
254 g_variant_get (parameters, "(^a&s)", &mime_types);
255
256 len = mime_types ? g_strv_length (mime_types) : 0;
257
258 tracker_gdbus_async_return_if_fail (len > 0, invocation);
259
260 request = tracker_g_dbus_request_begin (invocation, "%s(%d mime types)",
261 __FUNCTION__,
262 len);
263
264 connection = tracker_sparql_connection_get (NULL, &inner_error);
265
266 if (!connection) {
267 g_free (mime_types);
268 tracker_dbus_request_end (request, inner_error);
269 g_dbus_method_invocation_return_gerror (invocation, inner_error);
270 g_error_free (inner_error);
271 return;
272 }
273
274 tracker_dbus_request_comment (request,
275 "Attempting to reindex the following mime types:");
276
277 query = g_string_new ("SELECT ?url "
278 "WHERE {"
279 " ?resource nie:url ?url ;"
280 " nie:mimeType ?mime ."
281 " FILTER(");
282
283 for (i = 0; i < len; i++) {
284 tracker_dbus_request_comment (request, " %s", mime_types[i]);
285 g_string_append_printf (query, "?mime = '%s'", mime_types[i]);
286
287 if (i < len - 1) {
288 g_string_append (query, " || ");
289 }
290 }
291
292 g_string_append (query, ") }");
293
294 /* FIXME: save last call id */
295 tracker_sparql_connection_query_async (connection,
296 query->str,
297 NULL,
298 mime_types_cb,
299 mime_types_data_new (request,
300 invocation,
301 connection,
302 priv->files_miner));
303
304 g_string_free (query, TRUE);
305 g_object_unref (connection);
306 g_free (mime_types);
307 }
308
309 static void
310 handle_method_call_index_file (TrackerMinerFilesIndex *miner,
311 GDBusMethodInvocation *invocation,
312 GVariant *parameters)
313 {
314 TrackerMinerFilesIndexPrivate *priv;
315 TrackerDBusRequest *request;
316 GFile *file;
317 GFileInfo *file_info;
318 gboolean is_dir;
319 gboolean do_checks = FALSE;
320 GError *internal_error;
321 const gchar *file_uri;
322
323 priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (miner);
324
325 g_variant_get (parameters, "(&s)", &file_uri);
326
327 tracker_gdbus_async_return_if_fail (file_uri != NULL, invocation);
328
329 request = tracker_g_dbus_request_begin (invocation, "%s(uri:'%s')", __FUNCTION__, file_uri);
330
331 file = g_file_new_for_uri (file_uri);
332
333 file_info = g_file_query_info (file,
334 G_FILE_ATTRIBUTE_STANDARD_TYPE,
335 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
336 NULL, NULL);
337
338 if (!file_info) {
339 internal_error = g_error_new_literal (1, 0, "File does not exist");
340 tracker_dbus_request_end (request, internal_error);
341 g_dbus_method_invocation_return_gerror (invocation, internal_error);
342
343 g_error_free (internal_error);
344
345 g_object_unref (file);
346
347 return;
348 }
349
350 is_dir = (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY);
351 g_object_unref (file_info);
352
353 #ifdef REQUIRE_LOCATION_IN_CONFIG
354 do_checks = TRUE;
355 if (!tracker_miner_files_is_file_eligible (priv->files_miner, file)) {
356 internal_error = g_error_new_literal (1, 0, "File is not eligible to be indexed");
357 tracker_dbus_request_end (request, internal_error);
358 g_dbus_method_invocation_return_gerror (invocation, internal_error);
359
360 g_error_free (internal_error);
361
362 g_object_unref (file);
363
364 return;
365 }
366 #endif /* REQUIRE_LOCATION_IN_CONFIG */
367
368 if (is_dir) {
369 tracker_miner_fs_check_directory (TRACKER_MINER_FS (priv->files_miner), file, do_checks);
370 } else {
371 tracker_miner_fs_check_file (TRACKER_MINER_FS (priv->files_miner), file, do_checks);
372 }
373
374 tracker_dbus_request_end (request, NULL);
375 g_dbus_method_invocation_return_value (invocation, NULL);
376
377 g_object_unref (file);
378 }
379
380 static void
381 handle_method_call (GDBusConnection *connection,
382 const gchar *sender,
383 const gchar *object_path,
384 const gchar *interface_name,
385 const gchar *method_name,
386 GVariant *parameters,
387 GDBusMethodInvocation *invocation,
388 gpointer user_data)
389 {
390 TrackerMinerFilesIndex *miner = user_data;
391
392 tracker_gdbus_async_return_if_fail (miner != NULL, invocation);
393 tracker_gdbus_async_return_if_fail (TRACKER_IS_MINER_FILES_INDEX (miner), invocation);
394
395 if (g_strcmp0 (method_name, "ReindexMimeTypes") == 0) {
396 tracker_miner_files_index_reindex_mime_types (miner, invocation, parameters);
397 } else if (g_strcmp0 (method_name, "IndexFile") == 0) {
398 handle_method_call_index_file (miner, invocation, parameters);
399 } else {
400 g_assert_not_reached ();
401 }
402 }
403
404 static GVariant *
405 handle_get_property (GDBusConnection *connection,
406 const gchar *sender,
407 const gchar *object_path,
408 const gchar *interface_name,
409 const gchar *property_name,
410 GError **error,
411 gpointer user_data)
412 {
413 g_assert_not_reached ();
414 return NULL;
415 }
416
417 static gboolean
418 handle_set_property (GDBusConnection *connection,
419 const gchar *sender,
420 const gchar *object_path,
421 const gchar *interface_name,
422 const gchar *property_name,
423 GVariant *value,
424 GError **error,
425 gpointer user_data)
426 {
427 g_assert_not_reached ();
428 return TRUE;
429 }
430
431 static void
432 tracker_miner_files_index_init (TrackerMinerFilesIndex *object)
433 {
434 }
435
436 TrackerMinerFilesIndex *
437 tracker_miner_files_index_new (TrackerMinerFiles *miner_files)
438 {
439 GObject *miner;
440 TrackerMinerFilesIndexPrivate *priv;
441 gchar *full_path, *full_name;
442 GVariant *reply;
443 guint32 rval;
444 GError *error = NULL;
445 GDBusInterfaceVTable interface_vtable = {
446 handle_method_call,
447 handle_get_property,
448 handle_set_property
449 };
450
451 miner = g_object_new (TRACKER_TYPE_MINER_FILES_INDEX,
452 "files-miner", miner_files,
453 NULL);
454
455 priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (miner);
456
457 priv->d_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
458
459 if (!priv->d_connection) {
460 g_critical ("Could not connect to the D-Bus session bus, %s",
461 error ? error->message : "no error given.");
462 g_clear_error (&error);
463 g_object_unref (miner);
464 return NULL;
465 }
466
467 priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &error);
468 if (!priv->introspection_data) {
469 g_critical ("Could not create node info from introspection XML, %s",
470 error ? error->message : "no error given.");
471 g_clear_error (&error);
472 return NULL;
473 }
474
475 full_name = g_strconcat (TRACKER_MINER_DBUS_NAME_PREFIX, "Files.Index", NULL);
476 priv->full_name = full_name;
477
478 /* Register the service name for the miner */
479 full_path = g_strconcat (TRACKER_MINER_DBUS_PATH_PREFIX, "Files/Index", NULL);
480
481 g_message ("Registering D-Bus object...");
482 g_message (" Path:'%s'", full_path);
483 g_message (" Object Type:'%s'", G_OBJECT_TYPE_NAME (miner));
484
485 priv->registration_id =
486 g_dbus_connection_register_object (priv->d_connection,
487 full_path,
488 priv->introspection_data->interfaces[0],
489 &interface_vtable,
490 miner,
491 NULL,
492 &error);
493
494 if (error) {
495 g_critical ("Could not register the D-Bus object %s, %s",
496 full_path,
497 error ? error->message : "no error given.");
498 g_clear_error (&error);
499 g_object_unref (miner);
500 return NULL;
501 }
502
503 reply = g_dbus_connection_call_sync (priv->d_connection,
504 "org.freedesktop.DBus",
505 "/org/freedesktop/DBus",
506 "org.freedesktop.DBus",
507 "RequestName",
508 g_variant_new ("(su)", full_name, 0x4 /* DBUS_NAME_FLAG_DO_NOT_QUEUE */),
509 G_VARIANT_TYPE ("(u)"),
510 0, -1, NULL, &error);
511
512 if (error) {
513 g_critical ("Could not acquire name:'%s', %s",
514 full_name,
515 error->message);
516 g_clear_error (&error);
517 g_object_unref (miner);
518 return NULL;
519 }
520
521 g_variant_get (reply, "(u)", &rval);
522 g_variant_unref (reply);
523
524 if (rval != 1 /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */) {
525 g_critical ("D-Bus service name:'%s' is already taken, "
526 "perhaps the daemon is already running?",
527 full_name);
528 g_object_unref (miner);
529 return NULL;
530 }
531
532 priv->full_path = full_path;
533
534 return (TrackerMinerFilesIndex *) miner;
535 }