bin/amdumpext
changeset 9 d176b9443312
parent 8 69a0459ed8b1
child 10 8231f7b00052
equal deleted inserted replaced
8:69a0459ed8b1 9:d176b9443312
    86         'index=s'     => \$opt_index,        # --index line
    86         'index=s'     => \$opt_index,        # --index line
    87         'record!'     => \$opt_record,       # --record
    87         'record!'     => \$opt_record,       # --record
    88         'level=i@'    => \@opt_level,        # --level n
    88         'level=i@'    => \@opt_level,        # --level n
    89         'dumpdates=s' => \$opt_dumpdates,    # --dumpdates <file>
    89         'dumpdates=s' => \$opt_dumpdates,    # --dumpdates <file>
    90         'host=s'      => sub { },            # ignore
    90         'host=s'      => sub { },            # ignore
    91 	'disk=s'      => sub { },	     # ignore
    91         'disk=s'      => sub { },            # ignore
    92     ) or pod2usage;
    92     ) or pod2usage;
    93 
    93 
    94     given ($command) {
    94     given ($command) {
    95         when ("support") { exec_support }
    95         when ("support") { exec_support }
    96         when ("selfcheck") {
    96         when ("selfcheck") {
   119 
   119 
   120     # must: $opt_device
   120     # must: $opt_device
   121     # may: $opt_level
   121     # may: $opt_level
   122 
   122 
   123     OK "$ME version $VERSION";
   123     OK "$ME version $VERSION";
   124     OK "euid=$> (" . getpwuid($>) . ')'; 
   124     OK "euid=$> (" . getpwuid($>) . ')';
   125     OK "egid=" . do {
   125     OK "egid=" . do {
   126 	my $gid = (split ' ', $))[0];
   126         my $gid = (split ' ', $))[0];
   127 	my $group = getgrgid $gid;
   127         my $group = getgrgid $gid;
   128 	"$gid ($group)";
   128         "$gid ($group)";
   129     };
   129     };
   130     OK "groups=" . do {
   130     OK "groups=" . do {
   131 	my (undef, @gids) = split ' ', $);
   131         my (undef, @gids) = split ' ', $);
   132 	my @groups = map { '' . getgrgid $_ } @gids;
   132         my @groups = map { '' . getgrgid $_ } @gids;
   133 	"@gids (@groups)";
   133         "@gids (@groups)";
   134     };
   134     };
   135 
   135 
   136     foreach my $tool (qw(dump restore)) {
   136     foreach my $tool (qw(dump restore)) {
   137     if ($_ = (grep { -x ($_ .= "/$tool") } split /:/ => $ENV{PATH})[0]) {
   137         if ($_ = (grep { -x ($_ .= "/$tool") } split /:/ => $ENV{PATH})[0]) {
   138         chomp(my $version = (`$_ 2>&1`)[0]);
   138             chomp(my $version = (`$_ 2>&1`)[0]);
   139         OK "$tool is $version";
   139             OK "$tool is $version";
   140     }
   140         }
   141     else {
   141         else {
   142         ERROR "$tool not found in $ENV{PATH}";
   142             ERROR "$tool not found in $ENV{PATH}";
   143     }
   143         }
   144     }
   144     }
   145 
   145 
   146     # check the device
   146     # check the device
   147     # the opt_disk is just a label, the device is in opt_device!
   147     # the opt_disk is just a label, the device is in opt_device!
   148     my $device = device($opt_device);
   148     my $device = device($opt_device);
   170     my (@errors, @results);
   170     my (@errors, @results);
   171 
   171 
   172     foreach my $level (@opt_level) {
   172     foreach my $level (@opt_level) {
   173         my @cmd = (
   173         my @cmd = (
   174             dump => "-$level",
   174             dump => "-$level",
   175             '-S',   # estimate
   175             '-S',    # estimate
   176             $opt_record && $opt_dumpdates ? (-D => expand($opt_dumpdates)) : (),
   176             $opt_record && $opt_dumpdates ? (-D => expand($opt_dumpdates)) : (),
   177             device($opt_device),
   177             device($opt_device),
   178         );
   178         );
   179 
   179 
   180         my @output = `@cmd 2>&1`;
   180         my @output = `@cmd 2>&1`;
   216     # fd3: message channel
   216     # fd3: message channel
   217     # fd4: index channel
   217     # fd4: index channel
   218 
   218 
   219     my @dump = (
   219     my @dump = (
   220         dump => "-$opt_level[0]",
   220         dump => "-$opt_level[0]",
   221 	#'-v', # verbose
   221 
   222         -f   => '-',
   222         #'-v', # verbose
       
   223         -f => '-',
   223         $opt_record ? '-u' : (),
   224         $opt_record ? '-u' : (),
   224         $opt_record && $opt_dumpdates ? (-D => expand($opt_dumpdates)) : (),
   225         $opt_record && $opt_dumpdates ? (-D => expand($opt_dumpdates)) : (),
   225         device($opt_device)
   226         device($opt_device)
   226     );
   227     );
   227 
   228 
   233     open(my $idx, '>&=', FD4) or die "Can't open fd4: $!\n" if $opt_index;
   234     open(my $idx, '>&=', FD4) or die "Can't open fd4: $!\n" if $opt_index;
   234 
   235 
   235     if ($opt_index) {
   236     if ($opt_index) {
   236         my $pid = fork // die "Can't fork: $!\n";
   237         my $pid = fork // die "Can't fork: $!\n";
   237         if (not $pid) {
   238         if (not $pid) {
   238 	    $0 = "$ME [about to exec dump]";
   239             $0 = "$ME [about to exec dump]";
   239 
   240 
   240 	    # dump will be execed soon, first we've to establish
   241             # dump will be execed soon, first we've to establish
   241 	    # the channels - one for STDOUT, and one for STDIN
   242             # the channels - one for STDOUT, and one for STDIN
   242             open(STDOUT, '|-') or do {
   243             open(STDOUT, '|-') or do {
   243 		# this is the child that will read
   244 
   244 		# the STDOUT from dump
   245                 # this is the child that will read
   245 		$0 = "$ME [stdout < dump]";
   246                 # the STDOUT from dump
       
   247                 $0 = "$ME [stdout < dump]";
   246 
   248 
   247                 my $pid = open(my $restore, '|-') or do {
   249                 my $pid = open(my $restore, '|-') or do {
   248 		    $0 = "$ME [toc]";
   250                     $0 = "$ME [toc]";
   249                     open(STDOUT, '|-') or do {
   251                     open(STDOUT, '|-') or do {
   250                         postprocess_toc($idx);
   252                         postprocess_toc($idx);
   251                         exit 0;
   253                         exit 0;
   252                     };
   254                     };
   253                     exec 'restore', -tvf => '-';
   255                     exec 'restore', -tvf => '-';
   254                     die "Can't exec `restore -tvf -`: $!";
   256                     die "Can't exec `restore -tvf -`: $!";
   255                 };
   257                 };
   256 
   258 
   257 		# the restore may close it's input, we'll get
   259                 # the restore may close it's input, we'll get
   258 		# a SIG{PIPE} because of this
   260                 # a SIG{PIPE} because of this
   259 		local $SIG{PIPE} = sub { 
   261                 local $SIG{PIPE} = sub {
   260 		    close $restore;
   262                     close $restore;
   261 		    $restore = undef;
   263                     $restore = undef;
   262 		    $SIG{PIPE} = 'default';
   264                     $SIG{PIPE} = 'default';
   263 		};
   265                 };
   264 
   266 
   265                 local $/ = \(my $x = 64 * 1024);
   267                 local $/ = \(my $x = 64 * 1024);
   266                 while (<STDIN>) {
   268                 while (<STDIN>) {
   267                     print $_;
   269                     print $_;
   268                     print $restore $_ if $restore;
   270                     print $restore $_ if $restore;
   269                 }
   271                 }
   270 		close($restore) if $restore;
   272                 close($restore) if $restore;
   271                 exit 0;
   273                 exit 0;
   272             };
   274             };
   273 	    
   275 
   274             open(STDERR, '|-') or do {
   276             open(STDERR, '|-') or do {
   275 		$0 = "$ME [stderr < dump]";
   277                 $0 = "$ME [stderr < dump]";
   276                 postprocess_dump_messages($msg);
   278                 postprocess_dump_messages($msg);
   277                 exit 0;
   279                 exit 0;
   278             };
   280             };
   279 
   281 
   280 	     # we need to fork again, otherwise dump sees
   282             # we need to fork again, otherwise dump sees
   281 	     # the end of the above children and complains
   283             # the end of the above children and complains
   282 	     my $pid = fork // die "Can't fork: $!\n";
   284             my $pid = fork // die "Can't fork: $!\n";
   283 	     if (not $pid) {
   285             if (not $pid) {
   284 		exec @dump;
   286                 exec @dump;
   285 		die "Can't exec `@dump': $!\n";
   287                 die "Can't exec `@dump': $!\n";
   286 	    }
   288             }
   287 
   289 
   288 	    waitpid($pid, 0);
   290             waitpid($pid, 0);
   289         }
   291         }
   290 
   292 
   291         waitpid($pid, 0);
   293         waitpid($pid, 0);
   292         exit $?;
   294         exit $?;
   293     }
   295     }
   316 
   318 
   317 }
   319 }
   318 
   320 
   319 sub postprocess_dump_messages {
   321 sub postprocess_dump_messages {
   320 
   322 
   321     select +shift;  # send output to the message channel
   323     select +shift;    # send output to the message channel
   322 
   324 
   323     while (<STDIN>) {
   325     while (<STDIN>) {
   324         print "| $_";
   326         print "| $_";
   325         if (/^\s+DUMP: (\d+) blocks?/) {
   327         if (/^\s+DUMP: (\d+) blocks?/) {
       
   328 
   326             # we assume a block size of 1K
   329             # we assume a block size of 1K
   327             say "sendbackup: size $1";
   330             say "sendbackup: size $1";
   328         }
   331         }
   329         elsif (/^\s+DUMP: DUMP IS DONE/) {
   332         elsif (/^\s+DUMP: DUMP IS DONE/) {
   330             say 'sendbackup: end';
   333             say 'sendbackup: end';
   350     # restore to use a \0 separated output format
   353     # restore to use a \0 separated output format
   351 
   354 
   352     select +shift;
   355     select +shift;
   353     die 'IFS is not as expected!' if $/ ne "\n";
   356     die 'IFS is not as expected!' if $/ ne "\n";
   354 
   357 
   355 
       
   356     my $buffer = undef;
   358     my $buffer = undef;
   357     my $type   = undef;
   359     my $type   = undef;
   358 
   360 
   359     while (1) {
   361     while (1) {
   360 
   362 
   362 
   364 
   363         # skip the header lines
   365         # skip the header lines
   364         if (1 .. defined && /\Adir\s+\d+\s+(.*)\Z/) {
   366         if (1 .. defined && /\Adir\s+\d+\s+(.*)\Z/) {
   365             $buffer = '';
   367             $buffer = '';
   366             $type   = 'dir';
   368             $type   = 'dir';
   367 	    die "Unexpected end of input while reading from restore -tvf\n" if not defined;
   369             die "Unexpected end of input while reading from restore -tvf\n"
       
   370               if not defined;
   368             next;
   371             next;
   369         }
   372         }
   370 
   373 
   371         # if we match really good the buffer may be output
   374         # if we match really good the buffer may be output
   372         if (not defined
   375         if (not defined