summaryrefslogtreecommitdiff
path: root/gnome-2-24/monitor/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-2-24/monitor/proxy')
-rw-r--r--gnome-2-24/monitor/proxy/Makefile.am67
-rw-r--r--gnome-2-24/monitor/proxy/gproxydrive.c578
-rw-r--r--gnome-2-24/monitor/proxy/gproxydrive.h55
-rw-r--r--gnome-2-24/monitor/proxy/gproxymount.c560
-rw-r--r--gnome-2-24/monitor/proxy/gproxymount.h56
-rw-r--r--gnome-2-24/monitor/proxy/gproxyvolume.c689
-rw-r--r--gnome-2-24/monitor/proxy/gproxyvolume.h58
-rw-r--r--gnome-2-24/monitor/proxy/gproxyvolumemonitor.c1321
-rw-r--r--gnome-2-24/monitor/proxy/gproxyvolumemonitor.h77
-rw-r--r--gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.c1155
-rw-r--r--gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.h35
-rw-r--r--gnome-2-24/monitor/proxy/remote-volume-monitor-module.c64
12 files changed, 4715 insertions, 0 deletions
diff --git a/gnome-2-24/monitor/proxy/Makefile.am b/gnome-2-24/monitor/proxy/Makefile.am
new file mode 100644
index 00000000..9f1c9743
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/Makefile.am
@@ -0,0 +1,67 @@
+
+NULL =
+
+remote_volume_monitorsdir = $(datadir)/gvfs/remote-volume-monitors
+
+module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
+
+giomodules_LTLIBRARIES = libgioremote-volume-monitor.la
+
+libgioremote_volume_monitor_la_SOURCES = \
+ remote-volume-monitor-module.c \
+ gproxydrive.c gproxydrive.h \
+ gproxyvolume.c gproxyvolume.h \
+ gproxymount.c gproxymount.h \
+ gproxyvolumemonitor.c gproxyvolumemonitor.h \
+ $(NULL)
+
+libgioremote_volume_monitor_la_CFLAGS = \
+ -DG_LOG_DOMAIN=\"GVFS-RemoteVolumeMonitor\" \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
+ -DREMOTE_VOLUME_MONITORS_DIR=\"$(remote_volume_monitorsdir)\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+libgioremote_volume_monitor_la_LDFLAGS = \
+ $(module_flags) \
+ $(NULL)
+
+libgioremote_volume_monitor_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_LIBS) \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(NULL)
+
+############################################################################
+
+noinst_LTLIBRARIES = libgvfsproxyvolumemonitordaemon-noin.la
+
+libgvfsproxyvolumemonitordaemon_noin_la_SOURCES = \
+ gvfsproxyvolumemonitordaemon.c \
+ gvfsproxyvolumemonitordaemon.h
+
+libgvfsproxyvolumemonitordaemon_noin_la_CFLAGS = \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GDU_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GVFS-RemoteVolumeMonitorDaemon\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+libgvfsproxyvolumemonitordaemon_noin_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_LIBS) \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(NULL)
+
+clean-local:
+ rm -f *~ *.loT
+
+install-data-local:
+ mkdir -p $(DESTDIR)$(remote_volume_monitorsdir)
diff --git a/gnome-2-24/monitor/proxy/gproxydrive.c b/gnome-2-24/monitor/proxy/gproxydrive.c
new file mode 100644
index 00000000..b1e9533b
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxydrive.c
@@ -0,0 +1,578 @@
+/* -*- 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 <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxydrive.h"
+#include "gproxyvolume.h"
+
+/* Protects all fields of GProxyDrive that can change */
+G_LOCK_DEFINE_STATIC(proxy_drive);
+
+struct _GProxyDrive {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ char *id;
+ char *name;
+ GIcon *icon;
+ char **volume_ids;
+ gboolean can_eject;
+ gboolean can_poll_for_media;
+ gboolean is_media_check_automatic;
+ gboolean has_media;
+ gboolean is_media_removable;
+
+ GHashTable *identifiers;
+};
+
+static void g_proxy_drive_drive_iface_init (GDriveIface *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 (GProxyDrive, g_proxy_drive, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_DRIVE,
+ g_proxy_drive_drive_iface_init))
+
+static void
+g_proxy_drive_finalize (GObject *object)
+{
+ GProxyDrive *drive;
+
+ drive = G_PROXY_DRIVE (object);
+
+ if (drive->volume_monitor != NULL)
+ g_object_unref (drive->volume_monitor);
+ g_free (drive->id);
+ g_free (drive->name);
+ if (drive->icon != NULL)
+ g_object_unref (drive->icon);
+ g_strfreev (drive->volume_ids);
+ if (drive->identifiers != NULL)
+ g_hash_table_unref (drive->identifiers);
+
+ if (G_OBJECT_CLASS (g_proxy_drive_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_drive_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_drive_class_init (GProxyDriveClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_drive_finalize;
+}
+
+static void
+g_proxy_drive_class_finalize (GProxyDriveClass *klass)
+{
+}
+
+static void
+g_proxy_drive_init (GProxyDrive *proxy_drive)
+{
+}
+
+GProxyDrive *
+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);
+ return drive;
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * boolean can-eject
+ * boolean can-poll-for-media
+ * boolean has-media
+ * boolean is-media-removable
+ * array:string volume-ids
+ * dict:string->string identifiers
+ */
+#define DRIVE_STRUCT_TYPE "(sssbbbasa{ss})"
+
+void
+g_proxy_drive_update (GProxyDrive *drive,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_volume_ids_iter;
+ const char *id;
+ const char *name;
+ const char *gicon_data;
+ dbus_bool_t can_eject;
+ dbus_bool_t can_poll_for_media;
+ dbus_bool_t has_media;
+ dbus_bool_t is_media_removable;
+ GPtrArray *volume_ids;
+ GHashTable *identifiers;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &name);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &gicon_data);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_eject);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_poll_for_media);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &has_media);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &is_media_removable);
+ dbus_message_iter_next (&iter_struct);
+
+ volume_ids = g_ptr_array_new ();
+ dbus_message_iter_recurse (&iter_struct, &iter_volume_ids_iter);
+ while (dbus_message_iter_get_arg_type (&iter_volume_ids_iter) != DBUS_TYPE_INVALID)
+ {
+ const char *volume_id;
+ dbus_message_iter_get_basic (&iter_volume_ids_iter, &volume_id);
+ dbus_message_iter_next (&iter_volume_ids_iter);
+ g_ptr_array_add (volume_ids, (gpointer) volume_id);
+ }
+ g_ptr_array_add (volume_ids, NULL);
+ dbus_message_iter_next (&iter_struct);
+
+ identifiers = _get_identifiers (&iter_struct);
+ dbus_message_iter_next (&iter_struct);
+
+ if (drive->id != NULL && strcmp (drive->id, id) != 0)
+ {
+ g_warning ("id mismatch during update of drive");
+ goto out;
+ }
+
+ if (strlen (name) == 0)
+ name = NULL;
+
+ /* out with the old */
+ g_free (drive->id);
+ g_free (drive->name);
+ if (drive->icon != NULL)
+ g_object_unref (drive->icon);
+ g_strfreev (drive->volume_ids);
+ if (drive->identifiers != NULL)
+ g_hash_table_unref (drive->identifiers);
+
+ /* in with the new */
+ drive->id = g_strdup (id);
+ drive->name = g_strdup (name);
+ drive->icon = _g_icon_new_from_serialized_data (gicon_data);
+ drive->can_eject = can_eject;
+ drive->can_poll_for_media = can_poll_for_media;
+ drive->has_media = has_media;
+ drive->is_media_removable = is_media_removable;
+ drive->identifiers = identifiers != NULL ? g_hash_table_ref (identifiers) : NULL;
+ drive->volume_ids = g_strdupv ((char **) volume_ids->pdata);
+
+ out:
+ g_ptr_array_free (volume_ids, TRUE);
+ g_hash_table_unref (identifiers);
+}
+
+static GIcon *
+g_proxy_drive_get_icon (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ GIcon *icon;
+
+ G_LOCK (proxy_drive);
+ icon = proxy_drive->icon != NULL ? g_object_ref (proxy_drive->icon) : NULL;
+ G_UNLOCK (proxy_drive);
+
+ return icon;
+}
+
+static char *
+g_proxy_drive_get_name (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ char *name;
+
+ G_LOCK (proxy_drive);
+ name = g_strdup (proxy_drive->name);
+ G_UNLOCK (proxy_drive);
+
+ return name;
+}
+
+static GList *
+g_proxy_drive_get_volumes (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ GList *l;
+
+ l = NULL;
+
+ G_LOCK (proxy_drive);
+ if (proxy_drive->volume_monitor != NULL && proxy_drive->volume_ids != NULL)
+ {
+ int n;
+
+ for (n = 0; proxy_drive->volume_ids[n] != NULL; n++)
+ {
+ GProxyVolume *volume;
+ volume = g_proxy_volume_monitor_get_volume_for_id (proxy_drive->volume_monitor, proxy_drive->volume_ids[n]);
+ if (volume != NULL)
+ l = g_list_append (l, volume);
+ }
+ }
+ G_UNLOCK (proxy_drive);
+
+ return l;
+}
+
+static gboolean
+g_proxy_drive_has_volumes (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = (proxy_drive->volume_ids != NULL && g_strv_length (proxy_drive->volume_ids) > 0);
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_is_media_removable (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->is_media_removable;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_has_media (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->has_media;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_is_media_check_automatic (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->is_media_check_automatic;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_can_eject (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->can_eject;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_can_poll_for_media (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->can_poll_for_media;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static char *
+g_proxy_drive_get_identifier (GDrive *drive,
+ const char *kind)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ char *res;
+
+ G_LOCK (proxy_drive);
+ if (proxy_drive->identifiers != NULL)
+ res = g_strdup (g_hash_table_lookup (proxy_drive->identifiers, kind));
+ else
+ res = NULL;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static void
+add_identifier_key (const char *key, const char *value, GPtrArray *res)
+{
+ g_ptr_array_add (res, g_strdup (key));
+}
+
+static char **
+g_proxy_drive_enumerate_identifiers (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ GPtrArray *res;
+
+ res = g_ptr_array_new ();
+
+ G_LOCK (proxy_drive);
+ if (proxy_drive->identifiers != NULL)
+ g_hash_table_foreach (proxy_drive->identifiers, (GHFunc) add_identifier_key, res);
+ G_UNLOCK (proxy_drive);
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ return (char **) g_ptr_array_free (res, FALSE);
+}
+
+const char *
+g_proxy_drive_get_id (GProxyDrive *drive)
+{
+ return drive->id;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+} DBusOp;
+
+static void
+eject_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ GSimpleAsyncResult *simple;
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_drive_eject (GDrive *drive,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ DBusOp *data;
+ dbus_uint32_t _flags = flags;
+
+ G_LOCK (proxy_drive);
+
+ data = g_new0 (DBusOp, 1);
+ data->object = g_object_ref (drive);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_drive->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_drive->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "DriveEject");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_drive->id),
+ DBUS_TYPE_UINT32,
+ &_flags,
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_drive);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) eject_cb,
+ data);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+}
+
+static gboolean
+g_proxy_drive_eject_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+poll_for_media_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ GSimpleAsyncResult *simple;
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_drive_poll_for_media (GDrive *drive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ DBusOp *data;
+
+ G_LOCK (proxy_drive);
+
+ data = g_new0 (DBusOp, 1);
+ data->object = g_object_ref (drive);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_drive->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_drive->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "DrivePollForMedia");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_drive->id),
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_drive);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) poll_for_media_cb,
+ data);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+}
+
+static gboolean
+g_proxy_drive_poll_for_media_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+
+static void
+g_proxy_drive_drive_iface_init (GDriveIface *iface)
+{
+ iface->get_name = g_proxy_drive_get_name;
+ iface->get_icon = g_proxy_drive_get_icon;
+ iface->has_volumes = g_proxy_drive_has_volumes;
+ iface->get_volumes = g_proxy_drive_get_volumes;
+ iface->is_media_removable = g_proxy_drive_is_media_removable;
+ iface->has_media = g_proxy_drive_has_media;
+ iface->is_media_check_automatic = g_proxy_drive_is_media_check_automatic;
+ iface->can_eject = g_proxy_drive_can_eject;
+ iface->can_poll_for_media = g_proxy_drive_can_poll_for_media;
+ iface->eject = g_proxy_drive_eject;
+ iface->eject_finish = g_proxy_drive_eject_finish;
+ iface->poll_for_media = g_proxy_drive_poll_for_media;
+ iface->poll_for_media_finish = g_proxy_drive_poll_for_media_finish;
+ iface->get_identifier = g_proxy_drive_get_identifier;
+ iface->enumerate_identifiers = g_proxy_drive_enumerate_identifiers;
+}
+
+void
+g_proxy_drive_register (GIOModule *module)
+{
+ g_proxy_drive_register_type (G_TYPE_MODULE (module));
+}
diff --git a/gnome-2-24/monitor/proxy/gproxydrive.h b/gnome-2-24/monitor/proxy/gproxydrive.h
new file mode 100644
index 00000000..7494286c
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxydrive.h
@@ -0,0 +1,55 @@
+/* -*- 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_DRIVE_H__
+#define __G_PROXY_DRIVE_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_DRIVE (g_proxy_drive_get_type ())
+#define G_PROXY_DRIVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_DRIVE, GProxyDrive))
+#define G_PROXY_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_DRIVE, GProxyDriveClass))
+#define G_IS_PROXY_DRIVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_DRIVE))
+#define G_IS_PROXY_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_DRIVE))
+
+typedef struct _GProxyDriveClass GProxyDriveClass;
+
+struct _GProxyDriveClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_drive_get_type (void) G_GNUC_CONST;
+void g_proxy_drive_register (GIOModule *module);
+GProxyDrive *g_proxy_drive_new (GProxyVolumeMonitor *volume_monitor);
+void g_proxy_drive_update (GProxyDrive *drive,
+ DBusMessageIter *iter);
+const char *g_proxy_drive_get_id (GProxyDrive *drive);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_DRIVE_H__ */
diff --git a/gnome-2-24/monitor/proxy/gproxymount.c b/gnome-2-24/monitor/proxy/gproxymount.c
new file mode 100644
index 00000000..123f5c43
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxymount.c
@@ -0,0 +1,560 @@
+/* -*- 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 "gproxymount.h"
+#include "gproxyvolume.h"
+
+/* Protects all fields of GProxyMount that can change */
+G_LOCK_DEFINE_STATIC(proxy_mount);
+
+struct _GProxyMount {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ char *id;
+ char *name;
+ char *uuid;
+ char *volume_id;
+ gboolean can_unmount;
+ char **x_content_types;
+ GFile *root;
+ GIcon *icon;
+};
+
+static void g_proxy_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 (GProxyMount, g_proxy_mount, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_MOUNT,
+ g_proxy_mount_mount_iface_init))
+
+static void
+g_proxy_mount_finalize (GObject *object)
+{
+ GProxyMount *mount;
+
+ mount = G_PROXY_MOUNT (object);
+
+ g_free (mount->id);
+ g_free (mount->name);
+ g_free (mount->uuid);
+ g_free (mount->volume_id);
+ g_strfreev (mount->x_content_types);
+ if (mount->icon != NULL)
+ g_object_unref (mount->icon);
+ if (mount->root != NULL)
+ g_object_unref (mount->root);
+
+ if (mount->volume_monitor != NULL)
+ g_object_unref (mount->volume_monitor);
+
+ if (G_OBJECT_CLASS (g_proxy_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_mount_class_init (GProxyMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_mount_finalize;
+}
+
+static void
+g_proxy_mount_class_finalize (GProxyMountClass *klass)
+{
+}
+
+static void
+g_proxy_mount_init (GProxyMount *proxy_mount)
+{
+}
+
+GProxyMount *
+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);
+ return mount;
+}
+
+gboolean
+g_proxy_mount_has_mount_path (GProxyMount *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;
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string root_uri
+ * boolean can-unmount
+ * string volume-id
+ * array:string x-content-types
+ */
+
+void
+g_proxy_mount_update (GProxyMount *mount,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_x_content_types;
+ const char *id;
+ const char *name;
+ const char *gicon_data;
+ const char *uuid;
+ const char *root_uri;
+ dbus_bool_t can_unmount;
+ const char *volume_id;
+ GPtrArray *x_content_types;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &name);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &gicon_data);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &uuid);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &root_uri);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_unmount);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &volume_id);
+ dbus_message_iter_next (&iter_struct);
+
+ x_content_types = g_ptr_array_new ();
+ dbus_message_iter_recurse (&iter_struct, &iter_x_content_types);
+ while (dbus_message_iter_get_arg_type (&iter_x_content_types) != DBUS_TYPE_INVALID)
+ {
+ const char *x_content_type;
+ dbus_message_iter_get_basic (&iter_x_content_types, &x_content_type);
+ dbus_message_iter_next (&iter_x_content_types);
+ g_ptr_array_add (x_content_types, (gpointer) x_content_type);
+ }
+ g_ptr_array_add (x_content_types, NULL);
+ dbus_message_iter_next (&iter_struct);
+
+ if (mount->id != NULL && strcmp (mount->id, id) != 0)
+ {
+ g_warning ("id mismatch during update of mount");
+ goto out;
+ }
+
+ if (strlen (name) == 0)
+ name = NULL;
+ if (strlen (uuid) == 0)
+ uuid = NULL;
+
+ /* out with the old */
+ g_free (mount->id);
+ g_free (mount->name);
+ g_free (mount->uuid);
+ g_free (mount->volume_id);
+ if (mount->icon != NULL)
+ g_object_unref (mount->icon);
+ g_strfreev (mount->x_content_types);
+ if (mount->root != NULL)
+ g_object_unref (mount->root);
+
+ /* in with the new */
+ mount->id = g_strdup (id);
+ mount->name = g_strdup (name);
+ mount->icon = _g_icon_new_from_serialized_data (gicon_data);
+ mount->uuid = g_strdup (uuid);
+ mount->root = g_file_new_for_uri (root_uri);
+ mount->can_unmount = can_unmount;
+ mount->volume_id = g_strdup (volume_id);
+ mount->x_content_types = g_strdupv ((char **) x_content_types->pdata);
+
+ out:
+ g_ptr_array_free (x_content_types, TRUE);
+}
+
+const char *
+g_proxy_mount_get_id (GProxyMount *mount)
+{
+ return mount->id;
+}
+
+static GFile *
+g_proxy_mount_get_root (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GFile *root;
+
+ G_LOCK (proxy_mount);
+ root = proxy_mount->root != NULL ? g_object_ref (proxy_mount->root) : NULL;
+ G_UNLOCK (proxy_mount);
+ return root;
+}
+
+static GIcon *
+g_proxy_mount_get_icon (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GIcon *icon;
+
+ G_LOCK (proxy_mount);
+ icon = proxy_mount->icon != NULL ? g_object_ref (proxy_mount->icon) : NULL;
+ G_UNLOCK (proxy_mount);
+ return icon;
+}
+
+static char *
+g_proxy_mount_get_uuid (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ char *uuid;
+
+ G_LOCK (proxy_mount);
+ uuid = g_strdup (proxy_mount->uuid);
+ G_UNLOCK (proxy_mount);
+ return uuid;
+}
+
+static char *
+g_proxy_mount_get_name (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ char *name;
+
+ G_LOCK (proxy_mount);
+ name = g_strdup (proxy_mount->name);
+ G_UNLOCK (proxy_mount);
+
+ return name;
+}
+
+static GDrive *
+g_proxy_mount_get_drive (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GProxyVolume *volume;
+ GDrive *drive;
+
+ G_LOCK (proxy_mount);
+ volume = NULL;
+ if (proxy_mount->volume_id != NULL && strlen (proxy_mount->volume_id) > 0)
+ volume = g_proxy_volume_monitor_get_volume_for_id (proxy_mount->volume_monitor,
+ proxy_mount->volume_id);
+ G_UNLOCK (proxy_mount);
+
+ drive = NULL;
+ if (volume != NULL)
+ {
+ drive = g_volume_get_drive (G_VOLUME (volume));
+ g_object_unref (volume);
+ }
+
+ return drive;
+}
+
+static GVolume *
+g_proxy_mount_get_volume (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GProxyVolume *volume;
+
+ G_LOCK (proxy_mount);
+ volume = NULL;
+ if (proxy_mount->volume_id != NULL && strlen (proxy_mount->volume_id) > 0)
+ volume = g_proxy_volume_monitor_get_volume_for_id (proxy_mount->volume_monitor,
+ proxy_mount->volume_id);
+ G_UNLOCK (proxy_mount);
+
+ return volume != NULL ? G_VOLUME (volume) : NULL;
+}
+
+static gboolean
+g_proxy_mount_can_unmount (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_mount);
+ res = proxy_mount->can_unmount;
+ G_UNLOCK (proxy_mount);
+
+ return res;
+}
+
+static gboolean
+g_proxy_mount_can_eject (GMount *mount)
+{
+ GDrive *drive;
+ gboolean can_eject;
+
+ can_eject = FALSE;
+ drive = g_proxy_mount_get_drive (mount);
+ if (drive != NULL)
+ {
+ can_eject = g_drive_can_eject (drive);
+ g_object_unref (drive);
+ }
+
+ return can_eject;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDrive *drive;
+
+ drive = g_proxy_mount_get_drive (mount);
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+g_proxy_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GDrive *drive;
+ gboolean res;
+
+ res = TRUE;
+
+ drive = g_proxy_mount_get_drive (mount);
+
+ if (drive != NULL)
+ {
+ res = g_drive_eject_finish (drive, result, error);
+ g_object_unref (drive);
+ }
+ return res;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+} DBusOp;
+
+static void
+unmount_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ GSimpleAsyncResult *simple;
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ DBusOp *data;
+ dbus_uint32_t _flags = flags;
+
+ G_LOCK (proxy_mount);
+
+ data = g_new0 (DBusOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_mount->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_mount->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "MountUnmount");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_mount->id),
+ DBUS_TYPE_UINT32,
+ &_flags,
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_mount);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) unmount_cb,
+ data);
+
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+}
+
+static gboolean
+g_proxy_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+g_proxy_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ /* TODO: handle force_rescan */
+ simple = g_simple_async_result_new (G_OBJECT (mount),
+ callback,
+ user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static char **
+g_proxy_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ return g_strdupv (proxy_mount->x_content_types);
+}
+
+static char **
+g_proxy_mount_guess_content_type_sync (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ /* TODO: handle force_rescan */
+ return g_strdupv (proxy_mount->x_content_types);
+}
+
+static void
+g_proxy_mount_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_proxy_mount_get_root;
+ iface->get_name = g_proxy_mount_get_name;
+ iface->get_icon = g_proxy_mount_get_icon;
+ iface->get_uuid = g_proxy_mount_get_uuid;
+ iface->get_drive = g_proxy_mount_get_drive;
+ iface->get_volume = g_proxy_mount_get_volume;
+ iface->can_unmount = g_proxy_mount_can_unmount;
+ iface->can_eject = g_proxy_mount_can_eject;
+ iface->unmount = g_proxy_mount_unmount;
+ iface->unmount_finish = g_proxy_mount_unmount_finish;
+ iface->eject = g_proxy_mount_eject;
+ iface->eject_finish = g_proxy_mount_eject_finish;
+ iface->guess_content_type = g_proxy_mount_guess_content_type;
+ iface->guess_content_type_finish = g_proxy_mount_guess_content_type_finish;
+ iface->guess_content_type_sync = g_proxy_mount_guess_content_type_sync;
+}
+
+void
+g_proxy_mount_register (GIOModule *module)
+{
+ g_proxy_mount_register_type (G_TYPE_MODULE (module));
+}
diff --git a/gnome-2-24/monitor/proxy/gproxymount.h b/gnome-2-24/monitor/proxy/gproxymount.h
new file mode 100644
index 00000000..c6356518
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxymount.h
@@ -0,0 +1,56 @@
+/* -*- 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_MOUNT_H__
+#define __G_PROXY_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_MOUNT (g_proxy_mount_get_type ())
+#define G_PROXY_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_MOUNT, GProxyMount))
+#define G_PROXY_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_MOUNT, GProxyMountClass))
+#define G_IS_PROXY_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_MOUNT))
+#define G_IS_PROXY_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_MOUNT))
+
+typedef struct _GProxyMountClass GProxyMountClass;
+
+struct _GProxyMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_mount_get_type (void) G_GNUC_CONST;
+void g_proxy_mount_register (GIOModule *module);
+GProxyMount *g_proxy_mount_new (GProxyVolumeMonitor *volume_monitor);
+void g_proxy_mount_update (GProxyMount *mount,
+ DBusMessageIter *iter);
+const char *g_proxy_mount_get_id (GProxyMount *mount);
+gboolean g_proxy_mount_has_mount_path (GProxyMount *mount, const char *mount_path);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_MOUNT_H__ */
diff --git a/gnome-2-24/monitor/proxy/gproxyvolume.c b/gnome-2-24/monitor/proxy/gproxyvolume.c
new file mode 100644
index 00000000..23730b2f
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxyvolume.c
@@ -0,0 +1,689 @@
+/* -*- 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 "gproxydrive.h"
+#include "gproxyvolume.h"
+#include "gproxymount.h"
+
+/* Protects all fields of GProxyVolume that can change */
+G_LOCK_DEFINE_STATIC(proxy_volume);
+
+struct _GProxyVolume {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ char *id;
+ char *name;
+ char *uuid;
+ char *activation_uri;
+ GIcon *icon;
+ char *drive_id;
+ char *mount_id;
+ GHashTable *identifiers;
+
+ GMount *foreign_mount;
+
+ gboolean can_mount;
+ gboolean should_automount;
+};
+
+static void g_proxy_volume_volume_iface_init (GVolumeIface *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 (GProxyVolume, g_proxy_volume, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_VOLUME,
+ g_proxy_volume_volume_iface_init))
+
+static void
+g_proxy_volume_finalize (GObject *object)
+{
+ GProxyVolume *volume;
+
+ volume = G_PROXY_VOLUME (object);
+
+ g_free (volume->id);
+ g_free (volume->name);
+ g_free (volume->uuid);
+ g_free (volume->activation_uri);
+ if (volume->icon != NULL)
+ g_object_unref (volume->icon);
+ g_free (volume->drive_id);
+ g_free (volume->mount_id);
+ if (volume->identifiers != NULL)
+ g_hash_table_unref (volume->identifiers);
+
+ if (volume->foreign_mount != NULL)
+ g_object_unref (volume->foreign_mount);
+
+ if (volume->volume_monitor != NULL)
+ 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);
+}
+
+static void
+g_proxy_volume_class_init (GProxyVolumeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_volume_finalize;
+}
+
+static void
+g_proxy_volume_class_finalize (GProxyVolumeClass *klass)
+{
+}
+
+static void
+g_proxy_volume_init (GProxyVolume *proxy_volume)
+{
+}
+
+GProxyVolume *
+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);
+ 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
+foreign_mount_unmounted (GMount *mount, gpointer user_data)
+{
+ GProxyVolume *volume = G_PROXY_VOLUME (user_data);
+ gboolean check;
+
+ G_LOCK (proxy_volume);
+ check = (volume->foreign_mount == mount);
+ G_UNLOCK (proxy_volume);
+ if (check)
+ g_proxy_volume_adopt_foreign_mount (volume, NULL);
+}
+
+void
+g_proxy_volume_adopt_foreign_mount (GProxyVolume *volume,
+ GMount *foreign_mount)
+{
+ G_LOCK (proxy_volume);
+ if (volume->foreign_mount != NULL)
+ g_object_unref (volume->foreign_mount);
+
+ if (foreign_mount != NULL)
+ {
+ volume->foreign_mount = g_object_ref (foreign_mount);
+ g_signal_connect_object (foreign_mount, "unmounted", (GCallback) foreign_mount_unmounted, volume, 0);
+ }
+ else
+ volume->foreign_mount = NULL;
+
+ g_idle_add (changed_in_idle, g_object_ref (volume));
+ G_UNLOCK (proxy_volume);
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string activation_uri
+ * boolean can-mount
+ * boolean should-automount
+ * string drive-id
+ * string mount-id
+ * dict:string->string identifiers
+ */
+
+void g_proxy_volume_update (GProxyVolume *volume,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct;
+ const char *id;
+ const char *name;
+ const char *gicon_data;
+ const char *uuid;
+ const char *activation_uri;
+ const char *drive_id;
+ const char *mount_id;
+ dbus_bool_t can_mount;
+ dbus_bool_t should_automount;
+ GHashTable *identifiers;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &name);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &gicon_data);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &uuid);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &activation_uri);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_mount);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &should_automount);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &drive_id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &mount_id);
+ dbus_message_iter_next (&iter_struct);
+
+ identifiers = _get_identifiers (&iter_struct);
+ dbus_message_iter_next (&iter_struct);
+
+ if (volume->id != NULL && strcmp (volume->id, id) != 0)
+ {
+ g_warning ("id mismatch during update of volume");
+ goto out;
+ }
+
+ if (strlen (name) == 0)
+ name = NULL;
+ if (strlen (uuid) == 0)
+ uuid = NULL;
+ if (strlen (activation_uri) == 0)
+ activation_uri = NULL;
+
+ /* out with the old */
+ g_free (volume->id);
+ g_free (volume->name);
+ g_free (volume->uuid);
+ g_free (volume->activation_uri);
+ if (volume->icon != NULL)
+ g_object_unref (volume->icon);
+ g_free (volume->drive_id);
+ g_free (volume->mount_id);
+ if (volume->identifiers != NULL)
+ g_hash_table_unref (volume->identifiers);
+
+ /* in with the new */
+ volume->id = g_strdup (id);
+ volume->name = g_strdup (name);
+ volume->uuid = g_strdup (uuid);
+ volume->activation_uri = g_strdup (activation_uri);
+ volume->icon = _g_icon_new_from_serialized_data (gicon_data);
+ volume->drive_id = g_strdup (drive_id);
+ volume->mount_id = g_strdup (mount_id);
+ volume->can_mount = can_mount;
+ volume->should_automount = should_automount;
+ volume->identifiers = identifiers != NULL ? g_hash_table_ref (identifiers) : NULL;
+
+ out:
+ g_hash_table_unref (identifiers);
+}
+
+const char *
+g_proxy_volume_get_id (GProxyVolume *volume)
+{
+ return volume->id;
+}
+
+static GIcon *
+g_proxy_volume_get_icon (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GIcon *icon;
+
+ G_LOCK (proxy_volume);
+ icon = proxy_volume->icon != NULL ? g_object_ref (proxy_volume->icon) : NULL;
+ G_UNLOCK (proxy_volume);
+ return icon;
+}
+
+static char *
+g_proxy_volume_get_name (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ char *name;
+
+ G_LOCK (proxy_volume);
+ name = g_strdup (proxy_volume->name);
+ G_UNLOCK (proxy_volume);
+ return name;
+}
+
+static char *
+g_proxy_volume_get_uuid (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ char *uuid;
+
+ G_LOCK (proxy_volume);
+ uuid = g_strdup (proxy_volume->uuid);
+ G_UNLOCK (proxy_volume);
+ return uuid;
+}
+
+static gboolean
+g_proxy_volume_can_mount (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = proxy_volume->can_mount;
+ G_UNLOCK (proxy_volume);
+ return res;
+}
+
+static gboolean
+g_proxy_volume_can_eject (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = FALSE;
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ {
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ if (drive != NULL)
+ {
+ res = g_drive_can_eject (G_DRIVE (drive));
+ g_object_unref (drive);
+ }
+ }
+ G_UNLOCK (proxy_volume);
+
+ return res;
+}
+
+static gboolean
+g_proxy_volume_should_automount (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = proxy_volume->should_automount;
+ G_UNLOCK (proxy_volume);
+
+ return res;
+}
+
+static GDrive *
+g_proxy_volume_get_drive (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+
+ G_LOCK (proxy_volume);
+ drive = NULL;
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ G_UNLOCK (proxy_volume);
+
+ return drive != NULL ? G_DRIVE (drive) : NULL;
+}
+
+static GMount *
+g_proxy_volume_get_mount (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GMount *mount;
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->foreign_mount != NULL)
+ {
+ mount = g_object_ref (proxy_volume->foreign_mount);
+ }
+ else
+ {
+ 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);
+ }
+ }
+ G_UNLOCK (proxy_volume);
+
+ return mount;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_volume_eject (GVolume *volume,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+
+ drive = NULL;
+ G_LOCK (proxy_volume);
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ {
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ }
+ G_UNLOCK (proxy_volume);
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject (G_DRIVE (drive), flags, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+g_proxy_volume_eject_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = TRUE;
+ drive = NULL;
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ G_UNLOCK (proxy_volume);
+
+ if (drive != NULL)
+ {
+ res = g_drive_eject_finish (G_DRIVE (drive), result, error);
+ g_object_unref (drive);
+ }
+
+ return res;
+}
+
+static char *
+g_proxy_volume_get_identifier (GVolume *volume,
+ const char *kind)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ char *res;
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->identifiers != NULL)
+ res = g_strdup (g_hash_table_lookup (proxy_volume->identifiers, kind));
+ else
+ res = NULL;
+ G_UNLOCK (proxy_volume);
+
+ return res;
+}
+
+static void
+add_identifier_key (const char *key, const char *value, GPtrArray *res)
+{
+ g_ptr_array_add (res, g_strdup (key));
+}
+
+static char **
+g_proxy_volume_enumerate_identifiers (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GPtrArray *res;
+
+ res = g_ptr_array_new ();
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->identifiers != NULL)
+ g_hash_table_foreach (proxy_volume->identifiers, (GHFunc) add_identifier_key, res);
+ G_UNLOCK (proxy_volume);
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ return (char **) g_ptr_array_free (res, FALSE);
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+} DBusOp;
+
+static void
+mount_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ GSimpleAsyncResult *simple;
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+typedef struct
+{
+ GProxyVolume *enclosing_volume;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} ForeignMountOp;
+
+static void
+mount_foreign_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ForeignMountOp *data = user_data;
+ data->callback (G_OBJECT (data->enclosing_volume), res, data->user_data);
+ g_object_unref (data->enclosing_volume);
+ g_free (data);
+}
+
+static void
+g_proxy_volume_mount (GVolume *volume,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->activation_uri != NULL)
+ {
+ ForeignMountOp *data;
+ GFile *root;
+
+ data = g_new0 (ForeignMountOp, 1);
+ data->enclosing_volume = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ root = g_file_new_for_uri (proxy_volume->activation_uri);
+
+ G_UNLOCK (proxy_volume);
+
+ g_file_mount_enclosing_volume (root,
+ flags,
+ mount_operation,
+ cancellable,
+ mount_foreign_callback,
+ data);
+
+ g_object_unref (root);
+ }
+ else
+ {
+ DBusOp *data;
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ dbus_uint32_t _flags = flags;
+ dbus_bool_t use_mount_operation = mount_operation != NULL;
+
+ /* TODO: support mount_operation */
+
+ data = g_new0 (DBusOp, 1);
+ data->object = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_volume->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_volume->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "VolumeMount");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_volume->id),
+ DBUS_TYPE_UINT32,
+ &_flags,
+ DBUS_TYPE_BOOLEAN,
+ &use_mount_operation,
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_volume);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) mount_cb,
+ data);
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+ }
+}
+
+static gboolean
+g_proxy_volume_mount_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+static GFile *
+g_proxy_volume_get_activation_root (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ if (proxy_volume->activation_uri == NULL)
+ return NULL;
+ else
+ return g_file_new_for_uri (proxy_volume->activation_uri);
+}
+
+static void
+g_proxy_volume_volume_iface_init (GVolumeIface *iface)
+{
+ iface->get_name = g_proxy_volume_get_name;
+ iface->get_icon = g_proxy_volume_get_icon;
+ iface->get_uuid = g_proxy_volume_get_uuid;
+ iface->get_drive = g_proxy_volume_get_drive;
+ iface->get_mount = g_proxy_volume_get_mount;
+ iface->can_mount = g_proxy_volume_can_mount;
+ iface->can_eject = g_proxy_volume_can_eject;
+ iface->should_automount = g_proxy_volume_should_automount;
+ iface->mount_fn = g_proxy_volume_mount;
+ iface->mount_finish = g_proxy_volume_mount_finish;
+ iface->eject = g_proxy_volume_eject;
+ iface->eject_finish = g_proxy_volume_eject_finish;
+ iface->get_identifier = g_proxy_volume_get_identifier;
+ iface->enumerate_identifiers = g_proxy_volume_enumerate_identifiers;
+ iface->get_activation_root = g_proxy_volume_get_activation_root;
+}
+
+void
+g_proxy_volume_register (GIOModule *module)
+{
+ g_proxy_volume_register_type (G_TYPE_MODULE (module));
+}
diff --git a/gnome-2-24/monitor/proxy/gproxyvolume.h b/gnome-2-24/monitor/proxy/gproxyvolume.h
new file mode 100644
index 00000000..5626092f
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxyvolume.h
@@ -0,0 +1,58 @@
+/* -*- 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_VOLUME_H__
+#define __G_PROXY_VOLUME_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_VOLUME (g_proxy_volume_get_type ())
+#define G_PROXY_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_VOLUME, GProxyVolume))
+#define G_PROXY_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_VOLUME, GProxyVolumeClass))
+#define G_IS_PROXY_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_VOLUME))
+#define G_IS_PROXY_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_VOLUME))
+
+typedef struct _GProxyVolumeClass GProxyVolumeClass;
+
+struct _GProxyVolumeClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_volume_get_type (void) G_GNUC_CONST;
+GProxyVolume *g_proxy_volume_new (GProxyVolumeMonitor *volume_monitor);
+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);
+
+
+G_END_DECLS
+
+#endif /* __G_PROXY_VOLUME_H__ */
diff --git a/gnome-2-24/monitor/proxy/gproxyvolumemonitor.c b/gnome-2-24/monitor/proxy/gproxyvolumemonitor.c
new file mode 100644
index 00000000..e71fcde0
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxyvolumemonitor.c
@@ -0,0 +1,1321 @@
+/* -*- 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>
+ */
+
+/*
+ * TODO: since we already call IsSupported() at module load time (in
+ * order to register the appropriate types) we really just should
+ * construct all the volume monitors. This is a good idea because
+ *
+ * - instead of calling IsSupported() we just call List()
+ * - e.g. exactly the same IPC overhead
+ * - neglible memory + cpu overhead
+ * - will need to construct them at some point
+ * - we can actually implement get_mount_for_mount_path()
+ * correctly even when no volume monitor is constructed
+ *
+ * - implement support for GMountOperation
+ * - not implemented in the HAL volume monitor and that's all
+ * that is using it right now. Will implement at some point
+ * when it's needed or someone has spare cycles.
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxymount.h"
+#include "gproxyvolume.h"
+#include "gproxydrive.h"
+
+G_LOCK_DEFINE_STATIC(proxy_vm);
+
+static DBusConnection *the_session_bus = NULL;
+static gboolean the_session_bus_is_integrated = FALSE;
+static GHashTable *the_volume_monitors = NULL;
+
+struct _GProxyVolumeMonitor {
+ GNativeVolumeMonitor parent;
+ DBusConnection *session_bus;
+
+ GHashTable *drives;
+ GHashTable *volumes;
+ GHashTable *mounts;
+};
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyVolumeMonitor,
+ g_proxy_volume_monitor,
+ G_TYPE_NATIVE_VOLUME_MONITOR,
+ G_TYPE_FLAG_ABSTRACT,
+ {})
+
+static void seed_monitor (GProxyVolumeMonitor *monitor);
+
+static DBusHandlerResult filter_function (DBusConnection *connection, DBusMessage *message, void *user_data);
+
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
+static gboolean is_supported (GProxyVolumeMonitorClass *klass);
+
+/* The is_supported API is kinda lame and doesn't pass in the class,
+ so we work around this with this hack */
+typedef gboolean (*is_supported_func) (void);
+
+static GProxyVolumeMonitorClass *is_supported_classes[10] = { NULL };
+static gboolean is_supported_0 (void) { return is_supported (is_supported_classes[0]); };
+static gboolean is_supported_1 (void) { return is_supported (is_supported_classes[1]); };
+static gboolean is_supported_2 (void) { return is_supported (is_supported_classes[2]); };
+static gboolean is_supported_3 (void) { return is_supported (is_supported_classes[3]); };
+static gboolean is_supported_4 (void) { return is_supported (is_supported_classes[4]); };
+static gboolean is_supported_5 (void) { return is_supported (is_supported_classes[5]); };
+static gboolean is_supported_6 (void) { return is_supported (is_supported_classes[6]); };
+static gboolean is_supported_7 (void) { return is_supported (is_supported_classes[7]); };
+static gboolean is_supported_8 (void) { return is_supported (is_supported_classes[8]); };
+static gboolean is_supported_9 (void) { return is_supported (is_supported_classes[9]); };
+static is_supported_func is_supported_funcs[] = {
+ is_supported_0, is_supported_1, is_supported_2, is_supported_3,
+ is_supported_4, is_supported_5, is_supported_6, is_supported_7,
+ is_supported_8, is_supported_9,
+ NULL
+};
+
+static char *
+get_match_rule (GProxyVolumeMonitor *monitor)
+{
+ return g_strdup_printf ("type='signal',"
+ "interface='org.gtk.Private.RemoteVolumeMonitor',"
+ "sender='%s'",
+ g_proxy_volume_monitor_get_dbus_name (monitor));
+}
+
+static void
+g_proxy_volume_monitor_finalize (GObject *object)
+{
+ GProxyVolumeMonitor *monitor;
+ DBusError dbus_error;
+ char *match_rule;
+ GObjectClass *parent_class;
+
+ /* since GProxyVolumeMonitor is a non-instantiatable type we're dealing with a
+ * sub-type here. So we need to look at the grandparent sub-type to get the
+ * parent class for GProxyVolumeMonitor */
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (
+ g_type_class_peek_parent (G_OBJECT_GET_CLASS (object))));
+
+ monitor = G_PROXY_VOLUME_MONITOR (object);
+
+ g_hash_table_unref (monitor->drives);
+ g_hash_table_unref (monitor->volumes);
+ g_hash_table_unref (monitor->mounts);
+
+ dbus_connection_remove_filter (monitor->session_bus, filter_function, monitor);
+ match_rule = get_match_rule (monitor);
+ dbus_error_init (&dbus_error);
+ dbus_bus_remove_match (monitor->session_bus,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ /* not really a whole lot to do on failure than whine since
+ * GObject finalization can't fail...
+ */
+ g_warning ("cannot remove match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+ g_free (match_rule);
+ dbus_connection_unref (monitor->session_bus);
+
+ if (parent_class->finalize)
+ parent_class->finalize (object);
+}
+
+static GList *
+get_mounts (GVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitor *monitor;
+ GList *l;
+ GHashTableIter hash_iter;
+ GProxyMount *mount;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+ l = NULL;
+
+ G_LOCK (proxy_vm);
+
+ g_hash_table_iter_init (&hash_iter, monitor->mounts);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount))
+ l = g_list_append (l, g_object_ref (mount));
+
+ G_UNLOCK (proxy_vm);
+
+ return l;
+}
+
+static GList *
+get_volumes (GVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitor *monitor;
+ GList *l;
+ GHashTableIter hash_iter;
+ GProxyVolume *volume;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+ l = NULL;
+
+ G_LOCK (proxy_vm);
+
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+ l = g_list_append (l, g_object_ref (volume));
+
+ G_UNLOCK (proxy_vm);
+
+ return l;
+}
+
+static GList *
+get_connected_drives (GVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitor *monitor;
+ GList *l;
+ GHashTableIter hash_iter;
+ GProxyDrive *drive;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+ l = NULL;
+
+ G_LOCK (proxy_vm);
+
+ g_hash_table_iter_init (&hash_iter, monitor->drives);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &drive))
+ l = g_list_append (l, g_object_ref (drive));
+
+ G_UNLOCK (proxy_vm);
+
+ return l;
+}
+
+static GVolume *
+get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ GProxyVolumeMonitor *monitor;
+ GHashTableIter hash_iter;
+ GVolume *found_volume;
+ GVolume *volume;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+
+ G_LOCK (proxy_vm);
+
+ found_volume = NULL;
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume) &&
+ found_volume != NULL)
+ {
+ char *_uuid;
+ _uuid = g_volume_get_uuid (volume);
+ if (_uuid != NULL)
+ {
+ if (strcmp (uuid, _uuid) == 0)
+ found_volume = g_object_ref (volume);
+ g_free (_uuid);
+ }
+ }
+
+ G_UNLOCK (proxy_vm);
+
+ return found_volume;
+}
+
+static GMount *
+get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ GProxyVolumeMonitor *monitor;
+ GHashTableIter hash_iter;
+ GMount *found_mount;
+ GMount *mount;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+
+ G_LOCK (proxy_vm);
+
+ found_mount = NULL;
+ g_hash_table_iter_init (&hash_iter, monitor->mounts);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount) &&
+ found_mount != NULL)
+ {
+ char *_uuid;
+ _uuid = g_mount_get_uuid (mount);
+ if (_uuid != NULL)
+ {
+ if (strcmp (uuid, _uuid) == 0)
+ found_mount = g_object_ref (mount);
+ g_free (_uuid);
+ }
+ }
+
+ G_UNLOCK (proxy_vm);
+
+ return found_mount;
+}
+
+static GMount *
+get_mount_for_mount_path (const char *mount_path,
+ GCancellable *cancellable)
+{
+ GMount *mount;
+ GProxyVolumeMonitor *volume_monitor;
+ GProxyVolumeMonitorClass *klass;
+ GHashTableIter vm_hash_iter;
+ GHashTableIter vol_hash_iter;
+ GProxyMount *candidate_mount;
+
+ /* This static method on GNativeVolumeMonitor is a *complete* pain
+ * in the ass to deal with; we need to rework gio so it's deprecated
+ * and thus never will get called.
+ *
+ * TODO: we don't handle the case when there's no volume monitor ever
+ * constructed. See TODO at the top of this file on how to handle that.
+ */
+
+ mount = NULL;
+ G_LOCK (proxy_vm);
+
+ /* First find the native volume monitor if one exists */
+ g_hash_table_iter_init (&vm_hash_iter, the_volume_monitors);
+ while (g_hash_table_iter_next (&vm_hash_iter, NULL, (gpointer) &volume_monitor)) {
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (G_OBJECT_GET_CLASS (volume_monitor));
+
+ if (klass->is_native) {
+ /* The see if we've got a mount */
+ g_hash_table_iter_init (&vol_hash_iter, volume_monitor->mounts);
+ while (g_hash_table_iter_next (&vol_hash_iter, NULL, (gpointer) &candidate_mount)) {
+ if (g_proxy_mount_has_mount_path (candidate_mount, mount_path))
+ {
+ mount = g_object_ref (candidate_mount);
+ goto out;
+ }
+ }
+ goto out;
+ }
+ }
+
+ out:
+ G_UNLOCK (proxy_vm);
+ return mount;
+}
+
+static void
+volume_monitor_went_away (gpointer data,
+ GObject *where_the_object_was)
+{
+ GType type = (GType) data;
+ G_LOCK (proxy_vm);
+ g_hash_table_remove (the_volume_monitors, (gpointer) type);
+ G_UNLOCK (proxy_vm);
+}
+
+static GObject *
+g_proxy_volume_monitor_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GProxyVolumeMonitor *monitor;
+ GProxyVolumeMonitorClass *klass;
+ GObjectClass *parent_class;
+ DBusError dbus_error;
+ char *match_rule;
+
+ G_LOCK (proxy_vm);
+
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (g_type_class_peek (type));
+ object = g_hash_table_lookup (the_volume_monitors, (gpointer) type);
+ if (object != NULL)
+ {
+ g_object_ref (object);
+ goto out;
+ }
+
+ /* Invoke parent constructor. */
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (g_type_class_peek (G_TYPE_PROXY_VOLUME_MONITOR));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ monitor = G_PROXY_VOLUME_MONITOR (object);
+
+ dbus_error_init (&dbus_error);
+ monitor->session_bus = dbus_connection_ref (the_session_bus);
+ monitor->drives = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ monitor->volumes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ monitor->mounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+ dbus_connection_add_filter (monitor->session_bus, filter_function, monitor, NULL);
+ match_rule = get_match_rule (monitor);
+ dbus_bus_add_match (monitor->session_bus,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ /* not really a whole lot to do on failure than whine since
+ * GObject construction can't fail...
+ */
+ g_warning ("cannot add match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+ g_free (match_rule);
+
+ seed_monitor (monitor);
+
+ g_hash_table_insert (the_volume_monitors, (gpointer) type, object);
+ g_object_weak_ref (G_OBJECT (object), volume_monitor_went_away, (gpointer) type);
+
+ out:
+ G_UNLOCK (proxy_vm);
+ return object;
+}
+
+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);
+}
+
+
+
+static DBusHandlerResult
+filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ GProxyVolumeMonitor *monitor = G_PROXY_VOLUME_MONITOR (user_data);
+ DBusMessageIter iter;
+ const char *id;
+ const char *the_dbus_name;
+ const char *member;
+ GProxyDrive *drive;
+ GProxyVolume *volume;
+ GProxyMount *mount;
+ GProxyVolumeMonitorClass *klass;
+
+ G_LOCK (proxy_vm);
+
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (G_OBJECT_GET_CLASS (monitor));
+
+ member = dbus_message_get_member (message);
+
+ if (dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveChanged") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveConnected") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveDisconnected") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveEjectButton")) {
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &the_dbus_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &id);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (the_dbus_name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (strcmp (member, "DriveChanged") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive != NULL)
+ {
+ g_proxy_drive_update (drive, &iter);
+ signal_emit_in_idle (drive, "changed", NULL);
+ signal_emit_in_idle (monitor, "drive-changed", drive);
+ }
+ }
+ else if (strcmp (member, "DriveConnected") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive == NULL)
+ {
+ drive = g_proxy_drive_new (monitor);
+ g_proxy_drive_update (drive, &iter);
+ g_hash_table_insert (monitor->drives, g_strdup (g_proxy_drive_get_id (drive)), drive);
+ signal_emit_in_idle (monitor, "drive-connected", drive);
+ }
+ }
+ else if (strcmp (member, "DriveDisconnected") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive != NULL)
+ {
+ g_object_ref (drive);
+ g_hash_table_remove (monitor->drives, id);
+ signal_emit_in_idle (drive, "disconnected", NULL);
+ signal_emit_in_idle (monitor, "drive-disconnected", drive);
+ g_object_unref (drive);
+ }
+ }
+ else if (strcmp (member, "DriveEjectButton") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive != NULL)
+ {
+ signal_emit_in_idle (drive, "eject-button", NULL);
+ signal_emit_in_idle (monitor, "drive-eject-button", drive);
+ }
+ }
+
+ } else if (dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeChanged") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeAdded") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeRemoved")) {
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &the_dbus_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &id);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (the_dbus_name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (strcmp (member, "VolumeChanged") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ {
+ g_proxy_volume_update (volume, &iter);
+ signal_emit_in_idle (volume, "changed", NULL);
+ signal_emit_in_idle (monitor, "volume-changed", volume);
+ }
+ }
+ else if (strcmp (member, "VolumeAdded") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume == NULL)
+ {
+ volume = g_proxy_volume_new (monitor);
+ g_proxy_volume_update (volume, &iter);
+ g_hash_table_insert (monitor->volumes, g_strdup (g_proxy_volume_get_id (volume)), volume);
+ signal_emit_in_idle (monitor, "volume-added", volume);
+ }
+ }
+ else if (strcmp (member, "VolumeRemoved") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ {
+ g_object_ref (volume);
+ g_hash_table_remove (monitor->volumes, id);
+ signal_emit_in_idle (volume, "removed", NULL);
+ signal_emit_in_idle (monitor, "volume-removed", volume);
+ g_object_unref (volume);
+ }
+ }
+
+ } else if (dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountChanged") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountAdded") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountPreUnmount") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountRemoved")) {
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &the_dbus_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &id);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (the_dbus_name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (strcmp (member, "MountChanged") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount != NULL)
+ {
+ g_proxy_mount_update (mount, &iter);
+ signal_emit_in_idle (mount, "changed", NULL);
+ signal_emit_in_idle (monitor, "mount-changed", mount);
+ }
+ }
+ else if (strcmp (member, "MountAdded") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount == NULL)
+ {
+ mount = g_proxy_mount_new (monitor);
+ g_proxy_mount_update (mount, &iter);
+ g_hash_table_insert (monitor->mounts, g_strdup (g_proxy_mount_get_id (mount)), mount);
+ signal_emit_in_idle (monitor, "mount-added", mount);
+ }
+ }
+ else if (strcmp (member, "MountPreUnmount") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount != NULL)
+ {
+ signal_emit_in_idle (mount, "pre-unmount", NULL);
+ signal_emit_in_idle (monitor, "mount-pre-unmount", mount);
+ }
+ }
+ else if (strcmp (member, "MountRemoved") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount != NULL)
+ {
+ g_object_ref (mount);
+ g_hash_table_remove (monitor->mounts, id);
+ signal_emit_in_idle (mount, "unmounted", NULL);
+ signal_emit_in_idle (monitor, "mount-removed", mount);
+ g_object_unref (mount);
+ }
+ }
+
+ }
+
+ not_for_us:
+ G_UNLOCK (proxy_vm);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+g_proxy_volume_monitor_init (GProxyVolumeMonitor *monitor)
+{
+ g_proxy_volume_monitor_setup_session_bus_connection (TRUE);
+}
+
+static void
+g_proxy_volume_monitor_class_finalize (GProxyVolumeMonitorClass *klass)
+{
+ g_free (klass->dbus_name);
+}
+
+typedef struct {
+ char *dbus_name;
+ gboolean is_native;
+ int is_supported_nr;
+} ProxyClassData;
+
+static ProxyClassData *
+proxy_class_data_new (const char *dbus_name, gboolean is_native)
+{
+ ProxyClassData *data;
+ static int is_supported_nr = 0;
+
+ data = g_new0 (ProxyClassData, 1);
+ data->dbus_name = g_strdup (dbus_name);
+ data->is_native = is_native;
+ data->is_supported_nr = is_supported_nr++;
+
+ g_assert (is_supported_funcs[data->is_supported_nr] != NULL);
+
+ return data;
+}
+
+static void
+g_proxy_volume_monitor_class_intern_init_pre (GProxyVolumeMonitorClass *klass, gconstpointer class_data)
+{
+ ProxyClassData *data = (ProxyClassData *) class_data;
+ klass->dbus_name = g_strdup (data->dbus_name);
+ klass->is_native = data->is_native;
+ klass->is_supported_nr = data->is_supported_nr;
+ g_proxy_volume_monitor_class_intern_init (klass);
+}
+
+static gboolean
+is_remote_monitor_supported (const char *dbus_name)
+{
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ dbus_bool_t is_supported;
+
+ message = NULL;
+ reply = NULL;
+ is_supported = FALSE;
+
+ message = dbus_message_new_method_call (dbus_name,
+ "/",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "IsSupported");
+ if (message == NULL)
+ {
+ g_warning ("Cannot allocate memory for DBusMessage");
+ goto fail;
+ }
+ dbus_error_init (&dbus_error);
+ reply = dbus_connection_send_with_reply_and_block (the_session_bus,
+ message,
+ -1,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("invoking IsSupported() failed for remote volume monitor with dbus name %s: %s: %s",
+ dbus_name,
+ dbus_error.name,
+ dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto fail;
+ }
+
+ if (!dbus_message_get_args (reply, &dbus_error,
+ DBUS_TYPE_BOOLEAN, &is_supported,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args in reply for IsSupported(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto fail;
+ }
+
+ if (!is_supported)
+ g_warning ("remote volume monitor with dbus name %s is not supported", dbus_name);
+
+ fail:
+ if (message != NULL)
+ dbus_message_unref (message);
+ if (reply != NULL)
+ dbus_message_unref (reply);
+ return is_supported;
+}
+
+static gboolean
+is_supported (GProxyVolumeMonitorClass *klass)
+{
+ gboolean res;
+
+ G_LOCK (proxy_vm);
+ res = g_proxy_volume_monitor_setup_session_bus_connection (FALSE);
+ G_UNLOCK (proxy_vm);
+
+ if (res)
+ res = is_remote_monitor_supported (klass->dbus_name);
+
+ 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)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
+ GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass);
+ int i;
+
+ gobject_class->constructor = g_proxy_volume_monitor_constructor;
+ gobject_class->finalize = g_proxy_volume_monitor_finalize;
+
+ monitor_class->get_mounts = get_mounts;
+ monitor_class->get_volumes = get_volumes;
+ 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;
+ monitor_class->is_supported = is_supported_funcs[i];
+
+ native_class->get_mount_for_mount_path = get_mount_for_mount_path;
+}
+
+/* Must be called with no locks held */
+static void
+seed_monitor (GProxyVolumeMonitor *monitor)
+{
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ DBusMessageIter iter_reply;
+ DBusMessageIter iter_array;
+
+ message = dbus_message_new_method_call (g_proxy_volume_monitor_get_dbus_name (monitor),
+ "/",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "List");
+ if (message == NULL)
+ {
+ g_warning ("Cannot allocate memory for DBusMessage");
+ goto fail;
+ }
+ dbus_error_init (&dbus_error);
+ reply = dbus_connection_send_with_reply_and_block (monitor->session_bus,
+ message,
+ -1,
+ &dbus_error);
+ dbus_message_unref (message);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("invoking List() failed for type %s: %s: %s",
+ G_OBJECT_TYPE_NAME (monitor),
+ dbus_error.name,
+ dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto fail;
+ }
+
+ dbus_message_iter_init (reply, &iter_reply);
+
+ /* TODO: verify signature */
+
+ /* drives */
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ GProxyDrive *drive;
+ const char *id;
+ drive = g_proxy_drive_new (monitor);
+ g_proxy_drive_update (drive, &iter_array);
+ id = g_proxy_drive_get_id (drive);
+ g_hash_table_insert (monitor->drives, g_strdup (id), drive);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_iter_next (&iter_reply);
+
+ /* volumes */
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ GProxyVolume *volume;
+ const char *id;
+ volume = g_proxy_volume_new (monitor);
+ g_proxy_volume_update (volume, &iter_array);
+ id = g_proxy_volume_get_id (volume);
+ g_hash_table_insert (monitor->volumes, g_strdup (id), volume);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_iter_next (&iter_reply);
+
+ /* mounts */
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ GProxyMount *mount;
+ const char *id;
+ mount = g_proxy_mount_new (monitor);
+ g_proxy_mount_update (mount, &iter_array);
+ id = g_proxy_mount_get_id (mount);
+ g_hash_table_insert (monitor->mounts, g_strdup (id), mount);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_iter_next (&iter_reply);
+
+ dbus_message_unref (reply);
+
+ fail:
+ ;
+}
+
+GProxyDrive *
+g_proxy_volume_monitor_get_drive_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id)
+{
+ GProxyDrive *drive;
+
+ G_LOCK (proxy_vm);
+ drive = g_hash_table_lookup (volume_monitor->drives, id);
+ if (drive != NULL)
+ g_object_ref (drive);
+ G_UNLOCK (proxy_vm);
+
+ return drive;
+}
+
+GProxyVolume *
+g_proxy_volume_monitor_get_volume_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id)
+{
+ GProxyVolume *volume;
+
+ G_LOCK (proxy_vm);
+ volume = g_hash_table_lookup (volume_monitor->volumes, id);
+ if (volume != NULL)
+ g_object_ref (volume);
+ G_UNLOCK (proxy_vm);
+
+ return volume;
+}
+
+GProxyMount *
+g_proxy_volume_monitor_get_mount_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id)
+{
+ GProxyMount *mount;
+
+ G_LOCK (proxy_vm);
+ mount = g_hash_table_lookup (volume_monitor->mounts, id);
+ if (mount != NULL)
+ g_object_ref (mount);
+ G_UNLOCK (proxy_vm);
+
+ return mount;
+}
+
+
+GHashTable *
+_get_identifiers (DBusMessageIter *iter)
+{
+ GHashTable *hash_table;
+ DBusMessageIter iter_array;
+
+ hash_table = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+
+ dbus_message_iter_recurse (iter, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ DBusMessageIter iter_dict_entry;
+ const char *key;
+ const char *value;
+
+ dbus_message_iter_recurse (&iter_array, &iter_dict_entry);
+ dbus_message_iter_get_basic (&iter_dict_entry, &key);
+ dbus_message_iter_next (&iter_dict_entry);
+ dbus_message_iter_get_basic (&iter_dict_entry, &value);
+
+ g_hash_table_insert (hash_table, g_strdup (key), g_strdup (value));
+
+ dbus_message_iter_next (&iter_array);
+ }
+
+ return hash_table;
+}
+
+static GIcon *
+_g_icon_new_from_tokens (char **tokens, int num_tokens)
+{
+ GIcon *icon;
+
+ icon = NULL;
+ if (strcmp (tokens[0], "GFileIcon") == 0)
+ {
+ GFile *file;
+ char *unescaped_uri;
+
+ if (num_tokens != 2)
+ goto out;
+
+ unescaped_uri = g_uri_unescape_string (tokens[1], NULL);
+ file = g_file_new_for_uri (unescaped_uri);
+ icon = g_file_icon_new (file);
+ g_object_unref (file);
+ g_free (unescaped_uri);
+ }
+ else if (strcmp (tokens[0], "GThemedIcon") == 0)
+ {
+ int n;
+
+ for (n = 1; n < num_tokens; n++)
+ {
+ char *unescaped_name;
+
+ unescaped_name = g_uri_unescape_string (tokens[n], NULL);
+ if (icon == NULL)
+ icon = g_themed_icon_new (unescaped_name);
+ else
+ g_themed_icon_append_name (G_THEMED_ICON (icon), unescaped_name);
+ g_free (unescaped_name);
+ }
+ }
+ else if (strcmp (tokens[0], "GEmblemedIcon") == 0)
+ {
+ int n, m, i;
+ GIcon *base, *e_icon;
+ GEmblem *emblem;
+ GList *emblems, *e;
+ GEmblemOrigin origin;
+ char **t = tokens;
+
+ t++;
+ n = atoi (*t);
+ t++;
+ if (t - tokens >= num_tokens)
+ goto out;
+ base = _g_icon_new_from_tokens (t, n);
+ if (base == NULL)
+ goto out;
+
+ t = t + n;
+ m = atoi (*t);
+ t++;
+ emblems = NULL;
+ for (i = 0; i < m; i++)
+ {
+ origin = atoi (*t);
+ t++;
+ n = atoi (*t);
+ t++;
+ if (t - tokens >= num_tokens)
+ goto cleanup;
+ e_icon = _g_icon_new_from_tokens (t, n);
+ t += n;
+ if (e_icon == NULL)
+ goto cleanup;
+ emblem = g_emblem_new_with_origin (e_icon, origin);
+ emblems = g_list_append (emblems, emblem);
+ }
+ icon = g_emblemed_icon_new (base, (GEmblem*)emblems->data);
+ for (e = emblems->next; e; e = e->next)
+ g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (icon), (GEmblem*)e->data);
+
+ cleanup:
+ g_object_unref (base);
+ g_list_foreach (emblems, (GFunc)g_object_unref, NULL);
+ g_list_free (emblems);
+ }
+
+ out:
+ return icon;
+}
+
+GIcon *
+_g_icon_new_from_serialized_data (const char *gicon_data)
+{
+ char **tokens;
+ GIcon *icon;
+ gint num_tokens;
+
+ g_return_val_if_fail (gicon_data != NULL, NULL);
+
+ icon = NULL;
+
+ tokens = g_strsplit (gicon_data, " ", 0);
+
+ if (g_strv_length (tokens) >= 3)
+ {
+ num_tokens = atoi (tokens[0]);
+ icon = _g_icon_new_from_tokens (tokens + 1, num_tokens);
+ }
+
+ if (icon == NULL)
+ g_warning ("malformed GIcon data \"%s\"", gicon_data);
+
+ g_strfreev (tokens);
+ return icon;
+}
+
+DBusConnection *
+g_proxy_volume_monitor_get_dbus_connection (GProxyVolumeMonitor *volume_monitor)
+{
+ return dbus_connection_ref (volume_monitor->session_bus);
+}
+
+const char *
+g_proxy_volume_monitor_get_dbus_name (GProxyVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitorClass *klass = G_PROXY_VOLUME_MONITOR_CLASS (G_OBJECT_GET_CLASS (volume_monitor));
+ return klass->dbus_name;
+}
+
+static void
+register_volume_monitor (GTypeModule *type_module,
+ const char *type_name,
+ const char *dbus_name,
+ gboolean is_native,
+ int priority)
+{
+ GType type;
+ const GTypeInfo type_info = {
+ sizeof (GProxyVolumeMonitorClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) g_proxy_volume_monitor_class_intern_init_pre,
+ (GClassFinalizeFunc) g_proxy_volume_monitor_class_finalize,
+ (gconstpointer) proxy_class_data_new (dbus_name, is_native), /* class_data (leaked!) */
+ sizeof (GProxyVolumeMonitor),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) g_proxy_volume_monitor_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_module_register_type (type_module,
+ G_TYPE_PROXY_VOLUME_MONITOR,
+ type_name,
+ &type_info,
+ 0 /* type_flags */);
+
+ g_io_extension_point_implement (is_native ? G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME :
+ G_VOLUME_MONITOR_EXTENSION_POINT_NAME,
+ type,
+ type_name,
+ priority);
+}
+
+/* Call with proxy_vm lock held */
+gboolean
+g_proxy_volume_monitor_setup_session_bus_connection (gboolean need_integration)
+{
+ gboolean ret;
+ DBusError dbus_error;
+
+ ret = FALSE;
+
+ if (the_session_bus != NULL)
+ goto has_bus_already;
+
+ /* This is so that system daemons can use gio
+ * without spawning private dbus instances.
+ * See bug 526454.
+ */
+ if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
+ goto out;
+
+ dbus_error_init (&dbus_error);
+ the_session_bus = dbus_bus_get_private (DBUS_BUS_SESSION, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("cannot connect to the session bus: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ the_volume_monitors = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ has_bus_already:
+
+ if (need_integration && !the_session_bus_is_integrated)
+ {
+ _g_dbus_connection_integrate_with_main (the_session_bus);
+ the_session_bus_is_integrated = TRUE;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+void
+g_proxy_volume_monitor_teardown_session_bus_connection (void)
+{
+ G_LOCK (proxy_vm);
+ if (the_session_bus != NULL)
+ {
+ if (the_session_bus_is_integrated)
+ _g_dbus_connection_remove_from_main (the_session_bus);
+ the_session_bus_is_integrated = FALSE;
+ dbus_connection_close (the_session_bus);
+ the_session_bus = NULL;
+
+ g_hash_table_unref (the_volume_monitors);
+ the_volume_monitors = NULL;
+ }
+ G_UNLOCK (proxy_vm);
+}
+
+void
+g_proxy_volume_monitor_register (GIOModule *module)
+{
+ GDir *dir;
+ GError *error;
+
+ /* first register the abstract base type... */
+ g_proxy_volume_monitor_register_type (G_TYPE_MODULE (module));
+
+ /* ... then register instantiable types for each remote volume
+ * monitor - each remote volume monitor is defined in a key-value
+ * file in $(datadir)/gvfs/remote-volume-monitors that must have
+ * the suffix .monitor. Each file specifies
+ *
+ * - the name of the volume monitor
+ * - the name of the D-Bus service
+ * - whether the volume monitor is native
+ * - and if so the priority
+ */
+
+ error = NULL;
+ dir = g_dir_open (REMOTE_VOLUME_MONITORS_DIR, 0, &error);
+ if (dir == NULL)
+ {
+ g_warning ("cannot open directory " REMOTE_VOLUME_MONITORS_DIR ": %s", error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ const char *name;
+
+ while ((name = g_dir_read_name (dir)) != NULL)
+ {
+ GKeyFile *key_file;
+ char *type_name;
+ char *path;
+ char *dbus_name;
+ gboolean is_native;
+ int native_priority;
+
+ type_name = NULL;
+ key_file = NULL;
+ dbus_name = NULL;
+ path = NULL;
+
+ if (!g_str_has_suffix (name, ".monitor"))
+ goto cont;
+
+ path = g_build_filename (REMOTE_VOLUME_MONITORS_DIR, name, NULL);
+
+ key_file = g_key_file_new ();
+ error = NULL;
+ if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error))
+ {
+ g_warning ("error loading key-value file %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ type_name = g_key_file_get_string (key_file, "RemoteVolumeMonitor", "Name", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting Name key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ dbus_name = g_key_file_get_string (key_file, "RemoteVolumeMonitor", "DBusName", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting DBusName key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ is_native = g_key_file_get_boolean (key_file, "RemoteVolumeMonitor", "IsNative", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting IsNative key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ if (is_native)
+ {
+ native_priority = g_key_file_get_integer (key_file, "RemoteVolumeMonitor", "NativePriority", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting NativePriority key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+ }
+ else
+ {
+ native_priority = 0;
+ }
+
+ register_volume_monitor (G_TYPE_MODULE (module),
+ type_name,
+ dbus_name,
+ is_native,
+ native_priority);
+
+ cont:
+
+ g_free (type_name);
+ g_free (dbus_name);
+ g_free (path);
+ if (key_file != NULL)
+ g_key_file_free (key_file);
+ }
+ g_dir_close (dir);
+ }
+}
diff --git a/gnome-2-24/monitor/proxy/gproxyvolumemonitor.h b/gnome-2-24/monitor/proxy/gproxyvolumemonitor.h
new file mode 100644
index 00000000..4768ba8f
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gproxyvolumemonitor.h
@@ -0,0 +1,77 @@
+/* -*- 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_VOLUME_MONITOR_H__
+#define __G_PROXY_VOLUME_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_VOLUME_MONITOR (g_proxy_volume_monitor_get_type ())
+#define G_PROXY_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_VOLUME_MONITOR, GProxyVolumeMonitor))
+#define G_PROXY_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_VOLUME_MONITOR, GProxyVolumeMonitorClass))
+#define G_IS_PROXY_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_VOLUME_MONITOR))
+#define G_IS_PROXY_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_VOLUME_MONITOR))
+
+typedef struct _GProxyVolumeMonitor GProxyVolumeMonitor;
+typedef struct _GProxyVolumeMonitorClass GProxyVolumeMonitorClass;
+
+/* Forward definitions */
+typedef struct _GProxyDrive GProxyDrive;
+typedef struct _GProxyVolume GProxyVolume;
+typedef struct _GProxyMount GProxyMount;
+
+struct _GProxyVolumeMonitorClass {
+ GNativeVolumeMonitorClass parent_class;
+ char *dbus_name;
+ gboolean is_native;
+ int is_supported_nr;
+};
+
+GType g_proxy_volume_monitor_get_type (void) G_GNUC_CONST;
+
+void g_proxy_volume_monitor_register (GIOModule *module);
+GProxyDrive *g_proxy_volume_monitor_get_drive_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id);
+GProxyVolume *g_proxy_volume_monitor_get_volume_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id);
+GProxyMount *g_proxy_volume_monitor_get_mount_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id);
+DBusConnection *g_proxy_volume_monitor_get_dbus_connection (GProxyVolumeMonitor *volume_monitor);
+const char *g_proxy_volume_monitor_get_dbus_name (GProxyVolumeMonitor *volume_monitor);
+
+gboolean g_proxy_volume_monitor_setup_session_bus_connection (gboolean need_integration);
+void g_proxy_volume_monitor_teardown_session_bus_connection (void);
+
+
+GHashTable *_get_identifiers (DBusMessageIter *iter);
+
+GIcon *_g_icon_new_from_serialized_data (const char *gicon_data);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_VOLUME_MONITOR_H__ */
diff --git a/gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.c b/gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.c
new file mode 100644
index 00000000..3ee5bbf8
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.c
@@ -0,0 +1,1155 @@
+/* -*- 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 <locale.h>
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+
+#include "gdbusutils.h"
+#include "gvfsproxyvolumemonitordaemon.h"
+
+static GVolumeMonitor *monitor = NULL;
+static DBusConnection *connection = NULL;
+static GType the_volume_monitor_type;
+static const char *the_dbus_name = NULL;
+
+static void monitor_try_create (void);
+
+static char *
+_g_icon_serialize (GIcon *icon)
+{
+ char *ret;
+
+ g_return_val_if_fail (icon != NULL, NULL);
+ g_return_val_if_fail (G_IS_ICON (icon), NULL);
+
+ /* We encode icons as a series of whitespace-separated tokens.
+ * The first token is the type of the icon. To help decoding,
+ * the number of tokens is prepended as the first token (not
+ * included in the count).
+ */
+ if (G_IS_FILE_ICON (icon))
+ {
+ GFileIcon *file_icon = G_FILE_ICON (icon);
+ GFile *file;
+ char *uri;
+ char *escaped_uri;
+
+ file = g_file_icon_get_file (file_icon);
+ uri = g_file_get_uri (file);
+ escaped_uri = g_uri_escape_string (uri, NULL, TRUE);
+
+ ret = g_strdup_printf ("2 GFileIcon %s", escaped_uri);
+
+ g_free (uri);
+ g_free (escaped_uri);
+ }
+ else if (G_IS_THEMED_ICON (icon))
+ {
+ GThemedIcon *themed_icon = G_THEMED_ICON (icon);
+ char *escaped_name;
+ char **names;
+ GString *s;
+
+ g_object_get (themed_icon,
+ "names", &names,
+ NULL);
+
+ s = g_string_new (0);
+ g_string_append_printf (s, "%d GThemedIcon", g_strv_length (names) + 1);
+
+ if (names != NULL)
+ {
+ int n;
+ for (n = 0; names[n] != NULL; n++)
+ {
+ escaped_name = g_uri_escape_string (names[n], NULL, TRUE);
+ g_string_append_c (s, ' ');
+ g_string_append (s, escaped_name);
+ g_free (escaped_name);
+ }
+ }
+
+ ret = g_string_free (s, FALSE);
+
+ g_strfreev (names);
+ }
+ else if (G_IS_EMBLEMED_ICON (icon))
+ {
+ char *base, *s;
+ GList *emblems, *e;
+ int n;
+ GString *str;
+
+ /* GEmblemedIcons are encoded as
+ *
+ * <num_tokens> GEmblemedIcon <num_emblems> [<origin> <encoded_icon> ]*
+ */
+ str = g_string_new ("");
+ base = _g_icon_serialize (g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon)));
+ emblems = g_emblemed_icon_get_emblems (G_EMBLEMED_ICON (icon));
+ g_string_append_printf (str, "GEmblemedIcon %s %d", base, g_list_length (emblems));
+ n = atoi (base) + 2;
+ g_free (base);
+ for (e = emblems; e; e = e->next)
+ {
+ s = _g_icon_serialize (g_emblem_get_icon (G_EMBLEM (e->data)));
+ g_string_append_printf (str, " %d %s", g_emblem_get_origin (G_EMBLEM (e->data)), s);
+ n += atoi (s) + 2;
+ g_free (s);
+ }
+
+ s = g_string_free (str, FALSE);
+ ret = g_strdup_printf ("%d %s", n + 1, s);
+ g_free (s);
+ }
+ else
+ {
+ ret = NULL;
+ g_warning ("unknown icon type; please add support");
+ }
+
+ return ret;
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * boolean can-eject
+ * boolean can-poll-for-media
+ * boolean has-media
+ * boolean is-media-removable
+ * array:string volume-ids
+ * dict:string->string identifiers
+ */
+#define DRIVE_STRUCT_TYPE "(sssbbbbasa{ss})"
+
+static void
+append_drive (GDrive *drive, DBusMessageIter *iter_array)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_volume_array;
+ DBusMessageIter iter_identifiers;
+ char *id;
+ char *name;
+ GIcon *icon;
+ char *icon_data;
+ gboolean can_eject;
+ gboolean can_poll_for_media;
+ gboolean has_media;
+ gboolean is_media_removable;
+ GList *volumes, *l;
+ char **identifiers;
+ int n;
+
+ dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+
+ id = g_strdup_printf ("%p", drive);
+ name = g_drive_get_name (drive);
+ icon = g_drive_get_icon (drive);
+ icon_data = _g_icon_serialize (icon);
+ can_eject = g_drive_can_eject (drive);
+ can_poll_for_media = g_drive_can_poll_for_media (drive);
+ has_media = g_drive_has_media (drive);
+ is_media_removable = g_drive_is_media_removable (drive);
+ volumes = g_drive_get_volumes (drive);
+ identifiers = g_drive_enumerate_identifiers (drive);
+
+ if (name == NULL)
+ name = g_strdup ("");
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &icon_data);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_eject);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_poll_for_media);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &has_media);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &is_media_removable);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_volume_array);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ GVolume *volume = G_VOLUME (l->data);
+ char *volume_id;
+ volume_id = g_strdup_printf ("%p", volume);
+ dbus_message_iter_append_basic (&iter_volume_array, DBUS_TYPE_STRING, &volume_id);
+ g_free (volume_id);
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_volume_array);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}", &iter_identifiers);
+ for (n = 0; identifiers[n] != NULL; n++)
+ {
+ DBusMessageIter iter_dict_entry;
+ char *id_value;
+ id_value = g_drive_get_identifier (drive, identifiers[n]);
+ dbus_message_iter_open_container (&iter_identifiers,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &iter_dict_entry);
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &(identifiers[n]));
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &id_value);
+ dbus_message_iter_close_container (&iter_identifiers, &iter_dict_entry);
+ g_free (id_value);
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_identifiers);
+
+ g_strfreev (identifiers);
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ g_free (icon_data);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (id);
+
+ dbus_message_iter_close_container (iter_array, &iter_struct);
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string activation_uri
+ * boolean can-mount
+ * boolean should-automount
+ * string drive-id
+ * string mount-id
+ * dict:string->string identifiers
+ */
+#define VOLUME_STRUCT_TYPE "(sssssbbssa{ss})"
+
+static void
+append_volume (GVolume *volume, DBusMessageIter *iter_array)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_identifiers;
+ char *id;
+ char *name;
+ GIcon *icon;
+ char *icon_data;
+ char *uuid;
+ GFile *activation_root;
+ char *activation_uri;
+ gboolean can_mount;
+ gboolean should_automount;
+ GDrive *drive;
+ char *drive_id;
+ GMount *mount;
+ char *mount_id;
+ char **identifiers;
+ int n;
+
+ dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+
+ id = g_strdup_printf ("%p", volume);
+ name = g_volume_get_name (volume);
+ icon = g_volume_get_icon (volume);
+ icon_data = _g_icon_serialize (icon);
+ uuid = g_volume_get_uuid (volume);
+ activation_root = g_volume_get_activation_root (volume);
+ if (activation_root == NULL)
+ activation_uri = g_strdup ("");
+ else
+ activation_uri = g_file_get_uri (activation_root);
+ can_mount = g_volume_can_mount (volume);
+ should_automount = g_volume_should_automount (volume);
+ drive = g_volume_get_drive (volume);
+ if (drive == NULL)
+ drive_id = g_strdup ("");
+ else
+ drive_id = g_strdup_printf ("%p", drive);
+ mount = g_volume_get_mount (volume);
+ if (mount == NULL)
+ mount_id = g_strdup ("");
+ else
+ mount_id = g_strdup_printf ("%p", mount);
+ identifiers = g_volume_enumerate_identifiers (volume);
+
+ if (name == NULL)
+ name = g_strdup ("");
+ if (uuid == NULL)
+ uuid = g_strdup ("");
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &icon_data);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &uuid);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &activation_uri);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_mount);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &should_automount);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &drive_id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &mount_id);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}", &iter_identifiers);
+ for (n = 0; identifiers[n] != NULL; n++)
+ {
+ DBusMessageIter iter_dict_entry;
+ char *id_value;
+ id_value = g_volume_get_identifier (volume, identifiers[n]);
+ dbus_message_iter_open_container (&iter_identifiers,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &iter_dict_entry);
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &(identifiers[n]));
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &id_value);
+ dbus_message_iter_close_container (&iter_identifiers, &iter_dict_entry);
+ g_free (id_value);
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_identifiers);
+
+ g_strfreev (identifiers);
+ g_free (mount_id);
+ if (mount != NULL)
+ g_object_unref (mount);
+ g_free (drive_id);
+ if (drive != NULL)
+ g_object_unref (drive);
+ g_free (uuid);
+ if (activation_root != NULL)
+ g_object_unref (activation_root);
+ g_free (activation_uri);
+ g_free (icon_data);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (id);
+
+ dbus_message_iter_close_container (iter_array, &iter_struct);
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string root_uri
+ * boolean can-unmount
+ * string volume-id
+ * array:string x-content-types
+ */
+#define MOUNT_STRUCT_TYPE "(sssssbsas)"
+
+static void
+append_mount (GMount *mount, DBusMessageIter *iter_array)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_x_content_types_array;
+ char *id;
+ char *name;
+ GIcon *icon;
+ char *icon_data;
+ char *uuid;
+ GFile *root;
+ char *root_uri;
+ gboolean can_unmount;
+ GVolume *volume;
+ char *volume_id;
+ char **x_content_types;
+ int n;
+
+ dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+
+ id = g_strdup_printf ("%p", mount);
+ name = g_mount_get_name (mount);
+ icon = g_mount_get_icon (mount);
+ icon_data = _g_icon_serialize (icon);
+ uuid = g_mount_get_uuid (mount);
+ root = g_mount_get_root (mount);
+ root_uri = g_file_get_uri (root);
+ can_unmount = g_mount_can_unmount (mount);
+ volume = g_mount_get_volume (mount);
+ if (volume == NULL)
+ volume_id = g_strdup ("");
+ else
+ volume_id = g_strdup_printf ("%p", volume);
+
+ if (name == NULL)
+ name = g_strdup ("");
+ if (uuid == NULL)
+ uuid = g_strdup ("");
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &icon_data);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &uuid);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &root_uri);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_unmount);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &volume_id);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_x_content_types_array);
+ x_content_types = (char **) g_object_get_data (G_OBJECT (mount), "x-content-types");
+ if (x_content_types != NULL)
+ {
+ for (n = 0; x_content_types[n] != NULL; n++)
+ dbus_message_iter_append_basic (&iter_x_content_types_array, DBUS_TYPE_STRING, &(x_content_types[n]));
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_x_content_types_array);
+
+ g_free (volume_id);
+ if (volume != NULL)
+ g_object_unref (volume);
+ g_free (root_uri);
+ g_object_unref (root);
+ g_free (uuid);
+ g_free (icon_data);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (id);
+
+ dbus_message_iter_close_container (iter_array, &iter_struct);
+}
+
+static DBusHandlerResult
+handle_list (DBusConnection *connection, DBusMessage *message)
+{
+ GList *drives;
+ GList *volumes;
+ GList *mounts;
+ DBusMessageIter iter;
+ DBusMessageIter iter_array;
+ DBusMessage *reply;
+
+ drives = g_volume_monitor_get_connected_drives (monitor);
+ volumes = g_volume_monitor_get_volumes (monitor);
+ mounts = g_volume_monitor_get_mounts (monitor);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_message_iter_init_append (reply, &iter);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DRIVE_STRUCT_TYPE, &iter_array);
+ g_list_foreach (drives, (GFunc) append_drive, &iter_array);
+ dbus_message_iter_close_container (&iter, &iter_array);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, VOLUME_STRUCT_TYPE, &iter_array);
+ g_list_foreach (volumes, (GFunc) append_volume, &iter_array);
+ dbus_message_iter_close_container (&iter, &iter_array);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, MOUNT_STRUCT_TYPE, &iter_array);
+ g_list_foreach (mounts, (GFunc) append_mount, &iter_array);
+ dbus_message_iter_close_container (&iter, &iter_array);
+
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+mount_unmount_cb (GMount *mount, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ error = NULL;
+ if (!g_mount_unmount_finish (mount, result, &error))
+ {
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_mount_unmount (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ dbus_uint32_t unmount_flags;
+ DBusError dbus_error;
+ GList *mounts, *l;
+ GMount *mount;
+ DBusHandlerResult ret;
+
+ mounts = NULL;
+ unmount_flags = 0;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_UINT32 &unmount_flags,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for MountUnmount(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ mount = NULL;
+ mounts = g_volume_monitor_get_mounts (monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ char *mount_id;
+
+ mount = G_MOUNT (l->data);
+ mount_id = g_strdup_printf ("%p", mount);
+ if (strcmp (mount_id, id) == 0)
+ break;
+
+ g_free (mount_id);
+ }
+ if (l == NULL)
+ mount = NULL;
+
+ if (mount == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given mount was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ g_mount_unmount (mount,
+ unmount_flags,
+ NULL,
+ (GAsyncReadyCallback) mount_unmount_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (mounts != NULL)
+ {
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+volume_mount_cb (GVolume *volume, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ error = NULL;
+ if (!g_volume_mount_finish (volume, result, &error))
+ {
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_volume_mount (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ dbus_uint32_t mount_flags;
+ dbus_bool_t use_mount_operation;
+ DBusError dbus_error;
+ GList *volumes, *l;
+ GVolume *volume;
+ DBusHandlerResult ret;
+ GMountOperation *mount_operation;
+
+ volume = NULL;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_UINT32, &mount_flags,
+ DBUS_TYPE_BOOLEAN, &use_mount_operation,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for VolumeMount(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ volume = NULL;
+ volumes = g_volume_monitor_get_volumes (monitor);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ char *volume_id;
+
+ volume = G_VOLUME (l->data);
+ volume_id = g_strdup_printf ("%p", volume);
+ if (strcmp (volume_id, id) == 0)
+ break;
+
+ g_free (volume_id);
+ }
+ if (l == NULL)
+ volume = NULL;
+
+ if (volume == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given volume was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ mount_operation = NULL;
+ if (use_mount_operation)
+ mount_operation = g_mount_operation_new ();
+
+ g_volume_mount (volume,
+ mount_flags,
+ mount_operation,
+ NULL,
+ (GAsyncReadyCallback) volume_mount_cb,
+ dbus_message_ref (message));
+
+ if (mount_operation != NULL)
+ g_object_unref (mount_operation);
+
+ out:
+ if (volumes != NULL)
+ {
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+drive_eject_cb (GDrive *drive, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ error = NULL;
+ if (!g_drive_eject_finish (drive, result, &error))
+ {
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_drive_eject (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ dbus_uint32_t unmount_flags;
+ DBusError dbus_error;
+ GList *drives, *l;
+ GDrive *drive;
+ DBusHandlerResult ret;
+
+ drive = NULL;
+ unmount_flags = 0;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_UINT32 &unmount_flags,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for DriveEject(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ drive = NULL;
+ drives = g_volume_monitor_get_connected_drives (monitor);
+ for (l = drives; l != NULL; l = l->next)
+ {
+ char *drive_id;
+
+ drive = G_DRIVE (l->data);
+ drive_id = g_strdup_printf ("%p", drive);
+ if (strcmp (drive_id, id) == 0)
+ break;
+
+ g_free (drive_id);
+ }
+ if (l == NULL)
+ drive = NULL;
+
+ if (drive == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given drive was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ g_drive_eject (drive,
+ unmount_flags,
+ NULL,
+ (GAsyncReadyCallback) drive_eject_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (drives != NULL)
+ {
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+drive_poll_for_media_cb (GDrive *drive, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (drive, result, &error))
+ {
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_drive_poll_for_media (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ DBusError dbus_error;
+ GList *drives, *l;
+ GDrive *drive;
+ DBusHandlerResult ret;
+
+ drive = NULL;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for DrivePollForMedia(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ drive = NULL;
+ drives = g_volume_monitor_get_connected_drives (monitor);
+ for (l = drives; l != NULL; l = l->next)
+ {
+ char *drive_id;
+
+ drive = G_DRIVE (l->data);
+ drive_id = g_strdup_printf ("%p", drive);
+ if (strcmp (drive_id, id) == 0)
+ break;
+
+ g_free (drive_id);
+ }
+ if (l == NULL)
+ drive = NULL;
+
+ if (drive == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given drive was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ g_drive_poll_for_media (drive,
+ NULL,
+ (GAsyncReadyCallback) drive_poll_for_media_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (drives != NULL)
+ {
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static DBusHandlerResult
+handle_is_supported (DBusConnection *connection, DBusMessage *message)
+{
+ dbus_bool_t is_supported;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+
+ /* if monitor wasn't created on startup; try again */
+ if (monitor == NULL)
+ monitor_try_create ();
+
+ is_supported = (monitor != NULL);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_message_iter_init_append (reply, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &is_supported);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static DBusHandlerResult
+filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ DBusHandlerResult ret;
+
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "IsSupported") &&
+ strcmp (dbus_message_get_path (message), "/") == 0)
+ {
+ ret = handle_is_supported (connection, message);
+ }
+ else
+ {
+ if (monitor != NULL)
+ {
+ if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "List") &&
+ strcmp (dbus_message_get_path (message), "/") == 0)
+ ret = handle_list (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "MountUnmount") &&
+ strcmp (dbus_message_get_path (message), "/") == 0)
+ ret = handle_mount_unmount (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeMount") &&
+ strcmp (dbus_message_get_path (message), "/") == 0)
+ ret = handle_volume_mount (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveEject") &&
+ strcmp (dbus_message_get_path (message), "/") == 0)
+ ret = handle_drive_eject (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "DrivePollForMedia") &&
+ strcmp (dbus_message_get_path (message), "/") == 0)
+ ret = handle_drive_poll_for_media (connection, message);
+ }
+ }
+
+ return ret;
+}
+
+typedef void (*AppendFunc) (void *object, DBusMessageIter *iter);
+
+static void
+emit_signal (DBusConnection *connection, const char *signal_name, void *object, AppendFunc func)
+{
+ char *id;
+ DBusMessage *message;
+ DBusMessageIter iter;
+
+ id = g_strdup_printf ("%p", object);
+
+ message = dbus_message_new_signal ("/", "org.gtk.Private.RemoteVolumeMonitor", signal_name);
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &the_dbus_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id);
+
+ func (object, &iter);
+
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+
+
+ g_free (id);
+}
+
+static void
+drive_changed (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ emit_signal (connection, "DriveChanged", drive, (AppendFunc) append_drive);
+}
+
+static void
+drive_connected (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ emit_signal (connection, "DriveConnected", drive, (AppendFunc) append_drive);
+}
+
+static void
+drive_disconnected (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ emit_signal (connection, "DriveDisconnected", drive, (AppendFunc) append_drive);
+}
+
+static void
+drive_eject_button (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ g_warning ("drive eject button!");
+ emit_signal (connection, "DriveEjectButton", drive, (AppendFunc) append_drive);
+}
+
+static void
+volume_changed (GVolumeMonitor *monitor, GVolume *volume, DBusConnection *connection)
+{
+ emit_signal (connection, "VolumeChanged", volume, (AppendFunc) append_volume);
+}
+
+static void
+volume_added (GVolumeMonitor *monitor, GVolume *volume, DBusConnection *connection)
+{
+ emit_signal (connection, "VolumeAdded", volume, (AppendFunc) append_volume);
+}
+
+static void
+volume_removed (GVolumeMonitor *monitor, GVolume *volume, DBusConnection *connection)
+{
+ emit_signal (connection, "VolumeRemoved", volume, (AppendFunc) append_volume);
+}
+
+static void
+mount_changed (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ emit_signal (connection, "MountChanged", mount, (AppendFunc) append_mount);
+}
+
+static void
+mount_sniff_x_content_type (GMount *mount)
+{
+ char **x_content_types;
+ x_content_types = g_mount_guess_content_type_sync (mount, TRUE, NULL, NULL);
+ g_object_set_data_full (G_OBJECT (mount), "x-content-types", x_content_types, (GDestroyNotify) g_strfreev);
+}
+
+static void
+mount_added (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ mount_sniff_x_content_type (mount);
+ emit_signal (connection, "MountAdded", mount, (AppendFunc) append_mount);
+}
+
+static void
+mount_pre_unmount (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ emit_signal (connection, "MountPreUnmount", mount, (AppendFunc) append_mount);
+}
+
+static void
+mount_removed (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ emit_signal (connection, "MountRemoved", mount, (AppendFunc) append_mount);
+}
+
+void
+g_vfs_proxy_volume_monitor_daemon_init (void)
+{
+ /* avoid loading the gio proxy module which will spawn ourselves
+ *
+ * see remote-volume-monitor-module.c
+ */
+ g_setenv ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE", "1", TRUE);
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ dbus_threads_init_default ();
+ g_thread_init (NULL);
+ g_type_init ();
+}
+
+
+static void
+monitor_try_create (void)
+{
+ GVolumeMonitorClass *klass;
+ GList *mounts;
+ GList *l;
+
+ monitor = NULL;
+ klass = G_VOLUME_MONITOR_CLASS (g_type_class_ref (the_volume_monitor_type));
+ if (klass == NULL)
+ {
+ g_warning ("Can't get class for type");
+ goto fail;
+ }
+
+ if (klass->is_supported != NULL)
+ {
+ if (! (klass->is_supported ()))
+ {
+ g_warning ("monitor says it's not supported");
+ goto fail;
+ }
+ }
+
+ monitor = G_VOLUME_MONITOR (g_object_new (the_volume_monitor_type, NULL));
+ if (monitor == NULL)
+ {
+ g_warning ("Cannot instantiate volume monitor");
+ goto fail;
+ }
+
+ mounts = g_volume_monitor_get_mounts (monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ mount_sniff_x_content_type (G_MOUNT (l->data));
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+
+ fail:
+ if (klass != NULL)
+ g_type_class_unref (klass);
+}
+
+int
+g_vfs_proxy_volume_monitor_daemon_main (int argc,
+ char *argv[],
+ const char *dbus_name,
+ GType volume_monitor_type)
+{
+ int rc;
+ int ret;
+ GMainLoop *loop;
+ DBusError dbus_error;
+
+ ret = 1;
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ /* need to start up regardless of whether we can instantiate a
+ * volume monitor; this is because the proxy will need to be able to
+ * call IsSupported() on our D-Bus interface.
+ */
+
+ the_volume_monitor_type = volume_monitor_type;
+ the_dbus_name = dbus_name;
+
+ /* try and create the monitor */
+ monitor_try_create ();
+
+ dbus_error_init (&dbus_error);
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("Cannot connect to session bus: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ _g_dbus_connection_integrate_with_main (connection);
+
+ rc = dbus_bus_request_name (connection, dbus_name, 0, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("dbus_bus_request_name failed: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+ if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ g_warning ("Cannot become primary owner");
+ goto out;
+ }
+
+ if (!dbus_connection_add_filter (connection, filter_function, NULL, NULL))
+ {
+ g_warning ("Cannot add filter function");
+ goto out;
+ }
+
+ if (monitor != NULL)
+ {
+ g_signal_connect (monitor, "drive-changed", (GCallback) drive_changed, connection);
+ g_signal_connect (monitor, "drive-connected", (GCallback) drive_connected, connection);
+ g_signal_connect (monitor, "drive-disconnected", (GCallback) drive_disconnected, connection);
+ g_signal_connect (monitor, "drive-eject-button", (GCallback) drive_eject_button, connection);
+
+ g_signal_connect (monitor, "volume-changed", (GCallback) volume_changed, connection);
+ g_signal_connect (monitor, "volume-added", (GCallback) volume_added, connection);
+ g_signal_connect (monitor, "volume-removed", (GCallback) volume_removed, connection);
+
+ g_signal_connect (monitor, "mount-changed", (GCallback) mount_changed, connection);
+ g_signal_connect (monitor, "mount-added", (GCallback) mount_added, connection);
+ g_signal_connect (monitor, "mount-pre-unmount", (GCallback) mount_pre_unmount, connection);
+ g_signal_connect (monitor, "mount-removed", (GCallback) mount_removed, connection);
+ }
+
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ ret = 0;
+
+out:
+ return ret;
+}
diff --git a/gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.h b/gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.h
new file mode 100644
index 00000000..d6c767db
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/gvfsproxyvolumemonitordaemon.h
@@ -0,0 +1,35 @@
+/* -*- 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_VFS_PROXY_VOLUME_MONITOR_DAEMON_H__
+#define __G_VFS_PROXY_VOLUME_MONITOR_DAEMON_H__
+
+#include <gio/gio.h>
+
+void g_vfs_proxy_volume_monitor_daemon_init (void);
+int g_vfs_proxy_volume_monitor_daemon_main (int argc,
+ char *argv[],
+ const char *dbus_name,
+ GType volume_monitor_type);
+
+#endif
diff --git a/gnome-2-24/monitor/proxy/remote-volume-monitor-module.c b/gnome-2-24/monitor/proxy/remote-volume-monitor-module.c
new file mode 100644
index 00000000..90945141
--- /dev/null
+++ b/gnome-2-24/monitor/proxy/remote-volume-monitor-module.c
@@ -0,0 +1,64 @@
+/* -*- 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 <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxyvolume.h"
+#include "gproxymount.h"
+#include "gproxydrive.h"
+
+void
+g_io_module_load (GIOModule *module)
+{
+ /* see gvfsproxyvolumemonitor.c:g_vfs_proxy_volume_monitor_daemon_init() */
+ if (g_getenv ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE") != NULL)
+ goto out;
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ g_proxy_drive_register (module);
+ g_proxy_mount_register (module);
+ g_proxy_volume_register (module);
+ g_proxy_volume_monitor_register (module);
+out:
+ ;
+ }
+
+void
+g_io_module_unload (GIOModule *module)
+{
+ if (g_getenv ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE") != NULL)
+ goto out;
+
+ g_proxy_volume_monitor_teardown_session_bus_connection ();
+
+out:
+ ;
+}