X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famcheckdump.pl;h=d8042bc9294d0f62df571419fb4fea096c6f0c6c;hb=cd0b924f27312d57bd42f6c4fae2b795139e2d0b;hp=b0074562c06c1352f1315cdbd1adfa7db498144c;hpb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;p=debian%2Famanda diff --git a/server-src/amcheckdump.pl b/server-src/amcheckdump.pl index b007456..d8042bc 100644 --- a/server-src/amcheckdump.pl +++ b/server-src/amcheckdump.pl @@ -44,7 +44,7 @@ use Amanda::Xfer qw( :constants ); sub usage { print < 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); -# 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 ); -@ISA = qw( Amanda::Interactive ); +@ISA = qw( Amanda::Interactivity ); sub new { my $class = shift; @@ -135,12 +135,12 @@ sub user_request { 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(); - return $params{'finished_cb'}->( + return $params{'request_cb'}->( Amanda::Changer::Error->new('fatal', message => "Aborted by user")); } else { @@ -150,7 +150,7 @@ sub user_request { 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; +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 { @@ -249,16 +251,20 @@ sub main { my $tapelist; my $chg; - my $interactive; + my $interactivity; 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 - 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 @@ -271,17 +277,17 @@ sub main { unless defined $opt_timestamp; # make an interactivity plugin - $interactive = Amanda::Interactive::amcheckdump->new(); + $interactivity = Amanda::Interactivity::amcheckdump->new(); # 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, - interactive => $interactive); + interactivity => $interactivity); 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( - [ $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( - [ $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); @@ -382,17 +388,17 @@ sub main { # 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( - [ $hdr->{'clntcompprog'}, "-d" ], 0, 0); + [ $hdr->{'clntcompprog'}, "-d" ], 0); } 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 @@ -404,12 +410,46 @@ sub main { # 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); + # 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( @@ -458,7 +498,8 @@ sub main { 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) { @@ -468,8 +509,16 @@ sub main { $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(); });