[gvfs/wip/udisks2] udisks2: handle display, unlock/mount and unmount/lock of LUKS devices



commit 5c2fc336ee9aaeb339b05b568ca5e8a3e415a390
Author: David Zeuthen <davidz redhat com>
Date:   Wed Oct 5 13:45:33 2011 -0400

    udisks2: handle display, unlock/mount and unmount/lock of LUKS devices
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 monitor/udisks2/gvfsudisks2mount.c         |  109 +++++++--
 monitor/udisks2/gvfsudisks2volume.c        |  354 +++++++++++++++++++++++++---
 monitor/udisks2/gvfsudisks2volumemonitor.c |  156 ++++---------
 3 files changed, 449 insertions(+), 170 deletions(-)
---
diff --git a/monitor/udisks2/gvfsudisks2mount.c b/monitor/udisks2/gvfsudisks2mount.c
index 03cba80..4835dcd 100644
--- a/monitor/udisks2/gvfsudisks2mount.c
+++ b/monitor/udisks2/gvfsudisks2mount.c
@@ -580,6 +580,9 @@ typedef struct
 
   GVfsUDisks2Mount *mount;
 
+  UDisksEncrypted *encrypted;
+  UDisksFilesystem *filesystem;
+
   GCancellable *cancellable;
   gulong cancelled_handler_id;
   gboolean is_cancelled;
@@ -614,6 +617,8 @@ unmount_data_free (UnmountData *data)
     g_signal_handler_disconnect (data->cancellable, data->cancelled_handler_id);
   g_clear_object (&data->cancellable);
   g_clear_object (&data->mount_operation);
+  g_clear_object (&data->encrypted);
+  g_clear_object (&data->filesystem);
 
   g_free (data);
 }
@@ -724,6 +729,24 @@ unmount_show_busy (UnmountData        *data,
 }
 
 static void
+lock_cb (GObject       *source_object,
+         GAsyncResult  *res,
+         gpointer       user_data)
+{
+  UDisksEncrypted *encrypted = UDISKS_ENCRYPTED (source_object);
+  UnmountData *data = user_data;
+  GError *error;
+
+  error = NULL;
+  if (!udisks_encrypted_call_lock_finish (encrypted,
+                                          res,
+                                          &error))
+    g_simple_async_result_take_error (data->simple, error);
+  g_simple_async_result_complete (data->simple);
+  unmount_data_free (data);
+}
+
+static void
 unmount_cb (GObject       *source_object,
             GAsyncResult  *res,
             gpointer       user_data)
@@ -754,7 +777,19 @@ unmount_cb (GObject       *source_object,
   else
     {
       gvfs_udisks2_volume_monitor_update (data->mount->monitor);
-      g_simple_async_result_complete (data->simple);
+      if (data->encrypted != NULL)
+        {
+          udisks_encrypted_call_lock (data->encrypted,
+                                      g_variant_new ("a{sv}", NULL), /* options */
+                                      data->cancellable,
+                                      lock_cb,
+                                      data);
+          goto out;
+        }
+      else
+        {
+          g_simple_async_result_complete (data->simple);
+        }
     }
 
   unmount_data_free (data);
@@ -832,8 +867,6 @@ static void
 unmount_do (UnmountData *data,
             gboolean     force)
 {
-  UDisksBlock *block;
-  UDisksFilesystem *filesystem;
   GVariantBuilder builder;
 
   if (data->mount->volume == NULL)
@@ -842,25 +875,6 @@ unmount_do (UnmountData *data,
       goto out;
     }
 
-  block = gvfs_udisks2_volume_get_block (data->mount->volume);
-  if (block == NULL)
-    {
-      unmount_do_command (data, force);
-      goto out;
-    }
-
-  filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))));
-  if (filesystem == NULL)
-    {
-      g_simple_async_result_set_error (data->simple,
-                                       G_IO_ERROR,
-                                       G_IO_ERROR_FAILED,
-                                       "No filesystem interface on D-Bus object");
-      g_simple_async_result_complete (data->simple);
-      unmount_data_free (data);
-      goto out;
-    }
-
   g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
   if (data->mount_operation == NULL)
     {
@@ -874,7 +888,7 @@ unmount_do (UnmountData *data,
                              "{sv}",
                              "force", g_variant_new_boolean (TRUE));
     }
-  udisks_filesystem_call_unmount (filesystem,
+  udisks_filesystem_call_unmount (data->filesystem,
                                   g_variant_builder_end (&builder),
                                   data->cancellable,
                                   unmount_cb,
@@ -894,6 +908,8 @@ gvfs_udisks2_mount_unmount_with_operation (GMount              *_mount,
 {
   GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (_mount);
   UnmountData *data;
+  UDisksBlock *block;
+  UDisksObject *object;
 
   /* first emit the ::mount-pre-unmount signal */
   g_signal_emit_by_name (mount->monitor, "mount-pre-unmount", mount);
@@ -913,11 +929,54 @@ gvfs_udisks2_mount_unmount_with_operation (GMount              *_mount,
       /* burn mounts are really never mounted so complete successfully immediately */
       g_simple_async_result_complete_in_idle (data->simple);
       unmount_data_free (data);
+      goto out;
     }
-  else
+
+  block = gvfs_udisks2_volume_get_block (data->mount->volume);
+  if (block != NULL)
     {
-      unmount_do (data, FALSE);
+      object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block)));
+      data->filesystem = udisks_object_get_filesystem (object);
+      if (data->filesystem == NULL)
+        {
+          UDisksBlock *cleartext_block;
+
+          data->encrypted = udisks_object_get_encrypted (object);
+          if (data->encrypted == NULL)
+            {
+              g_simple_async_result_set_error (data->simple,
+                                               G_IO_ERROR,
+                                               G_IO_ERROR_FAILED,
+                                               "No filesystem or encrypted interface on D-Bus object");
+              g_simple_async_result_complete (data->simple);
+              unmount_data_free (data);
+              goto out;
+            }
+
+          cleartext_block = udisks_client_get_cleartext_block (gvfs_udisks2_volume_monitor_get_udisks_client (mount->monitor),
+                                                               block);
+          if (cleartext_block != NULL)
+            {
+              data->filesystem = udisks_object_get_filesystem (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (cleartext_block))));
+              g_object_unref (cleartext_block);
+              if (data->filesystem == NULL)
+                {
+                  g_simple_async_result_set_error (data->simple,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_FAILED,
+                                                   "No filesystem interface on D-Bus object for cleartext device");
+                  g_simple_async_result_complete (data->simple);
+                  unmount_data_free (data);
+                  goto out;
+                }
+            }
+        }
+      g_assert (data->filesystem != NULL);
     }
+  unmount_do (data, FALSE /* force */);
+
+ out:
+  ;
 }
 
 static gboolean
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index 1f48d75..fa9cb28 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -83,6 +83,9 @@ static void on_block_changed (GObject    *object,
                               GParamSpec *pspec,
                               gpointer    user_data);
 
+static void on_udisks_client_changed (UDisksClient *client,
+                                      gpointer      user_data);
+
 G_DEFINE_TYPE_EXTENDED (GVfsUDisks2Volume, gvfs_udisks2_volume, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, gvfs_udisks2_volume_volume_iface_init))
 
@@ -91,6 +94,10 @@ gvfs_udisks2_volume_finalize (GObject *object)
 {
   GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (object);
 
+  g_signal_handlers_disconnect_by_func (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
+                                        G_CALLBACK (on_udisks_client_changed),
+                                        volume);
+
   if (volume->mount != NULL)
     {
       gvfs_udisks2_mount_unset_volume (volume->mount, volume);
@@ -207,17 +214,36 @@ update_volume (GVfsUDisks2Volume *volume)
   if (volume->block != NULL)
     {
       const gchar *hint;
+      UDisksBlock *block;
+      UDisksBlock *cleartext_block;
+
+      /* If unlocked, use the values from the unlocked block device for presentation */
+      cleartext_block = udisks_client_get_cleartext_block (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
+                                                           volume->block);
+      if (cleartext_block != NULL)
+        block = cleartext_block;
+      else
+        block = volume->block;
 
-      volume->dev = makedev (udisks_block_get_major (volume->block), udisks_block_get_minor (volume->block));
-      volume->device_file = udisks_block_dup_device (volume->block);
+      volume->dev = makedev (udisks_block_get_major (block), udisks_block_get_minor (block));
+      volume->device_file = udisks_block_dup_device (block);
 
-      if (strlen (udisks_block_get_id_label (volume->block)) > 0)
+      if (strlen (udisks_block_get_id_label (block)) > 0)
         {
-          volume->name = g_strdup (udisks_block_get_id_label (volume->block));
+          volume->name = g_strdup (udisks_block_get_id_label (block));
+        }
+      else if (g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0)
+        {
+          s = udisks_util_get_size_for_display (udisks_block_get_size (volume->block), FALSE, FALSE);
+          /* Translators: This is used for encrypted volumes.
+           *              The first %s is the formatted size (e.g. "42.0 MB").
+           */
+          volume->name = g_strdup_printf (_("%s Encrypted"), s);
+          g_free (s);
         }
       else
         {
-          s = g_format_size (udisks_block_get_size (volume->block));
+          s = udisks_util_get_size_for_display (udisks_block_get_size (block), FALSE, FALSE);
           /* Translators: This is used for volume with no filesystem label.
            *              The first %s is the formatted size (e.g. "42.0 MB").
            */
@@ -226,7 +252,7 @@ update_volume (GVfsUDisks2Volume *volume)
         }
 
       udisks_drive = udisks_client_get_drive_for_block (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
-                                                    volume->block);
+                                                        volume->block);
       if (udisks_drive != NULL)
         {
           gchar *drive_desc;
@@ -285,6 +311,27 @@ update_volume (GVfsUDisks2Volume *volume)
           g_clear_object (&volume->icon);
           volume->icon = g_themed_icon_new_with_default_fallbacks (hint);
         }
+
+      /* Add an emblem, depending on whether the encrypted volume is locked or unlocked */
+      if (g_strcmp0 (udisks_block_get_id_type (volume->block), "crypto_LUKS") == 0 && volume->icon != NULL)
+        {
+          GEmblem *emblem;
+          GIcon *padlock;
+          GIcon *emblemed_icon;
+          if (cleartext_block != NULL)
+            padlock = g_themed_icon_new ("changes-allow");
+          else
+            padlock = g_themed_icon_new ("changes-prevent");
+          emblem = g_emblem_new_with_origin (padlock, G_EMBLEM_ORIGIN_DEVICE);
+          emblemed_icon = g_emblemed_icon_new (volume->icon, emblem);
+          g_object_unref (padlock);
+          g_object_unref (emblem);
+
+          g_object_unref (volume->icon);
+          volume->icon = emblemed_icon;
+        }
+
+      g_clear_object (&cleartext_block);
     }
   else
     {
@@ -338,6 +385,8 @@ update_volume (GVfsUDisks2Volume *volume)
   return changed;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
 static void
 on_block_changed (GObject    *object,
                   GParamSpec *pspec,
@@ -348,6 +397,18 @@ on_block_changed (GObject    *object,
     emit_changed (volume);
 }
 
+static void
+on_udisks_client_changed (UDisksClient *client,
+                          gpointer      user_data)
+{
+  GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (user_data);
+  /* This is a little too broad - technically we only need to do this if our block
+   * device has gained or lost a cleartext device...
+   */
+  if (update_volume (volume))
+    emit_changed (volume);
+}
+
 /* takes ownership of @mount_point if not NULL */
 GVfsUDisks2Volume *
 gvfs_udisks2_volume_new (GVfsUDisks2VolumeMonitor   *monitor,
@@ -383,9 +444,20 @@ gvfs_udisks2_volume_new (GVfsUDisks2VolumeMonitor   *monitor,
 
   update_volume (volume);
 
+  /* For LUKS devices, we also need to listen for changes on any possible cleartext device */
+  if (volume->block != NULL && g_strcmp0 (udisks_block_get_id_type (volume->block), "crypto_LUKS") == 0)
+    {
+      g_signal_connect (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
+                        "changed",
+                        G_CALLBACK (on_udisks_client_changed),
+                        volume);
+    }
+
   return volume;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
 void
 gvfs_udisks2_volume_removed (GVfsUDisks2Volume *volume)
 {
@@ -588,31 +660,53 @@ struct MountData
   GSimpleAsyncResult *simple;
 
   GVfsUDisks2Volume *volume;
-
   GCancellable *cancellable;
 
+  gulong mount_operation_reply_handler_id;
+  gulong mount_operation_aborted_handler_id;
   GMountOperation *mount_operation;
+
+  gchar *passphrase;
+
+  UDisksEncrypted *encrypted_to_unlock;
+  UDisksFilesystem *filesystem_to_mount;
+
 };
 
 static void
 mount_data_free (MountData *data)
 {
+  if (data->volume->mount_pending_op == data)
+    data->volume->mount_pending_op = NULL;
+
   g_object_unref (data->simple);
 
   g_clear_object (&data->volume);
   g_clear_object (&data->cancellable);
-  g_clear_object (&data->mount_operation);
+
+  if (data->mount_operation != NULL)
+    {
+      if (data->mount_operation_reply_handler_id != 0)
+        g_signal_handler_disconnect (data->mount_operation, data->mount_operation_reply_handler_id);
+      if (data->mount_operation_aborted_handler_id != 0)
+        g_signal_handler_disconnect (data->mount_operation, data->mount_operation_aborted_handler_id);
+      g_object_unref (data->mount_operation);
+    }
+
+  g_free (data->passphrase);
+
+  g_clear_object (&data->encrypted_to_unlock);
+  g_clear_object (&data->filesystem_to_mount);
   g_free (data);
 }
 
 static void
 mount_cancel_pending_op (MountData *data)
 {
+  g_cancellable_cancel (data->cancellable);
   /* send an ::aborted signal to make the dialog go away */
   if (data->mount_operation != NULL)
     g_signal_emit_by_name (data->mount_operation, "aborted");
-  g_cancellable_cancel (data->cancellable);
-  data->volume->mount_pending_op = NULL;
 }
 
 /* ------------------------------ */
@@ -649,11 +743,11 @@ do_mount_command (MountData *data)
 
   /* TODO: for e.g. NFS and CIFS mounts we could do GMountOperation stuff and pipe a
    * password to mount(8)'s stdin channel
+   *
+   * TODO: if this fails because the user is not authorized (e.g. EPERM), we could
+   * run it through a polkit-ified setuid root helper
    */
 
-  /* we are no longer pending */
-  data->volume->mount_pending_op = NULL;
-
   if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0)
     {
       gvfs_udisks2_volume_monitor_update (data->volume->monitor);
@@ -684,9 +778,6 @@ mount_cb (GObject       *source_object,
   gchar *mount_path;
   GError *error;
 
-  /* we are no longer pending */
-  data->volume->mount_pending_op = NULL;
-
   error = NULL;
   if (!udisks_filesystem_call_mount_finish (UDISKS_FILESYSTEM (source_object),
                                             &mount_path,
@@ -707,6 +798,200 @@ mount_cb (GObject       *source_object,
 }
 
 static void
+do_mount (MountData *data)
+{
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+  if (data->mount_operation == NULL)
+    {
+      g_variant_builder_add (&builder,
+                             "{sv}",
+                             "auth.no_user_interaction", g_variant_new_boolean (TRUE));
+    }
+  udisks_filesystem_call_mount (data->filesystem_to_mount,
+                                g_variant_builder_end (&builder),
+                                data->cancellable,
+                                mount_cb,
+                                data);
+}
+
+/* ------------------------------ */
+
+static void
+unlock_cb (GObject       *source_object,
+           GAsyncResult  *res,
+           gpointer       user_data)
+{
+  MountData *data = user_data;
+  gchar *cleartext_device = NULL;
+  GError *error;
+
+  error = NULL;
+  if (!udisks_encrypted_call_unlock_finish (UDISKS_ENCRYPTED (source_object),
+                                            &cleartext_device,
+                                            res,
+                                            &error))
+    {
+      gvfs_udisks2_utils_udisks_error_to_gio_error (error);
+      g_simple_async_result_take_error (data->simple, error);
+      g_simple_async_result_complete (data->simple);
+      mount_data_free (data);
+      goto out;
+    }
+  else
+    {
+      UDisksObject *object;
+
+      gvfs_udisks2_volume_monitor_update (data->volume->monitor);
+
+      object = udisks_client_peek_object (gvfs_udisks2_volume_monitor_get_udisks_client (data->volume->monitor),
+                                          cleartext_device);
+      data->filesystem_to_mount = object != NULL ? udisks_object_get_filesystem (object) : NULL;
+      if (data->filesystem_to_mount == NULL)
+        {
+          g_simple_async_result_set_error (data->simple,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_FAILED,
+                                           _("The unlocked device does not have a recognizable filesystem on it"));
+          g_simple_async_result_complete (data->simple);
+          mount_data_free (data);
+          goto out;
+        }
+
+      /* TODO: save in keyring depending on ASK_SAVE */
+
+      /* OK, ready to rock */
+      do_mount (data);
+    }
+
+ out:
+  g_free (cleartext_device);
+}
+
+static void do_unlock (MountData *data);
+
+static void
+on_mount_operation_reply (GMountOperation       *mount_operation,
+                          GMountOperationResult result,
+                          gpointer              user_data)
+{
+  MountData *data = user_data;
+
+  /* we got what we wanted; don't listen to any other signals from the mount operation */
+  if (data->mount_operation_reply_handler_id != 0)
+    {
+      g_signal_handler_disconnect (data->mount_operation, data->mount_operation_reply_handler_id);
+      data->mount_operation_reply_handler_id = 0;
+    }
+  if (data->mount_operation_aborted_handler_id != 0)
+    {
+      g_signal_handler_disconnect (data->mount_operation, data->mount_operation_aborted_handler_id);
+      data->mount_operation_aborted_handler_id = 0;
+    }
+
+  if (result != G_MOUNT_OPERATION_HANDLED)
+    {
+      if (result == G_MOUNT_OPERATION_ABORTED)
+        {
+          /* The user aborted the operation so consider it "handled" */
+          g_simple_async_result_set_error (data->simple,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_FAILED_HANDLED,
+                                           "Password dialog aborted (user should never see this error since it is G_IO_ERROR_FAILED_HANDLED)");
+        }
+      else
+        {
+          g_simple_async_result_set_error (data->simple,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_PERMISSION_DENIED,
+                                           "Expected G_MOUNT_OPERATION_HANDLED but got %d", result);
+        }
+      g_simple_async_result_complete (data->simple);
+      mount_data_free (data);
+      goto out;
+    }
+
+  data->passphrase = g_strdup (g_mount_operation_get_password (mount_operation));
+
+  /* TODO: check ASK_SAVE */
+  do_unlock (data);
+
+ out:
+  ;
+}
+
+static void
+on_mount_operation_aborted (GMountOperation       *mount_operation,
+                            gpointer              user_data)
+{
+  on_mount_operation_reply (mount_operation, G_MOUNT_OPERATION_ABORTED, user_data);
+}
+
+static void
+do_unlock (MountData *data)
+{
+  GVariantBuilder builder;
+
+  /* TODO: lookup passphrase in keyring */
+
+  if (data->passphrase == NULL)
+    {
+      gchar *message;
+
+      if (data->mount_operation == NULL)
+        {
+          g_simple_async_result_set_error (data->simple,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_FAILED,
+                                           _("A passphrase is required to access the volume"));
+          g_simple_async_result_complete (data->simple);
+          mount_data_free (data);
+          goto out;
+        }
+
+      data->mount_operation_reply_handler_id = g_signal_connect (data->mount_operation,
+                                                                 "reply",
+                                                                 G_CALLBACK (on_mount_operation_reply),
+                                                                 data);
+      data->mount_operation_aborted_handler_id = g_signal_connect (data->mount_operation,
+                                                                   "aborted",
+                                                                   G_CALLBACK (on_mount_operation_aborted),
+                                                                   data);
+      message = g_strdup_printf (_("Enter a password to unlock the volume\n"
+                                   "The device %s contains encrypted data."),
+                                 udisks_block_get_device (data->volume->block));
+      g_signal_emit_by_name (data->mount_operation,
+                             "ask-password",
+                             message,
+                             NULL,
+                             NULL,
+                             G_ASK_PASSWORD_NEED_PASSWORD |
+                             0/*G_ASK_PASSWORD_SAVING_SUPPORTED*/);
+      g_free (message);
+      goto out;
+    }
+
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+  if (data->mount_operation == NULL)
+    {
+      g_variant_builder_add (&builder,
+                             "{sv}",
+                             "auth.no_user_interaction", g_variant_new_boolean (TRUE));
+    }
+  udisks_encrypted_call_unlock (data->encrypted_to_unlock,
+                                data->passphrase,
+                                g_variant_builder_end (&builder),
+                                data->cancellable,
+                                unlock_cb,
+                                data);
+ out:
+  ;
+}
+
+
+static void
 gvfs_udisks2_volume_mount (GVolume             *_volume,
                            GMountMountFlags     flags,
                            GMountOperation     *mount_operation,
@@ -715,8 +1000,9 @@ gvfs_udisks2_volume_mount (GVolume             *_volume,
                            gpointer             user_data)
 {
   GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (_volume);
+  UDisksObject *object;
+  UDisksBlock *block;
   UDisksFilesystem *filesystem;
-  GVariantBuilder builder;
   MountData *data;
 
   data = g_new0 (MountData, 1);
@@ -746,30 +1032,36 @@ gvfs_udisks2_volume_mount (GVolume             *_volume,
       goto out;
     }
 
-  filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (volume->block))));
+  /* if encrypted and already unlocked, just mount the cleartext block device */
+  block = udisks_client_get_cleartext_block (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
+                                             volume->block);
+  if (block != NULL)
+    g_object_unref (block);
+  else
+    block = volume->block;
+
+  object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block)));
+  filesystem = udisks_object_peek_filesystem (object);
   if (filesystem == NULL)
     {
+      data->encrypted_to_unlock = udisks_object_get_encrypted (object);
+      if (data->encrypted_to_unlock != NULL)
+        {
+          do_unlock (data);
+          goto out;
+        }
+
       g_simple_async_result_set_error (data->simple,
                                        G_IO_ERROR,
                                        G_IO_ERROR_FAILED,
-                                       "No filesystem interface on D-Bus object");
+                                       "No .Filesystem or .Encrypted interface on D-Bus object");
       g_simple_async_result_complete (data->simple);
       mount_data_free (data);
       goto out;
     }
 
-  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
-  if (data->mount_operation == NULL)
-    {
-      g_variant_builder_add (&builder,
-                             "{sv}",
-                             "auth.no_user_interaction", g_variant_new_boolean (TRUE));
-    }
-  udisks_filesystem_call_mount (filesystem,
-                                g_variant_builder_end (&builder),
-                                data->cancellable,
-                                mount_cb,
-                                data);
+  data->filesystem_to_mount = g_object_ref (filesystem);
+  do_mount (data);
 
  out:
   ;
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index a64d31e..62c7c10 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -90,30 +90,8 @@ static void update_discs             (GVfsUDisks2VolumeMonitor  *monitor,
                                       GList                    **removed_mounts);
 
 
-static void on_object_added (GDBusObjectManager  *manager,
-                             GDBusObject         *object,
-                             gpointer             user_data);
-
-static void on_object_removed (GDBusObjectManager  *manager,
-                               GDBusObject         *object,
-                               gpointer             user_data);
-
-static void on_interface_added (GDBusObjectManager  *manager,
-                                GDBusObject         *object,
-                                GDBusInterface      *interface,
-                                gpointer             user_data);
-
-static void on_interface_removed (GDBusObjectManager  *manager,
-                                  GDBusObject         *object,
-                                  GDBusInterface      *interface,
-                                  gpointer             user_data);
-
-static void on_interface_proxy_properties_changed (GDBusObjectManagerClient   *manager,
-                                                   GDBusObjectProxy           *object_proxy,
-                                                   GDBusProxy                 *interface_proxy,
-                                                   GVariant                   *changed_properties,
-                                                   const gchar *const         *invalidated_properties,
-                                                   gpointer                    user_data);
+static void on_client_changed (UDisksClient *client,
+                               gpointer      user_data);
 
 static void mountpoints_changed      (GUnixMountMonitor  *mount_monitor,
                                       gpointer            user_data);
@@ -136,27 +114,13 @@ static void
 gvfs_udisks2_volume_monitor_finalize (GObject *object)
 {
   GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (object);
-  GDBusObjectManager *object_manager;
 
   g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mountpoints_changed, monitor);
   g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mounts_changed, monitor);
   g_clear_object (&monitor->mount_monitor);
 
-  object_manager = udisks_client_get_object_manager (monitor->client);
-  g_signal_handlers_disconnect_by_func (object_manager,
-                                        G_CALLBACK (on_object_added),
-                                        monitor);
-  g_signal_handlers_disconnect_by_func (object_manager,
-                                        G_CALLBACK (on_object_removed),
-                                        monitor);
-  g_signal_handlers_disconnect_by_func (object_manager,
-                                        G_CALLBACK (on_interface_added),
-                                        monitor);
-  g_signal_handlers_disconnect_by_func (object_manager,
-                                        G_CALLBACK (on_interface_removed),
-                                        monitor);
-  g_signal_handlers_disconnect_by_func (object_manager,
-                                        G_CALLBACK (on_interface_proxy_properties_changed),
+  g_signal_handlers_disconnect_by_func (monitor->client,
+                                        G_CALLBACK (on_client_changed),
                                         monitor);
 
   g_clear_object (&monitor->client);
@@ -337,31 +301,12 @@ gvfs_udisks2_volume_monitor_constructor (GType                  type,
 static void
 gvfs_udisks2_volume_monitor_init (GVfsUDisks2VolumeMonitor *monitor)
 {
-  GDBusObjectManager *object_manager;
-
-  monitor->client = get_udisks_client_sync (NULL);
   monitor->gudev_client = g_udev_client_new (NULL); /* don't listen to any changes */
 
-  object_manager = udisks_client_get_object_manager (monitor->client);
-  g_signal_connect (object_manager,
-                    "object-added",
-                    G_CALLBACK (on_object_added),
-                    monitor);
-  g_signal_connect (object_manager,
-                    "object-removed",
-                    G_CALLBACK (on_object_removed),
-                    monitor);
-  g_signal_connect (object_manager,
-                    "interface-added",
-                    G_CALLBACK (on_interface_added),
-                    monitor);
-  g_signal_connect (object_manager,
-                    "interface-removed",
-                    G_CALLBACK (on_interface_removed),
-                    monitor);
-  g_signal_connect (object_manager,
-                    "interface-proxy-properties-changed",
-                    G_CALLBACK (on_interface_proxy_properties_changed),
+  monitor->client = get_udisks_client_sync (NULL);
+  g_signal_connect (monitor->client,
+                    "changed",
+                    G_CALLBACK (on_client_changed),
                     monitor);
 
   monitor->mount_monitor = g_unix_mount_monitor_new ();
@@ -541,57 +486,10 @@ object_list_emit (GVfsUDisks2VolumeMonitor *monitor,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
-on_object_added (GDBusObjectManager  *manager,
-                 GDBusObject         *object,
-                 gpointer             user_data)
-{
-  GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
-  // g_debug ("on_object_added %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
-  update_all (monitor, TRUE);
-}
-
-static void
-on_object_removed (GDBusObjectManager  *manager,
-                   GDBusObject         *object,
-                   gpointer             user_data)
-{
-  GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
-  // g_debug ("on_object_removed %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
-  update_all (monitor, TRUE);
-}
-
-static void
-on_interface_added (GDBusObjectManager  *manager,
-                    GDBusObject         *object,
-                    GDBusInterface      *interface,
-                    gpointer             user_data)
-{
-  GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
-  // g_debug ("on_interface_added %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
-  update_all (monitor, TRUE);
-}
-
-static void
-on_interface_removed (GDBusObjectManager  *manager,
-                      GDBusObject         *object,
-                      GDBusInterface      *interface,
-                      gpointer             user_data)
+on_client_changed (UDisksClient  *client,
+                   gpointer       user_data)
 {
   GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
-  // g_debug ("on_interface_removed %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
-  update_all (monitor, TRUE);
-}
-
-static void
-on_interface_proxy_properties_changed (GDBusObjectManagerClient   *manager,
-                                       GDBusObjectProxy           *object_proxy,
-                                       GDBusProxy                 *interface_proxy,
-                                       GVariant                   *changed_properties,
-                                       const gchar *const         *invalidated_properties,
-                                       gpointer                    user_data)
-{
-  GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
-  // g_debug ("on_interface_proxy_properties_changed %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)));
   update_all (monitor, TRUE);
 }
 
@@ -724,10 +622,40 @@ should_include_volume_check_mount_points (GVfsUDisks2VolumeMonitor *monitor,
 
 static gboolean
 should_include_volume (GVfsUDisks2VolumeMonitor *monitor,
-                       UDisksBlock              *block)
+                       UDisksBlock              *block,
+                       gboolean                  allow_encrypted_cleartext)
 {
   gboolean ret = FALSE;
 
+  /* show encrypted volumes... */
+  if (g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0)
+    {
+      UDisksBlock *cleartext_block;
+      /* ... unless the volume is unlocked and we don't want to show the cleartext volume */
+      cleartext_block = udisks_client_get_cleartext_block (monitor->client, block);
+      if (cleartext_block != NULL)
+        {
+          ret = should_include_volume (monitor, cleartext_block, TRUE);
+          g_object_unref (cleartext_block);
+        }
+      else
+        {
+          ret = TRUE;
+        }
+      goto out;
+    }
+
+  if (!allow_encrypted_cleartext)
+    {
+      /* ... but not unlocked volumes (because the volume for the encrypted part morphs
+       * into the cleartext part when unlocked)
+       */
+      if (g_strcmp0 (udisks_block_get_crypto_backing_device (block), "/") != 0)
+        {
+          goto out;
+        }
+    }
+
   /* Check should_include_mount() for all mount points, if any - e.g. if a volume
    * is mounted in a place where the mount is to be ignored, we ignore the volume
    * as well
@@ -1162,7 +1090,7 @@ update_volumes (GVfsUDisks2VolumeMonitor  *monitor,
       UDisksBlock *block = udisks_object_peek_block (UDISKS_OBJECT (l->data));
       if (block == NULL)
         continue;
-      if (should_include_volume (monitor, block))
+      if (should_include_volume (monitor, block, FALSE))
         new_block_volumes = g_list_prepend (new_block_volumes, block);
     }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]