Move contents of BlockDevice.Probed and Filesystem into the BlockDevice iface
authorDavid Zeuthen <davidz@redhat.com>
Wed, 16 Feb 2011 20:26:12 +0000 (15:26 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Wed, 16 Feb 2011 20:26:12 +0000 (15:26 -0500)
Signed-off-by: David Zeuthen <davidz@redhat.com>
data/org.freedesktop.UDisks2.xml
src/Makefile.am
src/udisksfilesystemimpl.c [deleted file]
src/udisksfilesystemimpl.h [deleted file]
src/udiskslinuxblock.c
tools/udisksctl.c
tools/umount-udisks.c

index e485fc3..545ff43 100644 (file)
          to, or '/' if no such object exists.
       -->
     <property name="Drive" type="o" access="read"/>
-  </interface>
-
-  <interface name="org.freedesktop.UDisks2.BlockDevice.Probed">
-    <!-- Prereq: org.freedesktop.UDisks2.BlockDevice -->
 
-    <property name="Usage" type="s" access="read"/>
-    <property name="Type" type="s" access="read"/>
-    <property name="Version" type="s" access="read"/>
-    <property name="Label" type="ay" access="read"/>
-    <property name="UUID" type="ay" access="read"/>
-  </interface>
+    <!-- Properties related what's on the block device -->
+    <property name="IdUsage" type="s" access="read"/>
+    <property name="IdType" type="s" access="read"/>
+    <property name="IdVersion" type="s" access="read"/>
+    <property name="IdLabel" type="ay" access="read"/>
+    <property name="IdUUID" type="ay" access="read"/>
 
-  <interface name="org.freedesktop.UDisks2.Filesystem">
-    <!-- Prereq: org.freedesktop.UDisks2.BlockDevice -->
-
-    <property name="MountPoints" type="aay" access="read"/>
-
-    <method name="Mount">
+    <!-- Properties related to whether the device holds a filesystem -->
+    <property name="FilesystemMountPoints" type="aay" access="read"/>
+    <method name="FilesystemMount">
       <arg name="filesystem_type" direction="in" type="s"/>
       <arg name="options" direction="in" type="as"/>
       <arg name="mount_path" direction="out" type="ay"/>
     </method>
-
-    <method name="Unmount">
+    <method name="FilesystemUnmount">
       <arg name="options" direction="in" type="as"/>
     </method>
   </interface>
index adc70ab..7a8c9b9 100644 (file)
@@ -50,7 +50,6 @@ libudisks_daemon_la_SOURCES =                                         \
        udisksfstabprovider.h           udisksfstabprovider.c           \
        udiskslinuxblock.h              udiskslinuxblock.c              \
        udiskslinuxdrive.h              udiskslinuxdrive.c              \
-       udisksfilesystemimpl.h          udisksfilesystemimpl.c          \
        udisksbasejob.h                 udisksbasejob.c                 \
        udisksspawnedjob.h              udisksspawnedjob.c              \
        udisksthreadedjob.h             udisksthreadedjob.c             \
diff --git a/src/udisksfilesystemimpl.c b/src/udisksfilesystemimpl.c
deleted file mode 100644 (file)
index 445dde5..0000000
+++ /dev/null
@@ -1,1244 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <glib/gstdio.h>
-
-#include <string.h>
-
-#include "udisksdaemon.h"
-#include "udiskslinuxblock.h"
-#include "udisksbasejob.h"
-#include "udiskssimplejob.h"
-#include "udisksfilesystemimpl.h"
-#include "udiskspersistentstore.h"
-
-/**
- * SECTION:udisksfilesystemimpl
- * @title: UDisksFilesystemImpl
- * @short_description: Filesystem Implementation
- *
- * This type provides an implementation of the #UDisksFilesystem
- * interface that uses the <command>mount</command> and
- * <command>umount</command> commands.
- *
- * TODO: mention other impl details like
- * <filename>/var/lib/udisks/mtab</filename>, how mount options work,
- * what role <filename>/etc/fstab</filename> plays and so on.
- */
-
-
-typedef struct _UDisksFilesystemImplClass   UDisksFilesystemImplClass;
-
-/**
- * UDisksFilesystemImpl:
- *
- * The #UDisksFilesystemImpl structure contains only private data and
- * should only be accessed using the provided API.
- */
-struct _UDisksFilesystemImpl
-{
-  UDisksFilesystemStub parent_instance;
-};
-
-struct _UDisksFilesystemImplClass
-{
-  UDisksFilesystemStubClass parent_class;
-};
-
-static void filesystem_iface_init (UDisksFilesystemIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (UDisksFilesystemImpl, udisks_filesystem_impl, UDISKS_TYPE_FILESYSTEM_STUB,
-                         G_IMPLEMENT_INTERFACE (UDISKS_TYPE_FILESYSTEM, filesystem_iface_init));
-
-static void
-udisks_filesystem_impl_init (UDisksFilesystemImpl *filesystem)
-{
-  g_dbus_interface_set_flags (G_DBUS_INTERFACE (filesystem),
-                              G_DBUS_INTERFACE_FLAGS_RUN_IN_THREAD);
-}
-
-static void
-udisks_filesystem_impl_class_init (UDisksFilesystemImplClass *klass)
-{
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-get_uid_sync (GDBusMethodInvocation   *invocation,
-              GCancellable            *cancellable,
-              uid_t                   *out_uid,
-              GError                 **error)
-{
-  gboolean ret;
-  const gchar *caller;
-  GVariant *value;
-  GError *local_error;
-
-  ret = FALSE;
-
-  caller = g_dbus_method_invocation_get_sender (invocation);
-
-  local_error = NULL;
-  value = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (invocation),
-                                       "org.freedesktop.DBus",  /* bus name */
-                                       "/org/freedesktop/DBus", /* object path */
-                                       "org.freedesktop.DBus",  /* interface */
-                                       "GetConnectionUnixUser", /* method */
-                                       g_variant_new ("(s)", caller),
-                                       G_VARIANT_TYPE ("(u)"),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1, /* timeout_msec */
-                                       cancellable,
-                                       &local_error);
-  if (value == NULL)
-    {
-      g_set_error (error,
-                   UDISKS_ERROR,
-                   UDISKS_ERROR_FAILED,
-                   "Error determining uid of caller %s: %s (%s, %d)",
-                   caller,
-                   local_error->message,
-                   g_quark_to_string (local_error->domain),
-                   local_error->code);
-      g_error_free (local_error);
-      goto out;
-    }
-
-  G_STATIC_ASSERT (sizeof (uid_t) == sizeof (guint32));
-  g_variant_get (value, "(u)", out_uid);
-
-  ret = TRUE;
-
- out:
-  return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct
-{
-  const gchar *fstype;
-  const gchar * const *defaults;
-  const gchar * const *allow;
-  const gchar * const *allow_uid_self;
-  const gchar * const *allow_gid_self;
-} FSMountOptions;
-
-/* ---------------------- vfat -------------------- */
-
-static const gchar *vfat_defaults[] = { "uid=", "gid=", "shortname=mixed", "dmask=0077", "utf8=1", "showexec", NULL };
-static const gchar *vfat_allow[] = { "flush", "utf8=", "shortname=", "umask=", "dmask=", "fmask=", "codepage=", "iocharset=", "usefree", "showexec", NULL };
-static const gchar *vfat_allow_uid_self[] = { "uid=", NULL };
-static const gchar *vfat_allow_gid_self[] = { "gid=", NULL };
-
-/* ---------------------- ntfs -------------------- */
-/* this is assuming that ntfs-3g is used */
-
-static const gchar *ntfs_defaults[] = { "uid=", "gid=", "dmask=0077", "fmask=0177", NULL };
-static const gchar *ntfs_allow[] = { "umask=", "dmask=", "fmask=", NULL };
-static const gchar *ntfs_allow_uid_self[] = { "uid=", NULL };
-static const gchar *ntfs_allow_gid_self[] = { "gid=", NULL };
-
-/* ---------------------- iso9660 -------------------- */
-
-static const gchar *iso9660_defaults[] = { "uid=", "gid=", "iocharset=utf8", "mode=0400", "dmode=0500", NULL };
-static const gchar *iso9660_allow[] = { "norock", "nojoliet", "iocharset=", "mode=", "dmode=", NULL };
-static const gchar *iso9660_allow_uid_self[] = { "uid=", NULL };
-static const gchar *iso9660_allow_gid_self[] = { "gid=", NULL };
-
-/* ---------------------- udf -------------------- */
-
-static const gchar *udf_defaults[] = { "uid=", "gid=", "iocharset=utf8", "umask=0077", NULL };
-static const gchar *udf_allow[] = { "iocharset=", "umask=", NULL };
-static const gchar *udf_allow_uid_self[] = { "uid=", NULL };
-static const gchar *udf_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 FSMountOptions fs_mount_options[] =
-  {
-    { "vfat", vfat_defaults, vfat_allow, vfat_allow_uid_self, vfat_allow_gid_self },
-    { "ntfs", ntfs_defaults, ntfs_allow, ntfs_allow_uid_self, ntfs_allow_gid_self },
-    { "iso9660", iso9660_defaults, iso9660_allow, iso9660_allow_uid_self, iso9660_allow_gid_self },
-    { "udf", udf_defaults, udf_allow, udf_allow_uid_self, udf_allow_gid_self },
-  };
-
-/* ------------------------------------------------ */
-
-static int num_fs_mount_options = sizeof(fs_mount_options) / sizeof(FSMountOptions);
-
-static const FSMountOptions *
-find_mount_options_for_fs (const gchar *fstype)
-{
-  int n;
-  const FSMountOptions *fsmo;
-
-  for (n = 0; n < num_fs_mount_options; n++)
-    {
-      fsmo = fs_mount_options + n;
-      if (strcmp (fsmo->fstype, fstype) == 0)
-        goto out;
-    }
-
-  fsmo = NULL;
- out:
-  return fsmo;
-}
-
-static gid_t
-find_primary_gid (uid_t uid)
-{
-  struct passwd *pw;
-  gid_t gid;
-
-  gid = (gid_t) - 1;
-
-  pw = getpwuid (uid);
-  if (pw == NULL)
-    {
-      g_warning ("Couldn't look up uid %d: %m", uid);
-      goto out;
-    }
-  gid = pw->pw_gid;
-
- out:
-  return gid;
-}
-
-static gboolean
-is_uid_in_gid (uid_t uid,
-               gid_t gid)
-{
-  gboolean ret;
-  struct passwd *pw;
-  static gid_t supplementary_groups[128];
-  int num_supplementary_groups = 128;
-  int n;
-
-  /* TODO: use some #define instead of harcoding some random number like 128 */
-
-  ret = FALSE;
-
-  pw = getpwuid (uid);
-  if (pw == NULL)
-    {
-      g_warning ("Couldn't look up uid %d: %m", uid);
-      goto out;
-    }
-  if (pw->pw_gid == gid)
-    {
-      ret = TRUE;
-      goto out;
-    }
-
-  if (getgrouplist (pw->pw_name, pw->pw_gid, supplementary_groups, &num_supplementary_groups) < 0)
-    {
-      g_warning ("Couldn't find supplementary groups for uid %d: %m", uid);
-      goto out;
-    }
-
-  for (n = 0; n < num_supplementary_groups; n++)
-    {
-      if (supplementary_groups[n] == gid)
-        {
-          ret = TRUE;
-          goto out;
-        }
-    }
-
- out:
-  return ret;
-}
-
-static gboolean
-is_mount_option_allowed (const FSMountOptions *fsmo,
-                         const gchar          *option,
-                         uid_t                 caller_uid)
-{
-  int n;
-  gchar *endp;
-  uid_t uid;
-  gid_t gid;
-  gboolean allowed;
-  const gchar *ep;
-  gsize ep_len;
-
-  allowed = FALSE;
-
-  /* first run through the allowed mount options */
-  if (fsmo != NULL)
-    {
-      for (n = 0; fsmo->allow != NULL && fsmo->allow[n] != NULL; n++)
-        {
-          ep = strstr (fsmo->allow[n], "=");
-          if (ep != NULL && ep[1] == '\0')
-            {
-              ep_len = ep - fsmo->allow[n] + 1;
-              if (strncmp (fsmo->allow[n], option, ep_len) == 0)
-                {
-                  allowed = TRUE;
-                  goto out;
-                }
-            }
-          else
-            {
-              if (strcmp (fsmo->allow[n], option) == 0)
-                {
-                  allowed = TRUE;
-                  goto out;
-                }
-            }
-        }
-    }
-  for (n = 0; any_allow[n] != NULL; n++)
-    {
-      ep = strstr (any_allow[n], "=");
-      if (ep != NULL && ep[1] == '\0')
-        {
-          ep_len = ep - any_allow[n] + 1;
-          if (strncmp (any_allow[n], option, ep_len) == 0)
-            {
-              allowed = TRUE;
-              goto out;
-            }
-        }
-      else
-        {
-          if (strcmp (any_allow[n], option) == 0)
-            {
-              allowed = TRUE;
-              goto out;
-            }
-        }
-    }
-
-  /* .. then check for mount options where the caller is allowed to pass
-   * in his own uid
-   */
-  if (fsmo != NULL)
-    {
-      for (n = 0; fsmo->allow_uid_self != NULL && fsmo->allow_uid_self[n] != NULL; n++)
-        {
-          const gchar *r_mount_option = fsmo->allow_uid_self[n];
-          if (g_str_has_prefix (option, r_mount_option))
-            {
-              uid = strtol (option + strlen (r_mount_option), &endp, 10);
-              if (*endp != '\0')
-                continue;
-              if (uid == caller_uid)
-                {
-                  allowed = TRUE;
-                  goto out;
-                }
-            }
-        }
-    }
-
-  /* .. ditto for gid
-   */
-  if (fsmo != NULL)
-    {
-      for (n = 0; fsmo->allow_gid_self != NULL && fsmo->allow_gid_self[n] != NULL; n++)
-        {
-          const gchar *r_mount_option = fsmo->allow_gid_self[n];
-          if (g_str_has_prefix (option, r_mount_option))
-            {
-              gid = strtol (option + strlen (r_mount_option), &endp, 10);
-              if (*endp != '\0')
-                continue;
-              if (is_uid_in_gid (caller_uid, gid))
-                {
-                  allowed = TRUE;
-                  goto out;
-                }
-            }
-        }
-    }
-
- out:
-  return allowed;
-}
-
-static gchar **
-prepend_default_mount_options (const FSMountOptions *fsmo,
-                               uid_t caller_uid,
-                               const gchar * const *given_options)
-{
-  GPtrArray *options;
-  int n;
-  gchar *s;
-  gid_t gid;
-
-  options = g_ptr_array_new ();
-  if (fsmo != NULL)
-    {
-      for (n = 0; fsmo->defaults != NULL && fsmo->defaults[n] != NULL; n++)
-        {
-          const gchar *option = fsmo->defaults[n];
-
-          if (strcmp (option, "uid=") == 0)
-            {
-              s = g_strdup_printf ("uid=%d", caller_uid);
-              g_ptr_array_add (options, s);
-            }
-          else if (strcmp (option, "gid=") == 0)
-            {
-              gid = find_primary_gid (caller_uid);
-              if (gid != (gid_t) - 1)
-                {
-                  s = g_strdup_printf ("gid=%d", gid);
-                  g_ptr_array_add (options, s);
-                }
-            }
-          else
-            {
-              g_ptr_array_add (options, g_strdup (option));
-            }
-        }
-    }
-  for (n = 0; given_options[n] != NULL; n++)
-    {
-      g_ptr_array_add (options, g_strdup (given_options[n]));
-    }
-
-  g_ptr_array_add (options, NULL);
-
-  return (char **) g_ptr_array_free (options, FALSE);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-/*
- * calculate_fs_type: <internal>
- * @block: A #UDisksBlockDevice.
- * @block_probed: A #UDisksBlockDeviceProbed or %NULL.
- * @requested_fs_type: The requested file system type or %NULL.
- * @error: Return location for error or %NULL.
- *
- * Calculates the file system type to use.
- *
- * Returns: A valid UTF-8 string with the filesystem type (may be "auto") or %NULL if @error is set. Free with g_free().
- */
-static gchar *
-calculate_fs_type (UDisksBlockDevice         *block,
-                   UDisksBlockDeviceProbed   *block_probed,
-                   const gchar               *requested_fs_type,
-                   GError                   **error)
-{
-  gchar *fs_type_to_use;
-  const gchar *probed_fs_usage;
-  const gchar *probed_fs_type;
-
-  probed_fs_usage = NULL;
-  probed_fs_type = NULL;
-  if (block_probed != NULL)
-    {
-      probed_fs_usage = udisks_block_device_probed_get_usage (block_probed);
-      probed_fs_type = udisks_block_device_probed_get_type (block_probed);
-    }
-
-  fs_type_to_use = NULL;
-  if (requested_fs_type != NULL && 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);
-    }
-  else
-    {
-      if (probed_fs_type != NULL && strlen (probed_fs_type) > 0)
-        fs_type_to_use = g_strdup (probed_fs_type);
-      else
-        fs_type_to_use = g_strdup ("auto");
-    }
-
-  g_assert (fs_type_to_use == NULL || g_utf8_validate (fs_type_to_use, -1, NULL));
-
-  return fs_type_to_use;
-}
-
-/*
- * calculate_mount_options: <internal>
- * @block: A #UDisksBlockDevice.
- * @block_probed: A #UDisksBlockDeviceProbed or %NULL.
- * @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.
- * @error: Return location for error or %NULL.
- *
- * Calculates the mount option string to use. Ensures (by returning an
- * error) that only safe options are used.
- *
- * Returns: A string with mount options or %NULL if @error is set. Free with g_free().
- */
-static gchar *
-calculate_mount_options (UDisksBlockDevice         *block,
-                         UDisksBlockDeviceProbed   *block_probed,
-                         uid_t                      caller_uid,
-                         const gchar               *fs_type,
-                         const gchar *const        *requested_options,
-                         gboolean                  *out_auth_no_user_interaction,
-                         GError                   **error)
-{
-  const FSMountOptions *fsmo;
-  gchar **options_to_use;
-  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);
-
-  /* validate mount options */
-  str = g_string_new ("uhelper=udisks2,nodev,nosuid");
-  for (n = 0; options_to_use[n] != NULL; n++)
-    {
-      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_set_error (error,
-                       UDISKS_ERROR,
-                       UDISKS_ERROR_OPTION_NOT_PERMITTED,
-                       "Malformed mount option `%s'",
-                       option);
-          g_string_free (str, TRUE);
-          goto out;
-        }
-
-      /* first check if the mount option is allowed */
-      if (!is_mount_option_allowed (fsmo, option, caller_uid))
-        {
-          g_set_error (error,
-                       UDISKS_ERROR,
-                       UDISKS_ERROR_OPTION_NOT_PERMITTED,
-                       "Mount option `%s' is not allowed",
-                       option);
-          g_string_free (str, TRUE);
-          goto out;
-        }
-
-      g_string_append_c (str, ',');
-      g_string_append (str, option);
-    }
-  options_to_use_str = g_string_free (str, FALSE);
-
- out:
-  g_strfreev (options_to_use);
-
-  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 gchar *
-ensure_utf8 (const gchar *s)
-{
-  const gchar *end;
-  gchar *ret;
-
-  if (!g_utf8_validate (s, -1, &end))
-    {
-      gchar *tmp;
-      gint pos;
-      /* TODO: could possibly return a nicer UTF-8 string  */
-      pos = (gint) (end - s);
-      tmp = g_strndup (s, end - s);
-      ret = g_strdup_printf ("%s (Invalid UTF-8 at byte %d)", tmp, pos);
-      g_free (tmp);
-    }
-  else
-    {
-      ret = g_strdup (s);
-    }
-
-  return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-/*
- * calculate_mount_point: <internal>
- * @block: A #UDisksBlockDevice.
- * @block_probed: A #UDisksBlockDeviceProbed or %NULL.
- * @fs_type: The file system type to mount with
- * @error: Return location for error or %NULL.
- *
- * Calculates the mount point to use.
- *
- * Returns: A UTF-8 string with the mount point to use or %NULL if @error is set. Free with g_free().
- */
-static gchar *
-calculate_mount_point (UDisksBlockDevice         *block,
-                       UDisksBlockDeviceProbed   *block_probed,
-                       const gchar               *fs_type,
-                       GError                   **error)
-{
-  const gchar *label;
-  const gchar *uuid;
-  gchar *mount_point;
-  gchar *orig_mount_point;
-  GString *str;
-  gchar *s;
-  guint n;
-
-  label = NULL;
-  uuid = NULL;
-  if (block_probed != NULL)
-    {
-      label = udisks_block_device_probed_get_label (block_probed);
-      uuid = udisks_block_device_probed_get_uuid (block_probed);
-    }
-
-  /* NOTE: UTF-8 has the nice property that valid UTF-8 strings only contains
-   *       the byte 0x2F if it's for the '/' character (U+002F SOLIDUS).
-   *
-   *       See http://en.wikipedia.org/wiki/UTF-8 for details.
-   */
-
-  if (label != NULL && strlen (label) > 0)
-    {
-      str = g_string_new ("/media/");
-      s = ensure_utf8 (label);
-      for (n = 0; s[n] != '\0'; n++)
-        {
-          gint c = s[n];
-          if (c == '/')
-            g_string_append_c (str, '_');
-          else
-            g_string_append_c (str, c);
-        }
-      mount_point = g_string_free (str, FALSE);
-      g_free (s);
-    }
-  else if (uuid != NULL && strlen (uuid) > 0)
-    {
-      str = g_string_new ("/media/");
-      s = ensure_utf8 (uuid);
-      for (n = 0; s[n] != '\0'; n++)
-        {
-          gint c = s[n];
-          if (c == '/')
-            g_string_append_c (str, '_');
-          else
-            g_string_append_c (str, c);
-        }
-      mount_point = g_string_free (str, FALSE);
-      g_free (s);
-    }
-  else
-    {
-      mount_point = g_strdup ("/media/disk");
-    }
-
-  /* ... then uniqify the mount point */
-  orig_mount_point = g_strdup (mount_point);
-  n = 1;
-  while (TRUE)
-    {
-      if (!g_file_test (mount_point, G_FILE_TEST_EXISTS))
-        {
-          break;
-        }
-      else
-        {
-          g_free (mount_point);
-          mount_point = g_strdup_printf ("%s%d", orig_mount_point, n++);
-        }
-    }
-  g_free (orig_mount_point);
-
-  return mount_point;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-/* runs in thread dedicated to handling method call */
-static gboolean
-handle_mount (UDisksFilesystem       *filesystem,
-              GDBusMethodInvocation  *invocation,
-              const gchar            *requested_fs_type,
-              const gchar* const     *requested_options)
-{
-  GDBusObject *object;
-  UDisksDaemon *daemon;
-  UDisksPersistentStore *store;
-  gboolean ret;
-  uid_t caller_uid;
-  UDisksBlockDevice *block;
-  UDisksBlockDeviceProbed *block_probed;
-  GDBusInterface *iface;
-  const gchar * const *existing_mount_points;
-  const gchar *probed_fs_usage;
-  const gchar *probed_fs_type;
-  gchar *fs_type_to_use;
-  gchar *mount_options_to_use;
-  gchar *mount_point_to_use;
-  gchar *escaped_fs_type_to_use;
-  gchar *escaped_mount_options_to_use;
-  gchar *escaped_mount_point_to_use;
-  gchar *error_message;
-  GError *error;
-  PolkitSubject *auth_subject;
-  const gchar *auth_action_id;
-  PolkitDetails *auth_details;
-  gboolean auth_no_user_interaction;
-  PolkitCheckAuthorizationFlags auth_flags;
-  PolkitAuthorizationResult *auth_result;
-
-  ret = FALSE;
-  object = NULL;
-  daemon = NULL;
-  block = NULL;
-  block_probed = NULL;
-  error_message = NULL;
-  fs_type_to_use = NULL;
-  mount_options_to_use = NULL;
-  mount_point_to_use = NULL;
-  escaped_fs_type_to_use = NULL;
-  escaped_mount_options_to_use = NULL;
-  escaped_mount_point_to_use = NULL;
-  auth_subject = NULL;
-  auth_details = NULL;
-  auth_result = NULL;
-  auth_no_user_interaction = FALSE;
-
-  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (filesystem));
-  block = UDISKS_BLOCK_DEVICE (g_dbus_object_lookup_interface (object, "org.freedesktop.UDisks2.BlockDevice"));
-  iface = g_dbus_object_lookup_interface (object, "org.freedesktop.UDisks2.BlockDevice.Probed");
-  block_probed = iface != NULL ? UDISKS_BLOCK_DEVICE_PROBED (iface) : NULL;
-
-  daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
-  store = udisks_daemon_get_persistent_store (daemon);
-
-  /* TODO: check if mount point is managed by e.g. /etc/fstab or
-   *       similar - if so, use that instead of managing mount points
-   *       in /media
-   */
-
-  /* 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 (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_device_get_device (block),
-                                             str->str);
-      g_string_free (str, TRUE);
-      goto out;
-    }
-
-  /* Fail if the device is not mountable - we actually allow mounting
-   * devices that are not probed since since it could be that we just
-   * don't have the data in the udev database but the device has a
-   * filesystem *anyway*...
-   *
-   * For example, this applies to PC floppy devices - automatically
-   * probing for media them creates annoying noise. So they won't
-   * appear in the udev database.
-   */
-  probed_fs_usage = NULL;
-  probed_fs_type = NULL;
-  if (block_probed != NULL)
-    {
-      probed_fs_usage = udisks_block_device_probed_get_usage (block_probed);
-      probed_fs_type = udisks_block_device_probed_get_type (block_probed);
-    }
-  if (probed_fs_usage != NULL && strlen (probed_fs_usage) > 0 &&
-      g_strcmp0 (probed_fs_usage, "filesystem") != 0)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Cannot mount block device %s with probed usage `%s' - expected `filesystem'",
-                                             udisks_block_device_get_device (block),
-                                             probed_fs_usage);
-      goto out;
-    }
-
-  /* we need the uid of the caller to check mount options */
-  error = NULL;
-  if (!get_uid_sync (invocation, NULL /* GCancellable */, &caller_uid, &error))
-    {
-      g_dbus_method_invocation_return_gerror (invocation, error);
-      g_error_free (error);
-      goto out;
-    }
-
-  /* calculate filesystem type (guaranteed to be valid UTF-8) */
-  error = NULL;
-  fs_type_to_use = calculate_fs_type (block,
-                                      block_probed,
-                                      requested_fs_type,
-                                      &error);
-  if (fs_type_to_use == NULL)
-    {
-      g_dbus_method_invocation_return_gerror (invocation, error);
-      g_error_free (error);
-      goto out;
-    }
-
-  /* calculate mount options (guaranteed to be valid UTF-8) */
-  error = NULL;
-  mount_options_to_use = calculate_mount_options (block,
-                                                  block_probed,
-                                                  caller_uid,
-                                                  fs_type_to_use,
-                                                  requested_options,
-                                                  &auth_no_user_interaction,
-                                                  &error);
-  if (mount_options_to_use == NULL)
-    {
-      g_dbus_method_invocation_return_gerror (invocation, error);
-      g_error_free (error);
-      goto out;
-    }
-
-  /* calculate mount point (guaranteed to be valid UTF-8) */
-  error = NULL;
-  mount_point_to_use = calculate_mount_point (block,
-                                              block_probed,
-                                              fs_type_to_use,
-                                              &error);
-  if (mount_point_to_use == NULL)
-    {
-      g_dbus_method_invocation_return_gerror (invocation, error);
-      g_error_free (error);
-      goto out;
-    }
-
-  /* now check that the user is actually authorized to mount the device
-   *
-   * (TODO: fill in details and pick the right action_id)
-   */
-  auth_action_id = "org.freedesktop.udisks2.filesystem-mount",
-  auth_subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation));
-  auth_flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
-  if (!auth_no_user_interaction)
-    auth_flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
-  error = NULL;
-  auth_result = polkit_authority_check_authorization_sync (udisks_daemon_get_authority (daemon),
-                                                           auth_subject,
-                                                           auth_action_id,
-                                                           auth_details,
-                                                           auth_flags,
-                                                           NULL, /* GCancellable* */
-                                                           &error);
-  if (auth_result == NULL)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Error checking authorization: %s (%s, %d)",
-                                             error->message,
-                                             g_quark_to_string (error->domain),
-                                             error->code);
-      g_error_free (error);
-      goto out;
-    }
-  if (!polkit_authorization_result_get_is_authorized (auth_result))
-    {
-      g_dbus_method_invocation_return_error_literal (invocation,
-                                                     UDISKS_ERROR,
-                                                     polkit_authorization_result_get_is_challenge (auth_result) ?
-                                                     UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN :
-                                                     UDISKS_ERROR_NOT_AUTHORIZED,
-                                                     "Not authorized to perform operation");
-      goto out;
-    }
-
-  /* create the mount point */
-  if (g_mkdir (mount_point_to_use, 0700) != 0)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Error creating mount point `%s': %m",
-                                             mount_point_to_use);
-      goto out;
-    }
-
-  /* update the mounted-fs file */
-  if (!udisks_persistent_store_mounted_fs_add (store,
-                                               udisks_block_device_get_device (block),
-                                               mount_point_to_use,
-                                               caller_uid,
-                                               &error))
-    goto out;
-
-  escaped_fs_type_to_use       = g_strescape (fs_type_to_use, NULL);
-  escaped_mount_options_to_use = g_strescape (mount_options_to_use, NULL);
-  escaped_mount_point_to_use   = g_strescape (mount_point_to_use, NULL);
-
-  /* run mount(8) */
-  if (!udisks_daemon_launch_spawned_job_sync (daemon,
-                                              NULL,  /* GCancellable */
-                                              &error_message,
-                                              NULL,  /* input_string */
-                                              "mount -t \"%s\" -o \"%s\" \"%s\" \"%s\"",
-                                              escaped_fs_type_to_use,
-                                              escaped_mount_options_to_use,
-                                              udisks_block_device_get_device (block),
-                                              escaped_mount_point_to_use))
-    {
-      /* ugh, something went wrong.. we need to clean up the created mount point
-       * and also remove the entry from our mounted-fs file
-       *
-       * Either of these operations shouldn't really fail...
-       */
-      error = NULL;
-      if (!udisks_persistent_store_mounted_fs_remove (store,
-                                                      mount_point_to_use,
-                                                      &error))
-        {
-          udisks_daemon_log (daemon,
-                             UDISKS_LOG_LEVEL_WARNING,
-                             "Error removing mount point %s from filesystems file: %s (%s, %d)",
-                             mount_point_to_use,
-                             error->message,
-                             g_quark_to_string (error->domain),
-                             error->code);
-          g_error_free (error);
-        }
-      if (g_rmdir (mount_point_to_use) != 0)
-        {
-          udisks_daemon_log (daemon,
-                             UDISKS_LOG_LEVEL_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_device_get_device (block),
-                                             mount_point_to_use,
-                                             error_message);
-      goto out;
-    }
-
-  udisks_daemon_log (daemon,
-                     UDISKS_LOG_LEVEL_INFO,
-                     "Mounted %s at %s on behalf of uid %d",
-                     udisks_block_device_get_device (block),
-                     mount_point_to_use,
-                     caller_uid);
-
-  udisks_filesystem_complete_mount (filesystem, invocation, mount_point_to_use);
-
- out:
-  if (auth_subject != NULL)
-    g_object_unref (auth_subject);
-  if (auth_details != NULL)
-    g_object_unref (auth_details);
-  if (auth_result != NULL)
-    g_object_unref (auth_result);
-  g_free (error_message);
-  g_free (escaped_fs_type_to_use);
-  g_free (escaped_mount_options_to_use);
-  g_free (escaped_mount_point_to_use);
-  g_free (fs_type_to_use);
-  g_free (mount_options_to_use);
-  g_free (mount_point_to_use);
-  if (object != NULL)
-    g_object_unref (object);
-  if (block != NULL)
-    g_object_unref (block);
-  if (block_probed != NULL)
-    g_object_unref (block_probed);
-
-  return TRUE; /* returning TRUE means that we handled the method invocation */
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-/* runs in thread dedicated to handling method call */
-static gboolean
-handle_unmount (UDisksFilesystem       *filesystem,
-                GDBusMethodInvocation  *invocation,
-                const gchar* const     *options)
-{
-  GDBusObject *object;
-  UDisksBlockDevice *block;
-  UDisksDaemon *daemon;
-  UDisksPersistentStore *store;
-  gchar *mount_point;
-  gchar *escaped_mount_point;
-  GError *error;
-  uid_t mounted_by_uid;
-  uid_t caller_uid;
-  gchar *error_message;
-  const gchar *const *mount_points;
-  guint n;
-  gboolean opt_force;
-  gboolean rc;
-
-  mount_point = NULL;
-  escaped_mount_point = NULL;
-  error_message = NULL;
-  opt_force = FALSE;
-
-  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (filesystem));
-  block = UDISKS_BLOCK_DEVICE (g_dbus_object_lookup_interface (object, "org.freedesktop.UDisks2.BlockDevice"));
-  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++)
-    {
-      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;
-        }
-    }
-
-  mount_points = udisks_filesystem_get_mount_points (filesystem);
-  if (mount_points == NULL || g_strv_length ((gchar **) mount_points) == 0)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_NOT_MOUNTED,
-                                             "Device `%s' is not mounted",
-                                             udisks_block_device_get_device (block));
-      goto out;
-    }
-
-  error = NULL;
-  mount_point = udisks_persistent_store_mounted_fs_find (store,
-                                                         udisks_block_device_get_device (block),
-                                                         &mounted_by_uid,
-                                                         &error);
-  if (error != NULL)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Error when looking for entry `%s' in mounted-fs: %s (%s, %d)",
-                                             udisks_block_device_get_device (block),
-                                             error->message,
-                                             g_quark_to_string (error->domain),
-                                             error->code);
-      g_error_free (error);
-      goto out;
-    }
-  if (mount_point == NULL)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Entry for `%s' not found in mounted-fs",
-                                             udisks_block_device_get_device (block));
-      goto out;
-    }
-
-  /* TODO: allow unmounting stuff not in the mounted-fs file? */
-
-  error = NULL;
-  if (!get_uid_sync (invocation, NULL, &caller_uid, &error))
-    {
-      g_dbus_method_invocation_return_gerror (invocation, error);
-      g_error_free (error);
-      goto out;
-    }
-
-  if (caller_uid != 0 && (caller_uid != mounted_by_uid))
-    {
-      /* TODO: allow with special authorization (unmount-others) */
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_MOUNTED_BY_OTHER_USER,
-                                             "Cannot unmount filesystem at `%s' mounted by other user with uid %d",
-                                             mount_point,
-                                             mounted_by_uid);
-      goto out;
-    }
-
-  /* otherwise go ahead and unmount the filesystem */
-  if (!udisks_persistent_store_mounted_fs_currently_unmounting_add (store, mount_point))
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_ALREADY_UNMOUNTING,
-                                             "Cannot unmount %s: Mount point `%s' is currently being unmounted",
-                                             udisks_block_device_get_device (block),
-                                             mount_point);
-      goto out;
-    }
-
-  escaped_mount_point = g_strescape (mount_point, NULL);
-  if (opt_force)
-    {
-      /* right now -l is the only way to "force unmount" file systems... */
-      rc = udisks_daemon_launch_spawned_job_sync (daemon,
-                                                  NULL,  /* GCancellable */
-                                                  &error_message,
-                                                  NULL,  /* input_string */
-                                                  "umount -l \"%s\"",
-                                                  escaped_mount_point);
-    }
-  else
-    {
-      rc = udisks_daemon_launch_spawned_job_sync (daemon,
-                                                  NULL,  /* GCancellable */
-                                                  &error_message,
-                                                  NULL,  /* input_string */
-                                                  "umount \"%s\"",
-                                                  escaped_mount_point);
-    }
-  if (!rc)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Error unmounting %s from %s: %s",
-                                             udisks_block_device_get_device (block),
-                                             mount_point,
-                                             error_message);
-      udisks_persistent_store_mounted_fs_currently_unmounting_remove (store, mount_point);
-      goto out;
-    }
-
-  /* OK, filesystem unmounted.. now to remove the entry from mounted-fs as well as the mount point */
-  error = NULL;
-  if (!udisks_persistent_store_mounted_fs_remove (store,
-                                                  mount_point,
-                                                  &error))
-    {
-      if (error == NULL)
-        {
-          g_dbus_method_invocation_return_error (invocation,
-                                                 UDISKS_ERROR,
-                                                 UDISKS_ERROR_FAILED,
-                                                 "Error removing entry for `%s' from mounted-fs: Entry not found",
-                                                 mount_point);
-        }
-      else
-        {
-          g_dbus_method_invocation_return_error (invocation,
-                                                 UDISKS_ERROR,
-                                                 UDISKS_ERROR_FAILED,
-                                                 "Error removing entry for `%s' from mounted-fs: %s (%s, %d)",
-                                                 mount_point,
-                                                 error->message,
-                                                 g_quark_to_string (error->domain),
-                                                 error->code);
-          g_error_free (error);
-        }
-      udisks_persistent_store_mounted_fs_currently_unmounting_remove (store, mount_point);
-      goto out;
-    }
-  udisks_persistent_store_mounted_fs_currently_unmounting_remove (store, mount_point);
-
-  /* OK, removed the entry. Finally: nuke the mount point */
-  if (g_rmdir (mount_point) != 0)
-    {
-      udisks_daemon_log (daemon,
-                         UDISKS_LOG_LEVEL_ERROR,
-                         "Error removing mount point `%s': %m",
-                         mount_point);
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR,
-                                             UDISKS_ERROR_FAILED,
-                                             "Error removing mount point `%s': %m",
-                                             mount_point);
-      goto out;
-    }
-
-  udisks_daemon_log (daemon,
-                     UDISKS_LOG_LEVEL_INFO,
-                     "Unmounted %s from %s on behalf of uid %d",
-                     udisks_block_device_get_device (block),
-                     mount_point,
-                     caller_uid);
-
-  udisks_filesystem_complete_unmount (filesystem, invocation);
-
- out:
-  g_free (error_message);
-  g_free (escaped_mount_point);
-  g_free (mount_point);
-  g_object_unref (block);
-  g_object_unref (object);
-  return TRUE;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-filesystem_iface_init (UDisksFilesystemIface *iface)
-{
-  iface->handle_mount   = handle_mount;
-  iface->handle_unmount = handle_unmount;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/udisksfilesystemimpl.h b/src/udisksfilesystemimpl.h
deleted file mode 100644 (file)
index 1f17943..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef __UDISKS_FILESYSTEM_IMPL_H__
-#define __UDISKS_FILESYSTEM_IMPL_H__
-
-#include "types.h"
-
-G_BEGIN_DECLS
-
-#define UDISKS_TYPE_FILESYSTEM_IMPL         (udisks_filesystem_impl_get_type ())
-#define UDISKS_FILESYSTEM_IMPL(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_FILESYSTEM_IMPL, UDisksFilesystemImpl))
-#define UDISKS_IS_FILESYSTEM_IMPL(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_FILESYSTEM_IMPL))
-
-GType             udisks_filesystem_impl_get_type (void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __UDISKS_FILESYSTEM_IMPL_H__ */
index f94b395..2778b53 100644 (file)
 
 #include "config.h"
 
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib/gstdio.h>
+
 #include "udisksdaemon.h"
 #include "udisksdaemonutil.h"
 #include "udiskslinuxblock.h"
-#include "udisksfilesystemimpl.h"
 #include "udisksmount.h"
 #include "udisksmountmonitor.h"
 #include "udiskslinuxdrive.h"
+#include "udiskspersistentstore.h"
 
 /**
  * SECTION:udiskslinuxblock
@@ -56,8 +64,6 @@ struct _UDisksLinuxBlock
   /* interface */
   UDisksLinuxSysfsDevice *iface_linux_sysfs_device;
   UDisksBlockDevice *iface_block_device;
-  UDisksBlockDeviceProbed *iface_block_device_probed;
-  UDisksFilesystem *iface_filesystem;
 };
 
 struct _UDisksLinuxBlockClass
@@ -96,10 +102,6 @@ udisks_linux_block_finalize (GObject *object)
     g_object_unref (block->iface_linux_sysfs_device);
   if (block->iface_block_device != NULL)
     g_object_unref (block->iface_block_device);
-  if (block->iface_block_device_probed != NULL)
-    g_object_unref (block->iface_block_device_probed);
-  if (block->iface_filesystem != NULL)
-    g_object_unref (block->iface_filesystem);
 
   if (G_OBJECT_CLASS (udisks_linux_block_parent_class)->finalize != NULL)
     G_OBJECT_CLASS (udisks_linux_block_parent_class)->finalize (object);
@@ -292,6 +294,7 @@ udisks_linux_block_get_device (UDisksLinuxBlock *block)
 /* ---------------------------------------------------------------------------------------------------- */
 
 typedef gboolean (*HasInterfaceFunc)    (UDisksLinuxBlock     *block);
+typedef void     (*ConnectInterfaceFunc) (UDisksLinuxBlock     *block);
 typedef void     (*UpdateInterfaceFunc) (UDisksLinuxBlock     *block,
                                          const gchar    *uevent_action,
                                          GDBusInterface *interface);
@@ -300,6 +303,7 @@ static void
 update_iface (UDisksLinuxBlock           *block,
               const gchar          *uevent_action,
               HasInterfaceFunc      has_func,
+              ConnectInterfaceFunc   connect_func,
               UpdateInterfaceFunc   update_func,
               GType                 stub_type,
               gpointer              _interface_pointer)
@@ -323,6 +327,8 @@ update_iface (UDisksLinuxBlock           *block,
       if (has)
         {
           *interface_pointer = g_object_new (stub_type, NULL);
+          if (connect_func != NULL)
+            connect_func (block);
           add = TRUE;
         }
     }
@@ -356,6 +362,30 @@ block_device_check (UDisksLinuxBlock *block)
   return TRUE;
 }
 
+static gboolean
+handle_mount (UDisksBlockDevice      *block,
+              GDBusMethodInvocation  *invocation,
+              const gchar            *requested_fs_type,
+              const gchar* const     *requested_options);
+
+static gboolean
+handle_unmount (UDisksBlockDevice      *block,
+                GDBusMethodInvocation  *invocation,
+                const gchar* const     *options);
+
+static void
+block_device_connect (UDisksLinuxBlock *block)
+{
+  g_signal_connect (block->iface_block_device,
+                    "handle-filesystem-mount",
+                    G_CALLBACK (handle_mount),
+                    NULL);
+  g_signal_connect (block->iface_block_device,
+                    "handle-filesystem-unmount",
+                    G_CALLBACK (handle_unmount),
+                    NULL);
+}
+
 static gchar *
 find_drive (GDBusObjectManager *object_manager,
             GUdevDevice        *block_device)
@@ -416,6 +446,10 @@ block_device_update (UDisksLinuxBlock      *block,
   GUdevDeviceNumber dev;
   GDBusObjectManager *object_manager;
   gchar *drive_object_path;
+  gchar *s;
+  GList *mounts;
+  GList *l;
+  GPtrArray *p;
 
   dev = g_udev_device_get_device_number (block->device);
 
@@ -439,36 +473,33 @@ block_device_update (UDisksLinuxBlock      *block,
     {
       udisks_block_device_set_drive (iface, "/");
     }
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-/* org.freedesktop.UDisks.BlockDeviceProbed */
-
-static gboolean
-block_device_probed_check (UDisksLinuxBlock *block)
-{
-  return g_udev_device_has_property (block->device, "ID_FS_USAGE");
-}
-
-static void
-block_device_probed_update (UDisksLinuxBlock      *block,
-                            const gchar     *uevent_action,
-                            GDBusInterface  *_iface)
-{
-  UDisksBlockDeviceProbed *iface = UDISKS_BLOCK_DEVICE_PROBED (_iface);
-  gchar *s;
-
-  udisks_block_device_probed_set_usage (iface, g_udev_device_get_property (block->device, "ID_FS_USAGE"));
-  udisks_block_device_probed_set_type (iface, g_udev_device_get_property (block->device, "ID_FS_TYPE"));
-  udisks_block_device_probed_set_version (iface, g_udev_device_get_property (block->device, "ID_FS_VERSION"));
 
+  udisks_block_device_set_id_usage (iface, g_udev_device_get_property (block->device, "ID_FS_USAGE"));
+  udisks_block_device_set_id_type (iface, g_udev_device_get_property (block->device, "ID_FS_TYPE"));
+  udisks_block_device_set_id_version (iface, g_udev_device_get_property (block->device, "ID_FS_VERSION"));
   s = udisks_decode_udev_string (g_udev_device_get_property (block->device, "ID_FS_LABEL_ENC"));
-  udisks_block_device_probed_set_label (iface, s);
+  udisks_block_device_set_id_label (iface, s);
   g_free (s);
-
   s = udisks_decode_udev_string (g_udev_device_get_property (block->device, "ID_FS_UUID_ENC"));
-  udisks_block_device_probed_set_uuid (iface, s);
+  udisks_block_device_set_id_uuid (iface, s);
   g_free (s);
+
+  p = g_ptr_array_new ();
+  mounts = udisks_mount_monitor_get_mounts_for_dev (block->mount_monitor,
+                                                    g_udev_device_get_device_number (block->device));
+  /* we are guaranteed that the list is sorted so if there are
+   * multiple mounts we'll always get the same order
+   */
+  for (l = mounts; l != NULL; l = l->next)
+    {
+      UDisksMount *mount = UDISKS_MOUNT (l->data);
+      g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount));
+    }
+  g_ptr_array_add (p, NULL);
+  udisks_block_device_set_filesystem_mount_points (iface, (const gchar *const *) p->pdata);
+  g_ptr_array_free (p, TRUE);
+  g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+  g_list_free (mounts);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -495,44 +526,6 @@ linux_sysfs_device_update (UDisksLinuxBlock      *block,
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
-/* org.freedesktop.UDisks.Filesystem */
-
-static gboolean
-filesystem_check (UDisksLinuxBlock *block)
-{
-  return g_strcmp0 (g_udev_device_get_property (block->device, "ID_FS_USAGE"), "filesystem") == 0;
-}
-
-static void
-filesystem_update (UDisksLinuxBlock      *block,
-                   const gchar     *uevent_action,
-                   GDBusInterface  *_iface)
-{
-  UDisksFilesystem *iface = UDISKS_FILESYSTEM (_iface);
-  GList *mounts;
-  GList *l;
-  GPtrArray *p;
-
-  p = g_ptr_array_new ();
-  mounts = udisks_mount_monitor_get_mounts_for_dev (block->mount_monitor,
-                                                    g_udev_device_get_device_number (block->device));
-  /* we are guaranteed that the list is sorted so if there are
-   * multiple mounts we'll always get the same order
-   */
-  for (l = mounts; l != NULL; l = l->next)
-    {
-      UDisksMount *mount = UDISKS_MOUNT (l->data);
-      g_ptr_array_add (p, (gpointer) udisks_mount_get_mount_path (mount));
-    }
-  g_ptr_array_add (p, NULL);
-  udisks_filesystem_set_mount_points (iface, (const gchar *const *) p->pdata);
-  g_ptr_array_free (p, TRUE);
-
-  g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
-  g_list_free (mounts);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
 
 /**
  * udisks_linux_block_uevent:
@@ -557,14 +550,10 @@ udisks_linux_block_uevent (UDisksLinuxBlock *block,
       g_object_notify (G_OBJECT (block), "device");
     }
 
-  update_iface (block, action, linux_sysfs_device_check, linux_sysfs_device_update,
+  update_iface (block, action, linux_sysfs_device_check, NULL, linux_sysfs_device_update,
                 UDISKS_TYPE_LINUX_SYSFS_DEVICE_STUB, &block->iface_linux_sysfs_device);
-  update_iface (block, action, block_device_check, block_device_update,
+  update_iface (block, action, block_device_check, block_device_connect, block_device_update,
                 UDISKS_TYPE_BLOCK_DEVICE_STUB, &block->iface_block_device);
-  update_iface (block, action, block_device_probed_check, block_device_probed_update,
-                UDISKS_TYPE_BLOCK_DEVICE_PROBED_STUB, &block->iface_block_device_probed);
-  update_iface (block, action, filesystem_check, filesystem_update,
-                UDISKS_TYPE_FILESYSTEM_IMPL, &block->iface_filesystem);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -590,3 +579,1121 @@ on_mount_monitor_mount_removed (UDisksMountMonitor  *monitor,
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+get_uid_sync (GDBusMethodInvocation   *invocation,
+              GCancellable            *cancellable,
+              uid_t                   *out_uid,
+              GError                 **error)
+{
+  gboolean ret;
+  const gchar *caller;
+  GVariant *value;
+  GError *local_error;
+
+  ret = FALSE;
+
+  caller = g_dbus_method_invocation_get_sender (invocation);
+
+  local_error = NULL;
+  value = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (invocation),
+                                       "org.freedesktop.DBus",  /* bus name */
+                                       "/org/freedesktop/DBus", /* object path */
+                                       "org.freedesktop.DBus",  /* interface */
+                                       "GetConnectionUnixUser", /* method */
+                                       g_variant_new ("(s)", caller),
+                                       G_VARIANT_TYPE ("(u)"),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1, /* timeout_msec */
+                                       cancellable,
+                                       &local_error);
+  if (value == NULL)
+    {
+      g_set_error (error,
+                   UDISKS_ERROR,
+                   UDISKS_ERROR_FAILED,
+                   "Error determining uid of caller %s: %s (%s, %d)",
+                   caller,
+                   local_error->message,
+                   g_quark_to_string (local_error->domain),
+                   local_error->code);
+      g_error_free (local_error);
+      goto out;
+    }
+
+  G_STATIC_ASSERT (sizeof (uid_t) == sizeof (guint32));
+  g_variant_get (value, "(u)", out_uid);
+
+  ret = TRUE;
+
+ out:
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  const gchar *fstype;
+  const gchar * const *defaults;
+  const gchar * const *allow;
+  const gchar * const *allow_uid_self;
+  const gchar * const *allow_gid_self;
+} FSMountOptions;
+
+/* ---------------------- vfat -------------------- */
+
+static const gchar *vfat_defaults[] = { "uid=", "gid=", "shortname=mixed", "dmask=0077", "utf8=1", "showexec", NULL };
+static const gchar *vfat_allow[] = { "flush", "utf8=", "shortname=", "umask=", "dmask=", "fmask=", "codepage=", "iocharset=", "usefree", "showexec", NULL };
+static const gchar *vfat_allow_uid_self[] = { "uid=", NULL };
+static const gchar *vfat_allow_gid_self[] = { "gid=", NULL };
+
+/* ---------------------- ntfs -------------------- */
+/* this is assuming that ntfs-3g is used */
+
+static const gchar *ntfs_defaults[] = { "uid=", "gid=", "dmask=0077", "fmask=0177", NULL };
+static const gchar *ntfs_allow[] = { "umask=", "dmask=", "fmask=", NULL };
+static const gchar *ntfs_allow_uid_self[] = { "uid=", NULL };
+static const gchar *ntfs_allow_gid_self[] = { "gid=", NULL };
+
+/* ---------------------- iso9660 -------------------- */
+
+static const gchar *iso9660_defaults[] = { "uid=", "gid=", "iocharset=utf8", "mode=0400", "dmode=0500", NULL };
+static const gchar *iso9660_allow[] = { "norock", "nojoliet", "iocharset=", "mode=", "dmode=", NULL };
+static const gchar *iso9660_allow_uid_self[] = { "uid=", NULL };
+static const gchar *iso9660_allow_gid_self[] = { "gid=", NULL };
+
+/* ---------------------- udf -------------------- */
+
+static const gchar *udf_defaults[] = { "uid=", "gid=", "iocharset=utf8", "umask=0077", NULL };
+static const gchar *udf_allow[] = { "iocharset=", "umask=", NULL };
+static const gchar *udf_allow_uid_self[] = { "uid=", NULL };
+static const gchar *udf_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 FSMountOptions fs_mount_options[] =
+  {
+    { "vfat", vfat_defaults, vfat_allow, vfat_allow_uid_self, vfat_allow_gid_self },
+    { "ntfs", ntfs_defaults, ntfs_allow, ntfs_allow_uid_self, ntfs_allow_gid_self },
+    { "iso9660", iso9660_defaults, iso9660_allow, iso9660_allow_uid_self, iso9660_allow_gid_self },
+    { "udf", udf_defaults, udf_allow, udf_allow_uid_self, udf_allow_gid_self },
+  };
+
+/* ------------------------------------------------ */
+
+static int num_fs_mount_options = sizeof(fs_mount_options) / sizeof(FSMountOptions);
+
+static const FSMountOptions *
+find_mount_options_for_fs (const gchar *fstype)
+{
+  int n;
+  const FSMountOptions *fsmo;
+
+  for (n = 0; n < num_fs_mount_options; n++)
+    {
+      fsmo = fs_mount_options + n;
+      if (g_strcmp0 (fsmo->fstype, fstype) == 0)
+        goto out;
+    }
+
+  fsmo = NULL;
+ out:
+  return fsmo;
+}
+
+static gid_t
+find_primary_gid (uid_t uid)
+{
+  struct passwd *pw;
+  gid_t gid;
+
+  gid = (gid_t) - 1;
+
+  pw = getpwuid (uid);
+  if (pw == NULL)
+    {
+      g_warning ("Couldn't look up uid %d: %m", uid);
+      goto out;
+    }
+  gid = pw->pw_gid;
+
+ out:
+  return gid;
+}
+
+static gboolean
+is_uid_in_gid (uid_t uid,
+               gid_t gid)
+{
+  gboolean ret;
+  struct passwd *pw;
+  static gid_t supplementary_groups[128];
+  int num_supplementary_groups = 128;
+  int n;
+
+  /* TODO: use some #define instead of harcoding some random number like 128 */
+
+  ret = FALSE;
+
+  pw = getpwuid (uid);
+  if (pw == NULL)
+    {
+      g_warning ("Couldn't look up uid %d: %m", uid);
+      goto out;
+    }
+  if (pw->pw_gid == gid)
+    {
+      ret = TRUE;
+      goto out;
+    }
+
+  if (getgrouplist (pw->pw_name, pw->pw_gid, supplementary_groups, &num_supplementary_groups) < 0)
+    {
+      g_warning ("Couldn't find supplementary groups for uid %d: %m", uid);
+      goto out;
+    }
+
+  for (n = 0; n < num_supplementary_groups; n++)
+    {
+      if (supplementary_groups[n] == gid)
+        {
+          ret = TRUE;
+          goto out;
+        }
+    }
+
+ out:
+  return ret;
+}
+
+static gboolean
+is_mount_option_allowed (const FSMountOptions *fsmo,
+                         const gchar          *option,
+                         uid_t                 caller_uid)
+{
+  int n;
+  gchar *endp;
+  uid_t uid;
+  gid_t gid;
+  gboolean allowed;
+  const gchar *ep;
+  gsize ep_len;
+
+  allowed = FALSE;
+
+  /* first run through the allowed mount options */
+  if (fsmo != NULL)
+    {
+      for (n = 0; fsmo->allow != NULL && fsmo->allow[n] != NULL; n++)
+        {
+          ep = strstr (fsmo->allow[n], "=");
+          if (ep != NULL && ep[1] == '\0')
+            {
+              ep_len = ep - fsmo->allow[n] + 1;
+              if (strncmp (fsmo->allow[n], option, ep_len) == 0)
+                {
+                  allowed = TRUE;
+                  goto out;
+                }
+            }
+          else
+            {
+              if (strcmp (fsmo->allow[n], option) == 0)
+                {
+                  allowed = TRUE;
+                  goto out;
+                }
+            }
+        }
+    }
+  for (n = 0; any_allow[n] != NULL; n++)
+    {
+      ep = strstr (any_allow[n], "=");
+      if (ep != NULL && ep[1] == '\0')
+        {
+          ep_len = ep - any_allow[n] + 1;
+          if (strncmp (any_allow[n], option, ep_len) == 0)
+            {
+              allowed = TRUE;
+              goto out;
+            }
+        }
+      else
+        {
+          if (strcmp (any_allow[n], option) == 0)
+            {
+              allowed = TRUE;
+              goto out;
+            }
+        }
+    }
+
+  /* .. then check for mount options where the caller is allowed to pass
+   * in his own uid
+   */
+  if (fsmo != NULL)
+    {
+      for (n = 0; fsmo->allow_uid_self != NULL && fsmo->allow_uid_self[n] != NULL; n++)
+        {
+          const gchar *r_mount_option = fsmo->allow_uid_self[n];
+          if (g_str_has_prefix (option, r_mount_option))
+            {
+              uid = strtol (option + strlen (r_mount_option), &endp, 10);
+              if (*endp != '\0')
+                continue;
+              if (uid == caller_uid)
+                {
+                  allowed = TRUE;
+                  goto out;
+                }
+            }
+        }
+    }
+
+  /* .. ditto for gid
+   */
+  if (fsmo != NULL)
+    {
+      for (n = 0; fsmo->allow_gid_self != NULL && fsmo->allow_gid_self[n] != NULL; n++)
+        {
+          const gchar *r_mount_option = fsmo->allow_gid_self[n];
+          if (g_str_has_prefix (option, r_mount_option))
+            {
+              gid = strtol (option + strlen (r_mount_option), &endp, 10);
+              if (*endp != '\0')
+                continue;
+              if (is_uid_in_gid (caller_uid, gid))
+                {
+                  allowed = TRUE;
+                  goto out;
+                }
+            }
+        }
+    }
+
+ out:
+  return allowed;
+}
+
+static gchar **
+prepend_default_mount_options (const FSMountOptions *fsmo,
+                               uid_t caller_uid,
+                               const gchar * const *given_options)
+{
+  GPtrArray *options;
+  int n;
+  gchar *s;
+  gid_t gid;
+
+  options = g_ptr_array_new ();
+  if (fsmo != NULL)
+    {
+      for (n = 0; fsmo->defaults != NULL && fsmo->defaults[n] != NULL; n++)
+        {
+          const gchar *option = fsmo->defaults[n];
+
+          if (strcmp (option, "uid=") == 0)
+            {
+              s = g_strdup_printf ("uid=%d", caller_uid);
+              g_ptr_array_add (options, s);
+            }
+          else if (strcmp (option, "gid=") == 0)
+            {
+              gid = find_primary_gid (caller_uid);
+              if (gid != (gid_t) - 1)
+                {
+                  s = g_strdup_printf ("gid=%d", gid);
+                  g_ptr_array_add (options, s);
+                }
+            }
+          else
+            {
+              g_ptr_array_add (options, g_strdup (option));
+            }
+        }
+    }
+  for (n = 0; given_options[n] != NULL; n++)
+    {
+      g_ptr_array_add (options, g_strdup (given_options[n]));
+    }
+
+  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.
+ * @error: Return location for error or %NULL.
+ *
+ * Calculates the file system type to use.
+ *
+ * Returns: A valid UTF-8 string with the filesystem type (may be "auto") or %NULL if @error is set. Free with g_free().
+ */
+static gchar *
+calculate_fs_type (UDisksBlockDevice         *block,
+                   const gchar               *requested_fs_type,
+                   GError                   **error)
+{
+  gchar *fs_type_to_use;
+  const gchar *probed_fs_usage;
+  const gchar *probed_fs_type;
+
+  probed_fs_usage = NULL;
+  probed_fs_type = NULL;
+  if (block != NULL)
+    {
+      probed_fs_usage = udisks_block_device_get_id_usage (block);
+      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)
+    {
+      /* TODO: maybe check that it's compatible with probed_fs_type */
+      fs_type_to_use = g_strdup (requested_fs_type);
+    }
+  else
+    {
+      if (probed_fs_type != NULL && strlen (probed_fs_type) > 0)
+        fs_type_to_use = g_strdup (probed_fs_type);
+      else
+        fs_type_to_use = g_strdup ("auto");
+    }
+
+  g_assert (fs_type_to_use == NULL || g_utf8_validate (fs_type_to_use, -1, NULL));
+
+  return fs_type_to_use;
+}
+
+/*
+ * calculate_mount_options: <internal>
+ * @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.
+ * @error: Return location for error or %NULL.
+ *
+ * Calculates the mount option string to use. Ensures (by returning an
+ * error) that only safe options are used.
+ *
+ * Returns: A string with mount options or %NULL if @error is set. Free with g_free().
+ */
+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,
+                         GError                   **error)
+{
+  const FSMountOptions *fsmo;
+  gchar **options_to_use;
+  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);
+
+  /* validate mount options */
+  str = g_string_new ("uhelper=udisks2,nodev,nosuid");
+  for (n = 0; options_to_use[n] != NULL; n++)
+    {
+      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_set_error (error,
+                       UDISKS_ERROR,
+                       UDISKS_ERROR_OPTION_NOT_PERMITTED,
+                       "Malformed mount option `%s'",
+                       option);
+          g_string_free (str, TRUE);
+          goto out;
+        }
+
+      /* first check if the mount option is allowed */
+      if (!is_mount_option_allowed (fsmo, option, caller_uid))
+        {
+          g_set_error (error,
+                       UDISKS_ERROR,
+                       UDISKS_ERROR_OPTION_NOT_PERMITTED,
+                       "Mount option `%s' is not allowed",
+                       option);
+          g_string_free (str, TRUE);
+          goto out;
+        }
+
+      g_string_append_c (str, ',');
+      g_string_append (str, option);
+    }
+  options_to_use_str = g_string_free (str, FALSE);
+
+ out:
+  g_strfreev (options_to_use);
+
+  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 gchar *
+ensure_utf8 (const gchar *s)
+{
+  const gchar *end;
+  gchar *ret;
+
+  if (!g_utf8_validate (s, -1, &end))
+    {
+      gchar *tmp;
+      gint pos;
+      /* TODO: could possibly return a nicer UTF-8 string  */
+      pos = (gint) (end - s);
+      tmp = g_strndup (s, end - s);
+      ret = g_strdup_printf ("%s (Invalid UTF-8 at byte %d)", tmp, pos);
+      g_free (tmp);
+    }
+  else
+    {
+      ret = g_strdup (s);
+    }
+
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/*
+ * calculate_mount_point: <internal>
+ * @block: A #UDisksBlockDevice.
+ * @fs_type: The file system type to mount with
+ * @error: Return location for error or %NULL.
+ *
+ * Calculates the mount point to use.
+ *
+ * Returns: A UTF-8 string with the mount point to use or %NULL if @error is set. Free with g_free().
+ */
+static gchar *
+calculate_mount_point (UDisksBlockDevice         *block,
+                       const gchar               *fs_type,
+                       GError                   **error)
+{
+  const gchar *label;
+  const gchar *uuid;
+  gchar *mount_point;
+  gchar *orig_mount_point;
+  GString *str;
+  gchar *s;
+  guint n;
+
+  label = NULL;
+  uuid = NULL;
+  if (block != NULL)
+    {
+      label = udisks_block_device_get_id_label (block);
+      uuid = udisks_block_device_get_id_uuid (block);
+    }
+
+  /* NOTE: UTF-8 has the nice property that valid UTF-8 strings only contains
+   *       the byte 0x2F if it's for the '/' character (U+002F SOLIDUS).
+   *
+   *       See http://en.wikipedia.org/wiki/UTF-8 for details.
+   */
+
+  if (label != NULL && strlen (label) > 0)
+    {
+      str = g_string_new ("/media/");
+      s = ensure_utf8 (label);
+      for (n = 0; s[n] != '\0'; n++)
+        {
+          gint c = s[n];
+          if (c == '/')
+            g_string_append_c (str, '_');
+          else
+            g_string_append_c (str, c);
+        }
+      mount_point = g_string_free (str, FALSE);
+      g_free (s);
+    }
+  else if (uuid != NULL && strlen (uuid) > 0)
+    {
+      str = g_string_new ("/media/");
+      s = ensure_utf8 (uuid);
+      for (n = 0; s[n] != '\0'; n++)
+        {
+          gint c = s[n];
+          if (c == '/')
+            g_string_append_c (str, '_');
+          else
+            g_string_append_c (str, c);
+        }
+      mount_point = g_string_free (str, FALSE);
+      g_free (s);
+    }
+  else
+    {
+      mount_point = g_strdup ("/media/disk");
+    }
+
+  /* ... then uniqify the mount point */
+  orig_mount_point = g_strdup (mount_point);
+  n = 1;
+  while (TRUE)
+    {
+      if (!g_file_test (mount_point, G_FILE_TEST_EXISTS))
+        {
+          break;
+        }
+      else
+        {
+          g_free (mount_point);
+          mount_point = g_strdup_printf ("%s%d", orig_mount_point, n++);
+        }
+    }
+  g_free (orig_mount_point);
+
+  return mount_point;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* runs in thread dedicated to handling method call */
+static gboolean
+handle_mount (UDisksBlockDevice      *block,
+              GDBusMethodInvocation  *invocation,
+              const gchar            *requested_fs_type,
+              const gchar* const     *requested_options)
+{
+  GDBusObject *object;
+  UDisksDaemon *daemon;
+  UDisksPersistentStore *store;
+  gboolean ret;
+  uid_t caller_uid;
+  const gchar * const *existing_mount_points;
+  const gchar *probed_fs_usage;
+  const gchar *probed_fs_type;
+  gchar *fs_type_to_use;
+  gchar *mount_options_to_use;
+  gchar *mount_point_to_use;
+  gchar *escaped_fs_type_to_use;
+  gchar *escaped_mount_options_to_use;
+  gchar *escaped_mount_point_to_use;
+  gchar *error_message;
+  GError *error;
+  PolkitSubject *auth_subject;
+  const gchar *auth_action_id;
+  PolkitDetails *auth_details;
+  gboolean auth_no_user_interaction;
+  PolkitCheckAuthorizationFlags auth_flags;
+  PolkitAuthorizationResult *auth_result;
+
+  ret = FALSE;
+  object = NULL;
+  daemon = NULL;
+  error_message = NULL;
+  fs_type_to_use = NULL;
+  mount_options_to_use = NULL;
+  mount_point_to_use = NULL;
+  escaped_fs_type_to_use = NULL;
+  escaped_mount_options_to_use = NULL;
+  escaped_mount_point_to_use = NULL;
+  auth_subject = NULL;
+  auth_details = NULL;
+  auth_result = NULL;
+  auth_no_user_interaction = FALSE;
+
+  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
+  daemon = udisks_linux_block_get_daemon (UDISKS_LINUX_BLOCK (object));
+  store = udisks_daemon_get_persistent_store (daemon);
+
+  /* TODO: check if mount point is managed by e.g. /etc/fstab or
+   *       similar - if so, use that instead of managing mount points
+   *       in /media
+   */
+
+  /* Fail if the device is already mounted */
+  existing_mount_points = udisks_block_device_get_filesystem_mount_points (block);
+  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 (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_device_get_device (block),
+                                             str->str);
+      g_string_free (str, TRUE);
+      goto out;
+    }
+
+  /* Fail if the device is not mountable - we actually allow mounting
+   * devices that are not probed since since it could be that we just
+   * don't have the data in the udev database but the device has a
+   * filesystem *anyway*...
+   *
+   * For example, this applies to PC floppy devices - automatically
+   * probing for media them creates annoying noise. So they won't
+   * appear in the udev database.
+   */
+  probed_fs_usage = NULL;
+  probed_fs_type = NULL;
+  if (block != NULL)
+    {
+      probed_fs_usage = udisks_block_device_get_id_usage (block);
+      probed_fs_type = udisks_block_device_get_id_type (block);
+    }
+  if (probed_fs_usage != NULL && strlen (probed_fs_usage) > 0 &&
+      g_strcmp0 (probed_fs_usage, "filesystem") != 0)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Cannot mount block device %s with probed usage `%s' - expected `filesystem'",
+                                             udisks_block_device_get_device (block),
+                                             probed_fs_usage);
+      goto out;
+    }
+
+  /* we need the uid of the caller to check mount options */
+  error = NULL;
+  if (!get_uid_sync (invocation, NULL /* GCancellable */, &caller_uid, &error))
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* calculate filesystem type (guaranteed to be valid UTF-8) */
+  error = NULL;
+  fs_type_to_use = calculate_fs_type (block,
+                                      requested_fs_type,
+                                      &error);
+  if (fs_type_to_use == NULL)
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* calculate mount options (guaranteed to be valid UTF-8) */
+  error = NULL;
+  mount_options_to_use = calculate_mount_options (block,
+                                                  caller_uid,
+                                                  fs_type_to_use,
+                                                  requested_options,
+                                                  &auth_no_user_interaction,
+                                                  &error);
+  if (mount_options_to_use == NULL)
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* calculate mount point (guaranteed to be valid UTF-8) */
+  error = NULL;
+  mount_point_to_use = calculate_mount_point (block,
+                                              fs_type_to_use,
+                                              &error);
+  if (mount_point_to_use == NULL)
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* now check that the user is actually authorized to mount the device
+   *
+   * (TODO: fill in details and pick the right action_id)
+   */
+  auth_action_id = "org.freedesktop.udisks2.filesystem-mount",
+  auth_subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation));
+  auth_flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
+  if (!auth_no_user_interaction)
+    auth_flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
+  error = NULL;
+  auth_result = polkit_authority_check_authorization_sync (udisks_daemon_get_authority (daemon),
+                                                           auth_subject,
+                                                           auth_action_id,
+                                                           auth_details,
+                                                           auth_flags,
+                                                           NULL, /* GCancellable* */
+                                                           &error);
+  if (auth_result == NULL)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Error checking authorization: %s (%s, %d)",
+                                             error->message,
+                                             g_quark_to_string (error->domain),
+                                             error->code);
+      g_error_free (error);
+      goto out;
+    }
+  if (!polkit_authorization_result_get_is_authorized (auth_result))
+    {
+      g_dbus_method_invocation_return_error_literal (invocation,
+                                                     UDISKS_ERROR,
+                                                     polkit_authorization_result_get_is_challenge (auth_result) ?
+                                                     UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN :
+                                                     UDISKS_ERROR_NOT_AUTHORIZED,
+                                                     "Not authorized to perform operation");
+      goto out;
+    }
+
+  /* create the mount point */
+  if (g_mkdir (mount_point_to_use, 0700) != 0)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Error creating mount point `%s': %m",
+                                             mount_point_to_use);
+      goto out;
+    }
+
+  /* update the mounted-fs file */
+  if (!udisks_persistent_store_mounted_fs_add (store,
+                                               udisks_block_device_get_device (block),
+                                               mount_point_to_use,
+                                               caller_uid,
+                                               &error))
+    goto out;
+
+  escaped_fs_type_to_use       = g_strescape (fs_type_to_use, NULL);
+  escaped_mount_options_to_use = g_strescape (mount_options_to_use, NULL);
+  escaped_mount_point_to_use   = g_strescape (mount_point_to_use, NULL);
+
+  /* run mount(8) */
+  if (!udisks_daemon_launch_spawned_job_sync (daemon,
+                                              NULL,  /* GCancellable */
+                                              &error_message,
+                                              NULL,  /* input_string */
+                                              "mount -t \"%s\" -o \"%s\" \"%s\" \"%s\"",
+                                              escaped_fs_type_to_use,
+                                              escaped_mount_options_to_use,
+                                              udisks_block_device_get_device (block),
+                                              escaped_mount_point_to_use))
+    {
+      /* ugh, something went wrong.. we need to clean up the created mount point
+       * and also remove the entry from our mounted-fs file
+       *
+       * Either of these operations shouldn't really fail...
+       */
+      error = NULL;
+      if (!udisks_persistent_store_mounted_fs_remove (store,
+                                                      mount_point_to_use,
+                                                      &error))
+        {
+          udisks_daemon_log (daemon,
+                             UDISKS_LOG_LEVEL_WARNING,
+                             "Error removing mount point %s from filesystems file: %s (%s, %d)",
+                             mount_point_to_use,
+                             error->message,
+                             g_quark_to_string (error->domain),
+                             error->code);
+          g_error_free (error);
+        }
+      if (g_rmdir (mount_point_to_use) != 0)
+        {
+          udisks_daemon_log (daemon,
+                             UDISKS_LOG_LEVEL_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_device_get_device (block),
+                                             mount_point_to_use,
+                                             error_message);
+      goto out;
+    }
+
+  udisks_daemon_log (daemon,
+                     UDISKS_LOG_LEVEL_INFO,
+                     "Mounted %s at %s on behalf of uid %d",
+                     udisks_block_device_get_device (block),
+                     mount_point_to_use,
+                     caller_uid);
+
+  udisks_block_device_complete_filesystem_mount (block, invocation, mount_point_to_use);
+
+ out:
+  if (auth_subject != NULL)
+    g_object_unref (auth_subject);
+  if (auth_details != NULL)
+    g_object_unref (auth_details);
+  if (auth_result != NULL)
+    g_object_unref (auth_result);
+  g_free (error_message);
+  g_free (escaped_fs_type_to_use);
+  g_free (escaped_mount_options_to_use);
+  g_free (escaped_mount_point_to_use);
+  g_free (fs_type_to_use);
+  g_free (mount_options_to_use);
+  g_free (mount_point_to_use);
+  if (object != NULL)
+    g_object_unref (object);
+
+  return TRUE; /* returning TRUE means that we handled the method invocation */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* runs in thread dedicated to handling method call */
+static gboolean
+handle_unmount (UDisksBlockDevice      *block,
+                GDBusMethodInvocation  *invocation,
+                const gchar* const     *options)
+{
+  GDBusObject *object;
+  UDisksDaemon *daemon;
+  UDisksPersistentStore *store;
+  gchar *mount_point;
+  gchar *escaped_mount_point;
+  GError *error;
+  uid_t mounted_by_uid;
+  uid_t caller_uid;
+  gchar *error_message;
+  const gchar *const *mount_points;
+  guint n;
+  gboolean opt_force;
+  gboolean rc;
+
+  mount_point = NULL;
+  escaped_mount_point = NULL;
+  error_message = NULL;
+  opt_force = FALSE;
+
+  object = g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
+  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++)
+    {
+      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;
+        }
+    }
+
+  mount_points = udisks_block_device_get_filesystem_mount_points (block);
+  if (mount_points == NULL || g_strv_length ((gchar **) mount_points) == 0)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_NOT_MOUNTED,
+                                             "Device `%s' is not mounted",
+                                             udisks_block_device_get_device (block));
+      goto out;
+    }
+
+  error = NULL;
+  mount_point = udisks_persistent_store_mounted_fs_find (store,
+                                                         udisks_block_device_get_device (block),
+                                                         &mounted_by_uid,
+                                                         &error);
+  if (error != NULL)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Error when looking for entry `%s' in mounted-fs: %s (%s, %d)",
+                                             udisks_block_device_get_device (block),
+                                             error->message,
+                                             g_quark_to_string (error->domain),
+                                             error->code);
+      g_error_free (error);
+      goto out;
+    }
+  if (mount_point == NULL)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Entry for `%s' not found in mounted-fs",
+                                             udisks_block_device_get_device (block));
+      goto out;
+    }
+
+  /* TODO: allow unmounting stuff not in the mounted-fs file? */
+
+  error = NULL;
+  if (!get_uid_sync (invocation, NULL, &caller_uid, &error))
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  if (caller_uid != 0 && (caller_uid != mounted_by_uid))
+    {
+      /* TODO: allow with special authorization (unmount-others) */
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_MOUNTED_BY_OTHER_USER,
+                                             "Cannot unmount filesystem at `%s' mounted by other user with uid %d",
+                                             mount_point,
+                                             mounted_by_uid);
+      goto out;
+    }
+
+  /* otherwise go ahead and unmount the filesystem */
+  if (!udisks_persistent_store_mounted_fs_currently_unmounting_add (store, mount_point))
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_ALREADY_UNMOUNTING,
+                                             "Cannot unmount %s: Mount point `%s' is currently being unmounted",
+                                             udisks_block_device_get_device (block),
+                                             mount_point);
+      goto out;
+    }
+
+  escaped_mount_point = g_strescape (mount_point, NULL);
+  if (opt_force)
+    {
+      /* right now -l is the only way to "force unmount" file systems... */
+      rc = udisks_daemon_launch_spawned_job_sync (daemon,
+                                                  NULL,  /* GCancellable */
+                                                  &error_message,
+                                                  NULL,  /* input_string */
+                                                  "umount -l \"%s\"",
+                                                  escaped_mount_point);
+    }
+  else
+    {
+      rc = udisks_daemon_launch_spawned_job_sync (daemon,
+                                                  NULL,  /* GCancellable */
+                                                  &error_message,
+                                                  NULL,  /* input_string */
+                                                  "umount \"%s\"",
+                                                  escaped_mount_point);
+    }
+  if (!rc)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Error unmounting %s from %s: %s",
+                                             udisks_block_device_get_device (block),
+                                             mount_point,
+                                             error_message);
+      udisks_persistent_store_mounted_fs_currently_unmounting_remove (store, mount_point);
+      goto out;
+    }
+
+  /* OK, filesystem unmounted.. now to remove the entry from mounted-fs as well as the mount point */
+  error = NULL;
+  if (!udisks_persistent_store_mounted_fs_remove (store,
+                                                  mount_point,
+                                                  &error))
+    {
+      if (error == NULL)
+        {
+          g_dbus_method_invocation_return_error (invocation,
+                                                 UDISKS_ERROR,
+                                                 UDISKS_ERROR_FAILED,
+                                                 "Error removing entry for `%s' from mounted-fs: Entry not found",
+                                                 mount_point);
+        }
+      else
+        {
+          g_dbus_method_invocation_return_error (invocation,
+                                                 UDISKS_ERROR,
+                                                 UDISKS_ERROR_FAILED,
+                                                 "Error removing entry for `%s' from mounted-fs: %s (%s, %d)",
+                                                 mount_point,
+                                                 error->message,
+                                                 g_quark_to_string (error->domain),
+                                                 error->code);
+          g_error_free (error);
+        }
+      udisks_persistent_store_mounted_fs_currently_unmounting_remove (store, mount_point);
+      goto out;
+    }
+  udisks_persistent_store_mounted_fs_currently_unmounting_remove (store, mount_point);
+
+  /* OK, removed the entry. Finally: nuke the mount point */
+  if (g_rmdir (mount_point) != 0)
+    {
+      udisks_daemon_log (daemon,
+                         UDISKS_LOG_LEVEL_ERROR,
+                         "Error removing mount point `%s': %m",
+                         mount_point);
+      g_dbus_method_invocation_return_error (invocation,
+                                             UDISKS_ERROR,
+                                             UDISKS_ERROR_FAILED,
+                                             "Error removing mount point `%s': %m",
+                                             mount_point);
+      goto out;
+    }
+
+  udisks_daemon_log (daemon,
+                     UDISKS_LOG_LEVEL_INFO,
+                     "Unmounted %s from %s on behalf of uid %d",
+                     udisks_block_device_get_device (block),
+                     mount_point,
+                     caller_uid);
+
+  udisks_block_device_complete_filesystem_unmount (block, invocation);
+
+ out:
+  g_free (error_message);
+  g_free (escaped_mount_point);
+  g_free (mount_point);
+  g_object_unref (object);
+  return TRUE;
+}
index c1a859e..8be94bc 100644 (file)
@@ -570,8 +570,8 @@ handle_command_mount_unmount (gint        *argc,
   GList *object_proxies;
   GDBusObjectProxy *object_proxy;
   UDisksBlockDevice *block;
-  UDisksFilesystem *filesystem;
   guint n;
+  const gchar * const *mount_points;
 
   ret = 1;
   opt_mount_unmount_object_path = NULL;
@@ -637,17 +637,16 @@ handle_command_mount_unmount (gint        *argc,
       object_proxies = g_dbus_proxy_manager_get_all (manager);
       for (l = object_proxies; l != NULL; l = l->next)
         {
-          const gchar * const *mount_points;
           gboolean is_mounted;
 
           object_proxy = G_DBUS_OBJECT_PROXY (l->data);
-          filesystem = UDISKS_PEEK_FILESYSTEM (object_proxy);
+          block = UDISKS_PEEK_BLOCK_DEVICE (object_proxy);
 
-          if (filesystem == NULL)
+          if (block == NULL)
             continue;
 
           is_mounted = FALSE;
-          mount_points = udisks_filesystem_get_mount_points (filesystem);
+          mount_points = udisks_block_device_get_filesystem_mount_points (block);
           if (mount_points != NULL && g_strv_length ((gchar **) mount_points) > 0)
             is_mounted = TRUE;
 
@@ -670,15 +669,13 @@ handle_command_mount_unmount (gint        *argc,
         {
           object_proxy = G_DBUS_OBJECT_PROXY (l->data);
           block = UDISKS_PEEK_BLOCK_DEVICE (object_proxy);
-          filesystem = UDISKS_PEEK_FILESYSTEM (object_proxy);
 
-          if (block != NULL && filesystem != NULL)
+          if (block != NULL)
             {
-              const gchar * const *mount_points;
               gboolean is_mounted;
 
               is_mounted = FALSE;
-              mount_points = udisks_filesystem_get_mount_points (filesystem);
+              mount_points = udisks_block_device_get_filesystem_mount_points (block);
               if (mount_points != NULL && g_strv_length ((gchar **) mount_points) > 0)
                 is_mounted = TRUE;
 
@@ -735,8 +732,9 @@ handle_command_mount_unmount (gint        *argc,
       goto out;
     }
 
-  filesystem = UDISKS_PEEK_FILESYSTEM (object_proxy);
-  if (filesystem == NULL)
+  mount_points = udisks_block_device_get_filesystem_mount_points (block);
+  if (g_strv_length ((gchar **) mount_points) == 0 &&
+      g_strcmp0 (udisks_block_device_get_id_usage (block), "filesystem") != 0)
     {
       g_printerr ("Device %s is not a filesystem.\n", udisks_block_device_get_device (block));
       g_object_unref (object_proxy);
@@ -755,12 +753,12 @@ handle_command_mount_unmount (gint        *argc,
       gchar *mount_path;
 
       error = NULL;
-      if (!udisks_filesystem_call_mount_sync (filesystem,
-                                              opt_mount_filesystem_type,
-                                              (const gchar *const *) opt_mount_unmount_options,
-                                              &mount_path,
-                                              NULL,                       /* GCancellable */
-                                              &error))
+      if (!udisks_block_device_call_filesystem_mount_sync (block,
+                                                           opt_mount_filesystem_type,
+                                                           (const gchar *const *) opt_mount_unmount_options,
+                                                           &mount_path,
+                                                           NULL,                       /* GCancellable */
+                                                           &error))
         {
           if (error->domain == UDISKS_ERROR &&
               error->code == UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN &&
@@ -786,10 +784,10 @@ handle_command_mount_unmount (gint        *argc,
       GError *error;
 
       error = NULL;
-      if (!udisks_filesystem_call_unmount_sync (filesystem,
-                                                (const gchar *const *) opt_mount_unmount_options,
-                                                NULL,         /* GCancellable */
-                                                &error))
+      if (!udisks_block_device_call_filesystem_unmount_sync (block,
+                                                             (const gchar *const *) opt_mount_unmount_options,
+                                                             NULL,         /* GCancellable */
+                                                             &error))
         {
           if (error->domain == UDISKS_ERROR &&
               error->code == UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN &&
index 797210f..1c369f4 100644 (file)
@@ -27,6 +27,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <string.h>
 
 #include <udisks/udisks.h>
 
@@ -89,14 +90,14 @@ main (int argc, char *argv[])
   GError *error;
   struct stat statbuf;
   GDBusObjectProxy *object_proxy;
-  UDisksFilesystem *filesystem;
+  UDisksBlockDevice *block;
   const gchar *unmount_options[1] = {NULL};
 
   ret = 1;
   manager = NULL;
   block_device_file = NULL;
   object_proxy = NULL;
-  filesystem = NULL;
+  block = NULL;
 
   g_type_init ();
 
@@ -142,18 +143,13 @@ main (int argc, char *argv[])
       goto out;
     }
 
-  filesystem = UDISKS_GET_FILESYSTEM (object_proxy);
-  if (filesystem == NULL)
-    {
-      g_printerr ("Object for block device file %s does not appear to be a file system\n", block_device_file);
-      goto out;
-    }
+  block = UDISKS_PEEK_BLOCK_DEVICE (object_proxy);
 
   error = NULL;
-  if (!udisks_filesystem_call_unmount_sync (filesystem,
-                                            unmount_options,
-                                            NULL, /* GCancellable */
-                                            &error))
+  if (!udisks_block_device_call_filesystem_unmount_sync (block,
+                                                         unmount_options,
+                                                         NULL, /* GCancellable */
+                                                         &error))
     {
       g_printerr ("Error unmounting %s: %s\n", block_device_file, error->message);
       g_error_free (error);
@@ -163,8 +159,6 @@ main (int argc, char *argv[])
   ret = 0;
 
  out:
-  if (filesystem != NULL)
-    g_object_unref (filesystem);
   if (object_proxy != NULL)
     g_object_unref (object_proxy);
   g_free (block_device_file);