mirror of
https://github.com/outbackdingo/scratchpkg.git
synced 2026-02-05 08:28:00 +00:00
305 lines
7.4 KiB
Bash
Executable File
305 lines
7.4 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
|
|
-p, --package <pkg> check for certain package
|
|
-f, --no-filter skip filter (exclude) dirs, files and libraries
|
|
-e, --exclude <pkg1 pkg2 pkgN> exclude package when rebuild (use with -r/--rebuild)
|
|
-y, --yes dont ask user confirmation to rebuild package (use with -r/--rebuild)
|
|
-h, --help print this help message
|
|
|
|
EOF
|
|
}
|
|
|
|
confirm() {
|
|
read -r -p "$1 (Y/n) " response
|
|
case "$response" in
|
|
[Nn][Oo]|[Nn]) echo "$2"; exit 2 ;;
|
|
*) : ;;
|
|
esac
|
|
}
|
|
|
|
parse_opt() {
|
|
while [ $1 ]; do
|
|
case $1 in
|
|
-a|--all) PRINTALL=1 ;;
|
|
-r|--rebuild) REBUILD=1 ;;
|
|
-y|--yes) NOCONFIRM=1 ;;
|
|
-f|--no-filter) NO_FILTER=1 ;;
|
|
-e|--exclude) while [ "$2" ]; do
|
|
case $2 in
|
|
-*) break ;;
|
|
*) [ -z "$expkg" ] && expkg="$2" || expkg="$expkg $2"
|
|
esac
|
|
shift
|
|
done ;;
|
|
-p|--package) PKG=$2; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Invalid option ($1)"; exit 1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
rebuild() {
|
|
for allpkg in $(pkgdeplist -l -i $ALLPKG | cut -d ' ' -f2); do
|
|
for pkg in $ALLPKG; do
|
|
if [ $pkg = $allpkg ]; then
|
|
if [ -z "$order" ]; then
|
|
order="$allpkg"
|
|
else
|
|
order="$order $allpkg"
|
|
fi
|
|
break
|
|
fi
|
|
done
|
|
done
|
|
if [ -n "$order" ]; then
|
|
if [ "$NOCONFIRM" = "" ]; then
|
|
echo
|
|
echo "Package will be rebuild & reinstall by this order:"
|
|
echo " $order"
|
|
echo
|
|
confirm "Continue rebuild & reinstall broken packages?" "Operation cancelled."
|
|
fi
|
|
for p in $order; do
|
|
scratch build -f $p && scratch install -r $p || { cleanup; exit 1; }
|
|
done
|
|
fi
|
|
}
|
|
|
|
rev_exclude() {
|
|
# excluded dirs
|
|
EXCLUDE_DIRS="$(grep -v ^# /etc/revdep.conf 2>/dev/null | grep /$ | uniq | sed 's/\/*$//g')"
|
|
EXCLUDE_DIRS+=" $(grep -v ^# /etc/revdep.d/*.conf 2>/dev/null | cut -d : -f2 | grep /$ | uniq | sed 's/\/*$//g')"
|
|
|
|
for dd in $EXCLUDE_DIRS; do
|
|
if [ -d $dd ]; then
|
|
_DIRS+=" $dd"
|
|
ged="$ged -e ^$dd"
|
|
fi
|
|
done
|
|
|
|
EXCLUDE_DIRS=$(echo $_DIRS | tr ' ' '\n' | sort | uniq)
|
|
|
|
for d in $EXCLUDE_DIRS; do
|
|
EXCLUDED_DIRS+="-path $d -prune -o "
|
|
done
|
|
|
|
# excluded files
|
|
EXCLUDE_FILES="$(grep -v ^# /etc/revdep.conf 2>/dev/null | grep -v /$ | grep ^/)"
|
|
EXCLUDE_FILES+=" $(grep -v ^# /etc/revdep.d/*.conf 2>/dev/null | cut -d : -f2 | grep -v /$ | grep ^/)"
|
|
|
|
for ff in $EXCLUDE_FILES; do
|
|
if [ -f $ff ]; then
|
|
_FILES+=" $ff"
|
|
gef="$gef -e ^$ff$"
|
|
fi
|
|
done
|
|
|
|
EXCLUDE_FILES=$(echo $_FILES | tr ' ' '\n' | sort | uniq)
|
|
|
|
for f in $EXCLUDE_FILES; do
|
|
EXCLUDED_FILES+="! -path $f "
|
|
done
|
|
|
|
# excluded libraries
|
|
EXCLUDE_LIBS="$(grep -v ^# /etc/revdep.conf 2>/dev/null | grep -v ^/ | uniq | grep ".*.so.*")"
|
|
EXCLUDE_LIBS+=" $(grep -v ^# /etc/revdep.d/*.conf 2>/dev/null | cut -d : -f2 | grep -v ^/ | uniq | grep ".*.so.*")"
|
|
|
|
EXCLUDED_LIBS=$(echo $EXCLUDE_LIBS | tr ' ' '\n' | sort | uniq)
|
|
}
|
|
|
|
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
|
|
|
|
# package database directory
|
|
INDEX_DIR="/var/lib/scratchpkg/index"
|
|
SEARCH_DIRS="/bin /usr/bin /sbin /usr/sbin /lib /usr/lib /lib64 /usr/lib64 /usr/libexec"
|
|
|
|
parse_opt $@
|
|
|
|
if [ "$UID" != 0 ] && [ "$REBUILD" = 1 ]; then
|
|
echo "$(basename $0) need to run as root to rebuild & reinstall package"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$PKG" ] && [ ! -f "$INDEX_DIR/$PKG/.files" ]; then
|
|
echo "ERROR: Package '$PKG' not installed"
|
|
cleanup
|
|
exit 1
|
|
fi
|
|
|
|
# get search extra dirs
|
|
while read -r line; do
|
|
if [[ "${line::1}" = "/" ]]; then
|
|
EXTRA_SEARCH_DIRS+="$line "
|
|
fi
|
|
done < /etc/ld.so.conf
|
|
|
|
if [ -d /etc/ld.so.conf.d/ ]; then
|
|
for dir in /etc/ld.so.conf.d/*.conf; do
|
|
while read -r line; do
|
|
if [[ "${line::1}" = "/" ]]; then
|
|
EXTRA_SEARCH_DIRS+="$line "
|
|
fi
|
|
done < $dir
|
|
done
|
|
fi
|
|
|
|
if [ "$NO_FILTER" != 1 ]; then
|
|
rev_exclude
|
|
fi
|
|
|
|
# search dirs
|
|
TARGET_SEARCH_DIRS="$SEARCH_DIRS $EXTRA_SEARCH_DIRS"
|
|
|
|
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 ff in $EXCLUDE_FILES; do
|
|
echo " $ff"
|
|
done
|
|
echo
|
|
|
|
echo "EXCLUDED LIBS:"
|
|
for ll in $EXCLUDED_LIBS; do
|
|
echo " $ll"
|
|
done
|
|
echo
|
|
|
|
if [ "$PKG" ]; then
|
|
for D in $TARGET_SEARCH_DIRS; do
|
|
gx="$gx -e ^$D"
|
|
done
|
|
gx="$gx -e *\.so -e *\.so\.*"
|
|
if [ -n "$gef" ]; then
|
|
filterfile="grep -v $gef"
|
|
else
|
|
filterfile=cat
|
|
fi
|
|
if [ -n "$ged" ]; then
|
|
filterdir="grep -v $ged"
|
|
else
|
|
filterdir=cat
|
|
fi
|
|
echo -n "Find '$PKG' files... "
|
|
sed 's/^/\//' $INDEX_DIR/$PKG/.files | grep $gx | $filterfile | $filterdir > $FILE_LIST
|
|
else
|
|
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
|
|
fi
|
|
|
|
total=$(wc -l $FILE_LIST | awk '{print $1}')
|
|
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 -q "not found"; then
|
|
LIB_NAME=$(ldd $line 2>/dev/null | grep "not found" | sort | uniq | awk '{print $1}')
|
|
for l in $LIB_NAME; do
|
|
if ! echo $EXCLUDED_LIBS | grep -qw $l; then
|
|
NEW_LIB_NAME+=" $l"
|
|
fi
|
|
done
|
|
LIB_NAME=$NEW_LIB_NAME
|
|
[[ $LIB_NAME ]] || continue
|
|
PKG_NAME=$(echo $line | sed 's#^/##')
|
|
PKG_NAME=$(grep -Rx $PKG_NAME "$INDEX_DIR"/*/.files | cut -d : -f1)
|
|
[[ $PKG_NAME ]] || continue
|
|
PKG_NAME=$(dirname $PKG_NAME)
|
|
PKG_NAME=$(basename $PKG_NAME)
|
|
echo $expkg | tr ' ' '\n' | grep -qx $PKG_NAME && continue
|
|
REQ_LIB=$(objdump -p $line 2>/dev/null | grep NEEDED | awk '{print $2}' | 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 -qx "$PKG_NAME"; then
|
|
continue
|
|
else
|
|
ALLPKG+="$PKG_NAME "
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
;;
|
|
esac
|
|
unset NEW_LIB_NAME
|
|
done < $FILE_LIST
|
|
|
|
echo -ne "\033[0K"
|
|
|
|
if [ "$ALLPKG" ]; then
|
|
echo
|
|
echo "Broken package(s):"
|
|
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
|