418 lines
12 KiB
Plaintext
418 lines
12 KiB
Plaintext
|
#!/bin/bash
|
||
|
#
|
||
|
# prtwash - a simple bash script for cleaning the port tree
|
||
|
# of the CRUX Linux distribution.
|
||
|
#
|
||
|
# Copyright (c) 2003 by Simone Rota <sip@varlock.com>
|
||
|
# Revised 2021 by John McQuah <jmcquah@disroot.org>
|
||
|
#
|
||
|
# *************************************************************************
|
||
|
# * *
|
||
|
# * 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 2 of the License, or *
|
||
|
# * (at your option) any later version. *
|
||
|
# * *
|
||
|
# *************************************************************************
|
||
|
#
|
||
|
# Took some inspiration and code from Martin Opel's prtsweep v1.6 script,
|
||
|
# and comments by therealfun on FlySpray bug 1851.
|
||
|
#
|
||
|
# **** USE AT YOUR OWN RISK ****
|
||
|
#
|
||
|
# TODO
|
||
|
# - a summary of files / bytes removed after the
|
||
|
# execution would be useful.
|
||
|
# - verify signatures before sourcing each Pkgfile.
|
||
|
#
|
||
|
|
||
|
VERSION="0.9"
|
||
|
|
||
|
usage() {
|
||
|
echo "Usage: prtwash [-p] [-s] [-d] [-t] [-a] <path> [<path> ...]"
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
showversion() {
|
||
|
echo "prtwash" $VERSION
|
||
|
echo "(c) 2003 by Simone Rota, revised 2021 by John McQuah"
|
||
|
echo "This program is distributed under the GNU GPL license"
|
||
|
}
|
||
|
|
||
|
interrupted() {
|
||
|
echo "=======> operation interrupted."
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
checkparams() {
|
||
|
# Do some test on given parameters.
|
||
|
if [ "$auto" = "0" ]; then
|
||
|
|
||
|
if [ -z "$prtdirs" ]; then
|
||
|
usage
|
||
|
exit -1
|
||
|
fi
|
||
|
|
||
|
for (( p=0 ; p<=${#prtdirs[@]} ; p++ )); do
|
||
|
|
||
|
if [ -z "${prtdirs[$p]}" ]; then
|
||
|
unset prtdirs[$p]
|
||
|
continue
|
||
|
fi
|
||
|
|
||
|
if [ ! -d "${prtdirs[$p]}" ]; then
|
||
|
echo "WARN: '${prtdirs[$p]}' is not the directory for a port. Skipping."
|
||
|
unset prtdirs[$p]
|
||
|
continue
|
||
|
fi
|
||
|
|
||
|
if [ ! -f "${prtdirs[$p]}"/Pkgfile ]; then
|
||
|
echo "WARN: no Pkgfile found in '${prtdirs[$p]}'. Skipping."
|
||
|
unset prtdirs[$p]
|
||
|
fi
|
||
|
done
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
getoptions () {
|
||
|
# Name says it all.
|
||
|
while getopts bpsdathv opt; do
|
||
|
case "$opt" in
|
||
|
b) removeoldbuilds=1;;
|
||
|
p) removepackage=1;;
|
||
|
s) removesources=1;;
|
||
|
d) removeaddonfiles=1;;
|
||
|
t) test=1;;
|
||
|
a) auto=1;;
|
||
|
h) usage
|
||
|
exit 0
|
||
|
;;
|
||
|
v) showversion
|
||
|
exit 0
|
||
|
;;
|
||
|
\?) usage
|
||
|
exit -1
|
||
|
;;
|
||
|
esac
|
||
|
done
|
||
|
shift $(($OPTIND - 1))
|
||
|
prtdirs=("$@")
|
||
|
}
|
||
|
|
||
|
getdirs() {
|
||
|
# scans /etc/prt-get.conf for port dirs to process
|
||
|
current=""
|
||
|
for s in `sed 's/^[ \t]*//;s/[ \t]*$//' \
|
||
|
$CONF_PGET|grep '^prtdir.*:'|sed 's/:/ /;s/,/ /;s/prtdir//;s/#.*//'`
|
||
|
do
|
||
|
if [ "`echo $s|grep '/'`" != "" ]; then
|
||
|
current=$s
|
||
|
else
|
||
|
if [ "$current" != "" ]; then
|
||
|
singledirs=(${singledirs[*]} $current/$s)
|
||
|
fi
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
for s in `sed 's/^[ \t]*//;s/[ \t]*$//;/:/d' \
|
||
|
$CONF_PGET|grep '^prtdir.*'|sed 's/prtdir//;s/#.*//'`
|
||
|
do
|
||
|
basedirs=(${basedirs[*]} $s)
|
||
|
done
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
remove() {
|
||
|
# Removes a file/directory
|
||
|
if [ "$test" = 1 ]; then
|
||
|
echo "+ (t) removing" $1
|
||
|
else
|
||
|
echo "+ removing" $1
|
||
|
rm -r $1
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
swash() {
|
||
|
# There are faster and safer ways of cleaning a directory shared among all ports than
|
||
|
# to iterate through the ports collection itself.
|
||
|
# Inform the admin that this script is ill-suited for their configuration.
|
||
|
echo "It looks like you have defined common directories for downloads or packages." >&2
|
||
|
echo "For such a configuration, this script is slower and less reliable" >&2
|
||
|
echo "than a custom tool would be." >&2
|
||
|
echo "If you intended to clean out your ports repositories instead," >&2
|
||
|
echo "consider the companion tool prtsweep." >&2
|
||
|
echo "Proceed anyway? (y/n)" >&2
|
||
|
read CONFIRM
|
||
|
if [ "$CONFIRM" != "y" ]; then
|
||
|
exit 0
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
finalwarning() {
|
||
|
echo "Last chance to bail out!" >&2
|
||
|
echo "This script will remove from the common download directories more files " >&2
|
||
|
echo "than perhaps you intended." >&2
|
||
|
echo "Proceed anyway? (y/n)" >&2
|
||
|
read CONFIRM
|
||
|
if [ "$CONFIRM" != "y" ]; then
|
||
|
exit 0
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
nwash() {
|
||
|
if [ "$auto" = 0 ]; then
|
||
|
|
||
|
for p in ${prtdirs[@]}; do
|
||
|
echo "Washing the directory of port $p:"
|
||
|
wash $p
|
||
|
done
|
||
|
|
||
|
exit 0
|
||
|
else
|
||
|
|
||
|
if [ ! -f "$CONF_PGET" ]; then
|
||
|
echo "ERROR: cannot find configuration file '$CONF_PGET'"
|
||
|
exit -1
|
||
|
fi
|
||
|
echo "Analyzing port tree..."
|
||
|
|
||
|
getdirs
|
||
|
|
||
|
# wash base dirs
|
||
|
for d in ${basedirs[*]}; do
|
||
|
if [ -d "$d" ]; then
|
||
|
for p in "$d"/*; do
|
||
|
if [ -d "$p" ]; then
|
||
|
wash $p
|
||
|
fi
|
||
|
done
|
||
|
else
|
||
|
echo "ERROR: directory '$d' not found, check your configuration file!"
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
# wash custom dirs (see prt-get.conf)
|
||
|
for p in ${singledirs[*]}; do
|
||
|
if [ -d "$p" ]; then
|
||
|
wash $p
|
||
|
else
|
||
|
echo "ERROR: directory '$p' not found, check your configuration file!"
|
||
|
fi
|
||
|
done
|
||
|
exit 0
|
||
|
fi
|
||
|
exit 0
|
||
|
}
|
||
|
|
||
|
wash() {
|
||
|
# Does the actual removal work.
|
||
|
local tosave name version source renames pkgfiles packagename portname SAVELOC PKGLOC
|
||
|
local dir=$1
|
||
|
if [ ! -f "$dir"/Pkgfile ]; then
|
||
|
# tested before, the test here is for
|
||
|
# auto (-a) command
|
||
|
echo "WARN: no Pkgfile found in $dir. Skipping."
|
||
|
else
|
||
|
declare -a tosave # array of files not to be deleted
|
||
|
pkgfiles=(`( . $dir/Pkgfile; PKGLOC=$(eval "printf '%s' $PKGGLOB"); \
|
||
|
PKGFILE=$(eval "printf '%s' $BLTGLOB"); \
|
||
|
SAVELOC=$(eval "printf '%s' $SRCGLOB"); \
|
||
|
for (( p=0; p<${#source[@]}; p++ )); do \
|
||
|
[ -n "${renames[$p]}" -a "${renames[$p]}" != "SKIP" ] && source[$p]="ftp://host/${renames[$p]}"; \
|
||
|
done; \
|
||
|
printf '%s ' "${SAVELOC:-$dir}"; \
|
||
|
printf '%s ' "${PKGLOC:-$dir}/$PKGFILE"; \
|
||
|
printf '%s ' "${source[@]}")`)
|
||
|
|
||
|
SAVELOC=${pkgfiles[0]}
|
||
|
packagename=`basename ${pkgfiles[1]}`
|
||
|
PKGLOC=`dirname ${pkgfiles[1]}`
|
||
|
|
||
|
# keep sources
|
||
|
if [ "$removesources" = 0 ]; then
|
||
|
for (( p=2; p<${#pkgfiles[@]}; p++ )) ; do
|
||
|
tosave=( "${tosave[@]}" `get_filename "${pkgfiles[$p]}"` )
|
||
|
done
|
||
|
fi
|
||
|
|
||
|
# new in version 0.3 we (try to) always save files that are
|
||
|
# retrieved by rsync/httpup (non http(s) or ftp in source)
|
||
|
# ie patches, etc. These can be deleted with -d (extra files)
|
||
|
# option
|
||
|
if [ "$removesources" = 1 ] && [ "$removeaddonfiles" = 0 ]; then
|
||
|
for (( p=2; p<${#pkgfiles[@]}; p++ )) ; do
|
||
|
src="${pkgfiles[$p]}"
|
||
|
pkgfiles[$p]=$(get_filename $src)
|
||
|
[ "${src:0:7}" = "ftp://" \
|
||
|
-o "${src:0:8}" = "http://" \
|
||
|
-o "${src:0:6}" = "https://" ] ||
|
||
|
tosave=( "${tosave[@]}" "${pkgfiles[$p]}" )
|
||
|
done
|
||
|
fi
|
||
|
|
||
|
# Now that the distinction between files obtained via rsync/httpup
|
||
|
# and files downloaded during `pkgmk -d` has been encoded in the
|
||
|
# array $tosave, clean up the filenames in the $pkgfiles array.
|
||
|
if [ "$removesources" = 0 ] || [ "$removeaddonfiles" = 1 ]; then
|
||
|
for (( p=2; p<${#pkgfiles[@]}; p++ )) ; do
|
||
|
pkgfiles[$p]=$(get_filename ${pkgfiles[$p]})
|
||
|
done
|
||
|
fi
|
||
|
|
||
|
if [ ! "$removepackage" = 1 ]; then
|
||
|
# keep package
|
||
|
tosave=( "${tosave[@]}" "$packagename" )
|
||
|
fi
|
||
|
|
||
|
if [ ! "$removeaddonfiles" = 1 ]; then
|
||
|
# keep additional and dot files
|
||
|
tosave=( "${tosave[@]}" \
|
||
|
".signature" \
|
||
|
".32bit" \
|
||
|
".footprint" \
|
||
|
".nostrip" \
|
||
|
"README" \
|
||
|
"FAQ" \
|
||
|
"pre-install" \
|
||
|
"post-install" )
|
||
|
fi
|
||
|
|
||
|
# keep Pkgfile. We always want to keep this nice funny file.
|
||
|
tosave=( "${tosave[@]}" "Pkgfile" )
|
||
|
|
||
|
unset pkgfiles[0] pkgfiles[1]
|
||
|
|
||
|
# trust that our parsing of the Pkgfile has not set the wrong source directory.
|
||
|
# But if an absolute path is specified, restrict the `ls -A` output
|
||
|
# to avoid overzealous deletions.
|
||
|
cd $SAVELOC
|
||
|
if [ "${SAVELOC:0:1}" != "/" ]; then
|
||
|
for f in `ls -A`; do
|
||
|
keep $f || remove $f
|
||
|
done
|
||
|
elif [ ${#pkgfiles[@]} -gt 0 ]; then
|
||
|
for f in ${pkgfiles[@]}; do
|
||
|
for match in `ls -A ${f}* 2>/dev/null`; do
|
||
|
keep $match || remove $match
|
||
|
done
|
||
|
done
|
||
|
fi
|
||
|
cd - &>/dev/null
|
||
|
|
||
|
# same trust as to the location of the built packages, if different from SAVELOC.
|
||
|
# Older versions can be discarded too, if $removeoldbuilds = 1.
|
||
|
if [ "$removepackage" = 1 ]; then
|
||
|
(cd $PKGLOC; [ -f $packagename ] && keep "$packagename" || remove "$packagename")
|
||
|
fi
|
||
|
|
||
|
if [ "$removeoldbuilds" = 1 ]; then
|
||
|
portname=$(echo "$packagename" | sed 's/#.*//')
|
||
|
(cd $PKGLOC; for f in `ls ${portname}*.pkg.tar.[bgx]z* 2>/dev/null`; do keep $f || remove $f; done)
|
||
|
fi
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
keep() {
|
||
|
# Checks if filename item is in tosave[] array
|
||
|
# return 0 if present, 1 if not.
|
||
|
item=$1
|
||
|
local excode
|
||
|
excode=1 # assume not in the array until proven otherwise
|
||
|
|
||
|
for i in "${tosave[@]}"; do
|
||
|
if [ "$i" = "$item" ]; then
|
||
|
[ "$test" = "1" ] && echo "= (t) ... keeping $item" || echo "= ... keeping $item"
|
||
|
excode=0
|
||
|
break
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
return $excode
|
||
|
}
|
||
|
|
||
|
get_filename() {
|
||
|
if [[ $1 =~ ^(http|https|ftp|file)://.*/(.+) ]]; then
|
||
|
echo "${BASH_REMATCH[2]}"
|
||
|
else
|
||
|
echo $1
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
printparams() {
|
||
|
echo "removepackage: $removepackage"
|
||
|
echo "removeoldbuilds: $removeoldbuilds"
|
||
|
echo "removesources: $removesources"
|
||
|
echo "removeaddonfiles: $removeaddonfiles"
|
||
|
echo "auto: $auto"
|
||
|
echo "test: $test"
|
||
|
}
|
||
|
|
||
|
|
||
|
###################################################
|
||
|
# Main
|
||
|
###################################################
|
||
|
|
||
|
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
|
||
|
|
||
|
if [ $# -lt 1 ]; then
|
||
|
usage
|
||
|
exit -1
|
||
|
fi
|
||
|
|
||
|
removepackage=0
|
||
|
removesources=0
|
||
|
removeaddonfiles=0
|
||
|
removeoldbuilds=0
|
||
|
test=0
|
||
|
auto=0
|
||
|
basedirs=()
|
||
|
singledirs=()
|
||
|
prtdirs=()
|
||
|
|
||
|
CONF_PGET="/etc/prt-get.conf"
|
||
|
CONF_PMK="/etc/pkgmk.conf"
|
||
|
|
||
|
getoptions $@
|
||
|
checkparams $@
|
||
|
|
||
|
COMPRESSION_MODE="gz"
|
||
|
if [ -f $PKGCONFIG ]; then
|
||
|
COMPRESS_CFG=$(grep "PKGMK_COMPRESSION_MODE" $CONF_PMK | \
|
||
|
sed 's/[\t w]*#.*//;s/.*=//;s/\"//g')
|
||
|
[ -n "$COMPRESS_CFG" ] && COMPRESSION_MODE=$COMPRESS_CFG
|
||
|
SRCGLOB=$(grep "PKGMK_SOURCE_DIR" $CONF_PMK | sed 's/[\t w]*#.*//; s/.*=//; s/\"//g')
|
||
|
PKGGLOB=$(grep "PKGMK_PACKAGE_DIR" $CONF_PMK | sed 's/[\t w]*#.*//; s/.*=//; s/\"//g')
|
||
|
fi
|
||
|
|
||
|
BLTGLOB='$name#$version-$release.pkg.tar.$COMPRESSION_MODE'
|
||
|
|
||
|
# First determine the type of fs layout the admin configured for source downloads.
|
||
|
# Layouts 1 and 2: at least one directory is shared among all ports (for sources or built packages),
|
||
|
# or the admin has organized downloads in some other way outside of $PORTS_ROOT.
|
||
|
|
||
|
if [ -n "${SRCGLOB}" ] && echo "${SRCGLOB}" | grep -q -v '\$name'; then
|
||
|
swash
|
||
|
nwash
|
||
|
elif [ -n "${PKGGLOB}" ] && echo "${PKGGLOB}" | grep -q -v '\$name'; then
|
||
|
swash
|
||
|
nwash
|
||
|
fi
|
||
|
|
||
|
# Layout 3: separate directories, named according to port, are potentially cluttered with downloads.
|
||
|
# Unlike prtsweep, actually try to follow these dynamically-defined paths and clean them up.
|
||
|
# $PORTS_ROOT might still remain cluttered after this "wash", but the admin can just run prtsweep.
|
||
|
# For such filesystem layouts, the two scripts complement each other nicely.
|
||
|
if [ -z "${SRCGLOB}" -o -z "${PKGGLOB}" ]; then
|
||
|
nwash
|
||
|
elif [ -n "${SRCGLOB}" ] && echo "$SRCGLOB" | grep -q '\$name'; then
|
||
|
nwash
|
||
|
elif [ -n "${PKGGLOB}" ] && echo "$PKGGLOB" | grep -q '\$name'; then
|
||
|
nwash
|
||
|
else
|
||
|
# Should have exited by now, but if not,
|
||
|
# offer another chance to abort.
|
||
|
finalwarning
|
||
|
nwash
|
||
|
fi
|