#!/bin/bash

# Copyright (C) 2017-2018 Daniel Tartavel-jeannot   <contact@librepc.com>
#                         Jean-Baptiste Biernacki   <j.biernacki@free.fr>
#
# This program 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, see <http://www.gnu.org/licenses/>.

#Change the local to the most global
export LC_ALL=C

function WaitToContinue() {
    read -p "Break... Press [ENTER] to continue." GARBAGE
}

function title() {
    echo -e "\e[1;32m${1}\e[0m"
}

function info() {
    echo -e "\e[36m${1}\e[0m"
}

function warning() {
    echo -e "\e[1;35m${1}\e[0m"
}

function error() {
    echo -e "\e[1;31m${1}\e[0m"
}

function help() {
    echo -e "${CMDNAME} [option] [size of image in Go]"
    echo -e "Options:"
    echo -e "--all                create ready to burn image of Mageia ${MAGEIA_VERSION}"
    echo -e "--clean              Clean all (suppress all) to make a new image"
    echo -e "--size               size of image default: 7Go"
    echo -e "--build-path         Path to the build directory of the image of Mageia ${MAGEIA_VERSION}"
    echo -e "--target             target system (for now rpi, odroid)"
    echo -e "--target-version     version of the target (0, 1, 2, 3 for rpi, 3 or 4 for odroid)"
    echo -e "--config             Path to config files"
    echo -e "--bootfs             filesystem of boot partition (ext4 or vfat) default: ext4"
    echo -e "--nonfree            activate nonfree repos"
    echo -e "--tainted            activate tainted repos"
    
    echo -e "\nBuild levels:"
    echo -e "--create-chroot      Create the chroot directory"
    echo -e "--install-basesystem install base system"
    echo -e "--add-urpmimedia     add mirrors for urpmi"
    echo -e "--chroot             chroot to arm directory and launch packages installation"
    echo -e "--create-image       Create the image of Mageia ${MAGEIA_VERSION}"
	echo "--config				Path to config files (rpi1  rpi2  rpi3  rpi3+  xu4)"
    
    echo -e "\nFor image size, make sure it fit on physical support. (Default size is 7 Go)"
}


function verify_disk_space()
{
    title "Verifying if there is enough space on disk to make the image"
    DISK_SPACE=$(/usr/bin/df -BG --output=avail "${INSTALL_PATH}"  | sed '1d;s/[^0-9]//g')
    info "Free disk space: ${DISK_SPACE}G"
    if [ ${DISK_SPACE} -lt ${IMAGE_SIZE} ]; then
        warning "image size is greater than disk space"
        info "correct the problem and relaunch the script with parameter --create-rpi-image"
        info "${0} --size ${IMAGE_SIZE} --create-rpi-image"
        return 1
    fi
    return 0
}


# creation of install path and copy of qemu ( installing it if not yet installed )
function createchroot()
{
    title "Making chroot"
    if ! [ -f /bin/qemu-arm-static ]; then
        title "Qemu package not present : installing qemu packages"
        /usr/bin/dnf --assumeyes --setopt=install_weak_deps=False install qemu-user-static
        if [ ${?} -ne 0 ]; then
            error "line ${LINENO} can't install qemu-user-static : exiting"
            exit ${ERR_1}
        fi
    fi
    # Starting qemu service if not started
    /bin/systemctl is-active systemd-binfmt.service
    if  [ ${?} -ne 0 ]; then
        title "Starting systemd-binfmt.service"
        /bin/systemctl start systemd-binfmt.service
        if [ ${?} -ne 0 ]; then
            error "line ${LINENO} can't start qemu-user-static : exiting"
            exit ${ERR_1}
        fi
    fi
    return 0
}

# enabling extra Mageia repositories
function genusemirroroptions()
{
    DNF_CONFIGPATH="$(dirname $(realpath "$0"))/mageia4arm-dnf.conf"
    DNF_MIRROROPTS="--config=${DNF_CONFIGPATH} --forcearch=${ARM_VERSION} --nogpgcheck --releasever=${MAGEIA_VERSION}"
    if [ ! -z "${MIRROR}" ]; then
        DNF_MIRROROPTS="${DNF_MIRROROPTS} --disablerepo=\* --repofrompath=mgarel,${MIRROR}/media/core/release/ --repofrompath=mgaup,${MIRROR}/media/core/updates/ --enablerepo=mgarel --enablerepo=mgaup"
        if [ ${NONFREE} -eq 1 ]; then
            DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgarel-nonfree,${MIRROR}/media/nonfree/release/ --repofrompath=mgaup-nonfree,${MIRROR}/media/nonfree/updates/ --enablerepo=mgarel-nonfree --enablerepo=mgaup-nonfree"
        fi
        if [ ${TAINTED} -eq 1 ]; then
            DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgarel-tainted,${MIRROR}/media/tainted/release/ --repofrompath=mgaup-tainted,${MIRROR}/media/tainted/updates/ --enablerepo=mgarel-tainted --enablerepo=mgaup-tainted"
        fi
    fi
    export DNF_MIRROROPTS
    return 0
}

# enabling extra Mageia repositories
function enableextrarepos()
{
    if [ "${MAGEIA_VERSION}" = "cauldron" ]; then
        extrasect_baseprefix="cauldron"
        extrasect_updatesprefix="cauldron-updates"
    else
        extrasect_baseprefix="mageia"
        extrasect_updatesprefix="updates"
    fi
    if [ ${NONFREE} -eq 1 ]; then
        title "activating non-free repos"
        /usr/bin/dnf --installroot="${BUILD_PATH}" config-manager --set-enabled "${extrasect_baseprefix}-${ARM_VERSION}-nonfree" --set-enabled "${extrasect_updatesprefix}-${ARM_VERSION}-nonfree"
        err=${?}
        if [ ${err} -ne 0 ]; then
            error "line ${LINENO} error ${err} - can't activate nonfree repositories : exiting"
            exit ${ERR_1}
        fi
    fi
    if [ ${TAINTED} -eq 1 ]; then
        title "activating tainted repos"
        /usr/bin/dnf --installroot="${BUILD_PATH}" config-manager --set-enabled "${extrasect_baseprefix}-${ARM_VERSION}-tainted" --set-enabled "${extrasect_updatesprefix}-${ARM_VERSION}-tainted"
        err=${?}
        if [ ${err} -ne 0 ]; then
            error "line ${LINENO} error ${err} - can't activate tainted repositories : exiting"
            exit ${ERR_1}
        fi
    fi
    return 0
}

# adding Mageia urpmi repositories
function addurpmimedia()
{
    title "Creating media ${MIRROR}"
    
    info "Removing old media"
    /sbin/urpmi.removemedia --urpmi-root  "${BUILD_PATH}" -a
    
    info "Adding media"
    if [ ! -z "${MIRROR}" ] ; then
        /sbin/urpmi.addmedia --urpmi-root  "${BUILD_PATH}" --distrib "${MIRROR}"
    else
        info "MIRROR variable not set, using mirrorlist."
        /sbin/urpmi.addmedia --urpmi-root  "${BUILD_PATH}" --distrib --mirrorlist "http://mirrors.mageia.org/api/mageia.${MAGEIA_VERSION}.${ARM_VERSION}.list"
    fi
    
    err=${?}
    if [ ${err} -ne 0 ]; then
        error "line ${LINENO} error ${err} - can't add medias from ${MIRROR} : exiting"
        exit ${ERR_1}
    fi
    if [ ${NONFREE} -eq 1 ]; then
        title "activating non-free repos"
        /sbin/urpmi.update --urpmi-root  "${BUILD_PATH}" --no-ignore Nonfree\ Release Nonfree\ Updates
        err=${?}
        if [ ${err} -ne 0 ]; then
            error "line ${LINENO} error ${err} - can't activate medias nonfree : exiting"
            exit ${ERR_1}
        fi
    fi
    if [ ${TAINTED} -eq 1 ]; then
        title "activating tainted repos"
        /sbin/urpmi.update --urpmi-root  "${BUILD_PATH}" --no-ignore Tainted\ Release Tainted\ Updates
        err=${?}
        if [ ${err} -ne 0 ]; then
            error "line ${LINENO} error ${err} - can't activate medias tainted : exiting"
            exit ${ERR_1}
        fi
    fi
    return 0
}


function installbasesystem()
{
    # Create Build path
    if ! [ -d "${BUILD_PATH}" ]; then
        warning "Build path ( ${BUILD_PATH} ) does not exist, do you want to create it ? [Y|n] "
        read yn
        if [ -z ${yn} ] || [ ${yn} = "Y" ] || [ ${yn} = "y" ]; then
            title "Creating ${BUILD_PATH}"
            /bin/mkdir -p "${BUILD_PATH}/usr/bin" "${BUILD_PATH}/usr/lib/binfmt.d"
            if [ ${?} -ne 0 ]; then
                error "line ${LINENO} can't create ${BUILD_PATH} : exiting"
                exit ${ERR_1}
            fi
        else
            exit ${ERR_1}
        fi
    else
        info "Build path exists"
    fi

    title "installing basesystem"
    /usr/bin/dnf --installroot="${BUILD_PATH}" ${DNF_MIRROROPTS} --assumeyes install shadow-utils basesystem-minimal
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error installing shadow-utils or basesystem-minimal : exiting"
        exit ${ERR_1}
    fi
    #/usr/bin/dnf --installroot="${BUILD_PATH}" ${DNF_MIRROROPTS} --assumeyes install basesystem-minimal
    #if [ ${?} -ne 0 ]; then
    #    error "line ${LINENO} error installing basesystem-minimal  : exiting"
    #    exit ${ERR_1}
    #fi
    /usr/bin/dnf --installroot="${BUILD_PATH}" ${DNF_MIRROROPTS} --assumeyes install dnf dnf-plugins-core locales u-boot
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error installing dnf or locales : exiting"
        exit ${ERR_1}
    fi
    /usr/bin/dnf --installroot="${BUILD_PATH}" ${DNF_MIRROROPTS} --assumeyes install urpmi
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error installing urpmi : exiting"
        exit ${ERR_1}
    fi
    return 0
}


function preparechroot()
{
    title "Preparing chrooting in ${BUILD_PATH}"

    #Copying qemu

    /bin/cp /bin/qemu-arm-static "${BUILD_PATH}/usr/bin/"
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} can't copy /bin/qemu-user-static to ${BUILD_PATH}/usr/bin/ : exiting"
        exit ${ERR_1}
    fi
    /bin/cp /usr/lib/binfmt.d/qemu-arm-static.conf "${BUILD_PATH}/usr/lib/binfmt.d"
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} can't copy /usr/lib/binfmt.d/qemu-arm-static.conf to ${BUILD_PATH}/usr/lib/binfmt.d : exiting"
        exit ${ERR_1}
    fi


    info "making /etc/hostname"
    echo "${HOSTNAME}" > "${BUILD_PATH}/etc/hostname"

    info "copying second stage script in ${BUILD_PATH}"
    #echo "/bin/cp ${CONFIG_PATH}/second_stage_install.sh ${BUILD_PATH}/"
    cp --preserve=mode "${CONFIG_PATH}/second_stage_install.sh" "${BUILD_PATH}/second_stage_install.sh"
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error copying ${CONFIG_PATH}/second_stage_install.sh : exiting"
        exit ${ERR_1}
    fi

    info "Preparation for setting root and user account"
    if [ -n "${ROOT_PWD}" ]; then #If root password defined, it will be setted at the end of the chroot of the second_stage_install.sh script
        echo -e "    /bin/passwd << EOF\n${ROOT_PWD}\n${ROOT_PWD}\nEOF\n" >>"${BUILD_PATH}/second_stage_install.sh"
    else
        info "No root password... One password will be set at the first login."
        echo -e "    /bin/passwd -d root\n    /bin/passwd -e root\n" >>"${BUILD_PATH}/second_stage_install.sh"
    fi
    
    if [ -n "${ID_USER}" ]; then #If user ID defined, it will be setted at the end of the chroot of the second_stage_install.sh script
        echo -e "    /sbin/useradd ${ID_USER}\n" >>"${BUILD_PATH}/second_stage_install.sh"
        if [ -n "${PASSWORD}" ]; then
            echo -e "    /bin/passwd ${ID_USER} << EOF\n${PASSWORD}\n${PASSWORD}\nEOF" >>"${BUILD_PATH}/second_stage_install.sh"
        else
            echo -e "    /bin/passwd -d ${ID_USER}\n" >>"${BUILD_PATH}/second_stage_install.sh"
        fi
    else
        info "No user defined, no user account created."
    fi


#     info "Copying skel in root directory"
#     /bin/rsync -rlptH "${BUILD_PATH}/etc/skel/" "${BUILD_PATH}/root/"
#This line break the default .bashrc file from the package "rootfiles" and the values as PATH (and /usr/sbin programs).

    postPrepareChroot
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error in postPrepareChroot function."
        exit ${ERR_1}
    fi
    return 0
}


function jumpchroot()
{
    title "chrooting to ${BUILD_PATH}"
    info "mounting dev, sys, proc directories in chroot"
    /bin/mount -B /dev "${BUILD_PATH}/dev"
    if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error mounting ${BUILD_PATH}/dev : exiting"
            exit ${ERR_1}
    fi
    /bin/mount -B /sys "${BUILD_PATH}/sys"
    if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error mounting ${BUILD_PATH}/sys : exiting"
            exit ${ERR_1}
    fi
    /bin/mount -B /proc "${BUILD_PATH}/proc"
    if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error mounting ${BUILD_PATH}/proc : exiting"
            exit ${ERR_1}
    fi
    info "Copying resolv.conf"
    /bin/cp -v --preserve=mode /etc/resolv.conf "${BUILD_PATH}/etc/"
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error copying ${BUILD_PATH}/etc/resolv.conf : exiting"
        exit ${ERR_1}
    fi
    if [ "$OPT" = "chroot" ]; then
        /sbin/chroot "${BUILD_PATH}"
    else
        /sbin/chroot --userspec root:root "${BUILD_PATH}" /bin/bash -v -c 'bash /second_stage_install.sh 2>&1'
    fi
    RET=${?}
    if [ ${RET} -ne 0 ]; then
        error "line ${LINENO} Warning : chrooting to ${BUILD_PATH} retrurn an error ${RET}"
        ERRORN=$((${ERRORN}+1))
    fi
    info "unmounting dev, sys, proc"
    /bin/umount -lf "${BUILD_PATH}/dev"
    if [ ${?} -ne 0 ]; then
        warning "line ${LINENO} Warning : error unmounting ${BUILD_PATH}/dev, continuing anyway"
        ERRORN=$((${ERRORN}+1))
    fi
    /bin/umount -lf "${BUILD_PATH}/sys"
    if [ ${?} -ne 0 ]; then
        warning "line ${LINENO} Warning : error unmounting ${BUILD_PATH}/sys, continuing anyway"
        ERRORN=$((${ERRORN}+1))
    fi
    /bin/umount -lf "${BUILD_PATH}/proc"
    if [ ${?} -ne 0 ]; then
        warning "line ${LINENO} Warning : error unmounting ${BUILD_PATH}/proc, continuing anyway"
        ERRORN=$((${ERRORN}+1))
    fi
    return 0
}


function createImageWrap()
{
    title "Wrap image creation"
    preImgCreation
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error in the process ${CONFIG_PATH}/specialFunctions.sh ."
        exit ${ERR_1}
    fi
    createimage
    if [ -z "${BOOTFS}" ]; then
        BOOTFS="ext4"
    fi
    formatpartitions ${BOOTFS} ext4
    
    return 0
}


function createimage()
{
    title " in ${IMAGE}"
    if [ -f "${INSTALL_PATH}/${IMAGE}" ]; then
        warning "Deleting previous image"
        /bin/rm -f "${INSTALL_PATH}/${IMAGE}"
        if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error can't remove previous image at ${INSTALL_PATH}/${IMAGE} : exiting"
            exit ${ERR_1}
        fi
    fi

    warning "please wait until end of image creation"
    /bin/dd if=/dev/zero of="${INSTALL_PATH}/${IMAGE}" bs=1MB count=$(( ${IMAGE_SIZE} * 1024 ))
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} can't make image at ${INSTALL_PATH}/${IMAGE} : exiting"
        exit ${ERR_1}
    fi
    
    loopingImage
    
    bunrningBootloader
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error in the process ${CONFIG_PATH}/specialFunctions.sh ."
        exit ${ERR_1}
    fi

    info "making partitions"
    echo -e "${FDISK_SCRIPT}" | /sbin/fdisk ${DEVICE}

    #Activate 'pY' : /dev/loopXpY
    partx -vu "${DEVICE}"
    #Previous function give us a list of partition. It is easy to get it and define prior this list the partition.
    #But... How to distinguish between the boot p1 and the root p2 if both are empty and ext4 ? ...

    if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then
        BOOTP="${DEVICE}p1"
        ROOTP="${DEVICE}p2"
    else
        ROOTP="${DEVICE}p1"
    fi
    return 0
}


function loopingImage()
{
    title "Looping image ..."
    
    # Mettre en place et contrôler des périphériques boucle.
    # -f, --find                    trouver le premier périphérique inutilisé
    # --show                    afficher le nom du périphérique après configuration (avec -f)
    DEVICE=$(/sbin/losetup -f --show "${INSTALL_PATH}/${IMAGE}")

    return 0
}


function formatpartitions()
{
    info "Formatting partitions"
    if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then
        info "Boot : ${BOOTP} as ${1}"
        "/sbin/mkfs.${1}" "${BOOTP}"
        if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error formating ${BOOTP} : exiting"
            /sbin/losetup -d "${DEVICE}"
            exit ${ERR_1}
        fi
        BOOT_UUID=$(blkid -s UUID -o value UUID "${BOOTP}")
        info "Boot UUID: ${BOOT_UUID}"
    fi

    info "Root : ${ROOTP} as ${2}"
    "/sbin/mkfs.${2}" "${ROOTP}"
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error formating ${ROOTP} : exiting"
        /sbin/losetup -d "${DEVICE}"
        exit ${ERR_1}
    fi
    ROOT_UUID=$(blkid -s UUID -o value UUID "${ROOTP}")
    info "Root UUID: ${ROOT_UUID}"
    
    return 0
}

function generateExtlinux()
{
    info "Generate extlinux if extlinux.conf exists."
    if [ -e "${CONFIG_PATH}/extlinux.conf" ]; then
        info "\tFound extlinux.conf"
        if [ ! -d "${BUILD_PATH}/boot/extlinux" ]; then
            info "making /boot/extlinux/extlinux.conf"
            /bin/rm -rf "${BUILD_PATH}/boot/extlinux"
            mkdir -p "${BUILD_PATH}/boot/extlinux"
        fi
        if [ ! -f "${BUILD_PATH}/boot/extlinux/extlinux.conf" ]; then
            info "\tTuning extlinux.conf"
            cp "${CONFIG_PATH}/extlinux.conf" "${BUILD_PATH}/boot/extlinux/extlinux.conf"
            #In order to use the UUID, a initrd file is necessary.
            sed -i -e "s/<UUID>/${ROOT_UUID}/g" "${BUILD_PATH}/boot/extlinux/extlinux.conf"
            sed -i -e "s/<BOOT_ARGS>/${BOOT_ARGS}/g"  "${BUILD_PATH}/boot/extlinux/extlinux.conf"
            KERNEL_ID=$(basename ${BUILD_PATH}/usr/lib/linux-*)
            sed -i -e "s/<FDTDIR>/${KERNEL_ID}/g" "${BUILD_PATH}/boot/extlinux/extlinux.conf"
        fi
    fi
}

function copyingsystem()
{
    generateExtlinux
    
    info "Remove second_stage_install.sh"
    /bin/rm -f "${BUILD_PATH}/second_stage_install.sh"
    
    if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then
        ARM_BOOT="${BUILD_PATH}/mnt/arm_boot"
        if ! [ -d "${ARM_BOOT}" ]; then
            rm -rf "${ARM_BOOT}"
            mkdir -p "${ARM_BOOT}"
        fi
        info "copying Mageia image to root partition"
        /bin/rsync -rlptogDH --exclude "${ARM_BOOT}/" --exclude "qemu-arm-static*" "${BUILD_PATH}/" "${ROOT}/"
        /bin/rsync -rlptogDH "${ARM_BOOT}/" "${BOOT}/"
        /bin/rsync -rlptogDH "${BUILD_PATH}/boot/" "${BOOT}/"
    else
        info "copying Mageia image to root partition"
        /bin/rsync -rlptogDH --exclude "qemu-arm-static*" "${BUILD_PATH}/" "${ROOT}/"
    fi
    
    copyingCustomSystem
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error in the process ${CONFIG_PATH}/specialFunctions.sh ."
        exit ${ERR_1}
    fi

    copyingcommon

    sync
    warning "You can now burn the image ( ${INSTALL_PATH}/${IMAGE} ) on SD card"
    return 0
}


function mountPartitions(){
    info "mounting partitions, making mountpoint if necessary"
    
    if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then
        if ! [ -d "${BOOT}" ]; then
            /bin/mkdir "${BOOT}"
            if [ ${?} -ne 0 ]; then
                error "line ${LINENO} error making directory ${BOOT} : exiting"
                exit ${ERR_1}
            fi
        fi
        /bin/mount "${BOOTP}" "${BOOT}"
        if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error mounting ${BOOTP} : exiting"
            exit ${ERR_1}
        fi
    fi
    
    if ! [ -d "${ROOT}" ]; then
        /bin/mkdir "${ROOT}"
        if [ ${?} -ne 0 ]; then
            error "line ${LINENO} error making directory ${ROOT} : exiting"
            exit ${ERR_1}
        fi
    fi
    /bin/mount "${ROOTP}" "${ROOT}"
    if [ ${?} -ne 0 ]; then
        error "line ${LINENO} error mounting ${ROOTP} : exiting"
        exit ${ERR_1}
    fi
}


function unmountingPartitions()
{
    title "Unmounting partitions..."
    
    # Syncing devices before unmounting
    /usr/bin/sync
    
    if [ -z "${BOOTP}" ] && [ -z "${ROOTP}" ] ; then
        warning "Root partition and Boot partition not defined !"
        
        for LOOP in $(losetup -l -O NAME,BACK-FILE -n | grep "${IMAGE}" | cut -d ' ' -f 1 ) ; do
            IFS=$'\n'
            for PARTITION in $(mount -l | grep ${LOOP}); do
                MOUNTPOINT=$(echo "$PARTITION" | cut -d ' ' -f 3)
                PARTITION=$(echo "$PARTITION" | cut -d ' ' -f 1)
                info "unmount ${PARTITION} and remove ${MOUNTPOINT}"
                /usr/bin/umount "${PARTITION}" 
                if [ ${?} -eq 0 ]; then
                    /bin/rmdir "${MOUNTPOINT}"
                else
                    error "line ${LINENO} error unmounting ${BOOT}..."
                fi
            done
            unset IFS
        done
    else
        if [ ! -z "${BOOTP}" ]; then
            /usr/bin/umount "${BOOTP}" 
            if [ ${?} -eq 0 ]; then
                /bin/rmdir "${BOOT}"
            else
                error "line ${LINENO} error unmounting ${BOOT}..."
            fi
        fi
        /usr/bin/umount "${ROOTP}" 
        if [ ${?} -eq 0 ]; then
            /bin/rmdir "${ROOT}"
        else
            error "line ${LINENO} error unmounting ${ROOT}..."
        fi
    fi
    return 0
}


function unloopingImage(){
    title "Unlooping image..."
    # Syncing devices before unmounting
    /usr/bin/sync

    # [root@jabztop mageia4arm (master)]# losetup -l -O NAME,BACK-FILE -n
    # /dev/loop0 /home/jibz/workspaces/mageia4arm/build/Mageia-7-bananaPro1.img (deleted)
    info "Looped devices to unmount : $(losetup -l -O NAME,BACK-FILE -n | grep "${IMAGE}" | cut -d ' ' -f 1 ) "

    for LOOP in $(losetup -l -O NAME,BACK-FILE -n | grep "${IMAGE}" | cut -d ' ' -f 1 ) ; do
        info "removing ${LOOP}"
        for PARTITION in ${LOOP}p* ; do
            partx -dv "${PARTITION}"
        done
#         losetup -d "${LOOP}"
        kpartx -d "${INSTALL_PATH}/${IMAGE}"
    done
    
    return 0
}


# Copying files common to all systems
function copyingcommon()
{
    title "Copying common files and configuration"
    rsync -rlptDH "${SOURCE_PATH}/common/" "${ROOT}/"
    rsync -rlptDH "${SOURCE_PATH}/tools/"*.sh "${ROOT}/usr/local/bin/"
    chown root:root "${ROOT}/usr/local/bin/"
    return 0
}


function mkfstab()
{
    title "making /etc/fstab"
    ### BUG : /mnt/arm_boot is set to vfat for all plateforms, odroid configuration says ext4.
    #echo -e "proc            /proc           proc    defaults        0       0\nUUID=${BOOT_UUID}  /mnt/arm_boot   vfat    defaults        0       0\nUUID=${ROOT_UUID}  /               ext4    defaults        0       0" > "${BUILD_PATH}/etc/fstab"
    #echo -e "proc\t/proc\tproc\tdefaults\t0\t0\nUUID=${BOOT_UUID}\t/mnt/arm_boot\t${BOOTFS}\tdefaults\t0\t0\nUUID=${ROOT_UUID}\t/\text4\tdefaults\t0\t0" > "${BUILD_PATH}/etc/fstab"
    if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then
        echo -e "proc\t/proc\tproc\tdefaults\t0\t0\nUUID=${BOOT_UUID}\t/mnt/arm_boot\t${BOOTFS}\tdefaults\t0\t0\nUUID=${ROOT_UUID}\t/\text4\tdefaults\t0\t0" > "${BUILD_PATH}/etc/fstab"
    else
        echo -e "proc\t/proc\tproc\tdefaults\t0\t0\nUUID=${ROOT_UUID}\t/\text4\tdefaults\t0\t0" > "${BUILD_PATH}/etc/fstab"
    fi
    return 0
}


# cleaning build space
function clean()
{
    title "Cleaning"
    
    unmountingPartitions
    unloopingImage

    # Removing old Build directory
    if [ -d "${BUILD_PATH}" ]; then
        info "Removing ${BUILD_PATH}"
        /bin/rm -Rf "${BUILD_PATH}"
    else
        warning "${BUILD_PATH} does not exists"
    fi
    # removing old image
    if [ -e "${INSTALL_PATH}/${IMAGE}" ]; then
        info "Removing ${IMAGE}"
        /bin/rm -f "${INSTALL_PATH}/${IMAGE}"
    else
        warning "${IMAGE} does not exists"
    fi

    return 0
}


function preImgCreation()
{
    error "This function is called if no sourced file about fdisk was lauched."
    return 1
}

function postPrepareChroot()
{
    error "This function is called if no sourced file is containing postPrepareChroot function."
    return 1
}

function bunrningBootloader()
{
    error "This function is called if no sourced file is containing bunrningBootloader function."
    return 1
}

function copyingCustomSystem()
{
    error "This function is called if no sourced file is containing bunrningBootloader function."
    return 1
}



ERRORN=0
ERR_1=1
ERR_DEFAULT_CONFIG=2
ERR_NO_CONFIG_FILE=3
ERR_NOT_ROOT=4
ERR_DEPENDENCY_MISSING=5
ERR_NO_SPACE=6
ERR_7=7
ERR_8=8
ERR_9=9

SEPARATE_BOOT_PARTITION=1

#######################
# PROGRAMM START HERE #
#######################


info ${0}

#Check dependencies :
#if [ -e /usr/bin/qemu-arm-static ]; then
#   error "qemu-user-static package is needed."
#   exit ${ERR_DEPENDENCY_MISSING}
#fi
#if [ 0 -ne $(id -u) ]; then
#   error "Script need to be run as root."
#   exit ${ERR_NOT_ROOT}
#fi

SOURCE_PATH="$(/bin/dirname  "$(readlink -f "${0}")")"
INSTALL_PATH="$(pwd)/build"
# FILES_PATH="${SOURCE_PATH}/files"
PLATFORMS_PATH="${SOURCE_PATH}/platforms"

CMDNAME=$(/bin/basename "${0}")


if [ ${#} == 0 ]; then
    help
    exit
fi


# parsing commandline
TEMP=$(getopt -o h,a --long all,help,clean,create-chroot,add-urpmimedia,create-image,,config:,target:,target-version:,chroot,bootfs:,install-basesystem,update-mirror,build-path:,size:,nonfree,tainted -n ${CMDNAME}  -- "${@}")
if [ ${?} -ne 0 ] ; then error "line ${LINENO} Failed parsing options." >&2 ; exit ${ERR_1} ; fi
eval set -- "${TEMP}"

echo "${TEMP}"
# Note the quotes around `$TEMP': they are essential! Or not, $( ) do the same as ` `. But there are the ` ' used ?
while true; do
    case "${1}" in
    -h|--help)
        help
        exit 0
        ;;
    -a|--all)
        OPT="all"
        shift 1
        ;;
    --clean)
        OPT="clean"
        shift
        ;;
    --size)
        IMAGE_SIZE_P=${2}
        shift 2
        ;;
    --build-path)
        INSTALL_PATH_P=$(readlink -f "${2}")
        shift 2
        ;;
    --chroot)
        if [ -z ${OPT} ]; then
            OPT="chroot"
        fi
        shift
        ;;
    --create-chroot)
        if [ -z ${OPT} ]; then
            OPT="createchroot"
        fi
        shift
        ;;
    --add-urpmimedia)
        if [ -z ${OPT} ]; then
            OPT="addurpmimedia"
        fi
        shift
        ;;
    --update-mirror)
        if [ -z ${OPT} ]; then
            OPT="updatemirror"
        fi
        shift
        ;;
    --install-basesystem)
        if [ -z ${OPT} ]; then
            OPT="installbasesystem"
        fi
        shift
        ;;
    --create-image)
        if [ -z ${OPT} ]; then
            CREATEIMAGE=true
            OPT="createimage"
        fi
        shift
        ;;
    --target)
        TARGET_P=${2}
        shift 2
        ;;
    --target-version)
        TARGET_VERSION_P=${2}
        shift 2
        ;;
    --config)
        CONFIG_PATH="${PLATFORMS_PATH}/${2}"
        shift 2
        ;;
    --bootfs)
        BOOTFS_P=${2}
        shift 2
        ;;
    --nonfree)
        NONFREE_P=1
        shift
        ;;
    --tainted)
        TAINTED_P=1
        shift
        ;;
    --)
      shift
      break;;
    *)
        error "Parameter ${1} does not exists "
        exit ${ERR_1};;
    esac
done


# path of config file
if ! [ -d "${CONFIG_PATH}" ]; then
    info " Config path does not exists, defaulting to ./platforms/${TARGET}"
    CONFIG_PATH="${PLATFORMS_PATH}/${TARGET}"
    warning "Do you want to create it and to copy the template file in? [Y|n] "
    read yn
    if [ -z ${yn} ] || [ ${yn} = "Y" ] || [ ${yn} = "y" ]; then
        /usr/bin/mkdir "${CONFIG_PATH}/"
        /usr/bin/cp --preserve=mode "${SOURCE_PATH}/mageia4arm.cfg.template" "${CONFIG_PATH}/mageia4arm.cfg"
        warning "You need now to modify the config file (${CONFIG_PATH}/mageia4arm.cfg) and relaunch the script"
        exit ${ERR_DEFAULT_CONFIG}
    else
        error "Error: Can't continue without config file, exiting"
        exit ${ERR_NO_CONFIG_FILE}            
    fi
fi

if [ -e "${CONFIG_PATH}/mageia4arm.cfg" ]; then
    info "using ${CONFIG_PATH}/mageia4arm.cfg as config"
    source "${CONFIG_PATH}/mageia4arm.cfg"                  #NOTE1 : Here is sourced a file with variables.
else
    warning "Config file does not exists, do you want to copy template ? [Y|n] "
    read yn
    if [ -z ${yn} ] || [ ${yn} = "Y" ] || [ ${yn} = "y" ]; then
        /usr/bin/cp --preserve=mode "${SOURCE_PATH}/mageia4arm.cfg.template" "${CONFIG_PATH}/mageia4arm.cfg"
        warning "You need now to modify the config file (${CONFIG_PATH}/mageia4arm.cfg) and relaunch the script"
        exit ${ERR_DEFAULT_CONFIG}
    fi
fi

if ! [ -z "${IMAGE_SIZE_P}" ]; then
    IMAGE_SIZE=${IMAGE_SIZE_P}
fi
if ! [ -z "${INSTALL_PATH_P}" ]; then
    INSTALL_PATH=${INSTALL_PATH_P}
fi
if ! [ -z "${TARGET_P}" ]; then
    TARGET=${TARGET_P}
fi
if ! [ -z "${TARGET_VERSION_P}" ]; then
    TARGET_VERSION=${TARGET_VERSION_P}
fi
if ! [ -z "${BOOTFS_P}" ]; then
    BOOTFS=${BOOTFS_P}
fi
if ! [ -z "${NONFREE_P}" ]; then
    NONFREE=${NONFREE_P}
else
    NONFREE=0
fi
if ! [ -z "${TAINTED_P}" ]; then
    TAINTED=${TAINTED_P}
else
    TAINTED=0
fi

info "Option: "${OPT}

IMAGE="Mageia-${MAGEIA_VERSION}-${TARGET}${TARGET_VERSION}.img"
BOOT="/mnt/boot"
ROOT="/mnt/root"
BUILD_PATH="${INSTALL_PATH}/build-${TARGET}${TARGET_VERSION}"
ARM_VERSION="armv7hl"

# Assigne a script for creating a particular target image (rpi, odroid, ...)
if [ -e "${CONFIG_PATH}/specialFunctions.sh" ]; then
    source "${CONFIG_PATH}/specialFunctions.sh"
fi

info "target : ${TARGET}"
info "target_version : ${TARGET_VERSION}"
info "source path: ${SOURCE_PATH}"
info "Install path: ${INSTALL_PATH}"
info "Build path: ${BUILD_PATH}"
info "Commande : ${CMDNAME}"
info "Firmware path : ${FIRMWARE_PATH}"
info "Firmware dir : ${FIRMWARE_DIR}"

# Defining default image size to 7 go
if [[ "${IMAGE_SIZE}" -lt 2 ]] || [[ "${IMAGE_SIZE}" -gt 128 ]]; then
    IMAGE_SIZE=7
fi

# change dir to install path and create it if not existing
if [ "${OPT}" != "clean" ]; then
    info "cd ${INSTALL_PATH}"
    if ! [ -e "${INSTALL_PATH}" ]; then
        /bin/mkdir -p "${INSTALL_PATH}"
        if [ -z ${?} ]; then
            error "line ${LINENO} can't make directory ${INSTALL_PATH} , exiting"
            exit ${ERR_1}
        fi
    fi
    cd "${INSTALL_PATH}"
    if [ -z ${?} ]; then
        error "line ${LINENO} can't change to directory ${INSTALL_PATH} , exiting"
        exit ${ERR_1}
    fi
fi

#if no parameters then display help message
if  [ -z ${OPT} ]; then
    OPT="--help"
fi

info "Image size is: ${IMAGE_SIZE} GB"

case ${OPT} in
    "clean")
        clean
        ;;
    "all")
        verify_disk_space
        if [ ${?} -ne 0 ]; then
            echo -e "Not enough space on disk\nDo you want to continue anyway ? [Y,n]"
            read yn
            if [ ${yn} = "n" ]; then
                exit ${ERR_NO_SPACE}
            fi
        fi
        createImageWrap #Create the empty .img
        createchroot #Check qemu and activate it
        genusemirroroptions #Generate mirror options, if needed
        installbasesystem #Generate the rootfs, rootfiles, ...
        enableextrarepos
        addurpmimedia
        mkfstab 
        preparechroot
        jumpchroot
            #Check before is useless (with $MIRROR
            info "Use mirrorlist to light one server."
            MIRROR=
            genusemirroroptions
            enableextrarepos
            addurpmimedia
        mountPartitions
        copyingsystem
        unmountingPartitions
        unloopingImage
        ;;
    "createchroot")
        createchroot
        ;;
    "chroot")
        jumpchroot
        ;;
    "addurpmimedia")
        addurpmimedia
        ;;
    "createimage")
        verify_disk_space
        if [ ${?} -ne 0 ]; then
            warning "Not enough space on disk"
            exit ${ERR_NO_SPACE}
        fi
        createImageWrap
        ;;
    "installbasesystem")
        installbasesystem
        ;;
esac


if [ ${ERRORN} -ne 0 ]; then
    warning "Some errors occurs : ${ERRORN} errors"
fi

exit ${ERRORN}
