code wiki / (root) / nx_restage.nx

nx_restage.nx source

↩ module page · 101 lines · 6269 B

1// nx_restage.nx -- EAT THE DEPLOY-TOOLING DEBT (operator 2026-07-17 "eat the debt and build the tools"): 2// the missing primitive that restages a freshly-built elf into a build tree's _offc/. Without it, 3// buildroot/_offc generators go STALE vs runtime source (the F-004 stale-binary class: e.g. the compare 4// @verdict directive existed in nx_swcompare_sota.nx source but the staged _offc elf predated it, so the 5// SSOT verdict silently fell back to a hardcoded string). nx_fs_write refuses _offc (text + deny), nx_shelltool 6// is read-only, /api/build stages to nishihost not _offc -- so this closed gap blocked EVERY generator refresh. 7// nx_restage <target> [broot] broot default "buildroot" ("." = in-place / local test) 8// -> chdir broot; fork _offc/nx_sov_build_run.elf <target> --build-only (=> /tmp/<target>.sov.elf) 9// -> binary-safe copy to _offc/<target>.elf.new; VERIFY ELF magic + nonzero; atomic rename over _offc/<target>.elf 10// target sanitized [A-Za-z0-9_] (no path escape). Exit 0 restaged | 1 build/copy fail | 2 usage/bad-target. 11// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 12import "nx_tool_run.nx" 13const K_MAGIC_262144: i64 = 262144 14const K_MAGIC_65536: i64 = 65536 15 16func rp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17func rpe(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 } 18func rn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 19// append C-string src into dst at off; return new off 20func r_cat(dst: *u8, off: i64, src: *u8) -> i64 { var o: i64=off; var j: i64=0; while src[j]!=(0 as u8){dst[o]=src[j];o=o+1;j=j+1} return o } 21// target must be nonempty [A-Za-z0-9_], <64 chars. returns 1 ok / 0 reject. 22func r_san(name: *u8) -> i64 { 23 var i: i64 = 0 24 while name[i] != (0 as u8) { 25 let c: i64 = name[i] as i64 26 var ok: i64 = 0 27 if c >= 48 { if c <= 57 { ok = 1 } } // 0-9 28 if c >= 65 { if c <= 90 { ok = 1 } } // A-Z 29 if c >= 97 { if c <= 122 { ok = 1 } } // a-z 30 if c == 95 { ok = 1 } // _ 31 if ok == 0 { return 0 } 32 i = i + 1 33 if i >= 64 { return 0 } 34 } 35 if i == 0 { return 0 } 36 return 1 37} 38func main(argc: i64, argv: *i64) -> i64 { 39 if argc < 2 { rpe("usage: nx_restage <target> [buildroot]\n" as *u8); sys_exit(2); return 2 } 40 let target: *u8 = argv[1] as *u8 41 var broot: *u8 = "buildroot" as *u8 42 if argc >= 3 { broot = argv[2] as *u8 } 43 if r_san(target) == 0 { rpe("nx_restage: REFUSED bad target (need [A-Za-z0-9_], <64)\n" as *u8); sys_exit(2); return 2 } 44 if sys_chdir(broot) != 0 { rpe("nx_restage: cannot chdir buildroot\n" as *u8); sys_exit(1); return 1 } 45 46 // ---- build: fork _offc/nx_sov_build_run.elf <target> --build-only -> /tmp/<target>.sov.elf ---- 47 let av: *i64 = sys_mmap(64) as *i64 48 av[0] = "_offc/nx_sov_build_run.elf" as i64 49 av[1] = target as i64 50 av[2] = "--build-only" as i64 51 av[3] = 0 52 let cap: i64 = K_MAGIC_262144 53 let out: *u8 = sys_mmap(cap) 54 let ol: *i64 = sys_mmap(16) as *i64 55 let rc: i64 = tr_run_capture("_offc/nx_sov_build_run.elf" as *u8, av, out, cap, ol) 56 if rc != 0 { 57 rpe("nx_restage: BUILD FAILED rc=" as *u8); let d: *u8=sys_mmap(16); var m: i64=rc; if m<0{sys_write(2,"-" as *u8,1);m=0-m} var k: i64=0; if m==0{d[0]=48 as u8;k=1} while m>0{d[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var z: i64=0; let e: *u8=sys_mmap(16); while z<k{e[z]=d[k-1-z];z=z+1} sys_write(2,e,k); rpe("\n" as *u8) 58 if ol[0] > 0 { sys_write(2, out, ol[0]); rpe("\n" as *u8) } 59 sys_exit(1); return 1 60 } 61 62 // ---- paths ---- 63 let src: *u8 = sys_mmap(256) 64 // 2026-07-29 seq1267: runner emits buildroot/_build now (no-/tmp doctrine); we are post-chdir(broot), 65 // so the artifact is _build/<target>.sov.elf relative to the buildroot CWD. 66 var so: i64 = r_cat(src, 0, "_build/" as *u8); so = r_cat(src, so, target); so = r_cat(src, so, ".sov.elf" as *u8); src[so] = 0 as u8 67 let dnew: *u8 = sys_mmap(256) 68 var dno: i64 = r_cat(dnew, 0, "_offc/" as *u8); dno = r_cat(dnew, dno, target); dno = r_cat(dnew, dno, ".elf.new" as *u8); dnew[dno] = 0 as u8 69 let dst: *u8 = sys_mmap(256) 70 var dso: i64 = r_cat(dst, 0, "_offc/" as *u8); dso = r_cat(dst, dso, target); dso = r_cat(dst, dso, ".elf" as *u8); dst[dso] = 0 as u8 71 72 // ---- binary-safe copy src -> dnew, verify ELF magic on first bytes ---- 73 let fin: i64 = sys_openat_rd(src) 74 if fin < 0 { rpe("nx_restage: built elf missing in /tmp\n" as *u8); sys_exit(1); return 1 } 75 let fout: i64 = sys_openat_wr(dnew, 493) // 0755 executable 76 if fout < 0 { sys_close(fin); rpe("nx_restage: cannot open _offc/<target>.elf.new (write cap?)\n" as *u8); sys_exit(1); return 1 } 77 let buf: *u8 = sys_mmap(K_MAGIC_65536) 78 var total: i64 = 0 79 var magic_ok: i64 = 0 80 var go: i64 = 1 81 while go == 1 { 82 let r: i64 = sys_read(fin, buf, K_MAGIC_65536) 83 if r <= 0 { go = 0 } else { 84 if total == 0 { 85 if r >= 4 { if buf[0] == (127 as u8) { if buf[1] == (69 as u8) { if buf[2] == (76 as u8) { if buf[3] == (70 as u8) { magic_ok = 1 } } } } } 86 } 87 var w: i64 = 0 88 while w < r { let k: i64 = sys_write(fout, (buf as i64 + w) as *u8, r - w); if k <= 0 { go = 0; w = r } else { w = w + k } } 89 total = total + r 90 } 91 } 92 sys_close(fin) 93 sys_close(fout) 94 if total < 4 { rpe("nx_restage: copied 0 bytes\n" as *u8); sys_exit(1); return 1 } 95 if magic_ok == 0 { rpe("nx_restage: NOT an ELF (magic check failed) -- refusing to stage\n" as *u8); sys_exit(1); return 1 } 96 if sys_renameat(dnew, dst) != 0 { rpe("nx_restage: atomic rename into _offc failed\n" as *u8); sys_exit(1); return 1 } 97 98 rp("{\"action\":\"RESTAGED\",\"target\":\"" as *u8); rp(target); rp("\",\"path\":\"_offc/" as *u8); rp(target); rp(".elf\",\"bytes\":" as *u8); rn(total); rp("}\n" as *u8) 99 sys_exit(0) 100 return 0 101}