'get-updates'
'get-upgrades'
'get-plugins'
+ 'inhibit'
+ 'uninhibit'
'install'
'local-install'
'modify-config'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a update -d 'Updates all firmware to latest versions available'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a verify -d 'Checks cryptographic hash matches firmware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a verify-update -d 'Update the stored cryptographic hash with current ROM contents'
+complete -c fwupdmgr -n '__fish_use_subcommand' -x -a inhibit -d 'Inhibit the system to prevent upgrades'
+complete -c fwupdmgr -n '__fish_use_subcommand' -x -a uninhibit -d 'Uninhibit the system to allow upgrades'
# commands exclusively consuming device IDs
set -l deviceid_consumers activate clear-results downgrade get-releases get-results get-updates reinstall switch-branch unlock update verify verify-update
}
return TRUE;
}
+
+static void
+fwupd_client_inhibit_cb(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *)user_data;
+ helper->str = fwupd_client_inhibit_finish(FWUPD_CLIENT(source), res, &helper->error);
+ g_main_loop_quit(helper->loop);
+}
+
+/**
+ * fwupd_client_inhibit:
+ * @self: a #FwupdClient
+ * @reason: (not nullable): the inhibit reason, e.g. `user active`
+ * @cancellable: (nullable): optional #GCancellable
+ * @error: (nullable): optional return location for an error
+ *
+ * Marks all devices as unavailable for update. Update is only available if there is no other
+ * inhibit imposed by other applications or by the system (e.g. low power state).
+ *
+ * The same application can inhibit the system multiple times.
+ *
+ * Returns: (transfer full): a string to use for [method@FwupdClient.uninhibit_async],
+ * or %NULL for failure
+ *
+ * Since: 1.8.11
+ **/
+gchar *
+fwupd_client_inhibit(FwupdClient *self,
+ const gchar *reason,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail(FWUPD_IS_CLIENT(self), NULL);
+ g_return_val_if_fail(reason != NULL, NULL);
+ g_return_val_if_fail(cancellable == NULL || G_IS_CANCELLABLE(cancellable), NULL);
+ g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect(self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new(self);
+ fwupd_client_inhibit_async(self, reason, cancellable, fwupd_client_inhibit_cb, helper);
+ g_main_loop_run(helper->loop);
+ if (helper->str == NULL) {
+ g_propagate_error(error, g_steal_pointer(&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer(&helper->str);
+}
+
+static void
+fwupd_client_uninhibit_cb(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *)user_data;
+ helper->ret = fwupd_client_uninhibit_finish(FWUPD_CLIENT(source), res, &helper->error);
+ g_main_loop_quit(helper->loop);
+}
+
+/**
+ * fwupd_client_uninhibit:
+ * @self: a #FwupdClient
+ * @uninhibit_id: (not nullable): the inhibit ID
+ * @cancellable: (nullable): optional #GCancellable
+ * @error: (nullable): optional return location for an error
+ *
+ * Removes the inhibit token added by the application.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.8.11
+ **/
+gboolean
+fwupd_client_uninhibit(FwupdClient *self,
+ const gchar *inhibit_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail(FWUPD_IS_CLIENT(self), FALSE);
+ g_return_val_if_fail(inhibit_id != NULL, FALSE);
+ g_return_val_if_fail(cancellable == NULL || G_IS_CANCELLABLE(cancellable), FALSE);
+ g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect(self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new(self);
+ fwupd_client_uninhibit_async(self,
+ inhibit_id,
+ cancellable,
+ fwupd_client_uninhibit_cb,
+ helper);
+ g_main_loop_run(helper->loop);
+ if (!helper->ret) {
+ g_propagate_error(error, g_steal_pointer(&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
static void
fwupd_client_modify_config_cb(GObject *source, GAsyncResult *res, gpointer user_data)
{
const gchar *device_id,
GCancellable *cancellable,
GError **error) G_GNUC_WARN_UNUSED_RESULT;
+gchar *
+fwupd_client_inhibit(FwupdClient *self,
+ const gchar *reason,
+ GCancellable *cancellable,
+ GError **error) G_GNUC_WARN_UNUSED_RESULT;
+gboolean
+fwupd_client_uninhibit(FwupdClient *self,
+ const gchar *inhibit_id,
+ GCancellable *cancellable,
+ GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean
fwupd_client_modify_config(FwupdClient *self,
const gchar *key,
return g_task_propagate_pointer(G_TASK(res), error);
}
+static void
+fwupd_client_inhibit_cb(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autofree gchar *inhibit_id = NULL;
+ g_autoptr(GTask) task = G_TASK(user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error(error);
+ g_task_return_error(task, g_steal_pointer(&error));
+ return;
+ }
+
+ /* success */
+ g_variant_get(val, "(s)", &inhibit_id);
+ g_task_return_pointer(task, g_steal_pointer(&inhibit_id), g_free);
+}
+
+/**
+ * fwupd_client_inhibit_async:
+ * @self: a #FwupdClient
+ * @reason: (not nullable): the inhibit reason, e.g. `user active`
+ * @cancellable: (nullable): optional #GCancellable
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Marks all devices as unavailable for update. Update is only available if there is no other
+ * inhibit imposed by other applications or by the system (e.g. low power state).
+ *
+ * The same application can inhibit the system multiple times.
+ *
+ * Since: 1.8.11
+ **/
+void
+fwupd_client_inhibit_async(FwupdClient *self,
+ const gchar *reason,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE(self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail(FWUPD_IS_CLIENT(self));
+ g_return_if_fail(reason != NULL);
+ g_return_if_fail(cancellable == NULL || G_IS_CANCELLABLE(cancellable));
+ g_return_if_fail(priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new(self, cancellable, callback, callback_data);
+ g_dbus_proxy_call(priv->proxy,
+ "Inhibit",
+ g_variant_new("(s)", reason),
+ G_DBUS_CALL_FLAGS_NONE,
+ FWUPD_CLIENT_DBUS_PROXY_TIMEOUT,
+ cancellable,
+ fwupd_client_inhibit_cb,
+ g_steal_pointer(&task));
+}
+
+/**
+ * fwupd_client_inhibit_finish:
+ * @self: a #FwupdClient
+ * @res: (not nullable): the asynchronous result
+ * @error: (nullable): optional return location for an error
+ *
+ * Gets the result of [method@FwupdClient.inhibit_async].
+ *
+ * Returns: (transfer full): a string to use for [method@FwupdClient.uninhibit_async],
+ * or %NULL for failure
+ *
+ * Since: 1.8.11
+ **/
+gchar *
+fwupd_client_inhibit_finish(FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail(FWUPD_IS_CLIENT(self), NULL);
+ g_return_val_if_fail(g_task_is_valid(res, self), NULL);
+ g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer(G_TASK(res), error);
+}
+
+static void
+fwupd_client_uninhibit_cb(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK(user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error(error);
+ g_task_return_error(task, g_steal_pointer(&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean(task, TRUE);
+}
+
+/**
+ * fwupd_client_uninhibit_async:
+ * @self: a #FwupdClient
+ * @uninhibit_id: (not nullable): the inhibit ID
+ * @cancellable: (nullable): optional #GCancellable
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Removes the inhibit token added by the application.
+ *
+ * Since: 1.8.11
+ **/
+void
+fwupd_client_uninhibit_async(FwupdClient *self,
+ const gchar *inhibit_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE(self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail(FWUPD_IS_CLIENT(self));
+ g_return_if_fail(inhibit_id != NULL);
+ g_return_if_fail(cancellable == NULL || G_IS_CANCELLABLE(cancellable));
+ g_return_if_fail(priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new(self, cancellable, callback, callback_data);
+ g_dbus_proxy_call(priv->proxy,
+ "Uninhibit",
+ g_variant_new("(s)", inhibit_id),
+ G_DBUS_CALL_FLAGS_NONE,
+ FWUPD_CLIENT_DBUS_PROXY_TIMEOUT,
+ cancellable,
+ fwupd_client_uninhibit_cb,
+ g_steal_pointer(&task));
+}
+
+/**
+ * fwupd_client_uninhibit_finish:
+ * @self: a #FwupdClient
+ * @res: (not nullable): the asynchronous result
+ * @error: (nullable): optional return location for an error
+ *
+ * Gets the result of [method@FwupdClient.uninhibit_async].
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.8.11
+ **/
+gboolean
+fwupd_client_uninhibit_finish(FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail(FWUPD_IS_CLIENT(self), FALSE);
+ g_return_val_if_fail(g_task_is_valid(res, self), FALSE);
+ g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean(G_TASK(res), error);
+}
+
/**
* fwupd_client_add_hint:
* @self: a #FwupdClient
fwupd_client_get_report_metadata_finish(FwupdClient *self,
GAsyncResult *res,
GError **error) G_GNUC_WARN_UNUSED_RESULT;
+void
+fwupd_client_inhibit_async(FwupdClient *self,
+ const gchar *reason,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gchar *
+fwupd_client_inhibit_finish(FwupdClient *self,
+ GAsyncResult *res,
+ GError **error) G_GNUC_WARN_UNUSED_RESULT;
+void
+fwupd_client_uninhibit_async(FwupdClient *self,
+ const gchar *inhibit_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean
+fwupd_client_uninhibit_finish(FwupdClient *self,
+ GAsyncResult *res,
+ GError **error) G_GNUC_WARN_UNUSED_RESULT;
FwupdStatus
fwupd_client_get_status(FwupdClient *self);
return "is-emulated";
if (device_problem == FWUPD_DEVICE_PROBLEM_MISSING_LICENSE)
return "missing-license";
+ if (device_problem == FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT)
+ return "system-inhibit";
if (device_problem == FWUPD_DEVICE_PROBLEM_UNKNOWN)
return "unknown";
return NULL;
return FWUPD_DEVICE_PROBLEM_IS_EMULATED;
if (g_strcmp0(device_problem, "missing-license") == 0)
return FWUPD_DEVICE_PROBLEM_MISSING_LICENSE;
+ if (g_strcmp0(device_problem, "system-inhibit") == 0)
+ return FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT;
return FWUPD_DEVICE_PROBLEM_UNKNOWN;
}
* Since 1.8.6
*/
#define FWUPD_DEVICE_PROBLEM_MISSING_LICENSE (1u << 7)
+/**
+ * FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT:
+ *
+ * The device cannot be updated due to a system-wide inhibit.
+ *
+ * Since 1.8.10
+ */
+#define FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT (1u << 8)
/**
* FWUPD_DEVICE_PROBLEM_UNKNOWN:
*
g_assert_cmpstr(tmp, !=, NULL);
g_assert_cmpint(fwupd_device_flag_from_string(tmp), ==, i);
}
- for (guint64 i = 1; i <= FWUPD_DEVICE_PROBLEM_IS_EMULATED; i *= 2) {
+ for (guint64 i = 1; i <= FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT; i *= 2) {
const gchar *tmp = fwupd_device_problem_to_string(i);
if (tmp == NULL)
g_warning("missing device problem 0x%x", (guint)i);
fwupd_report_to_variant;
local: *;
} LIBFWUPD_1.8.7;
+
+LIBFWUPD_1.8.11 {
+ global:
+ fwupd_client_inhibit;
+ fwupd_client_inhibit_async;
+ fwupd_client_inhibit_finish;
+ fwupd_client_uninhibit;
+ fwupd_client_uninhibit_async;
+ fwupd_client_uninhibit_finish;
+ local: *;
+} LIBFWUPD_1.8.8;
**/
#define FU_CONTEXT_FLAG_SAVE_EVENTS (1u << 0)
+/**
+ * FU_CONTEXT_FLAG_SYSTEM_INHIBIT:
+ *
+ * All devices are not updatable due to a system-wide inhibit.
+ *
+ * Since: 1.8.10
+ **/
+#define FU_CONTEXT_FLAG_SYSTEM_INHIBIT (1u << 1)
+
/**
* FuContextFlags:
*
gboolean update_in_progress;
gboolean pending_stop;
FuDaemonMachineKind machine_kind;
+ GPtrArray *system_inhibits;
};
G_DEFINE_TYPE(FuDaemon, fu_daemon, G_TYPE_OBJECT)
self->process_quit_id = g_idle_add(fu_daemon_schedule_process_quit_cb, self);
}
+typedef struct {
+ gchar *id;
+ gchar *sender;
+ guint watcher_id;
+} FuDaemonSystemInhibit;
+
+static void
+fu_daemon_system_inhibit_free(FuDaemonSystemInhibit *inhibit)
+{
+ g_bus_unwatch_name(inhibit->watcher_id);
+ g_free(inhibit->id);
+ g_free(inhibit->sender);
+ g_free(inhibit);
+}
+
+static void
+fu_daemon_ensure_system_inhibit(FuDaemon *self)
+{
+ FuContext *ctx = fu_engine_get_context(self->engine);
+ if (self->system_inhibits->len > 0) {
+ fu_context_add_flag(ctx, FU_CONTEXT_FLAG_SYSTEM_INHIBIT);
+ return;
+ }
+ fu_context_remove_flag(ctx, FU_CONTEXT_FLAG_SYSTEM_INHIBIT);
+}
+
+static void
+fu_daemon_inhibit_name_vanished_cb(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ FuDaemon *self = FU_DAEMON(user_data);
+ for (guint i = 0; i < self->system_inhibits->len; i++) {
+ FuDaemonSystemInhibit *inhibit = g_ptr_array_index(self->system_inhibits, i);
+ if (g_strcmp0(inhibit->sender, name) == 0) {
+ g_debug("removing %s as %s vanished without calling Uninhibit",
+ inhibit->id,
+ name);
+ g_ptr_array_remove_index(self->system_inhibits, i);
+ fu_daemon_ensure_system_inhibit(self);
+ break;
+ }
+ }
+}
+
static void
fu_daemon_daemon_method_call(GDBusConnection *connection,
const gchar *sender,
g_dbus_method_invocation_return_value(invocation, NULL);
return;
}
+ if (g_strcmp0(method_name, "Inhibit") == 0) {
+ FuDaemonSystemInhibit *inhibit;
+ const gchar *reason = NULL;
+
+ g_variant_get(parameters, "(&s)", &reason);
+ g_debug("Called %s(%s)", method_name, reason);
+
+ /* watch */
+ inhibit = g_new0(FuDaemonSystemInhibit, 1);
+ inhibit->sender = g_strdup(sender);
+ inhibit->id = g_strdup_printf("dbus-%i", g_random_int_range(1, G_MAXINT - 1));
+ inhibit->watcher_id =
+ g_bus_watch_name_on_connection(self->connection,
+ sender,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ NULL,
+ fu_daemon_inhibit_name_vanished_cb,
+ self,
+ NULL);
+ g_ptr_array_add(self->system_inhibits, inhibit);
+ fu_daemon_ensure_system_inhibit(self);
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(s)", inhibit->id));
+ return;
+ }
+ if (g_strcmp0(method_name, "Uninhibit") == 0) {
+ const gchar *inhibit_id = NULL;
+ gboolean found = FALSE;
+
+ g_variant_get(parameters, "(&s)", &inhibit_id);
+ g_debug("Called %s(%s)", method_name, inhibit_id);
+
+ /* find by id, then uninhibit device */
+ for (guint i = 0; i < self->system_inhibits->len; i++) {
+ FuDaemonSystemInhibit *inhibit =
+ g_ptr_array_index(self->system_inhibits, i);
+ if (g_strcmp0(inhibit->id, inhibit_id) == 0) {
+ g_ptr_array_remove_index(self->system_inhibits, i);
+ fu_daemon_ensure_system_inhibit(self);
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ g_dbus_method_invocation_return_error_literal(invocation,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "Cannot find inhibit ID");
+ return;
+ }
+ g_dbus_method_invocation_return_value(invocation, NULL);
+ return;
+ }
if (g_strcmp0(method_name, "Install") == 0) {
#ifdef HAVE_GIO_UNIX
g_free,
(GDestroyNotify)fu_daemon_sender_item_free);
self->loop = g_main_loop_new(NULL, FALSE);
+ self->system_inhibits =
+ g_ptr_array_new_with_free_func((GDestroyNotify)fu_daemon_system_inhibit_free);
}
static void
{
FuDaemon *self = FU_DAEMON(obj);
+ g_ptr_array_unref(self->system_inhibits);
g_hash_table_unref(self->sender_items);
if (self->process_quit_id != 0)
g_source_remove(self->process_quit_id);
fu_device_remove_problem(device, FWUPD_DEVICE_PROBLEM_LID_IS_CLOSED);
}
+static void
+fu_engine_ensure_device_system_inhibit(FuEngine *self, FuDevice *device)
+{
+ if (fu_context_has_flag(self->ctx, FU_CONTEXT_FLAG_SYSTEM_INHIBIT)) {
+ fu_device_add_problem(device, FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT);
+ return;
+ }
+ fu_device_remove_problem(device, FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT);
+}
+
static gboolean
fu_engine_acquiesce_timeout_cb(gpointer user_data)
{
fu_engine_watch_device(self, device);
fu_engine_ensure_device_battery_inhibit(self, device);
fu_engine_ensure_device_lid_inhibit(self, device);
+ fu_engine_ensure_device_system_inhibit(self, device);
fu_engine_acquiesce_reset(self);
g_signal_emit(self, signals[SIGNAL_DEVICE_ADDED], 0, device);
}
FuDevice *device = g_ptr_array_index(devices, i);
fu_engine_ensure_device_battery_inhibit(self, device);
fu_engine_ensure_device_lid_inhibit(self, device);
+ fu_engine_ensure_device_system_inhibit(self, device);
}
}
"notify::battery-threshold",
G_CALLBACK(fu_engine_context_battery_changed_cb),
self);
+ g_signal_connect(FU_CONTEXT(self->ctx),
+ "notify::flags",
+ G_CALLBACK(fu_engine_context_battery_changed_cb),
+ self);
g_signal_connect(FU_CONFIG(self->config),
"changed",
/* TRANSLATORS: The device cannot be updated due to missing vendor's license." */
return g_strdup(_("Device requires a software license to update"));
}
+ if (problem == FWUPD_DEVICE_PROBLEM_SYSTEM_INHIBIT) {
+ /* TRANSLATORS: an application is preventing system updates */
+ return g_strdup(_("All devices are prevented from update by system inhibit"));
+ }
return NULL;
}
struct FuUtilPrivate {
GCancellable *cancellable;
GMainContext *main_ctx;
+ GMainLoop *loop;
GOptionContext *context;
FwupdInstallFlags flags;
FwupdClientDownloadFlags download_flags;
return TRUE;
}
+static gboolean
+fu_util_inhibit(FuUtilPrivate *priv, gchar **values, GError **error)
+{
+ const gchar *reason = "not set";
+ g_autofree gchar *inhibit_id = NULL;
+ g_autoptr(GString) str = g_string_new(NULL);
+
+ if (g_strv_length(values) > 0)
+ reason = values[1];
+
+ /* inhibit then wait */
+ inhibit_id = fwupd_client_inhibit(priv->client, reason, priv->cancellable, error);
+ if (inhibit_id == NULL)
+ return FALSE;
+
+ /* TRANSLATORS: the inhibit ID is a short string like dbus-123456 */
+ g_string_append_printf(str, _("Inhibit ID is %s."), inhibit_id);
+ g_string_append(str, "\n");
+ /* TRANSLATORS: CTRL^C [holding control, and then pressing C] will exit the program */
+ g_string_append(str, _("Use CTRL^C to cancel."));
+ /* TRANSLATORS: this CLI tool is now preventing system updates */
+ fu_util_warning_box(_("System Update Inhibited"), str->str, 80);
+ g_main_loop_run(priv->loop);
+ return TRUE;
+}
+
+static gboolean
+fu_util_uninhibit(FuUtilPrivate *priv, gchar **values, GError **error)
+{
+ /* one argument required */
+ if (g_strv_length(values) != 1) {
+ g_set_error_literal(error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_ARGS,
+ "Invalid arguments, expected INHIBIT-ID");
+ return FALSE;
+ }
+
+ /* just uninhibit with the token */
+ return fwupd_client_uninhibit(priv->client, values[0], priv->cancellable, error);
+}
+
static gboolean
fu_util_device_test(FuUtilPrivate *priv, gchar **values, GError **error)
{
if (priv->current_device != NULL)
g_object_unref(priv->current_device);
g_ptr_array_unref(priv->post_requests);
+ g_main_loop_unref(priv->loop);
g_main_context_unref(priv->main_ctx);
g_object_unref(priv->cancellable);
g_object_unref(priv->progressbar);
return fu_util_setup_interactive_console(error);
}
+static void
+fu_util_cancelled_cb(GCancellable *cancellable, gpointer user_data)
+{
+ FuUtilPrivate *priv = (FuUtilPrivate *)user_data;
+ if (!g_main_loop_is_running(priv->loop))
+ return;
+ /* TRANSLATORS: this is from ctrl+c */
+ g_print("%s\n", _("Cancelled"));
+ g_main_loop_quit(priv->loop);
+}
+
int
main(int argc, char *argv[])
{
/* create helper object */
priv->main_ctx = g_main_context_new();
+ priv->loop = g_main_loop_new(priv->main_ctx, FALSE);
priv->progressbar = fu_progressbar_new();
priv->post_requests = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
fu_progressbar_set_main_context(priv->progressbar, priv->main_ctx);
/* TRANSLATORS: command description */
_("Test a device using a JSON manifest"),
fu_util_device_test);
+ fu_util_cmd_array_add(cmd_array,
+ "inhibit",
+ /* TRANSLATORS: command argument: uppercase, spaces->dashes */
+ _("[REASON]"),
+ /* TRANSLATORS: command description */
+ _("Inhibit the system to prevent upgrades"),
+ fu_util_inhibit);
+ fu_util_cmd_array_add(cmd_array,
+ "uninhibit",
+ /* TRANSLATORS: command argument: uppercase, spaces->dashes */
+ _("INHIBIT-ID"),
+ /* TRANSLATORS: command description */
+ _("Uninhibit the system to allow upgrades"),
+ fu_util_uninhibit);
fu_util_cmd_array_add(
cmd_array,
"get-bios-settings,get-bios-setting",
/* do stuff on ctrl+c */
priv->cancellable = g_cancellable_new();
fu_util_setup_signal_handlers(priv);
+ g_signal_connect(G_CANCELLABLE(priv->cancellable),
+ "cancelled",
+ G_CALLBACK(fu_util_cancelled_cb),
+ priv);
/* sort by command name */
fu_util_cmd_array_sort(cmd_array);
</arg>
</method>
+ <!--***********************************************************-->
+ <method name='Inhibit'>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Marks the system as unavailable for update.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ <arg type='s' name='reason' direction='in'>
+ <doc:doc>
+ <doc:summary>
+ <doc:para>
+ A reason, e.g. <doc:tt>device is being used to capture content</doc:tt>.
+ </doc:para>
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type='s' name='inhibit_id' direction='out'>
+ <doc:doc>
+ <doc:summary>
+ <doc:para>The token that was used for inhibiting.</doc:para>
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ </method>
+
+ <!--***********************************************************-->
+ <method name='Uninhibit'>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Removes the inhibit token added by the application, but only if there is no other
+ inhibit imposed by other applications or by the system (e.g. low power state).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ <arg type='s' name='inhibit_id' direction='in'>
+ <doc:doc>
+ <doc:summary>
+ <doc:para>The token to use for uninhibiting.</doc:para>
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ </method>
+
<!--***********************************************************-->
<method name='Quit'>
<doc:doc>