#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL
# Description: This program will put Debian Live minimal + DRBL/Clonezilla program into a bootable iso file.

# Load DRBL setting and functions
if [ ! -f "/opt/drbl/sbin/drbl-conf-functions" ]; then
  echo "Unable to find /opt/drbl/sbin/drbl-conf-functions! Program terminated!" 
  exit 1
fi
. /opt/drbl/sbin/drbl-conf-functions

# Load some necessary setting from drbl-ocs.conf
. /opt/drbl/conf/drbl-ocs.conf

# Load basic functions of ocs
. /opt/drbl/sbin/ocs-functions

# other default settings
# If insert_mode=prog_only, only copy DRBL/Clonezilla programs only, no ocs images.
insert_mode="prog_and_img"
img_size_sum=0
# Default to output the result to iso file, another vaule is cdwriter.
output_mode="file"

#
prog="$(basename $0)"

# functions
USAGE() {
    echo "Usage:"
    echo "To put clonezilla image into live CD:"
    echo "$prog [OPTION] CLONEZILLA_IMAGE_NAME"
    echo "OPTION:"
    language_help_prompt_by_idx_no
    echo "-b, --bg-mode  [text|graphic]  Assign the back ground of boot menu. Default is graphic"
    echo "-p, --image-path   Assign the clonezilla image path where CLONEZILLA_IMAGE_NAME exists. Default = $ocsroot"
    echo "-s, --skip-image   Do not include any clonezilla image. The is used to created a live CD with DRBL/Clonezilla programs only."
    echo "-f, --on-the-fly DEV  Write the output to CD/DVD writer DEV (such as /dev/hdc) instead of creating an ISO file."
    echo "$prog will download a template Debian live CD for clonezilla iso file from $DEBIAN_ISO_URL if ncecessary. You can also download it by yourself, and put it in the working directory when you run $prog. If you want to create that template iso file in Debian Etch, run $DRBL_SCRIPT_PATH/sbin/create-debian-live."
    echo "NOTE! Due to the limitation in mkisofs, this program does not work in clonezilla image file larger than $FILE_LIMIT MB."
    echo "Ex:"
    echo "To put clonezilla image sarge-ocs (located in /home/partimag in clonezilla server) to Live CD, you can run:"
    echo "  $prog sarge-ocs"
    echo "To put more images, just append them, such as:"
    echo "  $prog sarge-ocs etch-ocs"
    echo "To create a Live CD with DRBL/Clonezilla programs, which can be used to save image:"
    echo "  $prog -s"
    echo "To put clonezilla image sarge-ocs, etch-ocs to to Live CD, and write it to cd writer /dev/hdc, you can run:"
    echo "  $prog -f /dev/hdc sarge-ocs etch-ocs"
}
#
check_file_size_in_ocs_image() {
  local img_path="$1"
  local size_t
  for ifile in $img_path/*; do
    size_t="$(du -Lms $ifile | awk -F" " '{print $1}')"
    if [ "$size_t" -gt "$FILE_LIMIT" ]; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
      echo "$ifile size ($size_t MB) is too large! $msg_mkisofs_unable_process_that"
      echo "$msg_unable_to_create_clonezilla_img_iso"
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
      exit 1
    fi
  done
}

#
check_if_root

# Parse command-line options
while [ $# -gt 0 ]; do
  case "$1" in
    -l|--language)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              specified_lang="$1"
              shift
            fi
	    [ -z "$specified_lang" ] && USAGE && exit 1
            ;;
    -b|--bg-mode)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              bg_mode="$1"
              shift
            fi
	    [ -z "$bg_mode" ] && USAGE && exit 1
            ;;
    -p|--image-path)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              image_path="$1"
              shift
            fi
	    [ -z "$image_path" ] && USAGE && exit 1
            ;;
    -s|--skip-image)
            insert_mode="prog_only"
            shift ;;
    -f|--on-the-fly)
            shift
	    output_mode="cdwriter"
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              output_dev="$1"
              shift
            fi
	    [ -z "$output_dev" ] && USAGE && exit 1
            ;;
    -*)     echo "${0}: ${1}: invalid option" >&2
            USAGE >& 2
            exit 2 ;;
    *)      break ;;
  esac
done
ocs_image="$*"
# strip the / to avoid problem
ocs_image="$(echo $ocs_image | sed -e "s|/||g")"
      
[ -z "$ocs_image" -a "$insert_mode" = "prog_and_img" ] && USAGE && exit 1
[ -z "$image_path" ] && image_path=$ocsroot
[ -z "$bg_mode" ] && bg_mode="$BG_MODE_DEF"

if ! type mkisofs 2>/dev/null; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "mkisofs not found!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_program_stop"
  exit 1
fi

if [ "$output_mode" = "cdwriter" -a type cdrecord &>/dev/null ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "Program cdrecord is not aviailable! You have to install it."
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_program_stop"
  exit 1
fi
#
ask_and_load_lang_set $specified_lang

iso_file="$(basename $DEBIAN_ISO_URL)"
if [ ! -f "$iso_file" ]; then
  echo "We need Debian live CD for Clonnezilla to create clonezilla cd."
  echo "Downloadling the iso file from $DEBIAN_ISO_URL..."
  wget $DEBIAN_ISO_URL
  get_iso_rc=$?
  # validate it
  if [ "$get_iso_rc" -eq 0 ]; then
    echo -n "Validating $DEBIAN_ISO... "
    md5_tmp="$(mktemp -d /tmp/isomd5.XXXXX)"
    #  wget http://opensource.nchc.org.tw/drbl-core/iso/MD5SUMS
    echo -n "Downloading $md5_file_url... "
    wget $wget_opt -P "$md5_tmp" $md5_file_url
    if ! grep -w "$DEBIAN_ISO" $md5_tmp/MD5SUMS | md5sum -c; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
      echo "$DEBIAN_ISO is broken! Something went wrong! Try to remove $DEBIAN_ISO and run this program again."
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
      echo "$msg_program_stop"
      exit 1
    fi
  else
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "Unable to download $DEBIAN_ISO_URL!"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo "$msg_program_stop"
    exit 1
  fi
fi

if [ "$insert_mode" = "prog_and_img" ]; then
  echo "Creating clonezilla ISO with image(s) $ocs_image from $image_path..."
  # here we put ocs-live-restore as ocs-live inside live cd, and it will be shown as /live_media/ocs-live when using in running live CD.
  # use the 1st image name as iso filename
  iso_label_tag="$(echo $ocs_image | awk -F" " '{print $1}')"
  # mkisofs only allow 32 characters for volume ID
  iso_label_tag="${iso_label_tag:0:31}"
  ocs_imgs_with_abs_path=""
  for im in $ocs_image; do
    if [ ! -d "$image_path/$im" ]; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
      echo "$image_path/$im $msg_NOT_found!"
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
      echo "$msg_program_stop"
      exit 1
    fi
    # we will put all the images in $ocsroot/ inside ISO file.
    ocs_imgs_with_abs_path="$ocs_imgs_with_abs_path $ocsroot/$im=$image_path/$im"
    convert_ocs_format_from_1.5_to_2.0_or_newer $image_path/$im/
    check_file_size_in_ocs_image $image_path/$im/
    img_size="$(du -ms $image_path/$im/ | awk -F" " '{print $1}')" # unit: MB
    img_size_sum="$((img_size_sum+img_size))"
  done
else
  echo "Creating clonezilla Live CD ISO file..."
  # here we put ocs-live-save-for-ro as ocs-live inside live cd, and it will be shown as /live_media/ocs-live when using in running live CD.
  iso_label_tag="live-`date +%Y%m%d`"
fi

target_iso="clonezilla-${iso_label_tag}.iso"

DEBIAN_ISO_TMP="$(mktemp -d /tmp/ocs-iso.XXXXXX)"
trap "[ -d "$DEBIAN_ISO_TMP" ] && umount $DEBIAN_ISO_TMP &>/dev/null && rm -rf $DEBIAN_ISO_TMP" HUP INT QUIT TERM EXIT
ISOLNX_TMP="$(mktemp -d /tmp/isolnx.XXXXXX)"
WD_TMP="$(mktemp -d /tmp/iso_wd.XXXXXX)"
mount -o loop $DEBIAN_ISO $DEBIAN_ISO_TMP
echo -n "Creating DRBL/Clonezilla program tarball from $DRBL_SCRIPT_PATH... "
create_live_media_opt_drbl_tarball $WD_TMP
echo "done!"
# 
if [ ! -e "$uni_font_file" ]; then
  echo "Download unifont.bgf from $uni_font_url..."
  wget $wget_opt $uni_font_url
  rc=$?
  if [ "$rc" -gt 0 ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "Unable to download unifont.bgf from $uni_font_url!"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo "$msg_program_stop"
    exit 1
  fi
fi

#
template_iso_size="$(du -Lms $DEBIAN_ISO | awk -F" " '{print $1}')"
drbl_prog_size="$(du -Lms $WD_TMP/opt_drbl.tgz | awk -F" " '{print $1}')" 
uni_font_size="$(du -Lms $uni_font_file | awk -F" " '{print $1}')"
target_iso_size="$((template_iso_size+drbl_prog_size+img_size_sum+uni_font_size))"

echo "Estimated target ISO file \"$target_iso\" size: $target_iso_size MB"
if [ "$target_iso_size" -gt "$FILE_LIMIT" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "$msg_ocs_iso_too_big_for_DVD"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_are_u_sure_u_want_to_continue"
  echo -n "[y/N] "
  read cont_ans
  case "$cont_ans" in
    y|Y|[yY][eE][sS])
       echo $msg_ok_let_do_it
       ;;
    *)
       echo "Abort!"
       exit 2
  esac
elif [ "$target_iso_size" -gt "$CD_FILE_LIMIT" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "$msg_ocs_iso_too_big_for_CD"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "$msg_are_u_sure_u_want_to_continue"
  echo -n "[y/N] "
  read cont_ans
  case "$cont_ans" in
    y|Y|[yY][eE][sS])
       echo $msg_ok_let_do_it
       ;;
    *)
       echo "Abort!"
       exit 2
  esac
fi

#
mkdir -p $WD_TMP/etc/ocs
if [ "$insert_mode" = "prog_and_img" ]; then
  cat <<-OCS_CONF > $WD_TMP/etc/ocs/ocs-live.conf
ocs_live_run="$DRBL_SCRIPT_PATH/sbin/ocs-live-restore" 
DIA="whiptail"
OCS_CONF
else
  cat <<-OCS_CONF > $WD_TMP/etc/ocs/ocs-live.conf
ocs_live_run="$DRBL_SCRIPT_PATH/sbin/ocs-live-save-for-ro"
DIA="whiptail"
OCS_CONF
fi

# Create the iso image file
# isolinux should be rw, so we have to copy it, and exclude the one in iso image.
rsync -a --exclude f*.txt --exclude boot.cat --exclude isolinux.txt --exclude splash.rle $DEBIAN_ISO_TMP/isolinux $ISOLNX_TMP/
# put the unifont
cp -a $uni_font_file $WD_TMP
# we have to overwrite isolinux.bin since vesamenu.c32 should be same version with that.
etherboot_zlilo="$($query_pkglist_cmd drbl-etherboot | grep -E "eb-.*-etherboot-pci.zlilo$")"
cp -f $isolinux_file $pxelinux_simple_vesamenu $pxelinux_simple_menu $pxelinux_bg_img $ocs_logo_img_syslinux $pxelinux_chain_file $ISOLNX_TMP/isolinux/
if [ -n "$etherboot_zlilo" ]; then
  # we have to force it name as etherboot.zdsk, since isolinux only uses the "plain" ISO 9660 filenames, i.e. it does not support Rock Ridge or Joliet filenames.
  # ref: http://syslinux.zytor.com/archives/2006-October/007440.html
  # "-" will be regards as "_" if you want to use "-" for isolinux.
  # In syslinux on vfat, etherboot.zlilo is too long, make it ever shorter as eb.zli
  cp -f $etherboot_zlilo $ISOLNX_TMP/isolinux/eb.zli
fi
ocs-live-boot-menu -l $lang_answer -f $VGA_MODE -b $bg_mode -k $kernel_file -i $initrd_file isolinux $ISOLNX_TMP/isolinux/

mkisofs \
 -A "Clonezilla live CD" \
 -V "$iso_label_tag" \
 -publisher "DRBL/Clonezilla http://drbl.sf.net http://clonezilla.sf.net" \
 -r -J -l \
 -b isolinux/isolinux.bin -c isolinux/boot.cat \
 -no-emul-boot -boot-load-size 4 -boot-info-table \
 -x $DEBIAN_ISO_TMP/isolinux \
 -x $DEBIAN_ISO_TMP/md5sum.txt \
 -graft-points $DEBIAN_ISO_TMP \
  /pkg/opt_drbl.tgz=$WD_TMP/opt_drbl.tgz \
  /isolinux/=$ISOLNX_TMP/isolinux \
  /etc/ocs/=$WD_TMP/etc/ocs/ \
  /pkg/unifont.bgf=$WD_TMP/unifont.bgf \
  /ocs.d/=$DRBL_SCRIPT_PATH/setup/files/ocs/ocs.d \
  /COPYING=$DRBL_SCRIPT_PATH/doc/COPYING \
  $ocs_imgs_with_abs_path \
  | \
  (
   case "$output_mode" in
    "cdwriter")
       cdrecord dev=$output_dev -data -eject -v -
       ;;
    *)
       # use /dev/stdout as the bridge
       cat - > $target_iso
       ;;
   esac
  )

rc=$?
if [ "$rc" -gt 0 ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "Something went wrong!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  umount $DEBIAN_ISO_TMP &>/dev/null
  [ ! -z "$DEBIAN_ISO_TMP" ] && rm -rf $DEBIAN_ISO_TMP
  [ ! -z "$ISOLNX_TMP" ] && rm -rf $ISOLNX_TMP
  [ -f "$target_iso" ] && rm -fv $target_iso
  echo "$msg_program_stop"
  exit 1
fi

# unmount all iso file
umount $DEBIAN_ISO_TMP &>/dev/null

# Clean the tmp working directory
echo "Cleaning tmp dirs..."
[ ! -z "$DEBIAN_ISO_TMP" ] && rm -rf $DEBIAN_ISO_TMP
[ ! -z "$ISOLNX_TMP" ] && rm -rf $ISOLNX_TMP
[ ! -z "$WD_TMP" ] && rm -rf $WD_TMP

# 
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "$msg_burn_clonezilla_img_iso: $target_iso"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
