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