2018-08-12 23:24:38 -05:00
#!/usr/bin/bash
2018-07-18 19:50:37 -05:00
# vim:ft=sh:fdm=marker:fmr={,}
# This program is free software, provided under the GNU GPL
2018-07-18 19:52:06 -05:00
# Written by Nathaniel Maia for use in Archlabs
# Some ideas and code were taken from other installers
# AIF, ABIF, Calamares, Arch Wiki.. Credit where credit is due
2018-07-18 19:50:37 -05:00
# set -n
# set -u
# set -v
2018-07-18 19:52:06 -05:00
# immutable variables {
2018-07-18 19:50:37 -05:00
2018-08-12 23:24:38 -05:00
readonly DIST="Archlabs" # Linux distributor
2018-08-22 02:26:21 -05:00
readonly VER="1.6.38" # Installer version
2018-08-12 23:24:38 -05:00
readonly LIVE="liveuser" # Live session user
readonly TRN="/usr/share/archlabs-installer" # Translation path
readonly MNT="/mnt/install" # Install mountpoint
readonly ERR="/tmp/errlog" # Built-in error log
2018-07-18 19:50:37 -05:00
2018-08-18 19:59:25 -05:00
# create a regex string of all usb devices on the system
for dev in $(lsblk -lno NAME,TRAN | awk '/usb/ {print $1}'); do USB_DEVS="${dev}$([[ $USB_DEVS ]] && echo -n "|$USB_DEVS")"; done
# determine which device was used for booting to ignore later during partition select
readonly IGNORE_DEV="$(lsblk -lno NAME,TYPE,TRAN,MOUNTPOINT | awk "/$USB_DEVS/"' && /\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
readonly SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE,TRAN | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
readonly LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if($1) print $1 " -"}' /etc/locale.gen)"
2018-07-18 19:52:06 -05:00
readonly SYS_MEM=$(grep 'MemTotal' /proc/meminfo | awk '{print int($2 / 1024)}')
readonly DEV_COUNT="$(wc -l <<< "$SYS_DEVS")"
2018-08-18 19:59:25 -05:00
readonly KBD="$(find /usr/share/kbd/keymaps -name '*.map.gz')"
2018-07-18 19:52:06 -05:00
readonly CONSOLE_MAPS="$(awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " -"}' <<< "$KBD" | sort -r)"
2018-07-18 19:50:37 -05:00
2018-08-18 19:59:25 -05:00
# create associative array for SUBZONES[zone], value is: 'sub-zone country_code'
2018-07-18 19:52:06 -05:00
declare -Ag SUBZONES
2018-08-17 20:44:17 -05:00
for zone in America Australia Asia Atlantic Africa Europe Indian Pacific Arctic Antarctica; do
2018-07-18 19:52:06 -05:00
SUBZONES[$zone]="$(awk "/$zone\// {gsub(/$zone\//, \"\"); print \$3 \" \"\$1}" /usr/share/zoneinfo/zone.tab)"
2018-07-18 19:50:37 -05:00
done
2018-07-18 19:52:06 -05:00
readonly SUBZONES # make it read only
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
for t in st termite xterm; do
hash $t >/dev/null 2>&1 && { readonly TERM_CMD="$t"; break; }
2018-07-18 19:50:37 -05:00
done
2018-07-18 19:52:06 -05:00
# static string of keymap codes and respective language
readonly KEYMAPS="us English cm English gb English au English gh English za English
ng English ca French cd French gn French tg French fr French de German at German ch German
es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic sy Arabic ara Arabic
ua Ukrainian cz Czech ru Russian sk Slovak nl Dutch it Italian hu Hungarian cn Chinese
tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai la Lao pl Polish se Swedish
is Icelandic fi Finnish dk Danish be Belgian in Indian al Albanian am Armenian bd Bangla
ba Bosnian bg Bulgarian dz Berber mm Burmese hr Croatian gr Greek il Hebrew ir Persian iq Iraqi
af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz kz Kazakh lt Lithuanian mt Maltese
mn Mongolian no Norwegian ro Romanian rs Serbian si Slovenian tj Tajik lk Sinhala tr Turkish
uz Uzbek ie Irish pk Urdu mv Dhivehi epo Esperanto np Nepali et Amharic sn Wolof ml Bambara
tz Swahili ke Swahili bw Tswana ph Filipino id Indonesian my Malay tm Turkmen bt Dzongkha
lv Latvian md Moldavian mao Maori by Belarusian me Montenegrin mk Macedonian kh Khmer
az Azerbaijani"
declare -Agr BOOT_MNTS=(
2018-08-17 20:44:17 -05:00
[UEFI-grub]="/boot/efi" [UEFI-systemd-boot]="/boot"
[BIOS-grub]="/boot" [BIOS-syslinux]="/boot"
2018-07-18 19:52:06 -05:00
)
2018-08-17 20:44:17 -05:00
# static list of bootloaders & boot partition mountpoints stored as the system type (BIOS or UEFI)
2018-07-18 19:52:06 -05:00
declare -Agr BOOTLOADERS=(
[UEFI]="grub ${BOOT_MNTS[UEFI-grub]} systemd-boot ${BOOT_MNTS[UEFI-systemd-boot]}"
[BIOS]="grub ${BOOT_MNTS[BIOS-grub]} syslinux ${BOOT_MNTS[BIOS-syslinux]}"
)
2018-08-17 20:44:17 -05:00
2018-07-18 19:52:06 -05:00
# static mkfs commands for each filesystem offered
declare -Agr FS_CMDS=(
2018-08-12 23:24:38 -05:00
[ext2]="mkfs.ext2 -q" [ext3]="mkfs.ext3 -q" [ext4]="mkfs.ext4 -q"
2018-08-17 20:44:17 -05:00
[f2fs]="mkfs.f2fs" [jfs]="mkfs.jfs -q" [xfs]="mkfs.xfs -f" [nilfs2]="mkfs.nilfs2 -q"
2018-08-12 23:24:38 -05:00
[ntfs]="mkfs.ntfs -q" [reiserfs]="mkfs.reiserfs -q" [vfat]="mkfs.vfat -F32"
2018-07-18 19:52:06 -05:00
)
2018-08-17 20:44:17 -05:00
2018-07-18 19:52:06 -05:00
# static filesystem mount options
declare -Agr FS_OPTS=(
[vfat]="" [ntfs]="" [ext2]="" [ext3]=""
[ext4]="dealloc - off discard - off nofail - off noacl - off relatime - off noatime - off nobarrier - off nodelalloc - off"
[jfs]="discard - off errors=continue - off errors=panic - off nointegrity - off"
[reiserfs]="acl - off nolog - off notail - off replayonly - off user_xattr - off"
[xfs]="discard - off filestreams - off ikeep - off largeio - off noalign - off nobarrier - off norecovery - off noquota - off wsync - off"
[nilfs2]="discard - off nobarrier - off errors=continue - off errors=panic - off order=relaxed - off order=strict - off norecovery - off"
2018-08-17 20:44:17 -05:00
[f2fs]="data_flush - off disable_roll_forward - off disable_ext_identify - off discard - off fastboot - off flush_merge - off inline_xattr - off inline_data - off inline_dentry - off no_heap - off noacl - off nobarrier - off noextent_cache - off noinline_data - off norecovery - off"
2018-07-18 19:52:06 -05:00
)
2018-07-18 19:50:37 -05:00
# }
2018-07-28 15:03:43 -05:00
luks_variable_init() {
declare -g LUKS=0
declare -g LVM=0
declare -g VOL_GROUP_MB=0
declare -g LUKS_NAME="cryptroot"
declare -g LUKS_PART=""
declare -g LUKS_PASS=""
declare -g LUKS_UUID=""
declare -g LUKS_DEV=""
declare -g MKINIT_HOOKS="shutdown"
declare -g SEPERATE_BOOT=0
}
2018-07-18 19:52:06 -05:00
initialize_variables() {
# Modified during runtime and are all globally accessible
# This is called once when the script is started, and again if/when an error occurs
# Some of may never be used, depending on the system and choices made
declare -g ROOT_PART=""
declare -g BOOT_DEVICE=""
declare -g BOOT_PART=""
declare -g BOOTLOADER=""
declare -g EXTRA_MNT=""
declare -g SWAP_FILE="none"
declare -g SWAP_SIZE="${SYS_MEM}M"
2018-08-20 04:26:13 -05:00
declare -g KERNEL="linux"
2018-07-18 19:52:06 -05:00
declare -g NEWUSER=""
declare -g USER_PASS=""
declare -g ROOT_PASS=""
2018-08-12 23:24:38 -05:00
declare -g LOGIN_WM=""
declare -g LOGIN_TYPE=""
declare -g INSTALL_WMS=""
declare -g WM_PACKAGES=""
declare -g EXTRA_PACKAGES=""
2018-08-19 22:32:21 -05:00
declare -g REMOVE_PKGS=""
2018-08-12 23:24:38 -05:00
2018-07-18 19:52:06 -05:00
declare -g CURRENT_MENU="main"
declare -g MENU_HIGHLIGHT=0
2018-07-28 15:03:43 -05:00
declare -g EDITOR_CHOICE=""
2018-07-30 02:30:35 -05:00
declare -g MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate"
2018-07-18 19:52:06 -05:00
# boolean checks
2018-08-12 23:24:38 -05:00
declare -g AUTOLOGIN=false
2018-07-18 19:52:06 -05:00
declare -g FIRST_PREP=false
declare -g FIRST_CONFIG=false
declare -g UNPACKED_BASE=false
declare -g SET_ROOT_PASSWD=false
declare -g TIMEZONE_SET=false
2018-07-27 22:54:09 -05:00
declare -g DONE_UPDATE=false
2018-07-18 19:52:06 -05:00
declare -g BOOT_DONE=false
declare -g FULL_DONE=false
declare -g CONFIRM_DONE=false
2018-08-17 03:21:15 -05:00
declare -g GRUB_UEFI_FALLBACK=false
2018-07-18 19:52:06 -05:00
# Commands used to install each bootloader.
# NOTE: syslinux and grub in particular can/will change during runtime
declare -Ag BOOT_CMDS=(
[syslinux]="syslinux-install_update -iam"
[grub]="grub-install --bootloader-id=$DIST --recheck --force"
[systemd-boot]="bootctl --path=/boot install"
)
# files able to be reviewed when finishing install
2018-08-17 20:44:17 -05:00
# item index [9] can change depending on which bootloader is selected
2018-07-18 19:52:06 -05:00
declare -Ag EDIT_FILES=(
2018-08-12 23:24:38 -05:00
[2]="/etc/X11/xorg.conf.d/00-keyboard.conf /etc/vconsole.conf /etc/default/keyboard"
[3]="/etc/locale.conf /etc/default/locale"
[4]="/etc/hostname /etc/hosts"
[5]="/etc/sudoers"
[6]="/etc/mkinitcpio.conf"
[7]="/etc/fstab"
[8]="/etc/crypttab"
[9]="/etc/default/grub"
[10]="/etc/pacman.conf"
2018-07-18 19:52:06 -05:00
)
}
2018-07-18 19:50:37 -05:00
######################################################################
## Utility and Check Functions ##
######################################################################
chroot_cmd() {
arch-chroot $MNT /bin/bash -c "$1"
}
show_devices() {
2018-07-18 19:52:06 -05:00
tput civis
2018-08-18 19:59:25 -05:00
if [[ $IGNORE_DEV != "" ]]; then
2018-07-28 15:03:43 -05:00
lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT |
2018-08-18 19:59:25 -05:00
awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/ {print $0}' > /tmp/.devlist
2018-07-28 15:03:43 -05:00
else
lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT |
awk '/disk|part|lvm|crypt|NAME/ {print $0}' > /tmp/.devlist
fi
2018-07-18 19:52:06 -05:00
dialog --cr-wrap --backtitle "$BT" --title " $_PrepShowDev " --textbox /tmp/.devlist 0 0
2018-07-18 19:50:37 -05:00
}
set_debug() {
set -x
2018-07-18 19:52:06 -05:00
exec 3>| /tmp/debug-log
2018-07-18 19:50:37 -05:00
BASH_XTRACEFD=3
2018-08-12 23:24:38 -05:00
if [[ $DISPLAY ]]; then
if [[ $TERM_CMD == 'st' ]]; then
$TERM_CMD -e tail -f /tmp/debug-log &
else
$TERM_CMD -e "tail -f /tmp/debug-log" &
fi
fi
2018-07-18 19:50:37 -05:00
}
select_language() {
2018-07-18 19:52:06 -05:00
tput civis
local lang
lang=$(dialog --cr-wrap --stdout --backtitle "$DIST Installer - (x86_64)" \
--title " Select Language " --menu \
"\nLanguage - sprache - taal - språk - lingua - idioma - nyelv - língua\n" 0 0 0 \
"1" "English (en_**)" "2" "Español (es_ES)" \
"3" "Português [Brasil] (pt_BR)" "4" "Português (pt_PT)" \
"5" "Français (fr_FR)" "6" "Russkiy (ru_RU)" \
"7" "Italiano (it_IT)" "8" "Nederlands (nl_NL)" \
"9" "Magyar (hu_HU)" "10" "Chinese (zh_CN)")
source $TRN/english.trans 2>/dev/null
2018-08-12 23:24:38 -05:00
FONT="ter-i16n"
2018-07-18 19:52:06 -05:00
case $lang in
2018-07-18 19:50:37 -05:00
1) LOC="en_US.UTF-8" ;;
2018-07-18 19:52:06 -05:00
2) source $TRN/spanish.trans 2>/dev/null && LOC="es_ES.UTF-8" ;;
3) source $TRN/p_brasil.trans 2>/dev/null && LOC="pt_BR.UTF-8" ;;
4) source $TRN/portuguese.trans 2>/dev/null && LOC="pt_PT.UTF-8" ;;
5) source $TRN/french.trans 2>/dev/null && LOC="fr_FR.UTF-8" ;;
2018-08-12 23:24:38 -05:00
6) source $TRN/russian.trans 2>/dev/null && LOC="ru_RU.UTF-8" FONT="LatKaCyrHeb-14" ;;
2018-07-18 19:52:06 -05:00
7) source $TRN/italian.trans 2>/dev/null && LOC="it_IT.UTF-8" ;;
8) source $TRN/dutch.trans 2>/dev/null && LOC="nl_NL.UTF-8" ;;
2018-08-12 23:24:38 -05:00
9) source $TRN/hungarian.trans 2>/dev/null && LOC="hu_HU.UTF-8" FONT="lat2-16" ;;
2018-07-18 19:52:06 -05:00
10) source $TRN/chinese.trans 2>/dev/null && LOC="zh_CN.UTF-8" ;;
2018-08-12 23:24:38 -05:00
*) clear; tput cnorm
pgrep -f "$TERM_CMD -e tail" && pkill -f "$TERM_CMD -e tail"
exit 0
2018-07-18 19:50:37 -05:00
esac
sed -i "s/#en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen
[[ $LOC != "en_US.UTF-8" ]] && sed -i "s/#${LOC}/${LOC}/" /etc/locale.gen
2018-07-18 19:52:06 -05:00
locale-gen >/dev/null 2>&1
2018-08-12 23:24:38 -05:00
setfont $FONT >/dev/null 2>&1
2018-07-18 19:50:37 -05:00
export LANG="$LOC"
}
identify_system() {
2018-07-18 19:52:06 -05:00
if grep -qi 'apple' /sys/class/dmi/id/sys_vendor; then
2018-07-18 19:50:37 -05:00
modprobe -r -q efivars || true
else
modprobe -q efivarfs
fi
2018-07-18 19:52:06 -05:00
if [[ -d /sys/firmware/efi ]]; then
2018-07-18 19:50:37 -05:00
SYS="UEFI"
2018-07-18 19:52:06 -05:00
[[ $(mount) =~ /sys/firmware/efi/efivars ]] && mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
2018-07-18 19:50:37 -05:00
else
SYS="BIOS"
fi
readonly BT="$DIST Installer - $SYS (x86_64) - Version $VER"
}
check_requirements() {
2018-07-28 15:03:43 -05:00
declare -g HAS_NETWORK=false
2018-07-18 19:52:06 -05:00
if [[ $(whoami) != "root" ]]; then
2018-08-12 23:24:38 -05:00
infobox "$_ErrTitle" "$_NotRoot\n$_Exit"; clear; tput cnorm
pgrep -f "$TERM_CMD -e tail" && pkill -f "$TERM_CMD -e tail"
exit 1
2018-07-18 19:52:06 -05:00
elif ! (ping -c 1 archlabslinux.com || ping -c 1 google.com || ping -c 1 bitbucket.org || ping -c 1 github.com || ping -c 1 sourceforge.net) >/dev/null 2>&1; then
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ $(systemctl is-active NetworkManager) == "active" ]] && hash nmtui >/dev/null 2>&1;then
2018-08-12 23:24:38 -05:00
tput civis; nmtui
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if (ping -c 1 archlabslinux.com || ping -c 1 google.com || ping -c 1 bitbucket.org || ping -c 1 github.com || ping -c 1 sourceforge.net) >/dev/null 2>&1; then
HAS_NETWORK=true
else
infobox "$_ErrTitle" "$_NoNetwork\nYou may experience issues without one...\n"
fi
else
HAS_NETWORK=true
2018-07-18 19:50:37 -05:00
fi
return 0
}
check_for_errors() {
2018-07-18 19:52:06 -05:00
# if the last process exited normally then we can bail
(( $? == 0 )) && return 0
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local command="$1"
local msg="\nThe command exited abnormally: $command"
# get error message from logfile and attempt to format slightly better for humans
# strip any non-printable characters, escape sequences, and other known messy text
local err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
if [[ $err != "" ]]; then
msgbox "$_ErrTitle" "$msg\n\nWith the following error message:\n\n$err"
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
if yesno "$_ErrTitle" "$msg\n$_ErrChoice" "Wipe Install" "Manual Fix" "no"; then
for d in $MNT/?*; do
if ! grep -q "boot" <<< "$d"; then
rm -rf "$d" 2>/dev/null
fi
done
unmount_partitions
[[ -e $ERR ]] && rm -rf $ERR
initialize_variables
2018-07-28 15:03:43 -05:00
luks_variable_init
2018-07-18 19:52:06 -05:00
fi
return 1
2018-07-18 19:50:37 -05:00
}
check_parts_are_mounted() {
2018-07-18 19:52:06 -05:00
[[ $(lsblk -o MOUNTPOINT) =~ "$MNT" ]] && return 0
2018-07-18 19:50:37 -05:00
msgbox "$_ErrTitle" "$_ErrNoMount"
return 1
}
check_base_unpacked() {
[[ -e $MNT/etc ]] && return 0
2018-07-18 19:52:06 -05:00
msgbox "$_ErrTitle" "$_ErrNoBase"
2018-07-18 19:50:37 -05:00
return 1
}
getinput() {
2018-07-18 19:52:06 -05:00
local answer
answer="$(dialog --cr-wrap --max-input 63 --stdout --backtitle "$BT" --title " $1 " --inputbox "$2" 0 0 "$3")"
[[ $? != 0 || $answer == "" ]] && return 1
echo "$answer"
}
2018-07-18 19:50:37 -05:00
msgbox() {
2018-07-18 19:52:06 -05:00
tput civis
dialog --cr-wrap --backtitle "$BT" --title " $1 " --msgbox "$2\n" 0 0
}
2018-07-18 19:50:37 -05:00
infobox() {
local bt="${BT:-$DIST Installer - (x86_64)}"
2018-07-18 19:52:06 -05:00
tput civis
dialog --cr-wrap --backtitle "$bt" --title " $1 " --infobox "$2\n" 0 0
2018-07-18 19:50:37 -05:00
sleep 2
2018-07-18 19:52:06 -05:00
}
2018-07-18 19:50:37 -05:00
yesno() {
2018-07-18 19:52:06 -05:00
tput civis
if [[ $# -eq 5 && $5 == "no" ]]; then
# option for default no using custom labels
dialog --cr-wrap --backtitle "$BT" --defaultno --title " $1 " \
--yes-label "$3" --no-label "$4" --yesno "$2\n" 0 0
elif [[ $# -eq 4 ]]; then
# option for custom labels with standard default yes
dialog --cr-wrap --backtitle "$BT" --title " $1 " --yes-label "$3" \
--no-label "$4" --yesno "$2\n" 0 0
else
# basic yes no without custom labels and default yes
dialog --cr-wrap --backtitle "$BT" --title " $1 " --yesno "$2\n" 0 0
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
wrap_up() {
if yesno "$_CloseInst" "$1" "$2" "$3"; then
unmount_partitions
[[ -e $ERR ]] && rm -rf $ERR
pgrep -f "$TERM_CMD -e tail" && pkill -f "$TERM_CMD -e tail"
tput cnorm
clear
[[ $4 == "reboot" ]] && reboot
exit 0
fi
}
2018-07-18 19:50:37 -05:00
######################################################################
## System Settings Functions ##
######################################################################
set_keymap() {
2018-07-18 19:52:06 -05:00
local map
tput civis
map="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepLayout " \
--menu "$_XMapBody" 20 70 12 $KEYMAPS)"
[[ $? != 0 || $map == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
cat >/tmp/00-keyboard.conf <<EOF
2018-07-18 19:50:37 -05:00
# Use localectl(1) to instruct systemd-localed to update it.
Section "InputClass"
2018-07-18 19:52:06 -05:00
Identifier "system-keyboard"
2018-07-18 19:50:37 -05:00
MatchIsKeyboard "on"
2018-07-18 19:52:06 -05:00
Option "XkbLayout" "$map"
2018-07-18 19:50:37 -05:00
EndSection
EOF
2018-07-18 19:52:06 -05:00
cat >/tmp/keyboard <<EOF
2018-07-18 19:50:37 -05:00
# KEYBOARD CONFIGURATION FILE
# Consult the keyboard(5) manual page.
XKBMODEL=""
XKBLAYOUT="$map"
XKBVARIANT=""
XKBOPTIONS=""
BACKSPACE="guess"
EOF
2018-07-18 19:52:06 -05:00
# when a matching console map is not available open a selection dialog
if ! [[ $CONSOLE_MAPS =~ "$map -" ]]; then
tput civis
map="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_CMapTitle " \
--menu "$_CMapBody" 20 70 12 $CONSOLE_MAPS)"
[[ $? != 0 || $map == "" ]] && return 1
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
2018-08-12 23:24:38 -05:00
setxkbmap $XKBMAP >/dev/null 2>&1
echo -e "KEYMAP=$map\nFONT=$FONT" >/tmp/vconsole.conf
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
set_locale() {
local locale
2018-07-18 19:52:06 -05:00
tput civis
2018-08-17 03:21:15 -05:00
locale="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \
--title "$_ConfLocale" --menu "$_LocaleBody" 25 70 12 $LOCALES)"
2018-07-18 19:52:06 -05:00
[[ $? != 0 || $locale == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
infobox "$_ConfLocale" "$_GenLocale $locale\n"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${locale}/${locale}/g" $MNT/etc/locale.gen
2018-07-18 19:50:37 -05:00
sed -i "s/en_US.UTF-8/${locale}/g" $MNT/etc/locale.conf
cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
chroot_cmd "locale-gen" >/dev/null 2>$ERR
2018-07-18 19:52:06 -05:00
check_for_errors 'locale-gen' || return 1
2018-07-18 19:50:37 -05:00
set_timezone
}
set_timezone() {
2018-07-18 19:52:06 -05:00
tput civis
2018-07-18 19:50:37 -05:00
2018-08-17 03:21:15 -05:00
local zone
zone="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \
2018-08-18 19:59:25 -05:00
--title " $_TimeZTitle " --menu "$_TimeZBody" 20 70 10 America - Australia - \
Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica -)"
2018-08-17 03:21:15 -05:00
local subzone
subzone="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \
--title " $_TimeZTitle " --menu "$_TimeSubZBody" 20 70 12 ${SUBZONES[$zone]})"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if yesno "$_TimeZTitle" "$_TimeZQ $zone/$subzone?\n"; then
2018-07-18 19:50:37 -05:00
chroot_cmd "ln -sf /usr/share/zoneinfo/$zone/$subzone /etc/localtime" 2>$ERR
2018-07-18 19:52:06 -05:00
check_for_errors "ln -sf /usr/share/zoneinfo/$zone/$subzone /etc/localtime" || return 1
2018-07-18 19:50:37 -05:00
else
2018-07-18 19:52:06 -05:00
set_timezone || return 1
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
TIMEZONE_SET=true
2018-07-18 19:50:37 -05:00
set_hwclock
}
set_hwclock() {
chroot_cmd "hwclock --systohc --utc"
2018-08-17 03:21:15 -05:00
if [[ $? != 0 ]]; then
2018-07-18 19:50:37 -05:00
chroot_cmd "hwclock --systohc --utc --directisa"
2018-08-17 03:21:15 -05:00
[[ $? != 0 ]] && infobox "$_ErrTitle" "\nHwclock setup attempts failed.\n\nContinuing anyway.\n"
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
set_hostname() {
2018-07-18 19:52:06 -05:00
tput cnorm
local hostname
hostname="$(getinput "$_ConfHost" "$_HostNameBody" "${DIST,,}")"
[[ $? != 0 || $hostname == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
echo "$hostname" > $MNT/etc/hostname
2018-07-18 19:50:37 -05:00
cat > $MNT/etc/hosts << EOF
127.0.0.1 localhost
2018-07-18 19:52:06 -05:00
127.0.1.1 $hostname
2018-07-18 19:50:37 -05:00
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
EOF
}
create_user() {
2018-08-12 23:24:38 -05:00
if [[ $AUTOLOGIN == true && $LOGIN_TYPE == 'lightdm' ]]; then
local groups="rfkill,wheel,autologin,nopasswdlogin,network,lp,storage,power,video,audio,lp"
else
local groups="rfkill,wheel,autologin,network,lp,storage,power,video,audio,lp"
fi
2018-07-18 19:52:06 -05:00
NEWUSER=""
user_input_values "$NEWUSER" || return 1
if [[ $SET_ROOT_PASSWD != true ]]; then
infobox "$_ConfRoot" "\nSetting root password\n"
chroot_cmd "echo 'root:$ROOT_PASS' | chpasswd" 2>$ERR
check_for_errors "chpasswd root" || return 1
SET_ROOT_PASSWD=true
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
infobox "$_ConfUser" "$_UserSetBody"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ -e $MNT/home/$LIVE ]]; then
# for first user created, swap the live user account
swap_livuser
chroot_cmd "mv -f /home/$LIVE /home/$NEWUSER" 2>$ERR
check_for_errors "mv -f /home/$LIVE /home/$NEWUSER" || return 1
chroot_cmd "usermod -aG $groups $NEWUSER" 2>$ERR
check_for_errors "usermod -aG $groups $NEWUSER" || return 1
else
# create new user account
chroot_cmd "useradd $NEWUSER -m -g users -G $groups -s /bin/zsh" 2>$ERR
check_for_errors "useradd $NEWUSER -m -g users -G $groups -s /bin/zsh" || return 1
chroot_cmd "cp -rf /etc/skel/ /home/$NEWUSER" 2>$ERR
check_for_errors "cp -rf /etc/skel/ /home/$NEWUSER" || return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
chroot_cmd "echo '$NEWUSER:$USER_PASS' | chpasswd" 2>$ERR
check_for_errors "chpasswd $NEWUSER" || return 1
chroot_cmd "chown -Rf $NEWUSER:users /home/$NEWUSER" 2>$ERR
check_for_errors "chown -Rf $NEWUSER:users /home/$NEWUSER" || return 1
2018-07-18 19:50:37 -05:00
2018-08-12 23:24:38 -05:00
if [[ $AUTOLOGIN == true && $LOGIN_TYPE == 'lightdm' ]]; then
sed -i "/#autologin-user=/ c autologin-user=${NEWUSER}" $MNT/etc/lightdm/lightdm.conf
fi
2018-07-18 19:52:06 -05:00
fix_home_files
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ $UNPACKED_BASE == true && $TIMEZONE_SET == true ]]; then
[[ $SET_ROOT_PASSWD == true && $BOOT_DONE == true ]] && FULL_DONE=true
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
swap_livuser() {
2018-08-12 23:24:38 -05:00
# edit the required files in /etc/ to swap the liveuser account name
sed -i "s/${LIVE}/${NEWUSER}/g" $MNT/etc/{group,gshadow,passwd,shadow}
2018-07-18 19:52:06 -05:00
2018-08-12 23:24:38 -05:00
if [[ $AUTOLOGIN != true || $LOGIN_TYPE == 'lightdm' ]]; then
rm -rf $MNT/etc/systemd/system/getty@tty1.service.d >/dev/null 2>&1
2018-08-20 04:26:13 -05:00
elif [[ $LOGIN_TYPE != 'lightdm' ]]; then
2018-08-12 23:24:38 -05:00
sed -i "s/${LIVE}/${NEWUSER}/g" $MNT/etc/systemd/system/getty@tty1.service.d/autologin.conf
2018-07-18 19:50:37 -05:00
fi
2018-08-12 23:24:38 -05:00
return 0
2018-07-18 19:52:06 -05:00
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
fix_home_files() {
local user_home="$MNT/home/$NEWUSER"
2018-08-12 23:24:38 -05:00
sed -i "s/${LIVE}/${NEWUSER}/g" $user_home/.config/{openbox/autostart,gtk-3.0/bookmarks} \
$user_home/.mozilla/firefox/{archlabs.default/prefs.js,archlabs.default/sessionstore.js}
if [[ $AUTOLOGIN == true ]]; then
if [[ $LOGIN_TYPE == 'lightdm' ]]; then
rm -rf $user_home/.{zprofile,xinitrc}
2018-08-20 04:26:13 -05:00
sed -i "/#autologin-user=/ c autologin-user=${NEWUSER}" $MNT/etc/lightdm/lightdm.conf
2018-08-12 23:24:38 -05:00
else
sed -i "s/:-openbox/:-${LOGIN_WM}/g" $user_home/.xinitrc
sed -i '/archlabs-installer/d' $user_home/.zprofile
echo '[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec startx -- vt1 &>/dev/null' >> $user_home/.zprofile
fi
else
2018-08-20 04:26:13 -05:00
sed -i '/archlabs-installer/d' $user_home/.zprofile
echo '[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec startx -- vt1 &>/dev/null' >> $user_home/.zprofile
2018-08-12 23:24:38 -05:00
sed -i "s/:-openbox/:-${LOGIN_WM}/g" $user_home/.xinitrc
fi
return 0
}
2018-08-20 04:26:13 -05:00
user_input_values() {
local user="$1"
local pass pass2
tput cnorm
local values
if [[ $SET_ROOT_PASSWD != true ]]; then
values="$(dialog --stdout --no-cancel --separator '~' --ok-label "Submit" --backtitle "$BT" \
--title " $_UserTitle " --insecure --mixedform "$_UserBody" 27 75 10 \
"$_Username" 1 1 "$user" 1 $((${#_Username} + 2)) 71 0 0 \
"$_Password" 2 1 "" 2 $((${#_Password} + 2)) 71 0 1 \
"$_Password2" 3 1 "" 3 $((${#_Password2} + 2)) 71 0 1 \
"$_RootBody" 6 1 "" 6 $((${#_RootBody} + 1)) 71 0 2 \
"$_Password" 8 1 "" 8 $((${#_Password} + 2)) 71 0 1 \
"$_Password2" 9 1 "" 9 $((${#_Password2} + 2)) 71 0 1)"
else
values="$(dialog --stdout --no-cancel --separator '~' --ok-label "Submit" --backtitle "$BT" \
--title " $_UserTitle " --insecure --mixedform "$_UserBody" 20 75 4 \
"$_Username" 1 1 "$user" 1 $((${#_Username} + 2)) 71 0 0 \
"$_Password" 2 1 "" 2 $((${#_Password} + 2)) 71 0 1 \
"$_Password2" 3 1 "" 3 $((${#_Password2} + 2)) 71 0 1)"
fi
[[ $? != 0 || $values == "" ]] && return 1
user="$(awk -F'~' '{print $1}' <<< "$values")"
pass="$(awk -F'~' '{print $2}' <<< "$values")"
pass2="$(awk -F'~' '{print $3}' <<< "$values")"
# if the root password has not yet been set
local rpass rpass2
if [[ $SET_ROOT_PASSWD != true ]]; then
rpass="$(awk -F'~' '{print $5}' <<< "$values")"
rpass2="$(awk -F'~' '{print $6}' <<< "$values")"
# when both passwords match but are empty
# resort to using the user passwords instead
if [[ $rpass == "" && $rpass2 == "" ]]; then
rpass="$pass"
rpass2="$pass2"
fi
fi
# make sure we dont have anything wrong and that the passwords match
if [[ ${#user} -eq 0 || $user =~ \ |\' || $user =~ [^a-z0-9\ ] || $pass == "" || "$pass" != "$pass2" || "$rpass" != "$rpass2" ]]; then
tput civis
# passwords don't match
if [[ $pass == "" || "$pass" != "$pass2" || "$rpass" != "$rpass2" ]]; then
if [[ "$rpass" != "$rpass2" ]]; then
msgbox "$_ErrTitle" "$_RootPassErr\n$_TryAgain"
else
msgbox "$_ErrTitle" "$_UserPassErr\n$_TryAgain"
fi
else
# bad username
msgbox "$_UserErrTitle" "$_UserErrBody"
user=""
fi
# recursively loop back unless the user chooses cancel, then bail
user_input_values "$user" || return 1
else
NEWUSER="$user"
USER_PASS="$pass"
[[ $SET_ROOT_PASSWD != true ]] && ROOT_PASS="$rpass"
fi
return 0
}
window_manager() {
2018-08-12 23:24:38 -05:00
LOGIN_WM=""
LOGIN_TYPE=""
WM_PACKAGES=""
INSTALL_WMS="$(dialog --cr-wrap --stdout --backtitle "$BT" --no-cancel \
--title " $_WMChoice " --checklist "$_WMChoiceBody\n" 0 0 0 \
"openbox" "A lightweight, powerful, and highly configurable stacking window manager" off \
"bspwm" "A tiling window manager that represents windows as the leaves of a binary tree" off \
"i3-gaps" "A fork of i3 window manager with more features including gaps" off \
2018-08-19 22:32:21 -05:00
"gnome" "A desktop environment that aims to be simple and easy to use" off \
2018-08-20 04:26:13 -05:00
"cinnamon" "A desktop environment combining a traditional desktop layout with modern graphical effects" off \
2018-08-12 23:24:38 -05:00
"xfce4" "A lightweight and modular desktop environment based on GTK+ 2 and 3" off)"
INSTALL_WMS="${INSTALL_WMS:-openbox}"
WM_NUM=$(awk '{print NF}' <<< "$INSTALL_WMS")
for wm in $INSTALL_WMS; do
WM_LOGIN_CHOICES="${WM_LOGIN_CHOICES}$wm - "
case $wm in
2018-08-20 04:26:13 -05:00
openbox) WM_PACKAGES="$WM_PACKAGES $wm obconf archlabs-ob-autostart archlabs-obkey archlabs-kickshaw" ;;
bspwm) WM_PACKAGES="$WM_PACKAGES $wm sxhkd lxappearance" ;;
i3-gaps) WM_PACKAGES="$WM_PACKAGES $wm i3status perl-anyevent-i3 lxappearance" ;;
gnome) WM_PACKAGES="$WM_PACKAGES $wm gnome-extra" ;;
cinnamon) WM_PACKAGES="$WM_PACKAGES $wm" ;;
xfce4) WM_PACKAGES="$WM_PACKAGES $wm xfce4-goodies xfce4-pulseaudio-plugin" ;;
2018-08-12 23:24:38 -05:00
esac
2018-07-18 19:52:06 -05:00
done
2018-07-18 19:50:37 -05:00
2018-08-12 23:24:38 -05:00
if yesno "$_WMLogin" "$_LoginTypeBody\n" "xinit" "lightdm"; then
LOGIN_TYPE="xinit"
else
LOGIN_TYPE="lightdm"
fi
if yesno "$_WMLogin" "$_AutoLoginBody\n"; then
AUTOLOGIN=true
else
AUTOLOGIN=false
fi
2018-07-18 19:52:06 -05:00
2018-08-12 23:24:38 -05:00
if [[ $WM_NUM -eq 1 ]]; then
LOGIN_WM="$INSTALL_WMS"
else
LOGIN_WM="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \
--title " $_WMLogin " --menu "$_WMLoginBody" 0 0 0 $WM_LOGIN_CHOICES)"
[[ $LOGIN_WM == "" ]] && LOGIN_WM="$(awk '{print $1}' <<< "$INSTALL_WMS")"
2018-07-18 19:52:06 -05:00
fi
2018-08-12 23:24:38 -05:00
2018-08-19 22:32:21 -05:00
case $LOGIN_WM in
2018-08-20 04:26:13 -05:00
i3-gaps) LOGIN_WM='i3' ;;
gnome) LOGIN_WM='gnome-session' ;;
cinnamon) LOGIN_WM='cinnamon-session' ;;
openbox) LOGIN_WM='openbox-session' ;;
xfce4) LOGIN_WM='startxfce4' ;;
2018-08-19 22:32:21 -05:00
esac
2018-08-18 19:59:25 -05:00
2018-08-12 23:24:38 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
2018-08-20 04:26:13 -05:00
extra_packages() {
if yesno "$_ExtraPackages" "$_ChooseExtraPackages"; then
EXTRA_PACKAGES="$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title " $_WMChoice " --checklist "$_WMChoiceBody\n" 0 0 20 \
"firefox" "A popular open-source graphical web browser from Mozilla" off \
"chromium" "an open-source graphical web browser based on the Blink rendering engine" off \
"opera" "Fast and secure, free of charge web browser from Opera Software" off \
"qutebrowser" "A keyboard-focused vim-like web browser based on Python and PyQt5" off \
"atom" "An open-source text editor developed by GitHub that is licensed under the MIT License" off \
"geany" "A fast and lightweight IDE" off \
"emacs" "An extensible, customizable, self-documenting real-time display editor" off \
"neovim" "A fork of Vim aiming to improve user experience, plugins, and GUIs." off \
"mousepad" "A simple text editor" off \
"urxvt" "A unicode enabled rxvt-clone terminal emulator" off \
"tilix" "A tiling terminal emulator for Linux using GTK+ 3" off \
"terminator" "Terminal emulator that supports tabs and grids" off \
"tilda" "A Gtk based drop down terminal for Linux and Unix" off \
"xfce4-terminal" "A terminal emulator primarily for the XFCE desktop" off \
"termite" "A minimal VTE-based terminal emulator" off \
"pcmanfm" "A fast and lightweight file manager" off \
"gnome-disk-utility" "Disk Management Utility" off \
"gnome-system-monitor" "View current processes and monitor system state" off \
"steam steam-native-runtime" "A popular game distribution platform by Valve" off \
"vlc qt4" "a free and open source cross-platform multimedia player" off \
"audacious" "A free and advanced audio player based on GTK+" off \
"nicotine+" "A graphical client for Soulseek" off \
"lollypop" "A new music playing application" off \
"rhythmbox" "Music playback and management application" off \
"deadbeef" "A GTK+ audio player for GNU/Linux" off \
"clementine" "A modern music player and library organizer" off \
"thunderbird" "Standalone mail and news reader from mozilla" off \
"geary" "A lightweight email client for the GNOME desktop" off \
"evolution" "Manage your email, contacts and schedule" off \
"mutt" "Small but very powerful text-based mail client" off \
"deluge" "A BitTorrent client written in python" off \
"transmission-gtk" "Free BitTorrent client GTK+ GUI" off \
"qbittorrent" "An advanced BitTorrent client" off \
"hexchat" "A popular and easy to use graphical IRC client" off \
"pidgin" "Multi-protocol instant messaging client" off \
"weechat" "Fast, light and extensible IRC client" off \
"irssi" "Modular text mode IRC client" off \
"libreoffice-fresh" "Full featured office suite" off \
"abiword" "Fully-featured word processor" off \
"calligra" "A set of applications for productivity" off \
"evince" "Document viewer" off \
"zathura" "Minimalistic document viewer" off \
"qpdfview" "A tabbed PDF viewer" off \
"mupdf" "Lightweight PDF and XPS viewer" off \
"gimp" "GNU Image Manipulation Program" off \
"inkscape" "Professional vector graphics editor" off \
"krita" "Edit and paint images" off \
"simplescreenrecorder" "A feature-rich screen recorder" off \
"obs-studio" "Free opensource streaming/recording software" off \
"guvcview" "Capture video from camera devices" off \
"gpick" "Advanced color picker using GTK+ toolkit" off \
"gcolor2" "A simple GTK+2 color selector" off \
"plank" "Stupidly simple dock" off \
"docky" "The finest dock no money can buy" off \
"cairo-dock" "Light, eye-candy filled dock and desklets" off \
"ttf-hack" "A hand groomed and optically balanced typeface based on Bitstream Vera Mono." off \
"ttf-anonymous-pro" "A family of four fixed-width fonts designed especially with coding in mind" off \
"ttf-font-awesome" "Iconic font designed for Bootstrap" off \
"ttf-fira-code" "Monospaced font with programming ligatures" off \
"noto-fonts-cjk" "Google Noto CJK fonts (Chinese, Japanese, Korean)" off)"
fi
return 0
}
2018-07-18 19:50:37 -05:00
######################################################################
## System Partitioning Functions ##
######################################################################
2018-08-17 03:21:15 -05:00
decrease_part_count() {
# remove a partition from the dialog list and decrement the number partitions left
local p="$1"
PARTS="$(sed "s~${p} [0-9]*[G-M]~~; s~${p} [0-9]*\.[0-9]*[G-M]~~" <<< "$PARTS")"
(( COUNT > 0 )) && (( COUNT-- ))
return 0
}
2018-07-18 19:52:06 -05:00
wipe_device() {
local device="$1"
if yesno "$_PartWipe" "$_PartBody1 $device $_PartWipeBody2"; then
tput civis
2018-08-12 23:24:38 -05:00
wipe -Ifre "$device" | dialog --cr-wrap --backtitle "$BT" --title " $_PartWipe " \
2018-07-18 19:52:06 -05:00
--progressbox "\nSecure wiping $device\n" 18 70
else
create_partitions "$device"
2018-07-18 19:50:37 -05:00
fi
}
mount_partition() {
local part="$1"
2018-07-18 19:52:06 -05:00
local mount="$2"
local fs="$(lsblk -lno FSTYPE $part)"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
mkdir -p "${MNT}$mount"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ ${FS_OPTS[$fs]} != "" && $part != "$BOOT_PART" ]] && select_mount_opts "$part" "$fs"; then
mount -o $MNT_OPTS "$part" "${MNT}$mount" 2>$ERR
check_for_errors "mount -o $MNT_OPTS $part ${MNT}$mount" || return 1
2018-07-18 19:50:37 -05:00
else
2018-07-18 19:52:06 -05:00
mount "$part" "${MNT}$mount" 2>$ERR
check_for_errors "mount $part ${MNT}$mount" || return 1
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
confirm_mount "$part" "${MNT}$mount" || return 1
2018-07-18 19:50:37 -05:00
check_part_is_crypt_or_lvm "$part"
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
unmount_partitions() {
swapoff -a
2018-07-18 19:52:06 -05:00
2018-07-18 19:50:37 -05:00
for i in $(mount | grep "$MNT" | awk '{print $3}' | sort -r); do
2018-07-18 19:52:06 -05:00
umount -r "$i" >/dev/null 2>&1
2018-07-18 19:50:37 -05:00
done
}
2018-07-18 19:52:06 -05:00
confirm_mount() {
local part="$1"
local mount="$2"
if [[ "$mount" == "$MNT" ]]; then
local msg="Partition: $part\nMountpoint: / (root)"
else
local msg="Partition: $part\nMountpoint: ${mount#$MNT}"
fi
# partition failed to mount properly
if ! grep -q "$mount" <<< "$(mount)"; then
infobox "$_MntTitle" "$_MntFail\n$msg\n"
return 1
fi
# mount was successful
infobox "$_MntTitle" "$_MntSucc\n$msg\n"
decrease_part_count "$part"
return 0
}
2018-07-18 19:50:37 -05:00
find_partitions() {
local str="$1"
2018-07-18 19:52:06 -05:00
local err='NONE'
2018-07-18 19:50:37 -05:00
2018-07-28 14:36:08 -05:00
# string of partitions as /TYPE/PART SIZE
2018-08-18 19:59:25 -05:00
if [[ $IGNORE_DEV != "" ]]; then
PARTS="$(lsblk -lno TYPE,NAME,SIZE |
awk "/$str/"' && !'"/$IGNORE_DEV/"' {sub(/^part/, "/dev/"); sub(/^lvm|^crypt/, "/dev/mapper/"); print $1$2 " " $3}')"
2018-07-28 15:03:43 -05:00
else
2018-08-18 19:59:25 -05:00
PARTS="$(lsblk -lno TYPE,NAME,SIZE |
awk "/$str/"' {sub(/^part/, "/dev/"); sub(/^lvm|^crypt/, "/dev/mapper/"); print $1$2 " " $3}')"
2018-07-28 15:03:43 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# number of partitions total
COUNT=$(wc -l <<< "$PARTS")
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# ensure we have enough partitions for the system and action type
2018-07-18 19:50:37 -05:00
case $str in
2018-07-18 19:52:06 -05:00
'part|lvm|crypt') [[ $COUNT -eq 0 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_PartErrBody" ;;
'part|crypt') (( COUNT == 0 )) && err="$_LvmPartErrBody" ;;
'part|lvm') (( COUNT < 2 )) && err="$_LuksPartErrBody" ;;
2018-07-18 19:50:37 -05:00
esac
2018-07-18 19:52:06 -05:00
# if an error was found with the partition setup and there aren't enough partitions
# show the appropriate error message for the given $str types were using
if [[ $err != 'NONE' ]]; then
2018-07-18 19:50:37 -05:00
msgbox "$_ErrTitle" "$err"
2018-07-18 19:52:06 -05:00
if select_device 'root'; then
create_partitions "$DEVICE"
else
return 1
fi
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
2018-07-18 19:52:06 -05:00
auto_partition() {
2018-07-18 19:50:37 -05:00
local device="$1"
2018-07-18 19:52:06 -05:00
# confirm or bail
yesno "$_PrepParts" "$_PartBody1 $device $_PartBody2" || return 0
infobox "$_PrepParts" "\nAuto partitioning device: $device\n"
2018-07-18 19:50:37 -05:00
2018-08-21 12:28:19 -05:00
swapoff -a # make sure swap is disabled in case the device was used for swap
# walk the partitions on the device in reverse order and delete them
2018-07-18 19:52:06 -05:00
local dev_info="$(parted -s $device print)"
2018-08-17 03:21:15 -05:00
for i in $(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r); do
parted -s $device rm $i 2>$ERR
check_for_errors "parted -s $device rm $i" || { break; return 1; }
2018-07-18 19:52:06 -05:00
done
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# make sure we have the correct device table for the system type, gpt or msdos
local table="$(awk '/Table:/ {print $3}' <<< "$dev_info")"
2018-08-21 12:28:19 -05:00
local newtable="gpt"
[[ $SYS == BIOS ]] && newtable="msdos"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# if the current device table isn't correct run mklabel
2018-08-17 03:21:15 -05:00
if [[ $table != "$newtable" ]]; then
2018-07-18 19:52:06 -05:00
parted -s $device mklabel $newtable 2>$ERR
check_for_errors "parted -s $device mklabel $newtable" || return 1
2018-07-18 19:50:37 -05:00
fi
2018-08-21 12:28:19 -05:00
# when device contains the string 'nvme' then add 'p' before the part number
local nvme=""
[[ $device =~ nvme ]] && nvme="p"
2018-07-18 19:52:06 -05:00
local part_num=1
2018-08-21 12:28:19 -05:00
BOOT_PART="$device${nvme}$part_num" # set the boot partition label to the first partition
2018-07-18 19:50:37 -05:00
if [[ $SYS == "BIOS" ]]; then
2018-07-18 19:52:06 -05:00
parted -s $device mkpart primary ext4 1MiB 513MiB 2>$ERR
2018-08-21 12:28:19 -05:00
check_for_errors "parted -s $device mkpart primary ext4 1MiB 513MiB" || return 1
2018-07-18 19:52:06 -05:00
mkfs.ext4 -q $BOOT_PART >/dev/null 2>$ERR
2018-08-21 12:28:19 -05:00
check_for_errors "mkfs.ext4 -q $BOOT_PART" || return 1
2018-07-18 19:52:06 -05:00
else
parted -s $device mkpart ESP fat32 1MiB 513MiB 2>$ERR
2018-08-21 12:28:19 -05:00
check_for_errors "parted -s $device mkpart ESP fat32 1MiB 513MiB" || return 1
2018-07-18 19:52:06 -05:00
mkfs.vfat -F32 $BOOT_PART >/dev/null 2>$ERR
2018-08-21 12:28:19 -05:00
check_for_errors "mkfs.vfat -F32 $BOOT_PART" || return 1
parted -s $device set $part_num esp on 2>$ERR
check_for_errors "parted -s $device set $part_num esp on" || return 1
2018-07-18 19:50:37 -05:00
fi
2018-08-21 12:28:19 -05:00
parted -s $device set $part_num boot on 2>$ERR
check_for_errors "parted -s $device set $part_num boot on" || return 1
2018-07-18 19:50:37 -05:00
2018-08-21 12:28:19 -05:00
(( part_num++ )) # increment the partition number
BOOT_DEVICE="$device" # only grub on BIOS systems uses this
ROOT_PART="${device}${nvme}$part_num" # set root partition label to the second partition
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
parted -s $device mkpart primary ext4 514MiB 100% 2>$ERR
check_for_errors "parted -s $device mkpart primary ext4 514MiB 100%" || return 1
mkfs.ext4 -q $ROOT_PART >/dev/null 2>$ERR
2018-08-21 12:28:19 -05:00
check_for_errors "mkfs.ext4 -q $ROOT_PART" || return 1
2018-07-18 19:50:37 -05:00
2018-08-21 12:28:19 -05:00
tput civis; sleep 0.5
2018-07-18 19:52:06 -05:00
echo -e "\nAuto partitioning complete.\n" > /tmp/.devlist
2018-07-28 14:36:08 -05:00
lsblk $device -o NAME,MODEL,TYPE,FSTYPE,SIZE >> /tmp/.devlist
2018-07-18 19:52:06 -05:00
dialog --cr-wrap --backtitle "$BT" --title " $_PrepParts " --textbox /tmp/.devlist 0 0
return 0
}
create_partitions() {
local device="$1"
local choice
tput civis
2018-08-12 23:24:38 -05:00
if hash gparted >/dev/null 2>&1 && [[ $DISPLAY ]]; then
choice="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PartTitle " \
--menu "$_PartBody" 0 0 0 "$_PartAuto" "BIOS & UEFI" \
"gparted" "BIOS & UEFI" "cfdisk" "BIOS & UEFI" "parted" "BIOS & UEFI" "$_PartWipe" "BIOS & UEFI")"
else
choice="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PartTitle " \
--menu "$_PartBody" 0 0 0 "$_PartAuto" "BIOS & UEFI" \
"cfdisk" "BIOS & UEFI" "parted" "BIOS & UEFI" "$_PartWipe" "BIOS & UEFI")"
fi
2018-07-18 19:52:06 -05:00
[[ $? != 0 || $choice == "" ]] && return 1 || clear
if [[ $choice != "$_PartWipe" && $choice != "$_PartAuto" ]]; then
2018-08-12 23:24:38 -05:00
$choice $device
2018-07-18 19:52:06 -05:00
elif [[ $choice == "$_PartWipe" ]]; then
2018-07-29 14:53:14 -05:00
wipe_device $device && create_partitions $device
2018-07-18 19:52:06 -05:00
else
2018-07-29 14:53:14 -05:00
auto_partition $device || { initialize_variables; return 1; }
2018-07-18 19:50:37 -05:00
fi
}
2018-07-18 19:52:06 -05:00
get_swap_size() {
tput cnorm
SWAP_SIZE="$(getinput "$_SelSwpSetup" "$_SelSwpSize" "$SWAP_SIZE")"
[[ $? != 0 || $SWAP_SIZE == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# size is incorrect
if ! [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; then
msgbox "$_SelSwpSetup Error" "\n$_SelSwpErr $SWAP_SIZE\n"
SWAP_SIZE="${SYS_MEM}M"
get_swap_size || return 1
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
select_swap() {
2018-08-14 21:58:07 -05:00
# Ask user to select partition or create swapfile
SWAP="$(dialog --backtitle "$BT" --cr-wrap --stdout --title " $_SelSwpSetup " \
--menu "$_SelSwpBody" 0 0 0 "$_SelSwpNone" "-" "$_SelSwpFile" "-" $PARTS)"
[[ $? != 0 || $SWAP == "$_SelSwpNone" ]] && return 0
if [[ $SWAP == "$_SelSwpFile" ]]; then
get_swap_size || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
fallocate -l $SWAP_SIZE $MNT/swapfile 2>$ERR
check_for_errors "fallocate -l $size $MNT/swapfile" || return 1
chmod 600 $MNT/swapfile 2>$ERR
check_for_errors "chmod 600 $MNT/swapfile" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
mkswap $MNT/swapfile >/dev/null 2>$ERR
check_for_errors "mkswap $MNT/swapfile" || return 1
swapon $MNT/swapfile >/dev/null 2>$ERR
check_for_errors "swapon $MNT/swapfile" || return 1
SWAP_FILE="/swapfile"
2018-08-14 21:58:07 -05:00
else
2018-08-17 03:21:15 -05:00
# Warn user if creating a new swap on the chosen partition
2018-08-14 21:58:07 -05:00
if ! grep -qi "swap" <<< "$(lsblk -o FSTYPE $SWAP)"; then
yesno "$_PrepMount" "\nmkswap $SWAP\n" || return 0
mkswap $SWAP >/dev/null 2>$ERR
check_for_errors "mkswap $SWAP" || return 1
fi
swapon $SWAP >/dev/null 2>$ERR
check_for_error "swapon $SWAP" || return 1
decrease_part_count "$SWAP"
SWAP_FILE="$SWAP"
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_device() {
local msg=""
[[ $1 == 'boot' ]] && msg="$_DevSelTitle for bootloader\n"
if (( DEV_COUNT == 1 )); then
DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
2018-07-28 15:03:43 -05:00
infobox "$_DevSelTitle" "\nOnly one device available$([[ $1 == 'boot' ]] && echo -n " for bootloader"): $DEVICE\n"
2018-07-18 19:52:06 -05:00
elif (( DEV_COUNT > 1 )); then
tput civis
DEVICE="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_DevSelTitle " \
--menu "${msg}$_DevSelBody" 0 0 0 $SYS_DEVS)"
[[ $? != 0 || $DEVICE == "" ]] && return 1
else
msgbox "$_ErrTitle" "\nNo available devices for installation to use.\n\nExiting.."
pgrep -f "$TERM_CMD -e tail" && pkill -f "$TERM_CMD -e tail"
tput cnorm
clear
exit 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# if the device selected was for grub, set the BOOT_DEVICE
# this is needed because grub uses the base device for BIOS, not the partition
[[ $msg != "" ]] && BOOT_DEVICE="$DEVICE"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_mount_opts() {
local part="$1"
local fs="$2"
local title="${fs^} Mount Options"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
tput civis
MNT_OPTS="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $title " \
--checklist "$_MntBody" 0 0 0 ${FS_OPTS[$fs]} | sed 's/ /,/g; $s/,$//')"
[[ $? != 0 || $MNT_OPTS == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if ! yesno "$title" "$_MntConfBody $MNT_OPTS\n"; then
select_mount_opts "$part" "$fs" || return 1
2018-07-18 19:50:37 -05:00
fi
return 0
}
2018-07-18 19:52:06 -05:00
select_filesystem() {
local part="$1"
2018-07-28 15:03:43 -05:00
local cur_fs
cur_fs="$(lsblk -lno FSTYPE $part)"
2018-07-18 19:52:06 -05:00
tput civis
local choice
2018-07-28 14:36:08 -05:00
choice="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_FSTitle: $part" \
2018-08-17 03:21:15 -05:00
--menu "\nPartition: ${part}$([[ $cur_fs != "" ]] && echo -n "\nCurrent: ${cur_fs}")\n$_FSBody" 0 0 0 \
$([[ $cur_fs != "" ]] && echo -n "$_Skip -") \
2018-08-12 23:24:38 -05:00
"ext4" "${FS_CMDS[ext4]}" "ext3" "${FS_CMDS[ext3]}" \
"ext2" "${FS_CMDS[ext2]}" "vfat" "${FS_CMDS[vfat]}" \
"ntfs" "${FS_CMDS[ntfs]}" "f2fs" "${FS_CMDS[f2fs]}" \
"jfs" "${FS_CMDS[jfs]}" "nilfs2" "${FS_CMDS[nilfs2]}" \
"reiserfs" "${FS_CMDS[reiserfs]}" "xfs" "${FS_CMDS[xfs]}")"
2018-08-17 03:21:15 -05:00
[[ $choice == "$_Skip" ]] && return 0
2018-08-17 20:44:17 -05:00
[[ $choice == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if yesno "$_FSTitle" "\nFormat $part as $choice?\n"; then
infobox "$_FSTitle" "\nFormatting: $part\n\nCommand: ${FS_CMDS[$choice]}\n"
${FS_CMDS[$choice]} $part >/dev/null 2>$ERR
check_for_errors "${FS_CMDS[$choice]} $part" || return 1
else
select_filesystem "$part" || return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
2018-07-18 19:52:06 -05:00
select_boot_setup() {
# choose bootloader and by extension mountpoint (if needed)
tput civis
2018-08-17 03:21:15 -05:00
BOOTLOADER="$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title " $_PrepMount " --menu "$_MntBootBody" 0 0 0 ${BOOTLOADERS[$SYS]})"
2018-07-18 19:52:06 -05:00
[[ $? != 0 || $BOOTLOADER == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-08-17 03:21:15 -05:00
if [[ $SYS == 'BIOS' ]]; then
2018-07-18 19:52:06 -05:00
if [[ $BOOTLOADER == "grub" && $BOOT_DEVICE == "" ]]; then
# grub BIOS needs an install device eg. /dev/sda
select_device 'boot' || return 1
BOOT_DEVICE="$DEVICE"
2018-08-17 03:21:15 -05:00
else
2018-07-18 19:52:06 -05:00
local cmd
cmd="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_InstSysTitle " \
--menu "$_InstSysBody\nDefault: ${BOOT_CMDS[syslinux]}" 0 0 0 \
"syslinux-install_update -iam" "[MBR]" \
"syslinux-install_update -i" "[/]")"
2018-08-17 03:21:15 -05:00
[[ $? != 0 || $cmd == "" ]] && return 1
BOOT_CMDS[syslinux]="$cmd"
2018-08-17 20:44:17 -05:00
EDIT_FILES[9]="/boot/syslinux/syslinux.cfg"
2018-08-17 03:21:15 -05:00
fi
else
if [[ $BOOTLOADER == 'systemd-boot' ]]; then
2018-08-17 20:44:17 -05:00
EDIT_FILES[9]="/boot/loader/entries/archlabs.conf"
2018-08-17 03:21:15 -05:00
else
2018-08-17 20:44:17 -05:00
EDIT_FILES[9]="/etc/default/grub"
2018-08-17 03:21:15 -05:00
if yesno "$_PrepMount" "$_SetBootDefault"; then
GRUB_UEFI_FALLBACK=true
fi
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
fi
# if BOOT_PART was set, mount the partition to the correct mountpoint
if [[ $BOOT_PART != "" ]]; then
mount_partition "$BOOT_PART" "${BOOT_MNTS[$SYS-$BOOTLOADER]}" || return 1
SEPERATE_BOOT=1
2018-07-18 19:50:37 -05:00
fi
return 0
}
2018-07-18 19:52:06 -05:00
select_efi_partition() {
format_efi_as_vfat() {
infobox "$_FSTitle" "\nFormatting $1 as vfat/fat32.\n"
mkfs.vfat -F32 "$1" >/dev/null 2>$ERR
check_for_errors "mkfs.vfat -F32 $1" || return 1
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if (( COUNT == 1 )); then
BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2018-07-28 15:03:43 -05:00
infobox "$_PrepMount" "\nOnly one partition available for EFI: $BOOT_PART\n"
2018-07-18 19:52:06 -05:00
else
tput civis
BOOT_PART="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepMount " \
--menu "$_SelUefiBody" 0 0 0 $PARTS)"
[[ $? != 0 || $BOOT_PART == "" ]] && return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
local msg="$_FormUefiBody $BOOT_PART $_FormUefiBody2"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if yesno "$_PrepMount" "$msg" "Format $BOOT_PART" "Skip Formatting" "no"; then
format_efi_as_vfat "$BOOT_PART" || return 1
fi
else
format_efi_as_vfat "$BOOT_PART" || return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_bios_boot_partition() {
2018-07-30 02:30:35 -05:00
format_as_ext4() {
infobox "$_FSTitle" "\nFormatting $1 as ext4.\n"
mkfs.ext4 -q "$1" >/dev/null 2>$ERR
check_for_errors "mkfs.ext4 -q $1" || return 1
}
2018-07-27 23:51:57 -05:00
tput civis
BOOT_PART="$(dialog --cr-wrap --stdout --backtitle "$BT" --title "$_PrepMount" \
--menu "$_SelBiosBody" 0 0 0 "$_Skip" "-" $PARTS)"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ $? != 0 || $BOOT_PART == "$_Skip" || $BOOT_PART == "" ]]; then
2018-07-28 15:03:43 -05:00
BOOT_PART=""
2018-07-18 19:52:06 -05:00
else
2018-07-30 02:30:35 -05:00
if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
local msg="$_FormBiosBody $BOOT_PART $_FormUefiBody2"
if yesno "$_PrepMount" "$msg" "Format $BOOT_PART" "Skip Formatting" "no"; then
format_as_ext4 "$BOOT_PART" || return 1
fi
else
format_as_ext4 "$BOOT_PART" || return 1
fi
2018-07-28 15:03:43 -05:00
# set BOOT_DEVICE for BIOS grub by removing digit from the end
BOOT_DEVICE="${BOOT_PART%[1-9]}"
2018-07-30 02:30:35 -05:00
PART_NUM="${BOOT_PART#$BOOT_DEVICE}"
parted -s $BOOT_DEVICE set $PART_NUM boot on 2>$ERR
check_for_errors "parted -s $BOOT_DEVICE set $PART_NUM boot on" || return 1
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
2018-07-18 19:52:06 -05:00
select_root_partition() {
if (( LUKS == 1 && LVM == 0 )); then
ROOT_PART="/dev/mapper/$LUKS_NAME"
decrease_part_count "$LUKS_PART"
2018-07-28 14:59:12 -05:00
elif (( LUKS == 1 && LVM == 1 )); then
decrease_part_count "$LUKS_PART"
decrease_part_count "/dev/mapper/$LUKS_NAME"
2018-07-28 15:03:43 -05:00
ROOT_PART=""
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-28 15:03:43 -05:00
if [[ $COUNT -eq 1 && $ROOT_PART == "" ]]; then
2018-07-18 19:52:06 -05:00
ROOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2018-07-28 14:59:12 -05:00
infobox "$_PrepMount" "\nOnly one partition available for root (/): $ROOT_PART\n"
2018-07-18 19:52:06 -05:00
elif [[ $ROOT_PART == "" || $LVM -eq 1 ]]; then
tput civis
ROOT_PART="$(dialog --cr-wrap --stdout --backtitle "$BT" --title "$_PrepMount" \
--menu "$_SelRootBody" 0 0 0 $PARTS)"
[[ $? != 0 || $ROOT_PART == "" ]] && return 1
2018-07-18 19:50:37 -05:00
else
2018-07-18 19:52:06 -05:00
infobox "$_PrepMount" "\nUsing $([[ $LUKS -eq 1 ]] && echo -n "encrypted ")root partition: $ROOT_PART\n"
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_filesystem "$ROOT_PART" || { ROOT_PART=""; return 1; }
2018-07-27 22:54:09 -05:00
mount_partition "$ROOT_PART" "" || { ROOT_PART=""; return 1; }
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_mountpoint() {
tput cnorm
2018-07-30 02:30:35 -05:00
EXTRA_MNT="$(getinput "$_PrepMount $part" "$_ExtPartBody1 /home /var\n" "/")"
2018-07-18 19:52:06 -05:00
[[ $? != 0 || $EXTRA_MNT == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# bad mountpoint
if [[ ${EXTRA_MNT:0:1} != "/" || ${#EXTRA_MNT} -le 1 || $EXTRA_MNT =~ \ |\' ]]; then
msgbox "$_ErrTitle" "$_ExtErrBody"
select_mountpoint || return 1
2018-07-18 19:50:37 -05:00
fi
return 0
}
2018-07-18 19:52:06 -05:00
select_extra_partitions() {
while (( COUNT > 0 )); do
tput civis
local part
part="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepMount " \
--menu "$_ExtPartBody" 0 0 0 "$_Done" "-" $PARTS)"
2018-07-18 19:50:37 -05:00
2018-07-28 14:36:08 -05:00
# cancel or done, exit normally
[[ $? != 0 || $part == "$_Done" || $part == "" ]] && break
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# choose what filesystem and get mountpoint
select_filesystem "$part" || { break; return 1; }
select_mountpoint || { break; return 1; }
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# mount it
mount_partition "$part" "$EXTRA_MNT" || { break; return 1; }
2018-07-18 19:50:37 -05:00
2018-07-28 14:36:08 -05:00
# if the mountpoint was /usr add 'usr' to MKINIT_HOOKS
[[ $EXTRA_MNT == "/usr" && $MKINIT_HOOKS != *usr* ]] && MKINIT_HOOKS="usr $MKINIT_HOOKS"
2018-07-18 19:52:06 -05:00
done
2018-07-18 19:50:37 -05:00
return 0
}
select_install_partitions() {
2018-07-18 19:52:06 -05:00
msgbox "$_PrepMount" "$_WarnMount"
2018-07-18 19:50:37 -05:00
lvm_detect
2018-07-18 19:52:06 -05:00
# prepare partition list PARTS for dialog
2018-07-18 19:50:37 -05:00
unmount_partitions
2018-07-18 19:52:06 -05:00
find_partitions 'part|lvm|crypt' || return 1
# remove boot partition from dialog list if we auto partitioned one
[[ $BOOT_PART != "" ]] && decrease_part_count "$BOOT_PART"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_root_partition || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ $BOOT_PART == "" ]]; then
if [[ $SYS == "UEFI" ]]; then
select_efi_partition || { BOOT_PART=""; return 1; }
2018-07-30 02:30:35 -05:00
elif (( COUNT > 0 )); then
2018-08-14 21:58:07 -05:00
select_bios_boot_partition || { BOOT_PART=""; return 1; }
2018-07-18 19:52:06 -05:00
fi
else
infobox "$_PrepMount" "\nUsing boot partition: $BOOT_PART\n"
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
select_boot_setup || { BOOTLOADER=""; return 1; }
2018-07-18 19:50:37 -05:00
select_swap || return 1
2018-07-28 14:36:08 -05:00
select_extra_partitions || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
check_part_is_crypt_or_lvm() {
local part="$1"
local devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# Identify if $part is "crypt" (LUKS on LVM, or LUKS alone)
if [[ $(lsblk -lno TYPE "$part") =~ 'crypt' ]]; then
LUKS=1
LUKS_NAME="${part#/dev/mapper/}"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
if grep -q "$LUKS_NAME" <<< "$(lsblk -lno NAME "$dev")"; then
LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
LVM=1
break
fi
done
for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
if grep -q "$LUKS_NAME" <<< "$(lsblk -lno NAME "$dev")"; then
LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
break
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
done
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
elif [[ $(lsblk -lno TYPE "$part") =~ 'lvm' ]]; then
LVM=1
VOLUME_NAME="${part#/dev/mapper/}"
for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
if grep -q "$VOLUME_NAME" <<< "$(lsblk -lno NAME "$dev")"; then
LUKS_NAME="$(sed 's~/dev/mapper/~~g' <<< "$dev")"
break
fi
done
for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
if grep -q "$LUKS_NAME" <<< "$(lsblk -lno NAME "$dev")"; then
LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
LUKS=1
break
fi
done
fi
2018-07-18 19:50:37 -05:00
}
######################################################################
## Encryption (dm_crypt) Functions ##
######################################################################
luks_open() {
2018-07-18 19:52:06 -05:00
LUKS_PART=""
modprobe -a dm-mod dm_crypt
2018-07-18 19:50:37 -05:00
unmount_partitions
2018-07-18 19:52:06 -05:00
find_partitions 'part|crypt|lvm'
tput civis
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if (( COUNT == 1 )); then
LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
infobox "$_LuksOpen" "\nOnly one partition available: $LUKS_PART\n"
else
tput civis
LUKS_PART="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_LuksOpen " \
--menu "$_LuksMenuBody" 0 0 0 $PARTS)"
[[ $? != 0 || $LUKS_PART == "" ]] && return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# get password and name for encryption
luks_input_values "$_LuksOpen" "$LUKS_NAME" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
infobox "$_LuksOpen" "$_LuksWaitBody $LUKS_NAME $_LuksWaitBody2 $LUKS_PART\n"
echo "$LUKS_PASS" | cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" 2>$ERR
check_for_errors "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
LUKS=1
luks_show
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
luks_input_values() {
local title="$1"
local name="$2"
LUKS_PASS=""
tput cnorm
local values
values="$(dialog --stdout --separator '~' --ok-label "Submit" --backtitle "$BT" \
--title " $title " --insecure --mixedform "$_LuksOpenBody" 16 75 4 \
"$_Name" 1 1 "$name" 1 $((${#_Name} + 2)) 71 0 0 \
"$_Password" 2 1 "" 2 $((${#_Password} + 2)) 71 0 1 \
"$_Password2" 3 1 "" 3 $((${#_Password2} + 2)) 71 0 1)"
[[ $? != 0 || $values == "" ]] && return 1
name="$(awk -F'~' '{print $1}' <<< "$values")"
local pass pass2
pass="$(awk -F'~' '{print $2}' <<< "$values")"
pass2="$(awk -F'~' '{print $3}' <<< "$values")"
if [[ $pass == "" || "$pass" != "$pass2" ]]; then
msgbox "$_ErrTitle" "$_PassErr\n$_TryAgain"
luks_input_values "$title" "$name" || return 1
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
LUKS_PASS="$pass"
LUKS_NAME="$name"
return 0
2018-07-18 19:50:37 -05:00
}
luks_setup() {
2018-07-18 19:52:06 -05:00
LUKS_PART=""
2018-07-18 19:50:37 -05:00
modprobe -a dm-mod dm_crypt
unmount_partitions
2018-07-18 19:52:06 -05:00
if [[ $ROOT_PART == "" || $LVM -eq 1 ]]; then
find_partitions 'part|lvm'
[[ $BOOT_PART != "" ]] && decrease_part_count "$BOOT_PART"
if (( COUNT == 1 )); then
LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
infobox "$_LuksEncrypt" "\nOnly one partition available: $LUKS_PART\n"
else
tput civis
LUKS_PART="$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title "$_LuksEncrypt" --menu "$_LuksEncryptBody" 0 0 0 $PARTS)"
[[ $? != 0 || $LUKS_PART == "" ]] && return 1
fi
else
infobox "$_PrepMount" "\nUsing root partition created in auto partitioning: $ROOT_PART\n"
LUKS_PART="$ROOT_PART"
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# get password and name for encryption
luks_input_values "$_LuksEncrypt" "$LUKS_NAME" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
luks_default() {
2018-07-18 19:52:06 -05:00
luks_setup || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local msg="$_LuksWaitBody $LUKS_NAME $_LuksWaitBody2 $LUKS_PART\n"
infobox "$_LuksEncrypt" "$msg"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
echo "$LUKS_PASS" | cryptsetup -q luksFormat "$LUKS_PART" 2>$ERR
check_for_errors "cryptsetup -q luksFormat $LUKS_PART" || return 1
echo "$LUKS_PASS" | cryptsetup open "$LUKS_PART" "$LUKS_NAME" 2>$ERR
check_for_errors "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
LUKS=1
luks_show
return 0
2018-07-18 19:50:37 -05:00
}
2018-07-18 19:52:06 -05:00
luks_cipher_key() {
2018-07-18 19:50:37 -05:00
if luks_setup; then
2018-07-18 19:52:06 -05:00
tput cnorm
local cipher
cipher="$(getinput "$_PrepLUKS" "$_LuksCipherKey" "-s 512 -c aes-xts-plain64")"
[[ $? != 0 || $cipher == "" ]] && return 1
infobox "$_LuksEncryptAdv" "$_LuksWaitBody $LUKS_NAME $_LuksWaitBody2 $LUKS_PART\n"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
echo "$LUKS_PASS" | cryptsetup -q $cipher luksFormat $LUKS_PART 2>$ERR
check_for_errors "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
echo "$LUKS_PASS" | cryptsetup open $LUKS_PART "$LUKS_NAME" 2>$ERR
check_for_errors "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2018-07-18 19:50:37 -05:00
luks_show
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
return 1
2018-07-18 19:50:37 -05:00
}
luks_show() {
2018-07-18 19:52:06 -05:00
tput civis
sleep 0.5
echo -e "$_LuksEncryptSucc" > /tmp/.devlist
lsblk -o NAME,TYPE,FSTYPE,SIZE $LUKS_PART >> /tmp/.devlist
dialog --cr-wrap --backtitle "$BT" --title " $_LuksEncrypt " --textbox /tmp/.devlist 0 0
2018-07-18 19:50:37 -05:00
}
luks_menu() {
2018-07-18 19:52:06 -05:00
tput civis
local choice
choice="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepLUKS " \
--menu "${_LuksMenuBody}${_LuksMenuBody2}${_LuksMenuBody3}" 0 0 0 \
2018-07-18 19:50:37 -05:00
"$_LuksEncrypt" "cryptsetup -q luksFormat" \
2018-07-18 19:52:06 -05:00
"$_LuksOpen" "cryptsetup open --type luks" \
2018-07-18 19:50:37 -05:00
"$_LuksEncryptAdv" "cryptsetup -q -s -c luksFormat" \
2018-07-18 19:52:06 -05:00
"$_Back" "-")"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
case $choice in
"$_LuksEncrypt") luks_default && return 0 ;;
"$_LuksOpen") luks_open && return 0 ;;
"$_LuksEncryptAdv") luks_cipher_key && return 0 ;;
2018-07-18 19:50:37 -05:00
*) return 0
esac
2018-07-18 19:52:06 -05:00
2018-07-18 19:50:37 -05:00
luks_menu
}
luks_keyfile() {
# Only used when choosing grub as bootloader. Without a keyfile, during boot
# the user will be asked to enter password for decryption twice, this is annoying
if [[ ! -e $MNT/crypto_keyfile.bin ]] && yesno "$_LuksKeyFileTitle" "$_LuksKeyFile"; then
2018-07-18 19:52:06 -05:00
infobox "$_LuksKeyFileTitle" "$_LuksKeyFileCreate"
2018-07-18 19:50:37 -05:00
local dev
2018-07-18 19:52:06 -05:00
dev="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2018-07-18 19:50:37 -05:00
2018-07-28 15:03:43 -05:00
dev="/dev/$dev"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local keycmd
keycmd="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin && chmod 000 /crypto_keyfile.bin &&
echo '$LUKS_PASS' | cryptsetup luksAddKey $dev /crypto_keyfile.bin"
chroot_cmd "$keycmd" 2>$ERR
check_for_errors "$keycmd" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
check_for_errors 'sed -i "s/FILES=()/FILES=(/crypto_keyfile.bin)/g"' || return 1
2018-07-18 19:50:37 -05:00
2018-08-20 04:26:13 -05:00
chroot_cmd "mkinitcpio -p $KERNEL" 2>$ERR >/dev/null 2>&1
check_for_errors "mkinitcpio -p $KERNEL" || return 1
2018-07-18 19:50:37 -05:00
fi
return 0
}
######################################################################
## Logical Volume Management Functions ##
######################################################################
lvm_detect() {
2018-07-18 19:52:06 -05:00
PHYSICAL_VOLUMES="$(pvs -o pv_name --noheading 2>/dev/null)"
VOLUME_GROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ $VOLUMES && $VOLUME_GROUP && $PHYSICAL_VOLUMES ]]; then
2018-07-18 19:50:37 -05:00
infobox "$_PrepLVM" "$_LvmDetBody"
modprobe dm-mod 2>$ERR
2018-07-18 19:52:06 -05:00
check_for_errors 'modprobe dm-mod' || return 1
2018-07-18 19:50:37 -05:00
vgscan >/dev/null 2>&1
vgchange -ay >/dev/null 2>&1
fi
}
lvm_show_vg() {
2018-07-28 02:25:31 -05:00
DEL_VG=""
2018-07-18 19:52:06 -05:00
VOL_GROUP_LIST=""
2018-07-18 19:50:37 -05:00
for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2018-07-18 19:52:06 -05:00
VOL_GROUP_LIST="$VOL_GROUP_LIST $i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}')"
2018-07-18 19:50:37 -05:00
done
2018-07-28 02:25:31 -05:00
if [[ $VOL_GROUP_LIST == "" ]]; then
msgbox "$_ErrTitle" "$_LvmVGErr"
2018-07-18 19:50:37 -05:00
return 1
fi
2018-07-18 19:52:06 -05:00
tput civis
2018-07-28 02:25:31 -05:00
DEL_VG="$(dialog --cr-wrap --stdout --backtitle "$BT" \
2018-07-18 19:52:06 -05:00
--title " $_PrepLVM " --menu "$_LvmSelVGBody" 18 70 10 $VOL_GROUP_LIST)"
2018-07-28 02:25:31 -05:00
[[ $? != 0 || $DEL_VG == "" ]] && return 1
2018-07-18 19:50:37 -05:00
}
2018-07-18 19:52:06 -05:00
get_lv_size() {
tput cnorm
local ttl=" $_LvmCreateVG (LV:$VOL_COUNT) "
local msg="${VOLUME_GROUP}: ${VOL_GROUP_SIZE}$VOL_GROUP_SIZE_TYPE (${VOL_GROUP_MB}MB $_LvmLvSizeBody1).$_LvmLvSizeBody2"
VOLUME_SIZE="$(getinput "$ttl" "$msg" "")"
[[ $? != 0 || $VOLUME_SIZE == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
ERR_SIZE=0
# if the size is empty or 0
(( ${#VOLUME_SIZE} == 0 || ${VOLUME_SIZE:0:1} == 0 )) && ERR_SIZE=1
2018-07-18 19:50:37 -05:00
if (( ERR_SIZE == 0 )); then
2018-07-18 19:52:06 -05:00
# number of characters in VOLUME_SIZE minus the last, which should be a letter
local lv="$((${#VOLUME_SIZE} - 1))"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# loop each character (except the last) in VOLUME_SIZE and ensure they are numbers
2018-07-18 19:50:37 -05:00
for (( i=0; i<lv; i++ )); do
2018-07-18 19:52:06 -05:00
[[ ${VOLUME_SIZE:$i:1} != [0-9] ]] && { ERR_SIZE=1; break; }
2018-07-18 19:50:37 -05:00
done
if (( ERR_SIZE == 0 )); then
2018-07-18 19:52:06 -05:00
# ensure the last character is either m/M or g/G
case ${VOLUME_SIZE:$lv:1} in
2018-07-18 19:50:37 -05:00
[mMgG]) ERR_SIZE=0 ;;
*) ERR_SIZE=1
esac
if (( ERR_SIZE == 0 )); then
2018-07-18 19:52:06 -05:00
s=${VOLUME_SIZE:0:$lv}
2018-07-18 19:50:37 -05:00
m=$((s * 1000))
2018-07-18 19:52:06 -05:00
# check whether the value is greater than or equal to the LV remaining Size.
# if not, convert into MB for VG space remaining.
case ${VOLUME_SIZE:$lv:1} in
[Gg])
if (( m >= VOL_GROUP_MB )); then
ERR_SIZE=1
else
VOL_GROUP_MB=$((VOL_GROUP_MB - m))
fi ;;
[Mm])
if (( ${VOLUME_SIZE:0:$lv} >= VOL_GROUP_MB )); then
ERR_SIZE=1
else
VOL_GROUP_MB=$((VOL_GROUP_MB - s))
fi ;;
2018-07-18 19:50:37 -05:00
*) ERR_SIZE=1
esac
fi
fi
fi
if (( ERR_SIZE == 1 )); then
msgbox "$_ErrTitle" "$_LvmLvSizeErrBody"
2018-07-18 19:52:06 -05:00
get_lv_size || return 1
2018-07-18 19:50:37 -05:00
fi
return 0
}
2018-07-18 19:52:06 -05:00
lvm_volume_name() {
local msg="$1"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local default="volmain"
(( VOL_COUNT > 1 )) && default="volextra"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
tput cnorm
local name
name="$(getinput "$_LvmCreateVG (LV:$VOL_COUNT)" "$msg" "$default")"
[[ $? != 0 || $name == "" ]] && return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# bad volume name answer or name already in use
if [[ ${name:0:1} == "/" || ${#name} -eq 0 || $name =~ \ |\' ]] || grep -q "$name" <<< "$(lsblk)"; then
msgbox "$_ErrTitle" "$_LvmLvNameErrBody"
lvm_volume_name "$msg" || return 1
fi
VOLUME_NAME="$name"
return 0
}
lvm_group_name() {
tput cnorm
local group
group="$(getinput "$_LvmCreateVG" "$_LvmNameVgBody" "VolGroup")"
[[ $? != 0 || $group == "" ]] && return 1
# bad answer or group name already taken
if [[ ${group:0:1} == "/" || ${#group} -eq 0 || $group =~ \ |\' ]] || grep -q "$group" <<< "$(lsblk)"; then
2018-07-18 19:50:37 -05:00
msgbox "$_ErrTitle" "$_LvmNameVgErr"
2018-07-18 19:52:06 -05:00
lvm_group_name || return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
VOLUME_GROUP="$group"
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
lvm_extra_lvs() {
while (( VOL_COUNT > 1 )); do
# get the name and size
lvm_volume_name "$_LvmLvNameBody1" || { break; return 1; }
get_lv_size || { break; return 1; }
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# create it
lvcreate -L "$VOLUME_SIZE" "$VOLUME_GROUP" -n "$VOLUME_NAME" 2>$ERR
check_for_errors "lvcreate -L $VOLUME_SIZE $VOLUME_GROUP -n $VOLUME_NAME" || { break; return 1; }
msgbox "$_LvmCreateVG (LV:$VOL_COUNT)" "$_Done LV $VOLUME_NAME ($VOLUME_SIZE) $_LvmPvDoneBody2."
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
((VOL_COUNT--)) # decrement the number of volumes chosen to end the loop
done
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
lvm_volume_count() {
VOL_COUNT=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_LvmCreateVG " \
2018-07-27 22:54:09 -05:00
--radiolist "$_LvmLvNumBody1 $VOLUME_GROUP\n$_LvmLvNumBody2" 0 0 0 \
2018-07-18 19:52:06 -05:00
"1" "-" off "2" "-" off "3" "-" off "4" "-" off "5" "-" off "6" "-" off "7" "-" off "8" "-" off "9" "-" off)
[[ $? != 0 || $VOL_COUNT == "" ]] && return 1
return 0
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
lvm_create() {
VOLUME_GROUP=""
VOL_GROUP_PARTS=""
VOL_GROUP_MB=0
unmount_partitions
if [[ $LUKS -eq 1 && $LUKS_NAME != "" ]]; then
VOL_GROUP_PARTS="/dev/mapper/$LUKS_NAME"
2018-07-28 15:03:43 -05:00
infobox "$_LvmCreateVG" "\nUsing encrypted partition created earlier: $VOL_GROUP_PARTS\n"
2018-07-18 19:52:06 -05:00
else
find_partitions 'part|crypt'
tput civis
PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
# choose partitions
VOL_GROUP_PARTS="$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title "$_LvmCreateVG" --checklist "$_LvmPvSelBody" 0 0 0 $PARTS)"
[[ $? != 0 || $VOL_GROUP_PARTS == "" ]] && return 1
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# get volume group name then confirm or bail out
lvm_group_name || return 1
2018-07-28 02:25:31 -05:00
yesno "$_LvmCreateVG" "$_LvmPvConfBody1 $VOLUME_GROUP\n\n$_LvmPvConfBody2 $VOL_GROUP_PARTS\n" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# create it
infobox "$_LvmCreateVG" "$_LvmPvActBody1 $VOLUME_GROUP\n"
vgcreate -f "$VOLUME_GROUP" "$VOL_GROUP_PARTS" >/dev/null 2>$ERR
check_for_errors "vgcreate -f $VOLUME_GROUP $VOL_GROUP_PARTS" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# get volume size and size type (MB, GB, etc..)
VOL_GROUP_SIZE=$(vgdisplay "$VOLUME_GROUP" | awk '/VG Size/ {gsub(/\..*|[^0-9]*/, ""); print}')
VOL_GROUP_SIZE_TYPE="$(vgdisplay "$VOLUME_GROUP" | awk '/VG Size/ {print $4}')"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# transform size to MB if needed
if [[ ${VOL_GROUP_SIZE_TYPE:0:1} == "G" ]]; then
VOL_GROUP_MB=$((VOL_GROUP_SIZE * 1000))
else
VOL_GROUP_MB=$VOL_GROUP_SIZE
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# finished volume group creation
2018-07-27 22:54:09 -05:00
msgbox "$_LvmCreateVG" "$_LvmPvDoneBody1 $VOLUME_GROUP ($VOL_GROUP_SIZE $VOL_GROUP_SIZE_TYPE) $_LvmPvDoneBody2\n"
2018-07-18 19:52:06 -05:00
tput civis
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# how many logical volumes
lvm_volume_count || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# if we chose more than one logical volume create all but the last
lvm_extra_lvs || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# last or only logical volume
2018-07-27 22:54:09 -05:00
lvm_volume_name "$_LvmLvNameBody1 $_LvmLvNameBody2 (${VOL_GROUP_MB}MB)" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# create it
lvcreate -l +100%FREE "$VOLUME_GROUP" -n "$VOLUME_NAME" 2>$ERR
check_for_errors "lvcreate -l +100%FREE $VOLUME_GROUP -n $VOLUME_NAME" || return 1
2018-07-18 19:50:37 -05:00
LVM=1
2018-07-18 19:52:06 -05:00
# offer the user to see the device tree
yesno "$_LvmCreateVG" "$_LvmCompBody" && show_devices
2018-07-18 19:50:37 -05:00
return 0
}
lvm_del_vg() {
2018-07-28 02:25:31 -05:00
if lvm_show_vg; then
yesno "$_LvmDelVG" "$_LvmDelQ" && vgremove -f "$DEL_VG" >/dev/null 2>&1
fi
2018-07-18 19:50:37 -05:00
return 0
}
lvm_del_all() {
2018-07-18 19:52:06 -05:00
PHYSICAL_VOLUMES="$(pvs -o pv_name --noheading 2>/dev/null)"
VOLUME_GROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2018-07-18 19:50:37 -05:00
if yesno "$_LvMDelAll" "$_LvmDelQ"; then
2018-07-18 19:52:06 -05:00
for i in $VOLUMES; do
2018-07-18 19:50:37 -05:00
lvremove -f "/dev/mapper/$i" >/dev/null 2>&1
done
2018-07-18 19:52:06 -05:00
for i in $VOLUME_GROUP; do
2018-07-18 19:50:37 -05:00
vgremove -f "$i" >/dev/null 2>&1
done
2018-07-18 19:52:06 -05:00
for i in $PHYSICAL_VOLUMES; do
2018-07-18 19:50:37 -05:00
pvremove -f "$i" >/dev/null 2>&1
done
LVM=0
fi
return 0
}
lvm_menu() {
lvm_detect
2018-07-18 19:52:06 -05:00
tput civis
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local choice
choice="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepLVM " \
--menu "$_LvmMenu" 0 0 0 \
2018-07-18 19:50:37 -05:00
"$_LvmCreateVG" "vgcreate -f, lvcreate -L -n" \
"$_LvmDelVG" "vgremove -f" \
"$_LvMDelAll" "lvrmeove, vgremove, pvremove -f" \
2018-07-18 19:52:06 -05:00
"$_Back" "-")"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
case $choice in
"$_LvmCreateVG") lvm_create && return 0 ;;
2018-07-18 19:50:37 -05:00
"$_LvmDelVG") lvm_del_vg ;;
"$_LvMDelAll") lvm_del_all ;;
*) return 0
esac
lvm_menu
}
######################################################################
## Installation Functions ##
######################################################################
install_main() {
2018-07-18 19:52:06 -05:00
if [[ $UNPACKED_BASE != true ]]; then
2018-07-30 02:30:35 -05:00
# whether to use a custom mirror sorting command later
2018-08-20 04:26:13 -05:00
mirrorlist_cmd || MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate"
window_manager || return 1
extra_packages
if yesno "Choose Kernel" "\nWant to use the standard linux or linux LTS kernel" "Linux" "Linux LTS"; then
KERNEL="linux"
2018-08-22 02:25:14 -05:00
else
KERNEL="linux-lts"
2018-08-20 04:26:13 -05:00
fi
2018-08-12 23:24:38 -05:00
2018-07-28 15:03:43 -05:00
# user can choose to bail at this point
unpack_base_system || { initialize_variables; return 1; }
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
genfstab -U $MNT > $MNT/etc/fstab 2>$ERR
check_for_errors "genfstab -U $MNT > $MNT/etc/fstab" || return 1
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ -f $MNT/swapfile ]]; then
sed -i "s~${MNT}~~" $MNT/etc/fstab 2>$ERR
check_for_errors "sed -i s~${MNT}~~ $MNT/etc/fstab" || return 1
fi
2018-07-18 19:50:37 -05:00
run_mkinitcpio || return 1
setup_bootloader || return 1
2018-07-18 19:52:06 -05:00
if [[ $HAS_NETWORK == true && $DONE_UPDATE != true ]]; then
2018-07-30 02:30:35 -05:00
update_mirrorlist
update_system
2018-07-18 19:52:06 -05:00
DONE_UPDATE=true
else
2018-08-20 04:26:13 -05:00
if ! grep -qi "hypervisor" <<< "$(dmesg)"; then
chroot_cmd "pacman -Rns archlabs-installer virtualbox-guest-utils virtualbox-guest-modules-arch --noconfirm" 2>/dev/null
2018-08-14 21:58:07 -05:00
[[ -e $MNT/etc/xdg/autostart/vboxclient.desktop ]] && rm -f $MNT/etc/xdg/autostart/vboxclient.desktop
2018-08-20 04:26:13 -05:00
else
chroot_cmd "pacman -Rs archlabs-installer --noconfirm" 2>/dev/null
2018-08-14 21:58:07 -05:00
fi
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
# these also only should need to be run once, when done jump to the config edit menu
if [[ $FULL_DONE != true ]]; then
configure_menu
if edit_config_menu; then
[[ $FULL_DONE == true ]] && return 0
2018-07-18 19:50:37 -05:00
fi
fi
2018-08-20 04:26:13 -05:00
return 0
2018-07-18 19:52:06 -05:00
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
unpack_base_system() {
# continue or bail
2018-07-28 15:03:43 -05:00
local msg="Boot Partition: ${BOOT_PART:-none}\nBootloader: $BOOTLOADER\nSwapfile: $SWAP_FILE"
2018-07-18 19:52:06 -05:00
yesno "$_InstTitle" "$_BeginInst $ROOT_PART\n$msg\n\n$_ContinueYN" || return 1
# create a loading bar while copying files using find, < <(), and a loop
# using awk, sed, or other means doesn't seem to work well (or at all).
local files=($(find /run/archiso/sfs/airootfs/ -maxdepth 1 -mindepth 1))
local total=${#files[@]}
local increment=0
tput civis
dialog --cr-wrap --backtitle "$BT" --title " $_InstTitle " \
--gauge "\nUnpacking the system\n" 7 70 < <(
for f in "${files[@]}"; do
current_percent=$((100 * (++increment) / total))
base="${f#/run/archiso/sfs/airootfs/}"
cat <<EOF
XXX
$current_percent
Unpacking /$base ...
XXX
EOF
if [[ $base == 'sbin' ]]; then
mkdir -p $MNT/usr/bin
ln -sfr $MNT/usr/bin $MNT/$base
elif [[ $base == 'bin' ]]; then
mkdir -p $MNT/usr/bin
ln -sfr $MNT/usr/bin $MNT/$base
elif [[ $base == 'lib' ]]; then
mkdir -p $MNT/usr/lib
ln -sfr $MNT/usr/lib $MNT/$base
elif [[ $base == 'lib64' ]]; then
mkdir -p $MNT/usr/lib
ln -sfr $MNT/usr/lib $MNT/$base
else
rsync -aq /run/archiso/sfs/airootfs/$base/ $MNT/$base
fi
done
)
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
find $MNT/usr/lib/initcpio -name 'archiso*' -type f -exec rm '{}' \;
rm -rf $MNT/etc/{mkinitcpio-archiso.conf,sudoers.d/g_wheel,polkit-1/rules.d/49-nopasswd_global.rules}
sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
cp -rf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
cp -f /run/archiso/bootmnt/arch/boot/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
cp -f /tmp/00-keyboard.conf $MNT/etc/X11/xorg.conf.d/
2018-07-18 19:50:37 -05:00
cp -f /tmp/keyboard $MNT/etc/default/
cp -f /tmp/vconsole.conf $MNT/etc/
cp -f /etc/resolv.conf $MNT/etc/
2018-07-18 19:52:06 -05:00
grep -qi "hypervisor" <<< "$(dmesg)" && rm -rf $MNT/etc/X11/xorg.conf.d
2018-08-17 20:44:17 -05:00
UNPACKED_BASE=true
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
2018-08-20 04:26:13 -05:00
update_system() {
local pkgcmd
if [[ $KERNEL == 'linux-lts' ]]; then
pkgcmd="pacman -Rs linux --noconfirm ; pacman -S iputils --noconfirm ; pacman -S base-devel git linux-lts linux-lts-headers --needed --noconfirm"
else
pkgcmd="pacman -S iputils --noconfirm ; pacman -S base-devel git --needed --noconfirm"
fi
if ! grep -qi "hypervisor" <<< "$(dmesg)"; then
pkgcmd="pacman -Rs archlabs-installer virtualbox-guest-utils virtualbox-guest-modules-arch --noconfirm ; $pkgcmd"
else
pkgcmd="pacman -Rs archlabs-installer --noconfirm ; $pkgcmd"
fi
if [[ $BOOTLOADER == 'grub' && $KERNEL == 'linux-lts' ]]; then
pkgcmd="$pkgcmd; grub-mkconfig -o /boot/grub/grub.cfg"
elif [[ $BOOTLOADER != 'grub' ]]; then
pkgcmd="$pkgcmd; pacman -Rs grub --noconfirm"
rm -rf $MNT/etc/default/grub
find $MNT/boot/ -name 'grub*' -exec rm -rf '{}' \; >/dev/null 2>&1
fi
tput civis
chroot_cmd "pacman -Syyu --noconfirm ; $pkgcmd" 2>/dev/null | dialog --cr-wrap \
--backtitle "$BT" --title " $_UpdSysTitle " --progressbox "$_UpdSysBody\n" 30 90
install_packages
return 0
}
2018-08-12 23:24:38 -05:00
install_packages() {
2018-07-18 19:52:06 -05:00
tput civis
2018-08-12 23:24:38 -05:00
local pkgs="$WM_PACKAGES"
[[ $LOGIN_TYPE == 'lightdm' ]] && pkgs="$pkgs lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
2018-08-14 21:58:07 -05:00
[[ $EXTRA_PACKAGES != "" ]] && pkgs="$pkgs $EXTRA_PACKAGES"
2018-07-18 19:52:06 -05:00
2018-08-20 04:26:13 -05:00
if [[ $INSTALL_WMS == 'gnome' || $INSTALL_WMS == 'cinnamon' ]]; then
2018-08-19 23:10:03 -05:00
REMOVE_PKGS="$(pacman -Qssq 'xfce4*' 2>/dev/null)"
fi
2018-08-19 22:32:21 -05:00
local pkgcmd="pacman -S $pkgs --needed --noconfirm"
[[ $REMOVE_PKGS != "" ]] && pkgcmd="pacman -Rns $REMOVE_PKGS --noconfirm ; $pkgcmd"
chroot_cmd "$pkgcmd" 2>/dev/null | dialog --cr-wrap --backtitle "$BT" --title " Install Packages " \
--progressbox "\nInstalling packages chosen during install setup.\n\n$pkgs" 30 90
2018-08-12 23:24:38 -05:00
[[ $LOGIN_TYPE == 'lightdm' ]] && setup_lightdm
return 0
}
2018-08-19 22:32:21 -05:00
setup_lightdm() {
chroot_cmd 'systemctl enable lightdm.service && systemctl set-default graphical.target' >/dev/null 2>&1
2018-08-14 21:58:07 -05:00
2018-08-19 22:32:21 -05:00
local cfg="$MNT/etc/lightdm/lightdm-gtk-greeter.conf"
sed -i '/#background=/ c background=/usr/share/backgrounds/archlabs/archlabs.jpg' $cfg
sed -i '/#theme-name=/ c theme-name=ArchLabs-dARK' $cfg
sed -i '/#icon-theme-name=/ c icon-theme-name=ArchLabs-Light' $cfg
sed -i '/#position=/ c position=34%,end 66%,end' $cfg
sed -i '/#font-name=/ c font-name=DejaVu Sans Mono 11' $cfg
sed -i '/\[greeter]/ a default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png' $cfg
sed -i '/\[greeter]/ a active-monitor=0' $cfg
2018-08-14 21:58:07 -05:00
2018-08-19 22:32:21 -05:00
if [[ $AUTOLOGIN == true ]]; then
chroot_cmd 'groupadd -r nopasswdlogin' >/dev/null 2>&1
sed -i '/#%PAM-1.0/ a auth sufficient pam_succeed_if.so user ingroup nopasswdlogin' $MNT/etc/pam.d/lightdm
sed -i "/#autologin-session=/ c autologin-session=${LOGIN_WM}" $MNT/etc/lightdm/lightdm.conf
fi
}
2018-08-14 21:58:07 -05:00
2018-08-20 04:26:13 -05:00
mirrorlist_cmd() {
2018-07-18 19:52:06 -05:00
if ! yesno "$_MirrorTitle" "$_MirrorSetup" "Automatic Sort" "Customize Sort"; then
2018-07-30 02:30:35 -05:00
infobox "$_MirrorTitle" "\nGathering mirror countries..\n"
2018-07-18 19:52:06 -05:00
local countries
countries="$(reflector --list-countries | awk 'NF > 1 {print $1 " -"}')"
if [[ $countries != "" ]]; then
tput civis
2018-07-30 02:30:35 -05:00
local country
2018-08-12 23:24:38 -05:00
country="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \
--title "$_MirrorTitle" --menu "$_MirrorCountry" 22 70 10 $countries)"
2018-07-30 02:30:35 -05:00
MIRROR_CMD="reflector --country $country --score 80 --latest 40 --fastest 10 --sort rate"
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local ref=" --score n Limit the list to the n servers with the highest score.
-l n, --latest n Limit the list to the n most recently synchronized servers.
-f n, --fastest n Return the n fastest mirrors that meet the other criteria.
--sort {age,rate,country,score,delay}
'age': last server synchronization; 'rate': download rate;
'country': server's location; 'score': MirrorStatus score;
'delay': MirrorStatus delay."
tput cnorm
2018-08-12 23:24:38 -05:00
MIRROR_CMD="$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \
--title " $_MirrorTitle " --inputbox "$_MirrorCmd\n\n$ref\n" 0 0 "$cmd")"
2018-07-18 19:50:37 -05:00
fi
2018-07-30 02:30:35 -05:00
return 0
}
update_mirrorlist() {
2018-07-18 19:50:37 -05:00
infobox "$_MirrorTitle" "$_MirrorSort"
2018-07-18 19:52:06 -05:00
2018-07-30 02:30:35 -05:00
if ! $MIRROR_CMD --save $MNT/etc/pacman.d/mirrorlist; then
infobox "$_ErrTitle" "\nAn error occurred while updating the mirrorlist.\n\nFalling back to automatic sorting...\n"
reflector --score 100 -l 50 -f 10 --sort rate --save $MNT/etc/pacman.d/mirrorlist
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
2018-07-18 19:52:06 -05:00
bootloader_config() {
ROOT_PART_ID="$ROOT_PART"
if ! grep -q "/dev/mapper/" <<< "$ROOT_PART"; then
ROOT_PART_ID="UUID=$(blkid -s PARTUUID $ROOT_PART | sed 's/.*=//g; s/"//g')"
[[ $BOOTLOADER == "systemd-boot" ]] && ROOT_PART_ID="PART$ROOT_PART_ID"
fi
2018-07-18 19:50:37 -05:00
if [[ $BOOTLOADER == "grub" ]]; then
2018-07-18 19:52:06 -05:00
local cfg="$MNT/etc/default/grub"
sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $cfg
2018-07-18 19:50:37 -05:00
if (( LUKS == 1 )); then
2018-07-18 19:52:06 -05:00
sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $cfg
2018-07-18 19:50:37 -05:00
fi
if [[ $SYS != "UEFI" ]]; then
if (( LVM == 1 && SEPERATE_BOOT == 0 )) || (( SEPERATE_BOOT == 2 )); then
2018-07-18 19:52:06 -05:00
sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $cfg
2018-07-18 19:50:37 -05:00
fi
fi
elif [[ $BOOTLOADER == "syslinux" ]]; then
local cfgdir="$MNT/boot/syslinux"
2018-07-18 19:52:06 -05:00
mkdir -p $cfgdir
cp -f /usr/lib/syslinux/bios/vesamenu.c32 $cfgdir/
cp -f /run/archiso/bootmnt/arch/boot/syslinux/splash.png $cfgdir/
2018-07-18 19:50:37 -05:00
cat > $cfgdir/syslinux.cfg << EOF
2018-07-18 19:52:06 -05:00
UI vesamenu.c32
DEFAULT archlabs
PROMPT 0
MENU TITLE $DIST Syslinux Boot Menu
MENU BACKGROUND splash.png
TIMEOUT 50
MENU WIDTH 78
MENU MARGIN 4
MENU ROWS 5
MENU VSHIFT 10
MENU TIMEOUTROW 13
MENU TABMSGROW 11
MENU CMDLINEROW 11
MENU HELPMSGROW 16
MENU HELPMSGENDROW 29
# Refer to https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
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
2018-07-18 19:50:37 -05:00
LABEL archlabs
2018-07-18 19:52:06 -05:00
MENU LABEL $DIST Linux
2018-08-20 04:26:13 -05:00
LINUX ../vmlinuz-$KERNEL
2018-07-18 19:52:06 -05:00
APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && echo -n "$LUKS_DEV ")rw
2018-08-20 04:26:13 -05:00
INITRD ../initramfs-$KERNEL.img
2018-07-18 19:50:37 -05:00
LABEL archlabsfallback
2018-07-18 19:52:06 -05:00
MENU LABEL $DIST Linux Fallback
2018-08-20 04:26:13 -05:00
LINUX ../vmlinuz-$KERNEL
2018-07-18 19:52:06 -05:00
APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && echo -n "$LUKS_DEV ")rw
2018-08-20 04:26:13 -05:00
INITRD ../initramfs-$KERNEL-fallback.img
2018-07-18 19:50:37 -05:00
LABEL hdt
MENU LABEL HDT (Hardware Detection Tool)
COM32 hdt.c32
LABEL reboot
MENU LABEL Reboot
COM32 reboot.c32
LABEL poweroff
MENU LABEL Poweroff
COM32 poweroff.c32
EOF
else
2018-07-18 19:52:06 -05:00
# systemd-boot requires this before running bootctl
systemd-machine-id-setup --root="$MNT" >/dev/null 2>&1
mkdir -p $MNT/boot/loader/entries
2018-07-18 19:50:37 -05:00
cat > $MNT/boot/loader/loader.conf << EOF
default archlabs
timeout 5
editor no
EOF
2018-07-18 19:52:06 -05:00
cat > $MNT/boot/loader/entries/${DIST,,}.conf << EOF
title $DIST Linux
2018-08-20 04:26:13 -05:00
linux /vmlinuz-$KERNEL
initrd /initramfs-$KERNEL.img
2018-07-18 19:50:37 -05:00
options root=$ROOT_PART_ID rw
EOF
2018-07-18 19:52:06 -05:00
for file in $MNT/boot/loader/entries/arch*?.conf; do
(( LUKS == 1 )) && sed -i "s~rw~$LUKS_DEV rw~g" "$file"
2018-07-18 19:50:37 -05:00
done
fi
return 0
}
2018-07-18 19:52:06 -05:00
grub_uefi_fallback() {
2018-08-17 03:21:15 -05:00
# some UEFI firmware is finicky and requires a specific folder in
# /boot/efi/EFI/ and named 'boot', 'Boot', or 'BOOT'
2018-07-18 19:52:06 -05:00
local fb="boot"
2018-08-17 03:21:15 -05:00
local esp="${MNT}${BOOT_MNTS[$SYS-$BOOTLOADER]}/EFI/"
for i in $(find "$esp" -maxdepth 1 -mindepth 1 -type d 2>/dev/null); do
2018-07-18 19:52:06 -05:00
if grep -qi "boot" <<< "$(basename $i)"; then
fb="$(basename $i)"
break
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
done
2018-07-18 19:50:37 -05:00
2018-08-17 03:21:15 -05:00
# copy grub's efi stub binary to that directory as $stub
mkdir -p ${esp}$fb
cp -f ${esp}$DIST/grubx64.efi ${esp}$fb/bootx64.efi
2018-08-14 23:00:11 -05:00
return 0
2018-07-18 19:52:06 -05:00
}
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
setup_bootloader() {
chroot_cmd "export PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/bin/core_perl"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
local msg="$_InstBootloader $BOOTLOADER\n"
[[ $BOOT_PART != "" ]] && msg="$msg\n$_InstBootDev $BOOT_PART\n"
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
infobox "$_InstBootTitle" "$msg\nMountpoint: ${BOOT_MNTS[$SYS-$BOOTLOADER]}\n"
2018-07-18 19:50:37 -05:00
2018-08-17 03:21:15 -05:00
if [[ $SYS == "UEFI" ]]; then
2018-07-18 19:52:06 -05:00
local eficmd="mount -o remount,rw -t efivarfs efivarfs /sys/firmware/efi/efivars"
$eficmd >/dev/null 2>&1
BOOT_CMDS[$BOOTLOADER]="$eficmd ; ${BOOT_CMDS[$BOOTLOADER]}"
2018-08-20 04:26:13 -05:00
find $MNT/boot/efi/EFI/ -maxdepth 1 -mindepth 1 -name '[aA][rR][cC][hH][lL]abs*' -type d -exec rm -rf '{}' \; >/dev/null 2>&1
2018-08-17 03:21:15 -05:00
if [[ $GRUB_UEFI_FALLBACK == true ]]; then
2018-08-20 04:26:13 -05:00
find $MNT/boot/efi/EFI/ -maxdepth 1 -mindepth 1 -name '[Bb][oO][oO][tT]' -type d -exec rm -rf '{}' \; >/dev/null 2>&1
2018-08-17 03:21:15 -05:00
fi
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
# grub is finicky and requires special treatment
if [[ $BOOTLOADER == "grub" ]]; then
# needed for os-prober module to work properly in the chroot
local udevcmd="mkdir -p /run/udev && mount --rbind /run/udev /run/udev"
$udevcmd >/dev/null 2>&1
BOOT_CMDS[grub]="$udevcmd ; ${BOOT_CMDS[grub]}"
[[ $SYS == "BIOS" ]] && BOOT_CMDS[grub]="${BOOT_CMDS[grub]} $BOOT_DEVICE"
2018-08-20 04:26:13 -05:00
BOOT_CMDS[grub]="${BOOT_CMDS[grub]} ; grub-mkconfig -o /boot/grub/grub.cfg"
2018-07-18 19:50:37 -05:00
fi
2018-08-17 03:21:15 -05:00
# create the bootloader configs and run the setup commands, BOOT_CMDS[$BOOTLOADER]
2018-07-18 19:52:06 -05:00
bootloader_config
chroot_cmd "${BOOT_CMDS[$BOOTLOADER]}" 2>$ERR >/dev/null 2>&1
check_for_errors "${BOOT_CMDS[$BOOTLOADER]}" || return 1
2018-07-18 19:50:37 -05:00
2018-08-17 03:21:15 -05:00
# copy grub efi stub to generic catch all
[[ $GRUB_UEFI_FALLBACK == true ]] && grub_uefi_fallback
2018-07-18 19:52:06 -05:00
BOOT_DONE=true
2018-07-18 19:50:37 -05:00
2018-08-17 03:21:15 -05:00
# offer to setup a keyfile for LUKS.. Only when choosing grub and system is UEFI
if [[ $LUKS -eq 1 && $SYS == 'UEFI' && $BOOTLOADER == 'grub' && $LUKS_PASS && $LUKS_UUID ]]; then
luks_keyfile || return 1
2018-07-18 19:52:06 -05:00
fi
2018-07-18 19:50:37 -05:00
return 0
}
run_mkinitcpio() {
local conf="$MNT/etc/mkinitcpio.conf"
2018-07-18 19:52:06 -05:00
# new HOOKS needed in /etc/mkinitcpio.conf if we used LUKS and/or LVM
local add
(( LVM == 1 )) && add="lvm2"
(( LUKS == 1 )) && add="encrypt$([[ $add != "" ]] && echo -n " $add")"
if [[ ! -e $MNT/boot/vmlinuz-linux ]]; then
cp -f /run/archiso/bootmnt/arch/boot/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
sed -i "s/block filesystems/block ${add} filesystems ${MKINIT_HOOKS}/g" $conf 2>$ERR
check_for_errors "sed -i 's/block filesystems/block ${add} filesystems ${MKINIT_HOOKS}/g' $conf" || return 1
tput civis
2018-08-20 04:26:13 -05:00
chroot_cmd "mkinitcpio -p $KERNEL" 2>$ERR | dialog --cr-wrap --backtitle "$BT" \
2018-08-17 03:21:15 -05:00
--title " $_RunMkinit " --progressbox "$_RunMkinitBody\nHOOKS: $MKINIT_HOOKS $add\n" 30 90
2018-08-20 04:26:13 -05:00
check_for_errors "mkinitcpio -p $KERNEL" || return 1
2018-07-18 19:52:06 -05:00
return 0
2018-07-18 19:50:37 -05:00
}
######################################################################
2018-07-18 19:52:06 -05:00
## Menu Dialogs ##
2018-07-18 19:50:37 -05:00
######################################################################
main_menu() {
2018-07-18 19:52:06 -05:00
if [[ $FIRST_PREP != true ]]; then
FIRST_PREP=true
prepare_menu
2018-07-18 19:50:37 -05:00
fi
if [[ $CURRENT_MENU != "main" ]]; then
2018-07-18 19:52:06 -05:00
MENU_HIGHLIGHT=1
2018-07-18 19:50:37 -05:00
CURRENT_MENU="main"
2018-07-18 19:52:06 -05:00
elif (( MENU_HIGHLIGHT < 5 )); then
((MENU_HIGHLIGHT++))
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
tput civis
MENU_HIGHLIGHT=$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title " $_MainTitle " --default-item $MENU_HIGHLIGHT --menu "$_MainBody" 0 0 0 \
"1" "$_PrepTitle" "2" "$_InstTitle" "3" "$_ConfTitle" "4" "$_EditTitle" "5" "$_Done")
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ -n $MENU_HIGHLIGHT ]]; then
2018-08-17 20:44:17 -05:00
# if trying to unpack the system make sure the partitions are mounted
2018-07-18 19:52:06 -05:00
if (( MENU_HIGHLIGHT == 2 )) && ! check_parts_are_mounted; then
2018-07-18 19:50:37 -05:00
return 1
2018-07-18 19:52:06 -05:00
elif (( MENU_HIGHLIGHT == 3 || MENU_HIGHLIGHT == 4 )); then
2018-08-17 20:44:17 -05:00
# when trying to use config_menu() or edit config files make sure
# the system is unpacked and the partitions are mounted
2018-07-18 19:50:37 -05:00
if ! (check_parts_are_mounted && check_base_unpacked); then
return 1
fi
fi
fi
2018-07-18 19:52:06 -05:00
case $MENU_HIGHLIGHT in
2018-07-18 19:50:37 -05:00
1) prepare_menu ;;
2) install_main ;;
3) configure_menu ;;
4) edit_config_menu ;;
2018-07-18 19:52:06 -05:00
*) wrap_up "$_CloseInstBody" 'Exit' 'Back' 'exit'
2018-07-18 19:50:37 -05:00
esac
}
prepare_menu() {
2018-07-18 19:52:06 -05:00
if [[ $ROOT_PART != "" && $BOOTLOADER != "" ]]; then
if check_parts_are_mounted; then
# this is where all the action happens, the rest is mostly automated
2018-07-28 14:36:08 -05:00
# the user will likely reboot after and never get back here, but if we do
# returning goes to the main menu
2018-07-18 19:52:06 -05:00
install_main && return 0
2018-07-18 19:50:37 -05:00
fi
fi
2018-07-18 19:52:06 -05:00
if [[ $CURRENT_MENU != "prep" ]]; then
MENU_HIGHLIGHT=1
CURRENT_MENU="prep"
elif (( MENU_HIGHLIGHT < 7 )); then
((MENU_HIGHLIGHT++))
fi
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
tput civis
MENU_HIGHLIGHT=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepTitle " \
--default-item $MENU_HIGHLIGHT --menu "$_PrepBody" 0 0 0 \
"1" "$_PrepLayout" "2" "$_PrepShowDev" "3" "$_PrepParts" "4" "$_PrepLUKS" \
"5" "$_PrepLVM" "6" "$_PrepMount" "7" "$_Back")
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
case $MENU_HIGHLIGHT in
2018-07-18 19:50:37 -05:00
1) set_keymap ;;
2) show_devices ;;
2018-07-18 19:52:06 -05:00
3) unmount_partitions && select_device 'root' && create_partitions "$DEVICE" ;;
2018-07-18 19:50:37 -05:00
4) luks_menu ;;
5) lvm_menu ;;
6) select_install_partitions ;;
*) return 0
esac
prepare_menu
}
configure_menu() {
chroot_cmd "export PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/core_perl"
2018-07-18 19:52:06 -05:00
if [[ $FIRST_CONFIG != true ]]; then
FIRST_CONFIG=true
set_hostname && set_locale && create_user
[[ $FULL_DONE == true ]] && return 0
2018-07-18 19:50:37 -05:00
elif [[ $CURRENT_MENU != "config" ]]; then
2018-07-18 19:52:06 -05:00
MENU_HIGHLIGHT=1
2018-07-18 19:50:37 -05:00
CURRENT_MENU="config"
2018-07-18 19:52:06 -05:00
elif (( MENU_HIGHLIGHT < 4 )); then
((MENU_HIGHLIGHT++))
2018-07-18 19:50:37 -05:00
fi
2018-07-18 19:52:06 -05:00
tput civis
MENU_HIGHLIGHT=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_ConfTitle " \
--default-item $MENU_HIGHLIGHT --menu "$_ConfBody" 0 0 0 \
"1" "$_ConfHost" "2" "$_ConfLocale" "3" "$_ConfUser" "4" "$_Back")
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
case $MENU_HIGHLIGHT in
2018-07-18 19:50:37 -05:00
1) set_hostname ;;
2) set_locale ;;
2018-07-18 19:52:06 -05:00
3) create_user ;;
2018-07-18 19:50:37 -05:00
*) return 0
esac
configure_menu
}
edit_config_menu() {
if [[ $CURRENT_MENU != "edit" ]]; then
2018-07-18 19:52:06 -05:00
MENU_HIGHLIGHT=1
2018-07-18 19:50:37 -05:00
CURRENT_MENU="edit"
2018-07-18 19:52:06 -05:00
elif (( MENU_HIGHLIGHT < 10 )); then
((MENU_HIGHLIGHT++))
fi
local msg
[[ $FULL_DONE == true ]] && msg="${_Final}$_EditBody" || msg="$_EditBody"
tput civis
MENU_HIGHLIGHT=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_EditTitle " \
--default-item $MENU_HIGHLIGHT --menu "$msg" 0 0 0 \
2018-08-12 23:24:38 -05:00
"1" "$_Done" "2" "keymaps" "3" "locale" "4" "hostname" "5" "sudoers" \
"6" "mkinitcpio.conf" "7" "fstab" "8" "crypttab" "9" "$BOOTLOADER" "10" "pacman.conf")
if [[ $MENU_HIGHLIGHT == "" || $MENU_HIGHLIGHT == 1 ]]; then
2018-07-18 19:52:06 -05:00
if [[ $FULL_DONE == true && $CONFIRM_DONE != true ]]; then
CONFIRM_DONE=true
wrap_up "$_InstFinBody" 'Exit & Reboot' 'Go Back' 'reboot'
fi
return 0
fi
local existing_files=""
for f in $(echo "${EDIT_FILES[$MENU_HIGHLIGHT]}"); do
[[ -e ${MNT}$f ]] && existing_files="$existing_files ${MNT}$f"
done
2018-07-18 19:50:37 -05:00
2018-07-18 19:52:06 -05:00
if [[ $existing_files != "" ]]; then
2018-08-12 23:24:38 -05:00
if [[ $EDITOR_CHOICE == "" && $DISPLAY ]] && hash geany >/dev/null 2>&1; then
2018-07-18 19:52:06 -05:00
if yesno "$_EditTitle" "\nOpen file(s) in Geany or Vim?\n" "Geany" "Vim"; then
2018-07-28 15:03:43 -05:00
EDITOR_CHOICE="geany -i"
2018-07-18 19:52:06 -05:00
geany -i $existing_files
else
2018-07-28 15:03:43 -05:00
EDITOR_CHOICE="vim -O"
2018-07-18 19:52:06 -05:00
vim -O $existing_files
fi
2018-08-12 23:24:38 -05:00
elif [[ $EDITOR_CHOICE ]]; then
2018-07-28 15:03:43 -05:00
$EDITOR_CHOICE $existing_files
2018-07-18 19:50:37 -05:00
else
2018-07-18 19:52:06 -05:00
vim -O $existing_files
2018-07-18 19:50:37 -05:00
fi
else
msgbox "$_ErrTitle" "$_NoFileErr"
fi
edit_config_menu
}
2018-07-18 19:52:06 -05:00
for arg in "$@"; do
2018-07-18 19:50:37 -05:00
[[ $arg == "--debug" || $arg == "-d" ]] && set_debug
done
2018-07-18 19:52:06 -05:00
initialize_variables
2018-07-28 15:03:43 -05:00
luks_variable_init
2018-07-18 19:50:37 -05:00
select_language
check_requirements
identify_system
# welcome message
msgbox "$_WelTitle $DIST Installer" "$_WelBody"
while true; do
main_menu
done