#!/usr/bin/env bash
#
# Logic
# ─────
#   • LXC guest ........... scan host bind-mounts
#   • Host / VM ........... scan host CIFS + bindfs
#       └─ if Docker running, also scan every container’s fuse.mapfs mounts
#
#   Any mount that shows no entry (or times out) is flagged.  All problems
#   are gathered and, if at least one exists, pushed to Telegram via Apprise.
#
# Requirements
# ────────────
#   sudo apt install apprise               # or pip install apprise
#   Export APPRISE_URL with your Telegram URL  *OR*
#   put it in /etc/apprise.yml  (see: https://github.com/caronc/apprise)
#
# Exit-codes
#   0  all good
#   1  problem(s) found  – message sent
# ────────────────────────────────────────────────────────────────────────────


# /etc/systemd/system/mount-check.service
# [Unit]
# Description=Check CIFS and bindfs mounts (skip inside LXC)

# [Service]
# Type=oneshot
# ExecStart=/usr/local/sbin/check-mount-contents.sh

# /etc/systemd/system/mount-check.timer
# [Unit]
# Description=Run mount check every 10 min

# [Timer]
# OnBootSec=2min
# OnUnitActiveSec=10min

# [Install]
# WantedBy=timers.target



set -euo pipefail

# ─────────────── tweakables ───────────────
TIMEOUT=3
HOST_FSTYPES="cifs,fuse.bindfs"
CTR_FSTYPES="fuse.mapfs"
APPRISE_CFG="tgram://5862752875:AAHo7tPSIhUIAtGhHLqRmsokpPMQ__K4clU/-1001730456573"                # leave empty to use $APPRISE_URL or /etc/apprise.yml
# ──────────────────────────────────────────

warn() { printf '\e[31mWARNING\e[0m: %s\n' "$*" >&2; problems+=("$*"); }

non_empty () {                # $1 mount-point → 0 if at least one entry
    timeout "${TIMEOUT}s" bash -O nullglob -O dotglob -c '
        files=("'"$1"'/"*")
        (( ${#files[@]} ))
    ' &>/dev/null
}

alive_cifs () { timeout "${TIMEOUT}s" stat -f "$1" &>/dev/null; }

problems=()                    # collected warnings (for Telegram body)

#############################################################################
# 1. LXC branch
#############################################################################
if [[ $(systemd-detect-virt --container 2>/dev/null || true) == "lxc" ]]; then
    mapfile -t binds < <(
        findmnt -rn -o TARGET,OPTIONS \
        | awk '$2 ~ /(^|,)bind(,|$)/ {print $1}' \
        | grep -Ev '^/(dev|proc|sys|run)(/|$)'
    )
    for mp in "${binds[@]}"; do
        non_empty "$mp" || warn "LXC: bind mount \"$mp\" empty or hung"
    done
else
#############################################################################
# 2. Host / full VM
#############################################################################
    # 2-a  host CIFS & bindfs
    mapfile -t host_tab < <(findmnt -rn -t "$HOST_FSTYPES" -o TARGET,FSTYPE)
    for entry in "${host_tab[@]}"; do
        mp=${entry%% *}; fstype=${entry##* }
        case $fstype in
            cifs)        alive_cifs "$mp" || warn "Host CIFS \"$mp\" unreachable" ;;
            fuse.bindfs) non_empty  "$mp" || warn "Host bindfs \"$mp\" empty"      ;;
        esac
    done

    # 2-b  each running Docker container’s fuse.mapfs mounts
    if command -v docker &>/dev/null && docker ps -q | grep -q .; then
        while read -r cid cname; do
            mapfile -t ctr_mps < <(
                docker exec "$cid" \
                    awk '/ (fuse\.mapfs) / {print $2}' /proc/self/mounts 2>/dev/null
            )
            for mp in "${ctr_mps[@]}"; do
                docker exec "$cid" sh -c \
                  "timeout ${TIMEOUT}s bash -O nullglob -O dotglob -c 'files=(\"$mp\"/*); (( \${#files[@]} ))'" \
                  &>/dev/null \
                || warn "Container \"$cname\": mapfs \"$mp\" empty or hung"
            done
        done < <(docker ps --format '{{.ID}} {{.Names}}')
    fi
fi

#############################################################################
# 3. Notify (if needed) & exit
#############################################################################
if ((${#problems[@]})); then
    # Compose single Telegram message
    body="Mount-check alert on $(hostname -s):\n$(printf '• %s\n' "${problems[@]}")"
    if command -v apprise &>/dev/null; then
        if [[ -n $APPRISE_CFG ]]; then
            apprise -c "$APPRISE_CFG" -b "$body" || warn "Apprise failed"
        else
            apprise -b "$body"         || warn "Apprise failed"
        fi
    else
        warn "Apprise not found – unable to send Telegram alert"
    fi
    exit 1
fi
exit 0