xref: /openbsd-src/gnu/usr.bin/perl/cpan/Archive-Tar/lib/Archive/Tar/File.pm (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1b39c5158Smillertpackage Archive::Tar::File;
2b39c5158Smillertuse strict;
3b39c5158Smillert
4b39c5158Smillertuse Carp                ();
5b39c5158Smillertuse IO::File;
6b39c5158Smillertuse File::Spec::Unix    ();
7b39c5158Smillertuse File::Spec          ();
8b39c5158Smillertuse File::Basename      ();
9b39c5158Smillert
10b39c5158Smillertuse Archive::Tar::Constant;
11b39c5158Smillert
12b39c5158Smillertuse vars qw[@ISA $VERSION];
13b39c5158Smillert#@ISA        = qw[Archive::Tar];
14*3d61058aSafresh1$VERSION    = '3.02_001';
15b39c5158Smillert
16b39c5158Smillert### set value to 1 to oct() it during the unpack ###
17898184e3Ssthen
18b39c5158Smillertmy $tmpl = [
19898184e3Ssthen        name        => 0,   # string					A100
20898184e3Ssthen        mode        => 1,   # octal					A8
21898184e3Ssthen        uid         => 1,   # octal					A8
22898184e3Ssthen        gid         => 1,   # octal					A8
23898184e3Ssthen        size        => 0,   # octal	# cdrake - not *always* octal..	A12
24898184e3Ssthen        mtime       => 1,   # octal					A12
25898184e3Ssthen        chksum      => 1,   # octal					A8
26898184e3Ssthen        type        => 0,   # character					A1
27898184e3Ssthen        linkname    => 0,   # string					A100
28898184e3Ssthen        magic       => 0,   # string					A6
29898184e3Ssthen        version     => 0,   # 2 bytes					A2
30898184e3Ssthen        uname       => 0,   # string					A32
31898184e3Ssthen        gname       => 0,   # string					A32
32898184e3Ssthen        devmajor    => 1,   # octal					A8
33898184e3Ssthen        devminor    => 1,   # octal					A8
34898184e3Ssthen        prefix      => 0,	#					A155 x 12
35b39c5158Smillert
36b39c5158Smillert### end UNPACK items ###
37b39c5158Smillert        raw         => 0,   # the raw data chunk
38b39c5158Smillert        data        => 0,   # the data associated with the file --
39b39c5158Smillert                            # This  might be very memory intensive
40b39c5158Smillert];
41b39c5158Smillert
42b39c5158Smillert### install get/set accessors for this object.
43b39c5158Smillertfor ( my $i=0; $i<scalar @$tmpl ; $i+=2 ) {
44b39c5158Smillert    my $key = $tmpl->[$i];
45b39c5158Smillert    no strict 'refs';
46b39c5158Smillert    *{__PACKAGE__."::$key"} = sub {
47b39c5158Smillert        my $self = shift;
48b39c5158Smillert        $self->{$key} = $_[0] if @_;
49b39c5158Smillert
50b39c5158Smillert        ### just in case the key is not there or undef or something ###
51b39c5158Smillert        {   local $^W = 0;
52b39c5158Smillert            return $self->{$key};
53b39c5158Smillert        }
54b39c5158Smillert    }
55b39c5158Smillert}
56b39c5158Smillert
57b39c5158Smillert=head1 NAME
58b39c5158Smillert
59b39c5158SmillertArchive::Tar::File - a subclass for in-memory extracted file from Archive::Tar
60b39c5158Smillert
61b39c5158Smillert=head1 SYNOPSIS
62b39c5158Smillert
63b39c5158Smillert    my @items = $tar->get_files;
64b39c5158Smillert
65b39c5158Smillert    print $_->name, ' ', $_->size, "\n" for @items;
66b39c5158Smillert
67b39c5158Smillert    print $object->get_content;
68b39c5158Smillert    $object->replace_content('new content');
69b39c5158Smillert
70b39c5158Smillert    $object->rename( 'new/full/path/to/file.c' );
71b39c5158Smillert
72b39c5158Smillert=head1 DESCRIPTION
73b39c5158Smillert
74*3d61058aSafresh1Archive::Tar::File provides a neat little object layer for in-memory
75b39c5158Smillertextracted files. It's mostly used internally in Archive::Tar to tidy
76b39c5158Smillertup the code, but there's no reason users shouldn't use this API as
77b39c5158Smillertwell.
78b39c5158Smillert
79b39c5158Smillert=head2 Accessors
80b39c5158Smillert
81b39c5158SmillertA lot of the methods in this package are accessors to the various
82b39c5158Smillertfields in the tar header:
83b39c5158Smillert
84b39c5158Smillert=over 4
85b39c5158Smillert
86b39c5158Smillert=item name
87b39c5158Smillert
88b39c5158SmillertThe file's name
89b39c5158Smillert
90b39c5158Smillert=item mode
91b39c5158Smillert
92b39c5158SmillertThe file's mode
93b39c5158Smillert
94b39c5158Smillert=item uid
95b39c5158Smillert
96b39c5158SmillertThe user id owning the file
97b39c5158Smillert
98b39c5158Smillert=item gid
99b39c5158Smillert
100b39c5158SmillertThe group id owning the file
101b39c5158Smillert
102b39c5158Smillert=item size
103b39c5158Smillert
104b39c5158SmillertFile size in bytes
105b39c5158Smillert
106b39c5158Smillert=item mtime
107b39c5158Smillert
108b39c5158SmillertModification time. Adjusted to mac-time on MacOS if required
109b39c5158Smillert
110b39c5158Smillert=item chksum
111b39c5158Smillert
112b39c5158SmillertChecksum field for the tar header
113b39c5158Smillert
114b39c5158Smillert=item type
115b39c5158Smillert
116b39c5158SmillertFile type -- numeric, but comparable to exported constants -- see
117b39c5158SmillertArchive::Tar's documentation
118b39c5158Smillert
119b39c5158Smillert=item linkname
120b39c5158Smillert
121b39c5158SmillertIf the file is a symlink, the file it's pointing to
122b39c5158Smillert
123b39c5158Smillert=item magic
124b39c5158Smillert
125b39c5158SmillertTar magic string -- not useful for most users
126b39c5158Smillert
127b39c5158Smillert=item version
128b39c5158Smillert
129b39c5158SmillertTar version string -- not useful for most users
130b39c5158Smillert
131b39c5158Smillert=item uname
132b39c5158Smillert
133b39c5158SmillertThe user name that owns the file
134b39c5158Smillert
135b39c5158Smillert=item gname
136b39c5158Smillert
137b39c5158SmillertThe group name that owns the file
138b39c5158Smillert
139b39c5158Smillert=item devmajor
140b39c5158Smillert
141b39c5158SmillertDevice major number in case of a special file
142b39c5158Smillert
143b39c5158Smillert=item devminor
144b39c5158Smillert
145b39c5158SmillertDevice minor number in case of a special file
146b39c5158Smillert
147b39c5158Smillert=item prefix
148b39c5158Smillert
149b39c5158SmillertAny directory to prefix to the extraction path, if any
150b39c5158Smillert
151b39c5158Smillert=item raw
152b39c5158Smillert
153b39c5158SmillertRaw tar header -- not useful for most users
154b39c5158Smillert
155b39c5158Smillert=back
156b39c5158Smillert
157b39c5158Smillert=head1 Methods
158b39c5158Smillert
159b39c5158Smillert=head2 Archive::Tar::File->new( file => $path )
160b39c5158Smillert
161b39c5158SmillertReturns a new Archive::Tar::File object from an existing file.
162b39c5158Smillert
163b39c5158SmillertReturns undef on failure.
164b39c5158Smillert
165b39c5158Smillert=head2 Archive::Tar::File->new( data => $path, $data, $opt )
166b39c5158Smillert
167b39c5158SmillertReturns a new Archive::Tar::File object from data.
168b39c5158Smillert
169b39c5158SmillertC<$path> defines the file name (which need not exist), C<$data> the
170b39c5158Smillertfile contents, and C<$opt> is a reference to a hash of attributes
171b39c5158Smillertwhich may be used to override the default attributes (fields in the
172b39c5158Smillerttar header), which are described above in the Accessors section.
173b39c5158Smillert
174b39c5158SmillertReturns undef on failure.
175b39c5158Smillert
176b39c5158Smillert=head2 Archive::Tar::File->new( chunk => $chunk )
177b39c5158Smillert
178b39c5158SmillertReturns a new Archive::Tar::File object from a raw 512-byte tar
179b39c5158Smillertarchive chunk.
180b39c5158Smillert
181b39c5158SmillertReturns undef on failure.
182b39c5158Smillert
183b39c5158Smillert=cut
184b39c5158Smillert
185b39c5158Smillertsub new {
186b39c5158Smillert    my $class   = shift;
187b39c5158Smillert    my $what    = shift;
188b39c5158Smillert
189b39c5158Smillert    my $obj =   ($what eq 'chunk') ? __PACKAGE__->_new_from_chunk( @_ ) :
190b39c5158Smillert                ($what eq 'file' ) ? __PACKAGE__->_new_from_file( @_ ) :
191b39c5158Smillert                ($what eq 'data' ) ? __PACKAGE__->_new_from_data( @_ ) :
192b39c5158Smillert                undef;
193b39c5158Smillert
194b39c5158Smillert    return $obj;
195b39c5158Smillert}
196b39c5158Smillert
197b39c5158Smillert### copies the data, creates a clone ###
198b39c5158Smillertsub clone {
199b39c5158Smillert    my $self = shift;
200b39c5158Smillert    return bless { %$self }, ref $self;
201b39c5158Smillert}
202b39c5158Smillert
203b39c5158Smillertsub _new_from_chunk {
204b39c5158Smillert    my $class = shift;
205b39c5158Smillert    my $chunk = shift or return;    # 512 bytes of tar header
206b39c5158Smillert    my %hash  = @_;
207b39c5158Smillert
208b39c5158Smillert    ### filter any arguments on defined-ness of values.
209b39c5158Smillert    ### this allows overriding from what the tar-header is saying
210b39c5158Smillert    ### about this tar-entry. Particularly useful for @LongLink files
211b39c5158Smillert    my %args  = map { $_ => $hash{$_} } grep { defined $hash{$_} } keys %hash;
212b39c5158Smillert
213b39c5158Smillert    ### makes it start at 0 actually... :) ###
214b39c5158Smillert    my $i = -1;
215b39c5158Smillert    my %entry = map {
216898184e3Ssthen	my ($s,$v)=($tmpl->[++$i],$tmpl->[++$i]);	# cdrake
217898184e3Ssthen	($_)=($_=~/^([^\0]*)/) unless($s eq 'size');	# cdrake
218898184e3Ssthen	$s=> $v ? oct $_ : $_				# cdrake
219898184e3Ssthen	# $tmpl->[++$i] => $tmpl->[++$i] ? oct $_ : $_	# removed by cdrake - mucks up binary sizes >8gb
220898184e3Ssthen    } unpack( UNPACK, $chunk );				# cdrake
221898184e3Ssthen    # } map { /^([^\0]*)/ } unpack( UNPACK, $chunk );	# old - replaced now by cdrake
222898184e3Ssthen
223898184e3Ssthen
224898184e3Ssthen    if(substr($entry{'size'}, 0, 1) eq "\x80") {	# binary size extension for files >8gigs (> octal 77777777777777)	# cdrake
2256fb12b70Safresh1      my @sz=unpack("aCSNN",$entry{'size'}); $entry{'size'}=$sz[4]+(2**32)*$sz[3]+$sz[2]*(2**64);	# Use the low 80 bits (should use the upper 15 as well, but as at year 2011, that seems unlikely to ever be needed - the numbers are just too big...) # cdrake
226898184e3Ssthen    } else {	# cdrake
227898184e3Ssthen      ($entry{'size'})=($entry{'size'}=~/^([^\0]*)/); $entry{'size'}=oct $entry{'size'};	# cdrake
228898184e3Ssthen    }	# cdrake
229898184e3Ssthen
230b39c5158Smillert
231b39c5158Smillert    my $obj = bless { %entry, %args }, $class;
232b39c5158Smillert
233b39c5158Smillert	### magic is a filetype string.. it should have something like 'ustar' or
234b39c5158Smillert	### something similar... if the chunk is garbage, skip it
235b39c5158Smillert	return unless $obj->magic !~ /\W/;
236b39c5158Smillert
237b39c5158Smillert    ### store the original chunk ###
238b39c5158Smillert    $obj->raw( $chunk );
239b39c5158Smillert
240b39c5158Smillert    $obj->type(FILE) if ( (!length $obj->type) or ($obj->type =~ /\W/) );
241b39c5158Smillert    $obj->type(DIR)  if ( ($obj->is_file) && ($obj->name =~ m|/$|) );
242b39c5158Smillert
243b39c5158Smillert
244b39c5158Smillert    return $obj;
245b39c5158Smillert
246b39c5158Smillert}
247b39c5158Smillert
248b39c5158Smillertsub _new_from_file {
249b39c5158Smillert    my $class       = shift;
250b39c5158Smillert    my $path        = shift;
251b39c5158Smillert
252b39c5158Smillert    ### path has to at least exist
253b39c5158Smillert    return unless defined $path;
254b39c5158Smillert
255b39c5158Smillert    my $type        = __PACKAGE__->_filetype($path);
256b39c5158Smillert    my $data        = '';
257b39c5158Smillert
258b39c5158Smillert    READ: {
259b39c5158Smillert        unless ($type == DIR ) {
260b39c5158Smillert            my $fh = IO::File->new;
261b39c5158Smillert
262b39c5158Smillert            unless( $fh->open($path) ) {
263b39c5158Smillert                ### dangling symlinks are fine, stop reading but continue
264b39c5158Smillert                ### creating the object
265b39c5158Smillert                last READ if $type == SYMLINK;
266b39c5158Smillert
267b39c5158Smillert                ### otherwise, return from this function --
268b39c5158Smillert                ### anything that's *not* a symlink should be
269b39c5158Smillert                ### resolvable
270b39c5158Smillert                return;
271b39c5158Smillert            }
272b39c5158Smillert
273b39c5158Smillert            ### binmode needed to read files properly on win32 ###
274b39c5158Smillert            binmode $fh;
275b39c5158Smillert            $data = do { local $/; <$fh> };
276b39c5158Smillert            close $fh;
277b39c5158Smillert        }
278b39c5158Smillert    }
279b39c5158Smillert
280b39c5158Smillert    my @items       = qw[mode uid gid size mtime];
281b39c5158Smillert    my %hash        = map { shift(@items), $_ } (lstat $path)[2,4,5,7,9];
282b39c5158Smillert
283b39c5158Smillert    if (ON_VMS) {
284b39c5158Smillert        ### VMS has two UID modes, traditional and POSIX.  Normally POSIX is
285b39c5158Smillert        ### not used.  We currently do not have an easy way to see if we are in
286b39c5158Smillert        ### POSIX mode.  In traditional mode, the UID is actually the VMS UIC.
287b39c5158Smillert        ### The VMS UIC has the upper 16 bits is the GID, which in many cases
288b39c5158Smillert        ### the VMS UIC will be larger than 209715, the largest that TAR can
289b39c5158Smillert        ### handle.  So for now, assume it is traditional if the UID is larger
290b39c5158Smillert        ### than 0x10000.
291b39c5158Smillert
292b39c5158Smillert        if ($hash{uid} > 0x10000) {
293b39c5158Smillert            $hash{uid} = $hash{uid} & 0xFFFF;
294b39c5158Smillert        }
295b39c5158Smillert
296b39c5158Smillert        ### The file length from stat() is the physical length of the file
297b39c5158Smillert        ### However the amount of data read in may be more for some file types.
298b39c5158Smillert        ### Fixed length files are read past the logical EOF to end of the block
299b39c5158Smillert        ### containing.  Other file types get expanded on read because record
300b39c5158Smillert        ### delimiters are added.
301b39c5158Smillert
302b39c5158Smillert        my $data_len = length $data;
303b39c5158Smillert        $hash{size} = $data_len if $hash{size} < $data_len;
304b39c5158Smillert
305b39c5158Smillert    }
306b39c5158Smillert    ### you *must* set size == 0 on symlinks, or the next entry will be
307b39c5158Smillert    ### though of as the contents of the symlink, which is wrong.
308b39c5158Smillert    ### this fixes bug #7937
309b39c5158Smillert    $hash{size}     = 0 if ($type == DIR or $type == SYMLINK);
310b39c5158Smillert    $hash{mtime}    -= TIME_OFFSET;
311b39c5158Smillert
312b39c5158Smillert    ### strip the high bits off the mode, which we don't need to store
313b39c5158Smillert    $hash{mode}     = STRIP_MODE->( $hash{mode} );
314b39c5158Smillert
315b39c5158Smillert
316b39c5158Smillert    ### probably requires some file path munging here ... ###
317b39c5158Smillert    ### name and prefix are set later
318b39c5158Smillert    my $obj = {
319b39c5158Smillert        %hash,
320b39c5158Smillert        name        => '',
321b39c5158Smillert        chksum      => CHECK_SUM,
322b39c5158Smillert        type        => $type,
323b39c5158Smillert        linkname    => ($type == SYMLINK and CAN_READLINK)
324b39c5158Smillert                            ? readlink $path
325b39c5158Smillert                            : '',
326b39c5158Smillert        magic       => MAGIC,
327b39c5158Smillert        version     => TAR_VERSION,
328b39c5158Smillert        uname       => UNAME->( $hash{uid} ),
329b39c5158Smillert        gname       => GNAME->( $hash{gid} ),
330b39c5158Smillert        devmajor    => 0,   # not handled
331b39c5158Smillert        devminor    => 0,   # not handled
332b39c5158Smillert        prefix      => '',
333b39c5158Smillert        data        => $data,
334b39c5158Smillert    };
335b39c5158Smillert
336b39c5158Smillert    bless $obj, $class;
337b39c5158Smillert
338b39c5158Smillert    ### fix up the prefix and file from the path
339b39c5158Smillert    my($prefix,$file) = $obj->_prefix_and_file( $path );
340b39c5158Smillert    $obj->prefix( $prefix );
341b39c5158Smillert    $obj->name( $file );
342b39c5158Smillert
343b39c5158Smillert    return $obj;
344b39c5158Smillert}
345b39c5158Smillert
346b39c5158Smillertsub _new_from_data {
347b39c5158Smillert    my $class   = shift;
348b39c5158Smillert    my $path    = shift;    return unless defined $path;
349b39c5158Smillert    my $data    = shift;    return unless defined $data;
350b39c5158Smillert    my $opt     = shift;
351b39c5158Smillert
352b39c5158Smillert    my $obj = {
353b39c5158Smillert        data        => $data,
354b39c5158Smillert        name        => '',
355b39c5158Smillert        mode        => MODE,
356b39c5158Smillert        uid         => UID,
357b39c5158Smillert        gid         => GID,
358b39c5158Smillert        size        => length $data,
359b39c5158Smillert        mtime       => time - TIME_OFFSET,
360b39c5158Smillert        chksum      => CHECK_SUM,
361b39c5158Smillert        type        => FILE,
362b39c5158Smillert        linkname    => '',
363b39c5158Smillert        magic       => MAGIC,
364b39c5158Smillert        version     => TAR_VERSION,
365b39c5158Smillert        uname       => UNAME->( UID ),
366b39c5158Smillert        gname       => GNAME->( GID ),
367b39c5158Smillert        devminor    => 0,
368b39c5158Smillert        devmajor    => 0,
369b39c5158Smillert        prefix      => '',
370b39c5158Smillert    };
371b39c5158Smillert
372b39c5158Smillert    ### overwrite with user options, if provided ###
373b39c5158Smillert    if( $opt and ref $opt eq 'HASH' ) {
374b39c5158Smillert        for my $key ( keys %$opt ) {
375b39c5158Smillert
376b39c5158Smillert            ### don't write bogus options ###
377b39c5158Smillert            next unless exists $obj->{$key};
378b39c5158Smillert            $obj->{$key} = $opt->{$key};
379b39c5158Smillert        }
380b39c5158Smillert    }
381b39c5158Smillert
382b39c5158Smillert    bless $obj, $class;
383b39c5158Smillert
384b39c5158Smillert    ### fix up the prefix and file from the path
385b39c5158Smillert    my($prefix,$file) = $obj->_prefix_and_file( $path );
386b39c5158Smillert    $obj->prefix( $prefix );
387b39c5158Smillert    $obj->name( $file );
388b39c5158Smillert
389b39c5158Smillert    return $obj;
390b39c5158Smillert}
391b39c5158Smillert
392b39c5158Smillertsub _prefix_and_file {
393b39c5158Smillert    my $self = shift;
394b39c5158Smillert    my $path = shift;
395b39c5158Smillert
396b39c5158Smillert    my ($vol, $dirs, $file) = File::Spec->splitpath( $path, $self->is_dir );
3979f11ffb7Safresh1    my @dirs = File::Spec->splitdir( File::Spec->canonpath($dirs) );
398b39c5158Smillert
399b39c5158Smillert    ### if it's a directory, then $file might be empty
400b39c5158Smillert    $file = pop @dirs if $self->is_dir and not length $file;
401b39c5158Smillert
402b39c5158Smillert    ### splitting ../ gives you the relative path in native syntax
403b46d8ef2Safresh1    ### Remove the root (000000) directory
404b46d8ef2Safresh1    ### The volume from splitpath will also be in native syntax
405b46d8ef2Safresh1    if (ON_VMS) {
406b46d8ef2Safresh1        map { $_ = '..' if $_  eq '-'; $_ = '' if $_ eq '000000' } @dirs;
407b46d8ef2Safresh1        if (length($vol)) {
408b46d8ef2Safresh1            $vol = VMS::Filespec::unixify($vol);
409b46d8ef2Safresh1            unshift @dirs, $vol;
410b46d8ef2Safresh1        }
411b46d8ef2Safresh1    }
412b39c5158Smillert
4139f11ffb7Safresh1    my $prefix = File::Spec::Unix->catdir(@dirs);
414b39c5158Smillert    return( $prefix, $file );
415b39c5158Smillert}
416b39c5158Smillert
417b39c5158Smillertsub _filetype {
418b39c5158Smillert    my $self = shift;
419b39c5158Smillert    my $file = shift;
420b39c5158Smillert
421b39c5158Smillert    return unless defined $file;
422b39c5158Smillert
423b39c5158Smillert    return SYMLINK  if (-l $file);	# Symlink
424b39c5158Smillert
425b39c5158Smillert    return FILE     if (-f _);		# Plain file
426b39c5158Smillert
427b39c5158Smillert    return DIR      if (-d _);		# Directory
428b39c5158Smillert
429b39c5158Smillert    return FIFO     if (-p _);		# Named pipe
430b39c5158Smillert
431b39c5158Smillert    return SOCKET   if (-S _);		# Socket
432b39c5158Smillert
433b39c5158Smillert    return BLOCKDEV if (-b _);		# Block special
434b39c5158Smillert
435b39c5158Smillert    return CHARDEV  if (-c _);		# Character special
436b39c5158Smillert
437b39c5158Smillert    ### shouldn't happen, this is when making archives, not reading ###
438b39c5158Smillert    return LONGLINK if ( $file eq LONGLINK_NAME );
439b39c5158Smillert
440b39c5158Smillert    return UNKNOWN;		            # Something else (like what?)
441b39c5158Smillert
442b39c5158Smillert}
443b39c5158Smillert
444b39c5158Smillert### this method 'downgrades' a file to plain file -- this is used for
445b39c5158Smillert### symlinks when FOLLOW_SYMLINKS is true.
446b39c5158Smillertsub _downgrade_to_plainfile {
447b39c5158Smillert    my $entry = shift;
448b39c5158Smillert    $entry->type( FILE );
449b39c5158Smillert    $entry->mode( MODE );
450b39c5158Smillert    $entry->linkname('');
451b39c5158Smillert
452b39c5158Smillert    return 1;
453b39c5158Smillert}
454b39c5158Smillert
455b39c5158Smillert=head2 $bool = $file->extract( [ $alternative_name ] )
456b39c5158Smillert
457b39c5158SmillertExtract this object, optionally to an alternative name.
458b39c5158Smillert
459b39c5158SmillertSee C<< Archive::Tar->extract_file >> for details.
460b39c5158Smillert
461b39c5158SmillertReturns true on success and false on failure.
462b39c5158Smillert
463b39c5158Smillert=cut
464b39c5158Smillert
465b39c5158Smillertsub extract {
466b39c5158Smillert    my $self = shift;
467b39c5158Smillert
468b39c5158Smillert    local $Carp::CarpLevel += 1;
469b39c5158Smillert
470eac174f2Safresh1    ### avoid circular use, so only require;
471eac174f2Safresh1    require Archive::Tar;
472b39c5158Smillert    return Archive::Tar->_extract_file( $self, @_ );
473b39c5158Smillert}
474b39c5158Smillert
475b39c5158Smillert=head2 $path = $file->full_path
476b39c5158Smillert
477b39c5158SmillertReturns the full path from the tar header; this is basically a
478b39c5158Smillertconcatenation of the C<prefix> and C<name> fields.
479b39c5158Smillert
480b39c5158Smillert=cut
481b39c5158Smillert
482b39c5158Smillertsub full_path {
483b39c5158Smillert    my $self = shift;
484b39c5158Smillert
4856fb12b70Safresh1    ### if prefix field is empty
486b39c5158Smillert    return $self->name unless defined $self->prefix and length $self->prefix;
487b39c5158Smillert
488b39c5158Smillert    ### or otherwise, catfile'd
489*3d61058aSafresh1    my $path = File::Spec::Unix->catfile( $self->prefix, $self->name );
490*3d61058aSafresh1    $path .= "/" if $self->name =~ m{/$};   # Re-add trailing slash if necessary, as catfile() strips them off.
491*3d61058aSafresh1    return $path;
492b39c5158Smillert}
493b39c5158Smillert
494b39c5158Smillert
495b39c5158Smillert=head2 $bool = $file->validate
496b39c5158Smillert
497b39c5158SmillertDone by Archive::Tar internally when reading the tar file:
498b39c5158Smillertvalidate the header against the checksum to ensure integer tar file.
499b39c5158Smillert
500b39c5158SmillertReturns true on success, false on failure
501b39c5158Smillert
502b39c5158Smillert=cut
503b39c5158Smillert
504b39c5158Smillertsub validate {
505b39c5158Smillert    my $self = shift;
506b39c5158Smillert
507b39c5158Smillert    my $raw = $self->raw;
508b39c5158Smillert
509b39c5158Smillert    ### don't know why this one is different from the one we /write/ ###
510b39c5158Smillert    substr ($raw, 148, 8) = "        ";
511b39c5158Smillert
512b39c5158Smillert    ### bug #43513: [PATCH] Accept wrong checksums from SunOS and HP-UX tar
513b39c5158Smillert    ### like GNU tar does. See here for details:
514b39c5158Smillert    ### http://www.gnu.org/software/tar/manual/tar.html#SEC139
515b39c5158Smillert    ### so we do both a signed AND unsigned validate. if one succeeds, that's
516b39c5158Smillert    ### good enough
517b39c5158Smillert	return (   (unpack ("%16C*", $raw) == $self->chksum)
518b39c5158Smillert	        or (unpack ("%16c*", $raw) == $self->chksum)) ? 1 : 0;
519b39c5158Smillert}
520b39c5158Smillert
521b39c5158Smillert=head2 $bool = $file->has_content
522b39c5158Smillert
523b39c5158SmillertReturns a boolean to indicate whether the current object has content.
524b39c5158SmillertSome special files like directories and so on never will have any
525b39c5158Smillertcontent. This method is mainly to make sure you don't get warnings
526b39c5158Smillertfor using uninitialized values when looking at an object's content.
527b39c5158Smillert
528b39c5158Smillert=cut
529b39c5158Smillert
530b39c5158Smillertsub has_content {
531b39c5158Smillert    my $self = shift;
532b39c5158Smillert    return defined $self->data() && length $self->data() ? 1 : 0;
533b39c5158Smillert}
534b39c5158Smillert
535b39c5158Smillert=head2 $content = $file->get_content
536b39c5158Smillert
537b39c5158SmillertReturns the current content for the in-memory file
538b39c5158Smillert
539b39c5158Smillert=cut
540b39c5158Smillert
541b39c5158Smillertsub get_content {
542b39c5158Smillert    my $self = shift;
543b39c5158Smillert    $self->data( );
544b39c5158Smillert}
545b39c5158Smillert
546b39c5158Smillert=head2 $cref = $file->get_content_by_ref
547b39c5158Smillert
548b39c5158SmillertReturns the current content for the in-memory file as a scalar
549b39c5158Smillertreference. Normal users won't need this, but it will save memory if
550b39c5158Smillertyou are dealing with very large data files in your tar archive, since
551b39c5158Smillertit will pass the contents by reference, rather than make a copy of it
552b39c5158Smillertfirst.
553b39c5158Smillert
554b39c5158Smillert=cut
555b39c5158Smillert
556b39c5158Smillertsub get_content_by_ref {
557b39c5158Smillert    my $self = shift;
558b39c5158Smillert
559b39c5158Smillert    return \$self->{data};
560b39c5158Smillert}
561b39c5158Smillert
562b39c5158Smillert=head2 $bool = $file->replace_content( $content )
563b39c5158Smillert
564b39c5158SmillertReplace the current content of the file with the new content. This
565b39c5158Smillertonly affects the in-memory archive, not the on-disk version until
566b39c5158Smillertyou write it.
567b39c5158Smillert
568b39c5158SmillertReturns true on success, false on failure.
569b39c5158Smillert
570b39c5158Smillert=cut
571b39c5158Smillert
572b39c5158Smillertsub replace_content {
573b39c5158Smillert    my $self = shift;
574b39c5158Smillert    my $data = shift || '';
575b39c5158Smillert
576b39c5158Smillert    $self->data( $data );
577b39c5158Smillert    $self->size( length $data );
578b39c5158Smillert    return 1;
579b39c5158Smillert}
580b39c5158Smillert
581b39c5158Smillert=head2 $bool = $file->rename( $new_name )
582b39c5158Smillert
583b39c5158SmillertRename the current file to $new_name.
584b39c5158Smillert
585b39c5158SmillertNote that you must specify a Unix path for $new_name, since per tar
586b39c5158Smillertstandard, all files in the archive must be Unix paths.
587b39c5158Smillert
588b39c5158SmillertReturns true on success and false on failure.
589b39c5158Smillert
590b39c5158Smillert=cut
591b39c5158Smillert
592b39c5158Smillertsub rename {
593b39c5158Smillert    my $self = shift;
594b39c5158Smillert    my $path = shift;
595b39c5158Smillert
596b39c5158Smillert    return unless defined $path;
597b39c5158Smillert
598b39c5158Smillert    my ($prefix,$file) = $self->_prefix_and_file( $path );
599b39c5158Smillert
600b39c5158Smillert    $self->name( $file );
601b39c5158Smillert    $self->prefix( $prefix );
602b39c5158Smillert
603b39c5158Smillert	return 1;
604b39c5158Smillert}
605b39c5158Smillert
606*3d61058aSafresh1=head2 $bool = $file->chmod( $mode )
607898184e3Ssthen
608898184e3SsthenChange mode of $file to $mode. The mode can be a string or a number
609898184e3Ssthenwhich is interpreted as octal whether or not a leading 0 is given.
610898184e3Ssthen
611898184e3SsthenReturns true on success and false on failure.
612898184e3Ssthen
613898184e3Ssthen=cut
614898184e3Ssthen
615898184e3Ssthensub chmod {
616898184e3Ssthen    my $self  = shift;
617898184e3Ssthen    my $mode = shift; return unless defined $mode && $mode =~ /^[0-7]{1,4}$/;
618898184e3Ssthen    $self->{mode} = oct($mode);
619898184e3Ssthen    return 1;
620898184e3Ssthen}
621898184e3Ssthen
622898184e3Ssthen=head2 $bool = $file->chown( $user [, $group])
623898184e3Ssthen
624898184e3SsthenChange owner of $file to $user. If a $group is given that is changed
625898184e3Ssthenas well. You can also pass a single parameter with a colon separating the
626898184e3Ssthenuse and group as in 'root:wheel'.
627898184e3Ssthen
628898184e3SsthenReturns true on success and false on failure.
629898184e3Ssthen
630898184e3Ssthen=cut
631898184e3Ssthen
632898184e3Ssthensub chown {
633898184e3Ssthen    my $self = shift;
634898184e3Ssthen    my $uname = shift;
635898184e3Ssthen    return unless defined $uname;
636898184e3Ssthen    my $gname;
637898184e3Ssthen    if (-1 != index($uname, ':')) {
638898184e3Ssthen	($uname, $gname) = split(/:/, $uname);
639898184e3Ssthen    } else {
640898184e3Ssthen	$gname = shift if @_ > 0;
641898184e3Ssthen    }
642898184e3Ssthen
643898184e3Ssthen    $self->uname( $uname );
644898184e3Ssthen    $self->gname( $gname ) if $gname;
645898184e3Ssthen	return 1;
646898184e3Ssthen}
647898184e3Ssthen
648b39c5158Smillert=head1 Convenience methods
649b39c5158Smillert
650b39c5158SmillertTo quickly check the type of a C<Archive::Tar::File> object, you can
651b39c5158Smillertuse the following methods:
652b39c5158Smillert
653b39c5158Smillert=over 4
654b39c5158Smillert
655b39c5158Smillert=item $file->is_file
656b39c5158Smillert
657b39c5158SmillertReturns true if the file is of type C<file>
658b39c5158Smillert
659b39c5158Smillert=item $file->is_dir
660b39c5158Smillert
661b39c5158SmillertReturns true if the file is of type C<dir>
662b39c5158Smillert
663b39c5158Smillert=item $file->is_hardlink
664b39c5158Smillert
665b39c5158SmillertReturns true if the file is of type C<hardlink>
666b39c5158Smillert
667b39c5158Smillert=item $file->is_symlink
668b39c5158Smillert
669b39c5158SmillertReturns true if the file is of type C<symlink>
670b39c5158Smillert
671b39c5158Smillert=item $file->is_chardev
672b39c5158Smillert
673b39c5158SmillertReturns true if the file is of type C<chardev>
674b39c5158Smillert
675b39c5158Smillert=item $file->is_blockdev
676b39c5158Smillert
677b39c5158SmillertReturns true if the file is of type C<blockdev>
678b39c5158Smillert
679b39c5158Smillert=item $file->is_fifo
680b39c5158Smillert
681b39c5158SmillertReturns true if the file is of type C<fifo>
682b39c5158Smillert
683b39c5158Smillert=item $file->is_socket
684b39c5158Smillert
685b39c5158SmillertReturns true if the file is of type C<socket>
686b39c5158Smillert
687b39c5158Smillert=item $file->is_longlink
688b39c5158Smillert
689b39c5158SmillertReturns true if the file is of type C<LongLink>.
690b39c5158SmillertShould not happen after a successful C<read>.
691b39c5158Smillert
692b39c5158Smillert=item $file->is_label
693b39c5158Smillert
694b39c5158SmillertReturns true if the file is of type C<Label>.
695b39c5158SmillertShould not happen after a successful C<read>.
696b39c5158Smillert
697b39c5158Smillert=item $file->is_unknown
698b39c5158Smillert
699b39c5158SmillertReturns true if the file type is C<unknown>
700b39c5158Smillert
701b39c5158Smillert=back
702b39c5158Smillert
703b39c5158Smillert=cut
704b39c5158Smillert
705b39c5158Smillert#stupid perl5.5.3 needs to warn if it's not numeric
706b39c5158Smillertsub is_file     { local $^W;    FILE      == $_[0]->type }
707b39c5158Smillertsub is_dir      { local $^W;    DIR       == $_[0]->type }
708b39c5158Smillertsub is_hardlink { local $^W;    HARDLINK  == $_[0]->type }
709b39c5158Smillertsub is_symlink  { local $^W;    SYMLINK   == $_[0]->type }
710b39c5158Smillertsub is_chardev  { local $^W;    CHARDEV   == $_[0]->type }
711b39c5158Smillertsub is_blockdev { local $^W;    BLOCKDEV  == $_[0]->type }
712b39c5158Smillertsub is_fifo     { local $^W;    FIFO      == $_[0]->type }
713b39c5158Smillertsub is_socket   { local $^W;    SOCKET    == $_[0]->type }
714b39c5158Smillertsub is_unknown  { local $^W;    UNKNOWN   == $_[0]->type }
715b39c5158Smillertsub is_longlink { local $^W;    LONGLINK  eq $_[0]->type }
716b39c5158Smillertsub is_label    { local $^W;    LABEL     eq $_[0]->type }
717b39c5158Smillert
718b39c5158Smillert1;
719