#!/usr/bin/env bash # ============================================================================= # tester-sans-sudo.sh — vérifie la logique de sauvegarde, sans clé ni sudo # ----------------------------------------------------------------------------- # Utilise le mode test de sauvegarde-cle-usb (SAUVEGARDE_TEST_DESTINATION) : # un dossier temporaire joue le rôle de la clé. Rien n'est monté, rien n'est # écrit dans /etc. Usage : ./tester-sans-sudo.sh [dossier-de-travail] # ============================================================================= # shellcheck disable=SC2016 # les bash -c reçoivent leurs arguments via $1, voulu set -euo pipefail ICI="$(cd "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" SCRIPT="$ICI/sauvegarde-cle-usb" BASE="${1:-$(mktemp -d)}" TRAVAIL="$BASE/essai-$$" SRC="$TRAVAIL/maison/marie" CLE="$TRAVAIL/cle" CONF="$TRAVAIL/test.conf" export TMPDIR="$TRAVAIL" REUSSIS=0 RATES=0 ok() { echo " OK $*"; REUSSIS=$((REUSSIS + 1)); } rate() { echo " RATÉ $*"; RATES=$((RATES + 1)); } verifier() { local desc="$1"; shift; if "$@"; then ok "$desc"; else rate "$desc"; fi; } ecrire_conf() { # $1 = CORBEILLE_JOURS, $2 = DOSSIER_DESTINATION, $3.. = sources local jours="$1" dest="$2"; shift 2 { echo "UUID=\"TEST\"" echo "UTILISATEUR=\"$(id -un)\"" printf 'SOURCES=('; printf ' "%s"' "$@"; echo ' )' echo "DOSSIER_DESTINATION=\"$dest\"" echo "CORBEILLE_JOURS=$jours" echo 'EXCLUSIONS=( ".cache/" ".local/share/Trash/" "*.tmp" )' echo 'VERIFIER_ESPACE="oui"' } > "$CONF" } lancer() { # lance le script en mode test ; sortie dans $TRAVAIL/sortie.txt sleep 1 # horodatage à la seconde : une corbeille par lancement set +e SAUVEGARDE_CONF="$CONF" SAUVEGARDE_TEST_DESTINATION="${DEST_TEST:-$CLE}" \ "$SCRIPT" "$@" > "$TRAVAIL/sortie.txt" 2>&1 CODE=$? set -e } nb_corbeilles() { find "$CLE/.corbeille" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l; } mkdir -p "$SRC/Documents" "$SRC/Images" "$SRC/.cache/firefox" "$SRC/.local/share/Trash/files" "$CLE" echo "lettre v1" > "$SRC/Documents/lettre.txt" echo "impôts 2026" > "$SRC/Documents/impots.txt" echo "photo" > "$SRC/Images/vacances.jpg" echo "cache" > "$SRC/.cache/firefox/gros-cache" echo "jeté" > "$SRC/.local/share/Trash/files/vieux.txt" echo "temporaire" > "$SRC/Documents/brouillon.tmp" ecrire_conf 30 Sauvegarde "$SRC" COPIE="$CLE/Sauvegarde/marie" echo "Dossier de test : $TRAVAIL" echo "1. Première sauvegarde" lancer verifier "code de sortie 0" test "$CODE" -eq 0 verifier "lettre.txt copiée" test -f "$COPIE/Documents/lettre.txt" verifier "vacances.jpg copiée" test -f "$COPIE/Images/vacances.jpg" verifier ".cache exclu" test ! -e "$COPIE/.cache" verifier "corbeille locale exclue" test ! -e "$COPIE/.local/share/Trash" verifier "*.tmp exclu" test ! -e "$COPIE/Documents/brouillon.tmp" verifier "derniere-sauvegarde.txt = OK" grep -q 'Résultat *: OK' "$CLE/derniere-sauvegarde.txt" echo "2. Simulation (--simulation) après suppression de impots.txt" rm "$SRC/Documents/impots.txt" lancer --simulation verifier "code de sortie 0" test "$CODE" -eq 0 verifier "annonce la suppression" grep -q 'deleting.*impots.txt' "$TRAVAIL/sortie.txt" verifier "impots.txt toujours sur la clé" test -f "$COPIE/Documents/impots.txt" verifier "aucune corbeille créée" test "$(nb_corbeilles)" -eq 0 echo "3. Suppression côté ordinateur → retiré de la copie, gardé en corbeille" lancer verifier "code de sortie 0" test "$CODE" -eq 0 verifier "impots.txt absent de la copie" test ! -e "$COPIE/Documents/impots.txt" CORB1="$(find "$CLE/.corbeille" -mindepth 1 -maxdepth 1 -type d | head -n1)" verifier "nom de corbeille AAAA-MM-JJ_HHMMSS" bash -c '[[ "$(basename "$1")" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{6}$ ]]' _ "$CORB1" verifier "impots.txt dans .corbeille/" test -f "$CORB1/marie/Documents/impots.txt" echo "4. Modification d'un fichier → nouvelle version copiée, ancienne en corbeille" echo "lettre v2, bien plus longue" > "$SRC/Documents/lettre.txt" lancer verifier "code de sortie 0" test "$CODE" -eq 0 verifier "copie = v2" grep -q 'v2' "$COPIE/Documents/lettre.txt" verifier "ancienne v1 en corbeille" bash -c 'grep -rqs "lettre v1" "$1"/.corbeille/*/marie/Documents/lettre.txt' _ "$CLE" verifier "deux corbeilles" test "$(nb_corbeilles)" -eq 2 echo "5. Purge des corbeilles de plus de 30 jours" mkdir -p "$CLE/.corbeille/2026-09-01_120000/marie" "$CLE/.corbeille/2026-10-30_120000" echo vieux > "$CLE/.corbeille/2026-09-01_120000/marie/vieux.txt" touch -d '40 days ago' "$CLE/.corbeille/2026-09-01_120000" touch -d '6 days ago' "$CLE/.corbeille/2026-10-30_120000" mkdir -p "$CLE/.corbeille/a-moi"; touch -d '90 days ago' "$CLE/.corbeille/a-moi" lancer verifier "code de sortie 0" test "$CODE" -eq 0 verifier "corbeille de 40 jours purgée" test ! -e "$CLE/.corbeille/2026-09-01_120000" verifier "corbeille de 6 jours gardée" test -d "$CLE/.corbeille/2026-10-30_120000" verifier "dossier au nom inattendu épargné" test -d "$CLE/.corbeille/a-moi" verifier "purge annoncée dans le journal" grep -q 'Purge.*2026-09-01_120000' "$TRAVAIL/sortie.txt" echo "6. CORBEILLE_JOURS=0 : miroir pur, sans corbeille" ecrire_conf 0 Sauvegarde "$SRC" avant="$(nb_corbeilles)" rm "$SRC/Images/vacances.jpg" lancer verifier "code de sortie 0" test "$CODE" -eq 0 verifier "vacances.jpg absent de la copie" test ! -e "$COPIE/Images/vacances.jpg" verifier "aucune nouvelle corbeille" test "$(nb_corbeilles)" -eq "$avant" verifier "vacances.jpg nulle part sur la clé" test -z "$(find "$CLE" -name vacances.jpg)" ecrire_conf 30 Sauvegarde "$SRC" echo "7. Clé FAT simulée : lien symbolique ignoré sans erreur" ln -s Documents/lettre.txt "$SRC/raccourci" SAUVEGARDE_TEST_FSTYPE=vfat lancer verifier "code de sortie 0" test "$CODE" -eq 0 verifier "lien non copié" test ! -e "$COPIE/raccourci" -a ! -L "$COPIE/raccourci" rm "$SRC/raccourci" echo "8. Garde-fous (tous doivent REFUSER, sans rien toucher)" empreinte() { find "$CLE" "$SRC" -printf '%p %s\n' | sort | md5sum; } E0="$(empreinte)" DEST_TEST="$TRAVAIL/nexiste-pas" lancer verifier "destination de test absente → refus" test "$CODE" -ne 0 DEST_TEST="/" lancer verifier "destination « / » → refus" test "$CODE" -ne 0 for d in "../evasion" "a/../../evasion" "/tmp/x" "." ".corbeille" ""; do ecrire_conf 30 "$d" "$SRC"; lancer verifier "DOSSIER_DESTINATION=« $d » → refus" test "$CODE" -ne 0 done verifier "rien n'a été créé hors de la clé" test ! -e "$TRAVAIL/evasion" -a ! -e "$TRAVAIL/x" ln -s "$TRAVAIL/maison" "$CLE/piege" ecrire_conf 30 piege "$SRC"; lancer verifier "lien sur la clé vers l'extérieur → refus" test "$CODE" -ne 0 rm "$CLE/piege" ecrire_conf 30 Sauvegarde; lancer verifier "SOURCES vide → refus" test "$CODE" -ne 0 mkdir -p "$TRAVAIL/vide" ecrire_conf 30 Sauvegarde "$TRAVAIL/vide"; lancer verifier "source vide → refus" test "$CODE" -ne 0 ecrire_conf 30 Sauvegarde "$TRAVAIL/absent"; lancer verifier "source inexistante → refus" test "$CODE" -ne 0 ecrire_conf 30 Sauvegarde "$CLE"; lancer verifier "source contenant la clé → refus" test "$CODE" -ne 0 ecrire_conf 30 Sauvegarde "$SRC/Documents" "$TRAVAIL/maison/marie/../marie/Documents"; lancer verifier "deux sources au même nom → refus" test "$CODE" -ne 0 verifier "clé et sources inchangées" test "$(empreinte)" = "$E0" ecrire_conf 30 Sauvegarde "$SRC" echo "9. Verrou : deux sauvegardes simultanées impossibles" exec 8>"$TRAVAIL/sauvegarde-cle-usb-test.lock"; flock -n 8 lancer verifier "2e exécution s'arrête sans rien faire" grep -q 'déjà en cours' "$TRAVAIL/sortie.txt" exec 8>&- echo echo "Bilan : $REUSSIS réussis, $RATES ratés." [[ "$RATES" -eq 0 ]] && rm -rf "$TRAVAIL" [[ "$RATES" -eq 0 ]]