Files
scratchpkg/revdep
2019-01-28 16:37:52 +08:00

239 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
#
# scratchpkg
#
# Copyright (c) 2018 by Emmett1 (emmett1.2miligrams@gmail.com)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
interrupted() {
cleanup
echo
exit 1
}
cleanup() {
rm -f $FILE_LIST
}
usage() {
cat << EOF
Usage:
$(basename $0) [option] [arg]
Options:
-a, --all print all affected files
-r, --rebuild rebuild & reinstall broken package
-e, --exclude <pkg1 pkg2 pkgN> exclude package when rebuild (use with -r/--rebuild)
-n, --no-confirm dont ask user confirmation to rebuild package (use with -r/--rebuild)
-h, --help print this help message
EOF
}
parse_opt() {
while [ $1 ]; do
case $1 in
-a|--all) PRINTALL=1 ;;
-r|--rebuild) REBUILD=1 ;;
-n|--no-confirm) NOCONFIRM=1 ;;
-e|--exclude) while [ "$2" ]; do
case $2 in
-*) break ;;
*) [ -z "$expkg" ] && expkg="$2" || expkg="$expkg $2"
esac
shift
done ;;
-h|--help) usage; exit 0 ;;
*) echo "Invalid option ($1)"; exit 1 ;;
esac
shift
done
}
rebuild() {
if [[ "$expkg" ]]; then
for broken in $ALLPKG; do
for exclude in $expkg; do
if [ $broken = $exclude ]; then
remove=1
fi
done
if [ "$remove" != 1 ]; then
if [ -z "$needrebuild" ]; then
needrebuild="$broken"
else
needrebuild="$needrebuild $broken"
fi
fi
unset remove
done
else
needrebuild=$ALLPKG
fi
for allpkg in $(pkgdeplist $needrebuild | cut -d ' ' -f2); do
for pkg in $needrebuild; do
if [ $pkg = $allpkg ]; then
if [ -z "$order" ]; then
order="$allpkg"
else
order="$order $allpkg"
fi
break
fi
done
done
if [ "$NOCONFIRM" = "" ]; then
echo
echo "Package will be rebuild & reinstall by this order:"
echo " $order"
echo
echo "Press ENTER to continue"
read
fi
for p in $order; do
scratch build -f $p && scratch install -r $p || { cleanup; exit 1; }
done
}
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
parse_opt $@
if [ "$UID" != 0 ] && [ "$REBUILD" = 1 ]; then
echo "$(basename $0) need to run as root to rebuild & reinstall package"
exit 1
fi
while read line; do
if [[ $(echo ${line::1}) = "/" ]]; then
EXTRA_SEARCH_DIRS+="$line "
fi
done < /etc/ld.so.conf
if [ -d /etc/ld.so.conf.d/ ]; then
for dir in $(ls /etc/ld.so.conf.d/); do
while read line; do
if [[ $(echo ${line::1}) = "/" ]]; then
EXTRA_SEARCH_DIRS+="$line "
fi
done < /etc/ld.so.conf.d/$dir
done
fi
# excluded dirs
EXCLUDE_DIRS="$(cat /etc/revdep.conf 2>/dev/null | grep /$ | sed 's/\/*$//g')"
EXCLUDE_DIRS+=" $(cat /etc/revdep.d/*.conf 2>/dev/null | grep /$ | sed 's/\/*$//g')"
for d in $EXCLUDE_DIRS; do
EXCLUDED_DIRS+="-path $d -prune -o "
done
# excluded files
EXCLUDE_FILES="$(cat /etc/revdep.conf 2>/dev/null | grep -v /$)"
EXCLUDE_FILES+=" $(cat /etc/revdep.d/*.conf 2>/dev/null | grep -v /$)"
for f in $EXCLUDE_FILES; do
EXCLUDED_FILES+="! -path $f "
done
# search dirs
TARGET_SEARCH_DIRS="/bin /usr/bin /sbin /usr/sbin /lib /usr/lib /lib64 /usr/libexec $EXTRA_SEARCH_DIRS"
INDEX_DIR="/var/lib/scratchpkg/index"
FILE_LIST=$(mktemp) || { echo "Can't create temporary file .Aborting..."; exit 1; }
echo "SEARCH DIRS:"
for d in $TARGET_SEARCH_DIRS; do
if [ -d $d ]; then
SEARCH_DIRS+=" $d"
echo " $d"
fi
done
echo
echo "EXCLUDED DIRS:"
for dd in $EXCLUDE_DIRS; do
echo " $dd"
done
echo
echo "EXCLUDED FILES:"
for dd in $EXCLUDE_FILES; do
echo " $dd"
done
echo
echo -n "Find all files... "
find ${SEARCH_DIRS[@]} $EXCLUDED_DIRS $EXCLUDED_FILES -type f \( -perm /+u+x -o -name '*.so' -o -name '*.so.*' \) -print 2> /dev/null | sort -u > $FILE_LIST
total=$(cat $FILE_LIST | wc -l)
count=0
echo "$total files found"
echo "Checking for broken linkage..."
while IFS=' ' read -r line; do
count=$(( $count + 1 ))
libname=$(basename "$line")
echo -ne " $(( 100*$count/$total ))% $libname\033[0K\r"
case "$(file -bi "$line")" in
*application/x-sharedlib* | *application/x-executable* | *application/x-pie-executable*)
if [ "$(ldd $line 2>/dev/null | grep "not found")" ]; then
LIB_NAME=$(ldd $line 2>/dev/null | grep "not found" | sort | uniq | awk '{print $1}')
line2=$(echo $line | sed 's#^/##')
PKG_NAME=$(grep -Rx $line2 $INDEX_DIR | cut -d : -f1)
[[ $PKG_NAME ]] || continue
PKG_NAME=$(dirname $(echo $PKG_NAME))
PKG_NAME=$(basename $(echo $PKG_NAME))
REQ_LIB=$(objdump -p $line 2>/dev/null | grep NEEDED | awk '{print $2}' | tr '\n' ' ')
LIB=$(echo $LIB_NAME | tr '\n' ' ')
for i in $LIB_NAME; do
[ "$PRINTALL" = 1 ] && echo -e " $PKG_NAME -> $line (requires $i)"
if echo $REQ_LIB | tr ' ' '\n' | grep -qx $i; then
[ "$PRINTALL" = 1 ] || echo -e " $PKG_NAME -> $line (requires $i)"
if [[ "$(echo ${ALLPKG[@]} | tr ' ' '\n' | grep -x "$PKG_NAME")" ]]; then
continue
else
ALLPKG+="$PKG_NAME "
fi
fi
done
fi
;;
esac
done < $FILE_LIST
echo -ne "\033[0K"
if [ "$ALLPKG" ]; then
echo
echo "This package(s) requires rebuild:"
for rebuild in $ALLPKG; do
echo -e " $rebuild"
done
if [ "$REBUILD" = 1 ]; then
rebuild
fi
else
echo "All packages is doing fine."
fi
cleanup
exit 0