#!/bin/bash

VERSIONE='1.6'
DATA_VERSIONE='15 gennaio 2012'
AUTORE='Alessandro Selli http://alessandro.route-add.net/'
LICENZA='GPL versione 3 o successiva'
HOST="$(hostname)"
HOST="${HOST%.[a-zA-Z0-9-]*}"
SERVER='niraya'
DIR='/mnt/dump_backup'
MOUNTDIR=''
DATA=$(date '+%Y-%m-%d')
LIVELLO='0'
FILE="${HOST}_${DATA}_$LIVELLO"
DUMPDATES_FILE="${HOST}_dumpdates"
DUMPDATES="$DIR/$DUMPDATES_FILE"
USER_PROVIDED_DUMPDATES='false'
IO="$(basename -- $0)"
OVERWRITE='no'
VERB='no'
SYNCDD='false'
TEST='no'
TOC='no'
NFS='no'
QUITONERR='false'
QUIET=1 # Preimpostato a falso, ossia non quieto
COD=0
ECHOE=''
BOLD=''
NORM=''

# Permetti di espandere gli alias nella shell non interattiva
shopt -s expand_aliases

alias QEcho='test "$QUIET" -ne 0 && echo$ECHOE'
alias VEcho='test "$VERB" != "no" && echo$ECHOE'

# Il comando infocmp (del pacchetto ncurses) serve per ottenere le proprietà
# del terminale.  Se c'è, si usa per fighettizzare i messaggi.  Se non c'è
# pazienza, si va di dumb-terminal.
if command -v infocmp > /dev/null
then if test -n "$(infocmp -1I $TERM | grep 'bold=\\E\[1m,')"
     then ESC="$(echo -en '\033')"
     	  ECHOE=' -e'
	  NORM="${ESC}[0m"
          BOLD="${ESC}[1m"
     fi
fi

for COM in basename dirname hostname dump tr date awk mktemp
do if ! command -v "$COM" > /dev/null
   then QEcho "${BOLD}ERRORE:${NORM} comando \"$COM\" necessario ma non disponibile" >&2
        exit 2
   fi
done

# De-utf8-izza LANG, che questo script (e quindi i suoi messaggi) sono scritti
# in ISO-8859-1
LANG="${LANG%\.UTF-8}"
LANG="${LANG%\.utf8}"

# Dump su un filesystem NFS ha prestazioni dannatamente scadenti (1/20 la
# larghezza di banda di una connessione da 100mbs).  Le operazioni di scrittura
# sono infatti pesantemente penalizzate dalle scritture sincrone che dump
# effettua sempre, indipendentemente dalle opzioni con cui è stato montato il
# filesystem NFS.  Per ovviare a questo problema, non avendo dump un'opzione
# che abiliti la scrittura asincrona, è stato introdotto lo switch -n (NFS) che
# crea una named pipe temporanea in $TMPDIR o in $TMP o in /tmp, mandando in
# esecuzione nello sfondo un cat che legge dalla named pipe e scrive nel file
# di dump sul filesystem NFS, e infine istruisce dump ad effettuare le
# scritture nella named pipe.

# DA FARE:
# 1) controllare, terminato un dump con l'opzione NFS (-n) attivata, che il comando
#    cat associato alla named pipe in cui scrive dump sia terminato;
# 2) gestire la compressione;
# 3) permettere di specificare sulla riga di comando i filesystem di cui
#    eseguire  un dump, invece di farlo automaticamente per tutti i filesystem in
#    /etc/fstab che lo richiedono.

function Esci () {
# Pulizia
# La funzione Esci è usata ogni volta che lo script cessa l'esecuzione, grazie alla
# trap EXIT.  Questo non impedisce allo script di uscire con un codice arbitrario 
# con un'istruzione exit x
if test $# -eq 1
then SIG="SIG${1#SIG}"
     if kill -l | grep -q "$SIG"
     then QEcho "Uscita causa ricezione segnale ${BOLD}$SIG${NORM}" >&2
          ERR=4
     else QEcho "${BOLD}ERRORE:${NORM} uscita anomala: funzione ${BOLD}Esci${NORM} chiamata con parametro: $1 (non è un segnale)" >&2
          ERR=6
     fi
else if test $# -gt 0
     then QEcho "${BOLD}ERRORE:${NORM}Uscita anomala: funzione ${BOLD}Esci${NORM} chiamata con $# parametri" >&2
          ERR=7
     fi
fi
# Se è un test PIPE non esiste, inutile mettere $ECHO davanti a rm
test -p "$PIPE" && rm -f "$PIPE"
COD=$?
if test -n "$MOUNTDIR" -a "$MD_IN_FSTAB" = 'yes' -a "$MD_MOUNTED" = 'no'
then $ECHO sync
     $ECHO umount "$MOUNTDIR"
     COD=$?
     if test $COD -ne 0
     then QEcho "${BOLD}ERRORE:${NORM} comando mount uscito con codice $COD" >&2
     fi
fi
exit
}

for SIGNAL in EXIT HUP INT ABRT TERM QUIT
do trap Esci "$SIGNAL"
done

for SIGNAL in USR1 USR2
do trap : "$SIGNAL"
done

function Codici () {
cat << EOH
${BOLD}Codici di errore:${NORM}
${BOLD}1${NORM}: opzione non valida
${BOLD}2${NORM}: non è stato trovato qualche comando essenziale
${BOLD}3${NORM}: nessun filesystem di cui eseguire il dump in /etc/fstab
${BOLD}4${NORM}: uscita prematura per ricezione segnale
${BOLD}6${NORM}: uscita con chiamata anomala funzione Esci con primo parametro non nome di segnale
${BOLD}7${NORM}: uscita con chiamata anomala funzione Esci con più di un parametro
${BOLD}10${NORM}: fallita verifica che il nome host/server contenga solo i caratteri previsti dalla RFC-1034
${BOLD}15${NORM}: errore interno invocazione procedura controllo nome host/server
${BOLD}20${NORM}: il valore del livello di dump non è numerico
${BOLD}22${NORM}: il valore del livello di dump contiene più di una cifra
${BOLD}25${NORM}: errore interno invocazione procedura controllo numero
${BOLD}30${NORM}: errato formato data
${BOLD}31${NORM}: data errata per il calendario
${BOLD}35${NORM}: errore invocazione procedura controllo data
${BOLD}36${NORM}: il parametro per MOUNTDIR non indica una directory
${BOLD}37${NORM}: errore invocazione procedura controllo directory
${BOLD}38${NORM}: montaggio di "${BOLD}$MOUNTDIR${NORM}" impossibile: la directory non compare in /etc/fstab 
${BOLD}39${NORM}: montaggio di "${BOLD}$MOUNTDIR${NORM}" fallito
${BOLD}40${NORM}: fallita esecuzione di mktemp
${BOLD}45${NORM}: fallita creazione di named pipe in $TMPDIR
${BOLD}50${NORM}: DIR non indica una directory scrivibile
${BOLD}53${NORM}: la directory di DUMPDATES non indica una directory scrivibile
${BOLD}60${NORM}: directory indicata per il file dumpdates non valida
${BOLD}70${NORM}: comando dump terminato con errore e opzione -e attiva
${BOLD}100+n${NORM}: errori di funzioni interne: n=0 funzione VerificaHostname;
        n=1 funzione VerificaData; n=3 funzione VerificaNumero
EOH
}

function Versione () {
 echo -e "$IO Versione $VERSIONE del $DATA_VERSIONE\\nDi $AUTORE\\nRilasciata sotto licenza $LICENZA"
}

function Help () {
Versione
echo ''
cat << EOH
${BOLD}Uso:${NORM} $IO [-d dir] [-D data] [-e] [-f base_file] [-F dumpdates] [-H hostname]
     [-l l] [-m mount_dir] [-h] [-n] [-o] [-q] [-s] [-t] [-T] [-v] [-V] [-x]
     [filesystem]

Dove (tra parentesi quadre i valori in uso):

${BOLD}hostname${NORM} indica il nome del computer che esegue ${IO} ${BOLD}[$HOST]${NORM};
${BOLD}dir${NORM} indica il percorso locale della directory dove va scritto il file di dump e,
    eventualmente, dove è posto il file dumpdates (switch -F)
    ${BOLD}[$DIR]${NORM};
${BOLD}data${NORM} indica la data da usare per costruire il nome del file di dump
    ${BOLD}[$DATA]${NORM}
${BOLD}base_file${NORM} indica la base del nome del file di dump ${BOLD}[$FILE]${NORM}
    Quella preimpostata è composta da: "${BOLD}\${HOST}_\${DATA}_\${LIVELLO}${NORM}". A questa
    base è poi automaticamente aggiunta la componente "${BOLD}_\$FILESYSTEM.dump${NORM}"
${BOLD}dumpdates${NORM} indica il file dumpdates che deve usare dump per tenere traccia delle
    operazioni eseguite, con eventuale percorso alternativo ${BOLD}[$DUMPDATES]${NORM};
${BOLD}l${NORM} indica il livello di dump che si vuole eseguire, compreso tra 0 e 9 ${BOLD}[$LIVELLO]${NORM}$(test -n "$MOUNTDIR" && echo -e "\nmount_dir indica la directory da montare prima di eseguire il dump\n    ${BOLD}[$MOUNTDIR]${NORM}")
${BOLD}mount_dir${NORM} indica la directory da montare per avere accesso al deposito dei file
    di dump
${BOLD}filesystem${NORM} indica il filesystem di cui eseguire il dump, indicato o come punto
    di montaggio di un dispositivo o come nome di dispositivo; se non indicato,
    la procedura interesserà tutti i filesystem che necessitano di un dump ${BOLD}[NON
    ANCORA IMPLEMENTATO!]${NORM}
${BOLD}-e${NORM} cessa la continuazione dello script se dump termina con un errore
${BOLD}-h${NORM} help, mostra questo testo
${BOLD}-n${NORM} attiva la modalità di funzionamento NFS in cui il file di dump è scritto in
   una named pipe ${BOLD}[$NFS]${NORM}
${BOLD}-o${NORM} indica che il file di output, se già esistente, deve essere sovrascritto ${BOLD}[$OVERWRITE]${NORM}
${BOLD}-q${NORM} attiva la modalità quieta, in cui non sono prodotti messaggi ${BOLD}[$(test "$QUIET" -ne 0 && echo 'normale' || echo 'quieta')]${NORM}
${BOLD}-s${NORM} mantieni sincronizzati i file dumpdates, quello dello script ${BOLD}"$DUMPDATES"${NORM}
   e quello di sistema ${BOLD}[$(test "$SYNCDD" = 'true' && echo 'si' || echo 'no')]${NORM}
${BOLD}-t${NORM} crea il file indice (toc: table of contents) ${BOLD}[$TOC]${NORM}
${BOLD}-T${NORM} modalità di test: il comando dump non è mandato in esecuzione, ma solo
   scritto sul terminale ${BOLD}[$TEST]${NORM}
${BOLD}-v${NORM} attiva la modalità verbosa ${BOLD}[$VERB]${NORM}
${BOLD}-V${NORM} mostra informazioni su: versione, autore e licenza
${BOLD}-x${NORM} trace execution, esecuzione in modalità tracciamento delle funzioni di shell
EOH
}

function VerificaHostname () {
# Controllo approssimativo, in realtà la RFC-1034 è più esigente
if test $# -eq 1
then A="$(echo $1 | tr -cd 'A-Za-z0-9.-')"
     if test "$1" != "$A"
     then return 10
     fi
else QEcho "${BOLD}ERRORE:${NORM} funzione VerificaHostname invocata con $# parametri invece di 1" >&2
     return 15
fi
}

function VerificaNumero () {
# Controlla che il parametro fornito sia un numero decimale
if test $# -eq 1
then if test "${#1}" = 1
     then A="$(echo $1 | tr -cd '0-9')"
          if test "$1" != "$A"
          then return 20
          fi
     else return 22
     fi
else QEcho "${BOLD}ERRORE:${NORM} funzione VerificaNumero invocata con $# parametri invece di 1" >&2
     return 25
fi
}

function VerificaData () {
if test $# -eq 1
then if [[ "$DATA" =~ ^[12][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9]$ ]]
     then if ! date "--date=$DATA" '+%Y-%m-%d' &> /dev/null
          then return 30
	  fi
     else return 31
     fi
else QEcho "${BOLD}ERRORE:${NORM} funzione VerificaData invocata con $# parametri invece di 1" >&2
     return 35
fi
}

function ChkDir () {
if test $# -eq 1
then if test ! -d "$1" -o ! -w "$1"
     then QEcho "${BOLD}ERRORE:${NORM} il parametro \"$1\" non è una directory o non è scrivibile" >&2
	  return 50
     fi
else QEcho "${BOLD}ERRORE:${NORM} funzione ChkDir invocata con $# parametri invece di 1" >&2
     return 37
fi
}

function FindDumpdates () {
# Tentativi che fanno via via più affidamento a criteri probabilistici o di verosimiglianza per 
# capire se il comando dump del sistema in uso usa di default il file dumdates in /etc oppure in
# /var/lib. Debian 6.0 e Ubuntu 11.10 usano di default /var/lib/dumpdates; Fedora15/16 (e,
# suppongo, RedHat, CentOS, Mandriva e YellowDog) invece usano (correttamente) /etc/dumpdates
DISTRO=''
DDFILE=''
if command -v lsb_release > /dev/null
then DISTRO="$(lsb_release -i | sed '/^Distributor ID:\t/s/^Distributor ID:\t//')"
     # Possibili valori noti: Debian, Fedora, Ubuntu
     # Possibili valori più o meno tirati ad indovinare: CentOS, MandrivaLinux, YellowDog
     # Le altre distribuzioni non le prendo in considerazione perché non ho idea di dove
     # abbiano il file dumpdates
fi
if test -z "$DISTRO"
then # O non abbiamo a disposizione il comando lsb_release, oppure non ne siamo riusciti ad estrarre
     # il nome della distribuzione. Tentiamo allora di cercare un file in /etc/ che ci dica in che
     # distribuzione stiamo girando, NON QUALSIASI distribuzione, ma quelle di cui conosco il
     # comportamento di default di dump, ossia Debian6.0/Ubuntu11.10 e Fedora16.  Il dump delle prime
     # ha il file dumpdates di default in /var/lib/, mentre la seconda (e verosimilmente anche 
     # RedHat, SuSE/Novell, CentOS, Mandriva, YellowDog ecc.) ce l'ha in /etc/.
     DISTROFILE=($(find /etc -maxdepth 1 -type f \( -name '*release' -o -name '*version' \) ))
     # Possono essere più file: Debian6.0 ha /etc/debian_version, 
     # Ubuntu 11.10 ha /etc/debian_version e /etc/lsb-release, di contenuto diverso.
     # Fedora 16 ha /etc/fedora-release.
     # Non ne analizziamo il contenuto, ci limitiamo a considerare il nome del file, se presente.
     # Più righe?  Le analizziamo tutte!
     for (( I=0 ; I < ${#DDFILE[@]} ; I++ ))
     do RIGA="${DISTROFILE[$I]#/etc/}"
        for DISTRIBUTION in 'debian' 'fedora' 'redhat' 'mandriva' 'yellowdog'
        do if test [[ "${RIGA}" = "{DISTRIBUTION}"* ]]
	   then DISTRO="$DISTRIBUTION"
	        break
	   fi
	done
     done
else DISTRO="$(echo "$DISTRO" | tr A-Z a-z)" # Meno male che non usiamo la codifica UTF-8!  :-)
fi
if test -n "$DISTRO"
then # Evviva!  Abbiamo trovato la distribuzione!
     if test "$DISTRO" = 'debian' -o "$DISTRO" = 'ubuntu'
     then DDFILE='/var/lib/dumpdates'
     else if test "$DISTRO" = 'fedora' -o "$DISTRO" = 'redhat' -o "$DISTRO" = 'mandriva' -o "$DISTRO" = 'yellowdog'
          then DDFILE='/etc/dumpdates'
	       # Per tutte le altre distribuzioni di cui non so, DDFILE resta vuoto
	  fi
     fi
fi
if test -z "$DDFILE"
then # Niente, non si riesce a capire quale dumpdates dump usi a partire dal nome della
     # distribuzione.  E se cercassimo di farlo spifferare dallo stesso dump?  Ma dump non
     # ha un'opzione di aiuto che glielo faccia dire con le buone.  Dobbiamo tentare con le
     # cattive, se possibile.  strings fa parte del pacchetto binutils, che è opzionale,
     # non si dia quindi per scontato che è disponibile:
     if command -v strings > /dev/null
     then STRINGS=($(strings "$(which dump)" | grep '/dumdates')) #"
          for (( I=0 ; I < ${#STRINGS[@]} ; I++ ))
	  do if [[ "$STRINGS[$I]" = */etc/dumpdates* ]]
	     then DDFILE='/etc/dumpdates'
	          break
	     else if [[ "$STRINGS[$I]" = */var/lib/dumpdates* ]]
	          then DDFILE='/var/lib/dumpdates'
		       break
		  fi
	     fi
	  done
     fi
fi
if test -z "$DDFILE"
then # Uffa.  Fin'ora tutto vano.  Vediamo se esiste già uno, e solo uno, dei file 
     # /etc/dumpdates o /var/lib/dumpdates/dumpdates.  Se si, assumo sia quello giusto.
     if test -f '/etc/dumpdates' -a ! -f '/var/lib/dumpdates'
     then DDFILE='/etc/dumpdates'
     else if test -f '/var/lib/dumpdates' -a ! -f '/etc/dumpdates' 
          then DDFILE='/var/lib/dumpdates'
	  fi
     fi
fi
# DDFILE contiene il percorso del file dumpdates trovato oppure una stringa vuota.
# Non è detto che DDFILE esista, fosse anche quello giusto, e non è detto che, anche
# esistesse, che sia un file e che sia quello giusto.
}

#shopt -s extglob # Non serve
# OPTIND=1 # Fatto automaticamente dalla shell al caricamento dello script
# Non usare shift [n]! Altrimenti getopts non vede le opzioni/parametri successivi!
OPTERR=0 # Resta silenzioso in caso di errori
while getopts H:d:D:f:F:l:m:honpqstTvVx NXOPT
do case "$NXOPT" in
        'H') # Controlla che parametro sia composto solamente di caratteri [a-zA-Z0-9.-]
	     if VerificaHostname "$OPTARG"
	     then HOST="$OPTARG"
	          # Aggiorniamo le variabili che dipendono da HOST: FILE e, se necessario, DUMPDATES
		  FILE="${HOST}_${DATA}_$LIVELLO"
		  test "$USER_PROVIDED_DUMPDATES" = 'false' && DUMPDATES="$DIR/$DUMPDATES_FILE"
	     else case $? in 
	       	       10) ERR=$?
			   QEcho "${BOLD}ERRORE:${NORM} caratteri non validi nel nome host: $OPTARG" >&2 ;;
		       15) ERR=$?
			   QEcho "${BOLD}ERRORE:${NORM} procedura interna fallita" >&2 ;;
		       *) QEcho "${BOLD}ERRORE:${NORM} procedura interna inaspettatamente fallita (VerificaHostname)" >&2
			  ERR=100 ;;
		   esac
		   exit "$ERR"
	     fi
	     ;;
        'd') DIR="$OPTARG"
	     # Non compierne verifiche: potrebbe stare sotto il possibile punto di montaggio (opzione -m)
	     ;;
	'e') QUITONERR='true' ;;
        'D') if VerificaData "$OPTARG"
	     then DATA="$OPTARG"
	          # Aggiorniamo la variabile FILE che dipende da DATA
		  FILE="${HOST}_${DATA}_$LIVELLO"
	     else case $? in
	               30) ERR=$?
			   QEcho "${BOLD}ERRORE:${NORM} la data non è congrua con il calendario" >&2 ;;
		       31) ERR=$?
			   QEcho "${BOLD}ERRORE:${NORM} la data non è nel formato ANNO-ME-GI" >&2 ;;
		       *) QEcho "${BOLD}ERRORE:${NORM} procedura interna inaspettatamente fallita (VerificaData)" >&2
			  ERR=101 ;;
	          esac
		  exit "$ERR"
	     fi ;;
        'f') FILE="$OPTARG" ;;
	'F') DUMPDATES_FILE="$(basename "$OPTARG")"
	     # ATTENTO!  Se OPTARG=/dir1/dir2/, basename "$OPTARG" = dir2 e dirname "$OPTARG" = /dir1
	     # Questo non è un problema perché l'opzione prevede che il percorso sia opzionale, ma la
	     # indicazione del file no, ci deve essere
	     if test "$DUMPDATES_FILE" = "$OPTARG" # È stato specificato solo un nome di file, non un percorso?
	     then DUMPDATES="$DIR/$DUMPDATES_FILE"
	          # Come per l'opzione -d DIR non se ne compiono verifiche: potrebbe stare sotto il possibile punto di montaggio (opzione -m)
	     else # È stato specificato anche il percorso, che sarà controllato dopo l'eventuale montaggio
		  DUMPDATES="$OPTARG"
	     fi
	     USER_PROVIDED_DUMPDATES='true' ;;
	'l') # Controlla che il parametro sia composto solamente di caratteri numerici
	     if VerificaNumero "$OPTARG"
	     then LIVELLO="$OPTARG"
	          # Aggiorniamo la variabile FILE che dipende da LIVELLO
		  FILE="${HOST}_${DATA}_$LIVELLO"
	     else case $? in
	               20|22) ERR=$?
			      QEcho "${BOLD}ERRORE:${NORM} indicazione livello non valida: dev'essere una cifra numerica (trovato: $OPTARG)" >&2 ;;
		       25) ERR=$?
			   QEcho "${BOLD}ERRORE:${NORM} procedura interna fallita" >&2 ;;
		       *) QEcho "${BOLD}ERRORE:${NORM} procedura interna fallita per motivi ignoti (VerificaNumero)" >&2
			  ERR=103 ;;
		  esac
		  exit "$ERR"
	     fi ;;
	'm') if test -d "$OPTARG"
	     then MOUNTDIR="$OPTARG"
	     else QEcho "${BOLD}ERRORE:${NORM} il parametro non indica una directory: $OPTARG" >&2
	          exit 36
	     fi
	     ;;
        'n') NFS='yes' ;;
        'o') OVERWRITE='yes' ;;
	'q') QUIET=0 ; VERB='no' ;;
	's') SYNCDD='true' ;;
        't') TOC='yes' ;;
	'T') TEST='yes'
	     ECHO='echo' ;;
        'h') Help
	     if test "$VERB" = 'yes'
	     then echo ; Codici
	     fi
	     exit ;;
        'v') VERB='yes' ; QUIET=1 ;;
	'V') Versione ; exit ;;
	'x') set -o xtrace ;;
	# Questo è eseguito quando getopts incontra un'opzione non prevista ma sintatticamente
	# valida
        *) # In teoria quando OPTERR=0 NXOPT è posto a ? e in OPTARG dovrebbe essere l'opzione non
	   # valida riscontrata; in realtà non ci trovo niente, per cui mi limito ad indicarne il numero
	   QEcho "${BOLD}ERRORE:${NORM} opzione numero $((OPTIND - 1)) non valida" >&2
	   exit 1 ;;
   esac
   if test NXOPT = ':'
   then # è stata riscontrata un'opzione non valida; se OPTERR=0 allora ?=1, NXOPT=: e OPTARG=opzione
        QEcho "${BOLD}ERRORE:${NORM} opzione ${BOLD}$NXOPT${NORM} non valida" >&2
	exit 1
   fi
done

# Eseguo qui i controlli sulla scrivibilità delle cartelle dopo l'eventuale montaggio, non
# nella procedura di analisi opzioni, perché questi controlli devono essere indipendenti dal_
# l'ordine delle opzioni sulla riga di comando (-d DIR -m MOUNTDIR oppure -m MOUNTDIR -d DIR)
# e DIR potrebbe essere una sottocartella di MOUNTDIR.  Inoltre se questa esecuzione è un
# test allora non monto MOUNTDIR, per cui non ne vedrei le sottocartelle e il controllo sulla
# loro scrivibilità fallirebbe
MD_IN_FSTAB="$(awk -v V="$MOUNTDIR" '$1 !~ /^#/ && $2 != V {FOUND = 1 ; exit} END {print FOUND ? "yes" : "no"}' /etc/fstab)"
MD_MOUNTED="$(mount | awk -v V="$MOUNTDIR" '$2 " " $3 == "on "V {TROVATO = 1 ; exit} END {print TROVATO ? "yes" : "no"}')"
if test -n "$MOUNTDIR" -a "$MD_MOUNTED" = 'no'
then # MOUNTDIR è definita (e quindi da montare) e non è montata
     if test "$MD_IN_FSTAB" = 'yes'
     then $ECHO mount "$MOUNTDIR"
	  ERR=$?
	  if test $ERR -ne 0
	  then QEcho "${BOLD}ERRORE:${NORM} montaggio di \"$MOUNTDIR\" fallito con errore num. $ERR" >&2
	       exit 39
	  fi
     else QEcho "${BOLD}ERRORE:${NORM} montaggio di \"$MOUNTDIR\" impossibile: la directory non compare in /etc/fstab" >&2
	  exit 38
     fi
fi

# O MOUNTDIR non è definita (e quindi non è da montare), o era stata montata prima
# dell'esecuzione dello script oppure è stata montata poche righe in alto
# Controlla che DIR sia scrivibile e aggiorna DUMPDATES
ChkDir "$DIR"
ERR=$?
if test $ERR -eq 0
then # Aggiorniamo, se necessario, la variabile DUMPDATES che dipende da DIR
     test "$USER_PROVIDED_DUMPDATES" = 'false' && DUMPDATES="$DIR/$DUMPDATES_FILE"
else QEcho "${BOLD}ERRORE:${NORM} \"$DIR\" non indica una directory scrivibile" >&2
     exit 50
fi
# Adesso si controlla la directory di DUMPDATES
### Da controllare! ###
ChkDir "$(dirname "$DUMPDATES")"
ERR=$?
if test $ERR -ne 0
then QEcho "${BOLD}ERRORE:${NORM} \"$(dirname "$DUMPDATES")\" non indica una directory scrivibile" >&2
     exit 53
fi

if test -z "$TMPDIR" -o ! -d "$TMPDIR"
then if test -z "$TMP" -o ! -d "$TMP"
     then VEcho "Variabili TMPDIR e TMP non inizializzate o che non puntano ad una directory." >&2
          VEcho "Posto TMPDIR=/tmp" >&2
          TMPDIR='/tmp'
     fi
fi

if test "$NFS" = 'yes'
then if PIPE="$(mktemp -u --tmpdir="$TMPDIR")"
     then $ECHO mknod "$PIPE" p
          if test $? -ne 0
          then QEcho "${BOLD}ERRORE:${NORM} fallita creazione di named pipe in $TMPDIR" >&2
               exit 45
          fi
     else QEcho "${BOLD}ERRORE:${NORM} fallita esecuzione di mktemp" >&2
          exit 40
     fi
fi

# Elencare i filesystem di cui fare il dump
MFS=($(awk '$1 !~ /^#/ && NF == 6 && $5 != 0 {print $2}' /etc/fstab))
if test ${#MFS[@]} = 0
then QEcho "${BOLD}ATTENZIONE:${NORM} non è stato trovato nessun filesystem di cui eseguire il dump in /etc/fstab" >&2
     exit 3
fi

# Si procede ora con il dump
IND=0
while test "$IND" -lt "${#MFS[@]}"
do FS="${MFS[$IND]}"
   if test -d "$FS"
   then if test "$FS" = '/'
        then FILESYSTEM='_rootfs'
        else FILESYSTEM="$(echo "$FS" | tr '/' '_')"
        fi
        DUMPFILE="$DIR/${FILE}${FILESYSTEM}.dump"
	if test "$OVERWRITE" = 'yes' -o ! -e "$DUMPFILE"
        then TOCFILE="${DUMPFILE%.dump}.toc"
	     if test "$NFS" = 'yes'
             then if test "$TEST" = 'yes'
	          then echo "cat $PIPE > $DUMPFILE &"
		  else cat "$PIPE" > "$DUMPFILE" &
		  fi
                  DUMPFILE="$PIPE"
             fi
	     if test "$TOC" = 'yes' -a \( "$OVERWRITE" = 'yes' -o ! -e "$TOCFILE" \)
	     then MKTOC='-A'
	     else MKTOC=''
	     fi
	     # stringhe vuote come argomento confondono dump che non capisce di quale filesystem fare il dump
	     if test "$QUIET" -eq 0
	     then # Controlla che non si possano fare tutte e due le righe sottostanti con un eval ###
	          $ECHO dump -D "$DUMPDATES" "-u${LIVELLO}f" "$DUMPFILE" ${MKTOC:+$MKTOC"$TOCFILE"} "$FS" &> /dev/null
	          ERR=$?
	     else $ECHO dump -D "$DUMPDATES" "-u${LIVELLO}f" "$DUMPFILE" ${MKTOC:+$MKTOC"$TOCFILE"} "$FS"
	          ERR=$?
	     fi
	     if test "$QUITONERR" = 'true' -a $ERR -ne 0
	     then QEcho "${BOLD}ERRORE:${NORM} comando dump terminato con errore $ERR" >&2
	          exit 70
	     else VEcho "${BOLD}NOTA:${NORM} comando dump terminato con codice $ERR" >&2
	     fi
	else QEcho "${BOLD}IMPORTANTE:${NORM} la sovrascrittura non è attivata e il file \"$DUMPFILE\" esiste." >&2
	     QEcho "Dump saltato per il filesystem \"$FS\"" >&2
	fi
   else QEcho "${BOLD}ERRORE:${NORM} il mountpoint \"$FS\" non è una directory. Controllare il file /etc/fstab" >&2
   fi
IND=$((IND+1))
done

if test "$SYNCDD" = 'true'
then alias Err_dump='QEcho "${BOLD}AVVISO:${NORM} sincronizzazione dei file dumpdates non effettuata anche se richiesta;" >&2'
     FindDumpdates
     if test $? -eq 0 -a -n "$DDFILE"
     then if test -f "$DDFILE"
          then # il 2> /dev/null forse dovrebbe essere fatto solo quando QUIET=1?
	       cp -f "$DDFILE"{,.bak}
	       ERR=$?
	       if test $ERR -eq 0
	       then cp -f "$DUMPDATES" "$DDFILE" 2> /dev/null
                    ERR=$?
                    if test $ERR -eq 0
	            then VEcho "Copia del file ${BOLD}$DUMPDATES${NORM} in ${BOLD}$DDFILE${NORM} effettuata"
	            else Err_dump
		         QEcho "  ${BOLD}AVVISO:${NORM} copia di ${BOLD}$DUMPDATES${NORM} in ${BOLD}$DDFILE${NORM} terminata con codice $ERR" >&2
	            fi
	       else Err_dump
	            QEcho "${BOLD}AVVISO:${NORM} la copia di ${BOLD}$DDFILE${NORM} in ${BOLD}${DDFILE}.bak${NORM} uscita con codice $ERR" >&2
	       fi
	  else Err_dump
	       QEcho "  l'oggetto \"dumpdates\" rilevato dalla funzione ${BOLD}FindDumpdates${NORM} non è un file" >&2
	  fi
     else Err_dump
          QEcho "  la funzione ${BOLD}FindDumpdates${NORM} non ha potuto rilevare il file dumpdates di sistema" >&2
     fi
else VEcho "Copia di sincronizzazione del file dumpdates non richiesta"
fi

