# Tectonic Bundle Format V1 Specification

A single TTBv1 bundle may be used on the network or from a local filesystem. This bundle format contains two parts:
 - A 66-byte header, documented below
 - File data, a concatenated blob of gzipped files. One of these blobs is the bundle index.

Note that the extension for a tectonic bundle is `ttb`, regardless of its version. Also note that a bundle's hash depends on it's content. If we generate two bundles in different formats from one specification, the the resulting bundle hashes should be identical..


### Header format
A TTBv1 header consists of the following fields, in order.
All numbers are stored with little-endian byte ordering.

 - `14 bytes`: magic bytes. Always `tectonicbundle`, in any ttb version.
 - ` 4 bytes`: bundle version, a `u32`. In this case, always 1.
 - ` 8 bytes`: index location, a `u64`. This is the first byte of the bundle index file.
 - ` 4 bytes`: gzipped index length, a `u32`. This is the length the bundle index file.
 - ` 4 bytes`: true index length, a `u32`. This is the decompressed length of the bundle index file.
 - `32 bytes`: this bundle's hash.


### Index
Bundle contents are stored as a concatenated `gzip` blobs after the header. These are found using a special file called the Index, the location of which location is stored in the header. The index is generated from the "meta-files" that the file selector produces, namely `FILELIST` and `SEARCH`. These are included in the bundle for consistency, but shouldn't ever be used.

The index may be retrieved from a bundle by running `dd if=file.ttb ibs=1 skip=<start> count=<len> | gunzip`.


The Index file comes in sections, each of which starts on a line marked with square braces. The following sections are currently used, all others are ignored.

 - `[DEFAULTSEARCH]`: the default search order.
 - `[SEARCH:<name>]`: a search specification. Tectonic will search these paths for files, in this order. See the [bundle spec documentation](../../bundles/README.md).
 - `[FILELIST]`: a list of files in this bundle.
   - Each line contains the following: `<start_byte> <gzip_len> <real_len> <hash> <path>`
   - `<hash>` is either a sha256 hash, or `nohash` for certain special files.
   - `<start_byte>` and `<gzip_len>` are the location and length of files in the bundle.
   - `<real_len>` is the decompressed length of each file, used for efficient memory allocation.
   - `<path>` is the file's path. This is relative, and doesn't start with a slash. Also, this is intentionally last: paths may contain spaces (but not newlines!).

This index is generated by a script, so *very little error-checking is done inside Tectonic*. Keep the following in mind:
 - Empty lines should not exist
 - Any lines before a section specification are ignored
 - Invalid sections are ignored
 - Only the last line of `[DEFAULTSEARCH]` has any effect
 - We assume that the default `[SEARCH:<name>]` exists.

An example index is below.
```
[DEFAULTSEARCH]
MAIN
[SEARCH:MAIN]
/
/include//
/texlive/tex/xelatex//
/texlive/tex/latex//
/texlive/tex/xetex//
/texlive/tex/plain//
[FILELIST]
70 6065990 17331559 nohash FILELIST
6066060 133 360 589b5c09a33c2655c76f9a6b9bbb6060674c896fbc5b4555af0e20c86f32ac13 SEARCH
6066193 72 65 nohash SHA256SUM
6066265 39 19 86d8d12cfdfbe74a81b9df7c5b38a766303a772d57e7cb0d228e1e7b9294cf34 include/tectonic/tectonic-format-latex.tex
... many more lines ...
```