#!/bin/bash

. ${TOOLKIT}-functions.sh

####################################
#	kernels clenaup
####################################

here=$(pwd)
cd /boot

fmt="  %-38s %s\n"

getconfirm machine.kernel_pinning && {
	echo "  kernels will NOT be upgraded on this machine"
	echo "  (machine.kernel_pinnig=TRUE)"
	exit 0
}


get_latest_kernel()
{
	local match="$1"
	local latest=

	(
	  cd /boot
	  ls vmlinuz-* 2>/dev/null \
		| sed -e 's/vmlinuz-//' \
		| egrep -- "${match}" | tail -1
	)
}

get_latest_release()
{
	if [ "X$1" != "X" ]
	then
		echo $1 | sed -e 's/-[a-zA-Z].*//'
	else
		echo "NONE"
	fi
}

get_kernel_package()
{
	local kernel=${1:-}
	local installed=
	local pkg=

	[ "X$kernel" = "X" ] && {
		echo "NOT_INSTALLED"
		return 0
	}

	for pkg in $(dpkg -l | grep '^ii  linux-image' \
		  | sed -e 's/^ii  //' -e 's/ .*//')
	do
		installed=$(dpkg -L $pkg | fgrep "/boot/vmlinuz-$kernel" \
			| sed -e 's/.*vmlinuz-//') || :
		[ "X$installed" != "X" ] && {
			echo "$pkg"
			break
		}
	done
	[ "X$installed" = "X" ] && echo "NOT_INSTALLED"
	return 0
}



# is the main class a server or a workstation/laptop?
#
is_server=true
class_requested ws	&& is_server=false
class_requested laptop	&& is_server=false

model=$(jtconf common.model)

update_val=$(jtconf machine.kernel_update 2>/dev/null || :)
echo

if getconfirm machine.kernel_update
then
	echo "  check for kernel upgrades (machine.kernel_update=$update_val)"
	update=true
	dummy=
else
	echo "  do NOT apply kernel upgrades (machine.kernel_update=$update_val)"
	update=false
	dummy="echo (dummy) "
fi

running_release=$(uname -r)
running_package=$(get_kernel_package $running_release)

wanted_kernel=$(jtconf machine.default_kernel)
override=$(jtconf machine.kernel)

echo
printf "$fmt" "running kernel:" "$running_release ($running_package)"
printf "$fmt" "default kernel:" "$wanted_kernel"

if [ "X$override" != "X" -a "X$override" != "X$wanted_kernel" ]
then
	printf "$fmt" "FORCED by config:" "$override"
	wanted_kernel=$override
	match=$override
else
	match=$(jtconf machine.kernel_match 2>/dev/null || :)
	match=${match:-$wanted_kernel}
fi

latest_kernel=$(get_latest_kernel "$match")
latest_release=$(get_latest_release "$latest_kernel")
latest_package=$(get_kernel_package $latest_kernel)

printf "$fmt" "search matching:" "$match"
printf "$fmt" "last matching installed:" "$latest_kernel ($latest_release, $latest_package)"

# safeguard
#
[ "$latest_package" = "NOT_INSTALLED" -a "$wanted_kernel" != "NONE" ] && {
	echo "  warning: no running matching kernel found?"
	echo "           installing safeguard kernel linux-image-$wanted_kernel"
	$dummy install_pkgs "linux-image-$wanted_kernel linux-headers-$wanted_kernel"
	$update && {
		latest_kernel=$(get_latest_kernel "$match")
		latest_release=$(get_latest_release "$latest_kernel")
		latest_package=$(get_kernel_package $latest_kernel)
		printf "$fmt" "last installed (now):" "$latest_kernel ($latest_release, $latest_package)"
	}
}


# scans kernel related installed packages, and mark to remove unneded ones
#
pkgs=$(COLUMNS=300 dpkg -l \
	| egrep "linux-image-|linux-.*modules-|linux-headers-" \
	| grep '^.i  ' \
	| sed -e 's/^....//' -e 's/ .*//'
) || :

bare_wanted_kernel=$(echo "$wanted_kernel" | sed -e 's/-[a-zA-Z].*//')

:> remove.tmp

for pkg in $pkgs
do
	release=$(echo "$pkg" | sed \
		-e 's/linux-image-//' \
		-e 's/linux-.*modules-//' \
		-e 's/linux-headers-//'
	)
	[ "$release" = "$running_release" ] && {
		printf "$fmt" "- $pkg:" "not removing (running)"
		continue
	}
	[ "$release" = "$wanted_kernel" ] && {
		printf "$fmt" "- $pkg:" "not removing (needed)"
		continue
	}
	echo "$release" | fgrep -q "$bare_wanted_kernel" && {
		printf "$fmt" "- $pkg:" "not removing (related to $bare_wanted_kernel)"
		continue
	}

	printf "$fmt" "- $pkg:" "REMOVE"
	echo "$pkg" >>remove.tmp
done
[ -s remove.tmp ] && {
	remove=$(cat remove.tmp)
	$dummy remove_pkgs $remove
}
rm -f remove.tmp


[ "$latest_kernel" != "" -a "$latest_kernel" != $(uname -r) ] && {
	echo -e "\nKernel updated, the computer must be rebooted.\n" > $here/need_reboot
}




# updates symlinks to latest kernel stuffs in /boot
# (idea from mandriva distros)

# this func will speed up things ..
update_link()
{
	local file=$1
	local last=$(ls ${file}-* 2>/dev/null | grep -v '\.bak$' | tail -1) || return 1
	local link=$(ls -ls $file 2>/dev/null | sed -e 's/.* //') || return 1
	[ "$link" != "$last" ] && {
		echo "  updating link $file -> $last"
		rm -f $file
		ln -s $last $file || return $?
	}
	return 0
}

cd /boot
update_link vmlinuz	|| exit $?
update_link System.map	|| exit $?
update_link initrd.img	|| exit $?
update_link abi		|| exit $?
update_link config	|| exit $?


# Xen DomU
#
# this is the only place, for now, where we can detect
# if we are in a Xen DomU or not

domU=false

service_requested arch-xen && {
	[ $latest_release = "NONE" ] && {
		echo "  Xen DomU detected"
		domU=true
	}
}

dir=/lib/tls
if $domU
then
	# fix /lib/tls (nonegseg) stuff
	#
	[ -d $dir ] && {
		echo "  xen DomU: disable dir $dir (libc nonegseg problem) ..."
		mv $dir $dir.disabled || exit $?
	}
else
	[ -d $dir.disabled -a ! -d $dir ] && {
		echo "  not yet xen DomU: restore dir $dir"
		mv $dir.disabled $dir || exit $?
	}
fi



# grub fixes
#
if [ -d /boot/grub ]
then
	[ "$(which update-grub)" != "" ] && {
		cd $here

		if $is_server
		then
			export temp_grub_opts=$(jtconf grub.options_srv 2>/dev/null)
			echo "  using server grub options: $temp_grub_opts"
		else
			export temp_grub_opts=$(jtconf grub.options_ws 2>/dev/null)
			echo "  using workstation grub options: $temp_grub_opts"
		fi


		# grub defaults will be installed only if not already done by
		# arch-alix module (platform specific)
		#
		service_requested arch-alix || {
			file="grub-default-$DISTRIB_FULL_ID"
			[ -f $file ] && {
				installfile $file /etc/default/grub root:root 644 || exit $?
			}
		}


		file="/usr/lib/grub/grub-mkconfig_lib"
		[ -f $file ] && {
		    getconfirm grub.use_search || {
			grep -q 'echo "search' $file && {
				fname=$(basename $file)
				echo "  patching $file to NOT USE 'search'"
				sed -e 's/echo "search.*/echo "  [ku] patch: search disabled" >\&2/' $file >$fname
				installfile $fname /usr/lib/grub/ root:root 644 || exit $?
			}
		    }
		}

		file="/etc/grub.d/10_linux"
		[ -f $file ] && {
		    fname=$(basename $file)
		    grep -q '"single ' $file && {
			echo "  patching $file recovery entry (single -> init=/bin/bash)"
			sed -e 's#"single #"init=/bin/bash #' $file >$fname
			installfile $fname $file root:root 755 || exit $?
		    }
		}

		$SOMETHING_CHANGED && update-grub

	} # which update-grub
else
	echo "  dir /boot/grub not exists: this system uses an EFI boot?"
fi


exit 0
