Archive-Libarchive
view release on metacpan or search on metacpan
archive_version_number
# archive_version_number
my $int = archive_version_number();
The libarchive version expressed as an integer. This will be the major,
minor and patch levels each using up to three digits, so 3.5.1 will be
3005001.
archive_version_string
# archive_version_string
my $string = archive_version_string();
The libarchive version as a string.
archive_zlib_version
# archive_zlib_version
my $string = archive_zlib_version();
The zlib version that libarchive was built with. This will return undef
if the library was not found at build time.
versions
my %versions = Archive::Libarchive->versions();
This returns a hash of libarchive and Archive::Libarchive versions and
dependency versions. This may be useful in a test report diagnostic.
EXAMPLES
These examples are translated from the libarchive C examples, which can
be found here:
https://github.com/libarchive/libarchive/wiki/Examples
List contents of archive stored in file
The main Archive::Libarchive API is based around two basic type of
classes. The Archive::Libarchive::Archive class serves as a basis for
all archive objects. The Archive::Libarchive::Entry represents the
header or metadata for files stored inside an archive (or as we will
see later, files on disk).
The basic life cycle of an archive instance is:
Create one using its new constructor
The constructor does not take any arguments, instead you will
configure it in the next step.
Configure it using "support" or "set" calls
Support calls allow Archive::Libarchive to decide when to use a
feature; "set" calls enable the feature unconditionally.
"Open" a particular data source
This can be using callbacks for a custom source, or one of the
pre-canned data sources supported directly by Archive::Libarchive.
Iterate over the contents
Ask alternatively for "header" or entry/file metadata (which is
represented by a Archive::Libarchive::Entry instance), and entry/file
content.
Finish by calling "close"
This will be called automatically if the archive instance falls out
of scope.
Writing an archive is very similar, except that you provide the
"header" and content data to Archive::Libarchive instead of asking for
them.
Here is a very basic example that simply opens a file and lists the
contents of the archive.
use 5.020;
use Archive::Libarchive qw( ARCHIVE_OK );
my $r = Archive::Libarchive::ArchiveRead->new;
$r->support_filter_all;
$r->support_format_all;
my $ret = $r->open_filename("archive.tar", 10240);
if($ret != ARCHIVE_OK) {
exit 1;
}
my $e = Archive::Libarchive::Entry->new;
while($r->next_header($e) == ARCHIVE_OK) {
say $e->pathname;
$r->read_data_skip;
}
Note that open_filename method inspects the file before deciding how to
handle the block size. If the filename provided refers to a tape
device, for example, it will use exactly the block size you specify.
For other devices, it may adjust the requested block size in order to
obtain better performance.
Note that the call to read_data_skip here is not actually necessary,
since Archive::Libarchive will invoke it automatically if you request
the next header without reading the data for the last entry.
The module Archive::Libarchive::Peek also provides similar
functionality to this example in a simple, less powerful interface.
List contents of archive stored in memory
There are several variants of the open methods. The "filename" variant
used above is intended to be simple to use in the common case of
reading from a file from disk, but you may find the "memory" variant
useful in other cases.
use 5.020;
use Path::Tiny qw( path );
use Archive::Libarchive qw( ARCHIVE_OK );
my $r = Archive::Libarchive::ArchiveRead->new;
$r->support_filter_all;
$r->support_format_all;
my $buffer = path('archive.tar')->slurp_raw;
my $ret = $r->open_memory(\$buffer);
if($ret != ARCHIVE_OK) {
exit 1;
}
my $e = Archive::Libarchive::Entry->new;
while($r->next_header($e) == ARCHIVE_OK) {
say $e->pathname;
$r->read_data_skip;
}
There are also variants to read from an already-opened file descriptor,
a libc FILE pointer, or a Perl file handle.
List contents of archive with custom read functions
Sometimes, none of the packaged open methods will work for you. In that
case, you can use the lower-level open method, which accepts a number
of callbacks. For this example we will use the open, read and close
callbacks.
use 5.020;
use Archive::Libarchive qw( :const );
my $r = Archive::Libarchive::ArchiveRead->new;
$r->support_filter_all;
$r->support_format_all;
my $fh;
$r->open(
open => sub {
open $fh, '<', 'archive.tar';
binmode $fh;
return ARCHIVE_OK;
},
read => sub {
my(undef, $ref) = @_;
my $size = read $fh, $$ref, 512;
return $size;
},
close => sub {
close $fh;
return ARCHIVE_OK;
},
) == ARCHIVE_OK or die $r->error_string;
my $e = Archive::Libarchive::Entry->new;
while(1) {
my $ret = $r->next_header($e);
last if $ret == ARCHIVE_EOF;
die $r->error_string if $ret < ARCHIVE_WARN;
warn $r->error_string if $ret != ARCHIVE_OK;
say $e->pathname;
}
$r->close;
For full power of read callbacks see the open method's documentation.
When writing to an archive the Archive::Libarchive::ArchiveWrite class
also has its own open method and callbacks.
A universal decompressor / defilter-er
The "raw" format handler treats arbitrary binary input as a
single-element archive. This allows you to get the output of a
libarchive filter chain, including files with multiple encodings, such
as gz.uu files:
use 5.020;
use Archive::Libarchive;
my $r = Archive::Libarchive::ArchiveRead->new;
$r->support_filter_all;
$r->support_format_raw;
$r->open_filename("hello.txt.uu");
$r->next_header(Archive::Libarchive::Entry->new);
my $buffer;
while($r->read_data(\$buffer)) {
print $buffer;
}
$r->close;
Note that the "raw" format is not enabled by the support_format_all
method on Archive::Libarchive::ArchiveRead. Also note that the "raw"
format handler does not recognize or accept empty files. If you
specifically want to be able to read empty files, you'll need to also
invoke the support_format_empty method on
Archive::Libarchive::ArchiveRead.
The module Archive::Libarchive::Unwrap also provides similar
functionality to this example in a simple, less powerful interface.
A basic write example
The following is a very simple example of using Archive::Libarchive to
write a group of files into a tar archive. This is a little more
complex than the read examples above because the write example actually
does something with the file bodies.
use 5.020;
use Archive::Libarchive;
use Path::Tiny qw( path );
my $w = Archive::Libarchive::ArchiveWrite->new;
$w->set_format_pax_restricted;
$w->open_filename("outarchive.tar");
path('.')->visit(sub ($path, $) {
my $path = shift;
return if $path->is_dir;
my $e = Archive::Libarchive::Entry->new;
$e->set_pathname("$path");
$e->set_size(-s $path);
$e->set_filetype('reg');
$e->set_perm( oct('0644') );
$w->write_header($e);
( run in 0.894 second using v1.01-cache-2.11-cpan-39bf76dae61 )