#!/bin/bash

# Root level functions requiring password for mx-snapshot

cleanup() {
    pkill mksquashfs
    if [[ -x /usr/sbin/installed-to-live ]]; then
        /usr/sbin/installed-to-live cleanup
    else
        /usr/bin/installed-to-live cleanup
    fi
}

cleanup_overlay() {
    local app_name overlay_base lower_dir
    app_name=$1
    [[ -z "$app_name" ]] && exit 2
    [[ "$app_name" =~ ^[A-Za-z0-9._-]+$ ]] || exit 2
    # Reject path-traversal: ".." would let overlay_base escape /run.
    [[ "$app_name" == *..* || "$app_name" == .* ]] && exit 2
    overlay_base="/run/${app_name}/bind-root-overlay"
    lower_dir="${overlay_base}/lower"
    local overlay_root="${overlay_base}/root"

    mountpoint -q "$overlay_root" && umount --recursive "$overlay_root"
    mountpoint -q "$lower_dir" && umount --recursive "$lower_dir"
    [[ -L "$overlay_base" ]] && exit 3
    [[ -d "$overlay_base" && "$overlay_base" == /run/*/bind-root-overlay ]] && rm -rf "$overlay_base"
}

copy_log() {
    local app src
    for app in iso-snapshot-cli mx-snapshot; do
        src="/tmp/${app}.log"
        # /tmp is world-writable: only copy an actual regular file, never a
        # symlink, so the source cannot be redirected at a root-owned file.
        [[ -f "$src" && ! -L "$src" ]] || continue
        [[ -f /var/log/${app}.log ]] && mv /var/log/${app}.log /var/log/${app}.log.old
        # -P (no-dereference): if the file is swapped for a symlink after the
        # check (TOCTOU), copy the link itself instead of leaking its target.
        cp -P -- "$src" "/var/log/${app}.log"
        break
    done
}

datetime_log() {
    date +"%Y%m%d_%H%M" > /etc/snapshot_created
}

kill_mksquashfs() {
    pkill mksquashfs
}

drop_caches() {
    echo 1 > /proc/sys/vm/drop_caches
}

chown_conf() {
    local uid user home app file real

    # Determine the calling (non-root) user reliably. pkexec exports
    # PKEXEC_UID; fall back to logname for non-pkexec invocations.
    if [[ -n "$PKEXEC_UID" ]]; then
        uid="$PKEXEC_UID"
    else
        uid=$(id -u "$(logname)" 2>/dev/null)
    fi
    [[ "$uid" =~ ^[0-9]+$ ]] || exit 2
    # Never operate on behalf of root.
    [[ "$uid" -eq 0 ]] && exit 2

    user=$(getent passwd "$uid" | cut -d: -f1)
    home=$(getent passwd "$uid" | cut -d: -f6)
    [[ -z "$user" || -z "$home" || ! -d "$home" ]] && exit 2
    # Resolve the home path too, so the confinement check below still
    # matches when /home (or a parent) is itself a symlink.
    home=$(realpath -e "$home" 2>/dev/null) || exit 2

    for app in iso-snapshot-cli mx-snapshot; do
        file="${home}/.config/MX-Linux/${app}.conf"
        # Must be an existing regular file that is NOT itself a symlink.
        [[ -f "$file" && ! -L "$file" ]] || continue
        # Resolve symlinks in any path component and confine the result
        # to the user's home, defeating symlink-redirection attacks.
        real=$(realpath -e "$file" 2>/dev/null) || continue
        [[ "$real" == "$home"/* ]] || continue
        # -h: do not dereference, guarding against a TOCTOU symlink swap.
        chown -h "${user}:" "$real"
    done
}

main() {
case "$1" in
    chown_conf)
        chown_conf;;
    cleanup)
        cleanup;;
    cleanup_overlay)
        cleanup_overlay "$2";;
    copy_log)
        copy_log;;
    datetime_log)
        datetime_log;;
    kill_mksquashfs)
        kill_mksquashfs;;
    drop_caches)
        drop_caches;;
esac
}

main "$@"
