the-custodian/docs/changes/netkingdom-target-2026-10-17/native-runtime-install-r2/build-transfer.py
codex ffd995213c
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Reject generated-only commits / generated-commit-guard (push) Successful in 8s
Record failed runtime trial and reviewed verification proposal (1/4)
2026-10-17 12:56:53 +02:00

71 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Deterministic public-runtime transfer; no runtime launch or network access."""
import argparse
import gzip
import hashlib
import importlib.util
import io
import json
import os
from pathlib import Path
import stat
import tarfile
ROOT = Path('/tmp/netkingdom-runtime-canonical-20261016/runtime')
EXPECTED = 'f59959b605a51abd2901becde14e7abd852c2bd3f848004b51d250d1cb81af6d'
HERE = Path(__file__).resolve().parent
class CountingHash:
def __init__(self, target=None):
self.target, self.hash, self.size = target, hashlib.sha256(), 0
def write(self, value):
self.hash.update(value); self.size += len(value)
if self.target: self.target.write(value)
return len(value)
def flush(self):
if self.target: self.target.flush()
def runtime_module():
p = HERE/'runtime.py'
spec = importlib.util.spec_from_file_location('reviewed_runtime_digest', p)
module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module)
return module
def build(target=None):
if runtime_module().runtime_digest(ROOT) != EXPECTED:
raise ValueError('source_runtime_changed')
result = CountingHash(target); logical = 0; members = 0
with gzip.GzipFile(filename='', mode='wb', compresslevel=6, mtime=0, fileobj=result) as stream:
with tarfile.open(fileobj=stream, mode='w|', format=tarfile.PAX_FORMAT) as archive:
for p in [ROOT, *sorted(ROOT.rglob('*'))]:
s=p.lstat(); name='runtime' + ('/'+p.relative_to(ROOT).as_posix() if p!=ROOT else '')
info=tarfile.TarInfo(name);info.uid=1000;info.gid=1000;info.mtime=0;info.mode=stat.S_IMODE(s.st_mode)
if stat.S_ISDIR(s.st_mode):info.type=tarfile.DIRTYPE
elif stat.S_ISLNK(s.st_mode):
info.type=tarfile.SYMTYPE; info.linkname=os.readlink(p)
if Path(info.linkname).is_absolute() or not p.resolve(strict=True).is_relative_to(ROOT):
raise ValueError('unsafe_runtime_symlink')
elif stat.S_ISREG(s.st_mode):info.type=tarfile.REGTYPE; info.size=s.st_size; logical += s.st_size
else:raise ValueError('runtime_special_file')
with p.open('rb') if stat.S_ISREG(s.st_mode) else io.BytesIO() as data:
archive.addfile(info,data if stat.S_ISREG(s.st_mode) else None)
members+=1
if runtime_module().runtime_digest(ROOT) != EXPECTED:
raise ValueError('source_runtime_changed_during_archive')
return {'sha256':'sha256:'+result.hash.hexdigest(),'bytes':result.size,'logical_file_bytes':logical,'members':members,
'format':'gzip mtime0; PAX tar; sorted tree; root runtime; UID/GID1000; modes and relative symlinks retained'}
def main():
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--output',type=Path)
args=parser.parse_args()
if args.output:
with args.output.open('xb') as stream:result=build(stream)
else:result=build()
print(json.dumps(result,sort_keys=True))
if __name__=='__main__':main()