#! /bin/bash
#
# (C) 1997 under GPL, Hans Lermen <lermen@fgan.de>
#
# Extract the system files and the bootsector out of a bootable
# DOS partition and store them into a directory
# NOTE: You need mtools >= 3.6 for this to work.
#

function usage {
  echo "USAGE:"
  echo '  extract-dos device [targetdir [-t] [-i IOname] [-m MSname]]'
  echo ""
  echo "where is:"
  echo "  device    = DOS-partition such as '/dev/hda1'"
  echo "              or a DOSEMU hdimage"
  echo "  targetdir = will be created, get the system files"
  echo "  -i nnn    = name of 'io.sys' if different"
  echo "  -m nnn    = name of 'msdos.sys' if different"
  echo "  -t        = autocheck for 'io.sys' and 'msdos.sys'"
  echo "or:"
  echo '  extract-dos device'
  echo 'in this case only the type of DOS is checked'
  exit 1
}

if [ "$(( `mtools -V|awk '{print $3}'|tr ',a-z' ' '|tr '.' '0'` < 306 ))" \
      = "1" ]; then
  echo "wrong mtools version installed, please upgrade to >= 3.6"
  exit 1
fi

mkdir -p ~/.dosemu/tmp

function is_hdimage {
  xxMAGIC=`dd if=$1 bs=5 count=1 2>/dev/null`
  xxDEX=`echo -e "\016DEXE"`
  if [ "$xxMAGIC" = "DOSEM" -o "$xxMAGIC" = "$xxDEX" ]; then
    return 0
  fi
  return 1
}

function do_mtool {
# $1  = device or hdimage
# $2  = mtools command
# $.. = rest of command line
# use 'W:' to access the dos drive
  device=$1
  mcommand=$2
  shift; shift
  params="$*"
  tmprc=~/.dosemu/tmp/mtoolrc.$$
  partition=""
  offset=""
  if is_hdimage $device; then
    partition="partition=1"
    offset="offset=128"
  fi
cat > $tmprc <<EOF
drive w: file="$device" MTOOLS_SKIP_CHECK=1 MTOOLS_LOWER_CASE=1 mtools_no_vfat=1 $partition $offset
EOF
  MTOOLSRC="$tmprc"
  export MTOOLSRC
  $mcommand $params
  rm -f $tmprc
}


function exist_file {
# $1 = device
# $2 = file on device

  if [ $2 = "N/A" ]; then return 0; fi

  if do_mtool $1 mdir -faw w:${2} | grep 'not found' >/dev/null; then
    return 1
  else
    return 0
  fi
}


function get_bootsect {
# $1  =  device or hdimage
# $2  =  target file name
  if is_hdimage $1; then
    dd if=$1 of=$2 bs=128 count=4 skip=69
  else
    dd if=$1 of=$2 bs=512 count=1
  fi
}

function check_bootsect {
# $1  =  device or hdimage
  tmp=~/.dosemu/tmp/bootsect.$$
  if is_hdimage $1; then
    dd if=$1 of=$tmp bs=128 count=4 skip=69 >/dev/null 2>&1
  else
    dd if=$1 of=$tmp bs=512 count=1 >/dev/null 2>&1
  fi
  if strings ${tmp} |grep 'IBMBIO  COM' >/dev/null 2>&1; then
    IOSYS="ibmbio.com"
    MSDOS="ibmdos.com"
    TYPE="IBMorOpenDos"
    if strings ${tmp} |grep 'NWDOS' >/dev/null 2>&1; then
      TYPE="NOVELL"
    fi
  else
    if strings ${tmp} |grep 'MSDOS   SYS' >/dev/null 2>&1; then
      IOSYS="io.sys"
      MSDOS="msdos.sys"
      if strings ${tmp} |grep 'WINBOOT SYS' >/dev/null 2>&1; then
        TYPE="WIN95"
      else
        TYPE="MSDOS"
      fi
    else
      if strings ${tmp} |grep 'IPL     SYS' >/dev/null 2>&1; then
        IOSYS="ipl.sys"
        MSDOS="kernel.exe"
        TYPE="FreeDos"
      else
        if strings ${tmp} |grep 'KERNEL  SYS' >/dev/null 2>&1; then
          IOSYS="kernel.sys"
          MSDOS="N/A"
          TYPE="FreeDosNoIPL"
        fi
      fi
    fi
  fi
  if ! exist_file $1 $IOSYS; then IOSYS="UNKNOWN"; TYPE="UNKNOWN"; fi
  if ! exist_file $1 $MSDOS; then 
    MSDOS="UNKNOWN";
    if [ "$TYPE" != "WIN95" ]; then TYPE="UNKNOWN"; fi
  fi
  rm -f ${tmp}
}


if [ -z $1 ]; then
  usage
fi

DEVICE="$1"

IOSYS="io.sys"
MSDOS="msdos.sys"
TYPE="UNKNOWN"

check_bootsect $DEVICE
if [ -z $2 ]; then
  echo "$TYPE $IOSYS $MSDOS"
  exit 0
fi


TARGDIR="$2"
shift; shift

badcase=0
while getopts "i:m:C:t" OPT; do
  case $OPT in
    i) IOSYS=$OPTARG;;
    m) MSDOS=$OPTARG;;
    C) COMCOM=$OPTARG;;
    t) check_bootsect $DEVICE;;
    ?) badcase=1
  esac
done
if [ $badcase -eq 1 ]; then usage; fi

if [ "$TYPE" = "WIN95" ]; then
  if exist_file $DEVICE /windows/${COMCOM}; then
    COMCOM="windows/${COMCOM}"
  fi
fi


echo "System type is $TYPE. sysfiles: ${IOSYS}, ${MSDOS}, $COMCOM"
mkdir -p $TARGDIR
get_bootsect $DEVICE ${TARGDIR}/boot.bin
if [ "$MSDOS" = "N/A" ]; then
  do_mtool $DEVICE mcopy -an w:/${IOSYS} w:/${COMCOM} $TARGDIR
else
  do_mtool $DEVICE mcopy -an w:/${IOSYS} w:/${MSDOS} w:/${COMCOM} $TARGDIR
fi
