File Coverage

lib/Archive/Tar.pm
Criterion Covered Total %
statement 502 645 77.8
branch 251 430 58.3
condition 112 188 59.5
subroutine 48 55 87.2
pod 29 30 96.6
total 942 1348 69.8


line stmt bran cond sub pod time code
1             ### the gnu tar specification:
2             ### https://www.gnu.org/software/tar/manual/tar.html
3             ###
4             ### and the pax format spec, which tar derives from:
5             ### https://www.opengroup.org/onlinepubs/007904975/utilities/pax.html
6              
7             package Archive::Tar;
8             require 5.005_03;
9              
10 17     17   2209593 use Cwd;
  17         39  
  17         1429  
11 17     17   10080 use IO::Zlib;
  17         1316824  
  17         147  
12 17     17   1116 use IO::File;
  17         35  
  17         2806  
13 17     17   119 use Carp qw(carp croak);
  17         40  
  17         1109  
14 17     17   166 use File::Spec ();
  17         46  
  17         429  
15 17     17   91 use File::Spec::Unix ();
  17         32  
  17         306  
16 17     17   78 use File::Path ();
  17         60  
  17         465  
17              
18 17     17   10559 use Archive::Tar::File;
  17         62  
  17         717  
19 17     17   120 use Archive::Tar::Constant;
  17         30  
  17         4100  
20              
21             require Exporter;
22              
23 17     17   159 use strict;
  17         42  
  17         1224  
24 17         4478 use vars qw[$DEBUG $error $VERSION $WARN $FOLLOW_SYMLINK $CHOWN $CHMOD
25             $DO_NOT_USE_PREFIX $HAS_PERLIO $HAS_IO_STRING $SAME_PERMISSIONS
26             $INSECURE_EXTRACT_MODE $ZERO_PAD_NUMBERS @ISA @EXPORT $RESOLVE_SYMLINK
27             $EXTRACT_BLOCK_SIZE $EXTRACT_HARDLINK
28 17     17   105 ];
  17         30  
29              
30             @ISA = qw[Exporter];
31             @EXPORT = qw[ COMPRESS_GZIP COMPRESS_BZIP COMPRESS_XZ ];
32             $DEBUG = 0;
33             $WARN = 1;
34             $FOLLOW_SYMLINK = 0;
35             $VERSION = "3.06";
36             $CHOWN = 1;
37             $CHMOD = 1;
38             $SAME_PERMISSIONS = $> == 0 ? 1 : 0;
39             $DO_NOT_USE_PREFIX = 0;
40             $INSECURE_EXTRACT_MODE = 0;
41             $ZERO_PAD_NUMBERS = 0;
42             $RESOLVE_SYMLINK = $ENV{'PERL5_AT_RESOLVE_SYMLINK'} || 'speed';
43             $EXTRACT_BLOCK_SIZE = 1024 * 1024 * 1024;
44             $EXTRACT_HARDLINK = 0;
45              
46             BEGIN {
47 17     17   124 use Config;
  17         29  
  17         1739  
48 17     17   1736 $HAS_PERLIO = $Config::Config{useperlio};
49              
50             ### try and load IO::String anyway, so you can dynamically
51             ### switch between perlio and IO::String
52 17   50     89 $HAS_IO_STRING = eval {
53             require IO::String;
54             IO::String->import;
55             1;
56             } || 0;
57             }
58              
59             =head1 NAME
60              
61             Archive::Tar - module for manipulations of tar archives
62              
63             =head1 SYNOPSIS
64              
65             use Archive::Tar;
66             my $tar = Archive::Tar->new;
67              
68             $tar->read('origin.tgz');
69             $tar->extract();
70              
71             $tar->add_files('file/foo.pl', 'docs/README');
72             $tar->add_data('file/baz.txt', 'This is the contents now');
73              
74             $tar->rename('oldname', 'new/file/name');
75             $tar->chown('/', 'root');
76             $tar->chown('/', 'root:root');
77             $tar->chmod('/tmp', '1777');
78              
79             $tar->write('files.tar'); # plain tar
80             $tar->write('files.tgz', COMPRESS_GZIP); # gzip compressed
81             $tar->write('files.tbz', COMPRESS_BZIP); # bzip2 compressed
82             $tar->write('files.txz', COMPRESS_XZ); # xz compressed
83              
84             =head1 DESCRIPTION
85              
86             Archive::Tar provides an object oriented mechanism for handling tar
87             files. It provides class methods for quick and easy files handling
88             while also allowing for the creation of tar file objects for custom
89             manipulation. If you have the IO::Zlib module installed,
90             Archive::Tar will also support compressed or gzipped tar files.
91              
92             An object of class Archive::Tar represents a .tar(.gz) archive full
93             of files and things.
94              
95             =head1 Object Methods
96              
97             =head2 Archive::Tar->new( [$file, $compressed] )
98              
99             Returns a new Tar object. If given any arguments, C calls the
100             C method automatically, passing on the arguments provided to
101             the C method.
102              
103             If C is invoked with arguments and the C method fails
104             for any reason, C returns undef.
105              
106             =cut
107              
108             my $tmpl = {
109             _data => [ ],
110             _file => 'Unknown',
111             };
112              
113             ### install get/set accessors for this object.
114             for my $key ( keys %$tmpl ) {
115 17     17   203 no strict 'refs';
  17         58  
  17         174105  
116             *{__PACKAGE__."::$key"} = sub {
117 719     719   1397 my $self = shift;
118 719 100       5185 $self->{$key} = $_[0] if @_;
119 719         3362 return $self->{$key};
120             }
121             }
122              
123             sub new {
124 77     77 1 640762 my $class = shift;
125 77 50       341 $class = ref $class if ref $class;
126              
127             ### copying $tmpl here since a shallow copy makes it use the
128             ### same aref, causing for files to remain in memory always.
129 77         516 my $obj = bless { _data => [ ], _file => 'Unknown', _error => '' }, $class;
130              
131 77 100       400 if (@_) {
132 14 50       48 unless ( $obj->read( @_ ) ) {
133 0         0 $obj->_error(qq[No data could be read from file]);
134 0         0 return;
135             }
136             }
137              
138 77         1747 return $obj;
139             }
140              
141             =head2 $tar->read ( $filename|$handle, [$compressed, {opt => 'val'}] )
142              
143             Read the given tar file into memory.
144             The first argument can either be the name of a file or a reference to
145             an already open filehandle (or an IO::Zlib object if it's compressed)
146              
147             The C will I any previous content in C<$tar>!
148              
149             The second argument may be considered optional, but remains for
150             backwards compatibility. Archive::Tar now looks at the file
151             magic to determine what class should be used to open the file
152             and will transparently Do The Right Thing.
153              
154             Archive::Tar will warn if you try to pass a bzip2 / xz compressed file and the
155             IO::Uncompress::Bunzip2 / IO::Uncompress::UnXz are not available and simply return.
156              
157             Note that you can currently B pass a C compressed
158             filehandle, which is not opened with C, a C compressed
159             filehandle, which is not opened with C, a C compressed
160             filehandle, which is not opened with C, nor a string
161             containing the full archive information (either compressed or
162             uncompressed). These are worth while features, but not currently
163             implemented. See the C section.
164              
165             The third argument can be a hash reference with options. Note that
166             all options are case-sensitive.
167              
168             =over 4
169              
170             =item limit
171              
172             Do not read more than C files. This is useful if you have
173             very big archives, and are only interested in the first few files.
174              
175             =item filter
176              
177             Can be set to a regular expression. Only files with names that match
178             the expression will be read.
179              
180             =item md5
181              
182             Set to 1 and the md5sum of files will be returned (instead of file data)
183             my $iter = Archive::Tar->iter( $file, 1, {md5 => 1} );
184             while( my $f = $iter->() ) {
185             print $f->data . "\t" . $f->full_path . $/;
186             }
187              
188             =item extract
189              
190             If set to true, immediately extract entries when reading them. This
191             gives you the same memory break as the C function.
192             Note however that entries will not be read into memory, but written
193             straight to disk. This means no C objects are
194             created for you to inspect.
195              
196             =back
197              
198             All files are stored internally as C objects.
199             Please consult the L documentation for details.
200              
201             Returns the number of files read in scalar context, and a list of
202             C objects in list context.
203              
204             =cut
205              
206             sub read {
207 50     50 1 7182 my $self = shift;
208 50         146 my $file = shift;
209 50   100     276 my $gzip = shift || 0;
210 50   100     306 my $opts = shift || {};
211              
212 50 100       194 unless( defined $file ) {
213 2         12 $self->_error( qq[No file to read from!] );
214 2         10 return;
215             } else {
216 48         222 $self->_file( $file );
217             }
218              
219 48 50       387 my $handle = $self->_get_handle($file, $gzip, READ_ONLY->( ZLIB ) )
220             or return;
221              
222 48 100       239 my $data = $self->_read_tar( $handle, $opts ) or return;
223              
224 46         269 $self->_data( $data );
225              
226 46 100       602 return wantarray ? @$data : scalar @$data;
227             }
228              
229             sub _get_handle {
230 93     93   177 my $self = shift;
231 93 50       173 my $file = shift; return unless defined $file;
  93         305  
232 93   100     3488 my $compress = shift || 0;
233 93   33     259 my $mode = shift || READ_ONLY->( ZLIB ); # default to read only
234              
235             ### Check if file is a file handle or IO glob
236 93 50       269 if ( ref $file ) {
237 0 0       0 return $file if eval{ *$file{IO} };
  0         0  
238 0 0       0 return $file if eval{ $file->isa(q{IO::Handle}) };
  0         0  
239 0         0 $file = q{}.$file;
240             }
241              
242             ### get a FH opened to the right class, so we can use it transparently
243             ### throughout the program
244 93         153 my $fh;
245             { ### reading magic only makes sense if we're opening a file for
246             ### reading. otherwise, just use what the user requested.
247 93         195 my $magic = '';
  93         272  
248 93 100       420 if( MODE_READ->($mode) ) {
249 63 50       4240 open my $tmp, $file or do {
250 0         0 $self->_error( qq[Could not open '$file' for reading: $!] );
251 0         0 return;
252             };
253              
254             ### read the first 6 bytes of the file to figure out which class to
255             ### use to open the file.
256 63         981 sysread( $tmp, $magic, 6 );
257 63         883 close $tmp;
258             }
259              
260             ### is it xz?
261             ### if you asked specifically for xz compression, or if we're in
262             ### read mode and the magic numbers add up, use xz
263 93 100 100     851 if( XZ and (
    100 66        
264             ($compress eq COMPRESS_XZ) or
265             ( MODE_READ->($mode) and $magic =~ XZ_MAGIC_NUM )
266             )
267             ) {
268             if( MODE_READ->($mode) ) {
269             $fh = IO::Uncompress::UnXz->new( $file ) or do {
270             $self->_error( qq[Could not read '$file': ] .
271             $IO::Uncompress::UnXz::UnXzError
272             );
273             return;
274             };
275             } else {
276             $fh = IO::Compress::Xz->new( $file ) or do {
277             $self->_error( qq[Could not write to '$file': ] .
278             $IO::Compress::Xz::XzError
279             );
280             return;
281             };
282             }
283              
284             ### is it bzip?
285             ### if you asked specifically for bzip compression, or if we're in
286             ### read mode and the magic numbers add up, use bzip
287 0 100 100     0 } elsif( BZIP and (
288             ($compress eq COMPRESS_BZIP) or
289             ( MODE_READ->($mode) and $magic =~ BZIP_MAGIC_NUM )
290             )
291             ) {
292              
293             ### different reader/writer modules, different error vars... sigh
294 17 100       53 if( MODE_READ->($mode) ) {
295 10 50       137 $fh = IO::Uncompress::Bunzip2->new( $file, MultiStream => 1 ) or do {
296 0         0 $self->_error( qq[Could not read '$file': ] .
297             $IO::Uncompress::Bunzip2::Bunzip2Error
298             );
299 0         0 return;
300             };
301              
302             } else {
303 7 50       224 $fh = IO::Compress::Bzip2->new( $file ) or do {
304 0         0 $self->_error( qq[Could not write to '$file': ] .
305             $IO::Compress::Bzip2::Bzip2Error
306             );
307 0         0 return;
308             };
309             }
310              
311             ### is it gzip?
312             ### if you asked for compression, if you wanted to read or the gzip
313             ### magic number is present (redundant with read)
314             } elsif( ZLIB and (
315             $compress or MODE_READ->($mode) or $magic =~ GZIP_MAGIC_NUM
316             )
317             ) {
318 61         739 $fh = IO::Zlib->new;
319              
320 61 50       6670 unless( $fh->open( $file, $mode ) ) {
321 0         0 $self->_error(qq[Could not create filehandle for '$file': $!]);
322 0         0 return;
323             }
324              
325             ### is it plain tar?
326             } else {
327 15         131 $fh = IO::File->new;
328              
329 15 50       696 unless( $fh->open( $file, $mode ) ) {
330 0         0 $self->_error(qq[Could not create filehandle for '$file': $!]);
331 0         0 return;
332             }
333              
334             ### enable bin mode on tar archives
335 15         3128 binmode $fh;
336             }
337             }
338              
339 93         172238 return $fh;
340             }
341              
342              
343             sub _read_tar {
344 81     81   198 my $self = shift;
345 81 50       220 my $handle = shift or return;
346 81   50     275 my $opts = shift || {};
347              
348 81   100     469 my $count = $opts->{limit} || 0;
349 81         208 my $filter = $opts->{filter};
350 81   50     330 my $md5 = $opts->{md5} || 0; # cdrake
351 81         149 my $filter_cb = $opts->{filter_cb};
352 81   100     333 my $extract = $opts->{extract} || 0;
353              
354             ### set a cap on the amount of files to extract ###
355 81         146 my $limit = 0;
356 81 100       216 $limit = 1 if $count > 0;
357              
358 81         157 my $tarfile = [ ];
359 81         148 my $chunk;
360 81         151 my $read = 0;
361 81         164 my $real_name; # to set the name of a file when
362             # we're encountering @longlink
363             my $data;
364              
365             LOOP:
366 81         711 while( $handle->read( $chunk, HEAD ) ) {
367             ### IO::Zlib doesn't support this yet
368 616         123071 my $offset;
369 616 100       1448 if ( ref($handle) ne 'IO::Zlib' ) {
370 81         123 local $@;
371 81   50     106 $offset = eval { tell $handle } || 'unknown';
372 81         931 $@ = '';
373             }
374             else {
375 535         862 $offset = 'unknown';
376             }
377              
378 616 100       1323 unless( $read++ ) {
379 77         161 my $gzip = GZIP_MAGIC_NUM;
380 77 50       854 if( $chunk =~ /$gzip/ ) {
381 0         0 $self->_error( qq[Cannot read compressed format in tar-mode] );
382 0         0 return;
383             }
384              
385             ### size is < HEAD, which means a corrupted file, as the minimum
386             ### length is _at least_ HEAD
387 77 100       265 if (length $chunk != HEAD) {
388 2         10 $self->_error( qq[Cannot read enough bytes from the tarfile] );
389 2         26 return;
390             }
391             }
392              
393             ### if we can't read in all bytes... ###
394 614 100       1255 last if length $chunk != HEAD;
395              
396             ### Apparently this should really be two blocks of 512 zeroes,
397             ### but GNU tar sometimes gets it wrong. See comment in the
398             ### source code (tar.c) to GNU cpio.
399 612 100       1451 next if $chunk eq TAR_END;
400              
401             ### according to the posix spec, the last 12 bytes of the header are
402             ### null bytes, to pad it to a 512 byte block. That means if these
403             ### bytes are NOT null bytes, it's a corrupt header. See:
404             ### www.koders.com/c/fidCE473AD3D9F835D690259D60AD5654591D91D5BA.aspx
405             ### line 111
406 242         382 { my $nulls = join '', "\0" x 12;
  242         368  
407 242 50       648 unless( $nulls eq substr( $chunk, 500, 12 ) ) {
408 0         0 $self->_error( qq[Invalid header block at offset $offset] );
409 0         0 next LOOP;
410             }
411             }
412              
413             ### pass the realname, so we can set it 'proper' right away
414             ### some of the heuristics are done on the name, so important
415             ### to set it ASAP
416 242         349 my $entry;
417 242         284 { my %extra_args = ();
  242         428  
418 242 100       580 $extra_args{'name'} = $$real_name if defined $real_name;
419              
420 242 50       1407 unless( $entry = Archive::Tar::File->new( chunk => $chunk,
421             %extra_args )
422             ) {
423 0         0 $self->_error( qq[Couldn't read chunk at offset $offset] );
424 0         0 next LOOP;
425             }
426             }
427              
428             ### ignore labels:
429             ### https://www.gnu.org/software/tar/manual/html_chapter/Media.html#SEC159
430 242 50       755 next if $entry->is_label;
431              
432 242 100 66     561 if( length $entry->type and ($entry->is_file || $entry->is_longlink) ) {
      33        
433              
434 184 50 33     345 if ( $entry->is_file && !$entry->validate ) {
435             ### sometimes the chunk is rather fux0r3d and a whole 512
436             ### bytes ends up in the ->name area.
437             ### clean it up, if need be
438 0         0 my $name = $entry->name;
439 0 0       0 $name = substr($name, 0, 100) if length $name > 100;
440 0         0 $name =~ s/\n/ /g;
441              
442 0         0 $self->_error( $name . qq[: checksum error] );
443 0         0 next LOOP;
444             }
445              
446 184         550 my $block = BLOCK_SIZE->( $entry->size );
447              
448 184         435 $data = $entry->get_content_by_ref;
449              
450 184         268 my $skip = 0;
451 184         283 my $ctx; # cdrake
452             ### skip this entry if we're filtering
453              
454 184 50 100     965 if($md5) { # cdrake
    100 100        
    100 33        
    50          
455 0         0 $ctx = Digest::MD5->new; # cdrake
456 0         0 $skip=5; # cdrake
457              
458             } elsif ($filter && $entry->name !~ $filter) {
459 22         43 $skip = 1;
460              
461             } elsif ($filter_cb && ! $filter_cb->($entry)) {
462 22         38 $skip = 2;
463              
464             ### skip this entry if it's a pax header. This is a special file added
465             ### by, among others, git-generated tarballs. It holds comments and is
466             ### not meant for extracting. See #38932: pax_global_header extracted
467             } elsif ( $entry->name eq PAX_HEADER or $entry->type =~ /^(x|g)$/ ) {
468 0         0 $skip = 3;
469             }
470              
471 184 100       392 if ($skip) {
472             #
473             # Since we're skipping, do not allocate memory for the
474             # whole file. Read it 64 BLOCKS at a time. Do not
475             # complete the skip yet because maybe what we read is a
476             # longlink and it won't get skipped after all
477             #
478 44         62 my $amt = $block;
479 44         95 my $fsz=$entry->size; # cdrake
480 44         112 while ($amt > 0) {
481 44         77 $$data = '';
482 44         72 my $this = 64 * BLOCK;
483 44 50       91 $this = $amt if $this > $amt;
484 44 50       308 if( $handle->read( $$data, $this ) < $this ) {
485 0         0 $self->_error( qq[Read error on tarfile (missing data) '].
486             $entry->full_path ."' at offset $offset" );
487 0         0 next LOOP;
488             }
489 44         7974 $amt -= $this;
490 44         76 $fsz -= $this; # cdrake
491 44 50       131 substr ($$data, $fsz) = "" if ($fsz<0); # remove external junk prior to md5 # cdrake
492 44 50       139 $ctx->add($$data) if($skip==5); # cdrake
493             }
494 44 0 33     123 $$data = $ctx->hexdigest if($skip==5 && !$entry->is_longlink && !$entry->is_unknown && !$entry->is_label ) ; # cdrake
      33        
      0        
495             } else {
496              
497             ### just read everything into memory
498             ### can't do lazy loading since IO::Zlib doesn't support 'seek'
499             ### this is because Compress::Zlib doesn't support it =/
500             ### this reads in the whole data in one read() call.
501 140 50       789 if ( $handle->read( $$data, $block ) < $block ) {
502 0         0 $self->_error( qq[Read error on tarfile (missing data) '].
503             $entry->full_path ."' at offset $offset" );
504 0         0 next LOOP;
505             }
506             ### throw away trailing garbage ###
507 140 50       24505 substr ($$data, $entry->size) = "" if defined $$data;
508             }
509              
510             ### part II of the @LongLink munging -- need to do /after/
511             ### the checksum check.
512 184 100       549 if( $entry->is_longlink ) {
513             ### weird thing in tarfiles -- if the file is actually a
514             ### @LongLink, the data part seems to have a trailing ^@
515             ### (unprintable) char. to display, pipe output through less.
516             ### but that doesn't *always* happen.. so check if the last
517             ### character is a control character, and if so remove it
518             ### at any rate, we better remove that character here, or tests
519             ### like 'eq' and hash lookups based on names will SO not work
520             ### remove it by calculating the proper size, and then
521             ### tossing out everything that's longer than that size.
522              
523             ### count number of nulls
524 51         163 my $nulls = $$data =~ tr/\0/\0/;
525              
526             ### cut data + size by that many bytes
527 51         118 $entry->size( $entry->size - $nulls );
528 51         116 substr ($$data, $entry->size) = "";
529             }
530             }
531              
532             ### clean up of the entries.. posix tar /apparently/ has some
533             ### weird 'feature' that allows for filenames > 255 characters
534             ### they'll put a header in with as name '././@LongLink' and the
535             ### contents will be the name of the /next/ file in the archive
536             ### pretty crappy and kludgy if you ask me
537              
538             ### set the name for the next entry if this is a @LongLink;
539             ### this is one ugly hack =/ but needed for direct extraction
540 242 100       593 if( $entry->is_longlink ) {
    100          
541 51         94 $real_name = $data;
542 51         358 next LOOP;
543             } elsif ( defined $real_name ) {
544 51         150 $entry->name( $$real_name );
545 51         135 $entry->prefix('');
546 51         96 undef $real_name;
547             }
548              
549 191 100 100     900 if ($filter && $entry->name !~ $filter) {
    100 100        
    50 33        
550 20         147 next LOOP;
551              
552             } elsif ($filter_cb && ! $filter_cb->($entry)) {
553 20         160 next LOOP;
554              
555             ### skip this entry if it's a pax header. This is a special file added
556             ### by, among others, git-generated tarballs. It holds comments and is
557             ### not meant for extracting. See #38932: pax_global_header extracted
558             } elsif ( $entry->name eq PAX_HEADER or $entry->type =~ /^(x|g)$/ ) {
559 0         0 next LOOP;
560             }
561              
562 151 50 66     500 if ( $extract && !$entry->is_longlink
      66        
      33        
563             && !$entry->is_unknown
564             && !$entry->is_label ) {
565 9 50       50 $self->_extract_file( $entry ) or return;
566             }
567              
568             ### Guard against tarfiles with garbage at the end
569 151 50       380 last LOOP if $entry->name eq '';
570              
571             ### push only the name on the rv if we're extracting
572             ### -- for extract_archive
573 151 100       413 push @$tarfile, ($extract ? $entry->name : $entry);
574              
575 151 100       2782 if( $limit ) {
576 21 100 66     67 $count-- unless $entry->is_longlink || $entry->is_dir;
577 21 100       118 last LOOP unless $count;
578             }
579             } continue {
580 597         6483 undef $data;
581             }
582              
583 79         23369 return $tarfile;
584             }
585              
586             =head2 $tar->contains_file( $filename )
587              
588             Check if the archive contains a certain file.
589             It will return true if the file is in the archive, false otherwise.
590              
591             Note however, that this function does an exact match using C
592             on the full path. So it cannot compensate for case-insensitive file-
593             systems or compare 2 paths to see if they would point to the same
594             underlying file.
595              
596             =cut
597              
598             sub contains_file {
599 2     2 1 5 my $self = shift;
600 2         7 my $full = shift;
601              
602 2 50       8 return unless defined $full;
603              
604             ### don't warn if the entry isn't there.. that's what this function
605             ### is for after all.
606 2         3 local $WARN = 0;
607 2 100       10 return 1 if $self->_find_entry($full);
608 1         3 return;
609             }
610              
611             =head2 $tar->extract( [@filenames] )
612              
613             Write files whose names are equivalent to any of the names in
614             C<@filenames> to disk, creating subdirectories as necessary. This
615             might not work too well under VMS.
616             Under MacPerl, the file's modification time will be converted to the
617             MacOS zero of time, and appropriate conversions will be done to the
618             path. However, the length of each element of the path is not
619             inspected to see whether it's longer than MacOS currently allows (32
620             characters).
621              
622             If C is called without a list of file names, the entire
623             contents of the archive are extracted.
624              
625             Returns a list of filenames extracted.
626              
627             =cut
628              
629             sub extract {
630 32     32 1 23175 my $self = shift;
631 32         133 my @args = @_;
632 32         67 my @files;
633             my $hashmap;
634              
635             # use the speed optimization for all extracted files
636 32 50       213116 local($self->{cwd}) = cwd() unless $self->{cwd};
637              
638             ### you requested the extraction of only certain files
639 32 100       704 if( @args ) {
640 2         56 for my $file ( @args ) {
641              
642             ### it's already an object?
643 2 100       69 if( UNIVERSAL::isa( $file, 'Archive::Tar::File' ) ) {
644 1         18 push @files, $file;
645 1         12 next;
646              
647             ### go find it then
648             } else {
649              
650             # create hash-map once to speed up lookup
651             $hashmap = $hashmap || {
652 1   50     40 map { $_->full_path, $_ } @{$self->_data}
653             };
654              
655 1 50       20 if (exists $hashmap->{$file}) {
656             ### we found the file you're looking for
657 1         38 push @files, $hashmap->{$file};
658             } else {
659 0         0 return $self->_error(
660             qq[Could not find '$file' in archive] );
661             }
662             }
663             }
664              
665             ### just grab all the file items
666             } else {
667 30         696 @files = $self->get_files;
668             }
669              
670             ### nothing found? that's an error
671 32 50       180 unless( scalar @files ) {
672 0         0 $self->_error( qq[No files found for ] . $self->_file );
673 0         0 return;
674             }
675              
676             ### now extract them
677 32         238 for my $entry ( @files ) {
678 111 100       532 unless( $self->_extract_file( $entry ) ) {
679 3         14 $self->_error(q[Could not extract ']. $entry->full_path .q['] );
680 3         14 return;
681             }
682             }
683              
684 29         836 return @files;
685             }
686              
687             =head2 $tar->extract_file( $file, [$extract_path] )
688              
689             Write an entry, whose name is equivalent to the file name provided to
690             disk. Optionally takes a second parameter, which is the full native
691             path (including filename) the entry will be written to.
692              
693             For example:
694              
695             $tar->extract_file( 'name/in/archive', 'name/i/want/to/give/it' );
696              
697             $tar->extract_file( $at_file_object, 'name/i/want/to/give/it' );
698              
699             Returns true on success, false on failure.
700              
701             =cut
702              
703             sub extract_file {
704 165     165 1 1819 my $self = shift;
705 165 50       510 my $file = shift; return unless defined $file;
  165         572  
706 165         270 my $alt = shift;
707              
708 165 50       1429 my $entry = $self->_find_entry( $file )
709             or $self->_error( qq[Could not find an entry for '$file'] ), return;
710              
711 165         967 return $self->_extract_file( $entry, $alt );
712             }
713              
714             sub _extract_file {
715 288     288   574 my $self = shift;
716 288 50       1047 my $entry = shift or return;
717 288         616 my $alt = shift;
718              
719             ### you wanted an alternate extraction location ###
720 288 100       2078 my $name = defined $alt ? $alt : $entry->full_path;
721              
722             ### splitpath takes a bool at the end to indicate
723             ### that it's splitting a dir
724 288         677 my ($vol,$dirs,$file);
725 288 100       738 if ( defined $alt ) { # It's a local-OS path
726 161         691 ($vol,$dirs,$file) = File::Spec->splitpath( $alt,
727             $entry->is_dir );
728             } else {
729 127         717 ($vol,$dirs,$file) = File::Spec::Unix->splitpath( $name,
730             $entry->is_dir );
731             }
732              
733 288         872 my $dir;
734             ### is $name an absolute path? ###
735 288 100 66     5328 if( $vol || File::Spec->file_name_is_absolute( $dirs ) ) {
736              
737             ### absolute names are not allowed to be in tarballs under
738             ### strict mode, so only allow it if a user tells us to do it
739 80 0 33     306 if( not defined $alt and not $INSECURE_EXTRACT_MODE ) {
740 0         0 $self->_error(
741             q[Entry ']. $entry->full_path .q[' is an absolute path. ].
742             q[Not extracting absolute paths under SECURE EXTRACT MODE]
743             );
744 0         0 return;
745             }
746              
747             ### user asked us to, it's fine.
748 80         866 $dir = File::Spec->catpath( $vol, $dirs, "" );
749              
750             ### it's a relative path ###
751             } else {
752             my $cwd = (ref $self and defined $self->{cwd})
753             ? $self->{cwd}
754 208 100 100     653599 : cwd();
755              
756 208 100       4686 my @dirs = defined $alt
757             ? File::Spec->splitdir( $dirs ) # It's a local-OS path
758             : File::Spec::Unix->splitdir( $dirs ); # it's UNIX-style, likely
759             # straight from the tarball
760              
761 208 100 100     1430 if( not defined $alt and
762             not $INSECURE_EXTRACT_MODE
763             ) {
764              
765             ### paths that leave the current directory are not allowed under
766             ### strict mode, so only allow it if a user tells us to do this.
767 121 100       408 if( grep { $_ eq '..' } @dirs ) {
  124         345  
768              
769 1         26 $self->_error(
770             q[Entry ']. $entry->full_path .q[' is attempting to leave ].
771             q[the current working directory. Not extracting under ].
772             q[SECURE EXTRACT MODE]
773             );
774 1         27 return;
775             }
776              
777             ### the archive may be asking us to extract into a symlink. This
778             ### is not sane and a possible security issue, as outlined here:
779             ### https://rt.cpan.org/Ticket/Display.html?id=30380
780             ### https://bugzilla.redhat.com/show_bug.cgi?id=295021
781             ### https://issues.rpath.com/browse/RPL-1716
782 120         355 my $full_path = $cwd;
783 120         426 for my $d ( @dirs ) {
784 120         879 $full_path = File::Spec->catdir( $full_path, $d );
785              
786             ### we've already checked this one, and it's safe. Move on.
787 120 100 100     792 next if ref $self and $self->{_link_cache}->{$full_path};
788              
789 26 100       873 if( -l $full_path ) {
790 2         81 my $to = readlink $full_path;
791 2         6 my $diag = "symlinked directory ($full_path => $to)";
792              
793 2         8 $self->_error(
794             q[Entry ']. $entry->full_path .q[' is attempting to ].
795             qq[extract to a $diag. This is considered a security ].
796             q[vulnerability and not allowed under SECURE EXTRACT ].
797             q[MODE]
798             );
799 2         12 return;
800             }
801              
802             ### XXX keep a cache if possible, so the stats become cheaper:
803 24 100       168 $self->{_link_cache}->{$full_path} = 1 if ref $self;
804             }
805             }
806              
807             ### '.' is the directory delimiter on VMS, which has to be escaped
808             ### or changed to '_' on vms. vmsify is used, because older versions
809             ### of vmspath do not handle this properly.
810             ### Must not add a '/' to an empty directory though.
811 205         343 map { length() ? VMS::Filespec::vmsify($_.'/') : $_ } @dirs if ON_VMS;
812              
813 205         7513 my ($cwd_vol,$cwd_dir,$cwd_file)
814             = File::Spec->splitpath( $cwd );
815 205         2258 my @cwd = File::Spec->splitdir( $cwd_dir );
816 205 50       1183 push @cwd, $cwd_file if length $cwd_file;
817              
818             ### We need to pass '' as the last element to catpath. Craig Berry
819             ### explains why (msgid ):
820             ### The root problem is that splitpath on UNIX always returns the
821             ### final path element as a file even if it is a directory, and of
822             ### course there is no way it can know the difference without checking
823             ### against the filesystem, which it is documented as not doing. When
824             ### you turn around and call catpath, on VMS you have to know which bits
825             ### are directory bits and which bits are file bits. In this case we
826             ### know the result should be a directory. I had thought you could omit
827             ### the file argument to catpath in such a case, but apparently on UNIX
828             ### you can't.
829 205         5400 $dir = File::Spec->catpath(
830             $cwd_vol, File::Spec->catdir( @cwd, @dirs ), ''
831             );
832              
833             ### catdir() returns undef if the path is longer than 255 chars on
834             ### older VMS systems.
835 205 50       1145 unless ( defined $dir ) {
836 0 0       0 $^W && $self->_error( qq[Could not compose a path for '$dirs'\n] );
837 0         0 return;
838             }
839              
840             }
841              
842 285 50 66     10461 if( -e $dir && !-d _ ) {
843 0 0       0 $^W && $self->_error( qq['$dir' exists, but it's not a directory!\n] );
844 0         0 return;
845             }
846              
847 285 100       871 unless ( -d _ ) {
848 12         33 eval { File::Path::mkpath( $dir, 0, 0777 ) };
  12         4711  
849 12 100       79 if( $@ ) {
850 1         14 my $fp = $entry->full_path;
851 1         18 $self->_error(qq[Could not create directory '$dir' for '$fp': $@]);
852 1         10 return;
853             }
854              
855             ### XXX chown here? that might not be the same as in the archive
856             ### as we're only chown'ing to the owner of the file we're extracting
857             ### not to the owner of the directory itself, which may or may not
858             ### be another entry in the archive
859             ### Answer: no, gnu tar doesn't do it either, it'd be the wrong
860             ### way to go.
861             #if( $CHOWN && CAN_CHOWN ) {
862             # chown $entry->uid, $entry->gid, $dir or
863             # $self->_error( qq[Could not set uid/gid on '$dir'] );
864             #}
865             }
866              
867             ### we're done if we just needed to create a dir ###
868 284 100       3011 return 1 if $entry->is_dir;
869              
870 266         3648 my $full = File::Spec->catfile( $dir, $file );
871              
872 266 50       1505 if( $entry->is_unknown ) {
873 0         0 $self->_error( qq[Unknown file type for file '$full'] );
874 0         0 return;
875             }
876              
877             ### If a file system already contains a block device with the same name as
878             ### the being extracted regular file, we would write the file's content
879             ### to the block device. So remove the existing file (block device) now.
880             ### If an archive contains multiple same-named entries, the last one
881             ### should replace the previous ones. So remove the old file now.
882             ### If the old entry is a symlink to a file outside of the CWD, the new
883             ### entry would create a file there. This is CVE-2018-12015
884             ### .
885 266 100 66     5892 if (-l $full || -e _) {
886 9 50       3535 if (!unlink $full) {
887 0         0 $self->_error( qq[Could not remove old file '$full': $!] );
888 0         0 return;
889             }
890             }
891 266 100 66     858 if( length $entry->type && $entry->is_file ) {
892 260         4636 my $fh = IO::File->new;
893 260 50       20768 $fh->open( $full, '>' ) or (
894             $self->_error( qq[Could not open file '$full': $!] ),
895             return
896             );
897              
898 260 100       65967 if( $entry->size ) {
899 234         829 binmode $fh;
900 234         746 my $offset = 0;
901 234         1266 my $content = $entry->get_content_by_ref();
902 234         820 while ($offset < $entry->size) {
903 16827         233098 my $written
904             = syswrite $fh, $$content, $EXTRACT_BLOCK_SIZE, $offset;
905 16827 50       32445 if (defined $written) {
906 16827         35232 $offset += $written;
907             } else {
908 0         0 $self->_error( qq[Could not write data to '$full': $!] );
909 0         0 return;
910             }
911             }
912             }
913              
914 260 50       4500 close $fh or (
915             $self->_error( qq[Could not close file '$full'] ),
916             return
917             );
918              
919             } else {
920 6 50       81 $self->_make_special_file( $entry, $full ) or return;
921             }
922              
923             ### only update the timestamp if it's not a symlink; that will change the
924             ### timestamp of the original. This addresses bug #33669: Could not update
925             ### timestamp warning on symlinks
926 266 0 50     7491 if( not -l $full and not ( $entry->is_hardlink and ON_UNIX and $EXTRACT_HARDLINK ) ) {
      33        
      66        
927 260 50       1228 utime time, $entry->mtime - TIME_OFFSET, $full or
928             $self->_error( qq[Could not update timestamp] );
929             }
930              
931 266 100 33     6785 if( $CHOWN && CAN_CHOWN->() and not -l $full and not ( $entry->is_hardlink and ON_UNIX and $EXTRACT_HARDLINK ) ) {
      66        
      33        
      66        
932 260 50       1309 CORE::chown( $entry->uid, $entry->gid, $full ) or
933             $self->_error( qq[Could not set uid/gid on '$full'] );
934             }
935              
936             ### only chmod if we're allowed to, but never chmod symlinks, since they'll
937             ### change the perms on the file they're linking too...
938 266 100 66     5109 if( $CHMOD and not -l $full and not ( $entry->is_hardlink and ON_UNIX and $EXTRACT_HARDLINK ) ) {
      33        
      66        
939 260         1122 my $mode = $entry->mode;
940 260 50       681 unless ($SAME_PERMISSIONS) {
941 0         0 $mode &= ~(oct(7000) | umask);
942             }
943 260 50       4999 CORE::chmod( $mode, $full ) or
944             $self->_error( qq[Could not chown '$full' to ] . $entry->mode );
945             }
946              
947 266         4229 return 1;
948             }
949              
950             sub _make_special_file {
951 6     6   20 my $self = shift;
952 6 50       22 my $entry = shift or return;
953 6 50       16 my $file = shift; return unless defined $file;
  6         29  
954              
955 6         18 my $err;
956              
957 6 50 0     23 if( $entry->is_symlink ) {
    0          
    0          
    0          
    0          
958 6         14 my $fail;
959 6         37 if( ON_UNIX ) {
960 6 50       23 symlink( $entry->linkname, $file ) or $fail++;
961              
962             } else {
963             $self->_extract_special_file_as_plain_file( $entry, $file )
964             or $fail++;
965             }
966              
967 6 50       30 $err = qq[Making symbolic link '$file' to '] .
968             $entry->linkname .q[' failed] if $fail;
969              
970             } elsif ( $entry->is_hardlink ) {
971 0         0 my $fail;
972 0 0       0 if( ON_UNIX && $EXTRACT_HARDLINK ) {
973 0 0       0 link( $entry->linkname, $file ) or $fail++;
974              
975             } else {
976 0 0       0 $self->_extract_special_file_as_plain_file( $entry, $file )
977             or $fail++;
978             }
979              
980 0 0       0 $err = qq[Making hard link from '] . $entry->linkname .
981             qq[' to '$file' failed] if $fail;
982              
983             } elsif ( $entry->is_fifo ) {
984 0 0       0 ON_UNIX && !system('mknod', $file, 'p') or
985             $err = qq[Making fifo ']. $entry->name .qq[' failed];
986              
987             } elsif ( $entry->is_blockdev or $entry->is_chardev ) {
988 0 0       0 my $mode = $entry->is_blockdev ? 'b' : 'c';
989              
990 0 0       0 ON_UNIX && !system('mknod', $file, $mode,
991             $entry->devmajor, $entry->devminor) or
992             $err = qq[Making block device ']. $entry->name .qq[' (maj=] .
993             $entry->devmajor . qq[ min=] . $entry->devminor .
994             qq[) failed.];
995              
996             } elsif ( $entry->is_socket ) {
997             ### the original doesn't do anything special for sockets.... ###
998 0         0 1;
999             }
1000              
1001 6 50       38 return $err ? $self->_error( $err ) : 1;
1002             }
1003              
1004             ### don't know how to make symlinks, let's just extract the file as
1005             ### a plain file
1006             sub _extract_special_file_as_plain_file {
1007 0     0   0 my $self = shift;
1008 0 0       0 my $entry = shift or return;
1009 0 0       0 my $file = shift; return unless defined $file;
  0         0  
1010              
1011 0         0 my $err;
1012             TRY: {
1013 0         0 my $orig = $self->_find_entry( $entry->linkname, $entry );
  0         0  
1014              
1015 0 0       0 unless( $orig ) {
1016 0         0 $err = qq[Could not find file '] . $entry->linkname .
1017             qq[' in memory.];
1018 0         0 last TRY;
1019             }
1020              
1021             ### clone the entry, make it appear as a normal file ###
1022 0         0 my $clone = $orig->clone;
1023 0         0 $clone->_downgrade_to_plainfile;
1024 0 0       0 $self->_extract_file( $clone, $file ) or last TRY;
1025              
1026 0         0 return 1;
1027             }
1028              
1029 0         0 return $self->_error($err);
1030             }
1031              
1032             =head2 $tar->list_files( [\@properties] )
1033              
1034             Returns a list of the names of all the files in the archive.
1035              
1036             If C is passed an array reference as its first argument
1037             it returns a list of hash references containing the requested
1038             properties of each file. The following list of properties is
1039             supported: name, size, mtime (last modified date), mode, uid, gid,
1040             linkname, uname, gname, devmajor, devminor, prefix.
1041              
1042             Passing an array reference containing only one element, 'name', is
1043             special cased to return a list of names rather than a list of hash
1044             references, making it equivalent to calling C without
1045             arguments.
1046              
1047             =cut
1048              
1049             sub list_files {
1050 38     38 1 282 my $self = shift;
1051 38   50     362 my $aref = shift || [ ];
1052              
1053 38 50       115 unless( $self->_data ) {
1054 0 0       0 $self->read() or return;
1055             }
1056              
1057 38 50 0     195 if( @$aref == 0 or ( @$aref == 1 and $aref->[0] eq 'name' ) ) {
      33        
1058 38         66 return map { $_->full_path } @{$self->_data};
  137         297  
  38         116  
1059             } else {
1060              
1061             #my @rv;
1062             #for my $obj ( @{$self->_data} ) {
1063             # push @rv, { map { $_ => $obj->$_() } @$aref };
1064             #}
1065             #return @rv;
1066              
1067             ### this does the same as the above.. just needs a +{ }
1068             ### to make sure perl doesn't confuse it for a block
1069 0         0 return map { my $o=$_;
1070 0         0 +{ map { $_ => $o->$_() } @$aref }
  0         0  
1071 0         0 } @{$self->_data};
  0         0  
1072             }
1073             }
1074              
1075             sub _find_entry {
1076 218     218   21886 my $self = shift;
1077 218         570 my $file = shift;
1078              
1079 218 50       648 unless( defined $file ) {
1080 0         0 $self->_error( qq[No file specified] );
1081 0         0 return;
1082             }
1083              
1084             ### it's an object already
1085 218 100       3139 return $file if UNIVERSAL::isa( $file, 'Archive::Tar::File' );
1086              
1087             seach_entry:
1088 202 50       1608 if($self->_data){
1089 202         288 for my $entry ( @{$self->_data} ) {
  202         398  
1090 510         1215 my $path = $entry->full_path;
1091 510 100       2188 return $entry if $path eq $file;
1092             }
1093             }
1094              
1095 3 50       18 if($Archive::Tar::RESOLVE_SYMLINK!~/none/){
1096 3 50       8 if(my $link_entry = shift()){#fallback mode when symlinks are using relative notations ( ../a/./b/text.bin )
1097 0         0 $file = _symlinks_resolver( $link_entry->name, $file );
1098 0 0       0 goto seach_entry if $self->_data;
1099              
1100             #this will be slower than never, but won't failed!
1101              
1102 0         0 my $iterargs = $link_entry->{'_archive'};
1103 0 0 0     0 if($Archive::Tar::RESOLVE_SYMLINK=~/speed/ && @$iterargs==3){
1104             #faster but whole archive will be read in memory
1105             #read whole archive and share data
1106 0         0 my $archive = Archive::Tar->new;
1107 0         0 $archive->read( @$iterargs );
1108 0         0 push @$iterargs, $archive; #take a trace for destruction
1109 0 0       0 if($archive->_data){
1110 0         0 $self->_data( $archive->_data );
1111 0         0 goto seach_entry;
1112             }
1113             }#faster
1114              
1115             {#slower but lower memory usage
1116             # $iterargs = [$filename, $compressed, $opts];
1117 0         0 my $next = Archive::Tar->iter( @$iterargs );
  0         0  
1118 0         0 while(my $e = $next->()){
1119 0 0       0 if($e->full_path eq $file){
1120 0         0 undef $next;
1121 0         0 return $e;
1122             }
1123             }
1124             }#slower
1125             }
1126             }
1127              
1128 3         20 $self->_error( qq[No such file in archive: '$file'] );
1129 3         8 return;
1130             }
1131              
1132             =head2 $tar->get_files( [@filenames] )
1133              
1134             Returns the C objects matching the filenames
1135             provided. If no filename list was passed, all C
1136             objects in the current Tar object are returned.
1137              
1138             Please refer to the C documentation on how to
1139             handle these objects.
1140              
1141             =cut
1142              
1143             sub get_files {
1144 109     109 1 8920 my $self = shift;
1145              
1146 109 100       627 return @{ $self->_data } unless @_;
  105         685  
1147              
1148 4         5 my @list;
1149 4         14 for my $file ( @_ ) {
1150 4         10 push @list, grep { defined } $self->_find_entry( $file );
  2         6  
1151             }
1152              
1153 4         18 return @list;
1154             }
1155              
1156             =head2 $tar->get_content( $file )
1157              
1158             Return the content of the named file.
1159              
1160             =cut
1161              
1162             sub get_content {
1163 11     11 1 2775 my $self = shift;
1164 11 50       28 my $entry = $self->_find_entry( shift ) or return;
1165              
1166 11         19 return $entry->data;
1167             }
1168              
1169             =head2 $tar->replace_content( $file, $content )
1170              
1171             Make the string $content be the content for the file named $file.
1172              
1173             =cut
1174              
1175             sub replace_content {
1176 1     1 1 2 my $self = shift;
1177 1 50       3 my $entry = $self->_find_entry( shift ) or return;
1178              
1179 1         3 return $entry->replace_content( shift );
1180             }
1181              
1182             =head2 $tar->rename( $file, $new_name )
1183              
1184             Rename the file of the in-memory archive to $new_name.
1185              
1186             Note that you must specify a Unix path for $new_name, since per tar
1187             standard, all files in the archive must be Unix paths.
1188              
1189             Returns true on success and false on failure.
1190              
1191             =cut
1192              
1193             sub rename {
1194 2     2 1 231 my $self = shift;
1195 2 50       3 my $file = shift; return unless defined $file;
  2         10  
1196 2 50       3 my $new = shift; return unless defined $new;
  2         6  
1197              
1198 2 50       7 my $entry = $self->_find_entry( $file ) or return;
1199              
1200 2         7 return $entry->rename( $new );
1201             }
1202              
1203             =head2 $tar->chmod( $file, $mode )
1204              
1205             Change mode of $file to $mode.
1206              
1207             Returns true on success and false on failure.
1208              
1209             =cut
1210              
1211             sub chmod {
1212 1     1 1 3 my $self = shift;
1213 1 50       2 my $file = shift; return unless defined $file;
  1         5  
1214 1 50 33     3 my $mode = shift; return unless defined $mode && $mode =~ /^[0-7]{1,4}$/;
  1         28  
1215 1         6 my @args = ("$mode");
1216              
1217 1 50       7 my $entry = $self->_find_entry( $file ) or return;
1218 1         4 my $x = $entry->chmod( @args );
1219 1         8 return $x;
1220             }
1221              
1222             =head2 $tar->chown( $file, $uname [, $gname] )
1223              
1224             Change owner $file to $uname and $gname.
1225              
1226             Returns true on success and false on failure.
1227              
1228             =cut
1229              
1230             sub chown {
1231 2     2 1 5 my $self = shift;
1232 2 50       5 my $file = shift; return unless defined $file;
  2         7  
1233 2 50       5 my $uname = shift; return unless defined $uname;
  2         5  
1234 2         5 my @args = ($uname);
1235 2         4 push(@args, shift);
1236              
1237 2 50       7 my $entry = $self->_find_entry( $file ) or return;
1238 2         9 my $x = $entry->chown( @args );
1239 2         13 return $x;
1240             }
1241              
1242             =head2 $tar->remove (@filenamelist)
1243              
1244             Removes any entries with names matching any of the given filenames
1245             from the in-memory archive. Returns a list of C
1246             objects that remain.
1247              
1248             =cut
1249              
1250             sub remove {
1251 1     1 1 555 my $self = shift;
1252 1         4 my @list = @_;
1253              
1254 1         2 my %seen = map { $_->full_path => $_ } @{$self->_data};
  5         13  
  1         5  
1255 1         7 delete $seen{ $_ } for @list;
1256              
1257 1         6 $self->_data( [values %seen] );
1258              
1259 1         8 return values %seen;
1260             }
1261              
1262             =head2 $tar->clear
1263              
1264             C clears the current in-memory archive. This effectively gives
1265             you a 'blank' object, ready to be filled again. Note that C
1266             only has effect on the object, not the underlying tarfile.
1267              
1268             =cut
1269              
1270             sub clear {
1271 2 50   2 1 490 my $self = shift or return;
1272              
1273 2         22 $self->_data( [] );
1274 2         17 $self->_file( '' );
1275              
1276 2         13 return 1;
1277             }
1278              
1279              
1280             =head2 $tar->write ( [$file, $compressed, $prefix] )
1281              
1282             Write the in-memory archive to disk. The first argument can either
1283             be the name of a file or a reference to an already open filehandle (a
1284             GLOB reference).
1285              
1286             The second argument is used to indicate compression. You can
1287             compress using C, C or C. If you pass a digit, it's assumed
1288             to be the C compression level (between 1 and 9), but the use of
1289             constants is preferred:
1290              
1291             # write a gzip compressed file
1292             $tar->write( 'out.tgz', COMPRESS_GZIP );
1293              
1294             # write a bzip compressed file
1295             $tar->write( 'out.tbz', COMPRESS_BZIP );
1296              
1297             # write a xz compressed file
1298             $tar->write( 'out.txz', COMPRESS_XZ );
1299              
1300             Note that when you pass in a filehandle, the compression argument
1301             is ignored, as all files are printed verbatim to your filehandle.
1302             If you wish to enable compression with filehandles, use an
1303             C, C or C filehandle instead.
1304              
1305             The third argument is an optional prefix. All files will be tucked
1306             away in the directory you specify as prefix. So if you have files
1307             'a' and 'b' in your archive, and you specify 'foo' as prefix, they
1308             will be written to the archive as 'foo/a' and 'foo/b'.
1309              
1310             If no arguments are given, C returns the entire formatted
1311             archive as a string, which could be useful if you'd like to stuff the
1312             archive into a socket or a pipe to gzip or something.
1313              
1314              
1315             =cut
1316              
1317             sub write {
1318 33     33 1 8831 my $self = shift;
1319 33 100       129 my $file = shift; $file = '' unless defined $file;
  33         213  
1320 33   100     231 my $gzip = shift || 0;
1321 33 50       67 my $ext_prefix = shift; $ext_prefix = '' unless defined $ext_prefix;
  33         202  
1322 33         146 my $dummy = '';
1323              
1324             ### only need a handle if we have a file to print to ###
1325             my $handle = length($file)
1326             ? ( $self->_get_handle($file, $gzip, WRITE_ONLY->($gzip) )
1327             or return )
1328 33 0 50     364 : $HAS_PERLIO ? do { open my $h, '>', \$dummy; $h }
  3 50       72  
  3 100       15  
1329             : $HAS_IO_STRING ? IO::String->new
1330             : __PACKAGE__->no_string_support();
1331              
1332             ### Addresses: #41798: Nonempty $\ when writing a TAR file produces a
1333             ### corrupt TAR file. Must clear out $\ to make sure no garbage is
1334             ### printed to the archive
1335 33         220 local $\;
1336              
1337 33         116 for my $entry ( @{$self->_data} ) {
  33         147  
1338             ### entries to be written to the tarfile ###
1339 74         1688 my @write_me;
1340              
1341             ### only now will we change the object to reflect the current state
1342             ### of the name and prefix fields -- this needs to be limited to
1343             ### write() only!
1344 74         336 my $clone = $entry->clone;
1345              
1346              
1347             ### so, if you don't want use to use the prefix, we'll stuff
1348             ### everything in the name field instead
1349 74 100       247 if( $DO_NOT_USE_PREFIX ) {
1350              
1351             ### you might have an extended prefix, if so, set it in the clone
1352             ### XXX is ::Unix right?
1353 4 50       21 $clone->name( length $ext_prefix
1354             ? File::Spec::Unix->catdir( $ext_prefix,
1355             $clone->full_path)
1356             : $clone->full_path );
1357 4         16 $clone->prefix( '' );
1358              
1359             ### otherwise, we'll have to set it properly -- prefix part in the
1360             ### prefix and name part in the name field.
1361             } else {
1362              
1363             ### split them here, not before!
1364 70         267 my ($prefix,$name) = $clone->_prefix_and_file( $clone->full_path );
1365              
1366             ### you might have an extended prefix, if so, set it in the clone
1367             ### XXX is ::Unix right?
1368 70 50       264 $prefix = File::Spec::Unix->catdir( $ext_prefix, $prefix )
1369             if length $ext_prefix;
1370              
1371 70         217 $clone->prefix( $prefix );
1372 70         192 $clone->name( $name );
1373             }
1374              
1375             ### names are too long, and will get truncated if we don't add a
1376             ### '@LongLink' file...
1377 74   100     180 my $make_longlink = ( length($clone->name) > NAME_LENGTH or
1378             length($clone->prefix) > PREFIX_LENGTH
1379             ) || 0;
1380              
1381             ### perhaps we need to make a longlink file?
1382 74 100       1150 if( $make_longlink ) {
1383 9         26 my $longlink = Archive::Tar::File->new(
1384             data => LONGLINK_NAME,
1385             $clone->full_path,
1386             { type => LONGLINK }
1387             );
1388              
1389 9 50       39 unless( $longlink ) {
1390 0         0 $self->_error( qq[Could not create 'LongLink' entry for ] .
1391             qq[oversize file '] . $clone->full_path ."'" );
1392 0         0 return;
1393             };
1394              
1395 9         22 push @write_me, $longlink;
1396             }
1397              
1398 74         170 push @write_me, $clone;
1399              
1400             ### write the one, optionally 2 a::t::file objects to the handle
1401 74         165 for my $clone (@write_me) {
1402              
1403             ### if the file is a symlink, there are 2 options:
1404             ### either we leave the symlink intact, but then we don't write any
1405             ### data OR we follow the symlink, which means we actually make a
1406             ### copy. if we do the latter, we have to change the TYPE of the
1407             ### clone to 'FILE'
1408 83   66     752 my $link_ok = $clone->is_symlink && $Archive::Tar::FOLLOW_SYMLINK;
1409 83   100     213 my $data_ok = !$clone->is_symlink && $clone->has_content;
1410              
1411             ### downgrade to a 'normal' file if it's a symlink we're going to
1412             ### treat as a regular file
1413 83 50       252 $clone->_downgrade_to_plainfile if $link_ok;
1414              
1415             ### get the header for this block
1416 83         311 my $header = $self->_format_tar_entry( $clone );
1417 83 50       234 unless( $header ) {
1418 0         0 $self->_error(q[Could not format header for: ] .
1419             $clone->full_path );
1420 0         0 return;
1421             }
1422              
1423 83 50       769 unless( print $handle $header ) {
1424 0         0 $self->_error(q[Could not write header for: ] .
1425             $clone->full_path);
1426 0         0 return;
1427             }
1428              
1429 83 100 66     6749 if( $link_ok or $data_ok ) {
1430 70 50       222 unless( print $handle $clone->data ) {
1431 0         0 $self->_error(q[Could not write data for: ] .
1432             $clone->full_path);
1433 0         0 return;
1434             }
1435              
1436             ### pad the end of the clone if required ###
1437 70 50       7585 print $handle TAR_PAD->( $clone->size ) if $clone->size % BLOCK
1438             }
1439              
1440             } ### done writing these entries
1441             }
1442              
1443             ### write the end markers ###
1444 33 50       1941 print $handle TAR_END x 2 or
1445             return $self->_error( qq[Could not write tar end markers] );
1446              
1447             ### did you want it written to a file, or returned as a string? ###
1448             my $rv = length($file) ? 1
1449             : $HAS_PERLIO ? $dummy
1450 33 50       5083 : do { seek $handle, 0, 0; local $/; <$handle> };
  0 100       0  
  0         0  
  0         0  
1451              
1452             ### make sure to close the handle if we created it
1453 33 50       200 if ( $file ne $handle ) {
1454 33 50       1235 unless( close $handle ) {
1455 0         0 $self->_error( qq[Could not write tar] );
1456 0         0 return;
1457             }
1458             }
1459              
1460 33         34275 return $rv;
1461             }
1462              
1463             sub _format_tar_entry {
1464 83     83   140 my $self = shift;
1465 83 50       221 my $entry = shift or return;
1466 83 50       129 my $ext_prefix = shift; $ext_prefix = '' unless defined $ext_prefix;
  83         215  
1467 83   50     353 my $no_prefix = shift || 0;
1468              
1469 83         212 my $file = $entry->name;
1470 83 50       209 my $prefix = $entry->prefix; $prefix = '' unless defined $prefix;
  83         201  
1471              
1472             ### remove the prefix from the file name
1473             ### not sure if this is still needed --kane
1474             ### no it's not -- Archive::Tar::File->_new_from_file will take care of
1475             ### this for us. Even worse, this would break if we tried to add a file
1476             ### like x/x.
1477             #if( length $prefix ) {
1478             # $file =~ s/^$match//;
1479             #}
1480              
1481 83 50       217 $prefix = File::Spec::Unix->catdir($ext_prefix, $prefix)
1482             if length $ext_prefix;
1483              
1484             ### not sure why this is... ###
1485 83         150 my $l = PREFIX_LENGTH; # is ambiguous otherwise...
1486 83 100       238 substr ($prefix, 0, -$l) = "" if length $prefix >= PREFIX_LENGTH;
1487              
1488 83 50       236 my $f1 = "%06o"; my $f2 = $ZERO_PAD_NUMBERS ? "%011o" : "%11o";
  83         251  
1489              
1490             ### this might be optimizable with a 'changed' flag in the file objects ###
1491             my $tar = pack (
1492             PACK,
1493             $file,
1494              
1495 249         794 (map { sprintf( $f1, $entry->$_() ) } qw[mode uid gid]),
1496 166         483 (map { sprintf( $f2, $entry->$_() ) } qw[size mtime]),
1497              
1498             "", # checksum field - space padded a bit down
1499              
1500 249         646 (map { $entry->$_() } qw[type linkname magic]),
1501              
1502             $entry->version || TAR_VERSION,
1503              
1504 166         478 (map { $entry->$_() } qw[uname gname]),
1505 83 50 50     198 (map { sprintf( $f1, $entry->$_() ) } qw[devmajor devminor]),
  166         451  
1506              
1507             ($no_prefix ? '' : $prefix)
1508             );
1509              
1510             ### add the checksum ###
1511 83 50       316 my $checksum_fmt = $ZERO_PAD_NUMBERS ? "%06o\0" : "%06o\0";
1512 83         612 substr($tar,148,7) = sprintf("%6o\0", unpack("%16C*",$tar));
1513              
1514 83         325 return $tar;
1515             }
1516              
1517             =head2 $tar->add_files( @filenamelist )
1518              
1519             Takes a list of filenames and adds them to the in-memory archive.
1520              
1521             The path to the file is automatically converted to a Unix like
1522             equivalent for use in the archive, and, if on MacOS, the file's
1523             modification time is converted from the MacOS epoch to the Unix epoch.
1524             So tar archives created on MacOS with B can be read
1525             both with I on Unix and applications like I or
1526             I on MacOS.
1527              
1528             Be aware that the file's type/creator and resource fork will be lost,
1529             which is usually what you want in cross-platform archives.
1530              
1531             Instead of a filename, you can also pass it an existing C
1532             object from, for example, another archive. The object will be clone, and
1533             effectively be a copy of the original, not an alias.
1534              
1535             Returns a list of C objects that were just added.
1536              
1537             =cut
1538              
1539             sub add_files {
1540 25     25 1 7459 my $self = shift;
1541 25 50       240 my @files = @_ or return;
1542              
1543 25         45 my @rv;
1544 25         167 for my $file ( @files ) {
1545              
1546             ### you passed an Archive::Tar::File object
1547             ### clone it so we don't accidentally have a reference to
1548             ### an object from another archive
1549 29 100       301 if( UNIVERSAL::isa( $file,'Archive::Tar::File' ) ) {
1550 7         19 push @rv, $file->clone;
1551 7         14 next;
1552             }
1553              
1554 22         76 eval {
1555 22 50       141 if( utf8::is_utf8( $file )) {
1556 0         0 utf8::encode( $file );
1557             }
1558             };
1559              
1560 22 50 33     541 unless( -e $file || -l $file ) {
1561 0         0 $self->_error( qq[No such file: '$file'] );
1562 0         0 next;
1563             }
1564              
1565 22         342 my $obj = Archive::Tar::File->new( file => $file );
1566 22 50       94 unless( $obj ) {
1567 0         0 $self->_error( qq[Unable to add file: '$file'] );
1568 0         0 next;
1569             }
1570              
1571 22         84 push @rv, $obj;
1572             }
1573              
1574 25         40 push @{$self->{_data}}, @rv;
  25         121  
1575              
1576 25         82 return @rv;
1577             }
1578              
1579             =head2 $tar->add_data ( $filename, $data, [$opthashref] )
1580              
1581             Takes a filename, a scalar full of data and optionally a reference to
1582             a hash with specific options.
1583              
1584             Will add a file to the in-memory archive, with name C<$filename> and
1585             content C<$data>. Specific properties can be set using C<$opthashref>.
1586             The following list of properties is supported: name, size, mtime
1587             (last modified date), mode, uid, gid, linkname, uname, gname,
1588             devmajor, devminor, prefix, type. (On MacOS, the file's path and
1589             modification times are converted to Unix equivalents.)
1590              
1591             Valid values for the file type are the following constants defined by
1592             Archive::Tar::Constant:
1593              
1594             =over 4
1595              
1596             =item FILE
1597              
1598             Regular file.
1599              
1600             =item HARDLINK
1601              
1602             =item SYMLINK
1603              
1604             Hard and symbolic ("soft") links; linkname should specify target.
1605              
1606             =item CHARDEV
1607              
1608             =item BLOCKDEV
1609              
1610             Character and block devices. devmajor and devminor should specify the major
1611             and minor device numbers.
1612              
1613             =item DIR
1614              
1615             Directory.
1616              
1617             =item FIFO
1618              
1619             FIFO (named pipe).
1620              
1621             =item SOCKET
1622              
1623             Socket.
1624              
1625             =back
1626              
1627             Returns the C object that was just added, or
1628             C on failure.
1629              
1630             =cut
1631              
1632             sub add_data {
1633 14     14 1 9108 my $self = shift;
1634 14         55 my ($file, $data, $opt) = @_;
1635              
1636 14         88 my $obj = Archive::Tar::File->new( data => $file, $data, $opt );
1637 14 100       36 unless( $obj ) {
1638 1         6 $self->_error( qq[Unable to add file: '$file'] );
1639 1         4 return;
1640             }
1641              
1642 13         23 push @{$self->{_data}}, $obj;
  13         38  
1643              
1644 13         46 return $obj;
1645             }
1646              
1647             =head2 $tar->error( [$BOOL] )
1648              
1649             Returns the current error string (usually, the last error reported).
1650             If a true value was specified, it will give the C
1651             equivalent of the error, in effect giving you a stacktrace.
1652              
1653             For backwards compatibility, this error is also available as
1654             C<$Archive::Tar::error> although it is much recommended you use the
1655             method call instead.
1656              
1657             =cut
1658              
1659             {
1660             $error = '';
1661             my $longmess;
1662              
1663             sub _error {
1664 15     15   31 my $self = shift;
1665 15         54 my $msg = $error = shift;
1666 15         4211 $longmess = Carp::longmess($error);
1667 15 50       71 if (ref $self) {
1668 15         57 $self->{_error} = $error;
1669 15         80 $self->{_longmess} = $longmess;
1670             }
1671              
1672             ### set Archive::Tar::WARN to 0 to disable printing
1673             ### of errors
1674 15 100       50 if( $WARN ) {
1675 6 50       966 carp $DEBUG ? $longmess : $msg;
1676             }
1677              
1678 15         79 return;
1679             }
1680              
1681             sub error {
1682 22     22 1 3486 my $self = shift;
1683 22 100       85 if (ref $self) {
1684 20 50       223 return shift() ? $self->{_longmess} : $self->{_error};
1685             } else {
1686 2 50       9 return shift() ? $longmess : $error;
1687             }
1688             }
1689             }
1690              
1691             =head2 $tar->setcwd( $cwd );
1692              
1693             C needs to know the current directory, and it will run
1694             C I time it extracts a I entry from the
1695             tarfile and saves it in the file system. (As of version 1.30, however,
1696             C will use the speed optimization described below
1697             automatically, so it's only relevant if you're using C).
1698              
1699             Since C doesn't change the current directory internally
1700             while it is extracting the items in a tarball, all calls to C
1701             can be avoided if we can guarantee that the current directory doesn't
1702             get changed externally.
1703              
1704             To use this performance boost, set the current directory via
1705              
1706             use Cwd;
1707             $tar->setcwd( cwd() );
1708              
1709             once before calling a function like C and
1710             C will use the current directory setting from then on
1711             and won't call C internally.
1712              
1713             To switch back to the default behaviour, use
1714              
1715             $tar->setcwd( undef );
1716              
1717             and C will call C internally again.
1718              
1719             If you're using C's C method, C will
1720             be called for you.
1721              
1722             =cut
1723              
1724             sub setcwd {
1725 0     0 1 0 my $self = shift;
1726 0         0 my $cwd = shift;
1727              
1728 0         0 $self->{cwd} = $cwd;
1729             }
1730              
1731             =head1 Class Methods
1732              
1733             =head2 Archive::Tar->create_archive($file, $compressed, @filelist)
1734              
1735             Creates a tar file from the list of files provided. The first
1736             argument can either be the name of the tar file to create or a
1737             reference to an open file handle (e.g. a GLOB reference).
1738              
1739             The second argument is used to indicate compression. You can
1740             compress using C, C or C. If you pass a digit, it's assumed
1741             to be the C compression level (between 1 and 9), but the use of
1742             constants is preferred:
1743              
1744             # write a gzip compressed file
1745             Archive::Tar->create_archive( 'out.tgz', COMPRESS_GZIP, @filelist );
1746              
1747             # write a bzip compressed file
1748             Archive::Tar->create_archive( 'out.tbz', COMPRESS_BZIP, @filelist );
1749              
1750             # write a xz compressed file
1751             Archive::Tar->create_archive( 'out.txz', COMPRESS_XZ, @filelist );
1752              
1753             Note that when you pass in a filehandle, the compression argument
1754             is ignored, as all files are printed verbatim to your filehandle.
1755             If you wish to enable compression with filehandles, use an
1756             C, C or C filehandle instead.
1757              
1758             The remaining arguments list the files to be included in the tar file.
1759             These files must all exist. Any files which don't exist or can't be
1760             read are silently ignored.
1761              
1762             If the archive creation fails for any reason, C will
1763             return false. Please use the C method to find the cause of the
1764             failure.
1765              
1766             Note that this method does not write C as it were; it
1767             still reads all the files into memory before writing out the archive.
1768             Consult the FAQ below if this is a problem.
1769              
1770             =cut
1771              
1772             sub create_archive {
1773 9     9 1 62 my $class = shift;
1774              
1775 9 50       38 my $file = shift; return unless defined $file;
  9         55  
1776 9   100     71 my $gzip = shift || 0;
1777 9         69 my @files = @_;
1778              
1779 9 50       31 unless( @files ) {
1780 0         0 return $class->_error( qq[Cowardly refusing to create empty archive!] );
1781             }
1782              
1783 9         82 my $tar = $class->new;
1784 9         246 $tar->add_files( @files );
1785 9         112 return $tar->write( $file, $gzip );
1786             }
1787              
1788             =head2 Archive::Tar->iter( $filename, [ $compressed, {opt => $val} ] )
1789              
1790             Returns an iterator function that reads the tar file without loading
1791             it all in memory. Each time the function is called it will return the
1792             next file in the tarball. The files are returned as
1793             C objects. The iterator function returns the
1794             empty list once it has exhausted the files contained.
1795              
1796             The second argument can be a hash reference with options, which are
1797             identical to the arguments passed to C.
1798              
1799             Example usage:
1800              
1801             my $next = Archive::Tar->iter( "example.tar.gz", 1, {filter => qr/\.pm$/} );
1802              
1803             while( my $f = $next->() ) {
1804             print $f->name, "\n";
1805              
1806             $f->extract or warn "Extraction failed";
1807              
1808             # ....
1809             }
1810              
1811             =cut
1812              
1813              
1814             sub iter {
1815 15     15 1 29473 my $class = shift;
1816 15         83 my $filename = shift;
1817 15 50       53 return unless defined $filename;
1818 15   100     80 my $compressed = shift || 0;
1819 15   100     108 my $opts = shift || {};
1820              
1821             ### get a handle to read from.
1822 15 50       83 my $handle = $class->_get_handle(
1823             $filename,
1824             $compressed,
1825             READ_ONLY->( ZLIB )
1826             ) or return;
1827              
1828 15         35 my @data;
1829 15         41 my $CONSTRUCT_ARGS = [ $filename, $compressed, $opts ];
1830             return sub {
1831 35 100   35   10611 return shift(@data) if @data; # more than one file returned?
1832 33 50       142 return unless $handle; # handle exhausted?
1833              
1834             ### read data, should only return file
1835 33         335 my $tarfile = $class->_read_tar($handle, { %$opts, limit => 1 });
1836 33 50 33     306 @data = @$tarfile if ref $tarfile && ref $tarfile eq 'ARRAY';
1837 33 50       177 if($Archive::Tar::RESOLVE_SYMLINK!~/none/){
1838 33         135 foreach(@data){
1839             #may refine this heuristic for ON_UNIX?
1840 20 100       65 if($_->linkname){
1841             #is there a better slot to store/share it ?
1842 1         8 $_->{'_archive'} = $CONSTRUCT_ARGS;
1843             }
1844             }
1845             }
1846              
1847             ### return one piece of data
1848 33 100       145 return shift(@data) if @data;
1849              
1850             ### data is exhausted, free the filehandle
1851 15         212 undef $handle;
1852 15 50       2370 if(@$CONSTRUCT_ARGS == 4){
1853             #free archive in memory
1854 0         0 undef $CONSTRUCT_ARGS->[-1];
1855             }
1856 15         71 return;
1857 15         147 };
1858             }
1859              
1860             =head2 Archive::Tar->list_archive($file, $compressed, [\@properties])
1861              
1862             Returns a list of the names of all the files in the archive. The
1863             first argument can either be the name of the tar file to list or a
1864             reference to an open file handle (e.g. a GLOB reference).
1865              
1866             If C is passed an array reference as its third
1867             argument it returns a list of hash references containing the requested
1868             properties of each file. The following list of properties is
1869             supported: full_path, name, size, mtime (last modified date), mode,
1870             uid, gid, linkname, uname, gname, devmajor, devminor, prefix, type.
1871              
1872             See C for details about supported properties.
1873              
1874             Passing an array reference containing only one element, 'name', is
1875             special cased to return a list of names rather than a list of hash
1876             references.
1877              
1878             =cut
1879              
1880             sub list_archive {
1881 3     3 1 1374 my $class = shift;
1882 3 50       5 my $file = shift; return unless defined $file;
  3         8  
1883 3   50     18 my $gzip = shift || 0;
1884              
1885 3         10 my $tar = $class->new($file, $gzip);
1886 3 50       7 return unless $tar;
1887              
1888 3         22 return $tar->list_files( @_ );
1889             }
1890              
1891             =head2 Archive::Tar->extract_archive($file, $compressed)
1892              
1893             Extracts the contents of the tar file. The first argument can either
1894             be the name of the tar file to create or a reference to an open file
1895             handle (e.g. a GLOB reference). All relative paths in the tar file will
1896             be created underneath the current working directory.
1897              
1898             C will return a list of files it extracted.
1899             If the archive extraction fails for any reason, C
1900             will return false. Please use the C method to find the cause
1901             of the failure.
1902              
1903             =cut
1904              
1905             sub extract_archive {
1906 9     9 1 34 my $class = shift;
1907 9 50       21 my $file = shift; return unless defined $file;
  9         60  
1908 9   100     51 my $gzip = shift || 0;
1909              
1910 9 50       42 my $tar = $class->new( ) or return;
1911              
1912 9         91 return $tar->read( $file, $gzip, { extract => 1 } );
1913             }
1914              
1915             =head2 $bool = Archive::Tar->has_io_string
1916              
1917             Returns true if we currently have C support loaded.
1918              
1919             Either C or C support is needed to support writing
1920             stringified archives. Currently, C is the preferred method, if
1921             available.
1922              
1923             See the C section to see how to change this preference.
1924              
1925             =cut
1926              
1927 0     0 1 0 sub has_io_string { return $HAS_IO_STRING; }
1928              
1929             =head2 $bool = Archive::Tar->has_perlio
1930              
1931             Returns true if we currently have C support loaded.
1932              
1933             This requires C or higher, compiled with C
1934              
1935             Either C or C support is needed to support writing
1936             stringified archives. Currently, C is the preferred method, if
1937             available.
1938              
1939             See the C section to see how to change this preference.
1940              
1941             =cut
1942              
1943 0     0 1 0 sub has_perlio { return $HAS_PERLIO; }
1944              
1945             =head2 $bool = Archive::Tar->has_zlib_support
1946              
1947             Returns true if C can extract C compressed archives
1948              
1949             =cut
1950              
1951 6     6 1 325473 sub has_zlib_support { return ZLIB }
1952              
1953             =head2 $bool = Archive::Tar->has_bzip2_support
1954              
1955             Returns true if C can extract C compressed archives
1956              
1957             =cut
1958              
1959 6     6 1 24 sub has_bzip2_support { return BZIP }
1960              
1961             =head2 $bool = Archive::Tar->has_xz_support
1962              
1963             Returns true if C can extract C compressed archives
1964              
1965             =cut
1966              
1967 5     5 1 27 sub has_xz_support { return XZ }
1968              
1969             =head2 Archive::Tar->can_handle_compressed_files
1970              
1971             A simple checking routine, which will return true if C
1972             is able to uncompress compressed archives on the fly with C,
1973             C and C or false if not both are installed.
1974              
1975             You can use this as a shortcut to determine whether C
1976             will do what you think before passing compressed archives to its
1977             C method.
1978              
1979             =cut
1980              
1981 0     0 1   sub can_handle_compressed_files { return ZLIB && BZIP ? 1 : 0 }
1982              
1983             sub no_string_support {
1984 0     0 0   croak("You have to install IO::String to support writing archives to strings");
1985             }
1986              
1987             sub _symlinks_resolver{
1988 0     0     my ($src, $trg) = @_;
1989 0           my @src = split /[\/\\]/, $src;
1990 0           my @trg = split /[\/\\]/, $trg;
1991 0           pop @src; #strip out current object name
1992 0 0 0       if(@trg and $trg[0] eq ''){
1993 0           shift @trg;
1994             #restart path from scratch
1995 0           @src = ( );
1996             }
1997 0           foreach my $part ( @trg ){
1998 0 0         next if $part eq '.'; #ignore current
1999 0 0         if($part eq '..'){
2000             #got to parent
2001 0           pop @src;
2002             }
2003             else{
2004             #append it
2005 0           push @src, $part;
2006             }
2007             }
2008 0           my $path = join('/', @src);
2009 0 0         warn "_symlinks_resolver('$src','$trg') = $path" if $DEBUG;
2010 0           return $path;
2011             }
2012              
2013             1;
2014              
2015             __END__