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

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

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

#! /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 3 (of 3)."
# Contents:  chkfile.c fsconfig.h
# Wrapped by mjy@sdti on Wed Nov 30 15:54:17 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f chkfile.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"chkfile.c\"
else
echo shar: Extracting \"chkfile.c\" \(15316 characters\)
sed "s/^X//" >chkfile.c <<'END_OF_chkfile.c'
Xstatic char sccsid[] = "@(#)$Id: chkfile.c, V4.1 88/11/16 17:29:30 $";
X
X/*
X * chkfile.c - analyze file
X * Version  : 4.1 - 88/11/16 17:29:30
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:00:44 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 * Fri Nov 11 16:25:44 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Fixed boundary condition error in scan().
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 * chk_indirects : scans a block containing data block numbers, looking
X * for block numbers that are not sequential.
X */
Xdaddr_t chk_indirects (block, cur_pos, data, inode, lbn)
Xdaddr_t block;                    /* indirect block to check */
Xdaddr_t cur_pos;                  /* current block offset */
Xstruct file_data *data;           /* current file statistics */
Xstruct dinode *inode;             /* inode being processed */
Xdaddr_t lbn;                      /* logical blk_no of 1st data block */
X{
X    daddr_t ind_blk[MAXINDIR];    /* holds an indirect block */
X    int num_blocks;               /* number of data blocks in
X                                   * an indirect block */
X    daddr_t pos;                  /* current data block */
X    daddr_t new_pos;              /* next data block */
X    int i;                        /* loop counter */
X    boolean sparse;               /* potential sparse 
X                                   * file detected */
X
X    num_blocks = nindir(fil_sys);
X    data->total_blocks += (bsize(fil_sys) / fsize(fil_sys));
X
X    /*
X     * the indirect block itself should be in the correct sequence
X     * with the data blocks
X     */
X    test_fragmentation (block, cur_pos, data);
X
X    /*
X     * get the indirect block
X     */
X    if (fseek (fsys, block * block_size, 0)){
X        error (errno, "\nerror seeking indirect block %ld\n", block);
X        /* NOTREACHED */
X        }
X    if (fread (ind_blk, sizeof (daddr_t), num_blocks, fsys) != num_blocks){
X        error (errno, "\nerror reading indirect block %ld\n", block);
X        /* NOTREACHED */
X        }
X    pos = block;
X
X    /*
X     * scan the data blocks looking for numbers out of sequence
X     */
X    sparse = FALSE;
X    for (i = 0; i < num_blocks; i++){
X        new_pos = ind_blk [i];
X        if (new_pos == 0){
X            sparse = TRUE;
X            continue;
X            }
X        if (sparse){
X            data->sparse++;
X            }
X        data->data_blocks += (blk_size (fil_sys, inode, lbn+i) / fsize(fil_sys));
X        data->total_blocks+= (blk_size (fil_sys, inode, lbn+i) / fsize(fil_sys));
X        test_fragmentation (new_pos, pos, data);
X        pos = new_pos;
X        }
X    return pos;
X    }
X
X/*
X * chk_double_indirects : scans a block containing a list of indirect
X * blocks, checking for data block numbers that are out of sequence.
X */
Xdaddr_t chk_double_indirects (block, cur_pos, data, inode, lbn)
Xdaddr_t block;                            /* indirect block to check */
Xdaddr_t cur_pos;                          /* current block offset */
Xstruct file_data *data;                   /* current file statistics */
Xstruct dinode *inode;                     /* inode being processed */
Xdaddr_t lbn;                              /* logical blk_no of 1st data block */
X{
X    daddr_t dindirect_blk[MAXINDIR];      /* holds a double-indirect
X                                           * block */
X    int i;                                /* loop counter */
X    int num_blocks;                       /* number of indirect blocks
X                                           * in a d-i block */
X    boolean sparse;                       /* potential sparse file
X                                           * detected */
X
X    num_blocks = nindir(fil_sys);
X    data->total_blocks += (bsize(fil_sys) / fsize(fil_sys));
X
X    /*
X     * the double-indirect block itself should be in sequence with the
X     * data blocks
X     */
X    test_fragmentation (block, cur_pos, data);
X
X    /*
X     * get the d-i block
X     */
X    if (fseek (fsys, block * block_size, 0)){
X        error (errno, "\nerror seeking double indirect block %ld\n",
X             block);
X        /* NOTREACHED */
X        }
X    if (fread (dindirect_blk, sizeof (daddr_t), num_blocks, fsys) != num_blocks){
X        error (errno, "\nerror reading double indirect block %ld\n",
X             block);
X        /* NOTREACHED */
X        }
X
X    /*
X     * scan through the d-i block
X     */
X    cur_pos = block;
X    sparse = FALSE;
X    for (i = 0; i < num_blocks; i++){
X        if (dindirect_blk[i] == 0){
X            sparse = TRUE;
X            continue;
X            }
X        if (sparse){
X            data->sparse++;
X            }
X        cur_pos = chk_indirects (dindirect_blk[i],
X                     cur_pos,
X                     data,
X		     inode,
X                     lbn + (i * nindir(fil_sys)));
X        }
X    return cur_pos;
X    }
X
X/*
X * chk_triple_indirects : scans a block containing a list of double
X * indirect blocks, looking for data block numbers that are out of sequence.
X */
Xdaddr_t chk_triple_indirects (block, cur_pos, data, inode, lbn)
Xdaddr_t block;                            /* indirect block to check */
Xdaddr_t cur_pos;                          /* current block offset */
Xstruct file_data *data;                   /* current file statistics */
Xstruct dinode *inode;                     /* inode being processed */
Xdaddr_t lbn;                              /* log. blk_no of 1st data block */
X{
X    daddr_t tindirect_blk[MAXINDIR];      /* holds a triple-indirect
X                                           * block */
X    int i;                                /* loop counter */
X    int num_blocks;                       /* number of double-indirect
X                                           * blocks in a triple-i blk */
X    boolean sparse;                       /* potential sparse file
X                                           * detected */
X
X
X    num_blocks = nindir(fil_sys);
X    data->total_blocks += (bsize(fil_sys) / fsize(fil_sys));
X
X    /*
X     * the triple-indirect block itself should be in sequence with the
X     * data blocks
X     */
X    test_fragmentation (block, cur_pos, data);
X
X    /*
X     * get the t-i block
X     */
X    if (fseek (fsys, block * block_size, 0)){
X        error (errno, "\nerror seeking triple indirect block %ld\n",
X             block);
X        /* NOTREACHED */
X        }
X    if (fread (tindirect_blk, sizeof (daddr_t), num_blocks, fsys) != num_blocks){
X        error (errno, "\nerror reading triple indirect block %ld\n",
X             block);
X        /* NOTREACHED */
X        }
X
X    /*
X     * scan through the t-i block
X     */
X    cur_pos = block;
X    sparse = FALSE;
X    for (i = 0; i < num_blocks; i++){
X        if (tindirect_blk[i] == 0){
X            sparse = TRUE;
X            continue;
X            }
X        if (sparse){
X            data->sparse++;
X            }
X        cur_pos = chk_double_indirects (tindirect_blk[i],
X                        cur_pos,
X                        data,
X			inode,
X                        lbn + (i * nindir (fil_sys) * nindir (fil_sys)));
X        }
X    return cur_pos;
X    }
X
X/*
X * chk_file : scans the data block numbers of an i-node, looking for
X * block numbers that are out of sequence, and would thus result in excess
X * track-to-track seeking.  This function also checks directory files for
X * indirection, and performs a simple consistency check on all file sizes.
X */
Xvoid chk_file (inode, inode_number, data)
Xstruct dinode *inode;                  /* inode info structure */
Xint inode_number;                      /* inode number to be
X                                        * checked */
Xstruct file_data *data;                /* current file statistics */
X{
X    daddr_t pos;                       /* current block */
X    daddr_t new_pos;                   /* next block in file */
X    int i;                             /* loop counter */
X    long file_size;                    /* file size computed by
X                                        * actual byte count */
X    boolean sparse;                    /* potential sparse file
X                                        * detected */
X
X    pos = blk_no (dta_blk (inode, 0)); /* first data block */
X
X    /*
X     * do some simple-minded statistics gathering
X     */
X    if (inode->di_nlink > 1){          /* multi-linked files */
X        linked_files++;
X        }
X
X    if (FILE_TYPE (inode) == S_IFDIR){ /* got a directory */
X        num_directories++;
X        }
X
X    /*
X     * no fragmentation checks for special files or 0-length files
X     */
X    if (IS_SPECIAL (inode->di_mode)){
X        num_specials++;
X	if (debug)printf ("inode %d is special\n", inode_number);
X        return;
X        }
X
X    if (inode->di_size == 0){
X	if (debug)printf ("inode %d is empty\n", inode_number);
X        return;                        /* ignore 0-size files */
X        }
X
X    data->data_blocks = data->total_blocks = (blk_size(fil_sys, inode, 1) / fsize (fil_sys));
X    if (debug)printf ("blk_size returns %ld\n", blk_size (fil_sys, inode, 1));
X
X    /*
X     * scan the data blocks looking for numbers out of sequence
X     */
X    sparse = FALSE;
X    for (i = 1; i < NDADDR; i++){
X        new_pos = blk_no (dta_blk (inode, i));
X        if (new_pos == 0){             /* end of file */
X            sparse = TRUE;
X            continue;
X            }
X        if (sparse){
X            data->sparse++;
X            }
X        data->data_blocks += (blk_size (fil_sys, inode, i) / fsize (fil_sys));
X        data->total_blocks += (blk_size (fil_sys, inode, i) / fsize (fil_sys));
X	if (debug)printf ("  blk_size returns %ld\n", blk_size(fil_sys,inode,i));
X        test_fragmentation (new_pos, pos, data);
X        pos = new_pos;
X        }
X
X    /*
X     * Indirect block 0, if non-zero, is the number of the block
X     * which contains the next NINDIR data block numbers.  It should
X     * also be in sequence with the data blocks.
X     */
X    if (blk_no (indir_blk (inode, 0))){
X        indirects++;
X        /*
X         * if a directory contains indirection, it is too large for
X         * efficient access.  Report it.
X         */
X        if (FILE_TYPE (inode) == S_IFDIR){
X            printf ("inode %d is a large directory\n", inode_number);
X            big_directories++;
X            }
X        pos = chk_indirects (blk_no (indir_blk (inode, 0)),
X                     pos,
X                     data,
X		     inode,
X                     NDADDR);
X        }
X
X    /*
X     * Indirect block 1, if non-zero, is the number of the block which contains
X     * the next NINDIR INDIRECT block numbers.  It should also be
X     * in sequence with the data blocks.  This block is called a "double-
X     * indirect" block.
X     */
X    if (blk_no (indir_blk (inode, 1))){
X        double_indirects++;
X        if (rpt_indirects){
X            printf ("double indirection : %d\n", inode_number);
X            }
X        pos = chk_double_indirects (blk_no (indir_blk (inode, 1)),
X                        pos,
X                        data,
X			inode,
X                        NDADDR+nindir(fil_sys));
X        }
X
X    /*
X     * Indirect block 2, if non-zero, is the number of the block which contains
X     * the next NINDIR DOUBLE-INDIRECT block numbers.  It should
X     * also be in sequence with the data blocks.  This block is called a
X     * "triple-indirect" block.
X     */
X    if (blk_no (indir_blk (inode, 2))){
X        triple_indirects++;
X        if (rpt_indirects){
X            printf ("triple indirection : %d\n", inode_number);
X            }
X        pos = chk_triple_indirects (blk_no (indir_blk (inode, 2)),
X                        pos,
X                        data,
X			inode,
X                        NDADDR + (nindir (fil_sys) * nindir (fil_sys)));
X        }
X
X    /*
X     * detect and display sparse files
X     */
X    if (data->sparse){
X        printf ("inode %d is sparse\n", inode_number);
X        sparse_files++;
X        }
X
X    /*
X     * do a simple check to detect possible file-size errors (a la
X     * fsck phase 1)
X     */
X    file_size = (inode->di_size + (block_size - 1)) / block_size;
X    data->wasted = (block_size - (inode->di_size % block_size));
X    if (file_size != data->data_blocks){
X        size_errors++;
X        if (rpt_errors){
X            printf ("inode %d, inconsistent file size : actual blocks = %ld, computed = %ld (%ld bytes)\n",
X                inode_number, data->data_blocks, 
X                file_size, inode->di_size);
X            }
X        }
X    }
X
X/*
X * scan : scan through each i-node of a file system, compiling statistics
X * regarding fragmentation and indirection.
X */
Xvoid scan (){
X    int    i, j;                        /* loop counters */
X    struct dinode i_node[MAXINOPB];     /* holds a block of inodes */
X    struct file_data data;              /* per-inode statistics */
X
X    for (i = first_inode; i < num_inodes(fil_sys); i+=inopb(fil_sys)){
X
X        /*
X         * for efficiency, read a block of i-nodes at a time
X         */
X        get_inodes (i, i_node, inopb(fil_sys));
X
X        /*
X         * scan through each i-node that was read in
X         */
X        for (j = 0; i+j <= num_inodes(fil_sys) && j < inopb(fil_sys); j++){
X            if (debug){
X                printf ("inode %d = mode %o\r", i+j, i_node[j].di_mode);
X                }
X            if (i+j <= 1)continue;                 /* don't scan i-node 1 */
X            if (i_node[j].di_mode != 0){           /* unused i-node ? */
X                init_stats (&data, i+j, i_node[j].di_size);
X                chk_file (&i_node[j], i+j, &data); /* scan blocks in file */
X                log_stats (&data);
X                }
X            else {
X                free_inodes++;
X                }
X            }
X        }
X    }
X
X/*
X * anal_file : analyzes a single file for fragmentation.
X */
Xvoid anal_file (ino, fname)
Xint ino;                        /* i-node number */
Xchar *fname;                    /* filename of this inode */
X{
X    struct file_data data;      /* current file statistics */
X
X    struct dinode i_node;       /* current inode data */
X
X    get_inodes (ino, &i_node, 1);
X    init_stats(&data, ino, i_node.di_size);
X    chk_file (&i_node, ino, &data);
X    log_stats (&data);
X    printf ("   %-14s\t%6d    %6ld   %6ld   %6.2f%%  %6.1f  %ld\n",
X        fname, data.inode, data.seeks+1, 
X        data.total_blocks, data.fragm*100,
X        data.rel_cost, data.wasted);
X    }
END_OF_chkfile.c
if test 15316 -ne `wc -c <chkfile.c`; then
    echo shar: \"chkfile.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fsconfig.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fsconfig.h\"
else
echo shar: Extracting \"fsconfig.h\" \(12938 characters\)
sed "s/^X//" >fsconfig.h <<'END_OF_fsconfig.h'
X/* @(#)$Id: fsconfig.h, V4.1.1.1 88/11/18 17:38:35 $ */
X
X/*
X * fsconfig.h - fsanalyze configuration-specific definitions
X * Version  : 4.1.1.1 - 88/11/18 17:38: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 */
X
X/*
X * Modification History:
X *
X *    Date       Author                   Description
X * -----------  --------  -----------------------------------------------
X * Wed Mar  9 17:51:38 EST 1988 - M. Young (mjy@sdti.SDTI.COM)
X *    Originated.
X *
X * Wed Apr 13 17:18:06 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
X *    Completed port to BSD.  Added fsize(), first_inode, and Sec_per_blk
X *    macros.
X *
X * Wed Jun 15 14:06:35 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
X *    Added NUMOFFEND macro.
X *
X * Tue Jul 26 15:27:52 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
X *    Modified Opt_interleave and cyl_pos macros to more closely reflect BSD
X *    placement algorithm (still unsure of this!).
X *
X * Thu Jul 28 16:43:20 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
X *    Opt_interleave formula now makes sense.
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 * Fri Nov 18 17:37:08 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
X *    Removed #defines for SUPERBOFF for all but XENIX/286
X */
X
X/*
X * One of the things fsanalyze displays is a list of the most fragmented
X * files.  The macro NUMOFFEND 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 * (5 lines).
X */
X#ifndef NUMOFFEND
X# define NUMOFFEND	10	/* number of top offenders to report	*/
X#endif
X
X/*
X * File System types - define _FS_TYPE accordingly
X */
X#define FS_ATT         1       /* AT&T File system derivatives, incl Version 7,
X                                * System III, & System V (sVr2 & sVr3) */
X#define FS_BSD         2       /* BSD fast file system derivatives */
X#define FS_BSD_NFS     3       /* BSD fast file system with NFS support */
X
X/*
X * OS-types -- although the basic structure of the file system remains
X * constant, many ports of Unix contain minor modifications.  Eventually,
X * the following should contain a complete list of special cases.  Those
X * OS's which do not contain special cases should be referred to as OS_ATT
X * or OS_BSD.
X */
X#define OS_ATT         1       /* Generic AT&T OS, no special cases */
X#define OS_BSD         2       /* Generic BSD 4.2 or later FFS, no special
X                                * cases */
X#define OS_XENIX_286   4       /* XENIX/286 */
X#define OS_UPORT_286   5       /* Microport System V/AT */
X
X#ifndef FS_TYPE
X# define FS_TYPE    FS_ATT
X#endif
X
X#ifndef OS_TYPE
X# define OS_TYPE    OS_ATT
X#endif
X
X
X/***************************************************************************
X *                            file system macros                           *
X ***************************************************************************/
X
X/*
X * File systems based on Version 7 Unix (System III and System V) are
X * significantly different than those based on the BSD Fast File System.
X * The following macros are defined to facilitate portable access to the
X * superblock and inode information.  Where possible, macro names 
X * the BSD <sys/fs.h> are used, and these macros must be created for non
X * BSD file systems.
X *
X *    SUPERBOFF                 Byte offset of the superblock
X *    DEV_BSIZE                 Physical device block size (sector size)
X *    MAXBSIZE                  Maximum block size of any file system
X *    MAXINOPB                  Maximum number of inodes per block (based
X *                              on largest possible block size of any file
X *                              system
X *    MAXINDIR                  Maximum number of indirect blocks per block
X *                              (based on largest possible block size of any
X *                              file system)
X *    inopb(fs)                 Number of inodes per block of a given file
X *                              system
X *    nindir(fs)                Number of indirect blocks per block in a
X *                              given file system
X *    bsize(fs)                 Block size (in bytes) of a given file system
X *    fsize(fs)                 Fragment size (in bytes) -- same as bsize()
X *                              in non-BSD file systems
X *    fssize(fs)                Total size of a file system (in blocks of
X *                              bsize(fs) bytes)
X *    dsize(fs)                 Number of data blocks in the file system
X *    isize(fs)                 Total number of blocks reserved for inode info
X *    num_inodes(fs)            Number of inodes supported by the file system
X *    first_inode               number of first inode in file system
X *    iblkno(fs)                Block number of the first inode in a file
X *                              system (or cylinder group)
X *    sec_per_cyl(fs)           Number of physical sectors per cylinder in
X *                              a given file system
X *    is_ok(fs)                 TRUE if the file system is not in need of
X *                              checking (with fsck(1M))
X *    opt_interleave(fs)        The optimum sector interleave which will result
X *                              in minimum rotational delay.
X *    Sec_per_blk               Number of sectors per logical block
X *    freespace(fs,res)         Total number of free blocks in a file system,
X *                              given a percentage that must be held in reserve
X *    inode_block(fs,inode)     Computes block number which contains inode info
X *    inode_offset(fs,inode)    Computes offset of an inode within its block
X *    blk_size(fs,inode,lbn)    Computes the size of a data block in bytes
X *    cylinder(fs,blk)          Computes cylinder which contains specified
X *                              block
X *    cyl_pos(fs,blk)           Computes relative sector position of the
X *                              specified block in its cylinder.
X *    NDADDR                    Number of direct data blocks within inode
X *    NIADDR                    Number of indirect data blocks within inode
X *    dta_blk(blk)              Returns pointer to data block within inode
X *                              cast as (char *) for compatibility with
X *                              AT&T file systems.
X *    indir_blk(blk)            Returns pointer to indirect block within inode
X *                              cast as (char *) for compatibility with
X *                              AT&T file systems.
X */
X
X/*
X * Sec_per_blk : Number of physical sectors (size DEV_BSIZE) per logical block.
X */
X#define Sec_per_blk             (block_size / DEV_BSIZE)
X
X#if (FS_TYPE == FS_ATT)
X
X/*
X * The following definitions provide the above-listed macros for a
X * "conventional" Unix file system.  Any versions of Unix that use a
X * file system structure that was derived directly from Version 7 Unix
X * (e.g., System III, System V, XENIX) use these definitions.
X */
X
Xtypedef struct filsys superblk_t;       /* superblock structure definition */
X
X/* SCO XENIX doesn't have SUPERBOFF, so we must set it explicitly.  Note
X * that XENIX/286 seems to want the value BSIZE*SUPERB (==1024L), yet
X * XENIX/386 is "normal" SystemV (512L).
X */
X# if (OS_TYPE == OS_XENIX_286)
X#   define SUPERBOFF	(BSIZE*SUPERB)
X# endif
X
X# define DEV_BSIZE      512
X
X/*
X * MAXBSIZE is defined as the largest possible BSIZE for any file system.
X * The largest I have come across in System V ports is 2048.  If a larger
X * one is encountered, MAXBSIZE should be increased accordingly.
X */
X# define MAXBSIZE       2048
X# define MAXINOPB       (MAXBSIZE / sizeof (struct dinode))
X# define MAXINDIR       (MAXBSIZE / sizeof (daddr_t))
X# ifdef FsINOPB
X#  define inopb(fs)	FsINOPB(fs)
X# else
X#  define inopb(fs)     INOPB
X# endif
X# ifdef FsNINDIR
X#  define nindir(fs)	FsNINDIR(fs)
X# else
X#  define nindir(fs)    NINDIR
X# endif
X
X/*
X * The following definition is used to determine the logical block size for
X * a particular file system.  Normally, SBUFSIZE == BSIZE == the logical
X * block size.  However, in systems that have dual file system support
X * enabled (rare), BSIZE is usually set to the block size of the smaller
X * file system, whereas SBUFSIZE is set to the larger.  If this is
X * different in your system, change the following macro accordingly.
X */
X# ifdef Fs2b
X#  define bsize(fs)      ((fs)->s_type == Fs2b ? SBUFSIZE : BSIZE)
X# else
X#  define bsize(fs)	 (BSIZE)
X# endif
X# define fsize(fs)       (bsize(fs))
X
X# define fssize(fs)      ((fs)->s_fsize)
X# define dsize(fs)       ((fs)->s_fsize - (fs)->s_isize)
X# define isize(fs)       ((fs)->s_isize)
X# define num_inodes(fs)  (((fs)->s_isize-ROOTINO) * inopb(fs))
X# define first_inode     1
X# define iblkno(fs)      2
X# define sec_per_cyl(fs) ((fs)->s_dinfo[1])
X
X/*
X * Note that the standard check for file system integrity does not work
X * on Microport systems because a clean, unmounted file system is not set
X * to FsOKAY, but some other undocumented constant.  It is therefore
X * strongly recommended that the HAVE_FSSTAT macro be defined for Microport
X * systems.
X */
X# if (OS_TYPE == OS_UPORT_286)
X#  define is_ok(fs) (TRUE)
X#  ifndef HAVE_FSSTAT
X#   define HAVE_FSSTAT
X#  endif
X# else
X#  if (OS_TYPE == OS_XENIX_286)
X#   define is_ok(fs) (TRUE)
X#  else
X#   define is_ok(fs) ((fs)->s_state == FsOKAY) || ((fs)->s_state == FsACTIVE)
X#  endif
X# endif
X
X# define opt_interleave(fs)      ((fs)->s_dinfo[0])
X# define freespace(fs,reserved)  ((fs)->s_tfree)
X# define inode_block(fs,inode)   (iblkno(fs) + (((inode)-1) / inopb(fs)))
X# define inode_offset(fs,inode)  (((inode)-1) % inopb(fs))
X# define blk_size(fs, inode, lbn) (bsize(fs))
X# define cylinder(fs,blk)        ((daddr_t)(blk) * Sec_per_blk / cyl_size)
X# define cyl_pos(fs,blk)         ((daddr_t)(blk) * Sec_per_blk % cyl_size)
X
X/*
X * inode data/indirect block access
X */
X# define NDADDR                  10    /* direct addresses in inode */
X# define NIADDR                  3     /* indirect addresses in inode */
X
X# define dta_blk(ino, blk)       (&(ino)->di_addr[(blk)*3])
X# define indir_blk(ino, blk)     (&(ino)->di_addr[((blk)+10)*3])
X
X#endif /* FS_TYPE == FS_ATT */
X
X#if ((FS_TYPE == FS_BSD) || (FS_TYPE == FS_BSD_NFS))
X
X/*
X * The following definitions provide the above-listed macros for a derivative
X * of the BSD Fast File System.
X */
X
Xtypedef struct fs superblk_t;    /* superblock structure definition */
X
X# define SUPERBOFF        (SBLOCK * DEV_BSIZE)
X/* DEV_BSIZE is defined in <sys/fs.h> */
X/* MAXBSIZE is defined in <sys/fs.h>  */
X# define MAXINOPB         (MAXBSIZE / sizeof (struct dinode))
X# define MAXINDIR         (MAXBSIZE / sizeof (daddr_t))
X# define inopb(fs)        INOPB(fs)
X# define nindir(fs)       NINDIR(fs)
X# define bsize(fs)        ((fs)->fs_bsize)
X# define fsize(fs)        (bsize(fs) / (fs)->fs_frag)
X# define fssize(fs)       ((fs)->fs_size)
X# define dsize(fs)        ((fs)->fs_dsize)
X# define isize(fs)        ((fs)->fs_ncg * (fs)->fs_ipg / inopb(fs))
X# define num_inodes(fs)   (isize(fs) * inopb(fs))
X# define first_inode      0
X# define iblkno(fs)       ((fs)->fs_iblkno)
X# define sec_per_cyl(fs)  ((fs)->fs_spc)
X
X/*
X * How do we determine file system integrity on a BSD file system?
X */
X# define is_ok(fs)        (TRUE)
X
X# define opt_interleave(fs) \
X         (((fs)->fs_rps * (fs)->fs_nsect * (fs)->fs_rotdelay /* sectors */\
X           + ((NSPB(fs)*1000)-1)) / 1000)      /* round up */
X
X/* freespace(fs,res) is defined in <sys/fs.h> */
X# define inode_block(fs,inode)   itod((fs),(inode))
X# define inode_offset(fs,inode)  itoo((fs),(inode))
X# define cylinder(fs,blk)        cbtocylno((fs),(blk))
X# define cyl_pos(fs,blk)         (cbtorpos((fs),(blk)) * NRPOS)
X
X# define blk_size(fs, inode, lbn)  (dblksize (fs, inode, lbn))
X
X/*
X * inode data/indirect block access
X */
X/* NDADDR is defined in inode.h */
X/* NIADDR is defined in inode.h */
X# define dta_blk(ino,blk)        ((char *)&((ino)->di_db[blk]))
X# define indir_blk(ino,blk)      ((char *)&((ino)->di_ib[blk]))
X
X# endif  /* FS_TYPE == FS_BSD || FS_TYPE == FS_BSD_NFS */
END_OF_fsconfig.h
if test 12938 -ne `wc -c <fsconfig.h`; then
    echo shar: \"fsconfig.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
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