export properties about cryptotext LUKS devices
authorDavid Zeuthen <davidz@redhat.com>
Sun, 15 Feb 2009 05:45:36 +0000 (00:45 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Sun, 15 Feb 2009 05:45:36 +0000 (00:45 -0500)
The properties are named luks-holder and device-is-luks.

Also make sure that all slaves and holders arrays are always up to
date (since the kernel still doesn't send 'change' events). To avoid
cycles, mark a device as being updated and clear all these flags in an
idle handler later.

src/devkit-disks-daemon.c
src/devkit-disks-daemon.h
src/devkit-disks-device-private.h
src/devkit-disks-device.c
src/org.freedesktop.DeviceKit.Disks.Device.xml
tools/devkit-disks.c

index 7f68f4c..5bf36cc 100644 (file)
@@ -593,6 +593,7 @@ devkit_disks_daemon_finalize (GObject *object)
                 g_hash_table_unref (daemon->priv->map_object_path_to_device);
         }
 
+
         if (daemon->priv->mount_monitor != NULL) {
                 g_object_unref (daemon->priv->mount_monitor);
         }
@@ -1034,16 +1035,19 @@ devkit_disks_daemon_new (void)
         GError *error = NULL;
         GList *devices;
         GList *l;
+        DevkitDisksDevice *device;
+        GHashTableIter device_iter;
         const char *subsystems[] = {"block", NULL};
 
         daemon = DEVKIT_DISKS_DAEMON (g_object_new (DEVKIT_TYPE_DISKS_DAEMON, NULL));
 
+
+
         if (!register_disks_daemon (DEVKIT_DISKS_DAEMON (daemon))) {
                 g_object_unref (daemon);
-                return NULL;
+                goto error;
         }
 
-
         devices = devkit_client_enumerate_by_subsystem (daemon->priv->devkit_client,
                                                          subsystems,
                                                          &error);
@@ -1051,7 +1055,7 @@ devkit_disks_daemon_new (void)
                 g_warning ("Cannot enumerate devices: %s", error->message);
                 g_error_free (error);
                 g_object_unref (daemon);
-                return NULL;
+                goto error;
         }
         for (l = devices; l != NULL; l = l->next) {
                 DevkitDevice *device = l->data;
@@ -1060,6 +1064,14 @@ devkit_disks_daemon_new (void)
         g_list_foreach (devices, (GFunc) g_object_unref, NULL);
         g_list_free (devices);
 
+        /* now refresh data for all devices just added to get slave/holder relationships
+         * properly initialized
+         */
+        g_hash_table_iter_init (&device_iter, daemon->priv->map_object_path_to_device);
+        while (g_hash_table_iter_next (&device_iter, NULL, (gpointer) &device)) {
+                devkit_disks_daemon_local_synthesize_changed (daemon, device->priv->d);
+        }
+
         /* clean stale directories in /media as well as stale
          * entries in /var/lib/DeviceKit-disks/mtab
          */
@@ -1071,6 +1083,9 @@ devkit_disks_daemon_new (void)
         refresh_smart_data (daemon);
 
         return daemon;
+
+ error:
+        return NULL;
 }
 
 DevkitDisksLogger *
index aa60340..134f98f 100644 (file)
@@ -90,12 +90,16 @@ DevkitDisksDaemon *devkit_disks_daemon_new                 (void);
 /* local methods */
 
 GList             *devkit_disks_daemon_local_get_all_devices     (DevkitDisksDaemon       *daemon);
+
 DevkitDisksDevice *devkit_disks_daemon_local_find_by_native_path (DevkitDisksDaemon       *daemon,
                                                                   const char              *native_path);
+
 DevkitDisksDevice *devkit_disks_daemon_local_find_by_object_path (DevkitDisksDaemon       *daemon,
                                                                   const char              *object_path);
+
 PolKitCaller      *devkit_disks_damon_local_get_caller_for_context (DevkitDisksDaemon     *daemon,
                                                                     DBusGMethodInvocation *context);
+
 gboolean           devkit_disks_damon_local_check_auth             (DevkitDisksDaemon     *daemon,
                                                                     PolKitCaller          *pk_caller,
                                                                     const char            *action_id,
index 31d9cbc..89f3a34 100644 (file)
@@ -81,6 +81,8 @@ struct DevkitDisksDevicePrivate
 
         guint linux_md_poll_timeout_id;
 
+        gboolean is_updated;
+
         struct {
                 char *device_file;
                 GPtrArray *device_file_by_id;
@@ -93,6 +95,7 @@ struct DevkitDisksDevicePrivate
                 gboolean device_is_read_only;
                 gboolean device_is_drive;
                 gboolean device_is_optical_disc;
+                gboolean device_is_luks;
                 gboolean device_is_luks_cleartext;
                 gboolean device_is_linux_md_component;
                 gboolean device_is_linux_md;
@@ -144,6 +147,8 @@ struct DevkitDisksDevicePrivate
                 guint optical_disc_num_tracks;
                 guint optical_disc_num_sessions;
 
+                char *luks_holder;
+
                 char *luks_cleartext_slave;
                 uid_t luks_cleartext_unlocked_by_uid;
 
index 58c655c..b92155d 100644 (file)
@@ -129,6 +129,7 @@ enum
         PROP_DEVICE_IS_READ_ONLY,
         PROP_DEVICE_IS_DRIVE,
         PROP_DEVICE_IS_OPTICAL_DISC,
+        PROP_DEVICE_IS_LUKS,
         PROP_DEVICE_IS_LUKS_CLEARTEXT,
         PROP_DEVICE_IS_LINUX_MD_COMPONENT,
         PROP_DEVICE_IS_LINUX_MD,
@@ -170,6 +171,8 @@ enum
         PROP_PARTITION_TABLE_OFFSETS,
         PROP_PARTITION_TABLE_SIZES,
 
+        PROP_LUKS_HOLDER,
+
         PROP_LUKS_CLEARTEXT_SLAVE,
         PROP_LUKS_CLEARTEXT_UNLOCKED_BY_UID,
 
@@ -299,6 +302,9 @@ get_property (GObject         *object,
        case PROP_DEVICE_IS_OPTICAL_DISC:
                g_value_set_boolean (value, device->priv->info.device_is_optical_disc);
                break;
+       case PROP_DEVICE_IS_LUKS:
+               g_value_set_boolean (value, device->priv->info.device_is_luks);
+               break;
        case PROP_DEVICE_IS_LUKS_CLEARTEXT:
                g_value_set_boolean (value, device->priv->info.device_is_luks_cleartext);
                break;
@@ -416,6 +422,13 @@ get_property (GObject         *object,
                g_value_set_boxed (value, device->priv->info.partition_table_sizes);
                break;
 
+       case PROP_LUKS_HOLDER:
+                if (device->priv->info.luks_holder != NULL)
+                        g_value_set_boxed (value, device->priv->info.luks_holder);
+                else
+                        g_value_set_boxed (value, "/");
+               break;
+
        case PROP_LUKS_CLEARTEXT_SLAVE:
                 if (device->priv->info.luks_cleartext_slave != NULL)
                         g_value_set_boxed (value, device->priv->info.luks_cleartext_slave);
@@ -657,6 +670,10 @@ devkit_disks_device_class_init (DevkitDisksDeviceClass *klass)
                 g_param_spec_boolean ("device-is-optical-disc", NULL, NULL, FALSE, G_PARAM_READABLE));
         g_object_class_install_property (
                 object_class,
+                PROP_DEVICE_IS_LUKS,
+                g_param_spec_boolean ("device-is-luks", NULL, NULL, FALSE, G_PARAM_READABLE));
+        g_object_class_install_property (
+                object_class,
                 PROP_DEVICE_IS_LUKS_CLEARTEXT,
                 g_param_spec_boolean ("device-is-luks-cleartext", NULL, NULL, FALSE, G_PARAM_READABLE));
         g_object_class_install_property (
@@ -812,6 +829,11 @@ devkit_disks_device_class_init (DevkitDisksDeviceClass *klass)
 
         g_object_class_install_property (
                 object_class,
+                PROP_LUKS_HOLDER,
+                g_param_spec_boxed ("luks-holder", NULL, NULL, DBUS_TYPE_G_OBJECT_PATH, G_PARAM_READABLE));
+
+        g_object_class_install_property (
+                object_class,
                 PROP_LUKS_CLEARTEXT_SLAVE,
                 g_param_spec_boxed ("luks-cleartext-slave", NULL, NULL, DBUS_TYPE_G_OBJECT_PATH, G_PARAM_READABLE));
         g_object_class_install_property (
@@ -1267,6 +1289,8 @@ free_info (DevkitDisksDevice *device)
 
         g_free (device->priv->info.partition_table_scheme);
 
+        g_free (device->priv->info.luks_holder);
+
         g_free (device->priv->info.luks_cleartext_slave);
 
         g_free (device->priv->info.drive_vendor);
@@ -1380,6 +1404,15 @@ update_info_properties_cb (DevkitDevice *d, const char *key, const char *value,
                 device->priv->info.id_usage   = g_strdup (value);
         } else if (strcmp (key, "ID_FS_TYPE") == 0) {
                 device->priv->info.id_type    = g_strdup (value);
+
+                if (g_strcmp0 (device->priv->info.id_type, "crypto_LUKS") == 0) {
+
+                        device->priv->info.device_is_luks = TRUE;
+
+                        if (device->priv->info.holders_objpath->len == 1)
+                                device->priv->info.luks_holder = g_strdup (device->priv->info.holders_objpath->pdata[0]);
+                }
+
         } else if (strcmp (key, "ID_FS_VERSION") == 0) {
                 device->priv->info.id_version = g_strdup (value);
                 if (device->priv->info.device_is_linux_md_component) {
@@ -1803,6 +1836,24 @@ update_slaves (DevkitDisksDevice *device)
 }
 
 static void
+update_holders (DevkitDisksDevice *device)
+{
+        unsigned int n;
+
+        /* This is similar to update_slaves() only the other way around. */
+
+        for (n = 0; n < device->priv->info.holders_objpath->len; n++) {
+                const char *holder_objpath = device->priv->info.holders_objpath->pdata[n];
+                DevkitDisksDevice *holder;
+
+                holder = devkit_disks_daemon_local_find_by_object_path (device->priv->daemon, holder_objpath);
+                if (holder != NULL) {
+                        update_info (holder);
+                }
+        }
+}
+
+static void
 update_drive_properties (DevkitDisksDevice *device)
 {
         char *s;
@@ -2034,6 +2085,27 @@ strv_has_str (char **strv, char *str)
         return FALSE;
 }
 
+static guint clear_handler_id = 0;
+
+static gboolean
+clear_is_updated_flags (DevkitDisksDaemon *daemon)
+{
+        GList *devices, *l;
+
+        devices = devkit_disks_daemon_local_get_all_devices (daemon);
+        for (l = devices; l != NULL; l = l->next) {
+                DevkitDisksDevice *device = DEVKIT_DISKS_DEVICE (l->data);
+
+                device->priv->is_updated = FALSE;
+        }
+
+        g_list_free (devices);
+
+        clear_handler_id = 0;
+
+        return FALSE;
+}
+
 /**
  * update_info:
  * @device: the device
@@ -2060,6 +2132,19 @@ update_info (DevkitDisksDevice *device)
 
         ret = FALSE;
 
+        if (device->priv->is_updated) {
+                g_debug ("Skipping update of %s because is_updated==TRUE", device->priv->native_path);
+                ret = TRUE;
+                goto out;
+        }
+
+        device->priv->is_updated = TRUE;
+
+        /* ensure we have set up and idle handler to clear all flags */
+        if (clear_handler_id == 0)
+                clear_handler_id = g_idle_add ((GSourceFunc) clear_is_updated_flags, device->priv->daemon);
+
+
         /* md is special; we don't get "remove" events from the kernel when an array is
          * stopped; so catch it very early before erasing our existing slave variable (we
          * need this to set them slaves free)
@@ -2239,6 +2324,7 @@ update_info (DevkitDisksDevice *device)
         }
 
         update_slaves (device);
+        update_holders (device);
 
         /* Linux MD detection */
         if (sysfs_file_exists (device->priv->native_path, "md")) {
@@ -2469,6 +2555,7 @@ devkit_disks_device_removed (DevkitDisksDevice *device)
         device->priv->removed = TRUE;
 
         update_slaves (device);
+        update_holders (device);
 
         /* If the device is busy, we possibly need to clean up if the
          * device itself is busy. This includes
@@ -5664,10 +5751,14 @@ luks_unlock_device_added_cb (DevkitDisksDaemon *daemon,
             device->priv->info.device_is_luks_cleartext &&
             strcmp (device->priv->info.luks_cleartext_slave, data->device->priv->object_path) == 0) {
 
+                /* update and emit a Changed() signal on the holder since the luks-holder
+                 * property indicates the cleartext device
+                 */
+                update_info (data->device);
+                emit_changed (data->device);
                 if (data->hook_func != NULL) {
                         data->hook_func (data->context, device, data->hook_user_data);
                 } else {
-                        /* yay! it is.. return value to the user */
                         dbus_g_method_return (data->context, object_path);
                 }
 
@@ -5705,6 +5796,11 @@ luks_unlock_start_waiting_for_cleartext_device (gpointer user_data)
 
         cleartext_device = find_cleartext_device (data->device);
         if (cleartext_device != NULL) {
+                /* update and emit a Changed() signal on the holder since the luks-holder
+                 * property indicates the cleartext device
+                 */
+                update_info (data->device);
+                emit_changed (data->device);
                 if (data->hook_func != NULL) {
                         data->hook_func (data->context, cleartext_device, data->hook_user_data);
                 } else {
@@ -5948,6 +6044,11 @@ luks_lock_wait_for_cleartext_device_removed_cb (DevkitDisksDaemon *daemon,
 
                 job_local_end (data->luks_device);
 
+                /* update and emit a Changed() signal on the holder since the luks-holder
+                 * property indicates the cleartext device
+                 */
+                update_info (data->luks_device);
+                emit_changed (data->luks_device);
                 dbus_g_method_return (data->context);
 
                 g_signal_handler_disconnect (daemon, data->device_removed_signal_handler_id);
@@ -5989,6 +6090,11 @@ luks_lock_completed_cb (DBusGMethodInvocation *context,
 
                 /* if device is already removed, just return */
                 if (data->cleartext_device->priv->removed) {
+                        /* update and emit a Changed() signal on the holder since the luks-holder
+                         * property indicates the cleartext device
+                         */
+                        update_info (data->luks_device);
+                        emit_changed (data->luks_device);
                         dbus_g_method_return (context);
                 } else {
                         /* otherwise sit and wait for the device to disappear */
index 55938df..39344a5 100644 (file)
             is TRUE.
       </doc:para></doc:description></doc:doc>
     </property>
+    <property name="device-is-luks" type="b" access="read">
+      <doc:doc><doc:description><doc:para>
+            TRUE if device is an LUKS encrypted device. See luks- properties for details.
+      </doc:para></doc:description></doc:doc>
+    </property>
     <property name="device-is-luks-cleartext" type="b" access="read">
       <doc:doc><doc:description><doc:para>
             TRUE if device is a cleartext device backed by a LUKS encrypted device. See luks-cleartext- properties for details.
       </doc:para></doc:description></doc:doc>
     </property>
 
+    <property name="luks-holder" type="o" access="read">
+      <doc:doc><doc:description><doc:para>
+            The cleartext device that is using the LUKS device.
+            This property is only valid if
+            <doc:ref type="property" to="Device:device-is-luks-cleartext">device-is-luks</doc:ref>
+            is TRUE.
+      </doc:para></doc:description></doc:doc>
+    </property>
+
     <property name="luks-cleartext-slave" type="o" access="read">
       <doc:doc><doc:description><doc:para>
             The encrypted LUKS device backing a crypto cleartext device.
index 88cd034..e8852ae 100644 (file)
@@ -408,6 +408,7 @@ typedef struct
         gboolean device_is_read_only;
         gboolean device_is_drive;
         gboolean device_is_optical_disc;
+        gboolean device_is_luks;
         gboolean device_is_luks_cleartext;
         gboolean device_is_mounted;
         gboolean device_is_busy;
@@ -449,6 +450,8 @@ typedef struct
         GArray  *partition_table_offsets;
         GArray  *partition_table_sizes;
 
+        char    *luks_holder;
+
         char    *luks_cleartext_slave;
         uid_t    luks_cleartext_unlocked_by_uid;
 
@@ -530,6 +533,8 @@ collect_props (const char *key, const GValue *value, DeviceProperties *props)
                 props->device_is_drive = g_value_get_boolean (value);
         else if (strcmp (key, "device-is-optical-disc") == 0)
                 props->device_is_optical_disc = g_value_get_boolean (value);
+        else if (strcmp (key, "device-is-luks") == 0)
+                props->device_is_luks = g_value_get_boolean (value);
         else if (strcmp (key, "device-is-luks-cleartext") == 0)
                 props->device_is_luks_cleartext = g_value_get_boolean (value);
         else if (strcmp (key, "device-is-linux-md-component") == 0)
@@ -614,6 +619,9 @@ collect_props (const char *key, const GValue *value, DeviceProperties *props)
                 props->partition_table_sizes = g_value_get_boxed (&dest_value);
         }
 
+        else if (strcmp (key, "luks-holder") == 0)
+                props->luks_holder = g_strdup (g_value_get_boxed (value));
+
         else if (strcmp (key, "luks-cleartext-slave") == 0)
                 props->luks_cleartext_slave = g_strdup (g_value_get_boxed (value));
         else if (strcmp (key, "luks-cleartext-unlocked-by-uid") == 0)
@@ -750,6 +758,7 @@ device_properties_free (DeviceProperties *props)
         g_free (props->partition_table_scheme);
         g_array_free (props->partition_table_offsets, TRUE);
         g_array_free (props->partition_table_sizes, TRUE);
+        g_free (props->luks_holder);
         g_free (props->luks_cleartext_slave);
         g_free (props->drive_model);
         g_free (props->drive_vendor);
@@ -914,6 +923,10 @@ do_show_info (const char *object_path)
                         g_print ("          %s (state: %s)\n",
                                  props->linux_md_slaves[n], props->linux_md_slaves_state[n]);
         }
+        if (props->device_is_luks) {
+                g_print ("  luks device:\n");
+                g_print ("    holder:        %s\n", props->luks_holder);
+        }
         if (props->device_is_luks_cleartext) {
                 g_print ("  cleartext luks device:\n");
                 g_print ("    backed by:     %s\n", props->luks_cleartext_slave);