[comp.sources.misc] v05i068: Fsanalyze Version 4.1, Part 1/3

mjy@sdti.sdti.com (Michael J. Young) (12/07/88)

Posting-number: Volume 5, Issue 68
Submitted-by: "Michael J. Young" <mjy@sdti.sdti.com>
Archive-name: fsanalyze4.1/part01

This is a completely new version of fsanalyze, which I originally posted
almost a year ago.  Major changes were made to port it to BSD file systems,
as well to fix a number of bugs that were reported to me.  Unfortunately, it
is also a fair bit larger than the old version.

For those who don't remember the original program, fsanalyze is a tool that
measures file system fragmentation along with various other useful
file system statistics.

Please send comments, bug reports, fixes, and ideas for enhancements to me.

#! /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 3)."
# Contents:  Changes MANIFEST Makefile Mkfile.sun Mkfile.sys5
#   Mkfile.uport Mkfile.xenix README fragm.c fsanalyze.c patchlevel.h
#   stats.c util.c
# Wrapped by mjy@sdti on Wed Nov 30 15:54:13 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Changes -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Changes\"
else
echo shar: Extracting \"Changes\" \(5025 characters\)
sed "s/^X//" >Changes <<'END_OF_Changes'
XRevision History:
X
X   Version 2.0 was a major rewrite of fsanalyze that added the following new
X   features:
X       - The ability to analyze individual files
X       - Display of the 10 most fragmented files in a file system
X       - Enhanced error checking on the file system argument
X
X   Version 2.01 contains a minor modification in which fsanalyze executes
X   /etc/fsstat to determine the health of the file system before analyzing
X   it.
X
X   Version 2.02 contains a minor modification to print out a warning message
X   if the file system being analyzed is currently mounted.
X
X   Version 2.03 contains a fix for a minor bug in which the size of the
X   volume data block size would be printed out incorrectly for large
X   file systems.
X
X   Version 2.04 incorporates the library function l3tol to access inode
X   block numbers.  This is the first version that was posted to the net
X   a few months back.
X
X   Version 3.00 contains major revisions for porting to Xenix, System
X   V Release 3, and the BSD fast file system, as well as fixing many
X   bugs and improprieties.   Specific changes include:
X	- Sparse files are now handled correctly.  Thanks to John Limpert
X	  (johnl@gronk.uucp) for this one!
X	- A bug in the way indirect blocks were factored into the
X	  fragmentation analysis was corrected.
X	- Fragmentation has been re-defined as cylinder-to-cylinder seeks.
X	  Suboptimum placement within a cylinder is handled separately as
X	  "rotational delay".  This resulted from the discovery by a number
X	  of people (thanks esp. to Steve Paddock and Dave Olson
X	  (olson@altos86.uucp)) that block interleaving wasn't handled
X	  correctly.  After doing some experimenting with the System V mkfs,
X	  I came to the conclusion that its algorithm for optimal record
X	  placement is rather crude.  For example, it does not take number
X	  of heads into account.  So rather than enforce an algorithm that I
X	  couldn't duplicate very well anyway, I split it out as a separate
X	  statistic.  This decision was confirmed when I ported fsanalyze to
X	  BSD, since the fast file system also makes the distinction between
X	  cylinder seeks and rotation delays.
X        - new command-line arguments have been added to override file system
X          block size, interleave factor, and number of sectors per cylinder.
X          Normally, these numbers are derived from information in the super-
X          block.  However, not all file systems may store the information
X          in a way expected by fsanalyze.  Use these flags to override.
X          Although all of the flags are supported for the BSD port, I doubt
X          if they are useful.
X	- Some function names and variables have been renamed to
X	  ensure uniqueness within 7 characters.  Thanks to John
X	  Limpert for catching this.
X	- The IS_SPECIAL macro has been rewritten. Thanks to Larry
X	  Cipriani and Dave Olson for catching the bugs here.
X	- A number of new macros have been defined to make porting to
X	  BSD file systems easier.  These are described in the new file
X	  fsconfig.h.
X        - The relative cost of fragmentation is now reported as the average
X          distance of each seek (in number of cylinders).  This is reported
X          as an average for the entire file system, as well as for each file.
X        - Some files must span more than one cylinder simply because they are
X          too large.  Single-cylinder seeks due to size are ignored in the
X          fragmentation calculation.
X        - A makefile has been created to enhance portability.  The
X          makefile contains instructions for configuration of fsanalyze.
X
X   Release 3.01 contains a few simple changes to enhance portability to
X   XENIX/286, and adds the NUMOFFEND configuration parameter, which
X   determines how many of the "top offender" (most fragmented) files
X   are reported.
X
X   Release 3.02 changes the rotation delay algorithm slightly to more closely
X   reflect the BSD placement algorigthm.  I still don't trust the results,
X   since they are non-intuitive, and always too high for what I would expect
X   from BSD.  The other major change is the addition of a "wasted space"
X   metric which reports unuseable space due to partial use of the last block
X   of each file.
X
X   Release 3.03 reports the total number of blocks used for indirection (and
X   thus unavailable for data).  I also made more changes to the rotation
X   delay algorithm, providing a formula for BSD Opt_interleave that makes
X   more sense than previous versions.  The results still seem a bit too
X   high, but they're more reasonable than before.  This version also
X   includes a complete code re-organization which makes it easier to pack
X   into shell archives, and some other general cleanup in preparation for
X   posting to Usenet.
X
X   Release 3.04 contains minor changes to avoid namespace conflicts in the
X   FS_TYPE and OS_TYPE macros.  NFS support is also disassociated with the
X   OS_TYPE.
X
X   Release 4.1 contains no major changes from 3.04, but resulted from
X   placing the code under SCCS.
END_OF_Changes
if test 5025 -ne `wc -c <Changes`; then
    echo shar: \"Changes\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(1115 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X Changes                   1		Revision History
X Info                      2		Useful information on interpreting
X					results
X MANIFEST                  1		This file...
X Makefile                  1		Guess.
X Mkfile.sun                1		Makefile for Suns
X Mkfile.sys5               1		Makefile for generic System V
X Mkfile.uport              1		Makefile for Microport System V/AT
X Mkfile.xenix              1		Makefile for XENIX/286
X README                    1		Useful information
X chkfile.c                 3		File Scanner
X fragm.c                   1		Fragmentation heuristics
X fsanalyze.8               2		Manual page
X fsanalyze.c               1		main()
X fsanalyze.h               2		Global declarations
X fsconfig.h                3		System-dependent declarations
X init.c                    2		System initialization
X patchlevel.h              1		Current patch level
X report.c                  2		Print report
X stats.c                   1		Statistics maintenance
X util.c                    1		Inode-related utilities
END_OF_MANIFEST
if test 1115 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(2425 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X
X##
X## FSANALYZE makefile
X## Version  : 4.1 - 88/11/16 17:27:40
X
X## One of the things FSANALYZE displays is a list of the most fragmented
X## files.  OFFEND determines how many of those files to report.
X## The report is in double column format, so the number should be divisible
X## by 2.  Ideally, this number should be set so that the report fits on
X## a single screen.  For a 24-line display, the suggested number is 10,
X## which is the default.
XOFFEND = 10
X
X## File System type - Use the first definition for derivatives of the old
X## AT&T file system, including Version 7, System III, and System V
X## releases 2 and 3, and XENIX.  Use the second definition for derivatives
X## of the BSD Fast File system without NFS.  If NFS support is also included,
X## use the third definition.
XFS = FS_ATT
X#FS = FS_BSD
X#FS = FS_BSD_NFS
X
X## Operating system type - This definition is used for OS-dependencies within
X## a given file system.  Use OS_ATT or OS_BSD if none of the other definitions
X## apply.
X#OS = OS_ATT
X#OS = OS_BSD
XOS  = OS_UPORT_286 # Microport System V/AT (286-based - use _ATT for /386)
X#OS = OS_XENIX_286 # XENIX/286 (use _ATT for XENIX/386)
X
X## Uncomment the next line if you have the fsstat(1) command.  Note that if
X## you are installing fsanalyze on a Microport System V/AT, this command
X## should be uncommented, since the is_ok macro as defined in fsconfig.h
X## will not work.
XFSSTAT = -DHAVE_FSSTAT
X
X## Where the executable should be placed...
XDESTDIR = /etc/local
X
X## Where the man file should be placed...
XMANDIR = /usr/man/man8
X
XCONFIG_FLGS = -DFS_TYPE=$(FS) -DOS_TYPE=$(OS) -DNUMOFFEND=$(OFFEND) $(FSSTAT)
X
X## edit as appropriate...
XCFLAGS = -O $(CONFIG_FLGS)
XLDFLAGS = 
X
XOBJS = fsanalyze.o chkfile.o fragm.o init.o report.o stats.o util.o
XSRCS = fsanalyze.c chkfile.c fragm.c init.c report.c stats.c util.c
X
Xfsanalyze:	$(OBJS)
X	$(CC) $(LDFLAGS) -o fsanalyze $(OBJS)
X
Xinstall: fsanalyze manual
X	mv fsanalyze $(DESTDIR)
X	chmod 755 $(DESTDIR)/fsanalyze
X
Xclean:
X	rm *.o fsanalyze
X
Xlint:	$(SRCS) fsconfig.h fsanalyze.h
X	lint -D_FS_TYPE=$(FS) -D_OS_TYPE=$(OS) $(FSSTAT) -p $(SRCS)
X
Xmanual:	fsanalyze.8
X	cp fsanalyze.8 $(MANDIR)
X	chmod 444 $(MANDIR)/fsanalyze.8
X
Xchkfile.o : fsconfig.h fsanalyze.h
Xfragm.o : fsconfig.h fsanalyze.h
Xfsanalyze.o : fsconfig.h fsanalyze.h
Xinit.o : fsconfig.h fsanalyze.h patchlevel.h
Xreport.o : fsconfig.h fsanalyze.h
Xstats.o : fsconfig.h fsanalyze.h
Xutil.o : fsconfig.h fsanalyze.h
END_OF_Makefile
if test 2425 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Mkfile.sun -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Mkfile.sun\"
else
echo shar: Extracting \"Mkfile.sun\" \(2474 characters\)
sed "s/^X//" >Mkfile.sun <<'END_OF_Mkfile.sun'
X## @(#)$Id: Mkfile.sun, V4.1 88/11/16 17:27:58 $
X##
X## FSANALYZE makefile
X## Version  : 4.1 - 88/11/16 17:27:58
X
X## One of the things FSANALYZE displays is a list of the most fragmented
X## files.  OFFEND determines how many of those files to report.
X## The report is in double column format, so the number should be divisible
X## by 2.  Ideally, this number should be set so that the report fits on
X## a single screen.  For a 24-line display, the suggested number is 10,
X## which is the default.
XOFFEND = 10
X
X## File System type - Use the first definition for derivatives of the old
X## AT&T file system, including Version 7, System III, and System V
X## releases 2 and 3, and XENIX.  Use the second definition for derivatives
X## of the BSD Fast File system without NFS.  If NFS support is also included,
X## use the third definition.
X#FS = FS_ATT
X#FS = FS_BSD
XFS = FS_BSD_NFS
X
X## Operating system type - This definition is used for OS-dependencies within
X## a given file system.  Use OS_ATT or OS_BSD if none of the other definitions
X## apply.
X#OS = OS_ATT
XOS = OS_BSD
X#OS  = OS_UPORT_286 # Microport System V/AT (286-based - use _ATT for /386)
X#OS = OS_XENIX_286 # XENIX/286 (use _ATT for XENIX/386)
X
X## Uncomment the next line if you have the fsstat(1) command.  Note that if
X## you are installing fsanalyze on a Microport System V/AT, this command
X## should be uncommented, since the is_ok macro as defined in fsconfig.h
X## will not work.
X#FSSTAT = -DHAVE_FSSTAT
X
X## Where the executable should be placed...
XDESTDIR = /etc/local
X
X## Where the man file should be placed...
XMANDIR = /usr/man/man8
X
XCONFIG_FLGS = -DFS_TYPE=$(FS) -DOS_TYPE=$(OS) -DNUMOFFEND=$(OFFEND) $(FSSTAT)
X
X## edit as appropriate...
XCFLAGS = -O $(CONFIG_FLGS)
XLDFLAGS = 
X
XOBJS = fsanalyze.o chkfile.o fragm.o init.o report.o stats.o util.o
XSRCS = fsanalyze.c chkfile.c fragm.c init.c report.c stats.c util.c
X
Xfsanalyze:	$(OBJS)
X	$(CC) $(LDFLAGS) -o fsanalyze $(OBJS)
X
Xinstall: fsanalyze manual
X	mv fsanalyze $(DESTDIR)
X	chmod 755 $(DESTDIR)/fsanalyze
X
Xclean:
X	rm *.o fsanalyze
X
Xlint:	$(SRCS) fsconfig.h fsanalyze.h
X	lint -D_FS_TYPE=$(FS) -D_OS_TYPE=$(OS) $(FSSTAT) -p $(SRCS)
X
Xmanual:	fsanalyze.8
X	cp fsanalyze.8 $(MANDIR)
X	chmod 444 $(MANDIR)/fsanalyze.8
X
Xchkfile.o : fsconfig.h fsanalyze.h
Xfragm.o : fsconfig.h fsanalyze.h
Xfsanalyze.o : fsconfig.h fsanalyze.h
Xinit.o : fsconfig.h fsanalyze.h patchlevel.h
Xreport.o : fsconfig.h fsanalyze.h
Xstats.o : fsconfig.h fsanalyze.h
Xutil.o : fsconfig.h fsanalyze.h
END_OF_Mkfile.sun
if test 2474 -ne `wc -c <Mkfile.sun`; then
    echo shar: \"Mkfile.sun\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Mkfile.sys5 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Mkfile.sys5\"
else
echo shar: Extracting \"Mkfile.sys5\" \(2474 characters\)
sed "s/^X//" >Mkfile.sys5 <<'END_OF_Mkfile.sys5'
X## @(#)$Id: Mkfile.sys5, V4.1 88/11/16 17:28:35 $
X##
X## FSANALYZE makefile
X## Version  : 4.1 - 88/11/16 17:28:35
X
X## One of the things FSANALYZE displays is a list of the most fragmented
X## files.  OFFEND determines how many of those files to report.
X## The report is in double column format, so the number should be divisible
X## by 2.  Ideally, this number should be set so that the report fits on
X## a single screen.  For a 24-line display, the suggested number is 10,
X## which is the default.
XOFFEND = 10
X
X## File System type - Use the first definition for derivatives of the old
X## AT&T file system, including Version 7, System III, and System V
X## releases 2 and 3, and XENIX.  Use the second definition for derivatives
X## of the BSD Fast File system without NFS.  If NFS support is also included,
X## use the third definition.
XFS = FS_ATT
X#FS = FS_BSD
X#FS = FS_BSD_NFS
X
X## Operating system type - This definition is used for OS-dependencies within
X## a given file system.  Use OS_ATT or OS_BSD if none of the other definitions
X## apply.
XOS = OS_ATT
X#OS = OS_BSD
X#OS = OS_UPORT_286 # Microport System V/AT (286-based - use _ATT for /386)
X#OS = OS_XENIX_286 # XENIX/286 (use _ATT for XENIX/386)
X
X## Uncomment the next line if you have the fsstat(1) command.  Note that if
X## you are installing fsanalyze on a Microport System V/AT, this command
X## should be uncommented, since the is_ok macro as defined in fsconfig.h
X## will not work.
X#FSSTAT = -DHAVE_FSSTAT
X
X## Where the executable should be placed...
XDESTDIR = /etc/local
X
X## Where the man file should be placed...
XMANDIR = /usr/man/man8
X
XCONFIG_FLGS = -DFS_TYPE=$(FS) -DOS_TYPE=$(OS) -DNUMOFFEND=$(OFFEND) $(FSSTAT)
X
X## edit as appropriate...
XCFLAGS = -O $(CONFIG_FLGS)
XLDFLAGS = 
X
XOBJS = fsanalyze.o chkfile.o fragm.o init.o report.o stats.o util.o
XSRCS = fsanalyze.c chkfile.c fragm.c init.c report.c stats.c util.c
X
Xfsanalyze:	$(OBJS)
X	$(CC) $(LDFLAGS) -o fsanalyze $(OBJS)
X
Xinstall: fsanalyze manual
X	mv fsanalyze $(DESTDIR)
X	chmod 755 $(DESTDIR)/fsanalyze
X
Xclean:
X	rm *.o fsanalyze
X
Xlint:	$(SRCS) fsconfig.h fsanalyze.h
X	lint -D_FS_TYPE=$(FS) -D_OS_TYPE=$(OS) $(FSSTAT) -p $(SRCS)
X
Xmanual:	fsanalyze.8
X	cp fsanalyze.8 $(MANDIR)
X	chmod 444 $(MANDIR)/fsanalyze.8
X
Xchkfile.o : fsconfig.h fsanalyze.h
Xfragm.o : fsconfig.h fsanalyze.h
Xfsanalyze.o : fsconfig.h fsanalyze.h
Xinit.o : fsconfig.h fsanalyze.h patchlevel.h
Xreport.o : fsconfig.h fsanalyze.h
Xstats.o : fsconfig.h fsanalyze.h
Xutil.o : fsconfig.h fsanalyze.h
END_OF_Mkfile.sys5
if test 2474 -ne `wc -c <Mkfile.sys5`; then
    echo shar: \"Mkfile.sys5\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Mkfile.uport -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Mkfile.uport\"
else
echo shar: Extracting \"Mkfile.uport\" \(2475 characters\)
sed "s/^X//" >Mkfile.uport <<'END_OF_Mkfile.uport'
X## @(#)$Id: Mkfile.uport, V4.1 88/11/16 17:28:47 $
X##
X## FSANALYZE makefile
X## Version  : 4.1 - 88/11/16 17:28:47
X
X## One of the things FSANALYZE displays is a list of the most fragmented
X## files.  OFFEND determines how many of those files to report.
X## The report is in double column format, so the number should be divisible
X## by 2.  Ideally, this number should be set so that the report fits on
X## a single screen.  For a 24-line display, the suggested number is 10,
X## which is the default.
XOFFEND = 10
X
X## File System type - Use the first definition for derivatives of the old
X## AT&T file system, including Version 7, System III, and System V
X## releases 2 and 3, and XENIX.  Use the second definition for derivatives
X## of the BSD Fast File system without NFS.  If NFS support is also included,
X## use the third definition.
XFS = FS_ATT
X#FS = FS_BSD
X#FS = FS_BSD_NFS
X
X## Operating system type - This definition is used for OS-dependencies within
X## a given file system.  Use OS_ATT or OS_BSD if none of the other definitions
X## apply.
X#OS = OS_ATT
X#OS = OS_BSD
XOS  = OS_UPORT_286 # Microport System V/AT (286-based - use _ATT for /386)
X#OS = OS_XENIX_286 # XENIX/286 (use _ATT for XENIX/386)
X
X## Uncomment the next line if you have the fsstat(1) command.  Note that if
X## you are installing fsanalyze on a Microport System V/AT, this command
X## should be uncommented, since the is_ok macro as defined in fsconfig.h
X## will not work.
XFSSTAT = -DHAVE_FSSTAT
X
X## Where the executable should be placed...
XDESTDIR = /etc/local
X
X## Where the man file should be placed...
XMANDIR = /usr/man/man8
X
XCONFIG_FLGS = -DFS_TYPE=$(FS) -DOS_TYPE=$(OS) -DNUMOFFEND=$(OFFEND) $(FSSTAT)
X
X## edit as appropriate...
XCFLAGS = -O $(CONFIG_FLGS)
XLDFLAGS = 
X
XOBJS = fsanalyze.o chkfile.o fragm.o init.o report.o stats.o util.o
XSRCS = fsanalyze.c chkfile.c fragm.c init.c report.c stats.c util.c
X
Xfsanalyze:	$(OBJS)
X	$(CC) $(LDFLAGS) -o fsanalyze $(OBJS)
X
Xinstall: fsanalyze manual
X	mv fsanalyze $(DESTDIR)
X	chmod 755 $(DESTDIR)/fsanalyze
X
Xclean:
X	rm *.o fsanalyze
X
Xlint:	$(SRCS) fsconfig.h fsanalyze.h
X	lint -D_FS_TYPE=$(FS) -D_OS_TYPE=$(OS) $(FSSTAT) -p $(SRCS)
X
Xmanual:	fsanalyze.8
X	cp fsanalyze.8 $(MANDIR)
X	chmod 444 $(MANDIR)/fsanalyze.8
X
Xchkfile.o : fsconfig.h fsanalyze.h
Xfragm.o : fsconfig.h fsanalyze.h
Xfsanalyze.o : fsconfig.h fsanalyze.h
Xinit.o : fsconfig.h fsanalyze.h patchlevel.h
Xreport.o : fsconfig.h fsanalyze.h
Xstats.o : fsconfig.h fsanalyze.h
Xutil.o : fsconfig.h fsanalyze.h
END_OF_Mkfile.uport
if test 2475 -ne `wc -c <Mkfile.uport`; then
    echo shar: \"Mkfile.uport\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Mkfile.xenix -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Mkfile.xenix\"
else
echo shar: Extracting \"Mkfile.xenix\" \(2476 characters\)
sed "s/^X//" >Mkfile.xenix <<'END_OF_Mkfile.xenix'
X## @(#)$Id: Mkfile.xenix, V4.1 88/11/16 17:29:01 $
X##
X## FSANALYZE makefile
X## Version  : 4.1 - 88/11/16 17:29:01
X
X## One of the things FSANALYZE displays is a list of the most fragmented
X## files.  OFFEND determines how many of those files to report.
X## The report is in double column format, so the number should be divisible
X## by 2.  Ideally, this number should be set so that the report fits on
X## a single screen.  For a 24-line display, the suggested number is 10,
X## which is the default.
XOFFEND = 10
X
X## File System type - Use the first definition for derivatives of the old
X## AT&T file system, including Version 7, System III, and System V
X## releases 2 and 3, and XENIX.  Use the second definition for derivatives
X## of the BSD Fast File system without NFS.  If NFS support is also included,
X## use the third definition.
XFS = FS_ATT
X#FS = FS_BSD
X#FS = FS_BSD_NFS
X
X## Operating system type - This definition is used for OS-dependencies within
X## a given file system.  Use OS_ATT or OS_BSD if none of the other definitions
X## apply.
X#OS = OS_ATT
X#OS = OS_BSD
X#OS  = OS_UPORT_286 # Microport System V/AT (286-based - use _ATT for /386)
XOS = OS_XENIX_286 # XENIX/286 (use _ATT for XENIX/386)
X
X## Uncomment the next line if you have the fsstat(1) command.  Note that if
X## you are installing fsanalyze on a Microport System V/AT, this command
X## should be uncommented, since the is_ok macro as defined in fsconfig.h
X## will not work.
X#FSSTAT = -DHAVE_FSSTAT
X
X## Where the executable should be placed...
XDESTDIR = /etc/local
X
X## Where the man file should be placed...
XMANDIR = /usr/man/man8
X
XCONFIG_FLGS = -DFS_TYPE=$(FS) -DOS_TYPE=$(OS) -DNUMOFFEND=$(OFFEND) $(FSSTAT)
X
X## edit as appropriate...
XCFLAGS = -O $(CONFIG_FLGS)
XLDFLAGS = 
X
XOBJS = fsanalyze.o chkfile.o fragm.o init.o report.o stats.o util.o
XSRCS = fsanalyze.c chkfile.c fragm.c init.c report.c stats.c util.c
X
Xfsanalyze:	$(OBJS)
X	$(CC) $(LDFLAGS) -o fsanalyze $(OBJS)
X
Xinstall: fsanalyze manual
X	mv fsanalyze $(DESTDIR)
X	chmod 755 $(DESTDIR)/fsanalyze
X
Xclean:
X	rm *.o fsanalyze
X
Xlint:	$(SRCS) fsconfig.h fsanalyze.h
X	lint -D_FS_TYPE=$(FS) -D_OS_TYPE=$(OS) $(FSSTAT) -p $(SRCS)
X
Xmanual:	fsanalyze.8
X	cp fsanalyze.8 $(MANDIR)
X	chmod 444 $(MANDIR)/fsanalyze.8
X
Xchkfile.o : fsconfig.h fsanalyze.h
Xfragm.o : fsconfig.h fsanalyze.h
Xfsanalyze.o : fsconfig.h fsanalyze.h
Xinit.o : fsconfig.h fsanalyze.h patchlevel.h
Xreport.o : fsconfig.h fsanalyze.h
Xstats.o : fsconfig.h fsanalyze.h
Xutil.o : fsconfig.h fsanalyze.h
END_OF_Mkfile.xenix
if test 2476 -ne `wc -c <Mkfile.xenix`; then
    echo shar: \"Mkfile.xenix\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(6616 characters\)
sed "s/^X//" >README <<'END_OF_README'
XFSANALYZE - File System Analyzer tool
XVersion  : 4.1.1.2 - 88/11/30 15:53:38
X
XAuthor   : Michael J. Young
XUSmail   : Software Development Technologies, Inc.
X           375 Dutton Rd
X           Sudbury MA  01776
XUUCP     : harvard!sdti!mjy
XInternet : mjy@sdti.SDTI.COM
X
X   =========================================================================
X   Note : This program has been placed in the public domain to permit
X   unrestricted distribution and use.  I have placed no copyright on it, but
X   I request that you keep me informed about any enhancements and bug fixes
X   you make so I can keep an up-to-date copy for further distribution.
X   =========================================================================
X
X   This is a completely new version of fsanalyze which contains a number of
X   bug fixes, new features, and enhanced portability.  This version of
X   fsanalyze has been ported to the BSD fast file system, and run
X   successfully on a Sun.  It has also run successfully under Ultrix,
X   but some changes may be needed in the #include directives in
X   the file "fsanalyze.h".
X
X   For a complete revision history, see the file called "Changes".  Other
X   useful information may be found in the file called "Info".
X
XIntroduction:
X   Fsanalyze is a simple tool that estimates file system fragmentation.  It
X   accomplishes this by scanning the data blocks for each i-node in the 
X   file system, looking for block numbers that are out of sequence.  In
X   effect, it is counting the number of disk seeks required to read the
X   entire file in sequence.  Fragmentation is then computed as the ratio
X   of actual "seeks" to the potential number of "seeks" if the file were
X   completely fragmented.
X
X   Fsanalyze also provides a number of other useful statistics regarding the
X   file system usage, including the number (and identity) of files that are
X   very large, sparse files, and excessively large directories (i.e.,
X   directory files that require data block indirection, making filename
X   searches very inefficient).
X   
X   After the general file system statistics are displayed, fsanalyze lists
X   the 10 most fragmented i-nodes in the file system.  The 10 most
X   fragmented files are listed in decreasing order of fragmentation based on
X   the absolute number of fragments.  For example, a 100-block file that
X   contains 40 individual fragments is 39.39% fragmented (39 seeks / 99
X   potential seeks), but is listed before a 2-block file that contains 2
X   fragments (100% fragmented).  Thus, larger fragmented files (which have a
X   greater effect on file system performance) are listed before small files.
X
X   In my estimation fsanalyze is completely safe, since it never writes to
X   the file system that it is analyzing and uses only the standard I/O
X   library to do its work.  It should be possible to run fsanalyze on a
X   write-protected file system, if you're worried.  If anything should go
X   wrong, the worst you will see is fseek() errors.  Be that as it may,
X   however, there is no express or implied warrantee as to safety or
X   accuracy of the results.  Use at your own risk.
X
XInstallation:
X
X   For most systems, installing fsanalyze should consist simply of editing
X   the Makefile and running make.  The Makefile is self-documenting (yeah,
X   I know, I know!).  For convenience, I've included a number of different
X   Makefiles that are configured for various systems.  Ultrix users should
X   be able to use the Sun version with no changes.
X
X   Note that for Microport System V/AT systems, HAVE_FSSTAT should be
X   defined, since the is_ok(fs) macro defined in fsanalyze.h will not work.
X
X   Where fsanalyze is installed doesn't really matter, but I would recommend
X   placing it somewhere in the root filesystem, which is always mounted.  I
X   typically run fsanalyze during my backup procedure, while my other
X   filesystems are unmounted.
X
X   Fsanalyze is not a setuid program, so the user must have read access to
X   the file system to be analyzed.  I run it as root for this reason, but
X   if you're paranoid, it would be better just run it in the same group
X   as the the file systems (sys on my system).
X
XUsage:
X   fsanalyze [-flags] special [file [...]]
X
X   If the optional file arguments are missing, the entire file system
X   is analyzed.  If present, the specified files are analyzed and reported
X   individually.
X
X   [flags] include the following:
X     b#  assume '#' bytes per logical block -- by default, this value
X         is calculated automatically.  Supported, but not useful, for
X         BSD file systems.
X     c#  assume '#' sectors per disk cylinder -- by default,
X         this value is determined by information in the superblock.
X     d   display i-node numbers as they are examined.
X     e   report file size inconsistencies - the inode numbers are reported
X         for files where the file size and number of data blocks are
X         inconsistent.
X     g#  assume an inter-block gap of '#' sectors -- by
X         default this information is taken from the superblock. Not
X         useful, for BSD file systems.
X     i   report double and triple indirection - the inode numbers are
X         reported for files that contain double and/or triple indirection.
X     o   overrides error checking on file system.  Use this flag if the
X         file system you are analyzing is damaged.  Note that fsanalyze
X         may give erroneous results if used on a damaged file system, but
X         the file system itself will not be modified.
X     v   Display current version number and patch level.
X
X   Example:
X     fsanalyze /dev/dsk/0s2	/* analyzes an entire file system */
X     fsanalyze /dev/dsk/0s2 *	/* analyzes all files in the current
X                                 * directory of the file system */
X
X   Since fsanalyze uses the superblock info ON THE DISK, more accurate
X   results will be returned fsanalyze is run on an unmounted, or read-only
X   mounted file system.
X
X   Since fsanalyze does its work the old fashioned way (brute-force), it
X   must scan through the file system inode by inode.  It therefore takes
X   a while to finish.  Be patient.
X
XBugs:
X   Please report any bugs (and possible fixes) to me, so I can keep my
X   source up-to-date.  I'm sure there are plenty of bugs, especially in the
X   BSD-specific stuff.  Since I don't have access to anything but my little 
X   Microport System V/AT system, it's hard for me to find portability bugs.
X
X   Known Bugs include:
X      1.  I don't trust the rotation delay statistics, especially for
X          BSD file systems.  The numbers seem to be much too high to be
X          believable.
END_OF_README
if test 6616 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fragm.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fragm.c\"
else
echo shar: Extracting \"fragm.c\" \(4443 characters\)
sed "s/^X//" >fragm.c <<'END_OF_fragm.c'
Xstatic char sccsid[] = "@(#)$Id: fragm.c, V4.1 88/11/16 17:29:42 $";
X
X/*
X * fragm.c - fragmentation analysis
X * Version  : 4.1 - 88/11/16 17:29:42
X *
X * Author   : Michael J. Young
X * USmail   : Software Development Technologies, Inc.
X *            375 Dutton Rd
X *            Sudbury MA 01776
X * UUCP     : harvard!sdti!mjy
X * Internet : mjy@sdti.SDTI.COM
X *
X * =========================================================================
X * Note : This program has been placed in the public domain to permit
X * unrestricted distribution and use.  I have placed no copyright on it, but
X * I request that you keep me informed about any enhancements and bug fixes
X * you make so I can keep an up-to-date copy for further distribution.
X *
X * This program is being provided "as is", with no warrantee as to safety or
X * accuracy of results.  Use at your own risk.
X * =========================================================================
X */
X
X/*
X * Modification History:
X *
X * Thu Jul 28 15:57:32 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Extracted from fsanalyze.c
X *
X * Mon Aug 08 11:27:39 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Revised OS_TYPE and FS_TYPE macros to avoid name-space conflicts
X *
X * Wed Nov 16 11:31:32 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Placed under SCCS
X */
X
X/*
X * Include files
X */
X#include "fsconfig.h"
X#include "fsanalyze.h"
X
X/*
X * must_seek : returns true if the two data blocks reside on different
X * disk cylinders.
X */
Xboolean must_seek (new_block, old_block)
Xdaddr_t new_block;            /* next data block */
Xdaddr_t old_block;            /* previous data block */
X{
X    daddr_t old_cyl;          /* base block of current cylinder */
X    daddr_t new_cyl;          /* base block of new cylinder */
X
X    old_cyl = cylinder (fil_sys, old_block);
X    new_cyl = cylinder (fil_sys, new_block);
X
X    return (old_cyl != new_cyl);
X    }
X
X/*
X * rotate_delay : returns true if the new data block is within the same
X * cylinder, but is not at the optimum position within the cylinder
X */
Xboolean rot_delay (new_block, old_block)
Xdaddr_t new_block;            /* next data block */
Xdaddr_t old_block;            /* previous data block */
X{
X    daddr_t old_off;          /* cylinder offset of current block */
X    daddr_t new_off;          /* cylinder offset of next block */
X
X    old_off = cyl_pos (fil_sys, old_block);
X    new_off = cyl_pos (fil_sys, new_block);
X
X    return ((new_off != old_off + interleave) &&
X        (new_off != (old_off + interleave) % cyl_size) &&
X        (new_block != old_block + 1));
X    }
X
X/*
X * seek_dist : returns the number of cylinders that must be traversed
X * to get from blk2 to blk1.
X */
Xlong seek_dist (blk1, blk2)
Xdaddr_t blk1;                       /* new block */
Xdaddr_t blk2;                       /* previous block */
X{
X    daddr_t cyl1;          /* base block of current cylinder */
X    daddr_t cyl2;          /* base block of new cylinder */
X
X    cyl1 = cylinder (fil_sys, blk1);
X    cyl2 = cylinder (fil_sys, blk2);
X
X    return diff (cyl1, cyl2);
X    }
X
X/*
X * minimum_seeks : returns the number of cylinders that the file spans just
X * by virtue of its size.  Any single-cylinder seeks due to the sheer size
X * of the file will be ignored in the fragmentation calculation.
X */
Xlong minimum_seeks (file_size)
Xoff_t file_size;                   /* size of file from inode entry */
X{
X    off_t bytes_per_cyl;
X
X    bytes_per_cyl = (off_t)cyl_size * DEV_BSIZE;
X    return (file_size / bytes_per_cyl);
X    }
X
X/*
X * test_fragmentation : determines whether or not the two specified blocks
X * indicate that fragmentation has occurred.  Disk seeks that are required
X * due to the sheer size of the file are ignored in the calculation.  If
X * no disk seeks are required, a heuristic is used to determine if the
X * data blocks are optimally placed within the cylinder.
X */
Xvoid test_fragmentation (new_pos, old_pos, data)
Xdaddr_t new_pos;                 /* new block number */
Xdaddr_t old_pos;                 /* original block */
Xstruct file_data *data;          /* file statistics data structure */
X{
X    data->potential_seeks++;
X    if (must_seek (new_pos, old_pos)){
X	if (data->min_cost && seek_dist (new_pos, old_pos) == 1){
X            data->min_cost--;
X	    }
X        else {
X            data->cost += seek_dist (new_pos, old_pos);
X            data->seeks++;
X	    }
X        }
X    else if (rot_delay (new_pos, old_pos)){
X        data->rotates++;
X        }
X    }
X
END_OF_fragm.c
if test 4443 -ne `wc -c <fragm.c`; then
    echo shar: \"fragm.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fsanalyze.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fsanalyze.c\"
else
echo shar: Extracting \"fsanalyze.c\" \(6212 characters\)
sed "s/^X//" >fsanalyze.c <<'END_OF_fsanalyze.c'
Xstatic char sccsid[] = "@(#)$Id: fsanalyze.c, V4.1 88/11/16 17:30:08 $";
X
X/*
X * fsanalyze.c - file system analyzer
X * Version  : 4.1 - 88/11/16 17:30:08
X *
X * Author   : Michael J. Young
X * USmail   : Software Development Technologies, Inc.
X *            375 Dutton Rd
X *            Sudbury MA 01776
X * UUCP     : harvard!sdti!mjy
X * Internet : mjy@sdti.SDTI.COM
X *
X * =========================================================================
X * Note : This program has been placed in the public domain to permit
X * unrestricted distribution and use.  I have placed no copyright on it, but
X * I request that you keep me informed about any enhancements and bug fixes
X * you make so I can keep an up-to-date copy for further distribution.
X *
X * This program is being provided "as is", with no warrantee as to safety or
X * accuracy of results.  Use at your own risk.
X * =========================================================================
X */
X
X/*
X * Modification History:
X *
X *    Date       Author                   Description
X * -----------  --------  -----------------------------------------------
X * 28 Jul 1987    MJY       Originated
X *  5 Oct 1987    MJY       Capability to analyze individual files,
X *                          Added error checking to file system argument,
X *                          Added -o flag
X *                          Prints out volume and file system name in summary
X * 12 Oct 1987    MJY       Use /etc/fsstat to do file system validity
X *                          checking
X *  9 Nov 1987    MJY       print out warning if file system is mounted
X * 12 Nov 1987    MJY       Volume size statistics now long instead of int
X *  7 Jan 1988    MJY       Modified blk_no() to use l3tol()
X *
X * Wed Mar  9 17:51:38 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Rewrite for portability between various versions of System V, esp.
X *    SCO XENIX and 5.3 systems.  First (incomplete) attempt at porting
X *    to BSD 4.3.  See README for details.
X *
X * Thu Apr  7 10:03:21 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Seeks for files that span cylinders due to their sheer size are
X *    ignored.  Average seek distance is now reported.
X *
X * Wed Apr 13 17:33:03 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Completed port to BSD.  Fixed bug in inode numbering for BSD.
X *    Symbolic links now handled correctly for individual files.
X *
X * Wed Jun 15 14:08:30 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Number of top offenders is now a configurable parameter via the
X *    NUMOFFEND macro in fsconfig.h.
X *
X * Fri Jun 24 16:22:10 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Make top offender size report consistent with anal_file reports.
X *
X * Tue Jul 26 15:24:30 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Added wasted space metric
X *    Modified BSD rotation delay algorithm
X *
X * Thu Jul 28 16:15:22 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Opt_interleave() formula now makes sense
X *    Re-organized code and general cleanup in preparation for posting.
X *
X * Mon Aug 08 11:27:39 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Revised OS_TYPE and FS_TYPE macros to avoid name-space conflicts
X *
X * Wed Nov 16 11:31:32 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Placed under SCCS
X */
X
X/*
X * Include files
X */
X#include "fsconfig.h"
X#include "fsanalyze.h"
X
X/***************************************************************************
X *                           Global Variables                              *
X ***************************************************************************/
X
X/*
X * interface to system error messages
X */
Xextern char *sys_errlist[];
Xextern int sys_nerr;
X
X/*
X * error : performs a function similar to perror(3), but supports variable
X * argument lists.  Prints out a formatted error string to stderr, followed if
X * possible by an appropriate system error message.  Control is then
X * returned to the system with an error status.  This function does not
X * return.
X */
X/* VARARGS0 */
Xvoid error (va_alist)
Xva_dcl                            /* varargs */
X{
X    int err;                      /* 1st arg - error number */
X    char *str;                    /* 2nd arg - error format string */
X    va_list args;
X    va_start(args);
X    err = va_arg (args, int);
X    str = va_arg (args, char *);
X    vfprintf (stderr, str, args);
X    if (err <= sys_nerr && err > 0)
X        fprintf (stderr, "%s\n", sys_errlist[err]);
X    else
X        fprintf (stderr, "unknown error : %d\n", err);
X    va_end(args);
X
X    /*
X     * print out partial report, if possible
X     */
X    if (fil_sys != NULL)print_report ();
X    exit(1);                      /* exit with error status */
X    }
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X    int next_param;
X    extern int stat ();
X    struct stat f_stat;
X
X    /*
X     * perform various initialization functions
X     */
X    next_param = init (argc, argv);
X
X    if (next_param == argc){
X        /*
X         * no individual files to check, scan entire file system
X         */
X        printf ("Analyzing file system %s...\n", special);
X
X        /*
X         * scan through all i-nodes in the file system
X         */
X        scan();
X
X        /*
X         * print out statistics summary
X         */
X        print_report();
X        }
X    else {
X        /*
X         * scan individual files instead of entire file system
X         */
X        printf ("                  \t                                       Seek  Wasted\n");
X        printf ("        Name      \ti-node    Fragments  Size      %%       Dist  Space\n");
X        for (; next_param < argc; next_param++){
X            if (stat (argv[next_param], &f_stat) != 0){
X                error (errno, "error opening \"%s\"\n",
X                       argv[next_param]);
X                /* NOTREACHED */
X                }
X            else {
X
X                /*
X                 * make sure the inode belongs to the correct device
X                 * (for BSD systems with symbolic links)
X                 */
X                if ((f_stat.st_dev == fs_device) &&
X                    !IS_SPECIAL (f_stat.st_mode)){
X                    anal_file (f_stat.st_ino, argv[next_param]);
X                    }
X                }
X            }
X        }
X    return (0);
X    }
END_OF_fsanalyze.c
if test 6212 -ne `wc -c <fsanalyze.c`; then
    echo shar: \"fsanalyze.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f patchlevel.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"patchlevel.h\"
else
echo shar: Extracting \"patchlevel.h\" \(950 characters\)
sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h'
X/* @(#)$Id: patchlevel.h, V4.1 88/11/16 17:55:39 $ */
X
X/*
X * patchlevel.h - current patch level
X * Version  : 4.1 - 88/11/16 17:55:39
X *
X * Author   : Michael J. Young
X * USmail   : Software Development Technologies, Inc.
X *            375 Dutton Rd
X *            Sudbury MA 01776
X * UUCP     : harvard!sdti!mjy
X * Internet : mjy@sdti.SDTI.COM
X *
X * =========================================================================
X * Note : This program has been placed in the public domain to permit
X * unrestricted distribution and use.  I have placed no copyright on it, but
X * I request that you keep me informed about any enhancements and bug fixes
X * you make so I can keep an up-to-date copy for further distribution.
X *
X * This program is being provided "as is", with no warrantee as to safety or
X * accuracy of results.  Use at your own risk.
X * =========================================================================
X */
X
X#define patch_level 0
X
END_OF_patchlevel.h
if test 950 -ne `wc -c <patchlevel.h`; then
    echo shar: \"patchlevel.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f stats.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"stats.c\"
else
echo shar: Extracting \"stats.c\" \(5581 characters\)
sed "s/^X//" >stats.c <<'END_OF_stats.c'
Xstatic char sccsid[] = "@(#)$Id: stats.c, V4.1 88/11/16 17:31:26 $";
X
X/*
X * stats.c - file system statistics
X * Version  : 4.1 - 88/11/16 17:31:26
X *
X * Author   : Michael J. Young
X * USmail   : Software Development Technologies, Inc.
X *            375 Dutton Rd
X *            Sudbury MA 01776
X * UUCP     : harvard!sdti!mjy
X * Internet : mjy@sdti.SDTI.COM
X *
X * =========================================================================
X * Note : This program has been placed in the public domain to permit
X * unrestricted distribution and use.  I have placed no copyright on it, but
X * I request that you keep me informed about any enhancements and bug fixes
X * you make so I can keep an up-to-date copy for further distribution.
X *
X * This program is being provided "as is", with no warrantee as to safety or
X * accuracy of results.  Use at your own risk.
X * =========================================================================
X */
X
X/*
X * Modification History:
X *
X * Thu Jul 28 16:02:51 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Extracted from fsanalyze.c
X *
X * Mon Aug 08 11:27:39 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Revised OS_TYPE and FS_TYPE macros to avoid name-space conflicts
X *
X * Wed Nov 16 11:31:32 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Placed under SCCS
X */
X
X#include "fsconfig.h"
X#include "fsanalyze.h"
X
X/*
X * calculated global statistics
X */
Xlong blocks              = 0;           /* running block count */
Xlong free_inodes         = 0;           /* number of unused i-nodes */
Xlong potential_seeks     = 0;           /* potential number of disk seeks
X                                         * during sequential access of a 
X                                         * file */
Xlong seeks               = 0;           /* actual number of disk seeks
X                                         * required during sequential access
X                                         * of a file */
Xlong total_seek_distance = 0;           /* actual distance of disk seeks
X                                         * required during sequential access
X                                         * of a file */
Xlong rotates             = 0;           /* number of disk rotation delays */
Xlong indirects           = 0;           /* number of files w/ more than
X                                         * 10 data blocks */
Xlong double_indirects    = 0;           /* number of files w/ more than
X                                        /* one level of indirection */
Xlong triple_indirects    = 0;           /* number of files w/ more than
X                                         * two levels of indirection */
Xlong ind_blks            = 0;           /* number of blocks used for
X                                         * indirection */
Xint big_directories      = 0;           /* number of directories with
X                                         * indirection */
Xint num_directories      = 0;           /* number of directories */
Xint num_specials         = 0;           /* number of special files */
Xint linked_files         = 0;           /* number of multiply-linked files */
Xint sparse_files         = 0;           /* number of sparse files */
Xint size_errors          = 0;           /* number of file size discrepancies */
Xlong unuseable           = 0;           /* unuseable bytes due to external
X                                         * fragmentation */
X
Xstruct file_data file_log[NUMOFFEND] = {0};    /* worst offenders */
X
X/*
X * init_stats : initializes per-file statistics structure
X */
Xvoid init_stats (data, inode, file_size)
Xstruct file_data *data;                           /* file stats to init */
Xint inode;                                        /* i-node number */
Xlong file_size;                                   /* file size */
X{
X    data->inode = inode;
X    data->total_blocks = data->data_blocks = 0;
X    data->potential_seeks = data->seeks = data->rotates = 0;
X    data->fragm = 0.0;
X    data->sparse = 0;
X    data->cost = 0;
X    data->min_cost = minimum_seeks (file_size);
X    data->rel_cost = 0.0;
X    data->wasted = 0;
X    }
X
X/*
X * log_stats : updates global statistics based on the current file statistics.
X * The current file is then checked to see if it qualifies as one of the
X * worst offenders (i.e., most fragmented) encountered thus far.  The worst
X * offenders are determined based on their absolute number of disk seeks
X * required to read the entire file.  Such an absolute test (viz a viz a
X * relative percentage test) ensures that very small, but fragmented, files
X * will not clutter the output.
X */
Xvoid log_stats (data)
Xstruct file_data *data;                /* file statistics to be
X                                        * logged */
X{
X    int i, j;                          /* loop counters */
X
X
X    /*
X     * update global statistics
X     */
X    blocks += data->total_blocks;
X    ind_blks += data->total_blocks - data->data_blocks;
X    potential_seeks += data->potential_seeks;
X    seeks += data->seeks;
X    total_seek_distance += data->cost;
X    rotates += data->rotates;
X    data->fragm = data->potential_seeks ? (float)data->seeks/(float)data->potential_seeks : 0.0;
X    data->rel_cost = (data->seeks ? (float)data->cost/(float)data->seeks : 0.0);
X    unuseable += data->wasted;
X
X    /*
X     * update worst offender array
X     */
X    for (i = 0; i < NUMOFFEND; i++){
X        if (data->seeks > file_log[i].seeks){
X            for (j = NUMOFFEND-1; j > i; j--){
X                file_log[j] = file_log[j-1];
X                }
X            file_log[i] = *data;
X            break;
X            }
X        }
X    }
X
END_OF_stats.c
if test 5581 -ne `wc -c <stats.c`; then
    echo shar: \"stats.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f util.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"util.c\"
else
echo shar: Extracting \"util.c\" \(2687 characters\)
sed "s/^X//" >util.c <<'END_OF_util.c'
Xstatic char sccsid[] = "@(#)$Id: util.c, V4.1 88/11/16 17:31:35 $";
X
X/*
X * util.c - inode utilities
X * Version  : 4.1 - 88/11/16 17:31:35
X *
X * Author   : Michael J. Young
X * USmail   : Software Development Technologies, Inc.
X *            375 Dutton Rd
X *            Sudbury MA 01776
X * UUCP     : harvard!sdti!mjy
X * Internet : mjy@sdti.SDTI.COM
X *
X * =========================================================================
X * Note : This program has been placed in the public domain to permit
X * unrestricted distribution and use.  I have placed no copyright on it, but
X * I request that you keep me informed about any enhancements and bug fixes
X * you make so I can keep an up-to-date copy for further distribution.
X *
X * This program is being provided "as is", with no warrantee as to safety or
X * accuracy of results.  Use at your own risk.
X * =========================================================================
X */
X
X/*
X * Modification History:
X *
X * Thu Jul 28 15:55:40 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Extracted from fsanalyze.c
X *
X * Mon Aug 08 11:27:39 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Revised OS_TYPE and FS_TYPE macros to avoid name-space conflicts
X *
X * Wed Nov 16 11:31:32 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Placed under SCCS
X */
X
X#include "fsconfig.h"
X#include "fsanalyze.h"
X
X/*
X * blk_no : given a pointer to an inode block number, returns a (daddr_t)
X * block number.  Used to provide portable access to the direct data blocks
X * of an i-node.
X */
Xdaddr_t blk_no (off)
Xunsigned char *off;                /* 3- or 4-byte offset */
X{
X    daddr_t temp = 0;
X
X#if FS_TYPE == FS_ATT
X    extern void l3tol();
X
X    l3tol (&temp, off, 1);
X#endif
X
X#if FS_TYPE == FS_BSD
X    temp = *((daddr_t *)off);
X#endif
X
X    return temp;
X    }
X
X/*
X * get_inodes : given an initial i-node number, reads a block of i-nodes
X * into an i-node array.
X */
Xvoid get_inodes (in, inp, num)
Xint in;                     /* inode number */
Xint num;                    /* # inodes to get */
Xstruct dinode *inp;         /* buffer to hold info */
X{
X    daddr_t position;          /* computed position of the
X                                * first requested i-node */
X
X    position = (daddr_t) inode_block(fil_sys, in) * block_size + 
X               (daddr_t) inode_offset(fil_sys, in) * sizeof(struct dinode);
X    if (fseek (fsys, position, 0)){
X        error (errno, "\nerror seeking inode %d, pos = %ld\n", in, position);
X        /* NOTREACHED */
X        }
X    else {
X        if (fread (inp, sizeof (struct dinode), num, fsys) != num){
X            error (errno, "\nerror reading inode %d\n", in);
X            /* NOTREACHED */
X            }
X        }
X    }
X
END_OF_util.c
if test 2687 -ne `wc -c <util.c`; then
    echo shar: \"util.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    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
-- 
Mike Young
Software Development Technologies, Inc., Sudbury MA       Tel: +1 508 443 5779
Internet: mjy@sdti.sdti.com                 UUCP: {harvard,mit-eddie}!sdti!mjy