[comp.unix.xenix] frag - A XENIX filesystem fragmentation display tool

meyer@mimsy.umd.edu (John R. Meyer) (12/28/89)

Hello --

	Here's a little program I wrote a while back that I've found
quite useful.  It is intended to complement the "packdisk" program
that floated around here a while ago.  "frag" reads in a filesystem
and displays it on standard output, indicating where the used and
unused data blocks are, in addition to the inode, super, and free
list blocks.  As far as I know, this works only with SCO XENIX-286
2.2.1 and SCO XENIX-386 2.3.2, although it should work with any other
later versions.

---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  README
#	  Makefile
#	  frag.1
#	  frag.h
#	  main.c
#	  io.c
#	  display.c
#
sed 's/^X//' << 'SHAR_EOF' > README &&
X            frag: A FILESYSTEM FRAGMENTATION DISPLAY TOOL FOR XENIX
X
X                                     by
X
X                                John R. Meyer
X                               john@nat-3.UUCP
X                         ...!uunet!mimsy!nat-3!john
X                        Version 1.1 December 27, 1989
X
X
XWhat It Is
X----------
X
X	frag displays the current layout of a XENIX filesystem, including
Xused and unused data blocks, the super block, the free list blocks, and
Xthe inode blocks as the following example shows:
X
X	% frag /dev/src
X	File system:  /dev/src
X	Last update:  Wed Dec 27 12:16:45 1989
X
X	System name:            Pack name:        
X
X	Total blocks:  20000    Allocated:  17117  (85%)  17.53/20.48 MB
X	Total inodes:  4992     Allocated:  2182   (43%)  2.23 MB
X	Block size:    1024 bytes
X
X	SIIIIIIIIIIIIIII********************-*------******
X	*********************---F--**---F*****************
X	**********-F---F-*-F******************************
X	**********************-***************---------F--
X	----F-----F--F----F--------**************--*******
X	**************************************************
X	**************************************************
X	**************************************************
X	**************************************-F-***--****
X	---------F-------*-*******************************
X	***************************-**********************
X	************---*********-F-FF-F---F****-------F---
X	*------F--F------**-*-F**-----********************
X	*****----********-********************************
X	*********--****--***-*--*********-------**--******
X	**************************************************
X	***************-***-*-****************************
X	************************************************--
X	F-------*F----*----------------------F-------F----
X	--*-*-F*-***---**--------***-----------------F--**
X
X	LEGEND:
X		* : Allocated block
X		- : Free block
X		I : Inodes block
X		F : Free list block
X		S : Super block
X
XIt is intended as a complement to the popular packdisk program written
Xby Andrew Fyfe (andy@csvax.caltech.edu).
X
X
X
XEnvironment
X-----------
X
X	Since frag requires direct access to the special device file for
Xthe file system to be analyzed, it should be set-uid to the "sysinfo" user
X(or whoever owns the device files on your system) if you wish to allow
Xnon-super-users to execute it.
X
X
X
XPortability
X-----------
X
X	This program was written on an IBM PC-AT and has been correctly
Xrun on SCO XENIX-286 2.2.1 and SCO XENIX-386 2.3.2.  It should not be
Xdifficult to port to other System V-type operating systems, although I
Xhave not tried to.
X
X	If you get frag working in any other other environments, please
Xmail your changes to source@nat-3.UUCP so they may be included in later
Xreleases of frag.
X
X
X
XLicense
X-------
X
X	You may freely copy and distribute verbatim copies of frag source
Xcode as you receive it, in any medium, provided you adhere to the following
Xprovisions:
X
X	1)	You provide ALL source code as received.
X	2)	You provide all copyright, warranty, and license information
X		as received.
X	3)	You do not use any part of the source code in any code
X		of your own without proper acknowledgements to the author.
X	4)	You do not charge any fee or fees for providing, copying
X		and/or distributing the code, except for the possible
X		cost of distribution media.
X	5)	You mark any changes you make to the code conspicuously
X		as not having been part of the original distribution.
X
X
X
XWarranty
X--------
X
X	frag IS PROVIDED BY JOHN R. MEYER AND/OR OTHER PARTIES "AS IS"
XWITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
XBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
XAND PERFORMANCE OF frag RESTS WITH YOU.  SHOULD frag PROVE DEFECTIVE,
XYOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
X
X	IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW SHALL JOHN R. MEYER
XAND/OR ANY OTHER PARTY WHO MAY MODIFY OR DISTRIBUTE frag AS PERMITTED
XABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST
XMONIES, OR OTHER SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
XOUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS
XOF DATA OR DATA BEING RENDERED OR LOSSES SUSTAINED BY THIRD PARTIES OR
XA FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) frag, EVEN
XIF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY
XCLAIM MADE BY ANY OTHER PARTY.
X
X
X
XCopyright
X---------
X
X	frag is Copyright (C) 1989 by John R. Meyer.
X
X
X
XAcknowledgements
X----------------
X
X	1)	The file system traversal algorithm was borrowed from
X		the fsanalyze program written by Michael J. Young
X		(mjy@sdti.SDTI.COM) and then modified.
X	2)	The warranty notice was copied from the smail 3.1
X		distribution notice.  smail is copyright (C) 1988 by
X		Landon Curt Knoll & Ronald S. Karr.
X	3)	The packdisk program was written by Andrew Fyfe
X		(andy@csvax.caltech.edu).
SHAR_EOF
chmod 0644 README || echo "restore of README fails"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#  [ frag ]
X#
X#  Author:  John R. Meyer
X#  File:    Makefile
X#  Version: 1.1
X#  Date:    12/27/89 13:43:42
X#
X#  @(#) Makefile  Version 1.1  (12/27/89 13:43:42)
X#
X#
X#  Description:
X#
X#	This file contains the make source code for the frag system.
X
X
X.SUFFIXES : .o .c .h
X
XSHELL = /bin/sh
XCFLAGS = -O
XLFLAGS = -s
X
XTARGET = frag
XINCLUDES = frag.h
XSOURCES = main.c io.c display.c
XOBJECTS = $(SOURCES:.c=.o)
XDOCUMENTS = frag.1
XSHARFILE = $(TARGET).shar
X
X
X#  The following is required only if making "install".
X
XBINDIR = /local/bin
XOWNER = sysinfo
XGROUP = bin
X
X
X#  Targets.
X
Xall $(TARGET) : $(OBJECTS)
X	cc $(CFLAGS) $(OBJECTS) $(LFLAGS) -o $(TARGET)
X
Xinstall : $(TARGET)
X	-[ -d $(BINDIR) ] || mkdir $(BINDIR)
X	cp $(TARGET) $(BINDIR)
X	chown $(OWNER) $(BINDIR)/$(TARGET)
X	chgrp $(GROUP) $(BINDIR)/$(TARGET)
X	chmod 4711 $(BINDIR)/$(TARGET)
X
Xshar $(SHARFILE) : Makefile $(DOCUMENTS) $(INCLUDES) $(SOURCES) README
X	shar -cxsMD README Makefile $(DOCUMENTS) $(INCLUDES) $(SOURCES) > $(SHARFILE)
X
Xclean :
X	rm -f $(OBJECTS)
X
Xclobber : clean
X	rm -f $(TARGET) $(SHARFILE) $(BINDIR)/$(TARGET)
X
Xprint :
X	for file in Makefile $(INCLUDES) $(SOURCES) ; do \
X		pr -f -n -h "   $(TARGET)($$file)   " $$file | lpr ; \
X	done
X
Xtouch :
X	touch Makefile $(DOCUMENTS) $(INCLUDES) $(SOURCES)
X
X
X#  Object file dependencies.
X
Xdisplay.o : display.c frag.h
Xio.o : io.c frag.h
Xmain.o : main.c frag.h
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
sed 's/^X//' << 'SHAR_EOF' > frag.1 &&
X.\" frag.1  (SCCS: SCCS/s.frag.1)  Version 1.1
X.TH FRAG 1L
X.SH NAME
X.sp 1
Xfrag - Print display of file system block fragmentation
X.SH SYNTAX
X.sp 1
X.B frag
X[ special ]
X.SH DESCRIPTION
X.sp 1
X.LP
X.B frag
Xanalyzes the given special file (or /dev/rroot if
X.I special
Xis not specified) for its block allocation.  The super block and blocks
Xcontaining inodes are also displayed along with file system
Xstatistics.
X.SH DIAGNOSTICS
X.sp 1
X.PP
XFollowing are the messages that can be issued and their associated
Xmeaning.  All messages are printed to the standard error output.
X.in +3
X.LP
Xunknown argument:  \fIc\fR
X.in +3
X.LP
XAn unknown argument was passed on the command line.  Call the
Xprogram again with the correct type of arguments.
X.in -3
X.LP
XError \fIxx\fR opening filesystem:  \fIs\fR
X.in +3
X.LP
XXENIX error \fIxx\fR occurred trying to open the device file.
XA descriptive message is printed in \fIs\fR indicating the reason.
X.in -3
X.LP
XError \fIxx\fR seeking to super block:  \fIs\fR
X.in +3
X.LP
XXENIX error \fIxx\fR occurred trying to seek the file pointer to
Xthe super block of the file system.  A descriptive message is
Xprinted in \fIs\fR indicating the reason.
X.in -3
X.LP
XError \fIxx\fR reading super block:  \fIs\fR
X.in +3
X.LP
XXENIX error \fIxx\fR occurred trying to read in the super block
Xof the file system.  A descriptive message is printed in \fIs\fR
Xindicating the reason.
X.in -3
X.LP
XBad filesystem:  number of free blocks > NICFREE (\fIxx\fR > \fIyy\fR)
X.in +3
X.LP
XThe number of free blocks in the super block is greater than the
Xmaximum number of free blocks allowed by XENIX.  This typically
Xmeans that the device is not a file system or it is corrupted.
XIn the latter case, run fsck(ADM) and try again.
X.in -3
X.LP
XBad filesystem:  number of inodes > NICINOD (\fIxx\fR > \fIyy\fR)
X.in +3
X.LP
XThe number of inodes in the super block is greater than the maximum
Xnumber of inodes allowed by XENIX.  This typically means that the
Xdevice is not a file system or it is corrupted.  In the latter case,
Xrun fsck(ADM) and try again.
X.in -3
X.LP
XBlock number \fIxx\fR out of range [\fIyy\fR, \fIzz\fR].
X.in +3
X.LP
XDuring the traversal of the linked list of block numbers in the
Xsuper block, block \fIxx\fR was encountered which is out of the
Xcorrect range for the file system.  This typically means that the
Xdevice is not a file system or it is corrupted.  In the latter
Xcase, run fsck(ADM) and try again.
X.in -3
X.LP
XError \fIxx\fR seeking to block \fIyy\fR:  \fIs\fR
X.in +3
X.LP
XXENIX error \fIxx\fR occurred trying to seek the file pointer to
Xthe next block in the linked list of free blocks.  A descriptive
Xmessage indicating the reason is given by \fIs\fR.
X.in -3
X.LP
XError \fIxx\fR reading block \fIyy\fR:  \fIs\fR
X.in +3
X.LP
XXENIX error \fIxx\fR occurred trying to read block \fIxx\fR of
Xthe file system.  A descriptive message indicating the reason
Xis given by \fIs\fR.
X.in -3
X.in -3
X.SH NOTES
X.sp 1
X.in +3
X.LP
X.B frag
Xperforms a
X.I sync
Xoperation on the filesystems to get the most recent information
X.in -3
X.SH "SEE ALSO
X.sp 1
Xfsck(ADM)
X.en
SHAR_EOF
chmod 0644 frag.1 || echo "restore of frag.1 fails"
sed 's/^X//' << 'SHAR_EOF' > frag.h &&
X/*
X *  [ frag ]
X *
X *  Author:  John R. Meyer
X *  File:    frag.h
X *  Version: 1.1
X *  Date:    12/27/89 13:43:42
X *
X *  @(#) frag.h  Version 1.1  (12/27/89 13:43:42)
X */
X
X
X
X/*
X *  Function entry and exit messages for debugging.
X */
X
X#if defined(DEBUG)
X#	define	ENTER(proc)	printf ("%s(%d):  Enter %s\n", __FILE__, __LINE__, proc)
X#	define  LEAVE(proc)	printf ("%s(%d):  Leave %s\n", __FILE__, __LINE__, proc)
X#else
X#	define  ENTER(proc)
X#	define	LEAVE(proc)
X#endif
X
X
X/*
X *  Number of rows and columns to use in the file system display.
X */
X
X#define  NUMROWS	20
X#define  NUMCOLUMNS	50
X
X
X/*
X *  Enumeration constants for the display.  Each of these constants must be
X *  in increasing order of importance to the display, since a larger (later)
X *  constant will overwrite a smaller one in the display map.
X */
X
Xtypedef enum  {
X	ALLOC,		/* Block is allocated */
X	FREE,		/* Block is free */
X	INODEBLOCK,	/* Block is inode block */
X	FREELIST,	/* Block contains a link in the free list */
X	SUPERBLOCK	/* Block is super block */
X}  POSITIONTYPE;
X
X
X/*
X *  frag-related functions.
X */
X
Xvoid  openfilesystem (char *);
Xvoid  checksuperblock (void);
Xvoid  readfilesystem (void);
Xvoid  getsblock (daddr_t *, ino_t *, daddr_t *, ino_t *, char **, char **, char **);
Xvoid  display (char *);
Xvoid  putinlayout (daddr_t, POSITIONTYPE, daddr_t);
X
X
X/*
X *  External system declarations.
X */
X
Xextern char  *sys_errlist [];
Xextern int  errno;
SHAR_EOF
chmod 0644 frag.h || echo "restore of frag.h fails"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X/*
X *  [ frag ]
X *
X *  Author:  John R. Meyer
X *  File:    main.c
X *  Version: 1.1
X *  Date:    12/27/89 13:43:43
X *
X *
X *  Description:
X *
X *	This file contains the main program for the frag system, a program that
X *	prints out a display of the blocks of a filesystem, showing those devoted
X *	to inodes, those that are unallocated, and those that are allocated to a
X *	file.
X *
X *	frag is called by:
X *
X *		frag [special]
X *
X *	where special is the name of a special file containing a file system.
X *	The filesystem that is analyzed need not be mounted or unmounted for
X *	the program to work.
X */
X
X
X#include  <stdio.h>
X#include  <sys/types.h>
X#include  "frag.h"
X
X#define  FSNAMESIZE	100		/* maximum length of special file name */
X
X
X/*
X *  SCCS information.
X */
X
X#if !defined(lint)
Xstatic char  sccsid []  =  "@(#) main.c  Version 1.1  (12/27/89 13:43:43)";
X#endif
X
X
X/*
X *  Forward function prototypes.
X */
X
Xvoid  optioncheck (int, char *[]);
Xvoid  usage (char *);
X
X
X/*
X *  Local static variables.
X */
X
Xstatic char  filesystem [FSNAMESIZE + 1] = "/dev/rroot";
X
X
X
X/* ARGSUSED */
X
Xint  main (argc, argv, envp)
X
X/*
X *  Function  main ()  checks the arguments on the command line and analyzes the
X *  given file system.
X *
X *  The parameters represent:
X *
X *	argc		The number of command line arguments
X *	argv		An array of pointers to strings containing the command
X *			line arguments.
X *	envp		An array of pointers to strings containing environment
X *			variables and their values.
X */
X
Xint  argc;
Xchar  *argv[], *envp[];
X
X{
X	optioncheck (argc, argv);
X	openfilesystem (filesystem);
X	checksuperblock ();
X	readfilesystem ();
X	display (filesystem);
X
X	exit (0);
X	/* NOTREACHED */
X}
X
X
X
X
Xstatic void  optioncheck (argc, argv)
X
X/*
X *  Function  optioncheck()  checks the command line arguments for validity,
X *  setting the local static variables.
X *
X *  The parameters represent:
X *
X *	argc		The number of command line arguments.
X *	argv		An array of pointers to strings containing the command
X *			line arguments.
X */
X
Xint  argc;
Xchar  *argv[];
X
X{
X	ENTER ("optioncheck");
X
X	switch  (argc)  {
X	case  1 :
X		break;
X		/* NOTREACHED */
X	case  2 :
X		(void) strncpy (filesystem, argv[1], FSNAMESIZE);
X		break;
X		/* NOTREACHED */
X	default :
X		usage (argv[0]);
X		exit (1);
X		/* NOTREACHED */
X	}
X
X	LEAVE ("optioncheck");
X}
X
X
X
X
Xstatic void  usage (cmd)
X
X/*
X *  Procedure  usage ()  prints out the usage instructions.
X */
X
Xchar  *cmd;
X
X{
X	ENTER ("usage");
X
X	fprintf (stderr, "Usage:  %s [special]\n", cmd);
X
X	LEAVE ("usage");
X}
SHAR_EOF
chmod 0644 main.c || echo "restore of main.c fails"
sed 's/^X//' << 'SHAR_EOF' > io.c &&
X/*
X *  [ frag ]
X *
X *  Author:  John R. Meyer
X *  File:    io.c
X *  Version: 1.1
X *  Date:    12/27/89 13:43:43
X *
X *
X *  Identifiers defined here:
X *
X *	openfilesystem ()
X *	checksuperblock ()
X *      readfilesystem ()
X *      getsblock ()
X */
X
X
X#include  <stdio.h>
X#include  <sys/types.h>
X#include  <sys/ino.h>
X#include  <sys/param.h>
X#include  <sys/fblk.h>
X#include  <sys/filsys.h>
X#include  <time.h>
X#include  "frag.h"
X
X
X
X#if  !defined(SUPERBOFF)
X#	define	SUPERBOFF	(BSIZE * SUPERB)
X#endif
X
X
X
X/*
X *  SCCS information.
X */
X
X#if !defined(lint)
Xstatic char  sccsid []  =  "@(#) io.c  Version 1.1 (12/27/89 13:43:43)";
X#endif
X
X
X/*
X *  Local function prototypes.
X */
X
Xdaddr_t  readlink (daddr_t);
X
X
X/*
X *  Local static variables.
X */
X
Xstatic FILE  *fsys;
Xstatic struct filsys  superblock;
Xstatic struct fblk  fblk  =  {
X	0,
X	{ (daddr_t) 0 }
X};
X
X
X
Xvoid  openfilesystem (filesystem)
X
X/*
X *  Function  openfilesystem()  opens the given file system argument
X *  for read access and reads in the super block.
X *
X *  The parameter represents:
X *
X *	filesystem	The full pathname of the file system to analyze.
X */
X
Xchar  *filesystem;
X
X{
X	ENTER ("openfilesystem");
X
X
X	/*
X	 *  Open the file system and read in the super block.
X	 */
X
X	sync ();
X
X	if  ((fsys = fopen (filesystem, "r")) == (FILE *) NULL)  {
X		fprintf (stderr, "%s(%d):  Error %d opening filesystem: %s\n",
X			__FILE__, __LINE__ - 2, errno, sys_errlist[errno]);
X		exit (errno);
X		/* NOTREACHED */
X	}
X	if  (fseek (fsys, (long) SUPERBOFF, 0) != 0)  {
X		fprintf (stderr, "%s(%d):  Error %d seeking to super block: %s\n",
X			__FILE__, __LINE__ - 2, errno, sys_errlist[errno]);
X		exit (errno);
X		/* NOTREACHED */
X	}
X	if  (fread ((char *) &superblock, sizeof (struct filsys), 1, fsys) != 1)  {
X		fprintf (stderr, "%s(%d):  Error %d reading super block: %s\n",
X			__FILE__, __LINE__ - 2, errno, sys_errlist[errno]);
X		exit (errno);
X		/* NOTREACHED */
X	}
X
X
X	LEAVE ("openfilesystem");
X}
X
X
X
Xvoid  checksuperblock ( )
X
X/*
X *  Function  checksuperblock()  performs some simple checks on the
X *  super block of the filesystem to make sure it is correct.
X */
X
X{
X	auto short int  index;
X
X
X	ENTER ("checksuperblock");
X
X
X	/*
X	 *  Perform some simple checks.
X	 */
X
X	if  (superblock.s_nfree > NICFREE)  {
X		fprintf (stderr, "%s(%d):  Bad filesystem:  number of free blocks > NICFREE (%ld > %ld)\n",
X			__FILE__, __LINE__ - 2, superblock.s_nfree, NICFREE);
X		exit (1);
X		/* NOTREACHED */
X	}
X
X	if  (superblock.s_ninode > NICINOD)  {
X		fprintf (stderr, "%s(%d):  Bad filesystem:  number of inodes > NICINOD (%ld > %ld)\n",
X			__FILE__, __LINE__ - 2, superblock.s_ninode, NICINOD);
X		exit (1);
X		/* NOTREACHED */
X	}
X
X
X	/*
X	 *  Read in the free list information from the super block cache.
X	 */
X
X	putinlayout ((daddr_t) 1, SUPERBLOCK, superblock.s_fsize);
X	for  (index = 1;  index < superblock.s_nfree;  index++)
X		putinlayout (superblock.s_free[index], FREE, superblock.s_fsize);
X
X	fblk.df_free[0] = superblock.s_free[0];
X
X
X	LEAVE ("checksuperblock");
X}
X
X
X
Xvoid  readfilesystem ( )
X
X/*
X *  This routine reads in the data associated with the file system,
X *  returning 1 if everything went alright, 0 otherwise.
X */
X
X{
X	auto ushort  inoblock;
X	auto short int  index;
X
X
X	ENTER ("readfilesystem");
X
X
X	/*
X	 *  Read in the free block list.
X	 */
X
X	while  (readlink (fblk.df_free[0]) != (daddr_t) 0)  {
X		putinlayout (fblk.df_free[0], FREELIST, superblock.s_fsize);
X		for  (index = 1;  index < fblk.df_nfree;  index++)
X			putinlayout (fblk.df_free [index], FREE, superblock.s_fsize);
X	}
X
X
X	/*
X	 *  Mark the inode blocks.
X	 */
X
X	for  (inoblock = 2;  inoblock < superblock.s_isize;  inoblock++)
X		putinlayout ((daddr_t) inoblock, INODEBLOCK, superblock.s_fsize);
X
X
X	LEAVE ("readfilesystem");
X}
X
X
X
Xstatic daddr_t  readlink (block)
X
X/*
X *  Function  readlink ()  reads in the next link in the linked list of
X *  free blocks in the filesystem, returning 1 if there exists such
X *  a block and all goes well, 0 otherwise.
X *
X *  The parameter represents:
X *
X *	block		The address of the block containing the next link.
X */
X
Xdaddr_t block;
X
X{
X	auto daddr_t  retval = (daddr_t) 0;
X
X
X	ENTER ("readlink");
X
X	if  (block != (daddr_t) 0)  {
X		if  ((block < superblock.s_isize) || (block > superblock.s_fsize))  {
X			fprintf (stderr, "%s(%d):  Block number %ld out of range [%ld, %ld].\n",
X				__FILE__, __LINE__ - 2, block, superblock.s_isize, superblock.s_fsize);
X			exit (1);
X			/* NOTREACHED */
X		}
X		if  (fseek (fsys, (long) block * (long) BSIZE, 0) != 0)  {
X			fprintf (stderr, "%s(%d):  Error %d seeking to block %ld: %s\n",
X				__FILE__, __LINE__ - 2, errno, block, sys_errlist[errno]);
X			exit (errno);
X			/* NOTREACHED */
X		}
X		if  (fread ((char *) &fblk, sizeof (struct fblk), 1, fsys) != 1)  {
X			fprintf (stderr, "%s(%d):  Error %d reading block %ld: %s\n",
X				__FILE__, __LINE__ - 2, errno, block, sys_errlist[errno]);
X			exit (errno);
X			/* NOTREACHED */
X		}
X		retval = fblk.df_free[0];
X	}
X
X
X	LEAVE ("readlink");
X
X	return  retval;
X}
X
X
X
Xvoid  getsblock (numblocks, numinodes, freeblocks, freeinodes, update, fname, pname)
X
X/*
X *  Procedure  getsblock ()  returns information concerning the super block
X *  of the filesystem.
X *
X *  The parameters represent:
X *
X *	numblocks	A pointer to a daddr_t to contain the number of blocks
X *			in the filesystem.
X *	numinodes	A pointer to an ino_t to contain the number of inodes in
X *			the filesystem.
X *	freeblocks	A pointer to a daddr_t to contain the number of free
X *			blocks in the filesystem.
X *	freeinodes	A pointer to an ino_t to contain the number of free inodes
X *			in the filesystem.
X *	update		A pointer to a pointer to a character string that contains the date
X *			and time of the last update of the filesystem.
X *	fname		A pointer to a pointer to a six-character file system name.
X *	pname		A pointer to a pointer to a six-character pack name.
X */
X
Xdaddr_t  *numblocks;
Xino_t  *numinodes;
Xdaddr_t  *freeblocks;
Xino_t  *freeinodes;
Xchar  **update;
Xchar  **fname, **pname;
X
X{
X	extern struct tm  *localtime (long *);
X	extern char  *asctime (struct tm *);
X
X
X	ENTER("getsblock");
X
X
X	*numblocks = superblock.s_fsize;
X	*numinodes = ((int) superblock.s_isize - 2) * 16;
X	*freeblocks = superblock.s_tfree;
X	*freeinodes = superblock.s_tinode;
X	*update = asctime (localtime ((long *) &superblock.s_time));
X	*fname = superblock.s_fname;
X	*pname = superblock.s_fpack;
X
X
X	LEAVE("getsblock");
X}
SHAR_EOF
chmod 0644 io.c || echo "restore of io.c fails"
sed 's/^X//' << 'SHAR_EOF' > display.c &&
X/*
X *  [ frag ]
X *
X *  Author:  John R. Meyer
X *  File:    display.c
X *  Version: 1.1
X *  Date:    12/27/89 13:43:42
X *
X *
X *  Identifiers defined here:
X *
X *	putinlayout ()
X *	display ()
X */
X
X
X#include  <sys/types.h>
X#include  <sys/param.h>
X#undef NULL
X#include  <stdio.h>
X#include  "frag.h"
X
X
X
X/*
X *  SCCS information.
X */
X
X#if !defined(lint)
Xstatic char  sccsid []  =  "@(#) display.c  Version 1.1 (12/27/89 13:43:42)";
X#endif
X
X
X/*
X *  Local static variables.
X */
X
Xstatic struct legend  {
X	char  symbol;
X	char  *description;
X}  prtchars []  =  {
X	{ '*', "Allocated block" },
X	{ '-', "Free block" },
X	{ 'I', "Inodes block" },
X	{ 'F', "Free list block" },
X	{ 'S', "Super block" }
X};
X
Xstatic POSITIONTYPE  layout [NUMROWS] [NUMCOLUMNS]  =  {
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	},
X	{
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X		ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC, ALLOC,
X	}
X};
X
X
X
Xvoid  putinlayout (block, type, fsize)
X
X/*
X *  Procedure  putinlayout ()  adds the given type information for the
X *  given block address in the layout array.
X *
X *  The parameters represent:
X *
X *	block		The address of the block.
X *	type		The type of the block.
X *	fsize		The size in blocks of the filesystem.
X */
X
Xdaddr_t  block;
XPOSITIONTYPE  type;
Xdaddr_t  fsize;
X
X{
X	auto int  index = (int) ((block * ((daddr_t) (NUMROWS * NUMCOLUMNS))) / fsize);
X	auto int  row = index / NUMCOLUMNS;
X	auto int  column = index % NUMCOLUMNS;
X
X
X	ENTER ("putinlayout");
X
X	if  (type > layout[row][column])
X		layout[row][column] = type;
X
X	LEAVE ("putinlayout");
X}
X
X
X
Xvoid  display (filesystem)
X
X/*
X *  Procedure  display ()  prints out the results of the fragmentation analysis.
X *
X *  The parameter represents:
X *
X *	filesystem		The name of the special file
X */
X
Xchar  *filesystem;
X
X{
X	auto int  row, column, type;
X	auto daddr_t  numblocks, freeblocks;
X	auto ino_t  numinodes, freeinodes;
X	auto char  *update;
X	auto char  *fname, *pname;
X
X
X	ENTER ("display");
X
X	getsblock (&numblocks, &numinodes, &freeblocks, &freeinodes, &update, &fname, &pname);
X	printf ("File system:  %s\n", filesystem);
X	printf ("Last update:  %s\n", update);
X	printf ("System name:  %-6s    Pack name:  %-6s\n\n", fname, pname);
X	printf ("Total blocks:  %-6ld   Allocated:  %-6ld (%2ld%%)  %4.2f/%-4.2f MB\n",
X		numblocks,
X		numblocks - freeblocks,
X		((numblocks - freeblocks) * (daddr_t) 100) / numblocks,
X		(float) ((numblocks - freeblocks) * BSIZE) / 1.0e+6,
X		(float) (numblocks * BSIZE) / 1.0e+6);
X	printf ("Total inodes:  %-6d   Allocated:  %-6u (%2ld%%)  %4.2f MB\n",
X		numinodes,
X		numinodes - freeinodes,
X		((long) (numinodes - freeinodes) * (long) 100) / (long) numinodes,
X		((float) (numinodes - freeinodes) * (float) BSIZE) / 1.0e+6);
X	printf ("Block size:    %d bytes\n\n", BSIZE);
X	for  (row = 0;  row < NUMROWS;  row++)  {
X		for  (column = 0;  column < NUMCOLUMNS;  column++)
X			printf ("%c", prtchars[(int) layout[row][column]].symbol);
X		putchar ('\n');
X	}
X
X	printf ("\nLEGEND:\n");
X	for  (type = 0;  type < sizeof prtchars / sizeof (struct legend);  type++)
X		printf ("\t%c : %s\n", prtchars[type].symbol, prtchars[type].description);
X	putchar ('\n');
X
X
X	LEAVE ("display");
X}
SHAR_EOF
chmod 0644 display.c || echo "restore of display.c fails"
exit 0
-- 
John R. Meyer				Domain: meyer@mimsy.umd.edu
10208-C Ashbrooke Ct.			Path:   uunet.uu.net!mimsy!meyer
Oakton, VA 22124 USA			Phone:  (703) 644-3944 (O)
Disclaimer:  The views expressed are my own.	(703) 281-5157 (H)