#!/sbin/openrc-run
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.

extra_commands="save show"

description="Sets the local clock to UTC or Local Time."
description_save="Saves the current time in the BIOS."
description_show="Displays the current time in the BIOS."

: ${clock_adjfile:=${CLOCK_ADJFILE}}
: ${clock_args:=${CLOCK_OPTS}}
: ${clock_systohc:=${CLOCK_SYSTOHC}}
: ${clock:=${CLOCK:-UTC}}
if [ "$clock" = "UTC" ]; then
	utc="UTC"
	utc_cmd="--utc"
else
	utc="Local Time"
	utc_cmd="--localtime"
fi

depend()
{
	provide clock
	if yesno $clock_adjfile; then
		use root
	else
		before *
	fi
	keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
}

setupopts()
{
	case "$(uname -m)" in
		s390*)
			utc="s390"
			;;
		*)
			if [ -e /proc/devices ] && \
				grep -q " cobd$" /proc/devices
			then
				utc="coLinux"
			fi
			;;
	esac

	case "$utc" in
		UTC|Local" "Time);;
		*) unset utc_cmd;;
	esac
}

# hwclock doesn't always return non zero on error
_hwclock()
{
	local err="$(hwclock "$@" 2>&1 >/dev/null)"

	[ -z "$err" ] && return 0
	echo "${err}" >&2
	return 1
}

start()
{
	local retval=0 errstr=""
	setupopts

	if [ -z "$utc_cmd" ]; then
		ewarn "Not setting clock for $utc system"
		return 0
	fi

	ebegin "Setting system clock using the hardware clock [$utc]"
	if [ -e /proc/modules ]; then
		local rtc=
		for rtc in /dev/rtc /dev/rtc[0-9]*; do
			[ -e "$rtc" ] && break
		done
		if [ ! -e "${rtc}" ]; then
			modprobe -q rtc-cmos || modprobe -q rtc || modprobe -q genrtc
		fi
	fi

	# Always set the kernel's time zone.
	_hwclock --systz $utc_cmd $clock_args
	: $(( retval += $? ))

	if [ -e /etc/adjtime ] && yesno $clock_adjfile; then
		_hwclock --adjust $utc_cmd
		: $(( retval += $? ))
	fi

	if yesno ${clock_hctosys:-YES}; then
		_hwclock --hctosys $utc_cmd $clock_args
		: $(( retval += $? ))
	fi

	eend $retval "Failed to set the system clock"

	return 0
}

stop()
{
	# Don't tweak the hardware clock on LiveCD halt.
	[ -n "$CDBOOT" ] && return 0
	yesno ${clock_systohc:-YES} || return 0

	local retval=0 errstr=""
	setupopts

	[ -z "$utc_cmd" ] && return 0

	ebegin "Setting hardware clock using the system clock" "[$utc]"

	if ! yesno $clock_adjfile; then
		# Some implementations don't handle adjustments
		if LC_ALL=C hwclock --help 2>&1 | grep -q "\-\-noadjfile"; then
			utc_cmd="$utc_cmd --noadjfile"
		fi
	fi

	_hwclock --systohc $utc_cmd $clock_args
	retval=$?

	eend $retval "Failed to sync clocks"
}

save()
{
	clock_systohc=yes
	stop
}

show()
{
	setupopts
	hwclock --show "$utc_cmd" $clock_args
}
