diff --git a/acinclude.m4 b/acinclude.m4 index 222661877..4ee84340a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -3,7 +3,11 @@ m4_include([m4.include/ax_path_lib_pcre.m4]) m4_include([m4.include/dx_doxygen.m4]) m4_include([m4.include/mc-cflags.m4]) m4_include([m4.include/mc-check-search-type.m4]) -m4_include([m4.include/ac-get-fs-info.m4]) +m4_include([m4.include/ls-mntd-fs.m4]) +m4_include([m4.include/fstypename.m4]) +m4_include([m4.include/fsusage.m4]) +m4_include([m4.include/mountlist.m4]) +m4_include([m4.include/mc-get-fs-info.m4]) m4_include([m4.include/mc-use-termcap.m4]) m4_include([m4.include/mc-with-screen.m4]) m4_include([m4.include/ac-glib.m4]) diff --git a/configure.ac b/configure.ac index 7b6384bd8..150e222c0 100644 --- a/configure.ac +++ b/configure.ac @@ -72,6 +72,7 @@ AM_CONDITIONAL([ENABLE_MCLIB], [test x$enable_mclib = xyes]) AC_HEADER_MAJOR AC_C_CONST +dnl Check this before type sizeof checks AC_SYS_LARGEFILE AC_PROG_LN_S @@ -209,11 +210,7 @@ AC_TYPE_UID_T AC_FUNC_ALLOCA AC_FUNC_STRCOLL -dnl -dnl This is from GNU fileutils, check aclocal.m4 for more information -dnl uintmat_t is required for FS info -dnl -AC_GET_FS_INFO +AC_MC_GET_FS_INFO dnl dnl X11 support. diff --git a/m4.include/ac-get-fs-info.m4 b/m4.include/ac-get-fs-info.m4 deleted file mode 100644 index 5256f623b..000000000 --- a/m4.include/ac-get-fs-info.m4 +++ /dev/null @@ -1,676 +0,0 @@ -#serial 6 - -# How to list mounted file systems. - -# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software -# Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -dnl From Jim Meyering. -dnl -dnl This is not pretty. I've just taken the autoconf code and wrapped -dnl it in an AC_DEFUN and made some other fixes. -dnl - -# Replace Autoconf's AC_FUNC_GETMNTENT to work around a bug in Autoconf -# through Autoconf 2.59. We can remove this once we assume Autoconf 2.60 -# or later. -AC_DEFUN([AC_FUNC_GETMNTENT], -[# getmntent is in the standard C library on UNICOS, in -lsun on Irix 4, -# -lseq on Dynix/PTX, -lgen on Unixware. -AC_SEARCH_LIBS(getmntent, [sun seq gen]) -AC_CHECK_FUNCS(getmntent) -]) - -# gl_LIST_MOUNTED_FILE_SYSTEMS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -AC_DEFUN([gl_LIST_MOUNTED_FILE_SYSTEMS], - [ -AC_CHECK_FUNCS(listmntent getmntinfo) -AC_CHECK_HEADERS_ONCE(sys/param.h sys/statvfs.h) - -# We must include grp.h before ucred.h on OSF V4.0, since ucred.h uses -# NGROUPS (as the array dimension for a struct member) without a definition. -AC_CHECK_HEADERS(sys/ucred.h, [], [], [#include ]) - -AC_CHECK_HEADERS(sys/mount.h, [], [], - [AC_INCLUDES_DEFAULT - [#if HAVE_SYS_PARAM_H - #include - #endif]]) - -AC_CHECK_HEADERS(mntent.h sys/fs_types.h) - getfsstat_includes="\ -$ac_includes_default -#if HAVE_SYS_PARAM_H -# include /* needed by powerpc-apple-darwin1.3.7 */ -#endif -#if HAVE_SYS_UCRED_H -# include /* needed for definition of NGROUPS */ -# include /* needed by powerpc-apple-darwin1.3.7 */ -#endif -#if HAVE_SYS_MOUNT_H -# include -#endif -#if HAVE_SYS_FS_TYPES_H -# include /* needed by powerpc-apple-darwin1.3.7 */ -#endif -" -AC_CHECK_MEMBERS([struct fsstat.f_fstypename],,,[$getfsstat_includes]) - -# Determine how to get the list of mounted file systems. -ac_list_mounted_fs= - -# If the getmntent function is available but not in the standard library, -# make sure LIBS contains the appropriate -l option. -AC_FUNC_GETMNTENT - -# This test must precede the ones for getmntent because Unicos-9 is -# reported to have the getmntent function, but its support is incompatible -# with other getmntent implementations. - -# NOTE: Normally, I wouldn't use a check for system type as I've done for -# `CRAY' below since that goes against the whole autoconf philosophy. But -# I think there is too great a chance that some non-Cray system has a -# function named listmntent to risk the false positive. - -if test x"$ac_list_mounted_fs" = x; then - # Cray UNICOS 9 - AC_MSG_CHECKING([for listmntent of Cray/Unicos-9]) - AC_CACHE_VAL(fu_cv_sys_mounted_cray_listmntent, - [fu_cv_sys_mounted_cray_listmntent=no - AC_EGREP_CPP(yes, - [#ifdef _CRAY -yes -#endif - ], [test x"$ac_cv_func_listmntent" = xyes \ - && fu_cv_sys_mounted_cray_listmntent=yes] - ) - ] - ) - AC_MSG_RESULT($fu_cv_sys_mounted_cray_listmntent) - if test x"$fu_cv_sys_mounted_cray_listmntent" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_LISTMNTENT, 1, - [Define if there is a function named listmntent that can be used to - list all mounted file systems. (UNICOS)]) - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - # AIX. - AC_MSG_CHECKING([for mntctl function and struct vmount]) - AC_CACHE_VAL(fu_cv_sys_mounted_vmount, - [AC_TRY_CPP([#include ], - fu_cv_sys_mounted_vmount=yes, - fu_cv_sys_mounted_vmount=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_vmount) - if test x"$fu_cv_sys_mounted_vmount" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_VMOUNT, 1, - [Define if there is a function named mntctl that can be used to read - the list of mounted file systems, and there is a system header file - that declares `struct vmount.' (AIX)]) - fi -fi - -if test x"$ac_cv_func_getmntent" = xyes; then - - # This system has the getmntent function. - # Determine whether it's the one-argument variant or the two-argument one. - - if test x"$ac_list_mounted_fs" = x; then - # 4.3BSD, SunOS, HP-UX, Dynix, Irix - AC_MSG_CHECKING([for one-argument getmntent function]) - AC_CACHE_VAL(fu_cv_sys_mounted_getmntent1, - [AC_TRY_COMPILE([ -/* SunOS 4.1.x /usr/include/mntent.h needs this for FILE */ -#include - -#include -#if !defined MOUNTED -# if defined _PATH_MOUNTED /* GNU libc */ -# define MOUNTED _PATH_MOUNTED -# endif -# if defined MNT_MNTTAB /* HP-UX. */ -# define MOUNTED MNT_MNTTAB -# endif -# if defined MNTTABNAME /* Dynix. */ -# define MOUNTED MNTTABNAME -# endif -#endif -], - [ struct mntent *mnt = 0; const char *table = MOUNTED; - if (sizeof mnt && sizeof table) return 0;], - fu_cv_sys_mounted_getmntent1=yes, - fu_cv_sys_mounted_getmntent1=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_getmntent1) - if test x"$fu_cv_sys_mounted_getmntent1" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_GETMNTENT1, 1, - [Define if there is a function named getmntent for reading the list - of mounted file systems, and that function takes a single argument. - (4.3BSD, SunOS, HP-UX, Dynix, Irix)]) - fi - fi - - if test x"$ac_list_mounted_fs" = x; then - # SVR4 - AC_MSG_CHECKING([for two-argument getmntent function]) - AC_CACHE_VAL(fu_cv_sys_mounted_getmntent2, - [AC_EGREP_HEADER(getmntent, sys/mnttab.h, - fu_cv_sys_mounted_getmntent2=yes, - fu_cv_sys_mounted_getmntent2=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_getmntent2) - if test x"$fu_cv_sys_mounted_getmntent2" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_GETMNTENT2, 1, - [Define if there is a function named getmntent for reading the list of - mounted file systems, and that function takes two arguments. (SVR4)]) - AC_CHECK_FUNCS(hasmntopt) - fi - fi - -fi - -if test x"$ac_list_mounted_fs" = x; then - # DEC Alpha running OSF/1, and Apple Darwin 1.3. - # powerpc-apple-darwin1.3.7 needs sys/param.h sys/ucred.h sys/fs_types.h - - AC_MSG_CHECKING([for getfsstat function]) - AC_CACHE_VAL(fu_cv_sys_mounted_getfsstat, - [AC_TRY_LINK([ -#include -#if HAVE_STRUCT_FSSTAT_F_FSTYPENAME -# define FS_TYPE(Ent) ((Ent).f_fstypename) -#else -# define FS_TYPE(Ent) mnt_names[(Ent).f_type] -#endif -]$getfsstat_includes -, - [struct statfs *stats; - int numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT); - char *t = FS_TYPE (*stats); ], - fu_cv_sys_mounted_getfsstat=yes, - fu_cv_sys_mounted_getfsstat=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_getfsstat) - if test x"$fu_cv_sys_mounted_getfsstat" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_GETFSSTAT, 1, - [Define if there is a function named getfsstat for reading the - list of mounted file systems. (DEC Alpha running OSF/1)]) - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - # SVR3 - AC_MSG_CHECKING([for FIXME existence of three headers]) - AC_CACHE_VAL(fu_cv_sys_mounted_fread_fstyp, - [AC_TRY_CPP([ -#include -#include -#include ], - fu_cv_sys_mounted_fread_fstyp=yes, - fu_cv_sys_mounted_fread_fstyp=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_fread_fstyp) - if test x"$fu_cv_sys_mounted_fread_fstyp" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_FREAD_FSTYP, 1, - [Define if (like SVR2) there is no specific function for reading the - list of mounted file systems, and your system has these header files: - and . (SVR3)]) - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - # 4.4BSD and DEC OSF/1. - AC_MSG_CHECKING([for getmntinfo function]) - AC_CACHE_VAL(fu_cv_sys_mounted_getmntinfo, - [ - test x"$ac_cv_func_getmntinfo" = xyes \ - && fu_cv_sys_mounted_getmntinfo=yes \ - || fu_cv_sys_mounted_getmntinfo=no - ]) - AC_MSG_RESULT($fu_cv_sys_mounted_getmntinfo) - if test x"$fu_cv_sys_mounted_getmntinfo" = xyes; then - AC_MSG_CHECKING([whether getmntinfo returns statvfs structures]) - AC_CACHE_VAL(fu_cv_sys_mounted_getmntinfo2, - [ - AC_TRY_COMPILE([ -#if HAVE_SYS_PARAM_H -# include -#endif -#include -#if HAVE_SYS_MOUNT_H -# include -#endif -#if HAVE_SYS_STATVFS_H -# include -#endif -extern int getmntinfo (struct statfs **, int); - ], [], - [fu_cv_sys_mounted_getmntinfo2=no], - [fu_cv_sys_mounted_getmntinfo2=yes]) - ]) - AC_MSG_RESULT([$fu_cv_sys_mounted_getmntinfo2]) - if test x"$fu_cv_sys_mounted_getmntinfo2" = xno; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_GETMNTINFO, 1, - [Define if there is a function named getmntinfo for reading the - list of mounted file systems and it returns an array of - 'struct statfs'. (4.4BSD, Darwin)]) - else - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_GETMNTINFO2, 1, - [Define if there is a function named getmntinfo for reading the - list of mounted file systems and it returns an array of - 'struct statvfs'. (NetBSD 3.0)]) - fi - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - # Ultrix - AC_MSG_CHECKING([for getmnt function]) - AC_CACHE_VAL(fu_cv_sys_mounted_getmnt, - [AC_TRY_CPP([ -#include -#include ], - fu_cv_sys_mounted_getmnt=yes, - fu_cv_sys_mounted_getmnt=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_getmnt) - if test x"$fu_cv_sys_mounted_getmnt" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_GETMNT, 1, - [Define if there is a function named getmnt for reading the list of - mounted file systems. (Ultrix)]) - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - # BeOS - AC_CHECK_FUNCS(next_dev fs_stat_dev) - AC_CHECK_HEADERS(fs_info.h) - AC_MSG_CHECKING([for BEOS mounted file system support functions]) - if test x"$ac_cv_header_fs_info_h" = xyes \ - && test x"$ac_cv_func_next_dev" = xyes \ - && test x"$ac_cv_func_fs_stat_dev" = xyes; then - fu_result=yes - else - fu_result=no - fi - AC_MSG_RESULT($fu_result) - if test x"$fu_result" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_FS_STAT_DEV, 1, - [Define if there are functions named next_dev and fs_stat_dev for - reading the list of mounted file systems. (BeOS)]) - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - # SVR2 - AC_MSG_CHECKING([whether it is possible to resort to fread on /etc/mnttab]) - AC_CACHE_VAL(fu_cv_sys_mounted_fread, - [AC_TRY_CPP([#include ], - fu_cv_sys_mounted_fread=yes, - fu_cv_sys_mounted_fread=no)]) - AC_MSG_RESULT($fu_cv_sys_mounted_fread) - if test x"$fu_cv_sys_mounted_fread" = xyes; then - ac_list_mounted_fs=found - AC_DEFINE(MOUNTED_FREAD, 1, - [Define if there is no specific function for reading the list of - mounted file systems. fread will be used to read /etc/mnttab. - (SVR2) ]) - fi -fi - -if test x"$ac_list_mounted_fs" = x; then - AC_MSG_ERROR([could not determine how to read list of mounted file systems]) - # FIXME -- no need to abort building the whole package - # Can't build mountlist.c or anything that needs its functions -fi - -AS_IF([test x"$ac_list_mounted_fs" = xfound], [$1], [$2]) - - ]) - -# Obtaining file system usage information. - -# Copyright (C) 1997, 1998, 2000, 2001, 2003-2007 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# Written by Jim Meyering. - -AC_DEFUN([gl_FSUSAGE], -[ - AC_LIBSOURCES([fsusage.c, fsusage.h]) - - AC_CHECK_HEADERS_ONCE(sys/param.h) - AC_CHECK_HEADERS_ONCE(sys/vfs.h sys/fs_types.h) - AC_CHECK_HEADERS(sys/mount.h, [], [], - [AC_INCLUDES_DEFAULT - [#if HAVE_SYS_PARAM_H - #include - #endif]]) - gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no]) - if test x"$gl_cv_fs_space" = xyes; then - AC_LIBOBJ(fsusage) - gl_PREREQ_FSUSAGE_EXTRA - fi -]) - -# Try to determine how a program can obtain file system usage information. -# If successful, define the appropriate symbol (see fsusage.c) and -# execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND. -# -# gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) - -AC_DEFUN([gl_FILE_SYSTEM_USAGE], -[ - -AC_MSG_NOTICE([checking how to get file system space usage]) -ac_fsusage_space=no - -# Perform only the link test since it seems there are no variants of the -# statvfs function. This check is more than just AC_CHECK_FUNCS(statvfs) -# because that got a false positive on SCO OSR5. Adding the declaration -# of a `struct statvfs' causes this test to fail (as it should) on such -# systems. That system is reported to work fine with STAT_STATFS4 which -# is what it gets when this test fails. -if test x"$ac_fsusage_space" = xno; then - # SVR4 - AC_CACHE_CHECK([for statvfs function (SVR4)], fu_cv_sys_stat_statvfs, - [AC_TRY_LINK([#include -#if defined __GLIBC__ && !defined __BEOS__ -Do not use statvfs on systems with GNU libc, because that function stats -all preceding entries in /proc/mounts, and that makes df hang if even -one of the corresponding file systems is hard-mounted, but not available. -statvfs in GNU libc on BeOS operates differently: it only makes a system -call. -#endif - -#ifdef __osf__ -"Do not use Tru64's statvfs implementation" -#endif - -#include ], - [struct statvfs fsd; statvfs (0, &fsd);], - fu_cv_sys_stat_statvfs=yes, - fu_cv_sys_stat_statvfs=no)]) - if test x"$fu_cv_sys_stat_statvfs" = xyes; then - ac_fsusage_space=yes - AC_DEFINE(STAT_STATVFS, 1, - [ Define if there is a function named statvfs. (SVR4)]) - fi -fi - -if test x"$ac_fsusage_space" = xno; then - # DEC Alpha running OSF/1 - AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1, - [AC_TRY_RUN([ -#include -#include -#include - int - main () - { - struct statfs fsd; - fsd.f_fsize = 0; - return statfs (".", &fsd, sizeof (struct statfs)) != 0; - }], - fu_cv_sys_stat_statfs3_osf1=yes, - fu_cv_sys_stat_statfs3_osf1=no, - fu_cv_sys_stat_statfs3_osf1=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1) - if test x"$fu_cv_sys_stat_statfs3_osf1" = xyes; then - ac_fsusage_space=yes - AC_DEFINE(STAT_STATFS3_OSF1, 1, - [ Define if statfs takes 3 args. (DEC Alpha running OSF/1)]) - fi -fi - -if test x"$ac_fsusage_space" = xno; then -# AIX - AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl -member (AIX, 4.3BSD)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize, - [AC_TRY_RUN([ -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif -#ifdef HAVE_SYS_VFS_H -#include -#endif - int - main () - { - struct statfs fsd; - fsd.f_bsize = 0; - return statfs (".", &fsd) != 0; - }], - fu_cv_sys_stat_statfs2_bsize=yes, - fu_cv_sys_stat_statfs2_bsize=no, - fu_cv_sys_stat_statfs2_bsize=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize) - if test x"$fu_cv_sys_stat_statfs2_bsize" = xyes; then - ac_fsusage_space=yes - AC_DEFINE(STAT_STATFS2_BSIZE, 1, -[ Define if statfs takes 2 args and struct statfs has a field named f_bsize. - (4.3BSD, SunOS 4, HP-UX, AIX PS/2)]) - fi -fi - -if test x"$ac_fsusage_space" = xno; then -# SVR3 - AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs4, - [AC_TRY_RUN([#include -#include - int - main () - { - struct statfs fsd; - return statfs (".", &fsd, sizeof fsd, 0) != 0; - }], - fu_cv_sys_stat_statfs4=yes, - fu_cv_sys_stat_statfs4=no, - fu_cv_sys_stat_statfs4=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs4) - if test x"$fu_cv_sys_stat_statfs4" = xyes; then - ac_fsusage_space=yes - AC_DEFINE(STAT_STATFS4, 1, - [ Define if statfs takes 4 args. (SVR3, Dynix, Irix, Dolphin)]) - fi -fi - -if test x"$ac_fsusage_space" = xno; then -# 4.4BSD and NetBSD - AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl -member (4.4BSD and NetBSD)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize, - [AC_TRY_RUN([#include -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif - int - main () - { - struct statfs fsd; - fsd.f_fsize = 0; - return statfs (".", &fsd) != 0; - }], - fu_cv_sys_stat_statfs2_fsize=yes, - fu_cv_sys_stat_statfs2_fsize=no, - fu_cv_sys_stat_statfs2_fsize=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize) - if test x"$fu_cv_sys_stat_statfs2_fsize" = xyes; then - ac_fsusage_space=yes - AC_DEFINE(STAT_STATFS2_FSIZE, 1, -[ Define if statfs takes 2 args and struct statfs has a field named f_fsize. - (4.4BSD, NetBSD)]) - fi -fi - -if test x"$ac_fsusage_space" = xno; then - # Ultrix - AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) - AC_CACHE_VAL(fu_cv_sys_stat_fs_data, - [AC_TRY_RUN([#include -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif -#ifdef HAVE_SYS_FS_TYPES_H -#include -#endif - int - main () - { - struct fs_data fsd; - /* Ultrix's statfs returns 1 for success, - 0 for not mounted, -1 for failure. */ - return statfs (".", &fsd) != 1; - }], - fu_cv_sys_stat_fs_data=yes, - fu_cv_sys_stat_fs_data=no, - fu_cv_sys_stat_fs_data=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_fs_data) - if test x"$fu_cv_sys_stat_fs_data" = xyes; then - ac_fsusage_space=yes - AC_DEFINE(STAT_STATFS2_FS_DATA, 1, -[ Define if statfs takes 2 args and the second argument has - type struct fs_data. (Ultrix)]) - fi -fi - -if test x"$ac_fsusage_space" = xno; then - # SVR2 - AC_TRY_CPP([#include - ], - AC_DEFINE(STAT_READ_FILSYS, 1, - [Define if there is no specific function for reading file systems usage - information and you have the header file. (SVR2)]) - ac_fsusage_space=yes) -fi - -AS_IF([test x"$ac_fsusage_space" = xyes], [$1], [$2]) - -]) - - -# Check for SunOS statfs brokenness wrt partitions 2GB and larger. -# If exists and struct statfs has a member named f_spare, -# enable the work-around code in fsusage.c. -AC_DEFUN([gl_STATFS_TRUNCATES], -[ - AC_MSG_CHECKING([for statfs that truncates block counts]) - AC_CACHE_VAL(fu_cv_sys_truncating_statfs, - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#if !defined(sun) && !defined(__sun) -choke -- this is a workaround for a Sun-specific problem -#endif -#include -#include ]], - [[struct statfs t; long c = *(t.f_spare); - if (c) return 0;]])], - [fu_cv_sys_truncating_statfs=yes], - [fu_cv_sys_truncating_statfs=no])]) - if test x"$fu_cv_sys_truncating_statfs" = xyes; then - AC_DEFINE(STATFS_TRUNCATES_BLOCK_COUNTS, 1, - [Define if the block counts reported by statfs may be truncated to 2GB - and the correct values may be stored in the f_spare array. - (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. - SunOS 4.1.1 seems not to be affected.)]) - fi - AC_MSG_RESULT($fu_cv_sys_truncating_statfs) -]) - - -# Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE. -AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA], -[ - AC_REQUIRE([gl_AC_TYPE_UINTMAX_T]) - AC_CHECK_HEADERS(dustat.h sys/fs/s5param.h sys/filsys.h sys/statfs.h) - gl_STATFS_TRUNCATES -]) - -dnl From Jim Meyering. -dnl -dnl See if struct statfs has the f_fstypename member. -dnl If so, define HAVE_STRUCT_STATFS_F_FSTYPENAME. -dnl - -# Copyright (C) 1998, 1999, 2001, 2004, 2006 Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -AC_DEFUN([gl_FSTYPENAME], -[ - AC_CHECK_MEMBERS([struct statfs.f_fstypename],,, - [ - #include - #include - #include - ]) - AC_CHECK_MEMBERS([struct statvfs.f_fstypename, struct statvfs.f_basetype],,, - [ - AC_INCLUDES_DEFAULT - #include - ]) -]) - -dnl -dnl posix_allocate() function detection -dnl - -AC_DEFUN([gl_POSIX_FALLOCATE], [ - dnl * Old glibcs have broken posix_fallocate(). Make sure not to use it. - AC_TRY_COMPILE([ - #define _XOPEN_SOURCE 600 - #include - #if defined(__GLIBC__) && (__GLIBC__ < 2 || __GLIBC_MINOR__ < 7) - possibly broken posix_fallocate - #endif - ], - [posix_fallocate(0, 0, 0);], - [AC_DEFINE( - [HAVE_POSIX_FALLOCATE], - [1], - [Define if you have a working posix_fallocate()]) - ]) -]) - -dnl -dnl Filesystem information detection -dnl -dnl To get information about the disk, mount points, etc. -dnl - -AC_DEFUN([AC_GET_FS_INFO], [ - AC_CHECK_HEADERS([fcntl.h utime.h]) - - gl_LIST_MOUNTED_FILE_SYSTEMS([ - AC_DEFINE(HAVE_INFOMOUNT_LIST, 1, - [Define if the list of mounted filesystems can be determined])], - [AC_MSG_WARN([could not determine how to read list of mounted fs])]) - - gl_FSUSAGE - gl_FSTYPENAME - gl_POSIX_FALLOCATE -]) diff --git a/m4.include/fstypename.m4 b/m4.include/fstypename.m4 new file mode 100644 index 000000000..20d2f05cf --- /dev/null +++ b/m4.include/fstypename.m4 @@ -0,0 +1,23 @@ +#serial 6 + +dnl From Jim Meyering. +dnl +dnl See if struct statfs has the f_fstypename member. +dnl If so, define HAVE_STRUCT_STATFS_F_FSTYPENAME. +dnl + +# Copyright (C) 1998-1999, 2001, 2004, 2006, 2009-2011 Free Software +# Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FSTYPENAME], +[ + AC_CHECK_MEMBERS([struct statfs.f_fstypename],,, + [ + #include + #include + #include + ]) +]) diff --git a/m4.include/fsusage.m4 b/m4.include/fsusage.m4 new file mode 100644 index 000000000..8e9e2cb5b --- /dev/null +++ b/m4.include/fsusage.m4 @@ -0,0 +1,323 @@ +# serial 29 +# Obtaining file system usage information. + +# Copyright (C) 1997-1998, 2000-2001, 2003-2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Written by Jim Meyering. + +AC_DEFUN([gl_FSUSAGE], +[ + AC_CHECK_HEADERS_ONCE([sys/param.h]) + AC_CHECK_HEADERS_ONCE([sys/vfs.h sys/fs_types.h]) + AC_CHECK_HEADERS([sys/mount.h], [], [], + [AC_INCLUDES_DEFAULT + [#if HAVE_SYS_PARAM_H + #include + #endif]]) + gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no]) +]) + +# Try to determine how a program can obtain file system usage information. +# If successful, define the appropriate symbol (see fsusage.c) and +# execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND. +# +# gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([gl_FILE_SYSTEM_USAGE], +[ +dnl Enable large-file support. This has the effect of changing the size +dnl of field f_blocks in 'struct statvfs' from 32 bit to 64 bit on +dnl glibc/Hurd, HP-UX 11, Solaris (32-bit mode). It also changes the size +dnl of field f_blocks in 'struct statfs' from 32 bit to 64 bit on +dnl MacOS X >= 10.5 (32-bit mode). +AC_REQUIRE([AC_SYS_LARGEFILE]) + +AC_MSG_NOTICE([checking how to get file system space usage]) +ac_fsusage_space=no + +# Perform only the link test since it seems there are no variants of the +# statvfs function. This check is more than just AC_CHECK_FUNCS([statvfs]) +# because that got a false positive on SCO OSR5. Adding the declaration +# of a `struct statvfs' causes this test to fail (as it should) on such +# systems. That system is reported to work fine with STAT_STATFS4 which +# is what it gets when this test fails. +if test $ac_fsusage_space = no; then + # glibc/{Hurd,kFreeBSD}, FreeBSD >= 5.0, NetBSD >= 3.0, + # OpenBSD >= 4.4, AIX, HP-UX, IRIX, Solaris, Cygwin, Interix, BeOS. + AC_CACHE_CHECK([for statvfs function (SVR4)], [fu_cv_sys_stat_statvfs], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include +#if (defined __GLIBC__ || defined __UCLIBC__) && defined __linux__ +Do not use statvfs on systems with GNU libc on Linux, because that function +stats all preceding entries in /proc/mounts, and that makes df hang if even +one of the corresponding file systems is hard-mounted, but not available. +statvfs in GNU libc on Hurd, BeOS, Haiku operates differently: it only makes +a system call. +#endif + +#ifdef __osf__ +"Do not use Tru64's statvfs implementation" +#endif + +#include + +struct statvfs fsd; + +#if defined __APPLE__ && defined __MACH__ +#include +/* On MacOS X >= 10.5, f_blocks in 'struct statvfs' is a 32-bit quantity; + that commonly limits file systems to 4 TiB. Whereas f_blocks in + 'struct statfs' is a 64-bit type, thanks to the large-file support + that was enabled above. In this case, don't use statvfs(); use statfs() + instead. */ +int check_f_blocks_size[sizeof fsd.f_blocks * CHAR_BIT <= 32 ? -1 : 1]; +#endif +]], + [[statvfs (0, &fsd);]])], + [fu_cv_sys_stat_statvfs=yes], + [fu_cv_sys_stat_statvfs=no])]) + if test $fu_cv_sys_stat_statvfs = yes; then + ac_fsusage_space=yes + # AIX >= 5.2 has statvfs64 that has a wider f_blocks field than statvfs. + # glibc, HP-UX, IRIX, Solaris have statvfs64 as well, but on these systems + # statvfs with large-file support is already equivalent to statvfs64. + AC_CACHE_CHECK([whether to use statvfs64], + [fu_cv_sys_stat_statvfs64], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + struct statvfs64 fsd; + int check_f_blocks_larger_in_statvfs64 + [sizeof (((struct statvfs64 *) 0)->f_blocks) + > sizeof (((struct statvfs *) 0)->f_blocks) + ? 1 : -1]; + ]], + [[statvfs64 (0, &fsd);]])], + [fu_cv_sys_stat_statvfs64=yes], + [fu_cv_sys_stat_statvfs64=no]) + ]) + if test $fu_cv_sys_stat_statvfs64 = yes; then + AC_DEFINE([STAT_STATVFS64], [1], + [ Define if statvfs64 should be preferred over statvfs.]) + else + AC_DEFINE([STAT_STATVFS], [1], + [ Define if there is a function named statvfs. (SVR4)]) + fi + fi +fi + +if test $ac_fsusage_space = no; then + # DEC Alpha running OSF/1 + AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) + AC_CACHE_VAL([fu_cv_sys_stat_statfs3_osf1], + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include + int + main () + { + struct statfs fsd; + fsd.f_fsize = 0; + return statfs (".", &fsd, sizeof (struct statfs)) != 0; + }]])], + [fu_cv_sys_stat_statfs3_osf1=yes], + [fu_cv_sys_stat_statfs3_osf1=no], + [fu_cv_sys_stat_statfs3_osf1=no])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs3_osf1]) + if test $fu_cv_sys_stat_statfs3_osf1 = yes; then + ac_fsusage_space=yes + AC_DEFINE([STAT_STATFS3_OSF1], [1], + [ Define if statfs takes 3 args. (DEC Alpha running OSF/1)]) + fi +fi + +if test $ac_fsusage_space = no; then + # glibc/Linux, MacOS X, FreeBSD < 5.0, NetBSD < 3.0, OpenBSD < 4.4. + # (glibc/{Hurd,kFreeBSD}, FreeBSD >= 5.0, NetBSD >= 3.0, + # OpenBSD >= 4.4, AIX, HP-UX, OSF/1, Cygwin already handled above.) + # (On IRIX you need to include , not only and + # .) + # (On Solaris, statfs has 4 arguments.) + AC_MSG_CHECKING([for two-argument statfs with statfs.f_bsize dnl +member (AIX, 4.3BSD)]) + AC_CACHE_VAL([fu_cv_sys_stat_statfs2_bsize], + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_bsize = 0; + return statfs (".", &fsd) != 0; + }]])], + [fu_cv_sys_stat_statfs2_bsize=yes], + [fu_cv_sys_stat_statfs2_bsize=no], + [fu_cv_sys_stat_statfs2_bsize=no])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_bsize]) + if test $fu_cv_sys_stat_statfs2_bsize = yes; then + ac_fsusage_space=yes + AC_DEFINE([STAT_STATFS2_BSIZE], [1], +[ Define if statfs takes 2 args and struct statfs has a field named f_bsize. + (4.3BSD, SunOS 4, HP-UX, AIX PS/2)]) + fi +fi + +if test $ac_fsusage_space = no; then + # SVR3 + # (Solaris already handled above.) + AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) + AC_CACHE_VAL([fu_cv_sys_stat_statfs4], + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include + int + main () + { + struct statfs fsd; + return statfs (".", &fsd, sizeof fsd, 0) != 0; + }]])], + [fu_cv_sys_stat_statfs4=yes], + [fu_cv_sys_stat_statfs4=no], + [fu_cv_sys_stat_statfs4=no])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs4]) + if test $fu_cv_sys_stat_statfs4 = yes; then + ac_fsusage_space=yes + AC_DEFINE([STAT_STATFS4], [1], + [ Define if statfs takes 4 args. (SVR3, Dynix, old Irix, old AIX, Dolphin)]) + fi +fi + +if test $ac_fsusage_space = no; then + # 4.4BSD and older NetBSD + # (OSF/1 already handled above.) + # (On AIX, you need to include , not only .) + # (On Solaris, statfs has 4 arguments and 'struct statfs' is not declared in + # .) + AC_MSG_CHECKING([for two-argument statfs with statfs.f_fsize dnl +member (4.4BSD and NetBSD)]) + AC_CACHE_VAL([fu_cv_sys_stat_statfs2_fsize], + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_fsize = 0; + return statfs (".", &fsd) != 0; + }]])], + [fu_cv_sys_stat_statfs2_fsize=yes], + [fu_cv_sys_stat_statfs2_fsize=no], + [fu_cv_sys_stat_statfs2_fsize=no])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_fsize]) + if test $fu_cv_sys_stat_statfs2_fsize = yes; then + ac_fsusage_space=yes + AC_DEFINE([STAT_STATFS2_FSIZE], [1], +[ Define if statfs takes 2 args and struct statfs has a field named f_fsize. + (4.4BSD, NetBSD)]) + fi +fi + +if test $ac_fsusage_space = no; then + # Ultrix + AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) + AC_CACHE_VAL([fu_cv_sys_stat_fs_data], + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_FS_TYPES_H +#include +#endif + int + main () + { + struct fs_data fsd; + /* Ultrix's statfs returns 1 for success, + 0 for not mounted, -1 for failure. */ + return statfs (".", &fsd) != 1; + }]])], + [fu_cv_sys_stat_fs_data=yes], + [fu_cv_sys_stat_fs_data=no], + [fu_cv_sys_stat_fs_data=no])]) + AC_MSG_RESULT([$fu_cv_sys_stat_fs_data]) + if test $fu_cv_sys_stat_fs_data = yes; then + ac_fsusage_space=yes + AC_DEFINE([STAT_STATFS2_FS_DATA], [1], +[ Define if statfs takes 2 args and the second argument has + type struct fs_data. (Ultrix)]) + fi +fi + +if test $ac_fsusage_space = no; then + # SVR2 + # (AIX, HP-UX, OSF/1 already handled above.) + AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include + ]])], + [AC_DEFINE([STAT_READ_FILSYS], [1], + [Define if there is no specific function for reading file systems usage + information and you have the header file. (SVR2)]) + ac_fsusage_space=yes]) +fi + +AS_IF([test $ac_fsusage_space = yes], [$1], [$2]) + +]) + + +# Check for SunOS statfs brokenness wrt partitions 2GB and larger. +# If exists and struct statfs has a member named f_spare, +# enable the work-around code in fsusage.c. +AC_DEFUN([gl_STATFS_TRUNCATES], +[ + AC_MSG_CHECKING([for statfs that truncates block counts]) + AC_CACHE_VAL([fu_cv_sys_truncating_statfs], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if !defined(sun) && !defined(__sun) +choke -- this is a workaround for a Sun-specific problem +#endif +#include +#include ]], + [[struct statfs t; long c = *(t.f_spare); + if (c) return 0;]])], + [fu_cv_sys_truncating_statfs=yes], + [fu_cv_sys_truncating_statfs=no])]) + if test $fu_cv_sys_truncating_statfs = yes; then + AC_DEFINE([STATFS_TRUNCATES_BLOCK_COUNTS], [1], + [Define if the block counts reported by statfs may be truncated to 2GB + and the correct values may be stored in the f_spare array. + (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. + SunOS 4.1.1 seems not to be affected.)]) + fi + AC_MSG_RESULT([$fu_cv_sys_truncating_statfs]) +]) + + +# Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE. +AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA], +[ + AC_CHECK_HEADERS([dustat.h sys/fs/s5param.h sys/filsys.h sys/statfs.h]) + gl_STATFS_TRUNCATES +]) diff --git a/m4.include/ls-mntd-fs.m4 b/m4.include/ls-mntd-fs.m4 new file mode 100644 index 000000000..714d539bf --- /dev/null +++ b/m4.include/ls-mntd-fs.m4 @@ -0,0 +1,357 @@ +# serial 29 +# How to list mounted file systems. + +# Copyright (C) 1998-2004, 2006, 2009-2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +dnl From Jim Meyering. +dnl +dnl This is not pretty. I've just taken the autoconf code and wrapped +dnl it in an AC_DEFUN and made some other fixes. +dnl + +# Replace Autoconf's AC_FUNC_GETMNTENT to work around a bug in Autoconf +# through Autoconf 2.59. We can remove this once we assume Autoconf 2.60 +# or later. +AC_DEFUN([AC_FUNC_GETMNTENT], +[# getmntent is in the standard C library on UNICOS, in -lsun on Irix 4, +# -lseq on Dynix/PTX, -lgen on Unixware. +AC_SEARCH_LIBS([getmntent], [sun seq gen]) +AC_CHECK_FUNCS([getmntent]) +]) + +# gl_LIST_MOUNTED_FILE_SYSTEMS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([gl_LIST_MOUNTED_FILE_SYSTEMS], + [ +AC_CHECK_FUNCS([listmntent getmntinfo]) +AC_CHECK_HEADERS_ONCE([sys/param.h sys/statvfs.h]) + +# We must include grp.h before ucred.h on OSF V4.0, since ucred.h uses +# NGROUPS (as the array dimension for a struct member) without a definition. +AC_CHECK_HEADERS([sys/ucred.h], [], [], [#include ]) + +AC_CHECK_HEADERS([sys/mount.h], [], [], + [AC_INCLUDES_DEFAULT + [#if HAVE_SYS_PARAM_H + #include + #endif]]) + +AC_CHECK_HEADERS([mntent.h sys/fs_types.h]) + getfsstat_includes="\ +$ac_includes_default +#if HAVE_SYS_PARAM_H +# include /* needed by powerpc-apple-darwin1.3.7 */ +#endif +#if HAVE_SYS_UCRED_H +# include /* needed for definition of NGROUPS */ +# include /* needed by powerpc-apple-darwin1.3.7 */ +#endif +#if HAVE_SYS_MOUNT_H +# include +#endif +#if HAVE_SYS_FS_TYPES_H +# include /* needed by powerpc-apple-darwin1.3.7 */ +#endif +" +AC_CHECK_MEMBERS([struct fsstat.f_fstypename],,,[$getfsstat_includes]) + +# Determine how to get the list of mounted file systems. +ac_list_mounted_fs= + +# If the getmntent function is available but not in the standard library, +# make sure LIBS contains the appropriate -l option. +AC_FUNC_GETMNTENT + +# This test must precede the ones for getmntent because Unicos-9 is +# reported to have the getmntent function, but its support is incompatible +# with other getmntent implementations. + +# NOTE: Normally, I wouldn't use a check for system type as I've done for +# `CRAY' below since that goes against the whole autoconf philosophy. But +# I think there is too great a chance that some non-Cray system has a +# function named listmntent to risk the false positive. + +if test -z "$ac_list_mounted_fs"; then + # Cray UNICOS 9 + AC_MSG_CHECKING([for listmntent of Cray/Unicos-9]) + AC_CACHE_VAL([fu_cv_sys_mounted_cray_listmntent], + [fu_cv_sys_mounted_cray_listmntent=no + AC_EGREP_CPP([yes], + [#ifdef _CRAY +yes +#endif + ], [test $ac_cv_func_listmntent = yes \ + && fu_cv_sys_mounted_cray_listmntent=yes] + ) + ] + ) + AC_MSG_RESULT([$fu_cv_sys_mounted_cray_listmntent]) + if test $fu_cv_sys_mounted_cray_listmntent = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_LISTMNTENT], [1], + [Define if there is a function named listmntent that can be used to + list all mounted file systems. (UNICOS)]) + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # AIX. + AC_MSG_CHECKING([for mntctl function and struct vmount]) + AC_CACHE_VAL([fu_cv_sys_mounted_vmount], + [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])], + [fu_cv_sys_mounted_vmount=yes], + [fu_cv_sys_mounted_vmount=no])]) + AC_MSG_RESULT([$fu_cv_sys_mounted_vmount]) + if test $fu_cv_sys_mounted_vmount = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_VMOUNT], [1], + [Define if there is a function named mntctl that can be used to read + the list of mounted file systems, and there is a system header file + that declares `struct vmount.' (AIX)]) + fi +fi + +if test $ac_cv_func_getmntent = yes; then + + # This system has the getmntent function. + # Determine whether it's the one-argument variant or the two-argument one. + + if test -z "$ac_list_mounted_fs"; then + # 4.3BSD, SunOS, HP-UX, Dynix, Irix + AC_MSG_CHECKING([for one-argument getmntent function]) + AC_CACHE_VAL([fu_cv_sys_mounted_getmntent1], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +/* SunOS 4.1.x /usr/include/mntent.h needs this for FILE */ +#include + +#include +#if !defined MOUNTED +# if defined _PATH_MOUNTED /* GNU libc */ +# define MOUNTED _PATH_MOUNTED +# endif +# if defined MNT_MNTTAB /* HP-UX. */ +# define MOUNTED MNT_MNTTAB +# endif +# if defined MNTTABNAME /* Dynix. */ +# define MOUNTED MNTTABNAME +# endif +#endif +]], + [[ struct mntent *mnt = 0; char *table = MOUNTED; + if (sizeof mnt && sizeof table) return 0;]])], + [fu_cv_sys_mounted_getmntent1=yes], + [fu_cv_sys_mounted_getmntent1=no])]) + AC_MSG_RESULT([$fu_cv_sys_mounted_getmntent1]) + if test $fu_cv_sys_mounted_getmntent1 = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_GETMNTENT1], [1], + [Define if there is a function named getmntent for reading the list + of mounted file systems, and that function takes a single argument. + (4.3BSD, SunOS, HP-UX, Dynix, Irix)]) + fi + fi + + if test -z "$ac_list_mounted_fs"; then + # SVR4 + AC_MSG_CHECKING([for two-argument getmntent function]) + AC_CACHE_VAL([fu_cv_sys_mounted_getmntent2], + [AC_EGREP_HEADER([getmntent], [sys/mnttab.h], + fu_cv_sys_mounted_getmntent2=yes, + fu_cv_sys_mounted_getmntent2=no)]) + AC_MSG_RESULT([$fu_cv_sys_mounted_getmntent2]) + if test $fu_cv_sys_mounted_getmntent2 = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_GETMNTENT2], [1], + [Define if there is a function named getmntent for reading the list of + mounted file systems, and that function takes two arguments. (SVR4)]) + AC_CHECK_FUNCS([hasmntopt]) + fi + fi + +fi + +if test -z "$ac_list_mounted_fs"; then + # DEC Alpha running OSF/1, and Apple Darwin 1.3. + # powerpc-apple-darwin1.3.7 needs sys/param.h sys/ucred.h sys/fs_types.h + + AC_MSG_CHECKING([for getfsstat function]) + AC_CACHE_VAL([fu_cv_sys_mounted_getfsstat], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#if HAVE_STRUCT_FSSTAT_F_FSTYPENAME +# define FS_TYPE(Ent) ((Ent).f_fstypename) +#else +# define FS_TYPE(Ent) mnt_names[(Ent).f_type] +#endif +$getfsstat_includes]] +, + [[struct statfs *stats; + int numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT); + char *t = FS_TYPE (*stats); ]])], + [fu_cv_sys_mounted_getfsstat=yes], + [fu_cv_sys_mounted_getfsstat=no])]) + AC_MSG_RESULT([$fu_cv_sys_mounted_getfsstat]) + if test $fu_cv_sys_mounted_getfsstat = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_GETFSSTAT], [1], + [Define if there is a function named getfsstat for reading the + list of mounted file systems. (DEC Alpha running OSF/1)]) + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # SVR3 + AC_MSG_CHECKING([for FIXME existence of three headers]) + AC_CACHE_VAL([fu_cv_sys_mounted_fread_fstyp], + [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include ]])], + [fu_cv_sys_mounted_fread_fstyp=yes], + [fu_cv_sys_mounted_fread_fstyp=no])]) + AC_MSG_RESULT([$fu_cv_sys_mounted_fread_fstyp]) + if test $fu_cv_sys_mounted_fread_fstyp = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_FREAD_FSTYP], [1], + [Define if (like SVR2) there is no specific function for reading the + list of mounted file systems, and your system has these header files: + and . (SVR3)]) + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # 4.4BSD and DEC OSF/1. + AC_MSG_CHECKING([for getmntinfo function]) + AC_CACHE_VAL([fu_cv_sys_mounted_getmntinfo], + [ + test "$ac_cv_func_getmntinfo" = yes \ + && fu_cv_sys_mounted_getmntinfo=yes \ + || fu_cv_sys_mounted_getmntinfo=no + ]) + AC_MSG_RESULT([$fu_cv_sys_mounted_getmntinfo]) + if test $fu_cv_sys_mounted_getmntinfo = yes; then + AC_MSG_CHECKING([whether getmntinfo returns statvfs structures]) + AC_CACHE_VAL([fu_cv_sys_mounted_getmntinfo2], + [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if HAVE_SYS_PARAM_H +# include +#endif +#include +#if HAVE_SYS_MOUNT_H +# include +#endif +#if HAVE_SYS_STATVFS_H +# include +#endif +extern +#ifdef __cplusplus +"C" +#endif +int getmntinfo (struct statfs **, int); + ]], [])], + [fu_cv_sys_mounted_getmntinfo2=no], + [fu_cv_sys_mounted_getmntinfo2=yes]) + ]) + AC_MSG_RESULT([$fu_cv_sys_mounted_getmntinfo2]) + if test $fu_cv_sys_mounted_getmntinfo2 = no; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_GETMNTINFO], [1], + [Define if there is a function named getmntinfo for reading the + list of mounted file systems and it returns an array of + 'struct statfs'. (4.4BSD, Darwin)]) + else + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_GETMNTINFO2], [1], + [Define if there is a function named getmntinfo for reading the + list of mounted file systems and it returns an array of + 'struct statvfs'. (NetBSD 3.0)]) + fi + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # Ultrix + AC_MSG_CHECKING([for getmnt function]) + AC_CACHE_VAL([fu_cv_sys_mounted_getmnt], + [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[ +#include +#include ]])], + [fu_cv_sys_mounted_getmnt=yes], + [fu_cv_sys_mounted_getmnt=no])]) + AC_MSG_RESULT([$fu_cv_sys_mounted_getmnt]) + if test $fu_cv_sys_mounted_getmnt = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_GETMNT], [1], + [Define if there is a function named getmnt for reading the list of + mounted file systems. (Ultrix)]) + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # BeOS + AC_CHECK_FUNCS([next_dev fs_stat_dev]) + AC_CHECK_HEADERS([fs_info.h]) + AC_MSG_CHECKING([for BEOS mounted file system support functions]) + if test $ac_cv_header_fs_info_h = yes \ + && test $ac_cv_func_next_dev = yes \ + && test $ac_cv_func_fs_stat_dev = yes; then + fu_result=yes + else + fu_result=no + fi + AC_MSG_RESULT([$fu_result]) + if test $fu_result = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_FS_STAT_DEV], [1], + [Define if there are functions named next_dev and fs_stat_dev for + reading the list of mounted file systems. (BeOS)]) + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # SVR2 + AC_MSG_CHECKING([whether it is possible to resort to fread on /etc/mnttab]) + AC_CACHE_VAL([fu_cv_sys_mounted_fread], + [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])], + [fu_cv_sys_mounted_fread=yes], + [fu_cv_sys_mounted_fread=no])]) + AC_MSG_RESULT([$fu_cv_sys_mounted_fread]) + if test $fu_cv_sys_mounted_fread = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_FREAD], [1], + [Define if there is no specific function for reading the list of + mounted file systems. fread will be used to read /etc/mnttab. + (SVR2) ]) + fi +fi + +if test -z "$ac_list_mounted_fs"; then + # Interix / BSD alike statvfs + # the code is really interix specific, so make sure, we're on it. + case "$host" in + *-interix*) + AC_CHECK_FUNCS([statvfs]) + if test $ac_cv_func_statvfs = yes; then + ac_list_mounted_fs=found + AC_DEFINE([MOUNTED_INTERIX_STATVFS], [1], + [Define if we are on interix, and ought to use statvfs plus + some special knowledge on where mounted filesystems can be + found. (Interix)]) + fi + ;; + esac +fi + +if test -z "$ac_list_mounted_fs"; then + AC_MSG_ERROR([could not determine how to read list of mounted file systems]) + # FIXME -- no need to abort building the whole package + # Can't build mountlist.c or anything that needs its functions +fi + +AS_IF([test $ac_list_mounted_fs = found], [$1], [$2]) + + ]) diff --git a/m4.include/mc-get-fs-info.m4 b/m4.include/mc-get-fs-info.m4 new file mode 100644 index 000000000..bc0ca54ec --- /dev/null +++ b/m4.include/mc-get-fs-info.m4 @@ -0,0 +1,49 @@ + +dnl +dnl posix_allocate() function detection +dnl + +AC_DEFUN([gl_POSIX_FALLOCATE], [ + dnl * Old glibcs have broken posix_fallocate(). Make sure not to use it. + AC_TRY_COMPILE([ + #define _XOPEN_SOURCE 600 + #include + #if defined(__GLIBC__) && (__GLIBC__ < 2 || __GLIBC_MINOR__ < 7) + possibly broken posix_fallocate + #endif + ], + [posix_fallocate(0, 0, 0);], + [AC_DEFINE( + [HAVE_POSIX_FALLOCATE], + [1], + [Define if you have a working posix_fallocate()]) + ]) +]) + +dnl +dnl Filesystem information detection +dnl +dnl To get information about the disk, mount points, etc. +dnl + +AC_DEFUN([AC_MC_GET_FS_INFO], [ + gl_MOUNTLIST + if test $gl_cv_list_mounted_fs = yes; then + gl_PREREQ_MOUNTLIST_EXTRA + fi + + AC_CHECK_HEADERS([fcntl.h utime.h]) + + gl_LIST_MOUNTED_FILE_SYSTEMS([ + AC_DEFINE(HAVE_INFOMOUNT_LIST, 1, + [Define if the list of mounted filesystems can be determined])], + [AC_MSG_WARN([could not determine how to read list of mounted fs])]) + + gl_FSUSAGE + if test $gl_cv_fs_space = yes; then + gl_PREREQ_FSUSAGE_EXTRA + fi + gl_FSTYPENAME + + gl_POSIX_FALLOCATE +]) diff --git a/m4.include/mountlist.m4 b/m4.include/mountlist.m4 new file mode 100644 index 000000000..a00082d0c --- /dev/null +++ b/m4.include/mountlist.m4 @@ -0,0 +1,19 @@ +# serial 11 +dnl Copyright (C) 2002-2006, 2009-2011 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_MOUNTLIST], +[ + gl_LIST_MOUNTED_FILE_SYSTEMS([gl_cv_list_mounted_fs=yes], + [gl_cv_list_mounted_fs=no]) +]) + +# Prerequisites of lib/mountlist.c not done by gl_LIST_MOUNTED_FILE_SYSTEMS. +AC_DEFUN([gl_PREREQ_MOUNTLIST_EXTRA], +[ + dnl Note gl_LIST_MOUNTED_FILE_SYSTEMS checks for mntent.h, not sys/mntent.h. + AC_CHECK_HEADERS([sys/mntent.h]) + gl_FSTYPENAME +]) diff --git a/src/filemanager/info.c b/src/filemanager/info.c index 1498f768a..ad0283bec 100644 --- a/src/filemanager/info.c +++ b/src/filemanager/info.c @@ -29,6 +29,7 @@ #include #include +#include /* PRIuMAX */ #include "lib/global.h" #include "lib/unixcompat.h" @@ -142,27 +143,29 @@ info_show_info (struct WInfo *info) case 16: widget_move (&info->widget, 16, 3); - if (myfs_stats.nfree > 0 || myfs_stats.nodes > 0) - tty_printf (_("Free nodes: %ld (%ld%%) of %ld"), - (size_t) myfs_stats.nfree, - myfs_stats.nodes != 0 - ? 100 * (size_t) myfs_stats.nfree / (size_t) myfs_stats.nodes : 0, - (size_t) myfs_stats.nodes); - else + if (myfs_stats.nfree == 0 && myfs_stats.nodes == 0) tty_print_string (_("No node information")); + else + tty_printf ("%s %" PRIuMAX "/%" PRIuMAX " (%d%%)", + _("Free nodes:"), + myfs_stats.nfree, myfs_stats.nodes, + myfs_stats.nodes == 0 ? 0 : + (int) (100 * (long double) myfs_stats.nfree / myfs_stats.nodes)); case 15: widget_move (&info->widget, 15, 3); - if (myfs_stats.avail > 0 || myfs_stats.total > 0) + if (myfs_stats.avail == 0 && myfs_stats.total == 0) + tty_print_string (_("No space information")); + else { char buffer1[6], buffer2[6]; + size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si); size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si); - tty_printf (_("Free space: %s (%d%%) of %s"), buffer1, myfs_stats.total ? - (int) (100 * (double) myfs_stats.avail / myfs_stats.total) : 0, buffer2); + tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2, + myfs_stats.total == 0 ? 0 : + (int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); } - else - tty_print_string (_("No space information")); case 14: widget_move (&info->widget, 14, 3); @@ -216,7 +219,7 @@ info_show_info (struct WInfo *info) tty_printf (_("Size: %s"), buffer); #ifdef HAVE_STRUCT_STAT_ST_BLOCKS tty_printf (ngettext (" (%ld block)", " (%ld blocks)", - (unsigned long int) st.st_blocks), (long int) st.st_blocks); + (unsigned long) st.st_blocks), (unsigned long) st.st_blocks); #endif } diff --git a/src/filemanager/mountlist.c b/src/filemanager/mountlist.c index a7b1f9e94..7a1af6662 100644 --- a/src/filemanager/mountlist.c +++ b/src/filemanager/mountlist.c @@ -1,5 +1,8 @@ /* - Return a list of mounted filesystems + Return a list of mounted file systems + + Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Copyright (C) 1991, 1992, 2011 The Free Software Foundation, Inc. @@ -26,28 +29,75 @@ #include +#include #include #include - +#include +#include /* SIZE_MAX */ #include +#include + +#if defined STAT_STATVFS || defined STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */ +#include +#else +/* Don't include backward-compatibility files unless they're needed. + Eventually we'd like to remove all this cruft. */ +#include +#include +#include + /* This header needs to be included before sys/mount.h on *BSD */ #ifdef HAVE_SYS_PARAM_H #include #endif -#if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */ +#ifdef MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */ +#ifdef HAVE_SYS_UCRED_H +#include /* needed on OSF V4.0 for definition of NGROUPS, + NGROUPS is used as an array dimension in ucred.h */ +#include /* needed by powerpc-apple-darwin1.3.7 */ +#endif +#ifdef HAVE_SYS_MOUNT_H #include -#include +#endif +#ifdef HAVE_SYS_FS_TYPES_H +#include /* needed by powerpc-apple-darwin1.3.7 */ +#endif +#ifdef HAVE_STRUCT_FSSTAT_F_FSTYPENAME +#define FS_TYPE(Ent) ((Ent).f_fstypename) +#else +#define FS_TYPE(Ent) mnt_names[(Ent).f_type] +#endif #endif /* MOUNTED_GETFSSTAT */ +#endif /* STAT_STATVFS || STAT_STATVFS64 */ + +#ifdef HAVE_SYS_VFS_H +#include +#endif +#ifdef HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ +#include +#endif +#if defined HAVE_SYS_FILSYS_H && !defined _CRAY +#include /* SVR2 */ +#endif +#ifdef HAVE_SYS_STATFS_H +#include +#endif +#ifdef HAVE_DUSTAT_H /* AIX PS/2 */ +#include +#endif #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ #include -#if !defined(MOUNTED) -#if defined(MNT_MNTTAB) /* HP-UX. */ +#ifndef MOUNTED +#ifdef _PATH_MOUNTED /* GNU libc */ +#define MOUNTED _PATH_MOUNTED +#endif +#ifdef MNT_MNTTAB /* HP-UX. */ #define MOUNTED MNT_MNTTAB #endif -#if defined(MNTTABNAME) /* Dynix. */ +#ifdef MNTTABNAME /* Dynix. */ #define MOUNTED MNTTABNAME #endif #endif @@ -59,7 +109,6 @@ #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ #include -#define statfs statvfs #endif #ifdef MOUNTED_GETMNT /* Ultrix. */ @@ -67,6 +116,11 @@ #include #endif +#ifdef MOUNTED_FS_STAT_DEV /* BeOS. */ +#include +#include +#endif + #ifdef MOUNTED_FREAD /* SVR2. */ #include #endif @@ -77,6 +131,10 @@ #include #endif +#ifdef MOUNTED_LISTMNTENT +#include +#endif + #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ #include #endif @@ -86,8 +144,27 @@ #include #endif -#ifdef HAVE_SYS_STATFS_H -#include +#ifdef MOUNTED_INTERIX_STATVFS /* Interix. */ +#include +#include +#endif + +#ifdef DOLPHIN +/* So special that it's not worth putting this in autoconf. */ +#undef MOUNTED_FREAD_FSTYP +#define MOUNTED_GETMNTTBL +#endif + +#ifdef HAVE_SYS_MNTENT_H +/* This is to get MNTOPT_IGNORE on e.g. SVR4. */ +#include +#endif + +#undef MNT_IGNORE +#if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT +#define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE) +#else +#define MNT_IGNORE(M) 0 #endif #ifdef HAVE_INFOMOUNT_QNX @@ -95,22 +172,6 @@ #include #endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif - -#ifdef HAVE_SYS_VFS_H -#include -#endif - -#ifdef HAVE_SYS_FILSYS_H -#include /* SVR2. */ -#endif - -#ifdef HAVE_DUSTAT_H /* AIX PS/2. */ -#include -#endif - #ifdef HAVE_SYS_STATVFS_H /* SVR4. */ #include #endif @@ -122,12 +183,6 @@ /*** file scope macro definitions ****************************************************************/ -#ifdef DOLPHIN -/* So special that it's not worth putting this in autoconf. */ -#undef MOUNTED_FREAD_FSTYP -#define MOUNTED_GETMNTTBL -#endif - #if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST) #define HAVE_INFOMOUNT_QNX #endif @@ -136,33 +191,126 @@ #define HAVE_INFOMOUNT #endif +/* The results of open() in this file are not used with fchdir, + therefore save some unnecessary work in fchdir.c. */ +#undef open +#undef close + +/* The results of opendir() in this file are not used with dirfd and fchdir, + therefore save some unnecessary work in fchdir.c. */ +#undef opendir +#undef closedir + +#ifndef ME_DUMMY +# define ME_DUMMY(Fs_name, Fs_type) \ + (strcmp (Fs_type, "autofs") == 0 \ + || strcmp (Fs_type, "none") == 0 \ + || strcmp (Fs_type, "proc") == 0 \ + || strcmp (Fs_type, "subfs") == 0 \ + /* for NetBSD 3.0 */ \ + || strcmp (Fs_type, "kernfs") == 0 \ + /* for Irix 6.5 */ \ + || strcmp (Fs_type, "ignore") == 0) +#endif + +#ifdef __CYGWIN__ +#include +#define ME_REMOTE me_remote +/* All cygwin mount points include `:' or start with `//'; so it + requires a native Windows call to determine remote disks. */ +static int +me_remote (char const *fs_name, char const *fs_type _GL_UNUSED) +{ + if (fs_name[0] && fs_name[1] == ':') + { + char drive[4]; + sprintf (drive, "%c:\\", fs_name[0]); + switch (GetDriveType (drive)) + { + case DRIVE_REMOVABLE: + case DRIVE_FIXED: + case DRIVE_CDROM: + case DRIVE_RAMDISK: + return 0; + } + } + return 1; +} +#endif +#ifndef ME_REMOTE +/* A file system is `remote' if its Fs_name contains a `:' + or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */ +# define ME_REMOTE(Fs_name, Fs_type) \ + (strchr (Fs_name, ':') != NULL \ + || ((Fs_name)[0] == '/' \ + && (Fs_name)[1] == '/' \ + && (strcmp (Fs_type, "smbfs") == 0 || strcmp (Fs_type, "cifs") == 0))) +#endif + +/* Many space usage primitives use all 1 bits to denote a value that is + not applicable or unknown. Propagate this information by returning + a uintmax_t value that is all 1 bits if X is all 1 bits, even if X + is unsigned and narrower than uintmax_t. */ +#define PROPAGATE_ALL_ONES(x) \ + ((sizeof (x) < sizeof (uintmax_t) \ + && (~ (x) == (sizeof (x) < sizeof (int) \ + ? - (1 << (sizeof (x) * CHAR_BIT)) \ + : 0))) \ + ? UINTMAX_MAX : (uintmax_t) (x)) + +/* Extract the top bit of X as an uintmax_t value. */ +#define EXTRACT_TOP_BIT(x) ((x) & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1))) + +/* If a value is negative, many space usage primitives store it into an + integer variable by assignment, even if the variable's type is unsigned. + So, if a space usage variable X's top bit is set, convert X to the + uintmax_t value V such that (- (uintmax_t) V) is the negative of + the original value. If X's top bit is clear, just yield X. + Use PROPAGATE_TOP_BIT if the original value might be negative; + otherwise, use PROPAGATE_ALL_ONES. */ +#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) + +#ifdef STAT_READ_FILSYS /* SVR2 */ +/* Set errno to zero upon EOF. */ +#define ZERO_BYTE_TRANSFER_ERRNO 0 + +#ifdef EINTR +#define IS_EINTR(x) ((x) == EINTR) +#else +#define IS_EINTR(x) 0 +#endif +#endif /* STAT_READ_FILSYS */ + /*** file scope type declarations ****************************************************************/ /* A mount table entry. */ struct mount_entry { - char *me_devname; /* Device node pathname, including "/dev/". */ - char *me_mountdir; /* Mount point directory pathname. */ - char *me_type; /* "nfs", "4.2", etc. */ - dev_t me_dev; /* Device number of me_mountdir. */ + char *me_devname; /* Device node name, including "/dev/". */ + char *me_mountdir; /* Mount point directory name. */ + char *me_type; /* "nfs", "4.2", etc. */ + dev_t me_dev; /* Device number of me_mountdir. */ + unsigned int me_dummy : 1; /* Nonzero for dummy file systems. */ + unsigned int me_remote : 1; /* Nonzero for remote fileystems. */ + unsigned int me_type_malloced : 1; /* Nonzero if me_type was malloced. */ struct mount_entry *me_next; }; struct fs_usage { - fsblkcnt_t fsu_blocks; /* Total blocks. */ - fsblkcnt_t fsu_bfree; /* Free blocks available to superuser. */ - fsblkcnt_t fsu_bavail; /* Free blocks available to non-superuser. */ - fsfilcnt_t fsu_files; /* Total file nodes. */ - fsfilcnt_t fsu_ffree; /* Free file nodes. */ + uintmax_t fsu_blocksize; /* Size of a block. */ + uintmax_t fsu_blocks; /* Total blocks. */ + uintmax_t fsu_bfree; /* Free blocks available to superuser. */ + uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ + int fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ + uintmax_t fsu_files; /* Total file nodes. */ + uintmax_t fsu_ffree; /* Free file nodes. */ }; /*** file scope variables ************************************************************************/ -static int get_fs_usage (char *path, struct fs_usage *fsp); - #ifdef HAVE_INFOMOUNT_LIST -static struct mount_entry *mount_list = NULL; +static struct mount_entry *mc_mount_list = NULL; #endif /* HAVE_INFOMOUNT_LIST */ /*** file scope functions ************************************************************************/ @@ -178,47 +326,18 @@ free_mount_entry (struct mount_entry *me) free (me->me_devname); if (me->me_mountdir) free (me->me_mountdir); - if (me->me_type) + if (me->me_type && me->me_type_malloced) free (me->me_type); free (me); } -#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ - /* --------------------------------------------------------------------------------------------- */ -/* Return the value of the hexadecimal number represented by CP. - No prefix (like '0x') or suffix (like 'h') is expected to be - part of CP. */ - -static int -xatoi (const char *cp) -{ - int val; - - val = 0; - while (*cp) - { - if (*cp >= 'a' && *cp <= 'f') - val = val * 16 + *cp - 'a' + 10; - else if (*cp >= 'A' && *cp <= 'F') - val = val * 16 + *cp - 'A' + 10; - else if (*cp >= '0' && *cp <= '9') - val = val * 16 + *cp - '0'; - else - break; - cp++; - } - return val; -} -#endif /* MOUNTED_GETMNTENT1 */ #ifdef MOUNTED_GETMNTINFO -/* --------------------------------------------------------------------------------------------- */ - #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME static char * -fstype_to_string (short t) +fstype_to_string (short int t) { switch (t) { @@ -312,6 +431,17 @@ fstype_to_string (short t) } #endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */ +/* --------------------------------------------------------------------------------------------- */ + +static char * +fsp_to_string (const struct statfs *fsp) +{ +#if HAVE_STRUCT_STATFS_F_FSTYPENAME + return (char *) (fsp->f_fstypename); +#else + return fstype_to_string (fsp->f_type); +#endif +} #endif /* MOUNTED_GETMNTINFO */ /* --------------------------------------------------------------------------------------------- */ @@ -331,72 +461,150 @@ fstype_to_string (int t) #endif /* MOUNTED_VMOUNT */ /* --------------------------------------------------------------------------------------------- */ -/** Return a list of the currently mounted filesystems, or NULL on error. + +#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2 + +/* Return the device number from MOUNT_OPTIONS, if possible. + Otherwise return (dev_t) -1. */ + +/* --------------------------------------------------------------------------------------------- */ + +static dev_t +dev_from_mount_options (char const *mount_options) +{ + /* GNU/Linux allows file system implementations to define their own + meaning for "dev=" mount options, so don't trust the meaning + here. */ +#ifndef __linux__ + static char const dev_pattern[] = ",dev="; + char const *devopt = strstr (mount_options, dev_pattern); + + if (devopt) + { + char const *optval = devopt + sizeof (dev_pattern) - 1; + char *optvalend; + unsigned long int dev; + errno = 0; + dev = strtoul (optval, &optvalend, 16); + if (optval != optvalend + && (*optvalend == '\0' || *optvalend == ',') + && !(dev == ULONG_MAX && errno == ERANGE) && dev == (dev_t) dev) + return dev; + } +#endif + + (void) mount_options; + return -1; +} + +#endif + +/* --------------------------------------------------------------------------------------------- */ + +#if defined _AIX && defined _I386 +/* AIX PS/2 does not supply statfs. */ + +static int +statfs (char *file, struct statfs *fsb) +{ + struct stat stats; + struct dustat fsd; + + if (stat (file, &stats) != 0) + return -1; + if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) + return -1; + fsb->f_type = 0; + fsb->f_bsize = fsd.du_bsize; + fsb->f_blocks = fsd.du_fsize - fsd.du_isize; + fsb->f_bfree = fsd.du_tfree; + fsb->f_bavail = fsd.du_tfree; + fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; + fsb->f_ffree = fsd.du_tinode; + fsb->f_fsid.val[0] = fsd.du_site; + fsb->f_fsid.val[1] = fsd.du_pckno; + return 0; +} + +#endif /* _AIX && _I386 */ + +/* --------------------------------------------------------------------------------------------- */ + +/* Return a list of the currently mounted file systems, or NULL on error. Add each entry to the tail of the list so that they stay in order. - If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in - the returned list are valid. Otherwise, they might not be. - If ALL_FS is zero, do not return entries for filesystems that - are automounter (dummy) entries. */ + If NEED_FS_TYPE is true, ensure that the file system type fields in + the returned list are valid. Otherwise, they might not be. */ static struct mount_entry * -read_filesystem_list (int need_fs_type, int all_fs) +read_file_system_list (int need_fs_type) { - struct mount_entry *mlist; + struct mount_entry *mount_list; struct mount_entry *me; - struct mount_entry *mtail; + struct mount_entry **mtail = &mount_list; - (void) need_fs_type; - (void) all_fs; +#ifdef MOUNTED_LISTMNTENT + { + struct tabmntent *mntlist, *p; + struct mntent *mnt; + struct mount_entry *me; - /* Start the list off with a dummy entry. */ - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_next = NULL; - mlist = mtail = me; + /* the third and fourth arguments could be used to filter mounts, + but Crays doesn't seem to have any mounts that we want to + remove. Specifically, automount create normal NFS mounts. + */ -#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -#ifdef MOUNTED + if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0) + return NULL; + for (p = mntlist; p; p = p->next) + { + mnt = p->ment; + me = malloc (sizeof (*me)); + me->me_devname = strdup (mnt->mnt_fsname); + me->me_mountdir = strdup (mnt->mnt_dir); + me->me_type = strdup (mnt->mnt_type); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = -1; + *mtail = me; + mtail = &me->me_next; + } + freemntlist (mntlist); + } +#endif + +#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ { struct mntent *mnt; + const char *table = MOUNTED; FILE *fp; - const char *devopt; - fp = setmntent (MOUNTED, "r"); + fp = setmntent (table, "r"); if (fp == NULL) return NULL; while ((mnt = getmntent (fp))) { - if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") || !strcmp (mnt->mnt_type, "auto"))) - continue; - - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me = malloc (sizeof (*me)); me->me_devname = strdup (mnt->mnt_fsname); me->me_mountdir = strdup (mnt->mnt_dir); me->me_type = strdup (mnt->mnt_type); - devopt = strstr (mnt->mnt_opts, "dev="); - if (devopt) - { - if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) - me->me_dev = xatoi (devopt + 6); - else - me->me_dev = xatoi (devopt + 4); - } - else - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = dev_from_mount_options (mnt->mnt_opts); /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } if (endmntent (fp) == 0) - return NULL; + goto free_then_fail; } -#endif /* MOUNTED */ -#endif /* MOUNTED_GETMNTENT1 */ +#endif /* MOUNTED_GETMNTENT1. */ -#if defined(MOUNTED_GETMNTINFO) || defined(MOUNTED_GETMNTINFO2) /* 4.4BSD and NetBSD >= 3 */ +#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ { struct statfs *fsp; int entries; @@ -404,26 +612,51 @@ read_filesystem_list (int need_fs_type, int all_fs) entries = getmntinfo (&fsp, MNT_NOWAIT); if (entries < 0) return NULL; - while (entries-- > 0) + for (; entries-- > 0; fsp++) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + char *fs_type = fsp_to_string (fsp); + + me = malloc (sizeof (*me)); me->me_devname = strdup (fsp->f_mntfromname); me->me_mountdir = strdup (fsp->f_mntonname); -#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || defined(MOUNTED_GETMNTINFO2) - me->me_type = strdup (fsp->f_fstypename); -#else - me->me_type = fstype_to_string (fsp->f_type); -#endif - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; + me->me_type = fs_type; + me->me_type_malloced = 0; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - fsp++; + *mtail = me; + mtail = &me->me_next; } } -#endif /* MOUNTED_GETMNTINFO || MOUNTED_GETMNTINFO2 */ +#endif /* MOUNTED_GETMNTINFO */ + +#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ + { + struct statvfs *fsp; + int entries; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + if (entries < 0) + return NULL; + for (; entries-- > 0; fsp++) + { + me = malloc (sizeof (*me)); + me->me_devname = strdup (fsp->f_mntfromname); + me->me_mountdir = strdup (fsp->f_mntonname); + me->me_type = strdup (fsp->f_fstypename); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + } +#endif /* MOUNTED_GETMNTINFO2 */ #ifdef MOUNTED_GETMNT /* Ultrix. */ { @@ -431,61 +664,176 @@ read_filesystem_list (int need_fs_type, int all_fs) int val; struct fs_data fsd; - while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, NULL)) > 0) + while (errno = 0, 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, (char *) 0))) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me = malloc (sizeof (*me)); me->me_devname = strdup (fsd.fd_req.devname); me->me_mountdir = strdup (fsd.fd_req.path); me->me_type = gt_names[fsd.fd_req.fstype]; + me->me_type_malloced = 0; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); me->me_dev = fsd.fd_req.dev; - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } if (val < 0) - return NULL; + goto free_then_fail; } -#endif /* MOUNTED_GETMNT */ +#endif /* MOUNTED_GETMNT. */ + +#if defined MOUNTED_FS_STAT_DEV /* BeOS */ + { + /* The next_dev() and fs_stat_dev() system calls give the list of + all file systems, including the information returned by statvfs() + (fs type, total blocks, free blocks etc.), but without the mount + point. But on BeOS all file systems except / are mounted in the + rootfs, directly under /. + The directory name of the mount point is often, but not always, + identical to the volume name of the device. + We therefore get the list of subdirectories of /, and the list + of all file systems, and match the two lists. */ + + DIR *dirp; + struct rootdir_entry + { + char *name; + dev_t dev; + ino_t ino; + struct rootdir_entry *next; + }; + struct rootdir_entry *rootdir_list; + struct rootdir_entry **rootdir_tail; + int32 pos; + dev_t dev; + fs_info fi; + + /* All volumes are mounted in the rootfs, directly under /. */ + rootdir_list = NULL; + rootdir_tail = &rootdir_list; + dirp = opendir ("/"); + if (dirp) + { + struct dirent *d; + + while ((d = readdir (dirp)) != NULL) + { + char *name; + struct stat statbuf; + + if (strcmp (d->d_name, "..") == 0) + continue; + + if (strcmp (d->d_name, ".") == 0) + name = strdup ("/"); + else + { + name = malloc (1 + strlen (d->d_name) + 1); + name[0] = '/'; + strcpy (name + 1, d->d_name); + } + + if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) + { + struct rootdir_entry *re = malloc (sizeof (*re)); + re->name = name; + re->dev = statbuf.st_dev; + re->ino = statbuf.st_ino; + + /* Add to the linked list. */ + *rootdir_tail = re; + rootdir_tail = &re->next; + } + else + free (name); + } + closedir (dirp); + } + *rootdir_tail = NULL; + + for (pos = 0; (dev = next_dev (&pos)) >= 0;) + if (fs_stat_dev (dev, &fi) >= 0) + { + /* Note: fi.dev == dev. */ + struct rootdir_entry *re; + + for (re = rootdir_list; re; re = re->next) + if (re->dev == fi.dev && re->ino == fi.root) + break; + + me = malloc (sizeof (*me)); + me->me_devname = strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name); + me->me_mountdir = strdup (re != NULL ? re->name : fi.fsh_name); + me->me_type = strdup (fi.fsh_name); + me->me_type_malloced = 1; + me->me_dev = fi.dev; + me->me_dummy = 0; + me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0; + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + *mtail = NULL; + + while (rootdir_list != NULL) + { + struct rootdir_entry *re = rootdir_list; + rootdir_list = re->next; + free (re->name); + free (re); + } + } +#endif /* MOUNTED_FS_STAT_DEV */ #ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ { - int numsys, counter, bufsize; + int numsys, counter; + size_t bufsize; struct statfs *stats; - numsys = getfsstat ((struct statfs *) 0, 0L, MNT_WAIT); + numsys = getfsstat (NULL, 0L, MNT_NOWAIT); if (numsys < 0) - return (NULL); + return NULL; + if (SIZE_MAX / sizeof (*stats) <= numsys) + { + fprintf (stderr, "%s\n", _("Memory exhausted!")); + exit (EXIT_FAILURE); + } - bufsize = (1 + numsys) * sizeof (struct statfs); - stats = (struct statfs *) malloc (bufsize); - numsys = getfsstat (stats, bufsize, MNT_WAIT); + bufsize = (1 + numsys) * sizeof (*stats); + stats = malloc (bufsize); + numsys = getfsstat (stats, bufsize, MNT_NOWAIT); if (numsys < 0) { free (stats); - return (NULL); + return NULL; } + for (counter = 0; counter < numsys; counter++) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me = malloc (sizeof (*me)); me->me_devname = strdup (stats[counter].f_mntfromname); me->me_mountdir = strdup (stats[counter].f_mntonname); - me->me_type = mnt_names[stats[counter].f_type]; - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; + me->me_type = strdup (FS_TYPE (stats[counter])); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } free (stats); } #endif /* MOUNTED_GETFSSTAT */ -#if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */ +#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */ { struct mnttab mnt; char *table = "/etc/mnttab"; @@ -495,9 +843,9 @@ read_filesystem_list (int need_fs_type, int all_fs) if (fp == NULL) return NULL; - while (fread (&mnt, sizeof mnt, 1, fp) > 0) + while (fread (&mnt, sizeof (mnt), 1, fp) > 0) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me = malloc (sizeof (*me)); #ifdef GETFSTYP /* SVR3. */ me->me_devname = strdup (mnt.mt_dev); #else @@ -506,134 +854,272 @@ read_filesystem_list (int need_fs_type, int all_fs) strcpy (me->me_devname + 5, mnt.mt_dev); #endif me->me_mountdir = strdup (mnt.mt_filsys); - me->me_dev = -1; /* Magic; means not known yet. */ + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ me->me_type = ""; + me->me_type_malloced = 0; #ifdef GETFSTYP /* SVR3. */ if (need_fs_type) { struct statfs fsd; char typebuf[FSTYPSZ]; - if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 + if (statfs (me->me_mountdir, &fsd, sizeof (fsd), 0) != -1 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) + { me->me_type = strdup (typebuf); + me->me_type_malloced = 1; + } } #endif - me->me_next = NULL; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; + } + + if (ferror (fp)) + { + /* The last fread() call must have failed. */ + int saved_errno = errno; + fclose (fp); + errno = saved_errno; + goto free_then_fail; } if (fclose (fp) == EOF) - return NULL; + goto free_then_fail; } -#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */ +#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ -#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */ +#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */ { struct mntent **mnttbl = getmnttbl (), **ent; for (ent = mnttbl; *ent; ent++) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me = malloc (sizeof (*me)); me->me_devname = strdup ((*ent)->mt_resource); me->me_mountdir = strdup ((*ent)->mt_directory); me->me_type = strdup ((*ent)->mt_fstype); - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } endmnttbl (); } -#endif /* MOUNTED_GETMNTTBL */ +#endif #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ { struct mnttab mnt; - const char *table = MNTTAB; + char *table = MNTTAB; FILE *fp; int ret; + int lockfd = -1; +#if defined F_RDLCK && defined F_SETLKW + /* MNTTAB_LOCK is a macro name of our own invention; it's not present in + e.g. Solaris 2.6. If the SVR4 folks ever define a macro + for this file name, we should use their macro name instead. + (Why not just lock MNTTAB directly? We don't know.) */ +#ifndef MNTTAB_LOCK +#define MNTTAB_LOCK "/etc/.mnttab.lock" +#endif + lockfd = open (MNTTAB_LOCK, O_RDONLY); + if (0 <= lockfd) + { + struct flock flock; + flock.l_type = F_RDLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + while (fcntl (lockfd, F_SETLKW, &flock) == -1) + if (errno != EINTR) + { + int saved_errno = errno; + close (lockfd); + errno = saved_errno; + return NULL; + } + } + else if (errno != ENOENT) + return NULL; +#endif + + errno = 0; fp = fopen (table, "r"); if (fp == NULL) - return NULL; - - while ((ret = getmntent (fp, &mnt)) == 0) + ret = errno; + else { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (mnt.mnt_special); - me->me_mountdir = strdup (mnt.mnt_mountp); - me->me_type = strdup (mnt.mnt_fstype); - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + while ((ret = getmntent (fp, &mnt)) == 0) + { + me = malloc (sizeof (*me)); + me->me_devname = strdup (mnt.mnt_special); + me->me_mountdir = strdup (mnt.mnt_mountp); + me->me_type = strdup (mnt.mnt_fstype); + me->me_type_malloced = 1; + me->me_dummy = MNT_IGNORE (&mnt) != 0; + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = dev_from_mount_options (mnt.mnt_mntopts); + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + + ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; } - if (ret > 0) - return NULL; - if (fclose (fp) == EOF) - return NULL; + if (0 <= lockfd && close (lockfd) != 0) + ret = errno; + + if (0 <= ret) + { + errno = ret; + goto free_then_fail; + } } -#endif /* MOUNTED_GETMNTENT2 */ +#endif /* MOUNTED_GETMNTENT2. */ #ifdef MOUNTED_VMOUNT /* AIX. */ { int bufsize; char *entries, *thisent; struct vmount *vmp; + int n_entries; + int i; - /* Ask how many bytes to allocate for the mounted filesystem info. */ - mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize); + /* Ask how many bytes to allocate for the mounted file system info. */ + if (mntctl (MCTL_QUERY, sizeof (bufsize), (struct vmount *) &bufsize) != 0) + return NULL; entries = malloc (bufsize); - /* Get the list of mounted filesystems. */ - mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); - - for (thisent = entries; thisent < entries + bufsize; thisent += vmp->vmt_length) + /* Get the list of mounted file systems. */ + n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); + if (n_entries < 0) { + int saved_errno = errno; + free (entries); + errno = saved_errno; + return NULL; + } + + for (i = 0, thisent = entries; i < n_entries; i++, thisent += vmp->vmt_length) + { + char *options, *ignore; + vmp = (struct vmount *) thisent; - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me = malloc (sizeof (*me)); if (vmp->vmt_flags & MNT_REMOTE) { - char *host, *path; + char *host, *dir; - /* Prepend the remote pathname. */ + me->me_remote = 1; + /* Prepend the remote dirname. */ host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; - path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; - me->me_devname = malloc (strlen (host) + strlen (path) + 2); + dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; + me->me_devname = malloc (strlen (host) + strlen (dir) + 2); strcpy (me->me_devname, host); strcat (me->me_devname, ":"); - strcat (me->me_devname, path); + strcat (me->me_devname, dir); } else { + me->me_remote = 0; me->me_devname = strdup (thisent + vmp->vmt_data[VMT_OBJECT].vmt_off); } me->me_mountdir = strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); me->me_type = strdup (fstype_to_string (vmp->vmt_gfstype)); - me->me_dev = -1; /* vmt_fsid might be the info we want. */ - me->me_next = NULL; + me->me_type_malloced = 1; + options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; + ignore = strstr (options, "ignore"); + me->me_dummy = (ignore + && (ignore == options || ignore[-1] == ',') + && (ignore[sizeof ("ignore") - 1] == ',' + || ignore[sizeof ("ignore") - 1] == '\0')); + me->me_dev = (dev_t)(-1); /* vmt_fsid might be the info we want. */ /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } free (entries); } -#endif /* MOUNTED_VMOUNT */ +#endif /* MOUNTED_VMOUNT. */ - /* Free the dummy head. */ - me = mlist; - mlist = mlist->me_next; - free (me); - return mlist; + +#ifdef MOUNTED_INTERIX_STATVFS + { + DIR *dirp = opendir ("/dev/fs"); + char node[9 + NAME_MAX]; + + if (!dirp) + goto free_then_fail; + + while (1) + { + struct statvfs dev; + struct dirent entry; + struct dirent *result; + + if (readdir_r (dirp, &entry, &result) || result == NULL) + break; + + strcpy (node, "/dev/fs/"); + strcat (node, entry.d_name); + + if (statvfs (node, &dev) == 0) + { + me = malloc (sizeof *me); + me->me_devname = strdup (dev.f_mntfromname); + me->me_mountdir = strdup (dev.f_mntonname); + me->me_type = strdup (dev.f_fstypename); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + } + } +#endif /* MOUNTED_INTERIX_STATVFS */ + + (void) need_fs_type; /* avoid argument-unused warning */ + *mtail = NULL; + return mount_list; + + + free_then_fail: + { + int saved_errno = errno; + *mtail = NULL; + + while (mount_list) + { + me = mount_list->me_next; + free (mount_list->me_devname); + free (mount_list->me_mountdir); + if (mount_list->me_type_malloced) + free (mount_list->me_type); + free (mount_list); + mount_list = me; + } + + errno = saved_errno; + return NULL; + } } + #endif /* HAVE_INFOMOUNT_LIST */ /* --------------------------------------------------------------------------------------------- */ @@ -648,7 +1134,7 @@ read_filesystem_list (int need_fs_type, int all_fs) */ static struct mount_entry * -read_filesystem_list (int need_fs_type, int all_fs) +read_file_system_list (int need_fs_type, int all_fs) { struct _disk_entry de; struct statfs fs; @@ -733,141 +1219,238 @@ read_filesystem_list (int need_fs_type, int all_fs) } #endif /* HAVE_INFOMOUNT_QNX */ +/* --------------------------------------------------------------------------------------------- */ + +#ifdef STAT_READ_FILSYS /* SVR2 */ + +/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if + interrupted. Return the actual number of bytes read(written), zero for EOF, + or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */ +static size_t +safe_read (int fd, void *buf, size_t count) +{ + /* Work around a bug in Tru64 5.1. Attempting to read more than + INT_MAX bytes fails with errno == EINVAL. See + . + When decreasing COUNT, keep it block-aligned. */ + enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 }; + + for (;;) + { + ssize_t result = read (fd, buf, count); + + if (0 <= result) + return result; + else if (IS_EINTR (errno)) + continue; + else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count) + count = BUGGY_READ_MAXIMUM; + else + return result; + } +} + +/* --------------------------------------------------------------------------------------------- */ + +/* Read COUNT bytes at BUF to(from) descriptor FD, retrying if + interrupted or if a partial write(read) occurs. Return the number + of bytes transferred. + When writing, set errno if fewer than COUNT bytes are written. + When reading, if fewer than COUNT bytes are read, you must examine + errno to distinguish failure from EOF (errno == 0). */ + +static size_t +full_read (int fd, void *buf, size_t count) +{ + size_t total = 0; + char *ptr = (char *) buf; + + while (count > 0) + { + size_t n_rw = safe_read (fd, ptr, count); + if (n_rw == (size_t) (-1)) + break; + if (n_rw == 0) + { + errno = ZERO_BYTE_TRANSFER_ERRNO; + break; + } + total += n_rw; + ptr += n_rw; + count -= n_rw; + } + + return total; +} + +#endif /* STAT_READ_FILSYS */ + +/* --------------------------------------------------------------------------------------------- */ + #ifdef HAVE_INFOMOUNT -/** Return the number of TOSIZE-byte blocks used by - BLOCKS FROMSIZE-byte blocks, rounding away from zero. - TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */ - -static fsblkcnt_t -fs_adjust_blocks (fsblkcnt_t blocks, int fromsize, int tosize) -{ - if (tosize <= 0) - abort (); - if (fromsize <= 0) - return -1; - - if (fromsize == tosize) /* E.g., from 512 to 512. */ - return blocks; - else if (fromsize > tosize) /* E.g., from 2048 to 512. */ - return blocks * (fromsize / tosize); - else /* E.g., from 256 to 512. */ - return blocks / (tosize / fromsize); -} - -/* --------------------------------------------------------------------------------------------- */ -#if defined(_AIX) && defined(_I386) -/* AIX PS/2 does not supply statfs. */ -static int -aix_statfs (char *path, struct statfs *fsb) -{ - struct stat stats; - struct dustat fsd; - - if (stat (path, &stats)) - return -1; - if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) - return -1; - fsb->f_type = 0; - fsb->f_bsize = fsd.du_bsize; - fsb->f_blocks = fsd.du_fsize - fsd.du_isize; - fsb->f_bfree = fsd.du_tfree; - fsb->f_bavail = fsd.du_tfree; - fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; - fsb->f_ffree = fsd.du_tinode; - fsb->f_fsid.val[0] = fsd.du_site; - fsb->f_fsid.val[1] = fsd.du_pckno; - return 0; -} - -#define statfs(path,fsb) aix_statfs(path,fsb) -#endif /* _AIX && _I386 */ - /* Fill in the fields of FSP with information about space usage for - the filesystem on which PATH resides. - Return 0 if successful, -1 if not. */ - -/* --------------------------------------------------------------------------------------------- */ + the file system on which FILE resides. + DISK is the device on which FILE is mounted, for space-getting + methods that need to know it. + Return 0 if successful, -1 if not. When returning -1, ensure that + ERRNO is either a system error value, or zero if DISK is NULL + on a system that requires a non-NULL value. */ static int -get_fs_usage (char *path, struct fs_usage *fsp) +get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) { -#ifdef STAT_STATFS3_OSF1 - struct statfs fsd; +#ifdef STAT_STATVFS /* POSIX, except glibc/Linux */ - if (statfs (path, &fsd, sizeof (struct statfs)) != 0) + struct statvfs fsd; + + if (statvfs (file, &fsd) < 0) return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512) -#endif /* STAT_STATFS3_OSF1 */ -#ifdef STAT_STATFS2_FS_DATA /* Ultrix. */ + /* f_frsize isn't guaranteed to be supported. */ + fsp->fsu_blocksize = (fsd.f_frsize + ? PROPAGATE_ALL_ONES (fsd.f_frsize) : PROPAGATE_ALL_ONES (fsd.f_bsize)); + +#elif defined STAT_STATVFS64 /* AIX */ + + struct statvfs64 fsd; + + if (statvfs64 (file, &fsd) < 0) + return -1; + + /* f_frsize isn't guaranteed to be supported. */ + fsp->fsu_blocksize = (fsd.f_frsize + ? PROPAGATE_ALL_ONES (fsd.f_frsize) : PROPAGATE_ALL_ONES (fsd.f_bsize)); + +#elif defined STAT_STATFS2_FS_DATA /* Ultrix */ + struct fs_data fsd; - if (statfs (path, &fsd) != 1) + if (statfs (file, &fsd) != 1) return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), 1024, 512) - fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot); - fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree); - fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen); - fsp->fsu_files = fsd.fd_req.gtot; - fsp->fsu_ffree = fsd.fd_req.gfree; + + fsp->fsu_blocksize = 1024; + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0; + fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree); + +#elif defined STAT_READ_FILSYS /* SVR2 */ +#ifndef SUPERBOFF +#define SUPERBOFF (SUPERB * 512) #endif -#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */ + struct filsys fsd; + int fd; + + if (!disk) + { + errno = 0; + return -1; + } + + fd = open (disk, O_RDONLY); + if (fd < 0) + return -1; + lseek (fd, (off_t) SUPERBOFF, 0); + if (full_read (fd, (char *) &fsd, sizeof (fsd)) != sizeof (fsd)) + { + close (fd); + return -1; + } + close (fd); + + fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512); + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0; + fsp->fsu_files = (fsd.s_isize == -1 + ? UINTMAX_MAX : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1)); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode); + +#elif defined STAT_STATFS3_OSF1 /* OSF/1 */ + struct statfs fsd; - if (statfs (path, &fsd) < 0) + if (statfs (file, &fsd, sizeof (struct statfs)) != 0) return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512) + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS2_BSIZE /* glibc/Linux, 4.3BSD, SunOS 4, \ + MacOS X < 10.4, FreeBSD < 5.0, \ + NetBSD < 3.0, OpenBSD < 4.4 */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); + +#ifdef STATFS_TRUNCATES_BLOCK_COUNTS + + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0) + { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ + +#elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \ + Dolphin */ + +#if !defined _AIX && !defined _SEQUENT_ && !defined DOLPHIN +#define f_bavail f_bfree #endif -#ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */ struct statfs fsd; - if (statfs (path, &fsd) < 0) + if (statfs (file, &fsd, sizeof (fsd), 0) < 0) return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512) -#endif -#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX. */ - struct statfs fsd; - - if (statfs (path, &fsd, sizeof fsd, 0) < 0) - return -1; /* Empirically, the block counts on most SVR3 and SVR3-derived systems seem to always be in terms of 512-byte blocks, no matter what value f_bsize has. */ -#if _AIX -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512) +#if defined _AIX || defined _CRAY + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); #else -#define CONVERT_BLOCKS(b) (b) -#ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */ -#ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ -#define f_bavail f_bfree -#endif -#endif -#endif + fsp->fsu_blocksize = 512; #endif -#ifdef STAT_STATVFS /* SVR4. */ - struct statvfs fsd; - - if (statvfs (path, &fsd) < 0) - return -1; - /* f_frsize isn't guaranteed to be supported. */ -#define CONVERT_BLOCKS(b) \ - fs_adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512) #endif -#if defined(CONVERT_BLOCKS) && !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS) /* !Ultrix && !SVR2. */ - fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks); - fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree); - fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail); - fsp->fsu_files = fsd.f_files; - fsp->fsu_ffree = fsd.f_ffree; +#if (defined STAT_STATVFS || defined STAT_STATVFS64 \ + || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS)) + + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0; + fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree); + #endif + (void) disk; /* avoid argument-unused warning */ return 0; } - #endif /* HAVE_INFOMOUNT */ /* --------------------------------------------------------------------------------------------- */ @@ -878,13 +1461,16 @@ void free_my_statfs (void) { #ifdef HAVE_INFOMOUNT_LIST - while (mount_list) + while (mc_mount_list != NULL) { - struct mount_entry *next = mount_list->me_next; - free_mount_entry (mount_list); - mount_list = next; + struct mount_entry *next; + + next = mc_mount_list->me_next; + free_mount_entry (mc_mount_list); + mc_mount_list = next; } - mount_list = NULL; + + mc_mount_list = NULL; #endif /* HAVE_INFOMOUNT_LIST */ } @@ -895,7 +1481,7 @@ init_my_statfs (void) { #ifdef HAVE_INFOMOUNT_LIST free_my_statfs (); - mount_list = read_filesystem_list (1, 1); + mc_mount_list = read_file_system_list (1); #endif /* HAVE_INFOMOUNT_LIST */ } @@ -907,7 +1493,7 @@ my_statfs (struct my_statfs *myfs_stats, const char *path) #ifdef HAVE_INFOMOUNT_LIST size_t i, len = 0; struct mount_entry *entry = NULL; - struct mount_entry *temp = mount_list; + struct mount_entry *temp = mc_mount_list; struct fs_usage fs_use; while (temp) @@ -925,23 +1511,23 @@ my_statfs (struct my_statfs *myfs_stats, const char *path) if (entry) { memset (&fs_use, 0, sizeof (struct fs_usage)); - get_fs_usage (entry->me_mountdir, &fs_use); + get_fs_usage (entry->me_mountdir, NULL, &fs_use); myfs_stats->type = entry->me_dev; myfs_stats->typename = entry->me_type; myfs_stats->mpoint = entry->me_mountdir; myfs_stats->device = entry->me_devname; - myfs_stats->avail = getuid ()? fs_use.fsu_bavail / 2 : fs_use.fsu_bfree / 2; - myfs_stats->total = fs_use.fsu_blocks / 2; - myfs_stats->nfree = fs_use.fsu_ffree; - myfs_stats->nodes = fs_use.fsu_files; + myfs_stats->avail = ((uintmax_t) (getuid () ? fs_use.fsu_bavail : fs_use.fsu_bfree) * fs_use.fsu_blocksize) >> 10; + myfs_stats->total = ((uintmax_t) fs_use.fsu_blocks * fs_use.fsu_blocksize) >> 10; + myfs_stats->nfree = (uintmax_t) fs_use.fsu_ffree; + myfs_stats->nodes = (uintmax_t) fs_use.fsu_files; } else #endif /* HAVE_INFOMOUNT_LIST */ #ifdef HAVE_INFOMOUNT_QNX /* - ** This is the "other side" of the hack to read_filesystem_list() in + ** This is the "other side" of the hack to read_file_system_list() in ** mountlist.c. ** It's not the most efficient approach, but consumes less memory. It ** also accomodates QNX's ability to mount filesystems on the fly. @@ -949,20 +1535,20 @@ my_statfs (struct my_statfs *myfs_stats, const char *path) struct mount_entry *entry; struct fs_usage fs_use; - entry = read_filesystem_list (0, 0); + entry = read_file_system_list (0, 0); if (entry != NULL) { - get_fs_usage (entry->me_mountdir, &fs_use); + get_fs_usage (entry->me_mountdir, NULL, &fs_use); myfs_stats->type = entry->me_dev; myfs_stats->typename = entry->me_type; myfs_stats->mpoint = entry->me_mountdir; myfs_stats->device = entry->me_devname; - myfs_stats->avail = fs_use.fsu_bfree / 2; - myfs_stats->total = fs_use.fsu_blocks / 2; - myfs_stats->nfree = fs_use.fsu_ffree; - myfs_stats->nodes = fs_use.fsu_files; + myfs_stats->avail = ((uintmax_t) fs_use.fsu_bfree * fs_use.fsu_blocksize) >> 10; + myfs_stats->total = ((uintmax_t) fs_use.fsu_blocks * fs_use.fsu_blocksize) >> 10; + myfs_stats->nfree = (uintmax_t) fs_use.fsu_ffree; + myfs_stats->nodes = (uintmax_t) fs_use.fsu_files; } else #endif /* HAVE_INFOMOUNT_QNX */ diff --git a/src/filemanager/mountlist.h b/src/filemanager/mountlist.h index b25d2c3a3..46f35137e 100644 --- a/src/filemanager/mountlist.h +++ b/src/filemanager/mountlist.h @@ -9,6 +9,8 @@ #ifndef MC__MOUNTLIST_H #define MC__MOUNTLIST_H +#include /* uintmax_t */ + /*** typedefs(not structures) and defined constants **********************************************/ /*** enums ***************************************************************************************/ @@ -22,20 +24,20 @@ struct my_statfs char *typename; const char *mpoint; const char *device; - int avail; - int total; - int nfree; - int nodes; + uintmax_t avail; /* in kB */ + uintmax_t total; /* in kB */ + uintmax_t nfree; + uintmax_t nodes; }; /*** global variables defined in .c file *********************************************************/ /*** declarations of public functions ************************************************************/ -/*** inline functions ****************************************************************************/ - void init_my_statfs (void); void my_statfs (struct my_statfs *myfs_stats, const char *path); void free_my_statfs (void); +/*** inline functions ****************************************************************************/ + #endif /* MC__MOUNTLIST_H */ diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c index 15895ae6c..64c1c7e6b 100644 --- a/src/filemanager/panel.c +++ b/src/filemanager/panel.c @@ -1048,7 +1048,7 @@ show_free_space (WPanel * panel) my_statfs (&myfs_stats, rpath); } - if (myfs_stats.avail > 0 || myfs_stats.total > 0) + if (myfs_stats.avail != 0 || myfs_stats.total != 0) { char buffer1[6], buffer2[6], tmp[BUF_SMALL]; size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1, @@ -1056,8 +1056,8 @@ show_free_space (WPanel * panel) size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1, panels_options.kilobyte_si); g_snprintf (tmp, sizeof (tmp), " %s/%s (%d%%) ", buffer1, buffer2, - myfs_stats.total > - 0 ? (int) (100 * (double) myfs_stats.avail / myfs_stats.total) : 0); + myfs_stats.total == 0 ? 0 : + (int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); widget_move (&panel->widget, panel->widget.lines - 1, panel->widget.cols - 2 - (int) strlen (tmp)); tty_setcolor (NORMAL_COLOR);