Article 12712 of alt.sources:
Newsgroups: alt.sources
Path: nntpd.lkg.dec.com!crl.dec.com!crl.dec.com!bloom-beacon.mit.edu!newsserver.pixel.kodak.com!clpd-newsserver!news.sprintlink.net!in1.uu.net!boo!seer!bll
From: bll@seer.gentoo.com (Brad Lanam)
Subject: Disk Information Utility (version 1.17)
Message-ID: <DD4ALs.16G@seer.gentoo.com>
Followup-To: alt.sources.d
Keywords: di; df; disk space
Organization: Brad Lanam  Walnut Creek, CA
Date: Thu, 10 Aug 1995 23:01:04 GMT
Expires: Sun, 10 Sep 1995 07:00:00 GMT
Lines: 3440


    'di' is a disk information utility, displaying everything (and more)
    that your 'df' command does.  It features the ability to display your
    disk usage in whatever format you desire/prefer/are used to.  It is
    designed to be portable across many platforms.  It was written at the
    request of a friend to get the same display format on every system he
    used, being tired of too many different 'df' formats.

    Version 1.17 features the ability to request local file systems
    display only (-l option).  This works for System V.4, Solaris,
    FreeBSD, and BSD/OS.  Maybe Ultrix.  Other systems need to be
    implemented, but I don't have access to them.

    A -d option has been added so that the blocks can be displayed
    using units other than kilobytes.  e.g. "-d m" will display the
    blocks in megabytes.  See the man page for details.

    I currently have access to and have tested this version on
    System V.4, Solaris 2.5, SCO and FreeBSD 2.x.

    Enjoy.
    -- Brad

Supersedes: di/part1
Supersedes: di/part01
Archive-name: di/Part01
Submitted-by: bll@gentoo.com

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  MANIFEST Makefile README TODO di.1 di.c
# Wrapped by root@seer on Thu Aug 10 15:59:02 1995
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(368 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Makefile                   1	di makefile
X README                     1	Read This
X TODO                       1	List of bugs/things to do
X di.1                       1	di Manual Page
X di.c                       1	di source
END_OF_FILE
if test 368 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(10981 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X#  di makefile
X#
X#  Copyright 1994 Brad Lanam
X#
X#  $Id: $
X#  @(#)Makefile	1.19
X#
X# select:
X#   one of
X#     HAS_MNTTAB       (SysV.4, Solaris)
X#     HAS_SVR3_MNTTAB  (SysV.3, Xenix, SCO, Coherent)
X#     HAS_MNTENT       (SunOS, Pyramid, sgi, NeXT, linux, A/UX)
X#     HAS_GETMNTINFO   (OSF1, FreeBSD, BSDI)
X#     HAS_GETMNT       (ULTRIX)
X#     HAS_MNTCTL       (AIX)
X#   one of
X#     HAS_STATVFS      (SysV.4, Solaris, sgi-irix-5)
X#     HAS_STATFS       (SunOS, Pyramid, NeXT, linux, AIX, A/UX)
X#     HAS_SYSV_STATFS  (SysV.3, sgi-irix-4, Xenix, SCO, Coherent)
X#     none needed      (ULTRIX, OSF1, FreeBSD, BSDI)
X#   other
X#     NEED_GETOPT_DEFS (SysV.3, SunOS, Pyramid, sgi-irix-4, ULTRIX, NeXT,
X#                       Xenix, A/UX)
X#                      Your system may or may not need this depending on
X#                      compiler options, your version of os, the phase of
X#                      the moon, etc.)
X#     NEED_ERRNO_DEFS  (Pyramid, NeXT)
X#     NEED_STATFS_DEFS (Linux, A/UX)
X#     HAS_SYSFS        (SysV.3, sgi)
X#     HAS_NO_STDLIB_H  (if doesn't have <stdlib.h>; Pyramid)
X#     HAS_STRINGS_H    (if using <strings.h> instead of <string.h>;
X#                       Pyramid, NeXT)
X#     HAS_NO_MALLOC_H  (if doesn't have <malloc.h>; Pyramid, NeXT, Xenix,
X#                       FreeBSD, BSDI)
X#     HAS_NO_MEMORY_H  (if doesn't have <memory.h>; Pyramid)
X#     HAS_BZERO        (bzero() rather than memset; Pyramid, NeXT)
X#     HAS_NO_UNISTD_H  (if doesn't have <unistd.h>; NeXT)
X#   If it uses HAS_GETMNTINFO:
X#     HAS_NO_FSTYPES_H (FreeBSD, bsdi)
X#     HAS_INITMOUNTNAMES (FreeBSD 2.x, bsdi 2.x)
X#     HAS_GETMNTINFO_FSIZE (bsdi 1.x, FreeBSD 1.x)
X#     HAS_GETMNTINFO_BSIZE (bsdi 2.x, FreeBSD 2.x)
X#
X#  HISTORY:
X#       2 aug 95 bll
X#           bsdi fixes; aux
X#       25 jul 95 bll
X#           changed sco_sl from njh.
X#       24 nov 94 bll
X#           added FreeBsd
X#       2 jun 94 bll
X#           added separate dynix; solaris w/gcc; fixed $(MAKE)
X#       1 may 94 bll
X#           added aix, coherent
X#       7 apr 94 bll
X#           Cleaned up sgi.
X#       4 mar 94 bll
X#           Added osf1, ultrix, solaris as a separate entry.
X#       3 mar 94 bll
X#           man page installation.
X#       1 mar 94 bll
X#           Added documentation.
X#       1 mar 94 bll
X#           Added defines for pyramid; rewrote make to select system;
X#           added sgi.  Rewrote install to be portable.
X#
X
XSHELL = /bin/sh
XCC = cc
X
X#
X# additional flags/libraries
X#
XCFLAGS =
XLDFLAGS =
XLIBS =
X
X#
X# installation options
X#
XSTRIP = strip
XMCS = mcs -d
XUSER = root
XGROUP = bin
XINSTDIR = /var/local/bin
XPROG = di
XTARGET = $(INSTDIR)/$(PROG)
X#INSTPERM = 111   # change USER to bin also...
XINSTPERM = 4111   # install suid if your system has a mount table only root
X#                   can read.  SysV.4, Solaris are two.
X
X#
X# simple man page installation
X#
XTOPMANDIR=/var/local/man
XCATDIR=cat1
XMANDIR=man1
XMANEXT=.1
XCOMPRESS=compress
XCOMPEXT=.Z
XNROFF=nroff -man
XMANTARGET=$(PROG)$(MANEXT)$(COMPEXT)
XMANPERM = 444
XMANUSER = bin
XMANGRP = bin
X
Xnothing:
X	@echo "Usage: make <system>"
X	@echo "  where system is one of:"
X	@echo "       aix         - AIX V3.2"
X	@echo "       aux         - A/UX"
X	@echo "       bsdi1       - BSD/OS 1.x"
X	@echo "       bsdi2       - BSD/OS 2.x"
X	@echo "       coherent    - Coherent 4.2"
X	@echo "       convex      - ConvexOS 10.1"
X	@echo "       dynix       - Sequent DYNIX 3.2"
X	@echo "       freebsd1    - FreeBSD 1.x"
X	@echo "       freebsd2    - FreeBSD 2.x"
X	@echo "       hpux        - HP/UX"
X	@echo "       linux       - Linux"
X	@echo "       next3       - NextStep 3.x"
X	@echo "       osf1        - OSF/1"
X	@echo "       ptx         - Sequent DYNIX/ptx v2.0+"
X	@echo "       pyr         - pyramid"
X	@echo "       sco         - SCO w/getopt"
X	@echo "       sco-2       - SCO w/o getopt (3.2.4 / ODT 3.0)"
X	@echo "       sco_sl      - SCO w/o getopt w/shared lib (3.2.4/ODT 3.0)"
X	@echo "       sgi4        - SGI Irix 4.x"
X	@echo "       sgi5        - SGI Irix 5.x"
X	@echo "       solaris     - Solaris 2.x"
X	@echo "       solaris-gcc - Solaris 2.x w/gcc C compiler"
X	@echo "       sun         - SunOS 4.x"
X	@echo "       sysv3       - System V R3"
X	@echo "       sysv3_nostd - System V R3 - no stdlib.h"
X	@echo "       sysv4       - System V R4"
X	@echo "       ultrix      - Ultrix"
X	@echo "       xenix       - Xenix"
X	@echo
X	@echo "       'make install' to install the program."
X	@echo "       'make installman' to install the man pages."
X	@echo "       or 'make installcatman' to install the man pages."
X	@echo
X
Xaix:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -DHAS_MNTCTL -DHAS_STATFS" all
X
X
X# BSD/OS 1.x
Xbsdi1:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_GETMNTINFO \
X		-DHAS_NO_MALLOC_H -DHAS_NO_FSTYPES_H -DHAS_GETMNTINFO_FSIZE" all
X
X
Xaux:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -DHAS_MNTENT -DHAS_STATFS \
X		-DNEED_GETOPT_DEFS -DNEED_STATFS_DEFS" all
X
X# BSD/OS 2.x
Xbsdi2:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_GETMNTINFO \
X		-DHAS_NO_MALLOC_H -DHAS_NO_FSTYPES_H -DHAS_GETMNTINFO_BSIZE \
X		-DHAS_INITMOUNTNAMES" all
X
X
X#
X# tested on Coherent 4.2.05
X#
X# Apparently coherent swaps the name and special device fields around
X# in their mount table.  Otherwise is SysV.3.
X#
Xcoherent:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -f -O -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DNEED_GETOPT_DEFS" all
X
X# ConvexOS 10.1
Xconvex:
X	$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_MNTENT=1 -DHAS_STATFS=1 \
X		-DHAS_NO_MALLOC_H=1 -DHAS_NO_MEMORY_H=1 -DHAS_STRINGS_H=1 \
X		-DNEED_GETOPT_DEFS=1" all
X
Xdynix:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_MNTENT -DHAS_STATFS \
X		-DHAS_NO_MALLOC_H -DNEED_GETOPT_DEFS" \
X		LIBS="-lseq" all
X
Xfreebsd1:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_GETMNTINFO \
X		-DHAS_NO_MALLOC_H -DHAS_NO_FSTYPES_H -DHAS_GETMNTINFO_FSIZE" all
X
Xfreebsd2:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_GETMNTINFO \
X		-DHAS_NO_MALLOC_H -DHAS_NO_FSTYPES_H  -DHAS_GETMNTINFO_BSIZE \
X		-DHAS_INITMOUNTNAMES" all
X
X#
X# CFLAGS="-Aa"
X#
X# > Pasi.Kaara@tpo.fi
X# On hp-ux 8.02 di needs " -DNEED_GETOPT_DEFS ".
X# On hp-ux 9.00 it is not needed, but it does not hurt either.
X#
Xhpux:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) +O3 -D_HPUX_SOURCE -DHAS_MNTENT \
X		-DHAS_STATFS -DNEED_GETOPT_DEFS" all
X
X#
X# CFLAGS="-m486"
X# also might need -DNEED_STATFS_DEFS
X#
X# Tested w/SLS 1.02
Xlinux:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O6 -N -s -DHAS_MNTENT \
X		-DHAS_STATFS" LDFLAGS="$(LDFLAGS) -N -s" all
X
X# Definition for NextStep 3.x
Xnext3:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_STATFS -DHAS_MNTENT \
X		-DNEED_GETOPT_DEFS -DHAS_NO_MALLOC_H\
X		-DHAS_STRINGS_H -DHAS_BZERO \
X		-DNEED_ERRNO_DEFS -DHAS_NO_UNISTD_H" all
X
Xosf1:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -DHAS_GETMNTINFO" all
X
X#
X# Use the following for Sequent DYNIX/ptx v2.0+
X#
Xptx:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_MNTENT \
X		-DHAS_SYSV_STATFS" LIBS="-lseq" all
X
Xpyr:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -Xa -DHAS_STATFS -DHAS_MNTENT \
X		-DNEED_GETOPT_DEFS -DHAS_NO_MALLOC_H -DHAS_NO_MEMORY_H \
X		-DHAS_NO_STDLIB_H -DHAS_STRINGS_H -DHAS_BZERO \
X		-DNEED_ERRNO_DEFS" all
X
X#
X# SCO UNIX and ODT
X#
X# may need -DNEED_GETOPT_DEFS
X#
Xsco:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DNEED_GETOPT_DEFS -DHAS_SYSFS" all
X
Xsco-2:		# use for UNIX 3.2.4 and ODT 3.0
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DHAS_SYSFS" all
X
X# Nigel Horne : njh@smsltd.demon.co.uk
X# 25 jul 1995
Xsco_sl:		# SCO UNIX/ODT with shared libs (small executable)
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DNEED_GETOPT_DEFS -DHAS_SYSFS" \
X		LDFLAGS="-s -nointl" LIBS="-lc_s -lmalloc -link -z" all
X
Xsgi4:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O2 -DHAS_MNTENT \
X		-DHAS_SYSV_STATFS -DHAS_SYSFS -DNEED_GETOPT_DEFS" \
X		LIBS="-lsun" all
X
Xsgi5:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O2 -DHAS_MNTENT -DHAS_STATVFS \
X		-DHAS_SYSFS" LIBS="-lsun" all
X
Xsolaris:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -Xc -v -DHAS_STATVFS \
X		-DHAS_MNTTAB -DNEED_GETOPT_DEFS" all
X
Xsolaris-gcc:
X	@$(MAKE) CC="gcc" CFLAGS="$(CFLAGS) -O -v -DHAS_STATVFS \
X		-DHAS_MNTTAB" all
X
X#
X# gcc compilation for sun4...
X#gcc -g -Wall -O -DHAS_STATFS -DHAS_MNTENT -DNEED_GETOPT_DEFS \
X#    -target sun4 -c  di.c
X#
Xsun:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O2 -DHAS_STATFS -DHAS_MNTENT \
X		-DNEED_GETOPT_DEFS" all
X
Xsysv3:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DHAS_SYSFS -DNEED_GETOPT_DEFS" all
X
Xsysv3_nostd:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DHAS_SYSFS -DNEED_GETOPT_DEFS \
X		-DHAS_NO_STDLIB_H" all
X
Xsysv4:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -O -Xc -v -DHAS_STATVFS \
X		-DHAS_MNTTAB" LDFLAGS="$(LDFLAGS) -s" all
X
Xsysv4-2:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -Xc -v -DHAS_SYSV_STATFS \
X		-DHAS_MNTTAB -DHAS_SYSFS" LDFLAGS="$(LDFLAGS) -s -Xc" all
X
Xsysv4-3:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -Xc -v -I/usr/ucbinclude \
X		-DHAS_STATVFS -DHAS_MNTTAB -DHAS_STRINGS_H -DHAS_BZERO \
X		-DNEED_BZERO_DEFS -DHAS_NO_MEMORY_H -DNEED_BCOPY_DEFS" \
X		LDFLAGS="$(LDFLAGS) -Xc" LIBS="/usr/ucblib/libucb.a" all
X
Xultrix:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -DHAS_GETMNT -DNEED_GETOPT_DEFS" all
X
Xxenix:
X	@$(MAKE) CC=$(CC) CFLAGS="$(CFLAGS) -DHAS_SYSV_STATFS \
X		-DHAS_SVR3_MNTTAB -DHAS_NO_MALLOC_H -DNEED_GETOPT_DEFS" all
X
X####################
X
XLINTOUT = lint.out
X
Xlint:
X	@-rm -f $(LINTOUT)
X	@-touch $(LINTOUT)
X	@echo "::::::::::::::" >> $(LINTOUT)
X	@echo "sysv4" >> $(LINTOUT)
X	@echo "::::::::::::::" >> $(LINTOUT)
X	-lint -p -DHAS_STATVFS -DHAS_MNTTAB di.c >> $(LINTOUT)
X
Xall:	di
X
Xclean:
X	-rm -f di di.o
X
Xrealclean:
X	-rm -f di di.o di-3 di-4 di-4a out-* \
X		lint.out di.shar Makelog MANIFEST MANIFEST.* >/dev/null 2>&1
X
Xinstall:
X	$(STRIP) di
X	$(MCS) di
X	test -f $(TARGET) && mv $(TARGET) $(TARGET).old
X	cp di $(TARGET)
X	chown $(USER) $(TARGET)
X	chgrp $(GROUP) $(TARGET)
X	chmod $(INSTPERM) $(TARGET)
X
Xinstallman:
X	cat di.1 | $(COMPRESS) > $(TOPMANDIR)/$(MANDIR)/$(MANTARGET)
X	chown $(MANUSER) $(TOPMANDIR)/$(MANDIR)/$(MANTARGET)
X	chgrp $(MANGRP) $(TOPMANDIR)/$(MANDIR)/$(MANTARGET)
X	chmod $(MANPERM) $(TOPMANDIR)/$(MANDIR)/$(MANTARGET)
X
Xinstallcatman:
X	$(NROFF) di.1 | $(COMPRESS) > $(TOPMANDIR)/$(CATDIR)/$(MANTARGET)
X	chown $(MANUSER) $(TOPMANDIR)/$(CATDIR)/$(MANTARGET)
X	chgrp $(MANGRP) $(TOPMANDIR)/$(CATDIR)/$(MANTARGET)
X	chmod $(MANPERM) $(TOPMANDIR)/$(CATDIR)/$(MANTARGET)
X
Xdi:	di.o
X	$(CC) $(CFLAGS) $(LDFLAGS) -o di di.o $(LIBS)
X
Xdi.o:	di.c
X	$(CC) -c $(CFLAGS) di.c
X
Xsccsget:
X	get -e SCCS
X
Xshar:	di.shar
X
XMANIFEST:
X	echo "" > MANIFEST
X	echo "" >> MANIFEST
X	echo "TODO		1	List of bugs/things to do" >> MANIFEST
X	echo "README		1	Read This" >> MANIFEST
X	echo "di.1		1	di Manual Page" >> MANIFEST
X	echo "di.c		1	di source" >> MANIFEST
X	echo "Makefile		1	di makefile" >> MANIFEST
X
Xdi.shar:	MANIFEST TODO README di.1 di.c Makefile
X	-rm -f di.shar Part??
X	chmod +w Makefile
X	makekit -m -s100k
X	chmod -w Makefile
X	-@rm -f MANIFEST.BAK
X	sh setname.sh
X	touch di.shar
END_OF_FILE
if test 10981 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(8103 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Xdi - disk information utility (ver 1.17).
X
XManifest:
X    TODO       - list of known bugs/problems/things to do.
X    README     - this file.
X    Makefile   - make file to build/install di.
X    di.1       - manual page, troff format.
X    di.c       - source.
X
XThe makefile currently supports the following systems:
X
X    AIX, Sequent Dynix and PT/x, FreeBSD 1.x and 2.x, HP/UX, Linux,
X    Next 3.x, OSF/1, Pyramid, SCO 3.2.2 & 3.2.4, SGI Irix 4 & 5,
X    SunOS, Solaris, Sys V.3, Sys V.4, Ultrix, Xenix, BSDI 1.x and 2.x,
X    A/UX, Convex
X
XType: make <system> to make 'di' for that system.
XType: make          to see a list of available systems.
X
XDepending on the compiler options, and what version of os you have,
Xwhat compiler you use, etc., etc. the -DNEED_GETOPT_DEFS=1 may need
Xto be added to the CFLAGS macro in the makefile.
X
XEdit the makefile to set the installation directories/permissions.
X
X    Type: make install to install di.
X
X    Type: make installman to install the man pages.
X
X    Type: make installcatman to install the man pages.
X
XFor other systems, edit the makefile to select the proper defines
Xto create 'di' for your system.
X
X    You must select the type of mount table for your system:
X        HAS_MNTTAB      - System V.4 format; Solaris;  Stored in /etc/mnttab.
X                          Uses the getmnttab() system call.
X        HAS_SVR3_MNTTAB - System V.3 format.  Stored in /etc/mnttab.
X        HAS_MNTENT      - BSD/SunOS format.
X                          Uses the setmntent(), getmntent(), etc. calls.
X        HAS_GETMNT      - Ultrix
X        HAS_GETMNTINFO  - OSF/1, FreeBSD, BSD/OS
X                          Uses the getmntinfo() system call.
X
X    You must select the type of disk statistics system call:
X        HAS_STATVFS     - Uses statvfs (). (Sys V.4, Solaris 2.x).
X        HAS_STATFS      - Uses statfs (char *, struct statfs *).
X                          (Most BSD variants).
X        HAS_SYSV_STATFS - Uses statfs (char *, struct statfs *, size_t, int).
X                          (Sys V.3).
X        none            - Ultrix, OSF/1, FreeBSD, BSDI
X
X    Other defines that your system may need:
X        NEED_GETOPT_DEFS     - getopt() et. al. is not declared in <unistd.h>.
X        NEED_ERRNO_DEFS      - extern int errno is not declared in <errno.h>.
X        NEED_STATFS_DEFS     - statfs() not declared in <vfs.h>.
X        HAS_SYSFS            - has the sysfs() system call to get the disk type.
X                               Mostly Sys V.3 variants.
X        HAS_NO_STDLIB_H      - <stdlib.h> does not exist.
X        HAS_STRINGS_H        - <strings.h> rather than <string.h>
X        HAS_NO_MALLOC_H      - <malloc.h> does not exist.
X        HAS_NO_MEMORY_H      - <memory.h> does not exist.  Use bcopy.
X        HAS_NO_UNISTD_H      - <unistd.h> does not exist.
X        HAS_BZERO            - No memset() call; uses bzero().
X    For those systems using the getmntinfo() system call:
X        HAS_NO_FSTYPES_H     - FreeBSD, BSD/OS
X        HAS_INITMOUNTNAMES   - FreeBSD 2.x, BSD/OS 2.x
X        HAS_GETMNTINFO_FSIZE - BSD/OS 1.x, FreeBSD 1.x
X        HAS_GETMNTINFO_BSIZE - BSD/OS 2.x, FreeBSD 2.x
X
XEdit the makefile to set the installation options for your system.
XType: make install to install 'di'.  Be sure to change the INSTPERM
Xdefine if your system's /etc/mnt* is readable only by root.
X
XIf you have _large_ partitions, you may want to change the width
Xfor the printed block values in di.c, and the default format string.
X
X===
X
XSend bug reports along with the output from 'di -A -x 2' and the
Xoutput from your standard df command (as verbose as possible) to:
X
X    bll@gentoo.com
X
XNote that depending on the compiler and the OS and the compiler
Xflags, some of the macros may or may not need to be defined.
X
XMany OS's have support for many different routines, and may
Xwork with different definitions.
X
XIf you have a new system that isn't in the makefile, go ahead
Xand e-mail it to me.
X
XIf your system is in the makefile, and there are just minor
Xdifferences, don't send them to me unless the differences are
Ximportant or due to a version change in the OS (I can't keep track
Xof all the compiler options/systems that may or may not need to
Xhave getopt() defined).  E-mail me the appropriate makefile entries
Xfor the versions you know about.
X
XIf your system should be using a more modern routine (e.g. statvfs()
Xover sysV.3 statfs()), e-mail me the changes.
X
X-- Brad
Xbll@gentoo.com
X
X===
X
XAnd for their comments and/or source and/or
Xmanual pages and/or bug fixes, thanks!
X
X        jjb@jagware.bcc.com (J.J.Bailey)
X        vogelke@c-17igp.wpafb.af.mil (Contr Karl Vogel)
X            [pyramid]
X        costales@ICSI.Berkeley.EDU (Bryan Costales)
X        Mark Neale <mark@edscom.demon.co.uk>
X        Pat Myrto <pat@rwing.uucp>
X            [sunOS filesystem type stuff]
X        henrikar@utctu1.ct.utwente.nl (Henri Karrenbeld)
X            [sgi]
X        Peter Bray <Peter.Bray@serg.cse.unsw.edu.au>
X        gsipe@pyramid.com (George M. Sipe)
X            [manual page]
X        Jeffrey Mogul <mogul@pa.dec.com>
X            [ultrix, osf/1, manual page, new format options]
X        thomas@idx.kodak.com (Th. Bullinger)
X            [help usage]
X        Seth Theriault <sltheria@artsci.wustl.edu>
X            [next]
X        steve@nshore.org (Stephen J. Walick)
X            [SCO]
X        Gerald Rinske <gerald@D012F291.mch.sni.de>
X            [sgi]
X        Mike Grupenhoff <kashmir@snare.dorm.umd.edu>
X            [linux]
X        R.K.Lloyd@csc.liv.ac.uk
X            [hpux]
X        "William Gibbs" <bill@wgc386.MV.COM>
X            [xenix]
X        Randy Thompson <randyt@sequent.com>
X            [sequent]
X        eriko@risc.austin.ibm.com (O'Shaughnessy Erik)
X            [aix]
X        Bill Davidsen <davidsen@tmr.com>
X            [linux, SCO, etc., new format options]
X        fredex@fcshome.stoneham.ma.us (fred smith)
X            [coherent 4.2.05]
X        bag@clipper.cs.kiev.ua (Andrey Blochintsev)
X            [bsdi]
X
X        et. al.
X
XCHANGES
X    1.17
X        Changed block values from unsigned long to doubles so that we
X        can display using different block sizes (-d flag).
X        Added -l flag for local filesystems only.
X    1.16
X        Added A/UX  [ blemoine@atheist.tamu.edu (Brett G. Lemoine) ]
X        Added convex [ "Schilperoort J.W." <J.W.Schilperoort@research.ptt.nl> ]
X    1.15
X	Fixed bsdi 1.x and bsdi 2.x.  Fragments weren't supported.
X	Fixed FreeBSD 1.x and 2.x; same problem.
X        Changed sco_sl makefile entry.
X    1.14
X        Fixed problem with display widths in conjunction with
X        ignore/include lists.
X    1.13
X        changed default length of filesystem type field to 7.
X        new debug 'all' format.
X        check for 0 fragment size; replace w/block size if we have it.
X    1.12
X        sco nfs 'nothing' fix.
X        freebsd 2.x; better freebsd filesystem types.
X    1.11
X        bsdi
X    1.10
X        added freebsd.
X    1.9
X        makefile fixes.
X    1.8
X        removed mount option junk.
X        added AIX.
X    1.7
X        cleaned up sgi in the makefile.
X        changed linux to be w/o need_statfs_defs.
X        solaris cdrom returning all sorts of negative values.
X        T format option.
X        mount options.
X        sunOs filesystem type info.
X    1.6
X        ultrix bug fixes.
X        add dynix to makefile.
X    1.5
X        sun had f_bfree instead of f_bavail!
X        xenix, linux, sco
X        -w, -W, -B.
X        fixed width for -f M, -f S.
X        usage.
X        Allow other characters in format string.
X        1.51 (local, pat@rwing)
X            SunOS *does* support filesystem type info.  Its all in the
X            mntent structure, but requires a small bit of work (see source).
X    1.4
X        -f B
X        bcopy.
X        solaris cdrom reports -2 for free blocks.
X    1.3
X        Command line specification of filenames.
X        sort output.
X        osf/1, ultrix.
X        -F, -f M, -F S.
X    1.2
X        # of inodes can be -1L
X        return code for getDiskInfo shouldn't be checked.
X        name of mount point must be maxpathlen.
X        error conditions.
X        pyramid.
X    1.1
X        initial release
X
END_OF_FILE
if test 8103 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'TODO' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'TODO'\"
else
echo shar: Extracting \"'TODO'\" \(666 characters\)
sed "s/^X//" >'TODO' <<'END_OF_FILE'
X
X    -   What needs testing: [ 9 aug 95 ].
X            Ultrix  everything, local filesystems.
X            BSD/OS  local filesystems
X
X    -   OSF/1 may support filesystems with fragments, in which case
X        we need to know how to get the fragment size. [ 9 aug 95 ].
X
X        Is OSF/1 the same as BSD/OS 1.x?
X        Is there an OSF/2 and is it the same as BSD/OS 2.x?
X
X    -   Local filesystems [ 9 aug 95 ].
X
X        How do we determine local file systems under Sys V.3 and Xenix?
X
X        How do we determine local file systems under SunOS?
X
X        How do we determine local file systems under AIX?
X
X        How do we determine local file systems under OSF/1?
END_OF_FILE
if test 666 -ne `wc -c <'TODO'`; then
    echo shar: \"'TODO'\" unpacked with wrong size!
fi
# end of 'TODO'
fi
if test -f 'di.1' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'di.1'\"
else
echo shar: Extracting \"'di.1'\" \(6834 characters\)
sed "s/^X//" >'di.1' <<'END_OF_FILE'
X.\"
X.\" @(#)di.1	1.11
X.\"
X.\" di.1
X.\"
X.\" Copyright 1994, 1995 Brad Lanam  Walnut Creek CA USA
X.\"
X.\" bll@gentoo.com
X.\"
X.\"
X.TH di 1 "9 August 1995"
X.SH Name
Xdi \- disk information
X.SH Synopsis
X.\" di [-Aahlnt] [-d display-size] [-f format] [-i ignore-fstyp-list]
X.\" [-I include-fstyp-list] [-s sort-type] [-w block-width]
X.\" [-W inode-width] [-x level] [file [...]]
X.B di
X[\fB-Aahlnt\fR] [\fB-d\fR \fIdisplay-size\fR] [\fB-f\fR \fIformat\fR]
X[\fB-i\fR \fIignore-fstyp-list\fR] [\fB-I\fR \fIinclude-fstyp-list\fR]
X[\fB-s\fR \fIsort-type\fR]
X[\fB-w\fR \fIblock-width\fR] [\fB-W\fR \fIinode-width\fR] [\fB-x\fR \fIlevel\fR]
X[\fIfile\fR [...]]
X.SH Description
X.NXA "di command" "dumpfs command"
X.NXA "di command" "df command"
X.NXR "disk" "displaying free space"
X.I di
XDisplays usage information on mounted filesystems.  Block values are
Xreported in kilobytes (1024 bytes) by default, but may be changed.
XIf \fIfile\fR is specified,
Xthe usage information for the partition on which \fIfile\fR is
Xlocated is printed.  Several switches may be specified to
Xcontrol the output of
X.I di\fR:
X.TP
X.B \-A
XPrint all fields (used for debugging).  Mount points and special
Xdevice names are printed at full width.  The \-a flag is set.
X.TP
X.B \-a
XPrints all mounted devices (normally, those with 0 total blocks are not
Xprinted - e.g. \fB/dev/proc\fR, \fB/dev/fd\fR).
X.TP
X.B \-d\ \fIdisplay-size\fR
XDisplay the blocks in units specified by \fIdisplay-size\fR.  \fIdisplay-size\fR
Xmay be one of: p \- posix (512 bytes), k \- kilobytes,
Xm \- megabytes, g - gigabytes, or a specific value to use as the block size.
XBlock display sizes greater than 1024 bytes are displayed with a %8.1f
Xdisplay format.
X.TP
X.B \-f\ \fIformat\fR
XUse the specified format string \fIformat\fR.  Format strings are
Xdescribed below.
X.TP
X.B \-h
XPrint out the usage for
X.I di
X.TP
X.B \-i \fIignore-fstype-list\fR
XIgnore the file system types listed in \fIignore-fstyp-list\fR.
XThe list is a comma separated list of file system types.  e.g.
X\-i nfs,rfs
X.TP
X.B \-I \fIinclude-fstype-list\fR
XInclude only the file system types listed in \fIinclude-fstyp-list\fR.
XThe list is a comma separated list of file system types.  e.g.
X\-I nfs,rfs
X.TP
X.B \-l
XDisplay only local file systems.  This option is not fully implemented
Xfor all systems as of version 1.17.
X.TP
X.B \-n
XDo not print a header line above the list of file systems.  Useful when
Xparsing the output of \fIdi\fR.
X.TP
X.B \-s\ \fIsort-type\fR
XUse \fIsort-type\fR to sort the output.
XThe output of \fIdi\fR is normally sorted by name.  The output may
Xbe left unsorted (\fB-s\ n\fR command line switch) i.e. as it appears
Xin the mount table or may be
Xsorted by the special device name
X(\fB-s\ s\fR command line switch).  If the \fB-s \ r\fR command line
Xswitch is used, the sort order will be reversed.
XIf \fIfile\fR is specifed on the
Xcommand line, no sorting is done.
X.TP
X.B \-t
XPrint a totals line below the list of file systems.
X.TP
X.B \-w\ \fIblock-width\fR
XSet the print width for block values.  Default is eight.
X.TP
X.B \-W\ \fIinode-width\fR
XSet the print width for inode values.  Default is seven.
X.TP
X.B \-x\ \fIlevel\fR
XSet the program's debugging level to \fIdebug-level\fR.
X.SH Format strings
XThe output of \fIdi\fR may be specified via a format string.  This
Xstring may be given either via the \fB-f\fR command line switch or by
Xthe \fBDIFMT\fR environment variable.  The format string may specify the
Xfollowing columns:
X.TP
X.B m
XPrint the name of the mount point.
X.TP
X.B M
XPrint the name of the mount point, at full length.  The mount point
Xis formatted to the maximum width necessary for the longest mount
Xpoint name.
X.TP
X.B b
XPrint the total number of Kbytes on the file system.
X.TP
X.B B
XPrint the total number of Kbytes on the file system
Xavailable for use by normal
Xusers.
X.TP
X.B u
XPrint the number of Kbytes in use on the file system
X(actual number of kbytes used = total - free).
XSee the \-d option also.
X.TP
X.B c
XPrint the number of Kbytes not available for use by normal users
X(total - available).
XSee the \-d option also.
X.TP
X.B f
XPrint the number of free (unused) Kbytes on the file system.
XSee the \-d option also.
X.TP
X.B v
XPrint the number of Kbytes available for use by normal users.
XSee the \-d option also.
X.TP
X.B p
XPrint the percentage of Kbytes not available for use by normal users
X(number of
Xkbytes not available for use / total disk space).
XSee the \-d option also.
X.TP
X.B 1
XPrint the percentage of total Kbytes in use
X(actual number of
Xkbytes used / total disk space).
XSee the \-d option also.
X.TP
X.B 2
XPrint the percentage of Kbytes in use, BSD-style.  Represents the
Xpercentage of user-available space in use.  Note that values over 100%
Xare possible
X(actual number of kbytes used / disk
Xspace available to non-root users).
XSee the \-d option also.
X.TP
X.B i
XPrint the total number of file slots (inodes) that can be created on the file
Xsystem.
X.TP
X.B U
XPrint the number of file slots in use.
X.TP
X.B F
XPrint the number of file slots available.
X.TP
X.B P
XPrint the percentage of file slots in use.
X.TP
X.B s
XPrint the file system name (special device or remote mount point).
X.TP
X.B S
XPrint the file system name (special device or remote mount point),
Xat full length.
XThe file system name
Xis formatted to the maximum width necessary for the longest file system
Xname.
X.TP
X.B t
XPrint the file system type.
X.TP
X.B T
XPrint the file system type at full length.  The file system type
Xis formatted to the maximum width necessary for the longest file system
Xtype.
X.PP
XThe default format string is \fBmbuvpiUFP\fR.
X.PP
XThe format string may also contain any other character not listed
Xabove.  The character will be printed as is.  e.g. \fBdi -f 'mbuvp|iUFP'\fR
Xwill print the character '|' between the disk usage and the file slot
Xusage.  The command sequence (Bourne Shell):
X.RS
X.br
X.B di -f 'mbuvp
X.br
X.B miUFP'
X.br
X.RE
Xwill print two lines of data.
X.SH Examples
XVarious \fIdf\fR
Xequivalent format strings for System V release 4 are:
X.PP
X.RS
X\fI/usr/bin/df -v\fR     \fBmsbuf1\fR (with 512 byte blocks)
X.br
X\fI/usr/bin/df -k\fR     \fBsbcvpm\fR
X.br
X\fI/usr/ucb/df\fR        \fBsbuv2m\fR
X.RE
X.PP
XIf you like your numbers to add up/calculate the percentage
Xcorrectly, try one
Xof the following format strings:
X.PP
X.RS
X.B di -f SMbuf1T
X.br
X.B di -f SMbcvpT
X.br
X.B di -f SMBuv2T
X.RE
X.SH Note
XFor filesystems that do not report available blocks (e.g. System V
Xrelease 3), the number of available blocks is considered to be the
Xnumber of free blocks.
X.SH WARNING
XDo not replace your system's \fIdf\fR command with this program.  You
Xwill in all likelihood break your installation procedures.
X.SH See Also
Xdf(1), fstab(5), getmnt(2), getmntinfo(2), mnttab(4), mount(1M)
Xstatfs(2), statvfs(2)
X.SH Author
XThis program is Copyright 1994, 1995 by Brad Lanam.
X.PP
XBrad Lanam, Walnut Creek, CA (bll@gentoo.com).
END_OF_FILE
if test 6834 -ne `wc -c <'di.1'`; then
    echo shar: \"'di.1'\" unpacked with wrong size!
fi
# end of 'di.1'
fi
if test -f 'di.c' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'di.c'\"
else
echo shar: Extracting \"'di.c'\" \(66204 characters\)
sed "s/^X//" >'di.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char    di_c_sccsid [] =
X"@(#)di.c	1.17";
Xstatic char    di_c_rcsid [] =
X"$Id: $";
Xstatic char    di_c_source [] =
X"$Source: $";
X#endif
X
X/*
X * di.c
X *
X *   Copyright 1994, 1995 Brad Lanam,  Walnut Creek, CA
X *
X *  Warning: Do not replace your systems 'df' command with this program.
X *           You will in all likelihood break your installation procedures.
X *
X *  Usage: di -AafntwWx [file [...]]
X *            -A   : print all fields (used for debugging)
X *            -a   : print all mounted devices; normally, those
X *                   with 0 total blocks are not printed.  e.g.
X *                   /dev/proc, /dev/fd.
X *            -d x : size to print blocks in (p, k, m, g, <n>)
X *            -f x : use format string <x>
X *            -i x : ignore filesystem type(s) x, where x is a comma
X *                   separated list.
X *            -I x : include only filesystem type(s) x, where x is a
X *                   separated list.
X *            -l   : local filesystems only
X *            -n   : don't print header
X *            -s t : sort type
X *            -t   : print totals
X *            -w n : use <n> for the block print width (default 8).
X *            -W n : use <n> for the inode print width (default 7).
X *            -x n : debug level <n>
X *
X *  All values are reported in K (1024 bytes).
X *
X *  Sort types (by name is default):
X *      n - none (mount order)
X *      s - special
X *      r - reverse sort
X *
X *  Format string values:
X *      m - mount point
X *      M - mount point, full length
X *      b - total kbytes
X *      B - total kbytes available for use by the user.
X *             [ (tot - (free - avail) ]
X *      u - kbytes used (actual number of kbytes used) [ (tot - free) ]
X *      c - calculated number of kbytes used [ (tot - avail) ]
X *      f - kbytes free
X *      v - kbytes available
X *      p - percentage not available for use.
X *          (number of blocks not available for use / total disk space)
X *             [ (tot - avail) / tot ]
X *      1 - percentage used.
X *          (actual number of blocks used / total disk space)
X *             [ (tot - free) / tot ]
X *      2 - percentage of user-available space in use (bsd style).
X *          Note that values over 100% are possible.
X *          (actual number of blocks used / disk space available to user)
X *             [ (tot - free) / (tot - (free - avail)) ]
X *      i - total i-nodes (files)
X *      U - used i-nodes
X *      F - free i-nodes
X *      P - percent i-nodes used     [ (tot - avail) / tot ]
X *      s - filesystem name (special)
X *      S - filesystem name (special), full length
X *      t - disk partition type
X *      T - disk partition type (full length)
X *
X *  System V.4 `/usr/bin/df -v`   Has format: msbuf1 (w/512 byte blocks)
X *  System V.4 `/usr/bin/df -k`   Has format: sbcvpm
X *  System V.4 `/usr/ucb/df`      Has format: sbuv2m
X *
X *  The default format string for this program is: mbuvpiUFP
X *
X *  The environment variable "DIFMT" may be set to the desired format
X *  string.
X *
X *  Note that for filesystems that do not have (S512K fs) or systems (SysV.3)
X *  that do not report available blocks, the number of available blocks is
X *  equal to the number of free blocks.
X *
X *  HISTORY:
X *     9 aug 95 bll
X *          Changed totals to use double; the totals can now be displayed with
X *          any wanted block size; sizes > one k have a single decimal point.
X *          -d option specifies block size.
X *          -l option for local file systems only.
X *     7 aug 95 bll
X *          convex fix.
X *     29 jul 95 bll
X *          Fixed bsdi variants.  The fragment size wasn't being supported.
X *     22 jul 95 bll
X *          fix problem with display widths in conjunction with ignore/include
X *     20 feb 95 bll
X *          added ignore/include file system type lists.
X *     8 jan 95 bll
X *          Added FreeBsd 2.x
X *     6 dec 94 bll
X *          sco nfs 'nothing' fix.
X *     28 nov 94 bll
X *          bsdi [bag@clipper.cs.kiev.ua (Andrey Blochintsev)]
X *     24 nov 94 bll
X *          Added FreeBsd - like OSF/1, but w/o nice mount name table.
X *     1 may 94 bll
X *          removed ill conceived mount options stuff.  Added AIX
X *          (Erik O'Shaughnessy eriko@risc.austin.ibm.com).
X *          Added coherent.
X *     9 apr 94 bll
X *          T format from Bill Davidsen. SunOS file system type.
X *          mount options.
X *     7 apr 94 bll
X *          cdrom under solaris returning -1 in addition to -2.
X *          Changed the test to test for any negative value.
X *    5 apr 94 pm
X *         Filesystem type info, and whether its read-write, readonly
X *         etc is in the mntent structure.  Added code to support it.
X *                  [Pat Myrto <pat@rwing.uucp>]
X *    25 mar 94 bll
X *          sun had f_bfree instead of f_bavail!
X *          Xenix, linux.
X *          -w, -W options, -B option, fixed width for -f M, -f S.
X *          Usage.  Allow other characters in format string.
X *     4 mar 94 bll
X *          -f B, bug fixes. bcopy.
X *          Solaris cdrom reports total, not free or avail.
X *          Allow command line specification of file names.
X *     3 mar 94 bll
X *          support for OSF/1 and ULTRIX, -F, -f M, -f S
X *                  [mogul@wrl.dec.com (Jeffrey Mogul)]
X *     3 mar 94   bll
X *          Allow command line specification of filename (s).
X *          Sort output.  Test of nonexistent return code removed.
X *     1 mar 94   bll
X *          # of inodes can be -1L if unreportable.
X *                  [jjb@jagware.bcc.com (J.J.Bailey)]
X *                  [Mark Neale <mark@edscom.demon.co.uk>]
X *          getDiskInfo () returning garbage
X *                  [costales@ICSI.Berkeley.EDU (Bryan Costales)]
X *                  [Mark Neale <mark@edscom.demon.co.uk>]
X *          pyramid #ifdefs
X *                  [vogelke@c-17igp.wpafb.af.mil (Contr Karl Vogel)]
X *          name must be maxpathlen
X *                  [Mark Neale <mark@edscom.demon.co.uk>]
X *          error prints/compile warnings.
X *                  [Mark Neale <mark@edscom.demon.co.uk>]
X *
X */
X
X#if defined (__STDC__) || defined (M_XENIX)
X# define PROTO(x)         x
X#endif
X
X#if ! defined (PROTO)
X# define PROTO(x)         ()
X#endif
X
X#include <stdio.h>
X#if ! defined (HAS_NO_STDLIB_H)
X# include <stdlib.h>
X#else
Xextern char *getenv PROTO ((char *));
X#endif
X#include <errno.h>
X#if ! defined (HAS_NO_MALLOC_H)
X# include <malloc.h>
X#endif
X#if ! defined (HAS_NO_MEMORY_H)
X# include <memory.h>
X#else
X# define memcpy(dst, src, cnt)     (bcopy((src), (dst), (cnt)), dst)
X# if defined (NEED_BCOPY_DEFS)
Xextern int bcopy (char *, char *, int);
X# endif
X#endif
X#if defined (HAS_STRINGS_H)
X# include <strings.h>
X#else
X# include <string.h>
X#endif
X#if ! defined (HAS_NO_UNISTD_H)
X# include <unistd.h>
X#endif
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X
X#if defined (_POSIX_SOURCE)
X# if !defined (__convex__)
Xtypedef ulong_t u_long;
X# endif
X#endif
X
X#if defined (HAS_MNTTAB)
X# include <sys/mnttab.h>
X#endif
X#if defined (HAS_SVR3_MNTTAB)
X# include <mnttab.h>
X# if ! defined (M_XENIX)
X#  include <limits.h>
X#  ifdef PATH_MAX
X#   define MAXPATHLEN        PATH_MAX
X#  endif
X#  ifdef _POSIX_PATH_MAX
X#   define MAXPATHLEN        _POSIX_PATH_MAX
X#  endif
X# else
X#  define MAXPATHLEN         LPNMAX
X# endif
X#endif
X
X#if defined (HAS_MNTENT)
X# include <mntent.h>
X#endif
X
X#if defined (HAS_GETMNTINFO)
X# include <sys/mount.h>
X# if ! defined (HAS_NO_FSTYPES_H)
X#  include <sys/fs_types.h>
X# endif
X#endif
X#if defined (HAS_GETMNT)
X# include <limits.h>
X# include <sys/mount.h>
X# include <sys/fs_types.h>
X#endif
X#if defined (HAS_MNTCTL)          /* AIX v3.2 */
X# include <sys/mntctl.h>
X# include <sys/vmount.h>
X# include <sys/statfs.h>
X# include <fshelp.h>
X# define FSMAGIC 5      /* base AIX configuration has 5 file systems */
X  typedef struct vmount *vmt_p;  /* short hand to prevent dreaded line wrap */
X#endif /* HAS_MNTCTL */
X
X#if defined (HAS_STATVFS)
X# include <sys/statvfs.h>
X#endif
X#if defined (HAS_SYSFS)
X# include <sys/fstyp.h>
X# define TYPE_LEN          FSTYPSZ
X#endif
X#if defined (HAS_STATFS)
X# include <sys/vfs.h>
X# if defined (NEED_STATFS_DEFS)
Xextern int statfs PROTO ((char *, struct statfs *));
X# endif
X#endif
X#if defined (HAS_SYSV_STATFS)
X# include <sys/statfs.h>
X#endif
X
X#if defined (HAS_VFSTAB)
X# include <sys/vfstab.h>
X# if ! defined (TYPE_LEN)
X#  define TYPE_LEN         FSTYPSZ
X# endif
X# define VFSTAB_FILE       "/etc/vfstab"
X#endif
X
X#if ! defined (TYPE_LEN)
X# define TYPE_LEN          16
X#endif
X
X#if ! defined (UBSIZE)
X# define UBSIZE            512
X#endif
X
X#if defined (MOUNTED)
X# define MOUNT_FILE        MOUNTED
X#else
X# if defined (MNTTAB)
X#  define MOUNT_FILE       MNTTAB
X# else
X#  define MOUNT_FILE       "/etc/mnttab"
X# endif
X#endif
X
X#if ! defined (TRUE)
X# define TRUE             1
X#endif
X#if ! defined (FALSE)
X# define FALSE            0
X#endif
X
X#if defined (HAS_BZERO)
X# if defined (NEED_BZERO_DEFS)
Xextern int bzero (char *, int);
X# endif
X#  define memset(s,c,n)    (bzero ((s), (n)), s)
X#endif
X
X#define F_ALL               0x00000001
X#define F_LOCAL_ONLY        0x00000002
X#define F_TOTAL             0x00000010
X#define F_NO_HEADER         0x00000020
X#define F_DEBUG_HDR         0x00000040
X
X    /* mount information */
X#define FMT_MOUNT           'm'
X#define FMT_MOUNT_FULL      'M'
X#define FMT_SPECIAL         's'
X#define FMT_SPECIAL_FULL    'S'
X#define FMT_TYPE            't'
X#define FMT_TYPE_FULL       'T'
X
X    /* disk information */
X#define FMT_BTOT            'b'
X#define FMT_BTOT_AVAIL      'B'
X#define FMT_BUSED           'u'
X#define FMT_BCUSED          'c'
X#define FMT_BFREE           'f'
X#define FMT_BAVAIL          'v'
X#define FMT_BPERC_AVAIL     'p'
X#define FMT_BPERC_FREE      '1'
X#define FMT_BPERC_BSD       '2'
X#define FMT_ITOT            'i'
X#define FMT_IUSED           'U'
X#define FMT_IFREE           'F'
X#define FMT_IPERC           'P'
X
X#define DI_IGNORE           0
X#define DI_OK               1
X#define DI_BAD              2
X
X#define DI_SORT_NONE        0
X#define DI_SORT_NAME        1
X#define DI_SORT_SPECIAL     2
X
X#define DI_SORT_ASCENDING   1
X#define DI_SORT_DESCENDING  -1
X
X#define DI_UNKNOWN_DEV      -1L
X#define DI_LIST_SEP         ","
X
X#define ALL_FORMAT          "MTS\n\tbuf1\n\tbcvp\n\tBuv2\n\tiUFP"
X
X#define HALF_K              512.0
X#define ONE_K               1024.0
X#define ONE_MEG             1048576.0
X#define ONE_GIG             1073241824.0
X
X#if ! defined (MAXPATHLEN)
X# define MAXPATHLEN         255
X#endif
X#define SPEC_NAME_LEN       MAXPATHLEN
X
X#define RETRY_COUNT         5
X#define MAX_REMOTE_TYPES    20
X
X   /* you may want to change some of these values.  Be sure to change all */
X   /* related entries.                                                    */
X#define DEFAULT_FORMAT      "mbuvpiUFP"
X/* #define DEFAULT_FORMAT      "STbuvpM" */
X#define PERC_FMT            "%3.0f%% "
X#define PERC_LBL_FMT        "%5s"
X#define NAME_LEN            MAXPATHLEN
X#define FSTYPE_FMT          "%-7.7s"
X#define MOUNT_FMT           "%-15.15s"
X#define SPEC_FMT            "%-18.18s"
X
X#define UNKNOWN_FSTYPE      "Unknown fstyp %.2d"
X
Xtypedef unsigned long _ulong;
Xtypedef int (*SORT_FUNC) PROTO ((char *, char *));
X
X#if defined (NEED_GETOPT_DEFS)
Xextern char    *optarg;
Xextern int     optind;
X    /* SCO will throw up on this...just comment it out */
Xextern int     getopt PROTO ((int, char *[], const char *));
X#endif
X#if defined (NEED_ERRNO_DEFS)
Xextern int     errno;
X#endif
X
Xtypedef struct
X{
X    double          totalBlocks;
X    double          freeBlocks;
X    double          availBlocks;
X    _ulong          totalInodes;
X    _ulong          freeInodes;
X    _ulong          availInodes;
X    long            st_dev;                      /* disk device number   */
X    char            printFlag;                   /* do we want to print  */
X                                                 /* this entry?          */
X    char            isLocal;                     /* is this mount point  */
X                                                 /* local?               */
X    char            name [NAME_LEN + 1];         /* mount point          */
X    char            special [SPEC_NAME_LEN + 1]; /* special device name  */
X    char            fsType [TYPE_LEN + 1];       /* type of file system  */
X} DiskInfo;
X
Xstatic DiskInfo     *diskInfo = { (DiskInfo *) NULL };
Xstatic int          diCount = { 0 };
Xstatic int          debug = { 0 };
Xstatic _ulong       flags = { 0 };
Xstatic int          sortType = { DI_SORT_NAME };
Xstatic int          sortOrder = { DI_SORT_ASCENDING };
Xstatic char         *formatString = { DEFAULT_FORMAT };
Xstatic char         mountFormat [20];
Xstatic char         specialFormat [20];
Xstatic char         typeFormat [20];
Xstatic int          width = { 8 };
Xstatic int          inodeWidth = { 7 };
Xstatic char         blockFormat [20];
Xstatic char         blockLabelFormat [20];
Xstatic char         inodeFormat [20];
Xstatic char         inodeLabelFormat [20];
Xstatic char         **ignoreList = { (char **) NULL };
Xstatic char         **includeList = { (char **) NULL };
Xstatic double       dispBlockSize = { ONE_K };
Xstatic int          remoteFileSystemCount = { 0 };
Xstatic char         remoteFileSystemTypes [MAX_REMOTE_TYPES][TYPE_LEN];
X
X
Xstatic void cleanup             PROTO ((void));
Xstatic void printDiskInfo       PROTO ((void));
Xstatic void printInfo           PROTO ((DiskInfo *));
Xstatic void addTotals           PROTO ((DiskInfo *, DiskInfo *));
Xstatic void printTitle          PROTO ((void));
Xstatic void printPerc           PROTO ((double, double, char *));
Xstatic char *Realloc            PROTO ((char *, long));
Xstatic void sortArray           PROTO ((char *, int, int, SORT_FUNC));
Xstatic int  diCompare           PROTO ((char *, char *));
Xstatic void getDiskStatInfo     PROTO ((void));
Xstatic void printFileInfo       PROTO ((int, int, char *[]));
Xstatic void checkDiskInfo       PROTO ((void));
Xstatic void usage               PROTO ((void));
Xstatic void processArgs         PROTO ((int, char *[]));
Xstatic void parseList           PROTO ((char ***, char *));
X
Xstatic int  getDiskEntries      PROTO ((void));
Xstatic void getDiskInfo         PROTO ((void));
X
Xint
Xmain (argc, argv)
X    int                 argc;
X    char                *argv [];
X{
X    char                *ptr;
X
X
X    if ((ptr = getenv ("DIFMT")) != (char *) NULL)
X    {
X        formatString = ptr;
X    }
X
X    processArgs (argc, argv);
X    if (debug > 0)
X    {
X        printf ("di ver 1.17\n");
X    }
X
X    if (getDiskEntries () < 0)
X    {
X        cleanup ();
X        exit (1);
X    }
X
X    getDiskInfo ();
X    checkDiskInfo ();
X    if (optind < argc)
X    {
X        getDiskStatInfo ();
X        printFileInfo (optind, argc, argv);
X    }
X    else
X    {
X        printDiskInfo ();
X    }
X
X    cleanup ();
X    exit (0);
X}
X
X/*
X * cleanup
X *
X * free up allocated memory
X *
X */
X
Xstatic void
Xcleanup ()
X{
X    char        **lptr;
X
X
X    if (diskInfo != (DiskInfo *) NULL)
X    {
X        free ((char *) diskInfo);
X    }
X
X    if (ignoreList != (char **) NULL)
X    {
X        lptr = ignoreList;
X        while (*lptr != (char *) NULL)
X        {
X            free ((char *) *lptr);
X            ++lptr;
X        }
X        free ((char *) ignoreList);
X    }
X
X    if (includeList != (char **) NULL)
X    {
X        lptr = includeList;
X        while (*lptr != (char *) NULL)
X        {
X            free ((char *) *lptr);
X            ++lptr;
X        }
X        free ((char *) includeList);
X    }
X}
X
X/*
X * printDiskInfo
X *
X * Print out the disk information table.
X * Loops through all mounted disks, prints and calculates totals.
X *
X */
X
Xstatic void
XprintDiskInfo ()
X{
X    int                 i;
X    DiskInfo            totals;
X
X
X    memset ((char *) &totals, '\0', sizeof (DiskInfo));
X    strcpy (totals.name, "Total");
X    totals.printFlag = DI_OK;
X
X    if ((flags & F_NO_HEADER) != F_NO_HEADER)
X    {
X        printTitle ();
X    }
X
X    if (sortType != DI_SORT_NONE)
X    {
X        sortArray ((char *) diskInfo, sizeof (DiskInfo), diCount, diCompare);
X    }
X
X    for (i = 0; i < diCount; ++i)
X    {
X        if (( (flags & F_ALL) == F_ALL && diskInfo [i].printFlag != DI_BAD) ||
X                diskInfo [i].printFlag == DI_OK)
X        {
X            printInfo (&diskInfo [i]);
X            addTotals (&diskInfo [i], &totals);
X        }
X    }
X
X    if ((flags & F_TOTAL) == F_TOTAL && (flags & F_NO_HEADER) != F_NO_HEADER)
X    {
X        printInfo (&totals);
X    }
X}
X
X/*
X * printInfo
X *
X * Print the information for a single partition.  Loop through the
X * format string and print the particular items wanted.
X *
X */
X
Xstatic void
XprintInfo (diskInfo)
X    DiskInfo            *diskInfo;
X{
X    double              used;
X    double              totAvail;
X    char                *ptr;
X    int                 valid;
X
X
X    ptr = formatString;
X    while (*ptr)
X    {
X        valid = TRUE;
X
X        switch (*ptr)
X        {
X            case FMT_MOUNT:
X            {
X                printf (MOUNT_FMT, diskInfo->name);
X                break;
X            }
X
X            case FMT_MOUNT_FULL:
X            {
X                printf (mountFormat, diskInfo->name);
X                break;
X            }
X
X            case FMT_BTOT:
X            {
X                printf (blockFormat, diskInfo->totalBlocks);
X                break;
X            }
X
X            case FMT_BTOT_AVAIL:
X            {
X                printf (blockFormat, diskInfo->totalBlocks -
X                        (diskInfo->freeBlocks - diskInfo->availBlocks));
X                break;
X            }
X
X            case FMT_BUSED:
X            {
X                printf (blockFormat, diskInfo->totalBlocks -
X                        diskInfo->freeBlocks);
X                break;
X            }
X
X            case FMT_BCUSED:
X            {
X                printf (blockFormat, diskInfo->totalBlocks - diskInfo->availBlocks);
X                break;
X            }
X
X            case FMT_BFREE:
X            {
X                printf (blockFormat, diskInfo->freeBlocks);
X                break;
X            }
X
X            case FMT_BAVAIL:
X            {
X                printf (blockFormat, diskInfo->availBlocks);
X                break;
X            }
X
X            case FMT_BPERC_AVAIL:
X            {
X                used = diskInfo->totalBlocks - diskInfo->availBlocks;
X                totAvail = diskInfo->totalBlocks;
X                printPerc (used, totAvail, PERC_FMT);
X                break;
X            }
X
X            case FMT_BPERC_FREE:
X            {
X                used = diskInfo->totalBlocks - diskInfo->freeBlocks;
X                totAvail = diskInfo->totalBlocks;
X                printPerc (used, totAvail, PERC_FMT);
X                break;
X            }
X
X            case FMT_BPERC_BSD:
X            {
X                used = diskInfo->totalBlocks - diskInfo->freeBlocks;
X                totAvail = diskInfo->totalBlocks -
X                        (diskInfo->freeBlocks - diskInfo->availBlocks);
X                printPerc (used, totAvail, PERC_FMT);
X                break;
X            }
X
X            case FMT_ITOT:
X            {
X                printf (inodeFormat, diskInfo->totalInodes);
X                break;
X            }
X
X            case FMT_IUSED:
X            {
X                printf (inodeFormat, diskInfo->totalInodes - diskInfo->freeInodes);
X                break;
X            }
X
X            case FMT_IFREE:
X            {
X                printf (inodeFormat, diskInfo->freeInodes);
X                break;
X            }
X
X            case FMT_IPERC:
X            {
X                used = diskInfo->totalInodes - diskInfo->availInodes;
X                totAvail = diskInfo->totalInodes;
X                printPerc (used, totAvail, PERC_FMT);
X                break;
X            }
X
X            case FMT_SPECIAL:
X            {
X                printf (SPEC_FMT, diskInfo->special);
X                break;
X            }
X
X            case FMT_SPECIAL_FULL:
X            {
X                printf (specialFormat, diskInfo->special);
X                break;
X            }
X
X            case FMT_TYPE:
X            {
X                printf (FSTYPE_FMT, diskInfo->fsType);
X                break;
X            }
X
X            case FMT_TYPE_FULL:
X            {
X                printf (typeFormat, diskInfo->fsType);
X                break;
X            }
X
X            default:
X            {
X                printf ("%c", *ptr);
X                valid = FALSE;
X                break;
X            }
X        }
X
X        ++ptr;
X        if (*ptr && valid)
X        {
X            printf (" ");
X        }
X    }
X
X    printf ("\n");
X}
X
X/*
X * addTotals
X *
X * Add up the totals for the blocks/inodes
X *
X */
X
Xstatic void
XaddTotals (diskInfo, totals)
X    DiskInfo      *diskInfo;
X    DiskInfo      *totals;
X{
X    totals->totalBlocks += diskInfo->totalBlocks;
X    totals->freeBlocks += diskInfo->freeBlocks;
X    totals->availBlocks += diskInfo->availBlocks;
X    totals->totalInodes += diskInfo->totalInodes;
X    totals->freeInodes += diskInfo->freeInodes;
X    totals->availInodes += diskInfo->availInodes;
X}
X
X/*
X * printTitle
X *
X * Loop through the format string and print the appropriate headings.
X *
X */
X
Xstatic void
XprintTitle ()
X{
X    char                *ptr;
X    int                 valid;
X    char                tbuff [20];
X
X    if ((flags & F_DEBUG_HDR) == F_DEBUG_HDR)
X    {
X        printf ("di ver 1.17           Default Format: %s\n", DEFAULT_FORMAT);
X    }
X
X    ptr = formatString;
X
X    while (*ptr)
X    {
X        valid = TRUE;
X
X        switch (*ptr)
X        {
X            case FMT_MOUNT:
X            {
X                printf (MOUNT_FMT, "Mount");
X                break;
X            }
X
X            case FMT_MOUNT_FULL:
X            {
X                printf (mountFormat, "Mount");
X                break;
X            }
X
X            case FMT_BTOT:
X            case FMT_BTOT_AVAIL:
X            {
X                if (dispBlockSize == ONE_K)
X                {
X                    printf (blockLabelFormat, "Kbytes");
X                }
X                else if (dispBlockSize == ONE_MEG)
X                {
X                    printf (blockLabelFormat, "  Megs");
X                }
X                else if (dispBlockSize == ONE_GIG)
X                {
X                    printf (blockLabelFormat, "  Gigs");
X                }
X                else if (dispBlockSize == HALF_K)
X                {
X                    printf (blockLabelFormat, "  512b");
X                }
X                else
X                {
X                    sprintf (tbuff, "%6.0f", dispBlockSize);
X                    printf (blockLabelFormat, tbuff);
X                }
X                break;
X            }
X
X            case FMT_BUSED:
X            case FMT_BCUSED:
X            {
X                printf (blockLabelFormat, "Used");
X                break;
X            }
X
X            case FMT_BFREE:
X            {
X                printf (blockLabelFormat, "Free");
X                break;
X            }
X
X            case FMT_BAVAIL:
X            {
X                printf (blockLabelFormat, "Avail");
X                break;
X            }
X
X            case FMT_BPERC_AVAIL:
X            case FMT_BPERC_FREE:
X            case FMT_BPERC_BSD:
X            {
X                printf (PERC_LBL_FMT, "%used");
X                break;
X            }
X
X            case FMT_ITOT:
X            {
X                printf (inodeLabelFormat, "Inodes");
X                break;
X            }
X
X            case FMT_IUSED:
X            {
X                printf (inodeLabelFormat, "Used");
X                break;
X            }
X
X            case FMT_IFREE:
X            {
X                printf (inodeLabelFormat, "Free");
X                break;
X            }
X
X            case FMT_IPERC:
X            {
X                printf (PERC_LBL_FMT, "%used");
X                break;
X            }
X
X            case FMT_SPECIAL:
X            {
X                printf (SPEC_FMT, "Filesystem");
X                break;
X            }
X
X            case FMT_SPECIAL_FULL:
X            {
X                printf (specialFormat, "Filesystem");
X                break;
X            }
X
X            case FMT_TYPE:
X            {
X                printf (FSTYPE_FMT, "fsType");
X                break;
X            }
X
X            case FMT_TYPE_FULL:
X            {
X                printf (typeFormat, "fs Type");
X                break;
X            }
X
X            default:
X            {
X                printf ("%c", *ptr);
X                valid = FALSE;
X                break;
X            }
X        }
X
X        ++ptr;
X        if (*ptr && valid)
X        {
X            printf (" ");
X        }
X    }
X
X    printf ("\n");
X}
X
X/*
X * printPerc
X *
X * Calculate and print a percentage using the values and format passed.
X *
X */
X
Xstatic void
XprintPerc (used, totAvail, format)
X    double      used;
X    double      totAvail;
X    char        *format;
X{
X    double      perc;
X
X
X    if (totAvail > 0.0)
X    {
X        perc = used / totAvail;
X        perc *= 100.0;
X    }
X    else
X    {
X        perc = 0.0;
X    }
X    printf (format, perc);
X}
X
X
X/*
X * Realloc
X *
X * portable realloc
X *
X */
X
Xstatic char *
XRealloc (ptr, size)
X    char      *ptr;
X    long      size;
X{
X    if (ptr == (char *) NULL)
X    {
X        ptr = (char *) malloc (size);
X    }
X    else
X    {
X        ptr = (char *) realloc (ptr, size);
X    }
X
X    return ptr;
X}
X
X
Xstatic void
XprintFileInfo (optind, argc, argv)
X    int                 optind;
X    int                 argc;
X    char                *argv [];
X{
X    int                 i;
X    int                 j;
X    struct stat         statBuf;
X    DiskInfo            totals;
X
X
X    memset ((char *) &totals, '\0', sizeof (DiskInfo));
X    strcpy (totals.name, "Total");
X    totals.printFlag = DI_OK;
X
X    if ((flags & F_NO_HEADER) != F_NO_HEADER)
X    {
X        printTitle ();
X    }
X
X    for (i = optind; i < argc; ++i)
X    {
X        if (stat (argv [i], &statBuf) == 0)
X        {
X            for (j = 0; j < diCount; ++j)
X            {
X                if (diskInfo [j].printFlag != DI_BAD &&
X                        diskInfo [j].st_dev != DI_UNKNOWN_DEV &&
X                        (long) statBuf.st_dev == diskInfo [j].st_dev)
X                {
X                    printInfo (&diskInfo [j]);
X                    addTotals (&diskInfo [j], &totals);
X                    break; /* out of inner for */
X                }
X            }
X        } /* if stat ok */
X        else
X        {
X            perror (argv [i]);
X        }
X    } /* for each file specified on command line */
X
X    if ((flags & F_TOTAL) == F_TOTAL && (flags & F_NO_HEADER) != F_NO_HEADER)
X    {
X        printInfo (&totals);
X    }
X}
X
X/*
X *  sortArray ()
X *
X *      shellsort!
X *
X */
X
Xstatic void
XsortArray (data, dataSize, count, compareFunc)
X    char            *data;
X    int             dataSize;
X    int             count;
X    SORT_FUNC       compareFunc;
X{
X    register int    j;
X    char            *tempData;
X    int             i;
X    int             gap;
X
X
X    if (count <= 1)
X    {
X        return;
X    }
X
X    tempData = (char *) malloc ((unsigned) dataSize);
X    if (tempData == (char *) NULL)
X    {
X        fprintf (stderr, "malloc failed in sortArray().  errno %d\n", errno);
X        cleanup ();
X        exit (1);
X    }
X
X    gap = 1;
X    while (gap < count)
X    {
X        gap = 3 * gap + 1;
X    }
X
X    for (gap /= 3; gap > 0; gap /= 3)
X    {
X        for (i = gap; i < count; ++i)
X        {
X            for (j = i - gap; j >= 0 &&
X                compareFunc (& (data [j * dataSize]),
X                             & (data [ (j + gap) * dataSize])) > 0;
X                j -= gap)
X            {
X                memcpy ((char *) tempData, (char *) & (data [j * dataSize]),
X                        dataSize);
X                memcpy ((char *) & (data [j * dataSize]),
X                        (char *) & (data [ (j + gap) * dataSize]), dataSize);
X                memcpy ((char *) & (data [ (j + gap) * dataSize]),
X                        (char *) tempData, dataSize);
X            }
X        }
X    }
X
X    free ((char *) tempData);
X}
X
X
Xstatic int
XdiCompare (a, b)
X    char        *a;
X    char        *b;
X{
X    DiskInfo    *di1;
X    DiskInfo    *di2;
X
X
X    di1 = (DiskInfo *) a;
X    di2 = (DiskInfo *) b;
X
X
X    switch (sortType)
X    {
X        case DI_SORT_NONE:
X        {
X            break;
X        }
X
X        case DI_SORT_NAME:
X        {
X            return (strcmp (di1->name, di2->name) * sortOrder);
X        }
X
X        case DI_SORT_SPECIAL:
X        {
X            return (strcmp (di1->special, di2->special) * sortOrder);
X        }
X    } /* switch on sort type */
X
X    return 0;
X}
X
X
X/*
X * getDiskStatInfo
X *
X * gets the disk device number for each entry.
X *
X */
X
Xstatic void
XgetDiskStatInfo ()
X{
X    int         i;
X    struct stat statBuf;
X
X    for (i = 0; i < diCount; ++i)
X    {
X        diskInfo [i].st_dev = DI_UNKNOWN_DEV;
X
X        if (stat (diskInfo [i].name, &statBuf) == 0)
X        {
X            diskInfo [i].st_dev = (long) statBuf.st_dev;
X        }
X        else
X        {
X            perror (diskInfo [i].name);
X        }
X    }
X}
X
X/*
X * checkDiskInfo
X *
X * checks the disk information returned for various return values.
X *
X */
X
Xstatic void
XcheckDiskInfo ()
X{
X    int           i;
X    int           len;
X    int           maxMountString;
X    int           maxSpecialString;
X    int           maxTypeString;
X    char          **ptr;
X
X
X    maxMountString = (flags & F_NO_HEADER) == F_NO_HEADER ? 0 : 5;
X    maxSpecialString = (flags & F_NO_HEADER) == F_NO_HEADER ? 0 : 10;
X    maxTypeString = (flags & F_NO_HEADER) == F_NO_HEADER ? 0 : 7;
X
X    for (i = 0; i < diCount; ++i)
X    {
X            /* Solaris reports a cdrom as having no free blocks,   */
X            /* no available.  Their df doesn't always work right!  */
X            /* -1 is returned.                                     */
X        if (debug > 2)
X        {
X            printf ("chk: free: %f\n", diskInfo [i].freeBlocks);
X        }
X        if (diskInfo [i].freeBlocks < 0.0)
X        {
X            diskInfo [i].freeBlocks = 0.0;
X        }
X        if (diskInfo [i].availBlocks < 0.0)
X        {
X            diskInfo [i].availBlocks = 0.0;
X        }
X
X        if ((long) diskInfo [i].totalInodes < 0L)
X        {
X            diskInfo [i].totalInodes = 0L;
X            diskInfo [i].freeInodes = 0L;
X            diskInfo [i].availInodes = 0L;
X        }
X
X        if (debug > 2)
X        {
X            printf ("chk: total: %f\n", diskInfo [i].totalBlocks);
X        }
X        if (diskInfo [i].totalBlocks <= 0.0)
X        {
X            diskInfo [i].printFlag = DI_IGNORE;
X        }
X
X            /* if the file system type is in the ignore list, skip it */
X        if (ignoreList != (char **) NULL)
X        {
X            ptr = ignoreList;
X            while (*ptr != (char *) NULL)
X            {
X                if (strcmp (*ptr, diskInfo [i].fsType) == 0)
X                {
X                    diskInfo [i].printFlag = DI_IGNORE;
X                    break;
X                }
X                ++ptr;
X            }
X        } /* if an ignore list was specified */
X
X            /* if the file system type is not in the include list, skip it */
X        if (includeList != (char **) NULL)
X        {
X            ptr = includeList;
X            while (*ptr != (char *) NULL)
X            {
X                if (strcmp (*ptr, diskInfo [i].fsType) == 0)
X                {
X                    diskInfo [i].printFlag = DI_OK;
X                    break;
X                }
X                else
X                {
X                    diskInfo [i].printFlag = DI_IGNORE;
X                }
X                ++ptr;
X            }
X        } /* if an include list was specified */
X    } /* for all disks */
X
X        /* this loop gets the max string lengths */
X    for (i = 0; i < diCount; ++i)
X    {
X        if (diskInfo [i].printFlag == DI_OK || (flags & F_ALL) == F_ALL)
X        {
X            len = strlen (diskInfo [i].name);
X            if (len > maxMountString)
X            {
X                maxMountString = len;
X            }
X
X            len = strlen (diskInfo [i].special);
X            if (len > maxSpecialString)
X            {
X                maxSpecialString = len;
X            }
X
X            len = strlen (diskInfo [i].fsType);
X            if (len > maxTypeString)
X            {
X                maxTypeString = len;
X            }
X        } /* if we are printing this item */
X    } /* for all disks */
X
X    sprintf (mountFormat, "%%-%d.%ds", maxMountString, maxMountString);
X    sprintf (specialFormat, "%%-%d.%ds", maxSpecialString,
X             maxSpecialString);
X    sprintf (typeFormat, "%%-%d.%ds", maxTypeString, maxTypeString);
X    if (dispBlockSize <= ONE_K)
X    {
X        sprintf (blockFormat, "%%%d.0f", width);
X    }
X    else
X    {
X        sprintf (blockFormat, "%%%d.1f", width);
X    }
X    sprintf (blockLabelFormat, "%%%ds", width);
X    sprintf (inodeFormat, "%%%dlu", inodeWidth);
X    sprintf (inodeLabelFormat, "%%%ds", inodeWidth);
X}
X
X/*
X * usage
X *
X */
X
Xstatic void
Xusage ()
X{
X    printf ("di ver 1.17           Default Format: %s\n", DEFAULT_FORMAT);
X         /*  12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
X    printf ("Usage: di [-ant] [-f format] [-s sort-type] [-i ignore-fstyp-list]\n");
X    printf ("       [-I include-fstyp-list] [-w kbyte-width] [-W inode-width] [file [...]]\n");
X    printf ("   -a   : print all mounted devices; normally, those with 0 total blocks are\n");
X    printf ("          not printed.  e.g. /dev/proc, /dev/fd.\n");
X    printf ("   -d x : size to print blocks in (p - posix (512), k - kbytes,\n");
X    printf ("          m - megabytes, g - gigabytes, <x> - numeric size).\n");
X    printf ("   -f x : use format string <x>\n");
X    printf ("   -i x : ignore file system types in <x>\n");
X    printf ("   -I x : include only file system types in <x>\n");
X    printf ("   -l   : display local filesystems only\n");
X    printf ("   -n   : don't print header\n");
X    printf ("   -s t : sort type; n - no sort, s - by special device, r - reverse\n");
X    printf ("   -t   : print totals\n");
X    printf ("   -w n : use width <n> for kbytes\n");
X    printf ("   -W n : use width <n> for i-nodes\n");
X    printf (" Format string values:\n");
X    printf ("    m - mount point                     M - mount point, full length\n");
X    printf ("    b - total kbytes                    B - kbytes available for use\n");
X    printf ("    u - used kbytes                     c - calculated kbytes in use\n");
X    printf ("    f - kbytes free                     v - kbytes available\n");
X    printf ("    p - percentage not avail. for use   1 - percentage used\n");
X    printf ("    2 - percentage of user-available space in use.\n");
X    printf ("    i - total file slots (i-nodes)      U - used file slots\n");
X    printf ("    F - free file slots                 P - percentage file slots used\n");
X    printf ("    s - filesystem name                 S - filesystem name, full length\n");
X    printf ("    t - disk partition type             T - partition type, full length\n");
X}
X
X
Xstatic void
XprocessArgs (argc, argv)
X    int         argc;
X    char        *argv [];
X{
X    int         ch;
X
X
X    while ((ch = getopt (argc, argv, "Aad:f:hi:I:Flns:tw:W:x:")) != -1)
X    {
X        switch (ch)
X        {
X            case 'A':
X            {
X                formatString = ALL_FORMAT;
X                flags |= F_ALL | F_DEBUG_HDR | F_TOTAL;
X                flags &= ~ F_NO_HEADER;
X                width = 10;
X                inodeWidth = 10;
X                break;
X            }
X
X            case 'a':
X            {
X                flags |= F_ALL;
X                break;
X            }
X
X            case 'd':
X            {
X                switch (tolower (*optarg))
X                {
X                    case 'p':
X                    {
X                        dispBlockSize = HALF_K;
X                        break;
X                    }
X
X                    case 'k':
X                    {
X                        dispBlockSize = ONE_K;
X                        break;
X                    }
X
X                    case 'm':
X                    {
X                        dispBlockSize = ONE_MEG;
X                        break;
X                    }
X
X                    case 'g':
X                    {
X                        dispBlockSize = ONE_GIG;
X                        break;
X                    }
X
X                    default:
X                    {
X                        if (isdigit (*optarg))
X                        {
X                            dispBlockSize = atof (optarg);
X                        }
X                        break;
X                    }
X                }
X                break;
X            }
X
X            case 'f':
X            {
X                formatString = optarg;
X                break;
X            }
X
X            case 'h':
X            {
X                usage ();
X                cleanup ();
X                exit (0);
X            }
X
X            case 'i':
X            {
X                parseList (&ignoreList, optarg);
X                break;
X            }
X
X            case 'I':
X            {
X                parseList (&includeList, optarg);
X                break;
X            }
X
X            case 'l':
X            {
X                flags |= F_LOCAL_ONLY;
X                break;
X            }
X
X            case 'n':
X            {
X                flags |= F_NO_HEADER;
X                break;
X            }
X
X            case 's':
X            {
X                switch (ch)
X                {
X                    case 's':
X                    {
X                        sortType = DI_SORT_SPECIAL;
X                        break;
X                    }
X
X                    case 'n':
X                    {
X                        sortType = DI_SORT_NONE;
X                        break;
X                    }
X
X                    case 'r':
X                    {
X                        sortOrder = DI_SORT_DESCENDING;
X                        break;
X                    }
X                }
X                break;
X            }
X
X            case 't':
X            {
X                flags |= F_TOTAL;
X                break;
X            }
X
X            case 'w':
X            {
X                width = atoi (optarg);
X                break;
X            }
X
X            case 'W':
X            {
X                inodeWidth = atoi (optarg);
X                break;
X            }
X
X            case 'x':
X            {
X                debug = atoi (optarg);
X                break;
X            }
X
X            case '?':
X            {
X                usage ();
X                cleanup ();
X                exit (1);
X            }
X        }
X    }
X}
X
X    /* list is assumed to be global */
Xstatic void
XparseList (list, str)
X    char        ***list;
X    char        *str;
X{
X    char        *dstr;
X    char        *ptr;
X    char        **lptr;
X    int         count;
X    int         i;
X    int         len;
X
X    i = strlen (str);
X    dstr = (char *) malloc (i + 1);
X    if (dstr == (char *) NULL)
X    {
X        fprintf (stderr, "malloc failed in parseList() (1).  errno %d\n", errno);
X        cleanup ();
X        exit (1);
X    }
X
X    memcpy (dstr, str, i + 1);
X
X    ptr = strtok (dstr, DI_LIST_SEP);
X    count = 0;
X    while (ptr != (char *) NULL)
X    {
X        ++count;
X        ptr = strtok ((char *) NULL, DI_LIST_SEP);
X    }
X
X    *list = (char **) malloc ((count + 1) * sizeof (char *));
X    if (*list == (char **) NULL)
X    {
X        fprintf (stderr, "malloc failed in parseList() (2).  errno %d\n", errno);
X        cleanup ();
X        exit (1);
X    }
X
X    ptr = dstr;
X    lptr = *list;
X    for (i = 0; i < count; ++i)
X    {
X        len = strlen (ptr);
X        *lptr = (char *) malloc (len + 1);
X        if (*lptr == (char *) NULL)
X        {
X            fprintf (stderr, "malloc failed in parseList() (3).  errno %d\n",
X                    errno);
X            cleanup ();
X            exit (1);
X        }
X        strcpy (*lptr, ptr);
X        ptr += len + 1;
X        ++lptr;
X    }
X
X    *lptr = (char *) NULL;
X    free ((char *) dstr);
X}
X
X#if defined (HAS_MNTTAB)
X
X#define DFS_FS_TABLE 	"/etc/dfs/fstypes"
X
X/*
X * getDiskEntries
X *
X * For SysV.4, we open the file and call getmntent () repeatedly.
X *
X */
X
Xstatic int
XgetDiskEntries ()
X{
X    FILE            *f;
X    int             idx;
X    int             i;
X    struct mnttab   mntEntry;
X    char            buff [80];
X
X    if ((flags & F_LOCAL_ONLY) == F_LOCAL_ONLY)
X    {
X        i = remoteFileSystemCount;
X
X        if ((f = fopen (DFS_FS_TABLE, "r")) != (FILE *) NULL)
X        {
X            fgets (buff, 80, f);
X            if (debug > 1)
X            {
X                printf ("remote file system type: %s\n", buff);
X            }
X            sscanf (buff, "%s", remoteFileSystemTypes [i++]);
X            fclose (f);
X        }
X
X        remoteFileSystemCount = i;
X    }
X
X    if ((f = fopen (MOUNT_FILE, "r")) == (FILE *) NULL)
X    {
X        fprintf (stderr, "Unable to open: %s errno %d\n", MOUNT_FILE, errno);
X        return -1;
X    }
X
X    while (getmntent (f, &mntEntry) == 0)
X    {
X        idx = diCount;
X        ++diCount;
X        diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
X                sizeof (DiskInfo) * diCount);
X        memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
X        diskInfo [idx].printFlag = DI_OK;
X
X        strncpy (diskInfo [idx].special, mntEntry.mnt_special, SPEC_NAME_LEN);
X        strncpy (diskInfo [idx].name, mntEntry.mnt_mountp, NAME_LEN);
X            /* get the file system type now... */
X        strncpy (diskInfo [idx].fsType, mntEntry.mnt_fstype, TYPE_LEN);
X
X        diskInfo [idx].isLocal = TRUE;
X        for (i = 0; i < remoteFileSystemCount; ++i)
X        {
X            if (strcmp (diskInfo [idx].fsType, remoteFileSystemTypes [i]) == 0)
X            {
X                diskInfo [idx].isLocal = FALSE;
X            }
X        }
X
X        if (debug > 0)
X        {
X            printf ("mnt:%s - %s\n", diskInfo [idx].name,
X                    diskInfo [idx].special);
X        }
X    }
X
X    fclose (f);
X    return 0;
X}
X
X#endif /* HAS_MNTTAB */
X
X#if defined (HAS_SVR3_MNTTAB)
X
X/*
X * getDiskEntries
X *
X * For SysV.3 we open the file and read it ourselves.
X *
X */
X
Xstatic int
XgetDiskEntries ()
X{
X    FILE             *f;
X    int              idx;
X    struct mnttab    mntEntry;
X
X
X    if ((f = fopen (MOUNT_FILE, "r")) == (FILE *) NULL)
X    {
X        fprintf (stderr, "Unable to open: %s errno %d\n", MOUNT_FILE, errno);
X        return -1;
X    }
X
X    while (fread ((char *) &mntEntry, sizeof (struct mnttab), 1, f) == 1)
X    {
X            /* xenix allows null mount table entries */
X            /* sco nfs background mounts are marked as "nothing" */
X        if (mntEntry.mt_filsys [0] &&
X                strcmp (mntEntry.mt_filsys, "nothing") != 0)
X        {
X            idx = diCount;
X            ++diCount;
X            diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
X                                             sizeof (DiskInfo) * diCount);
X            memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
X            diskInfo [idx].printFlag = DI_OK;
X            diskInfo [idx].isLocal = TRUE;
X
X# if defined (COHERENT)
X                /* Coherent seems to have these fields reversed. oh well. */
X            strncpy (diskInfo [idx].name, mntEntry.mt_dev, NAME_LEN);
X            strncpy (diskInfo [idx].special, mntEntry.mt_filsys, SPEC_NAME_LEN);
X# else
X            strncpy (diskInfo [idx].special, mntEntry.mt_dev, SPEC_NAME_LEN);
X            strncpy (diskInfo [idx].name, mntEntry.mt_filsys, NAME_LEN);
X# endif
X        }
X
X        if (debug > 0)
X        {
X            printf ("mnt:%s - %s\n", diskInfo [idx].name,
X                    diskInfo [idx].special);
X        }
X    }
X
X    fclose (f);
X    return 0;
X}
X
X#endif /* HAS_MNTTAB */
X
X#if defined (HAS_MNTENT)
X
X/*
X * getDiskEntries
X *
X * SunOS supplies an open and close routine for the mount table.
X *
X */
X
Xstatic int
XgetDiskEntries ()
X{
X    FILE             *f;
X    int              idx;
X    struct mntent    *mntEntry;
X    char             *devp; /* local ptr to dev entry */
X
X
X    if ((f = setmntent (MOUNT_FILE, "r")) == (FILE *) NULL)
X    {
X        fprintf (stderr, "Unable to open: %s errno %d\n", MOUNT_FILE, errno);
X        return -1;
X    }
X
X    while ((mntEntry = getmntent (f)) != (struct mntent *) NULL)
X    {
X        idx = diCount;
X        ++diCount;
X        diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
X                sizeof (DiskInfo) * diCount);
X        memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
X        diskInfo [idx].printFlag = DI_OK;
X        diskInfo [idx].isLocal = TRUE;
X
X        strncpy (diskInfo [idx].special, mntEntry->mnt_fsname, SPEC_NAME_LEN);
X        strncpy (diskInfo [idx].name, mntEntry->mnt_dir, NAME_LEN);
X        strncpy (diskInfo [idx].fsType, mntEntry->mnt_type, TYPE_LEN);
X
X        if (strcmp (mntEntry->mnt_type, MNTTYPE_IGNORE) == 0)
X        {
X            diskInfo [idx].printFlag = DI_IGNORE;
X        }
X
X        if (debug > 0)
X        {
X            printf ("mnt:%s - %s : %s\n", diskInfo [idx].name,
X                    diskInfo [idx].special, diskInfo [idx].fsType);
X        }
X    }
X
X    endmntent (f);
X    return 0;
X}
X
X#endif /* HAS_MNTENT */
X
X#if defined (HAS_GETMNTINFO)
X
X/*
X * getDiskEntries
X *
X * OSF/1 does this with a system call and library routine
X *
X *                  [mogul@wrl.dec.com (Jeffrey Mogul)]
X */
X
X#if defined (HAS_INITMOUNTNAMES) && defined (INITMOUNTNAMES)
Xstatic char *mnt_names [] = INITMOUNTNAMES;
X# define MNT_NUMTYPES (MOUNT_MAXTYPE + 1)
X#endif
X
Xstatic int
XgetDiskEntries ()
X{
X    int             count;
X    int             idx;
X    short           fstype;
X    struct statfs   *mntbufp;
X    double          mult;
X
X    count = getmntinfo (&mntbufp, MNT_NOWAIT);
X    if (count < 1)
X    {
X        fprintf (stderr, "Unable to do getmntinfo () errno %d\n", errno);
X        return -1;
X    }
X
X    diCount = count;
X    diskInfo = (DiskInfo *) malloc (sizeof (DiskInfo) * count);
X    if (diskInfo == (DiskInfo *) NULL)
X    {
X        fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
X        return -1;
X    }
X    memset ((char *) diskInfo, '\0', sizeof (DiskInfo) * count);
X
X    if (debug > 1)
X    {
X        printf ("type_len %d name_len %d spec_name_len %d\n", TYPE_LEN,
X                NAME_LEN, SPEC_NAME_LEN);
X    }
X
X    for (idx = 0; idx < count; idx++)
X    {
X        diskInfo [idx].printFlag = DI_OK;
X        diskInfo [idx].isLocal = TRUE;
X        if ((mntbufp [idx].f_flags & MNT_LOCAL) != MNT_LOCAL)
X        {
X            diskInfo [idx].isLocal = FALSE;
X        }
X
X        if (diskInfo [idx].isLocal == FALSE && (flags & F_LOCAL_ONLY) == F_LOCAL_ONLY)
X        {
X            diskInfo [idx].printFlag = DI_IGNORE;
X        }
X
X        strncpy (diskInfo [idx].special, mntbufp [idx].f_mntfromname,
X                SPEC_NAME_LEN);
X        strncpy (diskInfo [idx].name, mntbufp [idx].f_mntonname, NAME_LEN);
X
X        mult = 1.0;
X
X#  if defined (HAS_GETMNTINFO_FSIZE) /* bsdi 1.x */
X        mult = (double) mntbufp [idx].f_fsize / dispBlockSize;
X#  endif
X#  if defined (HAS_GETMNTINFO_BSIZE) /* bsdi 2.x */
X        mult = (double) mntbufp [idx].f_bsize / dispBlockSize;
X#  endif
X            /* OSF/1 keeps these fields in units of 1K byte */
X        diskInfo [idx].totalBlocks = ((double) mntbufp [idx].f_blocks * mult);
X        diskInfo [idx].freeBlocks = ((double) mntbufp [idx].f_bfree * mult);
X        diskInfo [idx].availBlocks = ((double) mntbufp [idx].f_bavail * mult);
X
X        diskInfo [idx].totalInodes = mntbufp [idx].f_files;
X        diskInfo [idx].freeInodes = mntbufp [idx].f_ffree;
X        diskInfo [idx].availInodes = mntbufp [idx].f_ffree;
X
X        fstype = mntbufp [idx].f_type;
X# if defined (HAS_NO_FSTYPES_H) && ! defined (HAS_INITMOUNTNAMES)
X        if ((fstype > 0) && (fstype <= MOUNT_MAXTYPE))
X        {
X            switch (fstype)
X            {
X#  if defined (MOUNT_UFS)
X                case MOUNT_UFS:         /* UNIX "Fast" Filesystem */
X                {
X                    strncpy (diskInfo [idx].fsType, "ufs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_NFS)
X                case MOUNT_NFS:         /* Network Filesystem */
X                {
X                    strncpy (diskInfo [idx].fsType, "nfs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_MFS)
X                case MOUNT_MFS:         /* Memory Filesystem */
X                {
X                    strncpy (diskInfo [idx].fsType, "mfs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_MSDOS)
X                case MOUNT_MSDOS:       /* MSDOS Filesystem */
X                {
X                    strncpy (diskInfo [idx].fsType, "msdos", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_LFS)
X                case MOUNT_LFS:
X                {
X                    strncpy (diskInfo [idx].fsType, "lfs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_LOFS)
X                case MOUNT_LOFS:
X                {
X                    strncpy (diskInfo [idx].fsType, "lofs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_FDESC)
X                case MOUNT_FDESC:
X                {
X                    strncpy (diskInfo [idx].fsType, "fdesc", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_PORTAL)
X                case MOUNT_PORTAL:
X                {
X                    strncpy (diskInfo [idx].fsType, "portal", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_NULL)
X                case MOUNT_NULL:
X                {
X                    strncpy (diskInfo [idx].fsType, "null", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_UMAP)
X                case MOUNT_UMAP:
X                {
X                    strncpy (diskInfo [idx].fsType, "umap", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_KERNFS)
X                case MOUNT_KERNFS:
X                {
X                    strncpy (diskInfo [idx].fsType, "kernfs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_PROCFS)
X                case MOUNT_PROCFS:      /* proc filesystem */
X                {
X                    strncpy (diskInfo [idx].fsType, "pfs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_AFS)
X                case MOUNT_AFS:
X                {
X                    strncpy (diskInfo [idx].fsType, "afs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_ISOFS)
X                case MOUNT_ISOFS:       /* iso9660 cdrom */
X                {
X                    strncpy (diskInfo [idx].fsType, "iso9660fs", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_ISO9660) && ! defined (MOUNT_CD9660)
X                case MOUNT_ISO9660:       /* iso9660 cdrom */
X                {
X                    strncpy (diskInfo [idx].fsType, "iso9660", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_CD9660)
X                case MOUNT_CD9660:       /* iso9660 cdrom */
X                {
X                    strncpy (diskInfo [idx].fsType, "cd9660", TYPE_LEN);
X                    break;
X                }
X#  endif
X
X#  if defined (MOUNT_UNION)
X                case MOUNT_UNION:
X                {
X                    strncpy (diskInfo [idx].fsType, "union", TYPE_LEN);
X                    break;
X                }
X#  endif
X            } /* switch on mount type */
X        }
X# else
X        if ((fstype > 0) && (fstype < MNT_NUMTYPES))
X        {
X            strncpy (diskInfo [idx].fsType, mnt_names [fstype], TYPE_LEN);
X        }
X        else
X        {
X            sprintf (diskInfo [idx].fsType, UNKNOWN_FSTYPE, fstype);
X        }
X# endif /* has fs_types.h */
X
X        if (debug > 1)
X        {
X            printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType);
X            printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
X                    mntbufp [idx].f_blocks, mntbufp [idx].f_bfree,
X                    mntbufp [idx].f_bavail);
X            printf ("\tmult: %f\n", mult);
X# if defined (HAS_GETMNTINFO_FSIZE)
X            printf ("\tfsize:%ld \n", mntbufp [idx].f_fsize);
X            printf ("\tbsize:%ld \n", mntbufp [idx].f_bsize);
X# endif
X# if defined (HAS_GETMNTINFO_BSIZE)
X            printf ("\tbsize:%ld \n", mntbufp [idx].f_bsize);
X            printf ("\tiosize:%ld \n", mntbufp [idx].f_iosize);
X# endif
X            printf ("\tinodes: tot:%ld free:%ld\n",
X                    mntbufp [idx].f_files, mntbufp [idx].f_ffree);
X        }
X    }
X
X    free ((char *) mntbufp);
X    return 0;
X}
X
X/* this is a no-op; we have already done all the work */
Xstatic void
XgetDiskInfo ()
X{
X}
X
X#endif /* HAS_GETMNTINFO */
X
X#if defined (HAS_GETMNT)
X
X/*
X * getDiskEntries
X *
X * ULTRIX does this with a system call.  The system call allows one
X * to retrieve the information in a series of calls, but coding that
X * looks a little tricky; I just allocate a huge buffer and do it in
X * one shot.
X *
X *                  [mogul@wrl.dec.com (Jeffrey Mogul)]
X */
X
Xstatic int
XgetDiskEntries ()
X{
X    int             count;
X    int             bufsize;
X    int             idx;
X    short           fstype;
X    struct fs_data  *fsdbuf;
X    int             start;
X
X    bufsize = NMOUNT * sizeof (struct fs_data);  /* enough for max # mounts */
X    fsdbuf = (struct fs_data *) malloc (bufsize);
X    if (fsdbuf == (struct fs_data *) NULL)
X    {
X        fprintf (stderr, "malloc (%d) for getmnt () failed errno %d\n",
X                 bufsize, errno);
X        return -1;
X    }
X
X    start = 0;
X    count = getmnt (&start, fsdbuf, bufsize, STAT_MANY, 0);
X    if (count < 1)
X    {
X        fprintf (stderr, "Unable to do getmnt () [= %d] errno %d\n",
X                 count, errno);
X        free ((char *) fsdbuf);
X        return -1;
X    }
X
X    diCount = count;
X    diskInfo = (DiskInfo *) malloc (sizeof (DiskInfo) * count);
X    if (diskInfo == (DiskInfo *) NULL)
X    {
X        fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
X        free ((char *) fsdbuf);
X        return -1;
X    }
X    memset ((char *) diskInfo, '\0', sizeof (DiskInfo) * count);
X
X    for (idx = 0; idx < count; idx++)
X    {
X        diskInfo [idx].printFlag = DI_OK;
X        diskInfo [idx].isLocal = TRUE;
X
X        if ((fsdbuf [idx].fd_req.flags & M_LOCAL) != M_LOCAL)
X        {
X            diskInfo [idx].isLocal = FALSE;
X        }
X
X        if (diskInfo [i].isLocal == FALSE && (flags & F_LOCAL_ONLY) == F_LOCAL_ONLY)
X        {
X            diskInfo [i].printFlag = DI_IGNORE;
X        }
X
X        strncpy (diskInfo [idx].special, fsdbuf [idx].fd_devname, SPEC_NAME_LEN);
X        strncpy (diskInfo [idx].name, fsdbuf [idx].fd_path, NAME_LEN);
X
X            /* ULTRIX keeps these fields in units of 1K byte */
X        diskInfo [idx].totalBlocks = fsdbuf [idx].fd_btot;
X        diskInfo [idx].freeBlocks = fsdbuf [idx].fd_bfree;
X        diskInfo [idx].availBlocks = fsdbuf [idx].fd_bfreen;
X
X        diskInfo [idx].totalInodes = fsdbuf [idx].fd_gtot;
X        diskInfo [idx].freeInodes = fsdbuf [idx].fd_gfree;
X        diskInfo [idx].availInodes = fsdbuf [idx].fd_gfree;
X
X        fstype = fsdbuf [idx].fd_fstype;
X        if (fstype == GT_UNKWN)
X        {
X            diskInfo [idx].printFlag = DI_IGNORE;
X        }
X        else if ((fstype > 0) && (fstype < GT_NUMTYPES))
X        {
X            strncpy (diskInfo [idx].fsType, gt_names [fstype], TYPE_LEN);
X        }
X        else
X        {
X            sprintf (diskInfo [idx].fsType, "Unknown fstyp %.2d", fstype);
X        }
X
X        if (debug > 1)
X        {
X            printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType);
X            printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
X                    fsdbuf [idx].fd_btot, fsdbuf [idx].fd_bfree,
X                    fsdbuf [idx].fd_bfreen);
X            printf ("\tinodes: tot:%ld free:%ld\n",
X                    fsdbuf [idx].fd_gtot, fsdbuf [idx].fd_gfree);
X        }
X    }
X
X    free ((char *) fsdbuf);
X    return 0;
X}
X
X/* this is a no-op; we have already done all the work */
Xstatic void
XgetDiskInfo ()
X{
X}
X
X#endif /* HAS_GETMNT */
X
X
X#if defined (HAS_MNTCTL)
X
X/*
X * getDiskEntries
X *
X * AIX V3.2 uses mntctl to find out about mounted file systems
X *
X */
X
X# define NUM_AIX_FSTYPES         6
Xstatic char *AIX_fsType [NUM_AIX_FSTYPES] =
X    { "oaix", "", "nfs", "jfs", "", "cdrom" };
X
X/*
X * from xfsm-1.80:
X *
X * MNT_AIX - "aix"
X * MNT_NFS - "nfs"
X * MNT_JFS - "jfs"
X * MNT_CDROM - "cdrom"
X * other - "user defined"
X *
X */
X
Xstatic int
XgetDiskEntries ()
X{
X    int             num;        /* number of vmount structs returned    */
X    char            *vmbuf;     /* buffer for vmount structs returned   */
X    int             vmbufsz;    /* size in bytes of vmbuf               */
X    int             i;          /* index for looping and stuff          */
X    char            *bufp;      /* pointer into vmbuf                   */
X    vmt_p           *vmtp;      /* pointer into vmbuf                   */
X    struct vfs_ent  *ve;        /* pointer for file system type entry   */
X
X
X    i = 0;
X    vmbufsz = sizeof (struct vmount) * FSMAGIC; /* initial vmount buffer */
X
X    do
X    {
X        if ((vmbuf = (char *) malloc (vmbufsz)) == (char *) NULL)
X        {
X            fprintf (stderr, "malloc (%d) for mntctl() failed errno %d\n",
X                    vmbufsz, errno);
X            return -1;
X        }
X
X        num = mntctl (MCTL_QUERY, vmbufsz, vmbuf);
X            /*
X             * vmbuf is too small, could happen for
X             * following reasons:
X             * - inital buffer is too small
X             * - newly mounted file system
X             */
X        if (num == 0)
X        {
X            memcpy (&vmbufsz, vmbuf, sizeof (vmbufsz)); /* see mntctl(2) */
X            if (debug > 0)
X            {
X                printf ("vmbufsz too small, new size: %d\n", vmbufsz);
X            }
X            free ((char *) vmbuf); /* free this last, it's still being used! */
X            ++i;
X        }
X    } while (num == 0 && i < RETRY_COUNT);
X
X    if (i >= RETRY_COUNT)
X    {
X        free ((char *) vmbuf);
X        fprintf (stderr, "unable to allocate adequate buffer for mntctl\n");
X        return -1;
X    }
X
X    switch (num)
X    {
X            /* error happened, probably null vmbuf */
X        case -1:
X        {
X            free ((char *) vmbuf);
X            fprintf (stderr,"%s errno %d\n", strerror (errno), errno);
X            return -1;
X        }
X
X            /* 'num' vmount structs returned in vmbuf */
X        default:
X        {
X            diCount = num;
X            diskInfo = (DiskInfo *) calloc (sizeof (DiskInfo), diCount);
X            if (diskInfo == (DiskInfo *) NULL)
X            {
X                fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
X                return -1;
X            }
X
X            for (i = 0, bufp = vmbuf; i < num;
X                    i++, bufp += ((struct vmount*) bufp)->vmt_length)
X            {
X                vmtp = (vmt_p) bufp;
X                diskInfo [i].printFlag = DI_OK;
X                diskInfo [idx].isLocal = TRUE;
X
X                strncpy (diskInfo [i].special, vmt2dataptr (vmtp, VMT_OBJECT),
X                        SPEC_NAME_LEN);
X                strncpy (diskInfo [i].name, vmt2dataptr (vmtp, VMT_STUB),
X                        NAME_LEN);
X                ve = getvfsbytype (vmtp->vmt_gfstype);
X                if (ve == (struct vfs_ent *) NULL || *ve->vfsent_name == '\0')
X                {
X                    if (vmtp->vmt_gfstype >= 0 &&
X                            (vmtp->vmt_gfstype < NUM_AIX_FSTYPES)
X                    {
X                        strncpy (diskInfo [i].fsType,
X                                AIX_fsType [vmtp->vmt_gfstype], TYPE_LEN);
X                    }
X                }
X                else
X                {
X                    strncpy (diskInfo [i].fsType, ve->vfsent_name, TYPE_LEN);
X                }
X            }
X
X            if (debug > 0)
X            {
X                printf ("mnt:%s - %s : %s\n", diskInfo [i].name,
X                        diskInfo [i].special, diskInfo [i].fsType);
X                printf ("\t%s\n", vmt2dataptr (vmtp, VMT_ARGS));
X            }
X
X            break;
X        } /* valid value returned */
X    } /* switch on num */
X}
X
X#endif  /* HAS_MNTCTL */
X
X
X#if defined (HAS_STATVFS)
X
X/*
X * getDiskInfo
X *
X * SysV.4.  statvfs () returns both the free and available blocks.
X *
X */
X
Xstatic void
XgetDiskInfo ()
X{
X    int             i;
X    double          mult;
X    struct statvfs  statBuf;
X
X    for (i = 0; i < diCount; ++i)
X    {
X        if (diskInfo [i].isLocal == FALSE && (flags & F_LOCAL_ONLY) == F_LOCAL_ONLY)
X        {
X            diskInfo [i].printFlag = DI_IGNORE;
X        }
X
X        if (diskInfo [i].printFlag == DI_OK || (flags & F_ALL) == F_ALL)
X        {
X            if (statvfs (diskInfo [i].name, &statBuf) == 0)
X            {
X                    /* data general DG/UX 5.4R3.00 sometime returns 0   */
X                    /* in the fragment size field.                      */
X                if (statBuf.f_frsize == 0 && statBuf.f_bsize != 0)
X                {
X                    mult = (double) (long) statBuf.f_bsize / dispBlockSize;
X                }
X                else
X                {
X                    mult = (double) (long) statBuf.f_frsize / dispBlockSize;
X                }
X
X                diskInfo [i].totalBlocks = ((double) (long) statBuf.f_blocks * mult);
X                diskInfo [i].freeBlocks = ((double) (long) statBuf.f_bfree * mult);
X                diskInfo [i].availBlocks = ((double) (long) statBuf.f_bavail * mult);
X
X                diskInfo [i].totalInodes = statBuf.f_files;
X                diskInfo [i].freeInodes = statBuf.f_ffree;
X                diskInfo [i].availInodes = statBuf.f_favail;
X                strncpy (diskInfo [i].fsType, statBuf.f_basetype, TYPE_LEN);
X
X                if (debug > 1)
X                {
X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
X                    printf ("\tmult:%f\n", mult);
X                    printf ("\tbsize:%ld  frsize:%ld\n", statBuf.f_bsize,
X                            statBuf.f_frsize);
X                    printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
X                            statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail);
X                    printf ("\tinodes: tot:%ld free:%ld avail:%ld\n",
X                            statBuf.f_files, statBuf.f_ffree, statBuf.f_favail);
X                }
X            }
X            else
X            {
X                perror (diskInfo [i].name);
X            }
X        }
X    } /* for each entry */
X}
X
X#endif /* HAS_STATVFS */
X
X
X#if defined (HAS_STATFS)
X
X/*
X * getDiskInfo
X *
X * SunOS/BSD/Pyramid
X *
X */
X
Xstatic void
XgetDiskInfo ()
X{
X    int             i;
X    double          mult;
X    struct statfs   statBuf;
X
X    for (i = 0; i < diCount; ++i)
X    {
X        if (diskInfo [i].printFlag == DI_OK || (flags & F_ALL) == F_ALL)
X        {
X            if (statfs (diskInfo [i].name, &statBuf) == 0)
X            {
X                mult = (double) statBuf.f_bsize / dispBlockSize;
X                diskInfo [i].totalBlocks = ((double) statBuf.f_blocks * mult);
X                diskInfo [i].freeBlocks = ((double) statBuf.f_bfree * mult);
X                diskInfo [i].availBlocks = ((double) statBuf.f_bavail * mult);
X
X                diskInfo [i].totalInodes = statBuf.f_files;
X                diskInfo [i].freeInodes = statBuf.f_ffree;
X                diskInfo [i].availInodes = statBuf.f_ffree;
X# if defined (HAS_SYSFS)
X                sysfs (GETFSTYP, statBuf.f_fstyp, diskInfo [i].fsType);
X# endif
X
X                if (debug > 1)
X                {
X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
X                    printf ("\tmult:%f\n", mult);
X                    printf ("\tbsize:%ld\n", statBuf.f_bsize);
X                    printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
X                            statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail);
X                    printf ("\tinodes: tot:%ld free:%ld\n",
X                            statBuf.f_files, statBuf.f_ffree);
X                }
X            } /* if we got the info */
X            else
X            {
X                perror (diskInfo [i].name);
X            }
X        }
X    } /* for each entry */
X}
X
X#endif /* HAS_STATFS */
X
X#if defined (HAS_SYSV_STATFS)
X
X/*
X * getDiskInfo
X *
X * SysV.3.  We don't have available blocks; just set it to free blocks.
X * The sysfs () call is used to get the disk type name.
X *
X */
X
Xstatic void
XgetDiskInfo ()
X{
X    int             i;
X    double          mult;
X    struct statfs   statBuf;
X
X    for (i = 0; i < diCount; ++i)
X    {
X        if (diskInfo [i].printFlag == DI_OK || (flags & F_ALL) == F_ALL)
X        {
X            if (statfs (diskInfo [i].name, &statBuf, sizeof (statBuf), 0) == 0)
X            {
X                mult = (double) UBSIZE / dispBlockSize;
X                diskInfo [i].totalBlocks = ((double) statBuf.f_blocks * mult);
X                diskInfo [i].freeBlocks = ((double) statBuf.f_bfree * mult);
X                diskInfo [i].availBlocks = ((double) statBuf.f_bfree * mult);
X
X                diskInfo [i].totalInodes = statBuf.f_files;
X                diskInfo [i].freeInodes = statBuf.f_ffree;
X                diskInfo [i].availInodes = statBuf.f_ffree;
X# if defined (HAS_SYSFS)
X                sysfs (GETFSTYP, statBuf.f_fstyp, diskInfo [i].fsType);
X# endif
X
X                if (debug > 1)
X                {
X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
X                    printf ("\tmult:%f\n", mult);
X                    printf ("\tUBSIZE:%ld\n", UBSIZE);
X# if defined (HAS_FRSIZE)
X                    printf ("\tbsize:%ld\n", statBuf.f_bsize);
X                    printf ("\tfrsize:%ld\n", statBuf.f_frsize);
X# endif
X                    printf ("\tblocks: tot:%ld free:%ld\n",
X                            statBuf.f_blocks, statBuf.f_bfree);
X                    printf ("\tinodes: tot:%ld free:%ld\n",
X                            statBuf.f_files, statBuf.f_ffree);
X                }
X            } /* if we got the info */
X            else
X            {
X                perror (diskInfo [i].name);
X            }
X        }
X    } /* for each entry */
X}
X
X#endif /* HAS_SYSV_STATFS */
END_OF_FILE
if test 66204 -ne `wc -c <'di.c'`; then
    echo shar: \"'di.c'\" unpacked with wrong size!
fi
# end of 'di.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Until the next disk seek...
   -- Brad Lanam      bll@gentoo.com


