chiark / gitweb /
do not placate -Wpointer-sign
[chiark-utils.git] / backup / checkallused
1 #!/usr/bin/perl
2 # checkallused
3 # check that the configuration is sane and backs up everything it should
4 #
5 # This file is part of chiark backup, a system for backing up GNU/Linux and
6 # other UN*X-compatible machines, as used on chiark.greenend.org.uk.
7 #
8 # chiark backup is:
9 #  Copyright (C) 1997-1998,2000-2001,2007
10 #                     Ian Jackson <ian@chiark.greenend.org.uk>
11 #  Copyright (C) 1999 Peter Maydell <pmaydell@chiark.greenend.org.uk>
12 #
13 # This is free software; you can redistribute it and/or modify it under the
14 # terms of the GNU General Public License as published by the Free Software
15 # Foundation; either version 3, or (at your option) any later version.
16 #
17 # This is distributed in the hope that it will be useful, but WITHOUT ANY
18 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
20 # details.
21 #
22 # You should have received a copy of the GNU General Public License along
23 # with this program; if not, consult the Free Software Foundation's
24 # website at www.fsf.org, or the GNU Project website at www.gnu.org.
25
26 # All filesystems must either be backed up in both full and
27 # incremental dumps or listed as exceptions.
28
29 BEGIN {
30     $etc= '/etc/chiark-backup';
31     require "$etc/settings.pl";
32     require 'backuplib.pl';
33 }
34
35 $|=1;
36
37 open X,'last-tape' or die $!;
38 chomp($tape= <X>);
39 close X or die $!;
40
41 while (!defined $tapedone{$tape}) {
42     open X,"$etc/tape.$tape" or die "$tape $!";
43     $fsg=''; $next='';
44     for (;;) {
45         $_= <X> or die $1; chomp; s/\s*$//;
46         last if m/^end$/;
47         next unless m/\S/;
48         next if m/^\#/;
49         if (m/^filesystems (\w+)$/) { $fsg= $1; }
50         elsif (m/^next (\w+)$/) { $next=$1; }
51         else { die "$tape $_ ?"; }
52     }
53     length $fsg or die "$tape $!";
54     length $next or die "$tape $!";
55     push @{$fsgdone{$fsg}}, $tape;
56     $tapedone{$tape}=1;
57     $tape= $next;
58 }
59
60 sub checkdevspec ($$$) {
61     my ($atf,$devspec,$why) = @_;
62     push @{ $devspec{$atf}{$devspec} }, $why;
63 }
64
65 for $fsg (sort keys %fsgdone) {
66     print "filesystem group $fsg: ".join(' ',@{$fsgdone{$fsg}}).":\n ";
67     @fsys= ();
68     readfsys($fsg);
69     for $tf (@fsys) {
70         parsefsys();
71         $pstr= "$pcstr$atf";
72         &e("dumped twice ($backed{$pstr}, $fsg): $pstr")
73             if defined $backed{$pstr};
74         $backed{$pstr}= $fsg;
75         checkdevspec($pstr,"$pcstr$dev","filesystem group $fsg")
76             if length $dev;
77         print " $pstr";
78     }
79     print "\n";
80 }
81
82 print "incremental group:\n ";
83 @fsys= ();
84 readfsys('all');
85 for $tf (@fsys) {
86     parsefsys();
87     $pstr= "$pcstr$atf";
88     $incrd{$pstr}= $fsg;
89     checkdevspec($pstr,"$pcstr$dev","incremental group") if length $dev;
90     print " $pstr";
91 }
92 print "\n";
93
94 for $pfx ('', sort keys %prefix) {
95     $rstr= length($pfx) ? $prefix{$pfx}.' ' : '';
96     $dfstr= exists($prefixdf{$pfx}) ? $prefixdf{$pfx} :
97         'df -P --no-sync -xiso9660 -xnfs -xproc -xtmpfs';
98     $cmd= "$rstr $dfstr";
99     open X, "$cmd |" or die $!;
100     $_= <X>; m/^Filesystem/ or die "$cmd => $_ ?";
101     $prefix= length($pfx) ? $pfx : '<local>';
102     $pcstr= length($pfx) ? "$pfx:" : '';
103     print "mount points: $prefix:";
104     while (<X>) {
105         chomp;
106         next if m,^procfs\s,;
107         m,^/dev/(\S+)\s.*\s(/\S*)\s*$, or die "$_ ?";
108         ($dev,$mp) = ($1,$2);
109         checkdevspec("$pcstr$mp","$pcstr/dev/$dev","df");
110         $mounted{"$pcstr$mp"}="$pcstr$dev"; print " $1-$2";
111         if (defined($backto= $backed{"$pcstr$mp"})) {
112             if (m,^/dev/\S+\s+\d+\s+(\d+)\s,) {
113                 $usedkb{$backto} += $1;
114                 $countedkb{"$pcstr$mp"}++;
115             }
116         }
117     }
118     print "\n";
119     $!=0; close(X); $? and die "$? $!";
120 }
121
122 foreach $fsg (keys %usedkb) {
123     print "filesystem group $fsg: $usedkb{$fsg} 1K-blocks raw accounted\n";
124 }
125
126 foreach $fsg (keys %backed) {
127     next if $countedkb{$fsg};
128     print "unaccounted filesystem: $fsg\n";
129 }
130
131 foreach $dsk (keys %devspec) {
132     if (keys %{ $devspec{$dsk} } != 1) {
133         foreach $devspec (keys %{ $devspec{$dsk} }) {
134             &e("inconsistent devices for $dsk: $devspec (".
135                join(', ', @{ $devspec{$dsk}{$devspec} }).")");
136         }
137     }
138 }
139
140 # We check that all mounted filesystems are dumped and all
141 # filesystems to be dumped are mounted. The expected-diffs
142 # config file allows us to make exceptions.
143 # eg: 
144 # #expect disk2 to be mounted but not dumped
145 # !/disk2
146 # # CD may or may not be mounted but should not be dumped in either case
147 # ?/cdrom
148
149 open Z,"$etc/expected-diffs" or die $!;
150 for (;;) {
151     $_= <Z> or die; chomp; s/\s*$//;
152     last if m/^end$/;
153     next unless m/^\S/;
154     next if m/^\#/;
155     if (s/^\?//) {
156         print "non-permanent filesystem expected not to be dumped: $_\n";
157         if (defined($mounted{$_})) {
158             delete $mounted{$_};
159         }
160     } elsif (s/^\!//) {
161         &e("expected not to be dumped, but not a mount point: $_")
162             unless defined($mounted{$_});
163         print "filesystem expected not to be dumped: $_\n";
164         delete $mounted{$_};
165     } else {
166         &e("non-filesystem expected to be dumped is mounted: $_ on $mounted{$_}")
167             if defined($mounted{$_});
168         $mounted{$_}= 'expected-diffs';
169         print "non-filesystem expected to be dumped: $_\n";
170     }
171 }
172     
173 for $fs (sort keys %backed) { length($mounted{$fs}) || &e("dumped ($backed{$fs}), not a mount point: $fs"); }
174 for $fs (sort keys %incrd) { length($mounted{$fs}) || &e("increm'd ($incrd{$fs}), not a mount point: $fs"); }
175 for $fs (sort keys %mounted) { length($backed{$fs}) || &e("mount point ($mounted{$fs}), not dumped: $fs"); }
176 for $fs (sort keys %mounted) { length($incrd{$fs}) || &e("mount point ($mounted{$fs}), not increm'd: $fs"); }
177
178 $emsg.= "configuration ok\n" unless $e;
179 print STDERR $emsg;
180 exit($e);
181
182 sub e { $emsg.="** @_\n"; $e=1; }