tracker-0.16.2/src/miners/fs/tracker-config.c

No issues found

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