diff options
Diffstat (limited to '')
-rwxr-xr-x | commands/build-all | 15 | ||||
-rwxr-xr-x | commands/build-arch | 67 | ||||
-rwxr-xr-x | commands/check | 16 | ||||
-rwxr-xr-x | commands/copy-modules | 168 | ||||
-rwxr-xr-x | commands/find-dups | 24 | ||||
-rwxr-xr-x | commands/find-unpackaged | 35 | ||||
-rwxr-xr-x | commands/gen-control | 98 | ||||
-rwxr-xr-x | commands/gen-deps | 35 | ||||
-rwxr-xr-x | commands/help | 12 | ||||
-rwxr-xr-x | commands/install-files | 170 | ||||
-rwxr-xr-x | commands/preprocess | 224 |
11 files changed, 864 insertions, 0 deletions
diff --git a/commands/build-all b/commands/build-all new file mode 100755 index 0000000..afb677f --- /dev/null +++ b/commands/build-all @@ -0,0 +1,15 @@ +#!/bin/sh +# This is a wrapper script that can be used to build all architectures. +# +# The script builds all architectures listed in kernel-versions. +# It expects to have the unpacked kernel packages for various arches in +# ../alpha, etc. modules.dep files have to be put in there too if they are +# not shipped in the .deb (varies) +# +# dpkg-cross must be installed, but you do not need a cross compiler. + +set -e + +for arch in $(cut -d ' ' -f 1 kernel-versions | grep -v ^# | uniq); do + kernel-wedge build-arch "$arch" +done diff --git a/commands/build-arch b/commands/build-arch new file mode 100755 index 0000000..5b910ab --- /dev/null +++ b/commands/build-arch @@ -0,0 +1,67 @@ +#!/bin/sh +# This is a wrapper script to build a specific architecture. +# +# It takes the architecture to be built as parameter and that architecture +# needs to be listed in kernel-versions. +# It expects to have the unpacked kernel packages for the architecture in +# e.g. ../alpha. modules.dep files have to be put in there too if they are +# not shipped in the .deb (varies) +# +# dpkg-cross must be installed, but you do not need a cross compiler. + +set -e + +buildpackage () { + dpkg-buildpackage -d -us -uc -rfakeroot -tc -I $@ +} + +# Build source package. Binaries are built below. +buildpackage -S + +# Directory for stubs, added to PATH. +arch="$1" +trap 'rm -rf $tmpdir' EXIT +tmpdir=$(mktemp -d) +PATH=$PATH:$tmpdir +export PATH + +if [ -z "$arch" ]; then + echo "** Error: architecture not specified" + exit 1 +fi +if ! cut -d ' ' -f 1 kernel-versions | grep -v "^$arch$"; then + echo "** Error: arch $arch not listed in kernel-versions" + exit 1 +fi + +if [ "$arch" != "`dpkg-architecture -qDEB_BUILD_ARCH`" ]; then + # Generate cross-compiler stub, this is needed to get the + # debian build system to cross-build the given arch w/o a + # real cross compiler. + CC=$tmpdir/$arch-linux-gcc + echo "#!/bin/sh" > $CC + echo "echo $arch-linux" >> $CC + chmod +x $CC + # Not only must it be in the path, but CC needs to be + # exported as well. + export CC +else + # native build + unset CC +fi + +if [ -d ../$arch ]; then + export SOURCEDIR=`pwd`/../$arch +else + unset SOURCEDIR +fi + +if [ "$arch" != "`dpkg-architecture -qDEB_BUILD_ARCH`" ]; then + if [ -z "$SOURCEDIR" ]; then + echo "** Warning: no SOURCEDIR for arch $arch" >&2 + fi + buildpackage -b -a$arch +else + # native build + buildpackage +fi diff --git a/commands/check b/commands/check new file mode 100755 index 0000000..4b416d1 --- /dev/null +++ b/commands/check @@ -0,0 +1,16 @@ +#!/bin/sh -e +empty= +if [ $# -ge 1 ]; then + packages="$*" +else + packages="$(dh_listpackages -s)" +fi +for pkg in $packages; do + if [ -z "$(find debian/$pkg -type f)" ]; then + echo "$pkg will be empty" >&2 + empty=1 + fi +done +if [ "$empty" -a -z "$KW_CHECK_NONFATAL" ]; then + exit 1 +fi diff --git a/commands/copy-modules b/commands/copy-modules new file mode 100755 index 0000000..30f9dc5 --- /dev/null +++ b/commands/copy-modules @@ -0,0 +1,168 @@ +#!/bin/bash +# +# Copy modules into the right directories in preparation for building udebs. +# This script is named after the its counterpart in the original +# kernel-image-di package by Joey Hess <joeyh@debian.org>. +# +# Copyright (c) 2001-2002 Herbert Xu <herbert@debian.org> +# +# Usage: copy-modules version flavour installedname + +set -e + +deplist() { + local deps=$1 + local list=$2 + + cp $list $tmpdir/work + + # recursively append external dependencies to $list + while :; do + + # list external dependencies of $work + join -o 2.2 $tmpdir/work $deps | sort -u | comm -23 - $list \ + > $tmpdir/work.new + mv $tmpdir/work.new $tmpdir/work + + # exit if work is empty + [ -s $tmpdir/work ] || break + + # append work to $list + sort -um -o $list $list $tmpdir/work + done +} + +version=$1-$2 +flavour=$2 +installedname=$3 +configdir=$(readlink -f ${KW_CONFIG_DIR:-.}) +arch=$(dpkg-architecture -qDEB_HOST_ARCH) +os=$(dpkg-architecture -qDEB_HOST_ARCH_OS) +home=$PWD + +trap 'rm -rf $tmpdir' EXIT +tmpdir=$(mktemp -d) + +# SOURCEDIR may be set externally to control where to copy from. +if [ -n "$SOURCEDIR" ]; then + moddir=$SOURCEDIR/lib/modules/$installedname +else + moddir=/lib/modules/$installedname +fi + +if [ ! -d $moddir ]; then + exit 0 +fi + +# The directory of modules lists to use. +if [ -d $configdir/modules/$arch-$flavour ]; then + modlistdir=$configdir/modules/$arch-$flavour +elif [ -d $configdir/modules/$flavour ]; then + modlistdir=$configdir/modules/$flavour +else + modlistdir=$configdir/modules/$arch +fi + +if [ "$os" = "linux" ] ; then + if [ "$SOURCEDIR" ]; then + modulesdep=$tmpdir/modules.dep + PATH="/usr/sbin:/sbin:$PATH" depmod \ + -b $SOURCEDIR $installedname -n \ + | sed '/^#/d; /^alias /,$d' >$modulesdep + elif [ -e "$moddir/modules.dep" ]; then + modulesdep=$moddir/modules.dep + else + echo "Installed kernel package is missing $moddir/modules.dep" >&2 + exit 1 + fi + + # get module dependencies from modules.dep + # sort it by field 2 + perl -lne ' + @words=split(" "); + s!'/lib/modules/$installedname'/!! foreach (@words); + if ($words[0] =~ /:$/) { + $words[0]=~s/:$//; + $module=shift @words; + } + foreach (@words) { + print "$module\t$_" unless $_ eq "\\"; + } + ' $modulesdep | sort -k 2,2 > $tmpdir/deps + + if [ ! -s $tmpdir/deps ] && [ ! -e $configdir/no-modules ]; then + echo "No module interdependencies found. This probably means your modules.dep is broken." >&2 + echo "If this is intentional, touch $configdir/no-modules" >&2 + exit 1 + fi +else + touch $tmpdir/deps +fi + +mkdir $tmpdir/module-deps $tmpdir/module-list + +# generate module interrelationships from package-list file +kernel-wedge gen-deps $flavour > $tmpdir/module-deps.packages + +code=0 +# loop over all udebs, sort that all dependent modules are processed first +for i in $( + { + find $modlistdir/ -maxdepth 1 \( -type f -or -type l \) -not -name '*.lnk' -printf "%f\t%f\n" + cat $tmpdir/module-deps.packages + } | tsort | tac +); do + # write dependent (direct and indirect) udebs to exclude + # write dependencies to module-deps/$i + echo $i | join -o 2.2 - $tmpdir/module-deps.packages | { # dependent modules + cd $tmpdir/module-deps + xargs -r sh -c 'printf "%s\n" "$@"; cat "$@"' sh # direct and indirect deps + } | sort -u | tee $tmpdir/module-deps/$i | { # write deps + cd $tmpdir/module-list + xargs -r cat + } | sort -u > $tmpdir/exclude # modules to exclude + + # preprocess file, handle includes and excludes and sort so that + # the joins work, no matter what the order of the input. + kernel-wedge preprocess $modlistdir/$i $moddir | + sort > $tmpdir/module-list/$i + test ${PIPESTATUS[0]} = 0 + + # exclude modules in exclude from dependency list + join -o 2.1,2.2 -2 2 -v 2 $tmpdir/exclude $tmpdir/deps | + sort -k 1,1 > $tmpdir/tmpdeps + + # include dependent modules which are not in a + # dependent udeb into module-list/$i + deplist $tmpdir/tmpdeps $tmpdir/module-list/$i + + if [ -s $tmpdir/module-list/$i ] && dh_listpackages | grep -qx "$i-$version-di"; then + # copy kernel modules to package build dir + cd $moddir + ret=$( ( ( + set +e + tar cfT - $tmpdir/module-list/$i + printf $? >&3 + ) | ( + set +e + dir=$home/debian/$i-$version-di/lib/modules/$installedname + mkdir -p $dir + cd $dir + tar xf - + printf $? >&3 + ) ) 3>&1) + if [ "$ret" != "00" ]; then + echo "tar failed" >&2 + exit $ret + fi + cd $home + + if [ "$os" = linux ]; then + cat >"debian/$i-$version-di.postinst" <<EOF +#!/bin/sh -e +depmod $installedname +EOF + fi + fi +done +exit $code diff --git a/commands/find-dups b/commands/find-dups new file mode 100755 index 0000000..7c4d45a --- /dev/null +++ b/commands/find-dups @@ -0,0 +1,24 @@ +#!/bin/bash -e +# Find duplicate modules. Pass the kernel name. +kernel=$1 +( + shopt -s nullglob + for dir in debian/*-modules-$kernel-di; do + cd $dir + find lib -type f -printf "$dir %p\n" + cd ../.. + done +) | sort -k2 | perl -ne ' + my $configdir = ($ENV{KW_CONFIG_DIR} || "."); + while (<>) { + ($d, $f)=split; + if ($f eq $lf) { print "$d $f\n$ld $lf\n"; $dups++ } + $lf=$f; + $ld=$d + } + if ($dups) { + print STDERR "some modules are in more than one package\n"; + exit 1 unless (-e "$configdir/ignore-dups" || + length($ENV{KW_CHECK_NONFATAL})); + } +' diff --git a/commands/find-unpackaged b/commands/find-unpackaged new file mode 100755 index 0000000..a7bcf6d --- /dev/null +++ b/commands/find-unpackaged @@ -0,0 +1,35 @@ +#!/usr/bin/perl +# Find unpackaged modules. Pass the kernel name and installed name +# (normally the same). +use strict; +use warnings; +use File::Find (); +use File::Spec; + +my $kernel = $ARGV[0]; +my $installedname = $ARGV[1]; + +my $moddir = "/lib/modules/$installedname"; +my $sourcedir = $ENV{SOURCEDIR} || ''; + +my %unpackaged; +my $dir = "$sourcedir$moddir"; +File::Find::find( + sub { + $unpackaged{File::Spec->abs2rel($File::Find::name, $dir)} = 1 + if /\.k?o$/; + }, + $dir); +for my $dir (glob("debian/*-modules-$kernel-di$moddir")) { + File::Find::find( + sub { + delete $unpackaged{File::Spec->abs2rel($File::Find::name, $dir)} + if /\.k?o$/; + }, + $dir); +} + +print "These modules from $kernel are unpackaged:\n"; +for my $path (sort(keys(%unpackaged))) { + print "\t\t$path\n"; +} diff --git a/commands/gen-control b/commands/gen-control new file mode 100755 index 0000000..67922d8 --- /dev/null +++ b/commands/gen-control @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# Generate a debian/control from the control stub, the kernel-versions +# files, and the package-list. +use strict; +use warnings; + +use KernelWedge qw(CONFIG_DIR CONTROL_FIELDS read_kernel_versions + read_package_lists for_each_package); + +my @builddeps; +my %excluded; + +my $fixkernelversion = $ARGV[0]; + +if (open(EXCLUDED, CONFIG_DIR . "/exclude-packages")) { + while (<EXCLUDED>) { + chomp; + $excluded{$_}=1; + } + close EXCLUDED; +} + +my $versions = read_kernel_versions($fixkernelversion); + +for my $ver (@$versions) { + (my $arch, my $kernelversion, undef, undef, undef, my $builddep) = + @$ver; + if (defined($fixkernelversion)) { + $ver->[1] = $fixkernelversion; + } + elsif ($kernelversion eq "-") { + die "kernel version not set in file or on command line"; + } + if ($builddep ne "-") { + foreach my $pkg (split(", ", $builddep)) { + push @builddeps, "$pkg [$arch]"; + } + } +} + +# Building with installed kernel package, or as part of a package? +if (@builddeps) { + open(STUB, "debian/control.stub") || die "debian/control.stub: $!"; + while (<STUB>) { + chomp; + if (/^Build-Depends:/) { + $_=join(", ", $_, @builddeps); + } + print $_."\n"; + } + close STUB; +} + +my $packages = read_package_lists(); + +for_each_package($packages, $versions, sub { + my ($arch, $kernelversion, $flavour, $modlistdir, $template) = @_; + + my %override; + $override{Architecture}=$arch; + $override{Package}=$template->("Package")."-".$kernelversion."-".$flavour."-di"; + $override{'Package-Type'}="udeb"; + $override{'Kernel-Version'}=$kernelversion."-".$flavour; + + return if $excluded{$override{Package}}; + + print "\n"; + + if (! defined $template->("Section") || $template->("Section") !~ /debian-installer$/) { + $override{Section}="debian-installer"; + } + + if (defined $template->("Depends")) { + $override{Depends}=join(", ", + map { $_."-".$kernelversion."-".$flavour."-di" } + # Remove force marker. + map { s/!$//; $_ } + # If the dep is not built for this arch, + # skip it, unless it's forced. + grep { -e "$modlistdir/$_" || /!$/ } + split(", ", $template->("Depends"))); + } + + foreach my $field (CONTROL_FIELDS) { + my $value = $override{$field} || $template->($field); + if ($field eq 'Provides') { + if (defined $value) { + print $field.": ".$template->("Package").", ".$value."\n"; + } + else { + print $field.": ".$template->("Package")."\n"; + } + } + else { + print $field.": ".$value."\n" if defined $value; + } + } +}); diff --git a/commands/gen-deps b/commands/gen-deps new file mode 100755 index 0000000..3a1a90c --- /dev/null +++ b/commands/gen-deps @@ -0,0 +1,35 @@ +#!/usr/bin/perl +# Generates from debian/control a dependency file, suitable to be fed to +# tsort. The file has the base package name on the left, and the package it +# depends on is on the right. It is sorted. +use strict; +use warnings; + +use KernelWedge qw(read_kernel_versions read_package_lists for_each_package); + +my $arch=`dpkg-architecture -qDEB_HOST_ARCH`; +chomp $arch; + +my $flavour=$ARGV[0]; + +my @out; + +my $versions = [[$arch, '-', $flavour]]; +my $packages = read_package_lists(); + +for_each_package($packages, $versions, sub { + my ($arch, $kernelversion, $flavour, $modlistdir, $package) = @_; + my $pkg_name = $package->("Package"); + my @depends = split(", ", $package->("Depends") || ""); + + @out = grep(!/^$pkg_name\t/, @out); + + foreach my $dep (@depends) { + # Skip depends that are not built for this + # architecture. + next unless -e "$modlistdir/$dep"; + push @out, "$pkg_name\t$dep\n"; + } +}); + +print sort @out; diff --git a/commands/help b/commands/help new file mode 100755 index 0000000..4a7a73f --- /dev/null +++ b/commands/help @@ -0,0 +1,12 @@ +#!/bin/sh +LIBDIR=/usr/share/kernel-wedge/commands +set -e +command=$1 +if [ -z "$command" ]; then + kernel-wedge +fi +if [ ! -x "$LIBDIR/$command" ]; then + echo "No such command." + exit 1 +fi +exec man 1 "kernel-wedge-$command" diff --git a/commands/install-files b/commands/install-files new file mode 100755 index 0000000..c88e29a --- /dev/null +++ b/commands/install-files @@ -0,0 +1,170 @@ +#!/usr/bin/perl -w +# Create and populate the package build directories. + +sub doit { + print "\t".join(" ", @_)."\n"; + my $ret=(system(@_) >> 8); + if ($ret != 0) { + die "command exited with status $ret\n"; + } +} + +my $hostarch=`dpkg-architecture -qDEB_HOST_ARCH`; +chomp $hostarch; +my $hostos=`dpkg-architecture -qDEB_HOST_ARCH_OS`; +chomp $hostos; + +my $configdir = ($ENV{KW_CONFIG_DIR} || '.'); +my $fixsourcedir = $ENV{SOURCEDIR}; + +my $fixkernelversion = $ARGV[0]; + +open(KVERS, "$configdir/kernel-versions") || die "kernel-versions: $!"; +my $version = 0; +while (<KVERS>) { + chomp; + next if /^#/ || ! length; + + my ($arch, $kernelversion, $flavour, $installedname, $suffix, $builddep)=split(' ', $_, 6); + if (! length $arch || ! length $kernelversion || + ! length $installedname || ! length $flavour || + ! length $builddep ) { + die "parse error: $_"; + } + next unless $arch eq $hostarch; + + if (defined($fixkernelversion)) { + $kernelversion = $fixkernelversion; + } + elsif ($kernelversion eq "-") { + die "kernel version not set in file or on command line"; + } + + if ($installedname eq "-") { + $installedname = "$kernelversion-$flavour"; + } + + my $sourcedir; + my $bootwrapper_sourcedir; + if (defined $fixsourcedir) { + $sourcedir = $fixsourcedir; + } + else { + # Building with installed kernel package, or as part + # of a package? + if ($builddep ne "-") { + $sourcedir = ""; + } + elsif ($arch =~ /^kfreebsd-/) { + $sourcedir = "debian/kfreebsd-image-$installedname"; + } + else { + ($sourcedir) = grep {-d} + ("debian/linux-image-$installedname", + "debian/linux-image-$installedname-unsigned"); + ($bootwrapper_sourcedir) = grep {-d} + "debian/linux-bootwrapper-$kernelversion"; + } + # Set SOURCEDIR for copy-modules + $ENV{SOURCEDIR} = $sourcedir; + } + + my $extraname=""; + if ($suffix =~ /^[yY]/) { + $extraname="-$kernelversion-$flavour"; + } + elsif ($suffix =~ /^-.+/) { + $extraname="$suffix"; + } + + my $modlistdir; + if (-d "$configdir/modules/$arch-$flavour") { + $modlistdir = "$configdir/modules/$arch-$flavour"; + } + elsif (-d "$configdir/modules/$flavour") { + $modlistdir = "$configdir/modules/$flavour"; + } + else { + $modlistdir = "$configdir/modules/$arch"; + } + + if (! -e "$modlistdir/kernel-image") { + # copy no kernel + } + elsif ($hostos eq 'linux') { + if (-e "$sourcedir/boot/vmlinux-$installedname") { + doit("install", "-D", "-m", 644, + "$sourcedir/boot/vmlinux-$installedname", + "debian/kernel-image-$kernelversion-$flavour-di/boot/vmlinux$extraname"); + } + elsif (-e "$sourcedir/boot/vmlinuz-$installedname") { + doit("install", "-D", "-m", 644, + "$sourcedir/boot/vmlinuz-$installedname", + "debian/kernel-image-$kernelversion-$flavour-di/boot/vmlinuz$extraname"); + } + else { + die "could not find kernel image"; + } + if (-e "$sourcedir/lib/modules/$installedname") { + doit("install", "-d", + "debian/kernel-image-$kernelversion-$flavour-di/lib/modules/$installedname"); + doit("install", "-m", 644, + "$sourcedir/lib/modules/$installedname/modules.builtin", + "$sourcedir/lib/modules/$installedname/modules.order", + "debian/kernel-image-$kernelversion-$flavour-di/lib/modules/$installedname/"); + } + } + elsif (-e "$sourcedir/boot/kfreebsd-$installedname.gz") { + doit("install", "-D", "-m", 644, + "$sourcedir/boot/kfreebsd-$installedname.gz", + "debian/kernel-image-$kernelversion-$flavour-di/boot/kfreebsd$extraname.gz"); + } + else { + die "could not find kernel image"; + } + doit("install", "-D", "-m", 644, + "$sourcedir/boot/System.map-$installedname", + "debian/kernel-image-$kernelversion-$flavour-di/boot/System.map$extraname") + if -e "$sourcedir/boot/System.map-$installedname" && + -e "$modlistdir/kernel-image"; + + # Include extra files to help the d-i build process build kernels + # for certain subarchitectures. This is powerpc-specific at the + # moment. + if (-d "$sourcedir/usr/lib/linux-image-$kernelversion-$flavour") { + my $installdir = + "debian/kernel-image-$kernelversion-$flavour-di" . + "/usr/lib/linux-image-$installedname"; + + doit("install", "-d", + "debian/kernel-image-$kernelversion-$flavour-di/usr/lib"); + doit("cp", "-a", + "$sourcedir/usr/lib/linux-image-$kernelversion-$flavour", + $installdir); + + # Replace symlinks into linux-bootwrapper with the target + # files, rather than building yet another udeb. + if (defined($bootwrapper_sourcedir)) { + opendir(my $dh, $installdir) + or die "opendir: $installdir: $!"; + for my $name (readdir($dh)) { + my $fullname = "$installdir/$name"; + my $target = readlink($fullname); + next unless defined($target) && + $target eq "../linux-bootwrapper-$kernelversion/$name"; + unlink($fullname) + or die "unlink: $fullname: $!"; + doit("cp", "-a", + $bootwrapper_sourcedir . + "/usr/lib/linux-bootwrapper-$kernelversion/$name", + $fullname); + } + closedir($dh); + } + } + + doit("kernel-wedge", "copy-modules", $kernelversion, $flavour, $installedname); + doit("kernel-wedge", "find-dups", "$kernelversion-$flavour"); + doit("kernel-wedge", "find-unpackaged", "$kernelversion-$flavour", $installedname); +} +close KVERS; diff --git a/commands/preprocess b/commands/preprocess new file mode 100755 index 0000000..7cd1041 --- /dev/null +++ b/commands/preprocess @@ -0,0 +1,224 @@ +#!/usr/bin/perl +use strict; +use warnings; +use File::Find (); +use File::Spec (); + +# Dummy filename for when we find that a module is actually built-in +use constant BUILTIN => "<builtin>"; + +my $defconfigdir = $ENV{KW_DEFCONFIG_DIR}; +if (!defined($defconfigdir)) { + print STDERR "$0: Required environment variable \$KW_DEFCONFIG_DIR is not defined\n"; + exit 2; +} +my $sysdir="$defconfigdir/modules/"; +my $os = `dpkg-architecture -qDEB_HOST_ARCH_OS`; +chomp $os; + +my @module_files; +my @modules_builtin; +my %modules; +my %missing; +my %loaded; + +sub find_all_modules { + my ($moddir) = @_; + + File::Find::find({ + follow => 1, # If $moddir is a symlink, follow it. + wanted => sub { + if (/\.ko(?:\.(?:xz|zstd))?$/) { + push @module_files, + File::Spec->abs2rel($File::Find::name, + $moddir); + } + } + }, $moddir); + + if ($os eq 'linux') { + if (open(my $builtin, "$moddir/modules.builtin")) { + while (<$builtin>) { + chomp; + push @modules_builtin, $_; + } + close($builtin); + } + } +} + +sub wildcard_to_regexp { + my ($pattern) = @_; + + # Convert to regexp syntax. We handle '**' as a recursive + # match-all. We don't bother to handle '\' or '[...]'. + my %glob_re = ('?' => '[^/]', + '*' => '[^/]*', + '**' => '.*', + '' => ''); + my $extra_wild; + if ($os eq 'linux') { + # Linux treats '-' and '_' as equivalent, and neither + # is used consistently. So let each match the other. + $glob_re{'-'} = $glob_re{'_'} = '[-_]'; + $extra_wild = '|[-_]'; + } else { + $extra_wild = ''; + } + $pattern =~ s/(.*?)(\*\*|[?*]$extra_wild|)/ + quotemeta($1) . $glob_re{$2}/eg; + + return $pattern; +} + +sub is_really_wild { + my ($pattern) = @_; + + return scalar($pattern =~ /[?*]/); +} + +sub find_modules { + my ($moddir, $pattern, $optional) = @_; + my $wild = is_really_wild($pattern); + + my @regexps; + if ($wild) { + my $re; + if ($pattern =~ m|^([^?*]*)/(.*)|) { + my $subdir = $1; + if (! -d "$moddir/$subdir") { + if (-d "$moddir/kernel/$subdir") { + $subdir = "kernel/$subdir"; + } elsif (!$optional) { + print STDERR "pattern $pattern refers to nonexistent subdirectory\n"; + unless ($ENV{KW_CHECK_NONFATAL}) { + $! = 1; + die; + } + } else { + return (); + } + } + $re = quotemeta($subdir) . '/' . wildcard_to_regexp($2); + } else { + $re = wildcard_to_regexp($pattern); + } + + # Add module suffix; anchor at start and end of string + @regexps = ('^' . $re . '\.ko(?:\.(?:xz|zstd))?$'); + } else { + # If pattern doesn't include a wildcard, find the + # module in any subdir, but prefer a module in the + # kernel subdir. We still do wildcard processing + # to handle equivalence of '-' and '_' for Linux. + my $re = wildcard_to_regexp($pattern); + @regexps = ('^kernel/(?:.*/)?' . $re . '\.ko(?:\.(?:xz|zstd))?$', + '(?:^|/)' . $re . '\.ko(?:\.(?:xz|zstd))?$'); + } + + my @modules; + regexp_loop: + for my $re (@regexps) { + for (@module_files) { + if (/$re/) { + push @modules, $_; + last regexp_loop unless $wild; + } + } + if (!$wild && grep(/$re/, @modules_builtin)) { + push @modules, BUILTIN; + last; + } + } + + return @modules; +} + +sub loadlist { + my ($list, $moddir) = @_; + + if ($loaded{$list}) { + $! = 1; + die "include loop detected loading $list\n"; + } + $loaded{$list}=1; + + my $fh; + unless (open($fh, $list)) { + $! = 1; + die "cannot read $list\n"; + } + while (<$fh>) { + s/^\s*//; + s/\s*$//; + if (/^#include\s+<(.*)>$/) { + my $basename=$1; + loadlist($sysdir.$basename, $moddir); + } + elsif (/^#include\s+"(.*)"$/) { + my $include=$1; + my ($dirname)=$list=~m!(.*/).*!; + loadlist($dirname.$include, $moddir); + } + elsif (/^$/) { + next; + } + elsif (/^#/) { + next; + } + elsif (/^(.*) -$/) { + # If this was explicitly included and is missing, + # we no longer care + delete $missing{$1}; + + for (find_modules($moddir, $1, 1)) { + delete $modules{$_}; + } + } + else { + my ($pattern, $optional, @found); + + if (/^(.*) \?$/) { + ($pattern, $optional) = ($1, 1); + } + # Support dash prefixing for backwards compatibility. + elsif (/^-(.*)/) { + ($pattern, $optional) = ($1, 1); + } else { + ($pattern, $optional) = ($_, 0); + } + + @found = find_modules($moddir, $pattern, $optional); + for (@found) { + $modules{$_} = 1 unless $_ eq BUILTIN; + } + + # Check for missing required module. This is not + # yet an error as it might be excluded later. + if (!is_really_wild($pattern) && !$optional + && !@found) { + $missing{$pattern} = 1; + } + } + } + close $fh; +} + +if (@ARGV < 2) { + print STDERR "$0: Required parameters missing\n"; + exit 2; +} +my ($file, $moddir) = @ARGV; +find_all_modules($moddir); +loadlist($file, $moddir); + +if (keys %missing) { + for (keys %missing) { + print STDERR "missing module $_\n"; + } + exit 1 unless $ENV{'KW_CHECK_NONFATAL'}; +} + +foreach my $m (sort keys %modules) { + print "$m\n"; +} |