Compare commits
22 commits
Author | SHA1 | Date | |
---|---|---|---|
28a3a15955 | |||
9e7d7d0d67 | |||
ff91e58219 | |||
38ebe6aa1f | |||
|
c7803e2e2e | ||
fe758b8441 | |||
b04758b133 | |||
bf6aaa30ac | |||
d7107567d1 | |||
712fdcf1ab | |||
59e5870e7b | |||
b78afd9e92 | |||
5761c527a0 | |||
7709ad49bb | |||
|
9366f1fee7 | ||
b1ba7dab3d | |||
792867a390 | |||
917a879c4b | |||
dc5bbb7173 | |||
e62f32b098 | |||
fcf1c407de | |||
1a17c70ffb |
13 changed files with 153 additions and 37 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,3 +1,15 @@
|
||||||
|
1.5.7 (2025-04-08)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- support for elxr Debian derivative
|
||||||
|
- support loong64
|
||||||
|
- mmdebstrap-autopkgtest-build-qemu: add --sshkey=...
|
||||||
|
|
||||||
|
1.5.6 (2025-01-11)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- bugfix release
|
||||||
|
|
||||||
1.5.5 (2025-01-09)
|
1.5.5 (2025-01-09)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -157,12 +157,13 @@ Contributors
|
||||||
============
|
============
|
||||||
|
|
||||||
- Johannes Schauer Marin Rodrigues (main author)
|
- Johannes Schauer Marin Rodrigues (main author)
|
||||||
- Helmut Grohne
|
|
||||||
- Jochen Sprickerhof
|
- Jochen Sprickerhof
|
||||||
|
- Helmut Grohne
|
||||||
- Gioele Barabucci
|
- Gioele Barabucci
|
||||||
- Benjamin Drung
|
- Benjamin Drung
|
||||||
- Josh Triplett
|
- Josh Triplett
|
||||||
- Konstantin Demin
|
- Konstantin Demin
|
||||||
|
- Charles Short
|
||||||
- Chris Hofstaedtler
|
- Chris Hofstaedtler
|
||||||
- Colin Watson
|
- Colin Watson
|
||||||
- David Kalnischkies
|
- David Kalnischkies
|
||||||
|
|
|
@ -26,7 +26,7 @@ if [ -e "$MMSCRIPT" ]; then
|
||||||
rm "$TMPFILE"
|
rm "$TMPFILE"
|
||||||
|
|
||||||
if [ "$(sed -e '/^__END__$/,$d' "$MMSCRIPT" | wc --max-line-length)" -gt 79 ]; then
|
if [ "$(sed -e '/^__END__$/,$d' "$MMSCRIPT" | wc --max-line-length)" -gt 79 ]; then
|
||||||
echo "exceeded maximum line length of 79 characters" >&2
|
echo "$MMSCRIPT exceeded maximum line length of 79 characters" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -435,3 +435,4 @@ Test: zombie-reaping
|
||||||
Modes: unshare
|
Modes: unshare
|
||||||
|
|
||||||
Test: empty-suite
|
Test: empty-suite
|
||||||
|
Needs-APT-Config: true
|
||||||
|
|
|
@ -47,5 +47,10 @@ case $GPGSTATUSFD in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if ! command -v gpgv >&2; then
|
||||||
|
eval 'echo "[GNUPG:] ERROR gpgv executable not found" >&'"$GPGSTATUSFD"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# we need eval because we cannot redirect a variable fd
|
# we need eval because we cannot redirect a variable fd
|
||||||
eval 'exec gpgv "$@" '"$GPGSTATUSFD"'>&1 | sed "s/^\[GNUPG:\] EXPKEYSIG /[GNUPG:] GOODSIG /" >&'"$GPGSTATUSFD"
|
eval 'exec gpgv "$@" '"$GPGSTATUSFD"'>&1 | sed "s/^\[GNUPG:\] EXPKEYSIG /[GNUPG:] GOODSIG /" >&'"$GPGSTATUSFD"
|
||||||
|
|
72
mmdebstrap
72
mmdebstrap
|
@ -23,7 +23,7 @@
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
our $VERSION = '1.5.5';
|
our $VERSION = '1.5.7';
|
||||||
|
|
||||||
use English;
|
use English;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
|
@ -40,7 +40,8 @@ use Fcntl
|
||||||
qw(S_IFCHR S_IFBLK FD_CLOEXEC F_GETFD F_SETFD LOCK_EX O_RDONLY O_DIRECTORY);
|
qw(S_IFCHR S_IFBLK FD_CLOEXEC F_GETFD F_SETFD LOCK_EX O_RDONLY O_DIRECTORY);
|
||||||
use List::Util qw(any none);
|
use List::Util qw(any none);
|
||||||
use POSIX
|
use POSIX
|
||||||
qw(SIGINT SIGHUP SIGPIPE SIGTERM SIG_BLOCK SIG_UNBLOCK strftime isatty);
|
qw(SIGINT SIGHUP SIGPIPE SIGTERM SIG_BLOCK SIG_UNBLOCK strftime isatty
|
||||||
|
WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG);
|
||||||
use Carp;
|
use Carp;
|
||||||
use Term::ANSIColor;
|
use Term::ANSIColor;
|
||||||
use Socket;
|
use Socket;
|
||||||
|
@ -1963,10 +1964,7 @@ sub run_progress {
|
||||||
}
|
}
|
||||||
|
|
||||||
close($pipe);
|
close($pipe);
|
||||||
my $fail = 0;
|
my $proc_exit = $?;
|
||||||
if ($? != 0 or $has_error) {
|
|
||||||
$fail = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid $pid2, 0;
|
waitpid $pid2, 0;
|
||||||
$? == 0 or error "progress parsing failed";
|
$? == 0 or error "progress parsing failed";
|
||||||
|
@ -1977,11 +1975,29 @@ sub run_progress {
|
||||||
|
|
||||||
# only print failure after progress output finished or otherwise it
|
# only print failure after progress output finished or otherwise it
|
||||||
# might interfere with the remaining output
|
# might interfere with the remaining output
|
||||||
if ($fail) {
|
if ($proc_exit != 0 or $has_error) {
|
||||||
if ($verbosity_level >= 1) {
|
if ($verbosity_level >= 1) {
|
||||||
print STDERR $output;
|
print STDERR $output;
|
||||||
}
|
}
|
||||||
error((join ' ', $get_exec->('<$fd>')) . ' failed');
|
my $what = '';
|
||||||
|
if ($proc_exit != 0) {
|
||||||
|
if (POSIX::WIFEXITED($proc_exit)) {
|
||||||
|
my $exit = POSIX::WEXITSTATUS($proc_exit);
|
||||||
|
$what
|
||||||
|
.= "process exited with $exit and error in console output";
|
||||||
|
} elsif (POSIX::WIFSIGNALED($proc_exit)) {
|
||||||
|
my $sig = POSIX::WTERMSIG($proc_exit);
|
||||||
|
$what = "process was killed by signal $sig";
|
||||||
|
} else {
|
||||||
|
$what = "process failed with unknown status code";
|
||||||
|
}
|
||||||
|
if ($has_error) {
|
||||||
|
$what .= " and error in console output";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$what .= "error in console output";
|
||||||
|
}
|
||||||
|
error((join ' ', $get_exec->('<$fd>')) . " failed: $what");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2870,6 +2886,9 @@ sub setup {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-e $options->{apttrusted} && !-r $options->{apttrusted}) {
|
if (-e $options->{apttrusted} && !-r $options->{apttrusted}) {
|
||||||
|
# FIXME: obtain the keyring file with the permissions of the user
|
||||||
|
# outside of the unshared namespace
|
||||||
|
# FIXME: apt no longer sets Dir::Etc::trusted by default
|
||||||
warning "cannot read $options->{apttrusted}";
|
warning "cannot read $options->{apttrusted}";
|
||||||
}
|
}
|
||||||
if (-e $options->{apttrustedparts} && !-r $options->{apttrustedparts}) {
|
if (-e $options->{apttrustedparts} && !-r $options->{apttrustedparts}) {
|
||||||
|
@ -3108,7 +3127,11 @@ sub run_setup() {
|
||||||
# dpkg-preconfigure should not be needed as we also have set
|
# dpkg-preconfigure should not be needed as we also have set
|
||||||
# DEBIAN_FRONTEND=noninteractive and DEBCONF_NONINTERACTIVE_SEEN=true and
|
# DEBIAN_FRONTEND=noninteractive and DEBCONF_NONINTERACTIVE_SEEN=true and
|
||||||
# should thus never see debconf prompts. See #1091442 for details.
|
# should thus never see debconf prompts. See #1091442 for details.
|
||||||
print $conf "#clear DPkg::Pre-Install-Pkgs;\n";
|
{
|
||||||
|
open my $tmp, '>', "$options->{root}/etc/apt/apt.conf.d/99debconf"
|
||||||
|
or error "cannot open /etc/apt/apt.conf.d/99debconf: $!";
|
||||||
|
print $tmp "#clear DPkg::Pre-Install-Pkgs;\n";
|
||||||
|
}
|
||||||
|
|
||||||
close $conf;
|
close $conf;
|
||||||
|
|
||||||
|
@ -4164,6 +4187,8 @@ sub run_cleanup() {
|
||||||
# clean up temporary configuration file
|
# clean up temporary configuration file
|
||||||
unlink "$options->{root}/etc/apt/apt.conf.d/00mmdebstrap"
|
unlink "$options->{root}/etc/apt/apt.conf.d/00mmdebstrap"
|
||||||
or warning "failed to unlink /etc/apt/apt.conf.d/00mmdebstrap: $!";
|
or warning "failed to unlink /etc/apt/apt.conf.d/00mmdebstrap: $!";
|
||||||
|
unlink "$options->{root}/etc/apt/apt.conf.d/99debconf"
|
||||||
|
or warning "failed to unlink /etc/apt/apt.conf.d/99debconf: $!";
|
||||||
|
|
||||||
if (defined $ENV{APT_CONFIG} && -e $ENV{APT_CONFIG}) {
|
if (defined $ENV{APT_CONFIG} && -e $ENV{APT_CONFIG}) {
|
||||||
unlink $ENV{APT_CONFIG}
|
unlink $ENV{APT_CONFIG}
|
||||||
|
@ -5121,6 +5146,7 @@ sub get_suite_by_vendor {
|
||||||
'ubuntu' => {},
|
'ubuntu' => {},
|
||||||
'tanglu' => {},
|
'tanglu' => {},
|
||||||
'kali' => {},
|
'kali' => {},
|
||||||
|
'elxr' => {},
|
||||||
);
|
);
|
||||||
|
|
||||||
# pre-fill with some known values
|
# pre-fill with some known values
|
||||||
|
@ -5142,6 +5168,9 @@ sub get_suite_by_vendor {
|
||||||
foreach my $suite ('kali-dev', 'kali-rolling', 'kali-bleeding-edge') {
|
foreach my $suite ('kali-dev', 'kali-rolling', 'kali-bleeding-edge') {
|
||||||
$suite_by_vendor{'kali'}->{$suite} = 0;
|
$suite_by_vendor{'kali'}->{$suite} = 0;
|
||||||
}
|
}
|
||||||
|
foreach my $suite ('aria') {
|
||||||
|
$suite_by_vendor{'elxr'}->{$suite} = 0;
|
||||||
|
}
|
||||||
foreach
|
foreach
|
||||||
my $suite ('trusty', 'xenial', 'zesty', 'artful', 'bionic', 'cosmic') {
|
my $suite ('trusty', 'xenial', 'zesty', 'artful', 'bionic', 'cosmic') {
|
||||||
$suite_by_vendor{'ubuntu'}->{$suite} = 0;
|
$suite_by_vendor{'ubuntu'}->{$suite} = 0;
|
||||||
|
@ -5190,6 +5219,9 @@ sub get_suite_by_vendor {
|
||||||
} elsif ($target eq "kali"
|
} elsif ($target eq "kali"
|
||||||
and not exists $suite_by_vendor{'kali'}->{$suite}) {
|
and not exists $suite_by_vendor{'kali'}->{$suite}) {
|
||||||
$suite_by_vendor{'kali'}->{$suite} = 0;
|
$suite_by_vendor{'kali'}->{$suite} = 0;
|
||||||
|
} elsif ($target eq "elxr"
|
||||||
|
and not exists $suite_by_vendor{'elxr'}->{$suite}) {
|
||||||
|
$suite_by_vendor{'elxr'}->{$suite} = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir($dh);
|
closedir($dh);
|
||||||
|
@ -5244,6 +5276,8 @@ sub get_keyring_by_suite {
|
||||||
return '/usr/share/keyrings/tanglu-archive-keyring.gpg';
|
return '/usr/share/keyrings/tanglu-archive-keyring.gpg';
|
||||||
} elsif ($vendor eq 'kali') {
|
} elsif ($vendor eq 'kali') {
|
||||||
return '/usr/share/keyrings/kali-archive-keyring.gpg';
|
return '/usr/share/keyrings/kali-archive-keyring.gpg';
|
||||||
|
} elsif ($vendor eq 'elxr') {
|
||||||
|
return '/usr/share/keyrings/elxr-archive-keyring.gpg';
|
||||||
} else {
|
} else {
|
||||||
error "unknown vendor: $vendor";
|
error "unknown vendor: $vendor";
|
||||||
}
|
}
|
||||||
|
@ -5280,6 +5314,7 @@ sub get_sourceslist_by_suite {
|
||||||
my @ubuntustable = keys %{ $suite_by_vendor->{'ubuntu'} };
|
my @ubuntustable = keys %{ $suite_by_vendor->{'ubuntu'} };
|
||||||
my @tanglustable = keys %{ $suite_by_vendor->{'tanglu'} };
|
my @tanglustable = keys %{ $suite_by_vendor->{'tanglu'} };
|
||||||
my @kali = keys %{ $suite_by_vendor->{'kali'} };
|
my @kali = keys %{ $suite_by_vendor->{'kali'} };
|
||||||
|
my @elxr = keys %{ $suite_by_vendor->{'elxr'} };
|
||||||
|
|
||||||
my $mirror = 'http://deb.debian.org/debian';
|
my $mirror = 'http://deb.debian.org/debian';
|
||||||
my $secmirror = 'http://security.debian.org/debian-security';
|
my $secmirror = 'http://security.debian.org/debian-security';
|
||||||
|
@ -5317,6 +5352,8 @@ sub get_sourceslist_by_suite {
|
||||||
$mirror = 'http://archive.tanglu.org/tanglu';
|
$mirror = 'http://archive.tanglu.org/tanglu';
|
||||||
} elsif (any { $_ eq $suite } @kali) {
|
} elsif (any { $_ eq $suite } @kali) {
|
||||||
$mirror = 'https://http.kali.org/kali';
|
$mirror = 'https://http.kali.org/kali';
|
||||||
|
} elsif (any { $_ eq $suite } @elxr) {
|
||||||
|
$mirror = 'https://mirror.elxr.dev';
|
||||||
}
|
}
|
||||||
my $sourceslist = '';
|
my $sourceslist = '';
|
||||||
$sourceslist .= "deb$signedby $mirror $suite $compstr\n";
|
$sourceslist .= "deb$signedby $mirror $suite $compstr\n";
|
||||||
|
@ -5542,9 +5579,9 @@ sub main() {
|
||||||
# obtain the correct defaults for the keyring locations that apt knows
|
# obtain the correct defaults for the keyring locations that apt knows
|
||||||
# about
|
# about
|
||||||
my $apttrusted
|
my $apttrusted
|
||||||
= `eval \$(apt-config shell v Dir::Etc::trusted/f); printf \$v`;
|
= `eval \$(apt-config shell v Dir::Etc::trusted/f); printf %s \$v`;
|
||||||
my $apttrustedparts
|
my $apttrustedparts
|
||||||
= `eval \$(apt-config shell v Dir::Etc::trustedparts/d); printf \$v`;
|
= `eval \$(apt-config shell v Dir::Etc::trustedparts/d); printf %s \$v`;
|
||||||
|
|
||||||
chomp(my $hostarch = `dpkg --print-architecture`);
|
chomp(my $hostarch = `dpkg --print-architecture`);
|
||||||
my $options = {
|
my $options = {
|
||||||
|
@ -5865,7 +5902,7 @@ sub main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# setting PATH for chroot, ldconfig, start-stop-daemon...
|
# setting PATH for chroot, ldconfig, start-stop-daemon...
|
||||||
my $defaultpath = `eval \$(apt-config shell v DPkg::Path); printf \$v`;
|
my $defaultpath = `eval \$(apt-config shell v DPkg::Path); printf %s \$v`;
|
||||||
if (length $ENV{PATH}) {
|
if (length $ENV{PATH}) {
|
||||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||||
$ENV{PATH} = "$ENV{PATH}:$defaultpath";
|
$ENV{PATH} = "$ENV{PATH}:$defaultpath";
|
||||||
|
@ -6128,6 +6165,7 @@ sub main() {
|
||||||
armhf => 'arm',
|
armhf => 'arm',
|
||||||
hppa => 'hppa',
|
hppa => 'hppa',
|
||||||
i386 => 'i386',
|
i386 => 'i386',
|
||||||
|
loong64 => 'loongarch64',
|
||||||
m68k => 'm68k',
|
m68k => 'm68k',
|
||||||
mips => 'mips',
|
mips => 'mips',
|
||||||
mips64 => 'mips64',
|
mips64 => 'mips64',
|
||||||
|
@ -6803,6 +6841,7 @@ sub main() {
|
||||||
if (any { $_ eq $options->{format} }
|
if (any { $_ eq $options->{format} }
|
||||||
('tar', 'squashfs', 'ext2', 'ext4', 'null')) {
|
('tar', 'squashfs', 'ext2', 'ext4', 'null')) {
|
||||||
if ($options->{format} ne 'null') {
|
if ($options->{format} ne 'null') {
|
||||||
|
#<<< perltidy 20220613 formatting
|
||||||
if (any { $_ eq $options->{variant} } ('extract', 'custom')
|
if (any { $_ eq $options->{variant} } ('extract', 'custom')
|
||||||
and $options->{mode} eq 'fakechroot') {
|
and $options->{mode} eq 'fakechroot') {
|
||||||
info "creating a tarball, squashfs, ext2 or ext4 image in"
|
info "creating a tarball, squashfs, ext2 or ext4 image in"
|
||||||
|
@ -6810,6 +6849,7 @@ sub main() {
|
||||||
. " custom variants because there might be no tar inside the"
|
. " custom variants because there might be no tar inside the"
|
||||||
. " chroot";
|
. " chroot";
|
||||||
}
|
}
|
||||||
|
#>>>
|
||||||
# try to fail early if target tarball or squashfs image cannot be
|
# try to fail early if target tarball or squashfs image cannot be
|
||||||
# opened for writing
|
# opened for writing
|
||||||
if ($options->{target} ne '-') {
|
if ($options->{target} ne '-') {
|
||||||
|
@ -6840,12 +6880,14 @@ sub main() {
|
||||||
# in unshare and root mode, other users than the current user need to
|
# in unshare and root mode, other users than the current user need to
|
||||||
# access the rootfs, most prominently, the _apt user. Thus, make the
|
# access the rootfs, most prominently, the _apt user. Thus, make the
|
||||||
# temporary directory world readable.
|
# temporary directory world readable.
|
||||||
|
#<<< perltidy 20220613 formatting
|
||||||
if (
|
if (
|
||||||
any { $_ eq $options->{mode} } ('unshare', 'root')
|
any { $_ eq $options->{mode} } ('unshare', 'root')
|
||||||
or ($EFFECTIVE_USER_ID == 0 and $options->{mode} eq 'chrootless')
|
or ($EFFECTIVE_USER_ID == 0 and $options->{mode} eq 'chrootless')
|
||||||
) {
|
) {
|
||||||
chmod 0755, $options->{root} or error "cannot chmod root: $!";
|
chmod 0755, $options->{root} or error "cannot chmod root: $!";
|
||||||
}
|
}
|
||||||
|
#>>>
|
||||||
} elsif ($options->{format} eq 'directory') {
|
} elsif ($options->{format} eq 'directory') {
|
||||||
# user does not seem to have specified a tarball as output, thus work
|
# user does not seem to have specified a tarball as output, thus work
|
||||||
# directly in the supplied directory
|
# directly in the supplied directory
|
||||||
|
@ -7331,9 +7373,11 @@ sub main() {
|
||||||
error "cannot copy to standard output: $!";
|
error "cannot copy to standard output: $!";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#<<< perltidy 20220613 formatting
|
||||||
if (any { $_ eq $options->{format} }
|
if (any { $_ eq $options->{format} }
|
||||||
('squashfs', 'ext2', 'ext4')
|
('squashfs', 'ext2', 'ext4')
|
||||||
or defined $tar_compressor) {
|
or defined $tar_compressor) {
|
||||||
|
#>>>
|
||||||
my @argv = ();
|
my @argv = ();
|
||||||
if ($options->{format} eq 'squashfs') {
|
if ($options->{format} eq 'squashfs') {
|
||||||
push @argv, 'tar2sqfs',
|
push @argv, 'tar2sqfs',
|
||||||
|
@ -8450,8 +8494,8 @@ its core, what B<mmdebstrap> does can be put into a 14 line shell script:
|
||||||
Apt::Architecture "$(dpkg --print-architecture)";
|
Apt::Architecture "$(dpkg --print-architecture)";
|
||||||
Apt::Architectures "$(dpkg --print-architecture)";
|
Apt::Architectures "$(dpkg --print-architecture)";
|
||||||
Dir "$(cd "$2" && pwd)";
|
Dir "$(cd "$2" && pwd)";
|
||||||
Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; printf "$v")";
|
Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; printf %s "$v")";
|
||||||
Dir::Etc::TrustedParts "$(eval "$(apt-config shell v Dir::Etc::TrustedParts/d)"; printf "$v")";
|
Dir::Etc::TrustedParts "$(eval "$(apt-config shell v Dir::Etc::TrustedParts/d)"; printf %s "$v")";
|
||||||
END
|
END
|
||||||
echo "deb http://deb.debian.org/debian/ $1 main" > "$2/etc/apt/sources.list"
|
echo "deb http://deb.debian.org/debian/ $1 main" > "$2/etc/apt/sources.list"
|
||||||
APT_CONFIG="$2/apt.conf" apt-get update
|
APT_CONFIG="$2/apt.conf" apt-get update
|
||||||
|
|
|
@ -95,6 +95,12 @@ explicitly select --boot=efi, operation will fail.
|
||||||
|
|
||||||
Passes an additional B<--keyring> parameter to B<mmdebstrap>.
|
Passes an additional B<--keyring> parameter to B<mmdebstrap>.
|
||||||
|
|
||||||
|
=item B<--sshkey>=F<sshkey>
|
||||||
|
|
||||||
|
Install the given ssh public key file into the virtual machine image for the root user.
|
||||||
|
This option also causes the ssh server to be installed.
|
||||||
|
By default, no key or server is installed.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 EXAMPLES
|
=head1 EXAMPLES
|
||||||
|
@ -131,7 +137,7 @@ die() {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
usage() {
|
usage() {
|
||||||
die "usage: $0 [--architecture=|--apt-proxy=|--keyring=|--mirror=|--script=|--size=] --boot=efi <RELEASE> <IMAGE>"
|
die "usage: $0 [--architecture=|--apt-proxy=|--keyring=|--sshkey=|--mirror=|--script=|--size=] --boot=efi <RELEASE> <IMAGE>"
|
||||||
}
|
}
|
||||||
usage_error() {
|
usage_error() {
|
||||||
echo "error: $*" 1>&2
|
echo "error: $*" 1>&2
|
||||||
|
@ -146,6 +152,7 @@ KEYRING=
|
||||||
RELEASE=
|
RELEASE=
|
||||||
SIZE=25G
|
SIZE=25G
|
||||||
SCRIPT=
|
SCRIPT=
|
||||||
|
SSHKEY=
|
||||||
|
|
||||||
# consumed by setup-testbed
|
# consumed by setup-testbed
|
||||||
export AUTOPKGTEST_BUILD_QEMU=1
|
export AUTOPKGTEST_BUILD_QEMU=1
|
||||||
|
@ -172,6 +179,9 @@ opt_apt_proxy() {
|
||||||
opt_keyring() {
|
opt_keyring() {
|
||||||
KEYRING="$1"
|
KEYRING="$1"
|
||||||
}
|
}
|
||||||
|
opt_sshkey() {
|
||||||
|
SSHKEY=$1
|
||||||
|
}
|
||||||
opt_mirror() {
|
opt_mirror() {
|
||||||
# consumed by setup-testbed
|
# consumed by setup-testbed
|
||||||
export MIRROR="$1"
|
export MIRROR="$1"
|
||||||
|
@ -202,14 +212,14 @@ positional_7() {
|
||||||
|
|
||||||
while test "$#" -gt 0; do
|
while test "$#" -gt 0; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--architecture=* | --arch=* | --boot=* | --keyring=* | --mirror=* | --script=* | --size=*)
|
--architecture=* | --arch=* | --boot=* | --keyring=* | --sshkey=* | --mirror=* | --script=* | --size=*)
|
||||||
optname="${1%%=*}"
|
optname="${1%%=*}"
|
||||||
"opt_${optname#--}" "${1#*=}"
|
"opt_${optname#--}" "${1#*=}"
|
||||||
;;
|
;;
|
||||||
--apt-proxy=*)
|
--apt-proxy=*)
|
||||||
opt_apt_proxy "${1#*=}"
|
opt_apt_proxy "${1#*=}"
|
||||||
;;
|
;;
|
||||||
--architecture | --arch | --boot | --keyring | --mirror | --script | --size)
|
--architecture | --arch | --boot | --keyring | --sshkey | --mirror | --script | --size)
|
||||||
test "$#" -ge 2 || usage_error "missing argument for $1"
|
test "$#" -ge 2 || usage_error "missing argument for $1"
|
||||||
"opt_${1#--}" "$2"
|
"opt_${1#--}" "$2"
|
||||||
shift
|
shift
|
||||||
|
@ -296,6 +306,10 @@ esac
|
||||||
test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed \
|
test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed \
|
||||||
|| die "please install dpkg-dev"
|
|| die "please install dpkg-dev"
|
||||||
|
|
||||||
|
if test -n "$SSHKEY" && ! test -f "$SSHKEY"; then
|
||||||
|
die "error: ssh keyfile '$SSHKEY' not found"
|
||||||
|
fi
|
||||||
|
|
||||||
dpkg-checkbuilddeps -d "autopkgtest, dosfstools, e2fsprogs, fdisk, mount, mtools, passwd, uidmap, libarchive13, systemd-boot-efi:$ARCHITECTURE $BINUTILS" /dev/null \
|
dpkg-checkbuilddeps -d "autopkgtest, dosfstools, e2fsprogs, fdisk, mount, mtools, passwd, uidmap, libarchive13, systemd-boot-efi:$ARCHITECTURE $BINUTILS" /dev/null \
|
||||||
|| die "please install the required packages listed above"
|
|| die "please install the required packages listed above"
|
||||||
|
|
||||||
|
@ -360,6 +374,14 @@ if test -n "$SCRIPT"; then
|
||||||
'--customize-hook=rm -f "$1/userscript"'
|
'--customize-hook=rm -f "$1/userscript"'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# add ssh key for root
|
||||||
|
if test -n "$SSHKEY"; then
|
||||||
|
set -- "$@" \
|
||||||
|
--include=openssh-server \
|
||||||
|
'--customize-hook=mkdir -m700 -p "$1/root/.ssh"' \
|
||||||
|
"--customize-hook=upload $SSHKEY /root/.ssh/authorized_keys"
|
||||||
|
fi
|
||||||
|
|
||||||
set -- "$@" \
|
set -- "$@" \
|
||||||
"--customize-hook=download vmlinuz '$WORKDIR/kernel'" \
|
"--customize-hook=download vmlinuz '$WORKDIR/kernel'" \
|
||||||
"--customize-hook=download initrd.img '$WORKDIR/initrd'" \
|
"--customize-hook=download initrd.img '$WORKDIR/initrd'" \
|
||||||
|
|
|
@ -7,7 +7,7 @@ while [ "$#" -gt 0 ]; do
|
||||||
key="$1"
|
key="$1"
|
||||||
case "$key" in
|
case "$key" in
|
||||||
SUDO)
|
SUDO)
|
||||||
SUDO=sudo
|
SUDO="sudo --preserve-env"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown argument: $key"
|
echo "Unknown argument: $key"
|
||||||
|
@ -33,6 +33,7 @@ ret=0
|
||||||
ret=0
|
ret=0
|
||||||
(
|
(
|
||||||
exec 3>&- 4>&-
|
exec 3>&- 4>&-
|
||||||
|
# shellcheck disable=SC2086
|
||||||
env --chdir=./shared $SUDO sh -x ./test.sh 2>&1
|
env --chdir=./shared $SUDO sh -x ./test.sh 2>&1
|
||||||
) || ret=$?
|
) || ret=$?
|
||||||
echo $ret >&3
|
echo $ret >&3
|
||||||
|
|
|
@ -28,11 +28,14 @@ fi
|
||||||
# https://bugs.debian.org/1031105
|
# https://bugs.debian.org/1031105
|
||||||
# https://salsa.debian.org/installer-team/debootstrap/-/merge_requests/90
|
# https://salsa.debian.org/installer-team/debootstrap/-/merge_requests/90
|
||||||
AUTOPROXY=
|
AUTOPROXY=
|
||||||
eval "$(apt-config shell AUTOPROXY Acquire::http::Proxy-Auto-Detect)"
|
# allow an empty http_proxy variable to disable this
|
||||||
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
|
if [ -n "${http_proxy-}" ]; then
|
||||||
TMP_APT_CONFIG=$(mktemp)
|
eval "$(apt-config shell AUTOPROXY Acquire::http::Proxy-Auto-Detect)"
|
||||||
echo 'Dir "/dev/null";' >"$TMP_APT_CONFIG"
|
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
|
||||||
chmod 644 "$TMP_APT_CONFIG"
|
TMP_APT_CONFIG=$(mktemp)
|
||||||
|
echo 'Dir "/dev/null";' >"$TMP_APT_CONFIG"
|
||||||
|
chmod 644 "$TMP_APT_CONFIG"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$prefix {{ CMD }} --variant=custom --mode={{ MODE }} \
|
$prefix {{ CMD }} --variant=custom --mode={{ MODE }} \
|
||||||
|
|
|
@ -2,7 +2,29 @@
|
||||||
set -eu
|
set -eu
|
||||||
export LC_ALL=C.UTF-8
|
export LC_ALL=C.UTF-8
|
||||||
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||||
trap "rm -f /tmp/chrootless.tar /tmp/root.tar" EXIT INT TERM
|
trap "rm -f /tmp/chrootless.tar /tmp/root.tar /tmp/before.md5 /tmp/before.tartv /tmp/after.md5 /tmp/after.tartv" EXIT INT TERM
|
||||||
|
|
||||||
|
rootfsmd5() {
|
||||||
|
bname="$1"
|
||||||
|
# dhclient changes /etc/resolv.conf, so it changes /etc and we thus must
|
||||||
|
# manually adjust the timestamp.
|
||||||
|
# There is a race condition here. dhclient could change /etc after touch but
|
||||||
|
# before tar packages it.
|
||||||
|
touch --date="@{{ SOURCE_DATE_EPOCH }}" /etc
|
||||||
|
(tar --one-file-system --anchored \
|
||||||
|
--exclude="./etc/resolv.conf" \
|
||||||
|
--exclude="./var/lib/dhcp/dhclient*.leases" \
|
||||||
|
--exclude="./var/log/journal/*" \
|
||||||
|
--exclude="./var/log/wtmp" \
|
||||||
|
--exclude="./var/backups" \
|
||||||
|
--exclude="./var/lib/apt" \
|
||||||
|
--exclude="./var/lib/systemd/timers" \
|
||||||
|
-C / --sort=name \
|
||||||
|
-c ./usr ./bin ./etc ./lib ./sbin ./var \
|
||||||
|
| tee /dev/fd/3 | md5sum >"/tmp/$bname.md5") 3>&1 | tar tv >"/tmp/$bname.tartv"
|
||||||
|
}
|
||||||
|
|
||||||
|
rootfsmd5 before
|
||||||
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
|
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
|
||||||
for MODE in root chrootless; do
|
for MODE in root chrootless; do
|
||||||
{{ CMD }} --mode=$MODE --variant={{ VARIANT }} \
|
{{ CMD }} --mode=$MODE --variant={{ VARIANT }} \
|
||||||
|
@ -12,3 +34,9 @@ for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
|
||||||
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
|
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
|
||||||
rm /tmp/chrootless.tar /tmp/root.tar
|
rm /tmp/chrootless.tar /tmp/root.tar
|
||||||
done
|
done
|
||||||
|
rootfsmd5 after
|
||||||
|
if ! cmp /tmp/before.md5 /tmp/after.md5; then
|
||||||
|
echo "found changes outside the chroot:" >&2
|
||||||
|
diff -u /tmp/before.tartv /tmp/after.tartv
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
|
@ -26,12 +26,7 @@ fi
|
||||||
[ "$(id -u)" -eq 0 ]
|
[ "$(id -u)" -eq 0 ]
|
||||||
[ -e "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" ]
|
[ -e "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" ]
|
||||||
|
|
||||||
# dpkg is unable to install architecture arch:all packages with a
|
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
|
||||||
# dependency on an arch:any package (perl-modules-5.34 in this case)
|
|
||||||
# inside foreign architecture chrootless chroots, because dpkg will use
|
|
||||||
# its own architecture as the native architecture, see #825385 and #1020533
|
|
||||||
# So we are not testing the installation of apt,build-essential here.
|
|
||||||
for INCLUDE in '' 'apt' 'systemd-sysv'; do
|
|
||||||
echo 1 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
|
echo 1 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
|
||||||
arch-test "$arch"
|
arch-test "$arch"
|
||||||
{{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \
|
{{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \
|
||||||
|
|
|
@ -72,6 +72,7 @@ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures="$foreign_arch
|
||||||
| grep -v "^\\./usr/lib/$native_gnu/ld-linux-aarch64\\.so\\.1$" \
|
| grep -v "^\\./usr/lib/$native_gnu/ld-linux-aarch64\\.so\\.1$" \
|
||||||
| grep -v "^\\./usr/lib/$native_gnu/libmvec\\.so\\.1$" \
|
| grep -v "^\\./usr/lib/$native_gnu/libmvec\\.so\\.1$" \
|
||||||
| grep -v "^\\./usr/lib/$native_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \
|
| grep -v "^\\./usr/lib/$native_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \
|
||||||
|
| grep -v "^\\./usr/lib/$native_gnu/engines-3/padlock\\.so$" \
|
||||||
| grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$native_arch\\.gz$" \
|
| grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$native_arch\\.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$'
|
||||||
|
|
|
@ -3,11 +3,14 @@ set -eu
|
||||||
export LC_ALL=C.UTF-8
|
export LC_ALL=C.UTF-8
|
||||||
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||||
|
|
||||||
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
trap "rm -f /tmp/debian-chroot1.tar /tmp/debian-chroot2.tar" EXIT INT TERM
|
||||||
|
|
||||||
{{ CMD }} --variant={{ VARIANT }} --verbose \
|
{{ CMD }} --variant={{ VARIANT }} \
|
||||||
|
{{ DIST }} /tmp/debian-chroot1.tar {{ MIRROR }}
|
||||||
|
|
||||||
|
{{ CMD }} --variant={{ VARIANT }} \
|
||||||
--setup-hook='echo deb {{ MIRROR }} {{ DIST }} main >> "$1"/etc/apt/sources.list' \
|
--setup-hook='echo deb {{ MIRROR }} {{ DIST }} main >> "$1"/etc/apt/sources.list' \
|
||||||
'' /tmp/debian-chroot.tar
|
'' /tmp/debian-chroot2.tar
|
||||||
|
|
||||||
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar \
|
cmp /tmp/debian-chroot1.tar /tmp/debian-chroot2.tar \
|
||||||
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar
|
|| diffoscope /tmp/debian-chroot1.tar /tmp/debian-chroot2.tar
|
||||||
|
|
Loading…
Reference in a new issue