2 Return a list of mounted file systems
4 Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
5 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
7 Copyright (C) 1991, 1992, 2011
8 The Free Software Foundation, Inc.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * \brief Source: list of mounted filesystems
36 #include <stdint.h> /* SIZE_MAX */
37 #include <sys/types.h>
41 /* This header needs to be included before sys/mount.h on *BSD */
42 #ifdef HAVE_SYS_PARAM_H
43 #include <sys/param.h>
46 #if defined STAT_STATVFS || defined STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */
47 #include <sys/statvfs.h>
49 /* Don't include backward-compatibility files unless they're needed.
50 Eventually we'd like to remove all this cruft. */
55 #ifdef MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
56 #ifdef HAVE_SYS_UCRED_H
57 #include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
58 NGROUPS is used as an array dimension in ucred.h */
59 #include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
61 #ifdef HAVE_SYS_MOUNT_H
62 #include <sys/mount.h>
64 #ifdef HAVE_SYS_FS_TYPES_H
65 #include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
67 #ifdef HAVE_STRUCT_FSSTAT_F_FSTYPENAME
68 #define FS_TYPE(Ent) ((Ent).f_fstypename)
70 #define FS_TYPE(Ent) mnt_names[(Ent).f_type]
72 #endif /* MOUNTED_GETFSSTAT */
73 #endif /* STAT_STATVFS || STAT_STATVFS64 */
78 #ifdef HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */
79 #include <sys/fs/s5param.h>
81 #if defined HAVE_SYS_FILSYS_H && !defined _CRAY
82 #include <sys/filsys.h> /* SVR2 */
84 #ifdef HAVE_SYS_STATFS_H
85 #include <sys/statfs.h>
87 #ifdef HAVE_DUSTAT_H /* AIX PS/2 */
88 #include <sys/dustat.h>
91 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
94 #ifdef _PATH_MOUNTED /* GNU libc */
95 #define MOUNTED _PATH_MOUNTED
97 #ifdef MNT_MNTTAB /* HP-UX. */
98 #define MOUNTED MNT_MNTTAB
100 #ifdef MNTTABNAME /* Dynix. */
101 #define MOUNTED MNTTABNAME
106 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
107 #include <sys/mount.h>
110 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
111 #include <sys/statvfs.h>
114 #ifdef MOUNTED_GETMNT /* Ultrix. */
115 #include <sys/mount.h>
116 #include <sys/fs_types.h>
119 #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
124 #ifdef MOUNTED_FREAD /* SVR2. */
128 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
130 #include <sys/fstyp.h>
131 #include <sys/statfs.h>
134 #ifdef MOUNTED_LISTMNTENT
138 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
139 #include <sys/mnttab.h>
142 #ifdef MOUNTED_VMOUNT /* AIX. */
147 #ifdef MOUNTED_INTERIX_STATVFS /* Interix. */
148 #include <sys/statvfs.h>
153 /* So special that it's not worth putting this in autoconf. */
154 #undef MOUNTED_FREAD_FSTYP
155 #define MOUNTED_GETMNTTBL
158 #ifdef HAVE_SYS_MNTENT_H
159 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
160 #include <sys/mntent.h>
163 #ifndef HAVE_HASMNTOPT
164 #define hasmntopt(mnt, opt) ((char *) 0)
169 #define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
171 #define MNT_IGNORE(M) 0
174 #ifdef HAVE_INFOMOUNT_QNX
175 #include <sys/disk.h>
176 #include <sys/fsys.h>
179 #ifdef HAVE_SYS_STATVFS_H /* SVR4. */
180 #include <sys/statvfs.h>
183 #include "lib/global.h"
184 #include "mountlist.h"
186 /*** global variables ****************************************************************************/
188 /*** file scope macro definitions ****************************************************************/
190 #if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST)
191 #define HAVE_INFOMOUNT_QNX
194 #if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX)
195 #define HAVE_INFOMOUNT
198 /* The results of open() in this file are not used with fchdir,
199 therefore save some unnecessary work in fchdir.c. */
203 /* The results of opendir() in this file are not used with dirfd and fchdir,
204 therefore save some unnecessary work in fchdir.c. */
208 #define ME_DUMMY_0(Fs_name, Fs_type) \
209 (strcmp (Fs_type, "autofs") == 0 \
210 || strcmp (Fs_type, "proc") == 0 \
211 || strcmp (Fs_type, "subfs") == 0 \
212 /* for Linux 2.6/3.x */ \
213 || strcmp (Fs_type, "debugfs") == 0 \
214 || strcmp (Fs_type, "devpts") == 0 \
215 || strcmp (Fs_type, "fusectl") == 0 \
216 || strcmp (Fs_type, "mqueue") == 0 \
217 || strcmp (Fs_type, "rpc_pipefs") == 0 \
218 || strcmp (Fs_type, "sysfs") == 0 \
219 /* FreeBSD, Linux 2.4 */ \
220 || strcmp (Fs_type, "devfs") == 0 \
221 /* for NetBSD 3.0 */ \
222 || strcmp (Fs_type, "kernfs") == 0 \
224 || strcmp (Fs_type, "ignore") == 0)
226 /* Historically, we have marked as "dummy" any file system of type "none",
227 but now that programs like du need to know about bind-mounted directories,
228 we grant an exception to any with "bind" in its list of mount options.
229 I.e., those are *not* dummy entries. */
230 #ifdef MOUNTED_GETMNTENT1
231 #define ME_DUMMY(Fs_name, Fs_type, Fs_ent) \
232 (ME_DUMMY_0 (Fs_name, Fs_type) \
233 || (strcmp (Fs_type, "none") == 0 \
234 && !hasmntopt (Fs_ent, "bind")))
236 #define ME_DUMMY(Fs_name, Fs_type) \
237 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
242 #define ME_REMOTE me_remote
243 /* All cygwin mount points include `:' or start with `//'; so it
244 requires a native Windows call to determine remote disks. */
246 me_remote (char const *fs_name
, char const *fs_type _GL_UNUSED
)
248 if (fs_name
[0] && fs_name
[1] == ':')
251 sprintf (drive
, "%c:\\", fs_name
[0]);
252 switch (GetDriveType (drive
))
254 case DRIVE_REMOVABLE
:
265 /* A file system is `remote' if its Fs_name contains a `:'
266 or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */
267 #define ME_REMOTE(Fs_name, Fs_type) \
268 (strchr (Fs_name, ':') != NULL \
269 || ((Fs_name)[0] == '/' \
270 && (Fs_name)[1] == '/' \
271 && (strcmp (Fs_type, "smbfs") == 0 || strcmp (Fs_type, "cifs") == 0)))
274 /* Many space usage primitives use all 1 bits to denote a value that is
275 not applicable or unknown. Propagate this information by returning
276 a uintmax_t value that is all 1 bits if X is all 1 bits, even if X
277 is unsigned and narrower than uintmax_t. */
278 #define PROPAGATE_ALL_ONES(x) \
279 ((sizeof (x) < sizeof (uintmax_t) \
280 && (~ (x) == (sizeof (x) < sizeof (int) \
281 ? - (1 << (sizeof (x) * CHAR_BIT)) \
283 ? UINTMAX_MAX : (uintmax_t) (x))
285 /* Extract the top bit of X as an uintmax_t value. */
286 #define EXTRACT_TOP_BIT(x) ((x) & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1)))
288 /* If a value is negative, many space usage primitives store it into an
289 integer variable by assignment, even if the variable's type is unsigned.
290 So, if a space usage variable X's top bit is set, convert X to the
291 uintmax_t value V such that (- (uintmax_t) V) is the negative of
292 the original value. If X's top bit is clear, just yield X.
293 Use PROPAGATE_TOP_BIT if the original value might be negative;
294 otherwise, use PROPAGATE_ALL_ONES. */
295 #define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1))
298 /* Return true if statvfs works. This is false for statvfs on systems
299 with GNU libc on Linux kernels before 2.6.36, which stats all
300 preceding entries in /proc/mounts; that makes df hang if even one
301 of the corresponding file systems is hard-mounted but not available. */
302 #if ! (__linux__ && (__GLIBC__ || __UCLIBC__))
303 /* The FRSIZE fallback is not required in this case. */
304 #undef STAT_STATFS2_FRSIZE
311 #include <string.h> /* for strverscmp */
312 #include <sys/utsname.h>
313 #include <sys/statfs.h>
314 #define STAT_STATFS2_BSIZE 1
319 static int statvfs_works_cache
= -1;
322 if (statvfs_works_cache
< 0)
323 statvfs_works_cache
= (uname (&name
) == 0 && 0 <= strverscmp (name
.release
, "2.6.36"));
324 return statvfs_works_cache
;
329 #ifdef STAT_READ_FILSYS /* SVR2 */
330 /* Set errno to zero upon EOF. */
331 #define ZERO_BYTE_TRANSFER_ERRNO 0
334 #define IS_EINTR(x) ((x) == EINTR)
336 #define IS_EINTR(x) 0
338 #endif /* STAT_READ_FILSYS */
340 /*** file scope type declarations ****************************************************************/
342 /* A mount table entry. */
345 char *me_devname
; /* Device node name, including "/dev/". */
346 char *me_mountdir
; /* Mount point directory name. */
347 char *me_type
; /* "nfs", "4.2", etc. */
348 dev_t me_dev
; /* Device number of me_mountdir. */
349 unsigned int me_dummy
:1; /* Nonzero for dummy file systems. */
350 unsigned int me_remote
:1; /* Nonzero for remote fileystems. */
351 unsigned int me_type_malloced
:1; /* Nonzero if me_type was malloced. */
352 struct mount_entry
*me_next
;
357 uintmax_t fsu_blocksize
; /* Size of a block. */
358 uintmax_t fsu_blocks
; /* Total blocks. */
359 uintmax_t fsu_bfree
; /* Free blocks available to superuser. */
360 uintmax_t fsu_bavail
; /* Free blocks available to non-superuser. */
361 int fsu_bavail_top_bit_set
; /* 1 if fsu_bavail represents a value < 0. */
362 uintmax_t fsu_files
; /* Total file nodes. */
363 uintmax_t fsu_ffree
; /* Free file nodes. */
366 /*** file scope variables ************************************************************************/
368 #ifdef HAVE_INFOMOUNT_LIST
369 static struct mount_entry
*mc_mount_list
= NULL
;
370 #endif /* HAVE_INFOMOUNT_LIST */
372 /*** file scope functions ************************************************************************/
373 /* --------------------------------------------------------------------------------------------- */
375 #ifdef HAVE_INFOMOUNT_LIST
377 free_mount_entry (struct mount_entry
*me
)
381 g_free (me
->me_devname
);
382 g_free (me
->me_mountdir
);
383 if (me
->me_type_malloced
)
384 g_free (me
->me_type
);
388 /* --------------------------------------------------------------------------------------------- */
390 #ifdef MOUNTED_GETMNTINFO
392 #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
394 fstype_to_string (short int t
)
486 #endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */
488 /* --------------------------------------------------------------------------------------------- */
491 fsp_to_string (const struct statfs
*fsp
)
493 #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
494 return (char *) (fsp
->f_fstypename
);
496 return fstype_to_string (fsp
->f_type
);
499 #endif /* MOUNTED_GETMNTINFO */
501 /* --------------------------------------------------------------------------------------------- */
503 #ifdef MOUNTED_VMOUNT /* AIX. */
505 fstype_to_string (int t
)
509 e
= getvfsbytype (t
);
510 if (!e
|| !e
->vfsent_name
)
513 return e
->vfsent_name
;
515 #endif /* MOUNTED_VMOUNT */
517 /* --------------------------------------------------------------------------------------------- */
519 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
521 /* Return the device number from MOUNT_OPTIONS, if possible.
522 Otherwise return (dev_t) -1. */
524 /* --------------------------------------------------------------------------------------------- */
527 dev_from_mount_options (char const *mount_options
)
529 /* GNU/Linux allows file system implementations to define their own
530 meaning for "dev=" mount options, so don't trust the meaning
533 static char const dev_pattern
[] = ",dev=";
534 char const *devopt
= strstr (mount_options
, dev_pattern
);
538 char const *optval
= devopt
+ sizeof (dev_pattern
) - 1;
540 unsigned long int dev
;
542 dev
= strtoul (optval
, &optvalend
, 16);
543 if (optval
!= optvalend
544 && (*optvalend
== '\0' || *optvalend
== ',')
545 && !(dev
== ULONG_MAX
&& errno
== ERANGE
) && dev
== (dev_t
) dev
)
550 (void) mount_options
;
556 /* --------------------------------------------------------------------------------------------- */
558 #if defined _AIX && defined _I386
559 /* AIX PS/2 does not supply statfs. */
562 statfs (char *file
, struct statfs
*fsb
)
567 if (stat (file
, &stats
) != 0)
569 if (dustat (stats
.st_dev
, 0, &fsd
, sizeof (fsd
)))
572 fsb
->f_bsize
= fsd
.du_bsize
;
573 fsb
->f_blocks
= fsd
.du_fsize
- fsd
.du_isize
;
574 fsb
->f_bfree
= fsd
.du_tfree
;
575 fsb
->f_bavail
= fsd
.du_tfree
;
576 fsb
->f_files
= (fsd
.du_isize
- 2) * fsd
.du_inopb
;
577 fsb
->f_ffree
= fsd
.du_tinode
;
578 fsb
->f_fsid
.val
[0] = fsd
.du_site
;
579 fsb
->f_fsid
.val
[1] = fsd
.du_pckno
;
583 #endif /* _AIX && _I386 */
585 /* --------------------------------------------------------------------------------------------- */
587 /* Return a list of the currently mounted file systems, or NULL on error.
588 Add each entry to the tail of the list so that they stay in order.
589 If NEED_FS_TYPE is true, ensure that the file system type fields in
590 the returned list are valid. Otherwise, they might not be. */
592 static struct mount_entry
*
593 read_file_system_list (int need_fs_type
)
595 struct mount_entry
*mount_list
;
596 struct mount_entry
*me
;
597 struct mount_entry
**mtail
= &mount_list
;
599 #ifdef MOUNTED_LISTMNTENT
601 struct tabmntent
*mntlist
, *p
;
603 struct mount_entry
*me
;
605 /* the third and fourth arguments could be used to filter mounts,
606 but Crays doesn't seem to have any mounts that we want to
607 remove. Specifically, automount create normal NFS mounts.
610 if (listmntent (&mntlist
, KMTAB
, NULL
, NULL
) < 0)
612 for (p
= mntlist
; p
; p
= p
->next
)
615 me
= g_malloc (sizeof (*me
));
616 me
->me_devname
= g_strdup (mnt
->mnt_fsname
);
617 me
->me_mountdir
= g_strdup (mnt
->mnt_dir
);
618 me
->me_type
= g_strdup (mnt
->mnt_type
);
619 me
->me_type_malloced
= 1;
620 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
621 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
624 mtail
= &me
->me_next
;
626 freemntlist (mntlist
);
630 #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
633 const char *table
= MOUNTED
;
636 fp
= setmntent (table
, "r");
640 while ((mnt
= getmntent (fp
)))
642 me
= g_malloc (sizeof (*me
));
643 me
->me_devname
= g_strdup (mnt
->mnt_fsname
);
644 me
->me_mountdir
= g_strdup (mnt
->mnt_dir
);
645 me
->me_type
= g_strdup (mnt
->mnt_type
);
646 me
->me_type_malloced
= 1;
647 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
, mnt
);
648 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
649 me
->me_dev
= dev_from_mount_options (mnt
->mnt_opts
);
651 /* Add to the linked list. */
653 mtail
= &me
->me_next
;
656 if (endmntent (fp
) == 0)
659 #endif /* MOUNTED_GETMNTENT1. */
661 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
666 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
669 for (; entries
-- > 0; fsp
++)
671 char *fs_type
= fsp_to_string (fsp
);
673 me
= g_malloc (sizeof (*me
));
674 me
->me_devname
= g_strdup (fsp
->f_mntfromname
);
675 me
->me_mountdir
= g_strdup (fsp
->f_mntonname
);
676 me
->me_type
= fs_type
;
677 me
->me_type_malloced
= 0;
678 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
679 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
680 me
->me_dev
= (dev_t
) (-1); /* Magic; means not known yet. */
682 /* Add to the linked list. */
684 mtail
= &me
->me_next
;
687 #endif /* MOUNTED_GETMNTINFO */
689 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
694 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
697 for (; entries
-- > 0; fsp
++)
699 me
= g_malloc (sizeof (*me
));
700 me
->me_devname
= g_strdup (fsp
->f_mntfromname
);
701 me
->me_mountdir
= g_strdup (fsp
->f_mntonname
);
702 me
->me_type
= g_strdup (fsp
->f_fstypename
);
703 me
->me_type_malloced
= 1;
704 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
705 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
706 me
->me_dev
= (dev_t
) (-1); /* Magic; means not known yet. */
708 /* Add to the linked list. */
710 mtail
= &me
->me_next
;
713 #endif /* MOUNTED_GETMNTINFO2 */
715 #ifdef MOUNTED_GETMNT /* Ultrix. */
721 while (errno
= 0, 0 < (val
= getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, (char *) 0)))
723 me
= g_malloc (sizeof (*me
));
724 me
->me_devname
= g_strdup (fsd
.fd_req
.devname
);
725 me
->me_mountdir
= g_strdup (fsd
.fd_req
.path
);
726 me
->me_type
= gt_names
[fsd
.fd_req
.fstype
];
727 me
->me_type_malloced
= 0;
728 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
729 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
730 me
->me_dev
= fsd
.fd_req
.dev
;
732 /* Add to the linked list. */
734 mtail
= &me
->me_next
;
739 #endif /* MOUNTED_GETMNT. */
741 #if defined MOUNTED_FS_STAT_DEV /* BeOS */
743 /* The next_dev() and fs_stat_dev() system calls give the list of
744 all file systems, including the information returned by statvfs()
745 (fs type, total blocks, free blocks etc.), but without the mount
746 point. But on BeOS all file systems except / are mounted in the
747 rootfs, directly under /.
748 The directory name of the mount point is often, but not always,
749 identical to the volume name of the device.
750 We therefore get the list of subdirectories of /, and the list
751 of all file systems, and match the two lists. */
759 struct rootdir_entry
*next
;
761 struct rootdir_entry
*rootdir_list
;
762 struct rootdir_entry
**rootdir_tail
;
767 /* All volumes are mounted in the rootfs, directly under /. */
769 rootdir_tail
= &rootdir_list
;
770 dirp
= opendir ("/");
775 while ((d
= readdir (dirp
)) != NULL
)
780 if (strcmp (d
->d_name
, "..") == 0)
783 if (strcmp (d
->d_name
, ".") == 0)
784 name
= g_strdup ("/");
786 name
= g_strconcat ("/", d
->d_name
, (char *) NULL
);
788 if (lstat (name
, &statbuf
) >= 0 && S_ISDIR (statbuf
.st_mode
))
790 struct rootdir_entry
*re
= g_malloc (sizeof (*re
));
792 re
->dev
= statbuf
.st_dev
;
793 re
->ino
= statbuf
.st_ino
;
795 /* Add to the linked list. */
797 rootdir_tail
= &re
->next
;
804 *rootdir_tail
= NULL
;
806 for (pos
= 0; (dev
= next_dev (&pos
)) >= 0;)
807 if (fs_stat_dev (dev
, &fi
) >= 0)
809 /* Note: fi.dev == dev. */
810 struct rootdir_entry
*re
;
812 for (re
= rootdir_list
; re
; re
= re
->next
)
813 if (re
->dev
== fi
.dev
&& re
->ino
== fi
.root
)
816 me
= g_malloc (sizeof (*me
));
818 g_strdup (fi
.device_name
[0] != '\0' ? fi
.device_name
: fi
.fsh_name
);
819 me
->me_mountdir
= g_strdup (re
!= NULL
? re
->name
: fi
.fsh_name
);
820 me
->me_type
= g_strdup (fi
.fsh_name
);
821 me
->me_type_malloced
= 1;
824 me
->me_remote
= (fi
.flags
& B_FS_IS_SHARED
) != 0;
826 /* Add to the linked list. */
828 mtail
= &me
->me_next
;
832 while (rootdir_list
!= NULL
)
834 struct rootdir_entry
*re
= rootdir_list
;
835 rootdir_list
= re
->next
;
840 #endif /* MOUNTED_FS_STAT_DEV */
842 #ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
846 struct statfs
*stats
;
848 numsys
= getfsstat (NULL
, 0L, MNT_NOWAIT
);
851 if (SIZE_MAX
/ sizeof (*stats
) <= numsys
)
853 fprintf (stderr
, "%s\n", _("Memory exhausted!"));
857 bufsize
= (1 + numsys
) * sizeof (*stats
);
858 stats
= g_malloc (bufsize
);
859 numsys
= getfsstat (stats
, bufsize
, MNT_NOWAIT
);
867 for (counter
= 0; counter
< numsys
; counter
++)
869 me
= g_malloc (sizeof (*me
));
870 me
->me_devname
= g_strdup (stats
[counter
].f_mntfromname
);
871 me
->me_mountdir
= g_strdup (stats
[counter
].f_mntonname
);
872 me
->me_type
= g_strdup (FS_TYPE (stats
[counter
]));
873 me
->me_type_malloced
= 1;
874 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
875 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
876 me
->me_dev
= (dev_t
) (-1); /* Magic; means not known yet. */
878 /* Add to the linked list. */
880 mtail
= &me
->me_next
;
885 #endif /* MOUNTED_GETFSSTAT */
887 #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
890 char *table
= "/etc/mnttab";
893 fp
= fopen (table
, "r");
897 while (fread (&mnt
, sizeof (mnt
), 1, fp
) > 0)
899 me
= g_malloc (sizeof (*me
));
900 #ifdef GETFSTYP /* SVR3. */
901 me
->me_devname
= g_strdup (mnt
.mt_dev
);
903 me
->me_devname
= g_strconcat ("/dev/", mnt
.mt_dev
, (char *) NULL
);
905 me
->me_mountdir
= g_strdup (mnt
.mt_filsys
);
906 me
->me_dev
= (dev_t
) (-1); /* Magic; means not known yet. */
908 me
->me_type_malloced
= 0;
909 #ifdef GETFSTYP /* SVR3. */
913 char typebuf
[FSTYPSZ
];
915 if (statfs (me
->me_mountdir
, &fsd
, sizeof (fsd
), 0) != -1
916 && sysfs (GETFSTYP
, fsd
.f_fstyp
, typebuf
) != -1)
918 me
->me_type
= g_strdup (typebuf
);
919 me
->me_type_malloced
= 1;
923 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
924 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
926 /* Add to the linked list. */
928 mtail
= &me
->me_next
;
933 /* The last fread() call must have failed. */
934 int saved_errno
= errno
;
940 if (fclose (fp
) == EOF
)
943 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
945 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */
947 struct mntent
**mnttbl
= getmnttbl (), **ent
;
948 for (ent
= mnttbl
; *ent
; ent
++)
950 me
= g_malloc (sizeof (*me
));
951 me
->me_devname
= g_strdup ((*ent
)->mt_resource
);
952 me
->me_mountdir
= g_strdup ((*ent
)->mt_directory
);
953 me
->me_type
= g_strdup ((*ent
)->mt_fstype
);
954 me
->me_type_malloced
= 1;
955 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
956 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
957 me
->me_dev
= (dev_t
) (-1); /* Magic; means not known yet. */
959 /* Add to the linked list. */
961 mtail
= &me
->me_next
;
967 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
970 char *table
= MNTTAB
;
975 #if defined F_RDLCK && defined F_SETLKW
976 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
977 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
978 for this file name, we should use their macro name instead.
979 (Why not just lock MNTTAB directly? We don't know.) */
981 #define MNTTAB_LOCK "/etc/.mnttab.lock"
983 lockfd
= open (MNTTAB_LOCK
, O_RDONLY
);
987 flock
.l_type
= F_RDLCK
;
988 flock
.l_whence
= SEEK_SET
;
991 while (fcntl (lockfd
, F_SETLKW
, &flock
) == -1)
994 int saved_errno
= errno
;
1000 else if (errno
!= ENOENT
)
1005 fp
= fopen (table
, "r");
1010 while ((ret
= getmntent (fp
, &mnt
)) == 0)
1012 me
= g_malloc (sizeof (*me
));
1013 me
->me_devname
= g_strdup (mnt
.mnt_special
);
1014 me
->me_mountdir
= g_strdup (mnt
.mnt_mountp
);
1015 me
->me_type
= g_strdup (mnt
.mnt_fstype
);
1016 me
->me_type_malloced
= 1;
1017 me
->me_dummy
= MNT_IGNORE (&mnt
) != 0;
1018 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
1019 me
->me_dev
= dev_from_mount_options (mnt
.mnt_mntopts
);
1021 /* Add to the linked list. */
1023 mtail
= &me
->me_next
;
1026 ret
= fclose (fp
) == EOF
? errno
: 0 < ret
? 0 : -1;
1029 if (0 <= lockfd
&& close (lockfd
) != 0)
1035 goto free_then_fail
;
1038 #endif /* MOUNTED_GETMNTENT2. */
1040 #ifdef MOUNTED_VMOUNT /* AIX. */
1043 char *entries
, *thisent
;
1048 /* Ask how many bytes to allocate for the mounted file system info. */
1049 if (mntctl (MCTL_QUERY
, sizeof (bufsize
), (struct vmount
*) &bufsize
) != 0)
1051 entries
= g_malloc (bufsize
);
1053 /* Get the list of mounted file systems. */
1054 n_entries
= mntctl (MCTL_QUERY
, bufsize
, (struct vmount
*) entries
);
1057 int saved_errno
= errno
;
1059 errno
= saved_errno
;
1063 for (i
= 0, thisent
= entries
; i
< n_entries
; i
++, thisent
+= vmp
->vmt_length
)
1065 char *options
, *ignore
;
1067 vmp
= (struct vmount
*) thisent
;
1068 me
= g_malloc (sizeof (*me
));
1069 if (vmp
->vmt_flags
& MNT_REMOTE
)
1074 /* Prepend the remote dirname. */
1075 host
= thisent
+ vmp
->vmt_data
[VMT_HOSTNAME
].vmt_off
;
1076 dir
= thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
;
1077 me
->me_devname
= g_strconcat (host
, ":", dir
, (char *) NULL
);
1082 me
->me_devname
= g_strdup (thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
);
1084 me
->me_mountdir
= g_strdup (thisent
+ vmp
->vmt_data
[VMT_STUB
].vmt_off
);
1085 me
->me_type
= g_strdup (fstype_to_string (vmp
->vmt_gfstype
));
1086 me
->me_type_malloced
= 1;
1087 options
= thisent
+ vmp
->vmt_data
[VMT_ARGS
].vmt_off
;
1088 ignore
= strstr (options
, "ignore");
1089 me
->me_dummy
= (ignore
1090 && (ignore
== options
|| ignore
[-1] == ',')
1091 && (ignore
[sizeof ("ignore") - 1] == ','
1092 || ignore
[sizeof ("ignore") - 1] == '\0'));
1093 me
->me_dev
= (dev_t
) (-1); /* vmt_fsid might be the info we want. */
1095 /* Add to the linked list. */
1097 mtail
= &me
->me_next
;
1101 #endif /* MOUNTED_VMOUNT. */
1104 #ifdef MOUNTED_INTERIX_STATVFS
1106 DIR *dirp
= opendir ("/dev/fs");
1107 char node
[9 + NAME_MAX
];
1110 goto free_then_fail
;
1115 struct dirent entry
;
1116 struct dirent
*result
;
1118 if (readdir_r (dirp
, &entry
, &result
) || result
== NULL
)
1121 strcpy (node
, "/dev/fs/");
1122 strcat (node
, entry
.d_name
);
1124 if (statvfs (node
, &dev
) == 0)
1126 me
= g_malloc (sizeof *me
);
1127 me
->me_devname
= g_strdup (dev
.f_mntfromname
);
1128 me
->me_mountdir
= g_strdup (dev
.f_mntonname
);
1129 me
->me_type
= g_strdup (dev
.f_fstypename
);
1130 me
->me_type_malloced
= 1;
1131 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
1132 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
1133 me
->me_dev
= (dev_t
) (-1); /* Magic; means not known yet. */
1135 /* Add to the linked list. */
1137 mtail
= &me
->me_next
;
1141 #endif /* MOUNTED_INTERIX_STATVFS */
1143 (void) need_fs_type
; /* avoid argument-unused warning */
1150 int saved_errno
= errno
;
1155 me
= mount_list
->me_next
;
1156 g_free (mount_list
->me_devname
);
1157 g_free (mount_list
->me_mountdir
);
1158 if (mount_list
->me_type_malloced
)
1159 g_free (mount_list
->me_type
);
1160 g_free (mount_list
);
1164 errno
= saved_errno
;
1169 #endif /* HAVE_INFOMOUNT_LIST */
1171 /* --------------------------------------------------------------------------------------------- */
1173 #ifdef HAVE_INFOMOUNT_QNX
1175 ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
1176 ** this via the following code.
1177 ** Note that, as this is based on CWD, it only fills one mount_entry
1178 ** structure. See my_statfs() in utilunix.c for the "other side" of
1182 static struct mount_entry
*
1183 read_file_system_list (int need_fs_type
, int all_fs
)
1185 struct _disk_entry de
;
1188 char *tp
, dev
[_POSIX_NAME_MAX
], dir
[_POSIX_PATH_MAX
];
1190 static struct mount_entry
*me
= NULL
;
1194 g_free (me
->me_devname
);
1195 g_free (me
->me_mountdir
);
1196 g_free (me
->me_type
);
1199 me
= (struct mount_entry
*) g_malloc (sizeof (struct mount_entry
));
1201 if (!getcwd (dir
, _POSIX_PATH_MAX
))
1204 fd
= open (dir
, O_RDONLY
);
1208 i
= disk_get_entry (fd
, &de
);
1215 switch (de
.disk_type
)
1242 if (fsys_get_mount_dev (dir
, &dev
) == -1)
1245 if (fsys_get_mount_pt (dev
, &dir
) == -1)
1248 me
->me_devname
= g_strdup (dev
);
1249 me
->me_mountdir
= g_strdup (dir
);
1250 me
->me_type
= g_strdup (tp
);
1251 me
->me_dev
= de
.disk_type
;
1255 "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
1256 de
.disk_type
, tp
, _DRIVER_NAME_LEN
, _DRIVER_NAME_LEN
, de
.driver_name
, de
.disk_drv
);
1257 fprintf (stderr
, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev
);
1258 fprintf (stderr
, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir
);
1263 #endif /* HAVE_INFOMOUNT_QNX */
1265 /* --------------------------------------------------------------------------------------------- */
1267 #ifdef STAT_READ_FILSYS /* SVR2 */
1269 /* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
1270 interrupted. Return the actual number of bytes read(written), zero for EOF,
1271 or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */
1273 safe_read (int fd
, void *buf
, size_t count
)
1275 /* Work around a bug in Tru64 5.1. Attempting to read more than
1276 INT_MAX bytes fails with errno == EINVAL. See
1277 <http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
1278 When decreasing COUNT, keep it block-aligned. */
1280 enum { BUGGY_READ_MAXIMUM
= INT_MAX
& ~8191 };
1287 result
= read (fd
, buf
, count
);
1291 else if (IS_EINTR (errno
))
1293 else if (errno
== EINVAL
&& BUGGY_READ_MAXIMUM
< count
)
1294 count
= BUGGY_READ_MAXIMUM
;
1300 /* --------------------------------------------------------------------------------------------- */
1302 /* Read COUNT bytes at BUF to(from) descriptor FD, retrying if
1303 interrupted or if a partial write(read) occurs. Return the number
1304 of bytes transferred.
1305 When writing, set errno if fewer than COUNT bytes are written.
1306 When reading, if fewer than COUNT bytes are read, you must examine
1307 errno to distinguish failure from EOF (errno == 0). */
1310 full_read (int fd
, void *buf
, size_t count
)
1313 char *ptr
= (char *) buf
;
1317 size_t n_rw
= safe_read (fd
, ptr
, count
);
1318 if (n_rw
== (size_t) (-1))
1322 errno
= ZERO_BYTE_TRANSFER_ERRNO
;
1333 #endif /* STAT_READ_FILSYS */
1335 /* --------------------------------------------------------------------------------------------- */
1337 #ifdef HAVE_INFOMOUNT
1338 /* Fill in the fields of FSP with information about space usage for
1339 the file system on which FILE resides.
1340 DISK is the device on which FILE is mounted, for space-getting
1341 methods that need to know it.
1342 Return 0 if successful, -1 if not. When returning -1, ensure that
1343 ERRNO is either a system error value, or zero if DISK is NULL
1344 on a system that requires a non-NULL value. */
1346 get_fs_usage (char const *file
, char const *disk
, struct fs_usage
*fsp
)
1348 #ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */
1350 if (statvfs_works ())
1352 struct statvfs vfsd
;
1354 if (statvfs (file
, &vfsd
) < 0)
1357 /* f_frsize isn't guaranteed to be supported. */
1358 fsp
->fsu_blocksize
= (vfsd
.f_frsize
1359 ? PROPAGATE_ALL_ONES (vfsd
.f_frsize
)
1360 : PROPAGATE_ALL_ONES (vfsd
.f_bsize
));
1362 fsp
->fsu_blocks
= PROPAGATE_ALL_ONES (vfsd
.f_blocks
);
1363 fsp
->fsu_bfree
= PROPAGATE_ALL_ONES (vfsd
.f_bfree
);
1364 fsp
->fsu_bavail
= PROPAGATE_TOP_BIT (vfsd
.f_bavail
);
1365 fsp
->fsu_bavail_top_bit_set
= EXTRACT_TOP_BIT (vfsd
.f_bavail
) != 0;
1366 fsp
->fsu_files
= PROPAGATE_ALL_ONES (vfsd
.f_files
);
1367 fsp
->fsu_ffree
= PROPAGATE_ALL_ONES (vfsd
.f_ffree
);
1373 #if defined STAT_STATVFS64 /* AIX */
1375 struct statvfs64 fsd
;
1377 if (statvfs64 (file
, &fsd
) < 0)
1380 /* f_frsize isn't guaranteed to be supported. */
1382 fsp
->fsu_blocksize
= fsd
.f_frsize
1383 ? PROPAGATE_ALL_ONES (fsd
.f_frsize
)
1384 : PROPAGATE_ALL_ONES (fsd
.f_bsize
);
1387 #elif defined STAT_STATFS2_FS_DATA /* Ultrix */
1391 if (statfs (file
, &fsd
) != 1)
1394 fsp
->fsu_blocksize
= 1024;
1395 fsp
->fsu_blocks
= PROPAGATE_ALL_ONES (fsd
.fd_req
.btot
);
1396 fsp
->fsu_bfree
= PROPAGATE_ALL_ONES (fsd
.fd_req
.bfree
);
1397 fsp
->fsu_bavail
= PROPAGATE_TOP_BIT (fsd
.fd_req
.bfreen
);
1398 fsp
->fsu_bavail_top_bit_set
= EXTRACT_TOP_BIT (fsd
.fd_req
.bfreen
) != 0;
1399 fsp
->fsu_files
= PROPAGATE_ALL_ONES (fsd
.fd_req
.gtot
);
1400 fsp
->fsu_ffree
= PROPAGATE_ALL_ONES (fsd
.fd_req
.gfree
);
1402 #elif defined STAT_READ_FILSYS /* SVR2 */
1404 #define SUPERBOFF (SUPERB * 512)
1416 fd
= open (disk
, O_RDONLY
);
1419 lseek (fd
, (off_t
) SUPERBOFF
, 0);
1420 if (full_read (fd
, (char *) &fsd
, sizeof (fsd
)) != sizeof (fsd
))
1427 fsp
->fsu_blocksize
= (fsd
.s_type
== Fs2b
? 1024 : 512);
1428 fsp
->fsu_blocks
= PROPAGATE_ALL_ONES (fsd
.s_fsize
);
1429 fsp
->fsu_bfree
= PROPAGATE_ALL_ONES (fsd
.s_tfree
);
1430 fsp
->fsu_bavail
= PROPAGATE_TOP_BIT (fsd
.s_tfree
);
1431 fsp
->fsu_bavail_top_bit_set
= EXTRACT_TOP_BIT (fsd
.s_tfree
) != 0;
1432 fsp
->fsu_files
= (fsd
.s_isize
== -1
1433 ? UINTMAX_MAX
: (fsd
.s_isize
- 2) * INOPB
* (fsd
.s_type
== Fs2b
? 2 : 1));
1434 fsp
->fsu_ffree
= PROPAGATE_ALL_ONES (fsd
.s_tinode
);
1436 #elif defined STAT_STATFS3_OSF1 /* OSF/1 */
1440 if (statfs (file
, &fsd
, sizeof (struct statfs
)) != 0)
1443 fsp
->fsu_blocksize
= PROPAGATE_ALL_ONES (fsd
.f_fsize
);
1445 #elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */
1449 if (statfs (file
, &fsd
) < 0)
1452 fsp
->fsu_blocksize
= PROPAGATE_ALL_ONES (fsd
.f_frsize
);
1454 #elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \
1455 Mac OS X < 10.4, FreeBSD < 5.0, \
1456 NetBSD < 3.0, OpenBSD < 4.4 */
1460 if (statfs (file
, &fsd
) < 0)
1463 fsp
->fsu_blocksize
= PROPAGATE_ALL_ONES (fsd
.f_bsize
);
1465 #ifdef STATFS_TRUNCATES_BLOCK_COUNTS
1467 /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
1468 struct statfs are truncated to 2GB. These conditions detect that
1469 truncation, presumably without botching the 4.1.1 case, in which
1470 the values are not truncated. The correct counts are stored in
1471 undocumented spare fields. */
1472 if (fsd
.f_blocks
== 0x7fffffff / fsd
.f_bsize
&& fsd
.f_spare
[0] > 0)
1474 fsd
.f_blocks
= fsd
.f_spare
[0];
1475 fsd
.f_bfree
= fsd
.f_spare
[1];
1476 fsd
.f_bavail
= fsd
.f_spare
[2];
1478 #endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
1480 #elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */
1484 if (statfs (file
, &fsd
) < 0)
1487 fsp
->fsu_blocksize
= PROPAGATE_ALL_ONES (fsd
.f_fsize
);
1489 #elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \
1492 #if !defined _AIX && !defined _SEQUENT_ && !defined DOLPHIN
1493 #define f_bavail f_bfree
1498 if (statfs (file
, &fsd
, sizeof (fsd
), 0) < 0)
1501 /* Empirically, the block counts on most SVR3 and SVR3-derived
1502 systems seem to always be in terms of 512-byte blocks,
1503 no matter what value f_bsize has. */
1504 #if defined _AIX || defined _CRAY
1505 fsp
->fsu_blocksize
= PROPAGATE_ALL_ONES (fsd
.f_bsize
);
1507 fsp
->fsu_blocksize
= 512;
1512 #if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
1513 || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \
1514 || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)
1516 fsp
->fsu_blocks
= PROPAGATE_ALL_ONES (fsd
.f_blocks
);
1517 fsp
->fsu_bfree
= PROPAGATE_ALL_ONES (fsd
.f_bfree
);
1518 fsp
->fsu_bavail
= PROPAGATE_TOP_BIT (fsd
.f_bavail
);
1519 fsp
->fsu_bavail_top_bit_set
= EXTRACT_TOP_BIT (fsd
.f_bavail
) != 0;
1520 fsp
->fsu_files
= PROPAGATE_ALL_ONES (fsd
.f_files
);
1521 fsp
->fsu_ffree
= PROPAGATE_ALL_ONES (fsd
.f_ffree
);
1526 (void) disk
; /* avoid argument-unused warning */
1530 #endif /* HAVE_INFOMOUNT */
1532 /* --------------------------------------------------------------------------------------------- */
1533 /*** public functions ****************************************************************************/
1534 /* --------------------------------------------------------------------------------------------- */
1537 free_my_statfs (void)
1539 #ifdef HAVE_INFOMOUNT_LIST
1540 while (mc_mount_list
!= NULL
)
1542 struct mount_entry
*next
;
1544 next
= mc_mount_list
->me_next
;
1545 free_mount_entry (mc_mount_list
);
1546 mc_mount_list
= next
;
1549 mc_mount_list
= NULL
;
1550 #endif /* HAVE_INFOMOUNT_LIST */
1553 /* --------------------------------------------------------------------------------------------- */
1556 init_my_statfs (void)
1558 #ifdef HAVE_INFOMOUNT_LIST
1560 mc_mount_list
= read_file_system_list (1);
1561 #endif /* HAVE_INFOMOUNT_LIST */
1564 /* --------------------------------------------------------------------------------------------- */
1567 my_statfs (struct my_statfs
*myfs_stats
, const char *path
)
1569 #ifdef HAVE_INFOMOUNT_LIST
1571 struct mount_entry
*entry
= NULL
;
1572 struct mount_entry
*temp
= mc_mount_list
;
1573 struct fs_usage fs_use
;
1577 i
= strlen (temp
->me_mountdir
);
1578 if (i
> len
&& (strncmp (path
, temp
->me_mountdir
, i
) == 0))
1579 if (!entry
|| (path
[i
] == PATH_SEP
|| path
[i
] == '\0'))
1584 temp
= temp
->me_next
;
1589 memset (&fs_use
, 0, sizeof (struct fs_usage
));
1590 get_fs_usage (entry
->me_mountdir
, NULL
, &fs_use
);
1592 myfs_stats
->type
= entry
->me_dev
;
1593 myfs_stats
->typename
= entry
->me_type
;
1594 myfs_stats
->mpoint
= entry
->me_mountdir
;
1595 myfs_stats
->device
= entry
->me_devname
;
1597 ((uintmax_t) (getuid ()? fs_use
.fsu_bavail
: fs_use
.fsu_bfree
) *
1598 fs_use
.fsu_blocksize
) >> 10;
1599 myfs_stats
->total
= ((uintmax_t) fs_use
.fsu_blocks
* fs_use
.fsu_blocksize
) >> 10;
1600 myfs_stats
->nfree
= (uintmax_t) fs_use
.fsu_ffree
;
1601 myfs_stats
->nodes
= (uintmax_t) fs_use
.fsu_files
;
1604 #endif /* HAVE_INFOMOUNT_LIST */
1606 #ifdef HAVE_INFOMOUNT_QNX
1608 ** This is the "other side" of the hack to read_file_system_list() in
1610 ** It's not the most efficient approach, but consumes less memory. It
1611 ** also accomodates QNX's ability to mount filesystems on the fly.
1613 struct mount_entry
*entry
;
1614 struct fs_usage fs_use
;
1616 entry
= read_file_system_list (0, 0);
1619 get_fs_usage (entry
->me_mountdir
, NULL
, &fs_use
);
1621 myfs_stats
->type
= entry
->me_dev
;
1622 myfs_stats
->typename
= entry
->me_type
;
1623 myfs_stats
->mpoint
= entry
->me_mountdir
;
1624 myfs_stats
->device
= entry
->me_devname
;
1626 myfs_stats
->avail
= ((uintmax_t) fs_use
.fsu_bfree
* fs_use
.fsu_blocksize
) >> 10;
1627 myfs_stats
->total
= ((uintmax_t) fs_use
.fsu_blocks
* fs_use
.fsu_blocksize
) >> 10;
1628 myfs_stats
->nfree
= (uintmax_t) fs_use
.fsu_ffree
;
1629 myfs_stats
->nodes
= (uintmax_t) fs_use
.fsu_files
;
1632 #endif /* HAVE_INFOMOUNT_QNX */
1634 myfs_stats
->type
= 0;
1635 myfs_stats
->mpoint
= "unknown";
1636 myfs_stats
->device
= "unknown";
1637 myfs_stats
->avail
= 0;
1638 myfs_stats
->total
= 0;
1639 myfs_stats
->nfree
= 0;
1640 myfs_stats
->nodes
= 0;
1644 /* --------------------------------------------------------------------------------------------- */