Add "unmount" option to DriveEject
authorMartin Pitt <martin.pitt@ubuntu.com>
Sun, 3 Apr 2011 22:07:03 +0000 (00:07 +0200)
committerMartin Pitt <martin.pitt@ubuntu.com>
Sun, 19 Jun 2011 18:10:44 +0000 (20:10 +0200)
DriveEject currently fails if there are mounted file systems on the drive. Add
an option "unmount" which will unmount any mounted file system on the drive to
be ejected first. The "eject" command conveniently already does this, so the
only thing we need to do here is to skip the "is mounted" check in
device_local_is_busy().

data/org.freedesktop.UDisks.Device.xml
src/device.c

index 8b76ccb..991976d 100644 (file)
     <method name="DriveEject">
       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
       <arg name="options" direction="in" type="as">
-        <doc:doc><doc:summary>Eject options. Currently no options are recognized.</doc:summary></doc:doc>
+        <doc:doc><doc:summary>Eject options. Valid options currently include only 'unmount'.</doc:summary></doc:doc>
       </arg>
 
       <doc:doc>
         <doc:description>
           <doc:para>
-            Ejects media from the device.
+            Ejects media from the device. If the <doc:term>unmount</doc:term> option is given, the device might have mounted file systems, which will be unmounted before ejection.
           </doc:para>
         </doc:description>
         <doc:permission>
index 6a34940..b30fe1c 100644 (file)
@@ -87,6 +87,7 @@ static void drain_pending_changes (Device *device,
 
 static gboolean device_local_is_busy (Device *device,
                                       gboolean check_partitions,
+                                      gboolean check_mounted,
                                       GError **error);
 
 static gboolean device_local_partitions_are_busy (Device *device);
@@ -4840,6 +4841,7 @@ update_info (Device *device)
  * device_local_is_busy:
  * @device: A #Device.
  * @check_partitions: Whether to check if partitions is busy if @device is a partition table
+ * @check_mounted: Whether to check if device has mounted file systems
  * @error: Either %NULL or a #GError to set to #ERROR_BUSY and an appropriate
  * message, e.g. "Device is busy" or "A partition on the device is busy" if the device is busy.
  *
@@ -4850,6 +4852,7 @@ update_info (Device *device)
 static gboolean
 device_local_is_busy (Device *device,
                       gboolean check_partitions,
+                      gboolean check_mounted,
                       GError **error)
 {
   gboolean ret;
@@ -4864,7 +4867,7 @@ device_local_is_busy (Device *device,
     }
 
   /* or if we're mounted */
-  if (device->priv->device_is_mounted)
+  if (check_mounted && device->priv->device_is_mounted)
     {
       g_set_error (error, ERROR, ERROR_BUSY, "%s is mounted", device->priv->device_file);
       goto out;
@@ -4947,7 +4950,7 @@ device_local_partitions_are_busy (Device *device)
           == 0)
         {
 
-          if (device_local_is_busy (d, FALSE, NULL))
+          if (device_local_is_busy (d, FALSE, TRUE, NULL))
             {
               ret = TRUE;
               break;
@@ -4979,7 +4982,7 @@ device_local_logical_partitions_are_busy (Device *device)
           == 0 && g_strcmp0 (d->priv->partition_scheme, "mbr") == 0 && d->priv->partition_number >= 5)
         {
 
-          if (device_local_is_busy (d, FALSE, NULL))
+          if (device_local_is_busy (d, FALSE, TRUE, NULL))
             {
               ret = TRUE;
               break;
@@ -6404,7 +6407,7 @@ device_filesystem_mount_authorized_cb (Daemon *daemon,
         }
     }
 
-  if (device_local_is_busy (device, FALSE, &error))
+  if (device_local_is_busy (device, FALSE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -7050,6 +7053,7 @@ device_drive_eject_authorized_cb (Daemon *daemon,
   int n;
   char *argv[16];
   GError *error;
+  gboolean unmount = FALSE;
 
   error = NULL;
 
@@ -7065,20 +7069,30 @@ device_drive_eject_authorized_cb (Daemon *daemon,
       goto out;
     }
 
-  if (device_local_is_busy (device, TRUE, &error))
+  for (n = 0; options[n] != NULL; n++)
     {
-      throw_error (context, ERROR_BUSY, error->message);
-      g_error_free (error);
-      goto out;
+      const char *option = options[n];
+      if (strcmp ("unmount", option) == 0)
+        {
+          unmount = TRUE;
+        }
+      else
+        {
+          throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
+          goto out;
+       }
     }
 
-  for (n = 0; options[n] != NULL; n++)
+  /* If we specify the unmount option, don't check if the device is mounted */
+  if (device_local_is_busy (device, TRUE, !unmount, &error))
     {
-      const char *option = options[n];
-      throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
+      throw_error (context, ERROR_BUSY, error->message);
+      g_error_free (error);
       goto out;
     }
 
+  /* eject already unmounts the file systems on the ejected drive, so we do not
+   * need any particular handling of the unmount flag here */
   n = 0;
   argv[n++] = "eject";
   argv[n++] = device->priv->device_file;
@@ -7185,7 +7199,7 @@ device_drive_detach_authorized_cb (Daemon *daemon,
       goto out;
     }
 
-  if (device_local_is_busy (device, TRUE, &error))
+  if (device_local_is_busy (device, TRUE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -7405,7 +7419,7 @@ device_partition_delete_authorized_cb (Daemon *daemon,
   part_number_as_string = NULL;
   error = NULL;
 
-  if (device_local_is_busy (device, FALSE, &error))
+  if (device_local_is_busy (device, FALSE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -7425,7 +7439,7 @@ device_partition_delete_authorized_cb (Daemon *daemon,
       goto out;
     }
 
-  if (device_local_is_busy (enclosing_device, FALSE, &error))
+  if (device_local_is_busy (enclosing_device, FALSE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -7763,7 +7777,7 @@ device_filesystem_create_internal (Device *device,
   passphrase_stdin = NULL;
   error = NULL;
 
-  if (device_local_is_busy (device, TRUE, &error))
+  if (device_local_is_busy (device, TRUE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -8277,7 +8291,7 @@ device_partition_create_authorized_cb (Daemon *daemon,
       goto out;
     }
 
-  if (device_local_is_busy (device, FALSE, &error))
+  if (device_local_is_busy (device, FALSE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -8510,7 +8524,7 @@ device_partition_modify_authorized_cb (Daemon *daemon,
       goto out;
     }
 
-  if (device_local_is_busy (enclosing_device, FALSE, &error))
+  if (device_local_is_busy (enclosing_device, FALSE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -8754,7 +8768,7 @@ device_partition_table_create_authorized_cb (Daemon *daemon,
 
   error = NULL;
 
-  if (device_local_is_busy (device, TRUE, &error))
+  if (device_local_is_busy (device, TRUE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -9070,7 +9084,7 @@ device_luks_unlock_internal (Device *device,
 
   daemon_local_get_uid (device->priv->daemon, &uid, context);
 
-  if (device_local_is_busy (device, FALSE, &error))
+  if (device_local_is_busy (device, FALSE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -9700,7 +9714,7 @@ device_filesystem_set_label_authorized_cb (Daemon *daemon,
 
   if (!fs_details->supports_online_label_rename)
     {
-      if (device_local_is_busy (device, FALSE, &error))
+      if (device_local_is_busy (device, FALSE, TRUE, &error))
         {
           dbus_g_method_return_error (context, error);
           g_error_free (error);
@@ -9758,7 +9772,7 @@ device_filesystem_set_label (Device *device,
 
   if (!fs_details->supports_online_label_rename)
     {
-      if (device_local_is_busy (device, FALSE, &error))
+      if (device_local_is_busy (device, FALSE, TRUE, &error))
         {
           dbus_g_method_return_error (context, error);
           g_error_free (error);
@@ -10436,7 +10450,7 @@ device_linux_md_add_spare_authorized_cb (Daemon *daemon,
    * hot adding a new disk if an old one failed
    */
 
-  if (device_local_is_busy (slave, TRUE, &error))
+  if (device_local_is_busy (slave, TRUE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -10587,7 +10601,7 @@ device_linux_md_expand_authorized_cb (Daemon *daemon,
           goto out;
         }
 
-      if (device_local_is_busy (slave, TRUE, &error))
+      if (device_local_is_busy (slave, TRUE, TRUE, &error))
         {
           dbus_g_method_return_error (context, error);
           g_error_free (error);
@@ -10717,7 +10731,7 @@ linux_md_remove_component_device_changed_cb (Daemon *daemon,
   if (device == data->slave)
     {
 
-      if (device_local_is_busy (data->slave, FALSE, &error))
+      if (device_local_is_busy (data->slave, FALSE, TRUE, &error))
         {
           dbus_g_method_return_error (data->context, error);
           g_error_free (error);
@@ -11137,7 +11151,7 @@ daemon_linux_md_start_authorized_cb (Daemon *daemon,
             }
         }
 
-      if (device_local_is_busy (slave, FALSE, &error))
+      if (device_local_is_busy (slave, FALSE, TRUE, &error))
         {
           dbus_g_method_return_error (context, error);
           g_error_free (error);
@@ -11493,7 +11507,7 @@ daemon_linux_md_create_authorized_cb (Daemon *daemon,
           goto out;
         }
 
-      if (device_local_is_busy (slave, FALSE, &error))
+      if (device_local_is_busy (slave, FALSE, TRUE, &error))
         {
           dbus_g_method_return_error (context, error);
           g_error_free (error);
@@ -13733,7 +13747,7 @@ daemon_linux_lvm2_vg_add_pv_authorized_cb (Daemon *daemon,
     }
 
   error = NULL;
-  if (device_local_is_busy (pv, TRUE, &error))
+  if (device_local_is_busy (pv, TRUE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);
@@ -13863,7 +13877,7 @@ daemon_linux_lvm2_vg_remove_pv_authorized_cb (Daemon *daemon,
     }
 
   error = NULL;
-  if (device_local_is_busy (pv, TRUE, &error))
+  if (device_local_is_busy (pv, TRUE, TRUE, &error))
     {
       dbus_g_method_return_error (context, error);
       g_error_free (error);