]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - common/configuration.c
Move config loading into one function; move that function into libcommon; call it...
[sojka/lightdm.git] / common / configuration.c
1 /*
2  * Copyright (C) 2010-2011 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  * 
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
9  * license.
10  */
11
12 #include <string.h>
13
14 #include "configuration.h"
15
16 struct ConfigurationPrivate
17 {
18     GKeyFile *key_file;
19 };
20
21 G_DEFINE_TYPE (Configuration, config, G_TYPE_OBJECT);
22
23 static Configuration *configuration_instance = NULL;
24
25 Configuration *
26 config_get_instance (void)
27 {
28     if (!configuration_instance)
29         configuration_instance = g_object_new (CONFIGURATION_TYPE, NULL);
30     return configuration_instance;
31 }
32
33 gboolean
34 config_load_from_file (Configuration *config, const gchar *path, GError **error)
35 {
36     GKeyFile *key_file;
37     gchar **groups;
38     int i;
39
40     key_file = g_key_file_new ();
41     if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, error))
42     {
43         g_key_file_free (key_file);
44         return FALSE;
45     }
46
47     groups = g_key_file_get_groups (key_file, NULL);
48     for (i = 0; groups[i]; i++)
49     {
50         gchar **keys;
51         int j;
52
53         keys = g_key_file_get_keys (key_file, groups[i], NULL, error);
54         if (!keys)
55             break;
56       
57         for (j = 0; keys[j]; j++)
58         {
59             gchar *value;
60
61             value = g_key_file_get_value (key_file, groups[i], keys[j], NULL);
62             g_key_file_set_value (config->priv->key_file, groups[i], keys[j], value);
63             g_free (value);
64         }
65
66         g_strfreev (keys);
67     }
68     g_strfreev (groups);
69
70     g_key_file_free (key_file);
71
72     return TRUE;
73 }
74
75 static gchar *
76 path_make_absolute (gchar *path)
77 {
78     gchar *cwd, *abs_path;
79
80     if (!path)
81         return NULL;
82
83     if (g_path_is_absolute (path))
84         return path;
85
86     cwd = g_get_current_dir ();
87     abs_path = g_build_filename (cwd, path, NULL);
88     g_free (path);
89
90     return abs_path;
91 }
92
93 static int
94 compare_strings (gconstpointer a, gconstpointer b)
95 {
96     return strcmp (a, b);
97 }
98
99 static void
100 load_config_directory (const gchar *path, GList **messages)
101 {
102     GDir *dir;
103     GList *files = NULL, *link;
104     GError *error = NULL;
105
106     /* Find configuration files */
107     dir = g_dir_open (path, 0, &error);
108     if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
109         g_printerr ("Failed to open configuration directory %s: %s\n", path, error->message);
110     g_clear_error (&error);
111     if (dir)
112     {
113         const gchar *name;
114         while ((name = g_dir_read_name (dir)))
115             files = g_list_append (files, g_strdup (name));
116         g_dir_close (dir);
117     }
118
119     /* Sort alphabetically and load onto existing configuration */
120     files = g_list_sort (files, compare_strings);
121     for (link = files; link; link = link->next)
122     {
123         gchar *filename = link->data;
124         gchar *conf_path;
125
126         conf_path = g_build_filename (path, filename, NULL);
127         if (g_str_has_suffix (filename, ".conf"))
128         {
129             if (messages)
130                 *messages = g_list_append (*messages, g_strdup_printf ("Loading configuration from %s", conf_path));
131             config_load_from_file (config_get_instance (), conf_path, &error);
132             if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
133                 g_printerr ("Failed to load configuration from %s: %s\n", filename, error->message);
134             g_clear_error (&error);
135         }
136         else
137             g_debug ("Ignoring configuration file %s, it does not have .conf suffix", conf_path);
138         g_free (conf_path);
139     }
140     g_list_free_full (files, g_free);
141 }
142
143 gboolean
144 config_load_from_standard_locations (Configuration *config, const gchar *config_path, GList **messages)
145 {
146     gchar *config_dir, *config_d_dir = NULL;
147     gboolean explicit_config = FALSE;
148     gboolean success = TRUE;
149     GError *error = NULL;
150
151     if (config_path)
152     {
153         config_dir = g_path_get_basename (config_path);
154         config_dir = path_make_absolute (config_dir);
155         explicit_config = TRUE;
156     }
157     else
158     {
159         config_dir = g_strdup (CONFIG_DIR);
160         config_d_dir = g_build_filename (config_dir, "lightdm.conf.d", NULL);
161         config_path = g_build_filename (config_dir, "lightdm.conf", NULL);
162     }
163     config_set_string (config, "LightDM", "config-directory", config_dir);
164     g_free (config_dir);
165
166     load_config_directory (SYSTEM_CONFIG_DIR, messages);
167     if (config_d_dir)
168         load_config_directory (config_d_dir, messages);
169     g_free (config_d_dir);
170
171     if (messages)
172         *messages = g_list_append (*messages, g_strdup_printf ("Loading configuration from %s", config_path));
173     if (!config_load_from_file (config, config_path, &error))
174     {
175         gboolean is_empty;
176
177         is_empty = error && g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
178
179         if (explicit_config || !is_empty)
180         {
181             if (error)
182                 g_printerr ("Failed to load configuration from %s: %s\n", config_path, error->message);
183             success = FALSE;
184         }
185     }
186     g_clear_error (&error);
187
188     return success;
189 }
190
191 gchar **
192 config_get_groups (Configuration *config)
193 {
194     return g_key_file_get_groups (config->priv->key_file, NULL);
195 }
196
197 gchar **
198 config_get_keys (Configuration *config, const gchar *group_name)
199 {
200     return g_key_file_get_keys (config->priv->key_file, group_name, NULL, NULL);
201 }
202
203 gboolean
204 config_has_key (Configuration *config, const gchar *section, const gchar *key)
205 {
206     return g_key_file_has_key (config->priv->key_file, section, key, NULL);
207 }
208
209 void
210 config_set_string (Configuration *config, const gchar *section, const gchar *key, const gchar *value)
211 {
212     g_key_file_set_string (config->priv->key_file, section, key, value);
213 }
214
215 gchar *
216 config_get_string (Configuration *config, const gchar *section, const gchar *key)
217 {
218     return g_key_file_get_string (config->priv->key_file, section, key, NULL);
219 }
220
221 void
222 config_set_string_list (Configuration *config, const gchar *section, const gchar *key, const gchar **value, gsize length)
223 {
224     g_key_file_set_string_list (config->priv->key_file, section, key, value, length);
225 }
226
227 gchar **
228 config_get_string_list (Configuration *config, const gchar *section, const gchar *key)
229 {
230     return g_key_file_get_string_list (config->priv->key_file, section, key, NULL, NULL);
231 }
232
233 void
234 config_set_integer (Configuration *config, const gchar *section, const gchar *key, gint value)
235 {
236     g_key_file_set_integer (config->priv->key_file, section, key, value);
237 }
238
239 gint
240 config_get_integer (Configuration *config, const gchar *section, const gchar *key)
241 {
242     return g_key_file_get_integer (config->priv->key_file, section, key, NULL);
243 }
244
245 void
246 config_set_boolean (Configuration *config, const gchar *section, const gchar *key, gboolean value)
247 {
248     g_key_file_set_boolean (config->priv->key_file, section, key, value);
249 }
250
251 gboolean
252 config_get_boolean (Configuration *config, const gchar *section, const gchar *key)
253 {
254     return g_key_file_get_boolean (config->priv->key_file, section, key, NULL);
255 }
256
257 static void
258 config_init (Configuration *config)
259 {
260     config->priv = G_TYPE_INSTANCE_GET_PRIVATE (config, CONFIGURATION_TYPE, ConfigurationPrivate);
261     config->priv->key_file = g_key_file_new ();  
262 }
263
264 static void
265 config_finalize (GObject *object)
266 {
267     Configuration *self;
268
269     self = CONFIGURATION (object);
270
271     g_key_file_free (self->priv->key_file);
272
273     G_OBJECT_CLASS (config_parent_class)->finalize (object);  
274 }
275
276 static void
277 config_class_init (ConfigurationClass *klass)
278 {
279     GObjectClass *object_class = G_OBJECT_CLASS (klass);
280
281     object_class->finalize = config_finalize;  
282
283     g_type_class_add_private (klass, sizeof (ConfigurationPrivate));
284 }