code wiki / _hdl_build / nx_mkdirp.nx
nx_mkdirp.nx source
↩ module page · 112 lines · 5094 B
1// nx_mkdirp.nx -- the missing sovereign mkdir-p MCP primitive: create a directory PATH (with parents).
2// The ecosystem had NO exposed mkdir verb (nx_fs_write cannot create parent dirs) -> knowledge/fetched/
3// never existed -> the ~119 *_research_fetch organs ALL SAVE-FAIL'd (seq191). This fills that gap.
4// GUARDED BY CONSTRUCTION (rule 12/26): path MUST start knowledge/ | sites/ | /tmp/ , NO '..' -> writes
5// confined to safe roots, never OS/system dirs. Idempotent (mkdirat EEXIST ignored). Pattern = the proven
6// __syscall(258=mkdirat, AT_FDCWD=-100, path, 0755) used across nx_manga_get_gate / nx_evidence_gather.
7// nx_mkdirp <relpath> -> creates each path component; prints MKDIRP OK <path>
8// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
9import "nx_syscalls.nx"
10const MP_MAGIC_1024: i64 = 1024
11
12const MP_OUT: i64 = 1
13const MP_ERR: i64 = 2
14
15func mp_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
16func mp_puts(s: *u8) -> i64 { sys_write(MP_OUT, s, mp_slen(s)); return 0 }
17func mp_werr(s: *u8) -> i64 { sys_write(MP_ERR, s, mp_slen(s)); return 0 }
18func mp_starts(p: *u8, pre: *u8) -> i64 {
19 var i: i64 = 0
20 while pre[i] != (0 as u8) {
21 if p[i] != pre[i] { return 0 }
22 i = i + 1
23 }
24 return 1
25}
26func mp_has_dotdot(p: *u8) -> i64 {
27 var i: i64 = 0
28 while p[i] != (0 as u8) {
29 if p[i] == (46 as u8) { if p[i+1] == (46 as u8) { return 1 } }
30 i = i + 1
31 }
32 return 0
33}
34func mp_prefix_ok(p: *u8) -> i64 {
35 if mp_starts(p, "knowledge/" as *u8) == 1 { return 1 }
36 if mp_starts(p, "sites/" as *u8) == 1 { return 1 }
37 if mp_starts(p, "/tmp/" as *u8) == 1 { return 1 }
38 return 0
39}
40// RUNTIME-COMPUTED syscall number: a LITERAL passes through the rv64->x86 constant-translate path
41// (nx_x86_64_ctx maps 34->258), so storing it first is the documented escape hatch (sys_symlinkat
42// "forced RUNTIME", nx_cms_gate `nb[0]=258`). Returns the RAW rc -- callers need the errno.
43func mp_mkdir_one(path: *u8) -> i64 {
44 let nbox: *i64 = sys_mmap(16) as *i64
45 nbox[0] = 258
46 let rc: i64 = __syscall(nbox[0], 0 - 100, path as i64, 0x1ed, 0, 0, 0)
47 sys_munmap(nbox as *u8, 16)
48 return rc
49}
50// A directory opens read-only on Linux, so this is a real existence probe, not an inference.
51func mp_exists(path: *u8) -> i64 {
52 let fd: i64 = sys_openat_rd(path)
53 if fd < 0 { return 0 }
54 sys_close(fd)
55 return 1
56}
57
58func main(argc: i64, argv: *i64) -> i64 {
59 if argc < 2 { mp_werr("usage: nx_mkdirp <relpath under knowledge/|sites/|/tmp/>\n" as *u8); sys_exit(1); return 1 }
60 let p: *u8 = argv[1] as *u8
61 if mp_has_dotdot(p) == 1 { mp_werr("REFUSED: path must not contain '..'\n" as *u8); sys_exit(2); return 2 }
62 if mp_prefix_ok(p) == 0 { mp_werr("REFUSED: path must start knowledge/ | sites/ | /tmp/\n" as *u8); sys_exit(3); return 3 }
63
64 let buf: *u8 = sys_mmap(MP_MAGIC_1024)
65 var i: i64 = 0
66 while p[i] != (0 as u8) { buf[i] = p[i]; i = i + 1 }
67 buf[i] = 0 as u8
68 let plen: i64 = i
69
70 var j: i64 = 1
71 while j < plen {
72 if buf[j] == (47 as u8) {
73 buf[j] = 0 as u8
74 mp_mkdir_one(buf)
75 buf[j] = 47 as u8
76 }
77 j = j + 1
78 }
79 let rc: i64 = mp_mkdir_one(buf)
80
81 // READ-BACK. This organ EXISTS because ~119 fetch organs silently save-failed on a missing dir --
82 // and it was reproducing that exact failure one layer up: it discarded the mkdirat rc and printed
83 // "MKDIRP OK" unconditionally. Measured 2026-08-01: it reported OK for knowledge/foundation/cred
84 // and the directory was never there, which sent a caller hunting a phantom root-mismatch.
85 // A WRITER IS ONLY TESTED BY A READ-BACK -- and the primitive every other writer depends on is
86 // the LAST place an unchecked success belongs.
87 if mp_exists(buf) == 0 {
88 // DISTINGUISH THE TWO FAILURES -- they have OPPOSITE remedies and reporting either as the
89 // other is what cost this session an hour. rc=-17 EEXIST + unopenable = the dir IS THERE and
90 // we lack permission (fix ownership); anything else = genuinely not created.
91 // nx_fs makes exactly this mistake, printing "ABSENT: cannot open dir" for EACCES.
92 mp_werr("MKDIRP FAILED: " as *u8); mp_werr(p)
93 if rc == 0 - 17 { mp_werr(" EXISTS but cannot be opened -- PERMISSION, not absence (rc=" as *u8) }
94 else { mp_werr(" was not created (rc=" as *u8) }
95 let t: *u8 = sys_mmap(32)
96 var m: i64 = rc
97 if m < 0 { mp_werr("-" as *u8); m = 0 - m }
98 var k: i64 = 0
99 if m == 0 { t[0] = 48 as u8; k = 1 }
100 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
101 let o: *u8 = sys_mmap(32)
102 var q: i64 = 0
103 while q < k { o[q] = t[k - 1 - q]; q = q + 1 }
104 sys_write(MP_ERR, o, k)
105 mp_werr("). NOT created -- do not treat this as success.\n" as *u8)
106 sys_exit(4)
107 return 4
108 }
109 mp_puts("MKDIRP OK " as *u8); mp_puts(p); mp_puts(" (verified present)\n" as *u8)
110 sys_exit(0)
111 return 0
112}