nx_filecopy.nx source
↩ module page · 168 lines · 9197 B
1// nx_filecopy.nx -- A COPY THAT PROVES IT COPIED (2026-08-07; STREAMING 2026-08-13).
2//
3// WHY IT EXISTS: `nx_gate_dry_apply` produces a migration candidate and `nx_gate_migrate verify` proves
4// it judge-equivalent (exit code, verdict and the whole PASS/FAIL vector identical) -- and then the
5// migration cannot be APPLIED, because nothing in the estate moves bytes from one path to another.
6// `nx_filehash cmp` can tell you two files match; no organ can MAKE them match. A capability search over
7// 938 tools returned no copier. So a proven-safe automated migration path was blocked on the most
8// ordinary primitive there is.
9// *AN AUTOMATED PATH THAT CANNOT APPLY ITS OWN RESULT IS A DEMONSTRATION, NOT A TOOL.*
10//
11// The alternative was round-tripping the candidate through JSON via read+write, and this codebase has
12// already banked that chunked JSON re-assembly is NOT byte-faithful. A silent one-byte corruption in a
13// GATE would be the mutation-class defect the estate has been bitten by twice.
14//
15// SO IT VERIFIES BY CONSTRUCTION: after writing, it RE-READS the destination and compares every byte to
16// the source. A copy that did not land, landed short, or landed altered REPORTS FAILURE and exits
17// non-zero. **AN UNVERIFIED COPY IS INDISTINGUISHABLE FROM A SUCCESSFUL ONE UNTIL SOMETHING DOWNSTREAM
18// BREAKS** -- which for a gate means a silently weakened guard, the worst possible failure mode.
19//
20// 2026-08-13 STREAMING FIX (debt 1786597688): v1 read the WHOLE source into one 8MiB buffer and treated
21// that read as the file -- so any source >8MiB was SILENTLY TRUNCATED and then "verified=1" against its
22// own truncation (it verified what it copied, not the source; caught when an 8.8MB model banked as an
23// 8,388,608-byte corrupt copy). Now: the 8MiB buffer is a CHUNK, the copy streams to source EOF, and the
24// verify re-reads BOTH files in aligned chunks to EOF and requires identical totals. The buffer can
25// never again masquerade as the population.
26//
27// OVERWRITE IS EXPLICIT. Clobbering an existing destination requires the literal 3rd arg `overwrite`,
28// because for a migration the clobber IS the intent and for everything else it is an accident.
29//
30// nx_filecopy <src> <dst> [overwrite]
31// exit 0 copied+verified | 1 verify FAILED | 2 io error | 3 usage/refused
32// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
33import "nx_syscalls.nx"
34
35const FC_CAP: i64 = 8388608 // CHUNK size, not a file-size cap -- both copy and verify stream to EOF
36
37func fcp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
38func fce(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 }
39func fcn(v: i64) -> i64 {
40 var m: i64 = v
41 if m < 0 { fcp("-" as *u8); m = 0 - m }
42 let t: *u8 = sys_mmap(32)
43 var k: i64 = 0
44 if m == 0 { t[0] = 48 as u8; k = 1 }
45 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
46 let b: *u8 = sys_mmap(32)
47 var i: i64 = 0
48 while i < k { b[i] = t[k-1-i]; i = i + 1 }
49 sys_write(1, b, k)
50 return 0
51}
52func fc_exists(p: *u8) -> i64 { let fd: i64 = sys_openat_rd(p); if fd < 0 { return 0 } sys_close(fd); return 1 }
53func fc_streq(a: *u8, b: *u8) -> i64 {
54 var i: i64 = 0
55 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
56 if b[i] != (0 as u8) { return 0 }
57 return 1
58}
59// fill buf with up to cap bytes from fd; returns bytes read (0 = EOF)
60func fc_chunk(fd: i64, buf: *u8, cap: i64) -> i64 {
61 var n: i64 = 0
62 var r: i64 = 1
63 while r > 0 {
64 r = sys_read(fd, ((buf as i64) + n) as *u8, cap - n)
65 if r > 0 { n = n + r }
66 if n >= cap { r = 0 }
67 }
68 return n
69}
70
71func main(argc: i64, argv: *i64) -> i64 {
72 if argc < 3 { fce("usage: nx_filecopy <src> <dst> [overwrite]\n" as *u8); sys_exit(3); return 3 }
73 let src: *u8 = argv[1] as *u8
74 let dst: *u8 = argv[2] as *u8
75 if fc_streq(src, dst) == 1 { fce("nx_filecopy: REFUSED src == dst\n" as *u8); sys_exit(3); return 3 }
76 var over: i64 = 0
77 if argc >= 4 { let o: *u8 = argv[3] as *u8; if o[0] == (111 as u8) { over = 1 } }
78 if fc_exists(dst) == 1 { if over == 0 { fce("nx_filecopy: REFUSED destination exists; pass `overwrite` to replace it deliberately\n" as *u8); sys_exit(3); return 3 } }
79
80 let sbuf: *u8 = sys_mmap(FC_CAP)
81 let dbuf: *u8 = sys_mmap(FC_CAP)
82 let sfd: i64 = sys_openat_rd(src)
83 if sfd < 0 { fce("nx_filecopy: cannot read src\n" as *u8); sys_exit(2); return 2 }
84 // read the FIRST chunk before touching dst, so an empty source refuses without clobbering anything.
85 // A ZERO-BYTE SOURCE IS REFUSED: copying nothing over a real file is the silent-truncation shape
86 // that an "it succeeded" message would completely hide.
87 var chunk: i64 = fc_chunk(sfd, sbuf, FC_CAP)
88 if chunk == 0 { sys_close(sfd); fce("nx_filecopy: REFUSED empty source (copying 0 bytes over a destination is silent truncation)\n" as *u8); sys_exit(3); return 3 }
89 let fd: i64 = sys_openat_wr(dst, 0x1a4)
90 if fd < 0 { sys_close(sfd); fce("nx_filecopy: cannot open dst for write\n" as *u8); sys_exit(2); return 2 }
91 var total: i64 = 0
92 var more: i64 = 1
93 while more == 1 {
94 var w: i64 = 0
95 var werr: i64 = 0
96 while w < chunk {
97 let r: i64 = sys_write(fd, ((sbuf as i64) + w) as *u8, chunk - w)
98 if r <= 0 { werr = 1; w = chunk } else { w = w + r }
99 }
100 if werr == 1 { more = 0; total = 0 - 1 } else {
101 total = total + chunk
102 chunk = fc_chunk(sfd, sbuf, FC_CAP)
103 if chunk == 0 { more = 0 }
104 }
105 }
106 sys_close(sfd)
107 sys_close(fd)
108 if total < 0 { fce("nx_filecopy: write failed mid-copy; treat the destination as CORRUPT\n" as *u8); sys_exit(2); return 2 }
109
110 // VERIFY BY RE-READING BOTH FILES TO EOF in aligned chunks. The write returning a byte count proves
111 // the syscall accepted it, not that the bytes are on disk and correct -- and an artifact check that
112 // only asks "did the call succeed" is the defect this whole session kept finding.
113 let vs: i64 = sys_openat_rd(src)
114 let vd: i64 = sys_openat_rd(dst)
115 var ok: i64 = 1
116 if vs < 0 { ok = 0 }
117 if vd < 0 { ok = 0 }
118 var vtotal: i64 = 0
119 var going: i64 = ok
120 while going == 1 {
121 let a: i64 = fc_chunk(vs, sbuf, FC_CAP)
122 let b2: i64 = fc_chunk(vd, dbuf, FC_CAP)
123 if a != b2 { ok = 0; going = 0 } else {
124 if a == 0 { going = 0 } else {
125 var i: i64 = 0
126 while i < a { if sbuf[i] != dbuf[i] { ok = 0; i = a; going = 0 } else { i = i + 1 } }
127 vtotal = vtotal + a
128 }
129 }
130 }
131 if vs >= 0 { sys_close(vs) }
132 if vd >= 0 { sys_close(vd) }
133 if vtotal != total { ok = 0 }
134
135 if ok == 1 {
136 // ---- PRESERVE THE SOURCE MODE (2026-08-14) ------------------------------------------------
137 // ★★★★★★A BYTE-FOR-BYTE VERIFY IS STRUCTURALLY BLIND TO THE EXECUTE BIT, SO THIS ORGAN COULD
138 // REPORT verified=1 ON A COPY THAT CANNOT RUN. It opened the destination 0644 unconditionally,
139 // so copying ANY executable produced a byte-perfect INERT artifact -- and the failure is silent
140 // and total: a fork of it yields ZERO bytes, which reads exactly like a bug in the organ being
141 // tested rather than in the copy.
142 // MEASURED THE SAME DAY: four binaries installed into _offc/ with this tool were byte-identical
143 // to their promoted originals and unrunnable; a sibling seat independently measured the same
144 // shape from the other side (a byte-identical _offc artifact without +x read as FRESH to
145 // nx_offc_install, so it never reinstalled, and every gate forking it got nothing).
146 // ★THE FIX IS TO COPY WHAT A COPY MEANS: mode is part of the file, not decoration. Preserving the
147 // SOURCE's mode is also the least surprising contract -- a copier that silently downgrades
148 // permissions is a defect generator no byte check can catch.
149 // st_mode is a u32 at offset 24 of struct stat; only the low 12 permission bits are applied.
150 let sb: *u8 = sys_mmap(160)
151 var mode_applied: i64 = 0 - 1
152 if sys_fstatat(src, sb) >= 0 {
153 let m: i64 = ((sb[24] as i64) + ((sb[25] as i64) << 8)) & 4095
154 if m > 0 { nx_chmod(dst, m); mode_applied = m }
155 }
156 fcp("NX-FILECOPY OK bytes=" as *u8); fcn(total)
157 fcp(" verified=1 (destination re-read and compared byte-for-byte)" as *u8)
158 // ANNOUNCE IT: a mode that was NOT applied must be visible, or the next reader inherits exactly
159 // the silent-inert-artifact defect this line exists to close.
160 if mode_applied >= 0 { fcp(" mode_preserved=" as *u8); fcn(mode_applied) } else { fcp(" mode_preserved=UNKNOWN (could not stat src; destination keeps the default 0644 and may be INERT if it is an executable)" as *u8) }
161 fcp("\n" as *u8)
162 return 0
163 }
164 fce("NX-FILECOPY VERIFY-FAILED src_bytes=" as *u8)
165 fce(" -- destination does NOT match source; treat the destination as CORRUPT\n" as *u8)
166 sys_exit(1)
167 return 1
168}