No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | tracker-main.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org>
3 * Copyright (C) 2008, Nokia <ivan.frade@nokia.com>
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 Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22
23 #define _XOPEN_SOURCE
24 #include <time.h>
25 #include <stdlib.h>
26 #include <locale.h>
27 #include <signal.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 #include <glib.h>
33 #include <glib-object.h>
34 #include <glib/gi18n.h>
35 #include <gio/gio.h>
36
37 #ifndef G_OS_WIN32
38 #include <sys/resource.h>
39 #endif
40
41 #include <libtracker-common/tracker-log.h>
42 #include <libtracker-common/tracker-dbus.h>
43 #include <libtracker-common/tracker-os-dependant.h>
44 #include <libtracker-common/tracker-ioprio.h>
45 #include <libtracker-common/tracker-locale.h>
46 #include <libtracker-common/tracker-sched.h>
47
48 #include <libtracker-data/tracker-db-manager.h>
49
50 #include "tracker-media-art.h"
51 #include "tracker-config.h"
52 #include "tracker-main.h"
53 #include "tracker-extract.h"
54 #include "tracker-controller.h"
55
56 #ifdef THREAD_ENABLE_TRACE
57 #warning Main thread traces enabled
58 #endif /* THREAD_ENABLE_TRACE */
59
60 #define ABOUT \
61 "Tracker " PACKAGE_VERSION "\n"
62
63 #define LICENSE \
64 "This program is free software and comes without any warranty.\n" \
65 "It is licensed under version 2 or later of the General Public " \
66 "License which can be viewed at:\n" \
67 "\n" \
68 " http://www.gnu.org/licenses/gpl.txt\n"
69
70 #define QUIT_TIMEOUT 30 /* 1/2 minutes worth of seconds */
71
72 static GMainLoop *main_loop;
73
74 static gint verbosity = -1;
75 static gchar *filename;
76 static gchar *mime_type;
77 static gboolean disable_shutdown;
78 static gboolean force_internal_extractors;
79 static gchar *force_module;
80 static gboolean version;
81
82 static TrackerConfig *config;
83
84 static GOptionEntry entries[] = {
85 { "verbosity", 'v', 0,
86 G_OPTION_ARG_INT, &verbosity,
87 N_("Logging, 0 = errors only, "
88 "1 = minimal, 2 = detailed and 3 = debug (default = 0)"),
89 NULL },
90 { "file", 'f', 0,
91 G_OPTION_ARG_FILENAME, &filename,
92 N_("File to extract metadata for"),
93 N_("FILE") },
94 { "mime", 't', 0,
95 G_OPTION_ARG_STRING, &mime_type,
96 N_("MIME type for file (if not provided, this will be guessed)"),
97 N_("MIME") },
98 /* Debug run is used to avoid that the mainloop exits, so that
99 * as a developer you can be relax when running the tool in gdb */
100 { "disable-shutdown", 'd', 0,
101 G_OPTION_ARG_NONE, &disable_shutdown,
102 N_("Disable shutting down after 30 seconds of inactivity"),
103 NULL },
104 { "force-internal-extractors", 'i', 0,
105 G_OPTION_ARG_NONE, &force_internal_extractors,
106 N_("Force internal extractors over 3rd parties like libstreamanalyzer"),
107 NULL },
108 { "force-module", 'm', 0,
109 G_OPTION_ARG_STRING, &force_module,
110 N_("Force a module to be used for extraction (e.g. \"foo\" for \"foo.so\")"),
111 N_("MODULE") },
112 { "version", 'V', 0,
113 G_OPTION_ARG_NONE, &version,
114 N_("Displays version information"),
115 NULL },
116 { NULL }
117 };
118
119 static void
120 initialize_priority_and_scheduling (TrackerSchedIdle sched_idle,
121 gboolean first_time_index)
122 {
123 /* Set CPU priority */
124 if (sched_idle == TRACKER_SCHED_IDLE_ALWAYS ||
125 (sched_idle == TRACKER_SCHED_IDLE_FIRST_INDEX && first_time_index)) {
126 tracker_sched_idle ();
127 }
128
129 /* Set disk IO priority and scheduling */
130 tracker_ioprio_init ();
131
132 /* Set process priority:
133 * The nice() function uses attribute "warn_unused_result" and
134 * so complains if we do not check its returned value. But it
135 * seems that since glibc 2.2.4, nice() can return -1 on a
136 * successful call so we have to check value of errno too.
137 * Stupid...
138 */
139 g_message ("Setting priority nice level to 19");
140
141 if (nice (19) == -1) {
142 const gchar *str = g_strerror (errno);
143
144 g_message ("Couldn't set nice value to 19, %s",
145 str ? str : "no error given");
146 }
147 }
148
149 static void
150 initialize_directories (void)
151 {
152 gchar *user_data_dir;
153
154 /* NOTE: We don't create the database directories here, the
155 * tracker-db-manager does that for us.
156 */
157
158 user_data_dir = g_build_filename (g_get_user_data_dir (),
159 "tracker",
160 NULL);
161
162 /* g_message ("Checking directory exists:'%s'", user_data_dir); */
163 g_mkdir_with_parents (user_data_dir, 00755);
164
165 g_free (user_data_dir);
166 }
167
168 static void
169 signal_handler (int signo)
170 {
171 static gboolean in_loop = FALSE;
172
173 /* Die if we get re-entrant signals handler calls */
174 if (in_loop) {
175 _exit (EXIT_FAILURE);
176 }
177
178 switch (signo) {
179 case SIGABRT:
180 case SIGALRM:
181 _exit (EXIT_FAILURE);
182 break;
183 case SIGTERM:
184 case SIGINT:
185 in_loop = TRUE;
186 disable_shutdown = FALSE;
187 g_main_loop_quit (main_loop);
188
189 /* Fall through */
190 default:
191 if (g_strsignal (signo)) {
192 g_print ("\n");
193 g_print ("Received signal:%d->'%s'\n",
194 signo,
195 g_strsignal (signo));
196 }
197 break;
198 }
199 }
200
201 static void
202 initialize_signal_handler (void)
203 {
204 #ifndef G_OS_WIN32
205 struct sigaction act;
206 sigset_t empty_mask;
207
208 sigemptyset (&empty_mask);
209 act.sa_handler = signal_handler;
210 act.sa_mask = empty_mask;
211 act.sa_flags = 0;
212
213 sigaction (SIGTERM, &act, NULL);
214 sigaction (SIGINT, &act, NULL);
215 sigaction (SIGHUP, &act, NULL);
216 sigaction (SIGALRM, &act, NULL);
217 sigaction (SIGABRT, &act, NULL);
218 #endif /* G_OS_WIN32 */
219 }
220
221 static void
222 log_handler (const gchar *domain,
223 GLogLevelFlags log_level,
224 const gchar *message,
225 gpointer user_data)
226 {
227 switch (log_level) {
228 case G_LOG_LEVEL_WARNING:
229 case G_LOG_LEVEL_CRITICAL:
230 case G_LOG_LEVEL_ERROR:
231 case G_LOG_FLAG_RECURSION:
232 case G_LOG_FLAG_FATAL:
233 g_fprintf (stderr, "%s\n", message);
234 fflush (stderr);
235 break;
236 case G_LOG_LEVEL_MESSAGE:
237 case G_LOG_LEVEL_INFO:
238 case G_LOG_LEVEL_DEBUG:
239 case G_LOG_LEVEL_MASK:
240 default:
241 g_fprintf (stdout, "%s\n", message);
242 fflush (stdout);
243 break;
244 }
245 }
246
247 static void
248 sanity_check_option_values (TrackerConfig *config)
249 {
250 g_message ("General options:");
251 g_message (" Verbosity ............................ %d",
252 tracker_config_get_verbosity (config));
253 g_message (" Sched Idle ........................... %d",
254 tracker_config_get_sched_idle (config));
255 g_message (" Max bytes (per file) ................. %d",
256 tracker_config_get_max_bytes (config));
257 }
258
259 TrackerConfig *
260 tracker_main_get_config (void)
261 {
262 return config;
263 }
264
265 static int
266 run_standalone (TrackerConfig *config)
267 {
268 TrackerExtract *object;
269 GFile *file;
270 gchar *uri;
271
272 /* Set log handler for library messages */
273 g_log_set_default_handler (log_handler, NULL);
274
275 /* Set the default verbosity if unset */
276 if (verbosity == -1) {
277 verbosity = 3;
278 }
279
280 tracker_locale_init ();
281 tracker_media_art_init ();
282
283 /* This makes sure we don't steal all the system's resources */
284 initialize_priority_and_scheduling (tracker_config_get_sched_idle (config),
285 tracker_db_manager_get_first_index_done () == FALSE);
286
287 file = g_file_new_for_commandline_arg (filename);
288 uri = g_file_get_uri (file);
289
290 object = tracker_extract_new (disable_shutdown,
291 force_internal_extractors,
292 force_module);
293
294 if (!object) {
295 g_object_unref (file);
296 g_free (uri);
297 tracker_media_art_shutdown ();
298 tracker_locale_shutdown ();
299 return EXIT_FAILURE;
300 }
301
302 tracker_memory_setrlimits ();
303
304 tracker_extract_get_metadata_by_cmdline (object, uri, mime_type);
305
306 g_object_unref (object);
307 g_object_unref (file);
308 g_free (uri);
309
310 tracker_media_art_shutdown ();
311 tracker_locale_shutdown ();
312
313 return EXIT_SUCCESS;
314 }
315
316 int
317 main (int argc, char *argv[])
318 {
319 GOptionContext *context;
320 GError *error = NULL;
321 TrackerExtract *object;
322 TrackerController *controller;
323 gchar *log_filename = NULL;
324 GMainLoop *my_main_loop;
325 guint shutdown_timeout;
326
327 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
328 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
329 textdomain (GETTEXT_PACKAGE);
330
331 /* Translators: this message will appear immediately after the */
332 /* usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE> */
333 context = g_option_context_new (_("- Extract file meta data"));
334
335 g_option_context_add_main_entries (context, entries, NULL);
336 g_option_context_parse (context, &argc, &argv, &error);
337
338 if (!filename && mime_type) {
339 gchar *help;
340
341 g_printerr ("%s\n\n",
342 _("Filename and mime type must be provided together"));
343
344 help = g_option_context_get_help (context, TRUE, NULL);
345 g_option_context_free (context);
346 g_printerr ("%s", help);
347 g_free (help);
348
349 return EXIT_FAILURE;
350 }
351
352 if (force_internal_extractors && force_module) {
353 gchar *help;
354
355 g_printerr ("%s\n\n",
356 _("Options --force-internal-extractors and --force-module can't be used together"));
357
358 help = g_option_context_get_help (context, TRUE, NULL);
359 g_option_context_free (context);
360 g_printerr ("%s", help);
361 g_free (help);
362
363 return EXIT_FAILURE;
364 }
365
366 g_option_context_free (context);
367
368 if (version) {
369 g_print ("\n" ABOUT "\n" LICENSE "\n");
370 return EXIT_SUCCESS;
371 }
372
373 initialize_signal_handler ();
374
375 g_set_application_name ("tracker-extract");
376
377 setlocale (LC_ALL, "");
378
379 config = tracker_config_new ();
380
381 /* Set conditions when we use stand alone settings */
382 if (filename) {
383 return run_standalone (config);
384 }
385
386 /* Initialize subsystems */
387 initialize_directories ();
388
389 /* Extractor command line arguments */
390 if (verbosity > -1) {
391 tracker_config_set_verbosity (config, verbosity);
392 }
393
394 tracker_log_init (tracker_config_get_verbosity (config), &log_filename);
395 if (log_filename != NULL) {
396 g_message ("Using log file:'%s'", log_filename);
397 g_free (log_filename);
398 }
399
400 g_message ("Shutdown after 30 seconds of inactivity is %s",
401 disable_shutdown ? "disabled" : "enabled");
402
403 sanity_check_option_values (config);
404
405 /* This makes sure we don't steal all the system's resources */
406 initialize_priority_and_scheduling (tracker_config_get_sched_idle (config),
407 tracker_db_manager_get_first_index_done () == FALSE);
408 tracker_memory_setrlimits ();
409
410 if (disable_shutdown) {
411 shutdown_timeout = 0;
412 } else {
413 shutdown_timeout = QUIT_TIMEOUT;
414 }
415
416 object = tracker_extract_new (disable_shutdown,
417 force_internal_extractors,
418 force_module);
419
420 if (!object) {
421 g_object_unref (config);
422 tracker_log_shutdown ();
423 return EXIT_FAILURE;
424 }
425
426 controller = tracker_controller_new (object, shutdown_timeout, &error);
427
428 if (!controller) {
429 g_critical ("Controller thread failed to initialize: %s\n", error->message);
430 g_error_free (error);
431 g_object_unref (config);
432 g_object_unref (object);
433 tracker_log_shutdown ();
434 return EXIT_FAILURE;
435 }
436
437 #ifdef THREAD_ENABLE_TRACE
438 g_debug ("Thread:%p (Main) --- Waiting for extract requests...",
439 g_thread_self ());
440 #endif /* THREAD_ENABLE_TRACE */
441
442 tracker_locale_init ();
443 tracker_media_art_init ();
444
445 /* Main loop */
446 main_loop = g_main_loop_new (NULL, FALSE);
447 g_main_loop_run (main_loop);
448
449 my_main_loop = main_loop;
450 main_loop = NULL;
451 g_main_loop_unref (my_main_loop);
452
453 g_message ("Shutdown started");
454
455 /* Shutdown subsystems */
456 tracker_media_art_shutdown ();
457 tracker_locale_shutdown ();
458
459 g_object_unref (object);
460 g_object_unref (controller);
461
462 tracker_log_shutdown ();
463
464 g_object_unref (config);
465
466 return EXIT_SUCCESS;
467 }