From 4c3697044537258843c2797fd5c024d39a49725c Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Fri, 16 Jun 2017 15:31:38 +0100 Subject: [PATCH] Move the remotes parsing from the client to the server This allows us to load the metadata stores in a more sensible way in the future. --- libfwupd/fwupd-client.c | 221 +++++++----------------------- libfwupd/fwupd-remote-private.h | 3 + libfwupd/fwupd-remote.c | 121 +++++++++++++++++ src/fu-config.c | 232 ++++++++++++++++++++++++++++++++ src/fu-config.h | 1 + src/fu-main.c | 39 ++++++ src/fu-util.c | 2 +- src/org.freedesktop.fwupd.xml | 18 +++ 8 files changed, 462 insertions(+), 175 deletions(-) diff --git a/libfwupd/fwupd-client.c b/libfwupd/fwupd-client.c index 0e64a33ba..0c28458b1 100644 --- a/libfwupd/fwupd-client.c +++ b/libfwupd/fwupd-client.c @@ -287,6 +287,26 @@ fwupd_client_parse_devices_from_variant (GVariant *val) return array; } +static GPtrArray * +fwupd_client_parse_remotes_from_data (GVariant *devices) +{ + GPtrArray *remotes = NULL; + gsize sz; + g_autoptr(GVariant) untuple = NULL; + + remotes = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + untuple = g_variant_get_child_value (devices, 0); + sz = g_variant_n_children (untuple); + for (guint i = 0; i < sz; i++) { + FwupdRemote *remote; + g_autoptr(GVariant) data = g_variant_get_child_value (untuple, i); + remote = fwupd_remote_new_from_data (data); + g_ptr_array_add (remotes, remote); + } + + return remotes; +} + static void fwupd_client_fixup_dbus_error (GError *error) { @@ -1251,131 +1271,6 @@ fwupd_client_update_metadata_with_id (FwupdClient *client, return TRUE; } -static GPtrArray * -fwupd_client_get_config_paths (void) -{ - GPtrArray *paths = g_ptr_array_new_with_free_func (g_free); - const gchar *remotes_dir; - const gchar *system_prefixlibdir = "/usr/lib/fwupd"; - const gchar *system_sysconfdir = "/etc/fwupd"; - g_autofree gchar *sysconfdir = NULL; - - /* only set by the self test program */ - remotes_dir = g_getenv ("FU_SELF_TEST_REMOTES_DIR"); - if (remotes_dir != NULL) { - g_ptr_array_add (paths, g_strdup (remotes_dir)); - return paths; - } - - /* use sysconfig, and then fall back to /etc */ - sysconfdir = g_build_filename (SYSCONFDIR, "fwupd", NULL); - if (g_file_test (sysconfdir, G_FILE_TEST_EXISTS)) { - g_ptr_array_add (paths, g_steal_pointer (&sysconfdir)); - } else { - g_debug ("falling back to system path"); - if (g_file_test (system_sysconfdir, G_FILE_TEST_EXISTS)) - g_ptr_array_add (paths, g_strdup (system_sysconfdir)); - } - - /* add in system-wide locations */ - if (g_file_test (system_prefixlibdir, G_FILE_TEST_EXISTS)) - g_ptr_array_add (paths, g_strdup (system_prefixlibdir)); - - return paths; -} - -static gboolean -fwupd_client_add_remotes_for_path (FwupdClient *client, - GPtrArray *remotes, - const gchar *path, - GCancellable *cancellable, - GError **error) -{ - const gchar *tmp; - g_autofree gchar *path_remotes = NULL; - g_autoptr(GDir) dir = NULL; - - path_remotes = g_build_filename (path, "remotes.d", NULL); - if (!g_file_test (path_remotes, G_FILE_TEST_EXISTS)) - return TRUE; - dir = g_dir_open (path_remotes, 0, error); - if (dir == NULL) - return FALSE; - while ((tmp = g_dir_read_name (dir)) != NULL) { - g_autofree gchar *filename = g_build_filename (path_remotes, tmp, NULL); - g_autoptr(FwupdRemote) remote = fwupd_remote_new (); - g_debug ("loading from %s", filename); - if (!fwupd_remote_load_from_filename (remote, filename, - cancellable, error)) - return FALSE; - g_ptr_array_add (remotes, g_steal_pointer (&remote)); - } - return TRUE; -} - -static gint -fwupd_client_remote_sort_cb (gconstpointer a, gconstpointer b) -{ - FwupdRemote *remote_a = *((FwupdRemote **) a); - FwupdRemote *remote_b = *((FwupdRemote **) b); - - /* use priority first */ - if (fwupd_remote_get_priority (remote_a) < fwupd_remote_get_priority (remote_b)) - return 1; - if (fwupd_remote_get_priority (remote_a) > fwupd_remote_get_priority (remote_b)) - return -1; - - /* fall back to name */ - return g_strcmp0 (fwupd_remote_get_id (remote_a), - fwupd_remote_get_id (remote_b)); -} - -static FwupdRemote * -fwupd_client_get_remote_by_id_noref (GPtrArray *remotes, const gchar *remote_id) -{ - for (guint i = 0; i < remotes->len; i++) { - FwupdRemote *remote = g_ptr_array_index (remotes, i); - if (g_strcmp0 (remote_id, fwupd_remote_get_id (remote)) == 0) - return remote; - } - return NULL; -} - -static guint -fwupd_client_remotes_depsolve_with_direction (GPtrArray *remotes, gint inc) -{ - guint cnt = 0; - for (guint i = 0; i < remotes->len; i++) { - FwupdRemote *remote = g_ptr_array_index (remotes, i); - gchar **order = inc < 0 ? fwupd_remote_get_order_after (remote) : - fwupd_remote_get_order_before (remote); - if (order == NULL) - continue; - for (guint j = 0; order[j] != NULL; j++) { - FwupdRemote *remote2; - if (g_strcmp0 (order[j], fwupd_remote_get_id (remote)) == 0) { - g_warning ("ignoring self-dep remote %s", order[j]); - continue; - } - remote2 = fwupd_client_get_remote_by_id_noref (remotes, order[j]); - if (remote2 == NULL) { - g_warning ("ignoring unfound remote %s", order[j]); - continue; - } - if (fwupd_remote_get_priority (remote) > fwupd_remote_get_priority (remote2)) - continue; - g_debug ("ordering %s=%s+%i", - fwupd_remote_get_id (remote), - fwupd_remote_get_id (remote2), - inc); - fwupd_remote_set_priority (remote, fwupd_remote_get_priority (remote2) + inc); - - /* increment changes counter */ - cnt++; - } - } - return cnt; -} /** * fwupd_client_get_remotes: * @client: A #FwupdClient @@ -1391,64 +1286,42 @@ fwupd_client_remotes_depsolve_with_direction (GPtrArray *remotes, gint inc) GPtrArray * fwupd_client_get_remotes (FwupdClient *client, GCancellable *cancellable, GError **error) { - guint depsolve_check; - g_autoptr(GPtrArray) paths = NULL; - g_autoptr(GPtrArray) remotes = NULL; + FwupdClientPrivate *priv = GET_PRIVATE (client); + g_autoptr(GVariant) val = NULL; g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - /* get a list of all config paths */ - paths = fwupd_client_get_config_paths (); - if (paths->len == 0) { - g_set_error_literal (error, - FWUPD_ERROR, - FWUPD_ERROR_NOT_FOUND, - "No search paths found"); + /* connect */ + if (!fwupd_client_connect (client, cancellable, error)) + return NULL; + + /* call into daemon */ + val = g_dbus_proxy_call_sync (priv->proxy, + "GetRemotes", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (val == NULL) { + if (error != NULL) + fwupd_client_fixup_dbus_error (*error); return NULL; } + return fwupd_client_parse_remotes_from_data (val); +} - /* look for all remotes */ - remotes = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); - for (guint i = 0; i < paths->len; i++) { - const gchar *path = g_ptr_array_index (paths, i); - g_debug ("using config path of %s", path); - if (!fwupd_client_add_remotes_for_path (client, remotes, path, - cancellable, error)) - return FALSE; +static FwupdRemote * +fwupd_client_get_remote_by_id_noref (GPtrArray *remotes, const gchar *remote_id) +{ + for (guint i = 0; i < remotes->len; i++) { + FwupdRemote *remote = g_ptr_array_index (remotes, i); + if (g_strcmp0 (remote_id, fwupd_remote_get_id (remote)) == 0) + return remote; } - - /* nothing found */ - if (remotes->len == 0) { - g_set_error_literal (error, - FWUPD_ERROR, - FWUPD_ERROR_NOT_FOUND, - "No remotes found in search paths"); - return NULL; - } - - /* depsolve */ - for (depsolve_check = 0; depsolve_check < 100; depsolve_check++) { - guint cnt = 0; - cnt += fwupd_client_remotes_depsolve_with_direction (remotes, 1); - cnt += fwupd_client_remotes_depsolve_with_direction (remotes, -1); - if (cnt == 0) - break; - } - if (depsolve_check == 100) { - g_set_error_literal (error, - FWUPD_ERROR, - FWUPD_ERROR_INTERNAL, - "Cannot depsolve remotes ordering"); - return NULL; - } - - /* order these by priority, then name */ - g_ptr_array_sort (remotes, fwupd_client_remote_sort_cb); - - /* success */ - return g_steal_pointer (&remotes); + return NULL; } /** diff --git a/libfwupd/fwupd-remote-private.h b/libfwupd/fwupd-remote-private.h index 734ea0125..349d3f268 100644 --- a/libfwupd/fwupd-remote-private.h +++ b/libfwupd/fwupd-remote-private.h @@ -26,6 +26,9 @@ G_BEGIN_DECLS +FwupdRemote *fwupd_remote_new_from_data (GVariant *data); +GVariant *fwupd_remote_to_data (FwupdRemote *self, + const gchar *type_string); gboolean fwupd_remote_load_from_filename (FwupdRemote *self, const gchar *filename, GCancellable *cancellable, diff --git a/libfwupd/fwupd-remote.c b/libfwupd/fwupd-remote.c index 434bc2e06..5597ecb80 100644 --- a/libfwupd/fwupd-remote.c +++ b/libfwupd/fwupd-remote.c @@ -368,6 +368,94 @@ fwupd_remote_get_id (FwupdRemote *self) return self->id; } +static void +fwupd_remote_to_variant_builder (FwupdRemote *self, GVariantBuilder *builder) +{ + if (self->id != NULL) { + g_variant_builder_add (builder, "{sv}", "Id", + g_variant_new_string (self->id)); + } + if (self->username != NULL) { + g_variant_builder_add (builder, "{sv}", "Username", + g_variant_new_string (self->username)); + } + if (self->password != NULL) { + g_variant_builder_add (builder, "{sv}", "Password", + g_variant_new_string (self->password)); + } + if (self->url != NULL) { + g_variant_builder_add (builder, "{sv}", "Url", + g_variant_new_string (self->url)); + } + if (self->priority != 0) { + g_variant_builder_add (builder, "{sv}", "Priority", + g_variant_new_int32 (self->priority)); + } + g_variant_builder_add (builder, "{sv}", "Enabled", + g_variant_new_boolean (self->enabled)); +} + +static void +fwupd_remote_set_from_variant_iter (FwupdRemote *self, GVariantIter *iter) +{ + GVariant *value; + const gchar *key; + g_autoptr(GVariantIter) iter2 = g_variant_iter_copy (iter); + g_autoptr(GVariantIter) iter3 = g_variant_iter_copy (iter); + + /* three passes, as we have to construct Id -> Url -> * */ + while (g_variant_iter_loop (iter, "{sv}", &key, &value)) { + if (g_strcmp0 (key, "Id") == 0) + fwupd_remote_set_id (self, g_variant_get_string (value, NULL)); + } + while (g_variant_iter_loop (iter2, "{sv}", &key, &value)) { + if (g_strcmp0 (key, "Url") == 0) + fwupd_remote_set_url (self, g_variant_get_string (value, NULL)); + } + while (g_variant_iter_loop (iter3, "{sv}", &key, &value)) { + if (g_strcmp0 (key, "Username") == 0) { + fwupd_remote_set_username (self, g_variant_get_string (value, NULL)); + } else if (g_strcmp0 (key, "Password") == 0) { + fwupd_remote_set_password (self, g_variant_get_string (value, NULL)); + } else if (g_strcmp0 (key, "Enabled") == 0) { + self->enabled = g_variant_get_boolean (value); + } else if (g_strcmp0 (key, "Priority") == 0) { + self->priority = g_variant_get_int32 (value); + } + } +} + +/** + * fwupd_remote_to_data: + * @remote: A #FwupdRemote + * @type_string: The Gvariant type string, e.g. "a{sv}" or "(a{sv})" + * + * Creates a GVariant from the remote data. + * + * Returns: the GVariant, or %NULL for error + * + * Since: 0.9.5 + **/ +GVariant * +fwupd_remote_to_data (FwupdRemote *self, const gchar *type_string) +{ + GVariantBuilder builder; + + g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL); + g_return_val_if_fail (type_string != NULL, NULL); + + /* create an array with all the metadata in */ + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + fwupd_remote_to_variant_builder (self, &builder); + + /* supported types */ + if (g_strcmp0 (type_string, "a{sv}") == 0) + return g_variant_new ("a{sv}", &builder); + if (g_strcmp0 (type_string, "(a{sv})") == 0) + return g_variant_new ("(a{sv})", &builder); + return NULL; +} + static void fwupd_remote_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec) @@ -464,6 +552,39 @@ fwupd_remote_finalize (GObject *obj) G_OBJECT_CLASS (fwupd_remote_parent_class)->finalize (obj); } +/** + * fwupd_remote_new_from_data: + * @data: a #GVariant + * + * Creates a new remote using packed data. + * + * Returns: a new #FwupdRemote, or %NULL if @data was invalid + * + * Since: 0.9.5 + **/ +FwupdRemote * +fwupd_remote_new_from_data (GVariant *data) +{ + FwupdRemote *rel = NULL; + const gchar *type_string; + g_autoptr(GVariantIter) iter = NULL; + + type_string = g_variant_get_type_string (data); + if (g_strcmp0 (type_string, "(a{sv})") == 0) { + rel = fwupd_remote_new (); + g_variant_get (data, "(a{sv})", &iter); + fwupd_remote_set_from_variant_iter (rel, iter); + fwupd_remote_set_from_variant_iter (rel, iter); + } else if (g_strcmp0 (type_string, "a{sv}") == 0) { + rel = fwupd_remote_new (); + g_variant_get (data, "a{sv}", &iter); + fwupd_remote_set_from_variant_iter (rel, iter); + } else { + g_warning ("type %s not known", type_string); + } + return rel; +} + /** * fwupd_remote_new: * diff --git a/src/fu-config.c b/src/fu-config.c index 7eed66c94..18d0a9980 100644 --- a/src/fu-config.c +++ b/src/fu-config.c @@ -26,12 +26,17 @@ #include "fu-config.h" +#include "fwupd-error.h" +#include "fwupd-remote-private.h" + static void fu_config_finalize (GObject *obj); struct _FuConfig { GObject parent_instance; GKeyFile *keyfile; + GPtrArray *remotes; + GPtrArray *monitors; GPtrArray *blacklist_devices; GPtrArray *blacklist_plugins; gboolean enable_option_rom; @@ -47,15 +52,217 @@ fu_config_get_sysconfig_dir (void) return "/etc"; } +static GPtrArray * +fu_config_get_config_paths (void) +{ + GPtrArray *paths = g_ptr_array_new_with_free_func (g_free); + const gchar *remotes_dir; + const gchar *system_prefixlibdir = "/usr/lib/fwupd"; + const gchar *system_sysconfdir = "/etc/fwupd"; + g_autofree gchar *sysconfdir = NULL; + + /* only set by the self test program */ + remotes_dir = g_getenv ("FU_SELF_TEST_REMOTES_DIR"); + if (remotes_dir != NULL) { + g_ptr_array_add (paths, g_strdup (remotes_dir)); + return paths; + } + + /* use sysconfig, and then fall back to /etc */ + sysconfdir = g_build_filename (SYSCONFDIR, "fwupd", NULL); + if (g_file_test (sysconfdir, G_FILE_TEST_EXISTS)) { + g_ptr_array_add (paths, g_steal_pointer (&sysconfdir)); + } else { + g_debug ("falling back to system path"); + if (g_file_test (system_sysconfdir, G_FILE_TEST_EXISTS)) + g_ptr_array_add (paths, g_strdup (system_sysconfdir)); + } + + /* add in system-wide locations */ + if (g_file_test (system_prefixlibdir, G_FILE_TEST_EXISTS)) + g_ptr_array_add (paths, g_strdup (system_prefixlibdir)); + + return paths; +} + +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_autofree gchar *filename = g_file_get_path (file); + g_debug ("%s changed, reloading all configs", filename); + if (!fu_config_load (self, &error)) + g_warning ("failed to rescan config: %s", error->message); +} + +static gboolean +fu_config_add_remotes_for_path (FuConfig *self, const gchar *path, GError **error) +{ + const gchar *tmp; + g_autofree gchar *path_remotes = NULL; + g_autoptr(GDir) dir = NULL; + + path_remotes = g_build_filename (path, "remotes.d", NULL); + if (!g_file_test (path_remotes, G_FILE_TEST_EXISTS)) + return TRUE; + dir = g_dir_open (path_remotes, 0, error); + if (dir == NULL) + return FALSE; + while ((tmp = g_dir_read_name (dir)) != NULL) { + GFileMonitor *monitor; + g_autofree gchar *filename = g_build_filename (path_remotes, tmp, NULL); + g_autoptr(FwupdRemote) remote = fwupd_remote_new (); + g_autoptr(GFile) file = g_file_new_for_path (filename); + g_debug ("loading from %s", filename); + if (!fwupd_remote_load_from_filename (remote, filename, + NULL, error)) + return FALSE; + g_ptr_array_add (self->remotes, g_steal_pointer (&remote)); + + /* set up a notify watch */ + monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, error); + if (monitor == NULL) + return FALSE; + g_signal_connect (monitor, "changed", + G_CALLBACK (fu_config_monitor_changed_cb), self); + g_ptr_array_add (self->monitors, monitor); + } + return TRUE; +} + +static gint +fu_config_remote_sort_cb (gconstpointer a, gconstpointer b) +{ + FwupdRemote *remote_a = *((FwupdRemote **) a); + FwupdRemote *remote_b = *((FwupdRemote **) b); + + /* use priority first */ + if (fwupd_remote_get_priority (remote_a) < fwupd_remote_get_priority (remote_b)) + return 1; + if (fwupd_remote_get_priority (remote_a) > fwupd_remote_get_priority (remote_b)) + return -1; + + /* fall back to name */ + return g_strcmp0 (fwupd_remote_get_id (remote_a), + fwupd_remote_get_id (remote_b)); +} + +static FwupdRemote * +fu_config_get_remote_by_id_noref (GPtrArray *remotes, const gchar *remote_id) +{ + for (guint i = 0; i < remotes->len; i++) { + FwupdRemote *remote = g_ptr_array_index (remotes, i); + if (g_strcmp0 (remote_id, fwupd_remote_get_id (remote)) == 0) + return remote; + } + return NULL; +} + +static guint +fu_config_remotes_depsolve_with_direction (FuConfig *self, gint inc) +{ + guint cnt = 0; + for (guint i = 0; i < self->remotes->len; i++) { + FwupdRemote *remote = g_ptr_array_index (self->remotes, i); + gchar **order = inc < 0 ? fwupd_remote_get_order_after (remote) : + fwupd_remote_get_order_before (remote); + if (order == NULL) + continue; + for (guint j = 0; order[j] != NULL; j++) { + FwupdRemote *remote2; + if (g_strcmp0 (order[j], fwupd_remote_get_id (remote)) == 0) { + g_warning ("ignoring self-dep remote %s", order[j]); + continue; + } + remote2 = fu_config_get_remote_by_id_noref (self->remotes, order[j]); + if (remote2 == NULL) { + g_warning ("ignoring unfound remote %s", order[j]); + continue; + } + if (fwupd_remote_get_priority (remote) > fwupd_remote_get_priority (remote2)) + continue; + g_debug ("ordering %s=%s+%i", + fwupd_remote_get_id (remote), + fwupd_remote_get_id (remote2), + inc); + fwupd_remote_set_priority (remote, fwupd_remote_get_priority (remote2) + inc); + + /* increment changes counter */ + cnt++; + } + } + return cnt; +} + +static gboolean +fu_config_load_remotes (FuConfig *self, GError **error) +{ + guint depsolve_check; + g_autoptr(GPtrArray) paths = NULL; + + /* get a list of all config paths */ + paths = fu_config_get_config_paths (); + if (paths->len == 0) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_NOT_FOUND, + "No search paths found"); + return FALSE; + } + + /* look for all remotes */ + for (guint i = 0; i < paths->len; i++) { + const gchar *path = g_ptr_array_index (paths, i); + g_debug ("using config path of %s", path); + if (!fu_config_add_remotes_for_path (self, path, error)) + return FALSE; + } + + /* depsolve */ + for (depsolve_check = 0; depsolve_check < 100; depsolve_check++) { + guint cnt = 0; + cnt += fu_config_remotes_depsolve_with_direction (self, 1); + cnt += fu_config_remotes_depsolve_with_direction (self, -1); + if (cnt == 0) + break; + } + if (depsolve_check == 100) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot depsolve remotes ordering"); + return FALSE; + } + + /* order these by priority, then name */ + g_ptr_array_sort (self->remotes, fu_config_remote_sort_cb); + + /* success */ + return TRUE; +} + gboolean fu_config_load (FuConfig *self, GError **error) { + GFileMonitor *monitor; g_autofree gchar *config_file = NULL; g_auto(GStrv) devices = NULL; g_auto(GStrv) plugins = NULL; + g_autoptr(GFile) file = NULL; g_return_val_if_fail (FU_IS_CONFIG (self), FALSE); + /* ensure empty in case we're called from a monitor change */ + g_ptr_array_set_size (self->blacklist_devices, 0); + g_ptr_array_set_size (self->blacklist_plugins, 0); + g_ptr_array_set_size (self->monitors, 0); + g_ptr_array_set_size (self->remotes, 0); + /* load the main daemon config file */ config_file = g_build_filename (fu_config_get_sysconfig_dir (), "fwupd.conf", NULL); @@ -64,6 +271,15 @@ fu_config_load (FuConfig *self, GError **error) G_KEY_FILE_NONE, error)) return FALSE; + /* set up a notify watch */ + file = g_file_new_for_path (config_file); + monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, error); + if (monitor == NULL) + return FALSE; + g_signal_connect (monitor, "changed", + G_CALLBACK (fu_config_monitor_changed_cb), self); + g_ptr_array_add (self->monitors, monitor); + /* optional, at the moment */ self->enable_option_rom = g_key_file_get_boolean (self->keyfile, @@ -97,9 +313,21 @@ fu_config_load (FuConfig *self, GError **error) } } + /* load remotes */ + if (!fu_config_load_remotes (self, error)) + return FALSE; + + /* success */ return TRUE; } +GPtrArray * +fu_config_get_remotes (FuConfig *self) +{ + g_return_val_if_fail (FU_IS_CONFIG (self), NULL); + return self->remotes; +} + GPtrArray * fu_config_get_blacklist_devices (FuConfig *self) { @@ -134,6 +362,8 @@ fu_config_init (FuConfig *self) self->keyfile = g_key_file_new (); self->blacklist_devices = g_ptr_array_new_with_free_func (g_free); self->blacklist_plugins = g_ptr_array_new_with_free_func (g_free); + self->remotes = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + self->monitors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); } static void @@ -144,6 +374,8 @@ fu_config_finalize (GObject *obj) g_key_file_unref (self->keyfile); g_ptr_array_unref (self->blacklist_devices); g_ptr_array_unref (self->blacklist_plugins); + g_ptr_array_unref (self->remotes); + g_ptr_array_unref (self->monitors); G_OBJECT_CLASS (fu_config_parent_class)->finalize (obj); } diff --git a/src/fu-config.h b/src/fu-config.h index 6f1931005..49866b569 100644 --- a/src/fu-config.h +++ b/src/fu-config.h @@ -36,6 +36,7 @@ gboolean fu_config_load (FuConfig *self, GPtrArray *fu_config_get_blacklist_devices (FuConfig *self); GPtrArray *fu_config_get_blacklist_plugins (FuConfig *self); gboolean fu_config_get_enable_option_rom (FuConfig *self); +GPtrArray *fu_config_get_remotes (FuConfig *self); G_END_DECLS diff --git a/src/fu-main.c b/src/fu-main.c index 071c5582f..a290386ee 100644 --- a/src/fu-main.c +++ b/src/fu-main.c @@ -36,6 +36,7 @@ #include "fwupd-common-private.h" #include "fwupd-enums-private.h" #include "fwupd-release-private.h" +#include "fwupd-remote-private.h" #include "fwupd-resources.h" #include "fu-config.h" @@ -1911,6 +1912,32 @@ fu_main_get_details_local_from_fd (FuMainPrivate *priv, gint fd, GError **error) return g_variant_new ("(a{sa{sv}})", &builder); } +static GVariant * +fu_main_get_remotes_as_variant (FuMainPrivate *priv, GError **error) +{ + GVariantBuilder builder; + GPtrArray *remotes; + + /* get the list of remotes */ + remotes = fu_config_get_remotes (priv->config); + if (remotes->len == 0) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "no remotes configured"); + return NULL; + } + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + for (guint i = 0; i < remotes->len; i++) { + GVariant *tmp; + FwupdRemote *remote = g_ptr_array_index (remotes, i); + tmp = fwupd_remote_to_data (remote, "a{sv}"); + g_variant_builder_add_value (&builder, tmp); + } + return g_variant_new ("(aa{sv})", &builder); +} + static void fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, @@ -1995,6 +2022,18 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender, return; } + /* return variant */ + if (g_strcmp0 (method_name, "GetRemotes") == 0) { + g_debug ("Called %s()", method_name); + val = fu_main_get_remotes_as_variant (priv, &error); + if (val == NULL) { + fu_main_invocation_return_error (priv, invocation, error); + return; + } + fu_main_invocation_return_value (priv, invocation, val); + return; + } + /* return '' */ if (g_strcmp0 (method_name, "ClearResults") == 0) { FuDeviceItem *item = NULL; diff --git a/src/fu-util.c b/src/fu-util.c index 4913afef7..3b665ddc9 100644 --- a/src/fu-util.c +++ b/src/fu-util.c @@ -1227,7 +1227,7 @@ fu_util_get_remotes (FuUtilPrivate *priv, gchar **values, GError **error) if (uri != NULL) { g_autofree gchar *uri_str = soup_uri_to_string (uri, FALSE); /* TRANSLATORS: remote URI */ - fu_util_print_data (_("URI"), uri_str); + fu_util_print_data (_("URL"), uri_str); } uri = fwupd_remote_get_uri_asc (remote); if (uri != NULL) { diff --git a/src/org.freedesktop.fwupd.xml b/src/org.freedesktop.fwupd.xml index 27faa1b88..99cfdb246 100644 --- a/src/org.freedesktop.fwupd.xml +++ b/src/org.freedesktop.fwupd.xml @@ -294,6 +294,24 @@ + + + + + + Gets the list of remotes. + + + + + + + The array remotes, with properties + + + + +