From cec43f678f2c6cc06e13cd051d7ef68f920a1fab Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 1 Dec 2008 13:58:05 +0000 Subject: Use the new support for shadow mounts instead of 2008-12-01 Alexander Larsson * 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 --- ChangeLog | 21 ++ client/gdaemonmount.c | 148 +-------- client/gdaemonvolumemonitor.c | 8 - monitor/proxy/Makefile.am | 1 + monitor/proxy/gproxydrive.c | 3 + monitor/proxy/gproxymount.c | 3 + monitor/proxy/gproxyshadowmount.c | 441 +++++++++++++++++++++++++++ monitor/proxy/gproxyshadowmount.h | 59 ++++ monitor/proxy/gproxyvolume.c | 282 ++++++++++++++--- monitor/proxy/gproxyvolume.h | 4 +- monitor/proxy/gproxyvolumemonitor.c | 72 ++--- monitor/proxy/gproxyvolumemonitor.h | 1 + monitor/proxy/remote-volume-monitor-module.c | 2 + programs/gvfs-mount.c | 252 ++++++++++++++- 14 files changed, 1037 insertions(+), 260 deletions(-) create mode 100644 monitor/proxy/gproxyshadowmount.c create mode 100644 monitor/proxy/gproxyshadowmount.h diff --git a/ChangeLog b/ChangeLog index e1f2a3be..84e8a0e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2008-12-01 Alexander Larsson + + * 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 * configure.ac: 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 + */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#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 + */ + +#ifndef __G_PROXY_SHADOW_MOUNT_H__ +#define __G_PROXY_SHADOW_MOUNT_H__ + +#include +#include + +#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 #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; -- cgit v1.2.1