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
[] = {
354 g_return_val_if_fail (fs_type
!= NULL
&& *fs_type
!= '\0', FALSE
);
356 return is_in (fs_type
, ignore_fs
);
360 * g_unix_is_system_device_path:
361 * @device_path: a device path, e.g. `/dev/loop0` or `nfsd`
363 * Determines if @device_path is considered a block device path which is only
364 * used in implementation of the OS. This is primarily used for hiding
365 * mounted volumes that are intended as APIs for programs to read, and system
366 * administrators at a shell; rather than something that should, for example,
367 * appear in a GUI. For example, the Linux `/proc` filesystem.
369 * The list of device paths considered ‘system’ ones may change over time.
371 * Returns: %TRUE if @device_path is considered an implementation detail of
376 g_unix_is_system_device_path (const char *device_path
)
378 const char *ignore_devices
[] = {
388 g_return_val_if_fail (device_path
!= NULL
&& *device_path
!= '\0', FALSE
);
390 return is_in (device_path
, ignore_devices
);
394 guess_system_internal (const char *mountpoint
,
398 if (g_unix_is_system_fs_type (fs
))
401 if (g_unix_is_system_device_path (device
))
404 if (g_unix_is_mount_path_system_internal (mountpoint
))
410 /* GUnixMounts (ie: mtab) implementations {{{1 */
412 static GUnixMountEntry
*
413 create_unix_mount_entry (const char *device_path
,
414 const char *mount_path
,
415 const char *filesystem_type
,
417 gboolean is_read_only
)
419 GUnixMountEntry
*mount_entry
= NULL
;
421 mount_entry
= g_new0 (GUnixMountEntry
, 1);
422 mount_entry
->device_path
= g_strdup (device_path
);
423 mount_entry
->mount_path
= g_strdup (mount_path
);
424 mount_entry
->filesystem_type
= g_strdup (filesystem_type
);
425 mount_entry
->options
= g_strdup (options
);
426 mount_entry
->is_read_only
= is_read_only
;
428 mount_entry
->is_system_internal
=
429 guess_system_internal (mount_entry
->mount_path
,
430 mount_entry
->filesystem_type
,
431 mount_entry
->device_path
);
435 static GUnixMountPoint
*
436 create_unix_mount_point (const char *device_path
,
437 const char *mount_path
,
438 const char *filesystem_type
,
440 gboolean is_read_only
,
441 gboolean is_user_mountable
,
442 gboolean is_loopback
)
444 GUnixMountPoint
*mount_point
= NULL
;
446 mount_point
= g_new0 (GUnixMountPoint
, 1);
447 mount_point
->device_path
= g_strdup (device_path
);
448 mount_point
->mount_path
= g_strdup (mount_path
);
449 mount_point
->filesystem_type
= g_strdup (filesystem_type
);
450 mount_point
->options
= g_strdup (options
);
451 mount_point
->is_read_only
= is_read_only
;
452 mount_point
->is_user_mountable
= is_user_mountable
;
453 mount_point
->is_loopback
= is_loopback
;
458 /* mntent.h (Linux, GNU, NSS) {{{2 */
463 /* For documentation on /proc/self/mountinfo see
464 * http://www.kernel.org/doc/Documentation/filesystems/proc.txt
466 #define PROC_MOUNTINFO_PATH "/proc/self/mountinfo"
469 _g_get_unix_mounts (void)
471 struct libmnt_table
*table
= NULL
;
472 struct libmnt_iter
* iter
= NULL
;
473 struct libmnt_fs
*fs
= NULL
;
474 GUnixMountEntry
*mount_entry
= NULL
;
475 GList
*return_list
= NULL
;
477 table
= mnt_new_table ();
478 if (mnt_table_parse_mtab (table
, NULL
) < 0)
481 iter
= mnt_new_iter (MNT_ITER_FORWARD
);
482 while (mnt_table_next_fs (table
, iter
, &fs
) == 0)
484 const char *device_path
= NULL
;
485 char *mount_options
= NULL
;
486 unsigned long mount_flags
= 0;
487 gboolean is_read_only
= FALSE
;
489 device_path
= mnt_fs_get_source (fs
);
490 if (g_strcmp0 (device_path
, "/dev/root") == 0)
491 device_path
= _resolve_dev_root ();
493 mount_options
= mnt_fs_strdup_options (fs
);
496 mnt_optstr_get_flags (mount_options
, &mount_flags
, mnt_get_builtin_optmap (MNT_LINUX_MAP
));
497 g_free (mount_options
);
499 is_read_only
= (mount_flags
& MS_RDONLY
) ? TRUE
: FALSE
;
501 mount_entry
= create_unix_mount_entry (device_path
,
502 mnt_fs_get_target (fs
),
503 mnt_fs_get_fstype (fs
),
504 mnt_fs_get_options (fs
),
507 return_list
= g_list_prepend (return_list
, mount_entry
);
509 mnt_free_iter (iter
);
512 mnt_free_table (table
);
514 return g_list_reverse (return_list
);
520 get_mtab_read_file (void)
524 return "/proc/mounts";
526 return _PATH_MOUNTED
;
533 #ifndef HAVE_GETMNTENT_R
534 G_LOCK_DEFINE_STATIC(getmntent
);
538 _g_get_unix_mounts (void)
540 #ifdef HAVE_GETMNTENT_R
544 struct mntent
*mntent
;
546 const char *read_file
;
547 GUnixMountEntry
*mount_entry
;
548 GHashTable
*mounts_hash
;
551 read_file
= get_mtab_read_file ();
553 file
= setmntent (read_file
, "r");
559 mounts_hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
561 #ifdef HAVE_GETMNTENT_R
562 while ((mntent
= getmntent_r (file
, &ent
, buf
, sizeof (buf
))) != NULL
)
565 while ((mntent
= getmntent (file
)) != NULL
)
568 const char *device_path
= NULL
;
569 gboolean is_read_only
= FALSE
;
571 /* ignore any mnt_fsname that is repeated and begins with a '/'
573 * We do this to avoid being fooled by --bind mounts, since
574 * these have the same device as the location they bind to.
575 * It's not an ideal solution to the problem, but it's likely that
576 * the most important mountpoint is first and the --bind ones after
577 * that aren't as important. So it should work.
579 * The '/' is to handle procfs, tmpfs and other no device mounts.
581 if (mntent
->mnt_fsname
!= NULL
&&
582 mntent
->mnt_fsname
[0] == '/' &&
583 g_hash_table_lookup (mounts_hash
, mntent
->mnt_fsname
))
586 if (g_strcmp0 (mntent
->mnt_fsname
, "/dev/root") == 0)
587 device_path
= _resolve_dev_root ();
589 device_path
= mntent
->mnt_fsname
;
591 #if defined (HAVE_HASMNTOPT)
592 if (hasmntopt (mntent
, MNTOPT_RO
) != NULL
)
596 mount_entry
= create_unix_mount_entry (device_path
,
602 g_hash_table_insert (mounts_hash
,
603 mount_entry
->device_path
,
604 mount_entry
->device_path
);
606 return_list
= g_list_prepend (return_list
, mount_entry
);
608 g_hash_table_destroy (mounts_hash
);
612 #ifndef HAVE_GETMNTENT_R
613 G_UNLOCK (getmntent
);
616 return g_list_reverse (return_list
);
619 #endif /* HAVE_LIBMOUNT */
622 get_mtab_monitor_file (void)
624 static const char *mountinfo_path
= NULL
;
629 if (mountinfo_path
!= NULL
)
630 return mountinfo_path
;
633 /* The mtab file is still used by some distros, so it has to be monitored in
634 * order to avoid races between g_unix_mounts_get and "mounts-changed" signal:
635 * https://bugzilla.gnome.org/show_bug.cgi?id=782814
637 if (mnt_has_regular_mtab (&mountinfo_path
, NULL
))
639 return mountinfo_path
;
642 if (stat (PROC_MOUNTINFO_PATH
, &buf
) == 0)
644 mountinfo_path
= PROC_MOUNTINFO_PATH
;
645 return mountinfo_path
;
651 mountinfo_path
= "/proc/mounts";
653 mountinfo_path
= _PATH_MOUNTED
;
656 mountinfo_path
= "/etc/mtab";
659 return mountinfo_path
;
663 #elif defined (HAVE_SYS_MNTTAB_H)
665 G_LOCK_DEFINE_STATIC(getmntent
);
668 get_mtab_read_file (void)
671 return _PATH_MOUNTED
;
673 return "/etc/mnttab";
678 get_mtab_monitor_file (void)
680 return get_mtab_read_file ();
684 _g_get_unix_mounts (void)
686 struct mnttab mntent
;
688 const char *read_file
;
689 GUnixMountEntry
*mount_entry
;
692 read_file
= get_mtab_read_file ();
694 file
= setmntent (read_file
, "r");
701 while (! getmntent (file
, &mntent
))
703 gboolean is_read_only
= FALSE
;
705 #if defined (HAVE_HASMNTOPT)
706 if (hasmntopt (&mntent
, MNTOPT_RO
) != NULL
)
710 mount_entry
= create_unix_mount_entry (mntent
.mnt_special
,
716 return_list
= g_list_prepend (return_list
, mount_entry
);
721 G_UNLOCK (getmntent
);
723 return g_list_reverse (return_list
);
726 /* mntctl.h (AIX) {{{2 */
727 #elif defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
730 get_mtab_monitor_file (void)
736 _g_get_unix_mounts (void)
738 struct vfs_ent
*fs_info
;
739 struct vmount
*vmount_info
;
741 unsigned int vmount_size
;
745 if (mntctl (MCTL_QUERY
, sizeof (vmount_size
), &vmount_size
) != 0)
747 g_warning ("Unable to know the number of mounted volumes");
752 vmount_info
= (struct vmount
*)g_malloc (vmount_size
);
754 vmount_number
= mntctl (MCTL_QUERY
, vmount_size
, vmount_info
);
756 if (vmount_info
->vmt_revision
!= VMT_REVISION
)
757 g_warning ("Bad vmount structure revision number, want %d, got %d", VMT_REVISION
, vmount_info
->vmt_revision
);
759 if (vmount_number
< 0)
761 g_warning ("Unable to recover mounted volumes information");
763 g_free (vmount_info
);
768 while (vmount_number
> 0)
770 gboolean is_read_only
= FALSE
;
772 fs_info
= getvfsbytype (vmount_info
->vmt_gfstype
);
774 /* is_removable = (vmount_info->vmt_flags & MNT_REMOVABLE) ? 1 : 0; */
775 is_read_only
= (vmount_info
->vmt_flags
& MNT_READONLY
) ? 1 : 0;
777 mount_entry
= create_unix_mount_entry (vmt2dataptr (vmount_info
, VMT_OBJECT
),
778 vmt2dataptr (vmount_info
, VMT_STUB
),
779 fs_info
== NULL
? "unknown" : fs_info
->vfsent_name
,
783 return_list
= g_list_prepend (return_list
, mount_entry
);
785 vmount_info
= (struct vmount
*)( (char*)vmount_info
786 + vmount_info
->vmt_length
);
790 g_free (vmount_info
);
792 return g_list_reverse (return_list
);
795 /* sys/mount.h {{{2 */
796 #elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
799 get_mtab_monitor_file (void)
805 _g_get_unix_mounts (void)
807 #if defined(USE_STATVFS)
808 struct statvfs
*mntent
= NULL
;
809 #elif defined(USE_STATFS)
810 struct statfs
*mntent
= NULL
;
812 #error statfs juggling failed
816 GUnixMountEntry
*mount_entry
;
819 /* Pass NOWAIT to avoid blocking trying to update NFS mounts. */
820 #if defined(USE_STATVFS) && defined(HAVE_GETVFSSTAT)
821 num_mounts
= getvfsstat (NULL
, 0, ST_NOWAIT
);
822 #elif defined(USE_STATFS) && defined(HAVE_GETFSSTAT)
823 num_mounts
= getfsstat (NULL
, 0, MNT_NOWAIT
);
825 if (num_mounts
== -1)
828 bufsize
= num_mounts
* sizeof (*mntent
);
829 mntent
= g_malloc (bufsize
);
830 #if defined(USE_STATVFS) && defined(HAVE_GETVFSSTAT)
831 num_mounts
= getvfsstat (mntent
, bufsize
, ST_NOWAIT
);
832 #elif defined(USE_STATFS) && defined(HAVE_GETFSSTAT)
833 num_mounts
= getfsstat (mntent
, bufsize
, MNT_NOWAIT
);
835 if (num_mounts
== -1)
840 for (i
= 0; i
< num_mounts
; i
++)
842 gboolean is_read_only
= FALSE
;
844 #if defined(USE_STATVFS)
845 if (mntent
[i
].f_flag
& ST_RDONLY
)
846 #elif defined(USE_STATFS)
847 if (mntent
[i
].f_flags
& MNT_RDONLY
)
849 #error statfs juggling failed
853 mount_entry
= create_unix_mount_entry (mntent
[i
].f_mntfromname
,
854 mntent
[i
].f_mntonname
,
855 mntent
[i
].f_fstypename
,
859 return_list
= g_list_prepend (return_list
, mount_entry
);
864 return g_list_reverse (return_list
);
868 #elif defined(__INTERIX)
871 get_mtab_monitor_file (void)
877 _g_get_unix_mounts (void)
880 GList
* return_list
= NULL
;
881 char filename
[9 + NAME_MAX
];
883 dirp
= opendir ("/dev/fs");
886 g_warning ("unable to read /dev/fs!");
892 struct statvfs statbuf
;
894 struct dirent
* result
;
896 if (readdir_r (dirp
, &entry
, &result
) || result
== NULL
)
899 strcpy (filename
, "/dev/fs/");
900 strcat (filename
, entry
.d_name
);
902 if (statvfs (filename
, &statbuf
) == 0)
904 GUnixMountEntry
* mount_entry
= g_new0(GUnixMountEntry
, 1);
906 mount_entry
->mount_path
= g_strdup (statbuf
.f_mntonname
);
907 mount_entry
->device_path
= g_strdup (statbuf
.f_mntfromname
);
908 mount_entry
->filesystem_type
= g_strdup (statbuf
.f_fstypename
);
910 if (statbuf
.f_flag
& ST_RDONLY
)
911 mount_entry
->is_read_only
= TRUE
;
913 return_list
= g_list_prepend(return_list
, mount_entry
);
917 return_list
= g_list_reverse (return_list
);
924 /* Common code {{{2 */
926 #error No _g_get_unix_mounts() implementation for system
929 /* GUnixMountPoints (ie: fstab) implementations {{{1 */
931 /* _g_get_unix_mount_points():
933 * don't return swap and ignore mounts.
937 get_fstab_file (void)
940 return (char *) mnt_get_fstab_path ();
942 #if defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
944 return "/etc/filesystems";
945 #elif defined(_PATH_MNTTAB)
947 #elif defined(VFSTAB)
955 /* mntent.h (Linux, GNU, NSS) {{{2 */
961 _g_get_unix_mount_points (void)
963 struct libmnt_table
*table
= NULL
;
964 struct libmnt_iter
* iter
= NULL
;
965 struct libmnt_fs
*fs
= NULL
;
966 GUnixMountPoint
*mount_point
= NULL
;
967 GList
*return_list
= NULL
;
969 table
= mnt_new_table ();
970 if (mnt_table_parse_fstab (table
, NULL
) < 0)
973 iter
= mnt_new_iter (MNT_ITER_FORWARD
);
974 while (mnt_table_next_fs (table
, iter
, &fs
) == 0)
976 const char *device_path
= NULL
;
977 const char *mount_path
= NULL
;
978 const char *mount_fstype
= NULL
;
979 char *mount_options
= NULL
;
980 gboolean is_read_only
= FALSE
;
981 gboolean is_user_mountable
= FALSE
;
982 gboolean is_loopback
= FALSE
;
984 mount_path
= mnt_fs_get_target (fs
);
985 if ((strcmp (mount_path
, "ignore") == 0) ||
986 (strcmp (mount_path
, "swap") == 0) ||
987 (strcmp (mount_path
, "none") == 0))
990 mount_fstype
= mnt_fs_get_fstype (fs
);
991 mount_options
= mnt_fs_strdup_options (fs
);
994 unsigned long mount_flags
= 0;
995 unsigned long userspace_flags
= 0;
997 mnt_optstr_get_flags (mount_options
, &mount_flags
, mnt_get_builtin_optmap (MNT_LINUX_MAP
));
998 mnt_optstr_get_flags (mount_options
, &userspace_flags
, mnt_get_builtin_optmap (MNT_USERSPACE_MAP
));
1000 /* We ignore bind fstab entries, as we ignore bind mounts anyway */
1001 if (mount_flags
& MS_BIND
)
1003 g_free (mount_options
);
1007 is_read_only
= (mount_flags
& MS_RDONLY
) != 0;
1008 is_loopback
= (userspace_flags
& MNT_MS_LOOP
) != 0;
1010 if ((mount_fstype
!= NULL
&& g_strcmp0 ("supermount", mount_fstype
) == 0) ||
1011 ((userspace_flags
& MNT_MS_USER
) &&
1012 (g_strstr_len (mount_options
, -1, "user_xattr") == NULL
)) ||
1013 (g_strstr_len (mount_options
, -1, "pamconsole") == NULL
) ||
1014 (userspace_flags
& MNT_MS_USERS
) ||
1015 (userspace_flags
& MNT_MS_OWNER
))
1017 is_user_mountable
= TRUE
;
1021 device_path
= mnt_fs_get_source (fs
);
1022 if (g_strcmp0 (device_path
, "/dev/root") == 0)
1023 device_path
= _resolve_dev_root ();
1025 mount_point
= create_unix_mount_point (device_path
,
1033 g_free (mount_options
);
1035 return_list
= g_list_prepend (return_list
, mount_point
);
1037 mnt_free_iter (iter
);
1040 mnt_free_table (table
);
1042 return g_list_reverse (return_list
);
1048 _g_get_unix_mount_points (void)
1050 #ifdef HAVE_GETMNTENT_R
1054 struct mntent
*mntent
;
1057 GUnixMountPoint
*mount_point
;
1060 read_file
= get_fstab_file ();
1062 file
= setmntent (read_file
, "r");
1068 #ifdef HAVE_GETMNTENT_R
1069 while ((mntent
= getmntent_r (file
, &ent
, buf
, sizeof (buf
))) != NULL
)
1072 while ((mntent
= getmntent (file
)) != NULL
)
1075 const char *device_path
= NULL
;
1076 gboolean is_read_only
= FALSE
;
1077 gboolean is_user_mountable
= FALSE
;
1078 gboolean is_loopback
= FALSE
;
1080 if ((strcmp (mntent
->mnt_dir
, "ignore") == 0) ||
1081 (strcmp (mntent
->mnt_dir
, "swap") == 0) ||
1082 (strcmp (mntent
->mnt_dir
, "none") == 0))
1085 #ifdef HAVE_HASMNTOPT
1086 /* We ignore bind fstab entries, as we ignore bind mounts anyway */
1087 if (hasmntopt (mntent
, "bind"))
1091 if (strcmp (mntent
->mnt_fsname
, "/dev/root") == 0)
1092 device_path
= _resolve_dev_root ();
1094 device_path
= mntent
->mnt_fsname
;
1096 #ifdef HAVE_HASMNTOPT
1097 if (hasmntopt (mntent
, MNTOPT_RO
) != NULL
)
1098 is_read_only
= TRUE
;
1100 if (hasmntopt (mntent
, "loop") != NULL
)
1105 if ((mntent
->mnt_type
!= NULL
&& strcmp ("supermount", mntent
->mnt_type
) == 0)
1106 #ifdef HAVE_HASMNTOPT
1107 || (hasmntopt (mntent
, "user") != NULL
1108 && hasmntopt (mntent
, "user") != hasmntopt (mntent
, "user_xattr"))
1109 || hasmntopt (mntent
, "pamconsole") != NULL
1110 || hasmntopt (mntent
, "users") != NULL
1111 || hasmntopt (mntent
, "owner") != NULL
1114 is_user_mountable
= TRUE
;
1116 mount_point
= create_unix_mount_point (device_path
,
1124 return_list
= g_list_prepend (return_list
, mount_point
);
1129 #ifndef HAVE_GETMNTENT_R
1130 G_UNLOCK (getmntent
);
1133 return g_list_reverse (return_list
);
1136 #endif /* HAVE_LIBMOUNT */
1139 #elif defined (HAVE_SYS_MNTTAB_H)
1142 _g_get_unix_mount_points (void)
1144 struct mnttab mntent
;
1147 GUnixMountPoint
*mount_point
;
1150 read_file
= get_fstab_file ();
1152 file
= setmntent (read_file
, "r");
1159 while (! getmntent (file
, &mntent
))
1161 gboolean is_read_only
= FALSE
;
1162 gboolean is_user_mountable
= FALSE
;
1163 gboolean is_loopback
= FALSE
;
1165 if ((strcmp (mntent
.mnt_mountp
, "ignore") == 0) ||
1166 (strcmp (mntent
.mnt_mountp
, "swap") == 0) ||
1167 (strcmp (mntent
.mnt_mountp
, "none") == 0))
1170 #ifdef HAVE_HASMNTOPT
1171 if (hasmntopt (&mntent
, MNTOPT_RO
) != NULL
)
1172 is_read_only
= TRUE
;
1174 if (hasmntopt (&mntent
, "lofs") != NULL
)
1178 if ((mntent
.mnt_fstype
!= NULL
)
1179 #ifdef HAVE_HASMNTOPT
1180 || (hasmntopt (&mntent
, "user") != NULL
1181 && hasmntopt (&mntent
, "user") != hasmntopt (&mntent
, "user_xattr"))
1182 || hasmntopt (&mntent
, "pamconsole") != NULL
1183 || hasmntopt (&mntent
, "users") != NULL
1184 || hasmntopt (&mntent
, "owner") != NULL
1187 is_user_mountable
= TRUE
;
1189 mount_point
= create_unix_mount_point (mntent
.mnt_special
,
1197 return_list
= g_list_prepend (return_list
, mount_point
);
1201 G_UNLOCK (getmntent
);
1203 return g_list_reverse (return_list
);
1206 /* mntctl.h (AIX) {{{2 */
1207 #elif defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
1209 /* functions to parse /etc/filesystems on aix */
1211 /* read character, ignoring comments (begin with '*', end with '\n' */
1213 aix_fs_getc (FILE *fd
)
1217 while ((c
= getc (fd
)) == '*')
1219 while (((c
= getc (fd
)) != '\n') && (c
!= EOF
))
1224 /* eat all continuous spaces in a file */
1226 aix_fs_ignorespace (FILE *fd
)
1230 while ((c
= aix_fs_getc (fd
)) != EOF
)
1232 if (!g_ascii_isspace (c
))
1242 /* read one word from file */
1244 aix_fs_getword (FILE *fd
,
1249 aix_fs_ignorespace (fd
);
1251 while (((c
= aix_fs_getc (fd
)) != EOF
) && !g_ascii_isspace (c
))
1255 while (((c
= aix_fs_getc (fd
)) != EOF
) && (c
!= '"'))
1267 char mnt_mount
[PATH_MAX
];
1268 char mnt_special
[PATH_MAX
];
1269 char mnt_fstype
[16];
1270 char mnt_options
[128];
1271 } AixMountTableEntry
;
1273 /* read mount points properties */
1275 aix_fs_get (FILE *fd
,
1276 AixMountTableEntry
*prop
)
1278 static char word
[PATH_MAX
] = { 0 };
1279 char value
[PATH_MAX
];
1284 if (aix_fs_getword (fd
, word
) == EOF
)
1288 word
[strlen(word
) - 1] = 0;
1289 strcpy (prop
->mnt_mount
, word
);
1291 /* read attributes and value */
1293 while (aix_fs_getword (fd
, word
) != EOF
)
1295 /* test if is attribute or new stanza */
1296 if (word
[strlen(word
) - 1] == ':')
1300 aix_fs_getword (fd
, value
);
1303 aix_fs_getword (fd
, value
);
1305 if (strcmp (word
, "dev") == 0)
1306 strcpy (prop
->mnt_special
, value
);
1307 else if (strcmp (word
, "vfs") == 0)
1308 strcpy (prop
->mnt_fstype
, value
);
1309 else if (strcmp (word
, "options") == 0)
1310 strcpy(prop
->mnt_options
, value
);
1317 _g_get_unix_mount_points (void)
1319 struct mntent
*mntent
;
1322 GUnixMountPoint
*mount_point
;
1323 AixMountTableEntry mntent
;
1326 read_file
= get_fstab_file ();
1328 file
= setmntent (read_file
, "r");
1334 while (!aix_fs_get (file
, &mntent
))
1336 if (strcmp ("cdrfs", mntent
.mnt_fstype
) == 0)
1338 mount_point
= create_unix_mount_point (mntent
.mnt_special
,
1346 return_list
= g_list_prepend (return_list
, mount_point
);
1352 return g_list_reverse (return_list
);
1355 #elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
1358 _g_get_unix_mount_points (void)
1360 struct fstab
*fstab
= NULL
;
1361 GUnixMountPoint
*mount_point
;
1363 #ifdef HAVE_SYS_SYSCTL_H
1373 #ifdef HAVE_SYS_SYSCTL_H
1374 #if defined(HAVE_SYSCTLBYNAME)
1376 size_t len
= sizeof(usermnt
);
1378 sysctlbyname ("vfs.usermount", &usermnt
, &len
, NULL
, 0);
1380 #elif defined(CTL_VFS) && defined(VFS_USERMOUNT)
1383 size_t len
= sizeof(usermnt
);
1386 mib
[1] = VFS_USERMOUNT
;
1387 sysctl (mib
, 2, &usermnt
, &len
, NULL
, 0);
1389 #elif defined(CTL_KERN) && defined(KERN_USERMOUNT)
1392 size_t len
= sizeof(usermnt
);
1395 mib
[1] = KERN_USERMOUNT
;
1396 sysctl (mib
, 2, &usermnt
, &len
, NULL
, 0);
1401 while ((fstab
= getfsent ()) != NULL
)
1403 gboolean is_read_only
= FALSE
;
1404 gboolean is_user_mountable
= FALSE
;
1406 if (strcmp (fstab
->fs_vfstype
, "swap") == 0)
1409 if (strcmp (fstab
->fs_type
, "ro") == 0)
1410 is_read_only
= TRUE
;
1412 #ifdef HAVE_SYS_SYSCTL_H
1415 uid_t uid
= getuid ();
1416 if (stat (fstab
->fs_file
, &sb
) == 0)
1418 if (uid
== 0 || sb
.st_uid
== uid
)
1419 is_user_mountable
= TRUE
;
1424 mount_point
= create_unix_mount_point (fstab
->fs_spec
,
1432 return_list
= g_list_prepend (return_list
, mount_point
);
1437 return g_list_reverse (return_list
);
1440 #elif defined(__INTERIX)
1442 _g_get_unix_mount_points (void)
1444 return _g_get_unix_mounts ();
1447 /* Common code {{{2 */
1449 #error No g_get_mount_table() implementation for system
1453 get_mounts_timestamp (void)
1455 const char *monitor_file
;
1458 monitor_file
= get_mtab_monitor_file ();
1459 /* Don't return mtime for /proc/ files */
1460 if (monitor_file
&& !g_str_has_prefix (monitor_file
, "/proc/"))
1462 if (stat (monitor_file
, &buf
) == 0)
1463 return (guint64
)buf
.st_mtime
;
1465 else if (proc_mounts_watch_is_running ())
1467 /* it's being monitored by poll, so return mount_poller_time */
1468 return mount_poller_time
;
1472 /* Case of /proc/ file not being monitored - Be on the safe side and
1473 * send a new timestamp to force g_unix_mounts_changed_since() to
1474 * return TRUE so any application caches depending on it (like eg.
1475 * the one in GIO) get invalidated and don't hold possibly outdated
1476 * data - see Bug 787731 */
1477 return (guint64
) g_get_monotonic_time ();
1483 get_mount_points_timestamp (void)
1485 const char *monitor_file
;
1488 monitor_file
= get_fstab_file ();
1491 if (stat (monitor_file
, &buf
) == 0)
1492 return (guint64
)buf
.st_mtime
;
1498 * g_unix_mounts_get:
1499 * @time_read: (out) (optional): guint64 to contain a timestamp, or %NULL
1501 * Gets a #GList of #GUnixMountEntry containing the unix mounts.
1502 * If @time_read is set, it will be filled with the mount
1503 * timestamp, allowing for checking if the mounts have changed
1504 * with g_unix_mounts_changed_since().
1506 * Returns: (element-type GUnixMountEntry) (transfer full):
1507 * a #GList of the UNIX mounts.
1510 g_unix_mounts_get (guint64
*time_read
)
1513 *time_read
= get_mounts_timestamp ();
1515 return _g_get_unix_mounts ();
1520 * @mount_path: (type filename): path for a possible unix mount.
1521 * @time_read: (out) (optional): guint64 to contain a timestamp.
1523 * Gets a #GUnixMountEntry for a given mount path. If @time_read
1524 * is set, it will be filled with a unix timestamp for checking
1525 * if the mounts have changed since with g_unix_mounts_changed_since().
1527 * Returns: (transfer full): a #GUnixMountEntry.
1530 g_unix_mount_at (const char *mount_path
,
1534 GUnixMountEntry
*mount_entry
, *found
;
1536 mounts
= g_unix_mounts_get (time_read
);
1539 for (l
= mounts
; l
!= NULL
; l
= l
->next
)
1541 mount_entry
= l
->data
;
1543 if (!found
&& strcmp (mount_path
, mount_entry
->mount_path
) == 0)
1544 found
= mount_entry
;
1546 g_unix_mount_free (mount_entry
);
1548 g_list_free (mounts
);
1555 * @file_path: (type filename): file path on some unix mount.
1556 * @time_read: (out) (optional): guint64 to contain a timestamp.
1558 * Gets a #GUnixMountEntry for a given file path. If @time_read
1559 * is set, it will be filled with a unix timestamp for checking
1560 * if the mounts have changed since with g_unix_mounts_changed_since().
1562 * Returns: (transfer full): a #GUnixMountEntry.
1567 g_unix_mount_for (const char *file_path
,
1570 GUnixMountEntry
*entry
;
1572 g_return_val_if_fail (file_path
!= NULL
, NULL
);
1574 entry
= g_unix_mount_at (file_path
, time_read
);
1579 topdir
= _g_local_file_find_topdir_for (file_path
);
1582 entry
= g_unix_mount_at (topdir
, time_read
);
1591 * g_unix_mount_points_get:
1592 * @time_read: (out) (optional): guint64 to contain a timestamp.
1594 * Gets a #GList of #GUnixMountPoint containing the unix mount points.
1595 * If @time_read is set, it will be filled with the mount timestamp,
1596 * allowing for checking if the mounts have changed with
1597 * g_unix_mount_points_changed_since().
1599 * Returns: (element-type GUnixMountPoint) (transfer full):
1600 * a #GList of the UNIX mountpoints.
1603 g_unix_mount_points_get (guint64
*time_read
)
1606 *time_read
= get_mount_points_timestamp ();
1608 return _g_get_unix_mount_points ();
1612 * g_unix_mounts_changed_since:
1613 * @time: guint64 to contain a timestamp.
1615 * Checks if the unix mounts have changed since a given unix time.
1617 * Returns: %TRUE if the mounts have changed since @time.
1620 g_unix_mounts_changed_since (guint64 time
)
1622 return get_mounts_timestamp () != time
;
1626 * g_unix_mount_points_changed_since:
1627 * @time: guint64 to contain a timestamp.
1629 * Checks if the unix mount points have changed since a given unix time.
1631 * Returns: %TRUE if the mount points have changed since @time.
1634 g_unix_mount_points_changed_since (guint64 time
)
1636 return get_mount_points_timestamp () != time
;
1639 /* GUnixMountMonitor {{{1 */
1643 MOUNTPOINTS_CHANGED
,
1647 static guint signals
[LAST_SIGNAL
];
1649 struct _GUnixMountMonitor
{
1652 GMainContext
*context
;
1655 struct _GUnixMountMonitorClass
{
1656 GObjectClass parent_class
;
1660 G_DEFINE_TYPE (GUnixMountMonitor
, g_unix_mount_monitor
, G_TYPE_OBJECT
)
1662 static GContextSpecificGroup mount_monitor_group
;
1663 static GFileMonitor
*fstab_monitor
;
1664 static GFileMonitor
*mtab_monitor
;
1665 static GSource
*proc_mounts_watch_source
;
1666 static GList
*mount_poller_mounts
;
1667 static guint mtab_file_changed_id
;
1670 proc_mounts_watch_is_running (void)
1672 return proc_mounts_watch_source
!= NULL
&&
1673 !g_source_is_destroyed (proc_mounts_watch_source
);
1677 fstab_file_changed (GFileMonitor
*monitor
,
1680 GFileMonitorEvent event_type
,
1683 if (event_type
!= G_FILE_MONITOR_EVENT_CHANGED
&&
1684 event_type
!= G_FILE_MONITOR_EVENT_CREATED
&&
1685 event_type
!= G_FILE_MONITOR_EVENT_DELETED
)
1688 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTPOINTS_CHANGED
]);
1692 mtab_file_changed_cb (gpointer user_data
)
1694 mtab_file_changed_id
= 0;
1695 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTS_CHANGED
]);
1697 return G_SOURCE_REMOVE
;
1701 mtab_file_changed (GFileMonitor
*monitor
,
1704 GFileMonitorEvent event_type
,
1707 if (event_type
!= G_FILE_MONITOR_EVENT_CHANGED
&&
1708 event_type
!= G_FILE_MONITOR_EVENT_CREATED
&&
1709 event_type
!= G_FILE_MONITOR_EVENT_DELETED
)
1712 /* Skip accumulated events from file monitor which we are not able to handle
1713 * in a real time instead of emitting mounts_changed signal several times.
1714 * This should behave equally to GIOChannel based monitoring. See Bug 792235.
1716 if (mtab_file_changed_id
> 0)
1719 mtab_file_changed_id
= g_idle_add (mtab_file_changed_cb
, NULL
);
1723 proc_mounts_changed (GIOChannel
*channel
,
1727 if (cond
& G_IO_ERR
)
1729 mount_poller_time
= (guint64
) g_get_monotonic_time ();
1730 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTS_CHANGED
]);
1737 mount_change_poller (gpointer user_data
)
1739 GList
*current_mounts
, *new_it
, *old_it
;
1740 gboolean has_changed
= FALSE
;
1742 current_mounts
= _g_get_unix_mounts ();
1744 for ( new_it
= current_mounts
, old_it
= mount_poller_mounts
;
1745 new_it
!= NULL
&& old_it
!= NULL
;
1746 new_it
= g_list_next (new_it
), old_it
= g_list_next (old_it
) )
1748 if (g_unix_mount_compare (new_it
->data
, old_it
->data
) != 0)
1754 if (!(new_it
== NULL
&& old_it
== NULL
))
1757 g_list_free_full (mount_poller_mounts
, (GDestroyNotify
) g_unix_mount_free
);
1759 mount_poller_mounts
= current_mounts
;
1763 mount_poller_time
= (guint64
) g_get_monotonic_time ();
1764 g_context_specific_group_emit (&mount_monitor_group
, signals
[MOUNTPOINTS_CHANGED
]);
1772 mount_monitor_stop (void)
1776 g_file_monitor_cancel (fstab_monitor
);
1777 g_object_unref (fstab_monitor
);
1780 if (proc_mounts_watch_source
!= NULL
)
1782 g_source_destroy (proc_mounts_watch_source
);
1783 proc_mounts_watch_source
= NULL
;
1788 g_file_monitor_cancel (mtab_monitor
);
1789 g_object_unref (mtab_monitor
);
1792 g_list_free_full (mount_poller_mounts
, (GDestroyNotify
) g_unix_mount_free
);
1796 mount_monitor_start (void)
1800 if (get_fstab_file () != NULL
)
1802 file
= g_file_new_for_path (get_fstab_file ());
1803 fstab_monitor
= g_file_monitor_file (file
, 0, NULL
, NULL
);
1804 g_object_unref (file
);
1806 g_signal_connect (fstab_monitor
, "changed", (GCallback
)fstab_file_changed
, NULL
);
1809 if (get_mtab_monitor_file () != NULL
)
1811 const gchar
*mtab_path
;
1813 mtab_path
= get_mtab_monitor_file ();
1814 /* Monitoring files in /proc/ is special - can't just use GFileMonitor.
1815 * See 'man proc' for more details.
1817 if (g_str_has_prefix (mtab_path
, "/proc/"))
1819 GIOChannel
*proc_mounts_channel
;
1820 GError
*error
= NULL
;
1821 proc_mounts_channel
= g_io_channel_new_file (mtab_path
, "r", &error
);
1822 if (proc_mounts_channel
== NULL
)
1824 g_warning ("Error creating IO channel for %s: %s (%s, %d)", mtab_path
,
1825 error
->message
, g_quark_to_string (error
->domain
), error
->code
);
1826 g_error_free (error
);
1830 proc_mounts_watch_source
= g_io_create_watch (proc_mounts_channel
, G_IO_ERR
);
1831 g_source_set_callback (proc_mounts_watch_source
,
1832 (GSourceFunc
) proc_mounts_changed
,
1834 g_source_attach (proc_mounts_watch_source
,
1835 g_main_context_get_thread_default ());
1836 g_source_unref (proc_mounts_watch_source
);
1837 g_io_channel_unref (proc_mounts_channel
);
1842 file
= g_file_new_for_path (mtab_path
);
1843 mtab_monitor
= g_file_monitor_file (file
, 0, NULL
, NULL
);
1844 g_object_unref (file
);
1845 g_signal_connect (mtab_monitor
, "changed", (GCallback
)mtab_file_changed
, NULL
);
1850 proc_mounts_watch_source
= g_timeout_source_new_seconds (3);
1851 mount_poller_mounts
= _g_get_unix_mounts ();
1852 mount_poller_time
= (guint64
)g_get_monotonic_time ();
1853 g_source_set_callback (proc_mounts_watch_source
,
1854 mount_change_poller
,
1856 g_source_attach (proc_mounts_watch_source
,
1857 g_main_context_get_thread_default ());
1858 g_source_unref (proc_mounts_watch_source
);
1863 g_unix_mount_monitor_finalize (GObject
*object
)
1865 GUnixMountMonitor
*monitor
;
1867 monitor
= G_UNIX_MOUNT_MONITOR (object
);
1869 g_context_specific_group_remove (&mount_monitor_group
, monitor
->context
, monitor
, mount_monitor_stop
);
1871 G_OBJECT_CLASS (g_unix_mount_monitor_parent_class
)->finalize (object
);
1875 g_unix_mount_monitor_class_init (GUnixMountMonitorClass
*klass
)
1877 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
1879 gobject_class
->finalize
= g_unix_mount_monitor_finalize
;
1882 * GUnixMountMonitor::mounts-changed:
1883 * @monitor: the object on which the signal is emitted
1885 * Emitted when the unix mounts have changed.
1887 signals
[MOUNTS_CHANGED
] =
1888 g_signal_new (I_("mounts-changed"),
1889 G_TYPE_FROM_CLASS (klass
),
1893 g_cclosure_marshal_VOID__VOID
,
1897 * GUnixMountMonitor::mountpoints-changed:
1898 * @monitor: the object on which the signal is emitted
1900 * Emitted when the unix mount points have changed.
1902 signals
[MOUNTPOINTS_CHANGED
] =
1903 g_signal_new (I_("mountpoints-changed"),
1904 G_TYPE_FROM_CLASS (klass
),
1908 g_cclosure_marshal_VOID__VOID
,
1913 g_unix_mount_monitor_init (GUnixMountMonitor
*monitor
)
1918 * g_unix_mount_monitor_set_rate_limit:
1919 * @mount_monitor: a #GUnixMountMonitor
1920 * @limit_msec: a integer with the limit in milliseconds to
1923 * This function does nothing.
1925 * Before 2.44, this was a partially-effective way of controlling the
1926 * rate at which events would be reported under some uncommon
1927 * circumstances. Since @mount_monitor is a singleton, it also meant
1928 * that calling this function would have side effects for other users of
1933 * Deprecated:2.44:This function does nothing. Don't call it.
1936 g_unix_mount_monitor_set_rate_limit (GUnixMountMonitor
*mount_monitor
,
1942 * g_unix_mount_monitor_get:
1944 * Gets the #GUnixMountMonitor for the current thread-default main
1947 * The mount monitor can be used to monitor for changes to the list of
1948 * mounted filesystems as well as the list of mount points (ie: fstab
1951 * You must only call g_object_unref() on the return value from under
1952 * the same main context as you called this function.
1954 * Returns: (transfer full): the #GUnixMountMonitor.
1959 g_unix_mount_monitor_get (void)
1961 return g_context_specific_group_get (&mount_monitor_group
,
1962 G_TYPE_UNIX_MOUNT_MONITOR
,
1963 G_STRUCT_OFFSET(GUnixMountMonitor
, context
),
1964 mount_monitor_start
);
1968 * g_unix_mount_monitor_new:
1970 * Deprecated alias for g_unix_mount_monitor_get().
1972 * This function was never a true constructor, which is why it was
1975 * Returns: a #GUnixMountMonitor.
1977 * Deprecated:2.44:Use g_unix_mount_monitor_get() instead.
1980 g_unix_mount_monitor_new (void)
1982 return g_unix_mount_monitor_get ();
1985 /* GUnixMount {{{1 */
1987 * g_unix_mount_free:
1988 * @mount_entry: a #GUnixMountEntry.
1990 * Frees a unix mount.
1993 g_unix_mount_free (GUnixMountEntry
*mount_entry
)
1995 g_return_if_fail (mount_entry
!= NULL
);
1997 g_free (mount_entry
->mount_path
);
1998 g_free (mount_entry
->device_path
);
1999 g_free (mount_entry
->filesystem_type
);
2000 g_free (mount_entry
->options
);
2001 g_free (mount_entry
);
2005 * g_unix_mount_copy:
2006 * @mount_entry: a #GUnixMountEntry.
2008 * Makes a copy of @mount_entry.
2010 * Returns: (transfer full): a new #GUnixMountEntry
2015 g_unix_mount_copy (GUnixMountEntry
*mount_entry
)
2017 GUnixMountEntry
*copy
;
2019 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2021 copy
= g_new0 (GUnixMountEntry
, 1);
2022 copy
->mount_path
= g_strdup (mount_entry
->mount_path
);
2023 copy
->device_path
= g_strdup (mount_entry
->device_path
);
2024 copy
->filesystem_type
= g_strdup (mount_entry
->filesystem_type
);
2025 copy
->options
= g_strdup (mount_entry
->options
);
2026 copy
->is_read_only
= mount_entry
->is_read_only
;
2027 copy
->is_system_internal
= mount_entry
->is_system_internal
;
2033 * g_unix_mount_point_free:
2034 * @mount_point: unix mount point to free.
2036 * Frees a unix mount point.
2039 g_unix_mount_point_free (GUnixMountPoint
*mount_point
)
2041 g_return_if_fail (mount_point
!= NULL
);
2043 g_free (mount_point
->mount_path
);
2044 g_free (mount_point
->device_path
);
2045 g_free (mount_point
->filesystem_type
);
2046 g_free (mount_point
->options
);
2047 g_free (mount_point
);
2051 * g_unix_mount_point_copy:
2052 * @mount_point: a #GUnixMountPoint.
2054 * Makes a copy of @mount_point.
2056 * Returns: (transfer full): a new #GUnixMountPoint
2061 g_unix_mount_point_copy (GUnixMountPoint
*mount_point
)
2063 GUnixMountPoint
*copy
;
2065 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2067 copy
= g_new0 (GUnixMountPoint
, 1);
2068 copy
->mount_path
= g_strdup (mount_point
->mount_path
);
2069 copy
->device_path
= g_strdup (mount_point
->device_path
);
2070 copy
->filesystem_type
= g_strdup (mount_point
->filesystem_type
);
2071 copy
->options
= g_strdup (mount_point
->options
);
2072 copy
->is_read_only
= mount_point
->is_read_only
;
2073 copy
->is_user_mountable
= mount_point
->is_user_mountable
;
2074 copy
->is_loopback
= mount_point
->is_loopback
;
2080 * g_unix_mount_compare:
2081 * @mount1: first #GUnixMountEntry to compare.
2082 * @mount2: second #GUnixMountEntry to compare.
2084 * Compares two unix mounts.
2086 * Returns: 1, 0 or -1 if @mount1 is greater than, equal to,
2087 * or less than @mount2, respectively.
2090 g_unix_mount_compare (GUnixMountEntry
*mount1
,
2091 GUnixMountEntry
*mount2
)
2095 g_return_val_if_fail (mount1
!= NULL
&& mount2
!= NULL
, 0);
2097 res
= g_strcmp0 (mount1
->mount_path
, mount2
->mount_path
);
2101 res
= g_strcmp0 (mount1
->device_path
, mount2
->device_path
);
2105 res
= g_strcmp0 (mount1
->filesystem_type
, mount2
->filesystem_type
);
2109 res
= g_strcmp0 (mount1
->options
, mount2
->options
);
2113 res
= mount1
->is_read_only
- mount2
->is_read_only
;
2121 * g_unix_mount_get_mount_path:
2122 * @mount_entry: input #GUnixMountEntry to get the mount path for.
2124 * Gets the mount path for a unix mount.
2126 * Returns: (type filename): the mount path for @mount_entry.
2129 g_unix_mount_get_mount_path (GUnixMountEntry
*mount_entry
)
2131 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2133 return mount_entry
->mount_path
;
2137 * g_unix_mount_get_device_path:
2138 * @mount_entry: a #GUnixMount.
2140 * Gets the device path for a unix mount.
2142 * Returns: (type filename): a string containing the device path.
2145 g_unix_mount_get_device_path (GUnixMountEntry
*mount_entry
)
2147 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2149 return mount_entry
->device_path
;
2153 * g_unix_mount_get_fs_type:
2154 * @mount_entry: a #GUnixMount.
2156 * Gets the filesystem type for the unix mount.
2158 * Returns: a string containing the file system type.
2161 g_unix_mount_get_fs_type (GUnixMountEntry
*mount_entry
)
2163 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2165 return mount_entry
->filesystem_type
;
2169 * g_unix_mount_get_options:
2170 * @mount_entry: a #GUnixMountEntry.
2172 * Gets a comma-separated list of mount options for the unix mount. For example,
2173 * `rw,relatime,seclabel,data=ordered`.
2175 * This is similar to g_unix_mount_point_get_options(), but it takes
2176 * a #GUnixMountEntry as an argument.
2178 * Returns: (nullable): a string containing the options, or %NULL if not
2184 g_unix_mount_get_options (GUnixMountEntry
*mount_entry
)
2186 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
2188 return mount_entry
->options
;
2192 * g_unix_mount_is_readonly:
2193 * @mount_entry: a #GUnixMount.
2195 * Checks if a unix mount is mounted read only.
2197 * Returns: %TRUE if @mount_entry is read only.
2200 g_unix_mount_is_readonly (GUnixMountEntry
*mount_entry
)
2202 g_return_val_if_fail (mount_entry
!= NULL
, FALSE
);
2204 return mount_entry
->is_read_only
;
2208 * g_unix_mount_is_system_internal:
2209 * @mount_entry: a #GUnixMount.
2211 * Checks if a Unix mount is a system mount. This is the Boolean OR of
2212 * g_unix_is_system_fs_type(), g_unix_is_system_device_path() and
2213 * g_unix_is_mount_path_system_internal() on @mount_entry’s properties.
2215 * The definition of what a ‘system’ mount entry is may change over time as new
2216 * file system types and device paths are ignored.
2218 * Returns: %TRUE if the unix mount is for a system path.
2221 g_unix_mount_is_system_internal (GUnixMountEntry
*mount_entry
)
2223 g_return_val_if_fail (mount_entry
!= NULL
, FALSE
);
2225 return mount_entry
->is_system_internal
;
2228 /* GUnixMountPoint {{{1 */
2230 * g_unix_mount_point_compare:
2231 * @mount1: a #GUnixMount.
2232 * @mount2: a #GUnixMount.
2234 * Compares two unix mount points.
2236 * Returns: 1, 0 or -1 if @mount1 is greater than, equal to,
2237 * or less than @mount2, respectively.
2240 g_unix_mount_point_compare (GUnixMountPoint
*mount1
,
2241 GUnixMountPoint
*mount2
)
2245 g_return_val_if_fail (mount1
!= NULL
&& mount2
!= NULL
, 0);
2247 res
= g_strcmp0 (mount1
->mount_path
, mount2
->mount_path
);
2251 res
= g_strcmp0 (mount1
->device_path
, mount2
->device_path
);
2255 res
= g_strcmp0 (mount1
->filesystem_type
, mount2
->filesystem_type
);
2259 res
= g_strcmp0 (mount1
->options
, mount2
->options
);
2263 res
= mount1
->is_read_only
- mount2
->is_read_only
;
2267 res
= mount1
->is_user_mountable
- mount2
->is_user_mountable
;
2271 res
= mount1
->is_loopback
- mount2
->is_loopback
;
2279 * g_unix_mount_point_get_mount_path:
2280 * @mount_point: a #GUnixMountPoint.
2282 * Gets the mount path for a unix mount point.
2284 * Returns: (type filename): a string containing the mount path.
2287 g_unix_mount_point_get_mount_path (GUnixMountPoint
*mount_point
)
2289 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2291 return mount_point
->mount_path
;
2295 * g_unix_mount_point_get_device_path:
2296 * @mount_point: a #GUnixMountPoint.
2298 * Gets the device path for a unix mount point.
2300 * Returns: (type filename): a string containing the device path.
2303 g_unix_mount_point_get_device_path (GUnixMountPoint
*mount_point
)
2305 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2307 return mount_point
->device_path
;
2311 * g_unix_mount_point_get_fs_type:
2312 * @mount_point: a #GUnixMountPoint.
2314 * Gets the file system type for the mount point.
2316 * Returns: a string containing the file system type.
2319 g_unix_mount_point_get_fs_type (GUnixMountPoint
*mount_point
)
2321 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2323 return mount_point
->filesystem_type
;
2327 * g_unix_mount_point_get_options:
2328 * @mount_point: a #GUnixMountPoint.
2330 * Gets the options for the mount point.
2332 * Returns: a string containing the options.
2337 g_unix_mount_point_get_options (GUnixMountPoint
*mount_point
)
2339 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
2341 return mount_point
->options
;
2345 * g_unix_mount_point_is_readonly:
2346 * @mount_point: a #GUnixMountPoint.
2348 * Checks if a unix mount point is read only.
2350 * Returns: %TRUE if a mount point is read only.
2353 g_unix_mount_point_is_readonly (GUnixMountPoint
*mount_point
)
2355 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
2357 return mount_point
->is_read_only
;
2361 * g_unix_mount_point_is_user_mountable:
2362 * @mount_point: a #GUnixMountPoint.
2364 * Checks if a unix mount point is mountable by the user.
2366 * Returns: %TRUE if the mount point is user mountable.
2369 g_unix_mount_point_is_user_mountable (GUnixMountPoint
*mount_point
)
2371 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
2373 return mount_point
->is_user_mountable
;
2377 * g_unix_mount_point_is_loopback:
2378 * @mount_point: a #GUnixMountPoint.
2380 * Checks if a unix mount point is a loopback device.
2382 * Returns: %TRUE if the mount point is a loopback. %FALSE otherwise.
2385 g_unix_mount_point_is_loopback (GUnixMountPoint
*mount_point
)
2387 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
2389 return mount_point
->is_loopback
;
2392 static GUnixMountType
2393 guess_mount_type (const char *mount_path
,
2394 const char *device_path
,
2395 const char *filesystem_type
)
2397 GUnixMountType type
;
2400 type
= G_UNIX_MOUNT_TYPE_UNKNOWN
;
2402 if ((strcmp (filesystem_type
, "udf") == 0) ||
2403 (strcmp (filesystem_type
, "iso9660") == 0) ||
2404 (strcmp (filesystem_type
, "cd9660") == 0))
2405 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2406 else if ((strcmp (filesystem_type
, "nfs") == 0) ||
2407 (strcmp (filesystem_type
, "nfs4") == 0))
2408 type
= G_UNIX_MOUNT_TYPE_NFS
;
2409 else if (g_str_has_prefix (device_path
, "/vol/dev/diskette/") ||
2410 g_str_has_prefix (device_path
, "/dev/fd") ||
2411 g_str_has_prefix (device_path
, "/dev/floppy"))
2412 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
2413 else if (g_str_has_prefix (device_path
, "/dev/cdrom") ||
2414 g_str_has_prefix (device_path
, "/dev/acd") ||
2415 g_str_has_prefix (device_path
, "/dev/cd"))
2416 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2417 else if (g_str_has_prefix (device_path
, "/vol/"))
2419 const char *name
= mount_path
+ strlen ("/");
2421 if (g_str_has_prefix (name
, "cdrom"))
2422 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2423 else if (g_str_has_prefix (name
, "floppy") ||
2424 g_str_has_prefix (device_path
, "/vol/dev/diskette/"))
2425 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
2426 else if (g_str_has_prefix (name
, "rmdisk"))
2427 type
= G_UNIX_MOUNT_TYPE_ZIP
;
2428 else if (g_str_has_prefix (name
, "jaz"))
2429 type
= G_UNIX_MOUNT_TYPE_JAZ
;
2430 else if (g_str_has_prefix (name
, "memstick"))
2431 type
= G_UNIX_MOUNT_TYPE_MEMSTICK
;
2435 basename
= g_path_get_basename (mount_path
);
2437 if (g_str_has_prefix (basename
, "cdr") ||
2438 g_str_has_prefix (basename
, "cdwriter") ||
2439 g_str_has_prefix (basename
, "burn") ||
2440 g_str_has_prefix (basename
, "dvdr"))
2441 type
= G_UNIX_MOUNT_TYPE_CDROM
;
2442 else if (g_str_has_prefix (basename
, "floppy"))
2443 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
2444 else if (g_str_has_prefix (basename
, "zip"))
2445 type
= G_UNIX_MOUNT_TYPE_ZIP
;
2446 else if (g_str_has_prefix (basename
, "jaz"))
2447 type
= G_UNIX_MOUNT_TYPE_JAZ
;
2448 else if (g_str_has_prefix (basename
, "camera"))
2449 type
= G_UNIX_MOUNT_TYPE_CAMERA
;
2450 else if (g_str_has_prefix (basename
, "memstick") ||
2451 g_str_has_prefix (basename
, "memory_stick") ||
2452 g_str_has_prefix (basename
, "ram"))
2453 type
= G_UNIX_MOUNT_TYPE_MEMSTICK
;
2454 else if (g_str_has_prefix (basename
, "compact_flash"))
2455 type
= G_UNIX_MOUNT_TYPE_CF
;
2456 else if (g_str_has_prefix (basename
, "smart_media"))
2457 type
= G_UNIX_MOUNT_TYPE_SM
;
2458 else if (g_str_has_prefix (basename
, "sd_mmc"))
2459 type
= G_UNIX_MOUNT_TYPE_SDMMC
;
2460 else if (g_str_has_prefix (basename
, "ipod"))
2461 type
= G_UNIX_MOUNT_TYPE_IPOD
;
2466 if (type
== G_UNIX_MOUNT_TYPE_UNKNOWN
)
2467 type
= G_UNIX_MOUNT_TYPE_HD
;
2473 * g_unix_mount_guess_type:
2474 * @mount_entry: a #GUnixMount.
2476 * Guesses the type of a unix mount. If the mount type cannot be
2477 * determined, returns %G_UNIX_MOUNT_TYPE_UNKNOWN.
2479 * Returns: a #GUnixMountType.
2481 static GUnixMountType
2482 g_unix_mount_guess_type (GUnixMountEntry
*mount_entry
)
2484 g_return_val_if_fail (mount_entry
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2485 g_return_val_if_fail (mount_entry
->mount_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2486 g_return_val_if_fail (mount_entry
->device_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2487 g_return_val_if_fail (mount_entry
->filesystem_type
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2489 return guess_mount_type (mount_entry
->mount_path
,
2490 mount_entry
->device_path
,
2491 mount_entry
->filesystem_type
);
2495 * g_unix_mount_point_guess_type:
2496 * @mount_point: a #GUnixMountPoint.
2498 * Guesses the type of a unix mount point.
2499 * If the mount type cannot be determined,
2500 * returns %G_UNIX_MOUNT_TYPE_UNKNOWN.
2502 * Returns: a #GUnixMountType.
2504 static GUnixMountType
2505 g_unix_mount_point_guess_type (GUnixMountPoint
*mount_point
)
2507 g_return_val_if_fail (mount_point
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2508 g_return_val_if_fail (mount_point
->mount_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2509 g_return_val_if_fail (mount_point
->device_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2510 g_return_val_if_fail (mount_point
->filesystem_type
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
2512 return guess_mount_type (mount_point
->mount_path
,
2513 mount_point
->device_path
,
2514 mount_point
->filesystem_type
);
2518 type_to_icon (GUnixMountType type
, gboolean is_mount_point
, gboolean use_symbolic
)
2520 const char *icon_name
;
2524 case G_UNIX_MOUNT_TYPE_HD
:
2526 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2528 icon_name
= use_symbolic
? "drive-harddisk-symbolic" : "drive-harddisk";
2530 case G_UNIX_MOUNT_TYPE_FLOPPY
:
2531 case G_UNIX_MOUNT_TYPE_ZIP
:
2532 case G_UNIX_MOUNT_TYPE_JAZ
:
2534 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2536 icon_name
= use_symbolic
? "media-removable-symbolic" : "media-floppy";
2538 case G_UNIX_MOUNT_TYPE_CDROM
:
2540 icon_name
= use_symbolic
? "drive-optical-symbolic" : "drive-optical";
2542 icon_name
= use_symbolic
? "media-optical-symbolic" : "media-optical";
2544 case G_UNIX_MOUNT_TYPE_NFS
:
2545 icon_name
= use_symbolic
? "folder-remote-symbolic" : "folder-remote";
2547 case G_UNIX_MOUNT_TYPE_MEMSTICK
:
2549 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2551 icon_name
= use_symbolic
? "media-removable-symbolic" : "media-flash";
2553 case G_UNIX_MOUNT_TYPE_CAMERA
:
2555 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2557 icon_name
= use_symbolic
? "camera-photo-symbolic" : "camera-photo";
2559 case G_UNIX_MOUNT_TYPE_IPOD
:
2561 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2563 icon_name
= use_symbolic
? "multimedia-player-symbolic" : "multimedia-player";
2565 case G_UNIX_MOUNT_TYPE_UNKNOWN
:
2568 icon_name
= use_symbolic
? "drive-removable-media-symbolic" : "drive-removable-media";
2570 icon_name
= use_symbolic
? "drive-harddisk-symbolic" : "drive-harddisk";
2578 * g_unix_mount_guess_name:
2579 * @mount_entry: a #GUnixMountEntry
2581 * Guesses the name of a Unix mount.
2582 * The result is a translated string.
2584 * Returns: A newly allocated string that must
2585 * be freed with g_free()
2588 g_unix_mount_guess_name (GUnixMountEntry
*mount_entry
)
2592 if (strcmp (mount_entry
->mount_path
, "/") == 0)
2593 name
= g_strdup (_("Filesystem root"));
2595 name
= g_filename_display_basename (mount_entry
->mount_path
);
2601 * g_unix_mount_guess_icon:
2602 * @mount_entry: a #GUnixMountEntry
2604 * Guesses the icon of a Unix mount.
2606 * Returns: (transfer full): a #GIcon
2609 g_unix_mount_guess_icon (GUnixMountEntry
*mount_entry
)
2611 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_guess_type (mount_entry
), FALSE
, FALSE
));
2615 * g_unix_mount_guess_symbolic_icon:
2616 * @mount_entry: a #GUnixMountEntry
2618 * Guesses the symbolic icon of a Unix mount.
2620 * Returns: (transfer full): a #GIcon
2625 g_unix_mount_guess_symbolic_icon (GUnixMountEntry
*mount_entry
)
2627 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_guess_type (mount_entry
), FALSE
, TRUE
));
2631 * g_unix_mount_point_guess_name:
2632 * @mount_point: a #GUnixMountPoint
2634 * Guesses the name of a Unix mount point.
2635 * The result is a translated string.
2637 * Returns: A newly allocated string that must
2638 * be freed with g_free()
2641 g_unix_mount_point_guess_name (GUnixMountPoint
*mount_point
)
2645 if (strcmp (mount_point
->mount_path
, "/") == 0)
2646 name
= g_strdup (_("Filesystem root"));
2648 name
= g_filename_display_basename (mount_point
->mount_path
);
2654 * g_unix_mount_point_guess_icon:
2655 * @mount_point: a #GUnixMountPoint
2657 * Guesses the icon of a Unix mount point.
2659 * Returns: (transfer full): a #GIcon
2662 g_unix_mount_point_guess_icon (GUnixMountPoint
*mount_point
)
2664 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_point_guess_type (mount_point
), TRUE
, FALSE
));
2668 * g_unix_mount_point_guess_symbolic_icon:
2669 * @mount_point: a #GUnixMountPoint
2671 * Guesses the symbolic icon of a Unix mount point.
2673 * Returns: (transfer full): a #GIcon
2678 g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint
*mount_point
)
2680 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_point_guess_type (mount_point
), TRUE
, TRUE
));
2684 * g_unix_mount_guess_can_eject:
2685 * @mount_entry: a #GUnixMountEntry
2687 * Guesses whether a Unix mount can be ejected.
2689 * Returns: %TRUE if @mount_entry is deemed to be ejectable.
2692 g_unix_mount_guess_can_eject (GUnixMountEntry
*mount_entry
)
2694 GUnixMountType guessed_type
;
2696 guessed_type
= g_unix_mount_guess_type (mount_entry
);
2697 if (guessed_type
== G_UNIX_MOUNT_TYPE_IPOD
||
2698 guessed_type
== G_UNIX_MOUNT_TYPE_CDROM
)
2705 * g_unix_mount_guess_should_display:
2706 * @mount_entry: a #GUnixMountEntry
2708 * Guesses whether a Unix mount should be displayed in the UI.
2710 * Returns: %TRUE if @mount_entry is deemed to be displayable.
2713 g_unix_mount_guess_should_display (GUnixMountEntry
*mount_entry
)
2715 const char *mount_path
;
2716 const gchar
*user_name
;
2717 gsize user_name_len
;
2719 /* Never display internal mountpoints */
2720 if (g_unix_mount_is_system_internal (mount_entry
))
2723 /* Only display things in /media (which are generally user mountable)
2724 and home dir (fuse stuff) and /run/media/$USER */
2725 mount_path
= mount_entry
->mount_path
;
2726 if (mount_path
!= NULL
)
2728 const gboolean running_as_root
= (getuid () == 0);
2729 gboolean is_in_runtime_dir
= FALSE
;
2731 /* Hide mounts within a dot path, suppose it was a purpose to hide this mount */
2732 if (g_strstr_len (mount_path
, -1, "/.") != NULL
)
2735 /* Check /run/media/$USER/. If running as root, display any mounts below
2737 if (running_as_root
)
2739 if (strncmp (mount_path
, "/run/media/", strlen ("/run/media/")) == 0)
2740 is_in_runtime_dir
= TRUE
;
2744 user_name
= g_get_user_name ();
2745 user_name_len
= strlen (user_name
);
2746 if (strncmp (mount_path
, "/run/media/", strlen ("/run/media/")) == 0 &&
2747 strncmp (mount_path
+ strlen ("/run/media/"), user_name
, user_name_len
) == 0 &&
2748 mount_path
[strlen ("/run/media/") + user_name_len
] == '/')
2749 is_in_runtime_dir
= TRUE
;
2752 if (is_in_runtime_dir
|| g_str_has_prefix (mount_path
, "/media/"))
2755 /* Avoid displaying mounts that are not accessible to the user.
2757 * See http://bugzilla.gnome.org/show_bug.cgi?id=526320 for why we
2758 * want to avoid g_access() for mount points which can potentially
2759 * block or fail stat()'ing, such as network mounts.
2761 path
= g_path_get_dirname (mount_path
);
2762 if (g_str_has_prefix (path
, "/media/"))
2764 if (g_access (path
, R_OK
|X_OK
) != 0)
2772 if (mount_entry
->device_path
&& mount_entry
->device_path
[0] == '/')
2775 if (g_stat (mount_entry
->device_path
, &st
) == 0 &&
2776 S_ISBLK(st
.st_mode
) &&
2777 g_access (mount_path
, R_OK
|X_OK
) != 0)
2783 if (g_str_has_prefix (mount_path
, g_get_home_dir ()) &&
2784 mount_path
[strlen (g_get_home_dir())] == G_DIR_SEPARATOR
)
2792 * g_unix_mount_point_guess_can_eject:
2793 * @mount_point: a #GUnixMountPoint
2795 * Guesses whether a Unix mount point can be ejected.
2797 * Returns: %TRUE if @mount_point is deemed to be ejectable.
2800 g_unix_mount_point_guess_can_eject (GUnixMountPoint
*mount_point
)
2802 GUnixMountType guessed_type
;
2804 guessed_type
= g_unix_mount_point_guess_type (mount_point
);
2805 if (guessed_type
== G_UNIX_MOUNT_TYPE_IPOD
||
2806 guessed_type
== G_UNIX_MOUNT_TYPE_CDROM
)
2812 /* Utility functions {{{1 */
2814 #ifdef HAVE_MNTENT_H
2815 /* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 */
2817 _canonicalize_filename (gchar
*filename
)
2820 gboolean last_was_slash
= FALSE
;
2827 if (*p
== G_DIR_SEPARATOR
)
2829 if (!last_was_slash
)
2830 *q
++ = G_DIR_SEPARATOR
;
2832 last_was_slash
= TRUE
;
2836 if (last_was_slash
&& *p
== '.')
2838 if (*(p
+ 1) == G_DIR_SEPARATOR
||
2841 if (*(p
+ 1) == '\0')
2846 else if (*(p
+ 1) == '.' &&
2847 (*(p
+ 2) == G_DIR_SEPARATOR
||
2850 if (q
> filename
+ 1)
2853 while (q
> filename
+ 1 &&
2854 *(q
- 1) != G_DIR_SEPARATOR
)
2858 if (*(p
+ 2) == '\0')
2866 last_was_slash
= FALSE
;
2872 last_was_slash
= FALSE
;
2879 if (q
> filename
+ 1 && *(q
- 1) == G_DIR_SEPARATOR
)
2886 _resolve_symlink (const char *file
)
2894 f
= g_strdup (file
);
2896 while (g_file_test (f
, G_FILE_TEST_IS_SYMLINK
))
2898 link
= g_file_read_link (f
, &error
);
2901 g_error_free (error
);
2907 dir
= g_path_get_dirname (f
);
2908 f1
= g_strdup_printf ("%s/%s", dir
, link
);
2917 _canonicalize_filename (f
);
2922 _resolve_dev_root (void)
2924 static gboolean have_real_dev_root
= FALSE
;
2925 static char real_dev_root
[256];
2926 struct stat statbuf
;
2928 /* see if it's cached already */
2929 if (have_real_dev_root
)
2932 /* otherwise we're going to find it right away.. */
2933 have_real_dev_root
= TRUE
;
2935 if (stat ("/dev/root", &statbuf
) == 0)
2937 if (! S_ISLNK (statbuf
.st_mode
))
2939 dev_t root_dev
= statbuf
.st_dev
;
2942 /* see if device with similar major:minor as /dev/root is mention
2943 * in /etc/mtab (it usually is)
2945 f
= fopen ("/etc/mtab", "r");
2948 struct mntent
*entp
;
2949 #ifdef HAVE_GETMNTENT_R
2952 while ((entp
= getmntent_r (f
, &ent
, buf
, sizeof (buf
))) != NULL
)
2956 while ((entp
= getmntent (f
)) != NULL
)
2959 if (stat (entp
->mnt_fsname
, &statbuf
) == 0 &&
2960 statbuf
.st_dev
== root_dev
)
2962 strncpy (real_dev_root
, entp
->mnt_fsname
, sizeof (real_dev_root
) - 1);
2963 real_dev_root
[sizeof (real_dev_root
) - 1] = '\0';
2971 #ifndef HAVE_GETMNTENT_R
2972 G_UNLOCK (getmntent
);
2976 /* no, that didn't work.. next we could scan /dev ... but I digress.. */
2982 resolved
= _resolve_symlink ("/dev/root");
2983 if (resolved
!= NULL
)
2985 strncpy (real_dev_root
, resolved
, sizeof (real_dev_root
) - 1);
2986 real_dev_root
[sizeof (real_dev_root
) - 1] = '\0';
2994 strcpy (real_dev_root
, "/dev/root");
2997 return real_dev_root
;
3002 /* vim:set foldmethod=marker: */