]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - debian/scripts/config-check
UBUNTU: [debian] Initial debian and ubuntu directories
[mirror_ubuntu-zesty-kernel.git] / debian / scripts / config-check
CommitLineData
356bd1e1
LO
1#!/usr/bin/perl
2#
3# check-config -- check the current config for issues
4#
5use strict;
6
7my $P = 'check-config';
8
9my $test = -1;
10if ($ARGV[0] eq '--test') {
11 $test = $ARGV[1] + 0;
12} elsif ($#ARGV != 4) {
13 die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only>\n";
14}
15
16my ($config, $arch, $flavour, $commonconfig, $warn_only) = @ARGV;
17
18my $checks = "$commonconfig/enforce";
19my %values = ();
20
21# If we are in overridden then still perform the checks and emit the messages
22# but do not return failure. Those items marked FATAL will alway trigger
23# failure.
24my $fail_exit = 1;
25$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1');
26my $exit_val = 0;
27
28# Predicate execution engine.
29sub pred_first {
30 my ($rest) = @_;
31 my $depth = 0;
32 my $off;
33 my $char;
34 my $pred;
35
36 for ($off = 0; $off <= length($rest); $off++) {
37 $char = substr($rest, $off, 1);
38 if ($char eq '(') {
39 $depth++;
40 } elsif ($char eq ')') {
41 $depth--;
42 } elsif ($depth == 0 && $char eq '&') {
43 last;
44 } elsif ($depth == 0 && $char eq '|') {
45 last;
46 }
47 }
48 if ($depth > 0) {
49 die "$P: $rest: missing close parenthesis ')'\n";
50 } elsif ($depth < 0) {
51 die "$P: $rest: missing open parenthesis '('\n";
52 }
53
54 ($pred, $rest) = (substr($rest, 0, $off), substr($rest, $off + 1));
55
56 $pred =~ s/^\s*//;
57 $pred =~ s/\s*$//;
58
59 #print "pred<$pred> rest<$rest> char<$char>\n";
60 ($pred, $rest, $char);
61}
62
63sub pred_do {
64 my ($pred) = @_;
65 my (@a) = split(' ', $pred);
66 my $possible;
67
68 if ($a[0] eq 'arch') {
69 die "$P: $pred: malformed -- $pred <arch>\n" if ($#a < 1);
70 for $possible (@a[1..$#a]) {
71 #print " *** ARCH<$flavour ?? $possible>\n";
72 return 1 if ($arch eq $possible);
73 }
74 return 0;
75 } elsif ($a[0] eq 'flavour') {
76 die "$P: $pred: malformed -- $pred <flavour>\n" if ($#a < 1);
77 for $possible (@a[1..$#a]) {
78 #print " *** FLAVOUR<$flavour ?? $a[1]>\n";
79 return 1 if ($flavour eq $possible);
80 }
81 return 0;
82 } elsif ($a[0] eq 'value') {
83 die "$P: $pred: malformed -- $pred <name> <val>\n" if ($#a != 2);
84 #print " *** CHECK<$a[1] $a[2] ?? " . $values{$a[1]} . ">\n";
85 return ($values{$a[1]} eq $a[2]);
86 } elsif ($a[0] eq 'exists') {
87 die "$P: $pred: malformed -- $pred <name>\n" if ($#a != 1);
88 return (defined $values{$a[1]});
89 } else {
90 die "$P: $pred: unknown predicate\n";
91 }
92 return 1;
93}
94sub pred_exec {
95 my ($rest) = @_;
96 my $pred;
97 my $cut = 0;
98 my $res;
99 my $sep;
100
101 #print "pred_exec<$rest>\n";
102
103 ($pred, $rest, $sep) = pred_first($rest);
104
105 # Leading ! implies inversion.
106 if ($pred =~ /^\s*!\s*(.*)$/) {
107 #print " invert<$1>\n";
108 ($cut, $res) = pred_exec($1);
109 $res = !$res;
110
111 # Leading / implies a CUT operation.
112 } elsif ($pred =~ /^\s*\/\s*(.*)$/) {
113 #print " cut<$1>\n";
114 ($cut, $res) = pred_exec($1);
115 $cut = 1;
116
117 # Recurse left for complex expressions.
118 } elsif ($pred =~ /^\s*\((.*)\)\s*$/) {
119 #print " left<$1>\n";
120 ($cut, $res) = pred_exec($1);
121
122 # Check for common syntax issues.
123 } elsif ($pred eq '') {
124 if ($sep eq '&' || $sep eq '|') {
125 die "$P: $pred$rest: malformed binary operator\n";
126 } else {
127 die "$P: $pred$rest: syntax error\n";
128 }
129
130 # A predicate, execute it.
131 } else {
132 #print " DO<$pred> sep<$sep>\n";
133 $res = pred_do($pred);
134 }
135
136 #print " pre-return res<$res> sep<$sep>\n";
137 if ($sep eq '') {
138 #
139
140 # Recurse right for binary operators -- note these are lazy.
141 } elsif ($sep eq '&' || $sep eq '|') {
142 #print " right<$rest> ? sep<$sep> res<$res>\n";
143 if ($rest =~ /^\s*($|\||\&)/) {
144 die "$P: $pred$rest: malformed binary operator\n";
145 }
146 if ($cut == 0 && (($res && $sep eq '&') || (!$res && $sep eq '|'))) {
147 #print " right<$rest>\n";
148 ($cut, $res) = pred_exec($rest);
149 }
150
151 } else {
152 die "$P: $pred$rest: malformed predicate\n";
153 }
154 #warn " return cut<$cut> res<$res> sep<$sep>\n";
155 return ($cut, $res);
156}
157
158#
159# PREDICATE TESTS
160#
161my $test_total = 1;
162my $test_good = 0;
163sub pred_test {
164 my ($pred, $eres, $eerr) = @_;
165 my ($cut, $res, $err, $fail);
166
167 $test_total++;
168 if ($test != 0 && $test != $test_total - 1) {
169 return;
170 }
171
172 eval {
173 ($cut, $res) = pred_exec($pred);
174 };
175 $err = $@;
176 chomp($err);
177
178 $res = !!$res;
179 $eres = !!$eres;
180
181 $fail = '';
182 if (defined $eres && $res != $eres) {
183 $fail = "result missmatch, expected $eres returned $res";
184 }
185 if (defined $eerr && $err eq '') {
186 $fail = "error missmatch, expected '$eerr' returned success";
187 } elsif (defined $eerr && $err !~ /$eerr/) {
188 $fail = "error missmatch, expected '$eerr' returned '$err'";
189 } elsif (!defined $eerr && $err ne '') {
190 $fail = "error missmatch, expected success returned '$err'";
191 }
192
193 if ($fail eq '') {
194 $test_good++;
195 } else {
196 print "$pred: $test_total: FAIL: $fail\n";
197 }
198 #print "TEST<$pred> eres<$eres> eerr<$eerr> res<$res> err<$err>\n";
199}
200if ($test >= 0) {
201 $arch = 'MYARCH';
202 $flavour = 'MYFLAVOUR';
203 %values = ( 'ENABLED' => 'y', 'DISABLED' => 'n' );
204
205 # Errors.
206 my $eunkn = 'unknown predicate';
207 my $epred = 'malformed';
208 my $eclose = 'missing close parenthesis';
209 my $eopen = 'missing open parenthesis';
210 my $ebinary = 'malformed binary operator';
211
212 # Basic predicate tests.
213 print "TEST: $test_total: basic predicate tests ...\n";
214
215 pred_test('nosuchcommand', undef, $eunkn);
216 pred_test('arch', undef, $epred);
217 pred_test('arch MYARCH', 1, undef);
218 pred_test('arch MYARCH NOTMYARCH', 1, undef);
219 pred_test('arch NOTMYARCH MYARCH', 1, undef);
220 pred_test('arch NOTMYARCH NOTMYARCH MYARCH', 1, undef);
221 pred_test('arch NOTMYARCH MYARCH NOTMYARCH', 1, undef);
222 pred_test('arch NOTMYARCH', 0, undef);
223
224 pred_test('flavour', undef, $epred);
225 pred_test('flavour MYFLAVOUR', 1, undef);
226 pred_test('flavour NOTMYFLAVOUR MYFLAVOUR', 1, undef);
227 pred_test('flavour NOTMYFLAVOUR NOTMYFLAVOUR MYFLAVOUR', 1, undef);
228 pred_test('flavour NOTMYFLAVOUR MYFLAVOUR NOTMYFLAVOUR', 1, undef);
229 pred_test('flavour NOTMYFLAVOUR', 0, undef);
230
231 pred_test('value', undef, $epred);
232 pred_test('value ENABLED', undef, $epred);
233 pred_test('value ENABLED ENABLED ENABLED', undef, $epred);
234 pred_test('value ENABLED y', 1, undef);
235 pred_test('value ENABLED n', 0, undef);
236 pred_test('value DISABLED n', 1, undef);
237 pred_test('value DISABLED y', 0, undef);
238
239 pred_test('exists', undef, $epred);
240 pred_test('exists ENABLED ENABLED', undef, $epred);
241 pred_test('exists ENABLED', 1, undef);
242 pred_test('exists DISABLED', 1, undef);
243 pred_test('exists MISSING', 0, undef);
244
245 print "TEST: $test_total: inversion tests ...\n";
246 pred_test('!exists ENABLED', 0, undef);
247 pred_test('!exists MISSING', 1, undef);
248 pred_test('!!exists ENABLED', 1, undef);
249 pred_test('!!exists MISSING', 0, undef);
250 pred_test('!!!exists ENABLED', 0, undef);
251 pred_test('!!!exists MISSING', 1, undef);
252
253 print "TEST: $test_total: parentheses tests ...\n";
254 pred_test('(exists ENABLED)', 1, undef);
255 pred_test('((exists ENABLED))', 1, undef);
256 pred_test('(((exists ENABLED)))', 1, undef);
257 pred_test('(exists MISSING)', 0, undef);
258 pred_test('((exists MISSING))', 0, undef);
259 pred_test('(((exists MISSING)))', 0, undef);
260
261 pred_test('(!exists ENABLED)', 0, undef);
262 pred_test('((!exists ENABLED))', 0, undef);
263 pred_test('(((!exists ENABLED)))', 0, undef);
264 pred_test('(!exists MISSING)', 1, undef);
265 pred_test('((!exists MISSING))', 1, undef);
266 pred_test('(((!exists MISSING)))', 1, undef);
267
268 pred_test('((!(exists ENABLED)))', 0, undef);
269 pred_test('((!(exists MISSING)))', 1, undef);
270 pred_test('(!((exists ENABLED)))', 0, undef);
271 pred_test('(!((exists MISSING)))', 1, undef);
272 pred_test('!(((exists ENABLED)))', 0, undef);
273 pred_test('!(((exists MISSING)))', 1, undef);
274 pred_test('!((!(exists ENABLED)))', 1, undef);
275 pred_test('!((!(exists MISSING)))', 0, undef);
276 pred_test('!(!(!(exists ENABLED)))', 0, undef);
277 pred_test('!(!(!(exists MISSING)))', 1, undef);
278
279 pred_test('(', undef, $eclose);
280 pred_test('()(', undef, $eclose);
281 pred_test('(())(', undef, $eclose);
282 pred_test('((()))(', undef, $eclose);
283 pred_test('(()', undef, $eclose);
284 pred_test('((())', undef, $eclose);
285 pred_test('(((()))', undef, $eclose);
286 pred_test('(()()', undef, $eclose);
287 pred_test('((())()', undef, $eclose);
288
289 pred_test(')', undef, $eopen);
290 pred_test('())', undef, $eopen);
291 pred_test('(()))', undef, $eopen);
292 pred_test('((())))', undef, $eopen);
293
294 print "TEST: $test_total: binary and tests ...\n";
295
296 pred_test('exists ENABLED &', undef, $ebinary);
297 pred_test('& exists ENABLED', undef, $ebinary);
298 pred_test('exists ENABLED & & exists ENABLED', undef, $ebinary);
299
300 pred_test('exists MISSING & exists MISSING', 0, undef);
301 pred_test('exists MISSING & exists ENABLED', 0, undef);
302 pred_test('exists ENABLED & exists MISSING', 0, undef);
303 pred_test('exists ENABLED & exists ENABLED', 1, undef);
304
305 pred_test('exists MISSING & exists MISSING & exists MISSING', 0, undef);
306 pred_test('exists MISSING & exists MISSING & exists ENABLED', 0, undef);
307 pred_test('exists MISSING & exists ENABLED & exists MISSING', 0, undef);
308 pred_test('exists MISSING & exists ENABLED & exists ENABLED', 0, undef);
309 pred_test('exists ENABLED & exists MISSING & exists MISSING', 0, undef);
310 pred_test('exists ENABLED & exists MISSING & exists ENABLED', 0, undef);
311 pred_test('exists ENABLED & exists ENABLED & exists MISSING', 0, undef);
312 pred_test('exists ENABLED & exists ENABLED & exists ENABLED', 1, undef);
313
314 print "TEST: $test_total: binary or tests ...\n";
315
316 pred_test('exists ENABLED |', undef, $ebinary);
317 pred_test('| exists ENABLED', undef, $ebinary);
318 pred_test('exists ENABLED | | exists ENABLED', undef, $ebinary);
319
320 pred_test('exists MISSING | exists MISSING', 0, undef);
321 pred_test('exists MISSING | exists ENABLED', 1, undef);
322 pred_test('exists ENABLED | exists MISSING', 1, undef);
323 pred_test('exists ENABLED | exists ENABLED', 1, undef);
324
325 pred_test('exists MISSING | exists MISSING | exists MISSING', 0, undef);
326 pred_test('exists MISSING | exists MISSING | exists ENABLED', 1, undef);
327 pred_test('exists MISSING | exists ENABLED | exists MISSING', 1, undef);
328 pred_test('exists MISSING | exists ENABLED | exists ENABLED', 1, undef);
329 pred_test('exists ENABLED | exists MISSING | exists MISSING', 1, undef);
330 pred_test('exists ENABLED | exists MISSING | exists ENABLED', 1, undef);
331 pred_test('exists ENABLED | exists ENABLED | exists MISSING', 1, undef);
332 pred_test('exists ENABLED | exists ENABLED | exists ENABLED', 1, undef);
333
334 print "TEST: $test_total: binary or/and combination tests ...\n";
335
336 pred_test('exists MISSING | exists MISSING & exists MISSING', 0, undef);
337 pred_test('exists MISSING | exists MISSING & exists ENABLED', 0, undef);
338 pred_test('exists MISSING | exists ENABLED & exists MISSING', 0, undef);
339 pred_test('exists MISSING | exists ENABLED & exists ENABLED', 1, undef);
340 pred_test('exists ENABLED | exists MISSING & exists MISSING', 1, undef);
341 pred_test('exists ENABLED | exists MISSING & exists ENABLED', 1, undef);
342 pred_test('exists ENABLED | exists ENABLED & exists MISSING', 1, undef);
343 pred_test('exists ENABLED | exists ENABLED & exists ENABLED', 1, undef);
344
345 print "TEST: $test_total: binary and/or combination tests ...\n";
346
347 pred_test('exists MISSING & exists MISSING | exists MISSING', 0, undef);
348 pred_test('exists MISSING & exists MISSING | exists ENABLED', 0, undef);
349 pred_test('exists MISSING & exists ENABLED | exists MISSING', 0, undef);
350 pred_test('exists MISSING & exists ENABLED | exists ENABLED', 0, undef);
351 pred_test('exists ENABLED & exists MISSING | exists MISSING', 0, undef);
352 pred_test('exists ENABLED & exists MISSING | exists ENABLED', 1, undef);
353 pred_test('exists ENABLED & exists ENABLED | exists MISSING', 1, undef);
354 pred_test('exists ENABLED & exists ENABLED | exists ENABLED', 1, undef);
355
356 print "TEST: $test_total: cut tests ...\n";
357 pred_test('(arch MYARCH & exists MISSING) | exists ENABLED', 1, undef);
358 pred_test('(arch MYARCH &/ exists MISSING) | exists ENABLED', 0, undef);
359
360 $test_total--;
361 print "TEST: $test_good/$test_total succeeded\n";
362
363 exit $exit_val;
364}
365
366# Load up the current configuration values -- FATAL if this fails
367print "$P: $config: loading config\n";
368open(CONFIG, "<$config") || die "$P: $config: open failed -- $! -- aborting\n";
369while (<CONFIG>) {
370 # Pull out values.
371 /^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next;
372 if ($2 eq 'is not set') {
373 $values{$1} = 'n';
374 } else {
375 $values{$1} = $2;
376 }
377}
378close(CONFIG);
379
380# FATAL: Check if we have an enforcement list.
381my $pass = 0;
382my $total = 0;
383my $line = '';
384print "$P: $checks: loading checks\n";
385open(CHECKS, "<$checks") || die "$P: $checks: open failed -- $! -- aborting\n";
386while (<CHECKS>) {
387 /^#/ && next;
388 chomp;
389
390 $line .= $_;
391 if ($line =~ /\\$/) {
392 chop($line);
393 $line .= " ";
394 next;
395 }
396 $line =~ /^\s*$/ && next;
397
398 #print "CHECK: <$line>\n";
399 $total++;
400 my (undef, $result) = pred_exec($line);
401 if (!$result) {
402 print "$P: FAIL: $line\n";
403 $exit_val = $fail_exit;
404 } else {
405 $pass++;
406 }
407
408 $line = '';
409}
410close(CHECKS);
411
412print "$P: $pass/$total checks passed -- exit $exit_val\n";
413exit $exit_val;