code wiki / (root) / nx_filecopy.nx

nx_filecopy.nx

buildroot/runtime/nx_filecopy.nx

9197 B168 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_filecopy.nx -- A COPY THAT PROVES IT COPIED (2026-08-07; STREAMING 2026-08-13). WHY IT EXISTS: `nx_gate_dry_apply` produces a migration candidate and `nx_gate_migrate verify` proves it judge-equivalent (exit code, verdict and the whole PASS/FAIL vector identical) -- and then the migration cannot be APPLIED, because nothing in the estate moves bytes from one path to another. `nx_filehash cmp` can tell you two files match; no organ can MAKE them match. A capability search over 938 tools returned no copier. So a proven-safe automated migration path was blocked on the most ordinary primitive there is. *AN AUTOMATED PATH THAT CANNOT APPLY ITS OWN RESULT IS A DEMONSTRATION, NOT A TOOL.* The alternative was round-tripping the candidate through JSON via read+write, and this codebase has already banked that chunked JSON re-assembly is NOT byte-faithful. A silent one-byte corruption in a GATE would be the mutation-class defect the estate has been bitten by twice. SO IT VERIFIES BY CONSTRUCTION: after writing, it RE-READS the destination and compares every byte to the source. A copy that did not land, landed short, or landed altered REPORTS FAILURE and exits non-zero. **AN UNVERIFIED COPY IS INDISTINGUISHABLE FROM A SUCCESSFUL ONE UNTIL SOMETHING DOWNSTREAM BREAKS** -- which for a gate means a silently weakened guard, the worst possible failure mode. 2026-08-13 STREAMING FIX (debt 1786597688): v1 read the WHOLE source into one 8MiB buffer and treated that read as the file -- so any source >8MiB was SILENTLY TRUNCATED and then "verified=1" against its own truncation (it verified what it copied, not the source; caught when an 8.8MB model banked as an 8,388,608-byte corrupt copy). Now: the 8MiB buffer is a CHUNK, the copy streams to source EOF, and the verify re-reads BOTH files in aligned chunks to EOF and requires identical totals. The buffer can never again masquerade as the population. OVERWRITE IS EXPLICIT. Clobbering an existing destination requires the literal 3rd arg `overwrite`, because for a migration the clobber IS the intent and for everything else it is an accident. nx_filecopy <src> <dst> [overwrite] exit 0 copied+verified | 1 verify FAILED | 2 io error | 3 usage/refused license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_filecopy.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main fce sys_write sys_exit fc_streq fc_exists sys_openat_rd sys_close sys_mmap nxa_die sys_write ↻ sys_exit ↻ nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ sys_openat_rd ↻ fc_chunk sys_read sys_close ↻ sys_openat_wr sys_write ↻ sys_fstatat nx_chmod fcp sys_write ↻ fcn fcp ↻ sys_mmap ↻ sys_write ↻

structs

none

consts

35const FC_CAP: i64 = 8388608 // CHUNK size, not a file-size cap -- both copy and verify stream to EOF

functions

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 }
called by 2: fcnmain calls 1: sys_write
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 }
called by 1: main calls 1: sys_write
39func fcn(v: i64) -> i64
called by 1: main calls 3: fcpsys_mmapsys_write
52func fc_exists(p: *u8) -> i64 { let fd: i64 = sys_openat_rd(p); if fd < 0 { return 0 } sys_close(fd); return 1 }
called by 1: main calls 2: sys_openat_rdsys_close
53func fc_streq(a: *u8, b: *u8) -> i64
called by 1: main
60func fc_chunk(fd: i64, buf: *u8, cap: i64) -> i64
called by 1: main calls 1: sys_read
71func main(argc: i64, argv: *i64) -> i64