Skip to content

Instantly share code, notes, and snippets.

@rmg
Created April 18, 2018 01:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rmg/0799e9c78bde43ae6346adf67f36cf20 to your computer and use it in GitHub Desktop.
Save rmg/0799e9c78bde43ae6346adf67f36cf20 to your computer and use it in GitHub Desktop.
Alpine Linux Package Utils
# Print tab-separated details for the given file based on the package that owns it
# Usage:
# awk -v file=/path/to/some/file -f find.awk /lib/apk/db/installed
BEGIN {
# multi-line records, go!
RS=""
# our input fields are lines, but our output is tab-delimited
OFS="\t"
# This is a big long ugly chunk of string manipulation to basically split "/usr/bin/ls" in to ["usr/bin", "ls"]
# There are easier ways to do this in other languages, but I'm not sure if that's the case for awk :-(
ofile = file
while (file ~ /^\//)
file = substr(file, 2)
p = split(file, parts, "/")
dirname = ""
for (i = 0; i <= p; i++) {
if (parts[i] ~ /^\s*$/)
continue
if (i == p)
filename = parts[i]
else
dirname = dirname "/" parts[i]
}
dirname = substr(dirname, 2)
# the trailing \\n is so we do an exact match on the path
# otherwise /usr/bin/foo will match /usr/bin/foobar and /usr/binaries/foo
# This is a side effect of how the package files are recorded in the APK db
dirpat = "F:" dirname "\\n"
filepat = "R:" filename "\\n"
}
# match any record that has both the directory and filename listed for it
$0 ~ dirpat && $0 ~ filepat {
for (i = 0; i < NF; i++)
f[substr($i, 0, 1)] = substr($i, 3)
print f["P"], f["V"], f["U"], f["L"], ofile
}
# Other snippets that came up in the process of poking at this
# The format spec for the APK database file is one of the few things documented:
# https://wiki.alpinelinux.org/wiki/Apk_spec
BEGIN {
RS=""
OFS="\t"
F["name"] = "^P:"
F["version"] = "^V:"
F["license"] = "^L:"
F["url"] = "^U:"
}
function extract(prefix, i, ret) {
for (i = 0; i < NF; i++)
if ($i ~ prefix)
return substr($i, length(prefix))
return ret
}
function rextract(r, i, k) {
for (i = 0; i < NF; i++)
for (k in F)
if ($i ~ F[k])
r[k] = substr($i, length(F[k]))
}
# Extract using the pre-defined F[] array that maps keys to their prefix
{
rextract(x)
print x["name"], x["version"], x["url"], x["license"]
}
# Extract using the custom extract() function
{
name = extract("^P:")
version = extract("^V:")
license = extract("^L:")
url = extract("^U:")
print name, version, url, license
}
# Inline extraction of desired fields by prefix
{
for (i = 0; i < NF; i++) {
if ($i ~ /^P:/)
name = substr($i, 3)
if ($i ~ /^V:/)
version = substr($i, 3)
if ($i ~ /^L:/)
license = substr($i, 3)
if ($i ~ /^U:/)
url = substr($i, 3)
}
print name, version, url, license
}
# Extract all the fields to an array keyed by their prefix code
{
for (i = 0; i < NF; i++)
f[substr($i, 0, 1)] = substr($i, 3)
print f["P"], f["V"], f["U"], f["L"]
}
# Dump tab-separated list of all installed packages
# Usage:
# awk -f packages.awk /lib/apk/db/installed
BEGIN {
RS=""
OFS="\t"
}
# every record
{
for (i = 0; i < NF; i++)
f[substr($i, 0, 1)] = substr($i, 3)
print f["P"], f["V"], f["U"], f["L"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment