Skip to content

Commit

Permalink
Merge pull request #2523 from rear/jsmeix-overhauled-ldd-test
Browse files Browse the repository at this point in the history
Completely overhauled ldd test in 990_verify_rootfs.sh:
Now if needed a special LD_LIBRARY_PATH is set only in the bash that runs ldd and
that bash exits after ldd finished so the special LD_LIBRARY_PATH setting is gone with it.
So there is no need to remember and restore some previously set LD_LIBRARY_PATH
because nothing was changed in the bash that runs rear.
Furthermore reporting when a binary requires additional libraries happens now
in the same 'for' loop after the ldd test was run which further simplifies the code.
  • Loading branch information
jsmeix committed Nov 26, 2020
2 parents 567668f + caf9503 commit 6b804a5
Showing 1 changed file with 71 additions and 50 deletions.
121 changes: 71 additions & 50 deletions usr/share/rear/build/default/990_verify_rootfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,34 +66,34 @@ fi
# FIXME: The following code fails if file names contain characters from IFS (e.g. blanks),
# see https://github.com/rear/rear/pull/1514#discussion_r141031975
# and for the general issue see https://github.com/rear/rear/issues/1372
Log "Testing each binary (except links) with ldd and look for 'not found' libraries within the recovery system"
DebugPrint "Testing each binary with 'ldd' and look for 'not found' libraries within the recovery system"
local backup_tool_LD_LIBRARY_PATH=""
local binary=""
local broken_binaries=""
local broken_binary_LD_LIBRARY_PATH=""
local broken_binaries="no"
local fatal_missing_library="no"
local ldd_output=""
# 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:
local old_LD_LIBRARY_PATH
# Save LD_LIBRARY_PATH only if one is already set:
test $LD_LIBRARY_PATH && old_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
# so that for testing such third-party backup tools we must also use their special LD_LIBRARY_PATH here:
if test "$BACKUP" = "TSM" ; then
# Use a TSM-specific LD_LIBRARY_PATH to find TSM libraries
# see https://github.com/rear/rear/issues/1533
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSM_LD_LIBRARY_PATH
test $LD_LIBRARY_PATH && backup_tool_LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSM_LD_LIBRARY_PATH || backup_tool_LD_LIBRARY_PATH=$TSM_LD_LIBRARY_PATH
fi
if test "$BACKUP" = "SESAM" ; then
# Use a SEP sesam-specific LD_LIBRARY_PATH to find sesam client related libraries
# see https://github.com/rear/rear/pull/1817
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SESAM_LD_LIBRARY_PATH
test $LD_LIBRARY_PATH && backup_tool_LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SESAM_LD_LIBRARY_PATH || backup_tool_LD_LIBRARY_PATH=$SESAM_LD_LIBRARY_PATH
fi
if test "$BACKUP" = "NBU" ; then
# Use a NBU-specific LD_LIBRARY_PATH to find NBU libraries
# see https://github.com/rear/rear/issues/1974
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NBU_LD_LIBRARY_PATH
test $LD_LIBRARY_PATH && backup_tool_LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NBU_LD_LIBRARY_PATH || backup_tool_LD_LIBRARY_PATH=$NBU_LD_LIBRARY_PATH
fi
if test "$BACKUP" = "FDRUPSTREAM" ; then
# Use a FDRUPSTREAM-specific LD_LIBRARY_PATH to find FDR libraries
# see https://github.com/rear/rear/pull/2296
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$FDRUPSTREAM_INSTALL_PATH/bin
# Use a FDRUPSTREAM-specific LD_LIBRARY_PATH to find FDR libraries
# see https://github.com/rear/rear/pull/2296
test $LD_LIBRARY_PATH && backup_tool_LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$FDRUPSTREAM_INSTALL_PATH/bin || backup_tool_LD_LIBRARY_PATH=$FDRUPSTREAM_INSTALL_PATH/bin
fi
# Actually test all binaries for 'not found' libraries.
# Find all binaries and libraries (in particular what is copied via COPY_AS_IS into arbitrary paths)
Expand Down Expand Up @@ -145,50 +145,72 @@ for binary in $( find $ROOTFS_DIR -type f \( -executable -o -name '*.so' -o -nam
# Redirected stdin for login shell avoids motd welcome message, cf. https://github.com/rear/rear/issues/2120
# and redirected stderr avoids ldd warnings in the log like "ldd: warning: you do not have execution permission for ..."
# cf. https://blog.schlomo.schapiro.org/2015/04/warning-is-waste-of-my-time.html
chroot $ROOTFS_DIR /bin/bash --login -c "cd $( dirname $binary ) && ldd $binary" </dev/null 2>/dev/null | grep -q 'not found' && broken_binaries="$broken_binaries $binary"
done
# Report binaries with 'not found' shared object dependencies:
local fatal_missing_library=""
if contains_visible_char "$broken_binaries" ; then
LogPrintError "There are binaries or libraries in the ReaR recovery system that need additional libraries"
local ldd_output=""
for binary in $broken_binaries ; do
# 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
# With an empty NON_FATAL_BINARIES_WITH_MISSING_LIBRARY grep -E '' would always match:
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)"
else
LogPrintError "$binary requires additional libraries (fatal error)"
fatal_missing_library="yes"
fi
# The login shell in the ReaR recovery system should behave same as when 'root' has logged in into the recovery system.
# Usually there is no LD_LIBRARY_PATH set when 'root' has logged in into the recovery system
# (in particular there is nothing about LD_LIBRARY_PATH in usr/share/rear/skel/*).
# First test the binary explicitly without any LD_LIBRARY_PATH setting inside the recovery system.
# Continue testing the next binary if this one succeeded (i.e. when it has no 'not found' shared object dependency):
chroot $ROOTFS_DIR /bin/bash --login -c "unset LD_LIBRARY_PATH && cd $( dirname $binary ) && ldd $binary" </dev/null 2>/dev/null | grep -q 'not found' || continue
broken_binary_LD_LIBRARY_PATH=""
Log "$binary requires additional libraries (no LD_LIBRARY_PATH set)"
# Second test for the binary with same LD_LIBRARY_PATH as what is currently set while "rear mkrecue/mkbackup" is running.
# The current LD_LIBRARY_PATH is explicitly set because the login shell in the recovery system has usually no LD_LIBRARY_PATH set.
if test $LD_LIBRARY_PATH ; then
Log "Another test for $binary with LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
# Continue testing the next binary if this one succeeded (i.e. when it has no 'not found' shared object dependency):
chroot $ROOTFS_DIR /bin/bash --login -c "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH && cd $( dirname $binary ) && ldd $binary" </dev/null 2>/dev/null | grep -q 'not found' || continue
broken_binary_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
Log "$binary requires additional libraries with LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
fi
# Third test for the binary with backup_tool_LD_LIBRARY_PATH if such a backup_tool_LD_LIBRARY_PATH was set above:
if test $backup_tool_LD_LIBRARY_PATH ; then
Log "Final test for $binary with LD_LIBRARY_PATH=$backup_tool_LD_LIBRARY_PATH"
# Continue testing the next binary if this one succeeded (i.e. when it has no 'not found' shared object dependency):
chroot $ROOTFS_DIR /bin/bash --login -c "export LD_LIBRARY_PATH=$backup_tool_LD_LIBRARY_PATH && cd $( dirname $binary ) && ldd $binary" </dev/null 2>/dev/null | grep -q 'not found' || continue
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"
# 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
# With an empty NON_FATAL_BINARIES_WITH_MISSING_LIBRARY grep -E '' would always match:
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)"
else
LogPrintError "$binary requires additional libraries (fatal error)"
fatal_missing_library="yes"
fi
else
LogPrintError "$binary requires additional libraries"
LogPrintError "$binary requires additional libraries (fatal error)"
fatal_missing_library="yes"
fi
# Run the same ldd call as above but now keep its whole output:
ldd_output="$( chroot $ROOTFS_DIR /bin/ldd $binary )"
# 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" )"
done
LogPrintError "ReaR recovery system in '$ROOTFS_DIR' needs additional libraries, check $RUNTIME_LOGFILE for details"
is_true "$fatal_missing_library" && keep_build_dir
fi
# Restore the LD_LIBRARY_PATH if it was saved above (i.e. when LD_LIBRARY_PATH had been set before)
# otherwise unset a possibly set LD_LIBRARY_PATH (i.e. when LD_LIBRARY_PATH had not been set before):
test $old_LD_LIBRARY_PATH && export LD_LIBRARY_PATH=$old_LD_LIBRARY_PATH || unset LD_LIBRARY_PATH
else
LogPrintError "$binary requires additional libraries"
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.
# Run that ldd call with the same LD_LIBRARY_PATH setting as it was run above:
if test $broken_binary_LD_LIBRARY_PATH ; then
ldd_output="$( chroot $ROOTFS_DIR /bin/bash --login -c "export LD_LIBRARY_PATH=$broken_binary_LD_LIBRARY_PATH && cd $( dirname $binary ) && ldd $binary" </dev/null 2>/dev/null )"
else
ldd_output="$( chroot $ROOTFS_DIR /bin/bash --login -c "unset LD_LIBRARY_PATH && cd $( dirname $binary ) && ldd $binary" </dev/null 2>/dev/null )"
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" )"
done
is_true $broken_binaries && 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
# provided the program exist on the original system:
Log "Testing that each program in the PROGS array can be found as executable command within the recovery system"
DebugPrint "Testing that each program in the PROGS array can be found as executable command within the recovery system"
local program=""
local missing_programs=""
for program in "${PROGS[@]}" ; do
Expand All @@ -215,7 +237,7 @@ if contains_visible_char "$missing_programs" ; then
fi

# Testing that each program in the REQUIRED_PROGS array can be found as executable command within the recovery system:
Log "Testing that each program in the REQUIRED_PROGS array can be found as executable command within the recovery system"
DebugPrint "Testing that each program in the REQUIRED_PROGS array can be found as executable command within the recovery system"
local required_program=""
local missing_required_programs=""
local fatal_missing_program=""
Expand Down Expand Up @@ -255,4 +277,3 @@ is_true "$fatal_missing_library" && Error "ReaR recovery system in '$ROOTFS_DIR'

# Finish this script successfully:
true

0 comments on commit 6b804a5

Please sign in to comment.