1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3 /* GIO - GLib Input, Output and Streaming Library
5 * Copyright (C) 2006-2007 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * Author: Alexander Larsson <alexl@redhat.com>
27 #include <sys/types.h>
30 #ifndef HAVE_SYSCTLBYNAME
31 #ifdef HAVE_SYS_PARAM_H
32 #include <sys/param.h>
48 #include <sys/statfs.h>
50 #if HAVE_SYS_STATVFS_H
51 #include <sys/statvfs.h>
55 #elif HAVE_SYS_MOUNT_H
57 #include <sys/param.h>
59 #include <sys/mount.h>
66 #include "gunixmounts.h"
67 #include "glocalfileprivate.h"
69 #include "gfilemonitor.h"
71 #include "gthemedicon.h"
72 #include "gcontextspecificgroup.h"
76 static const char *_resolve_dev_root (void);
81 * @include: gio/gunixmounts.h
82 * @short_description: UNIX mounts
84 * Routines for managing mounted UNIX mount points and paths.
86 * Note that `<gio/gunixmounts.h>` belongs to the UNIX-specific GIO
87 * interfaces, thus you have to use the `gio-unix-2.0.pc` pkg-config
93 * @G_UNIX_MOUNT_TYPE_UNKNOWN: Unknown UNIX mount type.
94 * @G_UNIX_MOUNT_TYPE_FLOPPY: Floppy disk UNIX mount type.
95 * @G_UNIX_MOUNT_TYPE_CDROM: CDROM UNIX mount type.
96 * @G_UNIX_MOUNT_TYPE_NFS: Network File System (NFS) UNIX mount type.
97 * @G_UNIX_MOUNT_TYPE_ZIP: ZIP UNIX mount type.
98 * @G_UNIX_MOUNT_TYPE_JAZ: JAZZ UNIX mount type.
99 * @G_UNIX_MOUNT_TYPE_MEMSTICK: Memory Stick UNIX mount type.
100 * @G_UNIX_MOUNT_TYPE_CF: Compact Flash UNIX mount type.
101 * @G_UNIX_MOUNT_TYPE_SM: Smart Media UNIX mount type.
102 * @G_UNIX_MOUNT_TYPE_SDMMC: SD/MMC UNIX mount type.
103 * @G_UNIX_MOUNT_TYPE_IPOD: iPod UNIX mount type.
104 * @G_UNIX_MOUNT_TYPE_CAMERA: Digital camera UNIX mount type.
105 * @G_UNIX_MOUNT_TYPE_HD: Hard drive UNIX mount type.
107 * Types of UNIX mounts.
110 G_UNIX_MOUNT_TYPE_UNKNOWN
,
111 G_UNIX_MOUNT_TYPE_FLOPPY
,
112 G_UNIX_MOUNT_TYPE_CDROM
,
113 G_UNIX_MOUNT_TYPE_NFS
,
114 G_UNIX_MOUNT_TYPE_ZIP
,
115 G_UNIX_MOUNT_TYPE_JAZ
,
116 G_UNIX_MOUNT_TYPE_MEMSTICK
,
117 G_UNIX_MOUNT_TYPE_CF
,
118 G_UNIX_MOUNT_TYPE_SM
,
119 G_UNIX_MOUNT_TYPE_SDMMC
,
120 G_UNIX_MOUNT_TYPE_IPOD
,
121 G_UNIX_MOUNT_TYPE_CAMERA
,
125 struct _GUnixMountEntry
{
128 char *filesystem_type
;
130 gboolean is_read_only
;
131 gboolean is_system_internal
;
134 G_DEFINE_BOXED_TYPE (GUnixMountEntry
, g_unix_mount_entry
,
135 g_unix_mount_copy
, g_unix_mount_free
)
137 struct _GUnixMountPoint
{
140 char *filesystem_type
;
142 gboolean is_read_only
;
143 gboolean is_user_mountable
;
144 gboolean is_loopback
;
147 G_DEFINE_BOXED_TYPE (GUnixMountPoint
, g_unix_mount_point
,
148 g_unix_mount_point_copy
, g_unix_mount_point_free
)
150 static GList
*_g_get_unix_mounts (void);
151 static GList
*_g_get_unix_mount_points (void);
152 static gboolean
proc_mounts_watch_is_running (void);
154 static guint64 mount_poller_time
= 0;
156 #ifdef HAVE_SYS_MNTTAB_H
157 #define MNTOPT_RO "ro"
163 #include <libmount.h>
165 #elif defined (HAVE_SYS_MNTTAB_H)
166 #include <sys/mnttab.h>
169 #ifdef HAVE_SYS_VFSTAB_H
170 #include <sys/vfstab.h>
173 #if defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
174 #include <sys/mntctl.h>
176 #include <sys/vmount.h>
180 #if (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
181 #include <sys/param.h>
182 #include <sys/ucred.h>
183 #include <sys/mount.h>
185 #ifdef HAVE_SYS_SYSCTL_H
186 #include <sys/sysctl.h>
190 #ifndef HAVE_SETMNTENT
191 #define setmntent(f,m) fopen(f,m)
193 #ifndef HAVE_ENDMNTENT
194 #define endmntent(f) fclose(f)
198 is_in (const char *value
, const char *set
[])
201 for (i
= 0; set
[i
] != NULL
; i
++)
203 if (strcmp (set
[i
], value
) == 0)
210 * g_unix_is_mount_path_system_internal:
211 * @mount_path: (type filename): a mount path, e.g. `/media/disk` or `/usr`
213 * Determines if @mount_path is considered an implementation of the
214 * OS. This is primarily used for hiding mountable and mounted volumes
215 * that only are used in the OS and has little to no relevance to the
218 * Returns: %TRUE if @mount_path is considered an implementation detail
222 g_unix_is_mount_path_system_internal (const char *mount_path
)
224 const char *ignore_mountpoints
[] = {
225 /* Includes all FHS 2.3 toplevel dirs and other specialized
226 * directories that we want to hide from the user.
228 "/", /* we already have "Filesystem root" in Nautilus */
231 "/compat/linux/proc",
260 "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */
263 "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */
271 if (is_in (mount_path
, ignore_mountpoints
))
274 if (g_str_has_prefix (mount_path
, "/dev/") ||
275 g_str_has_prefix (mount_path
, "/proc/") ||
276 g_str_has_prefix (mount_path
, "/sys/"))
279 if (g_str_has_suffix (mount_path
, "/.gvfs"))
286 * g_unix_is_system_fs_type:
287 * @fs_type: a file system type, e.g. `procfs` or `tmpfs`
289 * Determines if @fs_type is considered a type of file system which is only
290 * used in implementation of the OS. This is primarily used for hiding
291 * mounted volumes that are intended as APIs for programs to read, and system
292 * administrators at a shell; rather than something that should, for example,
293 * appear in a GUI. For example, the Linux `/proc` filesystem.
295 * The list of file system types considered ‘system’ ones may change over time.
297 * Returns: %TRUE if @fs_type is considered an implementation detail of the OS.
301 g_unix_is_system_fs_type (const char *fs_type
)
303 const char *ignore_fs
[] = {
350 g_return_val_if_fail (fs_type
!= NULL
&& *fs_type
!= '\0', FALSE
);
352 return is_in (fs_type
, ignore_fs
);
356 * g_unix_is_system_device_path:
357 * @device_path: a device path, e.g. `/dev/loop0` or `nfsd`
359 * Determines if @device_path is considered a block device path which is only
360 * used in implementation of the OS. This is primarily used for hiding
361 * mounted volumes that are intended as APIs for programs to read, and system
362 * administrators at a shell; rather than something that should, for example,
363 * appear in a GUI. For example, the Linux `/proc` filesystem.
365 * The list of device paths considered ‘system’ ones may change over time.
367 * Returns: %TRUE if @device_path is considered an implementation detail of
372 g_unix_is_system_device_path (const char *device_path
)
374 const char *ignore_devices
[] = {
384 g_return_val_if_fail (device_path
!= NULL
&& *device_path
!= '\0', FALSE
);
386 return is_in (device_path
, ignore_devices
);
390 guess_system_internal (const char *mountpoint
,
394 if (g_unix_is_system_fs_type (fs
))
397 if (g_unix_is_system_device_path (device
))
400 if (g_unix_is_mount_path_system_internal (mountpoint
))
406 /* GUnixMounts (ie: mtab) implementations {{{1 */
408 static GUnixMountEntry
*
409 create_unix_mount_entry (const char *device_path
,
410 const char *mount_path
,
411 const char *filesystem_type
,
413 gboolean is_read_only
)
415 GUnixMountEntry
*mount_entry
= NULL
;
417 mount_entry
= g_new0 (GUnixMountEntry
, 1);
418 mount_entry
->device_path
= g_strdup (device_path
);
419 mount_entry
->mount_path
= g_strdup (mount_path
);
420 mount_entry
->filesystem_type
= g_strdup (filesystem_type
);
421 mount_entry
->options
= g_strdup (options
);
422 mount_entry
->is_read_only
= is_read_only
;
424 mount_entry
->is_system_internal
=
425 guess_system_internal (mount_entry
->mount_path
,
426 mount_entry
->filesystem_type
,
427 mount_entry
->device_path
);
431 static GUnixMountPoint
*
432 create_unix_mount_point (const char *device_path
,
433 const char *mount_path
,
434 const char *filesystem_type
,
436 gboolean is_read_only
,
437 gboolean is_user_mountable
,
438 gboolean is_loopback
)
440 GUnixMountPoint
*mount_point
= NULL
;
442 mount_point
= g_new0 (GUnixMountPoint
, 1);
443 mount_point
->device_path
= g_strdup (device_path
);
444 mount_point
->mount_path
= g_strdup (mount_path
);
445 mount_point
->filesystem_type
= g_strdup (filesystem_type
);
446 mount_point
->options
= g_strdup (options
);
447 mount_point
->is_read_only
= is_read_only
;
448 mount_point
->is_user_mountable
= is_user_mountable
;
449 mount_point
->is_loopback
= is_loopback
;
454 /* mntent.h (Linux, GNU, NSS) {{{2 */
459 /* For documentation on /proc/self/mountinfo see
460 * http://www.kernel.org/doc/Documentation/filesystems/proc.txt
462 #define PROC_MOUNTINFO_PATH "/proc/self/mountinfo"
465 _g_get_unix_mounts (void)
467 struct libmnt_table
*table
= NULL
;
468 struct libmnt_iter
* iter
= NULL
;
469 struct libmnt_fs
*fs
= NULL
;
470 GUnixMountEntry
*mount_entry
= NULL
;
471 GList
*return_list
= NULL
;
473 table
= mnt_new_table ();
474 if (mnt_table_parse_mtab (table
, NULL
) < 0)
477 iter
= mnt_new_iter (MNT_ITER_FORWARD
);
478 while (mnt_table_next_fs (table
, iter
, &fs
) == 0)
480 const char *device_path
= NULL
;
481 char *mount_options
= NULL
;
482 unsigned long mount_flags
= 0;
483 gboolean is_read_only
= FALSE
;
485 device_path
= mnt_fs_get_source (fs
);
486 if (g_strcmp0 (device_path
, "/dev/root") == 0)
487 device_path
= _resolve_dev_root ();
489 mount_options
= mnt_fs_strdup_options (fs
);
492 mnt_optstr_get_flags (mount_options
, &mount_flags
, mnt_get_builtin_optmap (MNT_LINUX_MAP
));
493 g_free (mount_options
);
495 is_read_only
= (mount_flags
& MS_RDONLY
) ? TRUE
: FALSE
;
497 mount_entry
= create_unix_mount_entry (device_path
,
498 mnt_fs_get_target (fs
),
499 mnt_fs_get_fstype (fs
),
500 mnt_fs_get_options (fs
),
503 return_list
= g_list_prepend (return_list
, mount_entry
);
505 mnt_free_iter (iter
);
508 mnt_free_table (table
);
510 return g_list_reverse (return_list
);
516 get_mtab_read_file (void)
520 return "/proc/mounts";
522 return _PATH_MOUNTED
;
529 #ifndef HAVE_GETMNTENT_R
530 G_LOCK_DEFINE_STATIC(getmntent
);
534 _g_get_unix_mounts (void)
536 #ifdef HAVE_GETMNTENT_R
540 struct mntent
*mntent
;
542 const char *read_file
;
543 GUnixMountEntry
*mount_entry
;
544 GHashTable
*mounts_hash
;
547 read_file
= get_mtab_read_file ();
549 file
= setmntent (read_file
, "r");
555 mounts_hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
557 #ifdef HAVE_GETMNTENT_R
558 while ((mntent
= getmntent_r (file
, &ent
, buf
, sizeof (buf
))) != NULL
)
561 while ((mntent
= getmntent (file
)) != NULL
)
564 const char *device_path
= NULL
;
565 gboolean is_read_only
= FALSE
;
567 /* ignore any mnt_fsname that is repeated and begins with a '/'
569 * We do this to avoid being fooled by --bind mounts, since
570 * these have the same device as the location they bind to.
571 * It's not an ideal solution to the problem, but it's likely that
572 * the most important mountpoint is first and the --bind ones after
573 * that aren't as important. So it should work.
575 * The '/' is to handle procfs, tmpfs and other no device mounts.
577 if (mntent
->mnt_fsname
!= NULL
&&
578 mntent
->mnt_fsname
[0] == '/' &&
579 g_hash_table_lookup (mounts_hash
, mntent
->mnt_fsname
))
582 if (g_strcmp0 (mntent
->mnt_fsname
, "/dev/root") == 0)
583 device_path
= _resolve_dev_root ();
585 device_path
= mntent
->mnt_fsname
;
587 #if defined (HAVE_HASMNTOPT)
588 if (hasmntopt (mntent
, MNTOPT_RO
) != NULL
)
592 mount_entry
= create_unix_mount_entry (device_path
,
598 g_hash_table_insert (mounts_hash
,
599 mount_entry
->device_path
,
600 mount_entry
->device_path
);
602 return_list
= g_list_prepend (return_list
, mount_entry
);
604 g_hash_table_destroy (mounts_hash
);
608 #ifndef HAVE_GETMNTENT_R
609 G_UNLOCK (getmntent
);
612 return g_list_reverse (return_list
);
615 #endif /* HAVE_LIBMOUNT */
618 get_mtab_monitor_file (void)
620 static const char *mountinfo_path
= NULL
;
625 if (mountinfo_path
!= NULL
)
626 return mountinfo_path
;
629 /* The mtab file is still used by some distros, so it has to be monitored in
630 * order to avoid races between g_unix_mounts_get and "mounts-changed" signal:
631 * https://bugzilla.gnome.org/show_bug.cgi?id=782814
633 if (mnt_has_regular_mtab (&mountinfo_path
, NULL
))
635 return mountinfo_path
;
638 if (stat (PROC_MOUNTINFO_PATH
, &buf
) == 0)
640 mountinfo_path
= PROC_MOUNTINFO_PATH
;
641 return mountinfo_path
;
647 mountinfo_path
= "/proc/mounts";
649 mountinfo_path
= _PATH_MOUNTED
;
652 mountinfo_path
= "/etc/mtab";
655 return mountinfo_path
;
659 #elif defined (HAVE_SYS_MNTTAB_H)
661 G_LOCK_DEFINE_STATIC(getmntent
);
664 get_mtab_read_file (void)
667 return _PATH_MOUNTED
;
669 return "/etc/mnttab";
674 get_mtab_monitor_file (void)
676 return get_mtab_read_file ();
680 _g_get_unix_mounts (void)
682 struct mnttab mntent
;
684 const char *read_file
;
685 GUnixMountEntry
*mount_entry
;
688 read_file
= get_mtab_read_file ();
690 file
= setmntent (read_file
, "r");
697 while (! getmntent (file
, &mntent
))
699 gboolean is_read_only
= FALSE
;
701 #if defined (HAVE_HASMNTOPT)
702 if (hasmntopt (&mntent
, MNTOPT_RO
) != NULL
)
706 mount_entry
= create_unix_mount_entry (mntent
.mnt_special
,
712 return_list
= g_list_prepend (return_list
, mount_entry
);
717 G_UNLOCK (getmntent
);
719 return g_list_reverse (return_list
);
722 /* mntctl.h (AIX) {{{2 */
723 #elif defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
726 get_mtab_monitor_file (void)
732 _g_get_unix_mounts (void)
734 struct vfs_ent
*fs_info
;
735 struct vmount
*vmount_info
;
737 unsigned int vmount_size
;
741 if (mntctl (MCTL_QUERY
, sizeof (vmount_size
), &vmount_size
) != 0)
743 g_warning ("Unable to know the number of mounted volumes");
748 vmount_info
= (struct vmount
*)g_malloc (vmount_size
);
750 vmount_number
= mntctl (MCTL_QUERY
, vmount_size
, vmount_info
);
752 if (vmount_info
->vmt_revision
!= VMT_REVISION
)
753 g_warning ("Bad vmount structure revision number, want %d, got %d", VMT_REVISION
, vmount_info
->vmt_revision
);
755 if (vmount_number
< 0)
757 g_warning ("Unable to recover mounted volumes information");
759 g_free (vmount_info
);
764 while (vmount_number
> 0)
766 gboolean is_read_only
= FALSE
;
768 fs_info
= getvfsbytype (vmount_info
->vmt_gfstype
);
770 /* is_removable = (vmount_info->vmt_flags & MNT_REMOVABLE) ? 1 : 0; */
771 is_read_only
= (vmount_info
->vmt_flags
& MNT_READONLY
) ? 1 : 0;
773 mount_entry
= create_unix_mount_entry (vmt2dataptr (vmount_info
, VMT_OBJECT
),
774 vmt2dataptr (vmount_info
, VMT_STUB
),
775 fs_info
== NULL
? "unknown" : fs_info
->vfsent_name
,
779 return_list
= g_list_prepend (return_list
, mount_entry
);
781 vmount_info
= (struct vmount
*)( (char*)vmount_info
782 + vmount_info
->vmt_length
);
786 g_free (vmount_info
);
788 return g_list_reverse (return_list
);
791 /* sys/mount.h {{{2 */
792 #elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
795 get_mtab_monitor_file (void)
801 _g_get_unix_mounts (void)
803 #if defined(USE_STATVFS)
804 struct statvfs
*mntent
= NULL
;
805 #elif defined(USE_STATFS)
806 struct statfs
*mntent
= NULL
;
808 #error statfs juggling failed
812 GUnixMountEntry
*mount_entry
;
815 /* Pass NOWAIT to avoid blocking trying to update NFS mounts. */
816 #if defined(USE_STATVFS) && defined(HAVE_GETVFSSTAT)
817 num_mounts
= getvfsstat (NULL
, 0, ST_NOWAIT
);
818 #elif defined(USE_STATFS) && defined(HAVE_GETFSSTAT)
819 num_mounts
= getfsstat (NULL
, 0, MNT_NOWAIT
);
821 if (num_mounts
== -1)
824 bufsize
= num_mounts
* sizeof (*mntent
);
825 mntent
= g_malloc (bufsize
);
826 #if defined(USE_STATVFS) && defined(HAVE_GETVFSSTAT)
827 num_mounts
= getvfsstat (mntent
, bufsize
, ST_NOWAIT
);
828 #elif defined(USE_STATFS) && defined(HAVE_GETFSSTAT)
829 num_mounts
= getfsstat (mntent
, bufsize
, MNT_NOWAIT
);
831 if (num_mounts
== -1)
836 for (i
= 0; i
< num_mounts
; i
++)
838 gboolean is_read_only
= FALSE
;
840 #if defined(USE_STATVFS)
841 if (mntent
[i
].f_flag
& ST_RDONLY
)
842 #elif defined(USE_STATFS)
843 if (mntent
[i
].f_flags
& MNT_RDONLY
)
845 #error statfs juggling failed
849 mount_entry
= create_unix_mount_entry (mntent
[i
].f_mntfromname
,
850 mntent
[i
].f_mntonname
,
851 mntent
[i
].f_fstypename
,
855 return_list
= g_list_prepend (return_list
, mount_entry
);
860 return g_list_reverse (return_list
);
864 #elif defined(__INTERIX)
867 get_mtab_monitor_file (void)
873 _g_get_unix_mounts (void)
876 GList
* return_list
= NULL
;
877 char filename
[9 + NAME_MAX
];
879 dirp
= opendir ("/dev/fs");
882 g_warning ("unable to read /dev/fs!");
888 struct statvfs statbuf
;
890 struct dirent
* result
;
892 if (readdir_r (dirp
, &entry
, &result
) || result
== NULL
)
895 strcpy (filename
, "/dev/fs/");
896 strcat (filename
, entry
.d_name
);
898 if (statvfs (filename
, &statbuf
) == 0)
900 GUnixMountEntry
* mount_entry
= g_new0(GUnixMountEntry
, 1);
902 mount_entry
->mount_path
= g_strdup (statbuf
.f_mntonname
);
903 mount_entry
->device_path
= g_strdup (statbuf
.f_mntfromname
);
904 mount_entry
->filesystem_type
= g_strdup (statbuf
.f_fstypename
);
906 if (statbuf
.f_flag
& ST_RDONLY
)
907 mount_entry
->is_read_only
= TRUE
;
909 return_list
= g_list_prepend(return_list
, mount_entry
);
913 return_list
= g_list_reverse (return_list
);
920 /* Common code {{{2 */
922 #error No _g_get_unix_mounts() implementation for system
925 /* GUnixMountPoints (ie: fstab) implementations {{{1 */
927 /* _g_get_unix_mount_points():
929 * don't return swap and ignore mounts.
933 get_fstab_file (void)
936 return (char *) mnt_get_fstab_path ();
938 #if defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
940 return "/etc/filesystems";
941 #elif defined(_PATH_MNTTAB)
943 #elif defined(VFSTAB)
951 /* mntent.h (Linux, GNU, NSS) {{{2 */
957 _g_get_unix_mount_points (void)
959 struct libmnt_table
*table
= NULL
;
960 struct libmnt_iter
* iter
= NULL
;
961 struct libmnt_fs
*fs
= NULL
;
962 GUnixMountPoint
*mount_point
= NULL
;
963 GList
*return_list
= NULL
;
965 table
= mnt_new_table ();
966 if (mnt_table_parse_fstab (table
, NULL
) < 0)
969 iter
= mnt_new_iter (MNT_ITER_FORWARD
);
970 while (mnt_table_next_fs (table
, iter
, &fs
) == 0)
972 const char *device_path
= NULL
;
973 const char *mount_path
= NULL
;
974 const char *mount_fstype
= NULL
;
975 char *mount_options
= NULL
;
976 gboolean is_read_only
= FALSE
;
977 gboolean is_user_mountable
= FALSE
;
978 gboolean is_loopback
= FALSE
;
980 mount_path
= mnt_fs_get_target (fs
);
981 if ((strcmp (mount_path
, "ignore") == 0) ||
982 (strcmp (mount_path
, "swap") == 0) ||
983 (strcmp (mount_path
, "none") == 0))
986 mount_fstype
= mnt_fs_get_fstype (fs
);
987 mount_options
= mnt_fs_strdup_options (fs
);
990 unsigned long mount_flags
= 0;
991 unsigned long userspace_flags
= 0;
993 mnt_optstr_get_flags (mount_options
, &mount_flags
, mnt_get_builtin_optmap (MNT_LINUX_MAP
));
994 mnt_optstr_get_flags (mount_options
, &userspace_flags
, mnt_get_builtin_optmap (MNT_USERSPACE_MAP
));
996 /* We ignore bind fstab entries, as we ignore bind mounts anyway */
997 if (mount_flags
& MS_BIND
)
999 g_free (mount_options
);
1003 is_read_only
= (mount_flags
& MS_RDONLY
) != 0;
1004 is_loopback
= (userspace_flags
& MNT_MS_LOOP
) != 0;
1006 if ((mount_fstype
!= NULL
&& g_strcmp0 ("supermount", mount_fstype
) == 0) ||
1007 ((userspace_flags
& MNT_MS_USER
) &&
1008 (g_strstr_len (mount_options
, -1, "user_xattr") == NULL
)) ||
1009 (g_strstr_len (mount_options
, -1, "pamconsole") == NULL
) ||
1010 (userspace_flags
& MNT_MS_USERS
) ||
1011 (userspace_flags
& MNT_MS_OWNER
))
1013 is_user_mountable
= TRUE
;
1017 device_path
= mnt_fs_get_source (fs
);
1018 if (g_strcmp0 (device_path
, "/dev/root") == 0)
1019 device_path
= _resolve_dev_root ();
1021 mount_point
= create_unix_mount_point (device_path
,
1029 g_free (mount_options
);
1031 return_list
= g_list_prepend (return_list
, mount_point
);
1033 mnt_free_iter (iter
);
1036 mnt_free_table (table
);
1038 return g_list_reverse (return_list
);
1044 _g_get_unix_mount_points (void)
1046 #ifdef HAVE_GETMNTENT_R
1050 struct mntent
*mntent
;
1053 GUnixMountPoint
*mount_point
;
1056 read_file
= get_fstab_file ();
1058 file
= setmntent (read_file
, "r");
1064 #ifdef HAVE_GETMNTENT_R
1065 while ((mntent
= getmntent_r (file
, &ent
, buf
, sizeof (buf
))) != NULL
)
1068 while ((mntent
= getmntent (file
)) != NULL
)
1071 const char *device_path
= NULL
;
1072 gboolean is_read_only
= FALSE
;
1073 gboolean is_user_mountable
= FALSE
;
1074 gboolean is_loopback
= FALSE
;
1076 if ((strcmp (mntent
->mnt_dir
, "ignore") == 0) ||
1077 (strcmp (mntent
->mnt_dir
, "swap") == 0) ||
1078 (strcmp (mntent
->mnt_dir
, "none") == 0))
1081 #ifdef HAVE_HASMNTOPT
1082 /* We ignore bind fstab entries, as we ignore bind mounts anyway */
1083 if (hasmntopt (mntent
, "bind"))
1087 if (strcmp (mntent
->mnt_fsname
, "/dev/root") == 0)
1088 device_path
= _resolve_dev_root ();
1090 device_path
= mntent
->mnt_fsname
;
1092 #ifdef HAVE_HASMNTOPT
1093 if (hasmntopt (mntent
, MNTOPT_RO
) != NULL
)
1094 is_read_only
= TRUE
;
1096 if (hasmntopt (mntent
, "loop") != NULL
)
1101 if ((mntent
->mnt_type
!= NULL
&& strcmp ("supermount", mntent
->mnt_type
) == 0)
1102 #ifdef HAVE_HASMNTOPT
1103 || (hasmntopt (mntent
, "user") != NULL
1104 && hasmntopt (mntent
, "user") != hasmntopt (mntent
, "user_xattr"))
1105 || hasmntopt (mntent
, "pamconsole") != NULL
1106 || hasmntopt (mntent
, "users") != NULL
1107 || hasmntopt (mntent
, "owner") != NULL
1110 is_user_mountable
= TRUE
;
1112 mount_point
= create_unix_mount_point (device_path
,
1120 return_list
= g_list_prepend (return_list
, mount_point
);
1125 #ifndef HAVE_GETMNTENT_R
1126 G_UNLOCK (getmntent
);
1129 return g_list_reverse (return_list
);
1132 #endif /* HAVE_LIBMOUNT */
1135 #elif defined (HAVE_SYS_MNTTAB_H)
1138 _g_get_unix_mount_points (void)
1140 struct mnttab mntent
;
1143 GUnixMountPoint
*mount_point
;
1146 read_file
= get_fstab_file ();
1148 file
= setmntent (read_file
, "r");
1155 while (! getmntent (file
, &mntent
))
1157 gboolean is_read_only
= FALSE
;
1158 gboolean is_user_mountable
= FALSE
;
1159 gboolean is_loopback
= FALSE
;
1161 if ((strcmp (mntent
.mnt_mountp
, "ignore") == 0) ||
1162 (strcmp (mntent
.mnt_mountp
, "swap") == 0) ||
1163 (strcmp (mntent
.mnt_mountp
, "none") == 0))
1166 #ifdef HAVE_HASMNTOPT
1167 if (hasmntopt (&mntent
, MNTOPT_RO
) != NULL
)
1168 is_read_only
= TRUE
;
1170 if (hasmntopt (&mntent
, "lofs") != NULL
)
1174 if ((mntent
.mnt_fstype
!= NULL
)
1175 #ifdef HAVE_HASMNTOPT
1176 || (hasmntopt (&mntent
, "user") != NULL
1177 && hasmntopt (&mntent
, "user") != hasmntopt (&mntent
, "user_xattr"))
1178 || hasmntopt (&mntent
, "pamconsole") != NULL
1179 || hasmntopt (&mntent
, "users") != NULL
1180 || hasmntopt (&mntent
, "owner") != NULL
1183 is_user_mountable
= TRUE
;
1185 mount_point
= create_unix_mount_point (mntent
.mnt_special
,
1193 return_list
= g_list_prepend (return_list
, mount_point
);
1197 G_UNLOCK (getmntent
);
1199 return g_list_reverse (return_list
);
1202 /* mntctl.h (AIX) {{{2 */
1203 #elif defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
1205 /* functions to parse /etc/filesystems on aix */
1207 /* read character, ignoring comments (begin with '*', end with '\n' */
1209 aix_fs_getc (FILE *fd
)
1213 while ((c
= getc (fd
)) == '*')
1215 while (((c
= getc (fd
)) != '\n') && (c
!= EOF
))
1220 /* eat all continuous spaces in a file */
1222 aix_fs_ignorespace (FILE *fd
)
1226 while ((c
= aix_fs_getc (fd
)) != EOF
)
1228 if (!g_ascii_isspace (c
))
1238 /* read one word from file */
1240 aix_fs_getword (FILE *fd
,
1245 aix_fs_ignorespace (fd
);
1247 while (((c
= aix_fs_getc (fd
)) != EOF
) && !g_ascii_isspace (c
))
1251 while (((c
= aix_fs_getc (fd
)) != EOF
) && (c
!= '"'))
1263 char mnt_mount
[PATH_MAX
];
1264 char mnt_special
[PATH_MAX
];
1265 char mnt_fstype
[16];
1266 char mnt_options
[128];
1267 } AixMountTableEntry
;
1269 /* read mount points properties */
1271 aix_fs_get (FILE *fd
,
1272 AixMountTableEntry
*prop
)
1274 static char word
[PATH_MAX
] = { 0 };
1275 char value
[PATH_MAX
];
1280 if (aix_fs_getword (fd
, word
) == EOF
)
1284 word
[strlen(word
) - 1] = 0;
1285 strcpy (prop
->mnt_mount
, word
);
1287 /* read attributes and value */
1289 while (aix_fs_getword (fd
, word
) != EOF
)
1291 /* test if is attribute or new stanza */
1292 if (word
[strlen(word
) - 1] == ':')
1296 aix_fs_getword (fd
, value
);
1299 aix_fs_getword (fd
, value
);
1301 if (strcmp (word
, "dev") == 0)
1302 strcpy (prop
->mnt_special
, value
);
1303 else if (strcmp (word
, "vfs") == 0)
1304 strcpy (prop
->mnt_fstype
, value
);
1305 else if (strcmp (word
, "options") == 0)
1306 strcpy(prop
->mnt_options
, value
);
1313 _g_get_unix_mount_points (void)
1315 struct mntent
*mntent
;
1318 GUnixMountPoint
*mount_point
;
1319 AixMountTableEntry mntent
;
1322 read_file
= get_fstab_file ();
1324 file
= setmntent (read_file
, "r");
1330 while (!aix_fs_get (file
, &mntent
))
1332 if (strcmp ("cdrfs", mntent
.mnt_fstype
) == 0)
1334 mount_point
= create_unix_mount_point (mntent
.mnt_special
,
1342 return_list
= g_list_prepend (return_list
, mount_point
);
1348 return g_list_reverse (return_list
);
1351 #elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
1354 _g_get_unix_mount_points (void)
1356 struct fstab
*fstab
= NULL
;
1357 GUnixMountPoint
*mount_point
;
1359 #ifdef HAVE_SYS_SYSCTL_H
1369 #ifdef HAVE_SYS_SYSCTL_H
1370 #if defined(HAVE_SYSCTLBYNAME)
1372 size_t len
= sizeof(usermnt
);
1374 sysctlbyname ("vfs.usermount", &usermnt
, &len
, NULL
, 0);
1376 #elif defined(CTL_VFS) && defined(VFS_USERMOUNT)
1379 size_t len
= sizeof(usermnt
);
1382 mib
[1] = VFS_USERMOUNT
;
1383 sysctl (mib
, 2, &usermnt
, &len
, NULL
, 0);
1385 #elif defined(CTL_KERN) && defined(KERN_USERMOUNT)
1388 size_t len
= sizeof(usermnt
);
1391 mib
[1] = KERN_USERMOUNT
;
1392 sysctl (mib
, 2, &usermnt
, &len
, NULL
, 0);
1397 while ((fstab
= getfsent ()) != NULL
)
1399 gboolean is_read_only
= FALSE
;
1400 gboolean is_user_mountable
= FALSE
;
1402 if (strcmp (fstab
->fs_vfstype
, "swap") == 0)
1405 if (strcmp (fstab
->fs_type
, "ro") == 0)
1406 is_read_only
= TRUE
;
1408 #ifdef HAVE_SYS_SYSCTL_H
1411 uid_t uid
= getuid ();
1412 if (stat (fstab
->fs_file
, &sb
) == 0)
1414 if (uid
== 0 || sb
.st_uid
== uid
)
1415 is_user_mountable
= TRUE
;
1420 mount_point
= create_unix_mount_point (fstab
->fs_spec
,
1428 return_list
= g_list_prepend (return_list
, mount_point
);
1433 return g_list_reverse (return_list
);
1436 #elif defined(__INTERIX)
1438 _g_get_unix_mount_points (void)
1440 return _g_get_unix_mounts ();
1443 /* Common code {{{2 */
1445 #error No g_get_mount_table() implementation for system
1449 get_mounts_timestamp (void)
1451 const char *monitor_file
;
1454 monitor_file
= get_mtab_monitor_file ();
1455 /* Don't return mtime for /proc/ files */
1456 if (monitor_file
&& !g_str_has_prefix (monitor_file
, "/proc/"))
1458 if (stat (monitor_file
, &buf
) == 0)
1459 return (guint64
)buf
.st_mtime
;
1461 else if (proc_mounts_watch_is_running ())
1463 /* it's being monitored by poll, so return mount_poller_time */
1464 return mount_poller_time
;
1468 /* Case of /proc/ file not being monitored - Be on the safe side and
1469 * send a new timestamp to force g_unix_mounts_changed_since() to
1470 * return TRUE so any application caches depending on it (like eg.
1471 * the one in GIO) get invalidated and don't hold possibly outdated
1472 * data - see Bug 787731 */
1473 return (guint64
) g_get_monotonic_time ();
1479 get_mount_points_timestamp (void)
1481 const char *monitor_file
;
1484 monitor_file
= get_fstab_file ();
1487 if (stat (monitor_file
, &buf
) == 0)
1488 return (guint64
)buf
.st_mtime
;
1494 * g_unix_mounts_get:
1495 * @time_read: (out) (optional): guint64 to contain a timestamp, or %NULL
1497 * Gets a #GList of #GUnixMountEntry containing the unix mounts.
1498 * If @time_read is set, it will be filled with the mount
1499 * timestamp, allowing for checking if the mounts have changed
1500 * with g_unix_mounts_changed_since().
1502 * Returns: (element-type GUnixMountEntry) (transfer full):
1503 * a #GList of the UNIX mounts.
1506 g_unix_mounts_get (guint64
*time_read
)
1509 *time_read
= get_mounts_timestamp ();
1511 return _g_get_unix_mounts ();
1516 * @mount_path: (type filename): path for a possible unix mount.
1517 * @time_read: (out) (optional): guint64 to contain a timestamp.
1519 * Gets a #GUnixMountEntry for a given mount path. If @time_read
1520 * is set, it will be filled with a unix timestamp for checking
1521 * if the mounts have changed since with g_unix_mounts_changed_since().
1523 * Returns: (transfer full): a #GUnixMountEntry.
1526 g_unix_mount_at (const char *mount_path
,
1530 GUnixMountEntry
*mount_entry
, *found
;
1532 mounts
= g_unix_mounts_get (time_read
);
1535 for (l
= mounts
; l
!= NULL
; l
= l
->next
)
1537 mount_entry
= l
->data
;
1539 if (!found
&& strcmp (mount_path
, mount_entry
->mount_path
) == 0)
1540 found
= mount_entry
;
1542 g_unix_mount_free (mount_entry
);
1544 g_list_free (mounts
);
1551 * @file_path: (type filename): file path on some unix mount.
1552 * @time_read: (out) (optional): guint64 to contain a timestamp.
1554 * Gets a #GUnixMountEntry for a given file path. If @time_read
1555 * is set, it will be filled with a unix timestamp for checking
1556 * if the mounts have changed since with g_unix_mounts_changed_since().
1558 * Returns: (transfer full): a #GUnixMountEntry.
1563 g_unix_mount_for (const char *file_path
,
1566 GUnixMountEntry
*entry
;
1568 g_return_val_if_fail (file_path
!= NULL
, NULL
);
1570 entry
= g_unix_mount_at (file_path
, time_read
);
1575 topdir
= _g_local_file_find_topdir_for (file_path
);
1578 entry
= g_unix_mount_at (topdir
, time_read
);
1587 * g_unix_mount_points_get:
1588 * @time_read: (out) (optional): guint64 to contain a timestamp.
1590 * Gets a #GList of #GUnixMountPoint containing the unix mount points.
1591 * If @time_read is set, it will be filled with the mount timestamp,
1592 * allowing for checking if the mounts have changed with
1593 * g_unix_mount_points_changed_since().
1595 * Returns: (element-type GUnixMountPoint) (transfer full):
1596 * a #GList of the UNIX mountpoints.
1599 g_unix_mount_points_get (guint64
*time_read
)
1602 *time_read
= get_mount_points_timestamp ();
1604 return _g_get_unix_mount_points ();
1608 * g_unix_mounts_changed_since:
1609 * @time: guint64 to contain a timestamp.
1611 * Checks if the unix mounts have changed since a given unix time.
1613 * Returns: %TRUE if the mounts have changed since @time.
1616 g_unix_mounts_changed_since (guint64 time
)
1618 return get_mounts_timestamp () != time
;
1622 * g_unix_mount_points_changed_since:
1623 * @time: guint64 to contain a timestamp.
1625 * Checks if the unix mount points have changed since a given unix time.
1627 * Returns: %TRUE if the mount points have changed since @time.
1630 g_unix_mount_points_changed_since (guint64 time
)
1632 return get_mount_points_timestamp () != time
;
1635 /* GUnixMountMonitor {{{1 */
1639 MOUNTPOINTS_CHANGED
,
1643 static guint signals
[LAST_SIGNAL
];
1645 struct _GUnixMountMonitor
{
1648 GMainContext
*context
;
1651 struct _GUnixMountMonitorClass
{
1652 GObjectClass parent_class
;
1656 G_DEFINE_TYPE (GUnixMountMonitor
, g_unix_mount_monitor
, G_TYPE_OBJECT
)
1658 static GContextSpecificGroup mount_monitor_group
;
1659 static GFileMonitor
*fstab_monitor
;
1660 static GFileMonitor
*mtab_monitor
;
1661 static GSource
*proc_mounts_watch_source
;
1662 static GList
*mount_poller_mounts
;
1663 static guint mtab_file_changed_id
;
1666 proc_mounts_watch_is_running (void)
1668 return proc_mounts_watch_source
!= NULL
&&
1669 !g_source_is_destroyed (proc_mounts_watch_source
);
1673 fstab_file_changed (GFileMonitor
*monitor
,
1676 GFileMonitorEvent event_type
,
1679 if (event_type
!= G_FILE_MONITOR_EVENT_CHANGED
&&
1680 event_type
!= G_FILE_MONITOR_EVENT_CREATED
&&
1681 event_type
!= G_FILE_MONITOR_EVENT_DELETED
)
1684 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTPOINTS_CHANGED
]);
1688 mtab_file_changed_cb (gpointer user_data
)
1690 mtab_file_changed_id
= 0;
1691 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTS_CHANGED
]);
1693 return G_SOURCE_REMOVE
;
1697 mtab_file_changed (GFileMonitor
*monitor
,
1700 GFileMonitorEvent event_type
,
1703 if (event_type
!= G_FILE_MONITOR_EVENT_CHANGED
&&
1704 event_type
!= G_FILE_MONITOR_EVENT_CREATED
&&
1705 event_type
!= G_FILE_MONITOR_EVENT_DELETED
)
1708 /* Skip accumulated events from file monitor which we are not able to handle
1709 * in a real time instead of emitting mounts_changed signal several times.
1710 * This should behave equally to GIOChannel based monitoring. See Bug 792235.
1712 if (mtab_file_changed_id
> 0)
1715 mtab_file_changed_id
= g_idle_add (mtab_file_changed_cb
, NULL
);
1719 proc_mounts_changed (GIOChannel
*channel
,
1723 if (cond
& G_IO_ERR
)
1725 mount_poller_time
= (guint64
) g_get_monotonic_time ();
1726 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTS_CHANGED
]);
1733 mount_change_poller (gpointer user_data
)
1735 GList
*current_mounts
, *new_it
, *old_it
;
1736 gboolean has_changed
= FALSE
;
1738 current_mounts
= _g_get_unix_mounts ();
1740 for ( new_it
= current_mounts
, old_it
= mount_poller_mounts
;
1741 new_it
!= NULL
&& old_it
!= NULL
;
1742 new_it
= g_list_next (new_it
), old_it
= g_list_next (old_it
) )
1744 if (g_unix_mount_compare (new_it
->data
, old_it
->data
) != 0)
1750 if (!(new_it
== NULL
&& old_it
== NULL
))
1753 g_list_free_full (mount_poller_mounts
, (GDestroyNotify
) g_unix_mount_free
);
1755 mount_poller_mounts
= current_mounts
;
1759 mount_poller_time
= (guint64
) g_get_monotonic_time ();
1760 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTPOINTS_CHANGED
]);
1768 mount_monitor_stop (void)
1772 g_file_monitor_cancel (fstab_monitor
);
1773 g_object_unref (fstab_monitor
);
1776 if (proc_mounts_watch_source
!= NULL
)
1778 g_source_destroy (proc_mounts_watch_source
);
1779 proc_mounts_watch_source
= NULL
;
1784 g_file_monitor_cancel (mtab_monitor
);
1785 g_object_unref (mtab_monitor
);
1788 g_list_free_full (mount_poller_mounts
, (GDestroyNotify
) g_unix_mount_free
);
1792 mount_monitor_start (void)
1796 if (get_fstab_file () != NULL
)
1798 file
= g_file_new_for_path (get_fstab_file ());
1799 fstab_monitor
= g_file_monitor_file (file
, 0, NULL
, NULL
);
1800 g_object_unref (file
);
1802 g_signal_connect (fstab_monitor
, "changed", (GCallback
)fstab_file_changed
, NULL
);
1805 if (get_mtab_monitor_file () != NULL
)
1807 const gchar
*mtab_path
;
1809 mtab_path
= get_mtab_monitor_file ();
1810 /* Monitoring files in /proc/ is special - can't just use GFileMonitor.
1811 * See 'man proc' for more details.
1813 if (g_str_has_prefix (mtab_path
, "/proc/"))
1815 GIOChannel
*proc_mounts_channel
;
1816 GError
*error
= NULL
;
1817 proc_mounts_channel
= g_io_channel_new_file (mtab_path
, "r", &error
);
1818 if (proc_mounts_channel
== NULL
)
1820 g_warning ("Error creating IO channel for %s: %s (%s, %d)", mtab_path
,
1821 error
->message
, g_quark_to_string (error
->domain
), error
->code
);
1822 g_error_free (error
);
1826 proc_mounts_watch_source
= g_io_create_watch (proc_mounts_channel
, G_IO_ERR
);
1827 g_source_set_callback (proc_mounts_watch_source
,
1828 (GSourceFunc
) proc_mounts_changed
,
1830 g_source_attach (proc_mounts_watch_source
,
1831 g_main_context_get_thread_default ());
1832 g_source_unref (proc_mounts_watch_source
);
1833 g_io_channel_unref (proc_mounts_channel
);
1838 file
= g_file_new_for_path (mtab_path
);
1839 mtab_monitor
= g_file_monitor_file (file
, 0, NULL
, NULL
);
1840 g_object_unref (file
);
1841 g_signal_connect (mtab_monitor
, "changed", (GCallback
)mtab_file_changed
, NULL
);
1846 proc_mounts_watch_source
= g_timeout_source_new_seconds (3);
1847 mount_poller_mounts
= _g_get_unix_mounts ();
1848 mount_poller_time
= (guint64
)g_get_monotonic_time ();
1849 g_source_set_callback (proc_mounts_watch_source
,
1850 mount_change_poller
,
1852 g_source_attach (proc_mounts_watch_source
,
1853 g_main_context_get_thread_default ());
1854 g_source_unref (proc_mounts_watch_source
);
1859 g_unix_mount_monitor_finalize (GObject
*object
)
1861 GUnixMountMonitor
*monitor
;
1863 monitor
= G_UNIX_MOUNT_MONITOR (object
);
1865 g_context_specific_group_remove (&mount_monitor_group
, monitor
->context
, monitor
, mount_monitor_stop
);
1867 G_OBJECT_CLASS (g_unix_mount_monitor_parent_class
)->finalize (object
);
1871 g_unix_mount_monitor_class_init (GUnixMountMonitorClass
*klass
)
1873 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
1875 gobject_class
->finalize
= g_unix_mount_monitor_finalize
;
1878 * GUnixMountMonitor::mounts-changed:
1879 * @monitor: the object on which the signal is emitted
1881 * Emitted when the unix mounts have changed.
1883 signals
[MOUNTS_CHANGED
] =
1884 g_signal_new (I_("mounts-changed"),
1885 G_TYPE_FROM_CLASS (klass
),
1889 g_cclosure_marshal_VOID__VOID
,
1893 * GUnixMountMonitor::mountpoints-changed:
1894 * @monitor: the object on which the signal is emitted
1896 * Emitted when the unix mount points have changed.
1898 signals
[MOUNTPOINTS_CHANGED
] =
1899 g_signal_new (I_("mountpoints-changed"),
1900 G_TYPE_FROM_CLASS (klass
),
1904 g_cclosure_marshal_VOID__VOID
,
1909 g_unix_mount_monitor_init (GUnixMountMonitor
*monitor
)
1914 * g_unix_mount_monitor_set_rate_limit:
1915 * @mount_monitor: a #GUnixMountMonitor
1916 * @limit_msec: a integer with the limit in milliseconds to
1919 * This function does nothing.
1921 * Before 2.44, this was a partially-effective way of controlling the
1922 * rate at which events would be reported under some uncommon
1923 * circumstances. Since @mount_monitor is a singleton, it also meant
1924 * that calling this function would have side effects for other users of
1929 * Deprecated:2.44:This function does nothing. Don't call it.
1932 g_unix_mount_monitor_set_rate_limit (GUnixMountMonitor
*mount_monitor
,
1938 * g_unix_mount_monitor_get:
1940 * Gets the #GUnixMountMonitor for the current thread-default main
1943 * The mount monitor can be used to monitor for changes to the list of
1944 * mounted filesystems as well as the list of mount points (ie: fstab
1947 * You must only call g_object_unref() on the return value from under
1948 * the same main context as you called this function.
1950 * Returns: (transfer full): the #GUnixMountMonitor.
1955 g_unix_mount_monitor_get (void)
1957 return g_context_specific_group_get (&mount_monitor_group
,
1958 G_TYPE_UNIX_MOUNT_MONITOR
,
1959 G_STRUCT_OFFSET(GUnixMountMonitor
, context
),
1960 mount_monitor_start
);
1964 * g_unix_mount_monitor_new:
1966 * Deprecated alias for g_unix_mount_monitor_get().
1968 * This function was never a true constructor, which is why it was
1971 * Returns: a #GUnixMountMonitor.
1973 * Deprecated:2.44:Use g_unix_mount_monitor_get() instead.
1976 g_unix_mount_monitor_new (void)
1978 return g_unix_mount_monitor_get ();
1981 /* GUnixMount {{{1 */
1983 * g_unix_mount_free:
1984 * @mount_entry: a #GUnixMountEntry.
1986 * Frees a unix mount.
1989 g_unix_mount_free (GUnixMountEntry
*mount_entry
)
1991 g_return_if_fail (mount_entry
!= NULL
);
1993 g_free (mount_entry
->mount_path
);
1994 g_free (mount_entry
->device_path
);
1995 g_free (mount_entry
->filesystem_type
);
1996 g_free (mount_entry
->options
);
1997 g_free (mount_entry
);
2001 * g_unix_mount_copy:
2002 * @mount_entry: a #GUnixMountEntry.
2004 * Makes a copy of @mount_entry.
2006 * Returns: (transfer full): a new #GUnixMountEntry
2011 g_unix_mount_copy (GUnixMountEntry
*mount_entry
)
2013 GUnixMountEntry
*copy
;
2015 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2017 copy
= g_new0 (GUnixMountEntry
, 1);
2018 copy
->mount_path
= g_strdup (mount_entry
->mount_path
);
2019 copy
->device_path
= g_strdup (mount_entry
->device_path
);
2020 copy
->filesystem_type
= g_strdup (mount_entry
->filesystem_type
);
2021 copy
->options
= g_strdup (mount_entry
->options
);
2022 copy
->is_read_only
= mount_entry
->is_read_only
;
2023 copy
->is_system_internal
= mount_entry
->is_system_internal
;
2029 * g_unix_mount_point_free:
2030 * @mount_point: unix mount point to free.
2032 * Frees a unix mount point.
2035 g_unix_mount_point_free (GUnixMountPoint
*mount_point
)
2037 g_return_if_fail (mount_point
!= NULL
);
2039 g_free (mount_point
->mount_path
);
2040 g_free (mount_point
->device_path
);
2041 g_free (mount_point
->filesystem_type
);
2042 g_free (mount_point
->options
);
2043 g_free (mount_point
);
2047 * g_unix_mount_point_copy:
2048 * @mount_point: a #GUnixMountPoint.
2050 * Makes a copy of @mount_point.
2052 * Returns: (transfer full): a new #GUnixMountPoint
2057 g_unix_mount_point_copy (GUnixMountPoint
*mount_point
)
2059 GUnixMountPoint
*copy
;
2061 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2063 copy
= g_new0 (GUnixMountPoint
, 1);
2064 copy
->mount_path
= g_strdup (mount_point
->mount_path
);
2065 copy
->device_path
= g_strdup (mount_point
->device_path
);
2066 copy
->filesystem_type
= g_strdup (mount_point
->filesystem_type
);
2067 copy
->options
= g_strdup (mount_point
->options
);
2068 copy
->is_read_only
= mount_point
->is_read_only
;
2069 copy
->is_user_mountable
= mount_point
->is_user_mountable
;
2070 copy
->is_loopback
= mount_point
->is_loopback
;
2076 * g_unix_mount_compare:
2077 * @mount1: first #GUnixMountEntry to compare.
2078 * @mount2: second #GUnixMountEntry to compare.
2080 * Compares two unix mounts.
2082 * Returns: 1, 0 or -1 if @mount1 is greater than, equal to,
2083 * or less than @mount2, respectively.
2086 g_unix_mount_compare (GUnixMountEntry
*mount1
,
2087 GUnixMountEntry
*mount2
)
2091 g_return_val_if_fail (mount1
!= NULL
&& mount2
!= NULL
, 0);
2093 res
= g_strcmp0 (mount1
->mount_path
, mount2
->mount_path
);
2097 res
= g_strcmp0 (mount1
->device_path
, mount2
->device_path
);
2101 res
= g_strcmp0 (mount1
->filesystem_type
, mount2
->filesystem_type
);
2105 res
= g_strcmp0 (mount1
->options
, mount2
->options
);
2109 res
= mount1
->is_read_only
- mount2
->is_read_only
;
2117 * g_unix_mount_get_mount_path:
2118 * @mount_entry: input #GUnixMountEntry to get the mount path for.
2120 * Gets the mount path for a unix mount.
2122 * Returns: (type filename): the mount path for @mount_entry.
2125 g_unix_mount_get_mount_path (GUnixMountEntry
*mount_entry
)
2127 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2129 return mount_entry
->mount_path
;
2133 * g_unix_mount_get_device_path:
2134 * @mount_entry: a #GUnixMount.
2136 * Gets the device path for a unix mount.
2138 * Returns: (type filename): a string containing the device path.
2141 g_unix_mount_get_device_path (GUnixMountEntry
*mount_entry
)
2143 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2145 return mount_entry
->device_path
;
2149 * g_unix_mount_get_fs_type:
2150 * @mount_entry: a #GUnixMount.
2152 * Gets the filesystem type for the unix mount.
2154 * Returns: a string containing the file system type.
2157 g_unix_mount_get_fs_type (GUnixMountEntry
*mount_entry
)
2159 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2161 return mount_entry
->filesystem_type
;
2165 * g_unix_mount_get_options:
2166 * @mount_entry: a #GUnixMountEntry.
2168 * Gets a comma-separated list of mount options for the unix mount. For example,
2169 * `rw,relatime,seclabel,data=ordered`.
2171 * This is similar to g_unix_mount_point_get_options(), but it takes
2172 * a #GUnixMountEntry as an argument.
2174 * Returns: (nullable): a string containing the options, or %NULL if not
2180 g_unix_mount_get_options (GUnixMountEntry
*mount_entry
)
2182 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2184 return mount_entry
->options
;
2188 * g_unix_mount_is_readonly:
2189 * @mount_entry: a #GUnixMount.
2191 * Checks if a unix mount is mounted read only.
2193 * Returns: %TRUE if @mount_entry is read only.
2196 g_unix_mount_is_readonly (GUnixMountEntry
*mount_entry
)
2198 g_return_val_if_fail (mount_entry
!= NULL
, FALSE
);
2200 return mount_entry
->is_read_only
;
2204 * g_unix_mount_is_system_internal:
2205 * @mount_entry: a #GUnixMount.
2207 * Checks if a Unix mount is a system mount. This is the Boolean OR of
2208 * g_unix_is_system_fs_type(), g_unix_is_system_device_path() and
2209 * g_unix_is_mount_path_system_internal() on @mount_entry’s properties.
2211 * The definition of what a ‘system’ mount entry is may change over time as new
2212 * file system types and device paths are ignored.
2214 * Returns: %TRUE if the unix mount is for a system path.
2217 g_unix_mount_is_system_internal (GUnixMountEntry
*mount_entry
)
2219 g_return_val_if_fail (mount_entry
!= NULL
, FALSE
);
2221 return mount_entry
->is_system_internal
;
2224 /* GUnixMountPoint {{{1 */
2226 * g_unix_mount_point_compare:
2227 * @mount1: a #GUnixMount.
2228 * @mount2: a #GUnixMount.
2230 * Compares two unix mount points.
2232 * Returns: 1, 0 or -1 if @mount1 is greater than, equal to,
2233 * or less than @mount2, respectively.
2236 g_unix_mount_point_compare (GUnixMountPoint
*mount1
,
2237 GUnixMountPoint
*mount2
)
2241 g_return_val_if_fail (mount1
!= NULL
&& mount2
!= NULL
, 0);
2243 res
= g_strcmp0 (mount1
->mount_path
, mount2
->mount_path
);
2247 res
= g_strcmp0 (mount1
->device_path
, mount2
->device_path
);
2251 res
= g_strcmp0 (mount1
->filesystem_type
, mount2
->filesystem_type
);
2255 res
= g_strcmp0 (mount1
->options
, mount2
->options
);
2259 res
= mount1
->is_read_only
- mount2
->is_read_only
;
2263 res
= mount1
->is_user_mountable
- mount2
->is_user_mountable
;
2267 res
= mount1
->is_loopback
- mount2
->is_loopback
;
2275 * g_unix_mount_point_get_mount_path:
2276 * @mount_point: a #GUnixMountPoint.
2278 * Gets the mount path for a unix mount point.
2280 * Returns: (type filename): a string containing the mount path.
2283 g_unix_mount_point_get_mount_path (GUnixMountPoint
*mount_point
)
2285 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2287 return mount_point
->mount_path
;
2291 * g_unix_mount_point_get_device_path:
2292 * @mount_point: a #GUnixMountPoint.
2294 * Gets the device path for a unix mount point.
2296 * Returns: (type filename): a string containing the device path.
2299 g_unix_mount_point_get_device_path (GUnixMountPoint
*mount_point
)
2301 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2303 return mount_point
->device_path
;
2307 * g_unix_mount_point_get_fs_type:
2308 * @mount_point: a #GUnixMountPoint.
2310 * Gets the file system type for the mount point.
2312 * Returns: a string containing the file system type.
2315 g_unix_mount_point_get_fs_type (GUnixMountPoint
*mount_point
)
2317 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2319 return mount_point
->filesystem_type
;
2323 * g_unix_mount_point_get_options:
2324 * @mount_point: a #GUnixMountPoint.
2326 * Gets the options for the mount point.
2328 * Returns: a string containing the options.
2333 g_unix_mount_point_get_options (GUnixMountPoint
*mount_point
)
2335 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2337 return mount_point
->options
;
2341 * g_unix_mount_point_is_readonly:
2342 * @mount_point: a #GUnixMountPoint.
2344 * Checks if a unix mount point is read only.
2346 * Returns: %TRUE if a mount point is read only.
2349 g_unix_mount_point_is_readonly (GUnixMountPoint
*mount_point
)
2351 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
2353 return mount_point
->is_read_only
;
2357 * g_unix_mount_point_is_user_mountable:
2358 * @mount_point: a #GUnixMountPoint.
2360 * Checks if a unix mount point is mountable by the user.
2362 * Returns: %TRUE if the mount point is user mountable.
2365 g_unix_mount_point_is_user_mountable (GUnixMountPoint
*mount_point
)
2367 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
2369 return mount_point
->is_user_mountable
;
2373 * g_unix_mount_point_is_loopback:
2374 * @mount_point: a #GUnixMountPoint.
2376 * Checks if a unix mount point is a loopback device.
2378 * Returns: %TRUE if the mount point is a loopback. %FALSE otherwise.
2381 g_unix_mount_point_is_loopback (GUnixMountPoint
*mount_point
)
2383 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
2385 return mount_point
->is_loopback
;
2388 static GUnixMountType
2389 guess_mount_type (const char *mount_path
,
2390 const char *device_path
,
2391 const char *filesystem_type
)
2393 GUnixMountType type
;
2396 type
= G_UNIX_MOUNT_TYPE_UNKNOWN
;
2398 if ((strcmp (filesystem_type
, "udf") == 0) ||
2399 (strcmp (filesystem_type
, "iso9660") == 0) ||
2400 (strcmp (filesystem_type
, "cd9660") == 0))
2401 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2402 else if ((strcmp (filesystem_type
, "nfs") == 0) ||
2403 (strcmp (filesystem_type
, "nfs4") == 0))
2404 type
= G_UNIX_MOUNT_TYPE_NFS
;
2405 else if (g_str_has_prefix (device_path
, "/vol/dev/diskette/") ||
2406 g_str_has_prefix (device_path
, "/dev/fd") ||
2407 g_str_has_prefix (device_path
, "/dev/floppy"))
2408 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
2409 else if (g_str_has_prefix (device_path
, "/dev/cdrom") ||
2410 g_str_has_prefix (device_path
, "/dev/acd") ||
2411 g_str_has_prefix (device_path
, "/dev/cd"))
2412 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2413 else if (g_str_has_prefix (device_path
, "/vol/"))
2415 const char *name
= mount_path
+ strlen ("/");
2417 if (g_str_has_prefix (name
, "cdrom"))
2418 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2419 else if (g_str_has_prefix (name
, "floppy") ||
2420 g_str_has_prefix (device_path
, "/vol/dev/diskette/"))
2421 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
2422 else if (g_str_has_prefix (name
, "rmdisk"))
2423 type
= G_UNIX_MOUNT_TYPE_ZIP
;
2424 else if (g_str_has_prefix (name
, "jaz"))
2425 type
= G_UNIX_MOUNT_TYPE_JAZ
;
2426 else if (g_str_has_prefix (name
, "memstick"))
2427 type
= G_UNIX_MOUNT_TYPE_MEMSTICK
;
2431 basename
= g_path_get_basename (mount_path
);
2433 if (g_str_has_prefix (basename
, "cdr") ||
2434 g_str_has_prefix (basename
, "cdwriter") ||
2435 g_str_has_prefix (basename
, "burn") ||
2436 g_str_has_prefix (basename
, "dvdr"))
2437 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2438 else if (g_str_has_prefix (basename
, "floppy"))
2439 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
2440 else if (g_str_has_prefix (basename
, "zip"))
2441 type
= G_UNIX_MOUNT_TYPE_ZIP
;
2442 else if (g_str_has_prefix (basename
, "jaz"))
2443 type
= G_UNIX_MOUNT_TYPE_JAZ
;
2444 else if (g_str_has_prefix (basename
, "camera"))
2445 type
= G_UNIX_MOUNT_TYPE_CAMERA
;
2446 else if (g_str_has_prefix (basename
, "memstick") ||
2447 g_str_has_prefix (basename
, "memory_stick") ||
2448 g_str_has_prefix (basename
, "ram"))
2449 type
= G_UNIX_MOUNT_TYPE_MEMSTICK
;
2450 else if (g_str_has_prefix (basename
, "compact_flash"))
2451 type
= G_UNIX_MOUNT_TYPE_CF
;
2452 else if (g_str_has_prefix (basename
, "smart_media"))
2453 type
= G_UNIX_MOUNT_TYPE_SM
;
2454 else if (g_str_has_prefix (basename
, "sd_mmc"))
2455 type
= G_UNIX_MOUNT_TYPE_SDMMC
;
2456 else if (g_str_has_prefix (basename
, "ipod"))
2457 type
= G_UNIX_MOUNT_TYPE_IPOD
;
2462 if (type
== G_UNIX_MOUNT_TYPE_UNKNOWN
)
2463 type
= G_UNIX_MOUNT_TYPE_HD
;
2469 * g_unix_mount_guess_type:
2470 * @mount_entry: a #GUnixMount.
2472 * Guesses the type of a unix mount. If the mount type cannot be
2473 * determined, returns %G_UNIX_MOUNT_TYPE_UNKNOWN.
2475 * Returns: a #GUnixMountType.
2477 static GUnixMountType
2478 g_unix_mount_guess_type (GUnixMountEntry
*mount_entry
)
2480 g_return_val_if_fail (mount_entry
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2481 g_return_val_if_fail (mount_entry
->mount_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2482 g_return_val_if_fail (mount_entry
->device_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2483 g_return_val_if_fail (mount_entry
->filesystem_type
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2485 return guess_mount_type (mount_entry
->mount_path
,
2486 mount_entry
->device_path
,
2487 mount_entry
->filesystem_type
);
2491 * g_unix_mount_point_guess_type:
2492 * @mount_point: a #GUnixMountPoint.
2494 * Guesses the type of a unix mount point.
2495 * If the mount type cannot be determined,
2496 * returns %G_UNIX_MOUNT_TYPE_UNKNOWN.
2498 * Returns: a #GUnixMountType.
2500 static GUnixMountType
2501 g_unix_mount_point_guess_type (GUnixMountPoint
*mount_point
)
2503 g_return_val_if_fail (mount_point
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2504 g_return_val_if_fail (mount_point
->mount_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2505 g_return_val_if_fail (mount_point
->device_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2506 g_return_val_if_fail (mount_point
->filesystem_type
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2508 return guess_mount_type (mount_point
->mount_path
,
2509 mount_point
->device_path
,
2510 mount_point
->filesystem_type
);
2514 type_to_icon (GUnixMountType type
, gboolean is_mount_point
, gboolean use_symbolic
)
2516 const char *icon_name
;
2520 case G_UNIX_MOUNT_TYPE_HD
:
2522 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2524 icon_name
= use_symbolic
? "drive-harddisk-symbolic" : "drive-harddisk";
2526 case G_UNIX_MOUNT_TYPE_FLOPPY
:
2527 case G_UNIX_MOUNT_TYPE_ZIP
:
2528 case G_UNIX_MOUNT_TYPE_JAZ
:
2530 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2532 icon_name
= use_symbolic
? "media-removable-symbolic" : "media-floppy";
2534 case G_UNIX_MOUNT_TYPE_CDROM
:
2536 icon_name
= use_symbolic
? "drive-optical-symbolic" : "drive-optical";
2538 icon_name
= use_symbolic
? "media-optical-symbolic" : "media-optical";
2540 case G_UNIX_MOUNT_TYPE_NFS
:
2541 icon_name
= use_symbolic
? "folder-remote-symbolic" : "folder-remote";
2543 case G_UNIX_MOUNT_TYPE_MEMSTICK
:
2545 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2547 icon_name
= use_symbolic
? "media-removable-symbolic" : "media-flash";
2549 case G_UNIX_MOUNT_TYPE_CAMERA
:
2551 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2553 icon_name
= use_symbolic
? "camera-photo-symbolic" : "camera-photo";
2555 case G_UNIX_MOUNT_TYPE_IPOD
:
2557 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2559 icon_name
= use_symbolic
? "multimedia-player-symbolic" : "multimedia-player";
2561 case G_UNIX_MOUNT_TYPE_UNKNOWN
:
2564 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2566 icon_name
= use_symbolic
? "drive-harddisk-symbolic" : "drive-harddisk";
2574 * g_unix_mount_guess_name:
2575 * @mount_entry: a #GUnixMountEntry
2577 * Guesses the name of a Unix mount.
2578 * The result is a translated string.
2580 * Returns: A newly allocated string that must
2581 * be freed with g_free()
2584 g_unix_mount_guess_name (GUnixMountEntry
*mount_entry
)
2588 if (strcmp (mount_entry
->mount_path
, "/") == 0)
2589 name
= g_strdup (_("Filesystem root"));
2591 name
= g_filename_display_basename (mount_entry
->mount_path
);
2597 * g_unix_mount_guess_icon:
2598 * @mount_entry: a #GUnixMountEntry
2600 * Guesses the icon of a Unix mount.
2602 * Returns: (transfer full): a #GIcon
2605 g_unix_mount_guess_icon (GUnixMountEntry
*mount_entry
)
2607 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_guess_type (mount_entry
), FALSE
, FALSE
));
2611 * g_unix_mount_guess_symbolic_icon:
2612 * @mount_entry: a #GUnixMountEntry
2614 * Guesses the symbolic icon of a Unix mount.
2616 * Returns: (transfer full): a #GIcon
2621 g_unix_mount_guess_symbolic_icon (GUnixMountEntry
*mount_entry
)
2623 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_guess_type (mount_entry
), FALSE
, TRUE
));
2627 * g_unix_mount_point_guess_name:
2628 * @mount_point: a #GUnixMountPoint
2630 * Guesses the name of a Unix mount point.
2631 * The result is a translated string.
2633 * Returns: A newly allocated string that must
2634 * be freed with g_free()
2637 g_unix_mount_point_guess_name (GUnixMountPoint
*mount_point
)
2641 if (strcmp (mount_point
->mount_path
, "/") == 0)
2642 name
= g_strdup (_("Filesystem root"));
2644 name
= g_filename_display_basename (mount_point
->mount_path
);
2650 * g_unix_mount_point_guess_icon:
2651 * @mount_point: a #GUnixMountPoint
2653 * Guesses the icon of a Unix mount point.
2655 * Returns: (transfer full): a #GIcon
2658 g_unix_mount_point_guess_icon (GUnixMountPoint
*mount_point
)
2660 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_point_guess_type (mount_point
), TRUE
, FALSE
));
2664 * g_unix_mount_point_guess_symbolic_icon:
2665 * @mount_point: a #GUnixMountPoint
2667 * Guesses the symbolic icon of a Unix mount point.
2669 * Returns: (transfer full): a #GIcon
2674 g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint
*mount_point
)
2676 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_point_guess_type (mount_point
), TRUE
, TRUE
));
2680 * g_unix_mount_guess_can_eject:
2681 * @mount_entry: a #GUnixMountEntry
2683 * Guesses whether a Unix mount can be ejected.
2685 * Returns: %TRUE if @mount_entry is deemed to be ejectable.
2688 g_unix_mount_guess_can_eject (GUnixMountEntry
*mount_entry
)
2690 GUnixMountType guessed_type
;
2692 guessed_type
= g_unix_mount_guess_type (mount_entry
);
2693 if (guessed_type
== G_UNIX_MOUNT_TYPE_IPOD
||
2694 guessed_type
== G_UNIX_MOUNT_TYPE_CDROM
)
2701 * g_unix_mount_guess_should_display:
2702 * @mount_entry: a #GUnixMountEntry
2704 * Guesses whether a Unix mount should be displayed in the UI.
2706 * Returns: %TRUE if @mount_entry is deemed to be displayable.
2709 g_unix_mount_guess_should_display (GUnixMountEntry
*mount_entry
)
2711 const char *mount_path
;
2712 const gchar
*user_name
;
2713 gsize user_name_len
;
2715 /* Never display internal mountpoints */
2716 if (g_unix_mount_is_system_internal (mount_entry
))
2719 /* Only display things in /media (which are generally user mountable)
2720 and home dir (fuse stuff) and /run/media/$USER */
2721 mount_path
= mount_entry
->mount_path
;
2722 if (mount_path
!= NULL
)
2724 const gboolean running_as_root
= (getuid () == 0);
2725 gboolean is_in_runtime_dir
= FALSE
;
2727 /* Hide mounts within a dot path, suppose it was a purpose to hide this mount */
2728 if (g_strstr_len (mount_path
, -1, "/.") != NULL
)
2731 /* Check /run/media/$USER/. If running as root, display any mounts below
2733 if (running_as_root
)
2735 if (strncmp (mount_path
, "/run/media/", strlen ("/run/media/")) == 0)
2736 is_in_runtime_dir
= TRUE
;
2740 user_name
= g_get_user_name ();
2741 user_name_len
= strlen (user_name
);
2742 if (strncmp (mount_path
, "/run/media/", strlen ("/run/media/")) == 0 &&
2743 strncmp (mount_path
+ strlen ("/run/media/"), user_name
, user_name_len
) == 0 &&
2744 mount_path
[strlen ("/run/media/") + user_name_len
] == '/')
2745 is_in_runtime_dir
= TRUE
;
2748 if (is_in_runtime_dir
|| g_str_has_prefix (mount_path
, "/media/"))
2751 /* Avoid displaying mounts that are not accessible to the user.
2753 * See http://bugzilla.gnome.org/show_bug.cgi?id=526320 for why we
2754 * want to avoid g_access() for mount points which can potentially
2755 * block or fail stat()'ing, such as network mounts.
2757 path
= g_path_get_dirname (mount_path
);
2758 if (g_str_has_prefix (path
, "/media/"))
2760 if (g_access (path
, R_OK
|X_OK
) != 0)
2768 if (mount_entry
->device_path
&& mount_entry
->device_path
[0] == '/')
2771 if (g_stat (mount_entry
->device_path
, &st
) == 0 &&
2772 S_ISBLK(st
.st_mode
) &&
2773 g_access (mount_path
, R_OK
|X_OK
) != 0)
2779 if (g_str_has_prefix (mount_path
, g_get_home_dir ()) &&
2780 mount_path
[strlen (g_get_home_dir())] == G_DIR_SEPARATOR
)
2788 * g_unix_mount_point_guess_can_eject:
2789 * @mount_point: a #GUnixMountPoint
2791 * Guesses whether a Unix mount point can be ejected.
2793 * Returns: %TRUE if @mount_point is deemed to be ejectable.
2796 g_unix_mount_point_guess_can_eject (GUnixMountPoint
*mount_point
)
2798 GUnixMountType guessed_type
;
2800 guessed_type
= g_unix_mount_point_guess_type (mount_point
);
2801 if (guessed_type
== G_UNIX_MOUNT_TYPE_IPOD
||
2802 guessed_type
== G_UNIX_MOUNT_TYPE_CDROM
)
2808 /* Utility functions {{{1 */
2810 #ifdef HAVE_MNTENT_H
2811 /* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 */
2813 _canonicalize_filename (gchar
*filename
)
2816 gboolean last_was_slash
= FALSE
;
2823 if (*p
== G_DIR_SEPARATOR
)
2825 if (!last_was_slash
)
2826 *q
++ = G_DIR_SEPARATOR
;
2828 last_was_slash
= TRUE
;
2832 if (last_was_slash
&& *p
== '.')
2834 if (*(p
+ 1) == G_DIR_SEPARATOR
||
2837 if (*(p
+ 1) == '\0')
2842 else if (*(p
+ 1) == '.' &&
2843 (*(p
+ 2) == G_DIR_SEPARATOR
||
2846 if (q
> filename
+ 1)
2849 while (q
> filename
+ 1 &&
2850 *(q
- 1) != G_DIR_SEPARATOR
)
2854 if (*(p
+ 2) == '\0')
2862 last_was_slash
= FALSE
;
2868 last_was_slash
= FALSE
;
2875 if (q
> filename
+ 1 && *(q
- 1) == G_DIR_SEPARATOR
)
2882 _resolve_symlink (const char *file
)
2890 f
= g_strdup (file
);
2892 while (g_file_test (f
, G_FILE_TEST_IS_SYMLINK
))
2894 link
= g_file_read_link (f
, &error
);
2897 g_error_free (error
);
2903 dir
= g_path_get_dirname (f
);
2904 f1
= g_strdup_printf ("%s/%s", dir
, link
);
2913 _canonicalize_filename (f
);
2918 _resolve_dev_root (void)
2920 static gboolean have_real_dev_root
= FALSE
;
2921 static char real_dev_root
[256];
2922 struct stat statbuf
;
2924 /* see if it's cached already */
2925 if (have_real_dev_root
)
2928 /* otherwise we're going to find it right away.. */
2929 have_real_dev_root
= TRUE
;
2931 if (stat ("/dev/root", &statbuf
) == 0)
2933 if (! S_ISLNK (statbuf
.st_mode
))
2935 dev_t root_dev
= statbuf
.st_dev
;
2938 /* see if device with similar major:minor as /dev/root is mention
2939 * in /etc/mtab (it usually is)
2941 f
= fopen ("/etc/mtab", "r");
2944 struct mntent
*entp
;
2945 #ifdef HAVE_GETMNTENT_R
2948 while ((entp
= getmntent_r (f
, &ent
, buf
, sizeof (buf
))) != NULL
)
2952 while ((entp
= getmntent (f
)) != NULL
)
2955 if (stat (entp
->mnt_fsname
, &statbuf
) == 0 &&
2956 statbuf
.st_dev
== root_dev
)
2958 strncpy (real_dev_root
, entp
->mnt_fsname
, sizeof (real_dev_root
) - 1);
2959 real_dev_root
[sizeof (real_dev_root
) - 1] = '\0';
2967 #ifndef HAVE_GETMNTENT_R
2968 G_UNLOCK (getmntent
);
2972 /* no, that didn't work.. next we could scan /dev ... but I digress.. */
2978 resolved
= _resolve_symlink ("/dev/root");
2979 if (resolved
!= NULL
)
2981 strncpy (real_dev_root
, resolved
, sizeof (real_dev_root
) - 1);
2982 real_dev_root
[sizeof (real_dev_root
) - 1] = '\0';
2990 strcpy (real_dev_root
, "/dev/root");
2993 return real_dev_root
;
2998 /* vim:set foldmethod=marker: */