Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- |
| 2 | * |
| 3 | * Copyright (C) 2015 Richard Hughes <richard@hughsie.com> |
| 4 | * |
| 5 | * Licensed under the GNU General Public License Version 2 |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with this program; if not, write to the Free Software |
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | */ |
| 21 | |
| 22 | #include "config.h" |
| 23 | |
| 24 | #include <stdlib.h> |
| 25 | #include <gio/gio.h> |
| 26 | #include <gio/gunixfdlist.h> |
| 27 | #include <glib/gi18n.h> |
| 28 | #include <locale.h> |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 29 | #include <polkit/polkit.h> |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 30 | |
| 31 | #include "fu-cleanup.h" |
| 32 | #include "fu-common.h" |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 33 | #include "fu-debug.h" |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 34 | #include "fu-device.h" |
| 35 | #include "fu-provider-uefi.h" |
| 36 | #include "fu-resources.h" |
| 37 | |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 38 | typedef struct { |
| 39 | GDBusConnection *connection; |
| 40 | GDBusNodeInfo *introspection_daemon; |
| 41 | GMainLoop *loop; |
| 42 | GPtrArray *devices; |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 43 | GPtrArray *providers; |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 44 | PolkitAuthority *authority; |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 45 | } FuMainPrivate; |
| 46 | |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 47 | typedef struct { |
| 48 | FuDevice *device; |
| 49 | FuProvider *provider; |
| 50 | } FuDeviceItem; |
| 51 | |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 52 | /** |
| 53 | * fu_main_get_device_list_as_strv: |
| 54 | **/ |
| 55 | static gchar ** |
| 56 | fu_main_get_device_list_as_strv (FuMainPrivate *priv) |
| 57 | { |
| 58 | gchar **val; |
| 59 | guint i; |
| 60 | FuDevice *dev_tmp; |
| 61 | |
| 62 | val = g_new0 (gchar *, priv->devices->len + 1); |
| 63 | for (i = 0; i < priv->devices->len; i++) { |
| 64 | dev_tmp = g_ptr_array_index (priv->devices, i); |
| 65 | val[i] = g_strdup (fu_device_get_id (dev_tmp)); |
| 66 | } |
| 67 | return val; |
| 68 | } |
| 69 | |
| 70 | /** |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 71 | * fu_main_item_free: |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 72 | **/ |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 73 | static void |
| 74 | fu_main_item_free (FuDeviceItem *item) |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 75 | { |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 76 | g_object_unref (item->device); |
| 77 | g_object_unref (item->provider); |
| 78 | g_free (item); |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * fu_main_get_item_by_id: |
| 83 | **/ |
| 84 | static FuDeviceItem * |
| 85 | fu_main_get_item_by_id (FuMainPrivate *priv, const gchar *id) |
| 86 | { |
| 87 | FuDeviceItem *item; |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 88 | guint i; |
| 89 | |
| 90 | for (i = 0; i < priv->devices->len; i++) { |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 91 | item = g_ptr_array_index (priv->devices, i); |
| 92 | if (g_strcmp0 (fu_device_get_id (item->device), id) == 0) |
| 93 | return item; |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 94 | } |
| 95 | return NULL; |
| 96 | } |
| 97 | |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 98 | typedef struct { |
| 99 | GDBusMethodInvocation *invocation; |
| 100 | FuMainPrivate *priv; |
| 101 | gint fd; |
| 102 | gchar *id; |
| 103 | } FuMainAuthHelper; |
| 104 | |
| 105 | /** |
| 106 | * fu_main_helper_free: |
| 107 | **/ |
| 108 | static void |
| 109 | fu_main_helper_free (FuMainAuthHelper *helper) |
| 110 | { |
| 111 | g_object_unref (helper->invocation); |
| 112 | g_free (helper->id); |
| 113 | g_free (helper); |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * fu_main_check_authorization_cb: |
| 118 | **/ |
| 119 | static void |
| 120 | fu_main_check_authorization_cb (GObject *source, GAsyncResult *res, gpointer user_data) |
| 121 | { |
| 122 | FuMainAuthHelper *helper = (FuMainAuthHelper *) user_data; |
| 123 | FuDeviceItem *item; |
| 124 | _cleanup_error_free_ GError *error = NULL; |
| 125 | _cleanup_object_unref_ PolkitAuthorizationResult *auth = NULL; |
| 126 | |
| 127 | /* get result */ |
| 128 | auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source), |
| 129 | res, &error); |
| 130 | if (auth == NULL) { |
| 131 | g_dbus_method_invocation_return_error (helper->invocation, |
| 132 | FU_ERROR, |
| 133 | FU_ERROR_INTERNAL, |
| 134 | "could not check for auth: %s", |
| 135 | error->message); |
| 136 | fu_main_helper_free (helper); |
| 137 | return; |
| 138 | } |
| 139 | |
| 140 | /* did not auth */ |
| 141 | if (!polkit_authorization_result_get_is_authorized (auth)) { |
| 142 | g_dbus_method_invocation_return_error (helper->invocation, |
| 143 | FU_ERROR, |
| 144 | FU_ERROR_INTERNAL, |
| 145 | "failed to obtain auth"); |
| 146 | fu_main_helper_free (helper); |
| 147 | return; |
| 148 | } |
| 149 | |
| 150 | /* check the device still exists */ |
| 151 | item = fu_main_get_item_by_id (helper->priv, helper->id); |
| 152 | if (item == NULL) { |
| 153 | g_dbus_method_invocation_return_error (helper->invocation, |
| 154 | FU_ERROR, |
| 155 | FU_ERROR_INTERNAL, |
| 156 | "device %s was removed", |
| 157 | helper->id); |
| 158 | fu_main_helper_free (helper); |
| 159 | return; |
| 160 | } |
| 161 | |
| 162 | /* run the correct provider that added this */ |
| 163 | if (!fu_provider_update_offline (item->provider, |
| 164 | item->device, |
| 165 | helper->fd, &error)) { |
| 166 | g_dbus_method_invocation_return_gerror (helper->invocation, |
| 167 | error); |
| 168 | fu_main_helper_free (helper); |
| 169 | return; |
| 170 | } |
| 171 | |
| 172 | /* success */ |
| 173 | g_dbus_method_invocation_return_value (helper->invocation, NULL); |
| 174 | fu_main_helper_free (helper); |
| 175 | } |
| 176 | |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 177 | /** |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 178 | * fu_main_daemon_method_call: |
| 179 | **/ |
| 180 | static void |
| 181 | fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender, |
| 182 | const gchar *object_path, const gchar *interface_name, |
| 183 | const gchar *method_name, GVariant *parameters, |
| 184 | GDBusMethodInvocation *invocation, gpointer user_data) |
| 185 | { |
| 186 | FuMainPrivate *priv = (FuMainPrivate *) user_data; |
| 187 | GVariant *val; |
| 188 | |
| 189 | /* return 'as' */ |
| 190 | if (g_strcmp0 (method_name, "GetDevices") == 0) { |
| 191 | _cleanup_strv_free_ gchar **devices = NULL; |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 192 | g_debug ("Called %s()", method_name); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 193 | devices = fu_main_get_device_list_as_strv (priv); |
| 194 | val = g_variant_new ("(^as)", devices); |
| 195 | g_dbus_method_invocation_return_value (invocation, val); |
| 196 | return; |
| 197 | } |
| 198 | |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 199 | /* return '' */ |
| 200 | if (g_strcmp0 (method_name, "UpdateOffline") == 0) { |
| 201 | GDBusMessage *message; |
| 202 | GUnixFDList *fd_list; |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 203 | FuDeviceItem *item; |
| 204 | FuMainAuthHelper *helper; |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 205 | const gchar *id = NULL; |
| 206 | gint32 fd_handle = 0; |
| 207 | gint fd; |
| 208 | _cleanup_error_free_ GError *error = NULL; |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 209 | _cleanup_object_unref_ PolkitSubject *subject = NULL; |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 210 | |
| 211 | /* check the id exists */ |
| 212 | g_variant_get (parameters, "(&sh)", &id, &fd_handle); |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 213 | g_debug ("Called %s(%s,%i)", method_name, id, fd_handle); |
| 214 | item = fu_main_get_item_by_id (priv, id); |
| 215 | if (item == NULL) { |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 216 | g_dbus_method_invocation_return_error (invocation, |
| 217 | FU_ERROR, |
| 218 | FU_ERROR_INTERNAL, |
| 219 | "no such ID %s", |
| 220 | id); |
| 221 | return; |
| 222 | } |
| 223 | |
| 224 | /* get the fd */ |
| 225 | message = g_dbus_method_invocation_get_message (invocation); |
| 226 | fd_list = g_dbus_message_get_unix_fd_list (message); |
| 227 | if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) { |
| 228 | g_dbus_method_invocation_return_error (invocation, |
| 229 | FU_ERROR, |
| 230 | FU_ERROR_INTERNAL, |
| 231 | "invalid handle"); |
| 232 | return; |
| 233 | } |
| 234 | fd = g_unix_fd_list_get (fd_list, fd_handle, &error); |
| 235 | if (fd < 0) { |
| 236 | g_dbus_method_invocation_return_gerror (invocation, |
| 237 | error); |
| 238 | return; |
| 239 | } |
| 240 | |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 241 | |
| 242 | /* do authorization async */ |
| 243 | helper = g_new0 (FuMainAuthHelper, 1); |
| 244 | helper->invocation = g_object_ref (invocation); |
| 245 | helper->fd = fd; |
| 246 | helper->id = g_strdup (id); |
| 247 | helper->priv = priv; |
| 248 | subject = polkit_system_bus_name_new (sender); |
| 249 | polkit_authority_check_authorization (priv->authority, subject, |
| 250 | "org.freedesktop.fwupd.update", |
| 251 | NULL, |
| 252 | POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, |
| 253 | NULL, |
| 254 | fu_main_check_authorization_cb, |
| 255 | helper); |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 256 | return; |
| 257 | } |
| 258 | |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 259 | /* we suck */ |
| 260 | g_dbus_method_invocation_return_error (invocation, |
| 261 | FU_ERROR, |
| 262 | FU_ERROR_INTERNAL, |
| 263 | "no such method %s", |
| 264 | method_name); |
| 265 | } |
| 266 | |
| 267 | /** |
| 268 | * fu_main_daemon_get_property: |
| 269 | **/ |
| 270 | static GVariant * |
| 271 | fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender, |
| 272 | const gchar *object_path, const gchar *interface_name, |
| 273 | const gchar *property_name, GError **error, |
| 274 | gpointer user_data) |
| 275 | { |
| 276 | if (g_strcmp0 (property_name, "DaemonVersion") == 0) |
| 277 | return g_variant_new_string (VERSION); |
| 278 | |
| 279 | /* return an error */ |
| 280 | g_set_error (error, |
| 281 | FU_ERROR, |
| 282 | FU_ERROR_INTERNAL, |
| 283 | "failed to get daemon property %s", |
| 284 | property_name); |
| 285 | return NULL; |
| 286 | } |
| 287 | |
| 288 | /** |
| 289 | * fu_main_on_bus_acquired_cb: |
| 290 | **/ |
| 291 | static void |
| 292 | fu_main_on_bus_acquired_cb (GDBusConnection *connection, |
| 293 | const gchar *name, |
| 294 | gpointer user_data) |
| 295 | { |
| 296 | FuMainPrivate *priv = (FuMainPrivate *) user_data; |
| 297 | guint registration_id; |
| 298 | static const GDBusInterfaceVTable interface_vtable = { |
| 299 | fu_main_daemon_method_call, |
| 300 | fu_main_daemon_get_property, |
| 301 | NULL |
| 302 | }; |
| 303 | |
| 304 | priv->connection = g_object_ref (connection); |
| 305 | registration_id = g_dbus_connection_register_object (connection, |
| 306 | FWUPD_DBUS_PATH, |
| 307 | priv->introspection_daemon->interfaces[0], |
| 308 | &interface_vtable, |
| 309 | priv, /* user_data */ |
| 310 | NULL, /* user_data_free_func */ |
| 311 | NULL); /* GError** */ |
| 312 | g_assert (registration_id > 0); |
| 313 | } |
| 314 | |
| 315 | /** |
| 316 | * fu_main_on_name_acquired_cb: |
| 317 | **/ |
| 318 | static void |
| 319 | fu_main_on_name_acquired_cb (GDBusConnection *connection, |
| 320 | const gchar *name, |
| 321 | gpointer user_data) |
| 322 | { |
| 323 | FuMainPrivate *priv = (FuMainPrivate *) user_data; |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 324 | FuProvider *provider; |
| 325 | guint i; |
| 326 | |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 327 | g_debug ("FuMain: acquired name: %s", name); |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 328 | for (i = 0; i < priv->providers->len; i++) { |
| 329 | _cleanup_error_free_ GError *error = NULL; |
| 330 | provider = g_ptr_array_index (priv->providers, i); |
| 331 | if (!fu_provider_coldplug (FU_PROVIDER (provider), &error)) |
| 332 | g_warning ("Failed to coldplug: %s", error->message); |
| 333 | } |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 334 | } |
| 335 | |
| 336 | /** |
| 337 | * fu_main_on_name_lost_cb: |
| 338 | **/ |
| 339 | static void |
| 340 | fu_main_on_name_lost_cb (GDBusConnection *connection, |
| 341 | const gchar *name, |
| 342 | gpointer user_data) |
| 343 | { |
| 344 | FuMainPrivate *priv = (FuMainPrivate *) user_data; |
| 345 | g_debug ("FuMain: lost name: %s", name); |
| 346 | g_main_loop_quit (priv->loop); |
| 347 | } |
| 348 | |
| 349 | /** |
| 350 | * fu_main_timed_exit_cb: |
| 351 | **/ |
| 352 | static gboolean |
| 353 | fu_main_timed_exit_cb (gpointer user_data) |
| 354 | { |
| 355 | GMainLoop *loop = (GMainLoop *) user_data; |
| 356 | g_main_loop_quit (loop); |
| 357 | return G_SOURCE_REMOVE; |
| 358 | } |
| 359 | |
| 360 | /** |
| 361 | * fu_main_load_introspection: |
| 362 | **/ |
| 363 | static GDBusNodeInfo * |
| 364 | fu_main_load_introspection (const gchar *filename, GError **error) |
| 365 | { |
| 366 | _cleanup_bytes_unref_ GBytes *data = NULL; |
| 367 | _cleanup_free_ gchar *path = NULL; |
| 368 | |
| 369 | /* lookup data */ |
| 370 | path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL); |
| 371 | data = g_resource_lookup_data (fu_get_resource (), |
| 372 | path, |
| 373 | G_RESOURCE_LOOKUP_FLAGS_NONE, |
| 374 | error); |
| 375 | if (data == NULL) |
| 376 | return NULL; |
| 377 | |
| 378 | /* build introspection from XML */ |
| 379 | return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error); |
| 380 | } |
| 381 | |
| 382 | /** |
| 383 | * cd_main_provider_device_added_cb: |
| 384 | **/ |
| 385 | static void |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 386 | cd_main_provider_device_added_cb (FuProvider *provider, |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 387 | FuDevice *device, |
| 388 | gpointer user_data) |
| 389 | { |
| 390 | FuMainPrivate *priv = (FuMainPrivate *) user_data; |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 391 | FuDeviceItem *item; |
| 392 | |
| 393 | item = g_new0 (FuDeviceItem, 1); |
| 394 | item->device = g_object_ref (device); |
| 395 | item->provider = g_object_ref (provider); |
| 396 | g_ptr_array_add (priv->devices, item); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 397 | } |
| 398 | |
| 399 | /** |
| 400 | * cd_main_provider_device_removed_cb: |
| 401 | **/ |
| 402 | static void |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 403 | cd_main_provider_device_removed_cb (FuProvider *provider, |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 404 | FuDevice *device, |
| 405 | gpointer user_data) |
| 406 | { |
| 407 | FuMainPrivate *priv = (FuMainPrivate *) user_data; |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 408 | FuDeviceItem *item; |
| 409 | |
| 410 | item = fu_main_get_item_by_id (priv, fu_device_get_id (device)); |
| 411 | if (item == NULL) { |
| 412 | g_warning ("can't remove device %s", fu_device_get_id (device)); |
| 413 | return; |
| 414 | } |
| 415 | g_ptr_array_remove (priv->devices, item); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 416 | } |
| 417 | |
| 418 | /** |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 419 | * fu_main_add_provider: |
| 420 | **/ |
| 421 | static void |
| 422 | fu_main_add_provider (FuMainPrivate *priv, FuProvider *provider) |
| 423 | { |
| 424 | g_signal_connect (provider, "device-added", |
| 425 | G_CALLBACK (cd_main_provider_device_added_cb), |
| 426 | priv); |
| 427 | g_signal_connect (provider, "device-removed", |
| 428 | G_CALLBACK (cd_main_provider_device_removed_cb), |
| 429 | priv); |
| 430 | g_ptr_array_add (priv->providers, provider); |
| 431 | } |
| 432 | |
| 433 | /** |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 434 | * main: |
| 435 | **/ |
| 436 | int |
| 437 | main (int argc, char *argv[]) |
| 438 | { |
| 439 | FuMainPrivate *priv = NULL; |
| 440 | gboolean immediate_exit = FALSE; |
| 441 | gboolean ret; |
| 442 | gboolean timed_exit = FALSE; |
| 443 | GOptionContext *context; |
| 444 | guint owner_id = 0; |
| 445 | guint retval = 1; |
| 446 | const GOptionEntry options[] = { |
| 447 | { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit, |
| 448 | /* TRANSLATORS: exit after we've started up, used for user profiling */ |
| 449 | _("Exit after a small delay"), NULL }, |
| 450 | { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit, |
| 451 | /* TRANSLATORS: exit straight away, used for automatic profiling */ |
| 452 | _("Exit after the engine has loaded"), NULL }, |
| 453 | { NULL} |
| 454 | }; |
| 455 | _cleanup_error_free_ GError *error = NULL; |
| 456 | |
| 457 | setlocale (LC_ALL, ""); |
| 458 | |
| 459 | bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
| 460 | bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
| 461 | textdomain (GETTEXT_PACKAGE); |
| 462 | |
| 463 | /* TRANSLATORS: program name */ |
| 464 | g_set_application_name (_("Firmware Update")); |
| 465 | context = g_option_context_new (NULL); |
| 466 | g_option_context_add_main_entries (context, options, NULL); |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 467 | g_option_context_add_group (context, fu_debug_get_option_group ()); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 468 | g_option_context_set_summary (context, _("Firmware Update D-Bus Service")); |
| 469 | ret = g_option_context_parse (context, &argc, &argv, &error); |
| 470 | if (!ret) { |
| 471 | g_warning ("FuMain: failed to parse command line arguments: %s", |
| 472 | error->message); |
| 473 | goto out; |
| 474 | } |
| 475 | |
| 476 | /* create new objects */ |
| 477 | priv = g_new0 (FuMainPrivate, 1); |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 478 | priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) fu_main_item_free); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 479 | priv->loop = g_main_loop_new (NULL, FALSE); |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 480 | |
| 481 | /* add providers */ |
| 482 | priv->providers = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); |
| 483 | fu_main_add_provider (priv, fu_provider_uefi_new ()); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 484 | |
| 485 | /* load introspection from file */ |
| 486 | priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml", |
| 487 | &error); |
| 488 | if (priv->introspection_daemon == NULL) { |
| 489 | g_warning ("FuMain: failed to load daemon introspection: %s", |
| 490 | error->message); |
| 491 | goto out; |
| 492 | } |
| 493 | |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 494 | /* get authority */ |
| 495 | priv->authority = polkit_authority_get_sync (NULL, &error); |
| 496 | if (priv->authority == NULL) { |
| 497 | g_warning ("FuMain: failed to load polkit authority: %s", |
| 498 | error->message); |
| 499 | goto out; |
| 500 | } |
| 501 | |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 502 | /* own the object */ |
| 503 | owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM, |
| 504 | FWUPD_DBUS_SERVICE, |
| 505 | G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | |
| 506 | G_BUS_NAME_OWNER_FLAGS_REPLACE, |
| 507 | fu_main_on_bus_acquired_cb, |
| 508 | fu_main_on_name_acquired_cb, |
| 509 | fu_main_on_name_lost_cb, |
| 510 | priv, NULL); |
| 511 | |
| 512 | /* Only timeout and close the mainloop if we have specified it |
| 513 | * on the command line */ |
| 514 | if (immediate_exit) |
| 515 | g_idle_add (fu_main_timed_exit_cb, priv->loop); |
| 516 | else if (timed_exit) |
| 517 | g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop); |
| 518 | |
| 519 | /* wait */ |
| 520 | g_info ("Daemon ready for requests"); |
| 521 | g_main_loop_run (priv->loop); |
| 522 | |
| 523 | /* success */ |
| 524 | retval = 0; |
| 525 | out: |
| 526 | g_option_context_free (context); |
| 527 | if (owner_id > 0) |
| 528 | g_bus_unown_name (owner_id); |
| 529 | if (priv != NULL) { |
| 530 | if (priv->loop != NULL) |
| 531 | g_main_loop_unref (priv->loop); |
| 532 | if (priv->connection != NULL) |
| 533 | g_object_unref (priv->connection); |
Richard Hughes | f508e76 | 2015-02-27 12:49:36 +0000 | [diff] [blame^] | 534 | if (priv->authority != NULL) |
| 535 | g_object_unref (priv->authority); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 536 | if (priv->introspection_daemon != NULL) |
| 537 | g_dbus_node_info_unref (priv->introspection_daemon); |
Richard Hughes | 8bbfdf4 | 2015-02-26 22:28:09 +0000 | [diff] [blame] | 538 | g_ptr_array_unref (priv->providers); |
Richard Hughes | 8dbfb1c | 2015-02-26 13:07:40 +0000 | [diff] [blame] | 539 | g_ptr_array_unref (priv->devices); |
| 540 | g_free (priv); |
| 541 | } |
| 542 | return retval; |
| 543 | } |
| 544 | |