Read and write tar archives — the middle layer of a .deb.
Inside a .deb, both control.tar.* and data.tar.* are tar archives (once
decompressed). This module reads regular-file entries into {name, bytes}
pairs and writes entries back out as a deterministic ustar archive.
Regular files only
read/1 returns regular file entries. Directory, symlink, hardlink, and
device entries are skipped — .deb control tars are all regular files, which
is the case this library targets. (Data tars you typically store and serve
verbatim rather than read through here.)
Determinism
write/1 emits ustar entries with mtime 0, uid 0, and gid 0, so equal
input yields equal output — the basis for reproducible packages.
Example
iex> tar = Debkit.Tar.write!([
...> {"./control", "Package: hello\n"},
...> {"./md5sums", "", 0o644}
...> ])
iex> {:ok, entries} = Debkit.Tar.read(tar)
iex> Enum.map(entries, &elem(&1, 0))
["./control", "./md5sums"]
Summary
Types
An entry read from an archive: its name and contents.
An entry to write. The 2-tuple form defaults the file mode to 0o644; the
3-tuple form sets it explicitly.
Functions
Reads a tar archive into its regular-file entries, in archive order.
Like read/1 but returns the entries directly, raising Debkit.Error on failure.
Writes entries to a deterministic ustar archive.
Like write/1 but returns the bytes directly, raising Debkit.Error on failure.
Types
An entry read from an archive: its name and contents.
@type write_entry() :: {name :: String.t(), contents :: binary()} | {name :: String.t(), contents :: binary(), mode :: non_neg_integer()}
An entry to write. The 2-tuple form defaults the file mode to 0o644; the
3-tuple form sets it explicitly.
Functions
@spec read(binary()) :: {:ok, [entry()]} | {:error, Debkit.error()}
Reads a tar archive into its regular-file entries, in archive order.
Returns {:error, :corrupt} if binary is not a well-formed tar archive.
Examples
iex> {:ok, entries} = Debkit.Tar.read(Debkit.Tar.write!([{"./x", "hi"}]))
iex> entries
[{"./x", "hi"}]
Like read/1 but returns the entries directly, raising Debkit.Error on failure.
@spec write([write_entry()]) :: {:ok, binary()} | {:error, Debkit.error()}
Writes entries to a deterministic ustar archive.
Each entry is {name, contents} (mode defaults to 0o644) or
{name, contents, mode}. Entries are written in the order given.
Examples
iex> {:ok, tar} = Debkit.Tar.write([{"./control", "Package: hello\n", 0o644}])
iex> is_binary(tar)
true
@spec write!([write_entry()]) :: binary()
Like write/1 but returns the bytes directly, raising Debkit.Error on failure.