diff options
Diffstat (limited to 'monitor/proxy/gproxyvolumemonitor.c')
-rw-r--r-- | monitor/proxy/gproxyvolumemonitor.c | 1278 |
1 files changed, 0 insertions, 1278 deletions
diff --git a/monitor/proxy/gproxyvolumemonitor.c b/monitor/proxy/gproxyvolumemonitor.c deleted file mode 100644 index 06523714..00000000 --- a/monitor/proxy/gproxyvolumemonitor.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* -*- 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 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 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) -{ -} - -static void -g_proxy_volume_monitor_class_finalize (GProxyVolumeMonitorClass *klass) -{ - g_free (klass->dbus_name); -} - -typedef struct { - char *dbus_name; - gboolean is_native; -} ProxyClassData; - -static ProxyClassData * -proxy_class_data_new (const char *dbus_name, gboolean is_native) -{ - ProxyClassData *data; - data = g_new0 (ProxyClassData, 1); - data->dbus_name = g_strdup (dbus_name); - data->is_native = is_native; - 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; - g_proxy_volume_monitor_class_intern_init (klass); -} - -static gboolean -is_supported (void) -{ - if (the_session_bus != NULL) - return TRUE; - return FALSE; -} - -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); - - 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; - monitor_class->is_supported = is_supported; - - 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); -} - -gboolean -g_proxy_volume_monitor_setup_session_bus_connection (void) -{ - gboolean ret; - DBusError dbus_error; - - ret = FALSE; - - G_LOCK (proxy_vm); - if (the_session_bus != NULL) - { - g_warning ("session bus connection is already up!"); - dbus_connection_ref (the_session_bus); - goto out; - } - - /* 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; - } - - _g_dbus_connection_integrate_with_main (the_session_bus); - - the_volume_monitors = g_hash_table_new (g_direct_hash, g_direct_equal); - - ret = TRUE; - - out: - G_UNLOCK (proxy_vm); - return ret; -} - -void -g_proxy_volume_monitor_teardown_session_bus_connection (void) -{ - G_LOCK (proxy_vm); - if (the_session_bus != NULL) - { - /* it would be nice to check that refcount==1 here */ - _g_dbus_connection_remove_from_main (the_session_bus); - 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); -} - -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; -} - -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; - } - - if (is_remote_monitor_supported (dbus_name)) - { - 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); - } -} |