summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/gdaemonvfs.c115
-rw-r--r--client/gdaemonvfs.h1
-rw-r--r--common/Makefile.am1
-rw-r--r--common/gmounttracker.c384
-rw-r--r--common/gmounttracker.h51
-rw-r--r--daemon/mount.c43
6 files changed, 465 insertions, 130 deletions
diff --git a/client/gdaemonvfs.c b/client/gdaemonvfs.c
index f3e79a6c..685aad12 100644
--- a/client/gdaemonvfs.c
+++ b/client/gdaemonvfs.c
@@ -317,7 +317,7 @@ handler_lookup_mount_reply (DBusMessage *reply,
{
DBusError derror;
GMountRef *ref;
- DBusMessageIter iter;
+ DBusMessageIter iter, struct_iter;
const char *display_name, *icon, *obj_path, *dbus_id;
GMountSpec *mount_spec;
GList *l;
@@ -327,7 +327,10 @@ handler_lookup_mount_reply (DBusMessage *reply,
dbus_error_init (&derror);
dbus_message_iter_init (reply, &iter);
- if (!_g_dbus_message_iter_get_args (&iter,
+
+ dbus_message_iter_recurse (&iter, &struct_iter);
+
+ if (!_g_dbus_message_iter_get_args (&struct_iter,
&derror,
DBUS_TYPE_STRING, &display_name,
DBUS_TYPE_STRING, &icon,
@@ -340,7 +343,7 @@ handler_lookup_mount_reply (DBusMessage *reply,
return NULL;
}
- mount_spec = g_mount_spec_from_dbus (&iter);
+ mount_spec = g_mount_spec_from_dbus (&struct_iter);
if (mount_spec == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -511,112 +514,6 @@ _g_daemon_vfs_get_mount_ref_sync (GMountSpec *spec,
return ref;
}
-static GList *
-demarshal_mount_list (DBusMessage *message, GError **error)
-{
- DBusMessageIter iter;
- DBusError derror;
- GMountRef *ref;
- GList *mount_list = NULL;
-
- dbus_error_init (&derror);
-
- dbus_message_iter_init (message, &iter);
- dbus_message_iter_recurse (&iter, &iter);
-
- do
- {
- DBusMessageIter struct_iter;
- GMountSpec *mount_spec;
- gchar *display_name;
- gchar *icon;
- gchar *dbus_id;
- gchar *obj_path;
-
- dbus_message_iter_recurse (&iter, &struct_iter);
-
- if (!_g_dbus_message_iter_get_args (&struct_iter,
- &derror,
- DBUS_TYPE_STRING, &display_name,
- DBUS_TYPE_STRING, &icon,
- DBUS_TYPE_STRING, &dbus_id,
- DBUS_TYPE_OBJECT_PATH, &obj_path,
- 0))
- {
- g_list_foreach (mount_list, (GFunc) _g_mount_ref_unref, NULL);
- g_list_free (mount_list);
-
- _g_error_from_dbus (&derror, error);
- dbus_error_free (&derror);
- return NULL;
- }
-
- mount_spec = g_mount_spec_from_dbus (&struct_iter);
-
- if (mount_spec == NULL)
- {
- g_list_foreach (mount_list, (GFunc) _g_mount_ref_unref, NULL);
- g_list_free (mount_list);
-
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Error while listing mount info: %s",
- "Invalid reply");
- return NULL;
- }
-
- /* TODO: Update cache */
-
- ref = g_new0 (GMountRef, 1);
- ref->ref_count = 1;
- ref->dbus_id = g_strdup (dbus_id);
- ref->object_path = g_strdup (obj_path);
- ref->spec = mount_spec;
-
- mount_list = g_list_prepend (mount_list, ref);
- }
- while (dbus_message_iter_next (&iter));
-
- return mount_list;
-}
-
-GList *
-_g_daemon_vfs_get_mount_list_sync (GError **error)
-{
- DBusConnection *conn;
- DBusMessage *message, *reply;
- DBusError derror;
- GList *mount_list;
-
- conn = _g_dbus_connection_get_sync (NULL, error);
- if (conn == NULL)
- return NULL;
-
- message =
- dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
- G_VFS_DBUS_MOUNTTRACKER_PATH,
- G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
- G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS);
- dbus_message_set_auto_start (message, TRUE);
-
- dbus_error_init (&derror);
- reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
- dbus_message_unref (message);
-
- if (!reply)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Error while getting mount list: %s",
- derror.message);
- dbus_error_free (&derror);
- return NULL;
- }
-
- mount_list = demarshal_mount_list (reply, error);
- dbus_message_unref (reply);
-
- return mount_list;
-}
-
static GFile *
g_daemon_vfs_parse_name (GVfs *vfs,
const char *parse_name)
diff --git a/client/gdaemonvfs.h b/client/gdaemonvfs.h
index 99c621fd..4b8905e1 100644
--- a/client/gdaemonvfs.h
+++ b/client/gdaemonvfs.h
@@ -37,7 +37,6 @@ GType g_daemon_vfs_get_type (void) G_GNUC_CONST;
GDaemonVfs *g_daemon_vfs_new (void);
-GList *_g_daemon_vfs_get_mount_list_sync (GError **error);
void _g_daemon_vfs_get_mount_ref_async (GMountSpec *spec,
const char *path,
GMountRefLookupCallback callback,
diff --git a/common/Makefile.am b/common/Makefile.am
index dc7f695b..522bebea 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -14,6 +14,7 @@ libcommon_la_SOURCES = \
gmountspec.c gmountspec.h \
gmountoperationdbus.c gmountoperation.h \
gmountsource.c gmountsource.h \
+ gmounttracker.c gmounttracker.h \
gvfsdaemonprotocol.h \
$(NULL)
diff --git a/common/gmounttracker.c b/common/gmounttracker.c
new file mode 100644
index 00000000..145e56c2
--- /dev/null
+++ b/common/gmounttracker.c
@@ -0,0 +1,384 @@
+#include <config.h>
+
+#include <string.h>
+
+#include <gmounttracker.h>
+#include <gdbusutils.h>
+#include <gvfsdaemonprotocol.h>
+
+enum {
+ MOUNTED,
+ UNMOUNTED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _GMountTracker
+{
+ GObject parent_instance;
+
+ GList *mounts;
+};
+
+G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT);
+
+static DBusHandlerResult g_mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data);
+
+
+
+gboolean
+g_mount_info_equal (GMountInfo *info1,
+ GMountInfo *info2)
+{
+ return
+ strcmp (info1->dbus_id, info2->dbus_id) == 0 &&
+ strcmp (info1->object_path, info2->object_path) == 0;
+}
+
+GMountInfo *
+g_mount_info_dup (GMountInfo *info)
+{
+ GMountInfo *copy;
+
+ copy = g_new (GMountInfo, 1);
+ copy->display_name = g_strdup (info->display_name);
+ copy->icon = g_strdup (info->icon);
+ copy->dbus_id = g_strdup (info->dbus_id);
+ copy->object_path = g_strdup (info->object_path);
+ copy->mount_spec = g_mount_spec_copy (info->mount_spec);
+
+ return copy;
+}
+
+void
+g_mount_info_free (GMountInfo *info)
+{
+ g_free (info->display_name);
+ g_free (info->icon);
+ g_free (info->dbus_id);
+ g_free (info->object_path);
+ g_mount_spec_unref (info->mount_spec);
+ g_free (info);
+}
+
+static GMountInfo *
+g_mount_info_from_dbus (DBusMessageIter *iter)
+{
+ DBusMessageIter struct_iter;
+ GMountInfo *info;
+ GMountSpec *mount_spec;
+ gchar *display_name;
+ gchar *icon;
+ gchar *dbus_id;
+ gchar *obj_path;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ return NULL;
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
+ DBUS_TYPE_STRING, &display_name,
+ DBUS_TYPE_STRING, &icon,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ 0))
+ return NULL;
+
+ mount_spec = g_mount_spec_from_dbus (&struct_iter);
+ if (mount_spec == NULL)
+ return NULL;
+
+ info = g_new0 (GMountInfo, 1);
+ info->display_name = g_strdup (display_name);
+ info->icon = g_strdup (icon);
+ info->dbus_id = g_strdup (dbus_id);
+ info->object_path = g_strdup (obj_path);
+ info->mount_spec = mount_spec;
+
+ return info;
+}
+
+
+static void
+g_mount_tracker_finalize (GObject *object)
+{
+ GMountTracker *tracker;
+ DBusConnection *conn;
+
+ tracker = G_MOUNT_TRACKER (object);
+
+ g_list_foreach (tracker->mounts,
+ (GFunc)g_mount_info_free, NULL);
+ g_list_free (tracker->mounts);
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (conn)
+ {
+ dbus_connection_remove_filter (conn, g_mount_tracker_filter_func, tracker);
+
+
+ dbus_bus_remove_match (conn,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
+ NULL);
+ dbus_bus_remove_match (conn,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
+ NULL);
+
+ dbus_connection_unref (conn);
+ }
+
+
+ if (G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (object);
+}
+
+static void
+g_mount_tracker_class_init (GMountTrackerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_mount_tracker_finalize;
+
+ signals[MOUNTED] = g_signal_new (I_("mounted"),
+ G_TYPE_MOUNT_TRACKER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GMountTrackerClass, mounted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals[UNMOUNTED] = g_signal_new (I_("unmounted"),
+ G_TYPE_MOUNT_TRACKER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GMountTrackerClass, unmounted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+}
+
+static GList *
+g_mount_tracker_find (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ GList *l;
+
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ if (g_mount_info_equal (info, (GMountInfo *)l->data))
+ return l;
+ }
+
+ return NULL;
+}
+
+static void
+g_mount_tracker_add_mount (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ /* Don't add multiple times */
+ if (g_mount_tracker_find (tracker, info))
+ return;
+
+ tracker->mounts = g_list_prepend (tracker->mounts, g_mount_info_dup (info));
+
+ g_signal_emit (tracker, signals[MOUNTED], 0, info);
+}
+
+static void
+g_mount_tracker_remove_mount (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ GList *l;
+ GMountInfo *old_info;
+
+
+ l = g_mount_tracker_find (tracker, info);
+
+ /* Don't remove multiple times */
+ if (l == NULL)
+ return;
+
+ old_info = l->data;
+
+ tracker->mounts = g_list_delete_link (tracker->mounts, l);
+
+ g_signal_emit (tracker, signals[UNMOUNTED], 0, old_info);
+ g_mount_info_free (old_info);
+}
+
+static void
+list_mounts_reply (DBusPendingCall *pending,
+ void *_data)
+{
+ GMountTracker *tracker = _data;
+ DBusMessageIter iter, array_iter;
+ GMountInfo *info;
+ DBusMessage *reply;
+ gboolean b;
+
+ reply = dbus_pending_call_steal_reply (pending);
+ dbus_pending_call_unref (pending);
+
+ b = dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_recurse (&iter, &array_iter);
+
+ do
+ {
+ info = g_mount_info_from_dbus (&array_iter);
+ if (info)
+ {
+ g_mount_tracker_add_mount (tracker, info);
+ g_mount_info_free (info);
+ }
+ }
+ while (dbus_message_iter_next (&array_iter));
+
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+g_mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data)
+{
+ GMountTracker *tracker = data;
+ GMountInfo *info;
+ DBusMessageIter iter;
+
+ if (dbus_message_is_signal (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED))
+ {
+ dbus_message_iter_init (message, &iter);
+ info = g_mount_info_from_dbus (&iter);
+
+ if (info)
+ {
+ g_mount_tracker_add_mount (tracker, info);
+ g_mount_info_free (info);
+ }
+ }
+ else if (dbus_message_is_signal (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED))
+ {
+ dbus_message_iter_init (message, &iter);
+ info = g_mount_info_from_dbus (&iter);
+
+ if (info)
+ {
+ g_mount_tracker_remove_mount (tracker, info);
+ g_mount_info_free (info);
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static void
+g_mount_tracker_init (GMountTracker *tracker)
+{
+ DBusConnection *conn;
+ DBusMessage *message;
+ DBusPendingCall *pending;
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (conn)
+ {
+ message =
+ dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS);
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_set_auto_start (message, TRUE);
+
+ if (!dbus_connection_send_with_reply (conn, message,
+ &pending,
+ G_VFS_DBUS_TIMEOUT_MSECS))
+ _g_dbus_oom ();
+
+ dbus_message_unref (message);
+
+ if (pending != NULL)
+ {
+ if (!dbus_pending_call_set_notify (pending,
+ list_mounts_reply,
+ g_object_ref (tracker), g_object_unref))
+ _g_dbus_oom ();
+ }
+
+ dbus_connection_add_filter (conn, g_mount_tracker_filter_func, tracker, NULL);
+
+ dbus_bus_add_match (conn,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
+ NULL);
+ dbus_bus_add_match (conn,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
+ NULL);
+
+ dbus_connection_unref (conn);
+ }
+}
+
+GMountTracker *
+g_mount_tracker_new (void)
+{
+ GMountTracker *tracker;
+
+ tracker = g_object_new (G_TYPE_MOUNT_TRACKER, NULL);
+
+ return tracker;
+}
+
+GList *
+g_mount_tracker_list_mounts (GMountTracker *tracker)
+{
+ GList *res, *l;
+ GMountInfo *copy;
+
+ res = NULL;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ copy = g_mount_info_dup (l->data);
+ res = g_list_prepend (res, copy);
+ }
+
+ return g_list_reverse (res);
+}
+
+GMountInfo *
+g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec)
+{
+ GList *l;
+ GMountInfo *info;
+
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ info = l->data;
+
+ if (g_mount_spec_equal (info->mount_spec, mount_spec))
+ return g_mount_info_dup (info);
+ }
+
+ return NULL;
+}
+
+
diff --git a/common/gmounttracker.h b/common/gmounttracker.h
new file mode 100644
index 00000000..2a717a1f
--- /dev/null
+++ b/common/gmounttracker.h
@@ -0,0 +1,51 @@
+#ifndef __G_MOUNT_TRACKER_H__
+#define __G_MOUNT_TRACKER_H__
+
+#include <glib-object.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_MOUNT_TRACKER (g_mount_tracker_get_type ())
+#define G_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_TRACKER, GMountTracker))
+#define G_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_TRACKER, GMountTrackerClass))
+#define G_IS_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_TRACKER))
+#define G_IS_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_TRACKER))
+#define G_MOUNT_TRACKER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_TRACKER, GMountTrackerClass))
+
+typedef struct _GMountTracker GMountTracker;
+typedef struct _GMountTrackerClass GMountTrackerClass;
+
+typedef struct {
+ char *display_name;
+ char *icon;
+ char *dbus_id;
+ char *object_path;
+ GMountSpec *mount_spec;
+} GMountInfo;
+
+struct _GMountTrackerClass
+{
+ GObjectClass parent_class;
+
+ void (*mounted) (GMountTracker *tracker,
+ GMountInfo *info);
+ void (*unmounted) (GMountTracker *tracker,
+ GMountInfo *info);
+};
+
+GType g_mount_tracker_get_type (void) G_GNUC_CONST;
+
+gboolean g_mount_info_equal (GMountInfo *info1,
+ GMountInfo *info2);
+GMountInfo *g_mount_info_dup (GMountInfo *info);
+void g_mount_info_free (GMountInfo *info);
+
+GMountTracker *g_mount_tracker_new (void);
+GList * g_mount_tracker_list_mounts (GMountTracker *tracker);
+GMountInfo * g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_TRACKER_H__ */
diff --git a/daemon/mount.c b/daemon/mount.c
index 15377f1e..836d8ee9 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -123,27 +123,43 @@ static void
vfs_mount_to_dbus (VfsMount *mount,
DBusMessageIter *iter)
{
- if (!dbus_message_iter_append_basic (iter,
+ DBusMessageIter struct_iter;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_OBJECT_PATH_AS_STRING
+ G_MOUNT_SPEC_TYPE_AS_STRING,
+ &struct_iter))
+ _g_dbus_oom ();
+
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
DBUS_TYPE_STRING,
&mount->display_name))
_g_dbus_oom ();
- if (!dbus_message_iter_append_basic (iter,
+ if (!dbus_message_iter_append_basic (&struct_iter,
DBUS_TYPE_STRING,
&mount->icon))
_g_dbus_oom ();
- if (!dbus_message_iter_append_basic (iter,
+ if (!dbus_message_iter_append_basic (&struct_iter,
DBUS_TYPE_STRING,
&mount->dbus_id))
_g_dbus_oom ();
- if (!dbus_message_iter_append_basic (iter,
+ if (!dbus_message_iter_append_basic (&struct_iter,
DBUS_TYPE_OBJECT_PATH,
&mount->object_path))
_g_dbus_oom ();
- g_mount_spec_to_dbus (iter, mount->mount_spec);
+ g_mount_spec_to_dbus (&struct_iter, mount->mount_spec);
+
+ if (!dbus_message_iter_close_container (iter, &struct_iter))
+ _g_dbus_oom ();
}
/************************************************************************
@@ -659,7 +675,7 @@ list_mounts (DBusConnection *connection,
{
VfsMount *mount;
DBusMessage *reply;
- DBusMessageIter iter, array_iter, struct_iter;
+ DBusMessageIter iter, array_iter;
GList *l;
reply = dbus_message_new_method_return (message);
@@ -687,20 +703,7 @@ list_mounts (DBusConnection *connection,
g_print ("mount: %p, name: %s, spec: %p\n", mount, mount->display_name, mount->mount_spec);
- if (!dbus_message_iter_open_container (&array_iter,
- DBUS_TYPE_STRUCT,
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_OBJECT_PATH_AS_STRING
- G_MOUNT_SPEC_TYPE_AS_STRING,
- &struct_iter))
- _g_dbus_oom ();
-
- vfs_mount_to_dbus (mount, &struct_iter);
-
- if (!dbus_message_iter_close_container (&array_iter, &struct_iter))
- _g_dbus_oom ();
+ vfs_mount_to_dbus (mount, &array_iter);
}
if (!dbus_message_iter_close_container (&iter, &array_iter))