diff options
Diffstat (limited to 'daemon/mount.c')
-rw-r--r-- | daemon/mount.c | 1207 |
1 files changed, 0 insertions, 1207 deletions
diff --git a/daemon/mount.c b/daemon/mount.c deleted file mode 100644 index 75ef6be6..00000000 --- a/daemon/mount.c +++ /dev/null @@ -1,1207 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 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: Alexander Larsson <alexl@redhat.com> - */ - -#include <config.h> - -#include <string.h> -#include <unistd.h> -#include <signal.h> - -#include <glib.h> -#include <dbus/dbus.h> -#include <glib/gi18n.h> -#include "mount.h" -#include "gmountoperationdbus.h" -#include "gvfsdaemonprotocol.h" -#include "gdbusutils.h" -#include <glib/gurifuncs.h> -#include <gio/gio.h> - -typedef struct { - char *display_name; - char *stable_name; - char *x_content_types; - char *icon; - char *prefered_filename_encoding; - gboolean user_visible; - - /* Daemon object ref */ - char *dbus_id; - char *object_path; - - /* Mount details */ - GMountSpec *mount_spec; -} VfsMount; - -typedef struct { - char *type; - char *exec; - char *dbus_name; - gboolean automount; - char *scheme; - char **scheme_aliases; - int default_port; - gboolean hostname_is_inet; -} VfsMountable; - -typedef void (*MountCallback) (VfsMountable *mountable, - GError *error, - gpointer user_data); - -static GList *mountables = NULL; -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 VfsMount * -find_vfs_mount (const char *dbus_id, - const char *obj_path) -{ - GList *l; - for (l = mounts; l != NULL; l = l->next) - { - VfsMount *mount = l->data; - - if (strcmp (mount->dbus_id, dbus_id) == 0 && - strcmp (mount->object_path, obj_path) == 0) - return mount; - } - - return NULL; -} - -static VfsMount * -match_vfs_mount (GMountSpec *match) -{ - GList *l; - for (l = mounts; l != NULL; l = l->next) - { - VfsMount *mount = l->data; - - if (g_mount_spec_match (mount->mount_spec, match)) - return mount; - } - - return NULL; -} - -static VfsMountable * -find_mountable (const char *type) -{ - GList *l; - - for (l = mountables; l != NULL; l = l->next) - { - VfsMountable *mountable = l->data; - - if (strcmp (mountable->type, type) == 0) - return mountable; - } - - return NULL; -} - -static VfsMountable * -lookup_mountable (GMountSpec *spec) -{ - const char *type; - - type = g_mount_spec_get_type (spec); - if (type == NULL) - return NULL; - - return find_mountable (type); -} - -static void -vfs_mountable_free (VfsMountable *mountable) -{ - g_free (mountable->type); - g_free (mountable->exec); - g_free (mountable->dbus_name); - g_free (mountable->scheme); - g_strfreev (mountable->scheme_aliases); - g_free (mountable); -} - -static void -vfs_mount_free (VfsMount *mount) -{ - g_free (mount->display_name); - g_free (mount->stable_name); - g_free (mount->x_content_types); - g_free (mount->icon); - g_free (mount->prefered_filename_encoding); - 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) -{ - 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 = NULL; - if (fuse_available && mount->user_visible) - { - char *fs_name; - - /* Keep in sync with fuse daemon */ - fs_name = g_uri_escape_string (mount->stable_name, "+@#$., ", TRUE); - - fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL); - } - - if (fuse_mountpoint == NULL) - fuse_mountpoint = g_strdup (""); - - _g_dbus_message_iter_append_cstring (&struct_iter, fuse_mountpoint); - - g_mount_spec_to_dbus (&struct_iter, mount->mount_spec); - - if (!dbus_message_iter_close_container (iter, &struct_iter)) - _g_dbus_oom (); -} - -static void -vfs_mountable_to_dbus (VfsMountable *mountable, - DBusMessageIter *iter) -{ - 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 (); -} - - -/************************************************************************ - * Support for mounting a VfsMountable * - ************************************************************************/ - - -typedef struct { - VfsMountable *mountable; - dbus_bool_t automount; - GMountSource *source; - GMountSpec *mount_spec; - MountCallback callback; - gpointer user_data; - char *obj_path; - gboolean spawned; -} MountData; - -static void spawn_mount (MountData *data); - -static void -mount_data_free (MountData *data) -{ - g_object_unref (data->source); - g_mount_spec_unref (data->mount_spec); - g_free (data->obj_path); - - g_free (data); -} - -static void -mount_finish (MountData *data, GError *error) -{ - data->callback (data->mountable, error, data->user_data); - mount_data_free (data); -} - -static void -dbus_mount_reply (DBusPendingCall *pending, - void *_data) -{ - DBusMessage *reply; - GError *error; - MountData *data = _data; - - reply = dbus_pending_call_steal_reply (pending); - dbus_pending_call_unref (pending); - - 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); - else - { - error = NULL; - if (_g_error_from_message (reply, &error)) - { - mount_finish (data, error); - g_error_free (error); - } - else - mount_finish (data, NULL); - } - - dbus_message_unref (reply); -} - -static void -mountable_mount_with_name (MountData *data, - const char *dbus_name) -{ - DBusConnection *conn; - DBusMessage *message; - DBusPendingCall *pending; - 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); - - if (pending == NULL) - { - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "Connection is closed"); - mount_finish (data, error); - g_error_free (error); - return; - } - - if (!dbus_pending_call_set_notify (pending, - dbus_mount_reply, - data, NULL)) - _g_dbus_oom (); -} - -static DBusHandlerResult -spawn_mount_message_function (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - MountData *data = user_data; - GError *error = NULL; - dbus_bool_t succeeded; - char *error_message; - - if (dbus_message_is_method_call (message, - G_VFS_DBUS_SPAWNER_INTERFACE, - G_VFS_DBUS_OP_SPAWNED)) - { - 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; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static void -spawn_mount (MountData *data) -{ - char *exec; - GError *error; - DBusConnection *connection; - static int mount_id = 0; - DBusObjectPathVTable spawn_vtable = { - NULL, - spawn_mount_message_function - }; - - data->spawned = TRUE; - - error = NULL; - if (data->mountable->exec == NULL) - { - g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No exec key defined for mountpoint"); - mount_finish (data, error); - g_error_free (error); - } - else - { - 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 (); - - exec = g_strconcat (data->mountable->exec, " --spawner ", dbus_bus_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); - mount_finish (data, error); - g_error_free (error); - } - - /* TODO: Add a timeout here to detect spawned app crashing */ - - dbus_connection_unref (connection); - g_free (exec); - } -} - -static void -mountable_mount (VfsMountable *mountable, - GMountSpec *mount_spec, - GMountSource *source, - gboolean automount, - MountCallback callback, - gpointer user_data) -{ - MountData *data; - - data = g_new0 (MountData, 1); - data->automount = automount; - data->mountable = mountable; - data->source = g_object_ref (source); - data->mount_spec = g_mount_spec_ref (mount_spec); - data->callback = callback; - data->user_data = user_data; - - if (mountable->dbus_name == NULL) - spawn_mount (data); - else - mountable_mount_with_name (data, mountable->dbus_name); -} - -static void -read_mountable_config (void) -{ - GDir *dir; - char *mount_dir, *path; - const char *filename; - GKeyFile *keyfile; - char **types; - VfsMountable *mountable; - int i; - - mount_dir = MOUNTABLE_DIR; - dir = g_dir_open (mount_dir, 0, NULL); - - if (dir) - { - while ((filename = g_dir_read_name (dir)) != NULL) - { - path = g_build_filename (mount_dir, filename, NULL); - - keyfile = g_key_file_new (); - if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL)) - { - types = g_key_file_get_string_list (keyfile, "Mount", "Type", NULL, NULL); - if (types != NULL) - { - for (i = 0; types[i] != NULL; i++) - { - if (*types[i] != 0) - { - mountable = g_new0 (VfsMountable, 1); - mountable->type = g_strdup (types[i]); - mountable->exec = g_key_file_get_string (keyfile, "Mount", "Exec", NULL); - mountable->dbus_name = g_key_file_get_string (keyfile, "Mount", "DBusName", NULL); - mountable->automount = g_key_file_get_boolean (keyfile, "Mount", "AutoMount", NULL); - mountable->scheme = g_key_file_get_string (keyfile, "Mount", "Scheme", NULL); - mountable->scheme_aliases = - g_key_file_get_string_list (keyfile, "Mount", "SchemeAliases", NULL, NULL); - mountable->default_port = g_key_file_get_integer (keyfile, "Mount", "DefaultPort", NULL); - mountable->hostname_is_inet = g_key_file_get_boolean (keyfile, "Mount", "HostnameIsInetAddress", NULL); - - if (mountable->scheme == NULL) - mountable->scheme = g_strdup (mountable->type); - - mountables = g_list_prepend (mountables, mountable); - } - } - g_strfreev (types); - } - } - g_key_file_free (keyfile); - g_free (path); - } - g_dir_close (dir); - } -} - -static void -re_read_mountable_config (void) -{ - g_list_foreach (mountables, (GFunc)vfs_mountable_free, NULL); - g_list_free (mountables); - mountables = NULL; - - read_mountable_config (); -} - -/************************************************************************ - * Support for keeping track of active mounts * - ************************************************************************/ - -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); - - dbus_message_unref (message); -} - -static void -dbus_client_disconnected (const char *dbus_id) -{ - GList *l, *next; - - next = NULL; - for (l = mounts; l != NULL; l = next) - { - VfsMount *mount = l->data; - next = l->next; - - if (strcmp (mount->dbus_id, dbus_id) == 0) - { - signal_mounted_unmounted (mount, FALSE); - - vfs_mount_free (mount); - mounts = g_list_delete_link (mounts, l); - } - } -} - -static void -register_mount (DBusConnection *connection, - DBusMessage *message) -{ - VfsMount *mount; - DBusMessage *reply; - DBusError error; - const char *display_name, *stable_name, *x_content_types, *icon, *obj_path, *id, *prefered_filename_encoding; - dbus_bool_t user_visible; - DBusMessageIter iter; - 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)) - { - 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"); - 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; - - mounts = g_list_prepend (mounts, mount); - - signal_mounted_unmounted (mount, TRUE); - - reply = dbus_message_new_method_return (message); - } - } - else - { - reply = dbus_message_new_error (message, - error.name, error.message); - dbus_error_free (&error); - } - - if (reply == NULL) - _g_dbus_oom (); - - dbus_connection_send (connection, reply, NULL); -} - -typedef struct { - DBusMessage *message; - DBusConnection *connection; -} AutoMountData; - -static void -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); - } - else - lookup_mount (data->connection, - data->message, - FALSE); - - dbus_connection_unref (data->connection); - dbus_message_unref (data->message); - g_free (data); -} - -static DBusMessage * -maybe_automount (GMountSpec *spec, - DBusMessage *message, - DBusConnection *connection, - gboolean do_automount) -{ - VfsMountable *mountable; - DBusMessage *reply; - - mountable = lookup_mountable (spec); - - reply = NULL; - if (mountable != NULL && do_automount && mountable->automount) - { - AutoMountData *data; - GMountSource *mount_source; - - g_print ("automounting...\n"); - - mount_source = g_mount_source_new_dummy (); - - data = g_new0 (AutoMountData, 1); - data->message = dbus_message_ref (message); - data->connection = dbus_connection_ref (connection); - - 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")); - else - reply = _dbus_message_new_gerror (message, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - _("The specified location is not supported")); - - return reply; -} - -static void -lookup_mount (DBusConnection *connection, - DBusMessage *message, - gboolean do_automount) -{ - VfsMount *mount; - DBusMessage *reply; - DBusMessageIter iter; - GMountSpec *spec; - - dbus_message_iter_init (message, &iter); - spec = g_mount_spec_from_dbus (&iter); - - reply = NULL; - if (spec != NULL) - { - mount = match_vfs_mount (spec); - - if (mount == NULL) - reply = maybe_automount (spec, message, connection, do_automount); - else - { - reply = dbus_message_new_method_return (message); - - if (reply) - { - dbus_message_iter_init_append (reply, &iter); - - vfs_mount_to_dbus (mount, &iter); - } - } - } - else - reply = dbus_message_new_error (message, - DBUS_ERROR_INVALID_ARGS, - "Invalid arguments"); - - g_mount_spec_unref (spec); - if (reply != NULL) - dbus_connection_send (connection, reply, NULL); -} - -static void -list_mounts (DBusConnection *connection, - DBusMessage *message) -{ - VfsMount *mount; - 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); - - - 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_STRUCT_END_CHAR_AS_STRING, - &array_iter)) - _g_dbus_oom (); - - 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); -} - -static void -mount_location_done (VfsMountable *mountable, - GError *error, - gpointer user_data) -{ - DBusMessage *message, *reply; - DBusConnection *conn; - - message = user_data; - - if (error) - reply = _dbus_message_new_from_gerror (message, error); - else - reply = dbus_message_new_method_return (message); - - dbus_message_unref (message); - - 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); -} - -static void -mount_location (DBusConnection *connection, - DBusMessage *message) -{ - 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; - - spec = g_mount_spec_from_dbus (&iter); - if (spec == NULL) - reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, - "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); - } - 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")); - } - } - } - - if (reply) - dbus_connection_send (connection, reply, NULL); - 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); - -} - -static void -list_mount_types (DBusConnection *connection, - DBusMessage *message) -{ - 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); - - - if (!dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, - &array_iter)) - _g_dbus_oom (); - - 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 (); - } - - if (!dbus_message_iter_close_container (&iter, &array_iter)) - _g_dbus_oom (); - - dbus_connection_send (connection, reply, NULL); -} - -static void -list_mountable_info (DBusConnection *connection, - DBusMessage *message) -{ - 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); - - - 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); -} - -static DBusHandlerResult -dbus_message_function (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - DBusHandlerResult res; - - 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_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; - - return res; -} - -struct DBusObjectPathVTable tracker_dbus_vtable = { - NULL, - dbus_message_function -}; - - -static DBusHandlerResult -mount_tracker_filter_func (DBusConnection *conn, - DBusMessage *message, - gpointer 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; -} - - -static int reload_pipes[2]; - -static void -sigusr1_handler (int sig) -{ - while (write (reload_pipes[1], "a", 1) != 1) - ; -} - -static gboolean -reload_pipes_cb (GIOChannel *io, - GIOCondition condition, - gpointer data) -{ - char a; - - while (read (reload_pipes[0], &a, 1) != 1) - ; - - re_read_mountable_config (); - - return TRUE; -} - -void -mount_init (void) -{ - DBusConnection *conn; - DBusError error; - struct sigaction sa; - GIOChannel *io; - - read_mountable_config (); - - if (pipe (reload_pipes) != -1) - { - io = g_io_channel_unix_new (reload_pipes[0]); - g_io_add_watch (io, G_IO_IN, reload_pipes_cb, NULL); - - sa.sa_handler = sigusr1_handler; - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - 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 (); - - - 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)) - { - g_warning ("Failed to add dbus match: %s\n", error.message); - dbus_error_free (&error); - } -} - |