chiark / gitweb /
Merge branch 'acctdump'
[chiark-utils.git] / backup / checkallused
index fd613f3181b75d91c5fc603c70f510ad40ee2337..c0079d08bb726d4b4faa33fb4cab736ca2af23ea 100755 (executable)
@@ -1,7 +1,33 @@
 #!/usr/bin/perl
+# checkallused
+# check that the configuration is sane and backs up everything it should
+#
+# This file is part of chiark backup, a system for backing up GNU/Linux and
+# other UN*X-compatible machines, as used on chiark.greenend.org.uk.
+#
+# chiark backup is:
+#  Copyright (C) 1997-1998,2000-2001,2007
+#                     Ian Jackson <ian@chiark.greenend.org.uk>
+#  Copyright (C) 1999 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+#
+# This is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, consult the Free Software Foundation's
+# website at www.fsf.org, or the GNU Project website at www.gnu.org.
+
+# All filesystems must either be backed up in both full and
+# incremental dumps or listed as exceptions.
 
 BEGIN {
-    $etc= '/etc/backup';
+    $etc= '/etc/chiark-backup';
     require "$etc/settings.pl";
     require 'backuplib.pl';
 }
@@ -31,16 +57,23 @@ while (!defined $tapedone{$tape}) {
     $tape= $next;
 }
 
+sub checkdevspec ($$$) {
+    my ($atf,$devspec,$why) = @_;
+    push @{ $devspec{$atf}{$devspec} }, $why;
+}
+
 for $fsg (sort keys %fsgdone) {
     print "filesystem group $fsg: ".join(' ',@{$fsgdone{$fsg}}).":\n ";
     @fsys= ();
     readfsys($fsg);
     for $tf (@fsys) {
        parsefsys();
-       $pstr= $prefix ne '<local>' ? "$prefix:$atf" : $atf;
+       $pstr= "$pcstr$atf";
        &e("dumped twice ($backed{$pstr}, $fsg): $pstr")
            if defined $backed{$pstr};
        $backed{$pstr}= $fsg;
+       checkdevspec($pstr,"$pcstr$dev","filesystem group $fsg")
+           if length $dev;
        print " $pstr";
     }
     print "\n";
@@ -51,8 +84,9 @@ print "incremental group:\n ";
 readfsys('all');
 for $tf (@fsys) {
     parsefsys();
-    $pstr= $prefix ne '<local>' ? "$prefix:$atf" : $atf;
+    $pstr= "$pcstr$atf";
     $incrd{$pstr}= $fsg;
+    checkdevspec($pstr,"$pcstr$dev","incremental group") if length $dev;
     print " $pstr";
 }
 print "\n";
@@ -60,43 +94,70 @@ print "\n";
 for $pfx ('', sort keys %prefix) {
     $rstr= length($pfx) ? $prefix{$pfx}.' ' : '';
     $dfstr= exists($prefixdf{$pfx}) ? $prefixdf{$pfx} :
-       'df --no-sync -xiso9660 -xnfs -xproc';
+       'df -P --no-sync -xiso9660 -xnfs -xproc -xtmpfs';
     $cmd= "$rstr $dfstr";
     open X, "$cmd |" or die $!;
     $_= <X>; m/^Filesystem/ or die "$cmd => $_ ?";
-    $ppstr= length($pfx) ? $pfx : '<local>';
-    $pstr= length($pfx) ? "$pfx:" : '';
-    print "mount points: $ppstr:";
+    $prefix= length($pfx) ? $pfx : '<local>';
+    $pcstr= length($pfx) ? "$pfx:" : '';
+    print "mount points: $prefix:";
     while (<X>) {
        chomp;
        next if m,^procfs\s,;
        m,^/dev/(\S+)\s.*\s(/\S*)\s*$, or die "$_ ?";
        ($dev,$mp) = ($1,$2);
-       $mounted{"$pstr$mp"}="$pstr$dev"; print " $1-$2";
-       if (defined($backto= $backed{"$pstr$mp"})) {
+       checkdevspec("$pcstr$mp","$pcstr/dev/$dev","df");
+       $mounted{"$pcstr$mp"}="$pcstr$dev"; print " $1-$2";
+       if (defined($backto= $backed{"$pcstr$mp"})) {
            if (m,^/dev/\S+\s+\d+\s+(\d+)\s,) {
                $usedkb{$backto} += $1;
-           } else {
-               $usedkb{$backto} += 0;
-               $unkkb{$backto} .= " + $pstr$mp";
+               $countedkb{"$pcstr$mp"}++;
            }
        }
     }
     print "\n";
-    $!=0; close(X); $? and die "$cmd $? $!";
+    $!=0; close(X); $? and die "$? $!";
 }
 
 foreach $fsg (keys %usedkb) {
-    print "filesystem group $fsg: $usedkb{$fsg} 1K-blocks$unkkb{$fsg}\n";
+    print "filesystem group $fsg: $usedkb{$fsg} 1K-blocks raw accounted\n";
+}
+
+foreach $fsg (keys %backed) {
+    next if $countedkb{$fsg};
+    print "unaccounted filesystem: $fsg\n";
 }
 
+foreach $dsk (keys %devspec) {
+    if (keys %{ $devspec{$dsk} } != 1) {
+       foreach $devspec (keys %{ $devspec{$dsk} }) {
+           &e("inconsistent devices for $dsk: $devspec (".
+               join(', ', @{ $devspec{$dsk}{$devspec} }).")");
+       }
+    }
+}
+
+# We check that all mounted filesystems are dumped and all
+# filesystems to be dumped are mounted. The expected-diffs
+# config file allows us to make exceptions.
+# eg: 
+# #expect disk2 to be mounted but not dumped
+# !/disk2
+# # CD may or may not be mounted but should not be dumped in either case
+# ?/cdrom
+
 open Z,"$etc/expected-diffs" or die $!;
 for (;;) {
     $_= <Z> or die; chomp; s/\s*$//;
     last if m/^end$/;
     next unless m/^\S/;
     next if m/^\#/;
-    if (s/^\!//) {
+    if (s/^\?//) {
+        print "non-permanent filesystem expected not to be dumped: $_\n";
+        if (defined($mounted{$_})) {
+            delete $mounted{$_};
+        }
+    } elsif (s/^\!//) {
        &e("expected not to be dumped, but not a mount point: $_")
            unless defined($mounted{$_});
         print "filesystem expected not to be dumped: $_\n";