code wiki / _hdl_build / nx_janitor_dupname.nx
nx_janitor_dupname.nx source
↩ module page · 96 lines · 5379 B
1// nx_janitor_dupname.nx -- the "dup" part of the janitor's X-JAN-002 sprawl half (nx_janitor_sprawl already
2// covers the "dead-organ"/orphaned-.tsv part; this is its sibling). It detects DUPLICATE ORGAN NAMES =
3// SHADOWING collisions: the SAME basename in BOTH runtime/_hdl_build/ AND runtime/. nx_sov_build_run probes
4// _hdl_build/ FIRST, so the _hdl_build copy SHADOWS the runtime one -- you run "nx_foo" by name and get the
5// WRONG organ. This is the exact bug found this session (TWO nx_sovereignty_audit.nx: a per-file in-content
6// checker shadowing the tree-walking debt counter). Sovereign getdents walk of the two dirs, intersect the
7// basenames, flag every shadowed organ. READ-ONLY (never-brick): it FLAGS; renaming/resolving stays operator-
8// gated (build pipelines + callers must be checked first). license_tier: ORIGINAL
9import "nx_syscalls.nx"
10
11func jdn_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i] {return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
12func jdn_is_nx(nm: *u8) -> i64 { var nl: i64=0; while nm[nl]!=(0 as u8){nl=nl+1} if nl>3 { if nm[nl-3]==(46 as u8) { if nm[nl-2]==(110 as u8) { if nm[nl-1]==(120 as u8) { return 1 } } } } return 0 }
13
14// collect .nx basenames from `dir` into fnames (NUL-term each) + fnoff[k]=start-offset; appends from startk.
15func jdn_collect(dir: *u8, fnames: *u8, fnoff: *i64, startk: i64, maxk: i64) -> i64 {
16 let fd: i64 = sys_openat_rd(dir); if fd < 0 { return startk }
17 let dbuf: *u8 = sys_mmap(131072)
18 var k: i64 = startk; var go: i64 = 1
19 while go == 1 {
20 let nb: i64 = sys_getdents64(fd, dbuf, 131072)
21 if nb <= 0 { go = 0 } else {
22 var off: i64 = 0
23 while off < nb {
24 let rec: *u8 = (dbuf as i64 + off) as *u8
25 let rl: i64 = dirent_reclen(rec)
26 if rl <= 0 { off = nb } else {
27 let nm: *u8 = dirent_name(rec)
28 if jdn_is_nx(nm) == 1 { if k < maxk {
29 let start: i64 = fnoff[k]
30 var c: i64 = 0; while nm[c] != (0 as u8) { fnames[start+c] = nm[c]; c = c + 1 } fnames[start+c] = 0 as u8
31 fnoff[k+1] = start + c + 1
32 k = k + 1
33 } }
34 off = off + rl
35 }
36 }
37 }
38 }
39 sys_close(fd)
40 return k
41}
42
43// scan both dirs in the runner's PROBE ORDER: _hdl_build first ([0,hcount)), then runtime ([hcount,NF)). NF.
44func jdn_scan(fnames: *u8, fnoff: *i64, hcount_out: *i64) -> i64 {
45 fnoff[0] = 0
46 let h: i64 = jdn_collect("runtime/_hdl_build\x00" as *u8, fnames, fnoff, 0, 30000)
47 hcount_out[0] = h
48 let nf: i64 = jdn_collect("runtime\x00" as *u8, fnames, fnoff, h, 30000)
49 return nf
50}
51
52// is the runtime entry at idx ([hcount,NF)) shadowed by an _hdl_build entry ([0,hcount))?
53func jdn_is_shadowed(fnames: *u8, fnoff: *i64, idx: i64, hcount: i64) -> i64 {
54 let nm: *u8 = (fnames as i64 + fnoff[idx]) as *u8
55 var j: i64 = 0
56 while j < hcount { if jdn_streq(nm, (fnames as i64 + fnoff[j]) as *u8) == 1 { return 1 } j = j + 1 }
57 return 0
58}
59// count shadowing collisions (runtime organs whose name is ALSO in _hdl_build -> the runtime one is unreachable).
60func jdn_collisions(fnames: *u8, fnoff: *i64, hcount: i64, NF: i64) -> i64 {
61 var c: i64 = 0; var i: i64 = hcount
62 while i < NF { if jdn_is_shadowed(fnames, fnoff, i, hcount) == 1 { c = c + 1 } i = i + 1 }
63 return c
64}
65// is a specific basename present in BOTH dirs (a named collision)?
66func jdn_is_collision(fnames: *u8, fnoff: *i64, hcount: i64, NF: i64, name: *u8) -> i64 {
67 var inh: i64 = 0; var j: i64 = 0
68 while j < hcount { if jdn_streq((fnames as i64 + fnoff[j]) as *u8, name) == 1 { inh = 1 } j = j + 1 }
69 if inh == 0 { return 0 }
70 var i: i64 = hcount
71 while i < NF { if jdn_streq((fnames as i64 + fnoff[i]) as *u8, name) == 1 { return 1 } i = i + 1 }
72 return 0
73}
74
75// ---- content classification: is a collision a dangerous SHADOW (different bytes) or a redundant COPY (same)? ----
76func jdn_read(path: *u8, buf: *u8, cap: i64) -> i64 {
77 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 - 1 }
78 var total: i64 = 0; var nrd: i64 = sys_read(fd, buf, cap)
79 while nrd > 0 { total = total + nrd; if total >= cap { nrd = 0 } else { nrd = sys_read(fd, ((buf as i64)+total) as *u8, cap-total) } }
80 sys_close(fd); return total
81}
82func jdn_path(pfx: *u8, name: *u8, out: *u8) -> i64 { var o: i64=0; var i: i64=0; while pfx[i]!=(0 as u8){out[o]=pfx[i];o=o+1;i=i+1} i=0; while name[i]!=(0 as u8){out[o]=name[i];o=o+1;i=i+1} out[o]=0 as u8; return o }
83// do runtime/<name> and runtime/_hdl_build/<name> DIFFER? 1 = SHADOW (different content, wrong organ runs) |
84// 0 = COPY (byte-identical, just redundant) | -1 = read error. Caller provides two reusable read buffers.
85func jdn_pair_differs(name: *u8, br: *u8, bh: *u8, cap: i64) -> i64 {
86 let pr: *u8 = sys_mmap(1024); let ph: *u8 = sys_mmap(1024)
87 jdn_path("runtime/\x00" as *u8, name, pr)
88 jdn_path("runtime/_hdl_build/\x00" as *u8, name, ph)
89 let lr: i64 = jdn_read(pr, br, cap); let lh: i64 = jdn_read(ph, bh, cap)
90 if lr < 0 { return 0 - 1 }
91 if lh < 0 { return 0 - 1 }
92 if lr != lh { return 1 }
93 var i: i64 = 0
94 while i < lr { if br[i] != bh[i] { return 1 } i = i + 1 }
95 return 0
96}