[glib] localfile: add support for monitoring on NFS



commit 6be54e9f56e9344ecd55a8952dff957573a136b7
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Jan 18 18:44:11 2013 -0500

    localfile: add support for monitoring on NFS
    
    Add a pair of new extension points: 'gio-nfs-file-monitor' and
    'gio-nfs-directory-monitor'.
    
    Add a check to GLocalFile when creating a file monitor.  If the
    requested file is in the user's home directory and the user has an NFS
    home directory then attempt to use an implementation of one of the new
    extension points.  If we don't have any implementations then fall back
    to the normal "local" monitors.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=592211

 gio/giomodule.c              |    6 +++
 gio/glocaldirectorymonitor.c |   15 ++++++--
 gio/glocaldirectorymonitor.h |    2 +
 gio/glocalfile.c             |   73 ++++++++++++++++++++++++++++++++++++++++-
 gio/glocalfilemonitor.c      |   19 +++++++---
 gio/glocalfilemonitor.h      |    2 +
 6 files changed, 105 insertions(+), 12 deletions(-)
---
diff --git a/gio/giomodule.c b/gio/giomodule.c
index 1a010ba..a394c60 100644
--- a/gio/giomodule.c
+++ b/gio/giomodule.c
@@ -968,6 +968,12 @@ _g_io_modules_ensure_extension_points_registered (void)
       ep = g_io_extension_point_register (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME);
       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
       
+      ep = g_io_extension_point_register (G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
+
+      ep = g_io_extension_point_register (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
+
       ep = g_io_extension_point_register (G_VOLUME_MONITOR_EXTENSION_POINT_NAME);
       g_io_extension_point_set_required_type (ep, G_TYPE_VOLUME_MONITOR);
       
diff --git a/gio/glocaldirectorymonitor.c b/gio/glocaldirectorymonitor.c
index 319b87a..f175723 100644
--- a/gio/glocaldirectorymonitor.c
+++ b/gio/glocaldirectorymonitor.c
@@ -229,14 +229,21 @@ mounts_changed (GUnixMountMonitor *mount_monitor,
 GFileMonitor*
 _g_local_directory_monitor_new (const char         *dirname,
 				GFileMonitorFlags   flags,
+                                gboolean            is_remote_fs,
 				GError            **error)
 {
   GFileMonitor *monitor = NULL;
-  GType type;
+  GType type = G_TYPE_INVALID;
 
-  type = _g_io_module_get_default_type (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME,
-                                        "GIO_USE_FILE_MONITOR",
-                                        G_STRUCT_OFFSET (GLocalDirectoryMonitorClass, is_supported));
+  if (is_remote_fs)
+    type = _g_io_module_get_default_type (G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME,
+                                          "GIO_USE_FILE_MONITOR",
+                                          G_STRUCT_OFFSET (GLocalDirectoryMonitorClass, is_supported));
+
+  if (type == G_TYPE_INVALID)
+    type = _g_io_module_get_default_type (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME,
+                                          "GIO_USE_FILE_MONITOR",
+                                          G_STRUCT_OFFSET (GLocalDirectoryMonitorClass, is_supported));
 
   if (type != G_TYPE_INVALID)
     monitor = G_FILE_MONITOR (g_object_new (type, "dirname", dirname, "flags", flags, NULL));
diff --git a/gio/glocaldirectorymonitor.h b/gio/glocaldirectorymonitor.h
index 3baa843..a2bbc11 100644
--- a/gio/glocaldirectorymonitor.h
+++ b/gio/glocaldirectorymonitor.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 #define G_IS_LOCAL_DIRECTORY_MONITOR_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_DIRECTORY_MONITOR))
 
 #define G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME "gio-local-directory-monitor"
+#define G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME   "gio-nfs-directory-monitor"
 
 typedef struct _GLocalDirectoryMonitor      GLocalDirectoryMonitor;
 typedef struct _GLocalDirectoryMonitorClass GLocalDirectoryMonitorClass;
@@ -67,6 +68,7 @@ GType           g_local_directory_monitor_get_type (void) G_GNUC_CONST;
 
 GFileMonitor * _g_local_directory_monitor_new      (const char         *dirname,
                                                     GFileMonitorFlags   flags,
+                                                    gboolean            is_remote_fs,
                                                     GError            **error);
 
 G_END_DECLS
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index db4a48a..9617754 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -2405,6 +2405,75 @@ g_local_file_move (GFile                  *source,
   return TRUE;
 }
 
+static gboolean
+is_remote_fs (const gchar *filename)
+{
+  const char *fsname = NULL;
+
+#ifdef USE_STATFS
+  struct statfs statfs_buffer;
+  int statfs_result = 0;
+
+#if STATFS_ARGS == 2
+  statfs_result = statfs (filename, &statfs_buffer);
+#elif STATFS_ARGS == 4
+  statfs_result = statfs (filename, &statfs_buffer, sizeof (statfs_buffer), 0);
+#endif
+
+#elif defined(USE_STATVFS)
+  struct statvfs statfs_buffer;
+
+  statfs_result = statvfs (filename, &statfs_buffer);
+#else
+  return FALSE;
+#endif
+
+  if (statfs_result == -1)
+    return FALSE;
+
+#ifdef USE_STATFS
+#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
+  fsname = statfs_buffer.f_fstypename;
+#else
+  fsname = get_fs_type (statfs_buffer.f_type);
+#endif
+
+#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
+  fsname = statfs_buffer.f_basetype;
+#endif
+
+  if (fsname != NULL)
+    {
+      if (strcmp (fsname, "nfs") == 0)
+        return TRUE;
+      if (strcmp (fsname, "nfs4") == 0)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+is_remote (const gchar *filename)
+{
+  static gboolean remote_home;
+  static gsize initialized;
+  const gchar *home;
+
+  home = g_get_home_dir ();
+  if (path_has_prefix (filename, home))
+    {
+      if (g_once_init_enter (&initialized))
+        {
+          remote_home = is_remote_fs (home);
+          g_once_init_leave (&initialized, TRUE);
+        }
+      return remote_home;
+    }
+
+  return FALSE;
+}
+
 static GFileMonitor*
 g_local_file_monitor_dir (GFile             *file,
 			  GFileMonitorFlags  flags,
@@ -2412,7 +2481,7 @@ g_local_file_monitor_dir (GFile             *file,
 			  GError           **error)
 {
   GLocalFile* local_file = G_LOCAL_FILE(file);
-  return _g_local_directory_monitor_new (local_file->filename, flags, error);
+  return _g_local_directory_monitor_new (local_file->filename, flags, is_remote (local_file->filename), error);
 }
 
 static GFileMonitor*
@@ -2422,7 +2491,7 @@ g_local_file_monitor_file (GFile             *file,
 			   GError           **error)
 {
   GLocalFile* local_file = G_LOCAL_FILE(file);
-  return _g_local_file_monitor_new (local_file->filename, flags, error);
+  return _g_local_file_monitor_new (local_file->filename, flags, is_remote (local_file->filename), error);
 }
 
 static void
diff --git a/gio/glocalfilemonitor.c b/gio/glocalfilemonitor.c
index a8925c0..e33369d 100644
--- a/gio/glocalfilemonitor.c
+++ b/gio/glocalfilemonitor.c
@@ -152,15 +152,22 @@ static void g_local_file_monitor_class_init (GLocalFileMonitorClass *klass)
 
 GFileMonitor*
 _g_local_file_monitor_new (const char         *pathname,
-			   GFileMonitorFlags   flags,
-			   GError            **error)
+                           GFileMonitorFlags   flags,
+                           gboolean            is_remote_fs,
+                           GError            **error)
 {
   GFileMonitor *monitor = NULL;
-  GType type;
+  GType type = G_TYPE_INVALID;
 
-  type = _g_io_module_get_default_type (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
-                                        "GIO_USE_FILE_MONITOR",
-                                        G_STRUCT_OFFSET (GLocalFileMonitorClass, is_supported));
+  if (is_remote_fs)
+    type = _g_io_module_get_default_type (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
+                                          "GIO_USE_FILE_MONITOR",
+                                          G_STRUCT_OFFSET (GLocalFileMonitorClass, is_supported));
+
+  if (type == G_TYPE_INVALID)
+    type = _g_io_module_get_default_type (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
+                                          "GIO_USE_FILE_MONITOR",
+                                          G_STRUCT_OFFSET (GLocalFileMonitorClass, is_supported));
 
   if (type != G_TYPE_INVALID)
     monitor = G_FILE_MONITOR (g_object_new (type, "filename", pathname, "flags", flags, NULL));
diff --git a/gio/glocalfilemonitor.h b/gio/glocalfilemonitor.h
index 0c002f9..2c1b794 100644
--- a/gio/glocalfilemonitor.h
+++ b/gio/glocalfilemonitor.h
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
 #define G_IS_LOCAL_FILE_MONITOR_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_FILE_MONITOR))
 
 #define G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME "gio-local-file-monitor"
+#define G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME   "gio-nfs-file-monitor"
 
 typedef struct _GLocalFileMonitor      GLocalFileMonitor;
 typedef struct _GLocalFileMonitorClass GLocalFileMonitorClass;
@@ -60,6 +61,7 @@ GType           g_local_file_monitor_get_type (void) G_GNUC_CONST;
 
 GFileMonitor * _g_local_file_monitor_new      (const char         *pathname,
                                                GFileMonitorFlags   flags,
+                                               gboolean            is_remote_fs,
                                                GError            **error);
 
 G_END_DECLS



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]