joachim99@14
|
1 #!/usr/bin/perl -w
|
joachim99@14
|
2
|
joachim99@14
|
3 use DB_File;
|
joachim99@14
|
4 use Fcntl ':flock';
|
joachim99@14
|
5
|
joachim99@14
|
6 if (!defined($ARGV[0])) {
|
joachim99@14
|
7 print "usage: requires .class dump as parameter!\n";
|
joachim99@14
|
8 exit;
|
joachim99@14
|
9 }
|
joachim99@14
|
10
|
joachim99@14
|
11 sub bailout
|
joachim99@14
|
12 {
|
joachim99@14
|
13 untie %bcheckdb if(defined(%bcheckdb));
|
joachim99@14
|
14
|
joachim99@14
|
15 if(defined(MYLOCK)) {
|
joachim99@14
|
16 flock MYLOCK, LOCK_UN;
|
joachim99@14
|
17 close(MYLOCK);
|
joachim99@14
|
18 }
|
joachim99@14
|
19
|
joachim99@14
|
20 print @_;
|
joachim99@14
|
21 exit 5;
|
joachim99@14
|
22 }
|
joachim99@14
|
23
|
joachim99@14
|
24 sub ask_user
|
joachim99@14
|
25 {
|
joachim99@14
|
26 my ($dbkey, $dbchunk) = @_;
|
joachim99@14
|
27
|
joachim99@14
|
28 if (defined($ENV{"BCHECK_UPDATE"})) {
|
joachim99@14
|
29 $bcheckdb{$dbkey} = $dbchunk;
|
joachim99@14
|
30 return;
|
joachim99@14
|
31 }
|
joachim99@14
|
32
|
joachim99@14
|
33 &bailout("BC problem detected") if (! -t STDIN);
|
joachim99@14
|
34
|
joachim99@14
|
35 print "(I)gnore / (Q)uit / (U)pdate: ";
|
joachim99@14
|
36
|
joachim99@14
|
37 my $key;
|
joachim99@14
|
38 while(defined(read STDIN, $key, 1)) {
|
joachim99@14
|
39 $key = lc($key);
|
joachim99@14
|
40
|
joachim99@14
|
41 print "got: >$key<\n";
|
joachim99@14
|
42
|
joachim99@14
|
43 return if ($key eq 'i');
|
joachim99@14
|
44
|
joachim99@14
|
45 &bailout("BC problem. aborted") if ($key eq 'q');
|
joachim99@14
|
46
|
joachim99@14
|
47 if ($key eq 'u') {
|
joachim99@14
|
48 $bcheckdb{$dbkey} = $dbchunk;
|
joachim99@14
|
49 return;
|
joachim99@14
|
50 }
|
joachim99@14
|
51 print "\n(I)gnore / (Q)uit / (U)pdate: ";
|
joachim99@14
|
52 }
|
joachim99@14
|
53 }
|
joachim99@14
|
54
|
joachim99@14
|
55 sub diff_chunk($$)
|
joachim99@14
|
56 {
|
joachim99@14
|
57 my ($oldl, $newl) = @_;
|
joachim99@14
|
58 my @old = split /^/m, $oldl;
|
joachim99@14
|
59 my @new = split /^/m, $newl;
|
joachim99@14
|
60 my $haschanges = 0;
|
joachim99@14
|
61 my $max = $#old > $#new ? $#old : $#new;
|
joachim99@14
|
62
|
joachim99@14
|
63 die "whoops. key different" if ($old[0] ne $new[0]);
|
joachim99@14
|
64
|
joachim99@14
|
65 if ($#old != $#new) {
|
joachim99@14
|
66 warn ("Structural difference.\n");
|
joachim99@14
|
67 print @old;
|
joachim99@14
|
68 print "-----------------------------------------------\n";
|
joachim99@14
|
69 print @new;
|
joachim99@14
|
70 $haschanges = 1;
|
joachim99@14
|
71 return;
|
joachim99@14
|
72 }
|
joachim99@14
|
73
|
joachim99@14
|
74 print $old[0];
|
joachim99@14
|
75
|
joachim99@14
|
76 my ($class) = ($old[0] =~ /^(?:Class |Vtable for )(\S+)/);
|
joachim99@14
|
77
|
joachim99@14
|
78 my $c = 1;
|
joachim99@14
|
79 while ($c < $max) {
|
joachim99@14
|
80 my ($o, $n) = ($old[$c], $new[$c]);
|
joachim99@14
|
81 chomp $o;
|
joachim99@14
|
82 chomp $n;
|
joachim99@14
|
83 $c++;
|
joachim99@14
|
84 next if ($o eq $n);
|
joachim99@14
|
85
|
joachim99@14
|
86 if(defined($class) and $n =~ /^(\d+\s+)\w+(::\S+\s*.*)$/) {
|
joachim99@14
|
87 print "comparing >$n< against >$1$class$2<\n";
|
joachim99@14
|
88 next if ($n eq "$1$class$2");
|
joachim99@14
|
89 }
|
joachim99@14
|
90
|
joachim99@14
|
91 $haschanges = 1;
|
joachim99@14
|
92
|
joachim99@14
|
93 print "-$o\n+$n\n\n";
|
joachim99@14
|
94 }
|
joachim99@14
|
95
|
joachim99@14
|
96 return $haschanges;
|
joachim99@14
|
97 }
|
joachim99@14
|
98
|
joachim99@14
|
99 local $dblock = $ENV{"HOME"} . "/bcheck.lock";
|
joachim99@14
|
100 my $dbfile = $ENV{"HOME"} . "/bcheck.db";
|
joachim99@14
|
101 my $cdump = $ARGV[0];
|
joachim99@14
|
102
|
joachim99@14
|
103 die "file $cdump is not readable: $!" if (! -f $cdump);
|
joachim99@14
|
104
|
joachim99@14
|
105 # make sure the advisory lock exists
|
joachim99@14
|
106 open(MYLOCK, ">$dblock");
|
joachim99@14
|
107 print MYLOCK "";
|
joachim99@14
|
108
|
joachim99@14
|
109 flock MYLOCK, LOCK_EX;
|
joachim99@14
|
110
|
joachim99@14
|
111 tie %bcheckdb, 'DB_File', $dbfile;
|
joachim99@14
|
112
|
joachim99@14
|
113 my $chunk = "";
|
joachim99@14
|
114
|
joachim99@14
|
115 open (IN, "<$cdump") or die "cannot open $cdump: $!";
|
joachim99@14
|
116 while (<IN>) {
|
joachim99@14
|
117
|
joachim99@14
|
118 chop;
|
joachim99@14
|
119
|
joachim99@14
|
120 s/0x[0-9a-fA-F]+/0x......../g;
|
joachim99@14
|
121
|
joachim99@14
|
122 $chunk .= $_ . "\n";
|
joachim99@14
|
123
|
joachim99@14
|
124 if(/^\s*$/) {
|
joachim99@14
|
125 my @lines = split /^/m, $chunk;
|
joachim99@14
|
126 my $key = $lines[0];
|
joachim99@14
|
127 chomp $key;
|
joachim99@14
|
128
|
joachim99@14
|
129 if($key !~ /<anonymous struct>/ &&
|
joachim99@14
|
130 $key !~ /<anonymous union>/) {
|
joachim99@14
|
131 if(defined($bcheckdb{$key})) {
|
joachim99@14
|
132 my $dbversion = $bcheckdb{$key};
|
joachim99@14
|
133
|
joachim99@14
|
134 if($dbversion ne $chunk) {
|
joachim99@14
|
135 &ask_user($key, $chunk) if(&diff_chunk($dbversion, $chunk));
|
joachim99@14
|
136 }
|
joachim99@14
|
137 }
|
joachim99@14
|
138 else {
|
joachim99@14
|
139 $bcheckdb{$key} = $chunk;
|
joachim99@14
|
140 print "NEW: $key\n";
|
joachim99@14
|
141 }
|
joachim99@14
|
142 }
|
joachim99@14
|
143
|
joachim99@14
|
144 $chunk = "";
|
joachim99@14
|
145 next;
|
joachim99@14
|
146 }
|
joachim99@14
|
147
|
joachim99@14
|
148 }
|
joachim99@14
|
149 close(IN);
|
joachim99@14
|
150
|
joachim99@14
|
151 untie %bcheckdb;
|
joachim99@14
|
152 flock MYLOCK, LOCK_UN;
|
joachim99@14
|
153 close(MYLOCK);
|
joachim99@14
|
154
|
joachim99@14
|
155 exit 0;
|