nx_torrent_doctor.nx source
↩ module page · 110 lines · 6631 B
1// nx_torrent_doctor.nx -- SOVEREIGN torrent diagnostic (replaces shell dumps; SHELL IS BLEED). Scans the
2// download outdir (sys_getdents64, no ls/find) and reports every torrent's live state from its download.status
3// + download.control, then a summary classifying each (downloading-with-progress / stalled / finalized / etc.)
4// so "can't download multiple" becomes a measured fact, not a guess. Usage: nx_torrent_doctor. license_tier: ORIGINAL
5import "nx_syscalls.nx"
6const K_MAGIC_1024: i64 = 1024
7const K_MAGIC_4096: i64 = 4096
8
9const DBUF: i64 = 65536
10const OUT: *u8 = "/mnt/c/Users/elder/Downloads/nishi-torrents" as *u8
11
12func dr_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13func dr_n(v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(1,"-" as *u8,1)} 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} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
14func dr_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15func dr_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off+i]=s[i];i=i+1} return off+dr_len(s) }
16
17// read a whole file into buf (bounded); returns bytes read or 0.
18func dr_read(path: *u8, buf: *u8, cap: i64) -> i64 {
19 let fd: i64 = sys_openat_rd(path); if fd<0 { return 0 }
20 var off: i64=0; var go: i64=1
21 while go==1 { if off>=cap { go=0 } else { let r: i64=sys_read(fd, ((buf as i64)+off) as *u8, cap-off); if r<=0 {go=0} else {off=off+r} } }
22 sys_close(fd); return off
23}
24// status is newline-delimited key=value; copy the value of `key` (at a line start) into out. returns len.
25func dr_getval(buf: *u8, n: i64, key: *u8, out: *u8, ocap: i64) -> i64 {
26 let kl: i64 = dr_len(key)
27 var i: i64 = 0
28 while i < n {
29 // at a line start (i==0 or prev was \n), does key match?
30 var ls: i64 = 0; if i==0 { ls=1 } else { if (buf[i-1] as i64)==10 { ls=1 } }
31 if ls==1 {
32 var m: i64=1; var j: i64=0
33 while j<kl { if i+j>=n { m=0; j=kl } else { if buf[i+j]!=key[j] { m=0; j=kl } else { j=j+1 } } }
34 if m==1 {
35 var p: i64=i+kl; var o: i64=0
36 while p<n { if (buf[p] as i64)==10 { p=n } else { if o<ocap-1 { out[o]=buf[p]; o=o+1 } p=p+1 } }
37 out[o]=0 as u8; return o
38 }
39 }
40 i=i+1
41 }
42 out[0]=0 as u8; return 0
43}
44// parse a decimal value (digits only) from a NUL-terminated string.
45func dr_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8) { let c: i64=s[i] as i64; if c>=48 { if c<=57 { v=v*10+(c-48) } } i=i+1 } return v }
46// read+atoi a status key in one shot.
47func dr_atoi_kv(buf: *u8, n: i64, key: *u8) -> i64 {
48 let v: *u8 = sys_mmap(64); dr_getval(buf, n, key, v, 64); return dr_atoi(v)
49}
50
51func main() -> i64 {
52 let fd: i64 = sys_openat_rd(OUT)
53 if fd < 0 { dr_p("DOCTOR FAIL: cannot open outdir\n" as *u8); sys_exit(1); return 1 }
54 let gbuf: *u8 = sys_mmap(DBUF)
55 let path: *u8 = sys_mmap(K_MAGIC_1024)
56 let sbuf: *u8 = sys_mmap(K_MAGIC_4096)
57 let val: *u8 = sys_mmap(512); let nm: *u8 = sys_mmap(512); let ctl: *u8 = sys_mmap(64)
58 var total: i64=0; var downloading: i64=0; var progressing: i64=0; var stalled: i64=0; var finalized: i64=0; var active_ctl: i64=0
59 dr_p("=== NISHI TORRENT DOCTOR ===\n" as *u8)
60 dr_p("id | state | have/pieces | done_bytes | control\n" as *u8)
61 var go: i64 = 1
62 while go == 1 {
63 let n: i64 = sys_getdents64(fd, gbuf, DBUF)
64 if n <= 0 { go = 0 } else {
65 var off: i64 = 0
66 while off < n {
67 let rec: *u8 = ((gbuf as i64) + off) as *u8
68 let reclen: i64 = dirent_reclen(rec)
69 let name: *u8 = dirent_name(rec)
70 var skip: i64 = 0
71 if name[0]==(46 as u8) { skip=1 } // '.' '..' and hidden
72 // only consider entries that are directories with a download.status inside
73 if skip==0 {
74 var po: i64 = dr_cat(path, 0, OUT); path[po]=47 as u8; po=po+1
75 var ni: i64=0; while name[ni]!=(0 as u8){path[po]=name[ni];po=po+1;ni=ni+1}
76 let stem: i64 = po
77 path[po]=0 as u8
78 // <dir>/download.status
79 var sp: i64 = dr_cat(path, stem, "/download.status" as *u8); path[sp]=0 as u8
80 let sn: i64 = dr_read(path, sbuf, K_MAGIC_4096)
81 if sn > 0 {
82 total = total + 1
83 dr_getval(sbuf, sn, "state=" as *u8, val, 512)
84 dr_getval(sbuf, sn, "name=" as *u8, nm, 512)
85 let have: i64 = dr_atoi_kv(sbuf, sn, "have=" as *u8)
86 let pieces: i64 = dr_atoi_kv(sbuf, sn, "pieces=" as *u8)
87 let done: i64 = dr_atoi_kv(sbuf, sn, "done=" as *u8)
88 // control
89 var cp: i64 = dr_cat(path, stem, "/download.control" as *u8); path[cp]=0 as u8
90 let cn: i64 = dr_read(path, ctl, 63); if cn>0 { ctl[cn]=0 as u8 } else { ctl[0]=0 as u8 }
91 dr_p(name); dr_p(" | " as *u8); dr_p(val); dr_p(" | " as *u8); dr_n(have); dr_p("/" as *u8); dr_n(pieces); dr_p(" | " as *u8); dr_n(done); dr_p(" | " as *u8); dr_p(ctl); dr_p("\n" as *u8)
92 // classify
93 if ctl[0]==(97 as u8) { active_ctl = active_ctl + 1 } // 'a'ctive
94 let st0: i64 = val[0] as i64
95 if st0==(100 as u8) { downloading = downloading + 1; if have>0 { progressing = progressing + 1 } } // 'd'ownloading
96 if st0==(115 as u8) { stalled = stalled + 1 } // 's'talled
97 if st0==(102 as u8) { finalized = finalized + 1 } // 'f'inalized
98 }
99 }
100 if reclen <= 0 { off = n } else { off = off + reclen }
101 }
102 }
103 }
104 sys_close(fd)
105 dr_p("--- summary ---\n" as *u8)
106 dr_p("torrents=" as *u8); dr_n(total); dr_p(" control_active=" as *u8); dr_n(active_ctl)
107 dr_p(" downloading=" as *u8); dr_n(downloading); dr_p(" (with_progress=" as *u8); dr_n(progressing); dr_p(")" as *u8)
108 dr_p(" stalled=" as *u8); dr_n(stalled); dr_p(" finalized=" as *u8); dr_n(finalized); dr_p("\n" as *u8)
109 sys_exit(0); return 0
110}