tectonic/bundles/format-v1.md

3.3 KiB

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.
  • [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 ...