Compare commits

...

39 commits
1.5.3 ... main

Author SHA1 Message Date
28a3a15955
release 1.5.7 2025-04-08 12:29:53 +02:00
9e7d7d0d67
README.md: add Charles Short to list of contributors 2025-04-08 06:15:56 +02:00
ff91e58219
mmdebstrap-autopkgtest-build-qemu: shfmt --binary-next-line --case-indent --indent 2 --simplify 2025-04-08 06:15:56 +02:00
38ebe6aa1f
add two FIXME comments to be solved later... 2025-04-08 06:15:55 +02:00
Jochen Sprickerhof
c7803e2e2e
m-a-b-q: add --sshkey= arg
autopkgtest-virt-qemu opens an ssh port by default. This makes it
usable.
2025-04-08 06:15:55 +02:00
fe758b8441
tests/chrootless-foreign: enable build-essential as and were fixed in dpkg 2025-04-08 06:15:55 +02:00
b04758b133
tests/as-debootstrap-unshare-wrapper: allow disabling auto-apt-proxy by setting an empty http_proxy environment variable 2025-04-08 06:15:55 +02:00
bf6aaa30ac
run_progress(): print exit code or signal on failure 2025-04-08 06:15:55 +02:00
d7107567d1
support loong64
Thanks: Helmut Grohne
2025-04-08 06:15:54 +02:00
712fdcf1ab
coverage.sh: indicate what file exceeded maximum line length 2025-04-08 06:15:54 +02:00
59e5870e7b
gpgvnoexpkeysig: check if gpgv exists and print error otherwise 2025-04-08 06:15:54 +02:00
b78afd9e92
tests/chrootless: account for more moving parts in the underlying test system 2025-04-08 06:15:54 +02:00
5761c527a0
mmdebstrap: fix formatting of last commit 2025-04-08 06:15:46 +02:00
7709ad49bb Add support for elxr
eLxr is a debian derative based on Debian 12. We use
mmdebstrap to bootstrap our edge images. This patch
allows users to use the correct mirror, and right
suite when bootstrapping eLxr.

Signed-off-by: Charles Short <charles.short@windriver.com>
2025-04-08 03:28:16 +00:00
Jochen Sprickerhof
9366f1fee7
Use format string for shell printf
Fixes:

sh: 1: printf: usage: printf format [arg ...]

due to Dir::Etc::trusted no longer being a thing since apt 2.9.24.
2025-01-29 06:26:22 +01:00
b1ba7dab3d
tests/create-foreign-tarball: also remove padlock.so on x86_64 to equalize the test cases 2025-01-13 13:30:04 +01:00
792867a390
release 1.5.6 2025-01-13 13:28:55 +01:00
917a879c4b
place DPkg::Pre-Install-Pkgs workaround into a new config file
Using APT_CONFIG will render the setting ineffective.

Debian-Bug: 
2025-01-11 09:11:04 +01:00
dc5bbb7173
tests/chrootless: make sure that nothing outside the chroot changes 2025-01-11 09:04:07 +01:00
e62f32b098
keep some 20220613 formatting until 20250105 is in Debian stable 2025-01-10 10:53:11 +01:00
fcf1c407de
tests/empty-suite: do not rely on existing ./cache/mmdebstrap-unstable-apt.tar
This is useful for running this test standalone or as part of the Debian
package autopkgtest where it is run in the optional set of tests.
2025-01-10 01:36:14 +01:00
1a17c70ffb
coverage.txt: mark empty-suite with Needs-APT-Config: true 2025-01-10 00:27:49 +01:00
b6a2a210a3
release 1.5.5 2025-01-09 22:02:01 +01:00
403ac24184
Do not run dpkg-preconfigure via DPkg::Pre-Install-Pkgs hook
Usually running dpkg-preconfigure is not a problem unless in in
chrootless mode, which apt-extracttemplates does not and can not support
because it cannot know that this is a chrootless installation.  We
always turn it off for equivalent behavior in all modes. Running
dpkg-preconfigure should not be needed as we also have set
DEBIAN_FRONTEND=noninteractive and DEBCONF_NONINTERACTIVE_SEEN=true and
should thus never see debconf prompts.

Debian-Bug: 
2025-01-09 17:08:38 +01:00
b61e785f2d
tests/multiple-include: tzdata 2024b-5 does not create /etc/timezone anymore
Debian-Bug: 
2025-01-09 17:08:01 +01:00
e7242bf0e6
tests/create-foreign-tarball: openssl 3.4.0-2 dropped padlock.so on all arches other than x86 2025-01-09 10:01:18 +01:00
44c470b24b
make_mirror.sh: prefer gpg-from-sq over gpg for trixie and later 2025-01-09 10:00:14 +01:00
e65bb53697
tests/check-against-debootstrap-dist: debootstrap 1.0.139 no longers pulls in usr-is-merged 2025-01-03 23:03:56 +01:00
60273cd9bd
tests/chrootless*: no need for merged-usr hook anymore as base-files sets up merged-/usr 2025-01-03 15:12:09 +01:00
Jochen Sprickerhof
6e75f85588
m-a-b-q: support passing args to mmdebstrap 2024-12-16 18:47:40 +01:00
Jochen Sprickerhof
cf2b178f99
Replace gpg --update-trustdb by gpg --check-trustdb
Both arguments do the same but --check-trustdb avoids user interaction
and is implemented in gpg-from-sq.

Closes: 
Suggested-by: Blair Noctis <n@sail.ng>
2024-12-03 18:31:09 +01:00
e5d86136ed
remove unused call to dpkg --print-architecture 2024-11-27 07:28:03 +01:00
6617436d70
release 1.5.4 2024-10-28 09:16:58 +01:00
e4777d8fdf
document how to build a jessie chroot tarball 2024-10-28 09:15:18 +01:00
14e2f9ea11
tests/check-against-debootstrap-dist: require iputils-ping >= 3:20240905-1 2024-10-28 09:15:00 +01:00
99f82456f3
do not generate apt sources.list entry if SUITE is empty 2024-10-28 09:13:48 +01:00
5055b1b44c
tests/check-against-debootstrap-dist: since iputils-ping 20240905 there are no extended attributes anymore 2024-10-11 18:38:04 +02:00
c82fc7e261
format shell scripts with shfmt --binary-next-line --case-indent --indent 2 --simplify 2024-10-11 18:32:57 +02:00
eca6cb314c
tests/tarfilter-idshift: use a fabricated tarball instead of real chroot
iputils-ping does not ship /bin/ping with xattrs anymore.
2024-10-11 11:16:14 +02:00
113 changed files with 2154 additions and 1854 deletions

View file

@ -1,3 +1,26 @@
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)
------------------
- do not run dpkg-preconfigure via DPkg::Pre-Install-Pkgs hook
- m-a-b-q: support passing args to mmdebstrap
1.5.4 (2024-10-28)
------------------
- do not generate apt sources.list entry if SUITE is empty
1.5.3 (2024-09-13)
------------------

View file

@ -157,12 +157,13 @@ Contributors
============
- Johannes Schauer Marin Rodrigues (main author)
- Helmut Grohne
- Jochen Sprickerhof
- Helmut Grohne
- Gioele Barabucci
- Benjamin Drung
- Josh Triplett
- Konstantin Demin
- Charles Short
- Chris Hofstaedtler
- Colin Watson
- David Kalnischkies

View file

@ -362,6 +362,21 @@ def main():
check=False,
stdout=subprocess.PIPE,
).stdout.decode()
shfmt = subprocess.run(
[
"shfmt",
"--posix",
"--binary-next-line",
"--case-indent",
"--indent",
"2",
"--simplify",
"-d",
"shared/test.sh",
],
check=False,
stdout=subprocess.PIPE,
).stdout.decode()
argv = None
match test:
case "qemu":
@ -411,9 +426,11 @@ def main():
acc_time_per_test[name].append(walltime)
print(separator, file=sys.stderr)
print(f"duration: {walltime}", file=sys.stderr)
if proc.returncode != 0 or shellcheck != "":
if proc.returncode != 0 or shellcheck != "" or shfmt != "":
if shellcheck != "":
print(shellcheck)
if shfmt != "":
print(shfmt)
failed.append(formated_test_name)
print("result: FAILURE", file=sys.stderr)
else:

View file

@ -7,14 +7,15 @@ set -eu
: "${CMD:=perl -MDevel::Cover=-silent,-nogcov ./mmdebstrap}"
case "$CMD" in
"mmdebstrap "*|mmdebstrap|*" mmdebstrap"|*" mmdebstrap "*)
MMSCRIPT="$(command -v mmdebstrap 2>/dev/null)";;
*) MMSCRIPT=./mmdebstrap;;
"mmdebstrap "* | mmdebstrap | *" mmdebstrap" | *" mmdebstrap "*)
MMSCRIPT="$(command -v mmdebstrap 2>/dev/null)"
;;
*) MMSCRIPT=./mmdebstrap ;;
esac
if [ -e "$MMSCRIPT" ]; then
TMPFILE=$(mktemp)
perltidy < "$MMSCRIPT" > "$TMPFILE"
perltidy <"$MMSCRIPT" >"$TMPFILE"
ret=0
diff -u "$MMSCRIPT" "$TMPFILE" || ret=$?
if [ "$ret" -ne 0 ]; then
@ -25,7 +26,7 @@ if [ -e "$MMSCRIPT" ]; then
rm "$TMPFILE"
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
fi
@ -41,6 +42,8 @@ done
shellcheck --exclude=SC2016 coverage.sh make_mirror.sh run_null.sh run_qemu.sh gpgvnoexpkeysig mmdebstrap-autopkgtest-build-qemu hooks/*/*.sh
shfmt --binary-next-line --case-indent --indent 2 --simplify -d coverage.sh make_mirror.sh run_null.sh run_qemu.sh mmdebstrap-autopkgtest-build-qemu gpgvnoexpkeysig
mirrordir="./shared/cache/debian"
if [ ! -e "$mirrordir" ]; then
@ -85,7 +88,7 @@ if [ -e shared/cover_db.img ]; then
# produce report inside the VM to make sure that the versions match or
# otherwise we might get:
# Can't read shared/cover_db/runs/1598213854.252.64287/cover.14 with Sereal: Sereal: Error: Bad Sereal header: Not a valid Sereal document. at offset 1 of input at srl_decoder.c line 600 at /usr/lib/x86_64-linux-gnu/perl5/5.30/Devel/Cover/DB/IO/Sereal.pm line 34, <$fh> chunk 1.
cat << END > shared/test.sh
cat <<END >shared/test.sh
cover -nogcov -report html_basic cover_db >&2
mkdir -p report
for f in common.js coverage.html cover.css css.js mmdebstrap--branch.html mmdebstrap--condition.html mmdebstrap.html mmdebstrap--subroutine.html standardista-table-sorting.js; do
@ -105,7 +108,7 @@ END
fi
# check if the wiki has to be updated with pod2markdown output
if [ "${DEBEMAIL:-}" = "josch@debian.org" ]; then
if [ "${DEBEMAIL-}" = "josch@debian.org" ]; then
bash -exc "diff -u <(curl --silent https://gitlab.mister-muffin.de/josch/mmdebstrap/wiki/raw/Home | dos2unix; echo) <(pod2markdown < mmdebstrap)" || :
fi

View file

@ -433,3 +433,6 @@ Modes: unshare
Test: zombie-reaping
Modes: unshare
Test: empty-suite
Needs-APT-Config: true

View file

@ -41,11 +41,16 @@ find_gpgv_status_fd() {
GPGSTATUSFD="$(find_gpgv_status_fd "$@")"
case $GPGSTATUSFD in
''|*[!0-9]*)
'' | *[!0-9]*)
echo "invalid --status-fd argument" >&2
exit 1
;;
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
eval 'exec gpgv "$@" '"$GPGSTATUSFD"'>&1 | sed "s/^\[GNUPG:\] EXPKEYSIG /[GNUPG:] GOODSIG /" >&'"$GPGSTATUSFD"

View file

@ -11,7 +11,7 @@ set -eu
deletecache() {
dir="$1"
echo "running deletecache $dir">&2
echo "running deletecache $dir" >&2
if [ ! -e "$dir" ]; then
return
fi
@ -48,7 +48,7 @@ deletecache() {
else
echo "does not exist: $dir/debian/dists/$dist" >&2
fi
case "$dist" in oldstable|stable)
case "$dist" in oldstable | stable)
if [ -e "$dir/debian/dists/$dist-updates" ]; then
rm --one-file-system --recursive "$dir/debian/dists/$dist-updates"
else
@ -56,7 +56,7 @@ deletecache() {
fi
;;
esac
case "$dist" in oldstable|stable)
case "$dist" in oldstable | stable)
if [ -e "$dir/debian-security/dists/$dist-security" ]; then
rm --one-file-system --recursive "$dir/debian-security/dists/$dist-security"
else
@ -161,9 +161,9 @@ update_cache() (
done
# read sources.list content from stdin
cat > "$rootdir/etc/apt/sources.list"
cat >"$rootdir/etc/apt/sources.list"
cat << END > "$rootdir/etc/apt/apt.conf"
cat <<END >"$rootdir/etc/apt/apt.conf"
Apt::Architecture "$nativearch";
Apt::Architectures "$nativearch";
Dir::Etc "$rootdir/etc/apt";
@ -177,14 +177,14 @@ Dir::Etc::TrustedParts "/etc/apt/trusted.gpg.d";
Acquire::http::Proxy "http://127.0.0.1:8080/";
END
: > "$rootdir/var/lib/dpkg/status"
: >"$rootdir/var/lib/dpkg/status"
if [ "$dist" = "$DEFAULT_DIST" ] && [ "$nativearch" = "$HOSTARCH" ] && [ "$USE_HOST_APT_CONFIG" = "yes" ]; then
# we append sources and settings instead of overwriting after
# an empty line
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*; do
[ -e "$f" ] || continue
[ -e "$rootdir/$f" ] && echo >> "$rootdir/$f"
[ -e "$rootdir/$f" ] && echo >>"$rootdir/$f"
# Filter out file:// repositories as they are added
# to each mmdebstrap call verbatim by
# debian/tests/copy_host_apt_config
@ -195,17 +195,17 @@ END
if [ "$dist" = unstable ]; then
grep -v ' file://' "$f" \
| grep -E " (unstable|experimental) " \
>> "$rootdir/$f" || :
>>"$rootdir/$f" || :
else
grep -v ' file://' "$f" \
| grep " $DEFAULT_DIST " \
>> "$rootdir/$f" || :
>>"$rootdir/$f" || :
fi
done
for f in /etc/apt/preferences.d/*; do
[ -e "$f" ] || continue
[ -e "$rootdir/$f" ] && echo >> "$rootdir/$f"
cat "$f" >> "$rootdir/$f"
[ -e "$rootdir/$f" ] && echo >>"$rootdir/$f"
cat "$f" >>"$rootdir/$f"
done
fi
@ -226,13 +226,14 @@ END
--or --field=Priority important --or --field=Priority standard \
\))
pkgs="$pkgs build-essential busybox gpg eatmydata fakechroot fakeroot"
pkgs="$pkgs build-essential busybox eatmydata fakechroot fakeroot"
# we need usr-is-merged to simulate debootstrap behaviour for all dists
# starting from Debian 12 (Bullseye)
case "$dist" in
oldstable) : ;;
*) pkgs="$pkgs usr-is-merged usrmerge" ;;
oldstable) pkgs="$pkgs gpg" ;;
stable) pkgs="$pkgs gpg usr-is-merged usrmerge" ;;
testing | unstable) pkgs="$pkgs gpg-from-sq" ;;
esac
# shellcheck disable=SC2086
@ -322,8 +323,14 @@ if [ "$FORCE_UPDATE" != "yes" ] && [ -e "$oldmirrordir/dists/$DEFAULT_DIST/InRel
http_code=$(curl --output /dev/null --silent --location --head --time-cond "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" --write-out '%{http_code}' "$mirror/dists/$DEFAULT_DIST/InRelease")
case "$http_code" in
200) ;; # need update
304) echo up-to-date; exit 0;;
*) echo "unexpected status: $http_code"; exit 1;;
304)
echo up-to-date
exit 0
;;
*)
echo "unexpected status: $http_code"
exit 1
;;
esac
fi
@ -377,8 +384,8 @@ for dist in oldstable stable testing unstable; do
echo "deb [arch=$nativearch] $mirror $dist $components" | update_cache "$dist" "$nativearch"
# we need to include the base mirror again or otherwise
# packages like build-essential will be missing
case "$dist" in oldstable|stable)
cat << END | update_cache "$dist" "$nativearch"
case "$dist" in oldstable | stable)
cat <<END | update_cache "$dist" "$nativearch"
deb [arch=$nativearch] $mirror $dist $components
deb [arch=$nativearch] $mirror $dist-updates main
deb [arch=$nativearch] $security_mirror $dist-security main
@ -386,7 +393,7 @@ END
;;
esac
done
codename=$(awk '/^Codename: / { print $2; }' < "$newmirrordir/dists/$dist/InRelease")
codename=$(awk '/^Codename: / { print $2; }' <"$newmirrordir/dists/$dist/InRelease")
ln -s "$dist" "$newmirrordir/dists/$codename"
# split the InRelease file into Release and Release.gpg not because apt
@ -453,7 +460,7 @@ if [ "$HAVE_QEMU" = "yes" ]; then
tmpdir="$(mktemp -d)"
trap 'kill "$PROXYPID" || :;cleanuptmpdir; cleanup_newcachedir' EXIT INT TERM
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-binfmt,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,squashfs-tools-ng,genext2fs,linux-image-generic,passwd,e2fsprogs,uuid-runtime
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-binfmt,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg-from-sq,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,squashfs-tools-ng,genext2fs,linux-image-generic,passwd,e2fsprogs,uuid-runtime
if [ ! -e ./mmdebstrap ]; then
pkgs="$pkgs,mmdebstrap"
fi
@ -471,7 +478,7 @@ if [ "$HAVE_QEMU" = "yes" ]; then
esac
fi
cat << END > "$tmpdir/mmdebstrap.service"
cat <<END >"$tmpdir/mmdebstrap.service"
[Unit]
Description=mmdebstrap worker script
@ -490,7 +497,7 @@ END
# filesystem that doesn't support ownership information at all and a umask that
# gives read/write access to everybody.
# https://github.com/pjcj/Devel--Cover/issues/223
cat << 'END' > "$tmpdir/worker.sh"
cat <<'END' >"$tmpdir/worker.sh"
#!/bin/sh
echo 'root:root' | chpasswd
mount -t 9p -o trans=virtio,access=any,msize=128k mmdebstrap /mnt

View file

@ -23,7 +23,7 @@
use strict;
use warnings;
our $VERSION = '1.5.3';
our $VERSION = '1.5.7';
use English;
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);
use List::Util qw(any none);
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 Term::ANSIColor;
use Socket;
@ -1963,10 +1964,7 @@ sub run_progress {
}
close($pipe);
my $fail = 0;
if ($? != 0 or $has_error) {
$fail = 1;
}
my $proc_exit = $?;
waitpid $pid2, 0;
$? == 0 or error "progress parsing failed";
@ -1977,11 +1975,29 @@ sub run_progress {
# only print failure after progress output finished or otherwise it
# might interfere with the remaining output
if ($fail) {
if ($proc_exit != 0 or $has_error) {
if ($verbosity_level >= 1) {
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;
}
@ -2870,6 +2886,9 @@ sub setup {
}
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}";
}
if (-e $options->{apttrustedparts} && !-r $options->{apttrustedparts}) {
@ -3101,6 +3120,18 @@ sub run_setup() {
# don't have a good way to figure out whether apt is using an external
# solver or not short of parsing the --aptopt options.
print $conf "pkgCacheGen::ForceEssential \",\";\n";
# Avoid running dpkg-preconfigure. This is not a problem unless in in
# chrootless mode, which apt-extracttemplates does not and can not
# support because it cannot know that this is a chrootless installation.
# We always turn it off for equivalent behavior in all modes. Running
# dpkg-preconfigure should not be needed as we also have set
# DEBIAN_FRONTEND=noninteractive and DEBCONF_NONINTERACTIVE_SEEN=true and
# should thus never see debconf prompts. See #1091442 for details.
{
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;
@ -3130,7 +3161,6 @@ sub run_setup() {
# We nevertheless always add /var/lib/dpkg/arch to make a chroot built the
# normal way bit-by-bit identical to a foreign arch chroot built in
# chrootless mode.
chomp(my $hostarch = `dpkg --print-architecture`);
if ((!-e "$options->{root}/var/lib/dpkg/arch")) {
open my $fh, '>', "$options->{root}/var/lib/dpkg/arch"
or error "cannot open /var/lib/dpkg/arch: $!";
@ -4157,6 +4187,8 @@ sub run_cleanup() {
# clean up temporary configuration file
unlink "$options->{root}/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}) {
unlink $ENV{APT_CONFIG}
@ -5114,6 +5146,7 @@ sub get_suite_by_vendor {
'ubuntu' => {},
'tanglu' => {},
'kali' => {},
'elxr' => {},
);
# pre-fill with some known values
@ -5135,6 +5168,9 @@ sub get_suite_by_vendor {
foreach my $suite ('kali-dev', 'kali-rolling', 'kali-bleeding-edge') {
$suite_by_vendor{'kali'}->{$suite} = 0;
}
foreach my $suite ('aria') {
$suite_by_vendor{'elxr'}->{$suite} = 0;
}
foreach
my $suite ('trusty', 'xenial', 'zesty', 'artful', 'bionic', 'cosmic') {
$suite_by_vendor{'ubuntu'}->{$suite} = 0;
@ -5183,6 +5219,9 @@ sub get_suite_by_vendor {
} elsif ($target eq "kali"
and not exists $suite_by_vendor{'kali'}->{$suite}) {
$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);
@ -5237,6 +5276,8 @@ sub get_keyring_by_suite {
return '/usr/share/keyrings/tanglu-archive-keyring.gpg';
} elsif ($vendor eq 'kali') {
return '/usr/share/keyrings/kali-archive-keyring.gpg';
} elsif ($vendor eq 'elxr') {
return '/usr/share/keyrings/elxr-archive-keyring.gpg';
} else {
error "unknown vendor: $vendor";
}
@ -5265,10 +5306,15 @@ sub get_sourceslist_by_suite {
my $compstr = shift;
my $suite_by_vendor = shift;
if (!$suite) {
error "get_sourceslist_by_suite cannot operate with an empty suite";
}
my @debstable = keys %{ $suite_by_vendor->{'debian'} };
my @ubuntustable = keys %{ $suite_by_vendor->{'ubuntu'} };
my @tanglustable = keys %{ $suite_by_vendor->{'tanglu'} };
my @kali = keys %{ $suite_by_vendor->{'kali'} };
my @elxr = keys %{ $suite_by_vendor->{'elxr'} };
my $mirror = 'http://deb.debian.org/debian';
my $secmirror = 'http://security.debian.org/debian-security';
@ -5306,6 +5352,8 @@ sub get_sourceslist_by_suite {
$mirror = 'http://archive.tanglu.org/tanglu';
} elsif (any { $_ eq $suite } @kali) {
$mirror = 'https://http.kali.org/kali';
} elsif (any { $_ eq $suite } @elxr) {
$mirror = 'https://mirror.elxr.dev';
}
my $sourceslist = '';
$sourceslist .= "deb$signedby $mirror $suite $compstr\n";
@ -5531,9 +5579,9 @@ sub main() {
# obtain the correct defaults for the keyring locations that apt knows
# about
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
= `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`);
my $options = {
@ -5854,7 +5902,7 @@ sub main() {
}
# 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}) {
## no critic (Variables::RequireLocalizedPunctuationVars)
$ENV{PATH} = "$ENV{PATH}:$defaultpath";
@ -6117,6 +6165,7 @@ sub main() {
armhf => 'arm',
hppa => 'hppa',
i386 => 'i386',
loong64 => 'loongarch64',
m68k => 'm68k',
mips => 'mips',
mips64 => 'mips64',
@ -6388,7 +6437,7 @@ sub main() {
}
# initialize gpg trustdb with empty one
{
0 == system(@gpgcmd, '--update-trustdb')
0 == system(@gpgcmd, '--check-trustdb')
or error "gpg failed to initialize trustdb:: $?";
}
if (!-d $options->{apttrustedparts}) {
@ -6525,6 +6574,10 @@ sub main() {
};
}
} elsif ($arg =~ /:\/\//) {
if (!$options->{suite}) {
error( "cannot create sources.list entry for URI"
. "with empty suite");
}
my $content = join ' ',
(
"deb$signedby",
@ -6580,6 +6633,9 @@ sub main() {
error "invalid mirror: $arg";
}
}
} elsif (!length($options->{suite})) {
warning
"cannot guess apt sources.list entry with empty suite name";
} else {
my $sourceslist
= get_sourceslist_by_suite($options->{suite},
@ -6785,6 +6841,7 @@ sub main() {
if (any { $_ eq $options->{format} }
('tar', 'squashfs', 'ext2', 'ext4', 'null')) {
if ($options->{format} ne 'null') {
#<<< perltidy 20220613 formatting
if (any { $_ eq $options->{variant} } ('extract', 'custom')
and $options->{mode} eq 'fakechroot') {
info "creating a tarball, squashfs, ext2 or ext4 image in"
@ -6792,6 +6849,7 @@ sub main() {
. " custom variants because there might be no tar inside the"
. " chroot";
}
#>>>
# try to fail early if target tarball or squashfs image cannot be
# opened for writing
if ($options->{target} ne '-') {
@ -6822,12 +6880,14 @@ sub main() {
# in unshare and root mode, other users than the current user need to
# access the rootfs, most prominently, the _apt user. Thus, make the
# temporary directory world readable.
#<<< perltidy 20220613 formatting
if (
any { $_ eq $options->{mode} } ('unshare', 'root')
or ($EFFECTIVE_USER_ID == 0 and $options->{mode} eq 'chrootless')
) {
chmod 0755, $options->{root} or error "cannot chmod root: $!";
}
#>>>
} elsif ($options->{format} eq 'directory') {
# user does not seem to have specified a tarball as output, thus work
# directly in the supplied directory
@ -7313,9 +7373,11 @@ sub main() {
error "cannot copy to standard output: $!";
}
} else {
#<<< perltidy 20220613 formatting
if (any { $_ eq $options->{format} }
('squashfs', 'ext2', 'ext4')
or defined $tar_compressor) {
#>>>
my @argv = ();
if ($options->{format} eq 'squashfs') {
push @argv, 'tar2sqfs',
@ -8432,8 +8494,8 @@ its core, what B<mmdebstrap> does can be put into a 14 line shell script:
Apt::Architecture "$(dpkg --print-architecture)";
Apt::Architectures "$(dpkg --print-architecture)";
Dir "$(cd "$2" && pwd)";
Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; printf "$v")";
Dir::Etc::TrustedParts "$(eval "$(apt-config shell v Dir::Etc::TrustedParts/d)"; 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 %s "$v")";
END
echo "deb http://deb.debian.org/debian/ $1 main" > "$2/etc/apt/sources.list"
APT_CONFIG="$2/apt.conf" apt-get update
@ -8650,6 +8712,16 @@ Create a tarball for use with C<sbuild --chroot-mode=unshare>:
$ mmdebstrap --variant=buildd unstable ~/.cache/sbuild/unstable-amd64.tar
Create a buildd tarball for EOL distro:
$ mmdebstrap --include=apt --variant=buildd --aptopt \
'Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"' \
--aptopt='Acquire::Check-Valid-Until "false"' \
--keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg \
--hook-dir=/usr/share/mmdebstrap/hooks/maybe-jessie-or-older \
jessie ~/.cache/sbuild/jessie-arm64.tar \
http://archive.debian.org/debian
Instead of a tarball, a squashfs image can be created:
$ mmdebstrap unstable unstable-chroot.squashfs

View file

@ -95,6 +95,12 @@ explicitly select --boot=efi, operation will fail.
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
=head1 EXAMPLES
@ -131,7 +137,7 @@ die() {
exit 1
}
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() {
echo "error: $*" 1>&2
@ -146,6 +152,7 @@ KEYRING=
RELEASE=
SIZE=25G
SCRIPT=
SSHKEY=
# consumed by setup-testbed
export AUTOPKGTEST_BUILD_QEMU=1
@ -172,6 +179,9 @@ opt_apt_proxy() {
opt_keyring() {
KEYRING="$1"
}
opt_sshkey() {
SSHKEY=$1
}
opt_mirror() {
# consumed by setup-testbed
export MIRROR="$1"
@ -202,14 +212,14 @@ positional_7() {
while test "$#" -gt 0; do
case "$1" in
--architecture=*|--arch=*|--boot=*|--keyring=*|--mirror=*|--script=*|--size=*)
--architecture=* | --arch=* | --boot=* | --keyring=* | --sshkey=* | --mirror=* | --script=* | --size=*)
optname="${1%%=*}"
"opt_${optname#--}" "${1#*=}"
;;
--apt-proxy=*)
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"
"opt_${1#--}" "$2"
shift
@ -222,6 +232,10 @@ while test "$#" -gt 0; do
--efi)
opt_boot efi
;;
--)
shift
break
;;
--*)
usage_error "unrecognized argument $1"
;;
@ -234,8 +248,8 @@ while test "$#" -gt 0; do
done
test -z "$RELEASE" -o -z "$IMAGE" && usage_error "missing positional arguments"
test "$BOOT" = efi ||
die "this tool does not support boot modes other than efi"
test "$BOOT" = efi \
|| die "this tool does not support boot modes other than efi"
case "$ARCHITECTURE" in
amd64)
@ -289,11 +303,15 @@ case $arches in
*) die "enable $ARCHITECTURE by running: sudo dpkg --add-architecture $ARCHITECTURE && sudo apt update" ;;
esac
test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed ||
die "please install dpkg-dev"
test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed \
|| die "please install dpkg-dev"
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"
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 \
|| die "please install the required packages listed above"
BOOTSTUB="/usr/lib/systemd/boot/efi/linux${EFIIMG#boot}.stub"
@ -307,8 +325,8 @@ trap cleanup EXIT INT TERM QUIT
WORKDIR=$(mktemp -d)
FAT_OFFSET_SECTORS=$((1024*2))
FAT_SIZE_SECTORS=$((1024*254))
FAT_OFFSET_SECTORS=$((1024 * 2))
FAT_SIZE_SECTORS=$((1024 * 254))
# The image is raw and not in qcow2 format because:
# - faster run-time as the "qemu-image convert" step is not needed
@ -324,10 +342,12 @@ set -- \
--mode=unshare \
--format=tar \
--variant=important \
--architecture="$ARCHITECTURE"
--architecture="$ARCHITECTURE" \
"$@"
case $MIRROR in http://snapshot.debian.org/archive/*|https://snapshot.debian.org/archive/*)
set -- "$@" --aptopt='Acquire::Check-Valid-Until "false"';;
case $MIRROR in http://snapshot.debian.org/archive/* | https://snapshot.debian.org/archive/*)
set -- "$@" --aptopt='Acquire::Check-Valid-Until "false"'
;;
esac
EXT_FEATURES=
@ -354,6 +374,14 @@ if test -n "$SCRIPT"; then
'--customize-hook=rm -f "$1/userscript"'
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 -- "$@" \
"--customize-hook=download vmlinuz '$WORKDIR/kernel'" \
"--customize-hook=download initrd.img '$WORKDIR/initrd'" \
@ -372,8 +400,8 @@ mmdebstrap "$@" | {
if test -n "$EXT_FEATURES"; then
set -- "$@" -O "$EXT_FEATURES"
fi
EXTOPTS="offset=$(( (FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))"
if test -n "${SOURCE_DATE_EPOCH:-}"; then
EXTOPTS="offset=$(((FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))"
if test -n "${SOURCE_DATE_EPOCH-}"; then
uuid="$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name "$SOURCE_DATE_EPOCH")"
set -- "$@" -U "$uuid"
EXTOPTS="$EXTOPTS,hash_seed=$uuid"
@ -383,26 +411,25 @@ mmdebstrap "$@" | {
/sbin/mke2fs "$@"
}
echo "root=LABEL=autopkgtestvm rw console=ttyS0" > "$WORKDIR/cmdline"
echo "root=LABEL=autopkgtestvm rw console=ttyS0" >"$WORKDIR/cmdline"
align_size() {
echo "$(( ($1) + ($2) - 1 - (($1) + ($2) - 1) % ($2) ))"
echo "$((($1) + ($2) - 1 - (($1) + ($2) - 1) % ($2)))"
}
alignment=$("${GNU_PREFIX}objdump" -p "$BOOTSTUB" | sed 's/^SectionAlignment\s\+\([0-9]\)/0x/;t;d')
test -z "$alignment" && die "failed to discover the alignment of the efi stub"
echo "determined efi vma alignment as $alignment"
test "$RELEASE" = jessie -a "$((alignment))" -lt "$((1024*1024))" && {
test "$RELEASE" = jessie -a "$((alignment))" -lt "$((1024 * 1024))" && {
echo "increasing efi vma alignment for jessie"
alignment=$((1024*1024))
alignment=$((1024 * 1024))
}
lastoffset=0
# shellcheck disable=SC2034 # unused variables serve documentation
lastoffset="$("${GNU_PREFIX}objdump" -h "$BOOTSTUB" |
while read -r idx name size vma lma fileoff algn behind; do
lastoffset="$("${GNU_PREFIX}objdump" -h "$BOOTSTUB" \
| while read -r idx name size vma lma fileoff algn behind; do
test -z "$behind" -a "${algn#"2**"}" != "$algn" || continue
offset=$(( 0x$vma + 0x$size ))
offset=$((0x$vma + 0x$size))
test "$offset" -gt "$lastoffset" || continue
lastoffset="$offset"
echo "$lastoffset"
@ -438,7 +465,7 @@ mcopy -i "$WORKDIR/fat" "$WORKDIR/efiimg" "::EFI/BOOT/$EFIIMG"
rm -f "$WORKDIR/efiimg"
truncate --size="+$((34*512))" "$IMAGE"
truncate --size="+$((34 * 512))" "$IMAGE"
/sbin/sfdisk "$IMAGE" <<EOF
label: gpt
unit: sectors

View file

@ -7,7 +7,7 @@ while [ "$#" -gt 0 ]; do
key="$1"
case "$key" in
SUDO)
SUDO=sudo
SUDO="sudo --preserve-env"
;;
*)
echo "Unknown argument: $key"
@ -26,13 +26,23 @@ done
# - Read fd 3 and let the group exit with that value
# - Redirect fd 4 to stdout
ret=0
{ { { {
ret=0;
( exec 3>&- 4>&-; env --chdir=./shared $SUDO sh -x ./test.sh 2>&1) || ret=$?;
echo $ret >&3;
} | tee shared/output.txt >&4;
} 3>&1;
} | { read -r xs; exit "$xs"; }
{
{
{
{
ret=0
(
exec 3>&- 4>&-
# shellcheck disable=SC2086
env --chdir=./shared $SUDO sh -x ./test.sh 2>&1
) || ret=$?
echo $ret >&3
} | tee shared/output.txt >&4
} 3>&1
} | {
read -r xs
exit "$xs"
}
} 4>&1 || ret=$?
if [ "$ret" -ne 0 ]; then
echo "test.sh failed"

View file

@ -23,7 +23,7 @@ cleanup() {
trap cleanup INT TERM EXIT
echo 1 > shared/exitstatus.txt
echo 1 >shared/exitstatus.txt
if [ -e shared/output.txt ]; then
rm shared/output.txt
fi

View file

@ -6,4 +6,7 @@ trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
--include '?narrow(?archive(^{{ DIST }}$),?essential)' \
--include apt \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
{ tar -tf /tmp/debian-chroot.tar; echo ./var/lib/apt/extended_states; } | sort | diff -u tar1.txt -
{
tar -tf /tmp/debian-chroot.tar
echo ./var/lib/apt/extended_states
} | sort | diff -u tar1.txt -

View file

@ -2,7 +2,7 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/config" EXIT INT TERM
echo 'Acquire::Languages "none";' > /tmp/config
echo 'Acquire::Languages "none";' >/tmp/config
{{ CMD }} --mode=root --variant=apt --aptopt='Acquire::Check-Valid-Until "false"' --aptopt=/tmp/config {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
printf 'Acquire::Check-Valid-Until "false";\nAcquire::Languages "none";\n' | cmp /tmp/debian-chroot/etc/apt/apt.conf.d/99mmdebstrap -
rm /tmp/debian-chroot/etc/apt/apt.conf.d/99mmdebstrap

View file

@ -28,11 +28,14 @@ fi
# https://bugs.debian.org/1031105
# https://salsa.debian.org/installer-team/debootstrap/-/merge_requests/90
AUTOPROXY=
eval "$(apt-config shell AUTOPROXY Acquire::http::Proxy-Auto-Detect)"
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
# allow an empty http_proxy variable to disable this
if [ -n "${http_proxy-}" ]; then
eval "$(apt-config shell AUTOPROXY Acquire::http::Proxy-Auto-Detect)"
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
TMP_APT_CONFIG=$(mktemp)
echo "Dir \"/dev/null\";" > "$TMP_APT_CONFIG"
echo 'Dir "/dev/null";' >"$TMP_APT_CONFIG"
chmod 644 "$TMP_APT_CONFIG"
fi
fi
$prefix {{ CMD }} --variant=custom --mode={{ MODE }} \
@ -90,8 +93,8 @@ for f in shadow shadow-; do
fi
if ! cmp /tmp/debian-debootstrap/etc/$f /tmp/debian-mm/etc/$f >&2; then
echo patching /etc/$f >&2
awk -v FS=: -v OFS=: -v SDE={{ SOURCE_DATE_EPOCH }} '{ print $1,$2,int(SDE/60/60/24),$4,$5,$6,$7,$8,$9 }' < /tmp/debian-mm/etc/$f > /tmp/debian-mm/etc/$f.bak
cat /tmp/debian-mm/etc/$f.bak > /tmp/debian-mm/etc/$f
awk -v FS=: -v OFS=: -v SDE={{ SOURCE_DATE_EPOCH }} '{ print $1,$2,int(SDE/60/60/24),$4,$5,$6,$7,$8,$9 }' </tmp/debian-mm/etc/$f >/tmp/debian-mm/etc/$f.bak
cat /tmp/debian-mm/etc/$f.bak >/tmp/debian-mm/etc/$f
rm /tmp/debian-mm/etc/$f.bak
else
echo no difference for /etc/$f >&2
@ -102,7 +105,7 @@ done
# unshared wrapper. The responsible postinst snippet was automatically added
# by dh_apparmor since isc-dhcp-client 4.4.3-P1-1.1
if [ -e /tmp/debian-debootstrap/etc/apparmor.d/local/sbin.dhclient ] && [ ! -s /tmp/debian-debootstrap/etc/apparmor.d/local/sbin.dhclient ]; then
echo /sbin/setcap > /tmp/debian-debootstrap/etc/apparmor.d/local/sbin.dhclient
echo /sbin/setcap >/tmp/debian-debootstrap/etc/apparmor.d/local/sbin.dhclient
fi
# check if the file content differs
@ -120,8 +123,8 @@ for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do
done
tar -C /tmp/debian-debootstrap --numeric-owner --xattrs --xattrs-include='*' --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/root1.tar .
tar -C /tmp/debian-mm --numeric-owner --xattrs --xattrs-include='*' --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/root2.tar .
tar --full-time --verbose -tf /tmp/root1.tar > /tmp/root1.tar.list
tar --full-time --verbose -tf /tmp/root2.tar > /tmp/root2.tar.list
tar --full-time --verbose -tf /tmp/root1.tar >/tmp/root1.tar.list
tar --full-time --verbose -tf /tmp/root2.tar >/tmp/root2.tar.list
# despite SOURCE_DATE_EPOCH and --clamp-mtime, the timestamps in the tarball
# 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

View file

@ -3,9 +3,12 @@ set -eu
export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode={{ MODE }} --variant=custom \
--include "$(tr '\n' ',' < pkglist.txt)" \
--include "$(tr '\n' ',' <pkglist.txt)" \
--aptopt='APT::Solver "aspcud"' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
{ tar -tf /tmp/debian-chroot.tar; echo ./var/lib/apt/extended_states; } | sort \
{
tar -tf /tmp/debian-chroot.tar
echo ./var/lib/apt/extended_states
} | sort \
| grep -v '^./etc/apt/apt.conf.d/99mmdebstrap$' \
| diff -u tar1.txt -

View file

@ -5,7 +5,7 @@ if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2
exit 1
fi
cat << HOSTS >> /etc/hosts
cat <<HOSTS >>/etc/hosts
127.0.0.1 deb.debian.org
127.0.0.1 security.debian.org
HOSTS

View file

@ -12,8 +12,8 @@ echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
# we cannot use useradd because passwd is not Essential:yes
{{ CMD }} --variant={{ VARIANT }} --mode={{ MODE }} \
--essential-hook='[ {{ DIST }} = oldstable ] && [ {{ VARIANT }} = - ] && echo _apt:*:100:65534::/nonexistent:/usr/sbin/nologin >> "$1"/etc/passwd || :' \
"$(if [ {{ DIST }} = oldstable ]; then echo --merged-usr; else echo --hook-dir=./hooks/merged-usr; fi)" \
"$(case {{ DIST }} in oldstable) echo --include=e2fsprogs,mount,tzdata,gcc-9-base;; stable) echo --include=e2fsprogs,mount,tzdata;; *) echo --include=base-files ;; esac )" \
"$(case {{ DIST }} in stable) echo --hook-dir=./hooks/merged-usr ;; *) echo --no-merged-usr ;; esac)" \
"$(case {{ DIST }} in oldstable) echo --include=e2fsprogs,mount,tzdata,gcc-9-base ;; stable) echo --include=e2fsprogs,mount,tzdata ;; *) echo --include=base-files ;; esac)" \
{{ DIST }} /tmp/debian-{{ DIST }}-mm.tar {{ MIRROR }}
mkdir /tmp/debian-{{ DIST }}-mm
@ -79,12 +79,12 @@ rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/cmethopt
rm /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/arch
# since we installed packages directly from the .deb files, Priorities differ
# thus we first check for equality and then remove the files
chroot /tmp/debian-{{ DIST }}-debootstrap dpkg --list > /tmp/dpkg1
chroot /tmp/debian-{{ DIST }}-mm dpkg --list > /tmp/dpkg2
chroot /tmp/debian-{{ DIST }}-debootstrap dpkg --list >/tmp/dpkg1
chroot /tmp/debian-{{ DIST }}-mm dpkg --list >/tmp/dpkg2
diff -u /tmp/dpkg1 /tmp/dpkg2 >&2
rm /tmp/dpkg1 /tmp/dpkg2
grep -v '^Priority: ' /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status > /tmp/status1
grep -v '^Priority: ' /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status > /tmp/status2
grep -v '^Priority: ' /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status >/tmp/status1
grep -v '^Priority: ' /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status >/tmp/status2
diff -u /tmp/status1 /tmp/status2 >&2
rm /tmp/status1 /tmp/status2
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status
@ -109,6 +109,7 @@ if [ "{{ VARIANT }}" = "-" ]; then
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/systemd/catalog/database
rm /tmp/debian-{{ DIST }}-mm/var/lib/systemd/catalog/database
case {{ DIST }} in oldstable | stable)
cap=$(chroot /tmp/debian-{{ DIST }}-debootstrap /sbin/getcap /bin/ping)
expected="/bin/ping cap_net_raw=ep"
if [ "$cap" != "$expected" ]; then
@ -122,7 +123,10 @@ if [ "{{ VARIANT }}" = "-" ]; then
echo "but mmdebstrap produced: $cap" >&2
exit 1
fi
;;
esac
fi
rm /tmp/debian-{{ DIST }}-mm/var/cache/apt/archives/lock
rm /tmp/debian-{{ DIST }}-mm/var/lib/apt/extended_states
rm /tmp/debian-{{ DIST }}-mm/var/lib/apt/lists/lock
@ -163,7 +167,7 @@ for log in faillog lastlog; do
if [ ! -e "$f1" ] && [ ! -e "$f2" ]; then
continue
fi
if ! cmp "$f1" "$f2" >&2;then
if ! cmp "$f1" "$f2" >&2; then
# if the files differ, make sure they are all zeroes
cmp -n "$(stat -c %s "$f1")" "$f1" /dev/zero >&2
cmp -n "$(stat -c %s "$f2")" "$f2" /dev/zero >&2
@ -177,7 +181,7 @@ if [ "{{ VARIANT }}" = "-" ]; then
# of lines in /etc/group and /etc/gshadow differs
for f in group group- gshadow gshadow-; do
for d in mm debootstrap; do
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak
sort /tmp/debian-{{ DIST }}-$d/etc/$f >/tmp/debian-{{ DIST }}-$d/etc/$f.bak
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
@ -185,7 +189,7 @@ if [ "{{ VARIANT }}" = "-" ]; then
# the order of lines in /etc/shadow and /etc/shadow- differs
for f in shadow shadow-; do
for d in mm debootstrap; do
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak
sort /tmp/debian-{{ DIST }}-$d/etc/$f >/tmp/debian-{{ DIST }}-$d/etc/$f.bak
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
@ -207,7 +211,7 @@ fi
# starting with systemd 255 upstream dropped splitusr support and depending on
# the installation order, symlink targets are prefixed with /usr or not
# See #1060000 and #1054137
case {{ DIST }} in testing|unstable)
case {{ DIST }} in testing | unstable)
for f in multi-user.target.wants/e2scrub_reap.service timers.target.wants/apt-daily-upgrade.timer timers.target.wants/apt-daily.timer timers.target.wants/e2scrub_all.timer; do
for d in mm debootstrap; do
[ -L "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f" ] || continue
@ -215,7 +219,10 @@ case {{ DIST }} in testing|unstable)
case $oldlink in
/usr/*) : ;;
/*) oldlink="/usr$oldlink" ;;
*) echo unexpected >&2; exit 1 ;;
*)
echo unexpected >&2
exit 1
;;
esac
ln -sf "$oldlink" "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f"
done
@ -237,8 +244,8 @@ for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do
done
tar -C /tmp/debian-{{ DIST }}-debootstrap --numeric-owner --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/root1.tar .
tar -C /tmp/debian-{{ DIST }}-mm --numeric-owner --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/root2.tar .
tar --full-time --verbose -tf /tmp/root1.tar > /tmp/root1.tar.list
tar --full-time --verbose -tf /tmp/root2.tar > /tmp/root2.tar.list
tar --full-time --verbose -tf /tmp/root1.tar >/tmp/root1.tar.list
tar --full-time --verbose -tf /tmp/root2.tar >/tmp/root2.tar.list
diff -u /tmp/root1.tar.list /tmp/root2.tar.list >&2
rm /tmp/root1.tar /tmp/root2.tar /tmp/root1.tar.list /tmp/root2.tar.list

View file

@ -5,7 +5,7 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
trap "rm -f /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}" EXIT INT TERM
case {{ MODE }} in unshare|fakechroot) : ;; *) exit 1;; esac
case {{ MODE }} in unshare | fakechroot) : ;; *) exit 1 ;; esac
prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then

View file

@ -2,15 +2,41 @@
set -eu
export LC_ALL=C.UTF-8
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
trap "rm -f /tmp/chrootless.tar /tmp/root.tar" EXIT INT TERM
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
# DPKG_ROOT
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 MODE in root chrootless; do
{{ CMD }} --mode=$MODE --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \
{{ CMD }} --mode=$MODE --variant={{ VARIANT }} \
${INCLUDE:+--include="$INCLUDE"} --skip=check/chrootless \
{{ DIST }} "/tmp/$MODE.tar" {{ MIRROR }}
done
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
rm /tmp/chrootless.tar /tmp/root.tar
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

View file

@ -22,22 +22,20 @@ MMTARFILTER=
[ -x /usr/bin/mmtarfilter ] && MMTARFILTER=/usr/bin/mmtarfilter
[ -x ./tarfilter ] && MMTARFILTER=./tarfilter
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
# DPKG_ROOT
# permissions drwxr-sr-x and extended attributes of ./var/log/journal/ cannot
# be preserved under fakeroot
# this applies to 'z' lines in files in /usr/lib/tmpfiles.d/
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
{{ CMD }} --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \
{{ CMD }} --variant={{ VARIANT }} \
${INCLUDE:+--include="$INCLUDE"} \
{{ DIST }} - {{ MIRROR }} \
| "$MMTARFILTER" --path-exclude="/var/log/journal" --path-exclude="/etc/credstore*" \
>/tmp/root.tar
$prefix fakeroot {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \
$prefix fakeroot {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} \
${INCLUDE:+--include="$INCLUDE"} \
{{ DIST }} - {{ MIRROR }} \
| "$MMTARFILTER" --path-exclude="/var/log/journal" --path-exclude="/etc/credstore*" \
> /tmp/chrootless.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
done

View file

@ -10,11 +10,11 @@ fi
deb2qemu() {
case "$1" in
amd64) echo x86_64;;
arm64) echo aarch64;;
armel|armhf) echo arm;;
ppc64el) echo ppc64le;;
*) echo "$1";;
amd64) echo x86_64 ;;
arm64) echo aarch64 ;;
armel | armhf) echo arm ;;
ppc64el) echo ppc64le ;;
*) echo "$1" ;;
esac
}
if [ "$(dpkg --print-architecture)" = "arm64" ]; then
@ -26,25 +26,16 @@ fi
[ "$(id -u)" -eq 0 ]
[ -e "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" ]
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
# DPKG_ROOT
#
# dpkg is unable to install architecture arch:all packages with a
# 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")"
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
echo 1 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
arch-test "$arch"
{{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \
${INCLUDE:+--include="$INCLUDE"} \
{{ DIST }} "/tmp/root.tar" {{ MIRROR }}
echo 0 > "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
echo 0 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
arch-test "$arch" && exit 1
{{ CMD }} --mode=chrootless --architecture="$arch" --variant={{ VARIANT }} \
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \
${INCLUDE:+--include="$INCLUDE"} \
--skip=check/chrootless {{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }}
# when creating a foreign architecture chroot, the tarballs are not
# bit-by-bit identical but contain a few remaining differences:
@ -53,14 +44,13 @@ for INCLUDE in '' 'apt' 'systemd-sysv'; do
# * /var/lib/dpkg/triggers -- #990712
# * /var/cache/debconf/*.dat-old -- needs investigation
for tar in root chrootless; do
<"/tmp/$tar.tar" \
./tarfilter \
./tarfilter <"/tmp/$tar.tar" \
--path-exclude=/var/cache/debconf/config.dat-old \
--path-exclude=/var/cache/debconf/templates.dat-old \
--path-exclude=/etc/ld.so.cache \
--path-exclude=/var/lib/dpkg/triggers/File \
--path-exclude=/var/lib/dpkg/triggers/ldconfig \
> "/tmp/$tar.tar.tmp"
>"/tmp/$tar.tar.tmp"
mv "/tmp/$tar.tar.tmp" "/tmp/$tar.tar"
done
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar

View file

@ -21,7 +21,7 @@ fi
--setup-hook='mkdir -p "$1"/var/cache/apt/archives/partial' \
--setup-hook='touch "$1"/var/cache/apt/archives/lock' \
--setup-hook='chmod 0640 "$1"/var/cache/apt/archives/lock' \
{{ DIST }} - {{ MIRROR }} > /tmp/orig.tar
{{ DIST }} - {{ MIRROR }} >/tmp/orig.tar
# somehow, when trying to create a tarball from the 9p mount, tar throws the
# following error: tar: ./doc-debian_6.4_all.deb: File shrank by 132942 bytes; padding with zeros
# to reproduce, try: tar --directory /mnt/cache/debian/pool/main/d/doc-debian/ --create --file - . | tar --directory /tmp/ --extract --file -
@ -32,7 +32,7 @@ cp /mnt/cache/debian/pool/main/b/busybox/busybox_*"_{{ HOSTARCH }}.deb" /mnt/cac
{{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \
--setup-hook='mkdir -p "$1"/var/cache/apt/archives/partial' \
--setup-hook='sync-in "'"$tmpdir"'" /var/cache/apt/archives/partial' \
{{ DIST }} - {{ MIRROR }} > /tmp/test1.tar
{{ DIST }} - {{ MIRROR }} >/tmp/test1.tar
cmp /tmp/orig.tar /tmp/test1.tar
{{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \
--customize-hook='touch "$1"/var/cache/apt/archives/partial' \
@ -40,5 +40,5 @@ cmp /tmp/orig.tar /tmp/test1.tar
--setup-hook='sync-in "'"$tmpdir"'" /var/cache/apt/archives/' \
--setup-hook='chmod 0755 "$1"/var/cache/apt/archives/' \
--customize-hook='find "'"$tmpdir"'" -type f -exec md5sum "{}" \; | sed "s|"'"$tmpdir"'"|$1/var/cache/apt/archives|" | md5sum --check' \
{{ DIST }} - {{ MIRROR }} > /tmp/test2.tar
{{ DIST }} - {{ MIRROR }} >/tmp/test2.tar
cmp /tmp/orig.tar /tmp/test2.tar

View file

@ -5,5 +5,5 @@ export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot" EXIT INT TERM
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
chroot /tmp/debian-chroot dpkg-query --showformat '${binary:Package}\n' --show > pkglist.txt
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort > tar1.txt
chroot /tmp/debian-chroot dpkg-query --showformat '${binary:Package}\n' --show >pkglist.txt
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort >tar1.txt

View file

@ -38,7 +38,8 @@ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures="$foreign_arch
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
# we ignore differences between architectures by ignoring some files
# and renaming others
{ tar -tf /tmp/debian-chroot.tar \
{
tar -tf /tmp/debian-chroot.tar \
| grep -v '^\./usr/bin/i386$' \
| grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./lib64$' \
@ -49,14 +50,15 @@ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures="$foreign_arch
| grep -v "^\\./usr/lib/$foreign_gnu/ld-linux-x86-64\\.so\\.2$" \
| grep -v "^\\./usr/lib/$foreign_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \
| grep -v "^\\./usr/lib/$foreign_gnu/libmvec\\.so\\.1$" \
| grep -v "^\\./usr/lib/$foreign_gnu/engines-3/padlock\\.so$" \
| grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$foreign_arch\\.gz$" \
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$' \
| sed "s/$foreign_gnu/$native_gnu/" \
| sed "s/$foreign_arch/$native_arch/";
} | sort > /tmp/tar2.txt
{ < tar1.txt \
grep -v '^\./usr/bin/i386$' \
| sed "s/$foreign_arch/$native_arch/"
} | sort >/tmp/tar2.txt
{
grep <tar1.txt -v '^\./usr/bin/i386$' \
| grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./lib32$' \
| grep -v '^\./lib64$' \
@ -70,8 +72,9 @@ $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/libmvec\\.so\\.1$" \
| 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/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$'
} | sort | diff -u - /tmp/tar2.txt >&2
rm /tmp/debian-chroot.tar /tmp/tar2.txt

View file

@ -17,7 +17,7 @@ if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != root ] && [ "{{ MODE }}" != auto ];
fi
prefix="runuser -u ${SUDO_USER:-user} --"
if [ "{{ VARIANT }}" = extract ] || [ "{{ VARIANT }}" = custom ]; then
include="$(tr '\n' ',' < pkglist.txt)"
include="$(tr '\n' ',' <pkglist.txt)"
fi
fi
$prefix {{ CMD }} --mode={{ MODE }} --include="$include" --dry-run --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}

View file

@ -15,10 +15,10 @@ fi
prefix="runuser -u ${SUDO_USER:-user} --"
# https://www.etalabs.net/sh_tricks.html
quote () { printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/" ; }
quote() { printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"; }
homedir=$($prefix sh -c 'cd && pwd')
# apt:test/integration/test-apt-key
TMPDIR_ADD="This is fü\$\$ing cràzy, \$(apt -v)\$!"
TMPDIR_ADD='This is fü$$ing cràzy, $(apt -v)$!'
$prefix mkdir "$homedir/$TMPDIR_ADD"
# make sure the unshared user can traverse into the TMPDIR
chmod 711 "$homedir"

View file

@ -2,7 +2,7 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/customize.sh" EXIT INT TERM
cat << 'SCRIPT' > /tmp/customize.sh
cat <<'SCRIPT' >/tmp/customize.sh
#!/bin/sh
chroot "$1" whoami > "$1/output2"
chroot "$1" pwd >> "$1/output2"

View file

@ -2,13 +2,13 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/sources.list /tmp/deb822.sources" EXIT INT TERM
cat << SOURCES > /tmp/deb822.sources
cat <<SOURCES >/tmp/deb822.sources
Types: deb
URIs: {{ MIRROR }}1
Suites: {{ DIST }}
Components: main
SOURCES
echo "deb {{ MIRROR }}2 {{ DIST }} main" > /tmp/sources.list
echo "deb {{ MIRROR }}2 {{ DIST }} main" >/tmp/sources.list
echo "deb {{ MIRROR }}3 {{ DIST }} main" \
| {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} \
/tmp/debian-chroot \
@ -19,13 +19,13 @@ echo "deb {{ MIRROR }}3 {{ DIST }} main" \
{{ MIRROR }}6 \
/tmp/sources.list
test ! -e /tmp/debian-chroot/etc/apt/sources.list
cat << SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0000deb822.sources -
cat <<SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0000deb822.sources -
Types: deb
URIs: {{ MIRROR }}1
Suites: {{ DIST }}
Components: main
SOURCES
cat << SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0001main.list -
cat <<SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0001main.list -
deb {{ MIRROR }}4 {{ DIST }} main
deb {{ MIRROR }}3 {{ DIST }} main
@ -40,6 +40,6 @@ tar -C /tmp/debian-chroot --one-file-system -c . \
tar -t \
| grep -v "^./etc/apt/sources.list.d/0000deb822.sources$" \
| grep -v "^./etc/apt/sources.list.d/0001main.list$" \
| grep -v "^./etc/apt/sources.list.d/0002sources.list";
printf "./etc/apt/sources.list\n";
| grep -v "^./etc/apt/sources.list.d/0002sources.list"
printf "./etc/apt/sources.list\n"
} | sort | diff -u tar1.txt -

View file

@ -2,14 +2,14 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/sources /tmp/deb822" EXIT INT TERM
cat << SOURCES > /tmp/deb822
cat <<SOURCES >/tmp/deb822
Types: deb
URIs: {{ MIRROR }}1
Suites: {{ DIST }}
Components: main
SOURCES
echo "deb {{ MIRROR }}2 {{ DIST }} main" > /tmp/sources
cat << SOURCES | {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} \
echo "deb {{ MIRROR }}2 {{ DIST }} main" >/tmp/sources
cat <<SOURCES | {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} \
/tmp/debian-chroot \
/tmp/deb822 \
- \
@ -21,13 +21,13 @@ Components: main
SOURCES
test ! -e /tmp/debian-chroot/etc/apt/sources.list
ls -lha /tmp/debian-chroot/etc/apt/sources.list.d/
cat << SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0000deb822.sources -
cat <<SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0000deb822.sources -
Types: deb
URIs: {{ MIRROR }}1
Suites: {{ DIST }}
Components: main
SOURCES
cat << SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0001main.sources -
cat <<SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list.d/0001main.sources -
Types: deb
URIs: {{ MIRROR }}3
Suites: {{ DIST }}
@ -39,6 +39,6 @@ tar -C /tmp/debian-chroot --one-file-system -c . \
tar -t \
| grep -v "^./etc/apt/sources.list.d/0000deb822.sources$" \
| grep -v "^./etc/apt/sources.list.d/0001main.sources$" \
| grep -v "^./etc/apt/sources.list.d/0002sources.list$";
printf "./etc/apt/sources.list\n";
| grep -v "^./etc/apt/sources.list.d/0002sources.list$"
printf "./etc/apt/sources.list\n"
} | sort | diff -u tar1.txt -

View file

@ -12,5 +12,5 @@ if [ "$ret" -ne 0 ]; then
cat "$tmpdir/debootstrap/debootstrap.log"
exit 1
fi
tar --sort=name --mtime=@$SOURCE_DATE_EPOCH --clamp-mtime --numeric-owner --one-file-system --xattrs -C "$tmpdir" -c . > "./cache/debian-{{ DIST }}-{{ VARIANT }}.tar"
tar --sort=name --mtime=@$SOURCE_DATE_EPOCH --clamp-mtime --numeric-owner --one-file-system --xattrs -C "$tmpdir" -c . >"./cache/debian-{{ DIST }}-{{ VARIANT }}.tar"
rm -r "$tmpdir"

View file

@ -7,7 +7,7 @@ trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
# we use variant standard in verbose mode to see the maximum number of packages
# that was chosen in case of USE_HOST_APT_CONFIG=yes
case {{ VARIANT }} in standard) : ;; *) exit 1;; esac
case {{ VARIANT }} in standard) : ;; *) exit 1 ;; esac
{{ CMD }} --variant={{ VARIANT }} --debug {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}

View file

@ -20,7 +20,7 @@ if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto
fi
# this mimics what apt does in apt-pkg/deb/dpkgpm.cc/pkgDPkgPM::StartPtyMagic()
cat > /tmp/test.c << 'END'
cat >/tmp/test.c <<'END'
#define _GNU_SOURCE
#include <stdlib.h>

View file

@ -8,6 +8,6 @@ trap "rm -f InRelease; rm -rf /tmp/debian-chroot.tar /tmp/expected" EXIT INT TER
/usr/lib/apt/apt-helper download-file "{{ MIRROR }}/dists/{{ DIST }}/InRelease" InRelease
codename=$(awk '/^Codename: / { print $2; }' InRelease)
{{ CMD }} --mode={{ MODE }} --variant=apt "$codename" /tmp/debian-chroot.tar {{ MIRROR }}
echo "deb {{ MIRROR }} $codename main" > /tmp/expected
echo "deb {{ MIRROR }} $codename main" >/tmp/expected
tar --to-stdout --extract --file /tmp/debian-chroot.tar ./etc/apt/sources.list \
| diff -u /tmp/expected -

View file

@ -2,9 +2,13 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/config" EXIT INT TERM
echo no-pager > /tmp/config
echo no-pager >/tmp/config
{{ CMD }} --mode=root --variant=apt --dpkgopt="path-exclude=/usr/share/doc/*" --dpkgopt=/tmp/config --dpkgopt="path-include=/usr/share/doc/dpkg/copyright" {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
printf 'path-exclude=/usr/share/doc/*\nno-pager\npath-include=/usr/share/doc/dpkg/copyright\n' | cmp /tmp/debian-chroot/etc/dpkg/dpkg.cfg.d/99mmdebstrap -
rm /tmp/debian-chroot/etc/dpkg/dpkg.cfg.d/99mmdebstrap
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort > tar2.txt
{ grep -v '^./usr/share/doc/.' tar1.txt; echo ./usr/share/doc/dpkg/; echo ./usr/share/doc/dpkg/copyright; } | sort | diff -u - tar2.txt
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort >tar2.txt
{
grep -v '^./usr/share/doc/.' tar1.txt
echo ./usr/share/doc/dpkg/
echo ./usr/share/doc/dpkg/copyright
} | sort | diff -u - tar2.txt

View file

@ -1,7 +1,7 @@
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
cat << SCRIPT > /tmp/checkeatmydata.sh
cat <<SCRIPT >/tmp/checkeatmydata.sh
#!/bin/sh
set -exu
cat << EOF | diff - "\$1"/usr/bin/dpkg
@ -12,18 +12,24 @@ EOF
SCRIPT
chmod +x /tmp/checkeatmydata.sh
# first four bytes: magic
elfheader="\\177ELF"
elfheader='\177ELF'
# fifth byte: bits
case "$(dpkg-architecture -qDEB_HOST_ARCH_BITS)" in
32) elfheader="$elfheader\\001";;
64) elfheader="$elfheader\\002";;
*) echo "bits not supported"; exit 1;;
32) elfheader="$elfheader\\001" ;;
64) elfheader="$elfheader\\002" ;;
*)
echo "bits not supported"
exit 1
;;
esac
# sixth byte: endian
case "$(dpkg-architecture -qDEB_HOST_ARCH_ENDIAN)" in
little) elfheader="$elfheader\\001";;
big) elfheader="$elfheader\\002";;
*) echo "endian not supported"; exit 1;;
little) elfheader="$elfheader\\001" ;;
big) elfheader="$elfheader\\002" ;;
*)
echo "endian not supported"
exit 1
;;
esac
# seventh and eigth byte: elf version (1) and abi (unset)
elfheader="$elfheader\\001\\000"
@ -34,7 +40,7 @@ elfheader="$elfheader\\001\\000"
--hook-dir=./hooks/eatmydata \
--customize-hook='printf "'"$elfheader"'" | cmp --bytes=8 - "$1"/usr/bin/dpkg' \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }}
tar -C /tmp/debian-chroot --one-file-system -c . \
tar -C /tmp/debian-chroot --one-file-system -c . \
| tar -t \
| sort \
| diff -u tar1.txt -

16
tests/empty-suite Normal file
View file

@ -0,0 +1,16 @@
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
trap "rm -f /tmp/debian-chroot1.tar /tmp/debian-chroot2.tar" EXIT INT TERM
{{ CMD }} --variant={{ VARIANT }} \
{{ DIST }} /tmp/debian-chroot1.tar {{ MIRROR }}
{{ CMD }} --variant={{ VARIANT }} \
--setup-hook='echo deb {{ MIRROR }} {{ DIST }} main >> "$1"/etc/apt/sources.list' \
'' /tmp/debian-chroot2.tar
cmp /tmp/debian-chroot1.tar /tmp/debian-chroot2.tar \
|| diffoscope /tmp/debian-chroot1.tar /tmp/debian-chroot2.tar

View file

@ -2,7 +2,7 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/essential.sh" EXIT INT TERM
cat << 'SCRIPT' > /tmp/essential.sh
cat <<'SCRIPT' >/tmp/essential.sh
#!/bin/sh
echo tzdata tzdata/Zones/Europe select Berlin | chroot "$1" debconf-set-selections
SCRIPT

View file

@ -6,7 +6,7 @@ if [ ! -e /mmdebstrap-testenv ]; then
exit 1
fi
useradd --home-dir /home/user --create-home user
awk -F: '$1!="user"' /etc/subuid > /etc/subuid.tmp
awk -F: '$1!="user"' /etc/subuid >/etc/subuid.tmp
mv /etc/subuid.tmp /etc/subuid
ret=0
runuser -u user -- {{ CMD }} --mode=unshare --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$?

View file

@ -5,7 +5,7 @@ if [ ! -e /mmdebstrap-testenv ]; then
echo "this test requires the cache directory to be mounted on /mnt and should only be run inside a container" >&2
exit 1
fi
if [ "$(id -u)" -eq 0 ] && ! id -u user > /dev/null 2>&1; then
if [ "$(id -u)" -eq 0 ] && ! id -u user >/dev/null 2>&1; then
useradd --home-dir /home/user --create-home user
fi
prefix=

View file

@ -4,12 +4,12 @@ export LC_ALL=C.UTF-8
for h in hookA hookB; do
mkdir /tmp/$h
for s in setup extract essential customize; do
cat << SCRIPT > /tmp/$h/${s}00.sh
cat <<SCRIPT >/tmp/$h/${s}00.sh
#!/bin/sh
echo $h/${s}00 >> "\$1/$s"
SCRIPT
chmod +x /tmp/$h/${s}00.sh
cat << SCRIPT > /tmp/$h/${s}01.sh
cat <<SCRIPT >/tmp/$h/${s}01.sh
echo $h/${s}01 >> "\$1/$s"
SCRIPT
chmod +x /tmp/$h/${s}01.sh

View file

@ -10,7 +10,8 @@ apt-get remove --yes qemu-user-binfmt binfmt-support qemu-user
{{ CMD }} --mode={{ MODE }} --variant=apt --architectures=i386 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
# we ignore differences between architectures by ignoring some files
# and renaming others
{ tar -tf /tmp/debian-chroot.tar \
{
tar -tf /tmp/debian-chroot.tar \
| grep -v '^\./usr/bin/i386$' \
| grep -v '^\./usr/lib/ld-linux\.so\.2$' \
| grep -v '^\./usr/lib/i386-linux-gnu/ld-linux\.so\.2$' \
@ -20,10 +21,10 @@ apt-get remove --yes qemu-user-binfmt binfmt-support qemu-user
| grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.i386\.gz$' \
| sed 's/i386-linux-gnu/x86_64-linux-gnu/' \
| sed 's/i386/amd64/' \
| sed 's/\/stubs-32.ph$/\/stubs-64.ph/';
} | sort > tar2.txt
{ < tar1.txt \
grep -v '^\./usr/bin/i386$' \
| sed 's/\/stubs-32.ph$/\/stubs-64.ph/'
} | sort >tar2.txt
{
grep <tar1.txt -v '^\./usr/bin/i386$' \
| grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./usr/lib32/$' \
| grep -v '^\./lib32$' \
@ -36,6 +37,6 @@ apt-get remove --yes qemu-user-binfmt binfmt-support qemu-user
| grep -v '^\./usr/lib/x86_64-linux-gnu/libmvec\.so\.1$' \
| grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.amd64\.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$'
} | sort | diff -u - tar2.txt >&2
rm /tmp/debian-chroot.tar

View file

@ -21,7 +21,7 @@ fi
# otherwise apt might decide to download the package with the same name and
# version from the cache instead of using the local .deb
mkdir -p /tmp/dummypkg/DEBIAN
cat << END > "/tmp/dummypkg/DEBIAN/control"
cat <<END >"/tmp/dummypkg/DEBIAN/control"
Package: dummypkg
Priority: optional
Section: oldlibs

View file

@ -27,7 +27,10 @@ export LC_ALL=C.UTF-8
--architectures="$native_arch,$foreign_arch" \
--include="libmagic-mgc:$foreign_arch" \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }}
{ echo "$native_arch"; echo "$foreign_arch"; } | cmp /tmp/debian-chroot/var/lib/dpkg/arch -
{
echo "$native_arch"
echo "$foreign_arch"
} | cmp /tmp/debian-chroot/var/lib/dpkg/arch -
rm /tmp/debian-chroot/usr/lib/file/magic.mgc
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian
rm -f /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz"

View file

@ -28,7 +28,10 @@ export LC_ALL=C.UTF-8
--architectures="$foreign_arch" \
--include="libmagic-mgc:$foreign_arch" \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }}
{ echo "$native_arch"; echo "$foreign_arch"; } | cmp /tmp/debian-chroot/var/lib/dpkg/arch -
{
echo "$native_arch"
echo "$foreign_arch"
} | cmp /tmp/debian-chroot/var/lib/dpkg/arch -
rm /tmp/debian-chroot/usr/lib/file/magic.mgc
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian
rm -f /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz"

View file

@ -15,7 +15,7 @@ pkgs=base-files,base-passwd,busybox,debianutils,dpkg,libc-bin,mawk,tar
--setup-hook='printf "root:x:0:\nmail:x:8:\nutmp:x:43:\n" > "$1/etc/group"' \
--extract-hook='chroot "$1" busybox --install -s' \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }}
echo "$pkgs" | tr ',' '\n' > /tmp/expected
echo "$pkgs" | tr ',' '\n' >/tmp/expected
chroot /tmp/debian-chroot dpkg-query -f '${binary:Package}\n' -W \
| comm -12 - /tmp/expected \
| diff -u - /tmp/expected

View file

@ -21,7 +21,7 @@ fi
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --include=doc-debian {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
tar -C /tmp/debian-chroot --owner=0 --group=0 --numeric-owner --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/debian-chroot.tar .
tar tvf /tmp/debian-chroot.tar > doc-debian.tar.list
tar tvf /tmp/debian-chroot.tar >doc-debian.tar.list
rm /tmp/debian-chroot.tar
# delete contents of doc-debian
rm /tmp/debian-chroot/usr/share/doc-base/doc-debian.debian-*

View file

@ -37,7 +37,7 @@ filter() {
}
# base for comparison without jessie-or-older hook
{{ CMD }} --mode=root --variant={{ VARIANT }} {{ DIST }} - {{ MIRROR }} > /tmp/debian-chroot-root-normal.tar
{{ CMD }} --mode=root --variant={{ VARIANT }} {{ DIST }} - {{ MIRROR }} >/tmp/debian-chroot-root-normal.tar
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --hook-dir=./hooks/jessie-or-older {{ DIST }} - {{ MIRROR }} | filter > /tmp/debian-chroot-{{ MODE }}.tar
filter < /tmp/debian-chroot-root-normal.tar | cmp - /tmp/debian-chroot-{{ MODE }}.tar
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --hook-dir=./hooks/jessie-or-older {{ DIST }} - {{ MIRROR }} | filter >/tmp/debian-chroot-{{ MODE }}.tar
filter </tmp/debian-chroot-root-normal.tar | cmp - /tmp/debian-chroot-{{ MODE }}.tar

View file

@ -7,8 +7,8 @@ trap "rm -rf /tmp/debian-chroot /tmp/log /tmp/trimmed" EXIT INT TERM
# we check the full log to also prevent debug printfs to accidentally make it into a commit
{{ CMD }} --mode=root --variant=apt --logfile=/tmp/log {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
# omit the last line which should contain the runtime
head --lines=-1 /tmp/log > /tmp/trimmed
cat << LOG | diff -u - /tmp/trimmed
head --lines=-1 /tmp/log >/tmp/trimmed
cat <<LOG | diff -u - /tmp/trimmed
I: chroot architecture {{ HOSTARCH }} is equal to the host's architecture
I: finding correct signed-by value...
I: automatically chosen format: directory

View file

@ -9,7 +9,7 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
trap "rm -f /tmp/chroot-fakechroot.tar /tmp/chroot-root.tar" EXIT INT TERM
[ "$(whoami)" = "root" ]
{{ CMD }} --mode=root --variant=apt --hook-dir=./hooks/merged-usr {{ DIST }} /tmp/chroot-root.tar {{ MIRROR }}
cat << 'SCRIPT' > script.sh
cat <<'SCRIPT' >script.sh
#!/bin/sh
set -exu
rootfs="$1"

View file

@ -2,7 +2,7 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar /tmp/sources.list" EXIT INT TERM
echo "deb {{ MIRROR }} {{ DIST }} main" > /tmp/sources.list
echo "deb {{ MIRROR }} {{ DIST }} main" >/tmp/sources.list
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar /tmp/sources.list
tar -tf /tmp/debian-chroot.tar \
| sed 's#^./etc/apt/sources.list.d/0000sources.list$#./etc/apt/sources.list#' \

View file

@ -5,7 +5,7 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
[ "$(id -u)" -eq 0 ]
[ {{ MODE }} = "root" ]
case {{ FORMAT }} in tar|squashfs|ext2|ext4) : ;; *) exit 1;; esac
case {{ FORMAT }} in tar | squashfs | ext2 | ext4) : ;; *) exit 1 ;; esac
{{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }}
# creating an ext4 image on a 9p filesystem produces different results compared

View file

@ -8,7 +8,8 @@ rm -r /tmp/debian-chroot/usr/share/doc/debian
rm -r /tmp/debian-chroot/usr/share/doc/doc-debian
rm /tmp/debian-chroot/usr/share/lintian/overrides/tzdata
rm /tmp/debian-chroot/etc/localtime
rm /tmp/debian-chroot/etc/timezone
# tzdata 2024b-5 does not create /etc/timezone anymore #822733
case {{ DIST }} in oldstable | stable) rm /tmp/debian-chroot/etc/timezone ;; esac
rm -r /tmp/debian-chroot/usr/share/doc/tzdata
rm -r /tmp/debian-chroot/usr/share/zoneinfo
for p in doc-debian tzdata; do

View file

@ -5,10 +5,10 @@ if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2
exit 1
fi
cat << HOSTS >> /etc/hosts
cat <<HOSTS >>/etc/hosts
127.0.0.1 deb.debian.org
127.0.0.1 security.debian.org
HOSTS
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} > /tmp/debian-chroot.tar
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} >/tmp/debian-chroot.tar
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar

View file

@ -7,7 +7,7 @@ if [ ! -e /mmdebstrap-testenv ]; then
fi
for f in /etc/resolv.conf /etc/hostname; do
# preserve original content
cat "$f" > "$f.bak"
cat "$f" >"$f.bak"
# in case $f is a symlink, we replace it by a real file
if [ -L "$f" ]; then
rm "$f"

View file

@ -2,5 +2,5 @@
set -eu
export LC_ALL=C.UTF-8
trap "rm /tmp/debian-chroot.tar" EXIT INT TERM
echo "deb {{ MIRROR }} {{ DIST }} main" | {{ CMD }} --mode={{ MODE }} --variant=apt > /tmp/debian-chroot.tar
echo "deb {{ MIRROR }} {{ DIST }} main" | {{ CMD }} --mode={{ MODE }} --variant=apt >/tmp/debian-chroot.tar
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

@ -9,7 +9,7 @@ export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar script.sh" EXIT INT TERM
cat << 'SCRIPT' > script.sh
cat <<'SCRIPT' >script.sh
#!/bin/sh
set -exu
rootfs="$1"

View file

@ -20,7 +20,7 @@ if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto
prefix="runuser -u ${SUDO_USER:-user} --"
fi
cat << 'SCRIPT' > /tmp/script.sh
cat <<'SCRIPT' >/tmp/script.sh
#!/bin/sh
set -eu
rootfs="$1"

View file

@ -6,7 +6,7 @@ pid=$!
while sleep 1; do [ -e hookstarted ] && break; done
rm hookstarted
# negative PID values choose the whole process group
pgid=$((-1*$(ps -p "$pid" -o pgid=)))
pgid=$((-1 * $(ps -p "$pid" -o pgid=)))
/bin/kill --signal INT -- "$pgid"
ret=0
wait $pid || ret=$?

View file

@ -17,19 +17,19 @@ fi
# test this for both unshare and root mode because the code paths creating
# entries in /dev are different depending on whether mknod is available or not
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --skip=output/dev {{ DIST }} - {{ MIRROR }} | {
tar -t;
echo ./dev/console;
echo ./dev/fd;
echo ./dev/full;
echo ./dev/null;
echo ./dev/ptmx;
echo ./dev/pts/;
echo ./dev/random;
echo ./dev/shm/;
echo ./dev/stderr;
echo ./dev/stdin;
echo ./dev/stdout;
echo ./dev/tty;
echo ./dev/urandom;
echo ./dev/zero;
tar -t
echo ./dev/console
echo ./dev/fd
echo ./dev/full
echo ./dev/null
echo ./dev/ptmx
echo ./dev/pts/
echo ./dev/random
echo ./dev/shm/
echo ./dev/stderr
echo ./dev/stdin
echo ./dev/stdout
echo ./dev/tty
echo ./dev/urandom
echo ./dev/zero
} | sort | diff -u tar1.txt -

View file

@ -18,13 +18,13 @@ fi
# entries in /dev are different depending on whether mknod is available or not
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --skip=output/mknod \
{{ DIST }} - {{ MIRROR }} | {
tar -t;
echo ./dev/console;
echo ./dev/full;
echo ./dev/null;
echo ./dev/ptmx;
echo ./dev/random;
echo ./dev/tty;
echo ./dev/urandom;
echo ./dev/zero;
tar -t
echo ./dev/console
echo ./dev/full
echo ./dev/null
echo ./dev/ptmx
echo ./dev/random
echo ./dev/tty
echo ./dev/urandom
echo ./dev/zero
} | sort | diff -u tar1.txt -

View file

@ -6,11 +6,23 @@ mkdir /tmp/root
ln -s /real /tmp/root/link
mkdir /tmp/root/real
run_testA() {
echo content > /tmp/foo
echo content >/tmp/foo
# shellcheck disable=SC2094
{ { { {{ CMD }} --hook-helper /tmp/root root setup '' 1 upload /tmp/foo "$1" < /tmp/myfifo 3>&-; echo $? >&3; printf "\\000\\000adios";
} | {{ CMD }} --hook-listener 1 3>&- >/tmp/myfifo; echo $?; } 3>&1;
} | { read -r xs1; [ "$xs1" -eq 0 ]; read -r xs2; [ "$xs2" -eq 0 ]; }
{
{
{
{{ CMD }} --hook-helper /tmp/root root setup '' 1 upload /tmp/foo "$1" </tmp/myfifo 3>&-
echo $? >&3
printf '\000\000adios'
} | {{ CMD }} --hook-listener 1 3>&- >/tmp/myfifo
echo $?
} 3>&1
} | {
read -r xs1
[ "$xs1" -eq 0 ]
read -r xs2
[ "$xs2" -eq 0 ]
}
echo content | diff -u - /tmp/root/real/foo
rm /tmp/foo
rm /tmp/root/real/foo

View file

@ -1,7 +1,7 @@
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
cat << 'SCRIPT' > /tmp/script.sh
cat <<'SCRIPT' >/tmp/script.sh
#!/bin/sh
set -eu
echo "MMDEBSTRAP_APT_CONFIG $MMDEBSTRAP_APT_CONFIG"

View file

@ -17,27 +17,27 @@ fi
[ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot"
symlinktarget=/real
[ "{{ MODE }}" = "fakechroot" ] && symlinktarget='$1/real'
echo copy-in-setup > /tmp/copy-in-setup
echo copy-in-essential > /tmp/copy-in-essential
echo copy-in-customize > /tmp/copy-in-customize
echo tar-in-setup > /tmp/tar-in-setup
echo tar-in-essential > /tmp/tar-in-essential
echo tar-in-customize > /tmp/tar-in-customize
echo copy-in-setup >/tmp/copy-in-setup
echo copy-in-essential >/tmp/copy-in-essential
echo copy-in-customize >/tmp/copy-in-customize
echo tar-in-setup >/tmp/tar-in-setup
echo tar-in-essential >/tmp/tar-in-essential
echo tar-in-customize >/tmp/tar-in-customize
tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-setup.tar tar-in-setup
tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-essential.tar tar-in-essential
tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-customize.tar tar-in-customize
rm /tmp/tar-in-setup
rm /tmp/tar-in-essential
rm /tmp/tar-in-customize
echo upload-setup > /tmp/upload-setup
echo upload-essential > /tmp/upload-essential
echo upload-customize > /tmp/upload-customize
echo upload-setup >/tmp/upload-setup
echo upload-essential >/tmp/upload-essential
echo upload-customize >/tmp/upload-customize
mkdir /tmp/sync-in-setup
mkdir /tmp/sync-in-essential
mkdir /tmp/sync-in-customize
echo sync-in-setup > /tmp/sync-in-setup/file
echo sync-in-essential > /tmp/sync-in-essential/file
echo sync-in-customize > /tmp/sync-in-customize/file
echo sync-in-setup >/tmp/sync-in-setup/file
echo sync-in-essential >/tmp/sync-in-essential/file
echo sync-in-customize >/tmp/sync-in-customize/file
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
--setup-hook='mkdir "$1/real"' \
--setup-hook='copy-in /tmp/copy-in-setup /real' \

View file

@ -5,14 +5,14 @@ if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2
exit 1
fi
cat << HOSTS >> /etc/hosts
cat <<HOSTS >>/etc/hosts
127.0.0.1 deb.debian.org
127.0.0.1 security.debian.org
HOSTS
apt-cache policy
cat /etc/apt/sources.list
{{ CMD }} --mode=root --variant=apt stable /tmp/debian-chroot
cat << SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list
cat <<SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list
deb http://deb.debian.org/debian stable main
deb http://deb.debian.org/debian stable-updates main
deb http://security.debian.org/debian-security stable-security main

View file

@ -1,58 +1,111 @@
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2
exit 1
fi
trap "rm -f /tmp/debian-chroot.tar /tmp/debian-chroot-shifted.tar /tmp/debian-chroot.txt /tmp/debian-chroot-shiftedback.tar /tmp/expected; rm -rf /tmp/debian-chroot" EXIT INT TERM
useradd --home-dir /home/user --create-home user
echo user:100000:65536 | cmp /etc/subuid -
echo user:100000:65536 | cmp /etc/subgid -
# include iputils-ping so that we can verify that tarfilter does not remove
# extended attributes
# run through tarshift no-op to create a tarball that should be bit-by-bit
# identical to a round trip through "tarfilter --idshift X" and "tarfilter --idshift -X"
runuser -u user -- {{ CMD }} --mode=unshare --variant=apt --include=iputils-ping {{ DIST }} - {{ MIRROR }} \
| ./tarfilter --idshift 0 > /tmp/debian-chroot.tar
trap "rm -f /tmp/mkpaxtar.pl /tmp/orig.tar /tmp/file /tmp/expected /tmp/filtered.tar" EXIT INT TERM
cat <<'END' >/tmp/mkpaxtar.pl
#!/usr/bin/env perl
use strict;
use warnings;
my @entries = (
# filename mode type content
['./PaxHeaders/file', oct(644), 'x', "57 SCHILY.xattr.security.capability=\x01\0\0\x02\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x0a"],
['./file', oct(644), 0, 'test'],
);
my $num_entries = 0;
foreach my $file (@entries) {
my ($fname, $mode, $type, $content) = @{$file};
my $entry = pack(
'a100 a8 a8 a8 a12 a12 A8 a1 a100 a6 a2 a32 a32 a8 a8 a155 x12',
$fname,
sprintf('%07o', $mode),
sprintf('%07o', 0), # uid
sprintf('%07o', 0), # gid
sprintf('%011o', length $content), # size
sprintf('%011o', 0), # mtime
'', # checksum
$type,
'', # linkname
"ustar", # magic
"00", # version
'', # username
'', # groupname
'', # dev major
'', # dev minor
'', # prefix
);
# compute and insert checksum
substr($entry, 148, 7)
= sprintf("%06o\0", unpack("%16C*", $entry));
print $entry;
$num_entries += 1;
if (length $content) {
print(pack 'a512', $content);
$num_entries += 1;
}
}
# https://www.gnu.org/software/tar/manual/html_node/Standard.html
#
# Physically, an archive consists of a series of file entries terminated by an
# end-of-archive entry, which consists of two 512 blocks of zero bytes. At the
# end of the archive file there are two 512-byte blocks filled with binary
# zeros as an end-of-file marker.
print(pack 'a512', '');
print(pack 'a512', '');
$num_entries += 2;
# https://www.gnu.org/software/tar/manual/html_section/tar_76.html
#
# Some devices requires that all write operations be a multiple of a certain
# size, and so, tar pads the archive out to the next record boundary.
#
# The default blocking factor is 20. With a block size of 512 bytes, we get a
# record size of 10240.
for (my $i = $num_entries ; $i < 20 ; $i++) {
print(pack 'a512', '');
}
END
MMTARFILTER=
[ -x /usr/bin/mmtarfilter ] && MMTARFILTER=/usr/bin/mmtarfilter
[ -x ./tarfilter ] && MMTARFILTER=./tarfilter
perl /tmp/mkpaxtar.pl | "$MMTARFILTER" >/tmp/orig.tar
# make sure that xattrs are set in the original tarball
mkdir /tmp/debian-chroot
tar --xattrs --xattrs-include='*' --directory /tmp/debian-chroot -xf /tmp/debian-chroot.tar ./usr/bin/ping
echo "/tmp/debian-chroot/usr/bin/ping cap_net_raw=ep" > /tmp/expected
getcap /tmp/debian-chroot/usr/bin/ping | diff -u /tmp/expected - >&2
rm /tmp/debian-chroot/usr/bin/ping
rmdir /tmp/debian-chroot/usr/bin
rmdir /tmp/debian-chroot/usr
rmdir /tmp/debian-chroot
# shift the uid/gid forward by 100000 and backward by 100000
./tarfilter --idshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
./tarfilter --idshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
# the tarball before and after the roundtrip through tarfilter should be bit
# by bit identical
cmp /tmp/debian-chroot.tar /tmp/debian-chroot-shiftedback.tar
# manually adjust uid/gid and compare "tar -t" output
tar --numeric-owner -tvf /tmp/debian-chroot.tar \
| sed 's# 42/0 # 100042/100000 #' \
| sed 's# 0/0 # 100000/100000 #' \
| sed 's# 0/5 # 100000/100005 #' \
| sed 's# 0/8 # 100000/100008 #' \
| sed 's# 0/42 # 100000/100042 #' \
| sed 's# 0/43 # 100000/100043 #' \
| sed 's# 0/50 # 100000/100050 #' \
| sed 's/ \+/ /g' \
> /tmp/debian-chroot.txt
tar --numeric-owner -tvf /tmp/debian-chroot-shifted.tar \
| sed 's/ \+/ /g' \
| diff -u /tmp/debian-chroot.txt - >&2
mkdir /tmp/debian-chroot
tar --xattrs --xattrs-include='*' --directory /tmp/debian-chroot -xf /tmp/debian-chroot-shifted.tar
echo "100000 100000" > /tmp/expected
stat --format="%u %g" /tmp/debian-chroot/usr/bin/ping | diff -u /tmp/expected - >&2
echo "/tmp/debian-chroot/usr/bin/ping cap_net_raw=ep" > /tmp/expected
getcap /tmp/debian-chroot/usr/bin/ping | diff -u /tmp/expected - >&2
echo "0 0" > /tmp/expected
runuser -u user -- {{ CMD }} --unshare-helper /usr/sbin/chroot /tmp/debian-chroot stat --format="%u %g" /usr/bin/ping \
| diff -u /tmp/expected - >&2
echo "/usr/bin/ping cap_net_raw=ep" > /tmp/expected
runuser -u user -- {{ CMD }} --unshare-helper /usr/sbin/chroot /tmp/debian-chroot getcap /usr/bin/ping \
| diff -u /tmp/expected - >&2
tar --xattrs --xattrs-include='*' --directory /tmp/ -xf /tmp/orig.tar ./file
echo "/tmp/file cap_net_raw=ep" >/tmp/expected
getcap /tmp/file | diff -u /tmp/expected - >&2
# make sure that the file content is as expected
printf test | diff -u /tmp/file - >&2
# make sure that uid/gid are as expected in the original tarball
echo "0 0 644" >/tmp/expected
stat --format="%u %g %a" /tmp/file | diff -u /tmp/expected - >&2
rm /tmp/file
# tarball must be bit by-bit-identical after round-trip
"$MMTARFILTER" --idshift 0 </tmp/orig.tar >/tmp/filtered.tar
cmp /tmp/orig.tar /tmp/filtered.tar
# now shift uid/gid
"$MMTARFILTER" --idshift 100000 </tmp/orig.tar >/tmp/filtered.tar
# make sure that uid/gid are as expected in the filtered tarball
tar --xattrs --xattrs-include='*' --directory /tmp/ -xf /tmp/filtered.tar ./file
echo "100000 100000 644" >/tmp/expected
stat --format="%u %g %a" /tmp/file | diff -u /tmp/expected - >&2
rm /tmp/file
# now shift uid/gid back to create a round-trip
"$MMTARFILTER" --idshift -100000 </tmp/filtered.tar >/tmp/filtered2.tar
# the result must be identical to the original and will thus also include the
# correct xattr information
cmp /tmp/orig.tar /tmp/filtered2.tar

View file

@ -9,7 +9,7 @@ set -eu
export LC_ALL=C.UTF-8
[ "$(whoami)" = "root" ]
trap "rm -f /tmp/debian-chroot.tar script.sh" EXIT INT TERM
cat << 'SCRIPT' > script.sh
cat <<'SCRIPT' >script.sh
#!/bin/sh
set -eu
rootfs="$1"

View file

@ -23,7 +23,7 @@ fi
# otherwise apt might decide to download the package with the same name and
# version from the cache instead of using the local .deb
mkdir -p /tmp/dummypkg/DEBIAN
cat << END > "/tmp/dummypkg/DEBIAN/control"
cat <<END >"/tmp/dummypkg/DEBIAN/control"
Package: dummypkg
Priority: optional
Section: oldlibs

View file

@ -7,7 +7,7 @@ trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
# we use variant standard in verbose mode to see the maximum number of packages
# that was chosen in case of USE_HOST_APT_CONFIG=yes
case {{ VARIANT }} in standard) : ;; *) exit 1;; esac
case {{ VARIANT }} in standard) : ;; *) exit 1 ;; esac
{{ CMD }} --variant={{ VARIANT }} --verbose {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}

View file

@ -8,7 +8,8 @@ fi
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
rm /etc/resolv.conf /etc/hostname
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
{ tar -tf /tmp/debian-chroot.tar;
printf "./etc/hostname\n";
printf "./etc/resolv.conf\n";
{
tar -tf /tmp/debian-chroot.tar
printf "./etc/hostname\n"
printf "./etc/resolv.conf\n"
} | sort | diff -u tar1.txt -

View file

@ -28,11 +28,10 @@ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
--customize-hook='chroot "$1" sh -c "sleep 1m > /dev/null" &' \
{{ DIST }} - {{ MIRROR }} \
| "$MMTARFILTER" --path-exclude="/dev" \
> /tmp/debian-chroot.tar
>/tmp/debian-chroot.tar
origfilter() {
< ./cache/mmdebstrap-{{ DIST }}-apt.tar \
"$MMTARFILTER" --path-exclude="/dev/*" --path-exclude="/dev"
"$MMTARFILTER" <./cache/mmdebstrap-{{ DIST }}-apt.tar --path-exclude="/dev/*" --path-exclude="/dev"
}
origfilter | cmp - /tmp/debian-chroot.tar \