[gvfs/wip/udisks2] udisks2: support unmounting non-udisks mounts using the /bin/umount command
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/wip/udisks2] udisks2: support unmounting non-udisks mounts using the /bin/umount command
- Date: Thu, 29 Sep 2011 20:28:42 +0000 (UTC)
commit 4f37ff4df75c9a8e80f06b9da2498d0e409923b0
Author: David Zeuthen <davidz redhat com>
Date: Thu Sep 29 16:27:56 2011 -0400
udisks2: support unmounting non-udisks mounts using the /bin/umount command
Signed-off-by: David Zeuthen <davidz redhat com>
monitor/udisks2/gvfsudisks2mount.c | 178 ++++++++++++++++++++--------
monitor/udisks2/gvfsudisks2volumemonitor.c | 37 ++++++
2 files changed, 165 insertions(+), 50 deletions(-)
---
diff --git a/monitor/udisks2/gvfsudisks2mount.c b/monitor/udisks2/gvfsudisks2mount.c
index a4e105e..0c8ab54 100644
--- a/monitor/udisks2/gvfsudisks2mount.c
+++ b/monitor/udisks2/gvfsudisks2mount.c
@@ -57,6 +57,8 @@ struct _GVfsUDisks2Mount
GObject parent;
GVfsUDisks2VolumeMonitor *monitor; /* owned by volume monitor */
+
+ /* may be NULL */
GVfsUDisks2Volume *volume; /* owned by volume monitor */
/* the following members are set in update_mount() */
@@ -68,7 +70,7 @@ struct _GVfsUDisks2Mount
gchar *mount_path;
gboolean can_unmount;
gchar *mount_entry_name;
- GIcon *mount_entry_icon;
+ gchar *mount_entry_fs_type;
gboolean is_burn_mount;
@@ -115,8 +117,7 @@ gvfs_udisks2_mount_finalize (GObject *object)
g_free (mount->mount_path);
g_free (mount->mount_entry_name);
- if (mount->mount_entry_icon != NULL)
- g_object_unref (mount->mount_entry_icon);
+ g_free (mount->mount_entry_fs_type);
if (mount->autorun_icon != NULL)
g_object_unref (mount->autorun_icon);
@@ -247,7 +248,20 @@ update_mount (GVfsUDisks2Mount *mount)
else if (mount->autorun_icon != NULL)
mount->icon = g_object_ref (mount->autorun_icon);
else
- mount->icon = mount->mount_entry_icon != NULL ? g_object_ref (mount->mount_entry_icon) : NULL;
+ {
+ const gchar *icon_name;
+ if (g_strcmp0 (mount->mount_entry_fs_type, "nfs") == 0 ||
+ g_strcmp0 (mount->mount_entry_fs_type, "nfs4") == 0 ||
+ g_strcmp0 (mount->mount_entry_fs_type, "cifs") == 0)
+ {
+ icon_name = "folder-remote";
+ }
+ else
+ {
+ icon_name = "drive-removable-media";
+ }
+ mount->icon = g_themed_icon_new_with_default_fallbacks (icon_name);
+ }
g_free (mount->name);
@@ -332,7 +346,7 @@ gvfs_udisks2_mount_new (GVfsUDisks2VolumeMonitor *monitor,
{
/* No ref on GUnixMountEntry so save values for later use */
mount->mount_entry_name = g_unix_mount_guess_name (mount_entry);
- mount->mount_entry_icon = g_unix_mount_guess_icon (mount_entry);
+ mount->mount_entry_fs_type = g_strdup (g_unix_mount_get_fs_type (mount_entry));
mount->device_file = g_strdup (g_unix_mount_get_device_path (mount_entry));
mount->mount_path = g_strdup (g_unix_mount_get_mount_path (mount_entry));
mount->root = g_file_new_for_path (mount->mount_path);
@@ -446,7 +460,7 @@ gvfs_udisks2_mount_get_volume (GMount *_mount)
GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (_mount);
GVolume *volume = NULL;
- if (mount->volume)
+ if (mount->volume != NULL)
volume = G_VOLUME (g_object_ref (mount->volume));
return volume;
}
@@ -657,6 +671,44 @@ on_mount_op_reply (GMountOperation *mount_operation,
}
static void
+unmount_show_busy (UnmountData *data,
+ const gchar *const *mount_points)
+{
+ GArray *processes;
+ const gchar *choices[3] = {NULL, NULL, NULL};
+ const gchar *message;
+
+ processes = get_busy_processes (mount_points);
+
+ if (data->mount_op_reply_handler_id == 0)
+ {
+ data->mount_op_reply_handler_id = g_signal_connect (data->mount_operation,
+ "reply",
+ G_CALLBACK (on_mount_op_reply),
+ data);
+ }
+ choices[0] = _("Unmount Anyway");
+ choices[1] = _("Cancel");
+ message = _("Volume is busy\n"
+ "One or more applications are keeping the volume busy.");
+ g_signal_emit_by_name (data->mount_operation,
+ "show-processes",
+ message,
+ processes,
+ choices);
+ /* set up a timer to try unmounting every two seconds - this will also
+ * update the list of busy processes
+ */
+ if (data->retry_unmount_timer_id == 0)
+ {
+ data->retry_unmount_timer_id = g_timeout_add_seconds (2,
+ on_retry_timer_cb,
+ data);
+ }
+ g_array_free (processes, TRUE);
+}
+
+static void
unmount_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
@@ -675,39 +727,7 @@ unmount_cb (GObject *source_object,
/* if the user passed in a GMountOperation, then do the GMountOperation::show-processes dance ... */
if (error->code == G_IO_ERROR_BUSY && data->mount_operation != NULL)
{
- GArray *processes;
- const gchar *choices[3] = {NULL, NULL, NULL};
- const gchar *message;
-
- processes = get_busy_processes (udisks_filesystem_get_mount_points (filesystem));
-
- if (data->mount_op_reply_handler_id == 0)
- {
- data->mount_op_reply_handler_id = g_signal_connect (data->mount_operation,
- "reply",
- G_CALLBACK (on_mount_op_reply),
- data);
- }
- choices[0] = _("Unmount Anyway");
- choices[1] = _("Cancel");
- message = _("Volume is busy\n"
- "One or more applications are keeping the volume busy.");
- g_signal_emit_by_name (data->mount_operation,
- "show-processes",
- message,
- processes,
- choices);
- /* set up a timer to try unmounting every two seconds - this will also
- * update the list of busy processes
- */
- if (data->retry_unmount_timer_id == 0)
- {
- data->retry_unmount_timer_id = g_timeout_add_seconds (2,
- on_retry_timer_cb,
- data);
- }
-
- g_array_free (processes, TRUE);
+ unmount_show_busy (data, udisks_filesystem_get_mount_points (filesystem));
goto out;
}
else
@@ -728,28 +748,86 @@ unmount_cb (GObject *source_object,
}
static void
-unmount_do (UnmountData *data,
- gboolean force)
+unmount_do_command (UnmountData *data,
+ gboolean force)
{
- UDisksBlock *block;
- UDisksFilesystem *filesystem;
- GVariantBuilder builder;
+ GError *error;
+ gint exit_status;
+ gchar *standard_error = NULL;
+ const gchar *umount_argv[4] = {"umount", NULL, NULL, NULL};
- if (data->mount->volume != NULL)
+ if (force)
{
- block = gvfs_udisks2_volume_get_block (data->mount->volume);
+ umount_argv[1] = "-l";
+ umount_argv[2] = data->mount->mount_path;
}
else
{
- g_simple_async_result_set_error (data->simple,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "Don't know how to unmount non-udisks object yet (TODO)");
+ umount_argv[1] = data->mount->mount_path;
+ }
+
+ /* TODO: we could do this async but it's probably not worth the effort */
+ error = NULL;
+ if (!g_spawn_sync (NULL, /* working dir */
+ (gchar **) umount_argv,
+ NULL, /* envp */
+ G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user_data for child_setup */
+ NULL, /* standard_output */
+ &standard_error, /* standard_error */
+ &exit_status,
+ &error))
+ {
+ g_prefix_error (&error, "Error running umount: ");
+ g_simple_async_result_take_error (data->simple, error);
g_simple_async_result_complete (data->simple);
unmount_data_free (data);
goto out;
}
+ if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0)
+ {
+ gvfs_udisks2_volume_monitor_update (data->mount->monitor);
+ g_simple_async_result_complete (data->simple);
+ unmount_data_free (data);
+ goto out;
+ }
+
+ if (standard_error != NULL && strstr (standard_error, "device is busy") != NULL)
+ {
+ const gchar *mount_points[2] = {NULL, NULL};
+ mount_points[0] = data->mount->mount_path;
+ unmount_show_busy (data, mount_points);
+ goto out;
+ }
+
+ g_simple_async_result_set_error (data->simple,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ standard_error);
+ g_simple_async_result_complete (data->simple);
+ unmount_data_free (data);
+
+ out:
+ g_free (standard_error);
+}
+
+static void
+unmount_do (UnmountData *data,
+ gboolean force)
+{
+ UDisksBlock *block;
+ UDisksFilesystem *filesystem;
+ GVariantBuilder builder;
+
+ if (data->mount->volume == NULL)
+ {
+ unmount_do_command (data, force);
+ goto out;
+ }
+
+ block = gvfs_udisks2_volume_get_block (data->mount->volume);
filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))));
if (filesystem == NULL)
{
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index f21c56d..3b46478 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -55,6 +55,7 @@ struct _GVfsUDisks2VolumeMonitor
UDisksClient *client;
GUdevClient *gudev_client;
+ GUnixMountMonitor *mount_monitor;
GList *last_mounts;
@@ -112,6 +113,12 @@ static void on_interface_proxy_properties_changed (GDBusObjectManagerClient *m
const gchar *const *invalidated_properties,
gpointer user_data);
+static void mountpoints_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data);
+
+static void mounts_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data);
+
G_DEFINE_TYPE (GVfsUDisks2VolumeMonitor, gvfs_udisks2_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR)
static void
@@ -129,6 +136,10 @@ gvfs_udisks2_volume_monitor_finalize (GObject *object)
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (object);
GDBusObjectManager *object_manager;
+ g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mountpoints_changed, monitor);
+ g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mounts_changed, monitor);
+ g_clear_object (&monitor->mount_monitor);
+
object_manager = udisks_client_get_object_manager (monitor->client);
g_signal_handlers_disconnect_by_func (object_manager,
G_CALLBACK (on_object_added),
@@ -346,6 +357,16 @@ gvfs_udisks2_volume_monitor_init (GVfsUDisks2VolumeMonitor *monitor)
G_CALLBACK (on_interface_proxy_properties_changed),
monitor);
+ monitor->mount_monitor = g_unix_mount_monitor_new ();
+ g_signal_connect (monitor->mount_monitor,
+ "mounts-changed",
+ G_CALLBACK (mounts_changed),
+ monitor);
+ g_signal_connect (monitor->mount_monitor,
+ "mountpoints-changed",
+ G_CALLBACK (mountpoints_changed),
+ monitor);
+
update_all (monitor, FALSE);
}
@@ -567,6 +588,22 @@ on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager,
update_all (monitor, TRUE);
}
+static void
+mountpoints_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data)
+{
+ GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
+ update_all (monitor, TRUE);
+}
+
+static void
+mounts_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data)
+{
+ GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
+ update_all (monitor, TRUE);
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]