tracker-0.16.2/src/tracker-extract/tracker-main.c

No issues found

Incomplete coverage

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
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  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 }