chiark / gitweb /
rsync-backup.in: Add double-checking for the manifest comparison.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 30 May 2015 11:13:46 +0000 (12:13 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 30 May 2015 11:17:40 +0000 (12:17 +0100)
While hacking on 1c0d861..., I temporarily introduced a bug which failed
to spot differences between the local and remote fshash(1) manifests.
Add an explicit check of file hashes as a backstop to guard against this
kind of bug now or in the future.

Also dump the hashes into the log, so that one can verify after the fact
that everything actually worked properly.

rsync-backup.in

index 2c1e3b6ca6e87ddae00418f390ffd746cba0e876..43b5efb58ac95a5f0a74f25b3b14f951fe63fca0 100644 (file)
@@ -534,6 +534,21 @@ unset VOLUME
 
 bkprc=0
 
+hash_file () {
+  file=$1
+
+  case $HASH in
+    md5 | sha1 | sha224 | sha256 | sha384 | sha512)
+      set -- $(${HASH}sum <"$file")
+      echo "$1"
+      ;;
+    *)
+      set -- $(openssl dgst -$HASH <"$file")
+      echo "$2"
+      ;;
+  esac
+}
+
 remote_fshash () {
   _hostrun $userat$host "
        umask 077
@@ -628,6 +643,9 @@ do_backup () {
   ## Maybe we need to retry the backup.
   while :; do
 
+    ## Rig checksum variables to mismatch unless they're set later.
+    hrfs=REMOTE hlfs=LOCAL
+
     ## Create and mount the remote snapshot.
     case $dryrun in
       t)
@@ -685,7 +703,16 @@ do_backup () {
     run "@$host: fshash $fs" remote_fshash
     rc_fshash=$?
     set -e
-    case $dryrun in nil) $verbose " done" ;; esac
+    case $dryrun in
+      nil)
+       hrfs=$(hash_file "$fshashdir/$fs.bkp")
+       $log "remote fshash $HASH checksum: $hlfs"
+       $verbose " done"
+       ;;
+      t)
+       hrfs=UNSET
+       ;;
+    esac
 
     ## Remove the snapshot.
     maybe unsnap_$snap $snapargs $fs $fsarg
@@ -706,7 +733,16 @@ do_backup () {
       nil) $verbose -n "       local fshash..." ;;
     esac
     run "local fshash $host:$fs" local_fshash || return $?
-    case $dryrun in nil) $verbose " done" ;; esac
+    case $dryrun in
+      nil)
+       hlfs=$(hash_file "$localmap")
+       $log "local fshash $HASH checksum: $hlfs"
+       $verbose " done"
+       ;;
+      t)
+       hlfs=UNSET
+       ;;
+    esac
 
     ## Compare the two maps.
     set +e
@@ -730,6 +766,16 @@ do_backup () {
     esac
   done
 
+  ## Double-check the checksums.
+  if [ $hrfs != $hlfs ]; then
+    cat >&2 <<EOF
+$0: INTERNAL ERROR: fshash $HASH checksum mismatch -- aborting
+       remote fshash checksum = $hrfs
+       local fshash checksum = $hlfs
+EOF
+    exit 127
+  fi
+
   ## Glorious success.
   maybe rm -f $localmap
   case $fshash_diff in nil) ;; *) maybe rm -f $fshash_diff ;; esac