1 /*
2  * Copyright (C) 2009, Nokia <ivan.frade@nokia.com>
3  * Copyright (C) 2014, Lanedo <martyn@lanedo.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU 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-miners.h"
22 
23 #include <string.h>
24 #include <stdlib.h>
25 
26 #include <glib.h>
27 #include <gio/gio.h>
28 
29 #define G_SETTINGS_ENABLE_BACKEND
30 #include <gio/gsettingsbackend.h>
31 
32 #include <libtracker-miners-common/tracker-common.h>
33 
34 #include "tracker-config.h"
35 
36 #define CONFIG_SCHEMA "org.freedesktop.Tracker.Miner.Files"
37 #define CONFIG_PATH   "/org/freedesktop/tracker/miner/files/"
38 
39 /* Default values */
40 #define DEFAULT_VERBOSITY                        0
41 #define DEFAULT_SCHED_IDLE                       1
42 #define DEFAULT_INITIAL_SLEEP                    15       /* 0->1000 */
43 #define DEFAULT_ENABLE_MONITORS                  TRUE
44 #define DEFAULT_THROTTLE                         0        /* 0->20 */
45 #define DEFAULT_INDEX_REMOVABLE_DEVICES          FALSE
46 #define DEFAULT_INDEX_OPTICAL_DISCS              FALSE
47 #define DEFAULT_INDEX_ON_BATTERY                 FALSE
48 #define DEFAULT_INDEX_ON_BATTERY_FIRST_TIME      TRUE
49 #define DEFAULT_LOW_DISK_SPACE_LIMIT             1        /* 0->100 / -1 */
50 #define DEFAULT_CRAWLING_INTERVAL                -1       /* 0->365 / -1 / -2 */
51 #define DEFAULT_REMOVABLE_DAYS_THRESHOLD         3        /* 1->365 / 0  */
52 #define DEFAULT_ENABLE_WRITEBACK                 FALSE
53 
54 typedef struct {
55 	/* IMPORTANT: There are 3 versions of the directories:
56 	 * 1. a GStrv stored in GSettings
57 	 * 2. a GSList stored here which is the GStrv without any
58 	 *    aliases or duplicates resolved.
59 	 * 3. a GSList stored here which has duplicates and aliases
60 	 *    resolved.
61 	 */
62 	GSList *index_recursive_directories;
63 	GSList *index_recursive_directories_unfiltered;
64 	GSList *index_single_directories;
65 	GSList *index_single_directories_unfiltered;
66 	GSList *ignored_directories;
67 	GSList *ignored_directories_with_content;
68 	GSList *ignored_files;
69 
70 	/* Convenience data */
71 	GSList *ignored_directory_patterns;
72 	GSList *ignored_directory_paths;
73 	GSList *ignored_file_patterns;
74 	GSList *ignored_file_paths;
75 } TrackerConfigPrivate;
76 
77 static void config_set_property                         (GObject           *object,
78                                                          guint              param_id,
79                                                          const GValue      *value,
80                                                          GParamSpec        *pspec);
81 static void config_get_property                         (GObject           *object,
82                                                          guint              param_id,
83                                                          GValue            *value,
84                                                          GParamSpec        *pspec);
85 static void config_finalize                             (GObject           *object);
86 static void config_constructed                          (GObject           *object);
87 static void config_set_index_recursive_directories      (TrackerConfig     *config,
88                                                          GSList            *roots);
89 static void config_set_index_single_directories         (TrackerConfig     *config,
90                                                          GSList            *roots);
91 static void config_set_ignored_directories              (TrackerConfig     *config,
92                                                          GSList            *roots);
93 static void config_set_ignored_directories_with_content (TrackerConfig     *config,
94                                                          GSList            *roots);
95 static void config_set_ignored_files                    (TrackerConfig     *config,
96                                                          GSList            *files);
97 
98 enum {
99 	PROP_0,
100 
101 	/* General */
102 	PROP_VERBOSITY,
103 	PROP_SCHED_IDLE,
104 	PROP_INITIAL_SLEEP,
105 
106 	/* Monitors */
107 	PROP_ENABLE_MONITORS,
108 
109 	/* Indexing */
110 	PROP_THROTTLE,
111 	PROP_INDEX_ON_BATTERY,
112 	PROP_INDEX_ON_BATTERY_FIRST_TIME,
113 	PROP_INDEX_REMOVABLE_DEVICES,
114 	PROP_INDEX_OPTICAL_DISCS,
115 	PROP_LOW_DISK_SPACE_LIMIT,
116 	PROP_INDEX_RECURSIVE_DIRECTORIES,
117 	PROP_INDEX_SINGLE_DIRECTORIES,
118 	PROP_IGNORED_DIRECTORIES,
119 	PROP_IGNORED_DIRECTORIES_WITH_CONTENT,
120 	PROP_IGNORED_FILES,
121 	PROP_CRAWLING_INTERVAL,
122 	PROP_REMOVABLE_DAYS_THRESHOLD,
123 
124 	/* Writeback */
125 	PROP_ENABLE_WRITEBACK
126 
127 };
128 
G_DEFINE_TYPE_WITH_PRIVATE(TrackerConfig,tracker_config,G_TYPE_SETTINGS)129 G_DEFINE_TYPE_WITH_PRIVATE (TrackerConfig, tracker_config, G_TYPE_SETTINGS)
130 
131 static void
132 tracker_config_class_init (TrackerConfigClass *klass)
133 {
134 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
135 
136 	object_class->set_property = config_set_property;
137 	object_class->get_property = config_get_property;
138 	object_class->finalize     = config_finalize;
139 	object_class->constructed  = config_constructed;
140 
141 	/* General */
142 	g_object_class_install_property (object_class,
143 	                                 PROP_VERBOSITY,
144 	                                 g_param_spec_enum ("verbosity",
145 	                                                    "Log verbosity",
146 	                                                    "Log verbosity (0=errors, 1=minimal, 2=detailed, 3=debug)",
147 	                                                    TRACKER_TYPE_VERBOSITY,
148 	                                                    DEFAULT_VERBOSITY,
149 	                                                    G_PARAM_READWRITE));
150 	g_object_class_install_property (object_class,
151 	                                 PROP_SCHED_IDLE,
152 	                                 g_param_spec_enum ("sched-idle",
153 	                                                    "Scheduler priority when idle",
154 	                                                    "Scheduler priority when idle (0=always, 1=first-index, 2=never)",
155 	                                                    TRACKER_TYPE_SCHED_IDLE,
156 	                                                    DEFAULT_SCHED_IDLE,
157 	                                                    G_PARAM_READWRITE));
158 	g_object_class_install_property (object_class,
159 	                                 PROP_INITIAL_SLEEP,
160 	                                 g_param_spec_int ("initial-sleep",
161 	                                                   "Initial sleep",
162 	                                                   "Time in seconds before crawling filesystem (0->1000)",
163 	                                                   0,
164 	                                                   1000,
165 	                                                   DEFAULT_INITIAL_SLEEP,
166 	                                                   G_PARAM_READWRITE));
167 
168 	/* Monitors */
169 	g_object_class_install_property (object_class,
170 	                                 PROP_ENABLE_MONITORS,
171 	                                 g_param_spec_boolean ("enable-monitors",
172 	                                                       "Enable monitors",
173 	                                                       "Set to false to completely disable any monitoring",
174 	                                                       DEFAULT_ENABLE_MONITORS,
175 	                                                       G_PARAM_READWRITE));
176 
177 	/* Indexing */
178 	g_object_class_install_property (object_class,
179 	                                 PROP_THROTTLE,
180 	                                 g_param_spec_int ("throttle",
181 	                                                   "Throttle",
182 	                                                   "Sets the indexing speed (0->20, where 20=slowest speed)",
183 	                                                   0,
184 	                                                   20,
185 	                                                   DEFAULT_THROTTLE,
186 	                                                   G_PARAM_READWRITE));
187 	g_object_class_install_property (object_class,
188 	                                 PROP_INDEX_ON_BATTERY,
189 	                                 g_param_spec_boolean ("index-on-battery",
190 	                                                       "Index on battery",
191 	                                                       "Set to true to index while running on battery",
192 	                                                       DEFAULT_INDEX_ON_BATTERY,
193 	                                                       G_PARAM_READWRITE));
194 	g_object_class_install_property (object_class,
195 	                                 PROP_INDEX_ON_BATTERY_FIRST_TIME,
196 	                                 g_param_spec_boolean ("index-on-battery-first-time",
197 	                                                       "Index on battery first time",
198 	                                                       "Set to true to index while running on battery for the first time only",
199 	                                                       DEFAULT_INDEX_ON_BATTERY_FIRST_TIME,
200 	                                                       G_PARAM_READWRITE));
201 	g_object_class_install_property (object_class,
202 	                                 PROP_INDEX_REMOVABLE_DEVICES,
203 	                                 g_param_spec_boolean ("index-removable-devices",
204 	                                                       "index removable devices",
205 	                                                       "Set to true to enable traversing mounted directories for removable devices\n"
206 	                                                       "(this includes optical discs)",
207 	                                                       DEFAULT_INDEX_REMOVABLE_DEVICES,
208 	                                                       G_PARAM_READWRITE));
209 	g_object_class_install_property (object_class,
210 	                                 PROP_INDEX_OPTICAL_DISCS,
211 	                                 g_param_spec_boolean ("index-optical-discs",
212 	                                                       "index optical discs",
213 	                                                       "Set to true to enable traversing CDs, DVDs, and generally optical media\n"
214 	                                                       "(if removable devices are not indexed, optical discs won't be either)",
215 	                                                       DEFAULT_INDEX_OPTICAL_DISCS,
216 	                                                       G_PARAM_READWRITE));
217 	g_object_class_install_property (object_class,
218 	                                 PROP_LOW_DISK_SPACE_LIMIT,
219 	                                 g_param_spec_int ("low-disk-space-limit",
220 	                                                   "Low disk space limit",
221 	                                                   "Pause indexer when disk space is <= this value\n"
222 	                                                   "(0->100, value is in % of $HOME file system, -1=disable pausing)",
223 	                                                   -1,
224 	                                                   100,
225 	                                                   DEFAULT_LOW_DISK_SPACE_LIMIT,
226 	                                                   G_PARAM_READWRITE));
227 	g_object_class_install_property (object_class,
228 	                                 PROP_INDEX_RECURSIVE_DIRECTORIES,
229 	                                 g_param_spec_boxed ("index-recursive-directories",
230 	                                                     "Index recursive directories",
231 	                                                     " List of directories to crawl recursively for indexing (separator=;)\n"
232 	                                                     " Special values include: (see /etc/xdg/user-dirs.defaults & $HOME/.config/user-dirs.default)\n"
233 	                                                     "   &DESKTOP\n"
234 	                                                     "   &DOCUMENTS\n"
235 	                                                     "   &DOWNLOAD\n"
236 	                                                     "   &MUSIC\n"
237 	                                                     "   &PICTURES\n"
238 	                                                     "   &PUBLIC_SHARE\n"
239 	                                                     "   &TEMPLATES\n"
240 	                                                     "   &VIDEOS\n"
241 	                                                     " If $HOME is the default below, it is because $HOME/.config/user-dirs.default was missing.",
242 	                                                     G_TYPE_STRV,
243 	                                                     G_PARAM_READWRITE));
244 	g_object_class_install_property (object_class,
245 	                                 PROP_INDEX_SINGLE_DIRECTORIES,
246 	                                 g_param_spec_boxed ("index-single-directories",
247 	                                                     "Index single directories",
248 	                                                     " List of directories to index but not sub-directories for changes (separator=;)\n"
249 	                                                     " Special values used for IndexRecursiveDirectories can also be used here",
250 	                                                     G_TYPE_STRV,
251 	                                                     G_PARAM_READWRITE));
252 	g_object_class_install_property (object_class,
253 	                                 PROP_IGNORED_DIRECTORIES,
254 	                                 g_param_spec_boxed ("ignored-directories",
255 	                                                     "Ignored directories",
256 	                                                     " List of directories to NOT crawl for indexing (separator=;)",
257 	                                                     G_TYPE_STRV,
258 	                                                     G_PARAM_READWRITE));
259 	g_object_class_install_property (object_class,
260 	                                 PROP_IGNORED_DIRECTORIES_WITH_CONTENT,
261 	                                 g_param_spec_boxed ("ignored-directories-with-content",
262 	                                                     "Ignored directories with content",
263 	                                                     " List of directories to NOT crawl for indexing based on child files (separator=;)",
264 	                                                     G_TYPE_STRV,
265 	                                                     G_PARAM_READWRITE));
266 	g_object_class_install_property (object_class,
267 	                                 PROP_IGNORED_FILES,
268 	                                 g_param_spec_boxed ("ignored-files",
269 	                                                     "Ignored files",
270 	                                                     " List of files to NOT index (separator=;)",
271 	                                                     G_TYPE_STRV,
272 	                                                     G_PARAM_READWRITE));
273 	g_object_class_install_property (object_class,
274 	                                 PROP_CRAWLING_INTERVAL,
275 	                                 g_param_spec_int ("crawling-interval",
276 	                                                   "Crawling interval",
277 	                                                   " Interval in days to check the filesystem is up to date in the database,"
278 	                                                   " maximum is 365, default is -1.\n"
279 	                                                   "   -2 = crawling is disabled entirely\n"
280 	                                                   "   -1 = crawling *may* occur on startup (if not cleanly shutdown)\n"
281 	                                                   "    0 = crawling is forced",
282 	                                                   -2,
283 	                                                   365,
284 	                                                   DEFAULT_CRAWLING_INTERVAL,
285 	                                                   G_PARAM_READWRITE));
286 	g_object_class_install_property (object_class,
287 	                                 PROP_REMOVABLE_DAYS_THRESHOLD,
288 	                                 g_param_spec_int ("removable-days-threshold",
289 	                                                   "Removable days threshold",
290 	                                                   " Threshold in days after which files from removables devices"
291 	                                                   " will be removed from database if not mounted. 0 means never, "
292 	                                                   " maximum is 365.",
293 	                                                   0,
294 	                                                   365,
295 	                                                   DEFAULT_REMOVABLE_DAYS_THRESHOLD,
296 	                                                   G_PARAM_READWRITE));
297 
298 	/* Writeback */
299 	g_object_class_install_property (object_class,
300 	                                 PROP_ENABLE_WRITEBACK,
301 	                                 g_param_spec_boolean ("enable-writeback",
302 	                                                       "Enable Writeback",
303 	                                                       "Set to false to disable writeback",
304 	                                                       DEFAULT_ENABLE_WRITEBACK,
305 	                                                       G_PARAM_READWRITE));
306 }
307 
308 static void
tracker_config_init(TrackerConfig * object)309 tracker_config_init (TrackerConfig *object)
310 {
311 }
312 
313 static void
config_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)314 config_set_property (GObject      *object,
315                      guint         param_id,
316                      const GValue *value,
317                      GParamSpec   *pspec)
318 {
319 	TrackerConfig *config = TRACKER_CONFIG (object);
320 
321 	switch (param_id) {
322 		/* General */
323 		/* NOTE: We handle these because we have to be able
324 		 * to save these based on command line overrides.
325 		 */
326 	case PROP_VERBOSITY:
327 		tracker_config_set_verbosity (config, g_value_get_enum (value));
328 		break;
329 	case PROP_INITIAL_SLEEP:
330 		tracker_config_set_initial_sleep (config, g_value_get_int (value));
331 		break;
332 
333 		/* Indexing */
334 		/* NOTE: We handle these specifically because we
335 		 * create convenience data around these lists.
336 		 */
337 	case PROP_INDEX_RECURSIVE_DIRECTORIES: {
338 		GStrv strv = g_value_get_boxed (value);
339 		GSList *dirs = tracker_string_list_to_gslist (strv, -1);
340 
341 		config_set_index_recursive_directories (config, dirs);
342 
343 		g_slist_foreach (dirs, (GFunc) g_free, NULL);
344 		g_slist_free (dirs);
345 
346 		break;
347 	}
348 	case PROP_INDEX_SINGLE_DIRECTORIES: {
349 		GStrv strv = g_value_get_boxed (value);
350 		GSList *dirs = tracker_string_list_to_gslist (strv, -1);
351 
352 		config_set_index_single_directories (config, dirs);
353 
354 		g_slist_foreach (dirs, (GFunc) g_free, NULL);
355 		g_slist_free (dirs);
356 		break;
357 	}
358 	case PROP_IGNORED_DIRECTORIES: {
359 		GStrv strv = g_value_get_boxed (value);
360 		GSList *dirs = tracker_string_list_to_gslist (strv, -1);
361 
362 		config_set_ignored_directories (config, dirs);
363 
364 		g_slist_foreach (dirs, (GFunc) g_free, NULL);
365 		g_slist_free (dirs);
366 		break;
367 	}
368 	case PROP_IGNORED_DIRECTORIES_WITH_CONTENT: {
369 		GStrv strv = g_value_get_boxed (value);
370 		GSList *dirs = tracker_string_list_to_gslist (strv, -1);
371 
372 		config_set_ignored_directories_with_content (config, dirs);
373 
374 		g_slist_foreach (dirs, (GFunc) g_free, NULL);
375 		g_slist_free (dirs);
376 		break;
377 	}
378 	case PROP_IGNORED_FILES: {
379 		GStrv strv = g_value_get_boxed (value);
380 		GSList *files = tracker_string_list_to_gslist (strv, -1);
381 
382 		config_set_ignored_files (config, files);
383 
384 		g_slist_foreach (files, (GFunc) g_free, NULL);
385 		g_slist_free (files);
386 		break;
387 	}
388 	default:
389 		/* We don't care about the others... we don't save anyway. */
390 		break;
391 	};
392 }
393 
394 static void
config_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)395 config_get_property (GObject    *object,
396                      guint       param_id,
397                      GValue     *value,
398                      GParamSpec *pspec)
399 {
400 	TrackerConfig *config = TRACKER_CONFIG (object);
401 	TrackerConfigPrivate *priv = tracker_config_get_instance_private (config);
402 
403 	switch (param_id) {
404 		/* General */
405 	case PROP_VERBOSITY:
406 		g_value_set_enum (value, tracker_config_get_verbosity (config));
407 		break;
408 	case PROP_SCHED_IDLE:
409 		g_value_set_enum (value, tracker_config_get_sched_idle (config));
410 		break;
411 	case PROP_INITIAL_SLEEP:
412 		g_value_set_int (value, tracker_config_get_initial_sleep (config));
413 		break;
414 
415 		/* Montors */
416 	case PROP_ENABLE_MONITORS:
417 		g_value_set_boolean (value, tracker_config_get_enable_monitors (config));
418 		break;
419 
420 		/* Indexing */
421 	case PROP_THROTTLE:
422 		g_value_set_int (value, tracker_config_get_throttle (config));
423 		break;
424 	case PROP_INDEX_ON_BATTERY:
425 		g_value_set_boolean (value, tracker_config_get_index_on_battery (config));
426 		break;
427 	case PROP_INDEX_ON_BATTERY_FIRST_TIME:
428 		g_value_set_boolean (value, tracker_config_get_index_on_battery_first_time (config));
429 		break;
430 	case PROP_INDEX_REMOVABLE_DEVICES:
431 		g_value_set_boolean (value, tracker_config_get_index_removable_devices (config));
432 		break;
433 	case PROP_INDEX_OPTICAL_DISCS:
434 		g_value_set_boolean (value, tracker_config_get_index_optical_discs (config));
435 		break;
436 	case PROP_LOW_DISK_SPACE_LIMIT:
437 		g_value_set_int (value, tracker_config_get_low_disk_space_limit (config));
438 		break;
439 	case PROP_INDEX_RECURSIVE_DIRECTORIES:
440 		g_value_take_boxed (value, tracker_gslist_to_string_list (priv->index_recursive_directories_unfiltered));
441 		break;
442 	case PROP_INDEX_SINGLE_DIRECTORIES:
443 		g_value_take_boxed (value, tracker_gslist_to_string_list (priv->index_single_directories_unfiltered));
444 		break;
445 	case PROP_IGNORED_DIRECTORIES:
446 		g_value_take_boxed (value, tracker_gslist_to_string_list (priv->ignored_directories));
447 		break;
448 	case PROP_IGNORED_DIRECTORIES_WITH_CONTENT:
449 		g_value_take_boxed (value, tracker_gslist_to_string_list (priv->ignored_directories_with_content));
450 		break;
451 	case PROP_IGNORED_FILES:
452 		g_value_take_boxed (value, tracker_gslist_to_string_list (priv->ignored_files));
453 		break;
454 	case PROP_CRAWLING_INTERVAL:
455 		g_value_set_int (value, tracker_config_get_crawling_interval (config));
456 		break;
457 	case PROP_REMOVABLE_DAYS_THRESHOLD:
458 		g_value_set_int (value, tracker_config_get_removable_days_threshold (config));
459 		break;
460 
461 	/* Writeback */
462 	case PROP_ENABLE_WRITEBACK:
463 		g_value_set_boolean (value, tracker_config_get_enable_writeback (config));
464 		break;
465 
466 	/* Did we miss any new properties? */
467 	default:
468 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
469 		break;
470 	};
471 }
472 
473 static void
config_finalize(GObject * object)474 config_finalize (GObject *object)
475 {
476 	TrackerConfigPrivate *priv;
477 
478 	priv = tracker_config_get_instance_private (TRACKER_CONFIG (object));
479 
480 	g_slist_foreach (priv->ignored_file_patterns,
481 	                 (GFunc) g_pattern_spec_free,
482 	                 NULL);
483 	g_slist_free (priv->ignored_file_patterns);
484 
485 	g_slist_foreach (priv->ignored_file_paths,
486 	                 (GFunc) g_free,
487 	                 NULL);
488 	g_slist_free (priv->ignored_file_paths);
489 
490 	g_slist_foreach (priv->ignored_directory_patterns,
491 	                 (GFunc) g_pattern_spec_free,
492 	                 NULL);
493 	g_slist_free (priv->ignored_directory_patterns);
494 
495 	g_slist_foreach (priv->ignored_directory_paths,
496 	                 (GFunc) g_free,
497 	                 NULL);
498 	g_slist_free (priv->ignored_directory_paths);
499 
500 	g_slist_foreach (priv->ignored_files, (GFunc) g_free, NULL);
501 	g_slist_free (priv->ignored_files);
502 
503 	g_slist_foreach (priv->ignored_directories_with_content, (GFunc) g_free, NULL);
504 	g_slist_free (priv->ignored_directories_with_content);
505 
506 	g_slist_foreach (priv->ignored_directories, (GFunc) g_free, NULL);
507 	g_slist_free (priv->ignored_directories);
508 
509 	g_slist_foreach (priv->index_single_directories, (GFunc) g_free, NULL);
510 	g_slist_free (priv->index_single_directories);
511 
512 	g_slist_foreach (priv->index_single_directories_unfiltered, (GFunc) g_free, NULL);
513 	g_slist_free (priv->index_single_directories_unfiltered);
514 
515 	g_slist_foreach (priv->index_recursive_directories, (GFunc) g_free, NULL);
516 	g_slist_free (priv->index_recursive_directories);
517 
518 	g_slist_foreach (priv->index_recursive_directories_unfiltered, (GFunc) g_free, NULL);
519 	g_slist_free (priv->index_recursive_directories_unfiltered);
520 
521 	(G_OBJECT_CLASS (tracker_config_parent_class)->finalize) (object);
522 }
523 
524 static GSList *
dir_mapping_get(GSList * dirs,gboolean is_recursive)525 dir_mapping_get (GSList   *dirs,
526                  gboolean  is_recursive)
527 {
528 	GSList *filtered = NULL;
529 	GSList *evaluated_dirs, *l;
530 
531 	if (dirs) {
532 		filtered = tracker_path_list_filter_duplicates (dirs, ".", is_recursive);
533 	}
534 
535 	evaluated_dirs = NULL;
536 
537 	for (l = filtered; l; l = l->next) {
538 		gchar *path_to_use;
539 
540 		path_to_use = tracker_path_evaluate_name (l->data);
541 
542 		if (path_to_use) {
543 			evaluated_dirs = g_slist_prepend (evaluated_dirs, path_to_use);
544 		}
545 	}
546 
547 	g_slist_foreach (filtered, (GFunc) g_free, NULL);
548 	g_slist_free (filtered);
549 
550 	return g_slist_reverse (evaluated_dirs);
551 }
552 
553 static void
config_set_ignored_file_conveniences(TrackerConfig * config)554 config_set_ignored_file_conveniences (TrackerConfig *config)
555 {
556 	TrackerConfigPrivate *priv;
557 	GSList *l;
558 	GSList *paths = NULL;
559 	GSList *patterns = NULL;
560 
561 	priv = tracker_config_get_instance_private (config);
562 
563 	g_slist_foreach (priv->ignored_file_patterns,
564 	                 (GFunc) g_pattern_spec_free,
565 	                 NULL);
566 	g_slist_free (priv->ignored_file_patterns);
567 
568 	g_slist_foreach (priv->ignored_file_paths,
569 	                 (GFunc) g_free,
570 	                 NULL);
571 	g_slist_free (priv->ignored_file_paths);
572 
573 	for (l = priv->ignored_files; l; l = l->next) {
574 		const gchar *str = l->data;
575 
576 		if (!str) {
577 			continue;
578 		}
579 
580 		if (G_LIKELY (*str != G_DIR_SEPARATOR)) {
581 			GPatternSpec *spec;
582 
583 			spec = g_pattern_spec_new (l->data);
584 			patterns = g_slist_prepend (patterns, spec);
585 		} else {
586 			paths = g_slist_prepend (paths, g_strdup (l->data));
587 		}
588 	}
589 
590 	priv->ignored_file_patterns = g_slist_reverse (patterns);
591 	priv->ignored_file_paths = g_slist_reverse (paths);
592 }
593 
594 static void
config_set_ignored_directory_conveniences(TrackerConfig * config)595 config_set_ignored_directory_conveniences (TrackerConfig *config)
596 {
597 	TrackerConfigPrivate *priv;
598 	GSList *l;
599 	GSList *patterns = NULL;
600 	GSList *paths = NULL;
601 
602 	priv = tracker_config_get_instance_private (config);
603 
604 	g_slist_foreach (priv->ignored_directory_patterns,
605 	                 (GFunc) g_pattern_spec_free,
606 	                 NULL);
607 	g_slist_free (priv->ignored_directory_patterns);
608 
609 	g_slist_foreach (priv->ignored_directory_paths,
610 	                 (GFunc) g_free,
611 	                 NULL);
612 	g_slist_free (priv->ignored_directory_paths);
613 
614 	for (l = priv->ignored_directories; l; l = l->next) {
615 		const gchar *str = l->data;
616 
617 		if (!str) {
618 			continue;
619 		}
620 
621 		if (G_LIKELY (*str != G_DIR_SEPARATOR)) {
622 			GPatternSpec *spec;
623 
624 			spec = g_pattern_spec_new (l->data);
625 			patterns = g_slist_prepend (patterns, spec);
626 		} else {
627 			paths = g_slist_prepend (paths, g_strdup (l->data));
628 		}
629 	}
630 
631 	priv->ignored_directory_patterns = g_slist_reverse (patterns);
632 	priv->ignored_directory_paths = g_slist_reverse (paths);
633 }
634 
635 static void
config_constructed(GObject * object)636 config_constructed (GObject *object)
637 {
638 	GSettings *settings;
639 
640 	(G_OBJECT_CLASS (tracker_config_parent_class)->constructed) (object);
641 
642 	settings = G_SETTINGS (object);
643 
644 	/* NOTE: Without the _delay() call the updates to settings
645 	 * from tracker-preferences may not happen before we notify
646 	 * about the property change from _set_*() APIs. This is
647 	 * because the GValue in set_property() is not up to date at
648 	 * the time we are called back. Quite fscking stupid really if
649 	 * you ask me.
650 	 *
651 	 * NOTE: We need this. If we don't we can't have local
652 	 * settings which are *NOT* stored in the GSettings database.
653 	 * We need this for overriding things like verbosity on start
654 	 * up.
655 	 */
656 	if (G_LIKELY (!g_getenv ("TRACKER_USE_CONFIG_FILES"))) {
657 		g_settings_delay (settings);
658 	}
659 
660 	/* Set up bindings:
661 	 *
662 	 * What's interesting here is that 'verbosity' and
663 	 * 'initial-sleep' are command line arguments that can be
664 	 * overridden, so we don't update the config when we set them
665 	 * from main() because it's a session configuration only, not
666 	 * a permanent one. To do this we use the flag
667 	 * G_SETTINGS_BIND_GET_NO_CHANGES.
668 	 *
669 	 * For the other settings, we don't bind the
670 	 * G_SETTINGS_BIND_SET because we don't want to save anything,
671 	 * ever, we only want to know about updates to the settings as
672 	 * they're changed externally. The only time this may be
673 	 * different is where we use the environment variable
674 	 * TRACKER_USE_CONFIG_FILES and we want to write a config
675 	 * file for convenience. But this is only necessary if the
676 	 * config is different to the default.
677 	 */
678 	g_settings_bind (settings, "verbosity", object, "verbosity", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
679 	g_settings_bind (settings, "sched-idle", object, "sched-idle", G_SETTINGS_BIND_GET);
680 	g_settings_bind (settings, "initial-sleep", object, "initial-sleep", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
681 	g_settings_bind (settings, "throttle", object, "throttle", G_SETTINGS_BIND_GET);
682 	g_settings_bind (settings, "low-disk-space-limit", object, "low-disk-space-limit", G_SETTINGS_BIND_GET);
683 	g_settings_bind (settings, "crawling-interval", object, "crawling-interval", G_SETTINGS_BIND_GET);
684 	g_settings_bind (settings, "low-disk-space-limit", object, "low-disk-space-limit", G_SETTINGS_BIND_GET);
685 	g_settings_bind (settings, "removable-days-threshold", object, "removable-days-threshold", G_SETTINGS_BIND_GET);
686 	g_settings_bind (settings, "enable-monitors", object, "enable-monitors", G_SETTINGS_BIND_GET);
687 	g_settings_bind (settings, "enable-writeback", object, "enable-writeback", G_SETTINGS_BIND_GET);
688 	g_settings_bind (settings, "index-removable-devices", object, "index-removable-devices", G_SETTINGS_BIND_GET);
689 	g_settings_bind (settings, "index-optical-discs", object, "index-optical-discs", G_SETTINGS_BIND_GET);
690 	g_settings_bind (settings, "index-on-battery", object, "index-on-battery", G_SETTINGS_BIND_GET);
691 	g_settings_bind (settings, "index-on-battery-first-time", object, "index-on-battery-first-time", G_SETTINGS_BIND_GET);
692 	g_settings_bind (settings, "index-recursive-directories", object, "index-recursive-directories", G_SETTINGS_BIND_GET);
693 	g_settings_bind (settings, "index-single-directories", object, "index-single-directories", G_SETTINGS_BIND_GET);
694 	g_settings_bind (settings, "ignored-files", object, "ignored-files", G_SETTINGS_BIND_GET);
695 	g_settings_bind (settings, "ignored-directories", object, "ignored-directories", G_SETTINGS_BIND_GET);
696 	g_settings_bind (settings, "ignored-directories-with-content", object, "ignored-directories-with-content", G_SETTINGS_BIND_GET);
697 
698 	config_set_ignored_file_conveniences (TRACKER_CONFIG (object));
699 	config_set_ignored_directory_conveniences (TRACKER_CONFIG (object));
700 }
701 
702 TrackerConfig *
tracker_config_new(void)703 tracker_config_new (void)
704 {
705 	TrackerConfig *config = NULL;
706 
707 	/* FIXME: should we unset GSETTINGS_BACKEND env var? */
708 
709 	if (G_UNLIKELY (g_getenv ("TRACKER_USE_CONFIG_FILES"))) {
710 		GSettingsBackend *backend;
711 		gchar *filename, *basename;
712 		gboolean need_to_save;
713 
714 		basename = g_strdup_printf ("%s.cfg", g_get_prgname ());
715 		filename = g_build_filename (g_get_user_config_dir (), "tracker", basename, NULL);
716 		g_free (basename);
717 
718 		need_to_save = g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE;
719 
720 		backend = g_keyfile_settings_backend_new (filename, CONFIG_PATH, "General");
721 		g_info ("Using config file '%s'", filename);
722 		g_free (filename);
723 
724 		config = g_object_new (TRACKER_TYPE_CONFIG,
725 		                       "backend", backend,
726 		                       "schema-id", CONFIG_SCHEMA,
727 		                       "path", CONFIG_PATH,
728 		                       NULL);
729 		g_object_unref (backend);
730 
731 		if (need_to_save) {
732 			g_info ("  Config file does not exist, using default values...");
733 		}
734 	} else {
735 		config = g_object_new (TRACKER_TYPE_CONFIG,
736 		                       "schema-id", CONFIG_SCHEMA,
737 		                       "path", CONFIG_PATH,
738 		                       NULL);
739 	}
740 
741 	return config;
742 }
743 
744 gint
tracker_config_get_verbosity(TrackerConfig * config)745 tracker_config_get_verbosity (TrackerConfig *config)
746 {
747 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_VERBOSITY);
748 
749 	return g_settings_get_enum (G_SETTINGS (config), "verbosity");
750 }
751 
752 gint
tracker_config_get_sched_idle(TrackerConfig * config)753 tracker_config_get_sched_idle (TrackerConfig *config)
754 {
755 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_SCHED_IDLE);
756 
757 	return g_settings_get_enum (G_SETTINGS (config), "sched-idle");
758 }
759 
760 gint
tracker_config_get_initial_sleep(TrackerConfig * config)761 tracker_config_get_initial_sleep (TrackerConfig *config)
762 {
763 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INITIAL_SLEEP);
764 
765 	return g_settings_get_int (G_SETTINGS (config), "initial-sleep");
766 }
767 
768 gboolean
tracker_config_get_enable_monitors(TrackerConfig * config)769 tracker_config_get_enable_monitors (TrackerConfig *config)
770 {
771 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_ENABLE_MONITORS);
772 
773 	return g_settings_get_boolean (G_SETTINGS (config), "enable-monitors");
774 }
775 
776 gboolean
tracker_config_get_enable_writeback(TrackerConfig * config)777 tracker_config_get_enable_writeback (TrackerConfig *config)
778 {
779 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_ENABLE_WRITEBACK);
780 
781 	return g_settings_get_boolean (G_SETTINGS (config), "enable-writeback");
782 }
783 
784 gint
tracker_config_get_throttle(TrackerConfig * config)785 tracker_config_get_throttle (TrackerConfig *config)
786 {
787 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_THROTTLE);
788 
789 	return g_settings_get_int (G_SETTINGS (config), "throttle");
790 }
791 
792 gboolean
tracker_config_get_index_on_battery(TrackerConfig * config)793 tracker_config_get_index_on_battery (TrackerConfig *config)
794 {
795 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_ON_BATTERY);
796 
797 	return g_settings_get_boolean (G_SETTINGS (config), "index-on-battery");
798 }
799 
800 gboolean
tracker_config_get_index_on_battery_first_time(TrackerConfig * config)801 tracker_config_get_index_on_battery_first_time (TrackerConfig *config)
802 {
803 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_ON_BATTERY_FIRST_TIME);
804 
805 	return g_settings_get_boolean (G_SETTINGS (config), "index-on-battery-first-time");
806 }
807 
808 gboolean
tracker_config_get_index_removable_devices(TrackerConfig * config)809 tracker_config_get_index_removable_devices (TrackerConfig *config)
810 {
811 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_REMOVABLE_DEVICES);
812 
813 	return g_settings_get_boolean (G_SETTINGS (config), "index-removable-devices");
814 }
815 
816 gboolean
tracker_config_get_index_optical_discs(TrackerConfig * config)817 tracker_config_get_index_optical_discs (TrackerConfig *config)
818 {
819 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_OPTICAL_DISCS);
820 
821 	return g_settings_get_boolean (G_SETTINGS (config), "index-optical-discs");
822 }
823 
824 gint
tracker_config_get_low_disk_space_limit(TrackerConfig * config)825 tracker_config_get_low_disk_space_limit (TrackerConfig *config)
826 {
827 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_LOW_DISK_SPACE_LIMIT);
828 
829 	return g_settings_get_int (G_SETTINGS (config), "low-disk-space-limit");
830 }
831 
832 GSList *
tracker_config_get_index_recursive_directories(TrackerConfig * config)833 tracker_config_get_index_recursive_directories (TrackerConfig *config)
834 {
835 	TrackerConfigPrivate *priv;
836 
837 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
838 
839 	priv = tracker_config_get_instance_private (config);
840 
841 	return priv->index_recursive_directories;
842 }
843 
844 GSList *
tracker_config_get_index_single_directories(TrackerConfig * config)845 tracker_config_get_index_single_directories (TrackerConfig *config)
846 {
847 	TrackerConfigPrivate *priv;
848 
849 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
850 
851 	priv = tracker_config_get_instance_private (config);
852 
853 	return priv->index_single_directories;
854 }
855 
856 GSList *
tracker_config_get_ignored_directories(TrackerConfig * config)857 tracker_config_get_ignored_directories (TrackerConfig *config)
858 {
859 	TrackerConfigPrivate *priv;
860 
861 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
862 
863 	priv = tracker_config_get_instance_private (config);
864 
865 	return priv->ignored_directories;
866 }
867 
868 GSList *
tracker_config_get_ignored_directories_with_content(TrackerConfig * config)869 tracker_config_get_ignored_directories_with_content (TrackerConfig *config)
870 {
871 	TrackerConfigPrivate *priv;
872 
873 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
874 
875 	priv = tracker_config_get_instance_private (config);
876 
877 	return priv->ignored_directories_with_content;
878 }
879 
880 GSList *
tracker_config_get_ignored_files(TrackerConfig * config)881 tracker_config_get_ignored_files (TrackerConfig *config)
882 {
883 	TrackerConfigPrivate *priv;
884 
885 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
886 
887 	priv = tracker_config_get_instance_private (config);
888 
889 	return priv->ignored_files;
890 }
891 
892 gint
tracker_config_get_crawling_interval(TrackerConfig * config)893 tracker_config_get_crawling_interval (TrackerConfig *config)
894 {
895 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_CRAWLING_INTERVAL);
896 
897 	return g_settings_get_int (G_SETTINGS (config), "crawling-interval");
898 }
899 
900 gint
tracker_config_get_removable_days_threshold(TrackerConfig * config)901 tracker_config_get_removable_days_threshold (TrackerConfig *config)
902 {
903 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_REMOVABLE_DAYS_THRESHOLD);
904 
905 	return g_settings_get_int (G_SETTINGS (config), "removable-days-threshold");
906 }
907 
908 void
tracker_config_set_verbosity(TrackerConfig * config,gint value)909 tracker_config_set_verbosity (TrackerConfig *config,
910                               gint           value)
911 {
912 	g_return_if_fail (TRACKER_IS_CONFIG (config));
913 
914 	g_settings_set_enum (G_SETTINGS (config), "verbosity", value);
915 	g_object_notify (G_OBJECT (config), "verbosity");
916 }
917 
918 void
tracker_config_set_initial_sleep(TrackerConfig * config,gint value)919 tracker_config_set_initial_sleep (TrackerConfig *config,
920                                   gint           value)
921 {
922 	g_return_if_fail (TRACKER_IS_CONFIG (config));
923 
924 	g_settings_set_int (G_SETTINGS (config), "initial-sleep", value);
925 	g_object_notify (G_OBJECT (config), "initial-sleep");
926 }
927 
928 static void
rebuild_filtered_lists(TrackerConfig * config)929 rebuild_filtered_lists (TrackerConfig *config)
930 {
931 	TrackerConfigPrivate *priv;
932 	GSList *old_list;
933 
934 	/* This function does 3 things:
935 	 * 1. Convert aliases like &DESKTOP to real paths
936 	 * 2. Filter and remove duplicates
937 	 * 3. Save the new list to the lists we return with public API
938 	 *
939 	 * Importantly, we:
940 	 * 1. Only notify on changes.
941 	 * 2. Don't update the unfiltered lists (since they have aliases)
942 	 */
943 	priv = tracker_config_get_instance_private (config);
944 
945 	/* Filter single directories first, checking duplicates */
946 	old_list = priv->index_single_directories;
947 	priv->index_single_directories = NULL;
948 
949 	if (priv->index_single_directories_unfiltered) {
950 		GSList *mapped_dirs = dir_mapping_get (priv->index_single_directories_unfiltered, FALSE);
951 
952 		priv->index_single_directories =
953 			tracker_path_list_filter_duplicates (mapped_dirs, ".", FALSE);
954 
955 		if (mapped_dirs) {
956 			g_slist_foreach (mapped_dirs, (GFunc) g_free, NULL);
957 			g_slist_free (mapped_dirs);
958 		}
959 	}
960 
961 	if (!tracker_gslist_with_string_data_equal (old_list, priv->index_single_directories)) {
962 		g_object_notify (G_OBJECT (config), "index-single-directories");
963 	}
964 
965 	if (old_list) {
966 		g_slist_foreach (old_list, (GFunc) g_free, NULL);
967 		g_slist_free (old_list);
968 	}
969 
970 	/* Filter recursive directories */
971 	old_list = priv->index_recursive_directories;
972 	priv->index_recursive_directories = NULL;
973 
974 	if (priv->index_recursive_directories_unfiltered) {
975 		GSList *l, *checked_dirs = NULL;
976 		GSList *mapped_dirs;
977 
978 		/* First, translate aliases */
979 		mapped_dirs = dir_mapping_get (priv->index_recursive_directories_unfiltered, TRUE);
980 
981 		/* Second, remove elements already in single directories */
982 		for (l = mapped_dirs; l; l = l->next) {
983 			if (g_slist_find_custom (priv->index_single_directories,
984 			                         l->data,
985 			                         (GCompareFunc) g_strcmp0) != NULL) {
986 				g_message ("Path '%s' being removed from recursive directories "
987 				           "list, as it also exists in single directories list",
988 				           (gchar *) l->data);
989 			} else {
990 				checked_dirs = g_slist_prepend (checked_dirs, l->data);
991 			}
992 		}
993 
994 		g_slist_free (mapped_dirs);
995 		checked_dirs = g_slist_reverse (checked_dirs);
996 
997 		/* Third, clean up any duplicates */
998 		priv->index_recursive_directories =
999 			tracker_path_list_filter_duplicates (checked_dirs, ".", TRUE);
1000 
1001 		g_slist_foreach (checked_dirs, (GFunc) g_free, NULL);
1002 		g_slist_free (checked_dirs);
1003 	}
1004 
1005 	if (!tracker_gslist_with_string_data_equal (old_list, priv->index_recursive_directories)) {
1006 		g_object_notify (G_OBJECT (config), "index-recursive-directories");
1007 	}
1008 
1009 	if (old_list) {
1010 		g_slist_foreach (old_list, (GFunc) g_free, NULL);
1011 		g_slist_free (old_list);
1012 	}
1013 }
1014 
1015 static void
config_set_index_recursive_directories(TrackerConfig * config,GSList * roots)1016 config_set_index_recursive_directories (TrackerConfig *config,
1017                                         GSList        *roots)
1018 {
1019 	TrackerConfigPrivate *priv;
1020 	GSList *l;
1021 	gboolean equal;
1022 
1023 	g_return_if_fail (TRACKER_IS_CONFIG (config));
1024 
1025 	priv = tracker_config_get_instance_private (config);
1026 
1027 	l = priv->index_recursive_directories_unfiltered;
1028 
1029 	equal = tracker_gslist_with_string_data_equal (roots, l);
1030 
1031 	if (!roots) {
1032 		priv->index_recursive_directories_unfiltered = NULL;
1033 	} else {
1034 		priv->index_recursive_directories_unfiltered =
1035 			tracker_gslist_copy_with_string_data (roots);
1036 	}
1037 
1038 	g_slist_foreach (l, (GFunc) g_free, NULL);
1039 	g_slist_free (l);
1040 
1041 	if (equal) {
1042 		return;
1043 	}
1044 
1045 	rebuild_filtered_lists (config);
1046 }
1047 
1048 static void
config_set_index_single_directories(TrackerConfig * config,GSList * roots)1049 config_set_index_single_directories (TrackerConfig *config,
1050                                      GSList        *roots)
1051 {
1052 	TrackerConfigPrivate *priv;
1053 	GSList *l;
1054 	gboolean equal;
1055 
1056 	g_return_if_fail (TRACKER_IS_CONFIG (config));
1057 
1058 	priv = tracker_config_get_instance_private (config);
1059 
1060 	l = priv->index_single_directories_unfiltered;
1061 
1062 	equal = tracker_gslist_with_string_data_equal (roots, l);
1063 
1064 	if (!roots) {
1065 		priv->index_single_directories_unfiltered = NULL;
1066 	} else {
1067 		priv->index_single_directories_unfiltered =
1068 			tracker_gslist_copy_with_string_data (roots);
1069 	}
1070 
1071 	g_slist_foreach (l, (GFunc) g_free, NULL);
1072 	g_slist_free (l);
1073 
1074 	if (equal) {
1075 		return;
1076 	}
1077 
1078 	rebuild_filtered_lists (config);
1079 }
1080 
1081 static void
config_set_ignored_directories(TrackerConfig * config,GSList * roots)1082 config_set_ignored_directories (TrackerConfig *config,
1083                                 GSList        *roots)
1084 {
1085 	TrackerConfigPrivate *priv;
1086 	GSList *l;
1087 	gboolean equal;
1088 
1089 	g_return_if_fail (TRACKER_IS_CONFIG (config));
1090 
1091 	priv = tracker_config_get_instance_private (config);
1092 
1093 	l = priv->ignored_directories;
1094 
1095 	equal = tracker_gslist_with_string_data_equal (roots, l);
1096 
1097 	if (!roots) {
1098 		priv->ignored_directories = NULL;
1099 	} else {
1100 		priv->ignored_directories =
1101 			tracker_gslist_copy_with_string_data (roots);
1102 	}
1103 
1104 	g_slist_foreach (l, (GFunc) g_free, NULL);
1105 	g_slist_free (l);
1106 
1107 	if (equal) {
1108 		return;
1109 	}
1110 
1111 	/* Re-set up the GPatternSpec list */
1112 	config_set_ignored_directory_conveniences (config);
1113 
1114 	g_object_notify (G_OBJECT (config), "ignored-directories");
1115 }
1116 
1117 static void
config_set_ignored_directories_with_content(TrackerConfig * config,GSList * roots)1118 config_set_ignored_directories_with_content (TrackerConfig *config,
1119                                              GSList        *roots)
1120 {
1121 	TrackerConfigPrivate *priv;
1122 	GSList *l;
1123 	gboolean equal;
1124 
1125 	g_return_if_fail (TRACKER_IS_CONFIG (config));
1126 
1127 	priv = tracker_config_get_instance_private (config);
1128 
1129 	l = priv->ignored_directories_with_content;
1130 
1131 	equal = tracker_gslist_with_string_data_equal (roots, l);
1132 
1133 	if (!roots) {
1134 		priv->ignored_directories_with_content = NULL;
1135 	} else {
1136 		priv->ignored_directories_with_content =
1137 			tracker_gslist_copy_with_string_data (roots);
1138 	}
1139 
1140 	g_slist_foreach (l, (GFunc) g_free, NULL);
1141 	g_slist_free (l);
1142 
1143 	if (equal) {
1144 		return;
1145 	}
1146 
1147 	g_object_notify (G_OBJECT (config), "ignored-directories-with-content");
1148 }
1149 
1150 static void
config_set_ignored_files(TrackerConfig * config,GSList * files)1151 config_set_ignored_files (TrackerConfig *config,
1152                           GSList        *files)
1153 {
1154 	TrackerConfigPrivate *priv;
1155 	GSList *l;
1156 	gboolean equal;
1157 
1158 	g_return_if_fail (TRACKER_IS_CONFIG (config));
1159 
1160 	priv = tracker_config_get_instance_private (config);
1161 
1162 	l = priv->ignored_files;
1163 
1164 	equal = tracker_gslist_with_string_data_equal (files, l);
1165 
1166 	if (!files) {
1167 		priv->ignored_files = NULL;
1168 	} else {
1169 		priv->ignored_files =
1170 			tracker_gslist_copy_with_string_data (files);
1171 	}
1172 
1173 	g_slist_foreach (l, (GFunc) g_free, NULL);
1174 	g_slist_free (l);
1175 
1176 	if (equal) {
1177 		return;
1178 	}
1179 
1180 	/* Re-set up the GPatternSpec list */
1181 	config_set_ignored_file_conveniences (config);
1182 
1183 	g_object_notify (G_OBJECT (config), "ignored-files");
1184 }
1185 
1186 /*
1187  * Convenience functions
1188  */
1189 
1190 GSList *
tracker_config_get_ignored_directory_patterns(TrackerConfig * config)1191 tracker_config_get_ignored_directory_patterns (TrackerConfig *config)
1192 {
1193 	TrackerConfigPrivate *priv;
1194 
1195 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
1196 
1197 	priv = tracker_config_get_instance_private (config);
1198 
1199 	return priv->ignored_directory_patterns;
1200 }
1201 
1202 GSList *
tracker_config_get_ignored_file_patterns(TrackerConfig * config)1203 tracker_config_get_ignored_file_patterns (TrackerConfig *config)
1204 {
1205 	TrackerConfigPrivate *priv;
1206 
1207 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
1208 
1209 	priv = tracker_config_get_instance_private (config);
1210 
1211 	return priv->ignored_file_patterns;
1212 }
1213 
1214 GSList *
tracker_config_get_ignored_directory_paths(TrackerConfig * config)1215 tracker_config_get_ignored_directory_paths (TrackerConfig *config)
1216 {
1217 	TrackerConfigPrivate *priv;
1218 
1219 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
1220 
1221 	priv = tracker_config_get_instance_private (config);
1222 
1223 	return priv->ignored_directory_paths;
1224 }
1225 
1226 GSList *
tracker_config_get_ignored_file_paths(TrackerConfig * config)1227 tracker_config_get_ignored_file_paths (TrackerConfig *config)
1228 {
1229 	TrackerConfigPrivate *priv;
1230 
1231 	g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL);
1232 
1233 	priv = tracker_config_get_instance_private (config);
1234 
1235 	return priv->ignored_file_paths;
1236 }
1237