Code

from GNU fileutils for check_disk
authorKarl DeBisschop <kdebisschop@users.sourceforge.net>
Tue, 18 Mar 2003 07:47:37 +0000 (07:47 +0000)
committerKarl DeBisschop <kdebisschop@users.sourceforge.net>
Tue, 18 Mar 2003 07:47:37 +0000 (07:47 +0000)
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@429 f882894a-f735-0410-b71e-b25c423dba1c

lib/afs.m4 [new file with mode: 0644]
lib/fstypename.m4 [new file with mode: 0644]
lib/fsusage.c [new file with mode: 0644]
lib/fsusage.h [new file with mode: 0644]
lib/fsusage.m4 [new file with mode: 0644]
lib/ls-mntd-fs.m4 [new file with mode: 0644]
lib/mountlist.c [new file with mode: 0644]
lib/mountlist.h [new file with mode: 0644]

diff --git a/lib/afs.m4 b/lib/afs.m4
new file mode 100644 (file)
index 0000000..13f3bc9
--- /dev/null
@@ -0,0 +1,12 @@
+#serial 3
+
+AC_DEFUN(jm_AFS,
+  AC_MSG_CHECKING(for AFS)
+  if test -d /afs; then
+    AC_DEFINE(AFS, 1, [Define if you have the Andrew File System.])
+    ac_result=yes
+  else
+    ac_result=no
+  fi
+  AC_MSG_RESULT($ac_result)
+)
diff --git a/lib/fstypename.m4 b/lib/fstypename.m4
new file mode 100644 (file)
index 0000000..70abc12
--- /dev/null
@@ -0,0 +1,32 @@
+#serial 2
+
+dnl From Jim Meyering.
+dnl
+dnl See if struct statfs has the f_fstypename member.
+dnl If so, define HAVE_F_FSTYPENAME_IN_STATFS.
+dnl
+
+AC_DEFUN(jm_FSTYPENAME,
+  [
+    AC_CACHE_CHECK([for f_fstypename in struct statfs],
+                  fu_cv_sys_f_fstypename_in_statfs,
+      [
+       AC_TRY_COMPILE(
+         [
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+         ],
+         [struct statfs s; int i = sizeof s.f_fstypename;],
+         fu_cv_sys_f_fstypename_in_statfs=yes,
+         fu_cv_sys_f_fstypename_in_statfs=no
+       )
+      ]
+    )
+
+    if test $fu_cv_sys_f_fstypename_in_statfs = yes; then
+      AC_DEFINE_UNQUOTED(HAVE_F_FSTYPENAME_IN_STATFS, 1,
+                        [Define if struct statfs has the f_fstypename member.])
+    fi
+  ]
+)
diff --git a/lib/fsusage.c b/lib/fsusage.c
new file mode 100644 (file)
index 0000000..5a864bf
--- /dev/null
@@ -0,0 +1,281 @@
+/* fsusage.c -- return space usage of mounted filesystems
+   Copyright (C) 1991, 1992, 1996, 1998, 1999 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "../plugins/config.h"
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "fsusage.h"
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+int statfs ();
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_SYS_MOUNT_H
+# include <sys/mount.h>
+#endif
+
+#if HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+
+#if HAVE_SYS_FS_S5PARAM_H      /* Fujitsu UXP/V */
+# include <sys/fs/s5param.h>
+#endif
+
+#if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY)
+# include <sys/filsys.h>       /* SVR2 */
+#endif
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if HAVE_SYS_STATFS_H
+# include <sys/statfs.h>
+#endif
+
+#if HAVE_DUSTAT_H              /* AIX PS/2 */
+# include <sys/dustat.h>
+#endif
+
+#if HAVE_SYS_STATVFS_H         /* SVR4 */
+# include <sys/statvfs.h>
+int statvfs ();
+#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 the argument is all 1 bits,
+   even if the argument is unsigned and smaller than uintmax_t.  */
+#define PROPAGATE_ALL_ONES(x) ((x) == -1 ? (uintmax_t) -1 : (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))
+
+int safe_read ();
+
+/* Fill in the fields of FSP with information about space usage for
+   the filesystem on which PATH resides.
+   DISK is the device on which PATH 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.  */
+int
+get_fs_usage (const char *path, const char *disk, struct fs_usage *fsp)
+{
+#ifdef STAT_STATFS3_OSF1
+
+  struct statfs fsd;
+
+  if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
+    return -1;
+
+  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
+
+#endif /* STAT_STATFS3_OSF1 */
+
+#ifdef STAT_STATFS2_FS_DATA    /* Ultrix */
+
+  struct fs_data fsd;
+
+  if (statfs (path, &fsd) != 1)
+    return -1;
+
+  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);
+
+#endif /* STAT_STATFS2_FS_DATA */
+
+#ifdef STAT_READ_FILSYS                /* SVR2 */
+# ifndef SUPERBOFF
+#  define SUPERBOFF (SUPERB * 512)
+# endif
+
+  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 (safe_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_t) -1
+                   : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
+  fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
+
+#endif /* STAT_READ_FILSYS */
+
+#ifdef STAT_STATFS2_BSIZE      /* 4.3BSD, SunOS 4, HP-UX, AIX */
+
+  struct statfs fsd;
+
+  if (statfs (path, &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 */
+
+#endif /* STAT_STATFS2_BSIZE */
+
+#ifdef STAT_STATFS2_FSIZE      /* 4.4BSD */
+
+  struct statfs fsd;
+
+  if (statfs (path, &fsd) < 0)
+    return -1;
+
+  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
+
+#endif /* STAT_STATFS2_FSIZE */
+
+#ifdef STAT_STATFS4            /* SVR3, Dynix, Irix, AIX */
+
+# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
+#  define f_bavail f_bfree
+# endif
+
+  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 || defined(_CRAY)
+   fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
+# else
+   fsp->fsu_blocksize = 512;
+# endif
+
+#endif /* STAT_STATFS4 */
+
+#ifdef STAT_STATVFS            /* SVR4 */
+
+  struct statvfs fsd;
+
+  if (statvfs (path, &fsd) < 0)
+    return -1;
+
+  /* f_frsize isn't guaranteed to be supported.  */
+  fsp->fsu_blocksize =
+    PROPAGATE_ALL_ONES (fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize);
+
+#endif /* STAT_STATVFS */
+
+#if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS)
+                               /* !Ultrix && !SVR2 */
+
+  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 /* not STAT_STATFS2_FS_DATA && not STAT_READ_FILSYS */
+
+  return 0;
+}
+
+#if defined(_AIX) && defined(_I386)
+/* AIX PS/2 does not supply statfs.  */
+
+int
+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;
+}
+
+#endif /* _AIX && _I386 */
diff --git a/lib/fsusage.h b/lib/fsusage.h
new file mode 100644 (file)
index 0000000..e0c0db5
--- /dev/null
@@ -0,0 +1,45 @@
+/* fsusage.h -- declarations for filesystem space usage info
+   Copyright (C) 1991, 1992, 1997 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Space usage statistics for a filesystem.  Blocks are 512-byte. */
+
+#if !defined FSUSAGE_H_
+# define FSUSAGE_H_
+
+struct fs_usage
+{
+  int 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. */
+};
+
+# ifndef PARAMS
+#  if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+#   define PARAMS(Args) Args
+#  else
+#   define PARAMS(Args) ()
+#  endif
+# endif
+
+int get_fs_usage PARAMS ((const char *path, const char *disk,
+                         struct fs_usage *fsp));
+
+#endif
diff --git a/lib/fsusage.m4 b/lib/fsusage.m4
new file mode 100644 (file)
index 0000000..d5c646f
--- /dev/null
@@ -0,0 +1,194 @@
+#serial 7
+
+# From fileutils/configure.in
+
+# Try to determine how a program can obtain filesystem usage information.
+# If successful, define the appropriate symbol (see fsusage.c) and
+# execute ACTION-IF-FOUND.  Otherwise, execute ACTION-IF-NOT-FOUND.
+#
+# jm_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN(jm_FILE_SYSTEM_USAGE,
+[
+
+echo "checking how to get filesystem 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
+  # SVR4
+  AC_CACHE_CHECK([for statvfs function (SVR4)], fu_cv_sys_stat_statvfs,
+                [AC_TRY_LINK([#include <sys/types.h>
+#include <sys/statvfs.h>],
+                             [struct statvfs fsd; 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
+    AC_DEFINE_UNQUOTED(STAT_STATVFS, 1,
+             [  Define if there is a function named statvfs.  (SVR4)])
+  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_TRY_RUN([
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+  main ()
+  {
+    struct statfs fsd;
+    fsd.f_fsize = 0;
+    exit (statfs (".", &fsd, sizeof (struct statfs)));
+  }],
+  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_UNQUOTED(STAT_STATFS3_OSF1, 1,
+             [   Define if  statfs takes 3 args.  (DEC Alpha running OSF/1)])
+  fi
+fi
+
+if test $ac_fsusage_space = no; 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 <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+  main ()
+  {
+  struct statfs fsd;
+  fsd.f_bsize = 0;
+  exit (statfs (".", &fsd));
+  }],
+  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_UNQUOTED(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
+  AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)])
+  AC_CACHE_VAL(fu_cv_sys_stat_statfs4,
+  [AC_TRY_RUN([#include <sys/types.h>
+#include <sys/statfs.h>
+  main ()
+  {
+  struct statfs fsd;
+  exit (statfs (".", &fsd, sizeof fsd, 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_UNQUOTED(STAT_STATFS4, 1,
+             [  Define if statfs takes 4 args.  (SVR3, Dynix, Irix, Dolphin)])
+  fi
+fi
+
+if test $ac_fsusage_space = no; 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 <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+  main ()
+  {
+  struct statfs fsd;
+  fsd.f_fsize = 0;
+  exit (statfs (".", &fsd));
+  }],
+  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_UNQUOTED(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_TRY_RUN([#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_FS_TYPES_H
+#include <sys/fs_types.h>
+#endif
+  main ()
+  {
+  struct fs_data fsd;
+  /* Ultrix's statfs returns 1 for success,
+     0 for not mounted, -1 for failure.  */
+  exit (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_UNQUOTED(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
+  AC_TRY_CPP([#include <sys/filsys.h>
+    ],
+    AC_DEFINE_UNQUOTED(STAT_READ_FILSYS, 1,
+      [Define if there is no specific function for reading filesystems usage
+       information and you have the <sys/filsys.h> header file.  (SVR2)])
+    ac_fsusage_space=yes)
+fi
+
+dnl AS_IF([test $ac_fsusage_space = yes], [$1], [$2])
+if test $ac_fsusage_space = yes ; then [$1] ; else [$2] ; fi
+
+])
diff --git a/lib/ls-mntd-fs.m4 b/lib/ls-mntd-fs.m4
new file mode 100644 (file)
index 0000000..695b3ba
--- /dev/null
@@ -0,0 +1,243 @@
+#serial 10
+
+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.
+dnl
+
+# jm_LIST_MOUNTED_FILESYSTEMS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN(jm_LIST_MOUNTED_FILESYSTEMS,
+  [
+AC_CHECK_FUNCS(listmntent getmntinfo)
+AC_CHECK_HEADERS(mntent.h)
+
+# Determine how to get the list of mounted filesystems.
+ac_list_mounted_fs=
+
+# If the getmntent function is available but not in the standard library,
+# make sure LIBS contains -lsun (on Irix4) or -lseq (on PTX).
+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 filesystems. (UNICOS)])
+  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,
+                [test $ac_cv_header_mntent_h = yes \
+                  && 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 filesystems, 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 filesystems, and that function takes two arguments.  (SVR4)])
+    fi
+  fi
+
+  if test -z "$ac_list_mounted_fs"; then
+    AC_MSG_ERROR([could not determine how to read list of mounted filesystems])
+  fi
+
+fi
+
+if test -z "$ac_list_mounted_fs"; then
+  # DEC Alpha running OSF/1.
+  AC_MSG_CHECKING([for getfsstat function])
+  AC_CACHE_VAL(fu_cv_sys_mounted_getsstat,
+  [AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/fs_types.h>],
+  [struct statfs *stats;
+  int numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT); ],
+    fu_cv_sys_mounted_getsstat=yes,
+    fu_cv_sys_mounted_getsstat=no)])
+  AC_MSG_RESULT($fu_cv_sys_mounted_getsstat)
+  if test $fu_cv_sys_mounted_getsstat = 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 filesystems.  (DEC Alpha running OSF/1)])
+  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_TRY_CPP([#include <fshelp.h>],
+    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 filesystems, and there is a system header file
+   that declares `struct vmount.'  (AIX)])
+  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_TRY_CPP([
+#include <sys/statfs.h>
+#include <sys/fstyp.h>
+#include <mnttab.h>],
+               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 filesystems, and your system has these header files:
+   <sys/fstyp.h> and <sys/statfs.h>.  (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,
+    [
+      ok=
+      if test $ac_cv_func_getmntinfo = yes; then
+       AC_EGREP_HEADER(f_type;, sys/mount.h,
+                       ok=yes)
+      fi
+      test -n "$ok" \
+         && 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_list_mounted_fs=found
+    AC_DEFINE(MOUNTED_GETMNTINFO, 1,
+             [Define if there is a function named getmntinfo for reading the
+   list of mounted filesystems.  (4.4BSD)])
+  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_TRY_CPP([
+#include <sys/fs_types.h>
+#include <sys/mount.h>],
+               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 filesystems.  (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 filesystems.  (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_TRY_CPP([#include <mnttab.h>],
+               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 filesystems.  fread will be used to read /etc/mnttab.  (SVR2) ])
+  fi
+fi
+
+if test -z "$ac_list_mounted_fs"; then
+  AC_MSG_ERROR([could not determine how to read list of mounted filesystems])
+  # FIXME -- no need to abort building the whole package
+  # Can't build mountlist.c or anything that needs its functions
+fi
+
+dnl AS_IF([test $ac_list_mounted_fs = found], [$1], [$2])
+if test $ac_list_mounted_fs = found ; then [$1] ; else [$2] ; fi
+
+  ])
diff --git a/lib/mountlist.c b/lib/mountlist.c
new file mode 100644 (file)
index 0000000..b667c44
--- /dev/null
@@ -0,0 +1,788 @@
+/* mountlist.c -- return a list of mounted filesystems
+   Copyright (C) 1991, 1992, 1997-2000 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "../plugins/config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "mountlist.h"
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#else
+void free ();
+#endif
+#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#ifndef strstr
+char *strstr ();
+#endif
+char *xmalloc ();
+char *xrealloc ();
+char *xstrdup ();
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if defined (MOUNTED_GETFSSTAT)        /* __alpha running OSF_1 */
+# include <sys/mount.h>
+# include <sys/fs_types.h>
+#endif /* MOUNTED_GETFSSTAT */
+
+#ifdef MOUNTED_GETMNTENT1      /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
+# include <mntent.h>
+# if !defined(MOUNTED)
+#  if defined(MNT_MNTTAB)      /* HP-UX.  */
+#   define MOUNTED MNT_MNTTAB
+#  endif
+#  if defined(MNTTABNAME)      /* Dynix.  */
+#   define MOUNTED MNTTABNAME
+#  endif
+# endif
+#endif
+
+#ifdef MOUNTED_GETMNTINFO      /* 4.4BSD.  */
+# include <sys/mount.h>
+#endif
+
+#ifdef MOUNTED_GETMNT          /* Ultrix.  */
+# include <sys/mount.h>
+# include <sys/fs_types.h>
+#endif
+
+#ifdef MOUNTED_FS_STAT_DEV     /* BeOS.  */
+# include <fs_info.h>
+# include <dirent.h>
+#endif
+
+#ifdef MOUNTED_FREAD           /* SVR2.  */
+# include <mnttab.h>
+#endif
+
+#ifdef MOUNTED_FREAD_FSTYP     /* SVR3.  */
+# include <mnttab.h>
+# include <sys/fstyp.h>
+# include <sys/statfs.h>
+#endif
+
+#ifdef MOUNTED_LISTMNTENT
+# include <mntent.h>
+#endif
+
+#ifdef MOUNTED_GETMNTENT2      /* SVR4.  */
+# include <sys/mnttab.h>
+#endif
+
+#ifdef MOUNTED_VMOUNT          /* AIX.  */
+# include <fshelp.h>
+# include <sys/vfs.h>
+#endif
+
+#ifdef DOLPHIN
+/* So special that it's not worth putting this in autoconf.  */
+# undef MOUNTED_FREAD_FSTYP
+# define MOUNTED_GETMNTTBL
+#endif
+
+#if HAVE_SYS_MNTENT_H
+/* This is to get MNTOPT_IGNORE on e.g. SVR4.  */
+# include <sys/mntent.h>
+#endif
+
+#if defined (MNTOPT_IGNORE) && defined (HAVE_HASMNTOPT)
+# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
+#else
+# define MNT_IGNORE(M) 0
+#endif
+
+#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. */
+/* FIXME: this can overflow */
+
+static int
+xatoi (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.  */
+
+#if MOUNTED_GETMNTINFO
+
+# if ! HAVE_F_FSTYPENAME_IN_STATFS
+static char *
+fstype_to_string (short t)
+{
+  switch (t)
+    {
+#  ifdef MOUNT_PC
+    case MOUNT_PC:
+      return "pc";
+#  endif
+#  ifdef MOUNT_MFS
+    case MOUNT_MFS:
+      return "mfs";
+#  endif
+#  ifdef MOUNT_LO
+    case MOUNT_LO:
+      return "lo";
+#  endif
+#  ifdef MOUNT_TFS
+    case MOUNT_TFS:
+      return "tfs";
+#  endif
+#  ifdef MOUNT_TMP
+    case MOUNT_TMP:
+      return "tmp";
+#  endif
+#  ifdef MOUNT_UFS
+   case MOUNT_UFS:
+     return "ufs" ;
+#  endif
+#  ifdef MOUNT_NFS
+   case MOUNT_NFS:
+     return "nfs" ;
+#  endif
+#  ifdef MOUNT_MSDOS
+   case MOUNT_MSDOS:
+     return "msdos" ;
+#  endif
+#  ifdef MOUNT_LFS
+   case MOUNT_LFS:
+     return "lfs" ;
+#  endif
+#  ifdef MOUNT_LOFS
+   case MOUNT_LOFS:
+     return "lofs" ;
+#  endif
+#  ifdef MOUNT_FDESC
+   case MOUNT_FDESC:
+     return "fdesc" ;
+#  endif
+#  ifdef MOUNT_PORTAL
+   case MOUNT_PORTAL:
+     return "portal" ;
+#  endif
+#  ifdef MOUNT_NULL
+   case MOUNT_NULL:
+     return "null" ;
+#  endif
+#  ifdef MOUNT_UMAP
+   case MOUNT_UMAP:
+     return "umap" ;
+#  endif
+#  ifdef MOUNT_KERNFS
+   case MOUNT_KERNFS:
+     return "kernfs" ;
+#  endif
+#  ifdef MOUNT_PROCFS
+   case MOUNT_PROCFS:
+     return "procfs" ;
+#  endif
+#  ifdef MOUNT_AFS
+   case MOUNT_AFS:
+     return "afs" ;
+#  endif
+#  ifdef MOUNT_CD9660
+   case MOUNT_CD9660:
+     return "cd9660" ;
+#  endif
+#  ifdef MOUNT_UNION
+   case MOUNT_UNION:
+     return "union" ;
+#  endif
+#  ifdef MOUNT_DEVFS
+   case MOUNT_DEVFS:
+     return "devfs" ;
+#  endif
+#  ifdef MOUNT_EXT2FS
+   case MOUNT_EXT2FS:
+     return "ext2fs" ;
+#  endif
+    default:
+      return "?";
+    }
+}
+# endif /* ! HAVE_F_FSTYPENAME_IN_STATFS */
+
+/* __NetBSD__ || BSD_NET2 || __OpenBSD__ */
+static char *
+fsp_to_string (const struct statfs *fsp)
+{
+# if defined HAVE_F_FSTYPENAME_IN_STATFS
+  return (char *) (fsp->f_fstypename);
+# else
+  return fstype_to_string (fsp->f_type);
+# endif
+}
+
+#endif /* MOUNTED_GETMNTINFO */
+
+#ifdef MOUNTED_VMOUNT          /* AIX.  */
+static char *
+fstype_to_string (int t)
+{
+  struct vfs_ent *e;
+
+  e = getvfsbytype (t);
+  if (!e || !e->vfsent_name)
+    return "none";
+  else
+    return e->vfsent_name;
+}
+#endif /* MOUNTED_VMOUNT */
+
+/* Return a list of the currently mounted filesystems, 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.  */
+
+struct mount_entry *
+read_filesystem_list (int need_fs_type)
+{
+  struct mount_entry *mount_list;
+  struct mount_entry *me;
+  struct mount_entry **mtail = &mount_list;
+
+#ifdef MOUNTED_LISTMNTENT
+  {
+    struct tabmntent *mntlist, *p;
+    struct mntent *mnt;
+    struct mount_entry *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.
+       */
+
+    if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
+      return NULL;
+    for (p = mntlist; p; p = p->next) {
+      mnt = p->ment;
+      me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
+      me->me_devname = xstrdup(mnt->mnt_fsname);
+      me->me_mountdir = xstrdup(mnt->mnt_dir);
+      me->me_type = xstrdup(mnt->mnt_type);
+      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      /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
+  {
+    struct mntent *mnt;
+    char *table = MOUNTED;
+    FILE *fp;
+    char *devopt;
+
+    fp = setmntent (table, "r");
+    if (fp == NULL)
+      return NULL;
+
+    while ((mnt = getmntent (fp)))
+      {
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+       me->me_devname = xstrdup (mnt->mnt_fsname);
+       me->me_mountdir = xstrdup (mnt->mnt_dir);
+       me->me_type = xstrdup (mnt->mnt_type);
+       me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
+       me->me_remote = ME_REMOTE (me->me_devname, me->me_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 = (dev_t) -1;      /* Magic; means not known yet. */
+
+       /* Add to the linked list. */
+       *mtail = me;
+       mtail = &me->me_next;
+      }
+
+    if (endmntent (fp) == 0)
+      goto free_then_fail;
+  }
+#endif /* MOUNTED_GETMNTENT1. */
+
+#ifdef MOUNTED_GETMNTINFO      /* 4.4BSD.  */
+  {
+    struct statfs *fsp;
+    int entries;
+
+    entries = getmntinfo (&fsp, MNT_NOWAIT);
+    if (entries < 0)
+      return NULL;
+    for (; entries-- > 0; fsp++)
+      {
+       char *fs_type = fsp_to_string (fsp);
+
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+       me->me_devname = xstrdup (fsp->f_mntfromname);
+       me->me_mountdir = xstrdup (fsp->f_mntonname);
+       me->me_type = fs_type;
+       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_GETMNTINFO */
+
+#ifdef MOUNTED_GETMNT          /* Ultrix.  */
+  {
+    int offset = 0;
+    int val;
+    struct fs_data fsd;
+
+    while (errno = 0,
+          0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
+                             (char *) 0)))
+      {
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+       me->me_devname = xstrdup (fsd.fd_req.devname);
+       me->me_mountdir = xstrdup (fsd.fd_req.path);
+       me->me_type = gt_names[fsd.fd_req.fstype];
+       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;
+
+       /* Add to the linked list. */
+       *mtail = me;
+       mtail = &me->me_next;
+      }
+    if (val < 0)
+      goto free_then_fail;
+  }
+#endif /* MOUNTED_GETMNT. */
+
+#if defined (MOUNTED_FS_STAT_DEV) /* BeOS */
+  {
+    /* The next_dev() and fs_stat_dev() system calls give the list of
+       all filesystems, including the information returned by statvfs()
+       (fs type, total blocks, free blocks etc.), but without the mount
+       point. But on BeOS all filesystems 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 filesystems, 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 = xstrdup ("/");
+            else
+              {
+                name = xmalloc (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;
+
+                re = (struct rootdir_entry *) xmalloc (sizeof (struct rootdir_entry));
+                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 = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+          me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
+          me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
+          me->me_type = xstrdup (fi.fsh_name);
+          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 */
+
+#if defined (MOUNTED_GETFSSTAT)        /* __alpha running OSF_1 */
+  {
+    int numsys, counter, bufsize;
+    struct statfs *stats;
+
+    numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
+    if (numsys < 0)
+      return (NULL);
+
+    bufsize = (1 + numsys) * sizeof (struct statfs);
+    stats = (struct statfs *)xmalloc (bufsize);
+    numsys = getfsstat (stats, bufsize, MNT_WAIT);
+
+    if (numsys < 0)
+      {
+       free (stats);
+       return (NULL);
+      }
+
+    for (counter = 0; counter < numsys; counter++)
+      {
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+       me->me_devname = xstrdup (stats[counter].f_mntfromname);
+       me->me_mountdir = xstrdup (stats[counter].f_mntonname);
+       me->me_type = mnt_names[stats[counter].f_type];
+       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;
+      }
+
+    free (stats);
+  }
+#endif /* MOUNTED_GETFSSTAT */
+
+#if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23].  */
+  {
+    struct mnttab mnt;
+    char *table = "/etc/mnttab";
+    FILE *fp;
+
+    fp = fopen (table, "r");
+    if (fp == NULL)
+      return NULL;
+
+    while (fread (&mnt, sizeof mnt, 1, fp) > 0)
+      {
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+# ifdef GETFSTYP                       /* SVR3.  */
+       me->me_devname = xstrdup (mnt.mt_dev);
+# else
+       me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
+       strcpy (me->me_devname, "/dev/");
+       strcpy (me->me_devname + 5, mnt.mt_dev);
+# endif
+       me->me_mountdir = xstrdup (mnt.mt_filsys);
+       me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
+       me->me_type = "";
+# ifdef GETFSTYP                       /* SVR3.  */
+       if (need_fs_type)
+         {
+           struct statfs fsd;
+           char typebuf[FSTYPSZ];
+
+           if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
+               && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
+             me->me_type = xstrdup (typebuf);
+         }
+# endif
+       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;
+       mtail = &me->me_next;
+      }
+
+    if (ferror (fp))
+      {
+       int saved_errno = errno;
+       fclose (fp);
+       errno = saved_errno;
+       goto free_then_fail;
+      }
+
+    if (fclose (fp) == EOF)
+      goto free_then_fail;
+  }
+#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP.  */
+
+#ifdef MOUNTED_GETMNTTBL       /* DolphinOS goes it's own way */
+  {
+    struct mntent **mnttbl=getmnttbl(),**ent;
+    for (ent=mnttbl;*ent;ent++)
+      {
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+       me->me_devname = xstrdup ( (*ent)->mt_resource);
+       me->me_mountdir = xstrdup( (*ent)->mt_directory);
+       me->me_type =  xstrdup ((*ent)->mt_fstype);
+       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;
+      }
+    endmnttbl();
+  }
+#endif
+
+#ifdef MOUNTED_GETMNTENT2      /* SVR4.  */
+  {
+    struct mnttab mnt;
+    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)
+      ret = errno;
+    else
+      {
+       while ((ret = getmntent (fp, &mnt)) == 0)
+         {
+           me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+           me->me_devname = xstrdup (mnt.mnt_special);
+           me->me_mountdir = xstrdup (mnt.mnt_mountp);
+           me->me_type = xstrdup (mnt.mnt_fstype);
+           me->me_dummy = MNT_IGNORE (&mnt) != 0;
+           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;
+         }
+
+       ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
+      }
+
+    if (0 <= lockfd && close (lockfd) != 0)
+      ret = errno;
+
+    if (0 <= ret)
+      {
+       errno = ret;
+       goto free_then_fail;
+      }
+  }
+#endif /* MOUNTED_GETMNTENT2.  */
+
+#ifdef MOUNTED_VMOUNT          /* AIX.  */
+  {
+    int bufsize;
+    char *entries, *thisent;
+    struct vmount *vmp;
+
+    /* Ask how many bytes to allocate for the mounted filesystem info.  */
+    mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
+    entries = xmalloc (bufsize);
+
+    /* Get the list of mounted filesystems.  */
+    mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
+
+    for (thisent = entries; thisent < entries + bufsize;
+        thisent += vmp->vmt_length)
+      {
+       char *options, *ignore;
+
+       vmp = (struct vmount *) thisent;
+       me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
+       if (vmp->vmt_flags & MNT_REMOTE)
+         {
+           char *host, *path;
+
+           me->me_remote = 1;
+           /* Prepend the remote pathname.  */
+           host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
+           path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
+           me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
+           strcpy (me->me_devname, host);
+           strcat (me->me_devname, ":");
+           strcat (me->me_devname, path);
+         }
+       else
+         {
+           me->me_remote = 0;
+           me->me_devname = xstrdup (thisent +
+                                     vmp->vmt_data[VMT_OBJECT].vmt_off);
+         }
+       me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
+       me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
+       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;
+       mtail = &me->me_next;
+      }
+    free (entries);
+  }
+#endif /* MOUNTED_VMOUNT. */
+
+  *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);
+       /* FIXME: me_type is not always malloced.  */
+       free (mount_list);
+       mount_list = me;
+      }
+
+    errno = saved_errno;
+    return NULL;
+  }
+}
diff --git a/lib/mountlist.h b/lib/mountlist.h
new file mode 100644 (file)
index 0000000..c41490c
--- /dev/null
@@ -0,0 +1,50 @@
+/* mountlist.h -- declarations for list of mounted filesystems
+   Copyright (C) 1991, 1992, 1998, 2000 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* 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. */
+  unsigned int me_dummy : 1;   /* Nonzero for dummy filesystems. */
+  unsigned int me_remote : 1;  /* Nonzero for remote fileystems. */
+  struct mount_entry *me_next;
+};
+
+#ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+#endif
+
+struct mount_entry *read_filesystem_list PARAMS ((int need_fs_type));
+
+#ifndef ME_DUMMY
+# define ME_DUMMY(fs_name, fs_type) \
+    (!strcmp (fs_type, "auto") \
+     || !strcmp (fs_type, "autofs") \
+     /* for Irix 6.5 */ \
+     || !strcmp (fs_type, "ignore"))
+#endif
+
+#ifndef ME_REMOTE
+# define ME_REMOTE(fs_name, fs_type) (strchr (fs_name, ':') != 0)
+#endif