code wiki / _hdl_build / nx_crawl_preserve.nx

nx_crawl_preserve.nx source

↩ module page · 72 lines · 4289 B

1// nx_crawl_preserve.nx -- the CRAWL DRIVER: sweep a list of URLs, render-fetch each as a browser (browser headers 2// + redirect follow), and archive them all into ONE durable WARC -- then reload it and confirm every preserved 3// resource retrieves by URL. This is the "capture a dying site before it vanishes" step of the sovereign 4// Browsertrix, composing bf_fetch_follow (render front) + nx_web_archive (store). Non-200s are skipped + logged 5// (honest: hard hosts / access-control). Run from nxc2 root. argv[1..] = URLs (default = a small legal set). 6// license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_x509_trust_store.nx" 9import "nx_trust_store_load_from_certdata.nx" 10import "nx_csprng.nx" 11import "nx_browser_fetch.nx" 12import "nx_web_archive.nx" 13const K_MAGIC_4194304: i64 = 4194304 14const K_MAGIC_8388608: i64 = 8388608 15const K_MAGIC_33554432: i64 = 33554432 16 17func pw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func pn(v: i64) -> i64 { let b: *u8=sys_mmap(24); var m: i64=v; if m<0{pw("-" 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 } 19func psl(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 20 21func main(argc: i64, argv: *i64) -> i64 { 22 let def: *i64 = sys_mmap(8*4) as *i64 23 def[0] = "https://example.com" as *u8 as i64 24 def[1] = "https://example.org" as *u8 as i64 25 def[2] = "https://download.samplelib.com/mp4/sample-5s.mp4" as *u8 as i64 26 var list: *i64 = def; var nurls: i64 = 3 27 if argc >= 2 { list = ((argv as i64) + 8) as *i64; nurls = argc - 1 } 28 29 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, K_MAGIC_4194304) 30 if r <= 0 { pw("CRAWL: certdata load failed (run from nxc2 root)\n" as *u8); sys_exit(1); return 1 } 31 let store: *TrustStore = r as *TrustStore 32 let cr: *u8 = sys_mmap(32); let pk: *u8 = sys_mmap(32); nx_csprng_fill(cr, 32); nx_csprng_fill(pk, 32) 33 let now: i64 = sys_now_realtime_sec() 34 35 pw("== nx_crawl_preserve: sweep " as *u8); pn(nurls); pw(" URLs -> render-fetch -> archive -> durable WARC ==\n" as *u8) 36 let cap: i64 = K_MAGIC_8388608 37 let resp: *u8 = sys_mmap(cap) 38 let warc: *u8 = sys_mmap(K_MAGIC_33554432) // 32 MiB archive 39 var off: i64 = 0 40 var preserved: i64 = 0 41 42 var i: i64 = 0 43 while i < nurls { 44 let url: *u8 = (list[i]) as *u8 45 let n: i64 = bf_fetch_follow(url, store, cr, pk, now, resp, cap, 5) 46 let st: i64 = bf_status(resp, n) 47 let boff: i64 = bf_body_off(resp, n) 48 let blen: i64 = n - boff 49 pw(" [" as *u8); pn(st); pw("] " as *u8); pn(blen); pw("B " as *u8); pw(url); pw("\n" as *u8) 50 if st == 200 { if blen > 0 { let body: *u8 = ((resp as i64)+boff) as *u8; off = wa_write_resource(warc, off, url, "2026-07-11T00:00:00Z" as *u8, "application/octet-stream" as *u8, body, blen); preserved = preserved + 1 } } 51 i = i + 1 52 } 53 let path: *u8 = "nx_crawl.warc" as *u8 54 wa_save(path, warc, off) 55 pw("crawled " as *u8); pn(nurls); pw(", preserved " as *u8); pn(preserved); pw(" -> " as *u8); pw(path); pw(" (" as *u8); pn(off); pw(" bytes, " as *u8); pn(wa_count(warc, off)); pw(" records)\n" as *u8) 56 57 // reload the durable WARC + confirm every preserved URL retrieves 58 let warc2: *u8 = sys_mmap(K_MAGIC_33554432) 59 let n2: i64 = wa_load(path, warc2, K_MAGIC_33554432) 60 let op: *i64 = sys_mmap(8) as *i64; let ol: *i64 = sys_mmap(8) as *i64 61 var retrievable: i64 = 0 62 i = 0 63 while i < nurls { 64 let url: *u8 = (list[i]) as *u8 65 if wa_lookup(warc2, n2, url, psl(url), op, ol) == 1 { retrievable = retrievable + 1 } 66 i = i + 1 67 } 68 pw("reload durable WARC: " as *u8); pn(retrievable); pw("/" as *u8); pn(preserved); pw(" preserved resources retrievable by URL\n" as *u8) 69 if retrievable == preserved { if preserved > 0 { pw("verdict=GREEN (crawl->render-fetch->archive->durable WARC; every preserved resource survives the origin dying)\n" as *u8); sys_exit(0); return 0 } } 70 pw("verdict=RED (some preserved resource did not retrieve)\n" as *u8) 71 sys_exit(1); return 1 72}