#!/bin/bash
#
# Format a partition of a bochs disk-image.
# 
# $Author: bablokb $
# $Revision: 1.19 $
#
# License: GPL2
# -----------------------------------------------------------------------------

. `dirname $0`/bxtfuncs.inc
pgmDir=`dirname $0`

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

usage() {
  echo -e "\n`basename $0`: format a partition of a bochs-hd-image\n\
  \nusage: `basename $0` [options] image-name:partition\n\
  possible options:\n\
    -V       show version\n\
    -h       show this help\n\
    -q       run quiet (default)\n\
    -v       verbose messages\n\
    -s       only simulate\n\
    -t type  format partition with given type\n\
             supported types: swap, minix, ext2, ext3, ext4, reiserfs, fat, fat12, fat16, fat32\n\
    -x opts  pass extra options to mkfs (opts must be quoted)\n\
"
  exit 3
}

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

setDefaults() {
  quiet=1; simulate=0; overwrite=0
  type=ext2
  extraOptions=""
  partition=""
}

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

parseArguments() {

  while getopts ":t:x:Vhqvs" opt; do
    case $opt in
      t) type=$OPTARG;;
      x) extraOptions=$OPTARG;;
      V) showCopyright `basename $0` "format a partition of a bochs-hd-image";;
      h) usage;;
      q) quiet=1;;
      v) quiet=0;;
      s) simulate=1;;
      ?) echo "error: illegal option: $OPTARG" >&2
           usage;;
    esac
  done
  if [ $# -eq $OPTIND ]; then
    imageName=${!OPTIND%:*}
    partition=${!OPTIND#*:}
  elif [ $# -gt $OPTIND ]; then
    echo "error: illegal argument ${!#}" >&2
    usage
  else
    echo "error: missing argument image-name:partition" >&2
    usage
  fi
}

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

checkArguments() {
  if [ ! -f $imageName ]; then
    echo "error: image $imageName does not exist!" >&2
    exit 1
  fi
  if [ -z $partition ]; then
    echo "error: no partition number specified!" >&2
    exit 1
  fi
}

# set filesystem-type in partiton-table   -------------------------------------

setType() {
  local id=$1
  [ $type = "fat12"     -a $id =  "1" ] && return
  [ $type = "fat16"     -a $id =  "6" ] && return
  [ $type = "fat"       -a $id =  "6" ] && return
  [ $type = "fat32"     -a $id =  "c" ] && return
  [ $type = "swap"      -a $id = "82" ] && return
  [ $type = "ext2"      -a $id = "83" ] && return
  [ $type = "ext3"      -a $id = "83" ] && return
  [ $type = "ext4"      -a $id = "83" ] && return
  [ $type = "minix"     -a $id = "83" ] && return
  [ $type = "reiserfs"  -a $id = "83" ] && return

  cmd="sfdisk -q -L -N$partition -C $cyl -H $heads -S $spt $imageName"
  case $type in
    fat12)  cmd="echo  \",,1\" | $cmd 1>/dev/null 2>/dev/null";;
      fat)  cmd="echo  \",,6\" | $cmd 1>/dev/null 2>/dev/null";;
    fat16)  cmd="echo  \",,6\" | $cmd 1>/dev/null 2>/dev/null";;
    fat32)  cmd="echo  \",,c\" | $cmd 1>/dev/null 2>/dev/null";;
     swap)  cmd="echo \",,82\" | $cmd 1>/dev/null 2>/dev/null";;
        *)  cmd="echo \",,83\" | $cmd 1>/dev/null 2>/dev/null";;
  esac
  if ! do_cmd "$cmd"; then
    echo "error: could not set partition-id for $imageName:$partition" >&2
    exit 1
  fi
}

# format partition   ----------------------------------------------------------

formatPartition() {
  local offset=$1 size=$2 id=$3

  if [ -z $offset ]; then
    echo "error: partition $partition does not exist!" >&2
    exit 1
  elif [ $offset -eq 0 ]; then
    echo "error: partition $partition does not exist!" >&2
    exit 1
  fi

  setType $id  
  [ $type = "reiserfs" ] && let size=size/4

  if ! loopDevice=`getLoopDevice`; then
    echo "error: no free loop-device" >&2
    exit 1
  fi
  if ! do_cmd "losetup -o $offset $loopDevice $imageName"; then
    echo "error: could not setup $imageName on $loopDevice" >&2
    exit 1
  fi

  case $type in
        ext2) cmd="mkfs.ext2";;
        ext3) cmd="mkfs.ext3";;
        ext4) cmd="mkfs.ext4";;
        swap) cmd="mkswap";;
       minix) cmd="mkfs.minix";;
    reiserfs) cmd="mkreiserfs";;
         fat) cmd="mkdosfs";;
       fat12) cmd="mkdosfs -F12";;
       fat16) cmd="mkdosfs -F16";;
       fat32) cmd="mkdosfs -F32";;
           *) echo "error: unsupported fs-type: $type!" >&2
              do_cmd "losetup -d $loopDevice"
              exit 1;;
  esac 
  createTempFile "errMsgs" 
  cmd="$cmd $extraOptions $loopDevice $size"
  if ! do_cmd "$cmd" 2>$errMsgs; then
    if test "$type" != "swap" || grep -qv fsync $errMsgs; then
      echo "error: failed to create partition on $imageName:$partition" >&2
      do_cmd "losetup -d $loopDevice"
      rm -fr $errMsgs
      exit 1
    else
      echo "warning: fsync failed (usually, you can ignore this error)" >&2
      rm -fr $errMsgs
    fi
  fi
  do_cmd "losetup -d $loopDevice"
}

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

setDefaults
parseArguments "$@"
checkSfdisk
checkArguments
setGeometry $imageName
formatPartition `"$pgmDir"/bxtptinfo -p $partition $imageName`
exit 0
