kernel-srpm-macros/modalias.prov
Denys Vlasenko 35e1f2fc73 modalias.prov: speed up, explain and make more correct combining code
The time to run on tests/* data decreased from 34.517s to 30.201s.

Do not allow combining of any glob meta characters, either in first
or second line.

The code is still buggy, it may attempt to combine
    modalias(abc[def]123)
    modalias(abc[dXf]123)
into
    modalias(abc[d[eX]f]123)
(presumably there won't be any such cases in real modules, but still).

Eliminate "| head -n1" - do it with bash string ops.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2023-05-07 17:49:24 +02:00

126 lines
4.3 KiB
Bash
Executable File

#! /bin/bash -efu
# heavily based upon find-suggests.ksyms by Andreas Gruenbacher <agruen@suse.de>.
# with modifications by Michael Brown <Michael_E_Brown@dell.com>
#
# -- added module versioning info to modalias() symbols
# -- removed code which inspects spec files.
IFS=$'\n'
#
# Initially, dont generate modalias() lines for kernel package. This needs
# additional discussion. Would like to eventually add them for
# completeness, so that we can determine when drivers are folded into
# mainline kernel.
#
is_kernel_package=""
case "${1:-}" in
kernel-module-*) ;; # Fedora kernel module package names start with
# kernel-module.
kernel*) is_kernel_package=1 ;;
esac
if ! [ -z "$is_kernel_package" ]; then
cat > /dev/null
exit 0
fi
# Check for presence of the commands used.
# "command" is a builtin, faster to use than fork+execing "which" - see
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html
command -v /sbin/modinfo >/dev/null || exit 1
command -v sed >/dev/null || exit 1
command -v sort >/dev/null || exit 1
print_modaliases() {
local class="$1" variants="$2" pos="$3"
if [ -n "$variants" ]; then
echo "${class:0:pos}[$variants]${class:pos+1}"
else
[ -z "$class" ] || echo "$class"
fi
}
# Try to make "provides" list a bit smaller:
# find "mergeable" strings a-la
# modalias(pci:v0000168Cd00000023sv*sd*bc*sc*i*)
# modalias(pci:v0000168Cd00000024sv*sd*bc*sc*i*)
# modalias(pci:v0000168Cd00000027sv*sd*bc*sc*i*)
# modalias(pci:v0000168Cd00000029sv*sd*bc*sc*i*)
# replace with
# modalias(pci:v0000168Cd0000002[3479]sv*sd*bc*sc*i*)
combine_modaliases() {
local unused_len tag class variants="" pos="" n end xc
# Due to set -e, we can exit with exitcode 1 on read EOF
# and this makes our caller think we failed. "|| return 0" prevents this:
IFS=' ' read unused_len class || return 0
# For each line after the first...
while IFS=' ' read unused_len tag; do
if [ -z "$pos" ]; then
# 2nd line: after "modalias(" prefix, for each char in prev line...
n=9
end=${#class}
else
# 3rd+ lines: only check the char at the same position
n=$pos
end=$((pos + 1))
fi
# Search for aaaNbbb,aaaMbbb line pair, where N and M chars differ.
# sort -u guarantees there are no identical line pairs.
# We assume that lines will not differ only in " = version" suffix.
for ((; n < $end; n++)); do
if [ "${class:0:n}" != "${tag:0:n}" ]; then
# the prefixes already aren't the same: break
n=$end
break
fi
# If suffixes differ, go to next char
[ x"${class:n+1}" != x"${tag:n+1}" ] && continue
# aaaNbbb = aaaMbbb. If N and M aren't special...
xc=x"${class:n:1}"
[ x"[" = "$xc" -o x"]" = "$xc" ] && continue
[ x"?" = "$xc" -o x"*" = "$xc" ] && continue
xc=x"${tag:n:1}"
[ x"[" = "$xc" -o x"]" = "$xc" ] && continue
[ x"?" = "$xc" -o x"*" = "$xc" ] && continue
# Add M (and maybe N) to $variants, go to next line
variants="${variants:-${class:n:1}}${tag:n:1}"
pos=$n
break
done
if [ $n -eq $end ]; then
# This line is not mergeable with the previous one(s),
# print collected merged line and reset the state
print_modaliases "$class" "$variants" "$pos"
variants=""
pos=""
class=$tag
fi
done
# Print last collected merged line
print_modaliases "$class" "$variants" "$pos"
}
for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
modver=$(/sbin/modinfo -F version "$module")
# delete possible extra lines because some modules have *two* version tags. *cough*b44*cough*
modver=${modver%%$'\n'*} # using $'' bashism, avoid running "head -n1" process
# replace any strange chars with underscores.
modver=${modver//[^0-9a-zA-Z._]/_}
# only add version tag if it indeed has a version
[ -z "$modver" ] || modver=" = $modver"
/sbin/modinfo -F alias "$module" \
| sed -nre "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver,p"
# Below: combining code can only possibly combine lines of equal length.
# Prepend line lengths before sort, so that same-length lines end up next
# to each other. (The lengths are discarded by combine_modaliases).
done \
| { while read line; do echo "${#line} $line"; done } \
| LC_ALL=C sort -u \
| combine_modaliases