#!/bin/bash

# This is a hook for the updater that is run on init, download, update
# and postupdate
# It currently does:
# 1. On 'download' make as much free space as possible available,
#    by removing the old / large logs
# 2. On 'update' stop the player and put the update splash screen
# 3. On 'init' it makes sure the cache directory is not on the root
#    filesystem, if it is it moves it to a new temporary location
# 4. On 'update' and 'postupdate' remove all leftover locale files
#    and doc files on non-devel systems

ACTION="$1"
CALLER_VERSION="$2"
VERSION="1.4.0"

# Must match actual configuration and init script
CACHEDIR=/var/cache/updater
ALTCACHEDIR=/srv/updater-tmp-cache

# Checks if a mount point is mounted, returns 0
# if found, 1 otherwise. The argument must be the mount point, not
# the device.
ismounted()
{
    local match="$1"
    local dev mpt fstype opts dump pass junk
    while read dev mpt fstype opts dump pass junk; do
	[ "$match" = "$mpt" ] && return 0
	[ "$match/" = "$mpt" ] && return 0
	[ "$match" = "$mpt/" ] && return 0
    done < /proc/mounts
    return 1
}

# Moves the cache dir to the alternate cache dir if the cache dir
# sits on the root filesystem.
move_cache_dir() {
    if [ "$(stat -c '%d' /)" != "$(stat -c '%d' "$CACHEDIR")" ]; then
	# cache dir not in root fs
	return
    fi
    if ismounted "$CACHEDIR" ; then
	# already mounted the new cache dir, nothing to do
	return 0
    fi
    echo "setting up alternate cache dir"
    if ! mkdir -p "$ALTCACHEDIR" ; then
	echo "failed creating alternate cache dir"
	return 1
    fi
    if ! mount --bind "$ALTCACHEDIR" "$CACHEDIR"; then
	echo "failed mounting alternate cache dir"
	return 1
    fi
    return 0
}

clear_logs() {
    echo "clearing old / large logs"

    # Remove all log files that are old but not compressed
    find /var/log -type f -name "*.[0-9]" -print0 | \
	xargs -0r rm -f --

    # Remove all compressed log files above 100 K
    find /var/log -type f -size +100k -name "*.gz" -print0 | \
	xargs -0r rm -f --

    # Truncate all log files above 1000 K (logrotate is now using 800K
    # as limit); do not remove as they are anyways open elsewhere
    find /var/log -type f -size +1000k -exec cp /dev/null \{\} \;
}

# Removes all locale language directories that may have been left around by
# mis-packaged RPMs which do not tag locale files with a language tag
remove_locale_files()
{
    find /usr/share/locale/ -mindepth 1 -maxdepth 1 -type d -print0 | \
	xargs -0r rm -rf --
}

# Removes all documentation files (not directories!)
remove_doc_files()
{
    find /usr/share/man/ /usr/share/doc /usr/share/info \
	-type f -print0 | xargs -0r rm -f --
}

stop_player() {
    local pidfile="/var/run/raperca.pid"
    [ -s "$pidfile" ] || return
    echo "stopping player"
    local pid="$(< "$pidfile")"
    # using a stop-nowait against our caller will just show
    # the splash screen immediately, instead of waiting for
    # the watchdog to do it for us a bit later
    /etc/init.d/updater stop-nowait
    kill "$pid"
    rm -f "$pidfile"
}

case "$ACTION" in
    init)
	move_cache_dir
	;;
    update)
	NUM_PKGS="$3"
	# remove left-over locale and doc files (leave doc on devel systems)
	remove_locale_files
	[ -e /usr/include/stdlib.h ] || remove_doc_files
	# Do not do anything else if updating just a few packages
	# (safer if updating only the updater)
	if [ -z "$NUM_PKGS" ] || [ "$NUM_PKGS" -lt 5 ]; then
	    exit 0
	fi
	# Only attempt to stop the player if the caller version
	# is the same as our version
	[ "$CALLER_VERSION" = "$VERSION" ] && stop_player
	;;
    postupdate)
	# remove left-over locale and doc files (leave doc on devel systems)
	remove_locale_files
	[ -e /usr/include/stdlib.h ] || remove_doc_files
	;;
    download)
	clear_logs
	;;
esac

exit 0
