Imported Upstream version 3.3.0
[debian/amanda] / server-src / amcheckdump.pl
index b0074562c06c1352f1315cdbd1adfa7db498144c..d8042bc9294d0f62df571419fb4fea096c6f0c6c 100644 (file)
@@ -44,7 +44,7 @@ use Amanda::Xfer qw( :constants );
 
 sub usage {
     print <<EOF;
 
 sub usage {
     print <<EOF;
-USAGE: amcheckdump config [ --timestamp|-t timestamp ] [-o configoption]*
+USAGE: amcheckdump [ --timestamp|-t timestamp ] [-o configoption]* <conf>
     amcheckdump validates Amanda dump images by reading them from storage
 volume(s), and verifying archive integrity if the proper tool is locally
 available. amcheckdump does not actually compare the data located in the image
     amcheckdump validates Amanda dump images by reading them from storage
 volume(s), and verifying archive integrity if the proper tool is locally
 available. amcheckdump does not actually compare the data located in the image
@@ -95,12 +95,12 @@ if ($cfgerr_level >= $CFGERR_WARNINGS) {
 
 Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);
 
 
 Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);
 
-# Interactive package
-package Amanda::Interactive::amcheckdump;
+# Interactivity package
+package Amanda::Interactivity::amcheckdump;
 use POSIX qw( :errno_h );
 use Amanda::MainLoop qw( :GIOCondition );
 use vars qw( @ISA );
 use POSIX qw( :errno_h );
 use Amanda::MainLoop qw( :GIOCondition );
 use vars qw( @ISA );
-@ISA = qw( Amanda::Interactive );
+@ISA = qw( Amanda::Interactivity );
 
 sub new {
     my $class = shift;
 
 sub new {
     my $class = shift;
@@ -135,12 +135,12 @@ sub user_request {
        if (!defined $n_read) {
            return if ($! == EINTR);
            $self->abort();
        if (!defined $n_read) {
            return if ($! == EINTR);
            $self->abort();
-           return $params{'finished_cb'}->(
+           return $params{'request_cb'}->(
                Amanda::Changer::Error->new('fatal',
                        message => "Fail to read from stdin"));
        } elsif ($n_read == 0) {
            $self->abort();
                Amanda::Changer::Error->new('fatal',
                        message => "Fail to read from stdin"));
        } elsif ($n_read == 0) {
            $self->abort();
-           return $params{'finished_cb'}->(
+           return $params{'request_cb'}->(
                Amanda::Changer::Error->new('fatal',
                        message => "Aborted by user"));
        } else {
                Amanda::Changer::Error->new('fatal',
                        message => "Aborted by user"));
        } else {
@@ -150,7 +150,7 @@ sub user_request {
                chomp $line;
                $buffer = "";
                $self->abort();
                chomp $line;
                $buffer = "";
                $self->abort();
-               return $params{'finished_cb'}->(undef, $line);
+               return $params{'request_cb'}->(undef, $line);
            }
        }
     };
            }
        }
     };
@@ -196,6 +196,8 @@ sub clerk_notif_holding {
 
 package main;
 
 
 package main;
 
+use Amanda::MainLoop qw( :GIOCondition );
+
 # Given a dumpfile_t, figure out the command line to validate, specified
 # as an argv array
 sub find_validation_command {
 # Given a dumpfile_t, figure out the command line to validate, specified
 # as an argv array
 sub find_validation_command {
@@ -249,16 +251,20 @@ sub main {
 
     my $tapelist;
     my $chg;
 
     my $tapelist;
     my $chg;
-    my $interactive;
+    my $interactivity;
     my $scan;
     my $clerk;
     my $plan;
     my $timestamp;
     my $all_success = 1;
     my @xfer_errs;
     my $scan;
     my $clerk;
     my $plan;
     my $timestamp;
     my $all_success = 1;
     my @xfer_errs;
+    my %all_filter;
+    my $check_done;
 
     my $steps = define_steps
 
     my $steps = define_steps
-       cb_ref => \$finished_cb;
+       cb_ref => \$finished_cb,
+       finalize => sub { $scan->quit() if defined $scan;
+                         $chg->quit() if defined $chg    };
 
     step start => sub {
        # set up the tapelist
 
     step start => sub {
        # set up the tapelist
@@ -271,17 +277,17 @@ sub main {
            unless defined $opt_timestamp;
 
        # make an interactivity plugin
            unless defined $opt_timestamp;
 
        # make an interactivity plugin
-       $interactive = Amanda::Interactive::amcheckdump->new();
+       $interactivity = Amanda::Interactivity::amcheckdump->new();
 
        # make a changer
 
        # make a changer
-       $chg = Amanda::Changer->new();
+       $chg = Amanda::Changer->new(undef, tapelist => $tapelist);
        return $steps->{'quit'}->($chg)
            if $chg->isa("Amanda::Changer::Error");
 
        # make a scan
        $scan = Amanda::Recovery::Scan->new(
                            chg => $chg,
        return $steps->{'quit'}->($chg)
            if $chg->isa("Amanda::Changer::Error");
 
        # make a scan
        $scan = Amanda::Recovery::Scan->new(
                            chg => $chg,
-                           interactive => $interactive);
+                           interactivity => $interactivity);
        return $steps->{'quit'}->($scan)
            if $scan->isa("Amanda::Changer::Error");
 
        return $steps->{'quit'}->($scan)
            if $scan->isa("Amanda::Changer::Error");
 
@@ -357,11 +363,11 @@ sub main {
            if ($hdr->{'srv_encrypt'}) {
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
            if ($hdr->{'srv_encrypt'}) {
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
-                       [ $hdr->{'srv_encrypt'}, $hdr->{'srv_decrypt_opt'} ], 0, 0);
+                       [ $hdr->{'srv_encrypt'}, $hdr->{'srv_decrypt_opt'} ], 0);
            } elsif ($hdr->{'clnt_encrypt'}) {
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
            } elsif ($hdr->{'clnt_encrypt'}) {
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
-                       [ $hdr->{'clnt_encrypt'}, $hdr->{'clnt_decrypt_opt'} ], 0, 0);
+                       [ $hdr->{'clnt_encrypt'}, $hdr->{'clnt_decrypt_opt'} ], 0);
            } else {
                return failure("could not decrypt encrypted dump: no program specified",
                            $finished_cb);
            } else {
                return failure("could not decrypt encrypted dump: no program specified",
                            $finished_cb);
@@ -382,17 +388,17 @@ sub main {
                # TODO: this assumes that srvcompprog takes "-d" to decrypt
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
                # TODO: this assumes that srvcompprog takes "-d" to decrypt
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
-                       [ $hdr->{'srvcompprog'}, "-d" ], 0, 0);
+                       [ $hdr->{'srvcompprog'}, "-d" ], 0);
            } elsif ($hdr->{'clntcompprog'}) {
                # TODO: this assumes that clntcompprog takes "-d" to decrypt
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
            } elsif ($hdr->{'clntcompprog'}) {
                # TODO: this assumes that clntcompprog takes "-d" to decrypt
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
-                       [ $hdr->{'clntcompprog'}, "-d" ], 0, 0);
+                       [ $hdr->{'clntcompprog'}, "-d" ], 0);
            } else {
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
                        [ $Amanda::Constants::UNCOMPRESS_PATH,
            } else {
                push @filters,
                    Amanda::Xfer::Filter::Process->new(
                        [ $Amanda::Constants::UNCOMPRESS_PATH,
-                         $Amanda::Constants::UNCOMPRESS_OPT ], 0, 0);
+                         $Amanda::Constants::UNCOMPRESS_OPT ], 0);
            }
 
            # adjust the header
            }
 
            # adjust the header
@@ -404,12 +410,46 @@ sub main {
        # we need to throw out its stdout
        my $argv = find_validation_command($hdr);
        if (defined $argv) {
        # we need to throw out its stdout
        my $argv = find_validation_command($hdr);
        if (defined $argv) {
-           push @filters, Amanda::Xfer::Filter::Process->new($argv, 0, 0);
+           push @filters, Amanda::Xfer::Filter::Process->new($argv, 0);
        }
 
        # we always throw out stdout
        my $xfer_dest = Amanda::Xfer::Dest::Null->new(0);
 
        }
 
        # we always throw out stdout
        my $xfer_dest = Amanda::Xfer::Dest::Null->new(0);
 
+       # start reading all filter stderr
+       foreach my $filter (@filters) {
+           my $fd = $filter->get_stderr_fd();
+           $fd.="";
+           $fd = int($fd);
+           my $src = Amanda::MainLoop::fd_source($fd,
+                                                 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
+           my $buffer = "";
+           $all_filter{$src} = 1;
+           $src->set_callback( sub {
+               my $b;
+               my $n_read = POSIX::read($fd, $b, 1);
+               if (!defined $n_read) {
+                   return;
+               } elsif ($n_read == 0) {
+                   delete $all_filter{$src};
+                   $src->remove();
+                   POSIX::close($fd);
+                   if (!%all_filter and $check_done) {
+                       $finished_cb->();
+                   }
+               } else {
+                   $buffer .= $b;
+                   if ($b eq "\n") {
+                       my $line = $buffer;
+                       print STDERR "filter stderr: $line";
+                       chomp $line;
+                       debug("filter stderr: $line");
+                       $buffer = "";
+                   }
+               }
+           });
+       }
+
        my $xfer = Amanda::Xfer->new([ $xfer_src, @filters, $xfer_dest ]);
        $xfer->start($steps->{'handle_xmsg'});
        $clerk->start_recovery(
        my $xfer = Amanda::Xfer->new([ $xfer_src, @filters, $xfer_dest ]);
        $xfer->start($steps->{'handle_xmsg'});
        $clerk->start_recovery(
@@ -458,7 +498,8 @@ sub main {
        if ($err) {
            $exit_code = 1;
            print STDERR $err, "\n";
        if ($err) {
            $exit_code = 1;
            print STDERR $err, "\n";
-           return $clerk->quit(finished_cb => $finished_cb);
+           return $clerk->quit(finished_cb => $steps->{'quit1'}) if defined $clerk;;
+           return $steps->{'quit1'}->();
        }
 
        if ($all_success) {
        }
 
        if ($all_success) {
@@ -468,8 +509,16 @@ sub main {
            $exit_code = 1;
        }
 
            $exit_code = 1;
        }
 
-       return $clerk->quit(finished_cb => $finished_cb);
+       return $clerk->quit(finished_cb => $steps->{'quit1'});
     };
     };
+
+    step quit1 => sub {
+       $check_done = 1;
+
+       if (!%all_filter) {
+           $finished_cb->();
+       }
+    }
 }
 
 main(sub { Amanda::MainLoop::quit(); });
 }
 
 main(sub { Amanda::MainLoop::quit(); });