#! /bin/bash -eu

# A simplified RPM version comparison that takes into account knowledge about
# Y- and Z-streams (so it compares versions inside Y-stram or Z-stream if
# the version against which comparison is performed has appropriate versioning
# scheme).
#
# SPDX-License-Identifier: CC0-1.0

# $1 - kernel version to check
# $* - list of kernel versions to check against
check_kver()
{
	local t_major= t_minor= t_patch= t_y= t_z1= t_z2= t_rest=
	local m_major= m_minor= m_patch= m_y= m_z1= m_z2= m_rest=
	local cmp_type=

	#echo "$1" | IFS=.- read -r t_major t_minor t_patch t_y t_z1 t_z2 t_rest
	# "cannot create temp file for here-document: Read-only file system"
	# that's why we can't have nice things.
	t_major=${1%%[.-]*}
	t_rest=${1#${t_major}}
	t_rest=${t_rest#[.-]}
	t_minor=${t_rest%%[.-]*}
	t_rest=${t_rest#${t_minor}}
	t_rest=${t_rest#[.-]}
	t_patch=${t_rest%%[.-]*}
	t_rest=${t_rest#${t_patch}}
	t_rest=${t_rest#[.-]}
	t_y=${t_rest%%[.-]*}
	t_rest=${t_rest#${t_y}}
	t_rest=${t_rest#[.-]}
	t_z1=${t_rest%%[.-]*}
	t_rest=${t_rest#${t_z1}}
	t_rest=${t_rest#[.-]}
	t_z2=${t_rest%%[.-]*}

	# minor/major/patch/y should be numeric
	[ -n "${t_major##*[!0-9]*}" ] || return 1
	[ -n "${t_minor##*[!0-9]*}" ] || return 1
	[ -n "${t_patch##*[!0-9]*}" ] || return 1
	[ -n "${t_y##*[!0-9]*}" ] || return 1
	# reset z1/z2 to zero if non-numeric
	[ -n "${t_z1##*[!0-9]*}" ] || t_z1=0
	[ -n "${t_z2##*[!0-9]*}" ] || t_z2=0

	while [ 1 -lt "$#" ]; do
		cmp_type=upstream

		shift
		m_major=${1%%[.-]*}
		m_rest=${1#${m_major}}
		m_rest=${m_rest#[.-]}
		m_minor=${m_rest%%[.-]*}
		m_rest=${m_rest#${m_minor}}
		m_rest=${m_rest#[.-]}
		m_patch=${m_rest%%[.-]*}
		m_rest=${m_rest#${m_patch}}
		m_rest=${m_rest#[.-]}
		m_y=${m_rest%%[.-]*}
		m_rest=${m_rest#${m_y}}
		m_rest=${m_rest#[.-]}
		m_z1=${m_rest%%[.-]*}
		m_rest=${m_rest#${m_z1}}
		m_rest=${m_rest#[.-]}
		m_z2=${m_rest%%[.-]*}

		# minor/major/patch should be numeric
		[ -n "${m_major##*[!0-9]*}" ] || continue
		[ -n "${m_minor##*[!0-9]*}" ] || continue
		[ -n "${m_patch##*[!0-9]*}" ] || continue
		# reset z1/z2 to zero if non-numeric
		[ -n "${m_y##*[!0-9]*}" ] && cmp_type=y || m_y=0
		[ -n "${m_z1##*[!0-9]*}" ] && cmp_type=z || m_z1=0
		[ -n "${m_z2##*[!0-9]*}" ] && cmp_type=z || m_z2=0

		# Comparing versions
		case "$cmp_type" in
		upstream)
			[ "$t_major" -ge "$m_major" ] || continue
			[ "$t_minor" -ge "$m_minor" ] || continue
			[ "$t_patch" -ge "$m_patch" ] || continue
			return 0
			;;
		y)
			[ "$t_major" -eq "$m_major" ] || continue
			[ "$t_minor" -eq "$m_minor" ] || continue
			[ "$t_patch" -eq "$m_patch" ] || continue
			[ "$t_y" -ge "$m_y" ] || continue
			return 0
			;;
		z)
			[ "$t_major" -eq "$m_major" ] || continue
			[ "$t_minor" -eq "$m_minor" ] || continue
			[ "$t_patch" -eq "$m_patch" ] || continue
			[ "$t_y" -eq "$m_y" ] || continue
			[ "$t_z1" -ge "$m_z1" ] || continue
			[ "$t_z2" -ge "$m_z2" ] || continue
			return 0
			;;
		esac
	done

	return 1
}

check_kver "$@"
