#!/bin/bash
#
# A wrapper script to install a Linux-distribution from a source-directory
# to a Bochs disk-image.
# 
# $Author: bablokb $
# $Revision: 1.8 $
#
# License: GPL2
# -----------------------------------------------------------------------------

. `dirname $0`/bxtfuncs.inc

# usage message   -------------------------------------------------------------

usage() {
  echo -e "\n`basename $0`: clone a Linux-distribution to a bochs-hd-image\n\
  \nusage: `basename $0` [options] source-dir image-name\n\
  possible options:\n\
    -e x     add extra size x to hda1\n\
    -t type  partition-type of hda1 (defaults to auto)\n\
    -w y     set swap partition to y MB (default: 32 MB)\n\
    -o       overwrite existing file\n\
    -H heads number of heads (default: 16)\n\
    -S spt   number of sectors-per track (default: 63)\n\
    -V       show version\n\
    -h       show this help\n\
    -q       run quiet (default)\n\
    -v       verbose messages\n\
    -s       only simulate\n\
"
  exit 3
}

# set system defaults   -------------------------------------------------------

setDefaults() {
  quiet=1; simulate=0; debug=0
  overwrite=0
  bxtcreateArgs=""
  sizeAdd=-1
  SIZE_INC_REL=10                    # 10%
  SIZE_INC_ABS="20480"               # 20*1024k
  swapSize="32m"
  fsType="auto"
}

# parse arguments and set variables -------------------------------------------

parseArguments() {
  while getopts "e:w:t:H:S:oVhqvsd" opt; do
    case $opt in
      e) sizeAdd="$OPTARG";;
      w) swapSize=$OPTARG;;
      t) fsType=$OPTARG;;
      H) bxtcreateArgs="$bxtcreateArgs -H $OPTARG";;
      S) bxtcreateArgs="$bxtcreateArgs -S $OPTARG";;
      o) overwrite=1; bxtcreateArgs="$bxtcreateArgs -o";;
      V) showCopyright \
         `basename $0` "clone a Linux-distribution to a bochs-hd-image";;
      h) usage;;
      q) quiet=1;;
      v) quiet=0;;
      s) simulate=1;;
      d) debug=1;;
      ?) echo "illegal option: $OPTARG" >&2
           usage;;
    esac
  done
  shift $(( OPTIND-1 ))
  sourceDir=$1
  imageName=$2
}

# check arguments   -----------------------------------------------------------

checkArguments() {
  if [ -z "$sourceDir" ]; then
    echo "error: missing argument source-dir!" >&2
    usage
  fi
  if [ ! -d $sourceDir ]; then
    echo "error: source-dir $sourceDir does not exist!" >&2
    exit 1
  fi
  if [ -z "$imageName" ]; then
    echo "error: missing argument image-name!" >&2
    usage
  fi
  if [ -f $imageName -a $overwrite -eq 0 ]; then
    echo "error: image $imageName exists. Use option -o to overwrite existing image" >&2
    exit 3
  fi
}

# calculate necessary size of hda1   ------------------------------------------

calcSize() {
  let size=`du -sck $sourceDir |tail -n 1 | cut -f1`
  if [ "$sizeAdd" = "-1" ]; then  # default is max of 10% and 20 MB
    let sizeAdd=size/SIZE_INC_REL
    [ "$sizeAdd" -lt $SIZE_INC_ABS ] && let sizeAdd=$SIZE_INC_ABS
  elif echo "$sizeAdd" | grep -q "%"; then
    let sizeAdd=size/${sizeAdd%\%}
  else
    sizeAdd=`getSize $sizeAdd`
  fi
  [ $debug -eq 1 ] && echo "sizeAdd=$sizeAdd" >&2
  let size+=sizeAdd
  [ $debug -eq 1 ] && echo "size=$size" >&2
}

# find filesystem type of source-dir   ----------------------------------------

findType() {
  if [ "$fsType" = "auto" ]; then
    fsType=`df -PT $sourceDir | tail -n 1 | awk '{ print $2; }'`
  fi
  if [ "$fsType" = "vfat" ]; then
    fsDevice=`df -PT $sourceDir | tail -n 1 | awk '{ print $1; }'`
    if [ -f $fsDevice ]; then
      fsDevice=`mount | grep $fsDevice | sed -e 's/.*loop=\([^,]*\),.*/\1/'`
    fi
    fsSize=`file -s $fsDevice`
    fsSize=${fsSize#*\(}
    fsSize=${fsSize%% *}
    fsType="fat$fsSize"
  fi
  [ $debug -eq 1 ] && echo "fsType=$fsType" >&2

  if test "`getSize $swapSize`" -eq 0 || echo "$fsType" | grep -q "fat"; then
    withSwap=0
  else
    withSwap=1
    bxtcreateArgs="$bxtcreateArgs -2 $swapSize"
  fi
  [ $debug -eq 1 ] && echo "withSwap=$withSwap" >&2
}

# write /etc/fstab on new system   --------------------------------------------

writeFstab() {
  [ ! -f $sourceDir/etc/fstab ] && return
  if ! createMountPoint mountPoint; then
    echo "error: could not create mount-point for $imageName:1" >&2
    exit 3
  fi
  if ! doMount $imageName:1 $mountPoint; then
    echo "error: could not mount $imageName:1" >&2
    do_cmd "rm -fr $mountPoint"
    exit 3
  fi
  do_cmd "mv -f $mountPoint/etc/fstab $mountPoint/etc/fstab.bxtclone"
  cat > $mountPoint/etc/fstab <<EOF
# /etc/fstab: static file system information.
# 
# Created by bxtclone. Original /etc/fstab saved to /etc/fstab.bxtclone
#
# <file system> <mount point>   <type>  <options>               <dump>  <pass>
/dev/hda1       /               $fsType errors=remount-ro       0       1
proc            /proc           proc    defaults                0       0
/dev/fd0        /floppy         auto    user,noauto             0       0
/dev/cdrom      /cdrom          iso9660 ro,user,noauto          0       0
EOF
  [ $withSwap -eq 1 ] && cat >> $mountPoint/etc/fstab <<EOF
/dev/hda2       none            swap    sw                      0       0
EOF

  [ $debug -eq 1 ] && do_cmd "cat $mountPoint/etc/fstab"
  doUmount $mountPoint
}

# main program   --------------------------------------------------------------

setDefaults
parseArguments "$@"
checkArguments
calcSize
findType

if ! do_cmd "bxtcreate -q -1 ${size}k $bxtcreateArgs $imageName"; then
  echo "error: could not create $imageName" >&2
  exit 3
fi
if ! do_cmd "bxtmkfs -q -t $fsType $imageName:1"; then
  echo "error: could not create filesystem on $imageName:1" >&2
  exit 3
fi
[ $withSwap -eq 1 ] && if ! do_cmd "bxtmkfs -q -t swap $imageName:2"; then
  echo "error: could not create swap-partition on $imageName:2" >&2
  exit 3
fi
if ! do_cmd "bxtcopy -q $sourceDir $imageName:1"; then
  echo "error: could not copy source-directory" >&2
  exit 3
fi

writeFstab

if ! do_cmd "bxtlilo -q $imageName"; then
  echo "error: could not install lilo on $imageName" >&2
  exit 3
fi

exit 0