#!/bin/bash
#----------------------------------------------------------------------------
# /tmp/install.sh - install kernel update
#
# Copyright (c) 2001-2025 the eisfair team, team(at)eisfar(dot)org
#
# Creation   : 2008-08-14 tb
# Last Update: 2025-07-06 15:26:15 dv
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#----------------------------------------------------------------------------

. /var/install/include/eislib

variant="pae"
kernel="6.12.62-eisfair-1-PAE"
initrd_name="initrd-${kernel}.gz"
kernel_name="kernel-${kernel}"

klogfile='/var/log/log.kernel-update'

legacy_kernels=\
"3.2.54-  3.2.67-  3.2.71-  3.2.75-  3.2.77-  3.2.79-  3.2.81-  3.2.82-\
 3.2.84-  3.2.85-  3.2.87-  3.16.42- 3.16.44- 3.16.46- 3.16.47- 3.16.50-\
 3.16.52- 3.16.54- 3.16.56- 3.16.57- 3.16.58- 3.16.60- 3.16.62- 3.16.63-\
 3.16.65- 3.16.68- 3.16.69- 3.16.70- 3.16.74- 4.9.196- 4.9.207- 4.9.210-\
 4.9.215- 4.9.218- 4.9.220- 4.9.245-"

num_undo_steps="0"

#-----------------------------------------------------------------------------
# write message to log file
#-----------------------------------------------------------------------------
print_log()
{
    echo "${1}" >>"${klogfile}"
}

#-----------------------------------------------------------------------------
# print message
#-----------------------------------------------------------------------------
print()
{
    local message="${1}"
    echo "${message}"
    print_log "${message}"
}

#-----------------------------------------------------------------------------
# print info message
#-----------------------------------------------------------------------------
print_info()
{
    message="${1}"
    mecho --warn "${message}"
    print_log "${message}"
}

#-----------------------------------------------------------------------------
# print warning message
#-----------------------------------------------------------------------------
print_warning()
{
    message="${1}"
    mecho --warn "${message}"
    print_log "${message}"
}

#-----------------------------------------------------------------------------
# print error message
#-----------------------------------------------------------------------------
print_error()
{
    message="${1}"
    echo "${message}"
    print_log "${message}"
}

#-----------------------------------------------------------------------------
# deactivate a given kernel (move files to /boot)
#-----------------------------------------------------------------------------
activate_kernel()
{
    local kernel_name="${1}"
    local initrd_name="${2}"

    if ! mv "/var/lib/alt-kernel/${kernel_name}" "/boot/${kernel_name}"
    then
        rm -f "/boot/${kernel_name}"
        return 1
    fi

    if ! mv "/var/lib/alt-kernel/${initrd_name}" "/boot/${initrd_name}"
    then
        rm -f "/boot/${kernel_name}"
        rm -f "/boot/${initrd_name}"
        return 1
    fi

    # memorize activation as undo information
    local idx=${num_undo_steps:-0}
    eval 'UNDO_'${idx}'_ACTION'='ACTIVATE'
    eval 'UNDO_'${idx}'_KERNEL_NAME'=${kernel_name}
    eval 'UNDO_'${idx}'_INITRD_NAME'=${initrd_name}
    num_undo_steps=$((${idx} + 1))

    return 0
}

#-----------------------------------------------------------------------------
# deactivate a given kernel (move files to /var/lib/alt-kernel)
#-----------------------------------------------------------------------------
deactivate_kernel()
{
    local kernel_name="${1}"
    local initrd_name="${2}"

    # move kernel and initrd
    if [ -f "/boot/${kernel_name}" ]
    then
        rm -f "/var/lib/alt-kernel/${kernel_name}"
        if ! mv "/boot/${kernel_name}" "/var/lib/alt-kernel/${kernel_name}"
        then
            return 1
        fi
    fi

    if [ -f "/boot/${initrd_name}" ]
    then
        rm -f "/var/lib/alt-kernel/${initrd_name}"
        if ! mv "/boot/${initrd_name}" "/var/lib/alt-kernel/${initrd_name}"
        then
            return 1
        fi
    fi

    # memorize deactivation as undo information
    local idx=${num_undo_steps:-0}
    eval 'UNDO_'${idx}'_ACTION'='DEACTIVATE'
    eval 'UNDO_'${idx}'_KERNEL_NAME'=${kernel_name}
    eval 'UNDO_'${idx}'_INITRD_NAME'=${initrd_name}
    num_undo_steps=$((${idx} + 1))

    return 0
}

#-----------------------------------------------------------------------------
# set kernel as default
#-----------------------------------------------------------------------------
set_as_default()
{
    local kernel_name="${1}"
    local initrd_name="${2}"

    if [ -n "${kernel_name}" ] && [ -n "${initrd_name}" ]
    then
        # memorize activation as undo information
        if [ -L "/boot/kernel" ] && [ -L "/boot/initrd.gz" ]
        then
            local idx=${num_undo_steps:-0}
            eval 'UNDO_'${idx}'_ACTION'='SET_LINK'
            eval 'UNDO_'${idx}'_KERNEL_LINK'="$(basename $(readlink /boot/kernel))"
            eval 'UNDO_'${idx}'_INITRD_LINK'="$(basename $(readlink /boot/initrd.gz))"
            num_undo_steps=$((${idx} + 1))
        fi

        # update default kernel link
        rm -f "/boot/kernel"
        rm -f "/boot/initrd.gz"
        ln -srf "/boot/${kernel_name}" "/boot/kernel"
        ln -srf "/boot/${initrd_name}" "/boot/initrd.gz"
    fi
}

#-----------------------------------------------------------------------------
# in case of an update remove old kernel files
#-----------------------------------------------------------------------------
prepare_for_update()
{
    local kernel_name="${1}"
    local initrd_name="${2}"
    local fix_link=false

    if [ "$(basename $(readlink /boot/kernel))" = "${kernel_name}" ]
    then
        fix_link=true
    fi

    rm -f "/boot/${kernel_name}"
    rm -f "/boot/${initrd_name}"

    # memorize activation as undo information
    local idx=${num_undo_steps:-0}
    eval 'UNDO_'${idx}'_ACTION'='PREPARE_UPDATE'
    eval 'UNDO_'${idx}'_FIX_LINK'=${fix_link}
    num_undo_steps=$((${idx} + 1))

    return 0
}

#-----------------------------------------------------------------------------
# copy all files from boot into a temporary folder
#-----------------------------------------------------------------------------
backup_boot_folder()
{
    local backup_folder="${1}"

    if [ -n "${backup_folder}" ]
    then
        if ! cp -dr /boot/* "${backup_folder}" 2> /dev/null
        then
            rm -rf "${backup_folder}"
            return 1
        fi

        # memorize activation as undo information
        local idx=${num_undo_steps:-0}
        eval 'UNDO_'${idx}'_ACTION'='BACKUP'
        eval 'UNDO_'${idx}'_BACKUP_FOLDER'="${backup_folder}"
        num_undo_steps=$((${idx} + 1))
    fi
}

#-----------------------------------------------------------------------------
# generate config for bootloader
#-----------------------------------------------------------------------------
generate_bootloader_config()
{
    if [ -f /usr/libexec/update-bootloader ]
    then
        # memorize activation as undo information
        local idx=${num_undo_steps:-0}
        eval 'UNDO_'${idx}'_ACTION'='GENERATE_BOOTLOADER'
        num_undo_steps=$((${idx} + 1))

        if ! /usr/libexec/update-bootloader --generate-new
        then
            return 1
        fi
    fi

    return 0
}

#-----------------------------------------------------------------------------
# restore symbolic link to the best kernel found in /boot
#-----------------------------------------------------------------------------
restore_link()
{
    rm -f /boot/kernel
    rm -f /boot/initrd.gz

    local kernels=$(ls /boot/kernel-* | sort -Vr)
    local next_kernel

    for next_kernel in ${kernels}
    do
        local next_version="$(basename ${next_kernel} | sed 's#kernel-##g')"
        local next_initrd="/boot/initrd-${next_version}.gz"
        if [ -f "${next_initrd}" ]
        then
            ln -sr "${next_kernel}" /boot/kernel
            ln -sr "${next_initrd}" /boot/initrd.gz
            break
        fi
    done
}

#-----------------------------------------------------------------------------
# clean up after an error has occurred
#-----------------------------------------------------------------------------
exit_failure()
{
    print_info
    print_info "Some error occurred during installation!"
    print_info "The kernel has been installed but has not been activated!"
    print_info "Please see file '${klogfile}' for further details."
    print_info

    local bootloader_update=false
    local bootloader_generate=false

    # process undo log
    local idx=${num_undo_steps:-0}
    while [ "${idx}" -gt "0" ]
    do
        idx=$((${idx} - 1))

        eval local action='${UNDO_'${idx}'_ACTION}'

        case "${action}" in
            'BACKUP')
                eval local backup_folder='${UNDO_'${idx}'_BACKUP_FOLDER}'
                rm -f /boot/*
                cp -dr ${backup_folder}/* /boot  2> /dev/null
                rm -rf "${backup_folder}"
                bootloader_update=true
                ;;

            'SET_LINK')
                eval local kernel_link='${UNDO_'${idx}'_KERNEL_LINK}'
                eval local initrd_link='${UNDO_'${idx}'_INITRD_LINK}'
                set_as_default "${kernel_link}" "${initrd_link}"
                ;;

            'ACTIVATE')
                eval local kernel_name='${UNDO_'${idx}'_KERNEL_NAME}'
                eval local initrd_name='${UNDO_'${idx}'_INITRD_NAME}'
                deactivate_kernel "${kernel_name}" "${initrd_name}"
                ;;

            'DEACTIVATE')
                eval local kernel_name='${UNDO_'${idx}'_KERNEL_NAME}'
                eval local initrd_name='${UNDO_'${idx}'_INITRD_NAME}'
                activate_kernel "${kernel_name}" "${initrd_name}"
                bootloader_update=true
                ;;

            'PREPARE_UPDATE')
                eval local fix_link='${UNDO_'${idx}'_FIX_LINK}'
                if [ "${fix_link}" = true ]
                then
                    restore_link
                fi
                bootloader_update=true
                bootloader_generate=true
                ;;

            'GENERATE_BOOTLOADER')
                bootloader_update=true
                ;;
        esac
    done

    # finally restore bootloader setup
    if [ -f /usr/libexec/update-bootloader ]
    then
        if [ "${bootloader_update}" = true ]
        then
            if [ "${bootloader_generate}" = true ]
            then
                /usr/libexec/update-bootloader --generate-new
            else
                /usr/libexec/update-bootloader --use-existing
            fi
        fi
    fi

    anykey

    exit 0
}

#-----------------------------------------------------------------------------
# print contents of undo log
#-----------------------------------------------------------------------------
show_undo_history()
{
    # process undo log
    mecho --info "Undo history:"
    local idx=${num_undo_steps:-0}
    while [ "${idx}" -gt "0" ]
    do
        idx=$((${idx} - 1))

        eval local action='${UNDO_'${idx}'_ACTION}'

        case "${action}" in
            'BACKUP')
                eval local backup_folder='${UNDO_'${idx}'_BACKUP_FOLDER}'
                echo "BACKUP"
                echo "   folder = ${backup_folder}"
                ;;

            'SET_LINK')
                eval local kernel_link='${UNDO_'${idx}'_KERNEL_LINK}'
                eval local initrd_link='${UNDO_'${idx}'_INITRD_LINK}'
                echo "SET_LINK"
                echo "   previous kernel = ${kernel_link}"
                echo "   previous initrd = ${initrd_link}"
                ;;

            'ACTIVATE')
                eval local kernel_name='${UNDO_'${idx}'_KERNEL_NAME}'
                eval local initrd_name='${UNDO_'${idx}'_INITRD_NAME}'
                echo "ACTIVATE"
                echo "   kernel = ${kernel_name}"
                echo "   initrd = ${initrd_name}"
                ;;

            'DEACTIVATE')
                eval local kernel_name='${UNDO_'${idx}'_KERNEL_NAME}'
                eval local initrd_name='${UNDO_'${idx}'_INITRD_NAME}'
                echo "DEACTIVATE"
                echo "   kernel = ${kernel_name}"
                echo "   initrd = ${initrd_name}"
                ;;

            'PREPARE_UPDATE')
                eval local fix_link='${UNDO_'${idx}'_FIX_LINK}'
                echo "PREPARE_UPDATE"
                echo "   fix_link = ${fix_link}"
                ;;

            'GENERATE_BOOTLOADER')
                echo "GENERATE_BOOTLOADER"
                ;;

            *)
                echo "UNKNOWN"
                echo "   action = ${action}"
                ;;
        esac
    done
}

#-----------------------------------------------------------------------------
# create initrd image
#-----------------------------------------------------------------------------
create_initrd()
{
    local output_file="${1}"

    rm -f "${output_file}"

    # create initramfs without ucode
    if dracut -q --force "${output_file}" "${kernel}"
    then
        print_log "Creation of initrd succeeded!"
        return 0
    else
        print_error "Creation of initrd failed!"
        return 1
    fi
}

#-----------------------------------------------------------------------------
# check if space is sufficient to activate new kernel
#-----------------------------------------------------------------------------
check_available_space_in_boot()
{
    local available_space=0
    if [ -n "$(df /boot | grep ' /boot$')" ]
    then
        set -- $(df /boot | grep ' /boot$')
        available_space="${4}"
    else
        print_log "No mounted boot partition found!"
        set -- $(df / | grep ' /$')
        available_space="${4}"
    fi

    local kernel_size=$(du "/var/lib/alt-kernel/${kernel_name}" | awk '{print $1}')
    local initrd_size=$(du "/var/lib/alt-kernel/${initrd_name}" | awk '{print $1}')

    local needed_space=$(expr ${kernel_size:-0} + ${initrd_size:-0})

    print_log "Available space in /boot: ${available_space} 1K blocks"
    print_log "Required space in /boot: ${needed_space} 1K blocks"

    if [ "${needed_space:-0}" -gt "${available_space:-0}" ]
    then
        # insufficient space
        return 1
    fi

    return 0
}

#-----------------------------------------------------------------------------
# extract local version from a kernel image
#-----------------------------------------------------------------------------
lookup_local_version()
{
    local local_version=$(strings "${1}"                |
                  grep -E "^[0-9]+\.[0-9]+\.[0-9]+-.* .*" |
                  head -1                               |
                  cut -d' ' -f1)
    echo "${local_version}"
}

#-----------------------------------------------------------------------------
# expand name of kernel and initrd to localversion for 'kernel'
#-----------------------------------------------------------------------------
rename_and_harmonize_default_kernel()
{
    local local_version=$(lookup_local_version "/boot/kernel")
    local short_version=$(echo "${local_version}" | sed 's#eisfair-1-##g')

    # if versioned kernel exists, prefer default kernel over
    # versioned (fallback) one
    if [ -f "/boot/kernel-${local_version}" ]
    then
        rm -f "/boot/kernel-${local_version}"
        rm -f "/boot/initrd-${local_version}.gz"
    fi

    if [ -f "/boot/kernel-${short_version}" ]
    then
        rm -f "/boot/kernel-${short_version}"
        rm -f "/boot/initrd-${short_version}.gz"
    fi

    if ! mv "/boot/kernel" "/boot/kernel-${local_version}" ||
       ! mv "/boot/initrd.gz" "/boot/initrd-${local_version}.gz"
    then
        print_error "Failed to move kernel to kernel-${local_version}!"
        return 1
    fi

    if ! ln -sr "/boot/kernel-${local_version}" "/boot/kernel"
    then
        print_error "Failed to create link to kernel-${local_version}!"
        return 1
    fi

    return 0
}

#-----------------------------------------------------------------------------
# expand name of kernel and initrd to localversion for 'old-kernel'
#-----------------------------------------------------------------------------
rename_and_harmonize_old_kernel()
{
    local local_version=$(lookup_local_version "/boot/old-kernel")
    local short_version=$(echo "${local_version}" | sed 's#eisfair-1-##g')

    # convert short versions to long version
    if [ "${local_version}" != "${short_version}" ]
    then
        if [ -f "/boot/kernel-${short_version}" ]
        then
            mv "/boot/kernel-${short_version}" "/boot/kernel-${local_version}"
        fi
        if [ -f "/boot/initrd-${short_version}.gz" ]
        then
            mv "/boot/initrd-${short_version}.gz" "/boot/initrd-${local_version}.gz"
        fi
    fi

    # if versioned kernel exists, prefer versioned (fallback) kernel over
    # old kernel
    if [ ! -f "/boot/kernel-${local_version}" ] ||
       [ ! -f "/boot/initrd-${local_version}.gz" ]
    then
        rm -f "/boot/kernel-${local_version}"
        rm -f "/boot/initrd-${local_version}.gz"

        if ! mv "/boot/old-kernel" "/boot/kernel-${local_version}" ||
           ! mv "/boot/old-initrd.gz" "/boot/initrd-${local_version}.gz"
        then
            print_error "Failed to move old-kernel to kernel-${local_version}!"
            return 1
        fi
    else
        rm -f "/boot/old-kernel"
        rm -f "/boot/old-initrd.gz"
    fi

    return 0
}

#-----------------------------------------------------------------------------
# expand name of kernel and initrd to localversion for already versioned kernels
#-----------------------------------------------------------------------------
rename_and_harmonize()
{
    local kernel="${1}"
    local local_version=$(lookup_local_version "${kernel}")
    local short_version=$(echo "${local_version}" | sed 's#eisfair-1-##g')

    # convert short versions to long version
    if [ "${local_version}" != "${short_version}" ]
    then
        if [ -f "/boot/kernel-${short_version}" ] &&
           [ ! -f "/boot/kernel-${local_version}" ]
        then
            mv "/boot/kernel-${short_version}" "/boot/kernel-${local_version}"
        else
            rm -f "/boot/kernel-${short_version}"
        fi

        if [ -f "/boot/initrd-${short_version}.gz" ] &&
           [ ! -f "/boot/initrd-${local_version}.gz" ]
        then
            mv "/boot/initrd-${short_version}.gz" "/boot/initrd-${local_version}.gz"
        else
            rm -f "/boot/initrd-${short_version}.gz"
        fi
    fi

    return 0
}

#-----------------------------------------------------------------------------
# convert naming layout of files in boot
#-----------------------------------------------------------------------------
convert_boot_layout()
{
    if [ -f "/boot/kernel" ] && [ -f "/boot/initrd.gz" ]
    then
        if ! rename_and_harmonize_default_kernel
        then
            return 1
        fi
    else
        print_error "Missing default boot kernel!"
        return 1
    fi

    if [ -f "/boot/old-kernel" ] && [ -f "/boot/old-initrd.gz" ]
    then
        if ! rename_and_harmonize_old_kernel
        then
            return 1
        fi
    fi

    local kernels=$(ls /boot/kernel-* 2> /dev/null)
    local kernel

    for kernel in ${kernels}
    do
        rename_and_harmonize "${kernel}"
    done

    return 0
}

#-----------------------------------------------------------------------------
# check if kernel is in legacy kernel list
#-----------------------------------------------------------------------------
is_legacy_kernel()
{
    local kernel="${1}"
    local filter=$(echo "^(${legacy_kernels})" |
        sed -e 's#  # #g' -e 's#\.#\\\.#g' -e 's#-#-.*#g' -e 's# #)|(#g')

    echo "${kernel}" | grep -E -q "${filter}"
    return "$?"
}

#-----------------------------------------------------------------------------
# lookup oldest kernel version that is not running
#-----------------------------------------------------------------------------
lookup_oldest_kernel()
{
    local running_kernel="$(uname -r)"
    local kernels=$(ls /boot/kernel-* 2> /dev/null |
                    sed 's#/boot/kernel-##g'       |
                    sort -V)
    local kernel
    for kernel in ${kernels}
    do
        if [ "${kernel}" != "${running_kernel}" ]
        then
            if [ -f "/boot/initrd-${kernel}.gz" ]
            then
                echo "${kernel}"
                return 0
            fi
        fi
    done
}

#-----------------------------------------------------------------------------
# lookup oldest kernel version that is not running and in legacy kernel list
#-----------------------------------------------------------------------------
lookup_oldest_legacy_kernel()
{
    local running_kernel="$(uname -r)"
    local kernels=$(ls /boot/kernel-* 2> /dev/null |
                    sed 's#/boot/kernel-##g' |
                    sort -V)
    local kernel
    for kernel in ${kernels}
    do
        if [ "${kernel}" != "${running_kernel}" ]    &&
           [ -f "/boot/initrd-${kernel}.gz" ] &&
           is_legacy_kernel "${kernel}"
        then
            echo "${kernel}"
            return 0
        fi
    done
}

#-----------------------------------------------------------------------------
# count number of active kernels
#-----------------------------------------------------------------------------
get_num_active_kernels()
{
    local kernels=$(ls /boot/kernel-* 2> /dev/null |
                    sed 's#/boot/kernel-##g'       |
                    sort -V)
    local kernel
    local count=0
    for kernel in ${kernels}
    do
        if [ -f "/boot/initrd-${kernel}.gz" ]
        then
            count=$((${count} + 1))
        fi
    done

    echo "${count}"
}

#-----------------------------------------------------------------------------
# cleanup files belongig to a given kernel (only used for legacy kernels)
#-----------------------------------------------------------------------------
cleanup_kernel()
{
    local cleanup_kernel_name="${1}"
    local cleanup_kernel_initrd="${2}"

    # belasse alte Kernel auf Holgers System
    if [ -f /boot/dev-system ]
    then
        return 0
    fi

    local local_version=$(lookup_local_version /var/lib/alt-kernel/${cleanup_kernel_name})
    local short_version=$(echo ${local_version} | cut -d'-' -f1)

    print "Cleaning up kernel ${local_version} ..."
    rm -f "/var/lib/alt-kernel/${cleanup_kernel_name}"
    rm -f "/var/lib/alt-kernel/${cleanup_kernel_initrd}"
    rm -f "/System.map-${local_version}"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/dot-config"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/dot-config-nonsmp"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/Module.symvers-nonsmp"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/dot-config-pae"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/Module.symvers-pae"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/dot-config-smp"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/Module.symvers-smp"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/dot-config-virt"
    rm -f "/usr/src/linux-${short_version}-eisfair-1/Module.symvers-virt"

    rm -rf "/lib/modules/${local_version}"

    if [ -d "/usr/src/linux-${short_version}-eisfair-1" ]
    then
        rmdir --ignore-fail-on-non-empty "/usr/src/linux-${short_version}-eisfair-1"
    fi
}

#-----------------------------------------------------------------------------
# patch uninstall kernel routines to deal with relative links
#-----------------------------------------------------------------------------
patch_kernel_uninstall_scripts()
{
    local files=$(ls /var/install/deinstall/linux-kernel-*)
    local file
    for file in $files
    do
        sed -i 's#"\$(readlink /boot/kernel)" == "/boot/\${kernel_name}"#"$(basename $(readlink /boot/kernel))" == "${kernel_name}"#g' ${file}
        sed -i 's#ln -s "\${next_kernel}"#ln -sr "${next_kernel}"#g' ${file}
        sed -i 's#ln -s "\${next_initrd}"#ln -sr "${next_initrd}"#g' ${file}
    done
}

#-----------------------------------------------------------------------------
# show requirment to reboot the computer
#-----------------------------------------------------------------------------
show_reboot_notice()
{
    print_warning
    print_warning "Note:"
    print_warning "A reboot is required to make the changes take effect."
    print_warning
}

#-----------------------------------------------------------------------------
# show warning, if a realtek card is in use
#-----------------------------------------------------------------------------
show_realtek_warning()
{
    if lsmod | grep -E -q "^r8168 "
    then
        local result=$(eisman check "realtek-6.12.62-eisfair-1-${variant}")
        if [ "${result}" = "not-installed" ]
        then
            print_warning
            print_warning "Warning:"
            print_warning "You are using a r8168 realtek network card."
            print_warning "The driver required for this card no longer is part of the"
            print_warning "kernel package. Please install the addon package:"
            print_warning
            print_warning "  realtek-6.12.62-eisfair-1-${variant}"
            print_warning
            print_warning "or verify, that the included r8169 driver works for your"
            print_warning "hardware as well."
            print_warning
        fi
    fi
}

#-----------------------------------------------------------------------------
# main program
#-----------------------------------------------------------------------------
main()
{
    # do not append messages to log file
    rm -f "${klogfile}"

    print_log "-----------------------------------------------------------"
    print_log "Running install.sh of ${kernel} version 3.8.0"
    print_log "-----------------------------------------------------------"

    # update and verify module dependecies
    /sbin/depmod -ae -F "/System.map-${kernel}" "${kernel}"

    print "Creating initramfs ..."
    if ! create_initrd "/var/lib/alt-kernel/${initrd_name}"
    then
        # leave inactive kernel config
        exit_failure
    fi

    # check boot layout and convert if required
    if [ ! -L "/boot/kernel" ]
    then
        print "Old boot layout found. Converting ..."
        backup_folder=$(/bin/mktemp -d -t boot_backup.XXXXXXXXXX)

        if ! backup_boot_folder "${backup_folder}"
        then
            print_error "Failed to copy backup data!"
            exit_failure
        fi

        if ! convert_boot_layout
        then
            exit_failure
        fi
    fi

    # from here on, only new boot layout exists
    if [ -f "/boot/${initrd_name}" ]
    then
        is_update=true
        print_log "Processing update installation"
    else
        is_update=false
        print_log "Processing new kernel installation"
    fi

    # prepare space in boot
    if [ "${is_update}" = true ]
    then
        # kernel is installed and active just replace files in boot...
        prepare_for_update "${kernel_name}" "${initrd_name}"
        rm -f "/boot/${initrd_name}"
        rm -f "/boot/${kernel_name}"
    fi

    print "Checking for sufficient disk space in /boot ..."
    while ! check_available_space_in_boot
    do
        # there is isufficient disk space. try to find an old kernel
        # that is currently not in use and may be deactivated
        oldest_kernel="$(lookup_oldest_kernel)"
        if [ -z "${oldest_kernel}" ]
        then
            print_error "Insufficient disk space in /boot! Unable to activate the kernel!"
            exit_failure
        fi

        print "Deactivating kernel ${oldest_kernel} ..."
        deactivate_kernel "kernel-${oldest_kernel}" "initrd-${oldest_kernel}.gz"
    done

    # there is sufficient disk space left (now). but somehow we have
    # to get rid of legacy kernels.
    # so, if this is a stable release and the number of active kernels
    # is larger or equal 2, then we try to locate the oldest legacy kernel on
    # the system and prepare it for removal
    if [ "testing" = "stable" ] && [ "$(get_num_active_kernels)" -ge 2 ]
    then
        oldest_kernel="$(lookup_oldest_legacy_kernel)"
        if [ -n "${oldest_kernel}" ]
        then
            print "Deactivating kernel ${oldest_kernel} ..."
            deactivate_kernel "kernel-${oldest_kernel}" "initrd-${oldest_kernel}.gz"
        fi
    fi

    print "Activating kernel ${kernel_name} ..."
    if ! activate_kernel "${kernel_name}" "${initrd_name}"
    then
        exit_failure
    fi
    set_as_default "${kernel_name}" "${initrd_name}"

    print "Creating bootloader configuration ..."
    if ! generate_bootloader_config
    then
        anykey
        exit_failure
    fi

    show_reboot_notice

    # patch uninstall scrips
    patch_kernel_uninstall_scripts

    # use undo log to clean up legacy kernels
    local idx=${num_undo_steps:-0}
    while [ "${idx}" -gt "0" ]
    do
        idx=$((${idx} - 1))

        eval local action='${UNDO_'${idx}'_ACTION}'
        if [ "${action}" = 'DEACTIVATE' ]
        then
            eval local inactive_kernel='${UNDO_'${idx}'_KERNEL_NAME}'
            eval local inactive_initrd='${UNDO_'${idx}'_INITRD_NAME}'

            if is_legacy_kernel "${inactive_kernel:7}"
            then
                cleanup_kernel "${inactive_kernel}" "${inactive_initrd}"
            else
                print_warning
                print_warning "Note:"
                print_warning "Kernel \"${inactive_kernel}\" has been deactivated."
                print_warning "You may uninstall it to remove it permanently."
            fi
        fi
    done

    # check for and show realtek network card warning
    show_realtek_warning

    # for debug purpose only
    # show_undo_history

    # cleanup backup folder
    if [ -n "${backup_folder}" ]
    then
        rm -rf "${backup_folder}"
    fi

    exit 0
}

main "${@}"
