fix(linux/build): keep file handle open through TF patch loop (M1.1 iter38)
All checks were successful
Build SilverMetal Linux ISO (reproducibility-gated) / builder-image (push) Successful in 1s
Build SilverMetal Linux ISO (reproducibility-gated) / build-and-verify (push) Successful in 35m9s

Run #4285 hit:

    Traceback (most recent call last):
      File "<stdin>", line 26, in <module>
    ValueError: seek of closed file

iter37's Python heredoc had the search/seek/write loop OUTSIDE the
`with open(...) as f:` block — the file closes when the `with` body
finishes, and `data = f.read()` was the only statement inside it.
Indent the loop inside the with-suite. No semantic changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 16:06:45 +01:00
parent 6bafa85231
commit 303f602d38

View File

@@ -313,38 +313,36 @@ post_process_for_reproducibility() {
# marker plus the filename anchors the location.
echo "post-process: byte-patching Rock Ridge TF dates on /live/filesystem.squashfs"
sudo --non-interactive python3 - "${iso_file}" <<'PYEOF'
import sys, struct
import sys
path = sys.argv[1]
TF_HDR = b'TF\x1a\x01\x0e' # "TF" length=26 ver=1 flags=0x0e
NAME_TAG = b'filesystem.squashfs' # appears in the NM Rock Ridge entry
patched = 0
with open(path, 'r+b') as f:
data = f.read()
# Find TF entries near a "filesystem.squashfs" NM tag. We don't trust
# any single anchor; require both within a 96-byte window so we don't
# accidentally rewrite some other TF entry that happens to be near
# the NM tag of a different file.
patched = 0
i = 0
while True:
j = data.find(TF_HDR, i)
if j < 0:
break
# Look for the filename within ~96 bytes after this TF header.
window = data[j:j + 96]
if NAME_TAG in window:
# Date 1 starts at j + 5; copy its 7 bytes onto Date 2 (j+12)
# and Date 3 (j+19).
creation = data[j + 5:j + 12]
if creation[3:7] != b'\x00\x00\x00\x00': # sanity: not all zeroes
# only patch if MOD or ACCESS actually differs from CREATION
if data[j + 12:j + 19] != creation or data[j + 19:j + 26] != creation:
f.seek(j + 12)
f.write(creation)
f.seek(j + 19)
f.write(creation)
patched += 1
print(f' patched TF at offset {j} (creation={creation.hex()})')
i = j + 1
i = 0
while True:
j = data.find(TF_HDR, i)
if j < 0:
break
# Look for the filename within ~96 bytes after this TF header
# — anchors both ends so we don't rewrite some other file's
# TF entry that happens to be near the NM tag.
window = data[j:j + 96]
if NAME_TAG in window:
# Date 1 (CREATION) starts at j+5, 7 bytes long.
# Copy onto Date 2 (MODIFICATION, j+12) and Date 3 (ACCESS, j+19).
creation = data[j + 5:j + 12]
if creation[0] != 0: # sanity: year byte must be non-zero
if (data[j + 12:j + 19] != creation
or data[j + 19:j + 26] != creation):
f.seek(j + 12)
f.write(creation)
f.seek(j + 19)
f.write(creation)
patched += 1
print(f' patched TF at offset {j} (creation={creation.hex()})')
i = j + 1
print(f'post-process: byte-patcher fixed {patched} TF entr{"y" if patched == 1 else "ies"}')
PYEOF