code wiki / _hdl_build / nx_bench_fetch.nx

nx_bench_fetch.nx source

↩ module page · 130 lines · 5817 B

1// nx_bench_fetch.nx -- THE GENERIC SOVEREIGN URL->FILE FETCHER (rule 15 DRY; eats the hardcoded-URL 2// fetcher-family duplication class). 3// 4// WHY IT EXISTS: the ecosystem has ~119 `*_research_fetch` organs, each a copy of the same TLS+save body 5// with its URLs BAKED IN. I wrote two more this session (swebv, gmmlu) before the third instance made the 6// pattern obvious -- rule 15 says extract at 3. Every one of those copies also inherited the same latent 7// bugs (the ff_putn no-write class, the missing self-mkdir) precisely because they were copies. This organ 8// is the one body they should all have called: URL and destination are ARGUMENTS, not source edits. 9// 10// nx_bench_fetch <url> <outpath> [force] 11// outpath MUST be under knowledge/fetched/ or /tmp/ (boundary defense, rule 12) 12// idempotent: an existing outpath is a HAVE-SKIP unless `force` is passed 13// prints: status=<http> bytes=<n> SAVED | HAVE-SKIP | FETCH-FAIL | SAVE-FAIL | GZIP-skip 14// exit 0 saved-or-skipped | 2 usage/denied | 3 fetch failed 15// 16// SELF-MKDIRS knowledge/fetched (rule 20: a tool that needs a dir makes it -- the missing-dir bug that 17// silently SAVE-FAIL'd 119 organs, seq191). 18// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 19import "nx_syscalls.nx" 20import "nx_x509_trust_store.nx" 21import "nx_trust_store_load_from_certdata.nx" 22import "nx_https_fetch_follow.nx" 23 24const BF_CAP: i64 = 8388608 25const BF_ROOTS_MAX: i64 = 512 26const BF_CERTBUF: i64 = 4194304 27const BF_HOPS: i64 = 6 28const BF_MODE: i64 = 0x1a4 29const BF_DMODE: i64 = 0x1ed 30const BF_MKDIRAT: i64 = 258 31const BF_ATFDCWD: i64 = 0 - 100 32const BF_D0: i64 = 48 33const BF_B10: i64 = 10 34const BF_NUMB: i64 = 24 35const BF_STDERR: i64 = 2 36const BF_EXIT_USAGE: i64 = 2 37const BF_EXIT_FETCH: i64 = 3 38const BF_ARGC_MIN: i64 = 3 39const BF_ARGC_FORCE: i64 = 4 40 41func bf_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 42func bf_w(s: *u8) -> i64 { sys_write(1, s, bf_slen(s)); return 0 } 43func bf_werr(s: *u8) -> i64 { sys_write(BF_STDERR, s, bf_slen(s)); return 0 } 44func bf_wn(v: i64) -> i64 { 45 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 46 var m: i64 = v 47 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 48 let d: *u8 = sys_mmap(BF_NUMB) 49 var k: i64 = 0 50 while m > 0 { d[k] = (BF_D0 + (m % BF_B10)) as u8; m = m / BF_B10; k = k + 1 } 51 let o: *u8 = sys_mmap(BF_NUMB) 52 var i: i64 = 0 53 while i < k { o[i] = d[k - 1 - i]; i = i + 1 } 54 sys_write(1, o, k) 55 return 0 56} 57// does s start with pfx? 58func bf_pfx(s: *u8, pfx: *u8) -> i64 { 59 var i: i64 = 0 60 while pfx[i] != (0 as u8) { if s[i] != pfx[i] { return 0 } i = i + 1 } 61 return 1 62} 63func bf_has(s: *u8, sub: *u8) -> i64 { 64 let n: i64 = bf_slen(s) 65 let m: i64 = bf_slen(sub) 66 if m == 0 { return 0 } 67 var i: i64 = 0 68 while i + m <= n { 69 var j: i64 = 0 70 var ok: i64 = 1 71 while j < m { if s[i+j] != sub[j] { ok = 0; j = m } else { j = j + 1 } } 72 if ok == 1 { return 1 } 73 i = i + 1 74 } 75 return 0 76} 77func bf_exists(p: *u8) -> i64 { 78 let fd: i64 = sys_openat_rd(p) 79 if fd < 0 { return 0 } 80 sys_close(fd) 81 return 1 82} 83func bf_mkdir(p: *u8) -> i64 { return __syscall(BF_MKDIRAT, BF_ATFDCWD, p as i64, BF_DMODE, 0, 0, 0) } 84 85func main(argc: i64, argv: *i64) -> i64 { 86 if argc < BF_ARGC_MIN { bf_werr("usage: nx_bench_fetch <url> <outpath-under-knowledge/fetched-or-/tmp> [force]\n" as *u8); sys_exit(BF_EXIT_USAGE); return BF_EXIT_USAGE } 87 let url: *u8 = argv[1] as *u8 88 let outp: *u8 = argv[2] as *u8 89 var force: i64 = 0 90 if argc >= BF_ARGC_FORCE { force = 1 } 91 92 // BOUNDARY DEFENSE (rule 12): destination is confined, traversal refused by construction. 93 if bf_has(outp, ".." as *u8) == 1 { bf_werr("BF-REFUSED traversal in outpath\n" as *u8); sys_exit(BF_EXIT_USAGE); return BF_EXIT_USAGE } 94 var okdst: i64 = 0 95 if bf_pfx(outp, "knowledge/fetched/" as *u8) == 1 { okdst = 1 } 96 if bf_pfx(outp, "/tmp/" as *u8) == 1 { okdst = 1 } 97 if okdst == 0 { bf_werr("BF-REFUSED outpath must be under knowledge/fetched/ or /tmp/\n" as *u8); sys_exit(BF_EXIT_USAGE); return BF_EXIT_USAGE } 98 // only https is fetchable (the sovereign client is TLS-only by construction) 99 if bf_pfx(url, "https://" as *u8) == 0 { bf_werr("BF-REFUSED url must be https://\n" as *u8); sys_exit(BF_EXIT_USAGE); return BF_EXIT_USAGE } 100 101 bf_mkdir("knowledge" as *u8) 102 bf_mkdir("knowledge/fetched" as *u8) 103 104 if force == 0 { if bf_exists(outp) == 1 { bf_w(outp); bf_w(" HAVE-SKIP (pass `force` to refetch)\n" as *u8); sys_exit(0); return 0 } } 105 106 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, BF_ROOTS_MAX, BF_CERTBUF) 107 if r <= 0 { bf_werr("BF-FAIL certdata load failed (need data/mozilla_certdata.txt in cwd)\n" as *u8); sys_exit(BF_EXIT_FETCH); return BF_EXIT_FETCH } 108 let store: *TrustStore = r as *TrustStore 109 let out: *u8 = sys_mmap(BF_CAP) 110 let status: *i64 = sys_mmap(8) as *i64 111 let n: i64 = nx_https_fetch_follow(url, store, out, BF_CAP, BF_HOPS, status) 112 bf_w(url) 113 bf_w(" status=" as *u8) 114 bf_wn(status[0]) 115 bf_w(" bytes=" as *u8) 116 bf_wn(n) 117 if n <= 0 { bf_w(" FETCH-FAIL\n" as *u8); sys_exit(BF_EXIT_FETCH); return BF_EXIT_FETCH } 118 var gz: i64 = 0 119 if n >= 2 { if out[0] == 0x1f as u8 { if out[1] == 0x8b as u8 { gz = 1 } } } 120 if gz == 1 { bf_w(" GZIP-skip (body is gzip; sovereign client requested identity)\n" as *u8); sys_exit(BF_EXIT_FETCH); return BF_EXIT_FETCH } 121 let fd: i64 = sys_openat_wr(outp, BF_MODE) 122 if fd < 0 { bf_w(" SAVE-FAIL\n" as *u8); sys_exit(BF_EXIT_FETCH); return BF_EXIT_FETCH } 123 sys_write(fd, out, n) 124 sys_close(fd) 125 bf_w(" SAVED -> " as *u8) 126 bf_w(outp) 127 bf_w("\n" as *u8) 128 sys_exit(0) 129 return 0 130}