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 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, write to the
19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
22 * 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>
34 #ifdef HAVE_SYS_POLL_H
49 #include "gunixmounts.h"
51 #include "gfilemonitor.h"
53 #include "gthemedicon.h"
57 static const char *_resolve_dev_root (void);
61 * @include: gio/gunixmounts.h
62 * @short_description: Unix Mounts
64 * Routines for managing mounted UNIX mount points and paths.
70 * @G_UNIX_MOUNT_TYPE_UNKNOWN: Unknown UNIX mount type.
71 * @G_UNIX_MOUNT_TYPE_FLOPPY: Floppy disk UNIX mount type.
72 * @G_UNIX_MOUNT_TYPE_CDROM: CDROM UNIX mount type.
73 * @G_UNIX_MOUNT_TYPE_NFS: Network File System (NFS) UNIX mount type.
74 * @G_UNIX_MOUNT_TYPE_ZIP: ZIP UNIX mount type.
75 * @G_UNIX_MOUNT_TYPE_JAZ: JAZZ UNIX mount type.
76 * @G_UNIX_MOUNT_TYPE_MEMSTICK: Memory Stick UNIX mount type.
77 * @G_UNIX_MOUNT_TYPE_CF: Compact Flash UNIX mount type.
78 * @G_UNIX_MOUNT_TYPE_SM: Smart Media UNIX mount type.
79 * @G_UNIX_MOUNT_TYPE_SDMMC: SD/MMC UNIX mount type.
80 * @G_UNIX_MOUNT_TYPE_IPOD: iPod UNIX mount type.
81 * @G_UNIX_MOUNT_TYPE_CAMERA: Digital camera UNIX mount type.
82 * @G_UNIX_MOUNT_TYPE_HD: Hard drive UNIX mount type.
84 * Types of UNIX mounts.
87 G_UNIX_MOUNT_TYPE_UNKNOWN
,
88 G_UNIX_MOUNT_TYPE_FLOPPY
,
89 G_UNIX_MOUNT_TYPE_CDROM
,
90 G_UNIX_MOUNT_TYPE_NFS
,
91 G_UNIX_MOUNT_TYPE_ZIP
,
92 G_UNIX_MOUNT_TYPE_JAZ
,
93 G_UNIX_MOUNT_TYPE_MEMSTICK
,
96 G_UNIX_MOUNT_TYPE_SDMMC
,
97 G_UNIX_MOUNT_TYPE_IPOD
,
98 G_UNIX_MOUNT_TYPE_CAMERA
,
102 struct _GUnixMountEntry
{
105 char *filesystem_type
;
106 gboolean is_read_only
;
107 gboolean is_system_internal
;
110 struct _GUnixMountPoint
{
113 char *filesystem_type
;
114 gboolean is_read_only
;
115 gboolean is_user_mountable
;
116 gboolean is_loopback
;
125 static guint signals
[LAST_SIGNAL
];
127 struct _GUnixMountMonitor
{
130 GFileMonitor
*fstab_monitor
;
131 GFileMonitor
*mtab_monitor
;
134 struct _GUnixMountMonitorClass
{
135 GObjectClass parent_class
;
138 static GUnixMountMonitor
*the_mount_monitor
= NULL
;
140 static GList
*_g_get_unix_mounts (void);
141 static GList
*_g_get_unix_mount_points (void);
143 G_DEFINE_TYPE (GUnixMountMonitor
, g_unix_mount_monitor
, G_TYPE_OBJECT
);
145 #define MOUNT_POLL_INTERVAL 4000
147 #ifdef HAVE_SYS_MNTTAB_H
148 #define MNTOPT_RO "ro"
153 #elif defined (HAVE_SYS_MNTTAB_H)
154 #include <sys/mnttab.h>
157 #ifdef HAVE_SYS_VFSTAB_H
158 #include <sys/vfstab.h>
161 #if defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
162 #include <sys/mntctl.h>
164 #include <sys/vmount.h>
168 #if defined(HAVE_GETMNTINFO) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
169 #include <sys/ucred.h>
170 #include <sys/mount.h>
172 #ifdef HAVE_SYS_SYSCTL_H
173 #include <sys/sysctl.h>
177 #ifndef HAVE_SETMNTENT
178 #define setmntent(f,m) fopen(f,m)
180 #ifndef HAVE_ENDMNTENT
181 #define endmntent(f) fclose(f)
185 is_in (const char *value
, const char *set
[])
188 for (i
= 0; set
[i
] != NULL
; i
++)
190 if (strcmp (set
[i
], value
) == 0)
197 * g_unix_is_mount_path_system_internal:
198 * @mount_path: a mount path, e.g. <filename>/media/disk</filename>
199 * or <filename>/usr</filename>
201 * Determines if @mount_path is considered an implementation of the
202 * OS. This is primarily used for hiding mountable and mounted volumes
203 * that only are used in the OS and has little to no relevance to the
206 * Returns: %TRUE if @mount_path is considered an implementation detail
210 g_unix_is_mount_path_system_internal (const char *mount_path
)
212 const char *ignore_mountpoints
[] = {
213 /* Includes all FHS 2.3 toplevel dirs and other specilized
214 * directories that we want to hide from the user.
216 "/", /* we already have "Filesystem root" in Nautilus */
234 "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */
235 "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */
242 if (is_in (mount_path
, ignore_mountpoints
))
245 if (g_str_has_prefix (mount_path
, "/dev") ||
246 g_str_has_prefix (mount_path
, "/proc") ||
247 g_str_has_prefix (mount_path
, "/sys"))
250 if (strstr (mount_path
, "/.gvfs") != NULL
)
257 guess_system_internal (const char *mountpoint
,
261 const char *ignore_fs
[] = {
281 const char *ignore_devices
[] = {
291 if (is_in (fs
, ignore_fs
))
294 if (is_in (device
, ignore_devices
))
297 if (g_unix_is_mount_path_system_internal (mountpoint
))
306 get_mtab_read_file (void)
310 return "/proc/mounts";
312 return _PATH_MOUNTED
;
320 get_mtab_monitor_file (void)
323 return _PATH_MOUNTED
;
329 #ifndef HAVE_GETMNTENT_R
330 G_LOCK_DEFINE_STATIC(getmntent
);
334 _g_get_unix_mounts ()
336 #ifdef HAVE_GETMNTENT_R
340 struct mntent
*mntent
;
343 GUnixMountEntry
*mount_entry
;
344 GHashTable
*mounts_hash
;
347 read_file
= get_mtab_read_file ();
349 file
= setmntent (read_file
, "r");
355 mounts_hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
357 #ifdef HAVE_GETMNTENT_R
358 while ((mntent
= getmntent_r (file
, &ent
, buf
, sizeof (buf
))) != NULL
)
361 while ((mntent
= getmntent (file
)) != NULL
)
364 /* ignore any mnt_fsname that is repeated and begins with a '/'
366 * We do this to avoid being fooled by --bind mounts, since
367 * these have the same device as the location they bind to.
368 * Its not an ideal solution to the problem, but it's likely that
369 * the most important mountpoint is first and the --bind ones after
370 * that aren't as important. So it should work.
372 * The '/' is to handle procfs, tmpfs and other no device mounts.
374 if (mntent
->mnt_fsname
!= NULL
&&
375 mntent
->mnt_fsname
[0] == '/' &&
376 g_hash_table_lookup (mounts_hash
, mntent
->mnt_fsname
))
379 mount_entry
= g_new0 (GUnixMountEntry
, 1);
380 mount_entry
->mount_path
= g_strdup (mntent
->mnt_dir
);
381 if (strcmp (mntent
->mnt_fsname
, "/dev/root") == 0)
382 mount_entry
->device_path
= g_strdup (_resolve_dev_root ());
384 mount_entry
->device_path
= g_strdup (mntent
->mnt_fsname
);
385 mount_entry
->filesystem_type
= g_strdup (mntent
->mnt_type
);
387 #if defined (HAVE_HASMNTOPT)
388 if (hasmntopt (mntent
, MNTOPT_RO
) != NULL
)
389 mount_entry
->is_read_only
= TRUE
;
392 mount_entry
->is_system_internal
=
393 guess_system_internal (mount_entry
->mount_path
,
394 mount_entry
->filesystem_type
,
395 mount_entry
->device_path
);
397 g_hash_table_insert (mounts_hash
,
398 mount_entry
->device_path
,
399 mount_entry
->device_path
);
401 return_list
= g_list_prepend (return_list
, mount_entry
);
403 g_hash_table_destroy (mounts_hash
);
407 #ifndef HAVE_GETMNTENT_R
408 G_UNLOCK (getmntent
);
411 return g_list_reverse (return_list
);
414 #elif defined (HAVE_SYS_MNTTAB_H)
416 G_LOCK_DEFINE_STATIC(getmntent
);
419 get_mtab_read_file (void)
422 return _PATH_MOUNTED
;
424 return "/etc/mnttab";
429 get_mtab_monitor_file (void)
431 return get_mtab_read_file ();
435 _g_get_unix_mounts (void)
437 struct mnttab mntent
;
440 GUnixMountEntry
*mount_entry
;
443 read_file
= get_mtab_read_file ();
445 file
= setmntent (read_file
, "r");
452 while (! getmntent (file
, &mntent
))
454 mount_entry
= g_new0 (GUnixMountEntry
, 1);
456 mount_entry
->mount_path
= g_strdup (mntent
.mnt_mountp
);
457 mount_entry
->device_path
= g_strdup (mntent
.mnt_special
);
458 mount_entry
->filesystem_type
= g_strdup (mntent
.mnt_fstype
);
460 #if defined (HAVE_HASMNTOPT)
461 if (hasmntopt (&mntent
, MNTOPT_RO
) != NULL
)
462 mount_entry
->is_read_only
= TRUE
;
465 mount_entry
->is_system_internal
=
466 guess_system_internal (mount_entry
->mount_path
,
467 mount_entry
->filesystem_type
,
468 mount_entry
->device_path
);
470 return_list
= g_list_prepend (return_list
, mount_entry
);
475 G_UNLOCK (getmntent
);
477 return g_list_reverse (return_list
);
480 #elif defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
483 get_mtab_monitor_file (void)
489 _g_get_unix_mounts (void)
491 struct vfs_ent
*fs_info
;
492 struct vmount
*vmount_info
;
494 unsigned int vmount_size
;
498 if (mntctl (MCTL_QUERY
, sizeof (vmount_size
), &vmount_size
) != 0)
500 g_warning ("Unable to know the number of mounted volumes\n");
505 vmount_info
= (struct vmount
*)g_malloc (vmount_size
);
507 vmount_number
= mntctl (MCTL_QUERY
, vmount_size
, vmount_info
);
509 if (vmount_info
->vmt_revision
!= VMT_REVISION
)
510 g_warning ("Bad vmount structure revision number, want %d, got %d\n", VMT_REVISION
, vmount_info
->vmt_revision
);
512 if (vmount_number
< 0)
514 g_warning ("Unable to recover mounted volumes information\n");
516 g_free (vmount_info
);
521 while (vmount_number
> 0)
523 mount_entry
= g_new0 (GUnixMountEntry
, 1);
525 mount_entry
->device_path
= g_strdup (vmt2dataptr (vmount_info
, VMT_OBJECT
));
526 mount_entry
->mount_path
= g_strdup (vmt2dataptr (vmount_info
, VMT_STUB
));
527 /* is_removable = (vmount_info->vmt_flags & MNT_REMOVABLE) ? 1 : 0; */
528 mount_entry
->is_read_only
= (vmount_info
->vmt_flags
& MNT_READONLY
) ? 1 : 0;
530 fs_info
= getvfsbytype (vmount_info
->vmt_gfstype
);
533 mount_entry
->filesystem_type
= g_strdup ("unknown");
535 mount_entry
->filesystem_type
= g_strdup (fs_info
->vfsent_name
);
537 mount_entry
->is_system_internal
=
538 guess_system_internal (mount_entry
->mount_path
,
539 mount_entry
->filesystem_type
,
540 mount_entry
->device_path
);
542 return_list
= g_list_prepend (return_list
, mount_entry
);
544 vmount_info
= (struct vmount
*)( (char*)vmount_info
545 + vmount_info
->vmt_length
);
550 g_free (vmount_info
);
552 return g_list_reverse (return_list
);
555 #elif defined(HAVE_GETMNTINFO) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
558 get_mtab_monitor_file (void)
564 _g_get_unix_mounts (void)
566 struct statfs
*mntent
= NULL
;
568 GUnixMountEntry
*mount_entry
;
571 /* Pass MNT_NOWAIT to avoid blocking trying to update NFS mounts. */
572 if ((num_mounts
= getmntinfo (&mntent
, MNT_NOWAIT
)) == 0)
577 for (i
= 0; i
< num_mounts
; i
++)
579 mount_entry
= g_new0 (GUnixMountEntry
, 1);
581 mount_entry
->mount_path
= g_strdup (mntent
[i
].f_mntonname
);
582 mount_entry
->device_path
= g_strdup (mntent
[i
].f_mntfromname
);
583 mount_entry
->filesystem_type
= g_strdup (mntent
[i
].f_fstypename
);
584 if (mntent
[i
].f_flags
& MNT_RDONLY
)
585 mount_entry
->is_read_only
= TRUE
;
587 mount_entry
->is_system_internal
=
588 guess_system_internal (mount_entry
->mount_path
,
589 mount_entry
->filesystem_type
,
590 mount_entry
->device_path
);
592 return_list
= g_list_prepend (return_list
, mount_entry
);
595 return g_list_reverse (return_list
);
598 #error No _g_get_unix_mounts() implementation for system
601 /* _g_get_unix_mount_points():
603 * don't return swap and ignore mounts.
607 get_fstab_file (void)
609 #if defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
611 return "/etc/filesystems";
612 #elif defined(_PATH_MNTTAB)
614 #elif defined(VFSTAB)
623 _g_get_unix_mount_points (void)
625 #ifdef HAVE_GETMNTENT_R
629 struct mntent
*mntent
;
632 GUnixMountPoint
*mount_entry
;
635 read_file
= get_fstab_file ();
637 file
= setmntent (read_file
, "r");
643 #ifdef HAVE_GETMNTENT_R
644 while ((mntent
= getmntent_r (file
, &ent
, buf
, sizeof (buf
))) != NULL
)
647 while ((mntent
= getmntent (file
)) != NULL
)
650 if ((strcmp (mntent
->mnt_dir
, "ignore") == 0) ||
651 (strcmp (mntent
->mnt_dir
, "swap") == 0))
654 mount_entry
= g_new0 (GUnixMountPoint
, 1);
655 mount_entry
->mount_path
= g_strdup (mntent
->mnt_dir
);
656 if (strcmp (mntent
->mnt_fsname
, "/dev/root") == 0)
657 mount_entry
->device_path
= g_strdup (_resolve_dev_root ());
659 mount_entry
->device_path
= g_strdup (mntent
->mnt_fsname
);
660 mount_entry
->filesystem_type
= g_strdup (mntent
->mnt_type
);
662 #ifdef HAVE_HASMNTOPT
663 if (hasmntopt (mntent
, MNTOPT_RO
) != NULL
)
664 mount_entry
->is_read_only
= TRUE
;
666 if (hasmntopt (mntent
, "loop") != NULL
)
667 mount_entry
->is_loopback
= TRUE
;
671 if ((mntent
->mnt_type
!= NULL
&& strcmp ("supermount", mntent
->mnt_type
) == 0)
672 #ifdef HAVE_HASMNTOPT
673 || (hasmntopt (mntent
, "user") != NULL
674 && hasmntopt (mntent
, "user") != hasmntopt (mntent
, "user_xattr"))
675 || hasmntopt (mntent
, "pamconsole") != NULL
676 || hasmntopt (mntent
, "users") != NULL
677 || hasmntopt (mntent
, "owner") != NULL
680 mount_entry
->is_user_mountable
= TRUE
;
682 return_list
= g_list_prepend (return_list
, mount_entry
);
687 #ifndef HAVE_GETMNTENT_R
688 G_UNLOCK (getmntent
);
691 return g_list_reverse (return_list
);
694 #elif defined (HAVE_SYS_MNTTAB_H)
697 _g_get_unix_mount_points (void)
699 struct mnttab mntent
;
702 GUnixMountPoint
*mount_entry
;
705 read_file
= get_fstab_file ();
707 file
= setmntent (read_file
, "r");
714 while (! getmntent (file
, &mntent
))
716 if ((strcmp (mntent
.mnt_mountp
, "ignore") == 0) ||
717 (strcmp (mntent
.mnt_mountp
, "swap") == 0))
720 mount_entry
= g_new0 (GUnixMountPoint
, 1);
722 mount_entry
->mount_path
= g_strdup (mntent
.mnt_mountp
);
723 mount_entry
->device_path
= g_strdup (mntent
.mnt_special
);
724 mount_entry
->filesystem_type
= g_strdup (mntent
.mnt_fstype
);
726 #ifdef HAVE_HASMNTOPT
727 if (hasmntopt (&mntent
, MNTOPT_RO
) != NULL
)
728 mount_entry
->is_read_only
= TRUE
;
730 if (hasmntopt (&mntent
, "lofs") != NULL
)
731 mount_entry
->is_loopback
= TRUE
;
734 if ((mntent
.mnt_fstype
!= NULL
)
735 #ifdef HAVE_HASMNTOPT
736 || (hasmntopt (&mntent
, "user") != NULL
737 && hasmntopt (&mntent
, "user") != hasmntopt (&mntent
, "user_xattr"))
738 || hasmntopt (&mntent
, "pamconsole") != NULL
739 || hasmntopt (&mntent
, "users") != NULL
740 || hasmntopt (&mntent
, "owner") != NULL
743 mount_entry
->is_user_mountable
= TRUE
;
746 return_list
= g_list_prepend (return_list
, mount_entry
);
750 G_UNLOCK (getmntent
);
752 return g_list_reverse (return_list
);
754 #elif defined(HAVE_SYS_MNTCTL_H) && defined(HAVE_SYS_VMOUNT_H) && defined(HAVE_SYS_VFS_H)
756 /* functions to parse /etc/filesystems on aix */
758 /* read character, ignoring comments (begin with '*', end with '\n' */
760 aix_fs_getc (FILE *fd
)
764 while ((c
= getc (fd
)) == '*')
766 while (((c
= getc (fd
)) != '\n') && (c
!= EOF
))
771 /* eat all continuous spaces in a file */
773 aix_fs_ignorespace (FILE *fd
)
777 while ((c
= aix_fs_getc (fd
)) != EOF
)
779 if (!g_ascii_isspace (c
))
789 /* read one word from file */
791 aix_fs_getword (FILE *fd
,
796 aix_fs_ignorespace (fd
);
798 while (((c
= aix_fs_getc (fd
)) != EOF
) && !g_ascii_isspace (c
))
802 while (((c
= aix_fs_getc (fd
)) != EOF
) && (c
!= '"'))
814 char mnt_mount
[PATH_MAX
];
815 char mnt_special
[PATH_MAX
];
817 char mnt_options
[128];
818 } AixMountTableEntry
;
820 /* read mount points properties */
822 aix_fs_get (FILE *fd
,
823 AixMountTableEntry
*prop
)
825 static char word
[PATH_MAX
] = { 0 };
826 char value
[PATH_MAX
];
831 if (aix_fs_getword (fd
, word
) == EOF
)
835 word
[strlen(word
) - 1] = 0;
836 strcpy (prop
->mnt_mount
, word
);
838 /* read attributes and value */
840 while (aix_fs_getword (fd
, word
) != EOF
)
842 /* test if is attribute or new stanza */
843 if (word
[strlen(word
) - 1] == ':')
847 aix_fs_getword (fd
, value
);
850 aix_fs_getword (fd
, value
);
852 if (strcmp (word
, "dev") == 0)
853 strcpy (prop
->mnt_special
, value
);
854 else if (strcmp (word
, "vfs") == 0)
855 strcpy (prop
->mnt_fstype
, value
);
856 else if (strcmp (word
, "options") == 0)
857 strcpy(prop
->mnt_options
, value
);
864 _g_get_unix_mount_points (void)
866 struct mntent
*mntent
;
869 GUnixMountPoint
*mount_entry
;
870 AixMountTableEntry mntent
;
873 read_file
= get_fstab_file ();
875 file
= setmntent (read_file
, "r");
881 while (!aix_fs_get (file
, &mntent
))
883 if (strcmp ("cdrfs", mntent
.mnt_fstype
) == 0)
885 mount_entry
= g_new0 (GUnixMountPoint
, 1);
888 mount_entry
->mount_path
= g_strdup (mntent
.mnt_mount
);
889 mount_entry
->device_path
= g_strdup (mntent
.mnt_special
);
890 mount_entry
->filesystem_type
= g_strdup (mntent
.mnt_fstype
);
891 mount_entry
->is_read_only
= TRUE
;
892 mount_entry
->is_user_mountable
= TRUE
;
894 return_list
= g_list_prepend (return_list
, mount_entry
);
900 return g_list_reverse (return_list
);
903 #elif defined(HAVE_GETMNTINFO) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
906 _g_get_unix_mount_points (void)
908 struct fstab
*fstab
= NULL
;
909 GUnixMountPoint
*mount_entry
;
911 #ifdef HAVE_SYS_SYSCTL_H
913 size_t len
= sizeof(usermnt
);
922 #ifdef HAVE_SYS_SYSCTL_H
923 #if defined(HAVE_SYSCTLBYNAME)
924 sysctlbyname ("vfs.usermount", &usermnt
, &len
, NULL
, 0);
925 #elif defined(CTL_VFS) && defined(VFS_USERMOUNT)
930 mib
[1] = VFS_USERMOUNT
;
931 sysctl (mib
, 2, &usermnt
, &len
, NULL
, 0);
933 #elif defined(CTL_KERN) && defined(KERN_USERMOUNT)
938 mib
[1] = KERN_USERMOUNT
;
939 sysctl (mib
, 2, &usermnt
, &len
, NULL
, 0);
944 while ((fstab
= getfsent ()) != NULL
)
946 if (strcmp (fstab
->fs_vfstype
, "swap") == 0)
949 mount_entry
= g_new0 (GUnixMountPoint
, 1);
951 mount_entry
->mount_path
= g_strdup (fstab
->fs_file
);
952 mount_entry
->device_path
= g_strdup (fstab
->fs_spec
);
953 mount_entry
->filesystem_type
= g_strdup (fstab
->fs_vfstype
);
955 if (strcmp (fstab
->fs_type
, "ro") == 0)
956 mount_entry
->is_read_only
= TRUE
;
958 #ifdef HAVE_SYS_SYSCTL_H
961 uid_t uid
= getuid ();
962 if (stat (fstab
->fs_file
, &sb
) == 0)
964 if (uid
== 0 || sb
.st_uid
== uid
)
965 mount_entry
->is_user_mountable
= TRUE
;
970 return_list
= g_list_prepend (return_list
, mount_entry
);
975 return g_list_reverse (return_list
);
978 #error No g_get_mount_table() implementation for system
982 get_mounts_timestamp (void)
984 const char *monitor_file
;
987 monitor_file
= get_mtab_monitor_file ();
990 if (stat (monitor_file
, &buf
) == 0)
991 return (guint64
)buf
.st_mtime
;
997 get_mount_points_timestamp (void)
999 const char *monitor_file
;
1002 monitor_file
= get_fstab_file ();
1005 if (stat (monitor_file
, &buf
) == 0)
1006 return (guint64
)buf
.st_mtime
;
1012 * g_unix_mounts_get:
1013 * @time_read: guint64 to contain a timestamp.
1015 * Gets a #GList of strings containing the unix mounts.
1016 * If @time_read is set, it will be filled with the mount
1017 * timestamp, allowing for checking if the mounts have changed
1018 * with g_unix_mounts_changed_since().
1020 * Returns: a #GList of the UNIX mounts.
1023 g_unix_mounts_get (guint64
*time_read
)
1026 *time_read
= get_mounts_timestamp ();
1028 return _g_get_unix_mounts ();
1033 * @mount_path: path for a possible unix mount.
1034 * @time_read: guint64 to contain a timestamp.
1036 * Gets a #GUnixMountEntry for a given mount path. If @time_read
1037 * is set, it will be filled with a unix timestamp for checking
1038 * if the mounts have changed since with g_unix_mounts_changed_since().
1040 * Returns: a #GUnixMount.
1043 g_unix_mount_at (const char *mount_path
,
1047 GUnixMountEntry
*mount_entry
, *found
;
1049 mounts
= g_unix_mounts_get (time_read
);
1052 for (l
= mounts
; l
!= NULL
; l
= l
->next
)
1054 mount_entry
= l
->data
;
1056 if (strcmp (mount_path
, mount_entry
->mount_path
) == 0)
1057 found
= mount_entry
;
1059 g_unix_mount_free (mount_entry
);
1062 g_list_free (mounts
);
1068 * g_unix_mount_points_get:
1069 * @time_read: guint64 to contain a timestamp.
1071 * Gets a #GList of strings containing the unix mount points.
1072 * If @time_read is set, it will be filled with the mount timestamp,
1073 * allowing for checking if the mounts have changed with
1074 * g_unix_mounts_points_changed_since().
1076 * Returns: a #GList of the UNIX mountpoints.
1079 g_unix_mount_points_get (guint64
*time_read
)
1082 *time_read
= get_mount_points_timestamp ();
1084 return _g_get_unix_mount_points ();
1088 * g_unix_mounts_changed_since:
1089 * @time: guint64 to contain a timestamp.
1091 * Checks if the unix mounts have changed since a given unix time.
1093 * Returns: %TRUE if the mounts have changed since @time.
1096 g_unix_mounts_changed_since (guint64 time
)
1098 return get_mounts_timestamp () != time
;
1102 * g_unix_mount_points_changed_since:
1103 * @time: guint64 to contain a timestamp.
1105 * Checks if the unix mount points have changed since a given unix time.
1107 * Returns: %TRUE if the mount points have changed since @time.
1110 g_unix_mount_points_changed_since (guint64 time
)
1112 return get_mount_points_timestamp () != time
;
1116 g_unix_mount_monitor_finalize (GObject
*object
)
1118 GUnixMountMonitor
*monitor
;
1120 monitor
= G_UNIX_MOUNT_MONITOR (object
);
1122 if (monitor
->fstab_monitor
)
1124 g_file_monitor_cancel (monitor
->fstab_monitor
);
1125 g_object_unref (monitor
->fstab_monitor
);
1128 if (monitor
->mtab_monitor
)
1130 g_file_monitor_cancel (monitor
->mtab_monitor
);
1131 g_object_unref (monitor
->mtab_monitor
);
1134 the_mount_monitor
= NULL
;
1136 G_OBJECT_CLASS (g_unix_mount_monitor_parent_class
)->finalize (object
);
1141 g_unix_mount_monitor_class_init (GUnixMountMonitorClass
*klass
)
1143 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
1145 gobject_class
->finalize
= g_unix_mount_monitor_finalize
;
1147 * GUnixMountMonitor::mounts-changed:
1148 * @monitor: the object on which the signal is emitted
1150 * Emitted when the unix mounts have changed.
1152 signals
[MOUNTS_CHANGED
] =
1153 g_signal_new ("mounts-changed",
1154 G_TYPE_FROM_CLASS (klass
),
1158 g_cclosure_marshal_VOID__VOID
,
1161 * GUnixMountMonitor::mountpoints-changed:
1162 * @monitor: the object on which the signal is emitted
1164 * Emitted when the unix mount points have changed.
1166 signals
[MOUNTPOINTS_CHANGED
] =
1167 g_signal_new ("mountpoints-changed",
1168 G_TYPE_FROM_CLASS (klass
),
1172 g_cclosure_marshal_VOID__VOID
,
1177 fstab_file_changed (GFileMonitor
*monitor
,
1180 GFileMonitorEvent event_type
,
1183 GUnixMountMonitor
*mount_monitor
;
1185 if (event_type
!= G_FILE_MONITOR_EVENT_CHANGED
&&
1186 event_type
!= G_FILE_MONITOR_EVENT_CREATED
&&
1187 event_type
!= G_FILE_MONITOR_EVENT_DELETED
)
1190 mount_monitor
= user_data
;
1191 g_signal_emit (mount_monitor
, signals
[MOUNTPOINTS_CHANGED
], 0);
1195 mtab_file_changed (GFileMonitor
*monitor
,
1198 GFileMonitorEvent event_type
,
1201 GUnixMountMonitor
*mount_monitor
;
1203 if (event_type
!= G_FILE_MONITOR_EVENT_CHANGED
&&
1204 event_type
!= G_FILE_MONITOR_EVENT_CREATED
&&
1205 event_type
!= G_FILE_MONITOR_EVENT_DELETED
)
1208 mount_monitor
= user_data
;
1209 g_signal_emit (mount_monitor
, signals
[MOUNTS_CHANGED
], 0);
1213 g_unix_mount_monitor_init (GUnixMountMonitor
*monitor
)
1217 if (get_fstab_file () != NULL
)
1219 file
= g_file_new_for_path (get_fstab_file ());
1220 monitor
->fstab_monitor
= g_file_monitor_file (file
, 0, NULL
, NULL
);
1221 g_object_unref (file
);
1223 g_signal_connect (monitor
->fstab_monitor
, "changed", (GCallback
)fstab_file_changed
, monitor
);
1226 if (get_mtab_monitor_file () != NULL
)
1228 file
= g_file_new_for_path (get_mtab_monitor_file ());
1229 monitor
->mtab_monitor
= g_file_monitor_file (file
, 0, NULL
, NULL
);
1230 g_object_unref (file
);
1232 g_signal_connect (monitor
->mtab_monitor
, "changed", (GCallback
)mtab_file_changed
, monitor
);
1237 * g_unix_mount_monitor_set_rate_limit:
1238 * @mount_monitor: a #GUnixMountMonitor
1239 * @limit_msec: a integer with the limit in milliseconds to
1242 * Sets the rate limit to which the @mount_monitor will report
1243 * consecutive change events to the mount and mount point entry files.
1248 g_unix_mount_monitor_set_rate_limit (GUnixMountMonitor
*mount_monitor
,
1251 g_return_if_fail (G_IS_UNIX_MOUNT_MONITOR (mount_monitor
));
1253 if (mount_monitor
->fstab_monitor
!= NULL
)
1254 g_file_monitor_set_rate_limit (mount_monitor
->fstab_monitor
, limit_msec
);
1256 if (mount_monitor
->mtab_monitor
!= NULL
)
1257 g_file_monitor_set_rate_limit (mount_monitor
->mtab_monitor
, limit_msec
);
1261 * g_unix_mount_monitor_new:
1263 * Gets a new #GUnixMountMonitor. The default rate limit for which the
1264 * monitor will report consecutive changes for the mount and mount
1265 * point entry files is the default for a #GFileMonitor. Use
1266 * g_unix_mount_monitor_set_rate_limit() to change this.
1268 * Returns: a #GUnixMountMonitor.
1271 g_unix_mount_monitor_new (void)
1273 if (the_mount_monitor
== NULL
)
1275 the_mount_monitor
= g_object_new (G_TYPE_UNIX_MOUNT_MONITOR
, NULL
);
1276 return the_mount_monitor
;
1279 return g_object_ref (the_mount_monitor
);
1283 * g_unix_mount_free:
1284 * @mount_entry: a #GUnixMount.
1286 * Frees a unix mount.
1289 g_unix_mount_free (GUnixMountEntry
*mount_entry
)
1291 g_return_if_fail (mount_entry
!= NULL
);
1293 g_free (mount_entry
->mount_path
);
1294 g_free (mount_entry
->device_path
);
1295 g_free (mount_entry
->filesystem_type
);
1296 g_free (mount_entry
);
1300 * g_unix_mount_point_free:
1301 * @mount_point: unix mount point to free.
1303 * Frees a unix mount point.
1306 g_unix_mount_point_free (GUnixMountPoint
*mount_point
)
1308 g_return_if_fail (mount_point
!= NULL
);
1310 g_free (mount_point
->mount_path
);
1311 g_free (mount_point
->device_path
);
1312 g_free (mount_point
->filesystem_type
);
1313 g_free (mount_point
);
1317 * g_unix_mount_compare:
1318 * @mount1: first #GUnixMountEntry to compare.
1319 * @mount2: second #GUnixMountEntry to compare.
1321 * Compares two unix mounts.
1323 * Returns: 1, 0 or -1 if @mount1 is greater than, equal to,
1324 * or less than @mount2, respectively.
1327 g_unix_mount_compare (GUnixMountEntry
*mount1
,
1328 GUnixMountEntry
*mount2
)
1332 g_return_val_if_fail (mount1
!= NULL
&& mount2
!= NULL
, 0);
1334 res
= g_strcmp0 (mount1
->mount_path
, mount2
->mount_path
);
1338 res
= g_strcmp0 (mount1
->device_path
, mount2
->device_path
);
1342 res
= g_strcmp0 (mount1
->filesystem_type
, mount2
->filesystem_type
);
1346 res
= mount1
->is_read_only
- mount2
->is_read_only
;
1354 * g_unix_mount_get_mount_path:
1355 * @mount_entry: input #GUnixMountEntry to get the mount path for.
1357 * Gets the mount path for a unix mount.
1359 * Returns: the mount path for @mount_entry.
1362 g_unix_mount_get_mount_path (GUnixMountEntry
*mount_entry
)
1364 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
1366 return mount_entry
->mount_path
;
1370 * g_unix_mount_get_device_path:
1371 * @mount_entry: a #GUnixMount.
1373 * Gets the device path for a unix mount.
1375 * Returns: a string containing the device path.
1378 g_unix_mount_get_device_path (GUnixMountEntry
*mount_entry
)
1380 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
1382 return mount_entry
->device_path
;
1386 * g_unix_mount_get_fs_type:
1387 * @mount_entry: a #GUnixMount.
1389 * Gets the filesystem type for the unix mount.
1391 * Returns: a string containing the file system type.
1394 g_unix_mount_get_fs_type (GUnixMountEntry
*mount_entry
)
1396 g_return_val_if_fail (mount_entry
!= NULL
, NULL
);
1398 return mount_entry
->filesystem_type
;
1402 * g_unix_mount_is_readonly:
1403 * @mount_entry: a #GUnixMount.
1405 * Checks if a unix mount is mounted read only.
1407 * Returns: %TRUE if @mount_entry is read only.
1410 g_unix_mount_is_readonly (GUnixMountEntry
*mount_entry
)
1412 g_return_val_if_fail (mount_entry
!= NULL
, FALSE
);
1414 return mount_entry
->is_read_only
;
1418 * g_unix_mount_is_system_internal:
1419 * @mount_entry: a #GUnixMount.
1421 * Checks if a unix mount is a system path.
1423 * Returns: %TRUE if the unix mount is for a system path.
1426 g_unix_mount_is_system_internal (GUnixMountEntry
*mount_entry
)
1428 g_return_val_if_fail (mount_entry
!= NULL
, FALSE
);
1430 return mount_entry
->is_system_internal
;
1434 * g_unix_mount_point_compare:
1435 * @mount1: a #GUnixMount.
1436 * @mount2: a #GUnixMount.
1438 * Compares two unix mount points.
1440 * Returns: 1, 0 or -1 if @mount1 is greater than, equal to,
1441 * or less than @mount2, respectively.
1444 g_unix_mount_point_compare (GUnixMountPoint
*mount1
,
1445 GUnixMountPoint
*mount2
)
1449 g_return_val_if_fail (mount1
!= NULL
&& mount2
!= NULL
, 0);
1451 res
= g_strcmp0 (mount1
->mount_path
, mount2
->mount_path
);
1455 res
= g_strcmp0 (mount1
->device_path
, mount2
->device_path
);
1459 res
= g_strcmp0 (mount1
->filesystem_type
, mount2
->filesystem_type
);
1463 res
= mount1
->is_read_only
- mount2
->is_read_only
;
1467 res
= mount1
->is_user_mountable
- mount2
->is_user_mountable
;
1471 res
= mount1
->is_loopback
- mount2
->is_loopback
;
1479 * g_unix_mount_point_get_mount_path:
1480 * @mount_point: a #GUnixMountPoint.
1482 * Gets the mount path for a unix mount point.
1484 * Returns: a string containing the mount path.
1487 g_unix_mount_point_get_mount_path (GUnixMountPoint
*mount_point
)
1489 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
1491 return mount_point
->mount_path
;
1495 * g_unix_mount_point_get_device_path:
1496 * @mount_point: a #GUnixMountPoint.
1498 * Gets the device path for a unix mount point.
1500 * Returns: a string containing the device path.
1503 g_unix_mount_point_get_device_path (GUnixMountPoint
*mount_point
)
1505 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
1507 return mount_point
->device_path
;
1511 * g_unix_mount_point_get_fs_type:
1512 * @mount_point: a #GUnixMountPoint.
1514 * Gets the file system type for the mount point.
1516 * Returns: a string containing the file system type.
1519 g_unix_mount_point_get_fs_type (GUnixMountPoint
*mount_point
)
1521 g_return_val_if_fail (mount_point
!= NULL
, NULL
);
1523 return mount_point
->filesystem_type
;
1527 * g_unix_mount_point_is_readonly:
1528 * @mount_point: a #GUnixMountPoint.
1530 * Checks if a unix mount point is read only.
1532 * Returns: %TRUE if a mount point is read only.
1535 g_unix_mount_point_is_readonly (GUnixMountPoint
*mount_point
)
1537 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
1539 return mount_point
->is_read_only
;
1543 * g_unix_mount_point_is_user_mountable:
1544 * @mount_point: a #GUnixMountPoint.
1546 * Checks if a unix mount point is mountable by the user.
1548 * Returns: %TRUE if the mount point is user mountable.
1551 g_unix_mount_point_is_user_mountable (GUnixMountPoint
*mount_point
)
1553 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
1555 return mount_point
->is_user_mountable
;
1559 * g_unix_mount_point_is_loopback:
1560 * @mount_point: a #GUnixMountPoint.
1562 * Checks if a unix mount point is a loopback device.
1564 * Returns: %TRUE if the mount point is a loopback. %FALSE otherwise.
1567 g_unix_mount_point_is_loopback (GUnixMountPoint
*mount_point
)
1569 g_return_val_if_fail (mount_point
!= NULL
, FALSE
);
1571 return mount_point
->is_loopback
;
1574 static GUnixMountType
1575 guess_mount_type (const char *mount_path
,
1576 const char *device_path
,
1577 const char *filesystem_type
)
1579 GUnixMountType type
;
1582 type
= G_UNIX_MOUNT_TYPE_UNKNOWN
;
1584 if ((strcmp (filesystem_type
, "udf") == 0) ||
1585 (strcmp (filesystem_type
, "iso9660") == 0) ||
1586 (strcmp (filesystem_type
, "cd9660") == 0))
1587 type
= G_UNIX_MOUNT_TYPE_CDROM
;
1588 else if ((strcmp (filesystem_type
, "nfs") == 0) ||
1589 (strcmp (filesystem_type
, "nfs4") == 0))
1590 type
= G_UNIX_MOUNT_TYPE_NFS
;
1591 else if (g_str_has_prefix (device_path
, "/vol/dev/diskette/") ||
1592 g_str_has_prefix (device_path
, "/dev/fd") ||
1593 g_str_has_prefix (device_path
, "/dev/floppy"))
1594 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
1595 else if (g_str_has_prefix (device_path
, "/dev/cdrom") ||
1596 g_str_has_prefix (device_path
, "/dev/acd") ||
1597 g_str_has_prefix (device_path
, "/dev/cd"))
1598 type
= G_UNIX_MOUNT_TYPE_CDROM
;
1599 else if (g_str_has_prefix (device_path
, "/vol/"))
1601 const char *name
= mount_path
+ strlen ("/");
1603 if (g_str_has_prefix (name
, "cdrom"))
1604 type
= G_UNIX_MOUNT_TYPE_CDROM
;
1605 else if (g_str_has_prefix (name
, "floppy") ||
1606 g_str_has_prefix (device_path
, "/vol/dev/diskette/"))
1607 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
1608 else if (g_str_has_prefix (name
, "rmdisk"))
1609 type
= G_UNIX_MOUNT_TYPE_ZIP
;
1610 else if (g_str_has_prefix (name
, "jaz"))
1611 type
= G_UNIX_MOUNT_TYPE_JAZ
;
1612 else if (g_str_has_prefix (name
, "memstick"))
1613 type
= G_UNIX_MOUNT_TYPE_MEMSTICK
;
1617 basename
= g_path_get_basename (mount_path
);
1619 if (g_str_has_prefix (basename
, "cdr") ||
1620 g_str_has_prefix (basename
, "cdwriter") ||
1621 g_str_has_prefix (basename
, "burn") ||
1622 g_str_has_prefix (basename
, "dvdr"))
1623 type
= G_UNIX_MOUNT_TYPE_CDROM
;
1624 else if (g_str_has_prefix (basename
, "floppy"))
1625 type
= G_UNIX_MOUNT_TYPE_FLOPPY
;
1626 else if (g_str_has_prefix (basename
, "zip"))
1627 type
= G_UNIX_MOUNT_TYPE_ZIP
;
1628 else if (g_str_has_prefix (basename
, "jaz"))
1629 type
= G_UNIX_MOUNT_TYPE_JAZ
;
1630 else if (g_str_has_prefix (basename
, "camera"))
1631 type
= G_UNIX_MOUNT_TYPE_CAMERA
;
1632 else if (g_str_has_prefix (basename
, "memstick") ||
1633 g_str_has_prefix (basename
, "memory_stick") ||
1634 g_str_has_prefix (basename
, "ram"))
1635 type
= G_UNIX_MOUNT_TYPE_MEMSTICK
;
1636 else if (g_str_has_prefix (basename
, "compact_flash"))
1637 type
= G_UNIX_MOUNT_TYPE_CF
;
1638 else if (g_str_has_prefix (basename
, "smart_media"))
1639 type
= G_UNIX_MOUNT_TYPE_SM
;
1640 else if (g_str_has_prefix (basename
, "sd_mmc"))
1641 type
= G_UNIX_MOUNT_TYPE_SDMMC
;
1642 else if (g_str_has_prefix (basename
, "ipod"))
1643 type
= G_UNIX_MOUNT_TYPE_IPOD
;
1648 if (type
== G_UNIX_MOUNT_TYPE_UNKNOWN
)
1649 type
= G_UNIX_MOUNT_TYPE_HD
;
1655 * g_unix_mount_guess_type:
1656 * @mount_entry: a #GUnixMount.
1658 * Guesses the type of a unix mount. If the mount type cannot be
1659 * determined, returns %G_UNIX_MOUNT_TYPE_UNKNOWN.
1661 * Returns: a #GUnixMountType.
1663 static GUnixMountType
1664 g_unix_mount_guess_type (GUnixMountEntry
*mount_entry
)
1666 g_return_val_if_fail (mount_entry
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1667 g_return_val_if_fail (mount_entry
->mount_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1668 g_return_val_if_fail (mount_entry
->device_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1669 g_return_val_if_fail (mount_entry
->filesystem_type
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1671 return guess_mount_type (mount_entry
->mount_path
,
1672 mount_entry
->device_path
,
1673 mount_entry
->filesystem_type
);
1677 * g_unix_mount_point_guess_type:
1678 * @mount_point: a #GUnixMountPoint.
1680 * Guesses the type of a unix mount point.
1681 * If the mount type cannot be determined,
1682 * returns %G_UNIX_MOUNT_TYPE_UNKNOWN.
1684 * Returns: a #GUnixMountType.
1686 static GUnixMountType
1687 g_unix_mount_point_guess_type (GUnixMountPoint
*mount_point
)
1689 g_return_val_if_fail (mount_point
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1690 g_return_val_if_fail (mount_point
->mount_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1691 g_return_val_if_fail (mount_point
->device_path
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1692 g_return_val_if_fail (mount_point
->filesystem_type
!= NULL
, G_UNIX_MOUNT_TYPE_UNKNOWN
);
1694 return guess_mount_type (mount_point
->mount_path
,
1695 mount_point
->device_path
,
1696 mount_point
->filesystem_type
);
1700 type_to_icon (GUnixMountType type
, gboolean is_mount_point
)
1702 const char *icon_name
;
1706 case G_UNIX_MOUNT_TYPE_HD
:
1708 icon_name
= "drive-removable-media";
1710 icon_name
= "drive-harddisk";
1712 case G_UNIX_MOUNT_TYPE_FLOPPY
:
1713 case G_UNIX_MOUNT_TYPE_ZIP
:
1714 case G_UNIX_MOUNT_TYPE_JAZ
:
1716 icon_name
= "drive-removable-media";
1718 icon_name
= "media-floppy";
1720 case G_UNIX_MOUNT_TYPE_CDROM
:
1722 icon_name
= "drive-optical";
1724 icon_name
= "media-optical";
1726 case G_UNIX_MOUNT_TYPE_NFS
:
1727 /* TODO: Would like a better icon here... */
1729 icon_name
= "drive-removable-media";
1731 icon_name
= "drive-harddisk";
1733 case G_UNIX_MOUNT_TYPE_MEMSTICK
:
1735 icon_name
= "drive-removable-media";
1737 icon_name
= "media-flash";
1739 case G_UNIX_MOUNT_TYPE_CAMERA
:
1741 icon_name
= "drive-removable-media";
1743 icon_name
= "camera-photo";
1745 case G_UNIX_MOUNT_TYPE_IPOD
:
1747 icon_name
= "drive-removable-media";
1749 icon_name
= "multimedia-player";
1751 case G_UNIX_MOUNT_TYPE_UNKNOWN
:
1754 icon_name
= "drive-removable-media";
1756 icon_name
= "drive-harddisk";
1764 * g_unix_mount_guess_name:
1765 * @mount_entry: a #GUnixMountEntry
1767 * Guesses the name of a Unix mount.
1768 * The result is a translated string.
1770 * Returns: A newly allocated string that must
1771 * be freed with g_free()
1774 g_unix_mount_guess_name (GUnixMountEntry
*mount_entry
)
1778 if (strcmp (mount_entry
->mount_path
, "/") == 0)
1779 name
= g_strdup (_("Filesystem root"));
1781 name
= g_filename_display_basename (mount_entry
->mount_path
);
1787 * g_unix_mount_guess_icon:
1788 * @mount_entry: a #GUnixMountEntry
1790 * Guesses the icon of a Unix mount.
1795 g_unix_mount_guess_icon (GUnixMountEntry
*mount_entry
)
1797 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_guess_type (mount_entry
), FALSE
));
1801 * g_unix_mount_point_guess_name:
1802 * @mount_point: a #GUnixMountPoint
1804 * Guesses the name of a Unix mount point.
1805 * The result is a translated string.
1807 * Returns: A newly allocated string that must
1808 * be freed with g_free()
1811 g_unix_mount_point_guess_name (GUnixMountPoint
*mount_point
)
1815 if (strcmp (mount_point
->mount_path
, "/") == 0)
1816 name
= g_strdup (_("Filesystem root"));
1818 name
= g_filename_display_basename (mount_point
->mount_path
);
1824 * g_unix_mount_point_guess_icon:
1825 * @mount_point: a #GUnixMountPoint
1827 * Guesses the icon of a Unix mount point.
1832 g_unix_mount_point_guess_icon (GUnixMountPoint
*mount_point
)
1834 return g_themed_icon_new_with_default_fallbacks (type_to_icon (g_unix_mount_point_guess_type (mount_point
), TRUE
));
1838 * g_unix_mount_guess_can_eject:
1839 * @mount_entry: a #GUnixMountEntry
1841 * Guesses whether a Unix mount can be ejected.
1843 * Returns: %TRUE if @mount_entry is deemed to be ejectable.
1846 g_unix_mount_guess_can_eject (GUnixMountEntry
*mount_entry
)
1848 GUnixMountType guessed_type
;
1850 guessed_type
= g_unix_mount_guess_type (mount_entry
);
1851 if (guessed_type
== G_UNIX_MOUNT_TYPE_IPOD
||
1852 guessed_type
== G_UNIX_MOUNT_TYPE_CDROM
)
1859 * g_unix_mount_guess_should_display:
1860 * @mount_entry: a #GUnixMountEntry
1862 * Guesses whether a Unix mount should be displayed in the UI.
1864 * Returns: %TRUE if @mount_entry is deemed to be displayable.
1867 g_unix_mount_guess_should_display (GUnixMountEntry
*mount_entry
)
1869 const char *mount_path
;
1871 /* Never display internal mountpoints */
1872 if (g_unix_mount_is_system_internal (mount_entry
))
1875 /* Only display things in /media (which are generally user mountable)
1876 and home dir (fuse stuff) */
1877 mount_path
= mount_entry
->mount_path
;
1878 if (mount_path
!= NULL
)
1880 if (g_str_has_prefix (mount_path
, "/media/")) {
1882 /* Avoid displaying mounts that are not accessible to the user.
1884 * See http://bugzilla.gnome.org/show_bug.cgi?id=526320 for why we
1885 * want to avoid g_access() for every mount point.
1887 path
= g_path_get_dirname (mount_path
);
1888 if (g_str_has_prefix (path
, "/media/"))
1890 if (g_access (path
, R_OK
|X_OK
) != 0) {
1899 if (g_str_has_prefix (mount_path
, g_get_home_dir ()) && mount_path
[strlen (g_get_home_dir())] == G_DIR_SEPARATOR
)
1907 * g_unix_mount_point_guess_can_eject:
1908 * @mount_point: a #GUnixMountPoint
1910 * Guesses whether a Unix mount point can be ejected.
1912 * Returns: %TRUE if @mount_point is deemed to be ejectable.
1915 g_unix_mount_point_guess_can_eject (GUnixMountPoint
*mount_point
)
1917 GUnixMountType guessed_type
;
1919 guessed_type
= g_unix_mount_point_guess_type (mount_point
);
1920 if (guessed_type
== G_UNIX_MOUNT_TYPE_IPOD
||
1921 guessed_type
== G_UNIX_MOUNT_TYPE_CDROM
)
1928 /* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 */
1930 _canonicalize_filename (gchar
*filename
)
1933 gboolean last_was_slash
= FALSE
;
1940 if (*p
== G_DIR_SEPARATOR
)
1942 if (!last_was_slash
)
1943 *q
++ = G_DIR_SEPARATOR
;
1945 last_was_slash
= TRUE
;
1949 if (last_was_slash
&& *p
== '.')
1951 if (*(p
+ 1) == G_DIR_SEPARATOR
||
1954 if (*(p
+ 1) == '\0')
1959 else if (*(p
+ 1) == '.' &&
1960 (*(p
+ 2) == G_DIR_SEPARATOR
||
1963 if (q
> filename
+ 1)
1966 while (q
> filename
+ 1 &&
1967 *(q
- 1) != G_DIR_SEPARATOR
)
1971 if (*(p
+ 2) == '\0')
1979 last_was_slash
= FALSE
;
1985 last_was_slash
= FALSE
;
1992 if (q
> filename
+ 1 && *(q
- 1) == G_DIR_SEPARATOR
)
1999 _resolve_symlink (const char *file
)
2007 f
= g_strdup (file
);
2009 while (g_file_test (f
, G_FILE_TEST_IS_SYMLINK
)) {
2010 link
= g_file_read_link (f
, &error
);
2012 g_error_free (error
);
2018 dir
= g_path_get_dirname (f
);
2019 f1
= g_strdup_printf ("%s/%s", dir
, link
);
2028 _canonicalize_filename (f
);
2032 #ifdef HAVE_MNTENT_H
2034 _resolve_dev_root (void)
2036 static gboolean have_real_dev_root
= FALSE
;
2037 static char real_dev_root
[256];
2038 struct stat statbuf
;
2040 /* see if it's cached already */
2041 if (have_real_dev_root
)
2044 /* otherwise we're going to find it right away.. */
2045 have_real_dev_root
= TRUE
;
2047 if (stat ("/dev/root", &statbuf
) == 0) {
2048 if (! S_ISLNK (statbuf
.st_mode
)) {
2049 dev_t root_dev
= statbuf
.st_dev
;
2053 /* see if device with similar major:minor as /dev/root is mention
2054 * in /etc/mtab (it usually is)
2056 f
= fopen ("/etc/mtab", "r");
2058 struct mntent
*entp
;
2059 #ifdef HAVE_GETMNTENT_R
2061 while ((entp
= getmntent_r (f
, &ent
, buf
, sizeof (buf
))) != NULL
) {
2064 while ((entp
= getmntent (f
)) != NULL
) {
2066 if (stat (entp
->mnt_fsname
, &statbuf
) == 0 &&
2067 statbuf
.st_dev
== root_dev
) {
2068 strncpy (real_dev_root
, entp
->mnt_fsname
, sizeof (real_dev_root
) - 1);
2069 real_dev_root
[sizeof (real_dev_root
) - 1] = '\0';
2077 #ifndef HAVE_GETMNTENT_R
2078 G_UNLOCK (getmntent
);
2082 /* no, that didn't work.. next we could scan /dev ... but I digress.. */
2086 resolved
= _resolve_symlink ("/dev/root");
2087 if (resolved
!= NULL
) {
2088 strncpy (real_dev_root
, resolved
, sizeof (real_dev_root
) - 1);
2089 real_dev_root
[sizeof (real_dev_root
) - 1] = '\0';
2097 strcpy (real_dev_root
, "/dev/root");
2100 return real_dev_root
;
2104 #define __G_UNIX_MOUNTS_C__
2105 #include "gioaliasdef.c"