code wiki / _hdl_build / nx_janitor_retire.nx
nx_janitor_retire.nx source
↩ module page · 55 lines · 3268 B
1// nx_janitor_retire.nx -- the RETIRE step = the actual debt count-drop (operator: "keep the debt gone").
2// Migrating is additive (the original stays, so the auditor still counts it); RETIRING moves the already-
3// backed-up original OUT of the product zone into a fenced `_retired/` dir, so it stops counting and the
4// genuine_debt actually falls (then the ratchet locks the lower floor). SAFETY, by construction:
5// - REFUSES to retire a file whose bytes are not byte-verified in the store (never lose data).
6// - MOVES, never deletes -- the janitor has NO unlink syscall; a retire is sys_renameat (reversible).
7// - jan_unretire moves it straight back = proven reversible (never-brick #26, additive #13).
8// Pair with the auditor fencing `/_retired/` (done) so retired files are no longer product-contaminants.
9// Composes nx_janitor_scrub.jan_migrate for the verify. Sovereign. license_tier: ORIGINAL
10import "nx_janitor_scrub.nx" // jan_migrate, jan_exists
11import "nx_syscalls.nx"
12const K_MAGIC_1024: i64 = 1024
13
14// the file's bytes are byte-exact in `store_prefix`? (idempotent re-migrate+verify; the retire precondition)
15func jan_verify_in_store(src_path: *u8, store_prefix: *u8) -> i64 {
16 let totp: *i64 = sys_mmap(16) as *i64; let verp: *i64 = sys_mmap(16) as *i64
17 jan_migrate(src_path, store_prefix, totp, verp)
18 if totp[0] > 0 { if verp[0] == totp[0] { return 1 } }
19 return 0
20}
21
22// compute retdir = <dir>/_retired and dest = <dir>/_retired/<name> from a full path
23func jan_retire_dest(path: *u8, retdir: *u8, dest: *u8) -> i64 {
24 var slash: i64 = 0 - 1; var i: i64 = 0
25 while path[i] != (0 as u8) { if path[i] == (47 as u8) { slash = i } i = i + 1 }
26 var o: i64 = 0; var j: i64 = 0
27 while j <= slash { retdir[o] = path[j]; o = o + 1; j = j + 1 } // dir + trailing '/'
28 let suf: *u8 = "_retired" as *u8; var s: i64 = 0
29 while suf[s] != (0 as u8) { retdir[o] = suf[s]; o = o + 1; s = s + 1 } retdir[o] = 0 as u8
30 var d: i64 = 0; var r: i64 = 0
31 while retdir[r] != (0 as u8) { dest[d] = retdir[r]; d = d + 1; r = r + 1 }
32 dest[d] = 47 as u8; d = d + 1
33 var n: i64 = slash + 1
34 while path[n] != (0 as u8) { dest[d] = path[n]; d = d + 1; n = n + 1 } dest[d] = 0 as u8
35 return 0
36}
37
38// RETIRE: only if byte-verified in the store, MOVE (reversible, no delete) to <dir>/_retired/<name>.
39// 1 = retired | 0 = REFUSED (not verified-in-store, or the move failed)
40func jan_retire(src_path: *u8, store_prefix: *u8) -> i64 {
41 if jan_verify_in_store(src_path, store_prefix) != 1 { return 0 } // never retire unbacked-up data
42 let retdir: *u8 = sys_mmap(K_MAGIC_1024); let dest: *u8 = sys_mmap(K_MAGIC_1024)
43 jan_retire_dest(src_path, retdir, dest)
44 sys_mkdir(retdir, 493) // 0755; harmless if it already exists
45 if sys_renameat(src_path, dest) != 0 { return 0 }
46 return 1
47}
48
49// UN-RETIRE: move it straight back to the product zone (proves the retire is reversible). 1 = restored.
50func jan_unretire(src_path: *u8, store_prefix: *u8) -> i64 {
51 let retdir: *u8 = sys_mmap(K_MAGIC_1024); let dest: *u8 = sys_mmap(K_MAGIC_1024)
52 jan_retire_dest(src_path, retdir, dest)
53 if sys_renameat(dest, src_path) != 0 { return 0 }
54 return 1
55}