Detecting user installed pkgs

I finally remembered this thread, here's a rewrite of the script I did a few weeks back and a couple notes.

The opkg whatdepends x command computes the transitive closure of dependencies, so you get not just those packages that depend directly on x, but those packages that depend on the packages that depend on the packages... You get the idea, try opkg whatdepends terminfo for an example. As you've probably already guessed, this is phenomenally slow.

All of the information about packages is in /usr/lib/opkg/info/, with the *.control files being the most interesting. This is where opkg subcommands look for any information about installed packages, and you can just ls that directory and see what is installed.

Replacing whatdepends with appropriate grep + awk drops run time of the script from ~180+ seconds to ~5 seconds on my edge router (an apu2 x86), but it changes the dependency count reported on many of the non-top-level packages (i.e., those with zero dependencies), because it skips the transitivity search. If you can live with that, you can save some CPU cycles.

Also of note is that there is an alias-like (or maybe more symbolic-link-like?) thing that opkg supports. You can see it with grep 'Provides:' /usr/lib/opkg/info/*.control. It's easy to see it in action with the packages dnsmasq and dnsmasq-full, where the 'Provides:' field in both says (duh) dnsmasq. The opkg subcommands parse through these and make sure to do the right thing, whereas my script sometimes sticks in both the "real" package name and an alias for it in the output.

This manifests as some packages being reported as "top-level" even though they are not (for example, you'll see firewall4 reported as a top-level package, when in fact it "supplies" uci-firewall, which has a bunch of dependents). So far, I've only seen firewall4 and tc-tiny reported this way, and anyway these false positives won't break anything, they're just annoying.

Enough of my blah blah blah, here's the script.

#!/bin/sh
# vim: set expandtab softtabstop=4 shiftwidth=4:
#-------------------------------------------------------------------------------

log_all=false  # Log everything, or just those with count == 0.

package_list=./installed-packages
rm -f $package_list

examined=0
for pkg in $(opkg list-installed | awk '{print $1}') ; do
    examined=$((examined + 1))
    printf '%5d - %-40s\r' "$examined" "$pkg"
    #deps=$(opkg whatdepends "$pkg" | awk '/^\t/{printf $1" "}')
    deps=$(
        cd /usr/lib/opkg/info/ &&
        grep -lE "Depends:.* ${pkg}([, ].*|)$" -- *.control | awk -F'\.control' '{printf $1" "}'
    )
    count=$(echo "$deps" | wc -w)
    if $log_all || [ "$count" -eq 0 ] ; then
        printf '%d\t%s\t%s\n' "$count" "$pkg" "$deps" >> $package_list
    fi
done

n_logged=$(wc -l < $package_list)
printf 'Done, logged %d of %d entries\n' "$n_logged" "$examined"
1 Like