--- trunk/common/gvfsdaemonprotocol.h 2008/09/01 21:22:15 1922 +++ trunk/common/gvfsdaemonprotocol.h 2008/09/26 10:44:37 2031 @@ -12,6 +12,7 @@ #define G_VFS_DBUS_MOUNTTRACKER_INTERFACE "org.gtk.vfs.MountTracker" #define G_VFS_DBUS_MOUNTTRACKER_PATH "/org/gtk/vfs/mounttracker" #define G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT "lookupMount" +#define G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH "lookupMountByFusePath" #define G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION "mountLocation" #define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS "listMounts" #define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT "registerMount" --- trunk/client/gdaemonvfs.h 2008/01/31 16:54:22 1214 +++ trunk/client/gdaemonvfs.h 2008/09/26 10:44:37 2031 @@ -60,6 +60,8 @@ GMountInfo * _g_daemon_vfs_get_mount_info_sync (GMountSpec *spec, const char *path, GError **error); +GMountInfo * _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path, + char **mount_path); GMountSpec * _g_daemon_vfs_get_mount_spec_for_path (GMountSpec *spec, const char *path, const char *new_path); --- trunk/client/gdaemonvfs.c 2008/09/23 19:16:06 2021 +++ trunk/client/gdaemonvfs.c 2008/09/26 10:44:37 2031 @@ -55,6 +55,8 @@ GVfs *wrapped_vfs; GList *mount_cache; + GFile *fuse_root; + GHashTable *from_uri_hash; GHashTable *to_uri_hash; @@ -287,6 +289,7 @@ const char * const *schemes, * const *mount_types; GVfsUriMapper *mapper; GList *modules; + char *file; int i; bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR); @@ -319,6 +322,10 @@ vfs->wrapped_vfs = g_vfs_get_local (); + file = g_build_filename (g_get_home_dir(), ".gvfs", NULL); + 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); @@ -357,13 +364,42 @@ return g_object_new (G_TYPE_DAEMON_VFS, NULL); } +/* This unrefs file if its changed */ +static GFile * +convert_fuse_path (GVfs *vfs, + GFile *file) +{ + GFile *fuse_root; + char *fuse_path, *mount_path; + GMountInfo *mount_info; + + fuse_root = ((GDaemonVfs *)vfs)->fuse_root; + if (g_file_has_prefix (file, fuse_root)) + { + fuse_path = g_file_get_path (file); + mount_info = _g_daemon_vfs_get_mount_info_by_fuse_sync (fuse_path, &mount_path); + g_free (fuse_path); + if (mount_info) + { + g_object_unref (file); + /* TODO: Do we need to look at the prefix of the mount_spec? */ + file = g_daemon_file_new (mount_info->mount_spec, mount_path); + g_free (mount_path); + g_mount_info_unref (mount_info); + } + } + return file; +} + static GFile * g_daemon_vfs_get_file_for_path (GVfs *vfs, const char *path) { - /* TODO: detect fuse paths and convert to daemon vfs GFiles */ + GFile *file; - return g_vfs_get_file_for_path (G_DAEMON_VFS (vfs)->wrapped_vfs, path); + file = g_vfs_get_file_for_path (G_DAEMON_VFS (vfs)->wrapped_vfs, path); + file = convert_fuse_path (vfs, file); + return file; } static GFile * @@ -711,6 +747,41 @@ return info; } +static GMountInfo * +lookup_mount_info_by_fuse_path_in_cache (const char *fuse_path, + char **mount_path) +{ + GMountInfo *info; + GList *l; + + G_LOCK (mount_cache); + info = NULL; + for (l = the_vfs->mount_cache; l != NULL; l = l->next) + { + GMountInfo *mount_info = l->data; + + if (mount_info->fuse_mountpoint != NULL && + g_str_has_prefix (fuse_path, mount_info->fuse_mountpoint)) + { + int len = strlen (mount_info->fuse_mountpoint); + if (fuse_path[len] == 0 || + fuse_path[len] == '/') + { + if (fuse_path[len] == 0) + *mount_path = g_strdup ("/"); + else + *mount_path = g_strdup (fuse_path + len); + info = g_mount_info_ref (mount_info); + break; + } + } + } + G_UNLOCK (mount_cache); + + return info; +} + + void _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id) { @@ -908,6 +979,71 @@ return info; } +GMountInfo * +_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; + + 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); + + 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) + { + dbus_error_free (&derror); + return NULL; + } + + info = handler_lookup_mount_reply (reply, NULL); + dbus_message_unref (reply); + + if (info) + { + if (info->fuse_mountpoint) + { + len = strlen (info->fuse_mountpoint); + if (fuse_path[len] == 0) + *mount_path = g_strdup ("/"); + else + *mount_path = g_strdup (fuse_path + len); + } + else + { + /* This could happen if we race with the gvfs fuse mount + * at startup of gvfsd... */ + g_mount_info_unref (info); + info = NULL; + } + } + + + return info; +} + static GFile * g_daemon_vfs_parse_name (GVfs *vfs, const char *parse_name) @@ -917,8 +1053,8 @@ if (g_path_is_absolute (parse_name) || *parse_name == '~') { - /* TODO: detect fuse paths and convert to daemon vfs GFiles ? */ file = g_vfs_parse_name (G_DAEMON_VFS (vfs)->wrapped_vfs, parse_name); + file = convert_fuse_path (vfs, file); } else { --- trunk/daemon/mount.c 2008/08/02 11:00:07 1847 +++ trunk/daemon/mount.c 2008/09/26 10:44:37 2031 @@ -43,7 +43,8 @@ char *icon; char *prefered_filename_encoding; gboolean user_visible; - + char *fuse_mountpoint; /* Always set, even if fuse not availible */ + /* Daemon object ref */ char *dbus_id; char *object_path; @@ -100,6 +101,32 @@ } static VfsMount * +find_vfs_mount_by_fuse_path (const char *fuse_path) +{ + GList *l; + + if (!fuse_available) + return NULL; + + for (l = mounts; l != NULL; l = l->next) + { + VfsMount *mount = l->data; + + if (mount->fuse_mountpoint != NULL && + g_str_has_prefix (fuse_path, mount->fuse_mountpoint)) + { + int len = strlen (mount->fuse_mountpoint); + if (fuse_path[len] == 0 || + fuse_path[len] == '/') + return mount; + } + } + + return NULL; +} + + +static VfsMount * match_vfs_mount (GMountSpec *match) { GList *l; @@ -160,6 +187,7 @@ g_free (mount->stable_name); g_free (mount->x_content_types); g_free (mount->icon); + g_free (mount->fuse_mountpoint); g_free (mount->prefered_filename_encoding); g_free (mount->dbus_id); g_free (mount->object_path); @@ -223,21 +251,10 @@ &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 (""); + 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); @@ -699,6 +716,16 @@ mount->dbus_id = g_strdup (id); mount->object_path = g_strdup (obj_path); mount->mount_spec = mount_spec; + + if (user_visible) + { + char *fs_name; + + /* Keep in sync with fuse daemon */ + fs_name = g_uri_escape_string (mount->stable_name, "+@#$., ", TRUE); + + mount->fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL); + } mounts = g_list_prepend (mounts, mount); @@ -835,6 +862,48 @@ } static void +lookup_mount_by_fuse_path (DBusConnection *connection, + DBusMessage *message) +{ + VfsMount *mount; + DBusMessage *reply; + DBusMessageIter iter; + char *fuse_path; + + dbus_message_iter_init (message, &iter); + + 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); + + 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); + } + } + } + else + reply = dbus_message_new_error (message, + DBUS_ERROR_INVALID_ARGS, + "Invalid arguments"); + + if (reply != NULL) + dbus_connection_send (connection, reply, NULL); +} + +static void list_mounts (DBusConnection *connection, DBusMessage *message) { @@ -1084,6 +1153,10 @@ 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,