Hello

I've made some changes to add support for the remount option which I'd like you
to consider for upstream inclusion:

[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).

With kind 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/2] 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/2] 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

_______________________________________________
devkit-devel mailing list
devkit-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/devkit-devel

Reply via email to