diff options
Diffstat (limited to 'commands/preprocess')
-rwxr-xr-x | commands/preprocess | 224 |
1 files changed, 224 insertions, 0 deletions
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"; +} |