#!/bin/sh

# Copyright (c) 2015 SpinetiX
#
# media-mount hook for raperca
#
# This script takes care of installing the necessary bind
# mounts and doing misc related maintenance when storage
# is added or removed by media-mount.
#
# Input environment variables:
#
# MNTDIR: the directory where the filesystem was mounted
# MNTDEV: the device that was mounted
# MNTRW: set to non-empty if filesystem mounted read-write; only valid on "add"
#

# The mount point for content
CONTENT_MPT=/srv/raperca/content

# The mount point for streaming capture
CAPTURE_MPT=/srv/raperca/capture

# The sentinel file used for triggering font rescans on internal storage mount
FONTSENTINEL=/var/run/raperca/font-sentinel

# Load general helpers and config
. /etc/media-mount/media-mount-functions
load_sysconfig

add_bind_mount() {
    local entry
    local src="$1"
    local dst="$2"

    if ! mktmpfstab; then
	echo "ERROR: cannot create temporary fstab while adding mounts for $MNTDEV"
	return 1
    fi

    entry="$src $dst none bind,noauto 0 0"
    echo "INFO: adding '$entry' to fstab"
    echo "$entry" >> "$TMPFSTAB"
    if [ $? -eq 0 ]; then
	savetmpfstab
    else
	rmtmpfstab
	return 1
    fi
}

mount_dir() {
    local src="$1"
    local dst="$2"
    local msg="$3"

    if is_any_mounted_at "$dst"; then
	echo "WARN: USB storage configured as internal but one already mounted as $msg"
	return 0
    fi

    # NOTE: the mount command gets confused when the source of a bind mount is
    # a mount point itself; the mount command cannot disambiguate between its
    # argument being a device (i.e. mount source) or a mount point (i.e. mount
    # target); to overcome this we append "/." to the bind source (which makes
    # makes an equivalent path to the same directory) as this lifts the
    # ambiguity when passing "$MNTDIR" as argument to mount.
    [ -z "$src" ] && src=.

    add_bind_mount "${MNTDIR%/}"/"$src" "$dst"
    if [ $? -ne 0 ]; then
	echo "ERROR: failed adding bind mount for $msg"
	return 1
    fi

    # For the content mount point we need to trigger a font rescan;
    # a 1 second sleep is also necessary to ensure that mtime and
    # current time differ when new content is loaded (just after mount)
    if [ "$dst" = "$CONTENT_MPT" ]; then
	[ -f "$FONTSENTINEL" ] && touch "$FONTSENTINEL" && sleep 1
    fi

    mount "$dst"
    if [ $? -ne 0 ]; then
	echo "ERROR: failed mounting new bind mount"
	return 1
    fi
    return 0
}

# Removes all dav_fs tmp files from all the directories passed as
# arguments. dav_fs from Apache httpd 2.4 uses ".davfs.tmp" as prefix
# while SpinetiX patch for Apache httpd 2.2 uses ".davtmp."
clean_dav_tmp() {
    find "$@" -type f \( -name ".davfs.tmp*" -o -name ".davtmp.*" \) -print0 | \
	xargs -0r rm -f --
}

add() {
    local added= # set to non-empty if mount point added

    # NOTE: INTERNAL_USB_STORAGE refers to mounting the storage for raperca
    [ "$INTERNAL_USB_STORAGE" == "yes" ] || return 0

    if [ -f "$MNTDIR"/"$MOUNTCONFIGFILE" ]; then
	# new style mount, dedicated subdirectories
	if [ -d "$MNTDIR"/content ]; then
	    [ -n "$MNTRW" ] && clean_dav_tmp "$MNTDIR"/content
	    mount_dir content "$CONTENT_MPT" "content"
	    added=1
	fi
	if [ -d "$MNTDIR"/capture ]; then
	    mount_dir capture "$CAPTURE_MPT" "streaming capture"
	    added=1
	fi
    else
	# old style mount, root dir mounted as content
	if [ -f "$MNTDIR"/updates/repodata/repomd.xml -a ! -f "$MNTDIR"/index.svg ]; then
	    # this is a firmware update source, not content
	    return 0
	fi
	[ -n "$MNTRW" ] && clean_dav_tmp "$MNTDIR"
	mount_dir '' "$CONTENT_MPT" "content"
	added=1
    fi

    [ -n "$MNTRW" -a -n "$added" ] && spxdiskwatch
}

remove() {
    # Triggering a font update is only necessary if the filesystem is mounted
    # as content, but to know that we would need to chase all the bind mounts,
    # so we trigger it regardless; at worst this will generate a dummy
    # font config rescan; "sleep 1" is necessary (see add_content)
    [ -f "$FONTSENTINEL" ] && touch "$FONTSENTINEL" && sleep 1
}

#
# Main
#

case "$1" in
    add)
	add
	;;
    remove)
	remove
	;;
    *)
	;;
esac
