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 /daemon/gvfsdaemon.c | |
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
Diffstat (limited to 'daemon/gvfsdaemon.c')
-rw-r--r-- | daemon/gvfsdaemon.c | 719 |
1 files changed, 377 insertions, 342 deletions
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); } |