code wiki / _hdl_build / nx_media_usable.nx
nx_media_usable.nx source
↩ module page · 85 lines · 5401 B
1// nx_media_usable.nx -- MEDIA USABILITY VERIFIER (operator 2026-07-04: "lots of our systems dont confirm if the
2// media is USABLE -- i have a bunch of broken books like comic books, table headers... keep going but flag this").
3// Serving != working: this organ opens a comic/image book the way the READER would and proves every page actually
4// DECODES (not just "the file exists"). Given a book dir (reader/<slug>), it reads cbx.json, then for each page:
5// missing on disk / 0-byte / undecodable-bytes (e.g. an HTML error page saved as .jpg) / tiny(junk) -> BROKEN.
6// decodes to real W*H via nx_img_dims (jpeg/png/gif/webp) -> OK.
7// Verdict: OK (all pages decode) | DEGRADED (some broken) | BROKEN (no manifest or 0 usable pages). Read-only; safe
8// on root-owned live book dirs (world-readable). Prints a machine-readable line so the library UI + a census can
9// consume it. This is the books/comics rung of the media-liveness plane; video/movie verifiers are separate rungs.
10// license_tier: ORIGINAL expect_exit: 0
11import "nx_syscalls.nx"
12import "nx_img_dims.nx"
13const MU_MAGIC_2048: i64 = 2048
14const MU_MAGIC_4096: i64 = 4096
15
16const MU_MIN_EDGE: i64 = 120 // a real readable page's long edge; below = nav-icon/spacer/broken (matches the manga junk floor's ethos; TODO svc-config)
17
18func mw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
19func mn(v: i64) -> i64 { let b: *u8=sys_mmap(24); var m: i64=v; if m<0{mw("-" as *u8);m=0-m} let t: *u8=sys_mmap(24); 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{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
20func mu_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
21func mu_apps(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[o+i]=s[i];i=i+1} return o+i }
22// find substring `needle` in buf[0..n) from `from`; return index or -1
23func mu_find(buf: *u8, n: i64, needle: *u8, from: i64) -> i64 {
24 var nl: i64=0; while needle[nl]!=(0 as u8){nl=nl+1}
25 var i: i64=from
26 while i + nl <= n { var j: i64=0; while j<nl { if buf[i+j]!=needle[j] {j=nl+9} else {j=j+1} } if j==nl {return i} i=i+1 }
27 return 0-1
28}
29
30// verify one book dir. writes counts into out[0]=total out[1]=ok out[2]=broken; returns verdict 2=OK 1=DEGRADED 0=BROKEN
31func mu_check_book(dir: *u8, out: *i64, verbose: i64) -> i64 {
32 out[0]=0; out[1]=0; out[2]=0
33 let cbx: *u8 = sys_mmap(MU_MAGIC_2048); var co: i64 = mu_apps(cbx, 0, dir); co = mu_apps(cbx, co, "/cbx.json" as *u8); cbx[co]=0 as u8
34 let szbox: *i64 = sys_mmap(16) as *i64
35 let man: *u8 = sys_read_file(cbx, szbox)
36 if (man as i64) == 0 { if verbose==1 { mw(" NO cbx.json -> BROKEN (unopenable)\n" as *u8) } return 0 }
37 let mnn: i64 = szbox[0]
38 // iterate "file":"<name>"
39 var pos: i64 = 0; var guard: i64 = 0
40 var total: i64 = 0; var ok: i64 = 0; var broken: i64 = 0
41 while guard < MU_MAGIC_4096 {
42 guard = guard + 1
43 let fp: i64 = mu_find(man, mnn, "\"file\":\"" as *u8, pos)
44 if fp < 0 { guard = MU_MAGIC_4096 } else {
45 let vs: i64 = fp + 8
46 let ve: i64 = mu_find(man, mnn, "\"" as *u8, vs)
47 pos = ve + 1
48 if ve > vs {
49 total = total + 1
50 // page path = dir/<file>
51 let pp: *u8 = sys_mmap(MU_MAGIC_2048); var po: i64 = mu_apps(pp, 0, dir); pp[po]=47 as u8; po=po+1
52 var q: i64 = vs; while q < ve { pp[po]=man[q]; po=po+1; q=q+1 } pp[po]=0 as u8
53 let pbox: *i64 = sys_mmap(16) as *i64
54 let pdata: *u8 = sys_read_file(pp, pbox)
55 var bad: i64 = 0; var reason: *u8 = "ok" as *u8
56 if (pdata as i64) == 0 { bad = 1; reason = "missing/unreadable" as *u8 }
57 else { if pbox[0] < 64 { bad = 1; reason = "0-byte/truncated" as *u8 }
58 else { let wh: *i64 = sys_mmap(16) as *i64
59 if nx_img_dims(pdata, pbox[0], wh) == 0 { bad = 1; reason = "undecodable (not a valid image)" as *u8 }
60 else { var mx: i64 = wh[0]; if wh[1] > mx { mx = wh[1] }
61 if mx < MU_MIN_EDGE { bad = 1; reason = "tiny (junk/broken)" as *u8 } } } }
62 if bad == 1 { broken = broken + 1; if verbose==1 { mw(" BROKEN page: " as *u8); var z: i64=vs; while z<ve{let o1: *u8=sys_mmap(1);o1[0]=man[z];sys_write(1,o1,1);z=z+1} mw(" (" as *u8); mw(reason); mw(")\n" as *u8) } }
63 else { ok = ok + 1 }
64 }
65 }
66 }
67 out[0]=total; out[1]=ok; out[2]=broken
68 if total == 0 { return 0 }
69 if broken == 0 { return 2 }
70 if ok == 0 { return 0 }
71 return 1
72}
73
74func mu_verdict_str(v: i64) -> *u8 { if v==2 {return "OK" as *u8} if v==1 {return "DEGRADED" as *u8} return "BROKEN" as *u8 }
75
76func main(argc: i64, argv: *i64) -> i64 {
77 if argc < 2 { mw("usage: nx_media_usable <book_dir> [--quiet]\n" as *u8); sys_exit(2); return 2 }
78 let dir: *u8 = argv[1] as *u8
79 var verbose: i64 = 1
80 if argc > 2 { verbose = 0 }
81 let out: *i64 = sys_mmap(32) as *i64
82 let v: i64 = mu_check_book(dir, out, verbose)
83 mw("USABLE dir=" as *u8); mw(dir); mw(" pages=" as *u8); mn(out[0]); mw(" ok=" as *u8); mn(out[1]); mw(" broken=" as *u8); mn(out[2]); mw(" verdict=" as *u8); mw(mu_verdict_str(v)); mw("\n" as *u8)
84 sys_exit(0); return 0
85}