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}