mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-29 11:43:05 +00:00
336 lines
8.9 KiB
C
336 lines
8.9 KiB
C
/*
|
|
* Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#define G_LOG_DOMAIN "FuConfig"
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib-object.h>
|
|
#include <gio/gio.h>
|
|
|
|
#include "fu-common.h"
|
|
#include "fu-config.h"
|
|
|
|
enum {
|
|
SIGNAL_CHANGED,
|
|
SIGNAL_LAST
|
|
};
|
|
|
|
static guint signals[SIGNAL_LAST] = { 0 };
|
|
|
|
static void fu_config_finalize (GObject *obj);
|
|
|
|
struct _FuConfig
|
|
{
|
|
GObject parent_instance;
|
|
GFileMonitor *monitor;
|
|
GPtrArray *disabled_devices; /* (element-type utf-8) */
|
|
GPtrArray *disabled_plugins; /* (element-type utf-8) */
|
|
GPtrArray *approved_firmware; /* (element-type utf-8) */
|
|
GPtrArray *blocked_firmware; /* (element-type utf-8) */
|
|
guint64 archive_size_max;
|
|
guint idle_timeout;
|
|
gchar *config_file;
|
|
gboolean update_motd;
|
|
gboolean enumerate_all_devices;
|
|
};
|
|
|
|
G_DEFINE_TYPE (FuConfig, fu_config, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
fu_config_emit_changed (FuConfig *self)
|
|
{
|
|
g_debug ("::configuration changed");
|
|
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
|
}
|
|
|
|
static gboolean
|
|
fu_config_reload (FuConfig *self, GError **error)
|
|
{
|
|
guint64 archive_size_max;
|
|
guint idle_timeout;
|
|
g_auto(GStrv) approved_firmware = NULL;
|
|
g_auto(GStrv) blocked_firmware = NULL;
|
|
g_auto(GStrv) devices = NULL;
|
|
g_auto(GStrv) plugins = NULL;
|
|
g_autofree gchar *domains = NULL;
|
|
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
|
g_autoptr(GError) error_update_motd = NULL;
|
|
g_autoptr(GError) error_enumerate_all = NULL;
|
|
|
|
g_debug ("loading config values from %s", self->config_file);
|
|
if (!g_key_file_load_from_file (keyfile, self->config_file,
|
|
G_KEY_FILE_NONE, error))
|
|
return FALSE;
|
|
|
|
/* get disabled devices */
|
|
g_ptr_array_set_size (self->disabled_devices, 0);
|
|
devices = g_key_file_get_string_list (keyfile,
|
|
"fwupd",
|
|
"DisabledDevices",
|
|
NULL, /* length */
|
|
NULL);
|
|
if (devices != NULL) {
|
|
for (guint i = 0; devices[i] != NULL; i++) {
|
|
g_ptr_array_add (self->disabled_devices,
|
|
g_strdup (devices[i]));
|
|
}
|
|
}
|
|
|
|
/* get disabled plugins */
|
|
g_ptr_array_set_size (self->disabled_plugins, 0);
|
|
plugins = g_key_file_get_string_list (keyfile,
|
|
"fwupd",
|
|
"DisabledPlugins",
|
|
NULL, /* length */
|
|
NULL);
|
|
if (plugins != NULL) {
|
|
for (guint i = 0; plugins[i] != NULL; i++) {
|
|
g_ptr_array_add (self->disabled_plugins,
|
|
g_strdup (plugins[i]));
|
|
}
|
|
}
|
|
|
|
/* get approved firmware */
|
|
g_ptr_array_set_size (self->approved_firmware, 0);
|
|
approved_firmware = g_key_file_get_string_list (keyfile,
|
|
"fwupd",
|
|
"ApprovedFirmware",
|
|
NULL, /* length */
|
|
NULL);
|
|
if (approved_firmware != NULL) {
|
|
for (guint i = 0; approved_firmware[i] != NULL; i++) {
|
|
g_ptr_array_add (self->approved_firmware,
|
|
g_strdup (approved_firmware[i]));
|
|
}
|
|
}
|
|
|
|
/* get blocked firmware */
|
|
g_ptr_array_set_size (self->blocked_firmware, 0);
|
|
blocked_firmware = g_key_file_get_string_list (keyfile,
|
|
"fwupd",
|
|
"BlockedFirmware",
|
|
NULL, /* length */
|
|
NULL);
|
|
if (blocked_firmware != NULL) {
|
|
for (guint i = 0; blocked_firmware[i] != NULL; i++) {
|
|
g_ptr_array_add (self->blocked_firmware,
|
|
g_strdup (blocked_firmware[i]));
|
|
}
|
|
}
|
|
|
|
/* get maximum archive size, defaulting to something sane */
|
|
archive_size_max = g_key_file_get_uint64 (keyfile,
|
|
"fwupd",
|
|
"ArchiveSizeMax",
|
|
NULL);
|
|
if (archive_size_max > 0)
|
|
self->archive_size_max = archive_size_max * 0x100000;
|
|
|
|
/* get idle timeout */
|
|
idle_timeout = g_key_file_get_uint64 (keyfile,
|
|
"fwupd",
|
|
"IdleTimeout",
|
|
NULL);
|
|
if (idle_timeout > 0)
|
|
self->idle_timeout = idle_timeout;
|
|
|
|
/* get the domains to run in verbose */
|
|
domains = g_key_file_get_string (keyfile,
|
|
"fwupd",
|
|
"VerboseDomains",
|
|
NULL);
|
|
if (domains != NULL && domains[0] != '\0')
|
|
g_setenv ("FWUPD_VERBOSE", domains, TRUE);
|
|
|
|
/* whether to update the motd on changes */
|
|
self->update_motd = g_key_file_get_boolean (keyfile,
|
|
"fwupd",
|
|
"UpdateMotd",
|
|
&error_update_motd);
|
|
if (!self->update_motd && error_update_motd != NULL) {
|
|
g_debug ("failed to read UpdateMotd key: %s", error_update_motd->message);
|
|
self->update_motd = TRUE;
|
|
}
|
|
|
|
/* whether to only show supported devices for some plugins */
|
|
self->enumerate_all_devices = g_key_file_get_boolean (keyfile,
|
|
"fwupd",
|
|
"EnumerateAllDevices",
|
|
&error_enumerate_all);
|
|
/* if error parsing or missing, we want to default to true */
|
|
if (!self->enumerate_all_devices && error_enumerate_all != NULL) {
|
|
g_debug ("failed to read EnumerateAllDevices key: %s", error_enumerate_all->message);
|
|
self->enumerate_all_devices = TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
fu_config_monitor_changed_cb (GFileMonitor *monitor,
|
|
GFile *file,
|
|
GFile *other_file,
|
|
GFileMonitorEvent event_type,
|
|
gpointer user_data)
|
|
{
|
|
FuConfig *self = FU_CONFIG (user_data);
|
|
g_autoptr(GError) error = NULL;
|
|
g_debug ("%s changed, reloading all configs", self->config_file);
|
|
if (!fu_config_reload (self, &error))
|
|
g_warning ("failed to rescan daemon config: %s", error->message);
|
|
fu_config_emit_changed (self);
|
|
}
|
|
|
|
gboolean
|
|
fu_config_set_key_value (FuConfig *self, const gchar *key, const gchar *value, GError **error)
|
|
{
|
|
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
|
if (!g_key_file_load_from_file (keyfile, self->config_file,
|
|
G_KEY_FILE_KEEP_COMMENTS, error))
|
|
return FALSE;
|
|
g_key_file_set_string (keyfile, "fwupd", key, value);
|
|
if (!g_key_file_save_to_file (keyfile, self->config_file, error))
|
|
return FALSE;
|
|
return fu_config_reload (self, error);
|
|
}
|
|
|
|
gboolean
|
|
fu_config_load (FuConfig *self, GError **error)
|
|
{
|
|
g_autofree gchar *configdir = NULL;
|
|
g_autoptr(GFile) file = NULL;
|
|
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), FALSE);
|
|
g_return_val_if_fail (self->config_file == NULL, FALSE);
|
|
|
|
/* load the main daemon config file */
|
|
configdir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR_PKG);
|
|
self->config_file = g_build_filename (configdir, "daemon.conf", NULL);
|
|
if (g_file_test (self->config_file, G_FILE_TEST_EXISTS)) {
|
|
if (!fu_config_reload (self, error))
|
|
return FALSE;
|
|
} else {
|
|
g_warning ("Daemon configuration %s not found", self->config_file);
|
|
}
|
|
|
|
/* set up a notify watch */
|
|
file = g_file_new_for_path (self->config_file);
|
|
self->monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, error);
|
|
if (self->monitor == NULL)
|
|
return FALSE;
|
|
g_signal_connect (self->monitor, "changed",
|
|
G_CALLBACK (fu_config_monitor_changed_cb), self);
|
|
|
|
/* success */
|
|
return TRUE;
|
|
}
|
|
|
|
guint
|
|
fu_config_get_idle_timeout (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), 0);
|
|
return self->idle_timeout;
|
|
}
|
|
|
|
GPtrArray *
|
|
fu_config_get_disabled_devices (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
|
|
return self->disabled_devices;
|
|
}
|
|
|
|
GPtrArray *
|
|
fu_config_get_blocked_firmware (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
|
|
return self->blocked_firmware;
|
|
}
|
|
|
|
guint64
|
|
fu_config_get_archive_size_max (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), 0);
|
|
return self->archive_size_max;
|
|
}
|
|
|
|
GPtrArray *
|
|
fu_config_get_disabled_plugins (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
|
|
return self->disabled_plugins;
|
|
}
|
|
|
|
GPtrArray *
|
|
fu_config_get_approved_firmware (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
|
|
return self->approved_firmware;
|
|
}
|
|
|
|
gboolean
|
|
fu_config_get_update_motd (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), FALSE);
|
|
return self->update_motd;
|
|
}
|
|
|
|
gboolean
|
|
fu_config_get_enumerate_all_devices (FuConfig *self)
|
|
{
|
|
g_return_val_if_fail (FU_IS_CONFIG (self), FALSE);
|
|
return self->enumerate_all_devices;
|
|
}
|
|
|
|
static void
|
|
fu_config_class_init (FuConfigClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
object_class->finalize = fu_config_finalize;
|
|
|
|
signals[SIGNAL_CHANGED] =
|
|
g_signal_new ("changed",
|
|
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
|
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
}
|
|
|
|
static void
|
|
fu_config_init (FuConfig *self)
|
|
{
|
|
self->archive_size_max = 512 * 0x100000;
|
|
self->disabled_devices = g_ptr_array_new_with_free_func (g_free);
|
|
self->disabled_plugins = g_ptr_array_new_with_free_func (g_free);
|
|
self->approved_firmware = g_ptr_array_new_with_free_func (g_free);
|
|
self->blocked_firmware = g_ptr_array_new_with_free_func (g_free);
|
|
}
|
|
|
|
static void
|
|
fu_config_finalize (GObject *obj)
|
|
{
|
|
FuConfig *self = FU_CONFIG (obj);
|
|
|
|
if (self->monitor != NULL) {
|
|
g_file_monitor_cancel (self->monitor);
|
|
g_object_unref (self->monitor);
|
|
}
|
|
g_ptr_array_unref (self->disabled_devices);
|
|
g_ptr_array_unref (self->disabled_plugins);
|
|
g_ptr_array_unref (self->approved_firmware);
|
|
g_ptr_array_unref (self->blocked_firmware);
|
|
g_free (self->config_file);
|
|
|
|
G_OBJECT_CLASS (fu_config_parent_class)->finalize (obj);
|
|
}
|
|
|
|
FuConfig *
|
|
fu_config_new (void)
|
|
{
|
|
FuConfig *self;
|
|
self = g_object_new (FU_TYPE_CONFIG, NULL);
|
|
return FU_CONFIG (self);
|
|
}
|