hare fsdb Listing 6

/*
   @(#) sb.c - dump the contents of the superblock in a meaningful
format
   Copyright 1990, Chris Hare

   To compile for Motorola VME UNIX Systems, (R3V4 or later)
   cc -o sb -DMCS sb.c

   To Compile for SCO XENIX Systems (286)
        cc -o sb -DXENIX sb.c

   To Compile for SCO XENIX Systems (386)
        cc -o sb -DXENIX sb.c

   To Compile for SCO UNIX Systems (386)
        cc -o sb -DXENIX sb.c

*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#ifdef MCS                       /* Motorola VME UNIX Systems */
#   include <sys/fs/s5param.h>
#   include <sys/fs/s5filsys.h>
#endif
#ifdef XENIX
#   include <sys/param.h>
#   include <sys/filsys.h>
#endif
#include <sys/stat.h>
#include <string.h>
#include <memory.h>
#include <errno.h>
#include <time.h>

#define LONG_ZERO (long)0

extern int errno;                      /* system call error value */
extern int sys_err;              /* system call error value */
extern char *sys_errlist[];            /* error list for perror() */

main( argc, argv )
int argc;
char *argv[];
{
	int ReturnCode = 0,                 /* function call return code */
	FileDescriptor,                 /* device file descriptor */
	LoopCounter ,             /* LoopCounter  counter */
	LoopCounter2;             /* LoopCounter  counter */

	char *ctime(),                      /* declare ctime(S) */
	*timestr;                     /* storage area for time string */
	long int SeekReturnCode,            /* long function call return code */
	time();                   /* declare time(S) */
	struct stat StatBuf;          /* stat(S) structore for getting file type
	*/
	struct filsys FsBuf;          /* filesys (superblock) structure */

	/* check to see that we have enough arguements */
	if ( argc < 2 )
		usage( argv[0] );

	/* get the mode of the file */
	ReturnCode = stat( argv[1], &StatBuf );

	/* check for block special type */
	if ( ( StatBuf.st_mode & S_IFMT ) != ( S_IFBLK ) )
	{
		fprintf( stderr, "%s: not a block device\n", argv[1] );
		usage( argv[0] );
	}

	/* open the device file */
	FileDescriptor = open( argv[1], O_RDONLY );
	if ( FileDescriptor < 0 )
	{
		/* failures here will most likely be :
         no permission to open device
      */
		perror( argv[0] );
		exit(2);
	}

	/* make sure that we are at byte 0 in the device */
	SeekReturnCode = lseek( FileDescriptor, (long)0, 0 );
	if ( SeekReturnCode < LONG_ZERO )
	{
		fprintf( stderr, "%s : Can't seek to byte 0\n", argv[0] );
		perror( argv[0] );
		exit(3);
	}
	/* Seek past the boot block to the superblock */
	SeekReturnCode = lseek( FileDescriptor, (long)BSIZE, 1 );
	if ( SeekReturnCode < LONG_ZERO )
	{
		fprintf( stderr, "%s : Can't seek to byte %d\n", argv[0], BSIZE);
		perror( argv[0] );
		exit(3);
	}

	/* Read the superblock */
	ReturnCode = read( FileDescriptor, &FsBuf, BSIZE );
	if ( ReturnCode < 0 )
	{
		perror( argv[0] );
		exit(5);
	}

	/* Lets change the last modified time to something meaningful */
	timestr = ctime(&FsBuf.s_time);

	/* Lets have a look at what is in the superblock */
	/* and print the most useful stuff */
	printf( "Superblock dump for file system Name : %s\n", FsBuf.s_fname);
	printf( "Superblock dump for file system pack : %s\n", FsBuf.s_fpack);
	printf( "File System Block Size               : %d\n", FsBuf.s_type
	    * 512 );
	if ( FsBuf.s_type == 1 ) /* 512 byte blocks */
	{
		printf( "Size of i-list in blocks ( 512 byte) : %d\n",
		    FsBuf.s_isize );
		printf( "Size of Entire Volume    ( 512 byte) : %ld\n",
		    FsBuf.s_fsize );
		printf( "Total Free Blocks        ( 512 byte) : %d\n",
		    FsBuf.s_tfree );
	}
	if ( FsBuf.s_type == 2 ) /* 1024 byte blocks */
	{
		printf( "Size of i-list in blocks (1024 byte) : %d\n",
		    FsBuf.s_isize );
		printf( "Size of Entire Volume    (1024 byte) : %ld\n",
		    FsBuf.s_fsize );
		printf( "Total Free Blocks        (1024 byte) : %d\n",
		    FsBuf.s_tfree );
	}
	printf( "Total Free Inodes                    : %d\n",
	    FsBuf.s_tinode);

	/* Modify the report based upon the s_fmod status */
	if ( FsBuf.s_fmod == NULL )
		printf( "Has the super block been modified?   : No\n" );
	else
		printf( "Has the super block been modified?   : Yes\n" );

	/* Modify the report based upon the s_ronly status */
	if ( FsBuf.s_ronly == NULL )
		printf( "Is the file system mounted read-only : No\n" );
	else
		printf( "Is the file system mounted read-only : Yes\n" );

	printf( "Last super block update at           : %s\n", timestr );

	/* Print the free block list */
	printf( "\nNo of Addresses in free block list   : %d  Maximum : %d\n",
	    FsBuf.s_nfree, NICFREE );
	printf( "Current Free block list reads        :\n" );
	for ( LoopCounter  = 0; LoopCounter  < FsBuf.s_nfree; LoopCounter +=5)
	{
		for ( LoopCounter2 = LoopCounter; LoopCounter2 < LoopCounter +5;
		    LoopCounter2++ )
		{
			if ( LoopCounter2 >= FsBuf.s_nfree )
				break;
			printf( "a%02d:%10ld ",LoopCounter2, FsBuf.s_free[LoopCounter2]);
		}
		printf( "\n");
	}

	/* print the free inode list */
	printf( "\nNo of inodes in free inode list      : %d  Maximum : %d\n",
	    FsBuf.s_ninode, NICINOD );
	printf( "Current Free Inode list reads        :\n" );
	for ( LoopCounter  = 0; LoopCounter  < FsBuf.s_ninode; LoopCounter +=4 )
	{
		for ( LoopCounter2 = LoopCounter ; LoopCounter2 < LoopCounter +4;
		    LoopCounter2++ )
		{
			if ( LoopCounter2 >= FsBuf.s_ninode )
				break;
			printf( "i%03d:%10u ",LoopCounter2, FsBuf.s_inode[LoopCounter2]
			    );
		}
		printf( "\n");
	}

	/* Close the filesystem device file */
	ReturnCode = close( FileDescriptor );
	if ( ReturnCode < 0 )
	{
		perror( argv[0] );
		exit(7);
	}

	printf( "\n");
	exit (0);
}

int usage( cmd )
char *cmd;
{
	printf( "%s usage : %s block_filesystem_device \n", cmd, cmd );
	exit (1);
}

