1143 lines
54 KiB
Bash
1143 lines
54 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Source-only strict A1 recovery payload verifier.
|
|
|
|
readonly K3SLRA1_MANIFEST_MAX_BYTES=65536
|
|
readonly K3SLRA1_PATH_MAX_BYTES=512
|
|
readonly K3SLRA1_MOUNT_RECORD_MAX_BYTES=4096
|
|
readonly K3SLRA1_TARGET_COUNT=80
|
|
readonly K3SLRA1_TARGET_BYTES=22857829
|
|
readonly K3SLRA1_METADATA_FORMAT='%d:%i|%h|%s|%y|%F|%u:%g|%a'
|
|
readonly K3SLRA1_CANONICAL_DATABASE='./datastore/state.db'
|
|
readonly K3SLRA1_LEGACY_DATABASE='./rootfs/var/lib/rancher/k3s/server/db/state.db'
|
|
readonly K3SLRA1_MAIN_MAPPER='/dev/mapper/k3s-recovery'
|
|
readonly K3SLRA1_PROOF_MAPPER='/dev/mapper/k3s-recovery-proof'
|
|
readonly K3SLRA1_MAIN_MAPPING_NAME=k3s-recovery
|
|
readonly K3SLRA1_PROOF_MAPPING_NAME=k3s-recovery-proof
|
|
readonly K3SLRA1_SQLITE_QUERY='PRAGMA query_only=ON; PRAGMA quick_check;'
|
|
|
|
_k3slra1_command() {
|
|
"$@"
|
|
}
|
|
|
|
_k3slra1_output_name_is_safe() {
|
|
local output_name="${1-}"
|
|
(( $# == 1 )) || return 1
|
|
[[ "$output_name" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || return 1
|
|
[[ "$output_name" != _k3slra1_* ]]
|
|
}
|
|
|
|
_k3slra1_metadata() {
|
|
local path="${1-}" output_name="${2-}" line=''
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != path ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != line ]] || return 1
|
|
_k3slra1_packet_line metadata "$path" line || return 1
|
|
printf -v "$output_name" '%s' "$line"
|
|
}
|
|
|
|
_k3slra1_canonical_path() {
|
|
local path="${1-}" output_name="${2-}" line=''
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != path ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != line ]] || return 1
|
|
_k3slra1_packet_line readlink "$path" line || return 1
|
|
printf -v "$output_name" '%s' "$line"
|
|
}
|
|
|
|
_k3slra1_metadata_packet() {
|
|
local path="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/stat --format="$K3SLRA1_METADATA_FORMAT" -- "$path" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_fd_metadata_packet() {
|
|
local path="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/stat --dereference --format="$K3SLRA1_METADATA_FORMAT" -- "$path" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_mapper_stat_packet() {
|
|
local mapper="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/stat --format='%F|%Hr:%Lr' -- "$mapper" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_size_stat_packet() {
|
|
local path="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/stat --format='%s' -- "$path" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_wc_packet() {
|
|
local path="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/wc -c -- "$path" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_od_packet() {
|
|
local path="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/od -An -v -tx1 -- "$path" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_sha256_packet() {
|
|
local path="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/sha256sum -- "$path" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_findmnt_packet() {
|
|
local mount_root="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/findmnt --noheadings --raw --mountpoint "$mount_root" --output SOURCE,TARGET,FSTYPE,VFS-OPTIONS,FS-OPTIONS,MAJ:MIN 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_readlink_packet() {
|
|
local mapper="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/readlink --canonicalize-existing -- "$mapper" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_lsblk_packet() {
|
|
local mapper="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/lsblk --noheadings --nodeps --raw --output MAJ:MIN -- "$mapper" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_blockdev_packet() {
|
|
local mapper="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/sbin/blockdev --getro "$mapper" 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf '\0RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_stderr_marker() {
|
|
local chunk='' read_rc=0
|
|
if IFS= read -r -d '' -n 1 chunk; then
|
|
read_rc=0
|
|
else
|
|
read_rc=$?
|
|
fi
|
|
if (( read_rc == 0 )); then
|
|
printf '\0STDERR\0'
|
|
while IFS= read -r -d '' -n 4096 chunk; do
|
|
:
|
|
done
|
|
else
|
|
if [[ -n "$chunk" ]]; then
|
|
printf '\0STDERR\0'
|
|
fi
|
|
fi
|
|
}
|
|
|
|
_k3slra1_packet_value() {
|
|
local producer="${1-}" argument="${2-}" output_name="${3-}"
|
|
local -a records=()
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != producer ]] || return 1
|
|
[[ "$output_name" != argument ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != records ]] || return 1
|
|
case "$producer" in
|
|
findmnt) mapfile -d '' -t records < <(_k3slra1_findmnt_packet "$argument") ;;
|
|
metadata) mapfile -d '' -t records < <(_k3slra1_metadata_packet "$argument") ;;
|
|
fd-metadata) mapfile -d '' -t records < <(_k3slra1_fd_metadata_packet "$argument") ;;
|
|
mapper-stat) mapfile -d '' -t records < <(_k3slra1_mapper_stat_packet "$argument") ;;
|
|
size-stat) mapfile -d '' -t records < <(_k3slra1_size_stat_packet "$argument") ;;
|
|
wc) mapfile -d '' -t records < <(_k3slra1_wc_packet "$argument") ;;
|
|
od) mapfile -d '' -t records < <(_k3slra1_od_packet "$argument") ;;
|
|
sha256) mapfile -d '' -t records < <(_k3slra1_sha256_packet "$argument") ;;
|
|
readlink) mapfile -d '' -t records < <(_k3slra1_readlink_packet "$argument") ;;
|
|
lsblk) mapfile -d '' -t records < <(_k3slra1_lsblk_packet "$argument") ;;
|
|
blockdev) mapfile -d '' -t records < <(_k3slra1_blockdev_packet "$argument") ;;
|
|
*) return 1 ;;
|
|
esac
|
|
(( ${#records[@]} == 2 )) || return 1
|
|
[[ "${records[1]}" == RC=0 ]] || return 1
|
|
printf -v "$output_name" '%s' "${records[0]}"
|
|
}
|
|
|
|
_k3slra1_packet_line() {
|
|
local producer="${1-}" argument="${2-}" output_name="${3-}" value=''
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
case "$output_name" in producer|argument|output_name|value) return 1 ;; esac
|
|
_k3slra1_packet_value "$producer" "$argument" value || return 1
|
|
[[ "$value" == *$'\n' ]] || return 1
|
|
[[ "$value" != *$'\r'* ]] || return 1
|
|
value="${value%$'\n'}"
|
|
[[ -n "$value" ]] || return 1
|
|
[[ "$value" != *$'\n'* ]] || return 1
|
|
printf -v "$output_name" '%s' "$value"
|
|
}
|
|
|
|
_k3slra1_option_has() {
|
|
local options="${1-}" wanted="${2-}" option
|
|
local -a option_list=()
|
|
(( $# == 2 )) || return 1
|
|
IFS=, read -r -a option_list <<<"$options"
|
|
for option in "${option_list[@]}"; do
|
|
[[ "$option" == "$wanted" ]] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
_k3slra1_expected_mapper() {
|
|
local role="${1-}" output_name="${2-}" value=''
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != role ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != value ]] || return 1
|
|
case "$role" in
|
|
proof) value="$K3SLRA1_PROOF_MAPPER" ;;
|
|
original-baseline|original-final) value="$K3SLRA1_MAIN_MAPPER" ;;
|
|
*) return 1 ;;
|
|
esac
|
|
printf -v "$output_name" '%s' "$value"
|
|
}
|
|
|
|
_k3slra1_capture_mount_mapping_evidence() {
|
|
local mount_root="${1-}" role="${2-}" output_name="${3-}"
|
|
local expected_mapper='' mount_record='' mount_line='' source='' target='' fstype=''
|
|
local vfs_options='' fs_options='' mount_major_minor='' extra=''
|
|
local source_canonical='' canonical_mapper='' mapper_major_minor='' mapper_readonly='' mapper_stat=''
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
case "$output_name" in
|
|
mount_root|role|output_name|expected_mapper|mount_record|mount_line|source|target|fstype|vfs_options|fs_options|mount_major_minor|extra|source_canonical|canonical_mapper|mapper_major_minor|mapper_readonly|mapper_stat) return 1 ;;
|
|
esac
|
|
_k3slra1_expected_mapper "$role" expected_mapper || return 1
|
|
_k3slra1_packet_value findmnt "$mount_root" mount_record || return 1
|
|
(( ${#mount_record} >= 1 )) || return 1
|
|
(( ${#mount_record} <= K3SLRA1_MOUNT_RECORD_MAX_BYTES )) || return 1
|
|
[[ "$mount_record" == *$'\n' ]] || return 1
|
|
[[ "$mount_record" != *$'\r'* ]] || return 1
|
|
mount_line="${mount_record%$'\n'}"
|
|
[[ -n "$mount_line" ]] || return 1
|
|
[[ "$mount_line" != *$'\n'* ]] || return 1
|
|
[[ "$mount_line" =~ ^([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)$ ]] || return 1
|
|
source="${BASH_REMATCH[1]}"
|
|
target="${BASH_REMATCH[2]}"
|
|
fstype="${BASH_REMATCH[3]}"
|
|
vfs_options="${BASH_REMATCH[4]}"
|
|
fs_options="${BASH_REMATCH[5]}"
|
|
mount_major_minor="${BASH_REMATCH[6]}"
|
|
[[ -n "$source" ]] || return 1
|
|
[[ -n "$target" ]] || return 1
|
|
[[ -n "$fstype" ]] || return 1
|
|
[[ -n "$vfs_options" ]] || return 1
|
|
[[ -n "$fs_options" ]] || return 1
|
|
[[ -n "$mount_major_minor" ]] || return 1
|
|
[[ -z "$extra" ]] || return 1
|
|
[[ "$target" == "$mount_root" ]] || return 1
|
|
[[ "$fstype" == ext4 ]] || return 1
|
|
_k3slra1_option_has "$vfs_options" ro || return 1
|
|
_k3slra1_option_has "$vfs_options" nodev || return 1
|
|
_k3slra1_option_has "$vfs_options" nosuid || return 1
|
|
_k3slra1_option_has "$vfs_options" noexec || return 1
|
|
case ",${vfs_options}," in *,rw,*|*,dev,*|*,suid,*|*,exec,*) return 1 ;; esac
|
|
_k3slra1_option_has "$fs_options" noload || return 1
|
|
_k3slra1_packet_line readlink "$source" source_canonical || return 1
|
|
_k3slra1_packet_line readlink "$expected_mapper" canonical_mapper || return 1
|
|
[[ "$canonical_mapper" == "$source_canonical" ]] || return 1
|
|
[[ "$canonical_mapper" =~ ^/dev/dm-[0-9]+$ ]] || return 1
|
|
_k3slra1_packet_line mapper-stat "$canonical_mapper" mapper_stat || return 1
|
|
[[ "$mapper_stat" == "block special file|${mount_major_minor}" ]] || return 1
|
|
_k3slra1_packet_line lsblk "$canonical_mapper" mapper_major_minor || return 1
|
|
[[ "$mapper_major_minor" == "$mount_major_minor" ]] || return 1
|
|
_k3slra1_packet_value blockdev "$canonical_mapper" mapper_readonly || return 1
|
|
[[ "$mapper_readonly" == $'1\n' ]] || return 1
|
|
printf -v "$output_name" '%s' "${mount_record}|${canonical_mapper}|${mapper_major_minor}|${mapper_readonly}"
|
|
}
|
|
|
|
_k3slra1_output_names_are_distinct() {
|
|
local name seen_name
|
|
local -A seen=()
|
|
(( $# >= 1 )) || return 1
|
|
for name in "$@"; do
|
|
_k3slra1_output_name_is_safe "$name" || return 1
|
|
[[ "${seen[$name]+set}" != set ]] || return 1
|
|
printf -v 'seen[$name]' '%s' 1
|
|
done
|
|
}
|
|
|
|
_k3slra1_output_names_avoid() {
|
|
local output_count="${1-}" output_index=0 output_name forbidden_name
|
|
local -a output_names=()
|
|
(( $# >= 2 )) || return 1
|
|
[[ "$output_count" =~ ^[1-9][0-9]*$ ]] || return 1
|
|
shift
|
|
(( $# >= 10#$output_count + 1 )) || return 1
|
|
for (( output_index = 0; output_index < 10#$output_count; output_index += 1 )); do
|
|
output_names+=("${1-}")
|
|
shift
|
|
done
|
|
for forbidden_name in "$@"; do
|
|
for output_name in "${output_names[@]}"; do
|
|
[[ "$output_name" != "$forbidden_name" ]] || return 1
|
|
done
|
|
done
|
|
}
|
|
|
|
_k3slra1_metadata_fields() {
|
|
local path="${1-}" out_identity="${2-}" out_nlink="${3-}" out_size="${4-}"
|
|
local out_mtime="${5-}" out_type="${6-}" out_owner="${7-}" out_mode="${8-}"
|
|
local metadata='' _k3slra1_type_value=''
|
|
(( $# == 8 )) || return 1
|
|
_k3slra1_output_names_are_distinct "$out_identity" "$out_nlink" "$out_size" "$out_mtime" "$out_type" "$out_owner" "$out_mode" || return 1
|
|
case "$out_identity|$out_nlink|$out_size|$out_mtime|$out_type|$out_owner|$out_mode" in
|
|
*'|path|'*|path\|*|*\|path|*'|out_identity|'*|out_identity\|*|*\|out_identity|*'|out_nlink|'*|out_nlink\|*|*\|out_nlink|*'|out_size|'*|out_size\|*|*\|out_size|*'|out_mtime|'*|out_mtime\|*|*\|out_mtime|*'|out_type|'*|out_type\|*|*\|out_type|*'|out_owner|'*|out_owner\|*|*\|out_owner|*'|out_mode|'*|out_mode\|*|*\|out_mode|*'|metadata|'*|metadata\|*|*\|metadata) return 1 ;;
|
|
esac
|
|
_k3slra1_metadata "$path" metadata || return 1
|
|
[[ "$metadata" =~ ^([0-9]+:[0-9]+)\|([0-9]+)\|([0-9]+)\|([^|]+)\|(directory|regular[[:space:]]file|regular[[:space:]]empty[[:space:]]file|symbolic[[:space:]]link)\|([0-9]+:[0-9]+)\|([0-9]+)$ ]] || return 1
|
|
_k3slra1_type_value="${BASH_REMATCH[5]}"
|
|
if [[ "$_k3slra1_type_value" == 'regular empty file' ]]; then
|
|
printf -v _k3slra1_type_value '%s' 'regular file'
|
|
fi
|
|
printf -v "$out_identity" '%s' "${BASH_REMATCH[1]}"
|
|
printf -v "$out_nlink" '%s' "${BASH_REMATCH[2]}"
|
|
printf -v "$out_size" '%s' "${BASH_REMATCH[3]}"
|
|
printf -v "$out_mtime" '%s' "${BASH_REMATCH[4]}"
|
|
printf -v "$out_type" '%s' "$_k3slra1_type_value"
|
|
printf -v "$out_owner" '%s' "${BASH_REMATCH[6]}"
|
|
printf -v "$out_mode" '%s' "${BASH_REMATCH[7]}"
|
|
}
|
|
|
|
_k3slra1_fd_metadata_fields() {
|
|
local path="${1-}" out_identity="${2-}" out_nlink="${3-}" out_size="${4-}"
|
|
local out_mtime="${5-}" out_type="${6-}" out_owner="${7-}" out_mode="${8-}"
|
|
local metadata='' _k3slra1_type_value=''
|
|
(( $# == 8 )) || return 1
|
|
_k3slra1_output_names_are_distinct "$out_identity" "$out_nlink" "$out_size" "$out_mtime" "$out_type" "$out_owner" "$out_mode" || return 1
|
|
case "$out_identity|$out_nlink|$out_size|$out_mtime|$out_type|$out_owner|$out_mode" in
|
|
*'|path|'*|path\|*|*\|path|*'|out_identity|'*|out_identity\|*|*\|out_identity|*'|out_nlink|'*|out_nlink\|*|*\|out_nlink|*'|out_size|'*|out_size\|*|*\|out_size|*'|out_mtime|'*|out_mtime\|*|*\|out_mtime|*'|out_type|'*|out_type\|*|*\|out_type|*'|out_owner|'*|out_owner\|*|*\|out_owner|*'|out_mode|'*|out_mode\|*|*\|out_mode|*'|metadata|'*|metadata\|*|*\|metadata) return 1 ;;
|
|
esac
|
|
_k3slra1_packet_line fd-metadata "$path" metadata || return 1
|
|
[[ "$metadata" =~ ^([0-9]+:[0-9]+)\|([0-9]+)\|([0-9]+)\|([^|]+)\|(directory|regular[[:space:]]file|regular[[:space:]]empty[[:space:]]file|symbolic[[:space:]]link)\|([0-9]+:[0-9]+)\|([0-9]+)$ ]] || return 1
|
|
_k3slra1_type_value="${BASH_REMATCH[5]}"
|
|
if [[ "$_k3slra1_type_value" == 'regular empty file' ]]; then
|
|
printf -v _k3slra1_type_value '%s' 'regular file'
|
|
fi
|
|
printf -v "$out_identity" '%s' "${BASH_REMATCH[1]}"
|
|
printf -v "$out_nlink" '%s' "${BASH_REMATCH[2]}"
|
|
printf -v "$out_size" '%s' "${BASH_REMATCH[3]}"
|
|
printf -v "$out_mtime" '%s' "${BASH_REMATCH[4]}"
|
|
printf -v "$out_type" '%s' "$_k3slra1_type_value"
|
|
printf -v "$out_owner" '%s' "${BASH_REMATCH[6]}"
|
|
printf -v "$out_mode" '%s' "${BASH_REMATCH[7]}"
|
|
}
|
|
|
|
_k3slra1_find_mount_children_packet() {
|
|
local mount_root="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/find "$mount_root" -mindepth 1 -maxdepth 1 -print0 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf 'RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_find_regular_packet() {
|
|
local pre_root="${1-}" rc=0
|
|
(( $# == 1 )) || return 1
|
|
if _k3slra1_command /usr/bin/find "$pre_root" -xdev -type f -print0 2> >(_k3slra1_stderr_marker); then
|
|
rc=0
|
|
else
|
|
rc=$?
|
|
fi
|
|
printf 'RC=%s\0' "$rc"
|
|
}
|
|
|
|
_k3slra1_select_pre_bundle() {
|
|
local mount_root="${1-}" output_name="${2-}" entry base _k3slra1_selected_value=''
|
|
local canonical_mount='' canonical_bundle='' canonical_pre='' canonical_manifest=''
|
|
local mount_identity='' mount_nlink='' mount_size='' mount_mtime='' mount_type='' mount_owner='' mount_mode=''
|
|
local bundle_identity='' bundle_nlink='' bundle_size='' bundle_mtime='' bundle_type='' bundle_owner='' bundle_mode=''
|
|
local pre_identity='' pre_nlink='' pre_size='' pre_mtime='' pre_type='' pre_owner='' pre_mode=''
|
|
local manifest_identity='' manifest_nlink='' manifest_size='' manifest_mtime='' manifest_type='' manifest_owner='' manifest_mode=''
|
|
local pre_root='' manifest='' match_count=0 last_index=0
|
|
local -a entries=()
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
_k3slra1_output_names_avoid 1 "$output_name" mount_root output_name entry base canonical_mount canonical_bundle canonical_pre canonical_manifest mount_identity mount_nlink mount_size mount_mtime mount_type mount_owner mount_mode bundle_identity bundle_nlink bundle_size bundle_mtime bundle_type bundle_owner bundle_mode pre_identity pre_nlink pre_size pre_mtime pre_type pre_owner pre_mode manifest_identity manifest_nlink manifest_size manifest_mtime manifest_type manifest_owner manifest_mode pre_root manifest match_count last_index entries || return 1
|
|
mapfile -d '' -t entries < <(_k3slra1_find_mount_children_packet "$mount_root")
|
|
(( ${#entries[@]} >= 1 )) || return 1
|
|
(( last_index = ${#entries[@]} - 1 ))
|
|
[[ "${entries[$last_index]}" == RC=0 ]] || return 1
|
|
unset 'entries[last_index]'
|
|
for entry in "${entries[@]}"; do
|
|
[[ -n "$entry" ]] || return 1
|
|
[[ "$entry" != STDERR ]] || return 1
|
|
base="${entry##*/}"
|
|
if [[ "$base" =~ ^k3s-secrets-encryption-[0-9]{8}T[0-9]{6}Z$ ]]; then
|
|
(( match_count += 1 ))
|
|
_k3slra1_selected_value="$entry"
|
|
fi
|
|
done
|
|
(( match_count == 1 )) || return 1
|
|
pre_root="${_k3slra1_selected_value}/pre"
|
|
manifest="${pre_root}/verification.manifest"
|
|
_k3slra1_canonical_path "$mount_root" canonical_mount || return 1
|
|
_k3slra1_canonical_path "$_k3slra1_selected_value" canonical_bundle || return 1
|
|
_k3slra1_canonical_path "$pre_root" canonical_pre || return 1
|
|
_k3slra1_canonical_path "$manifest" canonical_manifest || return 1
|
|
[[ "$canonical_mount" == "$mount_root" ]] || return 1
|
|
[[ "$canonical_bundle" == "$_k3slra1_selected_value" ]] || return 1
|
|
[[ "$canonical_pre" == "$pre_root" ]] || return 1
|
|
[[ "$canonical_manifest" == "$manifest" ]] || return 1
|
|
_k3slra1_metadata_fields "$mount_root" mount_identity mount_nlink mount_size mount_mtime mount_type mount_owner mount_mode || return 1
|
|
_k3slra1_metadata_fields "$_k3slra1_selected_value" bundle_identity bundle_nlink bundle_size bundle_mtime bundle_type bundle_owner bundle_mode || return 1
|
|
_k3slra1_metadata_fields "$pre_root" pre_identity pre_nlink pre_size pre_mtime pre_type pre_owner pre_mode || return 1
|
|
_k3slra1_metadata_fields "$manifest" manifest_identity manifest_nlink manifest_size manifest_mtime manifest_type manifest_owner manifest_mode || return 1
|
|
[[ "$mount_type" == directory ]] || return 1
|
|
[[ "$bundle_type" == directory ]] || return 1
|
|
[[ "$pre_type" == directory ]] || return 1
|
|
[[ "$manifest_type" == 'regular file' ]] || return 1
|
|
[[ "$bundle_owner" == 0:0 ]] || return 1
|
|
[[ "$pre_owner" == 0:0 ]] || return 1
|
|
[[ "$manifest_owner" == 0:0 ]] || return 1
|
|
[[ "$bundle_mode" == 700 ]] || return 1
|
|
[[ "$pre_mode" == 700 ]] || return 1
|
|
[[ "$manifest_mode" == 600 ]] || return 1
|
|
[[ "$manifest_nlink" == 1 ]] || return 1
|
|
[[ "${bundle_identity%%:*}" == "${mount_identity%%:*}" ]] || return 1
|
|
[[ "${pre_identity%%:*}" == "${mount_identity%%:*}" ]] || return 1
|
|
[[ "${manifest_identity%%:*}" == "${mount_identity%%:*}" ]] || return 1
|
|
printf -v "$output_name" '%s' "$_k3slra1_selected_value"
|
|
}
|
|
|
|
_k3slra1_capture_manifest_hex() {
|
|
local manifest="${1-}" output_name="${2-}" stat_size='' byte_count='' od_output='' hex=''
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != manifest ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != size ]] || return 1
|
|
[[ "$output_name" != stat_size ]] || return 1
|
|
[[ "$output_name" != byte_count ]] || return 1
|
|
[[ "$output_name" != od_output ]] || return 1
|
|
[[ "$output_name" != hex ]] || return 1
|
|
_k3slra1_packet_line size-stat "$manifest" stat_size || return 1
|
|
[[ "$stat_size" =~ ^[0-9]+$ ]] || return 1
|
|
(( 10#$stat_size >= 1 )) || return 1
|
|
(( 10#$stat_size <= K3SLRA1_MANIFEST_MAX_BYTES )) || return 1
|
|
_k3slra1_packet_line wc "$manifest" byte_count || return 1
|
|
[[ "$byte_count" == *"$manifest" ]] || return 1
|
|
byte_count="${byte_count%"$manifest"}"
|
|
[[ "$byte_count" == *[[:space:]] ]] || return 1
|
|
byte_count="${byte_count//[[:space:]]/}"
|
|
[[ "$byte_count" == "$stat_size" ]] || return 1
|
|
_k3slra1_packet_value od "$manifest" od_output || return 1
|
|
[[ "$od_output" == *$'\n' ]] || return 1
|
|
[[ "$od_output" != *$'\r'* ]] || return 1
|
|
od_output="${od_output%$'\n'}"
|
|
[[ -n "$od_output" ]] || return 1
|
|
[[ "$od_output" != *$'\n' ]] || return 1
|
|
[[ "$od_output" != *$'\n\n'* ]] || return 1
|
|
hex="${od_output//[[:space:]]/}"
|
|
[[ "$hex" =~ ^[0-9a-f]+$ ]] || return 1
|
|
(( ${#hex} == 10#$stat_size * 2 )) || return 1
|
|
[[ " $od_output " != *[[:space:]]00[[:space:]]* ]] || return 1
|
|
[[ " $od_output " != *[[:space:]]0d[[:space:]]* ]] || return 1
|
|
[[ "${hex: -2}" == 0a ]] || return 1
|
|
printf -v "$output_name" '%s' "$hex"
|
|
}
|
|
|
|
_k3slra1_verify_payload() {
|
|
# Internal-only: the proof orchestrator supplies a reviewed helper staged in
|
|
# its root-owned runtime tmpfs before this privileged dispatch boundary.
|
|
local mount_root="${1-}" role="${2-}" capture_root="${3-}"
|
|
local helper=''
|
|
(( $# == 3 )) || return 1
|
|
case "$role" in
|
|
original-baseline|proof|original-final) ;;
|
|
*) return 1 ;;
|
|
esac
|
|
helper="${capture_root}/libexec/k3s-local-recovery-a1-check.sh"
|
|
_k3slra1_command /usr/bin/sudo --non-interactive -- /usr/bin/env -i PATH=/usr/sbin:/usr/bin:/sbin:/bin LC_ALL=C /usr/bin/bash --noprofile --norc -- "$helper" "$mount_root" "$role" "$capture_root" >/dev/null 2>&1
|
|
}
|
|
|
|
_k3slra1_verify_payload_root() {
|
|
local mount_root="${1-}" role="${2-}" capture_root="${3-}"
|
|
local _bundle='' _layout='' _count_before='' _bytes_before='' _snapshot_before=''
|
|
local _count_after='' _bytes_after='' _snapshot_after=''
|
|
local _mount_before='' _mount_sqlite='' _mount_after='' _sqlite_rc=0
|
|
(( $# == 3 )) || return 1
|
|
case "$role" in
|
|
original-baseline|proof|original-final) ;;
|
|
*) return 1 ;;
|
|
esac
|
|
_k3slra1_capture_mount_mapping_evidence "$mount_root" "$role" _mount_before || return 1
|
|
_k3slra1_select_pre_bundle "$mount_root" _bundle || return 1
|
|
_k3slra1_analyze_manifest "$_bundle" _count_before _bytes_before _snapshot_before || return 1
|
|
[[ "$_count_before" == "$K3SLRA1_TARGET_COUNT" ]] || return 1
|
|
[[ "$_bytes_before" == "$K3SLRA1_TARGET_BYTES" ]] || return 1
|
|
_k3slra1_select_sqlite_layout_from_snapshot "$_bundle" "$_snapshot_before" _layout || return 1
|
|
_k3slra1_capture_mount_mapping_evidence "$mount_root" "$role" _mount_sqlite || return 1
|
|
[[ "$_mount_sqlite" == "$_mount_before" ]] || return 1
|
|
if _k3slra1_sqlite_quick_check "$_bundle" "$_layout" "$capture_root"; then
|
|
_sqlite_rc=0
|
|
else
|
|
_sqlite_rc=$?
|
|
fi
|
|
case "$_sqlite_rc" in
|
|
0) ;;
|
|
130|143) return "$_sqlite_rc" ;;
|
|
*) return 1 ;;
|
|
esac
|
|
_k3slra1_analyze_manifest "$_bundle" _count_after _bytes_after _snapshot_after || return 1
|
|
[[ "$_count_after" == "$_count_before" ]] || return 1
|
|
[[ "$_bytes_after" == "$_bytes_before" ]] || return 1
|
|
[[ "$_snapshot_after" == "$_snapshot_before" ]] || return 1
|
|
_k3slra1_capture_mount_mapping_evidence "$mount_root" "$role" _mount_after || return 1
|
|
[[ "$_mount_after" == "$_mount_before" ]]
|
|
}
|
|
|
|
_k3slra1_sha256_record() {
|
|
local path="${1-}" output_name="${2-}" line=''
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != path ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != value ]] || return 1
|
|
[[ "$output_name" != line ]] || return 1
|
|
_k3slra1_packet_line sha256 "$path" line || return 1
|
|
printf -v "$output_name" '%s' "$line"
|
|
}
|
|
|
|
_k3slra1_analyze_manifest() {
|
|
local bundle="${1-}" out_count="${2-}" out_bytes="${3-}" out_snapshot="${4-}"
|
|
local mount_root='' _selected_value='' pre_root='' manifest='' manifest_hex_before='' manifest_hex_after=''
|
|
local bundle_identity='' bundle_nlink='' bundle_size='' bundle_mtime='' bundle_type='' bundle_owner='' bundle_mode=''
|
|
local pre_identity='' pre_nlink='' pre_size='' pre_mtime='' pre_type='' pre_owner='' pre_mode=''
|
|
local manifest_identity_before='' manifest_nlink_before='' manifest_size_before='' manifest_mtime_before=''
|
|
local manifest_type_before='' manifest_owner_before='' manifest_mode_before='' manifest_record_before=''
|
|
local manifest_identity_after='' manifest_nlink_after='' manifest_size_after='' manifest_mtime_after=''
|
|
local manifest_type_after='' manifest_owner_after='' manifest_mode_after='' manifest_record_after=''
|
|
local line='' hash='' relative='' target='' canonical_target='' target_record_before='' target_record_after=''
|
|
local target_identity='' target_nlink='' target_size='' target_mtime='' target_type='' target_owner='' target_mode=''
|
|
local inventory_path='' _snapshot_value='' _count_value=0 _bytes_value=0
|
|
local last_index=0 inventory_count=0
|
|
local -a inventory=() manifest_lines=()
|
|
local -A seen_paths=() seen_inodes=() expected_inventory=() seen_inventory=()
|
|
(( $# == 4 )) || return 1
|
|
_k3slra1_output_names_are_distinct "$out_count" "$out_bytes" "$out_snapshot" || return 1
|
|
_k3slra1_output_names_avoid 3 "$out_count" "$out_bytes" "$out_snapshot" bundle out_count out_bytes out_snapshot mount_root _selected_value pre_root manifest manifest_hex_before manifest_hex_after bundle_identity bundle_nlink bundle_size bundle_mtime bundle_type bundle_owner bundle_mode pre_identity pre_nlink pre_size pre_mtime pre_type pre_owner pre_mode manifest_identity_before manifest_nlink_before manifest_size_before manifest_mtime_before manifest_type_before manifest_owner_before manifest_mode_before manifest_record_before manifest_identity_after manifest_nlink_after manifest_size_after manifest_mtime_after manifest_type_after manifest_owner_after manifest_mode_after manifest_record_after line hash relative target canonical_target target_record_before target_record_after target_identity target_nlink target_size target_mtime target_type target_owner target_mode inventory_path _snapshot_value _count_value _bytes_value last_index inventory_count inventory manifest_lines seen_paths seen_inodes expected_inventory seen_inventory || return 1
|
|
mount_root="${bundle%/*}"
|
|
[[ -n "$mount_root" ]] || return 1
|
|
_k3slra1_select_pre_bundle "$mount_root" _selected_value || return 1
|
|
[[ "$_selected_value" == "$bundle" ]] || return 1
|
|
pre_root="${bundle}/pre"
|
|
manifest="${pre_root}/verification.manifest"
|
|
_k3slra1_metadata_fields "$bundle" bundle_identity bundle_nlink bundle_size bundle_mtime bundle_type bundle_owner bundle_mode || return 1
|
|
_k3slra1_metadata_fields "$pre_root" pre_identity pre_nlink pre_size pre_mtime pre_type pre_owner pre_mode || return 1
|
|
_k3slra1_metadata_fields "$manifest" manifest_identity_before manifest_nlink_before manifest_size_before manifest_mtime_before manifest_type_before manifest_owner_before manifest_mode_before || return 1
|
|
_k3slra1_capture_manifest_hex "$manifest" manifest_hex_before || return 1
|
|
_k3slra1_sha256_record "$manifest" manifest_record_before || return 1
|
|
printf -v "expected_inventory[$manifest]" '%s' 1
|
|
mapfile -t manifest_lines <"$manifest"
|
|
for line in "${manifest_lines[@]}"; do
|
|
(( _count_value += 1 ))
|
|
(( _count_value <= K3SLRA1_TARGET_COUNT )) || return 1
|
|
[[ "$line" =~ ^[0-9a-f]{64}\ \ \./[A-Za-z0-9._+/-]+$ ]] || return 1
|
|
hash="${line:0:64}"
|
|
relative="${line:66}"
|
|
(( ${#relative} <= K3SLRA1_PATH_MAX_BYTES )) || return 1
|
|
[[ "$relative" != './verification.manifest' ]] || return 1
|
|
[[ "$relative" != *//* ]] || return 1
|
|
[[ "$relative" != *'/./'* ]] || return 1
|
|
[[ "$relative" != *'/../'* ]] || return 1
|
|
[[ "$relative" != */. ]] || return 1
|
|
[[ "$relative" != */.. ]] || return 1
|
|
[[ "$relative" != */ ]] || return 1
|
|
[[ "${seen_paths[$relative]+set}" != set ]] || return 1
|
|
printf -v "seen_paths[$relative]" '%s' 1
|
|
target="${pre_root}/${relative#./}"
|
|
_k3slra1_canonical_path "$target" canonical_target || return 1
|
|
[[ "$canonical_target" == "$target" ]] || return 1
|
|
_k3slra1_metadata_fields "$target" target_identity target_nlink target_size target_mtime target_type target_owner target_mode || return 1
|
|
[[ "$target_type" == 'regular file' ]] || return 1
|
|
[[ "$target_nlink" == 1 ]] || return 1
|
|
[[ "${target_identity%%:*}" == "${pre_identity%%:*}" ]] || return 1
|
|
[[ "${seen_inodes[$target_identity]+set}" != set ]] || return 1
|
|
printf -v "seen_inodes[$target_identity]" '%s' 1
|
|
target_record_before="${target_identity}|${target_nlink}|${target_size}|${target_mtime}|${target_type}|${target_owner}|${target_mode}"
|
|
_k3slra1_sha256_record "$target" target_record_after || return 1
|
|
[[ "$target_record_after" == "${hash} ${target}" ]] || return 1
|
|
_k3slra1_metadata_fields "$target" target_identity target_nlink target_size target_mtime target_type target_owner target_mode || return 1
|
|
[[ "${target_identity}|${target_nlink}|${target_size}|${target_mtime}|${target_type}|${target_owner}|${target_mode}" == "$target_record_before" ]] || return 1
|
|
(( _bytes_value += 10#$target_size ))
|
|
printf -v _snapshot_value '%s%s|%s|%s\n' "$_snapshot_value" "$relative" "$target_record_before" "$hash"
|
|
printf -v "expected_inventory[$target]" '%s' 1
|
|
done
|
|
(( _count_value == K3SLRA1_TARGET_COUNT )) || return 1
|
|
(( _bytes_value == K3SLRA1_TARGET_BYTES )) || return 1
|
|
mapfile -d '' -t inventory < <(_k3slra1_find_regular_packet "$pre_root")
|
|
(( ${#inventory[@]} >= 1 )) || return 1
|
|
(( last_index = ${#inventory[@]} - 1 ))
|
|
[[ "${inventory[$last_index]}" == RC=0 ]] || return 1
|
|
unset 'inventory[last_index]'
|
|
for inventory_path in "${inventory[@]}"; do
|
|
[[ -n "$inventory_path" ]] || return 1
|
|
[[ "$inventory_path" != STDERR ]] || return 1
|
|
[[ "${expected_inventory[$inventory_path]+set}" == set ]] || return 1
|
|
[[ "${seen_inventory[$inventory_path]+set}" != set ]] || return 1
|
|
printf -v "seen_inventory[$inventory_path]" '%s' 1
|
|
(( inventory_count += 1 ))
|
|
done
|
|
(( inventory_count == K3SLRA1_TARGET_COUNT + 1 )) || return 1
|
|
_k3slra1_metadata_fields "$manifest" manifest_identity_after manifest_nlink_after manifest_size_after manifest_mtime_after manifest_type_after manifest_owner_after manifest_mode_after || return 1
|
|
_k3slra1_capture_manifest_hex "$manifest" manifest_hex_after || return 1
|
|
_k3slra1_sha256_record "$manifest" manifest_record_after || return 1
|
|
[[ "$manifest_identity_after" == "$manifest_identity_before" ]] || return 1
|
|
[[ "$manifest_nlink_after" == "$manifest_nlink_before" ]] || return 1
|
|
[[ "$manifest_size_after" == "$manifest_size_before" ]] || return 1
|
|
[[ "$manifest_mtime_after" == "$manifest_mtime_before" ]] || return 1
|
|
[[ "$manifest_type_after" == "$manifest_type_before" ]] || return 1
|
|
[[ "$manifest_owner_after" == "$manifest_owner_before" ]] || return 1
|
|
[[ "$manifest_mode_after" == "$manifest_mode_before" ]] || return 1
|
|
[[ "$manifest_hex_after" == "$manifest_hex_before" ]] || return 1
|
|
[[ "$manifest_record_after" == "$manifest_record_before" ]] || return 1
|
|
printf -v _snapshot_value '%s%s\n%s\n%s\n' "$_snapshot_value" "$bundle_identity|$bundle_nlink|$bundle_size|$bundle_mtime|$bundle_type|$bundle_owner|$bundle_mode" "$pre_identity|$pre_nlink|$pre_size|$pre_mtime|$pre_type|$pre_owner|$pre_mode" "$manifest_identity_before|$manifest_nlink_before|$manifest_size_before|$manifest_mtime_before|$manifest_type_before|$manifest_owner_before|$manifest_mode_before|$manifest_record_before"
|
|
printf -v "$out_count" '%s' "$_count_value"
|
|
printf -v "$out_bytes" '%s' "$_bytes_value"
|
|
printf -v "$out_snapshot" '%s' "$_snapshot_value"
|
|
}
|
|
|
|
_k3slra1_verify_manifest() {
|
|
local bundle="${1-}" out_count="${2-}" out_bytes="${3-}"
|
|
local _count_result='' _bytes_result='' _snapshot_result=''
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_output_names_are_distinct "$out_count" "$out_bytes" || return 1
|
|
_k3slra1_output_names_avoid 2 "$out_count" "$out_bytes" bundle out_count out_bytes _count_result _bytes_result _snapshot_result || return 1
|
|
_k3slra1_analyze_manifest "$bundle" _count_result _bytes_result _snapshot_result || return 1
|
|
printf -v "$out_count" '%s' "$_count_result"
|
|
printf -v "$out_bytes" '%s' "$_bytes_result"
|
|
}
|
|
|
|
_k3slra1_snapshot_metadata_for_relative() {
|
|
local snapshot="${1-}" relative="${2-}" output_name="${3-}"
|
|
local line='' value='' match_count=0
|
|
local -a snapshot_lines=()
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
_k3slra1_output_names_avoid 1 "$output_name" snapshot relative output_name line value match_count snapshot_lines || return 1
|
|
[[ "$relative" == ./* ]] || return 1
|
|
mapfile -t snapshot_lines <<<"$snapshot"
|
|
for line in "${snapshot_lines[@]}"; do
|
|
if [[ "$line" == "${relative}|"* ]]; then
|
|
(( match_count += 1 ))
|
|
value="${line#"${relative}|"}"
|
|
[[ "$value" =~ \|([0-9a-f]{64})$ ]] || return 1
|
|
value="${value%|${BASH_REMATCH[1]}}"
|
|
fi
|
|
done
|
|
(( match_count == 1 )) || return 1
|
|
[[ "$value" =~ ^[0-9]+:[0-9]+\|1\|[0-9]+\|.+\|regular[[:space:]]file\|[0-9]+:[0-9]+\|[0-9]+$ ]] || return 1
|
|
printf -v "$output_name" '%s' "$value"
|
|
}
|
|
|
|
_k3slra1_sqlite_selected_path_matches() {
|
|
local path="${1-}" expected_device="${2-}" expected_record="${3-}" canonical=''
|
|
local identity='' nlink='' size='' mtime='' type='' owner='' mode='' current_record=''
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_canonical_path "$path" canonical || return 1
|
|
[[ "$canonical" == "$path" ]] || return 1
|
|
_k3slra1_metadata_fields "$path" identity nlink size mtime type owner mode || return 1
|
|
[[ "${identity%%:*}" == "$expected_device" ]] || return 1
|
|
[[ "$nlink" == 1 ]] || return 1
|
|
[[ "$type" == 'regular file' ]] || return 1
|
|
current_record="${identity}|${nlink}|${size}|${mtime}|${type}|${owner}|${mode}"
|
|
[[ "$current_record" == "$expected_record" ]]
|
|
}
|
|
|
|
_k3slra1_select_sqlite_layout_from_snapshot() {
|
|
local bundle="${1-}" snapshot="${2-}" output_name="${3-}" path relative=''
|
|
local expected_record='' canonical_count=0 legacy_count=0 _k3slra1_layout_value=''
|
|
local pre_identity='' pre_nlink='' pre_size='' pre_mtime='' pre_type='' pre_owner='' pre_mode='' pre_device=''
|
|
local -a selected_paths=() canonical_paths=("${bundle}/pre/${K3SLRA1_CANONICAL_DATABASE#./}" "${bundle}/pre/${K3SLRA1_CANONICAL_DATABASE#./}-wal" "${bundle}/pre/${K3SLRA1_CANONICAL_DATABASE#./}-shm") legacy_paths=("${bundle}/pre/${K3SLRA1_LEGACY_DATABASE#./}" "${bundle}/pre/${K3SLRA1_LEGACY_DATABASE#./}-wal" "${bundle}/pre/${K3SLRA1_LEGACY_DATABASE#./}-shm")
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
_k3slra1_output_names_avoid 1 "$output_name" bundle snapshot output_name path relative expected_record canonical_count legacy_count pre_identity pre_nlink pre_size pre_mtime pre_type pre_owner pre_mode pre_device selected_paths canonical_paths legacy_paths || return 1
|
|
_k3slra1_metadata_fields "${bundle}/pre" pre_identity pre_nlink pre_size pre_mtime pre_type pre_owner pre_mode || return 1
|
|
pre_device="${pre_identity%%:*}"
|
|
for path in "${canonical_paths[@]}"; do
|
|
if [[ -e "$path" ]]; then
|
|
(( canonical_count += 1 ))
|
|
else
|
|
if [[ -L "$path" ]]; then
|
|
(( canonical_count += 1 ))
|
|
fi
|
|
fi
|
|
done
|
|
for path in "${legacy_paths[@]}"; do
|
|
if [[ -e "$path" ]]; then
|
|
(( legacy_count += 1 ))
|
|
else
|
|
if [[ -L "$path" ]]; then
|
|
(( legacy_count += 1 ))
|
|
fi
|
|
fi
|
|
done
|
|
if (( canonical_count == 3 )); then
|
|
(( legacy_count == 0 )) || return 1
|
|
_k3slra1_layout_value=canonical
|
|
selected_paths=("${canonical_paths[@]}")
|
|
else
|
|
if (( legacy_count == 3 )); then
|
|
(( canonical_count == 0 )) || return 1
|
|
_k3slra1_layout_value=legacy
|
|
selected_paths=("${legacy_paths[@]}")
|
|
else
|
|
return 1
|
|
fi
|
|
fi
|
|
for path in "${selected_paths[@]}"; do
|
|
relative="./${path#"${bundle}/pre/"}"
|
|
_k3slra1_snapshot_metadata_for_relative "$snapshot" "$relative" expected_record || return 1
|
|
_k3slra1_sqlite_selected_path_matches "$path" "$pre_device" "$expected_record" || return 1
|
|
done
|
|
printf -v "$output_name" '%s' "$_k3slra1_layout_value"
|
|
}
|
|
|
|
_k3slra1_select_sqlite_layout() {
|
|
local bundle="${1-}" output_name="${2-}" count='' bytes='' snapshot=''
|
|
(( $# == 2 )) || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
_k3slra1_output_names_avoid 1 "$output_name" bundle output_name count bytes snapshot path || return 1
|
|
_k3slra1_analyze_manifest "$bundle" count bytes snapshot || return 1
|
|
_k3slra1_select_sqlite_layout_from_snapshot "$bundle" "$snapshot" "$output_name"
|
|
}
|
|
|
|
_k3slra1_capture_file_hex() {
|
|
local file="${1-}" maximum="${2-}" output_name="${3-}" size='' count='' od_output='' hex=''
|
|
(( $# == 3 )) || return 1
|
|
[[ "$maximum" =~ ^[1-9][0-9]*$ ]] || return 1
|
|
_k3slra1_output_name_is_safe "$output_name" || return 1
|
|
[[ "$output_name" != file ]] || return 1
|
|
[[ "$output_name" != maximum ]] || return 1
|
|
[[ "$output_name" != output_name ]] || return 1
|
|
[[ "$output_name" != size ]] || return 1
|
|
[[ "$output_name" != count ]] || return 1
|
|
[[ "$output_name" != od_output ]] || return 1
|
|
[[ "$output_name" != hex ]] || return 1
|
|
_k3slra1_packet_line size-stat "$file" size || return 1
|
|
[[ "$size" =~ ^[0-9]+$ ]] || return 1
|
|
(( 10#$size <= 10#$maximum )) || return 1
|
|
_k3slra1_packet_line wc "$file" count || return 1
|
|
[[ "$count" == *"$file" ]] || return 1
|
|
count="${count%"$file"}"
|
|
[[ "$count" == *[[:space:]] ]] || return 1
|
|
count="${count//[[:space:]]/}"
|
|
[[ "$count" == "$size" ]] || return 1
|
|
_k3slra1_packet_value od "$file" od_output || return 1
|
|
[[ "$od_output" != *$'\r'* ]] || return 1
|
|
if [[ -n "$od_output" ]]; then
|
|
[[ "$od_output" == *$'\n' ]] || return 1
|
|
od_output="${od_output%$'\n'}"
|
|
[[ -n "$od_output" ]] || return 1
|
|
[[ "$od_output" != *$'\n' ]] || return 1
|
|
[[ "$od_output" != *$'\n\n'* ]] || return 1
|
|
fi
|
|
hex="${od_output//[[:space:]]/}"
|
|
if (( 10#$size == 0 )); then
|
|
[[ -z "$hex" ]] || return 1
|
|
else
|
|
[[ "$hex" =~ ^[0-9a-f]+$ ]] || return 1
|
|
(( ${#hex} == 10#$size * 2 )) || return 1
|
|
fi
|
|
printf -v "$output_name" '%s' "$hex"
|
|
}
|
|
|
|
_k3slra1_sqlite_capture_transaction() {
|
|
local database="${1-}" capture_root="${2-}" stdout_path="${3-}" stderr_path="${4-}"
|
|
local parent_identity_before='' parent_nlink='' parent_size='' parent_mtime='' parent_type='' parent_owner='' parent_mode=''
|
|
local parent_fd_identity_after='' parent_fd_nlink_after='' parent_fd_size_after=''
|
|
local parent_fd_mtime_after='' parent_fd_type_after='' parent_fd_owner_after='' parent_fd_mode_after=''
|
|
local stdout_identity_before='' stdout_nlink='' stdout_size='' stdout_mtime='' stdout_type='' stdout_owner='' stdout_mode=''
|
|
local stdout_fd_identity_after='' stdout_fd_nlink_after='' stdout_fd_size_after=''
|
|
local stdout_fd_mtime_after='' stdout_fd_type_after='' stdout_fd_owner_after='' stdout_fd_mode_after=''
|
|
local stderr_identity_before='' stderr_nlink='' stderr_size='' stderr_mtime='' stderr_type='' stderr_owner='' stderr_mode=''
|
|
local stderr_fd_identity='' stderr_fd_nlink='' stderr_fd_size='' stderr_fd_mtime='' stderr_fd_type='' stderr_fd_owner='' stderr_fd_mode=''
|
|
local stderr_fd_identity_after='' stderr_fd_nlink_after='' stderr_fd_size_after=''
|
|
local stderr_fd_mtime_after='' stderr_fd_type_after='' stderr_fd_owner_after='' stderr_fd_mode_after=''
|
|
local parent_identity_after='' parent_nlink_after='' parent_size_after='' parent_mtime_after='' parent_type_after='' parent_owner_after='' parent_mode_after=''
|
|
local stdout_identity_after='' stdout_nlink_after='' stdout_size_after='' stdout_mtime_after='' stdout_type_after='' stdout_owner_after='' stdout_mode_after=''
|
|
local stderr_identity_after='' stderr_nlink_after='' stderr_size_after='' stderr_mtime_after='' stderr_type_after='' stderr_owner_after='' stderr_mode_after=''
|
|
local stdout_hex='' stderr_hex='' validation_rc=0 child_rc=1 cleanup_rc=0
|
|
(( $# == 4 )) || return 1
|
|
_capture_entered=1
|
|
if _k3slra1_metadata_fields "$capture_root" parent_identity_before parent_nlink parent_size parent_mtime parent_type parent_owner parent_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_metadata_fields "$stdout_path" stdout_identity_before stdout_nlink stdout_size stdout_mtime stdout_type stdout_owner stdout_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_metadata_fields "$stderr_path" stderr_identity_before stderr_nlink stderr_size stderr_mtime stderr_type stderr_owner stderr_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_fd_metadata_fields "/proc/${BASHPID}/fd/8" stderr_fd_identity stderr_fd_nlink stderr_fd_size stderr_fd_mtime stderr_fd_type stderr_fd_owner stderr_fd_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
[[ "$parent_type" == directory ]] || validation_rc=1
|
|
[[ "$parent_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$parent_mode" == 700 ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_type" == directory ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_mode" == 700 ]] || validation_rc=1
|
|
[[ "$_stage_parent_identity" == "$parent_identity_before" ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_identity" == "$parent_identity_before" ]] || validation_rc=1
|
|
[[ "$stdout_type" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stderr_type" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stdout_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$stderr_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$stdout_mode" == 600 ]] || validation_rc=1
|
|
[[ "$stderr_mode" == 600 ]] || validation_rc=1
|
|
[[ "$stdout_nlink" == 1 ]] || validation_rc=1
|
|
[[ "$stderr_nlink" == 1 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_type" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stderr_fd_type" == 'regular file' ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$stderr_fd_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_mode" == 600 ]] || validation_rc=1
|
|
[[ "$stderr_fd_mode" == 600 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_nlink" == 1 ]] || validation_rc=1
|
|
[[ "$stderr_fd_nlink" == 1 ]] || validation_rc=1
|
|
[[ "$stdout_identity_before" == "$_stage_stdout_identity" ]] || validation_rc=1
|
|
[[ "$stdout_identity_before" == "$_stage_stdout_fd_identity" ]] || validation_rc=1
|
|
[[ "$stderr_identity_before" == "$stderr_fd_identity" ]] || validation_rc=1
|
|
[[ "$stdout_size" == "$_stage_stdout_fd_size" ]] || validation_rc=1
|
|
[[ "$stderr_size" == "$stderr_fd_size" ]] || validation_rc=1
|
|
[[ "$stdout_mtime" == "$_stage_stdout_fd_mtime" ]] || validation_rc=1
|
|
[[ "$stderr_mtime" == "$stderr_fd_mtime" ]] || validation_rc=1
|
|
[[ "$stdout_type" == "$_stage_stdout_fd_type" ]] || validation_rc=1
|
|
[[ "$stderr_type" == "$stderr_fd_type" ]] || validation_rc=1
|
|
[[ "$stdout_owner" == "$_stage_stdout_fd_owner" ]] || validation_rc=1
|
|
[[ "$stderr_owner" == "$stderr_fd_owner" ]] || validation_rc=1
|
|
[[ "$stdout_mode" == "$_stage_stdout_fd_mode" ]] || validation_rc=1
|
|
[[ "$stderr_mode" == "$stderr_fd_mode" ]] || validation_rc=1
|
|
[[ "$stderr_size" == 0 ]] || validation_rc=1
|
|
[[ "$stdout_identity_before" != "$stderr_identity_before" ]] || validation_rc=1
|
|
if (( validation_rc == 0 )); then
|
|
if _k3slra1_command /usr/bin/env -i PATH=/usr/sbin:/usr/bin:/sbin:/bin LC_ALL=C "HOME=${capture_root}/home" /usr/bin/sqlite3 -safe -nofollow -readonly -batch -bail -noheader -init /dev/null "$database" "$K3SLRA1_SQLITE_QUERY" >&7 2>&8; then
|
|
child_rc=0
|
|
else
|
|
child_rc=$?
|
|
fi
|
|
fi
|
|
if _k3slra1_metadata_fields "$stdout_path" stdout_identity_after stdout_nlink_after stdout_size_after stdout_mtime_after stdout_type_after stdout_owner_after stdout_mode_after; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_metadata_fields "$stderr_path" stderr_identity_after stderr_nlink_after stderr_size_after stderr_mtime_after stderr_type_after stderr_owner_after stderr_mode_after; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_metadata_fields "$capture_root" parent_identity_after parent_nlink_after parent_size_after parent_mtime_after parent_type_after parent_owner_after parent_mode_after; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_fd_metadata_fields "/proc/${BASHPID}/fd/6" parent_fd_identity_after parent_fd_nlink_after parent_fd_size_after parent_fd_mtime_after parent_fd_type_after parent_fd_owner_after parent_fd_mode_after; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_fd_metadata_fields "/proc/${BASHPID}/fd/7" stdout_fd_identity_after stdout_fd_nlink_after stdout_fd_size_after stdout_fd_mtime_after stdout_fd_type_after stdout_fd_owner_after stdout_fd_mode_after; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_fd_metadata_fields "/proc/${BASHPID}/fd/8" stderr_fd_identity_after stderr_fd_nlink_after stderr_fd_size_after stderr_fd_mtime_after stderr_fd_type_after stderr_fd_owner_after stderr_fd_mode_after; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
[[ "$parent_identity_after" == "$parent_identity_before" ]] || validation_rc=1
|
|
[[ "$parent_identity_after" == "$parent_fd_identity_after" ]] || validation_rc=1
|
|
[[ "$parent_fd_identity_after" == "$_stage_parent_fd_identity" ]] || validation_rc=1
|
|
[[ "$parent_type_after" == directory ]] || validation_rc=1
|
|
[[ "$parent_fd_type_after" == directory ]] || validation_rc=1
|
|
[[ "$parent_owner_after" == 0:0 ]] || validation_rc=1
|
|
[[ "$parent_fd_owner_after" == 0:0 ]] || validation_rc=1
|
|
[[ "$parent_mode_after" == 700 ]] || validation_rc=1
|
|
[[ "$parent_fd_mode_after" == 700 ]] || validation_rc=1
|
|
[[ "$stdout_identity_after" == "$stdout_identity_before" ]] || validation_rc=1
|
|
[[ "$stdout_identity_after" == "$stdout_fd_identity_after" ]] || validation_rc=1
|
|
[[ "$stdout_nlink_after" == 1 ]] || validation_rc=1
|
|
[[ "$stdout_fd_nlink_after" == 1 ]] || validation_rc=1
|
|
[[ "$stdout_type_after" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stdout_fd_type_after" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stdout_owner_after" == 0:0 ]] || validation_rc=1
|
|
[[ "$stdout_fd_owner_after" == 0:0 ]] || validation_rc=1
|
|
[[ "$stdout_mode_after" == 600 ]] || validation_rc=1
|
|
[[ "$stdout_fd_mode_after" == 600 ]] || validation_rc=1
|
|
[[ "$stdout_size_after" == "$stdout_fd_size_after" ]] || validation_rc=1
|
|
[[ "$stdout_mtime_after" == "$stdout_fd_mtime_after" ]] || validation_rc=1
|
|
[[ "$stderr_identity_after" == "$stderr_identity_before" ]] || validation_rc=1
|
|
[[ "$stderr_identity_after" == "$stderr_fd_identity_after" ]] || validation_rc=1
|
|
[[ "$stderr_nlink_after" == 1 ]] || validation_rc=1
|
|
[[ "$stderr_fd_nlink_after" == 1 ]] || validation_rc=1
|
|
[[ "$stderr_type_after" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stderr_fd_type_after" == 'regular file' ]] || validation_rc=1
|
|
[[ "$stderr_owner_after" == 0:0 ]] || validation_rc=1
|
|
[[ "$stderr_fd_owner_after" == 0:0 ]] || validation_rc=1
|
|
[[ "$stderr_mode_after" == 600 ]] || validation_rc=1
|
|
[[ "$stderr_fd_mode_after" == 600 ]] || validation_rc=1
|
|
[[ "$stderr_size_after" == "$stderr_fd_size_after" ]] || validation_rc=1
|
|
[[ "$stderr_mtime_after" == "$stderr_fd_mtime_after" ]] || validation_rc=1
|
|
if (( validation_rc == 0 )); then
|
|
_k3slra1_capture_file_hex "$stdout_path" 16 stdout_hex || validation_rc=1
|
|
_k3slra1_capture_file_hex "$stderr_path" 16 stderr_hex || validation_rc=1
|
|
[[ "$stdout_hex" == 6f6b0a ]] || validation_rc=1
|
|
[[ -z "$stderr_hex" ]] || validation_rc=1
|
|
(( child_rc == 0 )) || validation_rc=1
|
|
fi
|
|
_k3slra1_remove_owned_capture "$stdout_path" "$stdout_identity_before" || cleanup_rc=1
|
|
_k3slra1_remove_owned_capture "$stderr_path" "$stderr_identity_before" || cleanup_rc=1
|
|
if _k3slra1_metadata_fields "$capture_root" parent_identity_after parent_nlink_after parent_size_after parent_mtime_after parent_type_after parent_owner_after parent_mode_after; then
|
|
:
|
|
else
|
|
cleanup_rc=1
|
|
fi
|
|
[[ "$parent_identity_after" == "$parent_identity_before" ]] || cleanup_rc=1
|
|
(( cleanup_rc == 0 )) || return 1
|
|
case "${_capture_signal-0}" in
|
|
130|143) return "$_capture_signal" ;;
|
|
esac
|
|
(( validation_rc == 0 )) || return 1
|
|
}
|
|
|
|
_k3slra1_remove_owned_capture() {
|
|
local path="${1-}" expected_identity="${2-}" canonical=''
|
|
local identity='' nlink='' size='' mtime='' type='' owner='' mode=''
|
|
(( $# == 2 )) || return 1
|
|
[[ -n "$expected_identity" ]] || return 1
|
|
_k3slra1_canonical_path "$path" canonical || return 1
|
|
[[ "$canonical" == "$path" ]] || return 1
|
|
_k3slra1_metadata_fields "$path" identity nlink size mtime type owner mode || return 1
|
|
[[ "$identity" == "$expected_identity" ]] || return 1
|
|
[[ "$nlink" =~ ^[1-9][0-9]*$ ]] || return 1
|
|
[[ "$type" == 'regular file' ]] || return 1
|
|
_k3slra1_command /usr/bin/unlink "$path" >/dev/null 2>&1 || return 1
|
|
[[ ! -e "$path" ]] || return 1
|
|
[[ ! -L "$path" ]]
|
|
}
|
|
|
|
_k3slra1_remove_partial_capture() {
|
|
local path="${1-}" expected_device="${2-}" expected_identity="${3-}" canonical=''
|
|
local identity='' nlink='' size='' mtime='' type='' owner='' mode=''
|
|
(( $# == 3 )) || return 1
|
|
_k3slra1_canonical_path "$path" canonical || return 1
|
|
[[ "$canonical" == "$path" ]] || return 1
|
|
_k3slra1_metadata_fields "$path" identity nlink size mtime type owner mode || return 1
|
|
[[ "$identity" == "$expected_identity" ]] || return 1
|
|
[[ "$type" == 'regular file' ]] || return 1
|
|
[[ "$nlink" == 1 ]] || return 1
|
|
[[ "$owner" == 0:0 ]] || return 1
|
|
[[ "$mode" == 600 ]] || return 1
|
|
[[ "${identity%%:*}" == "$expected_device" ]] || return 1
|
|
_k3slra1_command /usr/bin/unlink "$path" >/dev/null 2>&1 || return 1
|
|
[[ ! -e "$path" ]] || return 1
|
|
[[ ! -L "$path" ]]
|
|
}
|
|
|
|
_k3slra1_stderr_open_boundary() {
|
|
:
|
|
}
|
|
|
|
_k3slra1_sqlite_stdout_stage() {
|
|
local database="${1-}" capture_root="${2-}" stdout_path="${3-}" stderr_path="${4-}"
|
|
local _stage_parent_identity='' _stage_parent_nlink='' _stage_parent_size=''
|
|
local _stage_parent_mtime='' _stage_parent_type='' _stage_parent_owner='' _stage_parent_mode=''
|
|
local _stage_parent_fd_identity='' _stage_parent_fd_nlink='' _stage_parent_fd_size=''
|
|
local _stage_parent_fd_mtime='' _stage_parent_fd_type='' _stage_parent_fd_owner='' _stage_parent_fd_mode=''
|
|
local _stage_stdout_identity='' _stage_stdout_nlink='' _stage_stdout_size=''
|
|
local _stage_stdout_mtime='' _stage_stdout_type='' _stage_stdout_owner='' _stage_stdout_mode=''
|
|
local _stage_stdout_fd_identity='' _stage_stdout_fd_nlink='' _stage_stdout_fd_size=''
|
|
local _stage_stdout_fd_mtime='' _stage_stdout_fd_type='' _stage_stdout_fd_owner='' _stage_stdout_fd_mode=''
|
|
local stage_rc=1 cleanup_rc=0 validation_rc=0
|
|
(( $# == 4 )) || return 1
|
|
if _k3slra1_metadata_fields "$capture_root" _stage_parent_identity _stage_parent_nlink _stage_parent_size _stage_parent_mtime _stage_parent_type _stage_parent_owner _stage_parent_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_fd_metadata_fields "/proc/${BASHPID}/fd/6" _stage_parent_fd_identity _stage_parent_fd_nlink _stage_parent_fd_size _stage_parent_fd_mtime _stage_parent_fd_type _stage_parent_fd_owner _stage_parent_fd_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_metadata_fields "$stdout_path" _stage_stdout_identity _stage_stdout_nlink _stage_stdout_size _stage_stdout_mtime _stage_stdout_type _stage_stdout_owner _stage_stdout_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
if _k3slra1_fd_metadata_fields "/proc/${BASHPID}/fd/7" _stage_stdout_fd_identity _stage_stdout_fd_nlink _stage_stdout_fd_size _stage_stdout_fd_mtime _stage_stdout_fd_type _stage_stdout_fd_owner _stage_stdout_fd_mode; then
|
|
:
|
|
else
|
|
validation_rc=1
|
|
fi
|
|
[[ "$_stage_parent_identity" == "$_stage_parent_fd_identity" ]] || validation_rc=1
|
|
[[ "$_stage_parent_type" == directory ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_type" == directory ]] || validation_rc=1
|
|
[[ "$_stage_parent_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_owner" == 0:0 ]] || validation_rc=1
|
|
[[ "$_stage_parent_mode" == 700 ]] || validation_rc=1
|
|
[[ "$_stage_parent_fd_mode" == 700 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_identity" == "$_stage_stdout_fd_identity" ]] || validation_rc=1
|
|
[[ "$_stage_stdout_type" == 'regular file' ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_type" == 'regular file' ]] || validation_rc=1
|
|
[[ "$_stage_stdout_nlink" == 1 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_nlink" == 1 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_size" == 0 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_fd_size" == 0 ]] || validation_rc=1
|
|
[[ "$_stage_stdout_identity" != "$_stage_parent_identity" ]] || validation_rc=1
|
|
if (( validation_rc == 0 )); then
|
|
if _k3slra1_stderr_open_boundary; then
|
|
if _k3slra1_sqlite_capture_transaction "$database" "$capture_root" "$stdout_path" "$stderr_path" 8>"$stderr_path"; then
|
|
stage_rc=0
|
|
else
|
|
stage_rc=$?
|
|
fi
|
|
fi
|
|
fi
|
|
if (( _capture_entered == 0 )); then
|
|
_k3slra1_remove_partial_capture "$stdout_path" "${_stage_parent_identity%%:*}" "$_stage_stdout_identity" || cleanup_rc=1
|
|
fi
|
|
(( cleanup_rc == 0 )) || return 1
|
|
case "$stage_rc" in
|
|
0)
|
|
case "${_capture_signal-0}" in
|
|
130|143) return "$_capture_signal" ;;
|
|
esac
|
|
(( validation_rc == 0 )) || return 1
|
|
return 0
|
|
;;
|
|
130|143) return "$stage_rc" ;;
|
|
*)
|
|
if (( _capture_entered == 0 )); then
|
|
case "${_capture_signal-0}" in
|
|
130|143) return "$_capture_signal" ;;
|
|
esac
|
|
fi
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_k3slra1_sqlite_quick_check() (
|
|
local bundle="${1-}" layout="${2-}" capture_root="${3-}" database_relative=''
|
|
local stdout_path='' stderr_path='' transaction_rc=1
|
|
local capture_canonical='' capture_identity='' capture_nlink='' capture_size='' capture_mtime=''
|
|
local capture_type='' capture_owner='' capture_mode=''
|
|
local _capture_entered=0 _capture_signal=0
|
|
(( $# == 3 )) || return 1
|
|
case "$layout" in
|
|
canonical) database_relative="$K3SLRA1_CANONICAL_DATABASE" ;;
|
|
legacy) database_relative="$K3SLRA1_LEGACY_DATABASE" ;;
|
|
*) return 1 ;;
|
|
esac
|
|
stdout_path="${capture_root}/sqlite.stdout"
|
|
stderr_path="${capture_root}/sqlite.stderr"
|
|
_k3slra1_canonical_path "$capture_root" capture_canonical || return 1
|
|
[[ "$capture_canonical" == "$capture_root" ]] || return 1
|
|
_k3slra1_metadata_fields "$capture_root" capture_identity capture_nlink capture_size capture_mtime capture_type capture_owner capture_mode || return 1
|
|
[[ "$capture_type" == directory ]] || return 1
|
|
[[ "$capture_owner" == 0:0 ]] || return 1
|
|
[[ "$capture_mode" == 700 ]] || return 1
|
|
[[ ! -e "$stdout_path" ]] || return 1
|
|
[[ ! -L "$stdout_path" ]] || return 1
|
|
[[ ! -e "$stderr_path" ]] || return 1
|
|
[[ ! -L "$stderr_path" ]] || return 1
|
|
umask 077
|
|
set -o noclobber
|
|
trap '_capture_signal=130; if (( transaction_rc == 0 )); then transaction_rc=130; fi' INT
|
|
trap '_capture_signal=143; if (( transaction_rc == 0 )); then transaction_rc=143; fi' TERM
|
|
if _k3slra1_sqlite_stdout_stage "${bundle}/pre/${database_relative#./}" "$capture_root" "$stdout_path" "$stderr_path" 2>/dev/null 6<"$capture_root" 7>"$stdout_path"; then
|
|
transaction_rc=0
|
|
else
|
|
transaction_rc=$?
|
|
fi
|
|
if (( _capture_signal != 0 && transaction_rc == 0 )); then
|
|
transaction_rc=$_capture_signal
|
|
fi
|
|
case "$transaction_rc" in
|
|
0) return 0 ;;
|
|
130|143) return "$transaction_rc" ;;
|
|
*) return 1 ;;
|
|
esac
|
|
)
|