tar
Tar archive codec over the CX bytes scalar kind. pack turns a sequence of entry maps (name, data, and optional mtime-unix, mode, type and link-target) into deterministic, byte-stable archive bytes; unpack decodes every entry; entries lists metadata without materializing payloads; extract decodes one entry by name. tar has a typeflag, so the entry model states :file / :directory / :symlink / :hardlink outright rather than encoding kind in the name. pack emits ustar when every field fits and pax extended headers only for a field ustar cannot represent. There are no tar.gz verbs — that is cx-stdlib/bytes gzip composed with these, which adds no capability as a wrapper. Refusals split by whose fault it is: a valid record this codec declines is CXER5501, a broken file is CXER5500.
tar:pack
[$tar:pack] -> bytes — Pack a sequence of entry maps into deterministic tar archive bytes; refuses unsafe or duplicate names.
[?lib 'cx-stdlib/tar']
[?lib 'cx-stdlib/bytes']
[$bytes:length [$tar:pack ()]]
1024
tar:unpack
[$tar:unpack] -> [sequence map] — Decode every archive entry to a map of name, data and metadata, verifying each header checksum.
[?lib 'cx-stdlib/tar']
[$count [$tar:unpack [$tar:pack ({name: 'docs/a.txt', data: 'alpha'},
{name: 'docs/b.txt', data: 'beta'})]]]
2
tar:entries
[$tar:entries] -> [sequence map] — List entry metadata without materializing payloads — one pass over the headers, skipping each payload by its declared size.
[?lib 'cx-stdlib/tar']
[?let [= $a [$tar:pack ({name: 'a.txt', data: 'hello'})]]
[= $e [$nth [$tar:entries $a] 1]]
($e/name, $e/size, $e/type)]
('a.txt', 5, file)
tar:extract
[$tar:extract] -> bytes — Decode a single entry payload by name; raises CXER5502 when the name is absent.
[?lib 'cx-stdlib/tar']
[?lib 'cx-stdlib/bytes']
[$bytes:to-string-utf8 [$tar:extract [$tar:pack ({name: 'a.txt', data: 'hello tar'})] "a.txt"]]
'hello tar'