NAME

File::Raw::Archive - Archive container reader/writer

VERSION

Version 0.02

SYNOPSIS

use File::Raw::Archive;

# iterate
my $ar = File::Raw::Archive->open("foo.tar");
while (my $entry = $ar->next) {
    next if $entry->is_dir;
    my $bytes = $entry->slurp;
}
$ar->close;

# one-liner each (last arg is the callback)
File::Raw::Archive->each("logs.tar.gz",
    compression => 'gzip',
    sub {
        my $e = shift;
        return if $e->is_dir;
        print $e->name, " (", $e->size, " bytes)\n";
    });

# list everything as an arrayref of metadata snapshots
my $rows = File::Raw::Archive->list("foo.tar");

# extract everything
File::Raw::Archive->extract_all("foo.tar.gz", "/tmp/out",
    compression => 'gzip');

# extract one entry by name
File::Raw::Archive->extract("foo.tar", "path/inside", "/tmp/out.txt");

# build a tarball
my $w = File::Raw::Archive->create("out.tar.gz",
    compression => 'gzip', level => 9);
$w->add(name => 'README', content => $readme, mode => 0644);
$w->add(name => 'src/');                                # dir
$w->add(name => 'src/main.c', content => $main_c);
$w->close;

DESCRIPTION

File::Raw::Archive handles archive containers with a streaming, plugin-driven API. The built-in tar plugin reads ustar (POSIX 1988), GNU ././@LongLink, and PAX extended-header tarballs, and writes ustar / GNU / PAX / auto depending on the format option.

Additional format plugins (zip, cpio, ar) can be loaded at run time by installing the matching File::Raw::Archive::* sister module.

METHODS

Reading

File::Raw::Archive->open($path, %opts)

Open $path for sequential reading. Returns a File::Raw::Archive::Reader. The format and compression are auto-detected unless overridden with plugin / compression.

my $r = File::Raw::Archive->open("foo.tar.gz");
while (my $e = $r->next) { ... }
$r->close;
File::Raw::Archive->list($path, %opts)

Read the entire archive and return an array-reference of metadata snapshots. Each element is a plain hashref with keys name, size, mode, mtime, mtime_ns, uid, gid, type, link_target, xattrs, and is_sparse.

my $entries = File::Raw::Archive->list("foo.tar");
printf "%s  %d\n", $_->{name}, $_->{size} for @$entries;
File::Raw::Archive->each($path, %opts, \&callback)

Iterate the archive, calling \&callback once per entry with a File::Raw::Archive::Entry as its sole argument. The callback is the last positional argument; options go between $path and the coderef. Returns nothing.

File::Raw::Archive->each("logs.tar.gz",
    compression => 'gzip',
    sub {
        my $e = shift;
        return if $e->is_dir;
        print $e->name, " (", $e->size, " bytes)\n";
    });

Accepts entry_filter to pre-screen entries before the callback runs.

File::Raw::Archive->extract($path, $name, $dest, %opts)

Extract the single entry whose name exactly matches $name from the archive at $path, writing it to the filesystem path $dest. Returns 1 if the entry was found and written, 0 if it was not present in the archive.

my $ok = File::Raw::Archive->extract(
    "foo.tar", "path/inside/archive", "/tmp/out.txt");
File::Raw::Archive->extract_all($path, $dest, %opts)

Extract every entry from $path under the directory $dest, creating it if necessary. Returns 1 on success; croaks on error.

File::Raw::Archive->extract_all("foo.tar.gz", "/tmp/out",
    compression => 'gzip');

When parallel => N (N > 1) is given, file content is dispatched round-robin to N forked worker processes. Falls back to sequential on platforms without fork(2).

Writing

File::Raw::Archive->create($path, %opts)

Open $path for writing and return a File::Raw::Archive::Writer.

my $w = File::Raw::Archive->create("out.tar.gz",
    compression => 'gzip', level => 9);
$w->add(name => 'README', content => $bytes, mode => 0644);
$w->add(name => 'src/');
$w->close;

Exported functions

Importing one or more names installs the matching file_archive_* function into the caller's package. All six names can be requested at once with import or :all.

use File::Raw::Archive qw(open list each extract extract_all create);
# or: all six at once
use File::Raw::Archive qw(import);
use File::Raw::Archive qw(:all);

Each exported function is identical to the class method of the same name but takes no leading $class argument.

file_archive_open($path, %opts)
file_archive_create($path, %opts)
file_archive_list($path, %opts)
file_archive_each($path, %opts, \&callback)
file_archive_extract($path, $name, $dest, %opts)
file_archive_extract_all($path, $dest, %opts)

OPTIONS

All options are passed as a flat key-value list after the mandatory positional arguments.

plugin

Archive format name. tar is always built in. Sister modules add zip, cpio, and ar. Default: tar.

compression

none, gzip, or auto. On read, auto sniffs the gzip magic bytes 1f 8b; on write, auto checks the path suffix (.gz). Default: auto.

level

Gzip compression level, 0-9. Meaningful only when compression => 'gzip' is in effect on a write. Default: 6.

format

Write-side only. Tar emission strategy: auto, pax, gnu, or ustar. See "TAR FORMAT MODES". Default: auto.

global_meta

Write-side only. A hashref of PAX key-value pairs emitted in a 'g' (global) extended header at the start of the archive. Subsequent entries inherit these values unless overridden per-entry.

entry_filter

Read-side coderef used by each and extract_all. Receives the File::Raw::Archive::Entry before the main callback or extraction step. Returning false causes the entry to be skipped.

xattrs

extract and extract_all only. When true (the default), extended attributes stored as SCHILY.xattr.* PAX records are applied to extracted files via the platform xattr API.

unsafe_paths

extract_all only. Default 0. When false, entry names containing .. components or absolute paths are refused. Set to 1 only for trusted archives.

parallel

extract_all only. Number of forked worker processes for parallel extraction. Default 1 (sequential). Falls back to sequential on platforms that lack fork(2).

TAR FORMAT MODES

auto (default)

Emit ustar when every field fits; escalate to GNU @LongLink for long names; escalate to PAX for everything ustar/@LongLink cannot carry (size > 8 GiB, large uid/gid, sub-second mtime, xattrs).

pax

Emit a PAX 'x' header for every entry needing escalation, matching GNU tar 1.30+ default behaviour. Slightly larger output but more uniform and portable.

gnu

Keep @LongLink for long names; croak on fields that require PAX.

ustar

Strict ustar only. Croaks on any field that does not fit.

PLUGIN API

File::Raw::Archive publishes its C plugin API (archive_plugin.h) via ExtUtils::Depends. Sister dists call archive_register_plugin at BOOT time to add new formats; archive_lookup_plugin and archive_probe_for are available for probing.

SEE ALSO

File::Raw::Archive::Reader, File::Raw::Archive::Writer, File::Raw::Archive::Entry, File::Raw, Archive::Tar, IO::Compress::Gzip.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)