Update install-stormux script.

This commit is contained in:
Storm Dragon
2026-05-11 21:34:43 -04:00
parent 9496559875
commit 9a0a6fef00
+356 -124
View File
@@ -3,7 +3,7 @@
# install-stormux: Interactive Arch Linux installer for Stormux # install-stormux: Interactive Arch Linux installer for Stormux
# Supports UEFI/BIOS, multiple partition layouts, and accessibility-first configuration # Supports UEFI/BIOS, multiple partition layouts, and accessibility-first configuration
set -euo pipefail set -Eeuo pipefail
# Global variables # Global variables
logFile="/tmp/install-stormux.log" logFile="/tmp/install-stormux.log"
@@ -25,6 +25,11 @@ enableSsh="no" # "yes" or "no"
installLinuxGameManager="no" # "yes" or "no" installLinuxGameManager="no" # "yes" or "no"
installAudiogameManager="no" # "yes" or "no" installAudiogameManager="no" # "yes" or "no"
autoLoginUser="" # User to auto-login for desktop environments autoLoginUser="" # User to auto-login for desktop environments
minHomePartitionMiB=1024
errorCount=0
warningCount=0
currentStep="initialization"
cleanupOnError=false
# #
@@ -36,10 +41,12 @@ log() {
} }
log_error() { log_error() {
errorCount=$((errorCount + 1))
echo "ERROR: $*" | tee -a "$logFile" >&2 echo "ERROR: $*" | tee -a "$logFile" >&2
} }
log_warning() { log_warning() {
warningCount=$((warningCount + 1))
echo "WARNING: $*" | tee -a "$logFile" >&2 echo "WARNING: $*" | tee -a "$logFile" >&2
} }
@@ -47,6 +54,22 @@ log_info() {
echo "$*" | tee -a "$logFile" echo "$*" | tee -a "$logFile"
} }
handle_unexpected_failure() {
local exitCode="$1"
if [[ "$exitCode" -eq 0 ]]; then
return 0
fi
log_error "Installation aborted during step: $currentStep (exit code $exitCode)"
if [[ "$cleanupOnError" == true ]]; then
cleanup_and_unmount
fi
exit "$exitCode"
}
# #
# Audio feedback functions # Audio feedback functions
# #
@@ -131,8 +154,24 @@ preflight_checks() {
# #
list_available_disks() { list_available_disks() {
# List disks excluding loop devices, the current root device, and ISO # List disks excluding loop devices and the disk backing the live root filesystem.
lsblk -dno NAME,SIZE,TYPE | grep -E "^[^l].*disk$" | grep -v "$(df / | tail -1 | cut -d' ' -f1 | sed 's|/dev/||;s|[0-9]*$||')" || true local rootSource rootDiskName
rootSource=$(findmnt -n -o SOURCE --target / 2>/dev/null || true)
if [[ "$rootSource" == /dev/* ]]; then
rootDiskName=$(lsblk -no PKNAME "$rootSource" 2>/dev/null | head -n 1 || true)
if [[ -z "$rootDiskName" ]]; then
rootDiskName=$(basename "$rootSource")
rootDiskName=$(echo "$rootDiskName" | sed -E 's/p?[0-9]+$//')
fi
fi
if [[ -n "${rootDiskName:-}" ]]; then
lsblk -dno NAME,SIZE,TYPE | awk -v excludedDisk="$rootDiskName" '$1 != excludedDisk && $3 == "disk"'
else
lsblk -dno NAME,SIZE,TYPE | awk '$3 == "disk"'
fi
} }
select_disk() { select_disk() {
@@ -165,6 +204,55 @@ select_disk() {
done done
} }
get_disk_size_mib() {
local disk="$1"
local diskSizeBytes
diskSizeBytes=$(lsblk -bdno SIZE "$disk" 2>/dev/null | head -n 1 || true)
if [[ -z "$diskSizeBytes" || ! "$diskSizeBytes" =~ ^[0-9]+$ ]]; then
log_error "Could not determine disk size for $disk"
return 1
fi
echo $((diskSizeBytes / 1024 / 1024))
}
validate_home_disk_size() {
local disk="$1"
local diskSizeMiB
diskSizeMiB=$(get_disk_size_mib "$disk") || return 1
if [[ "$diskSizeMiB" -lt "$minHomePartitionMiB" ]]; then
log_warning "Selected home disk $disk is too small (${diskSizeMiB}MiB)"
log_warning "Separate home disk requires at least ${minHomePartitionMiB}MiB"
return 1
fi
return 0
}
select_separate_home_disk() {
while true; do
if ! select_disk homeDisk "Select disk for /home partition:"; then
return 1
fi
if [[ "$homeDisk" == "$targetDisk" ]]; then
log_warning "Home disk must be different from target disk in separate home disk layout"
echo "Please choose a different disk."
continue
fi
if ! validate_home_disk_size "$homeDisk"; then
echo "Please choose a different disk for /home."
continue
fi
return 0
done
}
select_install_target() { select_install_target() {
echo "Select installation target:" echo "Select installation target:"
@@ -262,6 +350,51 @@ select_partition_layout() {
done done
} }
show_partition_plan() {
log ""
log "=== Planned Disk Layout ==="
log "Boot mode: $bootMode"
log "Target disk: $targetDisk"
case "$partitionLayout" in
single)
if [[ "$bootMode" == "uefi" ]]; then
log " ${targetDisk}1 -> EFI (FAT32) mounted at /boot"
log " ${targetDisk}2 -> root (ext4) mounted at /"
else
log " ${targetDisk}1 -> root (ext4, boot flag) mounted at /"
fi
log " /home will be inside root filesystem"
;;
separate_home)
if [[ "$bootMode" == "uefi" ]]; then
log " ${targetDisk}1 -> EFI (FAT32) mounted at /boot"
log " ${targetDisk}2 -> root (ext4) mounted at /"
log " ${targetDisk}3 -> home (ext4) mounted at /home"
else
log " ${targetDisk}1 -> root (ext4, boot flag) mounted at /"
log " ${targetDisk}2 -> home (ext4) mounted at /home"
fi
;;
separate_disk)
if [[ "$bootMode" == "uefi" ]]; then
log " ${targetDisk}1 -> EFI (FAT32) mounted at /boot"
log " ${targetDisk}2 -> root (ext4) mounted at /"
else
log " ${targetDisk}1 -> root (ext4, boot flag) mounted at /"
fi
log "Home disk: $homeDisk"
log " ${homeDisk}1 -> home (ext4) mounted at /home"
;;
esac
if [[ "$partitionLayout" == "separate_disk" ]]; then
log "WARNING: ALL DATA on $targetDisk and $homeDisk will be destroyed."
else
log "WARNING: ALL DATA on $targetDisk will be destroyed."
fi
}
# #
# Partitioning functions # Partitioning functions
# #
@@ -357,6 +490,10 @@ partition_disk_uefi_home_only() {
local disk="$1" local disk="$1"
log_info "Creating home partition on $disk" log_info "Creating home partition on $disk"
if ! validate_home_disk_size "$disk"; then
return 1
fi
# Wipe existing partition table # Wipe existing partition table
wipefs -af "$disk" wipefs -af "$disk"
@@ -450,6 +587,10 @@ partition_disk_bios_home_only() {
local disk="$1" local disk="$1"
log_info "Creating home partition on $disk (BIOS)" log_info "Creating home partition on $disk (BIOS)"
if ! validate_home_disk_size "$disk"; then
return 1
fi
# Wipe existing partition table # Wipe existing partition table
wipefs -af "$disk" wipefs -af "$disk"
@@ -523,12 +664,31 @@ get_partition_device() {
fi fi
} }
get_home_partition_number() {
case "$partitionLayout" in
separate_home)
if [[ "$bootMode" == "uefi" ]]; then
echo 3
else
echo 2
fi
;;
separate_disk)
echo 1
;;
*)
return 1
;;
esac
}
create_filesystems() { create_filesystems() {
log_info "=== Creating Filesystems ===" log_info "=== Creating Filesystems ==="
local rootPart local rootPart
local homePart local homePart
local efiPart local efiPart
local homePartNum
if [[ "$bootMode" == "uefi" ]]; then if [[ "$bootMode" == "uefi" ]]; then
efiPart=$(get_partition_device "$targetDisk" 1) efiPart=$(get_partition_device "$targetDisk" 1)
@@ -545,12 +705,14 @@ create_filesystems() {
case "$partitionLayout" in case "$partitionLayout" in
separate_home) separate_home)
homePart=$(get_partition_device "$targetDisk" 3) homePartNum=$(get_home_partition_number) || return 1
homePart=$(get_partition_device "$targetDisk" "$homePartNum")
log_info "Creating home filesystem on $homePart" log_info "Creating home filesystem on $homePart"
mkfs.ext4 -F "$homePart" mkfs.ext4 -F "$homePart"
;; ;;
separate_disk) separate_disk)
homePart=$(get_partition_device "$homeDisk" 1) homePartNum=$(get_home_partition_number) || return 1
homePart=$(get_partition_device "$homeDisk" "$homePartNum")
log_info "Creating home filesystem on $homePart" log_info "Creating home filesystem on $homePart"
mkfs.ext4 -F "$homePart" mkfs.ext4 -F "$homePart"
;; ;;
@@ -565,6 +727,7 @@ mount_filesystems() {
local rootPart local rootPart
local homePart local homePart
local efiPart local efiPart
local homePartNum
# Determine partition devices # Determine partition devices
if [[ "$bootMode" == "uefi" ]]; then if [[ "$bootMode" == "uefi" ]]; then
@@ -589,13 +752,15 @@ mount_filesystems() {
# Mount home if separate # Mount home if separate
case "$partitionLayout" in case "$partitionLayout" in
separate_home) separate_home)
homePart=$(get_partition_device "$targetDisk" 3) homePartNum=$(get_home_partition_number) || return 1
homePart=$(get_partition_device "$targetDisk" "$homePartNum")
log_info "Mounting home partition $homePart to $mountPoint/home" log_info "Mounting home partition $homePart to $mountPoint/home"
mkdir -p "$mountPoint/home" mkdir -p "$mountPoint/home"
mount "$homePart" "$mountPoint/home" mount "$homePart" "$mountPoint/home"
;; ;;
separate_disk) separate_disk)
homePart=$(get_partition_device "$homeDisk" 1) homePartNum=$(get_home_partition_number) || return 1
homePart=$(get_partition_device "$homeDisk" "$homePartNum")
log_info "Mounting home partition $homePart to $mountPoint/home" log_info "Mounting home partition $homePart to $mountPoint/home"
mkdir -p "$mountPoint/home" mkdir -p "$mountPoint/home"
mount "$homePart" "$mountPoint/home" mount "$homePart" "$mountPoint/home"
@@ -709,6 +874,32 @@ get_root_partition_device() {
fi fi
} }
resolve_parent_disk_device() {
local currentDevice="$1"
local maxHops=20
local hop=0
while [[ "$hop" -lt "$maxHops" ]]; do
local currentType parentName
currentType=$(lsblk -no TYPE "$currentDevice" 2>/dev/null | head -n 1 || true)
if [[ "$currentType" == "disk" ]]; then
echo "$currentDevice"
return 0
fi
parentName=$(lsblk -no PKNAME "$currentDevice" 2>/dev/null | head -n 1 || true)
if [[ -z "$parentName" ]]; then
return 1
fi
currentDevice="/dev/$parentName"
hop=$((hop + 1))
done
return 1
}
get_bios_install_disk() { get_bios_install_disk() {
if [[ "$useExistingMount" == false ]]; then if [[ "$useExistingMount" == false ]]; then
echo "$targetDisk" echo "$targetDisk"
@@ -727,28 +918,15 @@ get_bios_install_disk() {
return 1 return 1
fi fi
local rootType local installDisk
rootType=$(lsblk -no TYPE "$rootPart" 2>/dev/null | head -n 1 || true) installDisk=$(resolve_parent_disk_device "$rootPart" || true)
if [[ -z "$installDisk" ]]; then
log_error "Could not determine BIOS install disk from root source: $rootPart"
log_error "Set root on a block device that resolves to a physical disk (for example /dev/sdX or /dev/nvmeXnY)"
return 1
fi
case "$rootType" in echo "$installDisk"
part)
local parentDisk
parentDisk=$(lsblk -no PKNAME "$rootPart" 2>/dev/null | head -n 1 || true)
if [[ -z "$parentDisk" ]]; then
log_error "Could not determine parent disk for root partition: $rootPart"
return 1
fi
echo "/dev/$parentDisk"
;;
disk)
echo "$rootPart"
;;
*)
log_error "Unsupported root device type for BIOS bootloader installation: $rootType"
log_error "Automatic disk detection only supports direct partition or disk root devices"
return 1
;;
esac
} }
# #
@@ -1107,10 +1285,18 @@ install_base_system() {
return 1 return 1
fi fi
# Generate fstab # Generate or preserve fstab
log_info "Generating fstab" if [[ "$useExistingMount" == true ]]; then
log_info "Generating fstab" if [[ -s "$mountPoint/etc/fstab" ]]; then
genfstab -U "$mountPoint" > "$mountPoint/etc/fstab" log_info "Manual mount mode: preserving existing /etc/fstab"
else
log_warning "Manual mount mode: /etc/fstab not found, generating one"
genfstab -U "$mountPoint" > "$mountPoint/etc/fstab"
fi
else
log_info "Generating fstab"
genfstab -U "$mountPoint" > "$mountPoint/etc/fstab"
fi
log_info "Base system installed" log_info "Base system installed"
log_info "Base system installation complete" log_info "Base system installation complete"
@@ -1324,7 +1510,9 @@ echo \"Created user: $username\"
stormuxPackagesCmd=" stormuxPackagesCmd="
# Install Stormux-specific packages # Install Stormux-specific packages
echo \"Installing Stormux-specific packages: ${stormuxPackages[*]}\" echo \"Installing Stormux-specific packages: ${stormuxPackages[*]}\"
pacman -Sy --noconfirm --needed ${stormuxPackages[*]} 2>/dev/null || true if ! pacman -Sy --noconfirm --needed ${stormuxPackages[*]}; then
echo \"WARNING: Failed to install one or more Stormux-specific packages: ${stormuxPackages[*]}\"
fi
" "
fi fi
@@ -1337,14 +1525,18 @@ echo \"Installing packages for audiogame-manager...\"
# Critical packages: wine, p7zip, curl, dialog, sox, cabextract, unzip, xz # Critical packages: wine, p7zip, curl, dialog, sox, cabextract, unzip, xz
# Optional packages: winetricks, wine_gecko, wine-mono, translate-shell, gawk, perl, xclip, xdotool # Optional packages: winetricks, wine_gecko, wine-mono, translate-shell, gawk, perl, xclip, xdotool
# Audio packages: gst-plugins for multimedia support # Audio packages: gst-plugins for multimedia support
pacman -S --noconfirm --needed wine winetricks wine_gecko wine-mono p7zip curl dialog sox cabextract unzip xz translate-shell gawk perl xclip xdotool gst-plugins-bad gst-plugins-good gst-plugins-ugly gst-libav 2>/dev/null || true if ! pacman -S --noconfirm --needed wine winetricks wine_gecko wine-mono p7zip curl dialog sox cabextract unzip xz translate-shell gawk perl xclip xdotool gst-plugins-bad gst-plugins-good gst-plugins-ugly gst-libav; then
echo \"WARNING: Failed to install one or more audiogame-manager dependencies\"
fi
" "
fi fi
if [[ "$installLinuxGameManager" == "yes" ]]; then if [[ "$installLinuxGameManager" == "yes" ]]; then
gameManagerPackagesCmd+=" gameManagerPackagesCmd+="
# Install packages for linux-game-manager # Install packages for linux-game-manager
echo \"Installing packages for linux-game-manager...\" echo \"Installing packages for linux-game-manager...\"
pacman -S --noconfirm --needed p7zip curl dialog yad unzip 2>/dev/null || true if ! pacman -S --noconfirm --needed p7zip curl dialog yad unzip; then
echo \"WARNING: Failed to install one or more linux-game-manager dependencies\"
fi
" "
fi fi
@@ -1352,12 +1544,14 @@ pacman -S --noconfirm --needed p7zip curl dialog yad unzip 2>/dev/null || true
local pipewireConfigCmd="" local pipewireConfigCmd=""
for username in "${userNames[@]}"; do for username in "${userNames[@]}"; do
pipewireConfigCmd+=" pipewireConfigCmd+="
sudo -u $(printf %q "$username") /usr/share/fenrirscreenreader/tools/configure_pipewire.sh 2>/dev/null || true if ! sudo -u $(printf %q "$username") /usr/share/fenrirscreenreader/tools/configure_pipewire.sh; then
echo \"WARNING: Failed to configure PipeWire for user $(printf %q "$username")\"
fi
" "
done done
# Run configuration in chroot using heredoc (like pi4 script) # Run configuration in chroot using heredoc (like pi4 script)
if ! arch-chroot "$mountPoint" /bin/bash <<EOF if ! arch-chroot "$mountPoint" /bin/bash <<EOF 2>&1 | tee -a "$logFile"
set -euo pipefail set -euo pipefail
# Set timezone # Set timezone
@@ -1409,7 +1603,9 @@ echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
chmod 440 /etc/sudoers.d/wheel chmod 440 /etc/sudoers.d/wheel
# Disable systemd-networkd in favor of NetworkManager # Disable systemd-networkd in favor of NetworkManager
systemctl disable systemd-networkd.service systemd-networkd.socket 2>/dev/null || true if ! systemctl disable systemd-networkd.service systemd-networkd.socket; then
echo "WARNING: Could not disable systemd-networkd services (may already be disabled)"
fi
# Enable system services # Enable system services
systemctl enable NetworkManager.service systemctl enable NetworkManager.service
@@ -1419,7 +1615,9 @@ systemctl enable cronie.service
systemctl enable ssh-login-monitor.service systemctl enable ssh-login-monitor.service
# Enable bluetooth if present # Enable bluetooth if present
systemctl enable bluetooth.service 2>/dev/null || true if ! systemctl enable bluetooth.service; then
echo "WARNING: Could not enable bluetooth.service"
fi
# Enable SSH if requested # Enable SSH if requested
if [[ "${enableSsh}" == "yes" ]]; then if [[ "${enableSsh}" == "yes" ]]; then
@@ -1435,9 +1633,11 @@ if [[ "${desktopEnvironment}" == "i3" ]]; then
mkdir -p /home/\$firstUser/git mkdir -p /home/\$firstUser/git
chown \$firstUser:users /home/\$firstUser/git chown \$firstUser:users /home/\$firstUser/git
# Clone I38 to ~/git/I38 # Clone I38 to ~/git/I38
echo "Cloning I38 accessibility configuration..." echo "Cloning I38 accessibility configuration..."
sudo -u \$firstUser git clone https://git.stormux.org/storm/I38 /home/\$firstUser/git/I38 2>/dev/null || true if ! sudo -u \$firstUser git clone https://git.stormux.org/storm/I38 /home/\$firstUser/git/I38; then
echo "WARNING: Failed to clone I38 repository"
fi
# Run I38 setup to generate accessible i3 configuration # Run I38 setup to generate accessible i3 configuration
if [[ -d /home/\$firstUser/git/I38 ]]; then if [[ -d /home/\$firstUser/git/I38 ]]; then
@@ -1447,14 +1647,20 @@ if [[ "${desktopEnvironment}" == "i3" ]]; then
# Ensure xdotool is available for I38 setup # Ensure xdotool is available for I38 setup
if ! command -v xdotool >/dev/null 2>&1; then if ! command -v xdotool >/dev/null 2>&1; then
echo "Installing xdotool for I38..." echo "Installing xdotool for I38..."
pacman -Sy --noconfirm --needed xdotool 2>/dev/null || true if ! pacman -Sy --noconfirm --needed xdotool; then
echo "WARNING: Failed to install xdotool for I38 setup"
fi
fi fi
# Run I38 setup scripts as the user # Run I38 setup scripts as the user
# -x generates xinitrc and xprofile # -x generates xinitrc and xprofile
# Main script generates i3 config with accessibility features # Main script generates i3 config with accessibility features
sudo -u \$firstUser ./i38.sh -x || true if ! sudo -u \$firstUser ./i38.sh -x; then
sudo -u \$firstUser ./i38.sh || true echo "WARNING: I38 xinit/xprofile setup reported an error"
fi
if ! sudo -u \$firstUser ./i38.sh; then
echo "WARNING: I38 main setup reported an error"
fi
cd - > /dev/null || exit 1 cd - > /dev/null || exit 1
fi fi
@@ -1498,16 +1704,24 @@ export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1
export SAL_USE_VCLPLUGIN=gtk3 export SAL_USE_VCLPLUGIN=gtk3
# Enable Orca screen reader # Enable Orca screen reader
gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled true 2>/dev/null || true if ! gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled true; then
gsettings set org.mate.interface accessibility true 2>/dev/null || true echo "WARNING: Could not set GNOME screen-reader-enabled flag"
gsettings set org.mate.applications-at-visual startup true 2>/dev/null || true fi
if ! gsettings set org.mate.interface accessibility true; then
echo "WARNING: Could not set MATE accessibility flag"
fi
if ! gsettings set org.mate.applications-at-visual startup true; then
echo "WARNING: Could not set MATE startup applications accessibility flag"
fi
XPROFILE_MATE_EOF XPROFILE_MATE_EOF
chmod 755 /home/\$firstUser/.xprofile chmod 755 /home/\$firstUser/.xprofile
chown \$firstUser:users /home/\$firstUser/.xprofile chown \$firstUser:users /home/\$firstUser/.xprofile
# Configure speech-dispatcher for MATE # Configure speech-dispatcher for MATE
if [[ ! -d /home/\$firstUser/.config/speech-dispatcher ]]; then if [[ ! -d /home/\$firstUser/.config/speech-dispatcher ]]; then
sudo -u \$firstUser spd-conf -n 2>/dev/null || true if ! sudo -u \$firstUser spd-conf -n; then
echo "WARNING: Failed to initialize speech-dispatcher configuration for \$firstUser"
fi
fi fi
fi fi
@@ -1517,8 +1731,12 @@ pacman-key --populate archlinux
# Import Stormux key if present # Import Stormux key if present
if [[ -f /usr/share/pacman/keyrings/stormux.gpg ]]; then if [[ -f /usr/share/pacman/keyrings/stormux.gpg ]]; then
pacman-key --add /usr/share/pacman/keyrings/stormux.gpg 2>/dev/null || true if ! pacman-key --add /usr/share/pacman/keyrings/stormux.gpg; then
pacman-key --lsign-key 52ADA49000F1FF0456F8AEEFB4CDE1CD56EF8E82 2>/dev/null || true echo "WARNING: Could not add Stormux signing key to pacman keyring"
fi
if ! pacman-key --lsign-key 52ADA49000F1FF0456F8AEEFB4CDE1CD56EF8E82; then
echo "WARNING: Could not locally sign Stormux pacman key"
fi
fi fi
# Install Stormux-specific packages (built dynamically before chroot) # Install Stormux-specific packages (built dynamically before chroot)
@@ -1532,7 +1750,9 @@ systemctl --global enable pipewire.service pipewire-pulse.service wireplumber.se
# Configure pipewire for Fenrir screen reader (run as root first) # Configure pipewire for Fenrir screen reader (run as root first)
if [[ -x /usr/share/fenrirscreenreader/tools/configure_pipewire.sh ]]; then if [[ -x /usr/share/fenrirscreenreader/tools/configure_pipewire.sh ]]; then
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh 2>/dev/null || true if ! /usr/share/fenrirscreenreader/tools/configure_pipewire.sh; then
echo "WARNING: Failed to configure PipeWire for root/Fenrir"
fi
fi fi
# Configure pipewire for each user (built dynamically before chroot) # Configure pipewire for each user (built dynamically before chroot)
@@ -1788,6 +2008,7 @@ log_info "=== Stormux Installer Started ==="
log_info "Installation log: $logFile" log_info "Installation log: $logFile"
# Pre-flight checks # Pre-flight checks
currentStep="pre-flight checks"
if ! preflight_checks; then if ! preflight_checks; then
log_error "Pre-flight checks failed" log_error "Pre-flight checks failed"
exit 1 exit 1
@@ -1795,19 +2016,15 @@ fi
# Disk selection # Disk selection
log_info "=== Disk Selection ===" log_info "=== Disk Selection ==="
currentStep="disk selection"
if ! select_install_target; then if ! select_install_target; then
log_error "Target selection cancelled" log_error "Target selection cancelled"
exit 1 exit 1
fi fi
if [[ "$useExistingMount" == false ]]; then if [[ "$useExistingMount" == false ]]; then
if ! confirm_disk_destruction "$targetDisk"; then
log_error "Disk destruction not confirmed"
echo "Installation cancelled."
exit 1
fi
# Partition layout selection # Partition layout selection
currentStep="partition layout selection"
if ! select_partition_layout; then if ! select_partition_layout; then
log_error "Partition layout selection cancelled" log_error "Partition layout selection cancelled"
exit 1 exit 1
@@ -1815,11 +2032,25 @@ if [[ "$useExistingMount" == false ]]; then
# If separate disk layout, select home disk # If separate disk layout, select home disk
if [[ "$partitionLayout" == "separate_disk" ]]; then if [[ "$partitionLayout" == "separate_disk" ]]; then
if ! select_disk homeDisk "Select disk for /home partition:"; then currentStep="home disk selection"
if ! select_separate_home_disk; then
log_error "Home disk selection cancelled" log_error "Home disk selection cancelled"
exit 1 exit 1
fi fi
fi
currentStep="partition plan summary"
show_partition_plan
currentStep="target disk confirmation"
if ! confirm_disk_destruction "$targetDisk"; then
log_error "Disk destruction not confirmed"
echo "Installation cancelled."
exit 1
fi
if [[ "$partitionLayout" == "separate_disk" ]]; then
currentStep="home disk confirmation"
if ! confirm_disk_destruction "$homeDisk"; then if ! confirm_disk_destruction "$homeDisk"; then
log_error "Home disk destruction not confirmed" log_error "Home disk destruction not confirmed"
echo "Installation cancelled." echo "Installation cancelled."
@@ -1827,6 +2058,7 @@ if [[ "$useExistingMount" == false ]]; then
fi fi
fi fi
else else
currentStep="existing mount validation"
if ! validate_existing_mountpoint; then if ! validate_existing_mountpoint; then
log_error "Existing mountpoint validation failed" log_error "Existing mountpoint validation failed"
exit 1 exit 1
@@ -1834,102 +2066,102 @@ else
fi fi
# Gather system information # Gather system information
currentStep="system configuration prompts"
if ! gather_system_info; then if ! gather_system_info; then
log_error "System information gathering failed" log_error "System information gathering failed"
exit 1 exit 1
fi fi
trap 'handle_unexpected_failure "$?"' ERR
if [[ "$useExistingMount" == false ]]; then if [[ "$useExistingMount" == false ]]; then
# Partition disks # Partition disks
if ! partition_disks; then currentStep="disk partitioning"
log_error "Disk partitioning failed" partition_disks
echo "ERROR: Disk partitioning failed"
exit 1
fi
# Create filesystems # Create filesystems
if ! create_filesystems; then currentStep="filesystem creation"
log_error "Filesystem creation failed" create_filesystems
echo "ERROR: Filesystem creation failed"
exit 1
fi
# Mount filesystems # Mount filesystems
if ! mount_filesystems; then cleanupOnError=true
log_error "Filesystem mounting failed" currentStep="filesystem mounting"
echo "ERROR: Filesystem mounting failed" mount_filesystems
exit 1
fi
else else
cleanupOnError=true
log_info "Skipping partitioning, filesystem creation, and mounting (using existing $mountPoint)" log_info "Skipping partitioning, filesystem creation, and mounting (using existing $mountPoint)"
fi fi
# Install base system # Install base system
if ! install_base_system; then currentStep="base system installation"
log_error "Base system installation failed" install_base_system
cleanup_and_unmount
exit 1
fi
# Install audio configurations # Install audio configurations
if ! install_audio_configs; then currentStep="audio configuration"
log_error "Audio configuration failed" install_audio_configs
cleanup_and_unmount
exit 1
fi
# Install SSH login monitor files (script + service) # Install SSH login monitor files (script + service)
if ! install_ssh_login_monitor; then currentStep="ssh login monitor installation"
log_error "SSH login monitor installation failed" install_ssh_login_monitor
cleanup_and_unmount
exit 1
fi
# Configure system # Configure system
if ! configure_system; then currentStep="chroot system configuration"
log_error "System configuration failed" configure_system
cleanup_and_unmount
exit 1
fi
# Install bootloader # Install bootloader
if ! install_bootloader; then currentStep="bootloader installation"
log_error "Bootloader installation failed" install_bootloader
cleanup_and_unmount
exit 1
fi
# Install game managers # Install game managers
if ! install_game_managers; then currentStep="game manager installation"
log_warning "Game manager installation had issues (non-fatal)" install_game_managers
fi
# Cleanup and unmount # Cleanup and unmount
currentStep="cleanup"
cleanup_and_unmount cleanup_and_unmount
cleanupOnError=false
# Success message summaryWarningCount=$(grep -c '^WARNING:' "$logFile" 2>/dev/null || true)
log_info "=== Stormux Installer Completed Successfully ===" summaryErrorCount=$(grep -c '^ERROR:' "$logFile" 2>/dev/null || true)
log ""
log "╔════════════════════════════════════════════╗"
log "║ Installation Complete Successfully! ║"
log "╚════════════════════════════════════════════╝"
log ""
log "Next steps:"
log " 1. Remove the installation media"
log " 2. Reboot your system"
log " 3. Log in with one of your user accounts: ${userNames[*]}"
if [[ "$desktopEnvironment" == "i3" ]]; then log ""
log " 4. Your i3 desktop is configured with I38 for accessibility" log "=== Installation Summary ==="
log " - I38 source is available in ~/git/I38 for customization" log " Errors: ${summaryErrorCount:-0}"
log " - Press Alt+Shift+F1 for I38 help after login" log " Warnings: ${summaryWarningCount:-0}"
log " Log file: $logFile"
log ""
if [[ "$errorCount" -gt 0 ]]; then
log_warning "Installation completed with ${summaryErrorCount:-$errorCount} error(s)."
log_warning "Review the installation log before rebooting: $logFile"
finalExitCode=1
else
# Success message
log_info "=== Stormux Installer Completed Successfully ==="
log ""
log "╔════════════════════════════════════════════╗"
log "║ Installation Complete Successfully! ║"
log "╚════════════════════════════════════════════╝"
log ""
log "Next steps:"
log " 1. Remove the installation media"
log " 2. Reboot your system"
log " 3. Log in with one of your user accounts: ${userNames[*]}"
if [[ "$desktopEnvironment" == "i3" ]]; then
log " 4. Your i3 desktop is configured with I38 for accessibility"
log " - I38 source is available in ~/git/I38 for customization"
log " - Press Alt+Shift+F1 for I38 help after login"
fi
log ""
log "Installation log saved to: $logFile"
log ""
# Play success sound
play_success_sound
finalExitCode=0
fi fi
log ""
log "Installation log saved to: $logFile"
log ""
# Play success sound
play_success_sound
read -rp "Press Enter to exit..." read -rp "Press Enter to exit..."
exit "$finalExitCode"