Archive-Libarchive-FFI

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

  - Archive::Libarchive 0.19 compatability

0.0706    2014-03-31 11:10:49 -0400
  - fix for OpenBSD

0.0705    2014-03-27 12:59:38 -0400
  - for libarchive 2.x, use our own Perl implementation of archive_read_open_memory
    as interfacing with the C version is causing SIGSEGV.

0.0704    2014-03-27 10:41:31 -0400
  - Take advantage of FFI::Raw 0.29's ability to return strings from callbacks
  - And therefore remove dependency on Module::Build::FFI

0.0703    2014-03-24 17:17:33 -0400
  - fixed some type declarations which were causing failures on 32bit Linux
    (possibly others)
    specifically: use int64_t instead of gid_t/uid_t for UID/GID types
                  use size_t instead of int64_t for buffer sizes

0.0702    2014-02-22 10:30:50 -0500
  - require FFI::Raw 0.28 and FFI::Util 0.06 for recent bugfixes

lib/Archive/Libarchive/FFI/Callback.pm  view on Meta::CPAN

package Archive::Libarchive::FFI::Callback;

use strict;
use warnings;
use 5.008;

# ABSTRACT: Libarchive callbacks
our $VERSION = '0.0902'; # VERSION

package
  Archive::Libarchive::FFI;

BEGIN {

  if(eval { require FFI::Sweet })
  {
    FFI::Sweet->import;

lib/Archive/Libarchive/FFI/Callback.pm  view on Meta::CPAN

  CB_READ        => 1,
  CB_CLOSE       => 2,
  CB_OPEN        => 3,
  CB_WRITE       => 4,
  CB_SKIP        => 5,
  CB_SEEK        => 6,
  CB_SWITCH      => 7,
  CB_BUFFER      => 8,
};

my %callbacks;

do {
  no warnings 'redefine';
  sub _attach_function ($$$;$)
  {
    eval {
      attach_function($_[0], $_[1], $_[2], $_[3]);
    };
    warn $@ if $@ && $ENV{ARCHIVE_LIBARCHIVE_FFI_VERBOSE};
  }
};

my $myopen = FFI::Raw::Callback->new(sub {
  my($archive) = @_;
  my $status = eval {
    $callbacks{$archive}->[CB_OPEN]->($archive, $callbacks{$archive}->[CB_DATA]);
  };
  if($@)
  {
    warn $@;
    return ARCHIVE_FATAL();
  }
  $status;
}, _int, _ptr, _ptr);

my $mywrite = FFI::Raw::Callback->new(sub
{
  my($archive, $null, $ptr, $size) = @_;
  my $buffer = buffer_to_scalar($ptr, $size);
  my $status = eval {
    $callbacks{$archive}->[CB_WRITE]->($archive, $callbacks{$archive}->[CB_DATA], $buffer);
  };
  if($@)
  {
    warn $@;
    return ARCHIVE_FATAL();
  }
  $status;
}, _int, _ptr, _ptr, _ptr, _size_t);

my $myread = FFI::Raw::Callback->new(sub
{
  my($archive, $null, $optr) = @_;
  my($status, $buffer) = eval {
    $callbacks{$archive}->[CB_READ]->($archive, $callbacks{$archive}->[CB_DATA]);
  };
  if($@)
  {
    warn $@;
    return ARCHIVE_FATAL();
  }
  my($ptr, $size) = scalar_to_buffer($buffer);
  deref_ptr_set($optr, $ptr);
  $size;
}, _uint64, _ptr, _ptr, _ptr);

my $myskip = FFI::Raw::Callback->new(sub
{
  my($archive, $null, $request) = @_;
  my $status = eval {
    $callbacks{$archive}->[CB_SKIP]->($archive, $callbacks{$archive}->[CB_DATA], $request);
  };
  if($@)
  {
    warn $@;
    return ARCHIVE_FATAL();
  }
  $status;
}, _uint64, _ptr, _ptr, _uint64);

my $myseek = FFI::Raw::Callback->new(sub
{
  my($archive, $null, $offset, $whence) = @_;
  my $status = eval {
    $callbacks{$archive}->[CB_SEEK]->($archive, $callbacks{$archive}->[CB_DATA], $offset, $whence);
  };
  if($@)
  {
    warn $@;
    return ARCHIVE_FATAL();
  }
  $status;
}, _uint64, _ptr, _ptr, _uint64, _int);

my $myclose = FFI::Raw::Callback->new(sub
{
  my($archive) = @_;
  my $status = eval {
    $callbacks{$archive}->[CB_CLOSE]->($archive, $callbacks{$archive}->[CB_DATA]);
  };
  if($@)
  {
    warn $@;
    return ARCHIVE_FATAL();
  }
  $status;
}, _int, _ptr, _ptr);

_attach_function 'archive_write_open', [ _ptr, _ptr, _ptr, _ptr, _ptr ], _int, sub
{
  my($cb, $archive, $cd, $open, $write, $close) = @_;
  $callbacks{$archive}->[CB_DATA] = $cd;
  if(defined $open)
  {
    $callbacks{$archive}->[CB_OPEN] = $open;
    $open = $myopen;
  }
  if(defined $write)
  {
    $callbacks{$archive}->[CB_WRITE] = $write;
    $write = $mywrite;
  }
  if(defined $close)
  {
    $callbacks{$archive}->[CB_CLOSE] = $close;
    $close = $myclose;
  }
  $cb->($archive, undef, $open||0, $write||0, $close||0);
};

sub archive_read_open ($$$$$)
{
  my($archive, $data, $open, $read, $close) = @_;
  archive_read_open2($archive, $data, $open, $read, undef, $close);
}

_attach_function 'archive_read_open2', [ _ptr, _ptr, _ptr, _ptr, _ptr, _ptr ], _int, sub
{
  my($cb, $archive, $cd, $open, $read, $skip, $close) = @_;
  $callbacks{$archive}->[CB_DATA] = $cd;
  if(defined $open)
  {
    $callbacks{$archive}->[CB_OPEN] = $open;
    $open = $myopen;
  }
  if(defined $read)
  {
    $callbacks{$archive}->[CB_READ] = $read;
    $read = $myread;
  }
  if(defined $skip)
  {
    $callbacks{$archive}->[CB_SKIP] = $skip;
    $skip = $myskip;
  }
  if(defined $close)
  {
    $callbacks{$archive}->[CB_CLOSE] = $close;
    $close = $myclose;
  }
  $cb->($archive, undef, $open||0, $read||0, $skip||0, $close||0);
};

sub archive_read_set_callback_data ($$)
{
  my($archive, $data) = @_;
  $callbacks{$archive}->[CB_DATA] = $data;
  ARCHIVE_OK();
}

foreach my $name (qw( open read skip close seek ))
{
  my $const = 'CB_' . uc $name;
  my $wrapper = eval '# line '. __LINE__ . ' "' . __FILE__ . "\n" . qq{
    sub
    {
      my(\$cb, \$archive, \$callback) = \@_;
      \$callbacks{\$archive}->[$const] = \$callback;
      \$cb->(\$archive, \$my$name);
    }
  };die $@ if $@;

  _attach_function "archive_read_set_$name\_callback", [ _ptr, _ptr ], _int;
}

if(archive_version_number() >= 3000000)
{
  _attach_function 'archive_read_open_memory', [ _ptr, _ptr, _size_t ], _int, sub
  {
    my($cb, $archive, $buffer) = @_;
    my $length = do { use bytes; length $buffer };
    my $ptr = FFI::Raw::MemPtr->new_from_buf($buffer, $length);
    $callbacks{$archive}->[CB_BUFFER] = $ptr;  # TODO: CB_BUFFER or CB_DATA (or something else?)
    $cb->($archive, $ptr, $length);
  };
}
else
{
  sub _archive_read_open_memory_read
  {
    my($archive, $data) = @_;
    if($data->{done})
    {

lib/Archive/Libarchive/FFI/Callback.pm  view on Meta::CPAN

      warn "error: " . archive_error_string($archive);
    }
    $r;
  };
}

_attach_function archive_version_number() >= 3000000 ? 'archive_read_free' : [ archive_read_finish => 'archive_read_free' ], [ _ptr ], _int, sub
{
  my($cb, $archive) = @_;
  my $ret = $cb->($archive);
  delete $callbacks{$archive};
  $ret;
};

_attach_function archive_version_number() >= 3000000 ? 'archive_write_free' : [ archive_write_finish => 'archive_write_free' ], [ _ptr ], _int, sub
{
  my($cb, $archive) = @_;
  my $ret = $cb->($archive);
  delete $callbacks{$archive};
  $ret;
};

my %lookups;

use constant {
  CB_LOOKUP_USER  => 0,
  CB_LOOKUP_GROUP => 1,
};

lib/Archive/Libarchive/FFI/Callback.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Archive::Libarchive::FFI::Callback - Libarchive callbacks

=head1 VERSION

version 0.0902

=head1 SYNOPSIS

 use Archive::Libarchive::FFI qw( :all );
 
 # read

lib/Archive/Libarchive/FFI/Callback.pm  view on Meta::CPAN

 archive_read_open($archive, $data, \&myopen, \&myread, \&myclose);
 
 # write
 my $archive = archive_write_new();
 archive_write_open($archive, $data, \&myopen, \&mywrite, \&myclose);

=head1 DESCRIPTION

This document provides information of callback routines for writing
custom input/output interfaces to the libarchive perl bindings.  The
first two arguments passed into all callbacks are:

=over 4

=item $archive

The archive object (actually a pointer to the C structure that managed
the archive object).

=item $data

The callback data object (any legal Perl data structure).

=back

For the variable name / types conventions used in this document, see
L<Archive::Libarchive::FFI::Function>.

The expected return value for all callbacks EXCEPT the read callback
is a standard integer libarchive status value (example: C<ARCHIVE_OK>
or C<ARCHIVE_FATAL>).

If your callback dies (throws an exception), it will be caught at the
Perl level.  The error will be sent to standard error via L<warn|perlfunc#warn>
and C<ARCHIVE_FATAL> will be passed back to libarchive.

=head2 data

There is a data field for callbacks associated with each $archive object.
It can be any native Perl type (example: scalar, hashref, coderef, etc).
You can set this by calling
L<archive_read_set_callback_data|Archive::Libarchive::FFI::Function#archive_read_set_callback_data>,
or by passing the data argument when you "open" the archive using
L<archive_read_open|Archive::Libarchive::FFI::Function#archive_read_open>,
L<archive_read_open2|Archive::Libarchive::FFI::Function#archive_read_open2> or
L<archive_write_open|Archive::Libarchive::FFI::Function#archive_write_open>.

The data field will be passed into each callback as its second argument.

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN


Undocumented libarchive function.

=head2 archive_read_disk_set_gname_lookup

 my $status = archive_read_disk_set_gname_lookup($archive, $data, $lookup_callback, $cleanup_callback);

Register a callback for the lookup of GID from group names.  In order to deregister call
C<archive_read_disk_set_gname_lookup> with both callback functions set to C<undef>.

See L<Archive::Libarchive::FFI::Callback> for calling conventions for the lookup and cleanup callbacks.

=head2 archive_read_disk_set_standard_lookup

 my $status = archive_read_disk_set_standard_lookup($archive);

This convenience function installs a standard set of user and group name lookup functions.
These functions use C<getpwuid> and C<getgrgid> to convert ids to names, defaulting to C<undef>.
if the names cannot be looked up.  These functions also implement a simple memory cache to
reduce the number of calls to C<getpwuid> and C<getgrgid>.

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

This sets the mode used for handling symbolic links.  The "physical" mode does not
follow any symbolic links.

=head2 archive_read_disk_set_uname_lookup

 my $status = archive_read_disk_set_uname_lookup($archive, $data, $lookup_callback, $cleanup_callback);

Register a callback for the lookup of UID from user names.  In order to deregister call
C<archive_read_disk_setugname_lookup> with both callback functions set to C<undef>.

See L<Archive::Libarchive::FFI::Callback> for calling conventions for the lookup and cleanup callbacks.

=head2 archive_read_disk_uname

 my $string = archive_read_disk_uname($archive, $gid);

Returns a user name given a uid value.  By default always
returns C<undef>.

=head2 archive_read_extract

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

=head2 archive_read_open

 my $status = archive_read_open($archive, $data, $open_cb, $read_cb, $close_cb);

The same as C<archive_read_open2>, except that the skip callback is assumed to be C<undef>.

=head2 archive_read_open1

 my $status = archive_read_open1($archive);

Opening freezes the callbacks.

=head2 archive_read_open2

 my $status = archive_read_open2($archive, $data, $open_cb, $read_cb, $skip_cb, $close_cb);

Freeze the settings, open the archive, and prepare for reading entries.  This is the most
generic version of this call, which accepts four callback functions.  Most clients will
want to use C<archive_read_open_filename>, C<archive_read_open_FILE>, C<archive_read_open_fd>,
or C<archive_read_open_memory> instead.  The library invokes the client-provided functions to 
obtain raw bytes from the archive.

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

archive using C<archive_read_free>.

Bad things will happen if the buffer falls out of scope and is deallocated
before you free the archive, so make sure that there is a reference to the
buffer somewhere in your programmer until C<archive_read_free> is called.

=head2 archive_read_set_callback_data

 my $status = archive_read_set_callback_data($archive, $data);

Set the client data for callbacks.

=head2 archive_read_set_close_callback

 my $status = archive_read_set_close_callback($archive, $callback);

Set the close callback for the archive object.

=head2 archive_read_set_filter_option

 my $status = archive_read_set_filter_option($archive, $module, $option, $value);

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

 my $count_or_status = archive_seek_data($archive, $offset, $whence);

Seek within the body of an entry.  Similar to C<lseek>.

=head2 archive_set_error

 my $status = archive_set_error($archive, $errno, $format, @args);

Sets the numeric error code and error description that will be returned by
L<archive_errno|Archive::Libarchive::FFI::Function#archive_errno> and L<archive_error_string|Archive::Libarchive::FFI::Function#archive_error_string>.  This function should be
used within I/O callbacks to set system-specific error codes and error
descriptions.  This function accepts a printf-like format string and
arguments (via perl's L<sprintf|perlfunc#sprintf>.

=head2 archive_version_number

 my $version = archive_version_number();

Return the libarchive version as an integer.

=head2 archive_version_string

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

 my $status = archive_write_add_filter_none($archive);

Add none filter

=head2 archive_write_add_filter_program

 my $status = archive_write_add_filter_program($archive, $cmd);

The archive will be fed into the specified compression program. 
The output of that program is blocked and written to the client
write callbacks.

=head2 archive_write_add_filter_uuencode

 my $status = archive_write_add_filter_uuencode($archive);

Add uuencode filter

=head2 archive_write_add_filter_xz

 my $status = archive_write_add_filter_xz($archive);

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

(Depending on the implementation), either way, it can be passed into
any of the write functions documented here with an C<$archive> argument.

=head2 archive_write_disk_set_group_lookup

 my $status = archive_write_disk_set_group_lookup($archive, $data, $lookup_callback, $cleanup_callback);

Register a callback for the lookup of group names from group id numbers.  In order to deregister
call C<archive_write_disk_set_group_lookup> with both callback functions set to C<undef>.

See L<Archive::Libarchive::FFI::Callback> for calling conventions for the lookup and cleanup callbacks.

=head2 archive_write_disk_set_options

 my $status = archive_write_disk_set_options($archive, $flags);

The options field consists of a bitwise OR of one or more of the 
following values:

=over 4

lib/Archive/Libarchive/FFI/Function.pod  view on Meta::CPAN

a simple memory cache to reduce the number of calls to 
C<getpwnam> and C<getgrnam>.

=head2 archive_write_disk_set_user_lookup

 my $status = archive_write_disk_set_user_lookup($archive, $data, $lookup_callback, $cleanup_callback);

Register a callback for the lookup of user names from user id numbers.  In order to deregister
call C<archive_write_disk_set_user_lookup> with both callback functions set to C<undef>.

See L<Archive::Libarchive::FFI::Callback> for calling conventions for the lookup and cleanup callbacks.

=head2 archive_write_disk_uid

 my $int64 = archive_write_disk_uid($archive, $string, $int64);

Undocumented libarchive function.

=head2 archive_write_fail

 my $status = archive_write_fail($archive);

xt/author/pod_spelling_system.t  view on Meta::CPAN

Ollis
Mojolicious
plicease
CPAN
reinstall
TODO
filename
filenames
login
callback
callbacks
standalone
VMS
hostname
hostnames
TCP
UDP
IP
API
MSWin32
OpenBSD



( run in 0.560 second using v1.01-cache-2.11-cpan-9b1e4054eb1 )