summaryrefslogtreecommitdiffstats
path: root/hooks/merged-usr
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 14:14:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 14:14:39 +0000
commitee17e45964b786b48b455959dfe68715971893fb (patch)
tree118f40aa65dc838499053413b05adfd00f839c62 /hooks/merged-usr
parentInitial commit. (diff)
downloadmmdebstrap-ee17e45964b786b48b455959dfe68715971893fb.tar.xz
mmdebstrap-ee17e45964b786b48b455959dfe68715971893fb.zip
Adding upstream version 1.4.3.upstream/1.4.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'hooks/merged-usr')
-rwxr-xr-xhooks/merged-usr/essential00.sh28
-rwxr-xr-xhooks/merged-usr/extract00.sh85
-rwxr-xr-xhooks/merged-usr/setup00.sh79
3 files changed, 192 insertions, 0 deletions
diff --git a/hooks/merged-usr/essential00.sh b/hooks/merged-usr/essential00.sh
new file mode 100755
index 0000000..d9a8130
--- /dev/null
+++ b/hooks/merged-usr/essential00.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+set -eu
+
+if [ "${MMDEBSTRAP_VERBOSITY:-1}" -ge 3 ]; then
+ set -x
+fi
+
+TARGET="$1"
+
+if [ "${MMDEBSTRAP_MODE:-}" = "chrootless" ]; then
+ APT_CONFIG=$MMDEBSTRAP_APT_CONFIG apt-get --yes install \
+ -oDPkg::Chroot-Directory= \
+ -oDPkg::Options::=--force-not-root \
+ -oDPkg::Options::=--force-script-chrootless \
+ -oDPkg::Options::=--root="$TARGET" \
+ -oDPkg::Options::=--log="$TARGET/var/log/dpkg.log" \
+ usr-is-merged
+ export DPKG_ROOT="$TARGET"
+ dpkg-query --showformat '${db:Status-Status}\n' --show usr-is-merged | grep -q '^installed$'
+ dpkg-query --showformat '${Source}\n' --show usr-is-merged | grep -q '^usrmerge$'
+ dpkg --compare-versions "1" "lt" "$(dpkg-query --showformat '${Version}\n' --show usr-is-merged)"
+else
+ APT_CONFIG=$MMDEBSTRAP_APT_CONFIG apt-get --yes install usr-is-merged
+ chroot "$TARGET" dpkg-query --showformat '${db:Status-Status}\n' --show usr-is-merged | grep -q '^installed$'
+ chroot "$TARGET" dpkg-query --showformat '${Source}\n' --show usr-is-merged | grep -q '^usrmerge$'
+ dpkg --compare-versions "1" "lt" "$(chroot "$TARGET" dpkg-query --showformat '${Version}\n' --show usr-is-merged)"
+fi
diff --git a/hooks/merged-usr/extract00.sh b/hooks/merged-usr/extract00.sh
new file mode 100755
index 0000000..7334191
--- /dev/null
+++ b/hooks/merged-usr/extract00.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+set -eu
+
+if [ "${MMDEBSTRAP_VERBOSITY:-1}" -ge 3 ]; then
+ set -x
+fi
+
+TARGET="$1"
+
+# can_usrmerge_symlink() and can_usrmerge_symlink() are
+# Copyright 2023 Helmut Grohne <helmut@subdivi.de>
+# and part of the debootstrap source in /usr/share/debootstrap/functions
+# https://salsa.debian.org/installer-team/debootstrap/-/merge_requests/96
+# https://bugs.debian.org/104989
+can_usrmerge_symlink() {
+ # Absolute symlinks can be relocated without problems.
+ test "${2#/}" = "$2" || return 0
+ while :; do
+ if test "${2#/}" != "$2"; then
+ # Handle double-slashes.
+ set -- "$1" "${2#/}"
+ elif test "${2#./}" != "$2"; then
+ # Handle ./ inside a link target.
+ set -- "$1" "${2#./}"
+ elif test "$2" = ..; then
+ # A parent directory symlink is ok if it does not
+ # cross the top level directory.
+ test "${1%/*/*}" != "$1" -a -n "${1%/*/*}"
+ return $?
+ elif test "${2#../}" != "$2"; then
+ # Symbolic link crossing / cannot be moved safely.
+ # This is prohibited by Debian Policy 10.5.
+ test "${1%/*/*}" = "$1" -o -z "${1%/*/*}" && return 1
+ set -- "${1%/*}" "${2#../}"
+ else
+ # Consider the symlink ok if its target does not
+ # contain a parent directory. When we fail here,
+ # the link target is non-minimal and doesn't happen
+ # in the archive.
+ test "${2#*/../}" = "$2"
+ return $?
+ fi
+ done
+}
+
+merge_usr_entry() {
+ # shellcheck disable=SC3043
+ local entry canon
+ canon="$TARGET/usr/${1#"$TARGET/"}"
+ test -h "$canon" &&
+ error 1 USRMERGEFAIL "cannot move %s as its destination exists as a symlink" "${1#"$TARGET"}"
+ if ! test -e "$canon"; then
+ mv "$1" "$canon"
+ return 0
+ fi
+ test -d "$1" ||
+ error 1 USRMERGEFAIL "cannot move non-directory %s as its destination exists" "${1#"$TARGET"}"
+ test -d "$canon" ||
+ error 1 USRMERGEFAIL "cannot move directory %s as its destination is not a directory" "${1#"$TARGET"}"
+ for entry in "$1/"* "$1/."*; do
+ # Some shells return . and .. on dot globs.
+ test "${entry%/.}" != "${entry%/..}" && continue
+ if test -h "$entry" && ! can_usrmerge_symlink "${entry#"$TARGET"}" "$(readlink "$entry")"; then
+ error 1 USRMERGEFAIL "cannot move relative symlink crossing top-level directory" "${entry#"$TARGET"}"
+ fi
+ # Ignore glob match failures
+ if test "${entry%'/*'}" != "${entry%'/.*'}" && ! test -e "$entry"; then
+ continue
+ fi
+ merge_usr_entry "$entry"
+ done
+ rmdir "$1"
+}
+
+# This is list includes all possible multilib directories. It must be
+# updated when new multilib directories are being added. Hopefully,
+# all new architectures use multiarch instead, so we never get to
+# update this.
+for dir in bin lib lib32 lib64 libo32 libx32 sbin; do
+ test -h "$TARGET/$dir" && continue
+ test -e "$TARGET/$dir" || continue
+ merge_usr_entry "$TARGET/$dir"
+ ln -s "usr/$dir" "$TARGET/$dir"
+done
diff --git a/hooks/merged-usr/setup00.sh b/hooks/merged-usr/setup00.sh
new file mode 100755
index 0000000..a6b08d2
--- /dev/null
+++ b/hooks/merged-usr/setup00.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# mmdebstrap does have a --merged-usr option but only as a no-op for
+# debootstrap compatibility
+#
+# Using this hook script, you can emulate what debootstrap does to set up
+# merged /usr via directory symlinks, even using the exact same shell function
+# that debootstrap uses by running mmdebstrap with:
+#
+# --setup-hook=/usr/share/mmdebstrap/hooks/merged-usr/setup00.sh
+#
+# Alternatively, you can setup merged-/usr by installing the usrmerge package:
+#
+# --include=usrmerge
+#
+# mmdebstrap will not include this functionality via a --merged-usr option
+# because there are many reasons against implementing merged-/usr that way:
+#
+# https://wiki.debian.org/Teams/Dpkg/MergedUsr
+# https://wiki.debian.org/Teams/Dpkg/FAQ#Q:_Does_dpkg_support_merged-.2Fusr-via-aliased-dirs.3F
+# https://lists.debian.org/20190219044924.GB21901@gaara.hadrons.org
+# https://lists.debian.org/YAkLOMIocggdprSQ@thunder.hadrons.org
+# https://lists.debian.org/20181223030614.GA8788@gaara.hadrons.org
+#
+# In addition, the merged-/usr-via-aliased-dirs approach violates an important
+# principle of component based software engineering one of the core design
+# ideas/goals of mmdebstrap: All the information to create a chroot of a Debian
+# based distribution should be included in its packages and their metadata.
+# Using directory symlinks as used by debootstrap contradicts this principle.
+# The information whether a distribution uses this approach to merged-/usr or
+# not is not anymore contained in its packages but in a tool from the outside.
+#
+# Example real world problem: I'm using debbisect to bisect Debian unstable
+# between 2015 and today. For which snapshot.d.o timestamp should a merged-/usr
+# chroot be created and for which ones not?
+#
+# The problem is not the idea of merged-/usr but the problem is the way how it
+# got implemented in debootstrap via directory symlinks. That way of rolling
+# out merged-/usr is bad from the dpkg point-of-view and completely opposite of
+# the vision with which in mind I wrote mmdebstrap.
+
+set -eu
+
+if [ "${MMDEBSTRAP_VERBOSITY:-1}" -ge 3 ]; then
+ set -x
+fi
+
+TARGET="$1"
+
+# now install an empty "usr-is-merged" package to avoid installing the
+# usrmerge package on this system even after init-system-helpers starts
+# depending on "usrmerge | usr-is-merged".
+#
+# This package will not end up in the final chroot because the essential
+# hook replaces it with the actual usr-is-merged package from src:usrmerge.
+
+tmpdir=$(mktemp --directory --tmpdir="$TARGET/tmp")
+mkdir -p "$tmpdir/usr-is-merged/DEBIAN"
+
+cat << END > "$tmpdir/usr-is-merged/DEBIAN/control"
+Package: usr-is-merged
+Priority: optional
+Section: oldlibs
+Maintainer: Johannes Schauer Marin Rodrigues <josch@debian.org>
+Architecture: all
+Multi-Arch: foreign
+Source: mmdebstrap-dummy-usr-is-merged
+Version: 1
+Description: dummy package created by mmdebstrap merged-usr setup hook
+ This package was generated and installed by the mmdebstrap merged-usr
+ setup hook at /usr/share/mmdebstrap/hooks/merged-usr.
+ .
+ If this package is installed in the final chroot, then this is a bug
+ in mmdebstrap. Please report: https://gitlab.mister-muffin.de/josch/mmdebstrap
+END
+dpkg-deb --build "$tmpdir/usr-is-merged" "$tmpdir/usr-is-merged.deb"
+dpkg --root="$TARGET" --log="$TARGET/var/log/dpkg.log" --install "$tmpdir/usr-is-merged.deb"
+rm "$tmpdir/usr-is-merged.deb" "$tmpdir/usr-is-merged/DEBIAN/control"
+rmdir "$tmpdir/usr-is-merged/DEBIAN" "$tmpdir/usr-is-merged" "$tmpdir"