#!/bin/bash
# we rely on some output which is parsed in english!
unset LANG
ANSWER="/tmp/.setup"
TITLE="Arch Linux Installation"
# use the first VT not dedicated to a running console
LOG="/dev/tty7"
# don't use /mnt because it's intended to mount other things there!
DESTDIR="/tmp/install"
EDITOR=""

# name of the kernel image
VMLINUZ="vmlinuz26"
[[ "$(cat /proc/cmdline | grep -w BOOT_IMAGE=.*lts)" ]] && VMLINUZ="vmlinuz26-lts"
# name of kernel package
KERNELPKG="kernel26"
[[ "$(cat /proc/cmdline | grep -w BOOT_IMAGE=.*lts)" ]] && KERNELPKG="kernel26-lts"

# abstract the common pacman args
PACMAN="pacman --root ${DESTDIR} --config /tmp/pacman.conf --noconfirm --noprogressbar"
# downloader
DLPROG="wget"
# sources
SYNC_URL=""
FILE_URL="file:///src/core-$(uname -m)/pkg"
MIRRORLIST="/etc/pacman.d/mirrorlist"
PACKAGES=""

# destination of blockdevices in /sys
block=/sys/block

# partitions
PART_ROOT=""
ROOTFS=""

# Mylex DAC960 PCI RAID controller, Compaq Next Generation Drive Array, 
# Compaq Intelligent Drive Array
EXTRA_CONTROLLER="rd cciss ida"

# install stages
S_SRC=0         # choose install medium
S_NET=0         # network configuration
S_CLOCK=0       # clock and timezone
S_PART=0        # partitioning
S_MKFS=0        # formatting
S_MKFSAUTO=0    # auto fs part/formatting
S_SELECT=0      # package selection
S_INSTALL=0     # package installation
S_CONFIG=0      # configuration editing
S_GRUB=0        # using grub
S_GRUB2=0       # using grub2

# menu item tracker- autoselect the next item
NEXTITEM=""

# DIALOG()
# an el-cheapo dialog wrapper
#
# parameters: see dialog(1)
# returns: whatever dialog did
DIALOG() {
    dialog --backtitle "${TITLE}" --aspect 15 "$@"
    return $?
}

# chroot_mount()
# prepares target system as a chroot
#
chroot_mount()
{
    [[ -e "${DESTDIR}/sys" ]] || mkdir "${DESTDIR}/sys"
    [[ -e "${DESTDIR}/proc" ]] || mkdir "${DESTDIR}/proc"
    [[ -e "${DESTDIR}/dev" ]] || mkdir "${DESTDIR}/dev"
    mount -t sysfs sysfs "${DESTDIR}/sys"
    mount -t proc proc "${DESTDIR}/proc"
    mount -o bind /dev "${DESTDIR}/dev"
}

# chroot_umount()
# tears down chroot in target system
#
chroot_umount()
{
    umount ${DESTDIR}/proc
    umount ${DESTDIR}/sys
    umount ${DESTDIR}/dev
}

# getuuid()
# converts /dev devices to UUIDs
#
# parameters: device file
# outputs:    UUID on success
#             nothing on failure
# returns:    nothing
getuuid()
{
    echo "$(blkid -s UUID -o value ${1})"
}

# parameters: device file
# outputs:    LABEL on success
#             nothing on failure
# returns:    nothing
getlabel()
{
    echo "$(blkid -s LABEL -o value ${1})"
}

# activate_dmraid()
# activate dmraid devices
activate_dmraid()
{
    if [[ -e /sbin/dmraid ]]; then
        DIALOG --infobox "Activating dmraid arrays..." 0 0
        /sbin/dmraid -ay -I -Z >/dev/null 2>&1
    fi
}

# activate_lvm2
# activate lvm2 devices
activate_lvm2()
{
    ACTIVATE_LVM2=""
    if [[ -e /sbin/lvm ]]; then
        OLD_LVM2_GROUPS=${LVM2_GROUPS}
        OLD_LVM2_VOLUMES=${LVM2_VOLUMES}
        DIALOG --infobox "Scanning logical volumes..." 0 0
        /sbin/lvm vgscan --ignorelockingfailure >/dev/null 2>&1
        DIALOG --infobox "Activating logical volumes..." 0 0
        /sbin/lvm vgchange --ignorelockingfailure --ignoremonitoring -ay >/dev/null 2>&1
        LVM2_GROUPS="$(vgs -o vg_name --noheading 2>/dev/null)"
        LVM2_VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
        [[ "${OLD_LVM2_GROUPS}" = "${LVM2_GROUPS}" && "${OLD_LVM2_GROUPS}" = "${LVM2_GROUPS}" ]] && ACTIVATE_LVM2="no"
    fi
}

# activate_raid
# activate md devices
activate_raid()
{
    ACTIVATE_RAID=""
    if [[ -e /sbin/mdadm ]]; then
        DIALOG --infobox "Activating RAID arrays..." 0 0
        /sbin/mdadm --assemble --scan >/dev/null 2>&1 || ACTIVATE_RAID="no"
    fi
}

# activate_luks
# activate luks devices
activate_luks()
{
    ACTIVATE_LUKS=""
    if [[ -e /sbin/cryptsetup ]]; then
        DIALOG --infobox "Scanning for luks encrypted devices..." 0 0
        if [[ "$(blkid -c=/dev/null | grep "TYPE=\"crypto_LUKS\"")" ]]; then
            for PART in $(blkid -c=/dev/null | grep "TYPE=\"crypto_LUKS\"" | sed -e 's#:.*##g'); do
                # skip already encrypted devices, device mapper!
                OPEN_LUKS=""
                for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
                    [[ "$(cryptsetup status ${devpath} | grep ${PART})" ]] && OPEN_LUKS="no"
                done
                if ! [[ "${OPEN_LUKS}" = "no" ]]; then
                    RUN_LUKS=""
                    DIALOG --yesno "Setup detected luks encrypted device, do you want to activate ${PART} ?" 0 0 && RUN_LUKS="1"
                    [[ "${RUN_LUKS}" = "1" ]] && _enter_luks_name && _enter_luks_passphrase && _opening_luks
                    [[ "${RUN_LUKS}" = "" ]] && ACTIVATE_LUKS="no"
                else
                    ACTIVATE_LUKS="no"
                fi
            done
        else
            ACTIVATE_LUKS="no"
        fi
    fi
}

# activate_special_devices()
# activate special devices:
# activate dmraid, lvm2 and raid devices, if not already activated during bootup!
# run it more times if needed, it can be hidden by each other!
activate_special_devices()
{
    ACTIVATE_RAID=""
    ACTIVATE_LUKS=""
    ACTIVATE_LVM2=""
    activate_dmraid
    while ! [[ "${ACTIVATE_LVM2}" = "no" && "${ACTIVATE_RAID}" = "no"  && "${ACTIVATE_LUKS}" = "no" ]]; do
        activate_raid
        activate_lvm2
        activate_luks
    done
}

# Check media on install packages
check_media() {
    ! [[ "$(cat /proc/mounts | grep /dev/${dev})" ]] && mount /dev/${dev} ${media} >/dev/null 2>&1
    if [[ -d ${media}/core-$(uname -m)/pkg && -d ${media}/core-any/pkg ]]; then
        SET_MEDIA=1
        break
    else
        umount ${media} >/dev/null 2>&1
    fi
}

# Get cdroms and removable devices
get_media() {
    media=/src
    SET_MEDIA=0
    #unmount media first, we may have leftovers ...
    umount ${media}  >/dev/null 2>&1
    # ide devices
    if [[ "${SET_MEDIA}" = "0" ]]; then
        for dev in $(ls ${block} | egrep '^hd'); do
            if [[ "$(cat ${block}/${dev}/device/media)" = "cdrom" ]]; then
                check_media
            fi
        done
    fi
    if [[ "${SET_MEDIA}" = "0" ]]; then
        # scsi/sata and other devices
        for dev in $(ls ${block} | egrep '^[sv]d|^sr|^scd|^sg'); do
            if [[ "$(cat ${block}/${dev}/device/type)" = "5" ]]; then
                check_media
            fi
            #check virtio devices
            if ! [[ -e ${block}/${dev}/device/type ]]; then
                check_media
            fi
        done
    fi
    if [[ "${SET_MEDIA}" = "0" ]]; then
        # usb devices with raw partition
        for dev in $(ls ${block} | egrep '^sd'); do
            if [[ "$(cat ${block}/${dev}/device/type)" = "0" && "$(cat ${block}/${dev}/removable)" = "1" && ! "$(cat ${block}/${dev}/size)" = "0" ]]; then
                check_media
            fi
        done
    fi
    if [[ "${SET_MEDIA}" = "0" ]]; then
        # MMC devices with raw partitions
        for dev in $(ls /dev/mmcblk* 2>/dev/null | egrep -v 'p'); do
            check_media
        done
    fi
}

#check on manual mounted source
manual_media() {
    if [[ "${SET_MEDIA}" = "0" ]]; then
        DIALOG --msgbox "No source media was autodetected, please switch to another VC and manually mount the source media under /src.  If you manually mount to /src, make sure the packages are available under /src/core-$(uname -m)/pkg.\n\n" 15 55
    fi
    if [[ ! -d /src/core-$(uname -m)/pkg ]]; then
        DIALOG --msgbox "Package directory /src/core-$(uname -m)/pkg is missing!" 0 0
        return 1
    fi
    if [[ ! -d /src/core-any/pkg ]]; then
        DIALOG --msgbox "Package directory /src/core-any/pkg is missing!" 0 0
        return 1
    fi
}

# destdir_mounts()
# check if PART_ROOT is set and if something is mounted on ${DESTDIR}
destdir_mounts(){
    # Don't ask for filesystem and create new filesystems
    ASK_MOUNTPOINTS=""
    PART_ROOT=""
    # check if something is mounted on ${DESTDIR}
    PART_ROOT="$(mount | grep "${DESTDIR} " | cut -d' ' -f 1)"
    # Run mountpoints, if nothing is mounted on ${DESTDIR}
    if [[ "${PART_ROOT}" = "" ]]; then
        DIALOG --msgbox "Setup couldn't detect mounted partition(s) in ${DESTDIR}, please set mountpoints first." 0 0
        mountpoints || return 1
    fi
}

# lists default linux blockdevices
default_blockdevices() {
    # ide devices
    for dev in $(ls ${block} 2>/dev/null | egrep '^hd'); do
        if [[ "$(cat ${block}/${dev}/device/media)" = "disk" ]]; then
            if ! [[ "$(cat ${block}/${dev}/size)" = "0" ]]; then
                if ! [[ "$(cat /proc/mdstat 2>/dev/null | grep "${dev}\[")" || "$(dmraid -rc | grep /dev/${dev})" ]]; then
                    echo "/dev/${dev}"
                    [[ "${1}" ]] && echo ${1}
                fi
            fi
        fi
    done
    #scsi/sata devices, and virtio blockdevices (/dev/vd*)
    for dev in $(ls ${block} 2>/dev/null | egrep '^[sv]d'); do
        # virtio device doesn't have type file!
        blktype="$(cat ${block}/${dev}/device/type 2>/dev/null)"
        if ! [[ "${blktype}" = "5" ]]; then
            if ! [[ "$(cat ${block}/${dev}/size)" = "0" ]]; then
                if ! [[ "$(cat /proc/mdstat 2>/dev/null | grep "${dev}\[")" || "$(dmraid -rc | grep /dev/${dev})" ]]; then
                    echo "/dev/${dev}"
                    [[ "${1}" ]] && echo ${1}
                fi
            fi
        fi
    done
}

# lists additional linux blockdevices
additional_blockdevices() {
    # Include additional controllers:
    # Mylex DAC960 PCI RAID controller, Compaq Next Generation Drive Array, 
    # Compaq Intelligent Drive Array
    for i in ${EXTRA_CONTROLLER}; do
        for dev in $(ls ${block} 2>/dev/null | egrep "^${i}"); do
            for k in $(ls ${block}/${dev} 2>/dev/null | egrep "${dev}*p"); do
                if [[ -d "${block}/${dev}/${k}" ]]; then
                    echo "/dev/${i}/$(echo ${dev} | sed -e 's#.*\!##g')"
                    [[ "${1}" ]] && echo ${1}
                    break
                fi
            done
        done
    done
    # Include MMC devices
    for dev in $(ls ${block} 2>/dev/null | egrep '^mmcblk'); do
        for i in $(ls ${block}/${dev} 2>/dev/null | egrep ${dev}p); do 
            if [[ -d "${block}/${dev}/${i}" ]]; then 
                echo "/dev/${dev}"
                [[ "${1}" ]] && echo ${1}
                break
            fi
        done
    done
}

# lists additional linux blockdevices partitions
additional_blockdevices_partitions() {
    # Mylex DAC960 PCI RAID controller, Compaq Next Generation Drive Array, 
    # Compaq Intelligent Drive Array
    for k in ${EXTRA_CONTROLLER}; do
        for dev in $(ls ${block} 2>/dev/null | egrep "^${k}"); do
            for i in $(ls ${block}/${dev} 2>/dev/null | egrep "${dev}*p"); do
                if [[ -d "${block}/${dev}/${i}" ]]; then
                    disk="${k}/$(echo ${dev} | sed -e 's#.*\!##g')"
                    part="${k}/$(echo ${i} | sed -e 's#.*\!##g')"
                    # exclude checks:
                    #- part of raid device
                    #  $(cat /proc/mdstat 2>/dev/null | grep ${part})
                    #- part of lvm2 device
                    #  $(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "LVM2_member")
                    #- part of luks device
                    #  $(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "crypto_LUKS")
                    #- extended partition on device
                    #  $(sfdisk -c /dev/${disk} $(echo ${part} | sed -e "s#${disk}\p##g" 2>/dev/null | grep "5")
                    #- bios_grub partitions
                    # $(echo ${part} | grep "[a-z]$(parted /dev/${disk} print | grep bios_grub | cut -d " " -f 2)$")
                    if ! [[ "$(cat /proc/mdstat 2>/dev/null | grep ${part})" || "$(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "LVM2_member")" || "$(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "crypto_LUKS")" || "$(sfdisk -c /dev/${disk} $(echo ${part} | sed -e "s#${disk}\p##g") 2>/dev/null | grep "5")" || "$(echo ${part} | grep "[a-z]$(parted /dev/${disk} print | grep bios_grub | cut -d " " -f 2)$")" ]]; then
                        echo "/dev/${part}"
                        [[ "${1}" ]] && echo ${1}
                    fi
                fi
            done
        done
    done
    # Include MMC devices
    for dev in $(ls ${block} 2>/dev/null | egrep '^mmcblk'); do
        for i in $(ls ${block}/${dev} 2>/dev/null | egrep ${dev}p); do 
            if [[ -d "${block}/${dev}/${i}" ]]; then
                # exclude checks:
                #- part of raid device
                #  $(cat /proc/mdstat 2>/dev/null | grep ${i})
                #- part of lvm2 device
                #  $(blkid -c=/dev/null -o value -s TYPE /dev/${i} | grep "LVM2_member")
                #- part of luks device
                #  $(blkid -c=/dev/null -o value -s TYPE /dev/${i} | grep "crypto_LUKS")
                #- extended partition on device
                #  $(sfdisk -c /dev/${dev} $(echo ${i} | sed -e "s#${dev}\p##g" 2>/dev/null | grep "5")
                #- bios_grub partitions
                # $(echo ${i} | grep "[a-z]$(parted /dev/${dev} print | grep bios_grub | cut -d " " -f 2)$")
                if ! [[ "$(cat /proc/mdstat 2>/dev/null | grep ${i})" || "$(blkid -c=/dev/null -o value -s TYPE /dev/${i} | grep "LVM2_member")" || $(blkid -c=/dev/null -o value -s TYPE /dev/${i} | grep "crypto_LUKS") || "$(sfdisk -c /dev/${dev} $(echo ${i} | sed -e "s#${dev}\p##g") 2>/dev/null | grep "5")" || "$(echo ${i} | grep "[a-z]$(parted /dev/${dev} print | grep bios_grub | cut -d " " -f 2)$")" ]]; then
                    echo "/dev/${i}"
                    [[ "${1}" ]] && echo ${1}
                fi
            fi
        done
    done
}

# list none partitionable raid md devices
raid_devices() {
    for devpath in $(ls ${block} 2>/dev/null | egrep '^md'); do
        if ! [[ "$(ls ${block}/${devpath} 2>/dev/null | egrep ${devpath}p)" ]]; then 
            # exlude md partitions which are part of lvm or luks
            if ! [[ "$(blkid -c=/dev/null /dev/${devpath} | grep "TYPE=\"LVM2_member\"")" || "$(blkid -c=/dev/null /dev/${devpath} | grep "TYPE=\"crypto_LUKS\"")" ]]; then
                    echo "/dev/${devpath}"
                    [[ "${1}" ]] && echo ${1}
            fi
        fi
    done
}

# lists default linux partitionable raid devices
partitionable_raid_devices() {
    for dev in $(ls ${block} 2>/dev/null | egrep '^md'); do
        for i in $(ls ${block}/${dev} 2>/dev/null | egrep "${dev}\!*p"); do 
            if [[ -d "${block}/${dev}/${i}" ]]; then 
                echo "/dev/${dev}"
                [[ "${1}" ]] && echo ${1}
                break
            fi
        done
    done
}

# lists default linux partitionable raid devices
partitionable_raid_devices_partitions() {
    for dev in $(ls ${block} 2>/dev/null | egrep '^md'); do
        for i in $(ls ${block}/${dev} 2>/dev/null | egrep ${dev}p); do 
            if [[ -d "${block}/${dev}/${i}" ]]; then
                # exlude md partitions which are part of lvm or luks
                if ! [[ "$(blkid -c=/dev/null /dev/${i} | grep "TYPE=\"LVM2_member\"")" || ! "$(blkid -c=/dev/null /dev/${i} | grep "TYPE=\"crypto_LUKS\"")" ]]; then
                    echo "/dev/${i}"
                    [[ "${1}" ]] && echo ${1}
                fi
            fi
        done
    done
}

# lists default linux dmraid devices
dmraid_devices() {
    if [[ -d /dev/mapper ]] ; then
        for fakeraid in $(dmraid -s -c); do
                if [[ "$(echo ${fakeraid} | grep '_')" ]]; then
                    echo "/dev/mapper/${fakeraid}"
                    [[ "${1}" ]] && echo ${1}
                fi
        done
    fi
}

# check_dm_devices
# - remove part of encrypted devices
# - remove part of lvm
# - remove part ot raid
check_dm_devices() {
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        k="$(blkid -c=/dev/null /dev/mapper/${devpath} 2>/dev/null | grep "TYPE=\"crypto_LUKS\"" | sed -e 's#:.*##g')"
        partofcrypt="${partofcrypt} ${k}"
    done
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        k="$(blkid -c=/dev/null /dev/mapper/${devpath} 2>/dev/null | grep "TYPE=\"LVM2_member\"" | sed -e 's#:.*##g')"
        partoflvm="${partoflvm} ${k}"
    done
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        k="$(blkid -c=/dev/null /dev/mapper/${devpath} 2>/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g')"
        partofraid="${partofraid} ${k}"
    done
}

# dm_devices
# - show device mapper devices 
dm_devices() {
    check_dm_devices
    for i in $(dmraid -s -c); do
        EXCLUDE_DMRAID=""
        if [[ "$(echo ${i} | grep '_')" ]]; then
             EXCLUDE_DMRAID="${EXCLUDE_DMRAID} -e ${i} "
        fi
    done
    if [[ -d /dev/mapper ]] ; then
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v -e control ${EXCLUDE_DMRAID}); do
            if ! [[ "$(ls ${partofcrypt} 2>/dev/null | grep /dev/mapper/${devpath}$)" || "$(ls ${partoflvm} 2>/dev/null | grep /dev/mapper/${devpath}$)" || "$(ls ${partofraid} 2>/dev/null | grep /dev/mapper/${devpath}$)" ]]; then
                echo "/dev/mapper/${devpath}"
                [[ "${1}" ]] && echo ${1}
            fi
        done
    fi
}

# dmraid_partitions
# - show dmraid partitions
dmraid_partitions() {
    check_dm_devices
    if [[ -d /dev/mapper ]] ; then
        for fakeraid in $(dmraid -s -c); do
            if [[ "$(echo ${fakeraid} | grep '_')" ]]; then
                for k in $(ls /dev/mapper/${fakeraid}*); do
                    devpath=$(basename ${k})
                    if ! [[ "$(dmraid -s -c | grep ${devpath}$)" || "$(ls ${partofcrypt} 2>/dev/null | grep /dev/mapper/${devpath}$)" || "$(ls ${partoflvm} 2>/dev/null | grep /dev/mapper/${devpath}$)" || "$(ls ${partofraid} 2>/dev/null | grep /dev/mapper/${devpath}$)" ]]; then
                        echo "/dev/mapper/${devpath}"
                        [[ "${1}" ]] && echo ${1}
                    fi
                done
            fi
        done
    fi
}

# do sanity checks on partitions, argument comes ${devpath} loop
default_partition_check() {
        disk=$(basename ${devpath})
        for part in $(ls ${block}/${disk} 2>/dev/null | egrep -v ^${disk}p | egrep ^${disk}); do
            # exclude checks:
            #- part of raid device
            #  $(cat /proc/mdstat 2>/dev/null | grep ${part})
            #- part of lvm2 device
            #  $(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "LVM2_member")
            #- part of luks device
            #  $(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "crypto_LUKS")
            #- extended partition
            #  $(sfdisk -c /dev/${disk} $(echo ${part} | sed -e "s#${disk}##g") 2>/dev/null | grep "5")
            #- extended partition on raid partition device and mmc device
            #  $(sfdisk -c /dev/${disk} $(echo ${part} | sed -e "s#${disk}\p##g" 2>/dev/null | grep "5")
            #- bios_grub partitions
            # $(echo ${part} | grep "[a-z]$(parted /dev/${disk} print | grep bios_grub | cut -d " " -f 2)$")
            if ! [[ "$(cat /proc/mdstat 2>/dev/null | grep ${part})" || "$(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "LVM2_member")" || "$(blkid -c=/dev/null -o value -s TYPE /dev/${part} | grep "crypto_LUKS")" || "$(sfdisk -c /dev/${disk} $(echo ${part} | sed -e "s#${disk}##g") 2>/dev/null | grep "5")" || "$(sfdisk -c /dev/${disk} $(echo ${part} | sed -e "s#${disk}\p##g") 2>/dev/null | grep "5")" || "$(echo ${part} | grep "[a-z]$(parted /dev/${disk} print | grep bios_grub | cut -d " " -f 2)$")" ]]; then
                if [[ -d ${block}/${disk}/${part} ]]; then
                    echo "/dev/${part}"
                    [[ "${1}" ]] && echo ${1}
                fi
            fi
        done
}

finddisks() {
    default_blockdevices ${1}
    additional_blockdevices ${1}
    dmraid_devices ${1}
    partitionable_raid_devices ${1}
}

findpartitions() {
    for devpath in $(finddisks); do
        default_partition_check ${1}
    done
    additional_blockdevices_partitions ${1}
    dm_devices ${1}
    dmraid_partitions ${1}
    raid_devices ${1}
    partitionable_raid_devices_partitions ${1}
}

# don't check on raid devices!
findbootloaderdisks() {
    if ! [[ "${USE_DMRAID}" = "1" ]]; then
        default_blockdevices ${1}
        additional_blockdevices ${1}
    else
        dmraid_devices ${1}
    fi
}

# don't list raid devices, lvm2 and devicemapper!
findbootloaderpartitions() {
    if ! [[ "${USE_DMRAID}" = "1" ]]; then
        for devpath in $(findbootloaderdisks); do
            default_partition_check ${1}
        done
        additional_blockdevices_partitions ${1}
    else
        dmraid_partitions ${1}
    fi
}

# freeze and unfreeze xfs, as hack for grub/grub2 installing
freeze_xfs() {
    sync
    if [[ -x /usr/sbin/xfs_freeze ]]; then
        if [[ "$(cat /proc/mounts | grep "${DESTDIR}/boot " | grep " xfs ")" ]]; then
            /usr/sbin/xfs_freeze -f ${DESTDIR}/boot >/dev/null 2>&1
            /usr/sbin/xfs_freeze -u ${DESTDIR}/boot >/dev/null 2>&1
        fi
        if [[ "$(cat /proc/mounts | grep "${DESTDIR} " | grep " xfs ")" ]]; then
            /usr/sbin/xfs_freeze -f ${DESTDIR} >/dev/null 2>&1
            /usr/sbin/xfs_freeze -u ${DESTDIR} >/dev/null 2>&1
        fi
    fi
}

get_grub_map() {
    rm /tmp/dev.map
    DIALOG --infobox "Generating GRUB device map...\nThis could take a while.\n\n Please be patient." 0 0
    ${DESTDIR}/sbin/grub --no-floppy --device-map /tmp/dev.map >/tmp/grub.log 2>&1 <<EOF
quit
EOF
}

# dmraid needs manual mapping
get_grub_dmraid_map() {
    USE_DMRAID="1"
    rm /tmp/dev.map
    majorhd=0
    for i in $(dmraid -s -c); do
        echo "(hd${majorhd}) /dev/mapper/${i}" >> /tmp/dev.map
        majorhd="$((${majorhd}+1))"
    done
}

# virtio devices need manual mapping
get_grub_virtio_map() {
    rm /tmp/dev.map
    majorhd=0
    #add virtio devices
    for i in $(ls -d ${block}/vd[a-z]); do
        echo "(hd${majorhd}) /dev/$(basename ${i})" >> /tmp/dev.map
        majorhd="$((${majorhd}+1))"
    done
}

# virtio devices need manual mapping
get_grub_mmcblk_map() {
    rm /tmp/dev.map
    majorhd=0
    #add virtio devices
    for i in $(ls -d ${block}/mmcblk*); do
        echo "(hd${majorhd}) /dev/$(basename ${i})" >> /tmp/dev.map
        majorhd="$((${majorhd}+1))"
    done
}

# extra devices need manual mapping
get_grub_extra_devices_map() {
    rm /tmp/dev.map
    majorhd=0
    #add extra devices
    for k in ${EXTRA_CONTROLLER}; do
        for i in $(ls -d ${block}/${k}*); do
            echo "(hd${majorhd}) /dev/${k}/$(echo $(basename ${i}) | sed -e 's#\!##g')" >> /tmp/dev.map
            majorhd="$((${majorhd}+1))"
        done
    done
}

#get geometry of device for grub installation
get_chs() {
    realdev=""
    checkdev=""
    # we need the real device for geometry check!
    realdev="$(echo ${bootdev} | sed -e 's#,.*)#)#g')"
    checkdev="$(grep ${realdev} /tmp/dev.map | sed -e 's#.*\ ##g')"
    CYLINDERS="$(sfdisk -G ${checkdev} | cut -d " " -f2)"
    HEADS="$(sfdisk -G ${checkdev} | cut -d " " -f4)"
    SECTORS="$(sfdisk -G ${checkdev} | cut -d " " -f6)"
}

# we need symlinks for grub installation!
grub_dmraid_hack() {
    for i in $(dmraid_partitions); do
        if ! [[ "${i}" = "" ]]; then
            rm -f $(echo ${i} | sed -n -e "s/\(.*\)p/\1/p")
            ln -s ${i} $(echo ${i} | sed -n -e "s/\(.*\)p/\1/p")
        fi
    done
}

# remove created symlinks
remove_grub_dmraid_hack(){
    for i in $(dmraid_partitions); do
        if ! [[ "${i}" = "" ]]; then
            rm -f $(echo ${i} | sed -n -e "s/\(.*\)p/\1/p")
        fi
    done
}

get_grub2_map() {
    [ -e /tmp/device.map ] && rm /tmp/device.map
    DIALOG --infobox "Generating GRUB2 device map...\nThis could take a while.\n\n Please be patient." 0 0
    LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-mkdevicemap --no-floppy --device-map=/tmp/device.map >>/tmp/grub2.log
}

mapdev() {
    partition_flag=0
    device_found=0
    [[ "${GRUB_LEGACY}" = "" ]] && devs=$(cat /tmp/device.map | grep -v /dev/fd | sed 's/ *\t/ /' | sed ':a;$!N;$!ba;s/\n/ /g')
    [[ "${GRUB_LEGACY}" = "1" ]] && devs=$(cat /tmp/dev.map | grep -v /dev/fd | sed 's/ *\t/ /' | sed ':a;$!N;$!ba;s/\n/ /g')
    # check if we use hd sd  or vd device
    if ! [[ "$(echo ${1} | grep /dev/sd)" || "$(echo ${1} | grep /dev/hd)" || "$(echo ${1} | grep /dev/vd)" ]]; then
        linuxdevice=$(echo ${1} | sed -e 's#p[0-9].*$##')
    else
        linuxdevice=$(echo ${1} | sed -e 's#[0-9].*$##g')
    fi
    if ! [[ "$(echo ${1} | grep /dev/sd)" || "$(echo ${1} | grep /dev/hd)" || "$(echo ${1} | grep /dev/vd)" ]]; then
        if [[ "$(echo ${1} | egrep 'p[0-9].*$')" ]]; then
            pnum=$(echo ${1} | sed -e 's#.*p##g')
            [[ "${GRUB_LEGACY}" = "1" ]] && pnum=$((${pnum}-1))
            partition_flag=1
        fi
    else
        if [[ "$(echo ${1} | egrep '[0-9]$')" ]]; then
            # /dev/hdXY
            pnum=$(echo ${1} | cut -b9-)
            [[ "${GRUB_LEGACY}" = "1" ]] && pnum=$((${pnum}-1))
            partition_flag=1
        fi
    fi
    for  dev in ${devs}; do
        if [[ "(" = $(echo ${dev} | cut -b1) ]]; then
            grubdevice="${dev}"
        else
            if [[ "${dev}" = "${linuxdevice}" ]]; then
                device_found=1
                break
            fi
        fi
    done
    if [[ "${device_found}" = "1" ]]; then
        if [[ "${partition_flag}" = "0" ]]; then
            echo "${grubdevice}"
        else
            grubdevice_stringlen=${#grubdevice}
            grubdevice_stringlen=$((${grubdevice_stringlen} - 1))
            grubdevice=$(echo ${grubdevice} | cut -b1-${grubdevice_stringlen})
            echo "${grubdevice},${pnum})"
        fi
    else
        echo "DEVICE NOT FOUND"
    fi
}

printk()
{
    case ${1} in
        "on")  echo 4 >/proc/sys/kernel/printk ;;
        "off") echo 0 >/proc/sys/kernel/printk ;;
    esac
}

getdest() {
    [[ "${DESTDIR}" ]] && return 0
    DIALOG --inputbox "Enter the destination directory where your target system is mounted" 8 65 "/tmp/install" 2>${ANSWER} || return 1
    DESTDIR=$(cat ${ANSWER})
}

# geteditor()
# prompts the user to choose an editor
# sets EDITOR global variable
#
geteditor() {
    if ! [[ "${EDITOR}" ]]; then
        DIALOG --menu "Select a Text Editor to Use" 10 35 3 \
        "1" "nano (easier)" \
        "2" "vi" 2>${ANSWER} || return 1
        case $(cat ${ANSWER}) in
            "1") EDITOR="nano" ;;
            "2") EDITOR="vi" ;;
        esac
    fi
}

# set device name scheme
set_device_name_scheme() {
    NAME_SCHEME_PARAMETER=""
    NAME_SCHEME_LEVELS="UUID /dev/disk/by-uuid/<uuid> LABEL /dev/disk/by-label/<label> KERNEL /dev/<kernelname>"
    DIALOG --menu "Select the device name scheme you want to use in config files (recommended is UUID)." 11 50 5 ${NAME_SCHEME_LEVELS} 2>${ANSWER} || return 1
    NAME_SCHEME_PARAMETER=$(cat ${ANSWER})
    NAME_SCHEME_PARAMETER_RUN="1"
}

# set GUID (gpt) usage
set_guid() {
    GUIDPARAMETER=""
    DIALOG --defaultno --yesno "Do you want to use GUID Partition Table (GPT)?\n\nIt is a standard for the layout of the partition table on a physical hard disk. Although it forms a part of the Extensible Firmware Interface (EFI) standard (Intel's proposed replacement for the PC BIOS), it is also used on some BIOS systems because of the limitations of MBR partition tables, which restrict maximum disk size to 2 TiB.\n\nWindows XP and earlier Windows systems cannot (without hacks) read or write to drives formatted with a GUID partition table, however, Vista and Windows 7 and later versions include this capability.\n\nAttention:\n- Please check if your other operating systems have GPT support!\n- Use this option for a GRUB2 setup, which should support LVM, RAID etc.,\n  which doesn't fit into the usual 30k MS-DOS MBR gap." 0 0 && GUIDPARAMETER=yes
}

# Get a list of available disks for use in the "Available disks" dialogs. This
# will print the mountpoints as follows, getting size info from /sys:
#   /dev/sda: 64000 MB
#   /dev/sdb: 64000 MB
_getavaildisks()
{
    for i in $(finddisks); do
            if [[ "$(echo "${i}" | grep '/dev/mapper')" ]]; then
                # device mapper is always 512 aligned!
                # only dmraid device can be here
                echo -n "${i} : "; echo $(($(expr 512 '*' $(dmsetup status ${i} | cut -f2 -d " "))/1000000)) MB; echo "\n"
            # special block devices
            elif [[  "$(echo "${i}" | grep "/dev/rd")" ]]; then
                echo -n "${i}: "; echo $(($(expr $(cat ${block}/rd\!$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/rd\!$(basename ${i} | sed -e 's#p.*##g')/size))/1000000)) MB; echo "\n"
            elif [[  "$(echo "${i}" | grep "/dev/cciss")" ]]; then
                echo -n "${i}: "; echo $(($(expr $(cat ${block}/cciss\!$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/cciss\!$(basename ${i} | sed -e 's#p.*##g')/size))/1000000)) MB; echo "\n"
            elif [[  "$(echo "${i}" | grep "/dev/ida")" ]]; then
                echo -n "${i}: "; echo $(($(expr $(cat ${block}/ida\!$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/ida\!$(basename ${i} | sed -e 's#p.*##g')/size))/1000000)) MB; echo "\n"
            else
                echo -n "${i} : "; echo $(($(expr $(cat ${block}/$(basename ${i})/queue/logical_block_size) '*' $(cat ${block}/$(basename ${i})/size))/1000000)) MB; echo "\n"
            fi
    done
}

# Get a list of available partitions for use in the "Available Mountpoints" dialogs. This
# will print the mountpoints as follows, getting size info from /sys:
#   /dev/sda1: 640 MB
#   /dev/sdb2: 640 MB
_getavailpartitions()
{
    for i in $(findpartitions); do
        # mmc and raid partitions
        if [[ "$(echo "${i}" | grep '/dev/md_d[0-9]')"  ||  "$(echo "${i}" | grep '/dev/md[0-9]p')" || "$(echo "${i}" | grep '/dev/mmcblk')" ]]; then
            echo -n "${i}: "; echo $(($(expr $(cat ${block}/$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/$(basename ${i} | sed -e 's#p.*##g')/$(basename ${i})/size))/1000000)) MB; echo "\n"
        # special block devices
        elif [[  "$(echo "${i}" | grep "/dev/rd")" ]]; then
                echo -n "${i}: "; echo $(($(expr $(cat ${block}/rd\!$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/rd\!$(basename ${i} | sed -e 's#p.*##g')/rd\!$(basename ${i})/size))/1000000)) MB; echo "\n"
        elif [[  "$(echo "${i}" | grep "/dev/cciss")" ]]; then
                echo -n "${i}: "; echo $(($(expr $(cat ${block}/cciss\!$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/cciss\!$(basename ${i} | sed -e 's#p.*##g')/cciss\!$(basename ${i})/size))/1000000)) MB; echo "\n"
        elif [[  "$(echo "${i}" | grep "/dev/ida")" ]]; then
                echo -n "${i}: "; echo $(($(expr $(cat ${block}/ida\!$(basename ${i} | sed -e 's#p.*##g')/queue/logical_block_size) '*' $(cat ${block}/ida\!$(basename ${i} | sed -e 's#p.*##g')/ida\!$(basename ${i})/size))/1000000)) MB; echo "\n"
        # raid device
        elif [[ "$(echo "${i}" | grep -v 'p' |grep '/dev/md')" ]]; then
            echo -n "${i}: "; echo $(($(expr $(cat ${block}/$(basename ${i})/queue/logical_block_size) '*' $(cat ${block}/$(basename ${i})/size))/1000000)) MB; echo "\n"
        # mapper devices
        elif [[ "$(echo "${i}" | grep '/dev/mapper')" ]]; then
            # mapper devices are always 512 aligned
            # crypt device
            if [[ "$(cryptsetup status ${i} 2>/dev/null)" ]]; then
                echo -n "${i}: "; echo $(($(expr 512 '*' $(cryptsetup status $(basename ${i}) | grep " size:" | sed -e 's#sectors##g' -e 's#size:##g'))/1000000)) MB; echo "\n"
            # dmraid device
            elif [[ "$(dmsetup info ${i} | grep 'DMRAID')"  ]]; then
                [[ "$(echo ${i} | grep 'p*[0-9]$')" ]] && echo -n "${i}: "; echo $(($(expr 512 '*' $(dmsetup status ${i} | cut -f2 -d " "))/1000000)) MB; echo "\n"
            # mapper device
            else
                echo -n "${i}: "; echo $(lvs -o lv_size --noheading --units m ${i} | sed -e 's#m##g') MB; echo "\n"
            fi
        else
            echo -n "${i}: "; echo $(($(expr $(cat ${block}/$(basename ${i} | sed -e 's#[0-9].*##g')/queue/logical_block_size) '*' $(cat ${block}/$(basename ${i} | sed -e 's#[0-9].*##g')/$(basename ${i})/size))/1000000)) MB; echo "\n"
        fi
    done
}

# Disable swap and all mounted partitions for the destination system. Unmount
# the destination root partition last!
_umountall()
{
    DIALOG --infobox "Disabling swapspace, unmounting already mounted disk devices..." 0 0
    swapoff -a >/dev/null 2>&1
    umount $(mount | grep -v "${DESTDIR} " | grep "${DESTDIR}" | sed 's|\ .*||g') >/dev/null 2>&1
    umount $(mount | grep "${DESTDIR} " | sed 's|\ .*||g') >/dev/null 2>&1
}

# Disable all software raid devices
_stopmd()
{
    if [[ "$(cat /proc/mdstat 2>/dev/null | grep ^md)" ]]; then
        DISABLEMD=""
        DIALOG --defaultno --yesno "Setup detected already running raid devices, do you want to disable them completely?" 0 0 && DISABLEMD="1"
        if [[ "${DISABLEMD}" = "1" ]]; then
            DIALOG --infobox "Disabling all software raid devices..." 0 0
            for i in $(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's# :.*##g'); do
                mdadm --manage --stop /dev/${i} > ${LOG}
            done
            DIALOG --infobox "Cleaning superblocks of all software raid devices..." 0 0
            for i in $(blkid -c=/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g'); do
                mdadm --zero-superblock ${i} > ${LOG}
            done
        fi
    fi
    DISABLEMDSB=""
    if [[ "$(blkid -c=/dev/null | grep "TYPE=\"linux_raid_member\"")" ]]; then
        DIALOG --defaultno --yesno "Setup detected superblock of raid devices, do you want to clean the superblock of them?" 0 0 && DISABLEMDSB="1"
        if [[ "${DISABLEMDSB}" = "1" ]]; then
            DIALOG --infobox "Cleaning superblocks of all software raid devices..." 0 0
            for i in $(blkid -c=/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g'); do
                mdadm --zero-superblock ${i} > ${LOG}
            done
        fi
    fi
}

# Disable all lvm devices
_stoplvm()
{
    DISABLELVM=""
    DETECTED_LVM=""
    LV_VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
    LV_GROUPS="$(vgs -o vg_name --noheading 2>/dev/null)"
    LV_PHYSICAL="$(pvs -o pv_name --noheading 2>/dev/null)"
    ! [[ "${LV_VOLUMES}" = "" ]] && DETECTED_LVM=1
    ! [[ "${LV_GROUPS}" = "" ]] && DETECTED_LVM=1
    ! [[ "${LV_PHYSICAL}" = "" ]] && DETECTED_LVM=1
    if [[ "${DETECTED_LVM}" = "1" ]]; then
        DIALOG --defaultno --yesno "Setup detected lvm volumes, volume groups or physical devices, do you want to remove them completely?" 0 0 && DISABLELVM="1"
    fi
    if [[ "${DISABLELVM}" = "1" ]]; then
        DIALOG --infobox "Removing logical volumes ..." 0 0
        for i in ${LV_VOLUMES}; do
            lvremove -f /dev/mapper/${i} 2>/dev/null> ${LOG}
        done
        DIALOG --infobox "Removing logical groups ..." 0 0
        for i in ${LV_GROUPS}; do
            vgremove -f ${i} 2>/dev/null > ${LOG}
        done
        DIALOG --infobox "Removing physical volumes ..." 0 0
        for i in ${LV_PHYSICAL}; do
            pvremove -f ${i} 2>/dev/null > ${LOG}
        done
    fi
}

# Disable all luks encrypted devices
_stopluks()
{
    DISABLELUKS=""
    DETECTED_LUKS=""
    LUKSDEVICE=""

    # detect already running luks devices
    LUKS_DEVICES="$(ls /dev/mapper/ | grep -v control)"
    for i in ${LUKS_DEVICES}; do
        cryptsetup status ${i} 2>/dev/null && LUKSDEVICE="${LUKSDEVICE} ${i}"
    done
    ! [[ "${LUKSDEVICE}" = "" ]] && DETECTED_LUKS=1
    if [[ "${DETECTED_LUKS}" = "1" ]]; then
        DIALOG --defaultno --yesno "Setup detected running luks encrypted devices, do you want to remove them completely?" 0 0 && DISABLELUKS="1"
    fi
    if [[ "${DISABLELUKS}" = "1" ]]; then
        DIALOG --infobox "Removing luks encrypted devices ..." 0 0
        for i in ${LUKSDEVICE}; do
            LUKS_REAL_DEVICE="$(echo $(cryptsetup status ${i} | grep device: | sed -e 's#device:##g'))"
            cryptsetup remove ${i} > ${LOG}
            # delete header from device
            dd if=/dev/zero of=${LUKS_REAL_DEVICE} bs=512 count=2048 >/dev/null 2>&1
        done
    fi
    
    DISABLELUKS=""
    DETECTED_LUKS=""

    # detect not running luks devices
    [[ "$(blkid -c=/dev/null | grep "TYPE=\"crypto_LUKS\"")" ]] && DETECTED_LUKS=1
    if [[ "${DETECTED_LUKS}" = "1" ]]; then
        DIALOG --defaultno --yesno "Setup detected not running luks encrypted devices, do you want to remove them completely?" 0 0 && DISABLELUKS="1"
    fi
    if [[ "${DISABLELUKS}" = "1" ]]; then
        DIALOG --infobox "Removing not running luks encrypted devices ..." 0 0
        for i in $(blkid -c=/dev/null | grep "TYPE=\"crypto_LUKS\"" | sed -e 's#:.*##g'); do
            # delete header from device
            dd if=/dev/zero of=${i} bs=512 count=2048 >/dev/null 2>&1
        done
    fi
    [[ -e /tmp/.crypttab ]] && rm /tmp/.crypttab
}

#_dmraid_update
_dmraid_update()
{
    DIALOG --infobox "Deactivating dmraid devices ..." 0 0
    dmraid -an >/dev/null 2>&1
    if [[ "${DETECTED_LVM}" = "1" || "${DETECTED_LUKS}" = "1" ]]; then
        DIALOG --defaultno --yesno "Setup detected running dmraid devices and/or running lvm2, luks encrypted devices. If you reduced/deleted partitions on your dmraid device a complete reset of devicemapper devices is needed. This will reset also your created lvm2 or encrypted devices. Are you sure you want to do this?" 0 0 && RESETDM="1"
        if [[ "${RESETDM}" = "1" ]]; then
            DIALOG --infobox "Resetting devicemapper devices ..." 0 0
            dmsetup remove_all >/dev/null 2>&1
        fi
    else
        DIALOG --infobox "Resetting devicemapper devices ..." 0 0
        dmsetup remove_all >/dev/null 2>&1
    fi
    DIALOG --infobox "Reactivating dmraid devices ..." 0 0
    dmraid -ay -Z >/dev/null 2>&1
}

#helpbox for raid
_helpraid()
{
DIALOG --msgbox "LINUX SOFTWARE RAID SUMMARY:\n
-----------------------------\n\n
Linear mode:\n
You have two or more partitions which are not necessarily the same size\n
(but of course can be), which you want to append to each other.\n
Spare-disks are not supported here. If a disk dies, the array dies with\n
it.\n\n
RAID-0:\n
You have two or more devices, of approximately the same size, and you want\n
to combine their storage capacity and also combine their performance by\n
accessing them in parallel. Like in Linear mode, spare disks are not\n
supported here either. RAID-0 has no redundancy, so when a disk dies, the\n
array goes with it.\n\n
RAID-1:\n
You have two devices of approximately same size, and you want the two to\n
be mirrors of each other. Eventually you have more devices, which you\n
want to keep as stand-by spare-disks, that will automatically become a\n
part of the mirror if one of the active devices break.\n\n
RAID-4:\n
You have three or more devices of roughly the same size and you want\n
a way that protects data against loss of any one disk.\n
Fault tolerance is achieved by adding an extra disk to the array, which\n
is dedicated to storing parity information. The overall capacity of the\n
array is reduced by one disk.\n
The storage efficiency is 66 percent. With six drives, the storage\n
efficiency is 87 percent. The main disadvantage is poor performance for\n
multiple,\ simultaneous, and independent read/write operations.\n
Thus, if any disk fails, all data stay intact. But if two disks fail,\n
all data is lost.\n\n
RAID-5:\n
You have three or more devices of roughly the same size, you want to\n
combine them into a larger device, but still to maintain a degree of\n
redundancy fordata safety. Eventually you have a number of devices to use\n
as spare-disks, that will not take part in the array before another device\n
fails. If you use N devices where the smallest has size S, the size of the\n
entire array will be (N-1)*S. This \"missing\" space is used for parity\n
(redundancy) information. Thus, if any disk fails, all data stay intact.\n
But if two disks fail, all data is lost.\n\n
RAID-6:\n
You have four or more devices of roughly the same size and you want\n
a way that protects data against loss of any two disks.\n
Fault tolerance is achieved by adding an two extra disk to the array,\n
which is dedicated to storing parity information. The overall capacity\n
of the array is reduced by 2 disks.\n
Thus, if any two disks fail, all data stay intact. But if 3 disks fail,\n
all data is lost.\n\n
RAID-10:\n
Shorthand for RAID1+0, a mirrored striped array and needs a minimum of\n
two disks. It provides superior data security and can survive multiple\n
disk failures. The main disadvantage is cost, because 50% of your\n
storage is duplication." 0 0
}

# Create raid or raid_partition
_raid()
{
    MDFINISH=""
    while [[ "${MDFINISH}" != "DONE" ]]; do
        activate_special_devices
        : >/tmp/.raid
        : >/tmp/.raid-spare
        # check for devices
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        #hell yeah, this is complicated! kill software raid devices already in use.
        ALREADYINUSE=$(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's# :.*linear##g' -e 's# :.*raid[0-9][0-9]##g' -e 's# :.*raid[0-9]##g' -e 's#\[[0-9]\]##g')
        for i in ${ALREADYINUSE}; do
            PARTS=$(echo ${PARTS} | sed -e "s#/dev/${i}\ _##g" -e "s#/dev/${i}\p[0-9]\ _##g")
            k=$(echo /dev/${i} | sed -e 's#[0-9]##g')
            if ! [[ "$(echo ${k} | grep ^md)" ]]; then
                PARTS=$(echo ${PARTS} | sed -e "s#${k}\ _##g")
            fi
        done
        # skip encrypted mapper devices which contain raid devices
        ALREADYINUSE=""
        for i in $(ls /dev/mapper/* 2>/dev/null | grep -v control); do
            cryptsetup status ${i} 2>/dev/null | grep -q "device:.*/dev/md" && ALREADYINUSE="${ALREADYINUSE} ${i}"
        done
        # skip lvm with raid devices
        for devpath in $(pvs -o pv_name --noheading); do
            # skip simple lvm device with raid device
            if [[ "$(echo ${devpath} | grep /dev/md)" ]]; then
                killvolumegroup="$(echo $(pvs -o vg_name --noheading ${devpath}))"
                ALREADYINUSE="${ALREADYINUSE} $(ls /dev/mapper/${killvolumegroup}-*)"
            fi
            # skip encrypted raid device
            if [[ "$(echo ${devpath} | grep dm-)" ]]; then
                if [[ "$(cryptsetup status $(basename ${devpath}) | grep "device:.*/dev/md")" ]]; then
                   killvolumegroup="$(echo $(pvs -o vg_name --noheading ${devpath}))"
                   ALREADYINUSE="${ALREADYINUSE} $(ls /dev/mapper/${killvolumegroup}-*)"
                fi
            fi
        done
        # skip already encrypted volume devices with raid device
        for devpath in $(ls /dev/mapper/ 2>/dev/null | grep -v control); do
            realdevice="$(cryptsetup status ${devpath} 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
            if [[ "$(lvs ${realdevice} 2>/dev/null)" ]]; then
                vg="$(echo $(lvs -o vg_name --noheading ${realdevice}))"
                if [[ "$(pvs -o pv_name,vg_name --noheading | grep "${vg}$" | grep "/dev/md")" ]]; then
                   ALREADYINUSE="${ALREADYINUSE} /dev/mapper/${devpath}"
                fi
            fi
        done
        for i in ${ALREADYINUSE}; do
            PARTS=$(echo ${PARTS} | sed -e "s#${i}\ _##g")
        done
        # break if all devices are in use
        if [[ "${PARTS}" = "" ]]; then
            DIALOG --msgbox "All devices in use. No more devices left for new creation." 0 0
            return 1
        fi
        # enter raid device name
        RAIDDEVICE=""
        while [[ "${RAIDDEVICE}" = "" ]]; do
            if [[ "${RAID_PARTITION}" = "" ]]; then
                DIALOG --inputbox "Enter the node name for the raiddevice:\n/dev/md[number]\n/dev/md0\n/dev/md1\n\n" 15 65 "/dev/md0" 2>${ANSWER} || return 1
            fi
            if [[ "${RAID_PARTITION}" = "1" ]]; then
                DIALOG --inputbox "Enter the node name for partitionable raiddevice:\n/dev/md_d[number]\n/dev/md_d0\n/dev/md_d1" 15 65 "/dev/md_d0" 2>${ANSWER} || return 1
            fi
            RAIDDEVICE=$(cat ${ANSWER})
            if [[ "$(cat /proc/mdstat 2>/dev/null | grep "^$(echo ${RAIDDEVICE} | sed -e 's#/dev/##g')")" ]]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical node names! Please enter another name." 8 65
                RAIDDEVICE=""
            fi
        done
        RAIDLEVELS="linear - raid0 - raid1 - raid4 - raid5 - raid6 - raid10 -"
        DIALOG --menu "Select the raid level you want to use" 21 50 11 ${RAIDLEVELS} 2>${ANSWER} || return 1
        LEVEL=$(cat ${ANSWER})
        # raid5 and raid10 support parity parameter
        PARITY=""
        if [[ "${LEVEL}" = "raid5" || "${LEVEL}" = "raid6" || "${LEVEL}" = "raid10" ]]; then
            PARITYLEVELS="left-asymmetric - left-symmetric - right-asymmetric - right-symmetric -"
            DIALOG --menu "Select the parity layout you want to use (default is left-symmetric)" 21 50 13 ${PARITYLEVELS} 2>${ANSWER} || return 1
            PARTIY=$(cat ${ANSWER})
        fi
        METADATA="default"
        DIALOG --yesno "Do you want to use the old 0.90 METADATA(superblock) format?\n\nThis will ensure compatibility with bootloaders.It is recommended to use this, in order to allow bootloaders to boot from such devices.\n\nIf you don't boot from your raid device,\nyou can safely select 'no' and use the default metadata superblock format." 0 0 && METADATA="0.90"
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)" 0 0
        # select the first device to use, no missing option available!
        RAIDNUMBER=1
        DIALOG --menu "Select device ${RAIDNUMBER}" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
        PART=$(cat ${ANSWER})
        echo "${PART}" >>/tmp/.raid
        while [[ "${PART}" != "DONE" ]]; do
            RAIDNUMBER=$((${RAIDNUMBER} + 1))
            # clean loop from used partition and options
            PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g" -e 's#MISSING\ _##g' -e 's#SPARE\ _##g')"
            # raid0 doesn't support missing devices
            ! [[ "${LEVEL}" = "raid0" || "${LEVEL}" = "linear" ]] && MDEXTRA="MISSING _"
            # add more devices
            DIALOG --menu "Select additional device ${RAIDNUMBER}" 21 50 13 ${PARTS} ${MDEXTRA} DONE _ 2>${ANSWER} || return 1
            PART=$(cat ${ANSWER})
            SPARE=""
            ! [[ "${LEVEL}" = "raid0" || "${LEVEL}" = "linear" ]] && DIALOG --yesno --defaultno "Would you like to use ${PART} as spare device?" 0 0 && SPARE="1"
            [[ "${PART}" = "DONE" ]] && break
            if [[ "${PART}" = "MISSING" ]]; then
                DIALOG --yesno "Would you like to create a degraded raid on ${RAIDDEVICE}?" 0 0 && DEGRADED="missing"
                echo "${DEGRADED}" >>/tmp/.raid
            else
                if [[ "${SPARE}" = "1" ]]; then
                    echo "${PART}" >>/tmp/.raid-spare
                else
                    echo "${PART}" >>/tmp/.raid
                fi
            fi
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create ${RAIDDEVICE} like this?\n\nLEVEL:\n${LEVEL}\n\nDEVICES:\n$(for i in $(cat /tmp/.raid); do echo "${i}\n";done)\nSPARES:\n$(for i in $(cat /tmp/.raid-spare); do echo "${i}\n";done)\n\nMETADATA(superblock) FORMAT:${METADATA}" 0 0 && MDFINISH="DONE"
    done
    _createraid
}

# create raid device
_createraid()
{
    DEVICES="$(echo -n $(cat /tmp/.raid))"
    SPARES="$(echo -n $(cat /tmp/.raid-spare))"
    # combine both if spares are available, spares at the end!
    [[ -n ${SPARES} ]] && DEVICES="${DEVICES} ${SPARES}"
    # get number of devices
    RAID_DEVICES="$(cat /tmp/.raid | wc -l)"
    SPARE_DEVICES="$(cat /tmp/.raid-spare | wc -l)"
    # generate options for mdadm
    RAIDOPTIONS="--force --run --level=${LEVEL} --metadata=${METADATA}"
    [[ "$(echo ${RAIDDEVICE} | grep /md_d[0-9])" ]] && RAIDOPTIONS="${RAIDOPTIONS} -a mdp"
    ! [[ "${RAID_DEVICES}" = "0" ]] && RAIDOPTIONS="${RAIDOPTIONS} --raid-devices=${RAID_DEVICES}"
    ! [[ "${SPARE_DEVICES}" = "0" ]] && RAIDOPTIONS="${RAIDOPTIONS} --spare-devices=${SPARE_DEVICES}"
    ! [[ "${PARITY}" = "" ]] && RAIDOPTIONS="${RAIDOPTIONS} --layout=${PARITY}"
    DIALOG --infobox "Creating ${RAIDDEVICE}..." 0 0
    mdadm --create ${RAIDDEVICE} ${RAIDOPTIONS} ${DEVICES} >${LOG} 2>&1
    if [[ $? -gt 0 ]]; then
        DIALOG --msgbox "Error creating ${RAIDDEVICE} (see ${LOG} for details)." 0 0
        return 1
    fi
    if [[ "$(echo ${RAIDDEVICE} | grep /md_d[0-9])" ]]; then
        # switch for mbr usage
        set_guid
        if [[ "${GUIDPARAMETER}" = "" ]]; then
            DIALOG --msgbox "Now you'll be put into the parted program where you can partition your raiddevice to your needs." 18 70
            clear
            parted ${RAIDDEVICE} print
            parted ${RAIDDEVICE}
        else
            DISC=${RAIDDEVICE}
            parted_gpt
        fi
    fi
}

# help for lvm
_helplvm()
{
DIALOG --msgbox "LOGICAL VOLUME SUMMARY:\n
-----------------------------\n\n
LVM is a Logical Volume Manager for the Linux kernel. With LVM you can\n
abstract your storage space and have \"virtual partitions\" which are easier\n
to modify.\n\nThe basic building block of LVM are:\n
- Physical volume (PV):\n
  Partition on hard disk (or even hard disk itself or loopback file) on\n
  which you can have virtual groups. It has a special header and is\n
  divided into physical extents. Think of physical volumes as big building\n
  blocks which can be used to build your hard drive.\n
- Volume group (VG):\n 
  Group of physical volumes that are used as storage volume (as one disk).\n
  They contain logical volumes. Think of volume groups as hard drives.\n 
- Logical volume(LV):\n
  A \"virtual/logical partition\" that resides in a volume group and is\n 
  composed of physical extents. Think of logical volumes as normal\n
  partitions." 0 0
}

# Creates physical volume
_createpv()
{
    PVFINISH=""
    while [[ "${PVFINISH}" != "DONE" ]]; do
        activate_special_devices
        : >/tmp/.pvs-create
        PVDEVICE=""
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        # skip volume devices
        for i in $(ls /dev/mapper/* | grep -v control); do
            [[ "$(lvs ${i} 2>/dev/null)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
        done
        # skip already encrypted volume devices
        for devpath in $(ls /dev/mapper/ 2>/dev/null | grep -v control); do
            realdevice="$(cryptsetup status ${devpath} 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
            if ! [[ "${realdevice}" = "" ]]; then
                [[ "$(lvs ${realdevice} 2>/dev/null)" ]] && ALREADYINUSE="${ALREADYINUSE} /dev/mapper/${devpath}"
            fi
        done
        # skip md devices, which already have lvm devices!
        for i in ${PARTS}; do
            mdcheck="$(echo ${i} | sed -e 's#/dev/##g')"
            if ! [[ "$(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null)" = "" ]]; then
                for k in $(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null); do
                    # check encrypted volume
                    realdevice="$(cryptsetup status $(cat ${k}/dm/name) 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
                    [[ "$(lvs ${realdevice} 2>/dev/null)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                    # check on normal lvs
                    [[ "$(lvs /dev/mapper/$(cat ${k}/dm/name) 2>/dev/null)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                done
            fi
        done
        # skip md partition devices, which already have lvm devices!
        for i in ${PARTS}; do
            mdcheck="$(echo ${i} | grep /dev/md*p | sed -e 's#p.*##g' -e 's#/dev/##g')"
            if [[ "$(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null)" != "" && "${mdcheck}" != "" ]]; then
                for k in $(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null); do
                    # check encrypted volume
                    realdevice="$(cryptsetup status $(cat ${k}/dm/name) 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
                    [[ "$(lvs ${realdevice} 2>/dev/null)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                   # check on normal lvs
                    [[ "$(lvs /dev/mapper/$(cat ${k}/dm/name) 2>/dev/null)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                done
            fi
        done
        for i in ${ALREADYINUSE}; do
            PARTS=$(echo ${PARTS} | sed -e "s#${i}\ _##g")
        done
        # break if all devices are in use
        if [[ "${PARTS}" = "" ]]; then
            DIALOG --msgbox "No devices left for physical volume creation." 0 0
            return 1
        fi
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)\n\n" 0 0
        # select the first device to use
        DEVNUMBER=1
        DIALOG --menu "Select device number ${DEVNUMBER} for physical volume" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
        PART=$(cat ${ANSWER})
        echo "${PART}" >>/tmp/.pvs-create
        while [[ "${PART}" != "DONE" ]]; do
            DEVNUMBER=$((${DEVNUMBER} + 1))
            # clean loop from used partition and options
            PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
            # add more devices
            DIALOG --menu "Select additional device number ${DEVNUMBER} for physical volume" 21 50 13 ${PARTS} DONE _ 2>${ANSWER} || return 1
            PART=$(cat ${ANSWER})
            [[ "${PART}" = "DONE" ]] && break
            echo "${PART}" >>/tmp/.pvs-create
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create physical volume on devices below?\n$(cat /tmp/.pvs-create | sed -e 's#$#\\n#g')" 0 0 && PVFINISH="DONE"
    done
    DIALOG --infobox "Creating physical volume on ${PART}..." 0 0
    PART="$(echo -n $(cat /tmp/.pvs-create))"
    pvcreate ${PART} >${LOG} 2>&1
    if [[ $? -gt 0 ]]; then
        DIALOG --msgbox "Error creating physical volume on ${PART} (see ${LOG} for details)." 0 0
        return 1
    fi
}

#find physical volumes that are not in use
findpv()
{
    for i in $(pvs -o pv_name --noheading);do
        if [[ "$(pvs -o vg_name --noheading ${i})" = "      " ]]; then
                if [[ "$(echo ${i} | grep /dev/dm-)" ]]; then
                    for k in $(ls /dev/mapper | grep -v control); do
                        if [[ -h /dev/mapper/${k} ]]; then
                            pv="$(basename ${i})"
                            if [[ "$(readlink /dev/mapper/${k} | grep ${pv}$)" ]]; then
                                echo "${i}" | sed -e "s#/dev/dm-.*#/dev/mapper/${k}#g"
                                [[ "${1}" ]] && echo ${1}
                            fi
                        fi
                    done
                else
                    echo "${i}"
                    [[ "${1}" ]] && echo ${1}
                fi
        fi
    done
}

getavailablepv()
{
    for i in "$(pvs -o pv_name,pv_size --noheading --units m)"; do
            if [[ "$(echo ${i} | grep /dev/dm-)" ]]; then
                for k in $(ls /dev/mapper | grep -v control); do
                    if [[ -h /dev/mapper/${k} ]]; then
                        pv="$(basename ${i})"
                        if [[ "$(readlink /dev/mapper/${k} | grep ${pv}$)" ]]; then
                            echo "${i}" | sed -e "s#/dev/dm-.* #/dev/mapper/${k} #g" | sed -e 's#$#\\n#'
                        fi
                    fi
                 done
            else
                echo "${i}" | sed -e 's#$#\\n#'
            fi
    done
}

#find volume groups that are not already full in use
findvg()
{
    for dev in $(vgs -o vg_name --noheading);do
        if ! [[ "$(vgs -o vg_free --noheading --units m ${dev} | grep " 0m$")" ]]; then
            echo "${dev}"
            [[ "${1}" ]] && echo ${1}
        fi
    done
}

getavailablevg()
{
    for i in $(vgs -o vg_name,vg_free --noheading --units m); do
        if ! [[ "$(echo ${i} | grep " 0m$")" ]]; then
            echo ${i} | sed -e 's#$#\\n#'
        fi
    done
}

# Creates volume group
_createvg()
{
    VGFINISH=""
    while [[ "${VGFINISH}" != "DONE" ]]; do
        : >/tmp/.pvs
        VGDEVICE=""
        PVS=$(findpv _)
        # break if all devices are in use
        if [[ "${PVS}" = "" ]]; then
            DIALOG --msgbox "No devices left for Volume Group creation." 0 0
            return 1
        fi
        # enter volume group name
        VGDEVICE=""
        while [[ "${VGDEVICE}" = "" ]]; do
            DIALOG --inputbox "Enter the Volume Group name:\nfoogroup\n<yourvolumegroupname>\n\n" 15 65 "foogroup" 2>${ANSWER} || return 1
            VGDEVICE=$(cat ${ANSWER})
            if [[ "$(vgs -o vg_name --noheading 2>/dev/null | grep "^  $(echo ${VGDEVICE})")" ]]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical Volume Group names! Please enter another name." 8 65
                VGDEVICE=""
            fi
        done
        # show all devices with sizes
        DIALOG --msgbox "Physical Volumes:\n$(getavailablepv)\n\nPhysical Volumes that are not shown in next dialog, are already in use!" 0 0
        # select the first device to use, no missing option available!
        PVNUMBER=1
        DIALOG --menu "Select Physical Volume ${PVNUMBER} for ${VGDEVICE}" 21 50 13 ${PVS} 2>${ANSWER} || return 1
        PV=$(cat ${ANSWER})
        echo "${PV}" >>/tmp/.pvs
        while [[ "${PVS}" != "DONE" ]]; do
            PVNUMBER=$((${PVNUMBER} + 1))
            # clean loop from used partition and options
            PVS="$(echo ${PVS} | sed -e "s#${PV}\ _##g")"
            # add more devices
            DIALOG --menu "Select additional Physical Volume ${PVNUMBER} for ${VGDEVICE}" 21 50 13 ${PVS} DONE _ 2>${ANSWER} || return 1
            PV=$(cat ${ANSWER})
            [[ "${PV}" = "DONE" ]] && break
            echo "${PV}" >>/tmp/.pvs
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create Volume Group like this?\n\n${VGDEVICE}\n\nPhysical Volumes:\n$(cat /tmp/.pvs | sed -e 's#$#\\n#g')" 0 0 && VGFINISH="DONE"
    done
    DIALOG --infobox "Creating Volume Group ${VGDEVICE}..." 0 0
    PV="$(echo -n $(cat /tmp/.pvs))"
    vgcreate ${VGDEVICE} ${PV} >${LOG} 2>&1
    if [[ $? -gt 0 ]]; then
        DIALOG --msgbox "Error creating Volume Group ${VGDEVICE} (see ${LOG} for details)." 0 0
        return 1
    fi
}

# Creates logical volume
_createlv()
{
    LVFINISH=""
    while [[ "${LVFINISH}" != "DONE" ]]; do
        LVDEVICE=""
        LV_SIZE_SET=""
        LVS=$(findvg _)
        # break if all devices are in use
        if [[ "${LVS}" = "" ]]; then
            DIALOG --msgbox "No Volume Groups with free space available for Logical Volume creation." 0 0
            return 1
        fi
        # show all devices with sizes
        DIALOG --msgbox "Volume Groups:\n$(getavailablevg)\n\nVolume Groups that are not shown, are already 100% in use!" 0 0
        DIALOG --menu "Select Volume Group" 21 50 13 ${LVS} 2>${ANSWER} || return 1
        LV=$(cat ${ANSWER})
        # enter logical volume name
        LVDEVICE=""
        while [[ "${LVDEVICE}" = "" ]]; do
            DIALOG --inputbox "Enter the Logical Volume name:\nfooname\n<yourvolumename>\n\n" 15 65 "fooname" 2>${ANSWER} || return 1
            LVDEVICE=$(cat ${ANSWER})
            if [[ "$(lvs -o lv_name,vg_name --noheading 2>/dev/null | grep " $(echo ${LVDEVICE}) $(echo ${LV})"$)" ]]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical Logical Volume names! Please enter another name." 8 65
                LVDEVICE=""
            fi
        done
        while [[ "${LV_SIZE_SET}" = "" ]]; do
            LV_ALL=""
            DIALOG --inputbox "Enter the size (MB) of your Logical Volume,\nMinimum value is > 0.\n\nVolume space left: $(vgs -o vg_free --noheading --units m ${LV})B\n\nIf you enter no value, all free space left will be used." 10 65 "" 2>${ANSWER} || return 1
                LV_SIZE=$(cat ${ANSWER})
                if [[ "${LV_SIZE}" = "" ]]; then
                    DIALOG --yesno "Would you like to create Logical Volume with free space left?" 0 0 && LV_ALL="1"
                fi
                if [[ "${LV_SIZE}" = "0" ]]; then
                    DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
                else
                    if [[ "${LV_SIZE}" -ge "$(vgs -o vg_free --noheading --units m | sed -e 's#m##g')" ]]; then
                        DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                    else
                        LV_SIZE_SET=1
                    fi
                fi
        done
        #Contiguous doesn't work with +100%FREE
        LV_CONTIGUOUS=""
        [[ "${LV_ALL}" = "" ]] && DIALOG --defaultno --yesno "Would you like to create Logical Volume as a contiguous partition, that means that your space doesn't get partitioned over one or more disks nor over non-contiguous physical extents.\n(usefull for swap space etc.)?" 0 0 && LV_CONTIGUOUS="1"
        if [[ "${LV_CONTIGUOUS}" = "1" ]]; then
            CONTIGUOUS=yes
            LV_EXTRA="-C y"
        else
            CONTIGUOUS=no
            LV_EXTRA=""
        fi
        [[ "${LV_SIZE}" = "" ]] && LV_SIZE="All free space left"
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create Logical Volume ${LVDEVICE} like this?\nVolume Group:\n${LV}\nVolume Size:\n${LV_SIZE}\nContiguous Volume:\n${CONTIGUOUS}" 0 0 && LVFINISH="DONE"
    done
    DIALOG --infobox "Creating Logical Volume ${LVDEVICE}..." 0 0
    if [[ "${LV_ALL}" = "1" ]]; then
        lvcreate ${LV_EXTRA} -l +100%FREE ${LV} -n ${LVDEVICE} >${LOG} 2>&1
    else
        lvcreate ${LV_EXTRA} -L ${LV_SIZE} ${LV} -n ${LVDEVICE} >${LOG} 2>&1
    fi
    if [[ $? -gt 0 ]]; then
        DIALOG --msgbox "Error creating Logical Volume ${LVDEVICE} (see ${LOG} for details)." 0 0
        return 1
    fi
}

# enter luks name
_enter_luks_name() {
    LUKSDEVICE=""
    while [[ "${LUKSDEVICE}" = "" ]]; do
        DIALOG --inputbox "Enter the name for luks encrypted device ${PART}:\nfooname\n<yourname>\n\n" 15 65 "fooname" 2>${ANSWER} || return 1
        LUKSDEVICE=$(cat ${ANSWER})
        if ! [[ "$(cryptsetup status ${LUKSDEVICE} | grep inactive)" ]]; then
            DIALOG --msgbox "ERROR: You have defined 2 identical luks encryption device names! Please enter another name." 8 65
            LUKSDEVICE=""
        fi
    done
}

# enter luks passphrase
_enter_luks_passphrase () {
    LUKSPASSPHRASE=""
    while [[ "${LUKSPASSPHRASE}" = "" ]]; do
        DIALOG --insecure --passwordbox "Enter passphrase for luks encrypted device ${PART}:" 0 0 2>${ANSWER} || return 1
        LUKSPASS=$(cat ${ANSWER})
        DIALOG --insecure --passwordbox "Retype passphrase for luks encrypted device ${PART}:" 0 0 2>${ANSWER} || return 1
        LUKSPASS2=$(cat ${ANSWER})
        if [[ "${LUKSPASS}" = "${LUKSPASS2}" ]]; then
            LUKSPASSPHRASE=${LUKSPASS}
            echo ${LUKSPASSPHRASE} > /tmp/.passphrase
            LUKSPASSPHRASE=/tmp/.passphrase
        else
             DIALOG --msgbox "Passphrases didn't match, please enter again." 0 0
        fi
    done
}

# opening luks
_opening_luks() {
    DIALOG --infobox "Opening encrypted ${PART}..." 0 0
    luksOpen_success="0"
    while [[ "${luksOpen_success}" = "0" ]]; do
        cryptsetup luksOpen ${PART} ${LUKSDEVICE} >${LOG} <${LUKSPASSPHRASE} && luksOpen_success=1
        if [[ "${luksOpen_success}" = "0" ]]; then
            DIALOG --msgbox "Error: Passphrases didn't match, please enter again." 0 0
            _enter_luks_passphrase || return 1
        fi
    done
    LUKSPASSPHRASE="$(cat ${LUKSPASSPHRASE})"
    DIALOG --yesno "Would you like to safe the passphrase of luks device to /etc/crypttab?\nName:${LUKSDEVICE}" 0 0 || LUKSPASSPHRASE="ASK"
    echo ${LUKSDEVICE} ${PART} ${LUKSPASSPHRASE} >> /tmp/.crypttab
    [[ -e /tmp/.passphrase ]] && rm /tmp/.passphrase
}

# help for luks
_helpluks()
{
DIALOG --msgbox "LUKS ENCRYPTION SUMMARY:\n
-----------------------------\n\n
Encryption is useful for two (related) reasons.\n
Firstly, it prevents anyone with physical access to your computer,\n
and your hard drive in particular, from getting the data from it\n
(unless they have your passphrase/key).\n
Secondly, it allows you to wipe the data on your hard drive with\n
far more confidence in the event of you selling or discarding\n
your drive.\n
Basically, it supplements the access control mechanisms of the operating\n
system (like file permissions) by making it harder to bypass the operating\n
system by inserting a boot CD, for example. Encrypting the root partition\n
prevents anyone from using this method to insert viruses or trojans onto\n
your computer.\n\n
ATTENTION:\n
Having encrypted partitions does not protect you from all possible\n
attacks. The encryption is only as good as your key management, and there\n
are other ways to break into computers, while they are running." 0 0
}

# create luks device
_luks()
{
    NAME_SCHEME_PARAMETER_RUN=""
    LUKSFINISH=""
    while [[ "${LUKSFINISH}" != "DONE" ]]; do
        activate_special_devices
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        # skip already encrypted devices, device mapper!
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
            [[ "$(cryptsetup status ${devpath})" ]] && ALREADYINUSE="${ALREADYINUSE} /dev/mapper/${devpath}"
        done
        # skip already encrypted devices, device mapper with encrypted parts!
        for devpath in $(pvs -o pv_name --noheading); do
             if [[ "$(echo ${devpath} | grep dm-)" ]]; then
                if [[ "$(cryptsetup status $(basename ${devpath}))" ]]; then
                   killvolumegroup="$(echo $(pvs -o vg_name --noheading ${devpath}))"
                   ALREADYINUSE="${ALREADYINUSE} $(ls /dev/mapper/${killvolumegroup}-*)"
                fi
             fi
             # remove hidden crypt by md device
             if [[ "$(echo ${devpath} | grep /dev/md)" ]]; then
                 mdcheck="$(echo ${devpath} | sed -e 's#/dev/##g')"
                 if ! [[ "$(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null)" = "" ]]; then
                     for k in $(find ${block}/${mdcheck}/slaves/ -name 'dm*'); do
                         if [[ "$(cryptsetup status $(cat ${k}/dm/name))" ]]; then
                             killvolumegroup="$(echo $(pvs -o vg_name --noheading ${devpath}))"
                             ALREADYINUSE="${ALREADYINUSE} $(ls /dev/mapper/${killvolumegroup}-*)"
                         fi
                     done
                 fi
             fi
        done
        # skip md devices, which already has encrypted devices!
        for i in ${PARTS}; do
            mdcheck="$(echo ${i} | sed -e 's#/dev/##g')"
            if ! [[ "$(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null)" = "" ]]; then
                for k in $(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null); do
                    [[ "$(cryptsetup status $(cat ${k}/dm/name))"  ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                    # check lvm devices if encryption was used!
                    if [[ "$(lvs /dev/mapper/$(cat ${k}/dm/name) 2>/dev/null)" ]]; then
                        for devpath in ${ALREADYINUSE}; do
                            [[ "$(echo ${devpath} | grep "/dev/mapper/$(cat ${k}/dm/name)"$)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                        done
                    fi
                done
            fi
        done
        # skip md partition devices, which already has encrypted devices!
        for i in ${PARTS}; do
            mdcheck="$(echo ${i} | grep /dev/md*p | sed -e 's#p.*##g' -e 's#/dev/##g')"
            if [[ "$(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null)" != "" && "${mdcheck}" != "" ]]; then
                for k in $(find ${block}/${mdcheck}/slaves/ -name 'dm*' 2>/dev/null); do
                    [[ "$(cryptsetup status $(cat ${k}/dm/name))" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                    # check lvm devices if encryption was used!
                    if [[ "$(lvs /dev/mapper/$(cat ${k}/dm/name) 2>/dev/null)" ]]; then
                        for devpath in ${ALREADYINUSE}; do
                            [[ "$(echo ${devpath} | grep "/dev/mapper/$(cat ${k}/dm/name)"$)" ]] && ALREADYINUSE="${ALREADYINUSE} ${i}"
                        done
                    fi
                done
            fi
        done
        for i in ${ALREADYINUSE}; do
            PARTS=$(echo ${PARTS} | sed -e "s#${i}\ _##g")
        done
        # break if all devices are in use
        if [[ "${PARTS}" = "" ]]; then
            DIALOG --msgbox "No devices left for luks encryption." 0 0
            return 1
        fi
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)\n\n" 0 0
        DIALOG --menu "Select device for luks encryption" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
        PART=$(cat ${ANSWER})
        # enter luks name
        _enter_luks_name
        ### TODO: offer more options for encrypt!
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to encrypt luks device below?\nName:${LUKSDEVICE}\nDevice:${PART}\n" 0 0 && LUKSFINISH="DONE"
    done
    _enter_luks_passphrase
    DIALOG --infobox "Encrypting ${PART}..." 0 0
    cryptsetup -c aes-cbc-essiv:sha256 -s 128 luksFormat ${PART} >${LOG} <${LUKSPASSPHRASE}
    _opening_luks
}

autoprepare() {
    # check on encrypted devices, else weird things can happen!
    _stopluks
    # check on raid devices, else weird things can happen during partitioning!
    _stopmd
    # check on lvm devices, else weird things can happen during partitioning!
    _stoplvm
    NAME_SCHEME_PARAMETER_RUN=""
    # switch for mbr usage
    set_guid
    DISCS=$(default_blockdevices)
    if [[ "$(echo ${DISCS} | wc -w)" -gt 1 ]]; then
        DIALOG --msgbox "Available Disks:\n\n$(_getavaildisks)\n" 0 0
        DIALOG --menu "Select the hard drive to use" 14 55 7 $(default_blockdevices _) 2>${ANSWER} || return 1
        DISC=$(cat ${ANSWER})
    else
        DISC=${DISCS}
    fi
    DEFAULTFS=""
    BOOT_PART_SET=""
    SWAP_PART_SET=""
    ROOT_PART_SET=""
    CHOSEN_FS=""
    # get just the disk size in 1000*1000 MB
    if [[ "$(cat ${block}/$(basename ${DISC} 2>/dev/null)/size 2>/dev/null)" ]]; then
        DISC_SIZE="$(($(expr $(cat ${block}/$(basename ${DISC})/queue/logical_block_size) '*' $(cat ${block}/$(basename ${DISC})/size))/1000000))"
    else
        DIALOG --msgbox "ERROR: Setup cannot detect size of your device, please use normal installation routine for partitioning and mounting devices." 0 0
        return 1
    fi
    while [[ "${DEFAULTFS}" = "" ]]; do
        FSOPTS=""
        [[ "$(which mkfs.ext2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext2 Ext2"
        [[ "$(which mkfs.ext3 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext3 Ext3"
        [[ "$(which mkfs.ext4 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext4 Ext4"
        [[ "$(which mkfs.btrfs 2>/dev/null)" && "${KERNELPKG}" = "kernel26" ]] && FSOPTS="${FSOPTS} btrfs Btrfs-(Experimental)"
        [[ "$(which mkfs.nilfs2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} nilfs2 Nilfs2-(Experimental)"
        [[ "$(which mkreiserfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} reiserfs Reiser3"
        [[ "$(which mkfs.xfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} xfs XFS"
        [[ "$(which mkfs.jfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} jfs JFS"
        # create 10MB bios_grub partition for grub2 support
        if [[ "${GUIDPARAMETER}" = "yes" ]]; then
            GUID_PART_SIZE="2"
        else
            GUID_PART_SIZE="0"
        fi
        DISC_SIZE=$((${DISC_SIZE}-${GUID_PART_SIZE}))
        while [[ "${BOOT_PART_SET}" = "" ]]; do
            DIALOG --inputbox "Enter the size (MB) of your /boot partition,\nMinimum value is 16.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "32" 2>${ANSWER} || return 1
            BOOT_PART_SIZE="$(cat ${ANSWER})"
            if [[ "${BOOT_PART_SIZE}" = "" ]]; then
                DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
            else
                if [[ "${BOOT_PART_SIZE}" -ge "${DISC_SIZE}" || "${BOOT_PART_SIZE}" -lt "16" || "${SBOOT_PART_SIZE}" = "${DISC_SIZE}" ]]; then
                    DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
                else
                    BOOT_PART_SET=1
                fi
            fi
        done
        DISC_SIZE=$((${DISC_SIZE}-${BOOT_PART_SIZE}))
        SWAP_SIZE="256"
        [[ "${DISC_SIZE}" -lt "256" ]] && SWAP_SIZE="${DISC_SIZE}"
        while [[ "${SWAP_PART_SET}" = "" ]]; do
            DIALOG --inputbox "Enter the size (MB) of your swap partition,\nMinimum value is > 0.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "${SWAP_SIZE}" 2>${ANSWER} || return 1
            SWAP_PART_SIZE=$(cat ${ANSWER})
            if [[ "${SWAP_PART_SIZE}" = "" || "${SWAP_PART_SIZE}" = "0" ]]; then
                DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
            else
                if [[ "${SWAP_PART_SIZE}" -ge "${DISC_SIZE}" ]]; then
                    DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                else
                    SWAP_PART_SET=1
                fi
            fi
        done
        DISC_SIZE=$((${DISC_SIZE}-${SWAP_PART_SIZE}))
        ROOT_SIZE="7500"
        [[ "${DISC_SIZE}" -lt "7500" ]] && ROOT_SIZE="${DISC_SIZE}"
        while [[ "${ROOT_PART_SET}" = "" ]]; do
        DIALOG --inputbox "Enter the size (MB) of your / partition,\nthe /home partition will use the remaining space.\n\nDisk space left:  ${DISC_SIZE} MB" 10 65 "${ROOT_SIZE}" 2>${ANSWER} || return 1
        ROOT_PART_SIZE=$(cat ${ANSWER})
            if [[ "${ROOT_PART_SIZE}" = "" || "${ROOT_PART_SIZE}" = "0" ]]; then
                DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
            else
                if [[ "${ROOT_PART_SIZE}" -ge "${DISC_SIZE}" ]]; then
                    DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                else
                    DIALOG --yesno "$((${DISC_SIZE}-${ROOT_PART_SIZE})) MB will be used for your /home partition. Is this OK?" 0 0 && ROOT_PART_SET=1
                fi
            fi
        done
        while [[ "${CHOSEN_FS}" = "" ]]; do
            DIALOG --menu "Select a filesystem for / and /home:" 16 45 8 ${FSOPTS} 2>${ANSWER} || return 1
            FSTYPE=$(cat ${ANSWER})
            DIALOG --yesno "${FSTYPE} will be used for / and /home. Is this OK?" 0 0 && CHOSEN_FS=1
        done
        DEFAULTFS=1
    done
    DIALOG --defaultno --yesno "${DISC} will be COMPLETELY ERASED!  Are you absolutely sure?" 0 0 \
    || return 1
    DEVICE=${DISC}
    # default filesystem specs (the + is bootable flag)
    #  <mountpoint>:<partsize>:<fstype>[:+]:labelname
    FSSPECS="/boot:${BOOT_PART_SIZE}:ext2:+:BOOT_ARCH swap:${SWAP_PART_SIZE}:swap::SWAP_ARCH /:${ROOT_PART_SIZE}:${FSTYPE}::ROOT_ARCH /home:*:${FSTYPE}::HOME_ARCH"

    # validate DEVICE
    if [[ ! -b "${DEVICE}" ]]; then
      DIALOG --msgbox "Device '${DEVICE}' is not valid" 0 0
      return 1
    fi

    # validate DEST
    if [[ ! -d "${DESTDIR}" ]]; then
        DIALOG --msgbox "Destination directory '${DESTDIR}' is not valid" 0 0
        return 1
    fi

    [[ -e /tmp/.fstab ]] && rm -f /tmp/.fstab
    # disable swap and all mounted partitions, umount / last!
    _umountall
    if [[ "${NAME_SCHEME_PARAMETER_RUN}" = "" ]]; then
        set_device_name_scheme || return 1
    fi
    # we assume a /dev/hdX format (or /dev/sdX)
    if [[ "${GUIDPARAMETER}" = "yes" ]]; then
        PART_ROOT="${DEVICE}4"
        # GUID(GPT) is only supported by 'parted'
        printk off
        DIALOG --infobox "Partitioning ${DEVICE}" 0 0
        # clean partitiontable to avoid issues!
        dd if=/dev/zero of=${DEVICE} bs=512 count=2048 >/dev/null 2>&1
        parted -a optimal -s ${DEVICE} mklabel GPT >${LOG}
        parted -a optimal -s ${DEVICE} mkpart 1 1 ${GUID_PART_SIZE} >${LOG}
        parted -a optimal -s ${DEVICE} set 1 bios_grub on
        parted -a optimal -s ${DEVICE} name 1 GRUB2
        parted -a optimal -s ${DEVICE} mkpart 2 ${GUID_PART_SIZE} $((${GUID_PART_SIZE}+${BOOT_PART_SIZE})) >${LOG}
        parted -a optimal -s ${DEVICE} mkpart 3 $((${GUID_PART_SIZE}+${BOOT_PART_SIZE})) $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) >${LOG}
        parted -a optimal -s ${DEVICE} mkpart 4 $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE}+${ROOT_PART_SIZE})) >${LOG}
        parted -a optimal -s ${DEVICE} mkpart 5 $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE}+${ROOT_PART_SIZE})) 100% >${LOG}
    else
        PART_ROOT="${DEVICE}3"
        # start at sector 1 for 4k drive compatibility and correct alignment
        printk off
        DIALOG --infobox "Partitioning ${DEVICE}" 0 0
        # clean partitiontable to avoid issues!
        dd if=/dev/zero of=${DEVICE} bs=512 count=2048 >/dev/null 2>&1
        # create DOS MBR with parted
        parted -s ${DEVICE} mklabel msdos >/dev/null 2>&1
        parted -a optimal -s ${DEVICE} mkpart primary 1 $((${GUID_PART_SIZE}+${BOOT_PART_SIZE})) >${LOG}
        parted -a optimal -s ${DEVICE} toggle 1 boot >${LOG}
        parted -a optimal -s ${DEVICE} mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE})) $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) >${LOG}
        parted -a optimal -s ${DEVICE} mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE}+${ROOT_PART_SIZE})) >${LOG}
        parted -a optimal -s ${DEVICE} mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE}+${ROOT_PART_SIZE})) 100% >${LOG}
    fi
    if [[ $? -gt 0 ]]; then
        DIALOG --msgbox "Error partitioning ${DEVICE} (see ${LOG} for details)" 0 0
        printk on
        return 1
    fi
    printk on
    # wait until /dev initialized correct devices
    udevadm settle
    # need to mount root first, then do it again for the others
    part=1
    [[ "${GUIDPARAMETER}" = "yes" ]] && part=2
    for fsspec in ${FSSPECS}; do
        mountpoint=$(echo ${fsspec} | tr -d ' ' | cut -f1 -d:)
        fstype=$(echo ${fsspec} | tr -d ' ' | cut -f3 -d:)
        labelname=$(echo ${fsspec} | tr -d ' ' | cut -f5 -d:)
        fsoptions="NONE"
        btrfsdevices="${DEVICE}${part}"
        btrfsssd="NONE"
        btrfscompress="NONE"
        btrfssubvolume="NONE"
        btrfslevel="NONE"
        dosubvolume="no"
        if echo ${mountpoint} | tr -d ' ' | grep '^/$' 2>&1 >/dev/null; then
            DIALOG --infobox "Creating ${fstype} on ${DEVICE}${part}" 0 0
            _mkfs yes ${DEVICE}${part} "${fstype}" "${DESTDIR}" "${mountpoint}" "${labelname}" "${fsoptions}" "${btrfsdevices}" "${btrfssubvolume}" "${btrfslevel}" "${dosubvolume}" "${btrfssd}" "${btrfscompress}" || return 1
        fi
        part=$((${part} + 1))
    done

    # make other filesystems
    part=1
    [[ "${GUIDPARAMETER}" = "yes" ]] && part=2
    for fsspec in ${FSSPECS}; do
        mountpoint=$(echo ${fsspec} | tr -d ' ' | cut -f1 -d:)
        fstype=$(echo ${fsspec} | tr -d ' ' | cut -f3 -d:)
        labelname=$(echo ${fsspec} | tr -d ' ' | cut -f5 -d:)
        fsoptions="NONE"
        btrfsdevices="${DEVICE}${part}"
        btrfsssd="NONE"
        btrfscompress="NONE"
        btrfssubvolume="NONE"
        btrfslevel="NONE"
        dosubvolume="no"
        if [[ "$(echo ${mountpoint} | tr -d ' ' | grep '^/$' | wc -l)" -eq 0 ]]; then
            DIALOG --infobox "Creating ${fstype} on ${DEVICE}${part}" 0 0
            _mkfs yes ${DEVICE}${part} "${fstype}" "${DESTDIR}" "${mountpoint}" "${labelname}" "${fsoptions}" "${btrfsdevices}" "${btrfssubvolume}" "${btrfslevel}" "${dosubvolume}" "${btrfssd}" "${btrfscompress}" || return 1
        fi
        part=$((${part} + 1))
    done

    DIALOG --msgbox "Auto-prepare was successful" 0 0
    S_MKFSAUTO=1
}

parted_gpt() {
    
    [[ "$(parted -s ${DISC} print | grep 'Partition Table: gpt')" ]] && GUID_DETECTED=1    
    
    if [[ "${GUID_DETECTED}" = "" ]] ; then
        DIALOG --defaultno --yesno "Setup detected no GUID (gpt) partition table on ${DISC}.\nDo you want to convert the existing MBR table in ${DISC} to a GUID (gpt) partition table?" 0 0 || return 1
        sgdisk --mbrtogpt ${DISC} >${LOG}
    fi
    
    if [[ "${GUID_DETECTED}" = "1" ]]; then
        if [[ "${EFI_x86_64}" = "1" ]] || [[ "${EFI_i386}" = "1" ]]; then
            if ! [[ "$(parted -s ${DISC} print | grep 'boot')" ]]; then
            DIALOG --yesno "Setup detected no EFI SYSTEM PARTITION on ${DISC}.\nDo you want to create an EFISYS partition on ${DISC}?" 0 0 && CREATE_EFISYS=1
            fi
        elif ! [[ "$(parted -s ${DISC} print | grep 'bios_grub')" ]]; then
            DIALOG --yesno "Setup detected no bios_grub flag on ${DISC}.\n\nDo you want to create a small 1MB bios_grub partition for grub2 now on ${DISC}?" 0 0 && CREATE_BIOS_GRUB=1
        fi
    fi
    
    if [[ "${CREATE_EFISYS}" = "1" ]]; then
        DIALOG --msgbox "Setup cannot detect how many partitions already exist on ${DISC}.\nPlease create a 100 to 200 MB FAT32 EFISYS Partition for installing grub2-efi in next step by hand.\n\nparted shell commands:\nmkpartfs <partitionnumber> fat32 <start> <end>\nset <partitionnumber> boot on" 0 0
        parted ${DISC}
    fi
    
    if [[ "${CREATE_BIOS_GRUB}" = "1" && "${GUID_DETECTED}" = "" ]]; then
        # assume new partitiontable,if no GUID was already there,
        # no user interaction needed for bios_grub partition, jippie
        GUID_PART_SIZE="2"
        parted -a optimal -s ${DISC} mkpart 1 1 ${GUID_PART_SIZE} >${LOG}
        parted -a optimal -s ${DISC} set 1 bios_grub on >${LOG}
    else
        [[ "${CREATE_BIOS_GRUB}" = "1" ]] && DIALOG --msgbox "Setup cannot detect how many partitions already exist on ${DISC}.\nPlease create a 1MB bios_grub partition for grub2 in next step by hand.\n\nparted shell commands:\nmkpart <partitionnumber> ext2 <start> <start+1>\nset <partitionnumber> bios_grub on" 0 0
    fi
    DIALOG --msgbox "Now you'll be put into the parted shell where you can partition your hard drive. You should make a swap partition and as many data partitions as you will need.\n\nShort command list:\n- 'help' to get help text\n- 'print' to show  partition table\n- 'mkpart' for new partition\n- 'rm' for deleting a partition\n- 'quit' to leave parted\n\nNOTE: parted may tell you to reboot after creating partitions.  If you need to reboot, just re-enter this install program, skip this step and go on." 18 70
    clear
    parted ${DISC} print
    parted ${DISC}
    
}

partition() {
    # disable swap and all mounted partitions, umount / last!
    _umountall
    # check on encrypted devices, else weird things can happen!
    _stopluks
    # check on raid devices, else weird things can happen during partitioning!
    _stopmd
    # check on lvm devices, else weird things can happen during partitioning!
    _stoplvm
    # update dmraid
    _dmraid_update
    # switch for mbr usage
    set_guid
    # Select disk to partition
    DISCS=$(finddisks _)
    DISCS="${DISCS} OTHER _ DONE +"
    DIALOG --msgbox "Available Disks:\n\n$(_getavaildisks)\n" 0 0
    DISC=""
    while true; do
        # Prompt the user with a list of known disks
        DIALOG --menu "Select the disk you want to partition\n(select DONE when finished)" 14 55 7 ${DISCS} 2>${ANSWER} || return 1
        DISC=$(cat ${ANSWER})
        if [[ "${DISC}" = "OTHER" ]]; then
            DIALOG --inputbox "Enter the full path to the device you wish to partition" 8 65 "/dev/sda" 2>${ANSWER} || DISC=""
            DISC=$(cat ${ANSWER})
        fi
        # Leave our loop if the user is done partitioning
        [[ "${DISC}" = "DONE" ]] && break
        GUID_DETECTED=""
        MSDOS_DETECTED=""
        BIOS_GRUB=""
        CREATE_BIOS_GRUB=""
        if ! [[ "${DISC}" = "" ]]; then
            if [[ "${GUIDPARAMETER}" = "yes" ]]; then
                parted_gpt
            else
                [[ "$(parted ${DISC} print | grep "Partition Table: msdos")" ]] && MSDOS_DETECTED=1
                if [[ "${MSDOS_DETECTED}" = "" ]] ; then
                    DIALOG --defaultno --yesno "Setup detected no MS-DOS partition table on ${DISC}.\nDo you want to create a MS-DOS partition table now on ${DISC}?\n\n${DISC} will be COMPLETELY ERASED!  Are you absolutely sure?" 0 0 || return 1
                    # clean partitiontable to avoid issues!
                    dd if=/dev/zero of=${DEVICE} bs=512 count=2048 >/dev/null 2>&1
                    parted -s ${DISC} mklabel msdos >${LOG}
                fi
                # Partition disc
                DIALOG --msgbox "Now you'll be put into the parted shell where you can partition your hard drive. You should make a swap partition and as many data partitions as you will need.\n\nShort command list:\n- 'help' to get help text\n- 'print' to show  partition table\n- 'mkpart' for new partition\n- 'rm' for deleting a partition\n- 'quit' to leave parted\n\nNOTE: parted may tell you to reboot after creating partitions.  If you need to reboot, just re-enter this install program, skip this step and go on." 18 70
                clear
                parted ${DISC} print
                parted ${DISC}
            fi
        fi
    done
    # update dmraid
    _dmraid_update
    NEXTITEM="3"
    S_PART=1
}

# scan and update btrfs devices
btrfs_scan() {
    btrfs device scan >/dev/null 2>&1
}

# mount btrfs for checks
mount_btrfs() {
    btrfs_scan
    BTRFSMP="$(mktemp -d /tmp/brtfsmp.XXXX)"
    mount ${PART} ${BTRFSMP}
}

# unmount btrfs after checks done
umount_btrfs() {
    umount ${BTRFSMP}
    rm -r ${BTRFSMP}
}

# Set BTRFS_DEVICES on detected btrfs devices
find_btrfs_raid_devices() {
    btrfs_scan
    if [[ "${DETECT_CREATE_FILESYSTEM}" = "no" && "${FSTYPE}" = "btrfs" ]]; then
        for i in $(btrfs filesystem show ${PART} | cut -d " " -f 11); do
            BTRFS_DEVICES="${BTRFS_DEVICES}#${i}"
        done
    fi
}

find_btrfs_raid_bootloader_devices() {
    btrfs_scan
    BTRFS_COUNT=1
    if [[ "$(blkid -c /dev/null ${bootdev} -o value -s TYPE)" = "btrfs" ]]; then
        BTRFS_DEVICES=""
        for i in $(btrfs filesystem show ${bootdev} | cut -d " " -f 11); do
            BTRFS_DEVICES="${BTRFS_DEVICES}#${i}"
            BTRFS_COUNT=$((${BTRFS_COUNT}+1))
        done
    fi
}

# find btrfs subvolume
find_btrfs_subvolume() {
    if [[ "${DETECT_CREATE_FILESYSTEM}" = "no" ]]; then
        # existing btrfs subvolumes
        mount_btrfs
        for i in $(btrfs subvolume list ${BTRFSMP} | cut -d " " -f 7); do
            echo ${i}
            [[ "${1}" ]] && echo ${1}
        done
        umount_btrfs
    fi
}

find_btrfs_bootloader_subvolume() {
    BTRFS_SUBVOLUME_COUNT=1
    if [[ "$(blkid -c /dev/null ${bootdev} -o value -s TYPE)" = "btrfs" ]]; then
        BTRFS_SUBVOLUMES=""
        PART="${bootdev}"
        mount_btrfs
        for i in $(btrfs subvolume list ${BTRFSMP} | cut -d " " -f 7); do
            BTRFS_SUBVOLUMES="${BTRFS_SUBVOLUMES}#${i}"
            BTRFS_SUBVOLUME_COUNT=$((${BTRFS_COUNT}+1))
        done
        umount_btrfs
    fi
}

# subvolumes already in use
subvolumes_in_use() {
    SUBVOLUME_IN_USE=""
    for i in $(grep ${PART}[:#] /tmp/.parts); do
        if [[ "$(echo ${i} | grep ":btrfs:")" ]]; then
            SUBVOLUME_IN_USE="${SUBVOLUME_IN_USE} $(echo ${i} | cut -d: -f 9)"
        fi
    done
}

# ask for btrfs compress option
btrfs_compress() {
    BTRFS_COMPRESS="NONE"
    if [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; then
        DIALOG --defaultno --yesno "Would you like to compress the data on ${PART}?" 0 0 && BTRFS_COMPRESS="compress"
    else
        DIALOG --defaultno --yesno "Would you like to compress the data on ${PART} subvolume=${BTRFS_SUBVOLUME}?" 0 0 && BTRFS_COMPRESS="compress"
    fi
}

# ask for btrfs ssd option
btrfs_ssd() {
    BTRFS_SSD="NONE"
    if [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; then
        DIALOG --defaultno --yesno "Would you like to optimize the data for ssd disk usage on ${PART}?" 0 0 && BTRFS_SSD="ssd"
    else
        DIALOG --defaultno --yesno "Would you like to optimize the data for ssd disk usage on ${PART} subvolume=${BTRFS_SUBVOLUME}?" 0 0 && BTRFS_SSD="ssd"
    fi
}

# values that are only needed for btrfs creation
clear_btrfs_values() {
    : >/tmp/.btrfs-devices
    LABEL_NAME=""
    FS_OPTIONS=""
    BTRFS_DEVICES=""
    BTRFS_LEVEL=""
}

# do not ask for btrfs filesystem creation, if already prepared for creation!
check_btrfs_filesystem_creation() {
    DETECT_CREATE_FILESYSTEM="no"
    SKIP_FILESYSTEM="no"
    SKIP_ASK_SUBVOLUME="no"
    for i in $(grep ${PART}[:#] /tmp/.parts); do
        if [[ "$(echo ${i} | grep ":btrfs:")" ]]; then
            FSTYPE="btrfs"
            SKIP_FILESYSTEM="yes"
            # check on filesystem creation, skip subvolume asking then!
            [[ "$(echo ${i} | cut -d: -f 4 | grep yes)" ]] && DETECT_CREATE_FILESYSTEM="yes"
            [[ "${DETECT_CREATE_FILESYSTEM}" = "yes" ]] && SKIP_ASK_SUBVOLUME="yes"
        fi
    done
}

# remove devices with no subvolume from list and generate raid device list
btrfs_parts() {
     if [[ -s /tmp/.btrfs-devices ]]; then
         BTRFS_DEVICES=""
         for i in $(cat /tmp/.btrfs-devices); do
             BTRFS_DEVICES="${BTRFS_DEVICES}#${i}"
             # remove device if no subvolume is used!
             [[ "${BTRFS_SUBVOLUME}" = "NONE"  ]] && PARTS="$(echo ${PARTS} | sed -e "s#${i}\ _##g")"
         done
     else
         [[ "${BTRFS_SUBVOLUME}" = "NONE"  ]] && PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
     fi
}

# choose raid level to use on btrfs device
btrfs_raid_level() {
    BTRFS_RAIDLEVELS="NONE - raid0 - raid1 - raid10 - single -"
    BTRFS_RAID_FINISH=""
    BTRFS_LEVEL=""
    BTRFS_DEVICE="${PART}"
    : >/tmp/.btrfs-devices
    DIALOG --msgbox "BTRFS RAID OPTIONS:\n\nBTRFS has options to control the raid configuration for data and metadata.\nValid choices are raid0, raid1, raid10 and single.\nsingle means that no duplication of metadata is done, which may be desired when using hardware raid. raid10 requires at least 4 devices.\n\nIf you don't need this feature select NONE." 0 0
    while [[ "${BTRFS_RAID_FINISH}" != "DONE" ]]; do
        DIALOG --menu "Select the raid level you want to use" 21 50 9 ${BTRFS_RAIDLEVELS} 2>${ANSWER} || return 1
        BTRFS_LEVEL=$(cat ${ANSWER})
        if [[ "${BTRFS_LEVEL}" = "NONE" ]]; then
            echo "${BTRFS_DEVICE}" >>/tmp/.btrfs-devices
            break
        else
            # take selected device as 1st device, add additional devices in part below.
            select_btrfs_raid_devices
        fi
    done
}

# select btrfs raid devices
select_btrfs_raid_devices () {
    # show all devices with sizes
    # DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)" 0 0
    # select the second device to use, no missing option available!
    : >/tmp/.btrfs-devices
    BTRFS_PART="${BTRFS_DEVICE}"
    BTRFS_PARTS="${PARTS}"
    echo "${BTRFS_PART}" >>/tmp/.btrfs-devices
    BTRFS_PARTS="$(echo ${BTRFS_PARTS} | sed -e "s#${BTRFS_PART}\ _##g")"
    RAIDNUMBER=2
    DIALOG --menu "Select device ${RAIDNUMBER}" 21 50 13 ${BTRFS_PARTS} 2>${ANSWER} || return 1
    BTRFS_PART=$(cat ${ANSWER})
    echo "${BTRFS_PART}" >>/tmp/.btrfs-devices
    while [[ "${BTRFS_PART}" != "DONE" ]]; do
        BTRFS_DONE=""
        RAIDNUMBER=$((${RAIDNUMBER} + 1))
        # RAID10 need 4 devices!
        [[ "${RAIDNUMBER}" -ge 3 && ! "${BTRFS_LEVEL}" = "raid10" ]] && BTRFS_DONE="DONE _"
        [[ "${RAIDNUMBER}" -ge 5 && "${BTRFS_LEVEL}" = "raid10" ]] && BTRFS_DONE="DONE _"
        # clean loop from used partition and options
        BTRFS_PARTS="$(echo ${BTRFS_PARTS} | sed -e "s#${BTRFS_PART}\ _##g")"
        # add more devices
        DIALOG --menu "Select device ${RAIDNUMBER}" 21 50 13 ${BTRFS_PARTS} ${BTRFS_DONE} 2>${ANSWER} || return 1
        BTRFS_PART=$(cat ${ANSWER})
        [[ "${BTRFS_PART}" = "DONE" ]] && break
        echo "${BTRFS_PART}" >>/tmp/.btrfs-devices
     done
     # final step ask if everything is ok?
     DIALOG --yesno "Would you like to create btrfs raid like this?\n\nLEVEL:\n${BTRFS_LEVEL}\n\nDEVICES:\n$(for i in $(cat /tmp/.btrfs-devices); do echo "${i}\n"; done)" 0 0 && BTRFS_RAID_FINISH="DONE"
}

# prepare new btrfs device
prepare_btrfs() {
    btrfs_raid_level || return 1
    prepare_btrfs_subvolume || return 1
}

# prepare btrfs subvolume
prepare_btrfs_subvolume() {
    DOSUBVOLUME="no"
    BTRFS_SUBVOLUME="NONE"
    if [[ "${SKIP_ASK_SUBVOLUME}" = "no" ]]; then
        DIALOG --defaultno --yesno "Would you like to create a new subvolume on ${PART}?" 0 0 && DOSUBVOLUME="yes"
    else
        DOSUBVOLUME="yes"
    fi
    if [[ "${DOSUBVOLUME}" = "yes" ]]; then
        BTRFS_SUBVOLUME="NONE"
        while [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; do
            DIALOG --inputbox "Enter the SUBVOLUME name for the device, keep it short\nand use no spaces or special\ncharacters." 10 65 2>${ANSWER} || return 1
            BTRFS_SUBVOLUME=$(cat ${ANSWER})
            check_btrfs_subvolume
        done
    else
        BTRFS_SUBVOLUME="NONE"
    fi
}

# check btrfs subvolume
check_btrfs_subvolume(){
    [[ "${DOMKFS}" = "yes" && "${FSTYPE}" = "btrfs" ]] && DETECT_CREATE_FILESYSTEM="yes"
    if [[ "${DETECT_CREATE_FILESYSTEM}" = "no" ]]; then
        mount_btrfs
        for i in $(btrfs subvolume list ${BTRFSMP} | cut -d " " -f 7); do
            if [[ "$(echo ${i} | grep "${BTRFS_SUBVOLUME}"$)" ]]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical SUBVOLUME names or an empty name! Please enter another name." 8 65
                BTRFS_SUBVOLUME="NONE"
            fi
        done
        umount_btrfs
    else
        subvolumes_in_use
        if [[ "$(echo ${SUBVOLUME_IN_USE} | egrep "${BTRFS_SUBVOLUME}")" ]]; then
            DIALOG --msgbox "ERROR: You have defined 2 identical SUBVOLUME names or an empty name! Please enter another name." 8 65
            BTRFS_SUBVOLUME="NONE"
        fi
    fi
}

# create btrfs subvolume
create_btrfs_subvolume() {
    mount_btrfs
    btrfs subvolume create ${BTRFSMP}/${_btrfssubvolume} >${LOG}
    # change permission from 700 to 755 
    # to avoid warnings during package installation
    chmod 755 ${BTRFSMP}/${_btrfssubvolume}
    umount_btrfs
}

# choose btrfs subvolume from list
choose_btrfs_subvolume () {
    BTRFS_SUBVOLUME="NONE"
    SUBVOLUMES_DETECTED="no"
    SUBVOLUMES=$(find_btrfs_subvolume _)
    # check if subvolumes are present
    [[ -n "${SUBVOLUMES}" ]] && SUBVOLUMES_DETECTED="yes"
    subvolumes_in_use
    for i in ${SUBVOLUME_IN_USE}; do
        SUBVOLUMES=$(echo ${SUBVOLUMES} | sed -e "s#${i}\ _##g")
    done
    if [[ -n "${SUBVOLUMES}" ]] ; then
        DIALOG --menu "Select the subvolume to mount" 21 50 13 ${SUBVOLUMES} 2>${ANSWER} || return 1
        BTRFS_SUBVOLUME=$(cat ${ANSWER})
    else
        if [[ "${SUBVOLUMES_DETECTED}" = "yes" ]]; then
            DIALOG --msgbox "ERROR: All subvolumes of the device are already in use. Switching to create a new one now." 8 65
            SKIP_ASK_SUBVOLUME=yes
            prepare_btrfs_subvolume || return 1
        fi
    fi
}

# boot on btrfs subvolume is not supported
check_btrfs_boot_subvolume() {
    if [[ "${MP}" = "/boot" && "${FSTYPE}" = "btrfs" && ! "${BTRFS_SUBVOLUME}" = "NONE" ]] ; then
        DIALOG --msgbox "ERROR: \n/boot on a btrfs subvolume is not supported by any bootloader yet!" 8 65
        FILESYSTEM_FINISH="no"
    fi
}

# btrfs subvolume menu
btrfs_subvolume() {
    FILESYSTEM_FINISH=""
    if [[ "${FSTYPE}" = "btrfs" && "${DOMKFS}" = "no" ]]; then
        if [[ "${ASK_MOUNTPOINTS}" = "1" ]]; then
            # create subvolume if requested
            # choose btrfs subvolume if present
            prepare_btrfs_subvolume || return 1
            if [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; then
                choose_btrfs_subvolume || return 1
            fi
        else
            # use device if no subvolume is present
            choose_btrfs_subvolume || return 1
        fi
        btrfs_compress
        btrfs_ssd
    fi
    FILESYSTEM_FINISH="yes"
}

select_filesystem() {
    FILESYSTEM_FINISH=""
    # btrfs is not well supported by LTS .32 kernel
    # don't allow vfat as / filesystem, it will not work!
    # don't allow ntfs as / filesystem, this is stupid!
    FSOPTS=""
    [[ "$(which mkfs.ext2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext2 Ext2"
    [[ "$(which mkfs.ext3 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext3 Ext3"
    [[ "$(which mkfs.ext4 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext4 Ext4"
    [[ "$(which mkfs.btrfs 2>/dev/null)" && "${KERNELPKG}" = "kernel26" ]] && FSOPTS="${FSOPTS} btrfs Btrfs-(Experimental)"
    [[ "$(which mkfs.nilfs2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} nilfs2 Nilfs2-(Experimental)"
    [[ "$(which mkreiserfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} reiserfs Reiser3"
    [[ "$(which mkfs.xfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} xfs XFS"
    [[ "$(which mkfs.jfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} jfs JFS"
    [[ "$(which mkfs.ntfs 2>/dev/null)" && "${DO_ROOT}" = "DONE" ]] && FSOPTS="${FSOPTS} ntfs-3g NTFS"
    [[ "$(which mkfs.vfat 2>/dev/null)" && "${DO_ROOT}" = "DONE" ]] && FSOPTS="${FSOPTS} vfat VFAT"
    DIALOG --menu "Select a filesystem for ${PART}" 21 50 13 ${FSOPTS} 2>${ANSWER} || return 1
    FSTYPE=$(cat ${ANSWER})
}

enter_mountpoint() {
    FILESYSTEM_FINISH=""
    MP=""
    while [[ "${MP}" = "" ]]; do
        DIALOG --inputbox "Enter the mountpoint for ${PART}" 8 65 "/boot" 2>${ANSWER} || return 1
        MP=$(cat ${ANSWER})
        if grep ":${MP}:" /tmp/.parts; then
            DIALOG --msgbox "ERROR: You have defined 2 identical mountpoints! Please select another mountpoint." 8 65
            MP=""
        fi
    done
}

# set sane values for paramaters, if not already set
check_mkfs_values() {
    # Set values, to not confuse mkfs call!
    [[ "${FS_OPTIONS}" = "" ]] && FS_OPTIONS="NONE"
    [[ "${BTRFS_DEVICES}" = "" ]] && BTRFS_DEVICES="NONE"
    [[ "${BTRFS_LEVEL}" = "" ]] && BTRFS_LEVEL="NONE"
    [[ "${BTRFS_SUBVOLUME}" = "" ]] && BTRFS_SUBVOLUME="NONE"
    [[ "${DOSUBVOLUME}" = "" ]] && DOSUBVOLUME="no"
    [[ "${LABEL_NAME}" = "" && -n "$(blkid -c=/dev/null -o value -s LABEL ${PART})" ]] && LABEL_NAME="$(blkid -c=/dev/null -o value -s LABEL ${PART})"
    [[ "${LABEL_NAME}" = "" ]] && LABEL_NAME="NONE"
}

create_filesystem() {
    FILESYSTEM_FINISH=""
    LABEL_NAME=""
    FS_OPTIONS=""
    BTRFS_DEVICES=""
    BTRFS_LEVEL=""
    DIALOG --yesno "Would you like to create a filesystem on ${PART}?\n\n(This will overwrite existing data!)" 0 0 && DOMKFS="yes"
    if [[ "${DOMKFS}" = "yes" ]]; then
        while [[ "${LABEL_NAME}" = "" ]]; do
            DIALOG --inputbox "Enter the LABEL name for the device, keep it short\n(not more than 12 characters) and use no spaces or special\ncharacters." 10 65 \
            "$(blkid -c=/dev/null -o value -s LABEL ${PART})" 2>${ANSWER} || return 1
            LABEL_NAME=$(cat ${ANSWER})
            if grep ":${LABEL_NAME}$" /tmp/.parts; then
                DIALOG --msgbox "ERROR: You have defined 2 identical LABEL names! Please enter another name." 8 65
                LABEL_NAME=""
            fi
        done
        if [[ "${FSTYPE}" = "btrfs" ]]; then
            prepare_btrfs || return 1
            btrfs_compress
            btrfs_ssd
        fi
        DIALOG --inputbox "Enter additional options to the filesystem creation utility.\nUse this field only, if the defaults are not matching your needs,\nelse just leave it empty." 10 70  2>${ANSWER} || return 1
        FS_OPTIONS=$(cat ${ANSWER})
    fi
    FILESYSTEM_FINISH="yes"
}

mountpoints() {
    NAME_SCHEME_PARAMETER_RUN=""
    while [[ "${PARTFINISH}" != "DONE" ]]; do
        activate_special_devices
        : >/tmp/.device-names
        : >/tmp/.fstab
        : >/tmp/.parts
        #
        # Select mountpoints
        #
        DIALOG --msgbox "Available partitions:\n\n$(_getavailpartitions)\n" 0 0
        PARTS=$(findpartitions _)
        DO_SWAP=""
        while [[ "${DO_SWAP}" != "DONE" ]]; do
            FSTYPE="swap"
            DIALOG --menu "Select the partition to use as swap" 21 50 13 NONE - ${PARTS} 2>${ANSWER} || return 1
            PART=$(cat ${ANSWER})
            if [[ "${PART}" != "NONE" ]]; then
                DOMKFS="no"
                if [[ "${ASK_MOUNTPOINTS}" = "1" ]]; then
                    create_filesystem
                else
                    FILESYSTEM_FINISH="yes"
                fi
            else
                FILESYSTEM_FINISH="yes"
            fi
            [[ "${FILESYSTEM_FINISH}" = "yes" ]] && DO_SWAP=DONE
        done
        check_mkfs_values
        if [[ "${PART}" != "NONE" ]]; then
            PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
            echo "${PART}:swap:swap:${DOMKFS}:${LABEL_NAME}:${FS_OPTIONS}:${BTRFS_DEVICES}:${BTRFS_LEVEL}:${BTRFS_SUBVOLUME}:${DOSUBVOLUME}:${BTRFS_COMPRESS}:${BTRFS_SSD}" >>/tmp/.parts
        fi
        DO_ROOT=""
        while [[ "${DO_ROOT}" != "DONE" ]]; do
            DIALOG --menu "Select the partition to mount as /" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
            PART=$(cat ${ANSWER})
            PART_ROOT=${PART}
            # Select root filesystem type
            FSTYPE="$(blkid -c=/dev/null -o value -s TYPE ${PART})"
            DOMKFS="no"
            # clear values first!
            clear_btrfs_values
            check_btrfs_filesystem_creation
            if [[ "${ASK_MOUNTPOINTS}" = "1" && "${SKIP_FILESYSTEM}" = "no" ]]; then
                select_filesystem && create_filesystem && btrfs_subvolume
            else                   
                btrfs_subvolume
            fi
            [[ "${FILESYSTEM_FINISH}" = "yes" ]] && DO_ROOT=DONE
        done
        find_btrfs_raid_devices
        btrfs_parts
        check_mkfs_values
        echo "${PART}:${FSTYPE}:/:${DOMKFS}:${LABEL_NAME}:${FS_OPTIONS}:${BTRFS_DEVICES}:${BTRFS_LEVEL}:${BTRFS_SUBVOLUME}:${DOSUBVOLUME}:${BTRFS_COMPRESS}:${BTRFS_SSD}" >>/tmp/.parts
        ! [[ "${FSTYPE}" = "btrfs" ]] && PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
        #
        # Additional partitions
        #
        while [[ "${PART}" != "DONE" ]]; do
            DO_ADDITIONAL=""
            while [[ "${DO_ADDITIONAL}" != "DONE" ]]; do
                DIALOG --menu "Select any additional partitions to mount under your new root (select DONE when finished)" 21 52 13 ${PARTS} DONE _ 2>${ANSWER} || return 1
                PART=$(cat ${ANSWER})
                if [[ "${PART}" != "DONE" ]]; then
                    FSTYPE="$(blkid -c=/dev/null -o value -s TYPE ${PART})"
                    DOMKFS="no"
                    # clear values first!
                    clear_btrfs_values
                    check_btrfs_filesystem_creation
                    # Select a filesystem type
                    if [[ "${ASK_MOUNTPOINTS}" = "1" && "${SKIP_FILESYSTEM}" = "no" ]]; then
                        enter_mountpoint && select_filesystem && create_filesystem && btrfs_subvolume
                    else
                        enter_mountpoint
                        btrfs_subvolume
                    fi
                    check_btrfs_boot_subvolume
                else
                    FILESYSTEM_FINISH="yes"
                fi
                [[ "${FILESYSTEM_FINISH}" = "yes" ]] && DO_ADDITIONAL="DONE"
            done
            if [[ "${PART}" != "DONE" ]]; then
                find_btrfs_raid_devices
                btrfs_parts
                check_mkfs_values
                echo "${PART}:${FSTYPE}:${MP}:${DOMKFS}:${LABEL_NAME}:${FS_OPTIONS}:${BTRFS_DEVICES}:${BTRFS_LEVEL}:${BTRFS_SUBVOLUME}:${DOSUBVOLUME}:${BTRFS_COMPRESS}:${BTRFS_SSD}" >>/tmp/.parts
                ! [[ "${FSTYPE}" = "btrfs" ]] && PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
            fi
        done
        DIALOG --yesno "Would you like to create and mount the filesytems like this?\n\nSyntax\n------\nDEVICE:TYPE:MOUNTPOINT:FORMAT:LABEL:FSOPTIONS:BTRFS_DETAILS\n\n$(for i in $(cat /tmp/.parts | sed -e 's, ,#,g'); do echo "${i}\n";done)" 0 0 && PARTFINISH="DONE"
    done
    # disable swap and all mounted partitions
    _umountall
    if [[ "${NAME_SCHEME_PARAMETER_RUN}" = "" ]]; then
        set_device_name_scheme || return 1
    fi
    for line in $(cat /tmp/.parts); do
        PART=$(echo ${line} | cut -d: -f 1)
        FSTYPE=$(echo ${line} | cut -d: -f 2)
        MP=$(echo ${line} | cut -d: -f 3)
        DOMKFS=$(echo ${line} | cut -d: -f 4)
        LABEL_NAME=$(echo ${line} | cut -d: -f 5)
        FS_OPTIONS=$(echo ${line} | cut -d: -f 6)
        BTRFS_DEVICES=$(echo ${line} | cut -d: -f 7)
        BTRFS_LEVEL=$(echo ${line} | cut -d: -f 8)
        BTRFS_SUBVOLUME=$(echo ${line} | cut -d: -f 9)
        DOSUBVOLUME=$(echo ${line} | cut -d: -f 10)
        BTRFS_COMPRESS=$(echo ${line} | cut -d: -f 11)
        BTRFS_SSD=$(echo ${line} | cut -d: -f 12)
        if [[ "${DOMKFS}" = "yes" ]]; then
            if [[ "${FSTYPE}" = "swap" ]]; then
                DIALOG --infobox "Creating and activating swapspace on ${PART}" 0 0
            else
                DIALOG --infobox "Creating ${FSTYPE} on ${PART}, mounting to ${DESTDIR}${MP}" 0 0
            fi
            _mkfs yes ${PART} ${FSTYPE} ${DESTDIR} ${MP} ${LABEL_NAME} ${FS_OPTIONS} ${BTRFS_DEVICES} ${BTRFS_LEVEL} ${BTRFS_SUBVOLUME} ${DOSUBVOLUME} ${BTRFS_COMPRESS} ${BTRFS_SSD} || return 1
        else
            if [[ "${FSTYPE}" = "swap" ]]; then
                DIALOG --infobox "Activating swapspace on ${PART}" 0 0
            else
                DIALOG --infobox "Mounting ${FSTYPE} on ${PART} to ${DESTDIR}${MP}" 0 0
            fi
            _mkfs no ${PART} ${FSTYPE} ${DESTDIR} ${MP} ${LABEL_NAME} ${FS_OPTIONS} ${BTRFS_DEVICES} ${BTRFS_LEVEL} ${BTRFS_SUBVOLUME} ${DOSUBVOLUME} ${BTRFS_COMPRESS} ${BTRFS_SSD} || return 1
        fi
        sleep 1
    done

    DIALOG --msgbox "Partitions were successfully mounted." 0 0
    NEXTITEM="5"
    S_MKFS=1
}

# _mkfs()
# Create and mount filesystems in our destination system directory.
#
# args:
#  domk: Whether to make the filesystem or use what is already there
#  device: Device filesystem is on
#  fstype: type of filesystem located at the device (or what to create)
#  dest: Mounting location for the destination system
#  mountpoint: Mount point inside the destination system, e.g. '/boot'

# returns: 1 on failure
_mkfs() {
    local _domk=${1}
    local _device=${2}
    local _fstype=${3}
    local _dest=${4}
    local _mountpoint=${5}
    local _labelname=${6}
    local _fsoptions=${7}
    local _btrfsdevices="$(echo ${8} | sed -e 's|#| |g')"
    local _btrfslevel=${9}
    local _btrfssubvolume=${10}
    local _dosubvolume=${11}
    local _btrfscompress=${12}
    local _btrfsssd=${13}
    # correct empty entries
    [[ "${_fsoptions}" = "NONE" ]] && _fsoptions=""
    [[ "${_btrfsssd}" = "NONE" ]] && _btrfsssd=""
    [[ "${_btrfscompress}" = "NONE" ]] && _btrfscompress=""
    [[ "${_btrfssubvolume}" = "NONE" ]] && _btrfssubvolume=""
    # add btrfs raid level, if needed
    [[ ! "${_btrfslevel}" = "NONE" && "${_fstype}" = "btrfs" ]] && _fsoptions="${_fsoptions} -d ${_btrfslevel}"
    # we have two main cases: "swap" and everything else.
    if [[ "${_fstype}" = "swap" ]]; then
        swapoff ${_device} >/dev/null 2>&1
        if [[ "${_domk}" = "yes" ]]; then
            mkswap -L ${_labelname} ${_device} >${LOG} 2>&1
            if [[ $? != 0 ]]; then
                DIALOG --msgbox "Error creating swap: mkswap ${_device}" 0 0
                return 1
            fi
        fi
        swapon ${_device} >${LOG} 2>&1
        if [[ $? != 0 ]]; then
            DIALOG --msgbox "Error activating swap: swapon ${_device}" 0 0
            return 1
        fi
    else
        # make sure the fstype is one we can handle
        local knownfs=0
        for fs in xfs jfs reiserfs ext2 ext3 ext4 btrfs nilfs2 ntfs-3g vfat; do
            [[ "${_fstype}" = "${fs}" ]] && knownfs=1 && break
        done
        if [[ ${knownfs} -eq 0 ]]; then
            DIALOG --msgbox "unknown fstype ${_fstype} for ${_device}" 0 0
            return 1
        fi
        # if we were tasked to create the filesystem, do so
        if [[ "${_domk}" = "yes" ]]; then
            local ret
            case ${_fstype} in
                xfs)      mkfs.xfs ${_fsoptions} -L ${_labelname} -f ${_device} >${LOG} 2>&1; ret=$? ;;
                jfs)      yes | mkfs.jfs ${_fsoptions} -L ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
                reiserfs) yes | mkreiserfs ${_fsoptions} -l ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
                ext2)     mkfs.ext2 -L ${_fsoptions} ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
                ext3)     mke2fs ${_fsoptions} -L ${_labelname} -t ext3 ${_device} >${LOG} 2>&1; ret=$? ;;
                ext4)     mke2fs ${_fsoptions} -L ${_labelname} -t ext4 ${_device} >${LOG} 2>&1; ret=$? ;;
                btrfs)    mkfs.btrfs ${_fsoptions} -L ${_labelname} ${_btrfsdevices} >${LOG} 2>&1; ret=$? ;;
                nilfs2)   mkfs.nilfs2 ${_fsoptions} -L ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
                ntfs-3g)  mkfs.ntfs ${_fsoptions} -L ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
                vfat)     mkfs.vfat ${_fsoptions} -n ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
                # don't handle anything else here, we will error later
            esac
            if [[ ${ret} != 0 ]]; then
                DIALOG --msgbox "Error creating filesystem ${_fstype} on ${_device}" 0 0
                return 1
            fi
            sleep 2
        fi
        if [[ "${_fstype}" = "btrfs" && -n "${_btrfssubvolume}" && "${_dosubvolume}" = "yes" ]]; then
            create_btrfs_subvolume
        fi
        btrfs_scan
        sleep 2
        # create our mount directory
        mkdir -p ${_dest}${_mountpoint}
        # prepare btrfs mount options
        _btrfsmountoptions=""
        [[ -n "${_btrfssubvolume}" ]] && _btrfsmountoptions="subvol=${_btrfssubvolume}"
        [[ -n "${_btrfscompress}" ]] && _btrfsmountoptions="${_btrfsmountoptions} ${_btrfscompress}"
        [[ -n "${_btrfsssd}" ]] && _btrfsmountoptions="${_btrfsmountoptions} ${_btrfsssd}"
        _btrfsmountoptions="$(echo ${_btrfsmountoptions} | sed -e 's#^ ##g' | sed -e 's# #,#g')"
        # mount the bad boy
        if [[ "${_fstype}" = "btrfs" && -n "${_btrfsmountoptions}" ]]; then
            mount -t ${_fstype} -o ${_btrfsmountoptions} ${_device} ${_dest}${_mountpoint} >${LOG} 2>&1
        else
            mount -t ${_fstype} ${_device} ${_dest}${_mountpoint} >${LOG} 2>&1
        fi
        if [[ $? != 0 ]]; then
            DIALOG --msgbox "Error mounting ${_dest}${_mountpoint}" 0 0
            return 1
        fi
        # change permission of base directories to correct permission
        # to avoid btrfs issues
        if [[ "${_mountpoint}" = "/tmp" ]]; then
            chmod 1777 ${_dest}${_mountpoint}
        elif [[ "${_mountpoint}" = "/root" ]]; then
            chmod 750 ${_dest}${_mountpoint}
        else
            chmod 755 ${_dest}${_mountpoint}
        fi
    fi
    # add to .device-names for config files
    local _uuid="$(getuuid ${_device})"
    local _label="$(getlabel ${_device})"
    echo "# DEVICE DETAILS: ${_device} UUID=${_uuid} LABEL=${_label}" >> /tmp/.device-names
    # add to temp fstab
    if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" ]]; then
        if [[ -n "${_uuid}" ]]; then
            _device="UUID=${_uuid}"
        fi
    elif [[ "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
        if [[ -n "${_label}" ]]; then
            _device="LABEL=${_label}"
        fi
    fi
    if [[ "${_fstype}" = "btrfs" && -n "${_btrfsmountoptions}" ]]; then
        echo -n "${_device} ${_mountpoint} ${_fstype} defaults,${_btrfsmountoptions} 0 " >>/tmp/.fstab
    else
        echo -n "${_device} ${_mountpoint} ${_fstype} defaults 0 " >>/tmp/.fstab
    fi
    if [[ "${_fstype}" = "swap" ]]; then
        echo "0" >>/tmp/.fstab
    else
        echo "1" >>/tmp/.fstab
    fi
}

# source_set()
# check if installation source is set, if not run select_source!
source_set(){
    while ! [[ "${S_SRC}" = "1" ]]; do
        if ! [[ "${S_SRC}" = "1" ]]; then
            DIALOG --msgbox "Error:\nYou have to select Source first." 0 0
            select_source || break
        fi
    done
    if [[ "${S_SRC}" = "0" ]]; then
        return 1
    fi
}

getsource() {
    S_SRC=0
    if [[ "${MODE}" = "media" ]]; then
        get_media
        #last fallback, if autodetection fails!
        manual_media || return 1
    fi

    if [[ "${MODE}" = "ftp" ]]; then
        #in order to cache packages from media check on it first!
        get_media
        select_mirror || return 1
        NEXTITEM="2"
    fi
    S_SRC=1
}

# select_mirror()
# Prompt user for preferred mirror and set ${SYNC_URL}
#
# args: none
# returns: nothing
select_mirror() {
    DIALOG --msgbox "Keep in mind ftp.archlinux.org is throttled.\nPlease select another mirror to get full download speed." 8 65
    # FIXME: this regex doesn't honor commenting
    MIRRORS=$(egrep -o '((ftp)|(http))://[^/]*' "${MIRRORLIST}" | sed 's|$| _|g')
    DIALOG --menu "Select an FTP/HTTP mirror" 14 55 7 \
        ${MIRRORS} \
        "Custom" "_" 2>${ANSWER} || return 1
    local _server=$(cat ${ANSWER})
    if [[ "${_server}" = "Custom" ]]; then
        DIALOG --inputbox "Enter the full URL to core repo." 8 65 \
            "ftp://ftp.archlinux.org/core/os/$(uname -m)" 2>${ANSWER} || return 1
            SYNC_URL=$(cat ${ANSWER})
    else
        # Form the full URL for our mirror by grepping for the server name in
        # our mirrorlist and pulling the full URL out. Substitute 'core' in
        # for the repository name, and ensure that if it was listed twice we
        # only return one line for the mirror.
        SYNC_URL=$(egrep -o "${_server}.*" "${MIRRORLIST}" | head -n1)
    fi
    echo "Using mirror: ${SYNC_URL}" >${LOG}
}

# pacman_conf()
# creates temporary pacman.conf file
pacman_conf() {
    if [[ "${MODE}" = "media" ]]; then
        local serverurl="${FILE_URL}"
    elif [[ "${MODE}" = "ftp" ]]; then
        local serverurl="${SYNC_URL}"
    fi
    # Setup a pacman.conf in /tmp
    cat << EOF > /tmp/pacman.conf
[options]
Architecture = auto
CacheDir = ${DESTDIR}/var/cache/pacman/pkg
CacheDir = /src/core-$(uname -m)/pkg
CacheDir = /src/core-any/pkg

[core]
Server = ${serverurl}

[extra]
Server = ${serverurl}
EOF
}

# configures pacman and syncs db on destination system
# params: none
# returns: 1 on error
prepare_pacman() {
    # Set up the necessary directories for pacman use
    [[ ! -d "${DESTDIR}/var/cache/pacman/pkg" ]] && mkdir -m 755 -p "${DESTDIR}/var/cache/pacman/pkg"
    [[ ! -d "${DESTDIR}/var/lib/pacman" ]] && mkdir -m 755 -p "${DESTDIR}/var/lib/pacman"

    DIALOG --infobox "Refreshing package database..." 6 45
    ${PACMAN} -Sy >${LOG} 2>&1 || return 1
    if [[ $? -ne 0 ]]; then
        DIALOG --msgbox "Pacman preparation failed! Check ${LOG} for errors." 6 60
        return 1
    fi
    return 0
}

# Set PACKAGES parameter before running to install wanted packages
run_pacman(){
    # create chroot environment on target system
    # code straight from mkarchroot
    chroot_mount

    # execute pacman in a subshell so we can follow its progress
    # pacman output goes /tmp/pacman.log
    # /tmp/setup-pacman-running acts as a lockfile
    ( \
        echo "Installing Packages..." >/tmp/pacman.log ; \
        echo >>/tmp/pacman.log ; \
        touch /tmp/setup-pacman-running ; \
        ${PACMAN} -S ${PACKAGES} 2>&1 >> /tmp/pacman.log ; \
        echo $? > /tmp/.pacman-retcode ; \
        if [[ $(cat /tmp/.pacman-retcode) -ne 0 ]]; then
            echo -e "\nPackage Installation FAILED." >>/tmp/pacman.log
        else
            echo -e "\nPackage Installation Complete." >>/tmp/pacman.log
        fi
        rm /tmp/setup-pacman-running
    ) &

    # display pacman output while it's running
    sleep 2
    dialog --backtitle "${TITLE}" --title " Installing... Please Wait " \
        --no-kill --tailboxbg "/tmp/pacman.log" 18 70 2>${ANSWER}
    while [[ -f /tmp/setup-pacman-running ]]; do
        sleep 1
    done
    kill $(cat ${ANSWER})

    # pacman finished, display scrollable output
    local _result=''
    if [[ $(cat /tmp/.pacman-retcode) -ne 0 ]]; then
        _result="Installation Failed (see errors below)"
    else
        _result="Installation Complete"
    fi
    rm /tmp/.pacman-retcode
    DIALOG --title "${_result}" --exit-label "Continue" \
        --textbox "/tmp/pacman.log" 18 70 || return 1
    # ensure the disk is synced
    sync
    chroot_umount
}

# select_packages()
# prompts the user to select packages to install
#
# params: none
# returns: 1 on error
select_packages() {
    source_set || return 1
    pacman_conf
    prepare_pacman
    # Archboot setup media Mode uses packages.txt!
    if [[ "${MODE}" = "media" ]]; then
        DIALOG --msgbox "Package selection is split into two stages.  First you will select package categories that contain packages you may be interested in.  Then you will be presented with a full list of packages in your selected categories, allowing you to fine-tune your selection.\n\nNOTE: It is recommended that you install the BASE category from this setup, SUPPORT contains additional useful packages for networking and filesystems, DEVEL contains software building tools." 18 70
        PKGS="/src/core-$(uname -m)/pkg/packages.txt"
        if ! [[ -s /tmp/.pkgcategory ]]; then
            CHKLIST="base ^ ON"
            for category in $(cat ${PKGS} | sed 's|/.*$||g' | uniq | grep -v base | grep -v kernels); do
                CHKLIST="${CHKLIST} ${category} - OFF"
            done
        else
            CHKLIST=
            for i in $(cat /tmp/.pkgcategory | sed 's|\"||g'); do
                CHKLIST="${CHKLIST} ${i} ^ ON"
            done
            for category in $(cat ${PKGS} | sed 's|/.*$||g' | uniq | grep -v kernels); do
                grep ${category} /tmp/.pkgcategory >/dev/null 2>&1 || CHKLIST="${CHKLIST} ${category} - OFF"
            done
        fi
        DIALOG --checklist "Select Package Categories" 19 55 12 ${CHKLIST} 2>/tmp/.pkgcategory || return 1
        SELECTALL="no"
        DIALOG --yesno "Select all packages by default?" 0 0 && SELECTALL="yes"
        CHKLIST=
        for category in $(cat /tmp/.pkgcategory | sed 's|"||g'); do
            tag="OFF"
            if [[ "${SELECTALL}" = "yes" ]]; then
                tag="ON"
            fi
            list=$(cat ${PKGS} | grep "${category}/" | sed 's|^[a-z0-9-]*/||g' | sed "s|.pkg.tar.*$| (${category}) ${tag}|g" | sort)
            CHKLIST="${CHKLIST} ${list}"
            tag="OFF"
        done
        DIALOG --checklist "Select Packages to install. Use SPACE to select." 19 60 12 ${CHKLIST} 2>/tmp/.pkglist || return 1
        # fix pacman list!
        PACKAGES=
        sed -i -e 's/-i686//g' -e 's/-x86_64//g' -e 's/-any//g' -e 's/"//g' /tmp/.pkglist
        for pkg in $(cat /tmp/.pkglist); do
            pkgname=${pkg%-*-*}
            PACKAGES="${PACKAGES} ${pkgname}"
        done
    # Use default ftp install routine from arch livecd
    else
        # if selection has been done before, warn about loss of input
        # and let the user exit gracefully
        if [[ ${S_SELECT} -ne 0 ]]; then
            DIALOG --yesno "WARNING: Running this stage again will result in the loss of previous package selections.\n\nDo you wish to continue?" 10 50 || return 1
        fi
        DIALOG --msgbox "Package selection is split into two stages. First you will select package categories that contain packages you may be interested in. Then you will be presented with a full list of packages for each category, allowing you to fine-tune.\n\n" 10 70
        # show group listing for group selection
        # only show xorg and DEs
        local _catlist="base ^ ON"
        for i in $(${PACMAN} -Sg | sed "s/^base$/ /g" | grep -v -e "^kde[a-z]" -e "^kde-meta" -e "^bmp"\
                                                      -e "^gimp" -e "^fprint" -e "-l10n" -e "^ladspa"\
                                                      -e "qtcurve" -e "^telepathy" -e "^texlive" -e "^gstreamer"\
                                                      -e "i18n" -e "^koffice" -e "^vim" | sort); do
            _catlist="${_catlist} ${i} - OFF"
        done

        DIALOG --checklist "Select Package Categories\nDO NOT deselect BASE unless you know what you're doing!" 20 60 12 ${_catlist} 2>${ANSWER} || return 1
        _catlist="$(cat ${ANSWER})"

        DIALOG --infobox "Generating list with packages, this might take some time ..." 5 65  
        # assemble a list of packages with groups, marking pre-selected ones
        # <package> <group> <selected>
        local _pkgtmp="$(${PACMAN} -Sl core extra | awk '{print $2}')"
        local _pkglist=''
        local _pkglist_none=''
        # packages in groups
        ${PACMAN} -Si ${_pkgtmp} | \
        awk '/^Name/{ printf("%s ",$3) } /^Group/{ print $3 }' | grep -v 'None' > ${ANSWER}
        while read pkgname pkgcat; do
            # check if this package is in a selected group
            # slightly ugly but sorting later requires newlines in the variable
            if [[ "${_catlist/"\"${pkgcat}\""/XXXX}" != "${_catlist}" ]]; then
                _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkgcat} ON")"
            else
                _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkgcat} OFF")"
            fi
        done < ${ANSWER}
        # packages without groups
        ${PACMAN} -Si ${_pkgtmp} | \
        awk '/^Name/{ printf("%s ",$3) } /^Group/{ print $3 }' | grep 'None' > ${ANSWER}
        while read pkgname pkgcat; do
            # check if this package is in a selected group
            # slightly ugly but sorting later requires newlines in the variable
            if [[ "${_catlist/"\"${pkgcat}\""/XXXX}" != "${_catlist}" ]]; then
                _pkglist_none="$(echo -e "${_pkglist_none}\n${pkgname} ${pkgcat} ON")"
            else
                _pkglist_none="$(echo -e "${_pkglist_none}\n${pkgname} ${pkgcat} OFF")"
            fi
        done < ${ANSWER}

        # sort by category
        _pkglist="$(echo "${_pkglist}" | sort -f -k 2)"
        _pkglist_none="$(echo "${_pkglist_none}" | sort -f -k 2)"
        DIALOG  --separate-output --checklist "Select Packages To Install." 19 80 12 ${_pkglist} ${_pkglist_none} 2>${ANSWER} || return 1
        PACKAGES="$(cat ${ANSWER})"
    fi
    # Add packages which are not in core repository
    if [[ "$(grep -w nvidia-kms /proc/cmdline)" && "${VMLINUZ}" = "kernel26-lts" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w nouveau-drm)" ]] && PACKAGES="${PACKAGES} nouveau-drm-lts"
        ! [[ "$(echo ${PACKAGES} | grep -w nouveau-firmware)" ]] && PACKAGES="${PACKAGES} nouveau-firmware"
    fi
    if [[ "$(grep -w uvesafb /proc/cmdline)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w v86d)" ]] && PACKAGES="${PACKAGES} v86d"
    fi
    if [[ -e /var/state/dhcp/dhclient.leases ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w dhclient)" ]] && PACKAGES="${PACKAGES} dhclient"
    fi
    # Add filesystem packages
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep ntfs)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w ntfs-3g)" ]] && PACKAGES="${PACKAGES} ntfs-3g"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep btrfs)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w btrfs-progs-unstable)" ]] && PACKAGES="${PACKAGES} btrfs-progs-unstable"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep nilfs2)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w nilfs-utils)" ]] && PACKAGES="${PACKAGES} nilfs-utils"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep ext)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w e2fsprogs)" ]] && PACKAGES="${PACKAGES} e2fsprogs"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep reiserfs)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w reiserfsprogs)" ]] && PACKAGES="${PACKAGES} reiserfsprogs"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep xfs)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w xfsprogs)" ]] && PACKAGES="${PACKAGES} xfsprogs"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep jfs)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w jfsutils)" ]] && PACKAGES="${PACKAGES} jfsutils"
    fi
    if [[ "$(blkid -c /dev/null -o value -s TYPE | grep vfat)" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w dosfstools)" ]] && PACKAGES="${PACKAGES} dosfstools"
    fi
    if ! [[ "$(dmraid_devices)" = "" ]]; then
        ! [[ "$(echo ${PACKAGES} | grep -w dmraid)" ]] && PACKAGES="${PACKAGES} dmraid"
    fi
    # Only install the booted kernel image!
    ### TODO: This misses packages which pull in the kernel itself, like binary modules selected for the kernel!
    PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ kernel26\ # #g" -e  "s#\ kernel26-lts\ # #g")"
    PACKAGES="${KERNELPKG} ${PACKAGES}"
    NEXTITEM="5"
    S_SELECT=1
}


# install_packages()
# performs package installation to the target system
#
install_packages() {
    source_set || return 1
    destdir_mounts || return 1
    if [[ "${MODE}" = "media" ]]; then
        if [[ ! -f /tmp/.pkglist || "${S_SELECT}" != "1" ]]; then
            DIALOG --msgbox "Error:\nYou have to select packages first." 0 0
            select_packages || return 1
        fi
    else
        if [[ "${S_SELECT}" != "1" ]]; then
            DIALOG --msgbox "Error:\nYou have to select packages first." 0 0
            select_packages || return 1
        fi
    fi
    if [[ "${S_MKFS}" != "1" && "${S_MKFSAUTO}" != "1" ]]; then
        getdest
    fi
    DIALOG --msgbox "Package installation will begin now.  You can watch the output in the progress window. Please be patient." 0 0
    run_pacman
    S_INSTALL=1
    NEXTITEM="6"
    chroot_mount
    # automagic time!
    # any automatic configuration should go here
    DIALOG --infobox "Writing base configuration..." 6 40
    auto_addons
    auto_fstab
    auto_mdadm
    auto_luks
    auto_locale
    # tear down the chroot environment
    chroot_umount
}

# add archboot addons if activated
auto_addons()
{
    if [[ -d /tmp/packages ]]; then
        DO_ADDON=""
        DIALOG --yesno "Would you like to install your addons packages to installed system?" 0 0 && DO_ADDON="yes"
        if [[ "${DO_ADDON}" = "yes" ]] ; then
            DIALOG --infobox "Installing the addons packages..." 0 0
            ${PACMAN} -U /tmp/packages/* 2>&1 >> /tmp/pacman.log
        fi
    fi
}

# auto_fstab()
# preprocess fstab file
# comments out old fields and inserts new ones
# according to partitioning/formatting stage
#
auto_fstab(){
    # Modify fstab
    if [[ "${S_MKFS}" = "1" || "${S_MKFSAUTO}" = "1" ]]; then
        if [[ -f /tmp/.device-names ]]; then
            sort /tmp/.device-names >>${DESTDIR}/etc/fstab
        fi
        if [[ -f /tmp/.fstab ]]; then
            # clean fstab first from /dev entries
            sed -i -e '/^\/dev/d' ${DESTDIR}/etc/fstab
            sort /tmp/.fstab >>${DESTDIR}/etc/fstab
        fi
    fi
}

# auto_locale()
# enable glibc locales from rc.conf and build initial locale DB
auto_locale()
{
    for i in $(grep "^LOCALE" ${DESTDIR}/etc/rc.conf | sed -e 's/.*="//g' -e's/\..*//g'); do
        sed -i -e "s/^#${i}/${i}/g" ${DESTDIR}/etc/locale.gen
    done
    DIALOG --infobox "Generating glibc base locales..." 4 40
    chroot ${DESTDIR} locale-gen >/dev/null 2>&1
}

# auto_mdadm()
# add mdadm setup to existing /etc/mdadm.conf
auto_mdadm()
{
    if [[ -e ${DESTDIR}/etc/mdadm.conf ]];then
        if [[ "$(cat /proc/mdstat | grep ^md)" ]]; then
            DIALOG --infobox "Adding raid setup to ${DESTDIR}/etc/mdadm.conf ..." 4 40
            mdadm -Ds >> ${DESTDIR}/etc/mdadm.conf
        fi
    fi
}

# auto_network()
# configures network on host system according to installer
# settings if user wishes to do so
#
auto_network()
{
    # exit if network wasn't configured in installer
    if [[ ${S_NET} -eq 0 ]]; then
        return 1
    fi

    DIALOG --yesno "Do you want to use the previous network settings in rc.conf and resolv.conf?\nIf you used Proxy settings, they will be written to /etc/profile.d/proxy.sh" 0 0 || return 1

    if [[ "${S_DHCP}" != "1" ]]; then
        sed -i -e "s#^eth.*#${INTERFACE}=\"${INTERFACE} ${IPADDR} netmask ${SUBNET} broadcast ${BROADCAST}\"#g" ${DESTDIR}/etc/rc.conf
            if [[ "${GW}" != "" ]]; then
                sed -i -e "s#gw 192.168.0.1#gw ${GW}#g" ${DESTDIR}/etc/rc.conf
                sed -i -e "s#!gateway#gateway#g" ${DESTDIR}/etc/rc.conf
            fi
        echo "nameserver ${DNS}" >> ${DESTDIR}/etc/resolv.conf
    else
        sed -i -e "s#^eth.*#${INTERFACE}=\"dhcp\"#g" ${DESTDIR}/etc/rc.conf
    fi
        sed -i -e "s#eth0)#${INTERFACE})#g" ${DESTDIR}/etc/rc.conf
    if [[ "${PROXY_HTTP}" != "" ]]; then
        echo "export http_proxy=${PROXY_HTTP}" >> ${DESTDIR}/etc/profile.d/proxy.sh;
        chmod a+x ${DESTDIR}/etc/profile.d/proxy.sh
    fi
    if [[ "${PROXY_FTP}" != "" ]]; then
        echo "export ftp_proxy=${PROXY_FTP}" >> ${DESTDIR}/etc/profile.d/proxy.sh;
        chmod a+x ${DESTDIR}/etc/profile.d/proxy.sh
    fi
}

# donetwork()
# Hand-hold through setting up networking
#
# args: none
# returns: 1 on failure
donetwork() {
    INTERFACE=
    S_DHCP=
    ifaces=$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')
    if [[ "${ifaces}" = "" ]]; then
        DIALOG --yesno "Cannot find any ethernet interfaces. You probably haven't loaded\nyour network module yet.  You have two options:\n\n  1) Probe for not detectable module now. (very old hardware)\n  2) Switch to another VC (ALT-F2) and load your module\n     with the modprobe command, then switch back here (ALT-F1)\n     and continue.\n\nIf you know which module you need, you should do Step 2 and\nselect NO below.  If you don't know which module you need,\nchoose Step 1 by selecting YES below.\n\nProbe for network module?" 18 70
        if [[ $? -eq 0 ]]; then
            net_notdetectable
        fi
        ifaces=$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')
        if [[ "${ifaces}" = "" ]]; then
            DIALOG --msgbox "No network interfaces available." 0 0
            return 1
        fi
    fi
    while [[ "${INTERFACE}" = "" ]]; do
        DIALOG --msgbox "Available Ethernet Interfaces:\n$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')\n\nIf your ethernet interface is not listed,\n1) Probe for the correct module now.\n2) Switch to another VC (ALT-F2) and load your module with\n   the modprobe command, then switch back here (ALT-F1)\n" 0 0
        ifaces=$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')
        DIALOG --extra-button --extra-label "Probe" --ok-label "Select" --menu "Select a network interface" 14 55 7 ${ifaces} 2>${ANSWER}
        case $? in
            1) return 1 ;;
            0) INTERFACE=$(cat ${ANSWER}) ;;
            *) net_notdetectable ;;
        esac
    done
    # bring down everything, which could grab and affect the interface!
    [[ -e /var/run/dhcpcd-${INTERFACE}.pid ]] && kill $(cat /var/run/dhcpcd-${INTERFACE}.pid) && sleep 1
    [[ "$(ifconfig | grep ${INTERFACE})" ]] && ifconfig ${INTERFACE} down >${LOG} 2>&1
    [[ "$(route | grep default)" ]] && route del default >${LOG} 2>&1
    [[ -e /etc/resolv.conf ]] && rm /etc/resolv.conf >${LOG} 2>&1
    DIALOG --yesno "Do you want to use DHCP?" 0 0
    if [[ $? -eq 0 ]]; then
        DIALOG --infobox "Please wait.  Polling for DHCP server on ${INTERFACE}..." 10 65
        dhcpcd ${INTERFACE} >${LOG} 2>&1
        if [[ $? -ne 0 ]]; then
            DIALOG --msgbox "Failed to run dhcpcd.  See ${LOG} for details." 0 0
            return 1
        fi
        if [[ ! $(ifconfig ${INTERFACE} | grep 'inet addr:') ]]; then
            DIALOG --msgbox "DHCP request failed." 0 0 || return 1
        fi
        S_DHCP=1
    else
        NETPARAMETERS=""
        while [[ "${NETPARAMETERS}" = "" ]]; do
            DIALOG --inputbox "Enter your IP address" 8 65 "192.168.0.2" 2>${ANSWER} || return 1
            IPADDR=$(cat ${ANSWER})
            DIALOG --inputbox "Enter your netmask" 8 65 "255.255.255.0" 2>${ANSWER} || return 1
            SUBNET=$(cat ${ANSWER})
            DIALOG --inputbox "Enter your broadcast" 8 65 "192.168.0.255" 2>${ANSWER} || return 1
            BROADCAST=$(cat ${ANSWER})
            DIALOG --inputbox "Enter your gateway (optional)" 8 65 "192.168.0.1" 2>${ANSWER} || return 1
            GW=$(cat ${ANSWER})
            DIALOG --inputbox "Enter your DNS server IP" 8 65 "192.168.0.1" 2>${ANSWER} || return 1
            DNS=$(cat ${ANSWER})
            DIALOG --inputbox "Enter your HTTP proxy server, for example:\nhttp://name:port\nhttp://ip:port\nhttp://username:password@ip:port\n\n Leave the field empty if no proxy is needed to install." 16 65 "" 2>${ANSWER} || return 1
            PROXY_HTTP=$(cat ${ANSWER})
            DIALOG --inputbox "Enter your FTP proxy server, for example:\nhttp://name:port\nhttp://ip:port\nhttp://username:password@ip:port\n\n Leave the field empty if no proxy is needed to install." 16 65 "" 2>${ANSWER} || return 1
            PROXY_FTP=$(cat ${ANSWER})
            DIALOG --yesno "Are these settings correct?\n\nIP address:         ${IPADDR}\nNetmask:            ${SUBNET}\nGateway (optional): ${GW}\nDNS server:         ${DNS}\nHTTP proxy server:  ${PROXY_HTTP}\nFTP proxy server:   ${PROXY_FTP}" 0 0
            case $? in
                1) ;;
                0) NETPARAMETERS="1" ;;
            esac
        done
        echo "running: ifconfig ${INTERFACE} ${IPADDR} netmask ${SUBNET} broadcast ${BROADCAST} up" >${LOG}
        ifconfig ${INTERFACE} ${IPADDR} netmask ${SUBNET} broadcast ${BROADCAST} up >${LOG} 2>&1 || DIALOG --msgbox "Failed to setup ${INTERFACE} interface." 0 0 || return 1
        if [[ "${GW}" != "" ]]; then
            route add default gw ${GW} >${LOG} 2>&1 || DIALOG --msgbox "Failed to setup your gateway." 0 0 || return 1
        fi
        if [[ "${PROXY_HTTP}" = "" ]]; then
            unset http_proxy
        else
            export http_proxy=${PROXY_HTTP}
        fi
        if [[ "${PROXY_FTP}" = "" ]]; then
            unset ftp_proxy
        else
            export ftp_proxy=${PROXY_FTP}
        fi
        echo "nameserver ${DNS}" >/etc/resolv.conf
    fi
    ### Missing Proxy Configuration
    DIALOG --msgbox "The network is configured." 8 30
    NEXTITEM="1"
    S_NET=1
}

net_notdetectable() {
    # modules with no modalias exported! status kernel 2.6.18
    NOTDETECTABLE="hp ne de4x5 wd cs89x0 eepro smc9194 seeq8005 ni52 ni65 ac3200 smc-ultra at1700 hp-plus depca eexpress 82596 de600 eth16i de620 lance ewrk3 e2100 lp486e 3c501 3c503 3c505 3c507 3c509 3c515 myri10ge"
    for mod in ${NOTDETECTABLE}; do
        modprobe ${mod} >/dev/null 2>&1
    done
}

getrootfs() {
ROOTFS="$(blkid -c /dev/null ${PART_ROOT} -o value -s TYPE)"
}

getrootflags() {
# remove rw for all filesystems and gcpid for nilfs2
ROOTFLAGS=""
ROOTFLAGS="$(findmnt -m -n -o options -T ${DESTDIR} | sed -e 's/^rw//g' -e 's/,gcpid=.*[0-9]//g')"
[[ -n "${ROOTFLAGS}" ]] && ROOTFLAGS="rootflags=${ROOTFLAGS}"
}

getraidarrays() {
    RAIDARRAYS=""
    if ! [[ "$(grep ^ARRAY ${DESTDIR}/etc/mdadm.conf)" ]]; then
        RAIDARRAYS="$(echo -n $(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's#\[[0-9]\]##g' -e 's# :.* raid[0-9]##g' -e 's#md#md=#g' -e 's# #,/dev/#g' -e 's#_##g'))"
    fi
}

getcryptsetup() {
    CRYPTSETUP=""
    if ! [[ "$(cryptsetup status $(basename ${PART_ROOT}) | grep inactive)" ]]; then
        #avoid clash with dmraid here
        if [[ "$(cryptsetup status $(basename ${PART_ROOT}))" ]]; then
            if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" ]]; then
                CRYPTDEVICE="/dev/disk/by-uuid/$(echo $(blkid -s UUID -o value $(cryptsetup status $(basename ${PART_ROOT}) | grep device: | sed -e 's#device:##g')))"
            elif [[ "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
                CRYPTDEVICE="/dev/disk/by-label/$(echo $(blkid -s LABEL -o value $(cryptsetup status $(basename ${PART_ROOT}) | grep device: | sed -e 's#device:##g')))"
            else
                CRYPTDEVICE="$(echo $(cryptsetup status $(basename ${PART_ROOT}) | grep device: | sed -e 's#device:##g'))"    
            fi
            CRYPTNAME="$(basename ${PART_ROOT})"
            CRYPTSETUP="cryptdevice=${CRYPTDEVICE}:${CRYPTNAME}"
        fi
    fi
}

getrootuuid() {
    _rootpart="${PART_ROOT}"
    _uuid="$(getuuid ${PART_ROOT})"
    if [[ -n "${_uuid}" ]]; then
        _rootpart="/dev/disk/by-uuid/${_uuid}"
    fi
}

getrootlabel() {
    _rootpart="${PART_ROOT}"
    _label="$(getlabel ${PART_ROOT})"
    if [[ -n "${_label}" ]]; then
        _rootpart="/dev/disk/by-label/${_label}"
    fi
}


# basic checks needed for all bootloaders
common_bootloader_checks() {
    activate_special_devices
    getrootfs
    getraidarrays
    getcryptsetup
    getrootflags
    [[ "${NAME_SCHEME_PARAMETER}" = "UUID" ]] && getrootuuid
    [[ "${NAME_SCHEME_PARAMETER}" = "LABEL" ]] && getrootlabel
}

# look for a separately-mounted /boot partition
check_bootpart() {
    subdir=""
    bootdev=$(mount | grep ${DESTDIR}/boot | cut -d' ' -f 1)
    if [[ "${bootdev}" = "" ]]; then
        subdir=/boot
        bootdev=${PART_ROOT}
    fi
}

# check for btrfs bootpart and abort if detected
abort_btrfs_bootpart() {
        FSTYPE="$(blkid -c /dev/null ${bootdev} -o value -s TYPE)"
        if [[ "${FSTYPE}" = "btrfs" ]]; then
            DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from btrfs partition with /boot on it." 0 0
            return 1
        fi
}

# check for nilfs2 bootpart and abort if detected
abort_nilfs_bootpart() {
        FSTYPE="$(blkid -c /dev/null ${bootdev} -o value -s TYPE)"
        if [[ "${FSTYPE}" = "nilfs2" ]]; then
            DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from nilfs2 partition with /boot on it." 0 0
            return 1
        fi
}

# install syslinux and run preparation
prepare_syslinux () {
    if ! [[ -e "${DESTDIR}/sbin/extlinux" || -e "${DESTDIR}/usr/bin/mcopy" ]]; then
        DIALOG --msgbox "Couldn't find bootloader binary or helper program, installing syslinux now ..." 0 0
        PACKAGES="${SYSLINUX_PACKAGES}"
        run_pacman
        # reset PACKAGES after installing
        PACKAGES=""
    fi
    USE_DMRAID=""
    common_bootloader_checks
}

# common syslinux funtion
common_syslinux () {
    DEVS="$(findbootloaderdisks _)"
    DEVS="${DEVS} $(findbootloaderpartitions _)"
    
    if [[ "${DEVS}" = "" ]]; then
        DIALOG --msgbox "No hard drives were found" 0 0
        return 1
    fi
    
    DIALOG --menu "Select the boot device where the ${SYSLINUX} bootloader will be installed (usually the MBR)" 14 55 7 ${DEVS} 2>${ANSWER} || return 1
    ROOTDEV=$(cat ${ANSWER})
    
    # generate config file
    TEMPDIR=/tmp
    
    # check if GPT/GUID is used
    GUID_DETECTED=''
    [[ "$(parted -s ${ROOTDEV} print | grep "Partition Table: gpt")" ]] && GUID_DETECTED=1
    
    PARTITION_NUMBER=$(echo ${bootdev} | sed -e 's#.*[a-z]##g')
    if [[ "${GUID_DETECTED}" = '1' ]]; then
        # Set Legacy BIOS Bootable GPT Partition Attribute using sgdisk
        if ! [[ "$(sgdisk -i ${PARTITION_NUMBER} ${ROOTDEV} | grep '^Attribute' | grep '4$')" ]]; then
            sgdisk ${ROOTDEV} --attributes=${PARTITION_NUMBER}:set:2
        fi
    else
        # mark the partition with /boot as active in MBR
        parted -s ${ROOTDEV} set ${PARTITION_NUMBER} boot on >${LOG}
    fi
    
    [[ -e ${TEMPDIR}/${SYSLINUX_CONF} ]] && rm ${TEMPDIR}/${SYSLINUX_CONF}
    
    cat << EOF > ${TEMPDIR}/${SYSLINUX_CONF}
DEFAULT vesamenu.c32
PROMPT 0
MENU TITLE Arch Linux
MENU BACKGROUND ${subdir}/${SYSLINUX_DIR}/splash.png
TIMEOUT 300

MENU WIDTH 78
MENU MARGIN 4
MENU ROWS 10
MENU VSHIFT 10
MENU TIMEOUTROW 15
MENU TABMSGROW 13
MENU CMDLINEROW 11
MENU HELPMSGROW 17
MENU HELPMSGENDROW 29

# Refer to http://syslinux.zytor.com/wiki/index.php/Doc/menu

MENU COLOR border       30;44   #40ffffff #a0000000 std
MENU COLOR title        1;36;44 #9033ccff #a0000000 std
MENU COLOR sel          7;37;40 #e0ffffff #20ffffff all
MENU COLOR unsel        37;44   #50ffffff #a0000000 std
MENU COLOR help         37;40   #c0ffffff #a0000000 std
MENU COLOR timeout_msg  37;40   #80ffffff #00000000 std
MENU COLOR timeout      1;37;40 #c0ffffff #00000000 std
MENU COLOR msg07        37;40   #90ffffff #a0000000 std
MENU COLOR tabmsg       31;40   #30ffffff #00000000 std

ONTIMEOUT arch
EOF
    sort /tmp/.device-names >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "label arch" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "TEXT HELP" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "Boot Arch Linux" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "ENDTEXT" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "MENU LABEL Arch Linux" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "LINUX ${subdir}/${VMLINUZ}" >> ${TEMPDIR}/${SYSLINUX_CONF}
    if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" || "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
        echo "append initrd=${subdir}/${KERNELPKG}.img root=${_rootpart} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP}" | sed -e 's#  # #g' >> ${TEMPDIR}/${SYSLINUX_CONF}
    else
        echo "append initrd=${subdir}/${KERNELPKG}.img root=${PART_ROOT} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP}" | sed -e 's#  # #g' >> ${TEMPDIR}/${SYSLINUX_CONF}
    fi
    echo "label fallback" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "TEXT HELP" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "Boot Arch Linux Fallback" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "ENDTEXT" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "MENU LABEL Arch Linux Fallback" >> ${TEMPDIR}/${SYSLINUX_CONF}
    echo "LINUX ${subdir}/${VMLINUZ}" >> ${TEMPDIR}/${SYSLINUX_CONF}
    if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" || "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
        echo "append initrd=${subdir}/${KERNELPKG}-fallback.img root=${_rootpart} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP}" | sed -e 's#  # #g' >> ${TEMPDIR}/${SYSLINUX_CONF}
    else
        echo "append initrd=${subdir}/${KERNELPKG}-fallback.img root=${PART_ROOT} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP}" | sed -e 's#  # #g' >> ${TEMPDIR}/${SYSLINUX_CONF}
    fi
    
    # edit config file
    DIALOG --msgbox "Before installing ${SYSLINUX}, you must review the configuration file.  You will now be put into the editor.  After you save your changes and exit the editor, ${SYSLINUX} will be installed." 0 0
    geteditor || return 1
    ${EDITOR} ${TEMPDIR}/${SYSLINUX_CONF}
    
    # install syslinux
    DIALOG --infobox "Installing the ${SYSLINUX} bootloader..." 0 0
    ! [[ -d ${DESTDIR}/boot/${SYSLINUX_DIR} ]] && mkdir -p ${DESTDIR}/boot/${SYSLINUX_DIR}
    cp  ${TEMPDIR}/${SYSLINUX_CONF} ${DESTDIR}/boot/${SYSLINUX_DIR}/${SYSLINUX_CONF}
    cp  ${DESTDIR}/usr/lib/syslinux/*.c32 ${DESTDIR}/boot/${SYSLINUX_DIR}
}

# finish_syslinux
finish_syslinux () {
    MBR=${DESTDIR}/usr/lib/syslinux/mbr.bin
    GPTMBR=${DESTDIR}/usr/lib/syslinux/gptmbr.bin
    
    # check if GPT/GUID is used
    GUID_DETECTED=''
    [[ "$(parted -s ${ROOTDEV} print | grep "Partition Table: gpt")" ]] && GUID_DETECTED=1
    
    if [[ "${GUID_DETECTED}" = '1' ]]; then
        cat ${GPTMBR} > ${ROOTDEV}
    else
        cat ${MBR} > ${ROOTDEV}
    fi
    
    if [[ $? -gt 0 ]]; then
        chroot_umount
        DIALOG --msgbox "Error installing ${SYSLINUX}. (see ${LOG} for output)" 0 0
        return 1
    fi
    
    [[ -f "/src/boot/syslinux/splash.png" ]] && cp /src/boot/syslinux/splash.png ${DESTDIR}/boot/${SYSLINUX_DIR}
    chroot_umount
    
    DIALOG --msgbox "${SYSLINUX} was successfully installed." 0 0
}

# install extlinux bootloader
doextlinux () {
    bootdev=""
    SYSLINUX_PACKAGES="syslinux"
    SYSLINUX=EXTLINUX
    SYSLINUX_PROGRAM=extlinux
    SYSLINUX_DIR=syslinux
    SYSLINUX_CONF=syslinux.cfg
    SYSLINUX_OPTS=""
    prepare_syslinux
    check_bootpart
    abort_nilfs_bootpart || return 1
    # extlinux only can boot from ext2/3/4 and btrfs partitions!
    FSTYPE="$(blkid -c /dev/null ${bootdev} -o value -s TYPE)"
    if ! [[ "${FSTYPE}" = "ext2" || "${FSTYPE}" = "ext3" || "${FSTYPE}" = "ext4" || "${FSTYPE}" = "btrfs" || "${FSTYPE}" = "vfat" ]]; then
        DIALOG --msgbox "Error:\nCouldn't find ext2/3/4 , btrfs or vfat partition with /boot on it." 0 0
        return 1
    fi
    # extlinux cannot boot from any raid partition, encrypted and dmraid device
    if [[ "$(echo ${bootdev} | grep /dev/md*p)" || "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
        DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from any raid partition, encrypted or dmraid device." 0 0
        return 1
    fi
    # check if raid1 device is used, else fail.
    if [[ "$(echo ${bootdev} | grep /dev/md)" ]]; then
        if ! [[ "$(mdadm --detail ${bootdev} | grep Level | sed -e 's#.*:\ ##g')" = "raid1" ]]; then
            DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from non raid1 devices." 0 0
            return 1
        else
            SYSLINUX_OPTS="--raid"
        fi
    fi
    # extlinux cannot boot from btrfs raid
    find_btrfs_raid_bootloader_devices
    if [[ ${BTRFS_COUNT} -ge 3 ]]; then
        DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from any btrfs raid." 0 0
        return 1
    fi
    # extlinux cannot boot from btrfs subvolume
    find_btrfs_bootloader_subvolume
    if [[ ${BTRFS_SUBVOLUME_COUNT} -ge 3 ]]; then
        DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from btrfs subvolume." 0 0
        return 1
    fi
    common_syslinux
    chroot_mount
    chroot ${DESTDIR} ${SYSLINUX_PROGRAM} ${SYSLINUX_OPTS} --install /boot/${SYSLINUX_DIR} >${LOG} 2>&1
    finish_syslinux
}

dolilo() {
    if [[ ! -f ${DESTDIR}/etc/lilo.conf ]]; then
        DIALOG --msgbox "Couldn't find ${DESTDIR}/etc/lilo.conf, installing lilo now ..." 0 0
        PACKAGES="lilo"
        run_pacman
        # reset PACKAGES after installing
        PACKAGES=""
    fi
    USE_DMRAID=""
    common_bootloader_checks
    # check on GUID (gpt)
    if [[ "$(parted -sl | grep "Partition Table: gpt")" ]]; then
                DIALOG --defaultno --yesno "Warning:\nSetup detected GUID (gpt) partition table.\n\nLilo doesn't support booting from GUID (gpt) partition table.\n\nDo you want to install lilo to an other device, which contains a msdos partition table?" 0 0 || return 1
    fi
    check_bootpart
    abort_btrfs_bootpart || return 1
    abort_nilfs_bootpart || return 1
    # Try to auto-configure LILO...
    if ! [[ "${PART_ROOT}" = "" ]]; then
        if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" || "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
            sed -i "s|.*root=.*$|append=\"root=${_rootpart} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP}\"|g" ${DESTDIR}/etc/lilo.conf
        else
            sed -i "s|.*root=.*$|append=\"root=${PART_ROOT} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP}\"|g" ${DESTDIR}/etc/lilo.conf
        fi
        sed -i "s|image=/boot/vmlinuz26|image=/boot/${VMLINUZ}|g" ${DESTDIR}/etc/lilo.conf
        sed -i "s|initrd=.*kernel26.*fallback.img$|initrd=/boot/${KERNELPKG}-fallback.img|g" ${DESTDIR}/etc/lilo.conf
        sed -i "s|initrd=.*kernel26.img$|initrd=/boot/${KERNELPKG}.img|g" ${DESTDIR}/etc/lilo.conf
        sed -i "s|initrd=.*kernel26-lts.img$|initrd=/boot/${KERNELPKG}.img|g" ${DESTDIR}/etc/lilo.conf
    fi
    sed -i -e '/DEVICE DETAILS/d' ${DESTDIR}/etc/lilo.conf
    sort /tmp/.device-names >> ${DESTDIR}/etc/lilo.conf
    DEVS="$(findbootloaderdisks _)"
    DEVS="${DEVS} $(findbootloaderpartitions _)"
    if [[ "${DEVS}" = "" ]]; then
        DIALOG --msgbox "No hard drives were found" 0 0
        return 1
    fi
    DIALOG --menu "Select the boot device where the LILO bootloader will be installed (usually the MBR)" 14 55 7 ${DEVS} 2>${ANSWER} || return 1
    ROOTDEV=$(cat ${ANSWER})
    sed -i "s|boot=.*$|boot=${ROOTDEV}|g" ${DESTDIR}/etc/lilo.conf
    # HACK: if virtio device is used
    if [[ "$(echo ${ROOTDEV} | grep /dev/vd)" ]]; then
        sed -i "s|.*disk=.*$|disk=${ROOTDEV} bios=0x80 max-partitions=7|g" ${DESTDIR}/etc/lilo.conf
    else
        sed -i "s|^disk=.*$|# disk=${ROOTDEV} bios=0x80|g" ${DESTDIR}/etc/lilo.conf
    fi
    DIALOG --msgbox "Before installing LILO, you must review the configuration file.  You will now be put into the editor.  After you save your changes and exit the editor, LILO will be installed." 0 0
    geteditor || return 1
    ${EDITOR} ${DESTDIR}/etc/lilo.conf
    DIALOG --infobox "Installing the LILO bootloader..." 0 0
    chroot_mount
    chroot ${DESTDIR} /sbin/lilo >${LOG} 2>&1
    if [[ $? -gt 0 ]]; then
        chroot_umount
        DIALOG --msgbox "Error installing LILO. (see ${LOG} for output)" 0 0
        return 1
    fi
    chroot_umount
    DIALOG --msgbox "LILO was successfully installed." 0 0
}

dogrub() {
    if [[ -f ${DESTDIR}/boot/grub/grub.cfg ]]; then
        DIALOG --msgbox "Found ${DESTDIR}/boot/grub/grub.cfg, deinstalling grub2 now ..." 0 0
        ${PACMAN} -R grub2-bios grub2-common > ${LOG}
    fi
    if [[ ! -f ${DESTDIR}/boot/grub/menu.lst ]]; then
        DIALOG --msgbox "Couldn't find ${DESTDIR}/boot/grub/menu.lst, installing grub now ..." 0 0
        PACKAGES="grub"
        run_pacman
        # reset PACKAGES after installing
        PACKAGES=""
    fi
    grubdev=""
    _grubdev=""
    bootdev=""
    grubdev=""
    redundant=""
    common_bootloader_checks
    get_grub_map
    FAIL_RAID=""
    FAIL_DM=""
    GRUB_LEGACY="1"
    USE_DMRAID=""
    #checks for custom dev.map filesystem
    if ! [[ "$(dmraid -r | grep ^no )" ]]; then
        DIALOG --yesno "Setup detected dmraid device.\nDo you want to install grub on this device?" 0 0 && get_grub_dmraid_map
    fi
    if  [[ "$(ls ${block}/vd[a-z] 2>/dev/null)" ]]; then
        DIALOG --yesno "Setup detected virtio devices.\nDo you want to install grub on this device?" 0 0 && get_grub_virtio_map
    fi
    if  [[ "$(ls ${block}/mmcblk* 2>/dev/null)" ]]; then
        DIALOG --yesno "Setup detected mmcblk devices.\nDo you want to install grub on this device?" 0 0 && get_grub_mmcblk_map
    fi
    for i in ${EXTRA_CONTROLLER}; do
        if [[ "$(ls ${block}/${i}* 2>/dev/null)" ]]; then
                    DIALOG --yesno "Setup detected ${i} devices.\nDo you want to install grub on this device?" 0 0 && get_grub_extra_devices_map
        fi
    done
    # check on GUID (gpt)
    if [[ "$(parted -sl | grep "Partition Table: gpt")" ]]; then
                DIALOG --defaultno --yesno "Warning:\nSetup detected GUID (gpt) partition table.\n\nGrub doesn't support booting from GUID (gpt) partition table.\n\nDo you want to install grub to an other device, which contains a msdos partition table?" 0 0 || return 1
    fi
    if [[ "${PART_ROOT}" = "" ]]; then
        DIALOG --inputbox "Enter the full path to your root device" 8 65 "/dev/sda3" 2>${ANSWER} || return 1
        PART_ROOT=$(cat ${ANSWER})
    fi
    # try to auto-configure GRUB...
    if [[ "${PART_ROOT}" != "" ]]; then
        check_bootpart
        abort_btrfs_bootpart || return 1
        abort_nilfs_bootpart || return 1
        # check if raid device, devicemapper or dmraid is used  on /boot partition
        if [[ "$(echo ${bootdev} | grep /dev/md)" ]]; then
            if [[ "$(mdadm --detail ${bootdev} | grep Level | sed -e 's#.*:\ ##g')" = "raid1" ]]; then
                # get redundant devices
                for i in $(mdadm --detail ${bootdev} | grep "\ /dev/" | sed -e 's#.* /#/#g'); do
                    _grubdev="${_grubdev} $(mapdev ${i})"
                done
                redundant="1"
            else
                # none raid1 devices are not bootable with grub, let it fail!
                FAIL_RAID="1"
            fi
            if [[ "$(echo ${bootdev} | grep /dev/md*p)" ]]; then
                # partitionable raid is not supported by grub!
                FAIL_RAID="1"
            fi
        elif  [[ "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
                if ! [[ "$(dmsetup info ${bootdev} | grep 'DMRAID')" ]]; then
                    FAIL_DM="1"
                else
                    FAIL_DM=""
                    _grubdev=$(mapdev ${bootdev})
                fi
        else
            # use normal device
            _grubdev=$(mapdev ${bootdev})
        fi
        if [[ "${FAIL_RAID}" = "1" ]]; then
                DIALOG --msgbox "Error: Grub cannot boot from none raid1 devices or partitionable raid devices!" 0 0
                return 1
        fi
        if [[ "${FAIL_DM}" = "1" ]]; then
                DIALOG --msgbox "Error: Grub cannot boot from your created device mapper devices!" 0 0
                return 1
        fi
        if [[ "${_grubdev}" != "" ]]; then
            cp ${DESTDIR}/boot/grub/menu.lst /tmp/.menu.lst
            # remove the default entries by truncating the file at our little tag (#-*)
            head -n $(cat /tmp/.menu.lst | grep -n '#-\*' | cut -d: -f 1) /tmp/.menu.lst >${DESTDIR}/boot/grub/menu.lst
            rm -f /tmp/.menu.lst
            # keep the file from being completely bogus
            if [[ "${_grubdev}" = "DEVICE NOT FOUND" ]]; then
                DIALOG --msgbox "Your root boot device could not be autodetected by setup.  Ensure you adjust the 'root (hd0,0)' line in your GRUB config accordingly." 0 0
                _grubdev="(hd0,0)"
            fi
            NUMBER=0
            # create default grub entries
            sort /tmp/.device-names >>${DESTDIR}/boot/grub/menu.lst
            for grubdev in ${_grubdev}; do
                echo "" >>${DESTDIR}/boot/grub/menu.lst
                echo "# (${NUMBER}) Arch Linux" >>${DESTDIR}/boot/grub/menu.lst
                echo "title  Arch Linux" >>${DESTDIR}/boot/grub/menu.lst
                echo "root   ${grubdev}" >>${DESTDIR}/boot/grub/menu.lst
                if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" || "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
                    echo "kernel ${subdir}/${VMLINUZ} root=${_rootpart} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP} ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>${DESTDIR}/boot/grub/menu.lst
                else
                    echo "kernel ${subdir}/${VMLINUZ} root=${PART_ROOT} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP} ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>${DESTDIR}/boot/grub/menu.lst
                fi
                echo "initrd ${subdir}/${KERNELPKG}.img" >>${DESTDIR}/boot/grub/menu.lst
                echo "" >>${DESTDIR}/boot/grub/menu.lst
                # adding fallback/full image
                NUMBER=$((${NUMBER}+1))
                echo "# (${NUMBER}) Arch Linux" >>${DESTDIR}/boot/grub/menu.lst
                echo "title  Arch Linux Fallback" >>${DESTDIR}/boot/grub/menu.lst
                echo "root   ${grubdev}" >>${DESTDIR}/boot/grub/menu.lst
                if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" || "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]; then
                    echo "kernel ${subdir}/${VMLINUZ} root=${_rootpart} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP} ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>${DESTDIR}/boot/grub/menu.lst
                else
                    echo "kernel ${subdir}/${VMLINUZ} root=${PART_ROOT} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP} ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>${DESTDIR}/boot/grub/menu.lst
                fi
                echo "initrd ${subdir}/${KERNELPKG}-fallback.img" >>${DESTDIR}/boot/grub/menu.lst
                NUMBER=$((${NUMBER}+1))
            done
            ### TODO:
            # Is it possible to detect a windows installation?
            echo "" >>${DESTDIR}/boot/grub/menu.lst
            echo "# (${NUMBER}) Windows" >>${DESTDIR}/boot/grub/menu.lst
            echo "#title Windows" >>${DESTDIR}/boot/grub/menu.lst
            echo "#rootnoverify (hd0,0)" >>${DESTDIR}/boot/grub/menu.lst
            echo "#makeactive" >>${DESTDIR}/boot/grub/menu.lst
            echo "#chainloader +1" >>${DESTDIR}/boot/grub/menu.lst
        fi
    fi

    DIALOG --msgbox "Before installing GRUB, you must review the configuration file.  You will now be put into the editor.  After you save your changes and exit the editor, you can install GRUB." 0 0
    geteditor || return 1
    ${EDITOR} ${DESTDIR}/boot/grub/menu.lst

    DEVS="$(findbootloaderdisks _)"
    DEVS="${DEVS} $(findbootloaderpartitions _)"
    if [[ "${DEVS}" = "" ]]; then
        DIALOG --msgbox "No hard drives were found" 0 0
        return 1
    fi
    S_GRUB=""
    while [[ "${S_GRUB}" = "" ]]; do
        DIALOG --menu "Select the boot device where the GRUB bootloader will be installed (usually the MBR  and not a partition)." 14 55 7 ${DEVS} 2>${ANSWER} || return 1
        ROOTDEV=$(cat ${ANSWER})
        DIALOG --infobox "Installing the GRUB bootloader..." 0 0
        cp -a ${DESTDIR}/usr/lib/grub/i386-pc/* ${DESTDIR}/boot/grub/
        # freeze xfs filesystems to enable grub installation on xfs filesystems
        freeze_xfs
        bootpart=${bootdev}
        if [[ "$(echo ${bootpart} | grep /dev/md)" ]]; then
            bootpart=$(mdadm --detail ${bootpart} | grep ${ROOTDEV} | sed -e 's#.* /#/#g')
        fi
        bootpart=$(mapdev ${bootpart})
        bootdev=$(mapdev ${ROOTDEV})
        if [[ "${bootpart}" = "" ]]; then
            DIALOG --msgbox "Error: Missing/Invalid root device: ${bootpart}" 0 0
            return 1
        fi
        if [[ "${bootpart}" = "DEVICE NOT FOUND" || "${bootdev}" = "DEVICE NOT FOUND" ]]; then
            DIALOG --msgbox "GRUB root and setup devices could not be auto-located.  You will need to manually run the GRUB shell to install a bootloader." 0 0
            return 1
        fi
        get_chs
        ### HACK:we need a dmraid hack here! http://bugs.gentoo.org/show_bug.cgi?id=275566
        grub_dmraid_hack
        ${DESTDIR}/sbin/grub --device-map=/tmp/dev.map --no-floppy --batch >>/tmp/grub.log 2>&1 <<EOF
geometry ${realdev} ${CYLINDERS} ${HEADS} ${SECTORS}
root ${bootpart}
setup ${bootdev}
quit
EOF
        ### HACK:remove symlinks again! http://bugs.gentoo.org/show_bug.cgi?id=275566
        remove_grub_dmraid_hack
        cat /tmp/grub.log >${LOG}
        if grep "Error [0-9]*: " /tmp/grub.log >/dev/null; then
            DIALOG --msgbox "Error installing GRUB. (see ${LOG} for output)" 0 0
            return 1
        fi
        # copy device map file
        cp -f /tmp/dev.map ${DESTDIR}/boot/grub/device.map
        DIALOG --msgbox "GRUB was successfully installed." 0 0
        S_GRUB=1
        if [[ "$(blkid -c /dev/null | grep TYPE=\"linux_raid_member\")" ]]; then
            if [[ "${redundant}" = "1" ]]; then
                DIALOG --defaultno --yesno "Setup detected a redundant software raid device.\nDo you want to install grub additionally to an other hard disk?" 0 0 && S_GRUB=""
            fi
        fi
    done
}

dogrub2_common_before() {
    ##### Check whether the below limitations still continue with ver 1.99~beta0
    ### Grub2 restrictions:
    # - dmraid doesn't work:
    #   https://bugs.launchpad.net/ubuntu/+source/ubuntu-meta/+bug/436340
    #   grub2 restriction due to messy dmraid mapping
    # - Encryption is not supported by grub2 yet!
    # - raid with no supperblock 0.90 is not supported by grub2 yet!
    if [[ -f ${DESTDIR}/boot/grub/menu.lst ]]; then
        DIALOG --msgbox "Found ${DESTDIR}/boot/grub/menu.lst, deinstalling grub now ..." 0 0
        ${PACMAN} -R grub > ${LOG}
    fi
    bootdev=""
    grubdev=""
    complexuuid=""
    FAIL_COMPLEX=""
    GRUB_LEGACY=""
    USE_DMRAID=""
    RAID_ON_LVM=""
    common_bootloader_checks
    if ! [[ "$(dmraid -r | grep ^no )" ]]; then
        DIALOG --yesno "Setup detected dmraid device.\nDo you want to install grub on this device?" 0 0 && USE_DMRAID="1"
    fi
}

dogrub2_config() {

    BOOT_FS_UUID=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=fs_uuid ${DESTDIR}/boot 2>/dev/null)
    BOOT_FS=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=fs ${DESTDIR}/boot 2>/dev/null)
    
    BOOT_FS_LABEL=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=fs_label ${DESTDIR}/boot 2>/dev/null)
    BOOT_DRIVE=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=drive ${DESTDIR}/boot 2>/dev/null)
    
    ROOT_FS_UUID=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=fs_uuid ${DESTDIR}/ 2>/dev/null)
    ROOT_FS=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=fs ${DESTDIR}/ 2>/dev/null)
    
    ROOT_FS_LABEL=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=fs_label ${DESTDIR}/ 2>/dev/null)
    ROOT_DEVICE=$(LD_LIBRARY_PATH="${DESTDIR}/lib:${DESTDIR}/usr/lib" ${DESTDIR}/sbin/grub-probe --device-map=/tmp/device.map --target=device ${DESTDIR}/ 2>/dev/null)

    subdir='/boot'
    [[ "${ROOT_FS_UUID}" != "${BOOT_FS_UUID}" ]] && subdir=''
    
    cp ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg /tmp/.grub.cfg
    # remove the default entries by truncating the file at our little tag (set default)
    head -n $(cat /tmp/.grub.cfg | grep -n 'set default' | cut -d: -f 1) /tmp/.grub.cfg > ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    rm -f /tmp/.grub.cfg
    
    NUMBER=0
    
    ## Ignore if the insmod entries are repeated - there are possibilities of having /boot in one disk and root-fs in altogether different disk
    ## with totally different configuration.
    
    cat << EOF >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg

insmod part_gpt
insmod part_msdos

# Include fat fs module - required for uefi systems.
insmod fat

insmod ${BOOT_FS}
insmod ${ROOT_FS}

insmod search_fs_file
insmod search_fs_uuid
insmod search_label

insmod linux
insmod chain

set pager=1

EOF
    
    [[ "${USE_RAID}" = "1" ]] && echo "insmod raid" >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    ! [[ "${RAID_ON_LVM}" = "" ]] && echo "insmod lvm" >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    
    ## For UEFI systems, no kernel boot messages are displayed if framebuffer is not initialized in grub2. So initialize it.
    if [[ "${GRUB2_EFI}" = "1" ]]; then
        
        cat << EOF >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg

insmod efi_gop
insmod font

if loadfont \${prefix}/unicode.pf2
then
    insmod gfxterm
    set gfxmode="auto"
    set gfxpayload=keep
    terminal_output gfxterm
fi

EOF
    
    fi
    
    echo "" >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    sort /tmp/.device-names >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    echo "" >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    
    if [[ "${NAME_SCHEME_PARAMETER}" = "UUID" ]]
    then
        GRUB_ROOT_DRIVE="search --fs-uuid --no-floppy --set=root ${BOOT_FS_UUID}"
        _rootpart="/dev/disk/by-uuid/${ROOT_FS_UUID}"
        
    elif [[ "${NAME_SCHEME_PARAMETER}" = "LABEL" ]]
    then
        GRUB_ROOT_DRIVE="search --label --no-floppy --set=root ${BOOT_FS_LABEL}"
        _rootpart="/dev/disk/by-label/${ROOT_FS_LABEL}"
        
    else
        GRUB_ROOT_DRIVE="set root=${BOOT_DRIVE}"
        _rootpart="${ROOT_DEVICE}"
        
    fi
    # fallback to device if no label or uuid can be detected, eg. luks device
    [[ -z "${ROOT_FS_LABEL}" ]] && _rootpart="${ROOT_DEVICE}"
    [[ -z "${ROOT_FS_UUID}" ]] &&  _rootpart="${ROOT_DEVICE}"

    LINUX_UNMOD_COMMAND="linux (\${root})/${subdir}/${VMLINUZ} root=${_rootpart} ${ROOTFLAGS} rootfstype=${ROOTFS} ${RAIDARRAYS} ${CRYPTSETUP} ro nomodeset add_efi_memmap"
    LINUX_MOD_COMMAND=$(echo "${LINUX_UNMOD_COMMAND}" | sed -e 's#   # #g' | sed -e 's#  # #g')
    
    ## create default kernel entry
    cat << EOF >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg

# (${NUMBER}) Arch Linux
menuentry "Arch Linux" {
    ${GRUB_ROOT_DRIVE}
    ${LINUX_MOD_COMMAND}
    initrd (\${root})/${subdir}/${KERNELPKG}.img
}

EOF
    
    NUMBER=$((${NUMBER}+1))
    
    ## create kernel fallback entry
    cat << EOF >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg

# (${NUMBER}) Arch Linux Fallback
menuentry "Arch Linux Fallback" {
    ${GRUB_ROOT_DRIVE}
    ${LINUX_MOD_COMMAND}
    initrd (\${root})/${subdir}/${KERNELPKG}-fallback.img
}

EOF
    
    NUMBER=$((${NUMBER}+1))
    
    ## TODO: Detect actual Windows installation if any
    ## create example file for windows
    cat << EOF >> ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg

## (${NUMBER}) Windows
#menuentry \"Windows\" {
#    search --file --no-floppy --set=root /bootmgr
#    chainloader (${root})+1
#}

EOF
    
    unset BOOT_FS_UUID
    unset BOOT_FS
    unset BOOT_FS_LABEL
    unset BOOT_DRIVE
    
    unset ROOT_FS_UUID
    unset ROOT_FS
    unset ROOT_FS_LABEL
    unset ROOT_DEVICE
    
    unset GRUB_ROOT_DRIVE
    unset LINUX_UNMOD_COMMAND
    unset LINUX_MOD_COMMAND
    
}

dogrub2_common_after() {    
    
    if [[ "${PART_ROOT}" != "" ]]; then
        if [[ "${GRUB2_BIOS}" = "1" ]]; then
            [[ "${grubdev}" != "" ]] && dogrub2_config
        elif [[ "${GRUB2_EFI}" = "1" ]]; then
            dogrub2_config
        fi
    fi
    
    # Edit grub.cfg config file
    DIALOG --msgbox "You must now review the grub2 configuration file.\n\nYou will now be put into the editor. After you save your changes and exit the editor, you can install GRUB2." 0 0
    geteditor  || return 1
    ${EDITOR} ${DESTDIR}/${GRUB2_PREFIX_DIR}/grub.cfg
    
    cp ${DESTDIR}/usr/share/grub/{unicode.pf2,ascii.pf2} ${DESTDIR}/${GRUB2_PREFIX_DIR}/
    
    GRUB2_BIOS=""
    GRUB2_EFI=""
    
}

dogrub2_bios() {
    
    dogrub2_common_before
    
    if [[ ! -f ${DESTDIR}/boot/grub/grub.cfg ]]; then
        DIALOG --msgbox "Couldn't find ${DESTDIR}/boot/grub/grub.cfg, installing grub2-bios now ..." 0 0
        PACKAGES="grub2-bios grub2-common"
        run_pacman
        # reset PACKAGES after installing
        PACKAGES=""
    fi
    get_grub2_map
    # try to auto-configure GRUB2...
    if [[ "${PART_ROOT}" != "" ]]; then
        check_bootpart
        abort_btrfs_bootpart || return 1
        # check if raid, raid partition, dmraid or device devicemapper is used
        if [[ "$(echo ${bootdev} | grep /dev/md)" || "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
            # boot from lvm, raid and dmraid devices is supported
            FAIL_COMPLEX="0"
            if [[ "$(echo ${bootdev} | grep /dev/md*p)" || "$(cryptsetup status ${bootdev})" ]]; then
                # raid with no supperblock 0.90, partitionable raid and encryption
                # devices are not supported
                FAIL_COMPLEX="1"
            fi
        fi
        if [[ "${FAIL_COMPLEX}" = "0" ]]; then
            grubdev=$(basename ${bootdev})
            complexuuid=$(getuuid ${bootdev})
            # check if mapper is used
            if  [[ "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
                RAID_ON_LVM="0"
                #check if mapper contains a md device!
                for devpath in $(pvs -o pv_name --noheading); do
                    if [[ "$(echo ${devpath} | grep -v /dev/md*p | grep /dev/md)" ]]; then
                        detectedvolumegroup="$(echo $(pvs -o vg_name --noheading ${devpath}))"
                        if [[ "$(echo /dev/mapper/${detectedvolumegroup}-* | grep ${bootdev})" ]]; then
                            # change bootdev to md device!
                            bootdev=$(pvs -o pv_name --noheading ${devpath})
                            RAID_ON_LVM="1"
                            break
                        fi
                    fi
                done
            fi
            USE_RAID=""
            if [[ "$(echo ${bootdev} | grep /dev/md)" ]]; then
                # check if raid superblock is 0.90 format, if not fail
                [[ "$(mdadm -Q --detail ${bootdev} | grep 'Version : 0.90')" ]] || FAIL_COMPLEX="1"
                USE_RAID="1"
            fi
        else
            # use normal device
            grubdev=$(mapdev ${bootdev})
        fi
    fi
    
    
    # A switch is needed if complex ${bootdev} is used!
    # - It doesn't make sense to present device list, if raid or raid+lvm is used for ${bootdev}.
    # - LVM ${bootdev} needs the MBR of a device and cannot be used itself as ${bootdev}
    if [[ "${FAIL_COMPLEX}" = "0" ]]; then
        # use function below if no raid is detected!
        if [[ "${RAID_ON_LVM}" = "0" ]]; then
            DEVS="$(findbootloaderdisks _)"
            if [[ "${DEVS}" = "" ]]; then
                DIALOG --msgbox "No hard drives were found" 0 0
                return 1
            fi
            DIALOG --menu "Select the boot device where the GRUB2 bootloader will be installed." 14 55 7 ${DEVS} 2>${ANSWER} || return 1
            bootdev=$(cat ${ANSWER})
        fi
        if [[ "${USE_RAID}"  = "1" ]]; then
            DIALOG --yesno "Setup detected /boot on a raid setup.\n\nContinue installing GRUB2 on ${bootdev}?" 0 0 || return 1
        fi
    else
        DEVS="$(findbootloaderdisks _)"
        DEVS="${DEVS} $(findbootloaderpartitions _)"
        if [[ "${DEVS}" = "" ]]; then
            DIALOG --msgbox "No hard drives were found" 0 0
            return 1
        fi
        DIALOG --menu "Select the boot device where the GRUB2 bootloader will be installed (usually the MBR  and not a partition)." 14 55 7 ${DEVS} 2>${ANSWER} || return 1
        bootdev=$(cat ${ANSWER})
    fi
    
    if [[ "$(parted -sl | grep "Partition Table: gpt")" ]]; then
        if ! [[ "$(parted -sl | grep "bios_grub")" ]]; then
            DIALOG --defaultno --yesno "Warning:\nSetup detected no bios_grub flagged GUID (gpt) partition.\n\nDo you want to install grub2 to an other device, which contains a msdos partition table?" 0 0 || return 1
        fi
    else
        if [[ "${FAIL_COMPLEX}" = "0" ]]; then
            DIALOG --defaultno --yesno "Warning:\nSetup detected no GUID (gpt) partition table.\n\nGrub2 has only space for approx. 30k core.img file. Depending on your setup, it might not fit into this gap and fail.\n\nDo you really want to install grub2 to a msdos partition table?" 0 0 || return 1
        fi
    fi
    
    if [[ "${FAIL_COMPLEX}" = "1" ]]; then
        DIALOG --msgbox "Error:\nGrub2 cannot boot from ${bootdev}, which contains /boot!\n\nPossible error sources:\n- raid device (/dev/mdX) has no 0.90 superblock format\n- raid partition device (/dev/md_dX) are not supported\n- encrypted devices are not supported" 0 0
        return 1
    fi
    
    DIALOG --infobox "Installing the GRUB2 BIOS bootloader..." 0 0
    # freeze and unfreeze xfs filesystems to enable grub2 installation on xfs filesystems
    freeze_xfs
    chroot_mount
    chroot ${DESTDIR} /sbin/grub_bios-install --boot-directory=/boot --no-floppy --recheck ${bootdev} >> /tmp/grub2.log
    chroot_umount
    cat /tmp/grub2.log >${LOG}
    if ! [[ -s /tmp/grub2.log ]] ; then
        DIALOG --msgbox "Error installing GRUB2.\n\nProbably you need to install it manually by chrooting into ${DESTDIR}.\nDon't forget to bind /dev and /proc into ${DESTDIR} before chrooting." 0 0
        return 1
    fi
    DIALOG --msgbox "GRUB2 was successfully installed." 0 0
    
    GRUB2_PREFIX_DIR=/boot/grub/
    GRUB2_BIOS="1"
    dogrub2_common_after
    
}

dogrub2_efibootmgr() {
    
    modprobe -q efivars 2>/dev/null
    
    chroot_mount
    
    EFIBOOTMGR="efibootmgr"
    
    if [[ -d ${DESTDIR}/sys/firmware/efi/vars ]]
    then
        # Delete old entries of grub2 - needs to run within chroot - command to be checked
        for bootnum in $(${EFIBOOTMGR} | grep '^Boot[0-9]' | fgrep -i " grub2" | cut -b5-8)
        do
            ${EFIBOOTMGR} --bootnum "${bootnum}" --delete-bootnum
        done
        
        DISC=$(mount | grep ${DESTDIR}/boot/efi | cut -d' ' -f 1 | sed 's/\(.\{8\}\).*/\1/')
        
        [[ "${DISC}" = "" ]] && DISC=$(mount | grep ${DESTDIR}/boot | cut -d' ' -f 1 | sed 's/\(.\{8\}\).*/\1/')
        
        [[ "${EFISYS_PART}" = "" ]] && EFISYS_PART_NUM=$(sgdisk -p ${DISC} | grep "EF00" | sed 's/\(.\{4\}\).*/\1/' | sed 's/^ *//;s/ *$//')
        
    ${EFIBOOTMGR} --create --gpt --disk "${DISC}" --part "${EFISYS_PART_NUM}" --write-signature --label "GRUB2" --loader "\\EFI\\grub\\grub.efi"
    fi
    
    chroot_umount
    
}

dogrub2_efi_common() {
    
    dogrub2_common_before
    
    DIALOG --msgbox "Installing grub2-efi-${EFI_ARCH} now ..." 0 0
    PACKAGES="grub2-efi-${EFI_ARCH} grub2-common dosfstools efibootmgr"
    run_pacman
    # reset PACKAGES after installing
    PACKAGES=""
    get_grub2_map
    DISC=$(mount | grep ${DESTDIR}/boot/efi | cut -d' ' -f 1 | sed 's/\(.\{8\}\).*/\1/')
    
    if [[ "${DISC}" = "" ]]; then
        DISC=$(mount | grep ${DESTDIR}/boot | cut -d' ' -f 1 | sed 's/\(.\{8\}\).*/\1/')
        EFISYS=""
    fi
    
    parted_gpt
    
    if [[ -d ${DESTDIR}/boot/efi ]]; then
        EFISYS_PART=$(mount | grep ${DESTDIR}/boot/efi | cut -d' ' -f 1)
    else
        mkdir -p ${DESTDIR}/boot/efi
        EFISYS_PART=""
    fi
    
    if [[ "${EFISYS_PART}" = "" ]]; then
        EFISYS_PART_NUM=$(sgdisk -p ${DISC} | grep "EF00" | sed 's/\(.\{4\}\).*/\1/' | sed 's/^ *//;s/ *$//')
        mount -o rw -t vfat ${DISC}${EFISYS_PART_NUM} ${DESTDIR}/boot/efi
    else
        mount -o rw -t vfat ${EFISYS_PART} ${DESTDIR}/boot/efi
    fi
    
    chroot_mount
    
    chroot ${DESTDIR} /sbin/grub_efi_${EFI_ARCH}-install --boot-directory=/boot/efi/efi --bootloader-id=grub --no-floppy --recheck >> /tmp/grub2_efi.log
    
    chroot ${DESTDIR} /bin/grub-mkimage --directory=/usr/lib/grub/${EFI_ARCH}-efi \
                                        --format=${EFI_ARCH}-efi \
                                        --prefix="" \
                                        --output=/boot/efi/efi/grub/grub_custom.efi \
                                        --compression=auto \
                                        --verbose \
                                        part_gpt part_msdos part_apple \
                                        fat ext2 reiserfs iso9660 udf hfsplus hfs ntfs ntfscomp \
                                        fshelp xzio gzio \
                                        normal chain linux ls \
                                        search search_fs_file search_fs_uuid search_label \
                                        help boot configfile echo lvm efi_gop \
                                        png jpeg tga \
                                        usbms usb_keyboard > /tmp/grub2_efi_mkimage.log
    
    chroot_umount
    cat /tmp/grub2_efi.log > ${LOG}
    if ! [[ -s /tmp/grub2_efi.log ]] ; then
        DIALOG --msgbox "Error installing GRUB2.\n\nProbably you need to install it manually by chrooting into ${DESTDIR}.\nDon't forget to bind /dev, /sys and /proc into ${DESTDIR} before chrooting." 0 0
        return 1
    fi
    
    dogrub2_efibootmgr
    
    DIALOG --msgbox "GRUB2 UEFI was successfully installed." 0 0
    
    GRUB2_PREFIX_DIR=/boot/efi/efi/grub/
    GRUB2_EFI="1"
    dogrub2_common_after
    
}

dogrub2_efi_x86_64() {
    
    EFI_ARCH="x86_64"
    dogrub2_efi_common
    
}

dogrub2_efi_i386() {
    
    EFI_ARCH="i386"
    dogrub2_efi_common
    
}

select_source()
{
    NEXTITEM="3"
    if ! [[ "$(which ${DLPROG})" ]]; then
        DIALOG --menu "Please select an installation source" 10 45 3 \
        "1" "CD-ROM, USBSTICK or OTHER SOURCE" 2>${ANSWER} || return 1
    else
        DIALOG --menu "Please select an installation source" 10 45 3 \
        "1" "CD-ROM, USBSTICK or OTHER SOURCE" \
        "2" "FTP/HTTP" 2>${ANSWER} || return 1
    fi

    case $(cat ${ANSWER}) in
        "1")
            MODE="media"
            ;;
        "2")
            MODE="ftp"
            ;;
    esac

    if [[ "${MODE}" = "media" ]]; then
        TITLE="Arch Linux CDROM, USBSTICK or OTHER SOURCE Installation"
        getsource || return 1
    else
        DEFAULT=
        TITLE="Arch Linux FTP/HTTP Installation"
        while true; do
            if [[ -n "${NEXTITEM}" ]]; then
            DEFAULT="--default-item ${NEXTITEM}"
            else
            DEFAULT=""
            fi
            CANCEL=""
            DIALOG ${DEFAULT} --menu "FTP Installation" 10 35 3 \
            "0" "Set up Network" \
            "1" "Choose Mirror" \
            "2" "Return to Main Menu" 2>${ANSWER} || CANCEL="1"

            case "$(cat ${ANSWER})" in
            "0")
                donetwork ;;
            "1")
                getsource || return 1
                ;;
             *)
                break ;;
            esac
        done
    fi
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="3"
    else
        NEXTITEM="4"
    fi
}

set_clock()
{
    if [[ -e /usr/bin/tz ]]; then
        tz --setup && NEXTITEM="2"
    else
        DIALOG --msgbox "Error:\ntz script not found, aborting clock setting" 0 0
    fi
}

set_keyboard()
{
    if [[ -e /usr/bin/km ]]; then
        km --setup && NEXTITEM="1"
    else
        DIALOG --msgbox "Error:\nkm script not found, aborting keyboard and console setting" 0 0
    fi
}

# run_mkinitcpio()
# runs mkinitcpio on the target system, displays output
#
run_mkinitcpio()
{
    chroot_mount
    # all mkinitcpio output goes to /tmp/mkinitcpio.log, which we tail into a dialog
    ( \
    touch /tmp/setup-mkinitcpio-running
    echo "Initramfs progress ..." > /tmp/initramfs.log; echo >> /tmp/mkinitcpio.log
    chroot ${DESTDIR} /sbin/mkinitcpio -p ${KERNELPKG} >>/tmp/mkinitcpio.log 2>&1
    echo >> /tmp/mkinitcpio.log
    rm -f /tmp/setup-mkinitcpio-running
    ) &
    sleep 2
    dialog --backtitle "${TITLE}" --title "Rebuilding initramfs images ..." --no-kill --tailboxbg "/tmp/mkinitcpio.log" 18 70
    while [[ -f /tmp/setup-mkinitcpio-running ]]; do
        sleep 1
    done
    chroot_umount
}

prepare_harddrive()
{
    S_MKFSAUTO=0
    S_MKFS=0
    DONE=0
    NEXTITEM=""
    while [[ "${DONE}" = "0" ]]; do
        if [[ -n "${NEXTITEM}" ]]; then
            DEFAULT="--default-item ${NEXTITEM}"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Prepare Hard Drive" 12 60 5 \
            "1" "Auto-Prepare (erases the ENTIRE hard drive)" \
            "2" "Partition Hard Drives" \
            "3" "Create Software Raid, Lvm2 and Luks encryption" \
            "4" "Set Filesystem Mountpoints" \
            "5" "Return to Main Menu" 2>${ANSWER} || CANCEL="1"
        NEXTITEM="$(cat ${ANSWER})"
        [[ "${S_MKFSAUTO}" = "1" ]] && DONE=1
        case $(cat ${ANSWER}) in
            "1")
                autoprepare
                [[ "${S_MKFSAUTO}" = "1" ]] && DONE=1
                ;;
            "2")
                partition ;;
            "3")
                create_special ;;
            "4")
                PARTFINISH=""
                ASK_MOUNTPOINTS="1"
                mountpoints ;;
            *)
                DONE=1 ;;
        esac
    done
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="2"
    else
        NEXTITEM="3"
    fi
}

# menu for raid, lvm and encrypt
create_special()
{
    NEXTITEM=""
    SPECIALDONE=0
    while [[ "${SPECIALDONE}" = "0" ]]; do
        if [[ -n "${NEXTITEM}" ]]; then
            DEFAULT="--default-item ${NEXTITEM}"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create Software Raid, LVM2 and Luks encryption" 14 60 5 \
            "1" "Create Software Raid" \
            "2" "Create LVM2" \
            "3" "Create Luks encryption" \
            "4" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
        NEXTITEM="$(cat ${ANSWER})"
        case $(cat ${ANSWER}) in
            "1")
                _createmd ;;
            "2")
                _createlvm ;;
            "3")
                _createluks ;;
            *)
                SPECIALDONE=1 ;;
        esac
    done
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="3"
    else
        NEXTITEM="4"
    fi
}

# menu for md creation
_createmd()
{
    NEXTITEM=""
    MDDONE=0
    while [[ "${MDDONE}" = "0" ]]; do
        if [[ -n "${NEXTITEM}" ]]; then
            DEFAULT="--default-item ${NEXTITEM}"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create Software Raid" 12 60 5 \
            "1" "Raid Help" \
            "2" "Reset Software Raid completely" \
            "3" "Create Software Raid" \
            "4" "Create Partitionable Software Raid" \
            "5" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
        NEXTITEM="$(cat ${ANSWER})"
        case $(cat ${ANSWER}) in
            "1")
                _helpraid ;;
            "2")
                _stopmd ;;
            "3")
                RAID_PARTITION=""
                _raid ;;
            "4")
                RAID_PARTITION="1"
                _raid ;;
              *)
                MDDONE=1 ;;
        esac
    done
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="1"
    else
        NEXTITEM="4"
    fi
}

# menu for lvm creation
_createlvm()
{
    NEXTITEM=""
    LVMDONE=0
    while [[ "${LVMDONE}" = "0" ]]; do
        if [[ -n "${NEXTITEM}" ]]; then
            DEFAULT="--default-item ${NEXTITEM}"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create physical volume, volume group or logical volume" 13 60 7 \
            "1" "LVM Help" \
            "2" "Reset Logical Volume completely" \
            "3" "Create Physical Volume" \
            "4" "Create Volume Group" \
            "5" "Create Logical Volume" \
            "6" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
        NEXTITEM="$(cat ${ANSWER})"
        case $(cat ${ANSWER}) in
            "1")
                _helplvm ;;
            "2")
                _stoplvm ;;
            "3")
                _createpv ;;
            "4")
                _createvg ;;
            "5")
                _createlv ;;
              *)
                LVMDONE=1 ;;
        esac
    done
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="2"
    else
        NEXTITEM="4"
    fi
}

# menu for luks creation
_createluks()
{
    NEXTITEM=""
    LUKSDONE=0
    while [[ "${LUKSDONE}" = "0" ]]; do
        if [[ -n "${NEXTITEM}" ]]; then
            DEFAULT="--default-item ${NEXTITEM}"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create Luks Encryption" 12 60 5 \
            "1" "Luks Help" \
            "2" "Reset Luks Encryption completely" \
            "3" "Create Luks" \
            "4" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
        NEXTITEM="$(cat ${ANSWER})"
        case $(cat ${ANSWER}) in
            "1")
                _helpluks ;;
            "2")
                _stopluks ;;
            "3")
                _luks ;;
              *)
                LUKSDONE=1 ;;
        esac
    done
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="3"
    else
        NEXTITEM="4"
    fi
}

auto_hwdetect()
{
    HWDETECT=""
    FBPARAMETER=""
    HWPARAMETER=""
    HWDETECTMODULES=""
    HWDETECTHOOKS=""
    HWDETECTFILES=""
    HWDETECTRC=""
    DIALOG --yesno "PRECONFIGURATION?\n-----------------\n\nDo you want to use 'hwdetect' for:\n'/etc/rc.conf' and '/etc/mkinitcpio.conf'?\n\nThis ensures consistent ordering of your hard disk / usb controllers, network and sound devices.\n\nIt is recommended to say 'YES' here." 18 70 && HWDETECT="yes"
    if [[ "${HWDETECT}" = "yes" ]]; then
        # check if running in vmware
        [[ "$(vmware-detect)" ]] && HWPARAMETER="${HWPARAMETER} --vmware"
        # check on ide-legacy boot parameter
        [[ "$(grep -w ide-legacy /proc/cmdline)" ]] && HWPARAMETER="${HWPARAMETER} --ide-legacy"
        # check on used keymap
        ! [[ "$(grep '^KEYMAP="us"' ${DESTDIR}/etc/rc.conf)" ]] && HWPARAMETER="${HWPARAMETER} --keymap"
        # check on usb input
        [[ "$(grep hid /proc/modules)" ]] && HWPARAMETER="${HWPARAMETER} --usbinput"
        # check on framebuffer modules and kms
        if [[ -e ${DESTDIR}/lib/initcpio/hooks/v86d && "$(grep -w uvesafb /proc/cmdline)" ]]; then
             FBPARAMETER="--uvesafb"
             HWDETECTFILES="/etc/modprobe.d/uvesafb.conf"
        fi
        [[ "$(grep -w ati-kms /proc/cmdline)" ]] && (FBPARAMETER="--ati-kms";HWDETECTFILES="/etc/modprobe.d/modprobe.conf")
        [[ "$(grep -w intel-kms /proc/cmdline)" ]] && (FBPARAMETER="--intel-kms";HWDETECTFILES="/etc/modprobe.d/modprobe.conf")
        [[ "$(grep -w nvidia-kms /proc/cmdline)" ]] && (FBPARAMETER="--nvidia-kms";HWDETECTFILES="/etc/modprobe.d/modprobe.conf")
        [[ "$(grep -w fbmodule /proc/cmdline)" ]] && FBPARAMETER="--fbmodule"
        if [[ "$(grep usb_storage /proc/modules)" ]]; then
            DIALOG --defaultno --yesno "Setup detected usb storage driver...\nDo you need support for booting from usb devices?" 0 0 && HWPARAMETER="${HWPARAMETER} --usb"
        fi
        if [[ "$(grep sbp2 /proc/modules)" ]]; then
            DIALOG --defaultno --yesno "Setup detected firewire storage driver...\nDo you need support for booting from firewire devices?" 0 0 && HWPARAMETER="${HWPARAMETER} --fw"
        fi
        if [[ "$(grep pcmcia /proc/modules)" ]]; then
            DIALOG --defaultno --yesno "Setup detected pcmcia hardware...\nDo you need support for booting from pcmcia devices?" 0 0 && HWPARAMETER="${HWPARAMETER} --pcmcia"
        fi
        if [[ "$(grep nfs /proc/modules)" ]]; then
            DIALOG --defaultno --yesno "Setup detected nfs driver...\nDo you need support for booting from nfs shares?" 0 0 && HWPARAMETER="${HWPARAMETER} --nfs"
        fi
        if [[ -e ${DESTDIR}/lib/initcpio/hooks/dmraid ]]; then
            if ! [[ "$(dmraid -r | grep ^no )" ]]; then
                HWPARAMETER="${HWPARAMETER} --dmraid"
            fi
        fi
        [[ "$(blkid -c=/dev/null -o value -s TYPE ${PART_ROOT})" = "btrfs" ]] && HWPARAMETER="${HWPARAMETER} --btrfs"
        HWDETECTMODULES="$(echo $(hwdetect ${FBPARAMETER} --hostcontroller --filesystem ${HWPARAMETER}) | sed -e 's#.*\" ##g')"
        HWDETECTHOOKS="$(hwdetect --rootdevice=${PART_ROOT} --hooks-dir=${DESTDIR}/lib/initcpio/install ${FBPARAMETER} ${HWPARAMETER} --hooks)"
        HWDETECTRC="$(echo $(hwdetect --net --sound ${HWPARAMETER})| sed -e 's#.*) ##g')"
        [[ -n "${HWDETECTMODULES}" ]] && sed -i -e "s/^MODULES=.*/${HWDETECTMODULES}/g" ${DESTDIR}/etc/mkinitcpio.conf
        [[ -n "${HWDETECTHOOKS}" ]] && sed -i -e "s/^HOOKS=.*/${HWDETECTHOOKS}/g" ${DESTDIR}/etc/mkinitcpio.conf
        [[ -n "${HWDETECTFILES}" ]] && sed -i -e "s#^FILES=.*#FILES=\"${HWDETECTFILES}\"#g" ${DESTDIR}/etc/mkinitcpio.conf
        [[ -n "${HWDETECTRC}" ]] && sed -i -e "s/^MODULES=.*/${HWDETECTRC}/g" ${DESTDIR}/etc/rc.conf
    fi
}

auto_fb()
{
    UVESAFB=""
    if [[ "$(grep -w ati-kms /proc/cmdline)" || "$(grep -w intel-kms /proc/cmdline)" || "$(grep -w nvidia-kms /proc/cmdline)" ]]; then
        # clean modprobe.conf file from options first
        sed -i -e '/options/d' ${DESTDIR}/etc/modprobe.d/modprobe.conf
        ! [[ "$(grep nouveau ${DESTDIR}/etc/modprobe.d/modprobe.conf)" ]] && grep ^[a-z] /etc/modprobe.d/modprobe.conf >> ${DESTDIR}/etc/modprobe.d/modprobe.conf
        ! [[ "$(grep i915 ${DESTDIR}/etc/modprobe.d/modprobe.conf)" ]] && grep ^[a-z] /etc/modprobe.d/modprobe.conf >> ${DESTDIR}/etc/modprobe.d/modprobe.conf
        ! [[ "$(grep radeon ${DESTDIR}/etc/modprobe.d/modprobe.conf)" ]] && grep ^[a-z] /etc/modprobe.d/modprobe.conf >> ${DESTDIR}/etc/modprobe.d/modprobe.conf
    fi
    if [[ -e ${DESTDIR}/lib/initcpio/hooks/v86d && "$(grep -w uvesafb /proc/cmdline)" ]]; then
        UVESAFB="$(grep ^[a-z] /etc/modprobe.d/uvesafb.conf)" 
        sed -i -e "s#options.*#${UVESAFB}#g" ${DESTDIR}/etc/modprobe.d/uvesafb.conf
    fi
}

auto_parameters()
{
    if [[ -s /tmp/.keymap ]]; then
        DIALOG --infobox "Setting the keymap: $(cat /tmp/.keymap | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s/^KEYMAP=.*/KEYMAP=\"$(cat /tmp/.keymap | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
    fi
    if [[ -s /tmp/.font ]]; then
        DIALOG --infobox "Setting the consolefont: $(cat /tmp/.font | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s/^CONSOLEFONT=.*/CONSOLEFONT=\"$(cat /tmp/.font | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
    fi
    if [[ -s  /tmp/.hardwareclock ]]; then
        DIALOG --infobox "Setting the hardwareclock: $(cat /tmp/.hardwareclock | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s/^HARDWARECLOCK=.*/HARDWARECLOCK=\"$(cat /tmp/.hardwareclock | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
    fi
    if [[ -s  /tmp/.timezone ]]; then
        DIALOG --infobox "Setting the timezone: $(cat /tmp/.timezone | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s#^TIMEZONE=.*#TIMEZONE=\"$(cat /tmp/.timezone | sed -e 's/\..*//g')\"#g" ${DESTDIR}/etc/rc.conf
    fi
}

auto_luks()
{
    # remove root device from crypttab
    if [[ -e /tmp/.crypttab && "$(grep -v '^#' ${DESTDIR}/etc/crypttab)"  = "" ]]; then
        # add to temp crypttab
        sed -i -e "/^$(basename ${PART_ROOT}) /d" /tmp/.crypttab
        cat /tmp/.crypttab >> ${DESTDIR}/etc/crypttab
    fi
}

auto_timesetting()
{
    TIMEZONE=""
    eval $(grep "^TIMEZONE" ${DESTDIR}/etc/rc.conf)
    if [[ "${TIMEZONE}" != "" && -e ${DESTDIR}/usr/share/zoneinfo/${TIMEZONE} ]]; then
        cp ${DESTDIR}/usr/share/zoneinfo/${TIMEZONE} ${DESTDIR}/etc/localtime
        cp ${DESTDIR}/usr/share/zoneinfo/${TIMEZONE} /etc/localtime
    fi
    if [[ ! -f ${DESTDIR}/var/lib/hwclock/adjtime ]]; then
        echo "0.0 0 0.0" > ${DESTDIR}/var/lib/hwclock/adjtime
    fi
}

auto_ftpmirror()
{
    # /etc/pacman.d/mirrorlist
    # add installer-selected mirror to the top of the mirrorlist
    if [[ "${MODE}" = "ftp" && "${SYNC_URL}" != "" ]]; then
        SYNC_URL="${SYNC_URL}"
        awk "BEGIN { printf(\"# Mirror used during installation\nServer = "${SYNC_URL}"\n\n\") } 1 " "${DESTDIR}/etc/pacman.d/mirrorlist" > /tmp/inst-mirrorlist
        mv /tmp/inst-mirrorlist "${DESTDIR}/etc/pacman.d/mirrorlist"
    fi
}

configure_system()
{
    destdir_mounts || return 1
    ## PREPROCESSING ##
    # only done on first invocation of configure_system and redone on canceled configure system
    if [[ ${S_CONFIG} -eq 0 ]]; then
        auto_ftpmirror
        auto_network
        auto_parameters
        auto_fb
        auto_hwdetect
    fi
    ## END PREPROCESS ##
    geteditor || return 1
    FILE=""

    # main menu loop
    while true; do
        S_CONFIG=0
        if [[ -n "${FILE}" ]]; then
            DEFAULT="--default-item ${FILE}"
        else
            DEFAULT=""
        fi
        DIALOG ${DEFAULT} --menu "Configuration" 20 80 15 \
            "/etc/rc.conf"                  "System Config" \
            "/etc/fstab"                    "Filesystem Mountpoints" \
            "/etc/mkinitcpio.conf"          "Initramfs Config" \
            "/etc/modprobe.d/modprobe.conf" "Kernel Modules" \
            "/etc/resolv.conf"              "DNS Servers" \
            "/etc/hosts"                    "Network Hosts" \
            "/etc/hosts.deny"               "Denied Network Services" \
            "/etc/hosts.allow"              "Allowed Network Services" \
            "/etc/locale.gen"               "Glibc Locales" \
            "/etc/pacman.d/mirrorlist"      "Pacman Mirror List" \
            "/etc/pacman.conf"              "Pacman Config File" \
            "Root-Password"                 "Set the root password" \
            "Return"                        "Return to Main Menu" 2>${ANSWER} || break
        FILE="$(cat ${ANSWER})"

        if [[ "${FILE}" = "Return" || -z "${FILE}" ]]; then       # exit
            S_CONFIG=1
            break
        elif [[ "${FILE}" = "/etc/rc.conf" ]]; then    # non-file
                # if user edited /etc/rc.conf, add the hostname to /etc/hosts if it's not already there.
                # note that if the user edits rc.conf several times to change the hostname more then once, 
                # we will add them all to /etc/hosts.  this is not perfect, but to avoid this, too much code would be required 
                # (feel free to prove me wrong :))
                # we could maybe do this just once after the user is really done here, but then he doesn't get 
                # to see the updated file while being in this menu...
                HOSTNAME=$(sed -n '/^HOSTNAME/s/HOSTNAME=//p' ${DESTDIR}${FILE} | sed 's/"//g')
                if ! [[ "$(grep '127\.0\.0\.1' ${DESTDIR}/etc/hosts | grep -q "${HOSTNAME}")" ]]; then
                    sed -i "s/127\.0\.0\.1.*/& ${HOSTNAME}/" ${DESTDIR}/etc/hosts
                fi
                ${EDITOR} ${DESTDIR}${FILE}
        elif [[ "${FILE}" = "/etc/mkinitcpio.conf" ]]; then    # non-file
            DIALOG --msgbox "The mkinitcpio.conf file controls which modules will be placed into the initramfs for your system's kernel.\n\n- Non US keymap users should add 'keymap' to HOOKS= array\n- USB keyboard users should add 'usbinput' to HOOKS= array\n- If you install under VMWARE add 'BusLogic' to MODULES= array\n- raid, lvm2, encrypt are not enabled by default\n- 2 or more disk controllers, please specify the correct module\n  loading order in MODULES= array \n\nMost of you will not need to change anything in this file." 18 70
            HOOK_ERROR=""
            ${EDITOR} ${DESTDIR}${FILE}
            for i in $(cat ${DESTDIR}/etc/mkinitcpio.conf | grep ^HOOKS | sed -e 's/"//g' -e 's/HOOKS=//g'); do
                [[ -e ${DESTDIR}/lib/initcpio/install/${i} ]] || HOOK_ERROR=1
            done
            if [[ "${HOOK_ERROR}" = "1" ]]; then
                DIALOG --msgbox "ERROR: Detected error in 'HOOKS=' line, please correct HOOKS= in /etc/mkinitcpio.conf!" 18 70
            fi
        elif [[ "${FILE}" = "/etc/locale.gen" ]]; then          # non-file
            # enable glibc locales from rc.conf
                for i in $(grep "^LOCALE" ${DESTDIR}/etc/rc.conf | sed -e 's/.*="//g' -e's/\..*//g'); do
                    sed -i -e "s/^#${i}/${i}/g" ${DESTDIR}/etc/locale.gen
                done
            ${EDITOR} ${DESTDIR}${FILE}
        elif [[ "${FILE}" = "Root-Password" ]]; then            # non-file
            PASSWORD=""
            while [[ "${PASSWORD}" = "" ]]; do
                DIALOG --insecure --passwordbox "Enter root password:" 0 0 2>${ANSWER} || return 1
                PASS=$(cat ${ANSWER})
                DIALOG --insecure --passwordbox "Retype root password:" 0 0 2>${ANSWER} || return 1
                PASS2=$(cat ${ANSWER})
                if [[ "${PASS}" = "${PASS2}" ]]; then
                    PASSWORD=${PASS}
                    echo ${PASSWORD} > /tmp/.password
                    echo ${PASSWORD} >> /tmp/.password
                    PASSWORD=/tmp/.password
                else
                    DIALOG --msgbox "Password didn't match, please enter again." 0 0
                fi
            done
            chroot ${DESTDIR} passwd root < /tmp/.password
            rm /tmp/.password
        else                                                #regular file
            ${EDITOR} ${DESTDIR}${FILE}
        fi
    done
    if [[ ${S_CONFIG} -eq 1 ]]; then
        # only done on normal exit of configure menu
        ## POSTPROCESSING ##
        # adjust time
        auto_timesetting
        # /etc/initcpio.conf
        run_mkinitcpio
        # /etc/locale.gen
        chroot ${DESTDIR} locale-gen >/dev/null 2>&1
        ## END POSTPROCESSING ##
        NEXTITEM="7"
    fi
}

install_bootloader()
{
    destdir_mounts || return 1
    if [[ "${NAME_SCHEME_PARAMETER_RUN}" = "" ]]; then
        set_device_name_scheme || return 1
    fi
    source_set || return 1
    pacman_conf
    prepare_pacman
    CANCEL=""
    
    [[ "$(dmesg | grep 'EFI_ARCH_x86_64')" ]] && EFI_x86_64="1"
    [[ "$(dmesg | grep 'EFI_ARCH_i386')" ]] && EFI_i386="1"
    
    [[ "${EFI_x86_64}" = "1" ]] && DIALOG --yesno "Setup detected that you are using x86_64 (64-bit) (U)EFI ...\nDo you want to install grub2-efi-x86_64 as the bootloader?" 0 0 && dogrub2_efi_x86_64
    [[ "${EFI_i386}" = "1" ]] && DIALOG --yesno "Setup detected that you are using i386 (32-bit) (U)EFI ...\nDo you want to install grub2-efi-i386 as the bootloader?" 0 0 && dogrub2_efi_i386
    
    DIALOG --menu "Which BIOS/UEFI bootloader would you like to use?" 13 55 7 \
        "EXTLINUX" "EXTLINUX/SYSLINUX" \
        "GRUB2_BIOS" "GRUB2" \
        "GRUB2_EFI_x86_64" "GRUB2 64-bit UEFI" \
        "GRUB2_EFI_i386" "GRUB2 32-bit UEFI" \
        "GRUB_LEGACY" "GRUB LEGACY" \
        "LILO" "LILO" 2>${ANSWER} || CANCEL=1
    case $(cat ${ANSWER}) in
        "EXTLINUX") doextlinux ;;
        "GRUB2_BIOS") dogrub2_bios ;;
        "GRUB2_EFI_x86_64") dogrub2_efi_x86_64 ;;
        "GRUB2_EFI_i386") dogrub2_efi_i386 ;;
        "GRUB_LEGACY") dogrub ;;
        "LILO") dolilo ;;
    esac
    if [[ "${CANCEL}" = "1" ]]; then
        NEXTITEM="7"
    else
        NEXTITEM="8"
    fi
}

mainmenu() {
    if [[ -n "${NEXTITEM}" ]]; then
        DEFAULT="--default-item ${NEXTITEM}"
    else
        DEFAULT=""
    fi
    dialog ${DEFAULT} --backtitle "${TITLE}" --title " MAIN MENU " \
    --menu "Use the UP and DOWN arrows to navigate menus.\nUse TAB to switch between buttons and ENTER to select." 17 58 13 \
    "0" "Set Keyboard And Console Font" \
    "1" "Set Time And Date" \
    "2" "Prepare Hard Drive" \
    "3" "Select Source" \
    "4" "Select Packages" \
    "5" "Install Packages" \
    "6" "Configure System" \
    "7" "Install Bootloader" \
    "8" "Exit Install" 2>${ANSWER}
    NEXTITEM="$(cat ${ANSWER})"
    case $(cat ${ANSWER}) in
        "0")
            set_keyboard ;;
        "1")
            set_clock ;;
        "2")
            prepare_harddrive ;;
        "3")
            select_source ;;
        "4")
            select_packages ;;
        "5")
            install_packages ;;
        "6")
            configure_system ;;
        "7")
            install_bootloader ;;
        "8")
            if [[ "${S_SRC}" = "1" && "${MODE}" = "media" ]]; then
                umount /src >/dev/null 2>&1
            fi
            [[ -e /tmp/.setup-running ]] && rm /tmp/.setup-running
            clear
            echo ""
            echo "If the install finished successfully, you can now type 'reboot'"
            echo "to restart the system."
            echo ""
            exit 0 ;;
        *)
            DIALOG --yesno "Abort Installation?" 6 40 && [[ -e /tmp/.setup-running ]] && rm /tmp/.setup-running && clear && exit 0
            ;;
    esac
}

#####################
## begin execution ##
if [[ -e /tmp/.setup-running ]]; then
    echo "HINT:"
    echo "setup already runs on a different console!"
    echo "Please remove /tmp/.setup-running first to launch setup!"
    exit 1
fi
: >/tmp/.setup-running
: >/tmp/.setup

DIALOG --msgbox "Welcome to the Arch Linux Installation program.\n\nThe install process is fairly straightforward, and you should run through the options in the order they are presented.\n\nIf you are unfamiliar with partitioning/making filesystems, you may want to consult some documentation before continuing.\n\nYou can view all output from commands by viewing your VC7 console (ALT-F7). ALT-F1 will bring you back here." 14 65

while true; do
    mainmenu
done

clear
exit 0

# vim: set ts=4 sw=4 et:
