[gvfs/wip/udisks2] udisks2: generate volume objects from /etc/fstab entries
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/wip/udisks2] udisks2: generate volume objects from /etc/fstab entries
- Date: Thu, 29 Sep 2011 23:20:59 +0000 (UTC)
commit 8a06bc172b66857c41ec08eb91815a9b8e380bf8
Author: David Zeuthen <davidz redhat com>
Date: Thu Sep 29 19:20:33 2011 -0400
udisks2: generate volume objects from /etc/fstab entries
Signed-off-by: David Zeuthen <davidz redhat com>
monitor/udisks2/gvfsudisks2mount.c | 57 ++++--
monitor/udisks2/gvfsudisks2mount.h | 5 +-
monitor/udisks2/gvfsudisks2utils.c | 17 ++
monitor/udisks2/gvfsudisks2utils.h | 3 +-
monitor/udisks2/gvfsudisks2volume.c | 263 +++++++++++++++++++--------
monitor/udisks2/gvfsudisks2volume.h | 6 +-
monitor/udisks2/gvfsudisks2volumemonitor.c | 256 ++++++++++++++++++++++++++--
7 files changed, 496 insertions(+), 111 deletions(-)
---
diff --git a/monitor/udisks2/gvfsudisks2mount.c b/monitor/udisks2/gvfsudisks2mount.c
index 0c8ab54..03cba80 100644
--- a/monitor/udisks2/gvfsudisks2mount.c
+++ b/monitor/udisks2/gvfsudisks2mount.c
@@ -61,6 +61,9 @@ struct _GVfsUDisks2Mount
/* may be NULL */
GVfsUDisks2Volume *volume; /* owned by volume monitor */
+ /* may be NULL */
+ GUnixMountEntry *mount_entry;
+
/* the following members are set in update_mount() */
GFile *root;
GIcon *icon;
@@ -117,7 +120,6 @@ gvfs_udisks2_mount_finalize (GObject *object)
g_free (mount->mount_path);
g_free (mount->mount_entry_name);
- g_free (mount->mount_entry_fs_type);
if (mount->autorun_icon != NULL)
g_object_unref (mount->autorun_icon);
@@ -249,18 +251,7 @@ update_mount (GVfsUDisks2Mount *mount)
mount->icon = g_object_ref (mount->autorun_icon);
else
{
- 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);
+ mount->icon = gvfs_udisks2_utils_icon_from_fs_type (g_unix_mount_get_fs_type (mount->mount_entry));
}
g_free (mount->name);
@@ -330,7 +321,7 @@ on_volume_changed (GVolume *volume,
GVfsUDisks2Mount *
gvfs_udisks2_mount_new (GVfsUDisks2VolumeMonitor *monitor,
- GUnixMountEntry *mount_entry,
+ GUnixMountEntry *mount_entry, /* takes ownership */
GVfsUDisks2Volume *volume)
{
GVfsUDisks2Mount *mount = NULL;
@@ -344,9 +335,8 @@ gvfs_udisks2_mount_new (GVfsUDisks2VolumeMonitor *monitor,
if (mount_entry != NULL)
{
- /* No ref on GUnixMountEntry so save values for later use */
+ mount->mount_entry = mount_entry; /* takes ownership */
mount->mount_entry_name = g_unix_mount_guess_name (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);
@@ -400,6 +390,25 @@ gvfs_udisks2_mount_unset_volume (GVfsUDisks2Mount *mount,
}
}
+void
+gvfs_udisks2_mount_set_volume (GVfsUDisks2Mount *mount,
+ GVfsUDisks2Volume *volume)
+{
+ if (mount->volume != volume)
+ {
+ if (mount->volume != NULL)
+ gvfs_udisks2_mount_unset_volume (mount, mount->volume);
+ mount->volume = volume;
+ if (mount->volume != NULL)
+ {
+ gvfs_udisks2_volume_set_mount (volume, mount);
+ /* this is for piggy backing on the name and icon of the associated volume */
+ g_signal_connect (mount->volume, "changed", G_CALLBACK (on_volume_changed), mount);
+ }
+ emit_changed (mount);
+ }
+}
+
static GFile *
gvfs_udisks2_mount_get_root (GMount *_mount)
{
@@ -437,12 +446,18 @@ gvfs_udisks2_mount_has_uuid (GVfsUDisks2Mount *_mount,
}
const gchar *
-gvfs_udisks2_mount_get_mount_path (GVfsUDisks2Mount *_mount)
+gvfs_udisks2_mount_get_mount_path (GVfsUDisks2Mount *mount)
{
- GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (_mount);
return mount->mount_path;
}
+GUnixMountEntry *
+gvfs_udisks2_mount_get_mount_entry (GVfsUDisks2Mount *_mount)
+{
+ GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (_mount);
+ return mount->mount_entry;
+}
+
static GDrive *
gvfs_udisks2_mount_get_drive (GMount *_mount)
{
@@ -828,6 +843,12 @@ unmount_do (UnmountData *data,
}
block = gvfs_udisks2_volume_get_block (data->mount->volume);
+ if (block == NULL)
+ {
+ unmount_do_command (data, force);
+ goto out;
+ }
+
filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (block))));
if (filesystem == NULL)
{
diff --git a/monitor/udisks2/gvfsudisks2mount.h b/monitor/udisks2/gvfsudisks2mount.h
index dd16564..13c9656 100644
--- a/monitor/udisks2/gvfsudisks2mount.h
+++ b/monitor/udisks2/gvfsudisks2mount.h
@@ -45,12 +45,15 @@ void gvfs_udisks2_mount_unmounted (GVfsUDisks2Mount *m
gboolean gvfs_udisks2_mount_has_uuid (GVfsUDisks2Mount *mount,
const gchar *uuid);
+void gvfs_udisks2_mount_set_volume (GVfsUDisks2Mount *mount,
+ GVfsUDisks2Volume *volume);
void gvfs_udisks2_mount_unset_volume (GVfsUDisks2Mount *mount,
GVfsUDisks2Volume *volume);
gboolean gvfs_udisks2_mount_has_volume (GVfsUDisks2Mount *mount,
GVfsUDisks2Volume *volume);
-const gchar *gvfs_udisks2_mount_get_mount_path (GVfsUDisks2Mount *mount);
+const gchar *gvfs_udisks2_mount_get_mount_path (GVfsUDisks2Mount *mount);
+GUnixMountEntry *gvfs_udisks2_mount_get_mount_entry (GVfsUDisks2Mount *mount);
G_END_DECLS
diff --git a/monitor/udisks2/gvfsudisks2utils.c b/monitor/udisks2/gvfsudisks2utils.c
index 4cd8ca4..ebbbc13 100644
--- a/monitor/udisks2/gvfsudisks2utils.c
+++ b/monitor/udisks2/gvfsudisks2utils.c
@@ -64,3 +64,20 @@ gvfs_udisks2_utils_udisks_error_to_gio_error (GError *error)
g_dbus_error_strip_remote_error (error);
}
+
+GIcon *
+gvfs_udisks2_utils_icon_from_fs_type (const gchar *fs_type)
+{
+ const gchar *icon_name;
+ if (g_strcmp0 (fs_type, "nfs") == 0 ||
+ g_strcmp0 (fs_type, "nfs4") == 0 ||
+ g_strcmp0 (fs_type, "cifs") == 0)
+ {
+ icon_name = "folder-remote";
+ }
+ else
+ {
+ icon_name = "drive-removable-media";
+ }
+ return g_themed_icon_new_with_default_fallbacks (icon_name);
+}
diff --git a/monitor/udisks2/gvfsudisks2utils.h b/monitor/udisks2/gvfsudisks2utils.h
index 37b3cf1..8ba4ebb 100644
--- a/monitor/udisks2/gvfsudisks2utils.h
+++ b/monitor/udisks2/gvfsudisks2utils.h
@@ -31,7 +31,8 @@
G_BEGIN_DECLS
-void gvfs_udisks2_utils_udisks_error_to_gio_error (GError *error);
+void gvfs_udisks2_utils_udisks_error_to_gio_error (GError *error);
+GIcon *gvfs_udisks2_utils_icon_from_fs_type (const gchar *fs_type);
G_END_DECLS
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index 05cd460..23394f0 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -56,7 +56,9 @@ struct _GVfsUDisks2Volume
GVfsUDisks2Mount *mount; /* owned by volume monitor */
GVfsUDisks2Drive *drive; /* owned by volume monitor */
+ /* exactly one of these are set */
UDisksBlock *block;
+ GUnixMountPoint *mount_point;
/* set in update_volume() */
GIcon *icon;
@@ -99,8 +101,14 @@ gvfs_udisks2_volume_finalize (GObject *object)
gvfs_udisks2_drive_unset_volume (volume->drive, volume);
}
- g_signal_handlers_disconnect_by_func (volume->block, G_CALLBACK (on_block_changed), volume);
- g_object_unref (volume->block);
+ if (volume->block != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (volume->block, G_CALLBACK (on_block_changed), volume);
+ g_object_unref (volume->block);
+ }
+
+ if (volume->mount_point != NULL)
+ g_unix_mount_point_free (volume->mount_point);
if (volume->icon != NULL)
g_object_unref (volume->icon);
@@ -170,67 +178,75 @@ update_volume (GVfsUDisks2Volume *volume)
/* ---------------------------------------------------------------------------------------------------- */
/* in with the new */
- volume->dev = makedev (udisks_block_get_major (volume->block), udisks_block_get_minor (volume->block));
- volume->device_file = udisks_block_dup_device (volume->block);
-
- if (strlen (udisks_block_get_id_label (volume->block)) > 0)
+ if (volume->block != NULL)
{
- volume->name = g_strdup (udisks_block_get_id_label (volume->block));
- }
- else
- {
- s = g_format_size (udisks_block_get_size (volume->block));
- /* Translators: This is used for volume with no filesystem label.
- * The first %s is the formatted size (e.g. "42.0 MB").
- */
- volume->name = g_strdup_printf (_("%s Volume"), s);
- g_free (s);
- }
+ volume->dev = makedev (udisks_block_get_major (volume->block), udisks_block_get_minor (volume->block));
+ volume->device_file = udisks_block_dup_device (volume->block);
- udisks_drive = udisks_client_get_drive_for_block (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
- volume->block);
- if (udisks_drive != NULL)
- {
- gchar *drive_desc;
- GIcon *drive_icon;
- gchar *media_desc;
- GIcon *media_icon;
- udisks_util_get_drive_info (udisks_drive,
- NULL, /* drive_name */
- &drive_desc,
- &drive_icon,
- &media_desc,
- &media_icon);
- if (media_desc == NULL)
+ if (strlen (udisks_block_get_id_label (volume->block)) > 0)
{
- media_desc = drive_desc;
- drive_desc = NULL;
+ volume->name = g_strdup (udisks_block_get_id_label (volume->block));
}
- if (media_icon == NULL)
+ else
{
- media_icon = drive_icon;
- drive_icon = NULL;
+ s = g_format_size (udisks_block_get_size (volume->block));
+ /* Translators: This is used for volume with no filesystem label.
+ * The first %s is the formatted size (e.g. "42.0 MB").
+ */
+ volume->name = g_strdup_printf (_("%s Volume"), s);
+ g_free (s);
}
- /* Override name for blank and audio discs */
- if (udisks_drive_get_optical_blank (udisks_drive))
- {
- g_free (volume->name);
- volume->name = g_strdup (media_desc);
- }
- else if (volume->activation_root != NULL && g_file_has_uri_scheme (volume->activation_root, "cdda"))
+ udisks_drive = udisks_client_get_drive_for_block (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
+ volume->block);
+ if (udisks_drive != NULL)
{
- g_free (volume->name);
- volume->name = g_strdup (_("Audio Disc"));
+ gchar *drive_desc;
+ GIcon *drive_icon;
+ gchar *media_desc;
+ GIcon *media_icon;
+ udisks_util_get_drive_info (udisks_drive,
+ NULL, /* drive_name */
+ &drive_desc,
+ &drive_icon,
+ &media_desc,
+ &media_icon);
+ if (media_desc == NULL)
+ {
+ media_desc = drive_desc;
+ drive_desc = NULL;
+ }
+ if (media_icon == NULL)
+ {
+ media_icon = drive_icon;
+ drive_icon = NULL;
+ }
+
+ /* Override name for blank and audio discs */
+ if (udisks_drive_get_optical_blank (udisks_drive))
+ {
+ g_free (volume->name);
+ volume->name = g_strdup (media_desc);
+ }
+ else if (volume->activation_root != NULL && g_file_has_uri_scheme (volume->activation_root, "cdda"))
+ {
+ g_free (volume->name);
+ volume->name = g_strdup (_("Audio Disc"));
+ }
+
+ volume->icon = media_icon != NULL ? g_object_ref (media_icon) : NULL;
+
+ g_free (media_desc);
+ if (media_icon != NULL)
+ g_object_unref (media_icon);
+
+ g_object_unref (udisks_drive);
}
-
- volume->icon = media_icon != NULL ? g_object_ref (media_icon) : NULL;
-
- g_free (media_desc);
- if (media_icon != NULL)
- g_object_unref (media_icon);
-
- g_object_unref (udisks_drive);
+ }
+ else
+ {
+ volume->name = g_unix_mount_point_guess_name (volume->mount_point);
+ volume->icon = gvfs_udisks2_utils_icon_from_fs_type (g_unix_mount_point_get_fs_type (volume->mount_point));
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -276,9 +292,11 @@ on_block_changed (GObject *object,
emit_changed (volume);
}
+/* takes ownership of @mount_point if not NULL */
GVfsUDisks2Volume *
gvfs_udisks2_volume_new (GVfsUDisks2VolumeMonitor *monitor,
UDisksBlock *block,
+ GUnixMountPoint *mount_point,
GVfsUDisks2Drive *drive,
GFile *activation_root)
{
@@ -287,8 +305,19 @@ gvfs_udisks2_volume_new (GVfsUDisks2VolumeMonitor *monitor,
volume = g_object_new (GVFS_TYPE_UDISKS2_VOLUME, NULL);
volume->monitor = monitor;
- volume->block = g_object_ref (block);
- g_signal_connect (volume->block, "notify", G_CALLBACK (on_block_changed), volume);
+ if (block != NULL)
+ {
+ volume->block = g_object_ref (block);
+ g_signal_connect (volume->block, "notify", G_CALLBACK (on_block_changed), volume);
+ }
+ else if (mount_point != NULL)
+ {
+ volume->mount_point = mount_point;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
volume->activation_root = activation_root != NULL ? g_object_ref (activation_root) : NULL;
@@ -449,15 +478,18 @@ gvfs_udisks2_volume_get_identifier (GVolume *_volume,
const gchar *uuid;
gchar *ret = NULL;
- label = udisks_block_get_id_label (volume->block);
- uuid = udisks_block_get_id_uuid (volume->block);
-
- if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
- ret = g_strdup (volume->device_file);
- else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
- ret = strlen (label) > 0 ? g_strdup (label) : NULL;
- else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
- ret = strlen (uuid) > 0 ? g_strdup (uuid) : NULL;
+ if (volume->block != NULL)
+ {
+ label = udisks_block_get_id_label (volume->block);
+ uuid = udisks_block_get_id_uuid (volume->block);
+
+ if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
+ ret = g_strdup (volume->device_file);
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
+ ret = strlen (label) > 0 ? g_strdup (label) : NULL;
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
+ ret = strlen (uuid) > 0 ? g_strdup (uuid) : NULL;
+ }
return ret;
}
@@ -466,20 +498,22 @@ static gchar **
gvfs_udisks2_volume_enumerate_identifiers (GVolume *_volume)
{
GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (_volume);
- const gchar *label;
- const gchar *uuid;
GPtrArray *p;
- label = udisks_block_get_id_label (volume->block);
- uuid = udisks_block_get_id_uuid (volume->block);
-
p = g_ptr_array_new ();
g_ptr_array_add (p, g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE));
- if (strlen (label) > 0)
- g_ptr_array_add (p, g_strdup (G_VOLUME_IDENTIFIER_KIND_LABEL));
- if (strlen (uuid) > 0)
- g_ptr_array_add (p, g_strdup (G_VOLUME_IDENTIFIER_KIND_UUID));
+ if (volume->block != NULL)
+ {
+ const gchar *label;
+ const gchar *uuid;
+ label = udisks_block_get_id_label (volume->block);
+ uuid = udisks_block_get_id_uuid (volume->block);
+ if (strlen (label) > 0)
+ g_ptr_array_add (p, g_strdup (G_VOLUME_IDENTIFIER_KIND_LABEL));
+ if (strlen (uuid) > 0)
+ g_ptr_array_add (p, g_strdup (G_VOLUME_IDENTIFIER_KIND_UUID));
+ }
g_ptr_array_add (p, NULL);
return (gchar **) g_ptr_array_free (p, FALSE);
}
@@ -522,8 +556,69 @@ mount_cancel_pending_op (MountData *data)
if (data->mount_operation != NULL)
g_signal_emit_by_name (data->mount_operation, "aborted");
g_cancellable_cancel (data->cancellable);
+ data->volume->mount_pending_op = NULL;
+}
+
+/* ------------------------------ */
+
+static void
+do_mount_command (MountData *data)
+{
+ GError *error;
+ gint exit_status;
+ gchar *standard_error = NULL;
+ const gchar *mount_argv[3] = {"mount", NULL, NULL};
+
+ mount_argv[1] = g_unix_mount_point_get_mount_path (data->volume->mount_point);
+
+ /* TODO: we could do this async but it's probably not worth the effort */
+ error = NULL;
+ if (!g_spawn_sync (NULL, /* working dir */
+ (gchar **) mount_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 mount: ");
+ g_simple_async_result_take_error (data->simple, error);
+ g_simple_async_result_complete (data->simple);
+ mount_data_free (data);
+ goto out;
+ }
+
+ /* TODO: for e.g. NFS and CIFS mounts we could do GMountOperation stuff and pipe a
+ * password to mount(8)'s stdin channel
+ */
+
+ /* we are no longer pending */
+ data->volume->mount_pending_op = NULL;
+
+ if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0)
+ {
+ gvfs_udisks2_volume_monitor_update (data->volume->monitor);
+ g_simple_async_result_complete (data->simple);
+ mount_data_free (data);
+ 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);
+ mount_data_free (data);
+
+ out:
+ g_free (standard_error);
}
+/* ------------------------------ */
+
static void
mount_cb (GObject *source_object,
GAsyncResult *res,
@@ -574,6 +669,8 @@ gvfs_udisks2_volume_mount (GVolume *_volume,
user_data,
gvfs_udisks2_volume_mount);
data->volume = g_object_ref (volume);
+ data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
+ data->mount_operation = mount_operation != NULL ? g_object_ref (mount_operation) : NULL;
if (volume->mount_pending_op != NULL)
{
@@ -585,6 +682,13 @@ gvfs_udisks2_volume_mount (GVolume *_volume,
mount_data_free (data);
goto out;
}
+ volume->mount_pending_op = data;
+
+ if (volume->block == NULL)
+ {
+ do_mount_command (data);
+ goto out;
+ }
filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (volume->block))));
if (filesystem == NULL)
@@ -598,10 +702,6 @@ gvfs_udisks2_volume_mount (GVolume *_volume,
goto out;
}
- data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
- data->mount_operation = mount_operation != NULL ? g_object_ref (mount_operation) : NULL;
- volume->mount_pending_op = data;
-
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
if (data->mount_operation == NULL)
{
@@ -759,6 +859,13 @@ gvfs_udisks2_volume_get_block (GVfsUDisks2Volume *volume)
return volume->block;
}
+GUnixMountPoint *
+gvfs_udisks2_volume_get_mount_point (GVfsUDisks2Volume *volume)
+{
+ g_return_val_if_fail (GVFS_IS_UDISKS2_VOLUME (volume), NULL);
+ return volume->mount_point;
+}
+
dev_t
gvfs_udisks2_volume_get_dev (GVfsUDisks2Volume *volume)
{
diff --git a/monitor/udisks2/gvfsudisks2volume.h b/monitor/udisks2/gvfsudisks2volume.h
index cda2b9c..de21cbb 100644
--- a/monitor/udisks2/gvfsudisks2volume.h
+++ b/monitor/udisks2/gvfsudisks2volume.h
@@ -39,12 +39,14 @@ GType gvfs_udisks2_volume_get_type (void) G_GNUC_CONST;
GVfsUDisks2Volume *gvfs_udisks2_volume_new (GVfsUDisks2VolumeMonitor *monitor,
UDisksBlock *block,
+ GUnixMountPoint *mount_point,
GVfsUDisks2Drive *drive,
GFile *activation_root);
void gvfs_udisks2_volume_removed (GVfsUDisks2Volume *volume);
-UDisksBlock *gvfs_udisks2_volume_get_block (GVfsUDisks2Volume *volume);
-dev_t gvfs_udisks2_volume_get_dev (GVfsUDisks2Volume *volume);
+UDisksBlock *gvfs_udisks2_volume_get_block (GVfsUDisks2Volume *volume);
+GUnixMountPoint *gvfs_udisks2_volume_get_mount_point (GVfsUDisks2Volume *volume);
+dev_t gvfs_udisks2_volume_get_dev (GVfsUDisks2Volume *volume);
void gvfs_udisks2_volume_set_mount (GVfsUDisks2Volume *volume,
GVfsUDisks2Mount *mount);
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index 3b46478..5f6a7d6 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -57,10 +57,9 @@ struct _GVfsUDisks2VolumeMonitor
GUdevClient *gudev_client;
GUnixMountMonitor *mount_monitor;
- GList *last_mounts;
-
GList *drives;
GList *volumes;
+ GList *fstab_volumes;
GList *mounts;
/* we keep volumes/mounts for blank and audio discs separate to handle e.g. mixed discs properly */
GList *disc_volumes;
@@ -78,6 +77,9 @@ static void update_drives (GVfsUDisks2VolumeMonitor *monitor,
static void update_volumes (GVfsUDisks2VolumeMonitor *monitor,
GList **added_volumes,
GList **removed_volumes);
+static void update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes);
static void update_mounts (GVfsUDisks2VolumeMonitor *monitor,
GList **added_mounts,
GList **removed_mounts);
@@ -160,11 +162,9 @@ gvfs_udisks2_volume_monitor_finalize (GObject *object)
g_clear_object (&monitor->client);
g_clear_object (&monitor->gudev_client);
- g_list_foreach (monitor->last_mounts, (GFunc) g_unix_mount_free, NULL);
- g_list_free (monitor->last_mounts);
-
object_list_free (monitor->drives);
object_list_free (monitor->volumes);
+ object_list_free (monitor->fstab_volumes);
object_list_free (monitor->mounts);
object_list_free (monitor->disc_volumes);
@@ -192,6 +192,7 @@ get_volumes (GVolumeMonitor *_monitor)
GList *ret;
ret = g_list_copy (monitor->volumes);
+ ret = g_list_concat (ret, g_list_copy (monitor->fstab_volumes));
ret = g_list_concat (ret, g_list_copy (monitor->disc_volumes));
g_list_foreach (ret, (GFunc) g_object_ref, NULL);
return ret;
@@ -222,6 +223,12 @@ get_volume_for_uuid (GVolumeMonitor *_monitor,
if (gvfs_udisks2_volume_has_uuid (l->data, uuid))
goto found;
}
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ volume = l->data;
+ if (gvfs_udisks2_volume_has_uuid (l->data, uuid))
+ goto found;
+ }
for (l = monitor->disc_volumes; l != NULL; l = l->next)
{
volume = l->data;
@@ -623,6 +630,7 @@ update_all (GVfsUDisks2VolumeMonitor *monitor,
update_drives (monitor, &added_drives, &removed_drives);
update_volumes (monitor, &added_volumes, &removed_volumes);
+ update_fstab_volumes (monitor, &added_volumes, &removed_volumes);
update_mounts (monitor, &added_mounts, &removed_mounts);
update_discs (monitor,
&added_volumes, &removed_volumes,
@@ -878,6 +886,109 @@ find_volume_for_block (GVfsUDisks2VolumeMonitor *monitor,
/* ---------------------------------------------------------------------------------------------------- */
static GVfsUDisks2Volume *
+find_fstab_volume_for_mount_point (GVfsUDisks2VolumeMonitor *monitor,
+ GUnixMountPoint *mount_point)
+{
+ GVfsUDisks2Volume *ret = NULL;
+ GList *l;
+
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (l->data);
+ if (g_unix_mount_point_compare (gvfs_udisks2_volume_get_mount_point (volume), mount_point) == 0)
+ {
+ ret = volume;
+ goto out;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+mount_point_matches_mount_entry (GUnixMountPoint *mount_point,
+ GUnixMountEntry *mount_entry)
+{
+ gboolean ret = FALSE;
+ gchar *mp_path = NULL;
+ gchar *mp_entry = NULL;
+
+ mp_path = g_strdup (g_unix_mount_point_get_mount_path (mount_point));
+ mp_entry = g_strdup (g_unix_mount_get_mount_path (mount_entry));
+
+ if (g_str_has_suffix (mp_path, "/"))
+ mp_path[strlen(mp_path) - 1] = '\0';
+ if (g_str_has_suffix (mp_entry, "/"))
+ mp_entry[strlen(mp_entry) - 1] = '\0';
+
+ if (g_strcmp0 (mp_path, mp_entry) != 0)
+ goto out;
+
+ ret = TRUE;
+
+ out:
+ g_free (mp_path);
+ g_free (mp_entry);
+ return ret;
+}
+
+static GVfsUDisks2Volume *
+find_fstab_volume_for_mount_entry (GVfsUDisks2VolumeMonitor *monitor,
+ GUnixMountEntry *mount_entry)
+{
+ GVfsUDisks2Volume *ret = NULL;
+ GList *l;
+
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (l->data);
+ if (mount_point_matches_mount_entry (gvfs_udisks2_volume_get_mount_point (volume), mount_entry))
+ {
+ ret = volume;
+ goto out;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+static GVfsUDisks2Mount *
+find_lonely_mount_for_mount_point (GVfsUDisks2VolumeMonitor *monitor,
+ GUnixMountPoint *mount_point)
+{
+ GVfsUDisks2Mount *ret = NULL;
+ GList *l;
+
+ for (l = monitor->mounts; l != NULL; l = l->next)
+ {
+ GVfsUDisks2Mount *mount = GVFS_UDISKS2_MOUNT (l->data);
+ if (mount_point != NULL &&
+ mount_point_matches_mount_entry (mount_point, gvfs_udisks2_mount_get_mount_entry (mount)))
+ {
+ GVolume *volume = g_mount_get_volume (G_MOUNT (mount));
+ if (volume != NULL)
+ {
+ g_object_unref (volume);
+ }
+ else
+ {
+ ret = mount;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GVfsUDisks2Volume *
find_volume_for_device (GVfsUDisks2VolumeMonitor *monitor,
const gchar *device)
{
@@ -1087,6 +1198,7 @@ update_volumes (GVfsUDisks2VolumeMonitor *monitor,
}
volume = gvfs_udisks2_volume_new (monitor,
block,
+ NULL, /* mount_point */
drive,
NULL); /* activation_root */
if (volume != NULL)
@@ -1109,18 +1221,132 @@ update_volumes (GVfsUDisks2VolumeMonitor *monitor,
/* ---------------------------------------------------------------------------------------------------- */
static void
+update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes)
+{
+ GList *cur_mount_points;
+ GList *new_mount_points;
+ GList *added;
+ GList *removed;
+ GList *l, *ll;
+ GVfsUDisks2Volume *volume;
+
+ cur_mount_points = NULL;
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ GUnixMountPoint *mount_point = gvfs_udisks2_volume_get_mount_point (GVFS_UDISKS2_VOLUME (l->data));
+ if (mount_point != NULL)
+ cur_mount_points = g_list_prepend (cur_mount_points, mount_point);
+ }
+
+ new_mount_points = g_unix_mount_points_get (NULL);
+ /* filter the mount points that we don't want to include */
+ for (l = new_mount_points; l != NULL; l = ll)
+ {
+ GUnixMountPoint *mount_point = l->data;
+ gboolean keep = TRUE;
+
+ ll = l->next;
+
+ if (g_unix_is_mount_path_system_internal (g_unix_mount_point_get_mount_path (mount_point)))
+ {
+ keep = FALSE;
+ }
+ else
+ {
+ /* TODO: more checks - including not including the
+ * /etc/fstab entry if we've already got a udisks object for
+ * it
+ */
+ }
+
+ if (!keep)
+ new_mount_points = g_list_remove_link (new_mount_points, l);
+ }
+
+ cur_mount_points = g_list_sort (cur_mount_points, (GCompareFunc) g_unix_mount_point_compare);
+ new_mount_points = g_list_sort (new_mount_points, (GCompareFunc) g_unix_mount_point_compare);
+ diff_sorted_lists (cur_mount_points,
+ new_mount_points, (GCompareFunc) g_unix_mount_point_compare,
+ &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ GUnixMountPoint *mount_point = l->data;
+ volume = find_fstab_volume_for_mount_point (monitor, mount_point);
+ if (volume != NULL)
+ {
+ gvfs_udisks2_volume_removed (volume);
+ monitor->fstab_volumes = g_list_remove (monitor->fstab_volumes, volume);
+ *removed_volumes = g_list_prepend (*removed_volumes, g_object_ref (volume));
+ g_object_unref (volume);
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ GUnixMountPoint *mount_point = l->data;
+
+ volume = find_fstab_volume_for_mount_point (monitor, mount_point);
+ if (volume == NULL)
+ {
+ volume = gvfs_udisks2_volume_new (monitor,
+ NULL, /* block */
+ mount_point,
+ NULL, /* drive */
+ NULL); /* activation_root */
+ if (volume != NULL)
+ {
+ GVfsUDisks2Mount *mount;
+
+ monitor->fstab_volumes = g_list_prepend (monitor->fstab_volumes, volume);
+ *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
+ /* since @volume takes ownership of @mount_point, don't free it below */
+ new_mount_points = g_list_remove (new_mount_points, mount_point);
+
+ /* Could be there's already a mount for this volume - for example, the
+ * user could just have added it to the /etc/fstab file
+ */
+ mount = find_lonely_mount_for_mount_point (monitor, mount_point);
+ if (mount != NULL)
+ gvfs_udisks2_mount_set_volume (mount, volume);
+ }
+ }
+ }
+
+ g_list_foreach (new_mount_points, (GFunc) g_unix_mount_point_free, NULL);
+ g_list_free (new_mount_points);
+
+ g_list_free (cur_mount_points);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
update_mounts (GVfsUDisks2VolumeMonitor *monitor,
GList **added_mounts,
GList **removed_mounts)
{
+ GList *cur_mounts;
GList *new_mounts;
GList *removed, *added;
GList *l, *ll;
GVfsUDisks2Mount *mount;
GVfsUDisks2Volume *volume;
- new_mounts = g_unix_mounts_get (NULL);
+ cur_mounts = NULL;
+ for (l = monitor->mounts; l != NULL; l = l->next)
+ {
+ GUnixMountEntry *mount_entry;
+ mount = GVFS_UDISKS2_MOUNT (l->data);
+ mount_entry = gvfs_udisks2_mount_get_mount_entry (mount);
+ if (mount_entry != NULL)
+ cur_mounts = g_list_prepend (cur_mounts, mount_entry);
+ }
+
+ new_mounts = g_unix_mounts_get (NULL);
/* remove mounts we want to ignore - we do it here so we get to reevaluate
* on the next update whether they should still be ignored
*/
@@ -1134,9 +1360,10 @@ update_mounts (GVfsUDisks2VolumeMonitor *monitor,
new_mounts = g_list_delete_link (new_mounts, l);
}
}
- new_mounts = g_list_sort (new_mounts, (GCompareFunc) g_unix_mount_compare);
- diff_sorted_lists (monitor->last_mounts,
+ cur_mounts = g_list_sort (cur_mounts, (GCompareFunc) g_unix_mount_compare);
+ new_mounts = g_list_sort (new_mounts, (GCompareFunc) g_unix_mount_compare);
+ diff_sorted_lists (cur_mounts,
new_mounts, (GCompareFunc) g_unix_mount_compare,
&added, &removed);
@@ -1161,20 +1388,26 @@ update_mounts (GVfsUDisks2VolumeMonitor *monitor,
device_file = g_unix_mount_get_device_path (mount_entry);
volume = find_volume_for_device (monitor, device_file);
+ if (volume == NULL)
+ volume = find_fstab_volume_for_mount_entry (monitor, mount_entry);
mount = gvfs_udisks2_mount_new (monitor, mount_entry, volume); /* adopts mount_entry */
if (mount != NULL)
{
monitor->mounts = g_list_prepend (monitor->mounts, mount);
*added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount));
/*g_debug ("added mount at %s for %p", gvfs_udisks2_mount_get_mount_path (mount), volume);*/
+ /* since @mount takes ownership of @mount_entry, don't free it below */
+ new_mounts = g_list_remove (new_mounts, mount_entry);
}
}
g_list_free (added);
g_list_free (removed);
- g_list_foreach (monitor->last_mounts, (GFunc) g_unix_mount_free, NULL);
- g_list_free (monitor->last_mounts);
- monitor->last_mounts = new_mounts;
+
+ g_list_foreach (new_mounts, (GFunc) g_unix_mount_free, NULL);
+ g_list_free (new_mounts);
+
+ g_list_free (cur_mounts);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -1282,6 +1515,7 @@ update_discs (GVfsUDisks2VolumeMonitor *monitor,
activation_root = g_file_new_for_uri (uri);
volume = gvfs_udisks2_volume_new (monitor,
block,
+ NULL, /* mount_point */
find_drive_for_udisks_drive (monitor, udisks_drive),
activation_root);
if (volume != NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]