diff options
author | Tomas Bzatek <tbzatek@redhat.com> | 2012-07-31 11:58:09 +0200 |
---|---|---|
committer | Tomas Bzatek <tbzatek@redhat.com> | 2012-07-31 11:58:09 +0200 |
commit | 622a5c0d167556188c38fcde40a42a0dfad9c625 (patch) | |
tree | 04f27be7f2a54779e17029ede2554e39c3464aa0 | |
parent | a494b809eaf82994108bfbbe5d950fed1a0a8c7c (diff) | |
download | gvfs-622a5c0d167556188c38fcde40a42a0dfad9c625.tar.gz |
gdbus: Core daemon and client port
Port of most of the gvfs core, few bits still missing. Lot of debug prints around,
will be removed in further commits. Same amount of TODOs and FIXMEs.
Notes:
* kill serials?
* get rid of mainloops where applicable (copy/move progress callback, enumerator)
* fix keyring integration
* use gdbus builtin fd passing within gvfsdaemon.c, kill the extra_fd stuff
81 files changed, 6519 insertions, 6720 deletions
@@ -40,3 +40,4 @@ gtk-doc.make *.enums.xml monitor/proxy/gvfsvolumemonitordbus.* metadata/metadata-dbus.* +common/gvfsdbus.* diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c index 27e86950..bc0afbe3 100644 --- a/client/gdaemonfile.c +++ b/client/gdaemonfile.c @@ -38,11 +38,12 @@ #include <gdaemonfilemonitor.h> #include <gdaemonfileenumerator.h> #include <glib/gi18n-lib.h> -#include "gvfsdbusutils.h" #include "gmountoperationdbus.h" #include <gio/gio.h> #include "metatree.h" #include <metadata-dbus.h> +#include <gvfsdbus.h> +#include <gio/gunixfdlist.h> static void g_daemon_file_file_iface_init (GFileIface *iface); @@ -179,6 +180,7 @@ g_daemon_file_get_path (GFile *file) mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, daemon_file->path, + NULL, /* TODO: cancellable */ NULL); if (mount_info == NULL) @@ -370,210 +372,130 @@ g_daemon_file_resolve_relative_path (GFile *file, return child; } -static DBusMessage * -create_empty_message (GFile *file, - const char *op, - GMountInfo **mount_info_out, - GError **error) -{ - GDaemonFile *daemon_file = G_DAEMON_FILE (file); - DBusMessage *message; - GMountInfo *mount_info; - const char *path; - - mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, - daemon_file->path, - error); - if (mount_info == NULL) - return NULL; - - if (mount_info_out) - *mount_info_out = g_mount_info_ref (mount_info); - - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - op); - - path = g_mount_info_resolve_path (mount_info, - daemon_file->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0); - - g_mount_info_unref (mount_info); - return message; -} - -static DBusMessage * -do_sync_path_call (GFile *file, - const char *op, - GMountInfo **mount_info_out, - DBusConnection **connection_out, - GCancellable *cancellable, - GError **error, - int first_arg_type, - ...) -{ - DBusMessage *message, *reply; - va_list var_args; - GError *my_error; - - retry: - - message = create_empty_message (file, op, mount_info_out, error); - if (!message) - return NULL; - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (message, - first_arg_type, - var_args); - va_end (var_args); - - - my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - connection_out, - NULL, NULL, NULL, - cancellable, &my_error); - dbus_message_unref (message); - - if (reply == NULL) - { - if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) - { - g_error_free (my_error); - goto retry; - } - g_propagate_error (error, my_error); - } - - return reply; -} - -static DBusMessage * -do_sync_2_path_call (GFile *file1, - GFile *file2, - const char *op, - const char *callback_obj_path, - DBusObjectPathMessageFunction callback, - gpointer callback_user_data, - DBusConnection **connection_out, - GCancellable *cancellable, - GError **error, - int first_arg_type, - ...) +static GVfsDBusMount * +create_proxy_for_file2 (GFile *file1, + GFile *file2, + GMountInfo **mount_info1_out, + GMountInfo **mount_info2_out, + gchar **path1_out, + gchar **path2_out, + GDBusConnection **connection_out, + GCancellable *cancellable, + GError **error) { + GVfsDBusMount *proxy; GDaemonFile *daemon_file1 = G_DAEMON_FILE (file1); GDaemonFile *daemon_file2 = G_DAEMON_FILE (file2); - DBusMessage *message, *reply; GMountInfo *mount_info1, *mount_info2; - const char *path1, *path2; - va_list var_args; - GError *my_error; + GDBusConnection *connection; - retry: + proxy = NULL; + mount_info2 = NULL; mount_info1 = _g_daemon_vfs_get_mount_info_sync (daemon_file1->mount_spec, - daemon_file1->path, - error); + daemon_file1->path, + cancellable, + error); + if (mount_info1 == NULL) - return NULL; + goto out; - mount_info2 = NULL; if (daemon_file2) { mount_info2 = _g_daemon_vfs_get_mount_info_sync (daemon_file2->mount_spec, - daemon_file2->path, - error); + daemon_file2->path, + cancellable, + error); if (mount_info2 == NULL) - { - g_mount_info_unref (mount_info1); - return NULL; - } + goto out; - if (mount_info1 != mount_info2) - { - g_mount_info_unref (mount_info1); - /* For copy this will cause the fallback code to be involved */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Operation not supported, files on different mounts")); - return NULL; - } + if (! g_mount_info_equal (mount_info1, mount_info2)) + { + /* For copy this will cause the fallback code to be involved */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Operation not supported, files on different mounts")); + goto out; + } } - - message = - dbus_message_new_method_call (mount_info1->dbus_id, - mount_info1->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - op); - path1 = g_mount_info_resolve_path (mount_info1, - daemon_file1->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path1, 0); + connection = _g_dbus_connection_get_sync (mount_info1->dbus_id, cancellable, error); + if (connection == NULL) + goto out; - if (daemon_file2) - { - path2 = g_mount_info_resolve_path (mount_info2, - daemon_file2->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path2, 0); - } + proxy = gvfs_dbus_mount_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + mount_info1->dbus_id, + mount_info1->object_path, + cancellable, + error); - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (message, - first_arg_type, - var_args); - va_end (var_args); + if (proxy == NULL) + goto out; + + _g_dbus_connect_vfs_filters (connection); - my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - connection_out, - callback_obj_path, - callback, - callback_user_data, - cancellable, &my_error); - dbus_message_unref (message); + if (mount_info1_out) + *mount_info1_out = g_mount_info_ref (mount_info1); + if (mount_info2_out && mount_info2) + *mount_info2_out = g_mount_info_ref (mount_info2); + if (path1_out) + *path1_out = g_strdup (g_mount_info_resolve_path (mount_info1, daemon_file1->path)); + if (path2_out && mount_info2) + *path2_out = g_strdup (g_mount_info_resolve_path (mount_info2, daemon_file2->path)); + if (connection_out) + *connection_out = connection; + out: g_mount_info_unref (mount_info1); if (mount_info2) g_mount_info_unref (mount_info2); + + return proxy; +} - if (reply == NULL) - { - if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) - { - g_error_free (my_error); - goto retry; - } - g_propagate_error (error, my_error); - } - - return reply; +static GVfsDBusMount * +create_proxy_for_file (GFile *file, + GMountInfo **mount_info_out, + gchar **path_out, + GDBusConnection **connection_out, + GCancellable *cancellable, + GError **error) +{ + return create_proxy_for_file2 (file, NULL, + mount_info_out, NULL, + path_out, NULL, + connection_out, + cancellable, + error); } -typedef void (*AsyncPathCallCallback) (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data); +typedef void (*CreateProxyAsyncCallback) (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data); typedef struct { GSimpleAsyncResult *result; GFile *file; char *op; GCancellable *cancellable; - DBusMessage *args; - AsyncPathCallCallback callback; + CreateProxyAsyncCallback callback; gpointer callback_data; GDestroyNotify notify; GMountInfo *mount_info; -} AsyncPathCall; + GDBusConnection *connection; + GVfsDBusMount *proxy; +} AsyncProxyCreate; static void -async_path_call_free (AsyncPathCall *data) +async_proxy_create_free (AsyncProxyCreate *data) { + g_print ("async_proxy_create_free\n"); if (data->notify) data->notify (data->callback_data); @@ -583,144 +505,176 @@ async_path_call_free (AsyncPathCall *data) g_free (data->op); if (data->cancellable) g_object_unref (data->cancellable); - if (data->args) - dbus_message_unref (data->args); if (data->mount_info) g_mount_info_unref (data->mount_info); + if (data->connection) + g_object_unref (data->connection); + if (data->proxy) + g_object_unref (data->proxy); g_free (data); } static void -async_path_call_done (DBusMessage *reply, - DBusConnection *connection, - GError *io_error, - gpointer _data) +async_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - AsyncPathCall *data = _data; + AsyncProxyCreate *data = user_data; + GDaemonFile *daemon_file = G_DAEMON_FILE (data->file); + const char *path; + GVfsDBusMount *proxy; + GError *error = NULL; GSimpleAsyncResult *result; - - if (io_error != NULL) + + proxy = gvfs_dbus_mount_proxy_new_finish (res, &error); + g_print ("async_proxy_new_cb, proxy = %p\n", proxy); + if (proxy == NULL) { - g_simple_async_result_set_from_error (data->result, io_error); + g_simple_async_result_take_error (data->result, error); _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); - async_path_call_free (data); - } - else - { - result = data->result; - g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data); - data->result = NULL; - - data->callback (reply, - connection, - data->mount_info, - result, - data->cancellable, - data->callback_data); - - /* Free data here, or later if callback ref:ed the result */ - g_object_unref (result); + async_proxy_create_free (data); + return; } + + data->proxy = proxy; + _g_dbus_connect_vfs_filters (data->connection); + path = g_mount_info_resolve_path (data->mount_info, daemon_file->path); + + /* Complete the create_proxy_for_file_async() call */ + result = data->result; + g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_proxy_create_free, data); + data->result = NULL; + + data->callback (proxy, + data->connection, + data->mount_info, + path, + result, + NULL, + data->cancellable, + data->callback_data); + + /* Free data here, or later if callback ref:ed the result */ + g_object_unref (result); } static void -do_async_path_call_callback (GMountInfo *mount_info, - gpointer _data, - GError *error) +async_construct_proxy (GDBusConnection *connection, + AsyncProxyCreate *data) { - AsyncPathCall *data = _data; - GDaemonFile *daemon_file = G_DAEMON_FILE (data->file); - const char *path; - DBusMessage *message; - DBusMessageIter arg_source, arg_dest; + data->connection = g_object_ref (connection); + gvfs_dbus_mount_proxy_new (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + data->mount_info->dbus_id, + data->mount_info->object_path, + data->cancellable, + async_proxy_new_cb, + data); +} + +static void +bus_get_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + AsyncProxyCreate *data = user_data; + GDBusConnection *connection; + GError *error = NULL; - if (error != NULL) + connection = g_bus_get_finish (res, &error); + + if (connection == NULL) { - g_simple_async_result_set_from_error (data->result, error); + g_simple_async_result_set_from_error (data->result, error); _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); - async_path_call_free (data); + async_proxy_create_free (data); return; } - data->mount_info = g_mount_info_ref (mount_info); + async_construct_proxy (connection, data); +} - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - data->op); +static void +async_got_connection_cb (GDBusConnection *connection, + GError *io_error, + gpointer callback_data) +{ + AsyncProxyCreate *data = callback_data; + + g_print ("async_got_connection_cb, connection = %p\n", connection); - path = g_mount_info_resolve_path (mount_info, daemon_file->path); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0); + if (connection == NULL) + { + /* TODO: we should probably test if we really want a session bus; + * for now, this code is on par with the old dbus code */ + g_bus_get (G_BUS_TYPE_SESSION, + data->cancellable, + bus_get_cb, + data); + return; + } + + async_construct_proxy (connection, data); +} - /* Append more args from data->args */ +static void +async_got_mount_info (GMountInfo *mount_info, + gpointer _data, + GError *error) +{ + AsyncProxyCreate *data = _data; + + g_print ("async_got_mount_info, mount_info = %p\n", mount_info); - if (data->args) + if (error != NULL) { - dbus_message_iter_init (data->args, &arg_source); - dbus_message_iter_init_append (message, &arg_dest); - - _g_dbus_message_iter_copy (&arg_dest, &arg_source); + g_simple_async_result_set_from_error (data->result, error); + _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); + async_proxy_create_free (data); + return; } - _g_vfs_daemon_call_async (message, - async_path_call_done, data, - data->cancellable); - - dbus_message_unref (message); + data->mount_info = g_mount_info_ref (mount_info); + + _g_dbus_connection_get_for_async (mount_info->dbus_id, + async_got_connection_cb, + data, + data->cancellable); } static void -do_async_path_call (GFile *file, - const char *op, - GCancellable *cancellable, - GAsyncReadyCallback op_callback, - gpointer op_callback_data, - AsyncPathCallCallback callback, - gpointer callback_data, - GDestroyNotify notify, - int first_arg_type, - ...) +create_proxy_for_file_async (GFile *file, + GCancellable *cancellable, + GAsyncReadyCallback op_callback, + gpointer op_callback_data, + CreateProxyAsyncCallback callback, + gpointer callback_data, + GDestroyNotify notify) { GDaemonFile *daemon_file = G_DAEMON_FILE (file); - va_list var_args; - AsyncPathCall *data; + AsyncProxyCreate *data; - data = g_new0 (AsyncPathCall, 1); + g_print ("create_proxy_for_file_async\n"); + + data = g_new0 (AsyncProxyCreate, 1); data->result = g_simple_async_result_new (G_OBJECT (file), - op_callback, op_callback_data, - NULL); + op_callback, op_callback_data, + NULL); data->file = g_object_ref (file); - data->op = g_strdup (op); if (cancellable) data->cancellable = g_object_ref (cancellable); data->callback = callback; data->callback_data = callback_data; data->notify = notify; - if (first_arg_type != 0) - { - data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); - if (data->args == NULL) - _g_dbus_oom (); - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (data->args, - first_arg_type, - var_args); - va_end (var_args); - } - - _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec, - daemon_file->path, - do_async_path_call_callback, - data); + daemon_file->path, + async_got_mount_info, + data); } - static GFileEnumerator * g_daemon_file_enumerate_children (GFile *file, const char *attributes, @@ -728,47 +682,51 @@ g_daemon_file_enumerate_children (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; - dbus_uint32_t flags_dbus; char *obj_path; + char *path; GDaemonFileEnumerator *enumerator; - DBusConnection *connection; + GDBusConnection *connection; char *uri; - + GVfsDBusMount *proxy; + gboolean res; + + g_print ("g_daemon_file_enumerate_children\n"); + enumerator = g_daemon_file_enumerator_new (file, attributes); - obj_path = g_daemon_file_enumerator_get_object_path (enumerator); - + proxy = create_proxy_for_file (file, NULL, &path, &connection, cancellable, error); + if (proxy == NULL) + goto out; + + obj_path = g_daemon_file_enumerator_get_object_path (enumerator); uri = g_file_get_uri (file); + + res = gvfs_dbus_mount_call_enumerate_sync (proxy, + path, + obj_path, + attributes ? attributes : "", + flags, + uri, + cancellable, + error); + + g_print ("g_daemon_file_enumerate_children: done, res = %d\n", res); - if (attributes == NULL) - attributes = ""; - flags_dbus = flags; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_ENUMERATE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_STRING, &uri, - 0); + g_free (path); g_free (uri); g_free (obj_path); + g_object_unref (proxy); - if (reply == NULL) - goto error; - - dbus_message_unref (reply); - + if (! res) + goto out; + g_daemon_file_enumerator_set_sync_connection (enumerator, connection); return G_FILE_ENUMERATOR (enumerator); - - error: - if (reply) - dbus_message_unref (reply); - g_object_unref (enumerator); + +out: + if (enumerator != NULL) + g_object_unref (enumerator); return NULL; } @@ -843,94 +801,143 @@ g_daemon_file_query_info (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; - dbus_uint32_t flags_dbus; - DBusMessageIter iter; + char *path; GFileInfo *info; char *uri; + GVfsDBusMount *proxy; + GVariant *iter_info; + gboolean res; + + g_print ("g_daemon_file_query_info\n"); + + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) + return NULL; uri = g_file_get_uri (file); - if (attributes == NULL) - attributes = ""; - flags_dbus = flags; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_INFO, - NULL, NULL, - cancellable, error, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_STRING, &uri, - 0); + iter_info = NULL; + res = gvfs_dbus_mount_call_query_info_sync (proxy, + path, + attributes ? attributes : "", + flags, + uri, + &iter_info, + cancellable, + error); + + g_print ("g_daemon_file_query_info: done, res = %d\n", res); + g_free (path); g_free (uri); - - if (reply == NULL) - return NULL; + g_object_unref (proxy); - info = NULL; - - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - /* Translators: %s is the name of a programming function */ - _("Invalid return value from %s"), "get_info"); - goto out; - } + if (! res) + return NULL; - info = _g_dbus_get_file_info (&iter, error); + info = _g_dbus_get_file_info (iter_info, error); + g_variant_unref (iter_info); if (info) add_metadata (file, attributes, info); - - out: - dbus_message_unref (reply); + return info; } + +typedef struct { + GFile *file; + char *attributes; + GFileQueryInfoFlags flags; + int io_priority; + GSimpleAsyncResult *result; + GCancellable *cancellable; +} AsyncCallQueryInfo; + static void -query_info_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +async_call_query_info_free (AsyncCallQueryInfo *data) { - const char *attributes = callback_data; - DBusMessageIter iter; + if (data->file) + g_object_unref (data->file); + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + g_free (data->attributes); + g_free (data); +} + +static void +query_info_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) +{ + AsyncCallQueryInfo *data = user_data; + GError *error = NULL; + GSimpleAsyncResult *orig_result; + GVariant *iter_info; GFileInfo *info; - GError *error; GFile *file; - - info = NULL; - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) + g_print ("query_info_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_query_info_finish (proxy, &iter_info, res, &error)) { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "query_info"); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; + g_simple_async_result_take_error (orig_result, error); + goto out; } + + info = _g_dbus_get_file_info (iter_info, &error); + g_variant_unref (iter_info); - error = NULL; - info = _g_dbus_get_file_info (&iter, &error); if (info == NULL) { - g_simple_async_result_set_from_error (result, error); - g_error_free (error); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; + g_simple_async_result_take_error (orig_result, error); + goto out; } - file = G_FILE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); - add_metadata (file, attributes, info); + file = G_FILE (g_async_result_get_source_object (G_ASYNC_RESULT (orig_result))); + add_metadata (file, data->attributes, info); g_object_unref (file); - g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref); - _g_simple_async_result_complete_with_cancellable (result, cancellable); + g_simple_async_result_set_op_res_gpointer (orig_result, info, g_object_unref); + +out: + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ +} + +static void +query_info_async_get_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncCallQueryInfo *data = callback_data; + char *uri; + + g_print ("query_info_async_get_proxy_cb, proxy = %p\n", proxy); + + uri = g_file_get_uri (data->file); + + data->result = g_object_ref (result); + + gvfs_dbus_mount_call_query_info (proxy, + path, + data->attributes ? data->attributes : "", + data->flags, + uri, + cancellable, + (GAsyncReadyCallback) query_info_async_cb, + data); + + g_free (uri); } static void @@ -942,23 +949,23 @@ g_daemon_file_query_info_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - guint32 dbus_flags; - char *uri; + AsyncCallQueryInfo *data; - uri = g_file_get_uri (file); - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_INFO, - cancellable, - callback, user_data, - query_info_async_cb, g_strdup (attributes), g_free, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_STRING, &uri, - 0); + g_print ("g_daemon_file_query_info_async\n"); + + data = g_new0 (AsyncCallQueryInfo, 1); + data->file = g_object_ref (file); + data->attributes = g_strdup (attributes); + data->flags = flags; + data->io_priority = io_priority; + if (cancellable) + data->cancellable = g_object_ref (cancellable); - g_free (uri); + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + query_info_async_get_proxy_cb, + data, (GDestroyNotify) async_call_query_info_free); } static GFileInfo * @@ -976,67 +983,100 @@ g_daemon_file_query_info_finish (GFile *file, return NULL; } + typedef struct { + GFile *file; + guint16 mode; + int io_priority; + gchar *etag; + gboolean make_backup; + GFileCreateFlags flags; GSimpleAsyncResult *result; GCancellable *cancellable; - gboolean can_seek; -} GetFDData; +} AsyncCallFileReadWrite; + +static void +async_call_file_read_write_free (AsyncCallFileReadWrite *data) +{ + if (data->file) + g_object_unref (data->file); + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + g_free (data->etag); + g_free (data); +} static void -read_async_get_fd_cb (int fd, - gpointer callback_data) +read_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - GetFDData *data = callback_data; + AsyncCallFileReadWrite *data = user_data; + GError *error = NULL; + GSimpleAsyncResult *orig_result; + gboolean can_seek; + GUnixFDList *fd_list; + int fd; + guint fd_id; GFileInputStream *stream; + + g_print ("read_async_cb\n"); + orig_result = data->result; - if (fd == -1) + if (! gvfs_dbus_mount_call_open_for_read_finish (proxy, &fd_id, &can_seek, &fd_list, res, &error)) + { + g_simple_async_result_take_error (orig_result, error); + goto out; + } + + if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || + (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1) { - g_simple_async_result_set_error (data->result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Couldn't get stream file descriptor")); + g_simple_async_result_set_error (orig_result, + G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn't get stream file descriptor")); } else { - stream = g_daemon_file_input_stream_new (fd, data->can_seek); - g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref); + stream = g_daemon_file_input_stream_new (fd, can_seek); + g_simple_async_result_set_op_res_gpointer (orig_result, stream, g_object_unref); + g_object_unref (fd_list); } - _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); - - g_object_unref (data->result); - g_free (data); +out: + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ } static void -read_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - dbus_bool_t can_seek; - GetFDData *get_fd_data; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; - } +file_read_async_get_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncCallFileReadWrite *data = callback_data; + guint32 pid; + + g_print ("file_read_async_get_proxy_cb, proxy = %p\n", proxy); + + pid = get_pid_for_file (data->file); - get_fd_data = g_new0 (GetFDData, 1); - get_fd_data->result = g_object_ref (result); - get_fd_data->can_seek = can_seek; + data->result = g_object_ref (result); - _g_dbus_connection_get_fd_async (connection, fd_id, - read_async_get_fd_cb, get_fd_data); + gvfs_dbus_mount_call_open_for_read (proxy, + path, + pid, + NULL, + cancellable, + (GAsyncReadyCallback) read_async_cb, + data); } static void @@ -1046,17 +1086,21 @@ g_daemon_file_read_async (GFile *file, GAsyncReadyCallback callback, gpointer callback_data) { - guint32 pid; + AsyncCallFileReadWrite *data; - pid = get_pid_for_file (file); + g_print ("g_daemon_file_read_async\n"); + + data = g_new0 (AsyncCallFileReadWrite, 1); + data->file = g_object_ref (file); + data->io_priority = io_priority; + if (cancellable) + data->cancellable = g_object_ref (cancellable); - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ, - cancellable, - callback, callback_data, - read_async_cb, NULL, NULL, - DBUS_TYPE_UINT32, &pid, - 0); + create_proxy_for_file_async (file, + cancellable, + callback, callback_data, + file_read_async_get_proxy_cb, + data, (GDestroyNotify) async_call_file_read_write_free); } static GFileInputStream * @@ -1074,178 +1118,143 @@ g_daemon_file_read_finish (GFile *file, return NULL; } - static GFileInputStream * g_daemon_file_read (GFile *file, GCancellable *cancellable, GError **error) { - DBusConnection *connection; + GVfsDBusMount *proxy; + char *path; + gboolean res; + gboolean can_seek; + GUnixFDList *fd_list; int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; + guint fd_id; guint32 pid; + g_print ("g_daemon_file_read\n"); + pid = get_pid_for_file (file); - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT32, &pid, - 0); - if (reply == NULL) + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return NULL; - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - return NULL; - } + res = gvfs_dbus_mount_call_open_for_read_sync (proxy, + path, + pid, + NULL, + &fd_id, + &can_seek, + &fd_list, + cancellable, + error); - dbus_message_unref (reply); + g_print ("g_daemon_file_read: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) + if (! res) + return NULL; + + if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || + (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Didn't get stream file descriptor")); return NULL; } + + g_object_unref (fd_list); return g_daemon_file_input_stream_new (fd, can_seek); } static GFileOutputStream * -g_daemon_file_append_to (GFile *file, - GFileCreateFlags flags, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; +file_open_write (GFile *file, + guint16 mode, + const char *etag, + gboolean make_backup, + GFileCreateFlags flags, + GCancellable *cancellable, + GError **error) +{ + GVfsDBusMount *proxy; + char *path; + gboolean res; + gboolean can_seek; + GUnixFDList *fd_list; int fd; - DBusMessage *reply; guint32 fd_id; - dbus_bool_t can_seek; - guint16 mode; - guint64 initial_offset; - dbus_bool_t make_backup; - guint32 dbus_flags; - char *etag; guint32 pid; + guint64 initial_offset; pid = get_pid_for_file (file); - mode = 1; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_UINT32, &pid, - 0); - if (reply == NULL) + if (etag == NULL) + etag = ""; + + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return NULL; - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - return NULL; - } + res = gvfs_dbus_mount_call_open_for_write_sync (proxy, + path, + mode, + etag, + make_backup, + flags, + pid, + NULL, + &fd_id, + &can_seek, + &initial_offset, + &fd_list, + cancellable, + error); + + g_print ("file_open_write: done, res = %d\n", res); - dbus_message_unref (reply); + g_free (path); + g_object_unref (proxy); - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) + if (! res) + return NULL; + + if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || + (fd = g_unix_fd_list_get (fd_list, 0, NULL)) == -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); + _("Didn't get stream file descriptor")); return NULL; } + + g_object_unref (fd_list); return g_daemon_file_output_stream_new (fd, can_seek, initial_offset); } static GFileOutputStream * +g_daemon_file_append_to (GFile *file, + GFileCreateFlags flags, + GCancellable *cancellable, + GError **error) +{ + g_print ("g_daemon_file_append_to\n"); + + return file_open_write (file, 1, "", FALSE, flags, cancellable, error); +} + +static GFileOutputStream * g_daemon_file_create (GFile *file, GFileCreateFlags flags, GCancellable *cancellable, GError **error) { - DBusConnection *connection; - int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; - guint16 mode; - guint64 initial_offset; - dbus_bool_t make_backup; - char *etag; - guint32 dbus_flags; - guint32 pid; - - pid = get_pid_for_file (file); + g_print ("g_daemon_file_create\n"); - mode = 0; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_UINT32, &pid, - 0); - if (reply == NULL) - return NULL; - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - return NULL; - } - - dbus_message_unref (reply); - - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); - return NULL; - } - - return g_daemon_file_output_stream_new (fd, can_seek, initial_offset); + return file_open_write (file, 0, "", FALSE, flags, cancellable, error); } static GFileOutputStream * @@ -1256,62 +1265,29 @@ g_daemon_file_replace (GFile *file, GCancellable *cancellable, GError **error) { - DBusConnection *connection; - int fd; - DBusMessage *reply; - guint32 fd_id; - dbus_bool_t can_seek; - guint16 mode; - guint64 initial_offset; - dbus_bool_t dbus_make_backup; - guint32 dbus_flags; - guint32 pid; + g_print ("g_daemon_file_replace\n"); - pid = get_pid_for_file (file); - - mode = 2; - dbus_make_backup = make_backup; - dbus_flags = flags; + return file_open_write (file, 2, etag, make_backup, flags, cancellable, error); +} - if (etag == NULL) - etag = ""; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - NULL, &connection, - cancellable, error, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &dbus_make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_UINT32, &pid, - 0); - if (reply == NULL) - return NULL; - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - return NULL; - } - - dbus_message_unref (reply); +typedef struct { + GSimpleAsyncResult *result; + GCancellable *cancellable; + guint32 flags; + GMountOperation *mount_operation; +} AsyncMountOp; - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); - return NULL; - } - - return g_daemon_file_output_stream_new (fd, can_seek, initial_offset); +static void +free_async_mount_op (AsyncMountOp *data) +{ + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + if (data->mount_operation) + g_object_unref (data->mount_operation); + g_free (data); } static void @@ -1321,7 +1297,9 @@ mount_mountable_location_mounted_cb (GObject *source_object, { GSimpleAsyncResult *result = user_data; GError *error = NULL; - + + g_print ("mount_mountable_location_mounted_cb\n"); + if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error)) { g_simple_async_result_set_from_error (result, error); @@ -1330,77 +1308,115 @@ mount_mountable_location_mounted_cb (GObject *source_object, g_simple_async_result_complete (result); g_object_unref (result); - } static void -mount_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +mount_mountable_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - GMountOperation *mount_operation = callback_data; - GMountSpec *mount_spec; - char *path; - DBusMessageIter iter; + AsyncMountOp *data = user_data; + GSimpleAsyncResult *orig_result; + GError *error = NULL; + gboolean is_uri; + gchar *out_path; + gboolean must_mount_location; + GVariant *iter_mountspec; GFile *file; - dbus_bool_t must_mount_location, is_uri; - - path = NULL; - - dbus_message_iter_init (reply, &iter); + GMountSpec *mount_spec; - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_BOOLEAN, &is_uri, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_BOOLEAN, &must_mount_location, - 0)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "call"); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - - return; + g_print ("mount_mountable_async_cb\n"); + orig_result = data->result; + data->result = NULL; + + is_uri = FALSE; + out_path = NULL; + must_mount_location = FALSE; + iter_mountspec = NULL; + if (! gvfs_dbus_mount_call_mount_mountable_finish (proxy, + &is_uri, + &out_path, + &must_mount_location, + &iter_mountspec, + res, + &error)) + { + g_simple_async_result_take_error (orig_result, error); + goto out; } - + if (is_uri) { - file = g_file_new_for_uri (path); + file = g_file_new_for_uri (out_path); } else { - mount_spec = g_mount_spec_from_dbus (&iter); + mount_spec = g_mount_spec_from_dbus (iter_mountspec); + g_variant_unref (iter_mountspec); + if (mount_spec == NULL) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "call"); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; - } + { + g_simple_async_result_set_error (orig_result, + G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid return value from %s"), "call"); + goto out; + } - file = g_daemon_file_new (mount_spec, path); + file = g_daemon_file_new (mount_spec, out_path); g_mount_spec_unref (mount_spec); } - g_free (path); - g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref); + g_free (out_path); + g_simple_async_result_set_op_res_gpointer (orig_result, file, g_object_unref); if (must_mount_location) { g_file_mount_enclosing_volume (file, - 0, - mount_operation, - cancellable, - mount_mountable_location_mounted_cb, - g_object_ref (result)); - + 0, + data->mount_operation, + data->cancellable, + mount_mountable_location_mounted_cb, + orig_result); + return; } - else - _g_simple_async_result_complete_with_cancellable (result, cancellable); + +out: + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ +} + +static void +mount_mountable_got_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncMountOp *data = callback_data; + GMountSource *mount_source; + const char *dbus_id, *obj_path; + + g_print ("mount_mountable_got_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); + + dbus_id = g_mount_source_get_dbus_id (mount_source); + obj_path = g_mount_source_get_obj_path (mount_source); + + gvfs_dbus_mount_call_mount_mountable (proxy, + path, + dbus_id, + obj_path, + cancellable, + (GAsyncReadyCallback) mount_mountable_async_cb, + data); + + g_object_unref (mount_source); } static void @@ -1411,28 +1427,21 @@ g_daemon_file_mount_mountable (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - GMountSource *mount_source; - const char *dbus_id, *obj_path; - - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); + AsyncMountOp *data; - dbus_id = g_mount_source_get_dbus_id (mount_source); - obj_path = g_mount_source_get_obj_path (mount_source); - - if (mount_operation) - g_object_ref (mount_operation); - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE, - cancellable, - callback, user_data, - mount_mountable_async_cb, - mount_operation, mount_operation ? g_object_unref : NULL, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); + g_print ("g_daemon_file_mount_mountable\n"); + + data = g_new0 (AsyncMountOp, 1); + data->flags = flags; + data->mount_operation = g_object_ref (mount_operation); + if (cancellable) + data->cancellable = g_object_ref (cancellable); - g_object_unref (mount_source); + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + mount_mountable_got_proxy_cb, + data, (GDestroyNotify) free_async_mount_op); } static GFile * @@ -1451,46 +1460,82 @@ g_daemon_file_mount_mountable_finish (GFile *file, } static void -start_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +start_mountable_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - _g_simple_async_result_complete_with_cancellable (result, cancellable); + AsyncMountOp *data = user_data; + GSimpleAsyncResult *orig_result; + GError *error = NULL; + + g_print ("start_mountable_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_start_mountable_finish (proxy, res, &error)) + g_simple_async_result_take_error (orig_result, error); + + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ } static void -g_daemon_file_start_mountable (GFile *file, - GDriveStartFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ +start_mountable_got_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncMountOp *data = callback_data; GMountSource *mount_source; const char *dbus_id, *obj_path; - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); + g_print ("start_mountable_got_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); dbus_id = g_mount_source_get_dbus_id (mount_source); obj_path = g_mount_source_get_obj_path (mount_source); + + gvfs_dbus_mount_call_start_mountable (proxy, + path, + dbus_id, + obj_path, + cancellable, + (GAsyncReadyCallback) start_mountable_async_cb, + data); + + g_object_unref (mount_source); +} - if (mount_operation) - g_object_ref (mount_operation); - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_START_MOUNTABLE, - cancellable, - callback, user_data, - start_mountable_async_cb, - mount_operation, mount_operation ? g_object_unref : NULL, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); +static void +g_daemon_file_start_mountable (GFile *file, + GDriveStartFlags flags, + GMountOperation *mount_operation, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncMountOp *data; + + g_print ("g_daemon_file_start_mountable\n"); + + data = g_new0 (AsyncMountOp, 1); + data->flags = flags; + data->mount_operation = g_object_ref (mount_operation); + if (cancellable) + data->cancellable = g_object_ref (cancellable); - g_object_unref (mount_source); + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + start_mountable_got_proxy_cb, + data, (GDestroyNotify) free_async_mount_op); } static gboolean @@ -1502,50 +1547,85 @@ g_daemon_file_start_mountable_finish (GFile *file, } static void -stop_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +stop_mountable_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - _g_simple_async_result_complete_with_cancellable (result, cancellable); + AsyncMountOp *data = user_data; + GSimpleAsyncResult *orig_result; + GError *error = NULL; + + g_print ("stop_mountable_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_stop_mountable_finish (proxy, res, &error)) + g_simple_async_result_take_error (orig_result, error); + + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ } static void -g_daemon_file_stop_mountable (GFile *file, - GMountUnmountFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +stop_mountable_got_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) { - guint32 dbus_flags; + AsyncMountOp *data = callback_data; GMountSource *mount_source; const char *dbus_id, *obj_path; - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); + g_print ("stop_mountable_got_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); dbus_id = g_mount_source_get_dbus_id (mount_source); obj_path = g_mount_source_get_obj_path (mount_source); - - if (mount_operation) - g_object_ref (mount_operation); - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_STOP_MOUNTABLE, - cancellable, - callback, user_data, - stop_mountable_async_cb, - mount_operation, mount_operation ? g_object_unref : NULL, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); + + gvfs_dbus_mount_call_stop_mountable (proxy, + path, + data->flags, + dbus_id, + obj_path, + cancellable, + (GAsyncReadyCallback) stop_mountable_async_cb, + data); g_object_unref (mount_source); } +static void +g_daemon_file_stop_mountable (GFile *file, + GMountUnmountFlags flags, + GMountOperation *mount_operation, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncMountOp *data; + + g_print ("g_daemon_file_stop_mountable\n"); + + data = g_new0 (AsyncMountOp, 1); + data->flags = flags; + data->mount_operation = g_object_ref (mount_operation); + if (cancellable) + data->cancellable = g_object_ref (cancellable); + + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + stop_mountable_got_proxy_cb, + data, (GDestroyNotify) free_async_mount_op); +} + static gboolean g_daemon_file_stop_mountable_finish (GFile *file, GAsyncResult *result, @@ -1554,52 +1634,86 @@ g_daemon_file_stop_mountable_finish (GFile *file, return TRUE; } - static void -eject_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +eject_mountable_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - _g_simple_async_result_complete_with_cancellable (result, cancellable); + AsyncMountOp *data = user_data; + GSimpleAsyncResult *orig_result; + GError *error = NULL; + + g_print ("eject_mountable_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_eject_mountable_finish (proxy, res, &error)) + g_simple_async_result_take_error (orig_result, error); + + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ } static void -g_daemon_file_eject_mountable_with_operation (GFile *file, - GMountUnmountFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint32 dbus_flags; +eject_mountable_got_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncMountOp *data = callback_data; GMountSource *mount_source; const char *dbus_id, *obj_path; - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); + g_print ("eject_mountable_got_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); dbus_id = g_mount_source_get_dbus_id (mount_source); obj_path = g_mount_source_get_obj_path (mount_source); - - if (mount_operation) - g_object_ref (mount_operation); - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE, - cancellable, - callback, user_data, - eject_mountable_async_cb, - mount_operation, mount_operation ? g_object_unref : NULL, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); + + gvfs_dbus_mount_call_eject_mountable (proxy, + path, + data->flags, + dbus_id, + obj_path, + cancellable, + (GAsyncReadyCallback) eject_mountable_async_cb, + data); g_object_unref (mount_source); } +static void +g_daemon_file_eject_mountable_with_operation (GFile *file, + GMountUnmountFlags flags, + GMountOperation *mount_operation, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncMountOp *data; + + g_print ("g_daemon_file_eject_mountable_with_operation\n"); + + data = g_new0 (AsyncMountOp, 1); + data->flags = flags; + data->mount_operation = g_object_ref (mount_operation); + if (cancellable) + data->cancellable = g_object_ref (cancellable); + + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + eject_mountable_got_proxy_cb, + data, (GDestroyNotify) free_async_mount_op); +} + static gboolean g_daemon_file_eject_mountable_with_operation_finish (GFile *file, GAsyncResult *result, @@ -1627,50 +1741,85 @@ g_daemon_file_eject_mountable_finish (GFile *file, } static void -unmount_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +unmount_mountable_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - _g_simple_async_result_complete_with_cancellable (result, cancellable); + AsyncMountOp *data = user_data; + GSimpleAsyncResult *orig_result; + GError *error = NULL; + + g_print ("unmount_mountable_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_unmount_mountable_finish (proxy, res, &error)) + g_simple_async_result_take_error (orig_result, error); + + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ } static void -g_daemon_file_unmount_mountable_with_operation (GFile *file, - GMountUnmountFlags flags, - GMountOperation *mount_operation, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint32 dbus_flags; +unmount_mountable_got_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncMountOp *data = callback_data; GMountSource *mount_source; const char *dbus_id, *obj_path; - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); + g_print ("unmount_mountable_got_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); dbus_id = g_mount_source_get_dbus_id (mount_source); obj_path = g_mount_source_get_obj_path (mount_source); - - if (mount_operation) - g_object_ref (mount_operation); - - dbus_flags = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE, - cancellable, - callback, user_data, - unmount_mountable_async_cb, - mount_operation, mount_operation ? g_object_unref : NULL, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); + + gvfs_dbus_mount_call_unmount_mountable (proxy, + path, + data->flags, + dbus_id, + obj_path, + cancellable, + (GAsyncReadyCallback) unmount_mountable_async_cb, + data); g_object_unref (mount_source); } +static void +g_daemon_file_unmount_mountable_with_operation (GFile *file, + GMountUnmountFlags flags, + GMountOperation *mount_operation, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncMountOp *data; + + g_print ("g_daemon_file_unmount_mountable_with_operation\n"); + + data = g_new0 (AsyncMountOp, 1); + data->flags = flags; + data->mount_operation = g_object_ref (mount_operation); + if (cancellable) + data->cancellable = g_object_ref (cancellable); + + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + unmount_mountable_got_proxy_cb, + data, (GDestroyNotify) free_async_mount_op); +} + static gboolean g_daemon_file_unmount_mountable_with_operation_finish (GFile *file, GAsyncResult *result, @@ -1680,14 +1829,46 @@ g_daemon_file_unmount_mountable_with_operation_finish (GFile *file } static void -poll_mountable_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +poll_mountable_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - _g_simple_async_result_complete_with_cancellable (result, cancellable); + AsyncMountOp *data = user_data; + GSimpleAsyncResult *orig_result; + GError *error = NULL; + + g_print ("poll_mountable_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_poll_mountable_finish (proxy, res, &error)) + g_simple_async_result_take_error (orig_result, error); + + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ +} + +static void +poll_mountable_got_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncMountOp *data = callback_data; + + g_print ("poll_mountable_got_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + + gvfs_dbus_mount_call_poll_mountable (proxy, + path, + cancellable, + (GAsyncReadyCallback) poll_mountable_async_cb, + data); } static void @@ -1696,14 +1877,19 @@ g_daemon_file_poll_mountable (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_POLL_MOUNTABLE, - cancellable, - callback, user_data, - poll_mountable_async_cb, - NULL, - NULL, - 0); + AsyncMountOp *data; + + g_print ("g_daemon_file_poll_mountable\n"); + + data = g_new0 (AsyncMountOp, 1); + if (cancellable) + data->cancellable = g_object_ref (cancellable); + + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + poll_mountable_got_proxy_cb, + data, (GDestroyNotify) free_async_mount_op); } static gboolean @@ -1748,36 +1934,93 @@ static void g_daemon_file_mount_enclosing_volume (GFile *location, gpointer user_data); static void -mount_reply (DBusMessage *reply, - GError *error, - gpointer user_data) +free_mount_data (MountData *data) +{ + g_object_unref (data->file); + if (data->cancellable) + g_object_unref (data->cancellable); + if (data->mount_operation) + g_object_unref (data->mount_operation); + g_free (data); +} + +static void +mount_reply (GVfsDBusMountTracker *proxy, + GAsyncResult *res, + gpointer user_data) { MountData *data = user_data; - GSimpleAsyncResult *res; + GSimpleAsyncResult *ares; + GError *error = NULL; + + g_print ("mount_reply\n"); - if (reply == NULL) + if (!gvfs_dbus_mount_tracker_call_mount_location_finish (proxy, res, &error)) { - res = g_simple_async_result_new_from_error (G_OBJECT (data->file), - data->callback, - data->user_data, - error); + ares = g_simple_async_result_new_from_error (G_OBJECT (data->file), + data->callback, + data->user_data, + error); + g_error_free (error); } else { - res = g_simple_async_result_new (G_OBJECT (data->file), + ares = g_simple_async_result_new (G_OBJECT (data->file), data->callback, data->user_data, g_daemon_file_mount_enclosing_volume); } - _g_simple_async_result_complete_with_cancellable (res, data->cancellable); + _g_simple_async_result_complete_with_cancellable (ares, data->cancellable); + + free_mount_data (data); +} + +static void +mount_enclosing_volume_proxy_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + MountData *data = user_data; + GVfsDBusMountTracker *proxy; + GError *error = NULL; + GSimpleAsyncResult *ares; + GDaemonFile *daemon_file; + GMountSpec *spec; + GMountSource *mount_source; + + g_print ("mount_enclosing_volume_proxy_cb\n"); + daemon_file = G_DAEMON_FILE (data->file); + + proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error); + if (proxy == NULL) + { + ares = g_simple_async_result_new_from_error (G_OBJECT (data->file), + data->callback, + data->user_data, + error); + g_error_free (error); + _g_simple_async_result_complete_with_cancellable (ares, data->cancellable); + free_mount_data (data); + return; + } - g_object_unref (data->file); - if (data->cancellable) - g_object_unref (data->cancellable); - if (data->mount_operation) - g_object_unref (data->mount_operation); - g_free (data); + spec = g_mount_spec_copy (daemon_file->mount_spec); + g_mount_spec_set_mount_prefix (spec, daemon_file->path); + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); + + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS); + + gvfs_dbus_mount_tracker_call_mount_location (proxy, + g_mount_spec_to_dbus (spec), + g_mount_source_to_dbus (mount_source), + data->cancellable, + (GAsyncReadyCallback) mount_reply, + data); + + g_mount_spec_unref (spec); + g_object_unref (mount_source); + g_object_unref (proxy); } static void @@ -1788,30 +2031,10 @@ g_daemon_file_mount_enclosing_volume (GFile *location, GAsyncReadyCallback callback, gpointer user_data) { - GDaemonFile *daemon_file; - DBusMessage *message; - GMountSpec *spec; - GMountSource *mount_source; - DBusMessageIter iter; MountData *data; - daemon_file = G_DAEMON_FILE (location); + g_print ("g_daemon_file_mount_enclosing_volume\n"); - 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_MOUNT_LOCATION); - - spec = g_mount_spec_copy (daemon_file->mount_spec); - g_mount_spec_set_mount_prefix (spec, daemon_file->path); - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus (&iter, spec); - g_mount_spec_unref (spec); - - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); - g_mount_source_to_dbus (mount_source, message); - g_object_unref (mount_source); - data = g_new0 (MountData, 1); data->callback = callback; if (data->cancellable) @@ -1821,13 +2044,13 @@ g_daemon_file_mount_enclosing_volume (GFile *location, if (mount_operation) data->mount_operation = g_object_ref (mount_operation); - /* TODO: Ignoring cancellable here */ - _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (), - message, - G_VFS_DBUS_MOUNT_TIMEOUT_MSECS, - mount_reply, data); - - dbus_message_unref (message); + gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + G_VFS_DBUS_DAEMON_NAME, + G_VFS_DBUS_MOUNTTRACKER_PATH, + NULL, + mount_enclosing_volume_proxy_cb, + data); } static gboolean @@ -1845,74 +2068,127 @@ g_daemon_file_query_filesystem_info (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; - DBusMessageIter iter; GFileInfo *info; + GVfsDBusMount *proxy; + char *path; + gboolean res; + GVariant *iter_info; - if (attributes == NULL) - attributes = ""; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO, - NULL, NULL, - cancellable, error, - DBUS_TYPE_STRING, &attributes, - 0); - if (reply == NULL) + g_print ("g_daemon_file_query_filesystem_info\n"); + + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return NULL; - info = NULL; + iter_info = NULL; + res = gvfs_dbus_mount_call_query_filesystem_info_sync (proxy, + path, + attributes ? attributes : "", + &iter_info, + cancellable, + error); - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "get_filesystem_info"); - goto out; - } + g_print ("g_daemon_file_query_filesystem_info: done, res = %d\n", res); - info = _g_dbus_get_file_info (&iter, error); + g_free (path); + g_object_unref (proxy); + + if (! res) + return NULL; + + info = _g_dbus_get_file_info (iter_info, error); + g_variant_unref (iter_info); - out: - dbus_message_unref (reply); return info; } + +typedef struct { + GFile *file; + char *attributes; + GFileQueryInfoFlags flags; + int io_priority; + GSimpleAsyncResult *result; + GCancellable *cancellable; +} AsyncCallQueryFsInfo; + +static void +async_call_query_fs_info_free (AsyncCallQueryFsInfo *data) +{ + if (data->file) + g_object_unref (data->file); + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + g_free (data->attributes); + g_free (data); +} + static void -query_fs_info_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +query_fs_info_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - DBusMessageIter iter; + AsyncCallQueryFsInfo *data = user_data; GFileInfo *info; - GError *error; + GError *error = NULL; + GSimpleAsyncResult *orig_result; + GVariant *iter_info; - info = NULL; + g_print ("query_info_async_cb\n"); + orig_result = data->result; - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) + if (! gvfs_dbus_mount_call_query_filesystem_info_finish (proxy, &iter_info, res, &error)) { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "query_info"); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; + g_simple_async_result_take_error (orig_result, error); + goto out; } - error = NULL; - info = _g_dbus_get_file_info (&iter, &error); + info = _g_dbus_get_file_info (iter_info, &error); + g_variant_unref (iter_info); + if (info == NULL) { - g_simple_async_result_set_from_error (result, error); - g_error_free (error); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; + g_simple_async_result_take_error (orig_result, error); + goto out; } - g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref); - _g_simple_async_result_complete_with_cancellable (result, cancellable); + g_simple_async_result_set_op_res_gpointer (orig_result, info, g_object_unref); + +out: + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ +} + +static void +query_info_fs_async_get_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncCallQueryFsInfo *data = callback_data; + char *uri; + + g_print ("query_info_fs_async_get_proxy_cb, proxy = %p\n", proxy); + + uri = g_file_get_uri (data->file); + + data->result = g_object_ref (result); + + gvfs_dbus_mount_call_query_filesystem_info (proxy, + path, + data->attributes ? data->attributes : "", + cancellable, + (GAsyncReadyCallback) query_fs_info_async_cb, + data); + + g_free (uri); } static void @@ -1923,13 +2199,22 @@ g_daemon_file_query_filesystem_info_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO, - cancellable, - callback, user_data, - query_fs_info_async_cb, NULL, NULL, - DBUS_TYPE_STRING, &attributes, - 0); + AsyncCallQueryFsInfo *data; + + g_print ("g_daemon_file_query_filesystem_info_async\n"); + + data = g_new0 (AsyncCallQueryFsInfo, 1); + data->file = g_object_ref (file); + data->attributes = g_strdup (attributes); + data->io_priority = io_priority; + if (cancellable) + data->cancellable = g_object_ref (cancellable); + + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + query_info_fs_async_get_proxy_cb, + data, (GDestroyNotify) async_call_query_fs_info_free); } static GFileInfo * @@ -1958,6 +2243,7 @@ g_daemon_file_find_enclosing_mount (GFile *file, mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, daemon_file->path, + cancellable, error); if (mount_info == NULL) return NULL; @@ -1995,8 +2281,9 @@ g_daemon_file_get_child_for_display_name (GFile *file, GFile *child; mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec, - daemon_file->path, - NULL); + daemon_file->path, + NULL, /* TODO: cancellable */ + NULL); if (mount_info && mount_info->prefered_filename_encoding) @@ -2031,43 +2318,39 @@ g_daemon_file_set_display_name (GFile *file, { GDaemonFile *daemon_file; GMountInfo *mount_info; - DBusMessage *reply; - DBusMessageIter iter; char *new_path; + GVfsDBusMount *proxy; + char *path; + gboolean res; daemon_file = G_DAEMON_FILE (file); - mount_info = NULL; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME, - &mount_info, NULL, - cancellable, error, - DBUS_TYPE_STRING, &display_name, - 0); - if (reply == NULL) - { - if (mount_info) - g_mount_info_unref (mount_info); - return NULL; - } + g_print ("g_daemon_file_set_display_name\n"); - if (!dbus_message_iter_init (reply, &iter) || - !_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &new_path, - 0)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "query_filesystem_info"); - goto out; - } + proxy = create_proxy_for_file (file, &mount_info, &path, NULL, cancellable, error); + if (proxy == NULL) + return NULL; + + res = gvfs_dbus_mount_call_set_display_name_sync (proxy, + path, + display_name, + &new_path, + cancellable, + error); + g_print ("g_daemon_file_set_display_name: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + if (! res) + goto out; + g_mount_info_apply_prefix (mount_info, &new_path); file = new_file_for_new_path (daemon_file, new_path); g_free (new_path); out: g_mount_info_unref (mount_info); - dbus_message_unref (reply); return file; } @@ -2076,18 +2359,26 @@ g_daemon_file_delete (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + gboolean res; + + g_print ("g_daemon_file_delete\n"); - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_DELETE, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return FALSE; - dbus_message_unref (reply); - return TRUE; + res = gvfs_dbus_mount_call_delete_sync (proxy, + path, + cancellable, + error); + g_print ("g_daemon_file_delete: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + return res; } static gboolean @@ -2095,18 +2386,26 @@ g_daemon_file_trash (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + gboolean res; + + g_print ("g_daemon_file_trash\n"); - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_TRASH, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return FALSE; - dbus_message_unref (reply); - return TRUE; + res = gvfs_dbus_mount_call_trash_sync (proxy, + path, + cancellable, + error); + g_print ("g_daemon_file_trash: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + return res; } static gboolean @@ -2114,18 +2413,26 @@ g_daemon_file_make_directory (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + gboolean res; + + g_print ("g_daemon_file_make_directory\n"); - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return FALSE; - dbus_message_unref (reply); - return TRUE; + res = gvfs_dbus_mount_call_make_directory_sync (proxy, + path, + cancellable, + error); + g_print ("g_daemon_file_make_directory: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + return res; } static gboolean @@ -2134,19 +2441,27 @@ g_daemon_file_make_symbolic_link (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + gboolean res; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK, - NULL, NULL, - cancellable, error, - G_DBUS_TYPE_CSTRING, &symlink_value, - 0); - if (reply == NULL) + g_print ("g_daemon_file_make_symbolic_link\n"); + + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) return FALSE; - dbus_message_unref (reply); - return TRUE; + res = gvfs_dbus_mount_call_make_symbolic_link_sync (proxy, + path, + symlink_value, + cancellable, + error); + g_print ("g_daemon_file_make_symbolic_link: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + return res; } static GFileAttributeInfoList * @@ -2154,22 +2469,34 @@ g_daemon_file_query_settable_attributes (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + gboolean res; + GVariant *iter_list; GFileAttributeInfoList *list; - DBusMessageIter iter; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES, - NULL, NULL, - cancellable, error, - 0); - if (reply == NULL) + + g_print ("g_daemon_file_query_settable_attributes\n"); + + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) + return FALSE; + + iter_list = NULL; + res = gvfs_dbus_mount_call_query_settable_attributes_sync (proxy, + path, + &iter_list, + cancellable, + error); + g_print ("g_daemon_file_query_settable_attributes: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + if (!res) return NULL; - dbus_message_iter_init (reply, &iter); - list = _g_dbus_get_attribute_info_list (&iter, error); - - dbus_message_unref (reply); + list = _g_dbus_get_attribute_info_list (iter_list, error); + g_variant_unref (iter_list); return list; } @@ -2179,20 +2506,33 @@ g_daemon_file_query_writable_namespaces (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + gboolean res; + GVariant *iter_list; GFileAttributeInfoList *list; - DBusMessageIter iter; - - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES, - NULL, NULL, - cancellable, error, - 0); - if (reply) + + g_print ("g_daemon_file_query_writable_namespaces\n"); + + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) + return FALSE; + + iter_list = NULL; + res = gvfs_dbus_mount_call_query_writable_namespaces_sync (proxy, + path, + &iter_list, + cancellable, + error); + g_print ("g_daemon_file_query_writable_namespaces: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + if (res) { - dbus_message_iter_init (reply, &iter); - list = _g_dbus_get_attribute_info_list (&iter, error); - dbus_message_unref (reply); + list = _g_dbus_get_attribute_info_list (iter_list, error); + g_variant_unref (iter_list); } else { @@ -2200,11 +2540,11 @@ g_daemon_file_query_writable_namespaces (GFile *file, } g_file_attribute_info_list_add (list, - "metadata", - G_FILE_ATTRIBUTE_TYPE_STRING, /* Also STRINGV, but no way express this ... */ - G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | - G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); - + "metadata", + G_FILE_ATTRIBUTE_TYPE_STRING, /* Also STRINGV, but no way express this ... */ + G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | + G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); + return list; } @@ -2282,38 +2622,34 @@ g_daemon_file_set_attribute (GFile *file, GCancellable *cancellable, GError **error) { - DBusMessage *message, *reply; - DBusMessageIter iter; - dbus_uint32_t flags_dbus; + GVfsDBusMount *proxy; + char *path; + gboolean res; GError *my_error; if (g_str_has_prefix (attribute, "metadata::")) return set_metadata_attribute (file, attribute, type, value_p, cancellable, error); retry: - - message = create_empty_message (file, G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE, NULL, error); - if (!message) - return FALSE; - - dbus_message_iter_init_append (message, &iter); - - flags_dbus = flags; - dbus_message_iter_append_basic (&iter, - DBUS_TYPE_UINT32, - &flags_dbus); + g_print ("g_daemon_file_set_attribute\n"); - _g_dbus_append_file_attribute (&iter, attribute, 0, type, value_p); + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) + return FALSE; my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - NULL, - NULL, NULL, NULL, - cancellable, &my_error); + res = gvfs_dbus_mount_call_set_attribute_sync (proxy, + path, + flags, + _g_dbus_append_file_attribute (attribute, 0, type, value_p), + cancellable, + &my_error); + g_print ("g_daemon_file_set_attribute: done, res = %d\n", res); - dbus_message_unref (message); + g_free (path); + g_object_unref (proxy); - if (reply == NULL) + if (! res) { if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) { @@ -2324,38 +2660,28 @@ g_daemon_file_set_attribute (GFile *file, return FALSE; } - dbus_message_unref (reply); return TRUE; } -struct ProgressCallbackData { +typedef struct { GFileProgressCallback progress_callback; gpointer progress_callback_data; -}; +} ProgressCallbackData; -static DBusHandlerResult -progress_callback_message (DBusConnection *connection, - DBusMessage *message, - void *user_data) +static gboolean +handle_progress (GVfsDBusProgress *object, + GDBusMethodInvocation *invocation, + guint64 arg_current, + guint64 arg_total, + ProgressCallbackData *data) { - struct ProgressCallbackData *data = user_data; - dbus_uint64_t current_dbus, total_dbus; + g_print ("handle_progress\n"); - if (dbus_message_is_method_call (message, - G_VFS_DBUS_PROGRESS_INTERFACE, - G_VFS_DBUS_PROGRESS_OP_PROGRESS)) - { - if (dbus_message_get_args (message, NULL, - DBUS_TYPE_UINT64, ¤t_dbus, - DBUS_TYPE_UINT64, &total_dbus, - 0)) - data->progress_callback (current_dbus, total_dbus, data->progress_callback_data); - } - else - g_warning ("Unknown progress callback message type\n"); + data->progress_callback (arg_current, arg_total, data->progress_callback_data); + + gvfs_dbus_progress_complete_progress (object, invocation); - /* TODO: demarshal args and call reall callback */ - return DBUS_HANDLER_RESULT_HANDLED; + return TRUE; } static gboolean @@ -2368,17 +2694,23 @@ file_transfer (GFile *source, gpointer progress_callback_data, GError **error) { - DBusMessage *reply; - char *obj_path, *dbus_obj_path; - dbus_uint32_t flags_dbus; - dbus_bool_t dbus_remove_source; - struct ProgressCallbackData data; + char *obj_path; + ProgressCallbackData data; char *local_path = NULL; gboolean source_is_daemon; gboolean dest_is_daemon; gboolean native_transfer; gboolean send_progress; + GVfsDBusMount *proxy; + gchar *path1, *path2; + GDBusConnection *connection; + gboolean res; + GVfsDBusProgress *progress_skeleton; + GFile *file1, *file2; + GError *my_error; + res = FALSE; + progress_skeleton = NULL; native_transfer = FALSE; source_is_daemon = G_IS_DAEMON_FILE (source); dest_is_daemon = G_IS_DAEMON_FILE (destination); @@ -2408,76 +2740,126 @@ file_transfer (GFile *source, } if (progress_callback) + obj_path = g_strdup_printf ("/org/gtk/vfs/callback/%p", &obj_path); + else + obj_path = g_strdup ("/org/gtk/vfs/void"); + + data.progress_callback = progress_callback; + data.progress_callback_data = progress_callback_data; + + /* need to create proxy with daemon files only */ + if (native_transfer) { - obj_path = g_strdup_printf ("/org/gtk/vfs/callback/%p", &obj_path); - dbus_obj_path = obj_path; + file1 = source; + file2 = destination; } else { - obj_path = NULL; - /* Can't pass NULL obj path as arg */ - dbus_obj_path = "/org/gtk/vfs/void"; + if (dest_is_daemon) + { + file1 = destination; + file2 = NULL; + } + else + { + file1 = source; + file2 = NULL; + } } + +retry: + my_error = NULL; - data.progress_callback = progress_callback; - data.progress_callback_data = progress_callback_data; + proxy = create_proxy_for_file2 (file1, file2, + NULL, NULL, + &path1, &path2, + &connection, + cancellable, + &my_error); + + if (proxy == NULL) + goto out; + + /* Register progress interface skeleton */ + progress_skeleton = gvfs_dbus_progress_skeleton_new (); + g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (progress_skeleton), G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD); + g_signal_connect (progress_skeleton, "handle-progress", G_CALLBACK (handle_progress), &data); - flags_dbus = flags; - dbus_remove_source = remove_source; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (progress_skeleton), + connection, + obj_path, + &my_error)) + goto out; if (native_transfer == TRUE) { - const char *method_string; - if (remove_source == FALSE) - method_string = G_VFS_DBUS_MOUNT_OP_COPY; + { + res = gvfs_dbus_mount_call_copy_sync (proxy, + path1, path2, + flags, + obj_path, + cancellable, + &my_error); + } else - method_string = G_VFS_DBUS_MOUNT_OP_MOVE; - - reply = do_sync_2_path_call (source, destination, - method_string, - obj_path, progress_callback_message, &data, - NULL, cancellable, error, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_OBJECT_PATH, &dbus_obj_path, - 0); + { + res = gvfs_dbus_mount_call_move_sync (proxy, + path1, path2, + flags, + obj_path, + cancellable, + &my_error); + } } else if (dest_is_daemon == TRUE) { - reply = do_sync_2_path_call (destination, NULL, - G_VFS_DBUS_MOUNT_OP_PUSH, - obj_path, progress_callback_message, &data, - NULL, cancellable, error, - G_DBUS_TYPE_CSTRING, &local_path, - DBUS_TYPE_BOOLEAN, &send_progress, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_OBJECT_PATH, &dbus_obj_path, - DBUS_TYPE_BOOLEAN, &dbus_remove_source, - 0); + res = gvfs_dbus_mount_call_push_sync (proxy, + path1, + local_path, + send_progress, + flags, + obj_path, + remove_source, + cancellable, + &my_error); } else { - reply = do_sync_2_path_call (source, NULL, - G_VFS_DBUS_MOUNT_OP_PULL, - obj_path, progress_callback_message, &data, - NULL, cancellable, error, - G_DBUS_TYPE_CSTRING, &local_path, - DBUS_TYPE_BOOLEAN, &send_progress, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_OBJECT_PATH, &dbus_obj_path, - DBUS_TYPE_BOOLEAN, &dbus_remove_source, - 0); + res = gvfs_dbus_mount_call_pull_sync (proxy, + path1, + local_path, + send_progress, + flags, + obj_path, + remove_source, + cancellable, + &my_error); + } + out: + if (progress_skeleton) + { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (progress_skeleton)); + g_object_unref (progress_skeleton); + } + if (proxy) + g_object_unref (proxy); + + if (! res) + { + if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) + { + g_error_free (my_error); + goto retry; + } + g_propagate_error (error, my_error); } g_free (local_path); g_free (obj_path); - if (reply == NULL) - return FALSE; - - dbus_message_unref (reply); - return TRUE; + return res; } static gboolean @@ -2533,45 +2915,44 @@ g_daemon_file_monitor_dir (GFile* file, GError **error) { GFileMonitor *monitor; - char *obj_path; - dbus_uint32_t flags_dbus; GMountInfo *mount_info; - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + char *obj_path; + gboolean res; - flags_dbus = flags; + g_print ("g_daemon_file_monitor_dir\n"); + monitor = NULL; mount_info = NULL; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR, - &mount_info, NULL, - cancellable, error, - DBUS_TYPE_UINT32, &flags_dbus, - 0); - - if (reply == NULL) - { - if (mount_info) - g_mount_info_unref (mount_info); - return NULL; - } + obj_path = NULL; + + proxy = create_proxy_for_file (file, &mount_info, &path, NULL, cancellable, error); + if (proxy == NULL) + return FALSE; + - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_INVALID)) - { - g_mount_info_unref (mount_info); - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "monitor_dir"); - return NULL; - } + res = gvfs_dbus_mount_call_create_directory_monitor_sync (proxy, + path, + flags, + &obj_path, + cancellable, + error); + g_print ("g_daemon_file_monitor_dir: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + if (! res) + goto out; monitor = g_daemon_file_monitor_new (mount_info->dbus_id, obj_path); + out: g_mount_info_unref (mount_info); - dbus_message_unref (reply); - + g_free (obj_path); + return monitor; } @@ -2582,114 +2963,151 @@ g_daemon_file_monitor_file (GFile* file, GError **error) { GFileMonitor *monitor; - char *obj_path; - dbus_uint32_t flags_dbus; GMountInfo *mount_info; - DBusMessage *reply; + GVfsDBusMount *proxy; + char *path; + char *obj_path; + gboolean res; - flags_dbus = flags; + g_print ("g_daemon_file_monitor_file\n"); + monitor = NULL; mount_info = NULL; - reply = do_sync_path_call (file, - G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR, - &mount_info, NULL, - cancellable, error, - DBUS_TYPE_UINT32, &flags_dbus, - 0); - - if (reply == NULL) - { - if (mount_info) - g_mount_info_unref (mount_info); - return NULL; - } + obj_path = NULL; + + proxy = create_proxy_for_file (file, &mount_info, &path, NULL, cancellable, error); + if (proxy == NULL) + return FALSE; + - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_INVALID)) - { - g_mount_info_unref (mount_info); - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "monitor_file"); - return NULL; - } + res = gvfs_dbus_mount_call_create_file_monitor_sync (proxy, + path, + flags, + &obj_path, + cancellable, + error); + g_print ("g_daemon_file_monitor_file: done, res = %d\n", res); + + g_free (path); + g_object_unref (proxy); + + if (! res) + goto out; monitor = g_daemon_file_monitor_new (mount_info->dbus_id, - obj_path); + obj_path); + out: g_mount_info_unref (mount_info); - dbus_message_unref (reply); - + g_free (obj_path); + return monitor; } -typedef struct -{ - GSimpleAsyncResult *result; - GCancellable *cancellable; - dbus_bool_t can_seek; - guint64 initial_offset; -} -StreamOpenParams; static void -stream_open_cb (gint fd, StreamOpenParams *params) +file_open_write_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { + AsyncCallFileReadWrite *data = user_data; + GError *error = NULL; + GSimpleAsyncResult *orig_result; + gboolean can_seek; + GUnixFDList *fd_list; + int fd; + guint fd_id; + guint64 initial_offset; GFileOutputStream *output_stream; - if (fd == -1) + g_print ("file_open_write_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_open_for_write_finish (proxy, &fd_id, &can_seek, &initial_offset, &fd_list, res, &error)) { - g_simple_async_result_set_error (params->result, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", _("Didn't get stream file descriptor")); + g_simple_async_result_take_error (orig_result, error); goto out; } - output_stream = g_daemon_file_output_stream_new (fd, params->can_seek, params->initial_offset); - g_simple_async_result_set_op_res_gpointer (params->result, output_stream, g_object_unref); + if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || + (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1) + { + g_simple_async_result_set_error (orig_result, + G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn't get stream file descriptor")); + } + else + { + output_stream = g_daemon_file_output_stream_new (fd, can_seek, initial_offset); + g_simple_async_result_set_op_res_gpointer (orig_result, output_stream, g_object_unref); + g_object_unref (fd_list); + } out: - _g_simple_async_result_complete_with_cancellable (params->result, params->cancellable); - if (params->cancellable) - g_object_unref (params->cancellable); - g_object_unref (params->result); - g_slice_free (StreamOpenParams, params); + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ } static void -append_to_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +file_open_write_async_get_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) { - guint32 fd_id; - StreamOpenParams *open_params; + AsyncCallFileReadWrite *data = callback_data; + guint32 pid; - open_params = g_slice_new0 (StreamOpenParams); + g_print ("file_open_write_async_get_proxy_cb, proxy = %p\n", proxy); - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &open_params->can_seek, - DBUS_TYPE_UINT64, &open_params->initial_offset, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - goto failure; - } + pid = get_pid_for_file (data->file); + + data->result = g_object_ref (result); + + gvfs_dbus_mount_call_open_for_write (proxy, + path, + data->mode, + data->etag, + data->make_backup, + data->flags, + pid, + NULL, + cancellable, + (GAsyncReadyCallback) file_open_write_async_cb, + data); +} - open_params->result = g_object_ref (result); +static void +file_open_write_async (GFile *file, + guint16 mode, + const char *etag, + gboolean make_backup, + GFileCreateFlags flags, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncCallFileReadWrite *data; + + data = g_new0 (AsyncCallFileReadWrite, 1); + data->file = g_object_ref (file); + data->mode = mode; + data->etag = g_strdup (etag ? etag : ""); + data->make_backup = make_backup; + data->io_priority = io_priority; if (cancellable) - open_params->cancellable = g_object_ref (cancellable); - _g_dbus_connection_get_fd_async (connection, fd_id, - (GetFdAsyncCallback) stream_open_cb, open_params); - return; + data->cancellable = g_object_ref (cancellable); -failure: - g_slice_free (StreamOpenParams, open_params); - _g_simple_async_result_complete_with_cancellable (result, cancellable); + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + file_open_write_async_get_proxy_cb, + data, (GDestroyNotify) async_call_file_read_write_free); } static void @@ -2700,30 +3118,12 @@ g_daemon_file_append_to_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - guint16 mode; - dbus_bool_t make_backup; - guint32 dbus_flags; - char *etag; - guint32 pid; - - pid = get_pid_for_file (file); - - mode = 1; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; + g_print ("g_daemon_file_append_to_async\n"); - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - cancellable, - callback, user_data, - append_to_async_cb, NULL, NULL, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_UINT32, &pid, - 0); + file_open_write_async (file, + 1, "", FALSE, flags, io_priority, + cancellable, + callback, user_data); } static GFileOutputStream * @@ -2742,40 +3142,6 @@ g_daemon_file_append_to_finish (GFile *file, } static void -create_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - StreamOpenParams *open_params; - - open_params = g_slice_new0 (StreamOpenParams); - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &open_params->can_seek, - DBUS_TYPE_UINT64, &open_params->initial_offset, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - goto failure; - } - - open_params->result = g_object_ref (result); - _g_dbus_connection_get_fd_async (connection, fd_id, - (GetFdAsyncCallback) stream_open_cb, open_params); - return; - -failure: - g_slice_free (StreamOpenParams, open_params); - _g_simple_async_result_complete_with_cancellable (result, cancellable); -} - -static void g_daemon_file_create_async (GFile *file, GFileCreateFlags flags, int io_priority, @@ -2783,30 +3149,12 @@ g_daemon_file_create_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - guint16 mode; - dbus_bool_t make_backup; - char *etag; - guint32 dbus_flags; - guint32 pid; - - pid = get_pid_for_file (file); - - mode = 0; - etag = ""; - make_backup = FALSE; - dbus_flags = flags; + g_print ("g_daemon_file_create_async\n"); - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - cancellable, - callback, user_data, - create_async_cb, NULL, NULL, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_UINT32, &pid, - 0); + file_open_write_async (file, + 0, "", FALSE, flags, io_priority, + cancellable, + callback, user_data); } static GFileOutputStream * @@ -2824,29 +3172,95 @@ g_daemon_file_create_finish (GFile *file, return NULL; } + +typedef struct { + GFile *file; + char *attributes; + GFileQueryInfoFlags flags; + int io_priority; + GSimpleAsyncResult *result; + GCancellable *cancellable; + GDaemonFileEnumerator *enumerator; +} AsyncCallEnumerate; + static void -enumerate_children_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +async_call_enumerate_free (AsyncCallEnumerate *data) { - GDaemonFileEnumerator *enumerator = callback_data; + g_print ("async_call_enumerate_free\n"); + + if (data->file) + g_object_unref (data->file); + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + if (data->enumerator) + g_object_unref (data->enumerator); + g_free (data->attributes); + g_free (data); +} - if (reply == NULL || connection == NULL) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "enumerate_children"); - goto out; - } +static void +enumerate_children_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) +{ + AsyncCallEnumerate *data = user_data; + GError *error = NULL; + GSimpleAsyncResult *orig_result; - g_object_ref (enumerator); + g_print ("enumerate_children_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_enumerate_finish (proxy, res, &error)) + { + g_simple_async_result_take_error (orig_result, error); + goto out; + } + + g_object_ref (data->enumerator); - g_simple_async_result_set_op_res_gpointer (result, enumerator, g_object_unref); + g_simple_async_result_set_op_res_gpointer (orig_result, data->enumerator, g_object_unref); out: - _g_simple_async_result_complete_with_cancellable (result, cancellable); + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ +} + +static void +enumerate_children_async_get_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncCallEnumerate *data = callback_data; + char *obj_path; + char *uri; + + g_print ("enumerate_children_async_get_proxy_cb, proxy = %p\n", proxy); + + obj_path = g_daemon_file_enumerator_get_object_path (data->enumerator); + uri = g_file_get_uri (data->file); + + data->result = g_object_ref (result); + + gvfs_dbus_mount_call_enumerate (proxy, + path, + obj_path, + data->attributes ? data->attributes : "", + data->flags, + uri, + cancellable, + (GAsyncReadyCallback) enumerate_children_async_cb, + data); + + g_free (uri); + g_free (obj_path); } static void @@ -2858,31 +3272,24 @@ g_daemon_file_enumerate_children_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - dbus_uint32_t flags_dbus; - char *obj_path; - GDaemonFileEnumerator *enumerator; - char *uri; + AsyncCallEnumerate *data; - enumerator = g_daemon_file_enumerator_new (file, attributes); - obj_path = g_daemon_file_enumerator_get_object_path (enumerator); + g_print ("g_daemon_file_enumerate_children_async\n"); - uri = g_file_get_uri (file); + data = g_new0 (AsyncCallEnumerate, 1); + data->file = g_object_ref (file); + data->attributes = g_strdup (attributes); + data->flags = flags; + data->io_priority = io_priority; + if (cancellable) + data->cancellable = g_object_ref (cancellable); + data->enumerator = g_daemon_file_enumerator_new (data->file, data->attributes); - if (attributes == NULL) - attributes = ""; - flags_dbus = flags; - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_ENUMERATE, - cancellable, - callback, user_data, - enumerate_children_async_cb, enumerator, g_object_unref, - DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags_dbus, - DBUS_TYPE_STRING, &uri, - 0); - g_free (uri); - g_free (obj_path); + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + enumerate_children_async_get_proxy_cb, + data, (GDestroyNotify) async_call_enumerate_free); } static GFileEnumerator * @@ -3007,40 +3414,6 @@ g_daemon_file_find_enclosing_mount_finish (GFile *file, } static void -replace_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) -{ - guint32 fd_id; - StreamOpenParams *open_params; - - open_params = g_slice_new0 (StreamOpenParams); - - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &open_params->can_seek, - DBUS_TYPE_UINT64, &open_params->initial_offset, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - goto failure; - } - - open_params->result = g_object_ref (result); - _g_dbus_connection_get_fd_async (connection, fd_id, - (GetFdAsyncCallback) stream_open_cb, open_params); - return; - -failure: - g_slice_free (StreamOpenParams, open_params); - _g_simple_async_result_complete_with_cancellable (result, cancellable); -} - -static void g_daemon_file_replace_async (GFile *file, const char *etag, gboolean make_backup, @@ -3050,27 +3423,12 @@ g_daemon_file_replace_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - dbus_bool_t dbus_make_backup = make_backup; - guint32 dbus_flags = flags; - guint16 mode = 2; - guint32 pid; - - pid = get_pid_for_file (file); + g_print ("g_daemon_file_replace_async\n"); - if (etag == NULL) - etag = ""; - - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE, - cancellable, - callback, user_data, - replace_async_cb, NULL, NULL, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &dbus_make_backup, - DBUS_TYPE_UINT32, &dbus_flags, - DBUS_TYPE_UINT32, &pid, - 0); + file_open_write_async (file, + 2, etag, make_backup, flags, io_priority, + cancellable, + callback, user_data); } static GFileOutputStream * @@ -3088,38 +3446,86 @@ g_daemon_file_replace_finish (GFile *file, return NULL; } +typedef struct { + GFile *file; + char *display_name; + int io_priority; + GMountInfo *mount_info; + GSimpleAsyncResult *result; + GCancellable *cancellable; +} AsyncCallSetDisplayName; + +static void +async_call_set_display_name_free (AsyncCallSetDisplayName *data) +{ + if (data->file) + g_object_unref (data->file); + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + if (data->mount_info) + g_mount_info_unref (data->mount_info); + g_free (data->display_name); + g_free (data); +} + static void -set_display_name_async_cb (DBusMessage *reply, - DBusConnection *connection, - GMountInfo *mount_info, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +set_display_name_async_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - GDaemonFile *daemon_file = callback_data; + AsyncCallSetDisplayName *data = user_data; GFile *file; - DBusMessageIter iter; + GError *error = NULL; gchar *new_path; + GSimpleAsyncResult *orig_result; - if (!dbus_message_iter_init (reply, &iter) || - !_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &new_path, - 0)) + g_print ("set_display_name_async_cb\n"); + orig_result = data->result; + + if (! gvfs_dbus_mount_call_set_display_name_finish (proxy, &new_path, res, &error)) { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "set_display_name"); + g_simple_async_result_take_error (orig_result, error); goto out; } - g_mount_info_apply_prefix (mount_info, &new_path); - file = new_file_for_new_path (daemon_file, new_path); + g_mount_info_apply_prefix (data->mount_info, &new_path); + file = new_file_for_new_path (G_DAEMON_FILE (data->file), new_path); g_free (new_path); - g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref); + g_simple_async_result_set_op_res_gpointer (orig_result, file, g_object_unref); -out: - _g_simple_async_result_complete_with_cancellable (result, cancellable); + out: + _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable); + data->result = NULL; + g_object_unref (orig_result); /* trigger async_proxy_create_free() */ +} + +static void +set_display_name_async_get_proxy_cb (GVfsDBusMount *proxy, + GDBusConnection *connection, + GMountInfo *mount_info, + const gchar *path, + GSimpleAsyncResult *result, + GError *error, + GCancellable *cancellable, + gpointer callback_data) +{ + AsyncCallSetDisplayName *data = callback_data; + + g_print ("set_display_name_async_get_proxy_cb, proxy = %p\n", proxy); + + data->result = g_object_ref (result); + data->mount_info = g_mount_info_ref (mount_info); + + gvfs_dbus_mount_call_set_display_name (proxy, + path, + data->display_name, + cancellable, + (GAsyncReadyCallback) set_display_name_async_cb, + data); } static void @@ -3130,15 +3536,22 @@ g_daemon_file_set_display_name_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - g_object_ref (file); + AsyncCallSetDisplayName *data; + + g_print ("g_daemon_file_set_display_name_async\n"); + + data = g_new0 (AsyncCallSetDisplayName, 1); + data->file = g_object_ref (file); + data->display_name = g_strdup (display_name); + data->io_priority = io_priority; + if (cancellable) + data->cancellable = g_object_ref (cancellable); - do_async_path_call (file, - G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME, - cancellable, - callback, user_data, - set_display_name_async_cb, file, g_object_unref, - DBUS_TYPE_STRING, &display_name, - 0); + create_proxy_for_file_async (file, + cancellable, + callback, user_data, + set_display_name_async_get_proxy_cb, + data, (GDestroyNotify) async_call_set_display_name_free); } static GFile * diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c index 9e8722a2..80502f71 100644 --- a/client/gdaemonfileenumerator.c +++ b/client/gdaemonfileenumerator.c @@ -32,6 +32,7 @@ #include <gvfsdaemonprotocol.h> #include "gdaemonfile.h" #include "metatree.h" +#include <gvfsdbus.h> #define OBJ_PATH_PREFIX "/org/gtk/vfs/client/enumerator/" @@ -45,7 +46,7 @@ struct _GDaemonFileEnumerator GFileEnumerator parent; gint id; - DBusConnection *sync_connection; /* NULL if async, i.e. we're listening on main dbus connection */ + GDBusConnection *sync_connection; /* NULL if async, i.e. we're listening on main dbus connection */ /* protected by infos lock */ GList *infos; @@ -56,6 +57,9 @@ struct _GDaemonFileEnumerator gulong cancelled_tag; guint timeout_tag; GSimpleAsyncResult *async_res; + GMainLoop *next_files_mainloop; + guint next_files_sync_timeout_tag; + GMutex next_files_mutex; GFileAttributeMatcher *matcher; MetaTree *metadata_tree; @@ -86,9 +90,8 @@ static void g_daemon_file_enumerator_close_async (GFileEnumerator static gboolean g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator, GAsyncResult *result, GError **error); -static DBusHandlerResult g_daemon_file_enumerator_dbus_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data); +static void trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok); + static void free_info_list (GList *infos) @@ -105,6 +108,8 @@ g_daemon_file_enumerator_finalize (GObject *object) daemon = G_DAEMON_FILE_ENUMERATOR (object); + g_print ("g_daemon_file_enumerator_finalize: daemon = %p\n", daemon); + path = g_daemon_file_enumerator_get_object_path (daemon); _g_dbus_unregister_vfs_filter (path); g_free (path); @@ -116,7 +121,9 @@ g_daemon_file_enumerator_finalize (GObject *object) meta_tree_unref (daemon->metadata_tree); if (daemon->sync_connection) - dbus_connection_unref (daemon->sync_connection); + g_object_unref (daemon->sync_connection); + + g_mutex_clear (&daemon->next_files_mutex); if (G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) (*G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) (object); @@ -140,14 +147,127 @@ g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass) } static void +next_files_sync_check (GDaemonFileEnumerator *enumerator) +{ + g_print ("next_files_sync_check: enumerator->infos = %p, enumerator->done = %d, loop = %p, daemon = %p\n", enumerator->infos, enumerator->done, enumerator->next_files_mainloop, enumerator); + + g_mutex_lock (&enumerator->next_files_mutex); + if ((enumerator->infos || enumerator->done) && + enumerator->next_files_mainloop != NULL) + { + g_print ("next_files_sync_check: calling quit\n"); + g_main_loop_quit (enumerator->next_files_mainloop); + } + g_mutex_unlock (&enumerator->next_files_mutex); +} + +static gboolean +handle_done (GVfsDBusEnumerator *object, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GDaemonFileEnumerator *enumerator = user_data; + + g_print ("handle_done: daemon = %p, async_requested_files = %d\n", enumerator, enumerator->async_requested_files); + + G_LOCK (infos); + enumerator->done = TRUE; + if (enumerator->async_requested_files > 0) + trigger_async_done (enumerator, TRUE); + next_files_sync_check (enumerator); + G_UNLOCK (infos); + + gvfs_dbus_enumerator_complete_done (object, invocation); + + return TRUE; +} + +static gboolean +handle_got_info (GVfsDBusEnumerator *object, + GDBusMethodInvocation *invocation, + GVariant *arg_infos, + gpointer user_data) +{ + GDaemonFileEnumerator *enumerator = user_data; + GList *infos; + GFileInfo *info; + GVariantIter iter; + GVariant *child; + + g_print ("handle_got_info: daemon = %p\n", enumerator); + + infos = NULL; + + g_variant_iter_init (&iter, arg_infos); + while ((child = g_variant_iter_next_value (&iter))) + { + info = _g_dbus_get_file_info (child, NULL); + if (info) + g_assert (G_IS_FILE_INFO (info)); + + if (info) + infos = g_list_prepend (infos, info); + + g_variant_unref (child); + } + + infos = g_list_reverse (infos); + + G_LOCK (infos); + enumerator->infos = g_list_concat (enumerator->infos, infos); + if (enumerator->async_requested_files > 0 && + g_list_length (enumerator->infos) >= enumerator->async_requested_files) + trigger_async_done (enumerator, TRUE); + next_files_sync_check (enumerator); + G_UNLOCK (infos); + + gvfs_dbus_enumerator_complete_got_info (object, invocation); + + return TRUE; +} + +static GDBusInterfaceSkeleton * +register_vfs_filter_cb (GDBusConnection *connection, + const char *obj_path, + gpointer callback_data) +{ + GError *error; + GVfsDBusEnumerator *skeleton; + + skeleton = gvfs_dbus_enumerator_skeleton_new (); + g_signal_connect (skeleton, "handle-done", G_CALLBACK (handle_done), callback_data); + g_signal_connect (skeleton, "handle-got-info", G_CALLBACK (handle_got_info), callback_data); + + g_print ("register_vfs_filter_cb: callback_data = %p, skeleton = %p, obj_path = '%s'\n", callback_data, skeleton, obj_path); + + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), + connection, + obj_path, + &error)) + { + g_warning ("Error registering path: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + + return G_DBUS_INTERFACE_SKELETON (skeleton); +} + +static void g_daemon_file_enumerator_init (GDaemonFileEnumerator *daemon) { char *path; daemon->id = g_atomic_int_add (&path_counter, 1); + g_mutex_init (&daemon->next_files_mutex); + path = g_daemon_file_enumerator_get_object_path (daemon); - _g_dbus_register_vfs_filter (path, g_daemon_file_enumerator_dbus_filter, + g_print ("g_daemon_file_enumerator_init: daemon = %p, obj_path = '%s'\n", daemon, path); + + _g_dbus_register_vfs_filter (path, + register_vfs_filter_cb, G_OBJECT (daemon)); g_free (path); } @@ -243,7 +363,7 @@ static void trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok) { GList *rest, *l; - + if (daemon->cancelled_tag != 0) { GCancellable *cancellable = simple_async_result_get_cancellable (daemon->async_res); @@ -309,65 +429,6 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok) daemon->async_res = NULL; } -static DBusHandlerResult -g_daemon_file_enumerator_dbus_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - GDaemonFileEnumerator *enumerator = user_data; - const char *member; - DBusMessageIter iter, array_iter; - GList *infos; - GFileInfo *info; - - member = dbus_message_get_member (message); - - if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_DONE) == 0) - { - G_LOCK (infos); - enumerator->done = TRUE; - if (enumerator->async_requested_files > 0) - trigger_async_done (enumerator, TRUE); - G_UNLOCK (infos); - return DBUS_HANDLER_RESULT_HANDLED; - } - else if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO) == 0) - { - infos = NULL; - - dbus_message_iter_init (message, &iter); - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY && - dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_STRUCT) - { - dbus_message_iter_recurse (&iter, &array_iter); - - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) - { - info = _g_dbus_get_file_info (&array_iter, NULL); - if (info) - g_assert (G_IS_FILE_INFO (info)); - - if (info) - infos = g_list_prepend (infos, info); - - dbus_message_iter_next (&iter); - } - } - - infos = g_list_reverse (infos); - - G_LOCK (infos); - enumerator->infos = g_list_concat (enumerator->infos, infos); - if (enumerator->async_requested_files > 0 && - g_list_length (enumerator->infos) >= enumerator->async_requested_files) - trigger_async_done (enumerator, TRUE); - G_UNLOCK (infos); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - char * g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator) { @@ -376,9 +437,23 @@ g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator) void g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator, - DBusConnection *connection) + GDBusConnection *connection) { - enumerator->sync_connection = dbus_connection_ref (connection); + enumerator->sync_connection = g_object_ref (connection); +} + +static gboolean +sync_timeout (gpointer data) +{ + GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (data); + + g_print ("sync_timeout\n"); + + g_mutex_lock (&daemon->next_files_mutex); + g_main_loop_quit (daemon->next_files_mainloop); + g_mutex_unlock (&daemon->next_files_mutex); + + return FALSE; } static GFileInfo * @@ -388,71 +463,61 @@ g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, { GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); GFileInfo *info; - gboolean done; - int count; - info = NULL; - done = FALSE; - count = 0; - while (count++ < G_VFS_DBUS_TIMEOUT_MSECS / 100) + if (daemon->sync_connection == NULL) { - G_LOCK (infos); - if (daemon->infos) - { - done = TRUE; - info = daemon->infos->data; - if (info) - { - g_assert (G_IS_FILE_INFO (info)); - add_metadata (G_FILE_INFO (info), daemon); - } - daemon->infos = g_list_delete_link (daemon->infos, daemon->infos); - } - else if (daemon->done) - done = TRUE; - G_UNLOCK (infos); + /* The enumerator was initialized by an async call, so responses will + come to the async dbus connection. We can't pump that as that would + cause all sort of filters and stuff to run, possibly on the wrong + thread. If you want to do async next_files you must create the + enumerator asynchrounously. + */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Can't do synchronous next_files() on a file enumerator created asynchronously"); + return NULL; + } - if (info) - g_assert (G_IS_FILE_INFO (info)); + g_print ("g_daemon_file_enumerator_next_file: done = %d\n", daemon->done); + + if (! daemon->infos && ! daemon->done) + { + /* Wait for incoming data */ + daemon->next_files_sync_timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS, + sync_timeout, daemon); + + g_mutex_lock (&daemon->next_files_mutex); + g_print ("g_daemon_file_enumerator_next_file: starting loop, daemon = %p\n", daemon); + daemon->next_files_mainloop = g_main_loop_new (NULL, FALSE); + g_mutex_unlock (&daemon->next_files_mutex); - if (done) - break; + g_main_loop_run (daemon->next_files_mainloop); + + g_mutex_lock (&daemon->next_files_mutex); + g_print ("g_daemon_file_enumerator_next_file: loop done.\n"); + g_source_remove (daemon->next_files_sync_timeout_tag); + g_main_loop_unref (daemon->next_files_mainloop); + daemon->next_files_mainloop = NULL; + g_mutex_unlock (&daemon->next_files_mutex); + } + + info = NULL; - /* We sleep only 100 msecs here, not the full time because we might have - * raced with the filter func being called after unlocking - * and setting done or ->infos. So, we want to check it again reasonaby soon. - */ - if (daemon->sync_connection != NULL) - { - /* The initializing call for the enumerator was a sync one, and we - have a reference to its private connection. In order to ensure we - get the responses sent to that originating connection we pump it - here. - This should be safe as we're either on the thread that did the call - so its our connection, or its the private connection for another - thread. If that thread is idle the pumping won't affect anything, and - if it is doing something thats ok to, because we don't use filters - on the private sync connections so we won't cause any reentrancy - (except the file enumerator filter, but that is safe to run in - some other thread). - */ - if (!dbus_connection_read_write_dispatch (daemon->sync_connection, 100)) - break; - } - else - { - /* The enumerator was initialized by an async call, so responses will - come to the async dbus connection. We can't pump that as that would - cause all sort of filters and stuff to run, possibly on the wrong - thread. If you want to do async next_files you must create the - enumerator asynchrounously. - */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't do synchronous next_files() on a file enumerator created asynchronously"); - return NULL; - } + G_LOCK (infos); + if (daemon->infos) + { + info = daemon->infos->data; + if (info) + { + g_assert (G_IS_FILE_INFO (info)); + add_metadata (G_FILE_INFO (info), daemon); + } + daemon->infos = g_list_delete_link (daemon->infos, daemon->infos); } + G_UNLOCK (infos); + if (info) + g_assert (G_IS_FILE_INFO (info)); + return info; } diff --git a/client/gdaemonfileenumerator.h b/client/gdaemonfileenumerator.h index 17e7ddbe..32c61609 100644 --- a/client/gdaemonfileenumerator.h +++ b/client/gdaemonfileenumerator.h @@ -24,7 +24,6 @@ #define __G_DAEMON_FILE_ENUMERATOR_H__ #include <gio/gio.h> -#include <dbus/dbus.h> G_BEGIN_DECLS @@ -50,7 +49,7 @@ GDaemonFileEnumerator *g_daemon_file_enumerator_new (GFile *file const char *attributes); char * g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator); void g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator, - DBusConnection *connection); + GDBusConnection *connection); G_END_DECLS diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c index f1b82a7d..1104f9b6 100644 --- a/client/gdaemonmount.c +++ b/client/gdaemonmount.c @@ -31,10 +31,9 @@ #include "gdaemonmount.h" #include "gvfsdaemondbus.h" #include "gdaemonfile.h" -#include "gvfsdaemonprotocol.h" -#include "gvfsdbusutils.h" #include "gmountsource.h" #include "gmountoperationdbus.h" +#include <gvfsdbus.h> /* Protects all fields of GDaemonMount that can change which at this point is just foreign_volume */ @@ -173,19 +172,148 @@ g_daemon_mount_can_eject (GMount *mount) return FALSE; } + +typedef struct { + GMount *mount; + GCancellable *cancellable; + GSimpleAsyncResult *result; + GMountInfo *mount_info; + GMountOperation *mount_operation; + GMountUnmountFlags flags; + GDBusConnection *connection; + GVfsDBusMount *proxy; +} AsyncProxyCreate; + +static void +async_proxy_create_free (AsyncProxyCreate *data) +{ + if (data->mount) + g_object_unref (data->mount); + if (data->result) + g_object_unref (data->result); + if (data->cancellable) + g_object_unref (data->cancellable); + if (data->mount_operation) + g_object_unref (data->mount_operation); + if (data->connection) + g_object_unref (data->connection); + if (data->proxy) + g_object_unref (data->proxy); + g_free (data); +} + +static void +unmount_reply (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) +{ + AsyncProxyCreate *data = user_data; + GError *error = NULL; + + g_print ("gdaemonmount.c: unmount_reply, proxy = %p\n", proxy); + + if (! gvfs_dbus_mount_call_unmount_finish (proxy, res, &error)) + { + g_simple_async_result_take_error (data->result, error); + } + + _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); + async_proxy_create_free (data); +} + +static void +async_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + AsyncProxyCreate *data = user_data; + GVfsDBusMount *proxy; + GError *error = NULL; + GMountSource *mount_source; + + proxy = gvfs_dbus_mount_proxy_new_finish (res, &error); + g_print ("gdaemonmount.c: async_proxy_new_cb, proxy = %p\n", proxy); + if (proxy == NULL) + { + g_simple_async_result_take_error (data->result, error); + _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); + async_proxy_create_free (data); + return; + } + + data->proxy = proxy; + _g_dbus_connect_vfs_filters (data->connection); + + mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ()); + + gvfs_dbus_mount_call_unmount (proxy, + g_mount_source_get_dbus_id (mount_source), + g_mount_source_get_obj_path (mount_source), + data->flags, + data->cancellable, + (GAsyncReadyCallback) unmount_reply, + data); + + g_object_unref (mount_source); +} + +static void +async_construct_proxy (GDBusConnection *connection, + AsyncProxyCreate *data) +{ + data->connection = g_object_ref (connection); + gvfs_dbus_mount_proxy_new (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + data->mount_info->dbus_id, + data->mount_info->object_path, + data->cancellable, + async_proxy_new_cb, + data); +} + static void -unmount_reply (DBusMessage *reply, - DBusConnection *connection, - GError *io_error, - gpointer _data) +bus_get_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - GSimpleAsyncResult *result = _data; + AsyncProxyCreate *data = user_data; + GDBusConnection *connection; + GError *error = NULL; + + connection = g_bus_get_finish (res, &error); + + if (connection == NULL) + { + g_simple_async_result_set_from_error (data->result, error); + _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); + async_proxy_create_free (data); + return; + } + + async_construct_proxy (connection, data); +} - if (io_error != NULL) - g_simple_async_result_set_from_error (result, io_error); +static void +async_got_connection_cb (GDBusConnection *connection, + GError *io_error, + gpointer callback_data) +{ + AsyncProxyCreate *data = callback_data; + + g_print ("gdaemonmount.c: async_got_connection_cb, connection = %p\n", connection); + + if (connection == NULL) + { + /* TODO: we should probably test if we really want a session bus; + * for now, this code is on par with the old dbus code */ + g_bus_get (G_BUS_TYPE_SESSION, + data->cancellable, + bus_get_cb, + data); + return; + } - g_simple_async_result_complete (result); - g_object_unref (result); + async_construct_proxy (connection, data); } static void @@ -197,42 +325,26 @@ g_daemon_mount_unmount_with_operation (GMount *mount, gpointer user_data) { GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount); - DBusMessage *message; - GMountInfo *mount_info; - GSimpleAsyncResult *res; - guint32 dbus_flags; - GMountSource *mount_source; - const char *dbus_id, *obj_path; + AsyncProxyCreate *data; - mount_info = daemon_mount->mount_info; + g_print ("g_daemon_mount_unmount_with_operation\n"); - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_UNMOUNT); + data = g_new0 (AsyncProxyCreate, 1); + data->mount = g_object_ref (mount); + data->mount_info = daemon_mount->mount_info; + data->mount_operation = g_object_ref (mount_operation); + data->flags = flags; + if (cancellable) + data->cancellable = g_object_ref (cancellable); - mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ()); - dbus_id = g_mount_source_get_dbus_id (mount_source); - obj_path = g_mount_source_get_obj_path (mount_source); - - dbus_flags = flags; - _g_dbus_message_append_args (message, - DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_UINT32, &dbus_flags, - 0); - - res = g_simple_async_result_new (G_OBJECT (mount), - callback, user_data, - g_daemon_mount_unmount_with_operation); - - _g_vfs_daemon_call_async (message, - unmount_reply, res, - cancellable); + data->result = g_simple_async_result_new (G_OBJECT (mount), + callback, user_data, + g_daemon_mount_unmount_with_operation); - dbus_message_unref (message); - - g_object_unref (mount_source); + _g_dbus_connection_get_for_async (data->mount_info->dbus_id, + async_got_connection_cb, + data, + data->cancellable); } static gboolean diff --git a/client/gdaemonvfs.c b/client/gdaemonvfs.c index 6930a284..0bdee720 100644 --- a/client/gdaemonvfs.c +++ b/client/gdaemonvfs.c @@ -25,15 +25,12 @@ #include <signal.h> #include <stdlib.h> #include <errno.h> -#include <dbus/dbus.h> #include "gdaemonvfs.h" #include "gvfsuriutils.h" #include "gdaemonfile.h" #include <gio/gio.h> #include <gvfsdaemonprotocol.h> #include <gmodule.h> -#include "gvfsdaemondbus.h" -#include "gvfsdbusutils.h" #include "gmountspec.h" #include "gvfsurimapper.h" #include "gdaemonvolumemonitor.h" @@ -41,6 +38,7 @@ #include "gvfsiconloadable.h" #include <glib/gi18n-lib.h> #include <glib/gstdio.h> +#include <gvfsdbus.h> typedef struct { char *type; @@ -54,7 +52,7 @@ struct _GDaemonVfs { GVfs parent; - DBusConnection *async_bus; + GDBusConnection *async_bus; GVfs *wrapped_vfs; GList *mount_cache; @@ -101,10 +99,7 @@ g_daemon_vfs_finalize (GObject *object) g_strfreev (vfs->supported_uri_schemes); if (vfs->async_bus) - { - dbus_connection_close (vfs->async_bus); - dbus_connection_unref (vfs->async_bus); - } + g_object_unref (vfs->async_bus); if (vfs->wrapped_vfs) g_object_unref (vfs->wrapped_vfs); @@ -302,9 +297,7 @@ g_daemon_vfs_init (GDaemonVfs *vfs) bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - dbus_threads_init_default (); - - vfs->async_bus = dbus_bus_get_private (DBUS_BUS_SESSION, NULL); + vfs->async_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (vfs->async_bus == NULL) return; /* Not supported, return here and return false in vfs_is_active() */ @@ -336,9 +329,7 @@ g_daemon_vfs_init (GDaemonVfs *vfs) vfs->fuse_root = g_vfs_get_file_for_path (vfs->wrapped_vfs, file); g_free (file); - dbus_connection_set_exit_on_disconnect (vfs->async_bus, FALSE); - - _g_dbus_connection_integrate_with_main (vfs->async_bus); + g_dbus_connection_set_exit_on_close (vfs->async_bus, FALSE); modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR); @@ -611,107 +602,101 @@ find_string (GPtrArray *array, const char *find_me) return -1; } +static GVfsDBusMountTracker * +create_mount_tracker_proxy () +{ + GVfsDBusMountTracker *proxy; + GError *error; + + error = NULL; + proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + G_VFS_DBUS_DAEMON_NAME, + G_VFS_DBUS_MOUNTTRACKER_PATH, + NULL, + &error); + if (proxy == NULL) + { + g_printerr ("Error creating proxy: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + + return proxy; +} static void fill_mountable_info (GDaemonVfs *vfs) { - DBusMessage *message, *reply; - DBusError error; - DBusMessageIter iter, array_iter, struct_iter; MountableInfo *info; GPtrArray *infos, *uri_schemes; gint i; - - 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_MOUNTABLE_INFO); - - if (message == NULL) - _g_dbus_oom (); - - dbus_message_set_auto_start (message, TRUE); - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (vfs->async_bus, - message, - G_VFS_DBUS_TIMEOUT_MSECS, - &error); - dbus_message_unref (message); + GVfsDBusMountTracker *proxy; + GVariant *iter_mountables; + GError *error; + GVariantIter iter; + const gchar *type, *scheme, **scheme_aliases; + guint scheme_aliases_len; + gint32 default_port; + gboolean host_is_inet; - if (dbus_error_is_set (&error)) + proxy = create_mount_tracker_proxy (); + g_return_if_fail (proxy != NULL); + + error = NULL; + if (!gvfs_dbus_mount_tracker_call_list_mountable_info_sync (proxy, + &iter_mountables, + NULL, + &error)) { - dbus_error_free (&error); + g_printerr ("org.gtk.vfs.MountTracker.listMountableInfo call failed: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); return; } - - if (reply == NULL) - _g_dbus_oom (); - - dbus_message_iter_init (reply, &iter); - - dbus_message_iter_recurse (&iter, &array_iter); infos = g_ptr_array_new (); uri_schemes = g_ptr_array_new (); g_ptr_array_add (uri_schemes, g_strdup ("file")); - do - { - char *type, *scheme, **scheme_aliases; - int scheme_aliases_len; - gint32 default_port; - dbus_bool_t host_is_inet; - - if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_STRUCT) - break; - - dbus_message_iter_recurse (&array_iter, &struct_iter); - - if (!_g_dbus_message_iter_get_args (&struct_iter, NULL, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_STRING, &scheme, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &scheme_aliases, &scheme_aliases_len, - DBUS_TYPE_INT32, &default_port, - DBUS_TYPE_BOOLEAN, &host_is_inet, - 0)) - break; + g_variant_iter_init (&iter, iter_mountables); + while (g_variant_iter_loop (&iter, "(&s&s^a&sib)", &type, &scheme, &scheme_aliases, &default_port, &host_is_inet)) + { info = g_new0 (MountableInfo, 1); info->type = g_strdup (type); if (*scheme != 0) - { - info->scheme = g_strdup (scheme); - if (find_string (uri_schemes, scheme) == -1) - g_ptr_array_add (uri_schemes, g_strdup (scheme)); - } + { + info->scheme = g_strdup (scheme); + if (find_string (uri_schemes, scheme) == -1) + g_ptr_array_add (uri_schemes, g_strdup (scheme)); + } + scheme_aliases_len = g_strv_length ((gchar **) scheme_aliases); if (scheme_aliases_len > 0) - { - info->scheme_aliases = g_new (char *, scheme_aliases_len + 1); - for (i = 0; i < scheme_aliases_len; i++) - { - info->scheme_aliases[i] = g_strdup (scheme_aliases[i]); - if (find_string (uri_schemes, scheme_aliases[i]) == -1) - g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i])); - } - info->scheme_aliases[scheme_aliases_len] = NULL; - } - + { + info->scheme_aliases = g_new (char *, scheme_aliases_len + 1); + for (i = 0; i < scheme_aliases_len; i++) + { + info->scheme_aliases[i] = g_strdup (scheme_aliases[i]); + if (find_string (uri_schemes, scheme_aliases[i]) == -1) + g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i])); + } + info->scheme_aliases[scheme_aliases_len] = NULL; + } + info->default_port = default_port; info->host_is_inet = host_is_inet; g_ptr_array_add (infos, info); - - g_strfreev (scheme_aliases); } - while (dbus_message_iter_next (&array_iter)); - - dbus_message_unref (reply); g_ptr_array_add (uri_schemes, NULL); g_ptr_array_add (infos, NULL); vfs->mountable_info = (MountableInfo **)g_ptr_array_free (infos, FALSE); vfs->supported_uri_schemes = (char **)g_ptr_array_free (uri_schemes, FALSE); + + g_variant_unref (iter_mountables); + g_object_unref (proxy); } @@ -814,23 +799,14 @@ _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id) static GMountInfo * -handler_lookup_mount_reply (DBusMessage *reply, +handler_lookup_mount_reply (GVariant *iter, GError **error) { - DBusError derror; GMountInfo *info; - DBusMessageIter iter; GList *l; gboolean in_cache; - - if (_g_error_from_message (reply, error)) - return NULL; - - dbus_error_init (&derror); - dbus_message_iter_init (reply, &iter); - - info = g_mount_info_from_dbus (&iter); + info = g_mount_info_from_dbus (iter); if (info == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -869,34 +845,57 @@ typedef struct { GMountInfoLookupCallback callback; gpointer user_data; GMountInfo *info; + GMountSpec *spec; + char *path; } GetMountInfoData; static void -async_get_mount_info_response (DBusMessage *reply, - GError *io_error, - void *_data) +free_get_mount_info_data (GetMountInfoData *data) { - GetMountInfoData *data = _data; + if (data->info) + g_mount_info_unref (data->info); + if (data->spec) + g_mount_spec_unref (data->spec); + g_free (data->path); + g_free (data); +} + +static void +async_get_mount_info_response (GVfsDBusMountTracker *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GetMountInfoData *data = user_data; GMountInfo *info; GError *error; - - if (reply == NULL) - data->callback (NULL, data->user_data, io_error); + GVariant *iter_mount; + + error = NULL; + if (! gvfs_dbus_mount_tracker_call_lookup_mount_finish (proxy, + &iter_mount, + res, + &error)) + { + g_warning ("Error from org.gtk.vfs.MountTracker.lookupMount(): %s", error->message); + data->callback (NULL, data->user_data, error); + g_error_free (error); + } else { - error = NULL; - info = handler_lookup_mount_reply (reply, &error); + info = handler_lookup_mount_reply (iter_mount, &error); data->callback (info, data->user_data, error); if (info) - g_mount_info_unref (info); + g_mount_info_unref (info); + g_variant_unref (iter_mount); + if (error) - g_error_free (error); + g_error_free (error); } - g_free (data); + free_get_mount_info_data (data); } static gboolean @@ -904,11 +903,37 @@ async_get_mount_info_cache_hit (gpointer _data) { GetMountInfoData *data = _data; data->callback (data->info, data->user_data, NULL); - g_mount_info_unref (data->info); - g_free (data); + free_get_mount_info_data (data); return FALSE; } +static void +get_mount_info_async_got_proxy_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GetMountInfoData *data = user_data; + GVfsDBusMountTracker *proxy; + GError *error = NULL; + + proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error); + if (proxy == NULL) + { + g_warning ("Error creating MountTracker proxy: %s", error->message); + data->callback (NULL, data->user_data, error); + free_get_mount_info_data (data); + g_error_free (error); + return; + } + + gvfs_dbus_mount_tracker_call_lookup_mount (proxy, + g_mount_spec_to_dbus_with_path (data->spec, data->path), + NULL, + (GAsyncReadyCallback) async_get_mount_info_response, + data); + g_object_unref (proxy); +} + void _g_daemon_vfs_get_mount_info_async (GMountSpec *spec, const char *path, @@ -917,12 +942,12 @@ _g_daemon_vfs_get_mount_info_async (GMountSpec *spec, { GMountInfo *info; GetMountInfoData *data; - DBusMessage *message; - DBusMessageIter iter; data = g_new0 (GetMountInfoData, 1); data->callback = callback; data->user_data = user_data; + data->spec = g_mount_spec_ref (spec); + data->path = g_strdup (path); info = lookup_mount_info_in_cache (spec, path); @@ -933,70 +958,44 @@ _g_daemon_vfs_get_mount_info_async (GMountSpec *spec, return; } - 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_LOOKUP_MOUNT); - dbus_message_set_auto_start (message, TRUE); - - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus_with_path (&iter, spec, path); - - - _g_dbus_connection_call_async (the_vfs->async_bus, message, G_VFS_DBUS_TIMEOUT_MSECS, - async_get_mount_info_response, - data); - - dbus_message_unref (message); + gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + G_VFS_DBUS_DAEMON_NAME, + G_VFS_DBUS_MOUNTTRACKER_PATH, + NULL, + get_mount_info_async_got_proxy_cb, + data); } - GMountInfo * _g_daemon_vfs_get_mount_info_sync (GMountSpec *spec, const char *path, + GCancellable *cancellable, GError **error) { GMountInfo *info; - DBusConnection *conn; - DBusMessage *message, *reply; - DBusMessageIter iter; - DBusError derror; - + GVfsDBusMountTracker *proxy; + GVariant *iter_mount; + info = lookup_mount_info_in_cache (spec, path); - if (info != NULL) return info; - 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_LOOKUP_MOUNT); - dbus_message_set_auto_start (message, TRUE); + proxy = create_mount_tracker_proxy (); + g_return_val_if_fail (proxy != NULL, NULL); - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus_with_path (&iter, spec, path); - - dbus_error_init (&derror); - reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror); - dbus_message_unref (message); - - if (!reply) + if (gvfs_dbus_mount_tracker_call_lookup_mount_sync (proxy, + g_mount_spec_to_dbus_with_path (spec, path), + &iter_mount, + cancellable, + error)) { - _g_error_from_dbus (&derror, error); - dbus_error_free (&derror); - return NULL; + info = handler_lookup_mount_reply (iter_mount, error); + g_variant_unref (iter_mount); } - - info = handler_lookup_mount_reply (reply, error); - - dbus_message_unref (reply); + g_object_unref (proxy); + return info; } @@ -1005,43 +1004,28 @@ _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path, char **mount_path) { GMountInfo *info; - DBusConnection *conn; - DBusMessage *message, *reply; - DBusMessageIter iter; - DBusError derror; int len; const char *mount_path_end; - + GVfsDBusMountTracker *proxy; + GVariant *iter_mount; + info = lookup_mount_info_by_fuse_path_in_cache (fuse_path, mount_path); if (info != NULL) return info; - conn = _g_dbus_connection_get_sync (NULL, NULL); - 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_LOOKUP_MOUNT_BY_FUSE_PATH); - dbus_message_set_auto_start (message, TRUE); + proxy = create_mount_tracker_proxy (); + g_return_val_if_fail (proxy != NULL, NULL); - dbus_message_iter_init_append (message, &iter); - _g_dbus_message_iter_append_cstring (&iter, fuse_path); - - dbus_error_init (&derror); - reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror); - dbus_message_unref (message); - if (!reply) + if (gvfs_dbus_mount_tracker_call_lookup_mount_by_fuse_path_sync (proxy, + fuse_path, + &iter_mount, + NULL, + NULL)) { - dbus_error_free (&derror); - return NULL; + info = handler_lookup_mount_reply (iter_mount, NULL); + g_variant_unref (iter_mount); } - - info = handler_lookup_mount_reply (reply, NULL); - dbus_message_unref (reply); if (info) { @@ -1065,7 +1049,8 @@ _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path, } } - + g_object_unref (proxy); + return info; } @@ -1173,44 +1158,6 @@ g_daemon_vfs_add_writable_namespaces (GVfs *vfs, G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); } -/* Sends a message on the session bus and blocks for the reply, - using the thread local connection */ -gboolean -_g_daemon_vfs_send_message_sync (DBusMessage *message, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - DBusError derror; - DBusMessage *reply; - - connection = _g_dbus_connection_get_sync (NULL, NULL); - if (connection == NULL) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Error setting file metadata: %s"), - _("Can't contact session bus")); - return FALSE; - } - - dbus_error_init (&derror); - /* TODO: Handle cancellable */ - reply = dbus_connection_send_with_reply_and_block (connection, message, - G_VFS_DBUS_TIMEOUT_MSECS, - &derror); - if (!reply) - { - _g_error_from_dbus (&derror, error); - dbus_error_free (&derror); - return FALSE; - } - - dbus_message_unref (reply); - - return TRUE; -} - static gboolean strv_equal (char **a, char **b) { @@ -1529,7 +1476,7 @@ g_daemon_vfs_local_file_moved (GVfs *vfs, meta_lookup_cache_free (cache); } -DBusConnection * +GDBusConnection * _g_daemon_vfs_get_async_bus (void) { return the_vfs->async_bus; diff --git a/client/gdaemonvfs.h b/client/gdaemonvfs.h index e656a1cf..c5ecefc5 100644 --- a/client/gdaemonvfs.h +++ b/client/gdaemonvfs.h @@ -24,7 +24,6 @@ #define __G_DAEMON_VFS_H__ #include <gio/gio.h> -#include <dbus/dbus.h> #include "gmountspec.h" #include "gmounttracker.h" #include "gvfsuriutils.h" @@ -61,6 +60,7 @@ void _g_daemon_vfs_get_mount_info_async (GMountSpec gpointer user_data); GMountInfo * _g_daemon_vfs_get_mount_info_sync (GMountSpec *spec, const char *path, + GCancellable *cancellable, GError **error); GMountInfo * _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path, char **mount_path); @@ -68,10 +68,7 @@ GMountSpec * _g_daemon_vfs_get_mount_spec_for_path (GMountSpec const char *path, const char *new_path); void _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id); -DBusConnection *_g_daemon_vfs_get_async_bus (void); -gboolean _g_daemon_vfs_send_message_sync (DBusMessage *message, - GCancellable *cancellable, - GError **error); +GDBusConnection *_g_daemon_vfs_get_async_bus (void); int _g_daemon_vfs_append_metadata_for_set (GVariantBuilder *builder, MetaTree *tree, const char *path, diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c index e8f59e28..670827ad 100644 --- a/client/gvfsdaemondbus.c +++ b/client/gvfsdaemondbus.c @@ -38,6 +38,7 @@ #include <gdaemonvfs.h> #include "gvfsdbusutils.h" #include "gsysutils.h" +#include <gvfsdbus.h> /* Extra vfs-specific data for DBusConnections */ typedef struct { @@ -50,9 +51,6 @@ typedef struct { GSource *extra_fd_source; } VfsConnectionData; -static gint32 vfs_data_slot = -1; -static GOnce once_init_dbus = G_ONCE_INIT; - typedef struct _ThreadLocalConnections ThreadLocalConnections; static void free_local_connections (ThreadLocalConnections *local); @@ -66,10 +64,6 @@ G_LOCK_DEFINE_STATIC(async_map); static GHashTable *obj_path_map = NULL; G_LOCK_DEFINE_STATIC(obj_path_map); -static void setup_async_fd_receive (VfsConnectionData *connection_data); -static void invalidate_local_connection (const char *dbus_id, - GError **error); - GQuark _g_vfs_error_quark (void) @@ -77,42 +71,55 @@ _g_vfs_error_quark (void) return g_quark_from_static_string ("g-vfs-error-quark"); } -static gpointer -vfs_dbus_init (gpointer arg) -{ - if (!dbus_connection_allocate_data_slot (&vfs_data_slot)) - g_error ("Unable to allocate data slot"); - - return NULL; -} - /************************************************************************** * message filters for vfs dbus connections * *************************************************************************/ typedef struct { - DBusHandleMessageFunction callback; + GVfsRegisterVfsFilterCallback callback; GObject *data; + GHashTable *skeletons; } PathMapEntry; +static void +free_path_map_entry (PathMapEntry *entry) +{ + g_hash_table_destroy (entry->skeletons); + g_free (entry); +} + +static void +unref_skeleton (gpointer object) +{ + GDBusInterfaceSkeleton *skeleton = object; + + g_print ("unref_skeleton: unreffing skeleton %p\n", skeleton); + g_dbus_interface_skeleton_unexport (skeleton); + g_object_unref (skeleton); +} + +/* Please note the obj_path has to be unique even for different interfaces */ void _g_dbus_register_vfs_filter (const char *obj_path, - DBusHandleMessageFunction callback, + GVfsRegisterVfsFilterCallback callback, GObject *data) { - PathMapEntry * entry; + PathMapEntry *entry; + g_print ("_g_dbus_register_vfs_filter: obj_path = '%s'\n", obj_path); + G_LOCK (obj_path_map); if (obj_path_map == NULL) obj_path_map = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_free); + g_free, (GDestroyNotify)free_path_map_entry); - entry = g_new (PathMapEntry,1 ); + entry = g_new (PathMapEntry, 1); entry->callback = callback; entry->data = data; + entry->skeletons = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)unref_skeleton); - g_hash_table_insert (obj_path_map, g_strdup (obj_path), entry); + g_hash_table_insert (obj_path_map, g_strdup (obj_path), entry); G_UNLOCK (obj_path_map); } @@ -121,68 +128,58 @@ void _g_dbus_unregister_vfs_filter (const char *obj_path) { G_LOCK (obj_path_map); - + if (obj_path_map) g_hash_table_remove (obj_path_map, obj_path); G_UNLOCK (obj_path_map); } -static DBusHandlerResult -vfs_connection_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) +static void +register_skeleton (const char *obj_path, + PathMapEntry *entry, + GDBusConnection *dbus_conn) { - PathMapEntry *entry; - DBusHandlerResult res; - DBusHandleMessageFunction callback; - GObject *data; - VfsConnectionData *connection_data; - const char *path; + GDBusInterfaceSkeleton *skeleton; - callback = NULL; - data = NULL; - - if (dbus_message_is_signal (message, - DBUS_INTERFACE_LOCAL, - "Disconnected")) + if (! g_hash_table_contains (entry->skeletons, dbus_conn)) { - connection_data = dbus_connection_get_data (connection, vfs_data_slot); - if (connection_data->async_dbus_id) - { - _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id); - G_LOCK (async_map); - g_hash_table_remove (async_map, connection_data->async_dbus_id); - G_UNLOCK (async_map); - } + /* Note that the newly created GDBusInterfaceSkeleton instance refs the connection so it's not needed to watch for connection being destroyed */ + skeleton = entry->callback (dbus_conn, obj_path, entry->data); + g_print ("registering interface skeleton %p for path '%s' on the %p connection\n", skeleton, obj_path, dbus_conn); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + g_hash_table_insert (entry->skeletons, dbus_conn, skeleton); } - - path = dbus_message_get_path (message); - G_LOCK (obj_path_map); - if (obj_path_map && path) + else { - entry = g_hash_table_lookup (obj_path_map, - path); - - if (entry) - { - callback = entry->callback; - data = g_object_ref (entry->data); - } + g_print ("interface skeleton '%s' already registered on the %p connection, skipping\n", obj_path, dbus_conn); } - G_UNLOCK (obj_path_map); +} - res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +/* + * Export registered interface skeletons on this connection. This should ideally + * be called only once for every connection, but we often share/reuse existing + * connections. + * + * Already exported interface skeletons should live as long as possible + * since there might be ongoing data transfer and re-exporting (unreffing + creation) + * breaks running jobs randomly. + * + */ +void +_g_dbus_connect_vfs_filters (GDBusConnection *connection) +{ + g_print ("_g_dbus_connect_vfs_filters: connection = %p\n", connection); + + G_LOCK (obj_path_map); - if (callback) + if (obj_path_map) { - res = callback (connection, message, data); - g_object_unref (data); + /* Export new interface skeletons */ + g_hash_table_foreach (obj_path_map, (GHFunc) register_skeleton, connection); } - return res; + G_UNLOCK (obj_path_map); } static void @@ -208,164 +205,43 @@ connection_data_free (gpointer p) } static void -vfs_connection_setup (DBusConnection *connection, - int extra_fd, - gboolean async) +vfs_connection_closed (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) { VfsConnectionData *connection_data; - connection_data = g_new0 (VfsConnectionData, 1); - connection_data->extra_fd = extra_fd; - connection_data->extra_fd_count = 0; - - if (async) - setup_async_fd_receive (connection_data); + g_print ("gvfsdaemondbus.c: vfs_connection_closed()\n"); - if (!dbus_connection_set_data (connection, vfs_data_slot, connection_data, connection_data_free)) - _g_dbus_oom (); + connection_data = g_object_get_data (G_OBJECT (connection), "connection_data"); + g_assert (connection_data != NULL); - if (!dbus_connection_add_filter (connection, vfs_connection_filter, NULL, NULL)) - _g_dbus_oom (); -} + g_print (" async_dbus_id = '%s'\n", connection_data->async_dbus_id); -/************************************************************************** - * Functions to get fds from vfs dbus connections * - *************************************************************************/ - -typedef struct { - int fd; - GetFdAsyncCallback callback; - gpointer callback_data; -} OutstandingFD; - -static void -outstanding_fd_free (OutstandingFD *outstanding) -{ - if (outstanding->fd != -1) - close (outstanding->fd); - - g_free (outstanding); -} - -static gboolean -async_connection_accept_new_fd (VfsConnectionData *data, - GIOCondition condition, - int fd) -{ - int new_fd; - int fd_id; - OutstandingFD *outstanding_fd; - - if (condition & G_IO_HUP) + if (connection_data->async_dbus_id) { - close (data->extra_fd); - data->extra_fd = -1; - g_source_destroy (data->extra_fd_source); - g_source_unref (data->extra_fd_source); - data->extra_fd_source = NULL; - return FALSE; - } - - fd_id = data->extra_fd_count; - new_fd = _g_socket_receive_fd (data->extra_fd); - if (new_fd != -1) - { - data->extra_fd_count++; - - outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - - if (outstanding_fd) - { - outstanding_fd->callback (new_fd, outstanding_fd->callback_data); - g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - } - else - { - outstanding_fd = g_new0 (OutstandingFD, 1); - outstanding_fd->fd = new_fd; - outstanding_fd->callback = NULL; - outstanding_fd->callback_data = NULL; - g_hash_table_insert (data->outstanding_fds, - GINT_TO_POINTER (fd_id), - outstanding_fd); - } + _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id); + G_LOCK (async_map); + g_hash_table_remove (async_map, connection_data->async_dbus_id); + G_UNLOCK (async_map); } - - return TRUE; } static void -setup_async_fd_receive (VfsConnectionData *connection_data) -{ - connection_data->outstanding_fds = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify)outstanding_fd_free); - - - connection_data->extra_fd_source = - __g_fd_source_new (connection_data->extra_fd, G_IO_IN|G_IO_ERR, NULL); - g_source_set_callback (connection_data->extra_fd_source, - (GSourceFunc)async_connection_accept_new_fd, - connection_data, NULL); - g_source_attach (connection_data->extra_fd_source, NULL); -} - -int -_g_dbus_connection_get_fd_sync (DBusConnection *connection, - int fd_id) +vfs_connection_setup (GDBusConnection *connection, + int extra_fd, + gboolean async) { - VfsConnectionData *data; - int fd; - - data = dbus_connection_get_data (connection, vfs_data_slot); - g_assert (data != NULL); - - /* I don't think we can get reorders here, can we? - * Its a sync per-thread connection after all - */ - g_assert (fd_id == data->extra_fd_count); - - fd = _g_socket_receive_fd (data->extra_fd); - if (fd != -1) - data->extra_fd_count++; - - return fd; -} + VfsConnectionData *connection_data; -void -_g_dbus_connection_get_fd_async (DBusConnection *connection, - int fd_id, - GetFdAsyncCallback callback, - gpointer callback_data) -{ - VfsConnectionData *data; - OutstandingFD *outstanding_fd; - int fd; + connection_data = g_new0 (VfsConnectionData, 1); + connection_data->extra_fd = extra_fd; + connection_data->extra_fd_count = 0; - data = dbus_connection_get_data (connection, vfs_data_slot); - g_assert (data != NULL); - - outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id)); + g_object_set_data_full (G_OBJECT (connection), "connection_data", connection_data, connection_data_free); - if (outstanding_fd) - { - fd = outstanding_fd->fd; - outstanding_fd->fd = -1; - g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id)); - callback (fd, callback_data); - } - else - { - outstanding_fd = g_new0 (OutstandingFD, 1); - outstanding_fd->fd = -1; - outstanding_fd->callback = callback; - outstanding_fd->callback_data = callback_data; - g_hash_table_insert (data->outstanding_fds, - GINT_TO_POINTER (fd_id), - outstanding_fd); - } + g_signal_connect (connection, "closed", G_CALLBACK (vfs_connection_closed), NULL); } /******************************************************************* @@ -373,17 +249,17 @@ _g_dbus_connection_get_fd_async (DBusConnection *connection, *******************************************************************/ -static DBusConnection * +static GDBusConnection * get_connection_for_async (const char *dbus_id) { - DBusConnection *connection; + GDBusConnection *connection; connection = NULL; G_LOCK (async_map); if (async_map != NULL) connection = g_hash_table_lookup (async_map, dbus_id); if (connection) - dbus_connection_ref (connection); + g_object_ref (connection); G_UNLOCK (async_map); return connection; @@ -392,26 +268,31 @@ get_connection_for_async (const char *dbus_id) static void close_and_unref_connection (void *data) { - DBusConnection *connection = data; + GDBusConnection *connection = data; + + g_print ("close_and_unref_connection: closing connection\n"); - dbus_connection_close (connection); - dbus_connection_unref (connection); + /* TODO: watch for the need to manually call g_dbus_connection_close_sync () */ + g_object_unref (connection); } static void -set_connection_for_async (DBusConnection *connection, const char *dbus_id) +set_connection_for_async (GDBusConnection *connection, const char *dbus_id) { VfsConnectionData *data; + g_print ("set_connection_for_async: connection = %p, dbus_id = '%s'\n", connection, dbus_id); + G_LOCK (async_map); - data = dbus_connection_get_data (connection, vfs_data_slot); + data = g_object_get_data (G_OBJECT (connection), "connection_data"); + g_assert (data != NULL); data->async_dbus_id = g_strdup (dbus_id); if (async_map == NULL) async_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, close_and_unref_connection); g_hash_table_insert (async_map, g_strdup (dbus_id), connection); - dbus_connection_ref (connection); + g_object_ref (connection); G_UNLOCK (async_map); } @@ -422,8 +303,8 @@ set_connection_for_async (DBusConnection *connection, const char *dbus_id) typedef struct { const char *dbus_id; - DBusMessage *message; - DBusConnection *connection; + GDBusConnection *connection; + int extra_fd; GCancellable *cancellable; GVfsAsyncDBusCallback callback; @@ -434,17 +315,15 @@ typedef struct { } AsyncDBusCall; static void -async_call_finish (AsyncDBusCall *async_call, - DBusMessage *reply) +async_call_finish (AsyncDBusCall *async_call) { if (async_call->callback) - async_call->callback (reply, async_call->connection, + async_call->callback (async_call->io_error ? NULL : async_call->connection, async_call->io_error, async_call->callback_data); if (async_call->connection) - dbus_connection_unref (async_call->connection); - dbus_message_unref (async_call->message); + g_object_unref (async_call->connection); if (async_call->cancellable) g_object_unref (async_call->cancellable); if (async_call->io_error) @@ -453,148 +332,26 @@ async_call_finish (AsyncDBusCall *async_call, } static void -async_dbus_response (DBusMessage *reply, - GError *error, - gpointer data) +async_got_private_connection_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - AsyncDBusCall *async_call = data; - - if (async_call->cancelled_tag) - g_signal_handler_disconnect (async_call->cancellable, - async_call->cancelled_tag); - - if (reply == NULL) - async_call->io_error = g_error_copy (error); + AsyncDBusCall *async_call = user_data; + GDBusConnection *connection, *existing_connection; + GError *error = NULL; - async_call_finish (async_call, reply); -} - -typedef struct { - DBusConnection *connection; - dbus_uint32_t serial; -} AsyncCallCancelData; - -static void -async_call_cancel_data_free (gpointer _data) -{ - AsyncCallCancelData *data = _data; - - dbus_connection_unref (data->connection); - g_free (data); -} - -/* Might be called on another thread */ -static void -async_call_cancelled_cb (GCancellable *cancellable, - gpointer _data) -{ - AsyncCallCancelData *data = _data; - DBusMessage *cancel_message; - - /* Send cancellation message, this just queues it, sending - * will happen in mainloop */ - cancel_message = dbus_message_new_method_call (NULL, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_CANCEL); - if (cancel_message != NULL) - { - if (dbus_message_append_args (cancel_message, - DBUS_TYPE_UINT32, &data->serial, - DBUS_TYPE_INVALID)) - dbus_connection_send (data->connection, - cancel_message, NULL); - dbus_message_unref (cancel_message); - } -} - -static void -async_call_send (AsyncDBusCall *async_call) -{ - AsyncCallCancelData *cancel_data; - - _g_dbus_connection_call_async (async_call->connection, - async_call->message, - G_VFS_DBUS_TIMEOUT_MSECS, - async_dbus_response, - async_call); - - if (async_call->cancellable) - { - cancel_data = g_new0 (AsyncCallCancelData, 1); - cancel_data->connection = dbus_connection_ref (async_call->connection); - /* make sure we get the serial *after* the message has been sent, otherwise - * it will be 0 - */ - cancel_data->serial = dbus_message_get_serial (async_call->message); - async_call->cancelled_tag = - g_signal_connect_data (async_call->cancellable, "cancelled", - (GCallback)async_call_cancelled_cb, - cancel_data, - (GClosureNotify)async_call_cancel_data_free, - 0); - } -} - -static void -async_get_connection_response (DBusMessage *reply, - GError *error, - void *data) -{ - AsyncDBusCall *async_call = data; - DBusError derror; - char *address1, *address2; - int extra_fd; - DBusConnection *connection, *existing_connection; - - if (reply == NULL) + connection = g_dbus_connection_new_for_address_finish (res, &error); + g_print ("async_got_private_connection_cb, connection = %p\n", connection); + if (!connection) { + close (async_call->extra_fd); async_call->io_error = g_error_copy (error); - async_call_finish (async_call, NULL); - return; - } - - dbus_error_init (&derror); - if (!dbus_message_get_args (reply, &derror, - DBUS_TYPE_STRING, &address1, - DBUS_TYPE_STRING, &address2, - DBUS_TYPE_INVALID)) - { - _g_error_from_dbus (&derror, &async_call->io_error); - dbus_error_free (&derror); - async_call_finish (async_call, NULL); - return; - } - - /* I don't know of any way to do an async connect */ - error = NULL; - extra_fd = _g_socket_connect (address2, &error); - if (extra_fd == -1) - { - g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Error connecting to daemon: %s"), error->message); g_error_free (error); - async_call_finish (async_call, NULL); + async_call_finish (async_call); return; } - /* Unfortunately dbus doesn't have an async open */ - dbus_error_init (&derror); - connection = dbus_connection_open_private (address1, &derror); - if (!connection) - { - close (extra_fd); - dbus_message_unref (reply); - - g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - derror.message); - dbus_error_free (&derror); - async_call_finish (async_call, NULL); - return; - } - - vfs_connection_setup (connection, extra_fd, TRUE); + vfs_connection_setup (connection, async_call->extra_fd, TRUE); /* Maybe we already had a connection? This happens if we requested * the same owner several times in parallel. @@ -605,12 +362,11 @@ async_get_connection_response (DBusMessage *reply, if (existing_connection != NULL) { async_call->connection = existing_connection; - dbus_connection_close (connection); - dbus_connection_unref (connection); + /* TODO: watch for the need to manually call g_dbus_connection_close_sync () */ + g_object_unref (connection); } else { - _g_dbus_connection_integrate_with_main (connection); set_connection_for_async (connection, async_call->dbus_id); async_call->connection = connection; } @@ -619,49 +375,109 @@ async_get_connection_response (DBusMessage *reply, * avoid doing the operation */ if (g_cancellable_set_error_if_cancelled (async_call->cancellable, &async_call->io_error)) { - async_call_finish (async_call, NULL); + async_call_finish (async_call); return; } - async_call_send (async_call); + async_call_finish (async_call); } static void -open_connection_async (AsyncDBusCall *async_call) +async_get_connection_response (GVfsDBusDaemon *proxy, + GAsyncResult *res, + gpointer user_data) { - DBusMessage *get_connection_message; + AsyncDBusCall *async_call = user_data; + GError *error = NULL; + gchar *address1, *address2; - get_connection_message = dbus_message_new_method_call (async_call->dbus_id, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_GET_CONNECTION); - - if (get_connection_message == NULL) - _g_dbus_oom (); + g_print ("async_get_connection_response\n"); + if (! gvfs_dbus_daemon_call_get_connection_finish (proxy, + &address1, &address2, + res, + &error)) + { + async_call->io_error = g_error_copy (error); + g_error_free (error); + async_call_finish (async_call); + return; + } + + /* I don't know of any way to do an async connect */ + error = NULL; + async_call->extra_fd = _g_socket_connect (address2, &error); + if (async_call->extra_fd == -1) + { + g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Error connecting to daemon: %s"), error->message); + g_error_free (error); + async_call_finish (async_call); + return; + } + + g_dbus_connection_new_for_address (address1, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, /* GDBusAuthObserver */ + async_call->cancellable, + async_got_private_connection_cb, + async_call); +} - _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (), - get_connection_message, - G_VFS_DBUS_TIMEOUT_MSECS, - async_get_connection_response, - async_call); +static void +open_connection_async_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GVfsDBusDaemon *proxy; + AsyncDBusCall *async_call = user_data; + GError *error = NULL; + + proxy = gvfs_dbus_daemon_proxy_new_finish (res, &error); + g_print ("open_connection_async_cb, proxy = %p\n", proxy); + + if (proxy == NULL) + { + async_call->io_error = g_error_copy (error); + g_error_free (error); + async_call_finish (async_call); + return; + } + + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_TIMEOUT_MSECS); - dbus_message_unref (get_connection_message); + gvfs_dbus_daemon_call_get_connection (proxy, + async_call->cancellable, + (GAsyncReadyCallback) async_get_connection_response, + async_call); + + g_object_unref (proxy); +} + +static void +open_connection_async (AsyncDBusCall *async_call) +{ + gvfs_dbus_daemon_proxy_new (_g_daemon_vfs_get_async_bus (), + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + async_call->dbus_id, + G_VFS_DBUS_DAEMON_PATH, + async_call->cancellable, + open_connection_async_cb, + async_call); } void -_g_vfs_daemon_call_async (DBusMessage *message, - GVfsAsyncDBusCallback callback, - gpointer callback_data, - GCancellable *cancellable) +_g_dbus_connection_get_for_async (const char *dbus_id, + GVfsAsyncDBusCallback callback, + gpointer callback_data, + GCancellable *cancellable) { AsyncDBusCall *async_call; - g_once (&once_init_dbus, vfs_dbus_init, NULL); - + g_print ("_g_dbus_connection_get_for_async\n"); + async_call = g_new0 (AsyncDBusCall, 1); - async_call->dbus_id = dbus_message_get_destination (message); - async_call->message = dbus_message_ref (message); + async_call->dbus_id = g_strdup (dbus_id); if (cancellable) async_call->cancellable = g_object_ref (cancellable); async_call->callback = callback; @@ -671,194 +487,10 @@ _g_vfs_daemon_call_async (DBusMessage *message, if (async_call->connection == NULL) open_connection_async (async_call); else - async_call_send (async_call); -} - -/************************************************************************** - * Synchronous daemon calls * - *************************************************************************/ - -DBusMessage * -_g_vfs_daemon_call_sync (DBusMessage *message, - DBusConnection **connection_out, - const char *callback_obj_path, - DBusObjectPathMessageFunction callback, - gpointer callback_user_data, - GCancellable *cancellable, - GError **error) -{ - DBusConnection *connection; - DBusError derror; - DBusMessage *reply; - DBusPendingCall *pending; - int dbus_fd; - int cancel_fd; - gboolean sent_cancel; - DBusMessage *cancel_message; - dbus_uint32_t serial; - gboolean handle_callbacks; - const char *dbus_id = dbus_message_get_destination (message); - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return NULL; - - connection = _g_dbus_connection_get_sync (dbus_id, error); - if (connection == NULL) - return NULL; - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return NULL; - - handle_callbacks = FALSE; - if (callback_obj_path != NULL && callback != NULL) - { - struct DBusObjectPathVTable vtable = { NULL, callback }; - handle_callbacks = dbus_connection_register_object_path (connection, - callback_obj_path, - &vtable, - callback_user_data); - } - - reply = NULL; - cancel_fd = g_cancellable_get_fd (cancellable); - if (cancel_fd != -1 || handle_callbacks) - { - if (!dbus_connection_send_with_reply (connection, message, - &pending, - G_VFS_DBUS_TIMEOUT_MSECS)) - _g_dbus_oom (); - - if (pending == NULL || - !dbus_connection_get_is_connected (connection)) - { - if (pending) - dbus_pending_call_unref (pending); - invalidate_local_connection (dbus_id, error); - goto out; - } - - /* Make sure the message is sent */ - dbus_connection_flush (connection); - - if (!dbus_connection_get_unix_fd (connection, &dbus_fd)) - { - dbus_pending_call_unref (pending); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "No fd"); - goto out; - } - - sent_cancel = (cancel_fd == -1); - while (!dbus_pending_call_get_completed (pending)) - { - GPollFD poll_fds[2]; - int poll_ret; - - do - { - poll_fds[0].events = G_IO_IN; - poll_fds[0].fd = dbus_fd; - poll_fds[1].events = G_IO_IN; - poll_fds[1].fd = cancel_fd; - poll_ret = g_poll (poll_fds, sent_cancel?1:2, -1); - } - while (poll_ret == -1 && errno == EINTR); - - if (poll_ret == -1) - { - dbus_pending_call_unref (pending); - g_cancellable_release_fd (cancellable); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "poll error"); - goto out; - } - - if (poll_fds[0].revents & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) - { - dbus_pending_call_unref (pending); - g_cancellable_release_fd (cancellable); - invalidate_local_connection (dbus_id, error); - goto out; - } - - if (!sent_cancel && g_cancellable_is_cancelled (cancellable)) - { - sent_cancel = TRUE; - serial = dbus_message_get_serial (message); - cancel_message = - dbus_message_new_method_call (NULL, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_CANCEL); - if (cancel_message != NULL) - { - if (dbus_message_append_args (cancel_message, - DBUS_TYPE_UINT32, &serial, - DBUS_TYPE_INVALID)) - { - dbus_connection_send (connection, cancel_message, NULL); - dbus_connection_flush (connection); - } - - dbus_message_unref (cancel_message); - } - } - - if (poll_fds[0].revents != 0) - { - dbus_connection_read_write (connection, - G_VFS_DBUS_TIMEOUT_MSECS); - - while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS) - ; - } - } - - reply = dbus_pending_call_steal_reply (pending); - dbus_pending_call_unref (pending); - g_cancellable_release_fd (cancellable); - } - else - { - dbus_error_init (&derror); - reply = dbus_connection_send_with_reply_and_block (connection, message, - G_VFS_DBUS_TIMEOUT_MSECS, - &derror); - if (!reply) - { - if (dbus_error_has_name (&derror, DBUS_ERROR_NO_REPLY) && - !dbus_connection_get_is_connected (connection)) - { - /* The mount for this connection died, we invalidate - * the caches, and then caller needs to retry. - */ - - invalidate_local_connection (dbus_id, error); - } - else - _g_error_from_dbus (&derror, error); - dbus_error_free (&derror); - goto out; - } - } - - if (connection_out) - *connection_out = connection; - - out: - - if (handle_callbacks) - dbus_connection_unregister_object_path (connection, callback_obj_path); - - if (reply != NULL && _g_error_from_message (reply, error)) { - dbus_message_unref (reply); - return NULL; + g_print ("got connection from cache\n"); + async_call_finish (async_call); } - - return reply; } /************************************************************************* @@ -867,22 +499,16 @@ _g_vfs_daemon_call_sync (DBusMessage *message, struct _ThreadLocalConnections { GHashTable *connections; - DBusConnection *session_bus; + GDBusConnection *session_bus; }; static void -free_mount_connection (DBusConnection *conn) -{ - dbus_connection_close (conn); - dbus_connection_unref (conn); -} - -static void free_local_connections (ThreadLocalConnections *local) { + g_print ("free_local_connections()\n"); g_hash_table_destroy (local->connections); if (local->session_bus) - free_mount_connection (local->session_bus); + g_object_unref (local->session_bus); g_free (local); } @@ -904,27 +530,29 @@ invalidate_local_connection (const char *dbus_id, "Cache invalid, retry (internally handled)"); } -DBusConnection * +GDBusConnection * _g_dbus_connection_get_sync (const char *dbus_id, + GCancellable *cancellable, GError **error) { - DBusConnection *bus; + GDBusConnection *bus; ThreadLocalConnections *local; GError *local_error; - DBusConnection *connection; - DBusMessage *message, *reply; - DBusError derror; - char *address1, *address2; + GDBusConnection *connection; + gchar *address1, *address2; int extra_fd; + GVfsDBusDaemon *daemon_proxy; + gboolean res; - g_once (&once_init_dbus, vfs_dbus_init, NULL); + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return NULL; local = g_private_get (&local_connections); if (local == NULL) { local = g_new0 (ThreadLocalConnections, 1); local->connections = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify)free_mount_connection); + g_free, (GDestroyNotify)g_object_unref); g_private_set (&local_connections, local); } @@ -934,11 +562,11 @@ _g_dbus_connection_get_sync (const char *dbus_id, if (local->session_bus) { - if (dbus_connection_get_is_connected (local->session_bus)) + if (! g_dbus_connection_is_closed (local->session_bus)) return local->session_bus; /* Session bus was disconnected, re-connect */ - dbus_connection_unref (local->session_bus); + g_object_unref (local->session_bus); local->session_bus = NULL; } } @@ -949,7 +577,7 @@ _g_dbus_connection_get_sync (const char *dbus_id, connection = g_hash_table_lookup (local->connections, dbus_id); if (connection != NULL) { - if (!dbus_connection_get_is_connected (connection)) + if (g_dbus_connection_is_closed (connection)) { /* The mount for this connection died, we invalidate * the caches, and then caller needs to retry. @@ -963,50 +591,37 @@ _g_dbus_connection_get_sync (const char *dbus_id, } } - dbus_error_init (&derror); - if (local->session_bus == NULL) { - bus = dbus_bus_get_private (DBUS_BUS_SESSION, &derror); + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error); if (bus == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't get main dbus connection: %s", - derror.message); - dbus_error_free (&derror); - return NULL; - } + return NULL; local->session_bus = bus; if (dbus_id == NULL) return bus; /* We actually wanted the session bus, so done */ } - - message = dbus_message_new_method_call (dbus_id, - G_VFS_DBUS_DAEMON_PATH, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_GET_CONNECTION); - reply = dbus_connection_send_with_reply_and_block (local->session_bus, message, -1, - &derror); - dbus_message_unref (message); - - if (!reply) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - derror.message); - dbus_error_free (&derror); - return NULL; - } - if (_g_error_from_message (reply, error)) + address1 = address2 = NULL; + daemon_proxy = gvfs_dbus_daemon_proxy_new_sync (local->session_bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + dbus_id, + G_VFS_DBUS_DAEMON_PATH, + cancellable, + error); + if (daemon_proxy == NULL) + return NULL; + + res = gvfs_dbus_daemon_call_get_connection_sync (daemon_proxy, + &address1, + &address2, + cancellable, + error); + g_object_unref (daemon_proxy); + + if (!res) return NULL; - - dbus_message_get_args (reply, NULL, - DBUS_TYPE_STRING, &address1, - DBUS_TYPE_STRING, &address2, - DBUS_TYPE_INVALID); local_error = NULL; extra_fd = _g_socket_connect (address2, &local_error); @@ -1015,23 +630,27 @@ _g_dbus_connection_get_sync (const char *dbus_id, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Error connecting to daemon: %s"), local_error->message); g_error_free (local_error); - dbus_message_unref (reply); + g_free (address1); + g_free (address2); return NULL; } - dbus_error_init (&derror); - connection = dbus_connection_open_private (address1, &derror); + connection = g_dbus_connection_new_for_address_sync (address1, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, /* GDBusAuthObserver */ + cancellable, + &local_error); if (!connection) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Error while getting peer-to-peer dbus connection: %s", - derror.message); + local_error->message); close (extra_fd); - dbus_message_unref (reply); - dbus_error_free (&derror); + g_error_free (local_error); + g_free (address1); + g_free (address2); return NULL; } - dbus_message_unref (reply); vfs_connection_setup (connection, extra_fd, FALSE); diff --git a/client/gvfsdaemondbus.h b/client/gvfsdaemondbus.h index 3683eaf9..d1cd6660 100644 --- a/client/gvfsdaemondbus.h +++ b/client/gvfsdaemondbus.h @@ -24,7 +24,6 @@ #define __G_VFS_DAEMON_DBUS_H__ #include <glib.h> -#include <dbus/dbus.h> #include <gio/gio.h> G_BEGIN_DECLS @@ -39,42 +38,28 @@ typedef enum } GVfsError; -typedef void (*GVfsAsyncDBusCallback) (DBusMessage *reply, - DBusConnection *connection, +typedef void (*GVfsAsyncDBusCallback) (GDBusConnection *connection, GError *io_error, gpointer callback_data); typedef void (*GetFdAsyncCallback) (int fd, gpointer callback_data); +typedef GDBusInterfaceSkeleton * (*GVfsRegisterVfsFilterCallback) (GDBusConnection *connection, + const char *obj_path, + gpointer callback_data); + void _g_dbus_register_vfs_filter (const char *obj_path, - DBusHandleMessageFunction callback, + GVfsRegisterVfsFilterCallback callback, GObject *data); void _g_dbus_unregister_vfs_filter (const char *obj_path); -GList * _g_dbus_bus_list_names_with_prefix_sync (DBusConnection *connection, - const char *prefix, - DBusError *error); -DBusConnection *_g_dbus_connection_get_sync (const char *dbus_id, - GError **error); -int _g_dbus_connection_get_fd_sync (DBusConnection *conn, - int fd_id); -void _g_dbus_connection_get_fd_async (DBusConnection *connection, - int fd_id, - GetFdAsyncCallback callback, - gpointer callback_data); -void _g_vfs_daemon_call_async (DBusMessage *message, - GVfsAsyncDBusCallback callback, - gpointer callback_data, - GCancellable *cancellable); -DBusMessage * _g_vfs_daemon_call_sync (DBusMessage *message, - DBusConnection **connection_out, - const char *callback_obj_path, - DBusObjectPathMessageFunction callback, - gpointer callback_user_data, - GCancellable *cancellable, - GError **error); -GFileInfo * _g_dbus_get_file_info (DBusMessageIter *iter, +void _g_dbus_connect_vfs_filters (GDBusConnection *connection); +GDBusConnection *_g_dbus_connection_get_sync (const char *dbus_id, + GCancellable *cancellable, GError **error); - +void _g_dbus_connection_get_for_async (const char *dbus_id, + GVfsAsyncDBusCallback callback, + gpointer callback_data, + GCancellable *cancellable); void _g_simple_async_result_complete_with_cancellable (GSimpleAsyncResult *result, GCancellable *cancellable); diff --git a/common/Makefile.am b/common/Makefile.am index 5d5a54ea..4755711d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -8,6 +8,21 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \ -DG_LOG_DOMAIN=\"GVFS\" \ -DDBUS_API_SUBJECT_TO_CHANGE +dbus_built_sources = gvfsdbus.c gvfsdbus.h +BUILT_SOURCES = $(dbus_built_sources) + +$(dbus_built_sources) : Makefile.am dbus-interfaces.xml + gdbus-codegen \ + --interface-prefix org.gtk.vfs. \ + --c-namespace GVfsDBus \ + --generate-c-code gvfsdbus \ + --annotate "org.gtk.vfs.Mount.OpenForRead()" \ + org.gtk.GDBus.C.UnixFD true \ + --annotate "org.gtk.vfs.Mount.OpenForWrite()" \ + org.gtk.GDBus.C.UnixFD true \ + dbus-interfaces.xml \ + $(NULL) + libgvfscommon_la_SOURCES = \ gsysutils.c gsysutils.h \ gvfsdbusutils.c gvfsdbusutils.h \ @@ -19,6 +34,7 @@ libgvfscommon_la_SOURCES = \ gvfsicon.h gvfsicon.c \ gvfsmountinfo.h gvfsmountinfo.c \ gvfsfileinfo.c gvfsfileinfo.h \ + $(dbus_built_sources) \ $(NULL) # needed by cygwin (see bug #564003) @@ -46,3 +62,7 @@ libgvfscommon_dnssd_la_LIBADD = \ $(GLIB_LIBS) endif + +EXTRA_DIST = dbus-interfaces.xml + +CLEANFILES = $(dbus_built_sources) diff --git a/common/dbus-interfaces.xml b/common/dbus-interfaces.xml new file mode 100644 index 00000000..8bd349cd --- /dev/null +++ b/common/dbus-interfaces.xml @@ -0,0 +1,351 @@ +<!DOCTYPE node PUBLIC +"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<!-- + Copyright (C) 2011 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: Tomas Bzatek <tbzatek@redhat.com> +--> + +<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"> + <!-- + org.gtk.vfs.Daemon: + + Each daemon (main and for mounts) implement this. + --> + <interface name='org.gtk.vfs.Daemon'> + <method name="GetConnection"> + <arg type='s' name='address1' direction='out'/> + <arg type='s' name='address2' direction='out'/> + </method> + <method name="Cancel"> + <arg type='u' name='serial' direction='in'/> + </method> + <method name="mount"> + <arg type='b' name='automount' direction='in'/> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + <arg type='a{sv}' name='reply' direction='out'/> + </method> + </interface> + + <!-- + org.gtk.vfs.Spawner: + + Implemented by the spawner of a process, the spawned process sends the + spawned message (with noreply) when it has spawned and gotten a dbus id. + --> + <interface name='org.gtk.vfs.Spawner'> + <method name="spawned"> + <arg type='b' name='succeeded' direction='in'/> + <arg type='s' name='error_message' direction='in'/> + </method> + </interface> + + <!-- + org.gtk.vfs.MountTracker: + + The mount tracking interface in the main daemon. + --> + <interface name='org.gtk.vfs.MountTracker'> + <method name="lookupMount"> + <arg type='(aya{sv})' name='mount_spec' direction='in'/> + <arg type='(sosssssbay(aya{sv})ay)' name='mount' direction='out'/> + </method> + <method name="lookupMountByFusePath"> + <arg type='ay' name='fuse_path' direction='in'/> + <arg type='(sosssssbay(aya{sv})ay)' name='mount' direction='out'/> + </method> + <method name="mountLocation"> + <arg type='(aya{sv})' name='mount_spec' direction='in'/> + <arg type='(so)' name='mount_source' direction='in'/> + </method> + <method name="listMounts"> + <arg type='a(sosssssbay(aya{sv})ay)' name='mounts' direction='out'/> + </method> + <method name="registerMount"> + <arg type='o' name='obj_path' direction='in'/> + <arg type='s' name='display_name' direction='in'/> + <arg type='s' name='stable_name' direction='in'/> + <arg type='s' name='x_content_types' direction='in'/> + <arg type='s' name='icon' direction='in'/> + <arg type='s' name='prefered_filename_encoding' direction='in'/> + <arg type='b' name='user_visible' direction='in'/> + <arg type='(aya{sv})' name='mount_spec' direction='in'/> + <arg type='ay' name='default_location' direction='in'/> + </method> + <method name="unregisterMount"> + <arg type='o' name='obj_path' direction='in'/> + </method> + <method name="listMountTypes"> + <arg type='as' name='mount_types' direction='out'/> + </method> + <method name="listMountableInfo"> + <arg type='a(ssasib)' name='mountables' direction='out'/> + </method> + <method name="registerFuse"> + </method> + <signal name="mounted"> + <arg type='(sosssssbay(aya{sv})ay)' name='mount'/> + </signal> + <signal name="unmounted"> + <arg type='(sosssssbay(aya{sv})ay)' name='mount'/> + </signal> + </interface> + + <!-- + org.gtk.vfs.Mountable: + + Mount daemons that support mounting more mounts implement this, + and set the dbus name in the mountable description file. + --> + <interface name='org.gtk.vfs.Mountable'> + <method name="mount"> + <arg type='(aya{sv})' name='mount_spec' direction='in'/> + <arg type='b' name='automount' direction='in'/> + <arg type='(so)' name='mount_source' direction='in'/> + </method> + </interface> + + <!-- + org.gtk.vfs.MountOperation: + + Used by the dbus-proxying implementation of GMoutOperation. + --> + <interface name='org.gtk.vfs.MountOperation'> + <method name="askPassword"> + <arg type='s' name='message_string' direction='in'/> + <arg type='s' name='default_user' direction='in'/> + <arg type='s' name='default_domain' direction='in'/> + <arg type='u' name='flags_as_int' direction='in'/> + <arg type='b' name='handled' direction='out'/> + <arg type='b' name='aborted' direction='out'/> + <arg type='s' name='password' direction='out'/> + <arg type='s' name='username' direction='out'/> + <arg type='s' name='domain' direction='out'/> + <arg type='b' name='anonymous' direction='out'/> + <arg type='u' name='password_save' direction='out'/> + </method> + <method name="askQuestion"> + <arg type='s' name='message_string' direction='in'/> + <arg type='as' name='choices' direction='in'/> + <arg type='b' name='handled' direction='out'/> + <arg type='b' name='aborted' direction='out'/> + <arg type='u' name='choice' direction='out'/> + </method> + <method name="showProcesses"> + <arg type='s' name='message_string' direction='in'/> + <arg type='as' name='choices' direction='in'/> + <arg type='ai' name='processes' direction='in'/> + <arg type='b' name='handled' direction='out'/> + <arg type='b' name='aborted' direction='out'/> + <arg type='u' name='choice' direction='out'/> + </method> + <method name="ShowUnmountProgress"> + <arg type='s' name='message_string' direction='in'/> + <arg type='t' name='time_left' direction='in'/> + <arg type='t' name='bytes_left' direction='in'/> + </method> + <method name="aborted"> + </method> + </interface> + + <!-- + org.gtk.vfs.Mount: + + Each mount (there might be several in a daemon) implements one of these interfaces + for standard i/o operations. + --> + <interface name='org.gtk.vfs.Mount'> + <method name="Unmount"> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + <arg type='u' name='flags' direction='in'/> + </method> + <method name="OpenForRead"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='pid' direction='in'/> + <arg type='u' name='fd_id' direction='out'/> + <arg type='b' name='can_seek' direction='out'/> + </method> + <method name="OpenForWrite"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='q' name='mode' direction='in'/> + <arg type='s' name='etag' direction='in'/> + <arg type='b' name='make_backup' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='u' name='pid' direction='in'/> + <arg type='u' name='fd_id' direction='out'/> + <arg type='b' name='can_seek' direction='out'/> + <arg type='t' name='initial_offset' direction='out'/> + </method> + <method name="QueryInfo"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='s' name='attributes' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='uri' direction='in'/> + <arg type='a(suv)' name='info' direction='out'/> + </method> + <method name="QueryFilesystemInfo"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='s' name='attributes' direction='in'/> + <arg type='a(suv)' name='info' direction='out'/> + </method> + <method name="Enumerate"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='s' name='obj_path' direction='in'/> + <arg type='s' name='attributes' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='uri' direction='in'/> + </method> + <method name="CreateDirectoryMonitor"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='obj_path' direction='out'/> + </method> + <method name="CreateFileMonitor"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='obj_path' direction='out'/> + </method> + <method name="MountMountable"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + <arg type='b' name='is_uri' direction='out'/> + <arg type='ay' name='path' direction='out'/> + <arg type='b' name='must_mount_location' direction='out'/> + <arg type='(aya{sv})' name='mount_spec' direction='out'/> + </method> + <method name="UnmountMountable"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + </method> + <method name="EjectMountable"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + </method> + <method name="StartMountable"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + </method> + <method name="StopMountable"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='s' name='dbus_id' direction='in'/> + <arg type='o' name='obj_path' direction='in'/> + </method> + <method name="PollMountable"> + <arg type='ay' name='path_data' direction='in'/> + </method> + <method name="SetDisplayName"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='s' name='display_name' direction='in'/> + <arg type='ay' name='new_path' direction='out'/> + </method> + <method name="Delete"> + <arg type='ay' name='path_data' direction='in'/> + </method> + <method name="Trash"> + <arg type='ay' name='path_data' direction='in'/> + </method> + <method name="MakeDirectory"> + <arg type='ay' name='path_data' direction='in'/> + </method> + <method name="MakeSymbolicLink"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='ay' name='symlink_value' direction='in'/> + </method> + <method name="Copy"> + <arg type='ay' name='path1_data' direction='in'/> + <arg type='ay' name='path2_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='o' name='progress_obj_path' direction='in'/> + </method> + <method name="Move"> + <arg type='ay' name='path1_data' direction='in'/> + <arg type='ay' name='path2_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='o' name='progress_obj_path' direction='in'/> + </method> + <method name="Push"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='ay' name='local_path' direction='in'/> + <arg type='b' name='send_progress' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='o' name='progress_obj_path' direction='in'/> + <arg type='b' name='remove_source' direction='in'/> + </method> + <method name="Pull"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='ay' name='local_path' direction='in'/> + <arg type='b' name='send_progress' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='o' name='progress_obj_path' direction='in'/> + <arg type='b' name='remove_source' direction='in'/> + </method> + <method name="SetAttribute"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='flags' direction='in'/> + <arg type='(suv)' name='attribute' direction='in'/> + </method> + <method name="QuerySettableAttributes"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='a(suu)' name='list' direction='out'/> + </method> + <method name="QueryWritableNamespaces"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='a(suu)' name='list' direction='out'/> + </method> + <method name="OpenIconForRead"> + </method> + </interface> + + <!-- + org.gtk.vfs.Enumerator: + + Implemented by client side for a file enumerator. + --> + <interface name='org.gtk.vfs.Enumerator'> + <method name="Done"> + </method> + <method name="GotInfo"> + <arg type='aa(suv)' name='infos' direction='in'/> + </method> + </interface> + + <!-- + org.gtk.vfs.Progress: + + Progress callback interface for copy and move. + --> + <interface name='org.gtk.vfs.Progress'> + <method name="Progress"> + <arg type='t' name='current' direction='in'/> + <arg type='t' name='total' direction='in'/> + </method> + </interface> + +</node> + diff --git a/common/gmountoperationdbus.c b/common/gmountoperationdbus.c index b1989c16..dc332648 100644 --- a/common/gmountoperationdbus.c +++ b/common/gmountoperationdbus.c @@ -24,152 +24,32 @@ #include <string.h> -#include <dbus/dbus.h> - -#define I_(string) g_intern_static_string (string) - #include <gio/gio.h> -#include "gmountoperationdbus.h" -#include "gvfsdaemonprotocol.h" -#include "gvfsdbusutils.h" #include <glib/gi18n-lib.h> +#include "gmountoperationdbus.h" +#include "gvfsdbus.h" typedef struct { GMountOperation *op; char *obj_path; char *dbus_id; - DBusConnection *connection; + GDBusConnection *connection; + GVfsDBusMountOperation *mount_op_skeleton; } GMountOperationDBus; -static DBusHandlerResult mount_op_message_function (DBusConnection *connection, - DBusMessage *message, - void *user_data); -static void mount_op_unregister_function (DBusConnection *connection, - void *user_data); -static void mount_op_ask_password (GMountOperationDBus *op_dbus, - DBusMessage *message); -static void mount_op_ask_question (GMountOperationDBus *op_dbus, - DBusMessage *message); -static void mount_op_show_processes (GMountOperationDBus *op_dbus, - DBusMessage *message); -static void mount_op_show_unmount_progress (GMountOperationDBus *op_dbus, - DBusMessage *message); -static void mount_op_aborted (GMountOperationDBus *op_dbus, - DBusMessage *message); - -static void -g_mount_operation_dbus_free (GMountOperationDBus *op_dbus) -{ - if (op_dbus->connection) - { - dbus_connection_unregister_object_path (op_dbus->connection, - op_dbus->obj_path); - dbus_connection_unref (op_dbus->connection); - } - g_free (op_dbus->dbus_id); - g_free (op_dbus->obj_path); - g_free (op_dbus); -} - -GMountSource * -g_mount_operation_dbus_wrap (GMountOperation *op, - DBusConnection *connection) -{ - GMountOperationDBus *op_dbus; - static int mount_id = 0; - DBusObjectPathVTable mount_vtable = { - mount_op_unregister_function, - mount_op_message_function - }; - - if (op == NULL) - return g_mount_source_new_dummy (); - - op_dbus = g_new0 (GMountOperationDBus, 1); - - op_dbus->op = op; - op_dbus->connection = dbus_connection_ref (connection); - op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++); - if (op_dbus->connection) - { - op_dbus->dbus_id = g_strdup (dbus_bus_get_unique_name (op_dbus->connection)); - if (!dbus_connection_register_object_path (op_dbus->connection, - op_dbus->obj_path, - &mount_vtable, - op_dbus)) - _g_dbus_oom (); - } - - g_object_set_data_full (G_OBJECT (op), "dbus-op", - op_dbus, (GDestroyNotify)g_mount_operation_dbus_free); - - return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path); -} - -/** - * Called when a #DBusObjectPathVTable is unregistered (or its connection is freed). - * Found in #DBusObjectPathVTable. - */ -static void -mount_op_unregister_function (DBusConnection *connection, - void *user_data) -{ -} - -/** - * Called when a message is sent to a registered object path. Found in - * #DBusObjectPathVTable which is registered with dbus_connection_register_object_path() - * or dbus_connection_register_fallback(). - */ -static DBusHandlerResult -mount_op_message_function (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - GMountOperationDBus *op_dbus = user_data; - - if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD)) - mount_op_ask_password (op_dbus, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION)) - mount_op_ask_question (op_dbus, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES)) - mount_op_show_processes (op_dbus, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_UNMOUNT_PROGRESS)) - mount_op_show_unmount_progress (op_dbus, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_ABORTED)) - mount_op_aborted (op_dbus, message); - else - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - return DBUS_HANDLER_RESULT_HANDLED; -} - static void mount_op_send_reply (GMountOperationDBus *op_dbus, - DBusMessage *reply) + GDBusMethodInvocation *invocation) { - if (!dbus_connection_send (op_dbus->connection, reply, NULL)) - _g_dbus_oom (); - g_signal_handlers_disconnect_matched (op_dbus->op, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA, g_signal_lookup ("reply", G_TYPE_MOUNT_OPERATION), 0, NULL, NULL, - reply); - dbus_message_unref (reply); + invocation); + g_object_unref (invocation); } static void @@ -177,11 +57,11 @@ ask_password_reply (GMountOperation *op, GMountOperationResult result, gpointer data) { - DBusMessage *reply = data; + GDBusMethodInvocation *invocation = data; const char *username, *password, *domain; - dbus_bool_t anonymous; + gboolean anonymous; guint32 password_save; - dbus_bool_t handled, abort_dbus; + gboolean handled, abort_dbus; GMountOperationDBus *op_dbus; op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op"); @@ -201,63 +81,42 @@ ask_password_reply (GMountOperation *op, anonymous = g_mount_operation_get_anonymous (op); password_save = g_mount_operation_get_password_save (op); - _g_dbus_message_append_args (reply, - DBUS_TYPE_BOOLEAN, &handled, - DBUS_TYPE_BOOLEAN, &abort_dbus, - DBUS_TYPE_STRING, &password, - DBUS_TYPE_STRING, &username, - DBUS_TYPE_STRING, &domain, - DBUS_TYPE_BOOLEAN, &anonymous, - DBUS_TYPE_UINT32, &password_save, - 0); - - mount_op_send_reply (op_dbus, reply); + gvfs_dbus_mount_operation_complete_ask_password (NULL, /* FIXME */ + invocation, + handled, + abort_dbus, + password, + username, + domain, + anonymous, + password_save); + + mount_op_send_reply (op_dbus, invocation); } -static void -mount_op_ask_password (GMountOperationDBus *op_dbus, - DBusMessage *message) +static gboolean +handle_ask_password (GVfsDBusMountOperation *object, + GDBusMethodInvocation *invocation, + const gchar *arg_message_string, + const gchar *arg_default_user, + const gchar *arg_default_domain, + guint arg_flags_as_int, + gpointer data) { - const char *message_string, *default_user, *default_domain; - guint32 flags; - DBusMessageIter iter; - DBusMessage *reply; - DBusError error; + GMountOperationDBus *op_dbus = data; - reply = NULL; + g_print ("gmountoperationdbus.c: handle_ask_password()\n"); - dbus_message_iter_init (message, &iter); - - dbus_error_init (&error); - if (!_g_dbus_message_iter_get_args (&iter, - &error, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_STRING, &default_user, - DBUS_TYPE_STRING, &default_domain, - DBUS_TYPE_UINT32, &flags, - 0)) - { - reply = dbus_message_new_error (message, error.name, error.message); - if (reply == NULL) - _g_dbus_oom (); - if (!dbus_connection_send (op_dbus->connection, reply, NULL)) - _g_dbus_oom (); - dbus_message_unref (reply); - dbus_error_free (&error); - return; - } - - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); - - g_signal_connect (op_dbus->op, "reply", (GCallback)ask_password_reply, reply); + g_signal_connect (op_dbus->op, "reply", + (GCallback)ask_password_reply, + g_object_ref (invocation)); g_signal_emit_by_name (op_dbus->op, "ask_password", - message_string, - default_user, - default_domain, - flags); + arg_message_string, + arg_default_user, + arg_default_domain, + arg_flags_as_int); + return TRUE; } static void @@ -265,9 +124,9 @@ ask_question_reply (GMountOperation *op, GMountOperationResult result, gpointer data) { - DBusMessage *reply = data; + GDBusMethodInvocation *invocation = data; guint32 choice; - dbus_bool_t handled, abort_dbus; + gboolean handled, abort_dbus; GMountOperationDBus *op_dbus; op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op"); @@ -277,58 +136,35 @@ ask_question_reply (GMountOperation *op, choice = g_mount_operation_get_choice (op); - _g_dbus_message_append_args (reply, - DBUS_TYPE_BOOLEAN, &handled, - DBUS_TYPE_BOOLEAN, &abort_dbus, - DBUS_TYPE_UINT32, &choice, - 0); + gvfs_dbus_mount_operation_complete_ask_question (NULL, /* FIXME */ + invocation, + handled, + abort_dbus, + choice); - mount_op_send_reply (op_dbus, reply); + mount_op_send_reply (op_dbus, invocation); } -static void -mount_op_ask_question (GMountOperationDBus *op_dbus, - DBusMessage *message) +static gboolean +handle_ask_question (GVfsDBusMountOperation *object, + GDBusMethodInvocation *invocation, + const gchar *arg_message_string, + const gchar *const *arg_choices, + gpointer data) { - const char *message_string; - char **choices; - int num_choices; - DBusMessage *reply; - DBusError error; - DBusMessageIter iter; - - reply = NULL; - - dbus_message_iter_init (message, &iter); - dbus_error_init (&error); - if (!_g_dbus_message_iter_get_args (&iter, - &error, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &choices, &num_choices, - 0)) - { - reply = dbus_message_new_error (message, error.name, error.message); - if (reply == NULL) - _g_dbus_oom (); - if (!dbus_connection_send (op_dbus->connection, reply, NULL)) - _g_dbus_oom (); - dbus_message_unref (reply); - dbus_error_free (&error); - return; - } - - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); - - g_signal_connect (op_dbus->op, "reply", (GCallback)ask_question_reply, reply); + GMountOperationDBus *op_dbus = data; + + g_print ("gmountoperationdbus.c: handle_ask_question()\n"); + + g_signal_connect (op_dbus->op, + "reply", + (GCallback)ask_question_reply, + g_object_ref (invocation)); g_signal_emit_by_name (op_dbus->op, "ask_question", - message_string, - choices); - - dbus_free_string_array (choices); + arg_message_string, + arg_choices); + return TRUE; } static void @@ -336,9 +172,9 @@ show_processes_reply (GMountOperation *op, GMountOperationResult result, gpointer data) { - DBusMessage *reply = data; + GDBusMethodInvocation *invocation = data; guint32 choice; - dbus_bool_t handled, abort_dbus; + gboolean handled, abort_dbus; GMountOperationDBus *op_dbus; op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op"); @@ -347,119 +183,149 @@ show_processes_reply (GMountOperation *op, abort_dbus = (result == G_MOUNT_OPERATION_ABORTED); choice = g_mount_operation_get_choice (op); + + gvfs_dbus_mount_operation_complete_show_processes (NULL, /* FIXME */ + invocation, + handled, + abort_dbus, + choice); - _g_dbus_message_append_args (reply, - DBUS_TYPE_BOOLEAN, &handled, - DBUS_TYPE_BOOLEAN, &abort_dbus, - DBUS_TYPE_UINT32, &choice, - 0); - - mount_op_send_reply (op_dbus, reply); + mount_op_send_reply (op_dbus, invocation); } -static void -mount_op_show_processes (GMountOperationDBus *op_dbus, - DBusMessage *message) +static gboolean +handle_show_processes (GVfsDBusMountOperation *object, + GDBusMethodInvocation *invocation, + const gchar *arg_message_string, + const gchar *const *arg_choices, + GVariant *arg_processes, + gpointer data) { - const char *message_string; - char **choices; - int num_choices; - gint32 **process_pids; - int num_process_pids; - DBusMessage *reply; - DBusError error; - DBusMessageIter iter; + GMountOperationDBus *op_dbus = data; GArray *processes; + GPid pid; + GVariantIter iter; - reply = NULL; - - dbus_message_iter_init (message, &iter); - dbus_error_init (&error); - if (!_g_dbus_message_iter_get_args (&iter, - &error, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &choices, &num_choices, - DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, - &process_pids, &num_process_pids, - 0)) - { - reply = dbus_message_new_error (message, error.name, error.message); - if (reply == NULL) - _g_dbus_oom (); - if (!dbus_connection_send (op_dbus->connection, reply, NULL)) - _g_dbus_oom (); - dbus_message_unref (reply); - dbus_error_free (&error); - return; - } - - processes = g_array_sized_new (FALSE, FALSE, sizeof (GPid), num_process_pids); - g_array_append_vals (processes, process_pids, num_process_pids); + g_print ("gmountoperationdbus.c: handle_show_processes()\n"); - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); + processes = g_array_new (FALSE, FALSE, sizeof (GPid)); + g_variant_iter_init (&iter, arg_processes); + while (g_variant_iter_loop (&iter, "i", &pid)) + g_array_append_val (processes, pid); - g_signal_connect (op_dbus->op, "reply", (GCallback)show_processes_reply, reply); + g_signal_connect (op_dbus->op, + "reply", + (GCallback)show_processes_reply, + g_object_ref (invocation)); g_signal_emit_by_name (op_dbus->op, "show_processes", - message_string, + arg_message_string, processes, - choices); + arg_choices); - dbus_free_string_array (choices); g_array_unref (processes); + + return TRUE; } -static void -mount_op_show_unmount_progress (GMountOperationDBus *op_dbus, - DBusMessage *message) +static gboolean +handle_show_unmount_progress (GVfsDBusMountOperation *object, + GDBusMethodInvocation *invocation, + const gchar *arg_message_string, + guint64 arg_time_left, + guint64 arg_bytes_left, + gpointer data) { - const gchar *message_string; - guint64 time_left, bytes_left; - DBusMessage *reply; - DBusMessageIter iter; - DBusError error; - - reply = NULL; - - dbus_message_iter_init (message, &iter); - dbus_error_init (&error); - if (!_g_dbus_message_iter_get_args (&iter, - &error, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_UINT64, &time_left, - DBUS_TYPE_UINT64, &bytes_left, - 0)) - { - reply = dbus_message_new_error (message, error.name, error.message); - if (reply == NULL) - _g_dbus_oom (); - if (!dbus_connection_send (op_dbus->connection, reply, NULL)) - _g_dbus_oom (); - dbus_message_unref (reply); - dbus_error_free (&error); - return; - } - - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); + GMountOperationDBus *op_dbus = data; + + g_print ("gmountoperationdbus.c: handle_show_unmount_progress()\n"); g_signal_emit_by_name (op_dbus->op, "show-unmount-progress", - message_string, - time_left, - bytes_left); + arg_message_string, + arg_time_left, + arg_bytes_left); - mount_op_send_reply (op_dbus, reply); + gvfs_dbus_mount_operation_complete_show_unmount_progress (object, invocation); + + return TRUE; } -static void -mount_op_aborted (GMountOperationDBus *op_dbus, - DBusMessage *message) +static gboolean +handle_aborted (GVfsDBusMountOperation *object, + GDBusMethodInvocation *invocation, + gpointer data) { + GMountOperationDBus *op_dbus = data; + + g_print ("gmountoperationdbus.c: handle_aborted()\n"); + /* also emit reply to make the all DBus ops return */ g_mount_operation_reply (op_dbus->op, G_MOUNT_OPERATION_UNHANDLED); g_signal_emit_by_name (op_dbus->op, "aborted"); + gvfs_dbus_mount_operation_complete_aborted (object, invocation); + + return TRUE; +} + + +static void +g_mount_operation_dbus_free (GMountOperationDBus *op_dbus) +{ + if (op_dbus->connection) + { + if (op_dbus->mount_op_skeleton != NULL) + { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (op_dbus->mount_op_skeleton)); + g_object_unref (op_dbus->mount_op_skeleton); + } + g_object_unref (op_dbus->connection); + } + g_free (op_dbus->dbus_id); + g_free (op_dbus->obj_path); + g_free (op_dbus); +} + +GMountSource * +g_mount_operation_dbus_wrap (GMountOperation *op, + GDBusConnection *connection) +{ + GMountOperationDBus *op_dbus; + static int mount_id = 0; + GError *error; + + if (op == NULL) + return g_mount_source_new_dummy (); + + op_dbus = g_new0 (GMountOperationDBus, 1); + + op_dbus->op = op; + op_dbus->connection = g_object_ref (connection); + op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++); + if (op_dbus->connection) + { + op_dbus->dbus_id = g_strdup (g_dbus_connection_get_unique_name (op_dbus->connection)); + op_dbus->mount_op_skeleton = gvfs_dbus_mount_operation_skeleton_new (); + + g_signal_connect (op_dbus->mount_op_skeleton, "handle-ask-password", G_CALLBACK (handle_ask_password), op_dbus); + g_signal_connect (op_dbus->mount_op_skeleton, "handle-ask-question", G_CALLBACK (handle_ask_question), op_dbus); + g_signal_connect (op_dbus->mount_op_skeleton, "handle-show-processes", G_CALLBACK (handle_show_processes), op_dbus); + g_signal_connect (op_dbus->mount_op_skeleton, "handle-show-unmount-progress", G_CALLBACK (handle_show_unmount_progress), op_dbus); + g_signal_connect (op_dbus->mount_op_skeleton, "handle-aborted", G_CALLBACK (handle_aborted), op_dbus); + + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (op_dbus->mount_op_skeleton), + op_dbus->connection, + op_dbus->obj_path, + &error)) + { + g_warning ("Error exporting GMountOperationDBus: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + } + + g_object_set_data_full (G_OBJECT (op), "dbus-op", + op_dbus, (GDestroyNotify)g_mount_operation_dbus_free); + + return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path); } diff --git a/common/gmountoperationdbus.h b/common/gmountoperationdbus.h index 564fc739..7d4111a4 100644 --- a/common/gmountoperationdbus.h +++ b/common/gmountoperationdbus.h @@ -33,7 +33,7 @@ G_BEGIN_DECLS GMountSource *g_mount_operation_dbus_wrap (GMountOperation *op, - DBusConnection *connection); + GDBusConnection *connection); G_END_DECLS diff --git a/common/gmountsource.c b/common/gmountsource.c index 95202280..4aa107c9 100644 --- a/common/gmountsource.c +++ b/common/gmountsource.c @@ -23,9 +23,8 @@ #include <config.h> #include <gmountsource.h> -#include <gvfsdbusutils.h> #include <gio/gio.h> -#include <gvfsdaemonprotocol.h> +#include <gvfsdbus.h> #include <string.h> @@ -93,20 +92,27 @@ g_mount_source_new_dummy (void) return source; } - -void -g_mount_source_to_dbus (GMountSource *source, - DBusMessage *message) +GVariant * +g_mount_source_to_dbus (GMountSource *source) { g_assert (source->dbus_id != NULL); g_assert (source->obj_path != NULL); - if (!dbus_message_append_args (message, - DBUS_TYPE_STRING, &source->dbus_id, - DBUS_TYPE_OBJECT_PATH, &source->obj_path, - 0)) - _g_dbus_oom (); + return g_variant_new ("(so)", + source->dbus_id, + source->obj_path); +} + +GMountSource * +g_mount_source_from_dbus (GVariant *iter) +{ + const gchar *obj_path, *dbus_id; + + g_variant_get (iter, "(&s&o)", + &dbus_id, + &obj_path); + return g_mount_source_new (dbus_id, obj_path); } const char * @@ -156,64 +162,103 @@ ask_password_data_free (gpointer _data) g_free (data); } +static GVfsDBusMountOperation * +create_mount_operation_proxy (GMountSource *source, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GVfsDBusMountOperation *proxy; + GError *error; + + /* If no dbus id specified, reply that we weren't handled */ + if (source->dbus_id[0] == 0) + { + if (callback != NULL) + g_simple_async_report_error_in_idle (G_OBJECT (source), + callback, + user_data, + G_IO_ERROR, G_IO_ERROR_FAILED, + "Internal Error"); + return NULL; + } + + error = NULL; + proxy = gvfs_dbus_mount_operation_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + source->dbus_id, + source->obj_path, + NULL, + &error); + if (proxy == NULL) + if (callback != NULL) + g_simple_async_report_take_gerror_in_idle (G_OBJECT (source), + callback, + user_data, + error); + + return proxy; +} + /* the callback from dbus -> main thread */ static void -ask_password_reply (DBusMessage *reply, - GError *error, - gpointer _data) +ask_password_reply (GVfsDBusMountOperation *proxy, + GAsyncResult *res, + gpointer user_data) { GSimpleAsyncResult *result; AskPasswordData *data; - dbus_bool_t handled, aborted, anonymous; + gboolean handled, aborted, anonymous; guint32 password_save; - const char *password, *username, *domain; - DBusMessageIter iter; + gchar *password, *username, *domain; + GError *error; - result = G_SIMPLE_ASYNC_RESULT (_data); + result = G_SIMPLE_ASYNC_RESULT (user_data); handled = TRUE; + g_print ("gmountsource.c: ask_password_reply()\n"); + data = g_new0 (AskPasswordData, 1); g_simple_async_result_set_op_res_gpointer (result, data, ask_password_data_free); - if (reply == NULL) + error = NULL; + if (!gvfs_dbus_mount_operation_call_ask_password_finish (proxy, + &handled, + &aborted, + &password, + &username, + &domain, + &anonymous, + &password_save, + res, + &error)) { data->aborted = TRUE; + g_simple_async_result_take_error (result, error); } else { - dbus_message_iter_init (reply, &iter); - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_BOOLEAN, &handled, - DBUS_TYPE_BOOLEAN, &aborted, - DBUS_TYPE_STRING, &password, - DBUS_TYPE_STRING, &username, - DBUS_TYPE_STRING, &domain, - DBUS_TYPE_BOOLEAN, &anonymous, - DBUS_TYPE_UINT32, &password_save, - 0)) - data->aborted = TRUE; - else - { - data->aborted = aborted; - - if (!anonymous) - { - data->password = g_strdup (password); - data->username = *username == 0 ? NULL : g_strdup (username); - data->domain = *domain == 0 ? NULL : g_strdup (domain); - } - data->password_save = (GPasswordSave)password_save; - data->anonymous = anonymous; - - /* TODO: handle more args */ - } + data->aborted = aborted; + + if (!anonymous) + { + data->password = g_strdup (password); + data->username = *username == 0 ? NULL : g_strdup (username); + data->domain = *domain == 0 ? NULL : g_strdup (domain); + } + data->password_save = (GPasswordSave)password_save; + data->anonymous = anonymous; + + /* TODO: handle more args */ + g_free (password); + g_free (username); + g_free (domain); } if (handled == FALSE) { g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error"); } - + g_simple_async_result_complete (result); g_object_unref (result); } @@ -228,49 +273,27 @@ g_mount_source_ask_password_async (GMountSource *source, gpointer user_data) { GSimpleAsyncResult *result; - DBusMessage *message; - guint32 flags_as_int; - - - /* If no dbus id specified, reply that we weren't handled */ - if (source->dbus_id[0] == 0) - { - g_simple_async_report_error_in_idle (G_OBJECT (source), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Internal Error"); - return; - } - - if (message_string == NULL) - message_string = ""; - if (default_user == NULL) - default_user = ""; - if (default_domain == NULL) - default_domain = ""; - - flags_as_int = flags; - - message = dbus_message_new_method_call (source->dbus_id, - source->obj_path, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD); + GVfsDBusMountOperation *proxy; - _g_dbus_message_append_args (message, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_STRING, &default_user, - DBUS_TYPE_STRING, &default_domain, - DBUS_TYPE_UINT32, &flags_as_int, - 0); + proxy = create_mount_operation_proxy (source, callback, user_data); + if (proxy == NULL) + return; - result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, - g_mount_source_ask_password_async); /* 30 minute timeout */ - _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, - ask_password_reply, result); - dbus_message_unref (message); + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30); + result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, + g_mount_source_ask_password_async); + + gvfs_dbus_mount_operation_call_ask_password (proxy, + message_string ? message_string : "", + default_user ? default_user : "", + default_domain ? default_domain : "", + flags, + NULL, + (GAsyncReadyCallback) ask_password_reply, + result); + g_object_unref (proxy); } /** @@ -493,40 +516,39 @@ struct AskQuestionData { /* the callback from dbus -> main thread */ static void -ask_question_reply (DBusMessage *reply, - GError *error, - gpointer _data) +ask_question_reply (GVfsDBusMountOperation *proxy, + GAsyncResult *res, + gpointer user_data) { GSimpleAsyncResult *result; AskQuestionData *data; - dbus_bool_t handled, aborted; + gboolean handled, aborted; guint32 choice; - DBusMessageIter iter; - - result = G_SIMPLE_ASYNC_RESULT (_data); + GError *error; + + result = G_SIMPLE_ASYNC_RESULT (user_data); handled = TRUE; + g_print ("gmountsource.c: ask_question_reply()\n"); + data = g_new0 (AskQuestionData, 1); g_simple_async_result_set_op_res_gpointer (result, data, g_free); - if (reply == NULL) + error = NULL; + if (!gvfs_dbus_mount_operation_call_ask_question_finish (proxy, + &handled, + &aborted, + &choice, + res, + &error)) { data->aborted = TRUE; + g_simple_async_result_take_error (result, error); } else { - dbus_message_iter_init (reply, &iter); - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_BOOLEAN, &handled, - DBUS_TYPE_BOOLEAN, &aborted, - DBUS_TYPE_UINT32, &choice, - 0)) - data->aborted = TRUE; - else - { - data->aborted = aborted; - data->choice = choice; - } + data->aborted = aborted; + data->choice = choice; } if (handled == FALSE) @@ -593,40 +615,25 @@ g_mount_source_ask_question_async (GMountSource *source, gpointer user_data) { GSimpleAsyncResult *result; - DBusMessage *message; - - /* If no dbus id specified, reply that we weren't handled */ - if (source->dbus_id[0] == 0) - { - g_simple_async_report_error_in_idle (G_OBJECT (source), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Internal Error"); - return; - } - - if (message_string == NULL) - message_string = ""; + GVfsDBusMountOperation *proxy; - message = dbus_message_new_method_call (source->dbus_id, - source->obj_path, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION); + proxy = create_mount_operation_proxy (source, callback, user_data); + if (proxy == NULL) + return; - _g_dbus_message_append_args (message, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &choices, n_choices, - 0); + /* 30 minute timeout */ + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30); result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, g_mount_source_ask_question_async); - /* 30 minute timeout */ - _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, - ask_question_reply, result); - dbus_message_unref (message); - + + gvfs_dbus_mount_operation_call_ask_question (proxy, + message_string ? message_string : "", + choices, + NULL, + (GAsyncReadyCallback) ask_question_reply, + result); + g_object_unref (proxy); } gboolean @@ -714,40 +721,40 @@ struct ShowProcessesData { /* the callback from dbus -> main thread */ static void -show_processes_reply (DBusMessage *reply, - GError *error, - gpointer _data) +show_processes_reply (GVfsDBusMountOperation *proxy, + GAsyncResult *res, + gpointer user_data) { GSimpleAsyncResult *result; ShowProcessesData *data; - dbus_bool_t handled, aborted; + gboolean handled, aborted; guint32 choice; - DBusMessageIter iter; - - result = G_SIMPLE_ASYNC_RESULT (_data); + GError *error; + + result = G_SIMPLE_ASYNC_RESULT (user_data); handled = TRUE; + g_print ("gmountsource.c: show_processes_reply()\n"); + data = g_new0 (ShowProcessesData, 1); g_simple_async_result_set_op_res_gpointer (result, data, g_free); - if (reply == NULL) + + error = NULL; + if (!gvfs_dbus_mount_operation_call_show_processes_finish (proxy, + &handled, + &aborted, + &choice, + res, + &error)) { data->aborted = TRUE; + g_simple_async_result_take_error (result, error); } else { - dbus_message_iter_init (reply, &iter); - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_BOOLEAN, &handled, - DBUS_TYPE_BOOLEAN, &aborted, - DBUS_TYPE_UINT32, &choice, - 0)) - data->aborted = TRUE; - else - { - data->aborted = aborted; - data->choice = choice; - } + data->aborted = aborted; + data->choice = choice; } if (handled == FALSE) @@ -769,42 +776,33 @@ g_mount_source_show_processes_async (GMountSource *source, gpointer user_data) { GSimpleAsyncResult *result; - DBusMessage *message; + GVfsDBusMountOperation *proxy; + GVariantBuilder builder; + guint i; + + proxy = create_mount_operation_proxy (source, callback, user_data); + if (proxy == NULL) + return; - /* If no dbus id specified, reply that we weren't handled */ - if (source->dbus_id[0] == 0) - { - g_simple_async_report_error_in_idle (G_OBJECT (source), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Internal Error"); - return; - } + /* 30 minute timeout */ + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30); result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, g_mount_source_show_processes_async); - - if (message_string == NULL) - message_string = ""; - - message = dbus_message_new_method_call (source->dbus_id, - source->obj_path, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES); - - _g_dbus_message_append_args (message, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &choices, n_choices, - DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, - &processes->data, processes->len, - 0); - - /* 30 minute timeout */ - _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, - show_processes_reply, result); - dbus_message_unref (message); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ai")); + for (i = 0; i < processes->len; i++) + g_variant_builder_add (&builder, "i", + g_array_index (processes, gint32, i)); + + gvfs_dbus_mount_operation_call_show_processes (proxy, + message_string ? message_string : "", + choices, + g_variant_builder_end (&builder), + NULL, + (GAsyncReadyCallback) show_processes_reply, + result); + g_object_unref (proxy); } gboolean @@ -931,23 +929,28 @@ op_show_processes (GMountOperation *op, return TRUE; } -/* the callback from dbus -> main thread */ static void -show_unmount_progress_reply (DBusMessage *reply, - GError *error, - gpointer _data) +show_unmount_progress_reply (GVfsDBusMountOperation *proxy, + GAsyncResult *res, + gpointer user_data) { - if (error != NULL) - g_warning ("ShowUnmountProgress request failed: %s", error->message); + GError *error; + + error = NULL; + if (!gvfs_dbus_mount_operation_call_show_unmount_progress_finish (proxy, res, &error)) + { + g_warning ("ShowUnmountProgress request failed: %s", error->message); + g_error_free (error); + } } void -g_mount_source_show_unmount_progress (GMountSource *source, - const char *message_string, - guint64 time_left, - guint64 bytes_left) +g_mount_source_show_unmount_progress (GMountSource *source, + const char *message_string, + guint64 time_left, + guint64 bytes_left) { - DBusMessage *message; + GVfsDBusMountOperation *proxy; /* If no dbus id specified, warn and return */ if (source->dbus_id[0] == 0) @@ -956,25 +959,22 @@ g_mount_source_show_unmount_progress (GMountSource *source, "ignoring show-unmount-progress request"); return; } - - if (message_string == NULL) - message_string = ""; - - message = dbus_message_new_method_call (source->dbus_id, - source->obj_path, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_UNMOUNT_PROGRESS); - - _g_dbus_message_append_args (message, - DBUS_TYPE_STRING, &message_string, - DBUS_TYPE_UINT64, &time_left, - DBUS_TYPE_UINT64, &bytes_left, - 0); + + proxy = create_mount_operation_proxy (source, NULL, NULL); + if (proxy == NULL) + return; /* 30 minute timeout */ - _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, - show_unmount_progress_reply, NULL); - dbus_message_unref (message); + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30); + + gvfs_dbus_mount_operation_call_show_unmount_progress (proxy, + message_string ? message_string : "", + time_left, + bytes_left, + NULL, + (GAsyncReadyCallback) show_unmount_progress_reply, + NULL); + g_object_unref (proxy); } static void @@ -991,38 +991,30 @@ op_show_unmount_progress (GMountOperation *op, g_signal_stop_emission_by_name (op, "show_unmount_progress"); } -gboolean -g_mount_source_abort (GMountSource *source) +static void +abort_reply (GVfsDBusMountOperation *proxy, + GAsyncResult *res, + gpointer user_data) { - DBusMessage *message; - DBusConnection *connection; - gboolean ret; - - ret = FALSE; - - /* If no dbus id specified, reply that we weren't handled */ - if (source->dbus_id[0] == 0) - goto out; + g_print ("gmountsource.c: abort_reply()\n"); - connection = dbus_bus_get (DBUS_BUS_SESSION, NULL); - if (connection == NULL) - goto out; - - message = dbus_message_new_method_call (source->dbus_id, - source->obj_path, - G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, - G_VFS_DBUS_MOUNT_OPERATION_OP_ABORTED); - - if (message) - { - dbus_connection_send (connection, message, NULL); - dbus_message_unref (message); - } + gvfs_dbus_mount_operation_call_aborted_finish (proxy, res, NULL); +} - ret = TRUE; +gboolean +g_mount_source_abort (GMountSource *source) +{ + GVfsDBusMountOperation *proxy; - out: - return ret; + proxy = create_mount_operation_proxy (source, NULL, NULL); + if (proxy == NULL) + return FALSE; + + gvfs_dbus_mount_operation_call_aborted (proxy, NULL, + (GAsyncReadyCallback) abort_reply, NULL); + + g_object_unref (proxy); + return TRUE; } static void diff --git a/common/gmountsource.h b/common/gmountsource.h index 31b58afe..ce93cb3b 100644 --- a/common/gmountsource.h +++ b/common/gmountsource.h @@ -54,8 +54,8 @@ GType g_mount_source_get_type (void) G_GNUC_CONST; GMountSource *g_mount_source_new (const char *dbus_id, const char *obj_path); GMountSource *g_mount_source_new_dummy (void); -void g_mount_source_to_dbus (GMountSource *source, - DBusMessage *message); +GVariant *g_mount_source_to_dbus (GMountSource *source); +GMountSource *g_mount_source_from_dbus (GVariant *iter); gboolean g_mount_source_ask_password (GMountSource *mount_source, const char *message, const char *initial_user, diff --git a/common/gmountspec.c b/common/gmountspec.c index 5c42d900..968032ca 100644 --- a/common/gmountspec.c +++ b/common/gmountspec.c @@ -27,7 +27,6 @@ #include <glib/gi18n-lib.h> -#include "gvfsdbusutils.h" #include "gmountspec.h" static GHashTable *unique_hash = NULL; @@ -226,113 +225,64 @@ g_mount_spec_unref (GMountSpec *spec) } GMountSpec * -g_mount_spec_from_dbus (DBusMessageIter *iter) +g_mount_spec_from_dbus (GVariant *iter) { GMountSpec *spec; - DBusMessageIter array_iter, struct_iter, spec_iter; - const char *key; - char *value; - char *mount_prefix; - - if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT) - return NULL; - - dbus_message_iter_recurse (iter, &spec_iter); + const gchar *key; + const gchar *mount_prefix; + GVariantIter *iter_mount_spec_items; + GVariant *value; mount_prefix = NULL; - if (!_g_dbus_message_iter_get_args (&spec_iter, NULL, - G_DBUS_TYPE_CSTRING, &mount_prefix, - 0)) - return NULL; - + g_variant_get (iter, "(^&aya{sv})", + &mount_prefix, + &iter_mount_spec_items); + spec = g_mount_spec_new (NULL); g_free (spec->mount_prefix); - spec->mount_prefix = mount_prefix; - - if (dbus_message_iter_get_arg_type (&spec_iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type (&spec_iter) != DBUS_TYPE_STRUCT) - { - g_mount_spec_unref (spec); - return NULL; - } + spec->mount_prefix = g_strdup (mount_prefix); - dbus_message_iter_recurse (&spec_iter, &array_iter); - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) + while (g_variant_iter_loop (iter_mount_spec_items, "{&sv}", &key, &value)) { - dbus_message_iter_recurse (&array_iter, &struct_iter); - if (_g_dbus_message_iter_get_args (&struct_iter, NULL, - DBUS_TYPE_STRING, &key, - G_DBUS_TYPE_CSTRING, &value, - 0)) - add_item (spec, key, value); - dbus_message_iter_next (&array_iter); + add_item (spec, key, g_variant_dup_bytestring (value, NULL)); } - dbus_message_iter_next (iter); - /* Sort on key */ g_array_sort (spec->items, item_compare); return spec; } -void -g_mount_spec_to_dbus_with_path (DBusMessageIter *iter, - GMountSpec *spec, +GVariant * +g_mount_spec_to_dbus_with_path (GMountSpec *spec, const char *path) { - DBusMessageIter spec_iter, array_iter, item_iter; + GVariantBuilder builder; + GVariant *v; int i; - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_STRUCT, - NULL, - &spec_iter)) - _g_dbus_oom (); - - _g_dbus_message_iter_append_cstring (&spec_iter, path ? path : ""); - - if (!dbus_message_iter_open_container (&spec_iter, - DBUS_TYPE_ARRAY, - G_MOUNT_SPEC_ITEM_TYPE_AS_STRING, - &array_iter)) - _g_dbus_oom (); - + g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); for (i = 0; i < spec->items->len; i++) { GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); - if (!dbus_message_iter_open_container (&array_iter, - DBUS_TYPE_STRUCT, - NULL, - &item_iter)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&item_iter, DBUS_TYPE_STRING, - &item->key)) - _g_dbus_oom (); - _g_dbus_message_iter_append_cstring (&item_iter, item->value); - - if (!dbus_message_iter_close_container (&array_iter, &item_iter)) - _g_dbus_oom (); - + g_variant_builder_add_value (&builder, g_variant_new ("{sv}", + item->key, + g_variant_new_bytestring (item->value))); } - if (!dbus_message_iter_close_container (&spec_iter, &array_iter)) - _g_dbus_oom (); - + v = g_variant_new ("(^aya{sv})", + path ? path : "", + &builder); + g_variant_builder_clear (&builder); - - if (!dbus_message_iter_close_container (iter, &spec_iter)) - _g_dbus_oom (); - + return v; } -void -g_mount_spec_to_dbus (DBusMessageIter *iter, - GMountSpec *spec) +GVariant * +g_mount_spec_to_dbus (GMountSpec *spec) { - g_mount_spec_to_dbus_with_path (iter, spec, spec->mount_prefix); + return g_mount_spec_to_dbus_with_path (spec, spec->mount_prefix); } static gboolean diff --git a/common/gmountspec.h b/common/gmountspec.h index f7837e65..da903e1b 100644 --- a/common/gmountspec.h +++ b/common/gmountspec.h @@ -24,28 +24,10 @@ #define __G_MOUNT_SPEC_H__ #include <glib.h> -#include <dbus/dbus.h> +#include <gio/gio.h> G_BEGIN_DECLS -#define G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \ - DBUS_TYPE_STRING_AS_STRING \ - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING - -#define G_MOUNT_SPEC_ITEM_TYPE_AS_STRING \ - DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ - G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \ - DBUS_STRUCT_END_CHAR_AS_STRING - -#define G_MOUNT_SPEC_INNER_TYPE_AS_STRING \ - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING \ - DBUS_TYPE_ARRAY_AS_STRING G_MOUNT_SPEC_ITEM_TYPE_AS_STRING - -#define G_MOUNT_SPEC_TYPE_AS_STRING \ - DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ - G_MOUNT_SPEC_INNER_TYPE_AS_STRING \ - DBUS_STRUCT_END_CHAR_AS_STRING - typedef struct { char *key; char *value; @@ -65,11 +47,9 @@ GMountSpec *g_mount_spec_ref (GMountSpec *spec); void g_mount_spec_unref (GMountSpec *spec); GMountSpec *g_mount_spec_get_unique_for (GMountSpec *spec); GMountSpec *g_mount_spec_copy (GMountSpec *spec); -GMountSpec *g_mount_spec_from_dbus (DBusMessageIter *iter); -void g_mount_spec_to_dbus (DBusMessageIter *iter, - GMountSpec *spec); -void g_mount_spec_to_dbus_with_path (DBusMessageIter *iter, - GMountSpec *spec, +GMountSpec *g_mount_spec_from_dbus (GVariant *iter); +GVariant *g_mount_spec_to_dbus (GMountSpec *spec); +GVariant *g_mount_spec_to_dbus_with_path (GMountSpec *spec, const char *path); void g_mount_spec_set_mount_prefix (GMountSpec *spec, const char *mount_prefix); diff --git a/common/gmounttracker.c b/common/gmounttracker.c index 00908ca0..a3909884 100644 --- a/common/gmounttracker.c +++ b/common/gmounttracker.c @@ -25,8 +25,8 @@ #include <string.h> #include <gmounttracker.h> -#include <gvfsdbusutils.h> #include <gvfsdaemonprotocol.h> +#include <gvfsdbus.h> enum { MOUNTED, @@ -51,14 +51,12 @@ struct _GMountTracker GMutex lock; GList *mounts; - DBusConnection *connection; + GDBusConnection *connection; + GVfsDBusMountTracker *proxy; }; G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT) -static DBusHandlerResult g_mount_tracker_filter_func (DBusConnection *conn, - DBusMessage *message, - gpointer data); static GObject* g_mount_tracker_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params); @@ -174,53 +172,41 @@ g_mount_info_apply_prefix (GMountInfo *info, } GMountInfo * -g_mount_info_from_dbus (DBusMessageIter *iter) +g_mount_info_from_dbus (GVariant *iter) { - DBusMessageIter struct_iter; GMountInfo *info; GMountSpec *mount_spec; - dbus_bool_t user_visible; - char *display_name; - char *stable_name; - char *x_content_types; - char *icon_str; - char *prefered_filename_encoding; - char *dbus_id; - char *obj_path; - char *fuse_mountpoint; - char *default_location; + gboolean user_visible; + const gchar *display_name; + const gchar *stable_name; + const gchar *x_content_types; + const gchar *icon_str; + const gchar *prefered_filename_encoding; + const gchar *dbus_id; + const gchar *obj_path; + const gchar *fuse_mountpoint; + const gchar *default_location; GIcon *icon; + GVariant *iter_mount_spec; GError *error; - if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT) + g_variant_get (iter, "(&s&o&s&s&s&s&sb^&ay@(aya{sv})^&ay)", + &dbus_id, + &obj_path, + &display_name, + &stable_name, + &x_content_types, + &icon_str, + &prefered_filename_encoding, + &user_visible, + &fuse_mountpoint, + &iter_mount_spec, + &default_location); + + mount_spec = g_mount_spec_from_dbus (iter_mount_spec); + g_variant_unref (iter_mount_spec); + if (mount_spec == NULL) return NULL; - - dbus_message_iter_recurse (iter, &struct_iter); - - if (!_g_dbus_message_iter_get_args (&struct_iter, NULL, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_STRING, &display_name, - DBUS_TYPE_STRING, &stable_name, - DBUS_TYPE_STRING, &x_content_types, - DBUS_TYPE_STRING, &icon_str, - DBUS_TYPE_STRING, &prefered_filename_encoding, - DBUS_TYPE_BOOLEAN, &user_visible, - G_DBUS_TYPE_CSTRING, &fuse_mountpoint, - 0)) - return NULL; - - mount_spec = g_mount_spec_from_dbus (&struct_iter); - if (mount_spec == NULL) { - g_free (fuse_mountpoint); - return NULL; - } - - if (!_g_dbus_message_iter_get_args (&struct_iter, NULL, - G_DBUS_TYPE_CSTRING, &default_location, - 0)) - default_location = g_strdup (""); - if (icon_str == NULL || strlen (icon_str) == 0) icon_str = "drive-removable-media"; @@ -244,13 +230,12 @@ g_mount_info_from_dbus (DBusMessageIter *iter) info->mount_spec = mount_spec; info->user_visible = user_visible; info->prefered_filename_encoding = g_strdup (prefered_filename_encoding); - info->fuse_mountpoint = fuse_mountpoint; - info->default_location = default_location; + info->fuse_mountpoint = g_strdup (fuse_mountpoint); + info->default_location = g_strdup (default_location); return info; } - static void g_mount_tracker_finalize (GObject *object) { @@ -264,21 +249,10 @@ g_mount_tracker_finalize (GObject *object) (GFunc)g_mount_info_unref, NULL); g_list_free (tracker->mounts); - dbus_connection_remove_filter (tracker->connection, g_mount_tracker_filter_func, tracker); - - - dbus_bus_remove_match (tracker->connection, - "sender='"G_VFS_DBUS_DAEMON_NAME"'," - "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," - "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'", - NULL); - dbus_bus_remove_match (tracker->connection, - "sender='"G_VFS_DBUS_DAEMON_NAME"'," - "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," - "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'", - NULL); - - dbus_connection_unref (tracker->connection); + if (tracker->proxy) + g_object_unref (tracker->proxy); + if (tracker->connection) + g_object_unref (tracker->connection); if (G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (*G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (object); @@ -332,10 +306,10 @@ g_mount_tracker_set_property (GObject *object, { case PROP_CONNECTION: if (tracker->connection) - dbus_connection_unref (tracker->connection); + g_object_unref (tracker->connection); tracker->connection = NULL; if (g_value_get_pointer (value)) - tracker->connection = dbus_connection_ref (g_value_get_pointer (value)); + tracker->connection = g_object_ref (g_value_get_pointer (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -427,115 +401,94 @@ g_mount_tracker_remove_mount (GMountTracker *tracker, static void list_mounts_reply (GMountTracker *tracker, - DBusMessage *reply) + GVariant *iter_mounts) { - DBusMessageIter iter, array_iter; GMountInfo *info; - gboolean b; - - b = dbus_message_iter_init (reply, &iter); - if (b && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) + GVariantIter iter; + GVariant *child; + + g_variant_iter_init (&iter, iter_mounts); + while ((child = g_variant_iter_next_value (&iter))) { - dbus_message_iter_recurse (&iter, &array_iter); - - do + info = g_mount_info_from_dbus (child); + if (info) { - info = g_mount_info_from_dbus (&array_iter); - if (info) - { - g_mount_tracker_add_mount (tracker, info); - g_mount_info_unref (info); - } + g_mount_tracker_add_mount (tracker, info); + g_mount_info_unref (info); } - while (dbus_message_iter_next (&array_iter)); - } - else - { - /* list_mounts_reply problem - gvfsd not running? */ + g_variant_unref (child); } } -static DBusHandlerResult -g_mount_tracker_filter_func (DBusConnection *conn, - DBusMessage *message, - gpointer data) +static void +mounted_cb (GVfsDBusMountTracker *object, + GVariant *arg_mount, + gpointer user_data) { - GMountTracker *tracker = data; + GMountTracker *tracker = user_data; GMountInfo *info; - DBusMessageIter iter; - - if (dbus_message_is_signal (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED)) + + info = g_mount_info_from_dbus (arg_mount); + if (info) { - 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_unref (info); - } + g_mount_tracker_add_mount (tracker, info); + g_mount_info_unref (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_unref (info); - } +static void +unmounted_cb (GVfsDBusMountTracker *object, + GVariant *arg_mount, + gpointer user_data) +{ + GMountTracker *tracker = user_data; + GMountInfo *info; + + info = g_mount_info_from_dbus (arg_mount); + if (info) + { + g_mount_tracker_remove_mount (tracker, info); + g_mount_info_unref (info); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } /* Called after construction when the construct properties (like connection) are set */ static void init_connection (GMountTracker *tracker) { - DBusMessage *message, *reply; + GError *error; + GVariant *iter_mounts; if (tracker->connection == NULL) - tracker->connection = dbus_bus_get (DBUS_BUS_SESSION, 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); - if (message == NULL) - _g_dbus_oom (); - - dbus_message_set_auto_start (message, TRUE); - - reply = dbus_connection_send_with_reply_and_block (tracker->connection, message, - G_VFS_DBUS_TIMEOUT_MSECS, - NULL); - dbus_message_unref (message); - - if (reply != NULL) + tracker->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + + error = NULL; + tracker->proxy = gvfs_dbus_mount_tracker_proxy_new_sync (tracker->connection, + G_DBUS_PROXY_FLAGS_NONE, + G_VFS_DBUS_DAEMON_NAME, + G_VFS_DBUS_MOUNTTRACKER_PATH, + NULL, + &error); + if (tracker->proxy == NULL) { - list_mounts_reply (tracker, reply); - dbus_message_unref (reply); + g_printerr ("Error creating proxy: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + return; } - - dbus_connection_add_filter (tracker->connection, g_mount_tracker_filter_func, tracker, NULL); - - dbus_bus_add_match (tracker->connection, - "sender='"G_VFS_DBUS_DAEMON_NAME"'," - "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," - "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'", - NULL); - dbus_bus_add_match (tracker->connection, - "sender='"G_VFS_DBUS_DAEMON_NAME"'," - "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"'," - "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'", - NULL); + + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (tracker->proxy), + G_VFS_DBUS_TIMEOUT_MSECS); + + if (gvfs_dbus_mount_tracker_call_list_mounts_sync (tracker->proxy, &iter_mounts, NULL, NULL)) + { + list_mounts_reply (tracker, iter_mounts); + g_variant_unref (iter_mounts); + } + + g_signal_connect (tracker->proxy, "mounted", G_CALLBACK (mounted_cb), tracker); + g_signal_connect (tracker->proxy, "unmounted", G_CALLBACK (unmounted_cb), tracker); } static void @@ -565,7 +518,7 @@ g_mount_tracker_constructor (GType type, } GMountTracker * -g_mount_tracker_new (DBusConnection *connection) +g_mount_tracker_new (GDBusConnection *connection) { GMountTracker *tracker; diff --git a/common/gmounttracker.h b/common/gmounttracker.h index caaab8a6..894bddb3 100644 --- a/common/gmounttracker.h +++ b/common/gmounttracker.h @@ -76,9 +76,9 @@ const char *g_mount_info_resolve_path (GMountInfo *info, void g_mount_info_apply_prefix (GMountInfo *info, char **path); -GMountInfo * g_mount_info_from_dbus (DBusMessageIter *iter); +GMountInfo * g_mount_info_from_dbus (GVariant *iter); -GMountTracker *g_mount_tracker_new (DBusConnection *connection); +GMountTracker *g_mount_tracker_new (GDBusConnection *connection); GList * g_mount_tracker_list_mounts (GMountTracker *tracker); GMountInfo * g_mount_tracker_find_by_mount_spec (GMountTracker *tracker, GMountSpec *mount_spec); diff --git a/common/gvfsdaemonprotocol.c b/common/gvfsdaemonprotocol.c index b35efcb9..c73aac7d 100644 --- a/common/gvfsdaemonprotocol.c +++ b/common/gvfsdaemonprotocol.c @@ -23,48 +23,22 @@ #include <config.h> #include <glib-object.h> -#include <dbus/dbus.h> #include <glib/gi18n-lib.h> #include <gvfsdaemonprotocol.h> -#include <gvfsdbusutils.h> #include <gio/gio.h> static const char * get_object_signature (GObject *obj) { if (G_IS_ICON (obj)) - { - return - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_UINT32_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_STRUCT_END_CHAR_AS_STRING; - } - return - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_UINT32_AS_STRING - DBUS_STRUCT_END_CHAR_AS_STRING; + return "(us)"; + return "(u)"; } -static void -append_strv (DBusMessageIter *iter, char **strv) +static GVariant * +append_object (GObject *obj) { - _g_dbus_message_iter_append_args (iter, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &strv, g_strv_length (strv), - 0); -} - -static void -append_object (DBusMessageIter *iter, GObject *obj) -{ - DBusMessageIter obj_struct_iter; - guint32 v_uint32; - - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_STRUCT, - NULL, - &obj_struct_iter)) - _g_dbus_oom (); + GVariant *var; /* version 1 and 2 are deprecated old themed-icon and file-icon values */ if (G_IS_ICON (obj)) @@ -72,15 +46,7 @@ append_object (DBusMessageIter *iter, GObject *obj) char *data; data = g_icon_to_string (G_ICON (obj)); - v_uint32 = 3; - if (!dbus_message_iter_append_basic (&obj_struct_iter, - DBUS_TYPE_UINT32, &v_uint32)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&obj_struct_iter, - DBUS_TYPE_STRING, &data)) - _g_dbus_oom (); - + var = g_variant_new ("(us)", 3, data); g_free (data); } else @@ -89,14 +55,10 @@ append_object (DBusMessageIter *iter, GObject *obj) if (obj != NULL) g_warning ("Unknown attribute object type, ignoring"); - v_uint32 = 0; - if (!dbus_message_iter_append_basic (&obj_struct_iter, - DBUS_TYPE_UINT32, &v_uint32)) - _g_dbus_oom (); + var = g_variant_new ("(u)", 0); } - - if (!dbus_message_iter_close_container (iter, &obj_struct_iter)) - _g_dbus_oom (); + + return var; } void @@ -135,42 +97,42 @@ _g_dbus_attribute_as_pointer (GFileAttributeType type, } } -const char * +static const char * _g_dbus_type_from_file_attribute_type (GFileAttributeType type) { - char *dbus_type; + const char *dbus_type; switch (type) { case G_FILE_ATTRIBUTE_TYPE_STRING: - dbus_type = DBUS_TYPE_STRING_AS_STRING; + dbus_type = "s"; break; case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: - dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING; + dbus_type = "ay"; break; case G_FILE_ATTRIBUTE_TYPE_STRINGV: - dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; + dbus_type = "as"; break; case G_FILE_ATTRIBUTE_TYPE_BOOLEAN: - dbus_type = DBUS_TYPE_BOOLEAN_AS_STRING; + dbus_type = "b"; break; case G_FILE_ATTRIBUTE_TYPE_UINT32: - dbus_type = DBUS_TYPE_UINT32_AS_STRING; + dbus_type = "u"; break; case G_FILE_ATTRIBUTE_TYPE_INT32: - dbus_type = DBUS_TYPE_INT32_AS_STRING; + dbus_type = "i"; break; case G_FILE_ATTRIBUTE_TYPE_UINT64: - dbus_type = DBUS_TYPE_UINT64_AS_STRING; + dbus_type = "t"; break; case G_FILE_ATTRIBUTE_TYPE_INT64: - dbus_type = DBUS_TYPE_INT64_AS_STRING; + dbus_type = "x"; break; case G_FILE_ATTRIBUTE_TYPE_OBJECT: - dbus_type = DBUS_TYPE_STRUCT_AS_STRING; + dbus_type = "r"; break; case G_FILE_ATTRIBUTE_TYPE_INVALID: - dbus_type = DBUS_TYPE_BYTE_AS_STRING; + dbus_type = "ay"; break; default: dbus_type = NULL; @@ -181,114 +143,65 @@ _g_dbus_type_from_file_attribute_type (GFileAttributeType type) return dbus_type; } -void -_g_dbus_append_file_attribute (DBusMessageIter *iter, - const char *attribute, +GVariant * +_g_dbus_append_file_attribute (const char *attribute, GFileAttributeStatus status, GFileAttributeType type, gpointer value_p) { - DBusMessageIter variant_iter, inner_struct_iter; const char *dbus_type; - guint32 dbus_status; + GVariant *v; dbus_type = _g_dbus_type_from_file_attribute_type (type); - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_STRUCT, - NULL, - &inner_struct_iter)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&inner_struct_iter, - DBUS_TYPE_STRING, - &attribute)) - _g_dbus_oom (); - - dbus_status = status; - if (!dbus_message_iter_append_basic (&inner_struct_iter, - DBUS_TYPE_UINT32, - &dbus_status)) - _g_dbus_oom (); - - if (dbus_type[0] == DBUS_TYPE_STRUCT) + if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_TUPLE)) dbus_type = get_object_signature ((GObject *)value_p); - - if (!dbus_message_iter_open_container (&inner_struct_iter, - DBUS_TYPE_VARIANT, - dbus_type, - &variant_iter)) - _g_dbus_oom (); - if (dbus_type[0] == DBUS_TYPE_STRING) - { - if (!dbus_message_iter_append_basic (&variant_iter, - DBUS_TYPE_STRING, &value_p)) - _g_dbus_oom (); - } - else if (dbus_type[0] == DBUS_TYPE_ARRAY && dbus_type[1] == DBUS_TYPE_BYTE) - _g_dbus_message_iter_append_cstring (&variant_iter, (char *)value_p); - else if (dbus_type[0] == DBUS_TYPE_ARRAY && dbus_type[1] == DBUS_TYPE_STRING) - append_strv (&variant_iter, (char **)value_p); - else if (dbus_type[0] == DBUS_TYPE_BYTE) - { - char byte = 0; - if (!dbus_message_iter_append_basic (&variant_iter, - DBUS_TYPE_BYTE, &byte)) - _g_dbus_oom (); - } - else if (dbus_type[0] == DBUS_STRUCT_BEGIN_CHAR) - append_object (&variant_iter, (GObject *)value_p); - else if (dbus_type[0] == DBUS_TYPE_BOOLEAN) - { - /* dbus bool is uint32, gboolean is just "int", convert */ - dbus_bool_t bool = *(gboolean *)value_p; - if (!dbus_message_iter_append_basic (&variant_iter, - dbus_type[0], &bool)) - _g_dbus_oom (); - } + if (g_variant_type_is_tuple (G_VARIANT_TYPE (dbus_type))) + v = append_object ((GObject *)value_p); else + if (g_variant_type_is_array (G_VARIANT_TYPE (dbus_type))) { - /* All other types have the same size as dbus types */ - if (!dbus_message_iter_append_basic (&variant_iter, - dbus_type[0], value_p)) - _g_dbus_oom (); - } - - if (!dbus_message_iter_close_container (&inner_struct_iter, &variant_iter)) - _g_dbus_oom (); + char *s; - if (!dbus_message_iter_close_container (iter, &inner_struct_iter)) - _g_dbus_oom (); + s = g_strdup_printf ("^%s", dbus_type); + v = g_variant_new (s, value_p); + g_free (s); + } + else + if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_UINT32)) + v = g_variant_new (dbus_type, *(guint32 *)value_p); + else + if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_INT32)) + v = g_variant_new (dbus_type, *(gint32 *)value_p); + else + if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_UINT64)) + v = g_variant_new (dbus_type, *(guint64 *)value_p); + else + if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_INT64)) + v = g_variant_new (dbus_type, *(gint64 *)value_p); + else + if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_BOOLEAN)) + v = g_variant_new (dbus_type, *(gboolean *)value_p); + else + v = g_variant_new (dbus_type, value_p); + + return g_variant_new ("(suv)", + attribute, + status, + v); } -void -_g_dbus_append_file_info (DBusMessageIter *iter, - GFileInfo *info) +GVariant * +_g_dbus_append_file_info (GFileInfo *info) { - DBusMessageIter struct_iter, array_iter; + GVariantBuilder builder; char **attributes; int i; - attributes = g_file_info_list_attributes (info, NULL); - - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_STRUCT, - NULL, - &struct_iter)) - _g_dbus_oom (); - - - if (!dbus_message_iter_open_container (&struct_iter, - DBUS_TYPE_ARRAY, - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_UINT32_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_STRUCT_END_CHAR_AS_STRING, - &array_iter)) - _g_dbus_oom (); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(suv)")); + attributes = g_file_info_list_attributes (info, NULL); for (i = 0; attributes[i] != NULL; i++) { GFileAttributeType type; @@ -296,323 +209,194 @@ _g_dbus_append_file_info (DBusMessageIter *iter, gpointer value_p; if (g_file_info_get_attribute_data (info, attributes[i], &type, &value_p, &status)) - _g_dbus_append_file_attribute (&array_iter, attributes [i], status, type, value_p); + g_variant_builder_add_value (&builder, + _g_dbus_append_file_attribute (attributes[i], status, type, value_p)); } - g_strfreev (attributes); - if (!dbus_message_iter_close_container (&struct_iter, &array_iter)) - _g_dbus_oom (); - - if (!dbus_message_iter_close_container (iter, &struct_iter)) - _g_dbus_oom (); + return g_variant_builder_end (&builder); } gboolean -_g_dbus_get_file_attribute (DBusMessageIter *iter, +_g_dbus_get_file_attribute (GVariant *iter, gchar **attribute, GFileAttributeStatus *status, GFileAttributeType *type, GDbusAttributeValue *value) { + gboolean res; char *str; - char **strs; - int n_elements; - DBusMessageIter inner_struct_iter, variant_iter, cstring_iter, obj_iter; - const gchar *attribute_temp; - int element_type; - dbus_uint32_t obj_type, dbus_status; - dbus_bool_t dbus_bool; - guint8 byte; + guint32 obj_type; GObject *obj; + GVariant *v; - dbus_message_iter_recurse (iter, &inner_struct_iter); - - if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING) - goto error; - - dbus_message_iter_get_basic (&inner_struct_iter, &attribute_temp); - *attribute = g_strdup (attribute_temp); - - dbus_message_iter_next (&inner_struct_iter); - - dbus_message_iter_get_basic (&inner_struct_iter, &dbus_status); - if (status) - *status = dbus_status; - - dbus_message_iter_next (&inner_struct_iter); - - if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT) - goto error; - - dbus_message_iter_recurse (&inner_struct_iter, &variant_iter); + g_variant_get (iter, "(suv)", + attribute, + status, + &v); - switch (dbus_message_iter_get_arg_type (&variant_iter)) + res = TRUE; + if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)) { - case DBUS_TYPE_STRING: *type = G_FILE_ATTRIBUTE_TYPE_STRING; - dbus_message_iter_get_basic (&variant_iter, &str); - value->ptr = g_strdup (str); - break; - case DBUS_TYPE_ARRAY: - element_type = dbus_message_iter_get_element_type (&variant_iter); - if (element_type == DBUS_TYPE_BYTE) - { - *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING; - - dbus_message_iter_recurse (&variant_iter, &cstring_iter); - dbus_message_iter_get_fixed_array (&cstring_iter, - &str, &n_elements); - value->ptr = g_strndup (str, n_elements); - } - else if (element_type == DBUS_TYPE_STRING) - { - char **strv; - int n_elements; - if (!_g_dbus_message_iter_get_args (&variant_iter, NULL, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &strv, &n_elements, - 0)) - goto error; - *type = G_FILE_ATTRIBUTE_TYPE_STRINGV; - value->ptr = strv; - } - else - goto error; - - break; - case DBUS_TYPE_BYTE: - dbus_message_iter_get_basic (&variant_iter, &byte); + g_variant_get (v, "s", &value->ptr); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_BYTESTRING)) + { + *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING; + g_variant_get (v, "^ay", &value->ptr); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING_ARRAY)) + { + *type = G_FILE_ATTRIBUTE_TYPE_STRINGV; + g_variant_get (v, "^as", &value->ptr); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_BYTE)) + { *type = G_FILE_ATTRIBUTE_TYPE_INVALID; - break; - case DBUS_TYPE_BOOLEAN: - dbus_message_iter_get_basic (&variant_iter, &dbus_bool); - value->boolean = dbus_bool; + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) + { *type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN; - break; - case DBUS_TYPE_UINT32: - dbus_message_iter_get_basic (&variant_iter, value); + g_variant_get (v, "b", &value->boolean); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_UINT32)) + { *type = G_FILE_ATTRIBUTE_TYPE_UINT32; - break; - case DBUS_TYPE_INT32: - dbus_message_iter_get_basic (&variant_iter, value); + g_variant_get (v, "u", &value->uint32); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_INT32)) + { *type = G_FILE_ATTRIBUTE_TYPE_INT32; - break; - case DBUS_TYPE_UINT64: - dbus_message_iter_get_basic (&variant_iter, value); + g_variant_get (v, "i", &value->ptr); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_UINT64)) + { *type = G_FILE_ATTRIBUTE_TYPE_UINT64; - break; - case DBUS_TYPE_INT64: - dbus_message_iter_get_basic (&variant_iter, value); + g_variant_get (v, "t", &value->uint64); + } + else + if (g_variant_is_of_type (v, G_VARIANT_TYPE_INT64)) + { *type = G_FILE_ATTRIBUTE_TYPE_INT64; - break; - case DBUS_TYPE_STRUCT: - dbus_message_iter_recurse (&variant_iter, &obj_iter); - if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32) - goto error; - + g_variant_get (v, "x", &value->ptr); + } + else + if (g_variant_is_container (v)) + { *type = G_FILE_ATTRIBUTE_TYPE_OBJECT; - dbus_message_iter_get_basic (&obj_iter, &obj_type); - obj = NULL; - - dbus_message_iter_next (&obj_iter); - /* 0 == NULL */ - - if (obj_type == 1) - { - /* Old deprecated G_THEMED_ICON */ - if (_g_dbus_message_iter_get_args (&obj_iter, - NULL, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &strs, &n_elements, 0)) - { - obj = G_OBJECT (g_themed_icon_new_from_names (strs, n_elements)); - g_strfreev (strs); - } - } - else if (obj_type == 2) - { - /* Old deprecated G_FILE_ICON, w/ local file */ - if (_g_dbus_message_iter_get_args (&obj_iter, - NULL, - G_DBUS_TYPE_CSTRING, &str, - 0)) - { - GFile *file = g_file_new_for_path (str); - obj = G_OBJECT (g_file_icon_new (file)); - g_free (str); - } - } - else if (obj_type == 3) - { - /* serialized G_ICON */ - if (_g_dbus_message_iter_get_args (&obj_iter, - NULL, - DBUS_TYPE_STRING, &str, - 0)) - obj = (GObject *)g_icon_new_for_string (str, NULL); - } + if (g_variant_is_of_type (v, G_VARIANT_TYPE ("(u)"))) + { + g_variant_get (v, "(u)", &obj_type); + } else - { - /* NULL (or unsupported) */ - if (obj_type != 0) - g_warning ("Unsupported object type in file attribute"); - } + if (g_variant_is_of_type (v, G_VARIANT_TYPE ("(us)"))) + { + g_variant_get (v, "(u&s)", &obj_type, &str); + } - value->ptr = obj; - break; - default: - goto error; - } + obj = NULL; - return TRUE; + /* obj_type 1 and 2 are deprecated and treated as errors */ + if (obj_type == 3) + { + /* serialized G_ICON */ + obj = (GObject *)g_icon_new_for_string (str, NULL); + } + else + { + /* NULL (or unsupported) */ + if (obj_type != 0) + g_warning ("Unsupported object type in file attribute"); + } + value->ptr = obj; + } + else + res = FALSE; - error: - return FALSE; + g_variant_unref (v); + + return res; } GFileInfo * -_g_dbus_get_file_info (DBusMessageIter *iter, +_g_dbus_get_file_info (GVariant *iter, GError **error) { GFileInfo *info; - DBusMessageIter struct_iter, array_iter; gchar *attribute; GFileAttributeType type; GFileAttributeStatus status; GDbusAttributeValue value; + GVariantIter i; + GVariant *child; info = g_file_info_new (); - if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT) - goto error; - - dbus_message_iter_recurse (iter, &struct_iter); - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY) - goto error; - - dbus_message_iter_recurse (&struct_iter, &array_iter); - - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) + g_variant_iter_init (&i, iter); + while ((child = g_variant_iter_next_value (&i))) { - if (!_g_dbus_get_file_attribute (&array_iter, &attribute, &status, &type, &value)) + if (!_g_dbus_get_file_attribute (child, &attribute, &status, &type, &value)) goto error; g_file_info_set_attribute (info, attribute, type, _g_dbus_attribute_as_pointer (type, &value)); if (status) - g_file_info_set_attribute_status (info, attribute, status); + g_file_info_set_attribute_status (info, attribute, status); g_free (attribute); _g_dbus_attribute_value_destroy (type, &value); - dbus_message_iter_next (&array_iter); + g_variant_unref (child); } - dbus_message_iter_next (iter); return info; error: g_object_unref (info); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Invalid file info format")); - dbus_message_iter_next (iter); return NULL; } GFileAttributeInfoList * -_g_dbus_get_attribute_info_list (DBusMessageIter *iter, +_g_dbus_get_attribute_info_list (GVariant *iter, GError **error) { GFileAttributeInfoList *list; - DBusMessageIter array_iter, struct_iter; + GVariantIter i; const char *name; - dbus_uint32_t type, flags; + guint32 type, flags; - if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type (iter) != DBUS_TYPE_STRUCT) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid attribute info list content")); - return NULL; - } - list = g_file_attribute_info_list_new (); - dbus_message_iter_recurse (iter, &array_iter); - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) - { - dbus_message_iter_recurse (&array_iter, &struct_iter); - - if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic (&struct_iter, &name); - dbus_message_iter_next (&struct_iter); - - if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32) - { - dbus_message_iter_get_basic (&struct_iter, &type); - dbus_message_iter_next (&struct_iter); - - if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32) - { - dbus_message_iter_get_basic (&struct_iter, &flags); - - g_file_attribute_info_list_add (list, name, type, flags); - } - } - } + g_variant_iter_init (&i, iter); + while (g_variant_iter_next (&i, "(&suu)", &name, &type, &flags)) + g_file_attribute_info_list_add (list, name, type, flags); - dbus_message_iter_next (&array_iter); - } - return list; } -void -_g_dbus_append_attribute_info_list (DBusMessageIter *iter, - GFileAttributeInfoList *list) +GVariant * +_g_dbus_append_attribute_info_list (GFileAttributeInfoList *list) { - DBusMessageIter array_iter, struct_iter; + GVariantBuilder builder; int i; - dbus_uint32_t dbus_type, dbus_flags; - - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_ARRAY, - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_UINT32_AS_STRING - DBUS_TYPE_UINT32_AS_STRING - DBUS_STRUCT_END_CHAR_AS_STRING, - &array_iter)) - _g_dbus_oom (); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(suu)")); for (i = 0; i < list->n_infos; i++) - { - if (!dbus_message_iter_open_container (&array_iter, - DBUS_TYPE_STRUCT, - NULL, - &struct_iter)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, &list->infos[i].name)) - _g_dbus_oom (); - - dbus_type = list->infos[i].type; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT32, &dbus_type)) - _g_dbus_oom (); - - dbus_flags = list->infos[i].flags; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT32, &dbus_flags)) - _g_dbus_oom (); - - if (!dbus_message_iter_close_container (&array_iter, &struct_iter)) - _g_dbus_oom (); - } + g_variant_builder_add (&builder, "(suu)", + list->infos[i].name, + list->infos[i].type, + list->infos[i].flags); - if (!dbus_message_iter_close_container (iter, &array_iter)) - _g_dbus_oom (); + return g_variant_builder_end (&builder); } diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h index bc754866..6325e2db 100644 --- a/common/gvfsdaemonprotocol.h +++ b/common/gvfsdaemonprotocol.h @@ -186,26 +186,22 @@ void _g_dbus_attribute_value_destroy (GFileAttributeType ty GDbusAttributeValue *value); gpointer _g_dbus_attribute_as_pointer (GFileAttributeType type, GDbusAttributeValue *value); -const char*_g_dbus_type_from_file_attribute_type (GFileAttributeType type); -void _g_dbus_append_file_attribute (DBusMessageIter *iter, - const char *attribute, +GVariant * _g_dbus_append_file_attribute (const char *attribute, GFileAttributeStatus status, GFileAttributeType type, gpointer value_p); -void _g_dbus_append_file_info (DBusMessageIter *iter, - GFileInfo *file_info); -gboolean _g_dbus_get_file_attribute (DBusMessageIter *iter, +GVariant * _g_dbus_append_file_info (GFileInfo *file_info); +gboolean _g_dbus_get_file_attribute (GVariant *iter, gchar **attribute, GFileAttributeStatus *status, GFileAttributeType *type, GDbusAttributeValue *value); -GFileInfo *_g_dbus_get_file_info (DBusMessageIter *iter, +GFileInfo *_g_dbus_get_file_info (GVariant *iter, GError **error); -GFileAttributeInfoList *_g_dbus_get_attribute_info_list (DBusMessageIter *iter, +GFileAttributeInfoList *_g_dbus_get_attribute_info_list (GVariant *iter, GError **error); -void _g_dbus_append_attribute_info_list (DBusMessageIter *iter, - GFileAttributeInfoList *list); +GVariant * _g_dbus_append_attribute_info_list (GFileAttributeInfoList *list); G_END_DECLS diff --git a/daemon/daemon-main.c b/daemon/daemon-main.c index 39dea834..25ad3d98 100644 --- a/daemon/daemon-main.c +++ b/daemon/daemon-main.c @@ -28,17 +28,21 @@ #include <locale.h> #include <glib.h> -#include <dbus/dbus.h> #include "daemon-main.h" #include <glib/gi18n.h> #include <gvfsdaemon.h> -#include <gvfsdaemonprotocol.h> #include <gvfsbackend.h> +#include <gvfsdbus.h> static char *spawner_id = NULL; static char *spawner_path = NULL; static gboolean print_debug = FALSE; +static gboolean already_acquired = FALSE; +static int process_result = 0; + +static GMainLoop *loop; + static void log_debug (const gchar *log_domain, @@ -53,8 +57,8 @@ log_debug (const gchar *log_domain, void daemon_init (void) { - DBusConnection *connection; - DBusError derror; + GDBusConnection *conn; + GError *error; setlocale (LC_ALL, ""); @@ -62,7 +66,6 @@ daemon_init (void) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - dbus_threads_init_default (); g_type_init (); g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, log_debug, NULL); @@ -73,16 +76,17 @@ daemon_init (void) */ signal (SIGPIPE, SIG_IGN); #endif - - dbus_error_init (&derror); - connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); - if (connection == NULL) + + error = NULL; + conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (!conn) { - g_printerr (_("Error connecting to D-Bus: %s"), derror.message); - g_printerr ("\n"); - dbus_error_free (&derror); + g_printerr ("Error connecting to D-Bus: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); exit (1); } + g_object_unref (conn); } void @@ -99,11 +103,69 @@ daemon_setup (void) g_free (up); } +typedef struct { + GVfsDaemon *daemon; + GMountSpec *mount_spec; + int max_job_threads; + char *mountable_name; +} DaemonData; + +typedef struct { + GDestroyNotify callback; + gpointer user_data; +} SpawnData; + +static void +spawned_failed_cb (gpointer user_data) +{ + process_result = 1; + g_main_loop_quit (loop); +} + +static void +spawned_succeeded_cb (gpointer user_data) +{ + DaemonData *data = user_data; + GMountSource *mount_source; + + if (data->mount_spec) + { + mount_source = g_mount_source_new_dummy (); + g_vfs_daemon_initiate_mount (data->daemon, data->mount_spec, mount_source, FALSE, NULL, NULL); + g_mount_spec_unref (data->mount_spec); + g_object_unref (mount_source); + } +} + static void -send_spawned (DBusConnection *connection, gboolean succeeded, char *error_message) +call_spawned_cb (GVfsDBusSpawner *proxy, + GAsyncResult *res, + gpointer user_data) { - DBusMessage *message; - dbus_bool_t dbus_succeeded; + GError *error = NULL; + SpawnData *data = user_data; + + if (! gvfs_dbus_spawner_call_spawned_finish (proxy, res, &error)) + { + g_printerr ("call_spawned_cb: Error sending a message: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + g_print ("call_spawned_cb\n"); + + data->callback (data->user_data); + g_free (data); +} + +static void +send_spawned (gboolean succeeded, + char *error_message, + GDestroyNotify callback, + gpointer user_data) +{ + GVfsDBusSpawner *proxy; + GError *error; + SpawnData *data; if (error_message == NULL) error_message = ""; @@ -115,26 +177,42 @@ send_spawned (DBusConnection *connection, gboolean succeeded, char *error_messag g_printerr (_("Error: %s"), error_message); g_printerr ("\n"); } + callback (user_data); return; } + + g_print ("sending spawned.\n"); - message = dbus_message_new_method_call (spawner_id, - spawner_path, - G_VFS_DBUS_SPAWNER_INTERFACE, - G_VFS_DBUS_OP_SPAWNED); - dbus_message_set_no_reply (message, TRUE); - - dbus_succeeded = succeeded; - if (!dbus_message_append_args (message, - DBUS_TYPE_BOOLEAN, &dbus_succeeded, - DBUS_TYPE_STRING, &error_message, - DBUS_TYPE_INVALID)) - _g_dbus_oom (); - - dbus_connection_send (connection, message, NULL); - dbus_message_unref (message); - /* Make sure the message is sent */ - dbus_connection_flush (connection); + error = NULL; + g_print ("send_spawned: before proxy creation, spawner_id = '%s', spawner_path = '%s'\n", spawner_id, spawner_path); + proxy = gvfs_dbus_spawner_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + spawner_id, + spawner_path, + NULL, + &error); + g_print ("send_spawned: after proxy creation\n"); + if (proxy == NULL) + { + g_printerr ("Error creating proxy: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + return; + } + + data = g_new0 (SpawnData, 1); + data->callback = callback; + data->user_data = user_data; + + g_print ("send_spawned: before call_spawned\n"); + gvfs_dbus_spawner_call_spawned (proxy, + succeeded, + error_message, + NULL, + (GAsyncReadyCallback) call_spawned_cb, + data); + + g_object_unref (proxy); } GMountSpec * @@ -209,6 +287,67 @@ daemon_parse_args (int argc, char *argv[], const char *default_type) return mount_spec; } +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + DaemonData *data = user_data; + gchar *s; + + if (connection == NULL) + { + g_printerr ("A connection to the bus can't be made\n"); + process_result = 1; + } + else + { + if (already_acquired) + { + g_printerr ("Got NameLost, some other instance replaced us\n"); + } + else + { + s = g_strdup_printf (_("mountpoint for %s already running"), data->mountable_name); + g_printerr (_("Error: %s"), s); + g_printerr ("\n"); + g_free (s); + process_result = 1; + } + } + g_main_loop_quit (loop); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + DaemonData *data = user_data; + + g_warning ("daemon-main.c: Acquired the name on the session message bus\n"); + + already_acquired = TRUE; + + data->daemon = g_vfs_daemon_new (FALSE, FALSE); + if (data->daemon == NULL) + { + send_spawned (FALSE, _("error starting mount daemon"), spawned_failed_cb, data); + return; + } + + g_vfs_daemon_set_max_threads (data->daemon, data->max_job_threads); + + send_spawned (TRUE, NULL, spawned_succeeded_cb, data); +} + +static gboolean +do_name_acquired (gpointer user_data) +{ + on_name_acquired (NULL, NULL, user_data); + return FALSE; +} + void daemon_main (int argc, char *argv[], @@ -219,28 +358,17 @@ daemon_main (int argc, ...) { va_list var_args; - DBusConnection *connection; - GMainLoop *loop; - GVfsDaemon *daemon; - DBusError derror; - GMountSpec *mount_spec; - GMountSource *mount_source; - GError *error; - int res; const char *type; + guint name_owner_id; + DaemonData *data; - dbus_error_init (&derror); - connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); - if (connection == NULL) - { - g_printerr (_("Error connecting to D-Bus: %s"), derror.message); - g_printerr ("\n"); - dbus_error_free (&derror); - exit (1); - } + g_print ("daemon_main: mountable_name = '%s'\n", mountable_name); + + data = g_new0 (DaemonData, 1); + data->mountable_name = g_strdup (mountable_name); + data->max_job_threads = max_job_threads; + data->mount_spec = daemon_parse_args (argc, argv, default_type); - mount_spec = daemon_parse_args (argc, argv, default_type); - va_start (var_args, first_type_name); type = first_type_name; @@ -254,49 +382,38 @@ daemon_main (int argc, type = va_arg (var_args, char *); } - error = NULL; - if (mountable_name) - { - - res = dbus_bus_request_name (connection, - mountable_name, - 0, &derror); - - if (res != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - { - if (res == -1) - _g_error_from_dbus (&derror, &error); - else - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("mountpoint for %s already running"), mountable_name); - - send_spawned (connection, FALSE, error->message); - g_error_free (error); - exit (1); - } - } + loop = g_main_loop_new (NULL, FALSE); - daemon = g_vfs_daemon_new (FALSE, FALSE); - if (daemon == NULL) + name_owner_id = 0; + if (mountable_name) { - send_spawned (connection, FALSE, _("error starting mount daemon")); - exit (1); + g_print ("daemon_main: requesting name '%s'\n", mountable_name); + + name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + mountable_name, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, + on_name_acquired, + on_name_lost, + data, + NULL); } - - g_vfs_daemon_set_max_threads (daemon, max_job_threads); - - send_spawned (connection, TRUE, NULL); - - if (mount_spec) + else { - mount_source = g_mount_source_new_dummy (); - g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, FALSE, NULL); - g_mount_spec_unref (mount_spec); - g_object_unref (mount_source); + g_idle_add (do_name_acquired, data); } - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); + + if (data->daemon != NULL) + g_object_unref (data->daemon); + g_free (data->mountable_name); + g_free (data); + if (name_owner_id != 0) + g_bus_unown_name (name_owner_id); + if (loop != NULL) + g_main_loop_unref (loop); + + if (process_result) + exit (process_result); } - diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c index 409db731..d627623f 100644 --- a/daemon/gvfsbackend.c +++ b/daemon/gvfsbackend.c @@ -29,11 +29,9 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsbackend.h" #include "gvfsjobsource.h" -#include "gvfsdaemonprotocol.h" #include <gvfsjobopenforread.h> #include <gvfsjobopeniconforread.h> #include <gvfsjobopenforwrite.h> @@ -58,7 +56,7 @@ #include <gvfsjobpull.h> #include <gvfsjobsetattribute.h> #include <gvfsjobqueryattributes.h> -#include <gvfsdbusutils.h> +#include <gvfsdbus.h> enum { PROP_0, @@ -99,9 +97,6 @@ static void g_vfs_backend_set_property (GObject static GObject* g_vfs_backend_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params); -static DBusHandlerResult backend_dbus_handler (DBusConnection *connection, - DBusMessage *message, - void *user_data); G_DEFINE_TYPE_WITH_CODE (GVfsBackend, g_vfs_backend, G_TYPE_OBJECT, @@ -254,6 +249,56 @@ g_vfs_backend_get_property (GObject *object, } } +static GDBusInterfaceSkeleton * +register_path_cb (GDBusConnection *conn, + const char *obj_path, + gpointer data) +{ + GError *error; + GVfsDBusMount *skeleton; + + skeleton = gvfs_dbus_mount_skeleton_new (); + g_signal_connect (skeleton, "handle-enumerate", G_CALLBACK (g_vfs_job_enumerate_new_handle), data); + g_signal_connect (skeleton, "handle-query-info", G_CALLBACK (g_vfs_job_query_info_new_handle), data); + g_signal_connect (skeleton, "handle-query-filesystem-info", G_CALLBACK (g_vfs_job_query_fs_info_new_handle), data); + g_signal_connect (skeleton, "handle-set-display-name", G_CALLBACK (g_vfs_job_set_display_name_new_handle), data); + g_signal_connect (skeleton, "handle-delete", G_CALLBACK (g_vfs_job_delete_new_handle), data); + g_signal_connect (skeleton, "handle-trash", G_CALLBACK (g_vfs_job_trash_new_handle), data); + g_signal_connect (skeleton, "handle-make-directory", G_CALLBACK (g_vfs_job_make_directory_new_handle), data); + g_signal_connect (skeleton, "handle-make-symbolic-link", G_CALLBACK (g_vfs_job_make_symlink_new_handle), data); + g_signal_connect (skeleton, "handle-query-settable-attributes", G_CALLBACK (g_vfs_job_query_settable_attributes_new_handle), data); + g_signal_connect (skeleton, "handle-query-writable-namespaces", G_CALLBACK (g_vfs_job_query_writable_namespaces_new_handle), data); + g_signal_connect (skeleton, "handle-set-attribute", G_CALLBACK (g_vfs_job_set_attribute_new_handle), data); + g_signal_connect (skeleton, "handle-poll-mountable", G_CALLBACK (g_vfs_job_poll_mountable_new_handle), data); + g_signal_connect (skeleton, "handle-start-mountable", G_CALLBACK (g_vfs_job_start_mountable_new_handle), data); + g_signal_connect (skeleton, "handle-stop-mountable", G_CALLBACK (g_vfs_job_stop_mountable_new_handle), data); + g_signal_connect (skeleton, "handle-unmount-mountable", G_CALLBACK (g_vfs_job_unmount_mountable_new_handle), data); + g_signal_connect (skeleton, "handle-eject-mountable", G_CALLBACK (g_vfs_job_eject_mountable_new_handle), data); + g_signal_connect (skeleton, "handle-mount-mountable", G_CALLBACK (g_vfs_job_mount_mountable_new_handle), data); + g_signal_connect (skeleton, "handle-unmount", G_CALLBACK (g_vfs_job_unmount_new_handle), data); + g_signal_connect (skeleton, "handle-open-for-read", G_CALLBACK (g_vfs_job_open_for_read_new_handle), data); + g_signal_connect (skeleton, "handle-open-for-write", G_CALLBACK (g_vfs_job_open_for_write_new_handle), data); + g_signal_connect (skeleton, "handle_copy", G_CALLBACK (g_vfs_job_copy_new_handle), data); + g_signal_connect (skeleton, "handle-move", G_CALLBACK (g_vfs_job_move_new_handle), data); + g_signal_connect (skeleton, "handle-push", G_CALLBACK (g_vfs_job_push_new_handle), data); + g_signal_connect (skeleton, "handle-pull", G_CALLBACK (g_vfs_job_pull_new_handle), data); + g_signal_connect (skeleton, "handle-create-directory-monitor", G_CALLBACK (g_vfs_job_create_directory_monitor_new_handle), data); + g_signal_connect (skeleton, "handle-create-file-monitor", G_CALLBACK (g_vfs_job_create_file_monitor_new_handle), data); + + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), + conn, + obj_path, + &error)) + { + g_warning ("Error registering path: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + + return G_DBUS_INTERFACE_SKELETON (skeleton); +} + static GObject* g_vfs_backend_constructor (GType type, guint n_construct_properties, @@ -269,7 +314,8 @@ g_vfs_backend_constructor (GType type, g_vfs_daemon_register_path (backend->priv->daemon, backend->priv->object_path, - backend_dbus_handler, + "backend_path", + register_path_cb, backend); return object; @@ -522,167 +568,94 @@ g_vfs_backend_get_block_requests (GVfsBackend *backend) return backend->priv->block_requests; } - -static DBusHandlerResult -backend_dbus_handler (DBusConnection *connection, - DBusMessage *message, - void *user_data) +gboolean +g_vfs_backend_invocation_first_handler (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GVfsBackend *backend) { - GVfsBackend *backend = user_data; - GVfsJob *job; - - job = NULL; - g_debug ("backend_dbus_handler %s:%s\n", - dbus_message_get_interface (message), - dbus_message_get_member (message)); + g_dbus_method_invocation_get_interface_name (invocation), + g_dbus_method_invocation_get_method_name (invocation)); if (backend->priv->block_requests) { - DBusMessage *reply; + g_dbus_method_invocation_return_error (invocation, + G_IO_ERROR, + G_IO_ERROR_NOT_MOUNTED, + "%s", "Backend currently unmounting"); + return TRUE; + } - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, - G_IO_ERROR_NOT_MOUNTED, - "%s", "Backend currently unmounting"); + return FALSE; +} - g_assert (reply != NULL); - dbus_connection_send (connection, reply, NULL); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_UNMOUNT)) - job = g_vfs_job_unmount_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ)) - job = g_vfs_job_open_for_read_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ)) - job = g_vfs_job_open_icon_for_read_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_QUERY_INFO)) - job = g_vfs_job_query_info_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO)) - job = g_vfs_job_query_fs_info_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_ENUMERATE)) - job = g_vfs_job_enumerate_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE)) - job = g_vfs_job_open_for_write_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE)) - job = g_vfs_job_mount_mountable_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE)) - job = g_vfs_job_unmount_mountable_new (connection, message, backend, FALSE); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE)) - job = g_vfs_job_unmount_mountable_new (connection, message, backend, TRUE); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_START_MOUNTABLE)) - job = g_vfs_job_start_mountable_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_STOP_MOUNTABLE)) - job = g_vfs_job_stop_mountable_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_POLL_MOUNTABLE)) - job = g_vfs_job_poll_mountable_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME)) - job = g_vfs_job_set_display_name_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_DELETE)) - job = g_vfs_job_delete_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_TRASH)) - job = g_vfs_job_trash_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY)) - job = g_vfs_job_make_directory_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK)) - job = g_vfs_job_make_symlink_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_COPY)) - job = g_vfs_job_copy_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_PUSH)) - job = g_vfs_job_push_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_PULL)) - job = g_vfs_job_pull_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_MOVE)) - job = g_vfs_job_move_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE)) - job = g_vfs_job_set_attribute_new (connection, message, backend); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES)) - job = g_vfs_job_query_attributes_new (connection, message, backend, FALSE); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES)) - job = g_vfs_job_query_attributes_new (connection, message, backend, TRUE); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR)) - job = g_vfs_job_create_monitor_new (connection, message, backend, TRUE); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNT_INTERFACE, - G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR)) - job = g_vfs_job_create_monitor_new (connection, message, backend, FALSE); - - if (job) - { - g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), job); - g_object_unref (job); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +typedef struct { + GVfsBackend *backend; + GAsyncReadyCallback callback; + gpointer callback_data; +} AsyncProxyCreate; + +static void +async_proxy_create_free (AsyncProxyCreate *data) +{ + if (data->backend) + g_object_unref (data->backend); + g_free (data); } -void -g_vfs_backend_register_mount (GVfsBackend *backend, - GAsyncDBusCallback callback, - gpointer user_data) +static void +create_mount_tracker_proxy (GVfsBackend *backend, + GAsyncReadyCallback op_callback, + gpointer op_callback_data, + GAsyncReadyCallback callback) { + AsyncProxyCreate *data; + + g_print ("create_mount_tracker_proxy\n"); + + data = g_new0 (AsyncProxyCreate, 1); + data->callback = op_callback; + data->callback_data = op_callback_data; + data->backend = g_object_ref (backend); + + gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + G_VFS_DBUS_DAEMON_NAME, + G_VFS_DBUS_MOUNTTRACKER_PATH, + NULL, + callback, + data); +} + +static void +register_mount_got_proxy_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + AsyncProxyCreate *data = user_data; + GVfsDBusMountTracker *proxy; + GError *error = NULL; + GSimpleAsyncResult *result; + GVfsBackend *backend; const char *stable_name; - DBusMessage *message; - DBusMessageIter iter; - dbus_bool_t user_visible; char *x_content_types_string; char *icon_str; + proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error); + g_print ("register_mount_got_proxy_cb, proxy = %p\n", proxy); + if (proxy == NULL) + { + result = g_simple_async_result_new_take_error (source_object, + data->callback, data->callback_data, + error); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + async_proxy_create_free (data); + return; + } + + backend = data->backend; backend->priv->is_mounted = TRUE; if (backend->priv->x_content_types != NULL && g_strv_length (backend->priv->x_content_types) > 0) @@ -695,71 +668,86 @@ g_vfs_backend_register_mount (GVfsBackend *backend, else icon_str = g_strdup (""); - 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_REGISTER_MOUNT); - if (message == NULL) - _g_dbus_oom (); - if (backend->priv->stable_name != NULL && *backend->priv->stable_name != 0) stable_name = backend->priv->stable_name; else stable_name = backend->priv->display_name; - user_visible = backend->priv->user_visible; - if (!dbus_message_append_args (message, - DBUS_TYPE_OBJECT_PATH, &backend->priv->object_path, - DBUS_TYPE_STRING, &backend->priv->display_name, - DBUS_TYPE_STRING, &stable_name, - DBUS_TYPE_STRING, &x_content_types_string, - DBUS_TYPE_STRING, &icon_str, - DBUS_TYPE_STRING, &backend->priv->prefered_filename_encoding, - DBUS_TYPE_BOOLEAN, &user_visible, - 0)) - _g_dbus_oom (); + g_print ("g_vfs_backend_register_mount: calling register_mount() for object_path = '%s', display_name = '%s'\n", backend->priv->object_path, backend->priv->display_name); + + gvfs_dbus_mount_tracker_call_register_mount (proxy, + backend->priv->object_path, + backend->priv->display_name, + stable_name, + x_content_types_string, + icon_str, + backend->priv->prefered_filename_encoding, + backend->priv->user_visible, + g_mount_spec_to_dbus (backend->priv->mount_spec), + backend->priv->default_location, + NULL, + data->callback, data->callback_data); - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus (&iter, backend->priv->mount_spec); + g_free (x_content_types_string); + g_free (icon_str); + g_object_unref (proxy); + async_proxy_create_free (data); +} - _g_dbus_message_append_args (message, - G_DBUS_TYPE_CSTRING, &backend->priv->default_location, - 0); +void +g_vfs_backend_register_mount (GVfsBackend *backend, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_print ("g_vfs_backend_register_mount\n"); + + create_mount_tracker_proxy (backend, callback, user_data, register_mount_got_proxy_cb); +} +static void +unregister_mount_got_proxy_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + AsyncProxyCreate *data = user_data; + GVfsDBusMountTracker *proxy; + GError *error = NULL; + GSimpleAsyncResult *result; + GVfsBackend *backend; - dbus_message_set_auto_start (message, TRUE); + proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error); + g_print ("unregister_mount_got_proxy_cb, proxy = %p\n", proxy); + if (proxy == NULL) + { + result = g_simple_async_result_new_take_error (source_object, + data->callback, data->callback_data, + error); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + async_proxy_create_free (data); + return; + } - _g_dbus_connection_call_async (NULL, message, -1, - callback, user_data); - dbus_message_unref (message); + backend = data->backend; + + gvfs_dbus_mount_tracker_call_unregister_mount (proxy, + backend->priv->object_path, + NULL, + data->callback, data->callback_data); - g_free (x_content_types_string); - g_free (icon_str); + g_object_unref (proxy); + async_proxy_create_free (data); } void g_vfs_backend_unregister_mount (GVfsBackend *backend, - GAsyncDBusCallback callback, + GAsyncReadyCallback callback, gpointer user_data) { - DBusMessage *message; + g_print ("g_vfs_backend_unregister_mount\n"); - 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_UNREGISTER_MOUNT); - if (message == NULL) - _g_dbus_oom (); - - if (!dbus_message_append_args (message, - DBUS_TYPE_OBJECT_PATH, &backend->priv->object_path, - 0)) - _g_dbus_oom (); - - _g_dbus_connection_call_async (NULL, message, -1, - callback, user_data); - dbus_message_unref (message); + create_mount_tracker_proxy (backend, callback, user_data, unregister_mount_got_proxy_cb); } /* ------------------------------------------------------------------------------------------------- */ diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h index cf4abb64..8ba3d038 100644 --- a/daemon/gvfsbackend.h +++ b/daemon/gvfsbackend.h @@ -23,12 +23,10 @@ #ifndef __G_VFS_BACKEND_H__ #define __G_VFS_BACKEND_H__ -#include <dbus/dbus.h> #include <gio/gio.h> #include <gvfsdaemon.h> #include <gvfsjob.h> #include <gmountspec.h> -#include <gvfsdbusutils.h> G_BEGIN_DECLS @@ -478,10 +476,10 @@ void g_vfs_backend_set_default_location (GVfsBackend *ba void g_vfs_backend_set_mount_spec (GVfsBackend *backend, GMountSpec *mount_spec); void g_vfs_backend_register_mount (GVfsBackend *backend, - GAsyncDBusCallback callback, + GAsyncReadyCallback callback, gpointer user_data); void g_vfs_backend_unregister_mount (GVfsBackend *backend, - GAsyncDBusCallback callback, + GAsyncReadyCallback callback, gpointer user_data); const char *g_vfs_backend_get_backend_type (GVfsBackend *backend); const char *g_vfs_backend_get_display_name (GVfsBackend *backend); @@ -511,6 +509,10 @@ void g_vfs_backend_unmount_with_operation (GVfsBackend *backend, GAsyncReadyCallback callback, gpointer user_data); +gboolean g_vfs_backend_invocation_first_handler (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GVfsBackend *backend); + G_END_DECLS #endif /* __G_VFS_BACKEND_H__ */ diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c index 0614a5c5..38191b10 100644 --- a/daemon/gvfsdaemon.c +++ b/daemon/gvfsdaemon.c @@ -35,14 +35,12 @@ #include <glib/gi18n.h> #include <glib/gstdio.h> #include <glib-object.h> -#include <dbus-gmain.h> #include <gvfsdaemon.h> #include <gvfsdaemonprotocol.h> #include <gvfsdaemonutils.h> #include <gvfsjobmount.h> #include <gvfsjobopenforread.h> #include <gvfsjobopenforwrite.h> -#include <gvfsdbusutils.h> enum { PROP_0 @@ -50,8 +48,10 @@ enum { typedef struct { char *obj_path; - DBusObjectPathMessageFunction callback; + char *name; + GVfsRegisterPathCallback callback; gpointer data; + GDBusInterfaceSkeleton *skeleton; } RegisteredPath; struct _GVfsDaemon @@ -62,7 +62,6 @@ struct _GVfsDaemon gboolean main_daemon; GThreadPool *thread_pool; - DBusConnection *session_bus; GHashTable *registered_paths; GList *jobs; GList *job_sources; @@ -70,18 +69,24 @@ struct _GVfsDaemon guint exit_tag; gint mount_counter; + + GDBusConnection *conn; + GVfsDBusDaemon *daemon_skeleton; + GVfsDBusMountable *mountable_skeleton; + guint name_watcher; + gboolean lost_main_daemon; }; typedef struct { GVfsDaemon *daemon; char *socket_dir; guint io_watch; - DBusServer *server; + GDBusServer *server; gboolean got_dbus_connection; gboolean got_fd_connection; int fd; - DBusConnection *conn; + GDBusConnection *conn; } NewConnectionData; static void g_vfs_daemon_get_property (GObject *object, @@ -92,12 +97,25 @@ static void g_vfs_daemon_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static DBusHandlerResult daemon_message_func (DBusConnection *conn, - DBusMessage *message, - gpointer data); -static DBusHandlerResult peer_to_peer_filter_func (DBusConnection *conn, - DBusMessage *message, - gpointer data); + +static gboolean handle_get_connection (GVfsDBusDaemon *object, + GDBusMethodInvocation *invocation, + gpointer user_data); +static gboolean handle_cancel (GVfsDBusDaemon *object, + GDBusMethodInvocation *invocation, + guint arg_serial, + gpointer user_data); +static gboolean daemon_handle_mount (GVfsDBusMountable *object, + GDBusMethodInvocation *invocation, + GVariant *arg_mount_spec, + gboolean arg_automount, + GVariant *arg_mount_source, + gpointer user_data); +static void g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon); + + + + G_DEFINE_TYPE (GVfsDaemon, g_vfs_daemon, G_TYPE_OBJECT) @@ -106,6 +124,13 @@ static void registered_path_free (RegisteredPath *data) { g_free (data->obj_path); + g_free (data->name); + if (data->skeleton) + { + /* Unexport the interface skeleton on session bus */ + g_dbus_interface_skeleton_unexport (data->skeleton); + g_object_unref (data->skeleton); + } g_free (data); } @@ -118,6 +143,22 @@ g_vfs_daemon_finalize (GObject *object) g_assert (daemon->jobs == NULL); + if (daemon->name_watcher) + g_bus_unwatch_name (daemon->name_watcher); + + if (daemon->daemon_skeleton != NULL) + { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon->daemon_skeleton)); + g_object_unref (daemon->daemon_skeleton); + } + if (daemon->mountable_skeleton != NULL) + { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon->mountable_skeleton)); + g_object_unref (daemon->mountable_skeleton); + } + if (daemon->conn != NULL) + g_object_unref (daemon->conn); + g_hash_table_destroy (daemon->registered_paths); g_mutex_clear (&daemon->lock); @@ -145,12 +186,45 @@ job_handler_callback (gpointer data, } static void +name_appeared_handler (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + GVfsDaemon *daemon = user_data; + + g_print ("gvfsdaemon: name_appeared_handler()\n"); + + if (strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0 && + *name_owner != 0 && + daemon->lost_main_daemon) + { + /* There is a new owner. Register mounts with it */ + g_vfs_daemon_re_register_job_sources (daemon); + } +} + +static void +name_vanished_handler (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + GVfsDaemon *daemon = user_data; + + g_print ("gvfsdaemon: name_vanished_handler()\n"); + + /* Ensure we react only to really lost daemon */ + daemon->lost_main_daemon = TRUE; +} + +static void g_vfs_daemon_init (GVfsDaemon *daemon) { + GError *error; gint max_threads = 1; /* TODO: handle max threads */ - DBusError error; - - daemon->session_bus = dbus_bus_get (DBUS_BUS_SESSION, NULL); + + g_print ("g_vfs_daemon_init\n"); + daemon->thread_pool = g_thread_pool_new (job_handler_callback, daemon, max_threads, @@ -166,24 +240,40 @@ g_vfs_daemon_init (GVfsDaemon *daemon) daemon->registered_paths = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)registered_path_free); + + + daemon->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + g_assert (daemon->conn != NULL); - dbus_error_init (&error); - dbus_bus_add_match (daemon->session_bus, - "type='signal'," - "interface='org.freedesktop.DBus'," - "member='NameOwnerChanged'," - "arg0='"G_VFS_DBUS_DAEMON_NAME"'", - &error); + daemon->daemon_skeleton = gvfs_dbus_daemon_skeleton_new (); + g_signal_connect (daemon->daemon_skeleton, "handle-get-connection", G_CALLBACK (handle_get_connection), daemon); + /* TODO: this might never be called on this side */ + g_signal_connect (daemon->daemon_skeleton, "handle-cancel", G_CALLBACK (handle_cancel), daemon); - if (dbus_error_is_set (&error)) + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon->daemon_skeleton), + daemon->conn, + G_VFS_DBUS_DAEMON_PATH, + &error)) { - g_warning ("Failed to add dbus match: %s\n", error.message); - dbus_error_free (&error); + g_warning ("Error exporting daemon interface: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); } + + daemon->mountable_skeleton = gvfs_dbus_mountable_skeleton_new (); + g_signal_connect (daemon->mountable_skeleton, "handle-mount", G_CALLBACK (daemon_handle_mount), daemon); - if (!dbus_connection_add_filter (daemon->session_bus, - daemon_message_func, daemon, NULL)) - _g_dbus_oom (); + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon->mountable_skeleton), + daemon->conn, + G_VFS_DBUS_MOUNTABLE_PATH, + &error)) + { + g_warning ("Error exporting mountable interface: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } } static void @@ -192,11 +282,6 @@ g_vfs_daemon_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { -#if 0 - GVfsDaemon *daemon; - - daemon = G_VFS_DAEMON (object); -#endif switch (prop_id) { default: @@ -211,11 +296,6 @@ g_vfs_daemon_get_property (GObject *object, GValue *value, GParamSpec *pspec) { -#if 0 - GVfsDaemon *daemon; - - daemon = G_VFS_DAEMON (object); -#endif switch (prop_id) { default: @@ -228,58 +308,34 @@ GVfsDaemon * g_vfs_daemon_new (gboolean main_daemon, gboolean replace) { GVfsDaemon *daemon; - DBusConnection *conn; - DBusError error; - unsigned int flags; - int ret; + GDBusConnection *conn; + GError *error; - dbus_error_init (&error); - conn = dbus_bus_get (DBUS_BUS_SESSION, &error); + error = NULL; + conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); if (!conn) { - g_printerr ("Failed to connect to the D-BUS daemon: %s\n", - error.message); - - dbus_error_free (&error); + g_printerr ("Failed to connect to the D-BUS daemon: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); return NULL; } - dbus_connection_setup_with_g_main (conn, NULL); - daemon = g_object_new (G_VFS_TYPE_DAEMON, NULL); daemon->main_daemon = main_daemon; - - /* Request name only after we've installed the message filter */ - if (main_daemon) + + if (! main_daemon) { - flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT | DBUS_NAME_FLAG_DO_NOT_QUEUE; - if (replace) - flags |= DBUS_NAME_FLAG_REPLACE_EXISTING; - - ret = dbus_bus_request_name (conn, G_VFS_DBUS_DAEMON_NAME, flags, &error); - if (ret == -1) - { - g_printerr ("Failed to acquire daemon name: %s", error.message); - dbus_error_free (&error); - - g_object_unref (daemon); - daemon = NULL; - } - else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) - { - g_printerr ("VFS daemon already running, exiting.\n"); - g_object_unref (daemon); - daemon = NULL; - } - else if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - { - g_printerr ("Not primary owner of the service, exiting.\n"); - g_object_unref (daemon); - daemon = NULL; - } + daemon->name_watcher = g_bus_watch_name_on_connection (conn, + G_VFS_DBUS_DAEMON_NAME, + G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + name_appeared_handler, + name_vanished_handler, + daemon, + NULL); } - dbus_connection_unref (conn); + g_object_unref (conn); return daemon; } @@ -348,6 +404,21 @@ job_source_closed_callback (GVfsJobSource *job_source, } static void +re_register_jobs_cb (GVfsDBusMountTracker *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + gvfs_dbus_mount_tracker_call_register_mount_finish (proxy, + res, + &error); + g_debug ("re_register_jobs_cb, error: %p\n", error); + if (error) + g_error_free (error); +} + +static void g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon) { GList *l; @@ -363,7 +434,7 @@ g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon) /* Only re-register if we registered before, not e.g if we're currently mounting. */ if (g_vfs_backend_is_mounted (backend)) - g_vfs_backend_register_mount (backend, NULL, NULL); + g_vfs_backend_register_mount (backend, (GAsyncReadyCallback) re_register_jobs_cb, NULL); } } @@ -391,22 +462,32 @@ g_vfs_daemon_add_job_source (GVfsDaemon *daemon, g_mutex_unlock (&daemon->lock); } -/* This registers a dbus callback on *all* connections, client and session bus */ +/* This registers a dbus interface skeleton on *all* connections, client and session bus */ void g_vfs_daemon_register_path (GVfsDaemon *daemon, - const char *obj_path, - DBusObjectPathMessageFunction callback, - gpointer user_data) + const char *obj_path, + const char *name, + GVfsRegisterPathCallback callback, + gpointer user_data) { RegisteredPath *data; + g_print ("g_vfs_daemon_register_path: obj_path = '%s'\n", obj_path); + data = g_new0 (RegisteredPath, 1); data->obj_path = g_strdup (obj_path); + data->name = g_strdup (name); data->callback = callback; data->data = user_data; - + g_hash_table_insert (daemon->registered_paths, data->obj_path, data); + + /* Export the newly registered interface skeleton on session bus */ + /* TODO: change the way we export skeletons on connections once + * https://bugzilla.gnome.org/show_bug.cgi?id=662718 is in place. + */ + data->skeleton = callback (daemon->conn, data->obj_path, user_data); } void @@ -484,10 +565,75 @@ new_connection_data_free (void *memory) } static void +peer_unregister_skeleton (gpointer key, + RegisteredPath *reg_path, + GDBusConnection *dbus_conn) +{ + GDBusInterfaceSkeleton *skeleton; + + g_print ("unregistering '%s' on the %p connection\n", reg_path->name, dbus_conn); + + skeleton = g_object_get_data (G_OBJECT (dbus_conn), reg_path->name); + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (skeleton)); +} + +static void +peer_connection_closed (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) +{ + GVfsDaemon *daemon = user_data; + GList *l; + GVfsDBusDaemon *daemon_skeleton; + + g_print ("peer_connection_closed\n"); + + g_mutex_lock (&daemon->lock); + for (l = daemon->jobs; l != NULL; l = l->next) + { + GVfsJob *job = l->data; + + if (G_VFS_IS_JOB_DBUS (job) && + G_VFS_JOB_DBUS (job)->invocation && + g_dbus_method_invocation_get_connection (G_VFS_JOB_DBUS (job)->invocation) == connection) + g_vfs_job_cancel (job); + } + g_mutex_unlock (&daemon->lock); + + + daemon_skeleton = g_object_get_data (G_OBJECT (connection), "daemon_skeleton"); + /* daemon_skeleton should be always valid in this case */ + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon_skeleton)); + + /* Unexport the registered interface skeletons */ + g_hash_table_foreach (daemon->registered_paths, (GHFunc) peer_unregister_skeleton, connection); + + /* The peer-to-peer connection was disconnected */ + g_object_unref (connection); +} + +static void +peer_register_skeleton (gpointer key, + RegisteredPath *reg_path, + GDBusConnection *dbus_conn) +{ + GDBusInterfaceSkeleton *skeleton; + + g_print ("registering '%s' on the %p connection\n", reg_path->name, dbus_conn); + + skeleton = reg_path->callback (dbus_conn, reg_path->obj_path, reg_path->data); + g_object_set_data_full (G_OBJECT (dbus_conn), reg_path->name, skeleton, (GDestroyNotify) g_object_unref); +} + +static void daemon_peer_connection_setup (GVfsDaemon *daemon, - DBusConnection *dbus_conn, + GDBusConnection *dbus_conn, NewConnectionData *data) { + GVfsDBusDaemon *daemon_skeleton; + GError *error; + /* We wait until we have the extra fd */ if (!data->got_fd_connection) return; @@ -496,21 +642,34 @@ daemon_peer_connection_setup (GVfsDaemon *daemon, { /* The fd connection failed, abort the whole thing */ g_warning ("Failed to accept client: %s", "accept of extra fd failed"); - dbus_connection_unref (dbus_conn); + g_object_unref (data->conn); goto error_out; } + + daemon_skeleton = gvfs_dbus_daemon_skeleton_new (); + g_signal_connect (daemon_skeleton, "handle-cancel", G_CALLBACK (handle_cancel), daemon); - dbus_connection_setup_with_g_main (dbus_conn, NULL); - if (!dbus_connection_add_filter (dbus_conn, peer_to_peer_filter_func, daemon, NULL) || - !dbus_connection_add_filter (dbus_conn, daemon_message_func, daemon, NULL)) + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon_skeleton), + dbus_conn, + G_VFS_DBUS_DAEMON_PATH, + &error)) { - g_warning ("Failed to accept client: %s", "object registration failed"); - dbus_connection_unref (dbus_conn); + g_warning ("Failed to accept client: %s, %s (%s, %d)", "object registration failed", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + g_object_unref (data->conn); close (data->fd); goto error_out; } + g_object_set_data_full (G_OBJECT (data->conn), "daemon_skeleton", daemon_skeleton, (GDestroyNotify) g_object_unref); + + /* Export registered interface skeletons on this new connection */ + g_hash_table_foreach (daemon->registered_paths, (GHFunc) peer_register_skeleton, dbus_conn); - dbus_connection_add_fd_send_fd (dbus_conn, data->fd); + g_print ("daemon_peer_connection_setup: interface registration complete.\n"); + + g_signal_connect (data->conn, "closed", G_CALLBACK (peer_connection_closed), data->daemon); error_out: new_connection_data_free (data); @@ -645,10 +804,10 @@ generate_addresses (char **address1, #endif } -static void -daemon_new_connection_func (DBusServer *server, - DBusConnection *conn, - gpointer user_data) +static gboolean +daemon_new_connection_func (GDBusServer *server, + GDBusConnection *connection, + gpointer user_data) { NewConnectionData *data; @@ -656,13 +815,17 @@ daemon_new_connection_func (DBusServer *server, data->got_dbus_connection = TRUE; /* Take ownership */ - data->conn = dbus_connection_ref (conn); + data->conn = g_object_ref (connection); - daemon_peer_connection_setup (data->daemon, conn, data); + daemon_peer_connection_setup (data->daemon, data->conn, data); + g_print ("daemon_new_connection_func: closing server\n"); + /* Kill the server, no more need for it */ - dbus_server_disconnect (server); - dbus_server_unref (server); + g_dbus_server_stop (server); + g_object_unref (server); + + return TRUE; } static int @@ -724,6 +887,8 @@ accept_new_fd_client (GIOChannel *channel, struct sockaddr_un addr; socklen_t addrlen; + g_print ("accept_new_fd_client\n"); + data->got_fd_connection = TRUE; fd = g_io_channel_unix_get_fd (channel); @@ -743,28 +908,31 @@ accept_new_fd_client (GIOChannel *channel, { /* Didn't accept a dbus connection, and there is no need for one now */ g_warning ("Failed to accept client: %s", "accept of extra fd failed"); - dbus_server_disconnect (data->server); - dbus_server_unref (data->server); + g_dbus_server_stop (data->server); + g_object_unref (data->server); new_connection_data_free (data); } return FALSE; } -static void -daemon_handle_get_connection (DBusConnection *conn, - DBusMessage *message, - GVfsDaemon *daemon) +static gboolean +handle_get_connection (GVfsDBusDaemon *object, + GDBusMethodInvocation *invocation, + gpointer user_data) { - DBusServer *server; - DBusError error; - DBusMessage *reply; - gchar *address1; - gchar *address2; + GVfsDaemon *daemon = user_data; + GDBusServer *server; + GError *error; + gchar *address1; + gchar *address2; NewConnectionData *data; GIOChannel *channel; char *socket_dir; int fd; + gchar *guid; + + g_print ("called get_connection()\n"); generate_addresses (&address1, &address2, &socket_dir); @@ -775,60 +943,51 @@ daemon_handle_get_connection (DBusConnection *conn, data->got_dbus_connection = FALSE; data->fd = -1; data->conn = NULL; - - dbus_error_init (&error); - server = dbus_server_listen (address1, &error); - if (!server) - { - reply = dbus_message_new_error_printf (message, - G_VFS_DBUS_ERROR_SOCKET_FAILED, - "Failed to create new socket: %s", - error.message); - dbus_error_free (&error); - if (reply) - { - dbus_connection_send (conn, reply, NULL); - dbus_message_unref (reply); - } - - goto error_out; - } - data->server = server; - dbus_server_set_new_connection_function (server, - daemon_new_connection_func, - data, NULL); - dbus_server_setup_with_g_main (server, NULL); - fd = unix_socket_at (address2); if (fd == -1) goto error_out; + guid = g_dbus_generate_guid (); + error = NULL; + server = g_dbus_server_new_sync (address1, + G_DBUS_SERVER_FLAGS_NONE, + guid, + NULL, /* GDBusAuthObserver */ + NULL, /* GCancellable */ + &error); + g_free (guid); + + if (server == NULL) + { + g_dbus_method_invocation_return_gerror (invocation, error); + g_printerr ("daemon: Error creating server at address %s: %s\n", address1, error->message); + g_error_free (error); + goto error_out; + } + + g_dbus_server_start (server); + data->server = server; + + g_print ("Server is listening at: %s\n", g_dbus_server_get_client_address (server)); + g_signal_connect (server, "new-connection", G_CALLBACK (daemon_new_connection_func), data); + channel = g_io_channel_unix_new (fd); g_io_channel_set_close_on_unref (channel, TRUE); data->io_watch = g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_new_fd_client, data); g_io_channel_unref (channel); - - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); - - if (!dbus_message_append_args (reply, - DBUS_TYPE_STRING, &address1, - DBUS_TYPE_STRING, &address2, - DBUS_TYPE_INVALID)) - _g_dbus_oom (); - - dbus_connection_send (conn, reply, NULL); - - dbus_message_unref (reply); + + gvfs_dbus_daemon_complete_get_connection (object, + invocation, + address1, + address2); g_free (address1); g_free (address2); - - return; + return TRUE; error_out: + g_print ("handle_get_connection: error_out\n"); g_free (data); g_free (address1); g_free (address2); @@ -837,194 +996,78 @@ daemon_handle_get_connection (DBusConnection *conn, rmdir (socket_dir); g_free (socket_dir); } + return TRUE; } -static void -daemon_start_mount (GVfsDaemon *daemon, - DBusConnection *connection, - DBusMessage *message) -{ - const char *dbus_id, *obj_path; - DBusMessageIter iter; - DBusError derror; - DBusMessage *reply; - GMountSpec *mount_spec; - GMountSource *mount_source; - dbus_bool_t automount; - - dbus_message_iter_init (message, &iter); - - reply = NULL; - mount_spec = NULL; - dbus_error_init (&derror); - if ((mount_spec = g_mount_spec_from_dbus (&iter)) == NULL) - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Error in mount spec"); - else if (!_g_dbus_message_iter_get_args (&iter, &derror, - DBUS_TYPE_BOOLEAN, &automount, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0)) - { - reply = dbus_message_new_error (message, derror.name, derror.message); - dbus_error_free (&derror); - } - - if (reply) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } - else - { - mount_source = g_mount_source_new (dbus_id, obj_path); - g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, automount, message); - g_object_unref (mount_source); - g_mount_spec_unref (mount_spec); - } -} - -static DBusHandlerResult -daemon_message_func (DBusConnection *conn, - DBusMessage *message, - gpointer data) +static gboolean +handle_cancel (GVfsDBusDaemon *object, + GDBusMethodInvocation *invocation, + guint arg_serial, + gpointer user_data) { - GVfsDaemon *daemon = data; - RegisteredPath *registered_path; - const char *path; - char *name; - char *old_owner, *new_owner; + GVfsDaemon *daemon = user_data; + GList *l; + GVfsJob *job_to_cancel = NULL; - path = dbus_message_get_path (message); - if (path == NULL) - path = ""; + g_print ("called cancel(), should be on our private connection only\n"); - if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameLost")) - { - if (dbus_message_get_args (message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID) && - strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0) - { - /* Someone else got the name (i.e. someone used --replace), exit */ - if (daemon->main_daemon) - exit (1); - } - } - else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) - { - if (dbus_message_get_args (message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID) && - strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0 && - *new_owner != 0 && - !daemon->main_daemon) - { - /* There is a new owner. Register mounts with it */ - g_vfs_daemon_re_register_job_sources (daemon); - } - - } - - - if (dbus_message_is_method_call (message, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_GET_CONNECTION)) - { - daemon_handle_get_connection (conn, message, daemon); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (dbus_message_is_method_call (message, - G_VFS_DBUS_DAEMON_INTERFACE, - G_VFS_DBUS_OP_CANCEL)) + g_mutex_lock (&daemon->lock); + for (l = daemon->jobs; l != NULL; l = l->next) { - GList *l; - dbus_uint32_t serial; - GVfsJob *job_to_cancel = NULL; + GVfsJob *job = l->data; - if (dbus_message_get_args (message, NULL, - DBUS_TYPE_UINT32, &serial, - DBUS_TYPE_INVALID)) - { - g_mutex_lock (&daemon->lock); - for (l = daemon->jobs; l != NULL; l = l->next) - { - GVfsJob *job = l->data; - - if (G_VFS_IS_JOB_DBUS (job) && - g_vfs_job_dbus_is_serial (G_VFS_JOB_DBUS (job), - conn, serial)) - { - job_to_cancel = g_object_ref (job); - break; - } - } - g_mutex_unlock (&daemon->lock); - - - if (job_to_cancel) - { - g_vfs_job_cancel (job_to_cancel); - g_object_unref (job_to_cancel); - } - } - - return DBUS_HANDLER_RESULT_HANDLED; + if (G_VFS_IS_JOB_DBUS (job) && + g_vfs_job_dbus_is_serial (G_VFS_JOB_DBUS (job), + g_dbus_method_invocation_get_connection (invocation), + arg_serial)) + { + job_to_cancel = g_object_ref (job); + break; + } } + g_mutex_unlock (&daemon->lock); - if (strcmp (path, G_VFS_DBUS_MOUNTABLE_PATH) == 0 && - dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTABLE_INTERFACE, - G_VFS_DBUS_MOUNTABLE_OP_MOUNT)) + if (job_to_cancel) { - daemon_start_mount (daemon, conn, message); - return DBUS_HANDLER_RESULT_HANDLED; + g_vfs_job_cancel (job_to_cancel); + g_object_unref (job_to_cancel); } - registered_path = g_hash_table_lookup (daemon->registered_paths, path); - - if (registered_path) - return registered_path->callback (conn, message, registered_path->data); - else - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} + gvfs_dbus_daemon_complete_cancel (object, invocation); + return TRUE; +} -/* Only called for peer-to-peer connections */ -static DBusHandlerResult -peer_to_peer_filter_func (DBusConnection *conn, - DBusMessage *message, - gpointer data) +static gboolean +daemon_handle_mount (GVfsDBusMountable *object, + GDBusMethodInvocation *invocation, + GVariant *arg_mount_spec, + gboolean arg_automount, + GVariant *arg_mount_source, + gpointer user_data) { - GVfsDaemon *daemon = data; - - if (dbus_message_is_signal (message, - DBUS_INTERFACE_LOCAL, - "Disconnected")) + GVfsDaemon *daemon = user_data; + GMountSpec *mount_spec; + GMountSource *mount_source; + + g_print ("called daemon_handle_mount()\n"); + + mount_spec = g_mount_spec_from_dbus (arg_mount_spec); + if (mount_spec == NULL) + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Error in mount spec"); + else { - GList *l; - - g_mutex_lock (&daemon->lock); - for (l = daemon->jobs; l != NULL; l = l->next) - { - GVfsJob *job = l->data; - - if (G_VFS_IS_JOB_DBUS (job) && - G_VFS_JOB_DBUS (job)->connection == conn) - g_vfs_job_cancel (job); - } - g_mutex_unlock (&daemon->lock); - - /* The peer-to-peer connection was disconnected */ - dbus_connection_unref (conn); - return DBUS_HANDLER_RESULT_HANDLED; + mount_source = g_mount_source_from_dbus (arg_mount_source); + g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, arg_automount, + object, invocation); + g_object_unref (mount_source); + g_mount_spec_unref (mount_spec); } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return TRUE; } void @@ -1032,16 +1075,17 @@ g_vfs_daemon_initiate_mount (GVfsDaemon *daemon, GMountSpec *mount_spec, GMountSource *mount_source, gboolean is_automount, - DBusMessage *request) + GVfsDBusMountable *object, + GDBusMethodInvocation *invocation) { const char *type; GType backend_type; char *obj_path; GVfsJob *job; GVfsBackend *backend; - DBusConnection *conn; - DBusMessage *reply; + g_print ("g_vfs_daemon_initiate_mount\n"); + type = g_mount_spec_get_type (mount_spec); backend_type = G_TYPE_INVALID; @@ -1050,21 +1094,11 @@ g_vfs_daemon_initiate_mount (GVfsDaemon *daemon, if (backend_type == G_TYPE_INVALID) { - if (request) - { - reply = _dbus_message_new_gerror (request, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid backend type")); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - if (conn) - { - dbus_connection_send (conn, reply, NULL); - dbus_message_unref (reply); - dbus_connection_unref (conn); - } - } + if (invocation) + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_ALREADY_MOUNTED, + "Mountpoint Already registered"); else g_warning ("Error mounting: invalid backend type\n"); return; @@ -1075,12 +1109,13 @@ g_vfs_daemon_initiate_mount (GVfsDaemon *daemon, "daemon", daemon, "object-path", obj_path, NULL); + g_print ("g_vfs_daemon_initiate_mount: obj_path = '%s'\n", obj_path); g_free (obj_path); - + g_vfs_daemon_add_job_source (daemon, G_VFS_JOB_SOURCE (backend)); g_object_unref (backend); - job = g_vfs_job_mount_new (mount_spec, mount_source, is_automount, request, backend); + job = g_vfs_job_mount_new (mount_spec, mount_source, is_automount, object, invocation, backend); g_vfs_daemon_queue_job (daemon, job); g_object_unref (job); } diff --git a/daemon/gvfsdaemon.h b/daemon/gvfsdaemon.h index 00d7fe15..37ea7f09 100644 --- a/daemon/gvfsdaemon.h +++ b/daemon/gvfsdaemon.h @@ -26,7 +26,7 @@ #include <glib-object.h> #include <gvfsjobsource.h> #include <gmountsource.h> -#include <dbus/dbus.h> +#include <gvfsdbus.h> G_BEGIN_DECLS @@ -49,6 +49,10 @@ struct _GVfsDaemonClass }; +typedef GDBusInterfaceSkeleton * (*GVfsRegisterPathCallback) (GDBusConnection *conn, + const char *obj_path, + gpointer data); + GType g_vfs_daemon_get_type (void) G_GNUC_CONST; GVfsDaemon *g_vfs_daemon_new (gboolean main_daemon, @@ -60,16 +64,18 @@ void g_vfs_daemon_add_job_source (GVfsDaemon *daemon, void g_vfs_daemon_queue_job (GVfsDaemon *daemon, GVfsJob *job); void g_vfs_daemon_register_path (GVfsDaemon *daemon, - const char *obj_path, - DBusObjectPathMessageFunction callback, - gpointer user_data); + const char *obj_path, + const char *name, + GVfsRegisterPathCallback callback, + gpointer user_data); void g_vfs_daemon_unregister_path (GVfsDaemon *daemon, const char *obj_path); void g_vfs_daemon_initiate_mount (GVfsDaemon *daemon, GMountSpec *mount_spec, GMountSource *mount_source, gboolean is_automount, - DBusMessage *request); + GVfsDBusMountable *object, + GDBusMethodInvocation *invocation); GArray *g_vfs_daemon_get_blocking_processes (GVfsDaemon *daemon); void g_vfs_daemon_run_job_in_thread (GVfsDaemon *daemon, GVfsJob *job); diff --git a/daemon/gvfsdaemonutils.c b/daemon/gvfsdaemonutils.c index 1dfa4efe..7f6e99f5 100644 --- a/daemon/gvfsdaemonutils.c +++ b/daemon/gvfsdaemonutils.c @@ -35,84 +35,9 @@ #include <glib/gi18n.h> #include <gio/gio.h> -#include "gvfsdbusutils.h" -#include "gsysutils.h" #include "gvfsdaemonutils.h" #include "gvfsdaemonprotocol.h" -static gint32 extra_fd_slot = -1; -static GMutex extra_lock; - -typedef struct { - int extra_fd; - int fd_count; -} ConnectionExtra; - -static void -free_extra (gpointer p) -{ - ConnectionExtra *extra = p; - close (extra->extra_fd); - g_free (extra); -} - -void -dbus_connection_add_fd_send_fd (DBusConnection *connection, - int extra_fd) -{ - ConnectionExtra *extra; - - if (extra_fd_slot == -1 && - !dbus_connection_allocate_data_slot (&extra_fd_slot)) - g_error ("Unable to allocate data slot"); - - extra = g_new0 (ConnectionExtra, 1); - extra->extra_fd = extra_fd; - - if (!dbus_connection_set_data (connection, extra_fd_slot, extra, free_extra)) - _g_dbus_oom (); -} - -gboolean -dbus_connection_send_fd (DBusConnection *connection, - int fd, - int *fd_id, - GError **error) -{ - ConnectionExtra *extra; - - g_assert (extra_fd_slot != -1); - extra = dbus_connection_get_data (connection, extra_fd_slot); - g_assert (extra != NULL); - - if (extra->extra_fd == -1) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Internal Error (%s)"), "No fd passing socket available"); - return FALSE; - } - - g_mutex_lock (&extra_lock); - - if (_g_socket_send_fd (extra->extra_fd, fd) == -1) - { - int errsv = errno; - - g_set_error (error, G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error sending file descriptor: %s"), - g_strerror (errsv)); - g_mutex_unlock (&extra_lock); - return FALSE; - } - - *fd_id = extra->fd_count++; - - g_mutex_unlock (&extra_lock); - - return TRUE; -} char * g_error_to_daemon_reply (GError *error, guint32 seq_nr, gsize *len_out) diff --git a/daemon/gvfsdaemonutils.h b/daemon/gvfsdaemonutils.h index 9a00631f..0000caaf 100644 --- a/daemon/gvfsdaemonutils.h +++ b/daemon/gvfsdaemonutils.h @@ -24,16 +24,9 @@ #define __G_VFS_DAEMON_UTILS_H__ #include <glib-object.h> -#include <dbus/dbus.h> G_BEGIN_DECLS -void dbus_connection_add_fd_send_fd (DBusConnection *connection, - int extra_fd); -gboolean dbus_connection_send_fd (DBusConnection *connection, - int fd, - int *fd_id, - GError **error); char * g_error_to_daemon_reply (GError *error, guint32 seq_nr, gsize *len_out); diff --git a/daemon/gvfsjob.c b/daemon/gvfsjob.c index d9253d14..84f2e554 100644 --- a/daemon/gvfsjob.c +++ b/daemon/gvfsjob.c @@ -28,7 +28,6 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include <gio/gio.h> #include "gvfsjob.h" diff --git a/daemon/gvfsjobcopy.c b/daemon/gvfsjobcopy.c index 1a48b7f8..9be8472a 100644 --- a/daemon/gvfsjobcopy.c +++ b/daemon/gvfsjobcopy.c @@ -29,19 +29,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobcopy.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" +#include <gvfsdbus.h> G_DEFINE_TYPE (GVfsJobCopy, g_vfs_job_copy, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_copy_finalize (GObject *object) @@ -76,52 +74,90 @@ g_vfs_job_copy_init (GVfsJobCopy *job) { } -GVfsJob * -g_vfs_job_copy_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_copy_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path1_data, + const gchar *arg_path2_data, + guint arg_flags, + const gchar *arg_progress_obj_path, + GVfsBackend *backend) { GVfsJobCopy *job; - DBusMessage *reply; - DBusError derror; - int path1_len, path2_len; - const char *path1_data, *path2_data, *callback_obj_path; - dbus_uint32_t flags; - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path1_data, &path1_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path2_data, &path2_len, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_OBJECT_PATH, &callback_obj_path, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); + g_print ("called Copy()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + + job = g_object_new (G_VFS_TYPE_JOB_COPY, + "object", object, + "invocation", invocation, + NULL); + + job->source = g_strdup (arg_path1_data); + job->destination = g_strdup (arg_path2_data); + job->backend = backend; + job->flags = arg_flags; + if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0) + job->callback_obj_path = g_strdup (arg_progress_obj_path); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); + return TRUE; +} + +typedef struct { + goffset current_num_bytes; + goffset total_num_bytes; +} ProgressCallbackData; - return NULL; +static void +progress_cb (GVfsDBusProgress *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + g_print ("progress_cb\n"); + + if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error)) + { + g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); } +} - job = g_object_new (G_VFS_TYPE_JOB_COPY, - "message", message, - "connection", connection, - NULL); +static void +progress_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + ProgressCallbackData *data = user_data; + GVfsDBusProgress *proxy; + GError *error = NULL; - job->source = g_strndup (path1_data, path1_len); - job->destination = g_strndup (path2_data, path2_len); - job->backend = backend; - job->flags = flags; - if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0) - job->callback_obj_path = g_strdup (callback_obj_path); + g_print ("progress_proxy_new_cb\n"); + + proxy = gvfs_dbus_progress_proxy_new_finish (res, &error); + if (proxy == NULL) + { + g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + goto out; + } + + gvfs_dbus_progress_call_progress (proxy, + data->current_num_bytes, + data->total_num_bytes, + NULL, + (GAsyncReadyCallback) progress_cb, + NULL); + g_object_unref (proxy); - return G_VFS_JOB (job); + out: + g_free (data); } static void @@ -132,31 +168,24 @@ progress_callback (goffset current_num_bytes, GVfsJob *job = G_VFS_JOB (user_data); GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job); GVfsJobCopy *op_job = G_VFS_JOB_COPY (job); - dbus_uint64_t current_dbus, total_dbus; - DBusMessage *message; + ProgressCallbackData *data; g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes); if (op_job->callback_obj_path == NULL) return; - message = - dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message), - op_job->callback_obj_path, - G_VFS_DBUS_PROGRESS_INTERFACE, - G_VFS_DBUS_PROGRESS_OP_PROGRESS); - dbus_message_set_no_reply (message, TRUE); - - current_dbus = current_num_bytes; - total_dbus = total_num_bytes; - dbus_message_append_args (message, - DBUS_TYPE_UINT64, ¤t_dbus, - DBUS_TYPE_UINT64, &total_dbus, - 0); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - dbus_connection_send (dbus_job->connection, message, NULL); - dbus_message_unref (message); + data = g_new0 (ProgressCallbackData, 1); + data->current_num_bytes = current_num_bytes; + data->total_num_bytes = total_num_bytes; + + gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation), + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + g_dbus_method_invocation_get_sender (dbus_job->invocation), + op_job->callback_obj_path, + NULL, + progress_proxy_new_cb, + data); } static void @@ -200,14 +229,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_copy (object, invocation); } diff --git a/daemon/gvfsjobcopy.h b/daemon/gvfsjobcopy.h index ddadd503..322d2c71 100644 --- a/daemon/gvfsjobcopy.h +++ b/daemon/gvfsjobcopy.h @@ -58,9 +58,13 @@ struct _GVfsJobCopyClass GType g_vfs_job_copy_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_copy_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_copy_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path1_data, + const gchar *arg_path2_data, + guint arg_flags, + const gchar *arg_progress_obj_path, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobcreatemonitor.c b/daemon/gvfsjobcreatemonitor.c index e788ee43..4e3d772e 100644 --- a/daemon/gvfsjobcreatemonitor.c +++ b/daemon/gvfsjobcreatemonitor.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobcreatemonitor.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobCreateMonitor, g_vfs_job_create_monitor, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_create_monitor_finalize (GObject *object) @@ -75,50 +72,59 @@ g_vfs_job_create_monitor_init (GVfsJobCreateMonitor *job) { } -GVfsJob * -g_vfs_job_create_monitor_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend, - gboolean is_directory) + +static gboolean +create_monitor_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVfsBackend *backend, + gboolean is_directory) { GVfsJobCreateMonitor *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - char *path; - guint32 flags; - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - path = NULL; - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_UINT32, &flags, - 0)) - { - g_free (path); - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_CREATE_MONITOR, - "message", message, - "connection", connection, - NULL); - + "object", object, + "invocation", invocation, + NULL); + job->is_directory = is_directory; - job->filename = path; + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->flags = flags; + job->flags = arg_flags; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +gboolean +g_vfs_job_create_file_monitor_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVfsBackend *backend) +{ + g_print ("called CreateFileMonitor()\n"); - return G_VFS_JOB (job); + return create_monitor_new_handle (object, invocation, arg_path_data, arg_flags, backend, FALSE); +} + + +gboolean +g_vfs_job_create_directory_monitor_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVfsBackend *backend) +{ + g_print ("called CreateDirectoryMonitor()\n"); + + return create_monitor_new_handle (object, invocation, arg_path_data, arg_flags, backend, TRUE); } void @@ -217,18 +223,14 @@ unref_monitor_timeout (gpointer data) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobCreateMonitor *op_job = G_VFS_JOB_CREATE_MONITOR (job); - DBusMessage *reply; - DBusMessageIter iter; const char *obj_path; - reply = dbus_message_new_method_return (message); - /* Keep the monitor alive for at least 5 seconds to allow for a subscribe call to come in and bump the refcount */ @@ -238,10 +240,9 @@ create_reply (GVfsJob *job, op_job->monitor); obj_path = g_vfs_monitor_get_object_path (op_job->monitor); - dbus_message_iter_init_append (reply, &iter); - _g_dbus_message_append_args (reply, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0); - return reply; + if (op_job->is_directory) + gvfs_dbus_mount_complete_create_directory_monitor (object, invocation, obj_path); + else + gvfs_dbus_mount_complete_create_file_monitor (object, invocation, obj_path); } diff --git a/daemon/gvfsjobcreatemonitor.h b/daemon/gvfsjobcreatemonitor.h index 6c7285a7..6d0f8ae7 100644 --- a/daemon/gvfsjobcreatemonitor.h +++ b/daemon/gvfsjobcreatemonitor.h @@ -59,10 +59,17 @@ struct _GVfsJobCreateMonitorClass GType g_vfs_job_create_monitor_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_create_monitor_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend, - gboolean is_directory); +gboolean g_vfs_job_create_file_monitor_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVfsBackend *backend); +gboolean g_vfs_job_create_directory_monitor_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVfsBackend *backend); + void g_vfs_job_create_monitor_set_monitor (GVfsJobCreateMonitor *job, GVfsMonitor *monitor); diff --git a/daemon/gvfsjobdbus.c b/daemon/gvfsjobdbus.c index 48d7f7ea..a1ff65b0 100644 --- a/daemon/gvfsjobdbus.c +++ b/daemon/gvfsjobdbus.c @@ -28,10 +28,8 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobdbus.h" -#include "gvfsdbusutils.h" G_DEFINE_TYPE (GVfsJobDBus, g_vfs_job_dbus, G_VFS_TYPE_JOB) @@ -40,8 +38,8 @@ G_DEFINE_TYPE (GVfsJobDBus, g_vfs_job_dbus, G_VFS_TYPE_JOB) enum { PROP_0, - PROP_MESSAGE, - PROP_CONNECTION + PROP_INVOCATION, + PROP_OBJECT }; static void send_reply (GVfsJob *job); @@ -61,11 +59,11 @@ g_vfs_job_dbus_finalize (GObject *object) job = G_VFS_JOB_DBUS (object); - if (job->message) - dbus_message_unref (job->message); - - if (job->connection) - dbus_connection_unref (job->connection); + if (job->invocation) + g_object_unref (job->invocation); + + if (job->object) + g_object_unref (job->object); if (G_OBJECT_CLASS (g_vfs_job_dbus_parent_class)->finalize) (*G_OBJECT_CLASS (g_vfs_job_dbus_parent_class)->finalize) (object); @@ -84,19 +82,19 @@ g_vfs_job_dbus_class_init (GVfsJobDBusClass *klass) job_class->send_reply = send_reply; g_object_class_install_property (gobject_class, - PROP_CONNECTION, - g_param_spec_pointer ("connection", + PROP_INVOCATION, + g_param_spec_pointer ("invocation", P_("VFS Backend"), - P_("The implementation for this job operartion."), + P_("The implementation for this job operation."), G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); g_object_class_install_property (gobject_class, - PROP_MESSAGE, - g_param_spec_pointer ("message", - P_("VFS Backend"), - P_("The implementation for this job operartion."), - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + PROP_OBJECT, + g_param_spec_pointer ("object", + P_("VFS Backend"), + P_("The implementation for this job operation."), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); } static void @@ -114,11 +112,11 @@ g_vfs_job_dbus_set_property (GObject *object, switch (prop_id) { - case PROP_MESSAGE: - job->message = dbus_message_ref (g_value_get_pointer (value)); + case PROP_INVOCATION: + job->invocation = g_object_ref (g_value_get_pointer (value)); break; - case PROP_CONNECTION: - job->connection = dbus_connection_ref (g_value_get_pointer (value)); + case PROP_OBJECT: + job->object = g_object_ref (g_value_get_pointer (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -136,11 +134,11 @@ g_vfs_job_dbus_get_property (GObject *object, switch (prop_id) { - case PROP_MESSAGE: - g_value_set_pointer (value, job->message); + case PROP_INVOCATION: + g_value_set_pointer (value, job->invocation); break; - case PROP_CONNECTION: - g_value_set_pointer (value, job->connection); + case PROP_OBJECT: + g_value_set_pointer (value, job->object); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -153,44 +151,29 @@ static void send_reply (GVfsJob *job) { GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job); - DBusMessage *reply; GVfsJobDBusClass *class; g_debug ("send_reply(%p), failed=%d (%s)\n", job, job->failed, job->failed?job->error->message:""); class = G_VFS_JOB_DBUS_GET_CLASS (job); - if (job->failed) - reply = _dbus_message_new_from_gerror (dbus_job->message, job->error); + if (job->failed) + g_dbus_method_invocation_return_gerror (dbus_job->invocation, job->error); else - reply = class->create_reply (job, dbus_job->connection, dbus_job->message); + class->create_reply (job, dbus_job->object, dbus_job->invocation); - g_assert (reply != NULL); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - dbus_connection_send (dbus_job->connection, reply, NULL); - dbus_message_unref (reply); - g_vfs_job_emit_finished (job); } -DBusConnection * -g_vfs_job_dbus_get_connection (GVfsJobDBus *job_dbus) -{ - return job_dbus->connection; -} - -DBusMessage * -g_vfs_job_dbus_get_message (GVfsJobDBus *job_dbus) -{ - return job_dbus->message; -} - gboolean g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus, - DBusConnection *connection, - dbus_uint32_t serial) + GDBusConnection *connection, + guint serial) { + return TRUE; + + /* FIXME return job_dbus->connection == connection && dbus_message_get_serial (job_dbus->message) == serial; + */ } diff --git a/daemon/gvfsjobdbus.h b/daemon/gvfsjobdbus.h index 7c876347..b8ad65b3 100644 --- a/daemon/gvfsjobdbus.h +++ b/daemon/gvfsjobdbus.h @@ -23,7 +23,6 @@ #ifndef __G_VFS_JOB_DBUS_H__ #define __G_VFS_JOB_DBUS_H__ -#include <dbus/dbus.h> #include <gvfsjob.h> #include <gvfsbackend.h> @@ -43,8 +42,8 @@ struct _GVfsJobDBus { GVfsJob parent_instance; - DBusConnection *connection; - DBusMessage *message; + GVfsDBusMount *object; + GDBusMethodInvocation *invocation; }; struct _GVfsJobDBusClass @@ -52,18 +51,16 @@ struct _GVfsJobDBusClass GVfsJobClass parent_class; /* Might be called on an i/o thread */ - DBusMessage * (*create_reply) (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); + void (*create_reply) (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); }; GType g_vfs_job_dbus_get_type (void) G_GNUC_CONST; -gboolean g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus, - DBusConnection *connection, - dbus_uint32_t serial); -DBusConnection *g_vfs_job_dbus_get_connection (GVfsJobDBus *job_dbus); -DBusMessage *g_vfs_job_dbus_get_message (GVfsJobDBus *job_dbus); +gboolean g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus, + GDBusConnection *connection, + guint serial); G_END_DECLS diff --git a/daemon/gvfsjobdelete.c b/daemon/gvfsjobdelete.c index cc543569..51f59c3f 100644 --- a/daemon/gvfsjobdelete.c +++ b/daemon/gvfsjobdelete.c @@ -28,19 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobdelete.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobDelete, g_vfs_job_delete, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_delete_finalize (GObject *object) @@ -73,42 +71,31 @@ g_vfs_job_delete_init (GVfsJobDelete *job) { } -GVfsJob * -g_vfs_job_delete_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_delete_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend) { GVfsJobDelete *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + + g_print ("called Delete()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; job = g_object_new (G_VFS_TYPE_JOB_DELETE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = g_strndup (path_data, path_len); + job->filename = g_strdup (arg_path_data); job->backend = backend; - - return G_VFS_JOB (job); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -144,14 +131,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_delete (object, invocation); } diff --git a/daemon/gvfsjobdelete.h b/daemon/gvfsjobdelete.h index 91c2e8a5..9dd9bef6 100644 --- a/daemon/gvfsjobdelete.h +++ b/daemon/gvfsjobdelete.h @@ -54,10 +54,10 @@ struct _GVfsJobDeleteClass GType g_vfs_job_delete_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_delete_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); - +gboolean g_vfs_job_delete_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend); G_END_DECLS #endif /* __G_VFS_JOB_DELETE_H__ */ diff --git a/daemon/gvfsjobenumerate.c b/daemon/gvfsjobenumerate.c index 258a21ff..1dd25fac 100644 --- a/daemon/gvfsjobenumerate.c +++ b/daemon/gvfsjobenumerate.c @@ -28,20 +28,19 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobenumerate.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" +#include <gvfsdbus.h> G_DEFINE_TYPE (GVfsJobEnumerate, g_vfs_job_enumerate, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); static void send_reply (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_enumerate_finalize (GObject *object) @@ -79,72 +78,91 @@ g_vfs_job_enumerate_init (GVfsJobEnumerate *job) { } -GVfsJob * -g_vfs_job_enumerate_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_enumerate_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_obj_path, + const gchar *arg_attributes, + guint arg_flags, + const gchar *arg_uri, + GVfsBackend *backend) { GVfsJobEnumerate *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *obj_path; - const char *path_data; - char *attributes, *uri; - dbus_uint32_t flags; - DBusMessageIter iter; - - dbus_message_iter_init (message, &iter); - dbus_error_init (&derror); - if (!_g_dbus_message_iter_get_args (&iter, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } - /* Optional uri arg for thumbnail info */ - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_STRING, &uri, - 0)) - uri = NULL; + g_print ("called Enumerate()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_ENUMERATE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->object_path = g_strdup (obj_path); - job->filename = g_strndup (path_data, path_len); + job->object_path = g_strdup (arg_obj_path); + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->attributes = g_strdup (attributes); - job->attribute_matcher = g_file_attribute_matcher_new (attributes); - job->flags = flags; - job->uri = g_strdup (uri); + job->attributes = g_strdup (arg_attributes); + job->attribute_matcher = g_file_attribute_matcher_new (arg_attributes); + job->flags = arg_flags; + job->uri = g_strdup (arg_uri); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +static GVfsDBusEnumerator * +create_enumerator_proxy (GVfsJobEnumerate *job) +{ + GDBusConnection *connection; + const gchar *sender; + + connection = g_dbus_method_invocation_get_connection (G_VFS_JOB_DBUS (job)->invocation); + sender = g_dbus_method_invocation_get_sender (G_VFS_JOB_DBUS (job)->invocation); + + g_print ("create_enumerator_proxy: sender = '%s', object_path = '%s'\n", sender, job->object_path); - return G_VFS_JOB (job); + return gvfs_dbus_enumerator_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + sender, + job->object_path, + NULL, + NULL); +} + +static void +send_infos_cb (GVfsDBusEnumerator *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + gvfs_dbus_enumerator_call_got_info_finish (proxy, res, &error); + if (error != NULL) + { + g_warning ("send_infos_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } } static void send_infos (GVfsJobEnumerate *job) { - if (!dbus_message_iter_close_container (&job->building_iter, &job->building_array_iter)) - _g_dbus_oom (); + GVfsDBusEnumerator *proxy; + + proxy = create_enumerator_proxy (job); + g_assert (proxy != NULL); - dbus_connection_send (g_vfs_job_dbus_get_connection (G_VFS_JOB_DBUS (job)), - job->building_infos, NULL); - dbus_message_unref (job->building_infos); + gvfs_dbus_enumerator_call_got_info (proxy, + g_variant_builder_end (job->building_infos), + NULL, + (GAsyncReadyCallback) send_infos_cb, + NULL); + g_object_unref (proxy); + job->building_infos = NULL; job->n_building_infos = 0; } @@ -153,33 +171,15 @@ void g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job, GFileInfo *info) { - DBusMessage *message, *orig_message; char *uri, *escaped_name; + GVariant *v; if (job->building_infos == NULL) { - orig_message = g_vfs_job_dbus_get_message (G_VFS_JOB_DBUS (job)); - - message = dbus_message_new_method_call (dbus_message_get_sender (orig_message), - job->object_path, - G_VFS_DBUS_ENUMERATOR_INTERFACE, - G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO); - dbus_message_set_no_reply (message, TRUE); - - dbus_message_iter_init_append (message, &job->building_iter); - - if (!dbus_message_iter_open_container (&job->building_iter, - DBUS_TYPE_ARRAY, - G_FILE_INFO_TYPE_AS_STRING, - &job->building_array_iter)) - _g_dbus_oom (); - - job->building_infos = message; + job->building_infos = g_variant_builder_new (G_VARIANT_TYPE ("aa(suv)")); job->n_building_infos = 0; } - - uri = NULL; if (job->uri != NULL && g_file_info_get_name (info) != NULL) @@ -198,8 +198,9 @@ g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job, g_free (uri); g_file_info_set_attribute_mask (info, job->attribute_matcher); - - _g_dbus_append_file_info (&job->building_array_iter, info); + + v = _g_dbus_append_file_info (info); + g_variant_builder_add_value (job->building_infos, v); job->n_building_infos++; if (job->n_building_infos == 50) @@ -220,27 +221,45 @@ g_vfs_job_enumerate_add_infos (GVfsJobEnumerate *job, } } +static void +send_done_cb (GVfsDBusEnumerator *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + g_print ("send_done_cb\n"); + + gvfs_dbus_enumerator_call_done_finish (proxy, res, &error); + if (error != NULL) + { + g_warning ("send_done_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } +} + void g_vfs_job_enumerate_done (GVfsJobEnumerate *job) { - DBusMessage *message, *orig_message; + GVfsDBusEnumerator *proxy; g_assert (!G_VFS_JOB (job)->failed); + g_print ("g_vfs_job_enumerate_done: sending...\n"); + if (job->building_infos != NULL) send_infos (job); + + proxy = create_enumerator_proxy (job); + g_assert (proxy != NULL); - orig_message = g_vfs_job_dbus_get_message (G_VFS_JOB_DBUS (job)); - - message = dbus_message_new_method_call (dbus_message_get_sender (orig_message), - job->object_path, - G_VFS_DBUS_ENUMERATOR_INTERFACE, - G_VFS_DBUS_ENUMERATOR_OP_DONE); - dbus_message_set_no_reply (message, TRUE); + gvfs_dbus_enumerator_call_done (proxy, + NULL, + (GAsyncReadyCallback) send_done_cb, + NULL); + g_object_unref (proxy); - dbus_connection_send (g_vfs_job_dbus_get_connection (G_VFS_JOB_DBUS (job)), - message, NULL); - dbus_message_unref (message); + g_print ("g_vfs_job_enumerate_done: done.\n"); g_vfs_job_emit_finished (G_VFS_JOB (job)); } @@ -250,7 +269,7 @@ run (GVfsJob *job) { GVfsJobEnumerate *op_job = G_VFS_JOB_ENUMERATE (job); GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend); - + if (class->enumerate == NULL) { g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, @@ -285,37 +304,26 @@ static void send_reply (GVfsJob *job) { GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job); - DBusMessage *reply; GVfsJobDBusClass *class; g_debug ("send_reply(%p), failed=%d (%s)\n", job, job->failed, job->failed?job->error->message:""); class = G_VFS_JOB_DBUS_GET_CLASS (job); - if (job->failed) - reply = _dbus_message_new_from_gerror (dbus_job->message, job->error); + if (job->failed) + g_dbus_method_invocation_return_gerror (dbus_job->invocation, job->error); else - reply = class->create_reply (job, dbus_job->connection, dbus_job->message); + class->create_reply (job, dbus_job->object, dbus_job->invocation); - g_assert (reply != NULL); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - dbus_connection_send (dbus_job->connection, reply, NULL); - dbus_message_unref (reply); - if (job->failed) g_vfs_job_emit_finished (job); } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_enumerate (object, invocation); } diff --git a/daemon/gvfsjobenumerate.h b/daemon/gvfsjobenumerate.h index 622f49bb..56b0778e 100644 --- a/daemon/gvfsjobenumerate.h +++ b/daemon/gvfsjobenumerate.h @@ -51,9 +51,7 @@ struct _GVfsJobEnumerate GFileQueryInfoFlags flags; char *uri; - DBusMessage *building_infos; - DBusMessageIter building_iter; - DBusMessageIter building_array_iter; + GVariantBuilder *building_infos; int n_building_infos; }; @@ -64,9 +62,15 @@ struct _GVfsJobEnumerateClass GType g_vfs_job_enumerate_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_enumerate_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_enumerate_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_obj_path, + const gchar *arg_attributes, + guint arg_flags, + const gchar *arg_uri, + GVfsBackend *backend); + void g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job, GFileInfo *info); void g_vfs_job_enumerate_add_infos (GVfsJobEnumerate *job, diff --git a/daemon/gvfsjobmakedirectory.c b/daemon/gvfsjobmakedirectory.c index 5422393e..c26430e2 100644 --- a/daemon/gvfsjobmakedirectory.c +++ b/daemon/gvfsjobmakedirectory.c @@ -28,19 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobmakedirectory.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobMakeDirectory, g_vfs_job_make_directory, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_make_directory_finalize (GObject *object) @@ -73,42 +71,31 @@ g_vfs_job_make_directory_init (GVfsJobMakeDirectory *job) { } -GVfsJob * -g_vfs_job_make_directory_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_make_directory_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend) { GVfsJobMakeDirectory *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called MakeDirectory()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_MAKE_DIRECTORY, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = g_strndup (path_data, path_len); + job->filename = g_strdup (arg_path_data); job->backend = backend; - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -144,14 +131,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_make_directory (object, invocation); } diff --git a/daemon/gvfsjobmakedirectory.h b/daemon/gvfsjobmakedirectory.h index 0bb66a73..e1c5e826 100644 --- a/daemon/gvfsjobmakedirectory.h +++ b/daemon/gvfsjobmakedirectory.h @@ -54,10 +54,10 @@ struct _GVfsJobMakeDirectoryClass GType g_vfs_job_make_directory_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_make_directory_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); - +gboolean g_vfs_job_make_directory_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend); G_END_DECLS #endif /* __G_VFS_JOB_MAKE_DIRECTORY_H__ */ diff --git a/daemon/gvfsjobmakesymlink.c b/daemon/gvfsjobmakesymlink.c index 4f5ac437..a369c753 100644 --- a/daemon/gvfsjobmakesymlink.c +++ b/daemon/gvfsjobmakesymlink.c @@ -28,19 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobmakesymlink.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobMakeSymlink, g_vfs_job_make_symlink, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_make_symlink_finalize (GObject *object) @@ -74,45 +72,33 @@ g_vfs_job_make_symlink_init (GVfsJobMakeSymlink *job) { } -GVfsJob * -g_vfs_job_make_symlink_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_make_symlink_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_symlink_value, + GVfsBackend *backend) { GVfsJobMakeSymlink *job; - DBusMessage *reply; - DBusError derror; - int path_len, symlink_len; - const char *path_data, *symlink_data; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &symlink_data, &symlink_len, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called MakeSymlink()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_MAKE_SYMLINK, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = g_strndup (path_data, path_len); - job->symlink_value = g_strndup (symlink_data, symlink_len); + job->filename = g_strdup (arg_path_data); + job->symlink_value = g_strdup (arg_symlink_value); job->backend = backend; - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -150,14 +136,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_make_symbolic_link (object, invocation); } diff --git a/daemon/gvfsjobmakesymlink.h b/daemon/gvfsjobmakesymlink.h index df82c0f3..6f5d2314 100644 --- a/daemon/gvfsjobmakesymlink.h +++ b/daemon/gvfsjobmakesymlink.h @@ -55,9 +55,11 @@ struct _GVfsJobMakeSymlinkClass GType g_vfs_job_make_symlink_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_make_symlink_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_make_symlink_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_symlink_value, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobmount.c b/daemon/gvfsjobmount.c index c21d828d..fcca9457 100644 --- a/daemon/gvfsjobmount.c +++ b/daemon/gvfsjobmount.c @@ -28,11 +28,8 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobmount.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobMount, g_vfs_job_mount, G_VFS_TYPE_JOB) @@ -50,6 +47,10 @@ g_vfs_job_mount_finalize (GObject *object) g_mount_spec_unref (job->mount_spec); g_object_unref (job->mount_source); g_object_unref (job->backend); + if (job->object) + g_object_unref (job->object); + if (job->invocation) + g_object_unref (job->invocation); if (G_OBJECT_CLASS (g_vfs_job_mount_parent_class)->finalize) (*G_OBJECT_CLASS (g_vfs_job_mount_parent_class)->finalize) (object); @@ -76,8 +77,9 @@ GVfsJob * g_vfs_job_mount_new (GMountSpec *spec, GMountSource *source, gboolean is_automount, - DBusMessage *request, - GVfsBackend *backend) + GVfsDBusMountable *object, + GDBusMethodInvocation *invocation, + GVfsBackend *backend) { GVfsJobMount *job; @@ -90,8 +92,11 @@ g_vfs_job_mount_new (GMountSpec *spec, /* Ref the backend so we're sure its alive during the whole job request. */ job->backend = g_object_ref (backend); - if (request) - job->request = dbus_message_ref (request); + if (object != NULL && invocation != NULL) + { + job->object = g_object_ref (object); + job->invocation = g_object_ref (invocation); + } return G_VFS_JOB (job); } @@ -139,23 +144,10 @@ try (GVfsJob *job) static void mount_failed (GVfsJobMount *op_job, GError *error) { - DBusConnection *conn; - DBusMessage *reply; GVfsBackend *backend; - if (op_job->request) - { - reply = _dbus_message_new_from_gerror (op_job->request, error); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - if (conn) - { - dbus_connection_send (conn, reply, NULL); - dbus_message_unref (reply); - dbus_connection_unref (conn); - } - } + if (op_job->invocation) + g_dbus_method_invocation_return_gerror (op_job->invocation, error); else g_debug ("Mount failed: %s\n", error->message); @@ -168,35 +160,27 @@ mount_failed (GVfsJobMount *op_job, GError *error) } static void -register_mount_callback (DBusMessage *mount_reply, - GError *error, - gpointer user_data) +register_mount_callback (GVfsDBusMountTracker *proxy, + GAsyncResult *res, + gpointer user_data) { GVfsJobMount *op_job = G_VFS_JOB_MOUNT (user_data); - DBusConnection *conn; - DBusMessage *reply; - - g_debug ("register_mount_callback, mount_reply: %p, error: %p\n", mount_reply, error); + GError *error = NULL; - if (mount_reply == NULL) - mount_failed (op_job, error); + if (! gvfs_dbus_mount_tracker_call_register_mount_finish (proxy, res, &error)) + { + mount_failed (op_job, error); + } else { - if (op_job->request) - { - reply = dbus_message_new_method_return (op_job->request); - /* Queues reply (threadsafely), actually sends it in mainloop */ - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - if (conn) - { - dbus_connection_send (conn, reply, NULL); - dbus_message_unref (reply); - dbus_connection_unref (conn); - } - } + if (op_job->invocation && op_job->object) + gvfs_dbus_mountable_complete_mount (op_job->object, op_job->invocation); g_vfs_job_emit_finished (G_VFS_JOB (op_job)); } + + if (error != NULL) + g_error_free (error); } /* Might be called on an i/o thread */ @@ -211,6 +195,6 @@ send_reply (GVfsJob *job) mount_failed (op_job, job->error); else g_vfs_backend_register_mount (op_job->backend, - register_mount_callback, + (GAsyncReadyCallback) register_mount_callback, job); } diff --git a/daemon/gvfsjobmount.h b/daemon/gvfsjobmount.h index 0c3d31b4..3ae89aef 100644 --- a/daemon/gvfsjobmount.h +++ b/daemon/gvfsjobmount.h @@ -25,8 +25,8 @@ #include <gio/gio.h> #include <gvfsjob.h> -#include <gvfsjobdbus.h> #include <gvfsbackend.h> +#include <gvfsdbus.h> G_BEGIN_DECLS @@ -47,7 +47,8 @@ struct _GVfsJobMount gboolean is_automount; GMountSpec *mount_spec; GMountSource *mount_source; - DBusMessage *request; + GVfsDBusMountable *object; + GDBusMethodInvocation *invocation; }; struct _GVfsJobMountClass @@ -60,7 +61,8 @@ GType g_vfs_job_mount_get_type (void) G_GNUC_CONST; GVfsJob *g_vfs_job_mount_new (GMountSpec *spec, GMountSource *source, gboolean is_automount, - DBusMessage *request, + GVfsDBusMountable *object, + GDBusMethodInvocation *invocation, GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobmountmountable.c b/daemon/gvfsjobmountmountable.c index 133dc94c..71fe81e7 100644 --- a/daemon/gvfsjobmountmountable.c +++ b/daemon/gvfsjobmountmountable.c @@ -28,19 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobmountmountable.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobMountMountable, g_vfs_job_mount_mountable, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_mount_mountable_finalize (GObject *object) @@ -80,49 +78,34 @@ g_vfs_job_mount_mountable_init (GVfsJobMountMountable *job) { } -GVfsJob * -g_vfs_job_mount_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_mount_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend) { GVfsJobMountMountable *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - char *path; - const char *dbus_id, *obj_path; - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - path = NULL; - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0)) - { - g_free (path); - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called MountMountable()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_MOUNT_MOUNTABLE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = path; + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->mount_source = g_mount_source_new (dbus_id, obj_path); - - return G_VFS_JOB (job); + job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } void @@ -180,38 +163,28 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job); - DBusMessage *reply; - DBusMessageIter iter; - dbus_bool_t must_mount, is_uri; - - reply = dbus_message_new_method_return (message); - + gboolean is_uri, must_mount; + GMountSpec *fake_mountspec = NULL; + must_mount = op_job->must_mount_location; is_uri = op_job->target_uri != NULL; - if (is_uri) - { - _g_dbus_message_append_args (reply, - DBUS_TYPE_BOOLEAN, &is_uri, - G_DBUS_TYPE_CSTRING, &op_job->target_uri, - DBUS_TYPE_BOOLEAN, &must_mount, - 0); - } - else - { - _g_dbus_message_append_args (reply, - DBUS_TYPE_BOOLEAN, &is_uri, - G_DBUS_TYPE_CSTRING, &op_job->target_filename, - DBUS_TYPE_BOOLEAN, &must_mount, - 0); - dbus_message_iter_init_append (reply, &iter); - g_mount_spec_to_dbus (&iter, op_job->mount_spec); - } + + if (! is_uri) + fake_mountspec = g_mount_spec_new (NULL); + + gvfs_dbus_mount_complete_mount_mountable (object, + invocation, + is_uri, + is_uri ? op_job->target_uri : op_job->target_filename, + must_mount, + g_mount_spec_to_dbus (is_uri ? fake_mountspec : op_job->mount_spec)); - return reply; + if (fake_mountspec) + g_mount_spec_unref (fake_mountspec); } diff --git a/daemon/gvfsjobmountmountable.h b/daemon/gvfsjobmountmountable.h index aa640da6..83eb6a90 100644 --- a/daemon/gvfsjobmountmountable.h +++ b/daemon/gvfsjobmountmountable.h @@ -60,9 +60,13 @@ struct _GVfsJobMountMountableClass GType g_vfs_job_mount_mountable_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_mount_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_mount_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend); + void g_vfs_job_mount_mountable_set_target (GVfsJobMountMountable *job, GMountSpec *mount_spec, const char *filename, diff --git a/daemon/gvfsjobmove.c b/daemon/gvfsjobmove.c index da940123..bac56188 100644 --- a/daemon/gvfsjobmove.c +++ b/daemon/gvfsjobmove.c @@ -29,19 +29,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobmove.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" +#include "gvfsdbus.h" G_DEFINE_TYPE (GVfsJobMove, g_vfs_job_move, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_move_finalize (GObject *object) @@ -76,85 +74,117 @@ g_vfs_job_move_init (GVfsJobMove *job) { } -GVfsJob * -g_vfs_job_move_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_move_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path1_data, + const gchar *arg_path2_data, + guint arg_flags, + const gchar *arg_progress_obj_path, + GVfsBackend *backend) { GVfsJobMove *job; - DBusMessage *reply; - DBusError derror; - int path1_len, path2_len; - const char *path1_data, *path2_data, *callback_obj_path; - dbus_uint32_t flags; - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path1_data, &path1_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path2_data, &path2_len, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_OBJECT_PATH, &callback_obj_path, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called Move()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_MOVE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->source = g_strndup (path1_data, path1_len); - job->destination = g_strndup (path2_data, path2_len); + job->source = g_strdup (arg_path1_data); + job->destination = g_strdup (arg_path2_data); job->backend = backend; - job->flags = flags; - if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0) - job->callback_obj_path = g_strdup (callback_obj_path); + job->flags = arg_flags; + if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0) + job->callback_obj_path = g_strdup (arg_progress_obj_path); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +typedef struct { + goffset current_num_bytes; + goffset total_num_bytes; +} ProgressCallbackData; + +static void +progress_cb (GVfsDBusProgress *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + g_print ("progress_cb\n"); - return G_VFS_JOB (job); + if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error)) + { + g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } } -void +static void +progress_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + ProgressCallbackData *data = user_data; + GVfsDBusProgress *proxy; + GError *error = NULL; + + g_print ("progress_proxy_new_cb\n"); + + proxy = gvfs_dbus_progress_proxy_new_finish (res, &error); + if (proxy == NULL) + { + g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + goto out; + } + + gvfs_dbus_progress_call_progress (proxy, + data->current_num_bytes, + data->total_num_bytes, + NULL, + (GAsyncReadyCallback) progress_cb, + NULL); + g_object_unref (proxy); + + out: + g_free (data); +} + +void g_vfs_job_move_progress_callback (goffset current_num_bytes, - goffset total_num_bytes, - GVfsJob *job) + goffset total_num_bytes, + GVfsJob *job) { GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job); GVfsJobMove *op_job = G_VFS_JOB_MOVE (job); - dbus_uint64_t current_dbus, total_dbus; - DBusMessage *message; + ProgressCallbackData *data; g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes); if (op_job->callback_obj_path == NULL) return; - message = - dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message), - op_job->callback_obj_path, - G_VFS_DBUS_PROGRESS_INTERFACE, - G_VFS_DBUS_PROGRESS_OP_PROGRESS); - dbus_message_set_no_reply (message, TRUE); - - current_dbus = current_num_bytes; - total_dbus = total_num_bytes; - dbus_message_append_args (message, - DBUS_TYPE_UINT64, ¤t_dbus, - DBUS_TYPE_UINT64, &total_dbus, - 0); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - dbus_connection_send (dbus_job->connection, message, NULL); - dbus_message_unref (message); + data = g_new0 (ProgressCallbackData, 1); + data->current_num_bytes = current_num_bytes; + data->total_num_bytes = total_num_bytes; + + gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation), + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + g_dbus_method_invocation_get_sender (dbus_job->invocation), + op_job->callback_obj_path, + NULL, + progress_proxy_new_cb, + data); } static void @@ -198,14 +228,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_move (object, invocation); } diff --git a/daemon/gvfsjobmove.h b/daemon/gvfsjobmove.h index f793e2d1..b1eec943 100644 --- a/daemon/gvfsjobmove.h +++ b/daemon/gvfsjobmove.h @@ -58,9 +58,13 @@ struct _GVfsJobMoveClass GType g_vfs_job_move_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_move_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_move_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path1_data, + const gchar *arg_path2_data, + guint arg_flags, + const gchar *arg_progress_obj_path, + GVfsBackend *backend); void g_vfs_job_move_progress_callback (goffset current_num_bytes, goffset total_num_bytes, diff --git a/daemon/gvfsjobopenforread.c b/daemon/gvfsjobopenforread.c index 1d689203..75392339 100644 --- a/daemon/gvfsjobopenforread.c +++ b/daemon/gvfsjobopenforread.c @@ -28,11 +28,10 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> +#include <gio/gunixfdlist.h> #include "gvfsreadchannel.h" #include "gvfsjobopenforread.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobOpenForRead, g_vfs_job_open_for_read, G_VFS_TYPE_JOB_DBUS) @@ -40,9 +39,9 @@ G_DEFINE_TYPE (GVfsJobOpenForRead, g_vfs_job_open_for_read, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); static void finished (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_open_for_read_finalize (GObject *object) @@ -81,45 +80,34 @@ g_vfs_job_open_for_read_init (GVfsJobOpenForRead *job) { } -GVfsJob * -g_vfs_job_open_for_read_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_open_for_read_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_path_data, + guint arg_pid, + GVfsBackend *backend) { GVfsJobOpenForRead *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - guint32 pid; - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - DBUS_TYPE_UINT32, &pid, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called OpenForRead()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_OPEN_FOR_READ, - "message", message, - "connection", connection, - NULL); - - job->filename = g_strndup (path_data, path_len); - job->backend = backend; - job->pid = pid; + "object", object, + "invocation", invocation, + NULL); - return G_VFS_JOB (job); + job->filename = g_strdup (arg_path_data); + job->backend = backend; + job->pid = arg_pid; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -170,52 +158,45 @@ g_vfs_job_open_for_read_set_can_seek (GVfsJobOpenForRead *job, } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobOpenForRead *open_job = G_VFS_JOB_OPEN_FOR_READ (job); GVfsReadChannel *channel; - DBusMessage *reply; GError *error; int remote_fd; int fd_id; - dbus_bool_t can_seek; + GUnixFDList *fd_list; g_assert (open_job->backend_handle != NULL); - error = NULL; channel = g_vfs_read_channel_new (open_job->backend, open_job->pid); remote_fd = g_vfs_channel_steal_remote_fd (G_VFS_CHANNEL (channel)); - if (!dbus_connection_send_fd (connection, - remote_fd, - &fd_id, &error)) + + fd_list = g_unix_fd_list_new (); + error = NULL; + fd_id = g_unix_fd_list_append (fd_list, remote_fd, &error); + if (fd_id == -1) { - close (remote_fd); - reply = _dbus_message_new_from_gerror (message, error); + g_warning ("create_reply: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); - g_object_unref (channel); - return reply; } - close (remote_fd); - - reply = dbus_message_new_method_return (message); - can_seek = open_job->can_seek; - dbus_message_append_args (reply, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID); + gvfs_dbus_mount_complete_open_for_read (object, invocation, fd_list, fd_id, open_job->can_seek); + + /* FIXME: this could cause issues as long as fd_list closes all its fd's when it's finalized */ + close (remote_fd); + g_object_unref (fd_list); + g_vfs_channel_set_backend_handle (G_VFS_CHANNEL (channel), open_job->backend_handle); open_job->backend_handle = NULL; open_job->read_channel = channel; g_signal_emit_by_name (job, "new-source", open_job->read_channel); - - return reply; } static void diff --git a/daemon/gvfsjobopenforread.h b/daemon/gvfsjobopenforread.h index 964ce1c9..19f8321c 100644 --- a/daemon/gvfsjobopenforread.h +++ b/daemon/gvfsjobopenforread.h @@ -23,7 +23,6 @@ #ifndef __G_VFS_JOB_OPEN_FOR_READ_H__ #define __G_VFS_JOB_OPEN_FOR_READ_H__ -#include <dbus/dbus.h> #include <gvfsjobdbus.h> #include <gvfsbackend.h> #include <gvfsreadchannel.h> @@ -59,9 +58,12 @@ struct _GVfsJobOpenForReadClass GType g_vfs_job_open_for_read_get_type (void) G_GNUC_CONST; -GVfsJob * g_vfs_job_open_for_read_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_open_for_read_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_path_data, + guint arg_pid, + GVfsBackend *backend); void g_vfs_job_open_for_read_set_handle (GVfsJobOpenForRead *job, GVfsBackendHandle handle); void g_vfs_job_open_for_read_set_can_seek (GVfsJobOpenForRead *job, diff --git a/daemon/gvfsjobopenforwrite.c b/daemon/gvfsjobopenforwrite.c index 12ad295f..8ea680fa 100644 --- a/daemon/gvfsjobopenforwrite.c +++ b/daemon/gvfsjobopenforwrite.c @@ -28,11 +28,10 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> +#include <gio/gunixfdlist.h> #include "gvfswritechannel.h" #include "gvfsjobopenforwrite.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobOpenForWrite, g_vfs_job_open_for_write, G_VFS_TYPE_JOB_DBUS) @@ -40,9 +39,9 @@ G_DEFINE_TYPE (GVfsJobOpenForWrite, g_vfs_job_open_for_write, G_VFS_TYPE_JOB_DBU static void run (GVfsJob *job); static gboolean try (GVfsJob *job); static void finished (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_open_for_write_finalize (GObject *object) @@ -82,60 +81,43 @@ g_vfs_job_open_for_write_init (GVfsJobOpenForWrite *job) { } -GVfsJob * -g_vfs_job_open_for_write_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_open_for_write_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_path_data, + guint16 arg_mode, + const gchar *arg_etag, + gboolean arg_make_backup, + guint arg_flags, + guint arg_pid, + GVfsBackend *backend) { GVfsJobOpenForWrite *job; - DBusMessageIter iter; - DBusMessage *reply; - DBusError derror; - char *path; - guint16 mode; - dbus_bool_t make_backup; - const char *etag; - guint32 flags; - guint32 pid; - - path = NULL; - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_UINT16, &mode, - DBUS_TYPE_STRING, &etag, - DBUS_TYPE_BOOLEAN, &make_backup, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_UINT32, &pid, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - g_free (path); - return NULL; - } + + g_print ("called OpenForWrite()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; job = g_object_new (G_VFS_TYPE_JOB_OPEN_FOR_WRITE, - "message", message, - "connection", connection, - NULL); - - job->filename = path; - job->mode = mode; - if (*etag != 0) - job->etag = g_strdup (etag); - job->make_backup = make_backup; - job->flags = flags; - job->backend = backend; - job->pid = pid; + "object", object, + "invocation", invocation, + NULL); - return G_VFS_JOB (job); + job->filename = g_strdup (arg_path_data); + job->mode = arg_mode; + if (*arg_etag != 0) + job->etag = g_strdup (arg_etag); + job->make_backup = arg_make_backup; + job->flags = arg_flags; + job->backend = backend; + job->pid = arg_pid; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -259,56 +241,45 @@ g_vfs_job_open_for_write_set_initial_offset (GVfsJobOpenForWrite *job, job->initial_offset = initial_offset; } -/* Might be called on an i/o thwrite */ -static DBusMessage * +/* Might be called on an i/o thread */ +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobOpenForWrite *open_job = G_VFS_JOB_OPEN_FOR_WRITE (job); GVfsWriteChannel *channel; - DBusMessage *reply; GError *error; int remote_fd; int fd_id; - dbus_bool_t can_seek; - guint64 initial_offset; - + GUnixFDList *fd_list; + g_assert (open_job->backend_handle != NULL); - error = NULL; channel = g_vfs_write_channel_new (open_job->backend, open_job->pid); remote_fd = g_vfs_channel_steal_remote_fd (G_VFS_CHANNEL (channel)); - if (!dbus_connection_send_fd (connection, - remote_fd, - &fd_id, &error)) + + fd_list = g_unix_fd_list_new (); + error = NULL; + fd_id = g_unix_fd_list_append (fd_list, remote_fd, &error); + if (fd_id == -1) { - close (remote_fd); - reply = _dbus_message_new_from_gerror (message, error); + g_warning ("create_reply: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); - g_object_unref (channel); - return reply; } - close (remote_fd); - reply = dbus_message_new_method_return (message); - can_seek = open_job->can_seek; - initial_offset = open_job->initial_offset; - dbus_message_append_args (reply, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_UINT64, &initial_offset, - DBUS_TYPE_INVALID); + gvfs_dbus_mount_complete_open_for_write (object, invocation, fd_list, fd_id, open_job->can_seek, open_job->initial_offset); + + close (remote_fd); + g_object_unref (fd_list); g_vfs_channel_set_backend_handle (G_VFS_CHANNEL (channel), open_job->backend_handle); open_job->backend_handle = NULL; open_job->write_channel = channel; g_signal_emit_by_name (job, "new-source", open_job->write_channel); - - return reply; } static void diff --git a/daemon/gvfsjobopenforwrite.h b/daemon/gvfsjobopenforwrite.h index 8cab78ea..79854d23 100644 --- a/daemon/gvfsjobopenforwrite.h +++ b/daemon/gvfsjobopenforwrite.h @@ -23,7 +23,6 @@ #ifndef __G_VFS_JOB_OPEN_FOR_WRITE_H__ #define __G_VFS_JOB_OPEN_FOR_WRITE_H__ -#include <dbus/dbus.h> #include <gvfsjobdbus.h> #include <gvfsbackend.h> #include <gvfswritechannel.h> @@ -72,9 +71,16 @@ struct _GVfsJobOpenForWriteClass GType g_vfs_job_open_for_write_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_open_for_write_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_open_for_write_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_path_data, + guint16 arg_mode, + const gchar *arg_etag, + gboolean arg_make_backup, + guint arg_flags, + guint arg_pid, + GVfsBackend *backend); void g_vfs_job_open_for_write_set_handle (GVfsJobOpenForWrite *job, GVfsBackendHandle handle); void g_vfs_job_open_for_write_set_can_seek (GVfsJobOpenForWrite *job, diff --git a/daemon/gvfsjobpollmountable.c b/daemon/gvfsjobpollmountable.c index 1b0112a2..d9bbbbcb 100644 --- a/daemon/gvfsjobpollmountable.c +++ b/daemon/gvfsjobpollmountable.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobpollmountable.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobPollMountable, g_vfs_job_poll_mountable, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_poll_mountable_finalize (GObject *object) @@ -73,45 +70,31 @@ g_vfs_job_poll_mountable_init (GVfsJobPollMountable *job) { } -GVfsJob * -g_vfs_job_poll_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_poll_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend) { GVfsJobPollMountable *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - char *path; - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - path = NULL; - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - 0)) - { - g_free (path); - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + + g_print ("called PollMountable()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; job = g_object_new (G_VFS_TYPE_JOB_POLL_MOUNTABLE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = path; + job->filename = g_strdup (arg_path_data); job->backend = backend; - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -147,14 +130,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_poll_mountable (object, invocation); } diff --git a/daemon/gvfsjobpollmountable.h b/daemon/gvfsjobpollmountable.h index 01f89419..6e7ccc21 100644 --- a/daemon/gvfsjobpollmountable.h +++ b/daemon/gvfsjobpollmountable.h @@ -54,8 +54,9 @@ struct _GVfsJobPollMountableClass GType g_vfs_job_poll_mountable_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_poll_mountable_new (DBusConnection *connection, - DBusMessage *message, +gboolean g_vfs_job_poll_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobpull.c b/daemon/gvfsjobpull.c index 0a3347ae..3dda992c 100644 --- a/daemon/gvfsjobpull.c +++ b/daemon/gvfsjobpull.c @@ -29,19 +29,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobpull.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" +#include "gvfsdbus.h" G_DEFINE_TYPE (GVfsJobPull, g_vfs_job_pull, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_pull_finalize (GObject *object) @@ -76,92 +74,123 @@ g_vfs_job_pull_init (GVfsJobPull *job) { } -GVfsJob * -g_vfs_job_pull_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_pull_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_local_path, + gboolean arg_send_progress, + guint arg_flags, + const gchar *arg_progress_obj_path, + gboolean arg_remove_source, + GVfsBackend *backend) { GVfsJobPull *job; - DBusMessage *reply; - DBusError derror; - int path1_len, path2_len; - const char *path1_data, *path2_data, *callback_obj_path; - dbus_uint32_t flags; - dbus_bool_t remove_source, send_progress; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path1_data, &path1_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path2_data, &path2_len, - DBUS_TYPE_BOOLEAN, &send_progress, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_OBJECT_PATH, &callback_obj_path, - DBUS_TYPE_BOOLEAN, &remove_source, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + + g_print ("called Pull()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_PULL, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->source = g_strndup (path1_data, path1_len); - job->local_path = g_strndup (path2_data, path2_len); + job->source = g_strdup (arg_path_data); + job->local_path = g_strdup (arg_local_path); job->backend = backend; - job->flags = flags; - job->send_progress = send_progress; - job->remove_source = remove_source; - g_debug ("Remove Source: %s\n", remove_source ? "true" : "false"); - if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0) - job->callback_obj_path = g_strdup (callback_obj_path); - - return G_VFS_JOB (job); + job->flags = arg_flags; + job->send_progress = arg_send_progress; + job->remove_source = arg_remove_source; + g_debug ("Remove Source: %s\n", arg_remove_source ? "true" : "false"); + if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0) + job->callback_obj_path = g_strdup (arg_progress_obj_path); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +typedef struct { + goffset current_num_bytes; + goffset total_num_bytes; +} ProgressCallbackData; + +static void +progress_cb (GVfsDBusProgress *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + g_print ("progress_cb\n"); + + if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error)) + { + g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } +} + +static void +progress_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + ProgressCallbackData *data = user_data; + GVfsDBusProgress *proxy; + GError *error = NULL; + + g_print ("progress_proxy_new_cb\n"); + + proxy = gvfs_dbus_progress_proxy_new_finish (res, &error); + if (proxy == NULL) + { + g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + goto out; + } + + gvfs_dbus_progress_call_progress (proxy, + data->current_num_bytes, + data->total_num_bytes, + NULL, + (GAsyncReadyCallback) progress_cb, + NULL); + g_object_unref (proxy); + + out: + g_free (data); } static void progress_callback (goffset current_num_bytes, - goffset total_num_bytes, - gpointer user_data) + goffset total_num_bytes, + gpointer user_data) { GVfsJob *job = G_VFS_JOB (user_data); GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job); GVfsJobPull *op_job = G_VFS_JOB_PULL (job); - dbus_uint64_t current_dbus, total_dbus; - DBusMessage *message; + ProgressCallbackData *data; g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes); if (op_job->callback_obj_path == NULL) return; - message = - dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message), - op_job->callback_obj_path, - G_VFS_DBUS_PROGRESS_INTERFACE, - G_VFS_DBUS_PROGRESS_OP_PROGRESS); - dbus_message_set_no_reply (message, TRUE); - - current_dbus = current_num_bytes; - total_dbus = total_num_bytes; - dbus_message_append_args (message, - DBUS_TYPE_UINT64, ¤t_dbus, - DBUS_TYPE_UINT64, &total_dbus, - 0); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - dbus_connection_send (dbus_job->connection, message, NULL); - dbus_message_unref (message); + data = g_new0 (ProgressCallbackData, 1); + data->current_num_bytes = current_num_bytes; + data->total_num_bytes = total_num_bytes; + + gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation), + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + g_dbus_method_invocation_get_sender (dbus_job->invocation), + op_job->callback_obj_path, + NULL, + progress_proxy_new_cb, + data); } static void @@ -207,14 +236,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_pull (object, invocation); } diff --git a/daemon/gvfsjobpull.h b/daemon/gvfsjobpull.h index 1b89576c..eb739ea1 100644 --- a/daemon/gvfsjobpull.h +++ b/daemon/gvfsjobpull.h @@ -59,9 +59,15 @@ struct _GVfsJobPullClass GType g_vfs_job_pull_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_pull_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_pull_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_local_path, + gboolean arg_send_progress, + guint arg_flags, + const gchar *arg_progress_obj_path, + gboolean arg_remove_source, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobpush.c b/daemon/gvfsjobpush.c index 5abc7bb0..824a339d 100644 --- a/daemon/gvfsjobpush.c +++ b/daemon/gvfsjobpush.c @@ -29,19 +29,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobpush.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" +#include "gvfsdbus.h" G_DEFINE_TYPE (GVfsJobPush, g_vfs_job_push, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_push_finalize (GObject *object) @@ -76,92 +74,123 @@ g_vfs_job_push_init (GVfsJobPush *job) { } -GVfsJob * -g_vfs_job_push_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_push_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_local_path, + gboolean arg_send_progress, + guint arg_flags, + const gchar *arg_progress_obj_path, + gboolean arg_remove_source, + GVfsBackend *backend) { GVfsJobPush *job; - DBusMessage *reply; - DBusError derror; - int path1_len, path2_len; - const char *path1_data, *path2_data, *callback_obj_path; - dbus_uint32_t flags; - dbus_bool_t remove_source, send_progress; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path1_data, &path1_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path2_data, &path2_len, - DBUS_TYPE_BOOLEAN, &send_progress, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_OBJECT_PATH, &callback_obj_path, - DBUS_TYPE_BOOLEAN, &remove_source, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + + g_print ("called Push()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_PUSH, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->destination = g_strndup (path1_data, path1_len); - job->local_path = g_strndup (path2_data, path2_len); + job->destination = g_strdup (arg_path_data); + job->local_path = g_strdup (arg_local_path); job->backend = backend; - job->flags = flags; - job->send_progress = send_progress; - job->remove_source = remove_source; - g_debug ("Remove Source: %s\n", remove_source ? "true" : "false"); - if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0) - job->callback_obj_path = g_strdup (callback_obj_path); - - return G_VFS_JOB (job); + job->flags = arg_flags; + job->send_progress = arg_send_progress; + job->remove_source = arg_remove_source; + g_debug ("Remove Source: %s\n", arg_remove_source ? "true" : "false"); + if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0) + job->callback_obj_path = g_strdup (arg_progress_obj_path); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +typedef struct { + goffset current_num_bytes; + goffset total_num_bytes; +} ProgressCallbackData; + +static void +progress_cb (GVfsDBusProgress *proxy, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + g_print ("progress_cb\n"); + + if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error)) + { + g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } +} + +static void +progress_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + ProgressCallbackData *data = user_data; + GVfsDBusProgress *proxy; + GError *error = NULL; + + g_print ("progress_proxy_new_cb\n"); + + proxy = gvfs_dbus_progress_proxy_new_finish (res, &error); + if (proxy == NULL) + { + g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + goto out; + } + + gvfs_dbus_progress_call_progress (proxy, + data->current_num_bytes, + data->total_num_bytes, + NULL, + (GAsyncReadyCallback) progress_cb, + NULL); + g_object_unref (proxy); + + out: + g_free (data); } static void progress_callback (goffset current_num_bytes, - goffset total_num_bytes, - gpointer user_data) + goffset total_num_bytes, + gpointer user_data) { GVfsJob *job = G_VFS_JOB (user_data); GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job); GVfsJobPush *op_job = G_VFS_JOB_PUSH (job); - dbus_uint64_t current_dbus, total_dbus; - DBusMessage *message; + ProgressCallbackData *data; g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes); if (op_job->callback_obj_path == NULL) return; - message = - dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message), - op_job->callback_obj_path, - G_VFS_DBUS_PROGRESS_INTERFACE, - G_VFS_DBUS_PROGRESS_OP_PROGRESS); - dbus_message_set_no_reply (message, TRUE); - - current_dbus = current_num_bytes; - total_dbus = total_num_bytes; - dbus_message_append_args (message, - DBUS_TYPE_UINT64, ¤t_dbus, - DBUS_TYPE_UINT64, &total_dbus, - 0); - - /* Queues reply (threadsafely), actually sends it in mainloop */ - dbus_connection_send (dbus_job->connection, message, NULL); - dbus_message_unref (message); + data = g_new0 (ProgressCallbackData, 1); + data->current_num_bytes = current_num_bytes; + data->total_num_bytes = total_num_bytes; + + gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation), + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + g_dbus_method_invocation_get_sender (dbus_job->invocation), + op_job->callback_obj_path, + NULL, + progress_proxy_new_cb, + data); } static void @@ -207,14 +236,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_push (object, invocation); } diff --git a/daemon/gvfsjobpush.h b/daemon/gvfsjobpush.h index 09c9aa12..ae869b00 100644 --- a/daemon/gvfsjobpush.h +++ b/daemon/gvfsjobpush.h @@ -59,9 +59,15 @@ struct _GVfsJobPushClass GType g_vfs_job_push_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_push_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_push_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_local_path, + gboolean arg_send_progress, + guint arg_flags, + const gchar *arg_progress_obj_path, + gboolean arg_remove_source, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobqueryattributes.c b/daemon/gvfsjobqueryattributes.c index 51fbbc26..ba7d7be2 100644 --- a/daemon/gvfsjobqueryattributes.c +++ b/daemon/gvfsjobqueryattributes.c @@ -28,10 +28,7 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> -#include "gvfsjobmove.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" #include "gvfsjobqueryattributes.h" @@ -39,9 +36,9 @@ G_DEFINE_TYPE (GVfsJobQueryAttributes, g_vfs_job_query_attributes, G_VFS_TYPE_JO static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_query_attributes_finalize (GObject *object) @@ -76,44 +73,60 @@ g_vfs_job_query_attributes_init (GVfsJobQueryAttributes *job) { } -GVfsJob * -g_vfs_job_query_attributes_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend, - gboolean namespaces) +gboolean +g_vfs_job_query_settable_attributes_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend) { GVfsJobQueryAttributes *job; - DBusMessage *reply; - DBusError derror; - const gchar *path = NULL; - gint path_len; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path, &path_len, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called QuerySettableAttributes()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_QUERY_ATTRIBUTES, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); + + job->backend = backend; + job->filename = g_strdup (arg_path_data); + job->namespaces = FALSE; + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +gboolean +g_vfs_job_query_writable_namespaces_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend) +{ + GVfsJobQueryAttributes *job; + + g_print ("called QueryWritableNamespaces()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + + job = g_object_new (G_VFS_TYPE_JOB_QUERY_ATTRIBUTES, + "object", object, + "invocation", invocation, + NULL); + job->backend = backend; - job->filename = g_strndup (path, path_len); - job->namespaces = namespaces; + job->filename = g_strdup (arg_path_data); + job->namespaces = TRUE; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); - return G_VFS_JOB (job); + return TRUE; } static void @@ -172,20 +185,18 @@ g_vfs_job_query_attributes_set_list (GVfsJobQueryAttributes *job, } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobQueryAttributes *op_job = G_VFS_JOB_QUERY_ATTRIBUTES (job); - DBusMessage *reply; - DBusMessageIter iter; - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - _g_dbus_append_attribute_info_list (&iter, - op_job->list); + GVariant *list; - return reply; + list = _g_dbus_append_attribute_info_list (op_job->list); + + if (! op_job->namespaces) + gvfs_dbus_mount_complete_query_settable_attributes (object, invocation, list); + else + gvfs_dbus_mount_complete_query_writable_namespaces (object, invocation, list); } diff --git a/daemon/gvfsjobqueryattributes.h b/daemon/gvfsjobqueryattributes.h index 31776f61..0fb35f02 100644 --- a/daemon/gvfsjobqueryattributes.h +++ b/daemon/gvfsjobqueryattributes.h @@ -58,10 +58,14 @@ struct _GVfsJobQueryAttributesClass GType g_vfs_job_query_attributes_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_query_attributes_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend, - gboolean namespaces); +gboolean g_vfs_job_query_settable_attributes_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend); +gboolean g_vfs_job_query_writable_namespaces_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend); void g_vfs_job_query_attributes_set_list (GVfsJobQueryAttributes *job, GFileAttributeInfoList *list); diff --git a/daemon/gvfsjobqueryfsinfo.c b/daemon/gvfsjobqueryfsinfo.c index 1069f000..e62769ba 100644 --- a/daemon/gvfsjobqueryfsinfo.c +++ b/daemon/gvfsjobqueryfsinfo.c @@ -28,19 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobqueryfsinfo.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobQueryFsInfo, g_vfs_job_query_fs_info, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_query_fs_info_finalize (GObject *object) @@ -76,48 +74,36 @@ g_vfs_job_query_fs_info_init (GVfsJobQueryFsInfo *job) { } -GVfsJob * -g_vfs_job_query_fs_info_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_query_fs_info_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_attributes, + GVfsBackend *backend) { GVfsJobQueryFsInfo *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - char *attributes; - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - DBUS_TYPE_STRING, &attributes, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called QueryFsInfo()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; job = g_object_new (G_VFS_TYPE_JOB_QUERY_FS_INFO, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = g_strndup (path_data, path_len); + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->attribute_matcher = g_file_attribute_matcher_new (attributes); + job->attribute_matcher = g_file_attribute_matcher_new (arg_attributes); job->file_info = g_file_info_new (); g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher); - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -157,20 +143,14 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobQueryFsInfo *op_job = G_VFS_JOB_QUERY_FS_INFO (job); - DBusMessage *reply; - DBusMessageIter iter; const char *type; - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - type = g_vfs_backend_get_backend_type (op_job->backend); if (type) @@ -178,8 +158,6 @@ create_reply (GVfsJob *job, G_FILE_ATTRIBUTE_GVFS_BACKEND, type); - _g_dbus_append_file_info (&iter, - op_job->file_info); - - return reply; + gvfs_dbus_mount_complete_query_filesystem_info (object, invocation, + _g_dbus_append_file_info (op_job->file_info)); } diff --git a/daemon/gvfsjobqueryfsinfo.h b/daemon/gvfsjobqueryfsinfo.h index 876d0eb0..e1dead05 100644 --- a/daemon/gvfsjobqueryfsinfo.h +++ b/daemon/gvfsjobqueryfsinfo.h @@ -57,9 +57,11 @@ struct _GVfsJobQueryFsInfoClass GType g_vfs_job_query_fs_info_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_query_fs_info_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_query_fs_info_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_attributes, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobqueryinfo.c b/daemon/gvfsjobqueryinfo.c index 81b84c84..ee26dc44 100644 --- a/daemon/gvfsjobqueryinfo.c +++ b/daemon/gvfsjobqueryinfo.c @@ -29,19 +29,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobqueryinfo.h" -#include "gvfsdbusutils.h" #include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobQueryInfo, g_vfs_job_query_info, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_query_info_finalize (GObject *object) @@ -79,63 +77,41 @@ g_vfs_job_query_info_init (GVfsJobQueryInfo *job) { } -GVfsJob * -g_vfs_job_query_info_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_query_info_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_attributes, + guint arg_flags, + const gchar *arg_uri, + GVfsBackend *backend) { GVfsJobQueryInfo *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - char *attributes; - char *uri; - dbus_uint32_t flags; - DBusMessageIter iter; - - dbus_message_iter_init (message, &iter); - - dbus_error_init (&derror); - if (!_g_dbus_message_iter_get_args (&iter, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_UINT32, &flags, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } - /* Optional uri arg for thumbnail info */ - if (!_g_dbus_message_iter_get_args (&iter, NULL, - DBUS_TYPE_STRING, &uri, - 0)) - uri = NULL; - + g_print ("called QueryInfo()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_QUERY_INFO, - "message", message, - "connection", connection, + "object", object, + "invocation", invocation, NULL); - job->filename = g_strndup (path_data, path_len); + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->attributes = g_strdup (attributes); - job->attribute_matcher = g_file_attribute_matcher_new (attributes); - job->flags = flags; - job->uri = g_strdup (uri); + job->attributes = g_strdup (arg_attributes); + job->attribute_matcher = g_file_attribute_matcher_new (arg_attributes); + job->flags = arg_flags; + job->uri = g_strdup (arg_uri); job->file_info = g_file_info_new (); g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); - return G_VFS_JOB (job); + return TRUE; } static void @@ -177,26 +153,18 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobQueryInfo *op_job = G_VFS_JOB_QUERY_INFO (job); - DBusMessage *reply; - DBusMessageIter iter; - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - - g_vfs_backend_add_auto_info (op_job->backend, - op_job->attribute_matcher, - op_job->file_info, - op_job->uri); - _g_dbus_append_file_info (&iter, - op_job->file_info); - - return reply; + g_vfs_backend_add_auto_info (op_job->backend, + op_job->attribute_matcher, + op_job->file_info, + op_job->uri); + + gvfs_dbus_mount_complete_query_info (object, invocation, + _g_dbus_append_file_info (op_job->file_info)); } diff --git a/daemon/gvfsjobqueryinfo.h b/daemon/gvfsjobqueryinfo.h index 66faa193..f200f2a7 100644 --- a/daemon/gvfsjobqueryinfo.h +++ b/daemon/gvfsjobqueryinfo.h @@ -60,9 +60,14 @@ struct _GVfsJobQueryInfoClass GType g_vfs_job_query_info_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_query_info_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_query_info_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_attributes, + guint arg_flags, + const gchar *arg_uri, + GVfsBackend *backend); + G_END_DECLS diff --git a/daemon/gvfsjobsetattribute.c b/daemon/gvfsjobsetattribute.c index d99d05fd..eb45b00c 100644 --- a/daemon/gvfsjobsetattribute.c +++ b/daemon/gvfsjobsetattribute.c @@ -28,20 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobmove.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" #include "gvfsjobsetattribute.h" G_DEFINE_TYPE (GVfsJobSetAttribute, g_vfs_job_set_attribute, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_set_attribute_finalize (GObject *object) @@ -78,65 +75,49 @@ g_vfs_job_set_attribute_init (GVfsJobSetAttribute *job) job->type = G_FILE_ATTRIBUTE_TYPE_INVALID; } -GVfsJob * -g_vfs_job_set_attribute_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_set_attribute_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVariant *arg_attribute, + GVfsBackend *backend) { GVfsJobSetAttribute *job; - DBusMessage *reply; - DBusMessageIter iter, array_iter; - const gchar *filename = NULL; - gint filename_len; - GFileQueryInfoFlags flags; gchar *attribute; - dbus_uint32_t flags_u32 = 0; GFileAttributeType type; GDbusAttributeValue value; - - dbus_message_iter_init (message, &iter); - - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY && - dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_BYTE) - { - dbus_message_iter_recurse (&iter, &array_iter); - dbus_message_iter_get_fixed_array (&array_iter, &filename, &filename_len); - } - - dbus_message_iter_next (&iter); - - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32) - { - dbus_message_iter_get_basic (&iter, &flags_u32); - dbus_message_iter_next (&iter); - } + + g_print ("called SetAttribute()\n"); - flags = flags_u32; - - if (!(filename && _g_dbus_get_file_attribute (&iter, &attribute, NULL, &type, &value))) + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + + if (! _g_dbus_get_file_attribute (arg_attribute, &attribute, NULL, &type, &value)) { - reply = dbus_message_new_error (message, - DBUS_ERROR_FAILED, - _("Invalid dbus message")); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Invalid dbus message")); + return TRUE; } job = g_object_new (G_VFS_TYPE_JOB_SET_ATTRIBUTE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); job->backend = backend; - job->filename = g_strndup (filename, filename_len); + job->filename = g_strdup (arg_path_data); job->attribute = attribute; job->value = value; job->type = type; - job->flags = flags; + job->flags = arg_flags; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); - return G_VFS_JOB (job); + return TRUE; } static void @@ -180,14 +161,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_set_attribute (object, invocation); } diff --git a/daemon/gvfsjobsetattribute.h b/daemon/gvfsjobsetattribute.h index 4865a6a3..a75c15be 100644 --- a/daemon/gvfsjobsetattribute.h +++ b/daemon/gvfsjobsetattribute.h @@ -60,9 +60,12 @@ struct _GVfsJobSetAttributeClass GType g_vfs_job_set_attribute_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_set_attribute_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_set_attribute_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVariant *arg_attribute, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobsetdisplayname.c b/daemon/gvfsjobsetdisplayname.c index 983d6a0c..148f9c7a 100644 --- a/daemon/gvfsjobsetdisplayname.c +++ b/daemon/gvfsjobsetdisplayname.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobsetdisplayname.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobSetDisplayName, g_vfs_job_set_display_name, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_set_display_name_finalize (GObject *object) @@ -75,45 +72,33 @@ g_vfs_job_set_display_name_init (GVfsJobSetDisplayName *job) { } -GVfsJob * -g_vfs_job_set_display_name_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_set_display_name_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_display_name, + GVfsBackend *backend) { GVfsJobSetDisplayName *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - char *display_name; - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - DBUS_TYPE_STRING, &display_name, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called SetDisplayName()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_SET_DISPLAY_NAME, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = g_strndup (path_data, path_len); + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->display_name = g_strdup (display_name); + job->display_name = g_strdup (arg_display_name); - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -158,22 +143,14 @@ g_vfs_job_set_display_name_set_new_path (GVfsJobSetDisplayName *job, } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { GVfsJobSetDisplayName *op_job = G_VFS_JOB_SET_DISPLAY_NAME (job); - DBusMessage *reply; - DBusMessageIter iter; - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); g_assert (op_job->new_path != NULL); - _g_dbus_message_iter_append_cstring (&iter, op_job->new_path); - - return reply; + gvfs_dbus_mount_complete_set_display_name (object, invocation, op_job->new_path); } diff --git a/daemon/gvfsjobsetdisplayname.h b/daemon/gvfsjobsetdisplayname.h index 5c9c531a..8df19d8a 100644 --- a/daemon/gvfsjobsetdisplayname.h +++ b/daemon/gvfsjobsetdisplayname.h @@ -57,9 +57,11 @@ struct _GVfsJobSetDisplayNameClass GType g_vfs_job_set_display_name_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_set_display_name_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_set_display_name_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_display_name, + GVfsBackend *backend); void g_vfs_job_set_display_name_set_new_path (GVfsJobSetDisplayName *job, const char *new_path); diff --git a/daemon/gvfsjobstartmountable.c b/daemon/gvfsjobstartmountable.c index 5f68c994..9b0dce54 100644 --- a/daemon/gvfsjobstartmountable.c +++ b/daemon/gvfsjobstartmountable.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobstartmountable.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobStartMountable, g_vfs_job_start_mountable, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_start_mountable_finalize (GObject *object) @@ -76,49 +73,34 @@ g_vfs_job_start_mountable_init (GVfsJobStartMountable *job) { } -GVfsJob * -g_vfs_job_start_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_start_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend) { GVfsJobStartMountable *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - char *path; - const char *dbus_id, *obj_path; - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - path = NULL; - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0)) - { - g_free (path); - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called StartMountable()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_START_MOUNTABLE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = path; + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->mount_source = g_mount_source_new (dbus_id, obj_path); + job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path); + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); - return G_VFS_JOB (job); + return TRUE; } static void @@ -156,14 +138,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_start_mountable (object, invocation); } diff --git a/daemon/gvfsjobstartmountable.h b/daemon/gvfsjobstartmountable.h index 4593af3f..0aca7e58 100644 --- a/daemon/gvfsjobstartmountable.h +++ b/daemon/gvfsjobstartmountable.h @@ -55,9 +55,12 @@ struct _GVfsJobStartMountableClass GType g_vfs_job_start_mountable_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_start_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_start_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobstopmountable.c b/daemon/gvfsjobstopmountable.c index 96725f96..f876e7ee 100644 --- a/daemon/gvfsjobstopmountable.c +++ b/daemon/gvfsjobstopmountable.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobstopmountable.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobStopMountable, g_vfs_job_stop_mountable, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_stop_mountable_finalize (GObject *object) @@ -76,52 +73,36 @@ g_vfs_job_stop_mountable_init (GVfsJobStopMountable *job) { } -GVfsJob * -g_vfs_job_stop_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_stop_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend) { GVfsJobStopMountable *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - char *path; - const char *dbus_id, *obj_path; - guint32 flags; - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - path = NULL; - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0)) - { - g_free (path); - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } - job = g_object_new (G_VFS_TYPE_JOB_STOP_MOUNTABLE, - "message", message, - "connection", connection, - NULL); + g_print ("called StopMountable()\n"); - job->filename = path; + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + + job = g_object_new (G_VFS_TYPE_JOB_STOP_MOUNTABLE, + "object", object, + "invocation", invocation, + NULL); + + job->filename = g_strdup (arg_path_data); job->backend = backend; - job->mount_source = g_mount_source_new (dbus_id, obj_path); - job->flags = flags; + job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path); + job->flags = arg_flags; - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -161,14 +142,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_enumerate (object, invocation); } diff --git a/daemon/gvfsjobstopmountable.h b/daemon/gvfsjobstopmountable.h index 96adac21..cef6d814 100644 --- a/daemon/gvfsjobstopmountable.h +++ b/daemon/gvfsjobstopmountable.h @@ -56,8 +56,12 @@ struct _GVfsJobStopMountableClass GType g_vfs_job_stop_mountable_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_stop_mountable_new (DBusConnection *connection, - DBusMessage *message, +gboolean g_vfs_job_stop_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobtrash.c b/daemon/gvfsjobtrash.c index 1e1b13dc..5e2f8a9c 100644 --- a/daemon/gvfsjobtrash.c +++ b/daemon/gvfsjobtrash.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobtrash.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobTrash, g_vfs_job_trash, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_trash_finalize (GObject *object) @@ -73,42 +70,31 @@ g_vfs_job_trash_init (GVfsJobTrash *job) { } -GVfsJob * -g_vfs_job_trash_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_trash_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend) { GVfsJobTrash *job; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + g_print ("called Trash()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_TRASH, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = g_strndup (path_data, path_len); + job->filename = g_strdup (arg_path_data); job->backend = backend; - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -144,14 +130,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_trash (object, invocation); } diff --git a/daemon/gvfsjobtrash.h b/daemon/gvfsjobtrash.h index ddf663c3..a68ee07e 100644 --- a/daemon/gvfsjobtrash.h +++ b/daemon/gvfsjobtrash.h @@ -54,10 +54,10 @@ struct _GVfsJobTrashClass GType g_vfs_job_trash_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_trash_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); - +gboolean g_vfs_job_trash_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + GVfsBackend *backend); G_END_DECLS #endif /* __G_VFS_JOB_TRASH_H__ */ diff --git a/daemon/gvfsjobunmount.c b/daemon/gvfsjobunmount.c index 75e99dd3..7e79d691 100644 --- a/daemon/gvfsjobunmount.c +++ b/daemon/gvfsjobunmount.c @@ -28,20 +28,17 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobunmount.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonprotocol.h" G_DEFINE_TYPE (GVfsJobUnmount, g_vfs_job_unmount, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); static void send_reply (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_unmount_finalize (GObject *object) @@ -70,7 +67,6 @@ g_vfs_job_unmount_class_init (GVfsJobUnmountClass *klass) job_class->send_reply = send_reply; job_dbus_class->create_reply = create_reply; - } static void @@ -78,50 +74,36 @@ g_vfs_job_unmount_init (GVfsJobUnmount *job) { } -GVfsJob * -g_vfs_job_unmount_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_unmount_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + guint arg_flags, + GVfsBackend *backend) { GVfsJobUnmount *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - const char *dbus_id, *obj_path; - guint32 flags; - - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - if (!_g_dbus_message_iter_get_args (&iter, &derror, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_UINT32, &flags, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } - g_debug ("g_vfs_job_unmount_new request: %p\n", message); - + g_print ("called Unmount()\n"); + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + + g_debug ("g_vfs_job_unmount_new request: %p\n", invocation); + job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); job->backend = backend; - job->flags = flags; - job->mount_source = g_mount_source_new (dbus_id, obj_path); + job->flags = arg_flags; + job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path); - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; } static void @@ -289,16 +271,29 @@ try (GVfsJob *job) } static void -unregister_mount_callback (DBusMessage *unmount_reply, - GError *error, - gpointer user_data) +unregister_mount_callback (GVfsDBusMountTracker *proxy, + GAsyncResult *res, + gpointer user_data) { GVfsBackend *backend; GVfsDaemon *daemon; + GVfsJob *job = G_VFS_JOB (user_data); GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (user_data); + GError *error = NULL; - g_debug ("unregister_mount_callback, unmount_reply: %p, error: %p\n", unmount_reply, error); - + gvfs_dbus_mount_tracker_call_unregister_mount_finish (proxy, + res, + &error); + g_debug ("unregister_mount_callback, error: %p\n", error); + + if (error != NULL) + { + /* If we failed before, don't overwrite the error as this one is not that important */ + if (! job->failed) + g_vfs_job_failed_from_error (job, error); + g_error_free (error); + } + backend = op_job->backend; (*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job)); @@ -327,20 +322,16 @@ send_reply (GVfsJob *job) set active GVfsChannels to block requets */ g_vfs_backend_set_block_requests (backend); g_vfs_backend_unregister_mount (backend, - unregister_mount_callback, + (GAsyncReadyCallback) unregister_mount_callback, job); } } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_unmount (object, invocation); } diff --git a/daemon/gvfsjobunmount.h b/daemon/gvfsjobunmount.h index c5266cd5..991db459 100644 --- a/daemon/gvfsjobunmount.h +++ b/daemon/gvfsjobunmount.h @@ -58,9 +58,12 @@ struct _GVfsJobUnmountClass GType g_vfs_job_unmount_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_unmount_new (DBusConnection *connection, - DBusMessage *request, - GVfsBackend *backend); +gboolean g_vfs_job_unmount_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + guint arg_flags, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/gvfsjobunmountmountable.c b/daemon/gvfsjobunmountmountable.c index 3c99284a..a87de3bf 100644 --- a/daemon/gvfsjobunmountmountable.c +++ b/daemon/gvfsjobunmountmountable.c @@ -28,19 +28,16 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> #include "gvfsjobunmountmountable.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobUnmountMountable, g_vfs_job_unmount_mountable, G_VFS_TYPE_JOB_DBUS) static void run (GVfsJob *job); static gboolean try (GVfsJob *job); -static DBusMessage *create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); static void g_vfs_job_unmount_mountable_finalize (GObject *object) @@ -76,54 +73,78 @@ g_vfs_job_unmount_mountable_init (GVfsJobUnmountMountable *job) { } -GVfsJob * -g_vfs_job_unmount_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend, - gboolean eject) +static gboolean +do_g_vfs_job_unmount_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend, + gboolean eject) { GVfsJobUnmountMountable *job; - DBusMessage *reply; - DBusMessageIter iter; - DBusError derror; - char *path; - guint32 flags; - const char *dbus_id, *obj_path; - - dbus_error_init (&derror); - dbus_message_iter_init (message, &iter); - - path = NULL; - if (!_g_dbus_message_iter_get_args (&iter, &derror, - G_DBUS_TYPE_CSTRING, &path, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0)) - { - g_free (path); - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, - "message", message, - "connection", connection, - NULL); + "object", object, + "invocation", invocation, + NULL); - job->filename = path; + job->filename = g_strdup (arg_path_data); job->backend = backend; job->eject = eject; - job->flags = flags; - job->mount_source = g_mount_source_new (dbus_id, obj_path); + job->flags = arg_flags; + job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path); - return G_VFS_JOB (job); + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +gboolean +g_vfs_job_unmount_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend) +{ + g_print ("called UnmountMountable()\n"); + + return do_g_vfs_job_unmount_mountable_new_handle (object, + invocation, + arg_path_data, + arg_flags, + arg_dbus_id, + arg_obj_path, + backend, + FALSE); +} + +gboolean +g_vfs_job_eject_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend) +{ + g_print ("called EjectMountable()\n"); + + return do_g_vfs_job_unmount_mountable_new_handle (object, + invocation, + arg_path_data, + arg_flags, + arg_dbus_id, + arg_obj_path, + backend, + TRUE); } static void @@ -195,14 +216,10 @@ try (GVfsJob *job) } /* Might be called on an i/o thread */ -static DBusMessage * +static void create_reply (GVfsJob *job, - DBusConnection *connection, - DBusMessage *message) + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) { - DBusMessage *reply; - - reply = dbus_message_new_method_return (message); - - return reply; + gvfs_dbus_mount_complete_enumerate (object, invocation); } diff --git a/daemon/gvfsjobunmountmountable.h b/daemon/gvfsjobunmountmountable.h index d90da8ed..988514e2 100644 --- a/daemon/gvfsjobunmountmountable.h +++ b/daemon/gvfsjobunmountmountable.h @@ -57,10 +57,21 @@ struct _GVfsJobUnmountMountableClass GType g_vfs_job_unmount_mountable_get_type (void) G_GNUC_CONST; -GVfsJob *g_vfs_job_unmount_mountable_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend, - gboolean eject); +gboolean g_vfs_job_unmount_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend); + +gboolean g_vfs_job_eject_mountable_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + const gchar *arg_dbus_id, + const gchar *arg_obj_path, + GVfsBackend *backend); G_END_DECLS diff --git a/daemon/main.c b/daemon/main.c index 1ec1eb43..2a247bdd 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -25,21 +25,104 @@ #include <glib.h> #include <glib/gi18n.h> #include <glib/gstdio.h> -#include <dbus/dbus.h> #include "gvfsdaemon.h" #include "gvfsbackendtest.h" #include <gvfsdaemonprotocol.h> #include "mount.h" #include <locale.h> + + +static GMainLoop *loop; +static gboolean already_acquired = FALSE; +static int process_result = 0; + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + if (connection == NULL) + { + g_printerr ("A connection to the bus can't be made\n"); + process_result = 1; + } + else + { + if (already_acquired) + { + g_printerr ("Got NameLost, some other instance replaced us\n"); + } + else + { + g_printerr ("Failed to acquire daemon name, perhaps the VFS daemon is already running?\n"); + process_result = 1; + } + } + g_main_loop_quit (loop); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + gboolean no_fuse = GPOINTER_TO_UINT (user_data); + + g_warning ("main.c: Acquired the name %s on the session message bus\n", name); + already_acquired = TRUE; + + mount_init (); + +#ifdef HAVE_FUSE + if (!no_fuse) + { + char *fuse_path; + char *argv2[4]; + + /* Use the old .gvfs location as fallback, not .cache/gvfs */ + if (g_get_user_runtime_dir() == g_get_user_cache_dir ()) + fuse_path = g_build_filename (g_get_home_dir(), ".gvfs", NULL); + else + fuse_path = g_build_filename (g_get_user_runtime_dir (), "gvfs", NULL); + + if (!g_file_test (fuse_path, G_FILE_TEST_EXISTS)) + g_mkdir (fuse_path, 0700); + + /* The -f (foreground) option prevent libfuse to call daemon(). */ + /* First, this is not required as g_spawn_async() already */ + /* detach the process. Secondly, calling daemon() and then */ + /* pthread_create() produce an undefined result accoring to */ + /* Opengroup. On system with the uClibc library this will badly */ + /* hang the process. */ + argv2[0] = LIBEXEC_DIR "/gvfsd-fuse"; + argv2[1] = "-f"; + argv2[2] = fuse_path; + argv2[3] = NULL; + + g_spawn_async (NULL, + argv2, + NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + NULL, NULL); + + g_free (fuse_path); + } +#endif +} + + int main (int argc, char *argv[]) { - GMainLoop *loop; GVfsDaemon *daemon; gboolean replace; gboolean no_fuse; GError *error; + guint name_owner_id; + GBusNameOwnerFlags flags; GOptionContext *context; const GOptionEntry options[] = { { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, N_("Replace old daemon."), NULL }, @@ -87,58 +170,39 @@ main (int argc, char *argv[]) g_option_context_free (context); - dbus_threads_init_default (); - g_type_init (); + loop = g_main_loop_new (NULL, FALSE); daemon = g_vfs_daemon_new (TRUE, replace); if (daemon == NULL) return 1; - mount_init (); - - loop = g_main_loop_new (NULL, FALSE); + /* FIXME: a message filter??! */ + /* Request name only after we've installed the message filter */ + flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; + if (replace) + flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; + name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + G_VFS_DBUS_DAEMON_NAME, + flags, + NULL, + on_name_acquired, + on_name_lost, + GUINT_TO_POINTER (no_fuse), + NULL); -#ifdef HAVE_FUSE - if (!no_fuse) - { - char *fuse_path; - char *argv2[4]; - - /* Use the old .gvfs location as fallback, not .cache/gvfs */ - if (g_get_user_runtime_dir() == g_get_user_cache_dir ()) - fuse_path = g_build_filename (g_get_home_dir(), ".gvfs", NULL); - else - fuse_path = g_build_filename (g_get_user_runtime_dir (), "gvfs", NULL); - - if (!g_file_test (fuse_path, G_FILE_TEST_EXISTS)) - g_mkdir (fuse_path, 0700); - - /* The -f (foreground) option prevent libfuse to call daemon(). */ - /* First, this is not required as g_spawn_async() already */ - /* detach the process. Secondly, calling daemon() and then */ - /* pthread_create() produce an undefined result accoring to */ - /* Opengroup. On system with the uClibc library this will badly */ - /* hang the process. */ - argv2[0] = LIBEXEC_DIR "/gvfsd-fuse"; - argv2[1] = "-f"; - argv2[2] = fuse_path; - argv2[3] = NULL; - - g_spawn_async (NULL, - argv2, - NULL, - G_SPAWN_STDOUT_TO_DEV_NULL | - G_SPAWN_STDERR_TO_DEV_NULL, - NULL, NULL, - NULL, NULL); - - g_free (fuse_path); - } -#endif - g_main_loop_run (loop); + +#if 0 + /* FIXME: crashing */ + if (daemon != NULL) + g_object_unref (daemon); +#endif + if (name_owner_id != 0) + g_bus_unown_name (name_owner_id); + if (loop != NULL) + g_main_loop_unref (loop); - return 0; + return process_result; } diff --git a/daemon/mount.c b/daemon/mount.c index b6909460..97a01094 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -27,13 +27,12 @@ #include <signal.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> +#include <gio/gio.h> #include "mount.h" #include "gmountoperationdbus.h" #include "gvfsdaemonprotocol.h" -#include "gvfsdbusutils.h" -#include <gio/gio.h> +#include <gvfsdbus.h> typedef struct { char *display_name; @@ -43,11 +42,12 @@ typedef struct { char *prefered_filename_encoding; gboolean user_visible; char *default_location; - char *fuse_mountpoint; /* Always set, even if fuse not availible */ + char *fuse_mountpoint; /* Always set, even if fuse not available */ /* Daemon object ref */ char *dbus_id; char *object_path; + guint name_watcher_id; /* Mount details */ GMountSpec *mount_spec; @@ -73,15 +73,10 @@ static GList *mounts = NULL; static gboolean fuse_available; -static void lookup_mount (DBusConnection *connection, - DBusMessage *message, - gboolean do_automount); -static void mountable_mount (VfsMountable *mountable, - GMountSpec *mount_spec, - GMountSource *source, - gboolean automount, - MountCallback callback, - gpointer user_data); +static void lookup_mount (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + GMountSpec *spec, + gboolean do_automount); static VfsMount * find_vfs_mount (const char *dbus_id, @@ -125,7 +120,6 @@ find_vfs_mount_by_fuse_path (const char *fuse_path) return NULL; } - static VfsMount * match_vfs_mount (GMountSpec *match) { @@ -183,6 +177,9 @@ vfs_mountable_free (VfsMountable *mountable) static void vfs_mount_free (VfsMount *mount) { + if (mount->name_watcher_id != 0) + g_bus_unwatch_name (mount->name_watcher_id); + g_free (mount->display_name); g_free (mount->stable_name); g_free (mount->x_content_types); @@ -193,129 +190,43 @@ vfs_mount_free (VfsMount *mount) g_free (mount->dbus_id); g_free (mount->object_path); g_mount_spec_unref (mount->mount_spec); - + g_free (mount); } -static void -vfs_mount_to_dbus (VfsMount *mount, - DBusMessageIter *iter) + +/* Keep in sync with dbus-interfaces.xml */ +#define VFS_MOUNT_ARRAY_DBUS_STRUCT_TYPE "a(sosssssbay(aya{sv})ay)" +#define VFS_MOUNTABLE_ARRAY_DBUS_STRUCT_TYPE "a(ssasib)" + +static GVariant * +vfs_mount_to_dbus (VfsMount *mount) { - DBusMessageIter struct_iter; - dbus_bool_t user_visible; - char *fuse_mountpoint; - - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_STRUCT, - NULL, - &struct_iter)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &mount->dbus_id)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_OBJECT_PATH, - &mount->object_path)) - _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 (&struct_iter, - DBUS_TYPE_STRING, - &mount->stable_name)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &mount->x_content_types)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &mount->icon)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &mount->prefered_filename_encoding)) - _g_dbus_oom (); - - user_visible = mount->user_visible; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_BOOLEAN, - &user_visible)) - _g_dbus_oom (); - - fuse_mountpoint = ""; - if (fuse_available && mount->fuse_mountpoint) - fuse_mountpoint = mount->fuse_mountpoint; - _g_dbus_message_iter_append_cstring (&struct_iter, fuse_mountpoint); - - g_mount_spec_to_dbus (&struct_iter, mount->mount_spec); - - _g_dbus_message_iter_append_cstring (&struct_iter, mount->default_location); - - if (!dbus_message_iter_close_container (iter, &struct_iter)) - _g_dbus_oom (); + return g_variant_new ("(sosssssb^ay@(aya{sv})^ay)", + mount->dbus_id, + mount->object_path, + mount->display_name, + mount->stable_name, + mount->x_content_types, + mount->icon, + mount->prefered_filename_encoding, + mount->user_visible, + (fuse_available && mount->fuse_mountpoint) ? mount->fuse_mountpoint : "", + g_mount_spec_to_dbus (mount->mount_spec), + mount->default_location); } -static void -vfs_mountable_to_dbus (VfsMountable *mountable, - DBusMessageIter *iter) +static GVariant * +vfs_mountable_to_dbus (VfsMountable *mountable) { - DBusMessageIter struct_iter; - dbus_bool_t bool; - guint32 int32; - char *s; - char **a; char *empty[] = {NULL}; - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_STRUCT, - NULL, - &struct_iter)) - _g_dbus_oom (); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &mountable->type)) - _g_dbus_oom (); - - s = mountable->scheme; - if (s == NULL) - s = ""; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &s)) - _g_dbus_oom (); - - a = mountable->scheme_aliases; - if (a == NULL) - a = empty; - _g_dbus_message_iter_append_args (&struct_iter, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &a, (int)g_strv_length (a), - 0); - - int32 = mountable->default_port; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_INT32, - &int32)) - _g_dbus_oom (); - - bool = mountable->hostname_is_inet; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_BOOLEAN, - &bool)) - _g_dbus_oom (); - - if (!dbus_message_iter_close_container (iter, &struct_iter)) - _g_dbus_oom (); + return g_variant_new ("(ss^asib)", + mountable->type, + mountable->scheme ? mountable->scheme : "", + mountable->scheme_aliases ? mountable->scheme_aliases : empty, + mountable->default_port, + mountable->hostname_is_inet); } @@ -326,13 +237,14 @@ vfs_mountable_to_dbus (VfsMountable *mountable, typedef struct { VfsMountable *mountable; - dbus_bool_t automount; + gboolean automount; GMountSource *source; GMountSpec *mount_spec; MountCallback callback; gpointer user_data; char *obj_path; gboolean spawned; + GVfsDBusSpawner *spawner; } MountData; static void spawn_mount (MountData *data); @@ -343,7 +255,11 @@ mount_data_free (MountData *data) g_object_unref (data->source); g_mount_spec_unref (data->mount_spec); g_free (data->obj_path); - + if (data->spawner) + g_object_unref (data->spawner); + + g_print ("mount_data_free\n"); + g_free (data); } @@ -355,123 +271,116 @@ mount_finish (MountData *data, GError *error) } static void -dbus_mount_reply (DBusPendingCall *pending, - void *_data) +dbus_mount_reply (GVfsDBusMountable *proxy, + GAsyncResult *res, + gpointer user_data) { - DBusMessage *reply; - GError *error; - MountData *data = _data; - - reply = dbus_pending_call_steal_reply (pending); - dbus_pending_call_unref (pending); + GError *error = NULL; + MountData *data = user_data; - if ((dbus_message_is_error (reply, DBUS_ERROR_NAME_HAS_NO_OWNER) || - dbus_message_is_error (reply, DBUS_ERROR_SERVICE_UNKNOWN)) && - !data->spawned) - spawn_mount (data); + if (!gvfs_dbus_mountable_call_mount_finish (proxy, + res, + &error)) + { + g_warning ("dbus_mount_reply: Error from org.gtk.vfs.Mountable.mount(): %s", error->message); + g_warning ("dbus_mount_reply: TODO handle not spawned"); + + /* FIXME: handle NOT_SPAWNED */ +#if 0 + if ((dbus_message_is_error (reply, DBUS_ERROR_NAME_HAS_NO_OWNER) || + dbus_message_is_error (reply, DBUS_ERROR_SERVICE_UNKNOWN)) && + !data->spawned) + spawn_mount (data); +#endif + + mount_finish (data, error); + g_error_free (error); + } else { - error = NULL; - if (_g_error_from_message (reply, &error)) - { - mount_finish (data, error); - g_error_free (error); - } - else - mount_finish (data, NULL); + mount_finish (data, NULL); } - - dbus_message_unref (reply); } static void -mountable_mount_with_name (MountData *data, - const char *dbus_name) +mountable_mount_proxy_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - DBusConnection *conn; - DBusMessage *message; - DBusPendingCall *pending; + GVfsDBusMountable *proxy; GError *error = NULL; - DBusMessageIter iter; - - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - message = dbus_message_new_method_call (dbus_name, - G_VFS_DBUS_MOUNTABLE_PATH, - G_VFS_DBUS_MOUNTABLE_INTERFACE, - G_VFS_DBUS_MOUNTABLE_OP_MOUNT); - - dbus_message_iter_init_append (message, &iter); - g_mount_spec_to_dbus (&iter, data->mount_spec); - - _g_dbus_message_append_args (message, - DBUS_TYPE_BOOLEAN, &data->automount, - 0); - - g_mount_source_to_dbus (data->source, message); - - if (!dbus_connection_send_with_reply (conn, message, - &pending, - G_VFS_DBUS_MOUNT_TIMEOUT_MSECS)) - _g_dbus_oom (); - - dbus_message_unref (message); - dbus_connection_unref (conn); + MountData *data = user_data; - if (pending == NULL) + proxy = gvfs_dbus_mountable_proxy_new_for_bus_finish (res, &error); + g_print ("mountable_mount_proxy_cb: proxy = %p, error = %p\n", proxy, error); + + if (proxy == NULL) { - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "Connection is closed"); + g_printerr ("mountable_mount_proxy_cb: Error creating proxy: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); mount_finish (data, error); g_error_free (error); return; } + + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), + G_VFS_DBUS_MOUNT_TIMEOUT_MSECS); - if (!dbus_pending_call_set_notify (pending, - dbus_mount_reply, - data, NULL)) - _g_dbus_oom (); + g_print ("mountable_mount_with_name: before call_mount\n"); + gvfs_dbus_mountable_call_mount (proxy, + g_mount_spec_to_dbus (data->mount_spec), + data->automount, + g_mount_source_to_dbus (data->source), + NULL, + (GAsyncReadyCallback) dbus_mount_reply, data); + g_print ("mountable_mount_with_name: after call_mount\n"); + + g_object_unref (proxy); } -static DBusHandlerResult -spawn_mount_message_function (DBusConnection *connection, - DBusMessage *message, - void *user_data) +static void +mountable_mount_with_name (MountData *data, + const char *dbus_name) +{ + g_print ("mountable_mount_with_name: dbus_name = '%s'\n", dbus_name); + + gvfs_dbus_mountable_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + dbus_name, + G_VFS_DBUS_MOUNTABLE_PATH, + NULL, + mountable_mount_proxy_cb, + data); +} + +static gboolean +spawn_mount_handle_spawned (GVfsDBusSpawner *object, + GDBusMethodInvocation *invocation, + gboolean arg_succeeded, + const gchar *arg_error_message, + gpointer user_data) { MountData *data = user_data; - GError *error = NULL; - dbus_bool_t succeeded; - char *error_message; + GError *error; - if (dbus_message_is_method_call (message, - G_VFS_DBUS_SPAWNER_INTERFACE, - G_VFS_DBUS_OP_SPAWNED)) + g_print ("called org.gtk.vfs.Spawner.spawned(), sender = '%s', succeeded = %d\n", g_dbus_method_invocation_get_sender (invocation), arg_succeeded); + + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (data->spawner)); + + if (!arg_succeeded) { - dbus_connection_unregister_object_path (connection, data->obj_path); - - if (!dbus_message_get_args (message, NULL, - DBUS_TYPE_BOOLEAN, &succeeded, - DBUS_TYPE_STRING, &error_message, - DBUS_TYPE_INVALID)) - { - g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid arguments from spawned child")); - mount_finish (data, error); - g_error_free (error); - } - else if (!succeeded) - { - g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, error_message); - mount_finish (data, error); - g_error_free (error); - } - else - mountable_mount_with_name (data, dbus_message_get_sender (message)); - - return DBUS_HANDLER_RESULT_HANDLED; + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, arg_error_message); + mount_finish (data, error); + g_error_free (error); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + else + { + mountable_mount_with_name (data, g_dbus_method_invocation_get_sender (invocation)); + } + + gvfs_dbus_spawner_complete_spawned (object, invocation); + + return TRUE; } static void @@ -479,12 +388,8 @@ spawn_mount (MountData *data) { char *exec; GError *error; - DBusConnection *connection; + GDBusConnection *connection; static int mount_id = 0; - DBusObjectPathVTable spawn_vtable = { - NULL, - spawn_mount_message_function - }; data->spawned = TRUE; @@ -500,25 +405,41 @@ spawn_mount (MountData *data) { data->obj_path = g_strdup_printf ("/org/gtk/gvfs/exec_spaw/%d", mount_id++); - connection = dbus_bus_get (DBUS_BUS_SESSION, NULL); - if (!dbus_connection_register_object_path (connection, - data->obj_path, - &spawn_vtable, - data)) - _g_dbus_oom (); + connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (! connection) + { + mount_finish (data, error); + g_error_free (error); + return; + } - exec = g_strconcat (data->mountable->exec, " --spawner ", dbus_bus_get_unique_name (connection), " ", data->obj_path, NULL); - + data->spawner = gvfs_dbus_spawner_skeleton_new (); + g_signal_connect (data->spawner, "handle-spawned", G_CALLBACK (spawn_mount_handle_spawned), data); + + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (data->spawner), + connection, + data->obj_path, + &error)) + { + mount_finish (data, error); + g_error_free (error); + g_object_unref (connection); + return; + } + + exec = g_strconcat (data->mountable->exec, " --spawner ", g_dbus_connection_get_unique_name (connection), " ", data->obj_path, NULL); if (!g_spawn_command_line_async (exec, &error)) { - dbus_connection_unregister_object_path (connection, data->obj_path); + g_print ("spawning failed.\n"); + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (data->spawner)); mount_finish (data, error); g_error_free (error); } + g_print ("spawn okay.\n"); /* TODO: Add a timeout here to detect spawned app crashing */ - dbus_connection_unref (connection); + g_object_unref (connection); g_free (exec); } } @@ -618,31 +539,52 @@ re_read_mountable_config (void) * Support for keeping track of active mounts * ************************************************************************/ +typedef struct +{ + GVariant *mount; + gboolean mounted; +} SignalMountedData; + +static void +mount_tracker_proxy_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GVfsDBusMountTracker *proxy; + SignalMountedData *data = user_data; + + proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, NULL); + g_print ("mount_tracker_proxy_cb: signalling %s, proxy = %p\n", data->mounted ? "mount" : "umount", proxy); + + if (proxy != NULL) + { + if (data->mounted) + gvfs_dbus_mount_tracker_emit_mounted (proxy, data->mount); + else + gvfs_dbus_mount_tracker_emit_unmounted (proxy, data->mount); + + g_object_unref (proxy); + g_free (data); + } +} + static void signal_mounted_unmounted (VfsMount *mount, gboolean mounted) { - DBusMessage *message; - DBusMessageIter iter; - DBusConnection *conn; - - message = dbus_message_new_signal (G_VFS_DBUS_MOUNTTRACKER_PATH, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - mounted ? - G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED : - G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED - ); - if (message == NULL) - _g_dbus_oom (); - - dbus_message_iter_init_append (message, &iter); - vfs_mount_to_dbus (mount, &iter); - - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - dbus_connection_send (conn, message, NULL); - dbus_connection_unref (conn); + SignalMountedData *data; + + data = g_new0 (SignalMountedData, 1); + data->mount = vfs_mount_to_dbus (mount); + data->mounted = mounted; - dbus_message_unref (message); + gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + G_VFS_DBUS_DAEMON_NAME, + G_VFS_DBUS_MOUNTTRACKER_PATH, + NULL, + mount_tracker_proxy_cb, + data); } static void @@ -667,100 +609,107 @@ dbus_client_disconnected (const char *dbus_id) } static void -register_mount (DBusConnection *connection, - DBusMessage *message) +name_vanished_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_print ("name_vanished_cb: name = '%s'\n", name); + + dbus_client_disconnected (name); +} + +static gboolean +handle_register_mount (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + const gchar *arg_obj_path, + const gchar *arg_display_name, + const gchar *arg_stable_name, + const gchar *arg_x_content_types, + const gchar *arg_icon, + const gchar *arg_prefered_filename_encoding, + gboolean arg_user_visible, + GVariant *arg_mount_spec, + const gchar *arg_default_location, + gpointer user_data) { VfsMount *mount; - DBusMessage *reply; - DBusError error; - const char *display_name, *stable_name, *x_content_types, *icon, *obj_path; - const char *id, *prefered_filename_encoding; - char *default_location; - dbus_bool_t user_visible; - DBusMessageIter iter; + const char *id; GMountSpec *mount_spec; - id = dbus_message_get_sender (message); - - dbus_message_iter_init (message, &iter); - - dbus_error_init (&error); - if (_g_dbus_message_iter_get_args (&iter, - &error, - DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_STRING, &display_name, - DBUS_TYPE_STRING, &stable_name, - DBUS_TYPE_STRING, &x_content_types, - DBUS_TYPE_STRING, &icon, - DBUS_TYPE_STRING, &prefered_filename_encoding, - DBUS_TYPE_BOOLEAN, &user_visible, - 0)) + g_print ("called handle_register_mount()\n"); + + id = g_dbus_method_invocation_get_sender (invocation); + + if (find_vfs_mount (id, arg_obj_path) != NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_ALREADY_MOUNTED, + "Mountpoint Already registered"); + } + else if ((mount_spec = g_mount_spec_from_dbus (arg_mount_spec)) == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Error in mount spec"); + } + else if (match_vfs_mount (mount_spec) != NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_ALREADY_MOUNTED, + "Mountpoint Already registered"); + } + else { - if (find_vfs_mount (id, obj_path) != NULL) - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Mountpoint Already registered"); - else if ((mount_spec = g_mount_spec_from_dbus (&iter)) == NULL) - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Error in mount spec"); - else if (match_vfs_mount (mount_spec) != NULL) - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Mountpoint Already registered"); + mount = g_new0 (VfsMount, 1); + mount->display_name = g_strdup (arg_display_name); + mount->stable_name = g_strdup (arg_stable_name); + mount->x_content_types = g_strdup (arg_x_content_types); + mount->icon = g_strdup (arg_icon); + mount->prefered_filename_encoding = g_strdup (arg_prefered_filename_encoding); + mount->user_visible = arg_user_visible; + mount->dbus_id = g_strdup (id); + mount->object_path = g_strdup (arg_obj_path); + mount->mount_spec = mount_spec; + + if (arg_default_location) + mount->default_location = g_strdup (arg_default_location); else - { - mount = g_new0 (VfsMount, 1); - mount->display_name = g_strdup (display_name); - mount->stable_name = g_strdup (stable_name); - mount->x_content_types = g_strdup (x_content_types); - mount->icon = g_strdup (icon); - mount->prefered_filename_encoding = g_strdup (prefered_filename_encoding); - mount->user_visible = user_visible; - mount->dbus_id = g_strdup (id); - mount->object_path = g_strdup (obj_path); - mount->mount_spec = mount_spec; - - if (_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &default_location, - 0)) - mount->default_location = default_location; - else - mount->default_location = g_strdup (""); - - if (user_visible) - { - char *fs_name; - - /* Keep in sync with fuse daemon */ - fs_name = g_uri_escape_string (mount->stable_name, "+@#$., ", TRUE); - - /* Use the old .gvfs location as fallback, not .cache/gvfs */ - if (g_get_user_runtime_dir() == g_get_user_cache_dir ()) - mount->fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL); - else - mount->fuse_mountpoint = g_build_filename (g_get_user_runtime_dir(), "gvfs", fs_name, NULL); - } - - mounts = g_list_prepend (mounts, mount); - - signal_mounted_unmounted (mount, TRUE); + mount->default_location = g_strdup (""); + + if (arg_user_visible) + { + char *fs_name; + + /* Keep in sync with fuse daemon */ + fs_name = g_uri_escape_string (mount->stable_name, "+@#$., ", TRUE); + + /* Use the old .gvfs location as fallback, not .cache/gvfs */ + if (g_get_user_runtime_dir() == g_get_user_cache_dir ()) + mount->fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL); + else + mount->fuse_mountpoint = g_build_filename (g_get_user_runtime_dir(), "gvfs", fs_name, NULL); + } + + mounts = g_list_prepend (mounts, mount); - reply = dbus_message_new_method_return (message); - } - } - else - { - reply = dbus_message_new_error (message, - error.name, error.message); - dbus_error_free (&error); + g_print ("handle_register_mount: dbus_id = '%s'\n", id); + + /* watch the mount for being disconnected */ + mount->name_watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + id, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + name_vanished_cb, + NULL, + NULL); + + signal_mounted_unmounted (mount, TRUE); + + g_print ("handle_register_mount: calling complete\n"); + gvfs_dbus_mount_tracker_complete_register_mount (object, invocation); } - if (reply == NULL) - _g_dbus_oom (); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); + return TRUE; } typedef struct { @@ -773,39 +722,34 @@ automount_done (VfsMountable *mountable, GError *error, gpointer _data) { - DBusMessage *reply; AutoMountData *data = _data; if (error) - { - reply = _dbus_message_new_gerror (data->message, - G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED, - _("Automount failed: %s"), error->message); - dbus_connection_send (data->connection, reply, NULL); - dbus_message_unref (reply); - } + g_dbus_method_invocation_return_error (data->invocation, + G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED, + _("Automount failed: %s"), error->message); else - lookup_mount (data->connection, - data->message, - FALSE); - - dbus_connection_unref (data->connection); - dbus_message_unref (data->message); + lookup_mount (data->object, + data->invocation, + data->spec, + FALSE); + + g_object_unref (data->object); + g_object_unref (data->invocation); + g_mount_spec_unref (data->spec); g_free (data); } -static DBusMessage * +static void maybe_automount (GMountSpec *spec, - DBusMessage *message, - DBusConnection *connection, - gboolean do_automount) + GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + gboolean do_automount) { VfsMountable *mountable; - DBusMessage *reply; mountable = lookup_mountable (spec); - reply = NULL; if (mountable != NULL && do_automount && mountable->automount) { AutoMountData *data; @@ -816,163 +760,109 @@ maybe_automount (GMountSpec *spec, mount_source = g_mount_source_new_dummy (); data = g_new0 (AutoMountData, 1); - data->message = dbus_message_ref (message); - data->connection = dbus_connection_ref (connection); + data->object = g_object_ref (object); + data->invocation = g_object_ref (invocation); + data->spec = g_mount_spec_ref (spec); mountable_mount (mountable, spec, mount_source, TRUE, automount_done, data); g_object_unref (mount_source); } else if (mountable != NULL) - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, - G_IO_ERROR_NOT_MOUNTED, - _("The specified location is not mounted")); + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_NOT_MOUNTED, + _("The specified location is not mounted")); else - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - _("The specified location is not supported")); - - return reply; + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("The specified location is not supported")); } static void -lookup_mount (DBusConnection *connection, - DBusMessage *message, - gboolean do_automount) +lookup_mount (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + GMountSpec *spec, + gboolean do_automount) { VfsMount *mount; - DBusMessage *reply; - DBusMessageIter iter; - GMountSpec *spec; - dbus_message_iter_init (message, &iter); - spec = g_mount_spec_from_dbus (&iter); + mount = match_vfs_mount (spec); + if (mount == NULL) + maybe_automount (spec, object, invocation, do_automount); + else + gvfs_dbus_mount_tracker_complete_lookup_mount (object, invocation, + vfs_mount_to_dbus (mount)); +} - reply = NULL; - if (spec != NULL) - { - mount = match_vfs_mount (spec); +static gboolean +handle_lookup_mount (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + GVariant *arg_mount_spec, + gpointer user_data) +{ + GMountSpec *spec; - if (mount == NULL) - reply = maybe_automount (spec, message, connection, do_automount); - else - { - reply = dbus_message_new_method_return (message); + g_print ("called lookup_mount(), sender = '%s', obj_path = '%s'\n", g_dbus_method_invocation_get_sender (invocation), g_dbus_method_invocation_get_object_path (invocation)); - if (reply) - { - dbus_message_iter_init_append (reply, &iter); - - vfs_mount_to_dbus (mount, &iter); - } - } + spec = g_mount_spec_from_dbus (arg_mount_spec); + if (spec != NULL) + { + lookup_mount (object, invocation, spec, TRUE); g_mount_spec_unref (spec); } else - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Invalid arguments"); - - if (reply != NULL) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Invalid arguments"); + return TRUE; } -static void -lookup_mount_by_fuse_path (DBusConnection *connection, - DBusMessage *message) +static gboolean +handle_lookup_mount_by_fuse_path (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + const gchar *arg_fuse_path, + gpointer user_data) { VfsMount *mount; - DBusMessage *reply; - DBusMessageIter iter; - char *fuse_path; - dbus_message_iter_init (message, &iter); + g_print ("called lookup_mount_by_fuse_path()\n"); - reply = NULL; - if (_g_dbus_message_iter_get_args (&iter, NULL, - G_DBUS_TYPE_CSTRING, &fuse_path, - 0)) - { - mount = find_vfs_mount_by_fuse_path (fuse_path); + mount = find_vfs_mount_by_fuse_path (arg_fuse_path); - if (mount == NULL) - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, - G_IO_ERROR_NOT_MOUNTED, - _("The specified location is not mounted")); - else - { - reply = dbus_message_new_method_return (message); - if (reply) - { - dbus_message_iter_init_append (reply, &iter); - vfs_mount_to_dbus (mount, &iter); - } - } - } + if (mount == NULL) + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_NOT_MOUNTED, + _("The specified location is not mounted")); else - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Invalid arguments"); - - if (reply != NULL) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } + gvfs_dbus_mount_tracker_complete_lookup_mount_by_fuse_path (object, + invocation, + vfs_mount_to_dbus (mount)); + + return TRUE; } -static void -list_mounts (DBusConnection *connection, - DBusMessage *message) +static gboolean +handle_list_mounts (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + gpointer user_data) { - VfsMount *mount; - DBusMessage *reply; - DBusMessageIter iter, array_iter; GList *l; + GVariantBuilder mounts_array; - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); - - dbus_message_iter_init_append (reply, &iter); - - - if (!dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_OBJECT_PATH_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_BOOLEAN_AS_STRING - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING - G_MOUNT_SPEC_TYPE_AS_STRING - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING - DBUS_STRUCT_END_CHAR_AS_STRING, - &array_iter)) - _g_dbus_oom (); + g_print ("called list_mounts()\n"); + g_variant_builder_init (&mounts_array, G_VARIANT_TYPE (VFS_MOUNT_ARRAY_DBUS_STRUCT_TYPE)); for (l = mounts; l != NULL; l = l->next) - { - mount = l->data; - - vfs_mount_to_dbus (mount, &array_iter); - } - - if (!dbus_message_iter_close_container (&iter, &array_iter)) - _g_dbus_oom (); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); + g_variant_builder_add_value (&mounts_array, vfs_mount_to_dbus (l->data)); + + gvfs_dbus_mount_tracker_complete_list_mounts (object, invocation, + g_variant_builder_end (&mounts_array)); + + return TRUE; } static void @@ -980,263 +870,133 @@ mount_location_done (VfsMountable *mountable, GError *error, gpointer user_data) { - DBusMessage *message, *reply; - DBusConnection *conn; - - message = user_data; + GDBusMethodInvocation *invocation = user_data; if (error) - reply = _dbus_message_new_from_gerror (message, error); + g_dbus_method_invocation_return_gerror (invocation, error); else - reply = dbus_message_new_method_return (message); - - dbus_message_unref (message); + /* alas gvfs_dbus_mount_tracker_complete_mount_location() */ + g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); - if (reply == NULL) - _g_dbus_oom (); - - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - if (conn) - { - dbus_connection_send (conn, reply, NULL); - dbus_connection_unref (conn); - } - - dbus_message_unref (reply); + g_object_unref (invocation); } -static void -mount_location (DBusConnection *connection, - DBusMessage *message) +static gboolean +handle_mount_location (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + GVariant *arg_mount_spec, + GVariant *arg_mount_source, + gpointer user_data) { - DBusMessageIter iter; - DBusMessage *reply; - DBusError derror; GMountSpec *spec; - const char *obj_path, *dbus_id; VfsMountable *mountable; - - dbus_message_iter_init (message, &iter); - mountable = NULL; - spec = NULL; - reply = NULL; + g_print ("called mount_location()\n"); - spec = g_mount_spec_from_dbus (&iter); + spec = g_mount_spec_from_dbus (arg_mount_spec); if (spec == NULL) - reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "Invalid arguments"); + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Invalid arguments"); else { - dbus_error_init (&derror); - if (!_g_dbus_message_iter_get_args (&iter, - &derror, - DBUS_TYPE_STRING, &dbus_id, - DBUS_TYPE_OBJECT_PATH, &obj_path, - 0)) - { - reply = dbus_message_new_error (message, derror.name, derror.message); - dbus_error_free (&derror); - } + VfsMount *mount; + mount = match_vfs_mount (spec); + + if (mount != NULL) + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_ALREADY_MOUNTED, + _("Location is already mounted")); else - { - VfsMount *mount; - mount = match_vfs_mount (spec); - - if (mount != NULL) - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED, - _("Location is already mounted")); - else - { - mountable = lookup_mountable (spec); - - if (mountable == NULL) - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED, - _("Location is not mountable")); - } - } + { + mountable = lookup_mountable (spec); + + if (mountable == NULL) + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_NOT_MOUNTED, + _("Location is not mountable")); + else + { + GMountSource *source; + + source = g_mount_source_from_dbus (arg_mount_source); + mountable_mount (mountable, + spec, + source, + FALSE, + mount_location_done, g_object_ref (invocation)); + g_object_unref (source); + } + } } - if (reply) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } - else - { - GMountSource *source; - - source = g_mount_source_new (dbus_id, obj_path); - mountable_mount (mountable, - spec, - source, - FALSE, - mount_location_done, dbus_message_ref (message)); - g_object_unref (source); - } - if (spec) g_mount_spec_unref (spec); - + + return TRUE; } -static void -list_mount_types (DBusConnection *connection, - DBusMessage *message) +static gboolean +handle_list_mount_types (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + gpointer user_data) { VfsMountable *mountable; - DBusMessage *reply; - DBusMessageIter iter, array_iter; + GPtrArray *types; GList *l; - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); - - dbus_message_iter_init_append (reply, &iter); - - - if (!dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, - &array_iter)) - _g_dbus_oom (); + g_print ("called list_mount_types()\n"); + types = g_ptr_array_new (); for (l = mountables; l != NULL; l = l->next) { mountable = l->data; - if (!dbus_message_iter_append_basic (&array_iter, - DBUS_TYPE_STRING, - &mountable->type)) - _g_dbus_oom (); + g_ptr_array_add (types, (gpointer) mountable->type); } + g_ptr_array_add (types, NULL); - if (!dbus_message_iter_close_container (&iter, &array_iter)) - _g_dbus_oom (); + gvfs_dbus_mount_tracker_complete_list_mount_types (object, invocation, + (const gchar *const *) types->pdata); - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); + g_ptr_array_free (types, TRUE); + return TRUE; } -static void -list_mountable_info (DBusConnection *connection, - DBusMessage *message) +static gboolean +handle_list_mountable_info (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + gpointer user_data) { - VfsMountable *mountable; - DBusMessage *reply; - DBusMessageIter iter, array_iter; GList *l; - - reply = dbus_message_new_method_return (message); - if (reply == NULL) - _g_dbus_oom (); - - dbus_message_iter_init_append (reply, &iter); - + GVariantBuilder mountables_array; - if (!dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING /* type */ - DBUS_TYPE_STRING_AS_STRING /* scheme */ - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING /* scheme aliases */ - DBUS_TYPE_INT32_AS_STRING /* default port */ - DBUS_TYPE_BOOLEAN_AS_STRING /* host is inet */ - DBUS_STRUCT_END_CHAR_AS_STRING, - &array_iter)) - _g_dbus_oom (); - - for (l = mountables; l != NULL; l = l->next) - { - mountable = l->data; - - vfs_mountable_to_dbus (mountable, &array_iter); - } - - if (!dbus_message_iter_close_container (&iter, &array_iter)) - _g_dbus_oom (); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); -} - -static DBusHandlerResult -dbus_message_function (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - DBusHandlerResult res; + g_print ("called list_mountable_info()\n"); - res = DBUS_HANDLER_RESULT_HANDLED; - if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE)) - fuse_available = TRUE; - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT)) - register_mount (connection, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT)) - lookup_mount (connection, message, TRUE); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH)) - lookup_mount_by_fuse_path (connection, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS)) - list_mounts (connection, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION)) - mount_location (connection, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNT_TYPES)) - list_mount_types (connection, message); - else if (dbus_message_is_method_call (message, - G_VFS_DBUS_MOUNTTRACKER_INTERFACE, - G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO)) - list_mountable_info (connection, message); - else - res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + g_variant_builder_init (&mountables_array, G_VARIANT_TYPE (VFS_MOUNTABLE_ARRAY_DBUS_STRUCT_TYPE)); + for (l = mountables; l != NULL; l = l->next) { + g_variant_builder_add_value (&mountables_array, vfs_mountable_to_dbus (l->data)); + } - return res; + gvfs_dbus_mount_tracker_complete_list_mountable_info (object, invocation, + g_variant_builder_end (&mountables_array)); + + return TRUE; } -static struct DBusObjectPathVTable tracker_dbus_vtable = { - NULL, - dbus_message_function -}; - - -static DBusHandlerResult -mount_tracker_filter_func (DBusConnection *conn, - DBusMessage *message, - gpointer data) +static gboolean +handle_register_fuse (GVfsDBusMountTracker *object, + GDBusMethodInvocation *invocation, + gpointer user_data) { - const char *name, *from, *to; - - if (dbus_message_is_signal (message, - DBUS_INTERFACE_DBUS, - "NameOwnerChanged")) - { - if (dbus_message_get_args (message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &from, - DBUS_TYPE_STRING, &to, - DBUS_TYPE_INVALID)) - { - if (*name == ':' && *to == 0) - dbus_client_disconnected (name); - } - - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + g_print ("called register_fuse()\n"); + + fuse_available = TRUE; + gvfs_dbus_mount_tracker_complete_register_fuse (object, invocation); + + return TRUE; } @@ -1267,10 +1027,11 @@ reload_pipes_cb (GIOChannel *io, void mount_init (void) { - DBusConnection *conn; - DBusError error; + GDBusConnection *conn; struct sigaction sa; GIOChannel *io; + GVfsDBusMountTracker *mount_tracker; + GError *error; read_mountable_config (); @@ -1285,27 +1046,39 @@ mount_init (void) sigaction (SIGUSR1, &sa, NULL); } - conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); - - if (!dbus_connection_register_object_path (conn, G_VFS_DBUS_MOUNTTRACKER_PATH, - &tracker_dbus_vtable, NULL)) - _g_dbus_oom (); - - if (!dbus_connection_add_filter (conn, - mount_tracker_filter_func, NULL, NULL)) - _g_dbus_oom (); + error = NULL; + conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (! conn) + { + g_warning ("Error connecting to session bus: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + return; /* FIXME: gracefully return */ + } + + mount_tracker = gvfs_dbus_mount_tracker_skeleton_new (); + + g_signal_connect (mount_tracker, "handle-register-fuse", G_CALLBACK (handle_register_fuse), NULL); + g_signal_connect (mount_tracker, "handle-register-mount", G_CALLBACK (handle_register_mount), NULL); + g_signal_connect (mount_tracker, "handle-mount-location", G_CALLBACK (handle_mount_location), NULL); + g_signal_connect (mount_tracker, "handle-lookup-mount", G_CALLBACK (handle_lookup_mount), NULL); + g_signal_connect (mount_tracker, "handle-lookup-mount-by-fuse-path", G_CALLBACK (handle_lookup_mount_by_fuse_path), NULL); + g_signal_connect (mount_tracker, "handle-list-mounts", G_CALLBACK (handle_list_mounts), NULL); + g_signal_connect (mount_tracker, "handle-list-mountable-info", G_CALLBACK (handle_list_mountable_info), NULL); + g_signal_connect (mount_tracker, "handle-list-mount-types", G_CALLBACK (handle_list_mount_types), NULL); - dbus_error_init (&error); - dbus_bus_add_match (conn, - "sender='org.freedesktop.DBus'," - "interface='org.freedesktop.DBus'," - "member='NameOwnerChanged'", - &error); - if (dbus_error_is_set (&error)) + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (mount_tracker), conn, + G_VFS_DBUS_MOUNTTRACKER_PATH, &error)) { - g_warning ("Failed to add dbus match: %s\n", error.message); - dbus_error_free (&error); + g_warning ("Error exporting mount tracker: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + g_object_unref (mount_tracker); } + g_object_unref (conn); + + /* TODO: keep reference for 'mount_tracker' */ } |