#!/bin/bash
#
# myliveusb v 4.4 Jan 2020
#
# Sept. 7th 2010; Oct. 3rd Oct 2010; 3rd Nov 2010; 12th Feb 2011 (0.9.5);
# 15th Aug 2011 (0.9.6); 22nd October 2011 (0.9.7); 1st March 2012 (0.9.8);
# 6th Jan 2014 (0.9.9); 1st Feb 2018 re-written to use Grub2 only; Mar 2018 bug fix;
# Oct 2019 change to Yad, re-arrange prompt windows.
# clareoldie@gmail.com
#
# Dec  1 2019 fix labelling, force_grub
# Dec  9 2019 add partitioning info
# Dec 19 2019 call device restructuring after detection
# Dec 30 2019 check for valid disk structure and ext<2,3,4> data partition
# Jan  6 2020 reactivate MBR boot w/o EFI, adjust YAD window widths
# Jan 13 2020 Final fixes for v4.2
# Feb 10 2020 Restructure before getting partition, further adjustments
# Dec 24 2021 Combine input for boot options ,use ext4 instead of ext3
#
# my thanks to all who contributed especially the testers.
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Depends: grub2, grub2-efi, util-linux-ng (lsblk), rsync, dd, yad.
#
# Share link: https://pcloscloud.com/index.php/s/rcsjTz2x8LATcPH

# PATH
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/lib/kde4/libexec/
# Added for translation purposes
# i18n - Internationalisation - Internationalisierung
VERSION=4.4
export TEXTDOMAIN=myliveusb_$VERSION.sh
export TEXTDOMAINDIR="/usr/share/locale"
# variable for the gui
ICON=/usr/share/icons/myliveusb.png
TITLE="MyLiveUSB v4"

set -x                              # In case of failure, run from terminal to see all output.

testrun=false
if [ "$1" = "test" ]
then
    testrun=true
fi

run_as_root() {
#########################################################
### Ensure this is run as root                          #
#########################################################
    this_script_dir="$( cd "$( dirname "$0" )" && pwd )"
    this_script="`basename $0`"
    this_script_path_n_name="${this_script_dir}/${this_script}"
    GUI_SU="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY"
    if [ "$UID" != "0" ]
    then
        yadtxt=" \n                             <b>*** ALERT ***</b>  \n\n"
        yadtxt=$yadtxt"               This script must be run as root \n\n"
        yadtxt=$yadtxt"                 Would you like to continue? \n"
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width 340 \
            --question \
            --button=Yes:0 \
            --button="Quit MyLiveUSB":1 \
            --text="$yadtxt"
        if [ $? -eq 0 ]
        then
            $GUI_SU $this_script_path_n_name
            exit
        else
            exit 0
        fi
    fi
}

set_variables() {
#########################################################
# This list needs to be tidied up somewhat              #
#########################################################
    STANDARD=""                         # For boot option selection by user
    COPY2RAM=""                         # For boot option selection by user
    PERSIST=""                          # For boot option selection by user
    INSTALL=""                          # For boot option selection by user
    DeBug=""                            # For boot option selection by user
    mydevice=""                         # The difference between the 'DRIVES' ... the plugged in device
    DRIVES1=""                          # List of existing drives on a system before the device is plugged in
    DRIVES2=""                          # List of drives after the USB device is plugged in
    Part_Num=""                         # The partition number
    iso_file=""                         # The selected ISO file for the installation
    myaction=""                         # Used to get ADD variable from user
    LABEL="LIVE_PCLinuxOS"              # The default partition label if none exists.
    Mnt_Pnt="/media/MyLiveUSB.$RANDOM"  # The mount point for the target partition (ext4)
    iso_name=""                           # The chosen name for the OS to be installed
    SIZE1=""                            # The free space on the selected partition
    SIZE2=""                            # The space required for the selected OS
    target_part=""                      # The partition selected for the installation
    Type=""                             # We check the FS to ensure it is usable for the install
    isolin2=""                          # Get the actual name of the directory in case it had been renamed
    isolin_full=""                      # The full path and filename of the isolinx or renamed directory
    isolin_path=""                      # The corresponding isolinux directory when not using an ISO
    mypid=$$                            # PID of this script. Allows to kill the script on error.
    sqfs2=""                            # Get the actual name of the file in case it had been renamed
    sqfs_dir=""                         # The path only of the sqfs file
    sqfs_full=""                        # Full path and name of the sqfs file
    sqfs_name=""                        # The name only of the sqfs file ie. livecd
    efi_part=""                         # The EFI partition base name e.g  /dev/sdk1
    efi_Mnt="/media/MyLiveUSB.$RANDOM"  # The mount point for the EFI partition.
    forcegrub=0                         # Must Grub2 be installed or not
    data_partition_valid=true           # Initial setting for later validation
}

usb_install() {
#########################################################
# Actual installation of an OS on the device            #
#########################################################

    get_device
    opt_init_device
    get_device_part
    if [ "$data_partition_valid" != "new" ]
    then
        create_mounts
        mount_part
        write_label
    fi
    get_uuid
    get_job
    get_iso

    res1=$(date +%s)

    if [ "$data_partition_valid" != "new" ]
    then
        if [[ ! -e "$Mnt_Pnt/boot/grub2/grub.cfg" || "$Installed" = "" ]]
        then
            mkdir -p $Mnt_Pnt/boot/grub2
            rm -f $Mnt_Pnt/boot/grub2/grub.cfg
            write_grubcfg
        fi
        force_grub
    fi

# Get Grub2 Boot options from user
    grub2_boot_options
    prepare_for_install

# Copy the OS files to the device
    get_size
    copy_iso_files
    permissions

# Grub preparation and install, then unmount, finish, eject device
    yadtxt="\n                       <b>Creating the OS on the Device</b>\n\n\n"
    yadtxt=$yadtxt"                     Grub Preparation and installation\n\n"
    yadtxt=$yadtxt"                 Cleaning up and unmounting partitions\n"
    (
        echo
        sleep 1
        unmount_part
        eject $mydevice
        echo
        sleep 1
    ) |
        yad --window-icon=$ICON --title="$TITLE" \
            --width=480 --center \
            --progress --progress-text="" --pulsate --no-buttons \
            --text="$yadtxt" \
            --auto-close --auto-kill ;
    wait

# Notify the user of completion

    res2=$(date +%s)
    dt=$(echo "$res2 - $res1" | bc)
    dm=$(echo "$dt/60" | bc)
    ds=$(echo "$dt-60*$dm" | bc)
    runtime=$(printf "Total runtime: %d minutes, %d seconds\n" $dm $ds)

    yadtxt="\n                                                    <b>Successfully Completed</b>\n\n"
    yadtxt=$yadtxt"              <b>Congratulations, the live installation of the OS is complete</b>\n\n"
    yadtxt=$yadtxt"                                                 $runtime\n\n"
    yadtxt=$yadtxt"            The partition is unmounted. Please <b>Remove</b> the USB device now\n\n"
    yadtxt=$yadtxt"           You may then, after a few seconds, plug your device in again for use\n\n\n"
    yadtxt=$yadtxt"                                             Thank you for using PCLinuxOS\n "
    yad --window-icon=$ICON --title "$TITLE" \
        --width=680 --center \
        --info --no-wrap \
        --button=Done:0 \
        --text="$yadtxt"

    exit
}

get_device() {
#########################################################
# Detect USB devices                                    #
#########################################################
    mydevice=""
    mydevmodel=""

    dmesg -c > /dev/null
    sleep 0.1

    while [ "$mydevice" = "" ]
    do
        yadtxt=" \n                                   <b>DEVICE DETECTION</b>\n\n"
        yadtxt=$yadtxt"                              Insert your USB device now\n\n"
        yadtxt=$yadtxt"                  If inserted, please remove it and reinsert it\n\n"
        yadtxt=$yadtxt"                      Click 'Inserted' button after inserting\n\n"
        yadtxt=$yadtxt"                          This will take just a few moments\n\n"
        yad --center --window-icon=$ICON --title="$TITLE" \
            --height=260 --width=480 \
            --buttons-layout=center \
            --button="USB Device Inserted!!Confirm that the USB device has been inserted":0 \
            --button="Quit MyLiveUSB":1 \
            --text="$yadtxt"
        if [ $? = 1 ]; then abort; fi

        sleep 1
        mydevice=$(dmesg | tail -8 | grep -i "Attached SCSI " | \
            grep -i " disk" | grep -i sd[a-z] | sed 's|^.*\[||' | \
            sed 's|\].*||' | sed 's|s|/dev/s|')

# Make further check just in case a USB hub is used
        attached_devices=$(lsblk -l -d -n -o PATH,VENDOR,MODEL,TRAN | \
            grep -e '^/dev/sd' | \
            grep -e 'usb$' | \
            tr -s ' ' | cut -d' ' -f1-3 | tr -t ' ' '|')
        for i1 in $mydevice
        do
            for i2 in $attached_devices
            do
                if [ "$i1" = "${i2:0:8}" ]
                then
                    mydevice=$i1
                    mydevmodel=${i2:9}
                    mydevmodel=${mydevmodel/|/ }
                    break
                fi
            done
        done
    done

    show_structure
}

#########################################################
# Show device strucure, creating new one on demand      #
#########################################################
show_structure() {
    yadtxt="\n                                                         <b>CURRENT DEVICE STRUCTURE</b>\n\n"
    yadtxt=$yadtxt"                                  This is the current device structure of your USB device <b>$mydevice</b>\n\n"
    fdisk -l $mydevice | \
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=820 --height=600 \
            --text "$yadtxt" \
            --buttons-layout=spread \
            --button="Continue!!Continue with the current the structure of the device":0 \
            --button="Restructure!!Wipe the device and create required partitions":1 \
            --button="Quit MyLiveUSB":2 \
            --text-info
    myaction=$?
    case $myaction in
      1)
        create_structure
        return
        ;;
      2)
        abort_msg
        ;;
    esac
}

get_device_part() {
#########################################################
# Detect newly added USB device                         #
#########################################################
    check_device_valid

    target_part=""

    while [ "$target_part" = "" ]
    do
        sleep .2
        yadtxt="\n                        <b>Only suitable <span color='blue'><b>Linux</b></span>"
        yadtxt=$yadtxt" Partitions are listed</b> \n\n"
        yadtxt=$yadtxt"            <span color='blue'><b>Highlight</b></span>"
        yadtxt=$yadtxt" your selection and select <span color='blue'><b>Accept "
        yadtxt=$yadtxt"Choice</b></span> \n\n"
        yadtxt=$yadtxt"                     If there is no partition listed then please check \n"
        yadtxt=$yadtxt"                              the partition types on your media. \n\n"
        target_part=$(lsblk -l -o FSTYPE,NAME,SIZE,LABEL $mydevice | \
                        grep "sd" | grep ext | tr -s ' ' | \
                        cut -d ' ' -f2,3,4 | tr -t ' ' '\n' | \
                        sed 's|sd|\/dev\/sd|g' |
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=560 --height=400 \
            --list  \
            --buttons-layout=center \
            --button="Accept Choice":0 \
            --button="Quit MyLiveUSB":1 \
            --ellipsize=end \
            --text="$yadtxt" \
            --column="Device Partition " \
            --column="Partition Size  " \
            --column="Partition Label ")
        if [ "$?" = "1" ]
        then
            yadtxt="\n                             <b>Exiting the Application</b>\n\n"
            yadtxt=$yadtxt"                         This application will now exit\n\n"
            yadtxt=$yadtxt"             To try again, please restart the application\n"
            yad --center --window-icon=$ICON --title="$TITLE" \
                --error --width=460  \
                --button="Bye!!Unmount USB device and quit MyLiveUSB":0 \
                --text="$yadtxt"
            if [ "$mypid" != "" ]; then kill $mypid; fi
            abort
        fi
    done

#########################################################
# Drop unnecessary details about the partition          #
#   which were to provide information to the user       #
#########################################################
    target_part=$(echo $target_part | cut -d '|' -f1)
    echo $target_part

    umount $target_part                     # Required if previously mounted
    Part_Num=$(echo "$target_part" | cut -c9-10 )
}

check_device_valid() {
#########################################################
# Check for valid data partitions. If none are          #
# found, offer to create a new device structure         #
#########################################################
    data_partition_valid=true
    target_part=$(lsblk -l -o FSTYPE,NAME,SIZE,LABEL $mydevice | \
                    grep "sd" | grep ext | tr -s ' ' | \
                    cut -d ' ' -f2,3,4 | tr -t ' ' '\n' | \
                    sed 's|sd|\/dev\/sd|g') 
    if [ "$target_part" == "" ]
    then
        data_partition_valid=false
        opt_init_device
    fi
}

opt_init_device() {
#########################################################
# Check for valid boot partitions; If none are          #
# found, offer to create a new device structure         #
#########################################################

    get_device_type

# Select EFI Partition
    efi_part=$(fdisk -l $mydevice -o Device,Type | grep EFI | tr -s ' ' | cut -d ' ' -f1)

# Check for presence of bios_grub (BIOS boot) partition
    bios_grub=$(fdisk -l $mydevice -o Device,Type | grep BIOS | tr -s ' ' | cut -d ' ' -f1)

    device_suitable=true

    if [ "$DOS" != "" ]
    then
        if [ "$data_partition_valid" == "false" ]
        then
            device_suitable=false
        fi
    elif [ "$GPT" != "" ]
    then
        if  [[ ("$efi_part" == "" && "$bios_grub" == "") || "$data_partition_valid" == "false" ]]
        then
            device_suitable=false
        fi
    fi

    if [ "$device_suitable" == "false" ]
    then
        myaction=0
        while [ $myaction -eq 0 ]
        do
            yadtxt="\n                                 <b>UNSUITABLE DEVICE STRUCTURE</b>\n\n"
            yadtxt=$yadtxt"                           The device <span color='blue'><b>$mydevice</b></span> does not have the partitions\n"
            yadtxt=$yadtxt"                                  required to be used by MyLiveUSB\n\n"
            yadtxt=$yadtxt"                      Do you want the necessary partitions be created?\n\n"
            yadtxt=$yadtxt"                       If you answer YES, the device will be completely\n"
            yadtxt=$yadtxt"                         wiped and the required partitions created for\n"
            yadtxt=$yadtxt"                                                         MyLiveUSB\n\n"
            yad --center --window-icon=$ICON --title="$TITLE" \
                --height=225 --width=520 \
                --button="Show Structure!!Show the device structure using fdisk":0 \
                --button="Yes!!Wipe the device and create the required partitions":1 \
                --button="Quit MyLiveUSB":2 \
                --text="$yadtxt"
            myaction=$?
            if [ $myaction -eq 0 ]
            then
                yadtxt="\n                                                     <b>CURRENT DEVICE STRUCTURE</b>\n\n"
                yadtxt=$yadtxt"                                 This is the current device structure of your USB device\n\n"
                fdisk -l $mydevice | \
                    yad --center --window-icon=$ICON --title="$TITLE" \
                        --width=700 --height=580 \
                        --text "$yadtxt" \
                        --button=Continue:0 \
                        --text-info
            fi
        done
        if [ $myaction -eq 2 ]; then abort; fi
        create_structure
    fi
}

create_structure() {
#########################################################
# Create a new GPT partition type with EFI, BIOS        #
#   and EXT4 partitions                                 #
#########################################################

    yadtxt=" \n                                            <b>DEVICE PARTITIONING</b> \n\n"
    yadtxt=$yadtxt"                         The device <b>$mydevice</b> will now be FULLY WIPED\n"
    yadtxt=$yadtxt"                                     and required partitions created\n\n"
    yadtxt=$yadtxt"                         If this is correct, then click 'Yes' to continue\n\n"
    yadtxt=$yadtxt"                     To abort this script, click 'Quit MyLiveUSB'\n\n"
    yadtxt=$yadtxt"                      <i>Do you want to wipe and partition the device?</i>?\n\n"
    yad --center --window-icon=$ICON --title="$TITLE" \
        --height=240 --width=560 \
        --buttons-layout=spread \
        --button="Yes!!Wipe the USB device and create the required partitions":0 \
        --button="Quit MyLiveUSB":2 \
        --text="$yadtxt"
    retcod=$?
    if [ $retcod -eq 2 ]
    then
        abort_msg
    fi

    data_partition_valid=new

    get_label

    yadtxt=" \n                                      <b>DEVICE PARTITIONING</b> \n\n"
    yadtxt=$yadtxt"                Please note that creating the partitions as well as\n"
    yadtxt=$yadtxt"             installing Grub to the device may take a consiberable\n"
    yadtxt=$yadtxt"              amount of time, up to several minutes for each step\n\n"
    yadtxt=$yadtxt"                                              Please be patient\n\n"
    yad --center --window-icon=$ICON --title="$TITLE" \
        --height=140 --width=600 \
        --text "$yadtxt" \
        --button="OK!!Continue creating required partitioning":0

# unmount the partitions
    Partitions=$(lsblk -l -o FSTYPE,NAME,SIZE,LABEL $mydevice | \
                    grep "sd[a-z][1-9]" | \
                    tr -s ' ' | \
                    cut -d ' ' -f2
                )
    for i in $Partitions; do umount /dev/$i; done

# Delete the device partition structure
    wipefs -a $mydevice

# Zero the first 2MB for the bios_grub
    dd if=/dev/zero of=$mydevice bs=1M count=2
    retcod=$?
    if [ $retcod -ne 0 ]
    then
        yadtxt="\n                   <b>A WRITE ERROR $retcod HAS OCCURED</b>\n\n"
        yadtxt=$yadtxt"               An ERROR has occurred, so we are aborting\n\n"
        yadtxt=$yadtxt"                     Please give feedback about this error\n\n"
        yadtxt=$yadtxt"                                            Thank you. \n "
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=500 \
            --button="OK!!The USB device will be unmounted and MyLiveUSB will quit":0 \
            --error \
            --text="$yadtxt"
        abort
    fi

# Create new structure
echo "label: gpt
unit: sectors
first-lba: 34
: start=        2048, size=        2048, type=21686148-6449-6E6F-744E-656564454649
: start=        4096, size=       67584, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
: start=       71680,                    type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
" | sfdisk $mydevice

# Format partitions
    (
    efi_part="$mydevice"2
    umount $efi_part
    sleep 2
    mkfs.fat -F 32 -I $efi_part
    target_part="$mydevice"3
    umount $target_part
    sleep 2
    echo y | mkfs.ext4 $target_part
    e2label $target_part $mylabel
    ) | yad --center --window-icon=$ICON --title="$TITLE" \
            --progress --progress-text="" --pulsate \
            --width 400 --height 100 \
             --text="\n                      Formatting Partitions ...\n" \
             --auto-close --auto-kill;

# Install grub
    bios_grub="$mydevice"1
    efi_part="$mydevice"2
    target_part="$mydevice"3
    get_device_type
    create_mounts
    mount $efi_part $efi_Mnt
    mount $target_part $Mnt_Pnt
    if [ -d $Mnt_Pnt/lost+found ]
    then
        rm -rf $Mnt_Pnt/lost+found
    fi
    mkdir -p $Mnt_Pnt/boot
#    do_install_grub
    forcegrub=1
    copy_grub2
#    installgrub2 $mydevice

# Show the created device strucure
    yadtxt="\n                                                  <b>SUCCESSFULLY COMPLETED</b>\n\n"
    yadtxt=$yadtxt"                 Congratulations, the USB device <b>$mydevice</b> has been repartitioned\n\n"
    yadtxt=$yadtxt"                              The resulting device structure is as follows\n"
    fdisk -l $mydevice | \
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=780 --height=600 \
            --text "$yadtxt" \
            --button=Done:0 \
            --text-info
}

get_device_type() {
    DOS=""
    GPT=""
    DOS=$(fdisk -l $mydevice | grep "dos" | sed 's| ||g'| cut -d : -f2)
    GPT=$(fdisk -l $mydevice | grep "gpt" | sed 's| ||g'| cut -d : -f2)
}

create_mounts() {
    mkdir -p $efi_Mnt                       # Create the directory for the EFI mount.
    mkdir -p $Mnt_Pnt                       # Create the directory for the ext4 partition mount.
}

write_label() {
    LABEL_Exist=$(e2label $target_part)     # Check for an existing label

    if [ "$LABEL_Exist" == "" ]
    then
        get_label
        e2label $target_part $LABEL
    fi
}

get_uuid() {
#########################################################
# Get the UUID of the target partition.                 #
#########################################################
    PART_UUID=$(lsblk -l -n -o UUID "$target_part")
    if [ "$PART_UUID" == "" ]
    then
        yadtxt="\n                               <b>No Partition UUID Found</b> \n\n"
        yadtxt=$yadtxt"         No UUID was found for the selected LiveOS partition\n\n"
        yadtxt=$yadtxt"                     Sorry, but we must abort because of this\n\n"
        yad --center --window-icon=$ICON --title="$TITLE " \
            --info \
            --width=600 \
            --button="OK!!The USB device will be unmounted and MyLiveUSB will quit":1 \
            --text="$yadtxt"
        abort
    fi
}

get_job() {
#########################################################
# Function kept from previous version                   #
# Don't offer deleting if device is restructured        #
#########################################################

    if [ "$data_partition_valid" != "new" ]
    then
        delete_sqfs
    fi
}

delete_sqfs() {
#########################################################
# Detect existing OS entries on device                  #
# offer deletion via dialog                             #
#########################################################

    sqfs_file=""
    Installed=$(for sqfsfound in $(ls $Mnt_Pnt | grep .sqfs)
                do
                    echo $sqfsfound
                    basename $sqfsfound | cut -d '.' -f1
                    echo FALSE
                done)

# Return if no OS files found
    if [ "$Installed" == "" ]; then return; fi

    sqfs_file=${sqfs_file%?}
    echo $sqfs_file | tr '|' ' '
    echo "SQFS_File: $sqfs_file"

    yadtxt="                         <b>Existing OS Entries on the Device</b> \n\n"
    yadtxt=$yadtxt"                     These are the existing OS on your device\n\n"
    yadtxt=$yadtxt"                     If you wish to delete one or more OS(es),\n"
    yadtxt=$yadtxt"                 please activate the corresponding checkbox(es)\n\n"
    yadtxt=$yadtxt"                 If no checkboxes are ticked, we will continue\n"
    yadtxt=$yadtxt"                        without deleting any existing OS entries\n\n"
    myOS=$(yad --center  --title="$TITLE " \
               --width=600 --height=480 \
               --on-top \
               --text="$yadtxt" \
               --buttons-layout=spread \
               --button="Continue":0  \
               --button="Quit MyLiveUSB":1 \
               --list --print-all \
               --hide-column=1 \
               --column="SQFS_Name" \
               --column=Name \
               --column="                            Delete":CHK \
               $Installed)
    retcod=$?
    if [ $retcod -eq 1 ]; then abort; fi

    myselection=""

    (   for mydelete in $myOS
        do
            truefalse=$(echo $mydelete | awk -F'|' '{print $3}')
            if [ $truefalse == TRUE ]
                then
                sqfs_file=$Mnt_Pnt"/"$(echo $mydelete | awk -F'|' '{print $1}')
                sqfs_name=$(echo $mydelete | awk -F'|' '{print $2}')
                echo "#Deleting $sqfs_name ..."
                delete_list
            fi
        done ) | yad --center --window-icon=$ICON  --title="$TITLE" \
                     --width 400 --height 100 \
                     --progress --progress-text="" --pulsate \
                     --auto-close --auto-kill;

    Installed=$(ls $Mnt_Pnt/*.sqfs)
}

delete_list() {
#########################################################
# Delete OS from device                                 #
#########################################################
    curr_sqfs_file="$sqfs_file"
    curr_sqfs_dir="$(echo "$sqfs_file" | sed 's|.sqfs||g')"
    curr_sqfs_changes=$(dirname "$sqfs_file")/changes/$(basename $curr_sqfs_dir)

    isoname="$(basename "$sqfs_file" | sed 's|.\?.sqfs||g')"    # ISO name

    rm -f $curr_sqfs_file
    rm -rfd $curr_sqfs_dir
    rm -rfd $curr_sqfs_changes

# Edit grub.cfg
    touch "$Mnt_Pnt"/boot/grub2/grub.tmp

    sed -e "/\"$isoname\s/,/}/d" $Mnt_Pnt/boot/grub2/grub.cfg > $Mnt_Pnt/boot/grub2/grub.tmp
    sleep 1
    rm -f "$Mnt_Pnt"/boot/grub2/grub.cfg
    uniq $Mnt_Pnt/boot/grub2/grub.tmp $Mnt_Pnt/boot/grub2/grub.cfg
    sleep 1
}

mount_part() {
#########################################################
# Mount the target partition for use                    #
#########################################################
    mount $target_part $Mnt_Pnt
    retcod=$?
    if [[ "$retcod" != "0" && "$retcod" != "32" ]]
    then
        yadtxt=" \n                   <b>A Mount/Unmount Error has Occured</b>\n\n"
        yadtxt=$yadtxt"               An ERROR has occurred, so we are aborting\n\n"
        yadtxt=$yadtxt"                     Please give feedback about this error\n\n"
        yadtxt=$yadtxt"                                            Thank you. \n "
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=500 --button=OK:0 \
            --error \
            --text="$yadtxt"
        abort
    fi

# Only do the following IF the EFI partition exists
    if [ "$efi_part" != "" ]
    then
        mount $efi_part $efi_Mnt
        if [ ! -d "$efi_Mnt/EFI" ]
        then
            mkdir -p $efi_Mnt/EFI
        fi
    fi

}

get_iso() {
#########################################################
# Get user's OS name and ISO file                       #
#########################################################
    iso_name=""
    iso_file=""
    extension=""
    while [ "$extension" != "iso" ]
    do
        yadtxt="\n                                 <b>SELECT OS NAME and ISO FILE</b>\n\n"
        yadtxt=$yadtxt"                  Please select or enter the OS name, then\n"
        yadtxt=$yadtxt"                  navigate to and select the ISO you wish to\n"
        yadtxt=$yadtxt"                               use for this install\n\n"
        yadtxt=$yadtxt"              The OS name must contain at least one letter and/or\n"
        yadtxt=$yadtxt"                number, and only '.' and '_'as special characters\n"
        iso_name_file=$(yad  --center --window-icon=$ICON --title "$TITLE " \
                             --width=520 \
                             --text="$yadtxt" \
                             --button=Select:0  \
                             --buttons-layout=spread \
                             --button="Quit MyLiveUSB!!The USB device will be unmounted and MyLiveUSB will quit":2 \
                             --file-filter "*.iso" \
                             --form \
                             --field="OS name":CBE \
                             --field="Your ISO file: ":FL \
                             "KDE.!MATE.!OPENBOX.!TDE.!XFCE.!E23.")
        retcod=$?

        if [ $retcod -eq 2 ]; then abort; fi
        iso_name=$(echo $iso_name_file | awk -F'|' '{print $1}')
        iso_file=$(echo $iso_name_file | awk -F'|' '{print $2}')
        extension="$(echo ${iso_file##*.})"

        if [ "$iso_name" = "" ]
        then
            yadtxt="\n                                 <b>ERROR</b> \n\n"
            yadtxt=$yadtxt"                 You failed to correctly select or enter a\n"
            yadtxt=$yadtxt"                              valid name for the OS\n\n"
            yadtxt=$yadtxt"                                    Please try again\n"
            yad --center --window-icon=$ICON --title="$TITLE" --error \
                --width=480 \
                --button=Continue:0 \
                --text="$yadtxt"
        else
# Only do this check if we are Adding an OS
            if [ "data_partition_valid" != "new" ]
            then
                if [ -d $Mnt_Pnt/$iso_name$Part_Num ]
                then
                    yadtxt="\n                               <b>ERROR</b> \n\n"
                    yadtxt=$yadtxt"         You have selected an existing name for the OS\n\n"
                    yadtxt=$yadtxt"                                     Please try again\n"
                    yad --center --window-icon=$ICON --title="$TITLE" --error \
                        --width=480 \
                        --button=Continue:0 \
                        --text="$yadtxt"
                    iso_name=""
                    extension=""
                fi
            fi
        fi
    done
}

get_size() {
#########################################################
# Check for sufficient space for the chosen "ISO"       #
#########################################################
    SIZE1=$(df -m --output=avail $Mnt_Pnt | sed '1d' | cut -f1)
    SIZE2=$(du -m -s "$iso_file" | cut -f1)
    SIZE2=$(($SIZE2+10))
    if [ $SIZE2 -gt $SIZE1 ]
    then
        unmount_part
        yadtxt="\n                            <b>A Fatal Error has Occured</b>\n\n"
        yadtxt=$yadtxt"           There is Insufficient Room for the Installation\n\n"
        yadtxt=$yadtxt"                         This application will now abort\n"
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=520 \
            --error \
            --button="OK!!The USB device will be unmounted and MyLiveUSB will quit":0 \
            --text="$yadtxt"
        abort
    fi
}

copy_iso_files() {
#########################################################
# Copy the needed files from the ISO                    #
#########################################################
    mkdir -p $Mnt_Pnt/$iso_name$Part_Num.temp
    if [ "$?" != "0" ]
    then
        yadtxt=" \n                                     <b>An Error has Occured</b> \n\n"
        yadtxt=$yadtxt"             We could not create a directory on your partition\n\n"
        yadtxt=$yadtxt"                     Please give feedback about this error\n\n"
        yadtxt=$yadtxt"                                                 Thank you. \n"
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=540 \
            --error \
            --button="Dismiss!!The USB device will be unmounted and MyLiveUSB will quit":1 \
            --text="$yadtxt"
        abort
    fi

    mkdir -p /media/$iso_name                                     # Make tmp mount point and mount the ISO
    mount "$iso_file" /media/$iso_name                            # If live is "no" then  mount ISO

    source=/media/$iso_name
    sleep .1
    sourcesize=$(du -m -s "/media/$iso_name/" | cut -f1)          # The start size of source (ISO)
    target=$Mnt_Pnt/$iso_name$Part_Num.temp                       # The start size of target (.temp)

    touch $Mnt_Pnt/$iso_name$Part_Num.temp/test.file              # just ensure there is something to measure
    sleep .1

# This size should be ~0 at this point
    targetsize=$(du -m -s $target | cut -f1)

# Set up variables for calculations
    touch $Mnt_Pnt/$iso_name$Part_Num.sqfs                                 # ensure location exists for 'dd'
    sq_target=$Mnt_Pnt/$iso_name$Part_Num.sqfs                             # squash file path & name
    sq_sourcesize=$(du -m -s $source/livecd.sqfs | cut -f1)              # squash file size at source
    sq_targetsize=$(du -m -s $Mnt_Pnt/$iso_name$Part_Num.sqfs | cut -f1)   # squash file size at target
    sleep .1

# Using rsync to copy isolinux and boot directories to USB device
    rsync -a /media/$iso_name/EFI /media/$iso_name/isolinux /media/$iso_name/boot $Mnt_Pnt/$iso_name$Part_Num.temp/ &

# Use DD to copy and rename .sqfs file into root of USB device
    dd if=/media/$iso_name/livecd.sqfs of=$Mnt_Pnt/$iso_name$Part_Num.sqfs oflag=nocache &

# Drive the progress window
    yadtxt="\n                      Writing files to USB device\n\n"
    yadtxt=$yadtxt"                 <span color='blue'><b>$mydevice</b></span> ($mydevmodel)\n\n"
    (
        while [ $sq_targetsize -lt $sq_sourcesize ]
        do
            sq_targetsize=$(du -m -s $sq_target | cut -f1)
            percent=$(("$sq_targetsize"*100/$sq_sourcesize))
            echo $percent
            sleep 1
        done
   ) |
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=460 \
            --progress --percentage=0 --bar=percent:norm \
            --no-buttons \
            --text="$yadtxt" \
            --auto-close --auto-kill;

# If 'first' install and EFI required then move the EFI to the ESP partition
    if [ "data_partition_valid" == "new" ]
    then
        if [ -d $Mnt_Pnt/$iso_name$Part_Num.temp/EFI ]
        then
            mv $Mnt_Pnt/$iso_name$Part_Num.temp/EFI $Mnt_Pnt/EFI
        fi
    fi

# Move isolinux from .temp to root and rename it
    mv $Mnt_Pnt/$iso_name$Part_Num.temp/isolinux $Mnt_Pnt/$iso_name$Part_Num
    rm -rf $Mnt_Pnt/$iso_name$Part_Num.temp
}

permissions() {
#########################################################
# Apply permissions                                     #
#########################################################
    chmod -R 0777 $Mnt_Pnt
    chmod -R 0777  $Mnt_Pnt/$iso_name$Part_Num*
    wait
}

unmount_part() {
#########################################################
# Apply partition(s)                                    #
#########################################################
    umount "$target_part"
    if [ "$?" != "0" ]
    then
        yadtxt=" \n                    <b>A Mount/Unmount Error has Occured</b>\n\n"
        yadtxt=$yadtxt"                 An ERROR has occurred, so we are aborting\n\n"
        yadtxt=$yadtxt"                     Please give feedback about this error\n\n"
        yadtxt=$yadtxt"                                              Thank you. \n "
        yad --center --window-icon=$ICON --title="$TITLE" \
            --width=520 \
            --error \
            --button="OK!!The USB device will be unmounted and MyLiveUSB will quit":0 \
            --text="$yadtxt"
        abort
    fi

    if [ "$efi_part" != "" ]
    then
        umount "$efi_part"
    fi
    umount "$iso_file"
    sleep 1

    rm -df /media/MyLiveUSB.*
    rm -df /media/$iso_name
}

abort_msg() {
#########################################################
# Display standard abort message                        #
#########################################################
    yadtxt="\n                                                <b>CANCEL</b> \n\n"
    yadtxt=$yadtxt"                 You have chosen to cancel this application\n\n"
    yadtxt=$yadtxt"                          We will now abort the installation\n\n"
    yadtxt=$yadtxt"                             Thank you for using MyLiveUSB\n "
    yad --center --window-icon=$ICON --title="$TITLE" \
        --width=520 \
        --error \
        --button="Bye!!The USB device will be unmounted and MyLiveUSB will quit":0 \
        --text="$yadtxt"
    abort
}

abort() {
#########################################################
# On error do this                                      #
#########################################################
    if [ "$target_part" != "" ]; then umount $target_part; fi
    if [ "$iso_file" != "" ]; then umount "$iso_file"; fi
    if [ "$efi_part" != "" ]; then umount "$efi_part"; fi
    sleep 1
    if [ "$iso_name" != "" ]; then rm -df /media/$iso_name; fi
    rm -df /media/MyLiveUSB.*
    if [ "$mypid" != "" ]; then kill $mypid; fi
    exit
}

copy_grub2() {
#########################################################
# Copy Grub2 files from the installed OS                #
#########################################################
    echo ""
    echo "Copying Grub2 files from install to USB"
    echo ""
    mkdir -p $Mnt_Pnt/boot/grub2
    cp -fr /boot/grub2/fonts      $Mnt_Pnt/boot/grub2/
    cp -fr /boot/grub2/i386-pc    $Mnt_Pnt/boot/grub2/
    cp -fr /boot/grub2/locale     $Mnt_Pnt/boot/grub2/
    cp -fr /boot/grub2/themes     $Mnt_Pnt/boot/grub2/
    cp -fr /boot/grub2/x86_64-efi $Mnt_Pnt/boot/grub2/
    cp -f  /boot/gfxmenu          $Mnt_Pnt/boot/gfxmenu

# Ensure PCLOS icon is present
    if [ ! -f $Mnt_Pnt/boot/grub2/themes/pclinuxos/icons/pclinuxos.png ]
    then
        mkdir -p $Mnt_Pnt/boot/grub2/themes/pclinuxos/icons
        cp /usr/share/icons/pclinuxos.png $Mnt_Pnt/boot/grub2/themes/pclinuxos/icons/pclinuxos.png
    fi
}

prepare_for_install() {
#########################################################
# Get details for MBR and EFI installation              #
#########################################################

# Append menu entries in $BOOT to grub.cfg
    for i in "$BOOT"
    do
        echo "$i" >> $Mnt_Pnt/boot/grub2/grub.cfg
    done
    echo "" >> $Mnt_Pnt/boot/grub2/grub.cfg
}

write_grubcfg() {
#########################################################
# Write a template grub.cfg to the device               #
#########################################################

cat >> $Mnt_Pnt/boot/grub2/grub.cfg <<EOF
insmod part_gpt
insmod part_msdos
insmod fat
insmod ext2
insmod all_video
insmod font
insmod png
insmod jpeg

if loadfont "\${prefix}/fonts/unicode.pf2"
then
    insmod gfxterm
    set gfxmode=800x600
    set gfxpayload=keep
    terminal_input console
    terminal_output gfxterm
fi

set theme=(\$root)/boot/grub2/themes/pclinuxos/theme.txt
export theme
search --no-floppy --set=root -u $PART_UUID

EOF
}

grub2_boot_options() {
#########################################################
# $BOOT holds the boot options.                         #
# Define the variables for the grub.cfg file            #
#########################################################

# Clear previously used variables
    STANDARD=""
    COPY2RAM=""
    PERSIST=""
    INSTALL=""
    DeBug=""

# Apply complete name to $osname
    osname="$iso_name$Part_Num"

# Define the 5 boot options here for EFI grub.cfg file
    STANDARD="
    menuentry "'"'$iso_name' Standard Boot"'"  --class pclinuxos {
    linux /$osname/vmlinuz livecd=/$osname root=/ acpi=on fromusb quiet splash=silent
    initrd /$osname/initrd.gz
    }"

    PERSIST="
    menuentry  "'"'$iso_name' with Persistence"'"  --class pclinuxos {
    linux /$osname/vmlinuz livecd=/$osname root=/ changes_dev=UUID=$PART_UUID acpi=on fstab=rw,noauto fromusb quiet splash=silent
    initrd /$osname/initrd.gz
    }"

    SafeMode="
    menuentry "'"'$iso_name' Video Safe Mode - Vesa"'"  --class pclinuxos {
    linux /$osname/vmlinuz livecd=/$osname root=/ xdriver=vesa fromusb quiet splash=silent
    initrd /$osname/initrd.gz
    }"

    COPY2RAM="
    menuentry   "'"'$iso_name' Copy to RAM"'"  --class pclinuxos {
    linux /$osname/vmlinuz livecd=/$osname root=/ copy2ram acpi=on fromusb quiet splash=silent
    initrd /$osname/initrd.gz
    }"

    INSTALL="
    menuentry   "'"'$iso_name' Install"'"  --class pclinuxos {
    linux /$osname/vmlinuz livecd=/$osname root=/ acpi=on fromusb quiet splash=silent install
    initrd /$osname/initrd.gz
    }"

    DeBug="
    menuentry   "'"'$iso_name' Debug On"'"  --class pclinuxos {
    linux /$osname/vmlinuz livecd=/$osname root=/ acpi=on fromusb debug
    initrd /$osname/initrd.gz
    }"

# Let the user to select boot options
    BOOT=""
    while [ "$BOOT" == "" ]
    do
        yadtxt="\n                                   <b>Select the Boot options</b>\n\n"
        yadtxt=$yadtxt"                             Please select the Boot Options\n"
        yadtxt=$yadtxt"                      you wish to include from the list below\n\n"
        BOOT=$(yad  --center --window-icon=$ICON --title="$TITLE" \
                    --height=420 --width=480 \
                    --list --checklist --multiple \
                    --text="$yadtxt" \
                    --hide-column=2 --print-column=2 --separator=  \
                    --column "Select" --column " Option " \
                    --column "            - Option Detail -        " \
                    TRUE "$STANDARD" "Standard live boot option" \
                    FALSE "$PERSIST" "Boot with Persistence" \
                    FALSE "$SafeMode" "Video Safe Mode - Vesa" \
                    FALSE "$COPY2RAM" "Copy To RAM" \
                    FALSE "$INSTALL" "Install PCLOS" \
                    FALSE "$DeBug" "Boot in debug Mode")
        if [ "$BOOT" == "" ]
        then
            yad --center --window-icon=$ICON --title="$TITLE" \
                --error \
                --text "Please select at least ONE option,\notherwise this OS will not be bootable" \
                --button="Continue":0
        fi
    done
}

force_grub() {
#########################################################
# Do as many installs as the device will allow          #
#    Force a Grub2 install when ADDing an OS            #
#########################################################

    if [ "$Installed" = "" ]
    then
        if [ ! -e "$efi_Mnt/EFI/BOOT/BOOTX64.EFI" ]
        then
            forcegrub=1
        fi
    fi
    if [ $forcegrub -eq 1 ]
    then
#        installgrub2 $target_part
        do_install_grub
    fi
}

do_install_grub() {
#########################################################
# Install GRUB depending on device information          #
#########################################################
    grub2_gpt=false
    grub2_bios=false

    if [ "$GPT" = "gpt" ]
    then
        if [ "$bios_grub" != "" ]; then grub2_bios=true; fi
        if [ "$efi_part" != "" ]; then grub2_gpt=true; fi
    fi
    if [ "$DOS" = "dos" ]
    then
        grub2_bios=true
        if [ "$efi_part" != "" ]; then grub2_gpt=true; fi
    fi

    if [ "$grub2_bios" == "true" ]
    then
        if [ "$testrun" == "true" ]
        then
            yad --center --window-icon=$ICON  --title="$TITLE" \
                    --width 400 --height 100 \
                    --test="\n              TESTING Installing BIOS Grub ..."
        else
            (
                grub2-install --target=i386-pc --boot-directory=$Mnt_Pnt/boot $mydevice
            ) | yad --center --window-icon=$ICON  --title="$TITLE" \
                    --width 400 --height 100 \
                    --progress --progress-text="" --pulsate \
                    --text="\n                      Installing BIOS Grub ..." \
                    --auto-close --auto-kill;
        fi
    fi
    if [ "$grub2_gpt" == "true" ]
    then
        if [ "$testrun" == "true" ]
        then
            yad --center --window-icon=$ICON  --title="$TITLE" \
                    --width 400 --height 100 \
                    --test="\n              TESTING Installing GPT Grub ..."
        else
            (
                grub2-install --target=x86_64-efi --efi-directory=$efi_Mnt \
                            --boot-directory=$Mnt_Pnt/boot --removable --recheck
            ) | yad --center --window-icon=$ICON  --title="$TITLE" \
                    --progress --progress-text="" --pulsate \
                    --width 400 --height 100 \
                    --text="\n                      Installing GPT Grub ..." \
                    --auto-close --auto-kill;
        fi
    fi
}

get_label() {
#########################################################
# Let the user specify a partition name                 #
#########################################################
    origlabel="LIVE_PCLinuxOS"
    tstlabel=""
    infotext=""
    yadtxt="                                <b>SELECT PARTITION'S LABEL</b>\n\n"
    yadtxt=$yadtxt"                             You can accept the suggested label or \n"
    yadtxt=$yadtxt"                             click the name to replace it with your\n"
    yadtxt=$yadtxt"                                             own choice.\n\n"
    yadtxt=$yadtxt"                              Press Enter to apply your edit.\n\n"
    yadtxt=$yadtxt"                         * only letters, numbers and '_' are allowed\n"
    yadtxt=$yadtxt"                          and the length is limited to 16 characters\n\n"
    while [[ "$tstlabel" != "_" ]]
    do
        mylabel=$origlabel
        mylabel=$(yad --center --window-icon=$ICON --title="$TITLE" \
                      --width=540 \
                      --list --editable \
                      --text="$yadtxt$infotext" \
                      --button="Accept Choice":0 \
                      --button="Quit MyLiveUSB":1 \
                      --form \
                      --field="Partiton Label":CBE \
                      $mylabel)
        retcod=$?
        if [ $retcod -eq 1 ]
        then
            abort_msg
        fi

        infotext=""
        mylabel=${mylabel%?}
        if [ ${#mylabel} -gt 16 ]
        then
            infotext="<b><span color='red'>The maximum length is 16 characters</span></b>"
        else
            tstlabel=$(echo $mylabel | tr -s '0-9a-zA-Z' '_')
            if [ "$tstlabel" != "_" ]
            then
                infotext="<b><span color='red'>Invalid character(s) detected</span></b>"
            fi
        fi
    done
}

#########################################################
# MAIN PROCEDURE                                        #
#########################################################

run_as_root
set_variables
usb_install

exit
