code wiki / _hdl_build / nx_profile_backup_run.nx

nx_profile_backup_run.nx source

↩ module page · 137 lines · 6569 B

1// nx_profile_backup_run.nx -- RUNNER: encrypted OS backup of the REAL browser profile store. 2// Composes nx_browser_profile_store (seeds the live store on first run) + nx_profile_backup (machine-bound 3// ChaCha20-Poly1305 blobs, built-in restore-verify). Destination from knowledge/hosting/profile_backup.conf 4// (rule 17: config, not hardcode; default = /mnt/c/Users/elder/.nishi/profile_backup = the Windows OS side, 5// outside the repo). Enumerates knowledge/store/browser_profile-* via getdents (no shell). Appends ONE 6// receipt line to knowledge/status/profile_backup.log. Exit 0 iff every store file backed up + verified. 7// expect_exit: 0 license_tier: ORIGINAL 8import "nx_browser_profile_store.nx" 9import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 10import "nx_profile_backup.nx" 11const K_MAGIC_1024: i64 = 1024 12const K_MAGIC_262144: i64 = 262144 13const K_MAGIC_2048: i64 = 2048 14const K_MAGIC_4096: i64 = 4096 15 16func r_pw(s: *u8) -> i64 { sys_write(1, s, pb_slen(s)); return 0 } 17// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch 18// buffer per call and never freed it -- 4096B leaked PER CALL at page granularity, 19// the defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M 20// calls). nxi_* is MSB-first, allocates NOTHING, emits identical bytes incl. sign. 21func r_pn(v: i64) -> i64 { nxi_out(v); return 0 } 22func r_apps(b: *u8, n: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){b[n+i]=s[i];i=i+1} return n+i } 23func r_appn(b: *u8, n: i64, v: i64) -> i64 { 24 let t: *u8=sys_mmap(28); var m: i64=v; 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} 25 var i: i64=0; var p: i64=n; while i<k{b[p]=t[k-1-i];p=p+1;i=i+1} return p } 26 27func main() -> i64 { 28 r_pw("=== nx_profile_backup_run: encrypted OS backup of the live browser profile store ===\n" as *u8) 29 // machine-bound key material 30 let ikm: *u8 = sys_mmap(256) 31 let ilen: i64 = pb_machine_ikm(ikm, 256) 32 if ilen <= 0 { r_pw("no /etc/machine-id -> cannot derive machine-bound key\n" as *u8); return 1 } 33 34 // seed the live store on first run (so the profile store EXISTS as a real artifact) 35 if bp_exists(BP_PROFILE_PREFIX, "setting:profile_created" as *u8) == 0 { 36 let ep: *u8 = sys_mmap(64) 37 var en: i64 = 0 38 en = r_appn(ep, en, sys_now_realtime_sec()) 39 ep[en] = 0 as u8 40 bp_put(BP_PROFILE_PREFIX, "setting:profile_created" as *u8, ep, en) 41 r_pw("seeded live profile store (setting:profile_created)\n" as *u8) 42 } 43 44 // destination (simple parse: last line of conf that starts with '/') 45 let dest: *u8 = sys_mmap(K_MAGIC_1024) 46 var dlen: i64 = 0 - 1 47 let cbox: *i64 = sys_mmap(16) as *i64 48 let cb: *u8 = sys_read_file("knowledge/hosting/profile_backup.conf" as *u8, cbox) 49 if (cb as i64) != 0 { 50 var i: i64 = 0 51 var ls: i64 = 0 52 while i <= cbox[0] { 53 var eol: i64 = 0 54 if i == cbox[0] { eol = 1 } else { if (cb[i] as i64) == 10 { eol = 1 } } 55 if eol == 1 { 56 if i > ls { if (cb[ls] as i64) == 47 { 57 var k: i64 = 0 58 while ls + k < i { dest[k] = cb[ls + k]; k = k + 1 } 59 dest[k] = 0 as u8 60 dlen = k 61 } } 62 ls = i + 1 63 } 64 i = i + 1 65 } 66 } 67 if dlen <= 0 { r_pw("no dest in knowledge/hosting/profile_backup.conf -> RED\n" as *u8); return 1 } 68 r_pw("dest = " as *u8); r_pw(dest); r_pw("\n" as *u8) 69 // ensure the dest dirs exist (parent then dest; EEXIST is fine) 70 sys_mkdir("/mnt/c/Users/elder/.nishi" as *u8, 0x1c0) 71 sys_mkdir(dest, 0x1c0) 72 73 // enumerate knowledge/store/browser_profile-* and back each file up 74 let dfd: i64 = sys_openat_rd("knowledge/store" as *u8) 75 if dfd < 0 { r_pw("cannot open knowledge/store\n" as *u8); return 1 } 76 let buf: *u8 = sys_mmap(K_MAGIC_262144) 77 let stem: *u8 = "browser_profile-" 78 var files: i64 = 0 79 var okc: i64 = 0 80 let src: *u8 = sys_mmap(K_MAGIC_2048) 81 let dst: *u8 = sys_mmap(K_MAGIC_2048) 82 var go: i64 = 1 83 while go == 1 { 84 let n: i64 = sys_getdents64(dfd, buf, K_MAGIC_262144) 85 if n <= 0 { go = 0 } else { 86 var off: i64 = 0 87 while off < n { 88 let reclen: i64 = (buf[off+16] as i64) + ((buf[off+17] as i64) * 256) 89 let name: *u8 = buf + off + 19 90 var m: i64 = 1 91 var i: i64 = 0 92 while stem[i] != (0 as u8) { if name[i] != stem[i] { m = 0; i = pb_slen(stem) } else { i = i + 1 } } 93 if m == 1 { 94 files = files + 1 95 var o: i64 = 0 96 o = r_apps(src, 0, "knowledge/store/" as *u8) 97 o = r_apps(src, o, name) 98 src[o] = 0 as u8 99 o = r_apps(dst, 0, dest) 100 o = r_apps(dst, o, "/" as *u8) 101 o = r_apps(dst, o, name) 102 o = r_apps(dst, o, ".nxpb" as *u8) 103 dst[o] = 0 as u8 104 let rc: i64 = pb_backup_file(src, dst, ikm, ilen) 105 r_pw(" " as *u8); r_pw(name) 106 if rc == 0 { r_pw(" -> backed up + restore-verified\n" as *u8); okc = okc + 1 } else { r_pw(" -> FAILED rc=" as *u8); r_pn(rc); r_pw("\n" as *u8) } 107 } 108 off = off + reclen 109 } 110 } 111 } 112 sys_close(dfd) 113 114 // receipt (one line, appended) 115 let bb: *u8 = sys_mmap(K_MAGIC_4096) 116 var bn: i64 = 0 117 bn = r_apps(bb, bn, "PROFILE-BACKUP epoch=" as *u8) 118 bn = r_appn(bb, bn, sys_now_realtime_sec()) 119 bn = r_apps(bb, bn, " files=" as *u8) 120 bn = r_appn(bb, bn, files) 121 bn = r_apps(bb, bn, " ok=" as *u8) 122 bn = r_appn(bb, bn, okc) 123 bn = r_apps(bb, bn, " dest=" as *u8) 124 bn = r_apps(bb, bn, dest) 125 var green: i64 = 0 126 if files > 0 { if okc == files { green = 1 } } 127 if green == 1 { bn = r_apps(bb, bn, " verdict=GREEN" as *u8) } else { bn = r_apps(bb, bn, " verdict=RED" as *u8) } 128 bb[bn] = 10 as u8 129 bn = bn + 1 130 let lf: i64 = sys_openat_append("knowledge/status/profile_backup.log" as *u8, 0x1a4) 131 if lf >= 0 { sys_write(lf, bb, bn); sys_close(lf) } 132 133 r_pw("PROFILE-BACKUP files=" as *u8); r_pn(files); r_pw(" ok=" as *u8); r_pn(okc) 134 if green == 1 { r_pw(" verdict=GREEN -- second copy encrypted on the OS, every blob restore-verified\n" as *u8); return 0 } 135 r_pw(" verdict=RED\n" as *u8) 136 return 1 137}