/usr/share/perl5/Dpkg/Source/Archive.pm is in libdpkg-perl 1.18.25.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | # Copyright © 2008 Raphaël Hertzog <hertzog@debian.org>
#
# 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, see <https://www.gnu.org/licenses/>.
package Dpkg::Source::Archive;
use strict;
use warnings;
our $VERSION = '0.01';
use Carp;
use File::Temp qw(tempdir);
use File::Basename qw(basename);
use File::Spec;
use Cwd;
use Dpkg ();
use Dpkg::Gettext;
use Dpkg::ErrorHandling;
use Dpkg::IPC;
use Dpkg::Source::Functions qw(erasedir fixperms);
use parent qw(Dpkg::Compression::FileHandle);
sub create {
my ($self, %opts) = @_;
$opts{options} //= [];
my %spawn_opts;
# Possibly run tar from another directory
if ($opts{chdir}) {
$spawn_opts{chdir} = $opts{chdir};
*$self->{chdir} = $opts{chdir};
}
# Redirect input/output appropriately
$self->ensure_open('w');
$spawn_opts{to_handle} = $self->get_filehandle();
$spawn_opts{from_pipe} = \*$self->{tar_input};
# Try to use a deterministic mtime.
my $mtime = $opts{source_date} // $ENV{SOURCE_DATE_EPOCH} || time;
# Call tar creation process
$spawn_opts{delete_env} = [ 'TAR_OPTIONS' ];
$spawn_opts{exec} = [ $Dpkg::PROGTAR, '-cf', '-', '--format=gnu', '--sort=name',
'--mtime', "\@$mtime", '--clamp-mtime', '--null',
'--numeric-owner', '--owner=0', '--group=0',
@{$opts{options}}, '-T', '-' ];
*$self->{pid} = spawn(%spawn_opts);
*$self->{cwd} = getcwd();
}
sub _add_entry {
my ($self, $file) = @_;
my $cwd = *$self->{cwd};
croak 'call create() first' unless *$self->{tar_input};
$file = $2 if ($file =~ /^\Q$cwd\E\/(.+)$/); # Relative names
print({ *$self->{tar_input} } "$file\0")
or syserr(g_('write on tar input'));
}
sub add_file {
my ($self, $file) = @_;
my $testfile = $file;
if (*$self->{chdir}) {
$testfile = File::Spec->catfile(*$self->{chdir}, $file);
}
croak 'add_file() does not handle directories'
if not -l $testfile and -d _;
$self->_add_entry($file);
}
sub add_directory {
my ($self, $file) = @_;
my $testfile = $file;
if (*$self->{chdir}) {
$testfile = File::Spec->catdir(*$self->{chdir}, $file);
}
croak 'add_directory() only handles directories'
if -l $testfile or not -d _;
$self->_add_entry($file);
}
sub finish {
my $self = shift;
close(*$self->{tar_input}) or syserr(g_('close on tar input'));
wait_child(*$self->{pid}, cmdline => 'tar -cf -');
delete *$self->{pid};
delete *$self->{tar_input};
delete *$self->{cwd};
delete *$self->{chdir};
$self->close();
}
sub extract {
my ($self, $dest, %opts) = @_;
$opts{options} //= [];
$opts{in_place} //= 0;
$opts{no_fixperms} //= 0;
my %spawn_opts = (wait_child => 1);
# Prepare destination
my $tmp;
if ($opts{in_place}) {
$spawn_opts{chdir} = $dest;
$tmp = $dest; # So that fixperms call works
} else {
my $template = basename($self->get_filename()) . '.tmp-extract.XXXXX';
unless (-e $dest) {
# Kludge so that realpath works
mkdir($dest) or syserr(g_('cannot create directory %s'), $dest);
}
$tmp = tempdir($template, DIR => Cwd::realpath("$dest/.."), CLEANUP => 1);
$spawn_opts{chdir} = $tmp;
}
# Prepare stuff that handles the input of tar
$self->ensure_open('r', delete_sig => [ 'PIPE' ]);
$spawn_opts{from_handle} = $self->get_filehandle();
# Call tar extraction process
$spawn_opts{delete_env} = [ 'TAR_OPTIONS' ];
$spawn_opts{exec} = [ $Dpkg::PROGTAR, '-xf', '-', '--no-same-permissions',
'--no-same-owner', @{$opts{options}} ];
spawn(%spawn_opts);
$self->close();
# Fix permissions on extracted files because tar insists on applying
# our umask _to the original permissions_ rather than mostly-ignoring
# the original permissions.
# We still need --no-same-permissions because otherwise tar might
# extract directory setgid (which we want inherited, not
# extracted); we need --no-same-owner because putting the owner
# back is tedious - in particular, correct group ownership would
# have to be calculated using mount options and other madness.
fixperms($tmp) unless $opts{no_fixperms};
# Stop here if we extracted in-place as there's nothing to move around
return if $opts{in_place};
# Rename extracted directory
opendir(my $dir_dh, $tmp) or syserr(g_('cannot opendir %s'), $tmp);
my @entries = grep { $_ ne '.' && $_ ne '..' } readdir($dir_dh);
closedir($dir_dh);
my $done = 0;
erasedir($dest);
if (scalar(@entries) == 1 && ! -l "$tmp/$entries[0]" && -d _) {
rename("$tmp/$entries[0]", $dest)
or syserr(g_('unable to rename %s to %s'),
"$tmp/$entries[0]", $dest);
} else {
rename($tmp, $dest)
or syserr(g_('unable to rename %s to %s'), $tmp, $dest);
}
erasedir($tmp);
}
1;
|