SPS · log · files · refs · tags · releases · people · languages · GitHub · file
bin/pkstat
9371 bytes at 2909919 · GitHub
#!/bin/sh
sps_prog=pkstat
sps_bin_dir=$(CDPATH= cd -P "$(dirname "$0")" 2>/dev/null && pwd) || exit 1
if [ -z "${SPS_LIBDIR+x}" ]; then
if [ -r "$sps_bin_dir/../lib/common.sh" ]; then
SPS_LIBDIR=$sps_bin_dir/../lib
else
SPS_LIBDIR=$sps_bin_dir/../lib/sps
fi
fi
if ! . "$SPS_LIBDIR/common.sh"; then
printf '%s\n' "pkstat: cannot load $SPS_LIBDIR/common.sh" >&2
exit 1
fi
sps_load_config || exit $?
sps_usage()
{
cat <<'EOF'
usage: pkstat [PACKAGE]
pkstat --files PACKAGE
pkstat --owns PATH
pkstat --explicit
pkstat --orphans
pkstat --size PACKAGE
pkstat --count
EOF
}
sps_fail()
{
sps_code=$1
shift
printf '%s: %s\n' "$sps_prog" "$*" >&2
exit "$sps_code"
}
sps_target_path()
{
case $SPS_ROOT in
/) sps_target=/$1 ;;
*/) sps_target=$SPS_ROOT$1 ;;
*) sps_target=$SPS_ROOT/$1 ;;
esac
}
sps_require_installed()
{
[ -d "$SPS_DB/installed" ] && [ ! -L "$SPS_DB/installed" ] ||
sps_fail 11 "installed database is missing or is not a real directory"
}
sps_record_for()
{
sps_lookup_name=$1
sps_validate_package_name "$sps_lookup_name" ||
sps_fail 2 "invalid package name '$sps_lookup_name'"
sps_require_installed
sps_record=$SPS_DB/installed/$sps_lookup_name
if [ -L "$sps_record" ]; then
sps_fail 11 "installed record for '$sps_lookup_name' is unsafe"
fi
[ -d "$sps_record" ] || sps_fail 3 "package '$sps_lookup_name' is not installed"
[ -f "$sps_record/meta" ] && [ ! -L "$sps_record/meta" ] ||
sps_fail 11 "installed metadata for '$sps_lookup_name' is missing"
}
sps_summary()
{
sps_summary_name=$1
sps_summary_record=$SPS_DB/installed/$sps_summary_name
sps_summary_id=$(awk -v sps_action=meta-id -v sps_program=pkstat \
-f "$SPS_LIBDIR/package.awk" "$sps_summary_record/meta") ||
sps_fail 11 "installed metadata for '$sps_summary_name' is malformed"
sps_tab=$(printf '\tX')
sps_tab=${sps_tab%X}
sps_saved_ifs=$IFS
IFS=$sps_tab
set -- $sps_summary_id
IFS=$sps_saved_ifs
[ "$#" -eq 4 ] || sps_fail 11 "installed identity for '$sps_summary_name' is malformed"
printf '%s %s-%s %s\n' "$1" "$2" "$3" "$4"
}
sps_installed=$SPS_DB/installed
sps_command=${1-}
case $sps_command in
-h|--help)
sps_usage
exit 0
;;
--files)
[ "$#" -eq 2 ] || { sps_usage >&2; exit 2; }
sps_record_for "$2"
[ -f "$sps_record/files" ] && [ ! -L "$sps_record/files" ] ||
sps_fail 11 "installed manifest for '$2' is missing"
awk -v sps_action=validate-paths -v sps_program=pkstat \
-f "$SPS_LIBDIR/package.awk" "$sps_record/files" ||
sps_fail 11 "installed manifest for '$2' is malformed"
awk '{ print "/" $0 }' "$sps_record/files"
;;
--owns)
[ "$#" -eq 2 ] || { sps_usage >&2; exit 2; }
sps_query=$2
case $SPS_ROOT in
/) case $sps_query in /*) sps_path=${sps_query#/} ;; *) sps_path=$sps_query ;; esac ;;
*)
case $sps_query in
"$SPS_ROOT"/*) sps_path=${sps_query#"$SPS_ROOT"/} ;;
/*) sps_path=${sps_query#/} ;;
*) sps_path=$sps_query ;;
esac
;;
esac
sps_path=${sps_path%/}
[ -n "$sps_path" ] || sps_fail 3 "no package owns the filesystem root"
if ! printf '%s\n' "$sps_path" | awk -v sps_action=validate-paths \
-v sps_program=pkstat -f "$SPS_LIBDIR/package.awk"; then
sps_fail 2 "invalid ownership path '$sps_query'"
fi
[ -f "$SPS_DB/owners" ] && [ ! -L "$SPS_DB/owners" ] ||
sps_fail 11 "ownership database is missing or unsafe"
sps_owner=$(awk -v sps_action=owners-query -v sps_path="$sps_path" \
-v sps_program=pkstat -f "$SPS_LIBDIR/db.awk" "$SPS_DB/owners") ||
sps_fail 11 "ownership database is malformed"
[ -n "$sps_owner" ] || sps_fail 3 "no installed package owns /$sps_path"
sps_summary "$sps_owner"
;;
--explicit)
[ "$#" -eq 1 ] || { sps_usage >&2; exit 2; }
sps_require_installed
[ -f "$SPS_DB/world" ] && [ ! -L "$SPS_DB/world" ] ||
sps_fail 11 "world database is missing or unsafe"
awk -v sps_action=world-validate -v sps_program=pkstat \
-f "$SPS_LIBDIR/db.awk" "$SPS_DB/world" ||
sps_fail 11 "world database is malformed"
while IFS= read -r sps_name || [ -n "$sps_name" ]; do
[ -n "$sps_name" ] || continue
[ -d "$sps_installed/$sps_name" ] ||
sps_fail 11 "explicit package '$sps_name' has no installed record"
sps_summary "$sps_name"
done <"$SPS_DB/world"
;;
--orphans)
[ "$#" -eq 1 ] || { sps_usage >&2; exit 2; }
sps_require_installed
[ -f "$SPS_DB/world" ] && [ ! -L "$SPS_DB/world" ] ||
sps_fail 11 "world database is missing or unsafe"
awk -v sps_action=world-validate -v sps_program=pkstat \
-f "$SPS_LIBDIR/db.awk" "$SPS_DB/world" ||
sps_fail 11 "world database is malformed"
set -- "$sps_installed"/*/meta
[ -f "$1" ] || exit 0
awk -v world="$SPS_DB/world" '
function depname(spec, p) {
p=match(spec, />=|<=|=|>|</)
if (p) spec=substr(spec,1,RSTART-1)
return spec
}
function visit(pkg, k,a) {
if (reachable[pkg]++) return
for (k in edge) {
split(k,a,SUBSEP)
if (a[1] == pkg && (a[2] in installed)) visit(a[2])
}
}
BEGIN {
while ((getline name < world) > 0) if (name != "") root[name]=1
close(world)
}
FNR == 1 {
package=FILENAME
sub(/\/meta$/, "", package)
sub(/^.*\//, "", package)
installed[package]=1
}
{
pos=match($0, /[[:space:]]/)
if (!pos) next
key=substr($0,1,pos-1)
if (key != "depend") next
value=substr($0,pos)
sub(/^[[:space:]]+/, "", value)
gsub(/,/, " ", value)
n=split(value, part, /[[:space:]]+/)
for (i=1;i<=n;i++) {
d=depname(part[i])
if (d != "") edge[package SUBSEP d]=1
}
}
END {
for (package in root) if (package in installed) visit(package)
for (package in installed) if (!(package in reachable)) print package
}
' "$@" | LC_ALL=C sort
;;
--count)
[ "$#" -eq 1 ] || { sps_usage >&2; exit 2; }
sps_count=0
if [ -d "$SPS_DB/installed" ] && [ ! -L "$SPS_DB/installed" ]; then
for sps_record in "$SPS_DB/installed"/*; do
[ -d "$sps_record" ] || continue
[ ! -L "$sps_record" ] || continue
[ -f "$sps_record/meta" ] && [ ! -L "$sps_record/meta" ] || continue
sps_count=$((sps_count + 1))
done
fi
printf '%s\n' "$sps_count"
;;
--size)
[ "$#" -eq 2 ] || { sps_usage >&2; exit 2; }
sps_record_for "$2"
[ -f "$sps_record/files" ] && [ ! -L "$sps_record/files" ] ||
sps_fail 11 "installed manifest for '$2' is missing"
awk -v sps_action=validate-paths -v sps_program=pkstat \
-f "$SPS_LIBDIR/package.awk" "$sps_record/files" ||
sps_fail 11 "installed manifest for '$2' is malformed"
sps_size=0
while IFS= read -r sps_entry || [ -n "$sps_entry" ]; do
case $sps_entry in */) continue ;; esac
sps_target_path "$sps_entry"
if [ -f "$sps_target" ] && [ ! -L "$sps_target" ]; then
sps_bytes=$(wc -c <"$sps_target") || sps_fail 8 "cannot read /$sps_entry"
sps_size=$((sps_size + sps_bytes))
fi
done <"$sps_record/files"
printf '%s %s\n' "$2" "$sps_size"
;;
--*)
sps_usage >&2
exit 2
;;
'')
sps_require_installed
for sps_record in "$sps_installed"/*; do
[ -d "$sps_record" ] || continue
[ ! -L "$sps_record" ] || sps_fail 11 "unsafe installed record '${sps_record##*/}'"
sps_name=${sps_record##*/}
sps_summary "$sps_name"
done
;;
*)
[ "$#" -eq 1 ] || { sps_usage >&2; exit 2; }
sps_record_for "$1"
awk -v sps_action=validate-meta -v sps_program=pkstat \
-f "$SPS_LIBDIR/package.awk" "$sps_record/meta" ||
sps_fail 11 "installed metadata for '$1' is malformed"
awk '
{
pos = match($0, /[[:space:]]/)
if (!pos) { print; next }
key = substr($0, 1, pos - 1)
value = substr($0, pos)
sub(/^[[:space:]]+/, "", value)
printf "%-12s %s\n", key, value
}
' "$sps_record/meta"
;;
esac
exit 0