#!/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.
#180926 sfs 4 PRA ttp://bkhome.org/news/201710/easydd-frontend-for-dd.html

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}" "$@"
 ntf -i  "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="$(dd --help | grep '«progress»')"
[ ! "$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 "$(gettext '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 *.iso|.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###
 
 
 INTERFACE="$(gettext 'Interface:')"
 DESCRIPTION="$(gettext 'Description:')"
 ##DISKS="$(probedisk | cut -f 3- -d '/' | sed -e "s%|% (${INTERFACE} %" | sed -e "s%|% ${DESCRIPTION} %" | sed -e 's%$%)%')"
 DISKS="$(probedisk |egrep -v '^/dev/sr' | 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 help></button>
   <button ok></button>
   <button cancel></button>
  </hbox>
 </vbox>
</window>"

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

 #echo "$RETVARS" #TEST
 [ "$EXIT" = "Help" ] && { easydd-help ;exit ; } 
 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
if [ "$(echo -n "$FILESOURCE" | grep -E '\.img\.gz$|\.img\.xz$|\.img\.bzip2$|\.img$|\.iso$')" == "" ];then
 err_exit "$(gettext "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 ok></button>
   <button cancel></button>
  </hbox>
 </vbox>
</window>"

#echo "$EASYDD_DLG2" #TEST
##RETVARS="`gtkdialog --program=EASYDD_DLG2 --center`"
ntf -q "$(gettext 'Ready to write!') " "$(gettext 'Source file:')
<b>${FILESOURCE}</b>
$(gettext 'Target drive:')
<b>${DRVTARGET}</b>

<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>"
[ $? -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"
  EXEC2="gunzip -l"
  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"
  EXEC2="du -h"
  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"
  EXEC2="unxz -l"
  unxz --test $FILESOURCE > /dev/null 2>&1
  [ $? -ne 0 ] && err_exit "$(gettext 'Source file appears to be corrupted:')
${FILESOURCE}"
 ;;
 img)
  EXEC=''
 iso)
  EXEC=''
 ;;
 *)
  err_exit "$(gettext 'Filename is wrong')"
 ;;
esac

if [ "$EXEC" ];then
 echo "#!/bin/bash
echo \"${EXEC2} \"${FILESOURCE}\"\"
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
 urxvt -title 'EasyDD' -background '#ffff80' -geometry '80x8' -foreground 'black' -e /tmp/easydd-exec
else
 urxvt -title "EasyDD: $(gettext 'writing to') ${DRVTARGET}" -background '#ffff80' -foreground 'black' -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')"
ntf -w $(gettext 'Write finished')" "$(gettext 'You may unplug the drive')"
###END###
