#!/bin/ash
#(c) Copyright Barry Kauler, October 2017. License: GPL v3 (/usr/share/doc/legal)
#gui for 'dd' utility.
#optional cli mode: source-file target-drive
#171004 first release.

export TEXTDOMAIN=easydd
export OUTPUT_CHARSET=UTF-8

[ ! $DISPLAY ] && exit #cli mode does require final confirm window.

ERRTITLE="$(gettext 'ERROR')"
err_exit() {
 pupmessage -bg '#ffa0a0' -title "EasyDD: ${ERRTITLE}" "$@"
 exit 1
}

ERR=''
if ! which dd >/dev/null ;then ERR="${ERR} dd"; fi
if ! which gtkdialog >/dev/null ;then ERR="${ERR} gtkdialog"; fi
if [ "$ERR" ];then
 err_exit "$(gettext 'These utilities are missing:')
${ERR}"
fi
#the full dd is required...
DDTEST="$(dd --help | grep 'periodic transfer statistics')"
[ ! "$DDTEST" ] && err_exit "$(gettext "dd utility does not support 'status=progress' cli option")"

FILESOURCE=''; DRVTARGET=''
if [ $1 ];then
 if [ -f "$1" ];then
  FILESOURCE="$1"
  if [ ! $2 ];then
   err_exit "Target drive not specified"
  else
   DRVTARGET="${2/*\//}" #dump /dev/ if exists
   DRVVERIFY="$(probedisk | grep "^/dev/${DRVTARGET}|")"
   [ ! "$DRVVERIFY" ] && err_exit "$(gettext 'This drive does not exist:')
${DRVTARGET}
$(gettext 'Specify an existing drive, and not a partition')"
  fi
 else
  echo "EasyDD is a GUI frontend for the 'dd' utility."
  echo "Optional CLI: source-file target-drive"
  echo "Source file must be format *.img[.gz|.bzip2|.xz]"
  echo "Target must be an entire drive, not a partition. ex: sda"
  exit
 fi
fi

while [ ! "$DRVTARGET" ];do ###start gui-1###
 
 pupdialog --background '#ffff80' --backtitle "EasyDD" --yes-label "$(gettext 'Continue')" --no-label "$(gettext 'Cancel')" --colors --yesno "$(gettext 'This first version of EasyDD will write an image file to a drive.')
\Zb$(gettext 'Please plugin the target drive right now, if not already.')\ZB
$(gettext "Then, click the 'Continue' button...")

$(gettext '(Note, there will be further sanity checks before writing to the drive)')" 0 0
 [ $? -ne 0 ] && exit
 sleep 0.5
 
 INTERFACE="$(gettext 'Interface:')"
 DESCRIPTION="$(gettext 'Description:')"
 DISKS="$(probedisk | cut -f 3- -d '/' | sed -e "s%|% (${INTERFACE} %" | sed -e "s%|% ${DESCRIPTION} %" | sed -e 's%$%)%')"
 CNT=1; RADIOXML=""
 while read adisk
 do
  adev="$(echo -n "$adisk" | cut -f 1 -d ' ')" #ex: sda
  RADIOXML="${RADIOXML}
 <radiobutton><variable>DISK_${adev}</variable><label>${adisk}</label></radiobutton>"
  CNT=`expr $CNT + 1`
 done <<_EOF
$(echo "$DISKS")
_EOF

 [ ! "$RADIOXML" ] && err_exit "$(gettext 'Cannot find any drives')"

 export EASYDD_DLG1="
<window title=\"EasyDD $(gettext 'frontend for dd')\" icon-name=\"gtk-harddisk\">
 <vbox>
  <text use-markup=\"true\">
   <label>\"<b>$(gettext 'Simple GUI for dd')</b>\"</label>
  </text>
  <text><label>$(gettext 'This first version has only one purpose, to write an image file to an entire drive.')</label></text>
  <text use-markup=\"true\"><label>\"$(gettext 'An example would be a downloaded release of Easy OS, with a name like:')
<b>easy-0.6-and64.img.gz</b>\"</label></text>

  <frame $(gettext 'Source')>
   <text><label>$(gettext 'Choose the image file:')</label></text>
   <hbox>
    <entry accept=\"savefilename\">
     <variable>FILESOURCE</variable>
    </entry>
    <button>
     <input file stock=\"gtk-open\"></input>
     <variable>FILE_BROWSE_SAVEFILENAME</variable>
     <action function=\"fileselect\">FILESOURCE</action>
    </button>
   </hbox>
  </frame>
  
  <frame $(gettext 'Destination')>
   <text><label>$(gettext 'Choose the target drive:')</label></text>
   ${RADIOXML}
  </frame>
  <hbox>
   <button><label>$(gettext 'Go back to previous window')</label><action>exit:goback</action></button>
   <button cancel></button>
   <button ok></button>
  </hbox>
 </vbox>
</window>"

 RETVARS="`gtkdialog --program=EASYDD_DLG1 --center`"
 [ $? -ne 0 ] && exit
 eval "$RETVARS"

 #echo "$RETVARS" #TEST
 if [ "$EXIT" == "goback" ];then
  DRVTARGET=''
  continue
 fi
 [ "$EXIT" != "OK" ] && exit

 DRVTARGET="$(echo "$RETVARS" | grep '^DISK_' | grep '"true"' | cut -f 2 -d '_' | cut -f 1 -d '=')"
 break
done ###end gui-1###

#check source
if [ "$(echo -n "$FILESOURCE" | grep -E '\.img\.gz$|\.img\.xz$|\.img\.bzip2$|\.img$')" == "" ];then
 err_exit "For sanity-check, the source filename must end in '.img', '.img.gz', 'img.xz' or '.img.bzip2'"
fi

#check dest
MNTD="$(grep "^/dev/$DRVTARGET" /proc/mounts | cut -f 1 -d ' ')"
for amntd in $MNTD
do
 sync
 umount $amntd
done
MNTD="$(grep "^/dev/$DRVTARGET" /proc/mounts | cut -f 1 -d ' ')"
if [ "$MNTD" ];then
 err_exit "$(gettext 'A partition in target drive cannot be unmounted:')
${MNTD}"
fi

export EASYDD_DLG2="
<window title=\"EasyDD $(gettext 'frontend for dd')\" icon-name=\"gtk-harddisk\">
 <vbox>
  <text use-markup=\"true\"><label>\"<b>$(gettext 'Ready to write!')</b>\"</label></text>
  
  <text use-markup=\"true\"><label>\"$(gettext 'Source file:')
<b>${FILESOURCE}</b>
$(gettext 'Target drive:')
<b>${DRVTARGET}</b>\"</label></text>
  
  <text use-markup=\"true\"><label>\"<span fgcolor='red'>$(gettext 'Check very carefully that target drive is correct, as it will be entirely rewritten, and all pre-existing partitions wiped. Only click the OK button if you know what you are doing!')</span>\"</label></text>

  <hbox>
   <button cancel></button>
   <button ok></button>
  </hbox>
 </vbox>
</window>"

#echo "$EASYDD_DLG2" #TEST
RETVARS="`gtkdialog --program=EASYDD_DLG2 --center`"
[ $? -ne 0 ] && exit
eval "$RETVARS"
[ "$EXIT" != "OK" ] && exit

EXEC=''
EXT="${FILESOURCE/*./}"
case "$EXT" in
 gz)
  if ! which gunzip >/dev/null ;then err_exit "$(gettext 'Utility gunzip does not exist')"; fi
  EXEC="gunzip --stdout"
  gunzip --test $FILESOURCE > /dev/null 2>&1
  [ $? -ne 0 ] && err_exit "$(gettext 'Source file appears to be corrupted:')
${FILESOURCE}"
 ;;
 bzip2)
  if ! which bunzip2 >/dev/null ;then err_exit "$(gettext 'Uility bunzip2 does not exist')"; fi
  EXEC="bunzip2 --stdout"
  bunzip2 --test $FILESOURCE > /dev/null 2>&1
  [ $? -ne 0 ] && err_exit "$(gettext 'Source file appears to be corrupted:')
${FILESOURCE}"
 ;;
 xz)
  if ! which unxz >/dev/null ;then err_exit "$(gettext 'Utility unxz does not exist')"; fi
  EXEC="unxz --stdout"
  unxz --test $FILESOURCE > /dev/null 2>&1
  [ $? -ne 0 ] && err_exit "$(gettext 'Source file appears to be corrupted:')
${FILESOURCE}"
 ;;
 img)
  EXEC=''
 ;;
 *)
  err_exit "$(gettext 'Filename is wrong')"
 ;;
esac

if [ "$EXEC" ];then
 echo "#!/bin/bash
echo \"Executing:\"
echo \"${EXEC} \"${FILESOURCE}\" | dd of=/dev/${DRVTARGET} bs=1M conv=fsync status=progress oflag=sync\"
echo ''
echo \"Please wait...\"
${EXEC} \"${FILESOURCE}\" | dd of=/dev/${DRVTARGET} bs=1M conv=fsync status=progress oflag=sync" > /tmp/easydd-exec
 chmod 755 /tmp/easydd-exec
 rxvt -title 'EasyDD' -background '#ffff80' -geometry '80x8' -e /tmp/easydd-exec
else
 rxvt -title "EasyDD: $(gettext 'writing to') ${DRVTARGET}" -background '#ffff80' -geometry '80x2' -e dd if="${FILESOURCE}" of=/dev/${DRVTARGET} bs=1M conv=fsync status=progress oflag=sync
fi
sync

sleep 2 #need sleep before next line...
echo 'change' > /sys/block/${DRVTARGET}/uevent
pupmessage -bg '#a0ffa0' -title "EasyDD: $(gettext 'Write finished')" "$(gettext 'You may unplug the drive')"
###END###
