#!/bin/sh
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2021 Jakub Jirutka <jakub@jirutka.cz>
#---help---
# Usage: radacct-rotate [options]
#
# Compress and later remove old FreeRADIUS' radacct log files with "-YYYYMMDD"
# suffix. This script is provided by the freeradius package in Alpine Linux.
#
# Options:
#   -C FILE  Location of radacct-rotate config file (defaults to
#            /etc/raddb/radacct-rotate.conf).
#
#   -c DAYS  Compress files older than DAYS (overrides option
#            compress_after_days from the config).
#
#   -r DAYS  Remove compressed files older than DAYS (overrides
#            option remove_after_days from the config).
#
#   -d       Run in dry-run mode (only print what would be done).
#
#   -h       Show this message and exit.
#---help---
set -eu

readonly PROGNAME='radacct-rotate'
#                   Y    Y    Y    Y    m    m    d    d
readonly DATE_GLOB='[1-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9]'
readonly HELP_TAG='#---help---'

# Defaults
CONFIG='/etc/raddb/radacct-rotate.conf'
DRY_RUN=false
radacct_dir='/var/log/radius/radacct'
compress_cmd='gzip -9'
compress_ext='.gz'
compress_after_days=2
remove_after_days=180

while getopts ':C:c:dr:h' OPT; do
	case "$OPT" in
		C) CONFIG=$OPTARG;;
		c) COMPRESS_AFTER_DAYS=$OPTARG;;
		d) DRY_RUN=true;;
		r) REMOVE_AFTER_DAYS=$OPTARG;;
		h) sed -n "/^$HELP_TAG/,/^$HELP_TAG/{/^$HELP_TAG/d; s/^# \\?//; p;}" "$0"; exit 0;;
		\?) echo "$PROGNAME: invalid option: -$OPTARG (see '$PROGNAME -h')" >&2; exit 100;;
	esac
done

readonly CONFIG COMPRESS_AFTER_DAYS DRY_RUN REMOVE_AFTER_DAYS

sh -n "$CONFIG" || exit 100
. "$CONFIG"

compress_after_days=${COMPRESS_AFTER_DAYS:-$compress_after_days}
remove_after_days=${REMOVE_AFTER_DAYS:-$remove_after_days}


find_compressible() {
	find "$radacct_dir" -type f -name "*-$DATE_GLOB" -mtime "+$compress_after_days" "$@"
}

find_deletable() {
	find "$radacct_dir" -type f -name "*-${DATE_GLOB}${compress_ext}" -mtime "+$remove_after_days" "$@"
}

check_number() {
	case "$1" in
	''|*[!0-9]*) echo "$PROGNAME: option '$2' must be a number, but given: '$1'" >&2; exit 100;;
	esac
}
check_number "$compress_after_days" 'compress_after_days'
check_number "$remove_after_days" 'remove_after_days'

rc=0
if $DRY_RUN; then
	find_compressible -exec echo $compress_cmd {} \; || rc=111
	find_deletable -exec echo rm {} \; || rc=111
else
	for path in $(find_compressible -print); do
		$compress_cmd "$path" >&2 && touch -ct "${path##*-}0000" "$path".* || rc=111
	done
	find_deletable -exec rm '{}' \; >&2 || rc=111
fi

exit $rc
