summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2008-12-01 13:58:05 +0000
committerAlexander Larsson <alexl@src.gnome.org>2008-12-01 13:58:05 +0000
commitcec43f678f2c6cc06e13cd051d7ef68f920a1fab (patch)
tree360aa2a05b59514695b269c20043e48b36fb07a3
parentbefde2fec59ad361a309e307342b07ea8cf9835c (diff)
downloadgvfs-cec43f678f2c6cc06e13cd051d7ef68f920a1fab.tar.gz
Use the new support for shadow mounts instead of
2008-12-01 Alexander Larsson <alexl@redhat.com> * client/gdaemonmount.c: * client/gdaemonvolumemonitor.c: * monitor/proxy/Makefile.am: * monitor/proxy/gproxydrive.c: * monitor/proxy/gproxymount.c: * monitor/proxy/gproxyvolume.c: * monitor/proxy/gproxyvolume.h: * monitor/proxy/gproxyvolumemonitor.c: * monitor/proxy/gproxyvolumemonitor.h: * monitor/proxy/remote-volume-monitor-module.c: * monitor/proxy/gproxyshadowmount.[ch]: Use the new support for shadow mounts instead of g_volume_monitor_adopt_orphan_mount Patch from David Zeuthen (#555332) * programs/gvfs-mount.c: Add support to monitor volume monitor events svn path=/trunk/; revision=2119
-rw-r--r--ChangeLog21
-rw-r--r--client/gdaemonmount.c148
-rw-r--r--client/gdaemonvolumemonitor.c8
-rw-r--r--monitor/proxy/Makefile.am1
-rw-r--r--monitor/proxy/gproxydrive.c3
-rw-r--r--monitor/proxy/gproxymount.c3
-rw-r--r--monitor/proxy/gproxyshadowmount.c441
-rw-r--r--monitor/proxy/gproxyshadowmount.h59
-rw-r--r--monitor/proxy/gproxyvolume.c282
-rw-r--r--monitor/proxy/gproxyvolume.h4
-rw-r--r--monitor/proxy/gproxyvolumemonitor.c72
-rw-r--r--monitor/proxy/gproxyvolumemonitor.h1
-rw-r--r--monitor/proxy/remote-volume-monitor-module.c2
-rw-r--r--programs/gvfs-mount.c252
14 files changed, 1037 insertions, 260 deletions
diff --git a/ChangeLog b/ChangeLog
index e1f2a3be..84e8a0e4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
2008-12-01 Alexander Larsson <alexl@redhat.com>
+ * client/gdaemonmount.c:
+ * client/gdaemonvolumemonitor.c:
+ * monitor/proxy/Makefile.am:
+ * monitor/proxy/gproxydrive.c:
+ * monitor/proxy/gproxymount.c:
+ * monitor/proxy/gproxyvolume.c:
+ * monitor/proxy/gproxyvolume.h:
+ * monitor/proxy/gproxyvolumemonitor.c:
+ * monitor/proxy/gproxyvolumemonitor.h:
+ * monitor/proxy/remote-volume-monitor-module.c:
+ * monitor/proxy/gproxyshadowmount.[ch]:
+ Use the new support for shadow mounts instead
+ of g_volume_monitor_adopt_orphan_mount
+
+ Patch from David Zeuthen (#555332)
+
+ * programs/gvfs-mount.c:
+ Add support to monitor volume monitor events
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
* configure.ac:
Post release version bump
diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c
index 7c7b09f7..5c41c026 100644
--- a/client/gdaemonmount.c
+++ b/client/gdaemonmount.c
@@ -43,7 +43,6 @@ struct _GDaemonMount {
GMountInfo *mount_info;
- GVolume *foreign_volume;
GVolumeMonitor *volume_monitor;
};
@@ -60,9 +59,6 @@ g_daemon_mount_finalize (GObject *object)
mount = G_DAEMON_MOUNT (object);
- if (mount->foreign_volume != NULL)
- g_object_unref (mount->foreign_volume);
-
if (mount->volume_monitor != NULL)
g_object_remove_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor));
@@ -140,24 +136,13 @@ g_daemon_mount_get_uuid (GMount *mount)
static GVolume *
g_daemon_mount_get_volume (GMount *mount)
{
- GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
- if (daemon_mount->foreign_volume != NULL)
- return g_object_ref (daemon_mount->foreign_volume);
return NULL;
}
static GDrive *
g_daemon_mount_get_drive (GMount *mount)
{
- GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
- GDrive *drive;
-
- G_LOCK (daemon_mount);
- drive = NULL;
- if (daemon_mount->foreign_volume != NULL)
- drive = g_volume_get_drive (daemon_mount->foreign_volume);
- G_UNLOCK (daemon_mount);
- return drive;
+ return NULL;
}
static gboolean
@@ -169,60 +154,7 @@ g_daemon_mount_can_unmount (GMount *mount)
static gboolean
g_daemon_mount_can_eject (GMount *mount)
{
- GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
- gboolean res;
-
- G_LOCK (daemon_mount);
- res = FALSE;
- if (daemon_mount->foreign_volume != NULL)
- res = g_volume_can_eject (daemon_mount->foreign_volume);
- G_UNLOCK (daemon_mount);
-
- return res;
-}
-
-static void
-foreign_volume_removed (GVolume *volume, gpointer user_data)
-{
- GDaemonMount *daemon_mount = G_DAEMON_MOUNT (user_data);
-
- G_LOCK (daemon_mount);
-
- g_object_ref (daemon_mount);
-
- if (daemon_mount->foreign_volume == volume)
- {
- g_object_unref (daemon_mount->foreign_volume);
- daemon_mount->foreign_volume = NULL;
- }
-
- G_UNLOCK (daemon_mount);
-
- g_signal_emit_by_name (daemon_mount, "changed");
- if (daemon_mount->volume_monitor != NULL)
- g_signal_emit_by_name (daemon_mount->volume_monitor, "mount_changed", daemon_mount);
-
- g_object_unref (daemon_mount);
-}
-
-void
-g_daemon_mount_set_foreign_volume (GDaemonMount *mount,
- GVolume *foreign_volume)
-{
- G_LOCK (daemon_mount);
-
- if (mount->foreign_volume != NULL)
- g_object_unref (mount->foreign_volume);
-
- if (foreign_volume != NULL)
- {
- mount->foreign_volume = foreign_volume;
- g_signal_connect_object (foreign_volume, "removed", (GCallback) foreign_volume_removed, mount, 0);
- }
- else
- mount->foreign_volume = NULL;
-
- G_UNLOCK (daemon_mount);
+ return FALSE;
}
static void
@@ -283,80 +215,6 @@ g_daemon_mount_unmount_finish (GMount *mount,
return TRUE;
}
-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_free (data);
-}
-
-static void
-g_daemon_mount_eject (GMount *mount,
- GMountUnmountFlags flags,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
- GDrive *drive;
-
- G_LOCK (daemon_mount);
-
- drive = NULL;
- if (daemon_mount->foreign_volume != NULL)
- drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
-
- G_UNLOCK (daemon_mount);
-
- if (drive != NULL)
- {
- EjectWrapperOp *data;
- data = g_new0 (EjectWrapperOp, 1);
- data->object = G_OBJECT (mount);
- data->callback = callback;
- data->user_data = user_data;
- g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
- g_object_unref (drive);
- }
-}
-
-static gboolean
-g_daemon_mount_eject_finish (GMount *mount,
- GAsyncResult *result,
- GError **error)
-{
- GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
- GDrive *drive;
- gboolean res;
-
- res = TRUE;
-
- G_LOCK (daemon_mount);
-
- drive = NULL;
- if (daemon_mount->foreign_volume != NULL)
- drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
-
- G_UNLOCK (daemon_mount);
-
- if (drive != NULL)
- {
- res = g_drive_eject_finish (drive, result, error);
- g_object_unref (drive);
- }
-
- return res;
-}
-
static char **
g_daemon_mount_guess_content_type_sync (GMount *mount,
gboolean force_rescan,
@@ -414,8 +272,6 @@ g_daemon_mount_mount_iface_init (GMountIface *iface)
iface->can_eject = g_daemon_mount_can_eject;
iface->unmount = g_daemon_mount_unmount;
iface->unmount_finish = g_daemon_mount_unmount_finish;
- iface->eject = g_daemon_mount_eject;
- iface->eject_finish = g_daemon_mount_eject_finish;
iface->guess_content_type = g_daemon_mount_guess_content_type;
iface->guess_content_type_finish = g_daemon_mount_guess_content_type_finish;
iface->guess_content_type_sync = g_daemon_mount_guess_content_type_sync;
diff --git a/client/gdaemonvolumemonitor.c b/client/gdaemonvolumemonitor.c
index e26bde09..2ca21130 100644
--- a/client/gdaemonvolumemonitor.c
+++ b/client/gdaemonvolumemonitor.c
@@ -136,7 +136,6 @@ static void
mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info)
{
GDaemonMount *mount;
- GVolume *volume;
G_LOCK (daemon_vm);
@@ -152,9 +151,6 @@ mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info)
if (mount_info->user_visible)
{
mount = g_daemon_mount_new (mount_info, G_VOLUME_MONITOR (daemon_monitor));
- volume = g_volume_monitor_adopt_orphan_mount (G_MOUNT (mount));
- if (volume != NULL)
- g_daemon_mount_set_foreign_volume (mount, volume);
daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount);
/* Ref for the signal emission, other ref is owned by volume monitor */
@@ -204,7 +200,6 @@ g_daemon_volume_monitor_init (GDaemonVolumeMonitor *daemon_monitor)
GList *mounts, *l;
GDaemonMount *mount;
GMountInfo *info;
- GVolume *volume;
_the_daemon_volume_monitor = daemon_monitor;
@@ -223,9 +218,6 @@ g_daemon_volume_monitor_init (GDaemonVolumeMonitor *daemon_monitor)
if (info->user_visible)
{
mount = g_daemon_mount_new (info, G_VOLUME_MONITOR (daemon_monitor));
- volume = g_volume_monitor_adopt_orphan_mount (G_MOUNT (mount));
- if (volume != NULL)
- g_daemon_mount_set_foreign_volume (mount, volume);
daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount);
}
diff --git a/monitor/proxy/Makefile.am b/monitor/proxy/Makefile.am
index 9f1c9743..e85ea271 100644
--- a/monitor/proxy/Makefile.am
+++ b/monitor/proxy/Makefile.am
@@ -12,6 +12,7 @@ libgioremote_volume_monitor_la_SOURCES = \
gproxydrive.c gproxydrive.h \
gproxyvolume.c gproxyvolume.h \
gproxymount.c gproxymount.h \
+ gproxyshadowmount.c gproxyshadowmount.h \
gproxyvolumemonitor.c gproxyvolumemonitor.h \
$(NULL)
diff --git a/monitor/proxy/gproxydrive.c b/monitor/proxy/gproxydrive.c
index 5c150f7a..f2dd0baf 100644
--- a/monitor/proxy/gproxydrive.c
+++ b/monitor/proxy/gproxydrive.c
@@ -115,6 +115,9 @@ g_proxy_drive_new (GProxyVolumeMonitor *volume_monitor)
GProxyDrive *drive;
drive = g_object_new (G_TYPE_PROXY_DRIVE, NULL);
drive->volume_monitor = g_object_ref (volume_monitor);
+ g_object_set_data (G_OBJECT (drive),
+ "g-proxy-drive-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
return drive;
}
diff --git a/monitor/proxy/gproxymount.c b/monitor/proxy/gproxymount.c
index 4f9a4a8c..5d77963c 100644
--- a/monitor/proxy/gproxymount.c
+++ b/monitor/proxy/gproxymount.c
@@ -115,6 +115,9 @@ g_proxy_mount_new (GProxyVolumeMonitor *volume_monitor)
GProxyMount *mount;
mount = g_object_new (G_TYPE_PROXY_MOUNT, NULL);
mount->volume_monitor = g_object_ref (volume_monitor);
+ g_object_set_data (G_OBJECT (mount),
+ "g-proxy-mount-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
return mount;
}
diff --git a/monitor/proxy/gproxyshadowmount.c b/monitor/proxy/gproxyshadowmount.c
new file mode 100644
index 00000000..424c71d7
--- /dev/null
+++ b/monitor/proxy/gproxyshadowmount.c
@@ -0,0 +1,441 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxyshadowmount.h"
+#include "gproxyvolume.h"
+
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
+/* Protects all fields of GProxyShadowMount that can change */
+G_LOCK_DEFINE_STATIC(proxy_shadow_mount);
+
+struct _GProxyShadowMount {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ GProxyVolume *volume;
+ GMount *real_mount;
+ GFile *root;
+};
+
+static void g_proxy_shadow_mount_mount_iface_init (GMountIface *iface);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \
+ const GInterfaceInfo g_implement_interface_info = { \
+ (GInterfaceInitFunc) iface_init, NULL, NULL \
+ }; \
+ g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyShadowMount, g_proxy_shadow_mount, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_MOUNT,
+ g_proxy_shadow_mount_mount_iface_init))
+
+static void
+g_proxy_shadow_mount_finalize (GObject *object)
+{
+ GProxyShadowMount *mount;
+
+ mount = G_PROXY_SHADOW_MOUNT (object);
+
+ g_proxy_shadow_mount_remove (mount);
+
+ if (mount->volume_monitor != NULL)
+ g_object_unref (mount->volume_monitor);
+
+ if (mount->volume != NULL)
+ g_object_unref (mount->volume);
+
+ if (mount->root != NULL)
+ g_object_unref (mount->root);
+
+ if (G_OBJECT_CLASS (g_proxy_shadow_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_shadow_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_shadow_mount_class_init (GProxyShadowMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_shadow_mount_finalize;
+}
+
+static void
+g_proxy_shadow_mount_class_finalize (GProxyShadowMountClass *klass)
+{
+}
+
+static void
+g_proxy_shadow_mount_init (GProxyShadowMount *proxy_shadow_mount)
+{
+}
+
+void
+g_proxy_shadow_mount_remove (GProxyShadowMount *mount)
+{
+ if (mount->real_mount != NULL)
+ {
+ g_mount_unshadow (mount->real_mount);
+ signal_emit_in_idle (mount->real_mount, "changed", NULL);
+ signal_emit_in_idle (mount->volume_monitor, "mount-changed", mount->real_mount);
+ g_object_unref (mount->real_mount);
+ mount->real_mount = NULL;
+ }
+}
+
+GProxyShadowMount *
+g_proxy_shadow_mount_new (GProxyVolumeMonitor *volume_monitor,
+ GProxyVolume *volume,
+ GMount *real_mount)
+{
+ GProxyShadowMount *mount;
+ GFile *activation_root;
+
+ mount = NULL;
+
+ activation_root = g_volume_get_activation_root (G_VOLUME (volume));
+ if (activation_root == NULL)
+ {
+ g_warning ("Cannot construct a GProxyShadowMount object for a volume without an activation root");
+ goto out;
+ }
+
+ mount = g_object_new (G_TYPE_PROXY_SHADOW_MOUNT, NULL);
+ mount->volume_monitor = g_object_ref (volume_monitor);
+ mount->volume = g_object_ref (volume);
+ mount->real_mount = g_object_ref (real_mount);
+ mount->root = activation_root;
+
+ g_mount_shadow (mount->real_mount);
+ signal_emit_in_idle (mount->real_mount, "changed", NULL);
+ signal_emit_in_idle (mount->volume_monitor, "mount-changed", mount->real_mount);
+
+ g_object_set_data (G_OBJECT (mount),
+ "g-proxy-shadow-mount-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
+
+ out:
+ return mount;
+}
+
+gboolean
+g_proxy_shadow_mount_has_mount_path (GProxyShadowMount *mount, const char *mount_path)
+{
+ char *path;
+ gboolean result;
+ result = FALSE;
+ path = g_file_get_path (mount->root);
+ if (path != NULL)
+ {
+ if (strcmp (path, mount_path) == 0)
+ result = TRUE;
+ g_free (path);
+ }
+ return result;
+}
+
+static GFile *
+g_proxy_shadow_mount_get_root (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GFile *root;
+
+ G_LOCK (proxy_shadow_mount);
+ root = g_object_ref (proxy_shadow_mount->root);
+ G_UNLOCK (proxy_shadow_mount);
+ return root;
+}
+
+static GIcon *
+g_proxy_shadow_mount_get_icon (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GIcon *icon;
+
+ G_LOCK (proxy_shadow_mount);
+ icon = g_volume_get_icon (G_VOLUME (proxy_shadow_mount->volume));
+ G_UNLOCK (proxy_shadow_mount);
+ return icon;
+}
+
+static char *
+g_proxy_shadow_mount_get_uuid (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ char *uuid;
+
+ G_LOCK (proxy_shadow_mount);
+ uuid = g_mount_get_uuid (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+ return uuid;
+}
+
+static char *
+g_proxy_shadow_mount_get_name (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ char *name;
+
+ G_LOCK (proxy_shadow_mount);
+ name = g_volume_get_name (G_VOLUME (proxy_shadow_mount->volume));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return name;
+}
+
+static GDrive *
+g_proxy_shadow_mount_get_drive (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GDrive *drive;
+
+ G_LOCK (proxy_shadow_mount);
+ drive = g_mount_get_drive (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return drive;
+}
+
+static GVolume *
+g_proxy_shadow_mount_get_volume (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GVolume *volume;
+
+ G_LOCK (proxy_shadow_mount);
+ volume = g_object_ref (proxy_shadow_mount->volume);
+ G_UNLOCK (proxy_shadow_mount);
+
+ return volume;
+}
+
+static gboolean
+g_proxy_shadow_mount_can_unmount (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_shadow_mount);
+ res = g_mount_can_unmount (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return res;
+}
+
+static gboolean
+g_proxy_shadow_mount_can_eject (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_shadow_mount);
+ res = g_mount_can_eject (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return res;
+}
+
+static void
+g_proxy_shadow_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ g_mount_eject (proxy_shadow_mount->real_mount,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static gboolean
+g_proxy_shadow_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ return g_mount_eject_finish (proxy_shadow_mount->real_mount,
+ result,
+ error);
+}
+
+static void
+g_proxy_shadow_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ g_mount_unmount (proxy_shadow_mount->real_mount,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static gboolean
+g_proxy_shadow_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ return g_mount_unmount_finish (proxy_shadow_mount->real_mount,
+ result,
+ error);
+}
+
+static void
+g_proxy_shadow_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ g_mount_guess_content_type (proxy_shadow_mount->real_mount,
+ force_rescan,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static char **
+g_proxy_shadow_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ return g_mount_guess_content_type_finish (proxy_shadow_mount->real_mount,
+ result,
+ error);
+}
+
+static char **
+g_proxy_shadow_mount_guess_content_type_sync (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ return g_mount_guess_content_type_sync (proxy_shadow_mount->real_mount,
+ force_rescan,
+ cancellable,
+ error);
+}
+
+GMount *
+g_proxy_shadow_mount_get_real_mount (GProxyShadowMount *mount)
+{
+ return g_object_ref (mount->real_mount);
+}
+
+GFile *
+g_proxy_shadow_mount_get_activation_root (GProxyShadowMount *mount)
+{
+ return g_object_ref (mount->root);
+}
+
+static void
+g_proxy_shadow_mount_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_proxy_shadow_mount_get_root;
+ iface->get_name = g_proxy_shadow_mount_get_name;
+ iface->get_icon = g_proxy_shadow_mount_get_icon;
+ iface->get_uuid = g_proxy_shadow_mount_get_uuid;
+ iface->get_drive = g_proxy_shadow_mount_get_drive;
+ iface->get_volume = g_proxy_shadow_mount_get_volume;
+ iface->can_unmount = g_proxy_shadow_mount_can_unmount;
+ iface->can_eject = g_proxy_shadow_mount_can_eject;
+ iface->unmount = g_proxy_shadow_mount_unmount;
+ iface->unmount_finish = g_proxy_shadow_mount_unmount_finish;
+ iface->eject = g_proxy_shadow_mount_eject;
+ iface->eject_finish = g_proxy_shadow_mount_eject_finish;
+ iface->guess_content_type = g_proxy_shadow_mount_guess_content_type;
+ iface->guess_content_type_finish = g_proxy_shadow_mount_guess_content_type_finish;
+ iface->guess_content_type_sync = g_proxy_shadow_mount_guess_content_type_sync;
+}
+
+void
+g_proxy_shadow_mount_register (GIOModule *module)
+{
+ g_proxy_shadow_mount_register_type (G_TYPE_MODULE (module));
+}
+
+typedef struct {
+ const char *signal_name;
+ GObject *object;
+ GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+ if (data->other_object != NULL)
+ {
+ g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+ g_object_unref (data->other_object);
+ }
+ else
+ {
+ g_signal_emit_by_name (data->object, data->signal_name);
+ }
+ g_object_unref (data->object);
+ g_free (data);
+
+ return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+ SignalEmitIdleData *data;
+
+ data = g_new0 (SignalEmitIdleData, 1);
+ data->signal_name = signal_name;
+ data->object = g_object_ref (G_OBJECT (object));
+ data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+ g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}
diff --git a/monitor/proxy/gproxyshadowmount.h b/monitor/proxy/gproxyshadowmount.h
new file mode 100644
index 00000000..d099f9da
--- /dev/null
+++ b/monitor/proxy/gproxyshadowmount.h
@@ -0,0 +1,59 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_PROXY_SHADOW_MOUNT_H__
+#define __G_PROXY_SHADOW_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_SHADOW_MOUNT (g_proxy_shadow_mount_get_type ())
+#define G_PROXY_SHADOW_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_SHADOW_MOUNT, GProxyShadowMount))
+#define G_PROXY_SHADOW_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_SHADOW_MOUNT, GProxyShadowMountClass))
+#define G_IS_PROXY_SHADOW_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_SHADOW_MOUNT))
+#define G_IS_PROXY_SHADOW_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_SHADOW_MOUNT))
+
+typedef struct _GProxyShadowMountClass GProxyShadowMountClass;
+
+struct _GProxyShadowMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_shadow_mount_get_type (void) G_GNUC_CONST;
+void g_proxy_shadow_mount_register (GIOModule *module);
+GProxyShadowMount *g_proxy_shadow_mount_new (GProxyVolumeMonitor *volume_monitor,
+ GProxyVolume *volume,
+ GMount *real_mount);
+GMount *g_proxy_shadow_mount_get_real_mount (GProxyShadowMount *mount);
+GFile *g_proxy_shadow_mount_get_activation_root (GProxyShadowMount *mount);
+gboolean g_proxy_shadow_mount_has_mount_path (GProxyShadowMount *mount,
+ const char *mount_path);
+void g_proxy_shadow_mount_remove (GProxyShadowMount *mount);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_SHADOW_MOUNT_H__ */
diff --git a/monitor/proxy/gproxyvolume.c b/monitor/proxy/gproxyvolume.c
index 6eb8be67..d52c460e 100644
--- a/monitor/proxy/gproxyvolume.c
+++ b/monitor/proxy/gproxyvolume.c
@@ -37,6 +37,8 @@
#include "gproxyvolume.h"
#include "gproxymount.h"
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
/* Protects all fields of GProxyVolume that can change */
G_LOCK_DEFINE_STATIC(proxy_volume);
@@ -45,6 +47,9 @@ struct _GProxyVolume {
GProxyVolumeMonitor *volume_monitor;
+ /* non-NULL only if activation_uri != NULL */
+ GVolumeMonitor *union_monitor;
+
char *id;
char *name;
char *uuid;
@@ -54,10 +59,10 @@ struct _GProxyVolume {
char *mount_id;
GHashTable *identifiers;
- GMount *foreign_mount;
-
gboolean can_mount;
gboolean should_automount;
+
+ GProxyShadowMount *shadow_mount;
};
static void g_proxy_volume_volume_iface_init (GVolumeIface *iface);
@@ -73,6 +78,30 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyVolume, g_proxy_volume, G_TYPE_OBJECT, 0,
_G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_VOLUME,
g_proxy_volume_volume_iface_init))
+
+static void union_monitor_mount_added (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume);
+
+static void union_monitor_mount_removed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume);
+
+static void union_monitor_mount_changed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume);
+
+static void update_shadow_mount (GProxyVolume *volume);
+
+GProxyShadowMount *
+g_proxy_volume_get_shadow_mount (GProxyVolume *volume)
+{
+ if (volume->shadow_mount != NULL)
+ return g_object_ref (volume->shadow_mount);
+ else
+ return NULL;
+}
+
static void
g_proxy_volume_finalize (GObject *object)
{
@@ -91,11 +120,26 @@ g_proxy_volume_finalize (GObject *object)
if (volume->identifiers != NULL)
g_hash_table_unref (volume->identifiers);
- if (volume->foreign_mount != NULL)
- g_object_unref (volume->foreign_mount);
+ if (volume->shadow_mount != NULL)
+ {
+ signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+ g_proxy_shadow_mount_remove (volume->shadow_mount);
+ g_object_unref (volume->shadow_mount);
+ }
+
+ if (volume->union_monitor != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_added, volume);
+ g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_removed, volume);
+ g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_changed, volume);
+ g_object_unref (volume->union_monitor);
+ }
if (volume->volume_monitor != NULL)
- g_object_unref (volume->volume_monitor);
+ {
+ g_object_unref (volume->volume_monitor);
+ }
if (G_OBJECT_CLASS (g_proxy_volume_parent_class)->finalize)
(*G_OBJECT_CLASS (g_proxy_volume_parent_class)->finalize) (object);
@@ -125,53 +169,159 @@ g_proxy_volume_new (GProxyVolumeMonitor *volume_monitor)
GProxyVolume *volume;
volume = g_object_new (G_TYPE_PROXY_VOLUME, NULL);
volume->volume_monitor = g_object_ref (volume_monitor);
+ g_object_set_data (G_OBJECT (volume),
+ "g-proxy-volume-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
return volume;
}
-static gboolean
-changed_in_idle (gpointer data)
-{
- GProxyVolume *volume = data;
-
- g_signal_emit_by_name (volume, "changed");
- if (volume->volume_monitor != NULL)
- g_signal_emit_by_name (volume->volume_monitor, "volume-changed", volume);
- g_object_unref (volume);
- return FALSE;
+static void
+union_monitor_mount_added (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume)
+{
+ update_shadow_mount (volume);
}
static void
-foreign_mount_unmounted (GMount *mount, gpointer user_data)
+union_monitor_mount_removed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume)
{
- GProxyVolume *volume = G_PROXY_VOLUME (user_data);
- gboolean check;
+ update_shadow_mount (volume);
+}
- G_LOCK (proxy_volume);
- check = (volume->foreign_mount == mount);
- G_UNLOCK (proxy_volume);
- if (check)
- g_proxy_volume_adopt_foreign_mount (volume, NULL);
+static void
+union_monitor_mount_changed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume)
+{
+ if (volume->shadow_mount != NULL)
+ {
+ GMount *real_mount;
+ real_mount = g_proxy_shadow_mount_get_real_mount (volume->shadow_mount);
+ if (mount == real_mount)
+ {
+ signal_emit_in_idle (volume->shadow_mount, "changed", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-changed", volume->shadow_mount);
+ }
+ g_object_unref (real_mount);
+ }
}
-void
-g_proxy_volume_adopt_foreign_mount (GProxyVolume *volume,
- GMount *foreign_mount)
+static void
+update_shadow_mount (GProxyVolume *volume)
{
- G_LOCK (proxy_volume);
- if (volume->foreign_mount != NULL)
- g_object_unref (volume->foreign_mount);
+ GFile *activation_root;
+ GList *mounts;
+ GList *l;
+ GMount *mount_to_shadow;
+
+ activation_root = NULL;
+ mount_to_shadow = NULL;
+
+ if (volume->activation_uri == NULL)
+ goto out;
- if (foreign_mount != NULL)
+ activation_root = g_file_new_for_uri (volume->activation_uri);
+
+ if (volume->union_monitor == NULL)
{
- volume->foreign_mount = g_object_ref (foreign_mount);
- g_signal_connect_object (foreign_mount, "unmounted", (GCallback) foreign_mount_unmounted, volume, 0);
+ volume->union_monitor = g_volume_monitor_get ();
+ g_signal_connect (volume->union_monitor, "mount-added", (GCallback) union_monitor_mount_added, volume);
+ g_signal_connect (volume->union_monitor, "mount-removed", (GCallback) union_monitor_mount_removed, volume);
+ g_signal_connect (volume->union_monitor, "mount-changed", (GCallback) union_monitor_mount_changed, volume);
+ }
+
+ mounts = g_volume_monitor_get_mounts (volume->union_monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = G_MOUNT (l->data);
+ GFile *mount_root;
+
+ /* don't consider our (possibly) existing shadow mount */
+ if (G_IS_PROXY_SHADOW_MOUNT (mount))
+ continue;
+
+ mount_root = g_mount_get_root (mount);
+ if (g_file_has_prefix (activation_root, mount_root))
+ {
+ mount_to_shadow = g_object_ref (mount);
+ break;
+ }
+ }
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+
+ if (mount_to_shadow != NULL)
+ {
+ /* there's now a mount to shadow, if we don't have a GProxyShadowMount then create one */
+ if (volume->shadow_mount == NULL)
+ {
+ volume->shadow_mount = g_proxy_shadow_mount_new (volume->volume_monitor,
+ volume,
+ mount_to_shadow);
+ signal_emit_in_idle (volume->volume_monitor, "mount-added", volume->shadow_mount);
+ }
+ else
+ {
+ GFile *current_activation_root;
+
+ /* we have a GProxyShadowMount already. However, we need to replace it if the
+ * activation root has changed.
+ */
+ current_activation_root = g_proxy_shadow_mount_get_activation_root (volume->shadow_mount);
+ if (!g_file_equal (current_activation_root, activation_root))
+ {
+ signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+ g_proxy_shadow_mount_remove (volume->shadow_mount);
+ g_object_unref (volume->shadow_mount);
+ volume->shadow_mount = NULL;
+
+ volume->shadow_mount = g_proxy_shadow_mount_new (volume->volume_monitor,
+ volume,
+ mount_to_shadow);
+ signal_emit_in_idle (volume->volume_monitor, "mount-added", volume->shadow_mount);
+ }
+ g_object_unref (current_activation_root);
+ }
}
else
- volume->foreign_mount = NULL;
+ {
+ /* no mount to shadow; if we have a GProxyShadowMount then remove it */
+ if (volume->shadow_mount != NULL)
+ {
+ signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+ g_proxy_shadow_mount_remove (volume->shadow_mount);
+ g_object_unref (volume->shadow_mount);
+ volume->shadow_mount = NULL;
+ }
+ }
- g_idle_add (changed_in_idle, g_object_ref (volume));
- G_UNLOCK (proxy_volume);
+ out:
+
+ if (activation_root != NULL)
+ g_object_unref (activation_root);
+
+ if (mount_to_shadow != NULL)
+ g_object_unref (mount_to_shadow);
+}
+
+static gboolean
+update_shadow_mount_in_idle_do (GProxyVolume *volume)
+{
+ update_shadow_mount (volume);
+ g_object_unref (volume);
+ return FALSE;
+}
+
+static void
+update_shadow_mount_in_idle (GProxyVolume *volume)
+{
+ g_idle_add ((GSourceFunc) update_shadow_mount_in_idle_do, g_object_ref (volume));
}
/* string id
@@ -264,6 +414,9 @@ void g_proxy_volume_update (GProxyVolume *volume,
volume->should_automount = should_automount;
volume->identifiers = identifiers != NULL ? g_hash_table_ref (identifiers) : NULL;
+ /* this calls into the union monitor; do it in idle to avoid locking issues */
+ update_shadow_mount_in_idle (volume);
+
out:
g_hash_table_unref (identifiers);
}
@@ -381,22 +534,21 @@ g_proxy_volume_get_mount (GVolume *volume)
GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
GMount *mount;
+ mount = NULL;
+
G_LOCK (proxy_volume);
- if (proxy_volume->foreign_mount != NULL)
+
+ if (proxy_volume->shadow_mount != NULL)
{
- mount = g_object_ref (proxy_volume->foreign_mount);
+ mount = g_object_ref (proxy_volume->shadow_mount);
}
- else
+ else if (proxy_volume->mount_id != NULL && strlen (proxy_volume->mount_id) > 0)
{
- mount = NULL;
- if (proxy_volume->mount_id != NULL && strlen (proxy_volume->mount_id) > 0)
- {
- GProxyMount *proxy_mount;
- proxy_mount = g_proxy_volume_monitor_get_mount_for_id (proxy_volume->volume_monitor,
- proxy_volume->mount_id);
- if (proxy_mount != NULL)
- mount = G_MOUNT (proxy_mount);
- }
+ GProxyMount *proxy_mount;
+ proxy_mount = g_proxy_volume_monitor_get_mount_for_id (proxy_volume->volume_monitor,
+ proxy_volume->mount_id);
+ if (proxy_mount != NULL)
+ mount = G_MOUNT (proxy_mount);
}
G_UNLOCK (proxy_volume);
@@ -690,3 +842,39 @@ g_proxy_volume_register (GIOModule *module)
{
g_proxy_volume_register_type (G_TYPE_MODULE (module));
}
+
+typedef struct {
+ const char *signal_name;
+ GObject *object;
+ GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+ if (data->other_object != NULL)
+ {
+ g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+ g_object_unref (data->other_object);
+ }
+ else
+ {
+ g_signal_emit_by_name (data->object, data->signal_name);
+ }
+ g_object_unref (data->object);
+ g_free (data);
+
+ return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+ SignalEmitIdleData *data;
+
+ data = g_new0 (SignalEmitIdleData, 1);
+ data->signal_name = signal_name;
+ data->object = g_object_ref (G_OBJECT (object));
+ data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+ g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}
diff --git a/monitor/proxy/gproxyvolume.h b/monitor/proxy/gproxyvolume.h
index 5626092f..953b8008 100644
--- a/monitor/proxy/gproxyvolume.h
+++ b/monitor/proxy/gproxyvolume.h
@@ -28,6 +28,7 @@
#include <gio/gio.h>
#include "gproxyvolumemonitor.h"
+#include "gproxyshadowmount.h"
G_BEGIN_DECLS
@@ -48,10 +49,9 @@ GProxyVolume *g_proxy_volume_new (GProxyVolumeMonitor *volume_mo
void g_proxy_volume_update (GProxyVolume *volume,
DBusMessageIter *iter);
const char *g_proxy_volume_get_id (GProxyVolume *volume);
-void g_proxy_volume_adopt_foreign_mount (GProxyVolume *volume,
- GMount *foreign_mount);
void g_proxy_volume_register (GIOModule *module);
+GProxyShadowMount *g_proxy_volume_get_shadow_mount (GProxyVolume *volume);
G_END_DECLS
diff --git a/monitor/proxy/gproxyvolumemonitor.c b/monitor/proxy/gproxyvolumemonitor.c
index d9b4654c..f07672b6 100644
--- a/monitor/proxy/gproxyvolumemonitor.c
+++ b/monitor/proxy/gproxyvolumemonitor.c
@@ -162,6 +162,7 @@ get_mounts (GVolumeMonitor *volume_monitor)
GList *l;
GHashTableIter hash_iter;
GProxyMount *mount;
+ GProxyVolume *volume;
monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
l = NULL;
@@ -172,6 +173,16 @@ get_mounts (GVolumeMonitor *volume_monitor)
while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount))
l = g_list_append (l, g_object_ref (mount));
+ /* also return shadow mounts */
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+ {
+ GProxyShadowMount *shadow_mount;
+ shadow_mount = g_proxy_volume_get_shadow_mount (volume);
+ if (shadow_mount != NULL)
+ l = g_list_append (l, shadow_mount);
+ }
+
G_UNLOCK (proxy_vm);
return l;
@@ -534,9 +545,19 @@ filter_function (DBusConnection *connection, DBusMessage *message, void *user_da
volume = g_hash_table_lookup (monitor->volumes, id);
if (volume != NULL)
{
+ GProxyShadowMount *shadow_mount;
+
g_proxy_volume_update (volume, &iter);
signal_emit_in_idle (volume, "changed", NULL);
signal_emit_in_idle (monitor, "volume-changed", volume);
+
+ shadow_mount = g_proxy_volume_get_shadow_mount (volume);
+ if (shadow_mount != NULL)
+ {
+ signal_emit_in_idle (shadow_mount, "changed", NULL);
+ signal_emit_in_idle (monitor, "mount-changed", shadow_mount);
+ g_object_unref (shadow_mount);
+ }
}
}
else if (strcmp (member, "VolumeAdded") == 0)
@@ -743,56 +764,6 @@ is_supported (GProxyVolumeMonitorClass *klass)
return res;
}
-static GVolume *
-adopt_orphan_mount (GMount *mount, GVolumeMonitor *monitor)
-{
- GProxyVolumeMonitor *proxy_monitor = G_PROXY_VOLUME_MONITOR (monitor);
- GFile *mount_root;
- GProxyVolume *proxy_volume;
- GVolume *ret;
- GHashTableIter hash_iter;
-
- ret = NULL;
-
- G_LOCK (proxy_vm);
-
- mount_root = g_mount_get_root (mount);
-
- /* TODO: consider what happens if two volumes wants to adopt the same mount?
- *
- * e.g. imagine two GVolume objects with activation_roots
- *
- * ssh://server/dir1
- * ssh://server/dir2
- */
-
- g_hash_table_iter_init (&hash_iter, proxy_monitor->volumes);
- while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &proxy_volume))
- {
- GFile *activation_root;
-
- activation_root = g_volume_get_activation_root (G_VOLUME (proxy_volume));
- if (activation_root != NULL)
- {
- if (g_file_has_prefix (activation_root, mount_root) ||
- g_file_equal (activation_root, mount_root))
- {
- g_proxy_volume_adopt_foreign_mount (proxy_volume, mount);
- ret = g_object_ref (proxy_volume);
- g_object_unref (activation_root);
- goto found;
- }
- g_object_unref (activation_root);
- }
- }
-
- found:
- g_object_unref (mount_root);
-
- G_UNLOCK (proxy_vm);
- return ret;
-}
-
static void
g_proxy_volume_monitor_class_init (GProxyVolumeMonitorClass *klass)
{
@@ -809,7 +780,6 @@ g_proxy_volume_monitor_class_init (GProxyVolumeMonitorClass *klass)
monitor_class->get_connected_drives = get_connected_drives;
monitor_class->get_volume_for_uuid = get_volume_for_uuid;
monitor_class->get_mount_for_uuid = get_mount_for_uuid;
- monitor_class->adopt_orphan_mount = adopt_orphan_mount;
i = klass->is_supported_nr;
is_supported_classes[i] = klass;
diff --git a/monitor/proxy/gproxyvolumemonitor.h b/monitor/proxy/gproxyvolumemonitor.h
index 7d87c809..a53adabb 100644
--- a/monitor/proxy/gproxyvolumemonitor.h
+++ b/monitor/proxy/gproxyvolumemonitor.h
@@ -44,6 +44,7 @@ typedef struct _GProxyVolumeMonitorClass GProxyVolumeMonitorClass;
typedef struct _GProxyDrive GProxyDrive;
typedef struct _GProxyVolume GProxyVolume;
typedef struct _GProxyMount GProxyMount;
+typedef struct _GProxyShadowMount GProxyShadowMount;
struct _GProxyVolumeMonitorClass {
GNativeVolumeMonitorClass parent_class;
diff --git a/monitor/proxy/remote-volume-monitor-module.c b/monitor/proxy/remote-volume-monitor-module.c
index 90945141..9178f1e7 100644
--- a/monitor/proxy/remote-volume-monitor-module.c
+++ b/monitor/proxy/remote-volume-monitor-module.c
@@ -31,6 +31,7 @@
#include "gproxyvolumemonitor.h"
#include "gproxyvolume.h"
#include "gproxymount.h"
+#include "gproxyshadowmount.h"
#include "gproxydrive.h"
void
@@ -45,6 +46,7 @@ g_io_module_load (GIOModule *module)
g_proxy_drive_register (module);
g_proxy_mount_register (module);
+ g_proxy_shadow_mount_register (module);
g_proxy_volume_register (module);
g_proxy_volume_monitor_register (module);
out:
diff --git a/programs/gvfs-mount.c b/programs/gvfs-mount.c
index b2659a29..8d0412fa 100644
--- a/programs/gvfs-mount.c
+++ b/programs/gvfs-mount.c
@@ -43,7 +43,8 @@ static GMainLoop *main_loop;
static gboolean mount_mountable = FALSE;
static gboolean mount_unmount = FALSE;
static gboolean mount_list = FALSE;
-static gboolean mount_list_info = FALSE;
+static gboolean extra_detail = FALSE;
+static gboolean mount_monitor = FALSE;
static const char *unmount_scheme = NULL;
static const GOptionEntry entries[] =
@@ -52,7 +53,8 @@ static const GOptionEntry entries[] =
{ "unmount", 'u', 0, G_OPTION_ARG_NONE, &mount_unmount, "Unmount", NULL},
{ "unmount-scheme", 's', 0, G_OPTION_ARG_STRING, &unmount_scheme, "Unmount all mounts with the given scheme", NULL},
{ "list", 'l', 0, G_OPTION_ARG_NONE, &mount_list, "List", NULL},
- { "list-info", 'i', 0, G_OPTION_ARG_NONE, &mount_list_info, "List extra information", NULL},
+ { "detail", 'i', 0, G_OPTION_ARG_NONE, &extra_detail, "Show extra information for List and Monitor", NULL},
+ { "monitor", 'o', 0, G_OPTION_ARG_NONE, &mount_monitor, "Monitor events", NULL},
{ NULL }
};
@@ -292,6 +294,50 @@ show_themed_icon_names (GThemedIcon *icon, int indent)
g_strfreev (names);
}
+/* don't copy-paste this code */
+static char *
+get_type_name (gpointer object)
+{
+ const char *type_name;
+ char *ret;
+
+ type_name = g_type_name (G_TYPE_FROM_INSTANCE (object));
+ if (strcmp ("GProxyDrive", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-drive-volume-monitor-name"));
+ }
+ else if (strcmp ("GProxyVolume", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-volume-volume-monitor-name"));
+ }
+ else if (strcmp ("GProxyMount", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-mount-volume-monitor-name"));
+ }
+ else if (strcmp ("GProxyShadowMount", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-shadow-mount-volume-monitor-name"));
+ }
+ else
+ {
+ ret = g_strdup (type_name);
+ }
+
+ return ret;
+}
+
static void
list_mounts (GList *mounts,
int indent,
@@ -305,6 +351,7 @@ list_mounts (GList *mounts,
GFile *root;
GIcon *icon;
char **x_content_types;
+ char *type_name;
for (c = 0, l = mounts; l != NULL; l = l->next, c++)
{
@@ -315,7 +362,7 @@ list_mounts (GList *mounts,
volume = g_mount_get_volume (mount);
if (volume != NULL)
{
- g_object_unref (volume);
+ g_object_unref (volume);
continue;
}
}
@@ -326,7 +373,11 @@ list_mounts (GList *mounts,
g_print ("%*sMount(%d): %s -> %s\n", indent, "", c, name, uri);
- if (mount_list_info)
+ type_name = get_type_name (mount);
+ g_print ("%*sType: %s\n", indent+2, "", type_name);
+ g_free (type_name);
+
+ if (extra_detail)
{
uuid = g_mount_get_uuid (mount);
if (uuid)
@@ -354,6 +405,7 @@ list_mounts (GList *mounts,
g_print ("%*scan_unmount=%d\n", indent + 2, "", g_mount_can_unmount (mount));
g_print ("%*scan_eject=%d\n", indent + 2, "", g_mount_can_eject (mount));
+ g_print ("%*sis_shadowed=%d\n", indent + 2, "", g_mount_is_shadowed (mount));
g_free (uuid);
}
@@ -378,6 +430,7 @@ list_volumes (GList *volumes,
GFile *activation_root;
char **ids;
GIcon *icon;
+ char *type_name;
for (c = 0, l = volumes; l != NULL; l = l->next, c++)
{
@@ -398,7 +451,11 @@ list_volumes (GList *volumes,
g_print ("%*sVolume(%d): %s\n", indent, "", c, name);
g_free (name);
- if (mount_list_info)
+ type_name = get_type_name (volume);
+ g_print ("%*sType: %s\n", indent+2, "", type_name);
+ g_free (type_name);
+
+ if (extra_detail)
{
ids = g_volume_enumerate_identifiers (volume);
if (ids && ids[0] != NULL)
@@ -461,6 +518,7 @@ list_drives (GList *drives,
char *name;
char **ids;
GIcon *icon;
+ char *type_name;
for (c = 0, l = drives; l != NULL; l = l->next, c++)
{
@@ -469,8 +527,12 @@ list_drives (GList *drives,
g_print ("%*sDrive(%d): %s\n", indent, "", c, name);
g_free (name);
+
+ type_name = get_type_name (drive);
+ g_print ("%*sType: %s\n", indent+2, "", type_name);
+ g_free (type_name);
- if (mount_list_info)
+ if (extra_detail)
{
ids = g_drive_enumerate_identifiers (drive);
if (ids && ids[0] != NULL)
@@ -567,6 +629,180 @@ unmount_all_with_scheme (const char *scheme)
g_object_unref (volume_monitor);
}
+static void
+monitor_print_mount (GMount *mount)
+{
+ if (extra_detail)
+ {
+ GList *l;
+ l = g_list_prepend (NULL, mount);
+ list_mounts (l, 2, FALSE);
+ g_list_free (l);
+ g_print ("\n");
+ }
+}
+
+static void
+monitor_print_volume (GVolume *volume)
+{
+ if (extra_detail)
+ {
+ GList *l;
+ l = g_list_prepend (NULL, volume);
+ list_volumes (l, 2, FALSE);
+ g_list_free (l);
+ g_print ("\n");
+ }
+}
+
+static void
+monitor_print_drive (GDrive *drive)
+{
+ if (extra_detail)
+ {
+ GList *l;
+ l = g_list_prepend (NULL, drive);
+ list_drives (l, 2);
+ g_list_free (l);
+ g_print ("\n");
+ }
+}
+
+static void
+monitor_mount_added (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount added: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_removed (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount removed: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_changed (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount changed: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_pre_unmount (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount pre-unmount: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_volume_added (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+ char *name;
+ name = g_volume_get_name (volume);
+ g_print ("Volume added: '%s'\n", name);
+ g_free (name);
+ monitor_print_volume (volume);
+}
+
+static void
+monitor_volume_removed (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+ char *name;
+ name = g_volume_get_name (volume);
+ g_print ("Volume removed: '%s'\n", name);
+ g_free (name);
+ monitor_print_volume (volume);
+}
+
+static void
+monitor_volume_changed (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+ char *name;
+ name = g_volume_get_name (volume);
+ g_print ("Volume changed: '%s'\n", name);
+ g_free (name);
+ monitor_print_volume (volume);
+}
+
+static void
+monitor_drive_connected (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive connected: '%s'\n", name);
+ g_free (name);
+ monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_disconnected (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive disconnected: '%s'\n", name);
+ g_free (name);
+ monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_changed (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive changed: '%s'\n", name);
+ g_free (name);
+ monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_eject_button (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive eject button: '%s'\n", name);
+ g_free (name);
+}
+
+static void
+monitor (void)
+{
+ GMainLoop *loop;
+ GVolumeMonitor *volume_monitor;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ volume_monitor = g_volume_monitor_get ();
+
+ g_signal_connect (volume_monitor, "mount-added", (GCallback) monitor_mount_added, NULL);
+ g_signal_connect (volume_monitor, "mount-removed", (GCallback) monitor_mount_removed, NULL);
+ g_signal_connect (volume_monitor, "mount-changed", (GCallback) monitor_mount_changed, NULL);
+ g_signal_connect (volume_monitor, "mount-pre-unmount", (GCallback) monitor_mount_pre_unmount, NULL);
+ g_signal_connect (volume_monitor, "volume-added", (GCallback) monitor_volume_added, NULL);
+ g_signal_connect (volume_monitor, "volume-removed", (GCallback) monitor_volume_removed, NULL);
+ g_signal_connect (volume_monitor, "volume-changed", (GCallback) monitor_volume_changed, NULL);
+ g_signal_connect (volume_monitor, "drive-connected", (GCallback) monitor_drive_connected, NULL);
+ g_signal_connect (volume_monitor, "drive-disconnected", (GCallback) monitor_drive_disconnected, NULL);
+ g_signal_connect (volume_monitor, "drive-changed", (GCallback) monitor_drive_changed, NULL);
+ g_signal_connect (volume_monitor, "drive-eject-button", (GCallback) monitor_drive_eject_button, NULL);
+
+ g_print ("Monitoring events. Press Ctrl+C to quit.\n");
+
+ g_main_loop_run (main_loop);
+}
+
int
main (int argc, char *argv[])
{
@@ -592,6 +828,10 @@ main (int argc, char *argv[])
{
unmount_all_with_scheme (unmount_scheme);
}
+ else if (mount_monitor)
+ {
+ monitor ();
+ }
else if (argc > 1)
{
int i;