Compare commits

...

3 commits

108 changed files with 1950 additions and 1821 deletions

View file

@ -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 "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; echo) <(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

@ -28,23 +28,23 @@
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
# we need eval because we cannot redirect a variable fd # we need eval because we cannot redirect a variable fd

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 ext4 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,125 +177,125 @@ 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 gpg 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 usr-is-merged usrmerge" ;; *) pkgs="$pkgs usr-is-merged usrmerge" ;;
esac 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 \ || APT_CONFIG="$rootdir/etc/apt/apt.conf" apt-get --yes install \
-oDebug::pkgProblemResolver=true -oDebug::pkgDepCache::Marker=1 \ -oDebug::pkgProblemResolver=true -oDebug::pkgDepCache::Marker=1 \
-oDebug::pkgDepCache::AutoInstall=1 \ -oDebug::pkgDepCache::AutoInstall=1 \
$pkgs $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"
@ -319,12 +319,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" &
@ -332,13 +338,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
@ -349,9 +355,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
@ -359,43 +365,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
@ -405,73 +411,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-binfmt,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,squashfs-tools-ng,genext2fs,linux-image-generic,passwd,e2fsprogs,uuid-runtime pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-binfmt,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,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
@ -482,15 +488,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
@ -530,37 +536,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"' \
--customize-hook='touch "$1/etc/systemd/system/tmp.mount"' \ --customize-hook='touch "$1/etc/systemd/system/tmp.mount"' \
"$mirror" "$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

View file

@ -127,15 +127,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=|--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
@ -151,164 +151,164 @@ SCRIPT=
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_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=* | --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 | --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" usage_error "unrecognized argument $1"
;; ;;
*) *)
"positional_$positional" "$1" "positional_$positional" "$1"
positional=$((positional + 1)) positional=$((positional + 1))
;; ;;
esac esac
shift 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 LINUXIMAGE=linux-image-amd64
;; ;;
arm64) arm64)
EFIIMG=bootaa64.efi EFIIMG=bootaa64.efi
QEMUARCH=aarch64 QEMUARCH=aarch64
VMFPKG=qemu-efi-aarch64 VMFPKG=qemu-efi-aarch64
LINUXIMAGE=linux-image-arm64 LINUXIMAGE=linux-image-arm64
;; ;;
armhf) armhf)
EFIIMG=bootarm.efi EFIIMG=bootarm.efi
QEMUARCH=arm QEMUARCH=arm
VMFPKG=qemu-efi-arm VMFPKG=qemu-efi-arm
LINUXIMAGE=linux-image-armmp LINUXIMAGE=linux-image-armmp
;; ;;
i386) i386)
EFIIMG=bootia32.efi EFIIMG=bootia32.efi
QEMUARCH=i386 QEMUARCH=i386
VMFPKG=ovmf-ia32 VMFPKG=ovmf-ia32
LINUXIMAGE=linux-image-686-pae LINUXIMAGE=linux-image-686-pae
;; ;;
riscv64) riscv64)
EFIIMG=bootriscv64.efi EFIIMG=bootriscv64.efi
QEMUARCH=riscv64 QEMUARCH=riscv64
VMFPKG= VMFPKG=
LINUXIMAGE=linux-image-riscv64 LINUXIMAGE=linux-image-riscv64
;; ;;
*) *)
die "unsupported architecture: $ARCHITECTURE" 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= 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 _ -)"
BINUTILS=", binutils$GNU_SUFFIX | binutils-multiarch" BINUTILS=", binutils$GNU_SUFFIX | 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
test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed || test "$(dpkg-query -f '${db:Status-Status}' -W "dpkg-dev")" = installed \
die "please install dpkg-dev" || die "please install dpkg-dev"
dpkg-checkbuilddeps -d "autopkgtest, dosfstools, e2fsprogs, fdisk, mount, mtools, passwd, uidmap, libarchive13, systemd-boot-efi:$ARCHITECTURE $BINUTILS" /dev/null || dpkg-checkbuilddeps -d "autopkgtest, dosfstools, e2fsprogs, fdisk, mount, mtools, passwd, uidmap, libarchive13, systemd-boot-efi:$ARCHITECTURE $BINUTILS" /dev/null \
die "please install the required packages listed above" || die "please install the required packages listed above"
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
@ -321,44 +321,45 @@ FAT_SIZE_SECTORS=$((1024*254))
# custom options like compression # custom options like compression
set -- \ set -- \
--mode=unshare \ --mode=unshare \
--format=tar \ --format=tar \
--variant=important \ --variant=important \
--architecture="$ARCHITECTURE" --architecture="$ARCHITECTURE"
case $MIRROR in http://snapshot.debian.org/archive/*|https://snapshot.debian.org/archive/*) case $MIRROR in http://snapshot.debian.org/archive/* | https://snapshot.debian.org/archive/*)
set -- "$@" --aptopt='Acquire::Check-Valid-Until "false"';; set -- "$@" --aptopt='Acquire::Check-Valid-Until "false"'
;;
esac esac
EXT_FEATURES= EXT_FEATURES=
if test "$RELEASE" = jessie; then if test "$RELEASE" = jessie; then
set -- "$@" --keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg set -- "$@" --keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg
set -- "$@" --aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"' set -- "$@" --aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"'
set -- "$@" --hook-dir=/usr/share/mmdebstrap/hooks/jessie-or-older set -- "$@" --hook-dir=/usr/share/mmdebstrap/hooks/jessie-or-older
EXT_FEATURES="^metadata_csum,^metadata_csum_seed,^orphan_file" EXT_FEATURES="^metadata_csum,^metadata_csum_seed,^orphan_file"
fi fi
set -- "$@" \ set -- "$@" \
"--include=init,$LINUXIMAGE,python3" \ "--include=init,$LINUXIMAGE,python3" \
'--customize-hook=echo host >"$1/etc/hostname"' \ '--customize-hook=echo host >"$1/etc/hostname"' \
'--customize-hook=echo 127.0.0.1 localhost host >"$1/etc/hosts"' \ '--customize-hook=echo 127.0.0.1 localhost host >"$1/etc/hosts"' \
'--customize-hook=passwd --root "$1" --delete root' \ '--customize-hook=passwd --root "$1" --delete root' \
'--customize-hook=useradd --root "$1" --home-dir /home/user --create-home user' \ '--customize-hook=useradd --root "$1" --home-dir /home/user --create-home user' \
'--customize-hook=passwd --root "$1" --delete user' \ '--customize-hook=passwd --root "$1" --delete user' \
'--customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed' '--customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed'
if test -n "$SCRIPT"; then if test -n "$SCRIPT"; then
set -- "$@" \ set -- "$@" \
"--customize-hook=upload '$SCRIPT' /userscript" \ "--customize-hook=upload '$SCRIPT' /userscript" \
"--chrooted-customize-hook=sh /userscript" \ "--chrooted-customize-hook=sh /userscript" \
'--customize-hook=rm -f "$1/userscript"' '--customize-hook=rm -f "$1/userscript"'
fi fi
set -- "$@" \ set -- "$@" \
"--customize-hook=download vmlinuz '$WORKDIR/kernel'" \ "--customize-hook=download vmlinuz '$WORKDIR/kernel'" \
"--customize-hook=download initrd.img '$WORKDIR/initrd'" \ "--customize-hook=download initrd.img '$WORKDIR/initrd'" \
"$RELEASE" \ "$RELEASE" \
- -
test -n "$MIRROR" && set -- "$@" "$MIRROR" test -n "$MIRROR" && set -- "$@" "$MIRROR"
test -n "$KEYRING" && set -- "$@" "--keyring=$KEYRING" test -n "$KEYRING" && set -- "$@" "--keyring=$KEYRING"
@ -368,45 +369,44 @@ echo "+ mmdebstrap $*" >&2
# shellcheck disable=SC3040 # shellcheck disable=SC3040
set -o pipefail set -o pipefail
mmdebstrap "$@" | { mmdebstrap "$@" | {
set -- -t ext4 -L autopkgtestvm -d - set -- -t ext4 -L autopkgtestvm -d -
if test -n "$EXT_FEATURES"; then if test -n "$EXT_FEATURES"; then
set -- "$@" -O "$EXT_FEATURES" set -- "$@" -O "$EXT_FEATURES"
fi fi
EXTOPTS="offset=$(( (FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))" EXTOPTS="offset=$(((FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))"
if test -n "${SOURCE_DATE_EPOCH:-}"; then if test -n "${SOURCE_DATE_EPOCH-}"; then
uuid="$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name "$SOURCE_DATE_EPOCH")" uuid="$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name "$SOURCE_DATE_EPOCH")"
set -- "$@" -U "$uuid" set -- "$@" -U "$uuid"
EXTOPTS="$EXTOPTS,hash_seed=$uuid" EXTOPTS="$EXTOPTS,hash_seed=$uuid"
fi fi
set -- "$@" -E "$EXTOPTS" "$IMAGE" "$SIZE" set -- "$@" -E "$EXTOPTS" "$IMAGE" "$SIZE"
echo "+ mke2fs $*" >&2 echo "+ mke2fs $*" >&2
/sbin/mke2fs "$@" /sbin/mke2fs "$@"
} }
echo "root=LABEL=autopkgtestvm rw console=ttyS0" >"$WORKDIR/cmdline"
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"
@ -419,15 +419,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"
@ -438,7 +438,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
@ -450,10 +450,10 @@ 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: SUCCESS! Your new image can be found here: $IMAGE" >&2 echo "I: SUCCESS! Your new image can be found here: $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
;; ;;
*) *)
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,24 @@ 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>&-
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

@ -8,65 +8,65 @@ set -eu
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 &
set -- timeout --foreground 40m \ set -- timeout --foreground 40m \
debvm-run --image="$(realpath "$cachedir")/debian-$DEFAULT_DIST.ext4" \ debvm-run --image="$(realpath "$cachedir")/debian-$DEFAULT_DIST.ext4" \
-- --
cpuname=$(lscpu | awk '/Model name:/ {print $3}' | tr '\n' '+') cpuname=$(lscpu | awk '/Model name:/ {print $3}' | tr '\n' '+')
ncpu=$(lscpu | awk '/Core\(s\) per socket:/ {print $4}' | tr '\n' '+') ncpu=$(lscpu | awk '/Core\(s\) per socket:/ {print $4}' | tr '\n' '+')
if [ "$cpuname" = "Cortex-A53+Cortex-A73+" ] && [ "$ncpu" = "2+4+" ]; then if [ "$cpuname" = "Cortex-A53+Cortex-A73+" ] && [ "$ncpu" = "2+4+" ]; then
# crude detection of the big.LITTLE heterogeneous setup of cores on the # crude detection of the big.LITTLE heterogeneous setup of cores on the
# amlogic a311d bananapi # amlogic a311d bananapi
# #
# https://lists.nongnu.org/archive/html/qemu-devel/2020-10/msg08494.html # https://lists.nongnu.org/archive/html/qemu-devel/2020-10/msg08494.html
# https://gitlab.com/qemu-project/qemu/-/issues/239 # https://gitlab.com/qemu-project/qemu/-/issues/239
# https://segments.zhan.science/posts/kvm_on_pinehone_pro/#trouble-with-heterogeneous-architecture # https://segments.zhan.science/posts/kvm_on_pinehone_pro/#trouble-with-heterogeneous-architecture
set -- taskset --cpu-list 2,3,4,5 "$@" -smp 4 set -- taskset --cpu-list 2,3,4,5 "$@" -smp 4
fi fi
set -- "$@" -nic none -m 4G -snapshot set -- "$@" -nic none -m 4G -snapshot
if [ "$MMDEBSTRAP_TESTS_DEBUG" = "no" ]; then if [ "$MMDEBSTRAP_TESTS_DEBUG" = "no" ]; then
# to connect to serial use: # to connect to serial use:
# minicom -D 'unix#/tmp/ttyS0' # minicom -D 'unix#/tmp/ttyS0'
# or this (quit with ctrl+q): # or this (quit with ctrl+q):
# socat stdin,raw,echo=0,escape=0x11 unix-connect:/tmp/ttyS0 # socat stdin,raw,echo=0,escape=0x11 unix-connect:/tmp/ttyS0
set -- "$@" \ set -- "$@" \
-monitor unix:/tmp/monitor,server,nowait \ -monitor unix:/tmp/monitor,server,nowait \
-serial unix:/tmp/ttyS0,server,nowait \ -serial unix:/tmp/ttyS0,server,nowait \
-serial unix:/tmp/ttyS1,server,nowait -serial unix:/tmp/ttyS1,server,nowait
fi fi
set -- "$@" -virtfs local,id=mmdebstrap,path="$(pwd)/shared",security_model=none,mount_tag=mmdebstrap set -- "$@" -virtfs local,id=mmdebstrap,path="$(pwd)/shared",security_model=none,mount_tag=mmdebstrap
ret=0 ret=0
if [ "$MMDEBSTRAP_TESTS_DEBUG" = "no" ]; then if [ "$MMDEBSTRAP_TESTS_DEBUG" = "no" ]; then
"$@" >"$tmpdir/log" 2>&1 || ret=$? "$@" >"$tmpdir/log" 2>&1 || ret=$?
else else
"$@" 2>&1 | tee "$tmpdir/log" || ret=$? "$@" 2>&1 | tee "$tmpdir/log" || ret=$?
fi fi
if [ "$ret" -ne 0 ]; then if [ "$ret" -ne 0 ]; then
cat "$tmpdir/log" cat "$tmpdir/log"
exit $ret exit $ret
fi fi

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 | 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; echo ./var/lib/apt/extended_states; } | sort | diff -u tar1.txt - {
tar -tf /tmp/debian-chroot.tar
echo ./var/lib/apt/extended_states
} | sort | diff -u tar1.txt -

View file

@ -2,7 +2,7 @@
set -eu 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,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
apt-get remove --yes qemu-user-binfmt 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
@ -13,6 +13,6 @@ apt-get remove --yes qemu-user-binfmt 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
@ -30,16 +30,16 @@ fi
AUTOPROXY= AUTOPROXY=
eval "$(apt-config shell AUTOPROXY Acquire::http::Proxy-Auto-Detect)" eval "$(apt-config shell AUTOPROXY Acquire::http::Proxy-Auto-Detect)"
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
TMP_APT_CONFIG=$(mktemp) TMP_APT_CONFIG=$(mktemp)
echo "Dir \"/dev/null\";" > "$TMP_APT_CONFIG" echo 'Dir "/dev/null";' >"$TMP_APT_CONFIG"
chmod 644 "$TMP_APT_CONFIG" chmod 644 "$TMP_APT_CONFIG"
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 +62,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 +85,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 +111,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; echo ./var/lib/apt/extended_states; } | 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)" \ "$(if [ {{ DIST }} = oldstable ]; then echo --merged-usr; else echo --hook-dir=./hooks/merged-usr; fi)" \
"$(case {{ DIST }} in oldstable) echo --include=e2fsprogs,mount,tzdata,gcc-9-base;; stable) echo --include=e2fsprogs,mount,tzdata;; *) echo --include=base-files ;; esac )" \ "$(case {{ DIST }} in 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,17 +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 \ rm -f /tmp/debian-{{ DIST }}-debootstrap/var/lib/dpkg/diversions-old \
/tmp/debian-{{ DIST }}-mm/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
@ -79,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 | testing)
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
@ -130,97 +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
f1="/tmp/debian-{{ DIST }}-debootstrap/var/log/$log" f1="/tmp/debian-{{ DIST }}-debootstrap/var/log/$log"
f2="/tmp/debian-{{ DIST }}-mm/var/log/$log" f2="/tmp/debian-{{ DIST }}-mm/var/log/$log"
# skip cmp if file is absent in both chroots # skip cmp if file is absent in both chroots
if [ ! -e "$f1" ] && [ ! -e "$f2" ]; then if [ ! -e "$f1" ] && [ ! -e "$f2" ]; then
continue continue
fi fi
if ! cmp "$f1" "$f2" >&2;then if ! cmp "$f1" "$f2" >&2; then
# if the files differ, make sure they are all zeroes # 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 "$f1")" "$f1" /dev/zero >&2
cmp -n "$(stat -c %s "$f2")" "$f2" /dev/zero >&2 cmp -n "$(stat -c %s "$f2")" "$f2" /dev/zero >&2
# then delete them # then delete them
rm "$f1" "$f2" rm "$f1" "$f2"
fi fi
done done
if [ "{{ VARIANT }}" = "-" ]; then if [ "{{ VARIANT }}" = "-" ]; then
# the order in which systemd and cron get installed differ and thus the order # the order in which systemd and cron get installed differ and thus the order
# of lines in /etc/group and /etc/gshadow differs # of lines in /etc/group and /etc/gshadow differs
for f in group group- gshadow gshadow-; do for f in group group- gshadow gshadow-; do
for d in mm debootstrap; do for d in mm debootstrap; do
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak sort /tmp/debian-{{ DIST }}-$d/etc/$f >/tmp/debian-{{ DIST }}-$d/etc/$f.bak
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done done
done done
# the order in which systemd and passwd get installed differ and thus # the order in which systemd and passwd get installed differ and thus
# the order of lines in /etc/shadow and /etc/shadow- differs # the order of lines in /etc/shadow and /etc/shadow- differs
for f in shadow shadow-; do for f in shadow shadow-; do
for d in mm debootstrap; do for d in mm debootstrap; do
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak sort /tmp/debian-{{ DIST }}-$d/etc/$f >/tmp/debian-{{ DIST }}-$d/etc/$f.bak
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done done
done done
# and since the order was different, ignore the *- files # and since the order was different, ignore the *- files
for f in shadow- passwd-; do for f in shadow- passwd-; do
for d in mm debootstrap; do for d in mm debootstrap; do
rm /tmp/debian-{{ DIST }}-$d/etc/$f rm /tmp/debian-{{ DIST }}-$d/etc/$f
done done
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
@ -231,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

@ -6,11 +6,11 @@ trap "rm -f /tmp/chrootless.tar /tmp/root.tar" EXIT INT TERM
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand # we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
# DPKG_ROOT # DPKG_ROOT
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 }} --hook-dir=./hooks/merged-usr \
${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

View file

@ -8,14 +8,14 @@ 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=
@ -28,16 +28,16 @@ MMTARFILTER=
# 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 }} --hook-dir=./hooks/merged-usr \
${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 }} --hook-dir=./hooks/merged-usr \
${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,29 +4,28 @@ 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")" ]
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand # we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
# DPKG_ROOT # DPKG_ROOT
# #
@ -36,33 +35,32 @@ fi
# its own architecture as the native architecture, see #825385 and #1020533 # its own architecture as the native architecture, see #825385 and #1020533
# So we are not testing the installation of apt,build-essential here. # So we are not testing the installation of apt,build-essential here.
for INCLUDE in '' 'apt' 'systemd-sysv'; do for INCLUDE in '' 'apt' 'systemd-sysv'; do
echo 1 > "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" echo 1 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
arch-test "$arch" arch-test "$arch"
{{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \ {{ CMD }} --mode=root --architecture="$arch" --variant={{ VARIANT }} \
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \ --hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \
{{ DIST }} "/tmp/root.tar" {{ MIRROR }} {{ DIST }} "/tmp/root.tar" {{ MIRROR }}
echo 0 > "/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")" echo 0 >"/proc/sys/fs/binfmt_misc/qemu-$(deb2qemu "$arch")"
arch-test "$arch" && exit 1 arch-test "$arch" && exit 1
{{ CMD }} --mode=chrootless --architecture="$arch" --variant={{ VARIANT }} \ {{ CMD }} --mode=chrootless --architecture="$arch" --variant={{ VARIANT }} \
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \ --hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \
--skip=check/chrootless {{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }} --skip=check/chrootless {{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }}
# when creating a foreign architecture chroot, the tarballs are not # when creating a foreign architecture chroot, the tarballs are not
# bit-by-bit identical but contain a few remaining differences: # bit-by-bit identical but contain a few remaining differences:
# #
# * /etc/ld.so.cache -- hard problem, must be solved in glibc upstream # * /etc/ld.so.cache -- hard problem, must be solved in glibc upstream
# * /var/lib/dpkg/triggers -- #990712 # * /var/lib/dpkg/triggers -- #990712
# * /var/cache/debconf/*.dat-old -- needs investigation # * /var/cache/debconf/*.dat-old -- needs investigation
for tar in root chrootless; do for tar in root chrootless; do
<"/tmp/$tar.tar" \ ./tarfilter <"/tmp/$tar.tar" \
./tarfilter \ --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=/etc/ld.so.cache \
--path-exclude=/etc/ld.so.cache \ --path-exclude=/var/lib/dpkg/triggers/File \
--path-exclude=/var/lib/dpkg/triggers/File \ --path-exclude=/var/lib/dpkg/triggers/ldconfig \
--path-exclude=/var/lib/dpkg/triggers/ldconfig \ >"/tmp/$tar.tar.tmp"
> "/tmp/$tar.tar.tmp" mv "/tmp/$tar.tar.tmp" "/tmp/$tar.tar"
mv "/tmp/$tar.tar.tmp" "/tmp/$tar.tar" 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

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,75 @@ 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/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$foreign_arch\\.gz$" \
| grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$' \ | grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \
| sed "s/$foreign_gnu/$native_gnu/" \ | grep -v '^\./usr/share/man/man8/x86_64\.8\.gz$' \
| sed "s/$foreign_arch/$native_arch/"; | sed "s/$foreign_gnu/$native_gnu/" \
} | sort > /tmp/tar2.txt | sed "s/$foreign_arch/$native_arch/"
{ < tar1.txt \ } | sort >/tmp/tar2.txt
grep -v '^\./usr/bin/i386$' \ {
| grep -v '^\./usr/bin/x86_64$' \ grep <tar1.txt -v '^\./usr/bin/i386$' \
| grep -v '^\./lib32$' \ | grep -v '^\./usr/bin/x86_64$' \
| grep -v '^\./lib64$' \ | grep -v '^\./lib32$' \
| grep -v '^\./libx32$' \ | grep -v '^\./lib64$' \
| grep -v '^\./usr/lib32/$' \ | grep -v '^\./libx32$' \
| grep -v '^\./usr/libx32/$' \ | grep -v '^\./usr/lib32/$' \
| grep -v '^\./usr/lib64/$' \ | grep -v '^\./usr/libx32/$' \
| 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/$native_gnu/ld-linux-x86-64\\.so\\.2$" \ | grep -v '^\./usr/lib/ld-linux-aarch64\.so\.1$' \
| grep -v "^\\./usr/lib/$native_gnu/ld-linux-aarch64\\.so\\.1$" \ | grep -v "^\\./usr/lib/$native_gnu/ld-linux-x86-64\\.so\\.2$" \
| grep -v "^\\./usr/lib/$native_gnu/libmvec\\.so\\.1$" \ | grep -v "^\\./usr/lib/$native_gnu/ld-linux-aarch64\\.so\\.1$" \
| grep -v "^\\./usr/lib/$native_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \ | grep -v "^\\./usr/lib/$native_gnu/libmvec\\.so\\.1$" \
| grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$native_arch\\.gz$" \ | grep -v "^\\./usr/lib/$native_gnu/perl/5\\.[0-9][.0-9]\\+/.*\\.ph$" \
| grep -v '^\./usr/share/man/man8/i386\.8\.gz$' \ | grep -v "^\\./usr/share/doc/[^/]\\+/changelog\\(\\.Debian\\)\\?\\.$native_arch\\.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 - /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

@ -8,9 +8,9 @@ chmod 755 "$tmpdir"
ret=0 ret=0
debootstrap "$([ "{{ DIST }}" = oldstable ] && echo --no-merged-usr || echo --merged-usr)" --variant={{ VARIANT }} {{ DIST }} "$tmpdir" {{ MIRROR }} || ret=$? debootstrap "$([ "{{ DIST }}" = oldstable ] && echo --no-merged-usr || echo --merged-usr)" --variant={{ VARIANT }} {{ DIST }} "$tmpdir" {{ MIRROR }} || ret=$?
if [ "$ret" -ne 0 ]; then if [ "$ret" -ne 0 ]; then
echo "E: debootstrap failed, dumping $tmpdir/debootstrap/debootstrap.log" echo "E: debootstrap failed, dumping $tmpdir/debootstrap/debootstrap.log"
cat "$tmpdir/debootstrap/debootstrap.log" cat "$tmpdir/debootstrap/debootstrap.log"
exit 1 exit 1
fi fi
tar --sort=name --mtime=@$SOURCE_DATE_EPOCH --clamp-mtime --numeric-owner --one-file-system --xattrs -C "$tmpdir" -c . > "./cache/debian-{{ DIST }}-{{ VARIANT }}.tar" tar --sort=name --mtime=@$SOURCE_DATE_EPOCH --clamp-mtime --numeric-owner --one-file-system --xattrs -C "$tmpdir" -c . >"./cache/debian-{{ DIST }}-{{ VARIANT }}.tar"
rm -r "$tmpdir" rm -r "$tmpdir"

View file

@ -7,9 +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
case {{ VARIANT }} in standard) : ;; *) exit 1;; esac 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,31 +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 \
| 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='test -e "$1"/etc/apt/sources.list || 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 -

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,11 +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.' \
| 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-binfmt 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

@ -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,27 +7,30 @@
# - 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 -f /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"

View file

@ -7,28 +7,31 @@
# - 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 -f /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"

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 }}

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,20 +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/diversions-old \ --path-exclude=/var/lib/dpkg/diversions-old \
--path-exclude=/var/lib/dpkg/cmethopt \ --path-exclude=/var/lib/dpkg/cmethopt \
--path-exclude=/var/lib/dpkg/status-old \ --path-exclude=/var/lib/dpkg/status-old \
--path-exclude=/var/lib/shells.state --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

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,18 +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
# do not install base-files, so that /proc, /sys and /dev are missing # do not install base-files, so that /proc, /sys and /dev are missing
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} \ $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' \ --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 \ --include=dpkg,dash,diffutils,coreutils,libc-bin,sed \
{{ DIST }} /dev/null {{ MIRROR }} {{ 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,7 +5,7 @@ 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|ext4) : ;; *) exit 1;; esac case {{ FORMAT }} in tar | squashfs | ext2 | ext4) : ;; *) exit 1 ;; esac
{{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }} {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }}
# creating an ext4 image on a 9p filesystem produces different results compared # creating an ext4 image on a 9p filesystem produces different results compared
@ -14,18 +14,18 @@ case {{ FORMAT }} in tar|squashfs|ext2|ext4) : ;; *) exit 1;; esac
# https://lore.kernel.org/linux-ext4/171484520952.2626447.2160419274451668597@localhost/T/#t # https://lore.kernel.org/linux-ext4/171484520952.2626447.2160419274451668597@localhost/T/#t
mv /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} mv /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }}
if [ "{{ FORMAT }}" = tar ]; then if [ "{{ FORMAT }}" = tar ]; then
printf 'ustar\0' | 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 - 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 elif [ "{{ FORMAT }}" = ext4 ]; then
printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4 - 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 - 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)" ] [ "$(/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

@ -12,9 +12,9 @@ rm /tmp/debian-chroot/etc/timezone
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
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 | 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,perl \ --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,perl \ $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,perl {{ 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,perl \ $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,perl {{ 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

View file

@ -6,17 +6,17 @@ pid=$!
while sleep 1; do [ -e hookstarted ] && break; done while sleep 1; do [ -e hookstarted ] && break; done
rm hookstarted rm hookstarted
# negative PID values choose the whole process group # negative PID values choose the whole process group
pgid=$((-1*$(ps -p "$pid" -o pgid=))) pgid=$((-1 * $(ps -p "$pid" -o pgid=)))
/bin/kill --signal INT -- "$pgid" /bin/kill --signal INT -- "$pgid"
ret=0 ret=0
wait $pid || ret=$? wait $pid || ret=$?
rm -r /tmp/debian-chroot rm -r /tmp/debian-chroot
if [ -e fail ]; then if [ -e fail ]; then
echo customize hook was not interrupted >&2 echo customize hook was not interrupted >&2
rm fail rm fail
exit 1 exit 1
fi fi
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 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

@ -4,9 +4,9 @@ export LC_ALL=C.UTF-8
[ "{{ MODE }}" = "unshare" ] [ "{{ MODE }}" = "unshare" ]
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
{{ CMD }} --mode=unshare --variant=apt \ {{ CMD }} --mode=unshare --variant=apt \
--skip=chroot/mount/proc,chroot/mount/sys \ --skip=chroot/mount/proc,chroot/mount/sys \
--customize-hook='mountpoint "$1"/dev/null' \ --customize-hook='mountpoint "$1"/dev/null' \
--customize-hook='if mountpoint "$1"/sys; then exit 1; fi' \ --customize-hook='if mountpoint "$1"/sys; then exit 1; fi' \
--customize-hook='if mountpoint "$1"/proc; then exit 1; fi' \ --customize-hook='if mountpoint "$1"/proc; then exit 1; fi' \
{{ 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

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

View file

@ -4,27 +4,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
# test this for both unshare and root mode because the code paths creating # test this for both unshare and root mode because the code paths creating
# entries in /dev are different depending on whether mknod is available or not # entries in /dev are different depending on whether mknod is available or not
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --skip=output/mknod \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --skip=output/mknod \
{{ DIST }} - {{ MIRROR }} | { {{ DIST }} - {{ MIRROR }} | {
tar -t; tar -t
echo ./dev/console; echo ./dev/console
echo ./dev/full; echo ./dev/full
echo ./dev/null; echo ./dev/null
echo ./dev/ptmx; echo ./dev/ptmx
echo ./dev/random; echo ./dev/random
echo ./dev/tty; echo ./dev/tty
echo ./dev/urandom; echo ./dev/urandom
echo ./dev/zero; echo ./dev/zero
} | sort | diff -u tar1.txt - } | sort | diff -u tar1.txt -

View file

@ -3,8 +3,8 @@ 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 \
--skip=chroot/start-stop-daemon,chroot/policy-rc.d \ --skip=chroot/start-stop-daemon,chroot/policy-rc.d \
--customize-hook='test ! -e "$1/sbin/start-stop-daemon.REAL"' \ --customize-hook='test ! -e "$1/sbin/start-stop-daemon.REAL"' \
--customize-hook='test ! -e "$1/usr/sbin/policy-rc.d"' \ --customize-hook='test ! -e "$1/usr/sbin/policy-rc.d"' \
{{ 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,20 +9,20 @@ 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 {{ CMD }} --mode={{ MODE }} --variant=custom \ $prefix {{ CMD }} --mode={{ MODE }} --variant=custom \
--skip=update,setup,cleanup,tar-in/mknod \ --skip=update,setup,cleanup,tar-in/mknod \
--setup-hook='tar-in ./cache/mmdebstrap-{{ DIST }}-apt.tar /' \ --setup-hook='tar-in ./cache/mmdebstrap-{{ DIST }}-apt.tar /' \
'' /tmp/debian-chroot.tar '' /tmp/debian-chroot.tar
cmp ./cache/mmdebstrap-{{ DIST }}-apt.tar /tmp/debian-chroot.tar \ cmp ./cache/mmdebstrap-{{ DIST }}-apt.tar /tmp/debian-chroot.tar \
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-apt.tar /tmp/debian-chroot.tar || diffoscope ./cache/mmdebstrap-{{ DIST }}-apt.tar /tmp/debian-chroot.tar

View file

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

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/script.sh cat <<'SCRIPT' >/tmp/script.sh
#!/bin/sh #!/bin/sh
set -eu set -eu
echo "MMDEBSTRAP_APT_CONFIG $MMDEBSTRAP_APT_CONFIG" echo "MMDEBSTRAP_APT_CONFIG $MMDEBSTRAP_APT_CONFIG"
@ -21,11 +21,11 @@ rm test
SCRIPT SCRIPT
chmod +x /tmp/script.sh chmod +x /tmp/script.sh
{{ CMD }} --mode=root --variant=apt \ {{ CMD }} --mode=root --variant=apt \
--setup-hook=/tmp/script.sh \ --setup-hook=/tmp/script.sh \
--extract-hook=/tmp/script.sh \ --extract-hook=/tmp/script.sh \
--essential-hook=/tmp/script.sh \ --essential-hook=/tmp/script.sh \
--customize-hook=/tmp/script.sh \ --customize-hook=/tmp/script.sh \
{{ DIST }} /tmp/debian-chroot {{ MIRROR }} {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
printf "setup\nextract\nessential\ncustomize\n" | diff -u - /tmp/hooks printf "setup\nextract\nessential\ncustomize\n" | diff -u - /tmp/hooks
rm /tmp/script.sh /tmp/hooks rm /tmp/script.sh /tmp/hooks
rm -r /tmp/debian-chroot rm -r /tmp/debian-chroot

View file

@ -4,126 +4,126 @@ 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
[ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot" [ "{{ MODE }}" = "fakechroot" ] && prefix="$prefix fakechroot fakeroot"
symlinktarget=/real symlinktarget=/real
[ "{{ MODE }}" = "fakechroot" ] && symlinktarget='$1/real' [ "{{ MODE }}" = "fakechroot" ] && symlinktarget='$1/real'
echo copy-in-setup > /tmp/copy-in-setup echo copy-in-setup >/tmp/copy-in-setup
echo copy-in-essential > /tmp/copy-in-essential echo copy-in-essential >/tmp/copy-in-essential
echo copy-in-customize > /tmp/copy-in-customize echo copy-in-customize >/tmp/copy-in-customize
echo tar-in-setup > /tmp/tar-in-setup echo tar-in-setup >/tmp/tar-in-setup
echo tar-in-essential > /tmp/tar-in-essential echo tar-in-essential >/tmp/tar-in-essential
echo tar-in-customize > /tmp/tar-in-customize echo tar-in-customize >/tmp/tar-in-customize
tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-setup.tar tar-in-setup tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-setup.tar tar-in-setup
tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-essential.tar tar-in-essential tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-essential.tar tar-in-essential
tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-customize.tar tar-in-customize tar --numeric-owner --format=pax --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -C /tmp -cf /tmp/tar-in-customize.tar tar-in-customize
rm /tmp/tar-in-setup rm /tmp/tar-in-setup
rm /tmp/tar-in-essential rm /tmp/tar-in-essential
rm /tmp/tar-in-customize rm /tmp/tar-in-customize
echo upload-setup > /tmp/upload-setup echo upload-setup >/tmp/upload-setup
echo upload-essential > /tmp/upload-essential echo upload-essential >/tmp/upload-essential
echo upload-customize > /tmp/upload-customize echo upload-customize >/tmp/upload-customize
mkdir /tmp/sync-in-setup mkdir /tmp/sync-in-setup
mkdir /tmp/sync-in-essential mkdir /tmp/sync-in-essential
mkdir /tmp/sync-in-customize mkdir /tmp/sync-in-customize
echo sync-in-setup > /tmp/sync-in-setup/file echo sync-in-setup >/tmp/sync-in-setup/file
echo sync-in-essential > /tmp/sync-in-essential/file echo sync-in-essential >/tmp/sync-in-essential/file
echo sync-in-customize > /tmp/sync-in-customize/file echo sync-in-customize >/tmp/sync-in-customize/file
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
--setup-hook='mkdir "$1/real"' \ --setup-hook='mkdir "$1/real"' \
--setup-hook='copy-in /tmp/copy-in-setup /real' \ --setup-hook='copy-in /tmp/copy-in-setup /real' \
--setup-hook='echo copy-in-setup | cmp "$1/real/copy-in-setup" -' \ --setup-hook='echo copy-in-setup | cmp "$1/real/copy-in-setup" -' \
--setup-hook='rm "$1/real/copy-in-setup"' \ --setup-hook='rm "$1/real/copy-in-setup"' \
--setup-hook='echo copy-out-setup > "$1/real/copy-out-setup"' \ --setup-hook='echo copy-out-setup > "$1/real/copy-out-setup"' \
--setup-hook='copy-out /real/copy-out-setup /tmp' \ --setup-hook='copy-out /real/copy-out-setup /tmp' \
--setup-hook='rm "$1/real/copy-out-setup"' \ --setup-hook='rm "$1/real/copy-out-setup"' \
--setup-hook='tar-in /tmp/tar-in-setup.tar /real' \ --setup-hook='tar-in /tmp/tar-in-setup.tar /real' \
--setup-hook='echo tar-in-setup | cmp "$1/real/tar-in-setup" -' \ --setup-hook='echo tar-in-setup | cmp "$1/real/tar-in-setup" -' \
--setup-hook='tar-out /real/tar-in-setup /tmp/tar-out-setup.tar' \ --setup-hook='tar-out /real/tar-in-setup /tmp/tar-out-setup.tar' \
--setup-hook='rm "$1"/real/tar-in-setup' \ --setup-hook='rm "$1"/real/tar-in-setup' \
--setup-hook='upload /tmp/upload-setup /real/upload' \ --setup-hook='upload /tmp/upload-setup /real/upload' \
--setup-hook='echo upload-setup | cmp "$1/real/upload" -' \ --setup-hook='echo upload-setup | cmp "$1/real/upload" -' \
--setup-hook='download /real/upload /tmp/download-setup' \ --setup-hook='download /real/upload /tmp/download-setup' \
--setup-hook='rm "$1/real/upload"' \ --setup-hook='rm "$1/real/upload"' \
--setup-hook='sync-in /tmp/sync-in-setup /real' \ --setup-hook='sync-in /tmp/sync-in-setup /real' \
--setup-hook='echo sync-in-setup | cmp "$1/real/file" -' \ --setup-hook='echo sync-in-setup | cmp "$1/real/file" -' \
--setup-hook='sync-out /real /tmp/sync-out-setup' \ --setup-hook='sync-out /real /tmp/sync-out-setup' \
--setup-hook='rm "$1/real/file"' \ --setup-hook='rm "$1/real/file"' \
--essential-hook='ln -s "'"$symlinktarget"'" "$1/symlink"' \ --essential-hook='ln -s "'"$symlinktarget"'" "$1/symlink"' \
--essential-hook='copy-in /tmp/copy-in-essential /symlink' \ --essential-hook='copy-in /tmp/copy-in-essential /symlink' \
--essential-hook='echo copy-in-essential | cmp "$1/real/copy-in-essential" -' \ --essential-hook='echo copy-in-essential | cmp "$1/real/copy-in-essential" -' \
--essential-hook='rm "$1/real/copy-in-essential"' \ --essential-hook='rm "$1/real/copy-in-essential"' \
--essential-hook='echo copy-out-essential > "$1/real/copy-out-essential"' \ --essential-hook='echo copy-out-essential > "$1/real/copy-out-essential"' \
--essential-hook='copy-out /symlink/copy-out-essential /tmp' \ --essential-hook='copy-out /symlink/copy-out-essential /tmp' \
--essential-hook='rm "$1/real/copy-out-essential"' \ --essential-hook='rm "$1/real/copy-out-essential"' \
--essential-hook='tar-in /tmp/tar-in-essential.tar /symlink' \ --essential-hook='tar-in /tmp/tar-in-essential.tar /symlink' \
--essential-hook='echo tar-in-essential | cmp "$1/real/tar-in-essential" -' \ --essential-hook='echo tar-in-essential | cmp "$1/real/tar-in-essential" -' \
--essential-hook='tar-out /symlink/tar-in-essential /tmp/tar-out-essential.tar' \ --essential-hook='tar-out /symlink/tar-in-essential /tmp/tar-out-essential.tar' \
--essential-hook='rm "$1"/real/tar-in-essential' \ --essential-hook='rm "$1"/real/tar-in-essential' \
--essential-hook='upload /tmp/upload-essential /symlink/upload' \ --essential-hook='upload /tmp/upload-essential /symlink/upload' \
--essential-hook='echo upload-essential | cmp "$1/real/upload" -' \ --essential-hook='echo upload-essential | cmp "$1/real/upload" -' \
--essential-hook='download /symlink/upload /tmp/download-essential' \ --essential-hook='download /symlink/upload /tmp/download-essential' \
--essential-hook='rm "$1/real/upload"' \ --essential-hook='rm "$1/real/upload"' \
--essential-hook='sync-in /tmp/sync-in-essential /symlink' \ --essential-hook='sync-in /tmp/sync-in-essential /symlink' \
--essential-hook='echo sync-in-essential | cmp "$1/real/file" -' \ --essential-hook='echo sync-in-essential | cmp "$1/real/file" -' \
--essential-hook='sync-out /real /tmp/sync-out-essential' \ --essential-hook='sync-out /real /tmp/sync-out-essential' \
--essential-hook='rm "$1/real/file"' \ --essential-hook='rm "$1/real/file"' \
--customize-hook='copy-in /tmp/copy-in-customize /symlink' \ --customize-hook='copy-in /tmp/copy-in-customize /symlink' \
--customize-hook='echo copy-in-customize | cmp "$1/real/copy-in-customize" -' \ --customize-hook='echo copy-in-customize | cmp "$1/real/copy-in-customize" -' \
--customize-hook='rm "$1/real/copy-in-customize"' \ --customize-hook='rm "$1/real/copy-in-customize"' \
--customize-hook='echo copy-out-customize > "$1/real/copy-out-customize"' \ --customize-hook='echo copy-out-customize > "$1/real/copy-out-customize"' \
--customize-hook='copy-out /symlink/copy-out-customize /tmp' \ --customize-hook='copy-out /symlink/copy-out-customize /tmp' \
--customize-hook='rm "$1/real/copy-out-customize"' \ --customize-hook='rm "$1/real/copy-out-customize"' \
--customize-hook='tar-in /tmp/tar-in-customize.tar /symlink' \ --customize-hook='tar-in /tmp/tar-in-customize.tar /symlink' \
--customize-hook='echo tar-in-customize | cmp "$1/real/tar-in-customize" -' \ --customize-hook='echo tar-in-customize | cmp "$1/real/tar-in-customize" -' \
--customize-hook='tar-out /symlink/tar-in-customize /tmp/tar-out-customize.tar' \ --customize-hook='tar-out /symlink/tar-in-customize /tmp/tar-out-customize.tar' \
--customize-hook='rm "$1"/real/tar-in-customize' \ --customize-hook='rm "$1"/real/tar-in-customize' \
--customize-hook='upload /tmp/upload-customize /symlink/upload' \ --customize-hook='upload /tmp/upload-customize /symlink/upload' \
--customize-hook='echo upload-customize | cmp "$1/real/upload" -' \ --customize-hook='echo upload-customize | cmp "$1/real/upload" -' \
--customize-hook='download /symlink/upload /tmp/download-customize' \ --customize-hook='download /symlink/upload /tmp/download-customize' \
--customize-hook='rm "$1/real/upload"' \ --customize-hook='rm "$1/real/upload"' \
--customize-hook='sync-in /tmp/sync-in-customize /symlink' \ --customize-hook='sync-in /tmp/sync-in-customize /symlink' \
--customize-hook='echo sync-in-customize | cmp "$1/real/file" -' \ --customize-hook='echo sync-in-customize | cmp "$1/real/file" -' \
--customize-hook='sync-out /real /tmp/sync-out-customize' \ --customize-hook='sync-out /real /tmp/sync-out-customize' \
--customize-hook='rm "$1/real/file"' \ --customize-hook='rm "$1/real/file"' \
--customize-hook='rmdir "$1/real"' \ --customize-hook='rmdir "$1/real"' \
--customize-hook='rm "$1/symlink"' \ --customize-hook='rm "$1/symlink"' \
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }} {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
for n in setup essential customize; do for n in setup essential customize; do
ret=0 ret=0
cmp /tmp/tar-in-$n.tar /tmp/tar-out-$n.tar || ret=$? cmp /tmp/tar-in-$n.tar /tmp/tar-out-$n.tar || 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/tar-in-$n.tar /tmp/tar-out-$n.tar diffoscope /tmp/tar-in-$n.tar /tmp/tar-out-$n.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/tar-in-$n.tar base64 /tmp/tar-in-$n.tar
base64 /tmp/tar-out-$n.tar base64 /tmp/tar-out-$n.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/tar-in-$n.tar xxd /tmp/tar-in-$n.tar
xxd /tmp/tar-out-$n.tar xxd /tmp/tar-out-$n.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
done done
echo copy-out-setup | cmp /tmp/copy-out-setup - echo copy-out-setup | cmp /tmp/copy-out-setup -
echo copy-out-essential | cmp /tmp/copy-out-essential - echo copy-out-essential | cmp /tmp/copy-out-essential -
@ -136,13 +136,13 @@ echo sync-in-essential | cmp /tmp/sync-out-essential/file -
echo sync-in-customize | cmp /tmp/sync-out-customize/file - echo sync-in-customize | cmp /tmp/sync-out-customize/file -
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 \
/tmp/copy-in-setup /tmp/copy-in-essential /tmp/copy-in-customize \ /tmp/copy-in-setup /tmp/copy-in-essential /tmp/copy-in-customize \
/tmp/copy-out-setup /tmp/copy-out-essential /tmp/copy-out-customize \ /tmp/copy-out-setup /tmp/copy-out-essential /tmp/copy-out-customize \
/tmp/tar-in-setup.tar /tmp/tar-in-essential.tar /tmp/tar-in-customize.tar \ /tmp/tar-in-setup.tar /tmp/tar-in-essential.tar /tmp/tar-in-customize.tar \
/tmp/tar-out-setup.tar /tmp/tar-out-essential.tar /tmp/tar-out-customize.tar \ /tmp/tar-out-setup.tar /tmp/tar-out-essential.tar /tmp/tar-out-customize.tar \
/tmp/upload-setup /tmp/upload-essential /tmp/upload-customize \ /tmp/upload-setup /tmp/upload-essential /tmp/upload-customize \
/tmp/download-setup /tmp/download-essential /tmp/download-customize \ /tmp/download-setup /tmp/download-essential /tmp/download-customize \
/tmp/sync-in-setup/file /tmp/sync-in-essential/file /tmp/sync-in-customize/file \ /tmp/sync-in-setup/file /tmp/sync-in-essential/file /tmp/sync-in-customize/file \
/tmp/sync-out-setup/file /tmp/sync-out-essential/file /tmp/sync-out-customize/file /tmp/sync-out-setup/file /tmp/sync-out-essential/file /tmp/sync-out-customize/file
rmdir /tmp/sync-in-setup /tmp/sync-in-essential /tmp/sync-in-customize \ rmdir /tmp/sync-in-setup /tmp/sync-in-essential /tmp/sync-in-customize \
/tmp/sync-out-setup /tmp/sync-out-essential /tmp/sync-out-customize /tmp/sync-out-setup /tmp/sync-out-essential /tmp/sync-out-customize

View file

@ -2,17 +2,17 @@
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
apt-cache policy apt-cache policy
cat /etc/apt/sources.list cat /etc/apt/sources.list
{{ CMD }} --mode=root --variant=apt stable /tmp/debian-chroot {{ CMD }} --mode=root --variant=apt stable /tmp/debian-chroot
cat << SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list cat <<SOURCES | cmp /tmp/debian-chroot/etc/apt/sources.list
deb http://deb.debian.org/debian stable main deb http://deb.debian.org/debian stable main
deb http://deb.debian.org/debian stable-updates main deb http://deb.debian.org/debian stable-updates main
deb http://security.debian.org/debian-security stable-security main deb http://security.debian.org/debian-security stable-security main

View file

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

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