|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
#!/usr/bin/perl
|
|
|
|
|
#
|
|
|
|
|
# © 2018 - 2021 Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
|
|
|
|
# © 2018 - 2022 Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
|
|
|
|
#
|
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
# of this software and associated documentation files (the "Software"), to
|
|
|
|
@ -23,7 +23,7 @@
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
|
|
our $VERSION = '1.1.0';
|
|
|
|
|
our $VERSION = '1.2.0';
|
|
|
|
|
|
|
|
|
|
use English;
|
|
|
|
|
use Getopt::Long;
|
|
|
|
@ -1104,8 +1104,12 @@ sub run_chroot {
|
|
|
|
|
}
|
|
|
|
|
} elsif ($type == 3 or $type == 4) {
|
|
|
|
|
# character/block special
|
|
|
|
|
if ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
&& !$options->{canmount}) {
|
|
|
|
|
if (
|
|
|
|
|
any { $_ =~ '^chroot/mount(?:/dev)?$' }
|
|
|
|
|
@{ $options->{skip} }
|
|
|
|
|
) {
|
|
|
|
|
info "skipping chroot/mount/dev as requested";
|
|
|
|
|
} elsif (!$options->{canmount}) {
|
|
|
|
|
warning "skipping bind-mounting ./dev/$fname";
|
|
|
|
|
} elsif (!$options->{havemknod}) {
|
|
|
|
|
if (!-d "$options->{root}/dev") {
|
|
|
|
@ -1160,15 +1164,21 @@ sub run_chroot {
|
|
|
|
|
"$options->{root}/dev/$fname")
|
|
|
|
|
or error "mount ./dev/$fname failed: $?";
|
|
|
|
|
}
|
|
|
|
|
} elsif ($type == 5
|
|
|
|
|
&& (any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
&& !$options->{canmount}) {
|
|
|
|
|
} elsif ($type == 5) {
|
|
|
|
|
# directory
|
|
|
|
|
if (
|
|
|
|
|
any { $_ =~ '^chroot/mount(?:/dev)?$' }
|
|
|
|
|
@{ $options->{skip} }
|
|
|
|
|
) {
|
|
|
|
|
info "skipping chroot/mount/dev as requested";
|
|
|
|
|
} elsif (!$options->{canmount}) {
|
|
|
|
|
warning "skipping bind-mounting ./dev/$fname";
|
|
|
|
|
} elsif ($type == 5) { # directory
|
|
|
|
|
} else {
|
|
|
|
|
if (!-d "$options->{root}/dev") {
|
|
|
|
|
warning(
|
|
|
|
|
"skipping creation of ./dev/$fname because the"
|
|
|
|
|
. " /dev directory is missing in the target");
|
|
|
|
|
. " /dev directory is missing in the target"
|
|
|
|
|
);
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if (!-e "/dev/$fname" && $fname ne "pts/") {
|
|
|
|
@ -1192,7 +1202,8 @@ sub run_chroot {
|
|
|
|
|
};
|
|
|
|
|
if (-e "$options->{root}/dev/$fname") {
|
|
|
|
|
if (!-d "$options->{root}/dev/$fname") {
|
|
|
|
|
error "./dev/$fname already exists but is not"
|
|
|
|
|
error
|
|
|
|
|
"./dev/$fname already exists but is not"
|
|
|
|
|
. " a directory";
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -1209,8 +1220,8 @@ sub run_chroot {
|
|
|
|
|
} @$err
|
|
|
|
|
));
|
|
|
|
|
} elsif ($num_created == 0) {
|
|
|
|
|
error
|
|
|
|
|
"cannot create $options->{root}/dev/$fname";
|
|
|
|
|
error( "cannot create $options->{root}"
|
|
|
|
|
. "/dev/$fname");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
chmod $mode, "$options->{root}/dev/$fname"
|
|
|
|
@ -1251,17 +1262,13 @@ sub run_chroot {
|
|
|
|
|
"$options->{root}/dev/$fname")
|
|
|
|
|
or error "mount ./dev/$fname failed: $?";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
error "unsupported type: $type";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('proot', 'fakechroot', 'chrootless')
|
|
|
|
|
) {
|
|
|
|
|
# we cannot mount in fakechroot and proot mode
|
|
|
|
|
# in proot mode we have /dev bind-mounted already through
|
|
|
|
|
# --bind=/dev
|
|
|
|
|
} elsif (any { $_ eq $options->{mode} } ('fakechroot', 'chrootless')) {
|
|
|
|
|
# we cannot mount in fakechroot mode
|
|
|
|
|
} else {
|
|
|
|
|
error "unknown mode: $options->{mode}";
|
|
|
|
|
}
|
|
|
|
@ -1269,6 +1276,10 @@ sub run_chroot {
|
|
|
|
|
# set because if we mount it before, then base-files will not be able
|
|
|
|
|
# to extract those
|
|
|
|
|
if ( (any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
&& (any { $_ =~ '^chroot/mount(?:/sys)?$' } @{ $options->{skip} }))
|
|
|
|
|
{
|
|
|
|
|
info "skipping chroot/mount/sys as requested";
|
|
|
|
|
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
&& !$options->{canmount}) {
|
|
|
|
|
warning "skipping mount sysfs";
|
|
|
|
|
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
@ -1333,17 +1344,17 @@ sub run_chroot {
|
|
|
|
|
# type, bad option, bad superblock" error
|
|
|
|
|
0 == system('mount', '-o', 'rbind', '/sys', "$options->{root}/sys")
|
|
|
|
|
or error "mount /sys failed: $?";
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('proot', 'fakechroot', 'chrootless')
|
|
|
|
|
) {
|
|
|
|
|
# we cannot mount in fakechroot and proot mode
|
|
|
|
|
# in proot mode we have /proc bind-mounted already through
|
|
|
|
|
# --bind=/proc
|
|
|
|
|
} elsif (any { $_ eq $options->{mode} } ('fakechroot', 'chrootless')) {
|
|
|
|
|
# we cannot mount in fakechroot mode
|
|
|
|
|
} else {
|
|
|
|
|
error "unknown mode: $options->{mode}";
|
|
|
|
|
}
|
|
|
|
|
if ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
if (
|
|
|
|
|
(any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
&& (any { $_ =~ '^chroot/mount(?:/proc)?$' } @{ $options->{skip} })
|
|
|
|
|
) {
|
|
|
|
|
info "skipping chroot/mount/proc as requested";
|
|
|
|
|
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
|
&& !$options->{canmount}) {
|
|
|
|
|
warning "skipping mount proc";
|
|
|
|
|
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
|
|
|
@ -1408,13 +1419,8 @@ sub run_chroot {
|
|
|
|
|
};
|
|
|
|
|
0 == system('mount', '-t', 'proc', 'proc', "$options->{root}/proc")
|
|
|
|
|
or error "mount /proc failed: $?";
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('proot', 'fakechroot', 'chrootless')
|
|
|
|
|
) {
|
|
|
|
|
# we cannot mount in fakechroot and proot mode
|
|
|
|
|
# in proot mode we have /sys bind-mounted already through
|
|
|
|
|
# --bind=/sys
|
|
|
|
|
} elsif (any { $_ eq $options->{mode} } ('fakechroot', 'chrootless')) {
|
|
|
|
|
# we cannot mount in fakechroot mode
|
|
|
|
|
} else {
|
|
|
|
|
error "unknown mode: $options->{mode}";
|
|
|
|
|
}
|
|
|
|
@ -1426,6 +1432,9 @@ sub run_chroot {
|
|
|
|
|
# existing inside the chroot
|
|
|
|
|
#
|
|
|
|
|
# See #911290 for more problems of this interface
|
|
|
|
|
if (any { $_ eq 'chroot/policy-rc.d' } @{ $options->{skip} }) {
|
|
|
|
|
info "skipping chroot/policy-rc.d as requested";
|
|
|
|
|
} else {
|
|
|
|
|
if (-d "$options->{root}/usr/sbin/") {
|
|
|
|
|
open my $fh, '>', "$options->{root}/usr/sbin/policy-rc.d"
|
|
|
|
|
or error "cannot open policy-rc.d: $!";
|
|
|
|
@ -1435,11 +1444,16 @@ sub run_chroot {
|
|
|
|
|
chmod 0755, "$options->{root}/usr/sbin/policy-rc.d"
|
|
|
|
|
or error "cannot chmod policy-rc.d: $!";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# the file might not exist if it was removed in a hook
|
|
|
|
|
if (any { $_ eq 'chroot/start-stop-daemon' } @{ $options->{skip} }) {
|
|
|
|
|
info "skipping chroot/start-stop-daemon as requested";
|
|
|
|
|
} else {
|
|
|
|
|
if (-f "$options->{root}/sbin/start-stop-daemon") {
|
|
|
|
|
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
|
|
|
|
error "$options->{root}/sbin/start-stop-daemon.REAL already"
|
|
|
|
|
error
|
|
|
|
|
"$options->{root}/sbin/start-stop-daemon.REAL already"
|
|
|
|
|
. " exists";
|
|
|
|
|
}
|
|
|
|
|
move(
|
|
|
|
@ -1449,26 +1463,36 @@ sub run_chroot {
|
|
|
|
|
open my $fh, '>', "$options->{root}/sbin/start-stop-daemon"
|
|
|
|
|
or error "cannot open start-stop-daemon: $!";
|
|
|
|
|
print $fh "#!/bin/sh\n";
|
|
|
|
|
print $fh "echo \"Warning: Fake start-stop-daemon called, doing"
|
|
|
|
|
print $fh
|
|
|
|
|
"echo \"Warning: Fake start-stop-daemon called, doing"
|
|
|
|
|
. " nothing\">&2\n";
|
|
|
|
|
close $fh;
|
|
|
|
|
chmod 0755, "$options->{root}/sbin/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: $!";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -1530,6 +1554,20 @@ sub run_hooks {
|
|
|
|
|
# Store the verbosity of mmdebstrap so that hooks can be just as verbose
|
|
|
|
|
# as the mmdebstrap invocation that called them.
|
|
|
|
|
push @env_opts, ("MMDEBSTRAP_VERBOSITY=" . $verbosity_level);
|
|
|
|
|
# Store the packages given via --include in an environment variable so that
|
|
|
|
|
# hooks can, for example, make .deb files available inside the chroot.
|
|
|
|
|
{
|
|
|
|
|
my @escaped_includes = @{ $options->{include} };
|
|
|
|
|
foreach my $incl (@escaped_includes) {
|
|
|
|
|
# We have to encode commas so that values containing commas can
|
|
|
|
|
# be stored in the list. Since we encode using percent-encoding
|
|
|
|
|
# (urlencoding) we also have to encode the percent sign.
|
|
|
|
|
$incl =~ s/%/%25/g;
|
|
|
|
|
$incl =~ s/,/%2C/g;
|
|
|
|
|
}
|
|
|
|
|
push @env_opts,
|
|
|
|
|
("MMDEBSTRAP_INCLUDE=" . (join ",", @escaped_includes));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my $runner = sub {
|
|
|
|
|
foreach my $script (@{ $options->{"${name}_hook"} }) {
|
|
|
|
@ -1542,13 +1580,11 @@ sub run_hooks {
|
|
|
|
|
)\ /x
|
|
|
|
|
) {
|
|
|
|
|
info "running special hook: $script";
|
|
|
|
|
if (
|
|
|
|
|
any { $_ eq $options->{variant} } ('extract', 'custom')
|
|
|
|
|
and any { $_ eq $options->{mode} }
|
|
|
|
|
('fakechroot', 'proot') and $name ne 'setup'
|
|
|
|
|
) {
|
|
|
|
|
if ((any { $_ eq $options->{variant} } ('extract', 'custom'))
|
|
|
|
|
and $options->{mode} eq 'fakechroot'
|
|
|
|
|
and $name ne 'setup') {
|
|
|
|
|
info "the copy-in, copy-out, tar-in and tar-out commands"
|
|
|
|
|
. " in fakechroot mode or proot mode might fail in"
|
|
|
|
|
. " in fakechroot mode might fail in"
|
|
|
|
|
. " extract and custom variants because there might be"
|
|
|
|
|
. " no tar inside the chroot";
|
|
|
|
|
}
|
|
|
|
@ -2074,14 +2110,14 @@ sub run_setup() {
|
|
|
|
|
copy($tmpfile, \*STDERR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (none { $_ eq $options->{mode} } ('fakechroot', 'proot')) {
|
|
|
|
|
if ($options->{mode} ne 'fakechroot') {
|
|
|
|
|
# Apt dropping privileges to another user than root is not useful in
|
|
|
|
|
# fakechroot and proot mode because all users are faked and thus there
|
|
|
|
|
# is no real privilege difference anyways. We could set
|
|
|
|
|
# APT::Sandbox::User "root" in fakechroot and proot mode but we don't
|
|
|
|
|
# because if we would, then /var/cache/apt/archives/partial/ and
|
|
|
|
|
# /var/lib/apt/lists/partial/ would not be owned by the _apt user
|
|
|
|
|
# if mmdebstrap was run in fakechroot or proot mode.
|
|
|
|
|
# fakechroot mode because all users are faked and thus there is no real
|
|
|
|
|
# privilege difference anyways. We could set APT::Sandbox::User "root"
|
|
|
|
|
# in fakechroot mode but we don't because if we would, then
|
|
|
|
|
# /var/cache/apt/archives/partial/ and /var/lib/apt/lists/partial/
|
|
|
|
|
# would not be owned by the _apt user if mmdebstrap was run in
|
|
|
|
|
# fakechroot mode.
|
|
|
|
|
#
|
|
|
|
|
# when apt-get update is run by the root user, then apt will attempt to
|
|
|
|
|
# drop privileges to the _apt user. This will fail if the _apt user
|
|
|
|
@ -2493,29 +2529,15 @@ sub run_prepare {
|
|
|
|
|
# make sure that APT_CONFIG and TMPDIR are not set when executing
|
|
|
|
|
# anything inside the chroot
|
|
|
|
|
my @chrootcmd = ('env', '--unset=APT_CONFIG', '--unset=TMPDIR');
|
|
|
|
|
if ($options->{mode} eq 'proot') {
|
|
|
|
|
push @chrootcmd,
|
|
|
|
|
(
|
|
|
|
|
'proot', '--root-id',
|
|
|
|
|
'--bind=/dev', '--bind=/proc',
|
|
|
|
|
'--bind=/sys', "--rootfs=$options->{root}",
|
|
|
|
|
'--cwd=/'
|
|
|
|
|
);
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'unshare', 'fakechroot')
|
|
|
|
|
) {
|
|
|
|
|
if (any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot')) {
|
|
|
|
|
push @chrootcmd, ('chroot', $options->{root});
|
|
|
|
|
} else {
|
|
|
|
|
error "unknown mode: $options->{mode}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# copy qemu-user-static binary into chroot or setup proot with
|
|
|
|
|
# --qemu
|
|
|
|
|
# copy qemu-user-static binary into chroot
|
|
|
|
|
if (defined $options->{qemu}) {
|
|
|
|
|
if ($options->{mode} eq 'proot') {
|
|
|
|
|
push @chrootcmd, "--qemu=qemu-$options->{qemu}";
|
|
|
|
|
} elsif ($options->{mode} eq 'fakechroot') {
|
|
|
|
|
if ($options->{mode} eq 'fakechroot') {
|
|
|
|
|
# Make sure that the fakeroot and fakechroot shared
|
|
|
|
|
# libraries exist for the right architecture
|
|
|
|
|
open my $fh, '-|', 'dpkg-architecture', '-a',
|
|
|
|
@ -2601,29 +2623,21 @@ sub run_prepare {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# some versions of coreutils use the renameat2 system call in mv.
|
|
|
|
|
# This breaks certain versions of fakechroot and proot. Here we do
|
|
|
|
|
# This breaks certain versions of fakechroot. Here we do
|
|
|
|
|
# a sanity check and warn the user in case things might break.
|
|
|
|
|
if (any { $_ eq $options->{mode} } ('fakechroot', 'proot')
|
|
|
|
|
if ($options->{mode} eq 'fakechroot'
|
|
|
|
|
and -e "$options->{root}/bin/mv") {
|
|
|
|
|
mkdir "$options->{root}/000-move-me"
|
|
|
|
|
or error "cannot create directory: $!";
|
|
|
|
|
my $ret = system @chrootcmd, '/bin/mv', '/000-move-me',
|
|
|
|
|
'/001-delete-me';
|
|
|
|
|
if ($ret != 0) {
|
|
|
|
|
if ($options->{mode} eq 'proot') {
|
|
|
|
|
info "the /bin/mv binary inside the chroot doesn't"
|
|
|
|
|
. " work under proot";
|
|
|
|
|
info "this is likely due to missing support for"
|
|
|
|
|
. " renameat2 in proot";
|
|
|
|
|
info "see https://github.com/proot-me/PRoot/issues/147";
|
|
|
|
|
} else {
|
|
|
|
|
info "the /bin/mv binary inside the chroot doesn't"
|
|
|
|
|
. " work under fakechroot";
|
|
|
|
|
info "with certain versions of coreutils and glibc,"
|
|
|
|
|
. " this is due to missing support for renameat2 in"
|
|
|
|
|
. " fakechroot";
|
|
|
|
|
info "see https://github.com/dex4er/fakechroot/issues/60";
|
|
|
|
|
}
|
|
|
|
|
info "expect package post installation scripts not to work";
|
|
|
|
|
rmdir "$options->{root}/000-move-me"
|
|
|
|
|
or error "cannot rmdir: $!";
|
|
|
|
@ -2693,10 +2707,8 @@ sub run_essential() {
|
|
|
|
|
'--force-depends'
|
|
|
|
|
],
|
|
|
|
|
PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}] });
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'unshare', 'fakechroot', 'proot')
|
|
|
|
|
) {
|
|
|
|
|
} elsif (any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot'))
|
|
|
|
|
{
|
|
|
|
|
# install the extracted packages properly
|
|
|
|
|
# we need --force-depends because dpkg does not take Pre-Depends
|
|
|
|
|
# into account and thus doesn't install them in the right order
|
|
|
|
@ -2816,10 +2828,8 @@ sub run_install() {
|
|
|
|
|
PKGS => [@pkgs_to_install],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'unshare', 'fakechroot', 'proot')
|
|
|
|
|
) {
|
|
|
|
|
} elsif (any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot'))
|
|
|
|
|
{
|
|
|
|
|
if ($options->{variant} ne 'custom'
|
|
|
|
|
and scalar @pkgs_to_install > 0) {
|
|
|
|
|
# Advantage of running apt on the outside instead of inside the
|
|
|
|
@ -3001,10 +3011,31 @@ sub run_cleanup() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (any { $_ eq 'cleanup/run' } @{ $options->{skip} }) {
|
|
|
|
|
info "skipping cleanup/run as requested";
|
|
|
|
|
} else {
|
|
|
|
|
# remove any possible leftovers in /run
|
|
|
|
|
if (-d "$options->{root}/run") {
|
|
|
|
|
opendir(my $dh, "$options->{root}/run")
|
|
|
|
|
or error "Can't opendir($options->{root}/run): $!";
|
|
|
|
|
while (my $entry = readdir $dh) {
|
|
|
|
|
# skip the "." and ".." entries
|
|
|
|
|
next if $entry eq ".";
|
|
|
|
|
next if $entry eq "..";
|
|
|
|
|
debug "deleting files in /run: $entry";
|
|
|
|
|
0 == system(
|
|
|
|
|
'rm', '--interactive=never',
|
|
|
|
|
'--recursive', '--preserve-root',
|
|
|
|
|
'--one-file-system', "$options->{root}/run/$entry"
|
|
|
|
|
) or error "rm failed: $?";
|
|
|
|
|
}
|
|
|
|
|
closedir($dh);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (any { $_ eq 'cleanup/tmp' } @{ $options->{skip} }) {
|
|
|
|
|
info "skipping cleanup/tmp as requested";
|
|
|
|
|
} else {
|
|
|
|
|
# remove any possible leftovers in /tmp but warn about it
|
|
|
|
|
# remove any possible leftovers in /tmp
|
|
|
|
|
if (-d "$options->{root}/tmp") {
|
|
|
|
|
opendir(my $dh, "$options->{root}/tmp")
|
|
|
|
|
or error "Can't opendir($options->{root}/tmp): $!";
|
|
|
|
@ -3012,7 +3043,7 @@ sub run_cleanup() {
|
|
|
|
|
# skip the "." and ".." entries
|
|
|
|
|
next if $entry eq ".";
|
|
|
|
|
next if $entry eq "..";
|
|
|
|
|
warning "deleting files in /tmp: $entry";
|
|
|
|
|
debug "deleting files in /tmp: $entry";
|
|
|
|
|
0 == system(
|
|
|
|
|
'rm', '--interactive=never',
|
|
|
|
|
'--recursive', '--preserve-root',
|
|
|
|
@ -3105,26 +3136,12 @@ sub hookhelper {
|
|
|
|
|
. 'delete=atime,delete=ctime'
|
|
|
|
|
);
|
|
|
|
|
if ($hook eq 'setup') {
|
|
|
|
|
if ($mode eq 'proot') {
|
|
|
|
|
# since we cannot run tar inside the chroot under proot during
|
|
|
|
|
# the setup hook because the chroot is empty, we have to run
|
|
|
|
|
# tar from the outside, which leads to all files being owned
|
|
|
|
|
# by the user running mmdebstrap. To let the ownership
|
|
|
|
|
# information not be completely off, we force all files be
|
|
|
|
|
# owned by the root user.
|
|
|
|
|
push @tarcmd, '--owner=0', '--group=0';
|
|
|
|
|
}
|
|
|
|
|
} elsif (any { $_ eq $hook } ('extract', 'essential', 'customize')) {
|
|
|
|
|
if ($mode eq 'fakechroot') {
|
|
|
|
|
# Fakechroot requires tar to run inside the chroot or
|
|
|
|
|
# otherwise absolute symlinks will include the path to the
|
|
|
|
|
# root directory
|
|
|
|
|
push @cmdprefix, 'chroot', $root;
|
|
|
|
|
} elsif ($mode eq 'proot') {
|
|
|
|
|
# proot requires tar to run inside proot or otherwise
|
|
|
|
|
# permissions will be completely off
|
|
|
|
|
push @cmdprefix, 'proot', '--root-id', "--rootfs=$root",
|
|
|
|
|
'--cwd=/', "--qemu=$qemu";
|
|
|
|
|
} elsif (any { $_ eq $mode } ('root', 'chrootless', 'unshare')) {
|
|
|
|
|
# not chrooting in this case
|
|
|
|
|
} else {
|
|
|
|
@ -3155,7 +3172,7 @@ sub hookhelper {
|
|
|
|
|
any { $_ eq $hook }
|
|
|
|
|
('extract', 'essential', 'customize')
|
|
|
|
|
) {
|
|
|
|
|
if (any { $_ eq $mode } ('fakechroot', 'proot')) {
|
|
|
|
|
if ($mode eq 'fakechroot') {
|
|
|
|
|
# tar will run inside the chroot
|
|
|
|
|
$directory = $outpath;
|
|
|
|
|
} elsif (
|
|
|
|
@ -3170,10 +3187,10 @@ sub hookhelper {
|
|
|
|
|
error "unknown hook: $hook";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# if chrooted_realpath was used and if neither fakechroot or
|
|
|
|
|
# proot were used (absolute symlinks will be broken) we can
|
|
|
|
|
# if chrooted_realpath was used and if fakechroot
|
|
|
|
|
# was used (absolute symlinks will be broken) we can
|
|
|
|
|
# check and potentially fail early if the target does not exist
|
|
|
|
|
if (none { $_ eq $mode } ('fakechroot', 'proot')) {
|
|
|
|
|
if ($mode ne 'fakechroot') {
|
|
|
|
|
my $dirtocheck = $directory;
|
|
|
|
|
if ($command eq 'upload') {
|
|
|
|
|
# check the parent directory instead
|
|
|
|
@ -3302,7 +3319,7 @@ sub hookhelper {
|
|
|
|
|
any { $_ eq $hook }
|
|
|
|
|
('extract', 'essential', 'customize')
|
|
|
|
|
) {
|
|
|
|
|
if (any { $_ eq $mode } ('fakechroot', 'proot')) {
|
|
|
|
|
if ($mode eq 'fakechroot') {
|
|
|
|
|
# tar will run inside the chroot
|
|
|
|
|
$directory = $ARGV[$i];
|
|
|
|
|
} elsif (
|
|
|
|
@ -3317,10 +3334,10 @@ sub hookhelper {
|
|
|
|
|
error "unknown hook: $hook";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# if chrooted_realpath was used and if neither fakechroot or
|
|
|
|
|
# proot were used (absolute symlinks will be broken) we can
|
|
|
|
|
# if chrooted_realpath was used and if fakechroot
|
|
|
|
|
# was used (absolute symlinks will be broken) we can
|
|
|
|
|
# check and potentially fail early if the source does not exist
|
|
|
|
|
if (none { $_ eq $mode } ('fakechroot', 'proot')) {
|
|
|
|
|
if ($mode ne 'fakechroot') {
|
|
|
|
|
if (!-e $directory) {
|
|
|
|
|
error "path does not exist: $directory";
|
|
|
|
|
}
|
|
|
|
@ -4247,6 +4264,26 @@ sub main() {
|
|
|
|
|
'variant=s' => \$options->{variant},
|
|
|
|
|
'include=s' => sub {
|
|
|
|
|
my ($opt_name, $opt_value) = @_;
|
|
|
|
|
my $sanitize_path = sub {
|
|
|
|
|
my $pkg = shift;
|
|
|
|
|
$pkg = abs_path($pkg);
|
|
|
|
|
if (!defined $pkg) {
|
|
|
|
|
error "cannot resolve absolute path of $pkg: $!";
|
|
|
|
|
}
|
|
|
|
|
if (!-f $pkg) {
|
|
|
|
|
error "$pkg is not an existing file";
|
|
|
|
|
}
|
|
|
|
|
return $pkg;
|
|
|
|
|
};
|
|
|
|
|
if ($opt_value =~ /^[?~!(]/) {
|
|
|
|
|
# Treat option as a single apt pattern and don't split by comma
|
|
|
|
|
# or whitespace -- append it verbatim.
|
|
|
|
|
push @{ $options->{include} }, $opt_value;
|
|
|
|
|
} elsif ($opt_value =~ /^\.?\.?\//) {
|
|
|
|
|
# Treat option as a single path name and don't split by comma
|
|
|
|
|
# or whitespace -- append the normalized path.
|
|
|
|
|
push @{ $options->{include} }, sanitize_path($opt_value);
|
|
|
|
|
} else {
|
|
|
|
|
for my $pkg (split /[,\s]+/, $opt_value) {
|
|
|
|
|
# strip leading and trailing whitespace
|
|
|
|
|
$pkg =~ s/^\s+|\s+$//g;
|
|
|
|
@ -4254,8 +4291,17 @@ sub main() {
|
|
|
|
|
if ($pkg eq '') {
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
# Make paths canonical absolute paths, resolve symlinks
|
|
|
|
|
# and check if it's an existing file.
|
|
|
|
|
if ($pkg =~ /^\.?\.?\//) {
|
|
|
|
|
$pkg = sanitize_path($pkg);
|
|
|
|
|
}
|
|
|
|
|
push @{ $options->{include} }, $pkg;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
# We are not sorting or otherwise normalizing the order of
|
|
|
|
|
# arguments to apt because package order matters for "apt install"
|
|
|
|
|
# since https://salsa.debian.org/apt-team/apt/-/merge_requests/256
|
|
|
|
|
},
|
|
|
|
|
'architectures=s@' => \$options->{architectures},
|
|
|
|
|
'mode=s' => \$options->{mode},
|
|
|
|
@ -4355,8 +4401,18 @@ sub main() {
|
|
|
|
|
# here prepare for long suffering in dependency hell.
|
|
|
|
|
'simulate' => \$options->{dryrun},
|
|
|
|
|
'dry-run' => \$options->{dryrun},
|
|
|
|
|
'skip=s@' => \$options->{skip},
|
|
|
|
|
) or pod2usage(-exitval => 2, -verbose => 1);
|
|
|
|
|
'skip=s' => sub {
|
|
|
|
|
my ($opt_name, $opt_value) = @_;
|
|
|
|
|
for my $skip (split /[,\s]+/, $opt_value) {
|
|
|
|
|
# strip leading and trailing whitespace
|
|
|
|
|
$skip =~ s/^\s+|\s+$//g;
|
|
|
|
|
# skip if the remainder is an empty string
|
|
|
|
|
if ($skip eq '') {
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
push @{ $options->{skip} }, $skip;
|
|
|
|
|
}
|
|
|
|
|
}) or pod2usage(-exitval => 2, -verbose => 1);
|
|
|
|
|
|
|
|
|
|
if (defined($logfile)) {
|
|
|
|
|
open(STDERR, '>', $logfile) or error "cannot open $logfile: $!";
|
|
|
|
@ -4400,8 +4456,7 @@ sub main() {
|
|
|
|
|
if ($options->{mode} eq 'sudo') {
|
|
|
|
|
$options->{mode} = 'root';
|
|
|
|
|
}
|
|
|
|
|
my @valid_modes
|
|
|
|
|
= ('auto', 'root', 'unshare', 'fakechroot', 'proot', 'chrootless');
|
|
|
|
|
my @valid_modes = ('auto', 'root', 'unshare', 'fakechroot', 'chrootless');
|
|
|
|
|
if (none { $_ eq $options->{mode} } @valid_modes) {
|
|
|
|
|
error "invalid mode. Choose from " . (join ', ', @valid_modes);
|
|
|
|
|
}
|
|
|
|
@ -4525,9 +4580,6 @@ sub main() {
|
|
|
|
|
@prefix = ($EXECUTABLE_NAME, '-MDevel::Cover=-silent,-nogcov');
|
|
|
|
|
}
|
|
|
|
|
exec 'fakechroot', 'fakeroot', @prefix, $PROGRAM_NAME, @ARGVORIG;
|
|
|
|
|
} elsif (can_execute 'proot') {
|
|
|
|
|
# and lastly, proot
|
|
|
|
|
$options->{mode} = 'proot';
|
|
|
|
|
} else {
|
|
|
|
|
error "unable to pick chroot mode automatically";
|
|
|
|
|
}
|
|
|
|
@ -4536,10 +4588,6 @@ sub main() {
|
|
|
|
|
if ($EFFECTIVE_USER_ID != 0) {
|
|
|
|
|
error "need to be root";
|
|
|
|
|
}
|
|
|
|
|
} elsif ($options->{mode} eq 'proot') {
|
|
|
|
|
if (!can_execute 'proot') {
|
|
|
|
|
error "need working proot binary";
|
|
|
|
|
}
|
|
|
|
|
} elsif ($options->{mode} eq 'fakechroot') {
|
|
|
|
|
if (&{$check_fakechroot_running}()) {
|
|
|
|
|
# fakechroot is already running
|
|
|
|
@ -4616,7 +4664,7 @@ sub main() {
|
|
|
|
|
0 == syscall &SYS_capget, $hdrp, $datap
|
|
|
|
|
or error "capget failed: $!";
|
|
|
|
|
my ($effective, undef) = unpack "LLLLLL", $datap;
|
|
|
|
|
if (($effective >> $CAP_SYS_ADMIN) & 1 != 1) {
|
|
|
|
|
if ((($effective >> $CAP_SYS_ADMIN) & 1) != 1) {
|
|
|
|
|
warning
|
|
|
|
|
"cannot mount because CAP_SYS_ADMIN is not in the effective set";
|
|
|
|
|
$options->{canmount} = 0;
|
|
|
|
@ -5271,9 +5319,9 @@ sub main() {
|
|
|
|
|
if (any { $_ eq $format } ('tar', 'squashfs', 'ext2', 'null')) {
|
|
|
|
|
if ($format ne 'null') {
|
|
|
|
|
if (any { $_ eq $options->{variant} } ('extract', 'custom')
|
|
|
|
|
and any { $_ eq $options->{mode} } ('fakechroot', 'proot')) {
|
|
|
|
|
and $options->{mode} eq 'fakechroot') {
|
|
|
|
|
info "creating a tarball or squashfs image or ext2 image in"
|
|
|
|
|
. " fakechroot mode or proot mode might fail in extract and"
|
|
|
|
|
. " fakechroot mode might fail in extract and"
|
|
|
|
|
. " custom variants because there might be no tar inside the"
|
|
|
|
|
. " chroot";
|
|
|
|
|
}
|
|
|
|
@ -5411,7 +5459,7 @@ sub main() {
|
|
|
|
|
$? == 0 or error "havemknod failed";
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'fakechroot', 'proot', 'chrootless')
|
|
|
|
|
('root', 'fakechroot', 'chrootless')
|
|
|
|
|
) {
|
|
|
|
|
$options->{havemknod} = havemknod($options->{root});
|
|
|
|
|
} else {
|
|
|
|
@ -5572,7 +5620,7 @@ sub main() {
|
|
|
|
|
);
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'fakechroot', 'proot', 'chrootless')
|
|
|
|
|
('root', 'fakechroot', 'chrootless')
|
|
|
|
|
) {
|
|
|
|
|
$pid = fork() // error "fork() failed: $!";
|
|
|
|
|
if ($pid == 0) {
|
|
|
|
@ -5635,18 +5683,6 @@ sub main() {
|
|
|
|
|
0 == system('chroot', $options->{root}, 'tar',
|
|
|
|
|
@taropts, '-C', '/', '.')
|
|
|
|
|
or error "tar failed: $?";
|
|
|
|
|
} elsif ($options->{mode} eq 'proot') {
|
|
|
|
|
# proot requires tar to run inside proot or otherwise
|
|
|
|
|
# permissions will be completely off
|
|
|
|
|
my @qemuopt = ();
|
|
|
|
|
if (defined $options->{qemu}) {
|
|
|
|
|
push @qemuopt, "--qemu=qemu-$options->{qemu}";
|
|
|
|
|
push @taropts, "--exclude=./host-rootfs";
|
|
|
|
|
}
|
|
|
|
|
0 == system('proot', '--root-id',
|
|
|
|
|
"--rootfs=$options->{root}", '--cwd=/', @qemuopt,
|
|
|
|
|
'tar', @taropts, '-C', '/', '.')
|
|
|
|
|
or error "tar failed: $?";
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'chrootless')
|
|
|
|
@ -5884,15 +5920,11 @@ sub main() {
|
|
|
|
|
}
|
|
|
|
|
} elsif (
|
|
|
|
|
any { $_ eq $options->{mode} }
|
|
|
|
|
('root', 'fakechroot', 'proot', 'chrootless')
|
|
|
|
|
('root', 'fakechroot', 'chrootless')
|
|
|
|
|
) {
|
|
|
|
|
# without unshare, we use the system's rm to recursively remove the
|
|
|
|
|
# temporary directory just to make sure that we do not accidentally
|
|
|
|
|
# remove more than we should by using --one-file-system.
|
|
|
|
|
#
|
|
|
|
|
# --interactive=never is needed when in proot mode, the
|
|
|
|
|
# write-protected file /apt/apt.conf.d/01autoremove-kernels is to
|
|
|
|
|
# be removed.
|
|
|
|
|
0 == system('rm', '--interactive=never', '--recursive',
|
|
|
|
|
'--preserve-root', '--one-file-system', $options->{root})
|
|
|
|
|
or error "rm failed: $?";
|
|
|
|
@ -6013,7 +6045,7 @@ B<debootstrap>. See the section B<VARIANTS> for more information.
|
|
|
|
|
|
|
|
|
|
Choose how to perform the chroot operation and create a filesystem with
|
|
|
|
|
ownership information different from the current user. Valid mode I<name>s are
|
|
|
|
|
B<auto>, B<sudo>, B<root>, B<unshare>, B<fakeroot>, B<fakechroot>, B<proot> and
|
|
|
|
|
B<auto>, B<sudo>, B<root>, B<unshare>, B<fakeroot>, B<fakechroot> and
|
|
|
|
|
B<chrootless>. The default mode is B<auto>. See the section B<MODES> for more
|
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
@ -6118,16 +6150,35 @@ by this option will be the only ones that get either extracted or installed by
|
|
|
|
|
dpkg, respectively. For all other variants, apt is used to install the
|
|
|
|
|
additional packages. Package names are directly passed to apt and thus, you
|
|
|
|
|
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
|
|
|
|
|
regex for C<pkg> or use apt patterns. See apt(8) for the supported
|
|
|
|
|
syntax. The option can be specified multiple times and the packages are
|
|
|
|
|
concatenated in the order in which they are given on the command line. If
|
|
|
|
|
later list items are repeated, then they get dropped so that the resulting
|
|
|
|
|
package list is free of duplicates. So the following are equivalent:
|
|
|
|
|
regex for C<pkg>, use apt patterns or pass a path to a .deb package file. See
|
|
|
|
|
apt(8) for the supported syntax.
|
|
|
|
|
|
|
|
|
|
The option can be specified multiple times and the packages are concatenated in
|
|
|
|
|
the order in which they are given on the command line. If later list items are
|
|
|
|
|
repeated, then they get dropped so that the resulting package list is free of
|
|
|
|
|
duplicates. So the following are equivalent:
|
|
|
|
|
|
|
|
|
|
--include="pkg1/stable pkg2=1.0 pkg3-"
|
|
|
|
|
--include=pkg1/stable,pkg2=1.0,pkg3-
|
|
|
|
|
--include=pkg1/stable,pkg2=1.0,pkg3-,,,
|
|
|
|
|
--incl=pkg1/stable --incl="pkg2=1.0 pkg3-" --incl=pkg2=1.0,pkg3-
|
|
|
|
|
|
|
|
|
|
Since the list of packages is separated by comma or whitespace, it is not
|
|
|
|
|
possible to mix apt patterns or .deb package file paths containing either
|
|
|
|
|
commas or whitespace with normal package names. If you do, your patterns and
|
|
|
|
|
paths will be split by comma and whitespace as well and become useless. To pass
|
|
|
|
|
such a pattern or package file path, put them into their own B<--include>
|
|
|
|
|
option. If the argument to B<--include> starts with an apt pattern or with a
|
|
|
|
|
file path, then it will not be split:
|
|
|
|
|
|
|
|
|
|
--include="?or(?priority(required), ?priority(important))"
|
|
|
|
|
--include="./path/to/deb with spaces/and,commas/foo.deb"
|
|
|
|
|
|
|
|
|
|
Specifically, all arguments to B<--include> that start with a C<?>, C<!>, C<~>,
|
|
|
|
|
C<(>, C</>, C<./> or C<../> are not split and treated as single arguments to
|
|
|
|
|
apt. To add more packages, use multiple B<--include> options. To disable this
|
|
|
|
|
detection of patterns and paths, start the argument to B<--include> with a
|
|
|
|
|
comma or whitespace.
|
|
|
|
|
|
|
|
|
|
=item B<--components>=I<comp1>[,I<comp2>,...]
|
|
|
|
|
|
|
|
|
|
Comma or whitespace separated list of components like main, contrib and
|
|
|
|
@ -6278,7 +6329,8 @@ B<mmdebstrap> tries hard to implement sensible defaults and will try to stop
|
|
|
|
|
you before shooting yourself in the foot. This option is for when you are sure
|
|
|
|
|
you know what you are doing and allows one to skip certain actions and safety
|
|
|
|
|
checks. See section B<OPERATION> for a list of possible arguments and their
|
|
|
|
|
context.
|
|
|
|
|
context. The option can be specified multiple times or you can separate
|
|
|
|
|
multiple values by comma or whitespace.
|
|
|
|
|
|
|
|
|
|
=item B<-q,--quiet>, B<-s,--silent>
|
|
|
|
|
|
|
|
|
@ -6318,8 +6370,7 @@ This mode automatically selects a fitting mode. If the effective user id is the
|
|
|
|
|
one of the superuser, then the B<sudo> mode is chosen. Otherwise, the
|
|
|
|
|
B<unshare> mode is picked if the system has the sysctl
|
|
|
|
|
C<kernel.unprivileged_userns_clone> set to C<1>. Should that not be the case
|
|
|
|
|
and if the fakechroot binary exists, the B<fakechroot> mode is chosen. Lastly,
|
|
|
|
|
the B<proot> mode is used if the proot binary exists.
|
|
|
|
|
and if the fakechroot binary exists, the B<fakechroot> mode is chosen.
|
|
|
|
|
|
|
|
|
|
=item B<sudo>, B<root>
|
|
|
|
|
|
|
|
|
@ -6371,15 +6422,6 @@ package B<initramfs-tools> until version 0.132. This mode will also not work
|
|
|
|
|
with a different libc inside the chroot than on the outside. See the section
|
|
|
|
|
B<LIMITATIONS> in B<fakechroot(1)>.
|
|
|
|
|
|
|
|
|
|
=item B<proot>
|
|
|
|
|
|
|
|
|
|
This mode will carry out all calls to chroot with proot instead. Since
|
|
|
|
|
ownership information is only retained while proot is still running, this will
|
|
|
|
|
lead to wrong ownership information in the final directory (everything will be
|
|
|
|
|
owned by the user that executed B<mmdebstrap>) and tarball (everything will be
|
|
|
|
|
owned by the root user). Extended attributes are not retained. This mode is
|
|
|
|
|
useful if you plan to use the chroot with proot.
|
|
|
|
|
|
|
|
|
|
=item B<chrootless>
|
|
|
|
|
|
|
|
|
|
Uses the dpkg option C<--force-script-chrootless> to install packages into
|
|
|
|
@ -6387,8 +6429,8 @@ I<TARGET> without dpkg and apt inside I<TARGET> but using apt and dpkg from the
|
|
|
|
|
machine running B<mmdebstrap>. Maintainer scripts are run without chrooting
|
|
|
|
|
into I<TARGET> and rely on their dependencies being installed on the machine
|
|
|
|
|
running B<mmdebstrap>. Only very few packages support this mode. Namely, as of
|
|
|
|
|
2021, not all essential packages support it, mainly due to missing support in
|
|
|
|
|
debconf. See https://wiki.debian.org/Teams/Dpkg/Spec/InstallBootstrap or the
|
|
|
|
|
2022, not all essential packages support it. See
|
|
|
|
|
https://wiki.debian.org/Teams/Dpkg/Spec/InstallBootstrap or the
|
|
|
|
|
dpkg-root-support usertag of debian-dpkg@lists.debian.org in the Debian bug
|
|
|
|
|
tracking system. B<WARNING>: if this option is used carelessly with packages
|
|
|
|
|
that do not support C<DPKG_ROOT>, this mode can result in undesired changes to
|
|
|
|
@ -6572,19 +6614,20 @@ B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
|
|
|
|
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
|
|
|
|
|
extract, essential, customize) and C<MMDEBSTRAP_VERBOSITY> stores the numerical
|
|
|
|
|
verbosity level (0 for no output, 1 for normal, 2 for verbose and 3 for debug
|
|
|
|
|
output).
|
|
|
|
|
output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of packages, apt
|
|
|
|
|
patterns or file paths given by the B<--include> option, separated by a comma
|
|
|
|
|
and with commas and percent signs in the option values urlencoded.
|
|
|
|
|
|
|
|
|
|
In special hooks, the paths inside the chroot are relative to the root
|
|
|
|
|
directory of the chroot. The path on the outside is relative to current
|
|
|
|
|
directory of the original B<mmdebstrap> invocation. The path inside the chroot
|
|
|
|
|
must already exist. Paths outside the chroot are created as necessary.
|
|
|
|
|
|
|
|
|
|
In B<fakechroot> and B<proot> mode, C<tar>, or C<sh> and C<cat> have to be run
|
|
|
|
|
inside the chroot or otherwise, symlinks will be wrongly resolved and/or
|
|
|
|
|
permissions will be off. This means that the special hooks might fail in
|
|
|
|
|
B<fakechroot> and B<proot> mode for the B<setup> hook or for the B<extract> and
|
|
|
|
|
B<custom> variants if no C<tar> or C<sh> and C<cat> is available inside the
|
|
|
|
|
chroot.
|
|
|
|
|
In B<fakechroot> mode, C<tar>, or C<sh> and C<cat> have to be run inside the
|
|
|
|
|
chroot or otherwise, symlinks will be wrongly resolved and/or permissions will
|
|
|
|
|
be off. This means that the special hooks might fail in B<fakechroot> mode for
|
|
|
|
|
the B<setup> hook or for the B<extract> and B<custom> variants if no C<tar> or
|
|
|
|
|
C<sh> and C<cat> is available inside the chroot.
|
|
|
|
|
|
|
|
|
|
=over 8
|
|
|
|
|
|
|
|
|
@ -6754,6 +6797,18 @@ out in B<extract> mode.
|
|
|
|
|
Run B<--customize-hook> options and all F<customize*> scripts in B<--hook-dir>.
|
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
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<cleanup>
|
|
|
|
|
|
|
|
|
|
Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
|
|
|
@ -6784,6 +6839,8 @@ Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
|
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
|
|
=item * Remove everything in F</run> inside the chroot. This can be disabled using B<--skip=cleanup/run>.
|
|
|
|
|
|
|
|
|
|
=item * Remove everything in F</tmp> inside the chroot. This can be disabled using B<--skip=cleanup/tmp>.
|
|
|
|
|
|
|
|
|
|
=back
|
|
|
|
@ -7074,7 +7131,7 @@ This section lists some differences to debootstrap.
|
|
|
|
|
|
|
|
|
|
=item * Default mirrors for stable releases include updates and security mirror
|
|
|
|
|
|
|
|
|
|
=item * Multiple ways to operate as non-root: fakechroot, proot, unshare
|
|
|
|
|
=item * Multiple ways to operate as non-root: fakechroot and unshare
|
|
|
|
|
|
|
|
|
|
=item * twice as fast
|
|
|
|
|
|
|
|
|
|