#!/usr/bin/perl # # check-config -- check the current config for issues # use strict; use File::Basename; use File::Spec; my $P = 'check-config'; my $test = -1; if ($ARGV[0] eq '--test') { $test = $ARGV[1] + 0; } elsif ($#ARGV != 4) { die "Usage: $P \n"; } my ($configfile, $arch, $flavour, $commonconfig, $warn_only) = @ARGV; my %values = (); # If we are in overridden then still perform the checks and emit the messages # but do not return failure. Those items marked FATAL will alway trigger # failure. my $fail_exit = 1; $fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1'); my $exit_val = 0; # Load up the current configuration values -- FATAL if this fails print "$P: $configfile: loading config\n"; open(CONFIG, "<$configfile") || die "$P: $configfile: open failed -- $! -- aborting\n"; while () { # Pull out values. /^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next; if ($2 eq 'is not set') { $values{$1} = 'n'; } else { $values{$1} = $2; } } close(CONFIG); sub read_annotations { my ($filename) = @_; my %annot; my $form = 1; my ($config, $value, $options); # Keep track of the configs that shouldn't be appended because # they were include_annot from another annotations file. # That's a hash of undefs, aka a set. my %noappend; print "$P: $filename loading annotations\n"; open(my $fd, "<$filename") || die "$P: $filename: open failed -- $! -- aborting\n"; while (<$fd>) { if (/^# FORMAT: (\S+)/) { die "$P: $1: unknown annotations format\n" if ($1 != 2 && $1 != 3); $form = $1; } # Format #3 adds the include directive on top of format #2: if ($form == 3 && /^\s*include(\s|$)/) { # Include quoted or unquoted files: if (/^\s*include\s+"(.*)"\s*$/ || /^\s*include\s+(.*)$/) { # The include is relative to the current file my $include_filename = File::Spec->join(dirname($filename), $1); # Append the include files my %include_annot = read_annotations($include_filename); %annot = ( %annot, %include_annot ); # And marked them to not be appended: my %included_noappend; # Discard the values and keep only the keys @included_noappend{keys %include_annot} = (); %noappend = ( %noappend, %included_noappend ); next; } else { die "$P: Invalid include: $_"; } } /^#/ && next; chomp; /^$/ && next; /^CONFIG_/ || next; if ($form == 1) { ($config, $value, $options) = split(' ', $_, 3); } elsif ($form >= 2) { ($config, $options) = split(' ', $_, 2); } if (exists $noappend{$config}) { delete $annot{$config}; delete $noappend{$config}; } $annot{$config} = $annot{$config} . ' ' . $options; } close($fd); return %annot; } # ANNOTATIONS: check any annotations marked for enforcement my $annotations = "$commonconfig/annotations"; my %annot = read_annotations($annotations); my $pass = 0; my $total = 0; my ($config, $value, $options, $option, $check, $policy); for $config (keys %annot) { $check = 0; $options = $annot{$config}; $policy = undef; while ($options =~ /\s*(\S+)<(.*?)?>/g) { ($option, $value) = ($1, $2); if ($option eq 'mark' && $value eq 'ENFORCED') { $check = 1; } elsif ($option eq 'policy') { if ($value =~ /^{/) { $value =~ s/:/=>/g; $policy = eval($value); warn "$config: $@" if ($@); } else { $policy = undef; } } } if ($check == 1 && !defined($policy)) { print "$P: INVALID POLICY (use policy<{...}>) $config$options\n"; $total++; $check = 0; } if ($check) { my $is = '-'; $is = $values{$config} if (defined $values{$config}); my $value = '-'; for my $which ("$arch-$flavour", "$arch-*", "*-$flavour", "$arch", "*") { if (defined $policy->{$which}) { $value = $policy->{$which}; last; } } if ($is eq $value) { $pass++; } else { print "$P: FAIL ($is != $value): $config$options\n"; $exit_val = $fail_exit; } $total++; } } print "$P: $pass/$total checks passed -- exit $exit_val\n"; exit $exit_val;