forked from josch/mmdebstrap
Instead of re-execing mmdebstrap under /bin/sh, use Text::ParseWords::shellwords
- saves a few PIDs - saves a bit of time because useless exec and fork is avoided - allows to run in pivoted chroots without mmdebstrap
This commit is contained in:
parent
d2238c891b
commit
eb54f6a23a
1 changed files with 27 additions and 47 deletions
74
mmdebstrap
74
mmdebstrap
|
@ -45,6 +45,7 @@ use Term::ANSIColor;
|
||||||
use Socket;
|
use Socket;
|
||||||
use Time::HiRes;
|
use Time::HiRes;
|
||||||
use Math::BigInt;
|
use Math::BigInt;
|
||||||
|
use Text::ParseWords;
|
||||||
use version;
|
use version;
|
||||||
|
|
||||||
## no critic (InputOutput::RequireBriefOpen)
|
## no critic (InputOutput::RequireBriefOpen)
|
||||||
|
@ -1659,24 +1660,12 @@ sub run_hooks {
|
||||||
open(STDIN, '<&', $options->{hooksock})
|
open(STDIN, '<&', $options->{hooksock})
|
||||||
or error "cannot open STDIN: $!";
|
or error "cannot open STDIN: $!";
|
||||||
|
|
||||||
# we execute ourselves under sh to avoid having to
|
# Text::ParseWords::shellwords does for perl what shlex
|
||||||
# implement a clever parser of the quoting used in $script
|
# does for python
|
||||||
# for the filenames
|
my @args = shellwords $script;
|
||||||
my $prefix = "";
|
hookhelper($options->{root}, $options->{mode}, $name,
|
||||||
if ($is_covering) {
|
$options->{qemu}, $verbosity_level, @args);
|
||||||
$prefix
|
exit 0;
|
||||||
= "$EXECUTABLE_NAME -MDevel::Cover=-silent,-nogcov ";
|
|
||||||
}
|
|
||||||
exec 'sh', '-c',
|
|
||||||
"$prefix$PROGRAM_NAME --hook-helper"
|
|
||||||
. " \"\$1\" \"\$2\" \"\$3\" \"\$4\" \"\$5\" $script",
|
|
||||||
'exec', $options->{root}, $options->{mode}, $name,
|
|
||||||
(
|
|
||||||
defined $options->{qemu}
|
|
||||||
? "qemu-$options->{qemu}"
|
|
||||||
: 'env',
|
|
||||||
$verbosity_level
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
waitpid($pid, 0);
|
waitpid($pid, 0);
|
||||||
$? == 0 or error "special hook failed with exit code $?";
|
$? == 0 or error "special hook failed with exit code $?";
|
||||||
|
@ -3176,16 +3165,12 @@ sub chrooted_realpath {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hookhelper {
|
sub hookhelper {
|
||||||
|
my ($root, $mode, $hook, $qemu, $verbosity, $command, @args) = @_;
|
||||||
|
$verbosity_level = $verbosity;
|
||||||
# we put everything in an eval block because that way we can easily handle
|
# we put everything in an eval block because that way we can easily handle
|
||||||
# errors without goto labels or much code duplication: the error handler
|
# errors without goto labels or much code duplication: the error handler
|
||||||
# has to send an "error" message to the other side
|
# has to send an "error" message to the other side
|
||||||
eval {
|
eval {
|
||||||
my $root = $ARGV[1];
|
|
||||||
my $mode = $ARGV[2];
|
|
||||||
my $hook = $ARGV[3];
|
|
||||||
my $qemu = $ARGV[4];
|
|
||||||
$verbosity_level = $ARGV[5];
|
|
||||||
my $command = $ARGV[6];
|
|
||||||
|
|
||||||
my @cmdprefix = ();
|
my @cmdprefix = ();
|
||||||
my @tarcmd = (
|
my @tarcmd = (
|
||||||
|
@ -3213,12 +3198,12 @@ sub hookhelper {
|
||||||
any { $_ eq $command }
|
any { $_ eq $command }
|
||||||
('copy-in', 'tar-in', 'upload', 'sync-in')
|
('copy-in', 'tar-in', 'upload', 'sync-in')
|
||||||
) {
|
) {
|
||||||
if (scalar @ARGV < 9) {
|
if (scalar @args < 2) {
|
||||||
error "$command needs at least one path on the"
|
error "$command needs at least one path on the"
|
||||||
. " outside and the output path inside the chroot";
|
. " outside and the output path inside the chroot";
|
||||||
}
|
}
|
||||||
my $outpath = $ARGV[-1];
|
my $outpath = pop @args;
|
||||||
for (my $i = 7 ; $i < $#ARGV ; $i++) {
|
foreach my $file (@args) {
|
||||||
# the right argument for tar's --directory argument depends on
|
# the right argument for tar's --directory argument depends on
|
||||||
# whether tar is called from inside the chroot or from the
|
# whether tar is called from inside the chroot or from the
|
||||||
# outside
|
# outside
|
||||||
|
@ -3288,20 +3273,17 @@ sub hookhelper {
|
||||||
# instruct the parent process to create a tarball of the
|
# instruct the parent process to create a tarball of the
|
||||||
# requested path outside the chroot
|
# requested path outside the chroot
|
||||||
debug "helper: sending mktar";
|
debug "helper: sending mktar";
|
||||||
print STDOUT (
|
print STDOUT (pack("n", length $file) . "mktar" . $file);
|
||||||
pack("n", length $ARGV[$i]) . "mktar" . $ARGV[$i]);
|
|
||||||
} elsif ($command eq 'sync-in') {
|
} elsif ($command eq 'sync-in') {
|
||||||
# instruct the parent process to create a tarball of the
|
# instruct the parent process to create a tarball of the
|
||||||
# content of the requested path outside the chroot
|
# content of the requested path outside the chroot
|
||||||
debug "helper: sending mktac";
|
debug "helper: sending mktac";
|
||||||
print STDOUT (
|
print STDOUT (pack("n", length $file) . "mktac" . $file);
|
||||||
pack("n", length $ARGV[$i]) . "mktac" . $ARGV[$i]);
|
|
||||||
} elsif (any { $_ eq $command } ('upload', 'tar-in')) {
|
} elsif (any { $_ eq $command } ('upload', 'tar-in')) {
|
||||||
# instruct parent process to open a tarball of the
|
# instruct parent process to open a tarball of the
|
||||||
# requested path outside the chroot for reading
|
# requested path outside the chroot for reading
|
||||||
debug "helper: sending openr";
|
debug "helper: sending openr";
|
||||||
print STDOUT (
|
print STDOUT (pack("n", length $file) . "openr" . $file);
|
||||||
pack("n", length $ARGV[$i]) . "openr" . $ARGV[$i]);
|
|
||||||
} else {
|
} else {
|
||||||
error "unknown command: $command";
|
error "unknown command: $command";
|
||||||
}
|
}
|
||||||
|
@ -3360,31 +3342,31 @@ sub hookhelper {
|
||||||
any { $_ eq $command }
|
any { $_ eq $command }
|
||||||
('copy-out', 'tar-out', 'download', 'sync-out')
|
('copy-out', 'tar-out', 'download', 'sync-out')
|
||||||
) {
|
) {
|
||||||
if (scalar @ARGV < 9) {
|
if (scalar @args < 2) {
|
||||||
error "$command needs at least one path inside the chroot and"
|
error "$command needs at least one path inside the chroot and"
|
||||||
. " the output path on the outside";
|
. " the output path on the outside";
|
||||||
}
|
}
|
||||||
my $outpath = $ARGV[-1];
|
my $outpath = pop @args;
|
||||||
for (my $i = 7 ; $i < $#ARGV ; $i++) {
|
foreach my $file (@args) {
|
||||||
# the right argument for tar's --directory argument depends on
|
# the right argument for tar's --directory argument depends on
|
||||||
# whether tar is called from inside the chroot or from the
|
# whether tar is called from inside the chroot or from the
|
||||||
# outside
|
# outside
|
||||||
my $directory;
|
my $directory;
|
||||||
if ($hook eq 'setup') {
|
if ($hook eq 'setup') {
|
||||||
# tar runs outside, so acquire the correct path
|
# tar runs outside, so acquire the correct path
|
||||||
$directory = chrooted_realpath $root, $ARGV[$i];
|
$directory = chrooted_realpath $root, $file;
|
||||||
} elsif (
|
} elsif (
|
||||||
any { $_ eq $hook }
|
any { $_ eq $hook }
|
||||||
('extract', 'essential', 'customize')
|
('extract', 'essential', 'customize')
|
||||||
) {
|
) {
|
||||||
if ($mode eq 'fakechroot') {
|
if ($mode eq 'fakechroot') {
|
||||||
# tar will run inside the chroot
|
# tar will run inside the chroot
|
||||||
$directory = $ARGV[$i];
|
$directory = $file;
|
||||||
} elsif (
|
} elsif (
|
||||||
any { $_ eq $mode }
|
any { $_ eq $mode }
|
||||||
('root', 'chrootless', 'unshare')
|
('root', 'chrootless', 'unshare')
|
||||||
) {
|
) {
|
||||||
$directory = chrooted_realpath $root, $ARGV[$i];
|
$directory = chrooted_realpath $root, $file;
|
||||||
} else {
|
} else {
|
||||||
error "unknown mode: $mode";
|
error "unknown mode: $mode";
|
||||||
}
|
}
|
||||||
|
@ -3497,11 +3479,11 @@ sub hookhelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hooklistener {
|
sub hooklistener {
|
||||||
|
$verbosity_level = shift;
|
||||||
# we put everything in an eval block because that way we can easily handle
|
# we put everything in an eval block because that way we can easily handle
|
||||||
# errors without goto labels or much code duplication: the error handler
|
# errors without goto labels or much code duplication: the error handler
|
||||||
# has to send an "error" message to the other side
|
# has to send an "error" message to the other side
|
||||||
eval {
|
eval {
|
||||||
$verbosity_level = $ARGV[1];
|
|
||||||
while (1) {
|
while (1) {
|
||||||
# get the next message
|
# get the next message
|
||||||
my $msg = "error";
|
my $msg = "error";
|
||||||
|
@ -4235,14 +4217,15 @@ sub main() {
|
||||||
umask 022;
|
umask 022;
|
||||||
|
|
||||||
if (scalar @ARGV >= 7 && $ARGV[0] eq "--hook-helper") {
|
if (scalar @ARGV >= 7 && $ARGV[0] eq "--hook-helper") {
|
||||||
hookhelper();
|
shift @ARGV; # shift off "--hook-helper"
|
||||||
|
hookhelper(@ARGV);
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# this is the counterpart to --hook-helper and will receive and carry
|
# this is the counterpart to --hook-helper and will receive and carry
|
||||||
# out its instructions
|
# out its instructions
|
||||||
if (scalar @ARGV == 2 && $ARGV[0] eq "--hook-listener") {
|
if (scalar @ARGV == 2 && $ARGV[0] eq "--hook-listener") {
|
||||||
hooklistener();
|
hooklistener($ARGV[1]);
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5812,11 +5795,8 @@ sub main() {
|
||||||
open(STDIN, '<&', $parentsock)
|
open(STDIN, '<&', $parentsock)
|
||||||
or error "cannot open STDIN: $!";
|
or error "cannot open STDIN: $!";
|
||||||
|
|
||||||
my @prefix = ();
|
hooklistener($verbosity_level);
|
||||||
if ($is_covering) {
|
exit 0;
|
||||||
@prefix = ($EXECUTABLE_NAME, "-MDevel::Cover=-silent,-nogcov");
|
|
||||||
}
|
|
||||||
exec @prefix, $PROGRAM_NAME, "--hook-listener", $verbosity_level;
|
|
||||||
}
|
}
|
||||||
waitpid($lpid, 0);
|
waitpid($lpid, 0);
|
||||||
if ($? != 0) {
|
if ($? != 0) {
|
||||||
|
|
Loading…
Reference in a new issue