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
| Function | Description |
| 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
| Function | Description |
| 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
| Function | Description |
| 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
| Function | Description |
| 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 |