1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
3 * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <glib/gi18n-lib.h>
28 #include "udiskslogging.h"
29 #include "udisksdaemon.h"
30 #include "udisksdaemonutil.h"
31 #include "udiskslinuxprovider.h"
32 #include "udiskslinuxdriveobject.h"
33 #include "udiskslinuxdrive.h"
34 #include "udiskslinuxdriveata.h"
35 #include "udiskslinuxblockobject.h"
38 * SECTION:udiskslinuxdriveobject
39 * @title: UDisksLinuxDriveObject
40 * @short_description: Object representing a drive on Linux
42 * Object corresponding to a drive on Linux.
45 typedef struct _UDisksLinuxDriveObjectClass UDisksLinuxDriveObjectClass;
48 * UDisksLinuxDriveObject:
50 * The #UDisksLinuxDriveObject structure contains only private data and
51 * should only be accessed using the provided API.
53 struct _UDisksLinuxDriveObject
55 UDisksObjectSkeleton parent_instance;
59 /* list of GUdevDevice objects for block objects */
63 UDisksDrive *iface_drive;
64 UDisksDriveAta *iface_drive_ata;
67 struct _UDisksLinuxDriveObjectClass
69 UDisksObjectSkeletonClass parent_class;
79 G_DEFINE_TYPE (UDisksLinuxDriveObject, udisks_linux_drive_object, UDISKS_TYPE_OBJECT_SKELETON);
82 udisks_linux_drive_object_finalize (GObject *_object)
84 UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
86 /* note: we don't hold a ref to drive_object->daemon or drive_object->mount_monitor */
87 g_list_foreach (object->devices, (GFunc) g_object_unref, NULL);
88 g_list_free (object->devices);
90 if (object->iface_drive != NULL)
91 g_object_unref (object->iface_drive);
92 if (object->iface_drive_ata != NULL)
93 g_object_unref (object->iface_drive_ata);
95 if (G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->finalize != NULL)
96 G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->finalize (_object);
100 udisks_linux_drive_object_get_property (GObject *_object,
105 UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
110 g_value_set_object (value, udisks_linux_drive_object_get_daemon (object));
114 G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec);
120 udisks_linux_drive_object_set_property (GObject *_object,
125 UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
130 g_assert (object->daemon == NULL);
131 /* we don't take a reference to the daemon */
132 object->daemon = g_value_get_object (value);
136 g_assert (object->devices == NULL);
137 object->devices = g_list_prepend (NULL, g_value_dup_object (value));
141 G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec);
148 udisks_linux_drive_object_init (UDisksLinuxDriveObject *object)
152 static GObjectConstructParam *
153 find_construct_property (guint n_construct_properties,
154 GObjectConstructParam *construct_properties,
158 for (n = 0; n < n_construct_properties; n++)
159 if (g_strcmp0 (g_param_spec_get_name (construct_properties[n].pspec), name) == 0)
160 return &construct_properties[n];
164 /* unless given, compute object path from sysfs path */
166 udisks_linux_drive_object_constructor (GType type,
167 guint n_construct_properties,
168 GObjectConstructParam *construct_properties)
170 GObjectConstructParam *cp;
171 UDisksDaemon *daemon;
175 cp = find_construct_property (n_construct_properties, construct_properties, "daemon");
176 g_assert (cp != NULL);
177 daemon = UDISKS_DAEMON (g_value_get_object (cp->value));
178 g_assert (daemon != NULL);
180 client = udisks_linux_provider_get_udev_client (udisks_daemon_get_linux_provider (daemon));
182 cp = find_construct_property (n_construct_properties, construct_properties, "device");
183 g_assert (cp != NULL);
184 device = G_UDEV_DEVICE (g_value_get_object (cp->value));
185 g_assert (device != NULL);
187 if (!udisks_linux_drive_object_should_include_device (client, device, NULL))
193 return G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->constructor (type,
194 n_construct_properties,
195 construct_properties);
200 strip_and_replace_with_uscore (gchar *s)
209 for (n = 0; s != NULL && s[n] != '\0'; n++)
211 if (s[n] == ' ' || s[n] == '-')
220 udisks_linux_drive_object_constructed (GObject *_object)
222 UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
228 /* initial coldplug */
229 udisks_linux_drive_object_uevent (object, "add", object->devices->data);
231 /* compute the object path */
232 vendor = g_strdup (udisks_drive_get_vendor (object->iface_drive));
233 model = g_strdup (udisks_drive_get_model (object->iface_drive));
234 serial = g_strdup (udisks_drive_get_serial (object->iface_drive));
235 strip_and_replace_with_uscore (vendor);
236 strip_and_replace_with_uscore (model);
237 strip_and_replace_with_uscore (serial);
238 str = g_string_new ("/org/freedesktop/UDisks2/drives/");
239 if (vendor == NULL && model == NULL && serial == NULL)
241 g_string_append (str, "drive");
245 /* <VENDOR>_<MODEL>_<SERIAL> */
246 if (vendor != NULL && strlen (vendor) > 0)
248 udisks_safe_append_to_object_path (str, vendor);
250 if (model != NULL && strlen (model) > 0)
252 if (str->str[str->len - 1] != '/')
253 g_string_append_c (str, '_');
254 udisks_safe_append_to_object_path (str, model);
256 if (serial != NULL && strlen (serial) > 0)
258 if (str->str[str->len - 1] != '/')
259 g_string_append_c (str, '_');
260 udisks_safe_append_to_object_path (str, serial);
266 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), str->str);
267 g_string_free (str, TRUE);
269 if (G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->constructed != NULL)
270 G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->constructed (_object);
274 udisks_linux_drive_object_class_init (UDisksLinuxDriveObjectClass *klass)
276 GObjectClass *gobject_class;
278 gobject_class = G_OBJECT_CLASS (klass);
279 gobject_class->constructor = udisks_linux_drive_object_constructor;
280 gobject_class->finalize = udisks_linux_drive_object_finalize;
281 gobject_class->constructed = udisks_linux_drive_object_constructed;
282 gobject_class->set_property = udisks_linux_drive_object_set_property;
283 gobject_class->get_property = udisks_linux_drive_object_get_property;
286 * UDisksLinuxDriveObject:daemon:
288 * The #UDisksDaemon the object is for.
290 g_object_class_install_property (gobject_class,
292 g_param_spec_object ("daemon",
294 "The daemon the object is for",
298 G_PARAM_CONSTRUCT_ONLY |
299 G_PARAM_STATIC_STRINGS));
302 * UDisksLinuxDriveObject:device:
304 * The #GUdevDevice for the object. Connect to the #GObject::notify
305 * signal to get notified whenever this is updated.
307 g_object_class_install_property (gobject_class,
309 g_param_spec_object ("device",
311 "The device for the object",
314 G_PARAM_CONSTRUCT_ONLY |
315 G_PARAM_STATIC_STRINGS));
320 * udisks_linux_drive_object_new:
321 * @daemon: A #UDisksDaemon.
322 * @device: The #GUdevDevice for the sysfs block device.
324 * Create a new drive object.
326 * Returns: A #UDisksLinuxDriveObject object or %NULL if @device does not represent a drive. Free with g_object_unref().
328 UDisksLinuxDriveObject *
329 udisks_linux_drive_object_new (UDisksDaemon *daemon,
334 g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
335 g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
337 object = g_object_new (UDISKS_TYPE_LINUX_DRIVE_OBJECT,
343 return UDISKS_LINUX_DRIVE_OBJECT (object);
349 * udisks_linux_drive_object_get_daemon:
350 * @object: A #UDisksLinuxDriveObject.
352 * Gets the daemon used by @object.
354 * Returns: A #UDisksDaemon. Do not free, the object is owned by @object.
357 udisks_linux_drive_object_get_daemon (UDisksLinuxDriveObject *object)
359 g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object), NULL);
360 return object->daemon;
364 * udisks_linux_drive_object_get_devices:
365 * @object: A #UDisksLinuxDriveObject.
367 * Gets the current #GUdevDevice objects associated with @object.
369 * Returns: A list of #GUdevDevice objects. Free each element with
370 * g_object_unref(), then free the list with g_list_free().
373 udisks_linux_drive_object_get_devices (UDisksLinuxDriveObject *object)
376 g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object), NULL);
377 ret = g_list_copy (object->devices);
378 g_list_foreach (ret, (GFunc) g_object_ref, NULL);
383 * udisks_linux_drive_object_get_device:
384 * @object: A #UDisksLinuxDriveObject.
385 * @get_hw: If the drive is multipath, set to %TRUE to get a path device instead of the multipath device.
387 * Gets one of the #GUdevDevice object associated with @object.
389 * If @get_hw is %TRUE and @object represents a multipath device then
390 * one of the paths is returned rather than the multipath device. This
391 * is useful if you e.g. need to configure the physical hardware.
393 * Returns: A #GUdevDevice or %NULL. The returned object must be freed
394 * with g_object_unref().
397 udisks_linux_drive_object_get_device (UDisksLinuxDriveObject *object,
400 GUdevDevice *ret = NULL;
401 /* TODO: actually look at @get_hw */
402 if (object->devices != NULL)
404 ret = object->devices->data;
412 * udisks_linux_drive_object_get_block:
413 * @object: A #UDisksLinuxDriveObject.
414 * @get_hw: If the drive is multipath, set to %TRUE to get a path device instead of the multipath device.
416 * Gets a #UDisksLinuxBlockObject representing a block device associated with @object.
418 * Returns: A #UDisksLinuxBlockObject or %NULL. The returned object
419 * must be freed with g_object_unref().
421 UDisksLinuxBlockObject *
422 udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object,
425 GDBusObjectManagerServer *object_manager;
426 UDisksLinuxBlockObject *ret;
430 /* TODO: actually look at @get_hw */
434 object_manager = udisks_daemon_get_object_manager (object->daemon);
435 objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
436 for (l = objects; l != NULL; l = l->next)
438 GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data);
443 if (!UDISKS_IS_LINUX_BLOCK_OBJECT (iter_object))
446 device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (iter_object));
447 is_disk = (g_strcmp0 (g_udev_device_get_devtype (device), "disk") == 0);
448 g_object_unref (device);
453 block = udisks_object_peek_block (UDISKS_OBJECT (iter_object));
454 if (g_strcmp0 (udisks_block_get_drive (block),
455 g_dbus_object_get_object_path (G_DBUS_OBJECT (object))) == 0)
457 ret = g_object_ref (iter_object);
463 g_list_foreach (objects, (GFunc) g_object_unref, NULL);
464 g_list_free (objects);
468 /* ---------------------------------------------------------------------------------------------------- */
470 typedef gboolean (*HasInterfaceFunc) (UDisksLinuxDriveObject *object);
471 typedef void (*ConnectInterfaceFunc) (UDisksLinuxDriveObject *object);
472 typedef gboolean (*UpdateInterfaceFunc) (UDisksLinuxDriveObject *object,
473 const gchar *uevent_action,
474 GDBusInterface *interface);
477 update_iface (UDisksLinuxDriveObject *object,
478 const gchar *uevent_action,
479 HasInterfaceFunc has_func,
480 ConnectInterfaceFunc connect_func,
481 UpdateInterfaceFunc update_func,
483 gpointer _interface_pointer)
485 gboolean ret = FALSE;
488 GDBusInterface **interface_pointer = _interface_pointer;
490 g_return_val_if_fail (object != NULL, FALSE);
491 g_return_val_if_fail (has_func != NULL, FALSE);
492 g_return_val_if_fail (update_func != NULL, FALSE);
493 g_return_val_if_fail (g_type_is_a (skeleton_type, G_TYPE_OBJECT), FALSE);
494 g_return_val_if_fail (g_type_is_a (skeleton_type, G_TYPE_DBUS_INTERFACE), FALSE);
495 g_return_val_if_fail (interface_pointer != NULL, FALSE);
496 g_return_val_if_fail (*interface_pointer == NULL || G_IS_DBUS_INTERFACE (*interface_pointer), FALSE);
499 has = has_func (object);
500 if (*interface_pointer == NULL)
504 *interface_pointer = g_object_new (skeleton_type, NULL);
505 if (connect_func != NULL)
506 connect_func (object);
514 g_dbus_object_skeleton_remove_interface (G_DBUS_OBJECT_SKELETON (object),
515 G_DBUS_INTERFACE_SKELETON (*interface_pointer));
516 g_object_unref (*interface_pointer);
517 *interface_pointer = NULL;
521 if (*interface_pointer != NULL)
523 if (update_func (object, uevent_action, G_DBUS_INTERFACE (*interface_pointer)))
526 g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object),
527 G_DBUS_INTERFACE_SKELETON (*interface_pointer));
533 /* ---------------------------------------------------------------------------------------------------- */
536 drive_check (UDisksLinuxDriveObject *object)
542 drive_connect (UDisksLinuxDriveObject *object)
547 drive_update (UDisksLinuxDriveObject *object,
548 const gchar *uevent_action,
549 GDBusInterface *_iface)
551 return udisks_linux_drive_update (UDISKS_LINUX_DRIVE (object->iface_drive), object);
554 /* ---------------------------------------------------------------------------------------------------- */
557 drive_ata_check (UDisksLinuxDriveObject *object)
563 if (object->devices == NULL)
566 device = G_UDEV_DEVICE (object->devices->data);
567 if (!g_udev_device_get_property_as_boolean (device, "ID_ATA"))
577 drive_ata_connect (UDisksLinuxDriveObject *object)
583 drive_ata_update (UDisksLinuxDriveObject *object,
584 const gchar *uevent_action,
585 GDBusInterface *_iface)
587 return udisks_linux_drive_ata_update (UDISKS_LINUX_DRIVE_ATA (object->iface_drive_ata), object);
590 /* ---------------------------------------------------------------------------------------------------- */
592 static void apply_configuration (UDisksLinuxDriveObject *object);
595 find_link_for_sysfs_path (UDisksLinuxDriveObject *object,
596 const gchar *sysfs_path)
601 for (l = object->devices; l != NULL; l = l->next)
603 GUdevDevice *device = G_UDEV_DEVICE (l->data);
604 if (g_strcmp0 (g_udev_device_get_sysfs_path (device), sysfs_path) == 0)
615 * udisks_linux_drive_object_uevent:
616 * @object: A #UDisksLinuxDriveObject.
617 * @action: Uevent action or %NULL
618 * @device: A #GUdevDevice device object or %NULL if the device hasn't changed.
620 * Updates all information on interfaces on @drive.
623 udisks_linux_drive_object_uevent (UDisksLinuxDriveObject *object,
628 gboolean conf_changed;
630 g_return_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object));
631 g_return_if_fail (device == NULL || G_UDEV_IS_DEVICE (device));
635 link = find_link_for_sysfs_path (object, g_udev_device_get_sysfs_path (device));
636 if (g_strcmp0 (action, "remove") == 0)
640 g_object_unref (G_UDEV_DEVICE (link->data));
641 object->devices = g_list_delete_link (object->devices, link);
645 udisks_warning ("Drive doesn't have device with sysfs path %s on remove event",
646 g_udev_device_get_sysfs_path (device));
653 g_object_unref (G_UDEV_DEVICE (link->data));
654 link->data = g_object_ref (device);
659 object->devices = g_list_append (object->devices, g_object_ref (device));
663 conf_changed = FALSE;
664 conf_changed |= update_iface (object, action, drive_check, drive_connect, drive_update,
665 UDISKS_TYPE_LINUX_DRIVE, &object->iface_drive);
666 conf_changed |= update_iface (object, action, drive_ata_check, drive_ata_connect, drive_ata_update,
667 UDISKS_TYPE_LINUX_DRIVE_ATA, &object->iface_drive_ata);
670 apply_configuration (object);
673 /* ---------------------------------------------------------------------------------------------------- */
676 apply_configuration (UDisksLinuxDriveObject *object)
678 GVariant *configuration = NULL;
679 GUdevDevice *device = NULL;
681 if (object->iface_drive == NULL)
684 configuration = udisks_drive_dup_configuration (object->iface_drive);
685 if (configuration == NULL)
688 device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
692 if (object->iface_drive_ata != NULL)
694 udisks_linux_drive_ata_apply_configuration (UDISKS_LINUX_DRIVE_ATA (object->iface_drive_ata),
700 g_clear_object (&device);
701 if (configuration != NULL)
702 g_variant_unref (configuration);
705 /* ---------------------------------------------------------------------------------------------------- */
708 check_for_vpd (GUdevDevice *device)
715 g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE);
717 /* order of preference: WWN, serial, path */
718 serial = g_udev_device_get_property (device, "ID_SERIAL");
719 wwn = g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION");
720 path = g_udev_device_get_property (device, "ID_PATH");
721 if (wwn != NULL && strlen (wwn) > 0)
723 ret = g_strdup (wwn);
725 else if (serial != NULL && strlen (serial) > 0)
727 ret = g_strdup (serial);
729 else if (path != NULL && strlen (path) > 0)
731 ret = g_strdup (path);
737 * udisks_linux_drive_object_should_include_device:
738 * @client: A #GUdevClient.
739 * @device: A #GUdevDevice.
740 * @out_vpd: Return location for unique ID or %NULL.
742 * Checks if we should even construct a #UDisksLinuxDriveObject for @device.
744 * Returns: %TRUE if we should construct an object, %FALSE otherwise.
747 udisks_linux_drive_object_should_include_device (GUdevClient *client,
757 /* The 'block' subsystem encompasses several objects with varying
763 * and we are only interested in the first.
765 if (g_strcmp0 (g_udev_device_get_devtype (device), "disk") != 0)
768 vpd = check_for_vpd (device);
777 name = g_udev_device_get_name (device);
779 /* workaround for floppy devices */
780 if (g_str_has_prefix (name, "fd"))
782 vpd = g_strdup_printf ("pcfloppy_%s", name);
786 /* workaround for missing serial/wwn on virtio-blk */
787 if (g_str_has_prefix (name, "vd"))
789 vpd = g_strdup (name);
793 /* workaround for missing serial/wwn on VMware */
794 vendor = g_udev_device_get_property (device, "ID_VENDOR");
795 model = g_udev_device_get_property (device, "ID_MODEL");
796 if (g_str_has_prefix (name, "sd") &&
797 vendor != NULL && g_strcmp0 (vendor, "VMware") == 0 &&
798 model != NULL && g_str_has_prefix (model, "Virtual"))
800 vpd = g_strdup (name);
804 /* workaround for missing serial/wwn on firewire devices */
805 parent = g_udev_device_get_parent_with_subsystem (device, "firewire", NULL);
808 vpd = g_strdup (name);
809 g_object_unref (parent);
814 const gchar *dm_name;
815 dm_name = g_udev_device_get_sysfs_attr (device, "dm/name");
816 if (dm_name != NULL && g_str_has_prefix (dm_name, "mpath"))
820 slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device), "slaves");
821 for (n = 0; slaves[n] != NULL; n++)
824 slave = g_udev_client_query_by_sysfs_path (client, slaves[n]);
827 vpd = check_for_vpd (slave);
830 g_object_unref (slave);
834 g_object_unref (slave);
857 /* ---------------------------------------------------------------------------------------------------- */
860 * udisks_linux_drive_object_housekeeping:
861 * @object: A #UDisksLinuxDriveObject.
862 * @secs_since_last: Number of seconds sincex the last housekeeping or 0 if the first housekeeping ever.
863 * @cancellable: A %GCancellable or %NULL.
864 * @error: Return location for error or %NULL.
866 * Called periodically (every ten minutes or so) to perform
867 * housekeeping tasks such as refreshing ATA SMART data.
869 * The function runs in a dedicated thread and is allowed to perform
872 * Long-running tasks should periodically check @cancellable to see if
873 * they have been cancelled.
875 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
878 udisks_linux_drive_object_housekeeping (UDisksLinuxDriveObject *object,
879 guint secs_since_last,
880 GCancellable *cancellable,
887 if (object->iface_drive_ata != NULL &&
888 udisks_drive_ata_get_smart_supported (object->iface_drive_ata) &&
889 udisks_drive_ata_get_smart_enabled (object->iface_drive_ata))
894 /* Wake-up only on start-up */
896 if (secs_since_last == 0)
899 udisks_info ("Refreshing SMART data on %s (nowakeup=%d)",
900 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)),
904 if (!udisks_linux_drive_ata_refresh_smart_sync (UDISKS_LINUX_DRIVE_ATA (object->iface_drive_ata),
906 NULL, /* simulate_path */
910 if (nowakeup && (local_error->domain == UDISKS_ERROR &&
911 local_error->code == UDISKS_ERROR_WOULD_WAKEUP))
913 udisks_info ("Drive %s is in a sleep state",
914 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
915 g_error_free (local_error);
917 else if (nowakeup && (local_error->domain == UDISKS_ERROR &&
918 local_error->code == UDISKS_ERROR_DEVICE_BUSY))
920 /* typically because a "secure erase" operation is pending */
921 udisks_info ("Drive %s is busy",
922 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
923 g_error_free (local_error);
927 g_propagate_prefixed_error (error, local_error, "Error updating SMART data: ");
940 is_block_unlocked (GList *objects, const gchar *crypto_object_path)
942 gboolean ret = FALSE;
944 for (l = objects; l != NULL; l = l->next)
946 UDisksObject *object = UDISKS_OBJECT (l->data);
948 block = udisks_object_peek_block (object);
951 if (g_strcmp0 (udisks_block_get_crypto_backing_device (block), crypto_object_path) == 0)
963 * udisks_linux_drive_object_is_not_in_use:
964 * @object: A #UDisksLinuxDriveObject.
965 * @cancellable: (allow-none): A #GCancellable or %NULL.
966 * @error: A #GError or %NULL.
968 * Checks if the drive represented by @object is in use and sets
971 * Returns: %TRUE if @object is not is use, %FALSE if @error is set.
974 udisks_linux_drive_object_is_not_in_use (UDisksLinuxDriveObject *object,
975 GCancellable *cancellable,
978 GDBusObjectManagerServer *object_manager;
979 const gchar *drive_object_path;
981 GList *objects = NULL;
984 g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object), FALSE);
985 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
986 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
988 drive_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
990 object_manager = udisks_daemon_get_object_manager (object->daemon);
991 objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
993 /* Visit all block devices related to the drive... */
994 for (l = objects; l != NULL; l = l->next)
996 GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data);
998 UDisksFilesystem *filesystem;
1000 if (!UDISKS_IS_LINUX_BLOCK_OBJECT (iter_object))
1003 block = udisks_object_peek_block (UDISKS_OBJECT (iter_object));
1004 filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (iter_object));
1006 if (g_strcmp0 (udisks_block_get_drive (block), drive_object_path) != 0)
1009 /* bail if block device is mounted */
1010 if (filesystem != NULL)
1012 if (g_strv_length ((gchar **) udisks_filesystem_get_mount_points (filesystem)) > 0)
1016 UDISKS_ERROR_DEVICE_BUSY,
1017 "Device %s is mounted",
1018 udisks_block_get_preferred_device (block));
1024 /* bail if block device is unlocked (LUKS) */
1025 if (is_block_unlocked (objects, g_dbus_object_get_object_path (G_DBUS_OBJECT (iter_object))))
1029 UDISKS_ERROR_DEVICE_BUSY,
1030 "Encrypted device %s is unlocked",
1031 udisks_block_get_preferred_device (block));
1038 g_list_free_full (objects, g_object_unref);
1042 /* ---------------------------------------------------------------------------------------------------- */