#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

set -x
set -e

true "INFO: Currently running script: $BASH_SOURCE $@"

MYDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

cd "$MYDIR"
cd ..
cd help-steps

source pre
source colors
source variables

source "$source_code_folder_dist/packages/kicksecure/helper-scripts/usr/libexec/helper-scripts/strings.bsh"

create-live-build-image() {
   ## Record old umask so it can be restored at the end of this function.
   old_umask="$(umask)"
   ## Temporarily set Debian default umask.
   ## Compatibility with 'umask 027'.
   ## https://www.kicksecure.com/wiki/Dev/Strong_Linux_User_Account_Isolation#umask_hardening
   ## Fix APT error:
   ## > The key(s) in the keyring /etc/apt/trusted.gpg.d/derivative-temp.key.chroot.asc are ignored as the file is not readable by user '_apt' executing apt-key.
   umask -- 0022

   ## Prepare live-build directory
   dist_live_build_folder="${dist_binary_build_folder}/live-build"
   mkdir --parents -- "${dist_live_build_folder}/auto"
   pushd -- "${dist_live_build_folder}"

   ## Avoid errors related to /dev/null when running under Qubes OS
   if LC_ALL=C mount | grep ' on /home ' | grep -q 'nodev'; then
      $SUDO_TO_ROOT mount -o remount,rw,dev /home
   fi

   ## Install basic live-build configuration
   live_build_localrepo_location=""
   live_build_localrepo_suite=""
   live_build_localrepo_components=""

   if [ "${build_remote_derivative_pkgs}" != 'true' ]; then
      derivative_repository_name='kicksecure'
      set_dist_build_reprepro_folder_options
      live_build_localrepo_location="${dist_apt_repository_folder}"
      live_build_localrepo_suite="local"
      live_build_localrepo_components="main contrib non-free"
   fi

   true "INFO: sudo test"
   $SUDO_TO_ROOT test -d /usr

   $SUDO_TO_ROOT lb clean # In case there's a leftover build tree present.

   mkdir --parents -- auto

   live_build_cross_arch_config=''
   if [ "${host_architecture}" != "${dist_build_target_arch}" ]; then
      true "${green}INFO: dist_build_target_arch=${dist_build_target_arch}${reset}"
      true "${green}INFO: host_architecture=${host_architecture}${reset}"
      true "${green}INFO: Host architecture and target architecture do not match. Therefore, cross-building...${reset}"
      live_build_cross_arch_qemu=''
      case "${dist_build_target_arch}" in
         ## Both 32-bit ARM variants use the same emulator
         'armel'   ) live_build_cross_arch_qemu='arm';;
         'armhf'   ) live_build_cross_arch_qemu='arm';;
         'arm64'   ) live_build_cross_arch_qemu='aarch64';;
         'i386'    ) live_build_cross_arch_qemu='i386';;
         'amd64'   ) live_build_cross_arch_qemu='x86_64';;
         'mipsel'  ) live_build_cross_arch_qemu='mipsel';;
         'mips64el') live_build_cross_arch_qemu='mips64el';;
         ## Yes, the emulator for ppc64el really is ppc64le. This is not a typo.
         'ppc64el' ) live_build_cross_arch_qemu='ppc64le';;
         'riscv64' ) live_build_cross_arch_qemu='riscv64';;
         's390x'   ) live_build_cross_arch_qemu='s390x';;
      esac
      live_build_cross_arch_config="--bootstrap-qemu-arch ${dist_build_target_arch} \\
   --bootstrap-qemu-static /usr/bin/qemu-${live_build_cross_arch_qemu}-static \\"
   fi

   live_build_arch_specific_config=''
   case "${dist_build_target_arch}" in
      i386|amd64) live_build_arch_specific_config="--bootloaders 'grub-pc grub-efi' \\";;
      armel|armhf|arm64|riscv64) live_build_arch_specific_config="--bootloaders 'grub-efi' \\";;
      *) true "${red}WARNING: Don't specify a bootloader at all, leave live-build to figure it out, if it can.${reset}";;
   esac

   live_build_initramfs_type=''
   if [[ "${BUILD_INITRAMFS_PKGS}" =~ 'dracut' ]]; then
      live_build_initramfs_type='dracut-live'
   else
      true "${red}${bold}WARNING:${reset} ${under}The ISO to be built might be unbootable!${eunder}
- This is because the initramfs type has been set to 'none' or is not recognized.
- Please leave the initramfs type unset (which will default to dracut), or
  explicitly set it to the set of dracut packages you want. Other initramfs
  systems are not supported."
      live_build_initramfs_type='none'
   fi

   live_build_bootstrap_mirror_file="$(mktemp)"
   live_build_bootstrap_mirror_security_file="$(mktemp)"
   live_build_parent_bootstrap_mirror_file="$(mktemp)"
   live_build_parent_bootstrap_mirror_security_file="$(mktemp)"

   printf '%s\n' "\
Types: deb
URIs: ${dist_build_apt_sources_mirror}
Suites: ${dist_build_apt_stable_release}
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg" \
      | sponge "${live_build_bootstrap_mirror_file}"
   printf '%s\n' "\
Types: deb
URIs: ${dist_build_apt_sources_security_mirror}
Suites: ${dist_build_apt_stable_release}-security
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg" \
      | sponge "${live_build_bootstrap_mirror_security_file}"
   printf '%s\n' "\
Types: deb
URIs: ${dist_build_apt_sources_mirror}
Suites: ${dist_build_apt_stable_release}
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg" \
      | sponge "${live_build_parent_bootstrap_mirror_file}"
   printf '%s\n' "\
Types: deb
URIs: ${dist_build_apt_sources_security_mirror}
Suites: ${dist_build_apt_stable_release}-security
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg" \
      | sponge "${live_build_parent_bootstrap_mirror_security_file}"

   ## TODO: Should quote...? ${APTGETOPT[*]}

   ## NOTE: If changing '--bootappend-live' parameter 'rd.live.overlay.overlayfs=1'
   ##       also update at the same time grub-live:
   ##       /usr/lib/systemd/system/systemd-repart.service.d/30_grub-live.conf

   ## Sanity test.
   test -n "${dist_build_hostname}"

   printf '%s\n' "#!/bin/sh

set -e

lb config noauto \\
   --apt apt-get \\
   --apt-indices false \\
   --apt-options '${APTGETOPT[*]} --yes --allow-remove-essential' \\
   --apt-recommends false \\
   --apt-source-archives false \\
   --architecture '${dist_build_target_arch}' \\
   --archive-areas 'main contrib non-free non-free-firmware' \\
   --backports true \\
   --binary-image iso-hybrid \\
   --bootappend-live 'rd.live.overlay.overlayfs=1 boot=live components splash live-config.hostname=${dist_build_hostname} rd.live.image root=live:CDLABEL=${dist_build_type_short} rd.live.dir=live rd.live.squashimg=filesystem.squashfs' \\
   --bootappend-live-failsafe 'none' \\
   --cache false \\
   --checksums md5 \\
   --debian-installer none \\
   --debootstrap-engine mmdebstrap \\
   --debootstrap-options '--include=ca-certificates,openssl,fasttrack-archive-keyring --variant=minbase' \\
   --debug \\
   --distribution '${dist_build_apt_stable_release}' \\
   --firmware-binary false \\
   --firmware-chroot false \\
   --image-name '${dist_build_type_short}-${dist_build_version}' \\
   --initramfs '${live_build_initramfs_type}' \\
   --iso-application '${dist_build_type_short_pretty}' \\
   --iso-preparer '${dist_build_type_short_pretty} live-build; https://github.com/Kicksecure/live-build' \\
   --iso-publisher 'https://${project_clearnet}' \\
   --iso-volume '${dist_build_type_short}' \\
   --linux-packages 'linux-image linux-headers' \\
   --memtest 'memtest86+' \\
   --mirror-binary '${dist_build_apt_sources_mirror}' \\
   --mirror-binary-security '${dist_build_apt_sources_security_mirror}' \\
   --mirror-bootstrap '${live_build_bootstrap_mirror_file}' \\
   --mirror-bootstrap-security '${live_build_bootstrap_mirror_security_file}' \\
   --mirror-chroot '${dist_build_apt_sources_mirror}' \\
   --mirror-chroot-security '${dist_build_apt_sources_security_mirror}' \\
   --mirror-debian-installer '${dist_build_apt_sources_mirror}' \\
   --parent-mirror-binary '${dist_build_apt_sources_mirror}' \\
   --parent-mirror-binary-security '${dist_build_apt_sources_security_mirror}' \\
   --parent-mirror-bootstrap '${live_build_parent_bootstrap_mirror_file}' \\
   --parent-mirror-bootstrap-security '${live_build_parent_bootstrap_mirror_security_file}' \\
   --parent-mirror-chroot '${dist_build_apt_sources_mirror}' \\
   --parent-mirror-chroot-security '${dist_build_apt_sources_security_mirror}' \\
   --parent-mirror-debian-installer '${dist_build_apt_sources_mirror}' \\
   --verbose \\
   --zsync false \\
   --sysmaint-enable \\
   --unrestricted-admin-enable \\
   ${live_build_cross_arch_config} \\
   ${live_build_arch_specific_config} \\
   \"\${@}\"" \
   | sponge -- auto/config

   ## Obsolete lb config options:
   ## --apt-http-proxy '${REPO_PROXY}' # obsolete when using approx proxy

   chmod +x -- auto/config

   ## Debugging.
   bash -n -- auto/config
   realpath -- auto/config

   cp -- "${source_code_folder_dist}/live-build-data/live-build-config/live_build_auto_clean" auto/clean
   chmod +x -- auto/clean

   ## Generate initial autoconfig data (incomplete)
   lb config

   ## Install full configuration
   pushd -- config

   ## Apt archives
   mkdir --parents -- archives
   printf '%s\n' "Types: deb
URIs: http://127.0.0.1:9977/debian-fasttrack/
Suites: ${dist_build_apt_stable_release}-fasttrack
Components: main contrib
Enabled: yes
Signed-By: /usr/share/keyrings/fasttrack-archive-keyring.gpg" | sponge -- archives/fasttrack.sources.chroot
   if [ "${build_remote_derivative_pkgs}" = 'true' ]; then
      printf '%s\n' "$sources_list_build_remote_derivative" | sponge -- archives/derivative-temp.sources.chroot
      cp -- "${source_code_folder_dist}/packages/kicksecure/repository-dist/usr/share/keyrings/derivative.asc" archives/derivative-temp.key.chroot
   else
      printf '%s\n' "Types: deb
URIs: file://$(readlink -f "${live_build_localrepo_location}")
Suites: ${live_build_localrepo_suite}
Components: ${live_build_localrepo_components}
Enabled: yes
Trusted: yes" > archives/derivative-localrepo.sources.chroot
   fi

   ## Apt configuration
   live_build_package_pins="Package: calamares
Pin: release n=${dist_build_apt_stable_release}-backports
Pin-Priority: 900"
   printf '%s\n' "${live_build_package_pins}" | sponge -- archives/z-kicksecure.pref.chroot

   ## Package lists
   mkdir --parents -- package-lists
   cp -- "${source_code_folder_dist}/live-build-data/live-build-config/live_build_package_list_live" package-lists/live.list.chroot
   ## NOTE: This file is called 'z-kicksecure.list.chroot' because the list
   ## files are handled in alphabetical order and these packages MUST be
   ## handled last.
   cp -- "${source_code_folder_dist}/live-build-data/live-build-config/live_build_package_list_kicksecure" package-lists/z-kicksecure.list.chroot

   ## Replace linux-image-XXX_ARCHITECTURE_XXX and linux-headers-XXX_ARCHITECTURE_XXX with actual ${dist_build_target_arch}.
   sed -i "s/XXX_ARCHITECTURE_XXX/${dist_build_target_arch}/" package-lists/z-kicksecure.list.chroot

   case "${dist_build_target_arch}" in
      armel|mipsel|mips64el|riscv64)
         ## firmware-nonfreedom unsupported because of intel-microcode and amd64-microcode
         ## no VirtualBox utilities
         ## no support for livepatch, thus doesn't support tirdad
         ## no signed fwupd
         ## no grub-pc
         ## no shim-signed
         ## no signed grub-efi
         sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_DUMMY_TIRDAD_XXX/dummy-dependency-tirdad/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_FWUPD_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_PC_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_SHIM_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_EFI_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         ;;
      armhf)
         ## firmware-nonfreedom unsupported because of intel-microcode and amd64-microcode
         ## no VirtualBox utilities
         ## no support for livepatch, thus doesn't support tirdad
         ## has signed fwupd
         ## no grub-pc
         ## no shim-signed
         ## no signed grub-efi
         sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_DUMMY_TIRDAD_XXX/dummy-dependency-tirdad/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_FWUPD_SIGNED_XXX/fwupd-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_PC_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_SHIM_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_EFI_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         ;;
      arm64)
         ## firmware-nonfreedom unsupported because of intel-microcode and amd64-microcode
         ## no VirtualBox utilities
         ## no support for livepatch, thus doesn't support tirdad
         ## has signed fwupd
         ## no grub-pc
         ## has shim-signed
         ## has signed grub-efi
         sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_DUMMY_TIRDAD_XXX/dummy-dependency-tirdad/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_FWUPD_SIGNED_XXX/fwupd-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_PC_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_SHIM_SIGNED_XXX/shim-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_EFI_SIGNED_XXX/grub-efi-arm64-signed/' package-lists/z-kicksecure.list.chroot
         ;;
      ppc64el|s390x)
         ## firmware-nonfreedom unsupported because of intel-microcode and amd64-microcode
         ## no VirtualBox utilities
         ## supports livepatch, thus tirdad should work
         ## no signed fwupd
         ## no grub-pc
         ## no shim-signed
         ## no signed grub-efi
         sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_DUMMY_TIRDAD_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_FWUPD_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_PC_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_SHIM_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_EFI_SIGNED_XXX//' package-lists/z-kicksecure.list.chroot
         ;;
      i386)
         ## TODO: Full i386 installations are officially unsupported on Debian Trixie and higher, remove this architecture?
         ##       Quote https://www.debian.org/releases/bookworm/i386/release-notes/ch-information.en.html
         ##       > Debian's support for 32-bit PC (known as the Debian architecture i386) now no longer covers any i586 processor.
         ##       > The new minimum requirement is i686.
         ## firmware-nonfreedom supported, intel-microcode and amd64-microcode both exist
         ## Yes, amd64-microcode exists on i386.
         ## VirtualBox utilities exist
         ## no support for livepatch, thus doesn't support tirdad
         ## has signed fwupd
         ## has grub-pc
         ## has shim-signed
         ## has signed grub-efi
         if [ "$build_freedom_only" = "true" ]; then
            sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX//' package-lists/z-kicksecure.list.chroot
         elif [ "$build_freedom_only" = "false" ]; then
            sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX/firmware-nonfreedom/' package-lists/z-kicksecure.list.chroot
         fi
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX/virtualbox-guest-utils\nvirtualbox-guest-x11/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_DUMMY_TIRDAD_XXX/dummy-dependency-tirdad/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_FWUPD_SIGNED_XXX/fwupd-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_PC_XXX/grub-pc-bin/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_SHIM_SIGNED_XXX/shim-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_EFI_SIGNED_XXX/grub-efi-ia32-signed/' package-lists/z-kicksecure.list.chroot
         ;;
      amd64)
         ## Supports everything
         if [ "$build_freedom_only" = "true" ]; then
            sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX//' package-lists/z-kicksecure.list.chroot
         elif [ "$build_freedom_only" = "false" ]; then
            sed -i 's/XXX_FIRMWARE_NONFREEDOM_XXX/firmware-nonfreedom/' package-lists/z-kicksecure.list.chroot
         fi
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX/virtualbox-guest-utils\nvirtualbox-guest-x11/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_VIRTUALBOX_UTILS_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_DUMMY_TIRDAD_XXX//' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_FWUPD_SIGNED_XXX/fwupd-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_PC_XXX/grub-pc-bin/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_SHIM_SIGNED_XXX/shim-signed/' package-lists/z-kicksecure.list.chroot
         sed -i 's/XXX_GRUB_EFI_SIGNED_XXX/grub-efi-amd64-signed/' package-lists/z-kicksecure.list.chroot
         ;;
   esac

   ## Example flavor_meta_packages_to_install:
   ## kicksecure-baremetal-gui-lxqt kicksecure-baremetal-server

   live_build_flavor_line_list="$(trim_collapse_split "${flavor_meta_packages_to_install}")"
   ## Example live_build_flavor_line_list:
   ## kicksecure-baremetal-gui-lxqt \
   ## kicksecure-baremetal-server

   sed -i "s/XXX_KICKSECURE_HOST_XXX/${live_build_flavor_line_list}/" package-lists/z-kicksecure.list.chroot

   ## Branding and GRUB configuration
   mkdir --parents -- bootloaders
   cp --recursive -- "${source_code_folder_dist}/live-build-data/grub-config" bootloaders/grub-pc
   mkdir --parents -- includes.installer/usr/share/graphics
   cp -- "${source_code_folder_dist}/live-build-data/d-i-branding"/* includes.installer/usr/share/graphics/
   mkdir --parents -- 'includes.installer/usr/share/themes/Clearlooks/gtk-2.0'
   cp -- "${source_code_folder_dist}/live-build-data/d-i-theme/gtkrc" includes.installer/usr/share/themes/Clearlooks/gtk-2.0/gtkrc
   sed -i "s|@DIST_NAME@|${dist_build_type_short_pretty}|; s|@DIST_VERSION@|${dist_build_version}|;" bootloaders/grub-pc/splash.svg

   ## d-i config
   cp -- "${source_code_folder_dist}/live-build-data/preseed.cfg" includes.installer/preseed.cfg

   popd

   ## Parse full configuration
   lb config
   lb config --dump
   lb config --validate

   if [ "$build_dry_run" = "true" ]; then
      true "${bold}${cyan}INFO: Dry-run, skipping the rest of $BASH_SOURCE. ${reset}"
      ## Cannot be completely empty, or torrent creation would later fail during the prepare-release step.
      printf '%s\n' "dummy" | sponge -- "${binary_image_iso_file}"
      return 0
   fi

   ## Sanity test.
   if [ "${build_remote_derivative_pkgs}" != 'true' ]; then
      test -d "${dist_apt_repository_folder}"
   fi

   ## Build ISO bootstrap
   if ! $SUDO_TO_ROOT lb bootstrap --verbose --debug; then
      error "${bold}${red}ERROR: Live build bootstrap stage failed!${reset}"
   fi

   safe-rm -f -- "${live_build_bootstrap_mirror_file}"
   safe-rm -f -- "${live_build_bootstrap_mirror_security_file}"
   safe-rm -f -- "${live_build_parent_bootstrap_mirror_file}"
   safe-rm -f -- "${live_build_parent_bootstrap_mirror_security_file}"

   ## TODO: Set this centrally in 'help-steps/variables'? Because 'help-steps/variables' already sets variable 'CHROOT_FOLDER'.
   CHROOT_FOLDER="$(realpath -- chroot)"
   target_dracut_disable_config_snippet="$CHROOT_FOLDER/etc/dracut.conf.d/90-derivative-maker-build.conf"

   ## Keep security-misc from erroring out during installation
   $SUDO_TO_ROOT mkdir --parents -- "${CHROOT_FOLDER}/var/lib/security-misc"
   $SUDO_TO_ROOT touch "${CHROOT_FOLDER}/var/lib/security-misc/skip_install_check"

   ## Indicate to dist-base-files that its postinst script is running during a
   ## live-build build
   $SUDO_TO_ROOT mkdir --parents -- "${CHROOT_FOLDER}/var/lib/dist-base-files"
   $SUDO_TO_ROOT touch "${CHROOT_FOLDER}/var/lib/dist-base-files/live_build"

   ## Ensure kernel is configured properly, we aren't using grml-debootstrap so we have to do this ourselves
   $SUDO_TO_ROOT mkdir --parents -- "${CHROOT_FOLDER}/etc"
   $SUDO_TO_ROOT cp -- "${source_code_folder_dist}/live-build-data/live-build-config/live_build_kernel_img_conf" "${CHROOT_FOLDER}/etc/kernel-img.conf"

   ## Prevent needless initramfs builds.
   $SUDO_TO_ROOT mkdir --parents -- "$CHROOT_FOLDER/etc/dracut.conf.d"
   $SUDO_TO_ROOT cp --verbose -- "$source_dracut_disable_config_snippet" "$target_dracut_disable_config_snippet"

   ## Build ISO chroot
   if ! $SUDO_TO_ROOT lb chroot --verbose --debug; then
      error "${bold}${red}ERROR: Live build chroot stage failed!${reset}"
   fi

   ## Debugging.
   true "INFO: sudo test"
   $SUDO_TO_ROOT test -d /usr

   ## repository-dist-initializer
   ## requires: variable CHROOT_FOLDER
   repository_dist_initializer_setup

   if [ "${build_remote_derivative_pkgs}" = 'true' ]; then
      ## Deleting of temporary APT sources list file and keyring.
      safe-rm -- config/archives/derivative-temp.sources.chroot
      safe-rm -- config/archives/derivative-temp.key.chroot
   fi

   ## Extract bootloader configuration and put it in the live-build config
   ## live-build unmounts several important directories when it exits a stage,
   ## but we actually need some of those here, so we have to manually remount
   ## them.
   $SUDO_TO_ROOT mount --bind /dev "${CHROOT_FOLDER}/dev"
   $SUDO_TO_ROOT mount --bind /dev/pts "${CHROOT_FOLDER}/dev/pts"
   $SUDO_TO_ROOT mount --bind /sys "${CHROOT_FOLDER}/sys"
   $SUDO_TO_ROOT mount --bind /proc "${CHROOT_FOLDER}/proc"

   # || true needed to dodge pipefail
   live_build_bootloader_config="$(chroot_run grub-mkconfig \
      | grep '^\s*linux' \
      | head -n1 \
      | cut -d' ' -f5-)" || true

   sed -i "s/LB_BOOTAPPEND_LIVE=\"\(.*\)\"/LB_BOOTAPPEND_LIVE=\"\1 ${live_build_bootloader_config}\"/" config/binary

   ## Get rid of the temp bootloader, we don't need it anymore and it will
   ## cause installation issues
   ## Disabled, we're going to keep grub-efi while d-i is disabled.
   # chroot_run apt-get "${APTGETOPT[@]}" --yes purge grub-efi*
   # chroot_run apt-get "${APTGETOPT[@]}" --yes autopurge

   ## Enable fallback bootloader installation
   chroot_run debconf-set-selections <<< 'grub-efi-amd64 grub2/force_efi_extra_removable boolean true'

   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/proc"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/sys"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/dev/pts"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/dev"

   ## Add debian-installer
   ## Disabled.
   # if ! $SUDO_TO_ROOT lb installer --verbose --debug; then
   #    error "${bold}${red}ERROR: Live build debian-installer stage failed!${reset}"
   # fi

   ## Get rid of bad sources files, they have approx proxy junk embedded ('http://127.0.0.1/debian' / folder 'build_sources/')
   $SUDO_TO_ROOT safe-rm -f -- "${CHROOT_FOLDER}/etc/apt/sources.list"
   $SUDO_TO_ROOT safe-rm -f -- "${CHROOT_FOLDER}/etc/apt/sources.list.d"/*
   ## Don't keep recommended packages from installing, apparently live-build's way of doing this ends up persistent!
   $SUDO_TO_ROOT safe-rm -- "${CHROOT_FOLDER}/etc/apt/apt.conf.d/00recommends"
   ## Don't force Dracut to make reproducible images, the default is to not use reproducible mode, this is most likely a live-build artifact
   ## security-misc implements sets dracut's 'reproducible=yes' setting anyhow in file:
   ## ./packages/kicksecure/security-misc/etc/dracut.conf.d/30-security-misc.conf
   $SUDO_TO_ROOT safe-rm -- "${CHROOT_FOLDER}/etc/dracut.conf.d/50-reproducible.conf"
   ## Blank file most likely left by live-build
   $SUDO_TO_ROOT safe-rm -- "${CHROOT_FOLDER}/etc/udev/rules.d/70-persistent-cd.rules"
   ## We inserted this earlier to prevent security-misc from erroring out, but it could actually cause problems now, and it's no longer needed
   $SUDO_TO_ROOT safe-rm -- "${CHROOT_FOLDER}/var/lib/security-misc/skip_install_check"

   ## Sanity test.
   test -x "${CHROOT_FOLDER}/usr/bin/package-installed-check"

   ## Unreliable.
   #if [ "$(chroot_run dpkg-query --show --showformat='${Status}\n' anon-apt-sources-list)" = 'install ok installed' ]; then

   if $SUDO_TO_ROOT "${CHROOT_FOLDER}/usr/bin/package-installed-check" "anon-apt-sources-list"; then
      ## '/etc/apt/sources.list.d/debian.sources' gets overwritten and then deleted during the build.
      ## Restore the debian.sources file.
      $SUDO_TO_ROOT cp -- "${source_code_folder_dist}/packages/kicksecure/anon-apt-sources-list/etc/apt/sources.list.d/debian.sources" "${CHROOT_FOLDER}/etc/apt/sources.list.d/debian.sources"
   fi

   if $SUDO_TO_ROOT test -f "${CHROOT_FOLDER}/etc/apt/sources.list.d/debian.sources"; then
      $SUDO_TO_ROOT chmod o+r -- "${CHROOT_FOLDER}/etc/apt/sources.list.d/debian.sources"
   fi

   ## Run chroot post-install scripts from initializer-dist, TODO consider moving these file removes to there?
   ## Special mounts needed for these scripts to reliably work (in particular autologinchange will crash if this isn't done)
   $SUDO_TO_ROOT mount --bind /dev "${CHROOT_FOLDER}/dev"
   $SUDO_TO_ROOT mount --bind /dev/pts "${CHROOT_FOLDER}/dev/pts"
   $SUDO_TO_ROOT mount --bind /sys "${CHROOT_FOLDER}/sys"
   $SUDO_TO_ROOT mount --bind /proc "${CHROOT_FOLDER}/proc"
   $SUDO_TO_ROOT mount -t tmpfs tmpfs "${CHROOT_FOLDER}/run"

   if [ -d "${CHROOT_FOLDER}/usr/libexec/initializer-dist/chroot-scripts-post.d" ]; then
      ## Check which chroot scripts we got.
      chroot_run run-parts --verbose --test "/usr/libexec/initializer-dist/chroot-scripts-post.d/"

      ## Debugging.
      #chroot_run str_replace "/usr/sbin/autologinchange" "bash -x /usr/sbin/autologinchange" "/usr/libexec/initializer-dist/chroot-scripts-post.d/75_autologin"

      ## Run the chroot scripts.
      chroot_run run-parts --verbose --exit-on-error "/usr/libexec/initializer-dist/chroot-scripts-post.d/"
   else
      true "${green}${bold}INFO: Folder /usr/libexec/initializer-dist/chroot-scripts-post.d does not exist in chroot.
Not running any chroot scripts.${reset}"
   fi

   ## This flag file was needed to change the behavior of dist-base-files and initializer-dist during build, it's now done being used.
   $SUDO_TO_ROOT safe-rm -- "${CHROOT_FOLDER}/var/lib/dist-base-files/live_build"

   ## Network configuration
   printf '%s\n' "${dist_build_hostname}" | $SUDO_TO_ROOT sponge -- chroot/etc/hostname
   ## Sanity test.
   hostname_set_inside_chroot="$($SUDO_TO_ROOT cat -- chroot/etc/hostname)"
   test -n "${hostname_set_inside_chroot}"

   $SUDO_TO_ROOT cp -- "${source_code_folder_dist}/live-build-data/live-build-config/live_build_etc_hosts" "${CHROOT_FOLDER}/etc/hosts"

   ## Re-enable dracut initrd builds, then run dracut to build initrd.
   $SUDO_TO_ROOT safe-rm --force --verbose -- "$target_dracut_disable_config_snippet"

   ## For documentation on how to install dracut in a chroot, see:
   ## https://github.com/dracutdevs/dracut/issues/1596

   KERNELIMG="$(chroot_run ls -1 -- "/boot/")"
   KERNELIMG="$(printf "%s\n" "$KERNELIMG" | grep "vmlinuz")"
   KERNELIMG="$(printf "%s\n" "$KERNELIMG" | sed -n '1p')"
   ## example KERNELIMG:
   ## vmlinuz-6.1.0-9-amd64

   KERNELVER="${KERNELIMG#vmlinuz-}"
   ## example KERNELVER:
   ## 6.1.0-9-amd64

   chroot_run \
      dracut \
         --no-hostonly \
         --kver "$KERNELVER" \
         --force \
         --reproducible \
         --verbose \
         $INITRD_GENERATOR_OPTS

   ### {{{ GRUB keyboard layout

   ## Add keyboard layout options to the ISO.
   ## Use '--no-update-grub' because GRUB is handled by 'live-build'.
   ## NOTE: 'build-steps.d/*_run-chroot-scripts-post-d' also uses 'set-grub-keymap'. Should use the same/similar options.
   localectl list-x11-keymap-layouts | chroot_run set-grub-keymap --build-all --read-stdin --no-update-grub

   ## /etc/grub.d/44_kb_layout is provided by package 'usability-misc'
   chroot_run /etc/grub.d/44_kb_layout | sponge -a config/bootloaders/grub-pc/grub.cfg

   ## Fix the theme in the keyboard layout selection menu
   sed -i "s/\(submenu 'Keyboard layout options'.*\)/\1\n  source \/boot\/grub\/theme.cfg/" config/bootloaders/grub-pc/grub.cfg

   ## The layouts themselves have to appear on the binary image, so copy them
   ## out of the chroot into a binary includes dir where live-build will pick
   ## them up.
   $SUDO_TO_ROOT mkdir --parents -- config/includes.binary/boot/grub/
   $SUDO_TO_ROOT cp -r -- chroot/boot/grub/kb_layouts config/includes.binary/boot/grub/kb_layouts

   ## }}}

   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/proc"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/sys"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/dev/pts"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/dev"
   $SUDO_TO_ROOT umount "${CHROOT_FOLDER}/run"

   ## Package into an ISO
   if ! $SUDO_TO_ROOT lb binary --verbose --debug; then
      error "${bold}${red}ERROR: Live build binary stage failed!${reset}"
   fi

   ## 'live-build' does not support configuration of the output ISO file name.
   ## Rename from ISO file name defined by live-build format to derivative-maker format.
   mv "${dist_build_type_short}-${dist_build_version}-${dist_build_target_arch}.hybrid.iso" "${binary_image_iso_file}"

   popd

   ## Revert back to the original umask.
   umask -- "$old_umask"
}

main() {
   if [ "${dist_build_install_to_root}" = "true" ]; then
      true "${green}INFO: Skipping $BASH_SOURCE, because dist_build_install_to_root is set to true.${reset}"
      return 0
   fi

   if [ "${dist_build_iso}" != "true" ]; then
      true "${green}INFO: Skipping $BASH_SOURCE, because dist_build_iso is not set to true.${reset}"
      return 0
   fi

   create-live-build-image
}

main "$@"
