Use a{sv} for options instead of just as
authorDavid Zeuthen <davidz@redhat.com>
Fri, 17 Jun 2011 15:55:19 +0000 (11:55 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Fri, 17 Jun 2011 15:55:19 +0000 (11:55 -0400)
It's much more future-proof to do it this way.

Signed-off-by: David Zeuthen <davidz@redhat.com>
data/org.freedesktop.UDisks2.xml
doc/udisks2-docs.xml
src/udisksbasejob.c
src/udisksdaemonutil.c
src/udisksdaemonutil.h
src/udiskslinuxblock.c
src/udiskslinuxfilesystem.c
tools/udisksctl.c

index 5a599e5..7b7bf27 100644 (file)
     -->
     <property name="IdUUID" type="ay" access="read"/>
 
-    <!-- PartTable: Set to TRUE if a partition table signature was detected on the device. -->
+    <!-- PartTable: Set to %TRUE if a partition table signature was detected on the device. -->
     <property name="PartTable" type="b" access="read"/>
     <!-- PartTableScheme: The type of partition table detected.
          Known values include <literal>mbr</literal> (for <ulink
          <ulink
          url="http://en.wikipedia.org/wiki/Apple_Partition_Map">Apple
          Partition Map</ulink>). If blank, and
-         #org.freedesktop.UDisks2.BlockDevice:PartTable is TRUE, a
+         #org.freedesktop.UDisks2.BlockDevice:PartTable is %TRUE, a
          partition table was detected but its scheme is unknown.
     -->
     <property name="PartTableScheme" type="s" access="read"/>
 
-    <!-- PartEntry: Set to TRUE if the block device represents a partition. -->
+    <!-- PartEntry: Set to %TRUE if the block device represents a partition. -->
     <property name="PartEntry" type="b" access="read"/>
     <!-- PartEntryNumber: The number of the partition in the partition table. -->
     <property name="PartEntryNumber" type="u" access="read"/>
   <interface name="org.freedesktop.UDisks2.Filesystem">
     <!-- prereq: org.freedesktop.UDisks2.BlockDevice -->
 
-    <!-- SetLabel:
-         @label: The label to set.
-         @options: Options.
+    <!--
+        SetLabel:
+        @label: The label to set.
+        @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
 
-         Sets the filesystem label.
+        Sets the filesystem label.
     -->
     <method name="SetLabel">
       <arg name="label" direction="in" type="ay"/>
-      <arg name="options" direction="in" type="as"/>
+      <arg name="options" direction="in" type="a{sv}"/>
     </method>
 
     <!-- MountPoints:
 
     <!--
         Mount:
-        @filesystem_type: Filesystem type to use or blank to use the detected type.
-        @options: Options.
+        @options: Options - known options (in addition to <link linkend="udisks-std-options">standard options</link>) includes <parameter>fstype</parameter> (of type 's') and <parameter>options</parameter> (of type 's').
         @mount_path: The filesystem path where the device was mounted.
 
         Mount the filesystem.
+
+        The file system type can be overridden with the
+        <parameter>fstype</parameter> option and mount options can be
+        given in <parameter>options</parameter> as a comma-separated
+        string. Note that the mount options are validated - only a
+        small subset per filesystem type is allowed.
     -->
     <method name="Mount">
-      <arg name="filesystem_type" direction="in" type="s"/>
-      <arg name="options" direction="in" type="as"/>
+      <arg name="options" direction="in" type="a{sv}"/>
       <arg name="mount_path" direction="out" type="ay"/>
     </method>
 
     <!--
         Unmount:
-        @options: Options.
+        @options: Options - known options (in addition to <link linkend="udisks-std-options">standard options</link>) includes <parameter>force</parameter> (of type 'b').
 
         Unmount a mounted device.
+
+        If the filesystem is busy, this operation fails unless the
+        option <parameter>force</parameter> is given.
     -->
     <method name="Unmount">
-      <arg name="options" direction="in" type="as"/>
+      <arg name="options" direction="in" type="a{sv}"/>
     </method>
   </interface>
 
   <interface name="org.freedesktop.UDisks2.Swapspace">
     <!-- prereq: org.freedesktop.UDisks2.BlockDevice -->
 
-    <!-- Active: Set to TRUE if the device is currently in use by the OS. -->
+    <!-- Active: Set to %TRUE if the device is currently in use by the OS. -->
     <property name="Active" type="b" access="read"/>
 
-    <!-- Start:
-         @options: Options
+    <!--
+        Start:
+        @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
 
-         Activates the swap device.
+        Activates the swap device.
     -->
     <method name="Start">
-      <arg name="options" direction="in" type="as"/>
+      <arg name="options" direction="in" type="a{sv}"/>
     </method>
 
-    <!-- Stop:
-         @options: Options
+    <!--
+        Stop:
+        @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
 
-         Deactivates the swap device.
+        Deactivates the swap device.
     -->
     <method name="Stop">
-      <arg name="options" direction="in" type="as"/>
+      <arg name="options" direction="in" type="a{sv}"/>
     </method>
   </interface>
 
 
     <!--
         Cancel:
-        @options: Options.
+        @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
 
         Cancels the job.
     -->
     <method name="Cancel">
-      <arg name="options" direction="in" type="as"/>
+      <arg name="options" direction="in" type="a{sv}"/>
     </method>
 
     <!--
         Completed:
-        @success: If TRUE, the job completed successfully.
+        @success: If %TRUE, the job completed successfully.
         @message: A message describing the completion of the job, e.g. an error message.
 
         Emitted when a job completes.
index 5d23c72..cc11e7a 100644 (file)
           objects.
         </para>
       </sect1>
+      <sect1 id="udisks-std-options">
+        <title>The <parameter>options</parameter> parameter</title>
+        <para>
+          Many method calls take a parameter of type
+          <link linkend='G-VARIANT-TYPE-VARDICT:CAPS'>'a{sv}'</link>
+          that is normally called <parameter>options</parameter>.
+          The following table lists well-known options:
+        </para>
+        <table frame='all'>
+          <title>Well-known options</title>
+          <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+            <thead>
+              <row>
+                <entry>Option name</entry>
+                <entry>Value type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>auth.no_user_interaction</entry>
+                <entry><link linkend="G-VARIANT-TYPE-BOOLEAN:CAPS">'b'</link></entry>
+                <entry>
+                  If set to <constant>TRUE</constant>, then no user
+                  interaction will happen when checking if the method
+                  call is authorized.
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </table>
+      </sect1>
     </chapter>
 
     <chapter>
index bd16090..7b5fabf 100644 (file)
@@ -181,7 +181,7 @@ udisks_base_job_get_cancellable  (UDisksBaseJob  *job)
 static gboolean
 handle_cancel (UDisksJob              *object,
                GDBusMethodInvocation  *invocation,
-               const gchar* const     *options)
+               GVariant               *options)
 {
   UDisksBaseJob *job = UDISKS_BASE_JOB (object);
 
index c6dfded..cdadb03 100644 (file)
@@ -289,7 +289,7 @@ udisks_daemon_util_resolve_links (const gchar *path,
  * @daemon: A #UDisksDaemon.
  * @object: The #GDBusObject that the call is on.
  * @action_id: The action id to check for.
- * @auth_no_user_interaction: If %TRUE, user interaction will never happen.
+ * @options: (allow-none): A #GVariant to check for the <literal>auth.no_user_interaction</literal> option or %NULL.
  * @message: The message to convey (use N_).
  * @invocation: The invocation to check for.
  *
@@ -313,7 +313,7 @@ gboolean
 udisks_daemon_util_check_authorization_sync (UDisksDaemon          *daemon,
                                              UDisksObject          *object,
                                              const gchar           *action_id,
-                                             gboolean               auth_no_user_interaction,
+                                             GVariant              *options,
                                              const gchar           *message,
                                              GDBusMethodInvocation *invocation)
 {
@@ -324,14 +324,23 @@ udisks_daemon_util_check_authorization_sync (UDisksDaemon          *daemon,
   GError *error;
   gboolean ret;
   UDisksBlockDevice *block;
+  gboolean auth_no_user_interaction;
 
   ret = FALSE;
   subject = NULL;
   details = NULL;
   result = NULL;
   flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
+  auth_no_user_interaction = FALSE;
 
   subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation));
+  if (options != NULL)
+    {
+      g_variant_lookup (options,
+                        "auth.no_user_interaction",
+                        "b",
+                        &auth_no_user_interaction);
+    }
   if (!auth_no_user_interaction)
     flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
 
index a5811dc..624946f 100644 (file)
@@ -41,7 +41,7 @@ gchar **udisks_daemon_util_resolve_links (const gchar *path,
 gboolean udisks_daemon_util_check_authorization_sync (UDisksDaemon          *daemon,
                                                       UDisksObject          *object,
                                                       const gchar           *action_id,
-                                                      gboolean               auth_no_user_interaction,
+                                                      GVariant              *options,
                                                       const gchar           *message,
                                                       GDBusMethodInvocation *invocation);
 
index 1f896d3..9511a7a 100644 (file)
@@ -812,41 +812,22 @@ swapspace_start_on_job_completed (UDisksJob   *job,
 static gboolean
 swapspace_handle_start (UDisksSwapspace        *swapspace,
                         GDBusMethodInvocation  *invocation,
-                        const gchar* const     *options,
+                        GVariant               *options,
                         gpointer                user_data)
 {
   UDisksObject *object;
   UDisksDaemon *daemon;
   UDisksBlockDevice *block;
-  gboolean auth_no_user_interaction;
-  guint n;
   UDisksBaseJob *job;
 
   object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace)));
   daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
   block = udisks_object_peek_block_device (object);
 
-  auth_no_user_interaction = FALSE;
-  for (n = 0; options != NULL && options[n] != NULL; n++)
-    {
-      const gchar *option = options[n];
-      if (g_strcmp0 (option, "auth_no_user_interaction") == 0)
-        {
-          auth_no_user_interaction = TRUE;
-          continue;
-        }
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_OPTION_NOT_PERMITTED,
-                                             "Option `%s' is not allowed",
-                                             option);
-      goto out;
-    }
-
   if (!udisks_daemon_util_check_authorization_sync (daemon,
                                                     object,
                                                     "org.freedesktop.udisks2.swap",
-                                                    auth_no_user_interaction,
+                                                    options,
                                                     N_("Authentication is required to activate swapspace on $(udisks2.device)"),
                                                     invocation))
     goto out;
@@ -887,41 +868,22 @@ swapspace_stop_on_job_completed (UDisksJob   *job,
 static gboolean
 swapspace_handle_stop (UDisksSwapspace        *swapspace,
                        GDBusMethodInvocation  *invocation,
-                       const gchar* const     *options,
+                       GVariant               *options,
                        gpointer                user_data)
 {
   UDisksObject *object;
   UDisksDaemon *daemon;
   UDisksBlockDevice *block;
-  gboolean auth_no_user_interaction;
-  guint n;
   UDisksBaseJob *job;
 
   object = UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (swapspace)));
   daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
   block = udisks_object_peek_block_device (object);
 
-  auth_no_user_interaction = FALSE;
-  for (n = 0; options != NULL && options[n] != NULL; n++)
-    {
-      const gchar *option = options[n];
-      if (g_strcmp0 (option, "auth_no_user_interaction") == 0)
-        {
-          auth_no_user_interaction = TRUE;
-          continue;
-        }
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_OPTION_NOT_PERMITTED,
-                                             "Option `%s' is not allowed",
-                                             option);
-      goto out;
-    }
-
   if (!udisks_daemon_util_check_authorization_sync (daemon,
                                                     object,
                                                     "org.freedesktop.udisks2.swap",
-                                                    auth_no_user_interaction,
+                                                    options,
                                                     N_("Authentication is required to deactivate swapspace on $(udisks2.device)"),
                                                     invocation))
     goto out;
index 02249f1..44dbff0 100644 (file)
@@ -400,12 +400,13 @@ is_mount_option_allowed (const FSMountOptions *fsmo,
 static gchar **
 prepend_default_mount_options (const FSMountOptions *fsmo,
                                uid_t caller_uid,
-                               const gchar * const *given_options)
+                               GVariant *given_options)
 {
   GPtrArray *options;
-  int n;
+  gint n;
   gchar *s;
   gid_t gid;
+  const gchar *option_string;
 
   options = g_ptr_array_new ();
   if (fsmo != NULL)
@@ -434,11 +435,17 @@ prepend_default_mount_options (const FSMountOptions *fsmo,
             }
         }
     }
-  for (n = 0; given_options[n] != NULL; n++)
+
+  if (g_variant_lookup (given_options,
+                        "options",
+                        "&s", &option_string))
     {
-      g_ptr_array_add (options, g_strdup (given_options[n]));
+      gchar **split_option_string;
+      split_option_string = g_strsplit (option_string, ",", -1);
+      for (n = 0; split_option_string[n] != NULL; n++)
+        g_ptr_array_add (options, split_option_string[n]); /* steals string */
+      g_free (split_option_string);
     }
-
   g_ptr_array_add (options, NULL);
 
   return (char **) g_ptr_array_free (options, FALSE);
@@ -449,7 +456,7 @@ prepend_default_mount_options (const FSMountOptions *fsmo,
 /*
  * calculate_fs_type: <internal>
  * @block: A #UDisksBlockDevice.
- * @requested_fs_type: The requested file system type or %NULL.
+ * @given_options: The a{sv} #GVariant.
  * @error: Return location for error or %NULL.
  *
  * Calculates the file system type to use.
@@ -458,18 +465,22 @@ prepend_default_mount_options (const FSMountOptions *fsmo,
  */
 static gchar *
 calculate_fs_type (UDisksBlockDevice         *block,
-                   const gchar               *requested_fs_type,
+                   GVariant                  *given_options,
                    GError                   **error)
 {
   gchar *fs_type_to_use;
   const gchar *probed_fs_type;
+  const gchar *requested_fs_type;
 
   probed_fs_type = NULL;
   if (block != NULL)
     probed_fs_type = udisks_block_device_get_id_type (block);
 
   fs_type_to_use = NULL;
-  if (requested_fs_type != NULL && strlen (requested_fs_type) > 0)
+  if (g_variant_lookup (given_options,
+                        "fstype",
+                        "&s", &requested_fs_type) &&
+      strlen (requested_fs_type) > 0)
     {
       /* TODO: maybe check that it's compatible with probed_fs_type */
       fs_type_to_use = g_strdup (requested_fs_type);
@@ -492,8 +503,7 @@ calculate_fs_type (UDisksBlockDevice         *block,
  * @block: A #UDisksBlockDevice.
  * @caller_uid: The uid of the caller making the request.
  * @fs_type: The filesystem type to use or %NULL.
- * @requested_options: Options requested by the caller.
- * @out_auth_no_user_interaction: Return location for whether the 'auth_no_user_interaction' option was passed or %NULL.
+ * @options: Options requested by the caller.
  * @error: Return location for error or %NULL.
  *
  * Calculates the mount option string to use. Ensures (by returning an
@@ -505,8 +515,7 @@ static gchar *
 calculate_mount_options (UDisksBlockDevice         *block,
                          uid_t                      caller_uid,
                          const gchar               *fs_type,
-                         const gchar *const        *requested_options,
-                         gboolean                  *out_auth_no_user_interaction,
+                         GVariant                  *options,
                          GError                   **error)
 {
   const FSMountOptions *fsmo;
@@ -514,18 +523,16 @@ calculate_mount_options (UDisksBlockDevice         *block,
   gchar *options_to_use_str;
   GString *str;
   guint n;
-  gboolean auth_no_user_interaction;
 
   options_to_use = NULL;
   options_to_use_str = NULL;
-  auth_no_user_interaction = FALSE;
 
   fsmo = find_mount_options_for_fs (fs_type);
 
   /* always prepend some reasonable default mount options; these are
    * chosen here; the user can override them if he wants to
    */
-  options_to_use = prepend_default_mount_options (fsmo, caller_uid, requested_options);
+  options_to_use = prepend_default_mount_options (fsmo, caller_uid, options);
 
   /* validate mount options */
   str = g_string_new ("uhelper=udisks2,nodev,nosuid");
@@ -533,12 +540,6 @@ calculate_mount_options (UDisksBlockDevice         *block,
     {
       const gchar *option = options_to_use[n];
 
-      if (g_strcmp0 (option, "auth_no_user_interaction") == 0)
-        {
-          auth_no_user_interaction = TRUE;
-          continue;
-        }
-
       /* avoid attacks like passing "shortname=lower,uid=0" as a single mount option */
       if (strstr (option, ",") != NULL)
         {
@@ -573,9 +574,6 @@ calculate_mount_options (UDisksBlockDevice         *block,
 
   g_assert (options_to_use_str == NULL || g_utf8_validate (options_to_use_str, -1, NULL));
 
-  if (out_auth_no_user_interaction != NULL)
-    *out_auth_no_user_interaction = auth_no_user_interaction;
-
   return options_to_use_str;
 }
 
@@ -705,8 +703,7 @@ calculate_mount_point (UDisksBlockDevice         *block,
 static gboolean
 handle_mount (UDisksFilesystem       *filesystem,
               GDBusMethodInvocation  *invocation,
-              const gchar            *requested_fs_type,
-              const gchar* const     *requested_options)
+              GVariant               *options)
 {
   UDisksObject *object;
   UDisksBlockDevice *block;
@@ -723,7 +720,6 @@ handle_mount (UDisksFilesystem       *filesystem,
   gchar *escaped_mount_point_to_use;
   gchar *error_message;
   GError *error;
-  gboolean auth_no_user_interaction;
 
   object = NULL;
   daemon = NULL;
@@ -804,7 +800,7 @@ handle_mount (UDisksFilesystem       *filesystem,
   /* calculate filesystem type (guaranteed to be valid UTF-8) */
   error = NULL;
   fs_type_to_use = calculate_fs_type (block,
-                                      requested_fs_type,
+                                      options,
                                       &error);
   if (fs_type_to_use == NULL)
     {
@@ -818,8 +814,7 @@ handle_mount (UDisksFilesystem       *filesystem,
   mount_options_to_use = calculate_mount_options (block,
                                                   caller_uid,
                                                   fs_type_to_use,
-                                                  requested_options,
-                                                  &auth_no_user_interaction,
+                                                  options,
                                                   &error);
   if (mount_options_to_use == NULL)
     {
@@ -837,7 +832,7 @@ handle_mount (UDisksFilesystem       *filesystem,
   if (!udisks_daemon_util_check_authorization_sync (daemon,
                                                     object,
                                                     "org.freedesktop.udisks2.filesystem-mount",
-                                                    auth_no_user_interaction,
+                                                    options,
                                                     N_("Authentication is required to mount $(udisks2.device)"),
                                                     invocation))
     goto out;
@@ -945,7 +940,7 @@ handle_mount (UDisksFilesystem       *filesystem,
 static gboolean
 handle_unmount (UDisksFilesystem       *filesystem,
                 GDBusMethodInvocation  *invocation,
-                const gchar* const     *options)
+                GVariant               *options)
 {
   UDisksObject *object;
   UDisksBlockDevice *block;
@@ -958,7 +953,6 @@ handle_unmount (UDisksFilesystem       *filesystem,
   uid_t caller_uid;
   gchar *error_message;
   const gchar *const *mount_points;
-  guint n;
   gboolean opt_force;
   gboolean rc;
 
@@ -972,22 +966,12 @@ handle_unmount (UDisksFilesystem       *filesystem,
   daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
   store = udisks_daemon_get_persistent_store (daemon);
 
-  for (n = 0; options != NULL && options[n] != NULL; n++)
+  if (options != NULL)
     {
-      const gchar *option = options[n];
-      if (g_strcmp0 (option, "force") == 0)
-        {
-          opt_force = TRUE;
-        }
-      else
-        {
-          g_dbus_method_invocation_return_error (invocation,
-                                                 UDISKS_ERROR,
-                                                 UDISKS_ERROR_OPTION_NOT_PERMITTED,
-                                                 "Unsupported option `%s'",
-                                                 option);
-          goto out;
-        }
+      g_variant_lookup (options,
+                        "force",
+                        "b",
+                        &opt_force);
     }
 
   mount_points = udisks_filesystem_get_mount_points (filesystem);
@@ -1182,22 +1166,19 @@ static gboolean
 handle_set_label (UDisksFilesystem       *filesystem,
                   GDBusMethodInvocation  *invocation,
                   const gchar            *label,
-                  const gchar* const     *requested_options)
+                  GVariant               *options)
 {
   UDisksBlockDevice *block;
   UDisksObject *object;
   UDisksDaemon *daemon;
   const gchar *probed_fs_usage;
   const gchar *probed_fs_type;
-  gboolean auth_no_user_interaction;
   gboolean supports_online;
-  guint n;
   UDisksBaseJob *job;
   gchar *escaped_label;
 
   object = NULL;
   daemon = NULL;
-  auth_no_user_interaction = FALSE;
   supports_online = FALSE;
   escaped_label = NULL;
 
@@ -1243,23 +1224,6 @@ handle_set_label (UDisksFilesystem       *filesystem,
         }
     }
 
-  for (n = 0; requested_options != NULL && requested_options[n] != NULL; n++)
-    {
-      const gchar *option = requested_options[n];
-      if (g_strcmp0 (option, "auth_no_user_interaction") == 0)
-        {
-          auth_no_user_interaction = TRUE;
-          continue;
-        }
-
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_OPTION_NOT_PERMITTED,
-                                             "Option `%s' is not allowed",
-                                             option);
-      goto out;
-    }
-
   /* Check that the user is actually authorized to change the
    * filesystem label.
    *
@@ -1268,7 +1232,7 @@ handle_set_label (UDisksFilesystem       *filesystem,
   if (!udisks_daemon_util_check_authorization_sync (daemon,
                                                     object,
                                                     "org.freedesktop.udisks2.modify",
-                                                    auth_no_user_interaction,
+                                                    options,
                                                     N_("Authentication is required to change the label on $(udisks2.device)"),
                                                     invocation))
     goto out;
index fc17d5e..9d74ef5 100644 (file)
@@ -468,10 +468,12 @@ lookup_object_by_drive (const gchar *drive)
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static gchar  *opt_mount_unmount_object_path = NULL;
-static gchar  *opt_mount_unmount_device = NULL;
-static gchar **opt_mount_unmount_options = NULL;
-static gchar  *opt_mount_filesystem_type = NULL;
+static gchar   *opt_mount_unmount_object_path = NULL;
+static gchar   *opt_mount_unmount_device = NULL;
+static gchar   *opt_mount_options = NULL;
+static gchar   *opt_mount_filesystem_type = NULL;
+static gboolean opt_unmount_force = FALSE;
+static gboolean opt_mount_unmount_no_user_interaction = FALSE;
 
 static const GOptionEntry command_mount_entries[] =
 {
@@ -503,12 +505,21 @@ static const GOptionEntry command_mount_entries[] =
     NULL
   },
   {
-    "option",
+    "options",
     'o',
     0,
-    G_OPTION_ARG_STRING_ARRAY,
-    &opt_mount_unmount_options,
-    "Mount option (can be used several times)",
+    G_OPTION_ARG_STRING,
+    &opt_mount_options,
+    "Mount options",
+    NULL
+  },
+  {
+    "no-user-interaction",
+    0, /* no short option */
+    0,
+    G_OPTION_ARG_NONE,
+    &opt_mount_unmount_no_user_interaction,
+    "Do not authenticate the user if needed",
     NULL
   },
   {
@@ -537,12 +548,21 @@ static const GOptionEntry command_unmount_entries[] =
     NULL
   },
   {
-    "option",
-    'o',
+    "force",
+    'f',
     0,
-    G_OPTION_ARG_STRING_ARRAY,
-    &opt_mount_unmount_options,
-    "Unmount option (can be used several times)",
+    G_OPTION_ARG_NONE,
+    &opt_unmount_force,
+    "Force/lazy unmount",
+    NULL
+  },
+  {
+    "no-user-interaction",
+    0, /* no short option */
+    0,
+    G_OPTION_ARG_NONE,
+    &opt_mount_unmount_no_user_interaction,
+    "Do not authenticate the user if needed",
     NULL
   },
   {
@@ -572,13 +592,17 @@ handle_command_mount_unmount (gint        *argc,
   UDisksFilesystem *filesystem;
   guint n;
   const gchar * const *mount_points;
+  GVariant *options;
+  GVariantBuilder builder;
 
   ret = 1;
   opt_mount_unmount_object_path = NULL;
   opt_mount_unmount_device = NULL;
-  opt_mount_unmount_options = NULL;
+  opt_mount_options = NULL;
   opt_mount_filesystem_type = NULL;
+  opt_unmount_force = FALSE;
   object = NULL;
+  options = NULL;
 
   if (is_mount)
     modify_argv0_for_command (argc, argv, "mount");
@@ -740,8 +764,40 @@ handle_command_mount_unmount (gint        *argc,
 
   if (opt_mount_filesystem_type == NULL)
     opt_mount_filesystem_type = g_strdup ("");
-  if (opt_mount_unmount_options == NULL)
-    opt_mount_unmount_options = g_new0 (gchar *, 1);
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+  if (opt_mount_unmount_no_user_interaction)
+    {
+      g_variant_builder_add (&builder,
+                             "{sv}",
+                             "auth.no_user_interaction", g_variant_new_boolean (TRUE));
+    }
+  if (is_mount)
+    {
+      if (opt_mount_options != NULL)
+        {
+          g_variant_builder_add (&builder,
+                                 "{sv}",
+                                 "options", g_variant_new_string (opt_mount_options));
+        }
+      if (opt_mount_filesystem_type != NULL)
+        {
+          g_variant_builder_add (&builder,
+                                 "{sv}",
+                                 "fstype", g_variant_new_string (opt_mount_filesystem_type));
+        }
+    }
+  else
+    {
+      if (opt_unmount_force)
+        {
+          g_variant_builder_add (&builder,
+                                 "{sv}",
+                                 "force", g_variant_new_boolean (TRUE));
+        }
+    }
+  options = g_variant_builder_end (&builder);
+  g_variant_ref_sink (options);
 
  try_again:
   if (is_mount)
@@ -751,8 +807,7 @@ handle_command_mount_unmount (gint        *argc,
 
       error = NULL;
       if (!udisks_filesystem_call_mount_sync (filesystem,
-                                              opt_mount_filesystem_type,
-                                              (const gchar *const *) opt_mount_unmount_options,
+                                              options,
                                               &mount_path,
                                               NULL,                       /* GCancellable */
                                               &error))
@@ -782,7 +837,7 @@ handle_command_mount_unmount (gint        *argc,
 
       error = NULL;
       if (!udisks_filesystem_call_unmount_sync (filesystem,
-                                                (const gchar *const *) opt_mount_unmount_options,
+                                                options,
                                                 NULL,         /* GCancellable */
                                                 &error))
         {
@@ -809,10 +864,12 @@ handle_command_mount_unmount (gint        *argc,
   g_object_unref (object);
 
  out:
+  if (options != NULL)
+    g_variant_unref (options);
   g_option_context_free (o);
   g_free (opt_mount_unmount_object_path);
   g_free (opt_mount_unmount_device);
-  g_strfreev (opt_mount_unmount_options);
+  g_free (opt_mount_options);
   g_free (opt_mount_filesystem_type);
   return ret;
 }