A xar archive is a binary header, a zlib-compressed XML table of contents, and a heap
that holds everything else. This page follows the xarformat page of the
xar project’s wiki; the TOC elements that page does not list are from libxar’s source
and from real archives such as macOS installer packages, and are marked.
Header
Big-endian.
| Offset | Size | Name | Description |
|---|---|---|---|
0 | 4 | magic | 78 61 72 21, xar!. |
4 | 2 | size | Size of the header, magic included. At least 28. |
6 | 2 | version | 1. libxar writes 1 and ignores the value when reading. |
8 | 8 | toc_length_compressed | Length of the compressed table of contents. |
16 | 8 | toc_length_uncompressed | Length of the table of contents after decompression. |
24 | 4 | cksum_alg | Checksum of the table of contents: 0 none, 1 SHA-1, 2 MD5, 3 another, named next. |
28 | … | name | Only when cksum_alg is 3: the algorithm’s name, NUL-terminated, padded with zeros to a multiple of 4. |
With cksum_alg 3, size must be a multiple of 4 and at least
32; the name must not be empty or none, should not be
sha1 or md5 (use 1 or 2), and must match the
style of the TOC’s checksum element byte for byte. libxar
always writes a 64-byte header in this case, so the name can be up to 35 bytes; other
names seen are sha256 and sha512. Older libxar versions
mishandle any header size other than 28.
The compressed table of contents follows the header at offset size,
exactly toc_length_compressed bytes of zlib data (RFC 1950). The checksum
is taken over these compressed bytes.
Heap
- The heap starts right after the compressed table of contents. Every
offsetin the TOC counts from the start of the heap. - The TOC checksum is normally first: the TOC’s
checksumelement gives its offset (usually 0) and size (20 for SHA-1, 16 for MD5). - For each stored stream,
lengthis the number of bytes in the heap andsizethe size after decoding. - For an archive that can be read as a stream, all of one file’s heap entries are together, and its extended attributes come before its data, so the security context is set before the data is written.
Table of contents
A UTF-8 XML document whose root is xar, holding one toc.
| Element | In | Meaning |
|---|---|---|
checksum, attribute style | toc | Where the TOC checksum is in the heap: child offset and size. style is sha1, md5 or the name in the header. |
creation-time | toc | When the archive was made (libxar; ISO 8601 text). |
signature, attribute style | toc | A signature of the TOC checksum, stored in the heap at child offset and size; style RSA, with the signer’s certificates in a KeyInfo / X509Data / X509Certificate chain (XML Signature namespace). Used to sign macOS packages (libxar; not in the wiki page). |
x-signature | toc | A second signature, style CMS, written by Apple’s tools beside the RSA one (seen in packages; not in the wiki page). |
file, attribute id | toc or another file | One archive member. A folder’s members are nested inside its file element. id is a unique number. |
Inside file
| Element | Meaning |
|---|---|
name | The name, without the path (the nesting gives the path). |
type | file, directory, symlink, hardlink, fifo, character special, block special, socket or whiteout (libxar). A hard link has link="original" on the first copy and link="id" on the others. |
link | Target of a symbolic link, with type="file", "directory" or "broken". |
mode | Permission bits, in octal text, such as 0755. |
uid, gid | Numeric owner and group. |
user, group | Owner and group names. |
atime, mtime, ctime | Times in ISO 8601, such as 2024-05-01T12:00:00Z. |
size | Size of the file. |
inode, deviceno, nlink | Inode number, device number and link count (libxar). |
device | For device files: children major and minor (libxar). |
flags | BSD file flags, one child element per flag set, such as UserNoDump or SystemImmutable (libxar). |
FinderCreateTime | The Mac creation date: children time and nanoseconds (libxar on macOS). |
data | The file’s contents in the heap: see data. |
ea, attribute id | One extended attribute, such as com.apple.ResourceFork or com.apple.FinderInfo: child name and the same children as data. |
Inside data and ea
| Element | Meaning |
|---|---|
offset | Where the stored bytes start, from the start of the heap. |
length | How many bytes are stored. |
size | How many bytes they decode to. |
encoding, attribute style | How the bytes are stored, as a MIME type: application/octet-stream (stored), application/x-gzip (zlib data, despite the name), application/x-bzip2, application/x-lzma or application/x-xz (libxar’s set). |
archived-checksum, attribute style | Checksum of the stored bytes, in hexadecimal text. |
extracted-checksum, attribute style | Checksum of the decoded bytes. |
Example
<xar>
<toc>
<checksum style="sha1"><offset>0</offset><size>20</size></checksum>
<file id="1">
<name>hello.txt</name>
<type>file</type>
<mode>0644</mode>
<uid>501</uid><user>lew</user><gid>20</gid><group>staff</group>
<mtime>2024-05-01T12:00:00Z</mtime>
<data>
<offset>20</offset><length>26</length><size>14</size>
<encoding style="application/x-gzip"/>
<archived-checksum style="sha1">…</archived-checksum>
<extracted-checksum style="sha1">…</extracted-checksum>
</data>
</file>
</toc>
</xar>
An illustration put together for this page: the heap holds the 20-byte SHA-1 of the compressed TOC at offset 0, then the file’s 26 bytes of zlib data.