nx_coreutils_test.nx source
↩ module page · 112 lines · 5452 B
1// nx_coreutils_test.nx -- sovereign COREUTILS (the CLI daily-driver gap): cat / cp / mv / rm / ls,
2// built on real syscalls (sys_read_file, sys_openat_wr, sys_renameat, sys_getdents64, sys_mkdir).
3// NISHI rm = SOFT-DELETE to a trash dir (Rule 13: additive-only, history is sacred, reversible) --
4// NOT a hard unlink. KAT proves each on real files in /tmp. No persistent-hardware writes (Rule 26).
5// expect_exit: 0 license_tier: ORIGINAL
6import "nx_syscalls.nx"
7
8func cu_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
9func cu_putn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
10func beq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
11
12// cat -> read whole file into buf (caller-owned); returns length, or (0-1) if absent.
13func cu_read(path: *u8, buf: *u8, cap: i64) -> i64 {
14 let lenp: *i64 = sys_mmap(8) as *i64
15 let p: *u8 = sys_read_file(path, lenp)
16 if (p as i64)==0 { return 0-1 }
17 var n: i64 = lenp[0]
18 if n>cap { n=cap }
19 var i: i64=0
20 while i<n { buf[i]=p[i]; i=i+1 }
21 return n
22}
23func cu_write(path: *u8, buf: *u8, n: i64) -> i64 {
24 let fd: i64 = sys_openat_wr(path, 0x1a4)
25 if fd<=0 { return 0-1 }
26 sys_write(fd, buf, n)
27 sys_close(fd)
28 return 0
29}
30func cu_cp(src: *u8, dst: *u8) -> i64 {
31 let buf: *u8 = sys_mmap(1048576)
32 let n: i64 = cu_read(src, buf, 1048576)
33 if n<0 { return 0-1 }
34 return cu_write(dst, buf, n)
35}
36func cu_mv(src: *u8, dst: *u8) -> i64 { return sys_renameat(src, dst) }
37// rm = soft-delete: move into the trash dir (reversible; Rule 13)
38func cu_rm_soft(path: *u8, trash: *u8) -> i64 { return sys_renameat(path, trash) }
39// ls: getdents64 + print each name; returns entry count.
40func cu_ls(path: *u8) -> i64 {
41 let fd: i64 = sys_openat_rd(path)
42 if fd<0 { return 0-1 }
43 let buf: *u8 = sys_mmap(65536)
44 let nb: i64 = sys_getdents64(fd, buf, 65536)
45 sys_close(fd)
46 if nb<=0 { return 0 }
47 var off: i64=0
48 var c: i64=0
49 while off < nb {
50 let reclen: i64 = (buf[off+16] as i64) + ((buf[off+17] as i64)*256)
51 if reclen<=0 { off=nb } else {
52 var j: i64 = off+19
53 while buf[j]!=(0 as u8) { sys_write(1, ((buf as i64)+j) as *u8, 1); j=j+1 }
54 cu_puts(" " as *u8)
55 off = off + reclen
56 c = c + 1
57 }
58 }
59 cu_puts("\n" as *u8)
60 return c
61}
62
63func main() -> i64 {
64 cu_puts("SOVEREIGN COREUTILS KAT -- cat / cp / mv / rm(soft) / ls\n" as *u8)
65 let b: *u8 = sys_mmap(4096)
66 var pass: i64=0
67 var ttl: i64=0
68
69 // setup: write a known file
70 cu_write("/tmp/cu_a.txt\x00" as *u8, "hello nishi\x00" as *u8, 11)
71
72 // T1 cat: read it back, content matches
73 ttl=ttl+1
74 let n1: i64 = cu_read("/tmp/cu_a.txt\x00" as *u8, b, 4096)
75 cu_puts(" T1 cat (len=" as *u8); cu_putn(n1); cu_puts("): " as *u8)
76 if n1==11 { if beq(b, "hello nishi\x00" as *u8, 11)==1 { pass=pass+1; cu_puts("PASS\n" as *u8) } else { cu_puts("FAIL\n" as *u8) } } else { cu_puts("FAIL\n" as *u8) }
77
78 // T2 cp: copy, copy matches
79 ttl=ttl+1
80 cu_cp("/tmp/cu_a.txt\x00" as *u8, "/tmp/cu_b.txt\x00" as *u8)
81 let n2: i64 = cu_read("/tmp/cu_b.txt\x00" as *u8, b, 4096)
82 cu_puts(" T2 cp: " as *u8)
83 if n2==11 { if beq(b, "hello nishi\x00" as *u8, 11)==1 { pass=pass+1; cu_puts("PASS\n" as *u8) } else { cu_puts("FAIL\n" as *u8) } } else { cu_puts("FAIL\n" as *u8) }
84
85 // T3 mv: rename b->c; c exists, b gone
86 ttl=ttl+1
87 cu_mv("/tmp/cu_b.txt\x00" as *u8, "/tmp/cu_c.txt\x00" as *u8)
88 let nc: i64 = cu_read("/tmp/cu_c.txt\x00" as *u8, b, 4096)
89 let nb: i64 = cu_read("/tmp/cu_b.txt\x00" as *u8, b, 4096)
90 cu_puts(" T3 mv (c_len=" as *u8); cu_putn(nc); cu_puts(" b_gone=" as *u8); cu_putn(nb); cu_puts("): " as *u8)
91 if nc==11 { if nb<0 { pass=pass+1; cu_puts("PASS\n" as *u8) } else { cu_puts("FAIL\n" as *u8) } } else { cu_puts("FAIL\n" as *u8) }
92
93 // T4 rm(soft): move c into trash; c gone, trash has it (reversible)
94 ttl=ttl+1
95 sys_mkdir("/tmp/cu_trash\x00" as *u8, 0x1ff)
96 cu_rm_soft("/tmp/cu_c.txt\x00" as *u8, "/tmp/cu_trash/cu_c.txt\x00" as *u8)
97 let ngone: i64 = cu_read("/tmp/cu_c.txt\x00" as *u8, b, 4096)
98 let ntr: i64 = cu_read("/tmp/cu_trash/cu_c.txt\x00" as *u8, b, 4096)
99 cu_puts(" T4 rm-soft (c_gone=" as *u8); cu_putn(ngone); cu_puts(" trash_has=" as *u8); cu_putn(ntr); cu_puts(", reversible): " as *u8)
100 if ngone<0 { if ntr==11 { pass=pass+1; cu_puts("PASS\n" as *u8) } else { cu_puts("FAIL\n" as *u8) } } else { cu_puts("FAIL\n" as *u8) }
101
102 // T5 ls: list /tmp/cu_trash, >=1 entry
103 ttl=ttl+1
104 cu_puts(" T5 ls /tmp/cu_trash:\n " as *u8)
105 let lc: i64 = cu_ls("/tmp/cu_trash\x00" as *u8)
106 cu_puts(" entries=" as *u8); cu_putn(lc); cu_puts(": " as *u8)
107 if lc>=1 { pass=pass+1; cu_puts("PASS\n" as *u8) } else { cu_puts("FAIL\n" as *u8) }
108
109 cu_puts("COREUTILS-GATE passed " as *u8); cu_putn(pass); cu_puts("/" as *u8); cu_putn(ttl)
110 if pass==ttl { cu_puts(" verdict=GREEN (sovereign cat/cp/mv/rm-soft/ls; rm=additive-only per Rule 13)\n" as *u8); sys_exit(0); return 0 }
111 cu_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1
112}