mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 12:37:20 +01:00
feat: Improve image and answer file handling (#1957)
This commit is contained in:
+85
-97
@@ -268,52 +268,49 @@ removeGeneratedXML() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
generateEvalXML() {
|
generateAnswerFile() {
|
||||||
|
|
||||||
# Evaluation templates are generated from their normal counterpart so
|
|
||||||
# both variants remain identical except for evaluation-specific selectors.
|
|
||||||
|
|
||||||
local id="$1"
|
local id="$1"
|
||||||
local detected_index="${2:-}"
|
local source="$2"
|
||||||
local normal="${id::-5}"
|
local target="$3"
|
||||||
local source="/run/assets/$normal.xml"
|
local index="$4"
|
||||||
local target="/run/assets/$id.xml"
|
local type="$5"
|
||||||
local index="$detected_index" tmp
|
local remove_selector="$6"
|
||||||
|
local tmp
|
||||||
[[ "${id,,}" == *"-eval" ]] || return 1
|
|
||||||
|
|
||||||
removeGeneratedXML "$source" || return 1
|
|
||||||
|
|
||||||
if [ ! -s "$source" ]; then
|
|
||||||
source="/run/assets/${normal%%-*}.xml"
|
|
||||||
removeGeneratedXML "$source" || return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ -s "$source" ] || return 1
|
|
||||||
|
|
||||||
if [ -n "$index" ] && [[ ! "$index" =~ ^[1-9][0-9]*$ ]]; then
|
if [ -n "$index" ] && [[ ! "$index" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
error "Invalid evaluation image index: $index"
|
error "Invalid $type image index: $index"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! tmp=$(mktemp -p /run/assets ".${id}.XXXXXX"); then
|
if ! tmp=$(mktemp -p /run/assets ".${id}.XXXXXX"); then
|
||||||
error "Failed to create a temporary evaluation answer file!"
|
error "Failed to create a temporary $type answer file!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! sed \
|
local expressions
|
||||||
-e '/<ProductKey>.*<\/ProductKey>/d' \
|
|
||||||
-e '/<ProductKey>/,/<\/ProductKey>/d' \
|
if [ "$type" = "evaluation" ]; then
|
||||||
"$source" > "$tmp"; then
|
expressions=(
|
||||||
|
-e '/<ProductKey>.*<\/ProductKey>/d'
|
||||||
|
-e '/<ProductKey>/,/<\/ProductKey>/d'
|
||||||
|
)
|
||||||
|
else
|
||||||
|
expressions=(
|
||||||
|
-e '/<InstallFrom>.*<\/InstallFrom>/d'
|
||||||
|
-e '/<ProductKey>.*<\/ProductKey>/d'
|
||||||
|
-e '/<InstallFrom>/,/<\/InstallFrom>/d'
|
||||||
|
-e '/<ProductKey>/,/<\/ProductKey>/d'
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! sed "${expressions[@]}" "$source" > "$tmp"; then
|
||||||
rm -f "$tmp"
|
rm -f "$tmp"
|
||||||
error "Failed to generate evaluation answer file from $source!"
|
error "Failed to generate $type answer file from $source!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$detected_index" ]; then
|
if [ "$type" = "evaluation" ] && [ "$remove_selector" = "Y" ]; then
|
||||||
|
|
||||||
# A WIM index was detected, so replace any selector inherited from
|
|
||||||
# the normal template with the exact index from the ISO image.
|
|
||||||
if ! sed -i \
|
if ! sed -i \
|
||||||
-e '/<InstallFrom>.*<\/InstallFrom>/d' \
|
-e '/<InstallFrom>.*<\/InstallFrom>/d' \
|
||||||
-e '/<InstallFrom>/,/<\/InstallFrom>/d' \
|
-e '/<InstallFrom>/,/<\/InstallFrom>/d' \
|
||||||
@@ -322,15 +319,6 @@ generateEvalXML() {
|
|||||||
error "Failed to replace evaluation image selector!"
|
error "Failed to replace evaluation image selector!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
# No WIM was inspected, so retain the known defaults for download routes.
|
|
||||||
case "${id,,}" in
|
|
||||||
*"-ltsc-eval" ) index="1" ;;
|
|
||||||
*"-iot-eval" ) index="2" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$index" ] && ! grep -q '<InstallFrom>' "$tmp"; then
|
if [ -n "$index" ] && ! grep -q '<InstallFrom>' "$tmp"; then
|
||||||
@@ -344,7 +332,7 @@ generateEvalXML() {
|
|||||||
</InstallFrom>
|
</InstallFrom>
|
||||||
}' "$tmp"; then
|
}' "$tmp"; then
|
||||||
rm -f "$tmp"
|
rm -f "$tmp"
|
||||||
error "Failed to select evaluation image index $index!"
|
error "Failed to select $type image index $index!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -352,19 +340,59 @@ generateEvalXML() {
|
|||||||
if ! markGeneratedXML "$tmp" ||
|
if ! markGeneratedXML "$tmp" ||
|
||||||
! xmllint --nonet --noout "$tmp"; then
|
! xmllint --nonet --noout "$tmp"; then
|
||||||
rm -f "$tmp"
|
rm -f "$tmp"
|
||||||
error "Generated evaluation answer file is invalid!"
|
error "Generated $type answer file is invalid!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! chmod 644 "$tmp" || ! mv -f "$tmp" "$target"; then
|
if ! chmod 644 "$tmp" || ! mv -f "$tmp" "$target"; then
|
||||||
rm -f "$tmp"
|
rm -f "$tmp"
|
||||||
error "Failed to create evaluation answer file: $target"
|
error "Failed to create $type answer file: $target"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateEvalXML() {
|
||||||
|
|
||||||
|
# Evaluation templates are generated from their normal counterpart so
|
||||||
|
# both variants remain identical except for evaluation-specific selectors.
|
||||||
|
|
||||||
|
local id="$1"
|
||||||
|
local detected_index="${2:-}"
|
||||||
|
local normal="${id::-5}"
|
||||||
|
local source="/run/assets/$normal.xml"
|
||||||
|
local target="/run/assets/$id.xml"
|
||||||
|
local index="$detected_index"
|
||||||
|
local remove_selector="N"
|
||||||
|
|
||||||
|
[[ "${id,,}" == *"-eval" ]] || return 1
|
||||||
|
|
||||||
|
removeGeneratedXML "$source" || return 1
|
||||||
|
|
||||||
|
if [ ! -s "$source" ]; then
|
||||||
|
source="/run/assets/${normal%%-*}.xml"
|
||||||
|
removeGeneratedXML "$source" || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -s "$source" ] || return 1
|
||||||
|
|
||||||
|
if [ -n "$detected_index" ]; then
|
||||||
|
remove_selector="Y"
|
||||||
|
else
|
||||||
|
# No WIM was inspected, so retain the known defaults for download routes.
|
||||||
|
case "${id,,}" in
|
||||||
|
*"-ltsc-eval" ) index="1" ;;
|
||||||
|
*"-iot-eval" ) index="2" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
generateAnswerFile \
|
||||||
|
"$id" "$source" "$target" "$index" "evaluation" "$remove_selector" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
generateFallbackXML() {
|
generateFallbackXML() {
|
||||||
|
|
||||||
# Fallback templates are generated from the generic version so unsupported
|
# Fallback templates are generated from the generic version so unsupported
|
||||||
@@ -374,62 +402,14 @@ generateFallbackXML() {
|
|||||||
local index="${2:-}"
|
local index="${2:-}"
|
||||||
local source="/run/assets/${id%%-*}.xml"
|
local source="/run/assets/${id%%-*}.xml"
|
||||||
local target="/run/assets/$id.xml"
|
local target="/run/assets/$id.xml"
|
||||||
local tmp
|
|
||||||
|
|
||||||
[ "$source" != "$target" ] || return 1
|
[ "$source" != "$target" ] || return 1
|
||||||
|
|
||||||
removeGeneratedXML "$source" || return 1
|
removeGeneratedXML "$source" || return 1
|
||||||
[ -s "$source" ] || return 1
|
[ -s "$source" ] || return 1
|
||||||
|
|
||||||
if [ -n "$index" ] && [[ ! "$index" =~ ^[1-9][0-9]*$ ]]; then
|
generateAnswerFile \
|
||||||
error "Invalid fallback image index: $index"
|
"$id" "$source" "$target" "$index" "fallback" "Y" || return 1
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! tmp=$(mktemp -p /run/assets ".${id}.XXXXXX"); then
|
|
||||||
error "Failed to create a temporary fallback answer file!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! sed \
|
|
||||||
-e '/<InstallFrom>.*<\/InstallFrom>/d' \
|
|
||||||
-e '/<ProductKey>.*<\/ProductKey>/d' \
|
|
||||||
-e '/<InstallFrom>/,/<\/InstallFrom>/d' \
|
|
||||||
-e '/<ProductKey>/,/<\/ProductKey>/d' \
|
|
||||||
"$source" > "$tmp"; then
|
|
||||||
rm -f "$tmp"
|
|
||||||
error "Failed to generate fallback answer file from $source!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$index" ]; then
|
|
||||||
if ! sed -i \
|
|
||||||
'0,/<InstallTo>/{ /<InstallTo>/i\
|
|
||||||
<InstallFrom>\
|
|
||||||
<MetaData wcm:action="add">\
|
|
||||||
<Key>/IMAGE/INDEX</Key>\
|
|
||||||
<Value>'"$index"'</Value>\
|
|
||||||
</MetaData>\
|
|
||||||
</InstallFrom>
|
|
||||||
}' "$tmp"; then
|
|
||||||
rm -f "$tmp"
|
|
||||||
error "Failed to select fallback image index $index!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! markGeneratedXML "$tmp" ||
|
|
||||||
! xmllint --nonet --noout "$tmp"; then
|
|
||||||
rm -f "$tmp"
|
|
||||||
error "Generated fallback answer file is invalid!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! chmod 644 "$tmp" || ! mv -f "$tmp" "$target"; then
|
|
||||||
rm -f "$tmp"
|
|
||||||
error "Failed to create fallback answer file: $target"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -651,8 +631,7 @@ updateXML() {
|
|||||||
|
|
||||||
local asset="$1"
|
local asset="$1"
|
||||||
local language="$2"
|
local language="$2"
|
||||||
local app value culture admin key
|
local value user
|
||||||
local user user_xml edition pw host
|
|
||||||
|
|
||||||
[ -z "${WIDTH:-}" ] && WIDTH="1280"
|
[ -z "${WIDTH:-}" ] && WIDTH="1280"
|
||||||
[ -z "${HEIGHT:-}" ] && HEIGHT="720"
|
[ -z "${HEIGHT:-}" ] && HEIGHT="720"
|
||||||
@@ -664,6 +643,7 @@ updateXML() {
|
|||||||
validateProductKey "${KEY:-}" || return 1
|
validateProductKey "${KEY:-}" || return 1
|
||||||
validatePassword "${PASSWORD:-}" || return 1
|
validatePassword "${PASSWORD:-}" || return 1
|
||||||
|
|
||||||
|
local app
|
||||||
app=$(escapeXMLSed "$APP for $ENGINE") || return 1
|
app=$(escapeXMLSed "$APP for $ENGINE") || return 1
|
||||||
|
|
||||||
sed -i "s|>Windows for Docker<|>$app<|g" "$asset" || return 1
|
sed -i "s|>Windows for Docker<|>$app<|g" "$asset" || return 1
|
||||||
@@ -671,10 +651,12 @@ updateXML() {
|
|||||||
sed -i -E "s|<HorizontalResolution>[^<]*</HorizontalResolution>|<HorizontalResolution>$WIDTH</HorizontalResolution>|g" "$asset" || return 1
|
sed -i -E "s|<HorizontalResolution>[^<]*</HorizontalResolution>|<HorizontalResolution>$WIDTH</HorizontalResolution>|g" "$asset" || return 1
|
||||||
|
|
||||||
if [ -n "${HOST:-}" ]; then
|
if [ -n "${HOST:-}" ]; then
|
||||||
|
local host
|
||||||
host=$(escapeXMLSed "$HOST") || return 1
|
host=$(escapeXMLSed "$HOST") || return 1
|
||||||
sed -i -E "s|<ComputerName>[^<]*</ComputerName>|<ComputerName>$host</ComputerName>|g" "$asset" || return 1
|
sed -i -E "s|<ComputerName>[^<]*</ComputerName>|<ComputerName>$host</ComputerName>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local culture
|
||||||
culture=$(getLanguage "$language" "culture") || return 1
|
culture=$(getLanguage "$language" "culture") || return 1
|
||||||
|
|
||||||
if [ -n "$culture" ] && [[ "${culture,,}" != "en-us" ]]; then
|
if [ -n "$culture" ] && [[ "${culture,,}" != "en-us" ]]; then
|
||||||
@@ -765,6 +747,7 @@ updateXML() {
|
|||||||
validateUsername "$user" "local" || return 1
|
validateUsername "$user" "local" || return 1
|
||||||
|
|
||||||
if [ -n "$user" ]; then
|
if [ -n "$user" ]; then
|
||||||
|
local user_xml
|
||||||
user_xml=$(escapeXMLSed "$user") || return 1
|
user_xml=$(escapeXMLSed "$user") || return 1
|
||||||
|
|
||||||
sed -i "s|-name \"Docker\"|-name \"\$env:USERNAME\"|g" "$asset" || return 1
|
sed -i "s|-name \"Docker\"|-name \"\$env:USERNAME\"|g" "$asset" || return 1
|
||||||
@@ -775,6 +758,7 @@ updateXML() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local pass="${PASSWORD:-admin}"
|
local pass="${PASSWORD:-admin}"
|
||||||
|
local pw admin
|
||||||
|
|
||||||
pw=$(printf '%s' "${pass}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0) || return 1
|
pw=$(printf '%s' "${pass}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0) || return 1
|
||||||
admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0) || return 1
|
admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0) || return 1
|
||||||
@@ -828,6 +812,7 @@ updateXML() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${EDITION:-}" ]; then
|
if [ -n "${EDITION:-}" ]; then
|
||||||
|
local edition
|
||||||
|
|
||||||
edition=$(normalizeServerEdition "$EDITION") || return 1
|
edition=$(normalizeServerEdition "$EDITION") || return 1
|
||||||
edition="${edition//-/}"
|
edition="${edition//-/}"
|
||||||
@@ -839,6 +824,7 @@ updateXML() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${KEY:-}" ]; then
|
if [ -n "${KEY:-}" ]; then
|
||||||
|
local key
|
||||||
key=$(escapeXMLSed "$KEY") || return 1
|
key=$(escapeXMLSed "$KEY") || return 1
|
||||||
sed -i -E '/^[[:space:]]*<ProductKey>[[:space:]]*$/,/^[[:space:]]*<\/ProductKey>[[:space:]]*$/d' "$asset" || return 1
|
sed -i -E '/^[[:space:]]*<ProductKey>[[:space:]]*$/,/^[[:space:]]*<\/ProductKey>[[:space:]]*$/d' "$asset" || return 1
|
||||||
sed -i -E "s|<ProductKey>[^<]*</ProductKey>|<ProductKey>$key</ProductKey>|g" "$asset" || return 1
|
sed -i -E "s|<ProductKey>[^<]*</ProductKey>|<ProductKey>$key</ProductKey>|g" "$asset" || return 1
|
||||||
@@ -959,7 +945,7 @@ legacyInstall() {
|
|||||||
local desc="$3"
|
local desc="$3"
|
||||||
local driver="$4"
|
local driver="$4"
|
||||||
local drivers="/tmp/drivers"
|
local drivers="/tmp/drivers"
|
||||||
local pid file shortcut="Y"
|
local file shortcut="Y"
|
||||||
|
|
||||||
if disabled "$SHORTCUT" || disabled "${SAMBA:-Y}"; then
|
if disabled "$SHORTCUT" || disabled "${SAMBA:-Y}"; then
|
||||||
shortcut="N"
|
shortcut="N"
|
||||||
@@ -1053,11 +1039,13 @@ legacyInstall() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local key setup
|
local setup
|
||||||
setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini -print -quit) || return 1
|
setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini -print -quit) || return 1
|
||||||
|
|
||||||
if [ -n "$setup" ] && [ -z "$KEY" ]; then
|
if [ -n "$setup" ] && [ -z "$KEY" ]; then
|
||||||
|
|
||||||
|
local pid key
|
||||||
|
|
||||||
pid=$(<"$setup") || return 1
|
pid=$(<"$setup") || return 1
|
||||||
pid="${pid%$'\r'}"
|
pid="${pid%$'\r'}"
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -53,12 +53,14 @@ EDITION_ORDER=(
|
|||||||
SERVER_EDITION_ORDER=(
|
SERVER_EDITION_ORDER=(
|
||||||
"|default|@default"
|
"|default|@default"
|
||||||
"-datacenter|datacenter|datacenter datacenter-*"
|
"-datacenter|datacenter|datacenter datacenter-*"
|
||||||
|
"-datacenter-azure|datacenter|datacenter-azure"
|
||||||
"-enterprise|enterprise|enterprise enterprise-*"
|
"-enterprise|enterprise|enterprise enterprise-*"
|
||||||
"-web|web|web web-*"
|
"-web|web|web web-*"
|
||||||
"-foundation|foundation|foundation foundation-*"
|
"-foundation|foundation|foundation foundation-*"
|
||||||
"-essentials|essentials|essentials essentials-*"
|
"-essentials|essentials|essentials essentials-*"
|
||||||
"-standard-core|standard-core|standard-core standard-core-*"
|
"-standard-core|standard-core|standard-core standard-core-*"
|
||||||
"-datacenter-core|datacenter-core|datacenter-core datacenter-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-*"
|
"-enterprise-core|enterprise-core|enterprise-core enterprise-core-*"
|
||||||
"-web-core|web-core|web-core web-core-*"
|
"-web-core|web-core|web-core web-core-*"
|
||||||
"-hv|hv|hv hv-*"
|
"-hv|hv|hv hv-*"
|
||||||
@@ -883,13 +885,20 @@ normalizeServerEditionID() {
|
|||||||
"core" | "standard-core" | "standardcore" | "serverstandardcore" ) edition="standard-core" ;;
|
"core" | "standard-core" | "standardcore" | "serverstandardcore" ) edition="standard-core" ;;
|
||||||
"datacenter" | "serverdatacenter" ) edition="datacenter" ;;
|
"datacenter" | "serverdatacenter" ) edition="datacenter" ;;
|
||||||
"datacenter-core" | "datacentercore" | "serverdatacentercore" ) edition="datacenter-core" ;;
|
"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" | "serverenterprise" ) edition="enterprise" ;;
|
||||||
"enterprise-core" | "enterprisecore" | "serverenterprisecore" ) edition="enterprise-core" ;;
|
"enterprise-core" | "enterprisecore" | "serverenterprisecore" ) edition="enterprise-core" ;;
|
||||||
"web" | "serverweb" ) edition="web" ;;
|
"web" | "serverweb" ) edition="web" ;;
|
||||||
"web-core" | "webcore" | "serverwebcore" ) edition="web-core" ;;
|
"web-core" | "webcore" | "serverwebcore" ) edition="web-core" ;;
|
||||||
"foundation" | "serverfoundation" ) edition="foundation" ;;
|
"foundation" | "serverfoundation" ) edition="foundation" ;;
|
||||||
"essentials" | "serveressentials" ) edition="essentials" ;;
|
"essentials" | "serveressentials" ) edition="essentials" ;;
|
||||||
* ) edition="unknown" ;;
|
# Keep unrecognized internal edition IDs deterministic and unique.
|
||||||
|
# Known aliases above only provide stable, friendlier public names.
|
||||||
|
* ) : ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "$edition"
|
echo "$edition"
|
||||||
|
|||||||
+257
-171
@@ -4,26 +4,23 @@ set -Eeuo pipefail
|
|||||||
getPlatform() {
|
getPlatform() {
|
||||||
|
|
||||||
local xml="$1"
|
local xml="$1"
|
||||||
local tag="ARCH"
|
|
||||||
local platform="x64"
|
local platform="x64"
|
||||||
|
local x86 x64 arm64 count=0
|
||||||
|
|
||||||
local -a arches=()
|
x86=$(xmllint --nonet --xpath 'count(/WIM/IMAGE/WINDOWS/ARCH[text()="0"])' - 2>/dev/null <<< "$xml") || x86=0
|
||||||
|
x64=$(xmllint --nonet --xpath 'count(/WIM/IMAGE/WINDOWS/ARCH[text()="9"])' - 2>/dev/null <<< "$xml") || x64=0
|
||||||
|
arm64=$(xmllint --nonet --xpath 'count(/WIM/IMAGE/WINDOWS/ARCH[text()="12"])' - 2>/dev/null <<< "$xml") || arm64=0
|
||||||
|
|
||||||
mapfile -t arches < <(
|
(( x86 > 0 )) && ((count++))
|
||||||
sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml" |
|
(( x64 > 0 )) && ((count++))
|
||||||
sort -u
|
(( arm64 > 0 )) && ((count++))
|
||||||
)
|
|
||||||
|
|
||||||
if [ "${#arches[@]}" -gt 1 ]; then
|
if (( count > 1 )); then
|
||||||
platform="mixed"
|
platform="mixed"
|
||||||
elif [ "${#arches[@]}" -eq 1 ]; then
|
elif (( x86 > 0 )); then
|
||||||
local arch="${arches[0]}"
|
platform="x86"
|
||||||
|
elif (( arm64 > 0 )); then
|
||||||
case "${arch,,}" in
|
platform="arm64"
|
||||||
"0" ) platform="x86" ;;
|
|
||||||
"9" ) platform="x64" ;;
|
|
||||||
"12" ) platform="arm64" ;;
|
|
||||||
esac
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$platform"
|
echo "$platform"
|
||||||
@@ -59,62 +56,54 @@ hasVersion() {
|
|||||||
local wanted="$1"
|
local wanted="$1"
|
||||||
shift
|
shift
|
||||||
|
|
||||||
local actual i
|
local actual
|
||||||
local -a actuals=("$@")
|
|
||||||
local -a expected=("$wanted")
|
for actual in "$@"; do
|
||||||
local -a selected=("$wanted")
|
[[ "${actual,,}" == "${wanted,,}" ]] || continue
|
||||||
|
echo "$actual"
|
||||||
|
return 0
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
getCompatibleVersions() {
|
||||||
|
|
||||||
|
local wanted="$1"
|
||||||
|
local result_name="$2"
|
||||||
|
local -n result_ref="$result_name"
|
||||||
|
|
||||||
|
result_ref=("$wanted")
|
||||||
|
|
||||||
# Treat normal and Evaluation variants of the same edition as compatible.
|
# Treat normal and Evaluation variants of the same edition as compatible.
|
||||||
# The exact requested variant is always checked first.
|
# The exact requested variant is always checked first.
|
||||||
if [[ "${wanted,,}" == *"-eval" ]]; then
|
if [[ "${wanted,,}" == *"-eval" ]]; then
|
||||||
expected+=("${wanted%-eval}")
|
result_ref+=("${wanted%-eval}")
|
||||||
selected+=("${wanted%-eval}")
|
|
||||||
else
|
else
|
||||||
expected+=("$wanted-eval")
|
result_ref+=("$wanted-eval")
|
||||||
selected+=("$wanted-eval")
|
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
for (( i=0; i<${#expected[@]}; i++ )); do
|
hasAnswerFile() {
|
||||||
|
|
||||||
local expected_id="${expected[$i]}"
|
local id="$1"
|
||||||
local selected_id="${selected[$i]}"
|
local file="/run/assets/$id.xml"
|
||||||
|
|
||||||
for actual in "${actuals[@]}"; do
|
[ -s "$file" ] && return 0
|
||||||
|
|
||||||
[[ "${actual,,}" == "${expected_id,,}" ]] || continue
|
if [[ "${id,,}" == *"-eval" ]]; then
|
||||||
|
file="/run/assets/${id%-eval}.xml"
|
||||||
local file="/run/assets/$selected_id.xml"
|
[ -s "$file" ] && return 0
|
||||||
|
|
||||||
if [ -s "$file" ]; then
|
|
||||||
echo "$selected_id"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${selected_id,,}" == *"-eval" ]]; then
|
|
||||||
local source="/run/assets/${selected_id%-eval}.xml"
|
|
||||||
|
|
||||||
if [ -s "$source" ]; then
|
|
||||||
echo "$selected_id"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Editions without a dedicated template can use the generic template.
|
# Editions without a dedicated template can use the generic template.
|
||||||
case "${selected_id,,}" in
|
case "${id,,}" in
|
||||||
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | "win20"* )
|
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | "win20"* )
|
||||||
|
file="/run/assets/${id%%-*}.xml"
|
||||||
file="/run/assets/${selected_id%%-*}.xml"
|
[ -s "$file" ] && return 0
|
||||||
|
|
||||||
if [ -s "$file" ]; then
|
|
||||||
echo "$selected_id"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,8 +112,8 @@ getVersionPriority() {
|
|||||||
local id="${1,,}"
|
local id="${1,,}"
|
||||||
local base="${2,,}"
|
local base="${2,,}"
|
||||||
local order_name="EDITION_ORDER"
|
local order_name="EDITION_ORDER"
|
||||||
local edition entry priority patterns pattern
|
local entry priority patterns pattern
|
||||||
local result="other" prefix score best_score=-1
|
local result="other" score best_score=-1
|
||||||
|
|
||||||
id="${id%-eval}"
|
id="${id%-eval}"
|
||||||
|
|
||||||
@@ -136,7 +125,7 @@ getVersionPriority() {
|
|||||||
|
|
||||||
local -n order_ref="$order_name"
|
local -n order_ref="$order_name"
|
||||||
|
|
||||||
edition="${id#"$base"}"
|
local edition="${id#"$base"}"
|
||||||
edition="${edition#-}"
|
edition="${edition#-}"
|
||||||
|
|
||||||
# Use the most specific matching pattern. This prevents broad patterns
|
# Use the most specific matching pattern. This prevents broad patterns
|
||||||
@@ -151,7 +140,7 @@ getVersionPriority() {
|
|||||||
[ -z "$edition" ] || continue
|
[ -z "$edition" ] || continue
|
||||||
score=1
|
score=1
|
||||||
elif [[ "$pattern" == *"*" ]]; then
|
elif [[ "$pattern" == *"*" ]]; then
|
||||||
prefix="${pattern%\*}"
|
local prefix="${pattern%\*}"
|
||||||
[[ "$edition" == "$prefix"* ]] || continue
|
[[ "$edition" == "$prefix"* ]] || continue
|
||||||
score="${#pattern}"
|
score="${#pattern}"
|
||||||
elif [ "$edition" = "$pattern" ]; then
|
elif [ "$edition" = "$pattern" ]; then
|
||||||
@@ -185,8 +174,10 @@ getVersions() {
|
|||||||
local -n groups_ref="$groups_name"
|
local -n groups_ref="$groups_name"
|
||||||
local -n indexes_ref="$indexes_name"
|
local -n indexes_ref="$indexes_name"
|
||||||
|
|
||||||
local image image_index key
|
local count image image_index
|
||||||
local display product platform
|
local display product platform
|
||||||
|
local edition_id install_type
|
||||||
|
local candidate flags i
|
||||||
|
|
||||||
versions_ref=()
|
versions_ref=()
|
||||||
bases_ref=()
|
bases_ref=()
|
||||||
@@ -194,28 +185,76 @@ getVersions() {
|
|||||||
indexes_ref=()
|
indexes_ref=()
|
||||||
|
|
||||||
platform=$(getPlatform "$xml")
|
platform=$(getPlatform "$xml")
|
||||||
|
count=$(xmllint --nonet --xpath 'count(/WIM/IMAGE)' - 2>/dev/null <<< "$xml") || return 0
|
||||||
|
|
||||||
while IFS='|' read -r image_index display product image; do
|
for ((i=1; i<=count; i++)); do
|
||||||
|
|
||||||
|
image_index=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/@INDEX)" - 2>/dev/null <<< "$xml") || continue
|
||||||
|
display=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/DISPLAYNAME)" - 2>/dev/null <<< "$xml") || display=""
|
||||||
|
product=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/WINDOWS/PRODUCTNAME)" - 2>/dev/null <<< "$xml") || product=""
|
||||||
|
image=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/NAME)" - 2>/dev/null <<< "$xml") || image=""
|
||||||
|
edition_id=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/WINDOWS/EDITIONID)" - 2>/dev/null <<< "$xml") || edition_id=""
|
||||||
|
install_type=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/WINDOWS/INSTALLATIONTYPE)" - 2>/dev/null <<< "$xml") || install_type=""
|
||||||
|
flags=$(xmllint --nonet --xpath "string(/WIM/IMAGE[$i]/FLAGS)" - 2>/dev/null <<< "$xml") || flags=""
|
||||||
|
|
||||||
[ -n "$image_index" ] || continue
|
[ -n "$image_index" ] || continue
|
||||||
|
local candidate_id=""
|
||||||
|
local candidate_base=""
|
||||||
|
|
||||||
local candidate candidate_id candidate_base found=""
|
# NAME normally contains the most precise edition identifier (including
|
||||||
|
# Server Core), while DISPLAYNAME is the best fallback for other images.
|
||||||
for candidate in "$display" "$product" "$image"; do
|
for candidate in "$image" "$display" "$product"; do
|
||||||
|
|
||||||
[[ "$candidate" == *"Operating System"* ]] && continue
|
[[ "$candidate" == *"Operating System"* ]] && continue
|
||||||
[ -z "$candidate" ] && continue
|
[ -n "$candidate" ] || continue
|
||||||
|
|
||||||
candidate_base=$(fromName "$candidate" "$platform")
|
candidate_base=$(fromName "$candidate" "$platform")
|
||||||
candidate_id=$(getVersion "$candidate" "$platform")
|
candidate_id=$(getVersion "$candidate" "$platform")
|
||||||
|
|
||||||
|
[ -n "$candidate_base" ] && [ -n "$candidate_id" ] && break
|
||||||
|
done
|
||||||
|
|
||||||
if [ -z "$candidate_base" ] || [ -z "$candidate_id" ]; then
|
if [ -z "$candidate_base" ] || [ -z "$candidate_id" ]; then
|
||||||
|
local name="${display:-${image:-$product}}"
|
||||||
|
[ -n "$name" ] && warn "Unknown image name: '$name'"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
found="Y"
|
local 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
|
||||||
|
local structured=""
|
||||||
|
|
||||||
|
case "${candidate_base,,}" in
|
||||||
|
"winvista"* | "win7"* | "win8"* | "win10"* | "win11"* )
|
||||||
|
structured=$(normalizeEditionID "${edition_id:-${flags:-}}" "$candidate_base")
|
||||||
|
;;
|
||||||
|
"win20"* )
|
||||||
|
structured=$(normalizeServerEditionID "${flags:-$edition_id}")
|
||||||
|
|
||||||
|
# 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
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$structured" ]; then
|
||||||
|
candidate_id="$candidate_base-$structured"
|
||||||
key="${candidate_id,,}"
|
key="${candidate_id,,}"
|
||||||
[[ -v "indexes_ref[$key]" ]] && continue
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -v "indexes_ref[$key]" ]]; then
|
||||||
|
warn "Duplicate image identity '$candidate_id' at indexes ${indexes_ref[$key]} and $image_index"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
indexes_ref["$key"]="$image_index"
|
indexes_ref["$key"]="$image_index"
|
||||||
versions_ref+=("$candidate_id")
|
versions_ref+=("$candidate_id")
|
||||||
@@ -224,45 +263,6 @@ getVersions() {
|
|||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "$found" ]; then
|
|
||||||
local name="${display:-${product:-$image}}"
|
|
||||||
[ -n "$name" ] && warn "Unknown image name: '$name'"
|
|
||||||
fi
|
|
||||||
|
|
||||||
done < <(
|
|
||||||
awk '
|
|
||||||
/<IMAGE INDEX="/ {
|
|
||||||
image_index = $0
|
|
||||||
sub(/^.*<IMAGE INDEX="/, "", image_index)
|
|
||||||
sub(/".*$/, "", image_index)
|
|
||||||
display = product = name = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
image_index != "" && /<DISPLAYNAME>/ {
|
|
||||||
display = $0
|
|
||||||
sub(/^.*<DISPLAYNAME>/, "", display)
|
|
||||||
sub(/<\/DISPLAYNAME>.*$/, "", display)
|
|
||||||
}
|
|
||||||
|
|
||||||
image_index != "" && /<PRODUCTNAME>/ {
|
|
||||||
product = $0
|
|
||||||
sub(/^.*<PRODUCTNAME>/, "", product)
|
|
||||||
sub(/<\/PRODUCTNAME>.*$/, "", product)
|
|
||||||
}
|
|
||||||
|
|
||||||
image_index != "" && /<NAME>/ {
|
|
||||||
name = $0
|
|
||||||
sub(/^.*<NAME>/, "", name)
|
|
||||||
sub(/<\/NAME>.*$/, "", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/<\/IMAGE>/ {
|
|
||||||
print image_index "|" display "|" product "|" name
|
|
||||||
image_index = ""
|
|
||||||
}
|
|
||||||
' <<< "$xml"
|
|
||||||
)
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,18 +279,25 @@ selectVersion() {
|
|||||||
local -n selected_version="$result_name"
|
local -n selected_version="$result_name"
|
||||||
local -n selected_image_index="$index_name"
|
local -n selected_image_index="$index_name"
|
||||||
|
|
||||||
local wanted match key
|
local wanted candidate match
|
||||||
|
local -a candidates=()
|
||||||
|
|
||||||
for wanted in "${preference_list[@]}"; do
|
for wanted in "${preference_list[@]}"; do
|
||||||
|
|
||||||
[ -n "$wanted" ] || continue
|
[ -n "$wanted" ] || continue
|
||||||
|
getCompatibleVersions "$wanted" candidates
|
||||||
|
|
||||||
if match=$(hasVersion "$wanted" "${version_list[@]}"); then
|
for candidate in "${candidates[@]}"; do
|
||||||
key="${match,,}"
|
|
||||||
|
match=$(hasVersion "$candidate" "${version_list[@]}") || continue
|
||||||
|
hasAnswerFile "$match" || continue
|
||||||
|
|
||||||
|
local key="${match,,}"
|
||||||
selected_version="$match"
|
selected_version="$match"
|
||||||
selected_image_index="${index_map[$key]}"
|
selected_image_index="${index_map[$key]}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
|
||||||
|
done
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -405,8 +412,6 @@ detectVersion() {
|
|||||||
local suggested="${2:-}"
|
local suggested="${2:-}"
|
||||||
local result_name="$3"
|
local result_name="$3"
|
||||||
local index_name="$4"
|
local index_name="$4"
|
||||||
local -n result_ref="$result_name"
|
|
||||||
local -n index_ref="$index_name"
|
|
||||||
|
|
||||||
local order_name="EDITION_ORDER"
|
local order_name="EDITION_ORDER"
|
||||||
local normalize_name="normalizeEditionID"
|
local normalize_name="normalizeEditionID"
|
||||||
@@ -416,8 +421,8 @@ detectVersion() {
|
|||||||
local -a versions=()
|
local -a versions=()
|
||||||
local -A image_indexes=()
|
local -A image_indexes=()
|
||||||
|
|
||||||
result_ref=""
|
printf -v "$result_name" '%s' ""
|
||||||
index_ref=""
|
printf -v "$index_name" '%s' ""
|
||||||
|
|
||||||
getVersions \
|
getVersions \
|
||||||
"$xml" \
|
"$xml" \
|
||||||
@@ -446,10 +451,11 @@ detectVersion() {
|
|||||||
"$normalize_name" \
|
"$normalize_name" \
|
||||||
"$order_name" && return 0
|
"$order_name" && return 0
|
||||||
|
|
||||||
result_ref="${versions[0]}"
|
local result="${versions[0]}"
|
||||||
|
local key="${result,,}"
|
||||||
|
|
||||||
local key="${result_ref,,}"
|
printf -v "$result_name" '%s' "$result"
|
||||||
index_ref="${image_indexes[$key]}"
|
printf -v "$index_name" '%s' "${image_indexes[$key]}"
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -457,20 +463,20 @@ detectVersion() {
|
|||||||
detectLanguage() {
|
detectLanguage() {
|
||||||
|
|
||||||
local xml="$1"
|
local xml="$1"
|
||||||
local lang=""
|
local index="${2:-}"
|
||||||
|
local xpath lang
|
||||||
|
|
||||||
if [[ "$xml" == *"LANGUAGE><DEFAULT>"* ]]; then
|
if [[ "$index" =~ ^[0-9]+$ ]]; then
|
||||||
lang="${xml#*LANGUAGE><DEFAULT>}"
|
xpath="string((/WIM/IMAGE[@INDEX='$index']/WINDOWS/LANGUAGES/DEFAULT | /WIM/IMAGE[@INDEX='$index']/WINDOWS/LANGUAGES/FALLBACK/DEFAULT)[1])"
|
||||||
lang="${lang%%<*}"
|
|
||||||
else
|
else
|
||||||
if [[ "$xml" == *"FALLBACK><DEFAULT>"* ]]; then
|
xpath='string((/WIM/IMAGE/WINDOWS/LANGUAGES/DEFAULT | /WIM/IMAGE/WINDOWS/LANGUAGES/FALLBACK/DEFAULT)[1])'
|
||||||
lang="${xml#*FALLBACK><DEFAULT>}"
|
|
||||||
lang="${lang%%<*}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
lang=$(xmllint --nonet --xpath "$xpath" - 2>/dev/null <<< "$xml") || lang=""
|
||||||
|
|
||||||
if [ -z "$lang" ]; then
|
if [ -z "$lang" ]; then
|
||||||
warn "Language could not be detected from ISO!" && return 0
|
warn "Language could not be detected from ISO!"
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local culture
|
local culture
|
||||||
@@ -555,54 +561,55 @@ detectLegacy() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
detectImage() {
|
resolveImage() {
|
||||||
|
|
||||||
local dir="$1"
|
local version="$1"
|
||||||
local version="$2"
|
|
||||||
local desc
|
|
||||||
|
|
||||||
XML=""
|
[ -z "$DETECTED" ] || return 0
|
||||||
|
[ -z "$CUSTOM" ] || return 1
|
||||||
# For normal download routes, avoid inspecting install.wim when the route
|
[ -z "${REUSED_ISO:-}" ] || return 1
|
||||||
# already maps directly to an available answer file. Routes such as Tiny10
|
[[ "${version,,}" != "http"* ]] || return 1
|
||||||
# and Tiny11 have no corresponding answer file, so their actual Windows
|
|
||||||
# edition will be detected from the downloaded image instead.
|
|
||||||
if [ -z "$DETECTED" ] && [ -z "$CUSTOM" ] &&
|
|
||||||
[ -z "${REUSED_ISO:-}" ] && [[ "${version,,}" != "http"* ]]; then
|
|
||||||
|
|
||||||
local file="/run/assets/$version.xml"
|
local file="/run/assets/$version.xml"
|
||||||
|
|
||||||
if [ -s "$file" ]; then
|
if [ -s "$file" ]; then
|
||||||
DETECTED="$version"
|
DETECTED="$version"
|
||||||
elif [[ "${version,,}" == *"-eval" ]]; then
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${version,,}" == *"-eval" ]]; then
|
||||||
local source="/run/assets/${version%-eval}.xml"
|
local source="/run/assets/${version%-eval}.xml"
|
||||||
[ -s "$source" ] && DETECTED="$version"
|
|
||||||
|
if [ -s "$source" ]; then
|
||||||
|
DETECTED="$version"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
if [ -n "$DETECTED" ]; then
|
setImage() {
|
||||||
|
|
||||||
skipVersion "${DETECTED,,}" && return 0
|
skipVersion "${DETECTED,,}" && return 0
|
||||||
|
|
||||||
if ! setXML "" && ! enabled "$MANUAL"; then
|
if ! setXML "" && ! enabled "$MANUAL"; then
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
|
|
||||||
|
local desc
|
||||||
desc=$(printEdition "$DETECTED" "this version")
|
desc=$(printEdition "$DETECTED" "this version")
|
||||||
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
}
|
||||||
|
|
||||||
info "Detecting version from ISO image..."
|
findImage() {
|
||||||
|
|
||||||
if detectLegacy "$dir"; then
|
local dir="$1"
|
||||||
desc=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
local result_name="$2"
|
||||||
info "Detected: $desc"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local src
|
local src result
|
||||||
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
||||||
|
|
||||||
if [ ! -d "$src" ]; then
|
if [ ! -d "$src" ]; then
|
||||||
@@ -610,17 +617,25 @@ detectImage() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local wim
|
result=$(find "$src" -maxdepth 1 -type f \
|
||||||
wim=$(find "$src" -maxdepth 1 -type f \
|
|
||||||
\( -iname install.wim -or -iname install.esd \) -print -quit)
|
\( -iname install.wim -or -iname install.esd \) -print -quit)
|
||||||
|
|
||||||
if [ ! -f "$wim" ]; then
|
if [ ! -f "$result" ]; then
|
||||||
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB"
|
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local info
|
printf -v "$result_name" '%s' "$result"
|
||||||
info=$(wimlib-imagex info -xml "$wim" |
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
readImageInfo() {
|
||||||
|
|
||||||
|
local wim="$1"
|
||||||
|
local result_name="$2"
|
||||||
|
local result
|
||||||
|
|
||||||
|
result=$(wimlib-imagex info -xml "$wim" |
|
||||||
iconv -f UTF-16LE -t UTF-8) || {
|
iconv -f UTF-16LE -t UTF-8) || {
|
||||||
local rc=$?
|
local rc=$?
|
||||||
|
|
||||||
@@ -632,23 +647,25 @@ detectImage() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPlatform "$info" || exit 67
|
printf -v "$result_name" '%s' "$result"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
local suggested=""
|
getSuggestion() {
|
||||||
|
|
||||||
if [ -z "$CUSTOM" ] && [ -n "${REUSED_ISO:-}" ]; then
|
[ -z "$CUSTOM" ] || return 0
|
||||||
suggested="${SUGGEST:-}"
|
[ -n "${REUSED_ISO:-}" ] || return 0
|
||||||
fi
|
|
||||||
|
|
||||||
local index
|
echo "${SUGGEST:-}"
|
||||||
detectVersion "$info" "$suggested" DETECTED index
|
}
|
||||||
|
|
||||||
if [ -n "$EDITION" ]; then
|
validateEdition() {
|
||||||
local edition
|
|
||||||
|
[ -n "$EDITION" ] || return 0
|
||||||
|
|
||||||
case "${DETECTED,,}" in
|
case "${DETECTED,,}" in
|
||||||
"win20"* )
|
"win20"* )
|
||||||
|
local edition
|
||||||
edition=$(normalizeServerEditionID "$EDITION")
|
edition=$(normalizeServerEditionID "$EDITION")
|
||||||
|
|
||||||
if [ -n "$edition" ] &&
|
if [ -n "$edition" ] &&
|
||||||
@@ -658,9 +675,12 @@ detectImage() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$DETECTED" ]; then
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
unknownImage() {
|
||||||
|
|
||||||
local msg="Failed to determine Windows version from image"
|
local msg="Failed to determine Windows version from image"
|
||||||
|
|
||||||
if setXML "" || enabled "$MANUAL"; then
|
if setXML "" || enabled "$MANUAL"; then
|
||||||
@@ -671,19 +691,34 @@ detectImage() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
}
|
||||||
|
|
||||||
desc=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
describeImage() {
|
||||||
|
|
||||||
detectLanguage "$info"
|
local info_xml="$1"
|
||||||
|
local index="$2"
|
||||||
|
local result_name="$3"
|
||||||
|
local result
|
||||||
|
|
||||||
|
result=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
||||||
|
|
||||||
|
detectLanguage "$info_xml" "$index"
|
||||||
|
|
||||||
if [[ "${LANGUAGE,,}" != "en" && "${LANGUAGE,,}" != "en-"* ]]; then
|
if [[ "${LANGUAGE,,}" != "en" && "${LANGUAGE,,}" != "en-"* ]]; then
|
||||||
local language
|
local language
|
||||||
language=$(getLanguage "$LANGUAGE" "desc")
|
language=$(getLanguage "$LANGUAGE" "desc")
|
||||||
desc+=" ($language)"
|
result+=" ($language)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Detected: $desc"
|
printf -v "$result_name" '%s' "$result"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
configureImage() {
|
||||||
|
|
||||||
|
local index="$1"
|
||||||
|
local desc="$2"
|
||||||
|
|
||||||
setXML "" "$index" && return 0
|
setXML "" "$index" && return 0
|
||||||
|
|
||||||
if [[ "$DETECTED" == "win81x86"* ||
|
if [[ "$DETECTED" == "win81x86"* ||
|
||||||
@@ -704,3 +739,54 @@ detectImage() {
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detectImage() {
|
||||||
|
|
||||||
|
local dir="$1"
|
||||||
|
local version="$2"
|
||||||
|
local desc
|
||||||
|
|
||||||
|
XML=""
|
||||||
|
|
||||||
|
resolveImage "$version" || :
|
||||||
|
|
||||||
|
if [ -n "$DETECTED" ]; then
|
||||||
|
setImage || return 1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Detecting version from ISO image..."
|
||||||
|
|
||||||
|
if detectLegacy "$dir"; then
|
||||||
|
desc=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
||||||
|
info "Detected: $desc"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local wim
|
||||||
|
findImage "$dir" wim || return 1
|
||||||
|
|
||||||
|
local image_info
|
||||||
|
readImageInfo "$wim" image_info || return 1
|
||||||
|
|
||||||
|
checkPlatform "$image_info" || exit 67
|
||||||
|
|
||||||
|
local suggested
|
||||||
|
suggested=$(getSuggestion) || return 1
|
||||||
|
|
||||||
|
local index
|
||||||
|
detectVersion "$image_info" "$suggested" DETECTED index || return 1
|
||||||
|
validateEdition || return 1
|
||||||
|
|
||||||
|
if [ -z "$DETECTED" ]; then
|
||||||
|
unknownImage || return 1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
describeImage "$image_info" "$index" desc || return 1
|
||||||
|
info "Detected: $desc"
|
||||||
|
|
||||||
|
configureImage "$index" "$desc" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user