code wiki / (root) / nx_torrent_doctor.nx

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}