Compare commits

..

11 commits

Author SHA1 Message Date
8fe4fe3eda
hooks/busybox/extract00.sh: run busybox from an absolute path 2021-10-08 20:46:55 +02:00
7a062661e5
release 0.8.1 2021-10-07 13:35:39 +02:00
1d2a7ef71a
enforce dpkg >= 1.20.0 and remove dead code 2021-10-07 10:51:20 +02:00
4f278deadf
use rm and find instead of remove_tree()
* remove_tree() requires the CWD to be accessible or fails with
   cannot chdir to $CWD from $DIR_TO_DELETE: Permission denied, aborting.
 * CWD is not always accessible -- example: run mmdebstrap from a
   directory only accessible by the current user (like a tempdir) in
   unshare mode
 * find from findutils *also* requires CWD to be accessible but it's
   easier to temporarily change CWD in a subprocess because using
   there is no utility in perl core that changes CWD temporarily and
   cleans up after itself
 * we need to use find from findutils instead of rm in unshare mode
   because the root directory itself might not be removable by the
   unshared user so we only want to remove its subdirectories
2021-10-07 07:07:45 +02:00
c2d988b475
enforce apt >= 2.3.7 and remove dead code (closes: #14) 2021-10-06 23:30:09 +02:00
28cb757742
do not run xz and zstd with --threads=0
There are now systems with 160 cores (debci runs on two Ampere Altra
ARMv8 Neoverse-N1), which makes xz fail with: "xz: (stdin): Cannot
allocate memory"
2021-09-24 22:09:24 +02:00
932a3716bc
ldconfig.fakechroot: support DPKG_ROOT 2021-09-23 06:24:59 +02:00
12ec2c50aa
also create cmethopt and available in chrootless mode
- this allows bit-by-bit identical output of chrootless mode compared
   to other modes
2021-09-22 15:22:35 +02:00
03ebda088f
coverage.sh: use MMDEBSTRAP_APT_CONFIG to prevent apt options (like foreign archs) leaking into the apt calls 2021-09-22 09:04:27 +02:00
450881f4ce
coverage.sh: setup00-merged-usr.sh moved into a subdirectory 2021-09-21 23:01:58 +02:00
2bd6929fbc
make_mirror.sh: bullseye-updates doesn't ship Packages.gz anymore, so we use xz everywhere instead 2021-09-21 21:11:46 +02:00
6 changed files with 162 additions and 203 deletions

View file

@ -1,3 +1,12 @@
0.8.1 (2021-10-07)
------------------
- enforce dpkg >= 1.20.0 and apt >= 2.3.7
- allow working directory be not world readable
- do not run xz and zstd with --threads=0 since this is a bad default for
machines with more than 100 cores
- bit-by-bit identical chrootless mode
0.8.0 (2021-09-21) 0.8.0 (2021-09-21)
------------------ ------------------

View file

@ -103,12 +103,12 @@ if [ ! -e shared/ldconfig.fakechroot ] || [ ldconfig.fakechroot -nt shared/ldcon
cp -a /usr/libexec/mmdebstrap/ldconfig.fakechroot shared/ldconfig.fakechroot cp -a /usr/libexec/mmdebstrap/ldconfig.fakechroot shared/ldconfig.fakechroot
fi fi
fi fi
mkdir -p shared/hooks mkdir -p shared/hooks/merged-usr
if [ ! -e shared/hooks/setup00-merged-usr.sh ] || [ hooks/setup00-merged-usr.sh -nt shared/hooks/setup00-merged-usr.sh ]; then if [ ! -e shared/hooks/merged-usr/setup00.sh ] || [ hooks/merged-usr/setup00.sh -nt shared/hooks/merged-usr/setup00.sh ]; then
if [ -e hooks/setup00-merged-usr.sh ]; then if [ -e hooks/merged-usr/setup00.sh ]; then
cp -a hooks/setup00-merged-usr.sh shared/hooks/ cp -a hooks/merged-usr/setup00.sh shared/hooks/merged-usr/
else else
cp -a /usr/share/mmdebstrap/hooks/setup00-merged-usr.sh shared/hooks/ cp -a /usr/share/mmdebstrap/hooks/merged-usr/setup00.sh shared/hooks/merged-usr/
fi fi
fi fi
mkdir -p shared/hooks/eatmydata mkdir -p shared/hooks/eatmydata
@ -127,7 +127,7 @@ if [ ! -e shared/hooks/eatmydata/customize.sh ] || [ hooks/eatmydata/customize.s
fi fi
fi fi
starttime= starttime=
total=212 total=213
skipped=0 skipped=0
runtests=0 runtests=0
i=1 i=1
@ -240,7 +240,7 @@ 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
# remove dpkg files # remove dpkg files
rm /tmp/debian-$dist-debootstrap/var/lib/dpkg/available rm /tmp/debian-$dist-debootstrap/var/lib/dpkg/available
touch /tmp/debian-$dist-debootstrap/var/lib/dpkg/available rm /tmp/debian-$dist-debootstrap/var/lib/dpkg/cmethopt
# 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 > dpkg1 chroot /tmp/debian-$dist-debootstrap dpkg --list > dpkg1
@ -1055,6 +1055,39 @@ else
runtests=$((runtests+1)) runtests=$((runtests+1))
fi fi
print_header "mode=unshare,variant=apt: CWD directory not accessible by unshared user"
cat << END > shared/test.sh
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
if [ ! -e /mmdebstrap-testenv ]; then
echo "this test modifies the system and should only be run inside a container" >&2
exit 1
fi
adduser --gecos user --disabled-password user
sysctl -w kernel.unprivileged_userns_clone=1
mkdir /tmp/debian-chroot
chmod 700 /tmp/debian-chroot
chown user:user /tmp/debian-chroot
if [ "$CMD" = "./mmdebstrap" ]; then
CMD=\$(realpath --canonicalize-existing ./mmdebstrap)
elif [ "$CMD" = "perl -MDevel::Cover=-silent,-nogcov ./mmdebstrap" ]; then
CMD="perl -MDevel::Cover=-silent,-nogcov \$(realpath --canonicalize-existing ./mmdebstrap)"
else
CMD="$CMD"
fi
env --chdir=/tmp/debian-chroot runuser -u user -- \$CMD --mode=unshare --variant=apt $DEFAULT_DIST /tmp/debian-chroot.tar $mirror
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
rm /tmp/debian-chroot.tar
END
if [ "$HAVE_QEMU" = "yes" ]; then
./run_qemu.sh
runtests=$((runtests+1))
else
echo "HAVE_QEMU != yes -- Skipping test..." >&2
skipped=$((skipped+1))
fi
print_header "mode=unshare,variant=apt: create gzip compressed tarball" print_header "mode=unshare,variant=apt: create gzip compressed tarball"
cat << END > shared/test.sh cat << END > shared/test.sh
#!/bin/sh #!/bin/sh
@ -2076,7 +2109,7 @@ cat << END > shared/test.sh
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 \
--setup-hook=./hooks/setup00-merged-usr.sh \ --setup-hook=./hooks/merged-usr/setup00.sh \
--customize-hook='[ -L "\$1"/bin -a -L "\$1"/sbin -a -L "\$1"/lib ]' \ --customize-hook='[ -L "\$1"/bin -a -L "\$1"/sbin -a -L "\$1"/lib ]' \
$DEFAULT_DIST /tmp/debian-chroot $mirror $DEFAULT_DIST /tmp/debian-chroot $mirror
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
@ -2763,8 +2796,6 @@ rm /tmp/debian-chroot/etc/fstab
rm /tmp/debian-chroot/etc/hostname rm /tmp/debian-chroot/etc/hostname
rm /tmp/debian-chroot/etc/resolv.conf rm /tmp/debian-chroot/etc/resolv.conf
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
rm /tmp/debian-chroot/var/lib/dpkg/status rm /tmp/debian-chroot/var/lib/dpkg/status
# 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
@ -2793,8 +2824,6 @@ rm /tmp/debian-chroot/etc/fstab
rm /tmp/debian-chroot/etc/hostname rm /tmp/debian-chroot/etc/hostname
rm /tmp/debian-chroot/etc/resolv.conf rm /tmp/debian-chroot/etc/resolv.conf
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
rm /tmp/debian-chroot/var/lib/dpkg/status rm /tmp/debian-chroot/var/lib/dpkg/status
# 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
@ -2824,8 +2853,6 @@ rm /tmp/debian-chroot/etc/fstab
rm /tmp/debian-chroot/etc/hostname rm /tmp/debian-chroot/etc/hostname
rm /tmp/debian-chroot/etc/resolv.conf rm /tmp/debian-chroot/etc/resolv.conf
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
rm /tmp/debian-chroot/var/lib/dpkg/status rm /tmp/debian-chroot/var/lib/dpkg/status
# 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
@ -2844,8 +2871,8 @@ cat << END > shared/test.sh
set -eu set -eu
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
$CMD --mode=$defaultmode --variant=essential --include=apt \ $CMD --mode=$defaultmode --variant=essential --include=apt \
--essential-hook='apt-get -o Dir="\$1" -oDir::Etc::TrustedParts=/etc/apt/trusted.gpg.d -oAcquire::Languages=none update' \ --essential-hook='APT_CONFIG=\$MMDEBSTRAP_APT_CONFIG apt-get update' \
--essential-hook='apt-get --yes install --no-install-recommends -o Dir="\$1" -oDPkg::Chroot-Directory="\$1" apt' \ --essential-hook='APT_CONFIG=\$MMDEBSTRAP_APT_CONFIG apt-get --yes install -oDPkg::Chroot-Directory="\$1" apt' \
$DEFAULT_DIST /tmp/debian-chroot.tar $mirror $DEFAULT_DIST /tmp/debian-chroot.tar $mirror
tar -tf /tmp/debian-chroot.tar | sort | grep -v ./var/lib/apt/extended_states | diff -u tar1.txt - tar -tf /tmp/debian-chroot.tar | sort | grep -v ./var/lib/apt/extended_states | diff -u tar1.txt -
rm /tmp/debian-chroot.tar rm /tmp/debian-chroot.tar
@ -2971,8 +2998,6 @@ rm /tmp/debian-chroot/etc/fstab
rm /tmp/debian-chroot/etc/hostname rm /tmp/debian-chroot/etc/hostname
rm /tmp/debian-chroot/etc/resolv.conf rm /tmp/debian-chroot/etc/resolv.conf
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
rm /tmp/debian-chroot/var/lib/dpkg/status rm /tmp/debian-chroot/var/lib/dpkg/status
# 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
@ -3216,10 +3241,6 @@ rm /tmp/debian-chroot/var/lib/dpkg/status
rm /tmp/debian-chroot/var/cache/apt/archives/lock rm /tmp/debian-chroot/var/cache/apt/archives/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend
if [ "$mode" != "chrootless" ] || dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
fi
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
## delete merged usr symlinks ## delete merged usr symlinks
#rm /tmp/debian-chroot/libx32 #rm /tmp/debian-chroot/libx32
@ -3285,10 +3306,6 @@ rm /tmp/debian-chroot/var/cache/apt/archives/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
if [ "$mode" != "chrootless" ] || dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
fi
## delete merged usr symlinks ## delete merged usr symlinks
#rm /tmp/debian-chroot/libx32 #rm /tmp/debian-chroot/libx32
#rm /tmp/debian-chroot/lib64 #rm /tmp/debian-chroot/lib64
@ -3435,10 +3452,6 @@ rm /tmp/debian-chroot/var/cache/apt/archives/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
if dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
fi
## delete merged usr symlinks ## delete merged usr symlinks
#rm /tmp/debian-chroot/libx32 #rm /tmp/debian-chroot/libx32
#rm /tmp/debian-chroot/lib64 #rm /tmp/debian-chroot/lib64
@ -3497,10 +3510,6 @@ rm /tmp/debian-chroot/var/cache/apt/archives/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock
rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend
rm /tmp/debian-chroot/var/lib/apt/lists/lock rm /tmp/debian-chroot/var/lib/apt/lists/lock
if dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then
rm /tmp/debian-chroot/var/lib/dpkg/available
rm /tmp/debian-chroot/var/lib/dpkg/cmethopt
fi
## delete merged usr symlinks ## delete merged usr symlinks
#rm /tmp/debian-chroot/libx32 #rm /tmp/debian-chroot/libx32
#rm /tmp/debian-chroot/lib64 #rm /tmp/debian-chroot/lib64

View file

@ -4,4 +4,7 @@ set -exu
rootdir="$1" rootdir="$1"
chroot "$rootdir" busybox --install -s # Run busybox using an absolute path so that this script also works in case
# /proc is not mounted. Busybox uses /proc/self/exe to figure out the path
# to its executable.
chroot "$rootdir" /bin/busybox --install -s

View file

@ -90,6 +90,12 @@ def main():
chroot = Path(os.environ["FAKECHROOT_BASE_ORIG"]) chroot = Path(os.environ["FAKECHROOT_BASE_ORIG"])
# if chrootless mode is used from within a fakechroot chroot, then
# FAKECHROOT_BASE_ORIG will point at the outer chroot. We want to use
# the path from DPKG_ROOT inside of that instead
if os.environ.get("DPKG_ROOT", "") not in ["", "/"]:
chroot /= os.environ["DPKG_ROOT"].lstrip("/")
if not (chroot / "sbin" / "ldconfig").exists(): if not (chroot / "sbin" / "ldconfig").exists():
sys.exit(0) sys.exit(0)

View file

@ -97,7 +97,7 @@ get_oldaptnames() {
if [ ! -e "$1/$2" ]; then if [ ! -e "$1/$2" ]; then
return return
fi fi
gzip -dc "$1/$2" \ xz -dc "$1/$2" \
| grep-dctrl --no-field-names --show-field=Package,Version,Architecture,Filename '' \ | grep-dctrl --no-field-names --show-field=Package,Version,Architecture,Filename '' \
| paste -sd " \n" \ | paste -sd " \n" \
| while read name ver arch fname; do | while read name ver arch fname; do
@ -122,10 +122,10 @@ get_newaptnames() {
return return
fi fi
# skip empty files by trying to uncompress the first byte of the payload # skip empty files by trying to uncompress the first byte of the payload
if [ "$(gzip -dc "$1/$2" | head -c1 | wc -c)" -eq 0 ]; then if [ "$(xz -dc "$1/$2" | head -c1 | wc -c)" -eq 0 ]; then
return return
fi fi
gzip -dc "$1/$2" \ xz -dc "$1/$2" \
| grep-dctrl --no-field-names --show-field=Package,Version,Architecture,Filename,SHA256 '' \ | grep-dctrl --no-field-names --show-field=Package,Version,Architecture,Filename,SHA256 '' \
| paste -sd " \n" \ | paste -sd " \n" \
| while read name ver arch fname hash; do | while read name ver arch fname hash; do
@ -235,17 +235,17 @@ END
# /var/cache/apt/archives so that apt will not re-download *.deb # /var/cache/apt/archives so that apt will not re-download *.deb
# packages that we already have # packages that we already have
{ {
get_oldaptnames "$oldmirrordir" "dists/$dist/main/binary-$nativearch/Packages.gz" get_oldaptnames "$oldmirrordir" "dists/$dist/main/binary-$nativearch/Packages.xz"
case "$dist" in oldstable|stable) case "$dist" in oldstable|stable)
get_oldaptnames "$oldmirrordir" "dists/$dist-updates/main/binary-$nativearch/Packages.gz" get_oldaptnames "$oldmirrordir" "dists/$dist-updates/main/binary-$nativearch/Packages.xz"
;; ;;
esac esac
case "$dist" in case "$dist" in
oldstable) oldstable)
get_oldaptnames "$oldcachedir/debian-security" "dists/$dist/updates/main/binary-$nativearch/Packages.gz" get_oldaptnames "$oldcachedir/debian-security" "dists/$dist/updates/main/binary-$nativearch/Packages.xz"
;; ;;
stable) stable)
get_oldaptnames "$oldcachedir/debian-security" "dists/$dist-security/main/binary-$nativearch/Packages.gz" get_oldaptnames "$oldcachedir/debian-security" "dists/$dist-security/main/binary-$nativearch/Packages.xz"
;; ;;
esac esac
} | sort -u > "$rootdir/oldaptnames" } | sort -u > "$rootdir/oldaptnames"
@ -266,12 +266,12 @@ END
mkdir -p "$newmirrordir/dists/$dist/main/binary-$nativearch/" mkdir -p "$newmirrordir/dists/$dist/main/binary-$nativearch/"
curl --location "$mirror/dists/$dist/Release" > "$newmirrordir/dists/$dist/Release" curl --location "$mirror/dists/$dist/Release" > "$newmirrordir/dists/$dist/Release"
curl --location "$mirror/dists/$dist/Release.gpg" > "$newmirrordir/dists/$dist/Release.gpg" curl --location "$mirror/dists/$dist/Release.gpg" > "$newmirrordir/dists/$dist/Release.gpg"
curl --location "$mirror/dists/$dist/main/binary-$nativearch/Packages.gz" > "$newmirrordir/dists/$dist/main/binary-$nativearch/Packages.gz" curl --location "$mirror/dists/$dist/main/binary-$nativearch/Packages.xz" > "$newmirrordir/dists/$dist/main/binary-$nativearch/Packages.xz"
case "$dist" in oldstable|stable) case "$dist" in oldstable|stable)
mkdir -p "$newmirrordir/dists/$dist-updates/main/binary-$nativearch/" mkdir -p "$newmirrordir/dists/$dist-updates/main/binary-$nativearch/"
curl --location "$mirror/dists/$dist-updates/Release" > "$newmirrordir/dists/$dist-updates/Release" curl --location "$mirror/dists/$dist-updates/Release" > "$newmirrordir/dists/$dist-updates/Release"
curl --location "$mirror/dists/$dist-updates/Release.gpg" > "$newmirrordir/dists/$dist-updates/Release.gpg" curl --location "$mirror/dists/$dist-updates/Release.gpg" > "$newmirrordir/dists/$dist-updates/Release.gpg"
curl --location "$mirror/dists/$dist-updates/main/binary-$nativearch/Packages.gz" > "$newmirrordir/dists/$dist-updates/main/binary-$nativearch/Packages.gz" curl --location "$mirror/dists/$dist-updates/main/binary-$nativearch/Packages.xz" > "$newmirrordir/dists/$dist-updates/main/binary-$nativearch/Packages.xz"
;; ;;
esac esac
case "$dist" in case "$dist" in
@ -279,13 +279,13 @@ END
mkdir -p "$newcachedir/debian-security/dists/$dist/updates/main/binary-$nativearch/" mkdir -p "$newcachedir/debian-security/dists/$dist/updates/main/binary-$nativearch/"
curl --location "$security_mirror/dists/$dist/updates/Release" > "$newcachedir/debian-security/dists/$dist/updates/Release" curl --location "$security_mirror/dists/$dist/updates/Release" > "$newcachedir/debian-security/dists/$dist/updates/Release"
curl --location "$security_mirror/dists/$dist/updates/Release.gpg" > "$newcachedir/debian-security/dists/$dist/updates/Release.gpg" curl --location "$security_mirror/dists/$dist/updates/Release.gpg" > "$newcachedir/debian-security/dists/$dist/updates/Release.gpg"
curl --location "$security_mirror/dists/$dist/updates/main/binary-$nativearch/Packages.gz" > "$newcachedir/debian-security/dists/$dist/updates/main/binary-$nativearch/Packages.gz" curl --location "$security_mirror/dists/$dist/updates/main/binary-$nativearch/Packages.xz" > "$newcachedir/debian-security/dists/$dist/updates/main/binary-$nativearch/Packages.xz"
;; ;;
stable) stable)
mkdir -p "$newcachedir/debian-security/dists/$dist-security/main/binary-$nativearch/" mkdir -p "$newcachedir/debian-security/dists/$dist-security/main/binary-$nativearch/"
curl --location "$security_mirror/dists/$dist-security/Release" > "$newcachedir/debian-security/dists/$dist-security/Release" curl --location "$security_mirror/dists/$dist-security/Release" > "$newcachedir/debian-security/dists/$dist-security/Release"
curl --location "$security_mirror/dists/$dist-security/Release.gpg" > "$newcachedir/debian-security/dists/$dist-security/Release.gpg" curl --location "$security_mirror/dists/$dist-security/Release.gpg" > "$newcachedir/debian-security/dists/$dist-security/Release.gpg"
curl --location "$security_mirror/dists/$dist-security/main/binary-$nativearch/Packages.gz" > "$newcachedir/debian-security/dists/$dist-security/main/binary-$nativearch/Packages.gz" curl --location "$security_mirror/dists/$dist-security/main/binary-$nativearch/Packages.xz" > "$newcachedir/debian-security/dists/$dist-security/main/binary-$nativearch/Packages.xz"
;; ;;
esac esac
@ -298,17 +298,17 @@ END
# stripping the epoch from the filename and will break once mirrors change. # stripping the epoch from the filename and will break once mirrors change.
# This way, it doesn't matter where the mirror ends up storing the package. # This way, it doesn't matter where the mirror ends up storing the package.
{ {
get_newaptnames "$newmirrordir" "dists/$dist/main/binary-$nativearch/Packages.gz"; get_newaptnames "$newmirrordir" "dists/$dist/main/binary-$nativearch/Packages.xz";
case "$dist" in oldstable|stable) case "$dist" in oldstable|stable)
get_newaptnames "$newmirrordir" "dists/$dist-updates/main/binary-$nativearch/Packages.gz" get_newaptnames "$newmirrordir" "dists/$dist-updates/main/binary-$nativearch/Packages.xz"
;; ;;
esac esac
case "$dist" in case "$dist" in
oldstable) oldstable)
get_newaptnames "$newcachedir/debian-security" "dists/$dist/updates/main/binary-$nativearch/Packages.gz" get_newaptnames "$newcachedir/debian-security" "dists/$dist/updates/main/binary-$nativearch/Packages.xz"
;; ;;
stable) stable)
get_newaptnames "$newcachedir/debian-security" "dists/$dist-security/main/binary-$nativearch/Packages.gz" get_newaptnames "$newcachedir/debian-security" "dists/$dist-security/main/binary-$nativearch/Packages.xz"
;; ;;
esac esac
} | sort -u > "$rootdir/newaptnames" } | sort -u > "$rootdir/newaptnames"

View file

@ -23,13 +23,13 @@
use strict; use strict;
use warnings; use warnings;
our $VERSION = '0.8.0'; our $VERSION = '0.8.1';
use English; use English;
use Getopt::Long; use Getopt::Long;
use Pod::Usage; use Pod::Usage;
use File::Copy; use File::Copy;
use File::Path qw(make_path remove_tree); use File::Path qw(make_path);
use File::Temp qw(tempfile tempdir); use File::Temp qw(tempfile tempdir);
use File::Basename; use File::Basename;
use File::Find; use File::Find;
@ -244,9 +244,9 @@ sub get_tar_compressor {
} elsif ($filename =~ /\.lz4$/) { } elsif ($filename =~ /\.lz4$/) {
return ['lz4']; return ['lz4'];
} elsif ($filename =~ /\.(xz|txz)$/) { } elsif ($filename =~ /\.(xz|txz)$/) {
return ['xz', '--threads=0']; return ['xz'];
} elsif ($filename =~ /\.zst$/) { } elsif ($filename =~ /\.zst$/) {
return ['zstd', '--threads=0']; return ['zstd'];
} }
return; return;
} }
@ -1550,41 +1550,6 @@ sub setup {
sub run_setup() { sub run_setup() {
my $options = shift; my $options = shift;
my $dpkgversion = version->new(0);
{
my $pid = open my $fh, '-|' // error "failed to fork(): $!";
if ($pid == 0) {
# redirect stderr to /dev/null to hide error messages from dpkg
# versions before 1.20.0
open(STDERR, '>', '/dev/null')
or error "cannot open /dev/null for writing: $!";
exec 'dpkg', '--robot', '--version';
}
chomp(
my $content = do { local $/; <$fh> }
);
close $fh;
# the --robot option was introduced in 1.20.0 but until 1.20.2 the
# output contained a string after the version, separated by a
# whitespace -- since then, it's only the version
if ($? == 0 and $content =~ /^([0-9.]+)( .*)?$/) {
# dpkg is new enough for the --robot option
$dpkgversion = version->new($1);
}
}
my $aptversion = version->new(0);
{
my $pid = open my $fh, '-|', 'apt-get',
'--version' // error "failed to fork(): $!";
chomp(my $firstline = <$fh>);
close $fh;
if ( $? == 0
and $firstline =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+) \([a-z0-9-]+\)$/)
{
$aptversion = version->new($1);
}
}
{ {
my @directories = ( my @directories = (
'/etc/apt/apt.conf.d', '/etc/apt/sources.list.d', '/etc/apt/apt.conf.d', '/etc/apt/sources.list.d',
@ -1595,8 +1560,7 @@ sub run_setup() {
push @directories, '/var/lib/dpkg'; push @directories, '/var/lib/dpkg';
# since we do not know the dpkg version inside the chroot at this # since we do not know the dpkg version inside the chroot at this
# point, we can only omit it in chrootless mode # point, we can only omit it in chrootless mode
if ( $options->{mode} ne 'chrootless' if ($options->{mode} ne 'chrootless'
or $dpkgversion < "1.20.0"
or scalar @{ $options->{dpkgopts} } > 0) { or scalar @{ $options->{dpkgopts} } > 0) {
push @directories, '/etc/dpkg/dpkg.cfg.d/'; push @directories, '/etc/dpkg/dpkg.cfg.d/';
} }
@ -1609,8 +1573,7 @@ sub run_setup() {
push @directories, '/var/log/apt'; push @directories, '/var/log/apt';
# since we do not know the dpkg version inside the chroot at this # since we do not know the dpkg version inside the chroot at this
# point, we can only omit it in chrootless mode # point, we can only omit it in chrootless mode
if ( $options->{mode} ne 'chrootless' if ($options->{mode} ne 'chrootless') {
or $dpkgversion < "1.20.0") {
push @directories, '/var/lib/dpkg/triggers', push @directories, '/var/lib/dpkg/triggers',
'/var/lib/dpkg/info', '/var/lib/dpkg/alternatives', '/var/lib/dpkg/info', '/var/lib/dpkg/alternatives',
'/var/lib/dpkg/updates'; '/var/lib/dpkg/updates';
@ -1688,24 +1651,6 @@ sub run_setup() {
# options. # options.
print $conf "pkgCacheGen::ForceEssential \",\";\n"; print $conf "pkgCacheGen::ForceEssential \",\";\n";
} }
if ($options->{dryrun}
and ($aptversion < "2.1.16")) {
# Without this option, apt will fail with:
# E: Could not configure 'libc6:amd64'.
# E: Could not perform immediate configuration on 'libgcc1:amd64'.
#
# See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=953260
#
# For some while there were other immediate configuration problems
# which were fixed by changing the dependencies in src:glibc:
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972552
#
# Immediate configuration only was fixed in apt later which then also
# fixed these bugs:
# https://bugs.debian.org/973325
# https://bugs.debian.org/973305
print $conf "APT::Immediate-Configure false;\n";
}
close $conf; close $conf;
# We put certain configuration items in their own configuration file # We put certain configuration items in their own configuration file
@ -1728,29 +1673,6 @@ sub run_setup() {
close $fh; close $fh;
} }
# /var/lib/dpkg/available is required to exist or otherwise package
# removals will fail
# since we do not know the dpkg version inside the chroot at this point, we
# can only omit it in chrootless mode
if ( $options->{mode} ne 'chrootless'
or $dpkgversion < "1.20.0") {
open my $fh, '>', "$options->{root}/var/lib/dpkg/available"
or error "failed to open(): $!";
close $fh;
}
# /var/lib/dpkg/cmethopt is used by dselect
# see #930788
# since we do not know the dpkg version inside the chroot at this point, we
# can only omit it in chrootless mode
if ( $options->{mode} ne 'chrootless'
or $dpkgversion < "1.20.0") {
open my $fh, '>', "$options->{root}/var/lib/dpkg/cmethopt"
or error "failed to open(): $!";
print $fh "apt apt\n";
close $fh;
}
# we create /var/lib/dpkg/arch inside the chroot either if there is more # we create /var/lib/dpkg/arch inside the chroot either if there is more
# than the native architecture in the chroot or if chrootless mode is # than the native architecture in the chroot or if chrootless mode is
# used to create a chroot of a different architecture than the native # used to create a chroot of a different architecture than the native
@ -2039,27 +1961,10 @@ sub run_setup() {
sub run_update() { sub run_update() {
my $options = shift; my $options = shift;
my $aptversion = version->new(0);
{
my $pid = open my $fh, '-|', 'apt-get',
'--version' // error "failed to fork(): $!";
chomp(my $firstline = <$fh>);
close $fh;
if ( $? == 0
and $firstline =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+) \([a-z0-9-]+\)$/)
{
$aptversion = version->new($1);
}
}
my $aptopts = { my $aptopts = {
ARGV => ['apt-get', 'update'], ARGV => ['apt-get', 'update', '--error-on=any'],
CHDIR => $options->{root}, CHDIR => $options->{root},
}; };
if ($aptversion < "2.1.16") {
$aptopts->{FIND_APT_WARNINGS} = 1;
} else {
push @{ $aptopts->{ARGV} }, '--error-on=any';
}
info "running apt-get update..."; info "running apt-get update...";
run_apt_progress($aptopts); run_apt_progress($aptopts);
@ -3102,15 +3007,14 @@ sub run_cleanup() {
# apt since 1.6 creates the auxfiles directory. If apt inside the # apt since 1.6 creates the auxfiles directory. If apt inside the
# chroot is older than that, then it will not know how to clean it. # chroot is older than that, then it will not know how to clean it.
if (-e "$options->{root}/var/lib/apt/lists/auxfiles") { if (-e "$options->{root}/var/lib/apt/lists/auxfiles") {
remove_tree("$options->{root}/var/lib/apt/lists/auxfiles", 0 == system(
{ error => \my $err }); 'rm',
if (@$err) { '--interactive=never',
for my $diag (@$err) { '--recursive',
my ($file, $message) = %$diag; '--preserve-root',
if ($file eq '') { warning "general error: $message"; } '--one-file-system',
else { warning "problem unlinking $file: $message"; } "$options->{root}/var/lib/apt/lists/auxfiles"
} ) or error "rm failed: $?";
}
} }
} }
@ -3180,15 +3084,11 @@ sub run_cleanup() {
next if $entry eq "."; next if $entry eq ".";
next if $entry eq ".."; next if $entry eq "..";
warning "deleting files in /tmp: $entry"; warning "deleting files in /tmp: $entry";
remove_tree("$options->{root}/tmp/$entry", 0 == system(
{ error => \my $err }); 'rm', '--interactive=never',
if (@$err) { '--recursive', '--preserve-root',
for my $diag (@$err) { '--one-file-system', "$options->{root}/tmp/$entry"
my ($file, $message) = %$diag; ) or error "rm failed: $?";
if ($file eq '') { warning "general error: $message"; }
else { warning "problem unlinking $file: $message"; }
}
}
} }
closedir($dh); closedir($dh);
} }
@ -4564,8 +4464,11 @@ sub main() {
$ENV{PATH} = "/usr/sbin:/usr/bin:/sbin:/bin"; $ENV{PATH} = "/usr/sbin:/usr/bin:/sbin:/bin";
} }
foreach my $tool ('dpkg', 'dpkg-deb', 'apt-get', 'apt-cache', 'apt-config', foreach my $tool (
'tar') { 'dpkg', 'dpkg-deb', 'apt-get', 'apt-cache',
'apt-config', 'tar', 'rm', 'find',
'env'
) {
my $found = 0; my $found = 0;
foreach my $path (split /:/, $ENV{PATH}) { foreach my $path (split /:/, $ENV{PATH}) {
if (-f "$path/$tool" && -x _ ) { if (-f "$path/$tool" && -x _ ) {
@ -4578,6 +4481,49 @@ sub main() {
} }
} }
{
my $dpkgversion = version->new(0);
my $pid = open my $fh, '-|' // error "failed to fork(): $!";
if ($pid == 0) {
# redirect stderr to /dev/null to hide error messages from dpkg
# versions before 1.20.0
open(STDERR, '>', '/dev/null')
or error "cannot open /dev/null for writing: $!";
exec 'dpkg', '--robot', '--version';
}
chomp(
my $content = do { local $/; <$fh> }
);
close $fh;
# the --robot option was introduced in 1.20.0 but until 1.20.2 the
# output contained a string after the version, separated by a
# whitespace -- since then, it's only the version
if ($? == 0 and $content =~ /^([0-9.]+)( .*)?$/) {
# dpkg is new enough for the --robot option
$dpkgversion = version->new($1);
}
if ($dpkgversion < "1.20.0") {
error "need dpkg >= 1.20.0 but have $dpkgversion";
}
}
{
my $aptversion = version->new(0);
my $pid = open my $fh, '-|', 'apt-get',
'--version' // error "failed to fork(): $!";
chomp(
my $content = do { local $/; <$fh> }
);
close $fh;
if ( $? == 0
and $content =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+) \([a-z0-9-]+\)$/m) {
$aptversion = version->new($1);
}
if ($aptversion < "2.3.7") {
error "need apt >= 2.3.7 but have $aptversion";
}
}
my $check_fakechroot_running = sub { my $check_fakechroot_running = sub {
# test if we are inside fakechroot already # test if we are inside fakechroot already
# We fork a child process because setting FAKECHROOT_DETECT seems to # We fork a child process because setting FAKECHROOT_DETECT seems to
@ -5950,31 +5896,18 @@ sub main() {
# no risk of removing anything important. # no risk of removing anything important.
$pid = get_unshare_cmd( $pid = get_unshare_cmd(
sub { sub {
# File::Path will produce the error "cannot stat initial # change CWD to chroot directory because find tries to
# working directory" if the working directory cannot be # chdir to the current directory which might not be
# accessed by the unprivileged unshared user. Thus, we # accessible by the unshared user:
# first navigate to the parent of the root directory. # find: Failed to restore initial working directory
chdir "$options->{root}/.." 0 == system('env', "--chdir=$options->{root}", 'find',
or error "unable to chdir() to parent directory of" $options->{root}, '-mount',
. " $options->{root}: $!"; '-mindepth', '1', '-delete')
remove_tree($options->{root}, { error => \my $err }); or error "rm failed: $?";
if (@$err) { # ignore failure in case the unshared user doesn't have the
for my $diag (@$err) { # required permissions -- we attempt again later if
my ($file, $message) = %$diag; # necessary
if ($file eq '') { rmdir "$options->{root}";
warning "general error: $message";
} else {
# the unshared process might not have
# sufficient permissions to remove the root
# directory. We attempt its removal later, so
# don't warn if its removal fails now.
if ($file ne $options->{root}) {
warning
"problem unlinking $file: $message";
}
}
}
}
}, },
\@idmap \@idmap
); );
@ -5982,8 +5915,7 @@ sub main() {
$? == 0 or error "remove_tree failed"; $? == 0 or error "remove_tree failed";
# in unshare mode, the toplevel directory might've been created in # in unshare mode, the toplevel directory might've been created in
# a directory that the unshared user cannot change and thus cannot # a directory that the unshared user cannot change and thus cannot
# delete. If the root directory still exists after remove_tree # delete. We attempt its removal again outside as the normal user.
# above, we attempt its removal again outside as the normal user.
if (-e $options->{root}) { if (-e $options->{root}) {
rmdir "$options->{root}" rmdir "$options->{root}"
or error "cannot rmdir $options->{root}: $!"; or error "cannot rmdir $options->{root}: $!";
@ -6001,7 +5933,7 @@ sub main() {
# be removed. # be removed.
0 == system('rm', '--interactive=never', '--recursive', 0 == system('rm', '--interactive=never', '--recursive',
'--preserve-root', '--one-file-system', $options->{root}) '--preserve-root', '--one-file-system', $options->{root})
or error "rm failed: $!"; or error "rm failed: $?";
} else { } else {
error "unknown mode: $options->{mode}"; error "unknown mode: $options->{mode}";
} }
@ -7133,9 +7065,9 @@ extension to compressor applies:
.tlz lzma .tlz lzma
.lzo lzop .lzo lzop
.lz4 lz4 .lz4 lz4
.xz xz --threads=0 .xz xz
.txz xz --threads=0 .txz xz
.zst zstd --threads=0 .zst zstd
To change compression specific options, either use the respecitve environment To change compression specific options, either use the respecitve environment
variables like B<XZ_OPT> or send B<mmdebstrap> output to your compressor of variables like B<XZ_OPT> or send B<mmdebstrap> output to your compressor of