commit d6b50fc6c7d81f5908e1f6a611d59000fd475c0e Author: MSVSphere Packaging Team Date: Tue Nov 26 19:09:05 2024 +0300 import rear-2.7-12.el10 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a19ef3a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/rear-2.7-clean.tar.gz diff --git a/.rear.metadata b/.rear.metadata new file mode 100644 index 0000000..614145b --- /dev/null +++ b/.rear.metadata @@ -0,0 +1 @@ +b6bcabf45fc7855bfb23caf150c654e0d81d5beb SOURCES/rear-2.7-clean.tar.gz diff --git a/SOURCES/Makefile b/SOURCES/Makefile new file mode 100644 index 0000000..f99d1e0 --- /dev/null +++ b/SOURCES/Makefile @@ -0,0 +1,3 @@ +rear-%-clean.tar.gz: rear-%.tar.gz + set -o pipefail; gunzip -c $< | tar --delete "rear-"$*"/doc/rear-release-notes.txt" -f - | gzip -c - > $@.tmp + mv $@.tmp $@ diff --git a/SOURCES/rear-CVE-2024-23301.patch b/SOURCES/rear-CVE-2024-23301.patch new file mode 100644 index 0000000..1361f52 --- /dev/null +++ b/SOURCES/rear-CVE-2024-23301.patch @@ -0,0 +1,32 @@ +From 89b61793d80bc2cb2abe47a7d0549466fb087d16 Mon Sep 17 00:00:00 2001 +From: Johannes Meixner +Date: Fri, 12 Jan 2024 08:04:40 +0100 +Subject: [PATCH] Make initrd accessible only by root (#3123) + +In pack/GNU/Linux/900_create_initramfs.sh call +chmod 0600 "$TMP_DIR/$REAR_INITRD_FILENAME" +to let only 'root' access the ReaR initrd because +the ReaR recovery system in the initrd can contain secrets +(not by default but when certain things are explicitly +configured by the user like SSH keys without passphrase) +see https://github.com/rear/rear/issues/3122 +and https://bugzilla.opensuse.org/show_bug.cgi?id=1218728 +--- + usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh b/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh +index 1e0c11039..12be718ed 100644 +--- a/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh ++++ b/usr/share/rear/pack/GNU/Linux/900_create_initramfs.sh +@@ -125,4 +125,10 @@ case "$REAR_INITRD_COMPRESSION" in + fi + ;; + esac ++ ++# Only root should be allowed to access the initrd ++# because the ReaR recovery system can contain secrets ++# cf. https://github.com/rear/rear/issues/3122 ++test -s "$TMP_DIR/$REAR_INITRD_FILENAME" && chmod 0600 "$TMP_DIR/$REAR_INITRD_FILENAME" ++ + popd >/dev/null diff --git a/SOURCES/rear-bz1492177-warning.patch b/SOURCES/rear-bz1492177-warning.patch new file mode 100644 index 0000000..1f5556f --- /dev/null +++ b/SOURCES/rear-bz1492177-warning.patch @@ -0,0 +1,15 @@ +diff --git a/usr/share/rear/output/ISO/Linux-i386/249_check_rhel_grub2_efi_package.sh b/usr/share/rear/output/ISO/Linux-i386/249_check_rhel_grub2_efi_package.sh +new file mode 100644 +index 00000000..4c4ded08 +--- /dev/null ++++ b/usr/share/rear/output/ISO/Linux-i386/249_check_rhel_grub2_efi_package.sh +@@ -0,0 +1,9 @@ ++# 249_check_rhel_grub2_efi_package.sh ++ ++is_true $USING_UEFI_BOOTLOADER || return # empty or 0 means NO UEFI ++ ++( ++ VERBOSE=1 ++ test -r /usr/lib/grub/x86_64-efi/moddep.lst ++ PrintIfError "WARNING: /usr/lib/grub/x86_64-efi/moddep.lst not found, grub2-mkimage will likely fail. Please install the grub2-efi-x64-modules package to fix this." ++) diff --git a/SOURCES/rear-bz1747468.patch b/SOURCES/rear-bz1747468.patch new file mode 100644 index 0000000..a417f96 --- /dev/null +++ b/SOURCES/rear-bz1747468.patch @@ -0,0 +1,99 @@ +From 5d5d1db3ca621eb80b9481924d1fc470571cfc09 Mon Sep 17 00:00:00 2001 +From: Pavel Cahyna +Date: Mon, 30 Aug 2021 12:00:43 +0200 +Subject: [PATCH] Avoid vgcfgrestore on thin volumes/pools + +and any other unsupported volume types. + +vgcfgrestore is not supposed to be able to restore any logical volumes +that use kernel metadata. All volume types except linear and striped use +kernel metadata. Main purpose of vgcfgrestore (with mandatory --force +option) is to let users fix existing thin-pool, not to recreate the pool +on empty disks. Do not even try vgcfgrestore on VGs that need any kernel +metadata, because it might lead to an inconsistent state (if there are +data that the kernel might interpret as LV metadata present on the disks). + +For VGs that have any volume with kernel metadata and are thus +unsupported by vgcfgrestore, switch automatically to LV creation using +lvcreate, similarly to MIGRATION_MODE. + +Avoid vgcfgrestore --force entirely, since it should not be needed now. + +This mostly reverts changes in commits +311bfb3da1d5e47a2ff144123a2457e634f67893 and +1b779abfbf56693877fe666f56253ec623599674. The former code is preserved +and gets enabled if FORCE_VGCFGRESTORE=y. This option is on purpose +undocumented though and may be removed in the future. +--- + .../prepare/GNU/Linux/110_include_lvm_code.sh | 8 +++++- + usr/share/rear/lib/layout-functions.sh | 26 +++++++++++++++++++ + 2 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh +index 5babce228..54a55e688 100644 +--- a/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh ++++ b/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh +@@ -83,7 +83,7 @@ EOF + # '--mirrorlog', etc. + # Also, we likely do not support every layout yet (e.g. 'cachepool'). + +- if ! is_true "$MIGRATION_MODE" ; then ++ if ! is_true "$MIGRATION_MODE" && lvmgrp_supports_vgcfgrestore "$vgrp" ; then + cat >> "$LAYOUT_CODE" <&2 ; then + create_volume_group=( \$( RmInArray "$vg" "\${create_volume_group[@]}" ) ) + create_logical_volumes=( \$( RmInArray "$vg" "\${create_logical_volumes[@]}" ) ) + ++EOF ++ if is_true "${FORCE_VGCFGRESTORE-no}"; then ++ cat >> "$LAYOUT_CODE" <&2 ; then + create_volume_group=( \$( RmInArray "$vg" "\${create_volume_group[@]}" ) ) + create_thin_volumes_only+=( "$vg" ) + ++EOF ++ fi ++ cat >> "$LAYOUT_CODE" < in the first argument) ++# doesn't contain any LVs that use kernel metadata. ++# If the function returns true, we can safely use vgcfgrestore to restore the VG. ++function lvmgrp_supports_vgcfgrestore() { ++ if is_true "${FORCE_VGCFGRESTORE-no}"; then ++ # If we are willing to use vgcfgrestore --force and then remove broken volumes, ++ # then everything can be considered supported. Don't do it by default though. ++ return 0 ++ fi ++ ++ local lvmvol vgrp lvname size layout kval ++ ++ local supported_layouts=("linear" "striped") ++ ++ while read lvmvol vgrp lvname size layout kval; do ++ [ "$vgrp" == "$1" ] || BugError "vgrp '$vgrp' != '$1'" ++ if ! IsInArray $layout "${supported_layouts[@]}"; then ++ LogPrint "Layout '$layout' of LV '$lvname' in VG '$vgrp' not supported by vgcfgrestore" ++ return 1 ++ fi ++ done < <(grep "^lvmvol $1 " "$LAYOUT_FILE") ++} ++ + # vim: set et ts=4 sw=4: diff --git a/SOURCES/rear-bz2091163.patch b/SOURCES/rear-bz2091163.patch new file mode 100644 index 0000000..991a147 --- /dev/null +++ b/SOURCES/rear-bz2091163.patch @@ -0,0 +1,76 @@ +From 29e739ae7c0651f8f77c60846bfbe2b6c91baa29 Mon Sep 17 00:00:00 2001 +From: Pavel Cahyna +Date: Sat, 31 Dec 2022 17:40:39 +0100 +Subject: [PATCH] Protect against colons in pvdisplay output + +LVM can be configured to show device names under /dev/disk/by-path +in command output. These names often contain colons that separate fields +like channel and target (for example /dev/disk/by-path/pci-*-scsi-0:0:1:0-*, +similarly the pci-* part, which contains colon-separated PCI bus and +device numbers). Since the "pvdisplay -c" output also uses colons as +field separators and does not escape embedded colons in any way, +embedded colons break parsing of this output. + +As a fix, use the pipe character '|' as the field separator in pvdisplay +output. (This would break if a PV device has a '|' in its name, but this +is very much less likely than having a ':' .) + +Also, configure explicitly what fields to output - "pvdisplay -c" +prints many fields, but I have not found documentation about what fields +is it using exactly, so one had to guess what the output means. Using +"pvdisplay -C" and selecting the fields explicitly is much clearer. + +This also changes the PV size field to match documentation, the comment +says that size is in bytes, but it actually was not in bytes. As nothing +is actually using the PV size field, this inconsistency has not caused +any problem in practice, and no code needs adjusting for the change. +--- + .../layout/save/GNU/Linux/220_lvm_layout.sh | 24 ++++++++++++------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh +index e01dbf465..7400c586e 100644 +--- a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh ++++ b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh +@@ -70,14 +70,20 @@ local lvs_exit_code + # Get physical_device configuration. + # Format: lvmdev [] [] + header_printed="no" +- # Example output of "lvm pvdisplay -c": +- # /dev/sda1:system:41940992:-1:8:8:-1:4096:5119:2:5117:7wwpcO-KmNN-qsTE-7sp7-JBJS-vBdC-Zyt1W7 ++ # Set pvdisplay separator to '|' to prevent issues with a colon in the path under /dev/disk/by-path ++ # that contains a ':' in the SCSI slot name. ++ # Example output of "lvm pvdisplay -C --separator '|' --noheadings --nosuffix --units=b -o pv_name,vg_name,pv_size,pv_uuid" ++ # on a system where LVM is configured to show the /dev/disk/by-path device names instead of the usual ++ # /dev/sda etc. (by using a setting like ++ # filter = [ "r|/dev/disk/by-path/.*-usb-|", "a|/dev/disk/by-path/pci-.*-nvme-|", "a|/dev/disk/by-path/pci-.*-scsi-|", "a|/dev/disk/by-path/pci-.*-ata-|", "a|/dev/disk/by-path/pci-.*-sas-|", "a|loop|", "r|.*|" ] ++ # in /etc/lvm/lvm.conf): ++ # /dev/disk/by-path/pci-0000:03:00.0-scsi-0:0:1:0-part1|system|107340627968|7wwpcO-KmNN-qsTE-7sp7-JBJS-vBdC-Zyt1W7 + # There are two leading blanks in the output (at least on SLES12-SP4 with LVM 2.02.180). +- lvm pvdisplay -c | while read line ; do ++ lvm pvdisplay -C --separator '|' --noheadings --nosuffix --units=b -o pv_name,vg_name,pv_size,pv_uuid | while read line ; do + +- # With the above example pdev=/dev/sda1 ++ # With the above example pdev=/dev/disk/by-path/pci-0000:03:00.0-scsi-0:0:1:0-part1 + # (the "echo $line" makes the leading blanks disappear) +- pdev=$( echo $line | cut -d ":" -f "1" ) ++ pdev=$( echo $line | cut -d "|" -f "1" ) + + # Skip lines that are not describing physical devices + # i.e. lines where pdev does not start with a leading / character: +@@ -91,11 +97,11 @@ local lvs_exit_code + fi + + # With the above example vgrp=system +- vgrp=$( echo $line | cut -d ":" -f "2" ) +- # With the above example size=41940992 +- size=$( echo $line | cut -d ":" -f "3" ) ++ vgrp=$( echo $line | cut -d "|" -f "2" ) ++ # With the above example size=107340627968 ++ size=$( echo $line | cut -d "|" -f "3" ) + # With the above example uuid=7wwpcO-KmNN-qsTE-7sp7-JBJS-vBdC-Zyt1W7 +- uuid=$( echo $line | cut -d ":" -f "12" ) ++ uuid=$( echo $line | cut -d "|" -f "4" ) + + # Translate pdev through diskbyid_mappings file: + pdev=$( get_device_mapping $pdev ) diff --git a/SOURCES/rear-bz2104005.patch b/SOURCES/rear-bz2104005.patch new file mode 100644 index 0000000..b3159e9 --- /dev/null +++ b/SOURCES/rear-bz2104005.patch @@ -0,0 +1,60 @@ +commit bca0e7a92af16cb7fb82ef04401cdb3286068081 +Merge: d2d2300b f36bfe9b +Author: pcahyna +Date: Thu Jul 28 12:11:04 2022 +0200 + + Merge pull request #2839 from pcahyna/lvm-y + + Pass -y to lvcreate instead of piping the output of yes + +diff --git a/usr/share/rear/conf/GNU/Linux.conf b/usr/share/rear/conf/GNU/Linux.conf +index 82007719..7e47b912 100644 +--- a/usr/share/rear/conf/GNU/Linux.conf ++++ b/usr/share/rear/conf/GNU/Linux.conf +@@ -5,7 +5,7 @@ ip + less + parted + readlink +-# For noninteractive confirmation in lvm commands during layout recreation ++# For noninteractive confirmation in commands + yes + ) + +diff --git a/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh +index 0bd863ac..6089cc09 100644 +--- a/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh ++++ b/usr/share/rear/layout/prepare/GNU/Linux/110_include_lvm_code.sh +@@ -287,28 +287,16 @@ create_lvmvol() { + # so e.g. 'lvcreate -L 123456b -n LV VG' becomes 'lvcreate -l 100%FREE -n LV VG' + fallbacklvopts="$( sed -e 's/-L [0-9b]*/-l 100%FREE/' <<< "$lvopts" )" + +- # In SLES11 "man lvcreate" does not show '-y' or '--yes' +- # so we cannot use "lvm lvcreate -y ..." +- # see https://github.com/rear/rear/issues/2820#issuecomment-1161934013 +- # instead we input as many 'y' as asked for by "lvm lvcreate" +- # see https://github.com/rear/rear/issues/513 +- # and https://github.com/rear/rear/issues/2820 +- # plus be safe against possible 'set -o pipefail' non-zero exit code of 'yes' via '( yes || true ) | ...' +- # see https://github.com/rear/rear/issues/2820#issuecomment-1162804476 +- # because 'yes' may get terminated by SIGPIPE when plain 'yes | ...' is used +- # see https://github.com/rear/rear/issues/2820#issuecomment-1162772415 +- # and suppress needless "yes: standard output: Broken pipe" stderr messages +- # that appear at least with newer 'yes' in coreutils-8.32 in openSUSE Leap 15.3 + cat >> "$LAYOUT_CODE" </dev/null || true ) | lvm lvcreate $lvopts $vg ; then +- LogPrintError "Failed to create LVM volume '$vg/$lvname' with lvcreate $lvopts $vg" +- if ( yes 2>/dev/null || true ) | lvm lvcreate $fallbacklvopts $vg ; then +- LogPrintError "Created LVM volume '$vg/$lvname' using fallback options lvcreate $fallbacklvopts $vg" ++ if ! lvm lvcreate -y $lvopts $vg ; then ++ LogPrintError "Failed to create LVM volume '$vg/$lvname' with lvcreate -y $lvopts $vg" ++ if lvm lvcreate -y $fallbacklvopts $vg ; then ++ LogPrintError "Created LVM volume '$vg/$lvname' using fallback options lvcreate -y $fallbacklvopts $vg" + else +- LogPrintError "Also failed to create LVM volume '$vg/$lvname' with lvcreate $fallbacklvopts $vg" ++ LogPrintError "Also failed to create LVM volume '$vg/$lvname' with lvcreate -y $fallbacklvopts $vg" + # Explicit 'false' is needed to let the whole 'if then else fi' command exit with non zero exit state + # to let diskrestore.sh abort here as usual when a command fails (diskrestore.sh runs with 'set -e'): + false diff --git a/SOURCES/rear-bz2119501.patch b/SOURCES/rear-bz2119501.patch new file mode 100644 index 0000000..21e3253 --- /dev/null +++ b/SOURCES/rear-bz2119501.patch @@ -0,0 +1,39 @@ +diff --git a/usr/share/rear/build/default/490_fix_broken_links.sh b/usr/share/rear/build/default/490_fix_broken_links.sh +index 5bace664..cf960be8 100644 +--- a/usr/share/rear/build/default/490_fix_broken_links.sh ++++ b/usr/share/rear/build/default/490_fix_broken_links.sh +@@ -7,6 +7,23 @@ + # see https://github.com/rear/rear/issues/1638 + # and https://github.com/rear/rear/pull/1734 + ++# Some broken symlinks are expected. The 'build' and 'source' symlinks in kernel modules point to kernel sources ++# and are broken until one installs the kernel-debug-devel or kernel-devel packages (on Fedora) and even then ++# the targets are not included in the rescue system by default. ++# Do not warn about those, it is just noise. ++local irrelevant_symlinks=( '*/lib/modules/*/build' '*/lib/modules/*/source' ) ++function symlink_is_irrelevant () { ++ for i in "${irrelevant_symlinks[@]}"; do ++ # do not quote $i, it is a glob pattern, matching will be performed by [[ ... == ... ]] ++ # quoting inside [[ ]] prevents pattern matching ++ if [[ "$1" == $i ]]; then ++ return 0 ++ fi ++ done ++ return 1 ++} ++ ++ + # FIXME: The following code fails if symlinks or their targets contain characters from IFS (e.g. blanks), + # cf. the same kind of comments in build/default/990_verify_rootfs.sh + # and layout/prepare/GNU/Linux/130_include_mount_subvolumes_code.sh +@@ -38,6 +55,10 @@ pushd $ROOTFS_DIR + local broken_symlink='' + local link_target='' + for broken_symlink in $broken_symlinks ; do ++ if symlink_is_irrelevant "$broken_symlink" ; then ++ DebugPrint "Ignoring irrelevant broken symlink $broken_symlink" ++ continue ++ fi + # For each broken symlink absolute path inside ROOTFS_DIR + # we call "readlink -e" in the original system to get its link target there. + # If in the original system there was a chain of symbolic links like diff --git a/SOURCES/rear-bz2120736.patch b/SOURCES/rear-bz2120736.patch new file mode 100644 index 0000000..8bcce79 --- /dev/null +++ b/SOURCES/rear-bz2120736.patch @@ -0,0 +1,18 @@ +diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf +index b14525da..23a83b71 100644 +--- a/usr/share/rear/conf/default.conf ++++ b/usr/share/rear/conf/default.conf +@@ -1841,10 +1841,10 @@ OBDR_BLOCKSIZE=2048 + # BACKUP=NBU stuff (Symantec/Veritas NetBackup) + ## + # +-COPY_AS_IS_NBU=( /usr/openv/bin/vnetd /usr/openv/bin/vopied /usr/openv/lib /usr/openv/netbackup /usr/openv/var/auth/[mn]*.txt /opt/VRTSpbx /etc/vx/VxICS /etc/vx/vrtslog.conf ) +-COPY_AS_IS_EXCLUDE_NBU=( /usr/openv/netbackup/logs "/usr/openv/netbackup/bin/bpjava*" /usr/openv/netbackup/bin/xbp /usr/openv/netbackup/bin/private /usr/openv/lib/java /usr/openv/lib/shared/vddk /usr/openv/netbackup/baremetal ) ++COPY_AS_IS_NBU=( /usr/openv/bin/vnetd /usr/openv/bin/vopied /usr/openv/lib /usr/openv/netbackup /usr/openv/var/auth/[mn]*.txt /usr/openv/var/vxss /usr/openv/var/webtruststore /usr/openv/resources/nbpxyhelper /opt/VRTSpbx /etc/vx/VxICS /etc/vx/vrtslog.conf /var/log/VRTSpbx ) ++COPY_AS_IS_EXCLUDE_NBU=( "/usr/openv/netbackup/logs/*" "/usr/openv/netbackup/bin/bpjava*" /usr/openv/netbackup/bin/xbp /usr/openv/netbackup/bin/private /usr/openv/lib/java "/usr/openv/lib/*-plugins" /usr/openv/lib/shared/vddk /usr/openv/netbackup/baremetal "/var/log/VRTSpbx/*" ) + # See https://github.com/rear/rear/issues/2105 why /usr/openv/netbackup/sec/at/lib/ is needed: +-NBU_LD_LIBRARY_PATH="/usr/openv/lib:/usr/openv/netbackup/sec/at/lib/" ++NBU_LD_LIBRARY_PATH="/usr/openv/lib:/usr/openv/netbackup/sec/at/lib/:/usr/openv/lib/boost" + PROGS_NBU=( ) + + ## diff --git a/SOURCES/rear-bz2130945.patch b/SOURCES/rear-bz2130945.patch new file mode 100644 index 0000000..9d19586 --- /dev/null +++ b/SOURCES/rear-bz2130945.patch @@ -0,0 +1,41 @@ +From 6d1e5ab96213a0d79489c4296cd1f5a4be645597 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= +Date: Thu, 29 Sep 2022 15:32:22 +0200 +Subject: [PATCH] Fix initrd regeneration on s390x and Fedora/RHEL + +For some reason, the 550_rebuild_initramfs.sh script was not included +for s390x on Fedora/RHEL so the initrd was not regenerated after backup +restore on this architecture. + +Since all other architectures were actually using the same script, +let's just move it one level up to fix this bug and to also simplify +the directory structure a bit. +--- + .../rear/finalize/Fedora/{i386 => }/550_rebuild_initramfs.sh | 0 + usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh | 1 - + usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh | 1 - + 3 files changed, 2 deletions(-) + rename usr/share/rear/finalize/Fedora/{i386 => }/550_rebuild_initramfs.sh (100%) + delete mode 120000 usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh + delete mode 120000 usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh + +diff --git a/usr/share/rear/finalize/Fedora/i386/550_rebuild_initramfs.sh b/usr/share/rear/finalize/Fedora/550_rebuild_initramfs.sh +similarity index 100% +rename from usr/share/rear/finalize/Fedora/i386/550_rebuild_initramfs.sh +rename to usr/share/rear/finalize/Fedora/550_rebuild_initramfs.sh +diff --git a/usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh b/usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh +deleted file mode 120000 +index 22eede59d..000000000 +--- a/usr/share/rear/finalize/Fedora/ppc64/550_rebuild_initramfs.sh ++++ /dev/null +@@ -1 +0,0 @@ +-../i386/550_rebuild_initramfs.sh +\ No newline at end of file +diff --git a/usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh b/usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh +deleted file mode 120000 +index 22eede59d..000000000 +--- a/usr/share/rear/finalize/Fedora/ppc64le/550_rebuild_initramfs.sh ++++ /dev/null +@@ -1 +0,0 @@ +-../i386/550_rebuild_initramfs.sh +\ No newline at end of file diff --git a/SOURCES/rear-bz2188593-nbu-systemd.patch b/SOURCES/rear-bz2188593-nbu-systemd.patch new file mode 100644 index 0000000..24b117a --- /dev/null +++ b/SOURCES/rear-bz2188593-nbu-systemd.patch @@ -0,0 +1,440 @@ +diff --git a/usr/share/rear/rescue/NBU/default/460_prepare_netbackup_systemd.sh b/usr/share/rear/rescue/NBU/default/460_prepare_netbackup_systemd.sh +new file mode 100644 +index 00000000..f7423e0a +--- /dev/null ++++ b/usr/share/rear/rescue/NBU/default/460_prepare_netbackup_systemd.sh +@@ -0,0 +1,41 @@ ++# 460_prepare_netbackup_systemd.sh ++# prepare systemd units for NBU (only if NBU version >=7.x) ++ ++# set in 450_prepare_netbackup.sh ++[[ $NBU_version -lt 7 ]] && return # NBU is using xinetd when version <7.x ++ ++# Skip if systemd is not used. ++has_binary systemctl || return 0 ++ ++# Local functions that are 'unset' at the end of this script: ++ ++function get_unit_path () { ++ systemctl show -P FragmentPath $1 ++} ++ ++function get_unit_dropin_paths () { ++ systemctl show -P DropInPaths $1 ++} ++ ++local unit_file_path ++local i ++local unit ++ ++for unit in vxpbx_exchanged.service netbackup.service ; do ++ unit_file_path="$( get_unit_path $unit )" ++ if [ -n "$unit_file_path" ]; then ++ cp $v "$unit_file_path" $ROOTFS_DIR/etc/systemd/system ++ ln -s ../$unit $ROOTFS_DIR/etc/systemd/system/default.target.wants || Error "Failed to enable Netbackup service $unit in the rescue system" ++ Log "Enabled Netbackup service $unit in the rescue system" ++ for i in $( get_unit_dropin_paths $unit ) ; do ++ mkdir -p $ROOTFS_DIR/etc/systemd/system/$unit.d ++ cp $v $i $ROOTFS_DIR/etc/systemd/system/$unit.d ++ done ++ fi ++done ++ ++# Local functions must be 'unset' because bash does not support 'local function ...' ++# cf. https://unix.stackexchange.com/questions/104755/how-can-i-create-a-local-function-in-my-bashrc ++unset -f get_unit_path ++unset -f get_unit_dropin_paths ++unset -f unit_is_enabled +diff --git a/usr/share/rear/skel/default/etc/scripts/run-automatic-rear b/usr/share/rear/skel/default/etc/scripts/run-automatic-rear +new file mode 100755 +index 00000000..6edc657a +--- /dev/null ++++ b/usr/share/rear/skel/default/etc/scripts/run-automatic-rear +@@ -0,0 +1,82 @@ ++#!/bin/bash ++ ++source /etc/scripts/system-setup-functions.sh ++ ++# In debug mode run the automated 'rear recover' also with debug options. ++# Because the kernel command line option 'debug' means 'set -x' for the system setup scripts ++# it also means '-D' (i.e. 'set -x') for the automated 'rear recover' run: ++if rear_debug ; then ++ rear_debug_options='-D' ++else ++ rear_debug_options='' ++fi ++ ++# Launch rear recover automatically: ++if automatic_recovery ; then ++ choices=( "View Relax-and-Recover log file(s)" ++ "Go to Relax-and-Recover shell" ++ ) ++ echo -e "\nLaunching 'rear recover' automatically\n" ++ if rear $rear_debug_options recover ; then ++ echo -e "\n'rear recover' finished successfully\n" ++ choices+=( "Reboot" ) ++ else ++ echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n" ++ fi ++ PS3="Select what to do " ++ select choice in "${choices[@]}" ; do ++ case "$REPLY" in ++ (1) ++ # Do not assume the ReaR log file is named rear-$HOSTNAME.log ++ # the user can have specified any name as LOGFILE: ++ less /var/log/rear/* ++ ;; ++ (2) ++ echo "" > /etc/issue ++ echo "" > /etc/motd ++ break ++ ;; ++ (3) ++ reboot ++ ;; ++ esac ++ for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do ++ echo "$i) ${choices[$i-1]}" ++ done ++ done 2>&1 ++fi ++ ++# Launch rear recover automatically in unattended mode ++# i.e. with automated reboot after successful 'rear recover': ++if unattended_recovery ; then ++ choices=( "View Relax-and-Recover log file(s)" ++ "Go to Relax-and-Recover shell" ++ ) ++ echo -e "\nLaunching 'rear recover' automatically in unattended mode\n" ++ if rear $rear_debug_options recover ; then ++ echo -e "\n'rear recover' finished successfully\n" ++ echo -e "\nRebooting in 30 seconds (Ctrl-C to interrupt)\n" ++ sleep 30 ++ reboot ++ else ++ echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n" ++ PS3="Select what to do " ++ select choice in "${choices[@]}" ; do ++ case "$REPLY" in ++ (1) ++ # Do not assume the ReaR log file is named rear-$HOSTNAME.log ++ # the user can have specified any name as LOGFILE: ++ less /var/log/rear/* ++ ;; ++ (2) ++ echo "" > /etc/issue ++ echo "" > /etc/motd ++ break ++ ;; ++ esac ++ for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do ++ echo "$i) ${choices[$i-1]}" ++ done ++ done 2>&1 ++ fi ++fi +diff --git a/usr/share/rear/skel/default/etc/scripts/system-setup b/usr/share/rear/skel/default/etc/scripts/system-setup +index 1dc7f1e8..17487ac7 100755 +--- a/usr/share/rear/skel/default/etc/scripts/system-setup ++++ b/usr/share/rear/skel/default/etc/scripts/system-setup +@@ -9,36 +9,7 @@ + # (e.g. "ls foo*bar" becomes plain "ls" without "foo*bar: No such file or directory" error). + shopt -s nullglob + +-# Use an artificial array to get the kernel command line parameters as array elements +-kernel_command_line=( $( cat /proc/cmdline ) ) +- +-function rear_debug() { +- for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do +- test "debug" = "$kernel_command_line_parameter" && return 0 +- done +- return 1 +-} +- +-function unattended_recovery() { +- for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do +- test "unattended" = "$kernel_command_line_parameter" && return 0 +- done +- return 1 +-} +- +-function automatic_recovery() { +- # The unattended recovery mode implies automatic recovery (see the implementations below) +- # so that in unattended mode the automatic recovery code below must not be run +- # otherwise first the automatic recovery code and then the unattended recovery code +- # get run automatically one after the other where the unattended recovery fails +- # because for two subsequent 'rear recover' the second one fails: +- unattended_recovery && return 1 +- for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do +- test "auto_recover" = "$kernel_command_line_parameter" && return 0 +- test "automatic" = "$kernel_command_line_parameter" && return 0 +- done +- return 1 +-} ++source /etc/scripts/system-setup-functions.sh + + # The 'sleep 1' is used as workaround to avoid whatever inexplicable actual reason + # that at least on SLES12 some initial output lines of this script would get lost +@@ -135,84 +106,3 @@ echo -e "\nRelax-and-Recover rescue system is ready\n" + # Wait two seconds so that the user can read the 'Relax-and-Recover rescue system is ready' message + # on his screen before the screen gets cleared and replaced by the login screen: + sleep 2 +- +-# In debug mode run the automated 'rear recover' also with debug options. +-# Because the kernel command line option 'debug' means 'set -x' for the system setup scripts +-# it also means '-D' (i.e. 'set -x') for the automated 'rear recover' run: +-if rear_debug ; then +- rear_debug_options='-D' +-else +- rear_debug_options='' +-fi +- +-# Launch rear recover automatically: +-if automatic_recovery ; then +- choices=( "View Relax-and-Recover log file(s)" +- "Go to Relax-and-Recover shell" +- ) +- echo -e "\nLaunching 'rear recover' automatically\n" +- # The recover workflow is always verbose (see usr/sbin/rear): +- if rear $rear_debug_options recover ; then +- echo -e "\n'rear recover' finished successfully\n" +- choices+=( "Reboot" ) +- else +- echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n" +- fi +- PS3="Select what to do " +- select choice in "${choices[@]}" ; do +- case "$REPLY" in +- (1) +- # Do not assume the ReaR log file is named rear-$HOSTNAME.log +- # the user can have specified any name as LOGFILE: +- less /var/log/rear/* +- ;; +- (2) +- echo "" > /etc/issue +- echo "" > /etc/motd +- break +- ;; +- (3) +- reboot +- ;; +- esac +- for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do +- echo "$i) ${choices[$i-1]}" +- done +- done 2>&1 +-fi +- +-# Launch rear recover automatically in unattended mode +-# i.e. with automated reboot after successful 'rear recover': +-if unattended_recovery ; then +- choices=( "View Relax-and-Recover log file(s)" +- "Go to Relax-and-Recover shell" +- ) +- echo -e "\nLaunching 'rear recover' automatically in unattended mode\n" +- # The recover workflow is always verbose (see usr/sbin/rear): +- if rear $rear_debug_options recover ; then +- echo -e "\n'rear recover' finished successfully\n" +- echo -e "\nRebooting in 30 seconds (Ctrl-C to interrupt)\n" +- sleep 30 +- reboot +- else +- echo -e "\n'rear recover' failed, check the Relax-and-Recover log file(s)\n" +- PS3="Select what to do " +- select choice in "${choices[@]}" ; do +- case "$REPLY" in +- (1) +- # Do not assume the ReaR log file is named rear-$HOSTNAME.log +- # the user can have specified any name as LOGFILE: +- less /var/log/rear/* +- ;; +- (2) +- echo "" > /etc/issue +- echo "" > /etc/motd +- break +- ;; +- esac +- for (( i=1 ; i <= ${#choices[@]} ; i++ )) ; do +- echo "$i) ${choices[$i-1]}" +- done +- done 2>&1 +- fi +-fi +diff --git a/usr/share/rear/skel/default/etc/scripts/system-setup-functions.sh b/usr/share/rear/skel/default/etc/scripts/system-setup-functions.sh +new file mode 100644 +index 00000000..c320cf88 +--- /dev/null ++++ b/usr/share/rear/skel/default/etc/scripts/system-setup-functions.sh +@@ -0,0 +1,30 @@ ++# Use an artificial array to get the kernel command line parameters as array elements ++kernel_command_line=( $( cat /proc/cmdline ) ) ++ ++function rear_debug() { ++ for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do ++ test "debug" = "$kernel_command_line_parameter" && return 0 ++ done ++ return 1 ++} ++ ++function unattended_recovery() { ++ for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do ++ test "unattended" = "$kernel_command_line_parameter" && return 0 ++ done ++ return 1 ++} ++ ++function automatic_recovery() { ++ # The unattended recovery mode implies automatic recovery (see the implementations below) ++ # so that in unattended mode the automatic recovery code below must not be run ++ # otherwise first the automatic recovery code and then the unattended recovery code ++ # get run automatically one after the other where the unattended recovery fails ++ # because for two subsequent 'rear recover' the second one fails: ++ unattended_recovery && return 1 ++ for kernel_command_line_parameter in "${kernel_command_line[@]}" ; do ++ test "auto_recover" = "$kernel_command_line_parameter" && return 0 ++ test "automatic" = "$kernel_command_line_parameter" && return 0 ++ done ++ return 1 ++} +diff --git a/usr/share/rear/skel/default/etc/systemd/system/default.target.wants/.gitignore b/usr/share/rear/skel/default/etc/systemd/system/default.target.wants/.gitignore +new file mode 100644 +index 00000000..d6b7ef32 +--- /dev/null ++++ b/usr/share/rear/skel/default/etc/systemd/system/default.target.wants/.gitignore +@@ -0,0 +1,2 @@ ++* ++!.gitignore +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/automatic-rear.service b/usr/share/rear/skel/default/usr/lib/systemd/system/automatic-rear.service +new file mode 100644 +index 00000000..ee3187a8 +--- /dev/null ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/automatic-rear.service +@@ -0,0 +1,13 @@ ++[Unit] ++Description=Run Relax-and-Recover recovery automatically if requested ++Wants=network-online.target ++After=network-online.target ++ ++[Service] ++Type=oneshot ++ExecStart=/etc/scripts/run-automatic-rear ++StandardInput=tty ++RemainAfterExit=yes ++ ++[Install] ++WantedBy=multi-user.target +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service b/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service +index bf858ca8..abafd8b5 100644 +--- a/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/getty@.service +@@ -6,6 +6,8 @@ Description=Getty on %I + Documentation=man:agetty(8) + After=systemd-user-sessions.service plymouth-quit-wait.service + After=sysinit.service ++# Automatic ReaR uses the system console ++After=automatic-rear.service + + # If additional gettys are spawned during boot then we should make + # sure that this is synchronized before getty.target, even though +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target +index c5ea1cca..a88e219f 100644 +--- a/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target +@@ -4,7 +4,7 @@ + + [Unit] + Description=Multi-User +-Requires=sysinit.target ++Requires=sysinit.target basic.target + AllowIsolate=yes + + [Install] +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target.wants/automatic-rear.service b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target.wants/automatic-rear.service +new file mode 120000 +index 00000000..3e8a4161 +--- /dev/null ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/multi-user.target.wants/automatic-rear.service +@@ -0,0 +1 @@ ++../automatic-rear.service +\ No newline at end of file +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target +new file mode 100644 +index 00000000..c3edfeb4 +--- /dev/null ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target +@@ -0,0 +1,14 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++# ++# This file is part of systemd. ++# ++# systemd is free software; you can redistribute it and/or modify it ++# under the terms of the GNU Lesser General Public License as published by ++# the Free Software Foundation; either version 2.1 of the License, or ++# (at your option) any later version. ++ ++[Unit] ++Description=Network is Online ++Documentation=man:systemd.special(7) ++Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget ++After=network.target +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target.wants/sysinit.service b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target.wants/sysinit.service +new file mode 120000 +index 00000000..ed660a10 +--- /dev/null ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/network-online.target.wants/sysinit.service +@@ -0,0 +1 @@ ++../sysinit.service +\ No newline at end of file +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service b/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service +index ac171e0f..18fa17b5 100644 +--- a/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/rsyslog.service +@@ -1,6 +1,5 @@ + [Unit] + Description=Relax-and-Recover run-syslog script +-DefaultDependencies=no + + [Service] + Type=simple +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service +index ee22fafc..b34b2fe8 100644 +--- a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.service +@@ -1,9 +1,14 @@ + [Unit] + Description=Initialize Rescue System +-After=systemd-udevd.service ++DefaultDependencies=no ++After=systemd-udevd.service rear-boot-helper.service ++Before=network-online.target + + [Service] + Type=oneshot + ExecStart=/etc/scripts/system-setup + StandardInput=tty + RemainAfterExit=yes ++ ++[Install] ++WantedBy=network-online.target +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target +index 4187ef67..2a16369b 100644 +--- a/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/sysinit.target +@@ -4,3 +4,5 @@ + + [Unit] + Description=System Initialization ++Wants=sysinit.service rear-boot-helper.service ++After=sysinit.service rear-boot-helper.service +diff --git a/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket b/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket +index 9a0064c0..3fb02344 100644 +--- a/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket ++++ b/usr/share/rear/skel/default/usr/lib/systemd/system/syslog.socket +@@ -4,7 +4,6 @@ + + [Unit] + Description=Syslog Socket +-DefaultDependencies=no + Before=sockets.target syslog.target + + [Socket] diff --git a/SOURCES/rear-copy-console-kernel-cmdline-from-host.patch b/SOURCES/rear-copy-console-kernel-cmdline-from-host.patch new file mode 100644 index 0000000..1bcd171 --- /dev/null +++ b/SOURCES/rear-copy-console-kernel-cmdline-from-host.patch @@ -0,0 +1,587 @@ +commit 88f11d19d748fff3f36357ef1471ee75fbfacabb +Merge: bca0e7a9 4b4efc58 +Author: Johannes Meixner +Date: Wed Aug 3 15:04:20 2022 +0200 + + Merge pull request #2844 from rear/jsmeix-overhauled-290_kernel_cmdline + + Overhauled rescue/GNU/Linux/290_kernel_cmdline.sh + in particular to make it possible to add several already existing + kernel options by this script with same kernel option keyword + for example when /proc/cmdline contains + ... console=ttyS0,9600 ... console=tty0 ... + then via COPY_KERNEL_PARAMETERS+=( console ) + cf. https://github.com/rear/rear/pull/2749#issuecomment-1197843273 + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh b/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh +index 0e11204b..eb6c45de 100644 +--- a/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh ++++ b/usr/share/rear/rescue/GNU/Linux/290_kernel_cmdline.sh +@@ -1,8 +1,15 @@ +-# purpose of the script is to detect some important KERNEL CMDLINE options on the current system +-# we should also use in rescue mode (automatically update KERNEL_CMDLINE array variable). ++# Purpose of the script is to get the COPY_KERNEL_PARAMETERS on the current system ++# to be used in the rescue/recovery system via automated update of KERNEL_CMDLINE. + +-# Scanning current kernel cmdline to look for important option ($COPY_KERNEL_PARAMETERS) to include in KERNEL_CMDLINE +-for current_kernel_option in $( cat /proc/cmdline ); do ++# Also protect the rescue/recovery system by removing net.ifnames=0 from KERNEL_CMDLINE ++# if net.ifnames=0 is in KERNEL_CMDLINE but persistent network interface naming is used: ++local persistent_naming='no' ++is_persistent_ethernet_name $( ip route | awk '$2 == "dev" && $8 == "src" { print $3 }' | sort -u | head -n1 ) && persistent_naming='yes' ++ ++# Scan current kernel cmdline for options in COPY_KERNEL_PARAMETERS to be included in KERNEL_CMDLINE: ++local current_kernel_option ++local new_kernel_options_to_add=() ++for current_kernel_option in $( cat /proc/cmdline ) ; do + # Get the current kernel option name (part before leftmost "=") and + # add the whole option (with value) to new_kernel_options_to_add array + # if the option name is part of COPY_KERNEL_PARAMETERS array: +@@ -11,41 +18,45 @@ for current_kernel_option in $( cat /proc/cmdline ); do + fi + done + +-# Verify if the kernel option we want to add to KERNEL_CMDLINE are not already set/force by the user in the rear configuration. +-# If yes, the parameter set in the configuration file have the priority and superseed the current kernel option. ++# Check if the kernel options we want to add to KERNEL_CMDLINE are already set by the user in KERNEL_CMDLINE. ++# If yes, the user setting has priority and superseds the kernel option from the current system. ++# For the check use the existing KERNEL_CMDLINE when this script is started ++# and not the modified KERNEL_CMDLINE with already added kernel options ++# to make it possible to add several kernel options by this script ++# with same kernel option keyword like console=ttyS0,9600 console=tty0 ++# see https://github.com/rear/rear/pull/2749#issuecomment-1197843273 ++# and https://github.com/rear/rear/pull/2844 ++local existing_kernel_cmdline="$KERNEL_CMDLINE" ++local existing_kernel_option new_kernel_option new_kernel_option_keyword + for new_kernel_option in "${new_kernel_options_to_add[@]}" ; do + new_kernel_option_keyword="${new_kernel_option%%=*}" +- +- for rear_kernel_option in $KERNEL_CMDLINE ; do +- # Check if a kernel option key without value parameter (everything before =) is not already present in rear KERNEL_CMDLINE array. +- if test "$new_kernel_option_keyword" = "${rear_kernel_option%%=*}" ; then +- Log "Current kernel option [$new_kernel_option] supperseeded by [$rear_kernel_option] in your rear configuration: (KERNEL_CMDLINE)" ++ for existing_kernel_option in $existing_kernel_cmdline ; do ++ if test "$new_kernel_option_keyword" = "${existing_kernel_option%%=*}" ; then ++ LogPrint "Not adding '$new_kernel_option' (superseded by existing '$existing_kernel_option' in KERNEL_CMDLINE)" + # Continue with the next new_kernel_option (i.e. continue the outer 'for' loop): + continue 2 + fi + done +- ++ # If we are using persistent naming do not add net.ifnames to KERNEL_CMDLINE ++ # see https://github.com/rear/rear/pull/1874 ++ # and continue with the next new_kernel_option: + if test "net.ifnames" = "$new_kernel_option_keyword" ; then +- # If we are using persistent naming do not add net.ifnames to KERNEL_CMDLINE +- # see https://github.com/rear/rear/pull/1874 +- # and continue with the next new_kernel_option: +- is_persistent_ethernet_name $( ip r | awk '$2 == "dev" && $8 == "src" { print $3 }' | sort -u | head -1 ) && continue ++ if is_true $persistent_naming ; then ++ LogPrint "Not adding '$new_kernel_option' (persistent network interface naming is used)" ++ continue ++ fi + fi +- +- LogPrint "Adding $new_kernel_option to KERNEL_CMDLINE" +- KERNEL_CMDLINE="$KERNEL_CMDLINE $new_kernel_option" ++ LogPrint "Adding '$new_kernel_option' to KERNEL_CMDLINE" ++ KERNEL_CMDLINE+=" $new_kernel_option" + done + +-# In case we added 'KERNEL_CMDLINE="$KERNEL_CMDLINE net.ifnames=0"' to /etc/rear/local.conf, but we have no idea if we +-# are using persistent naming or not then we should protect the rescue image from doing stupid things and remove +-# the keyword (and value) in a preventive way in case "persistent naming is in use". +-# And, to be clear the /proc/cmdline did not contain the keyword net.ifnames +- +-if is_persistent_ethernet_name $( ip r | awk '$2 == "dev" && $8 == "src" { print $3 }' | sort -u | head -1 ) ; then +- # persistent naming is in use +- # When the KERNEL_CMDLINE does NOT contain net.ifnames=0 silently return +- echo $KERNEL_CMDLINE | grep -q 'net.ifnames=0' || return +- # Remove net.ifnames=0 from KERNEL_CMDLINE +- KERNEL_CMDLINE=$( echo $KERNEL_CMDLINE | sed -e 's/net.ifnames=0//' ) +- LogPrint "Removing net.ifnames=0 from KERNEL_CMDLINE" ++# The user may have added 'net.ifnames=0' to KERNEL_CMDLINE in /etc/rear/local.conf ++# but he may not know whether or not persistent naming is used. ++# So we should protect the rescue/recovery system from doing "stupid things" ++# and remove 'net.ifnames=0' in a preventive way when persistent naming is used: ++if is_true $persistent_naming ; then ++ if echo $KERNEL_CMDLINE | grep -q 'net.ifnames=0' ; then ++ KERNEL_CMDLINE=$( echo $KERNEL_CMDLINE | sed -e 's/net.ifnames=0//' ) ++ LogPrint "Removed 'net.ifnames=0' from KERNEL_CMDLINE (persistent network interface naming is used)" ++ fi + fi + +commit 42e04f36f5f8eea0017915bb35e56ee285b394d7 +Merge: 7c6296db 940fede7 +Author: Johannes Meixner +Date: Tue Jan 31 13:13:56 2023 +0100 + + Merge pull request #2915 from rear/jsmeix-serial-devs-fail-safe + + In lib/serial-functions.sh make the + get_serial_console_devices() function + fail-safe if no serial device node exists, see + https://github.com/rear/rear/issues/2914 + +diff --git a/usr/share/rear/lib/serial-functions.sh b/usr/share/rear/lib/serial-functions.sh +index aac5dc88..3d421b52 100644 +--- a/usr/share/rear/lib/serial-functions.sh ++++ b/usr/share/rear/lib/serial-functions.sh +@@ -1,13 +1,24 @@ + + # Get available serial devices: + function get_serial_console_devices () { +- test "$SERIAL_CONSOLE_DEVICES" && echo $SERIAL_CONSOLE_DEVICES || ls /dev/ttyS[0-9]* /dev/hvsi[0-9]* | sort ++ # Via SERIAL_CONSOLE_DEVICES the user specifies which ones to use (and no others): ++ if test "$SERIAL_CONSOLE_DEVICES" ; then ++ echo $SERIAL_CONSOLE_DEVICES ++ return 0 ++ fi ++ # Test if there is /dev/ttyS[0-9]* or /dev/hvsi[0-9]* ++ # because when there is neither /dev/ttyS[0-9]* nor /dev/hvsi[0-9]* ++ # the ls command below would become plain 'ls' because of 'nullglob' ++ # cf. "Beware of the emptiness" in https://github.com/rear/rear/wiki/Coding-Style ++ # see https://github.com/rear/rear/issues/2914#issuecomment-1396659184 ++ # and return 0 because it is no error when no serial device node exists ++ test "$( echo -n /dev/ttyS[0-9]* /dev/hvsi[0-9]* )" || return 0 + # Use plain 'sort' which results /dev/ttyS0 /dev/ttyS1 /dev/ttyS10 ... /dev/ttyS19 /dev/ttyS2 /dev/ttyS20 ... + # to get at least /dev/ttyS0 and /dev/ttyS1 before the other /dev/ttyS* devices because + # we cannot use "sort -V" which would result /dev/ttyS0 /dev/ttyS1 ... /dev/ttyS9 /dev/ttyS10 ... + # because in older Linux distributions 'sort' does not support '-V' e.g. SLES10 with GNU coreutils 5.93 + # (SLES11 with GNU coreutils 8.12 supports 'sort -V') but if 'sort' fails there is no output at all +- # cf. "Maintain backward compatibility" at https://github.com/rear/rear/wiki/Coding-Style ++ # cf. "Maintain backward compatibility" in https://github.com/rear/rear/wiki/Coding-Style + # Furthermore 'sort' results that /dev/hvsi* devices appear before /dev/ttyS* devices + # so the create_grub2_serial_entry function in lib/bootloader-functions.sh + # which uses by default the first one and skips the rest will result that +@@ -16,7 +27,8 @@ function get_serial_console_devices () { + # that have the HVSI driver loaded (a console driver for IBM's p5 servers) + # cf. https://lwn.net/Articles/98442/ + # and it seems right that when special console drivers are loaded +- # then their devices should be preferred by default. ++ # then their devices should be preferred by default: ++ ls /dev/ttyS[0-9]* /dev/hvsi[0-9]* | sort + } + + # Get the serial device speed for those device nodes that belong to actual serial devices. + +commit 07da02143b5597b202e66c187e53103561018255 +Merge: 91942f63 75a23e79 +Author: Johannes Meixner +Date: Fri Oct 20 14:45:23 2023 +0200 + + Merge pull request #2961 from rear/jsmeix-copy-serial-console + + For the automated serial console setup for the recovery system + use only the 'console=...' kernel arguments from the original system + which fixes https://github.com/rear/rear/issues/2843 + and it means that no longer all "real serial devices" get + auto-enabled as serial consoles in the recovery system, see + https://github.com/rear/rear/pull/2749#issuecomment-1196650631 + That new default behaviour is described in default.conf. + In particular prep/GNU/Linux/200_include_serial_console.sh + and lib/serial-functions.sh were overhauled which results + that rescue/GNU/Linux/400_use_serial_console.sh is obsolete. + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf +index ec1691b6..76355fb8 100644 +--- a/usr/share/rear/conf/default.conf ++++ b/usr/share/rear/conf/default.conf +@@ -3320,39 +3320,90 @@ SIMPLIFY_TEAMING=no + SIMPLIFY_TEAMING=no + + # Serial console support for the ReaR rescue/recovery system: +-# By default serial consoles get enabled if serial devices are found and +-# then matching kernel command line parameters like 'console=ttyS0,9600 console=ttyS1,9600' +-# are set when booting the rescue/recovery system (see KERNEL_CMDLINE above). + # IA64 platforms require it and people need it when no VGA console is available. +-# Specify 'yes' or 'no' or leave it empty to use ReaR's automatism: ++# By default there is serial console support in the ReaR recovery system ++# when 'getty' or 'agetty' and 'stty' can be found, ++# otherwise USE_SERIAL_CONSOLE is automatically set to 'no'. ++# When 'getty' or 'agetty' and 'stty' can be found ++# and there is a 'console=...' option in /proc/cmdline, ++# then USE_SERIAL_CONSOLE is automatically set to 'yes'. ++# With USE_SERIAL_CONSOLE="no" no serial console gets set up, ++# neither for the recovery system kernel nor for the recovery system bootloader. ++# With USE_SERIAL_CONSOLE="yes" plus appropriate SERIAL_CONSOLE_DEVICE... settings ++# serial consoles can be specified for the recovery system kernel and bootloader ++# for example when there is no 'console=...' option in /proc/cmdline ++# or when serial consoles for the recovery system kernel and bootloader ++# should differ from what 'console=...' options in /proc/cmdline tell. ++# By default (when empty) the automatism further described below is used: + USE_SERIAL_CONSOLE= +-# If you do not want to use all serial devices found as console you can specify the ones to use +-# e.g. SERIAL_CONSOLE_DEVICES="/dev/ttyS0 /dev/ttyS1" provided USE_SERIAL_CONSOLE is turned on. +-# By default (when empty) all serial devices found are used: ++# ++# Devices to be used in general for serial console setup ++# unless explicitly specified via SERIAL_CONSOLE_DEVICES_KERNEL ++# or SERIAL_CONSOLE_DEVICE_SYSLINUX or SERIAL_CONSOLE_DEVICE_GRUB: ++# E.g. SERIAL_CONSOLE_DEVICES="/dev/ttyS0 /dev/ttyS1" + SERIAL_CONSOLE_DEVICES= +-# Serial consoles for the kernel of the recovery system: ++# ++# Serial consoles for the kernel of the recovery system ++# provided USE_SERIAL_CONSOLE is not 'no': + # SERIAL_CONSOLE_DEVICES_KERNEL can be device nodes like "/dev/ttyS0 /dev/ttyS1" + # or 'console=...' kernel parameters like "console=ttyS1,9600 console=tty0" or both like + # SERIAL_CONSOLE_DEVICES_KERNEL="/dev/ttyS0 console=ttyS1,9600 console=tty0" +-# provided USE_SERIAL_CONSOLE is turned on. +-# By default (when empty) the SERIAL_CONSOLE_DEVICES are used for the kernel: ++# When SERIAL_CONSOLE_DEVICES_KERNEL is empty but SERIAL_CONSOLE_DEVICES is specified ++# then the specified SERIAL_CONSOLE_DEVICES are used for the kernel. ++# By default (when SERIAL_CONSOLE_DEVICES_KERNEL and SERIAL_CONSOLE_DEVICES are empty) ++# serial consoles get enabled for the recovery system kernel via COPY_KERNEL_PARAMETERS ++# for all 'console=...' options that are found in /proc/cmdline. + SERIAL_CONSOLE_DEVICES_KERNEL= +-# Serial console for SYSLINUX/EXTLINUX when it is used as bootloader for the recovery system: ++# ++# Serial console for SYSLINUX/EXTLINUX when it is used as bootloader for the recovery system ++# provided USE_SERIAL_CONSOLE is 'yes' (automatically with 'console=...' in /proc/cmdline): + # SYSLINUX supports only one serial device (because the last SYSLINUX 'serial' directive wins). + # The right /dev/ttyS* can be specified like SERIAL_CONSOLE_DEVICE_SYSLINUX="/dev/ttyS0" + # or a whole SYSLINUX 'serial' directive can be specified e.g. for /dev/ttyS1 like + # SERIAL_CONSOLE_DEVICE_SYSLINUX="serial 1 9600" +-# provided USE_SERIAL_CONSOLE is turned on. +-# By default (when empty) the first one of SERIAL_CONSOLE_DEVICES is used for SYSLINUX: ++# When SERIAL_CONSOLE_DEVICE_SYSLINUX is empty but SERIAL_CONSOLE_DEVICES is specified ++# then the first one of SERIAL_CONSOLE_DEVICES is used for SYSLINUX. ++# By default (when SERIAL_CONSOLE_DEVICE_SYSLINUX and SERIAL_CONSOLE_DEVICES are empty) ++# the devices of the 'console=...' options in /proc/cmdline ++# that exist as /dev/ttyS* or /dev/hvsi* character device nodes are used ++# (which excludes /dev/tty0 when there is 'console=tty0' in /proc/cmdline). + SERIAL_CONSOLE_DEVICE_SYSLINUX= +-# Serial console for GRUB when it is used as bootloader for the recovery system: ++# ++# Serial console for GRUB when it is used as bootloader for the recovery system ++# provided USE_SERIAL_CONSOLE is 'yes' (automatically with 'console=...' in /proc/cmdline): + # GRUB supports only one serial device (because the last GRUB 'serial' command wins). + # The right /dev/ttyS* can be specified like SERIAL_CONSOLE_DEVICE_GRUB="/dev/ttyS0" + # or a whole GRUB 'serial' command can be specified e.g. for /dev/ttyS1 like + # SERIAL_CONSOLE_DEVICE_GRUB="serial --unit=1 --speed=9600" +-# provided USE_SERIAL_CONSOLE is turned on. +-# By default (when empty) the first one of SERIAL_CONSOLE_DEVICES is used for GRUB: ++# When SERIAL_CONSOLE_DEVICE_GRUB is empty but SERIAL_CONSOLE_DEVICES is specified ++# then the first one of SERIAL_CONSOLE_DEVICES is used for GRUB. ++# By default (when SERIAL_CONSOLE_DEVICE_GRUB and SERIAL_CONSOLE_DEVICES are empty) ++# the devices of the 'console=...' options in /proc/cmdline ++# that exist as /dev/ttyS* or /dev/hvsi* character device nodes are used ++# (which excludes /dev/tty0 when there is 'console=tty0' in /proc/cmdline). + SERIAL_CONSOLE_DEVICE_GRUB= ++# ++# Examples ++# (provided USE_SERIAL_CONSOLE is not 'no' ++# and 'getty' or 'agetty' and 'stty' can be found): ++# ++# Default behaviour ++# when there is no 'console=...' option in /proc/cmdline ++# then no serial console is set up for the recovery system. ++# ++# Default behaviour when there are for example ++# 'console=ttyS0,9600' and 'console=tty0' in /proc/cmdline ++# then 'console=ttyS0,9600' and 'console=tty0' ++# are used for the recovery system kernel ++# and only /dev/ttyS0 is used as serial console ++# for the recovery system bootloader (SYSLINUX or GRUB). ++# ++# On a headless machine without VGA card but with serial device /dev/ttyS0 ++# the kernel would choose /dev/ttyS0 as its console automatically ++# so no 'console=...' kernel option needs to be used and then the automatism described above ++# would not set up a console for the recovery system (in particular not for the bootloader). ++# In this case USE_SERIAL_CONSOLE="yes" and appropriate SERIAL_CONSOLE_DEVICE... settings ++# are needed to manually specify the right console setup for the recovery system. + + # Say "y", "Yes", etc, to enable or "n", "No" etc. to disable the DHCP client protocol or leave empty to autodetect. + # When enabled, lets the rescue/recovery system run dhclient to get an IP address + # instead of using the same IP address as the original system: +diff --git a/usr/share/rear/lib/serial-functions.sh b/usr/share/rear/lib/serial-functions.sh +index 3d421b52..a586d357 100644 +--- a/usr/share/rear/lib/serial-functions.sh ++++ b/usr/share/rear/lib/serial-functions.sh +@@ -6,29 +6,34 @@ function get_serial_console_devices () { + echo $SERIAL_CONSOLE_DEVICES + return 0 + fi +- # Test if there is /dev/ttyS[0-9]* or /dev/hvsi[0-9]* +- # because when there is neither /dev/ttyS[0-9]* nor /dev/hvsi[0-9]* +- # the ls command below would become plain 'ls' because of 'nullglob' +- # cf. "Beware of the emptiness" in https://github.com/rear/rear/wiki/Coding-Style +- # see https://github.com/rear/rear/issues/2914#issuecomment-1396659184 +- # and return 0 because it is no error when no serial device node exists +- test "$( echo -n /dev/ttyS[0-9]* /dev/hvsi[0-9]* )" || return 0 +- # Use plain 'sort' which results /dev/ttyS0 /dev/ttyS1 /dev/ttyS10 ... /dev/ttyS19 /dev/ttyS2 /dev/ttyS20 ... +- # to get at least /dev/ttyS0 and /dev/ttyS1 before the other /dev/ttyS* devices because +- # we cannot use "sort -V" which would result /dev/ttyS0 /dev/ttyS1 ... /dev/ttyS9 /dev/ttyS10 ... +- # because in older Linux distributions 'sort' does not support '-V' e.g. SLES10 with GNU coreutils 5.93 +- # (SLES11 with GNU coreutils 8.12 supports 'sort -V') but if 'sort' fails there is no output at all +- # cf. "Maintain backward compatibility" in https://github.com/rear/rear/wiki/Coding-Style +- # Furthermore 'sort' results that /dev/hvsi* devices appear before /dev/ttyS* devices +- # so the create_grub2_serial_entry function in lib/bootloader-functions.sh +- # which uses by default the first one and skips the rest will result that +- # the first /dev/hvsi* device becomes used for the GRUB serial console by default +- # which looks right because /dev/hvsi* devices should exist only on systems +- # that have the HVSI driver loaded (a console driver for IBM's p5 servers) +- # cf. https://lwn.net/Articles/98442/ +- # and it seems right that when special console drivers are loaded +- # then their devices should be preferred by default: +- ls /dev/ttyS[0-9]* /dev/hvsi[0-9]* | sort ++ # Scan the kernel command line of the currently running original system ++ # for 'console=[,]' settings e.g. 'console=ttyS1,9600n8 ... console=ttyS3 ... console=tty0' ++ # and extract the specified serial device nodes e.g. ttyS1 -> /dev/ttyS1 ... ttyS3 -> /dev/ttyS3 ++ local kernel_option console_option_value console_option_device ++ for kernel_option in $( cat /proc/cmdline ) ; do ++ # Continue with next kernel option when the option name (part before leftmost "=") is not 'console': ++ test "${kernel_option%%=*}" = "console" || continue ++ # Get the console option value (part after leftmost "=") e.g. 'ttyS1,9600n8' 'ttyS3' 'tty0' ++ console_option_value="${kernel_option#*=}" ++ # Get the console option device (part before leftmost optional ',' separator) e.g. 'ttyS1' 'ttyS3' 'tty0' ++ console_option_device="${console_option_value%%,*}" ++ # Continue with next kernel option when the current console option device is no serial device (exclude 'tty0'). ++ # The special /dev/hvsi* devices should exist only on systems that have the HVSI driver loaded ++ # (a console driver for IBM's p5 servers) cf. https://lwn.net/Articles/98442/ ++ [[ $console_option_device == ttyS* ]] || [[ $console_option_device == hvsi* ]] || continue ++ # Test that the matching serial device node e.g. ttyS1 -> /dev/ttyS1 and ttyS3 -> /dev/ttyS3' exists ++ # to avoid that this automated serial console setup may not work in the ReaR recovery system ++ # when serial device nodes get specified for the recovery system that do not exist ++ # in the currently running original system because the default assumption is ++ # that the replacement system has same hardware as the original system, ++ # cf. https://github.com/rear/rear/pull/2749#issuecomment-1196650631 ++ # (if needed the user can specify what he wants via SERIAL_CONSOLE_DEVICES, see above): ++ if ! test -c "/dev/$console_option_device" ; then ++ LogPrintError "Found '$kernel_option' in /proc/cmdline but '/dev/$console_option_device' is no character device" ++ continue ++ fi ++ echo /dev/$console_option_device ++ done + } + + # Get the serial device speed for those device nodes that belong to actual serial devices. +@@ -39,64 +44,15 @@ function get_serial_device_speed () { + # Run it in a subshell so that 'set -o pipefail' does not affect the current shell and + # it can run in a subshell because the caller of this function only needs its stdout + # cf. the function get_root_disk_UUID in lib/bootloader-functions.sh +- # so when stty fails the get_serial_device_speed return code is the stty exit code and not the awk exit code +- # therefore one can call get_serial_device_speed with error checking for example like ++ # so when stty fails the get_serial_device_speed return code is the stty exit code and not the awk exit code. ++ # Therefore one can call get_serial_device_speed with error checking for example like + # speed=$( get_serial_device_speed $serial_device ) && COMMAND_WITH_speed || COMMAND_WITHOUT_speed +- # because the return code of variable=$( PIPE ) is the return code of the pipe, +- # cf. how get_serial_device_speed is called in cmdline_add_console below. ++ # because the return code of variable=$( PIPE ) is the return code of the pipe ++ # cf. how get_serial_device_speed is called in lib/bootloader-functions.sh ++ # and output/USB/Linux-i386/300_create_extlinux.sh + # Suppress stty stderr output because for most /dev/ttyS* device nodes the result is + # stty: /dev/ttyS...: Input/output error + # when the device node does not belong to an actual serial device (i.e. to real serial hardware) + # so get_serial_device_speed is also used to get those device nodes that belong to real serial devices: + ( set -o pipefail ; stty -F $devnode 2>/dev/null | awk '/^speed / { print $2 }' ) + } +- +-# Add serial console to kernel cmdline: +-function cmdline_add_console { +- # Nothing to do when using serial console is not wanted: +- is_true "$USE_SERIAL_CONSOLE" || return 0 +- +- # Strip existing 'console=...' kernel cmd parameters: +- local param cmdline="" +- for param in $KERNEL_CMDLINE ; do +- case "$param" in +- (console=*) ;; +- (*) cmdline+=" $param";; +- esac +- done +- +- # Add serial console config to kernel cmd line: +- local devnode speed="" +- if test "$SERIAL_CONSOLE_DEVICES_KERNEL" ; then +- # When the user has specified SERIAL_CONSOLE_DEVICES_KERNEL use only that (no automatisms): +- for devnode in $SERIAL_CONSOLE_DEVICES_KERNEL ; do +- # devnode can be a character device node like "/dev/ttyS0" or "/dev/lp0" or "/dev/ttyUSB0" +- # cf. https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html +- # or devnode can be a 'console=...' kernel cmd parameter like "console=ttyS1,9600" +- if test -c "$devnode" ; then +- if speed=$( get_serial_device_speed $devnode ) ; then +- cmdline+=" console=${devnode##/dev/},$speed" +- else +- cmdline+=" console=${devnode##/dev/}" +- fi +- else +- # When devnode is a 'console=...' kernel cmd parameter use it as specified: +- cmdline+=" $devnode" +- fi +- done +- else +- local real_consoles="" +- for devnode in $( get_serial_console_devices ) ; do +- # Only add for those device nodes that belong to actual serial devices: +- speed=$( get_serial_device_speed $devnode ) && real_consoles+=" console=${devnode##/dev/},$speed" +- done +- cmdline+=" $real_consoles" +- +- # Add fallback console if no real serial device was found: +- test "$real_consoles" || cmdline+=" console=tty0" +- fi +- +- # Have a trailing space to be on the safe side +- # so that more kernel cmd parameters could be "just appended" by other scripts: +- echo "$cmdline " +-} +diff --git a/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh b/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh +index 214af3c4..14ec113e 100644 +--- a/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh ++++ b/usr/share/rear/prep/GNU/Linux/200_include_serial_console.sh +@@ -1,31 +1,115 @@ + +-# If possible auto-enable serial console when not specified: +-if [[ -z "$USE_SERIAL_CONSOLE" ]] ; then +- local devnode speed="" +- for devnode in $( get_serial_console_devices ) ; do +- # Enable serial console when there is at least one real serial device: +- if speed=$( get_serial_device_speed $devnode ) ; then +- USE_SERIAL_CONSOLE="yes" +- break +- fi +- done +-fi ++# This script prep/GNU/Linux/200_include_serial_console.sh ++# is the first ...console... script that is run for "rear mkrescue/mkbackup". ++# ++# When USE_SERIAL_CONSOLE is empty then this script decides ++# if USE_SERIAL_CONSOLE is kept empty ++# or (provided there is sufficient reason) ++# it sets USE_SERIAL_CONSOLE to 'no' or 'yes'. ++# It sets USE_SERIAL_CONSOLE to 'no' ++# when serial consoles cannot work in the recovery system. ++# It sets USE_SERIAL_CONSOLE to 'yes' ++# when a serial console will be set up for the recovery system kernel. ++# Only when a serial console will be actually set up for the recovery system kernel, ++# then it makes sense to also set up a serial console for the recovery system bootloader. ++# So serial console setup for the recovery system bootloader is only done if USE_SERIAL_CONSOLE="yes" ++# because an empty USE_SERIAL_CONSOLE must not result serial console setup for the recovery system bootloader ++# (without actual serial console setup for the recovery system kernel). + +-# Always include getty or agetty as we don't know in advance whether they are needed ++# Always try to include getty or agetty as we do not know in advance whether they are needed + # (the user may boot the recovery system with manually specified kernel options + # to get serial console support in his recovery system). +-# For serial support we need to include the agetty binary, +-# but Debian distro's use getty instead of agetty: +-local getty_binary="" ++# For serial console support we need to include 'getty' or 'agetty'. ++# Debian distributions (in particular Ubuntu) use 'getty'. ++# Fedora, RHEL, SLES,... use 'agetty'. + if has_binary getty ; then +- # Debian, Ubuntu,... +- getty_binary="getty" ++ PROGS+=( getty ) + elif has_binary agetty ; then +- # Fedora, RHEL, SLES,... +- getty_binary="agetty" ++ PROGS+=( agetty ) ++else ++ is_true "$USE_SERIAL_CONSOLE" && Error "Failed to find 'getty' or 'agetty' (USE_SERIAL_CONSOLE is 'true')" ++ LogPrintError "No serial console support (failed to find 'getty' or 'agetty')" ++ USE_SERIAL_CONSOLE="no" ++fi ++ ++# Also try to include 'stty' which is (currently) only needed for serial console support ++# in skel/default/etc/scripts/system-setup.d/45-serial-console.sh ++# and lib/serial-functions.sh ++if has_binary stty ; then ++ PROGS+=( stty ) + else +- # The user must have the programs in REQUIRED_PROGS installed on his system: +- Error "Failed to find 'getty' or 'agetty' for serial console" ++ is_true "$USE_SERIAL_CONSOLE" && Error "Failed to find 'stty' (USE_SERIAL_CONSOLE is 'true')" ++ LogPrintError "No serial console support (failed to find 'stty')" ++ USE_SERIAL_CONSOLE="no" + fi + +-REQUIRED_PROGS+=( "$getty_binary" stty ) ++# Auto-enable serial console support for the recovery system ++# provided console support is not impossible because there is no getty or agetty and stty ++# and unless the user specified to not have serial console support: ++is_false "$USE_SERIAL_CONSOLE" && return 0 ++ ++# When the user has specified SERIAL_CONSOLE_DEVICES_KERNEL use only that, ++# otherwise use SERIAL_CONSOLE_DEVICES if the user has specified it: ++local serial_console_devices="" ++test "$SERIAL_CONSOLE_DEVICES" && serial_console_devices="$SERIAL_CONSOLE_DEVICES" ++test "$SERIAL_CONSOLE_DEVICES_KERNEL" && serial_console_devices="$SERIAL_CONSOLE_DEVICES_KERNEL" ++if test "$serial_console_devices" ; then ++ local serial_console speed="" cmdline_add_console="" ++ for serial_console in $serial_console_devices ; do ++ # serial_console can be a character device node like "/dev/ttyS0" or "/dev/lp0" or "/dev/ttyUSB0" ++ # cf. https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html ++ # or serial_console can be a 'console=...' kernel cmd parameter like "console=ttyS1,9600" ++ if test -c "$serial_console" ; then ++ if speed=$( get_serial_device_speed $serial_console ) ; then ++ cmdline_add_console+=" console=${serial_console##/dev/},$speed" ++ else ++ cmdline_add_console+=" console=${serial_console##/dev/}" ++ fi ++ else ++ # When serial_console is not a character device ++ # it should be a 'console=...' kernel cmd parameter ++ # that is used as specified ("final power to the user"): ++ cmdline_add_console+=" $serial_console" ++ fi ++ done ++ if test "$cmdline_add_console" ; then ++ KERNEL_CMDLINE+="$cmdline_add_console" ++ DebugPrint "Appended '$cmdline_add_console' to KERNEL_CMDLINE" ++ USE_SERIAL_CONSOLE="yes" ++ # No further automatisms when a 'console=...' kernel cmd parameter was set ++ # via SERIAL_CONSOLE_DEVICES_KERNEL or SERIAL_CONSOLE_DEVICES: ++ return ++ fi ++ LogPrintError "SERIAL_CONSOLE_DEVICES_KERNEL or SERIAL_CONSOLE_DEVICES specified but none is a character device" ++fi ++ ++# Auto-enable serial console support for the recovery system kernel: ++# The below auto-enable serial console support for the recovery system kernel ++# does not auto-enable serial console support for the recovery system bootloader. ++# Currently auto-enable serial console support for the recovery system bootloader ++# happens for the first real serial device from get_serial_console_devices() ++# in lib/bootloader-functions.sh in make_syslinux_config() and create_grub2_cfg() ++# and in output/USB/Linux-i386/300_create_extlinux.sh ++# The auto-enable serial console support for the recovery system bootloader should be ++# auto-aligned with the auto-enable serial console support for the recovery system kernel. ++# Things are auto-aligned when the first 'console=...' device in /proc/cmdline ++# is also the first real serial device from get_serial_console_devices(). ++# When current auto-alignment does not result what the user needs, what is needed can be specified ++# via SERIAL_CONSOLE_DEVICES_KERNEL and SERIAL_CONSOLE_DEVICE_SYSLINUX or SERIAL_CONSOLE_DEVICE_GRUB. ++ ++# Scan the kernel command line of the currently running original system ++# and auto-enable serial console for the recovery system kernel ++# only if there is at least one 'console=...' option: ++local kernel_option ++for kernel_option in $( cat /proc/cmdline ) ; do ++ # Get the kernel option name (part before leftmost "="): ++ if test "${kernel_option%%=*}" = "console" ; then ++ USE_SERIAL_CONSOLE="yes" ++ # Get all 'console=...' kernel command line options ++ # copied from the currently running original system ++ # via rescue/GNU/Linux/290_kernel_cmdline.sh that runs later: ++ COPY_KERNEL_PARAMETERS+=( console ) ++ return ++ fi ++done ++DebugPrint "No 'console=...' setting for recovery system kernel (none in /proc/cmdline)" +diff --git a/usr/share/rear/rescue/GNU/Linux/400_use_serial_console.sh b/usr/share/rear/rescue/GNU/Linux/400_use_serial_console.sh +deleted file mode 100644 +index fc935844..00000000 +--- a/usr/share/rear/rescue/GNU/Linux/400_use_serial_console.sh ++++ /dev/null +@@ -1,6 +0,0 @@ +- +-# Nothing to do when using serial console is not wanted: +-is_true "$USE_SERIAL_CONSOLE" || return 0 +- +-KERNEL_CMDLINE=$( cmdline_add_console ) +-Log "Modified kernel commandline to: '$KERNEL_CMDLINE'" diff --git a/SOURCES/rear-device-shrinking-bz2223895.patch b/SOURCES/rear-device-shrinking-bz2223895.patch new file mode 100644 index 0000000..1964255 --- /dev/null +++ b/SOURCES/rear-device-shrinking-bz2223895.patch @@ -0,0 +1,33 @@ +commit 41c2d9b1fbcece4b0890ab92e9f5817621917ad3 (from 23977a19101b6e6eaeebbe8ce013332ddf9ea517) +Merge: 23977a19 686012cb +Author: Johannes Meixner +Date: Thu Jul 20 15:11:52 2023 +0200 + + Merge pull request #3027 from rmetrich/shrinking_file + + In build/GNU/Linux/100_copy_as_is.sh + ensure to really get all COPY_AS_IS files copied by using + 'tar ... -i' when extracting to avoid a false regular exit of 'tar' + in particular when padding zeroes get added when a file being read shrinks + because for 'tar' (without '-i') two consecutive 512-blocks of zeroes mean EOF, + cf. https://github.com/rear/rear/pull/3027 + +diff --git a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh +index e8f2be20..2169efaa 100644 +--- a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh ++++ b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh +@@ -110,9 +110,13 @@ done >$copy_as_is_exclude_file + # COPY_AS_IS+=( /path/to/directory/* ) + # which are used in our scripts and by users in their etc/rear/local.conf + # cf. https://github.com/rear/rear/pull/2405#issuecomment-633512932 ++# Using '-i' when extracting is necessary to avoid a false regular exit of 'tar' ++# in particular when padding zeroes get added when a file being read shrinks ++# because for 'tar' (without '-i') two consecutive 512-blocks of zeroes mean EOF, ++# cf. https://github.com/rear/rear/pull/3027 + # FIXME: The following code fails if file names contain characters from IFS (e.g. blanks), + # cf. https://github.com/rear/rear/issues/1372 +-if ! tar -v -X $copy_as_is_exclude_file -P -C / -c ${COPY_AS_IS[*]} 2>$copy_as_is_filelist_file | tar $v -C $ROOTFS_DIR/ -x 1>/dev/null ; then ++if ! tar -v -X $copy_as_is_exclude_file -P -C / -c ${COPY_AS_IS[*]} 2>$copy_as_is_filelist_file | tar $v -C $ROOTFS_DIR/ -x -i 1>/dev/null ; then + Error "Failed to copy files and directories in COPY_AS_IS minus COPY_AS_IS_EXCLUDE" + fi + Log "Finished copying files and directories in COPY_AS_IS minus COPY_AS_IS_EXCLUDE" diff --git a/SOURCES/rear-fix-backup-of-btrfs-subvolumes.patch b/SOURCES/rear-fix-backup-of-btrfs-subvolumes.patch new file mode 100644 index 0000000..66fc042 --- /dev/null +++ b/SOURCES/rear-fix-backup-of-btrfs-subvolumes.patch @@ -0,0 +1,321 @@ +commit ec9080664303165799a215cef062826b65f6a6f8 +Author: Johannes Meixner +Date: Fri Apr 12 15:25:28 2024 +0200 + + New unique_unsorted() function (#3177) + + In lib/global-functions.sh added a + new unique_unsorted() function + that outputs lines in a file or from STDIN + without subsequent duplicate lines + which keeps the ordering of the lines, see + https://github.com/rear/rear/pull/3177 + In backup/NETFS/default/500_make_backup.sh use + unique_unsorted $TMP_DIR/backup-include.txt + to ignore duplicate arguments provided + to 'tar' and 'rsync' what should be archived + to avoid that 'tar' and 'rsync' archive + exact same things multiple times + which needlessly increases backup time and + in case of 'tar' the backup archive size and + storage space and backup restore time, cf. + https://github.com/rear/rear/pull/3175#issuecomment-1985306750 + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/backup/NETFS/default/500_make_backup.sh b/usr/share/rear/backup/NETFS/default/500_make_backup.sh +index feb4d322..fba03338 100644 +--- a/usr/share/rear/backup/NETFS/default/500_make_backup.sh ++++ b/usr/share/rear/backup/NETFS/default/500_make_backup.sh +@@ -42,10 +42,10 @@ fi + + # Log what is included in the backup and what is excluded from the backup + # cf. backup/NETFS/default/400_create_include_exclude_files.sh +-Log "Backup include list (backup-include.txt contents):" ++Log "Backup include list (backup-include.txt contents without subsequent duplicates):" + while read -r backup_include_item ; do + test "$backup_include_item" && Log " $backup_include_item" +-done < $TMP_DIR/backup-include.txt ++done < <( unique_unsorted $TMP_DIR/backup-include.txt ) + Log "Backup exclude list (backup-exclude.txt contents):" + while read -r backup_exclude_item ; do + test "$backup_exclude_item" && Log " $backup_exclude_item" +@@ -127,7 +127,7 @@ case "$(basename ${BACKUP_PROG})" in + $BACKUP_PROG_CREATE_NEWER_OPTIONS \ + ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + -X $TMP_DIR/backup-exclude.txt -C / -c -f - \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $BACKUP_PROG_CRYPT_OPTIONS BACKUP_PROG_CRYPT_KEY \| $SPLIT_COMMAND ++ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $BACKUP_PROG_CRYPT_OPTIONS BACKUP_PROG_CRYPT_KEY \| $SPLIT_COMMAND + else + Log $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \ + --no-wildcards-match-slash --one-file-system \ +@@ -135,7 +135,7 @@ case "$(basename ${BACKUP_PROG})" in + $BACKUP_PROG_CREATE_NEWER_OPTIONS \ + ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + -X $TMP_DIR/backup-exclude.txt -C / -c -f - \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $SPLIT_COMMAND ++ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE \| $SPLIT_COMMAND + fi + + if is_true "$BACKUP_PROG_CRYPT_ENABLED" ; then +@@ -151,7 +151,7 @@ case "$(basename ${BACKUP_PROG})" in + ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} \ + "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + -X $TMP_DIR/backup-exclude.txt -C / -c -f - \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \ ++ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \ + { $BACKUP_PROG_CRYPT_OPTIONS "$BACKUP_PROG_CRYPT_KEY" ; } 2>/dev/null | \ + $SPLIT_COMMAND + pipes_rc=( ${PIPESTATUS[@]} ) +@@ -160,14 +160,14 @@ case "$(basename ${BACKUP_PROG})" in + "$(basename $(echo "$BACKUP_PROG" | awk '{ print $1 }'))" + "$(basename $(echo "$SPLIT_COMMAND" | awk '{ print $1 }'))" + ) +- $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \ +- --no-wildcards-match-slash --one-file-system \ +- --ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \ +- $BACKUP_PROG_CREATE_NEWER_OPTIONS \ +- ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} \ +- "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ +- -X $TMP_DIR/backup-exclude.txt -C / -c -f - \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \ ++ $BACKUP_PROG $TAR_OPTIONS --sparse --block-number --totals --verbose \ ++ --no-wildcards-match-slash --one-file-system \ ++ --ignore-failed-read "${BACKUP_PROG_OPTIONS[@]}" \ ++ $BACKUP_PROG_CREATE_NEWER_OPTIONS \ ++ ${BACKUP_PROG_BLOCKS:+-b $BACKUP_PROG_BLOCKS} \ ++ "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ ++ -X $TMP_DIR/backup-exclude.txt -C / -c -f - \ ++ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE | \ + $SPLIT_COMMAND + pipes_rc=( ${PIPESTATUS[@]} ) + fi +@@ -213,21 +213,21 @@ case "$(basename ${BACKUP_PROG})" in + mkdir -p $v "$backuparchive" >&2 + Log $BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \ + --exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \ +- $(cat $TMP_DIR/backup-include.txt) "$backuparchive" ++ $(unique_unsorted $TMP_DIR/backup-include.txt) "$backuparchive" + $BACKUP_PROG --verbose "${BACKUP_RSYNC_OPTIONS[@]}" --one-file-system --delete \ + --exclude-from=$TMP_DIR/backup-exclude.txt --delete-excluded \ +- $(cat $TMP_DIR/backup-include.txt) "$backuparchive" >&2 ++ $(unique_unsorted $TMP_DIR/backup-include.txt) "$backuparchive" >&2 + ;; + (*) + Log "Using unsupported backup program '$BACKUP_PROG'" + Log $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + $BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \ + "${BACKUP_PROG_OPTIONS[@]}" "$backuparchive" \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive" ++ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive" + $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + $BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \ + "${BACKUP_PROG_OPTIONS[@]}" "$backuparchive" \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive" ++ $(unique_unsorted $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive" + ;; + esac 2> "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log" + # For the rsync and default case the backup prog is the last in the case entry +diff --git a/usr/share/rear/lib/global-functions.sh b/usr/share/rear/lib/global-functions.sh +index 77263cb1..1fc083b4 100644 +--- a/usr/share/rear/lib/global-functions.sh ++++ b/usr/share/rear/lib/global-functions.sh +@@ -14,6 +14,35 @@ function read_and_strip_file () { + sed -e '/^[[:space:]]/d;/^$/d;/^#/d' "$filename" + } + ++# Output lines in STDIN or in a file without subsequent duplicate lines ++# i.e. for each line that was seen (and output) do not output subsequent duplicates of that line. ++# This keeps the ordering of the lines so the input ++# one ++# two ++# one ++# three ++# two ++# one ++# gets output as ++# one ++# two ++# three ++# To remove duplicate lines and keep the ordering one could use ... | cat -n | sort -uk2 | sort -nk1 | cut -f2- ++# cf. https://stackoverflow.com/questions/11532157/remove-duplicate-lines-without-sorting/11532197#11532197 ++# that also explains an awk command that prints each line provided the line was not seen before. ++# The awk variable $0 holds an entire line and square brackets is associative array access in awk. ++# For each line the node of the associative array 'seen' is incremented and the line is printed ++# if the content of that node was not '!' previously set (i.e. if the line was not previously seen) ++# cf. https://www.thegeekstuff.com/2010/03/awk-arrays-explained-with-5-practical-examples/ ++function unique_unsorted () { ++ local filename="$1" ++ if test "$filename" ; then ++ test -r "$filename" && awk '!seen[$0]++' "$filename" ++ else ++ awk '!seen[$0]++' ++ fi ++} ++ + # Three functions to test + # if the argument is an integer + # if the argument is a positive integer (i.e. test for '> 0') + +commit 2da70f54936e5c558c9f607b1526b9b17f6501b1 +Author: Lukáš Zaoral +Date: Fri Jul 12 10:44:04 2024 +0200 + + Automatically include mounted btrfs subvolumes in NETFS backups (#3175) + + * automatically exclude btrfs snapshot subvolumes from 'btrfsmountedsubvol' + + Related: https://github.com/rear/rear/pull/3175#issuecomment-1983498175 + + * automatically include mounted btrfs subvolumes in NETFS backups + + ... unless they are explicitly excluded. + + Resolves: https://github.com/rear/rear/issues/2928 + + * always add the excluded component in RESTORE_EXCLUDE_FILE + + Otherwise, the component itself would not be included if it had any child + components of the `fs` type. + + * automatically exclude btrfs subvolume children of excluded components + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh b/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh +index 0a902041..1e7522b2 100644 +--- a/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh ++++ b/usr/share/rear/layout/prepare/default/610_exclude_from_restore.sh +@@ -7,24 +7,33 @@ RESTORE_EXCLUDE_FILE="$TMP_DIR/restore-exclude-list.txt" + + : >"$RESTORE_EXCLUDE_FILE" + ++local component ++ + for component in "${EXCLUDE_RECREATE[@]}" ; do + if ! IsInArray "$component" "${EXCLUDE_RESTORE[@]}" ; then + EXCLUDE_RESTORE+=( "$component" ) + fi + done + ++local comp_type children child ++local comp_types=( "btrfsmountedsubvol" "fs" ) ++ + for component in "${EXCLUDE_RESTORE[@]}" ; do +- fs_children=$(get_child_components "$component" "fs" | sort -u) +- if [ -n "$fs_children" ] ; then +- for child in $fs_children ; do +- child=${child#fs:} +- echo "${child#/}" >> "$RESTORE_EXCLUDE_FILE" +- echo "${child#/}/*" >> "$RESTORE_EXCLUDE_FILE" +- done +- else +- # if there are no fs deps, assume it is a wildcard path +- component=${component#fs:} +- echo "${component#/}" >> "$RESTORE_EXCLUDE_FILE" +- echo "${component#/}/*" >> "$RESTORE_EXCLUDE_FILE" +- fi ++ for comp_type in "${comp_types[@]}"; do ++ children=$(get_child_components "$component" "$comp_type" | sort -u) ++ if [ -n "$children" ] ; then ++ for child in $children ; do ++ child=${child#$comp_type:} ++ echo "${child#/}" >> "$RESTORE_EXCLUDE_FILE" ++ echo "${child#/}/*" >> "$RESTORE_EXCLUDE_FILE" ++ done ++ fi ++ done ++ ++ # exclude the component itself ++ for comp_type in "${comp_types[@]}"; do ++ component=${component#$comp_type:} ++ done ++ echo "${component#/}" >> "$RESTORE_EXCLUDE_FILE" ++ echo "${component#/}/*" >> "$RESTORE_EXCLUDE_FILE" + done +diff --git a/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh b/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh +index 7990c055..166b9cd2 100644 +--- a/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh ++++ b/usr/share/rear/layout/save/GNU/Linux/230_filesystem_layout.sh +@@ -434,6 +434,7 @@ fi + # Output header only once: + btrfsmountedsubvol_entry_exists="yes" + echo "# All mounted btrfs subvolumes (including mounted btrfs default subvolumes and mounted btrfs snapshot subvolumes)." ++ echo "# Mounted btrfs snapshot subvolumes are autoexcluded." + if test "$findmnt_FSROOT_works" ; then + echo "# Determined by the findmnt command that shows the mounted btrfs_subvolume_path." + echo "# Format: btrfsmountedsubvol " +@@ -469,7 +470,10 @@ fi + # Finally, test whether the btrfs subvolume listed as mounted actually exists. A running docker + # daemon apparently can convince the system to list a non-existing btrfs volume as mounted. + # See https://github.com/rear/rear/issues/1496 +- if btrfs_subvolume_exists "$subvolume_mountpoint" "$btrfs_subvolume_path"; then ++ if btrfs_snapshot_subvolume_exists "$subvolume_mountpoint" "$btrfs_subvolume_path"; then ++ # Exclude mounted snapshot subvolumes ++ echo "#btrfsmountedsubvol $device $subvolume_mountpoint $mount_options $btrfs_subvolume_path" ++ elif btrfs_subvolume_exists "$subvolume_mountpoint" "$btrfs_subvolume_path"; then + echo "btrfsmountedsubvol $device $subvolume_mountpoint $mount_options $btrfs_subvolume_path" + else + LogPrintError "Ignoring non-existing btrfs subvolume listed as mounted: $subvolume_mountpoint" +diff --git a/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh b/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh +index 2b58922b..fb358ccf 100644 +--- a/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh ++++ b/usr/share/rear/layout/save/default/340_generate_mountpoint_device.sh +@@ -7,15 +7,15 @@ + # EXCLUDE_RECREATE is handled automatically (commented out in LAYOUT_FILE) + excluded_mountpoints=() + while read fs device mountpoint junk ; do +- if IsInArray "fs:$mountpoint" "${EXCLUDE_BACKUP[@]}" ; then ++ if IsInArray "$fs:$mountpoint" "${EXCLUDE_BACKUP[@]}" ; then + excluded_mountpoints+=( $mountpoint ) + fi +- for component in $(get_parent_components "fs:$mountpoint" | sort -u) ; do ++ for component in $(get_parent_components "$fs:$mountpoint" | sort -u) ; do + if IsInArray "$component" "${EXCLUDE_BACKUP[@]}" ; then + excluded_mountpoints+=( $mountpoint ) + fi + done +-done < <(grep ^fs $LAYOUT_FILE) ++done < <(grep -E '^(fs|btrfsmountedsubvol)' $LAYOUT_FILE) + + # Generate the list of mountpoints and devices to exclude from backup + while read fs device mountpoint junk ; do +@@ -25,4 +25,4 @@ while read fs device mountpoint junk ; do + continue + fi + echo "$mountpoint $device" +-done < <(grep '^fs' $LAYOUT_FILE) > $VAR_DIR/recovery/mountpoint_device ++done < <(grep -E '^(fs|btrfsmountedsubvol)' $LAYOUT_FILE) | unique_unsorted > $VAR_DIR/recovery/mountpoint_device +diff --git a/usr/share/rear/lib/filesystems-functions.sh b/usr/share/rear/lib/filesystems-functions.sh +index f0547706..826571be 100644 +--- a/usr/share/rear/lib/filesystems-functions.sh ++++ b/usr/share/rear/lib/filesystems-functions.sh +@@ -3,16 +3,27 @@ + # + # File system support functions + ++function btrfs_snapshot_subvolume_exists() { ++ # returns true if the btrfs snapshot subvolume ($2) exists in the Btrfs ++ # file system at the mount point ($1). ++ ++ # Use -s so that btrfs subvolume list considers snapshots only ++ btrfs_subvolume_exists "$1" "$2" "-s" ++} ++ + function btrfs_subvolume_exists() { + # returns true if the btrfs subvolume ($2) exists in the Btrfs file system at the mount point ($1). + local subvolume_mountpoint="$1" btrfs_subvolume_path="$2" + ++ # extra options for the btrfs subvolume list command ($3) ++ local btrfs_extra_opts="$3" ++ + # A root subvolume can be assumed to always exist + [ "$btrfs_subvolume_path" == "/" ] && return 0 + + # A non-root subvolume exists if the btrfs subvolume list contains its complete path at the end of one line. + # This code deliberately uses a plain string comparison rather than a regexp. +- btrfs subvolume list -a "$subvolume_mountpoint" | sed -e 's; path /; path ;' | ++ btrfs subvolume list -a $btrfs_extra_opts "$subvolume_mountpoint" | sed -e 's; path /; path ;' | + awk -v path="$btrfs_subvolume_path" ' + BEGIN { + match_string = " path " path; diff --git a/SOURCES/rear-fix-compatibility-with-newer-systemd-bz2254871.patch b/SOURCES/rear-fix-compatibility-with-newer-systemd-bz2254871.patch new file mode 100644 index 0000000..ffec7b6 --- /dev/null +++ b/SOURCES/rear-fix-compatibility-with-newer-systemd-bz2254871.patch @@ -0,0 +1,54 @@ +From 060fef89b6968f0c8f254e6f612eff839b83c057 Mon Sep 17 00:00:00 2001 +From: Pavel Cahyna +Date: Mon, 13 Nov 2023 18:54:41 +0100 +Subject: [PATCH] Do not mount /sys if already mounted + +Newer versions of systemd (starting with Fedora 39) seem to mount /sys +themselves. Mounting it again leads to errors on the recovery system +startup (startup scripts failing with status=219/CGROUP ), see +https://github.com/rear/rear/issues/3017. + +Check if /sys is already mounted using the `mountpoint` tool and mount it +only if it is not. + +Do the same for the other system mountpoints like /proc, /dev, /dev/pts. +Not sure if they suffer from the same problem, but they probably could. + +N.B. the `mountpoint` command is already among REQUIRED_PROGS. +--- + usr/share/rear/skel/default/etc/scripts/boot | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/usr/share/rear/skel/default/etc/scripts/boot b/usr/share/rear/skel/default/etc/scripts/boot +index 0f221af3e4..f06e759620 100755 +--- a/usr/share/rear/skel/default/etc/scripts/boot ++++ b/usr/share/rear/skel/default/etc/scripts/boot +@@ -4,8 +4,8 @@ + dmesg -n1 + + # basic mounts +-mount -t proc -n none /proc +-mount -t sysfs none /sys ++mountpoint /proc || mount -t proc -n none /proc ++mountpoint /sys || mount -t sysfs none /sys + + if type udevd &>/dev/null && ! type udevinfo &>/dev/null; then + ### we use udevinfo to filter out old udev versions (<106) that don't +@@ -13,7 +13,7 @@ if type udevd &>/dev/null && ! type udevinfo &>/dev/null; then + udev_version=$(udevd --version) + if [[ "$udev_version" -gt 175 ]]; then + ### udev > 175 needs devtmpfs +- mount -t devtmpfs none /dev ++ mountpoint /dev || mount -t devtmpfs none /dev + fi + fi + +@@ -26,7 +26,7 @@ if [[ ! -L /dev/fd ]] ; then + ln -s /proc/self/fd /dev/fd + fi + +-mount -t devpts -o gid=5,mode=620 none /dev/pts ++mountpoint /dev/pts || mount -t devpts -o gid=5,mode=620 none /dev/pts + + cat /proc/mounts >/etc/mtab 2>/dev/null + diff --git a/SOURCES/rear-fix-ipv6.patch b/SOURCES/rear-fix-ipv6.patch new file mode 100644 index 0000000..4beb4c4 --- /dev/null +++ b/SOURCES/rear-fix-ipv6.patch @@ -0,0 +1,1542 @@ +commit 8a10135bf958c03b4b5077fc7ae7761ad2a71eec +Merge: eb574592 b496f860 +Author: pcahyna +Date: Tue Jun 18 14:38:23 2024 +0200 + + Merge pull request #3242 from rmetrich/ipv6 + + Fix IPv6 address support in OUTPUT_URL/BACKUP_URL + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/backup/BLOCKCLONE/default/400_copy_disk_struct_files.sh b/usr/share/rear/backup/BLOCKCLONE/default/400_copy_disk_struct_files.sh +index a5257278..dea78074 100644 +--- a/usr/share/rear/backup/BLOCKCLONE/default/400_copy_disk_struct_files.sh ++++ b/usr/share/rear/backup/BLOCKCLONE/default/400_copy_disk_struct_files.sh +@@ -7,17 +7,17 @@ if [ -z "$BLOCKCLONE_SAVE_MBR_DEV" ]; then + return + fi + +-local backup_path=$( url_path $BACKUP_URL ) +-local opath=$(backup_path $scheme $path) ++local backup_path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + LogPrint "Copying $VAR_DIR/layout/$BLOCKCLONE_PARTITIONS_CONF_FILE to $opath" + +-cp $v $VAR_DIR/layout/$BLOCKCLONE_PARTITIONS_CONF_FILE $opath ++cp $v "$VAR_DIR/layout/$BLOCKCLONE_PARTITIONS_CONF_FILE" "$opath" + StopIfError "Failed to copy \ + $VAR_DIR/layout/$BLOCKCLONE_PARTITIONS_CONF_FILE to $opath" + + LogPrint "Copying $VAR_DIR/layout/$BLOCKCLONE_MBR_FILE to $opath" + +-cp $v $VAR_DIR/layout/$BLOCKCLONE_MBR_FILE $opath ++cp $v "$VAR_DIR/layout/$BLOCKCLONE_MBR_FILE" "$opath" + + StopIfError "Failed to copy $VAR_DIR/layout/$BLOCKCLONE_MBR_FILE to $opath" +diff --git a/usr/share/rear/backup/DUPLICITY/default/100_mount_duplicity_path.sh b/usr/share/rear/backup/DUPLICITY/default/100_mount_duplicity_path.sh +index 6ba7d543..991cde86 100644 +--- a/usr/share/rear/backup/DUPLICITY/default/100_mount_duplicity_path.sh ++++ b/usr/share/rear/backup/DUPLICITY/default/100_mount_duplicity_path.sh +@@ -3,7 +3,7 @@ if [ -n "$BACKUP_DUPLICITY_NETFS_URL" -o -n "$BACKUP_DUPLICITY_NETFS_MOUNTCMD" ] + BACKUP_DUPLICITY_NETFS_URL="var://BACKUP_DUPLICITY_NETFS_MOUNTCMD" + fi + +- mount_url $BACKUP_DUPLICITY_NETFS_URL $BUILD_DIR/outputfs $BACKUP_DUPLICITY_NETFS_OPTIONS ++ mount_url "$BACKUP_DUPLICITY_NETFS_URL" "$BUILD_DIR/outputfs" $BACKUP_DUPLICITY_NETFS_OPTIONS + + BACKUP_DUPLICITY_URL="file://$BUILD_DIR/outputfs" + fi +diff --git a/usr/share/rear/backup/DUPLICITY/default/980_unmount_duplicity_path.sh b/usr/share/rear/backup/DUPLICITY/default/980_unmount_duplicity_path.sh +index 8525ab1d..1331c36e 100644 +--- a/usr/share/rear/backup/DUPLICITY/default/980_unmount_duplicity_path.sh ++++ b/usr/share/rear/backup/DUPLICITY/default/980_unmount_duplicity_path.sh +@@ -5,5 +5,5 @@ if [ -n "$BACKUP_DUPLICITY_NETFS_URL" -o -n "$BACKUP_DUPLICITY_NETFS_UMOUNTCMD" + BACKUP_DUPLICITY_NETFS_URL="var://BACKUP_DUPLICITY_NETFS_UMOUNTCMD" + fi + +- umount_url $BACKUP_DUPLICITY_NETFS_URL $BUILD_DIR/outputfs ++ umount_url "$BACKUP_DUPLICITY_NETFS_URL" "$BUILD_DIR/outputfs" + fi +diff --git a/usr/share/rear/backup/NETFS/GNU/Linux/600_start_selinux.sh b/usr/share/rear/backup/NETFS/GNU/Linux/600_start_selinux.sh +index 59e497d7..4ed6f4f0 100644 +--- a/usr/share/rear/backup/NETFS/GNU/Linux/600_start_selinux.sh ++++ b/usr/share/rear/backup/NETFS/GNU/Linux/600_start_selinux.sh +@@ -1,8 +1,8 @@ + # Start SELinux if it was stopped - check presence of $TMP_DIR/selinux.mode + [[ -f $TMP_DIR/selinux.mode ]] && { +- local scheme=$(url_scheme $BACKUP_URL) +- local path=$(url_path $BACKUP_URL) +- local opath=$(backup_path $scheme $path) ++ local scheme="$( url_scheme "$BACKUP_URL" )" ++ local path="$( url_path "$BACKUP_URL" )" ++ local opath="$( backup_path "$scheme" "$path" )" + cat $TMP_DIR/selinux.mode > $SELINUX_ENFORCE + Log "Restored original SELinux mode" + touch "${opath}/selinux.autorelabel" +diff --git a/usr/share/rear/backup/NETFS/default/100_mount_NETFS_path.sh b/usr/share/rear/backup/NETFS/default/100_mount_NETFS_path.sh +index b6a955db..8287582f 100644 +--- a/usr/share/rear/backup/NETFS/default/100_mount_NETFS_path.sh ++++ b/usr/share/rear/backup/NETFS/default/100_mount_NETFS_path.sh +@@ -2,4 +2,4 @@ if [[ "$BACKUP_MOUNTCMD" ]] ; then + BACKUP_URL="var://BACKUP_MOUNTCMD" + fi + +-mount_url $BACKUP_URL $BUILD_DIR/outputfs $BACKUP_OPTIONS ++mount_url "$BACKUP_URL" "$BUILD_DIR/outputfs" $BACKUP_OPTIONS +diff --git a/usr/share/rear/backup/NETFS/default/150_save_copy_of_prefix_dir.sh b/usr/share/rear/backup/NETFS/default/150_save_copy_of_prefix_dir.sh +index 9bf8f76a..20740a26 100644 +--- a/usr/share/rear/backup/NETFS/default/150_save_copy_of_prefix_dir.sh ++++ b/usr/share/rear/backup/NETFS/default/150_save_copy_of_prefix_dir.sh +@@ -3,9 +3,9 @@ + [ -z "${NETFS_KEEP_OLD_BACKUP_COPY}" ] && return + + # do not do this for tapes and special attention for file:///path +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # if $opath is empty return silently (e.g. scheme tape) + [ -z "$opath" ] && return 0 +diff --git a/usr/share/rear/backup/NETFS/default/200_make_prefix_dir.sh b/usr/share/rear/backup/NETFS/default/200_make_prefix_dir.sh +index 43f5b651..ccdf6515 100644 +--- a/usr/share/rear/backup/NETFS/default/200_make_prefix_dir.sh ++++ b/usr/share/rear/backup/NETFS/default/200_make_prefix_dir.sh +@@ -2,9 +2,9 @@ + # to $HOSTNAME + + # do not do this for tapes and special attention for file:///path +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # if $opath is empty return silently (e.g. scheme tape) + [ -z "$opath" ] && return 0 +diff --git a/usr/share/rear/backup/NETFS/default/250_create_lock.sh b/usr/share/rear/backup/NETFS/default/250_create_lock.sh +index 36d547ec..5526018c 100644 +--- a/usr/share/rear/backup/NETFS/default/250_create_lock.sh ++++ b/usr/share/rear/backup/NETFS/default/250_create_lock.sh +@@ -2,9 +2,9 @@ + # made by a previous mkbackup run when the variable NETFS_KEEP_OLD_BACKUP_COPY has been set + + # do not do this for tapes and special attention for file:///path +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # if $opath is empty return silently (e.g. scheme tape) + [ -z "$opath" ] && return 0 +diff --git a/usr/share/rear/backup/NETFS/default/500_make_backup.sh b/usr/share/rear/backup/NETFS/default/500_make_backup.sh +index 884774fd..740c2004 100644 +--- a/usr/share/rear/backup/NETFS/default/500_make_backup.sh ++++ b/usr/share/rear/backup/NETFS/default/500_make_backup.sh +@@ -8,7 +8,7 @@ function set_tar_features () { + # Test for features in tar + # true if at supports the --warning option (v1.23+) + FEATURE_TAR_WARNINGS= +- local tar_version=$( get_version tar --version ) ++ local tar_version="$( get_version tar --version )" + if version_newer "$tar_version" 1.23 ; then + FEATURE_TAR_WARNINGS="y" + TAR_OPTIONS="$TAR_OPTIONS --warning=no-xdev" +@@ -18,9 +18,9 @@ function set_tar_features () { + + local backup_prog_rc + +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + test "$opath" && mkdir $v -p "$opath" + + # In any case show an initial basic info what is currently done +@@ -222,12 +222,12 @@ case "$(basename ${BACKUP_PROG})" in + Log "Using unsupported backup program '$BACKUP_PROG'" + Log $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + $BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \ +- "${BACKUP_PROG_OPTIONS[@]}" $backuparchive \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > $backuparchive ++ "${BACKUP_PROG_OPTIONS[@]}" "$backuparchive" \ ++ $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive" + $BACKUP_PROG "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" \ + $BACKUP_PROG_OPTIONS_CREATE_ARCHIVE $TMP_DIR/backup-exclude.txt \ +- "${BACKUP_PROG_OPTIONS[@]}" $backuparchive \ +- $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > $backuparchive ++ "${BACKUP_PROG_OPTIONS[@]}" "$backuparchive" \ ++ $(cat $TMP_DIR/backup-include.txt) $RUNTIME_LOGFILE > "$backuparchive" + ;; + esac 2> "${TMP_DIR}/${BACKUP_PROG_ARCHIVE}.log" + # For the rsync and default case the backup prog is the last in the case entry +@@ -292,7 +292,7 @@ wait $BackupPID + backup_prog_rc=$? + + if [[ $BACKUP_INTEGRITY_CHECK =~ ^[yY1] && "$(basename ${BACKUP_PROG})" = "tar" ]] ; then +- (cd $(dirname $backuparchive) && md5sum $(basename $backuparchive) > ${backuparchive}.md5 || md5sum $(basename $backuparchive).?? > ${backuparchive}.md5) ++ (cd $(dirname "$backuparchive") && md5sum $(basename "$backuparchive") > "${backuparchive}".md5 || md5sum $(basename "$backuparchive").?? > "${backuparchive}".md5) + fi + + # TODO: Why do we sleep here after 'wait $BackupPID'? +diff --git a/usr/share/rear/backup/NETFS/default/970_remove_lock.sh b/usr/share/rear/backup/NETFS/default/970_remove_lock.sh +index 7038f5b9..90c00758 100644 +--- a/usr/share/rear/backup/NETFS/default/970_remove_lock.sh ++++ b/usr/share/rear/backup/NETFS/default/970_remove_lock.sh +@@ -1,7 +1,7 @@ + # remove the lockfile +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # if $opath is empty return silently (e.g. scheme tape) + [ -z "$opath" ] && return 0 +diff --git a/usr/share/rear/backup/NETFS/default/980_umount_NETFS_dir.sh b/usr/share/rear/backup/NETFS/default/980_umount_NETFS_dir.sh +index e1954dc5..f15e3951 100644 +--- a/usr/share/rear/backup/NETFS/default/980_umount_NETFS_dir.sh ++++ b/usr/share/rear/backup/NETFS/default/980_umount_NETFS_dir.sh +@@ -4,4 +4,4 @@ if [[ "$BACKUP_UMOUNTCMD" ]] ; then + BACKUP_URL="var://BACKUP_UMOUNTCMD" + fi + +-umount_url $BACKUP_URL $BUILD_DIR/outputfs ++umount_url "$BACKUP_URL" "$BUILD_DIR/outputfs" +diff --git a/usr/share/rear/backup/RSYNC/GNU/Linux/620_force_autorelabel.sh b/usr/share/rear/backup/RSYNC/GNU/Linux/620_force_autorelabel.sh +index de57d571..f1b598c9 100644 +--- a/usr/share/rear/backup/RSYNC/GNU/Linux/620_force_autorelabel.sh ++++ b/usr/share/rear/backup/RSYNC/GNU/Linux/620_force_autorelabel.sh +@@ -31,9 +31,9 @@ local backup_prog_rc + ;; + + (*) +- local scheme=$(url_scheme $BACKUP_URL) +- local path=$(url_path $BACKUP_URL) +- local opath=$(backup_path $scheme $path) ++ local scheme="$(url_scheme "$BACKUP_URL")" ++ local path="$(url_path "$BACKUP_URL")" ++ local opath="$(backup_path "$scheme" "$path")" + # probably using the BACKUP=NETFS workflow instead + if [ -d "${opath}" ]; then + if [ ! -f "${opath}/selinux.autorelabel" ]; then +diff --git a/usr/share/rear/layout/save/FDRUPSTREAM/Linux-s390/990_copy_disklayout_file.sh b/usr/share/rear/layout/save/FDRUPSTREAM/Linux-s390/990_copy_disklayout_file.sh +index 5df7e7b8..5040ec30 100644 +--- a/usr/share/rear/layout/save/FDRUPSTREAM/Linux-s390/990_copy_disklayout_file.sh ++++ b/usr/share/rear/layout/save/FDRUPSTREAM/Linux-s390/990_copy_disklayout_file.sh +@@ -24,11 +24,11 @@ is_true "$ZVM_NAMING" || return 0 + VM_UID=( $( vmcp q userid ) ) + test $VM_UID || Error "Could not set VM_UID ('vmcp q userid' did not return the VM user id)" + +-scheme=$( url_scheme $OUTPUT_URL ) +-path=$( url_path $OUTPUT_URL ) +-opath=$( output_path $scheme $path ) ++scheme="$( url_scheme "$OUTPUT_URL" )" ++path="$( url_path "$OUTPUT_URL" )" ++opath="$( output_path "$scheme" "$path" )" + test $opath || Error "Could not determine output path from OUTPUT_URL='$OUTPUT_URL'" + + LogPrint "s390 disklayout.conf will be saved as $opath/$VM_UID.disklayout.conf" +-mkdir $v -p $opath ++mkdir $v -p "$opath" + cp $v $DISKLAYOUT_FILE $opath/$VM_UID.disklayout.conf || Error "Failed to copy '$DISKLAYOUT_FILE' to $opath/$VM_UID.disklayout.conf" +diff --git a/usr/share/rear/layout/save/default/310_autoexclude_usb.sh b/usr/share/rear/layout/save/default/310_autoexclude_usb.sh +index f40c4efd..11581700 100644 +--- a/usr/share/rear/layout/save/default/310_autoexclude_usb.sh ++++ b/usr/share/rear/layout/save/default/310_autoexclude_usb.sh +@@ -6,9 +6,9 @@ + + for URL in "$OUTPUT_URL" "$BACKUP_URL" ; do + if [[ ! -z "$URL" ]] ; then +- local host=$(url_host $URL) +- local scheme=$(url_scheme $URL) +- local path=$(url_path $URL) ++ local host="$(url_host "$URL")" ++ local scheme="$(url_scheme "$URL")" ++ local path="$(url_path "$URL")" + + case $scheme in + (usb) +@@ -35,9 +35,9 @@ for URL in "$OUTPUT_URL" "$BACKUP_URL" ; do + + grep -q "^$REAL_USB_DEVICE " /proc/mounts + if [[ $? -eq 0 ]] ; then +- local usb_mntpt=$( grep "^$REAL_USB_DEVICE " /proc/mounts | cut -d" " -f2 | tail -1 ) ++ local usb_mntpt="$( grep "^$REAL_USB_DEVICE " /proc/mounts | cut -d" " -f2 | tail -1 )" + if ! IsInArray "$usb_mntpt" "${AUTOEXCLUDE_USB_PATH[@]}" ; then +- AUTOEXCLUDE_USB_PATH+=( $usb_mntpt ) ++ AUTOEXCLUDE_USB_PATH+=( "$usb_mntpt" ) + Log "Auto-excluding USB path $usb_mntpt [device $REAL_USB_DEVICE]" + fi + fi +diff --git a/usr/share/rear/lib/_input-output-functions.sh b/usr/share/rear/lib/_input-output-functions.sh +index d189ca24..5c853282 100644 +--- a/usr/share/rear/lib/_input-output-functions.sh ++++ b/usr/share/rear/lib/_input-output-functions.sh +@@ -1024,7 +1024,7 @@ function cleanup_build_area_and_end_program () { + sleep 2 + # umount_mountpoint_lazy is in lib/global-functions.sh + # which is not yet sourced in case of early Error() in usr/sbin/rear +- has_binary umount_mountpoint_lazy && umount_mountpoint_lazy $BUILD_DIR/outputfs ++ has_binary umount_mountpoint_lazy && umount_mountpoint_lazy "$BUILD_DIR/outputfs" + fi + # remove_temporary_mountpoint is in lib/global-functions.sh + # which is not yet sourced in case of early Error() in usr/sbin/rear +diff --git a/usr/share/rear/lib/global-functions.sh b/usr/share/rear/lib/global-functions.sh +index 1fc083b4..bd4624aa 100644 +--- a/usr/share/rear/lib/global-functions.sh ++++ b/usr/share/rear/lib/global-functions.sh +@@ -299,17 +299,17 @@ function percent_decode() { + # cf. http://bugzilla.opensuse.org/show_bug.cgi?id=561626#c7 + + function url_scheme() { +- local url=$1 ++ local url="$1" + # the scheme is the leading part up to '://' +- local scheme=${url%%://*} ++ local scheme="${url%%://*}" + # rsync scheme does not have to start with rsync:// it can also be scp style + # see the comments in usr/share/rear/lib/rsync-functions.sh +- echo $scheme | grep -q ":" && echo rsync || echo $scheme ++ echo "$scheme" | grep -q ":" && echo rsync || echo "$scheme" + } + + function url_host() { +- local url=$1 +- local url_without_scheme=${url#*//} ++ local url="$1" ++ local url_without_scheme="${url#*//}" + # the authority part is the part after the scheme (e.g. 'host' or 'user@host') + # i.e. after 'scheme://' all up to but excluding the next '/' + # which means it breaks if there is a username that contains a '/' +@@ -317,73 +317,73 @@ function url_host() { + # should have only characters from the portable filename character set + # which is ASCII letters, digits, dot, hyphen, and underscore + # (a hostname must not contain a '/' see RFC 952 and RFC 1123) +- local authority_part=${url_without_scheme%%/*} ++ local authority_part="${url_without_scheme%%/*}" + # for backward compatibility the url_host function returns the whole authority part + # see https://github.com/rear/rear/issues/856 + # to get only hostname or username use the url_hostname and url_username functions +- echo $authority_part ++ echo "$authority_part" + } + + function url_hostname() { +- local url=$1 +- local url_without_scheme=${url#*//} +- local authority_part=${url_without_scheme%%/*} ++ local url="$1" ++ local url_without_scheme="${url#*//}" ++ local authority_part="${url_without_scheme%%/*}" + # if authority_part contains a '@' we assume the 'user@host' format and + # then we remove the 'user@' part (i.e. all up to and including the last '@') + # so that it also works when the username contains a '@' + # like 'john@doe' in BACKUP_URL=sshfs://john@doe@host/G/rear/ + # (a hostname must not contain a '@' see RFC 952 and RFC 1123) +- local host_and_port=${authority_part##*@} ++ local host_and_port="${authority_part##*@}" + # if host_and_port contains a ':' we assume the 'host:port' format and + # then we remove the ':port' part (i.e. all from and including the last ':') + # so that it even works when the hostname contains a ':' (in spite of RFC 952 and RFC 1123) +- echo ${host_and_port%:*} ++ echo "${host_and_port%:*}" + } + + function url_username() { +- local url=$1 +- local url_without_scheme=${url#*//} +- local authority_part=${url_without_scheme%%/*} ++ local url="$1" ++ local url_without_scheme="${url#*//}" ++ local authority_part="${url_without_scheme%%/*}" + # authority_part must contain a '@' when a username is specified +- echo $authority_part | grep -q '@' || return 0 ++ echo "$authority_part" | grep -q '@' || return 0 + # we remove the '@host' part (i.e. all from and including the last '@') + # so that it also works when the username contains a '@' + # like 'john@doe' in BACKUP_URL=sshfs://john@doe@host/G/rear/ + # (a hostname must not contain a '@' see RFC 952 and RFC 1123) +- local user_and_password=${authority_part%@*} ++ local user_and_password="${authority_part%@*}" + # if user_and_password contains a ':' we assume the 'user:password' format and + # then we remove the ':password' part (i.e. all from and including the first ':') + # so that it works when the password contains a ':' + # (a POSIX-compliant username should not contain a ':') +- echo $user_and_password | grep -q ':' && echo ${user_and_password%%:*} || echo $user_and_password ++ echo "$user_and_password" | grep -q ':' && echo "${user_and_password%%:*}" || echo "$user_and_password" + } + + function url_password() { +- local url=$1 +- local url_without_scheme=${url#*//} +- local authority_part=${url_without_scheme%%/*} ++ local url="$1" ++ local url_without_scheme="${url#*//}" ++ local authority_part="${url_without_scheme%%/*}" + # authority_part must contain a '@' when a username is specified +- echo $authority_part | grep -q '@' || return 0 ++ echo "$authority_part" | grep -q '@' || return 0 + # we remove the '@host' part (i.e. all from and including the last '@') + # so that it also works when the username contains a '@' + # like 'john@doe' in BACKUP_URL=sshfs://john@doe@host/G/rear/ + # (a hostname must not contain a '@' see RFC 952 and RFC 1123) +- local user_and_password=${authority_part%@*} ++ local user_and_password="${authority_part%@*}" + # user_and_password must contain a ':' when a password is specified +- echo $user_and_password | grep -q ':' || return 0 ++ echo "$user_and_password" | grep -q ':' || return 0 + # we remove the 'user:' part (i.e. all up to and including the first ':') + # so that it works when the password contains a ':' + # (a POSIX-compliant username should not contain a ':') +- echo ${user_and_password#*:} ++ echo "${user_and_password#*:}" + } + + function url_path() { +- local url=$1 +- local url_without_scheme=${url#*//} ++ local url="$1" ++ local url_without_scheme="${url#*//}" + # the path is all from and including the first '/' in url_without_scheme + # i.e. the whole rest after the authority part so that + # it may contain an optional trailing '?query' and '#fragment' +- echo /${url_without_scheme#*/} ++ echo "/${url_without_scheme#*/}" + } + + ### Returns true if one can upload files to the URL +@@ -395,14 +395,14 @@ function scheme_accepts_files() { + # (then it would still exit with "bash: $1: cannot assign in this way") + # but using a default value is practicable here because $1 is used only once + # cf. https://github.com/rear/rear/pull/2675#discussion_r705018956 +- local scheme=${1:-} ++ local scheme="${1:-}" + # Return false if scheme is empty or blank (e.g. when OUTPUT_URL is unset or empty or blank) + # cf. https://github.com/rear/rear/issues/2676 + # and https://github.com/rear/rear/issues/2667#issuecomment-914447326 + # also return false if scheme is more than one word (so no quoted "$scheme" here) + # cf. https://github.com/rear/rear/pull/2675#discussion_r704401462 +- test $scheme || return 1 +- case $scheme in ++ test "$scheme" || return 1 ++ case "$scheme" in + (null|tape|obdr) + # tapes do not support uploading arbitrary files, one has to handle them + # as special case (usually passing the tape device as argument to tar) +@@ -426,10 +426,10 @@ function scheme_accepts_files() { + ### only that it can be mounted (use mount_url() first) + function scheme_supports_filesystem() { + # Be safe against 'set -eu' exit if scheme_supports_filesystem is called without argument +- local scheme=${1:-} ++ local scheme="${1:-}" + # Return false if scheme is empty or blank or more than one word, cf. scheme_accepts_files() above +- test $scheme || return 1 +- case $scheme in ++ test "$scheme" || return 1 ++ case "$scheme" in + (null|tape|obdr|rsync|fish|ftp|ftps|hftp|http|https|sftp) + return 1 + ;; +@@ -440,9 +440,9 @@ function scheme_supports_filesystem() { + } + + function backup_path() { +- local scheme=$1 +- local path=$2 +- case $scheme in ++ local scheme="$1" ++ local path="$2" ++ case "$scheme" in + (tape) # no path for tape required + path="" + ;; +@@ -466,8 +466,8 @@ function backup_path() { + } + + function output_path() { +- local scheme=$1 +- local path=$2 ++ local scheme="$1" ++ local path="$2" + + # Abort for unmountable schemes ("tape-like" or "ftp-like" schemes). + # Returning an empty string for them is not satisfactory: it could lead to caller putting its files +@@ -477,9 +477,9 @@ function output_path() { + # but if the directory is not a mountpoint, they would get silently lost. + # The caller needs to check the URL/scheme using scheme_supports_filesystem() + # before calling this function. +- scheme_supports_filesystem $scheme || BugError "output_path() called with scheme $scheme that does not support filesystem access" ++ scheme_supports_filesystem "$scheme" || BugError "output_path() called with scheme $scheme that does not support filesystem access" + +- case $scheme in ++ case "$scheme" in + (file) # type file needs a local path (must be mounted by user) + path="$path/${OUTPUT_PREFIX}" + ;; +@@ -493,19 +493,19 @@ function output_path() { + + ### Mount URL $1 at mountpoint $2[, with options $3] + function mount_url() { +- local url=$1 +- local mountpoint=$2 ++ local url="$1" ++ local mountpoint="$2" + local defaultoptions="rw,noatime" +- local options=${3:-"$defaultoptions"} ++ local options="${3:-"$defaultoptions"}" + local scheme + +- scheme=$( url_scheme $url ) ++ scheme="$( url_scheme "$url" )" + + # The cases where we return 0 are those that do not need umount and also do not need ExitTask handling. + # They thus need to be kept in sync with umount_url() so that RemoveExitTasks is used + # iff AddExitTask was used in mount_url(). + +- if ! scheme_supports_filesystem $scheme ; then ++ if ! scheme_supports_filesystem "$scheme" ; then + ### Stuff like null|tape|rsync|fish|ftp|ftps|hftp|http|https|sftp + ### Don't need to umount anything for these. + ### file: supports filesystem access, but is not mounted and unmounted, +@@ -516,7 +516,7 @@ function mount_url() { + + ### Generate a mount command + local mount_cmd +- case $scheme in ++ case "$scheme" in + (file) + ### Don't need to mount anything for file:, it is already mounted by user + return 0 +@@ -626,39 +626,39 @@ function mount_url() { + ;; + (var) + ### The mount command is given by variable in the url host +- local var=$(url_host $url) ++ local var="$(url_host "$url")" + mount_cmd="${!var} $mountpoint" + ;; + (cifs) + if [ x"$options" = x"$defaultoptions" ];then + # defaultoptions contains noatime which is not valid for cifs (issue #752) +- mount_cmd="mount $v -o rw,guest //$(url_host $url)$(url_path $url) $mountpoint" ++ mount_cmd="mount $v -o rw,guest //$(url_host "$url")$(url_path "$url") $mountpoint" + else +- mount_cmd="mount $v -o $options //$(url_host $url)$(url_path $url) $mountpoint" ++ mount_cmd="mount $v -o $options //$(url_host "$url")$(url_path "$url") $mountpoint" + fi + ;; + (usb) +- mount_cmd="mount $v -o $options $(url_path $url) $mountpoint" ++ mount_cmd="mount $v -o $options $(url_path "$url") $mountpoint" + ;; + (sshfs) +- local authority=$( url_host $url ) ++ local authority="$( url_host "$url" )" + test "$authority" || Error "Cannot run 'sshfs' because no authority '[user@]host' found in URL '$url'." +- local path=$( url_path $url ) ++ local path="$( url_path "$url" )" + test "$path" || Error "Cannot run 'sshfs' because no path found in URL '$url'." + # ensure the fuse kernel module is loaded because sshfs is based on FUSE + lsmod | grep -q '^fuse' || modprobe $verbose fuse || Error "Cannot run 'sshfs' because 'fuse' kernel module is not loadable." +- mount_cmd="sshfs $authority:$path $mountpoint -o $options" ++ mount_cmd="sshfs \"$authority\":\"$path\" $mountpoint -o $options" + ;; + (ftpfs) +- local hostname=$( url_hostname $url ) ++ local hostname="$( url_hostname "$url" )" + test "$hostname" || Error "Cannot run 'curlftpfs' because no hostname found in URL '$url'." +- local path=$( url_path $url ) ++ local path="$( url_path "$url" )" + test "$path" || Error "Cannot run 'curlftpfs' because no path found in URL '$url'." +- local username=$( url_username $url ) ++ local username="$( url_username "$url" )" + # ensure the fuse kernel module is loaded because ftpfs (via CurlFtpFS) is based on FUSE + lsmod | grep -q '^fuse' || modprobe $verbose fuse || Error "Cannot run 'curlftpfs' because 'fuse' kernel module is not loadable." + if test "$username" ; then +- local password=$( url_password $url ) ++ local password="$( url_password "$url" )" + if test "$password" ; then + # single quoting is a must for the password + mount_cmd="curlftpfs $verbose -o user='$username:$password' ftp://$hostname$path $mountpoint" +@@ -672,10 +672,10 @@ function mount_url() { + fi + ;; + (davfs) +- mount_cmd="mount $v -t davfs http://$(url_host $url)$(url_path $url) $mountpoint" ++ mount_cmd="mount $v -t davfs http://$(url_host "$url")$(url_path "$url") $mountpoint" + ;; + (*) +- mount_cmd="mount $v -t $(url_scheme $url) -o $options $(url_host $url):$(url_path $url) $mountpoint" ++ mount_cmd="mount $v -t $(url_scheme "$url") -o $options \"$(url_host "$url")\":\"$(url_path "$url")\" $mountpoint" + ;; + esac + +@@ -685,7 +685,7 @@ function mount_url() { + + Log "Mounting with '$mount_cmd'" + # eval is required when mount_cmd contains single quoted stuff (e.g. see the above mount_cmd for curlftpfs) +- eval $mount_cmd || Error "Mount command '$mount_cmd' failed." ++ eval "$mount_cmd" || Error "Mount command '$mount_cmd' failed." + + AddExitTask "perform_umount_url '$url' '$mountpoint' lazy" + return 0 +@@ -699,17 +699,17 @@ function remove_temporary_mountpoint() { + + ### Unmount url $1 at mountpoint $2, perform mountpoint cleanup and exit task + error handling + function umount_url() { +- local url=$1 +- local mountpoint=$2 ++ local url="$1" ++ local mountpoint="$2" + local scheme + +- scheme=$( url_scheme $url ) ++ scheme="$( url_scheme "$url" )" + + # The cases where we return 0 are those that do not need umount and also do not need ExitTask handling. + # They thus need to be kept in sync with mount_url() so that RemoveExitTasks is used + # iff AddExitTask was used in mount_url(). + +- if ! scheme_supports_filesystem $scheme ; then ++ if ! scheme_supports_filesystem "$scheme" ; then + ### Stuff like null|tape|rsync|fish|ftp|ftps|hftp|http|https|sftp + ### Don't need to umount anything for these. + ### file: supports filesystem access, but is not mounted and unmounted, +@@ -718,7 +718,7 @@ function umount_url() { + return 0 + fi + +- case $scheme in ++ case "$scheme" in + (file) + return 0 + ;; +@@ -738,7 +738,7 @@ function umount_url() { + # Therefore it also determines if exit task and mountpoint handling is required and returns early if not. + # The actual umount job is performed inside perform_umount_url(). + # We do not request lazy umount here because we want umount errors to be reliably reported. +- perform_umount_url $url $mountpoint || Error "Unmounting '$mountpoint' failed." ++ perform_umount_url "$url" "$mountpoint" || Error "Unmounting '$mountpoint' failed." + + RemoveExitTask "perform_umount_url '$url' '$mountpoint' lazy" + +@@ -748,9 +748,9 @@ function umount_url() { + + ### Unmount url $1 at mountpoint $2 [ lazily if $3 is set to 'lazy' and normal unmount fails ] + function perform_umount_url() { +- local url=$1 +- local mountpoint=$2 +- local lazy=${3:-} ++ local url="$1" ++ local mountpoint="$2" ++ local lazy="${3:-}" + + if test $lazy ; then + if test $lazy != "lazy" ; then +@@ -758,24 +758,24 @@ function perform_umount_url() { + fi + fi + +- case $(url_scheme $url) in ++ case "$(url_scheme "$url")" in + (sshfs) + # does ftpfs need this special case as well? +- fusermount -u ${lazy:+'-z'} $mountpoint ++ fusermount -u ${lazy:+'-z'} "$mountpoint" + ;; + (davfs) +- umount_davfs $mountpoint $lazy ++ umount_davfs "$mountpoint" $lazy + ;; + (var) + local var +- var=$(url_host $url) ++ var="$(url_host "$url")" + Log "Unmounting with '${!var} $mountpoint'" + # lazy unmount not supported with custom umount command +- ${!var} $mountpoint ++ ${!var} "$mountpoint" + ;; + (*) + # usual umount command +- umount_mountpoint $mountpoint $lazy ++ umount_mountpoint "$mountpoint" $lazy + esac + # The switch above must be the last statement in this function and the umount commands must be + # the last commands (or part of) in each branch. This ensures proper exit code propagation +@@ -785,7 +785,7 @@ function perform_umount_url() { + ### Helper which unmounts davfs mountpoint $1 and cleans up the cache, + ### performing lazy unmount if $2 = 'lazy' and normal unmount fails. + function umount_davfs() { +- local mountpoint=$1 ++ local mountpoint="$1" + local lazy="${2:-}" + + if test $lazy ; then +@@ -794,7 +794,7 @@ function umount_davfs() { + fi + fi + +- if umount_mountpoint $mountpoint ; then ++ if umount_mountpoint "$mountpoint" ; then + # Wait for 3 sek. then remove the cache-dir /var/cache/davfs + sleep 30 + # TODO: put in here the cache-dir from /etc/davfs2/davfs.conf +@@ -807,7 +807,7 @@ function umount_davfs() { + if test $lazy ; then + # try again to unmount lazily and this time do not delete the cache, it is still in use. + LogPrintError "davfs cache /var/cache/davfs2/*outputfs* needs to be cleaned up manually after the lazy unmount finishes" +- umount_mountpoint_lazy $mountpoint ++ umount_mountpoint_lazy "$mountpoint" + else + # propagate errors from umount + return $retval +@@ -819,8 +819,8 @@ function umount_davfs() { + ### Default implementation for filesystems that don't need anything fancy + ### For special umount commands use perform_umount_url() + function umount_mountpoint() { +- local mountpoint=$1 +- local lazy=${2:-} ++ local mountpoint="$1" ++ local lazy="${2:-}" + + if test $lazy ; then + if test $lazy != "lazy" ; then +@@ -830,7 +830,7 @@ function umount_mountpoint() { + + ### First, try a normal unmount, + Log "Unmounting '$mountpoint'" +- umount $v $mountpoint >&2 ++ umount $v "$mountpoint" >&2 + if [[ $? -eq 0 ]] ; then + return 0 + fi +@@ -840,7 +840,7 @@ function umount_mountpoint() { + + ### If that still fails, force unmount. + Log "Forced unmount of '$mountpoint'" +- umount $v -f $mountpoint >&2 ++ umount $v -f "$mountpoint" >&2 + if [[ $? -eq 0 ]] ; then + return 0 + fi +@@ -848,7 +848,7 @@ function umount_mountpoint() { + Log "Unmounting '$mountpoint' failed." + + if test $lazy ; then +- umount_mountpoint_lazy $mountpoint ++ umount_mountpoint_lazy "$mountpoint" + else + return 1 + fi +@@ -857,10 +857,10 @@ function umount_mountpoint() { + ### Unmount mountpoint $1 lazily + ### Preferably use "umount_mountpoint $mountpoint lazy", which attempts non-lazy unmount first. + function umount_mountpoint_lazy() { +- local mountpoint=$1 ++ local mountpoint="$1" + + LogPrint "Directory $mountpoint still mounted - trying lazy umount" +- umount $v -f -l $mountpoint >&2 ++ umount $v -f -l "$mountpoint" >&2 + } + + # Change $1 to user input or leave default value on empty input +@@ -884,9 +884,9 @@ function is_device_mounted() + local disk=$1 + [ -z "$disk" ] && echo 0 && return + +- local m=$(lsblk -n -o MOUNTPOINT $disk 2> /dev/null) ++ local m="$(lsblk -n -o MOUNTPOINT $disk 2> /dev/null)" + +- if [ -z $m ]; then ++ if [ -z "$m" ]; then + echo 0 + else + echo 1 +@@ -900,7 +900,7 @@ function get_mountpoint() + local disk=$1 + [ -z "$disk" ] && return 1 + +- local mp=$(lsblk -n -o MOUNTPOINT $disk 2> /dev/null) ++ local mp="$(lsblk -n -o MOUNTPOINT $disk 2> /dev/null)" + + echo $mp + } +@@ -909,12 +909,12 @@ function get_mountpoint() + # to re-mount the given mountpoint + function build_remount_cmd() + { +- local mp=$1 ++ local mp="$1" + [ -z "$mp" ] && return 1 + + local -a allopts=() + # Get: device, mountpoint, FS type, mount options as string +- local opt_string=$(mount | grep " $mp " | awk '{ print $1 " " $3 " " $5 " " $6 }') ++ local opt_string="$(mount | grep " $mp " | awk '{ print $1 " " $3 " " $5 " " $6 }')" + [ -z "$opt_string" ] && return 1 + + # Split string, store in array +diff --git a/usr/share/rear/lib/mkbackup-workflow.sh b/usr/share/rear/lib/mkbackup-workflow.sh +index ea8498a2..ae0ad7e3 100644 +--- a/usr/share/rear/lib/mkbackup-workflow.sh ++++ b/usr/share/rear/lib/mkbackup-workflow.sh +@@ -4,7 +4,7 @@ + WORKFLOW_mkbackup_DESCRIPTION="create rescue media and backup system" + WORKFLOWS+=( mkbackup ) + WORKFLOW_mkbackup () { +- local scheme=$(url_scheme $BACKUP_URL) ++ local scheme="$( url_scheme "$BACKUP_URL" )" + + SourceStage "prep" + +diff --git a/usr/share/rear/lib/rsync-functions.sh b/usr/share/rear/lib/rsync-functions.sh +index 862c8777..51983737 100644 +--- a/usr/share/rear/lib/rsync-functions.sh ++++ b/usr/share/rear/lib/rsync-functions.sh +@@ -39,7 +39,7 @@ function rsync_user () { + local url="$1" + local host + +- host=$(url_host "$url") ++ host="$(url_host "$url")" + + if grep -q '@' <<< $host ; then + echo "${host%%@*}" # grab user name +@@ -53,8 +53,8 @@ function rsync_host () { + local host + local path + +- host=$(url_host "$url") +- path=$(url_path "$url") ++ host="$(url_host "$url")" ++ path="$(url_path "$url")" + # remove USER@ if present + local tmp2="${host#*@}" + +@@ -77,8 +77,8 @@ function rsync_path () { + local url_without_scheme + local url_without_scheme_user + +- host=$(url_host "$url") +- path=$(url_path "$url") ++ host="$(url_host "$url")" ++ path="$(url_path "$url")" + local tmp2="${host#*@}" + + url_without_scheme="${url#*//}" +diff --git a/usr/share/rear/output/ISO/Linux-i386/810_prepare_multiple_iso.sh b/usr/share/rear/output/ISO/Linux-i386/810_prepare_multiple_iso.sh +index 76cfb802..2639d039 100644 +--- a/usr/share/rear/output/ISO/Linux-i386/810_prepare_multiple_iso.sh ++++ b/usr/share/rear/output/ISO/Linux-i386/810_prepare_multiple_iso.sh +@@ -25,13 +25,13 @@ test "$ISO_MAX_SIZE" || return 0 + # a "rear mkrescue" would overwrite an existing ISO that contains a backup. + test "mkrescue" = "$WORKFLOW" && Error "The mkrescue workflow is forbidden when ISO_MAX_SIZE is set" + +-local backup_path=$( url_path $BACKUP_URL ) ++local backup_path="$( url_path "$BACKUP_URL" )" + + # The backuparchive variable value is set in prep/NETFS/default/070_set_backup_archive.sh + # which is skipped in case of the mkrescue workflow but the mkrescue workflow is forbidden + # when ISO_MAX_SIZE is set and this script is skipped when ISO_MAX_SIZE is not set + # see https://github.com/rear/rear/pull/2063#issuecomment-469222487 +-local isofs_path=$( dirname $backuparchive ) ++local isofs_path="$( dirname "$backuparchive" )" + + # Because usr/sbin/rear sets 'shopt -s nullglob' the 'echo -n' command + # outputs nothing if nothing matches the bash globbing pattern '$backuparchive.??' +diff --git a/usr/share/rear/output/PXE/default/800_copy_to_tftp.sh b/usr/share/rear/output/PXE/default/800_copy_to_tftp.sh +index 70c1be48..aa649f47 100644 +--- a/usr/share/rear/output/PXE/default/800_copy_to_tftp.sh ++++ b/usr/share/rear/output/PXE/default/800_copy_to_tftp.sh +@@ -8,16 +8,16 @@ + + if [[ ! -z "$PXE_TFTP_URL" ]] ; then + # E.g. PXE_TFTP_URL=nfs://server/export/nfs/tftpboot +- local scheme=$( url_scheme $PXE_TFTP_URL ) ++ local scheme="$( url_scheme "$PXE_TFTP_URL" )" + + # We need filesystem access to the destination (schemes like ftp:// are not supported) +- if ! scheme_supports_filesystem $scheme ; then ++ if ! scheme_supports_filesystem "$scheme" ; then + Error "Scheme $scheme for PXE output not supported, use a scheme that supports mounting (like nfs: )" + fi + +- mount_url $PXE_TFTP_URL $BUILD_DIR/tftpbootfs $BACKUP_OPTIONS ++ mount_url "$PXE_TFTP_URL" "$BUILD_DIR/tftpbootfs" $BACKUP_OPTIONS + # However, we copy under $OUTPUT_PREFIX_PXE directory (usually HOSTNAME) to have different clients on one pxe server +- PXE_TFTP_LOCAL_PATH=$BUILD_DIR/tftpbootfs ++ PXE_TFTP_LOCAL_PATH="$BUILD_DIR/tftpbootfs" + # mode must readable for others for pxe and we copy under the client HOSTNAME (=OUTPUT_PREFIX_PXE) + mkdir -m 755 -p $v "$BUILD_DIR/tftpbootfs/$OUTPUT_PREFIX_PXE" >&2 + StopIfError "Could not mkdir '$BUILD_DIR/tftpbootfs/$OUTPUT_PREFIX_PXE'" +@@ -45,27 +45,27 @@ if [[ "$PXE_TFTP_UPLOAD_URL" ]] && [[ "$PXE_RECOVER_MODE" = "unattended" ]] ; th + # required pxe modules (and we assume that the PXE server run the same OS) + # copy pxelinux.0 and friends + # RHEL/SLES and friends +- PXELINUX_BIN=$( find_syslinux_file pxelinux.0 ) ++ PXELINUX_BIN="$( find_syslinux_file pxelinux.0 )" + if [[ -z "$PXELINUX_BIN" ]] ; then + # perhaps Debian/Ubuntu and friends + [[ -f /usr/lib/PXELINUX/pxelinux.0 ]] && PXELINUX_BIN=/usr/lib/PXELINUX/pxelinux.0 + fi + if [[ ! -z "$PXELINUX_BIN" ]] ; then +- cp $v "$PXELINUX_BIN" $BUILD_DIR/tftpbootfs >&2 ++ cp $v "$PXELINUX_BIN" "$BUILD_DIR/tftpbootfs" >&2 + fi +- syslinux_modules_dir=$( find_syslinux_modules_dir menu.c32 ) +- [[ -z "$syslinux_modules_dir" ]] && syslinux_modules_dir=$(dirname $PXELINUX_BIN) +- cp $v $syslinux_modules_dir/ldlinux.c32 $BUILD_DIR/tftpbootfs >&2 +- cp $v $syslinux_modules_dir/libcom32.c32 $BUILD_DIR/tftpbootfs >&2 +- cp $v $syslinux_modules_dir/libutil.c32 $BUILD_DIR/tftpbootfs >&2 +- cp $v $syslinux_modules_dir/menu.c32 $BUILD_DIR/tftpbootfs >&2 +- cp $v $syslinux_modules_dir/chain.c32 $BUILD_DIR/tftpbootfs >&2 +- cp $v $syslinux_modules_dir/hdt.c32 $BUILD_DIR/tftpbootfs >&2 +- cp $v $syslinux_modules_dir/reboot.c32 $BUILD_DIR/tftpbootfs >&2 ++ syslinux_modules_dir="$( find_syslinux_modules_dir menu.c32 )" ++ [[ -z "$syslinux_modules_dir" ]] && syslinux_modules_dir="$(dirname $PXELINUX_BIN)" ++ cp $v $syslinux_modules_dir/ldlinux.c32 "$BUILD_DIR/tftpbootfs" >&2 ++ cp $v $syslinux_modules_dir/libcom32.c32 "$BUILD_DIR/tftpbootfs" >&2 ++ cp $v $syslinux_modules_dir/libutil.c32 "$BUILD_DIR/tftpbootfs" >&2 ++ cp $v $syslinux_modules_dir/menu.c32 "$BUILD_DIR/tftpbootfs" >&2 ++ cp $v $syslinux_modules_dir/chain.c32 "$BUILD_DIR/tftpbootfs" >&2 ++ cp $v $syslinux_modules_dir/hdt.c32 "$BUILD_DIR/tftpbootfs" >&2 ++ cp $v $syslinux_modules_dir/reboot.c32 "$BUILD_DIR/tftpbootfs" >&2 + if [[ -r "$syslinux_modules_dir/poweroff.com" ]] ; then +- cp $v $syslinux_modules_dir/poweroff.com $BUILD_DIR/tftpbootfs >&2 ++ cp $v $syslinux_modules_dir/poweroff.com "$BUILD_DIR/tftpbootfs" >&2 + elif [[ -r "$syslinux_modules_dir/poweroff.c32" ]] ; then +- cp $v $syslinux_modules_dir/poweroff.c32 $BUILD_DIR/tftpbootfs >&2 ++ cp $v $syslinux_modules_dir/poweroff.c32 "$BUILD_DIR/tftpbootfs" >&2 + fi + chmod 644 $BUILD_DIR/tftpbootfs/*.c32 + chmod 644 $BUILD_DIR/tftpbootfs/*.0 +@@ -74,7 +74,7 @@ fi + + if [[ ! -z "$PXE_TFTP_URL" ]] ; then + LogPrint "Copied kernel+initrd $( du -shc $KERNEL_FILE "$TMP_DIR/$REAR_INITRD_FILENAME" | tail -n 1 | tr -s "\t " " " | cut -d " " -f 1 ) to $PXE_TFTP_URL/$OUTPUT_PREFIX_PXE" +- umount_url $PXE_TFTP_URL $BUILD_DIR/tftpbootfs ++ umount_url "$PXE_TFTP_URL" "$BUILD_DIR/tftpbootfs" + else + # legacy way PXE_TFTP_PATH + LogPrint "Copied kernel+initrd $( du -shc $KERNEL_FILE "$TMP_DIR/$REAR_INITRD_FILENAME" | tail -n 1 | tr -s "\t " " " | cut -d " " -f 1 ) to $PXE_TFTP_PATH" +diff --git a/usr/share/rear/output/PXE/default/810_create_pxelinux_cfg.sh b/usr/share/rear/output/PXE/default/810_create_pxelinux_cfg.sh +index 113428d4..1ed1cb0a 100644 +--- a/usr/share/rear/output/PXE/default/810_create_pxelinux_cfg.sh ++++ b/usr/share/rear/output/PXE/default/810_create_pxelinux_cfg.sh +@@ -11,18 +11,18 @@ local pxe_local_path + if [[ ! -z "$PXE_CONFIG_URL" ]] ; then + # E.g. PXE_CONFIG_URL=nfs://server/export/nfs/tftpboot/pxelinux.cfg + # Better be sure that on 'server' the directory /export/nfs/tftpboot/pxelinux.cfg exists +- local scheme=$( url_scheme $PXE_CONFIG_URL ) ++ local scheme="$( url_scheme "$PXE_CONFIG_URL" )" + + # We need filesystem access to the destination (schemes like ftp:// are not supported) +- if ! scheme_supports_filesystem $scheme ; then ++ if ! scheme_supports_filesystem "$scheme" ; then + Error "Scheme $scheme for PXE output not supported, use a scheme that supports mounting (like nfs: )" + fi + +- mount_url $PXE_CONFIG_URL $BUILD_DIR/tftpbootfs $BACKUP_OPTIONS +- PXE_LOCAL_PATH=$BUILD_DIR/tftpbootfs ++ mount_url "$PXE_CONFIG_URL" "$BUILD_DIR/tftpbootfs" $BACKUP_OPTIONS ++ PXE_LOCAL_PATH="$BUILD_DIR/tftpbootfs" + else + # legacy way using PXE_LOCAL_PATH default +- PXE_LOCAL_PATH=$PXE_CONFIG_PATH ++ PXE_LOCAL_PATH="$PXE_CONFIG_PATH" + fi + + # PXE_CONFIG_PREFIX is a "string" (by default rear-) - is the name of PXE boot configuration of $HOSTNAME +@@ -35,7 +35,7 @@ if [[ ! -z "$PXE_CONFIG_URL" ]] ; then + else + # legacy way using PXE_LOCAL_PATH default + cat >"$PXE_LOCAL_PATH/$PXE_CONFIG_FILE" </dev/null + + if [[ ! -z "$PXE_CONFIG_URL" ]] ; then + LogPrint "Created pxelinux config '${PXE_CONFIG_PREFIX}$HOSTNAME' and symlinks for $PXE_CREATE_LINKS adresses in $PXE_CONFIG_URL" +- umount_url $PXE_TFTP_URL $BUILD_DIR/tftpbootfs ++ umount_url "$PXE_TFTP_URL" "$BUILD_DIR/tftpbootfs" + else + LogPrint "Created pxelinux config '${PXE_CONFIG_PREFIX}$HOSTNAME' and symlinks for $PXE_CREATE_LINKS adresses in $PXE_CONFIG_PATH" + # Add to result files +diff --git a/usr/share/rear/output/default/100_mount_output_path.sh b/usr/share/rear/output/default/100_mount_output_path.sh +index 34ea8e5e..765e47f7 100644 +--- a/usr/share/rear/output/default/100_mount_output_path.sh ++++ b/usr/share/rear/output/default/100_mount_output_path.sh +@@ -6,4 +6,4 @@ if [[ -z "$OUTPUT_URL" ]] ; then + return + fi + +-mount_url $OUTPUT_URL $BUILD_DIR/outputfs $OUTPUT_OPTIONS ++mount_url "$OUTPUT_URL" "$BUILD_DIR/outputfs" $OUTPUT_OPTIONS +diff --git a/usr/share/rear/output/default/150_save_copy_of_prefix_dir.sh b/usr/share/rear/output/default/150_save_copy_of_prefix_dir.sh +index 06326114..5d34f93d 100644 +--- a/usr/share/rear/output/default/150_save_copy_of_prefix_dir.sh ++++ b/usr/share/rear/output/default/150_save_copy_of_prefix_dir.sh +@@ -3,16 +3,16 @@ + [ -z "${KEEP_OLD_OUTPUT_COPY}" ] && return + + # do not do this for tapes and special attention for file:///path +-local scheme=$( url_scheme $OUTPUT_URL ) +-local path=$( url_path $OUTPUT_URL ) ++local scheme="$( url_scheme "$OUTPUT_URL" )" ++local path="$( url_path "$OUTPUT_URL" )" + + # if filesystem access to url is unsupported return silently (e.g. scheme tape) + scheme_supports_filesystem $scheme || return 0 + +-local opath=$( output_path $scheme $path ) ++local opath="$( output_path "$scheme" "$path" )" + + # an old lockfile from a previous run not cleaned up by output is possible +-[[ -f ${opath}/.lockfile ]] && rm -f ${opath}/.lockfile >&2 ++[[ -f "${opath}/.lockfile" ]] && rm -f "${opath}/.lockfile" >&2 + + if test -d "${opath}" ; then + rm -rf $v "${opath}.old" || Error "Could not remove '${opath}.old'" +diff --git a/usr/share/rear/output/default/200_make_prefix_dir.sh b/usr/share/rear/output/default/200_make_prefix_dir.sh +index 42ade4b0..f28fbbbd 100644 +--- a/usr/share/rear/output/default/200_make_prefix_dir.sh ++++ b/usr/share/rear/output/default/200_make_prefix_dir.sh +@@ -7,13 +7,13 @@ + # but it is also happens for local stuff like OUTPUT_URL=usb:///dev/disk/by-label/REAR-000 + + # Do not do this for tapes and special attention for file:///path +-local scheme=$( url_scheme $OUTPUT_URL ) +-local path=$( url_path $OUTPUT_URL ) ++local scheme="$( url_scheme "$OUTPUT_URL" )" ++local path="$( url_path "$OUTPUT_URL" )" + + # If filesystem access to url is unsupported return silently (e.g. scheme tape) + scheme_supports_filesystem $scheme || return 0 + +-local opath=$( output_path $scheme $path ) ++local opath="$( output_path "$scheme" "$path" )" + + # Create $OUTPUT_PREFIX sub-directory. + # That directory should be neither world-readable nor world-writable +diff --git a/usr/share/rear/output/default/250_create_lock.sh b/usr/share/rear/output/default/250_create_lock.sh +index d792b036..5e17a48e 100644 +--- a/usr/share/rear/output/default/250_create_lock.sh ++++ b/usr/share/rear/output/default/250_create_lock.sh +@@ -2,13 +2,13 @@ + # made by a previous mkrescue run when the variable KEEP_OLD_OUTPUT_COPY has been set + + # do not do this for tapes and special attention for file:///path +-local scheme=$( url_scheme $OUTPUT_URL ) +-local path=$( url_path $OUTPUT_URL ) ++local scheme="$( url_scheme "$OUTPUT_URL" )" ++local path="$( url_path "$OUTPUT_URL" )" + + # if filesystem access to url is unsupported return silently (e.g. scheme tape) + scheme_supports_filesystem $scheme || return 0 + +-local opath=$( output_path $scheme $path ) ++local opath="$( output_path "$scheme" "$path" )" + + if test -d "${opath}" ; then + > "${opath}/.lockfile" || Error "Could not create '${opath}/.lockfile'" +diff --git a/usr/share/rear/output/default/950_copy_result_files.sh b/usr/share/rear/output/default/950_copy_result_files.sh +index a44542df..6a0062e7 100644 +--- a/usr/share/rear/output/default/950_copy_result_files.sh ++++ b/usr/share/rear/output/default/950_copy_result_files.sh +@@ -7,11 +7,11 @@ + # that would need to be copied here to the output location: + test "${RESULT_FILES[*]:-}" || return 0 + +-local scheme=$( url_scheme $OUTPUT_URL ) +-local host=$( url_host $OUTPUT_URL ) +-local path=$( url_path $OUTPUT_URL ) ++local scheme="$( url_scheme "$OUTPUT_URL" )" ++local host="$( url_host "$OUTPUT_URL" )" ++local path="$( url_path "$OUTPUT_URL" )" + +-if [ -z "$OUTPUT_URL" ] || ! scheme_accepts_files $scheme ; then ++if [ -z "$OUTPUT_URL" ] || ! scheme_accepts_files "$scheme" ; then + if [ "$scheme" == "null" -o -z "$OUTPUT_URL" ] ; then + # There are result files to copy, but OUTPUT_URL=null indicates that we are not interested in them + # TODO: empty OUTPUT_URL seems to be equivalent to null, should we continue to allow that, +diff --git a/usr/share/rear/output/default/970_remove_lock.sh b/usr/share/rear/output/default/970_remove_lock.sh +index 3b1b97cc..255afeda 100644 +--- a/usr/share/rear/output/default/970_remove_lock.sh ++++ b/usr/share/rear/output/default/970_remove_lock.sh +@@ -1,11 +1,11 @@ + # remove the lockfile +-local scheme=$(url_scheme $OUTPUT_URL) +-local path=$(url_path $OUTPUT_URL) ++local scheme="$( url_scheme "$OUTPUT_URL" )" ++local path="$( url_path "$OUTPUT_URL" )" + + # if filesystem access to url is unsupported return silently (e.g. scheme tape) +-scheme_supports_filesystem $scheme || return 0 ++scheme_supports_filesystem "$scheme" || return 0 + +-local opath=$( output_path $scheme $path ) ++local opath="$( output_path "$scheme" "$path" )" + + # when OUTPUT_URL=BACKUP_URL we keep the lockfile to avoid double moves of the directory + [[ "$OUTPUT_URL" != "$BACKUP_URL" ]] && rm -f $v "${opath}/.lockfile" >&2 +diff --git a/usr/share/rear/output/default/980_umount_output_dir.sh b/usr/share/rear/output/default/980_umount_output_dir.sh +index abf0cd53..1ea42dbe 100644 +--- a/usr/share/rear/output/default/980_umount_output_dir.sh ++++ b/usr/share/rear/output/default/980_umount_output_dir.sh +@@ -8,4 +8,4 @@ if [[ -z "$OUTPUT_URL" ]] ; then + return + fi + +-umount_url $OUTPUT_URL $BUILD_DIR/outputfs ++umount_url "$OUTPUT_URL" "$BUILD_DIR/outputfs" +diff --git a/usr/share/rear/prep/DUPLICITY/default/200_find_duply_profile.sh b/usr/share/rear/prep/DUPLICITY/default/200_find_duply_profile.sh +index 0461d643..f5e6f4bd 100644 +--- a/usr/share/rear/prep/DUPLICITY/default/200_find_duply_profile.sh ++++ b/usr/share/rear/prep/DUPLICITY/default/200_find_duply_profile.sh +@@ -27,7 +27,7 @@ if [ "$BACKUP_PROG" = "duplicity" ] && has_binary duply; then + # still here? + if [[ "$SOURCE" = "/" ]]; then + DUPLY_PROFILE_FILE=$CONF +- DUPLY_PROFILE=$( dirname $CONF ) # /root/.duply/mycloud/conf -> /root/.duply/mycloud ++ DUPLY_PROFILE="$( dirname "$CONF" )" # /root/.duply/mycloud/conf -> /root/.duply/mycloud + DUPLY_PROFILE=${DUPLY_PROFILE##*/} # /root/.duply/mycloud -> mycloud + break # the loop + else +@@ -40,7 +40,7 @@ if [ "$BACKUP_PROG" = "duplicity" ] && has_binary duply; then + # we found the duply program; check if we can find a profile defined in ReaR config file + if [[ -z "$DUPLY_PROFILE" ]]; then + # no profile pre-set in local.conf; let's try to find one +- DUPLY_PROFILE=$( find /etc/duply $ROOT_HOME_DIR/.duply -name conf 2>&1) ++ DUPLY_PROFILE="$( find /etc/duply $ROOT_HOME_DIR/.duply -name conf 2>&1)" + # above result could contain more than one profile + [[ -z "$DUPLY_PROFILE" ]] && return + find_duply_profile "$DUPLY_PROFILE" +@@ -50,7 +50,7 @@ if [ "$BACKUP_PROG" = "duplicity" ] && has_binary duply; then + [[ -z "$DUPLY_PROFILE" ]] && return + + # retrieve the real path of DUPLY_PROFILE in case DUPLY_PROFILE was defined local.conf +- DUPLY_PROFILE_FILE=$( ls /etc/duply/$DUPLY_PROFILE/conf $ROOT_HOME_DIR/.duply/$DUPLY_PROFILE/conf 2>/dev/null ) ++ DUPLY_PROFILE_FILE="$( ls /etc/duply/$DUPLY_PROFILE/conf $ROOT_HOME_DIR/.duply/$DUPLY_PROFILE/conf 2>/dev/null )" + # Assuming we have a duply configuration we must have a path, right? + [[ -z "$DUPLY_PROFILE_FILE" ]] && return + find_duply_profile "$DUPLY_PROFILE_FILE" +@@ -71,10 +71,10 @@ if [ "$BACKUP_PROG" = "duplicity" ] && has_binary duply; then + # check the scheme of the TARGET variable in DUPLY_PROFILE ($CONF has full path) to be + # sure we have all executables we need in the rescue image + source $DUPLY_PROFILE_FILE +- local scheme=$( url_scheme $TARGET ) +- case $scheme in ++ local scheme="$( url_scheme "$TARGET" )" ++ case "$scheme" in + (sftp|rsync|scp) +- PROGS+=( $scheme ) ++ PROGS+=( "$scheme" ) + esac + fi + +diff --git a/usr/share/rear/prep/DUPLICITY/default/210_check_NETFS_URL_requirements.sh b/usr/share/rear/prep/DUPLICITY/default/210_check_NETFS_URL_requirements.sh +index 3b4dc7b7..1a4856fd 100644 +--- a/usr/share/rear/prep/DUPLICITY/default/210_check_NETFS_URL_requirements.sh ++++ b/usr/share/rear/prep/DUPLICITY/default/210_check_NETFS_URL_requirements.sh +@@ -19,9 +19,9 @@ + StopIfError "You must specify either BACKUP_DUPLICITY_URL or BACKUP_DUPLICITY_NETFS_URL or BACKUP_DUPLICITY_NETFS_MOUNTCMD and BACKUP_DUPLICITY_NETFS_UMOUNTCMD !" + + if [[ "$BACKUP_DUPLICITY_NETFS_URL" ]] ; then +- local scheme=$( url_scheme $BACKUP_DUPLICITY_NETFS_URL ) +- local hostname=$( url_hostname $BACKUP_DUPLICITY_NETFS_URL ) +- local path=$( url_path $BACKUP_DUPLICITY_NETFS_URL ) ++ local scheme="$( url_scheme "$BACKUP_DUPLICITY_NETFS_URL" )" ++ local hostname="$( url_hostname "$BACKUP_DUPLICITY_NETFS_URL" )" ++ local path="$( url_path "$BACKUP_DUPLICITY_NETFS_URL" )" + + ### check for vaild BACKUP_DUPLICITY_NETFS_URL schemes + ### see https://github.com/rear/rear/issues/842 +diff --git a/usr/share/rear/prep/GNU/Linux/300_check_backup_and_output_url.sh b/usr/share/rear/prep/GNU/Linux/300_check_backup_and_output_url.sh +index ebf8315b..4819292d 100644 +--- a/usr/share/rear/prep/GNU/Linux/300_check_backup_and_output_url.sh ++++ b/usr/share/rear/prep/GNU/Linux/300_check_backup_and_output_url.sh +@@ -16,9 +16,9 @@ + local url="" + for url in "$BACKUP_URL" "$OUTPUT_URL" ; do + test "$url" || continue +- local scheme=$( url_scheme $url ) +- local authority=$( url_host $url ) +- local path=$( url_path $url ) ++ local scheme="$( url_scheme "$url" )" ++ local authority="$( url_host "$url" )" ++ local path="$( url_path "$url" )" + case "$scheme" in + (file|tape|usb) + # file:// tape:// usb:// URLs must not have an authority part (scheme://authority/path) +diff --git a/usr/share/rear/prep/ISO/GNU/Linux/340_add_isofs_module.sh b/usr/share/rear/prep/ISO/GNU/Linux/340_add_isofs_module.sh +index 3e705e34..0187a62e 100644 +--- a/usr/share/rear/prep/ISO/GNU/Linux/340_add_isofs_module.sh ++++ b/usr/share/rear/prep/ISO/GNU/Linux/340_add_isofs_module.sh +@@ -2,7 +2,7 @@ + # loopback mount the ISO containing the backup + # BACKUP_URL=iso://backup + +-local scheme=$(url_scheme $BACKUP_URL) ++local scheme="$( url_scheme "$BACKUP_URL" )" + + case "$scheme" in + (iso) +diff --git a/usr/share/rear/prep/NETFS/default/050_check_NETFS_requirements.sh b/usr/share/rear/prep/NETFS/default/050_check_NETFS_requirements.sh +index bcee8e96..65ea9609 100644 +--- a/usr/share/rear/prep/NETFS/default/050_check_NETFS_requirements.sh ++++ b/usr/share/rear/prep/NETFS/default/050_check_NETFS_requirements.sh +@@ -16,16 +16,16 @@ + StopIfError "You must specify either BACKUP_URL or BACKUP_MOUNTCMD and BACKUP_UMOUNTCMD !" + + # url_scheme results the empty string when $BACKUP_URL is empty: +-local scheme=$( url_scheme $BACKUP_URL ) ++local scheme="$( url_scheme "$BACKUP_URL" )" + + if [[ "$BACKUP_URL" ]] ; then + +- local hostname=$( url_hostname $BACKUP_URL ) +- local path=$( url_path $BACKUP_URL ) ++ local hostname="$( url_hostname "$BACKUP_URL" )" ++ local path="$( url_path "$BACKUP_URL" )" + + ### check for vaild BACKUP_URL schemes + ### see https://github.com/rear/rear/issues/842 +- case $scheme in ++ case "$scheme" in + (nfs|cifs|usb|tape|file|iso|sshfs|ftpfs) + # do nothing for vaild BACKUP_URL schemes + : +diff --git a/usr/share/rear/prep/NETFS/default/070_set_backup_archive.sh b/usr/share/rear/prep/NETFS/default/070_set_backup_archive.sh +index b7cd8b42..3d1cb7a4 100644 +--- a/usr/share/rear/prep/NETFS/default/070_set_backup_archive.sh ++++ b/usr/share/rear/prep/NETFS/default/070_set_backup_archive.sh +@@ -22,12 +22,12 @@ fi + local backup_file_suffix="$BACKUP_PROG_SUFFIX$BACKUP_PROG_COMPRESS_SUFFIX" + local backup_file_name="$BACKUP_PROG_ARCHIVE$backup_file_suffix" + +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" + case "$scheme" in + (file|iso) + # Define the output path according to the scheme +- local outputpath=$( backup_path $scheme $path ) ++ local outputpath="$( backup_path "$scheme" "$path" )" + backuparchive="$outputpath/$backup_file_name" + LogPrint "Using backup archive '$backuparchive'" + return +@@ -35,7 +35,7 @@ case "$scheme" in + (tape) + # TODO: Check if that case is really needed. + # Perhaps prep/default/030_translate_tape.sh does already all what is needed. +- backuparchive=$path ++ backuparchive="$path" + LogPrint "Using backup archive '$backuparchive'" + return + ;; +diff --git a/usr/share/rear/prep/NETFS/default/400_automatic_exclude_recreate.sh b/usr/share/rear/prep/NETFS/default/400_automatic_exclude_recreate.sh +index 2c59ad07..4bf38fa0 100644 +--- a/usr/share/rear/prep/NETFS/default/400_automatic_exclude_recreate.sh ++++ b/usr/share/rear/prep/NETFS/default/400_automatic_exclude_recreate.sh +@@ -5,8 +5,8 @@ + # Verify a local backup directory in BACKUP_URL=file:///path and + # add its mountpoint to the EXCLUDE_RECREATE array (if necessary). + +-local scheme=$( url_scheme $BACKUP_URL ) +-local backup_directory=$( url_path $BACKUP_URL ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local backup_directory="$( url_path "$BACKUP_URL" )" + local backup_directory_mountpoint="" + + case $scheme in +@@ -28,7 +28,7 @@ case $scheme in + mkdir $v -p "$backup_directory" >&2 || Error "Could not create backup directory '$backup_directory' (from URL '$BACKUP_URL')." + fi + test -d "$backup_directory" || Error "URL '$BACKUP_URL' specifies '$backup_directory' which is not a directory." +- backup_directory_mountpoint=$( df -P "$backup_directory" | tail -1 | awk '{print $6}' ) ++ backup_directory_mountpoint="$( df -P "$backup_directory" | tail -1 | awk '{print $6}' )" + test "/" = "$backup_directory_mountpoint" && Error "URL '$BACKUP_URL' has the backup directory '$backup_directory' in the '/' filesystem which is forbidden." + # When the mountpoint of the backup directory is not yet excluded add its mountpoint to the EXCLUDE_RECREATE array: + if ! grep -q "$backup_directory_mountpoint" <<< "${EXCLUDE_RECREATE[*]}" ; then +diff --git a/usr/share/rear/prep/RBME/default/050_include_rbme_requirements.sh b/usr/share/rear/prep/RBME/default/050_include_rbme_requirements.sh +index 556d2e5f..06c41987 100644 +--- a/usr/share/rear/prep/RBME/default/050_include_rbme_requirements.sh ++++ b/usr/share/rear/prep/RBME/default/050_include_rbme_requirements.sh +@@ -1,11 +1,11 @@ + +-scheme=$(url_scheme "$BACKUP_URL") ++scheme="$(url_scheme "$BACKUP_URL")" + case $scheme in + (nfs) + PROGS+=( + showmount +- mount.$(url_scheme $BACKUP_URL) +- umount.$(url_scheme $BACKUP_URL) ++ mount.$(url_scheme "$BACKUP_URL") ++ umount.$(url_scheme "$BACKUP_URL") + ) + ;; + (*) +diff --git a/usr/share/rear/prep/RSYNC/default/100_check_rsync.sh b/usr/share/rear/prep/RSYNC/default/100_check_rsync.sh +index 448a1b1a..64d18800 100644 +--- a/usr/share/rear/prep/RSYNC/default/100_check_rsync.sh ++++ b/usr/share/rear/prep/RSYNC/default/100_check_rsync.sh +@@ -7,7 +7,7 @@ if test -z "$BACKUP_URL" ; then + Error "Missing BACKUP_URL=rsync://[USER@]HOST[:PORT][::]/PATH !" + fi + +-local scheme=$(url_scheme $BACKUP_URL) # url_scheme still recognizes old style ++local scheme="$(url_scheme "$BACKUP_URL")" # url_scheme still recognizes old style + + if [[ "$scheme" != "rsync" ]]; then + Error "Missing BACKUP_URL=rsync://[USER@]HOST[:PORT][::]/PATH !" +diff --git a/usr/share/rear/prep/USB/default/060_set_usb_device.sh b/usr/share/rear/prep/USB/default/060_set_usb_device.sh +index aac579e1..9fdbdcfb 100644 +--- a/usr/share/rear/prep/USB/default/060_set_usb_device.sh ++++ b/usr/share/rear/prep/USB/default/060_set_usb_device.sh +@@ -1,8 +1,8 @@ + ### set USB device from OUTPUT_URL + if [[ -z "$USB_DEVICE" ]] && [[ "$OUTPUT_URL" ]]; then +- local scheme=$(url_scheme $OUTPUT_URL) +- local path=$(url_path $OUTPUT_URL) +- case $scheme in ++ local scheme="$( url_scheme "$OUTPUT_URL" )" ++ local path="$( url_path "$OUTPUT_URL" )" ++ case "$scheme" in + (usb) + USB_DEVICE="$path" + ;; +@@ -30,8 +30,8 @@ test "$USB_PREFIX" || USB_PREFIX="rear/$HOSTNAME/$(date +%Y%m%d.%H%M)" + + ### Change NETFS_PREFIX to USB_PREFIX if our backup URL is on USB + if [[ "$BACKUP_URL" ]] ; then +- local scheme=$(url_scheme $BACKUP_URL) +- case $scheme in ++ local scheme="$( url_scheme "$BACKUP_URL" )" ++ case "$scheme" in + (usb) + NETFS_PREFIX="$USB_PREFIX" + ;; +diff --git a/usr/share/rear/prep/default/030_translate_tape.sh b/usr/share/rear/prep/default/030_translate_tape.sh +index 7efb6603..b992683a 100644 +--- a/usr/share/rear/prep/default/030_translate_tape.sh ++++ b/usr/share/rear/prep/default/030_translate_tape.sh +@@ -1,9 +1,9 @@ + # Provide the necessary variables to use tape/obdr information + + if [[ "$BACKUP_URL" ]] ; then +- backup_scheme=$(url_scheme "$BACKUP_URL") ++ backup_scheme="$(url_scheme "$BACKUP_URL")" + if [[ "$backup_scheme" == tape || "$backup_scheme" == obdr ]] ; then +- testdevice=$(url_path "$BACKUP_URL") ++ testdevice="$(url_path "$BACKUP_URL")" + ### Complain when both are specified, but don't match + if [[ "$TAPE_DEVICE" && "$TAPE_DEVICE" != "$testdevice" ]]; then + Error "Tape device in BACKUP_URL '$BACKUP_URL' and TAPE_DEVICE '$TAPE_DEVICE' is not the same" +diff --git a/usr/share/rear/prep/default/040_check_backup_and_output_scheme.sh b/usr/share/rear/prep/default/040_check_backup_and_output_scheme.sh +index 8d34d305..09461509 100644 +--- a/usr/share/rear/prep/default/040_check_backup_and_output_scheme.sh ++++ b/usr/share/rear/prep/default/040_check_backup_and_output_scheme.sh +@@ -4,8 +4,8 @@ + # + + if test "$BACKUP_URL" ; then +- local backup_scheme=$( url_scheme "$BACKUP_URL" ) +- case $backup_scheme in ++ local backup_scheme="$( url_scheme "$BACKUP_URL" )" ++ case "$backup_scheme" in + (iso) + case $WORKFLOW in + (mkrescue|mkbackuponly) +@@ -52,8 +52,8 @@ else + fi + + if test "$OUTPUT_URL" ; then +- local output_scheme=$( url_scheme "$OUTPUT_URL" ) +- case $output_scheme in ++ local output_scheme="$( url_scheme "$OUTPUT_URL" )" ++ case "$output_scheme" in + (fish|ftp|ftps|hftp|http|https|sftp) + local required_prog='lftp' + has_binary $required_prog || Error "The OUTPUT_URL scheme '$output_scheme' requires the '$required_prog' command which is missing" +diff --git a/usr/share/rear/restore/BLOCKCLONE/default/390_create_partitions.sh b/usr/share/rear/restore/BLOCKCLONE/default/390_create_partitions.sh +index eb1cbdce..35993506 100644 +--- a/usr/share/rear/restore/BLOCKCLONE/default/390_create_partitions.sh ++++ b/usr/share/rear/restore/BLOCKCLONE/default/390_create_partitions.sh +@@ -9,8 +9,8 @@ if [ -z "$BLOCKCLONE_SAVE_MBR_DEV" ]; then + return + fi + +-local backup_path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local backup_path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # Destination partition is not present, try to recreate. + if [ ! -b "$BLOCKCLONE_SOURCE_DEV" ]; then +diff --git a/usr/share/rear/restore/NETFS/default/380_prepare_multiple_isos.sh b/usr/share/rear/restore/NETFS/default/380_prepare_multiple_isos.sh +index 458e9728..d8de8d37 100644 +--- a/usr/share/rear/restore/NETFS/default/380_prepare_multiple_isos.sh ++++ b/usr/share/rear/restore/NETFS/default/380_prepare_multiple_isos.sh +@@ -1,9 +1,9 @@ + # 380_prepare_multiple_isos + # + +-local scheme=$(url_scheme $BACKUP_URL) +-local path=$(url_path $BACKUP_URL) +-local opath=$(backup_path $scheme $path) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + [[ -f "${opath}/backup.splitted" ]] || return 0 + +diff --git a/usr/share/rear/restore/NETFS/default/400_restore_backup.sh b/usr/share/rear/restore/NETFS/default/400_restore_backup.sh +index f0bb8671..9daede32 100644 +--- a/usr/share/rear/restore/NETFS/default/400_restore_backup.sh ++++ b/usr/share/rear/restore/NETFS/default/400_restore_backup.sh +@@ -2,9 +2,9 @@ + # 400_restore_backup.sh + # + +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # Create backup restore log file name: + local backup_restore_log_dir="$VAR_DIR/restore" +@@ -54,7 +54,7 @@ if test -f $TMP_DIR/backup.splitted ; then + touch $waiting_for_medium_flag_file + while ! test -f "$backup_file_path" ; do + umount "$BUILD_DIR/outputfs" +- cdrom_drive_names=$( cat /proc/sys/dev/cdrom/info | grep -i "drive name:" | awk '{print $3 " " $4}' ) ++ cdrom_drive_names="$( cat /proc/sys/dev/cdrom/info | grep -i "drive name:" | awk '{print $3 " " $4}' )" + ProgressInfo "Insert medium labelled $vol_name (containing $backup_file_name) in a CD-ROM drive ($cdrom_drive_names) ..." + sleep 3 + for cdrom_dev in $cdrom_drive_names ; do +@@ -107,7 +107,7 @@ fi + for restore_input in "${RESTORE_ARCHIVES[@]}" ; do + # Create backup restore log file name (a different one for each restore_input). + # Each restore_input is a path like '/tmp/rear.XXXX/outputfs/f121/backup.tar.gz': +- restore_input_basename=$( basename $restore_input ) ++ restore_input_basename="$( basename "$restore_input" )" + backup_restore_log_file=$backup_restore_log_dir/$backup_restore_log_prefix.$restore_input_basename.$MASTER_PID.$backup_restore_log_suffix + cat /dev/null >$backup_restore_log_file + LogPrint "Restoring from '$restore_input' (restore log in $backup_restore_log_file) ..." +diff --git a/usr/share/rear/restore/NETFS/default/500_selinux_autorelabel.sh b/usr/share/rear/restore/NETFS/default/500_selinux_autorelabel.sh +index e212b681..0dabc9ef 100644 +--- a/usr/share/rear/restore/NETFS/default/500_selinux_autorelabel.sh ++++ b/usr/share/rear/restore/NETFS/default/500_selinux_autorelabel.sh +@@ -8,9 +8,9 @@ + # answer is yes force auto relabeling the files after the reboot to have a correct SELinux labeled system. + + # If selinux was turned off for the backup we have to label the +-local scheme=$( url_scheme $BACKUP_URL ) +-local path=$( url_path $BACKUP_URL ) +-local opath=$( backup_path $scheme $path ) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + if test -f "$opath/selinux.autorelabel" ; then + touch $TARGET_FS_ROOT/.autorelabel +diff --git a/usr/share/rear/restore/RBME/default/400_restore_backup.sh b/usr/share/rear/restore/RBME/default/400_restore_backup.sh +index 3e97e16b..210d84b2 100644 +--- a/usr/share/rear/restore/RBME/default/400_restore_backup.sh ++++ b/usr/share/rear/restore/RBME/default/400_restore_backup.sh +@@ -4,7 +4,7 @@ fi + + local backup_prog_rc + +-scheme=$(url_scheme "$BACKUP_URL") ++scheme="$( url_scheme "$BACKUP_URL" )" + + LogPrint "Restoring from backup $RBME_BACKUP." + ProgressStart "Preparing restore operation" +diff --git a/usr/share/rear/restore/YUM/default/410_restore_backup.sh b/usr/share/rear/restore/YUM/default/410_restore_backup.sh +index a114c5f6..0149475b 100644 +--- a/usr/share/rear/restore/YUM/default/410_restore_backup.sh ++++ b/usr/share/rear/restore/YUM/default/410_restore_backup.sh +@@ -12,9 +12,9 @@ LogPrint "Restoring system files (YUM_BACKUP_FILES=$YUM_BACKUP_FILES)" + # see https://github.com/rear/rear/wiki/Coding-Style + set -e -u -o pipefail + +-local scheme=$(url_scheme $BACKUP_URL) +-local path=$(url_path $BACKUP_URL) +-local opath=$(backup_path $scheme $path) ++local scheme="$( url_scheme "$BACKUP_URL" )" ++local path="$( url_path "$BACKUP_URL" )" ++local opath="$( backup_path "$scheme" "$path" )" + + # The RESTORE_ARCHIVES array contains the restore input files. + # If it is not set, RESTORE_ARCHIVES is only one element which is the backup archive: +diff --git a/usr/share/rear/verify/NETFS/default/050_start_required_nfs_daemons.sh b/usr/share/rear/verify/NETFS/default/050_start_required_nfs_daemons.sh +index d4894219..a47712d8 100644 +--- a/usr/share/rear/verify/NETFS/default/050_start_required_nfs_daemons.sh ++++ b/usr/share/rear/verify/NETFS/default/050_start_required_nfs_daemons.sh +@@ -31,7 +31,7 @@ + # and predefining all used variables + # see https://github.com/rear/rear/wiki/Coding-Style + # +-local backup_url_scheme=$( url_scheme "$BACKUP_URL" ) ++local backup_url_scheme="$( url_scheme "$BACKUP_URL" )" + # nothing to do when backup_url_scheme is not "nfs" + test "nfs" = "$backup_url_scheme" || return 0 + # predefine all used variables +diff --git a/usr/share/rear/verify/RBME/default/150_check_nobody_uid_nfs.sh b/usr/share/rear/verify/RBME/default/150_check_nobody_uid_nfs.sh +index edf15154..7a24da1d 100644 +--- a/usr/share/rear/verify/RBME/default/150_check_nobody_uid_nfs.sh ++++ b/usr/share/rear/verify/RBME/default/150_check_nobody_uid_nfs.sh +@@ -1,5 +1,5 @@ + # check if NFS user is nobody - for rsync restore this is a NOGO +-nfs_uid=$(ls -l $BUILD_DIR/outputfs | tail -1 | awk '{print $3}') ++nfs_uid=$(ls -l "$BUILD_DIR/outputfs" | tail -1 | awk '{print $3}') + case "$nfs_uid" in + "nobody"|"-1"|"-2"|"4294967294") + Error "RBME rsync restore will result in a broken system (owner=$nfs_uid). +diff --git a/usr/share/rear/verify/RBME/default/540_choose_backup.sh b/usr/share/rear/verify/RBME/default/540_choose_backup.sh +index a67f1df3..ee81f271 100644 +--- a/usr/share/rear/verify/RBME/default/540_choose_backup.sh ++++ b/usr/share/rear/verify/RBME/default/540_choose_backup.sh +@@ -1,6 +1,6 @@ + +-scheme=$(url_scheme "$BACKUP_URL") +-case $scheme in ++scheme="$( url_scheme "$BACKUP_URL" )" ++case "$scheme" in + (local|nfs) + : + ;; +diff --git a/usr/share/rear/verify/USB/NETFS/default/540_choose_backup_archive.sh b/usr/share/rear/verify/USB/NETFS/default/540_choose_backup_archive.sh +index 4cbc782c..a90dfd6e 100644 +--- a/usr/share/rear/verify/USB/NETFS/default/540_choose_backup_archive.sh ++++ b/usr/share/rear/verify/USB/NETFS/default/540_choose_backup_archive.sh +@@ -3,7 +3,7 @@ + # This script is only run during a backup restore workflow (recover/restoreoly) + # so that RESTORE_ARCHIVES is set in this script. + +-scheme=$( url_scheme "$BACKUP_URL" ) ++scheme="$( url_scheme "$BACKUP_URL" )" + # Skip if not backup on USB: + test "usb" = "$scheme" || return 0 + diff --git a/SOURCES/rear-fix-libsystemd-ldd-warning.patch b/SOURCES/rear-fix-libsystemd-ldd-warning.patch new file mode 100644 index 0000000..27a5e46 --- /dev/null +++ b/SOURCES/rear-fix-libsystemd-ldd-warning.patch @@ -0,0 +1,110 @@ +commit eb574592a21c7ca986393c4563fe5484b9f01454 +Author: Johannes Meixner +Date: Tue Jun 18 13:47:27 2024 +0200 + + In 990_verify_rootfs.sh fix issue #3021 (#3250) + + In build/default/990_verify_rootfs.sh + for each 'not found' shared object + (i.e. a shared object that was 'not found' by 'ldd') + check whether or not the shared object + may exist nevertheless in the recovery system + and if yes, we may sufficiently safely assume + things are OK in the ReaR recovery system + so we do not report it as missing to the user + (for debugging we have all in the log), see + https://github.com/rear/rear/issues/3021#issuecomment-2165453757 + Additionally in 990_verify_rootfs.sh + more consistent level when messages are shown, + i.e. now only LogPrint and LogPrintError + to show nothing (except errors) when not in verbose mode + and all messages when in verbose mode + to make the messages as a whole + better understandable by the user. + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/build/default/990_verify_rootfs.sh b/usr/share/rear/build/default/990_verify_rootfs.sh +index 3d203cca..dce42701 100644 +--- a/usr/share/rear/build/default/990_verify_rootfs.sh ++++ b/usr/share/rear/build/default/990_verify_rootfs.sh +@@ -70,9 +70,13 @@ DebugPrint "Testing each binary with 'ldd' and look for 'not found' libraries wi + local backup_tool_LD_LIBRARY_PATH="" + local binary="" + local broken_binary_LD_LIBRARY_PATH="" +-local broken_binaries="no" + local fatal_missing_library="no" + local ldd_output="" ++local not_found_output="" ++local not_found_library="" ++local junk="" ++local actually_found_library="" ++local actually_missing_libraries="no" + # Third-party backup tools may use LD_LIBRARY_PATH to find their libraries + # so that for testing such third-party backup tools we must also use their special LD_LIBRARY_PATH here: + if test "$BACKUP" = "TSM" ; then +@@ -159,9 +163,8 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam + broken_binary_LD_LIBRARY_PATH=$backup_tool_LD_LIBRARY_PATH + Log "$binary requires additional libraries with backup tool specific LD_LIBRARY_PATH=$backup_tool_LD_LIBRARY_PATH" + fi +- # All tests had a 'not found' shared object dependency so the binary requires additional libraries +- # without LD_LIBRARY_PATH and with LD_LIBRARY_PATH and with backup tool specific LD_LIBRARY_PATH: +- broken_binaries="yes" ++ # At this point all tests had a 'not found' shared object dependency so the binary requires additional libraries ++ # without LD_LIBRARY_PATH and with LD_LIBRARY_PATH and with backup tool specific LD_LIBRARY_PATH. + # Only for programs (i.e. files in a .../bin/... or .../sbin/... directory) treat a missing library as fatal + # unless specified when a 'not found' reported library is not fatal (when the 'ldd' test was false alarm): + if grep -q '/[s]*bin/' <<<"$binary" ; then +@@ -169,17 +172,17 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam + if test "$NON_FATAL_BINARIES_WITH_MISSING_LIBRARY" ; then + # A program with missing library is treated as fatal when it does not match the pattern: + if grep -E -q "$NON_FATAL_BINARIES_WITH_MISSING_LIBRARY" <<<"$binary" ; then +- LogPrintError "$binary requires additional libraries (specified as non-fatal)" ++ LogPrint "$binary requires libraries were 'ldd' shows 'not found' (specified as non-fatal)" + else +- LogPrintError "$binary requires additional libraries (fatal error)" ++ LogPrint "$binary requires libraries were 'ldd' shows 'not found' (fatal error)" + fatal_missing_library="yes" + fi + else +- LogPrintError "$binary requires additional libraries (fatal error)" ++ LogPrint "$binary requires libraries were 'ldd' shows 'not found' (fatal by default)" + fatal_missing_library="yes" + fi + else +- LogPrintError "$binary requires additional libraries" ++ LogPrint "$binary requires libraries were 'ldd' shows 'not found'" + fi + # Run the same ldd call as above but now keep its whole stdout output. + # The ldd call that results the final 'not found' shared object is the last of the above ldd calls that was run. +@@ -191,10 +194,27 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam + fi + # Have the whole ldd output only in the log: + Log "$ldd_output" +- # Show only the missing libraries to the user to not flood his screen with tons of other ldd output lines: +- PrintError "$( grep 'not found' <<<"$ldd_output" )" ++ # For each 'not found' shared object (i.e. a shared object that was 'not found' by 'ldd') ++ # check whether or not the shared object may exist nevertheless in the ReaR recovery system ++ # and if yes, we may sufficiently safely assume things are OK in the ReaR recovery system ++ # so we do not report it as missing to the user (for debugging we have all in the log) ++ # cf. https://github.com/rear/rear/issues/3021#issuecomment-2165453757 ++ not_found_output="$( grep 'not found' <<<"$ldd_output" )" ++ # not_found_output is a string of multiple lines (separated by \n) that look e.g. like ++ # libsystemd-shared-255.4-1.fc40.so => not found ++ # /path/to/library => not found ++ while read not_found_library junk ; do ++ # We prefer a simple 'grep -q' pipe over dealing with find -name versus -path options: ++ if actually_found_library="$( find $ROOTFS_DIR -xdev | grep "$not_found_library" )" ; then ++ LogPrint "$binary requires $not_found_library which was not found by 'ldd' but exists as $actually_found_library" ++ else ++ actually_missing_libraries="yes" ++ # Show only the missing libraries to the user to not flood his screen with tons of other ldd output lines: ++ LogPrintError "$binary requires $not_found_library which could not be found in the ReaR recovery system" ++ fi ++ done <<<"$not_found_output" + done +-is_true $broken_binaries && LogPrintError "ReaR recovery system in '$ROOTFS_DIR' needs additional libraries, check $RUNTIME_LOGFILE for details" ++is_true $actually_missing_libraries && LogPrintError "ReaR recovery system in '$ROOTFS_DIR' needs additional libraries, check $RUNTIME_LOGFILE for details" + is_true $fatal_missing_library && keep_build_dir + + # Testing that each program in the PROGS array can be found as executable command within the recovery system diff --git a/SOURCES/rear-nbu-RHEL-17390-RHEL-17393.patch b/SOURCES/rear-nbu-RHEL-17390-RHEL-17393.patch new file mode 100644 index 0000000..f482a3b --- /dev/null +++ b/SOURCES/rear-nbu-RHEL-17390-RHEL-17393.patch @@ -0,0 +1,117 @@ +diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf +index 17a764cba..a944114b3 100644 +--- a/usr/share/rear/conf/default.conf ++++ b/usr/share/rear/conf/default.conf +@@ -1866,7 +1866,7 @@ OBDR_BLOCKSIZE=2048 + # BACKUP=NBU stuff (Symantec/Veritas NetBackup) + ## + # +-COPY_AS_IS_NBU=( /usr/openv/bin/vnetd /usr/openv/bin/vopied /usr/openv/lib /usr/openv/netbackup /usr/openv/var/auth/[mn]*.txt /usr/openv/var/vxss /usr/openv/var/webtruststore /usr/openv/resources/nbpxyhelper /opt/VRTSpbx /etc/vx/VxICS /etc/vx/vrtslog.conf /var/log/VRTSpbx ) ++COPY_AS_IS_NBU=( /usr/openv/bin/vnetd /usr/openv/bin/vopied /usr/openv/lib /usr/openv/netbackup /usr/openv/var /usr/openv/resources/nbpxyhelper /opt/VRTSpbx /etc/vx/VxICS /etc/vx/vrtslog.conf /var/log/VRTSpbx ) + COPY_AS_IS_EXCLUDE_NBU=( "/usr/openv/netbackup/logs/*" "/usr/openv/netbackup/bin/bpjava*" /usr/openv/netbackup/bin/xbp /usr/openv/netbackup/bin/private /usr/openv/lib/java "/usr/openv/lib/*-plugins" /usr/openv/lib/shared/vddk /usr/openv/netbackup/baremetal "/var/log/VRTSpbx/*" ) + # See https://github.com/rear/rear/issues/2105 why /usr/openv/netbackup/sec/at/lib/ is needed: + NBU_LD_LIBRARY_PATH="/usr/openv/lib:/usr/openv/netbackup/sec/at/lib/:/usr/openv/lib/boost" +diff --git a/usr/share/rear/finalize/NBU/default/990_copy_bplogrestorelog.sh b/usr/share/rear/finalize/NBU/default/990_copy_bplogrestorelog.sh +index 60d9a222c..e326db612 100644 +--- a/usr/share/rear/finalize/NBU/default/990_copy_bplogrestorelog.sh ++++ b/usr/share/rear/finalize/NBU/default/990_copy_bplogrestorelog.sh +@@ -1,5 +1,51 @@ + # 990_copy_bprestorelog.sh +-# copy the logfile to the recovered system, at least the part that has been written till now. ++# copy the logfiles to the recovered system, at least the part that has been written till now. + +-mkdir -p $TARGET_FS_ROOT/$ROOT_HOME_DIR +-cp -f $TMP_DIR/bplog.restore* $TARGET_FS_ROOT/$ROOT_HOME_DIR/ ++# $VAR_DIR/restore will be copied to $recovery_system_recover_log_dir in wrapup/default/990_copy_logfile.sh ++mkdir -p "$VAR_DIR/restore/netbackup" ++cp -pr /usr/openv/netbackup/logs/* "$VAR_DIR/restore/netbackup" ++ ++# take care of $VAR_DIR/restore/bplog.restore* files (that used to be in /root before) ++function symlink_bprestore_logs () ++{ ++ # adapted from wrapup/default/990_copy_logfile.sh ++ local final_logfile_name_full ++ local final_logfile_name ++ local log_file_symlink_target ++ local log_file_symlink ++ local recover_log_dir=$LOG_DIR/recover ++ local recovery_system_recover_log_dir=$TARGET_FS_ROOT/$recover_log_dir ++ # Create the directories with mode 0700 (rwx------) so that only root can access files and subdirectories therein ++ # because in particular logfiles could contain security relevant information. ++ ++ # To be backward compatible with where to the logfile was copied before ++ # have it as a symbolic link that points to where the logfile actually is: ++ # ( "roots" in recovery_system_roots_home_dir means root's but ' in a variable name is not so good ;-) ++ local recovery_system_roots_home_dir=$TARGET_FS_ROOT/$ROOT_HOME_DIR ++ test -d $recovery_system_roots_home_dir || mkdir $verbose -m 0700 $recovery_system_roots_home_dir ++ ++ # Remove existing and now outdated symlinks that would falsely point to the same target ++ # The symlink name bplog.restore-$( date -Iseconds ).log is for example bplog.restore-2019-12-17T09:40:36+01:00.log or rear-2006-08-14T02:34:56-06:00.log ++ # so a matching globbing pattern is bplog.restore-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]*.log ('*' for the UTC offset): ++ for log_file_symlink in $recovery_system_roots_home_dir/bplog.restore*-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]*.log ; do ++ # Skip if a file that matches the globbing pattern is not a symlink (it could be even a directory full of user's sacrocanct files): ++ test -L $log_file_symlink || continue ++ # Remove also outdated dangling symlinks where their target does not exist by using 'readlink -m': ++ test "$log_file_symlink_target" = "$( readlink -m $log_file_symlink )" || continue ++ rm $verbose $log_file_symlink ++ done ++ ++ # At the moment this function runs, $VAR_DIR/restore will have been already copied ++ # to $recovery_system_recover_log_dir in wrapup/default/990_copy_logfile.sh ++ # (exit tasks run in reverse order, so this task will run after the tasks defined in ++ # wrapup/default/990_copy_logfile.sh ) ++ for final_logfile_name_full in $recovery_system_recover_log_dir/restore/bplog.restore* ; do ++ final_logfile_name="$( basename "$final_logfile_name_full" )" ++ log_file_symlink_target="$recover_log_dir/restore/$final_logfile_name" ++ # Create symlink with current timestamp that points to where the logfile actually is: ++ log_file_symlink=$recovery_system_roots_home_dir/$( basename "$final_logfile_name" .log )-$( date -Iseconds ).log ++ ln $verbose -s $log_file_symlink_target $log_file_symlink || true ++ done ++} ++ ++AddExitTask "symlink_bprestore_logs" +diff --git a/usr/share/rear/restore/NBU/default/400_restore_with_nbu.sh b/usr/share/rear/restore/NBU/default/400_restore_with_nbu.sh +index 71f7359a1..4280cb021 100644 +--- a/usr/share/rear/restore/NBU/default/400_restore_with_nbu.sh ++++ b/usr/share/rear/restore/NBU/default/400_restore_with_nbu.sh +@@ -2,6 +2,23 @@ + # 400_restore_with_nbu.sh + # restore files with NBU + ++# Unique log file name: adapted from restore/NETFS/default/400_restore_backup.sh ++# and restore/TSM/default/400_restore_with_tsm.sh ++local backup_restore_log_dir="$VAR_DIR/restore" ++mkdir -p $backup_restore_log_dir ++local backup_restore_log_file="" ++local backup_restore_log_prefix="bplog.restore" ++local backup_restore_log_suffix="log" ++# E.g. when "rear -C 'general.conf /path/to/special.conf' recover" was called CONFIG_APPEND_FILES is "general.conf /path/to/special.conf" ++# so that in particular '/' characters must be replaced in the backup restore log file (by a colon) and then ++# the backup restore log file name will be like .../restore/bplog.restore.generalconf_:path:to:specialconf.1234.log ++# It does not work with $( tr -d -c '[:alnum:]/[:space:]' <<<"$CONFIG_APPEND_FILES" | tr -s '/[:space:]' ':_' ) ++# because the <<<"$CONFIG_APPEND_FILES" results a trailing newline that becomes a trailing '_' character so that ++# echo -n $CONFIG_APPEND_FILES (without double quotes) is used to avoid leading and trailing spaces and newlines: ++test "$CONFIG_APPEND_FILES" && backup_restore_log_prefix=$backup_restore_log_prefix.$( echo -n $CONFIG_APPEND_FILES | tr -d -c '[:alnum:]/[:space:]' | tr -s '/[:space:]' ':_' ) ++ ++backup_restore_log_file=$backup_restore_log_dir/$backup_restore_log_prefix.$MASTER_PID.$backup_restore_log_suffix ++ + LogPrint "NetBackup: restoring / into $TARGET_FS_ROOT" + + echo "change / to $TARGET_FS_ROOT" > $TMP_DIR/nbu_change_file +@@ -10,13 +27,13 @@ echo "change / to $TARGET_FS_ROOT" > $TMP_DIR/nbu_change_file + # $TMP_DIR/restore_fs_list was made by 300_create_nbu_restore_fs_list.sh + if [ ${#NBU_ENDTIME[@]} -gt 0 ] ; then + edate="${NBU_ENDTIME[@]}" +- bprestore_args="-B -H -L $TMP_DIR/bplog.restore -8 -R $TMP_DIR/nbu_change_file -t 0 -w 0 -e ${edate} -C ${NBU_CLIENT_SOURCE} -D ${NBU_CLIENT_NAME} -f $TMP_DIR/restore_fs_list" ++ bprestore_args="-B -H -L $backup_restore_log_file -8 -R $TMP_DIR/nbu_change_file -t 0 -w 0 -e ${edate} -C ${NBU_CLIENT_SOURCE} -D ${NBU_CLIENT_NAME} -f $TMP_DIR/restore_fs_list" + else +- bprestore_args="-B -H -L $TMP_DIR/bplog.restore -8 -R $TMP_DIR/nbu_change_file -t 0 -w 0 -C ${NBU_CLIENT_SOURCE} -D ${NBU_CLIENT_NAME} -f $TMP_DIR/restore_fs_list" ++ bprestore_args="-B -H -L $backup_restore_log_file -8 -R $TMP_DIR/nbu_change_file -t 0 -w 0 -C ${NBU_CLIENT_SOURCE} -D ${NBU_CLIENT_NAME} -f $TMP_DIR/restore_fs_list" + fi + + LogPrint "RUN: /usr/openv/netbackup/bin/bprestore $bprestore_args" +-LogPrint "Restore progress: see $TMP_DIR/bplog.restore" ++LogPrint "Restore progress: see $backup_restore_log_file" + LANG=C /usr/openv/netbackup/bin/bprestore $bprestore_args + rc=$? + if (( $rc > 1 )) ; then diff --git a/SOURCES/rear-remove-lvmdevices-bz2145014.patch b/SOURCES/rear-remove-lvmdevices-bz2145014.patch new file mode 100644 index 0000000..cad9bcd --- /dev/null +++ b/SOURCES/rear-remove-lvmdevices-bz2145014.patch @@ -0,0 +1,50 @@ +From 5a8c5086bf3fc28236436ff3ef27196509f0375d Mon Sep 17 00:00:00 2001 +From: Pavel Cahyna +Date: Thu, 24 Aug 2023 11:41:25 +0200 +Subject: [PATCH] Remove the lvmdevices file at the end of recovery + +The file /etc/lvm/devices/system.devices restricts LVM to disks with +given (hardware) IDs (serial numbers, WWNs). See lvmdevices(8). + +Unfortunately, when restoring to different disks than in the original +system, it will mean that LVM is broken in the recovered system (it +won't find any disks). Therefore it is safer to remove the file to +force the old behavior where LVM scans all disks. This used to be the +LVM default (use_devicesfile=0). +--- + .../GNU/Linux/230_remove_lvmdevices.sh | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) + create mode 100644 usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh + +diff --git a/usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh b/usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh +new file mode 100644 +index 0000000000..9392c9f52f +--- /dev/null ++++ b/usr/share/rear/finalize/GNU/Linux/230_remove_lvmdevices.sh +@@ -0,0 +1,25 @@ ++# Adapted from 260_rename_diskbyid.sh ++ ++# Remove /etc/lvm/devices/system.devices ++# The file restricts LVM to disks with given (hardware) IDs (serial ++# numbers, WWNs). See lvmdevices(8). ++# Unfortunately, when restoring to different disks than in the original ++# system, it will mean that LVM is broken in the recovered system (it ++# won't find any disks). Therefore it is safer to remove the file to ++# force the old behavior where LVM scans all disks. This used to be the ++# LVM default (use_devicesfile=0). ++ ++# There may be other files under /etc/lvm/devices, but they are not used ++# by default ++ ++local file=/etc/lvm/devices/system.devices ++local realfile ++ ++realfile="$TARGET_FS_ROOT/$file" ++# OK if file not found ++test -f "$realfile" || return 0 ++mv $v "$realfile" "$realfile.rearbak" ++LogPrint "Renamed LVM devices file $realfile to $realfile.rearbak ++to prevent LVM problems in the recovered system, verify that the file ++is correct after booting the recovered system and move it back, or ++regenerate it using vgimportdevices." + diff --git a/SOURCES/rear-resolve-libraries-for-symlinks-in-COPY_AS_IS-RHEL-15108.patch b/SOURCES/rear-resolve-libraries-for-symlinks-in-COPY_AS_IS-RHEL-15108.patch new file mode 100644 index 0000000..792a48f --- /dev/null +++ b/SOURCES/rear-resolve-libraries-for-symlinks-in-COPY_AS_IS-RHEL-15108.patch @@ -0,0 +1,30 @@ +commit 9f859c13f5ba285cd1d5983c9b595975c21888d3 +Merge: 01f503ed 4434da63 +Author: pcahyna +Date: Tue Nov 14 14:33:56 2023 +0100 + + Merge pull request #3073 from pcahyna/resolve-libraries-for-symlinks-in-COPY_AS_IS + + Resolve libs for executable links in COPY_AS_IS + +diff --git a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh +index 2169efaa..2e991145 100644 +--- a/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh ++++ b/usr/share/rear/build/GNU/Linux/100_copy_as_is.sh +@@ -135,10 +135,13 @@ local copy_as_is_file="" + # cf. https://github.com/rear/rear/pull/2378 + # It is crucial to append to /dev/$DISPENSABLE_OUTPUT_DEV (cf. 'Print' in lib/_input-output-functions.sh): + while read -r copy_as_is_file ; do +- # Skip non-regular files like directories, device files, and 'tar' error messages (e.g. in case of non-existent files, see above): ++ # Skip non-regular files like directories, device files, and 'tar' error messages (e.g. in case of non-existent files, see above) ++ # but do not skip symbolic links. Their targets will be copied later by build/default/490_fix_broken_links.sh. ++ # We thus need library dependencies for symlinked executables just like for normal executables ++ # and build/default/490_fix_broken_links.sh does not perform library dependency scan. ++ # See GitHub PR https://github.com/rear/rear/pull/3073 ++ # and issue https://github.com/rear/rear/issues/3064 for details. + test -f "$copy_as_is_file" || continue +- # Skip symbolic links (only care about symbolic link targets): +- test -L "$copy_as_is_file" && continue + # Remember actual regular files that are executable: + test -x "$copy_as_is_file" && copy_as_is_executables+=( "$copy_as_is_file" ) + done < <( sort -u $copy_as_is_filelist_file ) 2>>/dev/$DISPENSABLE_OUTPUT_DEV diff --git a/SOURCES/rear-restore-hybrid-bootloader-RHEL-16864.patch b/SOURCES/rear-restore-hybrid-bootloader-RHEL-16864.patch new file mode 100644 index 0000000..7257bbc --- /dev/null +++ b/SOURCES/rear-restore-hybrid-bootloader-RHEL-16864.patch @@ -0,0 +1,589 @@ +commit 096bfde5e234f5a803bae74f24e3821798022c7c +Merge: 625775fc 1df15b03 +Author: pcahyna +Date: Tue Feb 6 18:37:52 2024 +0100 + + Merge pull request #3136 from pcahyna/no-recovery-bootdisk + + Include GRUB tools unconditionally and don't create $VAR_DIR/recovery/bootdisk in prep + +diff --git a/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh b/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh +index fcf0a5ff..7d494281 100644 +--- a/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh ++++ b/usr/share/rear/prep/GNU/Linux/300_include_grub_tools.sh +@@ -1,8 +1,6 @@ + # + # GRUB2 has much more commands than the legacy grub command, including modules + +-test -d $VAR_DIR/recovery || mkdir -p $VAR_DIR/recovery +- + # cf. https://github.com/rear/rear/issues/2137 + # s390 zlinux does not use grub + # ********************************************************************************* +@@ -11,19 +9,8 @@ test -d $VAR_DIR/recovery || mkdir -p $VAR_DIR/recovery + # ********************************************************************************* + [ "$ARCH" == "Linux-s390" ] && return 0 + +-# Because usr/sbin/rear sets 'shopt -s nullglob' the 'echo -n' command +-# outputs nothing if nothing matches the bash globbing pattern '/boot/grub*' +-local grubdir="$( echo -n /boot/grub* )" +-# Use '/boot/grub' as fallback if nothing matches '/boot/grub*' +-test -d "$grubdir" || grubdir='/boot/grub' +- +-# Check if we're using grub or grub2 before doing something. +-if has_binary grub-probe ; then +- grub-probe -t device $grubdir >$VAR_DIR/recovery/bootdisk 2>/dev/null || return 0 +-elif has_binary grub2-probe ; then +- grub2-probe -t device $grubdir >$VAR_DIR/recovery/bootdisk 2>/dev/null || return 0 +-fi +- ++# It is safe to assume that we are using GRUB and try to add these files to the rescue image ++# even if the assumption is wrong. + # Missing programs in the PROGS array are ignored: + PROGS+=( grub-bios-setup grub2-bios-setup + grub-install grub2-install +diff --git a/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh b/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh +index b4ab3786..4451f53d 100644 +--- a/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh ++++ b/usr/share/rear/prep/Linux-s390/305_include_s390_tools.sh +@@ -1,8 +1,6 @@ + # + # s390 zIPL boot loader and grubby for configuring boot loader` + +-test -d $VAR_DIR/recovery || mkdir -p $VAR_DIR/recovery +- + # See the code in prep/GNU/Linux/300_include_grub_tools.sh + # that sets grubdir via + # local grubdir="$( echo -n /boot/grub* )" +@@ -21,7 +19,7 @@ local bootdir="/boot/" + # findmnt returns --> /dev/dasda3[/@/.snapshots/1/snapshot] + # use 300_include_grub_tools.sh instead of this file (grub2-probe) + if has_binary findmnt ; then +- findmnt -no SOURCE --target $bootdir >$VAR_DIR/recovery/bootdisk || return 0 ++ findmnt -no SOURCE --target $bootdir > /dev/null || return 0 + fi + + # Missing programs in the PROGS array are ignored: +diff --git a/usr/share/rear/prep/default/320_include_uefi_env.sh b/usr/share/rear/prep/default/320_include_uefi_env.sh +index ea86af4c..93e59eae 100644 +--- a/usr/share/rear/prep/default/320_include_uefi_env.sh ++++ b/usr/share/rear/prep/default/320_include_uefi_env.sh +@@ -87,7 +87,3 @@ fi + DebugPrint "Found EFI system partition ${esp_proc_mounts_line[0]} on ${esp_proc_mounts_line[1]} type ${esp_proc_mounts_line[2]}" + USING_UEFI_BOOTLOADER=1 + LogPrint "Using UEFI Boot Loader for Linux (USING_UEFI_BOOTLOADER=1)" +- +-# Remember the ESP device node in VAR_DIR/recovery/bootdisk: +-echo "${esp_proc_mounts_line[0]}" >$VAR_DIR/recovery/bootdisk +- + +commit ca99d855579cfcab37f985e2547a3187e0f0aeeb +Merge: 8c59415c 40b883c0 +Author: pcahyna +Date: Fri Feb 16 11:40:04 2024 +0100 + + Merge pull request #3145 from rear/restore-hybrid-bootloader + + Support saving and restoring hybrid BIOS/UEFI bootloader setup and clean up bootloader detection + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/finalize/Linux-i386/630_install_grub.sh b/usr/share/rear/finalize/Linux-i386/630_install_grub.sh +index f3d9a820..a0e87e1d 100644 +--- a/usr/share/rear/finalize/Linux-i386/630_install_grub.sh ++++ b/usr/share/rear/finalize/Linux-i386/630_install_grub.sh +@@ -1,22 +1,18 @@ + # This script is an improvement over the default grub-install '(hd0)' + # +-# However the following issues still exist: ++# However the following issue still exists: + # + # * We don't know what the first disk will be, so we cannot be sure the MBR +-# is written to the correct disk(s). That's why we make all disks bootable. +-# +-# * There is no guarantee that GRUB was the boot loader used originally. +-# One possible attempt would be to save and restore the MBR for each disk, +-# but this does not guarantee a correct boot order, +-# or even a working boot loader config +-# (eg. GRUB stage2 might not be at the exact same location). ++# is written to the correct disk(s). That's why we make all suitable disks bootable. + + # Skip if another boot loader is already installed + # (then $NOBOOTLOADER is not a true value cf. finalize/default/010_prepare_checks.sh): + is_true $NOBOOTLOADER || return 0 + +-# For UEFI systems with grub legacy with should use efibootmgr instead: +-is_true $USING_UEFI_BOOTLOADER && return ++# For UEFI systems with grub legacy with should use efibootmgr instead, ++# but if BOOTLOADER is explicitly set to GRUB, we are on a hybrid (BIOS/UEFI) ++# boot system and we need to install GRUB to MBR as well. ++# Therefore, we don't test $USING_UEFI_BOOTLOADER. + + # If the BOOTLOADER variable (read by finalize/default/010_prepare_checks.sh) + # is not "GRUB" (which means GRUB Legacy) skip this script (which is only for GRUB Legacy) +@@ -25,31 +21,27 @@ is_true $USING_UEFI_BOOTLOADER && return + test "GRUB" = "$BOOTLOADER" || return 0 + + # If the BOOTLOADER variable is "GRUB" (which means GRUB Legacy) +-# do not unconditionally trust that because https://github.com/rear/rear/pull/589 +-# reads (excerpt): +-# Problems found: +-# The ..._install_grub.sh checked for GRUB2 which is not part +-# of the first 2048 bytes of a disk - only GRUB was present - +-# thus the check for grub-probe/grub2-probe +-# and https://github.com/rear/rear/commit/079de45b3ad8edcf0e3df54ded53fe955abded3b +-# reads (excerpt): +-# replace grub-install by grub-probe +-# as grub-install also exist in legacy grub +-# so that it seems there are cases where actually GRUB 2 is used +-# but wrongly detected as "GRUB" so that another test is needed +-# to detected if actually GRUB 2 is used and that test is to +-# check if grub-probe or grub2-probe is installed because +-# grub-probe or grub2-probe is only installed in case of GRUB 2 +-# and when GRUB 2 is installed we assume GRUB 2 is used as boot loader +-# so that then we skip this script (which is only for GRUB Legacy) +-# because finalize/Linux-i386/660_install_grub2.sh is for installing GRUB 2: +-if type -p grub-probe >&2 || type -p grub2-probe >&2 ; then +- LogPrint "Skip installing GRUB Legacy boot loader because GRUB 2 is installed (grub-probe or grub2-probe exist)." ++# we could in principle trust that and continue because ++# layout/save/default/445_guess_bootloader.sh (where the value has been set) ++# is now able to distinguish between GRUB Legacy and GRUB 2. ++# But, as this code used to support the value "GRUB" for GRUB 2, ++# the user can have BOOTLOADER=GRUB set explicitly in the configuration file ++# and then it overrides the autodetection in layout/save/default/445_guess_bootloader.sh . ++# The user expects this setting to work with GRUB 2, thus for backward compatibility ++# we need to take into accout the possibility that GRUB actually means GRUB 2. ++if is_grub2_installed ; then ++ LogPrint "Skip installing GRUB Legacy boot loader because GRUB 2 is installed." ++ # We have the ErrorIfDeprecated function, but it aborts ReaR by default, ++ # which is not a good thing to do during recovery. ++ # Therefore it better to log a warning and continue. ++ LogPrintError "WARNING: setting BOOTLOADER=GRUB for GRUB 2 is deprecated, set BOOTLOADER=GRUB2 if setting BOOTLOADER explicitly" + return + fi + + # The actual work: + LogPrint "Installing GRUB Legacy boot loader:" ++# See above for the reasoning why not to use ErrorIfDeprecated ++LogPrintError "WARNING: support for GRUB Legacy is deprecated" + + # Installing GRUB Legacy boot loader requires an executable "grub": + type -p grub >&2 || Error "Cannot install GRUB Legacy boot loader because there is no 'grub' program." +@@ -79,8 +71,10 @@ if [[ -r "$LAYOUT_FILE" && -r "$LAYOUT_DEPS" ]] ; then + + for disk in $disks ; do + # Installing grub on an LVM PV will wipe the metadata so we skip those +- # function is_disk_a_pv returns with 1 if disk is a PV +- is_disk_a_pv "$disk" || continue ++ # function is_disk_a_pv returns true if disk is a PV ++ is_disk_a_pv "$disk" && continue ++ # Is the disk suitable for GRUB installation at all? ++ is_disk_grub_candidate "$disk" || continue + # Use first boot partition by default + part=$( echo $bootparts | cut -d' ' -f1 ) + +diff --git a/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh b/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh +index d1c36bd3..5bf9144c 100644 +--- a/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh ++++ b/usr/share/rear/finalize/Linux-i386/660_install_grub2.sh +@@ -36,7 +36,9 @@ + # This script does not check BOOTLOADER because it is also used as fallback + # to install the nowadays most often used bootloader GRUB2 + # unless the BOOTLOADER variable tells to install another bootloader +-# (other bootloader install scripts check the BOOTLOADER variable). ++# (other bootloader install scripts check the BOOTLOADER variable) ++# and unless we are using UEFI (BOOTLOADER then indicates the BIOS bootloader ++# in a a hybrid boot setup). + # + # This script does not error out because at this late state of "rear recover" + # (i.e. after the backup was restored) I consider it too hard +@@ -45,6 +47,37 @@ + # so that after "rear recover" finished he can manually install the bootloader + # as appropriate for his particular system. + ++local grub_name ++local grub2_install_failed grub2_install_device ++local source_disk target_disk junk ++local grub2_installed_disks ++local part bootparts ++local disk disks bootdisk ++ ++function bios_grub_install () ++{ ++ local grub2_install_device="$1" ++ ++ if is_true $USING_UEFI_BOOTLOADER ; then ++ # If running under UEFI, we need to specify the target explicitly, otherwise grub-install thinks ++ # that we are installing the EFI bootloader. ++ if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install --target=i386-pc $grub2_install_device" ; then ++ LogPrintError "Failed to install GRUB2 for BIOS boot (target i386-pc) on $bootdisk" ++ # purely informational test that may help to explain the reason for the error ++ if ! test -d "$TARGET_FS_ROOT/boot/$grub_name/i386-pc" ; then ++ LogPrintError "GRUB2 module dir for BIOS boot (boot/$grub_name/i386-pc in $TARGET_FS_ROOT) does not exist, is GRUB2 for BIOS (target i386-pc) installed?" ++ fi ++ return 1 ++ fi ++ else ++ if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_install_device" ; then ++ LogPrintError "Failed to install GRUB2 on $grub2_install_device" ++ return 1 ++ fi ++ fi ++ return 0 ++} ++ + # Skip if another bootloader was already installed: + # In this case NOBOOTLOADER is not true, + # cf. finalize/default/050_prepare_checks.sh +@@ -52,12 +85,16 @@ is_true $NOBOOTLOADER || return 0 + + # For UEFI systems with grub2 we should use efibootmgr instead, + # cf. finalize/Linux-i386/670_run_efibootmgr.sh +-is_true $USING_UEFI_BOOTLOADER && return ++# but if BOOTLOADER is explicitly set to GRUB2, we are on a hybrid (BIOS/UEFI) ++# boot system and we need to install GRUB to MBR as well ++if is_true $USING_UEFI_BOOTLOADER && [ "GRUB2" != "$BOOTLOADER" ] ; then ++ return 0 ++fi + + # Only for GRUB2 - GRUB Legacy will be handled by its own script. + # GRUB2 is detected by testing for grub-probe or grub2-probe which does not exist in GRUB Legacy. + # If neither grub-probe nor grub2-probe is there assume GRUB2 is not there: +-type -p grub-probe || type -p grub2-probe || return 0 ++is_grub2_installed || return 0 + + LogPrint "Installing GRUB2 boot loader..." + +@@ -101,7 +138,7 @@ if test "$GRUB2_INSTALL_DEVICES" ; then + else + LogPrint "Installing GRUB2 on $grub2_install_device (specified in GRUB2_INSTALL_DEVICES)" + fi +- if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_install_device" ; then ++ if ! bios_grub_install "$grub2_install_device" ; then + LogPrintError "Failed to install GRUB2 on $grub2_install_device" + grub2_install_failed="yes" + fi +@@ -145,8 +182,8 @@ fi + grub2_installed_disks=() + for disk in $disks ; do + # Installing GRUB2 on an LVM PV will wipe the metadata so we skip those: +- # function is_disk_a_pv returns with 1 if disk is a PV +- is_disk_a_pv "$disk" || continue ++ # function is_disk_a_pv returns true if disk is a PV ++ is_disk_a_pv "$disk" && continue + + # Use first boot partition by default: + part=$( echo $bootparts | cut -d' ' -f1 ) +@@ -165,6 +202,8 @@ for disk in $disks ; do + + # Install GRUB2 on the boot disk if one was found: + if test "$bootdisk" ; then ++ # Is the disk suitable for GRUB installation at all? ++ is_disk_grub_candidate "$bootdisk" || continue + # Continue with the next possible boot disk when GRUB2 was already installed on the current one. + # When there are more disks like /dev/sda and /dev/sdb it can happen that + # for /dev/sda bootdisk=/dev/sda and GRUB2 gets installed on /dev/sda and +@@ -172,7 +211,7 @@ for disk in $disks ; do + # so we avoid that GRUB2 gets needlessly installed two times on the same device: + IsInArray "$bootdisk" "${grub2_installed_disks[@]}" && continue + LogPrint "Found possible boot disk $bootdisk - installing GRUB2 there" +- if chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $bootdisk" ; then ++ if bios_grub_install "$bootdisk" ; then + grub2_installed_disks+=( "$bootdisk" ) + # In contrast to the above behaviour when GRUB2_INSTALL_DEVICES is specified + # consider it here as a successful bootloader installation when GRUB2 +@@ -181,11 +220,14 @@ for disk in $disks ; do + # Continue with the next possible boot disk: + continue + fi +- LogPrintError "Failed to install GRUB2 on possible boot disk $bootdisk" + fi + done + + is_true $NOBOOTLOADER || return 0 +-LogPrintError "Failed to install GRUB2 - you may have to manually install it" ++if is_true $USING_UEFI_BOOTLOADER ; then ++ LogPrintError "Failed to install GRUB2 for BIOS boot - you may have to manually install it to preserve the hybrid BIOS/UEFI boot support, otherwise only UEFI boot will work" ++else ++ LogPrintError "Failed to install GRUB2 - you may have to manually install it" ++fi + return 1 + +diff --git a/usr/share/rear/finalize/default/050_prepare_checks.sh b/usr/share/rear/finalize/default/050_prepare_checks.sh +index 1679c9a4..57b44bca 100644 +--- a/usr/share/rear/finalize/default/050_prepare_checks.sh ++++ b/usr/share/rear/finalize/default/050_prepare_checks.sh +@@ -10,10 +10,18 @@ + NOBOOTLOADER=1 + + # Try to read the BOOTLOADER value if /var/lib/rear/recovery/bootloader is not empty. +-# Currently (June 2016) the used BOOTLOADER values (grep for '$BOOTLOADER') are: ++# Currently (February 2024) the used BOOTLOADER values (grep for '$BOOTLOADER') are: + # GRUB for GRUB Legacy + # GRUB2 for GRUB 2 + # ELILO for elilo ++# LILO for lilo ++# GRUB2-EFI for GRUB 2, EFI version ++# EFI for any EFI bootloader, dummy value ++# ARM for ARM devices, dummy value ++# ARM-ALLWINNER for Allwinner devices ++# ZIPL for zIPL, on IBM Z (s390x) ++# PPC for any bootloader in the PReP boot partition (can be LILO, YABOOT, GRUB2) ++ + local bootloader_file="$VAR_DIR/recovery/bootloader" + # The output is stored in an artificial bash array so that $BOOTLOADER is the first word: + test -s $bootloader_file && BOOTLOADER=( $( grep -v '^[[:space:]]*#' $bootloader_file ) ) +diff --git a/usr/share/rear/layout/save/default/445_guess_bootloader.sh b/usr/share/rear/layout/save/default/445_guess_bootloader.sh +index 06de7648..374a706f 100644 +--- a/usr/share/rear/layout/save/default/445_guess_bootloader.sh ++++ b/usr/share/rear/layout/save/default/445_guess_bootloader.sh +@@ -1,10 +1,26 @@ + + # Determine or guess the used bootloader if not specified by the user + # and save this information into /var/lib/rear/recovery/bootloader +-bootloader_file="$VAR_DIR/recovery/bootloader" ++local bootloader_file="$VAR_DIR/recovery/bootloader" ++ ++local sysconfig_bootloader ++local block_device ++local blockd ++local disk_device ++local bootloader_area_strings_file ++local block_size ++local known_bootloader + + # When BOOTLOADER is specified use that: + if test "$BOOTLOADER" ; then ++ # case-insensitive match, as later we conver all to uppercase ++ if [[ "$BOOTLOADER" == [Gg][Rr][Uu][Bb] ]] ; then ++ if is_grub2_installed ; then ++ LogPrintError "BOOTLOADER=GRUB used to mean GRUB 2 if GRUB 2 is installed and GRUB Legacy if not" ++ Error "BOOTLOADER set to '$BOOTLOADER', set it to 'GRUB2' explicitly to avoid the ambiguity" ++ fi ++ # we should add an ErrorIfDeprecated call here or later for GRUB Legacy deprecation ++ fi + LogPrint "Using specified bootloader '$BOOTLOADER' for 'rear recover'" + echo "$BOOTLOADER" | tr '[a-z]' '[A-Z]' >$bootloader_file + return +@@ -57,39 +73,31 @@ for block_device in /sys/block/* ; do + # Continue guessing the used bootloader by inspecting the first bytes on the next disk: + continue + fi +- # 'Hah!IdontNeedEFI' is the ASCII representation of the official GUID number +- # for a GPT BIOS boot partition which is 21686148-6449-6E6F-744E-656564454649 +- # see https://en.wikipedia.org/wiki/BIOS_boot_partition (issue #1752). +- # Use single quotes for 'Hah!IdontNeedEFI' to be on the safe side +- # because with double quotes the ! would cause history expansion if that is enabled +- # (non-interactive shells do not perform history expansion by default but better safe than sorry): +- if grep -q 'Hah!IdontNeedEFI' $bootloader_area_strings_file ; then +- # Because 'Hah!IdontNeedEFI' contains the known bootloader 'EFI' +- # the default code below would falsely guess that 'EFI' is used +- # but actually another non-EFI bootloader is used here +- # cf. https://github.com/rear/rear/issues/1752#issue-303856221 +- # so that in the 'Hah!IdontNeedEFI' case only non-EFI bootloaders are tested. +- # IBM Z (s390) uses zipl boot loader for RHEL and Ubuntu +- # cf. https://github.com/rear/rear/issues/2137 +- for known_bootloader in GRUB2 GRUB ELILO LILO ZIPL ; do +- if grep -q -i "$known_bootloader" $bootloader_area_strings_file ; then +- LogPrint "Using guessed bootloader '$known_bootloader' for 'rear recover' (found in first bytes on $disk_device with GPT BIOS boot partition)" +- echo "$known_bootloader" >$bootloader_file +- return +- fi +- done +- # When in the 'Hah!IdontNeedEFI' case no known non-EFI bootloader is found +- # continue guessing the used bootloader by inspecting the first bytes on the next disk +- # because otherwise the default code below would falsely guess that 'EFI' is used +- # cf. https://github.com/rear/rear/pull/1754#issuecomment-383531597 +- continue +- fi + # Check the default cases of known bootloaders. + # IBM Z (s390) uses zipl boot loader for RHEL and Ubuntu + # cf. https://github.com/rear/rear/issues/2137 +- for known_bootloader in GRUB2-EFI EFI GRUB2 GRUB ELILO LILO ZIPL ; do ++ for known_bootloader in GRUB2 GRUB LILO ZIPL ; do + if grep -q -i "$known_bootloader" $bootloader_area_strings_file ; then +- LogPrint "Using guessed bootloader '$known_bootloader' for 'rear recover' (found in first bytes on $disk_device)" ++ # If we find "GRUB" (which means GRUB Legacy) ++ # do not unconditionally trust that because https://github.com/rear/rear/pull/589 ++ # reads (excerpt): ++ # Problems found: ++ # The ..._install_grub.sh checked for GRUB2 which is not part ++ # of the first 2048 bytes of a disk - only GRUB was present - ++ # thus the check for grub-probe/grub2-probe ++ # and https://github.com/rear/rear/commit/079de45b3ad8edcf0e3df54ded53fe955abded3b ++ # reads (excerpt): ++ # replace grub-install by grub-probe ++ # as grub-install also exist in legacy grub ++ # so that if actually GRUB 2 is used, the string in the bootloader area ++ # is "GRUB" so that another test is needed to detect if actually GRUB 2 is used. ++ # When GRUB 2 is installed we assume GRUB 2 is used as boot loader. ++ if [ "$known_bootloader" = "GRUB" ] && is_grub2_installed ; then ++ known_bootloader=GRUB2 ++ LogPrint "GRUB found in first bytes on $disk_device and GRUB 2 is installed, using GRUB2 as a guessed bootloader for 'rear recover'" ++ else ++ LogPrint "Using guessed bootloader '$known_bootloader' for 'rear recover' (found in first bytes on $disk_device)" ++ fi + echo "$known_bootloader" >$bootloader_file + return + fi +@@ -103,6 +111,26 @@ for block_device in /sys/block/* ; do + Log "End of strings in the first bytes on $disk_device" + done + ++# No bootloader detected, but we are using UEFI - there is probably an EFI bootloader ++if is_true $USING_UEFI_BOOTLOADER ; then ++ if is_grub2_installed ; then ++ echo "GRUB2-EFI" >$bootloader_file ++ elif test -f /sbin/elilo ; then ++ echo "ELILO" >$bootloader_file ++ else ++ # There is an EFI bootloader, we don't know which one exactly. ++ # The value "EFI" is a bit redundant with USING_UEFI_BOOTLOADER=1, ++ # which already indicates that there is an EFI bootloader. We use it as a placeholder ++ # to not leave $bootloader_file empty. ++ # Note that it is legal to have USING_UEFI_BOOTLOADER=1 and e.g. known_bootloader=GRUB2 ++ # (i.e. a non=EFI bootloader). This will happen in BIOS/UEFI hybrid boot scenarios. ++ # known_bootloader=GRUB2 indicates that there is a BIOS bootloader and USING_UEFI_BOOTLOADER=1 ++ # indicates that there is also an EFI bootloader. Only the EFI one is being used at this ++ # time, but both will need to be restored. ++ echo "EFI" >$bootloader_file ++ fi ++ return 0 ++fi + + # Error out when no bootloader was specified or could be autodetected: + Error "Cannot autodetect what is used as bootloader, see default.conf about 'BOOTLOADER'" +diff --git a/usr/share/rear/lib/bootloader-functions.sh b/usr/share/rear/lib/bootloader-functions.sh +index a7363c4c..3dade874 100644 +--- a/usr/share/rear/lib/bootloader-functions.sh ++++ b/usr/share/rear/lib/bootloader-functions.sh +@@ -529,6 +529,53 @@ function get_root_disk_UUID { + ( set -o pipefail ; mount | grep ' on / ' | awk '{print $1}' | xargs blkid -s UUID -o value || Error "Failed to get root disk UUID" ) + } + ++# Detect whether actually GRUB 2 is installed and that test is to ++# check if grub-probe or grub2-probe is installed because ++# grub-probe or grub2-probe is only installed in case of GRUB 2. ++# Needed because one can't tell the GRUB version by looking at the MBR ++# (both GRUB 2 and GRUB Legacy have the string "GRUB" in their MBR). ++function is_grub2_installed () { ++ if type -p grub-probe >&2 || type -p grub2-probe >&2 ; then ++ Log "GRUB 2 is installed (grub-probe or grub2-probe exist)." ++ return 0 ++ else ++ return 1 ++ fi ++} ++ ++# Determine whether a disk is worth detecting or installing GRUB on ++function is_disk_grub_candidate () { ++ local disk="$1" ++ local disk_partitions part ++ local label flags ++ ++ # ToDo : validate $disk (does it even exist? Isn't it write-protected?) ++ ++ # Installing grub on an LVM PV will wipe the metadata so we skip those ++ is_disk_a_pv "$disk" && return 1 ++ ++ label="$( get_disklabel_type "$disk" )" || return 1 ++ # We don't care about the SUSE-specific 'gpt_sync_mbr' partition scheme ++ # anymore: https://github.com/rear/rear/pull/3145#discussion_r1481388431 ++ if [ "$label" == gpt ] ; then ++ # GPT needs a special BIOS boot partition to store GRUB (BIOS version). ++ # Let's try to find it. It can be recognized as having the bios_grub flag. ++ disk_partitions=( $( get_child_components "$disk" "part" ) ) ++ for part in "${disk_partitions[@]}" ; do ++ flags=( $( get_partition_flags "$part" ) ) ++ IsInArray bios_grub "${flags[@]}" && return 0 # found! ++ done ++ # If a given GPT-partitioned disk does not contain a BIOS boot partition, ++ # GRUB for BIOS booting can not be installed into its MBR (grub-install errors out). ++ return 1 ++ else ++ # Other disklabel types don't need anything special to install GRUB. ++ # The test for the PReP boot partition (finalize/Linux-ppc64le/660_install_grub2.sh) ++ # is a bit similar, but operates on the partition itself, not on the uderlying disk. ++ return 0 ++ fi ++} ++ + # Output GRUB2 configuration on stdout: + # $1 is the kernel file with appropriate path for GRUB2 to load the kernel from within GRUB2's root filesystem + # $2 is the initrd file with appropriate path for GRUB2 to load the initrd from within GRUB2's root filesystem +diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh +index 69f38b47..ee651b2a 100644 +--- a/usr/share/rear/lib/layout-functions.sh ++++ b/usr/share/rear/lib/layout-functions.sh +@@ -532,6 +532,33 @@ get_component_type() { + grep -E "^[^ ]+ $1 " $LAYOUT_TODO | cut -d " " -f 3 + } + ++# Get the disklabel (partition table) type of the disk $1 from the layout file ++# (NOT from the actual disk, so layout file must exist before calling this, ++# and it is useful during recovery even before the disk layout has been recreated) ++function get_disklabel_type () { ++ # from create_disk() in layout/prepare/GNU/Linux/100_include_partition_code.sh ++ local component disk size label junk ++ ++ disk='' ++ ++ read component disk size label junk < <(grep "^disk $1 " "$LAYOUT_FILE") ++ test $disk || return 1 ++ ++ echo $label ++} ++ ++# Get partition flags from layout (space-separated) of partition given as $1 ++function get_partition_flags () { ++ local part disk size pstart name flags partition junk ++ ++ while read part disk size pstart name flags partition junk; do ++ if [ "$partition" == "$1" ] ; then ++ echo "$flags" | tr ',' ' ' ++ return 0 ++ fi ++ done < <(grep "^part " $LAYOUT_FILE) ++} ++ + # Function returns 0 when v1 is greater or equal than v2 + version_newer() { + local v1list=( ${1//[-.]/ } ) +@@ -806,17 +833,17 @@ blkid_label_of_device() { + echo "$label" + } + +-# Returns 1 if the device is an LVM physical volume +-# Returns 0 otherwise or if the device doesn't exists ++# Returns true if the device is an LVM physical volume ++# Returns false otherwise or if the device doesn't exist + is_disk_a_pv() { + disk=$1 + + # Using awk, select the 'lvmdev' line for which $disk is the device (column 3), + # cf. https://github.com/rear/rear/pull/1897 + # If exit == 1, then there is such line (so $disk is a PV), +- # otherwise exit with default value '0', which falls through to 'return 0' below. +- awk "\$1 == \"lvmdev\" && \$3 == \"${disk}\" { exit 1 }" "$LAYOUT_FILE" >/dev/null || return 1 +- return 0 ++ # otherwise exit with default value '0', which falls through to 'return 1' below. ++ awk "\$1 == \"lvmdev\" && \$3 == \"${disk}\" { exit 1 }" "$LAYOUT_FILE" >/dev/null || return 0 ++ return 1 + } + + function is_multipath_used { +diff --git a/usr/share/rear/lib/savelayout-workflow.sh b/usr/share/rear/lib/savelayout-workflow.sh +index 69cda58e..27bb0a1a 100644 +--- a/usr/share/rear/lib/savelayout-workflow.sh ++++ b/usr/share/rear/lib/savelayout-workflow.sh +@@ -10,6 +10,10 @@ if [[ "$VERBOSE" ]]; then + fi + WORKFLOWS+=( savelayout ) + WORKFLOW_savelayout () { ++ # layout code needs to know whether we are using UEFI (USING_UEFI_BOOTLOADER) ++ # as it also detects the bootloader in use ( layout/save/default/445_guess_bootloader.sh ) ++ Source $SHARE_DIR/prep/default/320_include_uefi_env.sh ++ + #DISKLAYOUT_FILE=$VAR_DIR/layout/disklayout.conf # defined in default.conf now (issue #678) + SourceStage "layout/save" + } diff --git a/SOURCES/rear-save-lvm-poolmetadatasize-RHEL-6984.patch b/SOURCES/rear-save-lvm-poolmetadatasize-RHEL-6984.patch new file mode 100644 index 0000000..91c6dfc --- /dev/null +++ b/SOURCES/rear-save-lvm-poolmetadatasize-RHEL-6984.patch @@ -0,0 +1,112 @@ +commit f6af518baf3b5a4dc06bf8cfea262e627eee3e07 +Merge: ed4c78d5 75a86fc3 +Author: pcahyna +Date: Wed Nov 1 12:53:33 2023 +0100 + + Merge pull request #3061 from pcahyna/save-lvm-poolmetadatasize + + Save LVM pool metadata volume size in disk layout + +diff --git a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh +index 7400c586..b12cff1f 100644 +--- a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh ++++ b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh +@@ -18,7 +18,7 @@ local already_processed_lvs=() + local lv_layout_supported lvs_fields + local origin lv vg + local layout modules +-local thinpool chunksize stripes stripesize segmentsize ++local thinpool chunksize stripes stripesize segmentsize poolmetadatasize + local kval infokval + local lvs_exit_code + +@@ -130,7 +130,7 @@ local lvs_exit_code + echo "# Skipping PV $pdev that is not part of a valid VG (VG '$vgrp' empty or more than one word):" + contains_visible_char "$vgrp" || vgrp='' + echo "# lvmdev /dev/$vgrp $pdev $uuid $size" +- # Continue with the next line in the output of "lvm pvdisplay -c" ++ # Continue with the next line in the output of "lvm pvdisplay -C" + continue + fi + # With the above example the output is: +@@ -138,10 +138,10 @@ local lvs_exit_code + echo "lvmdev /dev/$vgrp $pdev $uuid $size" + + done +- # Check the exit code of "lvm pvdisplay -c" +- # in the "lvm pvdisplay -c | while read line ; do ... done" pipe: ++ # Check the exit code of "lvm pvdisplay -C" ++ # in the "lvm pvdisplay -C ... | while read line ; do ... done" pipe: + pvdisplay_exit_code=${PIPESTATUS[0]} +- test $pvdisplay_exit_code -eq 0 || Error "LVM command 'lvm pvdisplay -c' failed with exit code $pvdisplay_exit_code" ++ test $pvdisplay_exit_code -eq 0 || Error "LVM command 'lvm pvdisplay -C ... -o pv_name,vg_name,pv_size,pv_uuid' failed with exit code $pvdisplay_exit_code" + + # Get the volume group configuration: + # Format: lvmgrp [] [] +@@ -200,18 +200,18 @@ local lvs_exit_code + + # Specify the fields for the lvs command depending on whether or not the 'lv_layout' field is supported: + if is_true $lv_layout_supported ; then +- lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size" ++ lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size" + else + # Use the 'modules' field as fallback replacement when the 'lv_layout' field is not supported: +- lvs_fields="origin,lv_name,vg_name,lv_size,modules,pool_lv,chunk_size,stripes,stripe_size,seg_size" ++ lvs_fields="origin,lv_name,vg_name,lv_size,modules,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size" + fi + + # Example output of "lvs --separator=':' --noheadings --units b --nosuffix -o $lvs_fields" +- # with lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size" ++ # with lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size" + # i.e. when the 'lv_layout' field is supported: +- # :home:system:6148849664:linear::0:1:0:6148849664 +- # :root:system:14050918400:linear::0:1:0:14050918400 +- # :swap:system:1262485504:linear::0:1:0:1262485504 ++ # :home:system:6148849664:linear::0:1:0:6148849664: ++ # :root:system:14050918400:linear::0:1:0:14050918400: ++ # :swap:system:1262485504:linear::0:1:0:1262485504: + # There are two leading blanks in the output (at least on SLES12-SP4 with LVM 2.02.180 and SLES15-SP3 with LVM 2.03.05). + # The 'lvs' output lines ordering does not match the ordering of the LVs kernel device nodes /dev/dm-N + # # lsblk -ipbo NAME,KNAME,TYPE,FSTYPE,SIZE,MOUNTPOINT /dev/sda2 +@@ -251,9 +251,9 @@ local lvs_exit_code + # that the recreated system did not boot (boot screen showed GRUB but there it hung with constant 100% CPU usage) + # so automatically shrinking only the biggest LVs avoids that a relatively small 'swap' LV gets shrinked. + # With 'sort -n -t ':' -k 4' the above 'lvs' output lines become +- # :swap:system:1262485504:linear::0:1:0:1262485504 +- # :home:system:6148849664:linear::0:1:0:6148849664 +- # :root:system:14050918400:linear::0:1:0:14050918400 ++ # :swap:system:1262485504:linear::0:1:0:1262485504: ++ # :home:system:6148849664:linear::0:1:0:6148849664: ++ # :root:system:14050918400:linear::0:1:0:14050918400: + # so only the 'root' LV may get automatically shrinked if needed. + lvm lvs --separator=':' --noheadings --units b --nosuffix -o $lvs_fields | sort -n -t ':' -k 4 | while read line ; do + +@@ -304,14 +304,23 @@ local lvs_exit_code + # With the above example segmentsize=19927138304 and segmentsize=1535115264 + segmentsize="$( echo "$line" | awk -F ':' '{ print $10 }' )" + +- # TODO: Explain what that code is meant to do. +- # In particular a more explanatory variable name than 'kval' might help. +- # In 110_include_lvm_code.sh there is a comment what 'kval' means there +- # # kval: "key:value" pairs, separated by spaces +- # so probably 'kval' means the same here, but what is 'infokval'? ++ # With the above example poolmetadatasize="" ++ poolmetadatasize="$( echo "$line" | awk -F ':' '{ print $11 }' )" ++ ++ # kval is a string of space-separated key:value pairs. Key names are chosen to represent ++ # long options to lvcreate, and value will be the parameter for each long option. ++ # e.g. "chunksize:${chunksize}b" will eventually become a --chunksize=${chunksize}b ++ # argument to lvcreate. ++ # This way 110_include_lvm_code.sh which constructs the arguments to lvcreate ++ # can be kept generic and does not need to be updated every time an argument is added, ++ # as long as the argument can follow this generic scheme. ++ # infokval are key:value pairs that are not used when restoring the layout ++ # and are kept in disklayout.conf only as comments for information ++ # (because the setting is not easy or desirable to preserve). + kval="" + infokval="" + [ -z "$thinpool" ] || kval="${kval:+$kval }thinpool:$thinpool" ++ [ -z "$poolmetadatasize" ] || kval="${kval:+$kval }poolmetadatasize:${poolmetadatasize}b" + [ $chunksize -eq 0 ] || kval="${kval:+$kval }chunksize:${chunksize}b" + [ $stripesize -eq 0 ] || kval="${kval:+$kval }stripesize:${stripesize}b" + [ $segmentsize -eq $size ] || infokval="${infokval:+$infokval }segmentsize:${segmentsize}b" diff --git a/SOURCES/rear-skip-btrfs-subvolumes-when-detecting-ESP-partitions.patch b/SOURCES/rear-skip-btrfs-subvolumes-when-detecting-ESP-partitions.patch new file mode 100644 index 0000000..133a93e --- /dev/null +++ b/SOURCES/rear-skip-btrfs-subvolumes-when-detecting-ESP-partitions.patch @@ -0,0 +1,62 @@ +From c8409e1f2972e9cd87d9390ca0b52b908d1a872a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= +Date: Wed, 20 Mar 2024 12:22:46 +0100 +Subject: [PATCH] skip btrfs subvolumes when detecting ESP partitions + +The idea is to find all direct partitions that contain the ESP +mount point and to skip all other transitive `fs:` dependencies. + +The `diskdeps.conf` file contains following entries on default Fedora +installations (the list was shortened to only the relevant ones): +``` +/dev/vda1 /dev/vda +/dev/vda4 /dev/vda +/dev/vda5 /dev/vda +fs:/boot/efi /dev/vda1 +fs:/boot/efi fs:/boot +fs:/boot/efi fs:/ +fs:/boot/efi btrfsmountedsubvol:/ +fs:/boot /dev/vda4 +fs:/boot fs:/ +fs:/boot btrfsmountedsubvol:/ +fs:/ /dev/vda5 +btrfsmountedsubvol:/ /dev/vda5 +``` + +The ESP partition is only on `/dev/vda1`. However, the `find_partition` call +was not taking into account the need to skip mounted btrfs subvolumes as well. +Therefore, `/dev/vda5` was listed as an ESP partition as well. + +This change makes sure that only direct ESP partitions are listed and +fixes a bug where ReaR would create broken BootXXXX entries which point to +completely unrelated partitions. + +Relevant excerpts from logs: +``` +++ efibootmgr --create --gpt --disk /dev/vda --part 1 --write-signature --label 'RedHatEnterpriseServer 41' --loader '\EFI\fedora\grubx64.efi' +... +++ efibootmgr --create --gpt --disk /dev/vda --part 5 --write-signature --label 'RedHatEnterpriseServer 41' --loader '\EFI\fedora\grubx64.efi' +``` +--- + usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh b/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh +index 33d87767..8b658618 100644 +--- a/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh ++++ b/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh +@@ -47,7 +47,10 @@ fi + # accounting for possible trailing slashes in TARGET_FS_ROOT + esp_mountpoint_inside="${esp_mountpoint#${TARGET_FS_ROOT%%*(/)}}" + +-boot_efi_parts=$( find_partition "fs:$esp_mountpoint_inside" fs ) ++# Find all partitions with the ESP mount point and skip all other transitive ++# 'fs' and 'btrfsmountedsubvol' components in LAYOUT_DEPS (var/lib/rear/layout/diskdeps.conf) ++# to support ESP on software RAID (cf. https://github.com/rear/rear/pull/2608). ++boot_efi_parts=$( find_partition "fs:$esp_mountpoint_inside" 'btrfsmountedsubvol fs' ) + if ! test "$boot_efi_parts" ; then + LogPrint "Unable to find ESP $esp_mountpoint_inside in layout" + LogPrint "Trying to determine device currently mounted at $esp_mountpoint as fallback" +-- +2.44.0 + diff --git a/SOURCES/rear-skip-invalid-drives-RHEL-22863.patch b/SOURCES/rear-skip-invalid-drives-RHEL-22863.patch new file mode 100644 index 0000000..365022a --- /dev/null +++ b/SOURCES/rear-skip-invalid-drives-RHEL-22863.patch @@ -0,0 +1,90 @@ +commit c08658d5a0260c3242bb817e77b9c6dadecd14f6 +Merge: 879e173f db191aaf +Author: pcahyna +Date: Wed Sep 13 12:46:54 2023 +0200 + + Merge pull request #3047 from pcahyna/skip-invalid-drives + + Skip invalid disk drives (zero sized, no media) when saving layout + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh +index 9d6e0bc6..b2dc743a 100644 +--- a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh ++++ b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh +@@ -413,17 +413,21 @@ Log "Saving disks and their partitions" + elif [[ ! ($blockd = *rpmb || $blockd = *[0-9]boot[0-9]) ]]; then # Silently skip Replay Protected Memory Blocks and others + devname=$(get_device_name $disk) + devsize=$(get_disk_size ${disk#/sys/block/}) +- disktype=$(parted -s $devname print | grep -E "Partition Table|Disk label" | cut -d ":" -f "2" | tr -d " ") + # Ensure syntactically correct 'disk' entries: + # Each value must exist and each value must be a single non-blank word so we 'test' without quoting the value: + test $devname || Error "Invalid 'disk' entry (no disk device name for '$disk')" + test $devsize || Error "Invalid 'disk $devname' entry (no device size for '$devname')" +- # We do not error out when there is no partition label type value because +- # "rear recover" works in a special case without partition label type value when there is +- # only a 'disk' entry but nothing else for this disk exists in disklayout.conf +- # which can happen when /dev/sdX is an empty SD card slot without medium, +- # see https://github.com/rear/rear/issues/2810 +- test $disktype || LogPrintError "No partition label type for 'disk $devname' (may cause 'rear recover' failure)" ++ # Validation error can happen when /dev/sdX is an empty SD card slot without medium, ++ # see https://github.com/rear/rear/issues/2810 https://github.com/rear/rear/issues/2958 ++ # this is normal, but such device must be skipped and not be added to the layout ++ # - it does not contain any data anyway. ++ # See https://github.com/rear/rear/pull/3047 ++ if ! validation_error=$(is_disk_valid $devname) ; then ++ LogPrintError "Ignoring $blockd: $validation_error" ++ continue ++ fi ++ disktype=$(parted -s $devname print | grep -E "Partition Table|Disk label" | cut -d ":" -f "2" | tr -d " ") ++ test $disktype || Error "Invalid 'disk $devname' entry (no partition table type for '$devname')" + if [ "$disktype" != "dasd" ]; then + echo "# Disk $devname" + echo "# Format: disk " +diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh +index 6dd43313..e46478d6 100644 +--- a/usr/share/rear/lib/layout-functions.sh ++++ b/usr/share/rear/lib/layout-functions.sh +@@ -819,6 +819,41 @@ is_disk_a_pv() { + return 1 + } + ++# Check whether disk is suitable for being added to layout ++# Can be used to skip obviously unsuitable/broken devices ++# (missing device node, zero size, device can't be opened). ++# Should not be used to skip potential mapping targets before layout restoration ++# - an invalid disk may become valid later, for example if it is a DASD that needs ++# low-level formatting (see 090_include_dasd_code.sh and 360_generate_dasd_format_code.sh), ++# unformatted DASDs show zero size. ++# Returns 0 if the device is ok ++# Returns nonzero code if it should be skipped, and a text describing the error ++# on stdout ++# usage example: ++# local err ++# if ! err=$(is_disk_valid /dev/sda); then ++ ++function is_disk_valid { ++ local disk="$1" ++ local size ++ ++ if ! test -b "$disk" ; then ++ echo "$disk is not a block device" ++ return 1 ++ fi ++ # capture stdout in a variable and redirect stderr to stdout - the error message ++ # will be our output ++ if { size=$(blockdev --getsize64 "$disk") ; } 2>&1 ; then ++ if ! test "$size" -gt 0 2>/dev/null ; then ++ echo "$disk has invalid size $size" ++ return 1 ++ fi ++ return 0 ++ else ++ return 1 ++ fi ++} ++ + function is_multipath_used { + # Return 'false' if there is no multipath command: + type multipath &>/dev/null || return 1 diff --git a/SOURCES/rear-skip-useless-xfs-mount-options-RHEL-10478.patch b/SOURCES/rear-skip-useless-xfs-mount-options-RHEL-10478.patch new file mode 100644 index 0000000..38e3c03 --- /dev/null +++ b/SOURCES/rear-skip-useless-xfs-mount-options-RHEL-10478.patch @@ -0,0 +1,112 @@ +commit ed4c78d5fe493ea368989d0086a733653692f5cb +Merge: 3c9398bb 0cdcab02 +Author: pcahyna +Date: Mon Oct 30 18:31:01 2023 +0100 + + Merge pull request #3058 from pcahyna/skip-useless-xfs-mount-options + + Skip useless xfs mount options when mounting during recovery + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh +index d5707779..f7115f55 100644 +--- a/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh ++++ b/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh +@@ -29,6 +29,7 @@ mount_fs() { + case $name in + (options) + # Do not mount nodev, as chrooting later on would fail: ++ # FIXME: naive approach, will replace any "nodev" inside longer options/values + value=${value//nodev/dev} + # btrfs mount options like subvolid=259 or subvol=/@/.snapshots/1/snapshot + # from the old system cannot work here for recovery because btrfs subvolumes +@@ -36,13 +37,8 @@ mount_fs() { + # so that those mount options are removed here. All btrfs subvolume handling + # happens in the btrfs_subvolumes_setup_SLES function in 136_include_btrfs_subvolumes_SLES_code.sh + # or in the btrfs_subvolumes_setup_generic function in 135_include_btrfs_subvolumes_generic_code.sh +- # First add a comma at the end so that it is easier to remove a mount option at the end: +- value=${value/%/,} +- # Remove all subvolid= and subvol= mount options (the extglob shell option is enabled in rear): +- value=${value//subvolid=*([^,]),/} +- value=${value//subvol=*([^,]),/} +- # Remove all commas at the end: +- mountopts=${value/%,/} ++ # Remove all subvolid= and subvol= mount options: ++ mountopts="$( remove_mount_options_values $value subvolid subvol )" + ;; + esac + done +@@ -147,6 +143,27 @@ mount_fs() { + echo "mount $mountopts,remount,user_xattr $device $TARGET_FS_ROOT$mountpoint" + ) >> "$LAYOUT_CODE" + ;; ++ (xfs) ++ # remove logbsize=... mount option. It is a purely performance/memory usage optimization option, ++ # which can lead to mount failures, because it must be an integer multiple of the log stripe unit ++ # and the log stripe unit can be different in the recreated filesystem from the original filesystem ++ # (for example when using MKFS_XFS_OPTIONS, or in some exotic situations involving an old filesystem, ++ # see GitHub issue #2777 ). ++ # If logbsize is not an integer multiple of the log stripe unit, mount fails with the warning ++ # "XFS (...): logbuf size must be greater than or equal to log stripe size" ++ # in the kernel log ++ # (and a confusing error message ++ # "mount: ...: wrong fs type, bad option, bad superblock on ..., missing codepage or helper program, or other error." ++ # from the mount command), causing the layout restoration in the recovery process to fail. ++ # Wrong sunit/swidth can cause mount to fail as well, with this in the kernel log: ++ # "kernel: XFS (...): alignment check failed: sunit/swidth vs. agsize", ++ # so remove the sunit=.../swidth=... mount options as well. ++ mountopts="$( remove_mount_options_values "$mountopts" logbsize sunit swidth )" ++ ( ++ echo "mkdir -p $TARGET_FS_ROOT$mountpoint" ++ echo "mount $mountopts $device $TARGET_FS_ROOT$mountpoint" ++ ) >> "$LAYOUT_CODE" ++ ;; + (*) + ( + echo "mkdir -p $TARGET_FS_ROOT$mountpoint" +diff --git a/usr/share/rear/lib/filesystems-functions.sh b/usr/share/rear/lib/filesystems-functions.sh +index f459c204..f0547706 100644 +--- a/usr/share/rear/lib/filesystems-functions.sh ++++ b/usr/share/rear/lib/filesystems-functions.sh +@@ -256,3 +256,40 @@ function total_target_fs_used_disk_space() { + # Output xfs options for further use + echo "$xfs_opts" + } ++ ++ ++# $1 is a mount command argument (string containing comma-separated ++# mount options). The remaining arguments to the function ($2 ... ) ++# specify the mount options to remove from $1, together with a trailing "=" ++# and any value that follows each option. ++# For example, the call ++# "remove_mount_options_values nodev,uid=1,rw,gid=1 uid gid" ++# returns "nodev,rw". ++# There is no support for removing a mount option without a value and "=", ++# so "remove_mount_options_values nodev,uid=1,rw,gid=1 rw" will not work. ++# The function will return the modified string on stdout. ++ ++function remove_mount_options_values () { ++ local str="$1" ++ ++ shift ++ # First add a comma at the end so that it is easier to remove a mount option at the end: ++ str="${str/%/,}" ++ for i in "$@" ; do ++ # FIXME this also removes trailing strings at the end of longer words ++ # For example if one wants to remove any id=... option, ++ # the function will also replace "uid=1" by "u" by removing ++ # the trailing "id=1", which is not intended. ++ # Not easy to fix because $str can contain prefixes which are not ++ # mount options but arguments to the mount command itself ++ # (in particluar, "-o "). ++ # FIXME this simple approach would fail in case of mount options ++ # containing commas, for example the "context" option values, ++ # see mount(8) ++ ++ # the extglob shell option is enabled in rear ++ str="${str//$i=*([^,]),/}" ++ done ++ # Remove all commas at the end: ++ echo "${str/%,/}" ++} diff --git a/SOURCES/rear-uefi-booting-with-multiple-cdrom-devices.patch b/SOURCES/rear-uefi-booting-with-multiple-cdrom-devices.patch new file mode 100644 index 0000000..59b470b --- /dev/null +++ b/SOURCES/rear-uefi-booting-with-multiple-cdrom-devices.patch @@ -0,0 +1,343 @@ +commit 283efdaea10ff62dc94e968f74e1136b8384a954 +Merge: 41c2d9b1 70a39382 +Author: Johannes Meixner +Date: Fri Jul 21 14:56:34 2023 +0200 + + Merge pull request #3025 from rear/jsmeix-create_grub2_cfg + + Fixed create_grub2_cfg function usage: + Introduced GRUB2_SET_ROOT_COMMAND config variable + in addition to the existing GRUB2_SEARCH_ROOT_COMMAND + to get consistency how GRUB2 sets and/or searches its 'root' device + and adapted the create_grub2_cfg function calls accordingly. + Furthermore enhanced some messages regarding Secure Boot setup. + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf +index 3e29280f..5ec89049 100644 +--- a/usr/share/rear/conf/default.conf ++++ b/usr/share/rear/conf/default.conf +@@ -1210,15 +1210,6 @@ USB_BIOS_BOOT_DEFAULT="" + # Default is using GRUB2 for EFI other then elilo, extlinux for ext, syslinux otherwise: + USB_BOOTLOADER= + # +-# USB EFI booting can benefit with a better search string than the default: +-# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI +-# as hardcoded in script output/USB/Linux-i386/100_create_efiboot.sh +-# Only to be used by experts. An example of a different setup could be: +-# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI --hint hd0,msdos1" +-# or +-# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --file /EFI/BOOT/BOOTX64.efi" +-GRUB2_SEARCH_ROOT_COMMAND="" +-# + # Resulting files that should be copied onto the USB stick: + USB_FILES=() + # +@@ -3550,12 +3541,12 @@ GRUB2_INSTALL_DEVICES="${GRUB2_INSTALL_DEVICES:-}" + # and /boot/efi, if applicable. + # More modules can be installed into the Grub2 standalone image ramdisk without + # being included in the core image, see GRUB2_MODULES_UEFI. +-# This variable currently applies when building Grub2 boot loader for UEFI in two scenarios: ++# This variable currently applies when building GRUB2 boot loader for UEFI in two scenarios: + # 1. UEFI boot without secure boot (SECURE_BOOT_BOOTLOADER="") + # and / or + # 2. UEFI boot with GRUB_RESCUE="y" +-# Incorrect use of this variable can lead to unusable ReaR recovery system. +-# When you modify this variable, verify that your ReaR recovery system works. ++# Incorrect use of this variable can lead to an unusable ReaR recovery system. ++# When you specify it, verify that your ReaR recovery system works. + GRUB2_MODULES_UEFI_LOAD=() + + ## +@@ -3565,8 +3556,8 @@ GRUB2_MODULES_UEFI_LOAD=() + # When empty ReaR will use the defaults of grub-mkstandalone + # (install all modules in the standalone image ramdisk) + # This variable currently applies in the same scenarios as GRUB2_MODULES_UEFI_LOAD. +-# Incorrect use of this variable can lead to unusable ReaR recovery system. +-# When you modify this variable, verify that your ReaR recovery system works. ++# Incorrect use of this variable can lead to an unusable ReaR recovery system. ++# When you specify it, verify that your ReaR recovery system works. + GRUB2_MODULES_UEFI=() + + ## +@@ -3587,6 +3578,29 @@ GRUB2_DEFAULT_BOOT="chainloader" + # The timeout in seconds to automatically boot GRUB2_DEFAULT_BOOT + # when GRUB2 is used as bootloader for the ReaR recovery system. + GRUB2_TIMEOUT="$USER_INPUT_TIMEOUT" ++# ++# GRUB2_SET_ROOT_COMMAND ++# GRUB2_SEARCH_ROOT_COMMAND ++# Incorrect use of those variables can lead to an unusable ReaR recovery system. ++# When you specify one of them, verify that your ReaR recovery system works. ++# GRUB2_SET_ROOT_COMMAND is a GRUB2 command to set the 'root' device in GRUB2. ++# For example to set the first CDROM device to be used as 'root' device in GRUB2 use ++# GRUB2_SET_ROOT_COMMAND="set root=cd0" ++# GRUB2_SEARCH_ROOT_COMMAND is a GRUB2 command to let GRUB2 search for its 'root' device. ++# For example USB EFI booting may need a different search string than the default like ++# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI" ++# cf. the script output/USB/Linux-i386/100_create_efiboot.sh ++# Other examples of a different setup could be like ++# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label REAR-EFI --hint hd0,msdos1" ++# or ++# GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --file /EFI/BOOT/BOOTX64.efi" ++# When both GRUB2_SET_ROOT_COMMAND and GRUB2_SEARCH_ROOT_COMMAND are specified ++# then GRUB2_SET_ROOT_COMMAND is done before GRUB2_SEARCH_ROOT_COMMAND ++# so GRUB2_SET_ROOT_COMMAND sets a default 'root' device and ++# then GRUB2 searches for a 'root' device via GRUB2_SEARCH_ROOT_COMMAND ++# which is used if one is found - otherwise the default 'root' device is used as fallback. ++GRUB2_SET_ROOT_COMMAND="" ++GRUB2_SEARCH_ROOT_COMMAND="" + + ## + # USING_UEFI_BOOTLOADER +@@ -3625,13 +3639,18 @@ USING_UEFI_BOOTLOADER= + ## + # SECURE_BOOT_BOOTLOADER + # +-# When using Secure Boot set full path of your signed boot loader here. +-# e. g. +-# SECURE_BOOT_BOOTLOADER="/boot/efi/EFI/BOOT/shim.efi" +-# +-# SECURE_BOOT_BOOTLOADER overrides UEFI_BOOTLOADER +-# +-# c.f. https://github.com/rear/rear/pull/1385 ++# When using Secure Boot specify the full path of the Secure Boot bootloader. ++# For example: SECURE_BOOT_BOOTLOADER="/boot/efi/EFI/BOOT/shim.efi" ++# SECURE_BOOT_BOOTLOADER overrides UEFI_BOOTLOADER. ++# Normally Shim is the only used Secure Boot bootloader. ++# For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html ++# Shim is a first stage bootloader that loads and executes a second stage bootloader ++# which normally is GRUB that is usually available as a grub*.efi file. ++# When Shim is used, its second stage bootloader can be actually anything ++# named grub*.efi (second stage bootloader is Shim compile time option) ++# so when for example SECURE_BOOT_BOOTLOADER="/boot/efi/EFI/BOOT/shim.efi" is specified ++# then all /boot/efi/EFI/BOOT/grub*.efi files are made available as second stage bootloader. ++# For more details see the output/ISO/Linux-i386/250_populate_efibootimg.sh script. + SECURE_BOOT_BOOTLOADER="" + + ## +diff --git a/usr/share/rear/lib/bootloader-functions.sh b/usr/share/rear/lib/bootloader-functions.sh +index 5f18d2ad..f3e27937 100644 +--- a/usr/share/rear/lib/bootloader-functions.sh ++++ b/usr/share/rear/lib/bootloader-functions.sh +@@ -536,25 +536,25 @@ function get_root_disk_UUID { + # so that kernel and initrd are /boot_mountpoint/path/to/kernel and /boot_mountpoint/path/to/initrd + # and that boot partition gets set as root device name for GRUB2's + # then $1 would have to be /path/to/kernel and $2 would have to be /path/to/initrd +-# $3 is an appropriate GRUB2 command to set its root device (usually via GRUB2's 'root' environment variable) +-# e.g. when the filesystem that contains kernel and initrd has the filesystem label REARBOOT +-# then $3 could be something like 'search --no-floppy --set root --label REARBOOT' + function create_grub2_cfg { + local grub2_kernel="$1" + test "$grub2_kernel" || BugError "create_grub2_cfg function called without grub2_kernel argument" +- DebugPrint "Configuring GRUB2 kernel $grub2_kernel" ++ DebugPrint "Let GRUB2 load kernel $grub2_kernel" + local grub2_initrd="$2" + test "$grub2_initrd" || BugError "create_grub2_cfg function called without grub2_initrd argument" +- DebugPrint "Configuring GRUB2 initrd $grub2_initrd" +- local grub2_search_root_command="$3" +- if ! test "$grub2_search_root_command" ; then +- test "$grub2_set_root" && grub2_search_root_command="set root=$grub2_set_root" +- fi +- if ! test "$grub2_search_root_command" ; then +- test "$GRUB2_SEARCH_ROOT_COMMAND" && grub2_search_root_command="$GRUB2_SEARCH_ROOT_COMMAND" ++ DebugPrint "Let GRUB2 load initrd $grub2_initrd" ++ ++ # Before https://github.com/rear/rear/pull/3025 it was possible to call create_grub2_cfg() ++ # with a third argument that is a "search GRUB2 'root' device command" string: ++ test "$3" && BugError "create_grub2_cfg function must not be called with a third argument" ++ # Since https://github.com/rear/rear/pull/3025 GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND must be specified: ++ if contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" ; then ++ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" && DebugPrint "Set GRUB2 default root device via '$GRUB2_SET_ROOT_COMMAND'" ++ DebugPrint "Let GRUB2 search root device via '$GRUB2_SEARCH_ROOT_COMMAND'" ++ else ++ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" || BugError "create_grub2_cfg function called but neither GRUB2_SET_ROOT_COMMAND nor GRUB2_SEARCH_ROOT_COMMAND is specified" ++ DebugPrint "Set GRUB2 root device via '$GRUB2_SET_ROOT_COMMAND'" + fi +- test "$grub2_search_root_command" || grub2_search_root_command="search --no-floppy --set=root --file /boot/efiboot.img" +- DebugPrint "Configuring GRUB2 root device as '$grub2_search_root_command'" + + local grub2_default_menu_entry="$GRUB2_DEFAULT_BOOT" + test "$grub2_default_menu_entry" || grub2_default_menu_entry="chainloader" +@@ -613,6 +613,9 @@ function create_grub2_cfg { + echo "terminal_input serial" + echo "terminal_output serial" + fi ++ else ++ DebugPrint "No serial console in GRUB2 (USE_SERIAL_CONSOLE is not true)" ++ echo "echo 'No serial console (USE_SERIAL_CONSOLE was not true)'" + fi + } + +@@ -632,7 +635,6 @@ menuentry "Relax-and-Recover (BIOS or UEFI without Secure Boot)" --id=rear { + echo 'Loading initial ramdisk $grub2_initrd ...' + initrd $grub2_initrd + } +- + menuentry "Relax-and-Recover (UEFI and Secure Boot)" --id=rear_secure_boot { + insmod gzio + insmod xzio +@@ -714,10 +716,14 @@ EOF + + # The actual work starts here. + # Create and output GRUB2 configuration. +- # Sleep 3 seconds before the GRUB2 menu replaces what there is on the screen +- # so that the user has a chance to see possible (error) messages on the screen. ++ # Sleep (interruptible) USER_INPUT_INTERRUPT_TIMEOUT seconds (by default 30 seconds) ++ # before the GRUB2 menu replaces what there is on the screen ++ # so that the user can read and understand possible (error) messages on the screen. + cat << EOF +-$grub2_search_root_command ++$GRUB2_SET_ROOT_COMMAND ++$GRUB2_SEARCH_ROOT_COMMAND ++echo "Using root device (\$root) - available devices are:" ++ls + insmod all_video + set gfxpayload=keep + insmod part_gpt +@@ -727,8 +733,8 @@ $( create_grub2_serial_entry ) + set timeout="$grub2_timeout" + set default="$grub2_default_menu_entry" + set fallback="chainloader" +-echo 'Switching to GRUB2 boot menu...' +-sleep --verbose --interruptible 3 ++echo 'Switching to GRUB boot menu...' ++sleep --verbose --interruptible $USER_INPUT_INTERRUPT_TIMEOUT + $( create_grub2_rear_boot_entry ) + $( create_grub2_boot_next_entry ) + $( create_grub2_reboot_entry ) +diff --git a/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh b/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh +index c0fc5834..ff97dbd1 100644 +--- a/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh ++++ b/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh +@@ -13,22 +13,32 @@ mkdir $v -p $efi_boot_tmp_dir || Error "Could not create $efi_boot_tmp_dir" + mkdir $v -p $efi_boot_tmp_dir/fonts || Error "Could not create $efi_boot_tmp_dir/fonts" + mkdir $v -p $efi_boot_tmp_dir/locale || Error "Could not create $efi_boot_tmp_dir/locale" + +-# Copy the grub*.efi executable to EFI/BOOT/BOOTX64.efi ++# Copy the grub*.efi or shim.efi executable to EFI/BOOT/BOOTX64.efi + # Intentionally an empty UEFI_BOOTLOADER results an invalid "cp -v /tmp/.../mnt/EFI/BOOT/BOOTX64.efi" command that fails: + cp $v "$UEFI_BOOTLOADER" $efi_boot_tmp_dir/BOOTX64.efi || Error "Could not find UEFI_BOOTLOADER '$UEFI_BOOTLOADER'" + local uefi_bootloader_dirname="$( dirname $UEFI_BOOTLOADER )" + if test -f "$SECURE_BOOT_BOOTLOADER" ; then +- # FIXME: Explain why it tests that a SECURE_BOOT_BOOTLOADER file exists +- # but then it copies any grub*.efi files and ignores if there are none. +- # Why does it not copy SECURE_BOOT_BOOTLOADER and errors out if that fails? +- # If shim is used, bootloader can be actually anything +- # named as grub*.efi (follow-up loader is shim compile time option), see ++ # For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html ++ # Shim is a signed EFI binary that is a first stage bootloader ++ # that loads and executes another (signed) EFI binary ++ # which normally is a second stage bootloader ++ # which normally is a GRUB EFI binary ++ # which normally is available as a file named grub*.efi ++ # so when SECURE_BOOT_BOOTLOADER is used as UEFI_BOOTLOADER ++ # (cf. rescue/default/850_save_sysfs_uefi_vars.sh) ++ # then Shim (usually shim.efi) was copied above as efi_boot_tmp_dir/BOOTX64.efi ++ # and Shim's second stage bootloader must be also copied where Shim already is. ++ DebugPrint "Using Shim '$SECURE_BOOT_BOOTLOADER' as first stage UEFI bootloader BOOTX64.efi" ++ # When Shim is used, its second stage bootloader can be actually anything ++ # named grub*.efi (second stage bootloader is Shim compile time option), see + # http://www.rodsbooks.com/efi-bootloaders/secureboot.html#initial_shim ++ local second_stage_UEFI_bootloader_files="$( echo $uefi_bootloader_dirname/grub*.efi )" + # Avoid 'nullglob' pitfall when nothing matches .../grub*.efi which results + # an invalid "cp -v /tmp/.../mnt/EFI/BOOT/" command that fails + # cf. https://github.com/rear/rear/issues/1921 +- local shim_files="$( echo $uefi_bootloader_dirname/grub*.efi )" +- test "$shim_files" && cp $v $shim_files $efi_boot_tmp_dir/ ++ test "$second_stage_UEFI_bootloader_files" || Error "Could not find second stage bootloader '$uefi_bootloader_dirname/grub*.efi' for Shim" ++ DebugPrint "Using second stage UEFI bootloader files for Shim: $second_stage_UEFI_bootloader_files" ++ cp $v $second_stage_UEFI_bootloader_files $efi_boot_tmp_dir/ || Error "Failed to copy second stage bootloader files for Shim" + fi + + # FIXME: Do we need to test if we are ebiso at all? +@@ -47,6 +57,12 @@ if test "ebiso" = "$( basename $ISO_MKISOFS_BIN )" ; then + cp -pL $v $KERNEL_FILE $efi_boot_tmp_dir/kernel || Error "Failed to copy KERNEL_FILE '$KERNEL_FILE' to $efi_boot_tmp_dir/kernel" + cp $v $TMP_DIR/$REAR_INITRD_FILENAME $efi_boot_tmp_dir/$REAR_INITRD_FILENAME || Error "Failed to copy initrd '$REAR_INITRD_FILENAME' into $efi_boot_tmp_dir" + create_ebiso_elilo_conf > $efi_boot_tmp_dir/elilo.conf ++ # We need to set the GRUB environment variable 'root' to a reasonable default/fallback value ++ # because GRUB's default 'root' (or GRUB's 'root' identifcation heuristics) would point to the ramdisk ++ # but neither kernel nor initrd are located on the ramdisk but on the device where the recovery system was booted from. ++ # GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND is needed by the create_grub2_cfg() function. ++ # Set GRUB2_SET_ROOT_COMMAND if not specified by the user: ++ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" || GRUB2_SET_ROOT_COMMAND="set root=cd0" + create_grub2_cfg /isolinux/kernel /isolinux/$REAR_INITRD_FILENAME > $efi_boot_tmp_dir/grub.cfg + fi + fi +@@ -67,10 +83,12 @@ else + # This was seen at least in Debian Buster running in Qemu + # (VirtualBox works fine, RHEL/CentOS in Qemu works fine as well). + # The GRUB2 image created by grub-mkstandalone has 'root' set to memdisk, which can't work. +- # To make ReaR work in this case, set 'root' to a sensible value 'cd0' before trying search +- # (via ${grub2_set_root:+"set root=$grub2_set_root"} in the create_grub2_cfg function) ++ # To make ReaR work in this case, set 'root' to a sensible default value 'cd0' ++ # before trying to search via GRUB2_SEARCH_ROOT_COMMAND in the create_grub2_cfg function + # cf. https://github.com/rear/rear/issues/2434 and https://github.com/rear/rear/pull/2453 +- grub2_set_root=cd0 ++ # Set GRUB2_SET_ROOT_COMMAND and GRUB2_SEARCH_ROOT_COMMAND if not specified by the user: ++ contains_visible_char "$GRUB2_SET_ROOT_COMMAND" || GRUB2_SET_ROOT_COMMAND="set root=cd0" ++ contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" || GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --file /boot/efiboot.img" + create_grub2_cfg /isolinux/kernel /isolinux/$REAR_INITRD_FILENAME > $efi_boot_tmp_dir/grub.cfg + fi + +diff --git a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh +index 1f6ca069..8ad4d97e 100644 +--- a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh ++++ b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh +@@ -93,11 +93,13 @@ EOF + ;; + (2) + DebugPrint "Configuring GRUB2 for EFI boot" +- # We need to explicitly set GRUB 2 'root' variable to $efi_label (hardcoded "REAR-EFI") +- # because default $root would point to memdisk, where kernel and initrd are NOT present. +- # GRUB2_SEARCH_ROOT_COMMAND is used in the create_grub2_cfg() function: +- [[ -z "$GRUB2_SEARCH_ROOT_COMMAND" ]] && GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $efi_label" +- # Create config for GRUB 2 ++ # We need to set the GRUB environment variable 'root' to the partition device with label $efi_label (hardcoded "REAR-EFI") ++ # because GRUB's default 'root' (or GRUB's 'root' identifcation heuristics) would point to the ramdisk but neither kernel ++ # nor initrd are located on the ramdisk but on the partition device with label $efi_label. ++ # GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND is needed by the create_grub2_cfg() function. ++ # Set GRUB2_SEARCH_ROOT_COMMAND if not specified by the user: ++ contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" || GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $efi_label" ++ # Create config for GRUB2: + create_grub2_cfg $efi_dir/kernel $efi_dir/$REAR_INITRD_FILENAME > $efi_dst/grub.cfg + # Create BOOTX86.efi but only if we are NOT secure booting. + # We are not able to create signed boot loader +diff --git a/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh b/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh +index c2566bc5..1dbfe1de 100644 +--- a/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh ++++ b/usr/share/rear/output/USB/Linux-i386/300_create_grub.sh +@@ -70,10 +70,11 @@ if is_true $USING_UEFI_BOOTLOADER ; then + # grub[2]-install creates the $BUILD_DIR/outputfs/boot/grub[2] sub-directory that is needed + # to create the GRUB2 config $BUILD_DIR/outputfs/boot/grub[2].cfg in the next step: + DebugPrint "Creating GRUB2 config for legacy BIOS boot as USB bootloader" +-test "$USB_DEVICE_BOOT_LABEL" || USB_DEVICE_BOOT_LABEL="REARBOOT" ++contains_visible_char "$USB_DEVICE_BOOT_LABEL" || USB_DEVICE_BOOT_LABEL="REARBOOT" + # We need to set the GRUB environment variable 'root' to the partition device with filesystem label USB_DEVICE_BOOT_LABEL + # because GRUB's default 'root' (or GRUB's 'root' identifcation heuristics) would point to the ramdisk but neither kernel + # nor initrd are located on the ramdisk but on the partition device with filesystem label USB_DEVICE_BOOT_LABEL. +-# GRUB2_SEARCH_ROOT_COMMAND is used in the create_grub2_cfg() function: +-GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $USB_DEVICE_BOOT_LABEL" +-create_grub2_cfg /$USB_PREFIX/kernel /$USB_PREFIX/$REAR_INITRD_FILENAME > $usb_boot_dir/$grub_cfg || Error "Failed to create $usb_boot_dir/$grub_cfg" ++# GRUB2_SET_ROOT_COMMAND and/or GRUB2_SEARCH_ROOT_COMMAND is needed by the create_grub2_cfg() function. ++# Set GRUB2_SEARCH_ROOT_COMMAND if not specified by the user: ++contains_visible_char "$GRUB2_SEARCH_ROOT_COMMAND" || GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $USB_DEVICE_BOOT_LABEL" ++create_grub2_cfg /$USB_PREFIX/kernel /$USB_PREFIX/$REAR_INITRD_FILENAME > $usb_boot_dir/$grub_cfg +diff --git a/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh b/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh +index a1af17fa..051f2755 100644 +--- a/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh ++++ b/usr/share/rear/rescue/default/850_save_sysfs_uefi_vars.sh +@@ -135,7 +135,11 @@ for dummy in "once" ; do + done + + # Show to the user what will actually be used as UEFI bootloader file: +-LogPrint "Using '$UEFI_BOOTLOADER' as UEFI bootloader file" ++if test -f "$SECURE_BOOT_BOOTLOADER" ; then ++ LogPrint "Using '$UEFI_BOOTLOADER' as UEFI Secure Boot bootloader file" ++else ++ LogPrint "Using '$UEFI_BOOTLOADER' as UEFI bootloader file (non Secure Boot)" ++fi + + # Save the variables we need in recover mode into the rescue.conf file: + cat - <> "$ROOTFS_DIR/etc/rear/rescue.conf" diff --git a/SOURCES/rear-uefi-usb-secureboot-bz2196445.patch b/SOURCES/rear-uefi-usb-secureboot-bz2196445.patch new file mode 100644 index 0000000..c20ab8c --- /dev/null +++ b/SOURCES/rear-uefi-usb-secureboot-bz2196445.patch @@ -0,0 +1,88 @@ +commit 46b29195bff7f93cf5bd4c2dd83d69e5676800cb +Merge: 2611da2b efb37fb9 +Author: Johannes Meixner +Date: Tue Aug 8 14:44:16 2023 +0200 + + Merge pull request #3031 from rear/jsmeix-USB-Secure-Boot + + Secure Boot support for OUTPUT=USB: + In output/USB/Linux-i386/100_create_efiboot.sh + added SECURE_BOOT_BOOTLOADER related code that is based + on the code in output/ISO/Linux-i386/250_populate_efibootimg.sh + with some adaptions to make it work within the existing USB code. + The basic idea for Secure Boot booting of the ReaR recovery system + is to "just copy" the (signed) EFI binaries of the Linux distribution + (shim*.efi and grub*.efi as first and second stage UEFI bootloaders) + instead of let ReaR make its own EFI binary via build_bootx86_efi() + see https://github.com/rear/rear/pull/3031 + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh +index 8ad4d97e..123442cc 100644 +--- a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh ++++ b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh +@@ -51,8 +51,44 @@ mkdir -p $efi_dst || Error "Failed to create directory '$efi_dst'" + # "cp: failed to preserve ownership for '/tmp/rear-efi.XXXXXXXXXX/EFI/BOOT/kernel': Operation not permitted" + # because it copies to a VFAT filesystem on the EFI partition (see format/USB/default/300_format_usb_disk.sh) + # cf. https://github.com/rear/rear/issues/2683 +-# Copy boot loader: +-cp -L $v "$UEFI_BOOTLOADER" "$efi_dst/BOOTX64.efi" || Error "Failed to copy UEFI_BOOTLOADER '$UEFI_BOOTLOADER' to $efi_dst/BOOTX64.efi" ++# The SECURE_BOOT_BOOTLOADER related code below is based on the code in output/ISO/Linux-i386/250_populate_efibootimg.sh ++# because I noticed that Secure Boot works with ISO at least for me, cf. ++# https://github.com/rear/rear/pull/3025#issuecomment-1635876186 ++# but not with USB, cf. ++# https://github.com/rear/rear/pull/3025#issuecomment-1643774477 ++# so I tried to re-use the ISO Secure Boot code for USB ++# which made Secure Boot "just work" for me with USB ++# but I had to do some (minor) adaptions to make it work ++# within the existing USB code, cf. ++# https://github.com/rear/rear/pull/3031#issuecomment-1653443454 ++# Copy UEFI bootloader: ++if test -f "$SECURE_BOOT_BOOTLOADER" ; then ++ # For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html ++ # Shim is a signed EFI binary that is a first stage bootloader ++ # that loads and executes another (signed) EFI binary ++ # which normally is a second stage bootloader ++ # which normally is a GRUB EFI binary ++ # which normally is available as a file named grub*.efi ++ # so when SECURE_BOOT_BOOTLOADER is used as UEFI_BOOTLOADER ++ # (cf. rescue/default/850_save_sysfs_uefi_vars.sh) ++ # then Shim (usually shim.efi) must be copied as EFI/BOOT/BOOTX64.efi ++ # and Shim's second stage bootloader must be also copied where Shim already is. ++ DebugPrint "Using '$SECURE_BOOT_BOOTLOADER' as first stage Secure Boot bootloader BOOTX64.efi" ++ cp -L $v "$SECURE_BOOT_BOOTLOADER" "$efi_dst/BOOTX64.efi" || Error "Failed to copy SECURE_BOOT_BOOTLOADER '$SECURE_BOOT_BOOTLOADER' to $efi_dst/BOOTX64.efi" ++ # When Shim is used, its second stage bootloader can be actually anything ++ # named grub*.efi (second stage bootloader is Shim compile time option), see ++ # http://www.rodsbooks.com/efi-bootloaders/secureboot.html#initial_shim ++ local uefi_bootloader_dirname="$( dirname $SECURE_BOOT_BOOTLOADER )" ++ local second_stage_UEFI_bootloader_files="$( echo $uefi_bootloader_dirname/grub*.efi )" ++ # Avoid 'nullglob' pitfall when nothing matches .../grub*.efi which would result ++ # an invalid "cp -v /var/tmp/.../EFI/BOOT/" command that fails ++ # cf. https://github.com/rear/rear/issues/1921 ++ test "$second_stage_UEFI_bootloader_files" || Error "Could not find second stage Secure Boot bootloader $uefi_bootloader_dirname/grub*.efi" ++ DebugPrint "Using second stage Secure Boot bootloader files: $second_stage_UEFI_bootloader_files" ++ cp -L $v $second_stage_UEFI_bootloader_files $efi_dst/ || Error "Failed to copy second stage Secure Boot bootloader files" ++else ++ cp -L $v "$UEFI_BOOTLOADER" "$efi_dst/BOOTX64.efi" || Error "Failed to copy UEFI_BOOTLOADER '$UEFI_BOOTLOADER' to $efi_dst/BOOTX64.efi" ++fi + # Copy kernel: + cp -L $v "$KERNEL_FILE" "$efi_dst/kernel" || Error "Failed to copy KERNEL_FILE '$KERNEL_FILE' to $efi_dst/kernel" + # Copy initrd: +@@ -101,8 +137,14 @@ EOF + [[ -z "$GRUB2_SEARCH_ROOT_COMMAND" ]] && GRUB2_SEARCH_ROOT_COMMAND="search --no-floppy --set=root --label $efi_label" + # Create config for GRUB 2 + create_grub2_cfg $efi_dir/kernel $efi_dir/$REAR_INITRD_FILENAME > $efi_dst/grub.cfg +- # Create bootloader, this overwrite BOOTX64.efi copied in previous step ... +- build_bootx86_efi $efi_dst/BOOTX64.efi $efi_dst/grub.cfg "/boot" "$UEFI_BOOTLOADER" ++ # Create BOOTX86.efi but only if we are NOT secure booting. ++ # We are not able to create signed boot loader ++ # so we need to reuse existing one. ++ # See issue #1374 ++ # build_bootx86_efi () can be safely used for other scenarios. ++ if ! test -f "$SECURE_BOOT_BOOTLOADER" ; then ++ build_bootx86_efi $efi_dst/BOOTX64.efi $efi_dst/grub.cfg "/boot" "$UEFI_BOOTLOADER" ++ fi + ;; + (*) + Error "GRUB version '$grub_version' is neither '0' (legacy GRUB) nor '2' (GRUB 2)" diff --git a/SOURCES/rear.cron b/SOURCES/rear.cron new file mode 100644 index 0000000..b4dbce1 --- /dev/null +++ b/SOURCES/rear.cron @@ -0,0 +1,4 @@ +# cronjob for ReaR +# periodically check if disk layout has changed and update +# the rescue image +30 1 * * * root test -f /var/lib/rear/layout/disklayout.conf && /usr/sbin/rear checklayout || /usr/sbin/rear mkrescue diff --git a/SOURCES/rear.service b/SOURCES/rear.service new file mode 100644 index 0000000..e1e359a --- /dev/null +++ b/SOURCES/rear.service @@ -0,0 +1,6 @@ +[Unit] +Description=Update ReaR rescue image + +[Service] +Type=oneshot +ExecStart=/usr/sbin/rear checklayout || /usr/sbin/rear mkrescue diff --git a/SOURCES/rear.timer b/SOURCES/rear.timer new file mode 100644 index 0000000..6012724 --- /dev/null +++ b/SOURCES/rear.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Update ReaR rescue image + +[Timer] +OnCalendar=daily +RandomizedDelaySec=1h +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/SOURCES/s390-no-clobber-disks.patch b/SOURCES/s390-no-clobber-disks.patch new file mode 100644 index 0000000..7e17fc2 --- /dev/null +++ b/SOURCES/s390-no-clobber-disks.patch @@ -0,0 +1,797 @@ +commit 015c1ffd9fa96b01882b068714d3bc3aae3b5168 +Merge: 02dad206 20cc0137 +Author: Schlomo Schapiro +Date: Tue Feb 28 22:46:13 2023 +0100 + + Merge pull request #2943 from pcahyna/s390-layout-format + + s390x (IBM Z) disk formatting fixes + + Cherry-picked-by: Lukáš Zaoral + +diff --git a/packaging/rpm/rear.spec b/packaging/rpm/rear.spec +index eba48198..fb943019 100644 +--- a/packaging/rpm/rear.spec ++++ b/packaging/rpm/rear.spec +@@ -29,8 +29,8 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + # Of course the rear bash scripts can be installed on any architecture just as any binaries can be installed on any architecture. + # But the meaning of architecture dependent packages should be on what architectures they will work. + # Therefore only those architectures that are actually supported are explicitly listed. +-# This avoids that rear can be "just installed" on architectures that are actually not supported (e.g. ARM or IBM z Systems): +-ExclusiveArch: %ix86 x86_64 ppc ppc64 ppc64le ia64 ++# This avoids that rear can be "just installed" on architectures that are actually not supported (e.g. ARM): ++ExclusiveArch: %ix86 x86_64 ppc ppc64 ppc64le ia64 s390x + # Furthermore for some architectures it requires architecture dependent packages (like syslinux for x86 and x86_64) + # so that rear must be architecture dependent because ifarch conditions never match in case of "BuildArch: noarch" + # see the GitHub issue https://github.com/rear/rear/issues/629 +diff --git a/usr/share/rear/conf/default.conf b/usr/share/rear/conf/default.conf +index fe34636f..50baaf82 100644 +--- a/usr/share/rear/conf/default.conf ++++ b/usr/share/rear/conf/default.conf +@@ -486,6 +486,17 @@ test "$MIGRATION_MODE" || MIGRATION_MODE='' + # Currently by default no disk is wiped to avoid issues until this feature was more tested: + DISKS_TO_BE_WIPED='false' + ++## ++# Formatting DASDs (S/390 specific) ++# DASD (Direct Access Storage Device) denotes a disk drive on the S/390 architecture. ++# DASDs need to be formatted before use (even before creating a partition table on them). ++# By default ReaR will format the DASDs that are going to be used to recreate the system ++# (are referenced in disklayout.conf) before recreating the disk layout. ++# This can be suppressed by setting FORMAT_DASDS="false". It can be useful when one intends ++# to use already formatted DASDs as recovery target. ++FORMAT_DASDS="" ++## ++ + ## + # Resizing partitions in MIGRATION_MODE during "rear recover" + # +diff --git a/usr/share/rear/layout/prep-for-mount/Linux-s390/205_s390_enable_disk.sh b/usr/share/rear/layout/prep-for-mount/Linux-s390/205_s390_enable_disk.sh +new file mode 120000 +index 00000000..5f7a2ac0 +--- /dev/null ++++ b/usr/share/rear/layout/prep-for-mount/Linux-s390/205_s390_enable_disk.sh +@@ -0,0 +1 @@ ++../../prepare/Linux-s390/205_s390_enable_disk.sh +\ No newline at end of file +diff --git a/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh +index 84a7cd33..acc65adf 100644 +--- a/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh ++++ b/usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh +@@ -24,6 +24,7 @@ fi + ### Prepare a disk for partitioning/general usage. + create_disk() { + local component disk size label junk ++ local blocksize layout dasdtype dasdcyls junk2 + read component disk size label junk < <(grep "^disk $1 " "$LAYOUT_FILE") + + cat >> "$LAYOUT_CODE" <> "$LAYOUT_CODE" <> "$LAYOUT_CODE" <"$DASD_FORMAT_CODE" ++ ++# Show the current output of lsdasd, it can be useful for identifying disks ++# (in particular it shows the Linux device name <-> virtual device number mapping, ++# formatted / unformatted status and the number/size of blocks when formatted ) ++echo "# Current output of 'lsdasd':" >>"$DASD_FORMAT_CODE" ++lsdasd | sed -e 's/^/# /' >>"$DASD_FORMAT_CODE" ++ ++cat <>"$DASD_FORMAT_CODE" ++ ++LogPrint "Start DASD format restoration." ++ ++set -e ++set -x ++ ++EOF ++ ++while read component disk size label junk; do ++ if [ "$label" == dasd ]; then ++ # Ignore excluded components. ++ # Normally they are removed in 520_exclude_components.sh, ++ # but we run before it, so we must skip them here as well. ++ if IsInArray "$disk" "${EXCLUDE_RECREATE[@]}" ; then ++ Log "Excluding $disk from DASD reformatting." ++ continue ++ fi ++ # dasd has more fields - junk is not junk anymore ++ read blocksize layout dasdtype dasdcyls junk2 <<<$junk ++ dasd_format_code "$disk" "$size" "$blocksize" "$layout" "$dasdtype" "$dasdcyls" >> "$DASD_FORMAT_CODE" || \ ++ LogPrintError "Error producing DASD format code for $disk" ++ fi ++done < <(grep "^disk " "$LAYOUT_FILE") ++ ++cat <>"$DASD_FORMAT_CODE" ++ ++set +x ++set +e ++ ++LogPrint "DASD(s) formatted." ++ ++EOF +diff --git a/usr/share/rear/layout/prepare/Linux-s390/370_confirm_dasd_format_code.sh b/usr/share/rear/layout/prepare/Linux-s390/370_confirm_dasd_format_code.sh +new file mode 100644 +index 00000000..5ba4edd5 +--- /dev/null ++++ b/usr/share/rear/layout/prepare/Linux-s390/370_confirm_dasd_format_code.sh +@@ -0,0 +1,69 @@ ++# adapted from 100_confirm_layout_code.sh ++# ++# Let the user confirm the ++# DASD format code (dasdformat.sh) script. ++# ++ ++is_false "$FORMAT_DASDS" && return 0 ++ ++# Show the user confirmation dialog in any case but when not in migration mode ++# automatically proceed with less timeout USER_INPUT_INTERRUPT_TIMEOUT (by default 10 seconds) ++# to avoid longer delays (USER_INPUT_TIMEOUT is by default 300 seconds) in case of unattended recovery: ++# (taken from 120_confirm_wipedisk_disks.sh) ++local timeout="$USER_INPUT_TIMEOUT" ++is_true "$MIGRATION_MODE" || timeout="$USER_INPUT_INTERRUPT_TIMEOUT" ++ ++rear_workflow="rear $WORKFLOW" ++original_disk_space_usage_file="$VAR_DIR/layout/config/df.txt" ++rear_shell_history="$( echo -e "cd $VAR_DIR/layout/\nvi $DASD_FORMAT_CODE\nless $DASD_FORMAT_CODE" )" ++unset choices ++choices[0]="Confirm DASD format script and continue '$rear_workflow'" ++choices[1]="Edit DASD format script ($DASD_FORMAT_CODE)" ++choices[2]="View DASD format script ($DASD_FORMAT_CODE)" ++choices[3]="View original disk space usage ($original_disk_space_usage_file)" ++choices[4]="Confirm what is currently on the DASDs, skip formatting them and continue '$rear_workflow'" ++choices[5]="Use Relax-and-Recover shell and return back to here" ++choices[6]="Abort '$rear_workflow'" ++prompt="Confirm or edit the DASD format script" ++choice="" ++wilful_input="" ++# When USER_INPUT_DASD_FORMAT_CODE_CONFIRMATION has any 'true' value be liberal in what you accept and ++# assume choices[0] 'Confirm DASD format' was actually meant: ++is_true "$USER_INPUT_DASD_FORMAT_CODE_CONFIRMATION" && USER_INPUT_DASD_FORMAT_CODE_CONFIRMATION="${choices[0]}" ++while true ; do ++ choice="$( UserInput -I DASD_FORMAT_CODE_CONFIRMATION -t "$timeout" -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no" ++ case "$choice" in ++ (${choices[0]}) ++ # Confirm DASD format file and continue: ++ is_true "$wilful_input" && LogPrint "User confirmed DASD format script" || LogPrint "Continuing '$rear_workflow' by default" ++ break ++ ;; ++ (${choices[1]}) ++ # Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ vi $DASD_FORMAT_CODE 0<&6 1>&7 2>&8 ++ ;; ++ (${choices[2]}) ++ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ less $DASD_FORMAT_CODE 0<&6 1>&7 2>&8 ++ ;; ++ (${choices[3]}) ++ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ less $original_disk_space_usage_file 0<&6 1>&7 2>&8 ++ ;; ++ (${choices[4]}) ++ # Confirm what is on the disks and continue without formatting ++ FORMAT_DASDS="false" ++ ;; ++ (${choices[5]}) ++ # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ rear_shell "" "$rear_shell_history" ++ ;; ++ (${choices[6]}) ++ abort_dasd_format ++ Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}" ++ ;; ++ esac ++done ++ ++chmod +x $DASD_FORMAT_CODE ++ +diff --git a/usr/share/rear/layout/prepare/Linux-s390/400_run_dasd_format_code.sh b/usr/share/rear/layout/prepare/Linux-s390/400_run_dasd_format_code.sh +new file mode 100644 +index 00000000..16451af6 +--- /dev/null ++++ b/usr/share/rear/layout/prepare/Linux-s390/400_run_dasd_format_code.sh +@@ -0,0 +1,185 @@ ++# adapted from 200_run_layout_code.sh ++# ++# Run the DASD format code (dasdformat.sh) ++# again and again until it succeeds or the user aborts. ++# ++ ++# Skip DASD formatting when the user has explicitly specified to not format them ++# or when the user selected "Confirm what is currently on the DASDs, skip formatting them" ++# in 370_confirm_dasd_format_code.sh ++ ++is_false "$FORMAT_DASDS" && return 0 ++ ++function lsdasd_output () { ++ lsdasd 1>> >( tee -a "$RUNTIME_LOGFILE" 1>&7 ) ++} ++ ++rear_workflow="rear $WORKFLOW" ++original_disk_space_usage_file="$VAR_DIR/layout/config/df.txt" ++rear_shell_history="$( echo -e "cd $VAR_DIR/layout/\nvi $DASD_FORMAT_CODE\nless $RUNTIME_LOGFILE" )" ++wilful_input="" ++ ++unset choices ++choices[0]="Rerun DASD format script ($DASD_FORMAT_CODE)" ++choices[1]="View '$rear_workflow' log file ($RUNTIME_LOGFILE)" ++choices[2]="Edit DASD format script ($DASD_FORMAT_CODE)" ++choices[3]="Show what is currently on the disks ('lsdasd' device list)" ++choices[4]="View original disk space usage ($original_disk_space_usage_file)" ++choices[5]="Use Relax-and-Recover shell and return back to here" ++choices[6]="Confirm what is currently on the disks and continue '$rear_workflow'" ++choices[7]="Abort '$rear_workflow'" ++prompt="DASD format choices" ++ ++choice="" ++# When USER_INPUT_DASD_FORMAT_CODE_RUN has any 'true' value be liberal in what you accept and ++# assume choices[0] 'Rerun DASD format script' was actually meant ++# regardless that this likely lets 'rear recover' run an endless loop ++# of failed DASD format attempts but ReaR must obey what the user specified ++# (perhaps it is intended to let 'rear recover' loop here until an admin intervenes): ++is_true "$USER_INPUT_DASD_FORMAT_CODE_RUN" && USER_INPUT_DASD_FORMAT_CODE_RUN="${choices[0]}" ++ ++unset confirm_choices ++confirm_choices[0]="Confirm recreated DASD format and continue '$rear_workflow'" ++confirm_choices[1]="Go back one step to redo DASD format" ++confirm_choices[2]="Use Relax-and-Recover shell and return back to here" ++confirm_choices[3]="Abort '$rear_workflow'" ++confirm_prompt="Confirm the recreated DASD format or go back one step" ++confirm_choice="" ++# When USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION has any 'true' value be liberal in what you accept and ++# assume confirm_choices[0] 'Confirm recreated DASD format and continue' was actually meant: ++is_true "$USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION" && USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION="${confirm_choices[0]}" ++ ++# Run the DASD format code (dasdformat.sh) ++# again and again until it succeeds or the user aborts ++# or the user confirms to continue with what is currently on the disks ++# (the user may have setup manually what he needs via the Relax-and-Recover shell): ++while true ; do ++ prompt="The DASD format had failed" ++ # After switching to recreating with DASD format script ++ # change choices[0] from "Run ..." to "Rerun ...": ++ choices[0]="Rerun DASD format script ($DASD_FORMAT_CODE)" ++ # Run DASD_FORMAT_CODE in a sub-shell because it sets 'set -e' ++ # so that it exits the running shell in case of an error ++ # but that exit must not exit this running bash here: ++ ( source $DASD_FORMAT_CODE ) ++ # One must explicitly test whether or not $? is zero in a separated bash command ++ # because with bash 3.x and bash 4.x code like ++ # # ( set -e ; cat qqq ; echo "hello" ) && echo ok || echo failed ++ # cat: qqq: No such file or directory ++ # hello ++ # ok ++ # does not work as one may expect (cf. what "man bash" describes for 'set -e'). ++ # There is a subtle behavioural difference between bash 3.x and bash 4.x ++ # when a script that has 'set -e' set gets sourced: ++ # With bash 3.x the 'set -e' inside the sourced script is effective: ++ # # echo 'set -e ; cat qqq ; echo hello' >script.sh ++ # # ( source script.sh ) && echo ok || echo failed ++ # cat: qqq: No such file or directory ++ # failed ++ # With bash 4.x the 'set -e' inside the sourced script gets noneffective: ++ # # echo 'set -e ; cat qqq ; echo hello' >script.sh ++ # # ( source script.sh ) && echo ok || echo failed ++ # cat: qqq: No such file or directory ++ # hello ++ # ok ++ # With bash 3.x and bash 4.x testing $? in a separated bash command ++ # keeps the 'set -e' inside the sourced script effective: ++ # # echo 'set -e ; cat qqq ; echo hello' >script.sh ++ # # ( source script.sh ) ; (( $? == 0 )) && echo ok || echo failed ++ # cat: qqq: No such file or directory ++ # failed ++ # See also https://github.com/rear/rear/pull/1573#issuecomment-344303590 ++ if (( $? == 0 )) ; then ++ prompt="DASD format had been successful" ++ # When DASD_FORMAT_CODE succeeded and when not in migration mode ++ # break the outer while loop and continue the "rear recover" workflow ++ # which means continue with restoring the backup: ++ is_true "$MIGRATION_MODE" || break ++ # When DASD_FORMAT_CODE succeeded in migration mode ++ # let the user explicitly confirm the recreated (and usually migrated) format ++ # before continuing the "rear recover" workflow with restoring the backup. ++ # Show the recreated DASD format to the user on his terminal (and also in the log file): ++ LogPrint "Recreated DASD format:" ++ lsdasd_output ++ # Run an inner while loop with a user dialog so that the user can inspect the recreated DASD format ++ # and perhaps even manually fix the recreated DASD format if it is not what the user wants ++ # (e.g. by using the Relax-and-Recover shell and returning back to this user dialog): ++ while true ; do ++ confirm_choice="$( UserInput -I DASD_FORMAT_MIGRATED_CONFIRMATION -p "$confirm_prompt" -D "${confirm_choices[0]}" "${confirm_choices[@]}" )" && wilful_input="yes" || wilful_input="no" ++ case "$confirm_choice" in ++ (${confirm_choices[0]}) ++ # Confirm recreated DASD format and continue: ++ is_true "$wilful_input" && LogPrint "User confirmed recreated DASD format" || LogPrint "Continuing with recreated DASD format by default" ++ # Break the outer while loop and continue with restoring the backup: ++ break 2 ++ ;; ++ (${confirm_choices[1]}) ++ # Go back one step to redo DASD format: ++ # Only break the inner while loop (i.e. this user dialog loop) ++ # and continue with the next user dialog below: ++ break ++ ;; ++ (${confirm_choices[2]}) ++ # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ rear_shell "" "$rear_shell_history" ++ ;; ++ (${confirm_choices[3]}) ++ abort_dasd_format ++ Error "User did not confirm the recreated DASD format but aborted '$rear_workflow' in ${BASH_SOURCE[0]}" ++ ;; ++ esac ++ done ++ fi ++ # Run an inner while loop with a user dialog so that the user can fix things ++ # when DASD_FORMAT_CODE failed. ++ # Such a fix does not necessarily mean the user must change ++ # the dasdformat.sh script when DASD_FORMAT_CODE failed. ++ # The user might also fix things by only using the Relax-and-Recover shell and ++ # then confirm what is on the disks and continue with restoring the backup ++ # or abort this "rear recover" run to re-try from scratch. ++ while true ; do ++ choice="$( UserInput -I DASD_FORMAT_CODE_RUN -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no" ++ case "$choice" in ++ (${choices[0]}) ++ # Rerun or run (after switching to recreating with DASD format script) DASD format script: ++ is_true "$wilful_input" && LogPrint "User runs DASD format script" || LogPrint "Running DASD format script by default" ++ # Only break the inner while loop (i.e. the user dialog loop): ++ break ++ ;; ++ (${choices[1]}) ++ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ less $RUNTIME_LOGFILE 0<&6 1>&7 2>&8 ++ ;; ++ (${choices[2]}) ++ # Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ vi $DASD_FORMAT_CODE 0<&6 1>&7 2>&8 ++ ;; ++ (${choices[3]}) ++ LogPrint "This is the current list of DASDs:" ++ lsdasd_output ++ ;; ++ (${choices[4]}) ++ # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ less $original_disk_space_usage_file 0<&6 1>&7 2>&8 ++ ;; ++ (${choices[5]}) ++ # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user: ++ rear_shell "" "$rear_shell_history" ++ ;; ++ (${choices[6]}) ++ # Confirm what is on the disks and continue: ++ # Break the outer while loop and continue with restoring the backup: ++ break 2 ++ ;; ++ (${choices[7]}) ++ abort_dasd_format ++ Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}" ++ ;; ++ esac ++ done ++# End of the outer while loop: ++done ++ ++# Local functions must be 'unset' because bash does not support 'local function ...' ++# cf. https://unix.stackexchange.com/questions/104755/how-can-i-create-a-local-function-in-my-bashrc ++unset -f lsdasd_output +diff --git a/usr/share/rear/layout/prepare/default/010_prepare_files.sh b/usr/share/rear/layout/prepare/default/010_prepare_files.sh +index 7a980e63..4191be33 100644 +--- a/usr/share/rear/layout/prepare/default/010_prepare_files.sh ++++ b/usr/share/rear/layout/prepare/default/010_prepare_files.sh +@@ -7,6 +7,8 @@ LAYOUT_CODE="$VAR_DIR/layout/diskrestore.sh" + LAYOUT_XFS_OPT_DIR="$VAR_DIR/layout/xfs" + LAYOUT_XFS_OPT_DIR_RESTORE="$LAYOUT_XFS_OPT_DIR/restore" + ++DASD_FORMAT_CODE="$VAR_DIR/layout/dasdformat.sh" ++ + FS_UUID_MAP="$VAR_DIR/layout/fs_uuid_mapping" + LUN_WWID_MAP="$VAR_DIR/layout/lun_wwid_mapping" + +diff --git a/usr/share/rear/layout/prepare/default/250_compare_disks.sh b/usr/share/rear/layout/prepare/default/250_compare_disks.sh +index 260ab178..0931b183 100644 +--- a/usr/share/rear/layout/prepare/default/250_compare_disks.sh ++++ b/usr/share/rear/layout/prepare/default/250_compare_disks.sh +@@ -58,7 +58,9 @@ local more_than_one_same_orig_size='' + while read disk dev size junk ; do + old_disks_and_sizes+=( "$dev $size" ) + if IsInArray "$size" "${original_system_used_disk_sizes[@]}" ; then +- more_than_one_same_orig_size='true' ++ if ! has_mapping_hint "$dev" ; then ++ more_than_one_same_orig_size='true' ++ fi + else + original_system_used_disk_sizes+=( "$size" ) + fi +@@ -143,8 +145,8 @@ fi + # No further disk comparisons are needed when MIGRATION_MODE is already set true above: + if ! is_true "$MIGRATION_MODE" ; then + # Compare original disks and their possible target disk one by one: +- while read disk dev size junk ; do +- dev=$( get_sysfs_name $dev ) ++ while read disk devnode size junk ; do ++ dev=$( get_sysfs_name $devnode ) + Log "Comparing $dev" + if test -e "/sys/block/$dev" ; then + Log "Device /sys/block/$dev exists" +@@ -156,6 +158,14 @@ if ! is_true "$MIGRATION_MODE" ; then + else + LogPrint "Device $dev has expected (same) size $size bytes (will be used for '$WORKFLOW')" + fi ++ elif test "$( get_mapping_hint $devnode )" == "$devnode" ; then ++ Debug "Found identical mapping hint ${devnode} -> ${devnode}" ++ if is_write_protected "/sys/block/$dev"; then ++ LogPrint "Device $dev is designated as write-protected (needs manual configuration)" ++ MIGRATION_MODE='true' ++ else ++ LogPrint "Device $dev found according to mapping hints (will be used for '$WORKFLOW')" ++ fi + else + LogPrint "Device $dev has size $newsize bytes but $size bytes is expected (needs manual configuration)" + MIGRATION_MODE='true' +diff --git a/usr/share/rear/layout/prepare/default/300_map_disks.sh b/usr/share/rear/layout/prepare/default/300_map_disks.sh +index 3353daea..d7b45a84 100644 +--- a/usr/share/rear/layout/prepare/default/300_map_disks.sh ++++ b/usr/share/rear/layout/prepare/default/300_map_disks.sh +@@ -121,7 +121,14 @@ while read keyword orig_device orig_size junk ; do + # considered again during the subsequent "same size" tests: + excluded_target_device_names=() + # First, try to find if there is a current disk with same name and same size as the original: +- sysfs_device_name="$( get_sysfs_name "$orig_device" )" ++ # (possibly influenced by mapping hints if known) ++ if has_mapping_hint "$orig_device" ; then ++ candidate_target_device_name="$( get_mapping_hint "$orig_device" )" ++ Debug "Using mapping hint ${candidate_target_device_name} as candidate for $orig_device mapping" ++ else ++ candidate_target_device_name="$orig_device" ++ fi ++ sysfs_device_name="$( get_sysfs_name "$candidate_target_device_name" )" + current_device="/sys/block/$sysfs_device_name" + if test -e $current_device ; then + current_size=$( get_disk_size $sysfs_device_name ) +@@ -129,23 +136,28 @@ while read keyword orig_device orig_size junk ; do + # its matching actual block device (e.g. /dev/sda) must be determined: + preferred_target_device_name="$( get_device_name $current_device )" + # Use the current one if it is of same size as the old one: +- if test "$orig_size" -eq "$current_size" ; then ++ if has_mapping_hint "$orig_device" || test "$orig_size" -eq "$current_size" ; then + # Ensure the target device is really a block device on the replacement hardware. + # Here the target device has same name as the original device which was a block device on the original hardware + # but it might perhaps happen that this device name is not a block device on the replacement hardware: + if test -b "$preferred_target_device_name" ; then ++ if has_mapping_hint "$orig_device" ; then ++ mapping_reason="determined by mapping hint" ++ else ++ mapping_reason="same name and same size $current_size" ++ fi + # Do not map if the current one is already used as target in the mapping file: + if is_mapping_target "$preferred_target_device_name" ; then +- DebugPrint "Cannot use $preferred_target_device_name (same name and same size) for recreating $orig_device ($preferred_target_device_name already exists as target in $MAPPING_FILE)" ++ DebugPrint "Cannot use $preferred_target_device_name ($mapping_reason) for recreating $orig_device ($preferred_target_device_name already exists as target in $MAPPING_FILE)" + excluded_target_device_names+=( "$preferred_target_device_name" ) + else + # Ensure the determined target device is not write-protected: + if is_write_protected "$preferred_target_device_name" ; then +- DebugPrint "Cannot use $preferred_target_device_name (same name and same size) for recreating $orig_device ($preferred_target_device_name is write-protected)" ++ DebugPrint "Cannot use $preferred_target_device_name ($mapping_reason) for recreating $orig_device ($preferred_target_device_name is write-protected)" + excluded_target_device_names+=( "$preferred_target_device_name" ) + else + add_mapping "$orig_device" "$preferred_target_device_name" +- LogPrint "Using $preferred_target_device_name (same name and same size $current_size) for recreating $orig_device" ++ LogPrint "Using $preferred_target_device_name ($mapping_reason) for recreating $orig_device" + # Continue with next original device because the current one is now mapped: + continue + fi +diff --git a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh +index 52a4b142..a3e21c48 100644 +--- a/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh ++++ b/usr/share/rear/layout/save/GNU/Linux/200_partition_layout.sh +@@ -377,18 +377,27 @@ Log "Saving disks and their partitions" + + if [[ $blockd == dasd* && "$ARCH" == "Linux-s390" ]] ; then + devname=$(get_device_name $disk) ++ dasdnum=$( lsdasd | awk "\$3 == \"$blockd\" { print \$1}" ) ++ dasdstatus=$( lsdasd | awk "\$3 == \"$blockd\" { print \$2}" ) ++ # ECKD or FBA ++ dasdtype=$( lsdasd | awk "\$3 == \"$blockd\" { print \$5}" ) ++ if [ "$dasdtype" != ECKD ] && [ "$dasdtype" != FBA ]; then ++ LogPrint "Type $dasdtype of DASD $blockd unexpected: neither ECKD nor FBA" ++ fi + +- echo "# active dasd bus and channel" +- echo "# bus-id type" +- echo "dasd_channel $( lsdasd|grep $blockd|awk '{ print $1 " " $2 " " $3 " " $4}' )" +- +- echo "# dasdfmt - disk layout is either cdl for the compatible disk layout (default) or ldl" +- echo "# example usage: dasdfmt -b 4096 -d cdl -y /dev/dasda" +- layout=$(dasdview -x /dev/$blockd|grep "^format"|awk '{print $7}') +- blocksize=$( dasdview -i /dev/$blockd|grep blocksize|awk '{print $6}' ) +- echo "# dasdfmt $devname" +- echo "# dasdfmt -b -d -y " +- echo "dasdfmt -b $blocksize -d $layout -y $devname" ++ echo "# every DASD bus and channel" ++ echo "# Format: dasd_channel " ++ echo "dasd_channel $dasdnum $blockd" ++ ++ # We need to print the dasd_channel line even for ignored devices, ++ # otherwise we could have naming gaps and naming would change when ++ # recreating layout. ++ # E.g. if dasda is ignored, and dasdb is not, we would create only dasdb ++ # during recreation, but it would be named dasda. ++ if [ "$dasdstatus" != active ]; then ++ Log "Ignoring $blockd: it is not active (Status is $dasdstatus)" ++ continue ++ fi + fi + + #FIXME: exclude *rpmb (Replay Protected Memory Block) for nvme*, mmcblk* and uas +@@ -412,11 +421,38 @@ Log "Saving disks and their partitions" + # which can happen when /dev/sdX is an empty SD card slot without medium, + # see https://github.com/rear/rear/issues/2810 + test $disktype || LogPrintError "No partition label type for 'disk $devname' (may cause 'rear recover' failure)" +- +- echo "# Disk $devname" +- echo "# Format: disk " +- echo "disk $devname $devsize $disktype" +- ++ if [ "$disktype" != "dasd" ]; then ++ echo "# Disk $devname" ++ echo "# Format: disk " ++ echo "disk $devname $devsize $disktype" ++ elif [[ $blockd == dasd* && "$ARCH" == "Linux-s390" ]] ; then ++ layout=$(dasdview -x $devname |grep "^format"|awk '{print $7}') ++ case "$layout" in ++ (NOT) ++ # NOT -> dasdview has printed "NOT formatted" ++ LogPrintError "Ignoring $blockd: it is not formatted" ++ continue ++ ;; ++ (LDL|CDL) ++ ;; ++ (*) ++ BugError "Invalid 'disk $devname' entry (unknown DASD layout $layout)" ++ ;; ++ esac ++ test $disktype || Error "No partition label type for DASD entry 'disk $devname'" ++ blocksize=$( get_block_size "$blockd" ) ++ if ! test $blocksize ; then ++ # fallback - ugly method ++ blocksize=$( dasdview -i $devname |grep blocksize|awk '{print $6}' ) ++ test $blocksize || Error "Unknown block size of DASD $devname" ++ fi ++ dasdcyls=$( get_dasd_cylinders "$blockd" ) ++ echo "# Disk $devname" ++ echo "# Format: disk " ++ echo "disk $devname $devsize $disktype $blocksize $layout $dasdtype $dasdcyls" ++ else ++ Error "Invalid 'disk $devname' entry (DASD partition label on non-s390 arch $ARCH)" ++ fi + echo "# Partitions on $devname" + echo "# Format: part /dev/" + extract_partitions "$devname" +diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh +index cb33ac28..6dd43313 100644 +--- a/usr/share/rear/lib/layout-functions.sh ++++ b/usr/share/rear/lib/layout-functions.sh +@@ -87,6 +87,12 @@ abort_recreate() { + restore_original_file "$LAYOUT_FILE" + } + ++abort_dasd_format() { ++ Log "Error detected during DASD formatting." ++ Log "Restoring saved original $DASD_FORMAT_FILE" ++ restore_original_file "$DASD_FORMAT_FILE" ++} ++ + # Test and log if a component $1 (type $2) needs to be recreated. + create_component() { + local device="$1" +@@ -734,6 +740,46 @@ get_block_size() { + fi + } + ++# Get the number of cylinders of a DASD. ++# The number of cylinders has the advantage of being fixed - size depends on formatting ++# and number of cylinders is valid even for unformatted DASDs, size is not. ++get_dasd_cylinders() { ++ local disk_name="${1##*/}" # /some/path/dasda -> dasda ++ local dasd_cyls ++ ++ dasd_cyls=$(dasdview -i /dev/$disk_name | grep cylinders | cut -d ':' -f2 | awk '{print $4}') ++ ### Make sure we always return a number ++ echo $(( dasd_cyls )) ++} ++ ++# Sometimes we know what the new device for the original device should be in a more reliable way ++# than by looking at disk sizes. THis information is called "mapping hints". Let's pass them ++# to the mapping code using the DISK_MAPPING_HINTS array. Each element of the array has the form ++# "/dev/source /dev/target" (space-separated). ++ ++# Output the mapping hint for the original device. ++function get_mapping_hint () { ++ local device="$1" ++ local hint mapping_hint_source mapping_hint_target ++ ++ for hint in "${DISK_MAPPING_HINTS[@]}"; do ++ mapping_hint_source=${hint%% *} ++ mapping_hint_target=${hint##* } ++ if [ "${device}" == "${mapping_hint_source}" ] ; then ++ echo "$mapping_hint_target" ++ return 0 ++ fi ++ done ++ return 1 ++} ++ ++# Determine if there is a mapping hint for the original device. ++function has_mapping_hint () { ++ local device="$1" ++ ++ get_mapping_hint "$device" > /dev/null ++} ++ + # Get the UUID of a device. + # Device is something like /dev/sda1. + blkid_uuid_of_device() { diff --git a/SPECS/rear.spec b/SPECS/rear.spec new file mode 100644 index 0000000..a1bf2e1 --- /dev/null +++ b/SPECS/rear.spec @@ -0,0 +1,461 @@ +# this is purely a shell script, so no debug packages +%global debug_package %{nil} + +Name: rear +Version: 2.7 +Release: 12%{?dist} +Summary: Relax-and-Recover is a Linux disaster recovery and system migration tool +URL: https://relax-and-recover.org + +License: GPL-3.0-or-later + +#Source0: https://github.com/rear/rear/archive/%%{version}.tar.gz#/rear-%%{version}.tar.gz +Source0: rear-%{version}-clean.tar.gz +# Add cronjob and systemd timer as documentation +Source1: rear.cron +Source2: rear.service +Source3: rear.timer +# doc/rear-release-notes.txt is CC-BY-ND-3.0, which is not an allowed license +# for documentation. Therefore we use this Makefile to remove the file +# before shipping it. +# Download the upstream tarball and invoke "make rear-%%{version}-clean.tar.gz" +# while in the tarball's directory: +Source4: Makefile + +###################### +# upstream backports # +###################### +# pass -y to lvcreate instead of piping the output of yes +# https://github.com/rear/rear/commit/bca0e7a92af16cb7fb82ef04401cdb3286068081 +Patch101: rear-bz2104005.patch + +# fix initrd generation on s390x +# https://github.com/rear/rear/commit/6d1e5ab96213a0d79489c4296cd1f5a4be645597 +Patch102: rear-bz2130945.patch + +# do not use ':' as a field separator in pvdisplay output +# https://github.com/rear/rear/commit/29e739ae7c0651f8f77c60846bfbe2b6c91baa29 +Patch103: rear-bz2091163.patch + +# do not autoformat DASDs on s390x +# https://github.com/rear/rear/commit/015c1ffd9fa96b01882b068714d3bc3aae3b5168 +Patch104: s390-no-clobber-disks.patch + +# continue when extracting shrank files with tar +# https://github.com/rear/rear/commit/41c2d9b1fbcece4b0890ab92e9f5817621917ad3 +Patch105: rear-device-shrinking-bz2223895.patch + +# add secure boot support for OUTPUT=USB +# https://github.com/rear/rear/commit/46b29195bff7f93cf5bd4c2dd83d69e5676800cb +Patch106: rear-uefi-usb-secureboot-bz2196445.patch + +# remove the lvmdevices file at the end of recovery +# https://github.com/rear/rear/commit/5a8c5086bf3fc28236436ff3ef27196509f0375d +Patch107: rear-remove-lvmdevices-bz2145014.patch + +# save LVM pool metadata volume size in disk layout +# https://github.com/rear/rear/commit/f6af518baf3b5a4dc06bf8cfea262e627eee3e07 +Patch108: rear-save-lvm-poolmetadatasize-RHEL-6984.patch + +# skip useless xfs mount options when mounting during recovery +# https://github.com/rear/rear/commit/ed4c78d5fe493ea368989d0086a733653692f5cb +Patch109: rear-skip-useless-xfs-mount-options-RHEL-10478.patch + +# fix unusable recovery with newer systemd +# https://github.com/rear/rear/commit/060fef89b6968f0c8f254e6f612eff839b83c057 +Patch110: rear-fix-compatibility-with-newer-systemd-bz2254871.patch + +# make initrd accessible only by root +# https://github.com/rear/rear/commit/89b61793d80bc2cb2abe47a7d0549466fb087d16 +Patch111: rear-CVE-2024-23301.patch + +# copy the console= kernel arguments from the original system +# https://github.com/rear/rear/commit/88f11d19d748fff3f36357ef1471ee75fbfacabb +# https://github.com/rear/rear/commit/42e04f36f5f8eea0017915bb35e56ee285b394d7 +# https://github.com/rear/rear/commit/07da02143b5597b202e66c187e53103561018255 +Patch112: rear-copy-console-kernel-cmdline-from-host.patch + +# support saving and restoring hybrid BIOS/UEFI bootloader setup and clean +# up bootloader detection +# https://github.com/rear/rear/commit/096bfde5e234f5a803bae74f24e3821798022c7c +# https://github.com/rear/rear/commit/ca99d855579cfcab37f985e2547a3187e0f0aeeb +Patch113: rear-restore-hybrid-bootloader-RHEL-16864.patch + +# resolve libs for executable links in COPY_AS_IS +# https://github.com/rear/rear/commit/9f859c13f5ba285cd1d5983c9b595975c21888d3 +Patch114: rear-resolve-libraries-for-symlinks-in-COPY_AS_IS-RHEL-15108.patch + +# skip invalid disk drives (zero sized, no media) when saving layout +# https://github.com/rear/rear/commit/c08658d5a0260c3242bb817e77b9c6dadecd14f6 +Patch115: rear-skip-invalid-drives-RHEL-22863.patch + +# fix useless warning that libsystemd-core requires additional libraries +# and ReaR recovery system needs additional libraries +# https://github.com/rear/rear/commit/eb574592a21c7ca986393c4563fe5484b9f01454 +Patch116: rear-fix-libsystemd-ldd-warning.patch + +# fix IPv6 addresses in nfs:// and sshfs:// BACKUP/OUTPUT_URL +# https://github.com/rear/rear/commit/8a10135bf958c03b4b5077fc7ae7761ad2a71eec +Patch117: rear-fix-ipv6.patch + +# ALREADY INCLUDED IN REAR 2.7! +# remove obsolete FAT16 options to avoid kernel warning +# https://github.com/rear/rear/commit/9a6b9a109aa77afc6c96cf05bbd7988cf0310d61 +# Patch118: rear-no-fat-16.patch + +# fix booting on UEFI with multiple CDROM devices +# https://github.com/rear/rear/commit/283efdaea10ff62dc94e968f74e1136b8384a954 +Patch119: rear-uefi-booting-with-multiple-cdrom-devices.patch + +# skip btrfs subvolumes when detecting ESP partitions +# https://github.com/rear/rear/commit/c8409e1f2972e9cd87d9390ca0b52b908d1a872a +Patch120: rear-skip-btrfs-subvolumes-when-detecting-ESP-partitions.patch + +# fix backup of btrfs subvolumes +# https://github.com/rear/rear/commit/ec9080664303165799a215cef062826b65f6a6f8 +# https://github.com/rear/rear/commit/2da70f54936e5c558c9f607b1526b9b17f6501b1 +Patch121: rear-fix-backup-of-btrfs-subvolumes.patch + +###################### +# downstream patches # +###################### +# suggest to install grub-efi-x64-modules on x86_64 UEFI Fedora/RHEL machines +Patch201: rear-bz1492177-warning.patch + +# avoid vgcfgrestore on unsupported volume types +# https://github.com/pcahyna/rear/commit/5d5d1db3ca621eb80b9481924d1fc470571cfc09 +Patch202: rear-bz1747468.patch + +# skip deliberately broken symlinks in initrd on Fedora/RHEL +Patch203: rear-bz2119501.patch + +# additional fixes for NBU support +Patch204: rear-bz2120736.patch +Patch205: rear-bz2188593-nbu-systemd.patch +Patch206: rear-nbu-RHEL-17390-RHEL-17393.patch + +# rear contains only bash scripts plus documentation so that on first glance it could be "BuildArch: noarch" +# but actually it is not "noarch" because it only works on those architectures that are explicitly supported. +# Of course the rear bash scripts can be installed on any architecture just as any binaries can be installed on any architecture. +# But the meaning of architecture dependent packages should be on what architectures they will work. +# Therefore only those architectures that are actually supported are explicitly listed. +# This avoids that rear can be "just installed" on architectures that are actually not supported (e.g. ARM): +ExclusiveArch: %ix86 x86_64 ppc ppc64 ppc64le ia64 s390x +# Furthermore for some architectures it requires architecture dependent packages (like syslinux for x86 and x86_64) +# so that rear must be architecture dependent because ifarch conditions never match in case of "BuildArch: noarch" +# see the GitHub issue https://github.com/rear/rear/issues/629 +%ifarch %ix86 x86_64 +Requires: syslinux +# We need mkfs.vfat for recreating EFI System Partition +Recommends: dosfstools +%endif +%ifarch ppc ppc64 ppc64le +# Called by grub2-install (except on PowerNV) +Requires: /usr/sbin/ofpathname +# Needed to make PowerVM LPARs bootable +Requires: /usr/sbin/bootlist +%endif +%ifarch s390x +# Contain many utilities for working with DASDs +Requires: s390utils-base +Requires: s390utils-core +%endif + +# Required for HTML user guide +BuildRequires: asciidoctor +BuildRequires: git +BuildRequires: make + +### Mandatory dependencies: +Requires: attr +Requires: bc +Requires: binutils +Requires: dhcpcd +Requires: ethtool +Requires: file +Requires: gawk +Requires: gzip +Requires: iproute +Requires: iputils +Requires: openssl +Requires: parted +Requires: tar +# No ISO image support on s390x (may change when we add support for LPARs) +%ifnarch s390x +Requires: xorriso +%endif +%if 0%{?rhel} +Requires: util-linux +%endif + +%description +Relax-and-Recover is the leading Open Source disaster recovery and system +migration solution. It comprises of a modular +frame-work and ready-to-go workflows for many common situations to produce +a bootable image and restore from backup using this image. As a benefit, +it allows to restore to different hardware and can therefore be used as +a migration tool as well. + +Currently Relax-and-Recover supports various boot media (incl. ISO, PXE, +OBDR tape, USB or eSATA storage), a variety of network protocols (incl. +sftp, ftp, http, nfs, cifs) as well as a multitude of backup strategies +(incl. IBM TSM, MircroFocus Data Protector, Symantec NetBackup, EMC NetWorker, +Bacula, Bareos, BORG, Duplicity, rsync). + +Relax-and-Recover was designed to be easy to set up, requires no maintenance +and is there to assist when disaster strikes. Its setup-and-forget nature +removes any excuse for not having a disaster recovery solution implemented. + +Professional services and support are available. + +#-- PREP, BUILD & INSTALL -----------------------------------------------------# +%prep +%autosetup -p1 -S git + +### Add a specific os.conf so we do not depend on LSB dependencies +%{?fedora:echo -e "OS_VENDOR=Fedora\nOS_VERSION=%{?fedora}" >etc/rear/os.conf} +%{?rhel:echo -e "OS_VENDOR=RedHatEnterpriseServer\nOS_VERSION=%{?rhel}" >etc/rear/os.conf} + +# Change /lib to /usr/lib for COPY_AS_IS +sed -E -e "s:([\"' ])/lib:\1/usr/lib:g" \ + -i usr/share/rear/prep/GNU/Linux/*include*.sh + +# Same for Linux.conf +sed -e 's:/lib/:/usr/lib/:g' \ + -e 's:/lib\*/:/usr/lib\*/:g' \ + -e 's:/usr/usr/lib:/usr/lib:g' \ + -i 'usr/share/rear/conf/GNU/Linux.conf' + +%build +# build HTML user guide +# asciidoc writes a timestamp to files it produces, based on the last +# modified date of the source file, but is sensitive to the timezone. +# This makes the results differ according to the timezone of the build machine +# and spurious changes will be seen. +# Set the timezone to UTC as a workaround. +# https://wiki.debian.org/ReproducibleBuilds/TimestampsInDocumentationGeneratedByAsciidoc +TZ=UTC make doc + +%install +%{make_install} +install -p -d %{buildroot}%{_docdir}/%{name}/ +install -m 0644 %{SOURCE1} %{buildroot}%{_docdir}/%{name}/ +install -m 0644 %{SOURCE2} %{buildroot}%{_docdir}/%{name}/ +install -m 0644 %{SOURCE3} %{buildroot}%{_docdir}/%{name}/ + +#-- FILES ---------------------------------------------------------------------# +%files +%license COPYING +%doc MAINTAINERS README.adoc doc/user-guide/*.html +# the only upstream *.txt file has an unacceptable license (CC-BY-ND-3.0) +#%%doc doc/*.txt +%dir %{_sysconfdir}/rear/ +%config(noreplace) %{_sysconfdir}/rear/local.conf +%{_sysconfdir}/rear/os.conf +%{_datadir}/rear/ +%{_docdir}/%{name}/rear.* +%{_mandir}/man8/rear.8* +%{_sbindir}/rear +%{_sharedstatedir}/rear/ + +#-- CHANGELOG -----------------------------------------------------------------# +%changelog +* Thu Aug 8 2024 Pavel Cahyna - 2.7-12 +- Remove doc/rear-release-notes.txt, it is CC-BY-ND-3.0, which is not an allowed + license for documentation, and use a cleaned tarball (with the file removed) + for build + +* Wed Aug 7 2024 Pavel Cahyna - 2.7-11 +- Generate /etc/rear/os.conf during build again, it is better than generating it + in %%post, but do not mark it as config file to allow it to be updated during + package upgrade and avoid containing an old OS version information + +* Mon Aug 05 2024 Lukáš Zaoral - 2.7-10 +- skip btrfs subvolumes when detecting ESP partitions +- fix booting on UEFI systems with multiple CDROM devices +- fix copying of console kernel cmdline parameters +- Use git to apply patches in %%prep +- Sync with patches in CentOS Stream 9 (kudos to @pcahyna!): + - Backport PR 3250 to fix useless warning that libsystemd-core requires + additional libraries and ReaR recovery system needs additional libraries + - Backport PR 3242 to fix IPv6 address in nfs:// and sshfs:// + BACKUP/OUTPUT_URL +- fix backup of btrfs subvolumes + +* Mon Jun 24 2024 Troy Dawson - 2.7-9 +- Bump release for June 2024 mass rebuild + +* Fri Feb 09 2024 Lukáš Zaoral - 2.7-8 +- Sync with patches in CentOS Stream 9 (kudos to @pcahyna!) chronologically + from the latest: + - Resolve libs for executable links in COPY_AS_IS, PR 3073 + - Skip invalid disk drives when saving layout PR 3047 + - Do not delete NetBackup logs in case of errors and save + /usr/openv/netbackup/logs to the restored system after a successful recovery + - Add /usr/openv/var to COPY_AS_IS_NBU, fixes an issue seen + with NetBackup 10.2.0.1 + - Support saving and restoring hybrid BIOS/UEFI bootloader, PRs 3145 3136 + +* Thu Feb 08 2024 Lukáš Zaoral - 2.7-7 +- do not generate /etc/rear/os.conf during build + +* Wed Feb 07 2024 Lukáš Zaoral - 2.7-6 +- copy the console= kernel arguments from the original system + +* Tue Feb 06 2024 Lukáš Zaoral - 2.7-5 +- replace dhcp-client with dhcpcd (rhbz#2247060) + +* Tue Feb 06 2024 Lukáš Zaoral - 2.7-4 +- make initrd accessible only by root (CVE-2024-23301) + +* Tue Feb 06 2024 Lukáš Zaoral - 2.7-3 +- fix unusable recovery with newer systemd (rbhz#2254871) + +* Mon Feb 05 2024 Lukáš Zaoral - 2.7-2 +- migrate to SPDX license format +- properly use %%license and %%doc macros +- use https in URLs + +* Fri Feb 02 2024 Lukáš Zaoral - 2.7-1 +- rebase to version 2.7 (rhbz#2215778) +- drop obsolete patches +- rebase remaining patches + +* Fri Feb 2 2024 Lukáš Zaoral - 2.6-14 +- Sync with patches in CentOS Stream 9 (kudos to @pcahyna!) chronologically + from the latest: + - Backport PR 3061 to save LVM pool metadata volume size in disk layout + and restore it + - Backport PR 3058 to skip useless xfs mount options when mounting + during recovery, prevents mount errors like "logbuf size must be greater + than or equal to log stripe size" + - Add patch to force removal of lvmdevices, prevents LVM problems after + restoring to different disks/cloning. Upstream PR 3043 + - Add patch to start rsyslog and include NBU systemd units + - Apply PR 3027 to ensure correct creation of the rescue environment + when a file is shrinking while being read + - Backport PR 2774 to increase USB_UEFI_PART_SIZE to 1024 MiB + - Apply upstream patch for temp dir usage with LUKS to ensure + that during recovery an encrypted disk can be unlocked using a keyfile + - Backport upstream PR 3031: Secure Boot support for OUTPUT=USB + - Correct a mistake done when backporting PR 2691 + - Backport PR2943 to fix s390x dasd formatting + - Require s390utils-{core,base} on s390x + - Apply PR2903 to protect against colons in pvdisplay output + - Apply PR2873 to fix initrd regeneration on s390x + - Apply PR2431 to migrate XFS configuration files + - Exclude /etc/lvm/devices from the rescue system to work around a segfault + in lvm pvcreate + - Avoid stderr message about irrelevant broken links + - Changes for NetBackup (NBU) 9.x support + - Backport PR2831 - rsync URL refactoring + fixes rsync OUTPUT_URL when different from BACKUP_URL + - Apply PR2795 to detect changes in system files between backup + and rescue image + - Apply PR2808 to exclude dev/watchdog* from recovery system + - Backport upstream PRs 2827 and 2839 to pass -y to lvcreate instead of one "y" + on stdin + - Apply PR2811 to add the PRE/POST_RECOVERY_COMMANDS directives + - Recommend dosfstools on x86_64, needed for EFI System Partition + - Backport PR2825 to replace defunct mkinitrd with dracut + - Apply PR2580 to load the nvram module in the rescue environment in order + to be able to set the boot order on ppc64le LPARs + - Backport PR2822 to include the true vi executable in rescue ramdisk + - Apply PR2675 to fix leftover temp dir bug (introduced in backported PR2625) + - Apply PR2603 to ignore unused PV devices + - Apply upstream PR2750 to avoid exclusion of wanted multipath devices + - Remove unneeded xorriso dep on s390x (no ISO image support there) + - Apply upstream PR2736 to add the EXCLUDE_{IP_ADDRESSES,NETWORK_INTERFACES} + options + - Add patch for better handling of thin pools and other LV types not supported + by vgcfgrestore + - Sync spec changes and downstream patches from RHEL 8 rear-2.6-2 + - Fix multipath performance regression in 2.6, introduced by upstream PR #2299. + Resolves: rhbz1993296 + - On POWER add bootlist & ofpathname to the list of required programs + conditionally (bootlist only if running under PowerVM, ofpathname + always except on PowerNV) - upstream PR2665, add them to package + dependencies + Resolves: rhbz1983013 + - Backport PR2608: + Fix setting boot path in case of UEFI partition (ESP) on MD RAID + Resolves: rhbz1945869 + - Backport PR2625 + Prevents accidental backup removal in case of errors + Resolves: rhbz1958247 + - Fix rsync error and option handling + Resolves: rhbz1930662 + - Put TMPDIR on /var/tmp by default, otherwise it may lack space + RHBZ #1988420, upstream PR2664 + - Sync spec changes and downstream patches from RHEL 8 + - Require xorriso instead of genisoimage + - Add S/390 support and forgotten dependency on the file utility + - Backport upstream code related to LUKS2 support + - Modify the cron command to avoid an e-mail with error message after + ReaR is installed but not properly configured when the cron command + is triggered for the first time + - Changes for NetBackup (NBU) support, upstream PR2544 + - Add dependency on dhcp-client, RHBZ #1926451 + +* Fri Jan 26 2024 Fedora Release Engineering - 2.6-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Mon Jan 22 2024 Fedora Release Engineering - 2.6-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jul 21 2023 Fedora Release Engineering - 2.6-11 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Fri Jun 23 2023 Yaakov Selkowitz - 2.6-10 +- Switch to xorriso for iso image creation + +* Fri Jan 20 2023 Fedora Release Engineering - 2.6-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Sat Jul 23 2022 Fedora Release Engineering - 2.6-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Fri Jan 21 2022 Fedora Release Engineering - 2.6-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Fri Jul 23 2021 Fedora Release Engineering - 2.6-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Fri Feb 26 2021 Christopher Engelhard - 2.6-5 +- Change /lib to /usr/lib in scripts to fix RHBZ #1931112 + +* Wed Jan 27 2021 Fedora Release Engineering - 2.6-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Sep 23 2020 Christopher Engelhard - 2.6-3 +- Stop auto-creating a cronjob, but ship example cronjob/ + systemd timer units in docdir instead (upstream issue #1829) +- Build & ship HTML user guide +- Remove %pre scriptlet, as it was introduced only to fix a + specific upgrade issue with v1.15 in 2014 + +* Tue Sep 22 2020 Christopher Engelhard - 2.6-2 +- Backport upstream PR#2469 to fix RHBZ #1831311 + +* Tue Sep 22 2020 Christopher Engelhard - 2.6-1 +- Update to 2.6 +- Streamline & clean up spec file + +* Wed Jul 29 2020 Fedora Release Engineering - 2.4-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Thu Jan 30 2020 Fedora Release Engineering - 2.4-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Jul 26 2019 Fedora Release Engineering - 2.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sat Feb 02 2019 Fedora Release Engineering - 2.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Sat Jul 14 2018 Fedora Release Engineering - 2.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu Jul 30 2015 Johannes Meixner +- For a changelog see the rear-release-notes.txt file. +