#!/bin/bash

# copyright 2004 vagrant@freegeek.org, distributed under the terms of the
# GNU General Public License version 2 or any later version.

#TODO move a compaq partition if not the first physical
# partition, rather than exit
#TODO explore using parted instead of sfdisk

echo "setting fstab to $1"
fstab="$1"

tmpfile=`tempfile`

alldisks=`egrep "^/dev/hd" $fstab | awk '{print $1}' | \
  sed s/[1-9]//g | sort -u`
echo "making sfdisk-able entries for $alldisks"

for disk in $alldisks ; do
  zerotable=`sfdisk -d $disk | egrep "No partitions found"`
  if [ "" != "$zerotable" ]; then
    echo "partition table invalid, attempting to create an empty table"
    parted $disk mklabel msdos
    #create a partition, sfdisk doesn't work with the parted's empty table.
    parted $disk mkpart ext2 1 2
  fi

CpqCheck() {
  # checks for compaq partition, and sets some values appropriately...
  cpqtype="12"
  cpqcheck=`sfdisk -d $disk | egrep "Id=$cpqtype"`
  if [ "" != "$cpqcheck" ]; then
    echo "found a compaq partition"
    maxpartitions="3"
    cpqpart=`echo $cpqcheck | awk '{print $1}'`
    cpqstart=`echo $cpqcheck | awk '{print $4}' | sed s/,//g`
    cpqsize=`echo $cpqcheck | awk '{print $6}' | sed s/,//g`
    #echo "$compaqcheck" > $tmpfile
    echo cpqstart $cpqstart cpqsize $cpqsize
    if [ 63 -lt "$cpqstart" ]; then
      echo "compaq partition is does not start at beginning of"
      echo "disk... we just can't handle this yet. exiting..."
      exit 1
    fi
  else
    cpqpart=""
    cpqstart=0
    cpqsize=0
  fi
}

  shortdisk=`echo "$disk" | cut -d "/" -f 3`
  rm $tmpfile
  diskpartitions=`egrep "^$disk" $fstab | \
    egrep -v "iso9660|cdrom|#size=remaining|swap" | \
    awk '{print $1}' | sort`
  #don't want swap on hda1, so we put it later- maybe this is dumb
  diskpartitions=`echo "$diskpartitions" ; egrep "^$disk" $fstab | \
    egrep "swap" | awk '{print $1}'`
  #remaining needs to be the last partition...
  diskpartitions=`echo "$diskpartitions" ; egrep "^$disk" $fstab | \
    egrep "#size=remaining" | awk '{print $1}'`

  # currently, this script only handles primary partitions, thus, we are
  # limited to 4 partitions
  maxpartitions="4"
  fstabpartitions="$(echo $diskpartitions | egrep $disk | wc -w)"

  CpqCheck

  if [ "$maxpartitions" -lt "$fstabpartitions" ]; then
    echo "this script can only handle $maxpartitions partitions or less."
    echo "$fstabpartitions partitions were defined in $fstab"
    if [ "" != "$cpqcheck" ]; then
      echo "a compaq partition was found which reduces the number of"
      echo "available partitions."
    fi
    echo "you'll have to partition this manually."
    echo "exiting..."
    exit 1    
  fi


  echo "creating entries for $diskpartitions"

  cylindersize=`sfdisk -l $disk | egrep ^Units | awk '{print $5}'`
  sectorsize=`sfdisk -l -uS $disk | egrep ^Units | awk '{print $5}'`

  sectorsincyl="$(($cylindersize/$sectorsize))"
  if [ -z "$cpqcheck" ]; then
    start="$sectorsincyl"
    firstrun="yes"
  else
    start="$(($cpqstart+$cpqsize))"
    firstrun="no"
  fi
  totalsectors=`dmesg | egrep "^$shortdisk" | egrep sectors | \
    sort -u | awk '{print $2}'`
  if [ "" = "$totalsectors" ]; then
    totalsectors=`egrep "^$shortdisk" /var/log/dmesg | egrep sectors | \
  sort -u | awk '{print $2}'`
  fi
  diskleft="$(($totalsectors-$start))"

  for partition in $diskpartitions ; do
    echo "setting up $partition"
    mbsize=`egrep $partition $fstab | awk -F "#size=" '{print $2}'`
    isswap=`egrep "^$partition" $fstab | egrep "swap"`
    if [ "" = "$isswap" ]; then
      #set partition type to linux
      type="83"
    else
      # set partition type to swap
      type="82"
    fi

    if [ "$partition" = "$cpqpart" ]; then
    #then
      cpqstart="$cpqstart"
      cpqsize="$cpqsize"
      cpqtype="12"
      start=$(($cpqstart+$cpqsize))
      diskleft=$(($diskleft-$cpqsize-$cpqstart))
    fi

    # turn megabytes into bytes, then to sectors...
    # if $mbsize is a non-number, such as "remaining", the
    # result will be zero
    size="$(($mbsize*1024*1024/512))"

    # todo- figure out a better way to determine size...
    if [ "0" = "$size" ]; then
      size="$(($diskleft))"
    fi
    # this presumably rounds it out to cylinder boundaries
    size="$(($size/$sectorsincyl))"
    size="$(($size*$sectorsincyl))"

    if [ "$partition" = "$cpqpart" ]; then
       diskleft="$(($diskleft))"
    else
       diskleft="$(($diskleft-$size))"
    fi
    echo "remaining $diskleft"

    if [ "yes" = "$firstrun" ]; then
      echo "$partition : start= 63, size= "$(($size-63+$sectorsincyl))", Id=$type, bootable" \
        >> $tmpfile
      firstrun="no"
    else
      echo "$partition : start= $start, size= $size, Id=$type" \
        >> $tmpfile
    fi

    #set the beginning of the next partition
    start="$(($start+$size))"
    outfile="/tmp/$shortdisk"
  done
  echo "# partition table of $disk" > $outfile
  echo "unit: sectors" >> $outfile
  # sort partitions so order appears identical to fstab, we hope..
  cat $tmpfile | sort >> $outfile
  if [ "" != "$cpqpart" ]; then
    echo "$cpqpart : start= $cpqstart, size= $cpqsize, Id=$cpqtype, bootable" \
      >> $outfile
    cpqpart=""
  fi
  echo "to install this partition table, run"
  echo "sfdisk $disk < $outfile"
done
