Blame SOURCES/rear-bz1631183.patch

e8a0f5
diff --git a/usr/share/rear/backup/NETFS/default/500_make_backup.sh b/usr/share/rear/backup/NETFS/default/500_make_backup.sh
e8a0f5
index 47266910..7170cda6 100644
e8a0f5
--- a/usr/share/rear/backup/NETFS/default/500_make_backup.sh
e8a0f5
+++ b/usr/share/rear/backup/NETFS/default/500_make_backup.sh
e8a0f5
@@ -67,49 +67,99 @@ else
e8a0f5
     SPLIT_COMMAND="dd of=$backuparchive"
e8a0f5
 fi
e8a0f5
 
e8a0f5
+# Used by "tar" method to record which pipe command failed
e8a0f5
+FAILING_BACKUP_PROG_FILE="$TMP_DIR/failing_backup_prog"
e8a0f5
+FAILING_BACKUP_PROG_RC_FILE="$TMP_DIR/failing_backup_prog_rc"
e8a0f5
+
e8a0f5
 LogPrint "Creating $BACKUP_PROG archive '$backuparchive'"
e8a0f5
 ProgressStart "Preparing archive operation"
e8a0f5
 (
e8a0f5
 case "$(basename ${BACKUP_PROG})" in
e8a0f5
-	# tar compatible programs here
e8a0f5
-	(tar)
e8a0f5
-		set_tar_features
e8a0f5
-		Log $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \
e8a0f5
-			--no-wildcards-match-slash --one-file-system \
e8a0f5
-			--ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \
e8a0f5
-			$BACKUP_PROG_CREATE_NEWER_OPTIONS \
e8a0f5
-			${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
-			-X $TMP_DIR/backup-exclude.txt -C / -c -f - \
e8a0f5
-			$(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $BACKUP_PROG_CRYPT_OPTIONS BACKUP_PROG_CRYPT_KEY \| $SPLIT_COMMAND
e8a0f5
-		$BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \
e8a0f5
-			--no-wildcards-match-slash --one-file-system \
e8a0f5
-			--ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \
e8a0f5
-			$BACKUP_PROG_CREATE_NEWER_OPTIONS \
e8a0f5
-			${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
-			-X $TMP_DIR/backup-exclude.txt -C / -c -f - \
e8a0f5
-			$(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | $BACKUP_PROG_CRYPT_OPTIONS $BACKUP_PROG_CRYPT_KEY | $SPLIT_COMMAND
e8a0f5
-	;;
e8a0f5
-	(rsync)
e8a0f5
-		# make sure that the target is a directory
e8a0f5
-		mkdir -p $v "$backuparchive" >&2
e8a0f5
-		Log $BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \
e8a0f5
-			--exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \
e8a0f5
-			$(cat $TMP_DIR/backup-include.txt) "$backuparchive"
e8a0f5
-		$BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \
e8a0f5
-			--exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \
e8a0f5
-			$(cat $TMP_DIR/backup-include.txt) "$backuparchive" >&2
e8a0f5
-	;;
e8a0f5
-	(*)
e8a0f5
-		Log "Using unsupported backup program '$BACKUP_PROG'"
e8a0f5
-		Log $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
-			$BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \
e8a0f5
-			"${BACKUP_PROG_OPTIONS[@]}" $backuparchive \
e8a0f5
-			$(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > $backuparchive
e8a0f5
-		$BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
-			$BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \
e8a0f5
-			"${BACKUP_PROG_OPTIONS[@]}" $backuparchive \
e8a0f5
-			$(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > $backuparchive
e8a0f5
-	;;
e8a0f5
+    # tar compatible programs here
e8a0f5
+    (tar)
e8a0f5
+        set_tar_features
e8a0f5
+        Log $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \
e8a0f5
+            --no-wildcards-match-slash --one-file-system \
e8a0f5
+            --ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \
e8a0f5
+            $BACKUP_PROG_CREATE_NEWER_OPTIONS \
e8a0f5
+            ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
+            -X $TMP_DIR/backup-exclude.txt -C / -c -f - \
e8a0f5
+            $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $BACKUP_PROG_CRYPT_OPTIONS BACKUP_PROG_CRYPT_KEY \| $SPLIT_COMMAND
e8a0f5
+
e8a0f5
+        # Variable used to record the short name of piped commands in case of
e8a0f5
+        # error, e.g. ( "tar" "cat" "dd" ) in case of unencrypted and unsplit backup.
e8a0f5
+        backup_prog_shortnames=(
e8a0f5
+            "$(basename $(echo "$BACKUP_PROG" | awk '{ print $1 }'))"
e8a0f5
+            "$(basename $(echo "$BACKUP_PROG_CRYPT_OPTIONS" | awk '{ print $1 }'))"
e8a0f5
+            "$(basename $(echo "$SPLIT_COMMAND" | awk '{ print $1 }'))"
e8a0f5
+        )
e8a0f5
+        for index in ${!backup_prog_shortnames[@]} ; do
e8a0f5
+            [ -n "${backup_prog_shortnames[$index]}" ] || BugError "No computed shortname for pipe component $index"
e8a0f5
+        done
e8a0f5
+
e8a0f5
+        $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose    \
e8a0f5
+            --no-wildcards-match-slash --one-file-system                        \
e8a0f5
+            --ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}"                    \
e8a0f5
+            $BACKUP_PROG_CREATE_NEWER_OPTIONS                                   \
e8a0f5
+            ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS}                       \
e8a0f5
+            "${BACKUP_PROG_COMPRESS_OPTIONS[@]}"                                \
e8a0f5
+            -X $TMP_DIR/backup-exclude.txt -C / -c -f -                         \
e8a0f5
+            $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE |   \
e8a0f5
+                                                                    \
e8a0f5
+        $BACKUP_PROG_CRYPT_OPTIONS $BACKUP_PROG_CRYPT_KEY |         \
e8a0f5
+                                                                    \
e8a0f5
+        $SPLIT_COMMAND
e8a0f5
+        pipes_rc=( ${PIPESTATUS[@]} )
e8a0f5
+
e8a0f5
+        # Exit code logic:
e8a0f5
+        # - never return rc=1 (this is reserved for "tar" warning about modified files)
e8a0f5
+        # - process exit code in pipe's reverse order
e8a0f5
+        #   - if last command failed (e.g. "dd"), return an error
e8a0f5
+        #   - otherwise if previous command failed (e.g. "encrypt"), return an error
e8a0f5
+        #   ...
e8a0f5
+        #   - otherwise return "tar" exit code
e8a0f5
+        #
e8a0f5
+        # When an error occurs, record the program name in $FAILING_BACKUP_PROG_FILE
e8a0f5
+        # and real exit code in $FAILING_BACKUP_PROG_RC_FILE.
e8a0f5
+
e8a0f5
+        let index=${#pipes_rc[@]}-1
e8a0f5
+        while [ $index -ge 0 ] ; do
e8a0f5
+            rc=${pipes_rc[$index]}
e8a0f5
+            if [ $rc -ne 0 ] ; then
e8a0f5
+                echo "${backup_prog_shortnames[$index]}" > $FAILING_BACKUP_PROG_FILE
e8a0f5
+                echo "$rc" > $FAILING_BACKUP_PROG_RC_FILE
e8a0f5
+                if [ $rc -eq 1 ] && [ "${backup_prog_shortnames[$index]}" != "tar" ] ; then
e8a0f5
+                    rc=2
e8a0f5
+                fi
e8a0f5
+                exit $rc
e8a0f5
+            fi
e8a0f5
+            # This pipe command succeeded, check the previous one
e8a0f5
+            let index--
e8a0f5
+        done
e8a0f5
+        # This was a success
e8a0f5
+        exit 0
e8a0f5
+    ;;
e8a0f5
+    (rsync)
e8a0f5
+        # make sure that the target is a directory
e8a0f5
+        mkdir -p $v "$backuparchive" >&2
e8a0f5
+        Log $BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \
e8a0f5
+            --exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \
e8a0f5
+            $(cat $TMP_DIR/backup-include.txt) "$backuparchive"
e8a0f5
+        $BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \
e8a0f5
+            --exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \
e8a0f5
+            $(cat $TMP_DIR/backup-include.txt) "$backuparchive" >&2
e8a0f5
+    ;;
e8a0f5
+    (*)
e8a0f5
+        Log "Using unsupported backup program '$BACKUP_PROG'"
e8a0f5
+        Log $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
+            $BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \
e8a0f5
+            "${BACKUP_PROG_OPTIONS[@]}" $backuparchive \
e8a0f5
+            $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > $backuparchive
e8a0f5
+        $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \
e8a0f5
+            $BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \
e8a0f5
+            "${BACKUP_PROG_OPTIONS[@]}" $backuparchive \
e8a0f5
+            $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > $backuparchive
e8a0f5
+    ;;
e8a0f5
 esac 2> "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log"
e8a0f5
 # important trick: the backup prog is the last in each case entry and the case .. esac is the last command
e8a0f5
 # in the (..) subshell. As a result the return code of the subshell is the return code of the backup prog!
e8a0f5
@@ -121,44 +171,44 @@ sleep 1 # Give the backup software a good chance to start working
e8a0f5
 
e8a0f5
 # return disk usage in bytes
e8a0f5
 function get_disk_used() {
e8a0f5
-	let "$(stat -f -c 'used=(%b-%f)*%S' $1)"
e8a0f5
-	echo $used
e8a0f5
+    let "$(stat -f -c 'used=(%b-%f)*%S' $1)"
e8a0f5
+    echo $used
e8a0f5
 }
e8a0f5
 
e8a0f5
 # While the backup runs in a sub-process, display some progress information to the user.
e8a0f5
 # ProgressInfo texts have a space at the end to get the 'OK' from ProgressStop shown separated.
e8a0f5
 test "$PROGRESS_WAIT_SECONDS" || PROGRESS_WAIT_SECONDS=1
e8a0f5
 case "$( basename $BACKUP_PROG )" in
e8a0f5
-	(tar)
e8a0f5
-		while sleep $PROGRESS_WAIT_SECONDS ; kill -0 $BackupPID 2>/dev/null; do
e8a0f5
-			#blocks="$(stat -c %b ${backuparchive})"
e8a0f5
-			#size="$((blocks*512))"
e8a0f5
-			size="$(stat -c %s ${backuparchive}* | awk '{s+=$1} END {print s}')"
e8a0f5
-			ProgressInfo "Archived $((size/1024/1024)) MiB [avg $((size/1024/(SECONDS-starttime))) KiB/sec] "
e8a0f5
-		done
e8a0f5
-		;;
e8a0f5
-	(rsync)
e8a0f5
-		# since we do not want to do a $(du -s) run every second we count disk usage instead
e8a0f5
-		# this obviously leads to wrong results in case something else is writing to the same
e8a0f5
-		# disk at the same time as is very likely with a networked file system. For local disks
e8a0f5
-		# this should be good enough and in any case this is only some eye candy.
e8a0f5
-		# TODO: Find a fast way to count the actual transfer data, preferrable getting the info from rsync.
e8a0f5
-		let old_disk_used="$(get_disk_used "$backuparchive")"
e8a0f5
-		while sleep $PROGRESS_WAIT_SECONDS ; kill -0 $BackupPID 2>/dev/null; do
e8a0f5
-			let disk_used="$(get_disk_used "$backuparchive")" size=disk_used-old_disk_used
e8a0f5
-			ProgressInfo "Archived $((size/1024/1024)) MiB [avg $((size/1024/(SECONDS-starttime))) KiB/sec] "
e8a0f5
-		done
e8a0f5
-		;;
e8a0f5
-	(*)
e8a0f5
-		while sleep $PROGRESS_WAIT_SECONDS ; kill -0 $BackupPID 2>/dev/null; do
e8a0f5
-			size="$(stat -c "%s" "$backuparchive")" || {
e8a0f5
-				kill -9 $BackupPID
e8a0f5
-				ProgressError
e8a0f5
-				Error "$(basename $BACKUP_PROG) failed to create the archive file"
e8a0f5
-			}
e8a0f5
-			ProgressInfo "Archived $((size/1024/1024)) MiB [avg $((size/1024/(SECONDS-starttime))) KiB/sec] "
e8a0f5
-		done
e8a0f5
-		;;
e8a0f5
+    (tar)
e8a0f5
+        while sleep $PROGRESS_WAIT_SECONDS ; kill -0 $BackupPID 2>/dev/null; do
e8a0f5
+            #blocks="$(stat -c %b ${backuparchive})"
e8a0f5
+            #size="$((blocks*512))"
e8a0f5
+            size="$(stat -c %s ${backuparchive}* | awk '{s+=$1} END {print s}')"
e8a0f5
+            ProgressInfo "Archived $((size/1024/1024)) MiB [avg $((size/1024/(SECONDS-starttime))) KiB/sec] "
e8a0f5
+        done
e8a0f5
+        ;;
e8a0f5
+    (rsync)
e8a0f5
+        # since we do not want to do a $(du -s) run every second we count disk usage instead
e8a0f5
+        # this obviously leads to wrong results in case something else is writing to the same
e8a0f5
+        # disk at the same time as is very likely with a networked file system. For local disks
e8a0f5
+        # this should be good enough and in any case this is only some eye candy.
e8a0f5
+        # TODO: Find a fast way to count the actual transfer data, preferrable getting the info from rsync.
e8a0f5
+        let old_disk_used="$(get_disk_used "$backuparchive")"
e8a0f5
+        while sleep $PROGRESS_WAIT_SECONDS ; kill -0 $BackupPID 2>/dev/null; do
e8a0f5
+            let disk_used="$(get_disk_used "$backuparchive")" size=disk_used-old_disk_used
e8a0f5
+            ProgressInfo "Archived $((size/1024/1024)) MiB [avg $((size/1024/(SECONDS-starttime))) KiB/sec] "
e8a0f5
+        done
e8a0f5
+        ;;
e8a0f5
+    (*)
e8a0f5
+        while sleep $PROGRESS_WAIT_SECONDS ; kill -0 $BackupPID 2>/dev/null; do
e8a0f5
+            size="$(stat -c "%s" "$backuparchive")" || {
e8a0f5
+                kill -9 $BackupPID
e8a0f5
+                ProgressError
e8a0f5
+                Error "$(basename $BACKUP_PROG) failed to create the archive file"
e8a0f5
+            }
e8a0f5
+            ProgressInfo "Archived $((size/1024/1024)) MiB [avg $((size/1024/(SECONDS-starttime))) KiB/sec] "
e8a0f5
+        done
e8a0f5
+        ;;
e8a0f5
 esac
e8a0f5
 ProgressStop
e8a0f5
 transfertime="$((SECONDS-starttime))"
e8a0f5
@@ -177,10 +227,12 @@ sleep 1
e8a0f5
 # everyone should see this warning, even if not verbose
e8a0f5
 case "$(basename $BACKUP_PROG)" in
e8a0f5
     (tar)
e8a0f5
-        if (( $backup_prog_rc == 1 )); then
e8a0f5
-            LogPrint "WARNING: $(basename $BACKUP_PROG) ended with return code $backup_prog_rc and below output:
e8a0f5
+        if (( $backup_prog_rc != 0 )); then
e8a0f5
+            prog="$(cat $FAILING_BACKUP_PROG_FILE)"
e8a0f5
+            if (( $backup_prog_rc == 1 )); then
e8a0f5
+                LogUserOutput "WARNING: $prog ended with return code 1 and below output:
e8a0f5
   ---snip---
e8a0f5
-$(grep '^tar: ' $RUNTIME_LOGFILE | sed -e 's/^/  /' | tail -n3)
e8a0f5
+$(grep '^tar: ' "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log" | sed -e 's/^/  /' | tail -n3)
e8a0f5
   ----------
e8a0f5
 This means that files have been modified during the archiving
e8a0f5
 process. As a result the backup may not be completely consistent
e8a0f5
@@ -188,16 +240,19 @@ or may not be a perfect copy of the system. Relax-and-Recover
e8a0f5
 will continue, however it is highly advisable to verify the
e8a0f5
 backup in order to be sure to safely recover this system.
e8a0f5
 "
e8a0f5
-        elif (( $backup_prog_rc > 1 )); then
e8a0f5
-            Error "$(basename $BACKUP_PROG) failed with return code $backup_prog_rc and below output:
e8a0f5
+            else
e8a0f5
+                rc=$(cat $FAILING_BACKUP_PROG_RC_FILE)
e8a0f5
+                Error "$prog failed with return code $rc and below output:
e8a0f5
   ---snip---
e8a0f5
-$(grep '^tar: ' $RUNTIME_LOGFILE | sed -e 's/^/  /' | tail -n3)
e8a0f5
+$(grep "^$prog: " "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log" | sed -e 's/^/  /' | tail -n3)
e8a0f5
   ----------
e8a0f5
 This means that the archiving process ended prematurely, or did
e8a0f5
 not even start. As a result it is unlikely you can recover this
e8a0f5
 system properly. Relax-and-Recover is therefore aborting execution.
e8a0f5
 "
e8a0f5
-        fi;;
e8a0f5
+            fi
e8a0f5
+        fi
e8a0f5
+        ;;
e8a0f5
     (*)
e8a0f5
         if (( $backup_prog_rc > 0 )) ; then
e8a0f5
             Error "$(basename $BACKUP_PROG) failed with return code $backup_prog_rc
e8a0f5
@@ -212,10 +267,12 @@ esac
e8a0f5
 
e8a0f5
 tar_message="$(tac $RUNTIME_LOGFILE | grep -m1 '^Total bytes written: ')"
e8a0f5
 if [ $backup_prog_rc -eq 0 -a "$tar_message" ] ; then
e8a0f5
-	LogPrint "$tar_message in $transfertime seconds."
e8a0f5
+    LogPrint "$tar_message in $transfertime seconds."
e8a0f5
 elif [ "$size" ]; then
e8a0f5
-	LogPrint "Archived $((size/1024/1024)) MiB in $((transfertime)) seconds [avg $((size/1024/transfertime)) KiB/sec]"
e8a0f5
+    LogPrint "Archived $((size/1024/1024)) MiB in $((transfertime)) seconds [avg $((size/1024/transfertime)) KiB/sec]"
e8a0f5
 fi
e8a0f5
 
e8a0f5
 ### Copy progress log to backup media
e8a0f5
 cp $v "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log" "${opath}/${BACKUP_PROG_ARCHIVE}.log" >&2
e8a0f5
+
e8a0f5
+# vim: set et ts=4 sw=4: