It's much more future-proof to do it this way.
Signed-off-by: David Zeuthen <davidz@redhat.com>
-->
<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.
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>
static gboolean
handle_cancel (UDisksJob *object,
GDBusMethodInvocation *invocation,
- const gchar* const *options)
+ GVariant *options)
{
UDisksBaseJob *job = UDISKS_BASE_JOB (object);
* @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.
*
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)
{
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;
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);
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;
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;
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)
}
}
}
- 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);
/*
* 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.
*/
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);
* @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
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;
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");
{
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)
{
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;
}
static gboolean
handle_mount (UDisksFilesystem *filesystem,
GDBusMethodInvocation *invocation,
- const gchar *requested_fs_type,
- const gchar* const *requested_options)
+ GVariant *options)
{
UDisksObject *object;
UDisksBlockDevice *block;
gchar *escaped_mount_point_to_use;
gchar *error_message;
GError *error;
- gboolean auth_no_user_interaction;
object = NULL;
daemon = NULL;
/* 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)
{
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)
{
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;
static gboolean
handle_unmount (UDisksFilesystem *filesystem,
GDBusMethodInvocation *invocation,
- const gchar* const *options)
+ GVariant *options)
{
UDisksObject *object;
UDisksBlockDevice *block;
uid_t caller_uid;
gchar *error_message;
const gchar *const *mount_points;
- guint n;
gboolean opt_force;
gboolean rc;
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);
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;
}
}
- 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.
*
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;
/* ---------------------------------------------------------------------------------------------------- */
-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[] =
{
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
},
{
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
},
{
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");
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)
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))
error = NULL;
if (!udisks_filesystem_call_unmount_sync (filesystem,
- (const gchar *const *) opt_mount_unmount_options,
+ options,
NULL, /* GCancellable */
&error))
{
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;
}