#!/bin/sh

# Copyright (c) 2010, The ULBSD Project
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Id: ulbsd-clone 84 2022-07-15 13:23:43Z sv $

mnt_dir="/mnt"
label="uroot"
DIALOG="cdialog"
shutdown="shutdown -p now"
reboot="shutdown -r now"
lang=${1}

console="`tty | awk -F '/dev/ttyv' '{print $2}'`"

case "${console}" in
    0|1|2|3|4|5|6|7|8)
        console="`expr -e 0${console} + 1`"
        vidcontrol -s${console}
    ;;
esac

# ---------- Select language ----------

lang="`echo $LANG | awk -F '.' '{print $1}'`"

if [ "${lang}" == "ru_RU" ]
then
    . ${0}-msg-ru
else
    . ${0}-msg-en
fi

# ---------- Main menu ----------

dialog="${DIALOG} --stdout --no-collapse --no-cancel --backtitle '${backtitle}' --menu '${main_menu_msg}' 11 44 4 'Clone' '${main_menu_item_clone}' 'Reboot' '${main_menu_item_reboot}' 'Shutdown' '${main_menu_item_shutdown}' 'Exit' '${main_menu_item_exit}'"
input=$(eval $dialog)

case "$?" in
    0)
    ;;
    *)
    $0 $lang && exit
    ;;
esac

if [ "${input}" == "Reboot" ]
then
    ${reboot} && exit
fi

if [ "${input}" == "Shutdown" ]
then
    ${shutdown} && exit
fi

if [ "${input}" == "Exit" ]
then
    exit
fi

if [ "${input}" == "Clone" ]
then

# ---------- Select destination disk ----------

    avail_disks="`sysctl -n kern.disks | sed -E 's/[[:<:]](cd|ar)[0-9]+//g'`"
    avail_disks="`echo "${avail_disks}" | xargs`"
    avail_disks_info=""
    list_disks=""
    count_disks="0"

    if [ ! "${avail_disks}" ]
    then
        dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --msgbox '${disk_no_avail_msgbox_msg}' 5 40"
        eval $dialog
        $0 $lang && exit
    fi

    for cur_disk in ${avail_disks}
    do
        count_disks="`expr -e ${count_disks} + 1`"
        disk_size="`diskinfo ${cur_disk} | awk -F ' ' '{print $3}'`"
        disk_size="`expr -e 0${disk_size} / 1024 / 1024 / 1024`"
        list_disks="${list_disks} '${cur_disk}' '${disk_size}GB'"
        cur_disk_sn="`camcontrol identify ${cur_disk} 2>&1 | grep 'serial number' | tr -d 'serial number'`"
        if [ ! "${cur_disk_sn}" ]
        then
            cur_disk_sn="`camcontrol inquiry ${cur_disk} -S`"
            if [ ! "${cur_disk_sn}" ]
            then
                cur_disk_sn='UNKNOWN'
            fi
        fi
        avail_disks_info="${avail_disks_info}${cur_disk}: `camcontrol devlist | grep -w ${cur_disk} | grep -o '<.*>'` SN:${cur_disk_sn}\n"
    done

    break_cycle="0"
    while [ "$break_cycle" == "0" ]
    do
        dlg_height="`expr -e ${count_disks} + 7`"
        dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --cancel-label '${cancel_label}' --help-button --help-label '${disk_menu_help_label}' --menu '${disk_menu_msg}' ${dlg_height} 48 ${count_disks} ${list_disks}"
        input=$(eval $dialog)

        case "$?" in
            2)
                avail_disks_info="`echo ${avail_disks_info} | tr '\t' ' '`"
                dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --msgbox '${disk_info_msgbox_msg}\n\n${avail_disks_info}' $dlg_height 76"
                eval $dialog
            ;;
            0)
                break_cycle="1"
            ;;
            *)
            $0 $lang && exit
            ;;
        esac
    done

    work_disk="${input}"

# ---------- Enter swap size ----------

    swap_size="`sysctl hw.physmem | awk -F ':' '{print $2}'`"
    swap_size_min="`expr -e ${swap_size} / 1024 / 1024`"
    swap_size="`expr -e ${swap_size_min} + ${swap_size_min}`"
    swap_size_max="`expr -e ${swap_size} + ${swap_size} + ${swap_size}`"
    swap_size_min="0"

    break_cycle="0"
    while [ "$break_cycle" == "0" ]
    do

        dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --cancel-label '${cancel_label}' --inputbox '${swap_inputbox_msg}' 12 52 '${swap_size}'"
        input=$(eval $dialog)

        case "$?" in
            0)
                input="`echo ${input} | xargs`"
                check="`echo ${input} | tr -d '[0-9]'`"
                if [ ! "${check}" ]
                then
                    input="`expr -e 0${input} + 0`"
                fi
                if [ ! "${check}" ] && [ "${input}" -le ${swap_size_max} ] && [ "${input}" -ge ${swap_size_min} ]
                then
                    swap_size="${input}"
                    break_cycle="1"
                else
                    dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --msgbox '${incorrect_msgbox_msg}' 5 32"
                    eval $dialog;
                fi
            ;;
            *)
            $0 $lang && exit
            ;;
        esac
    done

# ---------- Select file system ----------

    avail_file_systems="UFS ZFS"
    dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --cancel-label '${cancel_label}' --menu '${fs_menu_msg}' 9 59 2 'UFS' '${fs_menu_item_ufs}' 'ZFS' '${fs_menu_item_zfs}'"
    input=$(eval $dialog)

    case "$?" in
        0)
        ;;
        *)
        $0 $lang && exit
        ;;
    esac

    file_system="${input}"

# ---------- Enter root partition label and ZFS pool name ----------

    break_cycle="0"
    while [ "$break_cycle" == "0" ]
    do

        if [ "$file_system" == "UFS" ]
        then
            label_inputbox_msg="$label_ufs_inputbox_msg"
        else
            label_inputbox_msg="$label_zfs_inputbox_msg"
            label="zroot"
        fi
        dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --cancel-label '${cancel_label}' --inputbox '${label_inputbox_msg}' 11 44 '${label}'"
        input=$(eval $dialog)

        case "$?" in
            0)
                input="`echo ${input} | xargs`"
                check="`echo ${input} | tr -d '[a-zA-Z0-9_]'`"
                if [ ! "${check}" ] && [ "${input}" ] && [ "${input}" != "root" ] && [ "${input}" != "boot" ] &&  [ "${input}" != "efi" ] && [ "${input}" != "swap" ]
                then
                    label="${input}"
                    break_cycle="1"
                else
                    dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --msgbox '${incorrect_msgbox_msg}' 5 32"
                    eval $dialog
                fi
            ;;
            *)
            $0 $lang && exit
            ;;
        esac
    done

# ---------- Start installation ----------

    dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --yes-label '${yes_label}' --no-label '${no_label}' --yesno '${final_yesno_msg_part1}${work_disk}${final_yesno_msg_part2}' 6 52"
    eval $dialog

    case "$?" in
        0)
        ;;
        *)
        $0 $lang && exit
        ;;
    esac

    install_script="${0}-ufs"

    if [ "${file_system}" == "ZFS" ]
    then
        install_script="${0}-zfs"
    fi

    dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --prgbox '${clone_prgbox_msg}' '${install_script} ${work_disk} ${swap_size} ${mnt_dir} ${label} 2>&1' 24 74"
    eval $dialog

    dialog="${DIALOG} --stdout --no-collapse --backtitle '${backtitle}' --msgbox '${alldone_msgbox_msg}' 7 48"
    eval $dialog
    $0 $lang && exit
fi
