#!/usr/bin/perl # unpacked -- lintian collector/unpack script # # Copyright (C) 1998 Christian Schwarz and Richard Braakman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, you can find it on the World Wide # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. use strict; use warnings; use lib "$ENV{'LINTIAN_ROOT'}/lib"; use Lintian::Command qw(spawn); use Util; ($#ARGV == 2) or fail('syntax: unpacked '); my ($pkg, $type, $dir) = @ARGV; if (-d "$dir/unpacked/") { delete_dir ("$dir/unpacked/") or fail("failed to remove unpacked directory of $pkg"); } if (-f "$dir/unpacked-errors") { unlink ("$dir/unpacked-errors") or fail("failed to remove unpacked-errors file of $pkg"); } # If we are asked to only remove the files stop right here if ($type =~ m/^remove-/) { exit 0; } if ($type eq 'source') { if (can_use_dpkg_source()) { # Ignore STDOUT of the child process because older versions of # dpkg-source print things out even with -q. my $opts = { out => '/dev/null', err => "$dir/unpacked-errors" }; my @args = ('-q'); push @args, '--no-check' if $ENV{'LINTIAN_COLL_UNPACKED_SKIP_SIG'}; print "N: Using dpkg-source to unpack $pkg\n" if $ENV{'LINTIAN_DEBUG'}; unless (spawn ($opts, ['dpkg-source', @args, '-x', "$dir/dsc", "$dir/unpacked"])) { open ERRORS, '<', "$dir/unpacked-errors" or fail("cannot open unpacked-errors: $!"); print STDERR while ; close ERRORS; fail('dpkg-source -x failed with status ', $opts->{harness}->result); } } else { print "N: Using libdpkg-perl to unpack $pkg\n" if $ENV{'LINTIAN_DEBUG'}; libdpkg_unpack_dsc("$dir/dsc", "$dir/unpacked"); } # fix permissions spawn({ fail => 'error' }, ['chmod', '-R', 'u+rwX,o+rX,o-w', "$dir/unpacked"]); } else { mkdir ("$dir/unpacked", 0777) or fail "mkdir unpacked: $!"; # avoid using dpkg-deb -x; this pipeline is far faster. I got a factor 2 # improvement on large debs, and factor 1.5 on small debs. # I heard it's because dpkg-deb syncs while writing. -- Richard my $opts = { err => "$dir/unpacked-errors" }; spawn($opts, ['dpkg-deb', '--fsys-tarfile', "$dir/deb"], '|', ['tar', 'xf', '-', '-C', "$dir/unpacked"]); unless ($opts->{success}) { open ERRORS, '<', "$dir/unpacked-errors" or fail("cannot open unpacked-errors: $!"); print STDERR while ; close ERRORS; fail('dpkg-deb | tar failed with status ', $opts->{harness}->result); } # fix permissions spawn({ fail => 'error' }, ['chmod', '-R', 'u+rwX,go-w', "$dir/unpacked"]); } sub libdpkg_unpack_dsc { my ($dsc, $target) = @_; my $opt = { # This is used to make check_signature fatal 'require_valid_signature' => 1, 'quiet' => 1 }; require Dpkg::Source::Package; open(STDOUT, '>', '/dev/null') or fail "Redirecting stdout failed: $!"; # Create the object that does everything my $srcpkg = Dpkg::Source::Package->new(filename => $dsc, options => $opt); $srcpkg->check_checksums(); if ($srcpkg->is_signed() && !$ENV{'LINTIAN_COLL_UNPACKED_SKIP_SIG'}) { $srcpkg->check_signature(); } # Unpack the source package (delegated to Dpkg::Source::Package::*) $srcpkg->extract($target); return 1; } sub can_use_dpkg_source{ my $test = $ENV{LINTIAN_TEST_FEATURE}; return 0 if defined $test && $test =~ m/unpack-libdpkg-perl/; return check_path('dpkg-source'); } # Local Variables: # indent-tabs-mode: nil # cperl-indent-level: 4 # End: # vim: syntax=perl sw=4 sts=4 sr et