home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / Chip_2000-05_cd1.bin / zkuste / Perl / ActivePerl-5.6.0.613.msi / 䆊䌷䈹䈙䏵-䞅䞆䞀㡆䞃䄦䠥 / _1791f0f0101131a53e257ca5553f9a12 < prev    next >
Text File  |  2000-03-15  |  19KB  |  719 lines

  1. package Archive::Tar;
  2.  
  3. use strict;
  4. use Carp;
  5. use Cwd;
  6. use File::Basename;
  7.  
  8. BEGIN {
  9.     # This bit is straight from the manpages
  10.     use Exporter ();
  11.     use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $symlinks $compression $has_getpwuid $has_getgrgid);
  12.  
  13.     $VERSION = 0.072;
  14.     @ISA = qw(Exporter);
  15.     @EXPORT = qw ();
  16.     %EXPORT_TAGS = ();
  17.     @EXPORT_OK = ();
  18.  
  19.     # The following bit is not straight from the manpages
  20.     # Check if symbolic links are available
  21.     $symlinks = 1;
  22.     eval { $_ = readlink $0; };    # Pointless assigment to make -w shut up
  23.     if ($@) {
  24.     warn "Symbolic links not available.\n";
  25.     $symlinks = undef;
  26.     }
  27.     # Check if Compress::Zlib is available
  28.     $compression = 1;
  29.     eval {require Compress::Zlib;};
  30.     if ($@) {
  31.     warn "Compression not available.\n";
  32.     $compression = undef;
  33.     }
  34.     # Check for get* (they don't exist on WinNT)
  35.     eval {$_=getpwuid(0)}; # Pointless assigment to make -w shut up
  36.     $has_getpwuid = !$@;
  37.     eval {$_=getgrgid(0)}; # Pointless assigment to make -w shut up
  38.     $has_getgrgid = !$@;
  39. }
  40.  
  41. use vars qw(@EXPORT_OK $tar_unpack_header $tar_header_length $error);
  42.  
  43. $tar_unpack_header 
  44.   ='A100 A8 A8 A8 A12 A12 A8 A1 A100 A6 A2 A32 A32 A8 A8 A155';
  45. $tar_header_length = 512;
  46.  
  47. sub format_tar_entry;
  48. sub format_tar_file;
  49.  
  50. ###
  51. ### Non-method functions
  52. ###
  53.  
  54. sub drat {$error=$!;return undef}
  55.  
  56. sub read_tar {
  57.     my ($filename, $compressed) = @_;
  58.     my @tarfile = ();
  59.     my $i = 0;
  60.     my $head;
  61.     
  62.     if ($compressed) {
  63.     if ($compression) {
  64.         $compressed = Compress::Zlib::gzopen($filename,"rb") or drat; # Open compressed
  65.         $compressed->gzread($head,$tar_header_length);
  66.     }
  67.     else {
  68.         $error = "Compression not available (install Compress::Zlib).\n";
  69.         return undef;
  70.     }
  71.     }
  72.     else {
  73.     open(TAR, $filename) or drat;
  74.     binmode TAR;
  75.     read(TAR,$head,$tar_header_length);
  76.     }
  77.   READLOOP:
  78.     while (length($head)==$tar_header_length) {
  79.     my ($name,        # string
  80.         $mode,        # octal number
  81.         $uid,        # octal number
  82.         $gid,        # octal number
  83.         $size,        # octal number
  84.         $mtime,        # octal number
  85.         $chksum,        # octal number
  86.         $typeflag,        # character
  87.         $linkname,        # string
  88.         $magic,        # string
  89.         $version,        # two bytes
  90.         $uname,        # string
  91.         $gname,        # string
  92.         $devmajor,        # octal number
  93.         $devminor,        # octal number
  94.         $prefix) = unpack($tar_unpack_header,$head);
  95.     my ($data, $diff, $dummy);
  96.     
  97.     $mode = oct $mode;
  98.     $uid = oct $uid;
  99.     $gid = oct $gid;
  100.     $size = oct $size;
  101.     $mtime = oct $mtime;
  102.     $chksum = oct $chksum;
  103.     $devmajor = oct $devmajor;
  104.     $devminor = oct $devminor;
  105.     $name = $prefix."/".$name if $prefix;
  106.     $prefix = "";
  107.     # some broken tar-s don't set the typeflag for directories
  108.     # so we ass_u_me a directory if the name ends in slash
  109.     $typeflag = 5 if $name =~ m|/$| and not $typeflag;
  110.     
  111.     last READLOOP if $head eq "\0" x 512;    # End of archive
  112.     # Apparently this should really be two blocks of 512 zeroes,
  113.     # but GNU tar sometimes gets it wrong. See comment in the
  114.     # source code (tar.c) to GNU cpio.
  115.     
  116.     substr($head,148,8) = "        ";
  117.     if (unpack("%16C*",$head)!=$chksum) {
  118.         warn "$name: checksum error.\n";
  119.     }
  120.  
  121.     if ($compressed) {
  122.         $compressed->gzread($data,$size);
  123.     }
  124.     else {
  125.         if (read(TAR,$data,$size)!=$size) {
  126.         $error = "Read error on tarfile.";
  127.         close TAR;
  128.         return undef;
  129.         }
  130.     }
  131.     $diff = $size%512;
  132.     
  133.     if ($diff!=0) {
  134.         if ($compressed) {
  135.         $compressed->gzread($dummy,512-$diff);
  136.         }
  137.         else {
  138.         read(TAR,$dummy,512-$diff); # Padding, throw away
  139.         }
  140.     }
  141.     
  142.     # Guard against tarfiles with garbage at the end
  143.     last READLOOP if $name eq ''; 
  144.     
  145.     $tarfile[$i++]={
  146.             name => $name,            
  147.             mode => $mode,
  148.             uid => $uid,
  149.             gid => $gid,
  150.             size => $size,
  151.             mtime => $mtime,
  152.             chksum => $chksum,
  153.             typeflag => $typeflag,
  154.             linkname => $linkname,
  155.             magic => $magic,
  156.             version => $version,
  157.             uname => $uname,
  158.             gname => $gname,
  159.             devmajor => $devmajor,
  160.             devminor => $devminor,
  161.             prefix => $prefix,
  162.             data => $data};
  163.     }
  164.     continue {
  165.     if ($compressed) {
  166.         $compressed->gzread($head,$tar_header_length);
  167.     }
  168.     else {
  169.         read(TAR,$head,$tar_header_length);
  170.     }
  171.     }
  172.     $compressed ? $compressed->gzclose() : close(TAR);
  173.     return @tarfile;
  174. }
  175.  
  176. sub format_tar_file {
  177.     my @tarfile = @_;
  178.     my $file = "";
  179.     
  180.     foreach (@tarfile) {
  181.     $file .= format_tar_entry $_;
  182.     }
  183.     $file .= "\0" x 1024;
  184.     return $file;
  185. }
  186.  
  187. sub write_tar {
  188.     my ($filename) = shift;
  189.     my ($compressed) = shift;
  190.     my @tarfile = @_;
  191.     my ($tmp);
  192.  
  193.     
  194.     $tmp = format_tar_file @tarfile;
  195.     if ($compressed) {
  196.     if (!$compression) {
  197.         $error = "Compression not available.\n";
  198.         return undef;
  199.     }
  200.     $compressed = Compress::Zlib::gzopen($filename,"wb") or drat;
  201.     $compressed->gzwrite($tmp);
  202.     $compressed->gzclose;
  203.     }
  204.     else {
  205.     open(TAR, ">".$filename) or drat;
  206.     binmode TAR;
  207.     syswrite(TAR,$tmp,length $tmp);
  208.     close(TAR) or carp "Failed to close $filename, data may be lost: $!\n";
  209.     }
  210. }
  211.  
  212. sub format_tar_entry {
  213.     my ($ref) = shift;
  214.     my ($tmp,$file,$prefix,$pos);
  215.  
  216.     $file = $ref->{name};
  217.     if (length($file)>99) {
  218.     $pos = index $file, "/",(length($file) - 100);
  219.     next if $pos == -1;    # Filename longer than 100 chars!
  220.     
  221.     $prefix = substr $file,0,$pos;
  222.     $file = substr $file,$pos+1;
  223.     substr($prefix,0,-155)="" if length($prefix)>154;
  224.     }
  225.     else {
  226.     $prefix="";
  227.     }
  228.     $tmp = pack("a100a8a8a8a12a12a8a1a100",
  229.         $file,
  230.         sprintf("%6o ",$ref->{mode}),
  231.         sprintf("%6o ",$ref->{uid}),
  232.         sprintf("%6o ",$ref->{gid}),
  233.         sprintf("%11o ",$ref->{size}),
  234.         sprintf("%11o ",$ref->{mtime}),
  235.         "        ",
  236.         $ref->{typeflag},
  237.         $ref->{linkname});
  238.     $tmp .= pack("a6", $ref->{magic});
  239.     $tmp .= '00';
  240.     $tmp .= pack("a32",$ref->{uname});
  241.     $tmp .= pack("a32",$ref->{gname});
  242.     $tmp .= pack("a8",sprintf("%6o ",$ref->{devmajor}));
  243.     $tmp .= pack("a8",sprintf("%6o ",$ref->{devminor}));
  244.     $tmp .= pack("a155",$prefix);
  245.     substr($tmp,148,6) = sprintf("%6o", unpack("%16C*",$tmp));
  246.     substr($tmp,154,1) = "\0";
  247.     $tmp .= "\0" x ($tar_header_length-length($tmp));
  248.     $tmp .= $ref->{data};
  249.     if ($ref->{size}>0) {
  250.     $tmp .= "\0" x (512 - ($ref->{size}%512)) unless $ref->{size}%512==0;
  251.     }
  252.     return $tmp;
  253. }
  254.  
  255.  
  256. ###
  257. ### Methods
  258. ###
  259.  
  260. # Constructor. Reads tarfile if given an argument that's the name of a
  261. # readable file.
  262. sub new {
  263.     my $class = shift;
  264.     my ($filename,$compressed) = @_;
  265.     my $self = {};
  266.  
  267.     bless $self, $class;
  268.  
  269.     $self->{'_filename'} = undef;
  270.     if (!defined $filename) {
  271.     return $self;
  272.     }
  273.     if (-r $filename) {
  274.     $self->{'_data'} = [read_tar $filename,$compressed];
  275.     $self->{'_filename'} = $filename;
  276.     return $self;
  277.     }
  278.     if (-e $filename) {
  279.     carp "File exists but is not readable: $filename\n";
  280.     }
  281.     return $self;
  282. }
  283.  
  284. # Return list with references to hashes representing the tar archive's
  285. # component files.
  286. sub data {
  287.     my $self = shift;
  288.  
  289.     return @{$self->{'_data'}};
  290. }
  291.  
  292. # Read a tarfile. Returns number of component files.
  293. sub read {
  294.     my $self = shift;
  295.     my ($file, $compressed) = @_;
  296.  
  297.     $self->{'_filename'} = undef;
  298.     if (! -e $file) {
  299.     carp "$file does not exist.\n";
  300.     $self->{'_data'}=[];
  301.     return undef;
  302.     }
  303.     elsif (! -r $file) {
  304.     carp "$file is not readable.\n";
  305.     $self->{'_data'}=[];
  306.     return undef;
  307.     }
  308.     else {
  309.     $self->{'_data'}=[read_tar $file, $compressed];
  310.     $self->{'_filename'} = $file;
  311.     return scalar @{$self->{'_data'}};
  312.     }
  313. }
  314.  
  315. # Write a tar archive to file
  316. sub write {
  317.     my ($self) = shift @_;
  318.     my ($file) = shift @_;
  319.     my ($compressed) = shift @_;
  320.     
  321.     unless ($file) {
  322.     return format_tar_file @{$self->{'_data'}};
  323.     }
  324.     write_tar $file, $compressed, @{$self->{'_data'}};
  325. }
  326.  
  327. # Add files to the archive. Returns number of successfully added files.
  328. sub add_files {
  329.     my ($self) = shift;
  330.     my (@files) = @_;
  331.     my $file;
  332.     my ($mode,$uid,$gid,$rdev,$size,$mtime,$data,$typeflag,$linkname);
  333.     my $counter = 0;
  334.     local ($/);
  335.     
  336.     undef $/;
  337.     foreach $file (@files) {
  338.     if ((undef,undef,$mode,undef,$uid,$gid,$rdev,$size,
  339.          undef,$mtime,undef,undef,undef) = stat($file)) {
  340.         $data = "";
  341.         $linkname = "";
  342.         if (-f $file) {    # Plain file
  343.         $typeflag = 0;
  344.         unless (open(FILE,$file)) {
  345.             next;    # Can't open file, for some reason. Try next one.
  346.         }
  347.         binmode FILE;
  348.         $data = <FILE>;
  349.         $data = "" unless defined $data;
  350.         close FILE;
  351.         }
  352.         elsif (-l $file) {    # Symlink
  353.         $typeflag = 1;
  354.         $linkname = readlink $file if $symlinks;
  355.         }
  356.         elsif (-d $file) {    # Directory
  357.         $typeflag = 5;
  358.         }
  359.         elsif (-p $file) {    # Named pipe
  360.         $typeflag = 6;
  361.         }
  362.         elsif (-S $file) {    # Socket
  363.         $typeflag = 8;    # Bogus value, POSIX doesn't believe in sockets
  364.         }
  365.         elsif (-b $file) {    # Block special
  366.         $typeflag = 4;
  367.         }
  368.         elsif (-c $file) {    # Character special
  369.         $typeflag = 3;
  370.         }
  371.         else {        # Something else (like what?)
  372.         $typeflag = 9;    # Also bogus value.
  373.         }
  374.         push(@{$self->{'_data'}},{
  375.                       name => $file,            
  376.                       mode => $mode,
  377.                       uid => $uid,
  378.                       gid => $gid,
  379.                       size => length $data,
  380.                       mtime => $mtime,
  381.                       chksum => "      ",
  382.                       typeflag => $typeflag, 
  383.                       linkname => $linkname,
  384.                       magic => "ustar\0",
  385.                       version => "00",
  386.                       # WinNT protection
  387.                       uname => 
  388.                   $has_getpwuid?(getpwuid($uid))[0]:"unknown",
  389.                       gname => 
  390.                   $has_getgrgid?(getgrgid($gid))[0]:"unknown",
  391.                       devmajor => 0, # We don't handle this yet
  392.                       devminor => 0, # We don't handle this yet
  393.                       prefix => "",
  394.                       'data' => $data,
  395.                      });
  396.         $counter++;        # Successfully added file
  397.     }
  398.     else {
  399.         next;        # stat failed
  400.     }
  401.     }
  402.     return $counter;
  403. }
  404.  
  405. sub remove {
  406.     my ($self) = shift;
  407.     my (@files) = @_;
  408.     my $file;
  409.     
  410.     foreach $file (@files) {
  411.     @{$self->{'_data'}} = grep {$_->{name} ne $file} @{$self->{'_data'}};
  412.     }
  413.     return $self;
  414. }
  415.  
  416. # Get the content of a file
  417. sub get_content {
  418.     my ($self) = shift;
  419.     my ($file) = @_;
  420.     my $entry;
  421.     
  422.     ($entry) = grep {$_->{name} eq $file} @{$self->{'_data'}};
  423.     return $entry->{'data'};
  424. }
  425.  
  426. # Replace the content of a file
  427. sub replace_content {
  428.     my ($self) = shift;
  429.     my ($file,$content) = @_;
  430.     my $entry;
  431.  
  432.     ($entry) = grep {$_->{name} eq $file} @{$self->{'_data'}};
  433.     if ($entry) {
  434.     $entry->{'data'} = $content;
  435.     return 1;
  436.     }
  437.     else {
  438.     return undef;
  439.     }
  440. }
  441.  
  442. # Add data as a file
  443. sub add_data {
  444.     my ($self, $file, $data, $opt) = @_;
  445.     my $ref = {};
  446.     my ($key);
  447.     
  448.     $ref->{'data'}=$data;
  449.     $ref->{name}=$file;
  450.     $ref->{mode}=0666&(0777-umask);
  451.     $ref->{uid}=$>;
  452.     $ref->{gid}=(split(/ /,$)))[0]; # Yuck
  453.     $ref->{size}=length $data;
  454.     $ref->{mtime}=time;
  455.     $ref->{chksum}="      ";    # Utterly pointless
  456.     $ref->{typeflag}=0;        # Ordinary file
  457.     $ref->{linkname}="";
  458.     $ref->{magic}="ustar\0";
  459.     $ref->{version}="00";
  460.     # WinNT protection
  461.     $ref->{uname}=$has_getpwuid?(getpwuid($>))[0]:"unknown";
  462.     $ref->{gname}=$has_getgrgid?(getgrgid($ref->{gid}))[0]:"unknown";
  463.     $ref->{devmajor}=0;
  464.     $ref->{devminor}=0;
  465.     $ref->{prefix}="";
  466.  
  467.     if ($opt) {
  468.     foreach $key (keys %$opt) {
  469.         $ref->{$key} = $opt->{$key}
  470.     }
  471.     }
  472.  
  473.     push(@{$self->{'_data'}},$ref);
  474.     return 1;
  475. }
  476.  
  477. # Write a single (probably) file from the in-memory archive to disk
  478. sub extract {
  479.     my $self = shift;
  480.     my (@files) = @_;
  481.     my ($file, $current, @path);
  482.  
  483.     foreach $file (@files) {
  484.     foreach (@{$self->{'_data'}}) {
  485.         if ($_->{name} eq $file) {
  486.         # For the moment, we assume that all paths in tarfiles
  487.         # are given according to Unix standards.
  488.         # Which they *are*, according to the tar format spec!
  489.         (@path) = split(/\//,$file);
  490.         $file = pop @path;
  491.         $current = cwd;
  492.         foreach (@path) {
  493.             if (-e $_ && ! -d $_) {
  494.             warn "$_ exists but is not a directory!\n";
  495.             next;
  496.             }
  497.             mkdir $_,0777 unless -d $_;
  498.             chdir $_;
  499.         }
  500.         if (not $_->{typeflag}) { # Ordinary file
  501.             open(FILE,">".$file);
  502.             binmode FILE;
  503.             print FILE $_->{'data'};
  504.             close FILE;
  505.         }
  506.         elsif ($_->{typeflag}==5) { # Directory
  507.             if (-e $file && ! -d $file) {
  508.             drat;
  509.             }
  510.             mkdir $file,0777 unless -d $file;
  511.         }
  512.         elsif ($_->{typeflag}==1) {
  513.             symlink $_->{linkname},$file if $symlinks;
  514.         }
  515.         elsif ($_->{typeflag}==6) {
  516.             warn "Doesn't handle named pipes (yet).\n";
  517.             return 1;
  518.         }
  519.         elsif ($_->{typeflag}==4) {
  520.             warn "Doesn't handle device files (yet).\n";
  521.             return 1;
  522.         }
  523.         elsif ($_->{typeflag}==3) {
  524.             warn "Doesn't handle device files (yet).\n";
  525.             return 1;
  526.         }
  527.         else {
  528.             $error = "unknown file type: $_->{typeflag}";
  529.             return undef;
  530.         }
  531.         utime time, $_->{mtime}, $file;
  532.         # We are root, and chown exists
  533.         if ($>==0 and $^O ne "MacOS" and $^O ne "MSWin32") {
  534.             chown $_->{uid},$_->{gid},$file;
  535.         }
  536.         # chmod is done last, in case it makes file readonly
  537.         # (this accomodates DOSish OSes)
  538.         chmod $_->{mode},$file;
  539.         chdir $current;
  540.         }
  541.     }
  542.     }
  543. }
  544.  
  545. # Return a list of all filenames in in-memory archive.
  546. sub list_files {
  547.     my ($self) = shift;
  548.  
  549.     return map {$_->{name}} @{$self->{'_data'}};
  550. }
  551.  
  552.  
  553. ### Standard end of module :-)
  554. 1;
  555.  
  556. =head1 NAME
  557.  
  558. Tar - module for manipulation of tar archives.
  559.  
  560. =head1 SYNOPSIS
  561.  
  562.   use Archive::Tar;
  563.  
  564.   $tar = Archive::Tar->new();
  565.   $tar->read("origin.tar.gz",1);
  566.   $tar->add_files("file/foo.c", "file/bar.c");
  567.   $tar->add_data("file/baz.c","This is the file contents");
  568.   $tar->write("files.tar");
  569.  
  570. =head1 DESCRIPTION
  571.  
  572. This is a module for the handling of tar archives. 
  573.  
  574. At the moment these methods are implemented:
  575.  
  576. =over 4
  577.  
  578. =item C<new()>
  579.  
  580. Returns a new Tar object. If given a filename as an argument, it will
  581. try to load that as a tar file. If given a true value as a second
  582. argument, will assume that the tar file is compressed, and will
  583. attempt to read it using L<Compress::Zlib>.
  584.  
  585. =item C<add_files(@filenamelist)>
  586.  
  587. Takes a list of filenames and adds them to the in-memory archive. 
  588. I suspect that this function will produce bogus tar archives when 
  589. used under MacOS, but I'm not sure and I have no Mac to test it on.
  590.  
  591. =item C<add_data($filename,$data,$opthashref)>
  592.  
  593. Takes a filename, a scalar full of data and optionally a reference to
  594. a hash with specific options. Will add a file to the in-memory
  595. archive, with name C<$filename> and content C<$data>. Specific options
  596. can be set using C<$opthashref>, which will be documented later.
  597.  
  598. =item C<remove(@filenamelist)>
  599.  
  600. Removes any entries with names matching any of the given filenames
  601. from the in-memory archive. String comparisons are done with C<eq>.
  602.  
  603. =item C<read('F<file.tar>',$compressed)>
  604.  
  605. Try to read the given tarfile into memory. If the second argument is a
  606. true value, the tarfile is assumed to be compressed. Will I<replace>
  607. any previous content in C<$tar>!
  608.  
  609. =item C<write('F<file.tar>',$compressed)>
  610.  
  611. Will write the in-memory archive to disk. If no filename is given,
  612. returns the entire formatted archive as a string, which should be
  613. useful if you'd like to stuff the archive into a socket or a pipe to
  614. gzip or something. If the second argument is true, the module will try
  615. to write the file compressed.
  616.  
  617. =item C<data()>
  618.  
  619. Returns the in-memory archive. This is a list of references to hashes,
  620. the internals of which is not currently documented.
  621.  
  622. =item C<extract(@filenames)>
  623.  
  624. Write files whose names are equivalent to any of the names in
  625. C<@filenames> to disk, creating subdirectories as neccesary. This
  626. might not work too well under VMS and MacOS.
  627.  
  628. =item C<list_files()>
  629.  
  630. Returns a list with the names of all files in the in-memory archive.
  631.  
  632. =item C<get_content($file)>
  633.  
  634. Return the content of the named file.
  635.  
  636. =item C<replace_content($file,$content)>
  637.  
  638. Make the string $content be the content for the file named $file.
  639.  
  640. =back
  641.  
  642. =head1 CHANGES
  643.  
  644. =over 4
  645.  
  646. =item Version 0.071
  647.  
  648. Minor release.
  649.  
  650. Arrange to chmod() at the very end in case it makes the file readonly.
  651. Win32 is actually picky about that.
  652.  
  653. SunOS 4.x tar makes tarfiles that contain directory entries
  654. that don't have typeflag set properly.  We use the trailing
  655. slash to recognize directories in such tarfiles.
  656.  
  657. =item Version 0.07
  658.  
  659. Fixed (hopefully) broken portability to MacOS, reported by Paul J.
  660. Schinder at Goddard Space Flight Center.
  661.  
  662. Fixed two bugs with symlink handling, reported in excellent detail by
  663. an admin at teleport.com called Chris.
  664.  
  665. Primive tar program (called ptar) included with distribution. Useage
  666. should be pretty obvious if you've used a normal tar program.
  667.  
  668. Added methods get_content and replace_content.
  669.  
  670. Added support for paths longer than 100 characters, according to
  671. POSIX. This is compatible with just about everything except GNU tar.
  672. Way to go, GNU tar (use a better tar, or GNU cpio). 
  673.  
  674. NOTE: When adding files to an archive, files with basenames longer
  675.       than 100 characters will be silently ignored. If the prefix part
  676.       of a path is longer than 155 characters, only the last 155
  677.       characters will be stored.
  678.  
  679. =item Version 0.06
  680.  
  681. Added list_files() method, as requested by Michael Wiedman.
  682.  
  683. Fixed a couple of dysfunctions when run under Windows NT. Michael
  684. Wiedmann reported the bugs.
  685.  
  686. Changed the documentation to reflect reality a bit better.
  687.  
  688. Fixed bug in format_tar_entry. Bug reported by Michael Schilli.
  689.  
  690. =item Version 0.05
  691.  
  692. Quoted lots of barewords to make C<use strict;> stop complaining under
  693. perl version 5.003.
  694.  
  695. Ties to L<Compress::Zlib> put in. Will warn if it isn't available.
  696.  
  697. $tar->write() with no argument now returns the formatted archive.
  698.  
  699. =item Version 0.04
  700.  
  701. Made changes to write_tar so that Solaris tar likes the resulting
  702. archives better.
  703.  
  704. Protected the calls to readlink() and symlink(). AFAIK this module
  705. should now run just fine on Windows NT.
  706.  
  707. Add method to write a single entry to disk (extract)
  708.  
  709. Added method to add entries entirely from scratch (add_data)
  710.  
  711. Changed name of add() to add_file()
  712.  
  713. All calls to croak() removed and replaced with returning undef and
  714. setting Tar::error.
  715.  
  716. Better handling of tarfiles with garbage at the end.
  717.  
  718. =cut
  719.