bf version 1.2

Brant Cheikes brant at manta.pha.pa.us
Sat Jun 10 04:00:57 AEST 1989


This is a new release of bf, a UNIXpc utility that, given a logical
block number (obtained, say, from an error message logged to the
unix.log file in /usr/adm), will look up and return the inode number
to which that block belongs.  Use it in good health. -b

#! /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 shell archive."
# Contents:  bf.c bf.1m
# Wrapped by brant at manta on Fri Jun  9 13:50:03 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'bf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bf.c'\"
else
echo shar: Extracting \"'bf.c'\" \(8968 characters\)
sed "s/^X//" >'bf.c' <<'END_OF_FILE'
X/*
X * bf.c 1.2
X * Search filesystem for particular blocks, returning corresponding inodes.
X *
X * Brant Cheikes
X * University of Pennsylvania, Department of Computer and Information Science
X * brant at manta.pha.pa.us, brant at linc.cis.upenn.edu, bpa!manta!brant
X *
X * Copyright (c) 1989 Brant A. Cheikes.  All rights reserved.
X *
X * bf is distributed in the hope that it will be useful, but WITHOUT ANY
X * WARRANTY.  No author or distributor accepts responsibility to anyone
X * for the consequences of using it or for whether it serves any particular
X * purpose or works at all, unless he says so in writing.
X *
X * Everyone is granted permission to copy, modify and redistribute bf,
X * but only under the conditions described in the GNU General Public License.
X * Among other things, the copyright notice and this notice must be preserved
X * on all copies.
X *
X * Modification History:
X *  1.1		Tue May 23 20:40:03 EDT 1989
X *	Peter Fales (att!ihlpb!psfales, psfales at ihlpb.att.com)
X *	reported a bug in which the first three blocks in the
X *	filesystem were incorrectly treated as part of the i-list.
X *	Some other minor fixups too, while I'm at it.
X *  1.2		Tue Jun  6 01:31:41 EDT 1989
X *	Peter Fales strikes again.  Found a bug in which bf would
X *	incorrectly search for block n, where n = superb.s_fsize.
X *	Minor tweaks.
X */
X
X#ifndef lint
Xstatic char *sccs = "@(#)bf.c	1.2";
X#endif
X
X#define KERNEL
X#include <stdio.h>
X#include <ctype.h>
X#include <fcntl.h>
X#include <sys/filsys.h>
X#include <sys/ino.h>
X#include <sys/inode.h>
X#include <sys/types.h>
X#include <sys/param.h>
X
X/*
X * Macros to manipulate block bitmap.
X * setmapbit(m,b) turns on the bit in bitmap m corresponding to block b.
X * inmap(m,b) evaluates to non-zero if block b's bit is on in map m.
X */
X#define setmapbit(m,b) *(m+((int)(b)>>3)) |= (char)(1<<((b)&7))
X#define inmap(m,b) (*(m+((b)>>3)) & (char)(1<<((b)&7)))
X
Xchar errmsg[100];
X
Xextern long lseek();
Xextern char *calloc();
Xextern void free(), perror(), exit();
X
X/*
X * Main program.
X */
Xmain(argc,argv)
X     int argc;
X     char **argv;
X{
X  int nblk;			/* number of blocks to find */
X  int fsdev;			/* file system to scan */
X  struct filsys superblk;	/* the superblock <sys/filsys.h> */
X  char *bitmap;			/* bitmap of allocated blocks */
X  void getsb();
X
X  /*
X   * Verify we were given at least three arguments.
X   */
X  if (argc < 3) {
X    (void) fprintf(stderr,"Usage: %s filesystem numbers\n",*argv);
X    exit(1);
X  }
X
X  /*
X   * Open the filesystem and read the superblock.
X   */
X  if ((fsdev = open(argv[1],O_RDONLY)) == EOF) {
X    (void) sprintf(errmsg,"cannot open %s",argv[1]);
X    perror(errmsg);
X    exit(1);
X  }
X  getsb(fsdev,&superblk);
X
X  /*
X   * Initialize the bitmap.
X   *
X   * The bitmap consists of one bit for each block in the filesystem.
X   * Bits in the bitmap are turned on for blocks that are being sought.
X   */
X  bitmap = calloc((unsigned)((superblk.s_fsize>>3)+1),sizeof(char));
X  if (bitmap == (char *)NULL) {
X    perror("calloc failed in main");
X    exit(1);
X  }
X
X  /*
X   * Read list of blocks from command line.
X   */
X  for (nblk = (argc -= 2), argv += 2; argc-- ; ++argv) {
X    long blk;
X    extern long atol();
X
X    blk = atol(*argv);
X    if (blk == 0) {
X      (void) puts("block 0 is superblock!");
X      --nblk;
X    } else if (blk == 1) {
X      (void) puts("block 1 reserved");
X      --nblk;
X    } else if (blk < superblk.s_isize) {
X      (void) printf("block %ld in i-list\n",blk);
X      --nblk;
X    } else if (blk >= superblk.s_fsize) {
X      (void) printf("block %ld out of range\n",blk);
X      --nblk;
X    } else
X      /*
X       * Turn on the bit in the bitmap corresponding to this block.
X       */
X      setmapbit(bitmap,blk);
X  }
X
X  /*
X   * Look for all blocks that remain.
X   */
X  if (nblk)
X    exit(scan_ilist(fsdev,&superblk,nblk,bitmap));
X  else {
X    (void) close(fsdev);
X    exit(0);
X  }
X}
X
X/*
X * Top-level loop of search.
X *
X * We scan thru the i-list, looking at inodes for regular, directory, or
X * fifo files.  For those inodes, we scan the allocated block lists for
X * the blocks we're searching for.
X *
X * Returns non-zero on error.
X */
Xint
Xscan_ilist(fp,superb,blkcnt,map)
X     int fp, blkcnt;
X     struct filsys *superb;
X     register char *map;
X{
X  int inoblk;			/* block in ilist being scanned */
X  int inode;			/* current inode */
X  int bcnt = 0;			/* count of sought blocks found */
X  struct dinode inobuf[INOPB];	/* a block's worth of inodes <sys/ino.h> */
X
X  /*
X   * Start at the root inode block (ROOTINO defined in <sys/param.h>).
X   * Loop through each block in the ilist.
X   */
X  for (inoblk = ROOTINO, inode = 1; inoblk < superb->s_isize; ++inoblk) {
X    int i;
X
X    /*
X     * Read a block.  If an error occurs (like a read failure), just
X     * move on to the next block in the ilist.
X     */
X    if (getblk((long)inoblk,(char *)inobuf,fp))
X      continue;
X
X    /*
X     * Loop through each inode in this block.
X     */
X    for (i = 0; i < INOPB; ++i, ++inode) {
X      if (inobuf[i].di_mode & IFREG || /* regular file */
X	  inobuf[i].di_mode & IFIFO || /* fifo */
X	  inobuf[i].di_mode & IFDIR) { /* directory */
X	if ((bcnt += scan_inode(fp,inobuf+i,inode,map)) == blkcnt) {
X	  (void) close(fp);
X	  return(0);
X	} else if (bcnt > blkcnt) {
X	  /*
X	   * A rare but possible scenario.  If we find more blocks than
X	   * we were looking for, that means that there's at least one
X	   * block allocated to more than one file.  So print error
X	   * message and quit.
X	   */
X	  (void) fputs("multiply-allocated block found--run fsck",stderr);
X	  return(1);
X	}
X      }
X    }
X  }
X  (void) close(fp);
X  return(0);
X}
X
X/*
X * Scan the list of allocated blocks in a particular inode.
X *
X * Input:
X *  fp: pointer to open filesystem
X *  inoptr: pointer to a disk inode
X *  ino: # of inode pointed to by inoptr
X *  map: pointer to block bitmap
X *
X * Returns:
X *  number of blocks found
X */
Xint
Xscan_inode(fp,inoptr,ino,map)
X     register struct dinode *inoptr;
X     int fp, ino;
X     register char *map;
X{
X  int i, bcnt = 0;
X  static long daddr[13];
X  extern void l3tol();
X
X  /*
X   * Convert the di_addr area to an array of block numbers.
X   */
X  l3tol(daddr,inoptr->di_addr,13);
X
X  /*
X   * Scan array.
X   */
X  for (i = 0; i < 13; ++i) {
X    if (daddr[i] && inmap(map,daddr[i])) {
X      (void) printf("block %ld inode %d\n",daddr[i],ino);
X      ++bcnt;
X    }
X
X    /*
X     * Scan indirect blocks.
X     */
X    if (i > 9 && daddr[i])
X      bcnt += scan_iblock(fp,daddr[i],i-9,ino,map);
X  }
X  return(bcnt);
X}
X
X/*
X * Recursive scan of indirect blocks.
X * Returns number of sought blocks that were found.
X */
Xint
Xscan_iblock(fp,blk,ilevel,ino,map)
X     long blk;
X     int fp, ilevel, ino;
X     register char *map;
X{
X  if (ilevel < 1 || ilevel > 3) {
X    (void) fputs("internal error: bad ilevel in scan_iblock",stderr);
X    exit(1);
X  } else {
X    int i, bcnt = 0;
X    long *ib;
X
X    ib = (long *)calloc((unsigned)(BSIZE/sizeof(long)),sizeof(long));
X    if (ib == (long *)NULL) {
X      perror("calloc failed in scan_iblock");
X      exit(1);
X    }
X
X    /*
X     * Try to read the indirect block.  If that succeeds,
X     * check each block that it points to.
X     */
X    if (getblk(blk,(char *)ib,fp) == 0) {
X      for (i = 0; i < BSIZE/sizeof(long); ++i) {
X	long iblk = *(ib+i);
X
X	if (iblk) {
X	  if (inmap(map,iblk)) {
X	    (void) printf("block %ld inode %d\n",iblk,ino);
X	    ++bcnt;
X	  }
X	  if (ilevel > 1)
X	    bcnt += scan_iblock(fp,iblk,ilevel-1,ino,map);
X	}
X      }
X    }
X    free((char *)ib);
X    return(bcnt);
X  }
X}
X
X/*
X * Read the superblock off the specified (open) device.
X * All errors are fatal.
X */
Xvoid
Xgetsb(fp,superb)
X     int fp;
X     register struct filsys *superb;
X{
X  /*
X   * SUPERBOFF is offset in bytes of superblock in block 0 of filesystem.
X   * It's defined in <sys/param.h>
X   */
X  if (lseek(fp,(long)SUPERBOFF,0) < 0L) {
X    perror("lseek failed in getsb");
X    exit(1);
X  }
X  if (read(fp,(char *)superb,sizeof(struct filsys)) < sizeof(struct filsys)) {
X    perror("superblock read failed");
X    exit(1);
X  }
X  if (superb->s_magic != FsMAGIC) {
X    (void) fputs("bad magic in superblock--not a filesystem?",stderr);
X    exit(1);
X  }
X}
X
X/*
X * getblk(n,bufp,dev)
X *
X * Read logical block #n of device dev into area pointed to by bufp.
X *
X * NB: This uses the (portable) lseek() call rather than diddling the
X * disk controller directly.  As a result it may be slow.
X */
Xint
Xgetblk(n,bufp,fp)
X     long n;
X     register char *bufp;
X     int fp;
X{
X  /*
X   * lseek errors are fatal.
X   *
X   * dbtob(x) defined in <sys/sysmacros.h>
X   * disk blocks to bytes
X   */
X  if (lseek(fp,dbtob(n),0) < 0L) {
X    (void) sprintf(errmsg,"lseek to block %ld failed",n);
X    perror(errmsg);
X    exit(1);
X  }
X  /*
X   * read errors are reported, but do not cause termination.
X   *
X   * BSIZE is size of a logical block in bytes
X   * defined in <sys/param.h>
X   */
X  if (read(fp,bufp,BSIZE) < BSIZE) {
X    (void) sprintf(errmsg,"read error (block %ld)",n);
X    perror(errmsg);
X    return(1);
X  }
X  return(0);
X}
END_OF_FILE
if test 8968 -ne `wc -c <'bf.c'`; then
    echo shar: \"'bf.c'\" unpacked with wrong size!
fi
# end of 'bf.c'
fi
if test -f 'bf.1m' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bf.1m'\"
else
echo shar: Extracting \"'bf.1m'\" \(1856 characters\)
sed "s/^X//" >'bf.1m' <<'END_OF_FILE'
X.TH BF 1M "6 June 1989" "Version 1.2"
X.SH NAME
Xbf \- find inodes corresponding to given blocks
X.SH SYNOPSIS
X.B bf
Xfilesystem block [ block ... ]
X.SH DESCRIPTION
X.I Bf
Xsearches the given
X.I filesystem
Xfor the inodes to which the
X.I blocks
Xare allocated.  Blocks 0 and 1 of the filesystem are special: block 0
Xis the
X.B superblock
Xand block 1 is reserved (NB: blocks in the UNIXpc filesystem
Xare 1024 bytes long).  Following block 1 is the i-list, a set of
Xblocks reserved for the inodes.  There are 16 inodes per block on the
XUNIXpc; from the count of total inodes (using
X.I df -t),
Xyou can calculate the number of blocks used by the i-list.
X.I Bf
Xwill tell you if a given block falls within the i-list.
X.P
XFor each block that is within the filesystem, yet not an i-list or
Xspecial block,
X.I bf
Xwill search for the inode to which that block is allocated.  When the
Xblock is found,
X.I bf
Xwill print a diagnostic of the form "block b inode i,"
Xwhere
X.B b
Xis the block number and
X.B i
Xis the owning inode.  You may then use
X.I ncheck
Xto find the file name from the inode.
X.P
X.I Bf
Xterminates the search as soon as all specified blocks are found.  If a
Xblock is not found, then it is free.
X.SH EXAMPLE
Xbf /dev/rfp002 14016 4127
X.br
X.RS
XThis searches the filesystem on /dev/rfp002 for blocks 14016 and 4127.
X.RE
X.SH RESTRICTIONS
X.I Bf
Xtrusts that the filesystem is consistent.  If you have any doubts, run
X.I fsck
Xfirst.
X.SH "SEE ALSO"
Xfsck(1m), ncheck(1m), fs(4)
X.SH AUTHOR
XBrant A. Cheikes
X.br
XUniversity of Pennsylvania
X.br
XDepartment of Computer and Information Science
X.bf
Xbrant at manta.pha.pa.us, brant at linc.cis.upenn.edu
X.SH COPYING
XCopyright (c) 1989 Brant A. Cheikes.  All rights reserved.
X.P
XPermission is granted to make and distribute verbatim copies of
Xthis manual provided the copyright notice and this permission notice
Xare preserved on all copies.
END_OF_FILE
if test 1856 -ne `wc -c <'bf.1m'`; then
    echo shar: \"'bf.1m'\" unpacked with wrong size!
fi
# end of 'bf.1m'
fi
echo shar: End of shell archive.
exit 0
-- 
Brant Cheikes
University of Pennsylvania, Department of Computer and Information Science
brant at manta.pha.pa.us, brant at linc.cis.upenn.edu, bpa!manta!brant



More information about the Unix-pc.sources mailing list