code wiki / (root) / nx_gunzip.nx

nx_gunzip.nx source

↩ module page · 111 lines · 4931 B

1// nx_gunzip.nx -- CLI for the sovereign decompressor: gzip / zlib / raw DEFLATE -> stdout or file. 2// 3// The missing half of our compression story. nx_gzip COMPRESSES; nothing could decompress, so any 4// HTTP body with Content-Encoding: gzip was unreadable by the sovereign fetch path. 5// 6// nx_gunzip <in.gz> [out] -- auto-detects gzip / zlib / raw by magic 7// nx_gunzip --crc <file> -- print the CRC32 of a file (the gzip integrity primitive) 8// 9// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 10import "nx_syscalls.nx" 11import "nx_inflate.nx" 12 13const GU_CAP: i64 = 268435456 14const GU_MODE: i64 = 0x1a4 15 16func gu_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 17func gu_e(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(2, s, n); return 0 } 18func gu_num(v: i64) -> i64 { 19 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 20 var m: i64 = v 21 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 22 let t: *u8 = sys_mmap(32) 23 var k: i64 = 0 24 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 25 let o: *u8 = sys_mmap(32) 26 var i: i64 = 0 27 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 28 sys_write(1, o, k) 29 return 0 30} 31// every error names the wall it hit -- a decompressor that fails silently is the defect this 32// organ exists to end, so the CLI refuses to be vague about why 33func gu_reason(rc: i64) -> i64 { 34 if rc == 0 - 1 { gu_e("INFLATE-RED output exceeds capacity\n" as *u8) } 35 if rc == 0 - 2 { gu_e("INFLATE-RED truncated stream (input exhausted)\n" as *u8) } 36 if rc == 0 - 3 { gu_e("INFLATE-RED invalid huffman symbol\n" as *u8) } 37 if rc == 0 - 4 { gu_e("INFLATE-RED back-reference points before the output buffer\n" as *u8) } 38 if rc == 0 - 5 { gu_e("INFLATE-RED reserved block type\n" as *u8) } 39 if rc == 0 - 6 { gu_e("INFLATE-RED stored block LEN/NLEN mismatch\n" as *u8) } 40 if rc == 0 - 7 { gu_e("INFLATE-RED not a gzip container\n" as *u8) } 41 if rc == 0 - 8 { gu_e("INFLATE-RED unsupported compression method\n" as *u8) } 42 if rc == 0 - 9 { gu_e("INFLATE-RED CRC32 MISMATCH -- output is corrupt, refusing to present it as data\n" as *u8) } 43 if rc == 0 - 10 { gu_e("INFLATE-RED ISIZE mismatch\n" as *u8) } 44 if rc == 0 - 11 { gu_e("INFLATE-RED not a zlib container\n" as *u8) } 45 if rc == 0 - 12 { gu_e("INFLATE-RED code-length run overflows the table\n" as *u8) } 46 return 0 47} 48 49func main(argc: i64, argv: *i64) -> i64 { 50 if argc < 2 { 51 gu_e("usage: nx_gunzip <in.gz> [out] | nx_gunzip --crc <file>\n" as *u8) 52 sys_exit(2) 53 return 2 54 } 55 let a1: *u8 = argv[1] as *u8 56 let lp: *i64 = sys_mmap(16) as *i64 57 58 if a1[0] == (45 as u8) { 59 if argc < 3 { gu_e("--crc needs a file\n" as *u8); sys_exit(2); return 2 } 60 let b2: *u8 = sys_read_file(argv[2] as *u8, lp) 61 if (b2 as i64) == 0 { gu_e("cannot read\n" as *u8); sys_exit(1); return 1 } 62 gu_w("CRC32 " as *u8); gu_num(inf_crc32(b2, lp[0])) 63 gu_w(" bytes " as *u8); gu_num(lp[0]); gu_w("\n" as *u8) 64 sys_exit(0) 65 return 0 66 } 67 68 let b: *u8 = sys_read_file(a1, lp) 69 if (b as i64) == 0 { gu_e("INFLATE-RED cannot read input\n" as *u8); sys_exit(1); return 1 } 70 let n: i64 = lp[0] 71 let out: *u8 = sys_mmap(GU_CAP) 72 if (out as i64) == 0 { gu_e("INFLATE-RED cannot allocate output\n" as *u8); sys_exit(1); return 1 } 73 74 // dispatch on the container's own magic rather than on the filename -- an extension is a 75 // claim by whoever named the file; the magic is the file itself 76 var rc: i64 = 0 77 var kind: *u8 = "raw-deflate" as *u8 78 if n >= 2 { 79 let m0: i64 = (b[0] & 0xff) as i64 80 let m1: i64 = (b[1] & 0xff) as i64 81 if m0 == 0x1f { 82 if m1 == 0x8b { kind = "gzip" as *u8; rc = inf_gunzip(b, n, out, GU_CAP) } 83 } 84 if (m0 & 15) == 8 { 85 if ((m0 * 256 + m1) % 31) == 0 { 86 if m0 != 0x1f { kind = "zlib" as *u8; rc = inf_zlib(b, n, out, GU_CAP) } 87 } 88 } 89 } 90 if kind[0] == (114 as u8) { rc = inf_raw(b, n, out, GU_CAP) } 91 92 if rc < 0 { gu_reason(rc); sys_exit(3); return 3 } 93 94 if argc >= 3 { 95 let fd: i64 = sys_openat_wr(argv[2] as *u8, GU_MODE) 96 if fd < 0 { gu_e("INFLATE-RED cannot open output\n" as *u8); sys_exit(1); return 1 } 97 var w: i64 = 0 98 while w < rc { 99 let k: i64 = sys_write(fd, ((out as i64) + w) as *u8, rc - w) 100 if k <= 0 { sys_close(fd); gu_e("INFLATE-RED short write\n" as *u8); sys_exit(1); return 1 } 101 w = w + k 102 } 103 sys_close(fd) 104 gu_w("INFLATE-GREEN " as *u8); gu_w(kind); gu_w(" " as *u8); gu_num(n) 105 gu_w(" -> " as *u8); gu_num(rc); gu_w(" bytes (CRC32 verified)\n" as *u8) 106 } else { 107 sys_write(1, out, rc) 108 } 109 sys_exit(0) 110 return 0 111}