code wiki / (root) / nx_galx_saveimg.nx

nx_galx_saveimg.nx source

↩ module page · 118 lines · 5042 B

1// nx_galx_saveimg.nx -- ingest ONE media file into the gallery so it SHOWS in the grid and SERVES 2// live with NO restart. The reusable "save to gallery" primitive behind 4chan-save and the safe-browse 3// adapters: a source downloads bytes to a dir, this makes them a first-class gallery image. 4// 5// Composes the sovereign cid + BOTH gallery indexes the 2026-08-07 native-store work exposed: 6// 1. cid = "nxc1-" + sha256hex(content) -- 69 chars, the gallery cid canon (matches nxc1-* gens). 7// 2. copy the file to <savedir>/<cid> -- the resolver's target path. 8// 3. APPEND "<cid>\t<savedpath>\n" to <cidtsv> (knowledge/status/galx_cid_paths.tsv). gs_sidecar's 9// FAST path is the boot-loaded O(1) index; on a MISS it reads THIS tsv FRESH per request, so a new 10// cid resolves LIVE with no restart, and the boot rebuild-preserving later merges it durably. 11// 4. nx_galx_view_prepend(<viewindex>, cid) -- 70-byte records NEWEST-FIRST, so the grid LISTS it. 12// Content-addressed: re-saving identical bytes yields the same cid -> idempotent (view PRESENT, tsv dup 13// harmless -- gs_sidecar returns the first match). The vault (nx_mvault_walk <dir> real <source>) owns 14// the durable CID/source record for migration; this organ makes it VISIBLE now. 15// 16// Usage: nx_galx_saveimg <srcfile> <savedir> <viewindex> <cidtsv> [source] 17// -> {"cid":"nxc1-..","bytes":N,"saved":"<savedir>/<cid>","view_added":0|1} exit 0 ok / 1 err 18// license_tier: ORIGINAL 19 20import "nx_syscalls.nx" 21import "nx_sha256.nx" 22import "nx_galx_viewadd_lib.nx" 23const SI_MAGIC_1024: i64 = 1024 24const SI_MAGIC_1152: i64 = 1152 25 26const SI_IMG_CAP: i64 = 33554432 27 28func si_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return sys_write(1, s, n) } 29func si_apps(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[o+i] = s[i]; i = i + 1 } return o + i } 30func si_num(dst: *u8, o: i64, v: i64) -> i64 { 31 if v == 0 { dst[o] = 48 as u8; return o + 1 } 32 let t: *u8 = sys_mmap(32); var m: i64 = v; var k: i64 = 0 33 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 34 var i: i64 = 0; while i < k { dst[o+i] = t[k-1-i]; i = i + 1 } return o + k 35} 36 37// 32-byte digest -> 64 lowercase hex chars at out[0..64] 38func si_hex(dig: *u8, out: *u8) -> i64 { 39 let hx: *u8 = "0123456789abcdef" as *u8 40 var i: i64 = 0 41 while i < 32 { 42 let b: i64 = dig[i] as i64 43 out[i*2] = hx[(b >> 4) & 15] 44 out[i*2+1] = hx[b & 15] 45 i = i + 1 46 } 47 return 64 48} 49 50func main(argc: i64, argv: *i64) -> i64 { 51 if argc < 5 { 52 si_puts("usage: nx_galx_saveimg <srcfile> <savedir> <viewindex> <cidtsv> [source]\n" as *u8) 53 return 2 54 } 55 let src: *u8 = argv[1] as *u8 56 let savedir: *u8 = argv[2] as *u8 57 let viewidx: *u8 = argv[3] as *u8 58 let cidtsv: *u8 = argv[4] as *u8 59 60 let sp: *i64 = sys_mmap(16) as *i64 61 let buf: *u8 = sys_read_file(src, sp) 62 if (buf as i64) == 0 { si_puts("{\"error\":\"cannot read src\"}\n" as *u8); return 1 } 63 let n: i64 = sp[0] 64 if n <= 0 { si_puts("{\"error\":\"empty src\"}\n" as *u8); return 1 } 65 66 let dig: *u8 = sys_mmap(64) 67 sha256_digest(buf, n, dig) 68 let cid: *u8 = sys_mmap(96) 69 var co: i64 = si_apps(cid, 0, "nxc1-" as *u8) 70 let hx: *u8 = sys_mmap(96) 71 si_hex(dig, hx) 72 var h: i64 = 0 73 while h < 64 { cid[co] = hx[h]; co = co + 1; h = h + 1 } 74 cid[co] = 0 as u8 75 76 let dest: *u8 = sys_mmap(SI_MAGIC_1024) 77 var do2: i64 = si_apps(dest, 0, savedir) 78 dest[do2] = 47 as u8; do2 = do2 + 1 79 var c2: i64 = 0 80 while c2 < 69 { dest[do2] = cid[c2]; do2 = do2 + 1; c2 = c2 + 1 } 81 dest[do2] = 0 as u8 82 83 __syscall(258, 0 - 100, savedir as i64, 0x1ed, 0, 0, 0) 84 85 let fdo: i64 = sys_openat_wr(dest, 0x1a4) 86 if fdo < 0 { si_puts("{\"error\":\"cannot open dest\"}\n" as *u8); return 1 } 87 if sys_write(fdo, buf, n) != n { sys_close(fdo); si_puts("{\"error\":\"short write\"}\n" as *u8); return 1 } 88 sys_close(fdo) 89 90 let row: *u8 = sys_mmap(SI_MAGIC_1152) 91 var ro: i64 = 0 92 var c3: i64 = 0 93 while c3 < 69 { row[ro] = cid[c3]; ro = ro + 1; c3 = c3 + 1 } 94 row[ro] = 9 as u8; ro = ro + 1 95 ro = si_apps(row, ro, dest) 96 row[ro] = 10 as u8; ro = ro + 1 97 let fdt: i64 = sys_openat_rdwr(cidtsv, 0x1a4) 98 if fdt >= 0 { 99 sys_lseek(fdt, 0, 2) 100 sys_write(fdt, row, ro) 101 sys_close(fdt) 102 } 103 104 let va: i64 = nx_galx_view_prepend(viewidx, cid) 105 var added: i64 = 0 106 if va == NXV_ADDED { added = 1 } 107 108 let out: *u8 = sys_mmap(SI_MAGIC_1152) 109 var oo: i64 = si_apps(out, 0, "{\"cid\":\"" as *u8) 110 var c4: i64 = 0 111 while c4 < 69 { out[oo] = cid[c4]; oo = oo + 1; c4 = c4 + 1 } 112 oo = si_apps(out, oo, "\",\"bytes\":" as *u8); oo = si_num(out, oo, n) 113 oo = si_apps(out, oo, ",\"saved\":\"" as *u8); oo = si_apps(out, oo, dest) 114 oo = si_apps(out, oo, "\",\"view_added\":" as *u8); oo = si_num(out, oo, added) 115 oo = si_apps(out, oo, "}\n" as *u8) 116 sys_write(1, out, oo) 117 return 0 118}