mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 20:47:12 +01:00
feat: Refactor Windows answer file handling (#1983)
This commit is contained in:
@@ -487,6 +487,15 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if grep -Fqi \
|
||||||
|
'CDBOOT: Cannot boot from CD - Code: 5' \
|
||||||
|
<<< "$container_log"; then
|
||||||
|
echo
|
||||||
|
echo "------------------------------------------------------------"
|
||||||
|
echo "Detected an unbootable installation medium."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
bios_starts="$(
|
bios_starts="$(
|
||||||
grep -Fci 'SeaBIOS (version ' <<< "$container_log" || true
|
grep -Fci 'SeaBIOS (version ' <<< "$container_log" || true
|
||||||
)"
|
)"
|
||||||
|
|||||||
+395
-186
@@ -141,30 +141,35 @@ validateUsername() {
|
|||||||
|
|
||||||
local value="$1"
|
local value="$1"
|
||||||
local type="$2"
|
local type="$2"
|
||||||
local maximum
|
local maximum length_suffix invalid_message
|
||||||
|
|
||||||
case "$type" in
|
case "$type" in
|
||||||
"local" )
|
"local" )
|
||||||
maximum=20
|
|
||||||
[ -z "$value" ] && return 0
|
[ -z "$value" ] && return 0
|
||||||
;;
|
|
||||||
"domain" )
|
|
||||||
maximum=256
|
|
||||||
|
|
||||||
|
maximum=20
|
||||||
|
length_suffix=""
|
||||||
|
invalid_message="The USERNAME variable contains characters that are not supported by Windows local accounts!"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"domain" )
|
||||||
if [ -z "$value" ]; then
|
if [ -z "$value" ]; then
|
||||||
error "The USERNAME variable does not contain a valid domain account name!"
|
error "The USERNAME variable does not contain a valid domain account name!"
|
||||||
return 1
|
return 1
|
||||||
fi ;;
|
fi
|
||||||
|
|
||||||
|
maximum=256
|
||||||
|
length_suffix=" for a domain account"
|
||||||
|
invalid_message="The domain account name contains characters that are not supported by Windows unattended setup!"
|
||||||
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
return 1 ;;
|
return 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "${#value}" -gt "$maximum" ]; then
|
if [ "${#value}" -gt "$maximum" ]; then
|
||||||
if [[ "$type" == "domain" ]]; then
|
error "The USERNAME variable cannot contain more than $maximum characters$length_suffix!"
|
||||||
error "The USERNAME variable cannot contain more than $maximum characters for a domain account!"
|
|
||||||
else
|
|
||||||
error "The USERNAME variable cannot contain more than $maximum characters!"
|
|
||||||
fi
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -175,12 +180,9 @@ validateUsername() {
|
|||||||
|
|
||||||
case "$value" in
|
case "$value" in
|
||||||
*'"'* | *'/'* | *\\* | *'['* | *']'* | *':'* | *';'* | *'|'* | *'='* | *','* | *'+'* | *'*'* | *'?'* | *'<'* | *'>'* | *'%'* | *'@'* )
|
*'"'* | *'/'* | *\\* | *'['* | *']'* | *':'* | *';'* | *'|'* | *'='* | *','* | *'+'* | *'*'* | *'?'* | *'<'* | *'>'* | *'%'* | *'@'* )
|
||||||
if [[ "$type" == "domain" ]]; then
|
error "$invalid_message"
|
||||||
error "The domain account name contains characters that are not supported by Windows unattended setup!"
|
return 1
|
||||||
else
|
;;
|
||||||
error "The USERNAME variable contains characters that are not supported by Windows local accounts!"
|
|
||||||
fi
|
|
||||||
return 1 ;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ "$value" == *"." ]]; then
|
if [[ "$value" == *"." ]]; then
|
||||||
@@ -196,12 +198,15 @@ validateUsername() {
|
|||||||
case "${value^^}" in
|
case "${value^^}" in
|
||||||
"NONE" )
|
"NONE" )
|
||||||
error "The USERNAME value \"NONE\" is reserved by Windows!"
|
error "The USERNAME value \"NONE\" is reserved by Windows!"
|
||||||
return 1 ;;
|
return 1
|
||||||
|
;;
|
||||||
|
|
||||||
"ADMINISTRATOR" | "GUEST" | "DEFAULTACCOUNT" | "WDAGUTILITYACCOUNT" | "WSIACCOUNT" )
|
"ADMINISTRATOR" | "GUEST" | "DEFAULTACCOUNT" | "WDAGUTILITYACCOUNT" | "WSIACCOUNT" )
|
||||||
if [[ "$type" == "local" ]]; then
|
[[ "$type" == "domain" ]] && return 0
|
||||||
|
|
||||||
error "The USERNAME value \"$value\" is reserved for a built-in Windows account!"
|
error "The USERNAME value \"$value\" is reserved for a built-in Windows account!"
|
||||||
return 1
|
return 1
|
||||||
fi ;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -234,14 +239,28 @@ validateDomainName() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getXMLArchitecture() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
local arch
|
||||||
|
|
||||||
|
arch=$(sed -n -E \
|
||||||
|
'0,/processorArchitecture="/s/.*processorArchitecture="([^"]+)".*/\1/p' \
|
||||||
|
"$asset") || return 1
|
||||||
|
|
||||||
|
[ -n "$arch" ] || return 1
|
||||||
|
|
||||||
|
printf '%s' "$arch"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
updateWorkgroup() {
|
updateWorkgroup() {
|
||||||
|
|
||||||
local asset="$1"
|
local asset="$1"
|
||||||
local workgroup arch tmp
|
local workgroup arch tmp
|
||||||
|
|
||||||
workgroup=$(escapeXML "$2") || return 1
|
workgroup=$(escapeXML "$2") || return 1
|
||||||
arch=$(sed -n -E '0,/processorArchitecture="/s/.*processorArchitecture="([^"]+)".*/\1/p' "$asset") || return 1
|
arch=$(getXMLArchitecture "$asset") || return 1
|
||||||
[ -z "$arch" ] && return 1
|
|
||||||
|
|
||||||
grep -q 'Microsoft-Windows-UnattendedJoin' "$asset" && return 1
|
grep -q 'Microsoft-Windows-UnattendedJoin' "$asset" && return 1
|
||||||
|
|
||||||
@@ -287,12 +306,7 @@ updateDomain() {
|
|||||||
auth=$(escapeXML "$4") || return 1
|
auth=$(escapeXML "$4") || return 1
|
||||||
pass=$(escapeXML "$5") || return 1
|
pass=$(escapeXML "$5") || return 1
|
||||||
ou=$(escapeXML "$6") || return 1
|
ou=$(escapeXML "$6") || return 1
|
||||||
|
arch=$(getXMLArchitecture "$asset") || return 1
|
||||||
arch=$(sed -n -E \
|
|
||||||
'0,/processorArchitecture="/s/.*processorArchitecture="([^"]+)".*/\1/p' \
|
|
||||||
"$asset") || return 1
|
|
||||||
|
|
||||||
[ -z "$arch" ] && return 1
|
|
||||||
|
|
||||||
local cred_domain="$domain"
|
local cred_domain="$domain"
|
||||||
|
|
||||||
@@ -397,17 +411,44 @@ updateDomain() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeLocalAccountXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
|
||||||
|
if ! sed -i -E \
|
||||||
|
-e '/^[[:space:]]*<LocalAccounts([[:space:]>])/,/^[[:space:]]*<\/LocalAccounts>[[:space:]]*$/d' \
|
||||||
|
-e '/^[[:space:]]*<AdministratorPassword([[:space:]>])/,/^[[:space:]]*<\/AdministratorPassword>[[:space:]]*$/d' \
|
||||||
|
"$asset"; then
|
||||||
|
|
||||||
|
error "Failed to remove local account configuration from answer file!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! sed -i -E '
|
||||||
|
/<SynchronousCommand([[:space:]>])/ {
|
||||||
|
:command
|
||||||
|
N
|
||||||
|
/<\/SynchronousCommand>/!b command
|
||||||
|
/<Description>Password Never Expires<\/Description>/d
|
||||||
|
}
|
||||||
|
' "$asset"; then
|
||||||
|
|
||||||
|
error "Failed to remove local account commands from answer file!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
enableLog() {
|
enableLog() {
|
||||||
|
|
||||||
local file="$1"
|
local file="$1"
|
||||||
|
|
||||||
enabled "$LOG" || return 0
|
|
||||||
[ -f "$file" ] || return 1
|
|
||||||
|
|
||||||
local old='C:\OEM\install.bat"</CommandLine>'
|
local old='C:\OEM\install.bat"</CommandLine>'
|
||||||
local new='C:\OEM\install.bat > C:\OEM\install.log 2>&1"</CommandLine>'
|
|
||||||
local msg="failed to enable install logging in the answer file!"
|
local msg="failed to enable install logging in the answer file!"
|
||||||
|
|
||||||
|
enabled "${LOG:-}" || return 0
|
||||||
|
[ -f "$file" ] || return 1
|
||||||
|
|
||||||
if ! grep -Fq "$old" "$file"; then
|
if ! grep -Fq "$old" "$file"; then
|
||||||
enabled "$DEBUG" && warn "$msg"
|
enabled "$DEBUG" && warn "$msg"
|
||||||
return 0
|
return 0
|
||||||
@@ -549,14 +590,15 @@ generateEvalXML() {
|
|||||||
|
|
||||||
local id="$1"
|
local id="$1"
|
||||||
local detected_index="${2:-}"
|
local detected_index="${2:-}"
|
||||||
|
|
||||||
|
[[ "${id,,}" == *"-eval" ]] || return 1
|
||||||
|
|
||||||
local normal="${id::-5}"
|
local normal="${id::-5}"
|
||||||
local source="/run/assets/$normal.xml"
|
local source="/run/assets/$normal.xml"
|
||||||
local target="/run/assets/$id.xml"
|
local target="/run/assets/$id.xml"
|
||||||
local index="$detected_index"
|
local index="$detected_index"
|
||||||
local remove_selector="N"
|
local remove_selector="N"
|
||||||
|
|
||||||
[[ "${id,,}" == *"-eval" ]] || return 1
|
|
||||||
|
|
||||||
removeGeneratedXML "$source" || return 1
|
removeGeneratedXML "$source" || return 1
|
||||||
|
|
||||||
if [ ! -s "$source" ]; then
|
if [ ! -s "$source" ]; then
|
||||||
@@ -605,7 +647,7 @@ generateFallbackXML() {
|
|||||||
|
|
||||||
setXML() {
|
setXML() {
|
||||||
|
|
||||||
local file
|
local file="$1"
|
||||||
local index="${2:-}"
|
local index="${2:-}"
|
||||||
local target="/run/assets/$DETECTED.xml"
|
local target="/run/assets/$DETECTED.xml"
|
||||||
|
|
||||||
@@ -634,17 +676,21 @@ setXML() {
|
|||||||
|
|
||||||
file="$1"
|
file="$1"
|
||||||
|
|
||||||
if [[ "${DETECTED,,}" == *"-eval" ]]; then
|
if [[ "${DETECTED,,}" == *"-eval" ]] &&
|
||||||
if [ ! -f "$file" ] || [ ! -s "$file" ]; then
|
{ [ ! -f "$file" ] || [ ! -s "$file" ]; }; then
|
||||||
generateEvalXML "$DETECTED" "$index" || return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$file" ] || [ ! -s "$file" ]; then
|
generateEvalXML "$DETECTED" "$index" || return 1
|
||||||
file="$target"
|
file="$target"
|
||||||
|
|
||||||
|
elif [ ! -f "$file" ] || [ ! -s "$file" ]; then
|
||||||
|
|
||||||
|
file="$target"
|
||||||
|
|
||||||
elif [[ "$file" != "$target" ]]; then
|
elif [[ "$file" != "$target" ]]; then
|
||||||
|
|
||||||
generateFallbackXML "$DETECTED" "$index" || return 1
|
generateFallbackXML "$DETECTED" "$index" || return 1
|
||||||
file="$target"
|
file="$target"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -f "$file" ] && [ -s "$file" ] || return 1
|
[ -f "$file" ] && [ -s "$file" ] || return 1
|
||||||
@@ -653,14 +699,7 @@ setXML() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
updateXML() {
|
validateXMLSettings() {
|
||||||
|
|
||||||
local asset="$1"
|
|
||||||
local language="$2"
|
|
||||||
local value user
|
|
||||||
|
|
||||||
[ -z "${WIDTH:-}" ] && WIDTH="1280"
|
|
||||||
[ -z "${HEIGHT:-}" ] && HEIGHT="720"
|
|
||||||
|
|
||||||
validateResolution "WIDTH" "$WIDTH" 320 || return 1
|
validateResolution "WIDTH" "$WIDTH" 320 || return 1
|
||||||
validateResolution "HEIGHT" "$HEIGHT" 200 || return 1
|
validateResolution "HEIGHT" "$HEIGHT" 200 || return 1
|
||||||
@@ -669,20 +708,34 @@ updateXML() {
|
|||||||
validateProductKey "${KEY:-}" || return 1
|
validateProductKey "${KEY:-}" || return 1
|
||||||
validatePassword "${PASSWORD:-}" || return 1
|
validatePassword "${PASSWORD:-}" || return 1
|
||||||
|
|
||||||
local app
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDisplayXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
local app host
|
||||||
|
|
||||||
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
|
||||||
sed -i -E "s|<VerticalResolution>[^<]*</VerticalResolution>|<VerticalResolution>$HEIGHT</VerticalResolution>|g" "$asset" || return 1
|
sed -i -E "s|<VerticalResolution>[^<]*</VerticalResolution>|<VerticalResolution>$HEIGHT</VerticalResolution>|g" "$asset" || return 1
|
||||||
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
|
[ -n "${HOST:-}" ] || return 0
|
||||||
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
|
|
||||||
|
|
||||||
local culture
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocaleXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
local language="$2"
|
||||||
|
local culture region keyboard value
|
||||||
|
|
||||||
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
|
||||||
@@ -690,8 +743,7 @@ updateXML() {
|
|||||||
sed -i "s|<UILanguage>en-US</UILanguage>|<UILanguage>$value</UILanguage>|g" "$asset" || return 1
|
sed -i "s|<UILanguage>en-US</UILanguage>|<UILanguage>$value</UILanguage>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local region="${REGION:-}"
|
region="${REGION:-$culture}"
|
||||||
[ -z "$region" ] && region="$culture"
|
|
||||||
|
|
||||||
if [ -n "$region" ] && [[ "${region,,}" != "en-us" ]]; then
|
if [ -n "$region" ] && [[ "${region,,}" != "en-us" ]]; then
|
||||||
value=$(escapeXMLSed "$region") || return 1
|
value=$(escapeXMLSed "$region") || return 1
|
||||||
@@ -699,8 +751,7 @@ updateXML() {
|
|||||||
sed -i "s|<SystemLocale>en-US</SystemLocale>|<SystemLocale>$value</SystemLocale>|g" "$asset" || return 1
|
sed -i "s|<SystemLocale>en-US</SystemLocale>|<SystemLocale>$value</SystemLocale>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local keyboard="${KEYBOARD:-}"
|
keyboard="${KEYBOARD:-$culture}"
|
||||||
[ -z "$keyboard" ] && keyboard="$culture"
|
|
||||||
|
|
||||||
if [ -n "$keyboard" ] && [[ "${keyboard,,}" != "en-us" ]]; then
|
if [ -n "$keyboard" ] && [[ "${keyboard,,}" != "en-us" ]]; then
|
||||||
value=$(escapeXMLSed "$keyboard") || return 1
|
value=$(escapeXMLSed "$keyboard") || return 1
|
||||||
@@ -708,12 +759,20 @@ updateXML() {
|
|||||||
sed -i "s|<InputLocale>0409:00000409</InputLocale>|<InputLocale>$value</InputLocale>|g" "$asset" || return 1
|
sed -i "s|<InputLocale>0409:00000409</InputLocale>|<InputLocale>$value</InputLocale>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local domain="${DOMAIN:-}"
|
return 0
|
||||||
local workgroup="${WORKGROUP:-}"
|
}
|
||||||
|
|
||||||
if [ -n "$domain" ]; then
|
prepareDomainAccount() {
|
||||||
|
|
||||||
if [ -z "${USERNAME:-}" ]; then
|
local domain="$1"
|
||||||
|
local -n account_ref="$2"
|
||||||
|
local -n auth_ref="$3"
|
||||||
|
local qualifier=""
|
||||||
|
|
||||||
|
auth_ref="${USERNAME:-}"
|
||||||
|
account_ref=""
|
||||||
|
|
||||||
|
if [ -z "$auth_ref" ]; then
|
||||||
error "The USERNAME variable must be specified when joining a domain!"
|
error "The USERNAME variable must be specified when joining a domain!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -725,20 +784,20 @@ updateXML() {
|
|||||||
|
|
||||||
validateDomainName "$domain" || return 1
|
validateDomainName "$domain" || return 1
|
||||||
|
|
||||||
local auth_user="$USERNAME"
|
if [[ "$auth_ref" == *\\* ]]; then
|
||||||
local qualifier=""
|
|
||||||
|
|
||||||
if [[ "$auth_user" == *\\* ]]; then
|
|
||||||
error "The USERNAME variable must use either \"user\" or \"user@domain\" format!"
|
error "The USERNAME variable must use either \"user\" or \"user@domain\" format!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$auth_user" in
|
case "$auth_ref" in
|
||||||
*@* )
|
*@* )
|
||||||
user="${auth_user%%@*}"
|
account_ref="${auth_ref%%@*}"
|
||||||
qualifier="${auth_user#*@}"
|
qualifier="${auth_ref#*@}"
|
||||||
|
|
||||||
|
if [ -z "$account_ref" ] ||
|
||||||
|
[ -z "$qualifier" ] ||
|
||||||
|
[[ "$qualifier" == *@* ]]; then
|
||||||
|
|
||||||
if [ -z "$user" ] || [ -z "$qualifier" ] || [[ "$qualifier" == *@* ]]; then
|
|
||||||
error "The USERNAME variable does not contain a valid domain account name!"
|
error "The USERNAME variable does not contain a valid domain account name!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -750,14 +809,15 @@ updateXML() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
user="$auth_user"
|
account_ref="$auth_ref"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
validateUsername "$user" "domain" || return 1
|
validateUsername "$account_ref" "domain" || return 1
|
||||||
|
|
||||||
if [[ "${user,,}" == "docker" ]]; then
|
if [[ "${account_ref,,}" == "docker" ]]; then
|
||||||
error "The USERNAME variable must be changed from its default value when joining a domain!"
|
error "The USERNAME variable must be changed from its default value when joining a domain!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -767,13 +827,19 @@ updateXML() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocalAccountXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
local user="${USERNAME:-}"
|
||||||
|
local pass="${PASSWORD:-admin}"
|
||||||
|
local user_xml pw admin
|
||||||
|
|
||||||
user="${USERNAME:-}"
|
|
||||||
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
|
||||||
@@ -783,85 +849,125 @@ updateXML() {
|
|||||||
sed -i "s|<Username>Docker</Username>|<Username>$user_xml</Username>|g" "$asset" || return 1
|
sed -i "s|<Username>Docker</Username>|<Username>$user_xml</Username>|g" "$asset" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local pass="${PASSWORD:-admin}"
|
pw=$(printf '%s' "${pass}Password" |
|
||||||
local pw admin
|
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" |
|
||||||
admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0) || return 1
|
iconv -f utf-8 -t utf-16le |
|
||||||
|
base64 -w 0) || return 1
|
||||||
|
|
||||||
sed -i -z -E "s#(<Password>[[:space:]]*<Value)([[:space:]]*/>|>[^<]*</Value>)#\1>$pw</Value>#g" "$asset" || return 1
|
sed -i -z -E \
|
||||||
sed -i -z -E "s#(<AdministratorPassword>[[:space:]]*<Value)([[:space:]]*/>|>[^<]*</Value>)#\1>$admin</Value>#g" "$asset" || return 1
|
"s#(<Password>[[:space:]]*<Value)([[:space:]]*/>|>[^<]*</Value>)#\1>$pw</Value>#g" \
|
||||||
|
"$asset" || return 1
|
||||||
|
|
||||||
fi
|
sed -i -z -E \
|
||||||
|
"s#(<AdministratorPassword>[[:space:]]*<Value)([[:space:]]*/>|>[^<]*</Value>)#\1>$admin</Value>#g" \
|
||||||
|
"$asset" || return 1
|
||||||
|
|
||||||
sed -i -E "s|<PlainText>[^<]*</PlainText>|<PlainText>false</PlainText>|g" "$asset" || return 1
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMembershipXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
local domain="$2"
|
||||||
|
local workgroup="$3"
|
||||||
|
local account="$4"
|
||||||
|
local auth="$5"
|
||||||
|
|
||||||
if [ -n "$domain" ]; then
|
if [ -n "$domain" ]; then
|
||||||
|
|
||||||
if updateDomain "$asset" "$domain" "$user" \
|
if ! updateDomain \
|
||||||
"$auth_user" "$PASSWORD" "$DOMAIN_OU"; then
|
"$asset" \
|
||||||
|
"$domain" \
|
||||||
|
"$account" \
|
||||||
|
"$auth" \
|
||||||
|
"$PASSWORD" \
|
||||||
|
"${DOMAIN_OU:-}"; then
|
||||||
|
|
||||||
if ! sed -i -E \
|
|
||||||
-e '/^[[:space:]]*<LocalAccounts([[:space:]>])/,/^[[:space:]]*<\/LocalAccounts>[[:space:]]*$/d' \
|
|
||||||
-e '/^[[:space:]]*<AdministratorPassword([[:space:]>])/,/^[[:space:]]*<\/AdministratorPassword>[[:space:]]*$/d' \
|
|
||||||
"$asset"; then
|
|
||||||
error "Failed to remove local account configuration from answer file!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! sed -i -E '
|
|
||||||
/<SynchronousCommand([[:space:]>])/ {
|
|
||||||
:command
|
|
||||||
N
|
|
||||||
/<\/SynchronousCommand>/!b command
|
|
||||||
/<Description>Password Never Expires<\/Description>/d
|
|
||||||
}
|
|
||||||
' "$asset"; then
|
|
||||||
error "Failed to remove local account commands from answer file!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
|
||||||
warn "failed to add domain configuration to answer file!"
|
warn "failed to add domain configuration to answer file!"
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [ -n "$workgroup" ]; then
|
removeLocalAccountXML "$asset" || return 1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$workgroup" ] || return 0
|
||||||
|
|
||||||
if ! updateWorkgroup "$asset" "$workgroup"; then
|
if ! updateWorkgroup "$asset" "$workgroup"; then
|
||||||
warn "failed to add workgroup configuration to answer file!"
|
warn "failed to add workgroup configuration to answer file!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if disabled "${AUTOLOGIN:-}"; then
|
updateAutologinXML() {
|
||||||
sed -i -E '/^[[:space:]]*<AutoLogon([[:space:]>])/,/^[[:space:]]*<\/AutoLogon>[[:space:]]*$/d' "$asset" || return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if enabled "${LOG:-}"; then
|
local asset="$1"
|
||||||
enableLog "$asset" || return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${EDITION:-}" ]; then
|
disabled "${AUTOLOGIN:-}" || return 0
|
||||||
|
|
||||||
|
sed -i -E \
|
||||||
|
'/^[[:space:]]*<AutoLogon([[:space:]>])/,/^[[:space:]]*<\/AutoLogon>[[:space:]]*$/d' \
|
||||||
|
"$asset" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEditionXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
local edition
|
local edition
|
||||||
|
|
||||||
|
[ -n "${EDITION:-}" ] || return 0
|
||||||
|
|
||||||
edition=$(normalizeServerEdition "$EDITION") || return 1
|
edition=$(normalizeServerEdition "$EDITION") || return 1
|
||||||
edition="${edition//-/}"
|
edition="${edition//-/}"
|
||||||
edition="${edition^^}"
|
edition="${edition^^}"
|
||||||
|
|
||||||
edition=$(escapeXMLSed "$edition") || return 1
|
edition=$(escapeXMLSed "$edition") || return 1
|
||||||
sed -i "s|SERVERSTANDARD</Value>|SERVER$edition</Value>|g" "$asset" || return 1
|
|
||||||
|
|
||||||
fi
|
sed -i \
|
||||||
|
"s|SERVERSTANDARD</Value>|SERVER$edition</Value>|g" \
|
||||||
|
"$asset" || return 1
|
||||||
|
|
||||||
if [ -n "${KEY:-}" ]; then
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProductKeyXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
local key
|
local key
|
||||||
|
|
||||||
|
[ -n "${KEY:-}" ] || return 0
|
||||||
|
|
||||||
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 "s|<ProductKey>[^<]*</ProductKey>|<ProductKey>$key</ProductKey>|g" "$asset" || return 1
|
sed -i -E \
|
||||||
sed -i "s|</UserData>| <ProductKey>\n <Key>$key</Key>\n <WillShowUI>OnError</WillShowUI>\n </ProductKey>\n </UserData>|g" "$asset" || return 1
|
'/^[[: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 \
|
||||||
|
"s|</UserData>| <ProductKey>\n <Key>$key</Key>\n <WillShowUI>OnError</WillShowUI>\n </ProductKey>\n </UserData>|g" \
|
||||||
|
"$asset" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSharedFolderXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
|
||||||
|
if ! disabled "${SHORTCUT:-}" &&
|
||||||
|
! disabled "${SAMBA:-}"; then
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if disabled "${SHORTCUT:-}" || disabled "${SAMBA:-}"; then
|
|
||||||
if ! sed -i -E '
|
if ! sed -i -E '
|
||||||
/<SynchronousCommand([[:space:]>])/ {
|
/<SynchronousCommand([[:space:]>])/ {
|
||||||
:command
|
:command
|
||||||
@@ -871,10 +977,17 @@ updateXML() {
|
|||||||
/<Description>Map shared folder<\/Description>/d
|
/<Description>Map shared folder<\/Description>/d
|
||||||
}
|
}
|
||||||
' "$asset"; then
|
' "$asset"; then
|
||||||
|
|
||||||
error "Failed to remove shared folder shortcuts from answer file!"
|
error "Failed to remove shared folder shortcuts from answer file!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
validateGeneratedXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
|
||||||
if ! xmllint --nonet --noout "$asset"; then
|
if ! xmllint --nonet --noout "$asset"; then
|
||||||
error "The generated answer file is not valid XML!"
|
error "The generated answer file is not valid XML!"
|
||||||
@@ -884,6 +997,49 @@ updateXML() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateXML() {
|
||||||
|
|
||||||
|
local asset="$1"
|
||||||
|
local language="$2"
|
||||||
|
local domain="${DOMAIN:-}"
|
||||||
|
local workgroup="${WORKGROUP:-}"
|
||||||
|
local account=""
|
||||||
|
local auth=""
|
||||||
|
|
||||||
|
[ -z "${WIDTH:-}" ] && WIDTH="1280"
|
||||||
|
[ -z "${HEIGHT:-}" ] && HEIGHT="720"
|
||||||
|
|
||||||
|
validateXMLSettings || return 1
|
||||||
|
updateDisplayXML "$asset" || return 1
|
||||||
|
updateLocaleXML "$asset" "$language" || return 1
|
||||||
|
|
||||||
|
if [ -n "$domain" ]; then
|
||||||
|
prepareDomainAccount "$domain" account auth || return 1
|
||||||
|
else
|
||||||
|
updateLocalAccountXML "$asset" || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i -E \
|
||||||
|
"s|<PlainText>[^<]*</PlainText>|<PlainText>false</PlainText>|g" \
|
||||||
|
"$asset" || return 1
|
||||||
|
|
||||||
|
updateMembershipXML \
|
||||||
|
"$asset" \
|
||||||
|
"$domain" \
|
||||||
|
"$workgroup" \
|
||||||
|
"$account" \
|
||||||
|
"$auth" || return 1
|
||||||
|
|
||||||
|
updateAutologinXML "$asset" || return 1
|
||||||
|
enableLog "$asset" || return 1
|
||||||
|
updateEditionXML "$asset" || return 1
|
||||||
|
updateProductKeyXML "$asset" || return 1
|
||||||
|
removeSharedFolderXML "$asset" || return 1
|
||||||
|
validateGeneratedXML "$asset" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
escapeSIFValue() {
|
escapeSIFValue() {
|
||||||
|
|
||||||
local s="$1"
|
local s="$1"
|
||||||
@@ -974,50 +1130,70 @@ validateLegacyUsername() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
addLegacyDrivers() {
|
extractLegacyDrivers() {
|
||||||
|
|
||||||
|
local drivers="$1"
|
||||||
|
|
||||||
|
rm -rf "$drivers" || return 1
|
||||||
|
mkdir -p "$drivers" || return 1
|
||||||
|
|
||||||
|
if ! bsdtar -xf /var/drivers.txz -C "$drivers"; then
|
||||||
|
error "Failed to extract drivers!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
copyLegacyStorageDriver() {
|
||||||
|
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local target="$2"
|
local target="$2"
|
||||||
local driver="$3"
|
local driver="$3"
|
||||||
local arch="$4"
|
local arch="$4"
|
||||||
local drivers="$5"
|
local drivers="$5"
|
||||||
local file
|
local destination="$dir/\$OEM\$/\$1/Drivers/viostor"
|
||||||
local msg="Adding drivers to image..."
|
|
||||||
|
|
||||||
info "$msg" && html "$msg"
|
|
||||||
|
|
||||||
rm -rf "$drivers" || return 1
|
|
||||||
mkdir -p "$drivers" || return 1
|
|
||||||
|
|
||||||
if ! bsdtar -xf /var/drivers.txz -C "$drivers"; then
|
|
||||||
error "Failed to extract drivers!" && return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$drivers/viostor/$driver/$arch/viostor.sys" ]; then
|
if [ ! -f "$drivers/viostor/$driver/$arch/viostor.sys" ]; then
|
||||||
error "Failed to locate required storage drivers!" && return 1
|
error "Failed to locate required storage drivers!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$target" || return 1
|
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$target" || return 1
|
||||||
|
|
||||||
mkdir -p "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
|
mkdir -p "$destination" || return 1
|
||||||
cp -L "$drivers/viostor/$driver/$arch/viostor.cat" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
|
cp -L "$drivers/viostor/$driver/$arch/viostor.cat" "$destination" || return 1
|
||||||
cp -L "$drivers/viostor/$driver/$arch/viostor.inf" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
|
cp -L "$drivers/viostor/$driver/$arch/viostor.inf" "$destination" || return 1
|
||||||
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
|
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$destination" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
addLegacyNetworkDriver() {
|
||||||
|
|
||||||
|
local dir="$1"
|
||||||
|
local driver="$2"
|
||||||
|
local arch="$3"
|
||||||
|
local drivers="$4"
|
||||||
|
local destination="$dir/\$OEM\$/\$1/Drivers/NetKVM"
|
||||||
|
|
||||||
if [ ! -f "$drivers/NetKVM/$driver/$arch/netkvm.sys" ]; then
|
if [ ! -f "$drivers/NetKVM/$driver/$arch/netkvm.sys" ]; then
|
||||||
error "Failed to locate required network drivers!" && return 1
|
error "Failed to locate required network drivers!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
|
mkdir -p "$destination" || return 1
|
||||||
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.cat" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
|
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.cat" "$destination" || return 1
|
||||||
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.inf" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
|
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.inf" "$destination" || return 1
|
||||||
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.sys" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
|
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.sys" "$destination" || return 1
|
||||||
|
|
||||||
file=$(find "$target" -maxdepth 1 -type f -iname TXTSETUP.SIF -print -quit) || return 1
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if [ -z "$file" ]; then
|
patchLegacyStorageDriver() {
|
||||||
error "The file TXTSETUP.SIF could not be found!" && return 1
|
|
||||||
fi
|
local file="$1"
|
||||||
|
local arch="$2"
|
||||||
|
|
||||||
sed -i '/^\[SCSI.Load\]/s/$/\nviostor=viostor.sys,4/' "$file" || return 1
|
sed -i '/^\[SCSI.Load\]/s/$/\nviostor=viostor.sys,4/' "$file" || return 1
|
||||||
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\nviostor.sys=1,,,,,,4_,4,1,,,1,4/' "$file" || return 1
|
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\nviostor.sys=1,,,,,,4_,4,1,,,1,4/' "$file" || return 1
|
||||||
@@ -1026,12 +1202,25 @@ addLegacyDrivers() {
|
|||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00020000=\"viostor\"/' "$file" || return 1
|
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00020000=\"viostor\"/' "$file" || return 1
|
||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00021AF4=\"viostor\"/' "$file" || return 1
|
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00021AF4=\"viostor\"/' "$file" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
addLegacySataDriver() {
|
||||||
|
|
||||||
|
local dir="$1"
|
||||||
|
local target="$2"
|
||||||
|
local arch="$3"
|
||||||
|
local drivers="$4"
|
||||||
|
local file="$5"
|
||||||
|
local destination="$dir/\$OEM\$/\$1/Drivers/sata"
|
||||||
|
|
||||||
if [ ! -d "$drivers/sata/xp/$arch" ]; then
|
if [ ! -d "$drivers/sata/xp/$arch" ]; then
|
||||||
error "Failed to locate required SATA drivers!" && return 1
|
error "Failed to locate required SATA drivers!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$dir/\$OEM\$/\$1/Drivers/sata" || return 1
|
mkdir -p "$destination" || return 1
|
||||||
cp -Lr "$drivers/sata/xp/$arch/." "$dir/\$OEM\$/\$1/Drivers/sata" || return 1
|
cp -Lr "$drivers/sata/xp/$arch/." "$destination" || return 1
|
||||||
cp -Lr "$drivers/sata/xp/$arch/." "$target" || return 1
|
cp -Lr "$drivers/sata/xp/$arch/." "$target" || return 1
|
||||||
|
|
||||||
sed -i '/^\[SCSI.Load\]/s/$/\niaStor=iaStor.sys,4/' "$file" || return 1
|
sed -i '/^\[SCSI.Load\]/s/$/\niaStor=iaStor.sys,4/' "$file" || return 1
|
||||||
@@ -1045,6 +1234,35 @@ addLegacyDrivers() {
|
|||||||
sed -i '/^\[SCSI\]/s/$/\niaStor=\"Intel\(R\) SATA RAID\/AHCI Controller\"/' "$file" || return 1
|
sed -i '/^\[SCSI\]/s/$/\niaStor=\"Intel\(R\) SATA RAID\/AHCI Controller\"/' "$file" || return 1
|
||||||
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_8086\&DEV_2922\&CC_0106=\"iaStor\"/' "$file" || return 1
|
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_8086\&DEV_2922\&CC_0106=\"iaStor\"/' "$file" || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
addLegacyDrivers() {
|
||||||
|
|
||||||
|
local dir="$1"
|
||||||
|
local target="$2"
|
||||||
|
local driver="$3"
|
||||||
|
local arch="$4"
|
||||||
|
local drivers="$5"
|
||||||
|
local file
|
||||||
|
local msg="Adding drivers to image..."
|
||||||
|
|
||||||
|
info "$msg" && html "$msg"
|
||||||
|
|
||||||
|
extractLegacyDrivers "$drivers" || return 1
|
||||||
|
copyLegacyStorageDriver "$dir" "$target" "$driver" "$arch" "$drivers" || return 1
|
||||||
|
addLegacyNetworkDriver "$dir" "$driver" "$arch" "$drivers" || return 1
|
||||||
|
|
||||||
|
file=$(find "$target" -maxdepth 1 -type f -iname TXTSETUP.SIF -print -quit) || return 1
|
||||||
|
|
||||||
|
if [ -z "$file" ]; then
|
||||||
|
error "The file TXTSETUP.SIF could not be found!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
patchLegacyStorageDriver "$file" "$arch" || return 1
|
||||||
|
addLegacySataDriver "$dir" "$target" "$arch" "$drivers" "$file" || return 1
|
||||||
|
|
||||||
rm -rf "$drivers" || return 1
|
rm -rf "$drivers" || return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -1060,34 +1278,31 @@ setLegacyKey() {
|
|||||||
|
|
||||||
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
|
[[ -n "$setup" ]] || return 0
|
||||||
|
[[ -z "$KEY" ]] || return 0
|
||||||
|
|
||||||
pid=$(<"$setup") || return 1
|
pid=$(<"$setup") || return 1
|
||||||
pid="${pid%$'\r'}"
|
pid="${pid%$'\r'}"
|
||||||
|
|
||||||
if [[ "$driver" == "2k" ]]; then
|
if [[ "$driver" == "2k" ]]; then
|
||||||
|
echo "${pid::-3}270" > "$setup" || return 1
|
||||||
echo "${pid:0:$((${#pid})) - 3}270" > "$setup" || return 1
|
return 0
|
||||||
|
fi
|
||||||
else
|
|
||||||
|
|
||||||
if [[ "$pid" == *"270" ]]; then
|
if [[ "$pid" == *"270" ]]; then
|
||||||
|
|
||||||
warn "this version of $desc requires a volume license key (VLK), it will ask for one during installation."
|
warn "this version of $desc requires a volume license key (VLK), it will ask for one during installation."
|
||||||
|
return 0
|
||||||
else
|
fi
|
||||||
|
|
||||||
file=$(find "$target" -maxdepth 1 -type f -iname PID.INF -print -quit) || return 1
|
file=$(find "$target" -maxdepth 1 -type f -iname PID.INF -print -quit) || return 1
|
||||||
|
|
||||||
if [ -n "$file" ]; then
|
if [[ -n "$file" ]]; then
|
||||||
|
|
||||||
if [[ "$driver" == "2k3" ]]; then
|
if [[ "$driver" == "2k3" ]]; then
|
||||||
|
|
||||||
key=$(grep -i -A 2 "StagingKey" "$file" | tail -n 2 | head -n 1) || key=""
|
key=$(grep -i -A 2 "StagingKey" "$file" | tail -n 2 | head -n 1) || key=""
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
key="${pid:$((${#pid})) - 8:5}"
|
key="${pid: -8:5}"
|
||||||
|
|
||||||
if [[ "${pid^^}" == *"OEM" ]]; then
|
if [[ "${pid^^}" == *"OEM" ]]; then
|
||||||
key=$(grep -i -A 2 "$key" "$file" | tail -n 2 | head -n 1) || key=""
|
key=$(grep -i -A 2 "$key" "$file" | tail -n 2 | head -n 1) || key=""
|
||||||
@@ -1104,7 +1319,7 @@ setLegacyKey() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$KEY" ]; then
|
[[ -n "$KEY" ]] && return 0
|
||||||
|
|
||||||
# These are NOT pirated keys, they come from official MS documentation.
|
# These are NOT pirated keys, they come from official MS documentation.
|
||||||
|
|
||||||
@@ -1133,15 +1348,7 @@ setLegacyKey() {
|
|||||||
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "${pid:0:$((${#pid})) - 3}000" > "$setup" || return 1
|
echo "${pid::-3}000" > "$setup" || return 1
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -1150,13 +1357,12 @@ writeCommand() {
|
|||||||
|
|
||||||
local install="$1"
|
local install="$1"
|
||||||
|
|
||||||
[ -z "$install" ] && return 0
|
[ -f "$install" ] || return 0
|
||||||
[ ! -f "$install" ] && return 0
|
|
||||||
|
|
||||||
if ! enabled "${LOG:-}"; then
|
if enabled "${LOG:-}"; then
|
||||||
printf '%s' "\"Script\"=\"cmd /C start \\\"Install\\\" \\\"cmd /C C:\\\\OEM\\\\install.bat\\\"\""
|
|
||||||
else
|
|
||||||
printf '%s' "\"Script\"=\"cmd /C start \\\"Install\\\" \\\"cmd /C C:\\\\OEM\\\\install.bat > C:\\\\OEM\\\\install.log 2>&1\\\"\""
|
printf '%s' "\"Script\"=\"cmd /C start \\\"Install\\\" \\\"cmd /C C:\\\\OEM\\\\install.bat > C:\\\\OEM\\\\install.log 2>&1\\\"\""
|
||||||
|
else
|
||||||
|
printf '%s' "\"Script\"=\"cmd /C start \\\"Install\\\" \\\"cmd /C C:\\\\OEM\\\\install.bat\\\"\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -1458,7 +1664,8 @@ legacyInstall() {
|
|||||||
ETFS="[BOOT]/Boot-NoEmul.img"
|
ETFS="[BOOT]/Boot-NoEmul.img"
|
||||||
|
|
||||||
if [ ! -f "$dir/$ETFS" ] || [ ! -s "$dir/$ETFS" ]; then
|
if [ ! -f "$dir/$ETFS" ] || [ ! -s "$dir/$ETFS" ]; then
|
||||||
error "Failed to locate file \"$ETFS\" in $desc ISO image!" && return 1
|
error "Failed to locate file \"$ETFS\" in $desc ISO image!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local arch="amd64"
|
local arch="amd64"
|
||||||
@@ -1468,7 +1675,8 @@ legacyInstall() {
|
|||||||
[[ "${arch,,}" == "x86" ]] && target="$dir/I386"
|
[[ "${arch,,}" == "x86" ]] && target="$dir/I386"
|
||||||
|
|
||||||
if [ ! -d "$target" ]; then
|
if [ ! -d "$target" ]; then
|
||||||
error "Failed to locate directory \"$target\" in $desc ISO image!" && return 1
|
error "Failed to locate directory \"$target\" in $desc ISO image!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${driver,,}" == "xp" || "${driver,,}" == "2k3" ]]; then
|
if [[ "${driver,,}" == "xp" || "${driver,,}" == "2k3" ]]; then
|
||||||
@@ -1484,7 +1692,8 @@ legacyInstall() {
|
|||||||
mkdir -p "$dir/\$OEM\$" || return 1
|
mkdir -p "$dir/\$OEM\$" || return 1
|
||||||
|
|
||||||
if ! addFolder "$dir"; then
|
if ! addFolder "$dir"; then
|
||||||
error "Failed to add OEM folder to image!" && return 1
|
error "Failed to add OEM folder to image!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local oem=""
|
local oem=""
|
||||||
|
|||||||
+182
-137
@@ -184,7 +184,7 @@ getVersions() {
|
|||||||
groups_ref=()
|
groups_ref=()
|
||||||
indexes_ref=()
|
indexes_ref=()
|
||||||
|
|
||||||
platform=$(getPlatform "$xml")
|
platform=$(getPlatform "$xml") || return 1
|
||||||
count=$(xmllint --nonet --xpath 'count(/WIM/IMAGE)' - 2>/dev/null <<< "$xml") || return 0
|
count=$(xmllint --nonet --xpath 'count(/WIM/IMAGE)' - 2>/dev/null <<< "$xml") || return 0
|
||||||
|
|
||||||
for ((i=1; i<=count; i++)); do
|
for ((i=1; i<=count; i++)); do
|
||||||
@@ -245,10 +245,10 @@ getVersions() {
|
|||||||
|
|
||||||
case "${candidate_base,,}" in
|
case "${candidate_base,,}" in
|
||||||
"winvista"* | "win7"* | "win8"* | "win10"* | "win11"* )
|
"winvista"* | "win7"* | "win8"* | "win10"* | "win11"* )
|
||||||
structured=$(normalizeEditionID "${edition_id:-${flags:-}}" "$candidate_base")
|
structured=$(normalizeEditionID "${edition_id:-${flags:-}}" "$candidate_base") || return 1
|
||||||
;;
|
;;
|
||||||
"win20"* )
|
"win20"* )
|
||||||
structured=$(normalizeServerEditionID "${flags:-$edition_id}")
|
structured=$(normalizeServerEditionID "${flags:-$edition_id}") || return 1
|
||||||
|
|
||||||
# Some media use the same EDITIONID for Core and Desktop images.
|
# Some media use the same EDITIONID for Core and Desktop images.
|
||||||
# INSTALLATIONTYPE provides the structural distinction without
|
# INSTALLATIONTYPE provides the structural distinction without
|
||||||
@@ -342,7 +342,7 @@ selectEdition() {
|
|||||||
if [ -n "$EDITION" ]; then
|
if [ -n "$EDITION" ]; then
|
||||||
|
|
||||||
for base in "${edition_bases[@]}"; do
|
for base in "${edition_bases[@]}"; do
|
||||||
edition=$("$normalize_name" "$EDITION" "$base")
|
edition=$("$normalize_name" "$EDITION" "$base") || return 1
|
||||||
preferred+=("$base${edition:+-$edition}")
|
preferred+=("$base${edition:+-$edition}")
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -444,7 +444,7 @@ detectVersion() {
|
|||||||
versions \
|
versions \
|
||||||
bases \
|
bases \
|
||||||
groups \
|
groups \
|
||||||
image_indexes
|
image_indexes || return 1
|
||||||
|
|
||||||
[ "${#versions[@]}" -eq 0 ] && return 0
|
[ "${#versions[@]}" -eq 0 ] && return 0
|
||||||
|
|
||||||
@@ -479,7 +479,7 @@ detectLanguage() {
|
|||||||
|
|
||||||
local xml="$1"
|
local xml="$1"
|
||||||
local index="${2:-}"
|
local index="${2:-}"
|
||||||
local xpath lang
|
local xpath lang culture
|
||||||
|
|
||||||
if [[ "$index" =~ ^[0-9]+$ ]]; then
|
if [[ "$index" =~ ^[0-9]+$ ]]; then
|
||||||
xpath="string((/WIM/IMAGE[@INDEX='$index']/WINDOWS/LANGUAGES/DEFAULT | /WIM/IMAGE[@INDEX='$index']/WINDOWS/LANGUAGES/FALLBACK/DEFAULT)[1])"
|
xpath="string((/WIM/IMAGE[@INDEX='$index']/WINDOWS/LANGUAGES/DEFAULT | /WIM/IMAGE[@INDEX='$index']/WINDOWS/LANGUAGES/FALLBACK/DEFAULT)[1])"
|
||||||
@@ -494,9 +494,12 @@ detectLanguage() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local culture
|
culture=$(getLanguage "$lang" "culture") || return 1
|
||||||
culture=$(getLanguage "$lang" "culture")
|
|
||||||
[ -n "$culture" ] && LANGUAGE="$lang" && return 0
|
if [ -n "$culture" ]; then
|
||||||
|
LANGUAGE="$lang"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
warn "Invalid language detected: \"$lang\""
|
warn "Invalid language detected: \"$lang\""
|
||||||
return 0
|
return 0
|
||||||
@@ -517,60 +520,105 @@ skipVersion() {
|
|||||||
detectLegacy() {
|
detectLegacy() {
|
||||||
|
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local find
|
local marker
|
||||||
|
|
||||||
[[ "${PLATFORM,,}" != "x64" ]] && return 1
|
[[ "${PLATFORM,,}" == "x64" ]] || return 1
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN95 -print -quit)
|
marker=$(find "$dir" -maxdepth 1 -type d -iname WIN95 -print -quit) || return 1
|
||||||
[ -n "$find" ] && DETECTED="win95" && return 0
|
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN98 -print -quit)
|
if [ -n "$marker" ]; then
|
||||||
[ -n "$find" ] && DETECTED="win98" && return 0
|
DETECTED="win95"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN9X -print -quit)
|
marker=$(find "$dir" -maxdepth 1 -type d -iname WIN98 -print -quit) || return 1
|
||||||
[ -n "$find" ] && DETECTED="win9x" && return 0
|
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_W.40 -print -quit)
|
if [ -n "$marker" ]; then
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_S.40 -print -quit)
|
DETECTED="win98"
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_TS.40 -print -quit)
|
return 0
|
||||||
[ -n "$find" ] && DETECTED="winnt4" && return 0
|
fi
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_NT.5 -print -quit)
|
marker=$(find "$dir" -maxdepth 1 -type d -iname WIN9X -print -quit) || return 1
|
||||||
|
|
||||||
if [ -n "$find" ]; then
|
if [ -n "$marker" ]; then
|
||||||
|
DETECTED="win9x"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IA.5 -print -quit)
|
marker=$(find "$dir" -maxdepth 1 -type f \
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_ID.5 -print -quit)
|
\( \
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IP.5 -print -quit)
|
-iname CDROM_W.40 -o \
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IS.5 -print -quit)
|
-iname CDROM_S.40 -o \
|
||||||
[ -n "$find" ] && DETECTED="win2k" && return 0
|
-iname CDROM_TS.40 \
|
||||||
|
\) \
|
||||||
|
-print -quit) || return 1
|
||||||
|
|
||||||
|
if [ -n "$marker" ]; then
|
||||||
|
DETECTED="winnt4"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
marker=$(find "$dir" -maxdepth 1 -type f -iname CDROM_NT.5 -print -quit) || return 1
|
||||||
|
|
||||||
|
if [ -n "$marker" ]; then
|
||||||
|
|
||||||
|
marker=$(find "$dir" -maxdepth 1 -type f \
|
||||||
|
\( \
|
||||||
|
-iname CDROM_IA.5 -o \
|
||||||
|
-iname CDROM_ID.5 -o \
|
||||||
|
-iname CDROM_IP.5 -o \
|
||||||
|
-iname CDROM_IS.5 \
|
||||||
|
\) \
|
||||||
|
-print -quit) || return 1
|
||||||
|
|
||||||
|
if [ -n "$marker" ]; then
|
||||||
|
DETECTED="win2k"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -iname WIN51 -print -quit)
|
marker=$(find "$dir" -maxdepth 1 -iname WIN51 -print -quit) || return 1
|
||||||
|
[ -n "$marker" ] || return 1
|
||||||
|
|
||||||
if [ -n "$find" ]; then
|
marker=$(find "$dir" -maxdepth 1 -type f -iname WIN51AP -print -quit) || return 1
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AP -print -quit)
|
if [ -n "$marker" ]; then
|
||||||
[ -n "$find" ] && DETECTED="winxpx64" && return 0
|
DETECTED="winxpx64"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IC -print -quit)
|
marker=$(find "$dir" -maxdepth 1 -type f \
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IP -print -quit)
|
\( \
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname setupxp.htm -print -quit)
|
-iname WIN51IC -o \
|
||||||
[ -n "$find" ] && DETECTED="winxpx86" && return 0
|
-iname WIN51IP -o \
|
||||||
|
-iname setupxp.htm \
|
||||||
|
\) \
|
||||||
|
-print -quit) || return 1
|
||||||
|
|
||||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IS -print -quit)
|
if [ -n "$marker" ]; then
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IA -print -quit)
|
DETECTED="winxpx86"
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IB -print -quit)
|
return 0
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51ID -print -quit)
|
fi
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IL -print -quit)
|
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AA -print -quit)
|
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AD -print -quit)
|
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AS -print -quit)
|
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51MA -print -quit)
|
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51MD -print -quit)
|
|
||||||
[ -n "$find" ] && DETECTED="win2003r2" && return 0
|
|
||||||
|
|
||||||
|
marker=$(find "$dir" -maxdepth 1 -type f \
|
||||||
|
\( \
|
||||||
|
-iname WIN51IS -o \
|
||||||
|
-iname WIN51IA -o \
|
||||||
|
-iname WIN51IB -o \
|
||||||
|
-iname WIN51ID -o \
|
||||||
|
-iname WIN51IL -o \
|
||||||
|
-iname WIN51AA -o \
|
||||||
|
-iname WIN51AD -o \
|
||||||
|
-iname WIN51AS -o \
|
||||||
|
-iname WIN51MA -o \
|
||||||
|
-iname WIN51MD \
|
||||||
|
\) \
|
||||||
|
-print -quit) || return 1
|
||||||
|
|
||||||
|
if [ -n "$marker" ]; then
|
||||||
|
DETECTED="win2003r2"
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
@@ -607,15 +655,15 @@ resolveImage() {
|
|||||||
setImage() {
|
setImage() {
|
||||||
|
|
||||||
skipVersion "${DETECTED,,}" && return 0
|
skipVersion "${DETECTED,,}" && return 0
|
||||||
|
setXML "" && return 0
|
||||||
|
enabled "$MANUAL" && return 0
|
||||||
|
|
||||||
if ! setXML "" && ! enabled "$MANUAL"; then
|
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
|
|
||||||
local desc
|
local desc
|
||||||
desc=$(printEdition "$DETECTED" "this version")
|
desc=$(printEdition "$DETECTED" "this version") || return 1
|
||||||
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,20 +725,19 @@ getSuggestion() {
|
|||||||
validateEdition() {
|
validateEdition() {
|
||||||
|
|
||||||
[ -n "$EDITION" ] || return 0
|
[ -n "$EDITION" ] || return 0
|
||||||
|
[[ "${DETECTED,,}" == "win20"* ]] || return 0
|
||||||
|
|
||||||
case "${DETECTED,,}" in
|
|
||||||
"win20"* )
|
|
||||||
local edition
|
local edition
|
||||||
edition=$(normalizeServerEditionID "$EDITION")
|
edition=$(normalizeServerEditionID "$EDITION") || return 1
|
||||||
|
|
||||||
if [ -n "$edition" ] &&
|
[ -n "$edition" ] || return 0
|
||||||
[[ "${DETECTED,,}" != *"-${edition,,}" &&
|
|
||||||
"${DETECTED,,}" != *"-${edition,,}-eval" ]]; then
|
if [[ "${DETECTED,,}" == *"-${edition,,}" ||
|
||||||
EDITION=""
|
"${DETECTED,,}" == *"-${edition,,}-eval" ]]; then
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
EDITION=""
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,13 +762,12 @@ describeImage() {
|
|||||||
local result_name="$3"
|
local result_name="$3"
|
||||||
local result
|
local result
|
||||||
|
|
||||||
result=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
result=$(printEdition "$DETECTED" "$DETECTED" "Y") || return 1
|
||||||
|
detectLanguage "$info_xml" "$index" || return 1
|
||||||
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") || return 1
|
||||||
result+=" ($language)"
|
result+=" ($language)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -745,12 +791,17 @@ configureImage() {
|
|||||||
local msg="the answer file for $desc was not found ($DETECTED.xml)"
|
local msg="the answer file for $desc was not found ($DETECTED.xml)"
|
||||||
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
||||||
|
|
||||||
if setXML "$fallback" "$index" || enabled "$MANUAL"; then
|
if setXML "$fallback" "$index"; then
|
||||||
! enabled "$MANUAL" && warn "${msg}."
|
if ! enabled "$MANUAL"; then
|
||||||
else
|
warn "${msg}."
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
enabled "$MANUAL" && return 0
|
||||||
|
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
warn "${msg}, $FB."
|
warn "${msg}, $FB."
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -763,9 +814,7 @@ detectImage() {
|
|||||||
|
|
||||||
XML=""
|
XML=""
|
||||||
|
|
||||||
resolveImage "$version" || :
|
if resolveImage "$version"; then
|
||||||
|
|
||||||
if [ -n "$DETECTED" ]; then
|
|
||||||
setImage || return 1
|
setImage || return 1
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -773,7 +822,7 @@ detectImage() {
|
|||||||
info "Detecting version from ISO image..."
|
info "Detecting version from ISO image..."
|
||||||
|
|
||||||
if detectLegacy "$dir"; then
|
if detectLegacy "$dir"; then
|
||||||
desc=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
desc=$(printEdition "$DETECTED" "$DETECTED" "Y") || return 1
|
||||||
info "Detected: $desc"
|
info "Detected: $desc"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -811,7 +860,6 @@ normalizeBatch() {
|
|||||||
local file="$1"
|
local file="$1"
|
||||||
local bom tmp encoding
|
local bom tmp encoding
|
||||||
|
|
||||||
[ ! -f "$file" ] && return 0
|
|
||||||
[ ! -s "$file" ] && return 0
|
[ ! -s "$file" ] && return 0
|
||||||
|
|
||||||
bom=$(od -An -N2 -tx1 "$file" | tr -d ' \n') || return 1
|
bom=$(od -An -N2 -tx1 "$file" | tr -d ' \n') || return 1
|
||||||
@@ -842,6 +890,30 @@ normalizeBatch() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reportBatchMatches() {
|
||||||
|
|
||||||
|
local file="$1"
|
||||||
|
local source="$2"
|
||||||
|
local pattern="$3"
|
||||||
|
local message="$4"
|
||||||
|
local suggestion="$5"
|
||||||
|
local matches line
|
||||||
|
|
||||||
|
matches=$(grep -Pin "$pattern" "$file" || true)
|
||||||
|
|
||||||
|
[ -n "$matches" ] || return 0
|
||||||
|
|
||||||
|
warn "$message in $source:"
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
printf ' %s\n' "$line" >&2
|
||||||
|
done <<< "$matches"
|
||||||
|
|
||||||
|
printf ' %s\n\n' "$suggestion" >&2
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
checkBatch() {
|
checkBatch() {
|
||||||
|
|
||||||
local file="$1"
|
local file="$1"
|
||||||
@@ -936,75 +1008,35 @@ EOC
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$tmp"
|
rm -rf "$tmp" || true
|
||||||
|
|
||||||
matches=$(
|
reportBatchMatches \
|
||||||
grep -Pin \
|
"$file" \
|
||||||
|
"$source" \
|
||||||
'(?<!\\)\\host[.]lan[\\]' \
|
'(?<!\\)\\host[.]lan[\\]' \
|
||||||
"$file" || true
|
"invalid single-backslash UNC path detected" \
|
||||||
)
|
'Use "\\host.lan\Data\..." instead of "\host.lan\Data\...".'
|
||||||
|
|
||||||
if [ -n "$matches" ]; then
|
reportBatchMatches \
|
||||||
warn "invalid single-backslash UNC path detected in $source:"
|
"$file" \
|
||||||
|
"$source" \
|
||||||
while IFS= read -r line; do
|
|
||||||
printf ' %s\n' "$line" >&2
|
|
||||||
done <<< "$matches"
|
|
||||||
|
|
||||||
printf '%s\n\n' \
|
|
||||||
' Use "\\host.lan\Data\..." instead of "\host.lan\Data\...".' >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
matches=$(
|
|
||||||
grep -Pin \
|
|
||||||
'(?<![\\[:alnum:]._-])host[.]lan[\\]' \
|
'(?<![\\[:alnum:]._-])host[.]lan[\\]' \
|
||||||
"$file" || true
|
"UNC path without leading backslashes detected" \
|
||||||
)
|
'Use "\\host.lan\Data\..." instead of "host.lan\Data\...".'
|
||||||
|
|
||||||
if [ -n "$matches" ]; then
|
reportBatchMatches \
|
||||||
warn "UNC path without leading backslashes detected in $source:"
|
"$file" \
|
||||||
|
"$source" \
|
||||||
while IFS= read -r line; do
|
|
||||||
printf ' %s\n' "$line" >&2
|
|
||||||
done <<< "$matches"
|
|
||||||
|
|
||||||
printf '%s\n\n' \
|
|
||||||
' Use "\\host.lan\Data\..." instead of "host.lan\Data\...".' >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
matches=$(
|
|
||||||
grep -Pin \
|
|
||||||
'//host[.]lan/' \
|
'//host[.]lan/' \
|
||||||
"$file" || true
|
"invalid forward-slash UNC path detected" \
|
||||||
)
|
'Use "\\host.lan\Data\..." instead of "//host.lan/Data/...".'
|
||||||
|
|
||||||
if [ -n "$matches" ]; then
|
reportBatchMatches \
|
||||||
warn "invalid forward-slash UNC path detected in $source:"
|
"$file" \
|
||||||
|
"$source" \
|
||||||
while IFS= read -r line; do
|
|
||||||
printf ' %s\n' "$line" >&2
|
|
||||||
done <<< "$matches"
|
|
||||||
|
|
||||||
printf '%s\n\n' \
|
|
||||||
' Use "\\host.lan\Data\..." instead of "//host.lan/Data/...".' >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
matches=$(
|
|
||||||
grep -Pin \
|
|
||||||
'\\\\host[.]lan\\shared(?:[\\/]|$)' \
|
'\\\\host[.]lan\\shared(?:[\\/]|$)' \
|
||||||
"$file" || true
|
"invalid Samba share name detected" \
|
||||||
)
|
'The "/shared" folder is exposed to Windows as "\\host.lan\Data".'
|
||||||
|
|
||||||
if [ -n "$matches" ]; then
|
|
||||||
warn "invalid Samba share name detected in $source:"
|
|
||||||
|
|
||||||
while IFS= read -r line; do
|
|
||||||
printf ' %s\n' "$line" >&2
|
|
||||||
done <<< "$matches"
|
|
||||||
|
|
||||||
printf '%s\n\n' \
|
|
||||||
' The "/shared" folder is exposed to Windows as "\\host.lan\Data".' >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -1134,7 +1166,10 @@ buildImage() {
|
|||||||
local hide="Warning: creating filesystem that does not conform to ISO-9660."
|
local hide="Warning: creating filesystem that does not conform to ISO-9660."
|
||||||
|
|
||||||
[ -s "$log" ] && err="$(<"$log")"
|
[ -s "$log" ] && err="$(<"$log")"
|
||||||
[[ "$err" != "$hide" ]] && echo "$err"
|
|
||||||
|
if [ -n "$err" ] && [[ "$err" != "$hide" ]]; then
|
||||||
|
echo "$err"
|
||||||
|
fi
|
||||||
|
|
||||||
mv -f "$out" "$BOOT" || return 1
|
mv -f "$out" "$BOOT" || return 1
|
||||||
|
|
||||||
@@ -1217,12 +1252,22 @@ extractBootImage() {
|
|||||||
|
|
||||||
rm -rf "$tmp" || true
|
rm -rf "$tmp" || true
|
||||||
|
|
||||||
if ! len=$(isoinfo -d -i "$iso" | grep "Nsect " | grep -o "[^ ]*$"); then
|
local boot_info
|
||||||
|
|
||||||
|
if ! boot_info=$(isoinfo -d -i "$iso"); then
|
||||||
|
error "Failed to read boot image information from $desc ISO!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
len=$(awk '/Nsect / { print $NF; exit }' <<< "$boot_info")
|
||||||
|
offset=$(awk '/Bootoff / { print $NF; exit }' <<< "$boot_info")
|
||||||
|
|
||||||
|
if [ -z "$len" ]; then
|
||||||
error "Failed to determine boot image size from $desc ISO!"
|
error "Failed to determine boot image size from $desc ISO!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! offset=$(isoinfo -d -i "$iso" | grep "Bootoff " | grep -o "[^ ]*$"); then
|
if [ -z "$offset" ]; then
|
||||||
error "Failed to determine boot image offset from $desc ISO!"
|
error "Failed to determine boot image offset from $desc ISO!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user