1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  *
3  * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
4  * Copyright (C)      2016 Peter Hatina <phatina@redhat.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 #include "config.h"
23 #include <glib/gi18n-lib.h>
24 #include <uuid.h>
25 #include <blockdev/blockdev.h>
26 
27 #include "udiskslogging.h"
28 #include "udisksdaemon.h"
29 #include "udisksdaemonutil.h"
30 #include "udisksprovider.h"
31 #include "udiskslinuxprovider.h"
32 #include "udisksmountmonitor.h"
33 #include "udisksmount.h"
34 #include "udisksbasejob.h"
35 #include "udisksspawnedjob.h"
36 #include "udisksthreadedjob.h"
37 #include "udiskssimplejob.h"
38 #include "udisksstate.h"
39 #include "udiskscrypttabmonitor.h"
40 #include "udiskscrypttabentry.h"
41 #include "udiskslinuxblockobject.h"
42 #include "udiskslinuxdevice.h"
43 #include "udisksmodulemanager.h"
44 #include "udisksmodule.h"
45 #include "udisksconfigmanager.h"
46 #include "udiskslinuxmountoptions.h"
47 
48 #ifdef HAVE_LIBMOUNT_UTAB
49 #include "udisksutabmonitor.h"
50 #endif
51 
52 /**
53  * SECTION:udisksdaemon
54  * @title: UDisksDaemon
55  * @short_description: Main daemon object
56  *
57  * Object holding all global state.
58  */
59 
60 typedef struct _UDisksDaemonClass   UDisksDaemonClass;
61 
62 /**
63  * UDisksDaemon:
64  *
65  * The #UDisksDaemon structure contains only private data and should
66  * only be accessed using the provided API.
67  */
68 struct _UDisksDaemon
69 {
70   GObject parent_instance;
71   GDBusConnection *connection;
72   GDBusObjectManagerServer *object_manager;
73 
74   UDisksMountMonitor *mount_monitor;
75 
76   UDisksLinuxProvider *linux_provider;
77 
78   /* may be NULL if polkit is masked */
79   PolkitAuthority *authority;
80 
81   UDisksState *state;
82 
83   UDisksCrypttabMonitor *crypttab_monitor;
84 
85 #ifdef HAVE_LIBMOUNT_UTAB
86   UDisksUtabMonitor *utab_monitor;
87 #endif
88 
89   UDisksModuleManager *module_manager;
90 
91   UDisksConfigManager *config_manager;
92 
93   gboolean disable_modules;
94   gboolean force_load_modules;
95   gboolean uninstalled;
96   gboolean enable_tcrypt;
97   gchar *uuid;
98 };
99 
100 struct _UDisksDaemonClass
101 {
102   GObjectClass parent_class;
103 };
104 
105 enum
106 {
107   PROP_0,
108   PROP_CONNECTION,
109   PROP_OBJECT_MANAGER,
110   PROP_MOUNT_MONITOR,
111   PROP_CRYPTTAB_MONITOR,
112   PROP_MODULE_MANAGER,
113   PROP_CONFIG_MANAGER,
114   PROP_DISABLE_MODULES,
115   PROP_FORCE_LOAD_MODULES,
116   PROP_UNINSTALLED,
117   PROP_ENABLE_TCRYPT,
118   PROP_UUID,
119 };
120 
121 G_DEFINE_TYPE (UDisksDaemon, udisks_daemon, G_TYPE_OBJECT);
122 
123 static void
udisks_daemon_finalize(GObject * object)124 udisks_daemon_finalize (GObject *object)
125 {
126   UDisksDaemon *daemon = UDISKS_DAEMON (object);
127 
128   udisks_state_stop_cleanup (daemon->state);
129 
130   /* Modules use the monitors and try to reference them when cleaning up */
131   udisks_module_manager_unload_modules (daemon->module_manager);
132 
133   g_clear_object (&daemon->authority);
134   g_object_unref (daemon->object_manager);
135   g_object_unref (daemon->linux_provider);
136   g_object_unref (daemon->connection);
137   g_object_unref (daemon->mount_monitor);
138   g_object_unref (daemon->crypttab_monitor);
139 #ifdef HAVE_LIBMOUNT_UTAB
140   g_object_unref (daemon->utab_monitor);
141 #endif
142   g_clear_object (&daemon->module_manager);
143 
144   g_object_unref (daemon->state);
145   g_free (daemon->uuid);
146 
147   g_clear_object (&daemon->config_manager);
148 
149   if (G_OBJECT_CLASS (udisks_daemon_parent_class)->finalize != NULL)
150     G_OBJECT_CLASS (udisks_daemon_parent_class)->finalize (object);
151 }
152 
153 static void
udisks_daemon_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)154 udisks_daemon_get_property (GObject    *object,
155                             guint       prop_id,
156                             GValue     *value,
157                             GParamSpec *pspec)
158 {
159   UDisksDaemon *daemon = UDISKS_DAEMON (object);
160 
161   switch (prop_id)
162     {
163     case PROP_CONNECTION:
164       g_value_set_object (value, udisks_daemon_get_connection (daemon));
165       break;
166 
167     case PROP_OBJECT_MANAGER:
168       g_value_set_object (value, udisks_daemon_get_object_manager (daemon));
169       break;
170 
171     case PROP_MOUNT_MONITOR:
172       g_value_set_object (value, udisks_daemon_get_mount_monitor (daemon));
173       break;
174 
175     case PROP_CRYPTTAB_MONITOR:
176       g_value_set_object (value, udisks_daemon_get_crypttab_monitor (daemon));
177       break;
178 
179     case PROP_MODULE_MANAGER:
180       g_value_set_object (value, udisks_daemon_get_module_manager (daemon));
181       break;
182 
183     case PROP_CONFIG_MANAGER:
184       g_value_set_object (value, udisks_daemon_get_config_manager (daemon));
185       break;
186 
187     case PROP_DISABLE_MODULES:
188       g_value_set_boolean (value, udisks_daemon_get_disable_modules (daemon));
189       break;
190 
191     case PROP_FORCE_LOAD_MODULES:
192       g_value_set_boolean (value, udisks_daemon_get_force_load_modules (daemon));
193       break;
194 
195     case PROP_UNINSTALLED:
196       g_value_set_boolean (value, udisks_daemon_get_uninstalled (daemon));
197       break;
198 
199     case PROP_ENABLE_TCRYPT:
200       g_value_set_boolean (value, udisks_daemon_get_enable_tcrypt (daemon));
201       break;
202 
203     case PROP_UUID:
204       g_value_set_string (value, udisks_daemon_get_uuid (daemon));
205       break;
206 
207     default:
208       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209       break;
210     }
211 }
212 
213 static void
udisks_daemon_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)214 udisks_daemon_set_property (GObject      *object,
215                             guint         prop_id,
216                             const GValue *value,
217                             GParamSpec   *pspec)
218 {
219   UDisksDaemon *daemon = UDISKS_DAEMON (object);
220   const gchar *s;
221   uuid_t uu;
222 
223   switch (prop_id)
224     {
225     case PROP_CONNECTION:
226       g_assert (daemon->connection == NULL);
227       daemon->connection = g_value_dup_object (value);
228       break;
229 
230     case PROP_DISABLE_MODULES:
231       daemon->disable_modules = g_value_get_boolean (value);
232       break;
233 
234     case PROP_FORCE_LOAD_MODULES:
235       daemon->force_load_modules = g_value_get_boolean (value);
236       break;
237 
238     case PROP_UNINSTALLED:
239       daemon->uninstalled = g_value_get_boolean (value);
240       break;
241 
242     case PROP_ENABLE_TCRYPT:
243       daemon->enable_tcrypt = g_value_get_boolean (value);
244       break;
245 
246     case PROP_UUID:
247       s = g_value_get_string (value);
248       if (s != NULL && uuid_parse (s, uu) == 0)
249         {
250           g_free (daemon->uuid);
251           daemon->uuid = g_strdup (s);
252         }
253       else
254         g_warning ("Invalid UUID string '%s'", s);
255       break;
256 
257     default:
258       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
259       break;
260     }
261 }
262 
263 static void
udisks_daemon_init(UDisksDaemon * daemon)264 udisks_daemon_init (UDisksDaemon *daemon)
265 {
266 }
267 
268 static void
mount_monitor_on_mount_removed(UDisksMountMonitor * monitor,UDisksMount * mount,gpointer user_data)269 mount_monitor_on_mount_removed (UDisksMountMonitor *monitor,
270                                 UDisksMount        *mount,
271                                 gpointer            user_data)
272 {
273   UDisksDaemon *daemon = UDISKS_DAEMON (user_data);
274   udisks_state_check (daemon->state);
275 }
276 
277 static gboolean
load_modules_in_idle_cb(gpointer user_data)278 load_modules_in_idle_cb (gpointer user_data)
279 {
280   UDisksDaemon *daemon = UDISKS_DAEMON (user_data);
281 
282   /* clear the state file, loading all modules anyway */
283   udisks_state_clear_modules (daemon->state);
284 
285   udisks_module_manager_load_modules (daemon->module_manager);
286 
287   return G_SOURCE_REMOVE;
288 }
289 
290 static gboolean
check_modules_state_in_idle_cb(gpointer user_data)291 check_modules_state_in_idle_cb (gpointer user_data)
292 {
293   UDisksDaemon *daemon = UDISKS_DAEMON (user_data);
294   gchar **modules;
295   gchar **l;
296   GError *error = NULL;
297 
298   modules = udisks_state_get_modules (daemon->state);
299 
300   /* first clear the state file */
301   udisks_state_clear_modules (daemon->state);
302 
303   if (modules)
304     {
305       if (*modules)
306         g_warning ("Unclean shutdown detected, reloading modules from previous session.");
307 
308       for (l = modules; l && *l; l++)
309         if (! udisks_module_manager_load_single_module (daemon->module_manager, *l, &error))
310           {
311             g_warning ("Error re-initializing module %s: %s", *l, error->message);
312             g_clear_error (&error);
313           }
314 
315       g_strfreev (modules);
316     }
317 
318   return G_SOURCE_REMOVE;
319 }
320 
321 static void
udisks_daemon_constructed(GObject * object)322 udisks_daemon_constructed (GObject *object)
323 {
324   UDisksDaemon *daemon = UDISKS_DAEMON (object);
325   GError *error;
326   gboolean ret = FALSE;
327   gchar uuid_buf[UUID_STR_LEN] = {0};
328   uuid_t uuid;
329 
330   /* NULL means no specific so_name (implementation) */
331   BDPluginSpec part_plugin = {BD_PLUGIN_PART, NULL};
332   BDPluginSpec swap_plugin = {BD_PLUGIN_SWAP, NULL};
333   BDPluginSpec loop_plugin = {BD_PLUGIN_LOOP, NULL};
334   BDPluginSpec mdraid_plugin = {BD_PLUGIN_MDRAID, NULL};
335   BDPluginSpec fs_plugin = {BD_PLUGIN_FS, NULL};
336   BDPluginSpec crypto_plugin = {BD_PLUGIN_CRYPTO, NULL};
337 
338   /* The core daemon needs the part, swap, loop, mdraid, fs and crypto plugins.
339      Additional plugins are required by various modules, but they make sure
340      plugins are loaded themselves. */
341   BDPluginSpec *plugins[] = {&part_plugin, &swap_plugin, &loop_plugin, &mdraid_plugin,
342                              &fs_plugin, &crypto_plugin, NULL};
343   BDPluginSpec **plugin_p = NULL;
344   error = NULL;
345 
346   /* Skip runtime dependency checks when initializing libblockdev. Plugin
347      shouldn't fail to load just because some if its dependencies is missing.
348    */
349   ret = bd_switch_init_checks (FALSE, &error);
350   if (!ret)
351     {
352       udisks_error ("Error initializing libblockdev library: %s (%s, %d)",
353                     error->message, g_quark_to_string (error->domain), error->code);
354       g_clear_error (&error);
355     }
356 
357   ret = bd_try_init (plugins, NULL, NULL, &error);
358   if (!ret)
359     {
360       if (error)
361         {
362           udisks_error ("Error initializing libblockdev library: %s (%s, %d)",
363                         error->message, g_quark_to_string (error->domain), error->code);
364           g_clear_error (&error);
365         }
366     else
367       {
368         /* a missing plugin is okay, calling functions from it will fail, but
369            until that happens, life will just be great */
370         for (plugin_p=plugins; *plugin_p; plugin_p++)
371           if (!bd_is_plugin_available ((*plugin_p)->name))
372             udisks_warning ("Failed to load the '%s' libblockdev plugin",
373                             bd_get_plugin_name ((*plugin_p)->name));
374       }
375     }
376 
377   /* Generate global UUID */
378   uuid_generate (uuid);
379   uuid_unparse (uuid, &uuid_buf[0]);
380   daemon->uuid = g_strdup (uuid_buf);
381 
382   daemon->authority = polkit_authority_get_sync (NULL, &error);
383   if (daemon->authority == NULL)
384     {
385       udisks_critical ("Error initializing polkit authority: %s (%s, %d)",
386                     error->message, g_quark_to_string (error->domain), error->code);
387       g_clear_error (&error);
388     }
389 
390   daemon->object_manager = g_dbus_object_manager_server_new ("/org/freedesktop/UDisks2");
391 
392   if (!g_file_test ("/run/udisks2", G_FILE_TEST_IS_DIR))
393     {
394       if (g_mkdir_with_parents ("/run/udisks2", 0700) != 0)
395         {
396           udisks_critical ("Error creating directory %s: %m", "/run/udisks2");
397         }
398     }
399 
400   if (!g_file_test (PACKAGE_LOCALSTATE_DIR "/lib/udisks2", G_FILE_TEST_IS_DIR))
401     {
402       if (g_mkdir_with_parents (PACKAGE_LOCALSTATE_DIR "/lib/udisks2", 0700) != 0)
403         {
404           udisks_critical ("Error creating directory %s: %m", PACKAGE_LOCALSTATE_DIR "/lib/udisks2");
405         }
406     }
407 
408 
409   if (! daemon->uninstalled)
410     {
411       daemon->config_manager = udisks_config_manager_new ();
412       daemon->module_manager = udisks_module_manager_new (daemon);
413     }
414   else
415     {
416       daemon->config_manager = udisks_config_manager_new_uninstalled ();
417       daemon->module_manager = udisks_module_manager_new_uninstalled (daemon);
418     }
419 
420   daemon->mount_monitor = udisks_mount_monitor_new ();
421 
422   daemon->state = udisks_state_new (daemon);
423 
424   g_signal_connect (daemon->mount_monitor,
425                     "mount-removed",
426                     G_CALLBACK (mount_monitor_on_mount_removed),
427                     daemon);
428 
429   daemon->crypttab_monitor = udisks_crypttab_monitor_new ();
430 #ifdef HAVE_LIBMOUNT_UTAB
431   daemon->utab_monitor = udisks_utab_monitor_new ();
432 #endif
433 
434   /* now add providers */
435   daemon->linux_provider = udisks_linux_provider_new (daemon);
436   udisks_provider_start (UDISKS_PROVIDER (daemon->linux_provider));
437 
438   /* fill in default mount options */
439   g_object_set_data_full (object,
440                           "mount-options",
441                           udisks_linux_mount_options_get_builtin (),
442                           (GDestroyNotify) g_hash_table_destroy);
443 
444   /* Load modules if requested but only once providers have started and
445    * have connected on the UDisksModuleManager::modules-activated signal.
446    */
447   if (daemon->force_load_modules ||
448       udisks_config_manager_get_load_preference (daemon->config_manager) == UDISKS_MODULE_LOAD_ONSTARTUP)
449     {
450       /* load all modules */
451       g_idle_add (load_modules_in_idle_cb, daemon);
452     } else {
453       /* crash recovery - load active modules from previous session */
454       g_idle_add (check_modules_state_in_idle_cb, daemon);
455     }
456 
457   /* Export the ObjectManager */
458   g_dbus_object_manager_server_set_connection (daemon->object_manager, daemon->connection);
459 
460   /* Start cleaning up */
461   udisks_state_start_cleanup (daemon->state);
462   udisks_state_check (daemon->state);
463 
464   if (G_OBJECT_CLASS (udisks_daemon_parent_class)->constructed != NULL)
465     G_OBJECT_CLASS (udisks_daemon_parent_class)->constructed (object);
466 }
467 
468 
469 static void
udisks_daemon_class_init(UDisksDaemonClass * klass)470 udisks_daemon_class_init (UDisksDaemonClass *klass)
471 {
472   GObjectClass *gobject_class;
473 
474   gobject_class = G_OBJECT_CLASS (klass);
475   gobject_class->finalize     = udisks_daemon_finalize;
476   gobject_class->constructed  = udisks_daemon_constructed;
477   gobject_class->set_property = udisks_daemon_set_property;
478   gobject_class->get_property = udisks_daemon_get_property;
479 
480   /**
481    * UDisksDaemon:connection:
482    *
483    * The #GDBusConnection the daemon is for.
484    */
485   g_object_class_install_property (gobject_class,
486                                    PROP_CONNECTION,
487                                    g_param_spec_object ("connection",
488                                                         "Connection",
489                                                         "The D-Bus connection the daemon is for",
490                                                         G_TYPE_DBUS_CONNECTION,
491                                                         G_PARAM_READABLE |
492                                                         G_PARAM_WRITABLE |
493                                                         G_PARAM_CONSTRUCT_ONLY |
494                                                         G_PARAM_STATIC_STRINGS));
495 
496   /**
497    * UDisksDaemon:object-manager:
498    *
499    * The #GDBusObjectManager used by the daemon
500    */
501   g_object_class_install_property (gobject_class,
502                                    PROP_OBJECT_MANAGER,
503                                    g_param_spec_object ("object-manager",
504                                                         "Object Manager",
505                                                         "The D-Bus Object Manager server used by the daemon",
506                                                         G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
507                                                         G_PARAM_READABLE |
508                                                         G_PARAM_STATIC_STRINGS));
509 
510   /**
511    * UDisksDaemon:mount-monitor:
512    *
513    * The #UDisksMountMonitor used by the daemon
514    */
515   g_object_class_install_property (gobject_class,
516                                    PROP_MOUNT_MONITOR,
517                                    g_param_spec_object ("mount-monitor",
518                                                         "Mount Monitor",
519                                                         "The mount monitor",
520                                                         UDISKS_TYPE_MOUNT_MONITOR,
521                                                         G_PARAM_READABLE |
522                                                         G_PARAM_STATIC_STRINGS));
523 
524   /**
525    * UDisksDaemon:disable-modules:
526    *
527    * Whether modules should be disabled
528    */
529   g_object_class_install_property (gobject_class,
530                                    PROP_DISABLE_MODULES,
531                                    g_param_spec_boolean ("disable-modules",
532                                                          "Disable modules",
533                                                          "Whether modules should be disabled",
534                                                          FALSE,
535                                                          G_PARAM_READABLE |
536                                                          G_PARAM_WRITABLE |
537                                                          G_PARAM_CONSTRUCT_ONLY));
538 
539   /**
540    * UDisksDaemon:force-load-modules:
541    *
542    * Whether modules should be activated upon startup
543    */
544   g_object_class_install_property (gobject_class,
545                                    PROP_FORCE_LOAD_MODULES,
546                                    g_param_spec_boolean ("force-load-modules",
547                                                          "Force load modules",
548                                                          "Whether modules should be activated upon startup",
549                                                          FALSE,
550                                                          G_PARAM_READABLE |
551                                                          G_PARAM_WRITABLE |
552                                                          G_PARAM_CONSTRUCT_ONLY));
553 
554   /**
555    * UDisksDaemon:uninstalled:
556    *
557    * Loads modules from the build directory.
558    */
559   g_object_class_install_property (gobject_class,
560                                    PROP_UNINSTALLED,
561                                    g_param_spec_boolean ("uninstalled",
562                                                          "Load modules from the build directory",
563                                                          "Whether the modules should be loaded from the build directory",
564                                                          FALSE,
565                                                          G_PARAM_READABLE |
566                                                          G_PARAM_WRITABLE |
567                                                          G_PARAM_CONSTRUCT_ONLY));
568 
569   /**
570    * UDisksDaemon:enable-tcrypt:
571    *
572    * Whether devices should be tested for being TCRYPT encrypted.
573    */
574   g_object_class_install_property (gobject_class,
575                                    PROP_ENABLE_TCRYPT,
576                                    g_param_spec_boolean ("enable-tcrypt",
577                                                          "Enable TCRYPT",
578                                                          "Whether devices should be tested for being TCRYPT encrypted",
579                                                          FALSE,
580                                                          G_PARAM_READABLE |
581                                                          G_PARAM_WRITABLE |
582                                                          G_PARAM_CONSTRUCT_ONLY));
583 
584   /**
585    * UDisksDaemon:uuid:
586    *
587    * The UUID specific for this daemon instance.
588    */
589   g_object_class_install_property (gobject_class,
590                                    PROP_UUID,
591                                    g_param_spec_string ("uuid",
592                                                         "Daemon UUID",
593                                                         "The UUID specific for this daemon instance",
594                                                          NULL,
595                                                          G_PARAM_READABLE |
596                                                          G_PARAM_WRITABLE));
597 }
598 
599 /**
600  * udisks_daemon_new:
601  * @connection: A #GDBusConnection.
602  * @disable_modules: Indicates whether modules should never be activated.
603  * @force_load_modules: Activate modules on startup (for debugging purposes).
604  * @uninstalled: Loads modules from the build directory (for debugging purposes).
605  * @enable_tcrypt: Checks whether devices could be TCRYPT encrypted.
606  *
607  * Create a new daemon object for exporting objects on @connection.
608  *
609  * Returns: A #UDisksDaemon object. Free with g_object_unref().
610  */
611 UDisksDaemon *
udisks_daemon_new(GDBusConnection * connection,gboolean disable_modules,gboolean force_load_modules,gboolean uninstalled,gboolean enable_tcrypt)612 udisks_daemon_new (GDBusConnection *connection,
613                    gboolean         disable_modules,
614                    gboolean         force_load_modules,
615                    gboolean         uninstalled,
616                    gboolean         enable_tcrypt)
617 {
618   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
619   return UDISKS_DAEMON (g_object_new (UDISKS_TYPE_DAEMON,
620                                       "connection", connection,
621                                       "disable-modules", disable_modules,
622                                       "force-load-modules", force_load_modules,
623                                       "uninstalled", uninstalled,
624                                       "enable-tcrypt", enable_tcrypt,
625                                       NULL));
626 }
627 
628 /**
629  * udisks_daemon_get_connection:
630  * @daemon: A #UDisksDaemon.
631  *
632  * Gets the D-Bus connection used by @daemon.
633  *
634  * Returns: A #GDBusConnection. Do not free, the object is owned by @daemon.
635  */
636 GDBusConnection *
udisks_daemon_get_connection(UDisksDaemon * daemon)637 udisks_daemon_get_connection (UDisksDaemon *daemon)
638 {
639   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
640   return daemon->connection;
641 }
642 
643 /**
644  * udisks_daemon_get_object_manager:
645  * @daemon: A #UDisksDaemon.
646  *
647  * Gets the D-Bus object manager used by @daemon.
648  *
649  * Returns: A #GDBusObjectManagerServer. Do not free, the object is owned by @daemon.
650  */
651 GDBusObjectManagerServer *
udisks_daemon_get_object_manager(UDisksDaemon * daemon)652 udisks_daemon_get_object_manager (UDisksDaemon *daemon)
653 {
654   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
655   return daemon->object_manager;
656 }
657 
658 /**
659  * udisks_daemon_get_mount_monitor:
660  * @daemon: A #UDisksDaemon
661  *
662  * Gets the mount monitor used by @daemon.
663  *
664  * Returns: A #UDisksMountMonitor. Do not free, the object is owned by @daemon.
665  */
666 UDisksMountMonitor *
udisks_daemon_get_mount_monitor(UDisksDaemon * daemon)667 udisks_daemon_get_mount_monitor (UDisksDaemon *daemon)
668 {
669   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
670   return daemon->mount_monitor;
671 }
672 
673 /**
674  * udisks_daemon_get_crypttab_monitor:
675  * @daemon: A #UDisksDaemon
676  *
677  * Gets the crypttab monitor used by @daemon.
678  *
679  * Returns: A #UDisksCrypttabMonitor. Do not free, the object is owned by @daemon.
680  */
681 UDisksCrypttabMonitor *
udisks_daemon_get_crypttab_monitor(UDisksDaemon * daemon)682 udisks_daemon_get_crypttab_monitor (UDisksDaemon *daemon)
683 {
684   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
685   return daemon->crypttab_monitor;
686 }
687 
688 #ifdef HAVE_LIBMOUNT_UTAB
689 /**
690  * udisks_daemon_get_utab_monitor:
691  * @daemon: A #UDisksDaemon
692  *
693  * Gets the utab monitor used by @daemon.
694  *
695  * Returns: A #UDisksUtabMonitor. Do not free, the object is owned by @daemon.
696  */
697 UDisksUtabMonitor *
udisks_daemon_get_utab_monitor(UDisksDaemon * daemon)698 udisks_daemon_get_utab_monitor (UDisksDaemon *daemon)
699 {
700   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
701   return daemon->utab_monitor;
702 }
703 #endif
704 
705 /**
706  * udisks_daemon_get_linux_provider:
707  * @daemon: A #UDisksDaemon.
708  *
709  * Gets the Linux Provider, if any.
710  *
711  * Returns: A #UDisksLinuxProvider or %NULL. Do not free, the object is owned by @daemon.
712  */
713 UDisksLinuxProvider *
udisks_daemon_get_linux_provider(UDisksDaemon * daemon)714 udisks_daemon_get_linux_provider (UDisksDaemon *daemon)
715 {
716   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
717   return daemon->linux_provider;
718 }
719 
720 /**
721  * udisks_daemon_get_authority:
722  * @daemon: A #UDisksDaemon.
723  *
724  * Gets the PolicyKit authority used by @daemon.
725  *
726  * Returns: A #PolkitAuthority instance or %NULL if the polkit
727  * authority is not available. Do not free, the object is owned by
728  * @daemon.
729  */
730 PolkitAuthority *
udisks_daemon_get_authority(UDisksDaemon * daemon)731 udisks_daemon_get_authority (UDisksDaemon *daemon)
732 {
733   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
734   return daemon->authority;
735 }
736 
737 /**
738  * udisks_daemon_get_state:
739  * @daemon: A #UDisksDaemon.
740  *
741  * Gets the state object used by @daemon.
742  *
743  * Returns: A #UDisksState instance. Do not free, the object is owned by @daemon.
744  */
745 UDisksState *
udisks_daemon_get_state(UDisksDaemon * daemon)746 udisks_daemon_get_state (UDisksDaemon *daemon)
747 {
748   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
749   return daemon->state;
750 }
751 
752 /* ---------------------------------------------------------------------------------------------------- */
753 
754 typedef struct
755 {
756   UDisksDaemon *daemon;
757   UDisksInhibitCookie *inhibit_cookie;
758 } JobData;
759 
760 static void
free_job_data(JobData * job_data)761 free_job_data (JobData *job_data)
762 {
763   if (job_data->daemon != NULL)
764     g_object_unref (job_data->daemon);
765   g_free (job_data);
766 }
767 
768 static void
on_job_completed(UDisksJob * job,gboolean success,const gchar * message,gpointer user_data)769 on_job_completed (UDisksJob    *job,
770                   gboolean      success,
771                   const gchar  *message,
772                   gpointer      user_data)
773 {
774   JobData *job_data = (JobData *) user_data;
775   UDisksDaemon *daemon = UDISKS_DAEMON (job_data->daemon);
776   UDisksObjectSkeleton *object;
777 
778   object = UDISKS_OBJECT_SKELETON (g_dbus_interface_get_object (G_DBUS_INTERFACE (job)));
779   g_assert (object != NULL);
780 
781   /* Unexport job */
782   g_dbus_object_manager_server_unexport (daemon->object_manager,
783                                          g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
784   g_object_unref (object);
785 
786   /* free the allocated job object */
787   g_object_unref (job);
788 
789   /* unregister inhibitor from systemd logind */
790   udisks_daemon_util_uninhibit_system_sync (job_data->inhibit_cookie);
791   /* returns the reference we took when connecting to the
792    * UDisksJob::completed signal in udisks_daemon_launch_{spawned,threaded}_job()
793    * below
794    */
795   free_job_data (job_data);
796 }
797 
798 /* ---------------------------------------------------------------------------------------------------- */
799 
800 static guint job_id = 0;
801 
802 /* ---------------------------------------------------------------------------------------------------- */
803 
804 static UDisksBaseJob *
common_job(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,gpointer job)805 common_job (UDisksDaemon    *daemon,
806             UDisksObject    *object,
807             const gchar     *job_operation,
808             uid_t            job_started_by_uid,
809             gpointer         job)
810 {
811   gchar *job_object_path;
812   UDisksObjectSkeleton *job_object;
813   JobData *job_data;
814   gchar *operation_description;
815 
816   job_data = g_new0 (JobData, 1);
817   job_data->daemon = g_object_ref (daemon);
818   /* register inhibitor to systemd logind while job is running */
819   operation_description = udisks_client_get_job_description_from_operation (job_operation);
820   job_data->inhibit_cookie = udisks_daemon_util_inhibit_system_sync (operation_description);
821   g_free (operation_description);
822 
823   if (object != NULL)
824     udisks_base_job_add_object (UDISKS_BASE_JOB (job), object);
825 
826   job_object_path = g_strdup_printf ("/org/freedesktop/UDisks2/jobs/%u", g_atomic_int_add (&job_id, 1));
827   job_object = udisks_object_skeleton_new (job_object_path);
828   udisks_object_skeleton_set_job (job_object, UDISKS_JOB (job));
829   g_free (job_object_path);
830 
831   udisks_job_set_cancelable (UDISKS_JOB (job), TRUE);
832   udisks_job_set_operation (UDISKS_JOB (job), job_operation);
833   udisks_job_set_started_by_uid (UDISKS_JOB (job), job_started_by_uid);
834 
835   g_dbus_object_manager_server_export (daemon->object_manager, G_DBUS_OBJECT_SKELETON (job_object));
836   g_signal_connect_after (job,
837                           "completed",
838                           G_CALLBACK (on_job_completed),
839                           job_data);
840 
841   return UDISKS_BASE_JOB (job);
842 }
843 
844 /**
845  * udisks_daemon_launch_simple_job:
846  * @daemon: A #UDisksDaemon.
847  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
848  * @job_operation: The operation for the job.
849  * @job_started_by_uid: The user who started the job.
850  * @cancellable: A #GCancellable or %NULL.
851  *
852  * Launches a new simple job.
853  *
854  * The returned object will be exported on the bus until the
855  * #UDisksJob::completed signal is emitted on the object. It is not
856  * valid to use the returned object after this signal fires.
857  *
858  * Returns: A #UDisksSimpleJob object. Do not free, the object
859  * belongs to @manager.
860  */
861 UDisksBaseJob *
udisks_daemon_launch_simple_job(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,GCancellable * cancellable)862 udisks_daemon_launch_simple_job (UDisksDaemon    *daemon,
863                                  UDisksObject    *object,
864                                  const gchar     *job_operation,
865                                  uid_t            job_started_by_uid,
866                                  GCancellable    *cancellable)
867 {
868   UDisksSimpleJob *job;
869 
870   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
871 
872   job = udisks_simple_job_new (daemon, cancellable);
873   return common_job (daemon, object, job_operation, job_started_by_uid, job);
874 }
875 
876 /* ---------------------------------------------------------------------------------------------------- */
877 
878 /**
879  * udisks_daemon_launch_threaded_job:
880  * @daemon: A #UDisksDaemon.
881  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
882  * @job_operation: The operation for the job.
883  * @job_started_by_uid: The user who started the job.
884  * @job_func: The function to run in another thread.
885  * @user_data: User data to pass to @job_func.
886  * @user_data_free_func: Function to free @user_data with or %NULL.
887  * @cancellable: A #GCancellable or %NULL.
888  *
889  * Launches a new job by running @job_func in a new dedicated thread.
890  *
891  * The job is not started automatically! Use udisks_threaded_job_start() to
892  * start the job after #UDisksThreadedJob::threaded-job-completed or
893  * #UDisksJob::completed signals are connected (to get notified when the job is
894  * done). This is to prevent a race condition with the @job_func finishing
895  * before the signals are connected in which case the signal handlers are never
896  * triggered.
897  *
898  * Long-running jobs should periodically check @cancellable to see if
899  * they have been cancelled.
900  *
901  * The returned object will be exported on the bus until the
902  * #UDisksJob::completed signal is emitted on the object. It is not
903  * valid to use the returned object after this signal fires.
904  *
905  * Returns: A #UDisksThreadedJob object. Do not free, the object
906  * belongs to @manager.
907  */
908 UDisksBaseJob *
udisks_daemon_launch_threaded_job(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,UDisksThreadedJobFunc job_func,gpointer user_data,GDestroyNotify user_data_free_func,GCancellable * cancellable)909 udisks_daemon_launch_threaded_job  (UDisksDaemon          *daemon,
910                                     UDisksObject          *object,
911                                     const gchar           *job_operation,
912                                     uid_t                  job_started_by_uid,
913                                     UDisksThreadedJobFunc  job_func,
914                                     gpointer               user_data,
915                                     GDestroyNotify         user_data_free_func,
916                                     GCancellable          *cancellable)
917 {
918   UDisksThreadedJob *job;
919 
920   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
921   g_return_val_if_fail (job_func != NULL, NULL);
922 
923   job = udisks_threaded_job_new (job_func,
924                                  user_data,
925                                  user_data_free_func,
926                                  daemon,
927                                  cancellable);
928   return common_job (daemon, object, job_operation, job_started_by_uid, job);
929 }
930 
931 /* ---------------------------------------------------------------------------------------------------- */
932 
933 /**
934  * udisks_daemon_launch_spawned_job:
935  * @daemon: A #UDisksDaemon.
936  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
937  * @job_operation: The operation for the job.
938  * @job_started_by_uid: The user who started the job.
939  * @cancellable: A #GCancellable or %NULL.
940  * @run_as_uid: The #uid_t to run the command as.
941  * @run_as_euid: The effective #uid_t to run the command as.
942  * @input_string: A string to write to stdin of the spawned program or %NULL.
943  * @command_line_format: printf()-style format for the command line to spawn.
944  * @...: Arguments for @command_line_format.
945  *
946  * Launches a new job for @command_line_format.
947  *
948  * The job is not started automatically! Use udisks_spawned_job_start() to start
949  * the job after #UDisksSpawnedJob::spawned-job-completed or
950  * #UDisksJob::completed signals are connected (to get notified when the job is
951  * done). This is to prevent a race condition with the spawned process
952  * terminating before the signals are connected in which case the signal
953  * handlers are never triggered.
954  *
955  * The returned object will be exported on the bus until the
956  * #UDisksJob::completed signal is emitted on the object. It is not
957  * valid to use the returned object after this signal fires.
958  *
959  * Returns: A #UDisksSpawnedJob object. Do not free, the object
960  * belongs to @manager.
961  */
962 UDisksBaseJob *
udisks_daemon_launch_spawned_job(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,GCancellable * cancellable,uid_t run_as_uid,uid_t run_as_euid,const gchar * input_string,const gchar * command_line_format,...)963 udisks_daemon_launch_spawned_job (UDisksDaemon    *daemon,
964                                   UDisksObject    *object,
965                                   const gchar     *job_operation,
966                                   uid_t            job_started_by_uid,
967                                   GCancellable    *cancellable,
968                                   uid_t            run_as_uid,
969                                   uid_t            run_as_euid,
970                                   const gchar     *input_string,
971                                   const gchar     *command_line_format,
972                                   ...)
973 {
974   va_list var_args;
975   gchar *command_line;
976   GString *input_string_as_gstring = NULL;
977   UDisksBaseJob *job;
978 
979   if (input_string != NULL)
980     input_string_as_gstring = g_string_new (input_string);
981 
982   va_start (var_args, command_line_format);
983   command_line = g_strdup_vprintf (command_line_format, var_args);
984   va_end (var_args);
985 
986   job = udisks_daemon_launch_spawned_job_gstring (daemon,
987                                           object,
988                                           job_operation,
989                                           job_started_by_uid,
990                                           cancellable,
991                                           run_as_uid,
992                                           run_as_euid,
993                                           input_string_as_gstring,
994                                           "%s",
995                                           command_line);
996 
997   udisks_string_wipe_and_free (input_string_as_gstring);
998   g_free (command_line);
999   return job;
1000 }
1001 
1002 /**
1003  * udisks_daemon_launch_spawned_job_gstring:
1004  * @daemon: A #UDisksDaemon.
1005  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
1006  * @job_operation: The operation for the job.
1007  * @job_started_by_uid: The user who started the job.
1008  * @cancellable: A #GCancellable or %NULL.
1009  * @run_as_uid: The #uid_t to run the command as.
1010  * @run_as_euid: The effective #uid_t to run the command as.
1011  * @input_string: A string to write to stdin of the spawned program or %NULL.
1012  * @command_line_format: printf()-style format for the command line to spawn.
1013  * @...: Arguments for @command_line_format.
1014  *
1015  * Launches a new job for @command_line_format.
1016  *
1017  * The job is not started automatically! Use udisks_spawned_job_start() to start
1018  * the job after #UDisksSpawnedJob::spawned-job-completed or
1019  * #UDisksJob::completed signals are connected (to get notified when the job is
1020  * done). This is to prevent a race condition with the spawned process
1021  * terminating before the signals are connected in which case the signal
1022  * handlers are never triggered.
1023  *
1024  * The returned object will be exported on the bus until the
1025  * #UDisksJob::completed signal is emitted on the object. It is not
1026  * valid to use the returned object after this signal fires.
1027  *
1028  * This function is the same as udisks_daemon_launch_spawned_job, with
1029  * the only difference that it takes a GString and is therefore able to
1030  * handle binary inputs that contain '\0' bytes.
1031  *
1032  * Returns: A #UDisksSpawnedJob object. Do not free, the object
1033  * belongs to @manager.
1034  */
1035 UDisksBaseJob *
udisks_daemon_launch_spawned_job_gstring(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,GCancellable * cancellable,uid_t run_as_uid,uid_t run_as_euid,GString * input_string,const gchar * command_line_format,...)1036 udisks_daemon_launch_spawned_job_gstring (
1037                                   UDisksDaemon    *daemon,
1038                                   UDisksObject    *object,
1039                                   const gchar     *job_operation,
1040                                   uid_t            job_started_by_uid,
1041                                   GCancellable    *cancellable,
1042                                   uid_t            run_as_uid,
1043                                   uid_t            run_as_euid,
1044                                   GString         *input_string,
1045                                   const gchar     *command_line_format,
1046                                   ...)
1047 {
1048   va_list var_args;
1049   gchar *command_line;
1050   UDisksSpawnedJob *job;
1051 
1052   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
1053   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1054   g_return_val_if_fail (command_line_format != NULL, NULL);
1055 
1056   va_start (var_args, command_line_format);
1057   command_line = g_strdup_vprintf (command_line_format, var_args);
1058   va_end (var_args);
1059   job = udisks_spawned_job_new (command_line, input_string, run_as_uid, run_as_euid, daemon, cancellable);
1060   g_free (command_line);
1061 
1062   return common_job (daemon, object, job_operation, job_started_by_uid, job);
1063 }
1064 
1065 /* ---------------------------------------------------------------------------------------------------- */
1066 
1067 typedef struct
1068 {
1069   GMainContext *context;
1070   GMainLoop *loop;
1071   gboolean success;
1072   gint status;
1073   gchar *message;
1074 } SpawnedJobSyncData;
1075 
1076 static gboolean
spawned_job_sync_on_spawned_job_completed(UDisksSpawnedJob * job,GError * error,gint status,GString * standard_output,GString * standard_error,gpointer user_data)1077 spawned_job_sync_on_spawned_job_completed (UDisksSpawnedJob *job,
1078                                            GError           *error,
1079                                            gint              status,
1080                                            GString          *standard_output,
1081                                            GString          *standard_error,
1082                                            gpointer          user_data)
1083 {
1084   SpawnedJobSyncData *data = user_data;
1085   data->status = status;
1086   return FALSE; /* let other handlers run */
1087 }
1088 
1089 static void
spawned_job_sync_on_completed(UDisksJob * job,gboolean success,const gchar * message,gpointer user_data)1090 spawned_job_sync_on_completed (UDisksJob    *job,
1091                                gboolean      success,
1092                                const gchar  *message,
1093                                gpointer      user_data)
1094 {
1095   SpawnedJobSyncData *data = user_data;
1096   data->success = success;
1097   data->message = g_strdup (message);
1098   g_main_loop_quit (data->loop);
1099 }
1100 
1101 /**
1102  * udisks_daemon_launch_spawned_job_sync:
1103  * @daemon: A #UDisksDaemon.
1104  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
1105  * @job_operation: The operation for the job.
1106  * @job_started_by_uid: The user who started the job.
1107  * @cancellable: A #GCancellable or %NULL.
1108  * @run_as_uid: The #uid_t to run the command as.
1109  * @run_as_euid: The effective #uid_t to run the command as.
1110  * @input_string: A string to write to stdin of the spawned program or %NULL.
1111  * @out_status: Return location for the @status parameter of the #UDisksSpawnedJob::spawned-job-completed signal.
1112  * @out_message: Return location for the @message parameter of the #UDisksJob::completed signal.
1113  * @command_line_format: printf()-style format for the command line to spawn.
1114  * @...: Arguments for @command_line_format.
1115  *
1116  * Like udisks_daemon_launch_spawned_job() but blocks the calling
1117  * thread until the job completes.
1118  *
1119  * Returns: The @success parameter of the #UDisksJob::completed signal.
1120  */
1121 gboolean
udisks_daemon_launch_spawned_job_sync(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,GCancellable * cancellable,uid_t run_as_uid,uid_t run_as_euid,gint * out_status,gchar ** out_message,const gchar * input_string,const gchar * command_line_format,...)1122 udisks_daemon_launch_spawned_job_sync (UDisksDaemon    *daemon,
1123                                        UDisksObject    *object,
1124                                        const gchar     *job_operation,
1125                                        uid_t            job_started_by_uid,
1126                                        GCancellable    *cancellable,
1127                                        uid_t            run_as_uid,
1128                                        uid_t            run_as_euid,
1129                                        gint            *out_status,
1130                                        gchar          **out_message,
1131                                        const gchar     *input_string,
1132                                        const gchar     *command_line_format,
1133                                        ...)
1134 {
1135   va_list var_args;
1136   gchar *command_line;
1137   GString *input_string_as_gstring = NULL;
1138   gboolean ret;
1139 
1140   if (input_string != NULL)
1141     input_string_as_gstring = g_string_new (input_string);
1142 
1143   va_start (var_args, command_line_format);
1144   command_line = g_strdup_vprintf (command_line_format, var_args);
1145   va_end (var_args);
1146 
1147   ret = udisks_daemon_launch_spawned_job_gstring_sync (daemon,
1148                                           object,
1149                                           job_operation,
1150                                           job_started_by_uid,
1151                                           cancellable,
1152                                           run_as_uid,
1153                                           run_as_euid,
1154                                           out_status,
1155                                           out_message,
1156                                           input_string_as_gstring,
1157                                           "%s",
1158                                           command_line);
1159 
1160   udisks_string_wipe_and_free (input_string_as_gstring);
1161   g_free (command_line);
1162   return ret;
1163 }
1164 
1165 /**
1166  * udisks_daemon_launch_spawned_job_gstring_sync:
1167  * @daemon: A #UDisksDaemon.
1168  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
1169  * @job_operation: The operation for the job.
1170  * @job_started_by_uid: The user who started the job.
1171  * @cancellable: A #GCancellable or %NULL.
1172  * @run_as_uid: The #uid_t to run the command as.
1173  * @run_as_euid: The effective #uid_t to run the command as.
1174  * @input_string: A string to write to stdin of the spawned program or %NULL.
1175  * @out_status: Return location for the @status parameter of the #UDisksSpawnedJob::spawned-job-completed signal.
1176  * @out_message: Return location for the @message parameter of the #UDisksJob::completed signal.
1177  * @command_line_format: printf()-style format for the command line to spawn.
1178  * @...: Arguments for @command_line_format.
1179  *
1180  * Like udisks_daemon_launch_spawned_job() but blocks the calling
1181  * thread until the job completes.
1182  *
1183  * This function is the same as udisks_daemon_launch_spawned_job_sync, with
1184  * the only difference that it takes a GString and is therefore able to
1185  * handle binary inputs that contain '\0' bytes.
1186  *
1187  * Returns: The @success parameter of the #UDisksJob::completed signal.
1188  */
1189 gboolean
udisks_daemon_launch_spawned_job_gstring_sync(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,GCancellable * cancellable,uid_t run_as_uid,uid_t run_as_euid,gint * out_status,gchar ** out_message,GString * input_string,const gchar * command_line_format,...)1190 udisks_daemon_launch_spawned_job_gstring_sync (UDisksDaemon    *daemon,
1191                                        UDisksObject    *object,
1192                                        const gchar     *job_operation,
1193                                        uid_t            job_started_by_uid,
1194                                        GCancellable    *cancellable,
1195                                        uid_t            run_as_uid,
1196                                        uid_t            run_as_euid,
1197                                        gint            *out_status,
1198                                        gchar          **out_message,
1199                                        GString         *input_string,
1200                                        const gchar     *command_line_format,
1201                                        ...)
1202 {
1203   va_list var_args;
1204   gchar *command_line;
1205   UDisksBaseJob *job;
1206   SpawnedJobSyncData data;
1207 
1208   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), FALSE);
1209   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1210   g_return_val_if_fail (command_line_format != NULL, FALSE);
1211 
1212   data.context = g_main_context_new ();
1213   g_main_context_push_thread_default (data.context);
1214   data.loop = g_main_loop_new (data.context, FALSE);
1215   data.success = FALSE;
1216   data.status = 0;
1217   data.message = NULL;
1218 
1219   va_start (var_args, command_line_format);
1220   command_line = g_strdup_vprintf (command_line_format, var_args);
1221   va_end (var_args);
1222   job = udisks_daemon_launch_spawned_job_gstring (daemon,
1223                                           object,
1224                                           job_operation,
1225                                           job_started_by_uid,
1226                                           cancellable,
1227                                           run_as_uid,
1228                                           run_as_euid,
1229                                           input_string,
1230                                           "%s",
1231                                           command_line);
1232   g_signal_connect (job,
1233                     "spawned-job-completed",
1234                     G_CALLBACK (spawned_job_sync_on_spawned_job_completed),
1235                     &data);
1236   g_signal_connect_after (job,
1237                           "completed",
1238                           G_CALLBACK (spawned_job_sync_on_completed),
1239                           &data);
1240 
1241   udisks_spawned_job_start (UDISKS_SPAWNED_JOB (job));
1242   g_main_loop_run (data.loop);
1243 
1244   if (out_status != NULL)
1245     *out_status = data.status;
1246 
1247   if (out_message != NULL)
1248     *out_message = data.message;
1249   else
1250     g_free (data.message);
1251 
1252   g_free (command_line);
1253   g_main_loop_unref (data.loop);
1254   g_main_context_pop_thread_default (data.context);
1255   g_main_context_unref (data.context);
1256 
1257   /* note: the job object is freed in the ::completed handler */
1258 
1259   return data.success;
1260 }
1261 
1262 /* ---------------------------------------------------------------------------------------------------- */
1263 
1264 static __thread UDisksJob *thread_job = NULL;
1265 
1266 static void
bd_thread_progress_callback(guint64 task_id,BDUtilsProgStatus status,guint8 completion,gchar * msg)1267 bd_thread_progress_callback (guint64            task_id,
1268                              BDUtilsProgStatus  status,
1269                              guint8             completion,
1270                              gchar             *msg)
1271 {
1272   if (thread_job != NULL && msg == NULL)
1273     {
1274       if (!udisks_job_get_progress_valid (UDISKS_JOB (thread_job)))
1275         {
1276           udisks_job_set_progress_valid (UDISKS_JOB (thread_job), TRUE);
1277         }
1278 
1279       udisks_job_set_progress (UDISKS_JOB (thread_job), completion / 100.0);
1280     }
1281 }
1282 
1283 void
udisks_bd_thread_set_progress_for_job(UDisksJob * job)1284 udisks_bd_thread_set_progress_for_job (UDisksJob *job)
1285 {
1286   thread_job = job;
1287   bd_utils_init_prog_reporting_thread (bd_thread_progress_callback, NULL);
1288 }
1289 
1290 void
udisks_bd_thread_disable_progress(void)1291 udisks_bd_thread_disable_progress (void)
1292 {
1293   thread_job = NULL;
1294   bd_utils_init_prog_reporting_thread (NULL, NULL);
1295 }
1296 
1297 /* ---------------------------------------------------------------------------------------------------- */
1298 
1299 /**
1300  * udisks_daemon_launch_threaded_job_sync:
1301  * @daemon: A #UDisksDaemon.
1302  * @object: (allow-none): A #UDisksObject to add to the job or %NULL.
1303  * @job_operation: The operation for the job.
1304  * @job_started_by_uid: The user who started the job.
1305  * @job_func: The function to run in another thread.
1306  * @user_data: User data to pass to @job_func.
1307  * @user_data_free_func: Function to free @user_data with or %NULL.
1308  * @cancellable: A #GCancellable or %NULL.
1309  * @error: The #GError set by the #UDisksThreadedJobFunc.
1310  *
1311  * Like udisks_daemon_launch_threaded_job() but blocks the calling
1312  * thread until the job completes.
1313  *
1314  * Returns: The @success parameter of the #UDisksJob::completed signal.
1315  */
1316 gboolean
udisks_daemon_launch_threaded_job_sync(UDisksDaemon * daemon,UDisksObject * object,const gchar * job_operation,uid_t job_started_by_uid,UDisksThreadedJobFunc job_func,gpointer user_data,GDestroyNotify user_data_free_func,GCancellable * cancellable,GError ** error)1317 udisks_daemon_launch_threaded_job_sync (UDisksDaemon          *daemon,
1318                                         UDisksObject          *object,
1319                                         const gchar           *job_operation,
1320                                         uid_t                  job_started_by_uid,
1321                                         UDisksThreadedJobFunc  job_func,
1322                                         gpointer               user_data,
1323                                         GDestroyNotify         user_data_free_func,
1324                                         GCancellable          *cancellable,
1325                                         GError               **error)
1326 {
1327   UDisksBaseJob *job;
1328   gboolean job_result;
1329 
1330   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), FALSE);
1331   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1332 
1333   job = udisks_daemon_launch_threaded_job (daemon,
1334                                            object,
1335                                            job_operation,
1336                                            job_started_by_uid,
1337                                            job_func,
1338                                            user_data,
1339                                            user_data_free_func,
1340                                            cancellable);
1341 
1342   /* TODO: There might not be much difference between calling the job_func() right away
1343    *       instead of having it enclosed in a GTask since we're blocking anyway.
1344    *       Deeper investigation of differences required. */
1345   job_result = udisks_threaded_job_run_sync (UDISKS_THREADED_JOB (job), error);
1346 
1347   /* note: the job object is freed in the ::completed handler */
1348   return job_result;
1349 }
1350 
1351 /* ---------------------------------------------------------------------------------------------------- */
1352 
1353 typedef struct {
1354   GMainContext *context;
1355   GMainLoop *loop;
1356   gboolean timed_out;
1357 } WaitData;
1358 
1359 static gboolean
wait_on_timed_out(gpointer user_data)1360 wait_on_timed_out (gpointer user_data)
1361 {
1362   WaitData *data = user_data;
1363   data->timed_out = TRUE;
1364   g_main_loop_quit (data->loop);
1365   return FALSE; /* remove the source */
1366 }
1367 
1368 static gboolean
wait_on_recheck(gpointer user_data)1369 wait_on_recheck (gpointer user_data)
1370 {
1371   WaitData *data = user_data;
1372   g_main_loop_quit (data->loop);
1373   return FALSE; /* remove the source */
1374 }
1375 
wait_for_objects(UDisksDaemon * daemon,UDisksDaemonWaitFuncGeneric wait_func,gpointer user_data,GDestroyNotify user_data_free_func,guint timeout_seconds,gboolean to_disappear,GError ** error)1376 static gpointer wait_for_objects (UDisksDaemon                *daemon,
1377                                   UDisksDaemonWaitFuncGeneric  wait_func,
1378                                   gpointer                     user_data,
1379                                   GDestroyNotify               user_data_free_func,
1380                                   guint                        timeout_seconds,
1381                                   gboolean                     to_disappear,
1382                                   GError                     **error)
1383 {
1384   gpointer ret;
1385   WaitData data;
1386 
1387   /* TODO: support GCancellable */
1388 
1389   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
1390   g_return_val_if_fail (wait_func != NULL, NULL);
1391 
1392   ret = NULL;
1393 
1394   memset (&data, '\0', sizeof (data));
1395   data.context = NULL;
1396   data.loop = NULL;
1397 
1398   g_object_ref (daemon);
1399 
1400  again:
1401   ret = wait_func (daemon, user_data);
1402 
1403   if ((!to_disappear && ret == NULL && timeout_seconds > 0) ||
1404       (to_disappear && ret != NULL && timeout_seconds > 0))
1405     {
1406       GSource *source;
1407 
1408       /* sit and wait for up to @timeout_seconds if the object isn't there already */
1409       if (data.context == NULL)
1410         {
1411           /* TODO: this will deadlock if we are calling from the main thread... */
1412           data.context = g_main_context_new ();
1413           data.loop = g_main_loop_new (data.context, FALSE);
1414 
1415           source = g_timeout_source_new_seconds (timeout_seconds);
1416           g_source_set_priority (source, G_PRIORITY_DEFAULT);
1417           g_source_set_callback (source, wait_on_timed_out, &data, NULL);
1418           g_source_attach (source, data.context);
1419           g_source_unref (source);
1420         }
1421 
1422       /* TODO: do something a bit more elegant than checking every 250ms ... it's
1423        *       probably going to involve having each UDisksProvider emit a "changed"
1424        *       signal when it's time to recheck... for now this works.
1425        */
1426       source = g_timeout_source_new (250);
1427       g_source_set_priority (source, G_PRIORITY_DEFAULT);
1428       g_source_set_callback (source, wait_on_recheck, &data, NULL);
1429       g_source_attach (source, data.context);
1430       g_source_unref (source);
1431 
1432       g_main_loop_run (data.loop);
1433 
1434       if (data.timed_out)
1435         {
1436           if (to_disappear)
1437             g_set_error (error,
1438                          UDISKS_ERROR, UDISKS_ERROR_FAILED,
1439                          "Timed out waiting");
1440           else
1441             g_set_error (error,
1442                          UDISKS_ERROR, UDISKS_ERROR_FAILED,
1443                          "Timed out waiting for object");
1444         }
1445       else
1446         {
1447           if (to_disappear)
1448             g_object_unref (G_OBJECT (ret));
1449           goto again;
1450         }
1451     }
1452 
1453   if (user_data_free_func != NULL)
1454     user_data_free_func (user_data);
1455 
1456   g_object_unref (daemon);
1457 
1458   if (data.loop != NULL)
1459     g_main_loop_unref (data.loop);
1460   if (data.context != NULL)
1461     g_main_context_unref (data.context);
1462 
1463   return ret;
1464 }
1465 
1466 
1467 /**
1468  * udisks_daemon_wait_for_object_sync:
1469  * @daemon: A #UDisksDaemon.
1470  * @wait_func: Function to check for desired object.
1471  * @user_data: User data to pass to @wait_func.
1472  * @user_data_free_func: (allow-none): Function to free @user_data or %NULL.
1473  * @timeout_seconds: Maximum time to wait for the object (in seconds) or 0 to never wait.
1474  * @error: (allow-none): Return location for error or %NULL.
1475  *
1476  * Blocks the calling thread until an object picked by @wait_func is
1477  * available or until @timeout_seconds has passed (in which case the
1478  * function fails with %UDISKS_ERROR_TIMED_OUT).
1479  *
1480  * Note that @wait_func will be called from time to time - for example
1481  * if there is a device event.
1482  *
1483  * Returns: (transfer full): The object picked by @wait_func or %NULL if @error is set.
1484  */
1485 UDisksObject *
udisks_daemon_wait_for_object_sync(UDisksDaemon * daemon,UDisksDaemonWaitFuncObject wait_func,gpointer user_data,GDestroyNotify user_data_free_func,guint timeout_seconds,GError ** error)1486 udisks_daemon_wait_for_object_sync (UDisksDaemon               *daemon,
1487                                     UDisksDaemonWaitFuncObject  wait_func,
1488                                     gpointer                    user_data,
1489                                     GDestroyNotify              user_data_free_func,
1490                                     guint                       timeout_seconds,
1491                                     GError                      **error)
1492 {
1493   return (UDisksObject *) wait_for_objects (daemon,
1494                                             (UDisksDaemonWaitFuncGeneric) wait_func,
1495                                             user_data,
1496                                             user_data_free_func,
1497                                             timeout_seconds,
1498                                             FALSE, /* to_disappear */
1499                                             error);
1500 }
1501 
1502 /**
1503  * udisks_daemon_wait_for_objects_sync:
1504  * @daemon: A #UDisksDaemon.
1505  * @wait_func: Function to check for desired object.
1506  * @user_data: User data to pass to @wait_func.
1507  * @user_data_free_func: (allow-none): Function to free @user_data or %NULL.
1508  * @timeout_seconds: Maximum time to wait for the object (in seconds) or 0 to never wait.
1509  * @error: (allow-none): Return location for error or %NULL.
1510  *
1511  * Blocks the calling thread until one or more objects picked by @wait_func
1512  * is/are available or until @timeout_seconds has passed (in which case the
1513  * function fails with %UDISKS_ERROR_TIMED_OUT).
1514  *
1515  * Note that @wait_func will be called from time to time - for example
1516  * if there is a device event.
1517  *
1518  * Returns: (transfer full): The objects picked by @wait_func or %NULL if @error is set.
1519  */
1520 UDisksObject **
udisks_daemon_wait_for_objects_sync(UDisksDaemon * daemon,UDisksDaemonWaitFuncObjects wait_func,gpointer user_data,GDestroyNotify user_data_free_func,guint timeout_seconds,GError ** error)1521 udisks_daemon_wait_for_objects_sync (UDisksDaemon                 *daemon,
1522                                      UDisksDaemonWaitFuncObjects   wait_func,
1523                                      gpointer                      user_data,
1524                                      GDestroyNotify                user_data_free_func,
1525                                      guint                         timeout_seconds,
1526                                      GError                      **error)
1527 {
1528   return (UDisksObject **) wait_for_objects (daemon,
1529                                              (UDisksDaemonWaitFuncGeneric) wait_func,
1530                                              user_data,
1531                                              user_data_free_func,
1532                                              timeout_seconds,
1533                                              FALSE, /* to_disappear */
1534                                              error);
1535 }
1536 
1537 
1538 /**
1539  * udisks_daemon_wait_for_object_to_disappear_sync:
1540  * @daemon: A #UDisksDaemon.
1541  * @wait_func: Function to check for desired object.
1542  * @user_data: User data to pass to @wait_func.
1543  * @user_data_free_func: (allow-none): Function to free @user_data or %NULL.
1544  * @timeout_seconds: Maximum time to wait for the object to disappear (in seconds) or 0 to never wait.
1545  * @error: (allow-none): Return location for error or %NULL.
1546  *
1547  * Blocks the calling thread until an object picked by @wait_func disappears or
1548  * until @timeout_seconds has passed (in which case the function fails with
1549  * %UDISKS_ERROR_TIMED_OUT).
1550  *
1551  * Note that @wait_func will be called from time to time - for example
1552  * if there is a device event. For consistency @wait_func is supposed
1553  * to return full reference to an existing object; udisks_daemon_wait_for_object_to_disappear_sync()
1554  * will take care of dropping the reference after each iteration.
1555  *
1556  * Returns: (transfer full): Whether the object picked by @wait_func disappeared or not (@error is set).
1557  */
1558 gboolean
udisks_daemon_wait_for_object_to_disappear_sync(UDisksDaemon * daemon,UDisksDaemonWaitFuncObject wait_func,gpointer user_data,GDestroyNotify user_data_free_func,guint timeout_seconds,GError ** error)1559 udisks_daemon_wait_for_object_to_disappear_sync (UDisksDaemon               *daemon,
1560                                                  UDisksDaemonWaitFuncObject  wait_func,
1561                                                  gpointer                    user_data,
1562                                                  GDestroyNotify              user_data_free_func,
1563                                                  guint                       timeout_seconds,
1564                                                  GError                      **error)
1565 {
1566   UDisksObject *object;
1567 
1568   object = (UDisksObject *) wait_for_objects (daemon,
1569                                               (UDisksDaemonWaitFuncGeneric) wait_func,
1570                                               user_data,
1571                                               user_data_free_func,
1572                                               timeout_seconds,
1573                                               TRUE, /* to_disappear */
1574                                               error);
1575   if (object != NULL)
1576     g_object_unref (object);
1577 
1578   return NULL == object;
1579 }
1580 
1581 
1582 /* ---------------------------------------------------------------------------------------------------- */
1583 
1584 /**
1585  * udisks_daemon_find_block:
1586  * @daemon: A #UDisksDaemon.
1587  * @block_device_number: A #dev_t with the device number to find.
1588  *
1589  * Finds a block device with the number given by @block_device_number.
1590  *
1591  * Returns: (transfer full): A #UDisksObject or %NULL if not found. Free with g_object_unref().
1592  */
1593 UDisksObject *
udisks_daemon_find_block(UDisksDaemon * daemon,dev_t block_device_number)1594 udisks_daemon_find_block (UDisksDaemon *daemon,
1595                           dev_t         block_device_number)
1596 {
1597   UDisksObject *ret = NULL;
1598   GList *objects, *l;
1599 
1600   objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (daemon->object_manager));
1601   for (l = objects; l != NULL; l = l->next)
1602     {
1603       UDisksObject *object = UDISKS_OBJECT (l->data);
1604       UDisksBlock *block;
1605 
1606       block = udisks_object_peek_block (object);
1607       if (block == NULL)
1608         continue;
1609 
1610       if (udisks_block_get_device_number (block) == block_device_number)
1611         {
1612           ret = g_object_ref (object);
1613           goto out;
1614         }
1615     }
1616  out:
1617   g_list_free_full (objects, g_object_unref);
1618   return ret;
1619 }
1620 
1621 /* ---------------------------------------------------------------------------------------------------- */
1622 
1623 /**
1624  * udisks_daemon_find_block_by_device_file:
1625  * @daemon: A #UDisksDaemon.
1626  * @device_file: A device file.
1627  *
1628  * Finds a block device with device file given by @device_file.
1629  *
1630  * Returns: (transfer full): A #UDisksObject or %NULL if not found. Free with g_object_unref().
1631  */
1632 UDisksObject *
udisks_daemon_find_block_by_device_file(UDisksDaemon * daemon,const gchar * device_file)1633 udisks_daemon_find_block_by_device_file (UDisksDaemon *daemon,
1634                                          const gchar  *device_file)
1635 {
1636   UDisksObject *ret = NULL;
1637   GList *objects, *l;
1638 
1639   objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (daemon->object_manager));
1640   for (l = objects; l != NULL; l = l->next)
1641     {
1642       UDisksObject *object = UDISKS_OBJECT (l->data);
1643       UDisksBlock *block;
1644 
1645       block = udisks_object_peek_block (object);
1646       if (block == NULL)
1647         continue;
1648 
1649       if (g_strcmp0 (udisks_block_get_device (block), device_file) == 0)
1650         {
1651           ret = g_object_ref (object);
1652           goto out;
1653         }
1654     }
1655  out:
1656   g_list_free_full (objects, g_object_unref);
1657   return ret;
1658 }
1659 
1660 /* ---------------------------------------------------------------------------------------------------- */
1661 
1662 /**
1663  * udisks_daemon_find_block_by_sysfs_path:
1664  * @daemon: A #UDisksDaemon.
1665  * @sysfs_path: A sysfs path.
1666  *
1667  * Finds a block device with a sysfs path given by @sysfs_path.
1668  *
1669  * Returns: (transfer full): A #UDisksObject or %NULL if not found. Free with g_object_unref().
1670  */
1671 UDisksObject *
udisks_daemon_find_block_by_sysfs_path(UDisksDaemon * daemon,const gchar * sysfs_path)1672 udisks_daemon_find_block_by_sysfs_path (UDisksDaemon *daemon,
1673                                         const gchar  *sysfs_path)
1674 {
1675   UDisksObject *ret = NULL;
1676   GList *objects, *l;
1677 
1678   objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (daemon->object_manager));
1679   for (l = objects; l != NULL; l = l->next)
1680     {
1681       UDisksObject *object = UDISKS_OBJECT (l->data);
1682       UDisksLinuxDevice *device;
1683 
1684       if (!UDISKS_IS_LINUX_BLOCK_OBJECT (object))
1685         continue;
1686 
1687       device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (object));
1688       if (device == NULL)
1689         continue;
1690 
1691       if (g_strcmp0 (g_udev_device_get_sysfs_path (device->udev_device), sysfs_path) == 0)
1692         {
1693           g_object_unref (device);
1694           ret = g_object_ref (object);
1695           goto out;
1696         }
1697       g_object_unref (device);
1698     }
1699  out:
1700   g_list_free_full (objects, g_object_unref);
1701   return ret;
1702 }
1703 
1704 /* ---------------------------------------------------------------------------------------------------- */
1705 
1706 /**
1707  * udisks_daemon_find_object:
1708  * @daemon: A #UDisksDaemon.
1709  * @object_path: A #dev_t with the device number to find.
1710  *
1711  * Finds an exported object with the object path given by @object_path.
1712  *
1713  * Returns: (transfer full): A #UDisksObject or %NULL if not found. Free with g_object_unref().
1714  */
1715 UDisksObject *
udisks_daemon_find_object(UDisksDaemon * daemon,const gchar * object_path)1716 udisks_daemon_find_object (UDisksDaemon *daemon,
1717                            const gchar  *object_path)
1718 {
1719   return (UDisksObject *) g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (daemon->object_manager),
1720                                                             object_path);
1721 }
1722 
1723 /**
1724  * udisks_daemon_get_objects:
1725  * @daemon: A #UDisksDaemon.
1726  *
1727  * Gets all D-Bus objects exported by @daemon.
1728  *
1729  * Returns: (transfer full) (element-type UDisksObject): A list of #UDisksObject instances. The returned list should be freed with g_list_free() after each element has been freed with g_object_unref().
1730  */
1731 GList *
udisks_daemon_get_objects(UDisksDaemon * daemon)1732 udisks_daemon_get_objects (UDisksDaemon *daemon)
1733 {
1734   return g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (daemon->object_manager));
1735 }
1736 
1737 /**
1738  * udisks_daemon_get_module_manager:
1739  * @daemon: A #UDisksDaemon.
1740  *
1741  * Gets the module manager used by @daemon.
1742  *
1743  * Returns: A #UDisksModuleManager. Do not free, the object is owned by @daemon.
1744  */
1745 UDisksModuleManager *
udisks_daemon_get_module_manager(UDisksDaemon * daemon)1746 udisks_daemon_get_module_manager (UDisksDaemon *daemon)
1747 {
1748   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
1749   return daemon->module_manager;
1750 }
1751 
1752 /**
1753  * udisks_daemon_get_config_manager:
1754  * @daemon: A #UDisksDaemon.
1755  *
1756  * Gets the config manager used by @daemon.
1757  *
1758  * Returns: A #UDisksConfigManager. Do not free, the object is owned by @daemon.
1759  */
1760 UDisksConfigManager *
udisks_daemon_get_config_manager(UDisksDaemon * daemon)1761 udisks_daemon_get_config_manager (UDisksDaemon *daemon)
1762 {
1763   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
1764   return daemon->config_manager;
1765 }
1766 
1767 /**
1768  * udisks_daemon_get_disable_modules:
1769  * @daemon: A #UDisksDaemon.
1770  *
1771  * Gets @daemon setting whether modules should never be loaded.
1772  *
1773  * Returns: %TRUE if --disable-modules commandline switch has been specified.
1774  */
1775 gboolean
udisks_daemon_get_disable_modules(UDisksDaemon * daemon)1776 udisks_daemon_get_disable_modules (UDisksDaemon*daemon)
1777 {
1778   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), FALSE);
1779   return daemon->disable_modules;
1780 }
1781 
1782 /**
1783  * udisks_daemon_get_force_load_modules:
1784  * @daemon: A #UDisksDaemon.
1785  *
1786  * Gets @daemon setting whether modules should be activated upon start.
1787  *
1788  * Returns: %TRUE if --force-load-modules commandline switch has been specified.
1789  */
1790 gboolean
udisks_daemon_get_force_load_modules(UDisksDaemon * daemon)1791 udisks_daemon_get_force_load_modules (UDisksDaemon *daemon)
1792 {
1793   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), FALSE);
1794   return daemon->force_load_modules;
1795 }
1796 
1797 /**
1798  * udisks_daemon_get_uninstalled:
1799  * @daemon: A #UDisksDaemon.
1800  *
1801  * Gets @daemon setting whether the modules should be loaded from the build
1802  * directory.
1803  *
1804  * Returns: %TRUE if --uninstalled commandline switch has been specified.
1805  */
1806 gboolean
udisks_daemon_get_uninstalled(UDisksDaemon * daemon)1807 udisks_daemon_get_uninstalled (UDisksDaemon *daemon)
1808 {
1809   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), FALSE);
1810   return daemon->uninstalled;
1811 }
1812 
1813 /**
1814  * udisks_daemon_get_enable_tcrypt:
1815  * @daemon: A #UDisksDaemon.
1816  *
1817  * Gets @daemon setting whether devices should be tested for being TCRYPT
1818  * encrypted.
1819  *
1820  * Returns: %TRUE if "/etc/udisks2/tcrypt.conf" was an existing file during
1821  * daemon startup.
1822  */
1823 gboolean
udisks_daemon_get_enable_tcrypt(UDisksDaemon * daemon)1824 udisks_daemon_get_enable_tcrypt (UDisksDaemon *daemon)
1825 {
1826   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), FALSE);
1827   return daemon->enable_tcrypt;
1828 }
1829 
1830 /**
1831  * udisks_daemon_get_uuid:
1832  * @daemon: A #UDisksDaemon.
1833  *
1834  * Gets the UUID string specific to this @daemon instance.
1835  *
1836  * Returns: the UUID string. Do not free, the string is owned by @daemon.
1837  */
1838 const gchar *
udisks_daemon_get_uuid(UDisksDaemon * daemon)1839 udisks_daemon_get_uuid (UDisksDaemon *daemon)
1840 {
1841   g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
1842   return daemon->uuid;
1843 }
1844 
1845 /* ---------------------------------------------------------------------------------------------------- */
1846 
1847 /**
1848  * udisks_daemon_get_parent_for_tracking:
1849  * @daemon: A #UDisksDaemon.
1850  * @path: object path of a child to find parent of
1851  * @uuid: a pointer to return parent UUID string
1852  *
1853  * Finds parent block device and returns its object path and UUID.
1854  * If the return value is %NULL, the value of @uuid has not been changed.
1855  *
1856  * Returns: (transfer full): object path of the parent device. Free with g_free().
1857  */
1858 gchar *
udisks_daemon_get_parent_for_tracking(UDisksDaemon * daemon,const gchar * path,gchar ** uuid)1859 udisks_daemon_get_parent_for_tracking (UDisksDaemon  *daemon,
1860                                        const gchar   *path,
1861                                        gchar        **uuid)
1862 {
1863   const gchar *parent_path = NULL;
1864   const gchar *parent_uuid = NULL;
1865 
1866   UDisksObject *object = NULL;
1867   UDisksObject *crypto_object = NULL;
1868   UDisksObject *mdraid_object = NULL;
1869   UDisksObject *table_object = NULL;
1870 
1871   UDisksBlock *block;
1872   UDisksBlock *crypto_block;
1873   UDisksMDRaid *mdraid;
1874   UDisksPartition *partition;
1875   UDisksBlock *table_block;
1876 
1877   GList *modules;
1878   GList *l;
1879   gchar *path_ret = NULL;
1880 
1881   object = udisks_daemon_find_object (daemon, path);
1882   if (object == NULL)
1883     goto out;
1884 
1885   block = udisks_object_peek_block (object);
1886   if (block)
1887     {
1888       crypto_object = udisks_daemon_find_object (daemon, udisks_block_get_crypto_backing_device (block));
1889       if (crypto_object)
1890         {
1891           crypto_block = udisks_object_peek_block (crypto_object);
1892           if (crypto_block)
1893             {
1894               parent_uuid = udisks_block_get_id_uuid (crypto_block);
1895               parent_path = udisks_block_get_crypto_backing_device (block);
1896               goto out;
1897             }
1898         }
1899 
1900       mdraid_object = udisks_daemon_find_object (daemon, udisks_block_get_mdraid (block));
1901       if (mdraid_object)
1902         {
1903           mdraid = udisks_object_peek_mdraid (mdraid_object);
1904           if (mdraid)
1905             {
1906               parent_uuid = udisks_mdraid_get_uuid (mdraid);
1907               parent_path = udisks_block_get_mdraid (block);
1908               goto out;
1909             }
1910         }
1911 
1912       partition = udisks_object_peek_partition (object);
1913       if (partition)
1914         {
1915           table_object = udisks_daemon_find_object (daemon, udisks_partition_get_table (partition));
1916           if (table_object)
1917             {
1918               table_block = udisks_object_peek_block (table_object);
1919               if (table_block)
1920                 {
1921                   /* We don't want to track partition tables because
1922                      they can't be 'closed' in a way that their
1923                      children temporarily invisible.
1924                   */
1925                   parent_uuid = NULL;
1926                   parent_path = udisks_partition_get_table (partition);
1927                   goto out;
1928                 }
1929             }
1930         }
1931     }
1932 
1933  out:
1934   g_clear_object (&object);
1935   g_clear_object (&crypto_object);
1936   g_clear_object (&mdraid_object);
1937   g_clear_object (&table_object);
1938 
1939   if (parent_path)
1940     {
1941       if (uuid)
1942         *uuid = g_strdup (parent_uuid);
1943       return g_strdup (parent_path);
1944     }
1945 
1946   modules = udisks_module_manager_get_modules (daemon->module_manager);
1947   for (l = modules; l != NULL; l = l->next)
1948     {
1949       UDisksModule *module = l->data;
1950 
1951       path_ret = udisks_module_track_parent (module, path, uuid);
1952       if (path_ret)
1953         break;
1954     }
1955   g_list_free_full (modules, g_object_unref);
1956 
1957   if (path_ret)
1958     return path_ret;
1959 
1960   return NULL;
1961 }
1962 
1963 /* ---------------------------------------------------------------------------------------------------- */
1964