diff --git a/README.md b/README.md index f694e25..f8faece 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,3 @@ # kernel-srpm-macros -The kernel-srpm-macros package - -This source package results in two "binary" packages, kernel-rpm-macros -and kernel-srpm-macros. The role and locations of files is as follows: - -kernel-srpm-macros: - -/usr/lib/rpm/fileattrs/kmod.attr - For /lib/modules/XYZ/modules.builtin and .../MODULE.ko.XYZ - specifies a Lua script to generate kmod(MODULE.ko) - "Provides:" deps -/usr/lib/rpm/macros.d/macros.kernel-srpm - Automatically included by all rpm invocations. - Defines %kernel_arches (try rpm --eval '%kernel_arches') - Question: what uses this macro? I didn't find any users. - -kernel-rpm-macros: - -/usr/lib/rpm/redhat/find-provides.ksyms - Runs from rpmbuild at the end of kernel builds and 3rd party module - builds, to extract - kernel(SYMBOL)=0xHASH "Provides:" deps from modules in kernel packages, - and ksym(SYMBOL)=0xHASH for 3rd party modules. - Takes input list of files on stdin. -/usr/lib/rpm/fileattrs/provided_ksyms.attr - For newer rpmbuild with "internal dependency generators", - this file specifies that find-provides.ksyms should be run - only on .ko.XYZ files - (with "external dependency generators", the script needs to - filter out the files by itself). - -/usr/lib/rpm/redhat/find-requires.ksyms - ? -/usr/lib/rpm/fileattrs/required_ksyms.attr - For newer rpmbuild with "internal dependency generators", - this file specifies that find-requires.ksyms should be run - only on .ko.XYZ files, and not for /lib/modules/XYZ/kernel/* - (IOW: only for building 3rd-party modules) - -/usr/lib/rpm/redhat/find-provides.d/modalias.prov - Runs from rpmbuild at the end of kernel builds and 3rd party module - builds, to extract - modalias(pci:SOMETHING)=OPTIONALLY_VERSION "Provides:" deps from modules - in kernel and 3rd party modules packages. - Takes input list of files on stdin. - Question: what uses these deps? -/usr/lib/rpm/fileattrs/modalias.attr - For newer rpmbuild with "internal dependency generators", - this file specifies that modalias.prov should be run - only on .ko.XYZ files - -/usr/lib/rpm/redhat/find-provides.d/firmware.prov - ? - -/usr/lib/rpm/kabi.sh - Runs from rpmbuild at the end of kernel build to extract - kernel(SYMBOL)=0xHASH "Provides:" deps. -/usr/lib/rpm/fileattrs/kabi.attr - For newer rpmbuild with "internal dependency generators", - this file specifies that kabi.sh should be run on - /boot/symvers-* and /lib/modules/XYZ/symvers.gz - -/usr/lib/rpm/macros.d/macros.kmp - Automatically included by all rpm invocations. - Defines a number of macros. - -/usr/lib/rpm/redhat/brp-kmod-restore-perms - ? -/usr/lib/rpm/redhat/brp-kmod-set-exec-bit - ? - -/usr/lib/rpm/redhat/kmodtool - ? -/usr/lib/rpm/redhat/rpmsort - ? -/usr/lib/rpm/redhat/symset-table - ? +The kernel-srpm-macros package \ No newline at end of file diff --git a/find-provides.ksyms b/find-provides.ksyms index 230fc09..af98b90 100755 --- a/find-provides.ksyms +++ b/find-provides.ksyms @@ -1,16 +1,12 @@ #! /bin/bash IFS=$'\n' -export LC_ALL=C - -# Prevent elfutils from trying to download debuginfos -unset DEBUGINFOD_URLS for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do dep_pfx="ksym" # For built-in kmods, "kernel()" syntax is used instead of "ksym()" printf "%s" "$module" | grep -v "^${RPM_BUILD_ROOT}/\?lib/modules/[1-9][^/]*/kernel" > /dev/null \ - || dep_pfx="kernel" + || dep_pfx="kernel" tmpfile="" if [ "x${module%.ko}" = "x${module}" ]; then @@ -37,102 +33,24 @@ for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do module="$tmpfile" fi - # A modversion can be stored as an ELF symbol in various ways: - # - An immediate symbol whose value is available directly; it shows up - # in the nm or objdump -t output, for example: - # $ nm mlx5_core_5.14.x86_64.ko | grep '__crc_' | head -n 3 - # 0000000092f175ca A __crc_mlx5_access_reg - # 000000005b88c9f1 A __crc_mlx5_add_flow_rules - # 00000000e7c0ec8a A __crc_mlx5_alloc_bfreg - # $ objdump -t lib/modules/mlx5_core_5.14.x86_64.ko | grep __crc_ | sort -k 5,5 | head -n 3 - # 0000000092f175ca g *ABS* 0000000000000000 __crc_mlx5_access_reg - # 000000005b88c9f1 g *ABS* 0000000000000000 __crc_mlx5_add_flow_rules - # 00000000e7c0ec8a g *ABS* 0000000000000000 __crc_mlx5_alloc_bfreg - # $ zgrep mlx5_access_reg ./lib/modules/5.14.0-284.15.1.el9_2.x86_64/symvers.gz - # 0x92f175ca mlx5_access_reg drivers/net/ethernet/mellanox/mlx5/core/mlx5_core EXPORT_SYMBOL_GPL - # This approach was being used on x86 and arm before Linux 5.19, - # for example. - # - # - A globally or locally visible symbol in a read-only (or not; - # sometimes .rodata is not a read-only section, after all, as binutils - # commit binutils-2_33~1385 has revealed (and binutils-2_35~1768 hasn't - # concealed back)) section (historically .rodata, __kcrctab/__kcrctab_gpl - # since Linux v5.19-rc1~139^2~2): - # $ nm mlx5_core_5.14.s390x.ko | grep '__crc_' | head -n 3 - # 0000000000002f7c R __crc_mlx5_access_reg - # 0000000000003304 R __crc_mlx5_add_flow_rules - # 0000000000002d2c R __crc_mlx5_alloc_bfreg - # This layout is used on ppc since Linux v4.10-rc7~15^2~1, for example, - # and on all architectures since Linux 5.19. To extract the symbol - # versions in this case, we get the offset and the section name - # from the "objdump -t" output: - # $ objdump -t lib/modules/mlx5_core_5.14.s390x.ko | grep '__crc_' | sort -k 5,5 | head -n 2 - # 0000000000002f7c g .rodata 0000000000000000 __crc_mlx5_access_reg - # 0000000000003304 g .rodata 0000000000000000 __crc_mlx5_add_flow_rules - # and the section contents from the "readelf -R" call: - # $ readelf -R .rodata mlx5_core_5.14.s390x.ko - # [... skipped output ...] - # 0x00002f70 6c6f635f 6e6f6465 00000000 ed6560a8 loc_node.....e`. - # ^^^^^^^^ - # comparison with the contents - # of lib/modules/5.14.0-284.15.1.el9_2.s390x/symvers.gz corroborates - # its correctness: - # 0xed6560a8 mlx5_access_reg drivers/net/ethernet/mellanox/mlx5/core/mlx5_core EXPORT_SYMBOL_GPL - # As mentioned earlier, for the later kernel versions, __kcrctab{,_gpl} - # sections are used: - # $ objdump -t lib/modules/mlx5_core_6.4.x86_64.ko | grep '__crc_' | sort -k 5,5 | head -n 2 - # 0000000000000000 l __kcrctab_gpl 0000000000000000 __crc_mlx5_access_reg - # 0000000000000090 l __kcrctab 0000000000000000 __crc_mlx5_add_flow_rules - # $ readelf -R __kcrctab_gpl mlx5_core_6.4.x86_64.ko - # 0x00000000 38b0d3c3 1840ce35 b99babc7 70b4700c 8....@.5....p.p. - # ^^^^^^^^ - # and in lib/modules/6.4.0-0.rc1.20230511git80e62bc8487b.19.eln126.x86_64/symvers.xz - # we see that it is correct (when accounted for the little endianness): - # 0xc3d3b038 mlx5_access_reg drivers/net/ethernet/mellanox/mlx5/core/mlx5_core EXPORT_SYMBOL_GPL - # This data, after some post-processing, can be used in the awk script - # that extracts parts of the section according to the offsets got - # from the "objdump -t" output. - objdump -t "$module" \ - | awk \ - -v 'dep_pfx='"$dep_pfx" \ - -v 'module='"$module" \ - --non-decimal-data \ - 'BEGIN { revbytes = 0 } - - function check_endianness( t) { - if (revbytes) return revbytes; - - revbytes = -1; - while (("readelf -h \"" module "\"" | getline t) > 0) { - if (match(t, /^ Data: *2\047s complement, little endian$/)) { - revbytes = 1; - break; - } - } - - return revbytes; - } - - function readsect(name, a, t) { - a = ""; - while (("readelf -R \"" name "\" \"" module "\"" | getline t) > 0) { - if (match(t, /^ 0x[0-9a-f]{8}/)) - a = a substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8); - } - if (check_endianness() == 1) - a = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", a); - sectdata[name] = a; - } - - match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) { - if (a[2] == "*ABS*") { - printf("%s(%s) = 0x%08x\n", dep_pfx, a[3], strtonum("0x" a[1])); - } else { - if (!(a[2] in sectdata)) { readsect(a[2]) } - printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata[a[2]], (strtonum("0x" a[1]) * 2) + 1, 8)) - } - }' + if [[ -n $(nm $module | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then + nm $module \ + | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \ + | awk --non-decimal-data '{printf("'"${dep_pfx}"'(%s) = 0x%08x\n", $2, $1)}' \ + | LC_ALL=C sort -u + else + ELFRODATA=$(readelf -R .rodata $module | awk '/0x/{printf $2$3$4$5}') + if [[ -n $(readelf -h $module | grep "little endian") ]]; then + RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g') + else + RODATA=$ELFRODATA + fi + for sym in $(nm $module | sed -r -ne 's:^0*([0-9a-f]+) R __crc_(.+):0x\1 \2:p'); do + echo $sym $RODATA + done \ + | awk --non-decimal-data '{printf("'"${dep_pfx}"'(%s) = 0x%08s\n", $2, substr($3,($1*2)+1,8))}' \ + | LC_ALL=C sort -u + fi [ -z "$tmpfile" ] || rm -f -- "$tmpfile" -done \ -| sort -k1,1 -u +done diff --git a/find-requires.ksyms b/find-requires.ksyms index 8ac7c40..105a458 100755 --- a/find-requires.ksyms +++ b/find-requires.ksyms @@ -6,10 +6,6 @@ # provided by an external module and "ksym" replaces th regular "kernel" dep. IFS=$'\n' -export LC_ALL=C - -# Prevent elfutils from trying to download debuginfos -unset DEBUGINFOD_URLS # Extract all of the symbols provided by this module. all_provides() { @@ -39,49 +35,26 @@ all_provides() { module="$tmpfile" fi - objdump -t "$module" \ - | awk \ - -v 'dep_pfx='"$dep_pfx" \ - -v 'module='"$module" \ - --non-decimal-data \ - 'BEGIN { revbytes = 0 } - - function check_endianness( t) { - if (revbytes) return revbytes; - - revbytes = -1; - while (("readelf -h \"" module "\"" | getline t) > 0) { - if (match(t, /^ Data: *2\047s complement, little endian$/)) { - revbytes = 1; - break; - } - } - - return revbytes; - } - - function readsect(name, a, t) { - a = ""; - while (("readelf -R \"" name "\" \"" module "\"" | getline t) > 0) { - if (match(t, /^ 0x[0-9a-f]{8}/)) - a = a substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8); - } - if (revbytes) { a = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", a); } - sectdata[name] = a; - } - - match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) { - if (a[2] == "*ABS*") { - printf("%s(%s) = 0x%08x\n", dep_pfx, a[3], strtonum("0x" a[1])); - } else { - if (!(a[2] in sectdata)) { readsect(a[2]) } - printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata[a[2]], (strtonum("0x" a[1]) * 2) + 1, 8)) - } - }' + if [[ -n $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then + nm "$module" \ + | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \ + | awk --non-decimal-data '{printf("%s:0x%08x\n", $2, $1)}' + else + ELFRODATA=$(readelf -R .rodata "$module" | awk '/0x/{printf $2$3$4$5}') + if [[ -n $(readelf -h "$module" | grep "little endian") ]]; then + RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g') + else + RODATA=$ELFRODATA + fi + for sym in $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) R __crc_(.+):0x\1 \2:p'); do + echo $sym $RODATA + done \ + | awk --non-decimal-data '{printf("%s:0x%08s\n", $2, substr($3,($1*2)+1,8))}' + fi [ -z "$tmpfile" ] || rm -f -- "$tmpfile" done \ - | sort -k1,1 -u + | LC_ALL=C sort -k1,1 -u } # Extract all of the requirements of this module. @@ -94,15 +67,15 @@ all_requires() { {printf("%s:0x%08x\n", $2, $1)}' \ | sed -r -e 's:$:\t'"$1"':' done \ - | sort -k1,1 -u + | LC_ALL=C sort -k1,1 -u } # Filter out requirements fulfilled by the module itself. mod_requires() { - join -t $'\t' -j 1 -v 1 \ + LC_ALL=C join -t $'\t' -j 1 -v 1 \ <(all_requires "$@") \ <(all_provides "$@") \ - | sort -k1,1 -u + | LC_ALL=C sort -k1,1 -u } if ! [ -e /sbin/modinfo -a -e /sbin/modprobe ]; then @@ -165,23 +138,23 @@ if [ ${#modules[@]} -gt 0 ]; then { print $2 ":" $1 } ' \ | sed -r -e 's:$:\t'"$kernel"':' \ - | sort -k1,1 -u > $symvers + | LC_ALL=C sort -k1,1 -u > $symvers # Symbols matching with the kernel get a "kernel" dependency mod_req=$(mktemp -t mod_req.XXXXX) mod_requires "${modules[@]}" > "$mod_req" - join -t $'\t' -j 1 $symvers "$mod_req" | sort -u \ + LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \ | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "kernel(" $1 ") = " $2 }' # Symbols from elsewhere get a "ksym" dependency - join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | sort -u \ + LC_ALL=C join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | LC_ALL=C sort -u \ | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "ksym(" $1 ") = " $2 }' os_id=$(sed -nr '/^ID[[:space:]]*=/{ s/ID[[:space:]]*=[[:space:]]*//; s/^"(.*)"$/\1/; p }' /etc/os-release) if [ "rhel" = "$os_id" ]; then # Check kABI if the kabi-stablelists package is installed # Do this last so we can try to output this error at the end - kabi_check_symbols=($(join -t $'\t' -j 1 $symvers "$mod_req" | sort -u \ + kabi_check_symbols=($(LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \ | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print $1 }')) check_kabi "${kabi_check_symbols[@]}" fi diff --git a/kabi.attr b/kabi.attr index 5500b17..2d81387 100644 --- a/kabi.attr +++ b/kabi.attr @@ -1,2 +1,2 @@ %__kabi_provides %{_rpmconfigdir}/kabi.sh -%__kabi_path ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.(gz|xz)$ +%__kabi_path ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz$ diff --git a/kabi.sh b/kabi.sh index dd49b8b..3fb749b 100644 --- a/kabi.sh +++ b/kabi.sh @@ -7,16 +7,10 @@ IFS=$'\n' -for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.(gz|xz)') "$@"; +for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz') "$@"; do - cat_prog="cat" - case "$symvers" in - *.gz) cat_prog="zcat" ;; - *.xz) cat_prog="xzcat" ;; - esac - # We generate dependencies only for symbols exported by vmlinux itself # and not for kmods here as they are spread across subpackages, # so Provides: generation for kmods is handled by find-provides.ksyms. - "$cat_prog" "$symvers" | awk '/[^ ]* [^ ]* vmlinux .*/ { print "kernel(" $2 ") = " $1 }' + zcat $symvers | awk '/[^ ]* [^ ]* vmlinux .*/ { print "kernel(" $2 ") = " $1 }' done diff --git a/kernel-srpm-macros.spec b/kernel-srpm-macros.spec index 058c08e..b35b87a 100644 --- a/kernel-srpm-macros.spec +++ b/kernel-srpm-macros.spec @@ -1,7 +1,7 @@ Name: kernel-srpm-macros Version: 1.0 # when bumping version and resetting release, don't forget to bump version of kernel-rpm-macros as well -Release: 27%{?dist} +Release: 15%{?dist} Summary: RPM macros that list arches the full kernel is built on # This package only exist in Fedora repositories # The license is the standard (MIT) specified in @@ -56,25 +56,10 @@ The variable to use is kernel_arches. %package -n kernel-rpm-macros Version: 205 Summary: Macros and scripts for building kernel module packages -# rpmsort is GPL-2.0-or-later -License: MIT AND GPL-2.0-or-later Requires: redhat-rpm-config >= 205 -# for brp-kmod-compress -Requires: %{_bindir}/xz -# for brp-kmod-compress, brp-kmod-set-exec-bit +# for brp-kmod-set-exec-bit Requires: %{_bindir}/find -# for find-provides.ksyms, find-requires.ksyms, kmodtool -Requires: %{_bindir}/sed -# for find-provides.ksyms, find-requires.ksyms -Requires: %{_bindir}/awk -Requires: %{_bindir}/grep -Requires: %{_bindir}/nm -Requires: %{_bindir}/objdump -Requires: %{_bindir}/readelf -# for find-requires.ksyms -Requires: %{_sbindir}/modinfo -Requires: %{_sbindir}/modprobe %description -n kernel-rpm-macros Macros and scripts for building kernel module packages. @@ -94,7 +79,7 @@ cp -p %{sources} . mkdir -p %{buildroot}/%{_rpmconfigdir}/macros.d install -p -m 0644 -t %{buildroot}/%{_rpmconfigdir}/macros.d macros.kernel-srpm %if 0%{?rhel} >= 8 - sed -i 's/^%%kernel_arches.*/%%kernel_arches x86_64 s390x ppc64le aarch64 riscv64/' \ + sed -i 's/^%%kernel_arches.*/%%kernel_arches x86_64 s390x ppc64le aarch64/' \ %{buildroot}/%{_rpmconfigdir}/macros.d/macros.kernel-srpm %endif @@ -136,53 +121,6 @@ install -p -m 644 -t "%{buildroot}%{_fileattrsdir}" modalias.attr %{rrcdir}/rpmsort %changelog -* Thu Jul 24 2025 Fedora Release Engineering - 1.0-27 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Tue Apr 01 2025 Andrea Bolognani - 1.0-26 -- Finish adding riscv64 (thanks Zhengyu He) - -* Fri Jan 17 2025 Fedora Release Engineering - 1.0-25 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Thu Jul 18 2024 Fedora Release Engineering - 1.0-24 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Wed Mar 06 2024 David Abdurachmanov - 1.0-23 -- Add riscv64 - -* Wed Jan 24 2024 Fedora Release Engineering - 1.0-22 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Sun Jan 21 2024 Fedora Release Engineering - 1.0-21 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Thu Jul 20 2023 Fedora Release Engineering - 1.0-20 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Tue May 09 2023 Eugene Syromiatnikov - 1.0-19 -- Capture local __crc_* symbols for "Provides: kernel()". -- Add support for XZ compression for the symvers file. -- Fix "Provides: kernel()" generation when both __kcrctab and __kcrctab_gpl - are present. -- Fix regression for "Provides:" generation in cases when modversions are stored - in a section that is over 64K in size. -- Speedup and cleanup changes in find-provides.ksyms and find-requires.ksyms. -- Fix regex usage in kmod.attr. (Denys Vlasenko) -- Implement modalias "Provides:" grouping. (Denys Vlasenko) -- Speedup and cleanup changes in modalias.prov and kmod.attr. (Denys Vlasenko) - -* Tue Mar 30 2023 Eugene Syromiatnikov - 1.0-18 -- Avoid triggering debuginfod during elfutils tools usage. - -* Tue Jan 31 2023 Eugene Syromiatnikov - 1.0-17 -- Support storing of __crc_* symbols in sections other than .rodata. -- Work around a change in type of __crc_* symbols for some kmods printed by nm - on ppc64le and s390x. - -* Thu Jan 19 2023 Fedora Release Engineering - 1.0-16 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - * Thu Jul 21 2022 Fedora Release Engineering - 1.0-15 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild diff --git a/kmod.attr b/kmod.attr index 8c57d0b..23b1289 100644 --- a/kmod.attr +++ b/kmod.attr @@ -1,54 +1,31 @@ %__kmod_path ^/lib/modules/.*/(modules.builtin|.*\.ko|.*\.ko\.gz|.*\.ko\.bz2|.*\.ko\.xz|.*\.ko\.zst)$ - -# Notes on Lua: -# The backslash in strings (like "\n" newline) needs to be doubled -# because we are inside rpm macro. Single backslashes before most chars -# disappear (removed by rpm's parser), so "\n" turns into just "n". -# In string.gsub patterns, unlike regexps, backslash has no special meaning. -# It can't escape . and such. (Use one-character set [.] to represent -# literal period, or lua's percent escape: %.) -# Pipe (|) has no special meaning too. - %__kmod_provides() %{lua: function basename(fn) - local b = string.gsub(fn, ".*/", "") - -- the above adjusts gsub() result to 1 value - -- "return f()" construct would return _all_ values, two in case of gsub() - return b + return string.gsub(fn, "(.*/)(.*)", "%2") end function strip_compress_sfx(fn) - local cnt - fn, cnt = string.gsub(fn, "%.gz$", "") - if cnt == 1 then return fn; end - fn, cnt = string.gsub(fn, "%.bz2$", "") - if cnt == 1 then return fn; end - fn, cnt = string.gsub(fn, "%.xz$", "") - if cnt == 1 then return fn; end - fn, cnt = string.gsub(fn, "%.zst$", "") - return fn + return string.gsub(fn, "(.*)(\.gz|\.bz2|\.xz|\.zst)?$", "%1") end function printdep(mod) print("kmod("..mod..") ") end - local fn = rpm.expand("%1") + local fn = rpm.expand("%{1}") local bn = basename(fn) if bn == "modules.builtin" then for l in io.lines(fn) do local builtin_mod = basename(l) printdep(builtin_mod) - local nocompr = strip_compress_sfx(builtin_mod) - if nocompr ~= builtin_mod then - printdep(nocompr) + if strip_compress_sfx(builtin_mod) ~= builtin_mod then + printdep(strip_compress_sfx(builtin_mod)) end end else - local mod = string.match(bn, "%g+%.ko") + local mod = string.match(bn, "%g+.ko") if mod then - printdep(mod) - local nocompr = strip_compress_sfx(mod) - if nocompr ~= mod then - printdep(nocompr) - end + printdep(mod) + if strip_compress_sfx(mod) ~= mod then + printdep(strip_compress_sfx(mod)) + end end end } diff --git a/macros.kernel-srpm b/macros.kernel-srpm index 5f6bb98..c7110f6 100644 --- a/macros.kernel-srpm +++ b/macros.kernel-srpm @@ -1,3 +1,3 @@ # kernel_arches lists what arches the full kernel is built for. -%kernel_arches x86_64 s390x ppc64le aarch64 %{arm} riscv64 +%kernel_arches x86_64 s390x ppc64le aarch64 %{arm} diff --git a/macros.kmp b/macros.kmp index fdfc182..00c0467 100644 --- a/macros.kmp +++ b/macros.kmp @@ -59,7 +59,7 @@ redhat_kmp_has_post_hooks 1 %global kmodtool %{-s*}%{!-s:/usr/lib/rpm/redhat/kmodtool} \ %global kmod_version %{-v*}%{!-v:%{version}} \ %global kmod_release %{-r*}%{!-r:%{release}} \ - %global latest_kernel %({ rpm -q --qf '%%{VERSION}-%%{RELEASE}.%%{ARCH}\\\\n' kernel-rt-devel kernel-aarch64-devel kernel-devel | grep -v 'is not installed' | /usr/lib/rpm/redhat/rpmsort -r | head -n 1; echo '%%%%{nil}'; } | head -n 1) \ + %global latest_kernel %({ rpm -q --qf '%%{VERSION}-%%{RELEASE}.%%{ARCH}\\\\n' `rpm -qa | egrep "^kernel(-rt|-aarch64)?-devel" | /usr/lib/rpm/redhat/rpmsort -r | head -n 1`; echo '%%%%{nil}'; } | head -n 1) \ %{!?kernel_version:%{expand:%%global kernel_version %{latest_kernel}}} \ %global kverrel %(%{kmodtool} verrel %{?kernel_version} 2>/dev/null) \ flavors="default" \ diff --git a/modalias.prov b/modalias.prov old mode 100755 new mode 100644 index 7707991..6408a6e --- a/modalias.prov +++ b/modalias.prov @@ -26,15 +26,13 @@ if ! [ -z "$is_kernel_package" ]; then 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 +# Check for presence of the commands used +which /sbin/modinfo >/dev/null || exit 0 +which sed >/dev/null || exit 0 +which sort >/dev/null || exit 0 print_modaliases() { - local class="$1" variants="$2" pos="$3" + declare class=$1 variants=$2 pos=$3 if [ -n "$variants" ]; then echo "${class:0:pos}[$variants]${class:pos+1}" else @@ -42,87 +40,39 @@ print_modaliases() { 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 next prev 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 prev || return 0 - - # For each line after the first... - while IFS=' ' read unused_len next; do - if [ -z "$pos" ]; then - # 2nd line: after "modalias(" prefix, for each char in prev line... - n=9 - end=${#prev} - # TODO speedup? if [ $end != ${#next} ]; then line is not mergeable - 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 [ "${prev:0:n}" != "${next:0:n}" ]; then - # the prefixes already aren't the same: break - n=$end + declare tag class variants="" pos="" n + read class + while read tag; do + for ((n=0; n<${#class}; n++)); do + if [ "*" != "${class:n:1}" -a \ + "${class:0:n}" = "${tag:0:n}" -a \ + "${class:n+1}" = "${tag:n+1}" ] && + ( [ -z "$pos" ] || [ $n = $pos ] ); then + variants="${variants:-${class:n:1}}${tag:n:1}" + pos=$n break fi - # If suffixes differ, go to next char - [ x"${prev:n+1}" != x"${next:n+1}" ] && continue - # Found aaaNbbb,aaaMbbb. If N and M aren't special... - xc=x"${prev:n:1}" - [ x"[" = "$xc" -o x"]" = "$xc" ] && continue - [ x"?" = "$xc" -o x"*" = "$xc" ] && continue - xc=x"${next: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:-${prev:n:1}}${next: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 "$prev" "$variants" "$pos" - variants="" - pos="" - prev=$next + if [ $n -eq ${#class} ]; then + print_modaliases "$class" "$variants" "$pos" + variants= + pos= + class=$tag fi done - # Print last collected merged line - print_modaliases "$prev" "$variants" "$pos" + 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. - # [!...] is glob's "match any char not in set" pattern - # (although bash supports [^...] too, it is not standard) - modver=${modver//[!0-9a-zA-Z._]/_} - # only add version tag if it indeed has a version + # | head -n1 because some modules have *two* version tags. *cough*b44*cough* + modver=$(/sbin/modinfo -F version "$module"| head -n1) + modver=${modver//[^0-9a-zA-Z._]/_} + # only add version tag if it has a version [ -z "$modver" ] || modver=" = $modver" /sbin/modinfo -F alias "$module" \ - | sed -E "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver," - - # 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). + | sed -nre "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver,p" done \ -| { while read line; do echo "${#line} $line"; done } \ -| LC_ALL=C sort -u \ +| sort -u \ | combine_modaliases diff --git a/tests/modalias.prov.collect b/tests/modalias.prov.collect deleted file mode 100755 index deaeaf7..0000000 --- a/tests/modalias.prov.collect +++ /dev/null @@ -1,31 +0,0 @@ -#! /bin/bash -efu - -# This fetches test data from current system's /lib/modules -# to /tmp/COLLECT - -IFS=$'\n' - -find /lib/modules | grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$' \ -| while IFS='' read -r module; 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. - # [!...] is glob's "match any char not in set" pattern - # (although bash supports [^...] too, it is not standard) - modver=${modver//[!0-9a-zA-Z._]/_} - # only add version tag if it has a version - [ -z "$modver" ] || modver=" = $modver" - - d="/tmp/COLLECT$module" - d="${d%/*}" - mkdir -p "$d" - - out=`/sbin/modinfo -F alias "$module" \ - | sed -E "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver,"` - - [ "$out" ] || continue - - echo "/tmp/COLLECT$module.modalias$modver" >&2 - printf '%s\n' "$out" >"/tmp/COLLECT$module.modalias" -done diff --git a/tests/modalias.prov.runtest b/tests/modalias.prov.runtest deleted file mode 100755 index 2fd03ad..0000000 --- a/tests/modalias.prov.runtest +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -function die() -{ - printf '%s\n' "$*" >&2 - exit 1 -} - -set -e - -cd modalias.prov.testdata -test -x ../../modalias.prov || die "No ../../modalias.prov" - -# Copy and add -t option to modalias.prov -cp ../../modalias.prov modalias.prov -patch -p1 <<"EOF" ---- a/modalias.prov -+++ b/modalias.prov -@@ -105,6 +105,17 @@ combine_modaliases() { - print_modaliases "$prev" "$variants" "$pos" - } - -+if [ "$#" = 2 ] && [ "$1" = "-t" ]; then -+ cat -- "$2" \ -+ | { while read line; do echo "${#line} $line"; done } \ -+ | LC_ALL=C sort -u \ -+ | combine_modaliases \ -+ >"$2.test" -+ echo "Comparing results for $2" -+ diff -u "$2.right" "$2.test" && rm -- "$2.test" -+ exit -+fi -+ - 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* -EOF - -find | grep '\.ko.*\.modalias$' | xargs -n1 ./modalias.prov -t - -# Rename newly generated .test as .right -#find | grep '\.ko.*\.modalias$' | xargs -I'{}' mv '{}'.test '{}'.right diff --git a/tests/modalias.prov.testdata.tar.xz b/tests/modalias.prov.testdata.tar.xz deleted file mode 100644 index 790d08e..0000000 Binary files a/tests/modalias.prov.testdata.tar.xz and /dev/null differ