libarchive clib

Universal archive I/O — create and extract tar, zip, 7z, gz, bz2, xz, zst with a single API.

ppm install libarchive
System dependency: sudo apt install libarchive-dev

Overview

libarchive reads and writes virtually every archive format — tar, zip, 7-zip, cpio, ar, iso9660 — with any compression codec (gzip, bzip2, xz, zstd, lz4). It is the engine behind pacman, cmake --install, bsdtar, and dozens of other package managers and build tools. On read, format and compression are auto-detected from magic bytes, so you never need to know the extension in advance.

The API is split into three tiers: one-shot helpers (ExtractAll, CompressDir) for the common case; an entry-level loop for selective extraction or inspection; and a streaming write API for constructing archives programmatically.

Quick Extract

uses libarchive;

// Extract every entry from any archive format to a destination folder
ExtractAll('archive.tar.gz', '/tmp/out');

// List all entries without extracting
var entries := ListEntries('archive.zip');
for var e in entries do
  WriteLn(e.Pathname, '  ', e.Size, ' bytes');

// Extract a single known file
ExtractFile('archive.tar.xz', 'config/settings.json', '/tmp/settings.json');

Manual Read Loop

uses libarchive;

var ar := OpenRead('backup.tar.bz2');
while NextEntry(ar) do begin
  var info := GetEntryInfo(ar);
  WriteLn(info.Pathname, '  ', info.Size, '  dir=', info.IsDir);

  if ContainsFile(ar, 'README.md') then begin
    var data := ReadEntryData(ar);
    WriteFile('/tmp/README.md', data);
  end;
end;
CloseArchive(ar);

Create a tar.gz

uses libarchive;

// Open a new .tar.gz for writing
var aw := OpenWrite('release.tar.gz', afTar, filterGzip);

// Add individual files and entire directories
AddFile(aw, '/src/main.pas');
AddFileAs(aw, '/build/app.exe', 'bin/app.exe');  // custom path inside archive
AddDirectory(aw, '/src/assets');

CloseArchive(aw);

In-Memory Zip

uses libarchive;

// Build a zip entirely in RAM — no temp file needed
var aw := OpenWriteMemory(afZip, filterNone);

AddBytes(aw, 'hello.txt', StrToBytes('Hello, archive!'));
AddBytes(aw, 'data/nums.bin', myBinaryBlob);

var zipBytes := WriteToBytes(aw);  // returns array of Byte
CloseArchive(aw);

// Detect what format a blob is
WriteLn(DetectFormat(zipBytes));  // 'zip'

API Reference

Reading

FunctionDescription
OpenRead(path)Open an archive file for reading; auto-detects format and compression
OpenReadBytes(data)Open an in-memory byte array as an archive for reading
NextEntry(ar)Advance to the next entry; returns False at end-of-archive
GetEntryInfo(ar)Return TArchiveEntry record for the current entry (Pathname, Size, MTime, Permissions, IsDir)
ReadEntryData(ar)Read and return the raw bytes of the current entry
ExtractEntry(ar, destDir)Extract the current entry to destDir, preserving sub-path
ExtractAll(path, destDir)One-shot: extract every entry from path into destDir
ExtractFile(path, entry, dest)Extract a single named entry from archive path to dest
ListEntries(path)Return a List of TArchiveEntry without extracting data
ContainsFile(ar, name)True if the current entry's pathname matches name

Writing

FunctionDescription
OpenWrite(path, fmt, filter)Create an archive file; fmt = afTar/afZip/af7Zip/afCpio; filter = filterGzip/filterBzip2/filterXz/filterZstd/filterNone
OpenWriteMemory(fmt, filter)Create an in-memory archive; use WriteToBytes to retrieve bytes
NewEntry(aw)Allocate a new TArchiveEntry for manual population
SetEntryPathname(e, path)Set the entry's path inside the archive
SetEntrySize(e, size)Set the entry's uncompressed size in bytes
SetEntryMTime(e, ts)Set the entry's modification timestamp (Unix epoch)
SetEntryPermissions(e, perm)Set POSIX permission bits (e.g. 0o644)
SetEntryIsDir(e, val)Mark the entry as a directory
WriteEntryHeader(aw, e)Write the entry header before streaming data
WriteEntryData(aw, data)Stream raw bytes for the current entry body
FreeEntry(e)Release a manually allocated TArchiveEntry
AddFile(aw, path)Add a file from disk using its filename as the archive path
AddFileAs(aw, path, archivePath)Add a file from disk with a custom path inside the archive
AddDirectory(aw, dir)Recursively add all files under dir
AddBytes(aw, name, data)Add an in-memory byte array as a named entry

One-Shot Helpers

FunctionDescription
CompressFile(src, dest)Wrap a single file into an archive; format inferred from dest extension
CompressDir(dir, dest)Recursively pack a directory into an archive file
CompressFiles(files, dest)Pack a List of file paths into one archive
CompressDirToBytes(dir, fmt, filter)Pack a directory and return the archive as a byte array

Close & Utilities

FunctionDescription
CloseArchive(ar)Flush and close a read or write archive handle
WriteToBytes(aw)Finalize an in-memory write archive and return its bytes
DetectFormat(data)Detect the archive format string ('tar', 'zip', '7zip', …) from a byte array