Blob Blame History Raw
--- 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,