#! /bin/bash

#-----------------------------------------------------------------------------
#
## Copyright 2016 Nio Wiklund
#
# GPLv3: GNU GPL version 3
# <http://gnu.org/licenses/gpl.html>.
#
# This is free software: you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.

# date        editor   comment
# 2016-02-26  sudodus  created from mk_mkdos in mkusb
# 2016-02-27  sudodus  accepting only mass storage devices as target
# 2016-02-27  sudodus  version 1.1
# ----------------------------------------------------------------------
# 2016-10-19  sudodus  prepared with ppf for dus
# 2016-10-19  sudodus  created from restore-pendrive (simplified)
# 2016-11-14  sudodus  dus-wipe version 0.0.0
# 2016-12-29  sudodus  version 12.0.0 - mkusb-dus
# 2019-10-11  sudodus  part_info: added partprobe
# 2019-10-11  sudodus  version 12.3.3
# 2020-06-28  sudodus  added p_zentest, wf_prep, wf_cleanup to use watch-flush
# 2020-06-28  sudodus  version 12.5.8

version="${0##*/} 12.5.8"

action=
target=
inversvid="\0033[7m"
resetvid="\0033[0m"
faintvid="\0033[2m"
#redtext="\0033[31;47m"
redback="\0033[1;37;41m"
greenback="\0033[1;37;42m"

#######################################################################
#######################################################################

function read_pff {

# reading $1
# assigning common variable(s) (declared above)

if [ "${1:0:4}" == "pff:" ]
then
# cat "${1/pff:}"
 for i in action target
 do
  read $i
 done < "${1/pff:}"
 rm     "${1/pff:}"
# echo "action=$action"
# echo "target=$target"
else
 echo "no pff input"
fi
}
#######################################################################
#######################################################################

function d_wipe_1 {

gpt_fix "$target"
dd if=/dev/zero of="$target" bs=1024 count=1024 2>&1
if [ $? -eq 0 ]
then
 result="$greenback Done :-) $resetvid"
else
 result="$redback Failed :-( $resetvid"
fi
echo "Syncing the device ..."
sleep 0.5
sync
echo -e "$result"
}
#######################################################################
#######################################################################

function d_wipe_whole_device {

curlang="$LANG"
LANG=C
errout=$(mktemp --tmpdir dus.XXXXXXXXXX)
trg=${target##*/}
size=$(lsblk -bo name,size|grep ^"$trg"|sed 's/.* //')
#echo $size

p_zentest
if [ "$manager" == "z" ] && which watch-flush
then
 wf=true
else
 wf=false
fi
if $wf
then
 wf_prep
fi

< /dev/zero pv -s $size | dd of="$target" bs=4096 2>"$errout"

echo "Syncing the device ..."
sleep 0.5

if $wf
then
 wf_cleanup
else
 sync
fi

cat "$errout"
result="$greenback Done,$resetvid$inversvid but you should also check for the line $resetvid
'dd: error writing to '$target': No space left on device',
which means that the whole device is wiped. (Look a few lines above ^) "
echo -e "$result"
LANG="$curlang"
}
########################################################################
########################################################################

function gpt_fix {

# $1 is the target device

echo \
"v
q" \
| gdisk "$1" 2>/dev/null |grep -e 'GPT: damaged' > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo \
"v
x
e
r
d
w
y" \
| gdisk "$1" > /dev/null 2>&1

echo \
"v
q" \
| gdisk "$1" 2>/dev/null |grep -e 'GPT: damaged' -e 'Problem:' > /dev/null 2>&1
if [ $? -eq 0 ]
then
 echo "gpt_fix: failed to fix the GUID partition table (GPT) of $1"
else
 echo "gpt_fix: done :-)"
fi
fi
}
########################################################################
########################################################################

function part_info {

target=$1
sync
sleep 0.5
if [ "${target:0:11}" == "/dev/mmcblk" ]
then
 read -p "Unplug and re-plug the flash card to see the correct info ... and press Enter "
#elif [ "$disk_name_type" == "microsoft-windows" ]
#then
# read -p "Unplug and re-plug the target drive to see the correct info ... and press Enter "
fi
dlay=5
echo -e "$inversvid Wait $dlay seconds and a little more ... $resetvid"
sleep $dlay
partprobe 2> /dev/null
sleep 1

blkid -c /dev/null "${target}?" > /dev/null
sleep 0.5
partinfo=$(LANG=C parted -s "$target" print; \
echo " "; lsblk -o MODEL,NAME,FSTYPE,LABEL "$target"; \
echo -e "$inversvid There should only be the drive name $resetvid \
- unrecognised disk label, no partitions")

echo "$partinfo"
}
#######################################################################

function p_zentest {

zenity --info --title="$version - zenity-test" --timeout 1 \
 --width=350 --height=150 \
--text="Checking if zenity works in this environment" > /dev/null 2>&1
exitnr=$?
if [ $exitnr -eq 0 ] || [ $exitnr -eq 5 ]
then
 manager=z
else
 return 1
fi
}
########################################################################

function wf_prep {

tailfile=$(mktemp)
if [ "$manager" == "z" ]
then
 ( watch-flush "$size" "$tailfile" > /dev/null ) & pid0=$!

 ( tail -f "$tailfile"| zenity --progress --title="$version - progress ..." \
 --width=500 --height=400 \
 --percentage=0 --auto-close --no-cancel \
 --window-icon="/usr/share/icons/hicolor/48x48/apps/mkusb.png"  2>> "/dev/null") & pid1=$!
else
 watch-flush "$size" "$tailfile" & pid0=$!
fi
}
########################################################################

function wf_cleanup {

echo -en "$faintvid"
if [ "$manager" != "z" ]
then
 echo ""
fi
echo "----- cleanup after writing ------------------------------------------"
sync
echo "100
# buffered data : 0 kB -- watching -- rate : 0 -- eta : n.a." >> "$tailfile"
sleep 5.5
ps -A|grep "^ *$pid0"
if [ $? -eq 0 ]
then
 kill "$pid0"
fi
if [ "$manager" == "z" ]
then
 ps -A|grep "^ *$pid1"
 if [ $? -eq 0 ]
 then
  kill "$pid1"
 fi
fi
rm  "$tailfile"
sleep 2
partprobe
sleep 4
umount "$target"*
echo -en "$resetvid"
}
########################################################################
########################################################################
#
# main program
#
########################################################################
########################################################################

read_pff "$1"

if [ "$target" != "" ]
then
 echo "Trying to unmount partitions if mounted on the target device"
 umount "$target"*
 df | grep "$target"
 if [ $? -eq 0 ]
 then
  echo "dus-wipe error: could not unmount a partition on the target device"
  exit
 fi
 echo "-------------------------------------------------------------------------------"
 # do it
 echo -e "$inversvid $action $resetvid"
 if [ "$action" == "wipe-1" ]
 then
  d_wipe_1
 elif [ "$action" == "wipe-whole-device" ]
 then
  d_wipe_whole_device
 fi
 part_info "$target"
fi
