#!/bin/sh
#
# A simple script to remove old kernel files/modules.
# Brought to you by yours truly Juan RP in the Public Domain.
#
: ${progname:=$(basename $0)}

case "$(xbps-uhelper arch)" in
    aarch64*) KIMAGE="vmlinux";;
    *) KIMAGE="vmlinuz";;
esac

usage()
{
	cat <<_EOF
Usage: $progname <target> [<version>]

Targets:
 list			Lists old installed kernels.
 rm <version...|all>	Remove kernel <version> or all old kernels.

Example:
	$ $progname list
	$ $progname rm 2.6.39.2
_EOF
	exit 1
}

list_kernels()
{
	local k kpkg installed kver _f

	for k in /boot/$KIMAGE-*; do
		_f=$(basename $k)
		kver=$(echo ${_f}|sed -e 's|-rc|rc|')
		installed=$(xbps-query -o "$k" 2>/dev/null)
		[ -n "$installed" ] && continue
		kpkg="$(xbps-uhelper getpkgversion ${_f} 2>/dev/null)"
		[ "$(uname -r)" = "$kpkg" ] && continue
		[ -n "$kpkg" ] && echo "$kpkg"
	done
}

run_hooks()
{
	local dir="$1"
	local kver="$2"
	local d

	for d in /etc/kernel.d/${dir}/*; do
		[ ! -x "$d" ] && continue
		echo "Running ${dir} kernel hook: $(basename $d)..."
		$d kernel $kver
	done
}

remove_kernel()
{
	local rmkver="$1"
	local installed f kfile

	if [ ! -f /boot/$KIMAGE-${rmkver} -a ! -d /lib/modules/${rmkver} ]; then
		echo "Kernel ${rmkver} not installed."
		exit 0
	fi

	installed=$(xbps-uhelper version "linux${rmkver%*.*}" 2>/dev/null)
	if [ -n "$installed" -a "$installed" = "$rmkver" ]; then
		echo "Kernel $rmkver is currently installed."
		exit 0
	fi

	# Execute pre-remove kernel hooks.
	run_hooks pre-remove $rmkver
	# Remove kernel files in /boot.
	for f in config System.map $KIMAGE; do
		kfile="/boot/${f}-${rmkver}"
		[ ! -f "${kfile}" ] && continue
		echo "Removing ${kfile}..."
		rm -f ${kfile}
	done
	# Remove kernel modules
	if [ -d "/lib/modules/${rmkver}" ]; then
		echo "Removing /lib/modules/${rmkver}..."
		rm -rf /lib/modules/${rmkver}
	fi
	# Execute post-remove kernel hooks.
	run_hooks post-remove $rmkver
	# Remove kernel-headers.
	if [ -d /usr/src/kernel-headers-${rmkver} ]; then
		rm -rf /usr/src/kernel-headers-${rmkver}
	fi
	# Remove debugging symbols.
	dfile=/usr/lib/debug/boot/vmlinux-${rmkver}
	if [ -f "${dfile}" ]; then
		echo "Removing ${dfile}..."
		rm -f ${dfile}
	fi
	if [ -d /usr/lib/debug/usr/lib/modules/${rmkver} ]; then
                echo "Removing /usr/lib/debug/usr/lib/modules/${rmkver}..."
                rm -rf /usr/lib/debug/usr/lib/modules/${rmkver}
	fi
}

if [ "$1" = "list" ]; then
	list_kernels
elif [ "$1" = "rm" ]; then
	if [ "$(id -u)" -ne 0 ]; then
		echo "You have to run this script as root!"
		exit 1
	fi

	if [ -z "$2" ]; then
		usage
	elif [ "$2" = "all" ]; then
		kernels=$(list_kernels)
		for k in ${kernels}; do
			echo "Removing kernel $k files ..."
			remove_kernel "$k"
		done
	else
		shift
		for k; do
			echo "Removing kernel $k files ..."
			remove_kernel "$k"
		done
	fi
else
	usage
fi

exit 0
