File rear23a-update.patch of Package rear23a.32111
--- usr/share/rear/build/GNU/Linux/400_copy_modules.sh 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/build/GNU/Linux/400_copy_modules.sh 2021-01-27 10:05:09.332386569 +0100
@@ -11,136 +11,165 @@
# Test the first MODULES array element because other scripts
# in particular rescue/GNU/Linux/240_kernel_modules.sh
# already appended other modules to the MODULES array:
if test "no_modules" = "$MODULES" ; then
LogPrint "Omit copying kernel modules (MODULES contains 'no_modules')"
return
fi
# As general condition the /lib/modules/$KERNEL_VERSION directory must exist:
test "$KERNEL_VERSION" || KERNEL_VERSION="$( uname -r )"
if ! test -d "/lib/modules/$KERNEL_VERSION" ; then
Error "Cannot copy kernel modules because /lib/modules/$KERNEL_VERSION does not exist"
fi
# Local functions that are 'unset' at the end of this script:
function modinfo_filename () {
local module_name=$1
local module_filename=""
- local alias_module_name=$(modprobe -n -R $module_name 2>/dev/null)
# If the installed modprobe command supports resolving module aliases (-R), use that capability.
+ # 'modprobe -n -R' prints all module names matching an alias so we have its output in an array
+ # and use only its first element to consider only the first printed module name:
+ local alias_module_name=( $( modprobe -n -R $module_name 2>/dev/null ) )
test $alias_module_name && module_name=$alias_module_name
# Older modinfo (e.g. the one in SLES10) does not support '-k'
# but that old modinfo returns a zero exit code when called as 'modinfo -k ...'
# and shows a 'modinfo: invalid option -- k ...' message on stderr and nothing on stdout
- # so that we need to check if we got a non-empty module filename:
- module_filename=$( modinfo -k $KERNEL_VERSION -F filename $module_name )
+ # so that we need to check if we got a non-empty module filename.
+ # Older modinfo (in particular modinfo before kmod-27 since SLES15-SP3)
+ # outputs nothing on stdout for builtin kernel "modules" and exits with exit code 1 like
+ # # modinfo -F filename unix
+ # modinfo: ERROR: Module unix not found.
+ # Newer modinfo (in particular modinfo in kmod-27 since SLES15-SP3)
+ # outputs on stdout for builtin kernel "modules" and exits with zero exit code like
+ # # modinfo -F filename unix
+ # name: unix
+ # (builtin)
+ # For real kernel modules the modinfo stdout is one word that is the kernel module filename like
+ # # modinfo -F filename sg
+ # /lib/modules/5.3.18-43-default/kernel/drivers/scsi/sg.ko.xz
+ module_filename="$( modinfo -k $KERNEL_VERSION -F filename $module_name )"
# If 'modinfo -k ...' stdout is empty we retry without '-k' regardless why stdout is empty
# but then we do not discard stderr so that error messages appear in the log file.
# In this case we must additionally ensure that KERNEL_VERSION matches 'uname -r'
# otherwise a module file for a wrong kernel version would be found:
- if ! test $module_filename ; then
+ if ! test "$module_filename" ; then
test "$KERNEL_VERSION" = "$( uname -r )" || Error "modinfo_filename failed because KERNEL_VERSION does not match 'uname -r'"
- module_filename=$( modinfo -F filename $module_name )
+ module_filename="$( modinfo -F filename $module_name )"
fi
- test $module_filename && echo $module_filename
+ # grep for '(builtin)' in the modinfo stdout to get the builtin kernel "module" case and otherwise
+ # 'readlink -e something' shows the filename when something is one or more files and exits with zero exit code
+ # 'readlink -e something' shows the symlink target when something is a symlink and exits with zero exit code
+ # 'readlink -e something' shows nothing when something is no file or a broken symlink and exits with exit code 1
+ # 'readlink -e something' shows nothing on stdout but an error on stderr when something is empty and exits with exit code 1
+ grep -q '(builtin)' <<<"$module_filename" && echo '' || readlink -e $module_filename
}
# Artificial 'for' clause that is run only once
# to be able to 'continue' with the code after it
# when the kernel modules have been copied into the rescue/recovery system
# (the 'for' loop is run only once so that 'continue' is the same as 'break')
# which avoids dowdy looking code with deeply nested 'if...else' conditions:
for dummy in "once" ; do
# The special user setting MODULES=( 'all_modules' ) enforces that
# all files in the /lib/modules/$KERNEL_VERSION directory
# get included in the rescue/recovery system.
# Test all MODULES array members to make the 'all_modules' functionality work for
# MODULES array contents like MODULES=( 'moduleX' 'all_modules' 'moduleY' ):
if IsInArray "all_modules" "${MODULES[@]}" ; then
LogPrint "Copying all kernel modules in /lib/modules/$KERNEL_VERSION (MODULES contains 'all_modules')"
# The '--parents' is needed to get the '/lib/modules/' directory in the copy:
if ! cp $verbose -t $ROOTFS_DIR -a --parents /lib/modules/$KERNEL_VERSION 1>&2 ; then
Error "Failed to copy all kernel modules in /lib/modules/$KERNEL_VERSION"
fi
# After successful copying do the the code after the artificial 'for' clause:
continue
fi
# The special user setting MODULES=( 'loaded_modules' ) enforces that
# only those kernel modules that are currently loaded
# get included in the rescue/recovery system.
# Test all MODULES array members to make the 'loaded_modules' functionality work for
# MODULES array contents like MODULES=( 'moduleX' 'loaded_modules' 'moduleY' ):
if IsInArray "loaded_modules" "${MODULES[@]}" ; then
- LogPrint "Copying only currently loaded kernel modules (MODULES contains 'loaded_modules')"
+ LogPrint "Copying only currently loaded kernel modules (MODULES contains 'loaded_modules') and those in MODULES_LOAD"
# The rescue/recovery system cannot work when its kernel modules
# do not match the kernel that gets included in the rescue/recovery system
# so that "rear mkrescue/mkbackup" errors out to be on the safe side
# cf. https://github.com/rear/rear/wiki/Coding-Style
# and https://github.com/rear/rear/wiki/Developers-Guide
currently_running_kernel_version="$( uname -r )"
if ! test "$KERNEL_VERSION" = "$currently_running_kernel_version" ; then
Error "KERNEL_VERSION='$KERNEL_VERSION' does not match currently running kernel version ('uname -r' shows '$currently_running_kernel_version')"
fi
- loaded_modules="$( lsmod | tail -n +2 | cut -d ' ' -f 1 )"
- # It can happen that a module is loaded but 'modinfo -F filename' cannot show its filename
- # when it is loaded under a module alias name but the above modinfo_filename function
- # could not resolve aliases (when the modprobe command does not support -R):
- loaded_modules_files="$( for loaded_module in $loaded_modules ; do modinfo_filename $loaded_module || Error "$loaded_module loaded but no module file?" ; done )"
- # $loaded_modules_files cannot be empty because modinfo_filename fails when it cannot show a module filename:
+ # Kernel modules that should be loaded during recovery system startup must be always copied into the recovery system:
+ loaded_modules="${MODULES_LOAD[@]}"
+ # The leading blank before $(...) is mandatory (otherwise the last in MODULES_LOAD is concatenated with the first of lsmod):
+ loaded_modules+=" $( lsmod | tail -n +2 | cut -d ' ' -f 1 )"
+ # It can happen that a module is loaded or should be loaded but 'modinfo -F filename' cannot show its filename
+ # when it is loaded or should be loaded under a module alias name but the above modinfo_filename function
+ # could not resolve aliases (when the modprobe command does not support -R).
+ # The 'sort -u' removes duplicates only to avoid useless stderr warnings from the subsequent 'cp'
+ # like "cp: warning: source file '/lib/modules/.../foo.ko' specified more than once"
+ # regardless that nothing goes wrong when 'cp' gets duplicate source files
+ # cf. http://blog.schlomo.schapiro.org/2015/04/warning-is-waste-of-my-time.html
+ loaded_modules_files="$( for loaded_module in $loaded_modules ; do modinfo_filename $loaded_module || Error "$loaded_module loaded or to be loaded but no module file?" ; done | sort -u )"
+ # $loaded_modules_files could be empty as extreme case because modinfo_filename outputs nothing in the builtin kernel "module" case:
+ test "$loaded_modules_files" || continue
if ! cp $verbose -t $ROOTFS_DIR -L --preserve=all --parents $loaded_modules_files 1>&2 ; then
Error "Failed to copy '$loaded_modules_files'"
fi
# After successful copying do the the code after the artificial 'for' clause:
continue
fi
# Finally the default case:
LogPrint "Copying kernel modules"
- for module in "${MODULES[@]}" ; do
+ # Kernel modules that should be loaded during recovery system startup must be always copied into the recovery system:
+ for module in "${MODULES_LOAD[@]}" "${MODULES[@]}" ; do
# Strip trailing ".o" if there:
module=${module#.o}
# Strip trailing ".ko" if there:
module=${module#.ko}
# Continue with the next module if the current one does not exist:
modinfo $module 1>/dev/null || continue
# Resolve module dependencies:
# Get the module file plus the module files of other needed modules.
# This is currently only a "best effort" attempt because
# in general 'modprobe --show-depends' is insufficient to get all needed modules
# see https://github.com/rear/rear/issues/1355
# The --ignore-install is helpful because it converts currently unsupported '^install' output lines
# into supported '^insmod' output lines for the particular module but that is also insufficient
# see also https://github.com/rear/rear/issues/1355
# The 'sort -u' removes duplicates only to avoid useless stderr warnings from the subsequent 'cp'
# like "cp: warning: source file '/lib/modules/.../foo.ko' specified more than once"
# regardless that nothing goes wrong when 'cp' gets duplicate source files
# cf. http://blog.schlomo.schapiro.org/2015/04/warning-is-waste-of-my-time.html
module_files=$( modprobe --ignore-install --set-version $KERNEL_VERSION --show-depends $module | awk '/^insmod / { print $2 }' | sort -u )
if ! test "$module_files" ; then
# Fallback is the plain module file without other needed modules (cf. the MODULES=( 'loaded_modules' ) case above):
# It can happen that 'modinfo -F filename' cannot show the module filename
# when it is specified under a module alias name but the above modinfo_filename function
# could not resolve aliases (when the modprobe command does not support -R):
module_files="$( modinfo_filename $module || Error "$module exists but no module file?" )"
fi
- # $module_files cannot be empty because modinfo_filename fails when it cannot show a module filename:
+ # $module_files can be empty because modinfo_filename outputs nothing in the builtin kernel "module" case:
+ test "$module_files" || continue
if ! cp $verbose -t $ROOTFS_DIR -L --preserve=all --parents $module_files 1>&2 ; then
Error "Failed to copy '$module_files'"
fi
done
# End of artificial 'for' clause:
done
# Remove those modules that are specified in the EXCLUDE_MODULES array:
for exclude_module in "${EXCLUDE_MODULES[@]}" ; do
# Continue with the next module if the current one does not exist:
modinfo $exclude_module 1>/dev/null || continue
# In this case it is ignored when a module exists but 'modinfo -F filename' cannot show its filename
# because then it is assumed that also no module file had been copied above:
exclude_module_file="$( modinfo_filename $exclude_module )"
test -e "$ROOTFS_DIR$exclude_module_file" && rm $verbose $ROOTFS_DIR$exclude_module_file 1>&2
done
--- usr/share/rear/finalize/Linux-ppc64le/620_install_grub2.sh 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/finalize/Linux-ppc64le/620_install_grub2.sh 2021-01-27 11:23:37.052386569 +0100
@@ -89,100 +89,130 @@
# cf. https://github.com/rear/rear/issues/1828#issuecomment-398717889
# and do not umount them when leaving this script because
# it is better when also after "rear recover" things still
# work in the "chroot TARGET_FS_ROOT" environment so that
# the user could more easily adapt things after "rear recover":
for mount_device in proc sys dev ; do
umount $TARGET_FS_ROOT/$mount_device && sleep 1
mount --bind /$mount_device $TARGET_FS_ROOT/$mount_device
done
# Generate GRUB configuration file anew to be on the safe side (this could be even mandatory in MIGRATION_MODE):
if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-mkconfig -o /boot/$grub_name/grub.cfg" ; then
LogPrintError "Failed to generate boot/$grub_name/grub.cfg in $TARGET_FS_ROOT - trying to install GRUB2 nevertheless"
fi
# Do not update nvram when system is running in PowerNV mode (BareMetal).
# grub2-install will fail if not run with the --no-nvram option on a PowerNV system,
# see https://github.com/rear/rear/pull/1742
-grub2_install_option=""
+grub2_no_nvram_option=""
if [[ $(awk '/platform/ {print $NF}' < /proc/cpuinfo) == PowerNV ]] ; then
- grub2_install_option="--no-nvram"
+ grub2_no_nvram_option="--no-nvram"
+fi
+# Also do not update nvram when no character device node /dev/nvram exists.
+# On POWER architecture the nvram kernel driver could be also built as a kernel module
+# that gets loaded via etc/scripts/system-setup.d/41-load-special-modules.sh
+# but whether or not the nvram kernel driver will then create /dev/nvram
+# depends on whether or not the hardware platform supports nvram.
+# I <jsmeix@suse.de> asked on a SUSE internal mailing list
+# and got the following reply (excerpts):
+# ----------------------------------------------------------------
+# > I would like to know when /dev/nvram exists and when not.
+# > I assume /dev/nvram gets created as other device nodes
+# > by the kernel (probably together with udev).
+# > I would like to know under what conditions /dev/nvram
+# > gets created and when it is not created.
+# > It seems on PPC /dev/nvram usually exist but sometimes not.
+# In case of powerpc, it gets created by nvram driver
+# (nvram_module_init) whenever the powerpc platform driver
+# has ppc_md.nvram_size greater than zero in it's machine
+# description structure.
+# How exactly ppc_md.nvram_size gets gets populated by platform
+# code depends on the platform, e.g. on most modern systems
+# it gets populated from 'nvram' device tree node
+# (and only if such node has #bytes > 0).
+# ----------------------------------------------------------------
+# So /dev/nvram may not exist regardless that the nvram kernel driver is there
+# and then grub2-install must be called with the '--no-nvram' option
+# because otherwise installing the bootloader fails
+# cf. https://github.com/rear/rear/issues/2554
+if ! test -c /dev/nvram ; then
+ grub2_no_nvram_option="--no-nvram"
fi
# When GRUB2_INSTALL_DEVICES is specified by the user
# install GRUB2 only there and nowhere else:
if test "$GRUB2_INSTALL_DEVICES" ; then
grub2_install_failed="no"
for grub2_install_device in $GRUB2_INSTALL_DEVICES ; do
# In MIGRATION_MODE disk mappings (in var/lib/rear/layout/disk_mappings)
# are applied when devices in GRUB2_INSTALL_DEVICES match
# cf. https://github.com/rear/rear/issues/1437
# MAPPING_FILE (var/lib/rear/layout/disk_mappings)
# is set in layout/prepare/default/300_map_disks.sh
# only if MIGRATION_MODE is true:
if test -s "$MAPPING_FILE" ; then
# Cf. the function apply_layout_mappings() in lib/layout-functions.sh
while read source_disk target_disk junk ; do
# Skip lines that have wrong syntax:
test "$source_disk" -a "$target_disk" || continue
if test "$grub2_install_device" = "$source_disk" ; then
LogPrint "Installing GRUB2 on $target_disk ($source_disk in GRUB2_INSTALL_DEVICES is mapped to $target_disk in $MAPPING_FILE)"
grub2_install_device="$target_disk"
break
fi
done < <( grep -v '^#' "$MAPPING_FILE" )
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_option $grub2_install_device" ; then
+ if ! chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_no_nvram_option $grub2_install_device" ; then
LogPrintError "Failed to install GRUB2 on $grub2_install_device"
grub2_install_failed="yes"
fi
done
is_false $grub2_install_failed && NOBOOTLOADER=''
# return even if it failed to install GRUB2 on one of the specified GRUB2_INSTALL_DEVICES
# because then the user gets an explicit WARNING via finalize/default/890_finish_checks.sh
is_true $NOBOOTLOADER && return 1 || return 0
fi
# If GRUB2_INSTALL_DEVICES is not specified try to automatically determine where to install GRUB2:
if ! test -r "$LAYOUT_FILE" ; then
LogPrintError "Cannot determine where to install GRUB2"
return 1
fi
LogPrint "Determining where to install GRUB2 (no GRUB2_INSTALL_DEVICES specified)"
# Find PPC PReP Boot partitions:
part_list=$( awk -F ' ' '/^part / {if ($6 ~ /prep/) {print $7}}' $LAYOUT_FILE )
if ! test "$part_list" ; then
LogPrintError "Cannot install GRUB2 (unable to find a PPC PReP boot partition)"
return 1
fi
# We do not know what the first boot device will be, so we cannot be sure
# GRUB2 is installed on the correct boot device.
# If software RAID1 is used, several boot devices will be found and
# then GRUB2 needs to be installed on each of them.
# This is the reason why we make all possible boot disks bootable here:
for part in $part_list ; do
# Install GRUB2 on the PPC PReP boot partition if one was found:
if test "$part" ; then
LogPrint "Found PPC PReP boot partition $part - installing GRUB2 there"
# Erase the first 512 bytes of the PPC PReP boot partition:
dd if=/dev/zero of=$part
- if chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_install_option $part" ; then
+ if chroot $TARGET_FS_ROOT /bin/bash --login -c "$grub_name-install $grub2_no_nvram_option $part" ; then
# In contrast to the above behaviour when GRUB2_INSTALL_DEVICES is specified
# consider it here as a successful bootloader installation when GRUB2
# got installed on at least one PPC PReP boot partition:
NOBOOTLOADER=''
# Continue with the next PPC PReP boot partition:
continue
fi
LogPrintError "Failed to install GRUB2 on PPC PReP boot partition $part"
fi
done
is_true $NOBOOTLOADER || return 0
LogPrintError "Failed to install GRUB2 - you may have to manually install it"
return 1
--- usr/share/rear/lib/layout-functions.sh 2018-09-26 14:05:57.000000000 +0200
+++ usr/share/rear/lib/layout-functions.sh 2021-01-20 14:51:05.010510411 +0100
@@ -630,37 +630,52 @@
label=$( echo "$LINE" | grep "^LABEL=" | cut -d= -f2 | sed -e 's/"//g' | sed -e 's/ /\\\\b/g') # replace all " " with "\\b"
[[ ! -z "$label" ]] && break
done
echo "$label"
}
# Returns 1 if the device is an LVM physical volume
# Returns 0 otherwise or if the device doesn't exists
is_disk_a_pv() {
disk=$1
if grep -q "^lvmdev .* ${disk} " $LAYOUT_FILE ; then
return 0
else
return 1
fi
}
function is_multipath_path {
- [ "$1" ] && type multipath &>/dev/null && multipath -c /dev/$1 &>/dev/null
+ # Return 'false' if there is no device as argument:
+ test "$1" || return 1
+ # Return 'false' if there is no multipath command:
+ type multipath &>/dev/null || return 1
+ # Return 'false' if multipath is not used,
+ # see https://github.com/rear/rear/issues/2298
+ # Because "multipath -l" always returns zero exit code
+ # we check if it has real output via grep -q '[[:alnum:]]'
+ # so that no "multipath -l" output could clutter the log
+ # (the "multipath -l" output is irrelevant here)
+ # in contrast to e.g. test "$( multipath -l )"
+ # that would falsely succeed with blank output and the
+ # output would appear in the log in 'set -x' debugscript mode:
+ multipath -l | grep -q '[[:alnum:]]' || return 1
+ # Check if a block device should be a path in a multipath device:
+ multipath -c /dev/$1 &>/dev/null
}
# retry_command () is binded with REAR_SLEEP_DELAY and REAR_MAX_RETRIES.
# This function will do maximum of REAR_MAX_RETRIES command execution
# and will sleep REAR_SLEEP_DELAY after each unsuccessful command execution.
# It outputs command stdout if succeeded or returns 1 on failure.
retry_command ()
{
local retry=0
until command_stdout=$(eval "$@"); do
sleep $REAR_SLEEP_DELAY
let retry++
if (( retry >= REAR_MAX_RETRIES )) ; then
Log "retry_command '$*' failed"
return 1
--- usr/share/rear/skel/default/etc/scripts/system-setup.d/41-load-special-modules.sh 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/skel/default/etc/scripts/system-setup.d/41-load-special-modules.sh 2021-01-27 11:24:13.228386569 +0100
@@ -1,6 +1,26 @@
-# some things are special
-# XEN PV does not autoload some modules
-if [ -d /proc/xen ] ; then
- modprobe xenblk
+# Special cases of kernel module loading.
+
+# XEN PV does not autoload some modules:
+test -d /proc/xen && modprobe xenblk
+
+# On POWER architecture the nvram kernel driver may be no longer built into the kernel
+# but nowadays it could be also built as a kernel module that needs to be loaded
+# cf. https://github.com/rear/rear/issues/2554#issuecomment-764720180
+# because normally grub2-install gets called without the '--no-nvram' option
+# e.g. see finalize/Linux-ppc64le/620_install_grub2.sh
+# which is how grub2-install should be called when the hardware supports nvram.
+# Nothing to do when the character device node /dev/nvram exists
+# because then the nvram kernel driver is already there:
+if ! test -c /dev/nvram ; then
+ # Nothing can be done when there is no nvram kernel module.
+ # Suppress the possible 'modprobe -n nvram' error message like
+ # "modprobe: FATAL: Module nvram not found in directory /lib/modules/..."
+ # to avoid a possible "FATAL" false alarm message that would appear
+ # on the user's terminal during recovery system startup
+ # cf. https://github.com/rear/rear/pull/2537#issuecomment-741825046
+ # but when there is a nvram kernel module show possible 'modprobe nvram'
+ # (error) messages on the user's terminal during recovery system startup:
+ modprobe -n nvram 2>/dev/null && modprobe nvram
fi
+
--- usr/share/rear/conf/GNU/Linux.conf.orig 2021-02-01 10:47:36.773795306 +0100
+++ usr/share/rear/conf/GNU/Linux.conf 2021-02-01 10:51:53.517795306 +0100
@@ -228,8 +228,10 @@
/usr/lib*/libnssdbm3.so*
)
+# nvram could be a module on POWER architecture, cf. https://github.com/rear/rear/issues/2554#issuecomment-764720180
MODULES=(
${MODULES[@]:-}
+nvram
vfat
nls_iso8859_1
nls_utf8
--- usr/share/rear/output/ISO/Linux-i386/810_prepare_multiple_iso.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/output/ISO/Linux-i386/810_prepare_multiple_iso.sh 2021-02-01 11:23:30.629795306 +0100
@@ -66,6 +66,9 @@
mkdir -p $TEMP_BACKUP_DIR
mv $BACKUP_NAME $TEMP_BACKUP_DIR
pushd $TEMP_ISO_DIR 1>/dev/null
+ # Error out when files greater or equal ISO_FILE_SIZE_LIMIT should be included in the ISO (cf. default.conf).
+ # Consider all regular files and follow symbolic links to also get regular files where symlinks point to:
+ assert_ISO_FILE_SIZE_LIMIT $( find -L . -type f )
if ! $ISO_MKISOFS_BIN $v -o "$ISO_OUTPUT_PATH" -R -J -volid "${ISO_VOLID}_$iso_number" -v -iso-level 3 . 1>/dev/null ; then
Error "Failed to create ISO image $ISO_NAME (with $ISO_MKISOFS_BIN)"
fi
--- usr/share/rear/output/ISO/Linux-i386/820_create_iso_image.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/output/ISO/Linux-i386/820_create_iso_image.sh 2021-02-01 11:24:55.037795306 +0100
@@ -16,6 +16,11 @@
fi
pushd $TMP_DIR/isofs >/dev/null
+
+# Error out when files greater or equal ISO_FILE_SIZE_LIMIT should be included in the ISO (cf. default.conf).
+# Consider all regular files and follow symbolic links to also get regular files where symlinks point to:
+assert_ISO_FILE_SIZE_LIMIT $( find -L . -type f )
+
# ebiso uses different command line options and parameters:
if test "ebiso" = $( basename $ISO_MKISOFS_BIN ) ; then
# ebiso currently works only with UEFI:
--- usr/share/rear/output/ISO/Linux-ia64/800_create_isofs.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/output/ISO/Linux-ia64/800_create_isofs.sh 2021-02-01 11:29:04.565795306 +0100
@@ -24,6 +24,10 @@
# Careful in case of 'return' after 'pushd' (must call the matching 'popd' before 'return'):
pushd $TMP_DIR/isofs >&2 # so that relative paths will work
+# Error out when files greater or equal ISO_FILE_SIZE_LIMIT should be included in the ISO (cf. default.conf).
+# Consider all regular files and follow symbolic links to also get regular files where symlinks point to:
+assert_ISO_FILE_SIZE_LIMIT $( find -L . -type f )
+
$ISO_MKISOFS_BIN $v -o "$ISO_DIR/$ISO_PREFIX.iso" -b boot/boot.img -c boot/boot.catalog \
-no-emul-boot -R -T -J -volid "$ISO_VOLID" -v . >/dev/null
StopIfError "Could not create ISO image"
--- usr/share/rear/output/ISO/Linux-ppc64le/820_create_iso_image.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/output/ISO/Linux-ppc64le/820_create_iso_image.sh 2021-02-01 11:37:06.337795306 +0100
@@ -17,6 +17,10 @@
chrp_boot_option="-chrp-boot"
fi
+# Error out when files greater or equal ISO_FILE_SIZE_LIMIT should be included in the ISO (cf. default.conf).
+# Consider all regular files and follow symbolic links to also get regular files where symlinks point to:
+assert_ISO_FILE_SIZE_LIMIT "${ISO_FILES[@]}"
+
$ISO_MKISOFS_BIN $v -o "$ISO_DIR/$ISO_PREFIX.iso" -U $chrp_boot_option -R -J -volid "$ISO_VOLID" -v -graft-points "${ISO_FILES[@]}" >&2
StopIfError "Could not create ISO image (with $ISO_MKISOFS_BIN)"
--- usr/share/rear/conf/default.conf.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/conf/default.conf 2021-02-01 11:20:42.677795306 +0100
@@ -573,7 +573,38 @@
# Accordingly when ISO_MAX_SIZE is set the mkrescue workflow is forbidden
# to be on the safe side to not possibly destroy an existing backup.
ISO_MAX_SIZE=
-
+#
+# Error out when files greater or equal ISO_FILE_SIZE_LIMIT should be included in the ISO.
+# There is a limit of the ISO 9660 file system that is 2GiB or 4GiB according to
+# https://en.wikipedia.org/wiki/ISO_9660#The_2/4_GiB_file_size_limit
+# Usually 'mkisofs' is called with '-iso-level 3'
+# cf. usr/share/rear/prep/ISO/GNU/Linux/320_verify_mkisofs.sh
+# but there are cases where ISO 9660 level 1 or 2 is used that has a 2GiB file size limit.
+# For example when 'ebiso' is used there is a 2GiB file size limit
+# cf. https://github.com/gozora/ebiso/issues/12
+# but also other tools that are specified by ISO_MKISOFS_BIN could have that limit.
+# Accordingly to be by default on the safe side we use by default a 2GiB limit
+# cf. https://github.com/rear/rear/pull/2525
+# Under normal circumstances files greater or equal 2GiB should not appear in the ISO.
+# An exception is when the backup is included in the ISO with BACKUP_URL=iso://
+# where the backup archive file (e.g. backup.tar.gz) could be greater or equal 2GiB.
+# The user might adapt ISO_FILE_SIZE_LIMIT provided he verified that "rear recover"
+# actually works in his particular environment even when there are files in his ISO
+# (in particular backup.tar.gz) that are actually greater than the default 2GiB limit.
+# When there is a 2GiB file size limit a backup.tar.gz that is greater than 2GiB
+# will get corrupted in the ISO so backup restore via "rear recover" would fail
+# which is a dead end because the backup in the ISO got corrupted which is a severe error.
+# Also the ReaR recovery system initrd could become greater or equal 2GiB
+# (e.g. because of accidentally too much in COPY_AS_IS) which is likely an error
+# that could let booting or running the recovery system fail because
+# a recovery system in a 2GiB or bigger compressed initrd will need
+# more memory space when uncompressed and running in the ramdisk.
+# By default we error out when files greater or equal ISO_FILE_SIZE_LIMIT should be
+# included in the ISO but if really needed this ISO_FILE_SIZE_LIMIT test
+# can be skipped with ISO_FILE_SIZE_LIMIT=0 in etc/rear/local.conf
+# (2 GiB = 2 * 1024 * 1024 * 1024 bytes = 2147483648 bytes):
+ISO_FILE_SIZE_LIMIT=2147483648
+#
# How to find mkisofs:
# Guess the common names mkisofs or genisoimage
# script in prep stage will verify this and complain if not found
--- usr/share/rear/lib/output-functions.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/lib/output-functions.sh 2021-02-01 11:06:18.633795306 +0100
@@ -25,3 +25,32 @@
done
}
+
+# Error out when files greater or equal ISO_FILE_SIZE_LIMIT should be included in the ISO (cf. default.conf)
+# for files passed as arguments e.g: assert_ISO_FILE_SIZE_LIMIT file1 relative/path/file2 /absolute/path/file3 ...
+# Normally there should be no error exit inside a function but a function should return non-zero exit code
+# and leave it to its caller what to do depending on the callers environment. But this function is an exception.
+# It is meant like the "assert" macro in C that outputs a message on stderr and then exits with abort().
+# Furthermore it is less duplicated code to implement the error exit inside this function
+# than to let this function return non-zero exit code and implement the error exit in each caller
+# when the meaning of this function is to always exit for files greater or equal ISO_FILE_SIZE_LIMIT
+# (for the reasoning why "always exit" for such files see default.conf).
+# It errors out for the first file that is greater or equal ISO_FILE_SIZE_LIMIT and shows only this one to the user
+# so if there are also other files greater or equal ISO_FILE_SIZE_LIMIT they are not shown. At least for now
+# this should be sufficient because more than one file greater or equal ISO_FILE_SIZE_LIMIT is not expected
+# and the "assert" meaning is that this error exit is there only as safeguard for exceptional cases.
+function assert_ISO_FILE_SIZE_LIMIT () {
+ # Skip when there is no usable ISO_FILE_SIZE_LIMIT set (in particular for ISO_FILE_SIZE_LIMIT=0):
+ is_positive_integer $ISO_FILE_SIZE_LIMIT || return 0
+ local file_for_iso file_for_iso_size
+ for file_for_iso in $@ ; do
+ file_for_iso_size=$( stat -L -c '%s' $file_for_iso )
+ # Continue "bona fide" with testing the next one if size could not be determined (assume the current one is OK):
+ is_positive_integer $file_for_iso_size || continue
+ # Continue testing the next one when this one is below the file size limit:
+ test $file_for_iso_size -lt $ISO_FILE_SIZE_LIMIT && continue
+ # Show only basename to avoid the meaningless ReaR-internal path where files for the ISO are (temporarily) located:
+ Error "File for ISO $( basename $file_for_iso ) size $file_for_iso_size greater or equal ISO_FILE_SIZE_LIMIT=$ISO_FILE_SIZE_LIMIT"
+ done
+}
+
--- usr/share/rear/prep/ISO/GNU/Linux/320_verify_mkisofs.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/prep/ISO/GNU/Linux/320_verify_mkisofs.sh 2021-02-01 11:58:44.209795306 +0100
@@ -1,8 +1,37 @@
-# verify that we have a working mkisofs
+
+# Verify that we have a working program to make ISO9660 filesystem.
#
-# default for ISO_MKISOFS_BIN is to check for mkisofs and genisoimage in the path
+# In default.conf ISO_MKISOFS_BIN is to check what there is in the path with
+# xorrisofs used as the preferred method for generating the iso image
+# and mkisofs and genisoimage as second and third option
+# but for UEFI bootable systems 'ISO_MKISOFS_BIN=/usr/bin/ebiso' is used.
+test -x "$ISO_MKISOFS_BIN" || Error "Could not find program to make ISO9660 filesystem. Install 'mkisofs', 'genisoimage' or 'ebiso' or specify ISO_MKISOFS_BIN (currently '$ISO_MKISOFS_BIN')"
+DebugPrint "Using '$ISO_MKISOFS_BIN' to create ISO filesystem images"
+
+# Include 'udf' module which is required if backup archive is >= 4GiB and mkisofs/genisoimage is used:
+IsInArray "all_modules" "${MODULES[@]}" || MODULES+=( udf )
+# Enforce 2GiB ISO_FILE_SIZE_LIMIT when the MODULES array contains 'loaded_modules'
+# because in this case MODULES+=( udf ) has no effect (unless it is loaded which normally isn't)
+# except the user has specified to skip the ISO_FILE_SIZE_LIMIT test with ISO_FILE_SIZE_LIMIT=0
+# but keep what the user has specified if ISO_FILE_SIZE_LIMIT is specified less than 2GiB.
+# Do nothing when the MODULES array contains 'no_modules' because that is meant for experts usually
+# when they have all needed modules (they have to know what they need) compiled into their kernel
+# (in default.conf a 2GiB ISO_FILE_SIZE_LIMIT is set so by default things should behave safe):
+if IsInArray "loaded_modules" "${MODULES[@]}" ; then
+ if is_positive_integer $ISO_FILE_SIZE_LIMIT && test $ISO_FILE_SIZE_LIMIT -gt 2147483648 ; then
+ DebugPrint "Enforcing 2GiB ISO_FILE_SIZE_LIMIT (MODULES contains 'loaded_modules')"
+ ISO_FILE_SIZE_LIMIT=2147483648
+ fi
+fi
-[ -x "$ISO_MKISOFS_BIN" ]
-StopIfError "Could not find 'mkisofs' compatible program. Please install 'mkisofs', 'genisoimage' or 'ebiso' into your path or manually set ISO_MKISOFS_BIN [$ISO_MKISOFS_BIN]"
+# ebiso has a 2GiB file size limit cf. https://github.com/gozora/ebiso/issues/12
+# so an actual ISO_FILE_SIZE_LIMIT value must be set that is not greater than 2GiB:
+if test "ebiso" = "$( basename $ISO_MKISOFS_BIN )" ; then
+ # For ebiso the ISO_FILE_SIZE_LIMIT test must not be skipped with ISO_FILE_SIZE_LIMIT=0
+ # because it would be disastrous when e.g. a backup.tar.gz in the ISO becomes bigger than 2GiB
+ # that gets corrupted in the ISO so the backup is lost and restore via "rear recover" cannot work:
+ is_positive_integer $ISO_FILE_SIZE_LIMIT || Error "ebiso has a 2GiB file size limit but ISO_FILE_SIZE_LIMIT is not set accordingly"
+ # 2 GiB = 2 * 1024 * 1024 * 1024 bytes = 2147483648 bytes:
+ test $ISO_FILE_SIZE_LIMIT -le 2147483648 || Error "ebiso has a 2GiB file size limit but ISO_FILE_SIZE_LIMIT is greater than 2GiB"
+fi
-Log "Using '$ISO_MKISOFS_BIN' to create ISO images"
--- usr/share/rear/build/default/980_verify_rootfs.sh.orig 2018-08-10 12:36:00.000000000 +0200
+++ usr/share/rear/build/default/980_verify_rootfs.sh 2021-02-01 13:35:10.249795306 +0100
@@ -54,6 +54,17 @@
# Actually test all binaries for 'not found' libraries.
# Find all binaries and libraries also e.g. those that are copied via COPY_AS_IS into other paths:
for binary in $( find $ROOTFS_DIR -type f -executable -printf '/%P\n' ); do
+ # Skip the ldd test for kernel modules because in general running ldd on kernel modules does not make sense
+ # and sometimes running ldd on kernel modules causes needless errors because sometimes that segfaults
+ # which results false alarm "ldd: exited with unknown exit code (139)" messages ( 139 - 128 = 11 = SIGSEGV )
+ # cf. https://github.com/rear/rear/issues/2177 which also shows that sometimes kernel modules could be
+ # not only in the usual directory /lib/modules/ but also e.g. in /usr/lib/modules/
+ # so we 'grep' for '/lib/modules/' anywhere in the full path of the binary.
+ # Skip the ldd test for firmware files where it also does not make sense.
+ # Skip the ldd test for ReaR files (mainly bash scripts) where it does not make sense
+ # (programs in the recovery system get all copied into /bin/ so it is /bin/rear)
+ # cf. https://github.com/rear/rear/issues/2519#issuecomment-731196820
+ egrep -q "/lib/modules/|/lib.*/firmware/|$SHARE_DIR|/bin/rear$" <<<"$binary" && continue
# In order to handle relative paths, we 'cd' to the directory containing $binary before running ldd.
# In particular third-party backup tools may have shared object dependencies with relative paths.
# For an example see https://github.com/rear/rear/pull/1560#issuecomment-343504359 that reads (excerpt):
--- usr/share/rear/lib/layout-functions.sh 2018-09-26 14:05:57.000000000 +0200
+++ usr/share/rear/lib/layout-functions.sh 2020-12-10 13:32:16.884965400 +0100
@@ -474,62 +543,57 @@
### Translate a sysfs name or device name to the name preferred in
### Relax-and-Recover.
### The device does not necessarily exist.
### cciss!c0d0 -> /dev/cciss/c0d0
### /dev/dm-3 -> /dev/mapper/system-tmp
### /dev/dm-4 -> /dev/mapper/oralun
### /dev/dm-5 -> /dev/mapper/oralunp1
+### /dev/sda -> /dev/sda
+###
+### Returns 0 on success, 1 if device is not existing
get_device_name() {
### strip common prefixes
local name=${1#/dev/}
name=${name#/sys/block/}
contains_visible_char "$name" || BugError "Empty string passed to get_device_name"
- ### Translate dm-8 -> mapper/test
- local device dev_number mapper_number
- if [[ -d /sys/block/$name ]] ; then
+ if [[ "$name" =~ ^mapper/ ]]; then
+ echo "/dev/$name"
+ return 0
+ fi
+
+ if [[ -L "/dev/$name" ]] ; then
+ # Map vg/lv into dm-X, which will then be resolved later
+ name="$( basename $(readlink -f /dev/$name) )"
+ fi
+
+ if [[ "$name" =~ ^dm- ]] ; then
+ local device
if [[ -r /sys/block/$name/dm/name ]] ; then
### recent kernels have a dm subfolder
- echo "/dev/mapper/$( < /sys/block/$name/dm/name)";
- return 0
+ device="$( < /sys/block/$name/dm/name )"
else
- ### loop over all block devices
- dev_number=$( < /sys/block/$name/dev)
- for device in /dev/mapper/* ; do
- mapper_number=$(dmsetup info -c --noheadings -o major,minor ${device#/dev/mapper/} 2>/dev/null )
- if [ "$dev_number" = "$mapper_number" ] ; then
- echo "$device"
- return 0
- fi
- done
+ local dev_number=$( < /sys/block/$name/dev)
+ if [[ ! -r "$TMP_DIR/dmsetup_info.txt" ]] ; then
+ dmsetup info --noheadings -c -o name,major,minor > "$TMP_DIR/dmsetup_info.txt"
+ fi
+ device="$( awk -F ':' "/$dev_number\$/ { print \$1 }" < "$TMP_DIR/dmsetup_info.txt" )"
+ [[ -n "$device" ]] || BugError "No device returned for major/minor $dev_number"
fi
- fi
-
- ### Translate device name to mapper name. ex: vg/lv -> mapper/vg-lv
- if [[ "$name" =~ ^mapper/ ]]; then
- echo "/dev/$name"
+ echo "/dev/mapper/$device"
return 0
fi
- if my_dm=`readlink /dev/$name`; then
- for mapper_dev in /dev/mapper/*; do
- if mapper_dm=`readlink $mapper_dev`; then
- if [ "$my_dm" = "$mapper_dm" ]; then
- echo $mapper_dev
- return 0
- fi
- fi
- done
- fi
### handle cciss sysfs naming
name=${name//!//}
### just return the possibly nonexisting name
echo "/dev/$name"
+ [[ -r "/dev/$name" ]] && return 0
return 1
}
# check $VAR_LIB/recovery/diskbyid_mappings file to see whether we find
# a disk/by-id mapping to dm style (the by-id dev is not translated
# properly by get_device_name function - dm dev are better)
# 220_lvm_layout.sh uses get_device_mapping to translate lvmdev better
--- usr/share/rear/rescue/GNU/Linux/270_fc_transport_info.sh 2021-02-08 12:17:23.301678202 +0100
+++ usr/share/rear/rescue/GNU/Linux/270_fc_transport_info.sh 2021-02-08 12:16:36.333049709 +0100
@@ -1,5 +1,9 @@
# collect output from production SAN disks
+# don't collect this anymore, this can be very slow
+# cf. https://github.com/rear/rear/pull/2034
+return 0
+
find /sys/class/fc_transport -follow -maxdepth 6 \( -name model -o -name vendor -o -name rev -name state -o -name model_name -o -name size -o -name node_name \) 2>/dev/null| egrep -v 'driver|rport|power|drivers|devices' | xargs grep '.' > $VAR_DIR/recovery/fc_transport.info >&2
if [[ -s $VAR_DIR/recovery/fc_transport.info ]]; then