From c5fea7243bf44b4ec202e5da04d3dbd4749cd3b3 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Wed, 1 Oct 2008 18:18:09 +0000 Subject: [PATCH] - Add patch for reverse mapping FUSE paths (bgo #530654) --- gvfs-1.1.1-reverse-map-fuse-paths.patch | 375 ++++++++++++++++++++++++ gvfs.spec | 9 +- 2 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 gvfs-1.1.1-reverse-map-fuse-paths.patch diff --git a/gvfs-1.1.1-reverse-map-fuse-paths.patch b/gvfs-1.1.1-reverse-map-fuse-paths.patch new file mode 100644 index 0000000..24f04c2 --- /dev/null +++ b/gvfs-1.1.1-reverse-map-fuse-paths.patch @@ -0,0 +1,375 @@ +--- 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, diff --git a/gvfs.spec b/gvfs.spec index d6e967c..9ffe21d 100644 --- a/gvfs.spec +++ b/gvfs.spec @@ -1,7 +1,7 @@ Summary: Backends for the gio framework in GLib Name: gvfs Version: 1.0.1 -Release: 3%{?dist} +Release: 4%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: http://www.gtk.org @@ -35,6 +35,9 @@ Patch2: gvfs-obexftp-updated-apis-3.patch # From upstream svn Patch3: fix-mounting.patch +# http://bugzilla.gnome.org/show_bug.cgi?id=530654 +Patch4: gvfs-1.1.1-reverse-map-fuse-paths.patch + %description The gvfs package provides backend implementations for the gio framework in GLib. It includes ftp, sftp, cifs. @@ -118,6 +121,7 @@ media players (Media Transfer Protocol) to applications using gvfs. %patch1 -p0 -b .archive-integration %patch2 -p0 -b .bluez-ods %patch3 -p1 -b .fix-mounting +%patch4 -p1 -b .reverse-map-fuse-paths.patch %build @@ -255,6 +259,9 @@ update-desktop-database &> /dev/null ||: %changelog +* Wed Oct 1 2008 David Zeuthen - 1.0.1-4 +- Add patch for reverse mapping FUSE paths (bgo #530654) + * Mon Sep 29 2008 Matthias Clasen - 1.0.1-3 - Fix mounting