bin/amdumpext
changeset 11 9ad262d8c301
parent 10 8231f7b00052
child 12 9e30f40ffb34
equal deleted inserted replaced
10:8231f7b00052 11:9ad262d8c301
    35 use constant NO        => 'NO';
    35 use constant NO        => 'NO';
    36 use constant DUMPDATES => '/var/lib/dumpdates';
    36 use constant DUMPDATES => '/var/lib/dumpdates';
    37 use constant FD3       => 3;
    37 use constant FD3       => 3;
    38 use constant FD4       => 4;
    38 use constant FD4       => 4;
    39 
    39 
       
    40 my $BS = 64 * 2**20;    # 64 MB read size
       
    41 
    40 $SIG{__DIE__} = sub { die $^S ? '' : "$ME: ", @_ };
    42 $SIG{__DIE__} = sub { die $^S ? '' : "$ME: ", @_ };
    41 
    43 
    42 my %SUPPORT = (
    44 my %SUPPORT = (
    43     CONFIG          => YES,    # --config … (default)
    45     CONFIG          => YES,    # --config … (default)
    44     DISK            => NO,     # --disk …
    46     DISK            => NO,     # --disk …
    56 
    58 
    57 sub exec_support;
    59 sub exec_support;
    58 sub exec_selfcheck;
    60 sub exec_selfcheck;
    59 sub exec_estimate;
    61 sub exec_estimate;
    60 sub exec_backup;
    62 sub exec_backup;
       
    63 sub exec_validate;
    61 
    64 
    62 # some helper functions
    65 # some helper functions
    63 
    66 
    64 sub device;
    67 sub device;
    65 sub OK;
    68 sub OK;
    90         'host=s'      => sub { },            # ignore
    93         'host=s'      => sub { },            # ignore
    91         'disk=s'      => sub { },            # ignore
    94         'disk=s'      => sub { },            # ignore
    92     ) or pod2usage;
    95     ) or pod2usage;
    93 
    96 
    94     given ($command) {
    97     given ($command) {
    95         when ("support") { exec_support }
    98         when ('support') { exec_support }
    96         when ("selfcheck") {
    99         when ('selfcheck') {
    97             pod2usage if undef ~~ $opt_device;
   100             pod2usage if undef ~~ $opt_device;
    98             exec_selfcheck
   101             exec_selfcheck
    99         }
   102         }
   100         when ("estimate") {
   103         when ('estimate') {
   101             pod2usage if undef ~~ [$opt_device, $opt_level[0]];
   104             pod2usage if undef ~~ [$opt_device, $opt_level[0]];
   102             exec_estimate
   105             exec_estimate
   103         }
   106         }
   104         when ("backup") {
   107         when ('backup') {
   105             pod2usage if undef ~~ [$opt_device, $opt_level[0]];
   108             pod2usage if undef ~~ [$opt_device, $opt_level[0]];
   106             exec_backup
   109             exec_backup
   107         }
   110         }
       
   111         when ('validate') {
       
   112             exec_validate
       
   113         }
       
   114 
   108         default { pod2usage }
   115         default { pod2usage }
   109     }
   116     }
   110 }
   117 }
   111 
   118 
   112 # output a list of supported options
   119 # output a list of supported options
   131         my (undef, @gids) = split ' ', $);
   138         my (undef, @gids) = split ' ', $);
   132         my @groups = map { '' . getgrgid $_ } @gids;
   139         my @groups = map { '' . getgrgid $_ } @gids;
   133         "@gids (@groups)";
   140         "@gids (@groups)";
   134     };
   141     };
   135 
   142 
   136     foreach my $tool (qw(dump restore)) {
   143     foreach my $tool (qw(dump restore cat)) {
   137         if ($_ = (grep { -x ($_ .= "/$tool") } split /:/ => $ENV{PATH})[0]) {
   144         if (my $path =
   138             my ($version, undef) = `$_ 2>&1`;
   145             (grep { -x ($_ .= "/$tool") } split /:/ => $ENV{PATH})[0])
   139 	    chomp $version;
   146         {
   140             OK "$tool is $version";
   147 
       
   148             # not all tools understand --version, but fortunately they
       
   149             # all output a line starting with the name of the tool and
       
   150             # the version information
       
   151             my ($version, undef) =
       
   152               map  { /^.*?\s+(.*)/ }
       
   153               grep { /\A(?:$path|$tool)\s/ } `$path --version 2>&1`;
       
   154             chomp $version;
       
   155             OK "$tool is $path $version";
   141         }
   156         }
   142         else {
   157         else {
   143             ERROR "$tool not found in $ENV{PATH}";
   158             ERROR "$tool not found in $ENV{PATH}";
   144         }
   159         }
   145     }
   160     }
   255                     };
   270                     };
   256                     exec 'restore', -tvf => '-';
   271                     exec 'restore', -tvf => '-';
   257                     die "Can't exec `restore -tvf -`: $!";
   272                     die "Can't exec `restore -tvf -`: $!";
   258                 };
   273                 };
   259 
   274 
   260                 # the restore may close it's input, we'll get
   275                 # The restore may close it's input, we'll get
   261                 # a SIG{PIPE} because of this
   276                 # a SIG{PIPE} because of this.
       
   277                 # But how can we be sure that it was the restore
       
   278                 # that just sent us the signal? Currently we write
       
   279                 # to two processes only, writing to STDOUT (the data
       
   280                 # stream up down to the server). If this fails we die.
       
   281                 # The other stream we write to is the 'restore'.
       
   282                 # If we got this SIGPIPE, we 'switch' to cat, since
       
   283                 # it's faster then our perl script.
   262                 local $SIG{PIPE} = sub {
   284                 local $SIG{PIPE} = sub {
   263                     close $restore;
   285                     close $restore;
   264                     $restore = undef;
   286                     $restore = undef;
   265                     $SIG{PIPE} = 'default';
   287                     $SIG{PIPE} = 'default';
       
   288                     exec 'cat';
       
   289                     die "Can't exec `cat': $!\n";
   266                 };
   290                 };
   267 
   291 
   268                 local $/ = \(my $x = 64 * 1024);
   292                 local $/ = \$BS;
   269                 while (<STDIN>) {
   293                 while (<STDIN>) {
   270                     print $_;
   294                     print $_ or die "Can't send data to `dump': $!\n";
   271                     print $restore $_ if $restore;
   295                     print $restore $_;
   272                 }
   296                 }
   273                 close($restore) if $restore;
   297                 close($restore) if $restore;
   274                 exit 0;
   298                 exit 0;
   275             };
   299             };
   276 
   300 
   395 
   419 
   396     }
   420     }
   397 
   421 
   398 }
   422 }
   399 
   423 
       
   424 sub exec_validate {
       
   425 
       
   426     my $pid = fork // die "Can't fork: $!\n";
       
   427 
       
   428     # the first part goes into restore
       
   429     # but restore stops reading after the directory
       
   430     if (not $pid) {
       
   431         exec 'restore', '-tf', '-';
       
   432         die "Can't exec restore: $!\n";
       
   433     }
       
   434     waitpid($pid, 0);
       
   435     die $? if $?;
       
   436 
       
   437     # read the remaining dump via cat, I think,
       
   438     # nobody is fast than cat
       
   439     open(STDOUT, '>', '/dev/null')
       
   440       or die "Can't redirect STDOUT to >/dev/null: $!\n";
       
   441     exec 'cat';
       
   442     die "Can't exec `cat': $!\n";
       
   443 }
       
   444 
   400 sub device {
   445 sub device {
   401     my $_ = shift;
   446     my $_ = shift;
   402     return $_ if /^\//;
   447     return $_ if /^\//;
   403     return "/dev/$_";
   448     return "/dev/$_";
   404 }
   449 }
   417   amdumpext - the amanda dump application
   462   amdumpext - the amanda dump application
   418 
   463 
   419 =head1 SYNOPSIS
   464 =head1 SYNOPSIS
   420 
   465 
   421   amdumpext support
   466   amdumpext support
   422   amdumpext selfcheck [options] [--level <level>]    --device <device> 
   467   amdumpext selfcheck [options] [--level <level>] --device <device> 
   423   amdumpext estimate [options]  [--level <level>]... --device <device> 
   468   amdumpext backup    [options] [--level <level>] --device <device> 
       
   469   amdumpext estimate  [options] [--level <level>]... --device <device> 
       
   470   amdumpext validate 
   424 
   471 
   425 =head1 DESCRIPTION
   472 =head1 DESCRIPTION
   426 
   473 
   427 The B<amdumpext> is an application plugin for amanda. It drives the
   474 The B<amdumpext> is an application plugin for amanda. It drives the
   428 native ext2/3/4 dump/restore programs found on most Linux systems. See L<dump(8)>
   475 native ext2/3/4 dump/restore programs found on most Linux systems. See L<dump(8)>
   486 
   533 
   487 Create an estimate about the amount of data we may expect for the
   534 Create an estimate about the amount of data we may expect for the
   488 backup. Multi-Level estimates are supported.
   535 backup. Multi-Level estimates are supported.
   489 
   536 
   490 mandatory options: device, level, ...
   537 mandatory options: device, level, ...
       
   538 
       
   539 =head2 validate
       
   540 
       
   541 This checks if the data stream is readable and looks like a dump.
       
   542 Actually it does not try to completly validate the stream, as B<restore>
       
   543 does not have such an option.
   491 
   544 
   492 =head1 PROPERTIES
   545 =head1 PROPERTIES
   493 
   546 
   494 The properties may be set on the server side to tune the behaviour
   547 The properties may be set on the server side to tune the behaviour
   495 of the application. Currently property setting on the client side is
   548 of the application. Currently property setting on the client side is