Allow the root user to ask the daemon to quit

This makes it easier to test the fwupd in the installed tests:

    sudo gdbus call --system \
    	--dest org.freedesktop.fwupd \
    	--object-path / \
    	--method org.freedesktop.fwupd.Quit
This commit is contained in:
Richard Hughes 2022-01-28 15:20:26 +00:00
parent a89e4ae2fc
commit 7290da5dda
4 changed files with 61 additions and 0 deletions

View File

@ -80,6 +80,13 @@ fu_engine_request_set_device_flags(FuEngineRequest *self, FwupdDeviceFlags devic
self->device_flags = device_flags; self->device_flags = device_flags;
} }
gboolean
fu_engine_request_has_device_flag(FuEngineRequest *self, FwupdDeviceFlags device_flag)
{
g_return_val_if_fail(FU_IS_ENGINE_REQUEST(self), FALSE);
return (self->device_flags & device_flag) > 0;
}
static void static void
fu_engine_request_init(FuEngineRequest *self) fu_engine_request_init(FuEngineRequest *self)
{ {

View File

@ -31,6 +31,8 @@ void
fu_engine_request_set_locale(FuEngineRequest *self, const gchar *locale); fu_engine_request_set_locale(FuEngineRequest *self, const gchar *locale);
gboolean gboolean
fu_engine_request_has_feature_flag(FuEngineRequest *self, FwupdFeatureFlags feature_flag); fu_engine_request_has_feature_flag(FuEngineRequest *self, FwupdFeatureFlags feature_flag);
gboolean
fu_engine_request_has_device_flag(FuEngineRequest *self, FwupdDeviceFlags device_flag);
FwupdDeviceFlags FwupdDeviceFlags
fu_engine_request_get_device_flags(FuEngineRequest *self); fu_engine_request_get_device_flags(FuEngineRequest *self);
void void

View File

@ -77,6 +77,7 @@ typedef struct {
PolkitAuthority *authority; PolkitAuthority *authority;
#endif #endif
guint owner_id; guint owner_id;
guint process_quit_id;
FuEngine *engine; FuEngine *engine;
gboolean update_in_progress; gboolean update_in_progress;
gboolean pending_sigterm; gboolean pending_sigterm;
@ -982,6 +983,32 @@ fu_main_device_id_valid(const gchar *device_id, GError **error)
return FALSE; return FALSE;
} }
static gboolean
fu_main_schedule_process_quit_cb(gpointer user_data)
{
FuMainPrivate *priv = (FuMainPrivate *)user_data;
g_debug("daemon asked to quit, shutting down");
priv->process_quit_id = 0;
g_main_loop_quit(priv->loop);
return G_SOURCE_REMOVE;
}
static void
fu_main_schedule_process_quit(FuMainPrivate *priv)
{
/* busy? */
if (priv->update_in_progress) {
g_warning("asked to quit during a firmware update, ignoring");
return;
}
/* allow the daemon to respond to the request, then quit */
if (priv->process_quit_id != 0)
g_source_remove(priv->process_quit_id);
priv->process_quit_id = g_idle_add(fu_main_schedule_process_quit_cb, priv);
}
static void static void
fu_main_daemon_method_call(GDBusConnection *connection, fu_main_daemon_method_call(GDBusConnection *connection,
const gchar *sender, const gchar *sender,
@ -1165,6 +1192,18 @@ fu_main_daemon_method_call(GDBusConnection *connection,
#endif /* HAVE_POLKIT */ #endif /* HAVE_POLKIT */
return; return;
} }
if (g_strcmp0(method_name, "Quit") == 0) {
if (!fu_engine_request_has_device_flag(request, FWUPD_DEVICE_FLAG_TRUSTED)) {
g_dbus_method_invocation_return_error_literal(invocation,
FWUPD_ERROR,
FWUPD_ERROR_PERMISSION_DENIED,
"Permission denied");
return;
}
fu_main_schedule_process_quit(priv);
g_dbus_method_invocation_return_value(invocation, NULL);
return;
}
if (g_strcmp0(method_name, "SelfSign") == 0) { if (g_strcmp0(method_name, "SelfSign") == 0) {
GVariant *prop_value; GVariant *prop_value;
const gchar *prop_key; const gchar *prop_key;
@ -1990,6 +2029,8 @@ static void
fu_main_private_free(FuMainPrivate *priv) fu_main_private_free(FuMainPrivate *priv)
{ {
g_hash_table_unref(priv->sender_items); g_hash_table_unref(priv->sender_items);
if (priv->process_quit_id != 0)
g_source_remove(priv->process_quit_id);
if (priv->loop != NULL) if (priv->loop != NULL)
g_main_loop_unref(priv->loop); g_main_loop_unref(priv->loop);
if (priv->owner_id > 0) if (priv->owner_id > 0)

View File

@ -821,6 +821,17 @@
</arg> </arg>
</method> </method>
<!--***********************************************************-->
<method name='Quit'>
<doc:doc>
<doc:description>
<doc:para>
Ask the daemon to quit. This can only be called by the root user.
</doc:para>
</doc:description>
</doc:doc>
</method>
<!--***********************************************************--> <!--***********************************************************-->
<signal name='Changed'> <signal name='Changed'>
<doc:doc> <doc:doc>