mirror of
https://github.com/dockur/windows.git
synced 2026-08-24 07:39:00 +01:00
feat: Improve error handling (#2120)
This commit is contained in:
+107
-39
@@ -30,10 +30,21 @@ updateXML() {
|
||||
[ -z "${HEIGHT:-}" ] && HEIGHT="720"
|
||||
|
||||
validateXMLSettings || return 1
|
||||
ensureXMLDefaultNamespace "$asset" || return 1
|
||||
|
||||
updateUserXML "$asset" || return 1
|
||||
updateLocaleXML "$asset" "$language" || return 1
|
||||
if ! ensureXMLDefaultNamespace "$asset"; then
|
||||
error "Failed to prepare the answer file XML namespace!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! updateUserXML "$asset"; then
|
||||
error "Failed to update user and display settings in answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! updateLocaleXML "$asset" "$language"; then
|
||||
error "Failed to update regional settings in answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$domain" ]; then
|
||||
|
||||
@@ -46,13 +57,24 @@ updateXML() {
|
||||
|
||||
else
|
||||
|
||||
updateLocalAccount "$asset" || return 1
|
||||
if ! updateLocalAccount "$asset"; then
|
||||
error "Failed to update local account settings in answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
updateMembership "$asset" "$domain" "$workgroup" "$account" "$auth" || return 1
|
||||
updateAutologinXML "$asset" || return 1
|
||||
updateEditionXML "$asset" || return 1
|
||||
|
||||
if ! updateAutologinXML "$asset"; then
|
||||
error "Failed to update automatic logon settings in answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! updateEditionXML "$asset"; then
|
||||
error "Failed to update edition settings in answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
validateGeneratedXML "$asset" || return 1
|
||||
|
||||
@@ -73,7 +95,7 @@ setXML() {
|
||||
|
||||
if [ -d "${custom_files[0]}" ]; then
|
||||
error "The bind ${custom_files[0]} maps to a file that does not exist!"
|
||||
exit 67
|
||||
return 2
|
||||
fi
|
||||
|
||||
# A custom answer file always takes precedence over bundled or generated
|
||||
@@ -182,7 +204,7 @@ addAnswerFile() {
|
||||
|
||||
if ! updateDiskID "$answer" "${DISK_TYPE:-}"; then
|
||||
error "Failed to adjust the Windows installation disk!"
|
||||
exit 85
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! setConfigurationXML "$answer"; then
|
||||
@@ -194,7 +216,10 @@ addAnswerFile() {
|
||||
|
||||
if [ -z "${CUSTOM_XML:-}" ]; then
|
||||
|
||||
prepareSetupScript "$asset" "$stage" || exit 84
|
||||
if ! prepareSetupScript "$asset" "$stage"; then
|
||||
error "Failed to prepare the Windows setup script!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
@@ -1080,7 +1105,13 @@ updateDiskID() {
|
||||
|
||||
done <<< "$values"
|
||||
|
||||
mapfile -t ids < <(printf '%s\n' "${ids[@]}" | sort -u)
|
||||
local unique
|
||||
unique=$(printf '%s\n' "${ids[@]}" | sort -u) || {
|
||||
error "Failed to normalize DiskID values from answer file: $asset"
|
||||
return 1
|
||||
}
|
||||
|
||||
mapfile -t ids <<< "$unique"
|
||||
|
||||
# Leave explicit multi-disk configurations untouched.
|
||||
(( ${#ids[@]} == 1 )) || return 0
|
||||
@@ -1946,10 +1977,16 @@ markGeneratedXML() {
|
||||
|
||||
local file="$1"
|
||||
local marker='<!-- generated-answer-file: do not reuse as a template -->'
|
||||
local first
|
||||
|
||||
[ -s "$file" ] || return 1
|
||||
|
||||
if head -n 1 "$file" | grep -q '^<?xml'; then
|
||||
if ! first=$(head -n 1 "$file"); then
|
||||
error "Failed to inspect generated answer file: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$first" == "<?xml"* ]]; then
|
||||
sed -i "1a$marker" "$file" || return 1
|
||||
else
|
||||
sed -i "1i$marker" "$file" || return 1
|
||||
@@ -1961,12 +1998,17 @@ markGeneratedXML() {
|
||||
removeGeneratedXML() {
|
||||
|
||||
local file="$1"
|
||||
local header
|
||||
|
||||
[ -n "$file" ] || return 0
|
||||
[ -f "$file" ] || return 0
|
||||
|
||||
head -n 5 "$file" |
|
||||
grep -Fqi 'generated-answer-file' || return 0
|
||||
if ! header=$(head -n 5 "$file"); then
|
||||
error "Failed to inspect answer file: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
grep -Fqi 'generated-answer-file' <<< "$header" || return 0
|
||||
|
||||
if ! rm -f "$file"; then
|
||||
error "Failed to remove generated answer file: $file"
|
||||
@@ -2323,10 +2365,18 @@ addSIFEntry() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if grep -Fqx "$entry" "$file" || grep -Fqx "$entry"$'\r' "$file"; then
|
||||
local rc=0
|
||||
grep -Fqx -e "$entry" -e "$entry"$'\r' "$file" || rc=$?
|
||||
|
||||
if (( rc == 0 )); then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if (( rc != 1 )); then
|
||||
error "Failed to inspect section \"$header\" in \"$file\" !"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$ending" == "crlf" ]]; then
|
||||
printf '%s\r\n' "$entry"
|
||||
else
|
||||
@@ -2412,7 +2462,9 @@ addLegacyDrivers() {
|
||||
patchStorageDriver "$file" "$arch" || return 1
|
||||
addSataDriver "$dir" "$target" "$arch" "$drivers" "$file" || return 1
|
||||
|
||||
rm -rf "$drivers" || return 1
|
||||
if ! rm -rf "$drivers"; then
|
||||
warn "failed to clean temporary driver files!"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -2424,7 +2476,7 @@ setLegacyKey() {
|
||||
local arch="$3"
|
||||
local desc="$4"
|
||||
|
||||
local setup pid key file
|
||||
local setup pid file block
|
||||
setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini -print -quit) || return 1
|
||||
|
||||
[[ -n "$setup" ]] || return 0
|
||||
@@ -2434,7 +2486,8 @@ setLegacyKey() {
|
||||
pid="${pid%$'\r'}"
|
||||
|
||||
if [[ "$driver" == "2k" ]]; then
|
||||
echo "${pid::-3}270" > "$setup" || return 1
|
||||
[ "${#pid}" -ge 3 ] || return 0
|
||||
echo "${pid::-3}270" > "$setup" || :
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -2447,28 +2500,44 @@ setLegacyKey() {
|
||||
|
||||
if [[ -n "$file" ]]; then
|
||||
|
||||
local key=""
|
||||
|
||||
# Prefer a staging or OEM key already shipped on the media before falling
|
||||
# back to Microsoft's documented generic installation keys.
|
||||
if [[ "$driver" == "2k3" ]]; then
|
||||
|
||||
key=$(grep -i -A 2 "StagingKey" "$file" | tail -n 2 | head -n 1) || key=""
|
||||
block=$(grep -i -A 2 "StagingKey" "$file") || block=""
|
||||
|
||||
if [ -n "$block" ]; then
|
||||
key=$(printf '%s\n' "$block" | tail -n 2 | head -n 1) || key=""
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
key="${pid: -8:5}"
|
||||
|
||||
if [[ "${pid^^}" == *"OEM" ]]; then
|
||||
key=$(grep -i -A 2 "$key" "$file" | tail -n 2 | head -n 1) || key=""
|
||||
|
||||
block=$(grep -i -A 2 "$key" "$file") || block=""
|
||||
|
||||
else
|
||||
key=$(grep -i -m 1 -A 2 "$key" "$file" | tail -n 2 | head -n 1) || key=""
|
||||
|
||||
block=$(grep -i -m 1 -A 2 "$key" "$file") || block=""
|
||||
|
||||
fi
|
||||
|
||||
if [ -n "$block" ]; then
|
||||
key=$(printf '%s\n' "$block" | tail -n 2 | head -n 1) || key=""
|
||||
fi
|
||||
|
||||
key="${key#*= }"
|
||||
|
||||
fi
|
||||
|
||||
key="${key%$'\r'}"
|
||||
[[ "${#key}" == "29" ]] && KEY="$key"
|
||||
if [ -n "$key" ]; then
|
||||
key="${key%$'\r'}"
|
||||
[[ "${#key}" == "29" ]] && KEY="$key"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
@@ -2499,7 +2568,9 @@ setLegacyKey() {
|
||||
|
||||
esac
|
||||
|
||||
echo "${pid::-3}000" > "$setup" || return 1
|
||||
if [ "${#pid}" -ge 3 ]; then
|
||||
echo "${pid::-3}000" > "$setup" || :
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -2768,12 +2839,10 @@ disableAutoReboot() {
|
||||
|
||||
local target="$1"
|
||||
|
||||
local file
|
||||
local file rc=0
|
||||
local pattern='^[[:space:]]*HKLM[[:space:]]*,[[:space:]]*"SYSTEM\\CurrentControlSet\\Control\\CrashControl"[[:space:]]*,[[:space:]]*"AutoReboot"[[:space:]]*,[[:space:]]*[^,]*,'
|
||||
|
||||
file=$(find \
|
||||
"$target" -maxdepth 1 -type f -iname HIVESYS.INF -print -quit
|
||||
) || return 1
|
||||
file=$(find "$target" -maxdepth 1 -type f -iname HIVESYS.INF -print -quit) || return 1
|
||||
|
||||
if [ -z "$file" ]; then
|
||||
error "The file HIVESYS.INF could not be found!"
|
||||
@@ -2782,19 +2851,18 @@ disableAutoReboot() {
|
||||
|
||||
# Keep setup crashes visible instead of immediately rebooting into an
|
||||
# opaque installation loop.
|
||||
if grep -Eqi "${pattern}[[:space:]]*[^,;[:space:]]+" "$file"; then
|
||||
grep -Eqi "${pattern}[[:space:]]*[^,;[:space:]]+" "$file" || rc=$?
|
||||
|
||||
sed -i -E \
|
||||
"s|(${pattern})[[:space:]]*[^,;[:space:]]+|\\1 0|I" \
|
||||
"$file" || return 1
|
||||
|
||||
else
|
||||
|
||||
printf '%s\n' \
|
||||
'HKLM,"SYSTEM\CurrentControlSet\Control\CrashControl","AutoReboot",0x00010001,0' |
|
||||
unix2dos >> "$file" || return 1
|
||||
|
||||
fi
|
||||
case "$rc" in
|
||||
0 )
|
||||
sed -i -E "s|(${pattern})[[:space:]]*[^,;[:space:]]+|\\1 0|I" "$file" || :
|
||||
;;
|
||||
1 )
|
||||
printf '%s\n' \
|
||||
'HKLM,"SYSTEM\CurrentControlSet\Control\CrashControl","AutoReboot",0x00010001,0' |
|
||||
unix2dos >> "$file" || :
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
+41
-23
@@ -647,23 +647,28 @@ getVersion() {
|
||||
local evaluation=""
|
||||
|
||||
id=$(fromName "$name" "$arch")
|
||||
[ -z "$id" ] && return 0
|
||||
|
||||
[[ "${name,,}" == *"evaluation"* ]] && evaluation="-eval"
|
||||
|
||||
case "${id,,}" in
|
||||
"winvista"* | "win7"* | "win8"* | "win10"* | "win11"* )
|
||||
if edition=$(getEditionID "$name" "$id"); then
|
||||
[ -n "$edition" ] && id+="-$edition"
|
||||
[ -n "$evaluation" ] && id+="$evaluation"
|
||||
fi
|
||||
;;
|
||||
|
||||
"win20"* )
|
||||
|
||||
if [[ "${name,,}" == *"hyper-v server"* ]]; then
|
||||
id+="-hv"
|
||||
elif edition=$(getServerEditionID "$name" "$id"); then
|
||||
[ -n "$edition" ] && id+="-$edition"
|
||||
[ -n "$evaluation" ] && id+="$evaluation"
|
||||
fi
|
||||
;;
|
||||
fi ;;
|
||||
|
||||
* )
|
||||
|
||||
if edition=$(getEditionID "$name" "$id"); then
|
||||
[ -n "$edition" ] && id+="-$edition"
|
||||
[ -n "$evaluation" ] && id+="$evaluation"
|
||||
fi ;;
|
||||
|
||||
esac
|
||||
|
||||
echo "$id"
|
||||
@@ -695,6 +700,7 @@ getEditionRank() {
|
||||
|
||||
case "$base" in
|
||||
"win20"* )
|
||||
|
||||
case "$edition" in
|
||||
"" ) echo 0 ;;
|
||||
"datacenter-azure-core" | "datacenter-azure-core-"* | \
|
||||
@@ -709,9 +715,10 @@ getEditionRank() {
|
||||
"essentials" | "essentials-"* ) echo 5 ;;
|
||||
"hv" | "hv-"* ) echo 10 ;;
|
||||
* ) echo 99 ;;
|
||||
esac
|
||||
;;
|
||||
esac ;;
|
||||
|
||||
* )
|
||||
|
||||
case "$edition" in
|
||||
"enterprise-iot" | "enterprise-iot-"* | "iot" | "iot-"* ) echo 3 ;;
|
||||
"enterprise-ltsc" | "enterprise-ltsc-"* | "ltsc" | "ltsc-"* ) echo 4 ;;
|
||||
@@ -723,8 +730,8 @@ getEditionRank() {
|
||||
"home" | "home-"* ) echo 6 ;;
|
||||
"starter" | "starter-"* ) echo 7 ;;
|
||||
* ) echo 99 ;;
|
||||
esac
|
||||
;;
|
||||
esac ;;
|
||||
|
||||
esac
|
||||
|
||||
return 0
|
||||
@@ -735,6 +742,7 @@ getEditionPolicy() {
|
||||
local base="${1,,}"
|
||||
|
||||
case "$base" in
|
||||
|
||||
"win20"* )
|
||||
printf '%s\n' \
|
||||
"normalizeServerEditionID" \
|
||||
@@ -750,9 +758,10 @@ getEditionPolicy() {
|
||||
"-datacenter-azure-core" \
|
||||
"-enterprise-core" \
|
||||
"-web-core" \
|
||||
"-hv"
|
||||
;;
|
||||
"-hv" ;;
|
||||
|
||||
* )
|
||||
|
||||
printf '%s\n' \
|
||||
"normalizeEditionID" \
|
||||
"-enterprise" \
|
||||
@@ -764,8 +773,8 @@ getEditionPolicy() {
|
||||
"-home" \
|
||||
"-home-premium" \
|
||||
"-home-basic" \
|
||||
"-starter"
|
||||
;;
|
||||
"-starter" ;;
|
||||
|
||||
esac
|
||||
|
||||
return 0
|
||||
@@ -774,18 +783,20 @@ getEditionPolicy() {
|
||||
normalizeEdition() {
|
||||
|
||||
local source="${1,,}"
|
||||
|
||||
local edition
|
||||
local edition transliterated
|
||||
|
||||
source="${source//evaluation/}"
|
||||
source=$(printf '%s' "$source" |
|
||||
uconv -x 'Any-Latin; Latin-ASCII' 2>/dev/null) || return 1
|
||||
|
||||
if transliterated=$(printf '%s' "$source" |
|
||||
uconv -x 'Any-Latin; Latin-ASCII' 2>/dev/null); then
|
||||
source="$transliterated"
|
||||
fi
|
||||
|
||||
edition=$(sed -E \
|
||||
-e 's/[^a-z0-9]+/-/g' \
|
||||
-e 's/^-+//' \
|
||||
-e 's/-+$//' \
|
||||
<<< "$source")
|
||||
<<< "$source") || edition=""
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
@@ -799,11 +810,15 @@ normalizeEditionID() {
|
||||
edition=$(normalizeEdition "$1") || return 1
|
||||
|
||||
case "$edition" in
|
||||
|
||||
"pro" | "professional" | "business" )
|
||||
edition="" ;;
|
||||
|
||||
"pro-n" | "pron" | "professional-n" | "professionaln" | "business-n" | "businessn" )
|
||||
edition="n" ;;
|
||||
|
||||
* )
|
||||
|
||||
if ! isClientEdition "$edition"; then
|
||||
case "$edition" in
|
||||
*"-n" ) base="${edition%-n}" ;;
|
||||
@@ -816,10 +831,13 @@ normalizeEditionID() {
|
||||
fi
|
||||
|
||||
fi ;;
|
||||
|
||||
esac
|
||||
|
||||
case "${id,,}" in
|
||||
|
||||
"win10"* | "win11"* )
|
||||
|
||||
case "$edition" in
|
||||
"iot-enterprise-ltsc" | \
|
||||
"iot-enterprise-ltsc-"[0-9][0-9][0-9][0-9] )
|
||||
@@ -827,8 +845,8 @@ normalizeEditionID() {
|
||||
"enterprise-ltsc" | \
|
||||
"enterprise-ltsc-"[0-9][0-9][0-9][0-9] )
|
||||
edition="ltsc" ;;
|
||||
esac
|
||||
;;
|
||||
esac ;;
|
||||
|
||||
esac
|
||||
|
||||
echo "$edition"
|
||||
|
||||
+86
-25
@@ -273,13 +273,17 @@ detectLanguage() {
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
|
||||
lang=$(xmlstarlet sel -T -t -v "normalize-space(string(($path)[1]))" - 2>/dev/null <<< "$xml") || lang=""
|
||||
if ! lang=$(xmlstarlet sel -T -t -v "normalize-space(string(($path)[1]))" - 2>/dev/null <<< "$xml"); then
|
||||
warn "failed to read language metadata from Windows image!"
|
||||
return 0
|
||||
fi
|
||||
|
||||
[ -n "$lang" ] && break
|
||||
|
||||
done
|
||||
|
||||
if [ -z "$lang" ]; then
|
||||
warn "Language could not be detected from ISO!"
|
||||
warn "language could not be detected from ISO!"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -290,7 +294,7 @@ detectLanguage() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "Invalid language detected: \"$lang\""
|
||||
warn "invalid language detected: \"$lang\""
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -617,7 +621,7 @@ detectLegacy() {
|
||||
|
||||
if [ -n "$marker" ]; then
|
||||
error "Windows IA-64 (Itanium) images are not supported by this container!"
|
||||
exit 67
|
||||
return 2
|
||||
fi
|
||||
|
||||
marker=$(find "$dir" -maxdepth 1 -type d -iname WIN95 -print -quit) || return 2
|
||||
@@ -786,7 +790,6 @@ readWimHeader() {
|
||||
|
||||
if ! rm -f -- "$header"; then
|
||||
enabled "$DEBUG" && echo "Failed to remove the previous temporary WIM header: $header" >&2
|
||||
error "Failed to prepare Windows image header!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -794,35 +797,30 @@ readWimHeader() {
|
||||
# extracting install.wim or install.esd from the ISO.
|
||||
if ! udfread range --ignore-case -o "$header" "$iso" "$image" 0 208 >/dev/null 2>&1; then
|
||||
enabled "$DEBUG" && echo "udfread failed to read the first 208 bytes of $image from $iso." >&2
|
||||
error "Failed to read Windows image header!"
|
||||
rm -f -- "$header"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! size=$(stat -c%s -- "$header"); then
|
||||
enabled "$DEBUG" && echo "Failed to determine the size of the temporary WIM header: $header" >&2
|
||||
error "Failed to read Windows image header!"
|
||||
rm -f -- "$header"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if (( size != 208 )); then
|
||||
enabled "$DEBUG" && echo "The WIM header is $size bytes instead of the expected 208 bytes." >&2
|
||||
error "Failed to read Windows image header!"
|
||||
rm -f -- "$header"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! signature=$(od -An -N8 -tx1 "$header" | tr -d ' \n'); then
|
||||
enabled "$DEBUG" && echo "Failed to read the WIM header signature from $header." >&2
|
||||
error "Failed to read Windows image header!"
|
||||
rm -f -- "$header"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$signature" != "4d5357494d000000" ]]; then
|
||||
enabled "$DEBUG" && echo "The WIM header has an invalid signature: ${signature:-empty}." >&2
|
||||
error "Failed to read Windows image header!"
|
||||
rm -f -- "$header"
|
||||
return 1
|
||||
fi
|
||||
@@ -1241,7 +1239,7 @@ configureImage() {
|
||||
|
||||
if [[ "$DETECTED" == "win81x86"* || "$DETECTED" == "win10x86"* ]]; then
|
||||
error "The 32-bit version of $desc is not supported!"
|
||||
exit 67
|
||||
return 2
|
||||
fi
|
||||
|
||||
local msg="the answer file for $desc was not found ($DETECTED.xml)"
|
||||
@@ -1269,18 +1267,14 @@ configureImage() {
|
||||
detectImageInfo() {
|
||||
|
||||
local image_info="$1"
|
||||
|
||||
local desc index rc
|
||||
|
||||
checkPlatform "$image_info" || {
|
||||
enabled "$DEBUG" && echo "Platform validation failed for the Windows image metadata." >&2
|
||||
exit 67
|
||||
}
|
||||
checkPlatform "$image_info" || return 2
|
||||
|
||||
local output
|
||||
output=$(detectVersion "$image_info") || {
|
||||
enabled "$DEBUG" && echo "Version detection failed while parsing the Windows image metadata." >&2
|
||||
error "Failed to detect Windows version from image metadata!"
|
||||
error "Failed to detect the Windows version from image metadata!"
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -1292,16 +1286,18 @@ detectImageInfo() {
|
||||
|
||||
validateEdition || {
|
||||
enabled "$DEBUG" && echo "Edition validation failed for detected image: ${DETECTED:-empty}, index: ${index:-empty}." >&2
|
||||
error "Failed to validate Windows edition from image metadata!"
|
||||
error "Failed to validate the Windows edition from image metadata!"
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -z "$DETECTED" ]; then
|
||||
|
||||
unknownImage || {
|
||||
rc=$?
|
||||
enabled "$DEBUG" && echo "Unknown-image handling failed after no Windows version could be detected (status $rc)." >&2
|
||||
return "$rc"
|
||||
}
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -1337,25 +1333,84 @@ detectIsoImage() {
|
||||
# the caller may extract the media. Metadata parsing/configuration errors use 2.
|
||||
image=$(findIsoImage "$iso") || {
|
||||
rc=$?
|
||||
enabled "$DEBUG" && echo "Direct ISO image lookup stopped with status $rc." >&2
|
||||
enabled "$DEBUG" && echo "ISO image lookup failed (status $rc)." >&2
|
||||
return "$rc"
|
||||
}
|
||||
|
||||
header=$(readWimHeader "$iso" "$image") || {
|
||||
enabled "$DEBUG" && echo "Reading the WIM header failed for $image." >&2
|
||||
error "Failed to read the Windows image header!"
|
||||
return 2
|
||||
}
|
||||
|
||||
image_info=$(readIsoImageInfo "$iso" "$image" "$header") || {
|
||||
enabled "$DEBUG" && echo "Reading the WIM XML metadata failed for $image." >&2
|
||||
error "Failed to read Windows image metadata!"
|
||||
error "Failed to read the Windows image metadata!"
|
||||
return 2
|
||||
}
|
||||
|
||||
info "Detecting version from ISO image..."
|
||||
|
||||
detectImageInfo "$image_info" || {
|
||||
enabled "$DEBUG" && echo "Processing the Windows image metadata failed." >&2
|
||||
error "Failed to process the Windows image metadata!"
|
||||
return 2
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
detectESDImage() {
|
||||
|
||||
local iso="$1"
|
||||
|
||||
local image_info install_info output index rc
|
||||
local -a detected=()
|
||||
|
||||
image_info=$(wimlib-imagex info "$iso" --xml 2>/dev/null |
|
||||
iconv -f UTF-16LE -t UTF-8 2>/dev/null) || {
|
||||
rc=$?
|
||||
error "Cannot read ESD file information (status $rc)."
|
||||
return 2
|
||||
}
|
||||
|
||||
# Microsoft download ESDs use images 1-3 for setup media, WinPE, and Windows
|
||||
# Setup; images 4 and higher contain installable editions.
|
||||
if ! install_info=$(xmlstarlet ed \
|
||||
-d '/WIM/IMAGE[number(@INDEX) < 4]' \
|
||||
<<< "$image_info" 2>/dev/null); then
|
||||
error "Cannot read installable images from ESD file!"
|
||||
return 2
|
||||
fi
|
||||
|
||||
checkPlatform "$install_info" || return 2
|
||||
|
||||
local output
|
||||
output=$(detectVersion "$install_info") || {
|
||||
error "Failed to detect Windows version from the ESD metadata!"
|
||||
return 2
|
||||
}
|
||||
|
||||
mapfile -t detected <<< "$output"
|
||||
index="${detected[1]:-}"
|
||||
|
||||
if [ -z "$index" ]; then
|
||||
error "Failed to select an installation image based on the ESD metadata!"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# extractESD removes every other image, leaving the selected edition at
|
||||
# index 1. Detect against that final layout so the generated answer file
|
||||
# already references the index that will exist after extraction.
|
||||
if ! image_info=$(xmlstarlet ed \
|
||||
-d "/WIM/IMAGE[number(@INDEX) != $index]" \
|
||||
-u "/WIM/IMAGE[@INDEX='$index']/@INDEX" -v '1' \
|
||||
<<< "$install_info" 2>/dev/null); then
|
||||
error "Cannot prepare ESD image information!"
|
||||
return 2
|
||||
fi
|
||||
|
||||
info "Detecting version from ESD image..."
|
||||
|
||||
detectImageInfo "$image_info" || {
|
||||
error "Failed to process the ESD image metadata!"
|
||||
return 2
|
||||
}
|
||||
|
||||
@@ -1364,6 +1419,8 @@ detectIsoImage() {
|
||||
|
||||
baseDir() {
|
||||
|
||||
# TODO: Can be removed with base image 7.45+
|
||||
|
||||
local path="${1%/}"
|
||||
|
||||
[[ -z "$path" || "$path" == "/" ]] && {
|
||||
@@ -1584,7 +1641,7 @@ extractESD() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
checkPlatform "$xml" || return
|
||||
checkPlatform "$installXml" || return
|
||||
|
||||
output=$(detectVersion "$installXml") || return
|
||||
mapfile -t detected <<< "$output"
|
||||
@@ -1990,7 +2047,11 @@ buildImage() {
|
||||
|
||||
base=$(basename "$BOOT")
|
||||
local out="$TMP/${base%.*}.tmp"
|
||||
rm -f "$out"
|
||||
|
||||
if ! rm -f "$out"; then
|
||||
error "Failed to remove temporary ISO image: $out"
|
||||
return 1
|
||||
fi
|
||||
|
||||
desc=$(printVariant "$DETECTED" "ISO")
|
||||
|
||||
|
||||
+171
-48
@@ -3,20 +3,43 @@ set -Eeuo pipefail
|
||||
|
||||
startWindows() {
|
||||
|
||||
parseVersion || exit 58
|
||||
parseLanguage || exit 62
|
||||
detectCustom || exit 64
|
||||
parseVersion || {
|
||||
error "Failed to parse the Windows version!"
|
||||
exit 58
|
||||
}
|
||||
|
||||
parseLanguage || {
|
||||
error "Failed to parse the Windows language!"
|
||||
exit 62
|
||||
}
|
||||
|
||||
detectCustom || {
|
||||
error "Failed to scan for custom installation media!"
|
||||
exit 64
|
||||
}
|
||||
|
||||
local rc=0
|
||||
startInstall || rc=$?
|
||||
(( rc > 1 )) && exit "$rc"
|
||||
|
||||
if (( rc )); then
|
||||
|
||||
bootWindows || {
|
||||
error "Failed to boot Windows!"
|
||||
exit 66
|
||||
}
|
||||
|
||||
if ! startInstall; then
|
||||
bootWindows || exit 66
|
||||
return 0
|
||||
|
||||
fi
|
||||
|
||||
if ! hasImage "$ISO"; then
|
||||
|
||||
if ! downloadImage "$ISO" "$VERSION" "$LANGUAGE"; then
|
||||
removeImage "$ISO" || :
|
||||
exit 68
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
local boot="$BOOT"
|
||||
@@ -48,11 +71,12 @@ selectWindowsImage() {
|
||||
XML=""
|
||||
FB="falling back to manual installation!"
|
||||
|
||||
normalizeDetected || return 70
|
||||
normalizeDetected || :
|
||||
|
||||
if [ -n "$DETECTED" ]; then
|
||||
|
||||
if ! setImage; then
|
||||
error "Failed to configure the detected Windows image!"
|
||||
return 70
|
||||
fi
|
||||
|
||||
@@ -61,6 +85,7 @@ selectWindowsImage() {
|
||||
fi
|
||||
|
||||
if ! extractImage "$iso" "$dir" "$VERSION"; then
|
||||
error "Failed to extract the Windows installation image!"
|
||||
removeImage "$iso" || :
|
||||
return 72
|
||||
fi
|
||||
@@ -76,11 +101,21 @@ selectWindowsImage() {
|
||||
detectIsoImage "$iso" && return 0
|
||||
|
||||
rc=$?
|
||||
(( rc == 1 )) || return 76
|
||||
if (( rc != 1 )); then
|
||||
error "Failed to inspect the Windows installation ISO!"
|
||||
return 76
|
||||
fi
|
||||
|
||||
elif [[ "${iso,,}" == *.esd ]]; then
|
||||
|
||||
detectESDImage "$iso" && return 0
|
||||
error "Failed to inspect the Windows installation ESD!"
|
||||
return 76
|
||||
|
||||
fi
|
||||
|
||||
if ! extractImage "$iso" "$dir" "$VERSION"; then
|
||||
error "Failed to extract the Windows installation image!"
|
||||
removeImage "$iso" || :
|
||||
return 74
|
||||
fi
|
||||
@@ -90,9 +125,15 @@ selectWindowsImage() {
|
||||
detectImage "$dir" && return 0
|
||||
|
||||
rc=$?
|
||||
(( rc == 1 )) || return 76
|
||||
if (( rc != 1 )); then
|
||||
error "Failed to detect the extracted Windows installation image!"
|
||||
return 76
|
||||
fi
|
||||
|
||||
skipUnattended "$dir" "$iso" "$boot" || return 76
|
||||
skipUnattended "$dir" "$iso" "$boot" || {
|
||||
error "Failed to fall back to manual installation!"
|
||||
return 76
|
||||
}
|
||||
|
||||
handled=1
|
||||
return 0
|
||||
@@ -108,24 +149,37 @@ configureMachine() {
|
||||
desc=$(printVariant "$DETECTED" "$DETECTED") || return 78
|
||||
|
||||
if ! checkMemory "$DETECTED"; then
|
||||
|
||||
if [ -z "$CUSTOM" ]; then
|
||||
useOriginalImage "$iso" || return 79
|
||||
useOriginalImage "$iso" || {
|
||||
error "Failed to preserve the original installation image!"
|
||||
return 79
|
||||
}
|
||||
fi
|
||||
|
||||
return 79
|
||||
fi
|
||||
|
||||
if ! setMachine "$DETECTED" "$iso" "$dir" "$desc"; then
|
||||
error "Failed to configure the virtual machine for $desc!"
|
||||
return 80
|
||||
fi
|
||||
|
||||
if ! restoreMachineState; then
|
||||
error "Failed to restore the saved machine state!"
|
||||
return 82
|
||||
fi
|
||||
|
||||
if ! supportsUnattended "$DETECTED"; then
|
||||
skipUnattended "$dir" "$iso" "$boot" "N" || return 83
|
||||
|
||||
skipUnattended "$dir" "$iso" "$boot" "N" || {
|
||||
error "Failed to fall back to manual installation!"
|
||||
return 83
|
||||
}
|
||||
|
||||
handled=1
|
||||
return 0
|
||||
|
||||
fi
|
||||
|
||||
return 0
|
||||
@@ -141,16 +195,23 @@ prepareWindowsImage() {
|
||||
if supportsXML "$DETECTED"; then
|
||||
|
||||
if ! createOverlay "$XML" "$LANGUAGE" "$TMP/setup"; then
|
||||
error "Failed to create the Windows setup overlay!"
|
||||
return 84
|
||||
fi
|
||||
|
||||
if ! createSetupImage "$TMP/setup" "$STORAGE/setup.img"; then
|
||||
error "Failed to create the Windows setup image!"
|
||||
return 86
|
||||
fi
|
||||
|
||||
# Bootable ISOs can be reused unchanged with the generated setup image.
|
||||
if (( ! extracted )); then
|
||||
useOriginalImage "$iso" || return 88
|
||||
if (( ! extracted )) && isDirectImage "$iso"; then
|
||||
|
||||
useOriginalImage "$iso" || {
|
||||
error "Failed to preserve the original installation image!"
|
||||
return 88
|
||||
}
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -158,28 +219,54 @@ prepareWindowsImage() {
|
||||
|
||||
# Extracted modern sources and SIF-based legacy media require a clean rebuild.
|
||||
if (( ! extracted )); then
|
||||
|
||||
if ! extractImage "$iso" "$dir" "$VERSION"; then
|
||||
error "Failed to extract the Windows installation image!"
|
||||
removeImage "$iso" || :
|
||||
return 90
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if ! prepareImage "$iso" "$dir"; then
|
||||
error "Failed to prepare the Windows installation image!"
|
||||
return 92
|
||||
fi
|
||||
|
||||
removeImage "$iso" || return 96
|
||||
buildImage "$dir" || return 98
|
||||
removeImage "$iso" || {
|
||||
error "Failed to remove the source installation image!"
|
||||
return 96
|
||||
}
|
||||
|
||||
buildImage "$dir" || {
|
||||
error "Failed to build the Windows installation image!"
|
||||
return 98
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
bootWindows() {
|
||||
|
||||
restoreMachineState || return
|
||||
restoreBootMode || return
|
||||
restoreMachine || return
|
||||
reserveSambaPorts || return
|
||||
if ! restoreMachineState; then
|
||||
error "Failed to restore the saved machine state!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! restoreBootMode; then
|
||||
error "Failed to restore the saved boot mode!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! restoreMachine; then
|
||||
error "Failed to restore the saved machine type!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! reserveSambaPorts; then
|
||||
error "Failed to reserve Samba ports!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -211,13 +298,17 @@ startInstall() {
|
||||
case "${boot,,}" in
|
||||
"windows."* )
|
||||
error "The download filename \"$file\" uses the reserved \"windows.*\" namespace!"
|
||||
exit 58 ;;
|
||||
return 58 ;;
|
||||
esac
|
||||
|
||||
else
|
||||
|
||||
local language
|
||||
language=$(getLanguage "$LANGUAGE" "culture")
|
||||
if ! language=$(getLanguage "$LANGUAGE" "culture"); then
|
||||
error "Failed to determine the Windows language!"
|
||||
return 62
|
||||
fi
|
||||
|
||||
language="${language%%-*}"
|
||||
|
||||
if [ -n "$language" ] && [[ "${language,,}" != "en" ]]; then
|
||||
@@ -235,28 +326,32 @@ startInstall() {
|
||||
|
||||
if ! rm -rf -- "$TMP"; then
|
||||
error "Failed to remove directory \"$TMP\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
local setup="$STORAGE/setup.img"
|
||||
|
||||
if ! rm -f -- "$setup" "${setup}.tmp"; then
|
||||
error "Failed to remove setup image \"$setup\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
local previousBase
|
||||
if ! previousBase=$(readState "base"); then
|
||||
error "Failed to read the previous installation state!"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
skipInstall "$BOOT" "$previousBase" && return 1
|
||||
local rc=0
|
||||
skipInstall "$BOOT" "$previousBase" || rc=$?
|
||||
|
||||
(( rc > 1 )) && return "$rc"
|
||||
(( rc )) || return 1
|
||||
|
||||
if [ -z "$previousBase" ] && hasData; then
|
||||
|
||||
if enabled "$SHUTDOWN" && [ ! -f "$STORAGE/windows.boot" ]; then
|
||||
discardPrevious "" || exit 50
|
||||
discardPrevious "" || return 50
|
||||
else
|
||||
if ! backupPrevious ""; then
|
||||
warn "the backup was incomplete, continuing with installation..."
|
||||
@@ -267,7 +362,7 @@ startInstall() {
|
||||
|
||||
if ! makeDir "$TMP"; then
|
||||
error "Failed to create directory \"$TMP\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
if [ -z "$CUSTOM" ]; then
|
||||
@@ -285,27 +380,27 @@ startInstall() {
|
||||
if [ -n "$CUSTOM" ] || [ ! -s "$BOOT" ]; then
|
||||
if ! rm -f -- "$BOOT"; then
|
||||
error "Failed to remove obsolete ISO file \"$BOOT\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! find "$STORAGE" -maxdepth 1 -type f -iname 'data.*' -not -iname '*.iso' -delete; then
|
||||
error "Failed to remove obsolete disk files from \"$STORAGE\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
if ! find "$STORAGE" -maxdepth 1 -type f -iname 'windows.*' -not -iname '*.iso' -delete; then
|
||||
error "Failed to remove obsolete Windows files from \"$STORAGE\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
if ! find "$STORAGE" -maxdepth 1 -type f \( -iname '*.rom' -or -iname '*.vars' \) -delete; then
|
||||
error "Failed to remove obsolete firmware files from \"$STORAGE\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
if [ -z "$CUSTOM" ] && [[ "${VERSION,,}" != "http"* ]]; then
|
||||
checkMemory "$VERSION" || exit 67
|
||||
checkMemory "$VERSION" || return 67
|
||||
fi
|
||||
|
||||
# Work from the temporary directory so the persistent source path can
|
||||
@@ -313,7 +408,7 @@ startInstall() {
|
||||
if [ -z "$CUSTOM" ] && [ -f "$BOOT" ] && [ -s "$BOOT" ]; then
|
||||
if ! mv -f -- "$BOOT" "$ISO"; then
|
||||
error "Failed to move ISO file from \"$BOOT\" to \"$ISO\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -333,7 +428,7 @@ skipUnattended() {
|
||||
# so they cannot use the manual-install fallback.
|
||||
if ! isDirectImage "$iso"; then
|
||||
error "Failed to boot \"$iso\" because it is not a directly bootable ISO image!"
|
||||
exit 60
|
||||
return 1
|
||||
fi
|
||||
|
||||
# When automatic preparation fails, inspect extracted media to determine
|
||||
@@ -382,7 +477,7 @@ skipInstall() {
|
||||
|
||||
if ! writeState "base" "$previousBase"; then
|
||||
error "Failed to migrate the previous installation state!"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
fi
|
||||
@@ -390,10 +485,12 @@ skipInstall() {
|
||||
# Older releases may have left a rebuilt custom ISO at its synthetic source
|
||||
# identity. A completed installation no longer needs that installation media.
|
||||
if [[ "${previousBase,,}" == "windows."* ]] && hasData && [ -f "$marker" ]; then
|
||||
|
||||
if ! rm -f -- "$STORAGE/$previousBase"; then
|
||||
error "Failed to remove obsolete ISO file \"$STORAGE/$previousBase\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# A changed source invalidates an unfinished installation. Back up an
|
||||
@@ -404,7 +501,7 @@ skipInstall() {
|
||||
|
||||
if ! rm -f -- "$STORAGE/$previousBase"; then
|
||||
error "Failed to remove ISO file \"$STORAGE/$previousBase\" !"
|
||||
exit 50
|
||||
return 50
|
||||
fi
|
||||
|
||||
return 1
|
||||
@@ -430,7 +527,7 @@ skipInstall() {
|
||||
fi
|
||||
|
||||
if enabled "$SHUTDOWN" && [ ! -f "$marker" ]; then
|
||||
discardPrevious "$STORAGE/$previousBase" || exit 50
|
||||
discardPrevious "$STORAGE/$previousBase" || return 50
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -469,7 +566,10 @@ finishInstall() {
|
||||
fi
|
||||
|
||||
local file="$STORAGE/windows.ver"
|
||||
cp -f /etc/version "$file" || return 1
|
||||
cp -f /etc/version "$file" || {
|
||||
error "Failed to save the Windows installation version!"
|
||||
return 1
|
||||
}
|
||||
|
||||
if ! setOwner "$file"; then
|
||||
warn "Failed to set the owner for \"$file\" !"
|
||||
@@ -477,15 +577,23 @@ finishInstall() {
|
||||
|
||||
if [[ "$boot" == "$STORAGE/"* ]]; then
|
||||
if [[ "$aborted" != [Yy1]* ]] || [ -z "$CUSTOM" ]; then
|
||||
|
||||
base=$(basename "$boot")
|
||||
writeState "base" "$base" || return 1
|
||||
writeState "base" "$base" || {
|
||||
error "Failed to save the Windows installation source!"
|
||||
return 1
|
||||
}
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
||||
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
||||
|
||||
writeState "mode" "$BOOT_MODE" || return 1
|
||||
writeState "mode" "$BOOT_MODE" || {
|
||||
error "Failed to save the Windows boot mode!"
|
||||
return 1
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
@@ -496,14 +604,22 @@ finishInstall() {
|
||||
fi
|
||||
|
||||
if (( secure )); then
|
||||
|
||||
BOOT_MODE="windows_secure"
|
||||
writeState "mode" "$BOOT_MODE" || return 1
|
||||
writeState "mode" "$BOOT_MODE" || {
|
||||
error "Failed to save the Windows boot mode!"
|
||||
return 1
|
||||
}
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
reserveSambaPorts || return 1
|
||||
reserveSambaPorts || {
|
||||
error "Failed to reserve Samba ports!"
|
||||
return 1
|
||||
}
|
||||
|
||||
if ! rm -rf -- "$TMP"; then
|
||||
error "Failed to remove directory \"$TMP\" !"
|
||||
@@ -516,7 +632,6 @@ finishInstall() {
|
||||
findFile() {
|
||||
|
||||
local fname="$1"
|
||||
|
||||
local dir file base
|
||||
local boot="$STORAGE/windows.boot"
|
||||
|
||||
@@ -896,7 +1011,12 @@ detectImage() {
|
||||
local image_info
|
||||
image_info=$(readImageInfo "$wim") || return $?
|
||||
|
||||
detectImageInfo "$image_info" || return 2
|
||||
detectImageInfo "$image_info" || {
|
||||
error "Failed to process the Windows image metadata!"
|
||||
return 2
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
prepareImage() {
|
||||
@@ -1212,7 +1332,10 @@ createOverlay() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
addAnswerFile "$asset" "$language" "$stage" || return 1
|
||||
addAnswerFile "$asset" "$language" "$stage" || {
|
||||
error "Failed to include the Windows answer file!"
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -1309,8 +1432,8 @@ backupPrevious () {
|
||||
failed="Y"
|
||||
fi
|
||||
|
||||
[ -z "$(ls -A "$dir")" ] && rm -rf "$dir"
|
||||
[ -z "$(ls -A "$root")" ] && rm -rf "$root"
|
||||
rmdir "$dir" 2>/dev/null || :
|
||||
rmdir "$root" 2>/dev/null || :
|
||||
|
||||
[ -n "$failed" ] && return 1
|
||||
|
||||
|
||||
+19
-10
@@ -175,13 +175,16 @@ downloadWindowsLink() {
|
||||
--max-filesize 100K \
|
||||
-- "$skuUrl") || return
|
||||
|
||||
# Let jq parsing failures propagate so malformed API data is not mistaken
|
||||
# for a normal missing-result response. The same applies to the link data.
|
||||
skuId=$(printf '%s\n' "$skuJson" | jq --arg LANG "$language" -r 'first(.Skus[]? | select(.Language == $LANG) | .Id) // empty') 2>/dev/null || return
|
||||
skuId=$(printf '%s\n' "$skuJson" | jq --arg LANG "$language" -r 'first(.Skus[]? | select(.Language == $LANG) | .Id) // empty') 2>/dev/null || skuId=""
|
||||
|
||||
if [ -z "$skuId" ] || [[ "${skuId,,}" == "null" ]]; then
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download in the $language language available for $desc!"
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download in the $language language available for $desc!"
|
||||
else
|
||||
error "Microsoft server provided us no SKU ID in response to our request!"
|
||||
info "Response: $skuJson"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -214,10 +217,10 @@ downloadWindowsLink() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
link=$(printf '%s\n' "$linkJson" | jq --argjson TYPE "$type" -r 'first(.ProductDownloadOptions[]? | select(.DownloadType == $TYPE) | .Uri) // empty') 2>/dev/null || return
|
||||
link=$(printf '%s\n' "$linkJson" | jq --argjson TYPE "$type" -r 'first(.ProductDownloadOptions[]? | select(.DownloadType == $TYPE) | .Uri) // empty') 2>/dev/null || link=""
|
||||
|
||||
if [ -z "$link" ] || [[ "${link,,}" == "null" ]]; then
|
||||
error "Microsoft server gave us no download link to our request for an automated download!"
|
||||
error "Microsoft server provided us no download link to our request for an automated download!"
|
||||
info "Response: $linkJson"
|
||||
return 1
|
||||
fi
|
||||
@@ -287,7 +290,7 @@ downloadWindows() {
|
||||
grep -Eio "<option[^>]*value=[\"'][0-9]+[\"'][^>]*>[[:space:]]*Windows[^<]*" |
|
||||
sed -nE "s/.*value=[\"']([0-9]+)[\"'].*/\1/p" |
|
||||
sed -n '1p' |
|
||||
cut -c 1-16) || return
|
||||
cut -c 1-16) || productId=""
|
||||
enabled "$DEBUG" && echo "$productId"
|
||||
|
||||
if [ -z "$productId" ]; then
|
||||
@@ -1119,7 +1122,7 @@ verifyFile() {
|
||||
info "Successfully verified $type!" && return 0
|
||||
fi
|
||||
|
||||
error "The downloaded file has an unknown $algo checksum: $hash , as the expected value was: $check. Please report this at $SUPPORT/issues"
|
||||
warn "the downloaded file has an unknown $algo checksum: $hash , as the expected value was: $check. Please report this at $SUPPORT/issues"
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -1280,7 +1283,11 @@ downloadImage() {
|
||||
desc=$(fromFile "$base")
|
||||
web_desc="$desc"
|
||||
|
||||
tryDownload "$iso" "$version" "" "" "$desc" "$seconds" "$web_desc" || return
|
||||
tryDownload "$iso" "$version" "" "" "$desc" "$seconds" "$web_desc" || {
|
||||
rc=$?
|
||||
error "Failed to download the Windows image from the specified URL!"
|
||||
return "$rc"
|
||||
}
|
||||
|
||||
return 0
|
||||
fi
|
||||
@@ -1450,6 +1457,8 @@ downloadImage() {
|
||||
|
||||
if [[ "$tried" == "n" ]]; then
|
||||
error "No download method is available for $desc!"
|
||||
else
|
||||
error "All download methods failed for $desc!"
|
||||
fi
|
||||
|
||||
return 1
|
||||
|
||||
Reference in New Issue
Block a user