Instead of mounting and unmounting for each run_chroot() call, do it once before the extract hook and unmount after the customize hooks
This commit is contained in:
parent
eb54f6a23a
commit
449fb248e2
1 changed files with 112 additions and 126 deletions
238
mmdebstrap
238
mmdebstrap
|
@ -1109,28 +1109,11 @@ sub run_apt_download_progress {
|
||||||
return @listofdebs;
|
return @listofdebs;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub run_chroot {
|
sub setup_mounts {
|
||||||
my $cmd = shift;
|
|
||||||
my $options = shift;
|
my $options = shift;
|
||||||
|
|
||||||
my @cleanup_tasks = ();
|
my @cleanup_tasks = ();
|
||||||
|
|
||||||
my $cleanup = sub {
|
|
||||||
my $signal = $_[0];
|
|
||||||
while (my $task = pop @cleanup_tasks) {
|
|
||||||
$task->();
|
|
||||||
}
|
|
||||||
if ($signal) {
|
|
||||||
warning "pid $PID cought signal: $signal";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
local $SIG{INT} = $cleanup;
|
|
||||||
local $SIG{HUP} = $cleanup;
|
|
||||||
local $SIG{PIPE} = $cleanup;
|
|
||||||
local $SIG{TERM} = $cleanup;
|
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
if (any { $_ eq $options->{mode} } ('root', 'unshare')) {
|
if (any { $_ eq $options->{mode} } ('root', 'unshare')) {
|
||||||
# if more than essential should be installed, make the system look
|
# if more than essential should be installed, make the system look
|
||||||
|
@ -1496,6 +1479,12 @@ sub run_chroot {
|
||||||
if (any { $_ eq 'chroot/policy-rc.d' } @{ $options->{skip} }) {
|
if (any { $_ eq 'chroot/policy-rc.d' } @{ $options->{skip} }) {
|
||||||
info "skipping chroot/policy-rc.d as requested";
|
info "skipping chroot/policy-rc.d as requested";
|
||||||
} else {
|
} else {
|
||||||
|
push @cleanup_tasks, sub {
|
||||||
|
if (-f "$options->{root}/usr/sbin/policy-rc.d") {
|
||||||
|
unlink "$options->{root}/usr/sbin/policy-rc.d"
|
||||||
|
or error "cannot unlink policy-rc.d: $!";
|
||||||
|
}
|
||||||
|
};
|
||||||
if (-d "$options->{root}/usr/sbin/") {
|
if (-d "$options->{root}/usr/sbin/") {
|
||||||
open my $fh, '>', "$options->{root}/usr/sbin/policy-rc.d"
|
open my $fh, '>', "$options->{root}/usr/sbin/policy-rc.d"
|
||||||
or error "cannot open policy-rc.d: $!";
|
or error "cannot open policy-rc.d: $!";
|
||||||
|
@ -1511,6 +1500,14 @@ sub run_chroot {
|
||||||
if (any { $_ eq 'chroot/start-stop-daemon' } @{ $options->{skip} }) {
|
if (any { $_ eq 'chroot/start-stop-daemon' } @{ $options->{skip} }) {
|
||||||
info "skipping chroot/start-stop-daemon as requested";
|
info "skipping chroot/start-stop-daemon as requested";
|
||||||
} else {
|
} else {
|
||||||
|
push @cleanup_tasks, sub {
|
||||||
|
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
||||||
|
move(
|
||||||
|
"$options->{root}/sbin/start-stop-daemon.REAL",
|
||||||
|
"$options->{root}/sbin/start-stop-daemon"
|
||||||
|
) or error "cannot move start-stop-daemon: $!";
|
||||||
|
}
|
||||||
|
};
|
||||||
if (-f "$options->{root}/sbin/start-stop-daemon") {
|
if (-f "$options->{root}/sbin/start-stop-daemon") {
|
||||||
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
||||||
error
|
error
|
||||||
|
@ -1532,40 +1529,12 @@ sub run_chroot {
|
||||||
or error "cannot chmod start-stop-daemon: $!";
|
or error "cannot chmod start-stop-daemon: $!";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&{$cmd}();
|
|
||||||
|
|
||||||
# cleanup
|
|
||||||
if (any { $_ eq 'chroot/start-stop-daemon' } @{ $options->{skip} }) {
|
|
||||||
info "skipping chroot/start-stop-daemon as requested";
|
|
||||||
} else {
|
|
||||||
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
|
||||||
move(
|
|
||||||
"$options->{root}/sbin/start-stop-daemon.REAL",
|
|
||||||
"$options->{root}/sbin/start-stop-daemon"
|
|
||||||
) or error "cannot move start-stop-daemon: $!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (any { $_ eq 'chroot/policy-rc.d' } @{ $options->{skip} }) {
|
|
||||||
info "skipping chroot/policy-rc.d as requested";
|
|
||||||
} else {
|
|
||||||
if (-f "$options->{root}/usr/sbin/policy-rc.d") {
|
|
||||||
unlink "$options->{root}/usr/sbin/policy-rc.d"
|
|
||||||
or error "cannot unlink policy-rc.d: $!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
my $error = $@;
|
if ($@) {
|
||||||
|
error "setup_mounts failed: $@";
|
||||||
# we use the cleanup function to do the unmounting
|
|
||||||
$cleanup->(0);
|
|
||||||
|
|
||||||
if ($error) {
|
|
||||||
error "run_chroot failed: $error";
|
|
||||||
}
|
}
|
||||||
return;
|
return @cleanup_tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub run_hooks {
|
sub run_hooks {
|
||||||
|
@ -1630,7 +1599,14 @@ sub run_hooks {
|
||||||
("MMDEBSTRAP_INCLUDE=" . (join ",", @escaped_includes));
|
("MMDEBSTRAP_INCLUDE=" . (join ",", @escaped_includes));
|
||||||
}
|
}
|
||||||
|
|
||||||
my $runner = sub {
|
# Unset the close-on-exec flag, so that the file descriptor does not
|
||||||
|
# get closed when we exec
|
||||||
|
my $flags = fcntl($options->{hooksock}, F_GETFD, 0)
|
||||||
|
or error "fcntl F_GETFD: $!";
|
||||||
|
fcntl($options->{hooksock}, F_SETFD, $flags & ~FD_CLOEXEC)
|
||||||
|
or error "fcntl F_SETFD: $!";
|
||||||
|
|
||||||
|
{
|
||||||
foreach my $script (@{ $options->{"${name}_hook"} }) {
|
foreach my $script (@{ $options->{"${name}_hook"} }) {
|
||||||
if (
|
if (
|
||||||
$script =~ /^(
|
$script =~ /^(
|
||||||
|
@ -1687,19 +1663,6 @@ sub run_hooks {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
# Unset the close-on-exec flag, so that the file descriptor does not
|
|
||||||
# get closed when we exec
|
|
||||||
my $flags = fcntl($options->{hooksock}, F_GETFD, 0)
|
|
||||||
or error "fcntl F_GETFD: $!";
|
|
||||||
fcntl($options->{hooksock}, F_SETFD, $flags & ~FD_CLOEXEC)
|
|
||||||
or error "fcntl F_SETFD: $!";
|
|
||||||
if ($name eq 'setup') {
|
|
||||||
# execute directly without mounting anything (the mount points do not
|
|
||||||
# exist yet)
|
|
||||||
&{$runner}();
|
|
||||||
} else {
|
|
||||||
run_chroot(\&$runner, $options);
|
|
||||||
}
|
|
||||||
# Restore flags
|
# Restore flags
|
||||||
fcntl($options->{hooksock}, F_SETFD, $flags) or error "fcntl F_SETFD: $!";
|
fcntl($options->{hooksock}, F_SETFD, $flags) or error "fcntl F_SETFD: $!";
|
||||||
return;
|
return;
|
||||||
|
@ -1755,21 +1718,57 @@ sub setup {
|
||||||
# FIXME: dpkg could be changed to produce the same results
|
# FIXME: dpkg could be changed to produce the same results
|
||||||
run_extract($options, $essential_pkgs);
|
run_extract($options, $essential_pkgs);
|
||||||
|
|
||||||
run_hooks('extract', $options);
|
# setup mounts
|
||||||
|
my @cleanup_tasks = ();
|
||||||
if ($options->{variant} ne 'extract') {
|
my $cleanup = sub {
|
||||||
my $chrootcmd = [];
|
my $signal = $_[0];
|
||||||
if ($options->{mode} ne 'chrootless') {
|
while (my $task = pop @cleanup_tasks) {
|
||||||
$chrootcmd = run_prepare($options);
|
$task->();
|
||||||
}
|
}
|
||||||
|
if ($signal) {
|
||||||
|
warning "pid $PID cought signal: $signal";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
run_essential($options, $essential_pkgs, $chrootcmd, $cached_debs);
|
# we only need to setup the mounts if there is anything to do
|
||||||
|
if ( $options->{variant} ne 'custom'
|
||||||
|
or scalar @{ $options->{include} } > 0
|
||||||
|
or scalar @{ $options->{"extract_hook"} } > 0
|
||||||
|
or scalar @{ $options->{"essential_hook"} } > 0
|
||||||
|
or scalar @{ $options->{"customize_hook"} } > 0) {
|
||||||
|
local $SIG{INT} = $cleanup;
|
||||||
|
local $SIG{HUP} = $cleanup;
|
||||||
|
local $SIG{PIPE} = $cleanup;
|
||||||
|
local $SIG{TERM} = $cleanup;
|
||||||
|
|
||||||
run_hooks('essential', $options);
|
@cleanup_tasks = setup_mounts($options);
|
||||||
|
}
|
||||||
|
|
||||||
run_install($options, $chrootcmd);
|
eval {
|
||||||
|
run_hooks('extract', $options);
|
||||||
|
|
||||||
run_hooks('customize', $options);
|
if ($options->{variant} ne 'extract') {
|
||||||
|
my $chrootcmd = [];
|
||||||
|
if ($options->{mode} ne 'chrootless') {
|
||||||
|
$chrootcmd = run_prepare($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
run_essential($options, $essential_pkgs, $chrootcmd, $cached_debs);
|
||||||
|
|
||||||
|
run_hooks('essential', $options);
|
||||||
|
|
||||||
|
run_install($options);
|
||||||
|
|
||||||
|
run_hooks('customize', $options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
my $msg = $@;
|
||||||
|
|
||||||
|
$cleanup->(0);
|
||||||
|
if ($msg) {
|
||||||
|
error "setup failed: $msg";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any { $_ eq 'cleanup' } @{ $options->{skip} }) {
|
if (any { $_ eq 'cleanup' } @{ $options->{skip} }) {
|
||||||
|
@ -2769,18 +2768,11 @@ sub run_essential() {
|
||||||
info "simulate installing essential packages...";
|
info "simulate installing essential packages...";
|
||||||
} else {
|
} else {
|
||||||
info "installing essential packages...";
|
info "installing essential packages...";
|
||||||
run_chroot(
|
run_dpkg_progress({
|
||||||
sub {
|
ARGV =>
|
||||||
run_dpkg_progress({
|
[@{$chrootcmd}, 'dpkg', '--install', '--force-depends'],
|
||||||
ARGV => [
|
PKGS => $essential_pkgs,
|
||||||
@{$chrootcmd}, 'dpkg',
|
});
|
||||||
'--install', '--force-depends'
|
|
||||||
],
|
|
||||||
PKGS => $essential_pkgs,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
$options
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
|
@ -2807,8 +2799,7 @@ sub run_essential() {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub run_install() {
|
sub run_install() {
|
||||||
my $options = shift;
|
my $options = shift;
|
||||||
my $chrootcmd = shift;
|
|
||||||
|
|
||||||
my %pkgs_to_install;
|
my %pkgs_to_install;
|
||||||
for my $incl (@{ $options->{include} }) {
|
for my $incl (@{ $options->{include} }) {
|
||||||
|
@ -2901,35 +2892,26 @@ sub run_install() {
|
||||||
# --root but this would only make sense in situations where there
|
# --root but this would only make sense in situations where there
|
||||||
# is no dpkg inside the chroot.
|
# is no dpkg inside the chroot.
|
||||||
if (!$options->{dryrun}) {
|
if (!$options->{dryrun}) {
|
||||||
run_chroot(
|
info "installing remaining packages inside the chroot...";
|
||||||
sub {
|
run_apt_progress({
|
||||||
info "installing remaining packages inside the"
|
ARGV => [
|
||||||
. " chroot...";
|
'apt-get',
|
||||||
run_apt_progress({
|
'-o',
|
||||||
ARGV => [
|
'Dir::Bin::dpkg=env',
|
||||||
'apt-get',
|
'-o',
|
||||||
'-o',
|
'DPkg::Options::=--unset=TMPDIR',
|
||||||
'Dir::Bin::dpkg=env',
|
'-o',
|
||||||
'-o',
|
'DPkg::Options::=dpkg',
|
||||||
'DPkg::Options::=--unset=TMPDIR',
|
$options->{mode} eq 'fakechroot'
|
||||||
'-o',
|
? ('-o', 'DPkg::Install::Recursive::force=true')
|
||||||
'DPkg::Options::=dpkg',
|
: (),
|
||||||
$options->{mode} eq 'fakechroot'
|
'-o',
|
||||||
? (
|
"DPkg::Chroot-Directory=$options->{root}",
|
||||||
'-o',
|
'--yes',
|
||||||
'DPkg::Install::Recursive::force=true'
|
'install'
|
||||||
)
|
],
|
||||||
: (),
|
PKGS => [@pkgs_to_install],
|
||||||
'-o',
|
});
|
||||||
"DPkg::Chroot-Directory=$options->{root}",
|
|
||||||
'--yes',
|
|
||||||
'install'
|
|
||||||
],
|
|
||||||
PKGS => [@pkgs_to_install],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
$options
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
info "simulate installing remaining packages inside the"
|
info "simulate installing remaining packages inside the"
|
||||||
. " chroot...";
|
. " chroot...";
|
||||||
|
@ -6822,6 +6804,17 @@ C<apt-get dist-upgrade>. In the remaining variants, all Packages files
|
||||||
downloaded by the B<update> step are inspected to find the C<Essential:yes>
|
downloaded by the B<update> step are inspected to find the C<Essential:yes>
|
||||||
package set as well as all packages of the required priority.
|
package set as well as all packages of the required priority.
|
||||||
|
|
||||||
|
=item B<mount>
|
||||||
|
|
||||||
|
Mount relevant device nodes, F</proc> and F</sys> into the chroot and unmount
|
||||||
|
them afterwards. This can be disabled using B<--skip=chroot/mount> or
|
||||||
|
specifically by B<--skip=chroot/mount/dev>, B<--skip=chroot/mount/proc> and
|
||||||
|
B<--skip=chroot/mount/sys>, respectively. B<mmdebstrap> will disable running
|
||||||
|
services by temporarily moving F</usr/sbin/policy-rc.d> and
|
||||||
|
F</sbin/start-stop-daemon> if they exist. This can be disabled with
|
||||||
|
B<--skip=chroot/policy-rc.d> and B<--skip=chroot/start-stop-daemon>,
|
||||||
|
respectively.
|
||||||
|
|
||||||
=item B<extract>
|
=item B<extract>
|
||||||
|
|
||||||
Extract the downloaded packages into the rootfs.
|
Extract the downloaded packages into the rootfs.
|
||||||
|
@ -6862,17 +6855,10 @@ out in B<extract> mode.
|
||||||
Run B<--customize-hook> options and all F<customize*> scripts in B<--hook-dir>.
|
Run B<--customize-hook> options and all F<customize*> scripts in B<--hook-dir>.
|
||||||
This step is not carried out in B<extract> mode.
|
This step is not carried out in B<extract> mode.
|
||||||
|
|
||||||
Whenever B<mmdebstrap> does a chroot call in B<root> or B<unshare> modes, it
|
=item B<unmount>
|
||||||
will mount relevant device nodes, F</proc> and F</sys> into the chroot and
|
|
||||||
unmount them afterwards. This can be disabled using B<--skip=chroot/mount> or
|
|
||||||
specifically by B<--skip=chroot/mount/dev>, B<--skip=chroot/mount/proc> and
|
|
||||||
B<--skip=chroot/mount/sys>, respectively.
|
|
||||||
|
|
||||||
For each command that is run inside the chroot, B<mmdebstrap> will disable
|
Unmount everything that was mounted during the B<mount> stage and restores
|
||||||
running services by temporarily moving F</usr/sbin/policy-rc.d> and
|
F</usr/sbin/policy-rc.d> and F</sbin/start-stop-daemon> if necessary.
|
||||||
F</sbin/start-stop-daemon> if they exist. This can be disabled with
|
|
||||||
B<--skip=chroot/policy-rc.d> and B<--skip=chroot/start-stop-daemon>,
|
|
||||||
respectively.
|
|
||||||
|
|
||||||
=item B<cleanup>
|
=item B<cleanup>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue