a19a3f
From 6121d5437d7800876567fd08b6020ca1d72eeaac Mon Sep 17 00:00:00 2001
a19a3f
From: Vratislav Podzimek <vpodzime@redhat.com>
a19a3f
Date: Fri, 20 Oct 2017 13:24:20 +0200
a19a3f
Subject: [PATCH] Add and use a service for cleaning up mount point directories
a19a3f
a19a3f
When udisks2 is used for mounting devices, it may need to create
a19a3f
the mount point directory. If unmount happens later, udisks2
a19a3f
cleans after itself and removes the mount point
a19a3f
directory. However, if the unmount happens during reboot, the
a19a3f
udisks2 daemon may already be terminated not having a chance to
a19a3f
do the cleanup. We need a different mechanism to do the job in
a19a3f
such cases.
a19a3f
a19a3f
systemd provides us with such a mechanism so let's make use of
a19a3f
it.
a19a3f
a19a3f
Resolves: rhbz#1384796
a19a3f
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
a19a3f
---
a19a3f
 data/Makefile.am                |  6 ++--
a19a3f
 data/clean-mount-point@.service | 10 +++++++
a19a3f
 packaging/udisks2.spec          |  1 +
a19a3f
 src/Makefile.am                 |  3 +-
a19a3f
 src/udiskslinuxfilesystem.c     | 61 +++++++++++++++++++++++++++++++++++++++--
a19a3f
 5 files changed, 74 insertions(+), 7 deletions(-)
a19a3f
 create mode 100644 data/clean-mount-point@.service
a19a3f
a19a3f
diff --git a/data/Makefile.am b/data/Makefile.am
a19a3f
index 83af330..9b8073a 100644
a19a3f
--- a/data/Makefile.am
a19a3f
+++ b/data/Makefile.am
a19a3f
@@ -15,14 +15,14 @@ dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
a19a3f
 $(dbusconf_DATA): $(dbusconf_in_files) Makefile
a19a3f
 	cp $< $@
a19a3f
 
a19a3f
-systemdservice_in_files = udisks2.service.in
a19a3f
+systemdservice_in_files = udisks2.service.in clean-mount-point@.service
a19a3f
 
a19a3f
 if HAVE_SYSTEMD
a19a3f
 systemdservicedir       = $(systemdsystemunitdir)
a19a3f
 systemdservice_DATA     = $(systemdservice_in_files:.service.in=.service)
a19a3f
 
a19a3f
-$(systemdservice_DATA): $(systemdservice_in_files) Makefile
a19a3f
-	@sed -e "s|\@udisksdprivdir\@|$(libexecdir)/udisks2|" $< > $@
a19a3f
+$(systemdservice_DATA): udisks2.service.in Makefile
a19a3f
+	@sed -e "s|\@udisksdprivdir\@|$(libexecdir)/udisks2|" udisks2.service.in > udisks2.service
a19a3f
 endif
a19a3f
 
a19a3f
 udevrulesdir = $(udevdir)/rules.d
a19a3f
diff --git a/data/clean-mount-point@.service b/data/clean-mount-point@.service
a19a3f
new file mode 100644
a19a3f
index 0000000..83edceb
a19a3f
--- /dev/null
a19a3f
+++ b/data/clean-mount-point@.service
a19a3f
@@ -0,0 +1,10 @@
a19a3f
+[Unit]
a19a3f
+Description=Clean the %f mount point
a19a3f
+Before=%i.mount
a19a3f
+BindsTo=%i.mount
a19a3f
+DefaultDependencies=no
a19a3f
+
a19a3f
+[Service]
a19a3f
+Type=oneshot
a19a3f
+RemainAfterExit=true
a19a3f
+ExecStop=/bin/rm -fd %f
a19a3f
diff --git a/src/Makefile.am b/src/Makefile.am
a19a3f
index 396ab4e..3b22cca 100644
a19a3f
--- a/src/Makefile.am
a19a3f
+++ b/src/Makefile.am
a19a3f
@@ -113,7 +113,8 @@ libudisks_daemon_la_LIBADD =                                                   \
a19a3f
 	$(GIO_LIBS)                                                            \
a19a3f
 	$(GMODULE_LIBS)                                                        \
a19a3f
 	$(GUDEV_LIBS)                                                          \
a19a3f
-	$(BLOCKDEV_LIBS)                                                          \
a19a3f
+	$(BLOCKDEV_LIBS)                                                       \
a19a3f
+	-lbd_utils                                                             \
a19a3f
 	$(LIBATASMART_LIBS)                                                    \
a19a3f
 	$(POLKIT_GOBJECT_1_LIBS)                                               \
a19a3f
 	$(ACL_LIBS)                                                            \
a19a3f
diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c
a19a3f
index 4cd2784..2910181 100644
a19a3f
--- a/src/udiskslinuxfilesystem.c
a19a3f
+++ b/src/udiskslinuxfilesystem.c
a19a3f
@@ -86,9 +86,11 @@ G_DEFINE_TYPE_WITH_CODE (UDisksLinuxFilesystem, udisks_linux_filesystem, UDISKS_
a19a3f
                          G_IMPLEMENT_INTERFACE (UDISKS_TYPE_FILESYSTEM, filesystem_iface_init));
a19a3f
 
a19a3f
 #ifdef HAVE_FHS_MEDIA
a19a3f
-#  define MOUNT_BASE "/media"
a19a3f
+#define MOUNT_BASE "/media"
a19a3f
+#define MOUNT_BASE_PERSISTENT TRUE
a19a3f
 #else
a19a3f
-#  define MOUNT_BASE "/run/media"
a19a3f
+#define MOUNT_BASE "/run/media"
a19a3f
+#define MOUNT_BASE_PERSISTENT FALSE
a19a3f
 #endif
a19a3f
 
a19a3f
 /* ---------------------------------------------------------------------------------------------------- */
a19a3f
@@ -833,6 +835,7 @@ add_acl (const gchar  *path,
a19a3f
  * @gid: group id of the calling user
a19a3f
  * @user_name: user name of the calling user
a19a3f
  * @fs_type: The file system type to mount with
a19a3f
+ * @persistent: if the mount point is persistent (survives reboot) or not
a19a3f
  * @error: Return location for error or %NULL.
a19a3f
  *
a19a3f
  * Calculates the mount point to use.
a19a3f
@@ -846,6 +849,7 @@ calculate_mount_point (UDisksDaemon  *daemon,
a19a3f
                        gid_t          gid,
a19a3f
                        const gchar   *user_name,
a19a3f
                        const gchar   *fs_type,
a19a3f
+                       gboolean      *persistent,
a19a3f
                        GError       **error)
a19a3f
 {
a19a3f
   UDisksLinuxBlockObject *object = NULL;
a19a3f
@@ -889,6 +893,7 @@ calculate_mount_point (UDisksDaemon  *daemon,
a19a3f
   if (!fs_shared && (user_name != NULL && strstr (user_name, "/") == NULL))
a19a3f
     {
a19a3f
       mount_dir = g_strdup_printf (MOUNT_BASE "/%s", user_name);
a19a3f
+      *persistent = MOUNT_BASE_PERSISTENT;
a19a3f
       if (!g_file_test (mount_dir, G_FILE_TEST_EXISTS))
a19a3f
         {
a19a3f
           /* First ensure that MOUNT_BASE exists */
a19a3f
@@ -933,8 +938,10 @@ calculate_mount_point (UDisksDaemon  *daemon,
a19a3f
         }
a19a3f
     }
a19a3f
   /* otherwise fall back to mounting in /media */
a19a3f
-  if (mount_dir == NULL)
a19a3f
+  if (mount_dir == NULL) {
a19a3f
     mount_dir = g_strdup ("/media");
a19a3f
+    *persistent = TRUE;
a19a3f
+  }
a19a3f
 
a19a3f
   /* NOTE: UTF-8 has the nice property that valid UTF-8 strings only contains
a19a3f
    *       the byte 0x2F if it's for the '/' character (U+002F SOLIDUS).
a19a3f
@@ -1135,6 +1142,49 @@ is_system_managed (UDisksBlock  *block,
a19a3f
   return ret;
a19a3f
 }
a19a3f
 
a19a3f
+static void trigger_mpoint_cleanup (const gchar *mount_point)
a19a3f
+{
a19a3f
+  const gchar *argv[] = {"systemctl", "start", NULL, NULL};
a19a3f
+  GError *error = NULL;
a19a3f
+  gchar *escaped_mpoint = NULL;
a19a3f
+  gsize len = 0;
a19a3f
+
a19a3f
+  if (g_str_has_prefix (mount_point, "/"))
a19a3f
+    mount_point++;
a19a3f
+  else
a19a3f
+    udisks_warning ("Invalid mount point given to trigger_mpoint_cleanup(): %s",
a19a3f
+                    mount_point);
a19a3f
+
a19a3f
+  /* start with the mount point without the leading '/' */
a19a3f
+  escaped_mpoint = g_strdup (mount_point);
a19a3f
+
a19a3f
+  /* and replace all '/'s with '-'s */
a19a3f
+  for (gchar *letter = escaped_mpoint; *letter != '\0'; letter++, len++)
a19a3f
+    {
a19a3f
+      if (*letter == '/')
a19a3f
+        *letter = '-';
a19a3f
+    }
a19a3f
+
a19a3f
+  /* remove the potential trailing '-' (would happen if the given mount_point
a19a3f
+     has a trailing '/') */
a19a3f
+  if (escaped_mpoint[len - 1] == '-')
a19a3f
+    escaped_mpoint[len - 1] = '\0';
a19a3f
+
a19a3f
+  argv[2] = g_strdup_printf ("clean-mount-point@%s", escaped_mpoint);
a19a3f
+
a19a3f
+  if (!bd_utils_exec_and_report_error (argv, NULL, &error) && (error != NULL))
a19a3f
+    {
a19a3f
+      /* this is a best-effort mechanism, if it fails, just log warning and move
a19a3f
+         on */
a19a3f
+      udisks_warning ("Failed to setup systemd-based mount point cleanup: %s",
a19a3f
+                      error->message);
a19a3f
+      g_clear_error (&error);
a19a3f
+    }
a19a3f
+
a19a3f
+  g_free (escaped_mpoint);
a19a3f
+  g_free ((gchar *) argv[2]);
a19a3f
+}
a19a3f
+
a19a3f
 /* ---------------------------------------------------------------------------------------------------- */
a19a3f
 
a19a3f
 /* runs in thread dedicated to handling @invocation */
a19a3f
@@ -1154,6 +1204,7 @@ handle_mount (UDisksFilesystem      *filesystem,
a19a3f
   gchar *fs_type_to_use = NULL;
a19a3f
   gchar *mount_options_to_use = NULL;
a19a3f
   gchar *mount_point_to_use = NULL;
a19a3f
+  gboolean mpoint_persistent = TRUE;
a19a3f
   gchar *fstab_mount_options = NULL;
a19a3f
   gchar *caller_user_name = NULL;
a19a3f
   GError *error = NULL;
a19a3f
@@ -1443,6 +1494,7 @@ handle_mount (UDisksFilesystem      *filesystem,
a19a3f
                                               caller_gid,
a19a3f
                                               caller_user_name,
a19a3f
                                               fs_type_to_use,
a19a3f
+                                              &mpoint_persistent,
a19a3f
                                               &error);
a19a3f
   if (mount_point_to_use == NULL)
a19a3f
     {
a19a3f
@@ -1487,6 +1539,9 @@ handle_mount (UDisksFilesystem      *filesystem,
a19a3f
   else
a19a3f
     udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), TRUE, NULL);
a19a3f
 
a19a3f
+  if (mpoint_persistent)
a19a3f
+    trigger_mpoint_cleanup (mount_point_to_use);
a19a3f
+
a19a3f
   /* update the mounted-fs file */
a19a3f
   udisks_state_add_mounted_fs (state,
a19a3f
                                mount_point_to_use,
a19a3f
-- 
a19a3f
2.9.5
a19a3f