File Coverage

lib/Archive/Tar.pm
Criterion Covered Total %
statement 507 663 76.4
branch 255 442 57.6
condition 112 188 59.5
subroutine 48 55 87.2
pod 29 30 96.6
total 951 1378 69.0


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   1842130 use Cwd;
  17         29  
  17         1408  
11 17     17   9004 use IO::Zlib;
  17         1228304  
  17         133  
12 17     17   1050 use IO::File;
  17         47  
  17         2667  
13 17     17   157 use Carp qw(carp croak);
  17         42  
  17         968  
14 17     17   110 use File::Spec ();
  17         53  
  17         310  
15 17     17   68 use File::Spec::Unix ();
  17         31  
  17         247  
16 17     17   61 use File::Path ();
  17         27  
  17         382  
17              
18 17     17   10772 use Archive::Tar::File;
  17         58  
  17         661  
19 17     17   115 use Archive::Tar::Constant;
  17         28  
  17         3419  
20              
21             require Exporter;
22              
23 17     17   111 use strict;
  17         31  
  17         1014  
24 17         4206 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   85 ];
  17         24  
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.08";
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   114 use Config;
  17         27  
  17         1583  
48 17     17   1683 $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     103 $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   108 no strict 'refs';
  17         70  
  17         149416  
116             *{__PACKAGE__."::$key"} = sub {
117 719     719   1199 my $self = shift;
118 719 100       2275 $self->{$key} = $_[0] if @_;
119 719         3183 return $self->{$key};
120             }
121             }
122              
123             sub new {
124 77     77 1 695836 my $class = shift;
125 77 50       386 $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         664 my $obj = bless { _data => [ ], _file => 'Unknown', _error => '' }, $class;
130              
131 77 100       327 if (@_) {
132 14 50       56 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         2115 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 4059 my $self = shift;
208 50         211 my $file = shift;
209 50   100     818 my $gzip = shift || 0;
210 50   100     303 my $opts = shift || {};
211              
212 50 100       167 unless( defined $file ) {
213 2         19 $self->_error( qq[No file to read from!] );
214 2         12 return;
215             } else {
216 48         251 $self->_file( $file );
217             }
218              
219 48 50       380 my $handle = $self->_get_handle($file, $gzip, READ_ONLY->( ZLIB ) )
220             or return;
221              
222 48 100       246 my $data = $self->_read_tar( $handle, $opts ) or return;
223              
224 46         320 $self->_data( $data );
225              
226 46 100       579 return wantarray ? @$data : scalar @$data;
227             }
228              
229             sub _get_handle {
230 93     93   347 my $self = shift;
231 93 50       189 my $file = shift; return unless defined $file;
  93         358  
232 93   100     371 my $compress = shift || 0;
233 93   33     370 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       263 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         170 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         171 my $magic = '';
  93         264  
248 93 100       371 if( MODE_READ->($mode) ) {
249 63 50       3880 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         948 sysread( $tmp, $magic, 6 );
257 63         891 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     793 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       45 if( MODE_READ->($mode) ) {
295 10 50       113 $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       198 $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         713 $fh = IO::Zlib->new;
319              
320 61 50       3581 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         115 $fh = IO::File->new;
328              
329 15 50       582 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         2767 binmode $fh;
336             }
337             }
338              
339 93         146560 return $fh;
340             }
341              
342              
343             sub _read_tar {
344 81     81   140 my $self = shift;
345 81 50       207 my $handle = shift or return;
346 81   50     184 my $opts = shift || {};
347              
348 81   100     446 my $count = $opts->{limit} || 0;
349 81         155 my $filter = $opts->{filter};
350 81   50     370 my $md5 = $opts->{md5} || 0; # cdrake
351 81         126 my $filter_cb = $opts->{filter_cb};
352 81   100     312 my $extract = $opts->{extract} || 0;
353              
354             ### set a cap on the amount of files to extract ###
355 81         137 my $limit = 0;
356 81 100       236 $limit = 1 if $count > 0;
357              
358 81         122 my $tarfile = [ ];
359 81         133 my $chunk;
360 81         110 my $read = 0;
361 81         139 my $real_name; # to set the name of a file when
362             # we're encountering @longlink
363             my $data;
364              
365             LOOP:
366 81         768 while( $handle->read( $chunk, HEAD ) ) {
367             ### IO::Zlib doesn't support this yet
368 616         87022 my $offset;
369 616 100       1178 if ( ref($handle) ne 'IO::Zlib' ) {
370 81         72 local $@;
371 81   50     97 $offset = eval { tell $handle } || 'unknown';
372 81         745 $@ = '';
373             }
374             else {
375 535         713 $offset = 'unknown';
376             }
377              
378 616 100       1087 unless( $read++ ) {
379 77         196 my $gzip = GZIP_MAGIC_NUM;
380 77 50       827 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       219 if (length $chunk != HEAD) {
388 2         14 $self->_error( qq[Cannot read enough bytes from the tarfile] );
389 2         33 return;
390             }
391             }
392              
393             ### if we can't read in all bytes... ###
394 614 100       1099 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       1256 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         224 { my $nulls = join '', "\0" x 12;
  242         288  
407 242 50       534 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         248 my $entry;
417 242         624 { my %extra_args = ();
  242         388  
418 242 100       472 $extra_args{'name'} = $$real_name if defined $real_name;
419              
420 242 50       1170 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       542 next if $entry->is_label;
431              
432 242 100 66     407 if( length $entry->type and ($entry->is_file || $entry->is_longlink) ) {
      33        
433              
434 184 50 33     307 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         431 my $block = BLOCK_SIZE->( $entry->size );
447              
448 184         367 $data = $entry->get_content_by_ref;
449              
450 184         219 my $skip = 0;
451 184         327 my $ctx; # cdrake
452             ### skip this entry if we're filtering
453              
454 184 50 100     789 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         26 $skip = 1;
460              
461             } elsif ($filter_cb && ! $filter_cb->($entry)) {
462 22         23 $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       391 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         41 my $amt = $block;
479 44         60 my $fsz=$entry->size; # cdrake
480 44         73 while ($amt > 0) {
481 44         47 $$data = '';
482 44         62 my $this = 64 * BLOCK;
483 44 50       71 $this = $amt if $this > $amt;
484 44 50       173 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         4784 $amt -= $this;
490 44         46 $fsz -= $this; # cdrake
491 44 50       73 substr ($$data, $fsz) = "" if ($fsz<0); # remove external junk prior to md5 # cdrake
492 44 50       86 $ctx->add($$data) if($skip==5); # cdrake
493             }
494 44 0 33     70 $$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       743 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       22574 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       538 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         147 my $nulls = $$data =~ tr/\0/\0/;
525              
526             ### cut data + size by that many bytes
527 51         95 $entry->size( $entry->size - $nulls );
528 51         87 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       444 if( $entry->is_longlink ) {
    100          
541 51         69 $real_name = $data;
542 51         257 next LOOP;
543             } elsif ( defined $real_name ) {
544 51         114 $entry->name( $$real_name );
545 51         119 $entry->prefix('');
546 51         75 undef $real_name;
547             }
548              
549 191 100 100     733 if ($filter && $entry->name !~ $filter) {
    100 100        
    50 33        
550 20         77 next LOOP;
551              
552             } elsif ($filter_cb && ! $filter_cb->($entry)) {
553 20         74 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     428 if ( $extract && !$entry->is_longlink
      66        
      33        
563             && !$entry->is_unknown
564             && !$entry->is_label ) {
565 9 50       83 $self->_extract_file( $entry ) or return;
566             }
567              
568             ### Guard against tarfiles with garbage at the end
569 151 50       301 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       372 push @$tarfile, ($extract ? $entry->name : $entry);
574              
575 151 100       858 if( $limit ) {
576 21 100 66     95 $count-- unless $entry->is_longlink || $entry->is_dir;
577 21 100       65 last LOOP unless $count;
578             }
579             } continue {
580 597         2648 undef $data;
581             }
582              
583 79         16424 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 6 my $self = shift;
600 2         7 my $full = shift;
601              
602 2 50       9 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         4 local $WARN = 0;
607 2 100       15 return 1 if $self->_find_entry($full);
608 1         4 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 21984 my $self = shift;
631 32         120 my @args = @_;
632 32         68 my @files;
633             my $hashmap;
634              
635             # use the speed optimization for all extracted files
636 32 50       221042 local($self->{cwd}) = cwd() unless $self->{cwd};
637              
638             ### you requested the extraction of only certain files
639 32 100       513 if( @args ) {
640 2         33 for my $file ( @args ) {
641              
642             ### it's already an object?
643 2 100       65 if( UNIVERSAL::isa( $file, 'Archive::Tar::File' ) ) {
644 1         11 push @files, $file;
645 1         6 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     34 map { $_->full_path, $_ } @{$self->_data}
653             };
654              
655 1 50       12 if (exists $hashmap->{$file}) {
656             ### we found the file you're looking for
657 1         10 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         570 @files = $self->get_files;
668             }
669              
670             ### nothing found? that's an error
671 32 50       172 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         211 for my $entry ( @files ) {
678 111 100       493 unless( $self->_extract_file( $entry ) ) {
679 3         12 $self->_error(q[Could not extract ']. $entry->full_path .q['] );
680 3         15 return;
681             }
682             }
683              
684 29         819 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 1363 my $self = shift;
705 165 50       527 my $file = shift; return unless defined $file;
  165         585  
706 165         295 my $alt = shift;
707              
708 165 50       1174 my $entry = $self->_find_entry( $file )
709             or $self->_error( qq[Could not find an entry for '$file'] ), return;
710              
711 165         554 return $self->_extract_file( $entry, $alt );
712             }
713              
714             sub _extract_file {
715 288     288   768 my $self = shift;
716 288 50       862 my $entry = shift or return;
717 288         541 my $alt = shift;
718              
719             ### you wanted an alternate extraction location ###
720 288 100       1515 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         718 my ($vol,$dirs,$file);
725 288 100       756 if ( defined $alt ) { # It's a local-OS path
726 161         472 ($vol,$dirs,$file) = File::Spec->splitpath( $alt,
727             $entry->is_dir );
728             } else {
729 127         471 ($vol,$dirs,$file) = File::Spec::Unix->splitpath( $name,
730             $entry->is_dir );
731             }
732              
733 288         827 my $dir;
734             ### is $name an absolute path? ###
735 288 100 66     4673 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     263 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         781 $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     630161 : cwd();
755              
756 208 100       4703 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     1716 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 117 100       364 if( grep { $_ eq '..' } @dirs ) {
  108         275  
768              
769 1         24 $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         19 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 116         307 my $full_path = $cwd;
783 116         330 for my $d ( @dirs ) {
784 104         709 $full_path = File::Spec->catdir( $full_path, $d );
785              
786             ### we've already checked this one, and it's safe. Move on.
787 104 100 100     659 next if ref $self and $self->{_link_cache}->{$full_path};
788              
789 14 100       487 if( -l $full_path ) {
790 2         139 my $to = readlink $full_path;
791 2         10 my $diag = "symlinked directory ($full_path => $to)";
792              
793 2         12 $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         15 return;
800             }
801              
802             ### XXX keep a cache if possible, so the stats become cheaper:
803 12 100       113 $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         272 map { length() ? VMS::Filespec::vmsify($_.'/') : $_ } @dirs if ON_VMS;
812              
813 205         7525 my ($cwd_vol,$cwd_dir,$cwd_file)
814             = File::Spec->splitpath( $cwd );
815 205         1921 my @cwd = File::Spec->splitdir( $cwd_dir );
816 205 50       817 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         4835 $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       1054 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     13329 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       956 unless ( -d _ ) {
848 12         44 eval { File::Path::mkpath( $dir, 0, 0777 ) };
  12         6191  
849 12 100       109 if( $@ ) {
850 1         17 my $fp = $entry->full_path;
851 1         21 $self->_error(qq[Could not create directory '$dir' for '$fp': $@]);
852 1         4 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       2613 return 1 if $entry->is_dir;
869              
870 266         3351 my $full = File::Spec->catfile( $dir, $file );
871              
872 266 50       1432 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     5717 if (-l $full || -e _) {
886 9 50       1937 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     855 if( length $entry->type && $entry->is_file ) {
892 260         4270 my $fh = IO::File->new;
893 260 50       18677 $fh->open( $full, '>' ) or (
894             $self->_error( qq[Could not open file '$full': $!] ),
895             return
896             );
897              
898 260 100       56552 if( $entry->size ) {
899 234         710 binmode $fh;
900 234         506 my $offset = 0;
901 234         1441 my $content = $entry->get_content_by_ref();
902 234         564 while ($offset < $entry->size) {
903 16827         208835 my $written
904             = syswrite $fh, $$content, $EXTRACT_BLOCK_SIZE, $offset;
905 16827 50       27307 if (defined $written) {
906 16827         33734 $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       4408 close $fh or (
915             $self->_error( qq[Could not close file '$full'] ),
916             return
917             );
918              
919             } else {
920 6 50       200 $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     7296 if( not -l $full and not ( $entry->is_hardlink and ON_UNIX and $EXTRACT_HARDLINK ) ) {
      33        
      66        
927 260 50       1490 utime time, $entry->mtime - TIME_OFFSET, $full or
928             $self->_error( qq[Could not update timestamp] );
929             }
930              
931 266 100 33     3284 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       858 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     5341 if( $CHMOD and not -l $full and not ( $entry->is_hardlink and ON_UNIX and $EXTRACT_HARDLINK ) ) {
      33        
      66        
939 260         1035 my $mode = $entry->mode;
940 260 50       623 unless ($SAME_PERMISSIONS) {
941 0         0 $mode &= ~(oct(7000) | umask);
942             }
943 260 50       5159 CORE::chmod( $mode, $full ) or
944             $self->_error( qq[Could not chown '$full' to ] . $entry->mode );
945             }
946              
947 266         7505 return 1;
948             }
949              
950             sub _make_special_file {
951 6     6   90 my $self = shift;
952 6 50       28 my $entry = shift or return;
953 6 50       14 my $file = shift; return unless defined $file;
  6         16  
954              
955 6         24 my $err;
956              
957 6 50 0     34 if( $entry->is_symlink ) {
    0          
    0          
    0          
    0          
958 6 100       36 if( !$INSECURE_EXTRACT_MODE ) {
959 2         14 my $linkname = $entry->linkname;
960 2 50       18 if( File::Spec->file_name_is_absolute($linkname) ) {
961 0         0 $self->_error( qq[Symlink '] . $entry->full_path .
962             qq[' has absolute target. Not extracting under SECURE EXTRACT MODE] );
963 0         0 return;
964             }
965 2 50       13 if( grep { $_ eq '..' } File::Spec->splitdir($linkname) ) {
  2         10  
966 0         0 $self->_error( qq[Symlink '] . $entry->full_path .
967             qq[' target attempts traversal. Not extracting under SECURE EXTRACT MODE] );
968 0         0 return;
969             }
970             }
971 6         93 my $fail;
972 6         10 if( ON_UNIX ) {
973 6 50       30 symlink( $entry->linkname, $file ) or $fail++;
974              
975             } else {
976             $self->_extract_special_file_as_plain_file( $entry, $file )
977             or $fail++;
978             }
979              
980 6 50       31 $err = qq[Making symbolic link '$file' to '] .
981             $entry->linkname .q[' failed] if $fail;
982              
983             } elsif ( $entry->is_hardlink ) {
984 0 0       0 if( !$INSECURE_EXTRACT_MODE ) {
985 0         0 my $linkname = $entry->linkname;
986 0 0       0 if( File::Spec->file_name_is_absolute($linkname) ) {
987 0         0 $self->_error( qq[Hardlink '] . $entry->full_path .
988             qq[' has absolute target '$linkname'. Not extracting ] .
989             qq[under SECURE EXTRACT MODE: extraction itself chmods ] .
990             qq[the shared inode.] );
991 0         0 return;
992             }
993 0 0       0 if( grep { $_ eq '..' } File::Spec->splitdir($linkname) ) {
  0         0  
994 0         0 $self->_error( qq[Hardlink '] . $entry->full_path .
995             qq[' target '$linkname' attempts traversal. Not ] .
996             qq[extracting under SECURE EXTRACT MODE: extraction ] .
997             qq[itself chmods the shared inode.] );
998 0         0 return;
999             }
1000             }
1001 0         0 my $fail;
1002 0 0       0 if( ON_UNIX && $EXTRACT_HARDLINK ) {
1003 0 0       0 link( $entry->linkname, $file ) or $fail++;
1004              
1005             } else {
1006 0 0       0 $self->_extract_special_file_as_plain_file( $entry, $file )
1007             or $fail++;
1008             }
1009              
1010 0 0       0 $err = qq[Making hard link from '] . $entry->linkname .
1011             qq[' to '$file' failed] if $fail;
1012              
1013             } elsif ( $entry->is_fifo ) {
1014 0 0       0 ON_UNIX && !system('mknod', $file, 'p') or
1015             $err = qq[Making fifo ']. $entry->name .qq[' failed];
1016              
1017             } elsif ( $entry->is_blockdev or $entry->is_chardev ) {
1018 0 0       0 my $mode = $entry->is_blockdev ? 'b' : 'c';
1019              
1020 0 0       0 ON_UNIX && !system('mknod', $file, $mode,
1021             $entry->devmajor, $entry->devminor) or
1022             $err = qq[Making block device ']. $entry->name .qq[' (maj=] .
1023             $entry->devmajor . qq[ min=] . $entry->devminor .
1024             qq[) failed.];
1025              
1026             } elsif ( $entry->is_socket ) {
1027             ### the original doesn't do anything special for sockets.... ###
1028 0         0 1;
1029             }
1030              
1031 6 50       30 return $err ? $self->_error( $err ) : 1;
1032             }
1033              
1034             ### don't know how to make symlinks, let's just extract the file as
1035             ### a plain file
1036             sub _extract_special_file_as_plain_file {
1037 0     0   0 my $self = shift;
1038 0 0       0 my $entry = shift or return;
1039 0 0       0 my $file = shift; return unless defined $file;
  0         0  
1040              
1041 0         0 my $err;
1042             TRY: {
1043 0         0 my $orig = $self->_find_entry( $entry->linkname, $entry );
  0         0  
1044              
1045 0 0       0 unless( $orig ) {
1046 0         0 $err = qq[Could not find file '] . $entry->linkname .
1047             qq[' in memory.];
1048 0         0 last TRY;
1049             }
1050              
1051             ### clone the entry, make it appear as a normal file ###
1052 0         0 my $clone = $orig->clone;
1053 0         0 $clone->_downgrade_to_plainfile;
1054 0 0       0 $self->_extract_file( $clone, $file ) or last TRY;
1055              
1056 0         0 return 1;
1057             }
1058              
1059 0         0 return $self->_error($err);
1060             }
1061              
1062             =head2 $tar->list_files( [\@properties] )
1063              
1064             Returns a list of the names of all the files in the archive.
1065              
1066             If C is passed an array reference as its first argument
1067             it returns a list of hash references containing the requested
1068             properties of each file. The following list of properties is
1069             supported: name, size, mtime (last modified date), mode, uid, gid,
1070             linkname, uname, gname, devmajor, devminor, prefix.
1071              
1072             Passing an array reference containing only one element, 'name', is
1073             special cased to return a list of names rather than a list of hash
1074             references, making it equivalent to calling C without
1075             arguments.
1076              
1077             =cut
1078              
1079             sub list_files {
1080 38     38 1 338 my $self = shift;
1081 38   50     344 my $aref = shift || [ ];
1082              
1083 38 50       159 unless( $self->_data ) {
1084 0 0       0 $self->read() or return;
1085             }
1086              
1087 38 50 0     215 if( @$aref == 0 or ( @$aref == 1 and $aref->[0] eq 'name' ) ) {
      33        
1088 38         85 return map { $_->full_path } @{$self->_data};
  137         305  
  38         66  
1089             } else {
1090              
1091             #my @rv;
1092             #for my $obj ( @{$self->_data} ) {
1093             # push @rv, { map { $_ => $obj->$_() } @$aref };
1094             #}
1095             #return @rv;
1096              
1097             ### this does the same as the above.. just needs a +{ }
1098             ### to make sure perl doesn't confuse it for a block
1099 0         0 return map { my $o=$_;
1100 0         0 +{ map { $_ => $o->$_() } @$aref }
  0         0  
1101 0         0 } @{$self->_data};
  0         0  
1102             }
1103             }
1104              
1105             sub _find_entry {
1106 218     218   10536 my $self = shift;
1107 218         842 my $file = shift;
1108              
1109 218 50       774 unless( defined $file ) {
1110 0         0 $self->_error( qq[No file specified] );
1111 0         0 return;
1112             }
1113              
1114             ### it's an object already
1115 218 100       2799 return $file if UNIVERSAL::isa( $file, 'Archive::Tar::File' );
1116              
1117             seach_entry:
1118 202 50       1243 if($self->_data){
1119 202         258 for my $entry ( @{$self->_data} ) {
  202         507  
1120 510         1125 my $path = $entry->full_path;
1121 510 100       2243 return $entry if $path eq $file;
1122             }
1123             }
1124              
1125 3 50       34 if($Archive::Tar::RESOLVE_SYMLINK!~/none/){
1126 3 50       12 if(my $link_entry = shift()){#fallback mode when symlinks are using relative notations ( ../a/./b/text.bin )
1127 0         0 $file = _symlinks_resolver( $link_entry->name, $file );
1128 0 0       0 goto seach_entry if $self->_data;
1129              
1130             #this will be slower than never, but won't failed!
1131              
1132 0         0 my $iterargs = $link_entry->{'_archive'};
1133 0 0 0     0 if($Archive::Tar::RESOLVE_SYMLINK=~/speed/ && @$iterargs==3){
1134             #faster but whole archive will be read in memory
1135             #read whole archive and share data
1136 0         0 my $archive = Archive::Tar->new;
1137 0         0 $archive->read( @$iterargs );
1138 0         0 push @$iterargs, $archive; #take a trace for destruction
1139 0 0       0 if($archive->_data){
1140 0         0 $self->_data( $archive->_data );
1141 0         0 goto seach_entry;
1142             }
1143             }#faster
1144              
1145             {#slower but lower memory usage
1146             # $iterargs = [$filename, $compressed, $opts];
1147 0         0 my $next = Archive::Tar->iter( @$iterargs );
  0         0  
1148 0         0 while(my $e = $next->()){
1149 0 0       0 if($e->full_path eq $file){
1150 0         0 undef $next;
1151 0         0 return $e;
1152             }
1153             }
1154             }#slower
1155             }
1156             }
1157              
1158 3         14 $self->_error( qq[No such file in archive: '$file'] );
1159 3         10 return;
1160             }
1161              
1162             =head2 $tar->get_files( [@filenames] )
1163              
1164             Returns the C objects matching the filenames
1165             provided. If no filename list was passed, all C
1166             objects in the current Tar object are returned.
1167              
1168             Please refer to the C documentation on how to
1169             handle these objects.
1170              
1171             =cut
1172              
1173             sub get_files {
1174 109     109 1 8025 my $self = shift;
1175              
1176 109 100       524 return @{ $self->_data } unless @_;
  105         633  
1177              
1178 4         5 my @list;
1179 4         13 for my $file ( @_ ) {
1180 4         9 push @list, grep { defined } $self->_find_entry( $file );
  2         5  
1181             }
1182              
1183 4         14 return @list;
1184             }
1185              
1186             =head2 $tar->get_content( $file )
1187              
1188             Return the content of the named file.
1189              
1190             =cut
1191              
1192             sub get_content {
1193 11     11 1 3333 my $self = shift;
1194 11 50       62 my $entry = $self->_find_entry( shift ) or return;
1195              
1196 11         29 return $entry->data;
1197             }
1198              
1199             =head2 $tar->replace_content( $file, $content )
1200              
1201             Make the string $content be the content for the file named $file.
1202              
1203             =cut
1204              
1205             sub replace_content {
1206 1     1 1 2 my $self = shift;
1207 1 50       2 my $entry = $self->_find_entry( shift ) or return;
1208              
1209 1         3 return $entry->replace_content( shift );
1210             }
1211              
1212             =head2 $tar->rename( $file, $new_name )
1213              
1214             Rename the file of the in-memory archive to $new_name.
1215              
1216             Note that you must specify a Unix path for $new_name, since per tar
1217             standard, all files in the archive must be Unix paths.
1218              
1219             Returns true on success and false on failure.
1220              
1221             =cut
1222              
1223             sub rename {
1224 2     2 1 258 my $self = shift;
1225 2 50       5 my $file = shift; return unless defined $file;
  2         8  
1226 2 50       4 my $new = shift; return unless defined $new;
  2         5  
1227              
1228 2 50       6 my $entry = $self->_find_entry( $file ) or return;
1229              
1230 2         9 return $entry->rename( $new );
1231             }
1232              
1233             =head2 $tar->chmod( $file, $mode )
1234              
1235             Change mode of $file to $mode.
1236              
1237             Returns true on success and false on failure.
1238              
1239             =cut
1240              
1241             sub chmod {
1242 1     1 1 3 my $self = shift;
1243 1 50       3 my $file = shift; return unless defined $file;
  1         4  
1244 1 50 33     2 my $mode = shift; return unless defined $mode && $mode =~ /^[0-7]{1,4}$/;
  1         12  
1245 1         5 my @args = ("$mode");
1246              
1247 1 50       5 my $entry = $self->_find_entry( $file ) or return;
1248 1         5 my $x = $entry->chmod( @args );
1249 1         16 return $x;
1250             }
1251              
1252             =head2 $tar->chown( $file, $uname [, $gname] )
1253              
1254             Change owner $file to $uname and $gname.
1255              
1256             Returns true on success and false on failure.
1257              
1258             =cut
1259              
1260             sub chown {
1261 2     2 1 6 my $self = shift;
1262 2 50       4 my $file = shift; return unless defined $file;
  2         8  
1263 2 50       4 my $uname = shift; return unless defined $uname;
  2         5  
1264 2         6 my @args = ($uname);
1265 2         5 push(@args, shift);
1266              
1267 2 50       7 my $entry = $self->_find_entry( $file ) or return;
1268 2         8 my $x = $entry->chown( @args );
1269 2         12 return $x;
1270             }
1271              
1272             =head2 $tar->remove (@filenamelist)
1273              
1274             Removes any entries with names matching any of the given filenames
1275             from the in-memory archive. Returns a list of C
1276             objects that remain.
1277              
1278             =cut
1279              
1280             sub remove {
1281 1     1 1 368 my $self = shift;
1282 1         4 my @list = @_;
1283              
1284 1         2 my %seen = map { $_->full_path => $_ } @{$self->_data};
  5         8  
  1         2  
1285 1         3 delete $seen{ $_ } for @list;
1286              
1287 1         5 $self->_data( [values %seen] );
1288              
1289 1         6 return values %seen;
1290             }
1291              
1292             =head2 $tar->clear
1293              
1294             C clears the current in-memory archive. This effectively gives
1295             you a 'blank' object, ready to be filled again. Note that C
1296             only has effect on the object, not the underlying tarfile.
1297              
1298             =cut
1299              
1300             sub clear {
1301 2 50   2 1 660 my $self = shift or return;
1302              
1303 2         13 $self->_data( [] );
1304 2         9 $self->_file( '' );
1305              
1306 2         21 return 1;
1307             }
1308              
1309              
1310             =head2 $tar->write ( [$file, $compressed, $prefix] )
1311              
1312             Write the in-memory archive to disk. The first argument can either
1313             be the name of a file or a reference to an already open filehandle (a
1314             GLOB reference).
1315              
1316             The second argument is used to indicate compression. You can
1317             compress using C, C or C. If you pass a digit, it's assumed
1318             to be the C compression level (between 1 and 9), but the use of
1319             constants is preferred:
1320              
1321             # write a gzip compressed file
1322             $tar->write( 'out.tgz', COMPRESS_GZIP );
1323              
1324             # write a bzip compressed file
1325             $tar->write( 'out.tbz', COMPRESS_BZIP );
1326              
1327             # write a xz compressed file
1328             $tar->write( 'out.txz', COMPRESS_XZ );
1329              
1330             Note that when you pass in a filehandle, the compression argument
1331             is ignored, as all files are printed verbatim to your filehandle.
1332             If you wish to enable compression with filehandles, use an
1333             C, C or C filehandle instead.
1334              
1335             The third argument is an optional prefix. All files will be tucked
1336             away in the directory you specify as prefix. So if you have files
1337             'a' and 'b' in your archive, and you specify 'foo' as prefix, they
1338             will be written to the archive as 'foo/a' and 'foo/b'.
1339              
1340             If no arguments are given, C returns the entire formatted
1341             archive as a string, which could be useful if you'd like to stuff the
1342             archive into a socket or a pipe to gzip or something.
1343              
1344              
1345             =cut
1346              
1347             sub write {
1348 33     33 1 5125 my $self = shift;
1349 33 100       150 my $file = shift; $file = '' unless defined $file;
  33         257  
1350 33   100     213 my $gzip = shift || 0;
1351 33 50       79 my $ext_prefix = shift; $ext_prefix = '' unless defined $ext_prefix;
  33         167  
1352 33         97 my $dummy = '';
1353              
1354             ### only need a handle if we have a file to print to ###
1355             my $handle = length($file)
1356             ? ( $self->_get_handle($file, $gzip, WRITE_ONLY->($gzip) )
1357             or return )
1358 33 0 50     324 : $HAS_PERLIO ? do { open my $h, '>', \$dummy; $h }
  3 50       51  
  3 100       7  
1359             : $HAS_IO_STRING ? IO::String->new
1360             : __PACKAGE__->no_string_support();
1361              
1362             ### Addresses: #41798: Nonempty $\ when writing a TAR file produces a
1363             ### corrupt TAR file. Must clear out $\ to make sure no garbage is
1364             ### printed to the archive
1365 33         187 local $\;
1366              
1367 33         208 for my $entry ( @{$self->_data} ) {
  33         141  
1368             ### entries to be written to the tarfile ###
1369 74         1571 my @write_me;
1370              
1371             ### only now will we change the object to reflect the current state
1372             ### of the name and prefix fields -- this needs to be limited to
1373             ### write() only!
1374 74         305 my $clone = $entry->clone;
1375              
1376              
1377             ### so, if you don't want use to use the prefix, we'll stuff
1378             ### everything in the name field instead
1379 74 100       207 if( $DO_NOT_USE_PREFIX ) {
1380              
1381             ### you might have an extended prefix, if so, set it in the clone
1382             ### XXX is ::Unix right?
1383 4 50       28 $clone->name( length $ext_prefix
1384             ? File::Spec::Unix->catdir( $ext_prefix,
1385             $clone->full_path)
1386             : $clone->full_path );
1387 4         14 $clone->prefix( '' );
1388              
1389             ### otherwise, we'll have to set it properly -- prefix part in the
1390             ### prefix and name part in the name field.
1391             } else {
1392              
1393             ### split them here, not before!
1394 70         317 my ($prefix,$name) = $clone->_prefix_and_file( $clone->full_path );
1395              
1396             ### you might have an extended prefix, if so, set it in the clone
1397             ### XXX is ::Unix right?
1398 70 50       180 $prefix = File::Spec::Unix->catdir( $ext_prefix, $prefix )
1399             if length $ext_prefix;
1400              
1401 70         163 $clone->prefix( $prefix );
1402 70         166 $clone->name( $name );
1403             }
1404              
1405             ### names are too long, and will get truncated if we don't add a
1406             ### '@LongLink' file...
1407 74   100     152 my $make_longlink = ( length($clone->name) > NAME_LENGTH or
1408             length($clone->prefix) > PREFIX_LENGTH
1409             ) || 0;
1410              
1411             ### perhaps we need to make a longlink file?
1412 74 100       187 if( $make_longlink ) {
1413 9         19 my $longlink = Archive::Tar::File->new(
1414             data => LONGLINK_NAME,
1415             $clone->full_path,
1416             { type => LONGLINK }
1417             );
1418              
1419 9 50       31 unless( $longlink ) {
1420 0         0 $self->_error( qq[Could not create 'LongLink' entry for ] .
1421             qq[oversize file '] . $clone->full_path ."'" );
1422 0         0 return;
1423             };
1424              
1425 9         17 push @write_me, $longlink;
1426             }
1427              
1428 74         190 push @write_me, $clone;
1429              
1430             ### write the one, optionally 2 a::t::file objects to the handle
1431 74         140 for my $clone (@write_me) {
1432              
1433             ### if the file is a symlink, there are 2 options:
1434             ### either we leave the symlink intact, but then we don't write any
1435             ### data OR we follow the symlink, which means we actually make a
1436             ### copy. if we do the latter, we have to change the TYPE of the
1437             ### clone to 'FILE'
1438 83   66     506 my $link_ok = $clone->is_symlink && $Archive::Tar::FOLLOW_SYMLINK;
1439 83   100     164 my $data_ok = !$clone->is_symlink && $clone->has_content;
1440              
1441             ### downgrade to a 'normal' file if it's a symlink we're going to
1442             ### treat as a regular file
1443 83 50       174 $clone->_downgrade_to_plainfile if $link_ok;
1444              
1445             ### get the header for this block
1446 83         268 my $header = $self->_format_tar_entry( $clone );
1447 83 50       177 unless( $header ) {
1448 0         0 $self->_error(q[Could not format header for: ] .
1449             $clone->full_path );
1450 0         0 return;
1451             }
1452              
1453 83 50       622 unless( print $handle $header ) {
1454 0         0 $self->_error(q[Could not write header for: ] .
1455             $clone->full_path);
1456 0         0 return;
1457             }
1458              
1459 83 100 66     6171 if( $link_ok or $data_ok ) {
1460 70 50       212 unless( print $handle $clone->data ) {
1461 0         0 $self->_error(q[Could not write data for: ] .
1462             $clone->full_path);
1463 0         0 return;
1464             }
1465              
1466             ### pad the end of the clone if required ###
1467 70 50       7090 print $handle TAR_PAD->( $clone->size ) if $clone->size % BLOCK
1468             }
1469              
1470             } ### done writing these entries
1471             }
1472              
1473             ### write the end markers ###
1474 33 50       1773 print $handle TAR_END x 2 or
1475             return $self->_error( qq[Could not write tar end markers] );
1476              
1477             ### did you want it written to a file, or returned as a string? ###
1478             my $rv = length($file) ? 1
1479             : $HAS_PERLIO ? $dummy
1480 33 50       1784 : do { seek $handle, 0, 0; local $/; <$handle> };
  0 100       0  
  0         0  
  0         0  
1481              
1482             ### make sure to close the handle if we created it
1483 33 50       155 if ( $file ne $handle ) {
1484 33 50       1181 unless( close $handle ) {
1485 0         0 $self->_error( qq[Could not write tar] );
1486 0         0 return;
1487             }
1488             }
1489              
1490 33         24031 return $rv;
1491             }
1492              
1493             sub _format_tar_entry {
1494 83     83   125 my $self = shift;
1495 83 50       180 my $entry = shift or return;
1496 83 50       118 my $ext_prefix = shift; $ext_prefix = '' unless defined $ext_prefix;
  83         216  
1497 83   50     487 my $no_prefix = shift || 0;
1498              
1499 83         175 my $file = $entry->name;
1500 83 50       156 my $prefix = $entry->prefix; $prefix = '' unless defined $prefix;
  83         147  
1501              
1502             ### remove the prefix from the file name
1503             ### not sure if this is still needed --kane
1504             ### no it's not -- Archive::Tar::File->_new_from_file will take care of
1505             ### this for us. Even worse, this would break if we tried to add a file
1506             ### like x/x.
1507             #if( length $prefix ) {
1508             # $file =~ s/^$match//;
1509             #}
1510              
1511 83 50       137 $prefix = File::Spec::Unix->catdir($ext_prefix, $prefix)
1512             if length $ext_prefix;
1513              
1514             ### not sure why this is... ###
1515 83         121 my $l = PREFIX_LENGTH; # is ambiguous otherwise...
1516 83 100       173 substr ($prefix, 0, -$l) = "" if length $prefix >= PREFIX_LENGTH;
1517              
1518 83 50       150 my $f1 = "%06o"; my $f2 = $ZERO_PAD_NUMBERS ? "%011o" : "%11o";
  83         220  
1519              
1520             ### this might be optimizable with a 'changed' flag in the file objects ###
1521             my $tar = pack (
1522             PACK,
1523             $file,
1524              
1525 249         545 (map { sprintf( $f1, $entry->$_() ) } qw[mode uid gid]),
1526 166         371 (map { sprintf( $f2, $entry->$_() ) } qw[size mtime]),
1527              
1528             "", # checksum field - space padded a bit down
1529              
1530 249         476 (map { $entry->$_() } qw[type linkname magic]),
1531              
1532             $entry->version || TAR_VERSION,
1533              
1534 166         353 (map { $entry->$_() } qw[uname gname]),
1535 83 50 50     159 (map { sprintf( $f1, $entry->$_() ) } qw[devmajor devminor]),
  166         366  
1536              
1537             ($no_prefix ? '' : $prefix)
1538             );
1539              
1540             ### add the checksum ###
1541 83 50       265 my $checksum_fmt = $ZERO_PAD_NUMBERS ? "%06o\0" : "%06o\0";
1542 83         501 substr($tar,148,7) = sprintf("%6o\0", unpack("%16C*",$tar));
1543              
1544 83         206 return $tar;
1545             }
1546              
1547             =head2 $tar->add_files( @filenamelist )
1548              
1549             Takes a list of filenames and adds them to the in-memory archive.
1550              
1551             The path to the file is automatically converted to a Unix like
1552             equivalent for use in the archive, and, if on MacOS, the file's
1553             modification time is converted from the MacOS epoch to the Unix epoch.
1554             So tar archives created on MacOS with B can be read
1555             both with I on Unix and applications like I or
1556             I on MacOS.
1557              
1558             Be aware that the file's type/creator and resource fork will be lost,
1559             which is usually what you want in cross-platform archives.
1560              
1561             Instead of a filename, you can also pass it an existing C
1562             object from, for example, another archive. The object will be clone, and
1563             effectively be a copy of the original, not an alias.
1564              
1565             Returns a list of C objects that were just added.
1566              
1567             =cut
1568              
1569             sub add_files {
1570 25     25 1 5324 my $self = shift;
1571 25 50       194 my @files = @_ or return;
1572              
1573 25         39 my @rv;
1574 25         201 for my $file ( @files ) {
1575              
1576             ### you passed an Archive::Tar::File object
1577             ### clone it so we don't accidentally have a reference to
1578             ### an object from another archive
1579 29 100       265 if( UNIVERSAL::isa( $file,'Archive::Tar::File' ) ) {
1580 7         20 push @rv, $file->clone;
1581 7         12 next;
1582             }
1583              
1584 22         72 eval {
1585 22 50       134 if( utf8::is_utf8( $file )) {
1586 0         0 utf8::encode( $file );
1587             }
1588             };
1589              
1590 22 50 33     511 unless( -e $file || -l $file ) {
1591 0         0 $self->_error( qq[No such file: '$file'] );
1592 0         0 next;
1593             }
1594              
1595 22         206 my $obj = Archive::Tar::File->new( file => $file );
1596 22 50       82 unless( $obj ) {
1597 0         0 $self->_error( qq[Unable to add file: '$file'] );
1598 0         0 next;
1599             }
1600              
1601 22         96 push @rv, $obj;
1602             }
1603              
1604 25         42 push @{$self->{_data}}, @rv;
  25         99  
1605              
1606 25         101 return @rv;
1607             }
1608              
1609             =head2 $tar->add_data ( $filename, $data, [$opthashref] )
1610              
1611             Takes a filename, a scalar full of data and optionally a reference to
1612             a hash with specific options.
1613              
1614             Will add a file to the in-memory archive, with name C<$filename> and
1615             content C<$data>. Specific properties can be set using C<$opthashref>.
1616             The following list of properties is supported: name, size, mtime
1617             (last modified date), mode, uid, gid, linkname, uname, gname,
1618             devmajor, devminor, prefix, type. (On MacOS, the file's path and
1619             modification times are converted to Unix equivalents.)
1620              
1621             Valid values for the file type are the following constants defined by
1622             Archive::Tar::Constant:
1623              
1624             =over 4
1625              
1626             =item FILE
1627              
1628             Regular file.
1629              
1630             =item HARDLINK
1631              
1632             =item SYMLINK
1633              
1634             Hard and symbolic ("soft") links; linkname should specify target.
1635              
1636             =item CHARDEV
1637              
1638             =item BLOCKDEV
1639              
1640             Character and block devices. devmajor and devminor should specify the major
1641             and minor device numbers.
1642              
1643             =item DIR
1644              
1645             Directory.
1646              
1647             =item FIFO
1648              
1649             FIFO (named pipe).
1650              
1651             =item SOCKET
1652              
1653             Socket.
1654              
1655             =back
1656              
1657             Returns the C object that was just added, or
1658             C on failure.
1659              
1660             =cut
1661              
1662             sub add_data {
1663 14     14 1 5656 my $self = shift;
1664 14         51 my ($file, $data, $opt) = @_;
1665              
1666 14         82 my $obj = Archive::Tar::File->new( data => $file, $data, $opt );
1667 14 100       28 unless( $obj ) {
1668 1         6 $self->_error( qq[Unable to add file: '$file'] );
1669 1         4 return;
1670             }
1671              
1672 13         14 push @{$self->{_data}}, $obj;
  13         33  
1673              
1674 13         35 return $obj;
1675             }
1676              
1677             =head2 $tar->error( [$BOOL] )
1678              
1679             Returns the current error string (usually, the last error reported).
1680             If a true value was specified, it will give the C
1681             equivalent of the error, in effect giving you a stacktrace.
1682              
1683             For backwards compatibility, this error is also available as
1684             C<$Archive::Tar::error> although it is much recommended you use the
1685             method call instead.
1686              
1687             =cut
1688              
1689             {
1690             $error = '';
1691             my $longmess;
1692              
1693             sub _error {
1694 15     15   29 my $self = shift;
1695 15         55 my $msg = $error = shift;
1696 15         4727 $longmess = Carp::longmess($error);
1697 15 50       111 if (ref $self) {
1698 15         66 $self->{_error} = $error;
1699 15         77 $self->{_longmess} = $longmess;
1700             }
1701              
1702             ### set Archive::Tar::WARN to 0 to disable printing
1703             ### of errors
1704 15 100       46 if( $WARN ) {
1705 6 50       1180 carp $DEBUG ? $longmess : $msg;
1706             }
1707              
1708 15         81 return;
1709             }
1710              
1711             sub error {
1712 22     22 1 3791 my $self = shift;
1713 22 100       83 if (ref $self) {
1714 20 50       225 return shift() ? $self->{_longmess} : $self->{_error};
1715             } else {
1716 2 50       14 return shift() ? $longmess : $error;
1717             }
1718             }
1719             }
1720              
1721             =head2 $tar->setcwd( $cwd );
1722              
1723             C needs to know the current directory, and it will run
1724             C I time it extracts a I entry from the
1725             tarfile and saves it in the file system. (As of version 1.30, however,
1726             C will use the speed optimization described below
1727             automatically, so it's only relevant if you're using C).
1728              
1729             Since C doesn't change the current directory internally
1730             while it is extracting the items in a tarball, all calls to C
1731             can be avoided if we can guarantee that the current directory doesn't
1732             get changed externally.
1733              
1734             To use this performance boost, set the current directory via
1735              
1736             use Cwd;
1737             $tar->setcwd( cwd() );
1738              
1739             once before calling a function like C and
1740             C will use the current directory setting from then on
1741             and won't call C internally.
1742              
1743             To switch back to the default behaviour, use
1744              
1745             $tar->setcwd( undef );
1746              
1747             and C will call C internally again.
1748              
1749             If you're using C's C method, C will
1750             be called for you.
1751              
1752             =cut
1753              
1754             sub setcwd {
1755 0     0 1 0 my $self = shift;
1756 0         0 my $cwd = shift;
1757              
1758 0         0 $self->{cwd} = $cwd;
1759             }
1760              
1761             =head1 Class Methods
1762              
1763             =head2 Archive::Tar->create_archive($file, $compressed, @filelist)
1764              
1765             Creates a tar file from the list of files provided. The first
1766             argument can either be the name of the tar file to create or a
1767             reference to an open file handle (e.g. a GLOB reference).
1768              
1769             The second argument is used to indicate compression. You can
1770             compress using C, C or C. If you pass a digit, it's assumed
1771             to be the C compression level (between 1 and 9), but the use of
1772             constants is preferred:
1773              
1774             # write a gzip compressed file
1775             Archive::Tar->create_archive( 'out.tgz', COMPRESS_GZIP, @filelist );
1776              
1777             # write a bzip compressed file
1778             Archive::Tar->create_archive( 'out.tbz', COMPRESS_BZIP, @filelist );
1779              
1780             # write a xz compressed file
1781             Archive::Tar->create_archive( 'out.txz', COMPRESS_XZ, @filelist );
1782              
1783             Note that when you pass in a filehandle, the compression argument
1784             is ignored, as all files are printed verbatim to your filehandle.
1785             If you wish to enable compression with filehandles, use an
1786             C, C or C filehandle instead.
1787              
1788             The remaining arguments list the files to be included in the tar file.
1789             These files must all exist. Any files which don't exist or can't be
1790             read are silently ignored.
1791              
1792             If the archive creation fails for any reason, C will
1793             return false. Please use the C method to find the cause of the
1794             failure.
1795              
1796             Note that this method does not write C as it were; it
1797             still reads all the files into memory before writing out the archive.
1798             Consult the FAQ below if this is a problem.
1799              
1800             =cut
1801              
1802             sub create_archive {
1803 9     9 1 51 my $class = shift;
1804              
1805 9 50       19 my $file = shift; return unless defined $file;
  9         63  
1806 9   100     60 my $gzip = shift || 0;
1807 9         51 my @files = @_;
1808              
1809 9 50       35 unless( @files ) {
1810 0         0 return $class->_error( qq[Cowardly refusing to create empty archive!] );
1811             }
1812              
1813 9         91 my $tar = $class->new;
1814 9         234 $tar->add_files( @files );
1815 9         110 return $tar->write( $file, $gzip );
1816             }
1817              
1818             =head2 Archive::Tar->iter( $filename, [ $compressed, {opt => $val} ] )
1819              
1820             Returns an iterator function that reads the tar file without loading
1821             it all in memory. Each time the function is called it will return the
1822             next file in the tarball. The files are returned as
1823             C objects. The iterator function returns the
1824             empty list once it has exhausted the files contained.
1825              
1826             The second argument can be a hash reference with options, which are
1827             identical to the arguments passed to C.
1828              
1829             Example usage:
1830              
1831             my $next = Archive::Tar->iter( "example.tar.gz", 1, {filter => qr/\.pm$/} );
1832              
1833             while( my $f = $next->() ) {
1834             print $f->name, "\n";
1835              
1836             $f->extract or warn "Extraction failed";
1837              
1838             # ....
1839             }
1840              
1841             =cut
1842              
1843              
1844             sub iter {
1845 15     15 1 20203 my $class = shift;
1846 15         32 my $filename = shift;
1847 15 50       54 return unless defined $filename;
1848 15   100     80 my $compressed = shift || 0;
1849 15   100     47 my $opts = shift || {};
1850              
1851             ### get a handle to read from.
1852 15 50       70 my $handle = $class->_get_handle(
1853             $filename,
1854             $compressed,
1855             READ_ONLY->( ZLIB )
1856             ) or return;
1857              
1858 15         29 my @data;
1859 15         36 my $CONSTRUCT_ARGS = [ $filename, $compressed, $opts ];
1860             return sub {
1861 35 100   35   7514 return shift(@data) if @data; # more than one file returned?
1862 33 50       66 return unless $handle; # handle exhausted?
1863              
1864             ### read data, should only return file
1865 33         298 my $tarfile = $class->_read_tar($handle, { %$opts, limit => 1 });
1866 33 50 33     252 @data = @$tarfile if ref $tarfile && ref $tarfile eq 'ARRAY';
1867 33 50       107 if($Archive::Tar::RESOLVE_SYMLINK!~/none/){
1868 33         120 foreach(@data){
1869             #may refine this heuristic for ON_UNIX?
1870 20 100       50 if($_->linkname){
1871             #is there a better slot to store/share it ?
1872 1         5 $_->{'_archive'} = $CONSTRUCT_ARGS;
1873             }
1874             }
1875             }
1876              
1877             ### return one piece of data
1878 33 100       104 return shift(@data) if @data;
1879              
1880             ### data is exhausted, free the filehandle
1881 15         202 undef $handle;
1882 15 50       2117 if(@$CONSTRUCT_ARGS == 4){
1883             #free archive in memory
1884 0         0 undef $CONSTRUCT_ARGS->[-1];
1885             }
1886 15         67 return;
1887 15         103 };
1888             }
1889              
1890             =head2 Archive::Tar->list_archive($file, $compressed, [\@properties])
1891              
1892             Returns a list of the names of all the files in the archive. The
1893             first argument can either be the name of the tar file to list or a
1894             reference to an open file handle (e.g. a GLOB reference).
1895              
1896             If C is passed an array reference as its third
1897             argument it returns a list of hash references containing the requested
1898             properties of each file. The following list of properties is
1899             supported: full_path, name, size, mtime (last modified date), mode,
1900             uid, gid, linkname, uname, gname, devmajor, devminor, prefix, type.
1901              
1902             See C for details about supported properties.
1903              
1904             Passing an array reference containing only one element, 'name', is
1905             special cased to return a list of names rather than a list of hash
1906             references.
1907              
1908             =cut
1909              
1910             sub list_archive {
1911 3     3 1 1848 my $class = shift;
1912 3 50       5 my $file = shift; return unless defined $file;
  3         10  
1913 3   50     20 my $gzip = shift || 0;
1914              
1915 3         14 my $tar = $class->new($file, $gzip);
1916 3 50       7 return unless $tar;
1917              
1918 3         26 return $tar->list_files( @_ );
1919             }
1920              
1921             =head2 Archive::Tar->extract_archive($file, $compressed)
1922              
1923             Extracts the contents of the tar file. The first argument can either
1924             be the name of the tar file to create or a reference to an open file
1925             handle (e.g. a GLOB reference). All relative paths in the tar file will
1926             be created underneath the current working directory.
1927              
1928             C will return a list of files it extracted.
1929             If the archive extraction fails for any reason, C
1930             will return false. Please use the C method to find the cause
1931             of the failure.
1932              
1933             =cut
1934              
1935             sub extract_archive {
1936 9     9 1 42 my $class = shift;
1937 9 50       20 my $file = shift; return unless defined $file;
  9         44  
1938 9   100     52 my $gzip = shift || 0;
1939              
1940 9 50       47 my $tar = $class->new( ) or return;
1941              
1942 9         93 return $tar->read( $file, $gzip, { extract => 1 } );
1943             }
1944              
1945             =head2 $bool = Archive::Tar->has_io_string
1946              
1947             Returns true if we currently have C support loaded.
1948              
1949             Either C or C support is needed to support writing
1950             stringified archives. Currently, C is the preferred method, if
1951             available.
1952              
1953             See the C section to see how to change this preference.
1954              
1955             =cut
1956              
1957 0     0 1 0 sub has_io_string { return $HAS_IO_STRING; }
1958              
1959             =head2 $bool = Archive::Tar->has_perlio
1960              
1961             Returns true if we currently have C support loaded.
1962              
1963             This requires C or higher, compiled with C
1964              
1965             Either C or C support is needed to support writing
1966             stringified archives. Currently, C is the preferred method, if
1967             available.
1968              
1969             See the C section to see how to change this preference.
1970              
1971             =cut
1972              
1973 0     0 1 0 sub has_perlio { return $HAS_PERLIO; }
1974              
1975             =head2 $bool = Archive::Tar->has_zlib_support
1976              
1977             Returns true if C can extract C compressed archives
1978              
1979             =cut
1980              
1981 6     6 1 215050 sub has_zlib_support { return ZLIB }
1982              
1983             =head2 $bool = Archive::Tar->has_bzip2_support
1984              
1985             Returns true if C can extract C compressed archives
1986              
1987             =cut
1988              
1989 6     6 1 29 sub has_bzip2_support { return BZIP }
1990              
1991             =head2 $bool = Archive::Tar->has_xz_support
1992              
1993             Returns true if C can extract C compressed archives
1994              
1995             =cut
1996              
1997 5     5 1 23 sub has_xz_support { return XZ }
1998              
1999             =head2 Archive::Tar->can_handle_compressed_files
2000              
2001             A simple checking routine, which will return true if C
2002             is able to uncompress compressed archives on the fly with C,
2003             C and C or false if not both are installed.
2004              
2005             You can use this as a shortcut to determine whether C
2006             will do what you think before passing compressed archives to its
2007             C method.
2008              
2009             =cut
2010              
2011 0     0 1   sub can_handle_compressed_files { return ZLIB && BZIP ? 1 : 0 }
2012              
2013             sub no_string_support {
2014 0     0 0   croak("You have to install IO::String to support writing archives to strings");
2015             }
2016              
2017             sub _symlinks_resolver{
2018 0     0     my ($src, $trg) = @_;
2019 0           my @src = split /[\/\\]/, $src;
2020 0           my @trg = split /[\/\\]/, $trg;
2021 0           pop @src; #strip out current object name
2022 0 0 0       if(@trg and $trg[0] eq ''){
2023 0           shift @trg;
2024             #restart path from scratch
2025 0           @src = ( );
2026             }
2027 0           foreach my $part ( @trg ){
2028 0 0         next if $part eq '.'; #ignore current
2029 0 0         if($part eq '..'){
2030             #got to parent
2031 0           pop @src;
2032             }
2033             else{
2034             #append it
2035 0           push @src, $part;
2036             }
2037             }
2038 0           my $path = join('/', @src);
2039 0 0         warn "_symlinks_resolver('$src','$trg') = $path" if $DEBUG;
2040 0           return $path;
2041             }
2042              
2043             1;
2044              
2045             __END__