#!/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.1"

# 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 --
}

# erases the given package if present and not needed by any other package
erase_rpm_if_uneeded()
{
    local pkg="$1"

    if ! rpm -q "$pkg" > /dev/null; then
	return 0
    fi
    if rpm -e --test "$pkg" > /dev/null 2>&1; then
	echo "$pkg no longer needed, removing"
	rpm -e "$pkg"
    else
	echo "$pkg still needed, keeping"
    fi
}

stop_player() {
    local pidfile="/var/run/raperca.pid"
    local pidfile2="/var/run/php-raperca.pid"
    [ -s "$pidfile" -o -s "$pidfile2" ] || return
    echo "stopping player"
    local pid pid2
    [ -s "$pidfile" ] && pid="$(< "$pidfile")"
    [ -s "$pidfile2" ] && pid2="$(< "$pidfile2")"
    # 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
    [ -n "$pid" ] && kill "$pid"
    [ -n "$pid2" ] && kill "$pid2"
    rm -f "$pidfile" "$pidfile2"
}

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
	# remove openssl098-libs if no longer needed and still present
	erase_rpm_if_uneeded openssl098-libs
	# On systems that use Yaffs2 as the root fs the mtime and
	# atime of directories is not updated, this breaks fontconfig
	# so we need to remove cache files. Here we handle the one for
	# the root system font directory, /usr/share/fonts. Other
	# should be handled per font package. Removing just the cache
	# for that directory greatly speeds up cache update on reboot.
	if grep -q '[[:space:]]/[[:space:]]\+yaffs2[[:space:]]' /proc/mounts; then
	    # the cache name is an MD5 of the directory path so it is fixed
	    rm -f /var/cache/fontconfig/3830d5c3ddfd5cd38a049b759396e72e-*
	fi
	;;
    download)
	clear_logs
	;;
esac

exit 0
