feat: Improve ESD extraction (#1825)

This commit is contained in:
Kroese
2026-07-07 22:29:38 +02:00
committed by GitHub
parent de136699cc
commit 2436d0e764
+126 -94
View File
@@ -433,112 +433,140 @@ detectCustom() {
return 0 return 0
} }
getEsdFieldValue() {
local values="$1"
local index="$2"
awk -F: -v index="$index" '
NR == index {
gsub(/^[ \t]+|[ \t]+$/, "", $2)
print $2
}
' <<< "$values"
return 0
}
extractESD() { extractESD() {
local iso="$1" local iso="$1"
local dir="$2" local dir="$2"
local version="$3" local version="$3"
local desc="$4" local desc="$4"
local size sizes
local retVal total total1 total2 total3 total4
local imageIndex links links1 links2 links3 links4
local msg="Extracting $desc bootdisk" local msg ret index
local minSize freeSpace bootPad installPad
local info count totals links
local bootTotal bootLinks bootSize
local wimTotal wimLinks wimSize
local installSize
local bootWim installWim
local edition imgEdition
minSize=100000000
freeSpace=9606127360
bootPad=60000000
installPad=3000000
msg="Extracting $desc bootdisk"
info "$msg..." && html "$msg..." info "$msg..." && html "$msg..."
if [ "$(stat -c%s "$iso")" -lt 100000000 ]; then if [ "$(stat -c%s "$iso")" -lt "$minSize" ]; then
error "Invalid ESD file: Size is smaller than 100 MB" && return 1 error "Invalid ESD file: Size is smaller than 100 MB"
return 1
fi fi
rm -rf "$dir" rm -rf "$dir"
if ! makeDir "$dir"; then if ! makeDir "$dir"; then
error "Failed to create directory \"$dir\" !" && return 1 error "Failed to create directory \"$dir\" !"
return 1
fi fi
size=9606127360 checkFreeSpace "$dir" "$freeSpace" || return 1
checkFreeSpace "$dir" "$size" || return 1
local esdInfo info=$(wimlib-imagex info "$iso") || {
esdInfo=$(wimlib-imagex info "$iso") || {
error "Cannot read ESD file information!" error "Cannot read ESD file information!"
return 1 return 1
} }
local esdImageCount count=$(awk '/Image Count:/ {print $3}' <<< "$info")
esdImageCount=$(awk '/Image Count:/ {print $3}' <<< "$esdInfo")
if [ -z "$esdImageCount" ]; then if [[ ! "$count" =~ ^[0-9]+$ ]]; then
error "Cannot read the image count in ESD file!" && return 1 error "Cannot read the image count in ESD file!"
fi
if (( esdImageCount < 3 )); then
error "Invalid ESD file: expected at least 3 images, found $esdImageCount."
return 1 return 1
fi fi
sizes=$(grep "Total Bytes:" <<< "$esdInfo" || true) if (( count < 3 )); then
links=$(grep "Hard Link Bytes:" <<< "$esdInfo" || true) error "Invalid ESD file: expected at least 3 images, found $count."
return 1
fi
total1=$(awk "NR==1{ print; }" <<< "$sizes" | cut -d':' -f2 | sed 's/^ *//') totals=$(grep "Total Bytes:" <<< "$info" || true)
links1=$(awk "NR==1{ print; }" <<< "$links" | cut -d':' -f2 | sed 's/^ *//') links=$(grep "Hard Link Bytes:" <<< "$info" || true)
if [[ ! "$total1" =~ ^[0-9]+$ ]] || [[ ! "$links1" =~ ^[0-9]+$ ]]; then bootTotal=$(getEsdFieldValue "$totals" 1)
bootLinks=$(getEsdFieldValue "$links" 1)
if [[ ! "$bootTotal" =~ ^[0-9]+$ ]] || [[ ! "$bootLinks" =~ ^[0-9]+$ ]]; then
error "Cannot read bootdisk size from ESD file!" error "Cannot read bootdisk size from ESD file!"
return 1 return 1
fi fi
total=$(( total1 - links1 )) bootSize=$(( bootTotal - bootLinks ))
total3=$(awk "NR==3{ print; }" <<< "$sizes" | cut -d':' -f2 | sed 's/^ *//') wimTotal=$(getEsdFieldValue "$totals" 3)
links3=$(awk "NR==3{ print; }" <<< "$links" | cut -d':' -f2 | sed 's/^ *//') wimLinks=$(getEsdFieldValue "$links" 3)
if [[ ! "$total3" =~ ^[0-9]+$ ]] || [[ ! "$links3" =~ ^[0-9]+$ ]]; then if [[ ! "$wimTotal" =~ ^[0-9]+$ ]] || [[ ! "$wimLinks" =~ ^[0-9]+$ ]]; then
error "Cannot read bootdisk size from ESD file!" error "Cannot read boot.wim size from ESD file!"
return 1 return 1
fi fi
total3=$(( total3 - links3 )) wimSize=$(( wimTotal - wimLinks + bootPad ))
total3=$(( total3 + 60000000 ))
/run/progress.sh "$dir" "$total" "$msg ([P])..." & /run/progress.sh "$dir" "$bootSize" "$msg ([P])..." &
imageIndex="1" index="1"
wimlib-imagex apply "$iso" "$imageIndex" "$dir" --quiet 2>/dev/null || { wimlib-imagex apply "$iso" "$index" "$dir" --quiet 2>/dev/null || {
retVal=$? ret=$?
fKill "progress.sh" fKill "progress.sh"
error "Extracting $desc bootdisk failed ($retVal)" && return 1 error "Extracting $desc bootdisk failed ($ret)"
return 1
} }
fKill "progress.sh" fKill "progress.sh"
local bootWimFile="$dir/sources/boot.wim" bootWim="$dir/sources/boot.wim"
local installWimFile="$dir/sources/install.wim" installWim="$dir/sources/install.wim"
local msg="Extracting $desc environment" msg="Extracting $desc environment"
info "$msg..." && html "$msg..." info "$msg..." && html "$msg..."
imageIndex="2" index="2"
/run/progress.sh "$bootWimFile" "$total3" "$msg ([P])..." & /run/progress.sh "$bootWim" "$wimSize" "$msg ([P])..." &
wimlib-imagex export "$iso" "$imageIndex" "$bootWimFile" --compress=none --quiet || { wimlib-imagex export "$iso" "$index" "$bootWim" --compress=none --quiet || {
retVal=$? ret=$?
fKill "progress.sh" fKill "progress.sh"
error "Adding WinPE failed ($retVal)" && return 1 error "Adding WinPE failed ($ret)"
return 1
} }
fKill "progress.sh" fKill "progress.sh"
local msg="Extracting $desc setup" msg="Extracting $desc setup"
info "$msg..." info "$msg..."
imageIndex="3" index="3"
/run/progress.sh "$bootWimFile" "$total3" "$msg ([P])..." & /run/progress.sh "$bootWim" "$wimSize" "$msg ([P])..." &
wimlib-imagex export "$iso" "$imageIndex" "$bootWimFile" --compress=none --boot --quiet || { wimlib-imagex export "$iso" "$index" "$bootWim" --compress=none --boot --quiet || {
retVal=$? ret=$?
fKill "progress.sh" fKill "progress.sh"
error "Adding Windows Setup failed ($retVal)" && return 1 error "Adding Windows Setup failed ($ret)"
return 1
} }
fKill "progress.sh" fKill "progress.sh"
@@ -549,30 +577,31 @@ extractESD() {
LABEL="CPBA_A64FRE_EN-US_DV9" LABEL="CPBA_A64FRE_EN-US_DV9"
fi fi
local msg="Extracting $desc image" msg="Extracting $desc image"
info "$msg..." && html "$msg..." info "$msg..." && html "$msg..."
local edition imageEdition
edition=$(getCatalog "$version" "name") edition=$(getCatalog "$version" "name")
if [ -z "$edition" ]; then if [ -z "$edition" ]; then
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1 error "Invalid VERSION specified, value \"$version\" is not recognized!"
return 1
fi fi
for (( imageIndex=4; imageIndex<=esdImageCount; imageIndex++ )); do for (( index=4; index<=count; index++ )); do
imageEdition=$(wimlib-imagex info "$iso" "$imageIndex" | grep '^Description:' | sed 's/Description:[ \t]*//') imgEdition=$(wimlib-imagex info "$iso" "$index" | grep '^Description:' | sed 's/Description:[ \t]*//')
[[ "${imageEdition,,}" != "${edition,,}" ]] && continue [[ "${imgEdition,,}" != "${edition,,}" ]] && continue
total4=$(du -sb "$iso" | cut -f1) installSize=$(stat -c%s "$iso")
total4=$(( total4 + 3000000 )) installSize=$(( installSize + installPad ))
/run/progress.sh "$installWimFile" "$total4" "$msg ([P])..." & /run/progress.sh "$installWim" "$installSize" "$msg ([P])..." &
wimlib-imagex export "$iso" "$imageIndex" "$installWimFile" --compress=LZMS --chunk-size 128K --quiet || { wimlib-imagex export "$iso" "$index" "$installWim" --compress=LZMS --chunk-size 128K --quiet || {
retVal=$? ret=$?
fKill "progress.sh" fKill "progress.sh"
error "Addition of $imageIndex to the $desc image failed ($retVal)" && return 1 error "Addition of $index to the $desc image failed ($ret)"
return 1
} }
fKill "progress.sh" fKill "progress.sh"
@@ -581,7 +610,8 @@ extractESD() {
done done
fKill "progress.sh" fKill "progress.sh"
error "Failed to find product '$edition' in install.wim!" && return 1 error "Failed to find product '$edition' in install.wim!"
return 1
} }
extractImage() { extractImage() {
@@ -802,7 +832,7 @@ detectImage() {
local dir="$1" local dir="$1"
local version="$2" local version="$2"
local desc msg find language local desc msg language
XML="" XML=""
@@ -1107,10 +1137,10 @@ updateImage() {
local asset="$2" local asset="$2"
local language="$3" local language="$3"
local tmp="/tmp/install" local tmp="/tmp/install"
local file="autounattend.xml" local xml="autounattend.xml"
local org="${file//.xml/.org}" local bak="${xml//.xml/.org}"
local dat="${file//.xml/.dat}" local dat="${xml//.xml/.dat}"
local desc path src wim xml index result local desc path src wim name info idx
skipVersion "${DETECTED,,}" && return 0 skipVersion "${DETECTED,,}" && return 0
@@ -1128,28 +1158,30 @@ updateImage() {
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit) src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
error "failed to locate 'sources' folder in ISO image, $FB" && return 1 error "failed to locate 'sources' folder in ISO image, $FB"
return 1
fi fi
wim=$(find "$src" -maxdepth 1 -type f \( -iname boot.wim -or -iname boot.esd \) -print -quit) wim=$(find "$src" -maxdepth 1 -type f \( -iname boot.wim -or -iname boot.esd \) -print -quit)
if [ ! -f "$wim" ]; then if [ ! -f "$wim" ]; then
error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1 error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB"
return 1
fi fi
index="1" idx="1"
if ! result=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8); then if ! info=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8); then
warn "failed to read boot image information, $FB" warn "failed to read boot image information, $FB"
MANUAL="Y" MANUAL="Y"
result="" info=""
fi fi
if [[ "${result^^}" == *"<IMAGE INDEX=\"2\">"* ]]; then if [[ "${info^^}" == *"<IMAGE INDEX=\"2\">"* ]]; then
index="2" idx="2"
fi fi
if ! addDrivers "$src" "$tmp" "$wim" "$index" "$DETECTED"; then if ! addDrivers "$src" "$tmp" "$wim" "$idx" "$DETECTED"; then
error "Failed to add drivers to image!" error "Failed to add drivers to image!"
fi fi
@@ -1157,11 +1189,11 @@ updateImage() {
error "Failed to add OEM folder to image!" error "Failed to add OEM folder to image!"
fi fi
if wimlib-imagex extract "$wim" "$index" "/$file" "--dest-dir=$tmp" >/dev/null 2>&1; then if wimlib-imagex extract "$wim" "$idx" "/$xml" "--dest-dir=$tmp" >/dev/null 2>&1; then
if ! wimlib-imagex extract "$wim" "$index" "/$dat" "--dest-dir=$tmp" >/dev/null 2>&1; then if ! wimlib-imagex extract "$wim" "$idx" "/$dat" "--dest-dir=$tmp" >/dev/null 2>&1; then
if ! wimlib-imagex extract "$wim" "$index" "/$org" "--dest-dir=$tmp" >/dev/null 2>&1; then if ! wimlib-imagex extract "$wim" "$idx" "/$bak" "--dest-dir=$tmp" >/dev/null 2>&1; then
if ! wimlib-imagex update "$wim" "$index" --command "rename /$file /$org" > /dev/null; then if ! wimlib-imagex update "$wim" "$idx" --command "rename /$xml /$bak" > /dev/null; then
warn "failed to backup original answer file ($file)." warn "failed to backup original answer file ($xml)."
fi fi
fi fi
fi fi
@@ -1169,10 +1201,10 @@ updateImage() {
if ! enabled "$MANUAL"; then if ! enabled "$MANUAL"; then
xml=$(basename "$asset") name=$(basename "$asset")
local answer="$tmp/$xml" local answer="$tmp/$name"
info "Adding $xml for automatic installation..." info "Adding $name for automatic installation..."
if ! cp "$asset" "$answer"; then if ! cp "$asset" "$answer"; then
error "Failed to copy answer file to $answer." error "Failed to copy answer file to $answer."
@@ -1184,30 +1216,30 @@ updateImage() {
return 1 return 1
fi fi
if ! wimlib-imagex update "$wim" "$index" --command "add $answer /$file" > /dev/null; then if ! wimlib-imagex update "$wim" "$idx" --command "add $answer /$xml" > /dev/null; then
MANUAL="Y" MANUAL="Y"
warn "failed to add answer file ($xml) to ISO image, $FB" warn "failed to add answer file ($name) to ISO image, $FB"
else else
wimlib-imagex update "$wim" "$index" --command "add $answer /$dat" > /dev/null || true wimlib-imagex update "$wim" "$idx" --command "add $answer /$dat" > /dev/null || true
fi fi
fi fi
if enabled "$MANUAL"; then if enabled "$MANUAL"; then
wimlib-imagex update "$wim" "$index" --command "delete --force /$file" > /dev/null || true wimlib-imagex update "$wim" "$idx" --command "delete --force /$xml" > /dev/null || true
if wimlib-imagex extract "$wim" "$index" "/$org" "--dest-dir=$tmp" >/dev/null 2>&1; then if wimlib-imagex extract "$wim" "$idx" "/$bak" "--dest-dir=$tmp" >/dev/null 2>&1; then
if ! wimlib-imagex update "$wim" "$index" --command "add $tmp/$org /$file" > /dev/null; then if ! wimlib-imagex update "$wim" "$idx" --command "add $tmp/$bak /$xml" > /dev/null; then
warn "failed to restore original answer file ($org)." warn "failed to restore original answer file ($bak)."
fi fi
fi fi
fi fi
local find="$file" name="$xml"
enabled "$MANUAL" && find="$org" enabled "$MANUAL" && name="$bak"
path=$(find "$dir" -maxdepth 1 -type f -iname "$find" -print -quit) path=$(find "$dir" -maxdepth 1 -type f -iname "$name" -print -quit)
if [ -f "$path" ]; then if [ -f "$path" ]; then
if ! enabled "$MANUAL"; then if ! enabled "$MANUAL"; then