Compare commits

...

89 commits
1.4.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
395ee60a7f
release 1.5.3 2024-09-13 07:35:10 +02:00
1a8f2537ac
explain --pax-option with comment 2024-09-13 01:19:17 +02:00
0f5d935941
more sanity checks of target directory 2024-09-13 01:19:02 +02:00
dbce1ee27b
fix typo 2024-09-13 01:18:20 +02:00
6e4ed4a049
add --skip=cleanup/reproducible/machine-id 2024-09-13 01:17:52 +02:00
87b9b385b3
tarfilter: do not rely on paths being absolute (starting with a single slash) 2024-09-13 01:16:31 +02:00
acf036fa79
qemu-user now includes the static binary and qemu-user-static will be dropped in the long-term 2024-09-13 01:13:04 +02:00
d9c04338f8
support chrootless hurd-i386
$ mmdebstrap --variant=apt --include=passwd,debian-ports-archive-keyring,mmdebstrap,sysvinit-core,sysv-rc \
    --customize-hook='chroot "$1" mmdebstrap --mode=chrootless --arch=hurd-i386 --include=sysvinit-core,sysv-rc,debian-ports-archive-keyring,gnumach-image-1-486 --customize-hook="passwd --root=\"\$1\" --delete root" --variant=apt unstable /tmp/chroot.tar "deb http://ftp.ports.debian.org/debian-ports/ unstable main" "deb http://ftp.ports.debian.org/debian-ports/ unreleased main"' \
    --customize-hook='copy-out /tmp/chroot.tar .' unstable /dev/null
$ /sbin/mkfs.ext2 -q -F -o hurd -I 128 -b 4096 -d chroot.tar hurd.ext2 204800
$ qemu-system-i386 -nographic -net user,hostfwd=tcp:127.0.0.1:2222-:22 \
    -net nic,model=e1000 -m 1G -kernel gnumach-1.8-486-up \
    -append 'root=device:hd0 console=com0' --initrd './ext2fs.static --multiboot-command-line=${kernel-command-line} --host-priv-port=${host-port} --device-master-port=${device-port} --exec-server-task=${exec-task} -T typed ${root} $(task-create) $(task-resume),./exec.static $(exec-task=task-create)' \
    -drive file=hurd.ext2,format=raw
2024-08-27 01:15:00 +02:00
d0568a2b9e
Wait for (reap) potential zombies and otherwise long-running background processes
Otherwise they might hog resources like /dev/null which can then not be
unmounted resulting in their mountpoints (the regular files) not being
removable and then the removal of device nodes in run_cleanup (if
mmdebstrap is run with --skip=output/dev) will fail.

Another potential solution would be to run each hook and apt invocation
in its own process namespace but this would require to remount /proc and
this in turn would require a new mount namespace as well but we'd like
to keep the mount namespace across multiple hooks...
2024-08-18 22:07:52 +02:00
Jochen Sprickerhof
98b3c7f2cd
m-a-b-q: replace test_installed by dpkg-checkbuilddeps 2024-07-12 09:49:39 +02:00
8e2f62d08c
release 1.5.2 2024-06-26 12:52:56 +02:00
8130f1cef0
README.md: add new authors 2024-06-26 07:36:40 +02:00
6262c1921c
tests/check-against-debootstrap-dist: allow for different installation order of passwd and systemd 2024-06-26 07:35:26 +02:00
500b0d2512
mmdebstrap: fix perltidy formatting 2024-06-26 07:35:26 +02:00
Chris Hofstaedtler
37678c4fb5
tests/check-against-debootstrap-dist: allow /var/log/{faillog,lastlog} to be absent 2024-06-26 07:35:19 +02:00
134330d786
mmdebstrap-autopkgtest-build-qemu: pipe tarball to mke2fs and make bit-by-bit reproducible 2024-06-26 07:35:19 +02:00
Colin Watson
bda207af63
mmdebstrap-autopkgtest-build-qemu: selects wrong kernel package for armhf
Package: mmdebstrap
Version: 1.5.0-2
Severity: normal
Tags: patch

With --architecture=armhf, mmdebstrap-autopkgtest-build-qemu fails with
"E: Unable to locate package linux-image-armhf".  The following patch
fixes that.

i386 has a similar problem, and I included a fix for that in this patch
too, though I haven't tested that.

After this, armhf still fails with:

  arm-linux-gnueabihf-objdump: /usr/lib/systemd/boot/efi/linuxarm.efi.stub: file format not recognized
  failed to discover the alignment of the efi stub

... but that's a separate problem.
2024-06-17 13:57:21 +02:00
d0c30c70bd
tests/debootstrap: dump $tmpdir/debootstrap/debootstrap.log on failure 2024-06-12 11:41:17 +02:00
1a4bb39aad
check if libarchive is available for ext4 format 2024-06-12 11:40:39 +02:00
dfeb21cfe5
tests/empty-sources.list: only write out /etc/apt/sources.list if it doesn't exist yet
In the mmdebstrap autpkgtest, debian/tests/sourcesfilter will write out
/etc/apt/sources.list before the test's setup-hook is run. Thus, the
test's setup-hook will overwrite the contents of the sources.list that
debian/tests/sourcesfilter set up, which will end up pulling in the
wrong packages.

Thus, only write out our own /etc/apt/sources.list if it does not yet
exist. If it does exist, nothing needs to be done.
2024-06-11 15:49:48 +02:00
Jochen Sprickerhof
d0add325d3
Mark oldstable as bullseye_or_later 2024-06-11 15:49:48 +02:00
d4149bb4db
coverage.sh: add missing newline at end of curl output 2024-06-11 15:49:48 +02:00
61509691a8
tests: base-files now ships merged-/usr symlinks 2024-06-11 15:49:48 +02:00
3969727cc0
tests: bug got fixed 2024-06-11 15:49:48 +02:00
6818d2ed40
release 1.5.1 2024-06-03 10:46:29 +02:00
9f8172bbc0
Switch variant apt from 'apt-get dist-upgrade' to apt patterns
The dist-upgrade method will fail to install essential packages but
still exit successfully without reporting an error, see 
2024-06-03 08:04:03 +02:00
767e8a8bfb
run_qemu.sh: allow setting MMDEBSTRAP_TESTS_DEBUG and add auto-detection for amlogic a311d bananapi 2024-06-03 08:04:03 +02:00
abc66c5dc7
increase additional number of blocks from 1.1 to 1.2 times the computed number 2024-06-03 08:04:02 +02:00
f3ea5f2676
add flock on temporary directory in /tmp
Since systemd 256~rc3-3, /tmp is regularly cleaned up, removing files
older than 10 days. Since a rootfs contains files with timestamps
potentially much older than that, we exclude our temporary directory by
adding an exclusive lock on it which will stop systemd-tmpfiles from
cleaning up anything in it.

Thanks: Peter Pentchev <roam@ringlet.net>
2024-06-03 08:03:04 +02:00
5f491f2955
make_mirror.sh: force systemd to not mount /tmp as tmpfs
Since systemd 256~rc3-3, /tmp is mounted as tmpfs by default. This
breaks our tests because /tmp is mounted with nodev which makes it
impossible for debootstrap to mknod.
2024-06-02 08:44:28 +02:00
821c2e1328
In unshare mode, make all mounts private recursively
This emulates what unshare(1) does by default or by passing
--propagation=private explicitly. Mounting and unmounting filesystems
will affect mounts outside the namespace which are marked as shared (see
last column of `findmnt -o+PROPAGATION`). Since mmdebstrap's goal is to
isolate the mounts in the new namespace, we perform the equivalent of

    mount(NULL, "/", MS_REC | MS_PRIVATE, NULL);

from util-linux/sys-utils/unshare.c:set_propagation() which is in shell:

    mount --make-rprivate /

See mount_namespaces(7) for details. Without setting this, unmounting
/sys (and its sub-mounts) in unshare mode as root user will also unmount
the sub-mounts of /sys on the outside of the namespace. This breaks
tests/unshare-as-root-user which will fail to shut down with the following
errors in the log:

[FAILED] Failed unmounting mnt.mount - /mnt.
[FAILED] Failed unmounting run-lock.mount - Legacy Locks Directory /run/lock.
[...]
[  OK  ] Reached target poweroff.target - System Power Off.

Afterwards it will stall indefinitely. Stopping mmdebstrap from messing
with the /sys mounts on the outside stops this behaviour and allows to
cleanly shut down the virtual machine.

Thanks: Helmut Grohne
2024-06-02 08:11:51 +02:00
84f80673f4
Revert "attempt diagnosing skip-tar-in-mknod failure 'file changed as we read it' using auditd"
This reverts commit 726fc38d1d.
2024-05-15 00:23:56 +02:00
e3eafd0009
release 1.5.0 2024-05-14 07:39:00 +02:00
eed6a86480
mmdebstrap-autopkgtest-build-qemu: document https://github.com/util-linux/util-linux/issues/2981 2024-05-14 07:37:19 +02:00
5a06c67aaa
document that --cache-dir is also not a supported debootstrap option 2024-05-14 07:32:28 +02:00
d26afd110f
add more docs to the tar-out special hook 2024-05-14 07:32:09 +02:00
4ad8245a14
tests/missing-dev-sys-proc-inside-the-chroot: work around for bug 2024-05-14 07:31:27 +02:00
409686048b
add --format=ext4 2024-05-12 18:38:47 +02:00
Jochen Sprickerhof
4a294f05bd
Add test if dpkg-dev is installed
Needed for dpkg-architecture.
2024-04-15 14:50:54 +02:00
Jochen Sprickerhof
8c0ddc3266
mmdebstrap-autopkgtest-build-qemu: use mount --no-mtab
Otherwise it fails with:

umount: /tmp/mmdebstrap.Tw9G7ZLL4J/mnt: filesystem was unmounted, but failed to update userspace mount table.
E: setup failed: E: command failed: umount --lazy "$1/mnt"

Also umount mnt/dev.
2024-04-15 14:18:11 +02:00
1e68ffd2c4
tests: changelog.Debian.$foreign_arch.gz files are not always present 2024-03-27 05:50:51 +01:00
726fc38d1d
attempt diagnosing skip-tar-in-mknod failure 'file changed as we read it' using auditd 2024-03-27 05:49:46 +01:00
ae09a50f9d
document unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps trick 2024-03-23 22:50:34 +01:00
9726836ac4
mmdebstrap-autopkgtest-build-qemu: add documentation of some unshare magic 2024-03-23 22:49:27 +01:00
cdf6959a41
make_mirror.sh: retry apt with verbose output 2024-03-23 22:38:30 +01:00
1cf0d87a60
hooks/file-mirror-automount/setup00.sh: prefix warning with W: 2024-03-23 22:37:26 +01:00
0973de1530
hooks/copy-host-apt-sources-and-preferences/setup00.sh: document with comment on top 2024-03-23 22:36:48 +01:00
d883fa13bb
hooks/maybe-merged-usr: prepare for the time when usr-is-merged exists only as a virtual package 2024-02-27 00:32:45 +01:00
Max-Julian Pogner
286cecc21b
follow adduser's changes in example: --gecos => --comment
Considered References:
https://www.debian.org/releases/bookworm/amd64/release-notes/ch-information.en.html#adduser-changes
/usr/share/doc/adduser/NEWS.Debian.gz (from adduser v3.134)
https://manpages.debian.org/bookworm/adduser/adduser.8.en.html
2024-02-08 12:30:17 +01:00
113532b3e1
refactor worker function to remove code duplication
Thanks: Guillem Jover <guillem@debian.org>
2024-02-02 23:13:13 +01:00
120 changed files with 3884 additions and 2232 deletions
CHANGELOG.mdREADME.mdcoverage.pycoverage.shcoverage.txtgpgvnoexpkeysig
hooks
copy-host-apt-sources-and-preferences
file-mirror-automount
maybe-merged-usr
make_mirror.shmmdebstrapmmdebstrap-autopkgtest-build-qemurun_null.shrun_qemu.shtarfilter
tests
apt-patternsapt-patterns-customaptoptarm64-without-qemu-supportas-debootstrap-unshare-wrapperascii-armored-keysaspcud-apt-solverauto-mode-as-normal-userauto-mode-without-unshare-capabilitiesautomatic-mirror-from-suitecheck-against-debootstrap-distcheck-for-bit-by-bit-identical-format-outputchrootlesschrootless-fakerootchrootless-foreigncompare-output-with-pre-seeded-var-cache-apt-archivescopy-mirrorcreate-directorycreate-directory-dry-runcreate-foreign-tarballcreate-gzip-compressed-tarballcreate-tarball-dry-runcreate-tarball-with-tmp-mounted-nodevcustom-tmpdircustomize-hookcwd-directory-not-accessible-by-unshared-userdeb822-1-2deb822-2-2debootstrapdebugdev-ptmxdirectory-ending-in-tardist-using-codenamedpkgopteatmydata-via-hook-dirempty-sources.listempty-suiteerror-if-stdout-is-ttyessential-hookfail-installing-to-existing-filefail-installing-to-non-empty-lost-foundfail-installing-to-non-empty-target-directoryfail-installing-to-rootfail-with-missing-lz4fail-with-path-with-quotesfail-without-etc-subuidfail-without-username-in-etc-subuidfailing-customize-hookfile-mirrorfile-mirror-automount-hookhook-directoryi386-which-can-be-executed-without-qemuincludeinclude-deb-fileinclude-foreign-libmagic-mgcinclude-foreign-libmagic-mgc-with-multiple-arch-optionsinstall-busybox-based-sub-essential-systeminstall-doc-debianinstall-doc-debian-and-output-tarballinstall-doc-debian-and-test-hooksinstall-libmagic-mgc-on-foreigninvalid-mirrorjessie-or-olderkeyringkeyring-overwriteslogfilemerged-fakechroot-inside-unmerged-chrootmirror-is-real-filemissing-dev-sys-proc-inside-the-chrootmissing-device-nodes-outside-the-chrootmmdebstrapmount-is-missingmultiple-includeno-sbin-in-pathnot-having-to-install-apt-in-include-because-a-hook-did-it-beforepass-distribution-but-implicitly-write-to-stdoutpivot_rootpreserve-mode-of-etc-resolv-conf-and-etc-hostnameread-from-stdin-write-to-stdoutremove-start-stop-daemon-and-policy-rc-d-in-hookroot-mode-inside-chrootroot-mode-inside-unshare-chrootroot-without-cap-sys-admin

View file

@ -1,3 +1,50 @@
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)
------------------
- tidy up any zombie processes
- chrootless hurd-i386
- add --skip=cleanup/reproducible/machine-id
- m-a-b-q: replace test_installed by dpkg-checkbuilddeps
1.5.2 (2024-06-26)
------------------
- mmdebstrap-autopkgtest-build-qemu produces bit-by-bit reproducible output
1.5.1 (2024-06-03)
------------------
- in root and unshare mode, run 'mount --make-rprivate /' before bind-mounting
- switch apt variant from using 'apt-get dist-upgrade' to apt patterns
1.5.0 (2024-05-14)
------------------
- add --format=ext4
1.4.3 (2024-02-01) 1.4.3 (2024-02-01)
------------------ ------------------

View file

@ -157,17 +157,21 @@ Contributors
============ ============
- Johannes Schauer Marin Rodrigues (main author) - Johannes Schauer Marin Rodrigues (main author)
- Jochen Sprickerhof
- Helmut Grohne - Helmut Grohne
- Gioele Barabucci - Gioele Barabucci
- Benjamin Drung - Benjamin Drung
- Jochen Sprickerhof
- Josh Triplett - Josh Triplett
- Konstantin Demin - Konstantin Demin
- Charles Short
- Chris Hofstaedtler
- Colin Watson
- David Kalnischkies - David Kalnischkies
- Emilio Pozuelo Monfort - Emilio Pozuelo Monfort
- Francesco Poli - Francesco Poli
- Jakub Wilk - Jakub Wilk
- Joe Groocock - Joe Groocock
- Max-Julian Pogner
- Nicolas Vigier - Nicolas Vigier
- Raul Tambre - Raul Tambre
- Steve Dodd - Steve Dodd

View file

@ -34,7 +34,7 @@ all_variants = [
"standard", "standard",
] ]
default_format = "auto" default_format = "auto"
all_formats = ["auto", "directory", "tar", "squashfs", "ext2", "null"] all_formats = ["auto", "directory", "tar", "squashfs", "ext2", "ext4", "null"]
mirror = os.getenv("mirror", "http://127.0.0.1/debian") mirror = os.getenv("mirror", "http://127.0.0.1/debian")
hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip() hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip()
@ -362,6 +362,21 @@ def main():
check=False, check=False,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
).stdout.decode() ).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 argv = None
match test: match test:
case "qemu": case "qemu":
@ -411,9 +426,11 @@ def main():
acc_time_per_test[name].append(walltime) acc_time_per_test[name].append(walltime)
print(separator, file=sys.stderr) print(separator, file=sys.stderr)
print(f"duration: {walltime}", 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 != "": if shellcheck != "":
print(shellcheck) print(shellcheck)
if shfmt != "":
print(shfmt)
failed.append(formated_test_name) failed.append(formated_test_name)
print("result: FAILURE", file=sys.stderr) print("result: FAILURE", file=sys.stderr)
else: else:

View file

@ -7,45 +7,48 @@ set -eu
: "${CMD:=perl -MDevel::Cover=-silent,-nogcov ./mmdebstrap}" : "${CMD:=perl -MDevel::Cover=-silent,-nogcov ./mmdebstrap}"
case "$CMD" in case "$CMD" in
"mmdebstrap "*|mmdebstrap|*" mmdebstrap"|*" mmdebstrap "*) "mmdebstrap "* | mmdebstrap | *" mmdebstrap" | *" mmdebstrap "*)
MMSCRIPT="$(command -v mmdebstrap 2>/dev/null)";; MMSCRIPT="$(command -v mmdebstrap 2>/dev/null)"
*) MMSCRIPT=./mmdebstrap;; ;;
*) MMSCRIPT=./mmdebstrap ;;
esac esac
if [ -e "$MMSCRIPT" ]; then if [ -e "$MMSCRIPT" ]; then
TMPFILE=$(mktemp) TMPFILE=$(mktemp)
perltidy < "$MMSCRIPT" > "$TMPFILE" perltidy <"$MMSCRIPT" >"$TMPFILE"
ret=0 ret=0
diff -u "$MMSCRIPT" "$TMPFILE" || ret=$? diff -u "$MMSCRIPT" "$TMPFILE" || ret=$?
if [ "$ret" -ne 0 ]; then if [ "$ret" -ne 0 ]; then
echo "perltidy failed" >&2 echo "perltidy failed" >&2
rm "$TMPFILE" rm "$TMPFILE"
exit 1 exit 1
fi fi
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
perlcritic --severity 4 --verbose 8 "$MMSCRIPT" perlcritic --severity 4 --verbose 8 "$MMSCRIPT"
pod2man "$MMSCRIPT" >/dev/null pod2man "$MMSCRIPT" >/dev/null
fi fi
for f in tarfilter coverage.py caching_proxy.py; do for f in tarfilter coverage.py caching_proxy.py; do
[ -e "./$f" ] || continue [ -e "./$f" ] || continue
black --check "./$f" black --check "./$f"
done done
shellcheck --exclude=SC2016 coverage.sh make_mirror.sh run_null.sh run_qemu.sh gpgvnoexpkeysig mmdebstrap-autopkgtest-build-qemu hooks/*/*.sh 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" mirrordir="./shared/cache/debian"
if [ ! -e "$mirrordir" ]; then if [ ! -e "$mirrordir" ]; then
echo "run ./make_mirror.sh before running $0" >&2 echo "run ./make_mirror.sh before running $0" >&2
exit 1 exit 1
fi fi
# we use -f because the file might not exist # we use -f because the file might not exist
@ -56,14 +59,14 @@ rm -f shared/cover_db.img
: "${RUN_MA_SAME_TESTS:=yes}" : "${RUN_MA_SAME_TESTS:=yes}"
if [ "$HAVE_QEMU" = "yes" ]; then if [ "$HAVE_QEMU" = "yes" ]; then
# prepare image for cover_db # prepare image for cover_db
fallocate -l 64M shared/cover_db.img fallocate -l 64M shared/cover_db.img
/usr/sbin/mkfs.vfat shared/cover_db.img /usr/sbin/mkfs.vfat shared/cover_db.img
if [ ! -e "./shared/cache/debian-$DEFAULT_DIST.ext4" ]; then if [ ! -e "./shared/cache/debian-$DEFAULT_DIST.ext4" ]; then
echo "./shared/cache/debian-$DEFAULT_DIST.ext4 does not exist" >&2 echo "./shared/cache/debian-$DEFAULT_DIST.ext4 does not exist" >&2
exit 1 exit 1
fi fi
fi fi
# choose the timestamp of the unstable Release file, so that we get # choose the timestamp of the unstable Release file, so that we get
@ -82,10 +85,10 @@ export HAVE_QEMU HAVE_BINFMT RUN_MA_SAME_TESTS DEFAULT_DIST SOURCE_DATE_EPOCH CM
./coverage.py "$@" ./coverage.py "$@"
if [ -e shared/cover_db.img ]; then if [ -e shared/cover_db.img ]; then
# produce report inside the VM to make sure that the versions match or # produce report inside the VM to make sure that the versions match or
# otherwise we might get: # 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. # 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 cover -nogcov -report html_basic cover_db >&2
mkdir -p report 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 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
@ -93,20 +96,20 @@ for f in common.js coverage.html cover.css css.js mmdebstrap--branch.html mmdebs
done done
cover -delete cover_db >&2 cover -delete cover_db >&2
END END
if [ "$HAVE_QEMU" = "yes" ]; then if [ "$HAVE_QEMU" = "yes" ]; then
./run_qemu.sh ./run_qemu.sh
else else
./run_null.sh ./run_null.sh
fi fi
echo echo
echo "open file://$(pwd)/shared/report/coverage.html in a browser" echo "open file://$(pwd)/shared/report/coverage.html in a browser"
echo echo
fi fi
# check if the wiki has to be updated with pod2markdown output # 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) <(pod2markdown < mmdebstrap)" || : bash -exc "diff -u <(curl --silent https://gitlab.mister-muffin.de/josch/mmdebstrap/wiki/raw/Home | dos2unix; echo) <(pod2markdown < mmdebstrap)" || :
fi fi
rm -f shared/test.sh shared/tar1.txt shared/tar2.txt shared/pkglist.txt shared/doc-debian.tar.list shared/mmdebstrap shared/tarfilter shared/proxysolver rm -f shared/test.sh shared/tar1.txt shared/tar2.txt shared/pkglist.txt shared/doc-debian.tar.list shared/mmdebstrap shared/tarfilter shared/proxysolver

View file

@ -59,21 +59,21 @@ Needs-QEMU: true
Test: mmdebstrap Test: mmdebstrap
Needs-Root: true Needs-Root: true
Modes: root Modes: root
Formats: tar squashfs ext2 Formats: tar squashfs ext2 ext4
Variants: essential apt minbase buildd - standard Variants: essential apt minbase buildd - standard
Skip-If: Skip-If:
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558 variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
mode == "fakechroot" and variant in ["-", "standard"] # no extended attributes mode == "fakechroot" and variant in ["-", "standard"] # no extended attributes
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276 variant == "standard" and dist in ["oldstable", "stable"] and hostarch in ["armel", "armhf", "mipsel"] # #1031276
Test: check-for-bit-by-bit-identical-format-output Test: check-for-bit-by-bit-identical-format-output
Modes: unshare fakechroot Modes: unshare fakechroot
Formats: tar squashfs ext2 Formats: tar squashfs ext2 ext4
Variants: essential apt minbase buildd - standard Variants: essential apt minbase buildd - standard
Skip-If: Skip-If:
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558 variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
mode == "fakechroot" and variant in ["-", "standard"] # no extended attributes mode == "fakechroot" and variant in ["-", "standard"] # no extended attributes
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276 variant == "standard" and dist in ["oldstable", "stable"] and hostarch in ["armel", "armhf", "mipsel"] # #1031276
Test: tarfilter-idshift Test: tarfilter-idshift
Needs-QEMU: true Needs-QEMU: true
@ -273,17 +273,13 @@ Test: debootstrap-no-op-options
Needs-Root: true Needs-Root: true
Test: verbose Test: verbose
Variants: - standard Variants: standard
Skip-If: Skip-If:
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558 variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
Test: debug Test: debug
Variants: - standard Variants: standard
Skip-If: Skip-If:
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558 variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
Test: quiet Test: quiet
@ -434,3 +430,9 @@ Modes: root unshare
Test: skip-tar-in-mknod Test: skip-tar-in-mknod
Modes: unshare Modes: unshare
Test: zombie-reaping
Modes: unshare
Test: empty-suite
Needs-APT-Config: true

View file

@ -28,24 +28,29 @@
set -eu set -eu
find_gpgv_status_fd() { find_gpgv_status_fd() {
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
if [ "$1" = '--status-fd' ]; then if [ "$1" = '--status-fd' ]; then
echo "$2" echo "$2"
return 0 return 0
fi fi
shift shift
done done
# default fd is stdout # default fd is stdout
echo 1 echo 1
} }
GPGSTATUSFD="$(find_gpgv_status_fd "$@")" GPGSTATUSFD="$(find_gpgv_status_fd "$@")"
case $GPGSTATUSFD in case $GPGSTATUSFD in
''|*[!0-9]*) '' | *[!0-9]*)
echo "invalid --status-fd argument" >&2 echo "invalid --status-fd argument" >&2
exit 1 exit 1
;; ;;
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"

View file

@ -1,4 +1,13 @@
#!/bin/sh #!/bin/sh
#
# This script makes sure that the apt sources.list and preferences from outside
# the chroot also exist inside the chroot by *appending* them to any existing
# files. If you do not want to keep the original content, add another setup
# hook before this one which cleans up the files you don't want to keep.
#
# If instead of copying sources.list verbatim you want to mangle its contents,
# consider using python-apt for that. An example can be found in the Debian
# packaging of mmdebstrap in ./debian/tests/sourcesfilter
set -eu set -eu

View file

@ -15,7 +15,7 @@ env APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get indextargets --no-release-info -
| while read -r path; do | while read -r path; do
mkdir -p "$rootdir/run/mmdebstrap" mkdir -p "$rootdir/run/mmdebstrap"
if [ ! -d "/$path" ]; then if [ ! -d "/$path" ]; then
echo "/$path is not an existing directory" >&2 echo "W: /$path is not an existing directory" >&2
continue continue
fi fi
case $MMDEBSTRAP_MODE in case $MMDEBSTRAP_MODE in

View file

@ -15,6 +15,10 @@ case "$ver" in
echo "usr-is-merged package from src:usrmerge installed -- not running merged-usr essential hook" >&2 echo "usr-is-merged package from src:usrmerge installed -- not running merged-usr essential hook" >&2
exit 0 exit 0
;; ;;
'not-installed ')
echo "usr-is-merged was not installed in a previous hook -- not running merged-usr essential hook" >&2
exit 0
;;
*) *)
echo "unexpected situation for package usr-is-merged: $ver" >&2 echo "unexpected situation for package usr-is-merged: $ver" >&2
exit 1 exit 1

View file

@ -4,12 +4,22 @@ set -eu
env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get update --error-on=any env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get update --error-on=any
# if the usr-is-merged package cannot be installed with apt, do nothing if env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-cache show --no-all-versions usr-is-merged > /dev/null 2>&1; then
if ! env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-cache show --no-all-versions usr-is-merged > /dev/null 2>&1; then # if apt-cache exited successfully, then usr-is-merged exists either as
echo "no package called usr-is-merged found -- not running merged-usr extract hook" >&2 # a real or virtual package
exit 0 if env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-cache show --no-all-versions usr-is-merged 2>/dev/null | grep -q "Package: usr-is-merged"; then
echo "usr-is-merged found -- running merged-usr extract hook" >&2
else
# The usr-is-merged must be virtual, so assume that nothing
# has to be done. This is the case with Debian Trixie or later
# or with Ubuntu Lunar or later
echo "usr-is-merged found but not real -- not running merged-usr extract hook" >&2
exit 0
fi
else else
echo "package usr-is-merged found -- running merged-usr extract hook" >&2 # if the usr-is-merged package cannot be installed with apt, do nothing
echo "no package providing usr-is-merged found -- not running merged-usr extract hook" >&2
exit 0
fi fi
# resolve the script path using several methods in order: # resolve the script path using several methods in order:

View file

@ -4,12 +4,22 @@ set -eu
env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get update --error-on=any env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get update --error-on=any
# if the usr-is-merged package cannot be installed with apt, do nothing if env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-cache show --no-all-versions usr-is-merged > /dev/null 2>&1; then
if ! env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-cache show --no-all-versions usr-is-merged > /dev/null 2>&1; then # if apt-cache exited successfully, then usr-is-merged exists either as
echo "no package called usr-is-merged found -- not running merged-usr setup hook" >&2 # a real or virtual package
exit 0 if env --chdir="$1" APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-cache show --no-all-versions usr-is-merged 2>/dev/null | grep -q "Package: usr-is-merged"; then
echo "usr-is-merged found -- running merged-usr setup hook" >&2
else
# The usr-is-merged must be virtual, so assume that nothing
# has to be done. This is the case with Debian Trixie or later
# or with Ubuntu Lunar or later
echo "usr-is-merged found but not real -- not running merged-usr setup hook" >&2
exit 0
fi
else else
echo "package usr-is-merged found -- running merged-usr setup hook" >&2 # if the usr-is-merged package cannot be installed with apt, do nothing
echo "no package providing usr-is-merged found -- not running merged-usr setup hook" >&2
exit 0
fi fi
# resolve the script path using several methods in order: # resolve the script path using several methods in order:

View file

@ -10,160 +10,160 @@ set -eu
# the local repository. # the local repository.
deletecache() { deletecache() {
dir="$1" dir="$1"
echo "running deletecache $dir">&2 echo "running deletecache $dir" >&2
if [ ! -e "$dir" ]; then if [ ! -e "$dir" ]; then
return return
fi fi
if [ ! -e "$dir/mmdebstrapcache" ]; then if [ ! -e "$dir/mmdebstrapcache" ]; then
echo "$dir cannot be the mmdebstrap cache" >&2 echo "$dir cannot be the mmdebstrap cache" >&2
return 1 return 1
fi fi
# be very careful with removing the old directory # be very careful with removing the old directory
# experimental is pulled in with USE_HOST_APT_CONFIG=yes on debci # experimental is pulled in with USE_HOST_APT_CONFIG=yes on debci
# when testing a package from experimental # when testing a package from experimental
for dist in oldstable stable testing unstable experimental; do for dist in oldstable stable testing unstable experimental; do
# deleting artifacts from test "debootstrap" # deleting artifacts from test "debootstrap"
for variant in minbase buildd -; do for variant in minbase buildd -; do
if [ -e "$dir/debian-$dist-$variant.tar" ]; then if [ -e "$dir/debian-$dist-$variant.tar" ]; then
rm "$dir/debian-$dist-$variant.tar" rm "$dir/debian-$dist-$variant.tar"
else else
echo "does not exist: $dir/debian-$dist-$variant.tar" >&2 echo "does not exist: $dir/debian-$dist-$variant.tar" >&2
fi fi
done done
# deleting artifacts from test "mmdebstrap" # deleting artifacts from test "mmdebstrap"
for variant in essential apt minbase buildd - standard; do for variant in essential apt minbase buildd - standard; do
for format in tar ext2 squashfs; do for format in tar ext2 ext4 squashfs; do
if [ -e "$dir/mmdebstrap-$dist-$variant.$format" ]; then if [ -e "$dir/mmdebstrap-$dist-$variant.$format" ]; then
# attempt to delete for all dists because DEFAULT_DIST might've been different the last time # attempt to delete for all dists because DEFAULT_DIST might've been different the last time
rm "$dir/mmdebstrap-$dist-$variant.$format" rm "$dir/mmdebstrap-$dist-$variant.$format"
elif [ "$dist" = "$DEFAULT_DIST" ]; then elif [ "$dist" = "$DEFAULT_DIST" ]; then
# only warn about non-existance when it's expected to exist # only warn about non-existance when it's expected to exist
echo "does not exist: $dir/mmdebstrap-$dist-$variant.$format" >&2 echo "does not exist: $dir/mmdebstrap-$dist-$variant.$format" >&2
fi fi
done done
done done
if [ -e "$dir/debian/dists/$dist" ]; then if [ -e "$dir/debian/dists/$dist" ]; then
rm --one-file-system --recursive "$dir/debian/dists/$dist" rm --one-file-system --recursive "$dir/debian/dists/$dist"
else else
echo "does not exist: $dir/debian/dists/$dist" >&2 echo "does not exist: $dir/debian/dists/$dist" >&2
fi fi
case "$dist" in oldstable|stable) case "$dist" in oldstable | stable)
if [ -e "$dir/debian/dists/$dist-updates" ]; then if [ -e "$dir/debian/dists/$dist-updates" ]; then
rm --one-file-system --recursive "$dir/debian/dists/$dist-updates" rm --one-file-system --recursive "$dir/debian/dists/$dist-updates"
else else
echo "does not exist: $dir/debian/dists/$dist-updates" >&2 echo "does not exist: $dir/debian/dists/$dist-updates" >&2
fi fi
;; ;;
esac esac
case "$dist" in oldstable|stable) case "$dist" in oldstable | stable)
if [ -e "$dir/debian-security/dists/$dist-security" ]; then if [ -e "$dir/debian-security/dists/$dist-security" ]; then
rm --one-file-system --recursive "$dir/debian-security/dists/$dist-security" rm --one-file-system --recursive "$dir/debian-security/dists/$dist-security"
else else
echo "does not exist: $dir/debian-security/dists/$dist-security" >&2 echo "does not exist: $dir/debian-security/dists/$dist-security" >&2
fi fi
;; ;;
esac esac
done done
for f in "$dir/debian-"*.ext4; do for f in "$dir/debian-"*.ext4; do
if [ -e "$f" ]; then if [ -e "$f" ]; then
rm --one-file-system "$f" rm --one-file-system "$f"
fi fi
done done
# on i386 and amd64, the intel-microcode and amd64-microcode packages # on i386 and amd64, the intel-microcode and amd64-microcode packages
# from non-free-firwame get pulled in because they are # from non-free-firwame get pulled in because they are
# priority:standard with USE_HOST_APT_CONFIG=yes # priority:standard with USE_HOST_APT_CONFIG=yes
for c in main non-free-firmware; do for c in main non-free-firmware; do
if [ -e "$dir/debian/pool/$c" ]; then if [ -e "$dir/debian/pool/$c" ]; then
rm --one-file-system --recursive "$dir/debian/pool/$c" rm --one-file-system --recursive "$dir/debian/pool/$c"
else else
echo "does not exist: $dir/debian/pool/$c" >&2 echo "does not exist: $dir/debian/pool/$c" >&2
fi fi
done done
if [ -e "$dir/debian-security/pool/updates/main" ]; then if [ -e "$dir/debian-security/pool/updates/main" ]; then
rm --one-file-system --recursive "$dir/debian-security/pool/updates/main" rm --one-file-system --recursive "$dir/debian-security/pool/updates/main"
else else
echo "does not exist: $dir/debian-security/pool/updates/main" >&2 echo "does not exist: $dir/debian-security/pool/updates/main" >&2
fi fi
for i in $(seq 1 6); do for i in $(seq 1 6); do
if [ ! -e "$dir/debian$i" ]; then if [ ! -e "$dir/debian$i" ]; then
continue continue
fi fi
rm "$dir/debian$i" rm "$dir/debian$i"
done done
rm "$dir/mmdebstrapcache" rm "$dir/mmdebstrapcache"
# remove all symlinks # remove all symlinks
find "$dir" -type l -delete find "$dir" -type l -delete
# now the rest should only be empty directories # now the rest should only be empty directories
if [ -e "$dir" ]; then if [ -e "$dir" ]; then
find "$dir" -depth -print0 | xargs -0 --no-run-if-empty rmdir find "$dir" -depth -print0 | xargs -0 --no-run-if-empty rmdir
else else
echo "does not exist: $dir" >&2 echo "does not exist: $dir" >&2
fi fi
} }
cleanup_newcachedir() { cleanup_newcachedir() {
echo "running cleanup_newcachedir" echo "running cleanup_newcachedir"
deletecache "$newcachedir" deletecache "$newcachedir"
} }
cleanupapt() { cleanupapt() {
echo "running cleanupapt" >&2 echo "running cleanupapt" >&2
if [ ! -e "$rootdir" ]; then if [ ! -e "$rootdir" ]; then
return return
fi fi
for f in \ for f in \
"$rootdir/var/cache/apt/archives/"*.deb \ "$rootdir/var/cache/apt/archives/"*.deb \
"$rootdir/var/cache/apt/archives/partial/"*.deb \ "$rootdir/var/cache/apt/archives/partial/"*.deb \
"$rootdir/var/cache/apt/"*.bin \ "$rootdir/var/cache/apt/"*.bin \
"$rootdir/var/lib/apt/lists/"* \ "$rootdir/var/lib/apt/lists/"* \
"$rootdir/var/lib/dpkg/status" \ "$rootdir/var/lib/dpkg/status" \
"$rootdir/var/lib/dpkg/lock-frontend" \ "$rootdir/var/lib/dpkg/lock-frontend" \
"$rootdir/var/lib/dpkg/lock" \ "$rootdir/var/lib/dpkg/lock" \
"$rootdir/var/lib/apt/lists/lock" \ "$rootdir/var/lib/apt/lists/lock" \
"$rootdir/etc/apt/apt.conf" \ "$rootdir/etc/apt/apt.conf" \
"$rootdir/etc/apt/sources.list.d/"* \ "$rootdir/etc/apt/sources.list.d/"* \
"$rootdir/etc/apt/preferences.d/"* \ "$rootdir/etc/apt/preferences.d/"* \
"$rootdir/etc/apt/sources.list" \ "$rootdir/etc/apt/sources.list" \
"$rootdir/var/cache/apt/archives/lock"; do "$rootdir/var/cache/apt/archives/lock"; do
if [ ! -e "$f" ]; then if [ ! -e "$f" ]; then
echo "does not exist: $f" >&2 echo "does not exist: $f" >&2
continue continue
fi fi
if [ -d "$f" ]; then if [ -d "$f" ]; then
rmdir "$f" rmdir "$f"
else else
rm "$f" rm "$f"
fi fi
done done
find "$rootdir" -depth -print0 | xargs -0 --no-run-if-empty rmdir find "$rootdir" -depth -print0 | xargs -0 --no-run-if-empty rmdir
} }
# note: this function uses brackets instead of curly braces, so that it's run # note: this function uses brackets instead of curly braces, so that it's run
# in its own process and we can handle traps independent from the outside # in its own process and we can handle traps independent from the outside
update_cache() ( update_cache() (
dist="$1" dist="$1"
nativearch="$2" nativearch="$2"
# use a subdirectory of $newcachedir so that we can use # use a subdirectory of $newcachedir so that we can use
# hardlinks # hardlinks
rootdir="$newcachedir/apt" rootdir="$newcachedir/apt"
mkdir -p "$rootdir" mkdir -p "$rootdir"
# we only set this trap here and overwrite the previous trap, because # we only set this trap here and overwrite the previous trap, because
# the update_cache function is run as part of a pipe and thus in its # the update_cache function is run as part of a pipe and thus in its
# own process which will EXIT after it finished # own process which will EXIT after it finished
trap 'kill "$PROXYPID" || :;cleanupapt' EXIT INT TERM trap 'kill "$PROXYPID" || :;cleanupapt' EXIT INT TERM
for p in /etc/apt/apt.conf.d /etc/apt/sources.list.d /etc/apt/preferences.d /var/cache/apt/archives /var/lib/apt/lists/partial /var/lib/dpkg; do for p in /etc/apt/apt.conf.d /etc/apt/sources.list.d /etc/apt/preferences.d /var/cache/apt/archives /var/lib/apt/lists/partial /var/lib/dpkg; do
mkdir -p "$rootdir/$p" mkdir -p "$rootdir/$p"
done done
# read sources.list content from stdin # 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::Architecture "$nativearch";
Apt::Architectures "$nativearch"; Apt::Architectures "$nativearch";
Dir::Etc "$rootdir/etc/apt"; Dir::Etc "$rootdir/etc/apt";
@ -177,121 +177,126 @@ Dir::Etc::TrustedParts "/etc/apt/trusted.gpg.d";
Acquire::http::Proxy "http://127.0.0.1:8080/"; Acquire::http::Proxy "http://127.0.0.1:8080/";
END END
: > "$rootdir/var/lib/dpkg/status" : >"$rootdir/var/lib/dpkg/status"
if [ "$dist" = "$DEFAULT_DIST" ] && [ "$nativearch" = "$HOSTARCH" ] && [ "$USE_HOST_APT_CONFIG" = "yes" ]; then if [ "$dist" = "$DEFAULT_DIST" ] && [ "$nativearch" = "$HOSTARCH" ] && [ "$USE_HOST_APT_CONFIG" = "yes" ]; then
# we append sources and settings instead of overwriting after # we append sources and settings instead of overwriting after
# an empty line # an empty line
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*; do for f in /etc/apt/sources.list /etc/apt/sources.list.d/*; do
[ -e "$f" ] || continue [ -e "$f" ] || continue
[ -e "$rootdir/$f" ] && echo >> "$rootdir/$f" [ -e "$rootdir/$f" ] && echo >>"$rootdir/$f"
# Filter out file:// repositories as they are added # Filter out file:// repositories as they are added
# to each mmdebstrap call verbatim by # to each mmdebstrap call verbatim by
# debian/tests/copy_host_apt_config # debian/tests/copy_host_apt_config
# Also filter out all mirrors that are not of suite # Also filter out all mirrors that are not of suite
# $DEFAULT_DIST, except experimental if the suite # $DEFAULT_DIST, except experimental if the suite
# is unstable. This prevents packages from # is unstable. This prevents packages from
# unstable entering a testing mirror. # unstable entering a testing mirror.
if [ "$dist" = unstable ]; then if [ "$dist" = unstable ]; then
grep -v ' file://' "$f" \ grep -v ' file://' "$f" \
| grep -E " (unstable|experimental) " \ | grep -E " (unstable|experimental) " \
>> "$rootdir/$f" || : >>"$rootdir/$f" || :
else else
grep -v ' file://' "$f" \ grep -v ' file://' "$f" \
| grep " $DEFAULT_DIST " \ | grep " $DEFAULT_DIST " \
>> "$rootdir/$f" || : >>"$rootdir/$f" || :
fi fi
done done
for f in /etc/apt/preferences.d/*; do for f in /etc/apt/preferences.d/*; do
[ -e "$f" ] || continue [ -e "$f" ] || continue
[ -e "$rootdir/$f" ] && echo >> "$rootdir/$f" [ -e "$rootdir/$f" ] && echo >>"$rootdir/$f"
cat "$f" >> "$rootdir/$f" cat "$f" >>"$rootdir/$f"
done done
fi fi
echo "creating mirror for $dist" >&2 echo "creating mirror for $dist" >&2
for f in /etc/apt/sources.list /etc/apt/sources.list.d/* /etc/apt/preferences.d/*; do for f in /etc/apt/sources.list /etc/apt/sources.list.d/* /etc/apt/preferences.d/*; do
[ -e "$rootdir/$f" ] || continue [ -e "$rootdir/$f" ] || continue
echo "contents of $f:" >&2 echo "contents of $f:" >&2
cat "$rootdir/$f" >&2 cat "$rootdir/$f" >&2
done done
APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get update --error-on=any APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get update --error-on=any
pkgs=$(APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get indextargets \ pkgs=$(APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get indextargets \
--format '$(FILENAME)' 'Created-By: Packages' "Architecture: $nativearch" \ --format '$(FILENAME)' 'Created-By: Packages' "Architecture: $nativearch" \
| xargs --delimiter='\n' /usr/lib/apt/apt-helper cat-file \ | xargs --delimiter='\n' /usr/lib/apt/apt-helper cat-file \
| grep-dctrl --no-field-names --show-field=Package --exact-match \ | grep-dctrl --no-field-names --show-field=Package --exact-match \
\( --field=Essential yes --or --field=Priority required \ \( --field=Essential yes --or --field=Priority required \
--or --field=Priority important --or --field=Priority standard \ --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 # we need usr-is-merged to simulate debootstrap behaviour for all dists
# starting from Debian 12 (Bullseye) # starting from Debian 12 (Bullseye)
case "$dist" in case "$dist" in
oldstable) : ;; oldstable) pkgs="$pkgs gpg" ;;
*) pkgs="$pkgs usr-is-merged usrmerge" ;; stable) pkgs="$pkgs gpg usr-is-merged usrmerge" ;;
esac testing | unstable) pkgs="$pkgs gpg-from-sq" ;;
esac
# shellcheck disable=SC2086 # shellcheck disable=SC2086
APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get --yes install $pkgs APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get --yes install $pkgs \
|| APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get --yes install \
-oDebug::pkgProblemResolver=true -oDebug::pkgDepCache::Marker=1 \
-oDebug::pkgDepCache::AutoInstall=1 \
$pkgs
rm "$rootdir/var/cache/apt/archives/lock" rm "$rootdir/var/cache/apt/archives/lock"
rmdir "$rootdir/var/cache/apt/archives/partial" rmdir "$rootdir/var/cache/apt/archives/partial"
APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get --option Dir::Etc::SourceList=/dev/null update APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get --option Dir::Etc::SourceList=/dev/null update
APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get clean APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get clean
cleanupapt cleanupapt
# this function is run in its own process, so we unset all traps before # this function is run in its own process, so we unset all traps before
# returning # returning
trap "-" EXIT INT TERM trap "-" EXIT INT TERM
) )
check_proxy_running() { check_proxy_running() {
if timeout 1 bash -c 'exec 3<>/dev/tcp/127.0.0.1/8080 && printf "GET http://deb.debian.org/debian/dists/'"$DEFAULT_DIST"'/InRelease HTTP/1.1\nHost: deb.debian.org\n\n" >&3 && grep "Suite: '"$DEFAULT_DIST"'" <&3 >/dev/null' 2>/dev/null; then if timeout 1 bash -c 'exec 3<>/dev/tcp/127.0.0.1/8080 && printf "GET http://deb.debian.org/debian/dists/'"$DEFAULT_DIST"'/InRelease HTTP/1.1\nHost: deb.debian.org\n\n" >&3 && grep "Suite: '"$DEFAULT_DIST"'" <&3 >/dev/null' 2>/dev/null; then
return 0 return 0
elif timeout 1 env http_proxy="http://127.0.0.1:8080/" wget --quiet -O - "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" | grep "Suite: $DEFAULT_DIST" >/dev/null; then elif timeout 1 env http_proxy="http://127.0.0.1:8080/" wget --quiet -O - "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" | grep "Suite: $DEFAULT_DIST" >/dev/null; then
return 0 return 0
elif timeout 1 curl --proxy "http://127.0.0.1:8080/" --silent "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" | grep "Suite: $DEFAULT_DIST" >/dev/null; then elif timeout 1 curl --proxy "http://127.0.0.1:8080/" --silent "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" | grep "Suite: $DEFAULT_DIST" >/dev/null; then
return 0 return 0
fi fi
return 1 return 1
} }
if [ -e "./shared/cache.A" ] && [ -e "./shared/cache.B" ]; then if [ -e "./shared/cache.A" ] && [ -e "./shared/cache.B" ]; then
echo "both ./shared/cache.A and ./shared/cache.B exist" >&2 echo "both ./shared/cache.A and ./shared/cache.B exist" >&2
echo "was a former run of the script aborted?" >&2 echo "was a former run of the script aborted?" >&2
if [ -e ./shared/cache ]; then if [ -e ./shared/cache ]; then
echo "cache symlink points to $(readlink ./shared/cache)" >&2 echo "cache symlink points to $(readlink ./shared/cache)" >&2
case "$(readlink ./shared/cache)" in case "$(readlink ./shared/cache)" in
cache.A) cache.A)
echo "removing ./shared/cache.B" >&2 echo "removing ./shared/cache.B" >&2
rm -r ./shared/cache.B rm -r ./shared/cache.B
;; ;;
cache.B) cache.B)
echo "removing ./shared/cache.A" >&2 echo "removing ./shared/cache.A" >&2
rm -r ./shared/cache.A rm -r ./shared/cache.A
;; ;;
*) *)
echo "unexpected" >&2 echo "unexpected" >&2
exit 1 exit 1
;; ;;
esac esac
else else
echo "./shared/cache doesn't exist" >&2 echo "./shared/cache doesn't exist" >&2
exit 1 exit 1
fi fi
fi fi
if [ -e "./shared/cache.A" ]; then if [ -e "./shared/cache.A" ]; then
oldcache=cache.A oldcache=cache.A
newcache=cache.B newcache=cache.B
else else
oldcache=cache.B oldcache=cache.B
newcache=cache.A newcache=cache.A
fi fi
oldcachedir="./shared/$oldcache" oldcachedir="./shared/$oldcache"
@ -315,12 +320,18 @@ components=main
: "${FORCE_UPDATE:=no}" : "${FORCE_UPDATE:=no}"
if [ "$FORCE_UPDATE" != "yes" ] && [ -e "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then if [ "$FORCE_UPDATE" != "yes" ] && [ -e "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
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") 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 case "$http_code" in
200) ;; # need update 200) ;; # need update
304) echo up-to-date; exit 0;; 304)
*) echo "unexpected status: $http_code"; exit 1;; echo up-to-date
esac exit 0
;;
*)
echo "unexpected status: $http_code"
exit 1
;;
esac
fi fi
./caching_proxy.py "$oldcachedir" "$newcachedir" & ./caching_proxy.py "$oldcachedir" "$newcachedir" &
@ -328,13 +339,13 @@ PROXYPID=$!
trap 'kill "$PROXYPID" || :' EXIT INT TERM trap 'kill "$PROXYPID" || :' EXIT INT TERM
for i in $(seq 10); do for i in $(seq 10); do
check_proxy_running && break check_proxy_running && break
sleep 1 sleep 1
done done
if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
echo "failed to start proxy" >&2 echo "failed to start proxy" >&2
kill $PROXYPID kill $PROXYPID
exit 1 exit 1
fi fi
trap 'kill "$PROXYPID" || :;cleanup_newcachedir' EXIT INT TERM trap 'kill "$PROXYPID" || :;cleanup_newcachedir' EXIT INT TERM
@ -345,9 +356,9 @@ touch "$newcachedir/mmdebstrapcache"
HOSTARCH=$(dpkg --print-architecture) HOSTARCH=$(dpkg --print-architecture)
arches="$HOSTARCH" arches="$HOSTARCH"
if [ "$HOSTARCH" = amd64 ]; then if [ "$HOSTARCH" = amd64 ]; then
arches="$arches arm64 i386" arches="$arches arm64 i386"
elif [ "$HOSTARCH" = arm64 ]; then elif [ "$HOSTARCH" = arm64 ]; then
arches="$arches amd64 armhf" arches="$arches amd64 armhf"
fi fi
# we need the split_inline_sig() function # we need the split_inline_sig() function
@ -355,43 +366,43 @@ fi
. /usr/share/debootstrap/functions . /usr/share/debootstrap/functions
for dist in oldstable stable testing unstable; do for dist in oldstable stable testing unstable; do
for nativearch in $arches; do for nativearch in $arches; do
# non-host architectures are only downloaded for $DEFAULT_DIST # non-host architectures are only downloaded for $DEFAULT_DIST
if [ "$nativearch" != "$HOSTARCH" ] && [ "$DEFAULT_DIST" != "$dist" ]; then if [ "$nativearch" != "$HOSTARCH" ] && [ "$DEFAULT_DIST" != "$dist" ]; then
continue continue
fi fi
# if ONLY_DEFAULT_DIST is set, only download DEFAULT_DIST # if ONLY_DEFAULT_DIST is set, only download DEFAULT_DIST
if [ "$ONLY_DEFAULT_DIST" = "yes" ] && [ "$DEFAULT_DIST" != "$dist" ]; then if [ "$ONLY_DEFAULT_DIST" = "yes" ] && [ "$DEFAULT_DIST" != "$dist" ]; then
continue continue
fi fi
if [ "$ONLY_HOSTARCH" = "yes" ] && [ "$nativearch" != "$HOSTARCH" ]; then if [ "$ONLY_HOSTARCH" = "yes" ] && [ "$nativearch" != "$HOSTARCH" ]; then
continue continue
fi fi
# we need a first pass without updates and security patches # we need a first pass without updates and security patches
# because otherwise, old package versions needed by # because otherwise, old package versions needed by
# debootstrap will not get included # debootstrap will not get included
echo "deb [arch=$nativearch] $mirror $dist $components" | update_cache "$dist" "$nativearch" echo "deb [arch=$nativearch] $mirror $dist $components" | update_cache "$dist" "$nativearch"
# we need to include the base mirror again or otherwise # we need to include the base mirror again or otherwise
# packages like build-essential will be missing # packages like build-essential will be missing
case "$dist" in oldstable|stable) case "$dist" in oldstable | stable)
cat << END | update_cache "$dist" "$nativearch" cat <<END | update_cache "$dist" "$nativearch"
deb [arch=$nativearch] $mirror $dist $components deb [arch=$nativearch] $mirror $dist $components
deb [arch=$nativearch] $mirror $dist-updates main deb [arch=$nativearch] $mirror $dist-updates main
deb [arch=$nativearch] $security_mirror $dist-security main deb [arch=$nativearch] $security_mirror $dist-security main
END END
;; ;;
esac esac
done 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" ln -s "$dist" "$newmirrordir/dists/$codename"
# split the InRelease file into Release and Release.gpg not because apt # split the InRelease file into Release and Release.gpg not because apt
# or debootstrap need it that way but because grep-dctrl does # or debootstrap need it that way but because grep-dctrl does
split_inline_sig \ split_inline_sig \
"$newmirrordir/dists/$dist/InRelease" \ "$newmirrordir/dists/$dist/InRelease" \
"$newmirrordir/dists/$dist/Release" \ "$newmirrordir/dists/$dist/Release" \
"$newmirrordir/dists/$dist/Release.gpg" "$newmirrordir/dists/$dist/Release.gpg"
touch --reference="$newmirrordir/dists/$dist/InRelease" "$newmirrordir/dists/$dist/Release" "$newmirrordir/dists/$dist/Release.gpg" touch --reference="$newmirrordir/dists/$dist/InRelease" "$newmirrordir/dists/$dist/Release" "$newmirrordir/dists/$dist/Release.gpg"
done done
kill $PROXYPID kill $PROXYPID
@ -401,73 +412,73 @@ kill $PROXYPID
# avoid the warning: # avoid the warning:
# W: Target Packages (main/binary-all/Packages) is configured multiple times... # W: Target Packages (main/binary-all/Packages) is configured multiple times...
for i in $(seq 1 6); do for i in $(seq 1 6); do
ln -s debian "$newcachedir/debian$i" ln -s debian "$newcachedir/debian$i"
done done
tmpdir="" tmpdir=""
cleanuptmpdir() { cleanuptmpdir() {
if [ -z "$tmpdir" ]; then if [ -z "$tmpdir" ]; then
return return
fi fi
if [ ! -e "$tmpdir" ]; then if [ ! -e "$tmpdir" ]; then
return return
fi fi
for f in "$tmpdir/worker.sh" "$tmpdir/mmdebstrap.service"; do for f in "$tmpdir/worker.sh" "$tmpdir/mmdebstrap.service"; do
if [ ! -e "$f" ]; then if [ ! -e "$f" ]; then
echo "does not exist: $f" >&2 echo "does not exist: $f" >&2
continue continue
fi fi
rm "$f" rm "$f"
done done
rmdir "$tmpdir" rmdir "$tmpdir"
} }
SOURCE_DATE_EPOCH="$(date --date="$(grep-dctrl -s Date -n '' "$newmirrordir/dists/$DEFAULT_DIST/Release")" +%s)" SOURCE_DATE_EPOCH="$(date --date="$(grep-dctrl -s Date -n '' "$newmirrordir/dists/$DEFAULT_DIST/Release")" +%s)"
export SOURCE_DATE_EPOCH export SOURCE_DATE_EPOCH
if [ "$HAVE_QEMU" = "yes" ]; then if [ "$HAVE_QEMU" = "yes" ]; then
# we use the caching proxy again when building the qemu image # we use the caching proxy again when building the qemu image
# - we can re-use the packages that were already downloaded earlier # - we can re-use the packages that were already downloaded earlier
# - we make sure that the qemu image uses the same Release file even # - we make sure that the qemu image uses the same Release file even
# if a mirror push happened between now and earlier # if a mirror push happened between now and earlier
# - we avoid polluting the mirror with the additional packages by # - we avoid polluting the mirror with the additional packages by
# using --readonly # using --readonly
./caching_proxy.py --readonly "$oldcachedir" "$newcachedir" & ./caching_proxy.py --readonly "$oldcachedir" "$newcachedir" &
PROXYPID=$! PROXYPID=$!
for i in $(seq 10); do for i in $(seq 10); do
check_proxy_running && break check_proxy_running && break
sleep 1 sleep 1
done done
if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
echo "failed to start proxy" >&2 echo "failed to start proxy" >&2
kill $PROXYPID kill $PROXYPID
exit 1 exit 1
fi fi
tmpdir="$(mktemp -d)" tmpdir="$(mktemp -d)"
trap 'kill "$PROXYPID" || :;cleanuptmpdir; cleanup_newcachedir' EXIT INT TERM trap 'kill "$PROXYPID" || :;cleanuptmpdir; cleanup_newcachedir' EXIT INT TERM
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-static,qemu-user,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 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 if [ ! -e ./mmdebstrap ]; then
pkgs="$pkgs,mmdebstrap" pkgs="$pkgs,mmdebstrap"
fi fi
arches=$HOSTARCH arches=$HOSTARCH
if [ "$RUN_MA_SAME_TESTS" = "yes" ]; then if [ "$RUN_MA_SAME_TESTS" = "yes" ]; then
case "$HOSTARCH" in case "$HOSTARCH" in
amd64) amd64)
arches=amd64,arm64 arches=amd64,arm64
pkgs="$pkgs,libfakechroot:arm64,libfakeroot:arm64" pkgs="$pkgs,libfakechroot:arm64,libfakeroot:arm64"
;; ;;
arm64) arm64)
arches=arm64,amd64 arches=arm64,amd64
pkgs="$pkgs,libfakechroot:amd64,libfakeroot:amd64" pkgs="$pkgs,libfakechroot:amd64,libfakeroot:amd64"
;; ;;
esac esac
fi fi
cat << END > "$tmpdir/mmdebstrap.service" cat <<END >"$tmpdir/mmdebstrap.service"
[Unit] [Unit]
Description=mmdebstrap worker script Description=mmdebstrap worker script
@ -478,15 +489,15 @@ ExecStart=/worker.sh
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
END END
# here is something crazy: # here is something crazy:
# as we run mmdebstrap, the process ends up being run by different users with # as we run mmdebstrap, the process ends up being run by different users with
# different privileges (real or fake). But for being able to collect # different privileges (real or fake). But for being able to collect
# Devel::Cover data, they must all share a single directory. The only way that # Devel::Cover data, they must all share a single directory. The only way that
# I found to make this work is to mount the database directory with a # I found to make this work is to mount the database directory with a
# filesystem that doesn't support ownership information at all and a umask that # filesystem that doesn't support ownership information at all and a umask that
# gives read/write access to everybody. # gives read/write access to everybody.
# https://github.com/pjcj/Devel--Cover/issues/223 # https://github.com/pjcj/Devel--Cover/issues/223
cat << 'END' > "$tmpdir/worker.sh" cat <<'END' >"$tmpdir/worker.sh"
#!/bin/sh #!/bin/sh
echo 'root:root' | chpasswd echo 'root:root' | chpasswd
mount -t 9p -o trans=virtio,access=any,msize=128k mmdebstrap /mnt mount -t 9p -o trans=virtio,access=any,msize=128k mmdebstrap /mnt
@ -526,36 +537,37 @@ handler () {
umount /mnt umount /mnt
systemctl poweroff systemctl poweroff
END END
chmod +x "$tmpdir/worker.sh" chmod +x "$tmpdir/worker.sh"
if [ -z ${DISK_SIZE+x} ]; then if [ -z ${DISK_SIZE+x} ]; then
DISK_SIZE=10G DISK_SIZE=10G
fi fi
# set PATH to pick up the correct mmdebstrap variant # set PATH to pick up the correct mmdebstrap variant
env PATH="$(dirname "$(realpath --canonicalize-existing "$CMD")"):$PATH" \ env PATH="$(dirname "$(realpath --canonicalize-existing "$CMD")"):$PATH" \
debvm-create --skip=usrmerge,systemdnetwork \ debvm-create --skip=usrmerge,systemdnetwork \
--size="$DISK_SIZE" --release="$DEFAULT_DIST" \ --size="$DISK_SIZE" --release="$DEFAULT_DIST" \
--output="$newcachedir/debian-$DEFAULT_DIST.ext4" -- \ --output="$newcachedir/debian-$DEFAULT_DIST.ext4" -- \
--architectures="$arches" --include="$pkgs" \ --architectures="$arches" --include="$pkgs" \
--setup-hook='echo "Acquire::http::Proxy \"http://127.0.0.1:8080/\";" > "$1/etc/apt/apt.conf.d/00proxy"' \ --setup-hook='echo "Acquire::http::Proxy \"http://127.0.0.1:8080/\";" > "$1/etc/apt/apt.conf.d/00proxy"' \
--hook-dir=/usr/share/mmdebstrap/hooks/maybe-merged-usr \ --hook-dir=/usr/share/mmdebstrap/hooks/maybe-merged-usr \
--customize-hook='rm "$1/etc/apt/apt.conf.d/00proxy"' \ --customize-hook='rm "$1/etc/apt/apt.conf.d/00proxy"' \
--customize-hook='mkdir -p "$1/etc/systemd/system/multi-user.target.wants"' \ --customize-hook='mkdir -p "$1/etc/systemd/system/multi-user.target.wants"' \
--customize-hook='ln -s ../mmdebstrap.service "$1/etc/systemd/system/multi-user.target.wants/mmdebstrap.service"' \ --customize-hook='ln -s ../mmdebstrap.service "$1/etc/systemd/system/multi-user.target.wants/mmdebstrap.service"' \
--customize-hook='touch "$1/mmdebstrap-testenv"' \ --customize-hook='touch "$1/mmdebstrap-testenv"' \
--customize-hook='copy-in "'"$tmpdir"'/mmdebstrap.service" /etc/systemd/system/' \ --customize-hook='copy-in "'"$tmpdir"'/mmdebstrap.service" /etc/systemd/system/' \
--customize-hook='copy-in "'"$tmpdir"'/worker.sh" /' \ --customize-hook='copy-in "'"$tmpdir"'/worker.sh" /' \
--customize-hook='echo 127.0.0.1 localhost > "$1/etc/hosts"' \ --customize-hook='echo 127.0.0.1 localhost > "$1/etc/hosts"' \
--customize-hook='printf "START=1\nDAEMON_OPTS=\"-h 127.0.0.1 -p 80 -u nobody -dd /mnt/cache -i /var/run/mini-httpd.pid -T UTF-8\"\n" > "$1/etc/default/mini-httpd"' \ --customize-hook='printf "START=1\nDAEMON_OPTS=\"-h 127.0.0.1 -p 80 -u nobody -dd /mnt/cache -i /var/run/mini-httpd.pid -T UTF-8\"\n" > "$1/etc/default/mini-httpd"' \
"$mirror" --customize-hook='touch "$1/etc/systemd/system/tmp.mount"' \
"$mirror"
kill $PROXYPID kill $PROXYPID
cleanuptmpdir cleanuptmpdir
trap "cleanup_newcachedir" EXIT INT TERM trap "cleanup_newcachedir" EXIT INT TERM
fi fi
# delete possibly leftover symlink # delete possibly leftover symlink
if [ -e ./shared/cache.tmp ]; then if [ -e ./shared/cache.tmp ]; then
rm ./shared/cache.tmp rm ./shared/cache.tmp
fi fi
# now atomically switch the symlink to point to the other directory # now atomically switch the symlink to point to the other directory
ln -s $newcache ./shared/cache.tmp ln -s $newcache ./shared/cache.tmp

2030
mmdebstrap

File diff suppressed because it is too large Load diff

View file

@ -29,10 +29,11 @@ B<mmdebstrap-autopkgtest-build-qemu> [I<OPTIONS>] B<--boot>=B<efi> I<RELEASE> I<
B<mmdebstrap-autopkgtest-build-qemu> is a mostly compatible drop-in replacement B<mmdebstrap-autopkgtest-build-qemu> is a mostly compatible drop-in replacement
for L<autopkgtest-build-qemu(1)> with two main differences: Firstly, it uses for L<autopkgtest-build-qemu(1)> with two main differences: Firstly, it uses
L<mmdebstrap(1)> instead of L<vmdb2(1)> and thus is able to create QEMU disk L<mmdebstrap(1)> instead of L<vmdb2(1)> and thus is able to create QEMU disk
images without requiring superuser privileges. Secondly, it uses images without requiring superuser privileges and with bit-by-bit reproducible
L<systemd-boot(7)> and thus only supports booting via EFI. For architectures output. Secondly, it uses L<systemd-boot(7)> and thus only supports booting via
for which L<autopkgtest-virt-qemu(1)> does not default to EFI booting you must EFI. For architectures for which L<autopkgtest-virt-qemu(1)> does not default
pass B<--boot=efi> when invoking the autopkgtest virt backend. to EFI booting you must pass B<--boot=efi> when invoking the autopkgtest virt
backend.
=head1 POSITIONAL PARAMETERS =head1 POSITIONAL PARAMETERS
@ -94,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
@ -110,6 +117,12 @@ all path components or by creating the image in a world-readable directory like
Make sure to add B<--boot=efi> to both the B<mmdebstrap-autopkgtest-build-qemu> Make sure to add B<--boot=efi> to both the B<mmdebstrap-autopkgtest-build-qemu>
as well as the B<autopkgtest-virt-qemu> invocation. as well as the B<autopkgtest-virt-qemu> invocation.
Create bit-by-bit reproducible images from a given snapshot.d.o timestamp.
SOURCE_DATE_EPOCH=1612543740 mmdebstrap-autopkgtest-build-qemu --boot=efi \
--mirror=http://snapshot.debian.org/archive/debian/20210205T164900Z/ \
unstable /path/to/debian-unstable.img
=head1 SEE ALSO =head1 SEE ALSO
L<autopkgtest-build-qemu(1)>, L<autopkgtest-virt-qemu(1)>, L<mmdebstrap(1)>, L<autopkgtest(1)> L<autopkgtest-build-qemu(1)>, L<autopkgtest-virt-qemu(1)>, L<mmdebstrap(1)>, L<autopkgtest(1)>
@ -120,15 +133,15 @@ POD2MAN
set -eu set -eu
die() { die() {
echo "$*" 1>&2 echo "$*" 1>&2
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
usage usage
} }
BOOT=auto BOOT=auto
@ -139,164 +152,181 @@ 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
opt_boot() { opt_boot() {
BOOT="$1" BOOT="$1"
} }
opt_architecture() { opt_architecture() {
ARCHITECTURE="$1" ARCHITECTURE="$1"
} }
opt_arch() { opt_arch() {
ARCHITECTURE="$1" ARCHITECTURE="$1"
} }
opt_apt_proxy() { opt_apt_proxy() {
# consumed by setup-testbed # consumed by setup-testbed
export AUTOPKGTEST_APT_PROXY="$1" export AUTOPKGTEST_APT_PROXY="$1"
# consumed by mmdebstrap # consumed by mmdebstrap
if test "$1" = DIRECT; then if test "$1" = DIRECT; then
unset http_proxy unset http_proxy
else else
export http_proxy="$1" export http_proxy="$1"
fi fi
} }
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"
} }
opt_script() { opt_script() {
test -f "$1" || die "passed script '$1' does not refer to a file" test -f "$1" || die "passed script '$1' does not refer to a file"
SCRIPT="$1" SCRIPT="$1"
} }
opt_size() { opt_size() {
SIZE="$1" SIZE="$1"
} }
positional=1 positional=1
positional_1() { positional_1() {
# consumed by setup-testbed # consumed by setup-testbed
export RELEASE="$1" export RELEASE="$1"
} }
positional_2() { positional_2() {
IMAGE="$1" IMAGE="$1"
} }
positional_3() { opt_mirror "$@"; } positional_3() { opt_mirror "$@"; }
positional_4() { opt_architecture "$@"; } positional_4() { opt_architecture "$@"; }
positional_5() { opt_script "$@"; } positional_5() { opt_script "$@"; }
positional_6() { opt_size "$@"; } positional_6() { opt_size "$@"; }
positional_7() { positional_7() {
die "too many positional options" die "too many positional options"
} }
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
;; ;;
--apt-proxy) --apt-proxy)
test "$#" -ge 2 || usage_error "missing argument for $1" test "$#" -ge 2 || usage_error "missing argument for $1"
opt_apt_proxy "$2" opt_apt_proxy "$2"
shift shift
;; ;;
--efi) --efi)
opt_boot efi opt_boot efi
;; ;;
--*) --)
usage_error "unrecognized argument $1" shift
;; break
*) ;;
"positional_$positional" "$1" --*)
positional=$((positional + 1)) usage_error "unrecognized argument $1"
;; ;;
esac *)
shift "positional_$positional" "$1"
positional=$((positional + 1))
;;
esac
shift
done done
test -z "$RELEASE" -o -z "$IMAGE" && usage_error "missing positional arguments" test -z "$RELEASE" -o -z "$IMAGE" && usage_error "missing positional arguments"
test "$BOOT" = efi || test "$BOOT" = efi \
die "this tool does not support boot modes other than efi" || die "this tool does not support boot modes other than efi"
case "$ARCHITECTURE" in case "$ARCHITECTURE" in
amd64) amd64)
EFIIMG=bootx64.efi EFIIMG=bootx64.efi
QEMUARCH=x86_64 QEMUARCH=x86_64
VMFPKG=ovmf VMFPKG=ovmf
;; LINUXIMAGE=linux-image-amd64
arm64) ;;
EFIIMG=bootaa64.efi arm64)
QEMUARCH=aarch64 EFIIMG=bootaa64.efi
VMFPKG=qemu-efi-aarch64 QEMUARCH=aarch64
;; VMFPKG=qemu-efi-aarch64
armhf) LINUXIMAGE=linux-image-arm64
EFIIMG=bootarm.efi ;;
QEMUARCH=arm armhf)
VMFPKG=qemu-efi-arm EFIIMG=bootarm.efi
;; QEMUARCH=arm
i386) VMFPKG=qemu-efi-arm
EFIIMG=bootia32.efi LINUXIMAGE=linux-image-armmp
QEMUARCH=i386 ;;
VMFPKG=ovmf-ia32 i386)
;; EFIIMG=bootia32.efi
riscv64) QEMUARCH=i386
EFIIMG=bootriscv64.efi VMFPKG=ovmf-ia32
QEMUARCH=riscv64 LINUXIMAGE=linux-image-686-pae
VMFPKG= ;;
;; riscv64)
*) EFIIMG=bootriscv64.efi
die "unsupported architecture: $ARCHITECTURE" QEMUARCH=riscv64
;; VMFPKG=
LINUXIMAGE=linux-image-riscv64
;;
*)
die "unsupported architecture: $ARCHITECTURE"
;;
esac esac
if test "$(dpkg-query -f '${db:Status-Status}' -W binutils-multiarch)" = installed; then if test "$(dpkg-query -f '${db:Status-Status}' -W binutils-multiarch)" = installed; then
GNU_PREFIX= GNU_PREFIX=
BINUTILS=
else else
GNU_ARCHITECTURE="$(dpkg-architecture "-a$ARCHITECTURE" -qDEB_HOST_GNU_TYPE)" GNU_ARCHITECTURE="$(dpkg-architecture "-a$ARCHITECTURE" -qDEB_HOST_GNU_TYPE)"
GNU_PREFIX="$GNU_ARCHITECTURE-" GNU_PREFIX="$GNU_ARCHITECTURE-"
GNU_SUFFIX="-$(echo "$GNU_ARCHITECTURE" | tr _ -)" GNU_SUFFIX="-$(echo "$GNU_ARCHITECTURE" | tr _ -)"
test "$(dpkg-query -f '${db:Status-Status}' -W "binutils$GNU_SUFFIX")" = installed || BINUTILS=", binutils$GNU_SUFFIX | binutils-multiarch"
die "please install binutils$GNU_SUFFIX or binutils-multiarch"
fi fi
arches=" $(dpkg --print-architecture) $(dpkg --print-foreign-architectures | tr '\n' ' ') " arches=" $(dpkg --print-architecture) $(dpkg --print-foreign-architectures | tr '\n' ' ') "
case $arches in case $arches in
*" $ARCHITECTURE "*) : ;; # nothing to do *" $ARCHITECTURE "*) : ;; # nothing to do
*) die "enable $ARCHITECTURE by running: sudo dpkg --add-architecture $ARCHITECTURE && sudo apt update" ;; *) die "enable $ARCHITECTURE by running: sudo dpkg --add-architecture $ARCHITECTURE && sudo apt update" ;;
esac esac
for pkg in autopkgtest dosfstools e2fsprogs fdisk mount mtools passwd "systemd-boot-efi:$ARCHITECTURE" uidmap; do test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed \
if [ "$(dpkg-query -f '${db:Status-Status}' -W "$pkg")" != installed ]; then || die "please install dpkg-dev"
die "please install $pkg"
fi if test -n "$SSHKEY" && ! test -f "$SSHKEY"; then
done 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" BOOTSTUB="/usr/lib/systemd/boot/efi/linux${EFIIMG#boot}.stub"
WORKDIR= WORKDIR=
cleanup() { cleanup() {
test -n "$WORKDIR" && rm -Rf "$WORKDIR" test -n "$WORKDIR" && rm -Rf "$WORKDIR"
} }
trap cleanup EXIT INT TERM QUIT trap cleanup EXIT INT TERM QUIT
WORKDIR=$(mktemp -d) WORKDIR=$(mktemp -d)
FAT_OFFSET_SECTORS=$((1024*2)) FAT_OFFSET_SECTORS=$((1024 * 2))
FAT_SIZE_SECTORS=$((1024*254)) FAT_SIZE_SECTORS=$((1024 * 254))
# The image is raw and not in qcow2 format because: # The image is raw and not in qcow2 format because:
# - faster run-time as the "qemu-image convert" step is not needed # - faster run-time as the "qemu-image convert" step is not needed
@ -307,91 +337,103 @@ FAT_SIZE_SECTORS=$((1024*254))
# - snapshots and overlays work just as well with raw images # - snapshots and overlays work just as well with raw images
# - users who prefer qcow2 get to choose to run it themselves with their own # - users who prefer qcow2 get to choose to run it themselves with their own
# custom options like compression # custom options like compression
#
# Make the image writeable to the first subgid. mmdebstrap will map this gid to
# the root group. unshare instead will map the current gid to 0 and the first
# subgid to 1. Therefore mmdebstrap will be able to write to the image.
rm -f "$IMAGE"
: >"$IMAGE"
unshare -U -r --map-groups=auto chown 0:1 "$IMAGE"
chmod 0660 "$IMAGE"
# Make sure that the unshared user is able to access the file.
# Alternatively to using /sbin/mkfs.ext4 could use --format=ext2 which would
# add an extra copy operation and come with the limitations of ext2.
# Another solution: https://github.com/tytso/e2fsprogs/pull/118
if ! mmdebstrap --unshare-helper touch "$IMAGE"; then
die "$IMAGE cannot be accessed by the unshared user -- either make all path components up to the image itself world-executable or place the image into a world-readable path like /tmp"
fi
set -- \ set -- \
--mode=unshare \ --mode=unshare \
--variant=important \ --format=tar \
--architecture="$ARCHITECTURE" --variant=important \
--architecture="$ARCHITECTURE" \
"$@"
test "$RELEASE" = jessie && case $MIRROR in http://snapshot.debian.org/archive/* | https://snapshot.debian.org/archive/*)
set -- "$@" --hook-dir=/usr/share/mmdebstrap/hooks/jessie-or-older set -- "$@" --aptopt='Acquire::Check-Valid-Until "false"'
;;
esac
set -- "$@" \ EXT_FEATURES=
"--include=init,linux-image-$ARCHITECTURE,python3" \ if test "$RELEASE" = jessie; then
'--customize-hook=echo host >"$1/etc/hostname"' \ set -- "$@" --keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg
'--customize-hook=echo 127.0.0.1 localhost host >"$1/etc/hosts"' \ set -- "$@" --aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"'
'--customize-hook=passwd --root "$1" --delete root' \ set -- "$@" --hook-dir=/usr/share/mmdebstrap/hooks/jessie-or-older
'--customize-hook=useradd --root "$1" --home-dir /home/user --create-home user' \ EXT_FEATURES="^metadata_csum,^metadata_csum_seed,^orphan_file"
'--customize-hook=passwd --root "$1" --delete user' \
'--customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed'
if test -n "$SCRIPT"; then
set -- "$@" \
"--customize-hook=upload '$SCRIPT' /userscript" \
"--chrooted-customize-hook=sh /userscript" \
'--customize-hook=rm -f "$1/userscript"'
fi fi
EXT4_OFFSET_BYTES=$(( (FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))
EXT4_OPTIONS="offset=$EXT4_OFFSET_BYTES,assume_storage_prezeroed=1"
set -- "$@" \ set -- "$@" \
"--customize-hook=download vmlinuz '$WORKDIR/kernel'" \ "--include=init,$LINUXIMAGE,python3" \
"--customize-hook=download initrd.img '$WORKDIR/initrd'" \ '--customize-hook=echo host >"$1/etc/hostname"' \
'--customize-hook=mount --bind "$1" "$1/mnt"' \ '--customize-hook=echo 127.0.0.1 localhost host >"$1/etc/hosts"' \
'--customize-hook=mount --bind "$1/mnt/mnt" "$1/mnt/dev"' \ '--customize-hook=passwd --root "$1" --delete root' \
'--customize-hook=/sbin/mkfs.ext4 -d "$1/mnt" -L autopkgtestvm -E '"'$EXT4_OPTIONS' '$IMAGE' '$SIZE'" \ '--customize-hook=useradd --root "$1" --home-dir /home/user --create-home user' \
'--customize-hook=umount --lazy "$1/mnt"' \ '--customize-hook=passwd --root "$1" --delete user' \
"$RELEASE" \ '--customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed'
/dev/null
if test -n "$SCRIPT"; then
set -- "$@" \
"--customize-hook=upload '$SCRIPT' /userscript" \
"--chrooted-customize-hook=sh /userscript" \
'--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'" \
"$RELEASE" \
-
test -n "$MIRROR" && set -- "$@" "$MIRROR" test -n "$MIRROR" && set -- "$@" "$MIRROR"
test -n "$KEYRING" && set -- "$@" "--keyring=$KEYRING" test -n "$KEYRING" && set -- "$@" "--keyring=$KEYRING"
echo "mmdebstrap $*" echo "+ mmdebstrap $*" >&2
mmdebstrap "$@" || die "mmdebstrap failed" # https://github.com/koalaman/shellcheck/issues/2555
# shellcheck disable=SC3040
set -o pipefail
mmdebstrap "$@" | {
set -- -t ext4 -L autopkgtestvm -d -
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
uuid="$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name "$SOURCE_DATE_EPOCH")"
set -- "$@" -U "$uuid"
EXTOPTS="$EXTOPTS,hash_seed=$uuid"
fi
set -- "$@" -E "$EXTOPTS" "$IMAGE" "$SIZE"
echo "+ mke2fs $*" >&2
/sbin/mke2fs "$@"
}
unshare -U -r --map-groups=auto chown 0:0 "$IMAGE" echo "root=LABEL=autopkgtestvm rw console=ttyS0" >"$WORKDIR/cmdline"
chmod "$(printf %o "$(( 0666 & ~0$(umask) ))")" "$IMAGE"
echo "root=LABEL=autopkgtestvm rw console=ttyS0" > "$WORKDIR/cmdline"
align_size() { 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') 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" test -z "$alignment" && die "failed to discover the alignment of the efi stub"
echo "determined efi vma alignment as $alignment" 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" echo "increasing efi vma alignment for jessie"
alignment=$((1024*1024)) alignment=$((1024 * 1024))
} }
lastoffset=0 lastoffset=0
# shellcheck disable=SC2034 # unused variables serve documentation # shellcheck disable=SC2034 # unused variables serve documentation
lastoffset="$("${GNU_PREFIX}objdump" -h "$BOOTSTUB" | lastoffset="$("${GNU_PREFIX}objdump" -h "$BOOTSTUB" \
while read -r idx name size vma lma fileoff algn behind; do | while read -r idx name size vma lma fileoff algn behind; do
test -z "$behind" -a "${algn#"2**"}" != "$algn" || continue test -z "$behind" -a "${algn#"2**"}" != "$algn" || continue
offset=$(( 0x$vma + 0x$size )) offset=$((0x$vma + 0x$size))
test "$offset" -gt "$lastoffset" || continue test "$offset" -gt "$lastoffset" || continue
lastoffset="$offset" lastoffset="$offset"
echo "$lastoffset" echo "$lastoffset"
done | tail -n1)" done | tail -n1)"
lastoffset=$(align_size "$lastoffset" "$alignment") lastoffset=$(align_size "$lastoffset" "$alignment")
echo "determined minimum efi vma offset as $lastoffset" echo "determined minimum efi vma offset as $lastoffset"
@ -404,15 +446,15 @@ linux_offset=$((cmdline_offset + cmdline_size))
initrd_offset=$((linux_offset + linux_size)) initrd_offset=$((linux_offset + linux_size))
SOURCE_DATE_EPOCH=0 \ SOURCE_DATE_EPOCH=0 \
"${GNU_PREFIX}objcopy" \ "${GNU_PREFIX}objcopy" \
--enable-deterministic-archives \ --enable-deterministic-archives \
--add-section .cmdline="$WORKDIR/cmdline" \ --add-section .cmdline="$WORKDIR/cmdline" \
--change-section-vma .cmdline="$(printf 0x%x "$cmdline_offset")" \ --change-section-vma .cmdline="$(printf 0x%x "$cmdline_offset")" \
--add-section .linux="$WORKDIR/kernel" \ --add-section .linux="$WORKDIR/kernel" \
--change-section-vma .linux="$(printf 0x%x "$linux_offset")" \ --change-section-vma .linux="$(printf 0x%x "$linux_offset")" \
--add-section .initrd="$WORKDIR/initrd" \ --add-section .initrd="$WORKDIR/initrd" \
--change-section-vma .initrd="$(printf 0x%x "$initrd_offset")" \ --change-section-vma .initrd="$(printf 0x%x "$initrd_offset")" \
"$BOOTSTUB" "$WORKDIR/efiimg" "$BOOTSTUB" "$WORKDIR/efiimg"
rm -f "$WORKDIR/kernel" "$WORKDIR/initrd" rm -f "$WORKDIR/kernel" "$WORKDIR/initrd"
@ -423,7 +465,7 @@ mcopy -i "$WORKDIR/fat" "$WORKDIR/efiimg" "::EFI/BOOT/$EFIIMG"
rm -f "$WORKDIR/efiimg" rm -f "$WORKDIR/efiimg"
truncate --size="+$((34*512))" "$IMAGE" truncate --size="+$((34 * 512))" "$IMAGE"
/sbin/sfdisk "$IMAGE" <<EOF /sbin/sfdisk "$IMAGE" <<EOF
label: gpt label: gpt
unit: sectors unit: sectors
@ -435,10 +477,11 @@ EOF
dd if="$WORKDIR/fat" of="$IMAGE" conv=notrunc,sparse bs=512 "seek=$FAT_OFFSET_SECTORS" status=none dd if="$WORKDIR/fat" of="$IMAGE" conv=notrunc,sparse bs=512 "seek=$FAT_OFFSET_SECTORS" status=none
if test "$(dpkg --print-architecture)" != "$ARCHITECTURE" && test "$(dpkg-query -f '${db:Status-Status}' -W "qemu-system-$QEMUARCH")" != installed; then if test "$(dpkg --print-architecture)" != "$ARCHITECTURE" && test "$(dpkg-query -f '${db:Status-Status}' -W "qemu-system-$QEMUARCH")" != installed; then
echo "I: you might need to install a package providing qemu-system-$QEMUARCH to use this image with autopkgtest-virt-qemu" >&2 echo "I: you might need to install a package providing qemu-system-$QEMUARCH to use this image with autopkgtest-virt-qemu" >&2
fi fi
if test -n "$VMFPKG" && test "$(dpkg-query -f '${db:Status-Status}' -W "$VMFPKG")" != installed; then if test -n "$VMFPKG" && test "$(dpkg-query -f '${db:Status-Status}' -W "$VMFPKG")" != installed; then
echo "I: you might need to install $VMFPKG to use this image with autopkgtest-virt-qemu" >&2 echo "I: you might need to install $VMFPKG to use this image with autopkgtest-virt-qemu" >&2
fi fi
echo "I: don't forget to pass --boot=efi when running autopkgtest-virt-qemu with this image" >&2 echo "I: SUCCESS! Your new image can be found here: $IMAGE" >&2
echo "I: Don't forget to pass --boot=efi when running autopkgtest-virt-qemu with this image" >&2

View file

@ -4,17 +4,17 @@ set -eu
SUDO= SUDO=
while [ "$#" -gt 0 ]; do 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"
exit 1 exit 1
;; ;;
esac esac
shift shift
done done
# - Run command with fds 3 and 4 closed so that whatever test.sh does it # - Run command with fds 3 and 4 closed so that whatever test.sh does it
@ -26,15 +26,25 @@ done
# - Read fd 3 and let the group exit with that value # - Read fd 3 and let the group exit with that value
# - Redirect fd 4 to stdout # - Redirect fd 4 to stdout
ret=0 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; ret=0
} 3>&1; (
} | { read -r xs; exit "$xs"; } 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=$? } 4>&1 || ret=$?
if [ "$ret" -ne 0 ]; then if [ "$ret" -ne 0 ]; then
echo "test.sh failed" echo "test.sh failed"
exit 1 exit 1
fi fi

View file

@ -4,46 +4,69 @@ set -eu
: "${DEFAULT_DIST:=unstable}" : "${DEFAULT_DIST:=unstable}"
: "${cachedir:=./shared/cache}" : "${cachedir:=./shared/cache}"
: "${MMDEBSTRAP_TESTS_DEBUG:=no}"
tmpdir="$(mktemp -d)" tmpdir="$(mktemp -d)"
cleanup() { cleanup() {
rv=$? rv=$?
rm -f "$tmpdir/log" rm -f "$tmpdir/log"
[ -e "$tmpdir" ] && rmdir "$tmpdir" [ -e "$tmpdir" ] && rmdir "$tmpdir"
if [ -e shared/output.txt ]; then if [ -e shared/output.txt ]; then
res="$(cat shared/exitstatus.txt)" res="$(cat shared/exitstatus.txt)"
if [ "$res" != "0" ]; then if [ "$res" != "0" ]; then
# this might possibly overwrite another non-zero rv # this might possibly overwrite another non-zero rv
rv=1 rv=1
fi fi
fi fi
exit $rv exit $rv
} }
trap cleanup INT TERM EXIT trap cleanup INT TERM EXIT
echo 1 > shared/exitstatus.txt echo 1 >shared/exitstatus.txt
if [ -e shared/output.txt ]; then if [ -e shared/output.txt ]; then
rm shared/output.txt rm shared/output.txt
fi fi
touch shared/output.txt touch shared/output.txt
setpriv --pdeathsig TERM tail -f shared/output.txt & setpriv --pdeathsig TERM tail -f shared/output.txt &
# to connect to serial use: set -- timeout --foreground 40m \
# minicom -D 'unix#/tmp/ttyS0' debvm-run --image="$(realpath "$cachedir")/debian-$DEFAULT_DIST.ext4" \
# --
# or this (quit with ctrl+q): cpuname=$(lscpu | awk '/Model name:/ {print $3}' | tr '\n' '+')
# socat stdin,raw,echo=0,escape=0x11 unix-connect:/tmp/ttyS0 ncpu=$(lscpu | awk '/Core\(s\) per socket:/ {print $4}' | tr '\n' '+')
ret=0 if [ "$cpuname" = "Cortex-A53+Cortex-A73+" ] && [ "$ncpu" = "2+4+" ]; then
timeout --foreground 40m debvm-run --image="$(realpath "$cachedir")/debian-$DEFAULT_DIST.ext4" -- \ # crude detection of the big.LITTLE heterogeneous setup of cores on the
-nic none \ # amlogic a311d bananapi
-m 4G -snapshot \ #
-monitor unix:/tmp/monitor,server,nowait \ # https://lists.nongnu.org/archive/html/qemu-devel/2020-10/msg08494.html
-serial unix:/tmp/ttyS0,server,nowait \ # https://gitlab.com/qemu-project/qemu/-/issues/239
-serial unix:/tmp/ttyS1,server,nowait \ # https://segments.zhan.science/posts/kvm_on_pinehone_pro/#trouble-with-heterogeneous-architecture
-virtfs local,id=mmdebstrap,path="$(pwd)/shared",security_model=none,mount_tag=mmdebstrap \ set -- taskset --cpu-list 2,3,4,5 "$@" -smp 4
>"$tmpdir/log" 2>&1 || ret=$? fi
if [ "$ret" -ne 0 ]; then
cat "$tmpdir/log" set -- "$@" -nic none -m 4G -snapshot
exit $ret
if [ "$MMDEBSTRAP_TESTS_DEBUG" = "no" ]; then
# to connect to serial use:
# minicom -D 'unix#/tmp/ttyS0'
# or this (quit with ctrl+q):
# socat stdin,raw,echo=0,escape=0x11 unix-connect:/tmp/ttyS0
set -- "$@" \
-monitor unix:/tmp/monitor,server,nowait \
-serial unix:/tmp/ttyS0,server,nowait \
-serial unix:/tmp/ttyS1,server,nowait
fi
set -- "$@" -virtfs local,id=mmdebstrap,path="$(pwd)/shared",security_model=none,mount_tag=mmdebstrap
ret=0
if [ "$MMDEBSTRAP_TESTS_DEBUG" = "no" ]; then
"$@" >"$tmpdir/log" 2>&1 || ret=$?
else
"$@" 2>&1 | tee "$tmpdir/log" || ret=$?
fi
if [ "$ret" -ne 0 ]; then
cat "$tmpdir/log"
exit $ret
fi fi

View file

@ -218,8 +218,11 @@ Lastly, shift user id and group id of each entry by the value given by the
skip = False skip = False
if not hasattr(args, "pathfilter"): if not hasattr(args, "pathfilter"):
return False return False
# normalize path and make it absolute by stripping off all leading
# dots and slashes and then prepending a slash
name = "/" + member.name.lstrip("./")
for t, r in args.pathfilter: for t, r in args.pathfilter:
if r.match(member.name[1:]) is not None: if r.match(name) is not None:
if t == "path_include": if t == "path_include":
skip = False skip = False
else: else:
@ -230,7 +233,7 @@ Lastly, shift user id and group id of each entry by the value given by the
continue continue
prefix = prefix_prog.sub(r"\1", r.pattern) prefix = prefix_prog.sub(r"\1", r.pattern)
prefix = prefix.rstrip("/") prefix = prefix.rstrip("/")
if member.name[1:].startswith(prefix): if name.startswith(prefix):
return False return False
return skip return skip

View file

@ -3,6 +3,6 @@ set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode={{ MODE }} --variant=essential \ {{ CMD }} --mode={{ MODE }} --variant=essential \
--include '?or(?exact-name(dummy-does-not-exist),?exact-name(apt))' \ --include '?or(?exact-name(dummy-does-not-exist),?exact-name(apt))' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | grep -v ./var/lib/apt/extended_states | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

@ -3,7 +3,10 @@ set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode={{ MODE }} --variant=custom \ {{ CMD }} --mode={{ MODE }} --variant=custom \
--include '?narrow(?archive(^{{ DIST }}$),?essential)' \ --include '?narrow(?archive(^{{ DIST }}$),?essential)' \
--include apt \ --include apt \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | 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 set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/config" EXIT INT TERM 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 }} {{ 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 - 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 rm /tmp/debian-chroot/etc/apt/apt.conf.d/99mmdebstrap

View file

@ -2,10 +2,10 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
apt-get remove --yes qemu-user-static binfmt-support qemu-user apt-get remove --yes qemu-user-binfmt binfmt-support qemu-user
# the following is not necessary anymore since systemd-binfmt # the following is not necessary anymore since systemd-binfmt
# successfully disables support upon removal of qemu-user with # successfully disables support upon removal of qemu-user with
# the upload of src:systemd 251.2-4: https://bugs.debian.org/1012163 # the upload of src:systemd 251.2-4: https://bugs.debian.org/1012163
@ -13,6 +13,6 @@ apt-get remove --yes qemu-user-static binfmt-support qemu-user
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt --architectures=arm64 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt --architectures=arm64 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -5,14 +5,14 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
# debootstrap uses apt-config to figure out whether the system running it has # debootstrap uses apt-config to figure out whether the system running it has
@ -28,18 +28,21 @@ 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 }} \
--setup-hook='env '"${AUTOPROXY:+APT_CONFIG='$TMP_APT_CONFIG'}"' debootstrap --variant={{ VARIANT }} unstable "$1" {{ MIRROR }}' \ --setup-hook='env '"${AUTOPROXY:+APT_CONFIG='$TMP_APT_CONFIG'}"' debootstrap --variant={{ VARIANT }} unstable "$1" {{ MIRROR }}' \
- /tmp/debian-mm.tar {{ MIRROR }} - /tmp/debian-mm.tar {{ MIRROR }}
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
rm "$TMP_APT_CONFIG" rm "$TMP_APT_CONFIG"
fi fi
mkdir /tmp/debian-mm mkdir /tmp/debian-mm
@ -62,21 +65,21 @@ rm /tmp/debian-debootstrap/var/cache/apt/archives/*.deb
rm /tmp/debian-debootstrap/var/cache/ldconfig/aux-cache rm /tmp/debian-debootstrap/var/cache/ldconfig/aux-cache
# remove logs # remove logs
rm /tmp/debian-debootstrap/var/log/dpkg.log \ rm /tmp/debian-debootstrap/var/log/dpkg.log \
/tmp/debian-debootstrap/var/log/bootstrap.log \ /tmp/debian-debootstrap/var/log/bootstrap.log \
/tmp/debian-debootstrap/var/log/alternatives.log \ /tmp/debian-debootstrap/var/log/alternatives.log \
/tmp/debian-mm/var/log/bootstrap.log /tmp/debian-mm/var/log/bootstrap.log
# clear out /run except for /run/lock # clear out /run except for /run/lock
find /tmp/debian-debootstrap/run/ -mindepth 1 -maxdepth 1 ! -name lock -print0 | xargs --no-run-if-empty -0 rm -r find /tmp/debian-debootstrap/run/ -mindepth 1 -maxdepth 1 ! -name lock -print0 | xargs --no-run-if-empty -0 rm -r
# debootstrap doesn't clean apt # debootstrap doesn't clean apt
rm /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_main_binary-{{ HOSTARCH }}_Packages \ rm /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_main_binary-{{ HOSTARCH }}_Packages \
/tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_InRelease \ /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_InRelease \
/tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_Release \ /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_Release \
/tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_Release.gpg /tmp/debian-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_unstable_Release.gpg
if [ -e /tmp/debian-debootstrap/etc/machine-id ]; then if [ -e /tmp/debian-debootstrap/etc/machine-id ]; then
rm /tmp/debian-debootstrap/etc/machine-id /tmp/debian-mm/etc/machine-id rm /tmp/debian-debootstrap/etc/machine-id /tmp/debian-mm/etc/machine-id
fi fi
rm /tmp/debian-mm/var/cache/apt/archives/lock rm /tmp/debian-mm/var/cache/apt/archives/lock
rm /tmp/debian-mm/var/lib/apt/lists/lock rm /tmp/debian-mm/var/lib/apt/lists/lock
@ -85,24 +88,24 @@ rm /tmp/debian-mm/var/lib/dpkg/arch
# also needed for users that are created by systemd-sysusers before systemd 252 # also needed for users that are created by systemd-sysusers before systemd 252
# https://github.com/systemd/systemd/pull/24534 # https://github.com/systemd/systemd/pull/24534
for f in shadow shadow-; do for f in shadow shadow-; do
if [ ! -e /tmp/debian-debootstrap/etc/$f ]; then if [ ! -e /tmp/debian-debootstrap/etc/$f ]; then
continue continue
fi fi
if ! cmp /tmp/debian-debootstrap/etc/$f /tmp/debian-mm/etc/$f >&2; then if ! cmp /tmp/debian-debootstrap/etc/$f /tmp/debian-mm/etc/$f >&2; then
echo patching /etc/$f >&2 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 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 cat /tmp/debian-mm/etc/$f.bak >/tmp/debian-mm/etc/$f
rm /tmp/debian-mm/etc/$f.bak rm /tmp/debian-mm/etc/$f.bak
else else
echo no difference for /etc/$f >&2 echo no difference for /etc/$f >&2
fi fi
done done
# isc-dhcp-client postinst doesn't create this file in debootstrap run with # isc-dhcp-client postinst doesn't create this file in debootstrap run with
# unshared wrapper. The responsible postinst snippet was automatically added # unshared wrapper. The responsible postinst snippet was automatically added
# by dh_apparmor since isc-dhcp-client 4.4.3-P1-1.1 # 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 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 fi
# check if the file content differs # check if the file content differs
@ -111,17 +114,17 @@ diff --unified --no-dereference --recursive /tmp/debian-debootstrap /tmp/debian-
# check permissions, ownership, symlink targets, modification times using tar # check permissions, ownership, symlink targets, modification times using tar
# mtimes of directories created by mmdebstrap will differ, thus we equalize them first # mtimes of directories created by mmdebstrap will differ, thus we equalize them first
for d in etc/apt/preferences.d/ etc/apt/sources.list.d/ etc/dpkg/dpkg.cfg.d/ var/log/apt/; do for d in etc/apt/preferences.d/ etc/apt/sources.list.d/ etc/dpkg/dpkg.cfg.d/ var/log/apt/; do
touch --date="@{{ SOURCE_DATE_EPOCH }}" /tmp/debian-debootstrap/$d /tmp/debian-mm/$d touch --date="@{{ SOURCE_DATE_EPOCH }}" /tmp/debian-debootstrap/$d /tmp/debian-mm/$d
done done
# debootstrap never ran apt -- fixing permissions # debootstrap never ran apt -- fixing permissions
for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do
chroot /tmp/debian-debootstrap chmod 0700 $d chroot /tmp/debian-debootstrap chmod 0700 $d
chroot /tmp/debian-debootstrap chown _apt:root $d chroot /tmp/debian-debootstrap chown _apt:root $d
done 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-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 -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/root1.tar >/tmp/root1.tar.list
tar --full-time --verbose -tf /tmp/root2.tar > /tmp/root2.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 # despite SOURCE_DATE_EPOCH and --clamp-mtime, the timestamps in the tarball
# will slightly differ from each other in the sub-second precision (last # will slightly differ from each other in the sub-second precision (last
# decimals) so the tarballs will not be identical, so we use diff to compare # decimals) so the tarballs will not be identical, so we use diff to compare

View file

@ -2,19 +2,19 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do
[ -e "$f" ] || continue [ -e "$f" ] || continue
rm "$f" rm "$f"
done done
rmdir /etc/apt/trusted.gpg.d rmdir /etc/apt/trusted.gpg.d
mkdir /etc/apt/trusted.gpg.d mkdir /etc/apt/trusted.gpg.d
for f in /usr/share/keyrings/*.gpg; do for f in /usr/share/keyrings/*.gpg; do
name=$(basename "$f" .gpg) name=$(basename "$f" .gpg)
gpg --no-default-keyring --keyring="/usr/share/keyrings/$name.gpg" --armor --output="/etc/apt/trusted.gpg.d/$name.asc" --export gpg --no-default-keyring --keyring="/usr/share/keyrings/$name.gpg" --armor --output="/etc/apt/trusted.gpg.d/$name.asc" --export
rm "/usr/share/keyrings/$name.gpg" rm "/usr/share/keyrings/$name.gpg"
done done
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

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

View file

@ -8,14 +8,14 @@ trap "rm -f /tmp/debian-chroot.tar.gz" EXIT INT TERM
prefix= prefix=
if [ "$(id -u)" -eq 0 ]; then if [ "$(id -u)" -eq 0 ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar.gz {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar.gz {{ MIRROR }}

View file

@ -2,12 +2,12 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir /home/user --create-home user useradd --home-dir /home/user --create-home user
if [ -e /proc/sys/kernel/unprivileged_userns_clone ] && [ "$(sysctl -n kernel.unprivileged_userns_clone)" = "1" ]; then if [ -e /proc/sys/kernel/unprivileged_userns_clone ] && [ "$(sysctl -n kernel.unprivileged_userns_clone)" = "1" ]; then
sysctl -w kernel.unprivileged_userns_clone=0 sysctl -w kernel.unprivileged_userns_clone=0
fi fi
runuser -u user -- {{ CMD }} --mode=auto --variant=apt {{ DIST }} /tmp/debian-chroot.tar.gz {{ MIRROR }} runuser -u user -- {{ CMD }} --mode=auto --variant=apt {{ DIST }} /tmp/debian-chroot.tar.gz {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar.gz | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar.gz | sort | diff -u tar1.txt -

View file

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

View file

@ -11,10 +11,10 @@ echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
# https://bugs.debian.org/969631 # https://bugs.debian.org/969631
# we cannot use useradd because passwd is not Essential:yes # we cannot use useradd because passwd is not Essential:yes
{{ CMD }} --variant={{ VARIANT }} --mode={{ MODE }} \ {{ CMD }} --variant={{ VARIANT }} --mode={{ MODE }} \
--essential-hook='[ {{ DIST }} = oldstable ] && [ {{ VARIANT }} = - ] && echo _apt:*:100:65534::/nonexistent:/usr/sbin/nologin >> "$1"/etc/passwd || :' \ --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 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 )" \ "$(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 }} {{ DIST }} /tmp/debian-{{ DIST }}-mm.tar {{ MIRROR }}
mkdir /tmp/debian-{{ DIST }}-mm mkdir /tmp/debian-{{ DIST }}-mm
tar --xattrs --xattrs-include='*' -C /tmp/debian-{{ DIST }}-mm -xf /tmp/debian-{{ DIST }}-mm.tar tar --xattrs --xattrs-include='*' -C /tmp/debian-{{ DIST }}-mm -xf /tmp/debian-{{ DIST }}-mm.tar
@ -30,27 +30,27 @@ tar -C /tmp/debian-{{ DIST }}-mm -cf /tmp/dev2.tar ./dev
ret=0 ret=0
cmp /tmp/dev1.tar /tmp/dev2.tar >&2 || ret=$? cmp /tmp/dev1.tar /tmp/dev2.tar >&2 || ret=$?
if [ "$ret" -ne 0 ]; then if [ "$ret" -ne 0 ]; then
if type diffoscope >/dev/null; then if type diffoscope >/dev/null; then
diffoscope /tmp/dev1.tar /tmp/dev2.tar diffoscope /tmp/dev1.tar /tmp/dev2.tar
exit 1 exit 1
else else
echo "no diffoscope installed" >&2 echo "no diffoscope installed" >&2
fi fi
if type base64 >/dev/null; then if type base64 >/dev/null; then
base64 /tmp/dev1.tar base64 /tmp/dev1.tar
base64 /tmp/dev2.tar base64 /tmp/dev2.tar
exit 1 exit 1
else else
echo "no base64 installed" >&2 echo "no base64 installed" >&2
fi fi
if type xxd >/dev/null; then if type xxd >/dev/null; then
xxd /tmp/dev1.tar xxd /tmp/dev1.tar
xxd /tmp/dev2.tar xxd /tmp/dev2.tar
exit 1 exit 1
else else
echo "no xxd installed" >&2 echo "no xxd installed" >&2
fi fi
exit 1 exit 1
fi fi
rm /tmp/dev1.tar /tmp/dev2.tar rm /tmp/dev1.tar /tmp/dev2.tar
rm -r /tmp/debian-{{ DIST }}-debootstrap/dev /tmp/debian-{{ DIST }}-mm/dev rm -r /tmp/debian-{{ DIST }}-debootstrap/dev /tmp/debian-{{ DIST }}-mm/dev
@ -61,15 +61,17 @@ rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/apt/archives/*.deb
rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/ldconfig/aux-cache rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/ldconfig/aux-cache
# remove logs # remove logs
rm /tmp/debian-{{ DIST }}-debootstrap/var/log/dpkg.log \ rm /tmp/debian-{{ DIST }}-debootstrap/var/log/dpkg.log \
/tmp/debian-{{ DIST }}-debootstrap/var/log/bootstrap.log \ /tmp/debian-{{ DIST }}-debootstrap/var/log/bootstrap.log \
/tmp/debian-{{ DIST }}-debootstrap/var/log/alternatives.log /tmp/debian-{{ DIST }}-debootstrap/var/log/alternatives.log
# remove *-old files # remove *-old files
rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/debconf/config.dat-old \ rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/debconf/config.dat-old \
/tmp/debian-{{ DIST }}-mm/var/cache/debconf/config.dat-old /tmp/debian-{{ DIST }}-mm/var/cache/debconf/config.dat-old
rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/debconf/templates.dat-old \ rm /tmp/debian-{{ DIST }}-debootstrap/var/cache/debconf/templates.dat-old \
/tmp/debian-{{ DIST }}-mm/var/cache/debconf/templates.dat-old /tmp/debian-{{ DIST }}-mm/var/cache/debconf/templates.dat-old
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status-old \ rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status-old \
/tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status-old /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status-old
rm -f /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/diversions-old \
/tmp/debian-{{ DIST }}-mm/var/lib/dpkg/diversions-old
# remove dpkg files # remove dpkg files
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/available rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/available
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/cmethopt rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/cmethopt
@ -77,50 +79,54 @@ rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/cmethopt
rm /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/arch rm /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/arch
# since we installed packages directly from the .deb files, Priorities differ # since we installed packages directly from the .deb files, Priorities differ
# thus we first check for equality and then remove the files # thus we first check for equality and then remove the files
chroot /tmp/debian-{{ DIST }}-debootstrap dpkg --list > /tmp/dpkg1 chroot /tmp/debian-{{ DIST }}-debootstrap dpkg --list >/tmp/dpkg1
chroot /tmp/debian-{{ DIST }}-mm dpkg --list > /tmp/dpkg2 chroot /tmp/debian-{{ DIST }}-mm dpkg --list >/tmp/dpkg2
diff -u /tmp/dpkg1 /tmp/dpkg2 >&2 diff -u /tmp/dpkg1 /tmp/dpkg2 >&2
rm /tmp/dpkg1 /tmp/dpkg2 rm /tmp/dpkg1 /tmp/dpkg2
grep -v '^Priority: ' /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status > /tmp/status1 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 }}-mm/var/lib/dpkg/status >/tmp/status2
diff -u /tmp/status1 /tmp/status2 >&2 diff -u /tmp/status1 /tmp/status2 >&2
rm /tmp/status1 /tmp/status2 rm /tmp/status1 /tmp/status2
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/status /tmp/debian-{{ DIST }}-mm/var/lib/dpkg/status
# debootstrap exposes the hosts's kernel version # debootstrap exposes the hosts's kernel version
if [ -e /tmp/debian-{{ DIST }}-debootstrap/etc/apt/apt.conf.d/01autoremove-kernels ]; then if [ -e /tmp/debian-{{ DIST }}-debootstrap/etc/apt/apt.conf.d/01autoremove-kernels ]; then
rm /tmp/debian-{{ DIST }}-debootstrap/etc/apt/apt.conf.d/01autoremove-kernels rm /tmp/debian-{{ DIST }}-debootstrap/etc/apt/apt.conf.d/01autoremove-kernels
fi fi
if [ -e /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels ]; then if [ -e /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels ]; then
rm /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels rm /tmp/debian-{{ DIST }}-mm/etc/apt/apt.conf.d/01autoremove-kernels
fi fi
# clear out /run except for /run/lock # clear out /run except for /run/lock
find /tmp/debian-{{ DIST }}-debootstrap/run/ -mindepth 1 -maxdepth 1 ! -name lock -print0 | xargs --no-run-if-empty -0 rm -r find /tmp/debian-{{ DIST }}-debootstrap/run/ -mindepth 1 -maxdepth 1 ! -name lock -print0 | xargs --no-run-if-empty -0 rm -r
# debootstrap doesn't clean apt # debootstrap doesn't clean apt
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_main_binary-{{ HOSTARCH }}_Packages \ rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_main_binary-{{ HOSTARCH }}_Packages \
/tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_InRelease \ /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_InRelease \
/tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_Release \ /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_Release \
/tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_Release.gpg /tmp/debian-{{ DIST }}-debootstrap/var/lib/apt/lists/127.0.0.1_debian_dists_{{ DIST }}_Release.gpg
if [ "{{ VARIANT }}" = "-" ]; then if [ "{{ VARIANT }}" = "-" ]; then
rm /tmp/debian-{{ DIST }}-debootstrap/etc/machine-id rm /tmp/debian-{{ DIST }}-debootstrap/etc/machine-id
rm /tmp/debian-{{ DIST }}-mm/etc/machine-id rm /tmp/debian-{{ DIST }}-mm/etc/machine-id
rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/systemd/catalog/database rm /tmp/debian-{{ DIST }}-debootstrap/var/lib/systemd/catalog/database
rm /tmp/debian-{{ DIST }}-mm/var/lib/systemd/catalog/database rm /tmp/debian-{{ DIST }}-mm/var/lib/systemd/catalog/database
cap=$(chroot /tmp/debian-{{ DIST }}-debootstrap /sbin/getcap /bin/ping) case {{ DIST }} in oldstable | stable)
expected="/bin/ping cap_net_raw=ep" cap=$(chroot /tmp/debian-{{ DIST }}-debootstrap /sbin/getcap /bin/ping)
if [ "$cap" != "$expected" ]; then expected="/bin/ping cap_net_raw=ep"
echo "expected bin/ping to have capabilities $expected" >&2 if [ "$cap" != "$expected" ]; then
echo "but debootstrap produced: $cap" >&2 echo "expected bin/ping to have capabilities $expected" >&2
exit 1 echo "but debootstrap produced: $cap" >&2
fi exit 1
cap=$(chroot /tmp/debian-{{ DIST }}-mm /sbin/getcap /bin/ping) fi
if [ "$cap" != "$expected" ]; then cap=$(chroot /tmp/debian-{{ DIST }}-mm /sbin/getcap /bin/ping)
echo "expected bin/ping to have capabilities $expected" >&2 if [ "$cap" != "$expected" ]; then
echo "but mmdebstrap produced: $cap" >&2 echo "expected bin/ping to have capabilities $expected" >&2
exit 1 echo "but mmdebstrap produced: $cap" >&2
fi exit 1
fi
;;
esac
fi fi
rm /tmp/debian-{{ DIST }}-mm/var/cache/apt/archives/lock 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/extended_states
rm /tmp/debian-{{ DIST }}-mm/var/lib/apt/lists/lock rm /tmp/debian-{{ DIST }}-mm/var/lib/apt/lists/lock
@ -128,77 +134,100 @@ rm /tmp/debian-{{ DIST }}-mm/var/lib/apt/lists/lock
# the list of shells might be sorted wrongly # the list of shells might be sorted wrongly
# /var/lib/dpkg/triggers/File might be sorted wrongly # /var/lib/dpkg/triggers/File might be sorted wrongly
for f in "/var/lib/dpkg/triggers/File" "/etc/shells"; do for f in "/var/lib/dpkg/triggers/File" "/etc/shells"; do
f1="/tmp/debian-{{ DIST }}-debootstrap/$f" f1="/tmp/debian-{{ DIST }}-debootstrap/$f"
f2="/tmp/debian-{{ DIST }}-mm/$f" f2="/tmp/debian-{{ DIST }}-mm/$f"
# both chroots must have the file # both chroots must have the file
if [ ! -e "$f1" ] || [ ! -e "$f2" ]; then if [ ! -e "$f1" ] || [ ! -e "$f2" ]; then
continue continue
fi fi
# the file must be different # the file must be different
if cmp "$f1" "$f2" >&2; then if cmp "$f1" "$f2" >&2; then
continue continue
fi fi
# then sort both # then sort both
sort -o "$f1" "$f1" sort -o "$f1" "$f1"
sort -o "$f2" "$f2" sort -o "$f2" "$f2"
done done
# Because of unreproducible uids (#969631) we created the _apt user ourselves # Because of unreproducible uids (#969631) we created the _apt user ourselves
# and because passwd is not Essential:yes we didn't use useradd. But newer # and because passwd is not Essential:yes we didn't use useradd. But newer
# versions of adduser and shadow will create a different /etc/shadow # versions of adduser and shadow will create a different /etc/shadow
if [ "{{ VARIANT }}" = "-" ] && [ "{{ DIST}}" = oldstable ]; then if [ "{{ VARIANT }}" = "-" ] && [ "{{ DIST}}" = oldstable ]; then
for f in shadow shadow-; do for f in shadow shadow-; do
if grep -q '^_apt:!:' /tmp/debian-{{ DIST }}-debootstrap/etc/$f; then if grep -q '^_apt:!:' /tmp/debian-{{ DIST }}-debootstrap/etc/$f; then
sed -i 's/^_apt:\*:\([^:]\+\):0:99999:7:::$/_apt:!:\1::::::/' /tmp/debian-{{ DIST }}-mm/etc/$f sed -i 's/^_apt:\*:\([^:]\+\):0:99999:7:::$/_apt:!:\1::::::/' /tmp/debian-{{ DIST }}-mm/etc/$f
fi fi
done done
fi fi
for log in faillog lastlog; do for log in faillog lastlog; do
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /tmp/debian-{{ DIST }}-mm/var/log/$log >&2;then f1="/tmp/debian-{{ DIST }}-debootstrap/var/log/$log"
# if the files differ, make sure they are all zeroes f2="/tmp/debian-{{ DIST }}-mm/var/log/$log"
cmp -n "$(stat -c %s "/tmp/debian-{{ DIST }}-debootstrap/var/log/$log")" "/tmp/debian-{{ DIST }}-debootstrap/var/log/$log" /dev/zero >&2 # skip cmp if file is absent in both chroots
cmp -n "$(stat -c %s "/tmp/debian-{{ DIST }}-mm/var/log/$log")" "/tmp/debian-{{ DIST }}-mm/var/log/$log" /dev/zero >&2 if [ ! -e "$f1" ] && [ ! -e "$f2" ]; then
# then delete them continue
rm /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /tmp/debian-{{ DIST }}-mm/var/log/$log fi
fi 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
# then delete them
rm "$f1" "$f2"
fi
done done
# the order in which systemd and cron get installed differ and thus the order
# of lines in /etc/group and /etc/gshadow differs
if [ "{{ VARIANT }}" = "-" ]; then if [ "{{ VARIANT }}" = "-" ]; then
for f in group group- gshadow gshadow-; do # the order in which systemd and cron get installed differ and thus the order
for d in mm debootstrap; do # of lines in /etc/group and /etc/gshadow differs
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak for f in group group- gshadow gshadow-; do
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f for d in mm debootstrap; do
done sort /tmp/debian-{{ DIST }}-$d/etc/$f >/tmp/debian-{{ DIST }}-$d/etc/$f.bak
done mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
# the order in which systemd and passwd get installed differ and thus
# 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
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
# and since the order was different, ignore the *- files
for f in shadow- passwd-; do
for d in mm debootstrap; do
rm /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
fi fi
# since debootstrap 1.0.133 there is no tzdata in the buildd variant and thus # since debootstrap 1.0.133 there is no tzdata in the buildd variant and thus
# debootstrap creates its own /etc/localtime # debootstrap creates its own /etc/localtime
if [ "{{ VARIANT }}" = "buildd" ] && [ "{{ DIST }}" != "stable" ] && [ "{{ DIST }}" != "oldstable" ]; then if [ "{{ VARIANT }}" = "buildd" ] && [ "{{ DIST }}" != "stable" ] && [ "{{ DIST }}" != "oldstable" ]; then
[ "$(readlink /tmp/debian-{{ DIST }}-debootstrap/etc/localtime)" = /usr/share/zoneinfo/UTC ] [ "$(readlink /tmp/debian-{{ DIST }}-debootstrap/etc/localtime)" = /usr/share/zoneinfo/UTC ]
rm /tmp/debian-{{ DIST }}-debootstrap/etc/localtime rm /tmp/debian-{{ DIST }}-debootstrap/etc/localtime
fi fi
# starting with systemd 255 upstream dropped splitusr support and depending on # starting with systemd 255 upstream dropped splitusr support and depending on
# the installation order, symlink targets are prefixed with /usr or not # the installation order, symlink targets are prefixed with /usr or not
# See #1060000 and #1054137 # 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 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 for d in mm debootstrap; do
[ -L "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f" ] || continue [ -L "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f" ] || continue
oldlink="$(readlink "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f")" oldlink="$(readlink "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f")"
case $oldlink in case $oldlink in
/usr/*) : ;; /usr/*) : ;;
/*) oldlink="/usr$oldlink" ;; /*) oldlink="/usr$oldlink" ;;
*) echo unexpected >&2; exit 1 ;; *)
esac echo unexpected >&2
ln -sf "$oldlink" "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f" exit 1
done ;;
done esac
;; ln -sf "$oldlink" "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f"
done
done
;;
esac esac
# check if the file content differs # check if the file content differs
@ -209,14 +238,14 @@ diff --unified --no-dereference --recursive /tmp/debian-{{ DIST }}-debootstrap /
find /tmp/debian-{{ DIST }}-debootstrap /tmp/debian-{{ DIST }}-mm -type d -print0 | xargs -0 touch --date="@{{ SOURCE_DATE_EPOCH }}" find /tmp/debian-{{ DIST }}-debootstrap /tmp/debian-{{ DIST }}-mm -type d -print0 | xargs -0 touch --date="@{{ SOURCE_DATE_EPOCH }}"
# debootstrap never ran apt -- fixing permissions # debootstrap never ran apt -- fixing permissions
for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do
unmergedPATH="$PATH$(if [ "{{ DIST }}" = oldstable ]; then echo :/bin:/sbin; fi)" unmergedPATH="$PATH$(if [ "{{ DIST }}" = oldstable ]; then echo :/bin:/sbin; fi)"
PATH="$unmergedPATH" chroot /tmp/debian-{{ DIST }}-debootstrap chmod 0700 $d PATH="$unmergedPATH" chroot /tmp/debian-{{ DIST }}-debootstrap chmod 0700 $d
PATH="$unmergedPATH" chroot /tmp/debian-{{ DIST }}-debootstrap chown "$(id -u _apt):root" $d PATH="$unmergedPATH" chroot /tmp/debian-{{ DIST }}-debootstrap chown "$(id -u _apt):root" $d
done 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 }}-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 -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/root1.tar >/tmp/root1.tar.list
tar --full-time --verbose -tf /tmp/root2.tar > /tmp/root2.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 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 rm /tmp/root1.tar /tmp/root2.tar /tmp/root1.tar.list /tmp/root2.tar.list

View file

@ -5,23 +5,23 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
trap "rm -f /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}" EXIT INT TERM 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= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} {{ MIRROR }}
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} \ cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} \
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} || diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}
# we cannot test chrootless mode here, because mmdebstrap relies on the # we cannot test chrootless mode here, because mmdebstrap relies on the
# usrmerge package to set up merged-/usr and that doesn't work in chrootless # usrmerge package to set up merged-/usr and that doesn't work in chrootless

View file

@ -2,15 +2,41 @@
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
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
# DPKG_ROOT 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 }} --hook-dir=./hooks/merged-usr \ {{ CMD }} --mode=$MODE --variant={{ VARIANT }} \
${INCLUDE:+--include="$INCLUDE"} --skip=check/chrootless \ ${INCLUDE:+--include="$INCLUDE"} --skip=check/chrootless \
{{ DIST }} "/tmp/$MODE.tar" {{ MIRROR }} {{ DIST }} "/tmp/$MODE.tar" {{ MIRROR }}
done done
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

View file

@ -8,36 +8,34 @@ trap "rm -f /tmp/chrootless.tar /tmp/root.tar" EXIT INT TERM
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
MMTARFILTER= MMTARFILTER=
[ -x /usr/bin/mmtarfilter ] && MMTARFILTER=/usr/bin/mmtarfilter [ -x /usr/bin/mmtarfilter ] && MMTARFILTER=/usr/bin/mmtarfilter
[ -x ./tarfilter ] && MMTARFILTER=./tarfilter [ -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 # permissions drwxr-sr-x and extended attributes of ./var/log/journal/ cannot
# be preserved under fakeroot # be preserved under fakeroot
# this applies to 'z' lines in files in /usr/lib/tmpfiles.d/ # this applies to 'z' lines in files in /usr/lib/tmpfiles.d/
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
{{ CMD }} --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \ {{ CMD }} --variant={{ VARIANT }} \
${INCLUDE:+--include="$INCLUDE"} \ ${INCLUDE:+--include="$INCLUDE"} \
{{ DIST }} - {{ MIRROR }} \ {{ DIST }} - {{ MIRROR }} \
| "$MMTARFILTER" --path-exclude="/var/log/journal" --path-exclude="/etc/credstore*" \ | "$MMTARFILTER" --path-exclude="/var/log/journal" --path-exclude="/etc/credstore*" \
>/tmp/root.tar >/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"} \ ${INCLUDE:+--include="$INCLUDE"} \
{{ DIST }} - {{ MIRROR }} \ {{ DIST }} - {{ MIRROR }} \
| "$MMTARFILTER" --path-exclude="/var/log/journal" --path-exclude="/etc/credstore*" \ | "$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 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

View file

@ -4,65 +4,55 @@ 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" EXIT INT TERM
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
deb2qemu() { deb2qemu() {
case "$1" in case "$1" in
amd64) echo x86_64;; amd64) echo x86_64 ;;
arm64) echo aarch64;; arm64) echo aarch64 ;;
armel|armhf) echo arm;; armel | armhf) echo arm ;;
ppc64el) echo ppc64le;; ppc64el) echo ppc64le ;;
*) echo "$1";; *) echo "$1" ;;
esac esac
} }
if [ "$(dpkg --print-architecture)" = "arm64" ]; then if [ "$(dpkg --print-architecture)" = "arm64" ]; then
arch=amd64 arch=amd64
else else
arch=arm64 arch=arm64
fi 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")" ]
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand echo 1 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
# DPKG_ROOT arch-test "$arch"
# {{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \
# dpkg is unable to install architecture arch:all packages with a ${INCLUDE:+--include="$INCLUDE"} \
# dependency on an arch:any package (perl-modules-5.34 in this case) {{ DIST }} "/tmp/root.tar" {{ MIRROR }}
# inside foreign architecture chrootless chroots, because dpkg will use echo 0 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
# its own architecture as the native architecture, see #825385 and #1020533 arch-test "$arch" && exit 1
# So we are not testing the installation of apt,build-essential here. {{ CMD }} --mode=chrootless --architecture="$arch" --variant={{ VARIANT }} \
for INCLUDE in '' 'apt' 'systemd-sysv'; do ${INCLUDE:+--include="$INCLUDE"} \
echo 1 > "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" --skip=check/chrootless {{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }}
arch-test "$arch" # when creating a foreign architecture chroot, the tarballs are not
{{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \ # bit-by-bit identical but contain a few remaining differences:
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \ #
{{ DIST }} "/tmp/root.tar" {{ MIRROR }} # * /etc/ld.so.cache -- hard problem, must be solved in glibc upstream
echo 0 > "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" # * /var/lib/dpkg/triggers -- #990712
arch-test "$arch" && exit 1 # * /var/cache/debconf/*.dat-old -- needs investigation
{{ CMD }} --mode=chrootless --architecture="$arch" --variant={{ VARIANT }} \ for tar in root chrootless; do
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \ ./tarfilter <"/tmp/$tar.tar" \
--skip=check/chrootless {{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }} --path-exclude=/var/cache/debconf/config.dat-old \
# when creating a foreign architecture chroot, the tarballs are not --path-exclude=/var/cache/debconf/templates.dat-old \
# bit-by-bit identical but contain a few remaining differences: --path-exclude=/etc/ld.so.cache \
# --path-exclude=/var/lib/dpkg/triggers/File \
# * /etc/ld.so.cache -- hard problem, must be solved in glibc upstream --path-exclude=/var/lib/dpkg/triggers/ldconfig \
# * /var/lib/dpkg/triggers -- #990712 >"/tmp/$tar.tar.tmp"
# * /var/cache/debconf/*.dat-old -- needs investigation mv "/tmp/$tar.tar.tmp" "/tmp/$tar.tar"
for tar in root chrootless; do done
<"/tmp/$tar.tar" \ cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
./tarfilter \ rm /tmp/chrootless.tar /tmp/root.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"
mv "/tmp/$tar.tar.tmp" "/tmp/$tar.tar"
done
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
rm /tmp/chrootless.tar /tmp/root.tar
done done

View file

@ -7,21 +7,21 @@ 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 }}
if [ ! -e /mmdebstrap-testenv ]; then 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 echo "this test requires the cache directory to be mounted on /mnt and should only be run inside a container" >&2
exit 1 exit 1
fi fi
tmpdir=$(mktemp -d) tmpdir=$(mktemp -d)
trap 'rm -f "$tmpdir"/*.deb /tmp/orig.tar /tmp/test1.tar /tmp/test2.tar; rmdir "$tmpdir"' EXIT INT TERM trap 'rm -f "$tmpdir"/*.deb /tmp/orig.tar /tmp/test1.tar /tmp/test2.tar; rmdir "$tmpdir"' EXIT INT TERM
include="--include=doc-debian" include="--include=doc-debian"
if [ "{{ VARIANT }}" = "custom" ]; then if [ "{{ VARIANT }}" = "custom" ]; then
include="$include,base-files,base-passwd,coreutils,dash,diffutils,dpkg,libc-bin,sed" include="$include,base-files,base-passwd,coreutils,dash,diffutils,dpkg,libc-bin,sed"
fi fi
{{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \ {{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \
--setup-hook='mkdir -p "$1"/var/cache/apt/archives/partial' \ --setup-hook='mkdir -p "$1"/var/cache/apt/archives/partial' \
--setup-hook='touch "$1"/var/cache/apt/archives/lock' \ --setup-hook='touch "$1"/var/cache/apt/archives/lock' \
--setup-hook='chmod 0640 "$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 # 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 # 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 - # to reproduce, try: tar --directory /mnt/cache/debian/pool/main/d/doc-debian/ --create --file - . | tar --directory /tmp/ --extract --file -
@ -30,15 +30,15 @@ fi
# another reason to copy the files into a new directory is, that we can use shell globs # another reason to copy the files into a new directory is, that we can use shell globs
cp /mnt/cache/debian/pool/main/b/busybox/busybox_*"_{{ HOSTARCH }}.deb" /mnt/cache/debian/pool/main/a/apt/apt_*"_{{ HOSTARCH }}.deb" "$tmpdir" cp /mnt/cache/debian/pool/main/b/busybox/busybox_*"_{{ HOSTARCH }}.deb" /mnt/cache/debian/pool/main/a/apt/apt_*"_{{ HOSTARCH }}.deb" "$tmpdir"
{{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \ {{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \
--setup-hook='mkdir -p "$1"/var/cache/apt/archives/partial' \ --setup-hook='mkdir -p "$1"/var/cache/apt/archives/partial' \
--setup-hook='sync-in "'"$tmpdir"'" /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 cmp /tmp/orig.tar /tmp/test1.tar
{{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \ {{ CMD }} $include --mode={{ MODE }} --variant={{ VARIANT }} \
--customize-hook='touch "$1"/var/cache/apt/archives/partial' \ --customize-hook='touch "$1"/var/cache/apt/archives/partial' \
--setup-hook='mkdir -p "$1"/var/cache/apt/archives/' \ --setup-hook='mkdir -p "$1"/var/cache/apt/archives/' \
--setup-hook='sync-in "'"$tmpdir"'" /var/cache/apt/archives/' \ --setup-hook='sync-in "'"$tmpdir"'" /var/cache/apt/archives/' \
--setup-hook='chmod 0755 "$1"/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' \ --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 cmp /tmp/orig.tar /tmp/test2.tar

View file

@ -2,8 +2,8 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then 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 echo "this test requires the cache directory to be mounted on /mnt and should only be run inside a container" >&2
exit 1 exit 1
fi fi
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar "deb copy:///mnt/cache/debian {{ DIST }} main" {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar "deb copy:///mnt/cache/debian {{ DIST }} main"
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

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

View file

@ -2,10 +2,10 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
{{ CMD }} --mode={{ MODE }} --dry-run --variant=apt \ {{ CMD }} --mode={{ MODE }} --dry-run --variant=apt \
--setup-hook="exit 1" \ --setup-hook="exit 1" \
--essential-hook="exit 1" \ --essential-hook="exit 1" \
--customize-hook="exit 1" \ --customize-hook="exit 1" \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
rm /tmp/debian-chroot/dev/console rm /tmp/debian-chroot/dev/console
rm /tmp/debian-chroot/dev/fd rm /tmp/debian-chroot/dev/fd
rm /tmp/debian-chroot/dev/full rm /tmp/debian-chroot/dev/full

View file

@ -4,74 +4,77 @@ export LC_ALL=C.UTF-8
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
case "$(dpkg --print-architecture)" in case "$(dpkg --print-architecture)" in
arm64) arm64)
native_arch=arm64 native_arch=arm64
native_gnu=aarch64-linux-gnu native_gnu=aarch64-linux-gnu
foreign_arch=amd64 foreign_arch=amd64
foreign_gnu=x86_64-linux-gnu foreign_gnu=x86_64-linux-gnu
;; ;;
amd64) amd64)
native_arch=amd64 native_arch=amd64
native_gnu=x86_64-linux-gnu native_gnu=x86_64-linux-gnu
foreign_arch=arm64 foreign_arch=arm64
foreign_gnu=aarch64-linux-gnu foreign_gnu=aarch64-linux-gnu
;; ;;
*) *)
echo "unsupported native architecture" >&2 echo "unsupported native architecture" >&2
exit 1 exit 1
;; ;;
esac esac
[ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot" [ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot"
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures="$foreign_arch" \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --architectures="$foreign_arch" \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
# we ignore differences between architectures by ignoring some files # we ignore differences between architectures by ignoring some files
# and renaming others # and renaming others
{ tar -tf /tmp/debian-chroot.tar \ {
| grep -v '^\./usr/bin/i386$' \ tar -tf /tmp/debian-chroot.tar \
| grep -v '^\./usr/bin/x86_64$' \ | grep -v '^\./usr/bin/i386$' \
| grep -v '^\./lib64$' \ | grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./usr/lib64/$' \ | grep -v '^\./lib64$' \
| grep -v '^\./usr/lib64/ld-linux-x86-64\.so\.2$' \ | grep -v '^\./usr/lib64/$' \
| grep -v '^\./usr/lib/ld-linux-aarch64\.so\.1$' \ | grep -v '^\./usr/lib64/ld-linux-x86-64\.so\.2$' \
| grep -v "^\\./usr/lib/$foreign_gnu/ld-linux-aarch64\\.so\\.1$" \ | grep -v '^\./usr/lib/ld-linux-aarch64\.so\.1$' \
| grep -v "^\\./usr/lib/$foreign_gnu/ld-linux-x86-64\\.so\\.2$" \ | grep -v "^\\./usr/lib/$foreign_gnu/ld-linux-aarch64\\.so\\.1$" \
| grep -v "^\\./usr/lib/$foreign_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \ | grep -v "^\\./usr/lib/$foreign_gnu/ld-linux-x86-64\\.so\\.2$" \
| grep -v "^\\./usr/lib/$foreign_gnu/libmvec\\.so\\.1$" \ | grep -v "^\\./usr/lib/$foreign_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \
| grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$foreign_arch\\.gz$" \ | grep -v "^\\./usr/lib/$foreign_gnu/libmvec\\.so\\.1$" \
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \ | grep -v "^\\./usr/lib/$foreign_gnu/engines-3/padlock\\.so$" \
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$' \ | grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$foreign_arch\\.gz$" \
| sed "s/$foreign_gnu/$native_gnu/" \ | grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
| sed "s/$foreign_arch/$native_arch/"; | grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$' \
} | sort > /tmp/tar2.txt | sed "s/$foreign_gnu/$native_gnu/" \
{ < tar1.txt \ | sed "s/$foreign_arch/$native_arch/"
grep -v '^\./usr/bin/i386$' \ } | sort >/tmp/tar2.txt
| grep -v '^\./usr/bin/x86_64$' \ {
| grep -v '^\./lib32$' \ grep <tar1.txt -v '^\./usr/bin/i386$' \
| grep -v '^\./lib64$' \ | grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./libx32$' \ | grep -v '^\./lib32$' \
| grep -v '^\./usr/lib32/$' \ | grep -v '^\./lib64$' \
| grep -v '^\./usr/libx32/$' \ | grep -v '^\./libx32$' \
| grep -v '^\./usr/lib64/$' \ | grep -v '^\./usr/lib32/$' \
| grep -v '^\./usr/lib64/ld-linux-x86-64\.so\.2$' \ | grep -v '^\./usr/libx32/$' \
| grep -v '^\./usr/lib/ld-linux-aarch64\.so\.1$' \ | grep -v '^\./usr/lib64/$' \
| grep -v "^\\./usr/lib/$native_gnu/ld-linux-x86-64\\.so\\.2$" \ | grep -v '^\./usr/lib64/ld-linux-x86-64\.so\.2$' \
| grep -v "^\\./usr/lib/$native_gnu/ld-linux-aarch64\\.so\\.1$" \ | grep -v '^\./usr/lib/ld-linux-aarch64\.so\.1$' \
| grep -v "^\\./usr/lib/$native_gnu/libmvec\\.so\\.1$" \ | grep -v "^\\./usr/lib/$native_gnu/ld-linux-x86-64\\.so\\.2$" \
| grep -v "^\\./usr/lib/$native_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \ | grep -v "^\\./usr/lib/$native_gnu/ld-linux-aarch64\\.so\\.1$" \
| grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$native_arch\\.gz$" \ | grep -v "^\\./usr/lib/$native_gnu/libmvec\\.so\\.1$" \
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \ | grep -v "^\\./usr/lib/$native_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$'; | 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$'
} | sort | diff -u - /tmp/tar2.txt >&2 } | sort | diff -u - /tmp/tar2.txt >&2
rm /tmp/debian-chroot.tar /tmp/tar2.txt rm /tmp/debian-chroot.tar /tmp/tar2.txt

View file

@ -4,14 +4,14 @@ export LC_ALL=C.UTF-8
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar.gz {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar.gz {{ MIRROR }}

View file

@ -8,20 +8,20 @@ export LC_ALL=C.UTF-8
prefix= prefix=
include=, include=,
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != root ] && [ "{{ MODE }}" != auto ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != root ] && [ "{{ MODE }}" != auto ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
if [ "{{ VARIANT }}" = extract ] || [ "{{ VARIANT }}" = custom ]; then if [ "{{ VARIANT }}" = extract ] || [ "{{ VARIANT }}" = custom ]; then
include="$(tr '\n' ',' < pkglist.txt)" include="$(tr '\n' ',' <pkglist.txt)"
fi fi
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --include="$include" --dry-run --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --include="$include" --dry-run --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
if [ -e /tmp/debian-chroot.tar ]; then if [ -e /tmp/debian-chroot.tar ]; then
echo "/tmp/debian-chroot.tar must not be created with --dry-run" >&2 echo "/tmp/debian-chroot.tar must not be created with --dry-run" >&2
exit 1 exit 1
fi fi

View file

@ -2,8 +2,8 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
mount -t tmpfs -o nodev,nosuid,size=400M tmpfs /tmp mount -t tmpfs -o nodev,nosuid,size=400M tmpfs /tmp
# use --customize-hook to exercise the mounting/unmounting code of block devices in root mode # use --customize-hook to exercise the mounting/unmounting code of block devices in root mode

View file

@ -6,27 +6,27 @@ export LC_ALL=C.UTF-8
[ {{ MODE }} = "unshare" ] [ {{ MODE }} = "unshare" ]
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
# https://www.etalabs.net/sh_tricks.html # 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') homedir=$($prefix sh -c 'cd && pwd')
# apt:test/integration/test-apt-key # 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" $prefix mkdir "$homedir/$TMPDIR_ADD"
# make sure the unshared user can traverse into the TMPDIR # make sure the unshared user can traverse into the TMPDIR
chmod 711 "$homedir" chmod 711 "$homedir"
# set permissions and sticky bit like the real /tmp # set permissions and sticky bit like the real /tmp
chmod 1777 "$homedir/$TMPDIR_ADD" chmod 1777 "$homedir/$TMPDIR_ADD"
$prefix env TMPDIR="$homedir/$TMPDIR_ADD" {{ CMD }} --mode={{ MODE }} --variant=apt \ $prefix env TMPDIR="$homedir/$TMPDIR_ADD" {{ CMD }} --mode={{ MODE }} --variant=apt \
--setup-hook='case "$1" in '"$(quote "$homedir/$TMPDIR_ADD/mmdebstrap.")"'??????????) exit 0;; *) echo "$1"; exit 1;; esac' \ --setup-hook='case "$1" in '"$(quote "$homedir/$TMPDIR_ADD/mmdebstrap.")"'??????????) exit 0;; *) echo "$1"; exit 1;; esac' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
# use rmdir as a quick check that nothing is remaining in TMPDIR # use rmdir as a quick check that nothing is remaining in TMPDIR
$prefix rmdir "$homedir/$TMPDIR_ADD" $prefix rmdir "$homedir/$TMPDIR_ADD"

View file

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

View file

@ -6,11 +6,11 @@ export LC_ALL=C.UTF-8
[ {{ MODE }} = "unshare" ] [ {{ MODE }} = "unshare" ]
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
@ -19,11 +19,11 @@ chmod 700 /tmp/debian-chroot
chown "${SUDO_USER:-user}:${SUDO_USER:-user}" /tmp/debian-chroot chown "${SUDO_USER:-user}:${SUDO_USER:-user}" /tmp/debian-chroot
set -- env --chdir=/tmp/debian-chroot set -- env --chdir=/tmp/debian-chroot
if [ "{{ CMD }}" = "./mmdebstrap" ]; then if [ "{{ CMD }}" = "./mmdebstrap" ]; then
set -- "$@" "$(realpath --canonicalize-existing ./mmdebstrap)" set -- "$@" "$(realpath --canonicalize-existing ./mmdebstrap)"
elif [ "{{ CMD }}" = "perl -MDevel::Cover=-silent,-nogcov ./mmdebstrap" ]; then elif [ "{{ CMD }}" = "perl -MDevel::Cover=-silent,-nogcov ./mmdebstrap" ]; then
set -- "$@" perl -MDevel::Cover=-silent,-nogcov "$(realpath --canonicalize-existing ./mmdebstrap)" set -- "$@" perl -MDevel::Cover=-silent,-nogcov "$(realpath --canonicalize-existing ./mmdebstrap)"
else else
set -- "$@" {{ CMD }} set -- "$@" {{ CMD }}
fi fi
$prefix "$@" --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} $prefix "$@" --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

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

View file

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

View file

@ -5,6 +5,12 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
tmpdir="$(mktemp -d)" tmpdir="$(mktemp -d)"
chmod 755 "$tmpdir" chmod 755 "$tmpdir"
debootstrap "$([ "{{ DIST }}" = oldstable ] && echo --no-merged-usr || echo --merged-usr)" --variant={{ VARIANT }} {{ DIST }} "$tmpdir" {{ MIRROR }} ret=0
tar --sort=name --mtime=@$SOURCE_DATE_EPOCH --clamp-mtime --numeric-owner --one-file-system --xattrs -C "$tmpdir" -c . > "./cache/debian-{{ DIST }}-{{ VARIANT }}.tar" debootstrap "$([ "{{ DIST }}" = oldstable ] && echo --no-merged-usr || echo --merged-usr)" --variant={{ VARIANT }} {{ DIST }} "$tmpdir" {{ MIRROR }} || ret=$?
if [ "$ret" -ne 0 ]; then
echo "E: debootstrap failed, dumping $tmpdir/debootstrap/debootstrap.log"
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"
rm -r "$tmpdir" rm -r "$tmpdir"

View file

@ -7,11 +7,9 @@ trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
# we use variant standard in verbose mode to see the maximum number of packages # 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 # that was chosen in case of USE_HOST_APT_CONFIG=yes
# we use variant important on arches where variant standard is not bit-by-bit case {{ VARIANT }} in standard) : ;; *) exit 1 ;; esac
# reproducible due to #1031276
case {{ VARIANT }} in standard|-) : ;; *) exit 1;; esac
{{ CMD }} --variant={{ VARIANT }} --debug {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ CMD }} --variant={{ VARIANT }} --debug {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar \ cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar \
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar || diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar

View file

@ -3,24 +3,24 @@ set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ {{ MODE }} != unshare ] && [ {{ MODE }} != root ]; then if [ {{ MODE }} != unshare ] && [ {{ MODE }} != root ]; then
echo "test requires root or unshare mode" >&2 echo "test requires root or unshare mode" >&2
exit 1 exit 1
fi fi
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
# this mimics what apt does in apt-pkg/deb/dpkgpm.cc/pkgDPkgPM::StartPtyMagic() # 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 #define _GNU_SOURCE
#include <stdlib.h> #include <stdlib.h>
@ -141,9 +141,9 @@ grep 'Can not write log' /tmp/log && fail=1
grep 'posix_openpt' /tmp/log && fail=1 grep 'posix_openpt' /tmp/log && fail=1
grep 'No such file or directory' /tmp/log && fail=1 grep 'No such file or directory' /tmp/log && fail=1
if [ $fail -eq 1 ]; then if [ $fail -eq 1 ]; then
echo "apt failed to write log:" >&2 echo "apt failed to write log:" >&2
cat /tmp/log >&2 cat /tmp/log >&2
exit 1 exit 1
fi fi
rm /tmp/test.c /tmp/log rm /tmp/test.c /tmp/log

View file

@ -6,7 +6,7 @@ trap "rm -rf /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode={{ MODE }} --variant=apt --format=directory {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ CMD }} --mode={{ MODE }} --variant=apt --format=directory {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
ftype=$(stat -c %F /tmp/debian-chroot.tar) ftype=$(stat -c %F /tmp/debian-chroot.tar)
if [ "$ftype" != directory ]; then if [ "$ftype" != directory ]; then
echo "expected directory but got: $ftype" >&2 echo "expected directory but got: $ftype" >&2
exit 1 exit 1
fi fi
tar -C /tmp/debian-chroot.tar --one-file-system -c . | tar -t | sort | diff -u tar1.txt - tar -C /tmp/debian-chroot.tar --one-file-system -c . | tar -t | sort | diff -u tar1.txt -

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 /usr/lib/apt/apt-helper download-file "{{ MIRROR }}/dists/{{ DIST }}/InRelease" InRelease
codename=$(awk '/^Codename: / { print $2; }' InRelease) codename=$(awk '/^Codename: / { print $2; }' InRelease)
{{ CMD }} --mode={{ MODE }} --variant=apt "$codename" /tmp/debian-chroot.tar {{ MIRROR }} {{ 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 \ tar --to-stdout --extract --file /tmp/debian-chroot.tar ./etc/apt/sources.list \
| diff -u /tmp/expected - | diff -u /tmp/expected -

View file

@ -2,9 +2,13 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/config" EXIT INT TERM 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 }} {{ 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 - 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 rm /tmp/debian-chroot/etc/dpkg/dpkg.cfg.d/99mmdebstrap
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort > 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 {
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 #!/bin/sh
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
cat << SCRIPT > /tmp/checkeatmydata.sh cat <<SCRIPT >/tmp/checkeatmydata.sh
#!/bin/sh #!/bin/sh
set -exu set -exu
cat << EOF | diff - "\$1"/usr/bin/dpkg cat << EOF | diff - "\$1"/usr/bin/dpkg
@ -12,32 +12,37 @@ EOF
SCRIPT SCRIPT
chmod +x /tmp/checkeatmydata.sh chmod +x /tmp/checkeatmydata.sh
# first four bytes: magic # first four bytes: magic
elfheader="\\177ELF" elfheader='\177ELF'
# fifth byte: bits # fifth byte: bits
case "$(dpkg-architecture -qDEB_HOST_ARCH_BITS)" in case "$(dpkg-architecture -qDEB_HOST_ARCH_BITS)" in
32) elfheader="$elfheader\\001";; 32) elfheader="$elfheader\\001" ;;
64) elfheader="$elfheader\\002";; 64) elfheader="$elfheader\\002" ;;
*) echo "bits not supported"; exit 1;; *)
echo "bits not supported"
exit 1
;;
esac esac
# sixth byte: endian # sixth byte: endian
case "$(dpkg-architecture -qDEB_HOST_ARCH_ENDIAN)" in case "$(dpkg-architecture -qDEB_HOST_ARCH_ENDIAN)" in
little) elfheader="$elfheader\\001";; little) elfheader="$elfheader\\001" ;;
big) elfheader="$elfheader\\002";; big) elfheader="$elfheader\\002" ;;
*) echo "endian not supported"; exit 1;; *)
echo "endian not supported"
exit 1
;;
esac esac
# seventh and eigth byte: elf version (1) and abi (unset) # seventh and eigth byte: elf version (1) and abi (unset)
elfheader="$elfheader\\001\\000" elfheader="$elfheader\\001\\000"
{{ CMD }} --mode=root --variant=apt \ {{ CMD }} --mode=root --variant=apt \
--customize-hook=/tmp/checkeatmydata.sh \ --customize-hook=/tmp/checkeatmydata.sh \
--essential-hook=/tmp/checkeatmydata.sh \ --essential-hook=/tmp/checkeatmydata.sh \
--extract-hook='printf "'"$elfheader"'" | cmp --bytes=8 - "$1"/usr/bin/dpkg' \ --extract-hook='printf "'"$elfheader"'" | cmp --bytes=8 - "$1"/usr/bin/dpkg' \
--hook-dir=./hooks/eatmydata \ --hook-dir=./hooks/eatmydata \
--customize-hook='printf "'"$elfheader"'" | cmp --bytes=8 - "$1"/usr/bin/dpkg' \ --customize-hook='printf "'"$elfheader"'" | cmp --bytes=8 - "$1"/usr/bin/dpkg' \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ 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 \ | tar -t \
| sort \ | sort \
| grep -v '^\./var/lib/dpkg/diversions\(-old\)\?$' \ | diff -u tar1.txt -
| diff -u tar1.txt -
rm /tmp/checkeatmydata.sh rm /tmp/checkeatmydata.sh
rm -r /tmp/debian-chroot rm -r /tmp/debian-chroot

View file

@ -3,6 +3,6 @@ set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
printf '' | {{ CMD }} --mode={{ MODE }} --variant=apt \ printf '' | {{ CMD }} --mode={{ MODE }} --variant=apt \
--setup-hook='echo "deb {{ MIRROR }} {{ DIST }} main" > "$1"/etc/apt/sources.list' \ --setup-hook='test -e "$1"/etc/apt/sources.list || echo "deb {{ MIRROR }} {{ DIST }} main" > "$1"/etc/apt/sources.list' \
{{ DIST }} /tmp/debian-chroot.tar - {{ DIST }} /tmp/debian-chroot.tar -
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | 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

@ -7,6 +7,6 @@ export LC_ALL=C.UTF-8
ret=0 ret=0
script -qfec "{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} - {{ MIRROR }}" /dev/null || ret=$? script -qfec "{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} - {{ MIRROR }}" /dev/null || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -2,7 +2,7 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -rf /tmp/debian-chroot; rm -f /tmp/essential.sh" EXIT INT TERM 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 #!/bin/sh
echo tzdata tzdata/Zones/Europe select Berlin | chroot "$1" debconf-set-selections echo tzdata tzdata/Zones/Europe select Berlin | chroot "$1" debconf-set-selections
SCRIPT SCRIPT
@ -10,12 +10,11 @@ chmod +x /tmp/essential.sh
{{ CMD }} --mode=root --variant=apt --include=tzdata --essential-hook='echo tzdata tzdata/Areas select Europe | chroot "$1" debconf-set-selections' --essential-hook=/tmp/essential.sh {{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ CMD }} --mode=root --variant=apt --include=tzdata --essential-hook='echo tzdata tzdata/Areas select Europe | chroot "$1" debconf-set-selections' --essential-hook=/tmp/essential.sh {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
[ "$(readlink /tmp/debian-chroot/etc/localtime)" = "/usr/share/zoneinfo/Europe/Berlin" ] [ "$(readlink /tmp/debian-chroot/etc/localtime)" = "/usr/share/zoneinfo/Europe/Berlin" ]
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort \ tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort \
| grep -v '^./etc/localtime' \ | grep -v '^./etc/localtime' \
| grep -v '^./etc/timezone' \ | grep -v '^./etc/timezone' \
| grep -v '^./usr/sbin/tzconfig' \ | grep -v '^./usr/sbin/tzconfig' \
| grep -v '^./usr/share/doc/tzdata' \ | grep -v '^./usr/share/doc/tzdata' \
| grep -v '^./usr/share/lintian/overrides/tzdata' \ | grep -v '^./usr/share/lintian/overrides/tzdata' \
| grep -v '^./usr/share/zoneinfo' \ | grep -v '^./usr/share/zoneinfo' \
| grep -v '^./var/lib/dpkg/info/tzdata.' \ | grep -v '^./var/lib/dpkg/info/tzdata.' \
| grep -v '^./var/lib/apt/extended_states$' \ | diff -u tar1.txt -
| diff -u tar1.txt -

View file

@ -8,6 +8,6 @@ touch /tmp/exists
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/exists {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/exists {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -8,6 +8,6 @@ touch /tmp/debian-chroot/lost+found/exists
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -8,6 +8,6 @@ touch /tmp/debian-chroot/exists
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -4,6 +4,6 @@ export LC_ALL=C.UTF-8
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} / {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} / {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -4,6 +4,6 @@ export LC_ALL=C.UTF-8
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar.lz4 {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar.lz4 {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -7,6 +7,6 @@ trap 'rm -rf /tmp/quoted\"path' EXIT INT TERM
ret=0 ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/quoted\"path {{ MIRROR }} || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/quoted\"path {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -2,15 +2,15 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir /home/user --create-home user useradd --home-dir /home/user --create-home user
rm /etc/subuid rm /etc/subuid
ret=0 ret=0
runuser -u user -- {{ CMD }} --mode=unshare --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$? runuser -u user -- {{ CMD }} --mode=unshare --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi
[ ! -e /tmp/debian-chroot ] [ ! -e /tmp/debian-chroot ]

View file

@ -2,16 +2,16 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir /home/user --create-home user 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 mv /etc/subuid.tmp /etc/subuid
ret=0 ret=0
runuser -u user -- {{ CMD }} --mode=unshare --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$? runuser -u user -- {{ CMD }} --mode=unshare --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$?
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi
[ ! -e /tmp/debian-chroot ] [ ! -e /tmp/debian-chroot ]

View file

@ -5,6 +5,6 @@ ret=0
{{ CMD }} --mode=root --variant=apt --customize-hook='chroot "$1" sh -c "exit 1"' {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$? {{ CMD }} --mode=root --variant=apt --customize-hook='chroot "$1" sh -c "exit 1"' {{ DIST }} /tmp/debian-chroot {{ MIRROR }} || ret=$?
rm -r /tmp/debian-chroot rm -r /tmp/debian-chroot
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -2,12 +2,12 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then 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 echo "this test requires the cache directory to be mounted on /mnt and should only be run inside a container" >&2
exit 1 exit 1
fi fi
{{ CMD }} --mode={{ MODE }} --variant=apt \ {{ CMD }} --mode={{ MODE }} --variant=apt \
--setup-hook='mkdir -p "$1"/mnt/cache/debian; mount -o ro,bind /mnt/cache/debian "$1"/mnt/cache/debian' \ --setup-hook='mkdir -p "$1"/mnt/cache/debian; mount -o ro,bind /mnt/cache/debian "$1"/mnt/cache/debian' \
--customize-hook='umount "$1"/mnt/cache/debian; rmdir "$1"/mnt/cache/debian "$1"/mnt/cache' \ --customize-hook='umount "$1"/mnt/cache/debian; rmdir "$1"/mnt/cache/debian "$1"/mnt/cache' \
{{ DIST }} /tmp/debian-chroot.tar "deb file:///mnt/cache/debian {{ DIST }} main" {{ DIST }} /tmp/debian-chroot.tar "deb file:///mnt/cache/debian {{ DIST }} main"
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar

View file

@ -2,19 +2,19 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then 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 echo "this test requires the cache directory to be mounted on /mnt and should only be run inside a container" >&2
exit 1 exit 1
fi 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 useradd --home-dir /home/user --create-home user
fi fi
prefix= prefix=
[ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && prefix="runuser -u user --" [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && prefix="runuser -u user --"
[ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot" [ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot"
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
--hook-dir=./hooks/file-mirror-automount \ --hook-dir=./hooks/file-mirror-automount \
--customize-hook='[ ! -e "$1"/mnt/cache/debian/ ] || rmdir "$1"/mnt/cache/debian/' \ --customize-hook='[ ! -e "$1"/mnt/cache/debian/ ] || rmdir "$1"/mnt/cache/debian/' \
--customize-hook='rmdir "$1"/mnt/cache' \ --customize-hook='rmdir "$1"/mnt/cache' \
{{ DIST }} /tmp/debian-chroot.tar "deb file:///mnt/cache/debian {{ DIST }} main" {{ DIST }} /tmp/debian-chroot.tar "deb file:///mnt/cache/debian {{ DIST }} main"
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar

View file

@ -2,48 +2,48 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
for h in hookA hookB; do for h in hookA hookB; do
mkdir /tmp/$h mkdir /tmp/$h
for s in setup extract essential customize; do for s in setup extract essential customize; do
cat << SCRIPT > /tmp/$h/${s}00.sh cat <<SCRIPT >/tmp/$h/${s}00.sh
#!/bin/sh #!/bin/sh
echo $h/${s}00 >> "\$1/$s" echo $h/${s}00 >> "\$1/$s"
SCRIPT SCRIPT
chmod +x /tmp/$h/${s}00.sh 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" echo $h/${s}01 >> "\$1/$s"
SCRIPT SCRIPT
chmod +x /tmp/$h/${s}01.sh chmod +x /tmp/$h/${s}01.sh
done done
done done
{{ CMD }} --mode=root --variant=apt \ {{ CMD }} --mode=root --variant=apt \
--setup-hook='echo cliA/setup >> "$1"/setup' \ --setup-hook='echo cliA/setup >> "$1"/setup' \
--extract-hook='echo cliA/extract >> "$1"/extract' \ --extract-hook='echo cliA/extract >> "$1"/extract' \
--essential-hook='echo cliA/essential >> "$1"/essential' \ --essential-hook='echo cliA/essential >> "$1"/essential' \
--customize-hook='echo cliA/customize >> "$1"/customize' \ --customize-hook='echo cliA/customize >> "$1"/customize' \
--hook-dir=/tmp/hookA \ --hook-dir=/tmp/hookA \
--setup-hook='echo cliB/setup >> "$1"/setup' \ --setup-hook='echo cliB/setup >> "$1"/setup' \
--extract-hook='echo cliB/extract >> "$1"/extract' \ --extract-hook='echo cliB/extract >> "$1"/extract' \
--essential-hook='echo cliB/essential >> "$1"/essential' \ --essential-hook='echo cliB/essential >> "$1"/essential' \
--customize-hook='echo cliB/customize >> "$1"/customize' \ --customize-hook='echo cliB/customize >> "$1"/customize' \
--hook-dir=/tmp/hookB \ --hook-dir=/tmp/hookB \
--setup-hook='echo cliC/setup >> "$1"/setup' \ --setup-hook='echo cliC/setup >> "$1"/setup' \
--extract-hook='echo cliC/extract >> "$1"/extract' \ --extract-hook='echo cliC/extract >> "$1"/extract' \
--essential-hook='echo cliC/essential >> "$1"/essential' \ --essential-hook='echo cliC/essential >> "$1"/essential' \
--customize-hook='echo cliC/customize >> "$1"/customize' \ --customize-hook='echo cliC/customize >> "$1"/customize' \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
printf "cliA/setup\nhookA/setup00\nhookA/setup01\ncliB/setup\nhookB/setup00\nhookB/setup01\ncliC/setup\n" | diff -u - /tmp/debian-chroot/setup printf "cliA/setup\nhookA/setup00\nhookA/setup01\ncliB/setup\nhookB/setup00\nhookB/setup01\ncliC/setup\n" | diff -u - /tmp/debian-chroot/setup
printf "cliA/extract\nhookA/extract00\nhookA/extract01\ncliB/extract\nhookB/extract00\nhookB/extract01\ncliC/extract\n" | diff -u - /tmp/debian-chroot/extract printf "cliA/extract\nhookA/extract00\nhookA/extract01\ncliB/extract\nhookB/extract00\nhookB/extract01\ncliC/extract\n" | diff -u - /tmp/debian-chroot/extract
printf "cliA/essential\nhookA/essential00\nhookA/essential01\ncliB/essential\nhookB/essential00\nhookB/essential01\ncliC/essential\n" | diff -u - /tmp/debian-chroot/essential printf "cliA/essential\nhookA/essential00\nhookA/essential01\ncliB/essential\nhookB/essential00\nhookB/essential01\ncliC/essential\n" | diff -u - /tmp/debian-chroot/essential
printf "cliA/customize\nhookA/customize00\nhookA/customize01\ncliB/customize\nhookB/customize00\nhookB/customize01\ncliC/customize\n" | diff -u - /tmp/debian-chroot/customize printf "cliA/customize\nhookA/customize00\nhookA/customize01\ncliB/customize\nhookB/customize00\nhookB/customize01\ncliC/customize\n" | diff -u - /tmp/debian-chroot/customize
for s in setup extract essential customize; do for s in setup extract essential customize; do
rm /tmp/debian-chroot/$s rm /tmp/debian-chroot/$s
done done
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt - tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
for h in hookA hookB; do for h in hookA hookB; do
for s in setup extract essential customize; do for s in setup extract essential customize; do
rm /tmp/$h/${s}00.sh rm /tmp/$h/${s}00.sh
rm /tmp/$h/${s}01.sh rm /tmp/$h/${s}01.sh
done done
rmdir /tmp/$h rmdir /tmp/$h
done done
rm -r /tmp/debian-chroot rm -r /tmp/debian-chroot

View file

@ -2,40 +2,41 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
# remove qemu just to be sure # remove qemu just to be sure
apt-get remove --yes qemu-user-static binfmt-support qemu-user apt-get remove --yes qemu-user-binfmt binfmt-support qemu-user
{{ CMD }} --mode={{ MODE }} --variant=apt --architectures=i386 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ CMD }} --mode={{ MODE }} --variant=apt --architectures=i386 {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
# we ignore differences between architectures by ignoring some files # we ignore differences between architectures by ignoring some files
# and renaming others # and renaming others
{ tar -tf /tmp/debian-chroot.tar \ {
| grep -v '^\./usr/bin/i386$' \ tar -tf /tmp/debian-chroot.tar \
| grep -v '^\./usr/lib/ld-linux\.so\.2$' \ | grep -v '^\./usr/bin/i386$' \
| grep -v '^\./usr/lib/i386-linux-gnu/ld-linux\.so\.2$' \ | grep -v '^\./usr/lib/ld-linux\.so\.2$' \
| grep -v '^\./usr/lib/gcc/i686-linux-gnu/$' \ | grep -v '^\./usr/lib/i386-linux-gnu/ld-linux\.so\.2$' \
| grep -v '^\./usr/lib/gcc/i686-linux-gnu/[0-9]\+/$' \ | grep -v '^\./usr/lib/gcc/i686-linux-gnu/$' \
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \ | grep -v '^\./usr/lib/gcc/i686-linux-gnu/[0-9]\+/$' \
| grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.i386\.gz$' \ | grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
| sed 's/i386-linux-gnu/x86_64-linux-gnu/' \ | grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.i386\.gz$' \
| sed 's/i386/amd64/' \ | sed 's/i386-linux-gnu/x86_64-linux-gnu/' \
| sed 's/\/stubs-32.ph$/\/stubs-64.ph/'; | sed 's/i386/amd64/' \
} | sort > tar2.txt | sed 's/\/stubs-32.ph$/\/stubs-64.ph/'
{ < tar1.txt \ } | sort >tar2.txt
grep -v '^\./usr/bin/i386$' \ {
| grep -v '^\./usr/bin/x86_64$' \ grep <tar1.txt -v '^\./usr/bin/i386$' \
| grep -v '^\./usr/lib32/$' \ | grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./lib32$' \ | grep -v '^\./usr/lib32/$' \
| grep -v '^\./lib64$' \ | grep -v '^\./lib32$' \
| grep -v '^\./usr/lib64/$' \ | grep -v '^\./lib64$' \
| grep -v '^\./usr/lib64/ld-linux-x86-64\.so\.2$' \ | grep -v '^\./usr/lib64/$' \
| grep -v '^\./usr/lib/gcc/x86_64-linux-gnu/$' \ | grep -v '^\./usr/lib64/ld-linux-x86-64\.so\.2$' \
| grep -v '^\./usr/lib/gcc/x86_64-linux-gnu/[0-9]\+/$' \ | grep -v '^\./usr/lib/gcc/x86_64-linux-gnu/$' \
| grep -v '^\./usr/lib/x86_64-linux-gnu/ld-linux-x86-64\.so\.2$' \ | grep -v '^\./usr/lib/gcc/x86_64-linux-gnu/[0-9]\+/$' \
| grep -v '^\./usr/lib/x86_64-linux-gnu/libmvec\.so\.1$' \ | grep -v '^\./usr/lib/x86_64-linux-gnu/ld-linux-x86-64\.so\.2$' \
| grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.amd64\.gz$' \ | grep -v '^\./usr/lib/x86_64-linux-gnu/libmvec\.so\.1$' \
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \ | grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.amd64\.gz$' \
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$'; | grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$'
} | sort | diff -u - tar2.txt >&2 } | sort | diff -u - tar2.txt >&2
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar

View file

@ -6,7 +6,6 @@ trap "rm -rf /tmp/debian-chroot" EXIT INT TERM
rm /tmp/debian-chroot/usr/share/doc-base/doc-debian.debian-* rm /tmp/debian-chroot/usr/share/doc-base/doc-debian.debian-*
rm -r /tmp/debian-chroot/usr/share/doc/debian rm -r /tmp/debian-chroot/usr/share/doc/debian
rm -r /tmp/debian-chroot/usr/share/doc/doc-debian rm -r /tmp/debian-chroot/usr/share/doc/doc-debian
rm /tmp/debian-chroot/var/lib/apt/extended_states
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.list rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.list
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.md5sums rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.md5sums
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt - tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -

View file

@ -7,21 +7,21 @@ trap "rm -rf /tmp/dummypkg.deb /tmp/dummypkg" EXIT INT TERM
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
# instead of obtaining a .deb from our cache, we create a new package because # instead of obtaining a .deb from our cache, we create a new package because
# otherwise apt might decide to download the package with the same name and # otherwise apt might decide to download the package with the same name and
# version from the cache instead of using the local .deb # version from the cache instead of using the local .deb
mkdir -p /tmp/dummypkg/DEBIAN mkdir -p /tmp/dummypkg/DEBIAN
cat << END > "/tmp/dummypkg/DEBIAN/control" cat <<END >"/tmp/dummypkg/DEBIAN/control"
Package: dummypkg Package: dummypkg
Priority: optional Priority: optional
Section: oldlibs Section: oldlibs
@ -35,6 +35,6 @@ END
dpkg-deb --build "/tmp/dummypkg" "/tmp/dummypkg.deb" dpkg-deb --build "/tmp/dummypkg" "/tmp/dummypkg.deb"
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include="/tmp/dummypkg.deb" \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include="/tmp/dummypkg.deb" \
--hook-dir=./hooks/file-mirror-automount \ --hook-dir=./hooks/file-mirror-automount \
--customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \ --customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \
{{ DIST }} /dev/null {{ MIRROR }} {{ DIST }} /dev/null {{ MIRROR }}

View file

@ -7,36 +7,38 @@
# - doesn't change its name regularly (like gcc-*-base) # - doesn't change its name regularly (like gcc-*-base)
case "$(dpkg --print-architecture)" in case "$(dpkg --print-architecture)" in
arm64) arm64)
native_arch=arm64 native_arch=arm64
foreign_arch=amd64 foreign_arch=amd64
;; ;;
amd64) amd64)
native_arch=amd64 native_arch=amd64
foreign_arch=arm64 foreign_arch=arm64
;; ;;
*) *)
echo "unsupported native architecture" >&2 echo "unsupported native architecture" >&2
exit 1 exit 1
;; ;;
esac esac
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
{{ CMD }} --mode=root --variant=apt \ {{ CMD }} --mode=root --variant=apt \
--architectures="$native_arch,$foreign_arch" \ --architectures="$native_arch,$foreign_arch" \
--include="libmagic-mgc:$foreign_arch" \ --include="libmagic-mgc:$foreign_arch" \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ 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/lib/file/magic.mgc
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz" rm -f /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz"
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright
rm /tmp/debian-chroot/usr/share/file/magic.mgc rm /tmp/debian-chroot/usr/share/file/magic.mgc
rm /tmp/debian-chroot/usr/share/misc/magic.mgc rm /tmp/debian-chroot/usr/share/misc/magic.mgc
rm /tmp/debian-chroot/var/lib/apt/extended_states
rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.list rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.list
rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.md5sums rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.md5sums
rmdir /tmp/debian-chroot/usr/share/doc/libmagic-mgc/ rmdir /tmp/debian-chroot/usr/share/doc/libmagic-mgc/

View file

@ -7,37 +7,39 @@
# - doesn't change its name regularly (like gcc-*-base) # - doesn't change its name regularly (like gcc-*-base)
case "$(dpkg --print-architecture)" in case "$(dpkg --print-architecture)" in
arm64) arm64)
native_arch=arm64 native_arch=arm64
foreign_arch=amd64 foreign_arch=amd64
;; ;;
amd64) amd64)
native_arch=amd64 native_arch=amd64
foreign_arch=arm64 foreign_arch=arm64
;; ;;
*) *)
echo "unsupported native architecture" >&2 echo "unsupported native architecture" >&2
exit 1 exit 1
;; ;;
esac esac
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
{{ CMD }} --mode=root --variant=apt \ {{ CMD }} --mode=root --variant=apt \
--architectures="$native_arch" \ --architectures="$native_arch" \
--architectures="$foreign_arch" \ --architectures="$foreign_arch" \
--include="libmagic-mgc:$foreign_arch" \ --include="libmagic-mgc:$foreign_arch" \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ 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/lib/file/magic.mgc
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz" rm -f /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz"
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright
rm /tmp/debian-chroot/usr/share/file/magic.mgc rm /tmp/debian-chroot/usr/share/file/magic.mgc
rm /tmp/debian-chroot/usr/share/misc/magic.mgc rm /tmp/debian-chroot/usr/share/misc/magic.mgc
rm /tmp/debian-chroot/var/lib/apt/extended_states
rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.list rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.list
rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.md5sums rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.md5sums
rmdir /tmp/debian-chroot/usr/share/doc/libmagic-mgc/ rmdir /tmp/debian-chroot/usr/share/doc/libmagic-mgc/

View file

@ -9,33 +9,33 @@ pkgs=base-files,base-passwd,busybox,debianutils,dpkg,libc-bin,mawk,tar
# existing files untouched. It has to run after extraction (otherwise there is # existing files untouched. It has to run after extraction (otherwise there is
# no busybox binary) and before first configuration # no busybox binary) and before first configuration
{{ CMD }} --mode=root --variant=custom \ {{ CMD }} --mode=root --variant=custom \
--include=$pkgs \ --include=$pkgs \
--setup-hook='mkdir -p "$1/bin"' \ --setup-hook='mkdir -p "$1/bin"' \
--setup-hook='echo root:x:0:0:root:/root:/bin/sh > "$1/etc/passwd"' \ --setup-hook='echo root:x:0:0:root:/root:/bin/sh > "$1/etc/passwd"' \
--setup-hook='printf "root:x:0:\nmail:x:8:\nutmp:x:43:\n" > "$1/etc/group"' \ --setup-hook='printf "root:x:0:\nmail:x:8:\nutmp:x:43:\n" > "$1/etc/group"' \
--extract-hook='chroot "$1" busybox --install -s' \ --extract-hook='chroot "$1" busybox --install -s' \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ 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 \ chroot /tmp/debian-chroot dpkg-query -f '${binary:Package}\n' -W \
| comm -12 - /tmp/expected \ | comm -12 - /tmp/expected \
| diff -u - /tmp/expected | diff -u - /tmp/expected
rm /tmp/expected rm /tmp/expected
for cmd in echo cat sed grep; do for cmd in echo cat sed grep; do
test -L /tmp/debian-chroot/bin/$cmd test -L /tmp/debian-chroot/bin/$cmd
test "$(readlink /tmp/debian-chroot/bin/$cmd)" = "/usr/bin/busybox" test "$(readlink /tmp/debian-chroot/bin/$cmd)" = "/usr/bin/busybox"
done done
for cmd in sort tee; do for cmd in sort tee; do
test -L /tmp/debian-chroot/usr/bin/$cmd test -L /tmp/debian-chroot/usr/bin/$cmd
test "$(readlink /tmp/debian-chroot/usr/bin/$cmd)" = "/usr/bin/busybox" test "$(readlink /tmp/debian-chroot/usr/bin/$cmd)" = "/usr/bin/busybox"
done done
# if /bin or /sbin are not symlinks, add /bin and /sbin to PATH # if /bin or /sbin are not symlinks, add /bin and /sbin to PATH
if [ ! -L /tmp/debian-chroot/bin ] || [ ! -L /tmp/debian-chroot/sbin ]; then if [ ! -L /tmp/debian-chroot/bin ] || [ ! -L /tmp/debian-chroot/sbin ]; then
export PATH="$PATH:/sbin:/bin" export PATH="$PATH:/sbin:/bin"
fi fi
chroot /tmp/debian-chroot echo foobar \ chroot /tmp/debian-chroot echo foobar \
| chroot /tmp/debian-chroot cat \ | chroot /tmp/debian-chroot cat \
| chroot /tmp/debian-chroot sort \ | chroot /tmp/debian-chroot sort \
| chroot /tmp/debian-chroot tee /dev/null \ | chroot /tmp/debian-chroot tee /dev/null \
| chroot /tmp/debian-chroot sed 's/foobar/blubber/' \ | chroot /tmp/debian-chroot sed 's/foobar/blubber/' \
| chroot /tmp/debian-chroot grep blubber >/dev/null | chroot /tmp/debian-chroot grep blubber >/dev/null

View file

@ -9,19 +9,19 @@ trap "rm -rf /tmp/debian-chroot" EXIT INT TERM
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --include=doc-debian {{ DIST }} /tmp/debian-chroot {{ MIRROR }} $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 -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 rm /tmp/debian-chroot.tar
# delete contents of doc-debian # delete contents of doc-debian
rm /tmp/debian-chroot/usr/share/doc-base/doc-debian.debian-* rm /tmp/debian-chroot/usr/share/doc-base/doc-debian.debian-*

View file

@ -8,14 +8,14 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --include=doc-debian {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --include=doc-debian {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}

View file

@ -10,14 +10,14 @@ trap "rm -rf /tmp/debian-chroot" EXIT INT TERM
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --skip=cleanup/tmp --variant={{ VARIANT }} --include=doc-debian --setup-hook='touch "$1/tmp/setup"' --customize-hook='touch "$1/tmp/customize"' {{ DIST }} /tmp/debian-chroot {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --skip=cleanup/tmp --variant={{ VARIANT }} --include=doc-debian --setup-hook='touch "$1/tmp/setup"' --customize-hook='touch "$1/tmp/customize"' {{ DIST }} /tmp/debian-chroot {{ MIRROR }}

View file

@ -7,27 +7,27 @@ export LC_ALL=C.UTF-8
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
case "$(dpkg --print-architecture)" in case "$(dpkg --print-architecture)" in
arm64) arm64)
foreign_arch=amd64 foreign_arch=amd64
;; ;;
amd64) amd64)
foreign_arch=arm64 foreign_arch=arm64
;; ;;
*) *)
echo "unsupported native architecture" >&2 echo "unsupported native architecture" >&2
exit 1 exit 1
;; ;;
esac esac
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --architectures="$foreign_arch" --include=libmagic-mgc {{ DIST }} /tmp/debian-chroot {{ MIRROR }} $prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --architectures="$foreign_arch" --include=libmagic-mgc {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
@ -37,7 +37,7 @@ rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright
rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz" rm -f /tmp/debian-chroot/usr/share/doc/libmagic-mgc/"changelog.Debian.$foreign_arch.gz"
rm /tmp/debian-chroot/usr/share/file/magic.mgc rm /tmp/debian-chroot/usr/share/file/magic.mgc
rm /tmp/debian-chroot/usr/share/misc/magic.mgc rm /tmp/debian-chroot/usr/share/misc/magic.mgc
# delete real files # delete real files

View file

@ -5,6 +5,6 @@ ret=0
{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}/invalid || ret=$? {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}/invalid || ret=$?
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

View file

@ -9,14 +9,14 @@ trap "rm -f /tmp/debian-chroot-{{ MODE }}.tar /tmp/debian-chroot-root-normal.tar
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
MMTARFILTER= MMTARFILTER=
@ -24,19 +24,20 @@ MMTARFILTER=
[ -x ./tarfilter ] && MMTARFILTER=./tarfilter [ -x ./tarfilter ] && MMTARFILTER=./tarfilter
filter() { filter() {
"$MMTARFILTER" \ "$MMTARFILTER" \
--path-exclude=/usr/bin/uncompress \ --path-exclude=/usr/bin/uncompress \
--path-exclude=/var/cache/debconf/config.dat-old \ --path-exclude=/var/cache/debconf/config.dat-old \
--path-exclude=/var/cache/debconf/templates.dat-old \ --path-exclude=/var/cache/debconf/templates.dat-old \
--path-exclude=/var/lib/dpkg/available \ --path-exclude=/var/lib/dpkg/available \
--path-exclude=/var/lib/dpkg/diversions \ --path-exclude=/var/lib/dpkg/diversions \
--path-exclude=/var/lib/dpkg/cmethopt \ --path-exclude=/var/lib/dpkg/diversions-old \
--path-exclude=/var/lib/dpkg/status-old \ --path-exclude=/var/lib/dpkg/cmethopt \
--path-exclude=/var/lib/shells.state --path-exclude=/var/lib/dpkg/status-old \
--path-exclude=/var/lib/shells.state
} }
# base for comparison without jessie-or-older hook # 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 $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 filter </tmp/debian-chroot-root-normal.tar | cmp - /tmp/debian-chroot-{{ MODE }}.tar

View file

@ -2,12 +2,12 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do
[ -e "$f" ] || continue [ -e "$f" ] || continue
rm "$f" rm "$f"
done done
rmdir /etc/apt/trusted.gpg.d rmdir /etc/apt/trusted.gpg.d
mkdir /etc/apt/trusted.gpg.d mkdir /etc/apt/trusted.gpg.d

View file

@ -10,6 +10,6 @@ ret=0
# make sure that no [signedby=...] managed to make it into the sources.list # make sure that no [signedby=...] managed to make it into the sources.list
echo "deb {{ MIRROR }} {{ DIST }} main" | cmp /tmp/debian-chroot/etc/apt/sources.list - echo "deb {{ MIRROR }} {{ DIST }} main" | cmp /tmp/debian-chroot/etc/apt/sources.list -
if [ "$ret" = 0 ]; then if [ "$ret" = 0 ]; then
echo expected failure but got exit $ret >&2 echo expected failure but got exit $ret >&2
exit 1 exit 1
fi fi

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 # 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 }} {{ CMD }} --mode=root --variant=apt --logfile=/tmp/log {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
# omit the last line which should contain the runtime # omit the last line which should contain the runtime
head --lines=-1 /tmp/log > /tmp/trimmed head --lines=-1 /tmp/log >/tmp/trimmed
cat << LOG | diff -u - /tmp/trimmed cat <<LOG | diff -u - /tmp/trimmed
I: chroot architecture {{ HOSTARCH }} is equal to the host's architecture I: chroot architecture {{ HOSTARCH }} is equal to the host's architecture
I: finding correct signed-by value... I: finding correct signed-by value...
I: automatically chosen format: directory I: automatically chosen format: directory
@ -16,6 +16,7 @@ I: running apt-get update...
I: downloading packages with apt... I: downloading packages with apt...
I: extracting archives... I: extracting archives...
I: installing essential packages... I: installing essential packages...
I: installing remaining packages inside the chroot...
I: cleaning package lists and apt cache... I: cleaning package lists and apt cache...
LOG LOG
tail --lines=1 /tmp/log | grep '^I: success in .* seconds$' tail --lines=1 /tmp/log | grep '^I: success in .* seconds$'

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 trap "rm -f /tmp/chroot-fakechroot.tar /tmp/chroot-root.tar" EXIT INT TERM
[ "$(whoami)" = "root" ] [ "$(whoami)" = "root" ]
{{ CMD }} --mode=root --variant=apt --hook-dir=./hooks/merged-usr {{ DIST }} /tmp/chroot-root.tar {{ MIRROR }} {{ 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 #!/bin/sh
set -exu set -exu
rootfs="$1" rootfs="$1"
@ -39,11 +39,11 @@ chroot "$rootfs" env --chdir=/mnt \
SCRIPT SCRIPT
chmod +x script.sh chmod +x script.sh
{{ CMD }} --mode=root --variant=apt --include=perl,python3,passwd,fakeroot,fakechroot \ {{ CMD }} --mode=root --variant=apt --include=perl,python3,passwd,fakeroot,fakechroot \
--hook-dir=./hooks/no-merged-usr \ --hook-dir=./hooks/no-merged-usr \
--customize-hook='chroot "$1" useradd --home-dir /home/user --create-home user' \ --customize-hook='chroot "$1" useradd --home-dir /home/user --create-home user' \
--customize-hook='chroot "$1" sh -c "exec test \"\$(realpath -e /usr/bin/ldd)\" = /usr/bin/ldd"' \ --customize-hook='chroot "$1" sh -c "exec test \"\$(realpath -e /usr/bin/ldd)\" = /usr/bin/ldd"' \
--customize-hook='chroot "$1" sh -c "exec test ! -e /usr/sbin/ldconfig"' \ --customize-hook='chroot "$1" sh -c "exec test ! -e /usr/sbin/ldconfig"' \
--customize-hook=./script.sh \ --customize-hook=./script.sh \
--customize-hook="copy-out /tmp/chroot-fakechroot.tar /tmp" \ --customize-hook="copy-out /tmp/chroot-fakechroot.tar /tmp" \
{{ DIST }} /dev/null {{ MIRROR }} {{ DIST }} /dev/null {{ MIRROR }}
cmp /tmp/chroot-fakechroot.tar /tmp/chroot-root.tar || diffoscope /tmp/chroot-fakechroot.tar /tmp/chroot-root.tar cmp /tmp/chroot-fakechroot.tar /tmp/chroot-root.tar || diffoscope /tmp/chroot-fakechroot.tar /tmp/chroot-root.tar

View file

@ -2,8 +2,8 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar /tmp/sources.list" EXIT INT TERM 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 {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar /tmp/sources.list
tar -tf /tmp/debian-chroot.tar \ tar -tf /tmp/debian-chroot.tar \
| sed 's#^./etc/apt/sources.list.d/0000sources.list$#./etc/apt/sources.list#' \ | sed 's#^./etc/apt/sources.list.d/0000sources.list$#./etc/apt/sources.list#' \
| sort | diff -u tar1.txt - | sort | diff -u tar1.txt -

View file

@ -7,14 +7,18 @@ export LC_ALL=C.UTF-8
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --include=dpkg,dash,diffutils,coreutils,libc-bin,sed {{ DIST }} /dev/null {{ MIRROR }} # do not install base-files, so that /proc, /sys and /dev are missing
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} \
--setup-hook='for dir in bin lib lib32 lib64 libo32 libx32 sbin; do ln -s "usr/$dir" "$1/$dir"; done' \
--include=dpkg,dash,diffutils,coreutils,libc-bin,sed \
{{ DIST }} /dev/null {{ MIRROR }}

View file

@ -2,8 +2,8 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
rm /dev/console rm /dev/console
useradd --home-dir /home/user --create-home user useradd --home-dir /home/user --create-home user

View file

@ -5,16 +5,27 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
[ "$(id -u)" -eq 0 ] [ "$(id -u)" -eq 0 ]
[ {{ MODE }} = "root" ] [ {{ MODE }} = "root" ]
case {{ FORMAT }} in tar|squashfs|ext2) : ;; *) exit 1;; esac case {{ FORMAT }} in tar | squashfs | ext2 | ext4) : ;; *) exit 1 ;; esac
{{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }} {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }}
# creating an ext4 image on a 9p filesystem produces different results compared
# to creating it on a tmpfs or ext4 fs because 9p does not support discards and
# even when running with -E nodiscard, the number of written bytes will differ
# https://lore.kernel.org/linux-ext4/171484520952.2626447.2160419274451668597@localhost/T/#t
mv /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }}
if [ "{{ FORMAT }}" = tar ]; then if [ "{{ FORMAT }}" = tar ]; then
printf 'ustar ' | cmp --bytes=6 --ignore-initial=257:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar - printf 'ustar\0' | cmp --bytes=6 --ignore-initial=257:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar -
elif [ "{{ FORMAT }}" = squashfs ]; then elif [ "{{ FORMAT }}" = squashfs ]; then
printf 'hsqs' | cmp --bytes=4 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.squashfs - printf 'hsqs' | cmp --bytes=4 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.squashfs -
elif [ "{{ FORMAT }}" = ext2 ]; then elif [ "{{ FORMAT }}" = ext2 ]; then
printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext2 - printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext2 -
printf '\000\000\000\000\000\000\000\000\000\000\000\000' | cmp --bytes=12 --ignore-initial=1116:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext2 -
elif [ "{{ FORMAT }}" = ext4 ]; then
printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4 -
printf '\074\020\000\000\302\042\000\000\153\004\000\000' | cmp --bytes=12 --ignore-initial=1116:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4 -
[ "$(/sbin/blkid --match-tag UUID --output value ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4)" = "$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name $SOURCE_DATE_EPOCH)" ]
else else
echo "unknown format: {{ FORMAT }}" >&2 echo "unknown format: {{ FORMAT }}" >&2
exit 1 exit 1
fi fi

View file

@ -2,11 +2,11 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
for p in /bin /usr/bin /sbin /usr/sbin; do for p in /bin /usr/bin /sbin /usr/sbin; do
rm -f "$p/mount" rm -f "$p/mount"
done done
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

@ -8,14 +8,14 @@ rm -r /tmp/debian-chroot/usr/share/doc/debian
rm -r /tmp/debian-chroot/usr/share/doc/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/usr/share/lintian/overrides/tzdata
rm /tmp/debian-chroot/etc/localtime 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/doc/tzdata
rm -r /tmp/debian-chroot/usr/share/zoneinfo rm -r /tmp/debian-chroot/usr/share/zoneinfo
rm /tmp/debian-chroot/var/lib/apt/extended_states
for p in doc-debian tzdata; do for p in doc-debian tzdata; do
for f in list md5sums config postinst postrm templates preinst prerm; do for f in list md5sums config postinst postrm templates preinst prerm; do
[ -e "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f" ] || continue [ -e "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f" ] || continue
rm "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f" rm "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f"
done done
done done
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt - tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -

View file

@ -14,14 +14,14 @@ trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix env PATH=/usr/bin:/bin fakechroot fakeroot {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} $prefix env PATH=/usr/bin:/bin fakechroot fakeroot {{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}

View file

@ -3,7 +3,7 @@ set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode={{ MODE }} --variant=essential --include=apt \ {{ CMD }} --mode={{ MODE }} --variant=essential --include=apt \
--essential-hook='APT_CONFIG=$MMDEBSTRAP_APT_CONFIG apt-get update' \ --essential-hook='APT_CONFIG=$MMDEBSTRAP_APT_CONFIG apt-get update' \
--essential-hook='APT_CONFIG=$MMDEBSTRAP_APT_CONFIG apt-get --yes install apt' \ --essential-hook='APT_CONFIG=$MMDEBSTRAP_APT_CONFIG apt-get --yes install apt' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | grep -v ./var/lib/apt/extended_states | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

@ -2,13 +2,13 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
cat << HOSTS >> /etc/hosts cat <<HOSTS >>/etc/hosts
127.0.0.1 deb.debian.org 127.0.0.1 deb.debian.org
127.0.0.1 security.debian.org 127.0.0.1 security.debian.org
HOSTS 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 - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar

View file

@ -6,49 +6,49 @@ trap "rm -f /tmp/chroot1.tar /tmp/chroot2.tar /tmp/chroot3.tar /tmp/mmdebstrap"
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" 2>/dev/null; then if ! id "${SUDO_USER:-user}" 2>/dev/null; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
--include=mount \ --include=mount,perl \
{{ DIST }} /tmp/chroot1.tar {{ MIRROR }} {{ DIST }} /tmp/chroot1.tar {{ MIRROR }}
if [ {{ MODE }} = "unshare" ]; then if [ {{ MODE }} = "unshare" ]; then
# calling pivot_root in root mode does not work for mysterious reasons: # calling pivot_root in root mode does not work for mysterious reasons:
# pivot_root: failed to change root from `.' to `mnt': Invalid argument # pivot_root: failed to change root from `.' to `mnt': Invalid argument
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include=mount \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include=mount,perl \
--customize-hook='mkdir -p "$1/mnt" "$1/oldroot"' \ --customize-hook='mkdir -p "$1/mnt" "$1/oldroot"' \
--customize-hook='[ ! -e /usr/bin/mmdebstrap ] || cp -aT /usr/bin/mmdebstrap "$1/usr/bin/mmdebstrap"' \ --customize-hook='[ ! -e /usr/bin/mmdebstrap ] || cp -aT /usr/bin/mmdebstrap "$1/usr/bin/mmdebstrap"' \
--customize-hook='[ ! -e ./mmdebstrap ] || cp -aT ./mmdebstrap "$1/mnt/mmdebstrap"' \ --customize-hook='[ ! -e ./mmdebstrap ] || cp -aT ./mmdebstrap "$1/mnt/mmdebstrap"' \
--customize-hook='mount -o rbind "$1" /mnt && cd /mnt && /sbin/pivot_root . oldroot' \ --customize-hook='mount -o rbind "$1" /mnt && cd /mnt && /sbin/pivot_root . oldroot' \
--customize-hook='unshare -U echo nested unprivileged unshare' \ --customize-hook='unshare -U echo nested unprivileged unshare' \
--customize-hook='env --chdir=/mnt {{ CMD }} --mode=unshare --variant=apt --include=mount {{ DIST }} /tmp/chroot3.tar {{ MIRROR }}' \ --customize-hook='env --chdir=/mnt {{ CMD }} --mode=unshare --variant=apt --include=mount,perl {{ DIST }} /tmp/chroot3.tar {{ MIRROR }}' \
--customize-hook='copy-out /tmp/chroot3.tar /tmp' \ --customize-hook='copy-out /tmp/chroot3.tar /tmp' \
--customize-hook='rm -f "/usr/bin/mmdebstrap" "/mnt/mmdebstrap"' \ --customize-hook='rm -f "/usr/bin/mmdebstrap" "/mnt/mmdebstrap"' \
--customize-hook='umount -l oldroot sys' \ --customize-hook='umount -l oldroot sys' \
--customize-hook='rmdir /oldroot' \ --customize-hook='rmdir /oldroot' \
{{ DIST }} /tmp/chroot2.tar {{ MIRROR }} {{ DIST }} /tmp/chroot2.tar {{ MIRROR }}
cmp /tmp/chroot1.tar /tmp/chroot2.tar || diffoscope /tmp/chroot1.tar /tmp/chroot2.tar cmp /tmp/chroot1.tar /tmp/chroot2.tar || diffoscope /tmp/chroot1.tar /tmp/chroot2.tar
cmp /tmp/chroot1.tar /tmp/chroot3.tar || diffoscope /tmp/chroot1.tar /tmp/chroot3.tar cmp /tmp/chroot1.tar /tmp/chroot3.tar || diffoscope /tmp/chroot1.tar /tmp/chroot3.tar
rm /tmp/chroot2.tar /tmp/chroot3.tar rm /tmp/chroot2.tar /tmp/chroot3.tar
fi fi
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include=mount \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include=mount,perl \
--customize-hook='mkdir -p "$1/mnt"' \ --customize-hook='mkdir -p "$1/mnt"' \
--customize-hook='[ ! -e /usr/bin/mmdebstrap ] || cp -aT /usr/bin/mmdebstrap "$1/usr/bin/mmdebstrap"' \ --customize-hook='[ ! -e /usr/bin/mmdebstrap ] || cp -aT /usr/bin/mmdebstrap "$1/usr/bin/mmdebstrap"' \
--customize-hook='[ ! -e ./mmdebstrap ] || cp -aT ./mmdebstrap "$1/mnt/mmdebstrap"' \ --customize-hook='[ ! -e ./mmdebstrap ] || cp -aT ./mmdebstrap "$1/mnt/mmdebstrap"' \
--chrooted-customize-hook='env --chdir=/mnt {{ CMD }} --mode=unshare --variant=apt --include=mount {{ DIST }} /tmp/chroot3.tar {{ MIRROR }}' \ --chrooted-customize-hook='env --chdir=/mnt {{ CMD }} --mode=unshare --variant=apt --include=mount,perl {{ DIST }} /tmp/chroot3.tar {{ MIRROR }}' \
--customize-hook='copy-out /tmp/chroot3.tar /tmp' \ --customize-hook='copy-out /tmp/chroot3.tar /tmp' \
--customize-hook='rm -f "$1/usr/bin/mmdebstrap" "$1/mnt/mmdebstrap"' \ --customize-hook='rm -f "$1/usr/bin/mmdebstrap" "$1/mnt/mmdebstrap"' \
{{ DIST }} /tmp/chroot2.tar {{ MIRROR }} {{ DIST }} /tmp/chroot2.tar {{ MIRROR }}
cmp /tmp/chroot1.tar /tmp/chroot2.tar || diffoscope /tmp/chroot1.tar /tmp/chroot2.tar cmp /tmp/chroot1.tar /tmp/chroot2.tar || diffoscope /tmp/chroot1.tar /tmp/chroot2.tar
cmp /tmp/chroot1.tar /tmp/chroot3.tar || diffoscope /tmp/chroot1.tar /tmp/chroot3.tar cmp /tmp/chroot1.tar /tmp/chroot3.tar || diffoscope /tmp/chroot1.tar /tmp/chroot3.tar

View file

@ -2,23 +2,23 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
for f in /etc/resolv.conf /etc/hostname; do for f in /etc/resolv.conf /etc/hostname; do
# preserve original content # preserve original content
cat "$f" > "$f.bak" cat "$f" >"$f.bak"
# in case $f is a symlink, we replace it by a real file # in case $f is a symlink, we replace it by a real file
if [ -L "$f" ]; then if [ -L "$f" ]; then
rm "$f" rm "$f"
cp "$f.bak" "$f" cp "$f.bak" "$f"
fi fi
chmod 644 "$f" chmod 644 "$f"
[ "$(stat --format=%A "$f")" = "-rw-r--r--" ] [ "$(stat --format=%A "$f")" = "-rw-r--r--" ]
done done
{{ CMD }} --variant=custom --mode={{ MODE }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ CMD }} --variant=custom --mode={{ MODE }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
for f in /etc/resolv.conf /etc/hostname; do for f in /etc/resolv.conf /etc/hostname; do
[ "$(stat --format=%A "/tmp/debian-chroot/$f")" = "-rw-r--r--" ] [ "$(stat --format=%A "/tmp/debian-chroot/$f")" = "-rw-r--r--" ]
done done
rm /tmp/debian-chroot/dev/console rm /tmp/debian-chroot/dev/console
rm /tmp/debian-chroot/dev/fd rm /tmp/debian-chroot/dev/fd
@ -42,12 +42,12 @@ rm /tmp/debian-chroot/var/lib/dpkg/arch
# the rest should be empty directories that we can rmdir recursively # the rest should be empty directories that we can rmdir recursively
find /tmp/debian-chroot -depth -print0 | xargs -0 rmdir find /tmp/debian-chroot -depth -print0 | xargs -0 rmdir
for f in /etc/resolv.conf /etc/hostname; do for f in /etc/resolv.conf /etc/hostname; do
chmod 755 "$f" chmod 755 "$f"
[ "$(stat --format=%A "$f")" = "-rwxr-xr-x" ] [ "$(stat --format=%A "$f")" = "-rwxr-xr-x" ]
done done
{{ CMD }} --variant=custom --mode={{ MODE }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ CMD }} --variant=custom --mode={{ MODE }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
for f in /etc/resolv.conf /etc/hostname; do for f in /etc/resolv.conf /etc/hostname; do
[ "$(stat --format=%A "/tmp/debian-chroot/$f")" = "-rwxr-xr-x" ] [ "$(stat --format=%A "/tmp/debian-chroot/$f")" = "-rwxr-xr-x" ]
done done
rm /tmp/debian-chroot/dev/console rm /tmp/debian-chroot/dev/console
rm /tmp/debian-chroot/dev/fd rm /tmp/debian-chroot/dev/fd
@ -71,13 +71,13 @@ rm /tmp/debian-chroot/var/lib/dpkg/arch
# the rest should be empty directories that we can rmdir recursively # the rest should be empty directories that we can rmdir recursively
find /tmp/debian-chroot -depth -print0 | xargs -0 rmdir find /tmp/debian-chroot -depth -print0 | xargs -0 rmdir
for f in /etc/resolv.conf /etc/hostname; do for f in /etc/resolv.conf /etc/hostname; do
rm "$f" rm "$f"
ln -s "$f.bak" "$f" ln -s "$f.bak" "$f"
[ "$(stat --format=%A "$f")" = "lrwxrwxrwx" ] [ "$(stat --format=%A "$f")" = "lrwxrwxrwx" ]
done done
{{ CMD }} --variant=custom --mode={{ MODE }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ CMD }} --variant=custom --mode={{ MODE }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
for f in /etc/resolv.conf /etc/hostname; do for f in /etc/resolv.conf /etc/hostname; do
[ "$(stat --format=%A "/tmp/debian-chroot/$f")" = "-rw-r--r--" ] [ "$(stat --format=%A "/tmp/debian-chroot/$f")" = "-rw-r--r--" ]
done done
rm /tmp/debian-chroot/dev/console rm /tmp/debian-chroot/dev/console
rm /tmp/debian-chroot/dev/fd rm /tmp/debian-chroot/dev/fd

View file

@ -2,5 +2,5 @@
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm /tmp/debian-chroot.tar" EXIT INT TERM 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 - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

@ -3,6 +3,6 @@ set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode={{ MODE }} --variant=apt \ {{ CMD }} --mode={{ MODE }} --variant=apt \
--customize-hook='rm "$1/usr/sbin/policy-rc.d"; rm "$1/usr/sbin/start-stop-daemon"' \ --customize-hook='rm "$1/usr/sbin/policy-rc.d"; rm "$1/usr/sbin/start-stop-daemon"' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - 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 trap "rm -f /tmp/debian-chroot.tar script.sh" EXIT INT TERM
cat << 'SCRIPT' > script.sh cat <<'SCRIPT' >script.sh
#!/bin/sh #!/bin/sh
set -exu set -exu
rootfs="$1" rootfs="$1"
@ -22,7 +22,7 @@ chroot "$rootfs" env --chdir=/mnt \
SCRIPT SCRIPT
chmod +x script.sh chmod +x script.sh
{{ CMD }} --mode=root --variant=apt --include=perl,mount \ {{ CMD }} --mode=root --variant=apt --include=perl,mount \
--customize-hook=./script.sh \ --customize-hook=./script.sh \
--customize-hook="download /tmp/debian-chroot.tar /tmp/debian-chroot.tar" \ --customize-hook="download /tmp/debian-chroot.tar /tmp/debian-chroot.tar" \
{{ DIST }} /dev/null {{ MIRROR }} {{ DIST }} /dev/null {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -

View file

@ -10,17 +10,17 @@ export LC_ALL=C.UTF-8
prefix= prefix=
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
if [ ! -e /mmdebstrap-testenv ]; then if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2 echo "this test modifies the system and should only be run inside a container" >&2
exit 1 exit 1
fi fi
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}" useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
fi fi
prefix="runuser -u ${SUDO_USER:-user} --" prefix="runuser -u ${SUDO_USER:-user} --"
fi fi
cat << 'SCRIPT' > /tmp/script.sh cat <<'SCRIPT' >/tmp/script.sh
#!/bin/sh #!/bin/sh
set -eu set -eu
rootfs="$1" rootfs="$1"
@ -33,8 +33,8 @@ chroot "$rootfs" env --chdir=/mnt \
SCRIPT SCRIPT
chmod +x /tmp/script.sh chmod +x /tmp/script.sh
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include=perl,mount \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include=perl,mount \
--customize-hook=/tmp/script.sh \ --customize-hook=/tmp/script.sh \
--customize-hook="download /tmp/debian-chroot.tar /tmp/debian-chroot.tar" \ --customize-hook="download /tmp/debian-chroot.tar /tmp/debian-chroot.tar" \
{{ DIST }} /dev/null {{ MIRROR }} {{ DIST }} /dev/null {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar /tmp/script.sh rm /tmp/debian-chroot.tar /tmp/script.sh

View file

@ -4,14 +4,14 @@ export LC_ALL=C.UTF-8
[ "$(whoami)" = "root" ] [ "$(whoami)" = "root" ]
if grep --null-data --quiet --no-messages '^container=lxc$' /proc/1/environ; then if grep --null-data --quiet --no-messages '^container=lxc$' /proc/1/environ; then
# see https://stackoverflow.com/questions/65748254/ # see https://stackoverflow.com/questions/65748254/
echo "cannot run under lxc -- Skipping test..." >&2 echo "cannot run under lxc -- Skipping test..." >&2
exit 0 exit 0
fi fi
capsh --drop=cap_sys_admin -- -c 'exec "$@"' exec \ capsh --drop=cap_sys_admin -- -c 'exec "$@"' exec \
{{ CMD }} --mode=root --variant=apt \ {{ CMD }} --mode=root --variant=apt \
--customize-hook='chroot "$1" sh -c "test ! -e /proc/self/fd"' \ --customize-hook='chroot "$1" sh -c "test ! -e /proc/self/fd"' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar

Some files were not shown because too many files have changed in this diff Show more