432 lines
17 KiB
Bash
432 lines
17 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
PATH=/usr/sbin:/usr/bin:/sbin:/bin
|
|
export PATH
|
|
LC_ALL=C
|
|
export LC_ALL
|
|
umask 077
|
|
set -Eeuo pipefail
|
|
|
|
_k3slrf_initial_guard() {
|
|
local candidate_euid="${1-}" shell_flags="${2-}"
|
|
[[ "$candidate_euid" =~ ^[0-9]+$ ]] || return 1
|
|
(( candidate_euid != 0 )) || return 1
|
|
[[ "$shell_flags" != *x* ]]
|
|
}
|
|
|
|
if ! _k3slrf_initial_guard "$EUID" "$-"; then
|
|
printf 'Local recovery feasibility refused\n' >&2
|
|
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then return 1; else exit 1; fi
|
|
fi
|
|
|
|
readonly K3SLRF_KEEPASSXC='/usr/bin/keepassxc-cli'
|
|
readonly K3SLRF_CRYPTSETUP='/usr/sbin/cryptsetup'
|
|
readonly K3SLRF_KEEPASS_PACKAGE='keepassxc'
|
|
readonly K3SLRF_KEEPASS_VERSION='2.7.6+dfsg.1-1build3'
|
|
readonly K3SLRF_CRYPTSETUP_PACKAGE='cryptsetup-bin'
|
|
readonly K3SLRF_CRYPTSETUP_VERSION='2:2.7.0-1ubuntu4.2'
|
|
readonly K3SLRF_SCRIPT_DIR="$(cd -P -- "${BASH_SOURCE[0]%/*}" && pwd -P)"
|
|
readonly K3SLRF_REPOSITORY_ROOT="$(cd -P -- "${K3SLRF_SCRIPT_DIR}/../.." && pwd -P)"
|
|
readonly K3SLRF_LIBRARY_PATH="${K3SLRF_REPOSITORY_ROOT}/scripts/lib/k3s-local-recovery.sh"
|
|
# shellcheck source=../lib/k3s-local-recovery.sh
|
|
builtin source -- "$K3SLRF_LIBRARY_PATH" || {
|
|
printf 'Local recovery feasibility refused\n' >&2
|
|
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then return 1; else exit 1; fi
|
|
}
|
|
|
|
_k3slrf_usage() {
|
|
printf 'Usage: bash scripts/validate/k3s-local-recovery-feasibility.sh [--execute]\n'
|
|
}
|
|
|
|
_k3slrf_fail() {
|
|
printf 'Local recovery feasibility failed\n' >&2
|
|
return 1
|
|
}
|
|
|
|
_k3slrf_require_interactive_stdin() {
|
|
[[ -t 0 ]]
|
|
}
|
|
|
|
_k3slrf_require_cached_sudo() {
|
|
_k3slr_cached_sudo_is_available
|
|
}
|
|
|
|
_k3slrf_package_version_is_exact() {
|
|
local package="$1" expected="$2" output
|
|
output="$(
|
|
_k3slr_command /usr/bin/dpkg-query --show --showformat='${db:Status-Abbrev}|${Version}\n' -- "$package" 2>/dev/null
|
|
printf '\034%s' "$?"
|
|
)" || return 1
|
|
[[ "$output" == "ii |${expected}"$'\n'$'\0340' ]]
|
|
}
|
|
|
|
_k3slrf_verify_prerequisites() {
|
|
_k3slr_trusted_root_executable /usr/bin/dpkg-query || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/mktemp || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/rm || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/cmp || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/mawk || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/od || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/ps || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/sleep || return 1
|
|
_k3slr_trusted_root_executable /usr/bin/sha256sum || return 1
|
|
_k3slr_trusted_root_executable "$K3SLRF_KEEPASSXC" || return 1
|
|
_k3slr_trusted_root_executable "$K3SLRF_CRYPTSETUP" || return 1
|
|
_k3slrf_package_version_is_exact "$K3SLRF_KEEPASS_PACKAGE" "$K3SLRF_KEEPASS_VERSION" || return 1
|
|
_k3slrf_package_version_is_exact "$K3SLRF_CRYPTSETUP_PACKAGE" "$K3SLRF_CRYPTSETUP_VERSION"
|
|
}
|
|
|
|
_k3slrf_create_fixture_dir() {
|
|
local destination_name="$1" identity_name="$2" owned_name="$3" created physical metadata uid
|
|
created="$(_k3slr_command /usr/bin/mktemp -d /tmp/k3slr-feasibility.XXXXXX)" || return 1
|
|
printf -v "$destination_name" '%s' "$created"
|
|
printf -v "$owned_name" '%s' true
|
|
[[ "$created" =~ ^/tmp/k3slr-feasibility\.[A-Za-z0-9]+$ ]] || return 1
|
|
_k3slr_command /usr/bin/test -d "$created" || return 1
|
|
_k3slr_command /usr/bin/test ! -L "$created" || return 1
|
|
physical="$(cd -P -- "$created" && pwd -P)" || return 1
|
|
[[ "$physical" == "$created" ]] || return 1
|
|
_k3slr_capture_one_line uid /usr/bin/id -u || return 1
|
|
_k3slr_capture_one_line metadata /usr/bin/stat --format='%u|%a|%F|%d:%i' -- "$created" || return 1
|
|
[[ "$metadata" == "${uid}|700|directory|"* ]] || return 1
|
|
printf -v "$identity_name" '%s' "${metadata##*|}"
|
|
}
|
|
|
|
_k3slrf_cleanup_fixture_dir() {
|
|
local fixture_dir="$1" expected_identity="$2" metadata uid
|
|
[[ "$fixture_dir" =~ ^/tmp/k3slr-feasibility\.[A-Za-z0-9]+$ ]] || return 1
|
|
_k3slr_command /usr/bin/test -d "$fixture_dir" || return 1
|
|
_k3slr_command /usr/bin/test ! -L "$fixture_dir" || return 1
|
|
_k3slr_capture_one_line uid /usr/bin/id -u || return 1
|
|
_k3slr_capture_one_line metadata /usr/bin/stat --format='%u|%a|%F|%d:%i' -- "$fixture_dir" 2>/dev/null || return 1
|
|
[[ "$metadata" == "${uid}|700|directory|"* ]] || return 1
|
|
[[ -z "$expected_identity" || "${metadata##*|}" == "$expected_identity" ]] || return 1
|
|
_k3slr_command /usr/bin/rm --recursive --one-file-system -- "$fixture_dir"
|
|
}
|
|
|
|
_k3slrf_synthetic_master_once_stdout() {
|
|
printf '%s' 'k3slr-package-feasibility-master-v1' |
|
|
_k3slr_command /usr/bin/sha256sum |
|
|
_k3slr_command /usr/bin/mawk '{ print $1 }'
|
|
}
|
|
|
|
_k3slrf_synthetic_master_twice_stdout() {
|
|
_k3slrf_synthetic_master_once_stdout
|
|
_k3slrf_synthetic_master_once_stdout
|
|
}
|
|
|
|
_k3slrf_validate_generated_password_stdin() {
|
|
_k3slr_command /usr/bin/od -An -v -tx1 |
|
|
_k3slr_command /usr/bin/mawk '
|
|
{
|
|
for (i=1; i<=NF; i++) {
|
|
n++; byte=$i
|
|
if (n == 41) { if (byte != "0a") bad=1 }
|
|
else if (byte ~ /^3[0-9]$/) digit=1
|
|
else if (byte ~ /^(4[1-9a-f]|5[0-9a])$/) upper=1
|
|
else if (byte ~ /^(6[1-9a-f]|7[0-9a])$/) lower=1
|
|
else bad=1
|
|
}
|
|
}
|
|
END { exit !(n == 41 && !bad && lower && upper && digit) }
|
|
'
|
|
}
|
|
|
|
_k3slrf_file_identity() {
|
|
local destination_name="$1" path="$2" metadata uid
|
|
_k3slr_command /usr/bin/test -f "$path" || return 1
|
|
_k3slr_command /usr/bin/test ! -L "$path" || return 1
|
|
_k3slr_capture_one_line uid /usr/bin/id -u || return 1
|
|
_k3slr_capture_one_line metadata /usr/bin/stat --format='%u|%a|%F|%d:%i' -- "$path" || return 1
|
|
[[ "$metadata" == "${uid}|600|regular file|"* ||
|
|
"$metadata" == "${uid}|600|regular empty file|"* ]] || return 1
|
|
printf -v "$destination_name" '%s' "${metadata##*|}"
|
|
}
|
|
|
|
_k3slrf_file_identity_matches() {
|
|
local current=''
|
|
_k3slrf_file_identity current "$1" || return 1
|
|
[[ "$current" == "$2" ]]
|
|
}
|
|
|
|
_k3slrf_directory_identity() {
|
|
local destination_name="$1" path="$2" physical metadata uid
|
|
[[ "$path" =~ ^/tmp/k3slr-feasibility\.[A-Za-z0-9]+$ ]] || return 1
|
|
_k3slr_command /usr/bin/test -d "$path" || return 1
|
|
_k3slr_command /usr/bin/test ! -L "$path" || return 1
|
|
physical="$(cd -P -- "$path" && pwd -P)" || return 1
|
|
[[ "$physical" == "$path" ]] || return 1
|
|
_k3slr_capture_one_line uid /usr/bin/id -u || return 1
|
|
_k3slr_capture_one_line metadata /usr/bin/stat --format='%u|%a|%F|%d:%i' -- "$path" || return 1
|
|
[[ "$metadata" == "${uid}|700|directory|"* ]] || return 1
|
|
printf -v "$destination_name" '%s' "${metadata##*|}"
|
|
}
|
|
|
|
_k3slrf_directory_identity_matches() {
|
|
local current=''
|
|
_k3slrf_directory_identity current "$1" || return 1
|
|
[[ "$current" == "$2" ]]
|
|
}
|
|
|
|
_k3slrf_run_tracked() {
|
|
local rc caller_group='' current_identity='' stopped_identity=''
|
|
_k3slr_process_group_for_pid caller_group "$BASHPID" || return 1
|
|
K3SLRF_ACTIVE_CHILD_STATE='launching'
|
|
K3SLRF_LAST_CLEANUP_OK=false
|
|
_k3slr_lifecycle_boundary feasibility-launch-before
|
|
_k3slrf_pending_checkpoint || return $?
|
|
set -m
|
|
(
|
|
tracked_cancel=''
|
|
trap '[[ "$tracked_cancel" == TERM ]] || tracked_cancel=INT' INT
|
|
trap 'tracked_cancel=TERM' TERM
|
|
kill -STOP "$BASHPID"
|
|
tracked_worker_rc=143
|
|
if [[ -z "$tracked_cancel" ]]; then
|
|
if "$@"; then tracked_worker_rc=0; else tracked_worker_rc=$?; fi
|
|
fi
|
|
while [[ -n "$tracked_cancel" ]]; do
|
|
_k3slr_command /usr/bin/sleep 0.01 || :
|
|
done
|
|
exit "$tracked_worker_rc"
|
|
) &
|
|
K3SLRF_ACTIVE_CHILD_PID=$!
|
|
K3SLRF_ACTIVE_CHILD_STATE='published'
|
|
_k3slr_lifecycle_boundary feasibility-pid-published "$K3SLRF_ACTIVE_CHILD_PID"
|
|
if ! _k3slr_process_identity K3SLRF_ACTIVE_CHILD_IDENTITY "$K3SLRF_ACTIVE_CHILD_PID"; then
|
|
set +m
|
|
_k3slrf_cleanup_active_child || return 1
|
|
if [[ -n "$K3SLRF_PENDING_SIGNAL" ]]; then return "$K3SLRF_PENDING_STATUS"; fi
|
|
return 1
|
|
fi
|
|
if ! _k3slr_wait_for_stopped_group K3SLRF_ACTIVE_CHILD_PGID stopped_identity "$K3SLRF_ACTIVE_CHILD_PID" ||
|
|
[[ "$stopped_identity" != "$K3SLRF_ACTIVE_CHILD_IDENTITY" ]]; then
|
|
set +m
|
|
_k3slrf_cleanup_active_child || return 1
|
|
if [[ -n "$K3SLRF_PENDING_SIGNAL" ]]; then return "$K3SLRF_PENDING_STATUS"; fi
|
|
return 1
|
|
fi
|
|
K3SLRF_ACTIVE_CHILD_STATE='stopped_pinned'
|
|
_k3slr_lifecycle_boundary feasibility-stop-query-complete
|
|
_k3slrf_pending_checkpoint || { rc=$?; set +m; return "$rc"; }
|
|
if [[ "$K3SLRF_ACTIVE_CHILD_PGID" == "$caller_group" ]]; then
|
|
set +m
|
|
_k3slrf_cleanup_active_child || return 1
|
|
return 1
|
|
fi
|
|
set +m
|
|
_k3slr_lifecycle_boundary feasibility-cont-before
|
|
_k3slrf_pending_checkpoint || return $?
|
|
_k3slr_continue_owned_child "$K3SLRF_ACTIVE_CHILD_PID" "$K3SLRF_ACTIVE_CHILD_PGID" \
|
|
"$K3SLRF_ACTIVE_CHILD_IDENTITY" || return 1
|
|
K3SLRF_ACTIVE_CHILD_STATE='continued'
|
|
_k3slr_lifecycle_boundary feasibility-cont-after
|
|
_k3slrf_pending_checkpoint || return $?
|
|
K3SLRF_ACTIVE_CHILD_STATE='waiting'
|
|
if _k3slr_wait_child "$K3SLRF_ACTIVE_CHILD_PID"; then rc=0; else rc=$?; fi
|
|
_k3slr_lifecycle_boundary feasibility-wait-reaped-before-clear
|
|
if _k3slr_process_identity current_identity "$K3SLRF_ACTIVE_CHILD_PID" 2>/dev/null &&
|
|
[[ "$current_identity" == "$K3SLRF_ACTIVE_CHILD_IDENTITY" ]]; then
|
|
_k3slrf_cleanup_active_child || return 1
|
|
fi
|
|
K3SLRF_ACTIVE_CHILD_STATE='reaped' K3SLRF_ACTIVE_CHILD_PID='' \
|
|
K3SLRF_ACTIVE_CHILD_PGID='' K3SLRF_ACTIVE_CHILD_IDENTITY=''
|
|
K3SLRF_LAST_CLEANUP_OK=true
|
|
_k3slr_lifecycle_boundary feasibility-state-cleared
|
|
if [[ -n "$K3SLRF_PENDING_SIGNAL" ]]; then
|
|
rc="$K3SLRF_PENDING_STATUS"
|
|
fi
|
|
return "$rc"
|
|
}
|
|
|
|
_k3slrf_db_create() {
|
|
_k3slrf_synthetic_master_twice_stdout |
|
|
_k3slr_command "$K3SLRF_KEEPASSXC" db-create --quiet --set-password "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
_k3slrf_entry_add() {
|
|
_k3slrf_synthetic_master_once_stdout |
|
|
_k3slr_command "$K3SLRF_KEEPASSXC" add --quiet --generate --length 40 \
|
|
--lower --upper --numeric --every-group "$1" "$K3SLR_KEEPASS_ENTRY" >/dev/null 2>&1
|
|
}
|
|
|
|
_k3slrf_password_check() {
|
|
_k3slrf_synthetic_master_once_stdout |
|
|
_k3slr_command "$K3SLRF_KEEPASSXC" show --show-protected \
|
|
--attributes Password "$1" "$K3SLR_KEEPASS_ENTRY" 2>/dev/null |
|
|
_k3slrf_validate_generated_password_stdin
|
|
}
|
|
|
|
_k3slrf_attachment_listing_stdout() {
|
|
(( $# == 1 )) || return 1
|
|
_k3slrf_synthetic_master_once_stdout |
|
|
_k3slr_command "$K3SLRF_KEEPASSXC" show --quiet --attributes Title \
|
|
--show-attachments "$1" "$K3SLR_KEEPASS_ENTRY"
|
|
}
|
|
|
|
_k3slrf_attachment_state_is() {
|
|
local database="${1-}" fixture_dir="${2-}" expected_state="${3-}"
|
|
local capture_base='' record='' state=''
|
|
(( $# == 3 )) || return 1
|
|
[[ "$expected_state" == absent || "$expected_state" == present ]] || return 1
|
|
capture_base="${fixture_dir}/keepass-listing.${BASHPID}"
|
|
_k3slr_capture_keepass_attachment_listing record \
|
|
"${capture_base}.stdout" "${capture_base}.stderr" \
|
|
_k3slrf_attachment_listing_stdout "$database" || return 1
|
|
_k3slr_parse_keepass_attachment_listing "$record" fixture.bin state || return 1
|
|
[[ "$state" == "$expected_state" ]]
|
|
}
|
|
|
|
_k3slrf_attachment_import() {
|
|
_k3slrf_synthetic_master_once_stdout |
|
|
_k3slr_command "$K3SLRF_KEEPASSXC" attachment-import --quiet "$1" "$K3SLR_KEEPASS_ENTRY" \
|
|
fixture.bin "$2" >/dev/null 2>&1
|
|
}
|
|
|
|
_k3slrf_attachment_export() {
|
|
_k3slrf_synthetic_master_once_stdout |
|
|
_k3slr_command "$K3SLRF_KEEPASSXC" attachment-export --quiet "$1" "$K3SLR_KEEPASS_ENTRY" \
|
|
fixture.bin "$2" >/dev/null 2>&1
|
|
}
|
|
|
|
_k3slrf_run_synthetic() {
|
|
local fixture_dir="$1" database input_file output_file database_identity input_identity output_identity fixture_identity export_fd
|
|
database="${fixture_dir}/synthetic.kdbx"
|
|
input_file="${fixture_dir}/input.bin"
|
|
output_file="${fixture_dir}/output.bin"
|
|
[[ ! -e "$database" && ! -L "$database" && ! -e "$input_file" && ! -L "$input_file" &&
|
|
! -e "$output_file" && ! -L "$output_file" ]] || return 1
|
|
_k3slrf_directory_identity fixture_identity "$fixture_dir" || return 1
|
|
( set -o noclobber; printf '%s\n' 'k3slr-attachment-roundtrip-v1' >"$input_file" ) || return 1
|
|
_k3slrf_file_identity input_identity "$input_file" || return 1
|
|
_k3slrf_run_tracked _k3slrf_db_create "$database" || return 1
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity database_identity "$database" || return 1
|
|
_k3slrf_run_tracked _k3slrf_entry_add "$database" || return 1
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity database_identity "$database" || return 1
|
|
_k3slrf_run_tracked _k3slrf_password_check "$database" || return 1
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity_matches "$database" "$database_identity" || return 1
|
|
_k3slrf_file_identity_matches "$input_file" "$input_identity" || return 1
|
|
_k3slrf_run_tracked _k3slrf_attachment_state_is "$database" "$fixture_dir" absent || return 1
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity_matches "$database" "$database_identity" || return 1
|
|
_k3slrf_file_identity_matches "$input_file" "$input_identity" || return 1
|
|
_k3slrf_run_tracked _k3slrf_attachment_import "$database" "$input_file" || return 1
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity database_identity "$database" || return 1
|
|
_k3slrf_run_tracked _k3slrf_attachment_state_is "$database" "$fixture_dir" present || return 1
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity_matches "$database" "$database_identity" || return 1
|
|
set -o noclobber
|
|
if ! exec {export_fd}>"$output_file"; then
|
|
set +o noclobber
|
|
return 1
|
|
fi
|
|
set +o noclobber
|
|
_k3slrf_file_identity output_identity "$output_file" || return 1
|
|
_k3slrf_run_tracked _k3slrf_attachment_export "$database" "/proc/${BASHPID}/fd/${export_fd}" || return 1
|
|
exec {export_fd}>&-
|
|
_k3slrf_directory_identity_matches "$fixture_dir" "$fixture_identity" || return 1
|
|
_k3slrf_file_identity_matches "$database" "$database_identity" || return 1
|
|
_k3slrf_file_identity_matches "$output_file" "$output_identity" || return 1
|
|
_k3slr_command /usr/bin/cmp --silent -- "$input_file" "$output_file"
|
|
}
|
|
|
|
k3slr_local_recovery_feasibility_main() (
|
|
local execute=false fixture_dir='' fixture_identity='' fixture_owned=false
|
|
local K3SLRF_ACTIVE_CHILD_PID='' K3SLRF_ACTIVE_CHILD_PGID='' K3SLRF_ACTIVE_CHILD_IDENTITY=''
|
|
local K3SLRF_ACTIVE_CHILD_STATE='empty' K3SLRF_PENDING_SIGNAL='' K3SLRF_PENDING_STATUS=''
|
|
local K3SLRF_LAST_CLEANUP_OK=false
|
|
case "$#" in
|
|
0) ;;
|
|
1) [[ "$1" == --execute ]] || { _k3slrf_usage >&2; return 2; }; execute=true ;;
|
|
*) _k3slrf_usage >&2; return 2 ;;
|
|
esac
|
|
|
|
if "$execute"; then
|
|
_k3slrf_require_interactive_stdin || { _k3slrf_fail; return 1; }
|
|
fi
|
|
_k3slrf_verify_prerequisites || { _k3slrf_fail; return 1; }
|
|
if ! "$execute"; then
|
|
printf 'Local recovery feasibility prerequisites: pass\n'
|
|
return 0
|
|
fi
|
|
_k3slrf_require_cached_sudo || { _k3slrf_fail; return 1; }
|
|
|
|
_k3slrf_cleanup_active_child() {
|
|
local cleanup_rc=0
|
|
if [[ -n "$K3SLRF_ACTIVE_CHILD_PID" ]]; then
|
|
if [[ "$K3SLRF_ACTIVE_CHILD_STATE" == published ]]; then
|
|
_k3slr_terminate_published_child "$K3SLRF_ACTIVE_CHILD_PID" || cleanup_rc=$?
|
|
elif [[ -n "$K3SLRF_ACTIVE_CHILD_IDENTITY" ]]; then
|
|
_k3slr_terminate_and_reap "$K3SLRF_ACTIVE_CHILD_PID" "$K3SLRF_ACTIVE_CHILD_PGID" \
|
|
"$K3SLRF_ACTIVE_CHILD_IDENTITY" || cleanup_rc=$?
|
|
else
|
|
cleanup_rc=1
|
|
fi
|
|
if (( cleanup_rc == 0 )); then
|
|
K3SLRF_ACTIVE_CHILD_PID=''
|
|
K3SLRF_ACTIVE_CHILD_PGID=''
|
|
K3SLRF_ACTIVE_CHILD_IDENTITY=''
|
|
K3SLRF_ACTIVE_CHILD_STATE='reaped'
|
|
K3SLRF_LAST_CLEANUP_OK=true
|
|
fi
|
|
fi
|
|
return "$cleanup_rc"
|
|
}
|
|
_k3slrf_signal() {
|
|
if [[ "$1" == TERM || "$K3SLRF_PENDING_SIGNAL" != TERM ]]; then
|
|
K3SLRF_PENDING_SIGNAL="$1"
|
|
K3SLRF_PENDING_STATUS="$2"
|
|
fi
|
|
}
|
|
_k3slrf_pending_checkpoint() {
|
|
local signal_status cleanup_rc=0
|
|
[[ -n "$K3SLRF_PENDING_SIGNAL" ]] || return 0
|
|
signal_status="$K3SLRF_PENDING_STATUS"
|
|
if [[ -n "$K3SLRF_ACTIVE_CHILD_PID" ]]; then
|
|
[[ -n "$K3SLRF_ACTIVE_CHILD_IDENTITY" ]] || return 1
|
|
_k3slrf_cleanup_active_child || cleanup_rc=$?
|
|
else
|
|
K3SLRF_LAST_CLEANUP_OK=true
|
|
fi
|
|
(( cleanup_rc == 0 )) || return 1
|
|
return "$signal_status"
|
|
}
|
|
_k3slrf_exit_cleanup() {
|
|
local original_status="$1" cleanup_rc=0
|
|
trap - EXIT
|
|
_k3slrf_cleanup_active_child || cleanup_rc=$?
|
|
if "$fixture_owned"; then
|
|
_k3slrf_cleanup_fixture_dir "$fixture_dir" "$fixture_identity" >/dev/null 2>&1 || cleanup_rc=1
|
|
fi
|
|
(( cleanup_rc == 0 )) || exit 1
|
|
exit "$original_status"
|
|
}
|
|
trap '_k3slrf_exit_cleanup "$?"' EXIT
|
|
trap '_k3slrf_signal INT 130' INT
|
|
trap '_k3slrf_signal TERM 143' TERM
|
|
_k3slrf_create_fixture_dir fixture_dir fixture_identity fixture_owned || { _k3slrf_fail; return 1; }
|
|
if ! _k3slrf_run_synthetic "$fixture_dir"; then
|
|
if [[ -n "$K3SLRF_PENDING_STATUS" && -z "$K3SLRF_ACTIVE_CHILD_PID" &&
|
|
"$K3SLRF_LAST_CLEANUP_OK" == true ]]; then
|
|
_k3slrf_cleanup_fixture_dir "$fixture_dir" "$fixture_identity" || return 1
|
|
fixture_owned=false
|
|
trap - EXIT INT TERM
|
|
return "$K3SLRF_PENDING_STATUS"
|
|
fi
|
|
_k3slrf_fail
|
|
return 1
|
|
fi
|
|
_k3slrf_cleanup_fixture_dir "$fixture_dir" "$fixture_identity" || { _k3slrf_fail; return 1; }
|
|
fixture_owned=false
|
|
trap - EXIT INT TERM
|
|
printf 'Local recovery feasibility: pass\n'
|
|
)
|
|
|
|
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
k3slr_local_recovery_feasibility_main "$@"
|
|
fi
|