Listing 5
#! perl
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
if 0;
#
# Copyright 1992, Chris Hare
#
#
# This PERL script is designed to read the superblock of the given
# filesystem name, and to print a report on it. While this version is
# coupled to the standard AT&T S51K filesystem, it may work with some other
# filesystem formats, so long as the superblock is the same.
#
# Load the configuration file with the filesystem superblock information
#
require "config.fs";
#
# set the filesystem block size type information
#
$Types{'1'} = 512; # 512 byte blocks
$Types{'2'} = 1024; # 1024 byte blocks
$Types{'3'} = 2048; # 2048 byte blocks
$Types{'4'} = 4096; # 4096 byte blocks
$Types{'5'} = 8192; # 8192 byte blocks
#
# Required arguments are
# block device name
#
&Usage if ( ! defined($ARGV[0]) );
$Device = $ARGV[0];
#
# check to see if it is a valid device, and it exists
#
&Error("ENFILE") if ( ! -e $Device );
&Error("ENBLK") if ( ! -b $Device );
&Error("ENOPERM") if ( ! -r $Device );
#
# open the named device
#
open( FS, "$Device" );
#
# seek in 512 bytes. This is the empty space which used to contain boot
# code (a long time ago).
#
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_dev, $s_tfree,
$s_tinode, $s_fname, $s_pack, $s_fill, $s_state, $s_magic,
$s_type ) = unpack( $S51K, $buf );
#
# unpack the free block list into an array
#
(@s_free) = unpack($S51K_s_free, $s_free);
#
# and now the free inode list
#
(@s_inode) = unpack($S51K_s_inode, $s_inode);
#
# calculate the Blocksize, which is typically mulitples of 512 bytes
#
$bsize = $Types{$s_type};
#
# now put a real word in for the superblock modified flag
#
if ( $s_fmod == 0 )
{
$s_fmod = "No";
}
else
{
$s_fmod = "Yes";
}
#
# OK, and now for the filesystem mounted read-only flag
#
if ( $s_ronly == 0 )
{
$s_ronly = "No";
}
else
{
$s_ronly = "Yes";
}
#
# print a report
#
printf "Filesystem Information for %s\n\n", $Device;
printf "Volumne Name : %6s Pack Name : %6s\n", $s_fname, $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? : %s\n", $s_fmod;
printf "Is the filesystem mounted read only? : %s\n", $s_ronly;
printf "Last superblock update at : %s\n\n\n",
&ctime($s_time);;
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;
printf "Current Free Inode List reads : \n";
&PrintFreeInodeList;
exit(0);
#
# The PrintFreeBlockList subroutine will read through the global variable
# $s_free printing five block addresses per line, with a prefix of
# a###: where ### is the entry number in the list
#
sub PrintFreeBlockList
{
#
# loop through the list starting a zero, and going to the actial number
# stored in the superblock
#
for ( $z = 0; $z < $s_nfree; $z+=5 )
{
#
# print five per line, and then do a line feed.
#
for ( $y = $z; $y < $z + 5; $y++ )
{
if ( $y < $s_nfree )
{
printf "a%02d:%10ld ",$y, $s_free[$y];
}
}
printf "\n";
}
}
#
# The PrintFreeInodeList subroutine will read through the global variable
# $s_inode printing five inode addresses per line, with a prefix of
# i###: where ### is the entry number in the list
#
sub PrintFreeInodeList
{
#
# loop through the list starting a zero, and going to the actial number
# stored in the superblock
#
for ( $z = 0; $z < $s_ninode; $z+=5 )
{
#
# print five per line, and then do a line feed.
#
for ( $y = $z; $y < $z + 5; $y++ )
{
if ( $y < $s_ninode )
{
printf "i%02d:%10ld ",$y, $s_inode[$y];
}
}
printf "\n";
}
}
#
# the Error subroutine will explain to the user what he/she/it did wrong.
# Possible errors are
# not a block device (ENBLK)
# file doesn't exist (ENFILE)
# no permissions (ENOPERM)
#
sub Error
{
local( $msg ) = @_;
if ( $msg eq "ENFILE" )
{
printf "The specified device file does not exist.\n";
&Usage;
}
if ( $msg eq "ENBLK" )
{
printf "The specified device file is not a block special
file.\n";
&Usage;
}
if ( $msg eq "ENOPERM" )
{
printf "Sorry, insufficient priveledges.\n";
exit(1);
}
}
#
# the usage subroutine will give the command usage
#
sub Usage
{
printf "Usage : fs.pl block_device\n";
exit(1);
}
#
# the ctime subroutine here is a modified version of that provided with the
# PERL distribution
#
# Original Author Waldemar Kebsch, Federal Republic of Germany, November 1988
# Modified by Marion Hakanson (hakanson@cse.ogi.edu)
# Modified by Chris Hare (chare@choreo.ca)
sub ctime {
@DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
@MoY = ('Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec');
local($time) = @_;
local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
# Determine what time zone is in effect.
# Use GMT if TZ is defined as null, local time if TZ undefined.
# There's no portable way to find the system default timezone.
$TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : '';
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
($TZ eq 'GMT') ? gmtime($time) : localtime($time);
# Hack to deal with 'PST8PDT' format of TZ
# Note that this can't deal with all the esoteric forms, but it
# does recognize the most common: [:]STDoff[DST[off][,rule]]
if($TZ=~/^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/){
$TZ = $isdst ? $4 : $1;
}
$TZ .= ' ' unless $TZ eq '';
$year += ($year < 70) ? 2000 : 1900;
sprintf("%s %s %2d %2d:%02d:%02d %s%4d",
$DoW[$wday], $MoY[$mon], $mday, $hour, $min, $sec, $TZ, $year);
}
#
# we won't execute this
#
printf "BUSTER!\n"
|