#!/bin/bash
#
#  This script verifies that the structure of the cdrom of 
#  a RedHat distribution has the proper characteristics.
#  There is a single argument: $rootdir which is the root of the
#  filesystem to check (e.g. the place where you mounted the CD)
#  This script will decide which architecture the cd is for and which of
#  the two cd's it is.
#
#  This script, and its associated component, 
#  chkcdboot, are assumed to be in the path.
#  The script ckcdrom is called as follows:
#  ckcdrom /mnt/cdrom  to check the logical structure of a disc1
#                      or to check disc2.
#  ckcdrom /mnt/cdrom --iso /dev/cdrom to check not only the 
#                      logical structure of the iso9660 cdrom
#                      mounted on /mnt/cdrom, but to check the
#                      bootable nature of the cdrom as mounted
#                      on /dev/cdrom.
#

version="1.2.0"

function unsigned () {
#
# this function accepts a list of RPMs, and checks to see if they are PGP 
# signed.
#
for i in $@ ; do
  rpm -K $i | grep -v -i pgp
done
}

function isdir () {
  if [ ! -d `pwd`/$1 ]; then
    echo "Directory  `pwd`/$1 is missing"
    let thisdirerrs=$thisdirerrs+1
  fi
}



function isblock () {
  if [ ! -b `pwd`/$1 ]; then
    echo "Block Device `pwd`/$1 is missing"
    let thisdirerrs=$thisdirerrs+1
  fi
}

function ischar () {
  if [ ! -c `pwd`/$1 ]; then
    echo "Character Device `pwd`/$1 is missing"
    let thisdirerrs=$thisdirerrs+1
  fi
}

function isfile () {
  if [ ! -f `pwd`/$1 ]; then
    echo "File `pwd`/$1 is missing"
    let thisdirerrs=$thisdirerrs+1
  fi
}

function islink () {
  
  perl -e '$_=shift(@ARGV);exit 4 if !-l $_;' $1
  rc=$?
  if [ $rc -ne 0 ]; then
    echo "File `pwd`/$1 is not a link."
    let thisdirerrs=$thisdirerrs+1
  fi
}

function isexe () {
  if [ $1 != "`pwd`/TRANS.TBL" ]; then
    if [ -f $1 ]; then
      #echo "isexe($1)"
      perl -e '$_=shift(@ARGV);exit 4 if !-x $_ && !-X $_;' $1
      rc=$?
      #echo "perl rc $rc"
      if [ $rc -ne 0 ]; then
        if [ $1 != "`pwd`/TRANS.TBL" ]; then
          echo "File $1 has incorrect attributes."
          let thisdirerrs=$thisdirerrs+1
        fi
      fi
    fi
  fi
}

#
# the script begins here.  
#

#export PATH=$PATH:/usr/rhs/bin
rootdir=$1
if [ "$rootdir" = "--version" ]; then
  echo "ckcdrom version $version."
  exit 0
fi
let nopgp=0;
if [ "$rootdir" = "--nopgp" ]; then
  let nopgp=1
  rootdir=$2
fi
if [ -z "$rootdir" ]; then
  echo "useage: ckcdrom <root dir to check> checks logical file structure"
  echo "        ckcdrom <--iso> <iso image file> checks an iso image"     
  echo "        ckcdrom <--iso> <device> checks a device e.g. a cdrom"    
  echo "        ckcdrom --nopgp <root dir or filesystem options> inhibits the PGP checks"
  echo "        ckcdrom --version displays the version of the script."
  exit 1
fi
isotest=$rootdir
echo $isotest
if [ "$isotest" = "--iso" ]; then
  #
  #  Here we perform the the bootable test.
  #  chkcdboot (Dr Mike's code) is assumed to reside in the
  #  same directory as this script
  #
  echo "going down the iso path"
  bootdir=$2
  echo "bootdir $bootdir"
  if [ -n "$bootdir" ]; then
    echo "bootdir not null $bootdir" 
    chkcdboot $bootdir
    #
    # at this point we will mount the file or device on /tmp/foo.pid
    #
    mkdir /tmp/foo.$$
    rootdir=/tmp/foo.$$
    if [ $? -ne 0 ]; then
      # mkdir failed
      echo "Could not make a directory to mount $bootdir on; exit!"
      exit 4
    fi
    #
    # now determine whether we have an iso image file or a device
    #
    if [ -f $isodir ]; then
      # iso image file
      mount -o loop $bootdir /tmp/foo.$$
      if [ $? -ne 0 ]; then
        # mount failed
        echo "Unable to mount file $bootdir on /tmp/foo.$$"
        rmdir /mnt/foo.$$
        exit 4
      fi
    else
      mount -t iso9660 -r $bootdir /tmp/foo.$$
      if [ $? -ne 0 ]; then
        # mount failed
        echo "Unable to mount device $bootdir on /tmp/foo.$$"
        rmdir /mnt/foo.$$
        exit 4
      fi
    fi 
  else
    echo "No iso file system specifier, bootability unchecked!"
    exit 4
  fi
fi

pgploc=`whereis pgp`
echo " pgploc: $pgploc"
if [ "$pgploc" = "pgp:" ]; then
  let nopgp=1
fi
echo "nopgp = $nopgp"
let toterrs=0
let thisdirerrs=0
pushd `pwd`
cd $rootdir
#
# determine whether this a disc1 or a disc2
#
if [ -d `pwd`/RedHat ]; then
  let disc=1
  echo "Checking disc 1"
  # 
  # if it's a disc 1, then check for the architecture
  #
  if [ -f `pwd`/RedHat/i386 ]; then
    let arch=1
    echo "For an intel architecture."
  elif [ -f `pwd`/RedHat/alpha ]; then
    let arch=2
    echo "For an Alpha architecture."
  elif [ -f `pwd`/RedHat/sparc ]; then
    let arch=3
    echo "For a Sparc architecture."
  else 
    echo "Architecture is indeterminate; exiting now!"
    if [ -n "$isotest" ] && [ "$isotest"="--iso" ]; then
      umount /tmp/foo.$$
      rmdir /tmp/foo.$$
    fi
    exit 1
  fi

else
  let disc=2
  echo "Checking disc 2"
fi

#
# here we check disc 1
#
if [ $disc -eq 1 ]; then
#  isfile .build_log
  isfile COPYING
  isfile README
  isfile RPM-PGP-KEY
#  isfile TRANS.TBL
  isdir RedHat
  isdir doc
  isdir dosutils
  isdir images
  isdir misc
#  isdir rr_moved
  #
  # we only need to check for a live file system when the architecture is
  # intel
  #
  if [ $arch -eq 1 ]; then
    isdir live
  fi

  #
  # the following files and directories are peculiar to the alpha
  # and the sparc
  #
  if [ $arch -eq 2 ]; then
  # alpha
    isdir home
    isdir kernels
    isdir milo
    isdir mntswap
    #
    # Now check under the milo directory 
    #
    if [ -d milo ]; then
      cd milo
      isdir arc
      if [ -d arc ]; then
        cd arc
	isfile linload.exe
	cd ..
      fi
      isfile avanti
      isfile cabrio
      isfile eb164
      isfile eb64p
      isfile eb66
      isfile eb66p
      isdir images
      if [ -d images ]; then
        cd images
        isfile alcor.img
        isfile avanti.img
        isfile cab.img
        isfile eb164.img
        isfile eb64p.img
        isfile eb66.img
        isfile eb66p.img
        isfile lx164.img
        isfile miata.img
        isfile noname.img
        isfile pc164.img
        isfile sx164.img
        isfile xlt.img
        cd ..
      fi 
      isfile lx164
      isfile miata
      isfile pc164
      isfile sx164
      isfile udb-noname
      isfile xl
      isfile xlt-alcor
      cd ..
    fi
  fi
  if [ $arch -gt 1 ]; then
    isdir mnt
    isdir proc
    isdir tmp
    islink bin
    if [ $arch -eq 3 ]; then
      # sparc
      isdir etc
      isdir dev
      if [ -d dev ]; then
        cd dev
	ischar console
	ischar cua0
	ischar null
	isblock ram
	ischar tty1
	ischar tty2
	ischar tty3
	ischar tty4
	ischar tty5
	ischar zero
	cd ..
      fi
      isdir lib
      isdir sbin
      isdir usr
    else
      # alpha
      islink etc
      islink dev
      islink lib
      islink sbin
      islink usr
    fi

  fi

  let toterrs=$((toterrs+thisdirerrs))
  if [ $toterrs -gt 0 ]; then
    echo "$toterrs errors in root directory!"
  # exit 1
  fi

  let thisdirerrs=0
  #
  # now do the $rootdir/RedHat directory
  #
  cd $rootdir
  parent="RedHat"
  if [ -d $parent ]; then
    cd $parent
    isdir RPMS
    isdir base
    if [ -d base ]; then
      cd base
      #isfile TRANS.TBL
      isfile comps
      isfile hdlist
      if [ $arch -eq 1 ]; then
        #
        # the file RedHat/base/rpmconvert does not exist on alphas
        #
        isexe rpmconvert
        isfile skeleton.cgz
      elif [ $arch -eq 2 ]; then
	# alpha
	let arch=2
      elif [ $arch -eq 3 ]; then
	# sparc
	let arch=3
      fi

      cd ..
    fi

    if [ $arch -eq 1 ]; then
    #
    # the directory RedHat/base/instimage does not exist on alphas
    # and on sparcs
    #
      isdir instimage
      if [ -d instimage ]; then
        cd instimage
        if [ -d usr ]; then
          cd usr
          if [ -d bin ]; then
            cd bin
            for name in `pwd`/*; do
	      isexe $name
            done
            cd ..
          fi

          cd ..
        fi

        cd ..
      fi

    fi

    #isfile TRANS.TBL
  fi

  let toterrs=$((toterrs+thisdirerrs))
  let thisdirerrs=0
  #
  # now do the $rootdir/dosutils directory
  #
  cd $rootdir
  if [ -d dosutils ]; then
    cd dosutils
    isfile README
    #isfile TRANS.TBL
    if [ $arch -eq 1 ]; then
      # intel only
      isdir autoboot
      if [ -d autoboot ]; then
        cd autoboot
        #isfile TRANS.TBL
        isfile initrd.img
        isfile vmlinuz
        cd ..
      fi

      isfile autoboot.bat
      isfile lodlin16.tgz
    fi

    isfile copying
    isfile fips.exe
    isfile fips15.zip
    isdir fipsdocs
    if [ -d fipsdocs ]; then
      cd fipsdocs
      #isfile TRANS.TBL
      isfile errors.txt
      isfile fips.doc
      isfile fips.faq
      isfile history.txt
      isfile readme.1st
      isfile special.doc
      isfile techinfo.txt
      cd ..
    fi

    isfile gzip.exe
    isfile loadlin.exe
    isfile rawrite.exe
    isfile rawrite3.doc
    isfile rdev.exe
    isfile restorrb.exe
    cd ..
  fi

  let toterrs=$((toterrs+thisdirerrs))
  let thisdirerrs=0
  #
  # now do the $rootdir/live directory for intel only
  #
  cd $rootdir
  if [ -d live ] && [ $arch -eq 1 ]; then
    cd live  
    #isfile TRANS.TBL
    isdir bin
    isdir boot
    isdir dev
    isdir etc
    isdir home
    isdir lib
    #isdir lost+found
    isdir mnt
    isdir proc
    isdir root
    isdir sbin
    isdir tmp
    isdir usr
    isdir var
    cd ..
  fi

  let toterrs=$((toterrs+thisdirerrs))
  let thisdirerrs=0
  #
  # now do the $rootdir/doc directory
  #
  cd $rootdir
  if [ -d doc ]; then
    cd doc  
    isdir FAQ
    isdir HOWTO
    if [ $arch -eq 1 ]; then
      #isfile LIN-XESS41.ps
      #isfile LIN-XESS41.txt
      #isfile MetroX41manual.ps
      isfile README.ks
    fi

    #isfile TRANS.TBL
    isdir rhmanual
    cd ..
  fi

  let toterrs=$((toterrs+thisdirerrs))
  let thisdirerrs=0
  #
  # now do the $rootdir/images directory
  #
  cd $rootdir
  if [ -d images ]; then
    cd images  
    if [ $arch -eq 2 ]; then
      # alpha only
      isfile  alcor-s.img
      isfile  alcor.img
      isfile  avanti-s.img
      isfile  avanti.img
      isfile  cab.img
      isfile  eb164.img
      isfile  eb64+.img
      isfile  eb66+.img
      isfile  eb66.img
      isfile  jensen.img
      isfile  miata.img
      isfile  noname.img
      isfile  pc164.img
      isfile  ramdisk.img
      isfile  sx164.img
      isfile  xlt.img
    else
      # intel and sparc
      #isfile TRANS.TBL
      isfile boot.img
      if [ $arch -eq 1 ]; then
        # intel
        isfile rescue.img
        isfile supp.img
      elif [ $arch -eq 3 ]; then
        # sparc only
        isfile tftpboot.img
        isfile README
      fi
   fi

    cd ..
  fi

  let toterrs=$((toterrs+thisdirerrs))
  let thisdirerrs=0
  #
  # now  do the $rootdir/misc directory
  #
  cd $rootdir
  if [ -d misc ]; then
    cd misc
    #isfile TRANS.TBL
    if [ $arch -eq 1 ]; then
    #
    # boot is only for intel
    #
      isdir boot
    elif [ $arch -eq 2 ]; then
      #
      # bootlx is peculiar to alpha
      #
      isexe bootlx
    fi

    isdir src
    if [ $arch -eq 2 ] && [ -d `pwd`/src ]; then
    #
    #  if it's alpha and $rootdir/misc/src is a directory...
    #
      cd src
      isdir install
      if [ -d install ]; then
	cd install
	isexe dmphdlist
	isexe genhdlist
	isexe install
	isexe install2
	cd ..
      fi

      if [ $arch -eq 2 ]; then
	# alpha
        isdir installinit
        if [ -d installinit ]; then
	  cd installinit
	  isexe init
	  cd ..
        fi
      fi

      if [ $arch -eq 2 ]; then
        isdir trees
        if [ -d trees ]; then
	  cd trees
	  isexe mkboot2
	  isexe updboot
	  isexe updkmaps
	  isdir boot
	  isdir keymaps
	  isfile debug.log
	  isfile ramdisk.img.nogz
	  cd ..
        fi

      fi

    fi

    cd ..
  fi

  #
  # check the alpha's milo directory
  #
  if [ -d milo ] && [ $arch -eq 2 ]; then
    cd milo
      isdir arc
      isfile avanti
      isfile cabrio
      isfile eb164
      isfile eb64p
      isfile eb66
      isfile eb66p
      isdir images
      isfile lx164
      isfile miata
      isfile pc164
      isfile sx164
      isfile udb-noname
      isfile xl
      isfile xlt-alcor
    cd ..
  fi

  let toterrs=$((toterrs+thisdirerrs))
  let thisdirerrs=0
  #
  # now check the $rootdir/RedHat/RPMS directory contents for 
  # correct PGP signatures on all rpms
  #
  cd $rootdir/RedHat/RPMS
  if [ $nopgp -eq 0 ]; then
    unsigned "$rootdir/RedHat/RPMS/*.rpm"
  else  
    echo "No PGP checking of RPMs."
  fi
  let thisdirerrs=$?
  let toterrs=$((toterrs+thisdirerrs))
  #
else
  #
  # now do disc 2 if it wasn't (obviously) a disc 1
  #
  #
  #  This script verifies that the structure of the second cdrom of 
  #  a RedHat distribution has the proper characteristics.
  #  There is a single argument: $rootdir which is the root of the
  #  filesystem to check (e.g. the place where you mounted the CD)
  #
  let thisdirerrs=0
  let toterrs=0
  cd $rootdir
  #isfile .build_log
  isfile COPYING
  isfile README
  #isfile TRANS.TBL
  isdir SRPMS
  #
  # Check to see that all SRPMs are PGP signed, unless we don't want to.
  #
  if [ $nopgp -eq 0 ]; then
    unsigned "$rootdir/SRPMS/*.rpm"
  else  
    echo "No PGP checking of SRPMs."
  fi
  let toterrs=$((toterrs+thisdirerrs))
  if [ $toterrs -gt 0 ]; then
    echo "$toterrs errors in root directory disc $disc"
#  exit 1
  else
  echo "No problems found with CD 2."
  fi

fi

#
# Report how many errors were encountered during the run
#
#
# find inserted for stale NFS handles, brings version 1.2
#
echo "Listing stale NFS Handles"
find $rootdir -name ".#*"
echo " "

echo "Errors are listed above while analyzing $rootdir on disc $disc."
popd
if [ -n "$isotest" ] && [ "$isotest" = "--iso" ]; then
  umount /tmp/foo.$$
  rmdir /tmp/foo.$$
fi
