Imported Upstream version 3.3.1
[debian/amanda] / server-src / amfetchdump.pl
index 11a6bc1b924e44c2db4dec11119569c5aa63d696..b1e1fb904d638a454c199a1b52981a5749c2d262 100644 (file)
@@ -38,12 +38,12 @@ use Amanda::Recovery::Planner;
 use Amanda::Recovery::Clerk;
 use Amanda::Recovery::Scan;
 
-# Interactive package
-package Amanda::Interactive::amfetchdump;
+# Interactivity package
+package Amanda::Interactivity::amfetchdump;
 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;
@@ -78,12 +78,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 {
@@ -93,7 +93,7 @@ sub user_request {
                chomp $line;
                $buffer = "";
                $self->abort();
-               return $params{'finished_cb'}->(undef, $line);
+               return $params{'request_cb'}->(undef, $line);
            }
        }
     };
@@ -112,10 +112,9 @@ package main;
 sub usage {
     my ($msg) = @_;
     print STDERR <<EOF;
-Usage: amfetchdump config [-c|-C|-l] [-p|-n] [-a]
-    [-O directory] [-d device] [-o configoption]*
-    [--header-file file] [--header-fd fd]
-    hostname [diskname [datestamp [hostname [diskname [datestamp ... ]]]]]"));
+Usage: amfetchdump [-c|-C|-l] [-p|-n] [-a] [-O directory] [-d device]
+    [-h] [--header-file file] [--header-fd fd] [-o configoption]* config
+    hostname [diskname [datestamp [hostname [diskname [datestamp ... ]]]]]
 EOF
     print STDERR "ERROR: $msg\n" if $msg;
     exit(1);
@@ -131,6 +130,8 @@ my $config_overrides = new_config_overrides($#ARGV+1);
 my ($opt_config, $opt_no_reassembly, $opt_compress, $opt_compress_best, $opt_pipe,
     $opt_assume, $opt_leave, $opt_blocksize, $opt_device, $opt_chdir, $opt_header,
     $opt_header_file, $opt_header_fd, @opt_dumpspecs);
+
+debug("Arguments: " . join(' ', @ARGV));
 Getopt::Long::Configure(qw(bundling));
 GetOptions(
     'version' => \&Amanda::Util::version_opt,
@@ -156,7 +157,7 @@ $opt_compress = 1 if $opt_compress_best;
 
 usage("must specify at least a hostname") unless @ARGV;
 @opt_dumpspecs = Amanda::Cmdline::parse_dumpspecs([@ARGV],
-    $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP);
+    $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL);
 
 usage("The -b option is no longer supported; set readblocksize in the tapetype section\n" .
       "of amanda.conf instead.")
@@ -212,14 +213,14 @@ sub new {
     }, $class;
 }
 
-sub notif_part {
+sub clerk_notif_part {
     my $self = shift;
     my ($label, $filenum, $header) = @_;
 
     print STDERR "amfetchdump: $filenum: restoring ", $header->summary(), "\n";
 }
 
-sub notif_holding {
+sub clerk_notif_holding {
     my $self = shift;
     my ($filename, $header) = @_;
 
@@ -229,11 +230,14 @@ sub notif_holding {
 
 package main;
 
+use Amanda::MainLoop qw( :GIOCondition );
 sub main {
     my ($finished_cb) = @_;
     my $current_dump;
     my $plan;
     my @xfer_errs;
+    my %all_filter;
+    my $fetch_done;
 
     my $steps = define_steps
        cb_ref => \$finished_cb;
@@ -248,7 +252,7 @@ sub main {
            return failure("Cannot chdir to $destdir: $!", $finished_cb);
        }
 
-       my $interactive = Amanda::Interactive::amfetchdump->new();
+       my $interactivity = Amanda::Interactivity::amfetchdump->new();
        # if we have an explicit device, then the clerk doesn't get a changer --
        # we operate the changer via Amanda::Recovery::Scan
        if (defined $opt_device) {
@@ -256,14 +260,14 @@ sub main {
            return failure($chg, $finished_cb) if $chg->isa("Amanda::Changer::Error");
            my $scan = Amanda::Recovery::Scan->new(
                                chg => $chg,
-                               interactive => $interactive);
+                               interactivity => $interactivity);
            return failure($scan, $finished_cb) if $scan->isa("Amanda::Changer::Error");
            $clerk = Amanda::Recovery::Clerk->new(
                feedback => main::Feedback->new($chg, $opt_device),
                scan     => $scan);
        } else {
            my $scan = Amanda::Recovery::Scan->new(
-                               interactive => $interactive);
+                               interactivity => $interactivity);
            return failure($scan, $finished_cb) if $scan->isa("Amanda::Changer::Error");
 
            $clerk = Amanda::Recovery::Clerk->new(
@@ -288,6 +292,11 @@ sub main {
            return failure("No matching dumps found", $finished_cb);
        }
 
+       # if we are doing a -p operation, only keep the first dump
+       if ($opt_pipe) {
+           @{$plan->{'dumps'}} = ($plan->{'dumps'}[0]);
+       }
+
        my @needed_labels = $plan->get_volume_list();
        my @needed_holding = $plan->get_holding_file_list();
        if (@needed_labels) {
@@ -431,8 +440,42 @@ sub main {
            syswrite $hdr_fh, $hdr->to_string(32768, 32768), 32768;
        }
 
+       # 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 $fetch_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'});
+       $xfer->start($steps->{'handle_xmsg'}, 0, $current_dump->{'bytes'});
        $clerk->start_recovery(
            xfer => $xfer,
            recovery_cb => $steps->{'recovery_cb'});
@@ -475,7 +518,11 @@ sub main {
 
        return failure($err, $finished_cb) if $err;
 
-       $finished_cb->();
+#do all filter are done reading stderr
+       $fetch_done = 1;
+        if (!%all_filter) {
+           $finished_cb->();
+       }
     };
 }