#!/bin/sh
#
# Modified from SGI Developer Toolbox utility
#   by Pete Turnbull, 6-May-1998.
#
#   Thanks to Chris and James for helping to
#   figure out exactly what it does, and why.
#
# Requires:  $TOOLDIR/{dvhfile,ffsck,makeproto}
#
# THIS IS UNSUPPORTED SOFTWARE.  SGI CANNOT PROVIDE ANY SUPPORT ON THIS.

SRC=`pwd`
DEST=/disk6/cdimages
TEMP=/usr/tmp
LOGFILE=/usr/tmp/mkefs.log
TOOLDIR=/usr/local/bin/CDR
VERBOSE=0
SLINKS=

usage()
{
	echo "usage: mkefs [-v] [-l] [-f source] [-o dest]"
        echo " "
        echo "Example: "
        echo " "
        echo "  mkefs -f $SRC -o $DEST"
        echo " "
        echo "  will write everything under $SRC"
        echo "  to a .vh and a .efs files under $DEST"
        echo " "
        echo "  -v gives more verbose information"
        echo "  -l preserves symbolic links (default: follow links)"
        echo " "
}

vecho()
{
	if [ "$VERBOSE" = "1" ]
	then
	    echo $*
	fi
}

########## Start Here :  If anything goes wrong, exit immediately ##########
set -e

# be sure we can find all the tools we need
PATH=/bin:/usr/bin:/usr/bsd:/etc:/sbin:/usr/etc:/usr/sbin:/usr/local/bin:$TOOLDIR


# say hello to the nice user
echo -n "mkefs EFS image creation utility starting, "
date
echo

#read options, and remember if we got any
while getopts f:o:hlv c
do
	case $c in
	f)	SRC=$OPTARG
                GotSRC=1
                ;;
	o)	DEST=$OPTARG
                GotDEST=1
                ;;
	h)	usage
		exit 0
		;;
	l)	SLINKS=L
		;;
	v)	VERBOSE=1
		;;
	\?)	usage
                exit 1
		;;
	esac
done

# check source and destination names are defined
if [ -z "$SRC" -o -z "$DEST" ]
then
	usage
        exit 1
fi

DIR=`pwd`

# if source dir pathname is relative, make it absolute
# ie if SRC = "subdir" and current DIR is "/usr/people/burner"
# then SRC := "/usr/people/burner/subdir"
SRC=`echo $SRC $DIR | nawk '
{
	if (1 == index( $1, "/" ))
		print $1
	else
		print $2 "/" $1
}'`

# if dest dir pathname is relative, make it absolute
DEST=`echo $DEST $DIR | nawk '
{
	if (1 == index( $1, "/" ))
		print $1
	else
		print $2 "/" $1
}'`

# check SRC and DEST are directories, and DEST is writable
ANS=n
while [ "$ANS" != "y" ]
do
  if [ -d $SRC ]
  then
    echo "Source directory: $SRC"
  else
    echo "*** Error:  source directory $SRC unreachable."
    usage
    exit 1
  fi
  if [ -d $DEST ]
  then
    echo "Destination: $DEST"
  else
    echo "Creating destination: $DEST"
    if mkdir -p $DEST > /dev/null 2>&1
    then
      :
    else
      echo "*** Error:  cannot create $DEST"
      usage
      exit 1
    fi
  fi
  # ensure dest is writable
  if touch $DEST/testfile.$$.$$ 
  then
    rm -f $DEST/testfile.$$.$$
  else
    echo "*** Error:  cannot write to destination directory $DEST"
    usage
    exit 1
  fi
  
  # if using default SRC/DEST, confirm/change
  if [ "$GotSRC" = "1" -a "$GotDEST" = "1" ]
  then
    ANS=y
  else
    # ask for confirmation
    echo " "
    echo "Is the information above correct? (y n) [y] \c"
    read ANS
    case $ANS in
      y*|"") ANS=y ;;
          *) echo " "
             usage
             echo "Source directory: [$SRC] \c"
             read ans
             if [ "$ans" != "" ]
             then
               SRC=$ans
             fi
             echo "Destination directory: [$DEST] \c"
             read ans
             if [ "$ans" != "" ]
             then
               DEST=$ans
             fi
             echo " "
             ;;
    esac
  fi
done

# see if source directory includes a boot image
if [ -f $SRC/sa -o -f $SRC/dist/sa ]
then
  echo "sa detected.  More complex volume header will be built."
  BOOT=1
  if [ -f $SRC/dist/sa ]
  then
    DISTDIR=$SRC/dist
  else
    DISTDIR=$SRC
  fi
else
  BOOT=0
fi

TMPDIR=$TEMP/_VH_$$
IMAGEDIR=$DEST/_image_$$

PRODUCT=`basename $SRC `

#
# Set up a directory that is the image we want on the CD ROM.
#

vecho `date`
echo Creating image of $SRC

cd $DEST

#
# Get rid of old stuff so that disk space calculations will succeed
#
vecho "Removing old .vh/.efs files from $DEST"
rm -f $PRODUCT.efs $PRODUCT.vh

vecho "Calculating sizes..."

CYLSIZE=32 # Phillips DuPont defaults to 32 spt disks
# keep cylgroups down so we don't get too many inodes
CFG=`expr $CYLSIZE \* 250`
# slop should be a multiple of the cyl size, in order to keep the
# partition sizes a multiple of the cylsize, for fx and dvhtool
#
# Give us a whole bunch of room for huge CD's
#

SLOP=`expr 10 \* $CFG`

space=`du -s$SLINKS $SRC | sed 's/[ 	].*//'`
vecho `date`
space=`expr \( \( $space + $CYLSIZE - 1 \) / $CYLSIZE \) \* $CYLSIZE`
vecho "Source occupies $space blocks"

if [ "$BOOT" = "1" ]
then
        vhspace=`ls -sL $DISTDIR/sa | sed 's/[  ].*//'`
        # room for extra junk (io4prom)
        vhspace=`expr $vhspace + 5000`
        # round up, + cylsize for unused first cyl
        vhspace=`expr \( \( $vhspace + $CYLSIZE - 1 \) / $CYLSIZE \) \* $CYLSIZE + $CYLSIZE`
else
        # Minimum volume header size is 2 cylinders
        vhspace=`expr $CYLSIZE \* 2`
fi
vecho "Volume header requires $vhspace blocks"

# add slop for inodes, bitmaps, etc
pspace=`expr $space + $SLOP + 1000`

#
# $PRODUCT.efs + $PRODUCT.vh
#
needed=`expr $pspace + $vhspace`

dfree=`df -b . | sed -e 1d -e 's/[^ 	]*[ 	]*[^ 	]*[ 	]*[^ 	]*[ 	]*[^ 	]*[ 	]*//' -e 's/[ 	].*$//'`
if [ "$dfree" -lt "$needed" ]
then
  echo "*** Error: need $needed blocks, only $dfree available in this directory"
  echo "    pspace is $pspace, vhspace is $vhspace"
  exit 3
else
  vecho "Total space required is $needed blocks"
fi

if [ "$BOOT" = "1" ]
then
  vecho "Making boot image in $TMPDIR..."
  mkdir -p $TMPDIR
  cd $TMPDIR
  vecho "  extracting files from sa"
  mkboottape -f $DISTDIR/sa -x
  if [ -f $DISTDIR/mr ]
  then
    vecho "  found miniroot"
  else
    if touch $DISTDIR/mr >/dev/null 2>&1
    then
      vecho "  created dummy miniroot"
    fi
  fi

  vecho "  making stand directory"
  mkdir -p $IMAGEDIR/stand
  vecho "  copying sash files"
  cp sash* $IMAGEDIR/stand
  # shorten any filenames > than 8 chars
  if ls sash.IP?? >/dev/null 2>&1
  then
    for i in sash.IP??
    do
      newname=`echo $i |sed "s/\.//"`
      vecho "    renaming $i to $newname"
      mv $i $newname
    done
  fi

  # copy all the ide's since we have plenty of room on /stand
  if ls ide* >/dev/null 2>&1
  then
    vecho "  copying ide files to $IMAGEDIR/stand"
    cp ide* $IMAGEDIR/stand >/dev/null 2>&1
  else
    echo "  Warning... no ide's in the sa (OK)"
  fi

  if ls fx* >/dev/null 2>&1
  then
    vecho "  moving fx files to $IMAGEDIR/stand"
    mv -f fx* $IMAGEDIR/stand >/dev/null 2>&1
  else
    echo "  Warning... no fx in the sa (OK)"
  fi
  rm -f ide*
  vecho "Creating bootable volume header file"
  dvhfile -f $DEST/$PRODUCT.vh -n "$RELEASE $ALPHA CDROM Installation disk" -h 1 -s $CYLSIZE -p 8,0,$vhspace,volhdr -p7,$vhspace,$pspace,efs $TMPDIR/*
  cd $DEST
  vecho "Removing $TMPDIR"
  rm -rf $TMPDIR
else
  vecho "Creating volume header file"
  dvhfile -f $PRODUCT.vh -n "$RELEASE $ALPHA CDROM Installation disk" -h 1 -s $CYLSIZE -p 8,0,$vhspace,volhdr -p 7,$vhspace,$pspace,efs
fi

vecho -n "Making prototype file "
if [ ${SLINKS:-F} = "F" ]
then
  timex makeproto $SRC > PROTO.$$
else
  timex makeproto -l $SRC > PROTO.$$
fi

inodes=`wc -l PROTO.$$ | nawk '{ print $1 }'`
# This number seems to get rounded DOWN by mkfs, so we'll boost it.
inodes=`expr $inodes + 6000`

echo Creating EFS filesystem as $PRODUCT.efs
cd $SRC
touch $DEST/$PRODUCT.efs
chmod +w $DEST/$PRODUCT.efs
vecho "  making filing system"

mkfs $DEST/$PRODUCT.efs $pspace $inodes 1 $CYLSIZE $CFG $CYLSIZE $CYLSIZE $DEST/PROTO.$$

# Note that mkfs may make a file smaller than the partitition.  Since we
# need to generate an image as large as the whole volume we may need to
# tack on some null blocks at the end, or a readcapacity on the drive
# will return too small a value, and due to the hack in the dksc driver,
# we will downsize the efs partition, and as a result we won't be able
# to mount it...
# We therefore add blocks if necessary
cd $DEST
efssize=`ls -sL $PRODUCT.efs | sed 's/[ 	].*//'`
if [ $efssize -lt $pspace ] ; then
	extra=`expr $pspace - $efssize`
	vecho adding $extra sectors at end of $PRODUCT.efs to bring up to partition size.
	dd if=/dev/zero bs=1b count=$extra >> $PRODUCT.efs
fi

vecho -n "  using ffsck to check $PRODUCT.efs  "
vecho `date`
# do this ls to re-establish the mount
ls $DEST/$PRODUCT.efs >/dev/null 2>&1
# mask out unimportant warning message
ffsck -y $DEST/$PRODUCT.efs 

vecho "  using dvhfile to check $PRODUCT.vh"
# do this ls to re-establish the mount
ls $DEST/$PRODUCT.vh >/dev/null 2>&1
dvhfile -f $DEST/$PRODUCT.vh -l

date
vecho -n "  using WordCount to get sums of each individual file  "
vecho `date`
a=`ls -l $DEST/$PRODUCT.efs |awk '{print $5 }'`
b=` ls -l $DEST/$PRODUCT.vh |awk '{print $5 }'`
c=`expr $a + $b`

echo  "Saving byte count of $PRODUCT ($c bytes)"
echo  "byte count of $PRODUCT $c bytes " > $DEST/$PRODUCT.bytecount 
if [ -d /usr/dist/tools/bytecounts ]
then
  echo  "byte count of $PRODUCT is $c bytes " > /usr/dist/tools/bytecounts/$PRODUCT.bytecount
else
  echo  "byte count of $PRODUCT is $c bytes " > /usr/tmp/$PRODUCT.bytecount
fi

date=`date '+%y/%m/%d %H:%M'`
echo "$date     $PRODUCT        $c      `hostname`" >> $LOGFILE

echo
echo "To burn the CD, concatenate the files"
echo " "
echo "  $DEST/$PRODUCT.vh and $DEST/$PRODUCT.efs"
echo " "
echo "and write them using WriteCDR(1), cdwrite(1), or cdrecord(1)."
date

exit 0
