Imported Upstream version 2.5.1p3
[debian/amanda] / server-src / amoverview.pl.in
index dc303d17474331149e94d8e790307c21329047c7..07fdb975d3a4b0a251711596e02f18aad1f2e57b 100644 (file)
@@ -9,12 +9,16 @@ require 5.001;
 
 use FileHandle;
 use Getopt::Long;
+use Text::ParseWords;
 use Carp;
 use POSIX;
 
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'};
+$ENV{'PATH'} = "/usr/bin:/usr/sbin:/sbin:/bin";
+
 sub Usage {
     print STDERR <<END;
-Usage: $0 [[-config] CONFIG] [-hostwidth width] [-diskwidth width] [-skipmissed] [-verbose]
+Usage: $0 [[-config] CONFIG] [-hostwidth width] [-diskwidth width] [-skipmissed] [-last] [-num0] [-togo0] [-verbose]
 
 This script generates to standard output an overview of the filesystems
 dumped over time and the type of dump done on a particular day, such as
@@ -56,12 +60,18 @@ my $opt_config              = "$config";
 my $opt_hostwidth      = 8;
 my $opt_diskwidth      = 20;
 my $opt_skipmissed     = 0;
+my $opt_last           = 0;
+my $opt_num0           = 0;
+my $opt_togo0          = 0;
 my $opt_verbose                = 0;
 
 GetOptions('config=s'          => \$opt_config,
           'hostwidth=i'        => \$opt_hostwidth,
           'diskwidth=i'        => \$opt_diskwidth,
           'skipmissed'         => \$opt_skipmissed,
+          'last'               => \$opt_last,
+          'num0'               => \$opt_num0,
+          'togo0'              => \$opt_togo0,
           'verbose'            => \$opt_verbose)
 or Usage();
 
@@ -72,6 +82,15 @@ elsif($#ARGV > 0) {
   Usage();
 }
 
+#untaint user input $ARGV[0]
+
+if ($opt_config =~ /^([\w.-]+)$/) {          # $1 is untainted
+   $opt_config = $1;
+} else {
+    die "filename '$opt_config' has invalid characters.\n";
+}
+
+
 -d "$confdir/$opt_config" or
        die "$0: directory `$confdir/$opt_config' does not exist.\n";
 
@@ -109,16 +128,31 @@ while (<$fh>) {
     next if /found Amanda directory/;
     next if /skipping cruft directory/;
     next if /skip-incr/;
-    ($date, $host, $disk, $level, $tape, $file, $status) = split ' ', $_;
+
+    ($date, $time, $host, $disk, $level, $tape, $file, $part, $status) = shellwords($_);
+
     next if $date eq 'date';
     next if $date eq 'Warning:';
     next if $date eq 'Scanning';
     next if $date eq "";
+
+    if($time !~/^\d\d:\d\d:\d\d$/) {
+       $status = $part;
+       $part = $file;
+       $file = $tape;
+       $tape = $level;
+       $level = $disk;
+       $disk = $host;
+       $host = $time;
+    }
+
     if ($date =~ /^\d\d\d\d-\d\d-\d\d$/) {
-       defined($level{$host}{$disk}{$date}) or
-           $level{$host}{$disk}{$date} = '';
-       $level{$host}{$disk}{$date} .= ($status eq 'OK') ? $level : 'E';
-       $dates{$date}++;
+       if(defined $disks{$host}{$disk}) {
+           defined($level{$host}{$disk}{$date}) or
+               $level{$host}{$disk}{$date} = '';
+           $level{$host}{$disk}{$date} .= ($status eq 'OK') ? $level : 'E';
+           $dates{$date}++;
+       }
     }
     else {
        print "bad date $date in $_\n";
@@ -128,19 +162,51 @@ $fh->close or
     die "$0: error in closing `$amadmin $opt_config find|' pipe: $!\n";
 
 # Process the status to arrive at a "last" status
-for $host (sort keys %disks) {
-    for $disk (sort keys %{$disks{$host}}) {
-       $level{$host}{$disk}{"0000-LA-ST"} = '';
-       for $date (sort keys %dates) {
-           if ($level{$host}{$disk}{$date} eq "E"
-                && $level{$host}{$disk}{"0000-LA-ST"} =~ /^\d/ ) {
-               $level{$host}{$disk}{"0000-LA-ST"} .= $level{$host}{$disk}{$date};
-           } elsif ($level{$host}{$disk}{$date} eq "") {
-               $level{$host}{$disk}{"0000-LA-ST"} =~ s/E//;
-           } else {
-               $level{$host}{$disk}{"0000-LA-ST"} = $level{$host}{$disk}{$date};
+if ($opt_last) {
+    for $host (sort keys %disks) {
+        for $disk (sort keys %{$disks{$host}}) {
+           $level{$host}{$disk}{"0000-LA-ST"} = '';
+           for $date (sort keys %dates) {
+               if ($level{$host}{$disk}{$date} eq "E"
+                    && $level{$host}{$disk}{"0000-LA-ST"} =~ /^\d/ ) {
+                   $level{$host}{$disk}{"0000-LA-ST"} .= $level{$host}{$disk}{$date};
+               } elsif ($level{$host}{$disk}{$date} eq "") {
+                   $level{$host}{$disk}{"0000-LA-ST"} =~ s/E//;
+               } else {
+                   $level{$host}{$disk}{"0000-LA-ST"} = $level{$host}{$disk}{$date};
+               }
            }
-       }
+        }
+    }
+}
+
+# Number of level 0 backups
+if ($opt_num0) {
+    for $host (sort keys %disks) {
+        for $disk (sort keys %{$disks{$host}}) {
+            $level{$host}{$disk}{'0000-NM-L0'} = 0;
+            for $date (sort keys %dates) {
+                if ($level{$host}{$disk}{$date} =~ /0/) {
+                    $level{$host}{$disk}{'0000-NM-L0'} += 1;
+                }
+            }
+        }
+    }
+}
+
+# Runs to the last level 0
+if ($opt_togo0) {
+    for $host (sort keys %disks) {
+        for $disk (sort keys %{$disks{$host}}) {
+            $level{$host}{$disk}{'0000-TO-GO'} = 0;
+            my $togo=0;
+            for $date (sort keys %dates) {
+                if ($level{$host}{$disk}{$date} =~ /0/) {
+                    $level{$host}{$disk}{'0000-TO-GO'} = $togo;
+                }
+                $togo++;
+            }
+        }
     }
 }
 
@@ -161,7 +227,13 @@ unless ($opt_skipmissed)
 }
 
 #Add the "last" entry    
-$dates{"0000-LA-ST"}=1;
+$dates{"0000-LA-ST"}=1 if ($opt_last);
+
+#Add the "Number of Level 0s" entry
+$dates{"0000-NM-L0"}=1 if ($opt_num0);
+
+#Add the "Runs to go" entry
+$dates{"0000-TO-GO"}=1 if ($opt_togo0);
 
 # make formats