#!/bin/sh
#
# These variables can be overwritten by Update.ini:
#
ACTION="restore"  # Automatically select option instead of showing the menu; possible options: update, restore, backup
FILENAME=""  # Filename to use for the image file; if empty, the filename will be composed automatically
EXTENSION=".os"  # Extension to use for the image file
PRODUCT=""  # Product type; if empty will be determined from the DMI table
COMPATIBILITY=""  # Compatibility range; if empty dialog will appear, initialized to the value in the DMI table
DATE=""  # Date for the image; if empty a date selector will appear, initialized to the current date
VERSION=""  # Version of the image; if empty an input box will appear
WARNING="true"  # If set to "false" security questions are disabled
OVERRIDE="0" # Override comparison checks; 1 = skip product type, 2 = skip compatibility too, 3 = skip size as well
#
# Include update.ini if available
#
UPDATEINI="/tmp/VIPAclone/update.ini"
if [ -f $UPDATEINI ]; then
  dos2unix $UPDATEINI  # Make sure the script has Unix line endings
  source $UPDATEINI    # Include file
fi
#
# These variables may be edited:
#
BASENAME="VIPAclone"  # Use this for archive files if not changed by SetBasename() or overridden by FILENAME
ARCHIVER="gzip"  # Archiver to use for backup; currently supported: gzip, xz
COMPRESSION="-4"  # Compression level used during backup; recommended: -4 for gzip, -2 for xz
REBOOT=0  # Automatic reboot after update if set to 1
VERIFY=0  # Verify data on destination if set to 1
#
# Do not touch these variables or constants:
#
ARG=$1  # Instead of searching for the USB drive, the calling script shall tell us which device we came from
RET=/tmp/dialog_answer  # Answer from dialog windows
BIN=/tmp/VIPAclone  # Directory where this script and all the additional tools are
HASHLOG=/tmp/hash.md5  # Hashlog output from dcfldd
SCB=/sys/class/block  # Look for block devices here
DMI=/sys/class/dmi/id  # DMI information is located here
INTERNALDRIVE=""  # Return variable for SelectInternalDrive()
SERIAL=""  # Optional serial number
BT="--backtitle VIPAclone_Backup/Restore_V1.0"  # Background title for all dialogs; underscores necessary because embedded quotes don't seem to work with dialog


#
# Set BASENAME according to product name
#
SetBasename()
{
if [ "$SYSVENDOR" = "VIPA" ]; then  # Only for VIPA
SERIAL="`cat $DMI/product_serial`"
BASENAME="`cat $DMI/product_name | awk '{print $2}'`"
PRODUCTNAME="$BASENAME"
#case $BASENAME in  # WES7 with or without Movicon; same image for both panel sizes
#  "67P-PNL0-JB") BASENAME="67x-PNL0-JB"; OSNAME="WES7" ;;
#  "67S-PNL0-JB") BASENAME="67x-PNL0-JB"; OSNAME="WES7" ;;
#  "67M-QQM0-JB") BASENAME="67M-QQM0-JB"; OSNAME="WES7" ;;
#  "67P-PNL0-JX") BASENAME="67x-PNL0-JX"; OSNAME="WES7" ;;
#  "67S-PNL0-JX") BASENAME="67x-PNL0-JX"; OSNAME="WES7" ;;
#  *) BASENAME="$BASENAME"; OSNAME="WEC7" ;;  # Otherwise it's WEC7
#esac
else  # Not VIPA, but SYSVENDOR has been set
  BASENAME="`cat $DMI/product_name | tr -s ' ' '_'`"  # Replace whitespace with underscore
fi
}


#
# Function to find and select internal drive
#
SelectInternalDrive()
{
if [ -z "$1" ]; then  # Forgot update or backup parameter
  INTERNALDRIVE=""
  return
fi

# Search for internal drives
dialog $BT --title "Searching..." --infobox "\n  Searching for internal drives..." 5 50
DEV=""
LAST=""
i=0
#parted -lsm > /tmp/parted.lsm
for BDEV in `ls /sys/block`
do
  if [ -z "`readlink $SCB/$BDEV | grep usb`" ]; then  # Only search for non-USB ones
    if [ -f /sys/block/$BDEV/device/model ]; then
	  NAME=`cat /sys/block/$BDEV/device/model | tr -s ' ' '_'`
	elif [ -f /sys/block/$BDEV/device/name ]; then
	  NAME=`cat /sys/block/$BDEV/device/name | tr -s ' ' '_'`
	else
	  continue
	fi
    if [ -f /sys/block/$BDEV/size ]; then
	  if [ "`wc /sys/block/$BDEV/size | awk '{print $3}'`" -gt 9 ]; then
        SIZE="`expr $(cat /sys/block/$BDEV/size) / 2097152`GB"
	  else
        SIZE="`expr $(cat /sys/block/$BDEV/size) / 2048`MB"
	  fi
	else
	  SIZE="???"
	fi
    i=$(($i+1))
#    DISK=`cat /tmp/parted.lsm | grep /dev/$BDEV`
#    NAME=`echo $DISK | cut -d ':' -f7 | tr -s ' ' '_'`
#    SIZE=`echo $DISK | cut -d ':' -f2`
    DEV="$DEV $BDEV $NAME/$SIZE"
    LAST="$BDEV"
  fi
done

if [ $i -eq 0 ]; then
  dialog $BT --title "No drives?" --msgbox "\n     No internal drives found!" 7 50
  INTERNALDRIVE=""
elif [ $i -eq 1 ]; then
  INTERNALDRIVE="$LAST"  # If only one drive, automatically select the one that was found last
else
  dialog $BT --title "Select Internal Drive" --ok-label "Select" --menu "\n Select drive to $1:" 20 60 $i $DEV 2>$RET
  if [ "$?" != "0" ]; then  # Cancel
    INTERNALDRIVE=""
  else
    INTERNALDRIVE="`cat $RET`"
  fi
fi
}


#
# Update function
#
VIPAupdate()
{
# Select internal drive
SelectInternalDrive "update"

if [ -z "$INTERNALDRIVE" ]; then
  return
else
  DST="$INTERNALDRIVE"
fi

if [ -z $OVERRIDE ]; then
  OVERRIDE="0"
fi

# This should only happen when the script is called manually without a drive parameter
if [ -z "$ARG" ]; then
  dialog $BT --title "No Source Medium" --msgbox "\n     No update source parameter!" 7 50
  return
fi

if [ ! -e "$ARG" ]; then
  dialog $BT --title "No Source Medium" --msgbox "\n     USB boot drive has been removed!" 7 50
  return
fi

# Try to mount USB drive
MOUNT="mount -t vfat"
if [ -n "`fdisk -l | grep $ARG  | grep NTFS`" ]; then
  MOUNT="ntfs-3g"
fi
$MOUNT $ARG /mnt
if [ "$?" != 0 ]; then
  dialog $BT --title "Mount Error" --msgbox "\n     Cannot mount $ARG to /mnt!" 7 50
  return
fi

# Search for image file, unless filename is given
if [ -z $FILENAME ]; then
  dialog $BT --title "Searching..." --infobox "\n  Searching for image files..." 5 50
  LIST=""
  i=0
  for FILE in `ls /mnt/*$EXTENSION`
  do
    if [ `$BIN/vipaheader -r $FILE -o | head -c 1` != "+" ]; then
	  continue  # No correct image header; next file...
	fi
    SRCTYPE=`$BIN/vipaheader -r $FILE -tx`  # Device type
	if [ "$OVERRIDE" -lt 1 ]; then  # Do not skip product type comparison
	  WILDCARDCMP=`$BIN/wildxcmp $SRCTYPE $PRODUCTNAME`
	  if [  "$WILDCARDCMP" != "Product types match" ]; then
	    continue
	  fi
	fi
    SRCCOMP=`$BIN/vipaheader -r $FILE -cx`  # Compatibility range
	if [ "$OVERRIDE" -lt 2 ]; then  # Do not skip compatibility comparison
	  MYCOMPATIBILITY="`cat $DMI/product_version | cut -d# -f2`"
	  if [ -n "$SRCCOMP" -a "$MYCOMPATIBILITY" -lt `echo $SRCCOMP | head -c 1` -o "$MYCOMPATIBILITY" -gt `echo $SRCCOMP | tail -c 2` ]; then
	    continue
	  fi
	fi
    SRCSIZE=`$BIN/vipaheader -r $FILE -sx`  # Uncompressed image size
	if [ "$OVERRIDE" -lt 3 ]; then  # Do not skip size comparison
	  SIZE=`expr $(cat $SCB/$DST/size) / 2048)`  # Size in MB, since block size is 512 byte in Linux
	  if [ $SIZE -lt $SRCSIZE ]; then
	    continue
	  fi
	fi
    SRCDATE=`$BIN/vipaheader -r $FILE -dx`  # Image date
    SRCVERS=`$BIN/vipaheader -r $FILE -vx`  # Image version
    LIST="$LIST `basename $FILE $EXTENSION` $SRCTYPE/$SRCCOMP/$SRCDATE/$SRCVERS/${SRCSIZE}MB"
	LAST="`basename $FILE`"
    i=$(($i+1))
  done
  if [ $i -eq 0 ]; then  # No file
    IMAGENAME=""
	umount /mnt
    dialog $BT --title "No Image File" --msgbox "\n     No (compatible) image file found!" 7 50
	return
  elif [ $i -eq 1 ]; then
    IMAGENAME="$LAST"  # If only one file, automatically select the one that was found last
  else  # Otherwise display list
    dialog $BT --title "Select Image File" --ok-label "Select" --menu "\n Select image file (Filename Type/Compatibility/Date/Version/Size):" 20 76 $i $LIST 2>$RET
    if [ "$?" != "0" ]; then  # Cancel
      IMAGENAME=""
      umount /mnt
      return
    else
      IMAGENAME="`cat $RET`$EXTENSION"
    fi
  fi
else  # FILENAME is not empty
  IMAGENAME="$FILENAME$EXTENSION"
fi

# Check if file exists
if [ ! -f /mnt/$IMAGENAME ]; then
  umount /mnt
  dialog $BT --title "Image File Missing" --msgbox "\n Cannot find $IMAGENAME!\n\n Make sure the image file is in the\n root directory of the USB drive." 10 60
  return
fi

# Check image header by trying to read the offset (which we need anyway)
OFFSET=`$BIN/vipaheader -r /mnt/$IMAGENAME -o`
if [ "`echo $OFFSET | head -c 1`" != "+" ]; then
  umount /mnt
  dialog $BT --title "Incorrect Header" --msgbox "\n Could not read header of file\n $IMAGENAME!\n\n Wrong or corrupt file?" 10 50
  return
fi

# Get more info from the header
SRCARCH=`$BIN/vipaheader -r /mnt/$IMAGENAME -ax`  # Compression method
SRCHASH=`$BIN/vipaheader -r /mnt/$IMAGENAME -hx`  # MD5 hash
SRCSIZE=`$BIN/vipaheader -r /mnt/$IMAGENAME -sx`  # Uncompressed image size
SRCTYPE=`$BIN/vipaheader -r /mnt/$IMAGENAME -tx`  # Device type
SRCCOMP=`$BIN/vipaheader -r /mnt/$IMAGENAME -cx`  # Compatibility range

# Get info on the internal drive
if [ -f $SCB/$DST/device/model ]; then
  NAME="`cat $SCB/$DST/device/model`"
elif [ -f $SCB/$DST/device/name ]; then
  NAME="`cat $SCB/$DST/device/name`"
else
  NAME="???"
fi
SIZE=`expr $(cat $SCB/$DST/size) / 2048)`  # Size in MB, since block size is 512 byte in Linux
#BS=`cat $SCB/$DST/queue/physical_block_size`
BS=`cat $SCB/$DST/queue/max_segment_size`

# Check product type
if [ "$OVERRIDE" -lt 1 ]; then  # Do not skip product type comparison
WILDCARDCMP=`$BIN/wildxcmp $SRCTYPE $PRODUCTNAME`
if [  "$WILDCARDCMP" != "Product types match" ]; then
  umount /mnt
  dialog $BT --title "Product Type Mismatch" --msgbox "\n Image is for type: $SRCTYPE\n\n Hardware has type: $PRODUCTNAME" 10 50
  return
fi
fi

# Check compatibility
if [ "$OVERRIDE" -lt 2 ]; then  # Do not skip compatibility comparison
if [ -n "$SRCCOMP" ]; then
  MYCOMPATIBILITY="`cat $DMI/product_version | cut -d# -f2`"
  LOWCOMPATIBILITY=`echo $SRCCOMP | head -c 1`
  HIGHCOMPATIBILITY=`echo $SRCCOMP | tail -c 2`
  if [ "$MYCOMPATIBILITY" -lt "$LOWCOMPATIBILITY" ]; then
    umount /mnt
    dialog $BT --title "Compatibility Mismatch" --msgbox "\n Hardware compatibility: '$MYCOMPATIBILITY'\n Image compatibility:    '$SRCCOMP'\n\n Hardware too old for this image file!" 10 50
	return
  fi
  if [ "$MYCOMPATIBILITY" -gt "$HIGHCOMPATIBILITY" ]; then
    umount /mnt
    dialog $BT --title "Compatibility Mismatch" --msgbox "\n Hardware compatibility: '$MYCOMPATIBILITY'\n Image compatibility:    '$SRCCOMP'\n\n Hardware too new for this image file!" 10 50
	return
  fi
fi
fi

# Check that image archiver is present
$SRCARCH -h > /tmp/archiver.out
if [ -z "`cat /tmp/archiver.out`" ]; then
  umount /mnt
  dialog $BT --title "Archiver Missing" --msgbox "\n Archiver '$SRCARCH' cannot be found! \n\n Newer VIPAclone version needed?" 10 50
  return
fi

# This hopefully never happens
if [ -z "$SIZE" ]; then
  umount /mnt
  dialog $BT --title "Destination Size Error" --msgbox "\n Could not determine size of destination disk!\n $SCB/$DST/size" 10 50
  return
fi

# Should only happen if there is a serious error with the header
if [ -z "$SRCSIZE" ]; then
  umount /mnt
  dialog $BT --title "Source Data Size Error" --msgbox "\n Could not determine size of original disk!\n Corrupt image header?" 10 50
  return
fi

# Should only happen if there is a serious error with the header
if [ -z "$SRCHASH" ]; then
  umount /mnt
  dialog $BT --title "Source Data Hash Error" --msgbox "\n Could not determine hash of original disk!\n Corrupt image header?" 10 50
  return
fi

# Check that image contents fit onto the destination drive
if [ "$OVERRIDE" -lt 3 ]; then  # Do not skip size comparison
if [ $SIZE -lt $SRCSIZE ]; then
  umount /mnt
  dialog $BT --title "Destination Disk Too Small" --msgbox "\n Destination disk $NAME\n smaller ($SIZE MB) than source data ($SRCSIZE MB)!" 10 54
  return
fi
fi

# Ask user to confirm the update operation
if [ "$WARNING" != "false" ]; then
  dialog $BT --title "Confirm Update/Restore" --yesno "\n Source:      $IMAGENAME\n Size:        $SRCSIZE MB\n Destination: $NAME\n\n All previous data on $NAME\n will be lost!\n\n Proceed with update?" 14 60
  if [ "$?" != "0" ]; then  # Cancel
    umount /mnt
    return
  fi
fi

# Serial number output for Christof Kauer
if [ -z "$SERIAL" ]; then
  SERNUM=""
else
  SERNUM="Serial Number: $SERIAL"
fi

# This is the main data transfer
(tail -c $OFFSET /mnt/$IMAGENAME | $SRCARCH -d -c | $BIN/pv -n -s ${SRCSIZE}m | $BIN/dcfldd status=off hashlog=/tmp/hash.md5 of=/dev/$DST bs=$BS) 2>&1 | \
 dialog $BT --title "Update/Restore" --gauge "\n  Extracting $SRCSIZE MB\n  from $IMAGENAME\n  to $NAME\n  $SERNUM\n\n  Please wait for a few minutes." 12 50 0

# USB drive no longer needed
umount /mnt

# Read MD5 hash created by dcfldd
DSTHASH=`cat /tmp/hash.md5 | grep Total | awk '{print $3}'`
if [ "$SRCHASH" != "$DSTHASH" ]; then
  echo -n -e "\a"
  dialog $BT --title "Data Mismatch" --msgbox "\n Difference between original and extracted data! \n\n Image file is probably corrupt! " 10 60
  return
fi

# Verify data on destination by creating MD5 hash
if [ $VERIFY = "1" -a $SIZE = $SRCSIZE ]; then
  ($BIN/pv -n -s ${SRCSIZE}m /dev/$DST | $BIN/dcfldd status=off of=/dev/null hashlog=/tmp/verify.md5) 2>&1 | \
   dialog $BT --title "Verify" --gauge "\n  Verifying $SRCSIZE MB\n  of $NAME\n\n  Please wait for a few minutes." 10 50 0
  VERIFYHASH=`cat /tmp/verify.md5 | grep Total | awk '{print $3}'`
  if [ "$SRCHASH" != "$VERIFYHASH" ]; then
    echo -n -e "\a"
    dialog $BT --title "Data Mismatch" --msgbox "\n Difference between original and destination data! \n\n Most likely write errors! " 10 60
    return
  fi
fi

# Update successful
dialog $BT --title "Update Successful" --infobox "\n  The update of $NAME\n  has been completed successfully." 8 50
echo -n -e "\a"; sleep 1; echo -n -e "\a"; sleep 1; echo -n -e "\a"
if [ $REBOOT = "1" ]; then
  reboot; exit
else
  dialog $BT --title "Update Successful" --msgbox "\n  The update of $NAME\n  has been completed successfully." 8 50
fi
}


#
# Backup function
#
VIPAbackup()
{
# Check that selected archiver is present
$ARCHIVER -h > /tmp/archiver.out
if [ -z "`cat /tmp/archiver.out`" ]; then
  dialog $BT --title "Archiver Missing" --msgbox "\n Selected archiver '$ARCHIVER' cannot be found! \n\n Wrong ARCHIVER setting in script\n or newer VIPAclone version needed?" 10 50
  return
fi

# Select internal drive
SelectInternalDrive "backup"

if [ -z "$INTERNALDRIVE" ]; then
  return
else
  SRC="$INTERNALDRIVE"
fi

# This should only happen when the script is called manually without a drive parameter
if [ -z "$ARG" ]; then
  dialog $BT --title "No Destination" --msgbox "\n     No backup destination parameter!" 7 50
  return
fi

if [ ! -e "$ARG" ]; then
  dialog $BT --title "No Destination" --msgbox "\n     USB boot drive has been removed!" 7 50
  return
fi

# Get product code from DMI table, unless given
if [ -z $PRODUCT ]; then
  PRODUCT="$BASENAME"
fi
PRODUCT=`echo $PRODUCT | awk '{print $1}' | head -c 11`
TYPEARG="-t $PRODUCT"

# Read compatibilty from system if not provided by update.ini
if [ -z $COMPATIBILITY ]; then
  MYCOMPATIBILITY="`cat $DMI/product_version | cut -d# -f2`"
  COMPATIBILITY="$MYCOMPATIBILITY$MYCOMPATIBILITY"
fi
# Loop until there is a correct compatibility range (or none)
while true
do
if [ -z $COMPATIBILITY ]; then
  dialog $BT --title "Compatibility Range" --inputbox "\n Please enter compatibility range\n (e.g. 12):" 10 40 "$MYCOMPATIBILITY$MYCOMPATIBILITY" 2>$RET
  if [ "$?" != "0" ]; then  # Cancel
    COMPATIBILITY=""
  else
    COMPATIBILITY=`cat $RET`
  fi
fi
COMPATIBILITY=`echo $COMPATIBILITY | awk '{print $1}' | head -c 2`  # Cut it down to size
if [ -z $COMPATIBILITY ]; then
  COMPATARG=""  # No compatibility in header
  break
else
  COMPATARG="-c $COMPATIBILITY"
  $BIN/vipaheader -w /tmp/testheader $COMPATARG > /tmp/vipaheader.out
  if [ -n "`grep "Compatibility must be" /tmp/vipaheader.out`" ]; then
    dialog $BT --title "Compatibility Range Error" --msgbox "\n Compatibility range must be two digits where\n the first is not bigger than the second!\n\n Got compatibility range: $COMPATIBILITY" 10 50
	COMPATIBILITY=""
  else
    break
  fi
fi
done

# Let the user select the date, unless given
if [ -z $DATE ]; then
  dialog $BT --title "Date" --ok-label "Select" --calendar "\n Select image date:" 4 40 2>$RET
  if [ "$?" != "0" ]; then  # Cancel
    IMAGEDATE=""
    DATEARG=""
  else
    DATEDAY=`cat $RET | cut -d '/' -f1`
    DATEMONTH=`cat $RET | cut -d '/' -f2`
    DATEYEAR=`cat $RET | cut -d '/' -f3`
	IMAGEDATE="$DATEYEAR$DATEMONTH$DATEDAY"
    DATEARG="-d $IMAGEDATE"
  fi
else
  IMAGEDATE=`echo $DATE | awk '{print $1}' | head -c 8`
  DATEARG="-d $IMAGEDATE"
fi

# Let the user enter the version, unless given
if [ -z $VERSION ]; then
  dialog $BT --title "Version" --inputbox "\n Please enter version\n (e.g. V1.2.3):" 10 30 2>$RET
  if [ "$?" != "0" ]; then  # Cancel
    IMAGEVERSION=""
  else
    IMAGEVERSION=`cat $RET`
  fi
else
  IMAGEVERSION="$VERSION"
fi
IMAGEVERSION=`echo $IMAGEVERSION | awk '{print $1}' | head -c 6`
if [ -z $IMAGEVERSION ]; then
  VERSARG=""
else
  VERSARG="-v $IMAGEVERSION"
fi

# Compose filename for image, unless $FILENAME is given
if [ -z $FILENAME ]; then
  IMAGENAME="$PRODUCT"
  if [ -n "$OSNAME" ]; then
    IMAGENAME="${IMAGENAME}_${OSNAME}"
  fi
  if [ -n "$IMAGEDATE" ]; then
    IMAGENAME="${IMAGENAME}_${IMAGEDATE}"
  fi
  if [ -n "$IMAGEVERSION" ]; then
    IMAGENAME="${IMAGENAME}_${IMAGEVERSION}"
  fi
else  # FILENAME is not empty
  IMAGENAME=`echo $FILENAME | tr -s ' ' '_'`
fi
IMAGENAME="$IMAGENAME$EXTENSION"

# Try to mount USB drive
MOUNT="mount -t vfat"
if [ -n "`fdisk -l | grep $ARG  | grep NTFS`" ]; then
  MOUNT="ntfs-3g"
fi
$MOUNT $ARG /mnt
if [ "$?" != 0 ]; then
  dialog $BT --title "Mount Error" --msgbox "\n     Cannot mount $ARG to /mnt!" 7 50
  return
fi

# Get information about internal drive as well as the free space on the USB drive
if [ -f $SCB/$SRC/device/model ]; then
  NAME="`cat $SCB/$SRC/device/model`"
elif [ -f $SCB/$SRC/device/name ]; then
  NAME="`cat $SCB/$SRC/device/name`"
else
  NAME="???"
fi
SIZE="`expr $(cat $SCB/$SRC/size) / 2048` MB"
FREE="`df -m | grep /mnt | awk '{print $4}'` MB"

# Ask user to confirm the backup operation
if [ "$WARNING" != "false" ]; then
  dialog $BT --title "Confirm Backup" --yesno "\n Source:      $NAME\n Size:        $SIZE\n Destination: $IMAGENAME\n Free:        $FREE\n\n Proceed with backup?" 12 60
  if [ "$?" != "0" ]; then  # Cancel
    umount /mnt
    return
  fi
fi

# Ask to delete file if it already exits, then write the image header
if [ -f /mnt/$IMAGENAME ]; then
  if [ "$WARNING" != "false" ]; then
    dialog $BT --title "Overwrite File?" --yesno "\n File $IMAGENAME\n already exits! \n\n Overwrite file and proceed with backup?" 10 60
    if [ "$?" != "0" ]; then  # Cancel
      umount /mnt
      return
    fi
  fi
  rm /mnt/$IMAGENAME
fi
$BIN/vipaheader -w /mnt/$IMAGENAME -s $SIZE -a $ARCHIVER $TYPEARG $DATEARG $COMPATARG $VERSARG
if [ "$?" != "0" -o ! -f /mnt/$IMAGENAME ]; then
  rm $IMAGENAME
  umount /mnt
  dialog $BT --title "Header Error" --msgbox "\n Could not write header for\n $IMAGENAME" 8 50
  return
fi

# This is the main data transfer; the compressed data is appended to the image header
($BIN/pv -n /dev/$SRC | $BIN/dcfldd status=off hashlog=$HASHLOG | $ARCHIVER -c $COMPRESSION >> /mnt/$IMAGENAME) 2>&1 | \
 dialog $BT --title "Backup" --gauge "\n  Compressing $SIZE\n  of $NAME\n  into $IMAGENAME\n\n  Please wait for a few minutes." 11 50 0

# Add MD5 hash to image header
HASH=`cat $HASHLOG | grep Total | awk '{print $3}'`
if [ -z "$HASH" ]; then  # Hash is missing if not all data was written
  dialog $BT --title "USB Drive Full" --infobox "\n  The USB drive does not have enough\n  free space to complete backup! \n\n  Removing incomplete backup data..." 10 50
  echo -n -e "\a"
  rm /mnt/$IMAGENAME
  umount /mnt
  dialog $BT --title "USB Drive Full" --msgbox "\n  The USB drive does not have enough\n  free space to complete backup! \n\n  Incomplete backup data has been removed." 10 50	
  return
else
  $BIN/vipaheader -w /mnt/$IMAGENAME -h $HASH
  sync
fi

if [ $VERIFY = "1" ]; then
  echo 3 > /proc/sys/vm/drop_caches  # Flush caches to make sure the data on the device is verified, not just the cache contents
  OFFSET=`$BIN/vipaheader -r /mnt/$IMAGENAME -o`
  SIZE=`$BIN/vipaheader -r /mnt/$IMAGENAME -sx`
  # Extract archive to /dev/null to create another MD5 hash
  (tail -c $OFFSET /mnt/$IMAGENAME | $ARCHIVER -d -c | $BIN/pv -n -s ${SIZE}m | $BIN/dcfldd status=off hashlog=/tmp/verify.md5 of=/dev/null) 2>&1 | \
   dialog $BT --title "Verify Backup" --gauge "\n  Verifying $SIZE MB\n  of $IMAGENAME\n\n  Please wait for a few minutes." 10 50 0
  VERIFYHASH=`cat /tmp/verify.md5 | grep Total | awk '{print $3}'`
  if [ "$HASH" != "$VERIFYHASH" ]; then
    if [ "`df | grep /mnt | awk '{print $4}'`" = "0" ]; then
	  REASON="USB drive does not have enough free space!"
	else
	  REASON=""
	fi
    dialog $BT --title "Backup Corrupt" --infobox "\n  Backup data is corrupt! \n\n  Removing faulty image file..." 10 60
    echo -n -e "\a"
    rm /mnt/$IMAGENAME
    umount /mnt
    dialog $BT --title "Backup Removed" --msgbox "\n Corrupt backup image file has been removed. \n\n  $REASON " 10 60
    return
  fi
fi

# All done
umount /mnt
dialog $BT --title "Backup Successful" --infobox "\n  The backup of $NAME\n  to $IMAGENAME\n  has been completed successfully." 10 50
echo -n -e "\a"; sleep 1; echo -n -e "\a"; sleep 1; echo -n -e "\a"
dialog $BT --title "Backup Successful" --msgbox "\n  The backup of $NAME\n  to $IMAGENAME\n  has been completed successfully." 10 50
}


#
# Erase function
#
VIPAerase()
{
# Select internal drive
SelectInternalDrive "erase"

if [ -z "$INTERNALDRIVE" ]; then
  return
else
  DST="$INTERNALDRIVE"
fi

# Get info on the internal drive
if [ -f $SCB/$DST/device/model ]; then
  NAME="`cat $SCB/$DST/device/model`"
elif [ -f $SCB/$DST/device/name ]; then
  NAME="`cat $SCB/$DST/device/name`"
else
  NAME="???"
fi
SIZE=`expr $(cat $SCB/$DST/size) / 2048)`  # Size in MB, since block size is 512 byte in Linux

# Ask user to confirm the update operation
dialog $BT --title "Confirm Erase" --yesno "\n Clear $SIZE MB of $NAME\n\n All data on $NAME\n will be lost!\n\n Proceed with erase?" 12 60
if [ "$?" != "0" ]; then  # Cancel
  return
fi

# This is the main erase operation
($BIN/pv -n -s ${SIZE}m /dev/zero | $BIN/dcfldd status=off of=/dev/$DST) 2>&1 | \
 dialog $BT --title "Erase" --gauge "\n  Clearing $SIZE MB of $NAME\n\n  Please wait for a few minutes." 10 50 0

dialog $BT --title "Erase Completed" --infobox "\n  The erase of $NAME\n  has been completed." 10 50
echo -n -e "\a"; sleep 1; echo -n -e "\a"; sleep 1; echo -n -e "\a"
dialog $BT --title "Erase Completed" --msgbox "\n  The erase of $NAME\n  has been completed." 10 50
}


#
# Menu function
#
MainMenu()
{
dialog ${BT} --title "VIPA Backup/Update" --cancel-label "Exit" --ok-label "Select" --menu "Please select:" 11 60 4 Update "Update internal drive from USB drive" Backup "Save internal drive to USB drive" Erase "Clear internal drive" Reboot "Reboot computer" 2>$RET

if [ "$?" != "0" ]; then  # Cancel
  exit
fi

CHOICE=`cat $RET`
case $CHOICE in
  "Update") VIPAupdate ;;
  "Backup") VIPAbackup ;;
  "Erase") VIPAerase ;;
  "Reboot") reboot; exit ;;
esac
}

# "Script start"
echo -e "\033[9;0]"  # Turn off screen blanking

SYSVENDOR="VIPA"
if [ -n "$SYSVENDOR" ]; then
  if [ "$SYSVENDOR" != "`cat $DMI/sys_vendor`" ]; then
    dialog $BT --title "Wrong Hardware" --msgbox "\n  This tool is meant for $SYSVENDOR hardware only! \n\n  Forgot SMBIOS/DMI settings?" 10 50
	reboot
	exit
  else
    SetBasename
  fi
fi

# Check if ACTION setting overrides the menu
if [ $ACTION = "update" -o $ACTION = "restore" ]; then
  VIPAupdate
  sleep 1
  reboot
  exit
elif [ $ACTION = "backup" ]; then
  VIPAbackup
  sleep 1
  reboot
  exit
elif [ $ACTION = "erase" ]; then
  VIPAerase
  sleep 1
  reboot
  exit
fi

# Infinite loop over main menu
while true
do
  MainMenu
done

# EOF
