Subject: more questions on unpack (long)

From: [email-masked] (Chris Hare)
Date: Sat, 28 Mar 1992 03:20:16 GMT

I posted some questions earlier this month, and I did get some feedback,
and I have a little more of this script working.

I am trying to build a script which reads the superblock of a filesystem
and then prints a report on the state of the union there.  It works, to a
point.  I think the problem is still in my unpack, but I'm still learning
my way around in PERL, and haven't yet mastered parts of it.

When I run my program (which I've included later showing some specific
questions, I get this

Filesystem Information for /dev/root
Volumne Name :                 Pack Name :       
File System Block Size                  :    0 bytes
Total size of Volume (   0 byte blocks) : 14580
Total size of i-list (   0 byte blocks) : 229
Total Free Blocks    (   0 byte blocks) : 0
Total Free Inodes                       : 0
Has the superblock been modified?       : 
Is the filesystem mounted read only?    : 
Last superblock update at               : 

Number of blocks in the free list : 19   Maximum : 50
Current Free Block List reads : 
a00:     14230 a01:     14268 a02:     14520 a03:     14235 a04:     14513 
a05:     13493 a06:      7257 a07:     14189 a08:     14512 a09:     14179 
a10:     14514 a11:     13748 a12:     13927 a13:     13842 a14:     13749 
a15:      9105 a16:      9817 a17:      9834 a18:     14536 

Number of inodes in the free list : 0   Maximum : 100

You will notice from this output, that some of the values make sense, and
other do not.  In fact, the values reported for the size of the volume, the
i-list, the number of blocks on the list and the list itself are correct.
I have a C program to do this.

The problem is that the information which follows the free block list
doesn't appear to be there - I think this is because I'm using the '@' on
the unpack as shown here :

( $s_isize, $s_fsize, $s_nfree, @s_free, $s_ninode, @s_inode, 
  $s_flock, $s_ilock, $s_fmod, $s_ronly, $s_time, $s_tfree, $s_tinode, $s_fname,
  $s_pack, $s_fill, $s_state, $s_magic, $s_type ) = unpack( $S51K, $buf );

So I'm probably correct in my assumption, but I don't know how to correct
it.  There are really several arrays in this structure:
	s_free	list of free blocks
	s_inode list of free inodes
	s_fname	6 char name of filesystem
	s_pack  6 char pack name

Any help to show me some method to fix this would be appreciated.

In addition, the s_type variable can have several values, and I would like
to initialize an assoc array which would have the values for s_type as the
keys.  Currently this is being done as
$Types{'1'} = 512;
$Types{'2'} = 1024;
$Types{'3'} = 2048;
$Types{'4'} = 4096;
$Types{'5'} = 8192;

but I'm sure that there is a better way to do that one also.

I am including the source code and the configuration file for completeness.

thanks for the help - and Larry, thanks for the language!

#
# config file
#

#
# AT&T S51K Superblock
#
#	ushort	s_isize;	/* size in blocks of i-list */
#	daddr_t	s_fsize;	/* size in blocks of entire volume */
#	short	s_nfree;	/* number of addresses in s_free */
#	daddr_t	s_free[NICFREE];/* free block list */
#	short	s_ninode;	/* number of i-nodes in s_inode */
#	ushort	s_inode[NICINOD];/* free i-node list */
#	char	s_flock;	/* lock during free list manipulation */
#	char	s_ilock;	/* lock during i-list manipulation */
#	char  	s_fmod; 	/* super block modified flag */
#	char	s_ronly;	/* mounted read-only flag */
#	time_t	s_time; 	/* last super block update */
#	short	s_dinfo[4];	/* device information */
#	daddr_t	s_tfree;	/* total free blocks*/
#	ushort	s_tinode;	/* total free inodes */
#	char	s_fname[6];	/* file system name */
#	char	s_fpack[6];	/* file system pack name */
#	long	s_fill[14];	/* adjust to make sizeof filsys be 512 */
#	long	s_state;	/* file system state */
#	long	s_magic;	/* magic number to indicate new file system */
#	long	s_type;		/* type of new file system */
#
$NICFREE = 50;
$NICINOD = 100;
$S51K = "S l s l$NICFREE s S$NICINOD c c c c l s4 l S c6 c6 l4 l l l";
1;

#
# script
#
require "config.fs";
$Types{'1'} = 512;
$Types{'2'} = 1024;
$Types{'3'} = 2048;
$Types{'4'} = 4096;
$Types{'5'} = 8192;

$Device = "/dev/root";
#
# open the named device and run the NoAuth subroutine if there is a problem
# gaining access.
#
open( FS, "/dev/root" ) || &NoAuth;
#
# seek in 512 bytes
#
seek( FS, 512, 0 );
#
# read the superblock, which is typically 512 bytes in size
#
read( FS, $buf, 512 );
#
# unpack it into the structure
# This piece of code may be system dependant - based upon the potentially
# different structures available
#
( $s_isize, $s_fsize, $s_nfree, @s_free, $s_ninode, @s_inode, 
  $s_flock, $s_ilock, $s_fmod, $s_ronly, $s_time, $s_tfree, $s_tinode, $s_fname,
  $s_pack, $s_fill, $s_state, $s_magic, $s_type ) = unpack( $S51K, $buf );
#
# calculate the Blocksize, which is typically mulitples of 512 bytes
#
$bsize = $Types{'$s_type'};
#
# print a report
#
printf "Filesystem Information for %s\n", $Device;
printf "Volumne Name : %6s          Pack Name : %6s\n", $s_name, $s_pack;
printf "File System Block Size                  : %4d bytes\n", $bsize;
printf "Total size of Volume (%4d byte blocks) : %ld\n", $bsize, $s_fsize;
printf "Total size of i-list (%4d byte blocks) : %u\n", $bsize, $s_isize;
printf "Total Free Blocks    (%4d byte blocks) : %ld\n", $bsize, $s_tfree;
printf "Total Free Inodes                       : %ld\n", $s_tinode;
printf "Has the superblock been modified?       : \n";
printf "Is the filesystem mounted read only?    : \n";
printf "Last superblock update at               : \n\n\n";
printf "Number of blocks in the free list : %ld   Maximum : %ld\n", 
	$s_nfree, $NICFREE;
printf "Current Free Block List reads : \n";
&PrintFreeBlockList;

printf "\nNumber of inodes in the free list : %ld   Maximum : %ld\n", 
	$s_ninode, $NICINOD;
&PrintFreeInodeList;
exit(0);

sub PrintFreeBlockList
{
   for ( $z = 0; $z < $s_nfree; $z+=5 )
	  {
      for ( $y = $z; $y < $z + 5; $y++ )
	     {
         if ( $y < $s_nfree )
			{
            printf "a%02d:%10ld ",$y, $s_free[$y];
			}
	     }
	  printf "\n";
	  }
}

sub PrintFreeInodeList
{
   for ( $z = 0; $z < $s_ninode; $z+=5 )
	  {
      for ( $y = $z; $y < $z + 5; $y++ )
	     {
         if ( $y < $s_ninode )
			{
            printf "a%02d:%10ld ",$y, $s_inode[$y];
			}
	     }
	  printf "\n";
	  }
}

sub NoAuth
{
   printf "You likely don't have the authority to read the superblock, \n";
   printf "you have not specified a valid device.\n";
   exit(1);
}
-- 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chris Hare				UUCP : uunet.ca!choreo!unilabs!chare
SCO Authorized Instructor		Choreo Systems Inc., Ottawa Canada
*** STANDARD DISCLAIMER APPLIES ***	DOMAIN: [email-masked]