summaryrefslogtreecommitdiff
path: root/gio/gunixmounts.c
diff options
context:
space:
mode:
Diffstat (limited to 'gio/gunixmounts.c')
-rw-r--r--gio/gunixmounts.c147
1 files changed, 128 insertions, 19 deletions
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
index 8e32b4f1e..fc3712987 100644
--- a/gio/gunixmounts.c
+++ b/gio/gunixmounts.c
@@ -148,6 +148,7 @@ G_DEFINE_BOXED_TYPE (GUnixMountPoint, g_unix_mount_point,
static GList *_g_get_unix_mounts (void);
static GList *_g_get_unix_mount_points (void);
+static gboolean proc_mounts_watch_is_running (void);
static guint64 mount_poller_time = 0;
@@ -280,35 +281,99 @@ g_unix_is_mount_path_system_internal (const char *mount_path)
return FALSE;
}
-static gboolean
-guess_system_internal (const char *mountpoint,
- const char *fs,
- const char *device)
+/**
+ * g_unix_is_system_fs_type:
+ * @fs_type: a file system type, e.g. `procfs` or `tmpfs`
+ *
+ * Determines if @fs_type is considered a type of file system which is only
+ * used in implementation of the OS. This is primarily used for hiding
+ * mounted volumes that are intended as APIs for programs to read, and system
+ * administrators at a shell; rather than something that should, for example,
+ * appear in a GUI. For example, the Linux `/proc` filesystem.
+ *
+ * The list of file system types considered ‘system’ ones may change over time.
+ *
+ * Returns: %TRUE if @fs_type is considered an implementation detail of the OS.
+ * Since: 2.56
+ */
+gboolean
+g_unix_is_system_fs_type (const char *fs_type)
{
const char *ignore_fs[] = {
+ "adfs",
+ "afs",
"auto",
"autofs",
+ "autofs4",
+ "cgroup",
+ "cifs",
+ "configfs",
+ "cxfs",
+ "debugfs",
"devfs",
"devpts",
+ "devtmpfs",
"ecryptfs",
"fdescfs",
+ "fusectl",
+ "gfs",
+ "gfs2",
+ "gpfs",
+ "hugetlbfs",
"kernfs",
"linprocfs",
+ "linsysfs",
+ "lustre",
+ "lustre_lite",
"mfs",
+ "mqueue",
+ "ncpfs",
+ "nfs",
+ "nfs4",
+ "nfsd",
"nullfs",
+ "ocfs2",
+ "overlay",
"proc",
"procfs",
+ "pstore",
"ptyfs",
"rootfs",
+ "rpc_pipefs",
+ "securityfs",
"selinuxfs",
+ "smbfs",
"sysfs",
"tmpfs",
"usbfs",
- "nfsd",
- "rpc_pipefs",
"zfs",
NULL
};
+
+ g_return_val_if_fail (fs_type != NULL && *fs_type != '\0', FALSE);
+
+ return is_in (fs_type, ignore_fs);
+}
+
+/**
+ * g_unix_is_system_device_path:
+ * @device_path: a device path, e.g. `/dev/loop0` or `nfsd`
+ *
+ * Determines if @device_path is considered a block device path which is only
+ * used in implementation of the OS. This is primarily used for hiding
+ * mounted volumes that are intended as APIs for programs to read, and system
+ * administrators at a shell; rather than something that should, for example,
+ * appear in a GUI. For example, the Linux `/proc` filesystem.
+ *
+ * The list of device paths considered ‘system’ ones may change over time.
+ *
+ * Returns: %TRUE if @device_path is considered an implementation detail of
+ * the OS.
+ * Since: 2.56
+ */
+gboolean
+g_unix_is_system_device_path (const char *device_path)
+{
const char *ignore_devices[] = {
"none",
"sunrpc",
@@ -318,11 +383,21 @@ guess_system_internal (const char *mountpoint,
"/dev/vn",
NULL
};
-
- if (is_in (fs, ignore_fs))
+
+ g_return_val_if_fail (device_path != NULL && *device_path != '\0', FALSE);
+
+ return is_in (device_path, ignore_devices);
+}
+
+static gboolean
+guess_system_internal (const char *mountpoint,
+ const char *fs,
+ const char *device)
+{
+ if (g_unix_is_system_fs_type (fs))
return TRUE;
- if (is_in (device, ignore_devices))
+ if (g_unix_is_system_device_path (device))
return TRUE;
if (g_unix_is_mount_path_system_internal (mountpoint))
@@ -430,7 +505,7 @@ _g_get_unix_mounts (void)
mnt_free_iter (iter);
out:
- mnt_unref_table (table);
+ mnt_free_table (table);
return g_list_reverse (return_list);
}
@@ -954,7 +1029,7 @@ _g_get_unix_mount_points (void)
mnt_free_iter (iter);
out:
- mnt_unref_table (table);
+ mnt_free_table (table);
return g_list_reverse (return_list);
}
@@ -1279,7 +1354,6 @@ _g_get_unix_mount_points (void)
GList *return_list;
#ifdef HAVE_SYS_SYSCTL_H
int usermnt = 0;
- size_t len = sizeof(usermnt);
struct stat sb;
#endif
@@ -1290,10 +1364,15 @@ _g_get_unix_mount_points (void)
#ifdef HAVE_SYS_SYSCTL_H
#if defined(HAVE_SYSCTLBYNAME)
- sysctlbyname ("vfs.usermount", &usermnt, &len, NULL, 0);
+ {
+ size_t len = sizeof(usermnt);
+
+ sysctlbyname ("vfs.usermount", &usermnt, &len, NULL, 0);
+ }
#elif defined(CTL_VFS) && defined(VFS_USERMOUNT)
{
int mib[2];
+ size_t len = sizeof(usermnt);
mib[0] = CTL_VFS;
mib[1] = VFS_USERMOUNT;
@@ -1302,6 +1381,7 @@ _g_get_unix_mount_points (void)
#elif defined(CTL_KERN) && defined(KERN_USERMOUNT)
{
int mib[2];
+ size_t len = sizeof(usermnt);
mib[0] = CTL_KERN;
mib[1] = KERN_USERMOUNT;
@@ -1368,15 +1448,26 @@ get_mounts_timestamp (void)
struct stat buf;
monitor_file = get_mtab_monitor_file ();
- if (monitor_file)
+ /* Don't return mtime for /proc/ files */
+ if (monitor_file && !g_str_has_prefix (monitor_file, "/proc/"))
{
if (stat (monitor_file, &buf) == 0)
return (guint64)buf.st_mtime;
}
- else
+ else if (proc_mounts_watch_is_running ())
{
+ /* it's being monitored by poll, so return mount_poller_time */
return mount_poller_time;
}
+ else
+ {
+ /* Case of /proc/ file not being monitored - Be on the safe side and
+ * send a new timestamp to force g_unix_mounts_changed_since() to
+ * return TRUE so any application caches depending on it (like eg.
+ * the one in GIO) get invalidated and don't hold possibly outdated
+ * data - see Bug 787731 */
+ return (guint64) g_get_monotonic_time ();
+ }
return 0;
}
@@ -1566,6 +1657,13 @@ static GFileMonitor *mtab_monitor;
static GSource *proc_mounts_watch_source;
static GList *mount_poller_mounts;
+static gboolean
+proc_mounts_watch_is_running (void)
+{
+ return proc_mounts_watch_source != NULL &&
+ !g_source_is_destroyed (proc_mounts_watch_source);
+}
+
static void
fstab_file_changed (GFileMonitor *monitor,
GFile *file,
@@ -1602,7 +1700,10 @@ proc_mounts_changed (GIOChannel *channel,
gpointer user_data)
{
if (cond & G_IO_ERR)
- g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]);
+ {
+ mount_poller_time = (guint64) g_get_monotonic_time ();
+ g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]);
+ }
return TRUE;
}
@@ -1652,7 +1753,10 @@ mount_monitor_stop (void)
}
if (proc_mounts_watch_source != NULL)
- g_source_destroy (proc_mounts_watch_source);
+ {
+ g_source_destroy (proc_mounts_watch_source);
+ proc_mounts_watch_source = NULL;
+ }
if (mtab_monitor)
{
@@ -2049,9 +2153,14 @@ g_unix_mount_is_readonly (GUnixMountEntry *mount_entry)
/**
* g_unix_mount_is_system_internal:
* @mount_entry: a #GUnixMount.
+ *
+ * Checks if a Unix mount is a system mount. This is the Boolean OR of
+ * g_unix_is_system_fs_type(), g_unix_is_system_device_path() and
+ * g_unix_is_mount_path_system_internal() on @mount_entry’s properties.
*
- * Checks if a unix mount is a system path.
- *
+ * The definition of what a ‘system’ mount entry is may change over time as new
+ * file system types and device paths are ignored.
+ *
* Returns: %TRUE if the unix mount is for a system path.
*/
gboolean