diff options
Diffstat (limited to '')
-rwxr-xr-x | debian/scripts/dh_dkms.in | 192 | ||||
-rwxr-xr-x | debian/scripts/dkms-autopkgtest | 229 | ||||
-rw-r--r-- | debian/scripts/dkms.pm | 8 | ||||
-rw-r--r-- | debian/scripts/postinst-dkms | 27 | ||||
-rw-r--r-- | debian/scripts/prerm-dkms | 10 |
5 files changed, 466 insertions, 0 deletions
diff --git a/debian/scripts/dh_dkms.in b/debian/scripts/dh_dkms.in new file mode 100755 index 0000000..2af732a --- /dev/null +++ b/debian/scripts/dh_dkms.in @@ -0,0 +1,192 @@ +#!/usr/bin/perl -w + +=head1 NAME + +dh_dkms - correctly handle DKMS usage by a kernel module package + +=cut + +use strict; +use Debian::Debhelper::Dh_Lib; + +=head1 SYNOPSIS + +B<dh_dkms> [S<I<debhelper options>>] [S<B<-l>>] [S<B<-V>[I<version>]>] [S<B<--> I<file>>] + +=head1 DESCRIPTION + +dh_dkms is a debhelper program that is responsible for correctly setting +postinst, postrm and dependencies in kernel module packages using DKMS. + +If a file named debian/package.dkms exists, then different actions are +performed, depending on its contents. + +=head1 FILES + +=over 4 + +=item debian/I<package>.dkms + +=item debian/dkms + +It can be a proper configuration file, and in this case it would be installed +in the proper directory as dkms.conf. + +It can also point to another file (this should be used when the configuration +is provided by upstream), and in this case that file will be installed as dkms.conf +in the proper directory. + +This file can only miss if a filename is provided when calling dh_dkms. + +=back + +=head1 OPTIONS + +=over 4 + +=item B<-l>, B<--legacy> + +Add code to also support DKMS versions < 2.1.0.0. + +=item B<-V>, B<-V> I<version> + +If C<PACKAGE_VERSION> in F<dkms.conf> is set to C<#MODULE_VERSION#>, set it to +the given I<version> or, if none is given, default to the upstream version of +the current package. Otherwise, leave the value specified in F<dkms.conf>. + +=item B<--> I<file> + +Don't look for debian/I<package>.dkms or debian/dkms, but install I<file> as dkms.conf. + +=back + +=head1 NOTES + +Note that this command is not idempotent. L<dh_prep(1)> should be called +between invocations of this command. Otherwise, it may cause multiple +instances of the same text to be added to maintainer scripts. + +=cut + +# placeholder substituted at build time +# is shown along generated autoscripts +#VERSION# + +init(options => { + "l|legacy" => \$dh{LEGACY_DKMS}, +}); + +foreach my $package (@{$dh{DOPACKAGES}}) { + #next if is_udeb($package); + + my $tmp = tmpdir($package); + my $dkms_dir = "/usr/lib/dkms/"; + my $dkms_conf = pkgfile($package, "dkms"); + my $is_snippet = 0; + my @other_conf; + my $name; + my $package_name; + my $package_version; + my $build_exclusive_config; + + if ($dkms_conf) { + # let's see if it's a proper snippet + open(IN, "< $dkms_conf"); + while (my $l = <IN>) { + $l =~ /PACKAGE_NAME=(["'])(.*)\1/ && ($is_snippet = 1); + } + close(IN); + + if ($is_snippet) { + $name = $dkms_conf; + } + else { + my @search_dirs = ($dh{SOURCEDIR} // '.', default_sourcedir($package)); + @other_conf = filearray($dkms_conf, \@search_dirs); + if ($#other_conf > 1) { + error "cannot list more than one file in $dkms_conf!"; + } + else { + $name = $other_conf[0]; + } + } + } + elsif ($#ARGV == 0) { + $name = $ARGV[0]; + } + else { + next; + } + verbose_print "installing $name as dkms.conf"; + + # now, parse our configuration file + open(IN, "< $name") || error("cannot read $name: $!"); + while (my $l = <IN>) { + $l =~ /PACKAGE_NAME=(["']?)(.*)\1/ && ($is_snippet = 1 && $package_name = $2); + $l =~ /PACKAGE_VERSION=(["']?)(.*)\1/ && ($package_version = $2); + $l =~ /BUILD_EXCLUSIVE_CONFIG=(["']?)(.*)\1/ && ($build_exclusive_config = $2); + $l =~ /BUILD_EXCLUSIVE_KERNEL_MIN=(["']?)(.*)\1/ && ($build_exclusive_config = "yes"); + $l =~ /BUILD_EXCLUSIVE_KERNEL_MAX=(["']?)(.*)\1/ && ($build_exclusive_config = "yes"); + } + close(IN); + + #$ENV{DH_AUTOSCRIPTDIR} = "debian/scripts/"; + if ($build_exclusive_config) { + addsubstvar($package, "misc:Depends", "dkms", ">= 3.0.11"); + } + elsif ($dh{LEGACY_DKMS}) { + doit("install", "-p", "-D", "-m755", "$dkms_dir/common.postinst", "$tmp/usr/share/$package/postinst"); + addsubstvar($package, "misc:Depends", "dkms"); + } + else { + addsubstvar($package, "misc:Depends", "dkms", ">= 2.1.0.0"); + } + + if ($dh{V_FLAG_SET} || $package_version eq "#MODULE_VERSION#") { + $package_version = $dh{V_FLAG} || ""; + if ($package_version eq "") { + # Call isnative because it sets $dh{VERSION} + # as a side effect. + isnative($package); + $package_version = $dh{VERSION}; + # Remove the Debian revision + $package_version =~ s/-[^-]+$//; + # Remove the Debian epoch + $package_version =~ s/^\d+://; + } + + my $old_name = $name; + $name = "debian/".pkgext($package)."dkms.debhelper"; + doit("cp", "-a", $old_name, $name); + doit("sed", "-i", "s/#MODULE_VERSION#/$package_version/g", $name); + } + + error "could not determine package name" + unless defined($package_name); + + error "could not determine package version" + unless defined($package_version); + + error "invalid package version '$package_version'" + unless $package_version =~ /^[-+.~:0-9a-zA-Z]+$/; + + autoscript($package, "prerm", "prerm-dkms", + "s/#MODULE_NAME#/$package_name/;s/#MODULE_VERSION#/$package_version/"); + autoscript($package, "postinst", "postinst-dkms", + "s/#MODULE_NAME#/$package_name/;s/#MODULE_VERSION#/$package_version/"); + doit("install", "-p", "-D", "-m644", "$name", "$tmp/usr/src/$package_name-$package_version/dkms.conf"); +} + +=head1 SEE ALSO + +L<debhelper(1)> + +This program is part of the Debian DKMS package. + +L<dkms(8)> + +=head1 AUTHOR + +David Paleino <dapal@debian.org> + +=cut diff --git a/debian/scripts/dkms-autopkgtest b/debian/scripts/dkms-autopkgtest new file mode 100755 index 0000000..7444368 --- /dev/null +++ b/debian/scripts/dkms-autopkgtest @@ -0,0 +1,229 @@ +#!/bin/sh +# Common autopkgtest script for testing a dkms source package. +# Author: Martin Pitt <martin.pitt@ubuntu.com> +# Copyright: (C) 2014 Canonical Ltd. +set -eu + +export DEBIAN_FRONTEND=noninteractive + +result=0 +summary= +crlf=" +" + +header_packages= +check_for_linux_headers() { + # Act only on the first run. + if [ -n "$header_packages" ]; then + return + fi + + # Which Linux header packages are installed? + header_packages=$(dpkg-query -f '${Status} ${Package}\n' -W 'linux-headers-*' 2>/dev/null | sed -r -n 's/^install ok installed //p') + if [ -n "$header_packages" ]; then + echo "I: Using the following Linux header packages that were already installed:" + for p in $header_packages ; do + echo "I: $p" + done + return + fi + + # Which Linux header packages could be installed? + # linux-doc is a dependency generated by autodep8 for autopkgtest-pkg-dkms + # install only linux-headers-* matching the source version of linux-doc + wanted_source_version=$(dpkg-query -f '${source:Version}' -W linux-doc 2>/dev/null || true) + candidates=$(apt-cache search --names-only '^linux-headers-' | awk '{print $1}' | grep -v -E -e '-common(-rt)?$') + echo "I: No Linux header packages are installed." + echo "I: Installing all available ones from src:linux $wanted_source_version:" + for p in $candidates ; do + if [ -z "$wanted_source_version" ]; then + echo "I: $p" + header_packages="$header_packages $p" + continue + fi + source_versions=$(apt-cache show $p | perl -ne 'if (/^$/) { print $s || $v, "\n"; $s=$v=""; } $s=$1 if /^Source: .* \((.*)\)$/; $v=$1 if /^Version: (.*)$/;') + for sv in $source_versions ; do + if [ "$sv" = "$wanted_source_version" ]; then + echo "I: install $p" + header_packages="$header_packages $p" + continue 2 + fi + done + echo "I: skip $p" + done + RC=0 + apt-get install --no-install-recommends -yq $header_packages </dev/null 2>&1 || RC=$? + if [ "$RC" -ne 0 ]; then + echo "E: Linux headers failed to install." >&2 + exit 1 + fi +} + +run_pkg() { + pkg="$1" + + test -x /usr/bin/openssl || apt-get install --no-install-recommends -yq openssl </dev/null 2>&1 + + echo "I: Removing binary package $pkg, to get clean state." + apt-get purge -yq $pkg </dev/null 2>&1 >/dev/null || true + + echo "I: Installing binary package $pkg" + RC=0 + apt-get install --no-install-recommends -yq $pkg </dev/null 2>&1 || RC=$? + if [ "$RC" -ne 0 ]; then + echo "E: Package $pkg failed to install." >&2 + result=1 + return + fi + + # Try and remove dkms to spot packages which miss a dkms dependency + echo "I: Checking for missing dkms dependency by trying to deinstall dkms" + dpkg --remove dkms || true + + if ! dkms_conf=$(dpkg -L $pkg | grep '/usr/src' | grep '/dkms.conf$'); then + echo "I: Package $pkg has no dkms.conf, skipping." + return + fi + + check_for_linux_headers + + echo "I: Testing binary package $pkg" + + dkms_pkg=$(bash -c ". $dkms_conf > /dev/null; echo \$PACKAGE_NAME" 2>/dev/null) + dkms_ver=$(bash -c ". $dkms_conf > /dev/null; echo \$PACKAGE_VERSION" 2>/dev/null) + build_depends=$(bash -c ". $dkms_conf > /dev/null; echo \$BUILD_DEPENDS" 2>/dev/null) + versioned_build_depends= + + for bd in $build_depends + do + bdpath=$(ls -d /usr/src/${bd}-*) + versioned_build_depends="$versioned_build_depends ${bd}/${bdpath#/usr/src/${bd}-}" + done + + for k in $(ls -dv /lib/modules/*/build) + do + test -d "$k" || continue + kver="${k%/build}" + kver="${kver#/lib/modules/}" + + # If any linux-meta is in triggers, only test abistems that + # match triggers otherwise continue. This helps integration + # with adt-matrix which specifically requests test results + # against each individual linux-meta and tracks unique results + # per kernel abi. + abistem=$(echo $kver | sed 's/-[a-z]*$//') + case "${ADT_TEST_TRIGGERS-}" in + *linux-meta*) + case "$ADT_TEST_TRIGGERS" in + *"$abistem"*) + ;; + *) + continue + ;; + esac + esac + + for bdv in $versioned_build_depends + do + echo "I: Trying to install build dependency $bdv for $kver" + dkms install "$bdv" -k "$kver" || test $? = 77 + done + + echo "I: Trying to build $dkms_pkg/$dkms_ver for $kver" + res=0 + dkms build -m "$dkms_pkg" -v "$dkms_ver" -k "$kver" || res=$? + + if [ "$res" = 77 ]; then + echo "I: $dkms_pkg/$dkms_ver is not supported on $kver (BUILD_EXCLUSIVE directive), skipping." + summary="${summary}I: SKIP $dkms_pkg/$dkms_ver $kver${crlf}" + continue + fi + + if [ "$res" != 0 ]; then + echo "E: $dkms_pkg/$dkms_ver failed to build for $kver" >&2 + makelog="/var/lib/dkms/$dkms_pkg/$dkms_ver/build/make.log" + echo "========== $makelog ==========" >&2 + cat "$makelog" >&2 || true + echo "====================" >&2 + summary="${summary}I: FAIL $dkms_pkg/$dkms_ver $kver${crlf}" + result=1 + continue + fi + + if ! dkms install --force -m "$dkms_pkg" -v "$dkms_ver" -k "$kver" ; then + echo "E: $dkms_pkg/$dkms_ver failed to install for $kver" >&2 + summary="${summary}I: FAIL $dkms_pkg/$dkms_ver $kver${crlf}" + result=1 + continue + fi + + echo "I: Testing if $dkms_pkg modules are correctly installed." + dkmsstatus="$(dkms status $dkms_pkg -k $kver)" + echo "$dkmsstatus" + if [ -z "$dkmsstatus" ]; then + echo "E: dkms status output is empty!" >&2 + summary="${summary}I: FAIL $dkms_pkg/$dkms_ver $kver${crlf}" + result=1 + continue + fi + + if ! echo "$dkmsstatus" | grep -q "installed$"; then + echo "E: not installed" >&2 + summary="${summary}I: FAIL $dkms_pkg/$dkms_ver $kver${crlf}" + result=1 + continue + fi + + summary="${summary}I: PASS $dkms_pkg/$dkms_ver $kver${crlf}" + + done + + # collect build logs as artifacts + if [ -d /var/lib/dkms ]; then + (cd /var/lib/dkms; find $dkms_pkg -name "make.log" -print0 | xargs -r -0 tar cvz) > "${AUTOPKGTEST_ARTIFACTS:-.}/$pkg-make-logs.tar.gz" + fi + + # skip modprobing for now; this fails too often (needs particular + # hardware/firmware/etc) + # for mod in $(awk -F '"' '/^BUILT_MODULE_NAME/ {print $2}' $dkms_conf); do + # echo "I: modprobe $mod" + # if ! modprobe $mod; then + # echo "E: Failed to modprobe module $mod" >&2 + # exit 1 + # else + # echo "I: $modname loaded" + # fi + # done +} + +# Do not (fail to) build the modules upon linux-header-* and *-dkms package +# installation, which can cause apt-get to fail. We will do this later with +# improved error reporting. +# (This only works if the *-dkms package is not yet installed.) +touch /etc/dkms/no-autoinstall + +pkg_list="$*" +if [ -z "$pkg_list" ]; then + test -x /usr/bin/grep-dctrl || apt-get install --no-install-recommends -yq dctrl-tools </dev/null 2>&1 + pkg_list="$(grep-dctrl -FDepends -e '(^| )dkms' -o -FPackage -e '\-dkms' debian/control -sPackage -n)" +fi + +for pkg in $pkg_list; do + # package might be arch: restriction or udeb etc. + if ! apt-cache show $pkg >/dev/null 2>&1; then + echo "I: Skipping unavailable package $pkg" + continue + fi + run_pkg $pkg +done + +if [ -n "$summary" ]; then + echo "I: Summary:" + echo -n "$summary" +fi + +rm -f /etc/dkms/no-autoinstall + +exit $result + +# vim: sw=4:ts=4:et diff --git a/debian/scripts/dkms.pm b/debian/scripts/dkms.pm new file mode 100644 index 0000000..a337a9c --- /dev/null +++ b/debian/scripts/dkms.pm @@ -0,0 +1,8 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Debian::Debhelper::Dh_Lib; + +insert_before("dh_installinit", "dh_dkms"); + +1; diff --git a/debian/scripts/postinst-dkms b/debian/scripts/postinst-dkms new file mode 100644 index 0000000..0084a6e --- /dev/null +++ b/debian/scripts/postinst-dkms @@ -0,0 +1,27 @@ +# The original file can be found in template-dkms-mkdeb/debian/postinst +# in the DKMS tarball, check it for copyright notices. + +DKMS_NAME=#MODULE_NAME# +DKMS_PACKAGE_NAME=$DKMS_NAME-dkms +DKMS_VERSION=#MODULE_VERSION# + +postinst_found=0 + +case "$1" in + configure) + for DKMS_POSTINST in /usr/lib/dkms/common.postinst /usr/share/$DKMS_PACKAGE_NAME/postinst; do + if [ -f $DKMS_POSTINST ]; then + $DKMS_POSTINST $DKMS_NAME $DKMS_VERSION /usr/share/$DKMS_PACKAGE_NAME "" $2 + postinst_found=1 + break + fi + done + if [ "$postinst_found" -eq 0 ]; then + echo "ERROR: DKMS version is too old and $DKMS_PACKAGE_NAME was not" + echo "built with legacy DKMS support." + echo "You must either rebuild $DKMS_PACKAGE_NAME with legacy postinst" + echo "support or upgrade DKMS to a more current version." + exit 1 + fi + ;; +esac diff --git a/debian/scripts/prerm-dkms b/debian/scripts/prerm-dkms new file mode 100644 index 0000000..6e93a1b --- /dev/null +++ b/debian/scripts/prerm-dkms @@ -0,0 +1,10 @@ +DKMS_NAME=#MODULE_NAME# +DKMS_VERSION=#MODULE_VERSION# + +case "$1" in + remove|upgrade|deconfigure) + if [ "$(dkms status -m $DKMS_NAME -v $DKMS_VERSION)" ]; then + dkms remove -m $DKMS_NAME -v $DKMS_VERSION --all + fi + ;; +esac |