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
This commit is contained in:
Ryan Lortie 2013-01-18 18:44:11 -05:00 committed by Matthias Clasen
parent c83600e8ae
commit 6be54e9f56
6 changed files with 105 additions and 12 deletions

View File

@ -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);

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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