Compare commits
No commits in common. "9682e74385e85c44652664a79ec6288cec4e1558" and "7ce6db0ca768d18390c9d34d67b83f4c22e262b1" have entirely different histories.
9682e74385
...
7ce6db0ca7
11 changed files with 318 additions and 414 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,18 +1,3 @@
|
||||||
1.2.0 (2022-09-05)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- remove proot mode
|
|
||||||
- error out if stdout is an interactive terminal
|
|
||||||
- replace taridshift by tarfilter --idshift
|
|
||||||
- tarfilter: add --transform option
|
|
||||||
- multiple --skip options can be separated by comma or whitespace
|
|
||||||
- also cleanup the contents of /run
|
|
||||||
- support apt patterns and paths with commas and whitespace in --include
|
|
||||||
- hooks: store the values of the --include option in MMDEBSTRAP_INCLUDE
|
|
||||||
- add new --skip options: chroot/start-stop-daemon, chroot/policy-rc.d
|
|
||||||
chroot/mount, chroot/mount/dev, chroot/mount/proc, chroot/mount/sys,
|
|
||||||
cleanup/run
|
|
||||||
|
|
||||||
1.1.0 (2022-07-26)
|
1.1.0 (2022-07-26)
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ Summary:
|
||||||
- chroot with apt in 11 seconds
|
- chroot with apt in 11 seconds
|
||||||
- gzipped tarball with apt is 27M small
|
- gzipped tarball with apt is 27M small
|
||||||
- bit-by-bit reproducible output
|
- bit-by-bit reproducible output
|
||||||
- unprivileged operation using Linux user namespaces or fakechroot
|
- unprivileged operation using Linux user namespaces, fakechroot or proot
|
||||||
- can operate on filesystems mounted with nodev
|
- can operate on filesystems mounted with nodev
|
||||||
- foreign architecture chroots with qemu-user
|
- foreign architecture chroots with qemu-user
|
||||||
- variant installing only Essential:yes packages and dependencies
|
- variant installing only Essential:yes packages and dependencies
|
||||||
|
@ -78,9 +78,9 @@ privileges to create a file (the chroot tarball) in one's home directory.
|
||||||
Thus, mmdebstrap provides multiple options to create a chroot tarball with the
|
Thus, mmdebstrap provides multiple options to create a chroot tarball with the
|
||||||
right permissions **without superuser privileges**. This avoids a whole class
|
right permissions **without superuser privileges**. This avoids a whole class
|
||||||
of bugs like #921815. Depending on what is available, it uses either Linux user
|
of bugs like #921815. Depending on what is available, it uses either Linux user
|
||||||
namespaces or fakechroot. Debootstrap supports fakechroot but will not
|
namespaces, fakechroot or proot. Debootstrap supports fakechroot but will not
|
||||||
create a tarball with the right permissions by itself. Support for Linux user
|
create a tarball with the right permissions by itself. Support for Linux user
|
||||||
namespaces is missing (see #829134).
|
namespaces and proot is missing (see bugs #829134 and #698347, respectively).
|
||||||
|
|
||||||
When creating a chroot tarball with debootstrap, the temporary chroot directory
|
When creating a chroot tarball with debootstrap, the temporary chroot directory
|
||||||
cannot be on a filesystem that has been mounted with nodev. In unprivileged
|
cannot be on a filesystem that has been mounted with nodev. In unprivileged
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
if [ -e ./mmdebstrap ]; then
|
if [ -e ./mmdebstrap -a -e ./taridshift -a -e ./tarfilter -a -e ./coverage.py ]; then
|
||||||
TMPFILE=$(mktemp)
|
TMPFILE=$(mktemp)
|
||||||
perltidy < ./mmdebstrap > "$TMPFILE"
|
perltidy < ./mmdebstrap > "$TMPFILE"
|
||||||
ret=0
|
ret=0
|
||||||
|
@ -20,10 +20,9 @@ if [ -e ./mmdebstrap ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
perlcritic --severity 4 --verbose 8 ./mmdebstrap
|
perlcritic --severity 4 --verbose 8 ./mmdebstrap
|
||||||
fi
|
|
||||||
|
|
||||||
[ -e ./tarfilter ] && black --check ./tarfilter
|
black --check ./taridshift ./tarfilter ./coverage.py
|
||||||
[ -e ./coverage.py ] && black --check ./coverage.py
|
fi
|
||||||
|
|
||||||
mirrordir="./shared/cache/debian"
|
mirrordir="./shared/cache/debian"
|
||||||
|
|
||||||
|
@ -114,4 +113,4 @@ END
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm shared/test.sh shared/tar1.txt shared/tar2.txt shared/pkglist.txt shared/doc-debian.tar.list shared/mmdebstrap shared/tarfilter shared/proxysolver
|
rm shared/test.sh shared/tar1.txt shared/tar2.txt shared/pkglist.txt shared/doc-debian.tar.list shared/mmdebstrap shared/taridshift shared/tarfilter shared/proxysolver
|
||||||
|
|
|
@ -264,11 +264,6 @@ Test: not-having-to-install-apt-in-include-because-a-hook-did-it-before
|
||||||
|
|
||||||
Test: remove-start-stop-daemon-and-policy-rc-d-in-hook
|
Test: remove-start-stop-daemon-and-policy-rc-d-in-hook
|
||||||
|
|
||||||
Test: skip-start-stop-daemon-policy-rc
|
|
||||||
|
|
||||||
Test: skip-mount
|
|
||||||
Modes: unshare
|
|
||||||
|
|
||||||
Test: compare-output-with-pre-seeded-var-cache-apt-archives
|
Test: compare-output-with-pre-seeded-var-cache-apt-archives
|
||||||
Needs-QEMU: true
|
Needs-QEMU: true
|
||||||
Variants: any
|
Variants: any
|
||||||
|
|
397
mmdebstrap
397
mmdebstrap
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
#
|
#
|
||||||
# © 2018 - 2022 Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
# © 2018 - 2021 Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
our $VERSION = '1.2.0';
|
our $VERSION = '1.1.0';
|
||||||
|
|
||||||
use English;
|
use English;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
|
@ -1104,12 +1104,8 @@ sub run_chroot {
|
||||||
}
|
}
|
||||||
} elsif ($type == 3 or $type == 4) {
|
} elsif ($type == 3 or $type == 4) {
|
||||||
# character/block special
|
# character/block special
|
||||||
if (
|
if ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
||||||
any { $_ =~ '^chroot/mount(?:/dev)?$' }
|
&& !$options->{canmount}) {
|
||||||
@{ $options->{skip} }
|
|
||||||
) {
|
|
||||||
info "skipping chroot/mount/dev as requested";
|
|
||||||
} elsif (!$options->{canmount}) {
|
|
||||||
warning "skipping bind-mounting ./dev/$fname";
|
warning "skipping bind-mounting ./dev/$fname";
|
||||||
} elsif (!$options->{havemknod}) {
|
} elsif (!$options->{havemknod}) {
|
||||||
if (!-d "$options->{root}/dev") {
|
if (!-d "$options->{root}/dev") {
|
||||||
|
@ -1164,21 +1160,15 @@ sub run_chroot {
|
||||||
"$options->{root}/dev/$fname")
|
"$options->{root}/dev/$fname")
|
||||||
or error "mount ./dev/$fname failed: $?";
|
or error "mount ./dev/$fname failed: $?";
|
||||||
}
|
}
|
||||||
} elsif ($type == 5) {
|
} elsif ($type == 5
|
||||||
# directory
|
&& (any { $_ eq $options->{mode} } ('root', 'unshare'))
|
||||||
if (
|
&& !$options->{canmount}) {
|
||||||
any { $_ =~ '^chroot/mount(?:/dev)?$' }
|
|
||||||
@{ $options->{skip} }
|
|
||||||
) {
|
|
||||||
info "skipping chroot/mount/dev as requested";
|
|
||||||
} elsif (!$options->{canmount}) {
|
|
||||||
warning "skipping bind-mounting ./dev/$fname";
|
warning "skipping bind-mounting ./dev/$fname";
|
||||||
} else {
|
} elsif ($type == 5) { # directory
|
||||||
if (!-d "$options->{root}/dev") {
|
if (!-d "$options->{root}/dev") {
|
||||||
warning(
|
warning(
|
||||||
"skipping creation of ./dev/$fname because the"
|
"skipping creation of ./dev/$fname because the"
|
||||||
. " /dev directory is missing in the target"
|
. " /dev directory is missing in the target");
|
||||||
);
|
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if (!-e "/dev/$fname" && $fname ne "pts/") {
|
if (!-e "/dev/$fname" && $fname ne "pts/") {
|
||||||
|
@ -1202,8 +1192,7 @@ sub run_chroot {
|
||||||
};
|
};
|
||||||
if (-e "$options->{root}/dev/$fname") {
|
if (-e "$options->{root}/dev/$fname") {
|
||||||
if (!-d "$options->{root}/dev/$fname") {
|
if (!-d "$options->{root}/dev/$fname") {
|
||||||
error
|
error "./dev/$fname already exists but is not"
|
||||||
"./dev/$fname already exists but is not"
|
|
||||||
. " a directory";
|
. " a directory";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1220,8 +1209,8 @@ sub run_chroot {
|
||||||
} @$err
|
} @$err
|
||||||
));
|
));
|
||||||
} elsif ($num_created == 0) {
|
} elsif ($num_created == 0) {
|
||||||
error( "cannot create $options->{root}"
|
error
|
||||||
. "/dev/$fname");
|
"cannot create $options->{root}/dev/$fname";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chmod $mode, "$options->{root}/dev/$fname"
|
chmod $mode, "$options->{root}/dev/$fname"
|
||||||
|
@ -1262,13 +1251,17 @@ sub run_chroot {
|
||||||
"$options->{root}/dev/$fname")
|
"$options->{root}/dev/$fname")
|
||||||
or error "mount ./dev/$fname failed: $?";
|
or error "mount ./dev/$fname failed: $?";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
error "unsupported type: $type";
|
error "unsupported type: $type";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elsif (any { $_ eq $options->{mode} } ('fakechroot', 'chrootless')) {
|
} elsif (
|
||||||
# we cannot mount in fakechroot mode
|
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
|
||||||
} else {
|
} else {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
|
@ -1276,10 +1269,6 @@ sub run_chroot {
|
||||||
# set because if we mount it before, then base-files will not be able
|
# set because if we mount it before, then base-files will not be able
|
||||||
# to extract those
|
# to extract those
|
||||||
if ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
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}) {
|
&& !$options->{canmount}) {
|
||||||
warning "skipping mount sysfs";
|
warning "skipping mount sysfs";
|
||||||
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
||||||
|
@ -1344,17 +1333,17 @@ sub run_chroot {
|
||||||
# type, bad option, bad superblock" error
|
# type, bad option, bad superblock" error
|
||||||
0 == system('mount', '-o', 'rbind', '/sys', "$options->{root}/sys")
|
0 == system('mount', '-o', 'rbind', '/sys', "$options->{root}/sys")
|
||||||
or error "mount /sys failed: $?";
|
or error "mount /sys failed: $?";
|
||||||
} elsif (any { $_ eq $options->{mode} } ('fakechroot', 'chrootless')) {
|
} elsif (
|
||||||
# we cannot mount in fakechroot mode
|
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
|
||||||
} else {
|
} else {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
if (
|
if ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
||||||
(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}) {
|
&& !$options->{canmount}) {
|
||||||
warning "skipping mount proc";
|
warning "skipping mount proc";
|
||||||
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
} elsif ((any { $_ eq $options->{mode} } ('root', 'unshare'))
|
||||||
|
@ -1419,8 +1408,13 @@ sub run_chroot {
|
||||||
};
|
};
|
||||||
0 == system('mount', '-t', 'proc', 'proc', "$options->{root}/proc")
|
0 == system('mount', '-t', 'proc', 'proc', "$options->{root}/proc")
|
||||||
or error "mount /proc failed: $?";
|
or error "mount /proc failed: $?";
|
||||||
} elsif (any { $_ eq $options->{mode} } ('fakechroot', 'chrootless')) {
|
} elsif (
|
||||||
# we cannot mount in fakechroot mode
|
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
|
||||||
} else {
|
} else {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
|
@ -1432,9 +1426,6 @@ sub run_chroot {
|
||||||
# existing inside the chroot
|
# existing inside the chroot
|
||||||
#
|
#
|
||||||
# See #911290 for more problems of this interface
|
# 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/") {
|
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: $!";
|
||||||
|
@ -1444,16 +1435,11 @@ sub run_chroot {
|
||||||
chmod 0755, "$options->{root}/usr/sbin/policy-rc.d"
|
chmod 0755, "$options->{root}/usr/sbin/policy-rc.d"
|
||||||
or error "cannot chmod policy-rc.d: $!";
|
or error "cannot chmod policy-rc.d: $!";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
# the file might not exist if it was removed in a hook
|
# 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 (-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 "$options->{root}/sbin/start-stop-daemon.REAL already"
|
||||||
"$options->{root}/sbin/start-stop-daemon.REAL already"
|
|
||||||
. " exists";
|
. " exists";
|
||||||
}
|
}
|
||||||
move(
|
move(
|
||||||
|
@ -1463,36 +1449,26 @@ sub run_chroot {
|
||||||
open my $fh, '>', "$options->{root}/sbin/start-stop-daemon"
|
open my $fh, '>', "$options->{root}/sbin/start-stop-daemon"
|
||||||
or error "cannot open start-stop-daemon: $!";
|
or error "cannot open start-stop-daemon: $!";
|
||||||
print $fh "#!/bin/sh\n";
|
print $fh "#!/bin/sh\n";
|
||||||
print $fh
|
print $fh "echo \"Warning: Fake start-stop-daemon called, doing"
|
||||||
"echo \"Warning: Fake start-stop-daemon called, doing"
|
|
||||||
. " nothing\">&2\n";
|
. " nothing\">&2\n";
|
||||||
close $fh;
|
close $fh;
|
||||||
chmod 0755, "$options->{root}/sbin/start-stop-daemon"
|
chmod 0755, "$options->{root}/sbin/start-stop-daemon"
|
||||||
or error "cannot chmod start-stop-daemon: $!";
|
or error "cannot chmod start-stop-daemon: $!";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&{$cmd}();
|
&{$cmd}();
|
||||||
|
|
||||||
# cleanup
|
# 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") {
|
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
||||||
move(
|
move(
|
||||||
"$options->{root}/sbin/start-stop-daemon.REAL",
|
"$options->{root}/sbin/start-stop-daemon.REAL",
|
||||||
"$options->{root}/sbin/start-stop-daemon"
|
"$options->{root}/sbin/start-stop-daemon"
|
||||||
) or error "cannot move 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") {
|
if (-f "$options->{root}/usr/sbin/policy-rc.d") {
|
||||||
unlink "$options->{root}/usr/sbin/policy-rc.d"
|
unlink "$options->{root}/usr/sbin/policy-rc.d"
|
||||||
or error "cannot unlink policy-rc.d: $!";
|
or error "cannot unlink policy-rc.d: $!";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1554,20 +1530,6 @@ sub run_hooks {
|
||||||
# Store the verbosity of mmdebstrap so that hooks can be just as verbose
|
# Store the verbosity of mmdebstrap so that hooks can be just as verbose
|
||||||
# as the mmdebstrap invocation that called them.
|
# as the mmdebstrap invocation that called them.
|
||||||
push @env_opts, ("MMDEBSTRAP_VERBOSITY=" . $verbosity_level);
|
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 {
|
my $runner = sub {
|
||||||
foreach my $script (@{ $options->{"${name}_hook"} }) {
|
foreach my $script (@{ $options->{"${name}_hook"} }) {
|
||||||
|
@ -1580,11 +1542,13 @@ sub run_hooks {
|
||||||
)\ /x
|
)\ /x
|
||||||
) {
|
) {
|
||||||
info "running special hook: $script";
|
info "running special hook: $script";
|
||||||
if ((any { $_ eq $options->{variant} } ('extract', 'custom'))
|
if (
|
||||||
and $options->{mode} eq 'fakechroot'
|
any { $_ eq $options->{variant} } ('extract', 'custom')
|
||||||
and $name ne 'setup') {
|
and any { $_ eq $options->{mode} }
|
||||||
|
('fakechroot', 'proot') and $name ne 'setup'
|
||||||
|
) {
|
||||||
info "the copy-in, copy-out, tar-in and tar-out commands"
|
info "the copy-in, copy-out, tar-in and tar-out commands"
|
||||||
. " in fakechroot mode might fail in"
|
. " in fakechroot mode or proot mode might fail in"
|
||||||
. " extract and custom variants because there might be"
|
. " extract and custom variants because there might be"
|
||||||
. " no tar inside the chroot";
|
. " no tar inside the chroot";
|
||||||
}
|
}
|
||||||
|
@ -2110,14 +2074,14 @@ sub run_setup() {
|
||||||
copy($tmpfile, \*STDERR);
|
copy($tmpfile, \*STDERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($options->{mode} ne 'fakechroot') {
|
if (none { $_ eq $options->{mode} } ('fakechroot', 'proot')) {
|
||||||
# Apt dropping privileges to another user than root is not useful in
|
# Apt dropping privileges to another user than root is not useful in
|
||||||
# fakechroot mode because all users are faked and thus there is no real
|
# fakechroot and proot mode because all users are faked and thus there
|
||||||
# privilege difference anyways. We could set APT::Sandbox::User "root"
|
# is no real privilege difference anyways. We could set
|
||||||
# in fakechroot mode but we don't because if we would, then
|
# APT::Sandbox::User "root" in fakechroot and proot mode but we don't
|
||||||
# /var/cache/apt/archives/partial/ and /var/lib/apt/lists/partial/
|
# because if we would, then /var/cache/apt/archives/partial/ and
|
||||||
# would not be owned by the _apt user if mmdebstrap was run in
|
# /var/lib/apt/lists/partial/ would not be owned by the _apt user
|
||||||
# fakechroot mode.
|
# if mmdebstrap was run in fakechroot or proot mode.
|
||||||
#
|
#
|
||||||
# when apt-get update is run by the root user, then apt will attempt to
|
# 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
|
# drop privileges to the _apt user. This will fail if the _apt user
|
||||||
|
@ -2529,15 +2493,29 @@ sub run_prepare {
|
||||||
# make sure that APT_CONFIG and TMPDIR are not set when executing
|
# make sure that APT_CONFIG and TMPDIR are not set when executing
|
||||||
# anything inside the chroot
|
# anything inside the chroot
|
||||||
my @chrootcmd = ('env', '--unset=APT_CONFIG', '--unset=TMPDIR');
|
my @chrootcmd = ('env', '--unset=APT_CONFIG', '--unset=TMPDIR');
|
||||||
if (any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot')) {
|
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')
|
||||||
|
) {
|
||||||
push @chrootcmd, ('chroot', $options->{root});
|
push @chrootcmd, ('chroot', $options->{root});
|
||||||
} else {
|
} else {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
|
|
||||||
# copy qemu-user-static binary into chroot
|
# copy qemu-user-static binary into chroot or setup proot with
|
||||||
|
# --qemu
|
||||||
if (defined $options->{qemu}) {
|
if (defined $options->{qemu}) {
|
||||||
if ($options->{mode} eq 'fakechroot') {
|
if ($options->{mode} eq 'proot') {
|
||||||
|
push @chrootcmd, "--qemu=qemu-$options->{qemu}";
|
||||||
|
} elsif ($options->{mode} eq 'fakechroot') {
|
||||||
# Make sure that the fakeroot and fakechroot shared
|
# Make sure that the fakeroot and fakechroot shared
|
||||||
# libraries exist for the right architecture
|
# libraries exist for the right architecture
|
||||||
open my $fh, '-|', 'dpkg-architecture', '-a',
|
open my $fh, '-|', 'dpkg-architecture', '-a',
|
||||||
|
@ -2623,21 +2601,29 @@ sub run_prepare {
|
||||||
}
|
}
|
||||||
|
|
||||||
# some versions of coreutils use the renameat2 system call in mv.
|
# some versions of coreutils use the renameat2 system call in mv.
|
||||||
# This breaks certain versions of fakechroot. Here we do
|
# This breaks certain versions of fakechroot and proot. Here we do
|
||||||
# a sanity check and warn the user in case things might break.
|
# a sanity check and warn the user in case things might break.
|
||||||
if ($options->{mode} eq 'fakechroot'
|
if (any { $_ eq $options->{mode} } ('fakechroot', 'proot')
|
||||||
and -e "$options->{root}/bin/mv") {
|
and -e "$options->{root}/bin/mv") {
|
||||||
mkdir "$options->{root}/000-move-me"
|
mkdir "$options->{root}/000-move-me"
|
||||||
or error "cannot create directory: $!";
|
or error "cannot create directory: $!";
|
||||||
my $ret = system @chrootcmd, '/bin/mv', '/000-move-me',
|
my $ret = system @chrootcmd, '/bin/mv', '/000-move-me',
|
||||||
'/001-delete-me';
|
'/001-delete-me';
|
||||||
if ($ret != 0) {
|
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"
|
info "the /bin/mv binary inside the chroot doesn't"
|
||||||
. " work under fakechroot";
|
. " work under fakechroot";
|
||||||
info "with certain versions of coreutils and glibc,"
|
info "with certain versions of coreutils and glibc,"
|
||||||
. " this is due to missing support for renameat2 in"
|
. " this is due to missing support for renameat2 in"
|
||||||
. " fakechroot";
|
. " fakechroot";
|
||||||
info "see https://github.com/dex4er/fakechroot/issues/60";
|
info "see https://github.com/dex4er/fakechroot/issues/60";
|
||||||
|
}
|
||||||
info "expect package post installation scripts not to work";
|
info "expect package post installation scripts not to work";
|
||||||
rmdir "$options->{root}/000-move-me"
|
rmdir "$options->{root}/000-move-me"
|
||||||
or error "cannot rmdir: $!";
|
or error "cannot rmdir: $!";
|
||||||
|
@ -2707,8 +2693,10 @@ sub run_essential() {
|
||||||
'--force-depends'
|
'--force-depends'
|
||||||
],
|
],
|
||||||
PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}] });
|
PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}] });
|
||||||
} elsif (any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot'))
|
} elsif (
|
||||||
{
|
any { $_ eq $options->{mode} }
|
||||||
|
('root', 'unshare', 'fakechroot', 'proot')
|
||||||
|
) {
|
||||||
# install the extracted packages properly
|
# install the extracted packages properly
|
||||||
# we need --force-depends because dpkg does not take Pre-Depends
|
# we need --force-depends because dpkg does not take Pre-Depends
|
||||||
# into account and thus doesn't install them in the right order
|
# into account and thus doesn't install them in the right order
|
||||||
|
@ -2828,8 +2816,10 @@ sub run_install() {
|
||||||
PKGS => [@pkgs_to_install],
|
PKGS => [@pkgs_to_install],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} elsif (any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot'))
|
} elsif (
|
||||||
{
|
any { $_ eq $options->{mode} }
|
||||||
|
('root', 'unshare', 'fakechroot', 'proot')
|
||||||
|
) {
|
||||||
if ($options->{variant} ne 'custom'
|
if ($options->{variant} ne 'custom'
|
||||||
and scalar @pkgs_to_install > 0) {
|
and scalar @pkgs_to_install > 0) {
|
||||||
# Advantage of running apt on the outside instead of inside the
|
# Advantage of running apt on the outside instead of inside the
|
||||||
|
@ -3011,31 +3001,10 @@ 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} }) {
|
if (any { $_ eq 'cleanup/tmp' } @{ $options->{skip} }) {
|
||||||
info "skipping cleanup/tmp as requested";
|
info "skipping cleanup/tmp as requested";
|
||||||
} else {
|
} else {
|
||||||
# remove any possible leftovers in /tmp
|
# remove any possible leftovers in /tmp but warn about it
|
||||||
if (-d "$options->{root}/tmp") {
|
if (-d "$options->{root}/tmp") {
|
||||||
opendir(my $dh, "$options->{root}/tmp")
|
opendir(my $dh, "$options->{root}/tmp")
|
||||||
or error "Can't opendir($options->{root}/tmp): $!";
|
or error "Can't opendir($options->{root}/tmp): $!";
|
||||||
|
@ -3043,7 +3012,7 @@ sub run_cleanup() {
|
||||||
# skip the "." and ".." entries
|
# skip the "." and ".." entries
|
||||||
next if $entry eq ".";
|
next if $entry eq ".";
|
||||||
next if $entry eq "..";
|
next if $entry eq "..";
|
||||||
debug "deleting files in /tmp: $entry";
|
warning "deleting files in /tmp: $entry";
|
||||||
0 == system(
|
0 == system(
|
||||||
'rm', '--interactive=never',
|
'rm', '--interactive=never',
|
||||||
'--recursive', '--preserve-root',
|
'--recursive', '--preserve-root',
|
||||||
|
@ -3136,12 +3105,26 @@ sub hookhelper {
|
||||||
. 'delete=atime,delete=ctime'
|
. 'delete=atime,delete=ctime'
|
||||||
);
|
);
|
||||||
if ($hook eq 'setup') {
|
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')) {
|
} elsif (any { $_ eq $hook } ('extract', 'essential', 'customize')) {
|
||||||
if ($mode eq 'fakechroot') {
|
if ($mode eq 'fakechroot') {
|
||||||
# Fakechroot requires tar to run inside the chroot or
|
# Fakechroot requires tar to run inside the chroot or
|
||||||
# otherwise absolute symlinks will include the path to the
|
# otherwise absolute symlinks will include the path to the
|
||||||
# root directory
|
# root directory
|
||||||
push @cmdprefix, 'chroot', $root;
|
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')) {
|
} elsif (any { $_ eq $mode } ('root', 'chrootless', 'unshare')) {
|
||||||
# not chrooting in this case
|
# not chrooting in this case
|
||||||
} else {
|
} else {
|
||||||
|
@ -3172,7 +3155,7 @@ sub hookhelper {
|
||||||
any { $_ eq $hook }
|
any { $_ eq $hook }
|
||||||
('extract', 'essential', 'customize')
|
('extract', 'essential', 'customize')
|
||||||
) {
|
) {
|
||||||
if ($mode eq 'fakechroot') {
|
if (any { $_ eq $mode } ('fakechroot', 'proot')) {
|
||||||
# tar will run inside the chroot
|
# tar will run inside the chroot
|
||||||
$directory = $outpath;
|
$directory = $outpath;
|
||||||
} elsif (
|
} elsif (
|
||||||
|
@ -3187,10 +3170,10 @@ sub hookhelper {
|
||||||
error "unknown hook: $hook";
|
error "unknown hook: $hook";
|
||||||
}
|
}
|
||||||
|
|
||||||
# if chrooted_realpath was used and if fakechroot
|
# if chrooted_realpath was used and if neither fakechroot or
|
||||||
# was used (absolute symlinks will be broken) we can
|
# proot were used (absolute symlinks will be broken) we can
|
||||||
# check and potentially fail early if the target does not exist
|
# check and potentially fail early if the target does not exist
|
||||||
if ($mode ne 'fakechroot') {
|
if (none { $_ eq $mode } ('fakechroot', 'proot')) {
|
||||||
my $dirtocheck = $directory;
|
my $dirtocheck = $directory;
|
||||||
if ($command eq 'upload') {
|
if ($command eq 'upload') {
|
||||||
# check the parent directory instead
|
# check the parent directory instead
|
||||||
|
@ -3319,7 +3302,7 @@ sub hookhelper {
|
||||||
any { $_ eq $hook }
|
any { $_ eq $hook }
|
||||||
('extract', 'essential', 'customize')
|
('extract', 'essential', 'customize')
|
||||||
) {
|
) {
|
||||||
if ($mode eq 'fakechroot') {
|
if (any { $_ eq $mode } ('fakechroot', 'proot')) {
|
||||||
# tar will run inside the chroot
|
# tar will run inside the chroot
|
||||||
$directory = $ARGV[$i];
|
$directory = $ARGV[$i];
|
||||||
} elsif (
|
} elsif (
|
||||||
|
@ -3334,10 +3317,10 @@ sub hookhelper {
|
||||||
error "unknown hook: $hook";
|
error "unknown hook: $hook";
|
||||||
}
|
}
|
||||||
|
|
||||||
# if chrooted_realpath was used and if fakechroot
|
# if chrooted_realpath was used and if neither fakechroot or
|
||||||
# was used (absolute symlinks will be broken) we can
|
# proot were used (absolute symlinks will be broken) we can
|
||||||
# check and potentially fail early if the source does not exist
|
# check and potentially fail early if the source does not exist
|
||||||
if ($mode ne 'fakechroot') {
|
if (none { $_ eq $mode } ('fakechroot', 'proot')) {
|
||||||
if (!-e $directory) {
|
if (!-e $directory) {
|
||||||
error "path does not exist: $directory";
|
error "path does not exist: $directory";
|
||||||
}
|
}
|
||||||
|
@ -4264,26 +4247,6 @@ sub main() {
|
||||||
'variant=s' => \$options->{variant},
|
'variant=s' => \$options->{variant},
|
||||||
'include=s' => sub {
|
'include=s' => sub {
|
||||||
my ($opt_name, $opt_value) = @_;
|
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) {
|
for my $pkg (split /[,\s]+/, $opt_value) {
|
||||||
# strip leading and trailing whitespace
|
# strip leading and trailing whitespace
|
||||||
$pkg =~ s/^\s+|\s+$//g;
|
$pkg =~ s/^\s+|\s+$//g;
|
||||||
|
@ -4291,17 +4254,8 @@ sub main() {
|
||||||
if ($pkg eq '') {
|
if ($pkg eq '') {
|
||||||
next;
|
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;
|
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},
|
'architectures=s@' => \$options->{architectures},
|
||||||
'mode=s' => \$options->{mode},
|
'mode=s' => \$options->{mode},
|
||||||
|
@ -4401,18 +4355,8 @@ sub main() {
|
||||||
# here prepare for long suffering in dependency hell.
|
# here prepare for long suffering in dependency hell.
|
||||||
'simulate' => \$options->{dryrun},
|
'simulate' => \$options->{dryrun},
|
||||||
'dry-run' => \$options->{dryrun},
|
'dry-run' => \$options->{dryrun},
|
||||||
'skip=s' => sub {
|
'skip=s@' => \$options->{skip},
|
||||||
my ($opt_name, $opt_value) = @_;
|
) or pod2usage(-exitval => 2, -verbose => 1);
|
||||||
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)) {
|
if (defined($logfile)) {
|
||||||
open(STDERR, '>', $logfile) or error "cannot open $logfile: $!";
|
open(STDERR, '>', $logfile) or error "cannot open $logfile: $!";
|
||||||
|
@ -4456,7 +4400,8 @@ sub main() {
|
||||||
if ($options->{mode} eq 'sudo') {
|
if ($options->{mode} eq 'sudo') {
|
||||||
$options->{mode} = 'root';
|
$options->{mode} = 'root';
|
||||||
}
|
}
|
||||||
my @valid_modes = ('auto', 'root', 'unshare', 'fakechroot', 'chrootless');
|
my @valid_modes
|
||||||
|
= ('auto', 'root', 'unshare', 'fakechroot', 'proot', 'chrootless');
|
||||||
if (none { $_ eq $options->{mode} } @valid_modes) {
|
if (none { $_ eq $options->{mode} } @valid_modes) {
|
||||||
error "invalid mode. Choose from " . (join ', ', @valid_modes);
|
error "invalid mode. Choose from " . (join ', ', @valid_modes);
|
||||||
}
|
}
|
||||||
|
@ -4580,6 +4525,9 @@ sub main() {
|
||||||
@prefix = ($EXECUTABLE_NAME, '-MDevel::Cover=-silent,-nogcov');
|
@prefix = ($EXECUTABLE_NAME, '-MDevel::Cover=-silent,-nogcov');
|
||||||
}
|
}
|
||||||
exec 'fakechroot', 'fakeroot', @prefix, $PROGRAM_NAME, @ARGVORIG;
|
exec 'fakechroot', 'fakeroot', @prefix, $PROGRAM_NAME, @ARGVORIG;
|
||||||
|
} elsif (can_execute 'proot') {
|
||||||
|
# and lastly, proot
|
||||||
|
$options->{mode} = 'proot';
|
||||||
} else {
|
} else {
|
||||||
error "unable to pick chroot mode automatically";
|
error "unable to pick chroot mode automatically";
|
||||||
}
|
}
|
||||||
|
@ -4588,6 +4536,10 @@ sub main() {
|
||||||
if ($EFFECTIVE_USER_ID != 0) {
|
if ($EFFECTIVE_USER_ID != 0) {
|
||||||
error "need to be root";
|
error "need to be root";
|
||||||
}
|
}
|
||||||
|
} elsif ($options->{mode} eq 'proot') {
|
||||||
|
if (!can_execute 'proot') {
|
||||||
|
error "need working proot binary";
|
||||||
|
}
|
||||||
} elsif ($options->{mode} eq 'fakechroot') {
|
} elsif ($options->{mode} eq 'fakechroot') {
|
||||||
if (&{$check_fakechroot_running}()) {
|
if (&{$check_fakechroot_running}()) {
|
||||||
# fakechroot is already running
|
# fakechroot is already running
|
||||||
|
@ -4664,7 +4616,7 @@ sub main() {
|
||||||
0 == syscall &SYS_capget, $hdrp, $datap
|
0 == syscall &SYS_capget, $hdrp, $datap
|
||||||
or error "capget failed: $!";
|
or error "capget failed: $!";
|
||||||
my ($effective, undef) = unpack "LLLLLL", $datap;
|
my ($effective, undef) = unpack "LLLLLL", $datap;
|
||||||
if ((($effective >> $CAP_SYS_ADMIN) & 1) != 1) {
|
if (($effective >> $CAP_SYS_ADMIN) & 1 != 1) {
|
||||||
warning
|
warning
|
||||||
"cannot mount because CAP_SYS_ADMIN is not in the effective set";
|
"cannot mount because CAP_SYS_ADMIN is not in the effective set";
|
||||||
$options->{canmount} = 0;
|
$options->{canmount} = 0;
|
||||||
|
@ -5319,9 +5271,9 @@ sub main() {
|
||||||
if (any { $_ eq $format } ('tar', 'squashfs', 'ext2', 'null')) {
|
if (any { $_ eq $format } ('tar', 'squashfs', 'ext2', 'null')) {
|
||||||
if ($format ne 'null') {
|
if ($format ne 'null') {
|
||||||
if ( any { $_ eq $options->{variant} } ('extract', 'custom')
|
if ( any { $_ eq $options->{variant} } ('extract', 'custom')
|
||||||
and $options->{mode} eq 'fakechroot') {
|
and any { $_ eq $options->{mode} } ('fakechroot', 'proot')) {
|
||||||
info "creating a tarball or squashfs image or ext2 image in"
|
info "creating a tarball or squashfs image or ext2 image in"
|
||||||
. " fakechroot mode might fail in extract and"
|
. " fakechroot mode or proot mode might fail in extract and"
|
||||||
. " custom variants because there might be no tar inside the"
|
. " custom variants because there might be no tar inside the"
|
||||||
. " chroot";
|
. " chroot";
|
||||||
}
|
}
|
||||||
|
@ -5459,7 +5411,7 @@ sub main() {
|
||||||
$? == 0 or error "havemknod failed";
|
$? == 0 or error "havemknod failed";
|
||||||
} elsif (
|
} elsif (
|
||||||
any { $_ eq $options->{mode} }
|
any { $_ eq $options->{mode} }
|
||||||
('root', 'fakechroot', 'chrootless')
|
('root', 'fakechroot', 'proot', 'chrootless')
|
||||||
) {
|
) {
|
||||||
$options->{havemknod} = havemknod($options->{root});
|
$options->{havemknod} = havemknod($options->{root});
|
||||||
} else {
|
} else {
|
||||||
|
@ -5620,7 +5572,7 @@ sub main() {
|
||||||
);
|
);
|
||||||
} elsif (
|
} elsif (
|
||||||
any { $_ eq $options->{mode} }
|
any { $_ eq $options->{mode} }
|
||||||
('root', 'fakechroot', 'chrootless')
|
('root', 'fakechroot', 'proot', 'chrootless')
|
||||||
) {
|
) {
|
||||||
$pid = fork() // error "fork() failed: $!";
|
$pid = fork() // error "fork() failed: $!";
|
||||||
if ($pid == 0) {
|
if ($pid == 0) {
|
||||||
|
@ -5683,6 +5635,18 @@ sub main() {
|
||||||
0 == system('chroot', $options->{root}, 'tar',
|
0 == system('chroot', $options->{root}, 'tar',
|
||||||
@taropts, '-C', '/', '.')
|
@taropts, '-C', '/', '.')
|
||||||
or error "tar failed: $?";
|
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 (
|
} elsif (
|
||||||
any { $_ eq $options->{mode} }
|
any { $_ eq $options->{mode} }
|
||||||
('root', 'chrootless')
|
('root', 'chrootless')
|
||||||
|
@ -5920,11 +5884,15 @@ sub main() {
|
||||||
}
|
}
|
||||||
} elsif (
|
} elsif (
|
||||||
any { $_ eq $options->{mode} }
|
any { $_ eq $options->{mode} }
|
||||||
('root', 'fakechroot', 'chrootless')
|
('root', 'fakechroot', 'proot', 'chrootless')
|
||||||
) {
|
) {
|
||||||
# without unshare, we use the system's rm to recursively remove the
|
# without unshare, we use the system's rm to recursively remove the
|
||||||
# temporary directory just to make sure that we do not accidentally
|
# temporary directory just to make sure that we do not accidentally
|
||||||
# remove more than we should by using --one-file-system.
|
# 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',
|
0 == system('rm', '--interactive=never', '--recursive',
|
||||||
'--preserve-root', '--one-file-system', $options->{root})
|
'--preserve-root', '--one-file-system', $options->{root})
|
||||||
or error "rm failed: $?";
|
or error "rm failed: $?";
|
||||||
|
@ -6045,7 +6013,7 @@ B<debootstrap>. See the section B<VARIANTS> for more information.
|
||||||
|
|
||||||
Choose how to perform the chroot operation and create a filesystem with
|
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
|
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> and
|
B<auto>, B<sudo>, B<root>, B<unshare>, B<fakeroot>, B<fakechroot>, B<proot> and
|
||||||
B<chrootless>. The default mode is B<auto>. See the section B<MODES> for more
|
B<chrootless>. The default mode is B<auto>. See the section B<MODES> for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
@ -6150,35 +6118,16 @@ 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
|
dpkg, respectively. For all other variants, apt is used to install the
|
||||||
additional packages. Package names are directly passed to apt and thus, you
|
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
|
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
|
||||||
regex for C<pkg>, use apt patterns or pass a path to a .deb package file. See
|
regex for C<pkg> or use apt patterns. See apt(8) for the supported
|
||||||
apt(8) for the supported syntax.
|
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
|
||||||
The option can be specified multiple times and the packages are concatenated in
|
later list items are repeated, then they get dropped so that the resulting
|
||||||
the order in which they are given on the command line. If later list items are
|
package list is free of duplicates. So the following are equivalent:
|
||||||
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-,,,
|
--include=pkg1/stable,pkg2=1.0,pkg3-
|
||||||
--incl=pkg1/stable --incl="pkg2=1.0 pkg3-" --incl=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>,...]
|
=item B<--components>=I<comp1>[,I<comp2>,...]
|
||||||
|
|
||||||
Comma or whitespace separated list of components like main, contrib and
|
Comma or whitespace separated list of components like main, contrib and
|
||||||
|
@ -6329,8 +6278,7 @@ 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 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
|
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
|
checks. See section B<OPERATION> for a list of possible arguments and their
|
||||||
context. The option can be specified multiple times or you can separate
|
context.
|
||||||
multiple values by comma or whitespace.
|
|
||||||
|
|
||||||
=item B<-q,--quiet>, B<-s,--silent>
|
=item B<-q,--quiet>, B<-s,--silent>
|
||||||
|
|
||||||
|
@ -6370,7 +6318,8 @@ 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
|
one of the superuser, then the B<sudo> mode is chosen. Otherwise, the
|
||||||
B<unshare> mode is picked if the system has the sysctl
|
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
|
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.
|
and if the fakechroot binary exists, the B<fakechroot> mode is chosen. Lastly,
|
||||||
|
the B<proot> mode is used if the proot binary exists.
|
||||||
|
|
||||||
=item B<sudo>, B<root>
|
=item B<sudo>, B<root>
|
||||||
|
|
||||||
|
@ -6422,6 +6371,15 @@ 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
|
with a different libc inside the chroot than on the outside. See the section
|
||||||
B<LIMITATIONS> in B<fakechroot(1)>.
|
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>
|
=item B<chrootless>
|
||||||
|
|
||||||
Uses the dpkg option C<--force-script-chrootless> to install packages into
|
Uses the dpkg option C<--force-script-chrootless> to install packages into
|
||||||
|
@ -6429,8 +6387,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
|
machine running B<mmdebstrap>. Maintainer scripts are run without chrooting
|
||||||
into I<TARGET> and rely on their dependencies being installed on the machine
|
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
|
running B<mmdebstrap>. Only very few packages support this mode. Namely, as of
|
||||||
2022, not all essential packages support it. See
|
2021, not all essential packages support it, mainly due to missing support in
|
||||||
https://wiki.debian.org/Teams/Dpkg/Spec/InstallBootstrap or the
|
debconf. 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
|
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
|
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
|
that do not support C<DPKG_ROOT>, this mode can result in undesired changes to
|
||||||
|
@ -6614,20 +6572,19 @@ B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
||||||
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
|
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
|
||||||
extract, essential, customize) and C<MMDEBSTRAP_VERBOSITY> stores the numerical
|
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
|
verbosity level (0 for no output, 1 for normal, 2 for verbose and 3 for debug
|
||||||
output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of packages, apt
|
output).
|
||||||
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
|
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 chroot. The path on the outside is relative to current
|
||||||
directory of the original B<mmdebstrap> invocation. The path inside the chroot
|
directory of the original B<mmdebstrap> invocation. The path inside the chroot
|
||||||
must already exist. Paths outside the chroot are created as necessary.
|
must already exist. Paths outside the chroot are created as necessary.
|
||||||
|
|
||||||
In B<fakechroot> mode, C<tar>, or C<sh> and C<cat> have to be run inside the
|
In B<fakechroot> and B<proot> mode, C<tar>, or C<sh> and C<cat> have to be run
|
||||||
chroot or otherwise, symlinks will be wrongly resolved and/or permissions will
|
inside the chroot or otherwise, symlinks will be wrongly resolved and/or
|
||||||
be off. This means that the special hooks might fail in B<fakechroot> mode for
|
permissions will be off. This means that the special hooks might fail in
|
||||||
the B<setup> hook or for the B<extract> and B<custom> variants if no C<tar> or
|
B<fakechroot> and B<proot> mode for the B<setup> hook or for the B<extract> and
|
||||||
C<sh> and C<cat> is available inside the chroot.
|
B<custom> variants if no C<tar> or C<sh> and C<cat> is available inside the
|
||||||
|
chroot.
|
||||||
|
|
||||||
=over 8
|
=over 8
|
||||||
|
|
||||||
|
@ -6797,18 +6754,6 @@ 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
|
|
||||||
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>
|
=item B<cleanup>
|
||||||
|
|
||||||
Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
||||||
|
@ -6839,8 +6784,6 @@ Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
||||||
|
|
||||||
=back
|
=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>.
|
=item * Remove everything in F</tmp> inside the chroot. This can be disabled using B<--skip=cleanup/tmp>.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
@ -7131,7 +7074,7 @@ This section lists some differences to debootstrap.
|
||||||
|
|
||||||
=item * Default mirrors for stable releases include updates and security mirror
|
=item * Default mirrors for stable releases include updates and security mirror
|
||||||
|
|
||||||
=item * Multiple ways to operate as non-root: fakechroot and unshare
|
=item * Multiple ways to operate as non-root: fakechroot, proot, unshare
|
||||||
|
|
||||||
=item * twice as fast
|
=item * twice as fast
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ tar --xattrs --xattrs-include='*' -C /tmp/debian-debootstrap -xf "cache/debian-u
|
||||||
# delete the directory
|
# delete the directory
|
||||||
tar -C /tmp/debian-debootstrap -cf dev1.tar ./dev
|
tar -C /tmp/debian-debootstrap -cf dev1.tar ./dev
|
||||||
tar -C /tmp/debian-mm -cf dev2.tar ./dev
|
tar -C /tmp/debian-mm -cf dev2.tar ./dev
|
||||||
cmp dev1.tar dev2.tar >&2
|
cmp dev1.tar dev2.tar
|
||||||
rm dev1.tar dev2.tar
|
rm dev1.tar dev2.tar
|
||||||
rm -r /tmp/debian-debootstrap/dev /tmp/debian-mm/dev
|
rm -r /tmp/debian-debootstrap/dev /tmp/debian-mm/dev
|
||||||
|
|
||||||
|
@ -34,9 +34,6 @@ rm /tmp/debian-debootstrap/var/log/dpkg.log \
|
||||||
/tmp/debian-debootstrap/var/log/alternatives.log \
|
/tmp/debian-debootstrap/var/log/alternatives.log \
|
||||||
/tmp/debian-mm/var/log/bootstrap.log
|
/tmp/debian-mm/var/log/bootstrap.log
|
||||||
|
|
||||||
# clear out /run
|
|
||||||
rm -r /tmp/debian-debootstrap/run/*
|
|
||||||
|
|
||||||
# debootstrap doesn't clean apt
|
# debootstrap doesn't clean apt
|
||||||
rm /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_main_binary-{{ HOSTARCH }}_Packages \
|
rm /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_main_binary-{{ HOSTARCH }}_Packages \
|
||||||
/tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_Release \
|
/tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_Release \
|
||||||
|
@ -47,7 +44,7 @@ rm /tmp/debian-mm/var/cache/apt/archives/lock
|
||||||
rm /tmp/debian-mm/var/lib/apt/lists/lock
|
rm /tmp/debian-mm/var/lib/apt/lists/lock
|
||||||
|
|
||||||
# check if the file content differs
|
# check if the file content differs
|
||||||
diff --no-dereference --recursive /tmp/debian-debootstrap /tmp/debian-mm >&2
|
diff --no-dereference --recursive /tmp/debian-debootstrap /tmp/debian-mm
|
||||||
|
|
||||||
# check permissions, ownership, symlink targets, modification times using tar
|
# check permissions, ownership, symlink targets, modification times using tar
|
||||||
# mtimes of directories created by mmdebstrap will differ, thus we equalize them first
|
# mtimes of directories created by mmdebstrap will differ, thus we equalize them first
|
||||||
|
@ -67,7 +64,7 @@ tar --full-time --verbose -tf /tmp/root2.tar > /tmp/root2.tar.list
|
||||||
# will slightly differ from each other in the sub-second precision (last
|
# will slightly differ from each other in the sub-second precision (last
|
||||||
# decimals) so the tarballs will not be identical, so we use diff to compare
|
# decimals) so the tarballs will not be identical, so we use diff to compare
|
||||||
# content and tar to compare attributes
|
# content and tar to compare attributes
|
||||||
diff -u /tmp/root1.tar.list /tmp/root2.tar.list >&2
|
diff -u /tmp/root1.tar.list /tmp/root2.tar.list
|
||||||
rm /tmp/root1.tar /tmp/root2.tar /tmp/root1.tar.list /tmp/root2.tar.list
|
rm /tmp/root1.tar /tmp/root2.tar /tmp/root1.tar.list /tmp/root2.tar.list
|
||||||
|
|
||||||
rm /tmp/debian-mm.tar
|
rm /tmp/debian-mm.tar
|
||||||
|
|
|
@ -95,8 +95,13 @@ fi
|
||||||
if [ -e /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels ]; then
|
if [ -e /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels ]; then
|
||||||
rm /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels
|
rm /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels
|
||||||
fi
|
fi
|
||||||
# clear out /run
|
# who creates /run/mount?
|
||||||
rm -r /tmp/debian-{{ DIST }}-debootstrap/run/*
|
if [ -e "/tmp/debian-{{ DIST }}-debootstrap/run/mount/utab" ]; then
|
||||||
|
rm "/tmp/debian-{{ DIST }}-debootstrap/run/mount/utab"
|
||||||
|
fi
|
||||||
|
if [ -e "/tmp/debian-{{ DIST }}-debootstrap/run/mount" ]; then
|
||||||
|
rmdir "/tmp/debian-{{ DIST }}-debootstrap/run/mount"
|
||||||
|
fi
|
||||||
# debootstrap doesn't clean apt
|
# debootstrap doesn't clean apt
|
||||||
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_main_binary-{{ HOSTARCH }}_Packages \
|
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_main_binary-{{ HOSTARCH }}_Packages \
|
||||||
/tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_Release \
|
/tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_Release \
|
||||||
|
|
|
@ -21,6 +21,7 @@ prefix=
|
||||||
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures=arm64 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures=arm64 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
||||||
# we ignore differences between architectures by ignoring some files
|
# we ignore differences between architectures by ignoring some files
|
||||||
# and renaming others
|
# and renaming others
|
||||||
|
# in proot mode, some extra files are put there by proot
|
||||||
{ tar -tf /tmp/debian-chroot.tar \
|
{ tar -tf /tmp/debian-chroot.tar \
|
||||||
| grep -v '^\./lib/ld-linux-aarch64\.so\.1$' \
|
| grep -v '^\./lib/ld-linux-aarch64\.so\.1$' \
|
||||||
| grep -v '^\./lib/aarch64-linux-gnu/ld-linux-aarch64\.so\.1$' \
|
| grep -v '^\./lib/aarch64-linux-gnu/ld-linux-aarch64\.so\.1$' \
|
||||||
|
@ -39,5 +40,6 @@ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures=arm64 {{ DIST
|
||||||
| grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.amd64\.gz$' \
|
| grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.amd64\.gz$' \
|
||||||
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
|
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
|
||||||
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$';
|
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$';
|
||||||
|
[ "{{ MODE }}" = "proot" ] && printf "./etc/ld.so.preload\n";
|
||||||
} | sort | diff -u - tar2.txt
|
} | sort | diff -u - tar2.txt
|
||||||
rm /tmp/debian-chroot.tar
|
rm /tmp/debian-chroot.tar
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
[ "{{ MODE }}" = "unshare" ]
|
|
||||||
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
|
||||||
{{ CMD }} --mode=unshare --variant=apt \
|
|
||||||
--skip=chroot/mount/proc,chroot/mount/sys \
|
|
||||||
--customize-hook='mountpoint "$1"/dev/null' \
|
|
||||||
--customize-hook='if mountpoint "$1"/sys; then exit 1; fi' \
|
|
||||||
--customize-hook='if mountpoint "$1"/proc; then exit 1; fi' \
|
|
||||||
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
|
||||||
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
|
||||||
{{ CMD }} --mode={{ MODE }} --variant=apt \
|
|
||||||
--skip=chroot/start-stop-daemon,chroot/policy-rc.d \
|
|
||||||
--customize-hook='test ! -e "$1/sbin/start-stop-daemon.REAL"' \
|
|
||||||
--customize-hook='test ! -e "$1/usr/sbin/policy-rc.d"' \
|
|
||||||
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
|
||||||
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
|
|
|
@ -19,7 +19,7 @@ prefix=
|
||||||
[ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && prefix="runuser -u user --"
|
[ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && prefix="runuser -u user --"
|
||||||
[ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot"
|
[ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot"
|
||||||
symlinktarget=/real
|
symlinktarget=/real
|
||||||
[ "{{ MODE }}" = "fakechroot" ] && symlinktarget='$1/real'
|
case {{ MODE }} in fakechroot|proot) symlinktarget='$1/real';; esac
|
||||||
echo copy-in-setup > /tmp/copy-in-setup
|
echo copy-in-setup > /tmp/copy-in-setup
|
||||||
echo copy-in-essential > /tmp/copy-in-essential
|
echo copy-in-essential > /tmp/copy-in-essential
|
||||||
echo copy-in-customize > /tmp/copy-in-customize
|
echo copy-in-customize > /tmp/copy-in-customize
|
||||||
|
|
Loading…
Reference in a new issue