2

I'm trying to set the file permissions of files contained in a tarball with the following:

print "Checking $tgz_file... ";
my $edited = 0;
my $tarball = Archive::Tar->new($tgz_file);
my @items = $tarball->get_files();
foreach (@items) {
    if ($_->is_dir && $_->mode != 0755) {
        $_->mode(0755);
        $edited = 1;
    } elsif ($_->is_file && $_->mode != 0644) {
        $_->mode(0644);
        $edited = 1;
    }
}
if ($edited) {
    $tarball->write($tgz_file, COMPRESS_GZIP);
    print "edited!\n";
} else {
    print "no changes.\n";
}

But when the write() method is called, the script dies with the following error:

Out of memory during "large" request for 268439552 bytes, total sbrk() is 313298944 bytes at /usr/lib/perl5/5.10/i686-cygwin/IO/Compress/Adapter/Deflate.pm line 43.

The tarball triggering this error is 22MB (59MB uncompressed), so the numbers above are a little alarming. Am I dealing with a bug in IO::Compress? Is there some kind of workaround in this case? I'm using perl 5.10.1 for i686-cygwin-thread-multi-64int.

Richard Simões
  • 12,401
  • 6
  • 41
  • 50

1 Answers1

4

This is a shot in the dark, but can you try the following script?

#!/usr/bin/perl

use strict; use warnings;
use Archive::Tar;

my $in = '...';
my $out = "edited-$in";

print "Checking $in ...\n";

my $out_archive = Archive::Tar->new;

my $edited;
my $next = Archive::Tar->iter($in);

while ( my $item = $next->() ) {
    if ($item->is_dir and $item->mode != 0755) {
        $item->mode(0755);
        $edited = 1;
    } elsif ($item->is_file and $item->mode != 0644) {
        $item->mode(0644);
        $edited = 1;
    }
    $out_archive->add_files( $item );
}

if ( $edited ) {
    print "Writing $out ...\n";
    $out_archive->write($out);
}
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • Your code doesn't trigger the error with my large file. I suppose I can then use the tar binary to gzip it and thus avoid Deflate.pm altogether. – Richard Simões Aug 12 '10 at 22:20
  • Well, I had intended to specify `COMPRESS_GZIP` in the `write` call. Would you mind trying it that way as well, for my edification. – Sinan Ünür Aug 12 '10 at 22:43
  • After adding `COMPRESS_GZIP`, the same error is thrown on `write()`. – Richard Simões Aug 12 '10 at 22:47
  • Incidentally, using `IO::Compress::Gzip` on the uncompressed tar file generated by `Archive::Tar` doesn't trigger this error. – Richard Simões Aug 12 '10 at 22:49
  • @Bipedal: if you can distill this down to a clearer reproduction case (perhaps by isolating which interfaces cause the error and which do not), you should file a bug with the module author, at http://rt.cpan.org. – Ether Aug 13 '10 at 00:24