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

usage() {
	cat <<_EOF
Usage: $progname list [version ...]
       $progname rm all
       $progname rm <version ...>
_EOF
	exit 1
}

list_kernels() {
	running=$(uname -r)
	installed=$(xbps-query -o "/boot/vmlinu[xz]-*" 2>/dev/null | awk '{print $2}')
	for arg; do
		case "$arg" in
			all) pattern="*" ;;
			*) pattern=$arg ;;
		esac
		for k in /boot/vmlinu[xz]-*; do
			case "$installed" in
				*"$k"*) continue ;;
			esac
			kver=${k#*-}
			case "$kver" in
				"$running") ;;
				"*") ;; # /boot isn't mounted -> no vmlinu[xz]
				$pattern) printf "%s\n" "$kver" ;;
			esac
		done
	done | sort -uV
}

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

	for d in /etc/kernel.d/"${dir}"/*; do
		[ -x "$d" ] || continue
		printf "Running %s kernel hook: %s...\n" "$dir" "${d##*/}"
		# Hooks assume they run from the root
		(cd / && ROOTDIR=. "$d" kernel "$kver")
	done
}

remove_kernel() {
	rmkver="$1"

	# Execute pre-remove kernel hooks.
	run_hooks pre-remove "$rmkver"

	for f in \
		/boot/config-"${rmkver}" \
		/boot/System.map-"${rmkver}" \
		/boot/vmlinu[xz]-"${rmkver}" \
		/usr/lib/modules/"${rmkver}"; do
		[ -e "$f" ] || continue
		printf "Removing %s...\n" "$f"
		rm -rf "$f"
	done

	# Execute post-remove kernel hooks.
	run_hooks post-remove "$rmkver"

	for f in \
		/usr/src/kernel-headers-"${rmkver}" \
		/usr/lib/debug/boot/vmlinu[xz]-"${rmkver}" \
		/usr/lib/debug/usr/lib/modules/"${rmkver}" \
		/boot/dtbs/dtbs-"${rmkver}"; do
		[ -e "$f" ] || continue
		printf "Removing %s...\n" "$f"
		rm -rf "$f"
	done
}

case "$1" in
	list) list_kernels "${2:-all}" ;;
	rm)
		[ -z "$2" ] && usage
		if [ "$(id -u)" -ne 0 ]; then
			printf "You have to run this script as root!\n" >&2
			exit 1
		fi
		shift
		for kver in $(list_kernels "$@"); do
			printf "Removing kernel %s...\n" "$kver"
			remove_kernel "$kver"
		done
		;;
	*) usage ;;
esac
exit 0