|
Jean Delvare |
591eab |
#!/usr/bin/perl -w
|
|
Jean Delvare |
591eab |
#
|
|
Jean Delvare |
591eab |
#############################################################################
|
|
Jean Delvare |
591eab |
# Copyright (c) 2014 Jean Delvare <jdelvare@suse.de>
|
|
Jean Delvare |
591eab |
# All Rights Reserved.
|
|
Jean Delvare |
591eab |
#
|
|
Jean Delvare |
591eab |
# This program is free software; you can redistribute it and/or
|
|
Jean Delvare |
591eab |
# modify it under the terms of version 2 of the GNU General Public License as
|
|
Jean Delvare |
591eab |
# published by the Free Software Foundation.
|
|
Jean Delvare |
591eab |
#
|
|
Jean Delvare |
591eab |
# This program is distributed in the hope that it will be useful,
|
|
Jean Delvare |
591eab |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Jean Delvare |
591eab |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Jean Delvare |
591eab |
# GNU General Public License for more details.
|
|
Jean Delvare |
591eab |
#############################################################################
|
|
Jean Delvare |
591eab |
#
|
|
Jean Delvare |
591eab |
# The purpose of this script is to catch, and in most cases fix,
|
|
Jean Delvare |
591eab |
# inconsistencies between supported.conf and the set of modules being actually
|
|
Jean Delvare |
591eab |
# installed. It is recommended to run it on a complete set of installed modules
|
|
Jean Delvare |
591eab |
# (all flavors and architectures) otherwise you may get false positives. Note
|
|
Jean Delvare |
591eab |
# that you can pass as many modules directories as you want.
|
|
Jean Delvare |
591eab |
#
|
|
Jean Delvare |
591eab |
# Usage: supported-conf-fixup [OPTIONS] supported.conf [/lib/modules/x.x-flavor ...]
|
|
Jean Delvare |
591eab |
# Options:
|
|
Jean Delvare |
591eab |
# -h, --help Print usage and exit
|
|
Jean Delvare |
591eab |
# --mod-path Report wrong module paths
|
|
Jean Delvare |
591eab |
# --mod-missing Report missing modules
|
|
Jean Delvare |
591eab |
# --mask-path Report wrong mask paths
|
|
Jean Delvare |
591eab |
# --mask-missing Report missing mask paths
|
|
Jean Delvare |
6a5951 |
# --not-listed Report unlisted modules
|
|
Jean Delvare |
591eab |
# -v, --verbose Be verbose
|
|
Jean Delvare |
591eab |
# -o, --output file Write updated supported.conf to file
|
|
Jean Delvare |
430664 |
# --sort Sort the output file
|
|
Jean Delvare |
591eab |
#
|
|
Jean Delvare |
591eab |
# To do: better handling of _ vs -
|
|
Jean Delvare |
591eab |
# To do: better handling of .ko being optional
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
use strict;
|
|
Jean Delvare |
591eab |
use vars qw($sup_conf_file @sup_conf_data @supported_mod @supported_mask %supported
|
|
Jean Delvare |
591eab |
%installed $n_ins %installed_paths %builtin %not_listed $verbose
|
|
Jean Delvare |
6a5951 |
$check_mod_path $check_mod_missing $check_mask_path $check_mask_missing
|
|
Jean Delvare |
6a5951 |
$check_not_listed $output $n_err $n_corrected $usage $sort);
|
|
Jean Delvare |
591eab |
use File::Find;
|
|
Jean Delvare |
591eab |
use Getopt::Long;
|
|
Jean Delvare |
591eab |
use Fcntl;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Data structures:
|
|
Jean Delvare |
591eab |
# @sup_conf_data contains raw lines from supported.conf
|
|
Jean Delvare |
591eab |
# @supported_mod contains hashes with the following keys:
|
|
Jean Delvare |
591eab |
# - line: line number in supported.conf
|
|
Jean Delvare |
591eab |
# - module path: relative path + module name
|
|
Jean Delvare |
591eab |
# @supported_mask contains hashes with the following keys:
|
|
Jean Delvare |
591eab |
# - line: line number in supported.conf
|
|
Jean Delvare |
591eab |
# - mask path: relative path + *
|
|
Jean Delvare |
591eab |
# %supported contains the same information as @supported_mod + @supported_mask,
|
|
Jean Delvare |
591eab |
# but as a module/mask path => line mapping
|
|
Jean Delvare |
591eab |
# %installed contains the list of installed modules, as a
|
|
Jean Delvare |
591eab |
# module name => module paths mapping
|
|
Jean Delvare |
591eab |
# %installed_paths records paths which contain installed modules (only
|
|
Jean Delvare |
591eab |
# keys are meaningful)
|
|
Jean Delvare |
591eab |
# %not_listed keys list installed modules which aren't listed in supported.conf
|
|
Jean Delvare |
591eab |
# (so their support status is unknown)
|
|
Jean Delvare |
591eab |
# %builtin contains the list of built-in modules, as a
|
|
Jean Delvare |
591eab |
# module name => module paths mapping
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
Getopt::Long::Configure("bundling");
|
|
Jean Delvare |
77722e |
$verbose = 0;
|
|
Jean Delvare |
591eab |
GetOptions(
|
|
Jean Delvare |
591eab |
"help|h" => \$usage,
|
|
Jean Delvare |
591eab |
"mod-path" => \$check_mod_path,
|
|
Jean Delvare |
591eab |
"mod-missing" => \$check_mod_missing,
|
|
Jean Delvare |
591eab |
"mask-path" => \$check_mask_path,
|
|
Jean Delvare |
591eab |
"mask-missing" => \$check_mask_missing,
|
|
Jean Delvare |
591eab |
"not-listed" => \$check_not_listed,
|
|
Jean Delvare |
591eab |
"verbose|v+" => \$verbose,
|
|
Jean Delvare |
591eab |
"output|o=s" => \$output,
|
|
Jean Delvare |
430664 |
"sort" => \$sort,
|
|
Jean Delvare |
591eab |
) or exit 1;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
if ($usage || @ARGV < 1) {
|
|
Jean Delvare |
591eab |
print STDERR
|
|
Jean Delvare |
591eab |
"Usage: $0 [OPTIONS] supported.conf [/lib/modules/x.x-flavor ...]
|
|
Jean Delvare |
591eab |
Options:
|
|
Jean Delvare |
591eab |
-h, --help Print usage and exit
|
|
Jean Delvare |
591eab |
--mod-path Report wrong module paths
|
|
Jean Delvare |
591eab |
--mod-missing Report missing modules
|
|
Jean Delvare |
591eab |
--mask-path Report wrong mask paths
|
|
Jean Delvare |
591eab |
--mask-missing Report missing mask paths
|
|
Jean Delvare |
591eab |
--not-listed Report unlisted modules
|
|
Jean Delvare |
591eab |
-v, --verbose Be verbose
|
|
Jean Delvare |
591eab |
-o, --output file Write updated supported.conf to file
|
|
Jean Delvare |
430664 |
--sort Sort the output file
|
|
Jean Delvare |
591eab |
";
|
|
Jean Delvare |
591eab |
exit 1;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
$sup_conf_file = shift @ARGV;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
sub gather_path
|
|
Jean Delvare |
591eab |
{
|
|
Jean Delvare |
591eab |
my $file_or_dir = $_;
|
|
Jean Delvare |
591eab |
my $module_path = $File::Find::name;
|
|
Jean Delvare |
591eab |
my ($path, $module);
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Special case for modules.builtin
|
|
Jean Delvare |
591eab |
if ($file_or_dir eq "modules.builtin") {
|
|
Jean Delvare |
591eab |
open(BUILTIN, "<$file_or_dir") or die;
|
|
Jean Delvare |
591eab |
while (<BUILTIN>) {
|
|
|
deab24 |
next unless m,^kernel/(.*)/([^/]+)\.ko(\.xz|\.gz|\.zst)?$,;
|
|
Jean Delvare |
591eab |
$path = $1;
|
|
Jean Delvare |
591eab |
$module = $2;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
if (exists $builtin{$module}) {
|
|
Jean Delvare |
591eab |
next if grep { $_ eq $path } @{$builtin{$module}};
|
|
Jean Delvare |
591eab |
# There can be duplicates with different paths across architectures
|
|
Jean Delvare |
591eab |
push @{$builtin{$module}}, $path;
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
$builtin{$module} = [ $path ];
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
close(BUILTIN);
|
|
Jean Delvare |
591eab |
return;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
return unless $module_path =~ s,^(.*?/)?kernel/,,;
|
|
Jean Delvare |
591eab |
if (-f $file_or_dir) {
|
|
|
deab24 |
return unless $module_path =~ m,^(.*)/([^/]+)\.ko(\.xz|\.gz|\.zst)?$,;
|
|
Jean Delvare |
591eab |
$path = $1;
|
|
Jean Delvare |
591eab |
$module = $2;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
if (exists $installed{$module}) {
|
|
Jean Delvare |
591eab |
return if grep { $_ eq $path } @{$installed{$module}};
|
|
Jean Delvare |
591eab |
# There can be duplicates with different paths across architectures
|
|
Jean Delvare |
591eab |
push @{$installed{$module}}, $path;
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
$installed{$module} = [ $path ];
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
$n_ins++;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
$not_listed{"$path/$module"} = 1;
|
|
Jean Delvare |
591eab |
} elsif (-d $file_or_dir) {
|
|
Jean Delvare |
591eab |
$installed_paths{$module_path}++;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# First, gather all installed modules with their path
|
|
Jean Delvare |
591eab |
$n_ins = 0;
|
|
Jean Delvare |
591eab |
if (@ARGV) {
|
|
Jean Delvare |
591eab |
find(\&gather_path, @ARGV);
|
|
Jean Delvare |
591eab |
print "Found $n_ins installed modules\n";
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
sub matching_mask
|
|
Jean Delvare |
591eab |
{
|
|
Jean Delvare |
591eab |
my $module_path = shift;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
foreach my $mask (@supported_mask) {
|
|
Jean Delvare |
591eab |
my $prefix = $mask->{module_path};
|
|
Jean Delvare |
591eab |
$prefix =~ s,/*,,;
|
|
Jean Delvare |
591eab |
return "$mask->{module_path} at line $mask->{line}"
|
|
Jean Delvare |
591eab |
if $module_path =~ m,^$prefix,;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Then, parse supported.conf
|
|
Jean Delvare |
591eab |
open(SUP, $sup_conf_file) || die;
|
|
Jean Delvare |
591eab |
while (<SUP>) {
|
|
Jean Delvare |
591eab |
# Store raw data, needed to generate the updated file
|
|
Jean Delvare |
591eab |
push @sup_conf_data, $_;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
chomp;
|
|
Jean Delvare |
591eab |
s/#.*$//; # Strip comments
|
|
Jean Delvare |
591eab |
s/\s+$//; # Strip trailing whitespace
|
|
Jean Delvare |
591eab |
next if m/^$/; # Skip blank lines
|
|
Michal Kubecek |
ce984f |
s/^([+-]([\w\d-]+)?\s)*\s*//; # Strip guards
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
my $new_entry = {
|
|
Jean Delvare |
591eab |
'line' => $.,
|
|
Jean Delvare |
591eab |
'module_path' => $_,
|
|
Jean Delvare |
591eab |
};
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Check for masks that come too early
|
|
Jean Delvare |
591eab |
my $matching_mask = matching_mask($_);
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
if (m/\/\*$/) {
|
|
Jean Delvare |
591eab |
print "WARNING: Mask $_ at line $. is shadowed by $matching_mask\n"
|
|
Jean Delvare |
591eab |
if $matching_mask;
|
|
Jean Delvare |
591eab |
push @supported_mask, $new_entry;
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
print "WARNING: Module $_ at line $. is shadowed by $matching_mask\n"
|
|
Jean Delvare |
591eab |
if $matching_mask;
|
|
Jean Delvare |
591eab |
push @supported_mod, $new_entry;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Check for duplicate entries
|
|
Jean Delvare |
591eab |
if (exists $supported{$_}) {
|
|
Jean Delvare |
591eab |
print "WARNING: Duplicate entry $_, lines $supported{$_} and $.\n";
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
$supported{$_} = $.;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
close(SUP);
|
|
Jean Delvare |
591eab |
print "Gathered ", scalar @supported_mod, " modules and ",
|
|
Jean Delvare |
591eab |
scalar @supported_mask, " masks from $sup_conf_file\n";
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Amongst all paths containing modules, list the ones which end the same as the parameter
|
|
Jean Delvare |
591eab |
sub candidate_paths
|
|
Jean Delvare |
591eab |
{
|
|
Jean Delvare |
591eab |
my $path = shift;
|
|
Jean Delvare |
591eab |
(my $last = $path) =~ s,.*/,,;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
return grep { $_ =~ m,[\s/]$last$, } keys %installed_paths;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
sub check_path
|
|
Jean Delvare |
591eab |
{
|
|
Jean Delvare |
591eab |
my $entry = $_;
|
|
Jean Delvare |
591eab |
my $module_path = $entry->{module_path};
|
|
Jean Delvare |
591eab |
my $line = $entry->{line};
|
|
Jean Delvare |
591eab |
my ($path, $module, $ext, $module_alt);
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
if ($module_path =~ m,^(.*)/\*$,) {
|
|
Jean Delvare |
591eab |
$path = $1;
|
|
Jean Delvare |
591eab |
# Mask, check that this directory exists
|
|
Jean Delvare |
591eab |
if (exists $installed_paths{$path}) {
|
|
Jean Delvare |
591eab |
# Mark all matching modules as listed
|
|
Jean Delvare |
591eab |
foreach $module (keys %not_listed) {
|
|
Jean Delvare |
591eab |
delete $not_listed{$module} if $module =~ m,^$path/,;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
# Check if other installed paths end with the same component
|
|
Jean Delvare |
591eab |
my @candidate = candidate_paths($path);
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
if (0 == scalar @candidate) {
|
|
Jean Delvare |
591eab |
if ($check_mask_missing) {
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Referenced path $path doesn't exist, no candidate\n"
|
|
Jean Delvare |
591eab |
if $verbose;
|
|
Jean Delvare |
591eab |
$n_err++;
|
|
Jean Delvare |
591eab |
# Delete that line
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] = '';
|
|
Jean Delvare |
591eab |
$n_corrected++;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
} elsif (1 == scalar @candidate) {
|
|
Jean Delvare |
591eab |
if ($check_mask_path) {
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Mask path $path is wrong, correct is $candidate[0]\n"
|
|
Jean Delvare |
591eab |
if $verbose;
|
|
Jean Delvare |
591eab |
$n_err++;
|
|
Jean Delvare |
591eab |
# Update the path
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] =~ s,(\s)$path/,$1$candidate[0]/,;
|
|
Jean Delvare |
591eab |
$n_corrected++;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Strip trailing whitespace
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] =~ s,\s*\n$,\n,;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
if ($check_mask_path) {
|
|
Jean Delvare |
591eab |
$n_err++;
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Referenced path $path doesn't exist, too many candidates (",
|
|
Jean Delvare |
591eab |
join(", ", @candidate), ")\n"
|
|
Jean Delvare |
591eab |
if $verbose;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
return;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
|
deab24 |
unless ($module_path =~ m,^(.*)/([^/]+)(\.ko)(\.xz|\.gz|\.zst)?$, ||
|
|
Jean Delvare |
591eab |
$module_path =~ m,^(.*)/([^/]+)$,) {
|
|
Jean Delvare |
591eab |
print STDERR "$sup_conf_file: $line: Unparsable module path: $module_path\n";
|
|
Jean Delvare |
591eab |
return;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
$path = $1;
|
|
Jean Delvare |
591eab |
$module = $2;
|
|
Jean Delvare |
591eab |
$ext = defined $3 ? $3 : '';
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Exact name may be different so try all variants
|
|
Jean Delvare |
591eab |
if (!exists $installed{$module}) {
|
|
Jean Delvare |
591eab |
($module_alt = $module) =~ tr/-/_/;
|
|
Jean Delvare |
591eab |
if (exists $installed{$module_alt}) {
|
|
Jean Delvare |
591eab |
$module = $module_alt;
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
($module_alt = $module) =~ tr/_/-/;
|
|
Jean Delvare |
591eab |
if (exists $installed{$module_alt}) {
|
|
Jean Delvare |
591eab |
$module = $module_alt;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Module, check if it exists
|
|
Jean Delvare |
591eab |
if (!exists $installed{$module}) {
|
|
Jean Delvare |
591eab |
if ($check_mod_missing) {
|
|
Jean Delvare |
591eab |
if (exists $builtin{$module}) {
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Referenced module $module is built-in\n"
|
|
Jean Delvare |
591eab |
if $verbose >= 2;
|
|
Jean Delvare |
591eab |
} else {
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Referenced module $module doesn't exist\n"
|
|
Jean Delvare |
591eab |
if $verbose;
|
|
Jean Delvare |
591eab |
$n_err++;
|
|
Jean Delvare |
591eab |
# Delete that line
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] = '';
|
|
Jean Delvare |
591eab |
$n_corrected++;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
if ($check_mod_path) {
|
|
Jean Delvare |
591eab |
if (exists $builtin{$module} && !grep { $_ eq $path } @{$builtin{$module}}) {
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Referenced module $module may be built-in but path doesn't match (",
|
|
Jean Delvare |
591eab |
join(" and ", @{$builtin{$module}}),
|
|
Jean Delvare |
591eab |
", supported.conf says $path\n" if $verbose;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
} elsif (!grep { $_ eq $path } @{$installed{$module}}) {
|
|
Jean Delvare |
591eab |
if ($check_mod_path) {
|
|
Jean Delvare |
591eab |
print "$sup_conf_file: $line: Path for module $module is wrong: installed at ",
|
|
Jean Delvare |
591eab |
join(" and ", @{$installed{$module}}),
|
|
Jean Delvare |
591eab |
", supported.conf says $path\n" if $verbose;
|
|
Jean Delvare |
591eab |
$n_err++;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# If there is only one candidate, assume it is right
|
|
Jean Delvare |
591eab |
if (1 == @{$installed{$module}}) {
|
|
Jean Delvare |
591eab |
# Update the path
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] =~ s,(\s)$path/,$1$installed{$module}->[0]/,;
|
|
Jean Delvare |
591eab |
$n_corrected++;
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Attempt to preserve tab-based comment alignment
|
|
Jean Delvare |
591eab |
if ($sup_conf_data[$line - 1] =~ m,(\t+)#,) {
|
|
Jean Delvare |
591eab |
my $old_len = length "$path/$module$ext";
|
|
Jean Delvare |
591eab |
my $new_len = length "$installed{$module}->[0]/$module$ext";
|
|
Jean Delvare |
591eab |
my $align = (int($old_len / 8) + length $1) * 8;
|
|
Jean Delvare |
591eab |
my $new_spacing = "\t" x ($align / 8 - int($new_len / 8));
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] =~ s,(\t+)#,$new_spacing#,;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
# Strip trailing whitespace
|
|
Jean Delvare |
591eab |
$sup_conf_data[$line - 1] =~ s,\s*\n$,\n,;
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Mark as listed
|
|
Jean Delvare |
591eab |
delete $not_listed{"$path/$module"};
|
|
Jean Delvare |
591eab |
# Exact name may be different so try all variants
|
|
Jean Delvare |
591eab |
$module =~ tr/-/_/;
|
|
Jean Delvare |
591eab |
delete $not_listed{"$path/$module"};
|
|
Jean Delvare |
591eab |
$module =~ tr/_/-/;
|
|
Jean Delvare |
591eab |
delete $not_listed{"$path/$module"};
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# Finally, compare both sets and report and/or correct inconsistencies
|
|
Jean Delvare |
591eab |
$n_err = $n_corrected = 0;
|
|
Jean Delvare |
591eab |
print "\n";
|
|
Jean Delvare |
591eab |
check_path($_) foreach (@supported_mod);
|
|
Jean Delvare |
591eab |
check_path($_) foreach (@supported_mask);
|
|
Jean Delvare |
591eab |
print "\nFound $n_err ", $n_err > 1 ? "errors" : "error", " (corrected $n_corrected)\n"
|
|
Jean Delvare |
591eab |
if ($check_mod_path || $check_mod_missing || $check_mask_path || $check_mask_missing);
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
591eab |
# If requested, print unlisted modules
|
|
Jean Delvare |
591eab |
if ($check_not_listed) {
|
|
Jean Delvare |
591eab |
print "Modules installed but not listed in supported.conf:\n";
|
|
Jean Delvare |
591eab |
print "$_\n" foreach (sort keys %not_listed);
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
|
|
Jean Delvare |
430664 |
# Module name comparison function for sorting
|
|
Jean Delvare |
430664 |
sub modcmp
|
|
Jean Delvare |
430664 |
{
|
|
Jean Delvare |
430664 |
my $mod1 = $a;
|
|
Jean Delvare |
430664 |
my $mod2 = $b;
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
$mod1 =~ s/\s*#.*$//mg; # Strip comments
|
|
Jean Delvare |
430664 |
$mod2 =~ s/\s*#.*$//mg; # Strip comments
|
|
Jean Delvare |
430664 |
$mod1 =~ s/\n//g; # Strip empty lines
|
|
Jean Delvare |
430664 |
$mod2 =~ s/\n//g; # Strip empty lines
|
|
Michal Kubecek |
ce984f |
$mod1 =~ s/^([+-]([\w\d-]+)?\s)*\s*//; # Strip guards
|
|
Michal Kubecek |
ce984f |
$mod2 =~ s/^([+-]([\w\d-]+)?\s)*\s*//; # Strip guards
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
5e526c |
# Masks must always go after explict module names they match
|
|
Jean Delvare |
5e526c |
return 1 if $mod1 =~ m/^(.*)\/\*$/ && substr($mod2, 0, length($1)) eq $1;
|
|
Jean Delvare |
5e526c |
return -1 if $mod2 =~ m/^(.*)\/\*$/ && substr($mod1, 0, length($1)) eq $1;
|
|
Jean Delvare |
5e526c |
|
|
Jean Delvare |
430664 |
return $mod1 cmp $mod2;
|
|
Jean Delvare |
430664 |
}
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
sub sort_data
|
|
Jean Delvare |
430664 |
{
|
|
Jean Delvare |
430664 |
my (@header, @sorted, $n, $comment);
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
# Preserve comments and blank lines at the top of supported.conf
|
|
Jean Delvare |
430664 |
for ($n = 0; $n < @sup_conf_data; $n++) {
|
|
Jean Delvare |
430664 |
last unless $sup_conf_data[$n] =~ m/^\s*(#|$)/;
|
|
Jean Delvare |
430664 |
push @header, $sup_conf_data[$n];
|
|
Jean Delvare |
430664 |
}
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
# Store all the rest in an array, except blank lines
|
|
Jean Delvare |
430664 |
for ($comment = ""; $n < @sup_conf_data; $n++) {
|
|
Jean Delvare |
430664 |
next if $sup_conf_data[$n] =~ m/^\s*$/;
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
# Comments are attached to the module which follows or precedes
|
|
Jean Delvare |
430664 |
# them. We use a heuristic to distinguish between the two
|
|
Jean Delvare |
430664 |
# cases: comments which start before column 24 are attached to
|
|
Jean Delvare |
430664 |
# the module which follows them, while comments which start
|
|
Jean Delvare |
430664 |
# after column 24 are attached to teh module which precedes
|
|
Jean Delvare |
430664 |
# them.
|
|
Jean Delvare |
430664 |
if ($sup_conf_data[$n] =~ m/^(\s*)#/) {
|
|
Jean Delvare |
430664 |
my $leading = $1;
|
|
Jean Delvare |
430664 |
$leading =~ s/ {1,7}\t/\t/g;
|
|
Jean Delvare |
430664 |
$leading =~ s/ {8}/\t/g;
|
|
Jean Delvare |
430664 |
if (length($leading) <= 3) {
|
|
Jean Delvare |
430664 |
$comment .= $sup_conf_data[$n];
|
|
Jean Delvare |
430664 |
} else {
|
|
Jean Delvare |
430664 |
$sorted[@sorted - 1] .= $sup_conf_data[$n];
|
|
Jean Delvare |
430664 |
}
|
|
Jean Delvare |
430664 |
next;
|
|
Jean Delvare |
430664 |
}
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
push @sorted, $comment . $sup_conf_data[$n];
|
|
Jean Delvare |
430664 |
$comment = "";
|
|
Jean Delvare |
430664 |
}
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
# Sort the module list
|
|
Jean Delvare |
430664 |
@sorted = sort modcmp @sorted;
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
430664 |
# Merge the header and the module list
|
|
Jean Delvare |
430664 |
@sup_conf_data = (@header, @sorted);
|
|
Jean Delvare |
430664 |
}
|
|
Jean Delvare |
430664 |
|
|
Jean Delvare |
591eab |
# If requested, write a fixed version of supported.conf
|
|
Jean Delvare |
591eab |
if ($output) {
|
|
Jean Delvare |
430664 |
sort_data() if $sort;
|
|
Jean Delvare |
591eab |
open(OUTPUT, ">$output") || die;
|
|
Jean Delvare |
591eab |
for (my $n = 0; $n < @sup_conf_data; $n++) {
|
|
Jean Delvare |
591eab |
# Merge blank lines
|
|
Jean Delvare |
591eab |
print OUTPUT $sup_conf_data[$n]
|
|
Jean Delvare |
591eab |
unless $sup_conf_data[$n] eq "\n" && $sup_conf_data[$n - 1] eq "\n";
|
|
Jean Delvare |
591eab |
}
|
|
Jean Delvare |
591eab |
close(OUTPUT);
|
|
Jean Delvare |
591eab |
print "Fixed supported.conf saved as $output\n";
|
|
Jean Delvare |
591eab |
} elsif ($n_corrected) {
|
|
Jean Delvare |
591eab |
print "Use option -o to write out the corrected file\n";
|
|
Jean Delvare |
430664 |
} elsif ($sort) {
|
|
Jean Delvare |
430664 |
print "Use option -o to write out the sorted file\n";
|
|
Jean Delvare |
591eab |
}
|