gvfs/gdu-0010-show-user-mountabl...

877 lines
30 KiB
Diff

From 0f7a44dd0eac01f9783879af4ca3d3fe4a53af14 Mon Sep 17 00:00:00 2001
From: David Zeuthen <davidz@redhat.com>
Date: Mon, 13 Apr 2009 10:57:38 -0400
Subject: [PATCH 10/13] show user-mountable fstab entries
Show all entries from /etc/fstab for which
- the entry is user mountable
- the mount point is in /media or $HOME
- if it's a /dev file make sure it exists and is not handled
by DeviceKit-disks already
For example this /etc/fstab entry
"quad.local:/media/FusionMedia /media/FusionMedia nfs defaults,users 0 0"
makes Nautilus display this when unmounted
http://people.freedesktop.org/~david/gvfs-user-mountable-fstab-entries.png
and these GVolume and GMount objects to appear when mounted
Volume(0): FusionMedia
Type: GProxyVolume (GProxyVolumeMonitorGdu)
themed icons: [folder-remote] [folder]
can_mount=1
can_eject=0
Mount(0): FusionMedia -> file:///media/FusionMedia
Type: GProxyMount (GProxyVolumeMonitorGdu)
themed icons: [folder-remote] [folder]
can_unmount=1
can_eject=0
is_shadowed=0
This should resolve http://bugzilla.gnome.org/show_bug.cgi?id=536292
---
monitor/gdu/ggdumount.c | 29 +++-
monitor/gdu/ggduvolume.c | 374 ++++++++++++++++++++++++++++++++++++---
monitor/gdu/ggduvolume.h | 7 +-
monitor/gdu/ggduvolumemonitor.c | 174 ++++++++++++++++++-
4 files changed, 548 insertions(+), 36 deletions(-)
diff --git a/monitor/gdu/ggdumount.c b/monitor/gdu/ggdumount.c
index 27c22d9..e074a20 100644
--- a/monitor/gdu/ggdumount.c
+++ b/monitor/gdu/ggdumount.c
@@ -696,8 +696,13 @@ g_gdu_mount_unmount (GMount *_mount,
{
GGduMount *mount = G_GDU_MOUNT (_mount);
GSimpleAsyncResult *simple;
+ GduPresentable *gdu_volume;
- if (mount->volume == NULL)
+ gdu_volume = NULL;
+ if (mount->volume != NULL)
+ gdu_volume = g_gdu_volume_get_presentable_with_cleartext (mount->volume);
+
+ if (mount->volume == NULL || gdu_volume == NULL)
{
gchar *argv[] = {"umount", NULL, NULL};
@@ -710,7 +715,7 @@ g_gdu_mount_unmount (GMount *_mount,
eject_unmount_do (_mount, cancellable, callback, user_data, argv);
}
- else
+ else if (gdu_volume != NULL)
{
simple = g_simple_async_result_new (G_OBJECT (mount),
callback,
@@ -726,18 +731,25 @@ g_gdu_mount_unmount (GMount *_mount,
else
{
GduDevice *device;
- GduPresentable *volume;
/* TODO: honor flags */
- volume = g_gdu_volume_get_presentable_with_cleartext (mount->volume);
- device = gdu_presentable_get_device (volume);
-
+ device = gdu_presentable_get_device (gdu_volume);
gdu_device_op_filesystem_unmount (device, unmount_cb, simple);
-
g_object_unref (device);
}
}
+ else
+ {
+ 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
@@ -855,7 +867,8 @@ g_gdu_mount_guess_content_type_sync (GMount *_mount,
{
GduPresentable *presentable;
presentable = g_gdu_volume_get_presentable_with_cleartext (mount->volume);
- device = gdu_presentable_get_device (presentable);
+ if (presentable != NULL)
+ device = gdu_presentable_get_device (presentable);
}
/* doesn't make sense to probe blank discs - look at the disc type instead */
diff --git a/monitor/gdu/ggduvolume.c b/monitor/gdu/ggduvolume.c
index 6779f0f..49494a1 100644
--- a/monitor/gdu/ggduvolume.c
+++ b/monitor/gdu/ggduvolume.c
@@ -35,12 +35,22 @@
#include "ggduvolume.h"
#include "ggdumount.h"
+/* for BUFSIZ */
+#include <stdio.h>
+
#include "polkit.h"
typedef struct MountOpData MountOpData;
static void cancel_pending_mount_op (MountOpData *data);
+static void g_gdu_volume_mount_unix_mount_point (GGduVolume *volume,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
struct _GGduVolume
{
GObject parent;
@@ -49,8 +59,12 @@ struct _GGduVolume
GGduMount *mount; /* owned by volume monitor */
GGduDrive *drive; /* owned by volume monitor */
+ /* only set if constructed via new() */
GduVolume *gdu_volume;
+ /* only set if constructed via new_for_unix_mount_point() */
+ GUnixMountPoint *unix_mount_point;
+
/* if the volume is encrypted, this is != NULL when unlocked */
GduVolume *cleartext_gdu_volume;
@@ -60,7 +74,7 @@ struct _GGduVolume
*/
MountOpData *pending_mount_op;
- /* the following members need to be set upon construction */
+ /* the following members need to be set upon construction, see constructors and update_volume() */
GIcon *icon;
GFile *activation_root;
gchar *name;
@@ -110,6 +124,11 @@ g_gdu_volume_finalize (GObject *object)
g_object_unref (volume->gdu_volume);
}
+ if (volume->unix_mount_point != NULL)
+ {
+ g_unix_mount_point_free (volume->unix_mount_point);
+ }
+
if (volume->cleartext_gdu_volume != NULL)
{
g_signal_handlers_disconnect_by_func (volume->cleartext_gdu_volume, gdu_cleartext_volume_removed, volume);
@@ -174,6 +193,30 @@ update_volume (GGduVolume *volume)
/* ---------------------------------------------------------------------------------------------------- */
+ /* if the volume is a fstab mount point, get the data from there */
+ if (volume->unix_mount_point != NULL)
+ {
+ volume->can_mount = TRUE;
+ volume->should_automount = FALSE;
+
+ g_free (volume->device_file);
+ volume->device_file = g_strdup (g_unix_mount_point_get_device_path (volume->unix_mount_point));
+
+ if (volume->icon != NULL)
+ g_object_unref (volume->icon);
+ if (g_strcmp0 (g_unix_mount_point_get_fs_type (volume->unix_mount_point), "nfs") == 0)
+ volume->icon = g_themed_icon_new_with_default_fallbacks ("folder-remote");
+ else
+ volume->icon = g_unix_mount_point_guess_icon (volume->unix_mount_point);
+
+ g_free (volume->name);
+ volume->name = g_unix_mount_point_guess_name (volume->unix_mount_point);
+
+ //volume->can_eject = g_unix_mount_point_guess_can_eject (volume->unix_mount_point);
+
+ goto update_done;
+ }
+
/* in with the new */
device = gdu_presentable_get_device (GDU_PRESENTABLE (volume->gdu_volume));
pool = gdu_device_get_pool (device);
@@ -347,6 +390,8 @@ update_volume (GGduVolume *volume)
/* ---------------------------------------------------------------------------------------------------- */
+ update_done:
+
/* compute whether something changed */
changed = !((old_can_mount == volume->can_mount) &&
(old_should_automount == volume->should_automount) &&
@@ -412,6 +457,23 @@ gdu_cleartext_volume_job_changed (GduPresentable *presentable,
}
GGduVolume *
+g_gdu_volume_new_for_unix_mount_point (GVolumeMonitor *volume_monitor,
+ GUnixMountPoint *unix_mount_point)
+{
+ GGduVolume *volume;
+
+ volume = g_object_new (G_TYPE_GDU_VOLUME, NULL);
+ volume->volume_monitor = volume_monitor;
+ g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(volume->volume_monitor));
+
+ volume->unix_mount_point = unix_mount_point;
+
+ update_volume (volume);
+
+ return volume;
+}
+
+GGduVolume *
g_gdu_volume_new (GVolumeMonitor *volume_monitor,
GduVolume *gdu_volume,
GGduDrive *drive,
@@ -1084,6 +1146,18 @@ g_gdu_volume_mount (GVolume *_volume,
pool = NULL;
device = NULL;
+ /* for fstab mounts, call the native mount command */
+ if (volume->unix_mount_point != NULL)
+ {
+ g_gdu_volume_mount_unix_mount_point (volume,
+ flags,
+ mount_operation,
+ cancellable,
+ callback,
+ user_data);
+ goto out;
+ }
+
if (volume->pending_mount_op != NULL)
{
simple = g_simple_async_result_new_error (G_OBJECT (volume),
@@ -1204,7 +1278,7 @@ g_gdu_volume_mount_finish (GVolume *volume,
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_gdu_volume_mount);
+ //g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_gdu_volume_mount);
return !g_simple_async_result_propagate_error (simple, error);
}
@@ -1212,6 +1286,247 @@ g_gdu_volume_mount_finish (GVolume *volume,
/* ---------------------------------------------------------------------------------------------------- */
typedef struct {
+ GGduVolume *volume;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+ int error_fd;
+ GIOChannel *error_channel;
+ guint error_channel_source_id;
+ GString *error_string;
+
+ guint wait_for_mount_timeout_id;
+ gulong wait_for_mount_changed_signal_handler_id;
+} MountPointOp;
+
+static void
+mount_point_op_free (MountPointOp *data)
+{
+ if (data->error_channel_source_id > 0)
+ g_source_remove (data->error_channel_source_id);
+ if (data->error_channel != NULL)
+ g_io_channel_unref (data->error_channel);
+ if (data->error_string != NULL)
+ g_string_free (data->error_string, TRUE);
+ if (data->error_fd > 0)
+ close (data->error_fd);
+ g_free (data);
+}
+
+static void
+mount_point_op_changed_cb (GVolume *volume,
+ gpointer user_data)
+{
+ MountPointOp *data = user_data;
+ GSimpleAsyncResult *simple;
+
+ /* keep waiting if the mount hasn't appeared */
+ if (data->volume->mount == NULL)
+ goto out;
+
+ simple = g_simple_async_result_new (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ NULL);
+ /* complete in idle to make sure the mount is added before we return */
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ g_signal_handler_disconnect (data->volume, data->wait_for_mount_changed_signal_handler_id);
+ g_source_remove (data->wait_for_mount_timeout_id);
+
+ mount_point_op_free (data);
+
+ out:
+ ;
+}
+
+static gboolean
+mount_point_op_never_appeared_cb (gpointer user_data)
+{
+ MountPointOp *data = user_data;
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new_error (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Timeout waiting for mount to appear");
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_signal_handler_disconnect (data->volume, data->wait_for_mount_changed_signal_handler_id);
+ g_source_remove (data->wait_for_mount_timeout_id);
+
+ mount_point_op_free (data);
+
+ return FALSE;
+}
+
+static void
+mount_point_op_cb (GPid pid, gint status, gpointer user_data)
+{
+ MountPointOp *data = user_data;
+ GSimpleAsyncResult *simple;
+
+ g_spawn_close_pid (pid);
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ GError *error;
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ data->error_string->str);
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ mount_point_op_free (data);
+ }
+ else
+ {
+ /* wait for the GMount to appear - this is to honor this requirement
+ *
+ * "If the mount operation succeeded, g_volume_get_mount() on
+ * volume is guaranteed to return the mount right after calling
+ * this function; there's no need to listen for the
+ * 'mount-added' signal on GVolumeMonitor."
+ *
+ * So we set up a signal handler waiting for it to appear. We also set up
+ * a timer for handling the case when it never appears.
+ */
+ if (data->volume->mount == NULL)
+ {
+ /* no need to ref, GSimpleAsyncResult has a ref on data->volume */
+ data->wait_for_mount_timeout_id = g_timeout_add (5 * 1000,
+ mount_point_op_never_appeared_cb,
+ data);
+ data->wait_for_mount_changed_signal_handler_id = g_signal_connect (data->volume,
+ "changed",
+ G_CALLBACK (mount_point_op_changed_cb),
+ data);
+ }
+ else
+ {
+ /* have the mount already, finish up */
+ simple = g_simple_async_result_new (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ mount_point_op_free (data);
+ }
+ }
+}
+
+static gboolean
+mount_point_op_read_error (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ MountPointOp *data = user_data;
+ gchar buf[BUFSIZ];
+ gsize bytes_read;
+ GError *error;
+ GIOStatus status;
+
+ error = NULL;
+read:
+ status = g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read, &error);
+ if (status == G_IO_STATUS_NORMAL)
+ {
+ g_string_append_len (data->error_string, buf, bytes_read);
+ if (bytes_read == sizeof (buf))
+ goto read;
+ }
+ else if (status == G_IO_STATUS_EOF)
+ {
+ g_string_append_len (data->error_string, buf, bytes_read);
+ }
+ else if (status == G_IO_STATUS_ERROR)
+ {
+ if (data->error_string->len > 0)
+ g_string_append (data->error_string, "\n");
+
+ g_string_append (data->error_string, error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+g_gdu_volume_mount_unix_mount_point (GGduVolume *volume,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MountPointOp *data;
+ GPid child_pid;
+ GError *error;
+ const gchar *argv[] = {"mount", NULL, NULL};
+
+ argv[1] = g_unix_mount_point_get_mount_path (volume->unix_mount_point);
+
+ data = g_new0 (MountPointOp, 1);
+ data->volume = volume;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ error = NULL;
+ if (!g_spawn_async_with_pipes (NULL, /* working dir */
+ (gchar **) argv,
+ NULL, /* envp */
+ G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user_data for child_setup */
+ &child_pid,
+ NULL, /* standard_input */
+ NULL, /* standard_output */
+ &(data->error_fd),
+ &error))
+ {
+ g_assert (error != NULL);
+ goto handle_error;
+ }
+
+ data->error_string = g_string_new ("");
+
+ data->error_channel = g_io_channel_unix_new (data->error_fd);
+ g_io_channel_set_flags (data->error_channel, G_IO_FLAG_NONBLOCK, &error);
+ if (error != NULL)
+ goto handle_error;
+
+ data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, mount_point_op_read_error, data);
+ g_child_watch_add (child_pid, mount_point_op_cb, data);
+
+handle_error:
+ if (error != NULL)
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ mount_point_op_free (data);
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct {
GObject *object;
GAsyncReadyCallback callback;
gpointer user_data;
@@ -1300,19 +1615,22 @@ g_gdu_volume_get_identifier (GVolume *_volume,
id = NULL;
- device = gdu_presentable_get_device (GDU_PRESENTABLE (volume->gdu_volume));
+ if (volume->gdu_volume != NULL)
+ {
+ device = gdu_presentable_get_device (GDU_PRESENTABLE (volume->gdu_volume));
- label = gdu_device_id_get_label (device);
- uuid = gdu_device_id_get_uuid (device);
+ label = gdu_device_id_get_label (device);
+ uuid = gdu_device_id_get_uuid (device);
- g_object_unref (device);
+ g_object_unref (device);
- if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
- id = g_strdup (volume->device_file);
- else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
- id = strlen (label) > 0 ? g_strdup (label) : NULL;
- else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
- id = strlen (uuid) > 0 ? g_strdup (uuid) : NULL;
+ if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
+ id = g_strdup (volume->device_file);
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
+ id = strlen (label) > 0 ? g_strdup (label) : NULL;
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
+ id = strlen (uuid) > 0 ? g_strdup (uuid) : NULL;
+ }
return id;
}
@@ -1326,19 +1644,21 @@ g_gdu_volume_enumerate_identifiers (GVolume *_volume)
const gchar *label;
const gchar *uuid;
- device = gdu_presentable_get_device (GDU_PRESENTABLE (volume->gdu_volume));
-
- label = gdu_device_id_get_label (device);
- uuid = gdu_device_id_get_uuid (device);
-
- g_object_unref (device);
-
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->gdu_volume != NULL)
+ {
+ device = gdu_presentable_get_device (GDU_PRESENTABLE (volume->gdu_volume));
+ label = gdu_device_id_get_label (device);
+ uuid = gdu_device_id_get_uuid (device);
+ g_object_unref (device);
+
+ 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));
+ }
g_ptr_array_add (p, NULL);
@@ -1452,3 +1772,9 @@ g_gdu_volume_get_presentable_with_cleartext (GGduVolume *volume)
return GDU_PRESENTABLE (ret);
}
+
+GUnixMountPoint *
+g_gdu_volume_get_unix_mount_point (GGduVolume *volume)
+{
+ return volume->unix_mount_point;
+}
diff --git a/monitor/gdu/ggduvolume.h b/monitor/gdu/ggduvolume.h
index 8fd7358..a230d28 100644
--- a/monitor/gdu/ggduvolume.h
+++ b/monitor/gdu/ggduvolume.h
@@ -50,6 +50,9 @@ GGduVolume *g_gdu_volume_new (GVolumeMonitor *volume_monitor,
GGduDrive *drive,
GFile *activation_root);
+GGduVolume *g_gdu_volume_new_for_unix_mount_point (GVolumeMonitor *volume_monitor,
+ GUnixMountPoint *unix_mount_point);
+
void g_gdu_volume_set_mount (GGduVolume *volume,
GGduMount *mount);
void g_gdu_volume_unset_mount (GGduVolume *volume,
@@ -69,10 +72,12 @@ gboolean g_gdu_volume_has_uuid (GGduVolume *volume,
gboolean g_gdu_volume_has_device_file (GGduVolume *volume,
const gchar *device_file);
-GduPresentable *g_gdu_volume_get_presentable (GGduVolume *volume);
+GduPresentable *g_gdu_volume_get_presentable (GGduVolume *volume);
GduPresentable *g_gdu_volume_get_presentable_with_cleartext (GGduVolume *volume);
+GUnixMountPoint *g_gdu_volume_get_unix_mount_point (GGduVolume *volume);
+
G_END_DECLS
#endif /* __G_GDU_VOLUME_H__ */
diff --git a/monitor/gdu/ggduvolumemonitor.c b/monitor/gdu/ggduvolumemonitor.c
index caa25a0..67e2ec0 100644
--- a/monitor/gdu/ggduvolumemonitor.c
+++ b/monitor/gdu/ggduvolumemonitor.c
@@ -51,6 +51,7 @@ struct _GGduVolumeMonitor {
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 */
@@ -80,6 +81,9 @@ static void update_drives (GGduVolumeMonitor *monitor,
static void update_volumes (GGduVolumeMonitor *monitor,
GList **added_volumes,
GList **removed_volumes);
+static void update_fstab_volumes (GGduVolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes);
static void update_mounts (GGduVolumeMonitor *monitor,
GList **added_mounts,
GList **removed_mounts);
@@ -135,6 +139,7 @@ g_gdu_volume_monitor_finalize (GObject *object)
g_list_free (monitor->last_mounts);
list_free (monitor->drives);
+ list_free (monitor->fstab_volumes);
list_free (monitor->volumes);
list_free (monitor->mounts);
@@ -171,6 +176,8 @@ get_volumes (GVolumeMonitor *volume_monitor)
monitor = G_GDU_VOLUME_MONITOR (volume_monitor);
l = g_list_copy (monitor->volumes);
+ ll = g_list_copy (monitor->fstab_volumes);
+ l = g_list_concat (l, ll);
ll = g_list_copy (monitor->disc_volumes);
l = g_list_concat (l, ll);
@@ -211,6 +218,13 @@ get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
goto found;
}
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ volume = l->data;
+ if (g_gdu_volume_has_uuid (volume, uuid))
+ goto found;
+ }
+
for (l = monitor->disc_volumes; l != NULL; l = l->next)
{
volume = l->data;
@@ -549,14 +563,49 @@ find_volume_for_mount_path (GGduVolumeMonitor *monitor,
for (l = monitor->volumes; l != NULL; l = l->next)
{
GGduVolume *volume = l->data;
+ if (g_gdu_volume_has_mount_path (volume, mount_path))
+ {
+ found = volume;
+ goto out;
+ }
+ }
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ GGduVolume *volume = l->data;
if (g_gdu_volume_has_mount_path (volume, mount_path))
{
found = volume;
- break;
+ goto out;
}
}
+ out:
+ return found;
+}
+
+static GGduVolume *
+find_volume_for_unix_mount_point (GGduVolumeMonitor *monitor,
+ GUnixMountPoint *unix_mount_point)
+{
+ GList *l;
+ GGduVolume *found;
+
+ found = NULL;
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ GGduVolume *volume = l->data;
+ GUnixMountPoint *volume_mount_point;
+
+ volume_mount_point = g_gdu_volume_get_unix_mount_point (volume);
+ if (g_unix_mount_point_compare (unix_mount_point, volume_mount_point) == 0)
+ {
+ found = volume;
+ goto out;
+ }
+ }
+
+ out:
return found;
}
@@ -859,6 +908,7 @@ update_all (GGduVolumeMonitor *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,
@@ -935,16 +985,34 @@ find_volume_for_device_file (GGduVolumeMonitor *monitor,
const gchar *device_file)
{
GList *l;
+ GGduVolume *ret;
+ ret = NULL;
for (l = monitor->volumes; l != NULL; l = l->next)
{
GGduVolume *volume = G_GDU_VOLUME (l->data);
if (g_gdu_volume_has_device_file (volume, device_file))
- return volume;
+ {
+ ret = volume;
+ goto out;
+ }
}
- return NULL;
+ ret = NULL;
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ {
+ GGduVolume *volume = G_GDU_VOLUME (l->data);
+
+ if (g_gdu_volume_has_device_file (volume, device_file))
+ {
+ ret = volume;
+ goto out;
+ }
+ }
+
+ out:
+ return ret;
}
static GGduDrive *
@@ -1189,6 +1257,106 @@ update_volumes (GGduVolumeMonitor *monitor,
}
static void
+update_fstab_volumes (GGduVolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes)
+{
+ GList *fstab_mount_points;
+ GList *cur_fstab_mount_points;
+ GList *new_fstab_mount_points;
+ GList *removed, *added;
+ GList *l;
+ GGduVolume *volume;
+
+ fstab_mount_points = g_unix_mount_points_get (NULL);
+
+ cur_fstab_mount_points = NULL;
+ for (l = monitor->fstab_volumes; l != NULL; l = l->next)
+ cur_fstab_mount_points = g_list_prepend (cur_fstab_mount_points, g_gdu_volume_get_unix_mount_point (G_GDU_VOLUME (l->data)));
+
+ new_fstab_mount_points = NULL;
+ for (l = fstab_mount_points; l != NULL; l = l->next)
+ {
+ GUnixMountPoint *mount_point = l->data;
+ const gchar *device_file;
+
+ /* only show user mountable mount points */
+ if (!g_unix_mount_point_is_user_mountable (mount_point))
+ continue;
+
+ /* only show stuff that can be mounted in user-visible locations */
+ if (!_g_unix_mount_point_guess_should_display (mount_point))
+ continue;
+
+ /* ignore mount point if the device doesn't exist or is handled by DeviceKit-disks */
+ device_file = g_unix_mount_point_get_device_path (mount_point);
+ if (g_str_has_prefix (device_file, "/dev/"))
+ {
+ gchar resolved_path[PATH_MAX];
+ GduDevice *device;
+
+ /* doesn't exist */
+ if (realpath (device_file, resolved_path) != 0)
+ continue;
+
+ /* is handled by DKD */
+ device = gdu_pool_get_by_device_file (monitor->pool, resolved_path);
+ if (device != NULL)
+ {
+ g_object_unref (device);
+ continue;
+ }
+ }
+
+ new_fstab_mount_points = g_list_prepend (new_fstab_mount_points, mount_point);
+ }
+
+ diff_sorted_lists (cur_fstab_mount_points,
+ new_fstab_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_volume_for_unix_mount_point (monitor, mount_point);
+ if (volume != NULL)
+ {
+ g_gdu_volume_removed (volume);
+ monitor->fstab_volumes = g_list_remove (monitor->fstab_volumes, volume);
+ *removed_volumes = g_list_prepend (*removed_volumes, volume);
+ /*g_debug ("removed volume for /etc/fstab mount point %s", g_unix_mount_point_get_mount_path (mount_point));*/
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ GUnixMountPoint *mount_point = l->data;
+
+ volume = g_gdu_volume_new_for_unix_mount_point (G_VOLUME_MONITOR (monitor), mount_point);
+ if (volume != NULL)
+ {
+ /* steal mount_point since g_gdu_volume_new_for_unix_mount_point() takes ownership of it */
+ fstab_mount_points = g_list_remove (fstab_mount_points, mount_point);
+ monitor->fstab_volumes = g_list_prepend (monitor->fstab_volumes, volume);
+ *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
+ /*g_debug ("added volume for /etc/fstab mount point %s", g_unix_mount_point_get_mount_path (mount_point));*/
+ }
+ else
+ {
+ g_unix_mount_point_free (mount_point);
+ }
+ }
+
+ g_list_free (added);
+ g_list_free (removed);
+
+ g_list_free (cur_fstab_mount_points);
+
+ g_list_foreach (fstab_mount_points, (GFunc) g_unix_mount_point_free, NULL);
+ g_list_free (fstab_mount_points);
+}
+
+static void
update_mounts (GGduVolumeMonitor *monitor,
GList **added_mounts,
GList **removed_mounts)
--
1.6.2.2