#!/bin/bash

# date        sign     comment
# 2018-05-19  sudodus  backup-home created for mkusb persistent live drives
# 2018-05-27  sudodus  renamed to dus-home-backup and called by dus
# 2018-05-28  sudodus  checking for graphical desktop environment and zenity
#                      made possible to backup and restore to a persistent
#                      live's own usbdata partition (by not unmounting early)
# 2018-05-28  sudodus  version 12.3.2
# 2020-09-18  sudodus  p_cal1: removed lame 'width height'
# 2020-09-18  sudodus  version 12.6.2
# 2020-09-25  sudodus  p_zensize: added manual size for zenity font and window
# 2020-09-25  sudodus  version 12.6.4

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

inversvid="\0033[7m"
resetvid="\0033[0m"
redback="\0033[1;37;41m"
greenback="\0033[1;37;42m"

action=
lstitem=
cntcrw=
result=
manager=
fontsave="$HOME/.mkusb/fontsave"  # setting for zenity window size and font
fontchar=auto
declare -i fontsize=0
mfnt=
msiz=

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

function p_zentest {

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

function p_zensize {

fontchar=auto
fontsize=0

hpix=$(xrandr | grep -m1 ' connected'|sed -e 's/x.*//' -e 's/.* //')
#echo "hpix=$hpix"
hsiz=$(xrandr | grep ' connected'|grep -om1 ' [0-9]*mm '|grep -o '[0-9]*')
vsiz=$(xrandr | grep ' connected'|grep -om1 ' [0-9]*mm$'|grep -o '[0-9]*')
#echo "hsiz=$hsiz"
if test -s "$fontsave"
then
 read fontchar < "$fontsave"
 if [ "$fontchar" != "auto" ]
 then
  fontsize="$fontchar"
 fi
fi
if [ "$hpix" == "" ]   || [ "$hsiz" == "" ]  || [ "$vsiz" == "" ] \
|| [ "$hpix" == "0" ]  || [ "$hsiz" == "0" ] || [ "$vsiz" == "0" ] \
|| [ $fontsize -gt 0 ] && [ $fontsize -le 11 ]
then
 mf100=1100
elif [ $fontsize -gt 11 ]
then
 mf100=$((fontsize * 100))
elif [ "$vsiz" -lt "160" ]
then
 mf100=1100
elif [ "$vsiz" -lt "200" ]
then
 mf100=$((19*12*hpix/hsiz))
else
 #psiz=$((100*hsiz/hpix))
 mf100=$((19*16*hpix/hsiz))
fi
mfnt=$((mf100/100))
#echo "mfnt=$mfnt"
msiz=$((mf100/11))
}
########################################################################

function mk_list {

devnam=$(sudo lsblk -dno name|grep -v 'sr0')

jj=0
for ii in $devnam
do
 if test -b "/dev/${ii}5"
 then
#             sudo lsblk -dno label "/dev/${ii}5"
  casperlbl=$(sudo lsblk -dno label "/dev/${ii}5" 2> /dev/null)
  if [ "$casperlbl" == "casper-rw" ] || [ "$casperlbl" == "writable" ]
  then
   if [ "$jj" == "0" ]
   then
    echo "Device      Model            Size     Persistent live OS"
   fi
   model=$(sudo lsblk -dno model "/dev/$ii")
   size=$(sudo lsblk -dno size "/dev/$ii")
   distrolbl=$(sudo lsblk -dno label "/dev/${ii}4" 2> /dev/null)
   lstitem[jj]="/dev/$ii"
   ((jj++))
   lstitem[jj]="$model"
   ((jj++))
   lstitem[jj]="$size"
   ((jj++))
   lstitem[jj]="$distrolbl"
   ((jj++))
   echo "/dev/$ii    $model $size    $distrolbl"
  fi 
 fi
done
#echo "${lstitem[@]}" #############################

#echo "$jj"
cntcrw="$(( $jj / 4 ))"
echo "cntcrw=$cntcrw"
#echo "----- lstitem --------------------------------------"
#echo -e "${lstitem[@]}"
}
########################################################################

function p_cal1 {

if [ "$USER" != "root" ]
then
 sudostr="live system or temporary superuser permissions"
 for i in 1 2 3
 do
  if [ "$i" == "1" ]
  then
   sudo -n echo "$sudostr" 2> /dev/null
  else
   sudo -n echo "$sudostr" > /dev/null 2> /dev/null
  fi
  if [ $? -ne 0 ]
  then
   if [ "$1" == "-z" ]
   then
    zenity --password --title "$action home" \
    --window-icon="/usr/share/icons/hicolor/48x48/apps/mkusb.png" \
    2> /dev/null \
    |sudo -S echo "$sudostr" 2> /dev/null
   else
#   3 attempts to enter password built into standard sudo
    sudo echo "$sudostr" 2> /dev/null
    if [ $? -ne 0 ]
    then
     exit
    fi
   fi
  fi
 done

 if [ $? -ne 0 ]
 then
  echo "${0##*/}: bad sudo password"
  exit
 fi
fi
}
########################################################################

function usage {

echo "$version can backup and restore the /home directory
in a 'casper-rw' or 'writable' partition
of a persistent live drive made by mkusb

Usage:    ${0##*/} -b or -r or -h or -v
Examples: ${0##*/} -b  # backup
          ${0##*/} -r  # restore
          ${0##*/} -h  # this help text
          ${0##*/} -v  # print version and exit
    
          dus-home-backup   # if in PATH, otherwise add directory path
          dus-home-restore  #                 - '' -                   "
}
########################################################################

# main

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

if [ "$1" == "-b" ]
then
 action=backup
elif [ "$1" == "-r" ]
then
 action=restore
elif [ "$1" == "-v" ]
then
 echo "$version"
 exit
elif [ "$1" == "-h" ]
then
 usage
 exit
elif [ "${0##*/}" == "dus-home-backup" ]
then
 action=backup
 echo "backup home"
elif [ "${0##*/}" == "dus-home-restore" ]
then
 action=restore
 echo "restore home"
else
 usage
 exit
fi 

if [ "${TERM:0:5}" == "xterm" ] || [ "$TERM" != "linux" ] || [ "$DISPLAY" != "" ]
then
# which zenity > /dev/null
 p_zentest
 if [ "$?" == "0" ]
 then
  p_cal1 -z
 else
  echo -e "$redback ${0##*/} needs the program package zenity $resetvid"
  read -t 8 -n 1
  exit
 fi
else
 echo -e "$redback ${0##*/} needs a graphical desktop environment $resetvid"
 read -t 8 -n 1
 exit
fi

# select casper-rw partition (if more than one) and mount it

lstcrw=$(mktemp)
mpcrw=$(mktemp -d)
echo "mpcrw=$mpcrw"

mk_list

if [ "$cntcrw" == "0" ]
then
 tmpstr="No 'casper-rw' or 'writable' partition. Please connect an mkusb persistent live drive."
 echo -e "$redback $tmpstr $resetvid"
 zenity --warning --title="No 'casper-rw' or 'writable' partition found." \
--width=$((msiz * 600 / 100)) --height=$((msiz * 200 / 100)) \
--text="<span font='$mfnt'>$tmpstr</span>" \
2> /dev/null
  rm "$lstcrw"
  rmdir "$mpcrw"
 exit
elif [ "$cntcrw" == "1" ]
then
 srcsel="${lstitem[@]}"
else
 srcsel=$(zenity --list --title="Select device with casper-rw/writable partition" \
 --width=$((msiz * 660 / 100)) --height=$((msiz * 250 / 100)) \
 --column="Device" \
 --column="Model" \
 --column="Size" \
 --column="Persistent live OS" \
 "${lstitem[@]}" \
 2> /dev/null)
fi
if [ "$?" -ne "0" ] || [ "$srcsel" == "" ]
then
 echo "No 'casper-rw' or 'writable' partition selected"
 rm "$lstcrw"
 rmdir "$mpcrw"
 exit
fi
#echo "srcsel=$srcsel #################"
sdrive=$(<<< "$srcsel" sed -e 's/ .*//')
srcdev="${sdrive}5"
echo "srcdev=$srcdev"
tmpst4="${sdrive}4"
tmpst4=$(sudo lsblk --list -n -o label "$tmpst4")
echo -e "$inversvid Device: $sdrive  OS: $tmpst4 $resetvid"

# select backup directory/file (a tarball)

if [ "$action" == "backup" ]
then
 bupfile=$(zenity --file-selection --title="Backup to directory/file" \
 --save --filename="$HOME/Documents/mkusb-backup-home.tar.gz" \
 --file-filter="*.gz" --confirm-overwrite \
 --width=$((msiz * 760 / 100)) --height=$((msiz * 600 / 100)) \
 2> /dev/null)
elif [ "$action" == "restore" ]
then
 bupfile=$(zenity --file-selection --title="Restore from directory/file" \
 --filename="$HOME/Documents/mkusb-backup-home.tar.gz" \
 --file-filter="*.gz" \
 --width=$((msiz * 760 / 100)) --height=$((msiz * 600 / 100)) \
 2> /dev/null)
else
 echo "Error, you should not arrive here - 1"
 exit
fi

if [ "$?" -ne "0" ]
then
 echo "No file selected"
 rm "$lstcrw"
 rmdir "$mpcrw"
 exit
fi

echo "bupfile=$bupfile"

# [try to] unmount all partitions and mount casper-rw partition

sudo umount ${sdrive}[345]
echo "mount 'casper-rw' or 'writable' partition"
sudo mount "$srcdev" "$mpcrw"
if [ "$?" -ne "0" ]
then
 echo "Could not mount a 'casper-rw' or 'writable' partition"
  rm "$lstcrw"
  rmdir "$mpcrw"
 exit
fi
sleep 0.5
dfh=$(LANG=C df -h "$mpcrw")
echo "$dfh"
echo "-----------------------------------------------------------------"

# Final checkpoint

tmpstr="
Device:	$sdrive  OS: $tmpst4
File:		$bupfile
Action:	<b>$action</b>
<tt>
$dfh
</tt>
Are you sure that you want to continue?"
zenity --question --title="Final checkpoint" \
--width=$((msiz * 600 / 100)) --height=$((msiz * 300 / 100)) \
--text="<span font='$mfnt'>$tmpstr</span>" \
2> /dev/null
if [ "$?" -ne "0" ]
then
 echo "Quit"
 sudo umount "$mpcrw"
 rm "$lstcrw"
 rmdir "$mpcrw"
 exit
fi

# backup to tarball or restore from tarball

trgver=$(<<< "$tmpst4" grep -o '[0-9][0-9].[0-9][0-9]'|sed 's/\.//' )
echo "target_version: $trgver"

curdir="$(pwd)"
cd "$mpcrw"

# backup #

if [ "$action" == "backup" ]
then
 if test -d upper/home
 then
  cd upper
  message="upper/home in 'casper-rw' or 'writable'"
 elif test -d home
 then
  message="home in 'casper-rw'"
 else
  echo -e "$redback Could not find a home directory in 'casper-rw' $resetvid"
  cd "$curdir"
  sudo umount "$mpcrw"
  rm "$lstcrw"
  rmdir "$mpcrw"
  exit
 fi
 echo -e "$inversvid Found $message $resetvid"
 
 sudo tar -cvzf "$bupfile" home

 if [ "$?" -eq "0" ]
 then
  result=success
  echo -e "'/home' from 'casper-rw'/'writable' $greenback backed up $resetvid to the file
$inversvid $bupfile $resetvid
from the device"
 else
  result=failure
  echo -e "$redback Backup failed :-( $resetvid"
 fi

# restore #

elif [ "$action" == "restore" ]
then
 if test -d "$mpcrw"/upper
 then
  tmpstr=$(ls "$mpcrw"/upper)
  if [ "$tmpstr" != "etc" ]
  then
   tmpstr="Device: $sdrive  OS: $tmpst4

Thís 'casper-rw' or 'writable' partition is not empty.

It may work, but chances are better if you create a new persistent live drive
or remove all directories and files except 'lost+found' from this one.
After that you can restore the home directory."
   zenity --question --title="Restore /home to 'casper-rw'/'writable'" \
   --width=$((msiz * 600 / 100)) --height=$((msiz * 300 / 100)) \
   --text="<span font='$mfnt'>$tmpstr

Do you want to try anyway?</span>" \
   2> /dev/null
   if [ "$?" -ne "0" ]
   then
    echo "Quit"
    cd "$curdir"
    sudo umount "$mpcrw"
    rm "$lstcrw"
    rmdir "$mpcrw"
    exit
   fi
  fi
 fi

 if [ "$trgver" -ge "1604" ]
 then
  sudo mkdir -p upper
  cd upper
  message="home to upper in 'casper-rw'/'writable'"
 else
  message="home to 'casper-rw'/'writable'"
 fi
 echo -e "$inversvid Restoring $message $resetvid"

 sudo tar -xvzf "$bupfile"

 if [ "$?" -eq "0" ]
 then
  result=success
  echo -e "'/home' in 'casper-rw'/'writable' $greenback restored $resetvid from the file
$inversvid $bupfile $resetvid
to the device"
 else
  result=failure
  echo -e "$redback Restore failed :-( $resetvid"
 fi
else
 echo "Error, you should not arrive here - 2"
fi
model=$(sudo lsblk -ndo model "$sdrive")
size=$(sudo lsblk -ndo size "$sdrive")
echo -e " name:  $sdrive 
 model: $model 
 size:  $size 
$inversvid OS:    $tmpst4 $resetvid"

# clean up

cd "$curdir"
echo "Please wait for sync (flushing file system buffers to the device)"
sync
sleep 1
sudo umount "$mpcrw"
sudo umount ${sdrive}1
rm "$lstcrw"
rmdir "$mpcrw"

# Final statements

if [ "$result" == "success" ]
then
 echo -e "$greenback Done :-) $resetvid"
 if [ "$action" == "backup" ]
 then
  zenity --info --title="Backed up :-)" \
  --width=$((msiz * 400 / 100)) --height=$((msiz * 160 / 100)) \
  --text="<span font='$mfnt'>Backed up $message</span>" 2> /dev/null
 else
  zenity --info --title="Restored :-)" \
  --width=$((msiz * 400 / 100)) --height=$((msiz * 160 / 100)) \
  --text="<span font='$mfnt'>Restored $message</span>" 2> /dev/null
 fi
elif [ "$result" == "failure" ]
then
 echo -e "$redback tar failed :-) $resetvid"
 tarball_dir="Is the tarball in the same home directory as you backup/restore?
In that case, select another directory for the tarball!"
 echo "$tarball_dir"
 if [ "$action" == "backup" ]
 then
  zenity --info --title="Failed backup :-)" \
  --width=$((msiz * 600 / 100)) --height=$((msiz * 240 / 100)) \
  --text="<span font='$mfnt'>Failed backup $message
  
$tarball_dir</span>" 2> /dev/null
 else
  zenity --info --title="Failed restore :-)" \
  --width=$((msiz * 600 / 100)) --height=$((msiz * 240 / 100)) \
  --text="<span font='$mfnt'>Failed restore $message
 
 $tarball_dir</span>" 2> /dev/null
 fi
else
 echo "Error, you should not arrive here - 2"
fi
