#!/bin/bash
#
# Resize a bootable DOS floppy image formatted with FAT12.
#
# 2005 Christian Schneider. USE ON YOUR OWN RISK!
#
# based on "mkfloppyimg.sh" by:
#
# Murali Krishnan Ganapathy's version:
#   http://people.cs.uchicago.edu/~gmurali/gui/downloads.html
#
# Carsten Grohmann's version:
#   http://www.carstengrohmann.de/
#
# This script requires:
# - the commands listed below
# - lmount and lumount are optional
#

########################################################################
# configuration part
########################################################################

# debugging
#set -x

# execute no command without full path
export PATH=""

# default new size
SIZE_DEFLT="2880"

# commands with full paths
MKDOSFS="/sbin/mkdosfs"
DD="/bin/dd"
CP="/bin/cp"
RMDIR="/bin/rmdir"
CUT="/usr/bin/cut"
GREP="/usr/bin/grep"
MKTEMP="/bin/mktemp"
MOUNT="/bin/mount"
UMOUNT="/bin/umount"
LMOUNT="/usr/local/bin/lmount"
LUMOUNT="/usr/local/bin/lumount"

# default mount points and options
if [ -x "${LMOUNT}" ]; then
  MNT_OLD="/media/loop1"
  MNT_NEW="/media/loop2"
  OPTS_OLD="ro"
  OPTS_NEW="rw,my_uid,my_gid"
  MOUNT="${LMOUNT}"
  UMOUNT="${LUMOUNT}"
else
  MNT_OLD="$("${MKTEMP}" -d /tmp/old.XXXXXX)"
  MNT_NEW="$("${MKTEMP}" -d /tmp/new.XXXXXX)"
  OPTS_OLD="loop,ro"
  OPTS_NEW="loop,rw"
fi

########################################################################
# functions
########################################################################

# print error message and exit
# arguments: 1 = error message
exit_error () {
  echo "ERROR: ${1}" >&2
  exit 1
}

# print help
# arguments: -
print_help () {
  echo "${0##*/} [-s <size>] <old image> <new image>" >&2
  echo "Resize a bootable DOS floppy image formatted with FAT12." >&2
  echo >&2
  echo "Parameters:" >&2
  echo "  -s <size>       size of the new image in kB (default: 2880)" >&2
  echo "  <old image>     image of the old bootable DOS floppy image with FAT12" >&2
  echo "  <new image>     the new, resized floppy image" >&2
  echo "  -h|--help       print this help" >&2
  exit 2
}

########################################################################
# parse command line options
########################################################################

# some variables to remember specified parameters
SIZE=""
IMG_OLD=""
IMG_NEW=""

# parse options
while [ "${1}" != "" ]; do
  case "${1}" in
    -s)
      [ "${SIZE}" = "" ] || exit_error "Parameter \"-s\" specified several times!"
      shift || exit_error "No size specified after \"-s\"!"
      SIZE="${1}"
      ;;
    -h|--help)
      print_help
      ;;
    *)
      if [ "${IMG_OLD}" = "" ]; then
        IMG_OLD="${1}"
      else
        if [ "${IMG_NEW}" = "" ]; then
	  IMG_NEW="${1}"
	else
          exit_error "Too many parameters: \"${1}\"!"
	fi
      fi
      ;;
  esac
  shift
done

########################################################################
# consistency check of command line parameters
########################################################################

# general check
[ "${SIZE}" = "" ] && SIZE="${SIZE_DEFLT}"
[ "${IMG_OLD}" = "" ] && exit_error "No image files specified!"
[ "${IMG_NEW}" = "" ] && exit_error "No new image file specified!"

# check existence of files
[ -f "${IMG_OLD}" ] || exit_error "${IMG_OLD} does not exist!"
[ -e "${IMG_NEW}" ] && exit_error "${IMG_NEW} already exists!"

########################################################################
# main part
########################################################################

# Create the filesystem
OUTPUT="$("${MKDOSFS}" -v -I -C -F 12 "${IMG_NEW}" "${SIZE}" | "${GREP}" 'heads')"
HEADS="$(echo "${OUTPUT}" | "${CUT}" -f3 -d' ')"
SECTORS="$(echo "${OUTPUT}" | "${CUT}" -f6 -d' ')"
CYLINDERS="$((2 * SIZE / HEADS / SECTORS))"
#             ^^^^^^^^ total number of sectors in new image

# Copy contents from old image to new image
"${MOUNT}" -t msdos -o "${OPTS_OLD}" "${IMG_OLD}" "${MNT_OLD}" || \
  exit_error "Mounting old image failed!"
"${MOUNT}" -o "${OPTS_NEW}" "${IMG_NEW}" "${MNT_NEW}" || \
  exit_error "Mounting new image failed!"
"${CP}" -r "${MNT_OLD}"/* "${MNT_NEW}" || \
  exit_error "Copying files to new image failed!"
"${UMOUNT}" "${MNT_OLD}" || exit_error "Umounting old image failed!"
"${UMOUNT}" "${MNT_NEW}" || exit_error "Umounting new image failed!"

# Create the boot sector of the new image
# copy bytes 1 to 11 from old image to new one
"${DD}" if="${IMG_OLD}" of="${IMG_NEW}" bs=1 count=11 conv=notrunc 2>/dev/null || \
  exit_error "Copying of first part of boot sector failed!"
# copy bytes 63 to 512 from old image to new one
"${DD}" if="${IMG_OLD}" of="${IMG_NEW}" bs=1 skip=62 seek=62 count=450 conv=notrunc 2>/dev/null || \
  exit_error "Copying of second part of boot sector failed!"

########################################################################
# print output
########################################################################

# Print details
if [ "${SIZE}" != "1200" -a "${SIZE}" != "1440" -a "${SIZE}" != "2880" ]; then
  echo "Add the following to the arguments of memdisk:"
  echo "\"floppy c=${CYLINDERS} s=${SECTORS} h=${HEADS}\""
fi

########################################################################
# clean up
########################################################################

if [ ! -x "${LMOUNT}" ]; then
  "${RMDIR}" "${MNT_OLD}"
  "${RMDIR}" "${MNT_NEW}"
fi
