AxlTar — ustar Archive Reader/Writer
A small POSIX ustar codec layered on AxlStream: write a
sequence of named byte blobs into a tar archive, or read them back,
streaming through any stream — an in-memory buffer (axl_bufopen), a
file (axl_fopen), or anything else backing the stream API.
The writer (axl_tar_writer_new → axl_tar_writer_add /
axl_tar_writer_add_dir → axl_tar_writer_finish) emits standard
ustar headers with a correct checksum and block padding; names longer
than 100 bytes use the ustar name/prefix split (up to ~255 bytes), and a
name that can’t be split is rejected rather than truncated. The reader
(axl_tar_reader_new → axl_tar_reader_next → axl_tar_reader_read)
validates each header checksum and streams entry data, stopping at the
end-of-archive marker.
It backs the tar host tool and mkfixture’s HTTP write target (which
builds a fixture tarball in memory and POSTs it). GNU/PAX long-name and
sparse extensions are out of scope.
Header: <axl/axl-tar.h>
API Reference
POSIX ustar archive reader and writer over AxlStream.
A small, dependency-light tar codec: write a sequence of named byte blobs into a ustar archive (or read them back), streaming through any AxlStream — an in-memory buffer (axl_bufopen), a file (axl_fopen), or anything else that backs the stream API. Used by the tar tool and by mkfixture’s HTTP write target (which builds a fixture tarball in memory and POSTs it).
Scope: the ustar format — regular files and directories, names up to 255 bytes via the name/prefix split. GNU/PAX long-name and sparse extensions are out of scope; a name that won’t fit the ustar name(100)+prefix(155) split is rejected rather than silently truncated.
Defines
-
AXL_TAR_BLOCK
ustar block size; every header and the data of each entry is padded to a multiple of this.
-
AXL_TAR_NAME_MAX
Max entry-name length: ustar name(100) + ‘/’ + prefix(155), + NUL.
-
AXL_TAR_TYPE_FILE
Entry type, from the ustar typeflag byte.
regular file (also accepts ‘\0’)
-
AXL_TAR_TYPE_DIR
directory
Typedefs
-
typedef struct AxlTarWriter AxlTarWriter
Opaque tar writer. Created by axl_tar_writer_new, destroyed by axl_tar_writer_free. Does NOT own or close the underlying stream.
-
typedef struct AxlTarReader AxlTarReader
Opaque tar reader. Created by axl_tar_reader_new, destroyed by axl_tar_reader_free. Does NOT own or close the underlying stream.
Functions
-
AxlTarWriter *axl_tar_writer_new(AxlStream *out)
Create a tar writer that emits to
out.The writer borrows
out— the caller keeps ownership and closes it afteraxl_tar_writer_finish+axl_tar_writer_free.- Parameters:
out – destination stream (borrowed)
- Returns:
a writer, or NULL on allocation failure or if
outis NULL.
-
int axl_tar_writer_add(AxlTarWriter *w, const char *name, uint32_t mode, const void *data, size_t len)
Append a regular-file entry with in-memory contents.
Writes a ustar header for
name(split across the name/prefix fields when longer than 100 bytes) followed bylendata bytes zero-padded to the block size.- Parameters:
w – writer
name – entry path (e.g. “acpi/facp.dat”)
mode – permission bits (e.g. 0644)
data – file contents (may be NULL iff
lenis 0)len – content length in bytes
- Returns:
AXL_OK on success, AXL_ERR if
w/nameis NULL,datais NULL with non-zerolen, the name is too long for ustar, or the stream write fails.
-
int axl_tar_writer_add_dir(AxlTarWriter *w, const char *name, uint32_t mode)
Append a directory entry (no data).
Optional — extracting tools create parent directories implicitly, so archives built for the HTTP sink omit these. Provided for the
tartool’s fidelity.- Parameters:
w – writer
name – directory path (a trailing ‘/’ is added if absent)
mode – permission bits (e.g. 0755)
- Returns:
AXL_OK on success, AXL_ERR on bad args / name too long / write failure.
-
int axl_tar_writer_finish(AxlTarWriter *w)
Write the end-of-archive marker (two zero blocks).
Call once after the last entry, before freeing. The stream is flushed by the caller (or by closing it).
- Returns:
AXL_OK on success, AXL_ERR on write failure.
-
void axl_tar_writer_free(AxlTarWriter *w)
Free a tar writer. NULL-safe. Does not close the stream.
-
AxlTarReader *axl_tar_reader_new(AxlStream *in)
Create a tar reader over
in.The reader borrows
in(which must be positioned at the start of an archive).- Parameters:
in – source stream (borrowed)
- Returns:
a reader, or NULL on allocation failure / NULL
in.
-
int axl_tar_reader_next(AxlTarReader *r, AxlTarEntry *out)
Advance to the next archive entry.
Skips any unread data (and its padding) from the previous entry, reads and parses the next 512-byte header into
out, and leaves the stream positioned at the entry’s data — read it withaxl_tar_reader_read.- Returns:
AXL_OK with
outpopulated, or AXL_ERR at the end-of-archive marker, on a malformed/short header, or on a stream error (outuntouched). A clean end and a truncated archive both stop iteration the same way.
-
axl_ssize_t axl_tar_reader_read(AxlTarReader *r, void *buf, size_t len)
Read up to
lenbytes of the current entry’s data.Reads no further than the current entry’s declared size; returns 0 once the entry is exhausted. Call repeatedly to stream large entries. The entry size is taken from the header and trusted to the stream’s EOF behavior — a truncated archive that over-declares a size simply short-reads here (and the next advance stops), it cannot over-read.
- Returns:
bytes read (0 at end of the current entry), or -1 on a stream error.
-
void axl_tar_reader_free(AxlTarReader *r)
Free a tar reader. NULL-safe. Does not close the stream.
-
struct AxlTarEntry
- #include <axl-tar.h>
One archive entry, as reported by axl_tar_reader_next.