diff options
author | David Zeuthen <davidz@redhat.com> | 2011-08-16 12:36:42 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2011-08-16 12:36:42 -0400 |
commit | bebb0c9adcd57045dee71408ae756cf6532568e8 (patch) | |
tree | fa02f66a3fe771f2edd75cc7125ea00a7d058466 | |
parent | c12cd7a91ae56e937a13746a3a87db73cc300e84 (diff) |
Factor block devices into separate types
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r-- | doc/udisks2-docs.xml | 50 | ||||
-rw-r--r-- | doc/udisks2-sections.txt | 73 | ||||
-rw-r--r-- | doc/udisks2.types | 3 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/udisksdaemontypes.h | 3 | ||||
-rw-r--r-- | src/udiskslinuxblock.c | 2022 | ||||
-rw-r--r-- | src/udiskslinuxblock.h | 19 | ||||
-rw-r--r-- | src/udiskslinuxblockobject.c | 586 | ||||
-rw-r--r-- | src/udiskslinuxblockobject.h | 44 | ||||
-rw-r--r-- | src/udiskslinuxdrive.c | 4 | ||||
-rw-r--r-- | src/udiskslinuxdriveata.c | 4 | ||||
-rw-r--r-- | src/udiskslinuxdriveobject.c | 11 | ||||
-rw-r--r-- | src/udiskslinuxdriveobject.h | 2 | ||||
-rw-r--r-- | src/udiskslinuxencrypted.c | 25 | ||||
-rw-r--r-- | src/udiskslinuxencrypted.h | 2 | ||||
-rw-r--r-- | src/udiskslinuxfilesystem.c | 52 | ||||
-rw-r--r-- | src/udiskslinuxfilesystem.h | 2 | ||||
-rw-r--r-- | src/udiskslinuxloop.c | 59 | ||||
-rw-r--r-- | src/udiskslinuxloop.h | 2 | ||||
-rw-r--r-- | src/udiskslinuxprovider.c | 56 | ||||
-rw-r--r-- | src/udiskslinuxswapspace.c | 37 | ||||
-rw-r--r-- | src/udiskslinuxswapspace.h | 2 |
22 files changed, 1686 insertions, 1373 deletions
diff --git a/doc/udisks2-docs.xml b/doc/udisks2-docs.xml index a6a7426..bfbaba5 100644 --- a/doc/udisks2-docs.xml +++ b/doc/udisks2-docs.xml @@ -171,18 +171,24 @@ <part id="ref-daemon"> <title>Daemon Implementation Details</title> - <xi:include href="xml/udisksdaemon.xml"/> - <xi:include href="xml/udisksdaemonutil.xml"/> - <xi:include href="xml/udiskslogging.xml"/> - <xi:include href="xml/udisksmount.xml"/> - <xi:include href="xml/udisksmountmonitor.xml"/> - <xi:include href="xml/udisksfstabentry.xml"/> - <xi:include href="xml/udisksfstabmonitor.xml"/> - <xi:include href="xml/udiskscrypttabentry.xml"/> - <xi:include href="xml/udiskscrypttabmonitor.xml"/> - <xi:include href="xml/udiskspersistentstore.xml"/> - <xi:include href="xml/udiskscleanup.xml"/> - <xi:include href="xml/udisksprovider.xml"/> + <chapter id="ref-daemon-core"> + <title>Core</title> + <xi:include href="xml/udisksdaemonutil.xml"/> + <xi:include href="xml/udiskslogging.xml"/> + <xi:include href="xml/udisksdaemon.xml"/> + <xi:include href="xml/udisksprovider.xml"/> + <xi:include href="xml/udiskscleanup.xml"/> + <xi:include href="xml/udiskspersistentstore.xml"/> + </chapter> + <chapter id="ref-daemon-monitoring"> + <title>State and Configuration</title> + <xi:include href="xml/udisksmountmonitor.xml"/> + <xi:include href="xml/udisksmount.xml"/> + <xi:include href="xml/udisksfstabmonitor.xml"/> + <xi:include href="xml/udisksfstabentry.xml"/> + <xi:include href="xml/udiskscrypttabmonitor.xml"/> + <xi:include href="xml/udiskscrypttabentry.xml"/> + </chapter> <chapter id="ref-daemon-jobs"> <title>Jobs</title> <xi:include href="xml/udisksbasejob.xml"/> @@ -190,22 +196,26 @@ <xi:include href="xml/udisksthreadedjob.xml"/> <xi:include href="xml/udisksspawnedjob.xml"/> </chapter> - <chapter id="ref-daemon-linux"> - <title>Linux-specific objects and providers</title> - <xi:include href="xml/udiskslinuxprovider.xml"/> + <chapter id="ref-daemon-drives"> + <title>Drives on Linux</title> <xi:include href="xml/udiskslinuxdriveobject.xml"/> - </chapter> - <chapter id="ref-daemon-linux-ifaces"> - <title>Linux implementation of interfaces</title> - <xi:include href="xml/udiskslinuxmanager.xml"/> - <xi:include href="xml/udiskslinuxblock.xml"/> <xi:include href="xml/udiskslinuxdrive.xml"/> <xi:include href="xml/udiskslinuxdriveata.xml"/> + </chapter> + <chapter id="ref-daemon-block-devices"> + <title>Block devices on Linux</title> + <xi:include href="xml/udiskslinuxblockobject.xml"/> + <xi:include href="xml/udiskslinuxblock.xml"/> <xi:include href="xml/udiskslinuxfilesystem.xml"/> <xi:include href="xml/udiskslinuxencrypted.xml"/> <xi:include href="xml/udiskslinuxswapspace.xml"/> <xi:include href="xml/udiskslinuxloop.xml"/> </chapter> + <chapter id="ref-daemon-linux-ifaces"> + <title>Other Linux-specific interfaces</title> + <xi:include href="xml/udiskslinuxprovider.xml"/> + <xi:include href="xml/udiskslinuxmanager.xml"/> + </chapter> </part> <part id="tools-fileformats"> diff --git a/doc/udisks2-sections.txt b/doc/udisks2-sections.txt index 4d5e48c..b26c12c 100644 --- a/doc/udisks2-sections.txt +++ b/doc/udisks2-sections.txt @@ -144,22 +144,6 @@ udisks_simple_job_get_type </SECTION> <SECTION> -<FILE>udiskslinuxblock</FILE> -<TITLE>UDisksLinuxBlock</TITLE> -UDisksLinuxBlock -udisks_linux_block_new -udisks_linux_block_uevent -udisks_linux_block_get_daemon -udisks_linux_block_get_device -<SUBSECTION Standard> -UDISKS_TYPE_LINUX_BLOCK -UDISKS_LINUX_BLOCK -UDISKS_IS_LINUX_BLOCK -<SUBSECTION Private> -udisks_linux_block_get_type -</SECTION> - -<SECTION> <FILE>udiskslinuxdriveobject</FILE> <TITLE>UDisksLinuxDriveObject</TITLE> UDisksLinuxDriveObject @@ -336,9 +320,39 @@ udisks_daemon_util_setup_by_user </SECTION> <SECTION> +<FILE>udiskslinuxblockobject</FILE> +<TITLE>UDisksLinuxBlockObject</TITLE> +UDisksLinuxBlockObject +udisks_linux_block_object_new +udisks_linux_block_object_uevent +udisks_linux_block_object_get_daemon +udisks_linux_block_object_get_device +<SUBSECTION Standard> +UDISKS_TYPE_LINUX_BLOCK_OBJECT +UDISKS_LINUX_BLOCK_OBJECT +UDISKS_IS_LINUX_BLOCK_OBJECT +<SUBSECTION Private> +udisks_linux_block_object_get_type +</SECTION> + +<SECTION> +<FILE>udiskslinuxblock</FILE> +UDisksLinuxBlock +udisks_linux_block_new +udisks_linux_block_update +<SUBSECTION Standard> +UDISKS_LINUX_BLOCK +UDISKS_IS_LINUX_BLOCK +UDISKS_TYPE_LINUX_BLOCK +<SUBSECTION Private> +udisks_linux_block_get_type +</SECTION> + +<SECTION> <FILE>udiskslinuxfilesystem</FILE> UDisksLinuxFilesystem udisks_linux_filesystem_new +udisks_linux_filesystem_update <SUBSECTION Standard> UDISKS_LINUX_FILESYSTEM UDISKS_IS_LINUX_FILESYSTEM @@ -351,6 +365,7 @@ udisks_linux_filesystem_get_type <FILE>udiskslinuxencrypted</FILE> UDisksLinuxEncrypted udisks_linux_encrypted_new +udisks_linux_encrypted_update <SUBSECTION Standard> UDISKS_LINUX_ENCRYPTED UDISKS_IS_LINUX_ENCRYPTED @@ -363,6 +378,7 @@ udisks_linux_encrypted_get_type <FILE>udiskslinuxswapspace</FILE> UDisksLinuxSwapspace udisks_linux_swapspace_new +udisks_linux_swapspace_update <SUBSECTION Standard> UDISKS_LINUX_SWAPSPACE UDISKS_IS_LINUX_SWAPSPACE @@ -372,6 +388,19 @@ udisks_linux_swapspace_get_type </SECTION> <SECTION> +<FILE>udiskslinuxloop</FILE> +UDisksLinuxLoop +udisks_linux_loop_new +udisks_linux_loop_update +<SUBSECTION Standard> +UDISKS_LINUX_LOOP +UDISKS_IS_LINUX_LOOP +UDISKS_TYPE_LINUX_LOOP +<SUBSECTION Private> +udisks_linux_loop_get_type +</SECTION> + +<SECTION> <FILE>UDisksObject</FILE> <TITLE>UDisksObject</TITLE> UDisksObject @@ -968,18 +997,6 @@ udisks_linux_manager_get_type </SECTION> <SECTION> -<FILE>udiskslinuxloop</FILE> -UDisksLinuxLoop -udisks_linux_loop_new -<SUBSECTION Standard> -UDISKS_LINUX_LOOP -UDISKS_IS_LINUX_LOOP -UDISKS_TYPE_LINUX_LOOP -<SUBSECTION Private> -udisks_linux_loop_get_type -</SECTION> - -<SECTION> <FILE>UDisksLoop</FILE> UDisksLoop UDisksLoopIface diff --git a/doc/udisks2.types b/doc/udisks2.types index c8de422..994a6a1 100644 --- a/doc/udisks2.types +++ b/doc/udisks2.types @@ -1,10 +1,11 @@ udisks_client_get_type udisks_daemon_get_type +udisks_linux_block_object_get_type udisks_linux_block_get_type +udisks_linux_drive_object_get_type udisks_linux_drive_get_type udisks_linux_drive_ata_get_type -udisks_linux_drive_object_get_type udisks_base_job_get_type udisks_spawned_job_get_type udisks_threaded_job_get_type diff --git a/src/Makefile.am b/src/Makefile.am index f628971..01faace 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ libudisks_daemon_la_SOURCES = \ udisksdaemon.h udisksdaemon.c \ udisksprovider.h udisksprovider.c \ udiskslinuxprovider.h udiskslinuxprovider.c \ + udiskslinuxblockobject.h udiskslinuxblockobject.c \ udiskslinuxblock.h udiskslinuxblock.c \ udiskslinuxfilesystem.h udiskslinuxfilesystem.c \ udiskslinuxencrypted.h udiskslinuxencrypted.c \ diff --git a/src/udisksdaemontypes.h b/src/udisksdaemontypes.h index 853fbc8..86238a9 100644 --- a/src/udisksdaemontypes.h +++ b/src/udisksdaemontypes.h @@ -34,6 +34,9 @@ typedef struct _UDisksDaemon UDisksDaemon; struct _UDisksLinuxProvider; typedef struct _UDisksLinuxProvider UDisksLinuxProvider; +struct _UDisksLinuxBlockObject; +typedef struct _UDisksLinuxBlockObject UDisksLinuxBlockObject; + struct _UDisksLinuxBlock; typedef struct _UDisksLinuxBlock UDisksLinuxBlock; diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c index b6b13a7..41a950e 100644 --- a/src/udiskslinuxblock.c +++ b/src/udiskslinuxblock.c @@ -24,29 +24,22 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> -#include <unistd.h> -#include <errno.h> #include <pwd.h> #include <grp.h> -#include <mntent.h> - #include <string.h> #include <stdlib.h> +#include <errno.h> +#include <mntent.h> + #include <glib/gstdio.h> #include "udiskslogging.h" -#include "udisksdaemon.h" -#include "udisksdaemonutil.h" #include "udiskslinuxblock.h" -#include "udisksmount.h" -#include "udisksmountmonitor.h" +#include "udiskslinuxblockobject.h" #include "udiskslinuxdriveobject.h" -#include "udiskslinuxdrive.h" -#include "udiskslinuxfilesystem.h" -#include "udiskslinuxencrypted.h" -#include "udiskslinuxswapspace.h" -#include "udiskslinuxloop.h" -#include "udiskspersistentstore.h" +#include "udisksdaemon.h" +#include "udiskscleanup.h" +#include "udisksdaemonutil.h" #include "udiskslinuxprovider.h" #include "udisksfstabmonitor.h" #include "udisksfstabentry.h" @@ -56,9 +49,10 @@ /** * SECTION:udiskslinuxblock * @title: UDisksLinuxBlock - * @short_description: Linux block devices + * @short_description: Block devices on Linux * - * Object corresponding to a Linux block device. + * This type provides an implementation of the #UDisksBlock + * interface on Linux. */ typedef struct _UDisksLinuxBlockClass UDisksLinuxBlockClass; @@ -66,341 +60,792 @@ typedef struct _UDisksLinuxBlockClass UDisksLinuxBlockClass; /** * UDisksLinuxBlock: * - * The #UDisksLinuxBlock structure contains only private data and - * should only be accessed using the provided API. + * The #UDisksLinuxBlock structure contains only private data and should + * only be accessed using the provided API. */ struct _UDisksLinuxBlock { - UDisksObjectSkeleton parent_instance; - - UDisksDaemon *daemon; - UDisksMountMonitor *mount_monitor; - - GUdevDevice *device; - - /* interface */ - UDisksBlockDevice *iface_block_device; - UDisksFilesystem *iface_filesystem; - UDisksSwapspace *iface_swapspace; - UDisksEncrypted *iface_encrypted; - UDisksLoop *iface_loop; + UDisksBlockDeviceSkeleton parent_instance; }; struct _UDisksLinuxBlockClass { - UDisksObjectSkeletonClass parent_class; + UDisksBlockDeviceSkeletonClass parent_class; }; -enum -{ - PROP_0, - PROP_DAEMON, - PROP_DEVICE -}; +static void block_iface_init (UDisksBlockDeviceIface *iface); -G_DEFINE_TYPE (UDisksLinuxBlock, udisks_linux_block, UDISKS_TYPE_OBJECT_SKELETON); +G_DEFINE_TYPE_WITH_CODE (UDisksLinuxBlock, udisks_linux_block, UDISKS_TYPE_BLOCK_DEVICE_SKELETON, + G_IMPLEMENT_INTERFACE (UDISKS_TYPE_BLOCK_DEVICE, block_iface_init)); -static void on_mount_monitor_mount_added (UDisksMountMonitor *monitor, - UDisksMount *mount, - gpointer user_data); -static void on_mount_monitor_mount_removed (UDisksMountMonitor *monitor, - UDisksMount *mount, - gpointer user_data); +/* ---------------------------------------------------------------------------------------------------- */ static void -udisks_linux_block_finalize (GObject *object) +udisks_linux_block_init (UDisksLinuxBlock *block) { - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (object); - - /* note: we don't hold a ref to block->daemon or block->mount_monitor */ - g_signal_handlers_disconnect_by_func (block->mount_monitor, on_mount_monitor_mount_added, block); - g_signal_handlers_disconnect_by_func (block->mount_monitor, on_mount_monitor_mount_removed, block); - - g_object_unref (block->device); - - if (block->iface_block_device != NULL) - g_object_unref (block->iface_block_device); - if (block->iface_filesystem != NULL) - g_object_unref (block->iface_filesystem); - if (block->iface_swapspace != NULL) - g_object_unref (block->iface_swapspace); - if (block->iface_encrypted != NULL) - g_object_unref (block->iface_encrypted); - if (block->iface_loop != NULL) - g_object_unref (block->iface_loop); - - if (G_OBJECT_CLASS (udisks_linux_block_parent_class)->finalize != NULL) - G_OBJECT_CLASS (udisks_linux_block_parent_class)->finalize (object); + g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (block), + G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD); } static void -udisks_linux_block_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +udisks_linux_block_class_init (UDisksLinuxBlockClass *klass) +{ +} + +/** + * udisks_linux_block_new: + * + * Creates a new #UDisksLinuxBlock instance. + * + * Returns: A new #UDisksLinuxBlock. Free with g_object_unref(). + */ +UDisksBlockDevice * +udisks_linux_block_new (void) +{ + return UDISKS_BLOCK_DEVICE (g_object_new (UDISKS_TYPE_LINUX_BLOCK, + NULL)); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static gchar * +get_sysfs_attr (GUdevDevice *device, + const gchar *attr) +{ + gchar *filename; + gchar *value; + filename = g_strconcat (g_udev_device_get_sysfs_path (device), + "/", + attr, + NULL); + value = NULL; + /* don't care about errors */ + g_file_get_contents (filename, + &value, + NULL, + NULL); + g_free (filename); + return value; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static gchar * +find_block_device_by_sysfs_path (GDBusObjectManagerServer *object_manager, + const gchar *sysfs_path) { - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (object); + gchar *ret; + GList *objects; + GList *l; + + ret = NULL; - switch (prop_id) + objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager)); + for (l = objects; l != NULL; l = l->next) { - case PROP_DAEMON: - g_value_set_object (value, udisks_linux_block_get_daemon (block)); - break; + GDBusObjectSkeleton *object = G_DBUS_OBJECT_SKELETON (l->data); + GUdevDevice *device; - case PROP_DEVICE: - g_value_set_object (value, udisks_linux_block_get_device (block)); - break; + if (!UDISKS_IS_LINUX_BLOCK_OBJECT (object)) + continue; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (object)); + if (g_strcmp0 (sysfs_path, g_udev_device_get_sysfs_path (device)) == 0) + { + ret = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); + g_object_unref (device); + goto out; + } + g_object_unref (device); } + + out: + g_list_foreach (objects, (GFunc) g_object_unref, NULL); + g_list_free (objects); + return ret; } -static void -udisks_linux_block_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +/* ---------------------------------------------------------------------------------------------------- */ + +static gchar * +find_drive (GDBusObjectManagerServer *object_manager, + GUdevDevice *block_device, + UDisksDrive **out_drive) { - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (object); + GUdevDevice *whole_disk_block_device; + const gchar *whole_disk_block_device_sysfs_path; + gchar *ret; + GList *objects; + GList *l; + + ret = NULL; - switch (prop_id) + if (g_strcmp0 (g_udev_device_get_devtype (block_device), "disk") == 0) + whole_disk_block_device = g_object_ref (block_device); + else + whole_disk_block_device = g_udev_device_get_parent_with_subsystem (block_device, "block", "disk"); + whole_disk_block_device_sysfs_path = g_udev_device_get_sysfs_path (whole_disk_block_device); + + objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager)); + for (l = objects; l != NULL; l = l->next) { - case PROP_DAEMON: - g_assert (block->daemon == NULL); - /* we don't take a reference to the daemon */ - block->daemon = g_value_get_object (value); - break; - - case PROP_DEVICE: - g_assert (block->device == NULL); - block->device = g_value_dup_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + GDBusObjectSkeleton *object = G_DBUS_OBJECT_SKELETON (l->data); + GList *drive_devices; + GList *j; + + if (!UDISKS_IS_LINUX_DRIVE_OBJECT (object)) + continue; + + drive_devices = udisks_linux_drive_object_get_devices (UDISKS_LINUX_DRIVE_OBJECT (object)); + for (j = drive_devices; j != NULL; j = j->next) + { + GUdevDevice *drive_device = G_UDEV_DEVICE (j->data); + const gchar *drive_sysfs_path; + + drive_sysfs_path = g_udev_device_get_sysfs_path (drive_device); + if (g_strcmp0 (whole_disk_block_device_sysfs_path, drive_sysfs_path) == 0) + { + if (out_drive != NULL) + *out_drive = udisks_object_get_drive (UDISKS_OBJECT (object)); + ret = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); + g_list_foreach (drive_devices, (GFunc) g_object_unref, NULL); + g_list_free (drive_devices); + goto out; + } + } + g_list_foreach (drive_devices, (GFunc) g_object_unref, NULL); + g_list_free (drive_devices); } + + out: + g_list_foreach (objects, (GFunc) g_object_unref, NULL); + g_list_free (objects); + g_object_unref (whole_disk_block_device); + return ret; } +/* ---------------------------------------------------------------------------------------------------- */ static void -udisks_linux_block_init (UDisksLinuxBlock *block) +update_hints (UDisksLinuxBlock *block, + GUdevDevice *device, + UDisksDrive *drive) { + UDisksBlockDevice *iface = UDISKS_BLOCK_DEVICE (block); + gboolean hint_system; + gboolean hint_ignore; + gboolean hint_auto; + const gchar *hint_name; + const gchar *hint_icon_name; + const gchar *device_file; + + /* very conservative defaults */ + hint_system = TRUE; + hint_ignore = FALSE; + hint_auto = FALSE; + hint_name = NULL; + hint_icon_name = NULL; + + device_file = g_udev_device_get_device_file (device); + + /* Provide easy access to _only_ the following devices + * + * - anything connected via known local buses (e.g. USB or Firewire, MMC or MemoryStick) + * - any device with removable media + * + * Be careful when extending this list as we don't want to automount + * the world when (inadvertently) connecting to a SAN. + */ + if (drive != NULL) + { + const gchar *connection_bus; + gboolean removable; + connection_bus = udisks_drive_get_connection_bus (drive); + removable = udisks_drive_get_media_removable (drive); + if (removable || + (g_strcmp0 (connection_bus, "usb") == 0 || g_strcmp0 (connection_bus, "firewire") == 0) || + (g_str_has_prefix (device_file, "/dev/mmcblk") || g_str_has_prefix (device_file, "/dev/mspblk"))) + { + hint_system = FALSE; + hint_auto = TRUE; + } + } + + /* TODO: set ignore to TRUE for physical paths belonging to a drive with multiple paths */ + + /* override from udev properties */ + if (g_udev_device_has_property (device, "UDISKS_SYSTEM")) + hint_system = g_udev_device_get_property_as_boolean (device, "UDISKS_SYSTEM"); + if (g_udev_device_has_property (device, "UDISKS_IGNORE")) + hint_ignore = g_udev_device_get_property_as_boolean (device, "UDISKS_IGNORE"); + if (g_udev_device_has_property (device, "UDISKS_AUTO")) + hint_auto = g_udev_device_get_property_as_boolean (device, "UDISKS_AUTO"); + if (g_udev_device_has_property (device, "UDISKS_NAME")) + hint_name = g_udev_device_get_property (device, "UDISKS_NAME"); + if (g_udev_device_has_property (device, "UDISKS_ICON_NAME")) + hint_icon_name = g_udev_device_get_property (device, "UDISKS_ICON_NAME"); + + /* ... and scene! */ + udisks_block_device_set_hint_system (iface, hint_system); + udisks_block_device_set_hint_ignore (iface, hint_ignore); + udisks_block_device_set_hint_auto (iface, hint_auto); + udisks_block_device_set_hint_name (iface, hint_name); + udisks_block_device_set_hint_icon_name (iface, hint_icon_name); } -static void -udisks_linux_block_constructed (GObject *object) +/* ---------------------------------------------------------------------------------------------------- */ + +static GList * +find_fstab_entries_for_device (UDisksLinuxBlock *block, + UDisksDaemon *daemon) { - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (object); - GString *str; + GList *entries; + GList *l; + GList *ret; + + ret = NULL; + + /* if this is too slow, we could add lookup methods to UDisksFstabMonitor... */ + entries = udisks_fstab_monitor_get_entries (udisks_daemon_get_fstab_monitor (daemon)); + for (l = entries; l != NULL; l = l->next) + { + UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data); + const gchar *const *symlinks; + const gchar *fsname; + gchar *device; + guint n; + + fsname = udisks_fstab_entry_get_fsname (entry); + device = NULL; + if (g_str_has_prefix (fsname, "UUID=")) + { + device = g_strdup_printf ("/dev/disk/by-uuid/%s", fsname + 5); + } + else if (g_str_has_prefix (fsname, "LABEL=")) + { + device = g_strdup_printf ("/dev/disk/by-label/%s", fsname + 6); + } + else if (g_str_has_prefix (fsname, "/dev")) + { + device = g_strdup (fsname); + } + else + { + /* ignore non-device entries */ + goto continue_loop; + } + + if (g_strcmp0 (device, udisks_block_device_get_device (UDISKS_BLOCK_DEVICE (block))) == 0) + { + ret = g_list_prepend (ret, g_object_ref (entry)); + } + else + { + symlinks = udisks_block_device_get_symlinks (UDISKS_BLOCK_DEVICE (block)); + if (symlinks != NULL) + { + for (n = 0; symlinks[n] != NULL; n++) + { + if (g_strcmp0 (device, symlinks[n]) == 0) + { + ret = g_list_prepend (ret, g_object_ref (entry)); + } + } + } + } - block->mount_monitor = udisks_daemon_get_mount_monitor (block->daemon); - g_signal_connect (block->mount_monitor, - "mount-added", - G_CALLBACK (on_mount_monitor_mount_added), - block); - g_signal_connect (block->mount_monitor, - "mount-removed", - G_CALLBACK (on_mount_monitor_mount_removed), - block); - - /* initial coldplug */ - udisks_linux_block_uevent (block, "add", NULL); - - /* compute the object path */ - str = g_string_new ("/org/freedesktop/UDisks2/block_devices/"); - udisks_safe_append_to_object_path (str, g_udev_device_get_name (block->device)); - g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (block), str->str); - g_string_free (str, TRUE); - - if (G_OBJECT_CLASS (udisks_linux_block_parent_class)->constructed != NULL) - G_OBJECT_CLASS (udisks_linux_block_parent_class)->constructed (object); + continue_loop: + g_free (device); + } + + g_list_foreach (entries, (GFunc) g_object_unref, NULL); + g_list_free (entries); + return ret; } -static void -udisks_linux_block_class_init (UDisksLinuxBlockClass *klass) +static GList * +find_crypttab_entries_for_device (UDisksLinuxBlock *block, + UDisksDaemon *daemon) { - GObjectClass *gobject_class; + GList *entries; + GList *l; + GList *ret; - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = udisks_linux_block_finalize; - gobject_class->constructed = udisks_linux_block_constructed; - gobject_class->set_property = udisks_linux_block_set_property; - gobject_class->get_property = udisks_linux_block_get_property; + ret = NULL; - /** - * UDisksLinuxBlock:daemon: - * - * The #UDisksDaemon the object is for. - */ - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The daemon the object is for", - UDISKS_TYPE_DAEMON, - G_PARAM_READABLE | - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - /** - * UDisksLinuxBlock:device: - * - * The #GUdevDevice for the object. Connect to the #GObject::notify - * signal to get notified whenever this is updated. - */ - g_object_class_install_property (gobject_class, - PROP_DEVICE, - g_param_spec_object ("device", - "Device", - "The device for the object", - G_UDEV_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + /* if this is too slow, we could add lookup methods to UDisksCrypttabMonitor... */ + entries = udisks_crypttab_monitor_get_entries (udisks_daemon_get_crypttab_monitor (daemon)); + for (l = entries; l != NULL; l = l->next) + { + UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data); + const gchar *const *symlinks; + const gchar *device_in_entry; + gchar *device; + guint n; + + device_in_entry = udisks_crypttab_entry_get_device (entry); + device = NULL; + if (g_str_has_prefix (device_in_entry, "UUID=")) + { + device = g_strdup_printf ("/dev/disk/by-uuid/%s", device_in_entry + 5); + } + else if (g_str_has_prefix (device_in_entry, "LABEL=")) + { + device = g_strdup_printf ("/dev/disk/by-label/%s", device_in_entry + 6); + } + else if (g_str_has_prefix (device_in_entry, "/dev")) + { + device = g_strdup (device_in_entry); + } + else + { + /* ignore non-device entries */ + goto continue_loop; + } + + if (g_strcmp0 (device, udisks_block_device_get_device (UDISKS_BLOCK_DEVICE (block))) == 0) + { + ret = g_list_prepend (ret, g_object_ref (entry)); + } + else + { + symlinks = udisks_block_device_get_symlinks (UDISKS_BLOCK_DEVICE (block)); + if (symlinks != NULL) + { + for (n = 0; symlinks[n] != NULL; n++) + { + if (g_strcmp0 (device, symlinks[n]) == 0) + { + ret = g_list_prepend (ret, g_object_ref (entry)); + } + } + } + } + + continue_loop: + g_free (device); + } + g_list_foreach (entries, (GFunc) g_object_unref, NULL); + g_list_free (entries); + return ret; } -/** - * udisks_linux_block_new: - * @daemon: A #UDisksDaemon. - * @device: The #GUdevDevice for the sysfs block device. - * - * Create a new block object. - * - * Returns: A #UDisksLinuxBlock object. Free with g_object_unref(). - */ -UDisksLinuxBlock * -udisks_linux_block_new (UDisksDaemon *daemon, - GUdevDevice *device) +/* returns a floating GVariant */ +static GVariant * +calculate_configuration (UDisksLinuxBlock *block, + UDisksDaemon *daemon, + gboolean include_secrets, + GError **error) { - g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL); - return UDISKS_LINUX_BLOCK (g_object_new (UDISKS_TYPE_LINUX_BLOCK, - "daemon", daemon, - "device", device, - NULL)); + GList *entries; + GList *l; + GVariantBuilder builder; + GVariant *ret; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + ret = NULL; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sa{sv})")); + /* First the /etc/fstab entries */ + entries = find_fstab_entries_for_device (block, daemon); + for (l = entries; l != NULL; l = l->next) + { + UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data); + GVariantBuilder dict_builder; + g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add (&dict_builder, "{sv}", "fsname", + g_variant_new_bytestring (udisks_fstab_entry_get_fsname (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "dir", + g_variant_new_bytestring (udisks_fstab_entry_get_dir (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "type", + g_variant_new_bytestring (udisks_fstab_entry_get_fstype (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "opts", + g_variant_new_bytestring (udisks_fstab_entry_get_opts (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "freq", + g_variant_new_int32 (udisks_fstab_entry_get_freq (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "passno", + g_variant_new_int32 (udisks_fstab_entry_get_passno (entry))); + g_variant_builder_add (&builder, + "(sa{sv})", + "fstab", &dict_builder); + } + g_list_foreach (entries, (GFunc) g_object_unref, NULL); + g_list_free (entries); + + /* Then the /etc/crypttab entries */ + entries = find_crypttab_entries_for_device (block, daemon); + for (l = entries; l != NULL; l = l->next) + { + UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data); + GVariantBuilder dict_builder; + const gchar *passphrase_path; + const gchar *options; + gchar *passphrase_contents; + gsize passphrase_contents_length; + + passphrase_path = udisks_crypttab_entry_get_passphrase_path (entry); + if (passphrase_path == NULL || g_strcmp0 (passphrase_path, "none") == 0) + passphrase_path = ""; + passphrase_contents = NULL; + if (!(g_strcmp0 (passphrase_path, "") == 0 || g_str_has_prefix (passphrase_path, "/dev"))) + { + if (include_secrets) + { + if (!g_file_get_contents (passphrase_path, + &passphrase_contents, + &passphrase_contents_length, + error)) + { + g_prefix_error (error, + "Error loading secrets from file `%s' referenced in /etc/crypttab entry: ", + passphrase_path); + g_variant_builder_clear (&builder); + g_list_foreach (entries, (GFunc) g_object_unref, NULL); + g_list_free (entries); + goto out; + } + } + } + + options = udisks_crypttab_entry_get_options (entry); + if (options == NULL) + options = ""; + + g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add (&dict_builder, "{sv}", "name", + g_variant_new_bytestring (udisks_crypttab_entry_get_name (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "device", + g_variant_new_bytestring (udisks_crypttab_entry_get_device (entry))); + g_variant_builder_add (&dict_builder, "{sv}", "passphrase-path", + g_variant_new_bytestring (passphrase_path)); + if (passphrase_contents != NULL) + { + g_variant_builder_add (&dict_builder, "{sv}", "passphrase-contents", + g_variant_new_bytestring (passphrase_contents)); + } + g_variant_builder_add (&dict_builder, "{sv}", "options", + g_variant_new_bytestring (options)); + g_variant_builder_add (&builder, + "(sa{sv})", + "crypttab", &dict_builder); + if (passphrase_contents != NULL) + { + memset (passphrase_contents, '\0', passphrase_contents_length); + g_free (passphrase_contents); + } + } + g_list_foreach (entries, (GFunc) g_object_unref, NULL); + g_list_free (entries); + + ret = g_variant_builder_end (&builder); + + out: + return ret; } -/** - * udisks_linux_block_get_daemon: - * @block: A #UDisksLinuxBlock. - * - * Gets the daemon used by @block. - * - * Returns: A #UDisksDaemon. Do not free, the object is owned by @block. - */ -UDisksDaemon * -udisks_linux_block_get_daemon (UDisksLinuxBlock *block) +static void +update_configuration (UDisksLinuxBlock *block, + UDisksDaemon *daemon) { - g_return_val_if_fail (UDISKS_IS_LINUX_BLOCK (block), NULL); - return block->daemon; + GVariant *configuration; + GError *error; + + error = NULL; + configuration = calculate_configuration (block, daemon, FALSE, &error); + if (configuration == NULL) + { + udisks_warning ("Error loading configuration: %s (%s, %d)", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + configuration = g_variant_new ("a(sa{sv})", NULL); + } + udisks_block_device_set_configuration (UDISKS_BLOCK_DEVICE (block), configuration); } +/* ---------------------------------------------------------------------------------------------------- */ + /** - * udisks_linux_block_get_device: + * udisks_linux_block_update: * @block: A #UDisksLinuxBlock. + * @object: The enclosing #UDisksLinuxBlockObject instance. * - * Gets the current #GUdevDevice for @block. Connect to - * #GObject::notify to track changes to the #UDisksLinuxBlock:device - * property. - * - * Returns: A #GUdevDevice. Free with g_object_unref(). + * Updates the interface. */ -GUdevDevice * -udisks_linux_block_get_device (UDisksLinuxBlock *block) +void +udisks_linux_block_update (UDisksLinuxBlock *block, + UDisksLinuxBlockObject *object) { - g_return_val_if_fail (UDISKS_IS_LINUX_BLOCK (block), NULL); - return g_object_ref (block->device); -} + UDisksBlockDevice *iface = UDISKS_BLOCK_DEVICE (block); + UDisksDaemon *daemon; + GDBusObjectManagerServer *object_manager; + GUdevDevice *device; + GUdevDeviceNumber dev; + gchar *drive_object_path; + UDisksDrive *drive; + gchar *s; + gboolean is_partition_table; + gboolean is_partition_entry; + const gchar *device_file; + const gchar *const *symlinks; + const gchar *preferred_device_file; -/* ---------------------------------------------------------------------------------------------------- */ + drive = NULL; -typedef gboolean (*HasInterfaceFunc) (UDisksLinuxBlock *block); -typedef void (*ConnectInterfaceFunc) (UDisksLinuxBlock *block); -typedef void (*UpdateInterfaceFunc) (UDisksLinuxBlock *block, - const gchar *uevent_action, - GDBusInterface *interface); + device = udisks_linux_block_object_get_device (object); + if (device == NULL) + goto out; -static void -update_iface (UDisksLinuxBlock *block, - const gchar *uevent_action, - HasInterfaceFunc has_func, - ConnectInterfaceFunc connect_func, - UpdateInterfaceFunc update_func, - GType skeleton_type, - gpointer _interface_pointer) -{ - gboolean has; - gboolean add; - GDBusInterface **interface_pointer = _interface_pointer; - - g_return_if_fail (block != NULL); - g_return_if_fail (has_func != NULL); - g_return_if_fail (update_func != NULL); - g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_OBJECT)); - g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_DBUS_INTERFACE)); - g_return_if_fail (interface_pointer != NULL); - g_return_if_fail (*interface_pointer == NULL || G_IS_DBUS_INTERFACE (*interface_pointer)); - - add = FALSE; - has = has_func (block); - if (*interface_pointer == NULL) + daemon = udisks_linux_block_object_get_daemon (object); + object_manager = udisks_daemon_get_object_manager (daemon); + + dev = g_udev_device_get_device_number (device); + device_file = g_udev_device_get_device_file (device); + symlinks = g_udev_device_get_device_file_symlinks (device); + + udisks_block_device_set_device (iface, device_file); + udisks_block_device_set_symlinks (iface, symlinks); + udisks_block_device_set_major (iface, major (dev)); + udisks_block_device_set_minor (iface, minor (dev)); + udisks_block_device_set_size (iface, udisks_daemon_util_block_get_size (device)); + + /* dm-crypt + * + * TODO: this might not be the best way to determine if the device-mapper device + * is a dm-crypt device.. but unfortunately device-mapper keeps all this stuff + * in user-space and wants you to use libdevmapper to obtain it... + */ + udisks_block_device_set_crypto_backing_device (iface, "/"); + if (g_str_has_prefix (g_udev_device_get_name (device), "dm-")) { - if (has) + gchar *dm_uuid; + dm_uuid = get_sysfs_attr (device, "dm/uuid"); + if (dm_uuid != NULL && g_str_has_prefix (dm_uuid, "CRYPT-LUKS1")) { - *interface_pointer = g_object_new (skeleton_type, NULL); - if (connect_func != NULL) - connect_func (block); - add = TRUE; + gchar **slaves; + slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device), + "slaves"); + if (g_strv_length (slaves) == 1) + { + gchar *slave_object_path; + slave_object_path = find_block_device_by_sysfs_path (object_manager, slaves[0]); + if (slave_object_path != NULL) + { + udisks_block_device_set_crypto_backing_device (iface, slave_object_path); + } + g_free (slave_object_path); + } + g_strfreev (slaves); } + g_free (dm_uuid); } - else + + /* Sort out preferred device... this is what UI shells should + * display. We default to the block device name. + * + * This is mostly for things like device-mapper where device file is + * a name of the form dm-%d and a symlink name conveys more + * information. + */ + preferred_device_file = NULL; + if (g_str_has_prefix (device_file, "/dev/dm-")) { - if (!has) + guint n; + const gchar *dm_name; + gchar *dm_name_dev_file = NULL; + const gchar *dm_name_dev_file_as_symlink = NULL; + + dm_name = g_udev_device_get_property (device, "DM_NAME"); + if (dm_name != NULL) + dm_name_dev_file = g_strdup_printf ("/dev/mapper/%s", dm_name); + for (n = 0; symlinks != NULL && symlinks[n] != NULL; n++) { - g_dbus_object_skeleton_remove_interface (G_DBUS_OBJECT_SKELETON (block), G_DBUS_INTERFACE_SKELETON (*interface_pointer)); - g_object_unref (*interface_pointer); - *interface_pointer = NULL; + if (g_str_has_prefix (symlinks[n], "/dev/vg_")) + { + /* LVM2 */ + preferred_device_file = symlinks[n]; + break; + } + else if (g_strcmp0 (symlinks[n], dm_name_dev_file) == 0) + { + dm_name_dev_file_as_symlink = symlinks[n]; + } } + /* fall back to /dev/mapper/$DM_NAME, if available as a symlink */ + if (preferred_device_file == NULL && dm_name_dev_file_as_symlink != NULL) + preferred_device_file = dm_name_dev_file_as_symlink; + g_free (dm_name_dev_file); + } + /* fallback to the device name */ + if (preferred_device_file == NULL) + preferred_device_file = g_udev_device_get_device_file (device); + udisks_block_device_set_preferred_device (iface, preferred_device_file); + + /* Determine the drive this block device belongs to + * + * TODO: if this is slow we could have a cache or ensure that we + * only do this once or something else + */ + drive_object_path = find_drive (object_manager, device, &drive); + if (drive_object_path != NULL) + { + udisks_block_device_set_drive (iface, drive_object_path); + g_free (drive_object_path); + } + else + { + udisks_block_device_set_drive (iface, "/"); + } + + udisks_block_device_set_id_usage (iface, g_udev_device_get_property (device, "ID_FS_USAGE")); + udisks_block_device_set_id_type (iface, g_udev_device_get_property (device, "ID_FS_TYPE")); + s = udisks_decode_udev_string (g_udev_device_get_property (device, "ID_FS_VERSION")); + udisks_block_device_set_id_version (iface, s); + g_free (s); + s = udisks_decode_udev_string (g_udev_device_get_property (device, "ID_FS_LABEL_ENC")); + udisks_block_device_set_id_label (iface, s); + g_free (s); + s = udisks_decode_udev_string (g_udev_device_get_property (device, "ID_FS_UUID_ENC")); + udisks_block_device_set_id_uuid (iface, s); + g_free (s); + + /* TODO: port this to blkid properties */ + + /* Update the partition table and partition entry properties */ + is_partition_table = FALSE; + is_partition_entry = FALSE; + if (g_strcmp0 (g_udev_device_get_devtype (device), "partition") == 0 || + g_udev_device_get_property_as_boolean (device, "UDISKS_PARTITION")) + { + is_partition_entry = TRUE; + } + else if (g_udev_device_get_property_as_boolean (device, "UDISKS_PARTITION_TABLE")) + { + is_partition_table = TRUE; + } + + /* partition table */ + if (is_partition_table) + { + udisks_block_device_set_part_table (iface, TRUE); + udisks_block_device_set_part_table_scheme (iface, + g_udev_device_get_property (device, + "UDISKS_PARTITION_TABLE_SCHEME")); + } + else + { + udisks_block_device_set_part_table (iface, FALSE); + udisks_block_device_set_part_table_scheme (iface, ""); } - if (*interface_pointer != NULL) + /* partition entry */ + if (is_partition_entry) + { + gchar *slave_sysfs_path; + udisks_block_device_set_part_entry (iface, TRUE); + udisks_block_device_set_part_entry_scheme (iface, + g_udev_device_get_property (device, + "UDISKS_PARTITION_SCHEME")); + udisks_block_device_set_part_entry_number (iface, + g_udev_device_get_property_as_int (device, + "UDISKS_PARTITION_NUMBER")); + udisks_block_device_set_part_entry_type (iface, + g_udev_device_get_property (device, + "UDISKS_PARTITION_TYPE")); + udisks_block_device_set_part_entry_flags (iface, + g_udev_device_get_property (device, + "UDISKS_PARTITION_FLAGS")); + udisks_block_device_set_part_entry_label (iface, + g_udev_device_get_property (device, + "UDISKS_PARTITION_LABEL")); + udisks_block_device_set_part_entry_uuid (iface, + g_udev_device_get_property (device, + "UDISKS_PARTITION_UUID")); + slave_sysfs_path = g_strdup (g_udev_device_get_property (device, "UDISKS_PARTITION_SLAVE")); + if (slave_sysfs_path == NULL) + { + if (g_strcmp0 (g_udev_device_get_devtype (device), "partition") == 0) + { + GUdevDevice *parent; + parent = g_udev_device_get_parent (device); + slave_sysfs_path = g_strdup (g_udev_device_get_sysfs_path (parent)); + g_object_unref (parent); + } + else + { + g_warning ("No UDISKS_PARTITION_SLAVE property and DEVTYPE is not partition for block device %s", + g_udev_device_get_sysfs_path (device)); + } + } + if (slave_sysfs_path != NULL) + { + gchar *slave_object_path; + slave_object_path = find_block_device_by_sysfs_path (object_manager, slave_sysfs_path); + if (slave_object_path != NULL) + udisks_block_device_set_part_entry_table (iface, slave_object_path); + else + udisks_block_device_set_part_entry_table (iface, "/"); + g_free (slave_object_path); + g_free (slave_sysfs_path); + } + else + { + udisks_block_device_set_part_entry_table (iface, "/"); + } + udisks_block_device_set_part_entry_offset (iface, + g_udev_device_get_property_as_uint64 (device, + "UDISKS_PARTITION_OFFSET")); + udisks_block_device_set_part_entry_size (iface, + g_udev_device_get_property_as_uint64 (device, + "UDISKS_PARTITION_SIZE")); + } + else { - update_func (block, uevent_action, G_DBUS_INTERFACE (*interface_pointer)); - if (add) - g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (block), G_DBUS_INTERFACE_SKELETON (*interface_pointer)); + udisks_block_device_set_part_entry (iface, FALSE); + udisks_block_device_set_part_entry_scheme (iface, ""); + udisks_block_device_set_part_entry_type (iface, ""); + udisks_block_device_set_part_entry_flags (iface, ""); + udisks_block_device_set_part_entry_table (iface, "/"); + udisks_block_device_set_part_entry_offset (iface, 0); + udisks_block_device_set_part_entry_size (iface, 0); } + + update_hints (block, device, drive); + update_configuration (block, daemon); + + out: + if (device != NULL) + g_object_unref (device); + if (drive != NULL) + g_object_unref (drive); } /* ---------------------------------------------------------------------------------------------------- */ -static GVariant *calculate_configuration (UDisksLinuxBlock *block, - gboolean include_secrets, - GError **error); - static gboolean -on_get_secret_configuration (UDisksBlockDevice *block, - GDBusMethodInvocation *invocation, - GVariant *options, - gpointer user_data) +handle_get_secret_configuration (UDisksBlockDevice *_block, + GDBusMethodInvocation *invocation, + GVariant *options) { - UDisksLinuxBlock *object = UDISKS_LINUX_BLOCK (user_data); + UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (_block); + UDisksLinuxBlockObject *object; + UDisksDaemon *daemon; GVariant *configuration; GError *error; + object = UDISKS_LINUX_BLOCK_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))); + daemon = udisks_linux_block_object_get_daemon (object); + error = NULL; - configuration = calculate_configuration (object, TRUE, &error); + configuration = calculate_configuration (block, daemon, TRUE, &error); if (configuration == NULL) { g_dbus_method_invocation_take_error (invocation, error); goto out; } - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.read-system-configuration-secrets", options, @@ -411,7 +856,8 @@ on_get_secret_configuration (UDisksBlockDevice *block, goto out; } - udisks_block_device_complete_get_secret_configuration (object->iface_block_device, invocation, + udisks_block_device_complete_get_secret_configuration (UDISKS_BLOCK_DEVICE (block), + invocation, configuration); /* consumes floating ref */ out: @@ -1002,22 +1448,25 @@ add_remove_crypttab_entry (GVariant *remove, /* ---------------------------------------------------------------------------------------------------- */ static gboolean -on_add_configuration_item (UDisksBlockDevice *block, - GDBusMethodInvocation *invocation, - GVariant *item, - GVariant *options, - gpointer user_data) +handle_add_configuration_item (UDisksBlockDevice *_block, + GDBusMethodInvocation *invocation, + GVariant *item, + GVariant *options) { - UDisksLinuxBlock *object = UDISKS_LINUX_BLOCK (user_data); + UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (_block); + UDisksLinuxBlockObject *object; + UDisksDaemon *daemon; const gchar *type; GVariant *details; GError *error; - g_variant_get (item, "(&s@a{sv})", &type, &details); + object = UDISKS_LINUX_BLOCK_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))); + daemon = udisks_linux_block_object_get_daemon (object); + g_variant_get (item, "(&s@a{sv})", &type, &details); if (g_strcmp0 (type, "fstab") == 0) { - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.modify-system-configuration", options, @@ -1030,11 +1479,11 @@ on_add_configuration_item (UDisksBlockDevice *block, g_dbus_method_invocation_take_error (invocation, error); goto out; } - udisks_block_device_complete_add_configuration_item (block, invocation); + udisks_block_device_complete_add_configuration_item (UDISKS_BLOCK_DEVICE (block), invocation); } else if (g_strcmp0 (type, "crypttab") == 0) { - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.modify-system-configuration", options, @@ -1047,7 +1496,7 @@ on_add_configuration_item (UDisksBlockDevice *block, g_dbus_method_invocation_take_error (invocation, error); goto out; } - udisks_block_device_complete_add_configuration_item (block, invocation); + udisks_block_device_complete_add_configuration_item (UDISKS_BLOCK_DEVICE (block), invocation); } else { @@ -1063,23 +1512,28 @@ on_add_configuration_item (UDisksBlockDevice *block, return TRUE; /* returning TRUE means that we handled the method invocation */ } +/* ---------------------------------------------------------------------------------------------------- */ + static gboolean -on_remove_configuration_item (UDisksBlockDevice *block, - GDBusMethodInvocation *invocation, - GVariant *item, - GVariant *options, - gpointer user_data) +handle_remove_configuration_item (UDisksBlockDevice *_block, + GDBusMethodInvocation *invocation, + GVariant *item, + GVariant *options) { - UDisksLinuxBlock *object = UDISKS_LINUX_BLOCK (user_data); + UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (_block); + UDisksLinuxBlockObject *object; + UDisksDaemon *daemon; const gchar *type; GVariant *details; GError *error; - g_variant_get (item, "(&s@a{sv})", &type, &details); + object = UDISKS_LINUX_BLOCK_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))); + daemon = udisks_linux_block_object_get_daemon (object); + g_variant_get (item, "(&s@a{sv})", &type, &details); if (g_strcmp0 (type, "fstab") == 0) { - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.modify-system-configuration", options, @@ -1092,11 +1546,11 @@ on_remove_configuration_item (UDisksBlockDevice *block, g_dbus_method_invocation_take_error (invocation, error); goto out; } - udisks_block_device_complete_add_configuration_item (block, invocation); + udisks_block_device_complete_add_configuration_item (UDISKS_BLOCK_DEVICE (block), invocation); } else if (g_strcmp0 (type, "crypttab") == 0) { - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.modify-system-configuration", options, @@ -1109,7 +1563,7 @@ on_remove_configuration_item (UDisksBlockDevice *block, g_dbus_method_invocation_take_error (invocation, error); goto out; } - udisks_block_device_complete_add_configuration_item (block, invocation); + udisks_block_device_complete_add_configuration_item (UDISKS_BLOCK_DEVICE (block), invocation); } else { @@ -1125,21 +1579,27 @@ on_remove_configuration_item (UDisksBlockDevice *block, return TRUE; /* returning TRUE means that we handled the method invocation */ } +/* ---------------------------------------------------------------------------------------------------- */ + static gboolean -on_update_configuration_item (UDisksBlockDevice *block, - GDBusMethodInvocation *invocation, - GVariant *old_item, - GVariant *new_item, - GVariant *options, - gpointer user_data) +handle_update_configuration_item (UDisksBlockDevice *_block, + GDBusMethodInvocation *invocation, + GVariant *old_item, + GVariant *new_item, + GVariant *options) { - UDisksLinuxBlock *object = UDISKS_LINUX_BLOCK (user_data); + UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (_block); + UDisksLinuxBlockObject *object; + UDisksDaemon *daemon; const gchar *old_type; const gchar *new_type; GVariant *old_details; GVariant *new_details; GError *error; + object = UDISKS_LINUX_BLOCK_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))); + daemon = udisks_linux_block_object_get_daemon (object); + g_variant_get (old_item, "(&s@a{sv})", &old_type, &old_details); g_variant_get (new_item, "(&s@a{sv})", &new_type, &new_details); if (g_strcmp0 (old_type, new_type) != 0) @@ -1153,7 +1613,7 @@ on_update_configuration_item (UDisksBlockDevice *block, if (g_strcmp0 (old_type, "fstab") == 0) { - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.modify-system-configuration", options, @@ -1166,11 +1626,11 @@ on_update_configuration_item (UDisksBlockDevice *block, g_dbus_method_invocation_take_error (invocation, error); goto out; } - udisks_block_device_complete_add_configuration_item (block, invocation); + udisks_block_device_complete_add_configuration_item (UDISKS_BLOCK_DEVICE (block), invocation); } else if (g_strcmp0 (old_type, "crypttab") == 0) { - if (!udisks_daemon_util_check_authorization_sync (object->daemon, + if (!udisks_daemon_util_check_authorization_sync (daemon, NULL, "org.freedesktop.udisks2.modify-system-configuration", options, @@ -1183,7 +1643,7 @@ on_update_configuration_item (UDisksBlockDevice *block, g_dbus_method_invocation_take_error (invocation, error); goto out; } - udisks_block_device_complete_add_configuration_item (block, invocation); + udisks_block_device_complete_add_configuration_item (UDISKS_BLOCK_DEVICE (block), invocation); } else { @@ -1201,968 +1661,12 @@ on_update_configuration_item (UDisksBlockDevice *block, } /* ---------------------------------------------------------------------------------------------------- */ -/* org.freedesktop.UDisks.BlockDevice */ - -static gboolean -block_device_check (UDisksLinuxBlock *block) -{ - return TRUE; -} - -static void -block_device_connect (UDisksLinuxBlock *block) -{ - g_signal_connect (block->iface_block_device, - "handle-get-secret-configuration", - G_CALLBACK (on_get_secret_configuration), - block); - g_signal_connect (block->iface_block_device, - "handle-add-configuration-item", - G_CALLBACK (on_add_configuration_item), - block); - g_signal_connect (block->iface_block_device, - "handle-remove-configuration-item", - G_CALLBACK (on_remove_configuration_item), - block); - g_signal_connect (block->iface_block_device, - "handle-update-configuration-item", - G_CALLBACK (on_update_configuration_item), - block); -} - -static gchar * -find_drive (GDBusObjectManagerServer *object_manager, - GUdevDevice *block_device, - UDisksDrive **out_drive) -{ - GUdevDevice *whole_disk_block_device; - const gchar *whole_disk_block_device_sysfs_path; - gchar *ret; - GList *objects; - GList *l; - - ret = NULL; - - if (g_strcmp0 (g_udev_device_get_devtype (block_device), "disk") == 0) - whole_disk_block_device = g_object_ref (block_device); - else - whole_disk_block_device = g_udev_device_get_parent_with_subsystem (block_device, "block", "disk"); - whole_disk_block_device_sysfs_path = g_udev_device_get_sysfs_path (whole_disk_block_device); - - objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager)); - for (l = objects; l != NULL; l = l->next) - { - GDBusObjectSkeleton *object = G_DBUS_OBJECT_SKELETON (l->data); - GList *drive_devices; - GList *j; - - if (!UDISKS_IS_LINUX_DRIVE_OBJECT (object)) - continue; - - drive_devices = udisks_linux_drive_object_get_devices (UDISKS_LINUX_DRIVE_OBJECT (object)); - for (j = drive_devices; j != NULL; j = j->next) - { - GUdevDevice *drive_device = G_UDEV_DEVICE (j->data); - const gchar *drive_sysfs_path; - - drive_sysfs_path = g_udev_device_get_sysfs_path (drive_device); - if (g_strcmp0 (whole_disk_block_device_sysfs_path, drive_sysfs_path) == 0) - { - if (out_drive != NULL) - *out_drive = udisks_object_get_drive (UDISKS_OBJECT (object)); - ret = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); - g_list_foreach (drive_devices, (GFunc) g_object_unref, NULL); - g_list_free (drive_devices); - goto out; - } - } - g_list_foreach (drive_devices, (GFunc) g_object_unref, NULL); - g_list_free (drive_devices); - } - - out: - g_list_foreach (objects, (GFunc) g_object_unref, NULL); - g_list_free (objects); - g_object_unref (whole_disk_block_device); - return ret; -} - -static gchar * -find_block_device_by_sysfs_path (GDBusObjectManagerServer *object_manager, - const gchar *sysfs_path) -{ - gchar *ret; - GList *objects; - GList *l; - - ret = NULL; - - objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager)); - for (l = objects; l != NULL; l = l->next) - { - GDBusObjectSkeleton *object = G_DBUS_OBJECT_SKELETON (l->data); - UDisksLinuxBlock *block; - - if (!UDISKS_IS_LINUX_BLOCK (object)) - continue; - - block = UDISKS_LINUX_BLOCK (object); - - if (g_strcmp0 (sysfs_path, g_udev_device_get_sysfs_path (block->device)) == 0) - { - ret = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); - goto out; - } - } - - out: - g_list_foreach (objects, (GFunc) g_object_unref, NULL); - g_list_free (objects); - return ret; -} - -static gchar * -get_sysfs_attr (GUdevDevice *device, - const gchar *attr) -{ - gchar *filename; - gchar *value; - filename = g_strconcat (g_udev_device_get_sysfs_path (device), - "/", - attr, - NULL); - value = NULL; - /* don't care about errors */ - g_file_get_contents (filename, - &value, - NULL, - NULL); - g_free (filename); - return value; -} - -static void -block_device_update_hints (UDisksLinuxBlock *block, - const gchar *uevent_action, - UDisksBlockDevice *iface, - const gchar *device_file, - UDisksDrive *drive) -{ - gboolean hint_system; - gboolean hint_ignore; - gboolean hint_auto; - const gchar *hint_name; - const gchar *hint_icon_name; - - /* very conservative defaults */ - hint_system = TRUE; - hint_ignore = FALSE; - hint_auto = FALSE; - hint_name = NULL; - hint_icon_name = NULL; - - /* Provide easy access to _only_ the following devices - * - * - anything connected via known local buses (e.g. USB or Firewire, MMC or MemoryStick) - * - any device with removable media - * - * Be careful when extending this list as we don't want to automount - * the world when (inadvertently) connecting to a SAN. - */ - if (drive != NULL) - { - const gchar *connection_bus; - gboolean removable; - connection_bus = udisks_drive_get_connection_bus (drive); - removable = udisks_drive_get_media_removable (drive); - if (removable || - (g_strcmp0 (connection_bus, "usb") == 0 || g_strcmp0 (connection_bus, "firewire") == 0) || - (g_str_has_prefix (device_file, "/dev/mmcblk") || g_str_has_prefix (device_file, "/dev/mspblk"))) - { - hint_system = FALSE; - hint_auto = TRUE; - } - } - - /* TODO: set ignore to TRUE for physical paths belonging to a drive with multiple paths */ - - /* override from udev properties */ - if (g_udev_device_has_property (block->device, "UDISKS_SYSTEM")) - hint_system = g_udev_device_get_property_as_boolean (block->device, "UDISKS_SYSTEM"); - if (g_udev_device_has_property (block->device, "UDISKS_IGNORE")) - hint_ignore = g_udev_device_get_property_as_boolean (block->device, "UDISKS_IGNORE"); - if (g_udev_device_has_property (block->device, "UDISKS_AUTO")) - hint_auto = g_udev_device_get_property_as_boolean (block->device, "UDISKS_AUTO"); - if (g_udev_device_has_property (block->device, "UDISKS_NAME")) - hint_name = g_udev_device_get_property (block->device, "UDISKS_NAME"); - if (g_udev_device_has_property (block->device, "UDISKS_ICON_NAME")) - hint_icon_name = g_udev_device_get_property (block->device, "UDISKS_ICON_NAME"); - - /* ... and scene! */ - udisks_block_device_set_hint_system (iface, hint_system); - udisks_block_device_set_hint_ignore (iface, hint_ignore); - udisks_block_device_set_hint_auto (iface, hint_auto); - udisks_block_device_set_hint_name (iface, hint_name); - udisks_block_device_set_hint_icon_name (iface, hint_icon_name); -} - -static GList * -find_fstab_entries_for_device (UDisksLinuxBlock *block) -{ - GList *entries; - GList *l; - GList *ret; - - ret = NULL; - - /* if this is too slow, we could add lookup methods to UDisksFstabMonitor... */ - entries = udisks_fstab_monitor_get_entries (udisks_daemon_get_fstab_monitor (block->daemon)); - for (l = entries; l != NULL; l = l->next) - { - UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data); - const gchar *const *symlinks; - const gchar *fsname; - gchar *device; - guint n; - - fsname = udisks_fstab_entry_get_fsname (entry); - device = NULL; - if (g_str_has_prefix (fsname, "UUID=")) - { - device = g_strdup_printf ("/dev/disk/by-uuid/%s", fsname + 5); - } - else if (g_str_has_prefix (fsname, "LABEL=")) - { - device = g_strdup_printf ("/dev/disk/by-label/%s", fsname + 6); - } - else if (g_str_has_prefix (fsname, "/dev")) - { - device = g_strdup (fsname); - } - else - { - /* ignore non-device entries */ - goto continue_loop; - } - - if (g_strcmp0 (device, udisks_block_device_get_device (block->iface_block_device)) == 0) - { - ret = g_list_prepend (ret, g_object_ref (entry)); - } - else - { - symlinks = udisks_block_device_get_symlinks (block->iface_block_device); - if (symlinks != NULL) - { - for (n = 0; symlinks[n] != NULL; n++) - { - if (g_strcmp0 (device, symlinks[n]) == 0) - { - ret = g_list_prepend (ret, g_object_ref (entry)); - } - } - } - } - - continue_loop: - g_free (device); - } - - g_list_foreach (entries, (GFunc) g_object_unref, NULL); - g_list_free (entries); - return ret; -} - -static GList * -find_crypttab_entries_for_device (UDisksLinuxBlock *block) -{ - GList *entries; - GList *l; - GList *ret; - - ret = NULL; - - /* if this is too slow, we could add lookup methods to UDisksCrypttabMonitor... */ - entries = udisks_crypttab_monitor_get_entries (udisks_daemon_get_crypttab_monitor (block->daemon)); - for (l = entries; l != NULL; l = l->next) - { - UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data); - const gchar *const *symlinks; - const gchar *device_in_entry; - gchar *device; - guint n; - - device_in_entry = udisks_crypttab_entry_get_device (entry); - device = NULL; - if (g_str_has_prefix (device_in_entry, "UUID=")) - { - device = g_strdup_printf ("/dev/disk/by-uuid/%s", device_in_entry + 5); - } - else if (g_str_has_prefix (device_in_entry, "LABEL=")) - { - device = g_strdup_printf ("/dev/disk/by-label/%s", device_in_entry + 6); - } - else if (g_str_has_prefix (device_in_entry, "/dev")) - { - device = g_strdup (device_in_entry); - } - else - { - /* ignore non-device entries */ - goto continue_loop; - } - - if (g_strcmp0 (device, udisks_block_device_get_device (block->iface_block_device)) == 0) - { - ret = g_list_prepend (ret, g_object_ref (entry)); - } - else - { - symlinks = udisks_block_device_get_symlinks (block->iface_block_device); - if (symlinks != NULL) - { - for (n = 0; symlinks[n] != NULL; n++) - { - if (g_strcmp0 (device, symlinks[n]) == 0) - { - ret = g_list_prepend (ret, g_object_ref (entry)); - } - } - } - } - - continue_loop: - g_free (device); - } - - g_list_foreach (entries, (GFunc) g_object_unref, NULL); - g_list_free (entries); - return ret; -} - -/* returns a floating GVariant */ -static GVariant * -calculate_configuration (UDisksLinuxBlock *block, - gboolean include_secrets, - GError **error) -{ - GList *entries; - GList *l; - GVariantBuilder builder; - GVariant *ret; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - ret = NULL; - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sa{sv})")); - /* First the /etc/fstab entries */ - entries = find_fstab_entries_for_device (block); - for (l = entries; l != NULL; l = l->next) - { - UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data); - GVariantBuilder dict_builder; - g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&dict_builder, "{sv}", "fsname", - g_variant_new_bytestring (udisks_fstab_entry_get_fsname (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "dir", - g_variant_new_bytestring (udisks_fstab_entry_get_dir (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "type", - g_variant_new_bytestring (udisks_fstab_entry_get_fstype (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "opts", - g_variant_new_bytestring (udisks_fstab_entry_get_opts (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "freq", - g_variant_new_int32 (udisks_fstab_entry_get_freq (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "passno", - g_variant_new_int32 (udisks_fstab_entry_get_passno (entry))); - g_variant_builder_add (&builder, - "(sa{sv})", - "fstab", &dict_builder); - } - g_list_foreach (entries, (GFunc) g_object_unref, NULL); - g_list_free (entries); - - /* Then the /etc/crypttab entries */ - entries = find_crypttab_entries_for_device (block); - for (l = entries; l != NULL; l = l->next) - { - UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data); - GVariantBuilder dict_builder; - const gchar *passphrase_path; - const gchar *options; - gchar *passphrase_contents; - gsize passphrase_contents_length; - - passphrase_path = udisks_crypttab_entry_get_passphrase_path (entry); - if (passphrase_path == NULL || g_strcmp0 (passphrase_path, "none") == 0) - passphrase_path = ""; - passphrase_contents = NULL; - if (!(g_strcmp0 (passphrase_path, "") == 0 || g_str_has_prefix (passphrase_path, "/dev"))) - { - if (include_secrets) - { - if (!g_file_get_contents (passphrase_path, - &passphrase_contents, - &passphrase_contents_length, - error)) - { - g_prefix_error (error, - "Error loading secrets from file `%s' referenced in /etc/crypttab entry: ", - passphrase_path); - g_variant_builder_clear (&builder); - g_list_foreach (entries, (GFunc) g_object_unref, NULL); - g_list_free (entries); - goto out; - } - } - } - - options = udisks_crypttab_entry_get_options (entry); - if (options == NULL) - options = ""; - - g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&dict_builder, "{sv}", "name", - g_variant_new_bytestring (udisks_crypttab_entry_get_name (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "device", - g_variant_new_bytestring (udisks_crypttab_entry_get_device (entry))); - g_variant_builder_add (&dict_builder, "{sv}", "passphrase-path", - g_variant_new_bytestring (passphrase_path)); - if (passphrase_contents != NULL) - { - g_variant_builder_add (&dict_builder, "{sv}", "passphrase-contents", - g_variant_new_bytestring (passphrase_contents)); - } - g_variant_builder_add (&dict_builder, "{sv}", "options", - g_variant_new_bytestring (options)); - g_variant_builder_add (&builder, - "(sa{sv})", - "crypttab", &dict_builder); - if (passphrase_contents != NULL) - { - memset (passphrase_contents, '\0', passphrase_contents_length); - g_free (passphrase_contents); - } - } - g_list_foreach (entries, (GFunc) g_object_unref, NULL); - g_list_free (entries); - - ret = g_variant_builder_end (&builder); - - out: - return ret; -} - -static void -block_device_update_configuration (UDisksLinuxBlock *block, - const gchar *uevent_action, - UDisksBlockDevice *iface, - const gchar *device_file, - UDisksDrive *drive) -{ - GVariant *configuration; - GError *error; - - error = NULL; - configuration = calculate_configuration (block, FALSE, &error); - if (configuration == NULL) - { - udisks_warning ("Error loading configuration: %s (%s, %d)", - error->message, g_quark_to_string (error->domain), error->code); - g_error_free (error); - configuration = g_variant_new ("a(sa{sv})", NULL); - } - udisks_block_device_set_configuration (block->iface_block_device, configuration); -} - -static void -block_device_update (UDisksLinuxBlock *block, - const gchar *uevent_action, - GDBusInterface *_iface) -{ - UDisksBlockDevice *iface = UDISKS_BLOCK_DEVICE (_iface); - GUdevDeviceNumber dev; - GDBusObjectManagerServer *object_manager; - gchar *drive_object_path; - UDisksDrive *drive; - gchar *s; - gboolean is_partition_table; - gboolean is_partition_entry; - const gchar *device_file; - const gchar *const *symlinks; - const gchar *preferred_device_file; - - drive = NULL; - - dev = g_udev_device_get_device_number (block->device); - device_file = g_udev_device_get_device_file (block->device); - symlinks = g_udev_device_get_device_file_symlinks (block->device); - - udisks_block_device_set_device (iface, device_file); - udisks_block_device_set_symlinks (iface, symlinks); - udisks_block_device_set_major (iface, major (dev)); - udisks_block_device_set_minor (iface, minor (dev)); - udisks_block_device_set_size (iface, udisks_daemon_util_block_get_size (block->device)); - - /* dm-crypt - * - * TODO: this might not be the best way to determine if the device-mapper device - * is a dm-crypt device.. but unfortunately device-mapper keeps all this stuff - * in user-space and wants you to use libdevmapper to obtain it... - */ - udisks_block_device_set_crypto_backing_device (iface, "/"); - if (g_str_has_prefix (g_udev_device_get_name (block->device), "dm-")) - { - gchar *dm_uuid; - dm_uuid = get_sysfs_attr (block->device, "dm/uuid"); - if (dm_uuid != NULL && g_str_has_prefix (dm_uuid, "CRYPT-LUKS1")) - { - gchar **slaves; - slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (block->device), - "slaves"); - if (g_strv_length (slaves) == 1) - { - gchar *slave_object_path; - slave_object_path = find_block_device_by_sysfs_path (udisks_daemon_get_object_manager (block->daemon), - slaves[0]); - if (slave_object_path != NULL) - { - udisks_block_device_set_crypto_backing_device (iface, slave_object_path); - } - g_free (slave_object_path); - } - g_strfreev (slaves); - } - g_free (dm_uuid); - } - - /* Sort out preferred device... this is what UI shells should - * display. We default to the block device name. - * - * This is mostly for things like device-mapper where device file is - * a name of the form dm-%d and a symlink name conveys more - * information. - */ - preferred_device_file = NULL; - if (g_str_has_prefix (device_file, "/dev/dm-")) - { - guint n; - const gchar *dm_name; - gchar *dm_name_dev_file = NULL; - const gchar *dm_name_dev_file_as_symlink = NULL; - - dm_name = g_udev_device_get_property (block->device, "DM_NAME"); - if (dm_name != NULL) - dm_name_dev_file = g_strdup_printf ("/dev/mapper/%s", dm_name); - for (n = 0; symlinks != NULL && symlinks[n] != NULL; n++) - { - if (g_str_has_prefix (symlinks[n], "/dev/vg_")) - { - /* LVM2 */ - preferred_device_file = symlinks[n]; - break; - } - else if (g_strcmp0 (symlinks[n], dm_name_dev_file) == 0) - { - dm_name_dev_file_as_symlink = symlinks[n]; - } - } - /* fall back to /dev/mapper/$DM_NAME, if available as a symlink */ - if (preferred_device_file == NULL && dm_name_dev_file_as_symlink != NULL) - preferred_device_file = dm_name_dev_file_as_symlink; - g_free (dm_name_dev_file); - } - /* fallback to the device name */ - if (preferred_device_file == NULL) - preferred_device_file = g_udev_device_get_device_file (block->device); - udisks_block_device_set_preferred_device (iface, preferred_device_file); - - /* Determine the drive this block device belongs to - * - * TODO: if this is slow we could have a cache or ensure that we - * only do this once or something else - */ - object_manager = udisks_daemon_get_object_manager (block->daemon); - drive_object_path = find_drive (object_manager, block->device, &drive); - if (drive_object_path != NULL) - { - udisks_block_device_set_drive (iface, drive_object_path); - g_free (drive_object_path); - } - else - { - udisks_block_device_set_drive (iface, "/"); - } - - udisks_block_device_set_id_usage (iface, g_udev_device_get_property (block->device, "ID_FS_USAGE")); - udisks_block_device_set_id_type (iface, g_udev_device_get_property (block->device, "ID_FS_TYPE")); - s = udisks_decode_udev_string (g_udev_device_get_property (block->device, "ID_FS_VERSION")); - udisks_block_device_set_id_version (iface, s); - g_free (s); - s = udisks_decode_udev_string (g_udev_device_get_property (block->device, "ID_FS_LABEL_ENC")); - udisks_block_device_set_id_label (iface, s); - g_free (s); - s = udisks_decode_udev_string (g_udev_device_get_property (block->device, "ID_FS_UUID_ENC")); - udisks_block_device_set_id_uuid (iface, s); - g_free (s); - - /* TODO: port this to blkid properties */ - - /* Update the partition table and partition entry properties */ - is_partition_table = FALSE; - is_partition_entry = FALSE; - if (g_strcmp0 (g_udev_device_get_devtype (block->device), "partition") == 0 || - g_udev_device_get_property_as_boolean (block->device, "UDISKS_PARTITION")) - { - is_partition_entry = TRUE; - } - else if (g_udev_device_get_property_as_boolean (block->device, "UDISKS_PARTITION_TABLE")) - { - is_partition_table = TRUE; - } - - /* partition table */ - if (is_partition_table) - { - udisks_block_device_set_part_table (iface, TRUE); - udisks_block_device_set_part_table_scheme (iface, - g_udev_device_get_property (block->device, - "UDISKS_PARTITION_TABLE_SCHEME")); - } - else - { - udisks_block_device_set_part_table (iface, FALSE); - udisks_block_device_set_part_table_scheme (iface, ""); - } - - /* partition entry */ - if (is_partition_entry) - { - gchar *slave_sysfs_path; - udisks_block_device_set_part_entry (iface, TRUE); - udisks_block_device_set_part_entry_scheme (iface, - g_udev_device_get_property (block->device, - "UDISKS_PARTITION_SCHEME")); - udisks_block_device_set_part_entry_number (iface, - g_udev_device_get_property_as_int (block->device, - "UDISKS_PARTITION_NUMBER")); - udisks_block_device_set_part_entry_type (iface, - g_udev_device_get_property (block->device, - "UDISKS_PARTITION_TYPE")); - udisks_block_device_set_part_entry_flags (iface, - g_udev_device_get_property (block->device, - "UDISKS_PARTITION_FLAGS")); - udisks_block_device_set_part_entry_label (iface, - g_udev_device_get_property (block->device, - "UDISKS_PARTITION_LABEL")); - udisks_block_device_set_part_entry_uuid (iface, - g_udev_device_get_property (block->device, - "UDISKS_PARTITION_UUID")); - slave_sysfs_path = g_strdup (g_udev_device_get_property (block->device, "UDISKS_PARTITION_SLAVE")); - if (slave_sysfs_path == NULL) - { - if (g_strcmp0 (g_udev_device_get_devtype (block->device), "partition") == 0) - { - GUdevDevice *parent; - parent = g_udev_device_get_parent (block->device); - slave_sysfs_path = g_strdup (g_udev_device_get_sysfs_path (parent)); - g_object_unref (parent); - } - else - { - g_warning ("No UDISKS_PARTITION_SLAVE property and DEVTYPE is not partition for block device %s", - g_udev_device_get_sysfs_path (block->device)); - } - } - if (slave_sysfs_path != NULL) - { - gchar *slave_object_path; - slave_object_path = find_block_device_by_sysfs_path (udisks_daemon_get_object_manager (block->daemon), - slave_sysfs_path); - if (slave_object_path != NULL) - udisks_block_device_set_part_entry_table (iface, slave_object_path); - else - udisks_block_device_set_part_entry_table (iface, "/"); - g_free (slave_object_path); - g_free (slave_sysfs_path); - } - else - { - udisks_block_device_set_part_entry_table (iface, "/"); - } - udisks_block_device_set_part_entry_offset (iface, - g_udev_device_get_property_as_uint64 (block->device, - "UDISKS_PARTITION_OFFSET")); - udisks_block_device_set_part_entry_size (iface, - g_udev_device_get_property_as_uint64 (block->device, - "UDISKS_PARTITION_SIZE")); - } - else - { - udisks_block_device_set_part_entry (iface, FALSE); - udisks_block_device_set_part_entry_scheme (iface, ""); - udisks_block_device_set_part_entry_type (iface, ""); - udisks_block_device_set_part_entry_flags (iface, ""); - udisks_block_device_set_part_entry_table (iface, "/"); - udisks_block_device_set_part_entry_offset (iface, 0); - udisks_block_device_set_part_entry_size (iface, 0); - } - - block_device_update_hints (block, uevent_action, iface, device_file, drive); - block_device_update_configuration (block, uevent_action, iface, device_file, drive); - - if (drive != NULL) - g_object_unref (drive); -} - -/* ---------------------------------------------------------------------------------------------------- */ -/* org.freedesktop.UDisks.Filesystem */ - -static gboolean -filesystem_check (UDisksLinuxBlock *block) -{ - gboolean ret; - UDisksMountType mount_type; - - ret = FALSE; - if (g_strcmp0 (udisks_block_device_get_id_usage (block->iface_block_device), "filesystem") == 0 || - (udisks_mount_monitor_is_dev_in_use (block->mount_monitor, - g_udev_device_get_device_number (block->device), - &mount_type) && - mount_type == UDISKS_MOUNT_TYPE_FILESYSTEM)) - ret = TRUE; - - return ret; -} - -static void -filesystem_update (UDisksLinuxBlock *block, - const gchar *uevent_action, - GDBusInterface *_iface) -{ - UDisksFilesystem *iface = UDISKS_FILESYSTEM (_iface); - GPtrArray *p; - GList *mounts; - GList *l; - - p = g_ptr_array_new (); - mounts = udisks_mount_monitor_get_mounts_for_dev (block->mount_monitor, - g_udev_device_get_device_number (block->device)); - /* we are guaranteed that the list is sorted so if there are - * multiple mounts we'll always get the same order - */ - for (l = mounts; l != NULL; l = l->next) - { - UDisksMount *mount = UDISKS_MOUNT (l->data); - if (udisks_mount_get_mount_type (mount) == UDISKS_MOUNT_TYPE_FILESYSTEM) - g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount)); - } - g_ptr_array_add (p, NULL); - udisks_filesystem_set_mount_points (iface, (const gchar *const *) p->pdata); - g_ptr_array_free (p, TRUE); - g_list_foreach (mounts, (GFunc) g_object_unref, NULL); - g_list_free (mounts); -} - -/* ---------------------------------------------------------------------------------------------------- */ -/* org.freedesktop.UDisks.Swapspace */ - -static gboolean -swapspace_check (UDisksLinuxBlock *block) -{ - gboolean ret; - UDisksMountType mount_type; - - ret = FALSE; - if ((g_strcmp0 (udisks_block_device_get_id_usage (block->iface_block_device), "other") == 0 && - g_strcmp0 (udisks_block_device_get_id_type (block->iface_block_device), "swap") == 0) - || (udisks_mount_monitor_is_dev_in_use (block->mount_monitor, - g_udev_device_get_device_number (block->device), - &mount_type) - && mount_type == UDISKS_MOUNT_TYPE_SWAP)) - ret = TRUE; - - return ret; -} - -static void -swapspace_connect (UDisksLinuxBlock *block) -{ - /* do nothing */ -} - -static void -swapspace_update (UDisksLinuxBlock *block, - const gchar *uevent_action, - GDBusInterface *_iface) -{ - UDisksSwapspace *iface = UDISKS_SWAPSPACE (_iface); - UDisksMountType mount_type; - gboolean active; - - active = FALSE; - if (udisks_mount_monitor_is_dev_in_use (block->mount_monitor, - g_udev_device_get_device_number (block->device), - &mount_type) - && mount_type == UDISKS_MOUNT_TYPE_SWAP) - active = TRUE; - udisks_swapspace_set_active (iface, active); -} - -/* ---------------------------------------------------------------------------------------------------- */ - -static gboolean -encrypted_check (UDisksLinuxBlock *block) -{ - gboolean ret; - - ret = FALSE; - if (g_strcmp0 (udisks_block_device_get_id_usage (block->iface_block_device), "crypto") == 0 && - g_strcmp0 (udisks_block_device_get_id_type (block->iface_block_device), "crypto_LUKS") == 0) - ret = TRUE; - - return ret; -} - -static void -encrypted_connect (UDisksLinuxBlock *block) -{ - /* do nothing */ -} - -static void -encrypted_update (UDisksLinuxBlock *block, - const gchar *uevent_action, - GDBusInterface *_iface) -{ - /* do nothing */ -} - -/* ---------------------------------------------------------------------------------------------------- */ - -static gboolean -loop_check (UDisksLinuxBlock *block) -{ - gboolean ret; - - ret = FALSE; - if (g_str_has_prefix (g_udev_device_get_name (block->device), "loop")) - ret = TRUE; - - return ret; -} - -static void -loop_connect (UDisksLinuxBlock *block) -{ - /* do nothing */ -} - -static void -loop_update (UDisksLinuxBlock *block, - const gchar *uevent_action, - GDBusInterface *_iface) -{ - UDisksLoop *iface = UDISKS_LOOP (_iface); - - if (g_str_has_prefix (g_udev_device_get_name (block->device), "loop")) - { - gchar *filename; - gchar *backing_file; - GError *error; - filename = g_strconcat (g_udev_device_get_sysfs_path (block->device), - "/loop/backing_file", - NULL); - error = NULL; - if (!g_file_get_contents (filename, - &backing_file, - NULL, - &error)) - { - /* ENOENT is not unexpected */ - if (!(error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)) - { - udisks_warning ("Error loading %s: %s (%s, %d)", - filename, - error->message, - g_quark_to_string (error->domain), - error->code); - } - g_error_free (error); - udisks_loop_set_backing_file (iface, ""); - } - else - { - /* TODO: validate UTF-8 */ - g_strstrip (backing_file); - udisks_loop_set_backing_file (iface, backing_file); - g_free (backing_file); - } - g_free (filename); - } - else - { - udisks_loop_set_backing_file (iface, ""); - } -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * udisks_linux_block_uevent: - * @block: A #UDisksLinuxBlock. - * @action: Uevent action or %NULL - * @device: A new #GUdevDevice device object or %NULL if the device hasn't changed. - * - * Updates all information on interfaces on @block. - */ -void -udisks_linux_block_uevent (UDisksLinuxBlock *block, - const gchar *action, - GUdevDevice *device) -{ - g_return_if_fail (UDISKS_IS_LINUX_BLOCK (block)); - g_return_if_fail (device == NULL || G_UDEV_IS_DEVICE (device)); - - if (device != NULL) - { - g_object_unref (block->device); - block->device = g_object_ref (device); - g_object_notify (G_OBJECT (block), "device"); - } - - update_iface (block, action, block_device_check, block_device_connect, block_device_update, - UDISKS_TYPE_BLOCK_DEVICE_SKELETON, &block->iface_block_device); - update_iface (block, action, filesystem_check, NULL, filesystem_update, - UDISKS_TYPE_LINUX_FILESYSTEM, &block->iface_filesystem); - update_iface (block, action, swapspace_check, swapspace_connect, swapspace_update, - UDISKS_TYPE_LINUX_SWAPSPACE, &block->iface_swapspace); - update_iface (block, action, encrypted_check, encrypted_connect, encrypted_update, - UDISKS_TYPE_LINUX_ENCRYPTED, &block->iface_encrypted); - update_iface (block, action, loop_check, loop_connect, loop_update, - UDISKS_TYPE_LINUX_LOOP, &block->iface_loop); -} - -/* ---------------------------------------------------------------------------------------------------- */ - -static void -on_mount_monitor_mount_added (UDisksMountMonitor *monitor, - UDisksMount *mount, - gpointer user_data) -{ - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (user_data); - if (udisks_mount_get_dev (mount) == g_udev_device_get_device_number (block->device)) - udisks_linux_block_uevent (block, NULL, NULL); -} static void -on_mount_monitor_mount_removed (UDisksMountMonitor *monitor, - UDisksMount *mount, - gpointer user_data) +block_iface_init (UDisksBlockDeviceIface *iface) { - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (user_data); - if (udisks_mount_get_dev (mount) == g_udev_device_get_device_number (block->device)) - udisks_linux_block_uevent (block, NULL, NULL); + iface->handle_get_secret_configuration = handle_get_secret_configuration; + iface->handle_add_configuration_item = handle_add_configuration_item; + iface->handle_remove_configuration_item = handle_remove_configuration_item; + iface->handle_update_configuration_item = handle_update_configuration_item; } - -/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/udiskslinuxblock.h b/src/udiskslinuxblock.h index 9e7fd5b..65ab632 100644 --- a/src/udiskslinuxblock.h +++ b/src/udiskslinuxblock.h @@ -22,22 +22,17 @@ #define __UDISKS_LINUX_BLOCK_H__ #include "udisksdaemontypes.h" -#include <gudev/gudev.h> G_BEGIN_DECLS -#define UDISKS_TYPE_LINUX_BLOCK (udisks_linux_block_get_type ()) -#define UDISKS_LINUX_BLOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_BLOCK, UDisksLinuxBlock)) -#define UDISKS_IS_LINUX_BLOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_BLOCK)) +#define UDISKS_TYPE_LINUX_BLOCK (udisks_linux_block_get_type ()) +#define UDISKS_LINUX_BLOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_BLOCK, UDisksLinuxBlock)) +#define UDISKS_IS_LINUX_BLOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_BLOCK)) -GType udisks_linux_block_get_type (void) G_GNUC_CONST; -UDisksLinuxBlock *udisks_linux_block_new (UDisksDaemon *daemon, - GUdevDevice *device); -void udisks_linux_block_uevent (UDisksLinuxBlock *block, - const gchar *action, - GUdevDevice *device); -UDisksDaemon *udisks_linux_block_get_daemon (UDisksLinuxBlock *block); -GUdevDevice *udisks_linux_block_get_device (UDisksLinuxBlock *block); +GType udisks_linux_block_get_type (void) G_GNUC_CONST; +UDisksBlockDevice *udisks_linux_block_new (void); +void udisks_linux_block_update (UDisksLinuxBlock *block, + UDisksLinuxBlockObject *object); G_END_DECLS diff --git a/src/udiskslinuxblockobject.c b/src/udiskslinuxblockobject.c new file mode 100644 index 0000000..e841dcf --- /dev/null +++ b/src/udiskslinuxblockobject.c @@ -0,0 +1,586 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include <glib/gi18n-lib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <pwd.h> +#include <grp.h> +#include <mntent.h> + +#include <string.h> +#include <stdlib.h> +#include <glib/gstdio.h> + +#include "udiskslogging.h" +#include "udisksdaemon.h" +#include "udisksdaemonutil.h" +#include "udiskslinuxblockobject.h" +#include "udiskslinuxblock.h" +#include "udisksmount.h" +#include "udisksmountmonitor.h" +#include "udiskslinuxdriveobject.h" +#include "udiskslinuxdrive.h" +#include "udiskslinuxfilesystem.h" +#include "udiskslinuxencrypted.h" +#include "udiskslinuxswapspace.h" +#include "udiskslinuxloop.h" +#include "udiskspersistentstore.h" +#include "udiskslinuxprovider.h" +#include "udisksfstabmonitor.h" +#include "udisksfstabentry.h" +#include "udiskscrypttabmonitor.h" +#include "udiskscrypttabentry.h" + +/** + * SECTION:udiskslinuxblockobject + * @title: UDisksLinuxBlockObject + * @short_description: Object representing a block device on Linux. + * + * Object corresponding to a block device on Linux. + */ + +typedef struct _UDisksLinuxBlockObjectClass UDisksLinuxBlockObjectClass; + +/** + * UDisksLinuxBlockObject: + * + * The #UDisksLinuxBlockObject structure contains only private data and + * should only be accessed using the provided API. + */ +struct _UDisksLinuxBlockObject +{ + UDisksObjectSkeleton parent_instance; + + UDisksDaemon *daemon; + UDisksMountMonitor *mount_monitor; + + GUdevDevice *device; + + /* interface */ + UDisksBlockDevice *iface_block_device; + UDisksFilesystem *iface_filesystem; + UDisksSwapspace *iface_swapspace; + UDisksEncrypted *iface_encrypted; + UDisksLoop *iface_loop; +}; + +struct _UDisksLinuxBlockObjectClass +{ + UDisksObjectSkeletonClass parent_class; +}; + +enum +{ + PROP_0, + PROP_DAEMON, + PROP_DEVICE +}; + +G_DEFINE_TYPE (UDisksLinuxBlockObject, udisks_linux_block_object, UDISKS_TYPE_OBJECT_SKELETON); + +static void on_mount_monitor_mount_added (UDisksMountMonitor *monitor, + UDisksMount *mount, + gpointer user_data); +static void on_mount_monitor_mount_removed (UDisksMountMonitor *monitor, + UDisksMount *mount, + gpointer user_data); + +static void +udisks_linux_block_object_finalize (GObject *_object) +{ + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (_object); + + /* note: we don't hold a ref to block->daemon or block->mount_monitor */ + g_signal_handlers_disconnect_by_func (object->mount_monitor, on_mount_monitor_mount_added, object); + g_signal_handlers_disconnect_by_func (object->mount_monitor, on_mount_monitor_mount_removed, object); + + g_object_unref (object->device); + + if (object->iface_block_device != NULL) + g_object_unref (object->iface_block_device); + if (object->iface_filesystem != NULL) + g_object_unref (object->iface_filesystem); + if (object->iface_swapspace != NULL) + g_object_unref (object->iface_swapspace); + if (object->iface_encrypted != NULL) + g_object_unref (object->iface_encrypted); + if (object->iface_loop != NULL) + g_object_unref (object->iface_loop); + + if (G_OBJECT_CLASS (udisks_linux_block_object_parent_class)->finalize != NULL) + G_OBJECT_CLASS (udisks_linux_block_object_parent_class)->finalize (_object); +} + +static void +udisks_linux_block_object_get_property (GObject *_object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (_object); + + switch (prop_id) + { + case PROP_DAEMON: + g_value_set_object (value, udisks_linux_block_object_get_daemon (object)); + break; + + case PROP_DEVICE: + g_value_set_object (value, udisks_linux_block_object_get_device (object)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec); + break; + } +} + +static void +udisks_linux_block_object_set_property (GObject *_object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (_object); + + switch (prop_id) + { + case PROP_DAEMON: + g_assert (object->daemon == NULL); + /* we don't take a reference to the daemon */ + object->daemon = g_value_get_object (value); + break; + + case PROP_DEVICE: + g_assert (object->device == NULL); + object->device = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec); + break; + } +} + + +static void +udisks_linux_block_object_init (UDisksLinuxBlockObject *object) +{ +} + +static void +udisks_linux_block_object_constructed (GObject *_object) +{ + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (_object); + GString *str; + + object->mount_monitor = udisks_daemon_get_mount_monitor (object->daemon); + g_signal_connect (object->mount_monitor, + "mount-added", + G_CALLBACK (on_mount_monitor_mount_added), + object); + g_signal_connect (object->mount_monitor, + "mount-removed", + G_CALLBACK (on_mount_monitor_mount_removed), + object); + + /* initial coldplug */ + udisks_linux_block_object_uevent (object, "add", NULL); + + /* compute the object path */ + str = g_string_new ("/org/freedesktop/UDisks2/block_devices/"); + udisks_safe_append_to_object_path (str, g_udev_device_get_name (object->device)); + g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), str->str); + g_string_free (str, TRUE); + + if (G_OBJECT_CLASS (udisks_linux_block_object_parent_class)->constructed != NULL) + G_OBJECT_CLASS (udisks_linux_block_object_parent_class)->constructed (_object); +} + +static void +udisks_linux_block_object_class_init (UDisksLinuxBlockObjectClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = udisks_linux_block_object_finalize; + gobject_class->constructed = udisks_linux_block_object_constructed; + gobject_class->set_property = udisks_linux_block_object_set_property; + gobject_class->get_property = udisks_linux_block_object_get_property; + + /** + * UDisksLinuxBlockObject:daemon: + * + * The #UDisksDaemon the object is for. + */ + g_object_class_install_property (gobject_class, + PROP_DAEMON, + g_param_spec_object ("daemon", + "Daemon", + "The daemon the object is for", + UDISKS_TYPE_DAEMON, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * UDisksLinuxBlockObject:device: + * + * The #GUdevDevice for the object. Connect to the #GObject::notify + * signal to get notified whenever this is updated. + */ + g_object_class_install_property (gobject_class, + PROP_DEVICE, + g_param_spec_object ("device", + "Device", + "The device for the object", + G_UDEV_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + +} + +/** + * udisks_linux_block_object_new: + * @daemon: A #UDisksDaemon. + * @device: The #GUdevDevice for the sysfs block device. + * + * Create a new block object. + * + * Returns: A #UDisksLinuxBlockObject object. Free with g_object_unref(). + */ +UDisksLinuxBlockObject * +udisks_linux_block_object_new (UDisksDaemon *daemon, + GUdevDevice *device) +{ + g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL); + return UDISKS_LINUX_BLOCK_OBJECT (g_object_new (UDISKS_TYPE_LINUX_BLOCK_OBJECT, + "daemon", daemon, + "device", device, + NULL)); +} + +/** + * udisks_linux_block_object_get_daemon: + * @object: A #UDisksLinuxBlockObject. + * + * Gets the daemon used by @object. + * + * Returns: A #UDisksDaemon. Do not free, the object is owned by @object. + */ +UDisksDaemon * +udisks_linux_block_object_get_daemon (UDisksLinuxBlockObject *object) +{ + g_return_val_if_fail (UDISKS_IS_LINUX_BLOCK_OBJECT (object), NULL); + return object->daemon; +} + +/** + * udisks_linux_block_object_get_device: + * @object: A #UDisksLinuxBlockObject. + * + * Gets the current #GUdevDevice for @object. Connect to + * #GObject::notify to track changes to the #UDisksLinuxBlockObject:device + * property. + * + * Returns: A #GUdevDevice. Free with g_object_unref(). + */ +GUdevDevice * +udisks_linux_block_object_get_device (UDisksLinuxBlockObject *object) +{ + g_return_val_if_fail (UDISKS_IS_LINUX_BLOCK_OBJECT (object), NULL); + return g_object_ref (object->device); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +typedef gboolean (*HasInterfaceFunc) (UDisksLinuxBlockObject *object); +typedef void (*ConnectInterfaceFunc) (UDisksLinuxBlockObject *object); +typedef void (*UpdateInterfaceFunc) (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + GDBusInterface *interface); + +static void +update_iface (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + HasInterfaceFunc has_func, + ConnectInterfaceFunc connect_func, + UpdateInterfaceFunc update_func, + GType skeleton_type, + gpointer _interface_pointer) +{ + gboolean has; + gboolean add; + GDBusInterface **interface_pointer = _interface_pointer; + + g_return_if_fail (object != NULL); + g_return_if_fail (has_func != NULL); + g_return_if_fail (update_func != NULL); + g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_OBJECT)); + g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_DBUS_INTERFACE)); + g_return_if_fail (interface_pointer != NULL); + g_return_if_fail (*interface_pointer == NULL || G_IS_DBUS_INTERFACE (*interface_pointer)); + + add = FALSE; + has = has_func (object); + if (*interface_pointer == NULL) + { + if (has) + { + *interface_pointer = g_object_new (skeleton_type, NULL); + if (connect_func != NULL) + connect_func (object); + add = TRUE; + } + } + else + { + if (!has) + { + g_dbus_object_skeleton_remove_interface (G_DBUS_OBJECT_SKELETON (object), + G_DBUS_INTERFACE_SKELETON (*interface_pointer)); + g_object_unref (*interface_pointer); + *interface_pointer = NULL; + } + } + + if (*interface_pointer != NULL) + { + update_func (object, uevent_action, G_DBUS_INTERFACE (*interface_pointer)); + if (add) + g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object), + G_DBUS_INTERFACE_SKELETON (*interface_pointer)); + } +} + +/* ---------------------------------------------------------------------------------------------------- */ +/* org.freedesktop.UDisks.BlockDevice */ + +static gboolean +block_device_check (UDisksLinuxBlockObject *object) +{ + return TRUE; +} + +static void +block_device_connect (UDisksLinuxBlockObject *object) +{ +} + +static void +block_device_update (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + GDBusInterface *_iface) +{ + udisks_linux_block_update (UDISKS_LINUX_BLOCK (_iface), object); +} + +/* ---------------------------------------------------------------------------------------------------- */ +/* org.freedesktop.UDisks.Filesystem */ + +static gboolean +filesystem_check (UDisksLinuxBlockObject *object) +{ + gboolean ret; + UDisksMountType mount_type; + + ret = FALSE; + if (g_strcmp0 (udisks_block_device_get_id_usage (object->iface_block_device), "filesystem") == 0 || + (udisks_mount_monitor_is_dev_in_use (object->mount_monitor, + g_udev_device_get_device_number (object->device), + &mount_type) && + mount_type == UDISKS_MOUNT_TYPE_FILESYSTEM)) + ret = TRUE; + + return ret; +} + + +static void +filesystem_connect (UDisksLinuxBlockObject *object) +{ +} + +static void +filesystem_update (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + GDBusInterface *_iface) +{ + udisks_linux_filesystem_update (UDISKS_LINUX_FILESYSTEM (_iface), object); +} + +/* ---------------------------------------------------------------------------------------------------- */ +/* org.freedesktop.UDisks.Swapspace */ + +static gboolean +swapspace_check (UDisksLinuxBlockObject *object) +{ + gboolean ret; + UDisksMountType mount_type; + + ret = FALSE; + if ((g_strcmp0 (udisks_block_device_get_id_usage (object->iface_block_device), "other") == 0 && + g_strcmp0 (udisks_block_device_get_id_type (object->iface_block_device), "swap") == 0) + || (udisks_mount_monitor_is_dev_in_use (object->mount_monitor, + g_udev_device_get_device_number (object->device), + &mount_type) + && mount_type == UDISKS_MOUNT_TYPE_SWAP)) + ret = TRUE; + + return ret; +} + +static void +swapspace_connect (UDisksLinuxBlockObject *object) +{ +} + +static void +swapspace_update (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + GDBusInterface *_iface) +{ + udisks_linux_swapspace_update (UDISKS_LINUX_SWAPSPACE (_iface), object); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +encrypted_check (UDisksLinuxBlockObject *object) +{ + gboolean ret; + + ret = FALSE; + if (g_strcmp0 (udisks_block_device_get_id_usage (object->iface_block_device), "crypto") == 0 && + g_strcmp0 (udisks_block_device_get_id_type (object->iface_block_device), "crypto_LUKS") == 0) + ret = TRUE; + + return ret; +} + +static void +encrypted_connect (UDisksLinuxBlockObject *object) +{ +} + +static void +encrypted_update (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + GDBusInterface *_iface) +{ + udisks_linux_encrypted_update (UDISKS_LINUX_ENCRYPTED (_iface), object); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +loop_check (UDisksLinuxBlockObject *object) +{ + gboolean ret; + + ret = FALSE; + if (g_str_has_prefix (g_udev_device_get_name (object->device), "loop")) + ret = TRUE; + + return ret; +} + +static void +loop_connect (UDisksLinuxBlockObject *object) +{ +} + +static void +loop_update (UDisksLinuxBlockObject *object, + const gchar *uevent_action, + GDBusInterface *_iface) +{ + udisks_linux_loop_update (UDISKS_LINUX_LOOP (_iface), object); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +/** + * udisks_linux_block_object_uevent: + * @object: A #UDisksLinuxBlockObject. + * @action: Uevent action or %NULL + * @device: A new #GUdevDevice device object or %NULL if the device hasn't changed. + * + * Updates all information on interfaces on @object. + */ +void +udisks_linux_block_object_uevent (UDisksLinuxBlockObject *object, + const gchar *action, + GUdevDevice *device) +{ + g_return_if_fail (UDISKS_IS_LINUX_BLOCK_OBJECT (object)); + g_return_if_fail (device == NULL || G_UDEV_IS_DEVICE (device)); + + if (device != NULL) + { + g_object_unref (object->device); + object->device = g_object_ref (device); + g_object_notify (G_OBJECT (object), "device"); + } + + update_iface (object, action, block_device_check, block_device_connect, block_device_update, + UDISKS_TYPE_LINUX_BLOCK, &object->iface_block_device); + update_iface (object, action, filesystem_check, filesystem_connect, filesystem_update, + UDISKS_TYPE_LINUX_FILESYSTEM, &object->iface_filesystem); + update_iface (object, action, swapspace_check, swapspace_connect, swapspace_update, + UDISKS_TYPE_LINUX_SWAPSPACE, &object->iface_swapspace); + update_iface (object, action, encrypted_check, encrypted_connect, encrypted_update, + UDISKS_TYPE_LINUX_ENCRYPTED, &object->iface_encrypted); + update_iface (object, action, loop_check, loop_connect, loop_update, + UDISKS_TYPE_LINUX_LOOP, &object->iface_loop); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +on_mount_monitor_mount_added (UDisksMountMonitor *monitor, + UDisksMount *mount, + gpointer user_data) +{ + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (user_data); + if (udisks_mount_get_dev (mount) == g_udev_device_get_device_number (object->device)) + udisks_linux_block_object_uevent (object, NULL, NULL); +} + +static void +on_mount_monitor_mount_removed (UDisksMountMonitor *monitor, + UDisksMount *mount, + gpointer user_data) +{ + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (user_data); + if (udisks_mount_get_dev (mount) == g_udev_device_get_device_number (object->device)) + udisks_linux_block_object_uevent (object, NULL, NULL); +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/udiskslinuxblockobject.h b/src/udiskslinuxblockobject.h new file mode 100644 index 0000000..78abaf0 --- /dev/null +++ b/src/udiskslinuxblockobject.h @@ -0,0 +1,44 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __UDISKS_LINUX_BLOCK_OBJECT_H__ +#define __UDISKS_LINUX_BLOCK_OBJECT_H__ + +#include "udisksdaemontypes.h" +#include <gudev/gudev.h> + +G_BEGIN_DECLS + +#define UDISKS_TYPE_LINUX_BLOCK_OBJECT (udisks_linux_block_object_get_type ()) +#define UDISKS_LINUX_BLOCK_OBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_BLOCK_OBJECT, UDisksLinuxBlockObject)) +#define UDISKS_IS_LINUX_BLOCK_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_BLOCK_OBJECT)) + +GType udisks_linux_block_object_get_type (void) G_GNUC_CONST; +UDisksLinuxBlockObject *udisks_linux_block_object_new (UDisksDaemon *daemon, + GUdevDevice *device); +void udisks_linux_block_object_uevent (UDisksLinuxBlockObject *object, + const gchar *action, + GUdevDevice *device); +UDisksDaemon *udisks_linux_block_object_get_daemon (UDisksLinuxBlockObject *object); +GUdevDevice *udisks_linux_block_object_get_device (UDisksLinuxBlockObject *object); + +G_END_DECLS + +#endif /* __UDISKS_LINUX_BLOCK_OBJECT_H__ */ diff --git a/src/udiskslinuxdrive.c b/src/udiskslinuxdrive.c index 9a6db9a..e0002ef 100644 --- a/src/udiskslinuxdrive.c +++ b/src/udiskslinuxdrive.c @@ -35,7 +35,7 @@ #include "udiskslinuxprovider.h" #include "udiskslinuxdriveobject.h" #include "udiskslinuxdrive.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udisksdaemon.h" #include "udiskscleanup.h" #include "udisksdaemonutil.h" @@ -474,7 +474,7 @@ handle_eject (UDisksDrive *_drive, { UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (_drive); UDisksLinuxDriveObject *object; - UDisksLinuxBlock *block_object; + UDisksLinuxBlockObject *block_object; UDisksBlockDevice *block; UDisksDaemon *daemon; const gchar *action_id; diff --git a/src/udiskslinuxdriveata.c b/src/udiskslinuxdriveata.c index 00104f3..0d55f99 100644 --- a/src/udiskslinuxdriveata.c +++ b/src/udiskslinuxdriveata.c @@ -37,7 +37,7 @@ #include "udiskslinuxprovider.h" #include "udiskslinuxdriveobject.h" #include "udiskslinuxdriveata.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udisksdaemon.h" #include "udiskscleanup.h" #include "udisksdaemonutil.h" @@ -297,7 +297,7 @@ handle_smart_update (UDisksDriveAta *_drive, { UDisksLinuxDriveAta *drive = UDISKS_LINUX_DRIVE_ATA (_drive); UDisksLinuxDriveObject *object; - UDisksLinuxBlock *block_object; + UDisksLinuxBlockObject *block_object; UDisksBlockDevice *block; UDisksDaemon *daemon; const gchar *action_id; diff --git a/src/udiskslinuxdriveobject.c b/src/udiskslinuxdriveobject.c index 0956419..2874429 100644 --- a/src/udiskslinuxdriveobject.c +++ b/src/udiskslinuxdriveobject.c @@ -32,7 +32,7 @@ #include "udiskslinuxdriveobject.h" #include "udiskslinuxdrive.h" #include "udiskslinuxdriveata.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" /** * SECTION:udiskslinuxdriveobject @@ -417,12 +417,12 @@ udisks_linux_drive_object_get_device (UDisksLinuxDriveObject *object, * Returns: A #UDisksLinuxBlockObject or %NULL. The returned object * must be freed with g_object_unref(). */ -UDisksLinuxBlock * +UDisksLinuxBlockObject * udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object, gboolean get_hw) { GDBusObjectManagerServer *object_manager; - UDisksLinuxBlock *ret; + UDisksLinuxBlockObject *ret; GList *objects; GList *l; @@ -439,10 +439,10 @@ udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object, GUdevDevice *device; gboolean is_disk; - if (!UDISKS_IS_LINUX_BLOCK (iter_object)) + if (!UDISKS_IS_LINUX_BLOCK_OBJECT (iter_object)) continue; - device = udisks_linux_block_get_device (UDISKS_LINUX_BLOCK (iter_object)); + device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (iter_object)); is_disk = (g_strcmp0 (g_udev_device_get_devtype (device), "disk") == 0); g_object_unref (device); @@ -462,7 +462,6 @@ udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object, g_list_foreach (objects, (GFunc) g_object_unref, NULL); g_list_free (objects); return ret; - } /* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/udiskslinuxdriveobject.h b/src/udiskslinuxdriveobject.h index 289bffc..193feb4 100644 --- a/src/udiskslinuxdriveobject.h +++ b/src/udiskslinuxdriveobject.h @@ -40,7 +40,7 @@ UDisksDaemon *udisks_linux_drive_object_get_daemon (UDisksLinuxDriv GList *udisks_linux_drive_object_get_devices (UDisksLinuxDriveObject *object); GUdevDevice *udisks_linux_drive_object_get_device (UDisksLinuxDriveObject *object, gboolean get_hw); -UDisksLinuxBlock *udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object, +UDisksLinuxBlockObject *udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object, gboolean get_hw); gboolean udisks_linux_drive_object_housekeeping (UDisksLinuxDriveObject *object, diff --git a/src/udiskslinuxencrypted.c b/src/udiskslinuxencrypted.c index 7dba4d3..336817e 100644 --- a/src/udiskslinuxencrypted.c +++ b/src/udiskslinuxencrypted.c @@ -31,7 +31,7 @@ #include "udiskslogging.h" #include "udiskslinuxencrypted.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udisksdaemon.h" #include "udiskspersistentstore.h" #include "udisksdaemonutil.h" @@ -96,6 +96,21 @@ udisks_linux_encrypted_new (void) return UDISKS_ENCRYPTED (g_object_new (UDISKS_TYPE_LINUX_ENCRYPTED, NULL)); } +/* ---------------------------------------------------------------------------------------------------- */ + +/** + * udisks_linux_encrypted_update: + * @encrypted: A #UDisksLinuxEncrypted. + * @object: The enclosing #UDisksLinuxBlockObject instance. + * + * Updates the interface. + */ +void +udisks_linux_encrypted_update (UDisksLinuxEncrypted *encrypted, + UDisksLinuxBlockObject *object) +{ + /* do nothing */ +} /* ---------------------------------------------------------------------------------------------------- */ @@ -211,7 +226,7 @@ handle_unlock (UDisksEncrypted *encrypted, object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (encrypted))); block = udisks_object_peek_block_device (object); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); cleanup = udisks_daemon_get_cleanup (daemon); /* TODO: check if the device is mentioned in /etc/crypttab (see crypttab(5)) - if so use that @@ -346,7 +361,7 @@ handle_unlock (UDisksEncrypted *encrypted, udisks_block_device_get_device (block), udisks_block_device_get_device (cleartext_block)); - udev_cleartext_device = udisks_linux_block_get_device (UDISKS_LINUX_BLOCK (cleartext_object)); + udev_cleartext_device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (cleartext_object)); /* update the unlocked-luks file */ if (!udisks_cleanup_add_unlocked_luks (cleanup, @@ -411,7 +426,7 @@ handle_lock (UDisksEncrypted *encrypted, object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (encrypted))); block = udisks_object_peek_block_device (object); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); cleanup = udisks_daemon_get_cleanup (daemon); /* TODO: check if the device is mentioned in /etc/crypttab (see crypttab(5)) - if so use that @@ -497,7 +512,7 @@ handle_lock (UDisksEncrypted *encrypted, goto out; } - device = udisks_linux_block_get_device (UDISKS_LINUX_BLOCK (cleartext_object)); + device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (cleartext_object)); escaped_name = g_strescape (g_udev_device_get_sysfs_attr (device, "dm/name"), NULL); if (cleartext_device_from_file != 0) diff --git a/src/udiskslinuxencrypted.h b/src/udiskslinuxencrypted.h index 042d496..a27b42a 100644 --- a/src/udiskslinuxencrypted.h +++ b/src/udiskslinuxencrypted.h @@ -31,6 +31,8 @@ G_BEGIN_DECLS GType udisks_linux_encrypted_get_type (void) G_GNUC_CONST; UDisksEncrypted *udisks_linux_encrypted_new (void); +void udisks_linux_encrypted_update (UDisksLinuxEncrypted *encrypted, + UDisksLinuxBlockObject *object); G_END_DECLS diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c index 72d0a7a..1d32b60 100644 --- a/src/udiskslinuxfilesystem.c +++ b/src/udiskslinuxfilesystem.c @@ -33,10 +33,12 @@ #include "udiskslogging.h" #include "udiskslinuxfilesystem.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udisksdaemon.h" #include "udiskscleanup.h" #include "udisksdaemonutil.h" +#include "udisksmountmonitor.h" +#include "udisksmount.h" /** * SECTION:udiskslinuxfilesystem @@ -100,6 +102,48 @@ udisks_linux_filesystem_new (void) /* ---------------------------------------------------------------------------------------------------- */ +/** + * udisks_linux_filesystem_update: + * @filesystem: A #UDisksLinuxFilesystem. + * @object: The enclosing #UDisksLinuxBlockObject instance. + * + * Updates the interface. + */ +void +udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, + UDisksLinuxBlockObject *object) +{ + UDisksMountMonitor *mount_monitor; + GUdevDevice *device; + GPtrArray *p; + GList *mounts; + GList *l; + + mount_monitor = udisks_daemon_get_mount_monitor (udisks_linux_block_object_get_daemon (object)); + device = udisks_linux_block_object_get_device (object); + + p = g_ptr_array_new (); + mounts = udisks_mount_monitor_get_mounts_for_dev (mount_monitor, g_udev_device_get_device_number (device)); + /* we are guaranteed that the list is sorted so if there are + * multiple mounts we'll always get the same order + */ + for (l = mounts; l != NULL; l = l->next) + { + UDisksMount *mount = UDISKS_MOUNT (l->data); + if (udisks_mount_get_mount_type (mount) == UDISKS_MOUNT_TYPE_FILESYSTEM) + g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount)); + } + g_ptr_array_add (p, NULL); + udisks_filesystem_set_mount_points (UDISKS_FILESYSTEM (filesystem), + (const gchar *const *) p->pdata); + g_ptr_array_free (p, TRUE); + g_list_foreach (mounts, (GFunc) g_object_unref, NULL); + g_list_free (mounts); + g_object_unref (device); +} + +/* ---------------------------------------------------------------------------------------------------- */ + typedef struct { const gchar *fstype; @@ -784,7 +828,7 @@ handle_mount (UDisksFilesystem *filesystem, object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (filesystem))); block = udisks_object_peek_block_device (object); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); cleanup = udisks_daemon_get_cleanup (daemon); /* check if mount point is managed by e.g. /etc/fstab or similar */ @@ -1104,7 +1148,7 @@ handle_unmount (UDisksFilesystem *filesystem, object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (filesystem))); block = udisks_object_peek_block_device (object); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); cleanup = udisks_daemon_get_cleanup (daemon); system_managed = FALSE; @@ -1394,7 +1438,7 @@ handle_set_label (UDisksFilesystem *filesystem, escaped_label = NULL; object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (filesystem))); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); block = udisks_object_peek_block_device (object); probed_fs_usage = udisks_block_device_get_id_usage (block); diff --git a/src/udiskslinuxfilesystem.h b/src/udiskslinuxfilesystem.h index 73afea4..cee47c6 100644 --- a/src/udiskslinuxfilesystem.h +++ b/src/udiskslinuxfilesystem.h @@ -31,6 +31,8 @@ G_BEGIN_DECLS GType udisks_linux_filesystem_get_type (void) G_GNUC_CONST; UDisksFilesystem *udisks_linux_filesystem_new (void); +void udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, + UDisksLinuxBlockObject *object); G_END_DECLS diff --git a/src/udiskslinuxloop.c b/src/udiskslinuxloop.c index 61d42f6..1790cbb 100644 --- a/src/udiskslinuxloop.c +++ b/src/udiskslinuxloop.c @@ -31,7 +31,7 @@ #include "udiskslogging.h" #include "udiskslinuxloop.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udisksdaemon.h" #include "udiskscleanup.h" #include "udisksdaemonutil.h" @@ -98,6 +98,61 @@ udisks_linux_loop_new (void) /* ---------------------------------------------------------------------------------------------------- */ +/** + * udisks_linux_loop_update: + * @loop: A #UDisksLinuxLoop. + * @object: The enclosing #UDisksLinuxBlockObject instance. + * + * Updates the interface. + */ +void +udisks_linux_loop_update (UDisksLinuxLoop *loop, + UDisksLinuxBlockObject *object) +{ + GUdevDevice *device; + device = udisks_linux_block_object_get_device (object); + if (g_str_has_prefix (g_udev_device_get_name (device), "loop")) + { + gchar *filename; + gchar *backing_file; + GError *error; + filename = g_strconcat (g_udev_device_get_sysfs_path (device), "/loop/backing_file", NULL); + error = NULL; + if (!g_file_get_contents (filename, + &backing_file, + NULL, + &error)) + { + /* ENOENT is not unexpected */ + if (!(error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)) + { + udisks_warning ("Error loading %s: %s (%s, %d)", + filename, + error->message, + g_quark_to_string (error->domain), + error->code); + } + g_error_free (error); + udisks_loop_set_backing_file (UDISKS_LOOP (loop), ""); + } + else + { + /* TODO: validate UTF-8 */ + g_strstrip (backing_file); + udisks_loop_set_backing_file (UDISKS_LOOP (loop), backing_file); + g_free (backing_file); + } + g_free (filename); + } + else + { + udisks_loop_set_backing_file (UDISKS_LOOP (loop), ""); + } + g_object_unref (device); +} + +/* ---------------------------------------------------------------------------------------------------- */ + /* runs in thread dedicated to handling @invocation */ static gboolean handle_delete (UDisksLoop *loop, @@ -121,7 +176,7 @@ handle_delete (UDisksLoop *loop, object = g_object_ref (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (loop)))); block = udisks_object_peek_block_device (object); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); cleanup = udisks_daemon_get_cleanup (daemon); error = NULL; diff --git a/src/udiskslinuxloop.h b/src/udiskslinuxloop.h index f8dfcba..21eacd5 100644 --- a/src/udiskslinuxloop.h +++ b/src/udiskslinuxloop.h @@ -31,6 +31,8 @@ G_BEGIN_DECLS GType udisks_linux_loop_get_type (void) G_GNUC_CONST; UDisksLoop *udisks_linux_loop_new (void); +void udisks_linux_loop_update (UDisksLinuxLoop *loop, + UDisksLinuxBlockObject *object); G_END_DECLS diff --git a/src/udiskslinuxprovider.c b/src/udiskslinuxprovider.c index 9a0fbca..76893e3 100644 --- a/src/udiskslinuxprovider.c +++ b/src/udiskslinuxprovider.c @@ -27,7 +27,7 @@ #include "udisksdaemon.h" #include "udisksprovider.h" #include "udiskslinuxprovider.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udiskslinuxdriveobject.h" #include "udiskslinuxmanager.h" #include "udiskscleanup.h" @@ -57,7 +57,7 @@ struct _UDisksLinuxProvider UDisksObjectSkeleton *manager_object; - /* maps from sysfs path to UDisksLinuxBlock objects */ + /* maps from sysfs path to UDisksLinuxBlockObject objects */ GHashTable *sysfs_to_block; /* maps from VPD (serial, wwn) and sysfs_path to UDisksLinuxDriveObject instances */ @@ -395,7 +395,7 @@ handle_block_uevent_for_block (UDisksLinuxProvider *provider, GUdevDevice *device) { const gchar *sysfs_path; - UDisksLinuxBlock *block; + UDisksLinuxBlockObject *object; UDisksDaemon *daemon; daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider)); @@ -403,27 +403,27 @@ handle_block_uevent_for_block (UDisksLinuxProvider *provider, if (g_strcmp0 (action, "remove") == 0) { - block = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); - if (block != NULL) + object = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); + if (object != NULL) { g_dbus_object_manager_server_unexport (udisks_daemon_get_object_manager (daemon), - g_dbus_object_get_object_path (G_DBUS_OBJECT (block))); + g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); g_warn_if_fail (g_hash_table_remove (provider->sysfs_to_block, sysfs_path)); } } else { - block = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); - if (block != NULL) + object = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); + if (object != NULL) { - udisks_linux_block_uevent (block, action, device); + udisks_linux_block_object_uevent (object, action, device); } else { - block = udisks_linux_block_new (daemon, device); + object = udisks_linux_block_object_new (daemon, device); g_dbus_object_manager_server_export_uniquely (udisks_daemon_get_object_manager (daemon), - G_DBUS_OBJECT_SKELETON (block)); - g_hash_table_insert (provider->sysfs_to_block, g_strdup (sysfs_path), block); + G_DBUS_OBJECT_SKELETON (object)); + g_hash_table_insert (provider->sysfs_to_block, g_strdup (sysfs_path), object); } } } @@ -434,9 +434,9 @@ handle_block_uevent (UDisksLinuxProvider *provider, const gchar *action, GUdevDevice *device) { - /* We use the sysfs block device for both UDisksLinuxDriveObject and BlockDevice - * objects. Ensure that drive are added before and removed after - * BlockDevice + /* We use the sysfs block device for both UDisksLinuxDriveObject and + * UDisksLinuxBlockObject objects. Ensure that drive objects are + * added before and removed after block objects. */ if (g_strcmp0 (action, "remove") == 0) { @@ -571,24 +571,24 @@ on_housekeeping_timeout (gpointer user_data) /* ---------------------------------------------------------------------------------------------------- */ static void -update_all_block_devices (UDisksLinuxProvider *provider) +update_all_block_objects (UDisksLinuxProvider *provider) { - GList *block_devices; + GList *objects; GList *l; G_LOCK (provider_lock); - block_devices = g_hash_table_get_values (provider->sysfs_to_block); - g_list_foreach (block_devices, (GFunc) g_object_ref, NULL); + objects = g_hash_table_get_values (provider->sysfs_to_block); + g_list_foreach (objects, (GFunc) g_object_ref, NULL); G_UNLOCK (provider_lock); - for (l = block_devices; l != NULL; l = l->next) + for (l = objects; l != NULL; l = l->next) { - UDisksLinuxBlock *block = UDISKS_LINUX_BLOCK (l->data); - udisks_linux_block_uevent (block, "change", NULL); + UDisksLinuxBlockObject *object = UDISKS_LINUX_BLOCK_OBJECT (l->data); + udisks_linux_block_object_uevent (object, "change", NULL); } - g_list_foreach (block_devices, (GFunc) g_object_unref, NULL); - g_list_free (block_devices); + g_list_foreach (objects, (GFunc) g_object_unref, NULL); + g_list_free (objects); } static void @@ -597,7 +597,7 @@ fstab_monitor_on_entry_added (UDisksFstabMonitor *monitor, gpointer user_data) { UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data); - update_all_block_devices (provider); + update_all_block_objects (provider); } static void @@ -606,7 +606,7 @@ fstab_monitor_on_entry_removed (UDisksFstabMonitor *monitor, gpointer user_data) { UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data); - update_all_block_devices (provider); + update_all_block_objects (provider); } static void @@ -615,7 +615,7 @@ crypttab_monitor_on_entry_added (UDisksCrypttabMonitor *monitor, gpointer user_data) { UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data); - update_all_block_devices (provider); + update_all_block_objects (provider); } static void @@ -624,5 +624,5 @@ crypttab_monitor_on_entry_removed (UDisksCrypttabMonitor *monitor, gpointer user_data) { UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data); - update_all_block_devices (provider); + update_all_block_objects (provider); } diff --git a/src/udiskslinuxswapspace.c b/src/udiskslinuxswapspace.c index 32ae054..9499bb2 100644 --- a/src/udiskslinuxswapspace.c +++ b/src/udiskslinuxswapspace.c @@ -31,10 +31,11 @@ #include "udiskslogging.h" #include "udiskslinuxswapspace.h" -#include "udiskslinuxblock.h" +#include "udiskslinuxblockobject.h" #include "udisksdaemon.h" #include "udiskscleanup.h" #include "udisksdaemonutil.h" +#include "udisksmountmonitor.h" /** * SECTION:udiskslinuxswapspace @@ -98,6 +99,36 @@ udisks_linux_swapspace_new (void) /* ---------------------------------------------------------------------------------------------------- */ +/** + * udisks_linux_swapspace_update: + * @swapspace: A #UDisksLinuxSwapspace. + * @object: The enclosing #UDisksLinuxBlockObject instance. + * + * Updates the interface. + */ +void +udisks_linux_swapspace_update (UDisksLinuxSwapspace *swapspace, + UDisksLinuxBlockObject *object) +{ + UDisksMountMonitor *mount_monitor; + GUdevDevice *device; + UDisksMountType mount_type; + gboolean active; + + mount_monitor = udisks_daemon_get_mount_monitor (udisks_linux_block_object_get_daemon (object)); + device = udisks_linux_block_object_get_device (object); + + active = FALSE; + if (udisks_mount_monitor_is_dev_in_use (mount_monitor, g_udev_device_get_device_number (device), &mount_type) && + mount_type == UDISKS_MOUNT_TYPE_SWAP) + active = TRUE; + udisks_swapspace_set_active (UDISKS_SWAPSPACE (swapspace), active); + + g_object_unref (device); +} + +/* ---------------------------------------------------------------------------------------------------- */ + static void swapspace_start_on_job_completed (UDisksJob *job, @@ -129,7 +160,7 @@ handle_start (UDisksSwapspace *swapspace, UDisksBaseJob *job; object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace))); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); block = udisks_object_peek_block_device (object); if (!udisks_daemon_util_check_authorization_sync (daemon, @@ -186,7 +217,7 @@ handle_stop (UDisksSwapspace *swapspace, UDisksBaseJob *job; object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace))); - daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object)); + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); block = udisks_object_peek_block_device (object); /* Now, check that the user is actually authorized to stop the swap space. diff --git a/src/udiskslinuxswapspace.h b/src/udiskslinuxswapspace.h index bfe13ad..45c9942 100644 --- a/src/udiskslinuxswapspace.h +++ b/src/udiskslinuxswapspace.h @@ -31,6 +31,8 @@ G_BEGIN_DECLS GType udisks_linux_swapspace_get_type (void) G_GNUC_CONST; UDisksSwapspace *udisks_linux_swapspace_new (void); +void udisks_linux_swapspace_update (UDisksLinuxSwapspace *swapspace, + UDisksLinuxBlockObject *object); G_END_DECLS |