blob: 50ed6b199b14abd64c2417b3c845ec2e503ab361 [file] [log] [blame]
Richard Hughes02c90d82018-08-09 12:13:03 +01001/*
Richard Hughes980ef142017-06-16 12:45:27 +01002 * Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
3 *
Mario Limonciello51308e62018-05-28 20:05:46 -05004 * SPDX-License-Identifier: LGPL-2.1+
Richard Hughes980ef142017-06-16 12:45:27 +01005 */
6
Richard Hughesb08e7bc2018-09-11 10:51:13 +01007#define G_LOG_DOMAIN "FuConfig"
8
Richard Hughes980ef142017-06-16 12:45:27 +01009#include "config.h"
10
11#include <glib-object.h>
12#include <gio/gio.h>
13
Richard Hughes4be17d12018-05-30 20:36:29 +010014#include "fu-common.h"
Richard Hughes980ef142017-06-16 12:45:27 +010015#include "fu-config.h"
16
Mario Limonciello263cab92019-08-20 17:16:00 -050017enum {
18 SIGNAL_CHANGED,
19 SIGNAL_LAST
20};
21
22static guint signals[SIGNAL_LAST] = { 0 };
23
Richard Hughes980ef142017-06-16 12:45:27 +010024static void fu_config_finalize (GObject *obj);
25
26struct _FuConfig
27{
28 GObject parent_instance;
Richard Hughesd1808aa2019-12-10 15:20:30 +000029 GFileMonitor *monitor;
30 GPtrArray *blacklist_devices; /* (element-type utf-8) */
31 GPtrArray *blacklist_plugins; /* (element-type utf-8) */
32 GPtrArray *approved_firmware; /* (element-type utf-8) */
Richard Hughesc7bbbc22018-01-02 22:22:25 +000033 guint64 archive_size_max;
Richard Hughes75b965d2018-11-15 13:51:21 +000034 guint idle_timeout;
Mario Limonciellobfcf75b2019-04-17 15:05:39 +010035 gchar *config_file;
Mario Limonciellod81ea2e2020-01-13 14:11:43 -060036 gboolean update_motd;
Richard Hughes980ef142017-06-16 12:45:27 +010037};
38
39G_DEFINE_TYPE (FuConfig, fu_config, G_TYPE_OBJECT)
40
Mario Limonciello263cab92019-08-20 17:16:00 -050041static void
42fu_config_emit_changed (FuConfig *self)
43{
44 g_debug ("::configuration changed");
45 g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
46}
47
Richard Hughes4c369702017-06-16 15:31:38 +010048static gboolean
Richard Hughesd1808aa2019-12-10 15:20:30 +000049fu_config_reload (FuConfig *self, GError **error)
Richard Hughescda1cdf2017-06-16 21:49:35 +010050{
Richard Hughes321f77a2018-02-14 10:25:53 +000051 guint64 archive_size_max;
Richard Hughes75b965d2018-11-15 13:51:21 +000052 guint idle_timeout;
Richard Hughes8dd4c1c2019-03-03 18:27:57 +000053 g_auto(GStrv) approved_firmware = NULL;
Richard Hughes980ef142017-06-16 12:45:27 +010054 g_auto(GStrv) devices = NULL;
55 g_auto(GStrv) plugins = NULL;
Mario Limonciello38027e62019-04-17 15:16:07 +010056 g_autofree gchar *domains = NULL;
Richard Hughesd1808aa2019-12-10 15:20:30 +000057 g_autoptr(GKeyFile) keyfile = g_key_file_new ();
Richard Hughes980ef142017-06-16 12:45:27 +010058
Richard Hughesd1808aa2019-12-10 15:20:30 +000059 g_debug ("loading config values from %s", self->config_file);
60 if (!g_key_file_load_from_file (keyfile, self->config_file,
61 G_KEY_FILE_NONE, error))
Richard Hughes980ef142017-06-16 12:45:27 +010062 return FALSE;
63
Richard Hughes980ef142017-06-16 12:45:27 +010064 /* get blacklisted devices */
Richard Hughesd1808aa2019-12-10 15:20:30 +000065 g_ptr_array_set_size (self->blacklist_devices, 0);
66 devices = g_key_file_get_string_list (keyfile,
Richard Hughes980ef142017-06-16 12:45:27 +010067 "fwupd",
68 "BlacklistDevices",
69 NULL, /* length */
70 NULL);
71 if (devices != NULL) {
72 for (guint i = 0; devices[i] != NULL; i++) {
73 g_ptr_array_add (self->blacklist_devices,
74 g_strdup (devices[i]));
75 }
76 }
77
78 /* get blacklisted plugins */
Richard Hughesd1808aa2019-12-10 15:20:30 +000079 g_ptr_array_set_size (self->blacklist_plugins, 0);
80 plugins = g_key_file_get_string_list (keyfile,
Richard Hughes980ef142017-06-16 12:45:27 +010081 "fwupd",
82 "BlacklistPlugins",
83 NULL, /* length */
84 NULL);
85 if (plugins != NULL) {
86 for (guint i = 0; plugins[i] != NULL; i++) {
87 g_ptr_array_add (self->blacklist_plugins,
88 g_strdup (plugins[i]));
89 }
90 }
91
Richard Hughes8dd4c1c2019-03-03 18:27:57 +000092 /* get approved firmware */
Richard Hughesd1808aa2019-12-10 15:20:30 +000093 g_ptr_array_set_size (self->approved_firmware, 0);
94 approved_firmware = g_key_file_get_string_list (keyfile,
Richard Hughes8dd4c1c2019-03-03 18:27:57 +000095 "fwupd",
96 "ApprovedFirmware",
97 NULL, /* length */
98 NULL);
99 if (approved_firmware != NULL) {
100 for (guint i = 0; approved_firmware[i] != NULL; i++) {
101 g_ptr_array_add (self->approved_firmware,
102 g_strdup (approved_firmware[i]));
103 }
104 }
105
Richard Hughesc7bbbc22018-01-02 22:22:25 +0000106 /* get maximum archive size, defaulting to something sane */
Richard Hughesd1808aa2019-12-10 15:20:30 +0000107 archive_size_max = g_key_file_get_uint64 (keyfile,
Richard Hughes321f77a2018-02-14 10:25:53 +0000108 "fwupd",
109 "ArchiveSizeMax",
110 NULL);
111 if (archive_size_max > 0)
112 self->archive_size_max = archive_size_max *= 0x100000;
Richard Hughes75b965d2018-11-15 13:51:21 +0000113
114 /* get idle timeout */
Richard Hughesd1808aa2019-12-10 15:20:30 +0000115 idle_timeout = g_key_file_get_uint64 (keyfile,
Richard Hughes75b965d2018-11-15 13:51:21 +0000116 "fwupd",
117 "IdleTimeout",
118 NULL);
119 if (idle_timeout > 0)
120 self->idle_timeout = idle_timeout;
Mario Limonciello38027e62019-04-17 15:16:07 +0100121
122 /* get the domains to run in verbose */
Richard Hughesd1808aa2019-12-10 15:20:30 +0000123 domains = g_key_file_get_string (keyfile,
Mario Limonciello38027e62019-04-17 15:16:07 +0100124 "fwupd",
125 "VerboseDomains",
126 NULL);
127 if (domains != NULL && domains[0] != '\0')
128 g_setenv ("FWUPD_VERBOSE", domains, TRUE);
129
Mario Limonciellod81ea2e2020-01-13 14:11:43 -0600130 /* whether to update the motd on changes */
131 self->update_motd = g_key_file_get_boolean (keyfile,
132 "fwupd",
133 "UpdateMotd",
134 NULL);
135
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500136 return TRUE;
137}
138
Richard Hughesd1808aa2019-12-10 15:20:30 +0000139static void
140fu_config_monitor_changed_cb (GFileMonitor *monitor,
141 GFile *file,
142 GFile *other_file,
143 GFileMonitorEvent event_type,
144 gpointer user_data)
Richard Hughes481aa2a2018-09-18 20:51:46 +0100145{
Richard Hughesd1808aa2019-12-10 15:20:30 +0000146 FuConfig *self = FU_CONFIG (user_data);
147 g_autoptr(GError) error = NULL;
148 g_debug ("%s changed, reloading all configs", self->config_file);
149 if (!fu_config_reload (self, &error))
150 g_warning ("failed to rescan daemon config: %s", error->message);
151 fu_config_emit_changed (self);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100152}
153
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500154gboolean
Richard Hughesd1808aa2019-12-10 15:20:30 +0000155fu_config_set_key_value (FuConfig *self, const gchar *key, const gchar *value, GError **error)
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500156{
Richard Hughesd1808aa2019-12-10 15:20:30 +0000157 g_autoptr(GKeyFile) keyfile = g_key_file_new ();
158 if (!g_key_file_load_from_file (keyfile, self->config_file,
159 G_KEY_FILE_KEEP_COMMENTS, error))
160 return FALSE;
161 g_key_file_set_string (keyfile, "fwupd", key, value);
162 if (!g_key_file_save_to_file (keyfile, self->config_file, error))
163 return FALSE;
164 return fu_config_reload (self, error);
165}
166
167gboolean
168fu_config_load (FuConfig *self, GError **error)
169{
Richard Hughes4be17d12018-05-30 20:36:29 +0100170 g_autofree gchar *configdir = NULL;
Richard Hughesd1808aa2019-12-10 15:20:30 +0000171 g_autoptr(GFile) file = NULL;
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500172
173 g_return_val_if_fail (FU_IS_CONFIG (self), FALSE);
Richard Hughesd1808aa2019-12-10 15:20:30 +0000174 g_return_val_if_fail (self->config_file == NULL, FALSE);
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500175
176 /* load the main daemon config file */
Richard Hughes4be17d12018-05-30 20:36:29 +0100177 configdir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR_PKG);
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100178 self->config_file = g_build_filename (configdir, "daemon.conf", NULL);
179 if (g_file_test (self->config_file, G_FILE_TEST_EXISTS)) {
Richard Hughesd1808aa2019-12-10 15:20:30 +0000180 if (!fu_config_reload (self, error))
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500181 return FALSE;
182 } else {
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100183 g_warning ("Daemon configuration %s not found", self->config_file);
Mario Limonciellod82e3b52018-05-22 10:18:27 -0500184 }
Richard Hughesc7bbbc22018-01-02 22:22:25 +0000185
Richard Hughesd1808aa2019-12-10 15:20:30 +0000186 /* set up a notify watch */
187 file = g_file_new_for_path (self->config_file);
188 self->monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, error);
189 if (self->monitor == NULL)
Richard Hughes1fd3ecf2018-04-16 10:53:46 +0100190 return FALSE;
Richard Hughesd1808aa2019-12-10 15:20:30 +0000191 g_signal_connect (self->monitor, "changed",
192 G_CALLBACK (fu_config_monitor_changed_cb), self);
Richard Hughes4c369702017-06-16 15:31:38 +0100193
194 /* success */
Richard Hughes980ef142017-06-16 12:45:27 +0100195 return TRUE;
196}
197
Richard Hughes75b965d2018-11-15 13:51:21 +0000198guint
199fu_config_get_idle_timeout (FuConfig *self)
200{
201 g_return_val_if_fail (FU_IS_CONFIG (self), 0);
202 return self->idle_timeout;
203}
204
Richard Hughes4c369702017-06-16 15:31:38 +0100205GPtrArray *
Richard Hughes980ef142017-06-16 12:45:27 +0100206fu_config_get_blacklist_devices (FuConfig *self)
207{
208 g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
209 return self->blacklist_devices;
210}
211
Richard Hughesc7bbbc22018-01-02 22:22:25 +0000212guint64
213fu_config_get_archive_size_max (FuConfig *self)
214{
215 g_return_val_if_fail (FU_IS_CONFIG (self), 0);
216 return self->archive_size_max;
217}
218
Richard Hughes980ef142017-06-16 12:45:27 +0100219GPtrArray *
220fu_config_get_blacklist_plugins (FuConfig *self)
221{
222 g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
223 return self->blacklist_plugins;
224}
225
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000226GPtrArray *
227fu_config_get_approved_firmware (FuConfig *self)
228{
229 g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
230 return self->approved_firmware;
231}
232
Mario Limonciellod81ea2e2020-01-13 14:11:43 -0600233gboolean
234fu_config_get_update_motd (FuConfig *self)
235{
236 g_return_val_if_fail (FU_IS_CONFIG (self), FALSE);
237 return self->update_motd;
238}
239
Richard Hughes980ef142017-06-16 12:45:27 +0100240static void
241fu_config_class_init (FuConfigClass *klass)
242{
243 GObjectClass *object_class = G_OBJECT_CLASS (klass);
244 object_class->finalize = fu_config_finalize;
Mario Limonciello263cab92019-08-20 17:16:00 -0500245
246 signals[SIGNAL_CHANGED] =
247 g_signal_new ("changed",
248 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
249 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
250 G_TYPE_NONE, 0);
Richard Hughes980ef142017-06-16 12:45:27 +0100251}
252
253static void
254fu_config_init (FuConfig *self)
255{
Richard Hughesc7bbbc22018-01-02 22:22:25 +0000256 self->archive_size_max = 512 * 0x100000;
Richard Hughes980ef142017-06-16 12:45:27 +0100257 self->blacklist_devices = g_ptr_array_new_with_free_func (g_free);
258 self->blacklist_plugins = g_ptr_array_new_with_free_func (g_free);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000259 self->approved_firmware = g_ptr_array_new_with_free_func (g_free);
Richard Hughes980ef142017-06-16 12:45:27 +0100260}
261
262static void
263fu_config_finalize (GObject *obj)
264{
265 FuConfig *self = FU_CONFIG (obj);
266
Richard Hughesd1808aa2019-12-10 15:20:30 +0000267 if (self->monitor != NULL)
268 g_object_unref (self->monitor);
Richard Hughes980ef142017-06-16 12:45:27 +0100269 g_ptr_array_unref (self->blacklist_devices);
270 g_ptr_array_unref (self->blacklist_plugins);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000271 g_ptr_array_unref (self->approved_firmware);
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100272 g_free (self->config_file);
Richard Hughes980ef142017-06-16 12:45:27 +0100273
274 G_OBJECT_CLASS (fu_config_parent_class)->finalize (obj);
275}
276
277FuConfig *
278fu_config_new (void)
279{
280 FuConfig *self;
281 self = g_object_new (FU_TYPE_CONFIG, NULL);
282 return FU_CONFIG (self);
283}