#!/bin/bash
# License: GPL 
# Author: Steven Shiau <steven _at_ nchc org tw>
# Description: Program to check the Clonezilla image integrity
# (1) Check the partition table files (GPT included)
# (2) Check the MBR/EFI boot loader
# (3) Check the partition image using partclone.chkimg

#
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
# By default we do not check the image saved by dd.
dd_checking_method="no-check"
chk_img_restoreable=""
verbose="no"

#
USAGE() {
    echo "$ocs - To convert the image of Clonezilla from existing compression format to another one"
    echo "Usage:"
    echo "To run $ocs:"
    echo "$ocs [OPTION] SRC_IMAGE_NAME DEST_IMAGE_NAME"
    echo "Options:"
    echo "-b, --batch-mode   Run image checking in batch mode"
    echo "-or, --ocsroot DIR Specify DIR (absolute path) as directory ocsroot (i.e. overwrite the ocsroot assigned in drbl.conf)"
    echo "-sc, --skip-check-restorable  Skip checking the image if restorable after it is converted."
    echo "-v, --verbose            Prints verbose information"
    echo "-z0, --no-compress       Convert to uncompression format"
    echo "-z1, --gzip-compress     Convert to gzip format"
    echo "-z2, --bz2-compress      Convert to bzip2 format"
    echo "-z3, --lzo-compress      Convert to lzop format"
    echo "-z4, --lzma-compress     Convert to lzma format"
    echo "-z5, --xz-compress       Convert to xz format"
    echo "-z6, --lzip-compress     Convert to lzip format"
    echo "-z7, --lrzip-compress    Convert to lrzip format"
    echo "SRC_IMAGE_NAME and DEST_IMAGE_NAME are the image dir name, not absolute path"
    echo "If the destination compression format is not assigned, XZ format will be used"
    echo "If \"ask_user\" is used as SRC_IMAGE_NAME or DEST_IMAGE_NAME, a dialog menu will be shown to allow selection or inputing."
    echo "If no SRC_IMAGE_NAME or DEST_IMAGE_NAME is specified, a dialog menu will be shown."
    echo "Ex:"
    echo "To convert the image \"my-image\", which is located in $ocsroot/my-image to \"my-image-xz\" with xz format, run"
    echo "   $ocs -z5 my-image my-image-pixz"
    echo
} # end of USAGE
#
choose_compress_format() {
  local TMP=`mktemp /tmp/ocs_comp.XXXXXX`
  local z_opt
  trap "[ -f "$TMP" ] && rm -f $TMP" HUP INT QUIT TERM EXIT
  show_z4_or_above_menu_or_not
  $DIA --backtitle "$msg_nchc_free_software_labs" --title  \
  "$msg_nchc_clonezilla" --menu "$msg_choose_one_compression_param_to_save" \
  0 0 0 $DIA_ESC \
  "-z1"      "$msg_ocs_param_z1" \
  "-z2"      "$msg_ocs_param_z2" \
  "-z3"      "$msg_ocs_param_z3($msg_note!!)" \
  $ocs_z4_option_1      $ocs_z4_option_2 \
  $ocs_z5_option_1      $ocs_z5_option_2 \
  $ocs_z6_option_1      $ocs_z6_option_2 \
  $ocs_z7_option_1      $ocs_z7_option_2 \
  "-z0"      "$msg_ocs_param_z0" \
  2> $TMP
  z_opt="$(cat $TMP)"
  case "$z_opt" in
   -z0)  IMG_CLONE_CMP="cat";;
   -z1)  IMG_CLONE_CMP="pigz -c $extra_pigz_opt";;
   -z2)
         if [ "$parallel_bzip2_prog" = "pbzip2" ]; then
           IMG_CLONE_CMP="pbzip2 -c $extra_pbzip2_opt"
         elif [ "$parallel_bzip2_prog" = "lbzip2" ]; then
           IMG_CLONE_CMP="lbzip2 -c $extra_lbzip2_opt"
         fi
         ;;
   -z3)  IMG_CLONE_CMP="lzop -c $extra_lzop_opt";;
   -z4)  IMG_CLONE_CMP="lzma -c $extra_lzma_opt";;
   -z6)  IMG_CLONE_CMP="plzip -c $extra_plzip_opt";;
   -z7)  IMG_CLONE_CMP="lrzip -q - $extra_lrzip_opt";;
     *)  IMG_CLONE_CMP="pixz $extra_pixz_opt";;
  esac
  [ -f "$TMP" ] && rm -f $TMP
} # end of choose_compress_format
#
ask_if_check_converted_img() {
  local TMP=`mktemp /tmp/ocs_chk.XXXXXX`
  local sc_opt
  trap "[ -f "$TMP" ] && rm -f $TMP" HUP INT QUIT TERM EXIT
  # Question about checking the image after conversion
  $DIA --backtitle "$msg_nchc_free_software_labs" --title  \
  "$msg_nchc_clonezilla" --menu "$msg_choose_if_checking_image_restorable" \
  0 0 0 $DIA_ESC \
  " "     "$msg_check_converted_img_restorable" \
  "-sc "  "$msg_skip_check_converted_img_restorable" \
  2> $TMP
  sc_opt="$(cat $TMP)"
  case "$sc_opt" in
   -sc)  chk_img_restoreable="no";;
     *)  chk_img_restoreable="yes";;
  esac
  [ -f "$TMP" ] && rm -f $TMP
} # ask_if_check_converted_img
#
img_covert_to_diff_compression() {
  local file_ fs_ partclone_img_info_tmp file_basename rc img_info
  local used_size block_size used_size_byte rmopt_v
  # First, we find the filesystem 
  file_="$(unalias ls &>/dev/null; ls $target_d/$img_file.*-img* 2>/dev/null | sort | head -n 1)"
  file_basename="$(basename ${file_})"
  if [ -n "${file_}" ]; then
    if [ -n "$(echo $file_basename | grep -Eo -- "-ptcl-img")" ]; then
      # new format, image file is like: sda1.ext4-ptcl-img.gz, sda1.ext4-ptcl-img.gz.aa
      fs_="$(echo $file_basename | sed -e "s/^$img_file\.//g" -e "s/-ptcl-img.*//g")"
    else
      # old format, image file is like: sda2.hfsp-img.aa  sda2.hfsp-img.ab  sda2.hfsp-img.ac
      fs_="$(echo $file_basename | sed -e "s/^$img_file\.//g" -e "s/-img.*//g")"
    fi
  fi
  if [ -z "${fs_}" ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "The file system can not be decided in function img_covert_to_diff_compression!!!"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo "$msg_program_stop!"
    exit 1
  fi
 
  if [ -n "$(echo "$file_basename" | grep -Eo -- "-ptcl-img")" ]; then
    # New format
    if [ -n "$(echo "$file_basename" | grep -Eo -- "-ptcl-img.*.aa")" ]; then
      # New format with image split, e.g. sda1.ext4-ptcl-img.gz.aa
      get_image_cat_zip_cmd ${file_basename}
      # e.g. sda1.ext4-ptcl-img.gz.aa -> sda1.ext4-ptcl-img.gz.*
      img_file_prefix="$(echo ${file_basename} | sed -e "s/\.aa$//").*"
    else
      # New format with image not split, e.g. sda1.ext4-ptcl-img.gz
      get_image_cat_zip_cmd ${file_basename}
      # The file is NOT split, so the file name is just like "sda1.ext4-ptcl-img.gz" only, no "."
      img_file_prefix="${file_basename}"
    fi
  else
    # Old format
    if [ -f "$target_d/$img_file.${fs_}-img.aa" ]; then
      # Old format with image split
      get_image_cat_zip_cmd $target_d/$img_file.${fs_}-img.aa
      # The files are split, like hda1.00, hda1.01, so we have to add "."
      img_file_prefix="$img_file.${fs_}-img.*"
    else
      # Old format with image not split
      get_image_cat_zip_cmd $target_d/$img_file.${fs_}-img
      # The file is NOT split, so the file name is just like "hda1" only, no "."
      img_file_prefix="$img_file.${fs_}-img"
    fi
  fi
  echo $msg_delimiter_star_line

  s_comp_suf="$(ocs-get-comp-suffix $unzip_stdin_cmd)"
  # e.g. sda1.ext4-ptcl-img.gz.aa -> sda1.ext4-ptcl-img.gz.*
  # New format with image not split, e.g. sda1.ext4-ptcl-img.gz
  t_img_file_prefix="$(echo $img_file_prefix | sed -r -e "s|\.\*$||g" -e "s|\.$s_comp_suf||g")"

  # //NOTE// Here we force to use LC_ALL=C for partclone since we need to use get_partclone_image_info to parse the log file to get the rate. Only the keyword in English is supported in get_partclone_image_info.

  split_error="$(mktemp /tmp/split_error.XXXXXX)"
  trap "[ -f "$TMP" ] && rm -f $split_error" HUP INT QUIT TERM EXIT

  compress_prog_opt="$IMG_CLONE_CMP"
  cmd_compress="$compress_prog_opt"
  t_comp_suf="$(ocs-get-comp-suffix $compress_prog_opt)"
  # sda1.ext4-ptcl-img.gz.aa -> /home/partimag/precise-x86-20131112/sda1.ext4-ptcl-img.gz.aa
  # sda5.ext4-ptcl-img.gz.aa -> /home/partimag/precise-x86-20131112/sda5.ext4-ptcl-img.gz.aa
  # e.g. sda1.ext4-ptcl-img.gz.aa -> sda1.ext4-ptcl-img.gz.*

  # Check if source and destination compression program is the same format. If it's the same, we can not go on, otherwise the source file will be overwritten, and it will be broken due to source and destination are the same one.
  if [ "$img_comp_format" = "$t_comp_suf" ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "Source compression format and destination format are the same: $img_comp_format"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo "$msg_program_stop!"
    exit 1
  else
    echo "Now process the image file of partition: $img_file_prefix"
    echo "Converting compression format: $img_comp_format -> $t_comp_suf"
  fi

  img_info="$(mktemp /tmp/ocs_img_info.XXXXXXX)"
  trap "[ -f "$img_info" ] && rm -f $img_info" HUP INT QUIT TERM EXIT
  # Find the used space from partclone.info. Because for pv, -s option only accepts integer
  # So we can not use 1.5 GB for example, instead we have to use 356732*4096=1461174272
  # Partclone v0.2.68 http://partclone.org
  # Unknown mode
  # File system:  EXTFS
  # Device size:    5.0 GB = 1220352 Blocks
  # Space in use:   1.5 GB = 356732 Blocks
  # Free Space:     3.5 GB = 863620 Blocks
  # Block size:   4096 Byte
  ( for img in $target_d/$img_file_prefix; do
      cat $img
    done
  ) | \
  $unzip_stdin_cmd | partclone.info -s - &> $img_info
  used_size="$(LC_ALL=C awk -F":" '/^Space in use/ {print $2}' $img_info | sed -r -e "s/^.*[[:space:]]=//g" -e "s/^[[:space:]]*//g" -e "s/[[:space:]]*Blocks//g")"
  block_size="$(LC_ALL=C awk -F":" '/^Block size/ {print $2}' $img_info | sed -r -e "s/^[[:space:]]*//g" -e "s/Byte$//g")"
  used_size_byte="$(LC_ALL=C echo "scale=0; $used_size * $block_size / 1" | bc -l)"
  if [ -n "$used_size_byte" ]; then
    # Option for pv. The -s option only accepts integer
    used_size_opt="-s $used_size_byte"
  fi
  rm -f $img_info

  #
  ( for img in $target_d/$img_file_prefix; do
      cat $img
    done
  ) | \
  $unzip_stdin_cmd | \
  (
    case "$VOL_LIMIT" in
      [1-9]*)
         # $target_dir_fullpath/$t_img_file_prefix.${t_comp_suf}. is prefix, the last "." is necessary make the output file is like sda1.${fs_pre}-img.aa, sda1.${fs_pre}-img.ab. We do not add -d to make it like sda1.${fs_pre}-img.00, sda1.${fs_pre}-img.01, since it will confuse people that it looks like created by partimage (sda1.${fs_pre}-img.000, sda1.${fs_pre}-img.001)
         pv -pae $used_size_opt | ${cmd_compress} | split -b ${VOL_LIMIT}m - $target_dir_fullpath/$t_img_file_prefix.${t_comp_suf}. 2> $split_error
         ;;
      *)
         pv -pae $used_size_opt | ${cmd_compress} | cat - > $target_dir_fullpath/$t_img_file_prefix.${t_comp_suf} 2> $split_error
         ;;
    esac
  )

  rc="$?"
  if [ "$rc" -eq 0 ]; then
    if [ -L $target_d/$img_file_prefix ]; then
      if [ "$verbose" = "yes" ]; then
        echo "Remove the temp link image file(s) $target_d/$img_file_prefix"
	rmopt_v="-v"
      fi
      rm -f $rmopt_v $target_d/$img_file_prefix
    fi
  fi
  if [ -s "$split_error" ]; then
    cat $split_error
  fi
  rm -f $split_error

  return $rc
} # end of img_covert_to_diff_compression
#
do_partition_or_lv_img_convert() {
  # part is like: /dev/hda1
  local target_d="$1"
  local img_file="$(to_filename $2)"
  local rc hdtmp partition
  image_name_="$(basename $target_d)"
  # get the cat program: cat, zcat or bzcat

  if [ -f "$target_d/$img_file.000" -o \
       -f "$target_d/$img_file.aa" -o \
       -f "$target_d/$img_file" ]; then
    # The saved image is from partimage
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "This partition image was saved by partimage." | tee --append ${OCS_LOGFILE}
    echo "$msg_img_check_not_supported" | tee --append ${OCS_LOGFILE}
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    rc=1
    if [ "$ocs_batch_mode" != "on" ]; then
      echo -n "$msg_press_enter_to_continue..."
      read
    fi
  elif [ -f "$target_d/$img_file.ntfs-img" -o -f "$target_d/$img_file.ntfs-img.aa" ]; then
    # The saved image is from ntfsclone
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "This partition image was saved by ntfsclone." | tee --append ${OCS_LOGFILE}
    echo "$msg_img_check_not_supported" | tee --append ${OCS_LOGFILE}
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    rc=1
    if [ "$ocs_batch_mode" != "on" ]; then
      echo -n "$msg_press_enter_to_continue..."
      read
    fi
  elif is_partclone_image $target_d $img_file; then
    # The saved image is from partclone
    img_covert_to_diff_compression
    rc=$?
    if [ "$rc" -gt 0 -a "$ocs_batch_mode" != "on" ]; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
      echo "This image conversion failed: $img_file" | tee --append ${OCS_LOGFILE}
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
      echo -n "$msg_press_enter_to_continue..."
      read
    else
      [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
      echo "This image conversion is finished: $img_file" | tee --append ${OCS_LOGFILE}
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    fi
  elif [ -f "$target_d/$img_file.dd-img" -o -f "$target_d/$img_file.dd-img.aa" ]; then
    if [ "$dd_checking_method" = "no-check" ]; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
      echo "Image was saved by dd. No need to check the file system integrity: $img_file" | tee --append ${OCS_LOGFILE}
      sleep 1
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
      rc=0
    else
      # For some of the special partition, even it's dd, we do not need to check that. E.g. VMware vmkcore partition. It only need partition ID=fc, we do not care the content of the file system. Ref: http://communities.vmware.com/thread/85788
      # The saved image is from dd
      if [ -e "$target_d/$img_file.dd-img.info" ]; then
        # Get the paritition info, we will get "$partition"
        . $target_d/$img_file.dd-img.info
      fi
      if [ "$partition" = "VMware_vmkcore_partition" ]; then
        echo "VMware vmkcore partition found. No ndeed to check the file system." | tee --append ${OCS_LOGFILE}
        rc=0
      elif [ "$partition" = "BSD_slice" ]; then
        echo "BSD slice found. No ndeed to check the file system." | tee --append ${OCS_LOGFILE}
        rc=0
      elif [ "$partition" = "BSD_swap_partition" ]; then
        echo "BSD swap partition found. No ndeed to check the file system." | tee --append ${OCS_LOGFILE}
        rc=0
      else
        [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
        echo "This partition image was saved by dd." | tee --append ${OCS_LOGFILE}
        echo "$msg_img_check_not_supported"
        [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
        rc=1
        if [ "$ocs_batch_mode" != "on" ]; then
          echo -n "$msg_press_enter_to_continue..."
          read
        fi
      fi
    fi
  fi

  echo $msg_delimiter_star_line
  return $rc
} # end of do_partition_or_lv_img_convert
#
task_logv_convert() {
  # mode is unicast or multicast
  local tgt_parts="$1"  # tgt_parts is like: hda1 hda2 hda5
  local volg is_in_chosen_partition lvm_tmp rc rctlv
  PV_PARSE_CONF="$target_dir_fullpath/lvm_vg_dev.list"
  LOGV_PARSE_CONF="$target_dir_fullpath/lvm_logv.list"
  if [ ! -f "$PV_PARSE_CONF" ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "This LVM PV file NOT found: $PV_PARSE_CONF"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "$msg_press_enter_to_continue..."
    read
  fi
  if [ ! -f "$LOGV_PARSE_CONF" ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "This LVM LV file NOT found: $LOGV_PARSE_CONF"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "$msg_press_enter_to_continue..."
    read
  fi
  
  #
  while read lv fs; do
   # Then we process the real data partition, only those in the chosen partitions
   # Ex:
   # /dev/vg3/lvol0  Linux rev 1.0 ext3 filesystem data (large files)
   # Then lvol0 is belong to VG vg3
   volg="$(echo "$lv" | awk -F"/" '{print $3}')"
   # Find if the LV is in the chosen partition (via VG, we can determine that)
   # EX: tgt_parts: hda1, hda3, hda5...
   #     vg3 /dev/hda3 nPMQQ0-D2yN-YRHL-9fBM-0cUm-vgcw-DCUTri
   is_in_chosen_partition="no"
   for ipt in $tgt_parts; do
     if [ -n "$(grep -E "[[:space:]]+/dev/$ipt[[:space:]]+" $PV_PARSE_CONF | grep -E "\<$volg\>")" ]; then
       # Found the chosen partitions is in the VG
       is_in_chosen_partition="yes"
       break
     fi
   done
   # If not in the chosen partition, skip this, continue with the next.
   [ "$is_in_chosen_partition" = "no" ] && continue
   fn="$(echo $lv | sed -e "s|^/dev/||" -e "s|/|-|g")"
   # create the swap if it's swap partition
   case "$fs" in 
     *[Ss][Ww][Aa][Pp]*)
        echo $msg_delimiter_star_line
        echo "Found the swap partition $lv info:"
	# read LABEL, UUID info for $partition if swappt-$(to_filename ${fn}).info exists
        uuid_opt=""
        label_opt=""
	if [ -e "$target_dir_fullpath/swappt-$(to_filename ${fn}).info" ]; then
	  cat "$target_dir_fullpath/swappt-$(to_filename ${fn}).info"
          echo "Swap partition info file found!"
        else
          [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
          echo "$msg_this_swap_part_info_not_found: ${fn}"
          [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
          echo -n "$msg_press_enter_to_continue..."
          read
        fi
        echo $msg_delimiter_star_line
	# then skip the rest.
        continue;; 
   esac
   [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
   echo "Checking the device LV $fn in the image \"$(basename $target_dir_fullpath)\"..."
   [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
   do_partition_or_lv_img_convert $target_dir_fullpath $fn $lv
   rc=$?
   rctlv="$(($rctlv + $rc))"
  done < $LOGV_PARSE_CONF
  return $rctlv
} # end of task_logv_convert

#
task_convertimage() {
  local target_dir="$1"
  local parts_included target_dir_fullpath
  local ptype rc rct

  #
  target_parts="$(LC_ALL=C cat $ocsroot/$target_dir/parts)"

  # target_hd will be extract from $target_parts, maybe we will have one more
  # find the target hd
  # maybe we will have one more hd (like hda1, hda2, hdb1, hdb3 -> hda, hdb)
  for ipart in $target_parts; do
    thd_tmp="$(get_diskname $ipart)"
    if [ -z "$target_hd" ]; then
      target_hd="$thd_tmp"
    elif [ -z "$(echo $target_hd | grep -Ew "$thd_tmp" 2>/dev/null)" ]; then
      target_hd="$target_hd $thd_tmp"
    fi
  done

  #
  if [ -e "$ocsroot/$target_dir/disk" ]; then
    image_type="disk"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "$msg_a_disk_image_saved_from_hd: $(cat $ocsroot/$target_dir/disk)"
    echo "$msg_the_part_image_to_be_convert: $target_parts"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  elif [ -e "$ocsroot/$target_dir/parts" ]; then
    image_type="partition"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "$msg_a_part_image_saved_from_partitions: $(cat $ocsroot/$target_dir/parts)"
    echo "$msg_the_part_image_to_be_cheked: $target_parts"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  else
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "$msg_broken_image_dir"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  fi

  # Use $target_dir_fullpath as the absolute path, i.e. put leading $ocsroot, since from now on we need the full path dir to access them.
  target_dir_fullpath="$ocsroot/$target_dir"
  check_input_target_image "$target_dir_fullpath"

  screen_not_blank

  # if $create_part (global variable) is no, only some preparations 
  # in create_partition, it won't run sfdisk in fact.
  
  # strip the leading spaces
  target_parts="$(echo $target_parts | sed -e "s/^[[:space:]]*//g")"

  echo $msg_delimiter_star_line
  PV_PARSE_CONF="$target_dir_fullpath/lvm_vg_dev.list"
  do_LVM_restore="no"
  rct=0
  for partition in $target_parts; do
    # hda1 -> hda
    hd_tmp="$(get_diskname $partition)"
    # If we partition is listed in lvm_vg_dev.list, process LVM later. //NOTE// LVM might use Id=83 instead of 8e, so we can not parse it based on Id.
    if [ -e $PV_PARSE_CONF ]; then
      for i in $(sed -e 's!^.*/dev/\([^[:space:]]\{3,\}\)[[:space:]]*.*$!\1!g' $PV_PARSE_CONF); do
        if [ "$partition" = "$(get_master_dev_of_multipath $i)" ]; then
          do_LVM_restore="yes"
          continue
        fi
      done
    elif check_LVM_partition /dev/$partition; then
      do_LVM_restore="yes"
      continue
    fi
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "Converting the image of partition $partition in the image \"$target_dir\"..."
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    do_partition_or_lv_img_convert $target_dir_fullpath $partition
    rc=$?
    rct="$(($rct + $rc))"
  done

  # Check LVM
  if [ "$do_LVM_restore" = "yes" ]; then
    # LVM exists, check PV/VG/LV.
    task_logv_convert "$target_parts"
    rc=$?
    rct="$(($rct + $rc))"
    echo $msg_delimiter_star_line
  fi

  if [ "$rct" -gt 0 -a "$ocs_batch_mode" != "on" ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "$msg_failed_to_convert_the_img_compression: $target_dir" | tee --append ${OCS_LOGFILE}
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "$msg_press_enter_to_continue..."
    read
  else
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "$msg_succeeded_convert_the_img_compression: $target_dir" | tee --append ${OCS_LOGFILE}
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  fi
} # end of task_convertimage

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

ocs_file="$0"
ocs=`basename $ocs_file`
#
while [ $# -gt 0 ]; do
 case "$1" in
   -b|--batch) ocs_batch_mode="on"; shift;;
   -or|--ocsroot)
           # overwrite the ocsroot in drbl.conf
           shift; 
           if [ -z "$(echo $1 |grep ^-.)" ]; then
             # skip the -xx option, in case 
             ocsroot="$1"
             shift;
           fi
           [ -z "$ocsroot" ] && USAGE && exit 1
           ;;
   -sc|--skip-check-restorable)
           # Flag to check if the image is restorable
           chk_img_restoreable="no"
	   shift;;
   -v|--verbose) verbose="yes"; shift;;
   -z0|--no-compress)    IMG_CLONE_CMP="cat"; shift;;
   -z1|--gzip-compress)  IMG_CLONE_CMP="pigz -c $extra_pigz_opt"; shift;;
   -z2|--bz2-compress)
           if [ "$parallel_bzip2_prog" = "pbzip2" ]; then
             IMG_CLONE_CMP="pbzip2 -c $extra_pbzip2_opt"
           elif [ "$parallel_bzip2_prog" = "lbzip2" ]; then
             IMG_CLONE_CMP="lbzip2 -c $extra_lbzip2_opt"
           fi
           shift;;
   -z3|--lzo-compress)   IMG_CLONE_CMP="lzop -c $extra_lzop_opt"; shift;;
   -z4|--lzma-compress)  IMG_CLONE_CMP="lzma -c $extra_lzma_opt"; shift;;
   -z5|--xz-compress)    IMG_CLONE_CMP="pixz $extra_pixz_opt"; shift;;
   -z6|--lzip-compress)  IMG_CLONE_CMP="plzip -c $extra_plzip_opt"; shift;;
   -z7|--lrzip-compress) IMG_CLONE_CMP="lrzip -q - $extra_lrzip_opt"; shift;;
   -*)     echo "${0}: ${1}: invalid option" >&2
           USAGE >& 2
           exit 2 ;;
   *)      break ;;
 esac
done

ocs_src_img_name="$1"
shift
ocs_dest_img_name="$1"

# Fedora Core 1 seems to use dumb for rc1, we have to force it use linux.
# otherwise setterm will complain.
[ -z "$TERM" -o "$TERM" = "dumb" ] && TERM="linux"
echo "Setting the TERM as $TERM"
export TERM="$TERM"

#
check_if_root
ask_and_load_lang_set

# check DIA
check_DIA_set_ESC $DIA
#
[ -z "$VOL_LIMIT" ] && VOL_LIMIT=$VOL_LIMIT_DEFAULT
[ -z "$IMG_CLONE_CMP" ] && IMG_CLONE_CMP="$IMG_CLONE_CMP_def"

# imagedir is a variable which ask_user related function need
imagedir="$ocsroot"
[ -z "$ocs_src_img_name" ] && ocs_src_img_name="ask_user"
[ -z "$ocs_dest_img_name" ] && ocs_dest_img_name="ask_user"

# Prepare the image to be converted
# 1st, check if "$ocs_dest_img_name" exist
if [ "$ocs_src_img_name" = "ask_user" ]; then
  get_target_dir_name_when_converting_img
fi
ocs_src_img_name="$target_dir"
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "$msg_the_image_to_be_convert: $ocs_src_img_name"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL

if [ -z "$IMG_CLONE_CMP" ]; then
  choose_compress_format
fi

append_name="$(ocs-get-comp-suffix $IMG_CLONE_CMP)"

if [ "$ocs_dest_img_name" = "ask_user" ]; then
  get_target_dir_name_when_saving  ${ocs_src_img_name}-${append_name} # get $target_dir
fi
ocs_dest_img_name="$target_dir"

if [ -z "$chk_img_restoreable" ]; then
  ask_if_check_converted_img
fi

#
create-ocs-tmp-img -t $ocsroot -n "$ocs_src_img_name" "$ocs_dest_img_name"

task_convertimage "$ocs_dest_img_name"

#
if [ "$chk_img_restoreable" = "yes" ]; then
  echo $msg_delimiter_star_line
  echo "Checking the converted image..."
  ocs-chkimg -b $ocs_dest_img_name
fi
