#!/bin/bash
#
# ##############################################################################
#
# Copyright (C) 2014 Opinsys Oy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##############################################################################
#
# Author: Tuomas Räsänen <tuomasjjrasanen@tjjr.fi>
#

set -eu

on_exit()
{
    local exitval=$?

    set +eu

    if [ -n "${tmpdir}" ]; then
        rm -rf "${tmpdir}"
    fi

    if ${encountered_errors}; then
        exit 1
    fi

    exit ${exitval}
}

usage_error()
{
    echo "error: $1" >&2
    echo "Try '$0 --help' for more information." >&2
    return 1
}

do_prune=false
force_flag=

while [ $# -gt 0 ]; do
    case $1 in
        -h|--help)
            shift
            echo "Usage: $0"
            echo
            echo "Copy /boot from image files to TFTP boot directories."
            echo
            echo "Image file directory defaults to /images but can be set in "
            echo "PUAVO_IMAGE_DIR environment variable."
            echo
            echo "TFTP boot directory defaults to /var/lib/tftpboot/ltsp but can be set in "
            echo "PUAVO_TFTP_BOOT_DIR environment variable."
            echo
            echo "By default, only boot directories, which are older than their corresponding"
            echo "image files, are updated. One can use --force to update all boot directories,"
            echo "regardless of their last modification times."
            echo
            echo "Options:"
            echo "    -h, --help                   print help and exit"
            echo "    --force-copy                 copy all boot directories, regardless of"
            echo "                                 their last modification times"
            echo "    --prune                      remove all orphan boot directories"
            echo
            exit 0
            ;;
        --force-copy)
            shift
            force_flag='--force'
            break
            ;;
        --prune)
            shift
            do_prune=true
            break
            ;;
        --)
            shift
            break
            ;;
        -*)
            usage_error "invalid argument '$1'"
            ;;
        *)
            break
            ;;
    esac
done

if [ $# -ne 0 ]; then
    usage_error "invalid number of arguments ($#), expected 0"
fi

tmpdir=
encountered_errors=false

trap on_exit EXIT

tmpdir=$(mktemp -d)
image_filepaths="${tmpdir}/image_filepaths"
image_dir="${PUAVO_IMAGE_DIR:-/images}"

if [ -e "${image_dir}" ]; then
    # Save the list of image filepaths to a temporary file.
    find "${image_dir}"  \
        -mindepth 1 -maxdepth 1                                      \
        '(' -type f -o -type l ')'                                   \
        -name '*.img' -a ! -name ltsp.img -a ! -name ltsp-backup.img \
      > "${image_filepaths}"
else
    echo > "${image_filepaths}"
fi

while read image_filepath; do
    image_name=$(basename "${image_filepath}" '.img')

    /usr/lib/puavo-ltsp-bootserver/copy-tftpboot ${force_flag} "${image_filepath}" || {
        encountered_errors=true
        echo "W: failed to copy the boot directory of image '${image_name}'" >&2
        continue
    }
done <"${image_filepaths}"

if $do_prune; then
    bootdirs="${tmpdir}/bootdirs"

    if [ -e "${PUAVO_TFTP_BOOT_DIR:-/var/lib/tftpboot/ltsp}" ]; then
        # Save the list of boot directories to a temporary file.
        find "${PUAVO_TFTP_BOOT_DIR:-/var/lib/tftpboot/ltsp}"/  \
            -mindepth 1 -maxdepth 1 -type d >"${bootdirs}"
    else
        echo >"${bootdirs}"
    fi

    while read bootdir; do
        image_name=$(basename "${bootdir}")
        image_filepath="${image_dir}/${image_name}.img"

        if [ ! -e "${image_filepath}" ]; then
            rm -rf "${bootdir}"
        fi
    done <"${bootdirs}"
fi
