]>
Commit | Line | Data |
---|---|---|
0d34a427 LO |
1 | #!/usr/bin/perl |
2 | # | |
3 | # check-config -- check the current config for issues | |
4 | # | |
5 | use strict; | |
be89b232 MHC |
6 | use File::Basename; |
7 | use File::Spec; | |
0d34a427 LO |
8 | |
9 | my $P = 'check-config'; | |
10 | ||
11 | my $test = -1; | |
12 | if ($ARGV[0] eq '--test') { | |
13 | $test = $ARGV[1] + 0; | |
14 | } elsif ($#ARGV != 4) { | |
15 | die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only>\n"; | |
16 | } | |
17 | ||
be89b232 | 18 | my ($configfile, $arch, $flavour, $commonconfig, $warn_only) = @ARGV; |
0d34a427 LO |
19 | |
20 | my %values = (); | |
21 | ||
22 | # If we are in overridden then still perform the checks and emit the messages | |
23 | # but do not return failure. Those items marked FATAL will alway trigger | |
24 | # failure. | |
25 | my $fail_exit = 1; | |
26 | $fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1'); | |
27 | my $exit_val = 0; | |
28 | ||
29 | # Load up the current configuration values -- FATAL if this fails | |
be89b232 MHC |
30 | print "$P: $configfile: loading config\n"; |
31 | open(CONFIG, "<$configfile") || die "$P: $configfile: open failed -- $! -- aborting\n"; | |
0d34a427 LO |
32 | while (<CONFIG>) { |
33 | # Pull out values. | |
34 | /^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next; | |
35 | if ($2 eq 'is not set') { | |
36 | $values{$1} = 'n'; | |
37 | } else { | |
38 | $values{$1} = $2; | |
39 | } | |
40 | } | |
41 | close(CONFIG); | |
42 | ||
be89b232 MHC |
43 | sub read_annotations { |
44 | my ($filename) = @_; | |
45 | my %annot; | |
46 | my $form = 1; | |
47 | my ($config, $value, $options); | |
48 | ||
49 | # Keep track of the configs that shouldn't be appended because | |
50 | # they were include_annot from another annotations file. | |
51 | # That's a hash of undefs, aka a set. | |
52 | my %noappend; | |
53 | ||
54 | print "$P: $filename loading annotations\n"; | |
55 | open(my $fd, "<$filename") || | |
56 | die "$P: $filename: open failed -- $! -- aborting\n"; | |
57 | while (<$fd>) { | |
0d34a427 | 58 | if (/^# FORMAT: (\S+)/) { |
be89b232 MHC |
59 | die "$P: $1: unknown annotations format\n" if ($1 != 2 && $1 != 3); |
60 | $form = $1; | |
61 | } | |
62 | ||
63 | # Format #3 adds the include directive on top of format #2: | |
64 | if ($form == 3 && /^\s*include(\s|$)/) { | |
65 | # Include quoted or unquoted files: | |
66 | if (/^\s*include\s+"(.*)"\s*$/ || /^\s*include\s+(.*)$/) { | |
67 | # The include is relative to the current file | |
68 | my $include_filename = File::Spec->join(dirname($filename), $1); | |
69 | # Append the include files | |
70 | my %include_annot = read_annotations($include_filename); | |
71 | %annot = ( %annot, %include_annot ); | |
72 | # And marked them to not be appended: | |
73 | my %included_noappend; | |
74 | # Discard the values and keep only the keys | |
75 | @included_noappend{keys %include_annot} = (); | |
76 | %noappend = ( %noappend, %included_noappend ); | |
77 | next; | |
78 | } else { | |
79 | die "$P: Invalid include: $_"; | |
80 | } | |
0d34a427 LO |
81 | } |
82 | ||
83 | /^#/ && next; | |
84 | chomp; | |
85 | /^$/ && next; | |
0d34a427 LO |
86 | /^CONFIG_/ || next; |
87 | ||
88 | if ($form == 1) { | |
be89b232 MHC |
89 | ($config, $value, $options) = split(' ', $_, 3); |
90 | } elsif ($form >= 2) { | |
91 | ($config, $options) = split(' ', $_, 2); | |
0d34a427 LO |
92 | } |
93 | ||
be89b232 MHC |
94 | if (exists $noappend{$config}) { |
95 | delete $annot{$config}; | |
96 | delete $noappend{$config}; | |
97 | } | |
0d34a427 | 98 | $annot{$config} = $annot{$config} . ' ' . $options; |
be89b232 MHC |
99 | } |
100 | close($fd); | |
101 | return %annot; | |
0d34a427 | 102 | } |
0d34a427 | 103 | |
be89b232 MHC |
104 | # ANNOTATIONS: check any annotations marked for enforcement |
105 | my $annotations = "$commonconfig/annotations"; | |
106 | my %annot = read_annotations($annotations); | |
107 | ||
108 | my $pass = 0; | |
109 | my $total = 0; | |
110 | my ($config, $value, $options, $option, $check, $policy); | |
0d34a427 LO |
111 | for $config (keys %annot) { |
112 | $check = 0; | |
113 | $options = $annot{$config}; | |
114 | ||
115 | $policy = undef; | |
116 | while ($options =~ /\s*(\S+)<(.*?)?>/g) { | |
117 | ($option, $value) = ($1, $2); | |
118 | ||
119 | if ($option eq 'mark' && $value eq 'ENFORCED') { | |
120 | $check = 1; | |
121 | ||
122 | } elsif ($option eq 'policy') { | |
123 | if ($value =~ /^{/) { | |
124 | $value =~ s/:/=>/g; | |
125 | $policy = eval($value); | |
126 | warn "$config: $@" if ($@); | |
127 | } else { | |
128 | $policy = undef; | |
129 | } | |
130 | } | |
131 | } | |
132 | if ($check == 1 && !defined($policy)) { | |
133 | print "$P: INVALID POLICY (use policy<{...}>) $config$options\n"; | |
134 | $total++; | |
135 | $check = 0; | |
136 | } | |
137 | if ($check) { | |
138 | my $is = '-'; | |
139 | $is = $values{$config} if (defined $values{$config}); | |
140 | ||
141 | my $value = '-'; | |
142 | for my $which ("$arch-$flavour", "$arch-*", "*-$flavour", "$arch", "*") { | |
143 | if (defined $policy->{$which}) { | |
144 | $value = $policy->{$which}; | |
145 | last; | |
146 | } | |
147 | } | |
148 | if ($is eq $value) { | |
149 | $pass++; | |
150 | } else { | |
151 | print "$P: FAIL ($is != $value): $config$options\n"; | |
152 | $exit_val = $fail_exit; | |
153 | } | |
154 | $total++; | |
155 | } | |
156 | } | |
157 | ||
158 | print "$P: $pass/$total checks passed -- exit $exit_val\n"; | |
159 | exit $exit_val; |