#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS

function display_help() {
    uecho "$scriptname: faire une sauvegarde des fichiers

USAGE
    $scriptname [options]

OPTIONS
    -l  Lister les profils de sauvegarde disponibles.
    -p  Spécifier le profil de sauvegarde à effectuer. Par défaut, toutes les
        sauvegardes sont effectuées.
    -u USER
        Faire le sauvegarde pour l'utilisateur \$USER. Cette option n'est valide
        que pour l'utilisateur root.
    -n  Afficher ce qui doit être fait plutôt que de le faire
    -H  Arrêter la machine après une sauvegarde REUSSIE."
}

action=getargs
profile=
HOMEDIR="$HOME"
fake_maybe=
halt=
lockfile="$TMPDIR/ubackup.lock"
parse_opts "${PRETTYOPTS[@]}" \
    --help '$exit_with display_help' \
    -l,--list action=list \
    -p:,--profile: profile= \
    -u:,--user: user= \
    -n,--fake fake_maybe=echo \
    -H,--halt halt=1 \
    --backup action=backup \
    --lockfile: lockfile= \
    @ args -- "$@" && set -- "${args[@]}" || die "$args"

if [ -n "$user" ]; then
    if is_root; then
        eval "HOMEDIR=~$user"
    else
        die "L'option -u n'est supportée que pour l'utilisateur root"
    fi
fi

function __set_defaults() {
    local HOME="$HOMEDIR"
    set_defaults ubackup
}
__set_defaults

if [ "$action" == "list" ]; then
    echo "${BACKUPS[*]}"
    exit 0
elif [ "$action" == "getargs" ]; then
    # mettre un verrou pour empêcher les opérations de sauvegarde simultanées
    if [ -f "$lockfile" ]; then
        if [ "$(<"$lockfile")" != "$$" ]; then
            die "Une sauvegarde est en cours. Impossible de continuer.
Si ce message est erroné, supprimez manuellement $lockfile"
        fi
    fi

    # n'installer le trap de cleanup qu'après avoir testé qu'une sauvegarde n'était pas en cours.
    autoclean "$lockfile"
    echo "$$" >"$lockfile"

    # arguments pour la sauvegarde
    args=()
    if [ -n "$profile" ]; then
        backups=("$profile")
    else
        backups=("${BACKUPS[@]}")
    fi
    for backup in "${backups[@]}"; do
        if [ "$backup" == "DEFAULT" ]; then
            backup=
        fi
        destdir="${backup:+${backup}_}DESTDIR"; destdir="${!destdir}"
        vgname="${backup:+${backup}_}VGNAME"; vgname="${!vgname}"
        lvname="${backup:+${backup}_}LVNAME"; lvname="${!lvname}"
        configdir="${backup:+${backup}_}CONFIGDIR"; configdir="${!configdir:-$HOMEDIR/etc}"
        includes="${backup:+${backup}_}INCLUDES"; includes="${!includes}"
        excludes="${backup:+${backup}_}EXCLUDES"; excludes="${!excludes}"
        script="${backup:+${backup}_}SCRIPT"; script="${!script}"
        mount="${backup:+${backup}_}MOUNT"; mount="${!mount:-$scriptdir/lib/backup.mount}"
        umount="${backup:+${backup}_}UMOUNT"; umount="${!umount:-$scriptdir/lib/backup.umount}"

        destdir="$(abspath "$destdir" "$configdir")"
        [ -d "$destdir" ] || die "$destdir: répertoire de sauvegarde inexistant"
        configdir="$(abspath "$configdir")"
        [ -n "$includes" ] && includes="$(abspath "$includes" "$configdir")"
        [ -f "$includes" ] || die "$(ppath "$includes"): liste des fichiers à inclure inexistante"
        [ -n "$excludes" ] && excludes="$(abspath "$excludes" "$configdir")"
        [ -n "$script" ] && script="$(abspath "$script" "$configdir")"
        [ -n "$mount" ] && mount="$(abspath "$mount" "$configdir")"
        [ -n "$umount" ] && umount="$(abspath "$umount" "$configdir")"

        args=("${args[@]}" "$backup" "$destdir" "$vgname" "$lvname" "$includes" "$excludes" "$script" "$mount" "$umount")
    done

    # ce script doit tourner en root
    if is_root; then
        action=backup
        set -- "${args[@]}"
    else
        run_as_root --backup --lockfile "$lockfile" ${halt:+-H }${fake_maybe:+-n }"${args[@]}"
    fi
fi
    
if [ "$action" == "backup" ]; then
    no_error=1
    function err_result() {
        shift # STATUS
        eerror "$*"
        no_error=
    }

    while [ -n "$*" ]; do
        backup_name="$1"; shift
        backup_destdir="$1"; shift
        backup_vgname="$1"; shift
        backup_lvname="$1"; shift
        backup_includes="$1"; shift
        backup_excludes="$1"; shift
        backup_script="$1"; shift
        backup_mount="$1"; shift
        backup_umount="$1"; shift

        etitle "${backup_name:-DEFAULT}"
        result="$("$backup_mount" "$backup_destdir" "$backup_vgname" "$backup_lvname")"
        if [ $? -ne 0 ]; then
            err_result $result
        else
            suffix="${backup_name:+-$backup_name}"
            last="last$suffix"

            destdir="$backup_destdir"
            mkdir -p "$destdir"

            # calculer les répertoires de destination et ceux à supprimer
            eval "$("$scriptdir/plbck" -S "$suffix" -e "$destdir")"
        
            # sauvegarder
            etitle -s "Sauvegarde dans $CURRENT${PREVIOUS:+ depuis $PREVIOUS}"
            error=
            if $fake_maybe rsync -aHAX --delete ${PREVIOUS:+--link-dest="$PREVIOUS"} \
                ${backup_excludes:+--delete-excluded --exclude-from="$backup_excludes"} \
                --include-from="$backup_includes" \
                / "$CURRENT"; then
                cwd="$(pwd)"
                cd "$destdir"
                [ -L "$last" ] && $fake_maybe /bin/rm -f "$last"
                $fake_maybe ln -s "$(basename "$CURRENT")" "$last"
                cd "$cwd"
                
                [ -n "$backup_commands" ] && $fake_maybe source "$backup_commands"
            else
                err_result 1 "Une erreur s'est produite pendant la sauvegarde. Arrêt des opération pour $backup_name"
                error=1
            fi
            eend
            
            # supprimer
            if [ -z "$error" -a -n "${DELETES[*]}" ]; then
                etitle -s "Suppression des anciennes versions"
                for delete in "${DELETES[@]}"; do
                    estep "$delete"
                    $fake_maybe rm_maybe -rf "$delete"
                done
                eend
            fi
        
            # démonter le répertoire
            result="$("$backup_umount" $result)"
            if [ $? -ne 0 ]; then
                err_result $result
            fi
        fi
    done

    rm "$lockfile"
    if [ -n "$no_error" -a -n "$halt" ]; then
        $fake_maybe /sbin/shutdown -h now
    fi

else
    die "Action inconnue: $action"
fi
