2 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
14 #include "configuration.h"
16 struct ConfigurationPrivate
21 GHashTable *key_sources;
24 G_DEFINE_TYPE (Configuration, config, G_TYPE_OBJECT);
26 static Configuration *configuration_instance = NULL;
29 config_get_instance (void)
31 if (!configuration_instance)
32 configuration_instance = g_object_new (CONFIGURATION_TYPE, NULL);
33 return configuration_instance;
37 config_load_from_file (Configuration *config, const gchar *path, GList **messages, GError **error)
40 gchar *source_path, **groups;
43 key_file = g_key_file_new ();
44 if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, error))
46 g_key_file_free (key_file);
50 source_path = g_strdup (path);
51 config->priv->sources = g_list_append (config->priv->sources, source_path);
53 groups = g_key_file_get_groups (key_file, NULL);
54 for (i = 0; groups[i]; i++)
59 /* Move keys from deprecated [SeatDefaults] into [Seat:*] */
61 if (strcmp (group, "SeatDefaults") == 0)
64 *messages = g_list_append (*messages, g_strdup (" [SeatDefaults] is now called [Seat:*], please update this configuration"));
68 keys = g_key_file_get_keys (key_file, groups[i], NULL, error);
72 for (j = 0; keys[j]; j++)
76 if (messages && g_str_has_prefix (group, "Seat:") && strcmp (keys[j], "xdg-seat") == 0)
77 *messages = g_list_append (*messages, g_strdup_printf (" [%s] contains deprecated option xdg-seat, this can be safely removed", group));
78 if (messages && strcmp (group, "LightDM") == 0 && strcmp (keys[j], "logind-load-seats") == 0)
79 *messages = g_list_append (*messages, g_strdup (" [LightDM] contains deprecated option logind-load-seats, this can be safely removed"));
81 value = g_key_file_get_value (key_file, groups[i], keys[j], NULL);
82 g_key_file_set_value (config->priv->key_file, group, keys[j], value);
85 k = g_strdup_printf ("%s]%s", group, keys[j]);
86 g_hash_table_insert (config->priv->key_sources, k, source_path);
93 g_key_file_free (key_file);
99 path_make_absolute (gchar *path)
101 gchar *cwd, *abs_path;
106 if (g_path_is_absolute (path))
109 cwd = g_get_current_dir ();
110 abs_path = g_build_filename (cwd, path, NULL);
117 compare_strings (gconstpointer a, gconstpointer b)
119 return strcmp (a, b);
123 load_config_directory (const gchar *path, GList **messages)
126 GList *files = NULL, *link;
127 GError *error = NULL;
129 /* Find configuration files */
130 dir = g_dir_open (path, 0, &error);
131 if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
132 g_printerr ("Failed to open configuration directory %s: %s\n", path, error->message);
133 g_clear_error (&error);
137 while ((name = g_dir_read_name (dir)))
138 files = g_list_append (files, g_strdup (name));
142 /* Sort alphabetically and load onto existing configuration */
143 files = g_list_sort (files, compare_strings);
144 for (link = files; link; link = link->next)
146 gchar *filename = link->data;
149 conf_path = g_build_filename (path, filename, NULL);
150 if (g_str_has_suffix (filename, ".conf"))
153 *messages = g_list_append (*messages, g_strdup_printf ("Loading configuration from %s", conf_path));
154 config_load_from_file (config_get_instance (), conf_path, messages, &error);
155 if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
156 g_printerr ("Failed to load configuration from %s: %s\n", filename, error->message);
157 g_clear_error (&error);
160 g_debug ("Ignoring configuration file %s, it does not have .conf suffix", conf_path);
163 g_list_free_full (files, g_free);
167 load_config_directories (const gchar * const *dirs, GList **messages)
171 /* Load in reverse order, because XDG_* fields are preference-ordered and the directories in front should override directories in back. */
172 for (i = g_strv_length ((gchar **)dirs) - 1; i >= 0; i--)
174 gchar *full_dir = g_build_filename (dirs[i], "lightdm", "lightdm.conf.d", NULL);
176 *messages = g_list_append (*messages, g_strdup_printf ("Loading configuration dirs from %s", full_dir));
177 load_config_directory (full_dir, messages);
183 config_load_from_standard_locations (Configuration *config, const gchar *config_path, GList **messages)
185 gchar *config_d_dir = NULL, *path;
186 gboolean success = TRUE;
187 GError *error = NULL;
189 g_return_val_if_fail (config->priv->dir == NULL, FALSE);
191 load_config_directories (g_get_system_data_dirs (), messages);
192 load_config_directories (g_get_system_config_dirs (), messages);
196 path = g_strdup (config_path);
197 config->priv->dir = path_make_absolute (g_path_get_basename (config_path));
201 config->priv->dir = g_strdup (CONFIG_DIR);
202 config_d_dir = g_build_filename (config->priv->dir, "lightdm.conf.d", NULL);
203 path = g_build_filename (config->priv->dir, "lightdm.conf", NULL);
207 load_config_directory (config_d_dir, messages);
210 *messages = g_list_append (*messages, g_strdup_printf ("Loading configuration from %s", path));
211 if (!config_load_from_file (config, path, messages, &error))
215 is_empty = error && g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
217 if (config_path || !is_empty)
220 g_printerr ("Failed to load configuration from %s: %s\n", path, error->message);
224 g_clear_error (&error);
226 g_free (config_d_dir);
233 config_get_directory (Configuration *config)
235 return config->priv->dir;
239 config_get_groups (Configuration *config)
241 return g_key_file_get_groups (config->priv->key_file, NULL);
245 config_get_keys (Configuration *config, const gchar *group_name)
247 return g_key_file_get_keys (config->priv->key_file, group_name, NULL, NULL);
251 config_has_key (Configuration *config, const gchar *section, const gchar *key)
253 return g_key_file_has_key (config->priv->key_file, section, key, NULL);
257 config_get_sources (Configuration *config)
259 return config->priv->sources;
263 config_get_source (Configuration *config, const gchar *section, const gchar *key)
268 k = g_strdup_printf ("%s]%s", section, key);
269 source = g_hash_table_lookup (config->priv->key_sources, k);
276 config_set_string (Configuration *config, const gchar *section, const gchar *key, const gchar *value)
278 g_key_file_set_string (config->priv->key_file, section, key, value);
282 config_get_string (Configuration *config, const gchar *section, const gchar *key)
284 return g_key_file_get_string (config->priv->key_file, section, key, NULL);
288 config_set_string_list (Configuration *config, const gchar *section, const gchar *key, const gchar **value, gsize length)
290 g_key_file_set_string_list (config->priv->key_file, section, key, value, length);
294 config_get_string_list (Configuration *config, const gchar *section, const gchar *key)
296 return g_key_file_get_string_list (config->priv->key_file, section, key, NULL, NULL);
300 config_set_integer (Configuration *config, const gchar *section, const gchar *key, gint value)
302 g_key_file_set_integer (config->priv->key_file, section, key, value);
306 config_get_integer (Configuration *config, const gchar *section, const gchar *key)
308 return g_key_file_get_integer (config->priv->key_file, section, key, NULL);
312 config_set_boolean (Configuration *config, const gchar *section, const gchar *key, gboolean value)
314 g_key_file_set_boolean (config->priv->key_file, section, key, value);
318 config_get_boolean (Configuration *config, const gchar *section, const gchar *key)
320 /* We don't use the standard function because it doesn't work with trailing whitespace:
321 * https://bugzilla.gnome.org/show_bug.cgi?id=664740
323 /*return g_key_file_get_boolean (config->priv->key_file, section, key, NULL);*/
328 value = g_key_file_get_value (config->priv->key_file, section, key, NULL);
332 v = strcmp (value, "true") == 0;
339 config_init (Configuration *config)
341 config->priv = G_TYPE_INSTANCE_GET_PRIVATE (config, CONFIGURATION_TYPE, ConfigurationPrivate);
342 config->priv->key_file = g_key_file_new ();
343 config->priv->key_sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
347 config_finalize (GObject *object)
349 Configuration *self = CONFIGURATION (object);
351 g_free (self->priv->dir);
352 g_key_file_free (self->priv->key_file);
353 g_list_free_full (self->priv->sources, g_free);
354 g_hash_table_destroy (self->priv->key_sources);
356 G_OBJECT_CLASS (config_parent_class)->finalize (object);
360 config_class_init (ConfigurationClass *klass)
362 GObjectClass *object_class = G_OBJECT_CLASS (klass);
364 object_class->finalize = config_finalize;
366 g_type_class_add_private (klass, sizeof (ConfigurationPrivate));