122 lines
5.3 KiB
Bash
Executable File
122 lines
5.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ============================================================================
|
|
# qcrows-inspect — Read QCrows image metadata without full extraction
|
|
# ============================================================================
|
|
set -euo pipefail
|
|
|
|
CYAN='\033[0;36m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
FILE="${1:-}"
|
|
[[ -z "$FILE" ]] && { echo "Usage: qcrows-inspect <file.qcrows>"; exit 1; }
|
|
[[ ! -f "$FILE" ]] && { echo "File not found: $FILE" >&2; exit 1; }
|
|
|
|
# ─── Archive extraction helpers (single dispatch point) ──────────────────────
|
|
|
|
# Extract a file from the archive to stdout
|
|
tar_extract() {
|
|
local archive="$1"; shift
|
|
if [[ "$archive" == *.gz ]]; then
|
|
tar xzf "$archive" "$@" 2>/dev/null
|
|
else
|
|
tar xf "$archive" "$@" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# List archive contents to stdout
|
|
tar_list() {
|
|
local archive="$1"
|
|
if [[ "$archive" == *.gz ]]; then
|
|
tar tzf "$archive" 2>/dev/null
|
|
else
|
|
tar tf "$archive" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# ─── Read values from TOML content ──────────────────────────────────────────
|
|
|
|
get_val() {
|
|
echo "$META" | grep -E "^${1}" | head -1 | sed 's/.*= *//' | tr -d '"' | tr -d ' '
|
|
}
|
|
|
|
get_array() {
|
|
echo "$META" | grep -E "^${1}" | head -1 | sed 's/.*= *//' | tr -d '[]"' | sed 's/, */, /g'
|
|
}
|
|
|
|
get_section_val() {
|
|
local section="$1" key="$2"
|
|
echo "$META" | awk "/\[.*${section}.*\]/{found=1} found && /^${key}/{print; exit}"
|
|
}
|
|
|
|
# ─── Read metadata.toml ────────────────────────────────────────────────────
|
|
|
|
META="$(tar_extract "$FILE" -O ./metadata.toml 2>/dev/null || tar_extract "$FILE" -O metadata.toml 2>/dev/null || echo "")"
|
|
if [[ -z "$META" ]]; then
|
|
echo "Error: Could not read metadata.toml from archive" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Format output ─────────────────────────────────────────────────────────
|
|
FMT=" %-16s ${CYAN}%s${NC}\n"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}QCrows Image Inspection${NC}"
|
|
echo -e "${YELLOW}──────────────────────────────────────────────────────${NC}"
|
|
|
|
printf "$FMT" "Name:" "$(get_val 'name')"
|
|
printf "$FMT" "Version:" "$(get_val 'version')"
|
|
printf "$FMT" "Description:" "$(echo "$META" | grep '^description' | head -1 | sed "s/.*= *//;s/^\"//;s/\"$//")"
|
|
printf "$FMT" "Arch:" "$(get_val 'arch')"
|
|
printf "$FMT" "Created:" "$(get_val 'created_at')"
|
|
echo ""
|
|
echo -e "${YELLOW}Compatibility:${NC}"
|
|
printf "$FMT" "Hypervisors:" "$(get_array 'hypervisors')"
|
|
printf "$FMT" "Kata min:" "$(get_val 'kata_runtime_min')"
|
|
echo ""
|
|
|
|
# ─── Component details ─────────────────────────────────────────────────────
|
|
echo -e "${YELLOW}Components:${NC}"
|
|
|
|
k_included=$(get_section_val kernel included | sed 's/.*= *//' | tr -d ' ' || echo "false")
|
|
k_version=$(get_section_val kernel version | sed 's/.*= *//' | tr -d '"' || echo "unknown")
|
|
k_format=$(get_section_val kernel format | sed 's/.*= *//' | tr -d '"' || echo "vmlinuz")
|
|
k_size=$(get_section_val kernel size_mb | sed 's/.*= *//' | tr -d ' ' || echo "0")
|
|
|
|
printf "$FMT" "Kernel:" "${k_version} (${k_format})"
|
|
printf "$FMT" "Kernel size:" "${k_size} MiB"
|
|
printf "$FMT" "Kernel config:" "$(get_section_val kernel config_path | sed 's/.*= *//' | tr -d '"' || echo "missing")"
|
|
printf "$FMT" "Initrd:" "$(get_val 'type') (included=$(get_val 'included'))"
|
|
printf "$FMT" "Rootfs:" "$(get_val 'type')"
|
|
printf "$FMT" "Rootfs size:" "$(get_val 'size_mb') MiB"
|
|
|
|
boot_included=$(get_section_val boot_params included | sed 's/.*= *//' | tr -d ' ' || echo "false")
|
|
printf "$FMT" "Boot params:" "${boot_included}"
|
|
echo ""
|
|
|
|
# ─── Build info ─────────────────────────────────────────────────────────────
|
|
BUILD_SYS=$(get_section_val build system | sed 's/.*= *//' | tr -d '"' || true)
|
|
if [[ -n "$BUILD_SYS" ]]; then
|
|
echo -e "${YELLOW}Build:${NC}"
|
|
printf "$FMT" "System:" "$BUILD_SYS"
|
|
printf "$FMT" "Timestamp:" "$(get_section_val build timestamp | sed 's/.*= *//' | tr -d '"' || echo 'N/A')"
|
|
echo ""
|
|
fi
|
|
|
|
# ─── Menu entry ─────────────────────────────────────────────────────────────
|
|
MENU="$(tar_extract "$FILE" -O ./menu.toml 2>/dev/null || tar_extract "$FILE" -O menu.toml 2>/dev/null || echo "")"
|
|
if [[ -n "$MENU" ]]; then
|
|
menu_label=$(echo "$MENU" | grep '^label' | head -1 | sed 's/.*= *//' | tr -d '"' || echo "N/A")
|
|
menu_cat=$(echo "$MENU" | grep '^category' | head -1 | sed 's/.*= *//' | tr -d '"' || echo "N/A")
|
|
echo -e "${YELLOW}Menu Entry:${NC}"
|
|
printf "$FMT" "Label:" "$menu_label"
|
|
printf "$FMT" "Category:" "$menu_cat"
|
|
echo ""
|
|
fi
|
|
|
|
# ─── Archive contents (direct pipeline — no subshell loop) ──────────────────
|
|
echo -e "${YELLOW}Archive Contents:${NC}"
|
|
tar_list "$FILE" | sort | sed "s/^/ ${CYAN}/;s/$/${NC}/"
|
|
echo ""
|