#!/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" -a "$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" -a "$ACTIVATE_RAID" = "no"  -a "$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 -a -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" -a "$(cat $block/$dev/removable)" = "1" -a ! "$(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\[")" -o "$(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\[")" -o "$(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)" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LVM2_member")" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "crypto_LUKS")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#${disk}\p##g") 2>/dev/null | grep "5")" -o "$(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)" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$i | grep "LVM2_member")" -o $(blkid -c=/dev/null -o value -s TYPE /dev/$i | grep "crypto_LUKS") -o "$(sfdisk -c /dev/$dev $(echo $i | sed -e "s#${dev}\p##g") 2>/dev/null | grep "5")" -o "$(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\"")" -o "$(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\"")" -o ! "$(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
    if [ -d /dev/mapper ] ; then
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
            if ! [ "$(dmraid -s -c | grep ^$devpath)" -o "$(ls $partofcrypt 2>/dev/null | grep /dev/mapper/$devpath$)" -o "$(ls $partoflvm 2>/dev/null | grep /dev/mapper/$devpath$)" -o "$(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 devpath in $(ls /dev/mapper/$fakeraid*); do
                    if ! [ "$(dmraid -s -c | grep $devpath$)" -o "$(ls $partofcrypt 2>/dev/null | grep /dev/mapper/$devpath$)" -o "$(ls $partoflvm 2>/dev/null | grep /dev/mapper/$devpath$)" -o "$(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)" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LVM2_member")" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "crypto_LUKS")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk##g") 2>/dev/null | grep "5")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk\p##g") 2>/dev/null | grep "5")" -o "$(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 $(ls /dev/mapper 2>/dev/null | grep -v control); do
        if ! [ "$(dmraid -s -c | grep $i$)" ]; then
            rm -f /dev/mapper/$(echo $i | sed -n -e "s/\(.*\)p/\1/p")
            ln -s /dev/mapper/$i  /dev/mapper/$(echo $i | sed -n -e "s/\(.*\)p/\1/p")
        fi
    done
}

# remove created symlinks
remove_grub_dmraid_hack(){
    for i in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        if ! [ "$(dmraid -s -c | grep $i$)" ]; then
            rm -f /dev/mapper/$(echo $i | sed -n -e "s/\(.*\)p/\1/p")
        fi
    done
}

get_grub2_map() {
    rm /tmp/device.map
    DIALOG --infobox "Generating GRUB2 device map...\nThis could take a while.\n\n Please be patient." 0 0
    $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)" -o "$(echo $1 | grep /dev/hd)" -o "$(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)" -o "$(echo $1 | grep /dev/hd)" -o "$(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
        if ! [ "$(which vi)" ]; then
            DIALOG --menu "Select a Text Editor to Use" 10 35 3 \
                "1" "nano (easier)" 2>$ANSWER
        else
            DIALOG --menu "Select a Text Editor to Use" 10 35 3 \
                "1" "nano (easier)" \
                "2" "vi" 2>$ANSWER
        fi
        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
                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 512 '*' $(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 512 '*' $(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 512 '*' $(cat $block/ida\!$(basename $i | sed -e 's#p.*##g')/size))/1000000)) MB; echo "\n"
            else
                echo -n "$i : "; echo $(($(expr 512 '*' $(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]')"  -o  "$(echo "$i" | grep '/dev/md[0-9]p')" -o "$(echo "$i" | grep '/dev/mmcblk')" ]; then
            echo -n "$i: "; echo $(($(expr 512 '*' $(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 512 '*' $(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 512 '*' $(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 512 '*' $(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 512 '*' $(cat $block/$(basename $i)/size))/1000000)) MB; echo "\n"
        # mapper devices
        elif [ "$(echo "$i" | grep '/dev/mapper')" ]; then
            # 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 512 '*' $(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 -)"
    LV_GROUPS="$(vgs -o vg_name --noheading)"
    LV_PHYSICAL="$(pvs -o pv_name --noheading)"
    ! [ "$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=""
    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 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
            wipefs -a $LUKS_REAL_DEVICE > $LOG
        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" -o "$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" -o "$LEVEL" = "raid6" -o "$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" -o "$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" -o "$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 fdisk program where you can partition your raiddevice to your needs." 18 70
            clear
            fdisk -l $DISC
            fdisk $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)" != "" -a "$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)"; 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\M $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 passphrasefor 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
    cryptsetup luksOpen $PART $LUKSDEVICE >$LOG <$LUKSPASSPHRASE  
    LUKSPASSPHRASE="$(cat $LUKSPASSPHRASE)"
    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()
{
    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)" != "" -a "$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
        # 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-xts-plain -s 512 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
    DISC_SIZE=$(echo $(($(expr 512 '*' $(cat $block/$(basename $DISC)/size))/1000000)))
    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)" -a "$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" -o "$BOOT_PART_SIZE" -lt "16" -o "$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" = "" -o  "$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" = "" -o "$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_AUTO swap:$SWAP_PART_SIZE:swap::SWAP_AUTO /:$ROOT_PART_SIZE:$FSTYPE::ROOT_AUTO /home:*:$FSTYPE::HOME_AUTO"

    # 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|| 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
    [ "$(parted -s $DISC print | grep "bios_grub")" ] && BIOS_GRUB=1
    if [ "$GUID_DETECTED" = "" ] ; then
        DIALOG --defaultno --yesno "Setup detected no GUID (gpt) partition table on $DISC.\nDo you want to create a GUID (gpt) 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 -a optimal -s $DISC mklabel GPT >$LOG
    fi
    if [ "$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
    if [ "$CREATE_BIOS_GRUB" = "1" -a "$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 fdisk program 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- 'h' to get help text\n- 'p' to show  partition table\n- 'n' for new partition\n- 'd' for deleting a partition\n- 'q' to leave fdisk\n\nNOTE: fdisk 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
                fdisk -l $DISC
                fdisk $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" -a "$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"
    DIALOG --defaultno --yesno "Would you like to compress the data on $PART?" 0 0 && BTRFS_COMPRESS="compress"
}

# ask for btrfs ssd option
btrfs_ssd() {
    BTRFS_SSD="NONE"
    DIALOG --defaultno --yesno "Would you like to optimize the data for ssd disk usage on $PART?" 0 0 && BTRFS_SSD="ssd"
}

# 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 -a ! "$BTRFS_LEVEL" = "raid10" ] && BTRFS_DONE="DONE _"
        [ "$RAIDNUMBER" -ge 5 -a "$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 --yesno "Would you like to create a 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" -a "$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" -a "$FSTYPE" = "btrfs" -a ! "$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" -a "$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
    fi
    FILESYSTEM_FINISH="yes"
}

select_filesystem() {
    FILESYSTEM_FINISH=""
    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" = "" -a -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"
    if [ "$FSTYPE" = "btrfs" ]; then
        btrfs_compress
        btrfs_ssd
    fi
}

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
        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
        # btrfs is not well supported by LTS .32 kernel
        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)" -a "$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)" ] && FSOPTS="$FSOPTS ntfs-3g NTFS"
        [ "$(which mkfs.vfat 2>/dev/null)" ] && FSOPTS="$FSOPTS vfat VFAT"
        #
        # 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" -a "$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" -a "$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" -a "${_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" -a -n "${_btrfssubvolume}" -a "${_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" -a -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
    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" -a -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)" -a "$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 [ "$(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 [ -e /var/state/dhcp/dhclient.leases ]; then
        ! [ "$(echo $PACKAGES | grep -w dhclient)" ] && PACKAGES="$PACKAGES dhclient"
    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 -o "$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" -a "$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" -o "$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
            # clean /media from old floppy,cd,dvd entries
            rm -r $DESTDIR/media/cd*
            rm -r $DESTDIR/media/dvd*
            rm -r $DESTDIR/media/fl*
            # add floppy,cd and dvd entries first
            for i in $(ls -d /dev/cdro* | grep -v "0"); do
                k=$(echo $i | sed -e 's|/dev/||g')
                echo "$i /media/$k   auto    ro,user,noauto,unhide   0      0" >>$DESTDIR/etc/fstab
            # create dirs in /media
                mkdir -p $DESTDIR/media/$k
            done
            for i in $(ls -d /dev/dvd* | grep -v "0"); do
                k=$(echo $i | sed -e 's|/dev/||g')
                echo "$i /media/$k   auto    ro,user,noauto,unhide   0      0" >>$DESTDIR/etc/fstab
            # create dirs in /media
                mkdir -p $DESTDIR/media/$k
            done
            for i in $(ls -d /dev/fd[0-9] | grep -v "[0-9][0-9][0-9]"); do
                k=$(echo $i | sed -e 's|/dev/||g')
                echo "$i /media/$k   auto    user,noauto   0      0" >>$DESTDIR/etc/fstab
            # create dirs in /media
                mkdir -p $DESTDIR/media/$k
            done
            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 gcpid for nilfs2
ROOTFLAGS="$(findmnt -m -n -o options -T $DESTDIR | sed -e 's/,gcpid=.*[0-9]//g')"
}

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/usr/sbin/extlinux" -o -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 () {
    DIALOG --msgbox "Attention:\nIn order to get a booting system, you need the boot flag on the partition syslinux will boot the kernel from!" 0 0
    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
    MBR=$DESTDIR/usr/lib/syslinux/mbr.bin
    [ -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/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 "kernel $subdir/$VMLINUZ" >> ${TEMPDIR}/${SYSLINUX_CONF}
    if [ "$NAME_SCHEME_PARAMETER" = "UUID" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
        echo "append initrd=$subdir/$KERNELPKG.img root=${_rootpart} rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP" | sed -e 's#  # #g' >> ${TEMPDIR}/${SYSLINUX_CONF}
    else
        echo "append initrd=$subdir/$KERNELPKG.img root=${PART_ROOT} rootflags=$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 "kernel $subdir/$VMLINUZ" >> ${TEMPDIR}/${SYSLINUX_CONF}
    if [ "$NAME_SCHEME_PARAMETER" = "UUID" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
        echo "append initrd=$subdir/$KERNELPKG-fallback.img root=${_rootpart} rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP" | sed -e 's#  # #g' >> ${TEMPDIR}/${SYSLINUX_CONF}
    else
        echo "append initrd=$subdir/$KERNELPKG-fallback.img root=${PART_ROOT} rootflags=$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
    cp  ${TEMPDIR}/${SYSLINUX_CONF} ${DESTDIR}/boot/${SYSLINUX_CONF}
    cp  ${DESTDIR}/usr/lib/syslinux/*.c32 ${DESTDIR}/boot/
    cat ${MBR} > ${ROOTDEV}
    if [ -e ${DESTDIR}/boot/ldlinux.sys ]; then 
        rm ${DESTDIR}/boot/ldlinux.sys
    fi
}
# finish_syslinux
finish_syslinux () {
    if [ $? -gt 0 ]; then
        chroot_umount
        DIALOG --msgbox "Error installing $SYSLINUX. (see $LOG for output)" 0 0
        return 1
    fi
    [ -f "/src/isolinux/splash.png" ] && cp /src/isolinux/splash.png $DESTDIR/boot
    chroot_umount
    DIALOG --msgbox "$SYSLINUX was successfully installed." 0 0
}

# install extlinux bootloader
doextlinux () {
    bootdev=""
    SYSLINUX_PACKAGES="syslinux"
    SYSLINUX=EXTLINUX
    SYSLINUX_PROGRAM=extlinux
    SYSLINUX_CONF=extlinux.conf
    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" -o "$FSTYPE" = "ext3" -o "$FSTYPE" = "ext4" -o "$FSTYPE" = "btrfs" ]; then
        DIALOG --msgbox "Error:\nCouldn't find ext2/3/4 or btrfs 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)" -o "$(echo $bootdev | grep /dev/mapper)" ]; then
        DIALOG --msgbox "Error:\n$SYSLINUX cannot boot from any raid, 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 none raid1 devices." 0 0
            return 1
        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 || return 1
    chroot_mount
    chroot $DESTDIR $SYSLINUX_PROGRAM --install /boot >$LOG 2>&1
    finish_syslinux
}

# install syslinux bootloader
dosyslinux() {
    bootdev=""
    subdir=""
    SYSLINUX_PACKAGES="syslinux mtools"
    SYSLINUX=SYSLINUX
    SYSLINUX_CONF=syslinux.cfg
    SYSLINUX_PROGRAM=syslinux
    prepare_syslinux
    # look for a separately-mounted /boot partition
    bootdev=$(mount | grep $DESTDIR/boot | cut -d' ' -f 1)
    if [ "$bootdev" = "" ]; then
        DIALOG --msgbox "Error:\nCouldn't find separate /boot partition." 0 0
        return 1
    fi
    # syslinux only can boot from vfat partitions!
    FSTYPE="$(blkid -c /dev/null $bootdev -o value -s TYPE)"
    if ! [ "$FSTYPE" = "vfat" ]; then
        DIALOG --msgbox "Error:\nCouldn't find vfat /boot partition." 0 0
        return 1
    fi
    # syslinux cannot boot from any raid, raid partition, encrypted and dmraid device
    if [ "$(echo $bootdev | grep /dev/md)" -o "$(echo $bootdev | grep /dev/mapper)" ]; then
        DIALOG --msgbox "Error:\n$SYSLINUX cannot boot from any raid, raid partition, encrypted or dmraid device." 0 0
        return 1
    fi
    common_syslinux || return 1
    chroot_mount
    chroot $DESTDIR $SYSLINUX_PROGRAM $bootdev >$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" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
            sed -i "s|.*root=.*$|append=\"root=${_rootpart} rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP\"|g" $DESTDIR/etc/lilo.conf
        else
            sed -i "s|.*root=.*$|append=\"root=${PART_ROOT} rootflags=$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 > $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" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
                    echo "kernel $subdir/$VMLINUZ root=${_rootpart} rootflags=$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=$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" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
                    echo "kernel $subdir/$VMLINUZ root=${_rootpart} rootflags=$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=$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" -o "$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(){
    ### 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
    if [ ! -f $DESTDIR/boot/grub/grub.cfg ]; then
        DIALOG --msgbox "Couldn't find $DESTDIR/boot/grub/grub.cfg, installing grub2 now ..." 0 0
        PACKAGES="grub2"
        run_pacman
        # reset PACKAGES after installing
        PACKAGES=""
    fi
    bootdev=""
    grubdev=""
    complexuuid=""
    FAIL_COMPLEX=""
    GRUB_LEGACY=""
    USE_DMRAID=""
    RAID_ON_LVM=""
    common_bootloader_checks
    get_grub2_map
    # try to auto-configure GRUB2...
    if [ "$PART_ROOT" != "" ]; then
        check_bootpart
        abort_btrfs_bootpart || return 1
        abort_nilfs_bootpart || return 1
        # check if raid, raid partition, dmraid or device devicemapper is used
        if [ "$(echo $bootdev | grep /dev/md)" -o "$(echo $bootdev | grep /dev/mapper)" ]; then
                # boot from lvm and raid devices is supported
                FAIL_COMPLEX="0"
            if [ "$(echo $bootdev | grep /dev/md*p)" -o "$(dmsetup info $bootdev | grep 'DMRAID')" -o "$(cryptsetup status $bootdev)" ]; then
                # raid with no supperblock 0.90, partitionable raid, dmraid 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
        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 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- dmraid aka fakeraid devices are not supported\n- encrypted devices are not supported" 0 0
                return 1
        fi
        if [ "$grubdev" != "" ]; then
            cp $DESTDIR/boot/grub/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/boot/grub/grub.cfg
            rm -f /tmp/.grub.cfg
            # keep the file from being completely bogus
            if [ "$grubdev" = "DEVICE NOT FOUND" ]; then
                DIALOG --msgbox "Your device, which contains /boot could not be autodetected by setup.\n\nEnsure you adjust the 'set root=(hd0,1)' line in your GRUB config accordingly." 0 0
                grubdev="(hd0,1)"
            fi
            NUMBER=0
            echo "" >>$DESTDIR/boot/grub/grub.cfg
            sort /tmp/.device-names >>$DESTDIR/boot/grub/grub.cfg
            # create default grub entries
            echo "" >>$DESTDIR/boot/grub/grub.cfg
            [ "$USE_RAID" = "1" ] && echo "insmod raid" >>$DESTDIR/boot/grub/grub.cfg
            ! [ "$RAID_ON_LVM" = "" ] && echo "insmod lvm" >>$DESTDIR/boot/grub/grub.cfg
            echo "# ($NUMBER) Arch Linux" >>$DESTDIR/boot/grub/grub.cfg
            echo "menuentry \"Arch Linux\" {" >>$DESTDIR/boot/grub/grub.cfg
            if [ "$FAIL_COMPLEX" = "0" ]; then
                echo "set root=($grubdev)" >>$DESTDIR/boot/grub/grub.cfg
            else
                echo "set root=$grubdev" >>$DESTDIR/boot/grub/grub.cfg
            fi
            [ "$FAIL_COMPLEX" = "0" ] && echo "search --fs-uuid --set $complexuuid" >>$DESTDIR/boot/grub/grub.cfg
            if [ "$NAME_SCHEME_PARAMETER" = "UUID" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
                echo "linux $subdir/$VMLINUZ root=${_rootpart} rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/grub.cfg
            else
                echo "linux $subdir/$VMLINUZ root=$PART_ROOT rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/grub.cfg
            fi
            echo "initrd $subdir/$KERNELPKG.img" >>$DESTDIR/boot/grub/grub.cfg
            echo "}" >>$DESTDIR/boot/grub/grub.cfg
            echo "" >>$DESTDIR/boot/grub/grub.cfg
            # adding fallback/full image
            NUMBER=$(($NUMBER+1))
            echo "# ($NUMBER) Arch Linux" >>$DESTDIR/boot/grub/grub.cfg
            echo "menuentry  \"Arch Linux Fallback\" {" >>$DESTDIR/boot/grub/grub.cfg
            if [ "$FAIL_COMPLEX" = "0" ]; then
                echo "set root=($grubdev)" >>$DESTDIR/boot/grub/grub.cfg
            else
                echo "set root=$grubdev" >>$DESTDIR/boot/grub/grub.cfg
            fi
            [ "$FAIL_COMPLEX" = "0" ] && echo "search --fs-uuid --set $complexuuid" >>$DESTDIR/boot/grub/grub.cfg
            if [ "$NAME_SCHEME_PARAMETER" = "UUID" -o "$NAME_SCHEME_PARAMETER" = "LABEL" ]; then
                echo "linux $subdir/$VMLINUZ root=${_rootpart} rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/grub.cfg
            else
                echo "linux $subdir/$VMLINUZ root=$PART_ROOT rootflags=$ROOTFLAGS rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/grub.cfg
            fi
            echo "initrd $subdir/$KERNELPKG-fallback.img" >>$DESTDIR/boot/grub/grub.cfg
            echo "}" >>$DESTDIR/boot/grub/grub.cfg
            ### TODO:
            # Is it possible to detect a windows installation?
            NUMBER=$(($NUMBER+1))
            echo "" >>$DESTDIR/boot/grub/grub.cfg
            echo "## ($NUMBER) Windows" >>$DESTDIR/boot/grub/grub.cfg
            echo "#menuentry \"Windows\" {" >>$DESTDIR/boot/grub/grub.cfg
            echo "#set root=(hd0,3)" >>$DESTDIR/boot/grub/grub.cfg
            echo "#chainloader +1" >>$DESTDIR/boot/grub/grub.cfg
            echo "#}" >>$DESTDIR/boot/grub/grub.cfg
        fi
    fi

    # Edit grub.cfg config file
    DIALOG --msgbox "Before installing GRUB2, you must review the 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}/boot/grub/grub.cfg

    # 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
    DIALOG --infobox "Installing the GRUB2 bootloader..." 0 0
    # freeze and unfreeze xfs filesystems to enable grub2 installation on xfs filesystems
    freeze_xfs
    chroot_mount
    chroot $DESTDIR /sbin/grub-install --no-floppy $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
}

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" "Setup 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 -a "$(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 --hooks $FBPARAMETER $HWPARAMETER)"
        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)" -o "$(grep -w intel-kms /proc/cmdline)" -o "$(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 -a "$(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()
{
    if [ -e /tmp/.crypttab -a "$(grep -v '^#' ${DESTDIR}/etc/crypttab)"  = "" ]; then
        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" != "" -a -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" -a "${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" -o -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=""
    DIALOG --menu "Which bootloader would you like to use?" 12 55 5 \
        "GRUB" "Use the GRUB bootloader (default)" \
        "GRUB2" "Use the GRUB2 bootloader (experimental)" \
        "LILO" "Use the LILO bootloader" \
        "EXTLINUX" "Use the EXTLINUX bootloader" \
        "SYSLINUX" "Use the SYSLINUX bootloader" 2>$ANSWER || CANCEL=1
    case $(cat $ANSWER) in
        "GRUB") dogrub ;;
        "GRUB2") dogrub2 ;;
        "LILO") dolilo ;;
        "EXTLINUX") doextlinux ;;
        "SYSLINUX") dosyslinux ;;
    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" -a "$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:
