code wiki / _hdl_build / nx_consol_apply_mc.nx

nx_consol_apply_mc.nx source

↩ module page · 170 lines · 8246 B

1// nx_consol_apply_mc.nx -- MULTI-CONSUMER consolidation applier (extends nx_consol_apply past the 2// zero-importer soundness limit). To retire a shadow of a LIB that N organs import, rebuild EVERY 3// importer + byte-compare each artifact before/after: CONSOLIDATED only if ALL importers are byte- 4// identical (the retired copy was dead for all of them), else REFUSE + restore (never-brick). This is 5// the COMPLETE behaviour-preservation proof for a multi-consumer shadow -- no consumer can silently 6// change. Importers come from the atlas/funcmine importer histogram (a file, one target per line). 7// argv: <shadow> <retire> <buildonly-elf> <importers-file> 8// Artifact convention: buildonly writes /tmp/<importer>.sov.elf (BEFORE saved to /tmp/<importer>.mcbefore). 9// exit: 0 CONSOLIDATED | 1 REFUSED (restored) | 2 usage/shadow-absent | 3 no buildable importer / move err 10// license_tier: ORIGINAL No hw writes (Rule 26). 11import "nx_seat_drive_lib.nx" 12import "nx_seg_store.nx" 13import "nx_deploy_lib.nx" 14import "nx_syscalls.nx" 15const MC_MAGIC_1048576: i64 = 1048576 16 17const MC_CAP: i64 = 4194304 18const MC_MAXI: i64 = 512 19 20func mc_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd >= 0 { sys_close(fd); return 1 } return 0 } 21func mc_read(path: *u8, buf: *u8, cap: i64) -> i64 { 22 let fd: i64 = sys_openat_rd(path) 23 if fd < 0 { return 0 - 1 } 24 var n: i64 = 0 25 var r: i64 = sys_read(fd, buf, cap - 1) 26 while r > 0 { n = n + r; if n >= cap - 1 { r = 0 } else { r = sys_read(fd, buf + n, cap - 1 - n) } } 27 sys_close(fd) 28 return n 29} 30func mc_eq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 { if an != bn { return 0 } var i: i64 = 0; while i < an { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 31// build importer T (target name span), snapshot /tmp/T.sov.elf -> outpath; returns artifact bytes or -1 32func mc_build_snap(buildelf: *u8, tname: *u8, artpath: *u8, snappath: *u8, buf: *u8) -> i64 { 33 // SOUNDNESS: unlink the artifact FIRST so a FAILED build leaves no stale artifact (which would 34 // otherwise read as a false "identical"). Its presence after == the build genuinely produced it. 35 sys_unlinkat(artpath) 36 let av: *i64 = sys_mmap(16) as *i64 37 av[0] = tname as i64 38 dep_run_capture(buildelf, av, 1, "/tmp/mc_build.log" as *u8) 39 let n: i64 = mc_read(artpath, buf, MC_CAP) 40 if n > 0 { if (snappath as i64) != 0 { ss_writefile(snappath, buf, n) } } 41 return n 42} 43 44func main(argc: i64, argv: *i64) -> i64 { 45 if argc < 5 { sd_w("usage: nx_consol_apply_mc <shadow> <retire> <buildonly-elf> <importers-file>\n" as *u8); sys_exit(2); return 2 } 46 let shadow: *u8 = argv[1] as *u8 47 let retire: *u8 = argv[2] as *u8 48 let buildelf: *u8 = argv[3] as *u8 49 let impfile: *u8 = argv[4] as *u8 50 if mc_exists(shadow) == 0 { 51 sd_w("NX-CONSOL-APPLY-MC verdict=ABORTED reason=shadow-file-not-found:" as *u8); sd_w(shadow) 52 sd_w(" fix=verify-the-path;-it-may-already-be-consolidated-(check-runtime/_retired_shadow/)\n" as *u8) 53 sys_exit(2); return 2 54 } 55 56 // read importers list (one basename per line) 57 let ib: *u8 = sys_mmap(MC_MAGIC_1048576) 58 let in2: i64 = mc_read(impfile, ib, MC_MAGIC_1048576) 59 if in2 <= 0 { 60 sd_w("NX-CONSOL-APPLY-MC verdict=ABORTED reason=no-importers-listed(empty-file)" as *u8) 61 sd_w(" fix=if-this-is-a-ZERO-importer-organ-use-single-target-nx_consol_apply-instead;-else-regenerate-the-importer-list\n" as *u8) 62 sys_exit(2); return 2 63 } 64 // store per-importer name spans + built flag 65 let noff: *i64 = sys_mmap(8 * MC_MAXI) as *i64 66 let nlen: *i64 = sys_mmap(8 * MC_MAXI) as *i64 67 let built: *i64 = sys_mmap(8 * MC_MAXI) as *i64 68 var ni: i64 = 0 69 var i: i64 = 0 70 while i < in2 { 71 var le: i64 = i 72 var s: i64 = 1 73 while s == 1 { if le >= in2 { s = 0 } else { if ib[le] == (10 as u8) { s = 0 } else { le = le + 1 } } } 74 if le > i { if ni < MC_MAXI { noff[ni] = i; nlen[ni] = le - i; ib[le] = 0 as u8; ni = ni + 1 } } 75 i = le + 1 76 } 77 78 let buf: *u8 = sys_mmap(MC_CAP) 79 let bufb: *u8 = sys_mmap(MC_CAP) 80 let art: *u8 = sys_mmap(512) 81 let snap: *u8 = sys_mmap(512) 82 var nbuilt: i64 = 0 83 84 // BEFORE: build each importer, snapshot 85 var k: i64 = 0 86 while k < ni { 87 let tn: *u8 = ((ib as i64) + noff[k]) as *u8 88 // art = /tmp/<tn>.sov.elf ; snap = /tmp/<tn>.mcbefore 89 var ao: i64 = sd_cat(art, 0, "/tmp/" as *u8) 90 ao = sd_cat(art, ao, tn) 91 ao = sd_cat(art, ao, ".sov.elf" as *u8) 92 var so: i64 = sd_cat(snap, 0, "/tmp/" as *u8) 93 so = sd_cat(snap, so, tn) 94 so = sd_cat(snap, so, ".mcbefore" as *u8) 95 let bn: i64 = mc_build_snap(buildelf, tn, art, snap, buf) 96 if bn > 0 { built[k] = 1; nbuilt = nbuilt + 1 } else { built[k] = 0 } 97 k = k + 1 98 } 99 if nbuilt == 0 { 100 sd_w("NX-CONSOL-APPLY-MC verdict=ABORTED reason=no-importer-could-be-built(no-baseline-to-compare)" as *u8) 101 sd_w(" fix=importer-names-may-be-non-buildable-by-bare-name-or-in-unscanned-dirs-resolve-them-to-real-build-targets;-or-the-importers-are-genuinely-broken(separate-debt)-fix-them-first. shadow-UNTOUCHED\n" as *u8) 102 sys_exit(3); return 3 103 } 104 105 // RETIRE the shadow 106 if sys_renameat(shadow, retire) != 0 { 107 sd_w("NX-CONSOL-APPLY-MC verdict=ABORTED reason=retire-move-failed(filesystem-error)" as *u8) 108 sd_w(" fix=ensure-the-retire-directory-exists-and-is-writable(mkdir-p-its-parent). shadow-UNTOUCHED\n" as *u8) 109 sys_exit(3); return 3 110 } 111 112 // AFTER: rebuild EVERY importer (built AND unbuilt) and require its outcome UNCHANGED. SOUND 113 // coverage: built-before -> must be byte-identical now; unbuilt-before -> must STILL not build 114 // (a before-broken importer that now builds is a CHANGE too -> refuse). No importer is a blind spot. 115 var changed: i64 = 0 116 k = 0 117 while k < ni { 118 let tn: *u8 = ((ib as i64) + noff[k]) as *u8 119 var ao: i64 = sd_cat(art, 0, "/tmp/" as *u8) 120 ao = sd_cat(art, ao, tn) 121 ao = sd_cat(art, ao, ".sov.elf" as *u8) 122 var so: i64 = sd_cat(snap, 0, "/tmp/" as *u8) 123 so = sd_cat(snap, so, tn) 124 so = sd_cat(snap, so, ".mcbefore" as *u8) 125 let an: i64 = mc_build_snap(buildelf, tn, art, 0 as *u8, buf) 126 if built[k] == 1 { 127 let sn: i64 = mc_read(snap, bufb, MC_CAP) 128 if an <= 0 { changed = changed + 1; sd_w("MC-CHANGED(build-broke) " as *u8); sd_w(tn); sd_w("\n" as *u8) } else { 129 if mc_eq(buf, an, bufb, sn) == 0 { changed = changed + 1; sd_w("MC-CHANGED " as *u8); sd_w(tn); sd_w("\n" as *u8) } 130 } 131 } else { 132 if an > 0 { changed = changed + 1; sd_w("MC-CHANGED(now-builds) " as *u8); sd_w(tn); sd_w("\n" as *u8) } 133 } 134 k = k + 1 135 } 136 137 if changed == 0 { 138 sd_w("NX-CONSOL-APPLY-MC verdict=CONSOLIDATED (all " as *u8) 139 let ob: *u8 = sys_mmap(32) 140 sd_num(ob, 0, ni) 141 sd_w(ob) 142 sd_w(" importers unchanged, " as *u8) 143 sd_num(ob, 0, nbuilt) 144 sd_w(ob) 145 sd_w(" built; shadow was dead) retired=" as *u8) 146 sd_w(retire) 147 sd_w("\n" as *u8) 148 sys_exit(0) 149 return 0 150 } 151 // some importer changed -> the shadow was LIVE for it -> RESTORE + REFUSE 152 if sys_renameat(retire, shadow) != 0 { 153 sd_w("NX-CONSOL-APPLY-MC verdict=REFUSED-AND-RESTORE-FAILED reason=an-importer-changed-AND-the-restore-move-failed shadow=" as *u8) 154 sd_w(shadow) 155 sd_w(" fix=MANUAL-RESTORE-NEEDED-move-" as *u8) 156 sd_w(retire) 157 sd_w("-back-to-" as *u8) 158 sd_w(shadow) 159 sd_w("-immediately\n" as *u8) 160 sys_exit(3) 161 return 3 162 } 163 sd_w("NX-CONSOL-APPLY-MC verdict=REFUSED reason=" as *u8) 164 let ob2: *u8 = sys_mmap(32) 165 sd_num(ob2, 0, changed) 166 sd_w(ob2) 167 sd_w("-importer(s)-changed-when-the-shadow-was-retired-so-the-shadow-is-LIVE(genuinely-used,-not-dead) fix=this-is-a-DIVERGENT-lib-not-a-dead-shadow:-resolve-by-RENAME+REPOINT(three-party-SHARP1)-not-retirement;-the-MC-CHANGED-line(s)-above-name-the-consumer(s)-that-resolve-the-retired-copy. shadow-RESTORED(safe)\n" as *u8) 168 sys_exit(1) 169 return 1 170}