From 4ae04facfacac713719bb8fabfb285321a2f2d66 Mon Sep 17 00:00:00 2001 From: Kroese Date: Sat, 8 Aug 2026 03:53:42 +0200 Subject: [PATCH] feat: Simplify WIM platform and version detection (#2108) --- src/define.sh | 87 ++------- src/image.sh | 502 ++++++++++++++++++-------------------------------- 2 files changed, 193 insertions(+), 396 deletions(-) diff --git a/src/define.sh b/src/define.sh index d6c66ece..31ce66fc 100644 --- a/src/define.sh +++ b/src/define.sh @@ -762,27 +762,23 @@ normalizeServerEdition() { edition="${edition#r2-}" case "$edition" in - "core" | "core-installation" | "server-core-installation" ) + "core" | "server-core" | "servercore" | \ + "core-installation" | "server-core-installation" ) edition="standard-core" ;; "desktop-experience" | "server-with-a-gui" | "full-installation" ) edition="standard" ;; - *"-server-core-installation" ) - edition="${edition%-server-core-installation}-core" ;; - *"-core-installation" ) + *"-server-core-installation" | *"-core-installation" ) + edition="${edition%-server-core-installation}" edition="${edition%-core-installation}-core" ;; - *"-desktop-experience" ) - edition="${edition%-desktop-experience}" ;; - *"-server-with-a-gui" ) - edition="${edition%-server-with-a-gui}" ;; - *"-full-installation" ) + *"-desktop-experience" | *"-server-with-a-gui" | *"-full-installation" ) + edition="${edition%-desktop-experience}" + edition="${edition%-server-with-a-gui}" edition="${edition%-full-installation}" ;; esac edition="${edition#server-}" edition="${edition#server}" - [ "$edition" == "core" ] && edition="standard-core" - echo "$edition" return 0 } @@ -794,24 +790,13 @@ normalizeServerEditionID() { edition=$(normalizeServerEdition "$1") || return 1 case "$edition" in - "" | "standard" | "serverstandard" ) edition="" ;; - "core" | "standard-core" | "standardcore" | "serverstandardcore" ) edition="standard-core" ;; - "datacenter" | "serverdatacenter" ) edition="datacenter" ;; - "datacenter-core" | "datacentercore" | "serverdatacentercore" ) edition="datacenter-core" ;; - "datacenter-azure" | "datacenter-azure-edition" | "datacenterazureedition" | \ - "serverdatacenterazureedition" | "serverturbine" ) edition="datacenter-azure" ;; - "datacenter-azure-core" | "datacenter-azure-edition-core" | \ - "datacenterazureeditioncore" | "serverdatacenterazureeditioncore" | \ - "serverturbinecore" ) edition="datacenter-azure-core" ;; - "enterprise" | "serverenterprise" ) edition="enterprise" ;; - "enterprise-core" | "enterprisecore" | "serverenterprisecore" ) edition="enterprise-core" ;; - "web" | "serverweb" ) edition="web" ;; - "web-core" | "webcore" | "serverwebcore" ) edition="web-core" ;; - "foundation" | "serverfoundation" ) edition="foundation" ;; - "essentials" | "serveressentials" ) edition="essentials" ;; - # Keep unrecognized internal edition IDs deterministic and unique. - # Known aliases above only provide stable, friendlier public names. - * ) : ;; + "standard" ) edition="" ;; + "standardcore" | "datacentercore" | "enterprisecore" | "webcore" ) + edition="${edition%core}-core" ;; + "datacenter-azure-edition" | "datacenterazureedition" ) + edition="datacenter-azure" ;; + "datacenter-azure-edition-core" | "datacenterazureeditioncore" ) + edition="datacenter-azure-core" ;; esac echo "$edition" @@ -842,45 +827,6 @@ getServerEditionID() { return 0 } -getEditionOrder() { - - local id="${1,,}" - - case "$id" in - "win20"* ) - printf '%s\n' \ - "|default|@default" \ - "-datacenter|datacenter|datacenter datacenter-*" \ - "-datacenter-azure|datacenter|datacenter-azure" \ - "-enterprise|enterprise|enterprise enterprise-*" \ - "-web|web|web web-*" \ - "-foundation|foundation|foundation foundation-*" \ - "-essentials|essentials|essentials essentials-*" \ - "-standard-core|standard-core|standard-core standard-core-*" \ - "-datacenter-core|datacenter-core|datacenter-core datacenter-core-*" \ - "-datacenter-azure-core|datacenter-core|datacenter-azure-core" \ - "-enterprise-core|enterprise-core|enterprise-core enterprise-core-*" \ - "-web-core|web-core|web-core web-core-*" \ - "-hv|hv|hv hv-*" - ;; - * ) - printf '%s\n' \ - "-enterprise|enterprise|enterprise enterprise-*" \ - "-ultimate|ultimate|ultimate ultimate-*" \ - "|default|@default n pro pro-* professional professional-* business business-*" \ - "-iot|iot|iot iot-* enterprise-iot enterprise-iot-*" \ - "-ltsc|ltsc|ltsc ltsc-* enterprise-ltsc enterprise-ltsc-*" \ - "-education|education|education education-* pro-education pro-education-*" \ - "-home|home|home home-*" \ - "-home-premium|home|home-premium home-premium-*" \ - "-home-basic|home|home-basic home-basic-*" \ - "-starter|starter|starter starter-*" - ;; - esac - - return 0 -} - getVersion() { local name="$1" @@ -899,8 +845,7 @@ getVersion() { [ -n "$evaluation" ] && id+="$evaluation" fi ;; - "win2025"* | "win2022"* | "win2019"* | "win2016"* | \ - "win2012"* | "win2008"* | "win2003"* ) + "win20"* ) if [[ "${name,,}" == *"hyper-v server"* ]]; then id+="-hv" elif edition=$(getServerEditionID "$name" "$id"); then @@ -1453,7 +1398,7 @@ getLink4() { "win2008r2" ) size=3166584832 sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8" - url="en_windows_server_2008_r2_with_sp1_x64_dvd_617601_202006/en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso" + url="en_windows_server_2008_r2_with_sp1_x64_dvd_617601_202405/en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso" ;; "win7x64" | "win7x64-ultimate" ) size=3320903680 diff --git a/src/image.sh b/src/image.sh index ea2e7ade..5b498f6e 100644 --- a/src/image.sh +++ b/src/image.sh @@ -4,39 +4,17 @@ set -Eeuo pipefail getVersions() { local xml="$1" - local versions_name="$2" - local bases_name="$3" - local groups_name="$4" - local indexes_name="$5" - local -n bases_ref="$bases_name" - local -n groups_ref="$groups_name" - local -n indexes_ref="$indexes_name" - local -n versions_ref="$versions_name" - - local platform image_count records record_count=0 - local image_index display product image edition_id - local install_type flags candidate candidate_id - local candidate_base evaluation key name structured + local image_index image edition_id + local install_type candidate_base + local candidate candidate_id flags + local evaluation key name structured + local platform records display product local separator=$'\x1f' - - bases_ref=() - groups_ref=() - indexes_ref=() - versions_ref=() + local -A indexes=() platform=$(getPlatform "$xml") || return 1 - image_count=$(xmlstarlet sel -T -t -v 'count(/WIM/IMAGE)' - 2>/dev/null <<< "$xml") || return 1 - if [[ ! "$image_count" =~ ^[0-9]+$ ]]; then - error "Invalid image count in WIM metadata: '$image_count'" - return 1 - fi - - (( image_count > 0 )) || return 0 - - # Keep one compact record per image. XML 1.0 cannot contain U+001F, so it - # can safely separate fields while all edition logic remains in Bash. if ! records=$(xmlstarlet sel \ -T -t \ -m '/WIM/IMAGE' \ @@ -54,8 +32,6 @@ getVersions() { while IFS="$separator" read -r image_index display product image edition_id install_type flags; do - ((record_count += 1)) - [ -n "$image_index" ] || continue if [[ ! "$image_index" =~ ^[1-9][0-9]*$ ]]; then @@ -66,47 +42,41 @@ getVersions() { candidate_id="" candidate_base="" - # NAME normally contains the most precise edition identifier (including - # Server Core), while DISPLAYNAME is the best fallback for other images. for candidate in "$image" "$display" "$product"; do [[ "$candidate" == *"Operating System"* ]] && continue [ -n "$candidate" ] || continue - candidate_base=$(fromName "$candidate" "$platform") candidate_id=$(getVersion "$candidate" "$platform") + candidate_base="${candidate_id%%-*}" - [ -n "$candidate_base" ] && [ -n "$candidate_id" ] && break + [ -n "$candidate_id" ] && break done - # Preserve NAME precedence, but allow a recognized DISPLAYNAME edition to - # refine an otherwise generic family name. + # NAME sometimes contains only the Windows family while DISPLAYNAME + # contains the actual edition. Use the more specific DISPLAYNAME then. if [ -n "$candidate_base" ] && [ -n "$candidate_id" ] && [ -n "$display" ]; then name=$(normalizeEdition "$(printVersion "$candidate_base" "")") || return 1 candidate=$(normalizeEdition "$candidate") || return 1 if [ "$candidate" = "$name" ]; then - structured=$(getVersion "$display" "$platform") - if [ "$(fromName "$display" "$platform")" = "$candidate_base" ] && - [ -n "$structured" ] && [[ "${structured%-eval}" != "$candidate_base" ]] && - [[ "$(getVersionPriority "$structured" "$candidate_base")" != "other" ]]; then + if [ -n "$structured" ] && [ "${structured%%-*}" = "$candidate_base" ] && + [[ "${structured%-eval}" != "$candidate_base" ]] && + [ "$(getEditionRank "$structured")" -lt 99 ]; then candidate_id="$structured" fi - fi + fi if [ -z "$candidate_base" ] || [ -z "$candidate_id" ]; then - name="${display:-${image:-$product}}" [ -n "$name" ] && warn "Unknown image name: '$name'" - continue - fi evaluation="" @@ -122,10 +92,9 @@ getVersions() { key="${candidate_id,,}" - # Some client media use the same friendly name-derived ID for distinct - # editions. Preserve the established unsuffixed Pro ID, and use the - # structured edition metadata only to disambiguate a collision. - if [[ -v "indexes_ref[$key]" ]]; then + # Friendly names can collapse two different images to the same ID. + # Structured metadata is only needed to disambiguate that collision. + if [[ -v "indexes[$key]" ]]; then structured="" @@ -136,9 +105,6 @@ getVersions() { "win20"* ) structured=$(normalizeServerEditionID "${flags:-$edition_id}") || return 1 - # Some media use the same EDITIONID for Core and Desktop images. - # INSTALLATIONTYPE provides the structural distinction without - # requiring a hardcoded marketing name. if [[ "${install_type,,}" == *"core"* && "$structured" != *"-core" ]]; then structured+="-core" fi @@ -152,262 +118,187 @@ getVersions() { fi - if [[ -v "indexes_ref[$key]" ]]; then - warn "Duplicate image identity '$candidate_id' at indexes ${indexes_ref[$key]} and $image_index" + if [[ -v "indexes[$key]" ]]; then + warn "Duplicate image identity '$candidate_id' at indexes ${indexes[$key]} and $image_index" continue fi - indexes_ref["$key"]="$image_index" - versions_ref+=( "$candidate_id" ) - bases_ref+=( "$candidate_base" ) - groups_ref+=( "$(getVersionPriority "$candidate_id" "$candidate_base")" ) + indexes["$key"]="$image_index" + printf '%s\t%s\n' "$candidate_id" "$image_index" done <<< "$records" - if (( record_count != image_count )); then - error "Expected $image_count image records in WIM metadata, found $record_count!" - return 1 - fi - return 0 } -getVersionPriority() { +getEditionRank() { local id="${1,,}" - local base="${2,,}" - - local entry priority patterns pattern - local result="other" score best_score=-1 - local -a order=() pattern_list=() + local base="${id%%-*}" + local edition id="${id%-eval}" - - mapfile -t order < <(getEditionOrder "$base") - - local edition="${id#"$base"}" + edition="${id#"$base"}" edition="${edition#-}" - # Use the most specific matching pattern. This prevents broad patterns - # such as enterprise-* from taking precedence over enterprise-iot-*. - for entry in "${order[@]}"; do - - IFS='|' read -r _ priority patterns <<< "$entry" - read -r -a pattern_list <<< "$patterns" - - for pattern in "${pattern_list[@]}"; do - - if [ "$pattern" = "@default" ]; then - [ -z "$edition" ] || continue - score=1 - elif [[ "$pattern" == *"*" ]]; then - local prefix="${pattern%\*}" - [[ "$edition" == "$prefix"* ]] || continue - score="${#pattern}" - elif [ "$edition" = "$pattern" ]; then - score="${#pattern}" - else - continue - fi - - if (( score > best_score )); then - result="$priority" - best_score="$score" - fi - - done - - done - - echo "$result" - return 0 + case "$base" in + "win20"* ) + case "$edition" in + "" ) echo 0 ;; + "datacenter-azure-core" | "datacenter-azure-core-"* | \ + "datacenter-core" | "datacenter-core-"* ) echo 7 ;; + "enterprise-core" | "enterprise-core-"* ) echo 8 ;; + "web-core" | "web-core-"* ) echo 9 ;; + "standard-core" | "standard-core-"* ) echo 6 ;; + "datacenter" | "datacenter-"* ) echo 1 ;; + "enterprise" | "enterprise-"* ) echo 2 ;; + "web" | "web-"* ) echo 3 ;; + "foundation" | "foundation-"* ) echo 4 ;; + "essentials" | "essentials-"* ) echo 5 ;; + "hv" | "hv-"* ) echo 10 ;; + * ) echo 99 ;; + esac + ;; + * ) + case "$edition" in + "enterprise-iot" | "enterprise-iot-"* | "iot" | "iot-"* ) echo 3 ;; + "enterprise-ltsc" | "enterprise-ltsc-"* | "ltsc" | "ltsc-"* ) echo 4 ;; + "pro-education" | "pro-education-"* | "education" | "education-"* ) echo 5 ;; + "enterprise" | "enterprise-"* ) echo 0 ;; + "ultimate" | "ultimate-"* ) echo 1 ;; + "" | "n" | "pro" | "pro-"* | "professional" | "professional-"* | \ + "business" | "business-"* ) echo 2 ;; + "home" | "home-"* ) echo 6 ;; + "starter" | "starter-"* ) echo 7 ;; + * ) echo 99 ;; + esac + ;; + esac } selectVersion() { - local versions_name="$1" - local indexes_name="$2" - local preferred_name="$3" - local result_name="$4" - local index_name="$5" + local wanted="$1" + shift - local -a candidates=() - local -n index_map="$indexes_name" - local -n version_list="$versions_name" - local -n selected_version="$result_name" - local -n preference_list="$preferred_name" - local -n selected_image_index="$index_name" - local wanted candidate match + local candidate record id index + local -a candidates=("$wanted") - # A detected edition is only selectable when a matching answer file can - # actually be staged for it. - for wanted in "${preference_list[@]}"; do + # Normal and Evaluation variants of the same edition are compatible. + if [[ "${wanted,,}" == *"-eval" ]]; then + candidates+=("${wanted%-eval}") + else + candidates+=("$wanted-eval") + fi - [ -n "$wanted" ] || continue - mapfile -t candidates < <(getCompatibleVersions "$wanted") + for candidate in "${candidates[@]}"; do + for record in "$@"; do - for candidate in "${candidates[@]}"; do - - match=$(hasVersion "$candidate" "${version_list[@]}") || continue - - hasAnswerFile "$match" || continue - - local key="${match,,}" - selected_version="$match" - selected_image_index="${index_map[$key]}" + IFS=$'\t' read -r id index <<< "$record" + [[ "${id,,}" == "${candidate,,}" ]] || continue + hasAnswerFile "$id" || continue + printf '%s\n%s\n' "$id" "$index" return 0 done - done return 1 } -getCompatibleVersions() { - - local wanted="$1" - - printf '%s\n' "$wanted" - - # Treat normal and Evaluation variants of the same edition as compatible. - # The exact requested variant is always checked first. - if [[ "${wanted,,}" == *"-eval" ]]; then - printf '%s\n' "${wanted%-eval}" - else - printf '%s\n' "$wanted-eval" - fi - -} - -selectEdition() { - - local versions_name="$1" - local bases_name="$2" - local groups_name="$3" - local indexes_name="$4" - local suggested="$5" - local result_name="$6" - local index_name="$7" - local normalize_name="$8" - local order_name="$9" - - local -A seen=() - local -a preferred=() - local -n edition_bases="$bases_name" - local -n edition_order="$order_name" - local -n edition_groups="$groups_name" - local -n edition_versions="$versions_name" - local base edition entry suffix priority i - - # Selection precedence is explicit EDITION, source suggestion, canonical - # edition order, then noncanonical editions from the same priority groups. - if [ -n "$EDITION" ]; then - - for base in "${edition_bases[@]}"; do - edition=$("$normalize_name" "$EDITION" "$base") || return 1 - preferred+=("$base${edition:+-$edition}") - done - - if selectVersion "$versions_name" "$indexes_name" preferred "$result_name" "$index_name"; then - return 0 - fi - - warn "edition '$EDITION' is not supported by this image, using automatic selection instead." - - fi - - if [ -n "$suggested" ]; then - - preferred=("$suggested") - - if selectVersion "$versions_name" "$indexes_name" preferred "$result_name" "$index_name"; then - return 0 - fi - - fi - - # First try each canonical edition in its configured order. - preferred=() - - for entry in "${edition_order[@]}"; do - - IFS='|' read -r suffix _ _ <<< "$entry" - - for base in "${edition_bases[@]}"; do - preferred+=("$base$suffix") - done - - done - - if selectVersion "$versions_name" "$indexes_name" preferred "$result_name" "$index_name"; then - return 0 - fi - - # Then try noncanonical editions from the same preference groups. - seen=() - preferred=() - - for entry in "${edition_order[@]}"; do - - IFS='|' read -r _ priority _ <<< "$entry" - - [[ -v "seen[$priority]" ]] && continue - seen["$priority"]="Y" - - for ((i=0;i<${#edition_versions[@]};i++)); do - - [[ "${edition_groups[$i]}" == "$priority" ]] || continue - preferred+=("${edition_versions[$i]}") - - done - - done - - selectVersion "$versions_name" "$indexes_name" preferred "$result_name" "$index_name" -} - detectVersion() { local xml="$1" - local suggested="${2:-}" - local -a bases=() - local -a groups=() - local -a versions=() - local -A image_indexes=() - local -a selection_order=() - local result="" index="" + local normalize="normalizeEditionID" + local output record id index base edition suffix + local -a images=() bases=() order=() - getVersions "$xml" versions bases groups image_indexes || return + output=$(getVersions "$xml") || return + [ -n "$output" ] && mapfile -t images <<< "$output" - if [ "${#versions[@]}" -eq 0 ]; then - printf '%s\n%s\n' "$result" "$index" + if [ "${#images[@]}" -eq 0 ]; then + printf '\n\n' return 0 fi - local normalize="normalizeEditionID" + for record in "${images[@]}"; do + IFS=$'\t' read -r id _ <<< "$record" + bases+=("${id%%-*}") + done case "${bases[0],,}" in "win20"* ) - normalize="normalizeServerEditionID" ;; + normalize="normalizeServerEditionID" + order=( + "" "-datacenter" "-datacenter-azure" "-enterprise" "-web" + "-foundation" "-essentials" "-standard-core" "-datacenter-core" + "-datacenter-azure-core" "-enterprise-core" "-web-core" "-hv" + ) ;; + * ) + order=( + "-enterprise" "-ultimate" "" "-iot" "-ltsc" "-education" + "-home" "-home-premium" "-home-basic" "-starter" + ) ;; esac - mapfile -t selection_order < <(getEditionOrder "${bases[0]}") + # An explicit EDITION always gets first choice. + if [ -n "$EDITION" ]; then - if selectEdition versions bases groups image_indexes "$suggested" result index "$normalize" selection_order; then - printf '%s\n%s\n' "$result" "$index" + for base in "${bases[@]}"; do + + edition=$("$normalize" "$EDITION" "$base") || return 1 + + if output=$(selectVersion "$base${edition:+-$edition}" "${images[@]}"); then + printf '%s\n' "$output" + return 0 + fi + + done + + warn "edition '$EDITION' is not supported by this image, using automatic selection instead." + fi + + # Prefer the normal editions in their established order. + for suffix in "${order[@]}"; do + for base in "${bases[@]}"; do + + if output=$(selectVersion "$base$suffix" "${images[@]}"); then + printf '%s\n' "$output" + return 0 + fi + + done + done + + # Otherwise keep the established family preference for noncanonical + # editions, while preserving WIM order within the same family. + local rank best_rank=99 result="" result_index="" + + for record in "${images[@]}"; do + + IFS=$'\t' read -r id index <<< "$record" + hasAnswerFile "$id" || continue + + rank=$(getEditionRank "$id") + (( rank < best_rank )) || continue + + best_rank="$rank" + result="$id" + result_index="$index" + + done + + if [ -n "$result" ]; then + printf '%s\n%s\n' "$result" "$result_index" return 0 fi - # Keep the first detected image identity when no edition with a usable answer - # file was found, so manual and generic fallback handling can still continue. - result="${versions[0]}" - local key="${result,,}" - index="${image_indexes[$key]}" + # Keep the first detected identity when only manual/generic fallback remains. + IFS=$'\t' read -r id index <<< "${images[0]}" - printf '%s\n%s\n' "$result" "$index" + printf '%s\n%s\n' "$id" "$index" return 0 } @@ -513,22 +404,6 @@ getImageSize() { printf '%s\n' "$size" } -hasVersion() { - - local wanted="$1" - shift - - local actual - - for actual in "$@"; do - [[ "${actual,,}" == "${wanted,,}" ]] || continue - echo "$actual" - return 0 - done - - return 1 -} - checkPlatform() { local xml="$1" @@ -571,76 +446,53 @@ getPlatform() { local xml="$1" - local image_count invalid_count - local x86 x64 arm64 unknown value - local platform="" count=0 output - local -a counts=() + local arch current platform="" + local image_count output records + local separator=$'\x1f' if ! output=$(xmlstarlet sel \ -T -t \ -v 'count(/WIM/IMAGE)' -n \ - -v 'count(/WIM/IMAGE[count(WINDOWS/ARCH) != 1])' -n \ - -v 'count(/WIM/IMAGE/WINDOWS/ARCH[normalize-space(.)="0"])' -n \ - -v 'count(/WIM/IMAGE/WINDOWS/ARCH[normalize-space(.)="9"])' -n \ - -v 'count(/WIM/IMAGE/WINDOWS/ARCH[normalize-space(.)="12"])' -n \ - -v 'count(/WIM/IMAGE/WINDOWS/ARCH[normalize-space(.)!="0" and normalize-space(.)!="9" and normalize-space(.)!="12"])' -n \ + -m '/WIM/IMAGE' \ + -v 'count(WINDOWS/ARCH)' -o "$separator" \ + -v 'normalize-space(WINDOWS/ARCH)' -n \ - 2>/dev/null <<< "$xml"); then error "Failed to read architecture metadata from WIM image!" return 1 fi - mapfile -t counts <<< "$output" + image_count="${output%%$'\n'*}" - if (( ${#counts[@]} != 6 )); then - error "Failed to read architecture counts from WIM metadata!" - return 1 - fi - - for value in "${counts[@]}"; do - if [[ ! "$value" =~ ^[0-9]+$ ]]; then - error "Invalid architecture count in WIM metadata: '$value'" - return 1 - fi - done - - image_count="${counts[0]}" - invalid_count="${counts[1]}" - x86="${counts[2]}" - x64="${counts[3]}" - arm64="${counts[4]}" - unknown="${counts[5]}" - - if (( image_count == 0 )); then + if [ "$image_count" = "0" ]; then error "No images were found in WIM metadata!" return 1 fi - if (( invalid_count > 0 )); then - error "Missing or duplicate architecture metadata in WIM image!" - return 1 - fi + records="${output#*$'\n'}" - if (( unknown > 0 )); then - error "Unsupported architecture value in WIM metadata!" - return 1 - fi + while IFS="$separator" read -r count arch; do - (( x86 > 0 )) && ((count += 1)) - (( x64 > 0 )) && ((count += 1)) - (( arm64 > 0 )) && ((count += 1)) + if [ "$count" != "1" ]; then + error "Missing or duplicate architecture metadata in WIM image!" + return 1 + fi - if (( count > 1 )); then - platform="mixed" - elif (( x86 > 0 )); then - platform="x86" - elif (( x64 > 0 )); then - platform="x64" - elif (( arm64 > 0 )); then - platform="arm64" - else - error "Failed to determine architecture from WIM metadata!" - return 1 - fi + case "$arch" in + "0" ) current="x86" ;; + "9" ) current="x64" ;; + "12" ) current="arm64" ;; + * ) + error "Unsupported architecture value in WIM metadata!" + return 1 ;; + esac + + if [ -z "$platform" ]; then + platform="$current" + elif [ "$platform" != "$current" ]; then + platform="mixed" + fi + + done <<< "$records" echo "$platform" return 0