X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famrestore.pl;h=b9cde45d12add14f8ba59c86389d1ed5776fc6c3;hb=HEAD;hp=c2ec9d441bfaefcafedded12accb2554755f5964;hpb=fd48f3e498442f0cbff5f3606c7c403d0566150e;p=debian%2Famanda diff --git a/server-src/amrestore.pl b/server-src/amrestore.pl index c2ec9d4..b9cde45 100644 --- a/server-src/amrestore.pl +++ b/server-src/amrestore.pl @@ -1,9 +1,10 @@ #! @PERL@ -# Copyright (c) 2009, 2010 Zmanda, Inc. All Rights Reserved. +# Copyright (c) 2009-2012 Zmanda, Inc. All Rights Reserved. # -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 as published -# by the Free Software Foundation. +# This program 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 2 +# of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -30,9 +31,11 @@ use Amanda::Util qw( :constants ); use Amanda::Changer; use Amanda::Constants; use Amanda::MainLoop; +use Amanda::MainLoop qw( :GIOCondition ); use Amanda::Header; use Amanda::Holding; use Amanda::Cmdline; +use Amanda::Tapelist; use Amanda::Xfer qw( :constants ); sub usage { @@ -40,7 +43,7 @@ sub usage { print STDERR "$msg\n" if $msg; print STDERR < \&Amanda::Util::version_opt, 'help|usage|?' => \&usage, 'config=s' => \$opt_config, 'holding' => \$opt_holding, + 'exact-match' => \$opt_exact_match, 'b=i' => \$opt_blocksize, 'r' => \$opt_raw, 'c' => \$opt_compress, @@ -83,8 +89,9 @@ if (!$opt_holding) { if (Amanda::Holding::get_header($opt_restore_src)); } -my @opt_dumpspecs = Amanda::Cmdline::parse_dumpspecs([@ARGV], - $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP); +my $cmd_flags = $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP; +$cmd_flags |= $Amanda::Cmdline::CMDLINE_EXACT_MATCH if $opt_exact_match; +my @opt_dumpspecs = Amanda::Cmdline::parse_dumpspecs([@ARGV], $cmd_flags); usage("Cannot check a label on a holding-disk file") if ($opt_holding and $opt_label); @@ -132,12 +139,16 @@ sub main { my $dev; my $hdr; + my $chg; my $filenum = $opt_filenum; $filenum = 1 if (!$filenum); $filenum = 0 + "$filenum"; # convert to integer + my %all_filter; + my $restore_done; my $steps = define_steps - cb_ref => \$finished_cb; + cb_ref => \$finished_cb, + finalize => sub { $chg->quit() if defined $chg }; step start => sub { # first, return to the original working directory we were started in @@ -148,7 +159,9 @@ sub main { if ($opt_holding) { $steps->{'read_header'}->(); } else { - my $chg = Amanda::Changer->new($opt_restore_src); + my $tlf = Amanda::Config::config_dir_relative(getconf($CNF_TAPELIST)); + my $tl = Amanda::Tapelist->new($tlf); + $chg = Amanda::Changer->new($opt_restore_src, tapelist => $tl); if ($chg->isa("Amanda::Changer::Error")) { return failure($chg, $finished_cb); } @@ -163,6 +176,16 @@ sub main { return failure($err, $finished_cb) if $err; $dev = $res->{'device'}; + + if ($opt_blocksize) { + if ( !$dev->property_set("BLOCK_SIZE", $opt_blocksize)) { + return failure($dev->error_or_status, $finished_cb); + } + + # re-read the label with the correct blocksize + $dev->read_label(); + } + if ($dev->status != $DEVICE_STATUS_SUCCESS) { return failure($dev->error_or_status, $finished_cb); } @@ -175,11 +198,6 @@ sub main { return failure($dev->error_or_status, $finished_cb); } - $res->set_label(label => $dev->volume_label, - finished_cb => $steps->{'set_labeled'}); - }; - - step set_labeled => sub { if ($opt_label) { if ($dev->volume_label ne $opt_label) { my $got = $dev->volume_label; @@ -348,7 +366,41 @@ sub main { # write the header to the destination if requested if ($opt_header) { $hdr->{'blocksize'} = Amanda::Holding::DISK_BLOCK_BYTES; - print $dest_fh $hdr->to_string(32768, 32768); + $dest_fh->syswrite($hdr->to_string(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 $restore_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([ $src, @filters, $dest ]); @@ -372,13 +424,14 @@ sub main { my ($err) = @_; return failure($err, $finished_cb) if $err; - $steps->{'next_file'}->(); + $steps->{'next_file'}->('extracted'); }; step next_file => sub { - # amrestore does not loop over multiple files when reading from - # holding or when outputting to a pipe - if ($opt_holding or $opt_pipe) { + my ($extracted) = @_; + # amrestore does not loop over multiple files when reading from holding + # when outputting to a pipe amrestore extracts only the first file + if ($opt_holding or ($opt_pipe and $extracted)) { return $steps->{'finished'}->(); } @@ -397,10 +450,12 @@ sub main { step quit => sub { my ($err) = @_; $res = undef; - + $restore_done = 1; return failure($err, $finished_cb) if $err; - $finished_cb->(); + if (!%all_filter) { + $finished_cb->(); + } }; } main(\&Amanda::MainLoop::quit);