[gvfs/wip/udisks2] udisks2: implement eject methods
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/wip/udisks2] udisks2: implement eject methods
- Date: Wed, 28 Sep 2011 20:25:50 +0000 (UTC)
commit a120992e117fea554055aceb52bc8377583dc754
Author: David Zeuthen <davidz redhat com>
Date: Wed Sep 28 16:25:19 2011 -0400
udisks2: implement eject methods
Signed-off-by: David Zeuthen <davidz redhat com>
monitor/udisks2/gvfsudisks2drive.c | 267 ++++++++++++++++++++++++++++++++++-
monitor/udisks2/gvfsudisks2mount.c | 105 ++++++++++++++-
monitor/udisks2/gvfsudisks2volume.c | 99 +++++++++++++-
3 files changed, 466 insertions(+), 5 deletions(-)
---
diff --git a/monitor/udisks2/gvfsudisks2drive.c b/monitor/udisks2/gvfsudisks2drive.c
index b83af8e..9ceb1ad 100644
--- a/monitor/udisks2/gvfsudisks2drive.c
+++ b/monitor/udisks2/gvfsudisks2drive.c
@@ -166,7 +166,7 @@ update_drive (GVfsUDisks2Drive *drive)
if (drive->is_media_removable)
{
drive->has_media = (udisks_drive_get_size (drive->udisks_drive) > 0);
- drive->can_eject = FALSE; // TODO: set to TRUE when eject() has been implemented
+ drive->can_eject = TRUE;
}
else
{
@@ -409,6 +409,269 @@ gvfs_udisks2_drive_enumerate_identifiers (GDrive *_drive)
/* ---------------------------------------------------------------------------------------------------- */
+typedef void (*UnmountsMountsFunc) (GDrive *drive,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ gpointer on_all_unmounted_data);
+
+typedef struct {
+ GDrive *drive;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GMountOperation *mount_operation;
+ GCancellable *cancellable;
+ GMountUnmountFlags flags;
+
+ GList *pending_mounts;
+
+ UnmountsMountsFunc on_all_unmounted;
+ gpointer on_all_unmounted_data;
+} UnmountMountsOp;
+
+static void
+free_unmount_mounts_op (UnmountMountsOp *data)
+{
+ GList *l;
+ for (l = data->pending_mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = G_MOUNT (l->data);
+ g_object_unref (mount);
+ }
+ g_list_free (data->pending_mounts);
+}
+
+static void
+unmount_mounts_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+static void
+unmount_mounts_do (UnmountMountsOp *data)
+{
+ if (data->pending_mounts == NULL)
+ {
+ data->on_all_unmounted (data->drive,
+ data->mount_operation,
+ data->cancellable,
+ data->callback,
+ data->user_data,
+ data->on_all_unmounted_data);
+
+ g_object_unref (data->drive);
+ g_free (data);
+ }
+ else
+ {
+ GMount *mount;
+ mount = data->pending_mounts->data;
+ data->pending_mounts = g_list_remove (data->pending_mounts, mount);
+
+ g_mount_unmount_with_operation (mount,
+ data->flags,
+ data->mount_operation,
+ data->cancellable,
+ unmount_mounts_cb,
+ data);
+ }
+}
+
+static void
+unmount_mounts_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ UnmountMountsOp *data = user_data;
+ GMount *mount = G_MOUNT (source_object);
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ if (!g_mount_unmount_with_operation_finish (mount, res, &error))
+ {
+ /* make the error dialog more targeted to the drive.. unless the user has already seen a dialog */
+ if (error->code != G_IO_ERROR_FAILED_HANDLED)
+ {
+ g_error_free (error);
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("Failed to eject medium; one or more volumes on the medium are busy."));
+ }
+
+ /* unmount failed; need to fail the whole eject operation */
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ free_unmount_mounts_op (data);
+ }
+ else
+ {
+ /* move on to the next mount.. */
+ unmount_mounts_do (data);
+ }
+ g_object_unref (mount);
+}
+
+static void
+unmount_mounts (GVfsUDisks2Drive *drive,
+ GMountUnmountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ UnmountsMountsFunc on_all_unmounted,
+ gpointer on_all_unmounted_data)
+{
+ GMount *mount;
+ UnmountMountsOp *data;
+ GList *l;
+
+ data = g_new0 (UnmountMountsOp, 1);
+ data->drive = g_object_ref (drive);
+ data->mount_operation = mount_operation;
+ data->cancellable = cancellable;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->flags = flags;
+ data->on_all_unmounted = on_all_unmounted;
+ data->on_all_unmounted_data = on_all_unmounted_data;
+
+ for (l = drive->volumes; l != NULL; l = l->next)
+ {
+ GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (l->data);
+ mount = g_volume_get_mount (G_VOLUME (volume));
+ if (mount != NULL && g_mount_can_unmount (mount))
+ data->pending_mounts = g_list_prepend (data->pending_mounts, g_object_ref (mount));
+ }
+
+ unmount_mounts_do (data);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ GSimpleAsyncResult *simple;
+
+ GVfsUDisks2Drive *drive;
+} EjectData;
+
+static void
+eject_data_free (EjectData *data)
+{
+ g_object_unref (data->simple);
+ g_clear_object (&data->drive);
+ g_free (data);
+}
+
+static void
+eject_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectData *data = user_data;
+ GError *error;
+
+ error = NULL;
+ if (!udisks_drive_call_eject_finish (UDISKS_DRIVE (source_object), res, &error))
+ {
+ g_simple_async_result_take_error (data->simple, error);
+ g_simple_async_result_complete (data->simple);
+ goto out;
+ }
+
+ g_simple_async_result_complete (data->simple);
+
+ out:
+ eject_data_free (data);
+}
+
+static void
+gvfs_udisks2_drive_eject_on_all_unmounted (GDrive *_drive,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ gpointer on_all_unmounted_data)
+{
+ GVfsUDisks2Drive *drive = GVFS_UDISKS2_DRIVE (_drive);
+ GVariantBuilder builder;
+ EjectData *data;
+
+ data = g_new0 (EjectData, 1);
+ data->simple = g_simple_async_result_new (G_OBJECT (drive),
+ callback,
+ user_data,
+ gvfs_udisks2_drive_eject_on_all_unmounted);
+ data->drive = g_object_ref (drive);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ if (mount_operation == NULL)
+ {
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "auth.no_user_interaction", g_variant_new_boolean (TRUE));
+ }
+ udisks_drive_call_eject (drive->udisks_drive,
+ g_variant_builder_end (&builder),
+ cancellable,
+ eject_cb,
+ data);
+}
+
+static void
+gvfs_udisks2_drive_eject_with_operation (GDrive *_drive,
+ GMountUnmountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GVfsUDisks2Drive *drive = GVFS_UDISKS2_DRIVE (_drive);
+
+ /* first we need to go through all the volumes and unmount their assoicated mounts (if any) */
+ unmount_mounts (drive,
+ flags,
+ mount_operation,
+ cancellable,
+ callback,
+ user_data,
+ gvfs_udisks2_drive_eject_on_all_unmounted,
+ NULL);
+}
+
+static gboolean
+gvfs_udisks2_drive_eject_with_operation_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+}
+
+static void
+gvfs_udisks2_drive_eject (GDrive *drive,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ gvfs_udisks2_drive_eject_with_operation (drive, flags, NULL, cancellable, callback, user_data);
+}
+
+static gboolean
+gvfs_udisks2_drive_eject_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ return gvfs_udisks2_drive_eject_with_operation_finish (drive, result, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
gvfs_udisks2_drive_drive_iface_init (GDriveIface *iface)
{
@@ -428,11 +691,11 @@ gvfs_udisks2_drive_drive_iface_init (GDriveIface *iface)
iface->can_start_degraded = gvfs_udisks2_drive_can_start_degraded;
iface->can_stop = gvfs_udisks2_drive_can_stop;
-#if 0
iface->eject = gvfs_udisks2_drive_eject;
iface->eject_finish = gvfs_udisks2_drive_eject_finish;
iface->eject_with_operation = gvfs_udisks2_drive_eject_with_operation;
iface->eject_with_operation_finish = gvfs_udisks2_drive_eject_with_operation_finish;
+#if 0
iface->poll_for_media = gvfs_udisks2_drive_poll_for_media;
iface->poll_for_media_finish = gvfs_udisks2_drive_poll_for_media_finish;
iface->start = gvfs_udisks2_drive_start;
diff --git a/monitor/udisks2/gvfsudisks2mount.c b/monitor/udisks2/gvfsudisks2mount.c
index 6d82b61..728b158 100644
--- a/monitor/udisks2/gvfsudisks2mount.c
+++ b/monitor/udisks2/gvfsudisks2mount.c
@@ -847,6 +847,109 @@ gvfs_udisks2_mount_unmount_finish (GMount *mount,
/* ---------------------------------------------------------------------------------------------------- */
+typedef struct
+{
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+gvfs_udisks2_mount_eject_with_operation (GMount *_mount,
+ GMountUnmountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (_mount);
+ GDrive *drive;
+
+ drive = NULL;
+ if (mount->volume != NULL)
+ drive = g_volume_get_drive (G_VOLUME (mount->volume));
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject_with_operation (drive, flags, mount_operation, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+ else
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_error (G_OBJECT (mount),
+ callback,
+ user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Operation not supported by backend"));
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+}
+
+static gboolean
+gvfs_udisks2_mount_eject_with_operation_finish (GMount *_mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (_mount);
+ gboolean ret = TRUE;
+ GDrive *drive;
+
+ drive = NULL;
+ if (mount->volume != NULL)
+ drive = g_volume_get_drive (G_VOLUME (mount->volume));
+
+ if (drive != NULL)
+ {
+ ret = g_drive_eject_with_operation_finish (drive, result, error);
+ g_object_unref (drive);
+ }
+ else
+ {
+ g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static void
+gvfs_udisks2_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ gvfs_udisks2_mount_eject_with_operation (mount, flags, NULL, cancellable, callback, user_data);
+}
+
+static gboolean
+gvfs_udisks2_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ return gvfs_udisks2_mount_eject_with_operation_finish (mount, result, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
gvfs_udisks2_mount_mount_iface_init (GMountIface *iface)
{
@@ -862,11 +965,11 @@ gvfs_udisks2_mount_mount_iface_init (GMountIface *iface)
iface->unmount_finish = gvfs_udisks2_mount_unmount_finish;
iface->unmount_with_operation = gvfs_udisks2_mount_unmount_with_operation;
iface->unmount_with_operation_finish = gvfs_udisks2_mount_unmount_with_operation_finish;
-#if 0
iface->eject = gvfs_udisks2_mount_eject;
iface->eject_finish = gvfs_udisks2_mount_eject_finish;
iface->eject_with_operation = gvfs_udisks2_mount_eject_with_operation;
iface->eject_with_operation_finish = gvfs_udisks2_mount_eject_with_operation_finish;
+#if 0
iface->guess_content_type = gvfs_udisks2_mount_guess_content_type;
iface->guess_content_type_finish = gvfs_udisks2_mount_guess_content_type_finish;
iface->guess_content_type_sync = gvfs_udisks2_mount_guess_content_type_sync;
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index 440bd99..d2b1537 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -636,6 +636,103 @@ gvfs_udisks2_volume_mount_finish (GVolume *volume,
/* ---------------------------------------------------------------------------------------------------- */
+typedef struct
+{
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+gvfs_udisks2_volume_eject_with_operation (GVolume *_volume,
+ GMountUnmountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (_volume);
+ GVfsUDisks2Drive *drive;
+
+ drive = NULL;
+ if (volume->drive != NULL)
+ drive = g_object_ref (volume->drive);
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject_with_operation (G_DRIVE (drive), flags, mount_operation, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+ else
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_error (G_OBJECT (volume),
+ callback,
+ user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Operation not supported by backend"));
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+}
+
+static gboolean
+gvfs_udisks2_volume_eject_with_operation_finish (GVolume *_volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (_volume);
+ gboolean ret = TRUE;
+
+ if (volume->drive != NULL)
+ {
+ ret = g_drive_eject_with_operation_finish (G_DRIVE (volume->drive), result, error);
+ }
+ else
+ {
+ g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static void
+gvfs_udisks2_volume_eject (GVolume *volume,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ gvfs_udisks2_volume_eject_with_operation (volume, flags, NULL, cancellable, callback, user_data);
+}
+
+static gboolean
+gvfs_udisks2_volume_eject_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ return gvfs_udisks2_volume_eject_with_operation_finish (volume, result, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
gvfs_udisks2_volume_volume_iface_init (GVolumeIface *iface)
{
@@ -653,12 +750,10 @@ gvfs_udisks2_volume_volume_iface_init (GVolumeIface *iface)
iface->mount_fn = gvfs_udisks2_volume_mount;
iface->mount_finish = gvfs_udisks2_volume_mount_finish;
-#if 0
iface->eject = gvfs_udisks2_volume_eject;
iface->eject_finish = gvfs_udisks2_volume_eject_finish;
iface->eject_with_operation = gvfs_udisks2_volume_eject_with_operation;
iface->eject_with_operation_finish = gvfs_udisks2_volume_eject_with_operation_finish;
-#endif
}
/* ---------------------------------------------------------------------------------------------------- */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]