342 lines
11 KiB
Bash
342 lines
11 KiB
Bash
#!/usr/bin/bash
|
|
|
|
# vim:ft=sh:fdm=marker:fmr={,}
|
|
|
|
# archlabs installer library script file
|
|
# this file is not meant to be run directly
|
|
# sourcing this file in a non bash shell is not advised
|
|
|
|
# shellcheck disable=2154,2155,2153,2046,2034
|
|
|
|
declare -Agr FS_CMDS=(
|
|
[ext2]="mkfs.ext2 -q" [ext3]="mkfs.ext3 -q" [ext4]="mkfs.ext4 -q"
|
|
[f2fs]="mkfs.f2fs" [jfs]="mkfs.jfs -q" [xfs]="mkfs.xfs -f" [nilfs2]="mkfs.nilfs2 -q"
|
|
[ntfs]="mkfs.ntfs -q" [reiserfs]="mkfs.reiserfs -q" [vfat]="mkfs.vfat -F32"
|
|
)
|
|
|
|
declare -Agr FS_OPTS=([vfat]="" [ntfs]="" [ext2]="" [ext3]=""
|
|
[ext4]="discard - off dealloc - 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"
|
|
[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"
|
|
)
|
|
|
|
format()
|
|
{
|
|
infobox "$_FSTitle" "\nFormatting: $1\n\nCommand: ${FS_CMDS[$2]}\n" 0
|
|
${FS_CMDS[$2]} $1 >/dev/null 2>$ERR
|
|
echeck "${FS_CMDS[$2]} $1"
|
|
}
|
|
|
|
partition()
|
|
{
|
|
local device
|
|
if [[ $# -eq 0 ]]; then
|
|
select_device 'root' || return 1
|
|
device="$DEVICE"
|
|
else
|
|
device="$1"
|
|
fi
|
|
|
|
tput civis
|
|
local choice
|
|
if ! choice="$(menubox "$_PartTitle" "$_PartBody" 0 0 0 "$_PartShowTree" "-" "$_PartAuto" "-" \
|
|
$({ [[ $DISPLAY ]] && hash gparted >/dev/null 2>&1; } && printf "gparted -") \
|
|
"cfdisk" "-" "parted" "-" "$_PartWipe" "-")"; then
|
|
return 1
|
|
fi
|
|
|
|
tput civis
|
|
if [[ $choice != "$_PartWipe" && $choice != "$_PartAuto" && $choice != "$_PartShowTree" ]]; then
|
|
clear; tput cnorm; $choice $device
|
|
elif [[ $choice == "$_PartShowTree" ]]; then
|
|
msgbox "$_PrepShowDev" "\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT "$device")\n"
|
|
partition $device
|
|
elif [[ $choice == "$_PartWipe" ]]; then
|
|
yesno "$_PartWipe" "$_PartBody1 $device $_PartWipeBody2" && wipe -Ifrev $device
|
|
partition $device
|
|
else
|
|
# if auto_partition fails we need to empty the partition variables
|
|
auto_partition $device || { ROOT_PART=""; BOOT_PART=""; BOOT_DEVICE=""; return 1; }
|
|
fi
|
|
}
|
|
|
|
decr_count()
|
|
{
|
|
# remove a partition from the dialog list and decrement the number partitions left
|
|
(( $# == 1 )) || return 1
|
|
|
|
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
|
|
}
|
|
|
|
enable_swap()
|
|
{
|
|
if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
|
|
fallocate -l $SWAP_SIZE $1 2>$ERR
|
|
echeck "fallocate -l $SWAP_SIZE $1"
|
|
chmod 600 $1 2>$ERR
|
|
echeck "chmod 600 $1"
|
|
fi
|
|
mkswap $1 >/dev/null 2>$ERR
|
|
echeck "mkswap $1"
|
|
swapon $1 >/dev/null 2>$ERR
|
|
echeck "swapon $1"
|
|
return 0
|
|
}
|
|
|
|
device_tree()
|
|
{
|
|
tput civis
|
|
local msg
|
|
if [[ $IGNORE_DEV != "" ]]; then
|
|
msg="$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT |
|
|
awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/ {print $0}')"
|
|
else
|
|
msg="$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT |
|
|
awk '/disk|part|lvm|crypt|NAME/ {print $0}')"
|
|
fi
|
|
msgbox "$_PrepShowDev" "$msg"
|
|
}
|
|
|
|
select_device()
|
|
{
|
|
local dev
|
|
local msg
|
|
if [[ $1 == 'boot' ]]; then
|
|
msg="$_DevSelTitle for bootloader\n"
|
|
else
|
|
umount_dir $MNT
|
|
fi
|
|
|
|
if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
|
|
DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
|
|
msg="\nOnly one device available$([[ $1 == 'boot' ]] && printf " for bootloader"):"
|
|
infobox "$_DevSelTitle" "$msg $DEVICE\n" 1
|
|
elif (( DEV_COUNT > 1 )); then
|
|
tput civis
|
|
if ! DEVICE="$(menubox "$_DevSelTitle " "${msg}$_DevSelBody" 0 0 0 $SYS_DEVS)"; then
|
|
return 1
|
|
fi
|
|
elif [[ $DEV_COUNT -lt 1 && $1 != 'boot' ]]; then
|
|
msgbox "$_ErrTitle" "\nNo available devices to use.\n$_Exit"; die 1
|
|
fi
|
|
|
|
# if the device selected was for bootloader, set the BOOT_DEVICE
|
|
[[ $1 == 'boot' ]] && BOOT_DEVICE="$DEVICE"
|
|
|
|
return 0
|
|
}
|
|
|
|
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
|
|
|
|
if [[ $(mount) == *"$mount"* ]]; then
|
|
infobox "$_MntTitle" "$_MntSucc\n$msg\n" 1; decr_count "$part"
|
|
else
|
|
infobox "$_MntTitle" "$_MntFail\n$msg\n" 1; return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
check_cryptlvm()
|
|
{
|
|
local dev=""
|
|
local part="$1"
|
|
local devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
|
|
|
|
# Identify if $part is "crypt" (LUKS on LVM, or LUKS alone)
|
|
if [[ $(lsblk -lno TYPE "$part") =~ 'crypt' ]]; then
|
|
LUKS=' encrypted'
|
|
LUKS_NAME="${part#/dev/mapper/}"
|
|
|
|
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=' logical volume'
|
|
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
|
|
fi
|
|
done
|
|
|
|
elif [[ $(lsblk -lno TYPE "$part") =~ 'lvm' ]]; then
|
|
LVM=' logical volume'
|
|
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=' encrypted'
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
auto_partition()
|
|
{
|
|
local device="$1"
|
|
local size
|
|
size=$(lsblk -lno SIZE $device |
|
|
awk 'NR == 1 {
|
|
if ($1 ~ "G") {
|
|
sub(/G/, ""); print ($1 * 1000 - 512) / 1000"G"
|
|
} else {
|
|
sub(/M/, ""); print ($1 - 512)"M"
|
|
}
|
|
}')
|
|
|
|
local msg="$_PartBody2"
|
|
local table="gpt"
|
|
local fs="fat32";
|
|
|
|
if [[ $SYS == 'BIOS' ]]; then
|
|
msg="$(sed 's|vfat/fat32|ext4|' <<< "$msg")"
|
|
table="msdos"
|
|
fs="ext4"
|
|
fi
|
|
|
|
# confirm or bail
|
|
yesno "$_PrepParts" "$_PartBody1 $device $msg ($size)$_PartBody3" || return 0
|
|
infobox "$_PrepParts" "\nRemoving existing partitions on $device and setting partition table to $table\n" 1
|
|
swapoff -a # in case the device was previously used for swap
|
|
|
|
local dev_info
|
|
dev_info="$(parted -s $device print)"
|
|
|
|
# walk the partitions on the device in reverse order and delete them
|
|
# shellcheck disable=2013
|
|
for i in $(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r); do
|
|
parted -s $device rm $i >/dev/null 2>&1
|
|
done
|
|
|
|
if [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]]; then
|
|
parted -s $device mklabel $table >/dev/null 2>&1
|
|
fi
|
|
|
|
infobox "$_PrepParts" "\nCreating a 512M $fs boot partition.\n" 1
|
|
if [[ $SYS == "BIOS" ]]; then
|
|
parted -s $device mkpart primary $fs 1MiB 513MiB >/dev/null 2>&1
|
|
else
|
|
parted -s $device mkpart ESP $fs 1MiB 513MiB >/dev/null 2>&1
|
|
fi
|
|
|
|
sleep 0.1
|
|
BOOT_DEVICE="$device"
|
|
BOOT_PART=$(lsblk -lno NAME,TYPE $device | awk 'NR == 2 {print "/dev/"$1}')
|
|
|
|
if [[ $SYS == "BIOS" ]]; then
|
|
mkfs.ext4 -q $BOOT_PART >/dev/null 2>&1
|
|
else
|
|
mkfs.vfat -F32 $BOOT_PART >/dev/null 2>&1
|
|
fi
|
|
|
|
infobox "$_PrepParts" "\nCreating a $size ext4 root partition.\n" 0
|
|
parted -s $device mkpart primary ext4 513MiB 100% >/dev/null 2>&1
|
|
sleep 0.1
|
|
ROOT_PART=$(lsblk -lno NAME,TYPE $device | awk 'NR == 3 {print "/dev/"$1}')
|
|
mkfs.ext4 -q $ROOT_PART >/dev/null 2>&1
|
|
|
|
tput civis; sleep 0.5
|
|
msgbox "$_PrepParts" "\nAuto partitioning complete.\n\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $device)"
|
|
}
|
|
|
|
mount_partition()
|
|
{
|
|
local part="$1"
|
|
local mountp="${MNT}$2"
|
|
local fs="$(lsblk -lno FSTYPE $part)"
|
|
|
|
mkdir -p "$mountp"
|
|
|
|
if [[ ${FS_OPTS[$fs]} != "" && $part != "$BOOT_PART" ]] && select_mount_opts "$part" "$fs"; then
|
|
mount -o $MNT_OPTS $part "$mountp" 2>$ERR
|
|
echeck "mount -o $MNT_OPTS $part $mountp"
|
|
else
|
|
mount $part "$mountp" 2>$ERR
|
|
echeck "mount $part $mountp"
|
|
fi
|
|
|
|
confirm_mount $part "$mountp" || return 1
|
|
check_cryptlvm "$part"
|
|
|
|
return 0
|
|
}
|
|
|
|
mount_boot_part()
|
|
{
|
|
if ! mount_partition "$BOOT_PART" "${BMNTS[$SYS-$BOOTLDR]}"; then
|
|
src /usr/share/archlabs/installer/lib/boot.sh
|
|
return 1
|
|
else
|
|
SEPERATE_BOOT=true
|
|
fi
|
|
}
|
|
|
|
find_partitions()
|
|
{
|
|
local str="$1"
|
|
local err=''
|
|
|
|
# string of partitions as /TYPE/PART SIZE
|
|
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
|
|
}')"
|
|
else
|
|
PARTS="$(lsblk -lno TYPE,NAME,SIZE |
|
|
awk "/$str/"' {
|
|
sub(/^part/, "/dev/")
|
|
sub(/^lvm|^crypt/, "/dev/mapper/")
|
|
print $1$2 " " $3
|
|
}')"
|
|
fi
|
|
|
|
# number of partitions total
|
|
COUNT=$(wc -l <<< "$PARTS")
|
|
|
|
# ensure we have enough partitions for the system and action type
|
|
case $str in
|
|
'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" ;;
|
|
esac
|
|
|
|
# if there aren't enough partitions show the error message
|
|
if [[ $err ]]; then
|
|
msgbox "$_ErrTitle" "$err"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|