mirror of https://github.com/digint/btrbk
btrbk: use global stderr (replace err); refeactor filter_stderr, add fatal_stderr
if fatal_stderr is set and returns true, the command exit code is set to -1, resulting in run_cmd() returning undef.pull/299/head
parent
360c8918bb
commit
485bc3ab0c
266
btrbk
266
btrbk
|
@ -285,7 +285,6 @@ my $quiet;
|
|||
my @exclude_vf;
|
||||
my $do_dumper;
|
||||
my $show_progress = 0;
|
||||
my $err = "";
|
||||
my $output_format;
|
||||
my $lockfile;
|
||||
my $tlog_fh;
|
||||
|
@ -294,6 +293,7 @@ my $current_transaction;
|
|||
my @transaction_log;
|
||||
my %config_override;
|
||||
my @tm_now; # current localtime ( sec, min, hour, mday, mon, year, wday, yday, isdst )
|
||||
my @stderr; # stderr of last run_cmd
|
||||
my %warn_once;
|
||||
my %kdf_vars;
|
||||
my $kdf_session_key;
|
||||
|
@ -687,16 +687,15 @@ sub run_cmd(@)
|
|||
|
||||
my @cmd_pipe_in = (ref($_[0]) eq "HASH") ? @_ : { @_ };
|
||||
die unless(scalar(@cmd_pipe_in));
|
||||
$err = "";
|
||||
@stderr = ();
|
||||
|
||||
my $destructive = 0;
|
||||
my $catch_stderr = 0;
|
||||
my $exitcode_loglevel = "debug";
|
||||
my $filter_stderr = undef;
|
||||
my @cmd_pipe;
|
||||
my @unsafe_cmd;
|
||||
my $compressed = undef;
|
||||
my $stream_options = $cmd_pipe_in[0]->{stream_options} // {};
|
||||
my @filter_stderr;
|
||||
my $fatal_stderr;
|
||||
my $has_rsh;
|
||||
|
||||
$cmd_pipe_in[0]->{stream_source} = 1;
|
||||
|
@ -706,10 +705,9 @@ sub run_cmd(@)
|
|||
{
|
||||
die if(defined($href->{cmd_text}));
|
||||
|
||||
$catch_stderr = 1 if($href->{catch_stderr});
|
||||
$filter_stderr = $href->{filter_stderr} if($href->{filter_stderr}); # NOTE: last filter wins!
|
||||
push @filter_stderr, ((ref($href->{filter_stderr}) eq "ARRAY") ? @{$href->{filter_stderr}} : $href->{filter_stderr}) if($href->{filter_stderr});
|
||||
$fatal_stderr = $href->{fatal_stderr} if($href->{fatal_stderr});
|
||||
$destructive = 1 unless($href->{non_destructive});
|
||||
$exitcode_loglevel = $href->{exitcode_loglevel} if($href->{exitcode_loglevel});
|
||||
$has_rsh = 1 if($href->{rsh});
|
||||
|
||||
if($href->{check_unsafe}) {
|
||||
|
@ -819,15 +817,15 @@ sub run_cmd(@)
|
|||
|
||||
|
||||
# execute command
|
||||
my ($pid, $out_fh, $err_fh, @stdout, @stderr);
|
||||
my ($pid, $out_fh, $err_fh, @stdout);
|
||||
$err_fh = gensym;
|
||||
if(eval_quiet { $pid = open3(undef, $out_fh, $err_fh, $cmd); }) {
|
||||
chomp(@stdout = readline($out_fh));
|
||||
chomp(@stderr = readline($err_fh));
|
||||
waitpid($pid, 0);
|
||||
if($loglevel >= 4) {
|
||||
TRACE "[stdout] $_" foreach(@stdout);
|
||||
TRACE "[stderr] $_" foreach(@stderr);
|
||||
TRACE map("[stdout] $_", @stdout);
|
||||
TRACE map("[stderr] $_", @stderr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -847,26 +845,22 @@ sub run_cmd(@)
|
|||
}
|
||||
my $exitcode = $? >> 8;
|
||||
|
||||
my @filtered_err;
|
||||
if($filter_stderr) {
|
||||
@filtered_err = map { &{$filter_stderr} ($exitcode) // () } @stderr;
|
||||
# call hooks: fatal_stderr, filter_stderr
|
||||
if(($exitcode == 0) && $fatal_stderr) {
|
||||
$exitcode = -1 if(grep &{$fatal_stderr}(), @stderr);
|
||||
}
|
||||
elsif($has_rsh && ($exitcode == 255)) {
|
||||
# SSH returns exit status 255 if an error occurred.
|
||||
@filtered_err = map { { error => $_ } } @stderr;
|
||||
$exitcode_loglevel = "error";
|
||||
foreach my $filter_fn (@filter_stderr) {
|
||||
@stderr = map { &{$filter_fn} ($exitcode); $_ // () } @stderr;
|
||||
}
|
||||
|
||||
if($exitcode || (grep { $_->{fatal} } @filtered_err)) {
|
||||
my $log_text = "Command execution failed (exitcode=$exitcode): `$cmd`";
|
||||
$exitcode_loglevel = "error" if(scalar(@filtered_err));
|
||||
if($exitcode_loglevel eq "error") { ERROR $log_text; }
|
||||
elsif($exitcode_loglevel eq "warn") { WARN $log_text; }
|
||||
else { DEBUG $log_text; }
|
||||
foreach(@filtered_err) {
|
||||
ERROR "... $_->{error}" if(defined($_->{error}));
|
||||
WARN "... $_->{warn}" if(defined($_->{warn}));
|
||||
DEBUG "... $_->{debug}" if(defined($_->{debug}));
|
||||
unshift @stderr, "sh: $cmd";
|
||||
|
||||
if($exitcode) {
|
||||
my @log_text = ("Command execution failed (exitcode=$exitcode): `$cmd`", map("... $_", @stderr));
|
||||
if($has_rsh && ($exitcode == 255)) { # SSH returns exit status 255 if an error occurred.
|
||||
ERROR @log_text;
|
||||
} else {
|
||||
DEBUG @log_text;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
@ -877,13 +871,25 @@ sub run_cmd(@)
|
|||
}
|
||||
|
||||
|
||||
sub _btrfs_filter_stderr
|
||||
{
|
||||
if(/^usage: / || /(unrecognized|invalid) option/) {
|
||||
WARN_ONCE "Using unsupported btrfs-progs < v$BTRFS_PROGS_MIN";
|
||||
}
|
||||
# strip error prefix (we print our own)
|
||||
# note that this also affects ssh_filter_btrbk.sh error strings
|
||||
s/^ERROR: //;
|
||||
}
|
||||
|
||||
|
||||
sub btrfs_filesystem_show($)
|
||||
{
|
||||
my $vol = shift || die;
|
||||
my $path = $vol->{PATH} // die;
|
||||
return run_cmd( cmd => vinfo_cmd($vol, "btrfs filesystem show", { unsafe => $path } ),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1
|
||||
non_destructive => 1,
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -894,7 +900,8 @@ sub btrfs_filesystem_df($)
|
|||
my $path = $vol->{PATH} // die;
|
||||
return run_cmd( cmd => vinfo_cmd($vol, "btrfs filesystem df", { unsafe => $path }),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1
|
||||
non_destructive => 1,
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -905,8 +912,14 @@ sub btrfs_filesystem_usage($)
|
|||
my $path = $vol->{PATH} // die;
|
||||
my $ret = run_cmd( cmd => vinfo_cmd($vol, "btrfs filesystem usage", { unsafe => $path } ),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1
|
||||
non_destructive => 1,
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
unless(defined($ret)) {
|
||||
ERROR "Failed to fetch btrfs filesystem usage for: $vol->{PRINT}", map("... $_", @stderr);
|
||||
return undef;
|
||||
}
|
||||
|
||||
return undef unless(defined($ret));
|
||||
|
||||
my %detail;
|
||||
|
@ -978,21 +991,7 @@ sub btrfs_subvolume_show($;@)
|
|||
my $ret = run_cmd(cmd => vinfo_cmd($vol, "btrfs subvolume show", @cmd_options, { unsafe => $path }),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1,
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
filter_stderr => sub {
|
||||
return undef unless($_[0]); # do nothing if exitcode=0
|
||||
if(s/^ERROR: //) { # catch errors from btrfs-progs as well as ssh_filter_btrbk.sh
|
||||
$err = $_;
|
||||
return { error => $_, fatal => 1 } if(/^ssh_filter_btrbk.sh/); # "fatal" causes run_cmd to return undef
|
||||
} elsif(/(unrecognized|invalid) option/) {
|
||||
WARN_ONCE "$_ (maybe using unsupported btrfs-progs < v$BTRFS_PROGS_MIN " . ($vol->{HOST} ? "on host=$vol->{HOST} " : "") . "?)";
|
||||
} else {
|
||||
DEBUG "Unparsed error: $_";
|
||||
$err ||= $_;
|
||||
}
|
||||
# soft fail: $err can be displayed as a user-friendly WARNING
|
||||
return undef;
|
||||
},
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
|
||||
return undef unless(defined($ret));
|
||||
|
@ -1103,6 +1102,7 @@ sub btrfs_subvolume_list_readonly_flag($)
|
|||
my $ret = run_cmd(cmd => vinfo_cmd($vol, "btrfs subvolume list", '-a', '-r', { unsafe => $path } ),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1,
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
return undef unless(defined($ret));
|
||||
|
||||
|
@ -1135,6 +1135,7 @@ sub btrfs_subvolume_list($;@)
|
|||
my $ret = run_cmd(cmd => vinfo_cmd($vol, "btrfs subvolume list", @filter_options, @display_options, { unsafe => $path } ),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1,
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
return undef unless(defined($ret));
|
||||
|
||||
|
@ -1219,9 +1220,10 @@ sub btrfs_subvolume_find_new($$;$)
|
|||
my $ret = run_cmd(cmd => vinfo_cmd($vol, "btrfs subvolume find-new", { unsafe => $path }, $lastgen ),
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1,
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
unless(defined($ret)) {
|
||||
ERROR "Failed to fetch modified files for: $vol->{PRINT}";
|
||||
ERROR "Failed to fetch modified files for: $vol->{PRINT}", map("... $_", @stderr);
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
@ -1285,10 +1287,11 @@ sub btrfs_subvolume_snapshot($$)
|
|||
);
|
||||
my $ret = run_cmd(cmd => vinfo_cmd($svol, "btrfs subvolume snapshot", '-r', { unsafe => $src_path }, { unsafe => $target_path } ),
|
||||
rsh => vinfo_rsh($svol),
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
end_transaction("snapshot", defined($ret));
|
||||
unless(defined($ret)) {
|
||||
ERROR "Failed to create btrfs subvolume snapshot: $svol->{PRINT} -> $target_path";
|
||||
ERROR "Failed to create snapshot: $svol->{PRINT} -> $target_path", map("... $_", @stderr);
|
||||
return undef;
|
||||
}
|
||||
return $target_vol;
|
||||
|
@ -1338,45 +1341,35 @@ sub btrfs_subvolume_delete($@)
|
|||
}
|
||||
$ret = run_cmd(cmd => ['rm', '-f', @cmd_target_paths ],
|
||||
rsh => vinfo_rsh($targets->[0]),
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
filter_stderr => sub {
|
||||
# catch errors from "rm -f"
|
||||
if(/^rm: cannot remove '($file_match)':/) {
|
||||
my $catch = $1; # make sure $catch matches $vol->{PATH}
|
||||
$catch =~ s/\.info$//;
|
||||
$catch =~ s/\.split_[a-z][a-z]$//;
|
||||
$err_catch{$catch} //= [];
|
||||
push(@{$err_catch{$catch}}, $_);
|
||||
return undef; # no error messages in run_cmd
|
||||
}
|
||||
else {
|
||||
# show errors in run_cmd; force "Command execution failed" error message
|
||||
return { error => $_, fatal => 1 };
|
||||
}
|
||||
},
|
||||
);
|
||||
unless(defined($ret)) {
|
||||
foreach(@stderr) {
|
||||
next unless(/^rm: cannot remove '($file_match)':/);
|
||||
my $catch = $1; # make sure $catch matches $vol->{PATH}
|
||||
$catch =~ s/\.info$//;
|
||||
$catch =~ s/\.split_[a-z][a-z]$//;
|
||||
$err_catch{$catch} //= [];
|
||||
push(@{$err_catch{$catch}}, $_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
my @cmd_target_paths = map { { unsafe => $_->{PATH} } } @$targets;
|
||||
my $unparsed_errors;
|
||||
my @options;
|
||||
@options = ("--commit-$commit") if($commit);
|
||||
$ret = run_cmd(cmd => vinfo_cmd($targets->[0], "btrfs subvolume delete", @options, @cmd_target_paths ),
|
||||
rsh => vinfo_rsh($targets->[0]),
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
filter_stderr => sub {
|
||||
return undef unless(s/^ERROR: //); # strip ERROR prefix
|
||||
if(/'($file_match)'/ || /: ($file_match)$/ || /($file_match):/) {
|
||||
# NOTE: as of btrfs-progs-4.16, this does not catch anything
|
||||
$err_catch{$1} //= [];
|
||||
push(@{$err_catch{$1}}, $_);
|
||||
} else {
|
||||
$unparsed_errors = 1;
|
||||
}
|
||||
return undef; # no error messages in run_cmd
|
||||
},
|
||||
fatal_stderr => sub { m/^ERROR: /; }, # probably not needed, "btrfs sub delete" returns correct exit status
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
$ret = undef if($unparsed_errors);
|
||||
unless(defined($ret)) {
|
||||
foreach(@stderr) {
|
||||
next unless(/'($file_match)'/ || /: ($file_match)$/ || /($file_match):/);
|
||||
# NOTE: as of btrfs-progs-4.16, this does not catch anything
|
||||
$err_catch{$1} //= [];
|
||||
push(@{$err_catch{$1}}, $_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(defined($ret)) {
|
||||
|
@ -1388,7 +1381,7 @@ sub btrfs_subvolume_delete($@)
|
|||
foreach my $check_target (@$targets) {
|
||||
my $err_ary = $err_catch{$check_target->{PATH}};
|
||||
if($err_ary) {
|
||||
ERROR "Failed to delete subvolume \"$check_target->{PRINT}\": $_" foreach(@$err_ary);
|
||||
ERROR map("Failed to delete subvolume \"$check_target->{PRINT}\": $_", @$err_ary);
|
||||
$catch_count++;
|
||||
}
|
||||
else {
|
||||
|
@ -1398,9 +1391,9 @@ sub btrfs_subvolume_delete($@)
|
|||
@deleted = () if($catch_count != (scalar keys %err_catch));
|
||||
}
|
||||
unless(scalar(@deleted)) {
|
||||
ERROR "Failed to match error messages from delete command, assuming nothing deleted:";
|
||||
ERROR "... possibly not deleted subvolume: $_" foreach(map( { $_->{PRINT} } @$targets));
|
||||
ERROR "... consider running 'btrbk prune -n'";
|
||||
ERROR "Failed to match error messages from delete command, assuming nothing deleted", map("... $_", @stderr);
|
||||
ERROR map("Possibly not deleted subvolume: $_->{PRINT}", @$targets);
|
||||
ERROR "Consider running 'btrbk prune -n'";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1426,10 +1419,11 @@ sub btrfs_qgroup_destroy($@)
|
|||
vinfo_prefixed_keys("target", $vol));
|
||||
my $ret = run_cmd(cmd => vinfo_cmd($vol, "btrfs qgroup destroy", $qgroup_id, { unsafe => $path }),
|
||||
rsh => vinfo_rsh($vol),
|
||||
filter_stderr => \&_btrfs_filter_stderr,
|
||||
);
|
||||
end_transaction($opts{type} // "qgroup_destroy", defined($ret));
|
||||
unless(defined($ret)) {
|
||||
ERROR "Failed to destroy qgroup \"$qgroup_id\" for subvolume: $vol->{PRINT}";
|
||||
ERROR "Failed to destroy qgroup \"$qgroup_id\" for subvolume: $vol->{PRINT}", map("... $_", @stderr);
|
||||
return undef;
|
||||
}
|
||||
return $vol;
|
||||
|
@ -1472,21 +1466,14 @@ sub btrfs_send_receive($$;$$$)
|
|||
rsh => vinfo_rsh($snapshot, disable_compression => $stream_options->{stream_compress}),
|
||||
name => "btrfs send",
|
||||
stream_options => $stream_options,
|
||||
exitcode_loglevel => "error", # print error message if exitcode != 0
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
filter_stderr => [ \&_btrfs_filter_stderr, sub { $_ = undef if(/^At subvol/) } ],
|
||||
};
|
||||
|
||||
push @cmd_pipe, {
|
||||
cmd => vinfo_cmd($target, "btrfs receive", @receive_options, { unsafe => $target_path . '/' } ),
|
||||
rsh => vinfo_rsh($target, disable_compression => $stream_options->{stream_compress}),
|
||||
name => "btrfs receive",
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
filter_stderr => sub {
|
||||
# NOTE: btrfs-progs < 4.11: if "btrfs send" fails, "btrfs receive" returns 0!
|
||||
return { error => $_, fatal => 1 } if(s/^ERROR: //); # "fatal" causes run_cmd to return undef
|
||||
return { warn => $_ } if(s/^WARNING: //);
|
||||
return undef;
|
||||
},
|
||||
fatal_stderr => sub { m/^ERROR: /; }, # NOTE: btrfs-progs < 4.11: if "btrfs send" fails, "btrfs receive" returns 0!
|
||||
};
|
||||
|
||||
my $send_receive_error = 0;
|
||||
|
@ -1496,7 +1483,9 @@ sub btrfs_send_receive($$;$$$)
|
|||
vinfo_prefixed_keys("parent", $parent),
|
||||
);
|
||||
my $ret = run_cmd(@cmd_pipe);
|
||||
my @cmd_err;
|
||||
unless(defined($ret)) {
|
||||
@cmd_err = @stderr; # save for later
|
||||
$send_receive_error = 1;
|
||||
}
|
||||
|
||||
|
@ -1522,21 +1511,21 @@ sub btrfs_send_receive($$;$$$)
|
|||
unless($send_receive_error) {
|
||||
# plausibility checks on target detail
|
||||
unless($detail->{readonly}) {
|
||||
ERROR "[send/receive] target is not readonly: $vol_received->{PRINT}";
|
||||
push @cmd_err, "target is not readonly: $vol_received->{PRINT}";
|
||||
$send_receive_error = 1;
|
||||
}
|
||||
if($detail->{received_uuid} && ($detail->{received_uuid} eq '-')) {
|
||||
# NOTE: received_uuid is not in @required_keys (needs btrfs-progs >= 4.1 (BTRFS_PROGS_MIN))
|
||||
# so we only check it if it's really present
|
||||
ERROR "[send/receive] received_uuid is not set on target: $vol_received->{PRINT}";
|
||||
push @cmd_err, "received_uuid is not set on target: $vol_received->{PRINT}";
|
||||
$send_receive_error = 1;
|
||||
}
|
||||
if($parent && ($detail->{parent_uuid} eq '-')) {
|
||||
ERROR "[send/receive] parent_uuid is not set on target: $vol_received->{PRINT}";
|
||||
push @cmd_err, "parent_uuid is not set on target: $vol_received->{PRINT}";
|
||||
$send_receive_error = 1;
|
||||
}
|
||||
if((not $parent) && ($detail->{parent_uuid} ne '-')) {
|
||||
ERROR "[send/receive] parent_uuid is set on target: $vol_received->{PRINT}";
|
||||
push @cmd_err, "parent_uuid is set on target: $vol_received->{PRINT}";
|
||||
$send_receive_error = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1545,7 +1534,7 @@ sub btrfs_send_receive($$;$$$)
|
|||
$is_garbled = ((not $detail->{readonly}) && defined($detail->{received_uuid}) && ($detail->{received_uuid} eq '-'));
|
||||
}
|
||||
else {
|
||||
$err = "" if($send_receive_error); # ignore $err if send/receive failed
|
||||
push @cmd_err, "failed to check target subvolume: $vol_received->{PRINT}", @stderr;
|
||||
$send_receive_error = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1554,7 +1543,7 @@ sub btrfs_send_receive($$;$$$)
|
|||
|
||||
if($send_receive_error) {
|
||||
ERROR "Failed to send/receive subvolume: $snapshot->{PRINT} " . ($parent_path ? "[$parent_path]" : "") . " -> $vol_received->{PRINT}";
|
||||
ERROR "... $err" if($err);
|
||||
ERROR map("... $_", @cmd_err);
|
||||
}
|
||||
|
||||
if($is_garbled) {
|
||||
|
@ -1619,13 +1608,8 @@ sub btrfs_send_to_file($$$;$$)
|
|||
rsh => vinfo_rsh($source, disable_compression => $stream_options->{stream_compress}),
|
||||
name => "btrfs send",
|
||||
stream_options => $stream_options,
|
||||
exitcode_loglevel => "error", # print error message if exitcode != 0
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
filter_stderr => sub {
|
||||
return { error => $_, fatal => 1 } if(s/^ERROR: //); # "fatal" causes run_cmd to return undef
|
||||
return { warn => $_ } if(s/^WARNING: //);
|
||||
return undef;
|
||||
},
|
||||
filter_stderr => [ \&_btrfs_filter_stderr, sub { $_ = undef if(/^At subvol/) } ],
|
||||
fatal_stderr => sub { m/^ERROR: /; },
|
||||
};
|
||||
|
||||
if($compress) {
|
||||
|
@ -1702,12 +1686,18 @@ sub btrfs_send_to_file($$$;$$)
|
|||
DEBUG "Generating session key for: $vol_received->{PRINT}";
|
||||
my $kdf_backend_name = $encrypt->{kdf_backend};
|
||||
$kdf_backend_name =~ s/^.*\///;
|
||||
my $key_target_text = $encrypt->{kdf_keygen_each} ? "\"$vol_received->{PRINT}\"" : "all raw backups";
|
||||
|
||||
print STDOUT "\nGenerate session key for " . ($encrypt->{kdf_keygen_each} ? "\"$vol_received->{PRINT}\"" : "all raw backups") . ":\n";
|
||||
print STDOUT "\nGenerate session key for $key_target_text:\n";
|
||||
my $kdf_values = run_cmd(cmd => [ $encrypt->{kdf_backend}, $encrypt->{kdf_keysize} ],
|
||||
non_destructive => 1,
|
||||
name => $kdf_backend_name
|
||||
);
|
||||
unless(defined($kdf_values)) {
|
||||
ERROR "Failed to generate session key for $key_target_text", map("... $_", @stderr);
|
||||
return undef;
|
||||
}
|
||||
|
||||
return undef unless(defined($kdf_values));
|
||||
foreach(@$kdf_values) {
|
||||
chomp;
|
||||
|
@ -1803,8 +1793,13 @@ sub btrfs_send_to_file($$$;$$)
|
|||
my $ret;
|
||||
$ret = system_write_raw_info($vol_received, \%raw_info);
|
||||
|
||||
my @cmd_err;
|
||||
if(defined($ret)) {
|
||||
$ret = run_cmd(@cmd_pipe);
|
||||
@cmd_err = @stderr unless(defined($ret)); # save for later
|
||||
}
|
||||
else {
|
||||
push @cmd_err, "failed to write raw .info file: $vol_received->{PATH}.info", @stderr;
|
||||
}
|
||||
|
||||
if(defined($ret)) {
|
||||
|
@ -1813,9 +1808,10 @@ sub btrfs_send_to_file($$$;$$)
|
|||
# redirection as well as "dd" always creates the target file.
|
||||
# Note that "split" does not create empty files.
|
||||
my $test_postfix = ($split ? ".split_aa" : "");
|
||||
DEBUG "Testing target data file (non-zero size)";
|
||||
my $check_file = "${target_path}/${target_filename}${test_postfix}";
|
||||
DEBUG "Testing target data file (non-zero size): $check_file";
|
||||
$ret = run_cmd({
|
||||
cmd => ['test', '-s', { unsafe => "${target_path}/${target_filename}${test_postfix}" } ],
|
||||
cmd => ['test', '-s', { unsafe => $check_file } ],
|
||||
rsh => vinfo_rsh($target),
|
||||
name => "test",
|
||||
});
|
||||
|
@ -1824,10 +1820,14 @@ sub btrfs_send_to_file($$$;$$)
|
|||
delete $raw_info{INCOMPLETE};
|
||||
$ret = system_write_raw_info($vol_received, \%raw_info);
|
||||
}
|
||||
else {
|
||||
push @cmd_err, "failed to check target file (not present or zero length): $check_file";
|
||||
}
|
||||
}
|
||||
end_transaction("send-to-raw", defined($ret));
|
||||
unless(defined($ret)) {
|
||||
ERROR "Failed to send btrfs subvolume to raw file: $source->{PRINT} " . ($parent_path ? "[$parent_path]" : "") . " -> $vol_received->{PRINT}";
|
||||
ERROR map("... $_", @cmd_err);
|
||||
return undef;
|
||||
}
|
||||
return 1;
|
||||
|
@ -1841,8 +1841,6 @@ sub system_list_mountinfo($)
|
|||
my $ret = run_cmd(cmd => [ qw(cat), $file ],
|
||||
rsh => vinfo_rsh($vol),
|
||||
non_destructive => 1,
|
||||
exitcode_loglevel => "error", # print error message if exitcode != 0
|
||||
catch_stderr => 1, # hack for shell-based run_cmd()
|
||||
);
|
||||
return undef unless(defined($ret));
|
||||
|
||||
|
@ -5195,11 +5193,11 @@ MAIN:
|
|||
# NOTE: ssh://{src,target} uses default config
|
||||
|
||||
my $src_vol = vinfo($src_url, $config);
|
||||
unless(vinfo_init_root($src_vol)) { ERROR "Failed to fetch subvolume detail for '$src_vol->{PRINT}'" . ($err ? ": $err" : ""); exit 1; }
|
||||
unless(vinfo_init_root($src_vol)) { ERROR "Failed to fetch subvolume detail for '$src_vol->{PRINT}'", map("... $_", @stderr); exit 1; }
|
||||
if($src_vol->{node}{is_root}) { ERROR "Subvolume is btrfs root: $src_vol->{PRINT}"; exit 1; }
|
||||
|
||||
my $target_vol = vinfo($target_url, $config);
|
||||
unless(vinfo_init_root($target_vol)) { ERROR "Failed to fetch subvolume detail for '$target_vol->{PRINT}'" . ($err ? ": $err" : ""); exit 1; }
|
||||
unless(vinfo_init_root($target_vol)) { ERROR "Failed to fetch subvolume detail for '$target_vol->{PRINT}'", map("... $_", @stderr); exit 1; }
|
||||
if($target_vol->{node}{is_root}) { ERROR "Subvolume is btrfs root: $target_vol->{PRINT}"; exit 1; }
|
||||
|
||||
unless(_is_same_fs_tree($src_vol->{node}, $target_vol->{node})) {
|
||||
|
@ -5301,7 +5299,7 @@ MAIN:
|
|||
$realpath_cache{$mnt->{mount_point}} = $mnt->{mount_point}; # we know those are real paths, prevents calling readlink in btrfs_mountpoint
|
||||
my $vol = vinfo($mnt->{mount_point}, $config);
|
||||
unless(vinfo_init_root($vol)) {
|
||||
ERROR "Failed to fetch subvolume detail for: $vol->{PRINT}" . ($err ? ": $err" : "");
|
||||
ERROR "Failed to fetch subvolume detail for: $vol->{PRINT}", map("... $_", @stderr);
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
@ -5381,12 +5379,12 @@ MAIN:
|
|||
|
||||
my $src_root = vinfo($src_url, $config);
|
||||
unless(vinfo_init_root($src_root)) {
|
||||
ERROR "Failed to fetch subvolume detail for '$src_root->{PRINT}'" . ($err ? ": $err" : "");
|
||||
ERROR "Failed to fetch subvolume detail for '$src_root->{PRINT}'", map("... $_", @stderr);
|
||||
exit 1;
|
||||
}
|
||||
my $archive_root = vinfo($archive_url, $config);
|
||||
unless($archive_raw ? vinfo_init_raw_root($archive_root) : vinfo_init_root($archive_root)) {
|
||||
ERROR "Failed to fetch " . ($archive_raw ? "raw target metadata" : "subvolume detail") . " for '$archive_root->{PRINT}'" . ($err ? ": $err" : "");
|
||||
ERROR "Failed to fetch " . ($archive_raw ? "raw target metadata" : "subvolume detail") . " for '$archive_root->{PRINT}'", map("... $_", @stderr);
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
@ -5421,18 +5419,18 @@ MAIN:
|
|||
my $sroot = vinfo($sroot_url, $config_sroot);
|
||||
vinfo_assign_config($sroot);
|
||||
unless(vinfo_init_root($sroot)) {
|
||||
ABORTED($sroot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping archive source \"$sroot->{PRINT}\": " . ABORTED_TEXT($sroot);
|
||||
ABORTED($sroot, "Failed to fetch subvolume detail");
|
||||
WARN "Skipping archive source \"$sroot->{PRINT}\": " . ABORTED_TEXT($sroot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
|
||||
my $droot = vinfo($droot_url, $config_droot);
|
||||
vinfo_assign_config($droot);
|
||||
unless($archive_raw ? vinfo_init_raw_root($droot) : vinfo_init_root($droot)) {
|
||||
DEBUG "Failed to fetch " . ($archive_raw ? "raw target metadata" : "subvolume detail") . " for '$droot->{PRINT}'" . ($err ? ": $err" : "");
|
||||
DEBUG "Failed to fetch " . ($archive_raw ? "raw target metadata" : "subvolume detail") . " for '$droot->{PRINT}'";
|
||||
unless(system_mkdir($droot)) {
|
||||
ABORTED($droot, "Failed to create directory: $droot->{PRINT}/");
|
||||
WARN "Skipping archive target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot);
|
||||
WARN "Skipping archive target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
$droot->{SUBDIR_CREATED} = 1;
|
||||
|
@ -5445,8 +5443,8 @@ MAIN:
|
|||
else {
|
||||
# after directory is created, try to init again
|
||||
unless($archive_raw ? vinfo_init_raw_root($droot) : vinfo_init_root($droot)) {
|
||||
ABORTED($droot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping archive target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot);
|
||||
ABORTED($droot, "Failed to fetch subvolume detail");
|
||||
WARN "Skipping archive target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
@ -5616,8 +5614,8 @@ MAIN:
|
|||
next unless(grep defined($_->{GLOB_CONTEXT}), @{$config_vol->{SUBSECTION}});
|
||||
my $sroot = vinfo($config_vol->{url}, $config_vol);
|
||||
unless(vinfo_init_root($sroot)) {
|
||||
ABORTED($sroot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping volume \"$sroot->{PRINT}\": " . ABORTED_TEXT($sroot);
|
||||
ABORTED($sroot, "Failed to fetch subvolume detail");
|
||||
WARN "Skipping volume \"$sroot->{PRINT}\": " . ABORTED_TEXT($sroot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
|
||||
|
@ -5953,15 +5951,15 @@ MAIN:
|
|||
foreach my $sroot (vinfo_subsection($config, 'volume')) {
|
||||
DEBUG "Initializing volume section: $sroot->{PRINT}";
|
||||
unless(vinfo_init_root($sroot)) {
|
||||
ABORTED($sroot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping volume \"$sroot->{PRINT}\": " . ABORTED_TEXT($sroot);
|
||||
ABORTED($sroot, "Failed to fetch subvolume detail");
|
||||
WARN "Skipping volume \"$sroot->{PRINT}\": " . ABORTED_TEXT($sroot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
foreach my $svol (vinfo_subsection($sroot, 'subvolume')) {
|
||||
DEBUG "Initializing subvolume section: $svol->{PRINT}";
|
||||
unless(vinfo_init_root($svol)) {
|
||||
ABORTED($svol, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping subvolume \"$svol->{PRINT}\": " . ABORTED_TEXT($svol);
|
||||
ABORTED($svol, "Failed to fetch subvolume detail");
|
||||
WARN "Skipping subvolume \"$svol->{PRINT}\": " . ABORTED_TEXT($svol), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
if((not $svol->{node}{uuid}) || ($svol->{node}{uuid} eq '-')) {
|
||||
|
@ -5991,8 +5989,8 @@ MAIN:
|
|||
|
||||
my $snaproot = vinfo_snapshot_root($svol);
|
||||
unless(vinfo_init_root($snaproot)) {
|
||||
ABORTED($svol, "Failed to fetch subvolume detail for snapshot_dir" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping subvolume \"$svol->{PRINT}\": " . ABORTED_TEXT($svol);
|
||||
ABORTED($svol, "Failed to fetch subvolume detail for snapshot_dir");
|
||||
WARN "Skipping subvolume \"$svol->{PRINT}\": " . ABORTED_TEXT($svol), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
unless(_is_same_fs_tree($snaproot->{node}, $svol->{node})) {
|
||||
|
@ -6018,16 +6016,16 @@ MAIN:
|
|||
if($target_type eq "send-receive")
|
||||
{
|
||||
unless(vinfo_init_root($droot)) {
|
||||
ABORTED($droot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot);
|
||||
ABORTED($droot, "Failed to fetch subvolume detail");
|
||||
WARN "Skipping target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
}
|
||||
elsif($target_type eq "raw")
|
||||
{
|
||||
unless(vinfo_init_raw_root($droot)) {
|
||||
ABORTED($droot, "Failed to fetch raw target metadata" . ($err ? ": $err" : ""));
|
||||
WARN "Skipping target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot);
|
||||
ABORTED($droot, "Failed to fetch raw target metadata");
|
||||
WARN "Skipping target \"$droot->{PRINT}\": " . ABORTED_TEXT($droot), map("... $_", @stderr);
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
@ -6077,7 +6075,7 @@ MAIN:
|
|||
my $url = $subvol_args[0] || die;
|
||||
my $vol = vinfo($url, $config);
|
||||
unless(vinfo_init_root($vol)) {
|
||||
ERROR "Failed to fetch subvolume detail for: $url" . ($err ? ": $err" : "");
|
||||
ERROR "Failed to fetch subvolume detail for: $url", map("... $_", @stderr);
|
||||
exit 1;
|
||||
}
|
||||
if($vol->{node}{is_root}) {
|
||||
|
|
Loading…
Reference in New Issue