Hi I've added another change which makes the mapping of mount options to the associated mount point more clear and robust (this was the result of an internal review):
> [Patch 0001] extends the DBUS interface by the MountOptions property, which > holds the mounts options corresponding to the MountPoints property. > It also allows an application to be notified by DBUS PropertiesChanged signal > when the mount options of an mounted FS have changed (e.g. FS remounted > read-only). > > [Patch 0002] adds support for the mount -o remount option allowing to remount > a > already mounted FS via DBUS (and udisksctl). [Patch 0003] changes type of MountOptions property to path-options-pairs. Regards Daniel
From da7cf8535ca488808c56c13a5a0b37a96f61e45e Mon Sep 17 00:00:00 2001 From: Daniel Mueller <daniel.muel...@karlstorz.com> Date: Wed, 4 Nov 2015 10:04:55 +0100 Subject: [PATCH 1/3] Extend DBUS interface by MountOptions property Additionally monitor mount options instead of mount points only and add MountOptions property to the DBUS interface. --- data/org.freedesktop.UDisks2.xml | 6 ++++++ src/udiskslinuxfilesystem.c | 11 ++++++++++- src/udisksmount.c | 26 ++++++++++++++++++++++++++ src/udisksmount.h | 13 +++++++------ src/udisksmountmonitor.c | 14 ++++++++++---- src/udisksprivate.h | 1 + 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml index bd72795..bc77e8a 100644 --- a/data/org.freedesktop.UDisks2.xml +++ b/data/org.freedesktop.UDisks2.xml @@ -1510,6 +1510,12 @@ --> <property name="MountPoints" type="aay" access="read"/> + <!-- MountOptions: + An array of mount option strings corresponding to the mount + points. If the device is not mounted, this array is empty. + --> + <property name="MountOptions" type="aay" access="read"/> + <!-- Mount: @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'). diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c index 4db3745..c88d7ed 100644 --- a/src/udiskslinuxfilesystem.c +++ b/src/udiskslinuxfilesystem.c @@ -145,6 +145,7 @@ udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, UDisksMountMonitor *mount_monitor; UDisksLinuxDevice *device; GPtrArray *p; + GPtrArray *o; GList *mounts; GList *l; @@ -152,6 +153,7 @@ udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, device = udisks_linux_block_object_get_device (object); p = g_ptr_array_new (); + o = g_ptr_array_new (); mounts = udisks_mount_monitor_get_mounts_for_dev (mount_monitor, g_udev_device_get_device_number (device->udev_device)); /* we are guaranteed that the list is sorted so if there are * multiple mounts we'll always get the same order @@ -160,12 +162,19 @@ udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, { UDisksMount *mount = UDISKS_MOUNT (l->data); if (udisks_mount_get_mount_type (mount) == UDISKS_MOUNT_TYPE_FILESYSTEM) - g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount)); + { + g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount)); + g_ptr_array_add (o, (gpointer) udisks_mount_get_mount_options (mount)); + } } g_ptr_array_add (p, NULL); + g_ptr_array_add (o, NULL); udisks_filesystem_set_mount_points (UDISKS_FILESYSTEM (filesystem), (const gchar *const *) p->pdata); + udisks_filesystem_set_mount_options (UDISKS_FILESYSTEM (filesystem), + (const gchar *const *) o->pdata); g_ptr_array_free (p, TRUE); + g_ptr_array_free (o, TRUE); g_list_foreach (mounts, (GFunc) g_object_unref, NULL); g_list_free (mounts); g_object_unref (device); diff --git a/src/udisksmount.c b/src/udisksmount.c index b91cc2e..2ea5e88 100644 --- a/src/udisksmount.c +++ b/src/udisksmount.c @@ -48,6 +48,7 @@ struct _UDisksMount gchar *mount_path; dev_t dev; + gchar *mount_options; UDisksMountType type; }; @@ -66,6 +67,7 @@ udisks_mount_finalize (GObject *object) UDisksMount *mount = UDISKS_MOUNT (object); g_free (mount->mount_path); + g_free (mount->mount_options); if (G_OBJECT_CLASS (udisks_mount_parent_class)->finalize) G_OBJECT_CLASS (udisks_mount_parent_class)->finalize (object); @@ -88,6 +90,7 @@ udisks_mount_class_init (UDisksMountClass *klass) UDisksMount * _udisks_mount_new (dev_t dev, const gchar *mount_path, + const gchar *mount_options, UDisksMountType type) { UDisksMount *mount; @@ -95,6 +98,7 @@ _udisks_mount_new (dev_t dev, mount = UDISKS_MOUNT (g_object_new (UDISKS_TYPE_MOUNT, NULL)); mount->dev = dev; mount->mount_path = g_strdup (mount_path); + mount->mount_options = g_strdup (mount_options); mount->type = type; return mount; @@ -119,6 +123,24 @@ udisks_mount_get_mount_path (UDisksMount *mount) } /** + * udisks_mount_get_mount_options: + * @mount: A #UDisksMount + * + * Gets the mount options for a #UDISKS_MOUNT_TYPE_FILESYSTEM<!-- -->-type mount. + * + * It is a programming error to call this on any other type of #UDisksMount. + * + * Returns: A string owned by @mount. Do not free. + */ +const gchar * +udisks_mount_get_mount_options (UDisksMount *mount) +{ + g_return_val_if_fail (UDISKS_IS_MOUNT (mount), NULL); + g_return_val_if_fail (mount->type == UDISKS_MOUNT_TYPE_FILESYSTEM, NULL); + return mount->mount_options; +} + +/** * udisks_mount_get_dev: * @mount: A #UDisksMount. * @@ -160,6 +182,10 @@ udisks_mount_compare (UDisksMount *mount, goto out; ret = other_mount->type - mount->type; + if (ret != 0) + goto out; + + ret = g_strcmp0 (mount->mount_options, other_mount->mount_options); out: return ret; diff --git a/src/udisksmount.h b/src/udisksmount.h index 0beaf32..308c956 100644 --- a/src/udisksmount.h +++ b/src/udisksmount.h @@ -29,12 +29,13 @@ G_BEGIN_DECLS #define UDISKS_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_MOUNT, UDisksMount)) #define UDISKS_IS_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_MOUNT)) -GType udisks_mount_get_type (void) G_GNUC_CONST; -UDisksMountType udisks_mount_get_mount_type (UDisksMount *mount); -const gchar *udisks_mount_get_mount_path (UDisksMount *mount); -dev_t udisks_mount_get_dev (UDisksMount *mount); -gint udisks_mount_compare (UDisksMount *mount, - UDisksMount *other_mount); +GType udisks_mount_get_type (void) G_GNUC_CONST; +UDisksMountType udisks_mount_get_mount_type (UDisksMount *mount); +const gchar *udisks_mount_get_mount_path (UDisksMount *mount); +const gchar *udisks_mount_get_mount_options (UDisksMount *mount); +dev_t udisks_mount_get_dev (UDisksMount *mount); +gint udisks_mount_compare (UDisksMount *mount, + UDisksMount *other_mount); G_END_DECLS diff --git a/src/udisksmountmonitor.c b/src/udisksmountmonitor.c index 891d118..a6e783d 100644 --- a/src/udisksmountmonitor.c +++ b/src/udisksmountmonitor.c @@ -423,26 +423,30 @@ udisks_mount_monitor_get_mountinfo (UDisksMountMonitor *monitor, guint major, minor; gchar encoded_root[PATH_MAX + 1]; gchar encoded_mount_point[PATH_MAX + 1]; + gchar encoded_mount_options[PATH_MAX + 1]; gchar *mount_point; + gchar *mount_options; dev_t dev; if (strlen (lines[n]) == 0) continue; if (sscanf (lines[n], - "%u %u %u:%u " PATH_MAX_FMT " " PATH_MAX_FMT, + "%u %u %u:%u " PATH_MAX_FMT " " PATH_MAX_FMT " " PATH_MAX_FMT, &mount_id, &parent_id, &major, &minor, encoded_root, - encoded_mount_point) != 6) + encoded_mount_point, + encoded_mount_options) != 7) { udisks_warning ("Error parsing line '%s'", lines[n]); continue; } encoded_root[sizeof encoded_root - 1] = '\0'; encoded_mount_point[sizeof encoded_mount_point - 1] = '\0'; + encoded_mount_options[sizeof encoded_mount_options - 1] = '\0'; /* Temporary work-around for btrfs, see * @@ -500,16 +504,18 @@ udisks_mount_monitor_get_mountinfo (UDisksMountMonitor *monitor, } mount_point = g_strcompress (encoded_mount_point); + mount_options = g_strcompress (encoded_mount_options); /* TODO: we can probably use a hash table or something if this turns out to be slow */ if (!have_mount (monitor, dev, mount_point)) { UDisksMount *mount; - mount = _udisks_mount_new (dev, mount_point, UDISKS_MOUNT_TYPE_FILESYSTEM); + mount = _udisks_mount_new (dev, mount_point, mount_options, UDISKS_MOUNT_TYPE_FILESYSTEM); monitor->mounts = g_list_prepend (monitor->mounts, mount); } g_free (mount_point); + g_free (mount_options); } ret = TRUE; @@ -584,7 +590,7 @@ udisks_mount_monitor_get_swaps (UDisksMountMonitor *monitor, if (!have_mount (monitor, dev, NULL)) { UDisksMount *mount; - mount = _udisks_mount_new (dev, NULL, UDISKS_MOUNT_TYPE_SWAP); + mount = _udisks_mount_new (dev, NULL, NULL, UDISKS_MOUNT_TYPE_SWAP); monitor->mounts = g_list_prepend (monitor->mounts, mount); } } diff --git a/src/udisksprivate.h b/src/udisksprivate.h index 5dfd77e..a61002c 100644 --- a/src/udisksprivate.h +++ b/src/udisksprivate.h @@ -28,6 +28,7 @@ G_BEGIN_DECLS UDisksMount *_udisks_mount_new (dev_t dev, const gchar *mount_path, + const gchar *mount_options, UDisksMountType type); UDisksFstabEntry *_udisks_fstab_entry_new (const struct mntent *mntent); -- 2.4.0
From 594e733c9344175ea05f5002468679d798be5eba Mon Sep 17 00:00:00 2001 From: Daniel Mueller <daniel.muel...@karlstorz.com> Date: Wed, 4 Nov 2015 11:23:03 +0100 Subject: [PATCH 2/3] Add support for mount's remount option. Allow filesystems being remounted via udisksctl. --- src/udiskslinuxfilesystem.c | 158 ++++++++++++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 42 deletions(-) diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c index c88d7ed..d9093f0 100644 --- a/src/udiskslinuxfilesystem.c +++ b/src/udiskslinuxfilesystem.c @@ -328,7 +328,7 @@ static const gchar *exfat_allow_gid_self[] = { "gid=", NULL }; /* ------------------------------------------------ */ /* TODO: support context= */ -static const gchar *any_allow[] = { "exec", "noexec", "nodev", "nosuid", "atime", "noatime", "nodiratime", "ro", "rw", "sync", "dirsync", NULL }; +static const gchar *any_allow[] = { "exec", "noexec", "nodev", "nosuid", "atime", "noatime", "nodiratime", "ro", "rw", "sync", "dirsync", "remount", NULL }; static const FSMountOptions fs_mount_options[] = { @@ -1035,6 +1035,28 @@ has_option (const gchar *options, } static gboolean +has_variant_option (GVariant *options, + const gchar *option) +{ + const gchar *option_string; + gboolean ret; + + option_string = NULL; + ret = FALSE; + if (g_variant_lookup (options, + "options", + "&s", &option_string)) + { + if (has_option (option_string, option)) + { + ret = TRUE; + } + } + + return ret; +} + +static gboolean is_in_fstab (UDisksBlock *block, const gchar *fstab_path, gchar **out_mount_point, @@ -1172,6 +1194,7 @@ handle_mount (UDisksFilesystem *filesystem, const gchar *message; gboolean system_managed; gchar *escaped_device = NULL; + gboolean remount_requested; object = NULL; error_message = NULL; @@ -1184,6 +1207,7 @@ handle_mount (UDisksFilesystem *filesystem, escaped_mount_point_to_use = NULL; caller_user_name = NULL; system_managed = FALSE; + remount_requested = FALSE; /* only allow a single call at a time */ g_mutex_lock (&UDISKS_LINUX_FILESYSTEM (filesystem)->lock); @@ -1206,27 +1230,49 @@ handle_mount (UDisksFilesystem *filesystem, system_managed = TRUE; } + /* Check if remount requested. */ + if (has_variant_option (options, "remount")) + { + remount_requested = TRUE; + } + /* First, fail if the device is already mounted */ existing_mount_points = udisks_filesystem_get_mount_points (filesystem); if (existing_mount_points != NULL && g_strv_length ((gchar **) existing_mount_points) > 0) { - GString *str; - guint n; - str = g_string_new (NULL); - for (n = 0; existing_mount_points[n] != NULL; n++) + if (!remount_requested) { - if (n > 0) - g_string_append (str, ", "); - g_string_append_printf (str, "`%s'", existing_mount_points[n]); + GString *str; + guint n; + str = g_string_new (NULL); + for (n = 0; existing_mount_points[n] != NULL; n++) + { + if (n > 0) + g_string_append (str, ", "); + g_string_append_printf (str, "`%s'", existing_mount_points[n]); + } + g_dbus_method_invocation_return_error (invocation, + UDISKS_ERROR, + UDISKS_ERROR_ALREADY_MOUNTED, + "Device %s is already mounted at %s.\n", + udisks_block_get_device (block), + str->str); + g_string_free (str, TRUE); + goto out; + } + } + /* Fail if the device is not mounted and remount requested. */ + else + { + if (remount_requested) + { + g_dbus_method_invocation_return_error (invocation, + UDISKS_ERROR, + UDISKS_ERROR_NOT_MOUNTED, + "Device %s is not mounted.\n", + udisks_block_get_device (block)); + goto out; } - g_dbus_method_invocation_return_error (invocation, - UDISKS_ERROR, - UDISKS_ERROR_ALREADY_MOUNTED, - "Device %s is already mounted at %s.\n", - udisks_block_get_device (block), - str->str); - g_string_free (str, TRUE); - goto out; } error = NULL; @@ -1473,32 +1519,60 @@ handle_mount (UDisksFilesystem *filesystem, escaped_device = udisks_daemon_util_escape_and_quote (udisks_block_get_device (block)); /* run mount(8) */ - if (!udisks_daemon_launch_spawned_job_sync (daemon, - object, - "filesystem-mount", caller_uid, - NULL, /* GCancellable */ - 0, /* uid_t run_as_uid */ - 0, /* uid_t run_as_euid */ - NULL, /* gint *out_status */ - &error_message, - NULL, /* input_string */ - "mount -t %s -o %s %s %s", - escaped_fs_type_to_use, - escaped_mount_options_to_use, - escaped_device, - escaped_mount_point_to_use)) - { - /* ugh, something went wrong.. we need to clean up the created mount point */ - if (g_rmdir (mount_point_to_use) != 0) - udisks_warning ("Error removing directory %s: %m", mount_point_to_use); - g_dbus_method_invocation_return_error (invocation, - UDISKS_ERROR, - UDISKS_ERROR_FAILED, - "Error mounting %s at %s: %s", - udisks_block_get_device (block), - mount_point_to_use, - error_message); - goto out; + if (!remount_requested) + { + if (!udisks_daemon_launch_spawned_job_sync (daemon, + object, + "filesystem-mount", caller_uid, + NULL, /* GCancellable */ + 0, /* uid_t run_as_uid */ + 0, /* uid_t run_as_euid */ + NULL, /* gint *out_status */ + &error_message, + NULL, /* input_string */ + "mount -t %s -o %s %s %s", + escaped_fs_type_to_use, + escaped_mount_options_to_use, + escaped_device, + escaped_mount_point_to_use)) + { + /* ugh, something went wrong.. we need to clean up the created mount point */ + if (g_rmdir (mount_point_to_use) != 0) + udisks_warning ("Error removing directory %s: %m", mount_point_to_use); + g_dbus_method_invocation_return_error (invocation, + UDISKS_ERROR, + UDISKS_ERROR_FAILED, + "Error mounting %s at %s: %s", + udisks_block_get_device (block), + mount_point_to_use, + error_message); + goto out; + } + } + else + { + if (!udisks_daemon_launch_spawned_job_sync (daemon, + object, + "filesystem-mount", caller_uid, + NULL, /* GCancellable */ + 0, /* uid_t run_as_uid */ + 0, /* uid_t run_as_euid */ + NULL, /* gint *out_status */ + &error_message, + NULL, /* input_string */ + "mount -t %s -o %s %s", + escaped_fs_type_to_use, + escaped_mount_options_to_use, + escaped_device)) + { + g_dbus_method_invocation_return_error (invocation, + UDISKS_ERROR, + UDISKS_ERROR_FAILED, + "Error remounting %s: %s", + mount_point_to_use, + error_message); + goto out; + } } /* update the mounted-fs file */ -- 2.4.0
From 18e73eb35c914f32a96d6753274c64101a77d326 Mon Sep 17 00:00:00 2001 From: Daniel Mueller <daniel.muel...@karlstorz.com> Date: Mon, 9 Nov 2015 17:40:44 +0100 Subject: [PATCH 3/3] Handle MountOptions property as path/options pairs. --- data/org.freedesktop.UDisks2.xml | 7 ++++--- src/udiskslinuxfilesystem.c | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml index bc77e8a..3ac418e 100644 --- a/data/org.freedesktop.UDisks2.xml +++ b/data/org.freedesktop.UDisks2.xml @@ -1511,10 +1511,11 @@ <property name="MountPoints" type="aay" access="read"/> <!-- MountOptions: - An array of mount option strings corresponding to the mount - points. If the device is not mounted, this array is empty. + An array of mount path/options-pairs for each mount path where + the device is mounted. If the device is not mounted, this array + is empty. --> - <property name="MountOptions" type="aay" access="read"/> + <property name="MountOptions" type="a(ayay)" access="read"/> <!-- Mount: diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c index d9093f0..775f079 100644 --- a/src/udiskslinuxfilesystem.c +++ b/src/udiskslinuxfilesystem.c @@ -145,7 +145,7 @@ udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, UDisksMountMonitor *mount_monitor; UDisksLinuxDevice *device; GPtrArray *p; - GPtrArray *o; + GVariantBuilder options_builder; GList *mounts; GList *l; @@ -153,7 +153,7 @@ udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, device = udisks_linux_block_object_get_device (object); p = g_ptr_array_new (); - o = g_ptr_array_new (); + g_variant_builder_init (&options_builder, G_VARIANT_TYPE ("a(ayay)")); mounts = udisks_mount_monitor_get_mounts_for_dev (mount_monitor, g_udev_device_get_device_number (device->udev_device)); /* we are guaranteed that the list is sorted so if there are * multiple mounts we'll always get the same order @@ -164,17 +164,17 @@ udisks_linux_filesystem_update (UDisksLinuxFilesystem *filesystem, if (udisks_mount_get_mount_type (mount) == UDISKS_MOUNT_TYPE_FILESYSTEM) { g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount)); - g_ptr_array_add (o, (gpointer) udisks_mount_get_mount_options (mount)); + g_variant_builder_add (&options_builder, "(^ay^ay)", + (const gchar *const *) udisks_mount_get_mount_path (mount), + (const gchar *const *) udisks_mount_get_mount_options (mount)); } } g_ptr_array_add (p, NULL); - g_ptr_array_add (o, NULL); udisks_filesystem_set_mount_points (UDISKS_FILESYSTEM (filesystem), (const gchar *const *) p->pdata); udisks_filesystem_set_mount_options (UDISKS_FILESYSTEM (filesystem), - (const gchar *const *) o->pdata); + g_variant_new ("a(ayay)", &options_builder)); g_ptr_array_free (p, TRUE); - g_ptr_array_free (o, TRUE); g_list_foreach (mounts, (GFunc) g_object_unref, NULL); g_list_free (mounts); g_object_unref (device); -- 2.4.0
_______________________________________________ devkit-devel mailing list devkit-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/devkit-devel