[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 package Archive::Tar::File; 2 use strict; 3 4 use IO::File; 5 use File::Spec::Unix (); 6 use File::Spec (); 7 use File::Basename (); 8 9 use Archive::Tar::Constant; 10 11 use vars qw[@ISA $VERSION]; 12 @ISA = qw[Archive::Tar]; 13 $VERSION = '0.02'; 14 15 ### set value to 1 to oct() it during the unpack ### 16 my $tmpl = [ 17 name => 0, # string 18 mode => 1, # octal 19 uid => 1, # octal 20 gid => 1, # octal 21 size => 1, # octal 22 mtime => 1, # octal 23 chksum => 1, # octal 24 type => 0, # character 25 linkname => 0, # string 26 magic => 0, # string 27 version => 0, # 2 bytes 28 uname => 0, # string 29 gname => 0, # string 30 devmajor => 1, # octal 31 devminor => 1, # octal 32 prefix => 0, 33 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 38 ]; 39 40 ### install get/set accessors for this object. 41 for ( my $i=0; $i<scalar @$tmpl ; $i+=2 ) { 42 my $key = $tmpl->[$i]; 43 no strict 'refs'; 44 *{__PACKAGE__."::$key"} = sub { 45 my $self = shift; 46 $self->{$key} = $_[0] if @_; 47 48 ### just in case the key is not there or undef or something ### 49 { local $^W = 0; 50 return $self->{$key}; 51 } 52 } 53 } 54 55 =head1 NAME 56 57 Archive::Tar::File - a subclass for in-memory extracted file from Archive::Tar 58 59 =head1 SYNOPSIS 60 61 my @items = $tar->get_files; 62 63 print $_->name, ' ', $_->size, "\n" for @items; 64 65 print $object->get_content; 66 $object->replace_content('new content'); 67 68 $object->rename( 'new/full/path/to/file.c' ); 69 70 =head1 DESCRIPTION 71 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 75 well. 76 77 =head2 Accessors 78 79 A lot of the methods in this package are accessors to the various 80 fields in the tar header: 81 82 =over 4 83 84 =item name 85 86 The file's name 87 88 =item mode 89 90 The file's mode 91 92 =item uid 93 94 The user id owning the file 95 96 =item gid 97 98 The group id owning the file 99 100 =item size 101 102 File size in bytes 103 104 =item mtime 105 106 Modification time. Adjusted to mac-time on MacOS if required 107 108 =item chksum 109 110 Checksum field for the tar header 111 112 =item type 113 114 File type -- numeric, but comparable to exported constants -- see 115 Archive::Tar's documentation 116 117 =item linkname 118 119 If the file is a symlink, the file it's pointing to 120 121 =item magic 122 123 Tar magic string -- not useful for most users 124 125 =item version 126 127 Tar version string -- not useful for most users 128 129 =item uname 130 131 The user name that owns the file 132 133 =item gname 134 135 The group name that owns the file 136 137 =item devmajor 138 139 Device major number in case of a special file 140 141 =item devminor 142 143 Device minor number in case of a special file 144 145 =item prefix 146 147 Any directory to prefix to the extraction path, if any 148 149 =item raw 150 151 Raw tar header -- not useful for most users 152 153 =back 154 155 =head1 Methods 156 157 =head2 new( file => $path ) 158 159 Returns a new Archive::Tar::File object from an existing file. 160 161 Returns undef on failure. 162 163 =head2 new( data => $path, $data, $opt ) 164 165 Returns a new Archive::Tar::File object from data. 166 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. 171 172 Returns undef on failure. 173 174 =head2 new( chunk => $chunk ) 175 176 Returns a new Archive::Tar::File object from a raw 512-byte tar 177 archive chunk. 178 179 Returns undef on failure. 180 181 =cut 182 183 sub new { 184 my $class = shift; 185 my $what = shift; 186 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( @_ ) : 190 undef; 191 192 return $obj; 193 } 194 195 ### copies the data, creates a clone ### 196 sub clone { 197 my $self = shift; 198 return bless { %$self }, ref $self; 199 } 200 201 sub _new_from_chunk { 202 my $class = shift; 203 my $chunk = shift or return; # 512 bytes of tar header 204 my %hash = @_; 205 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; 210 211 ### makes it start at 0 actually... :) ### 212 my $i = -1; 213 my %entry = map { 214 $tmpl->[++$i] => $tmpl->[++$i] ? oct $_ : $_ 215 } map { /^([^\0]*)/ } unpack( UNPACK, $chunk ); 216 217 my $obj = bless { %entry, %args }, $class; 218 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/; 222 223 ### store the original chunk ### 224 $obj->raw( $chunk ); 225 226 $obj->type(FILE) if ( (!length $obj->type) or ($obj->type =~ /\W/) ); 227 $obj->type(DIR) if ( ($obj->is_file) && ($obj->name =~ m|/$|) ); 228 229 230 return $obj; 231 232 } 233 234 sub _new_from_file { 235 my $class = shift; 236 my $path = shift; 237 238 ### path has to at least exist 239 return unless defined $path; 240 241 my $type = __PACKAGE__->_filetype($path); 242 my $data = ''; 243 244 READ: { 245 unless ($type == DIR ) { 246 my $fh = IO::File->new; 247 248 unless( $fh->open($path) ) { 249 ### dangling symlinks are fine, stop reading but continue 250 ### creating the object 251 last READ if $type == SYMLINK; 252 253 ### otherwise, return from this function -- 254 ### anything that's *not* a symlink should be 255 ### resolvable 256 return; 257 } 258 259 ### binmode needed to read files properly on win32 ### 260 binmode $fh; 261 $data = do { local $/; <$fh> }; 262 close $fh; 263 } 264 } 265 266 my @items = qw[mode uid gid size mtime]; 267 my %hash = map { shift(@items), $_ } (lstat $path)[2,4,5,7,9]; 268 269 ### you *must* set size == 0 on symlinks, or the next entry will be 270 ### though of as the contents of the symlink, which is wrong. 271 ### this fixes bug #7937 272 $hash{size} = 0 if ($type == DIR or $type == SYMLINK); 273 $hash{mtime} -= TIME_OFFSET; 274 275 ### strip the high bits off the mode, which we don't need to store 276 $hash{mode} = STRIP_MODE->( $hash{mode} ); 277 278 279 ### probably requires some file path munging here ... ### 280 ### name and prefix are set later 281 my $obj = { 282 %hash, 283 name => '', 284 chksum => CHECK_SUM, 285 type => $type, 286 linkname => ($type == SYMLINK and CAN_READLINK) 287 ? readlink $path 288 : '', 289 magic => MAGIC, 290 version => TAR_VERSION, 291 uname => UNAME->( $hash{uid} ), 292 gname => GNAME->( $hash{gid} ), 293 devmajor => 0, # not handled 294 devminor => 0, # not handled 295 prefix => '', 296 data => $data, 297 }; 298 299 bless $obj, $class; 300 301 ### fix up the prefix and file from the path 302 my($prefix,$file) = $obj->_prefix_and_file( $path ); 303 $obj->prefix( $prefix ); 304 $obj->name( $file ); 305 306 return $obj; 307 } 308 309 sub _new_from_data { 310 my $class = shift; 311 my $path = shift; return unless defined $path; 312 my $data = shift; return unless defined $data; 313 my $opt = shift; 314 315 my $obj = { 316 data => $data, 317 name => '', 318 mode => MODE, 319 uid => UID, 320 gid => GID, 321 size => length $data, 322 mtime => time - TIME_OFFSET, 323 chksum => CHECK_SUM, 324 type => FILE, 325 linkname => '', 326 magic => MAGIC, 327 version => TAR_VERSION, 328 uname => UNAME->( UID ), 329 gname => GNAME->( GID ), 330 devminor => 0, 331 devmajor => 0, 332 prefix => '', 333 }; 334 335 ### overwrite with user options, if provided ### 336 if( $opt and ref $opt eq 'HASH' ) { 337 for my $key ( keys %$opt ) { 338 339 ### don't write bogus options ### 340 next unless exists $obj->{$key}; 341 $obj->{$key} = $opt->{$key}; 342 } 343 } 344 345 bless $obj, $class; 346 347 ### fix up the prefix and file from the path 348 my($prefix,$file) = $obj->_prefix_and_file( $path ); 349 $obj->prefix( $prefix ); 350 $obj->name( $file ); 351 352 return $obj; 353 } 354 355 sub _prefix_and_file { 356 my $self = shift; 357 my $path = shift; 358 359 my ($vol, $dirs, $file) = File::Spec->splitpath( $path, $self->is_dir ); 360 my @dirs = File::Spec->splitdir( $dirs ); 361 362 ### so sometimes the last element is '' -- probably when trailing 363 ### dir slashes are encountered... this is is of course pointless, 364 ### so remove it 365 pop @dirs while @dirs and not length $dirs[-1]; 366 367 ### if it's a directory, then $file might be empty 368 $file = pop @dirs if $self->is_dir and not length $file; 369 370 my $prefix = File::Spec::Unix->catdir( 371 grep { length } $vol, @dirs 372 ); 373 return( $prefix, $file ); 374 } 375 376 sub _filetype { 377 my $self = shift; 378 my $file = shift; 379 380 return unless defined $file; 381 382 return SYMLINK if (-l $file); # Symlink 383 384 return FILE if (-f _); # Plain file 385 386 return DIR if (-d _); # Directory 387 388 return FIFO if (-p _); # Named pipe 389 390 return SOCKET if (-S _); # Socket 391 392 return BLOCKDEV if (-b _); # Block special 393 394 return CHARDEV if (-c _); # Character special 395 396 ### shouldn't happen, this is when making archives, not reading ### 397 return LONGLINK if ( $file eq LONGLINK_NAME ); 398 399 return UNKNOWN; # Something else (like what?) 400 401 } 402 403 ### this method 'downgrades' a file to plain file -- this is used for 404 ### symlinks when FOLLOW_SYMLINKS is true. 405 sub _downgrade_to_plainfile { 406 my $entry = shift; 407 $entry->type( FILE ); 408 $entry->mode( MODE ); 409 $entry->linkname(''); 410 411 return 1; 412 } 413 414 =head2 full_path 415 416 Returns the full path from the tar header; this is basically a 417 concatenation of the C<prefix> and C<name> fields. 418 419 =cut 420 421 sub full_path { 422 my $self = shift; 423 424 ### if prefix field is emtpy 425 return $self->name unless defined $self->prefix and length $self->prefix; 426 427 ### or otherwise, catfile'd 428 return File::Spec::Unix->catfile( $self->prefix, $self->name ); 429 } 430 431 432 =head2 validate 433 434 Done by Archive::Tar internally when reading the tar file: 435 validate the header against the checksum to ensure integer tar file. 436 437 Returns true on success, false on failure 438 439 =cut 440 441 sub validate { 442 my $self = shift; 443 444 my $raw = $self->raw; 445 446 ### don't know why this one is different from the one we /write/ ### 447 substr ($raw, 148, 8) = " "; 448 return unpack ("%16C*", $raw) == $self->chksum ? 1 : 0; 449 } 450 451 =head2 has_content 452 453 Returns a boolean to indicate whether the current object has content. 454 Some special files like directories and so on never will have any 455 content. This method is mainly to make sure you don't get warnings 456 for using uninitialized values when looking at an object's content. 457 458 =cut 459 460 sub has_content { 461 my $self = shift; 462 return defined $self->data() && length $self->data() ? 1 : 0; 463 } 464 465 =head2 get_content 466 467 Returns the current content for the in-memory file 468 469 =cut 470 471 sub get_content { 472 my $self = shift; 473 $self->data( ); 474 } 475 476 =head2 get_content_by_ref 477 478 Returns the current content for the in-memory file as a scalar 479 reference. Normal users won't need this, but it will save memory if 480 you are dealing with very large data files in your tar archive, since 481 it will pass the contents by reference, rather than make a copy of it 482 first. 483 484 =cut 485 486 sub get_content_by_ref { 487 my $self = shift; 488 489 return \$self->{data}; 490 } 491 492 =head2 replace_content( $content ) 493 494 Replace the current content of the file with the new content. This 495 only affects the in-memory archive, not the on-disk version until 496 you write it. 497 498 Returns true on success, false on failure. 499 500 =cut 501 502 sub replace_content { 503 my $self = shift; 504 my $data = shift || ''; 505 506 $self->data( $data ); 507 $self->size( length $data ); 508 return 1; 509 } 510 511 =head2 rename( $new_name ) 512 513 Rename the current file to $new_name. 514 515 Note that you must specify a Unix path for $new_name, since per tar 516 standard, all files in the archive must be Unix paths. 517 518 Returns true on success and false on failure. 519 520 =cut 521 522 sub rename { 523 my $self = shift; 524 my $path = shift; 525 526 return unless defined $path; 527 528 my ($prefix,$file) = $self->_prefix_and_file( $path ); 529 530 $self->name( $file ); 531 $self->prefix( $prefix ); 532 533 return 1; 534 } 535 536 =head1 Convenience methods 537 538 To quickly check the type of a C<Archive::Tar::File> object, you can 539 use the following methods: 540 541 =over 4 542 543 =item is_file 544 545 Returns true if the file is of type C<file> 546 547 =item is_dir 548 549 Returns true if the file is of type C<dir> 550 551 =item is_hardlink 552 553 Returns true if the file is of type C<hardlink> 554 555 =item is_symlink 556 557 Returns true if the file is of type C<symlink> 558 559 =item is_chardev 560 561 Returns true if the file is of type C<chardev> 562 563 =item is_blockdev 564 565 Returns true if the file is of type C<blockdev> 566 567 =item is_fifo 568 569 Returns true if the file is of type C<fifo> 570 571 =item is_socket 572 573 Returns true if the file is of type C<socket> 574 575 =item is_longlink 576 577 Returns true if the file is of type C<LongLink>. 578 Should not happen after a successful C<read>. 579 580 =item is_label 581 582 Returns true if the file is of type C<Label>. 583 Should not happen after a successful C<read>. 584 585 =item is_unknown 586 587 Returns true if the file type is C<unknown> 588 589 =back 590 591 =cut 592 593 #stupid perl5.5.3 needs to warn if it's not numeric 594 sub is_file { local $^W; FILE == $_[0]->type } 595 sub is_dir { local $^W; DIR == $_[0]->type } 596 sub is_hardlink { local $^W; HARDLINK == $_[0]->type } 597 sub is_symlink { local $^W; SYMLINK == $_[0]->type } 598 sub is_chardev { local $^W; CHARDEV == $_[0]->type } 599 sub is_blockdev { local $^W; BLOCKDEV == $_[0]->type } 600 sub is_fifo { local $^W; FIFO == $_[0]->type } 601 sub is_socket { local $^W; SOCKET == $_[0]->type } 602 sub is_unknown { local $^W; UNKNOWN == $_[0]->type } 603 sub is_longlink { local $^W; LONGLINK eq $_[0]->type } 604 sub is_label { local $^W; LABEL eq $_[0]->type } 605 606 1;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |