75 lines
5.3 KiB
Python
75 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Copy exact candidate and compile verified historical C17 clients only.
|
|
|
|
CONTRACT: exclusive campaign registration prevents another LAB/reset/retry.
|
|
WHY: historical client executable hashes were not sealed; source provenance was.
|
|
"""
|
|
import json, os, shutil, stat, subprocess, tempfile, ast, argparse
|
|
from pathlib import Path
|
|
from support import sha, command, save
|
|
OLD=Path('/home/fy59/swayfx-mosaic-static-runtime-hm5kbdkt')
|
|
OWNER=Path.home()/'swayfx-mosaic-static-rgb-input-retest-v1.owner'
|
|
p=argparse.ArgumentParser();p.add_argument('--resume-preparation',action='store_true');a=p.parse_args()
|
|
if a.resume_preparation:
|
|
# CONTRACT: only recover pre-run preparation in the same exclusive LAB.
|
|
# No ledger/reset, second LAB, completed preparation or executed run is allowed.
|
|
lab=Path(OWNER.read_text().strip()).resolve()
|
|
assert lab.is_dir() and (lab/'campaign-owner').read_text().strip()==str(OWNER)
|
|
assert not (lab/'run').exists() and not (lab/'results/budget.json').exists()
|
|
assert not (lab/'results/fixture-freeze-sha256.txt').exists()
|
|
else:
|
|
fd=os.open(OWNER,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
|
|
with os.fdopen(fd,'w') as f:
|
|
lab=Path(tempfile.mkdtemp(prefix='swayfx-mosaic-static-rgb-input-retest-',dir=Path.home()))
|
|
f.write(str(lab)+'\n');f.flush();os.fsync(f.fileno())
|
|
for name in ['results','raw']:(lab/name).mkdir()
|
|
(lab/'campaign-owner').write_text(str(OWNER)+'\n')
|
|
for name,digest in [('source','ed55bd418595ca977c022fa98917a899072cf3b6f0fb15457db823081046e797'),('evidence','e260ce5793ffc9a29ee4bfa2189663feeb6dc025bd46d3f5ddebccd225f3eef1')]:
|
|
manifest=OLD/'results'/(name+'-sha256.txt');assert sha(manifest)==digest
|
|
for line in manifest.read_text().splitlines():
|
|
h,p=line.split(' ',1);assert sha(p)==h,p
|
|
binary=OLD/'stage-static/usr/bin/swayfx-mosaic'
|
|
expected='f82557c1a9978a5e9665b9b4291b74880253725359e3df1c5b8d554921f7603b'
|
|
assert binary.is_file() and not binary.is_symlink() and os.access(binary,os.X_OK)
|
|
assert sha(binary)==expected and stat.S_IMODE(binary.stat().st_mode)==0o755
|
|
if not (lab/'swayfx-mosaic').exists():shutil.copy2(binary,lab/'swayfx-mosaic')
|
|
assert sha(lab/'swayfx-mosaic')==expected
|
|
elf=((lab/'raw/binary-elf.log').read_text() if a.resume_preparation else
|
|
command(lab,'binary-elf',['readelf','-hW','-nW','-dW',lab/'swayfx-mosaic']))
|
|
assert 'libscenefx' not in elf and '942db64269640778ee433e5970ba1100bc60f94c' in elf
|
|
assert 'ELF64' in elf and 'Advanced Micro Devices X86-64' in elf
|
|
# WHY: private static clip definitions are ordinary ELF symbols, not exports.
|
|
symbols=command(lab,'clip-symbols-static',['nm',lab/'swayfx-mosaic'])
|
|
assert all(' T '+s in symbols for s in ['wlr_scene_tree_set_clip','wlr_scene_tree_get_clip'])
|
|
assert '(RPATH)' not in elf and '(RUNPATH)' not in elf
|
|
loader=command(lab,'dependencies',['ldd','-r',lab/'swayfx-mosaic'])
|
|
assert 'not found' not in loader and 'undefined symbol' not in loader and 'libscenefx' not in loader
|
|
wl=Path('/usr/lib/libwlroots-0.20.so').resolve()
|
|
assert sha(wl)=='7edca9a7d65855addda68e29ba5db94d57c803eb5fa7d0f86db3136b90ca9837'
|
|
assert str(wl) in loader
|
|
save(lab,'binary-identity',{'status':'PASS','source':str(binary),'copy':str(lab/'swayfx-mosaic'),'sha256':expected,'build_id':'942db64269640778ee433e5970ba1100bc60f94c','mode':'0755','wlroots':str(wl),'wlroots_sha256':sha(wl),'new_compositor_builds':0})
|
|
shutil.copytree(OLD/'client-source',lab/'client-source')
|
|
flags=subprocess.check_output(['pkg-config','--cflags','--libs','wayland-client'],text=True).split()
|
|
clients=[]
|
|
for name,proto in [('saved-client','xdg-shell'),('static-reference','xdg-shell'),('pointer-daemon','virtual-pointer')]:
|
|
src=lab/'client-source';argv=['cc','-std=c17','-Wall','-Wextra','-Werror','-Wno-unused-parameter','-I'+str(src),src/(name+'.c'),src/(proto+'-protocol.c'),*flags]
|
|
command(lab,name+'-syntax',[*argv,'-fsyntax-only'])
|
|
command(lab,name+'-compile',[*argv,'-o',lab/name])
|
|
clients.append({'name':name,'source_sha256':sha(src/(name+'.c')),'binary_sha256':sha(lab/name),'historical_binary_sha256_unsealed':sha(OLD/name)})
|
|
save(lab,'client-provenance',{'historical':json.loads((OLD/'results/client-provenance.json').read_text()),'source_manifest_verified':True,'clients':clients})
|
|
save(lab,'source-provenance',{'clients':clients,'historical_manifests_verified':True,
|
|
'source_manifest_sha256':sha(OLD/'results/source-sha256.txt'),
|
|
'evidence_manifest_sha256':sha(OLD/'results/evidence-sha256.txt'),
|
|
'new_Mosaic_builds':0,'new_SceneFX_builds':0})
|
|
repo=Path(__file__).resolve().parents[3]
|
|
shutil.copytree(Path(__file__).parent,lab/'fixture')
|
|
(lab/'protocol-before-run.md').write_bytes((repo/'docs/design/STEP20C_STATIC_RGB_INPUT_STANDARD_RETEST.md').read_bytes())
|
|
for p in (lab/'fixture').glob('*.py'):ast.parse(p.read_text(),filename=str(p))
|
|
with (lab/'results/fixture-freeze-sha256.txt').open('x') as f:
|
|
for p in sorted((lab/'fixture').rglob('*')):
|
|
if p.is_file():f.write(f'{sha(p)} {p}\n')
|
|
f.write(f'{sha(lab/"protocol-before-run.md")} {lab/"protocol-before-run.md"}\n')
|
|
save(lab,'protected-before', {str(p):sha(p) for p in [Path('/usr/bin/sway'),
|
|
Path('/usr/lib/libwlroots-0.20.so').resolve(),Path('/usr/lib/libscenefx-0.5.so').resolve(),
|
|
repo/'PKGBUILD',repo/'patches/0001-mosaic-layout-viewport.patch',repo/'AGENTS.md',repo/'docs/UX.md']})
|
|
print('LAB='+str(lab))
|