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); |
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'; |