1 package Archive::Tar::File;
5 use File::Spec::Unix ();
9 use Archive::Tar::Constant;
11 use vars qw[@ISA $VERSION];
12 @ISA = qw[Archive::Tar];
15 ### set value to 1 to oct() it during the unpack ###
24 type => 0, # character
25 linkname => 0, # string
27 version => 0, # 2 bytes
30 devmajor => 1, # octal
31 devminor => 1, # octal
34 ### end UNPACK items ###
35 raw => 0, # the raw data chunk
36 data => 0, # the data associated with the file --
37 # This might be very memory intensive
40 ### install get/set accessors for this object.
41 for ( my $i=0; $i<scalar @$tmpl ; $i+=2 ) {
42 my $key = $tmpl->[$i];
44 *{__PACKAGE__."::$key"} = sub {
46 $self->{$key} = $_[0] if @_;
48 ### just in case the key is not there or undef or something ###
57 Archive::Tar::File - a subclass for in-memory extracted file from Archive::Tar
61 my @items = $tar->get_files;
63 print $_->name, ' ', $_->size, "\n" for @items;
65 print $object->get_content;
66 $object->replace_content('new content');
68 $object->rename( 'new/full/path/to/file.c' );
72 Archive::Tar::Files provides a neat little object layer for in-memory
73 extracted files. It's mostly used internally in Archive::Tar to tidy
74 up the code, but there's no reason users shouldn't use this API as
79 A lot of the methods in this package are accessors to the various
80 fields in the tar header:
94 The user id owning the file
98 The group id owning the file
106 Modification time. Adjusted to mac-time on MacOS if required
110 Checksum field for the tar header
114 File type -- numeric, but comparable to exported constants -- see
115 Archive::Tar's documentation
119 If the file is a symlink, the file it's pointing to
123 Tar magic string -- not useful for most users
127 Tar version string -- not useful for most users
131 The user name that owns the file
135 The group name that owns the file
139 Device major number in case of a special file
143 Device minor number in case of a special file
147 Any directory to prefix to the extraction path, if any
151 Raw tar header -- not useful for most users
157 =head2 new( file => $path )
159 Returns a new Archive::Tar::File object from an existing file.
161 Returns undef on failure.
163 =head2 new( data => $path, $data, $opt )
165 Returns a new Archive::Tar::File object from data.
167 C<$path> defines the file name (which need not exist), C<$data> the
168 file contents, and C<$opt> is a reference to a hash of attributes
169 which may be used to override the default attributes (fields in the
170 tar header), which are described above in the Accessors section.
172 Returns undef on failure.
174 =head2 new( chunk => $chunk )
176 Returns a new Archive::Tar::File object from a raw 512-byte tar
179 Returns undef on failure.
187 my $obj = ($what eq 'chunk') ? __PACKAGE__->_new_from_chunk( @_ ) :
188 ($what eq 'file' ) ? __PACKAGE__->_new_from_file( @_ ) :
189 ($what eq 'data' ) ? __PACKAGE__->_new_from_data( @_ ) :
195 ### copies the data, creates a clone ###
198 return bless { %$self }, ref $self;
201 sub _new_from_chunk {
203 my $chunk = shift or return;
206 ### filter any arguments on defined-ness of values.
207 ### this allows overriding from what the tar-header is saying
208 ### about this tar-entry. Particularly useful for @LongLink files
209 my %args = map { $_ => $hash{$_} } grep { defined $hash{$_} } keys %hash;
211 ### makes it start at 0 actually... :) ###
214 $tmpl->[++$i] => $tmpl->[++$i] ? oct $_ : $_
215 } map { /^([^\0]*)/ } unpack( UNPACK, $chunk );
217 my $obj = bless { %entry, %args }, $class;
219 ### magic is a filetype string.. it should have something like 'ustar' or
220 ### something similar... if the chunk is garbage, skip it
221 return unless $obj->magic !~ /\W/;
223 ### store the original chunk ###
226 $obj->type(FILE) if ( (!length $obj->type) or ($obj->type =~ /\W/) );
227 $obj->type(DIR) if ( ($obj->is_file) && ($obj->name =~ m|/$|) );
236 my $path = shift or return;
237 my $type = __PACKAGE__->_filetype($path);
241 unless ($type == DIR ) {
242 my $fh = IO::File->new;
244 unless( $fh->open($path) ) {
245 ### dangling symlinks are fine, stop reading but continue
246 ### creating the object
247 last READ if $type == SYMLINK;
249 ### otherwise, return from this function --
250 ### anything that's *not* a symlink should be
255 ### binmode needed to read files properly on win32 ###
257 $data = do { local $/; <$fh> };
262 my @items = qw[mode uid gid size mtime];
263 my %hash = map { shift(@items), $_ } (lstat $path)[2,4,5,7,9];
265 ### you *must* set size == 0 on symlinks, or the next entry will be
266 ### though of as the contents of the symlink, which is wrong.
267 ### this fixes bug #7937
268 $hash{size} = 0 if ($type == DIR or $type == SYMLINK);
269 $hash{mtime} -= TIME_OFFSET;
271 ### strip the high bits off the mode, which we don't need to store
272 $hash{mode} = STRIP_MODE->( $hash{mode} );
275 ### probably requires some file path munging here ... ###
276 ### name and prefix are set later
282 linkname => ($type == SYMLINK and CAN_READLINK)
286 version => TAR_VERSION,
287 uname => UNAME->( $hash{uid} ),
288 gname => GNAME->( $hash{gid} ),
289 devmajor => 0, # not handled
290 devminor => 0, # not handled
297 ### fix up the prefix and file from the path
298 my($prefix,$file) = $obj->_prefix_and_file( $path );
299 $obj->prefix( $prefix );
307 my $path = shift or return;
308 my $data = shift; return unless defined $data;
317 size => length $data,
318 mtime => time - TIME_OFFSET,
323 version => TAR_VERSION,
324 uname => UNAME->( UID ),
325 gname => GNAME->( GID ),
331 ### overwrite with user options, if provided ###
332 if( $opt and ref $opt eq 'HASH' ) {
333 for my $key ( keys %$opt ) {
335 ### don't write bogus options ###
336 next unless exists $obj->{$key};
337 $obj->{$key} = $opt->{$key};
343 ### fix up the prefix and file from the path
344 my($prefix,$file) = $obj->_prefix_and_file( $path );
345 $obj->prefix( $prefix );
351 sub _prefix_and_file {
355 my ($vol, $dirs, $file) = File::Spec->splitpath( $path, $self->is_dir );
356 my @dirs = File::Spec->splitdir( $dirs );
358 ### so sometimes the last element is '' -- probably when trailing
359 ### dir slashes are encountered... this is is of course pointless,
361 pop @dirs while @dirs and not length $dirs[-1];
363 ### if it's a directory, then $file might be empty
364 $file = pop @dirs if $self->is_dir and not length $file;
366 my $prefix = File::Spec::Unix->catdir(
367 grep { length } $vol, @dirs
369 return( $prefix, $file );
374 my $file = shift or return;
376 return SYMLINK if (-l $file); # Symlink
378 return FILE if (-f _); # Plain file
380 return DIR if (-d _); # Directory
382 return FIFO if (-p _); # Named pipe
384 return SOCKET if (-S _); # Socket
386 return BLOCKDEV if (-b _); # Block special
388 return CHARDEV if (-c _); # Character special
390 ### shouldn't happen, this is when making archives, not reading ###
391 return LONGLINK if ( $file eq LONGLINK_NAME );
393 return UNKNOWN; # Something else (like what?)
397 ### this method 'downgrades' a file to plain file -- this is used for
398 ### symlinks when FOLLOW_SYMLINKS is true.
399 sub _downgrade_to_plainfile {
401 $entry->type( FILE );
402 $entry->mode( MODE );
403 $entry->linkname('');
410 Returns the full path from the tar header; this is basically a
411 concatenation of the C<prefix> and C<name> fields.
418 ### if prefix field is emtpy
419 return $self->name unless defined $self->prefix and length $self->prefix;
421 ### or otherwise, catfile'd
422 return File::Spec::Unix->catfile( $self->prefix, $self->name );
428 Done by Archive::Tar internally when reading the tar file:
429 validate the header against the checksum to ensure integer tar file.
431 Returns true on success, false on failure
438 my $raw = $self->raw;
440 ### don't know why this one is different from the one we /write/ ###
441 substr ($raw, 148, 8) = " ";
442 return unpack ("%16C*", $raw) == $self->chksum ? 1 : 0;
447 Returns a boolean to indicate whether the current object has content.
448 Some special files like directories and so on never will have any
449 content. This method is mainly to make sure you don't get warnings
450 for using uninitialized values when looking at an object's content.
456 return defined $self->data() && length $self->data() ? 1 : 0;
461 Returns the current content for the in-memory file
470 =head2 get_content_by_ref
472 Returns the current content for the in-memory file as a scalar
473 reference. Normal users won't need this, but it will save memory if
474 you are dealing with very large data files in your tar archive, since
475 it will pass the contents by reference, rather than make a copy of it
480 sub get_content_by_ref {
483 return \$self->{data};
486 =head2 replace_content( $content )
488 Replace the current content of the file with the new content. This
489 only affects the in-memory archive, not the on-disk version until
492 Returns true on success, false on failure.
496 sub replace_content {
498 my $data = shift || '';
500 $self->data( $data );
501 $self->size( length $data );
505 =head2 rename( $new_name )
507 Rename the current file to $new_name.
509 Note that you must specify a Unix path for $new_name, since per tar
510 standard, all files in the archive must be Unix paths.
512 Returns true on success and false on failure.
518 my $path = shift or return;
520 my ($prefix,$file) = $self->_prefix_and_file( $path );
522 $self->name( $file );
523 $self->prefix( $prefix );
528 =head1 Convenience methods
530 To quickly check the type of a C<Archive::Tar::File> object, you can
531 use the following methods:
537 Returns true if the file is of type C<file>
541 Returns true if the file is of type C<dir>
545 Returns true if the file is of type C<hardlink>
549 Returns true if the file is of type C<symlink>
553 Returns true if the file is of type C<chardev>
557 Returns true if the file is of type C<blockdev>
561 Returns true if the file is of type C<fifo>
565 Returns true if the file is of type C<socket>
569 Returns true if the file is of type C<LongLink>.
570 Should not happen after a successful C<read>.
574 Returns true if the file is of type C<Label>.
575 Should not happen after a successful C<read>.
579 Returns true if the file type is C<unknown>
585 #stupid perl5.5.3 needs to warn if it's not numeric
586 sub is_file { local $^W; FILE == $_[0]->type }
587 sub is_dir { local $^W; DIR == $_[0]->type }
588 sub is_hardlink { local $^W; HARDLINK == $_[0]->type }
589 sub is_symlink { local $^W; SYMLINK == $_[0]->type }
590 sub is_chardev { local $^W; CHARDEV == $_[0]->type }
591 sub is_blockdev { local $^W; BLOCKDEV == $_[0]->type }
592 sub is_fifo { local $^W; FIFO == $_[0]->type }
593 sub is_socket { local $^W; SOCKET == $_[0]->type }
594 sub is_unknown { local $^W; UNKNOWN == $_[0]->type }
595 sub is_longlink { local $^W; LONGLINK eq $_[0]->type }
596 sub is_label { local $^W; LABEL eq $_[0]->type }