void-packages/xbps-src/shutils/verify_rundeps.sh

242 lines
6.8 KiB
Bash

#-
# Copyright (c) 2010-2011 Juan Romero Pardines.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#-
#
# Finds all required libraries for a package, by looking at its executables
# and shared libraries and skipping duplicated matches.
#
# Once the list is known it finds the binary package names mapped to those
# libraries and reports if any of them was not added.
#
find_rundep()
{
local dep="$1" i rpkgdep
for i in ${run_depends}; do
rpkgdep="$($XBPS_PKGDB_CMD getpkgdepname $i)"
[ "${rpkgdep}" != "${dep}" ] && continue
return 1
done
}
verify_rundeps()
{
local j f nlib verify_deps maplib found_dup igndir soname_arch
local broken rdep found rsonamef soname_list revbumped tmplf newrev
maplib="$XBPS_COMMONVARSDIR/mapping_shlib_binpkg.txt"
[ -n "$noarch" -o -n "$noverifyrdeps" ] && return 0
msg_normal "$pkgver: verifying required shlibs...\n"
depsftmp=$(mktemp -t xbps_src_depstmp.XXXXXXXXXX) || exit 1
find ${1} -type f -perm -u+w > $depsftmp 2>/dev/null
exec 3<&0 # save stdin
exec < $depsftmp
while read f; do
# Don't check dirs specified in ignore_vdeps_dir.
for j in ${ignore_vdeps_dir}; do
if grep -q ${j} "${f}"; then
igndir=1
break
fi
done
[ -n "$igndir" ] && continue
unset igndir
case "$(file -bi "$f")" in
application/x-executable*|application/x-sharedlib*)
for nlib in $(objdump -p "$f"|grep NEEDED|awk '{print $2}'); do
if [ -z "$verify_deps" ]; then
verify_deps="$nlib"
continue
fi
for j in ${verify_deps}; do
[ "$j" != "$nlib" ] && continue
found_dup=1
break
done
if [ -z "$found_dup" ]; then
verify_deps="$verify_deps $nlib"
fi
unset found_dup
done
;;
esac
done
exec 0<&3 # restore stdin
rm -f $depsftmp
if [ -f $XBPS_SRCPKGDIR/$pkgname/$pkgname.template ]; then
tmplf=$XBPS_SRCPKGDIR/$pkgname/$pkgname.template
else
tmplf=$XBPS_SRCPKGDIR/$pkgname/template
fi
#
# Add required run time packages by using required shlibs resolved
# above, the mapping is done thru the mapping_shlib_binpkg.txt file.
#
for f in ${verify_deps}; do
unset j rdep _rdep rdepcnt
rdep="$(grep "^${f}.*$" $maplib|awk '{print $2}')"
rdepcnt="$(grep "^${f}.*$" $maplib|awk '{print $2}'|wc -l)"
if [ -z "$rdep" ]; then
# Ignore libs by current pkg
soname=$(find ${DESTDIR} -type f -name "$f");
if [ -z "$soname" ]; then
echo " SONAME: $f <-> UNKNOWN PKG PLEASE FIX!"
broken=1
else
echo " SONAME: $f <-> $pkgname (ignored)"
fi
continue
elif [ "$rdepcnt" -gt 1 ]; then
unset j found
# Check if shlib is provided by multiple pkgs.
for j in ${rdep}; do
# if there's a SONAME matching pkgname, use it.
[ "${j}" != "${pkgname}" ] && continue
found=1
break
done
if [ -n "$found" ]; then
_rdep=$j
else
# otherwise pick up the first one.
for j in ${rdep}; do
[ -z "${_rdep}" ] && _rdep=$j
done
fi
else
_rdep=$rdep
fi
if [ "${_rdep}" != "$pkgname" ]; then
echo " SONAME: $f <-> ${_rdep}"
else
# Ignore libs by current pkg
echo " SONAME: $f <-> ${_rdep} (ignored)"
continue
fi
# Add required shlib to rundeps.
if [ -z "$soname_list" ]; then
soname_list="${f}"
else
soname_list="${soname_list} ${f}"
fi
# Try to remove the line from template
sed -i -r "/^Add_dependency run ${_rdep}([[:space:]]+\".*\")*$/d" $tmplf
if find_rundep ${_rdep}; then
Add_dependency run ${_rdep}
fi
done
#
# If pkg uses any SONAME not known, error out.
#
[ -n "$broken" ] && \
msg_error "$pkgver: cannot guess required shlibs, aborting!\n"
#
# Update package's rshlibs file.
#
unset broken f
msg_normal "$pkgver: updating rshlibs file...\n"
rsonamef=${XBPS_SRCPKGDIR}/${pkgname}/${pkgname}.rshlibs
if [ ! -f $rsonamef ]; then
# file not found, add soname.
for j in ${soname_list}; do
echo " SONAME: $j (added)"
echo "${j}" >> $rsonamef
done
[ -n "$soname_list" ] && broken=1
else
# check if soname is already in the rshlibs file.
for j in ${soname_list}; do
if ! grep -q "$j" $rsonamef; then
echo " SONAME: $j (added)"
echo "$j" >> $rsonamef
broken=1
fi
done
unset f
exec 3<&0 # save stdin
exec < $rsonamef
# now check if any soname in the rshlibs file is unnecessary.
while read f; do
local _soname=$(echo "$f"|awk '{print $1}')
local _soname_arch=$(echo "$f"|awk '{print $2}')
for j in ${soname_list}; do
if [ "${_soname}" = "$j" ]; then
found=1
continue
fi
done
if [ -n "$found" ]; then
unset found
continue
fi
# Sometimes a required SONAME is arch dependent, so
# ignore it in such case.
if [ -n "${_soname_arch}" -a "${_soname_arch}" != "$XBPS_MACHINE" ]; then
continue
fi
# If SONAME is arch specific, only remove it if
# matching on the target arch.
_soname_arch=$(grep "$f" $maplib|awk '{print $4}')
if [ -z "${_soname_arch}" ] || \
[ -n "${_soname_arch}" -a "${_soname_arch}" = "$XBPS_MACHINE" ]; then
echo " SONAME: $f (removed, not required)"
sed -i "/^${_soname}$/d" $rsonamef
broken=1
fi
unset _soname _soname_arch
done
exec 0<&3 # restore stdin
fi
if [ -n "$broken" ]; then
msg_warn "$pkgver: shlibs changed... package has been revbumped!\n"
_rev=$(egrep '^revision=.*' $tmplf)
if [ -n "${_rev}" ]; then
if [ -z "$revbumped" ]; then
readonly newrev=$((${_rev#revision=} + 1))
sed -i "s/^revision=.*$/revision=${newrev}/" $tmplf
export revision=${newrev}
export pkgver="${pkgname}-${version}_${revision}"
revbumped=1
fi
else
if [ -z "$revbumped" ]; then
sed -i "/^short_desc=.*$/irevision=1" $tmplf
export revision=1
export pkgver="${pkgname}-${version}_${revision}"
revbumped=1
fi
fi
fi
}