#!/bin/bash
# License: GPL 
# Author: Steven Shiau <steven _at_ stevenshiau org>
# Description: Program to inspect the checksum in the image and the files in the block device

#
DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
. /etc/drbl/drbl-ocs.conf
. $DRBL_SCRIPT_PATH/sbin/ocs-functions

# Load the config in ocs-live.conf. This is specially for Clonezilla live. It will overwrite some settings of /etc/drbl/drbl-ocs.conf, such as $DIA...
[ -e "/etc/ocs/ocs-live.conf" ] && . /etc/ocs/ocs-live.conf

# Settings
ocs_parallel_mode="no"

#
USAGE() {
    echo "$ocs - To inspect the checksum in the image and the files in the block device"
    echo "Usage:"
    echo "To run $ocs:"
    echo "$ocs [OPTION] IMAGE DEVICE"
    echo "IMAGE is the image name, e.g., Debian-Jessie, which must be previously saved by the option -gmf"
    echo "DEVICE name can be with or without /dev/, e.g., /dev/sda or sda."
    echo "It can be a disk name or partition name."
    echo
    echo "OPTION:"
    echo "-p, --parallel  Run the checksum inspection in parallel. The inspection for all partitions in a disk will be run in parallel. Maybe it's not a good idea if too many partitions and it might cause too many I/Os then less efficiency."
    echo
    echo "Ex:"
    echo "To inspect the checksum in the image \"Debian-Jessie\" with the external disk \"sdc\", run"
    echo "   $ocs Debian-Jessie sdc"
    echo
} # end of USAGE
#

####################
### Main program ###
####################

ocs_file="$0"
ocs=`basename $ocs_file`
#
while [ $# -gt 0 ]; do
 case "$1" in
   -p|--parallel) ocs_parallel_mode="yes"; shift;;
   -*)     echo "${0}: ${1}: invalid option" >&2
           USAGE >& 2
           exit 2 ;;
   *)      break ;;
 esac
done

ocs_chk_img_name="$1"
shift
ocs_chk_dev="$(strip_leading_dev $*)"

#
check_if_root

# Create log dir
mkdir -p $ocs_log_dir

ask_and_load_lang_set

#
# imagedir is a variable which ask_user related function need
imagedir="$ocsroot"
[ -z "$ocs_chk_img_name" ] && ocs_chk_img_name="ask_user"
[ -z "$ocs_chk_dev" ] && ocs_chk_dev="ask_user"
if [ "$ocs_chk_img_name" = "ask_user" ]; then
  get_target_dir_name_when_checking_img_checksum # output: target_dir
  ocs_chk_img_name="$target_dir"
fi
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "$msg_the_image_to_be_cheked: $ocs_chk_img_name"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL

if [ "$ocs_chk_dev" = "ask_user" ]; then
  # To get $target_hd
  get_target_hd_name_from_local_machine "$msg_local_source_disk_for_checksum_inspect \n$msg_linux_disk_naming $msg_press_space_to_mark_selection"
  ocs_chk_dev="$(select_VG "$target_hd")"
elif [ "$ocs_chk_dev" = "all" ]; then
  get_not_busy_disks_or_parts harddisk "" ""  # we will get dev_list
  ocs_chk_dev="$dev_list"
fi
# check if the device exists
ANS_TMP=`mktemp /tmp/ocs_chkdev.XXXXXX`
trap "[ -f "$ANS_TMP" ] && rm -f $ANS_TMP" HUP INT QUIT TERM EXIT
check_if_input_device_exist $ANS_TMP $ocs_chk_dev 
ocs_chk_dev="$(cat $ANS_TMP | tr -d \")"
[ -f "$ANS_TMP" ] && rm -f $ANS_TMP

#
if [ -z "$ocs_chk_img_name" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "No image name is assigned!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_program_stop!"
  exit 1
fi
if [ ! -d "$ocsroot/$ocs_chk_img_name" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "Image $ocs_chk_img_name not found in $ocsroot!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_program_stop!"
  exit 1
fi
if [ -z "$ocs_chk_dev" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "No destination device is assigned!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_program_stop!"
  exit 1
fi
# Check if the block device exists
for idev in $ocs_chk_dev; do
  if [ ! -b "/dev/$idev" ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "This block device was not found: $idev"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo "$msg_program_stop!"
    exit 1
  fi
done

#
case "$ocs_parallel_mode" in
  yes) go_bg="&";;
  *)   go_bg="";;
esac
  

#
src_disk="$(cat $ocsroot/$ocs_chk_img_name/disk)"

#
target_disks=""
target_parts=""
# Check if ocs_chk_dev a disk or partition
for idev in $ocs_chk_dev; do
  if is_whole_disk $idev; then
    # Disk
    # Get all the partitions
    BACKUP_DEVS=""
    echo "Searching for data partition(s)..." | tee -a $ocs_log_dir/${ocs}-${idev}.log
    get_known_partition_proc_format $idev data
    target_parts="$BACKUP_DEVS"
    if [ "$idev" != "$src_disk" ]; then
      create-ocs-tmp-img -t /tmp $ocs_chk_img_name ${ocs_chk_img_name}_cnvt_${idev} $src_disk ${idev} | tee -a $ocs_log_dir/${ocs}-${idev}.log
      target_dir_fullpath="/tmp/${ocs_chk_img_name}_cnvt_${idev}"
    else
      target_dir_fullpath="$ocsroot/$ocs_chk_img_name"
    fi
    for ipartition in $target_parts; do
      echo $msg_delimiter_star_line | tee -a $ocs_log_dir/${ocs}-${idev}.log
      inspect_cmd="inspect_chksum_for_files_in_dev /dev/$ipartition "$target_dir_fullpath" |  tee -a $ocs_log_dir/${ocs}-${idev}.log $go_bg"
      eval $inspect_cmd
      echo $msg_delimiter_star_line | tee -a $ocs_log_dir/${ocs}-${idev}.log
    done
  else
    # Partition
    thd_tmp="$(get_diskname $idev)"
    if [ "$thd_tmp" != "$src_disk" ]; then
      create-ocs-tmp-img -t /tmp $ocs_chk_img_name ${ocs_chk_img_name}_cnvt_${thd_tmp} $src_disk ${thd_tmp} | tee -a $ocs_log_dir/${ocs}-${idev}.log
      target_dir_fullpath="/tmp/${ocs_chk_img_name}_cnvt_${thd_tmp}"
    else
      target_dir_fullpath="$ocsroot/$ocs_chk_img_name"
    fi
    echo $msg_delimiter_star_line | tee -a $ocs_log_dir/${ocs}-${idev}.log
    inspect_chksum_for_files_in_dev /dev/$idev "$target_dir_fullpath" | tee -a $ocs_log_dir/${ocs}-${idev}.log &
    echo $msg_delimiter_star_line | tee -a $ocs_log_dir/${ocs}-${idev}.log
  fi
done

# wait for all processes to finish before exit
wait 

# Clean the temp dir.
for i in $target_disks; do
  if [ -e "/tmp/${image_name}_cnvt_${i}/converted-not-portable" ]; then
    rm -f /tmp/${image_name}_cnvt_${i}/*
    rmdir /tmp/${image_name}_cnvt_${i}
  fi
done
my_ocs_exit 1
