File Coverage

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