File Coverage

blib/lib/Archive/Ar/Libarchive.pm
Criterion Covered Total %
statement 119 131 90.8
branch 31 46 67.3
condition 13 20 65.0
subroutine 26 28 92.8
pod 11 14 78.5
total 200 239 83.6


line stmt bran cond sub pod time code
1             package Archive::Ar::Libarchive;
2              
3 25     25   2596883 use strict;
  25         273  
  25         747  
4 25     25   136 use warnings;
  25         52  
  25         726  
5 25     25   134 use base qw( Exporter );
  25         106  
  25         3037  
6 25     25   164 use constant COMMON => 1;
  25         52  
  25         2178  
7 25     25   176 use constant BSD => 2;
  25         59  
  25         1297  
8 25     25   149 use constant GNU => 3;
  25         69  
  25         1297  
9 25     25   172 use Carp qw( carp longmess );
  25         46  
  25         1785  
10 25     25   176 use File::Basename ();
  25         56  
  25         22557  
11              
12             # ABSTRACT: Interface for manipulating ar archives with libarchive
13             our $VERSION = '2.08'; # VERSION
14              
15             require XSLoader;
16             XSLoader::load('Archive::Ar::Libarchive', $VERSION);
17              
18             our @EXPORT_OK = qw( COMMON BSD GNU );
19              
20              
21             sub new
22             {
23 42     42 1 93887 my($class, $filename_or_handle, $debug) = @_;
24 42         702 my $self = _new();
25 42 100       240 $self->DEBUG if $debug;
26              
27 42 100       183 if($filename_or_handle)
28             {
29 14 100       103 unless($self->read($filename_or_handle))
30             {
31 3         281 return $self->_error("new() failed on filename for filehandle read");
32             }
33             }
34              
35 39         366 $self;
36             }
37              
38              
39             sub read
40             {
41 25     25 1 106 my($self, $filename_or_handle) = @_;
42              
43 25         60 my $ret = 0;
44              
45 25 100       107 if(ref $filename_or_handle)
46             {
47 15 50 33     40 return $self->_error("Not a filehandle") unless eval{*$filename_or_handle{IO}} or $filename_or_handle->isa('IO::Handle');
  15         227  
48 15         39 my $buffer;
49             $ret = $self->_read_from_callback(sub {
50 30     30   186 my $br = read $filename_or_handle, $buffer, 1024;
51 30 50       751 ((defined $br ? 0 : -30), \$buffer);
52 15         477 });
53 15         121 close $filename_or_handle;
54             }
55             else
56             {
57 10         1105 $ret = $self->_read_from_filename($filename_or_handle);
58             }
59              
60 25 50       155 $ret || undef;
61             }
62              
63              
64             sub read_memory
65             {
66 14     14 1 1792 my($self, $data) = @_;
67              
68 14     13   785 open my $fh, '<', \$data;
  13         147  
  13         31  
  13         140  
69 14         11190 binmode $fh;
70 14         82 my $ret = $self->read($fh);
71              
72 14         117 $ret;
73             }
74              
75              
76             sub chmod
77             {
78 1     1 1 52 my($self, $filename, $mode) = @_;
79 1 50       46 $self->_chmod($filename, $mode + 0 eq $mode ? $mode : oct($mode));
80             }
81              
82              
83             sub chown
84             {
85 2     2 1 27 my($self, $filename, $uid, $gid) = @_;
86 2         40 $self->_chown($filename, $uid, $gid);
87             }
88              
89              
90             sub remove
91             {
92 2     2 1 1054 my $self = shift;
93 2         5 my $count = 0;
94 2 100       2 foreach my $pathname (@{ ref $_[0] ? $_[0] : \@_ })
  2         42  
95             {
96 4         38 $count += $self->_remove($pathname);
97             }
98 2         7 $count;
99             }
100              
101              
102             sub list_files
103             {
104 22     22 1 10784 my $list = shift->_list_files;
105 22 100       153 wantarray ? @$list : $list; ## no critic (Freenode::Wantarray)
106             }
107              
108              
109             sub add_files
110             {
111 2     2 1 66 my $self = shift;
112 2         4 my $count = 0;
113 2 50       6 foreach my $filename (@{ ref $_[0] ? $_[0] : \@_ })
  2         11  
114             {
115 6 50       116 unless(-r $filename)
116             {
117 0         0 $self->_error("No such file: $filename");
118 0         0 next;
119             }
120 6         78 my @props = stat($filename);
121 6 50       21 unless(@props)
122             {
123 0         0 $self->_error("Could not stat $filename.");
124 0         0 next;
125             }
126              
127 6 50       210 open(my $fh, '<', $filename) || do {
128 0         0 $self->_error("Unable to open $filename $!");
129 0         0 next;
130             };
131 6         25 binmode $fh;
132             # TODO: we don't check for error on the actual
133             # read operation (but then nethier does
134             # Archive::Ar).
135 6         11 my $data = do { local $/; <$fh> };
  6         29  
  6         181  
136 6         114 close $fh;
137              
138 6         259 $self->add_data(File::Basename::basename($filename), $data, {
139             date => $props[9],
140             uid => $props[4],
141             gid => $props[5],
142             mode => $props[2],
143             size => length $data,
144             });
145 6         32 $count++;
146             }
147              
148 2 50       8 return unless $count;
149 2         7 $count;
150             }
151              
152              
153             sub add_data
154             {
155 22     22 1 150 my($self, $filename, $data, $filedata) = @_;
156 22   100     82 $filedata ||= {};
157 22   100     433 $self->_add_data($filename, $data, $filedata->{uid} || 0, $filedata->{gid} || 0, $filedata->{date} || time, $filedata->{mode} || oct(100644));
      100        
      66        
      100        
158 25     25   16202 use bytes;
  25         382  
  25         141  
159 22         81 length $data;
160             }
161              
162              
163             sub write
164             {
165 12     12 1 504 my($self, $filename) = @_;
166 12 100       41 if(defined $filename)
167             {
168 4         9 my $fh;
169              
170 4 100       13 if(ref $filename)
171             {
172 1 50 33     2 return $self->_error("Not a filehandle") unless eval{*$filename{IO}} or $filename->isa('IO::Handle');
  1         19  
173 1         3 $fh = $filename;
174              
175             return $self->_write_to_callback(sub {
176 1     1   5 my($archive, $buffer) = @_;
177 1         22 print $fh $buffer;
178 1         14 length $buffer;
179 1         48 });
180             }
181              
182 3         441 return $self->_write_to_filename($filename);
183             }
184             else
185             {
186 8         20 my $content = '';
187             my $status = $self->_write_to_callback(sub {
188 8     8   39 my($archive, $buffer) = @_;
189 8         27 $content .= $buffer;
190 8         49 length $buffer;
191 8         336 });
192 8 50       58 return unless $status;
193 8         70 return $content;
194             }
195             }
196              
197              
198             sub get_handle
199             {
200 3     3 1 5771 my $data = shift->get_data(@_);
201 3 50       12 return unless defined $data;
202 3         54 open my $fh, '<', \$data;
203 3         887 $fh;
204             }
205              
206              
207             sub set_output_format_bsd
208             {
209 0     0 0 0 carp "set_output_format_bsd is deprecated, use \$ar->set_opt(type => BSD) instead";
210 0         0 shift->set_opt(type => BSD);
211             }
212              
213             sub set_output_format_svr4
214             {
215 0     0 0 0 carp "set_output_format_bsd is deprecated, use \$ar->set_opt(type => COMMON) instead";
216 0         0 shift->set_opt(type => COMMON);
217             }
218              
219             sub DEBUG
220             {
221 2     2 0 957 carp "DEBUG is deprecated, use \$ar->set_opt(\"warn\", 1) instead";
222 2         89 my($self, $value) = @_;
223 2 50 33     20 $self->set_opt(warn => 1) unless defined $value and $value == 0;
224             }
225              
226             sub _error
227             {
228 4     4   544 my($self, $message) = @_;
229 4         21 my $opt_warn = $self->get_opt('warn');
230 4         426 my $longmess = longmess $message;
231 4         414 $self->_set_error($message, $longmess);
232 4 50       18 if($opt_warn > 1)
    50          
233             {
234 0         0 carp $longmess;
235             }
236             elsif($opt_warn)
237             {
238 0         0 carp $message;
239             }
240 4         28 return;
241             }
242              
243             1;
244              
245             __END__