code wiki / _hdl_build / nx_galx_viewadd_lib.nx

nx_galx_viewadd_lib.nx source

↩ module page · 77 lines · 2946 B

1// nx_galx_viewadd_lib.nx -- prepend a cid to the gallery's VIEW index. ONE implementation. 2// 3// This is a library, not a copy: nx_galx_viewadd (the CLI) and nx_gen_ingest (the pipeline) both 4// call it. Two writers of a FIXED-WIDTH file that disagreed by one byte would shift every record 5// after the insertion point and scramble 226,576 images -- and it would look like the gallery had 6// been shuffled, not like a write bug. 7// ★ WHEN TWO CALLERS MUST AGREE ON A BYTE LAYOUT, THEY MUST SHARE THE CODE, NOT THE COMMENT. 8// 9// Format (measured): 70-byte records = 69-char cid + '\n', NEWEST-FIRST, so a new gen PREPENDS. 10// Returns 1 = added, 0 = already present, negative = refused/error. 11// license_tier: ORIGINAL 12 13import "nx_syscalls.nx" 14const NXV_MAGIC_1024: i64 = 1024 15 16const NXV_REC: i64 = 70 17const NXV_CIDLEN: i64 = 69 18 19const NXV_ADDED: i64 = 1 20const NXV_PRESENT: i64 = 0 21const NXV_EREAD: i64 = 0 - 1 22const NXV_ECORRUPT:i64 = 0 - 2 // file size not a multiple of the record 23const NXV_EBADCID: i64 = 0 - 3 // cid not exactly 69 chars 24const NXV_EWRITE: i64 = 0 - 4 25 26func _nxv_len(s: *u8) -> i64 { 27 var n: i64 = 0 28 while s[n] != (0 as u8) { n = n + 1 } 29 return n 30} 31 32func nx_galx_view_present(buf: *u8, n: i64, cid: *u8) -> i64 { 33 var r: i64 = 0 34 while r * NXV_REC < n { 35 let at: i64 = r * NXV_REC 36 var i: i64 = 0 37 var same: i64 = 1 38 while i < NXV_CIDLEN { 39 if buf[at + i] != cid[i] { same = 0; i = NXV_CIDLEN } else { i = i + 1 } 40 } 41 if same == 1 { return 1 } 42 r = r + 1 43 } 44 return 0 45} 46 47func nx_galx_view_prepend(path: *u8, cid: *u8) -> i64 { 48 // A cid of the wrong length is refused BEFORE any write. In a fixed-width file a short record 49 // does not corrupt one row, it corrupts every row after it. 50 if _nxv_len(cid) != NXV_CIDLEN { return NXV_EBADCID } 51 52 let sp: *i64 = sys_mmap(16) as *i64 53 let buf: *u8 = sys_read_file(path, sp) 54 if (buf as i64) == 0 { return NXV_EREAD } 55 let n: i64 = sp[0] 56 if n - (n / NXV_REC) * NXV_REC != 0 { return NXV_ECORRUPT } 57 if nx_galx_view_present(buf, n, cid) == 1 { return NXV_PRESENT } 58 59 // temp + rename: a crash mid-write must never leave the gallery reading a half file. 60 let tmp: *u8 = sys_mmap(NXV_MAGIC_1024) 61 var t: i64 = 0 62 while path[t] != (0 as u8) { tmp[t] = path[t]; t = t + 1 } 63 tmp[t] = 0x2E; tmp[t+1] = 0x6E; tmp[t+2] = 0x65; tmp[t+3] = 0x77; tmp[t+4] = 0 // ".new" 64 65 let rec: *u8 = sys_mmap(128) 66 var i: i64 = 0 67 while i < NXV_CIDLEN { rec[i] = cid[i]; i = i + 1 } 68 rec[NXV_CIDLEN] = 10 as u8 69 70 let fd: i64 = sys_openat_wr(tmp, 0x1a4) 71 if fd < 0 { return NXV_EWRITE } 72 if sys_write(fd, rec, NXV_REC) != NXV_REC { sys_close(fd); return NXV_EWRITE } 73 if sys_write(fd, buf, n) != n { sys_close(fd); return NXV_EWRITE } 74 sys_close(fd) 75 if sys_renameat(tmp, path) != 0 { return NXV_EWRITE } 76 return NXV_ADDED 77}