momo33 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I would like to manipulate a cpio archive. CPAN has http://search.cpan.org/~pixel/Archive-Cpio-0.07/ This looks just what I need. Unfortunately, it does not what I expect.

Im my cpio archive test.cpio are three files: test1, test2, and test3

use Archive::Cpio; my $cpio = Archive::Cpio->new; $cpio->read('test.cpio'); $cpio->remove('test1'); $cio->write('newtest.cpio');

Unfortunately, test.cpio is identical to newtest.cpio; I want test1 to be gone. Is this a bug or my mistake?

One step further, I would like to insert a new file: new1. The docs give me $cpio->add_data($filename, $data, $opthashref).
$cpio->add_data('new1',$data, ???) did not do it. In addition, I have no idea about $opthashref. Any suggestions?

Thank you.

Replies are listed 'Best First'.
Re: manipulating cpio archive
by Corion (Patriarch) on Jan 16, 2011 at 20:29 UTC

    Seeing that Archive::Cpio::read is implemented as

    sub read { my ($cpio, $file) = @_; my $IN; if (ref $file) { $IN = $file; } else { open($IN, '<', $file) or die "can't open $file: $!\n"; } read_with_handler($cpio, $IN, sub { my ($e) = @_; push @{$cpio->{list}}, $e; });

    and Archive::Cpio::remove is implemented as

    sub remove { my ($cpio, @filenames) = @_; $cpio->{list} or die "can't remove from nothing\n"; my %filenames = map { $_ => 1 } @filenames; @{$cpio->{list}} = grep { !$filenames{$_} } @{$cpio->{list}}; }

    I would assume that there is no file test1 in your cpio archive. Maybe there is a directory name prepended? Have a look at what information Archive::Cpio actually reads from your archive, and/or what your archive actually contains.

      Thank you for your reply.
      I tried it again, and made better notes. My archive is td.cpio:
      $ cpio --list -i <td.cpio . t2 t1 t3 1 block $
      My script is
      #!/opt/ActivePerl-5.12/bin/perl use Archive::Cpio; my $cpio = Archive::Cpio->new; $cpio->read('td.cpio'); $cpio->remove('t1'); $cpio->write('tdnew.cpio');
      The output tdnew.cpio is identical to td.cpio

      I think the answer is in the Archive::Cpio code. The entry should be removed in

      sub remove { my ($cpio, @filenames) = @_; $cpio->{list} or die "can't remove from nothing\n"; my %filenames = map { $_ => 1 } @filenames; @{$cpio->{list}} = grep { !$filenames{$_} } @{$cpio->{list}}; }
      I cannot decipher that last line but I do not like it (I may be completely wrong).

      How can I get this right? Thank you.

        I would now look inside the Archive::Cpio object (using Data::Dumper) to see what it contains, before and after your modification.