--- /dev/null
+. lib/prefixed_msg.sh
+
+# NB: to avoid confusing the IFS handling, ensure none of the lines is empty –
+# even if ignored!
+apt_digested_SEDS=$(cat << "DELIMITER"
+Get:
+Get:[[:digit:]]+ (.*)
+\1
+--------------------
+Hit:
+Hit:[[:digit:]]+ (.*)
+\1
+--------------------
+.
+Generation complete.
+IGNORE
+--------------------
+.
+Preconfiguring packages \.\.\.
+IGNORE
+--------------------
+.
+Preparing to unpack [[:print:]]+ \.\.\.
+IGNORE
+--------------------
+.
+Unpacking [[:print:]]+ \([[:print:]]+\)( over \([[:print:]]+\))? \.\.\.
+IGNORE
+--------------------
+Adding diversion(s):
+Adding 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)'
+ \3:[\1 → \2]
+--------------------
+Created symlink(s):
+Created symlink '([[:print:]]+)' → '([[:print:]]+)'\.
+ [\1 → \2]
+--------------------
+Installing new version of config file(s):
+Installing new version of config file ([[:print:]]+) \.\.\.
+\1
+--------------------
+Processing triggers for:
+Processing triggers for ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Purging configuration files:
+Purging configuration files for ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Removing:
+Removing ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Removing diversion(s):
+Removing 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)
+ \3:[\1 → \2]
+--------------------
+Removing obsolete conffile(s):
+Removing obsolete conffile ([[:print:]]+) \.\.\.
+\1
+--------------------
+Selecting previously unselected:
+Selecting previously unselected package ([[:print:]]+)\.
+\1
+--------------------
+Setting up:
+Setting up ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Updating to current default:
+Updating ([[:print:]]+) to current default.
+\1
+--------------------
+disabled or static unit, so not starting:
+([[:print:]]+) is a disabled or a static unit, not starting it\.
+\1
+--------------------
+
+disabled or static unit not running, so not starting:
+([[:print:]]+) is a disabled or a static unit not running, not starting it\.
+\1
+--------------------
+dpkg warns: unable to delete old directories (not empty):
+dpkg: warning: unable to delete old directory '"'"'([[:print:]]+)'"'"': Directory not empty
+\1
+--------------------
+update-alternatives: providing in auto mode:
+update-alternatives: using ([[:print:]]+) to provide ([[:print:]]+) \(([[:print:]]+)\) in auto mode
+ [\1 → \2 (\3)]
+--------------------
+Warning: Problem unlinking files (Remove Caches/13: Permission denied):
+Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
+\1
+--------------------
+.
+\(Reading database \.\.\. .*
+IGNORE
+--------------------
+.
+WARNING: apt does not have a stable CLI interface.*
+IGNORE
+--------------------
+Warning: Problem unlinking files (Remove Caches/13: Permission denied):
+Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
+\1
+--------------------
+FOLLOW_PREFIX
+([[:print:]]+) depends on ([[:print:]]+)( \([>=]+ [[:print:]]+\))?\.
+[\2 → \1]
+--------------------
+BECOME_NEXT_PREFIX
+dpkg: ([[:print:]]+): dependency problems, but removing anyway as you requested:
+dpkg warns: removing \1 despite dependency problems:
+--------------------
+DELIMITER
+)
+
+apt_digested() {
+ prefixed_msg_init 'apt_digested'
+ local APT_GET_EXIT_CODE
+ local FINISH_LINE='apt_digested_FINISH_LINE'
+
+ run_apt() {
+ set +e
+ DEBIAN_FRONTEND=noninteractive apt -y "$@"
+ APT_GET_EXIT_CODE=$?
+ set -e
+ echo "${FINISH_LINE} ${APT_GET_EXIT_CODE}"
+ }
+
+ local OUR_NEWLINE='\r' # be \n\r except on 1st run, so no empty 1st line
+ local LAST_PREFIX=
+ local LEADER_PREFIX
+ local APT_LINE
+ run_apt "$@" 2>&1 | while read -r APT_LINE; do
+ APT_LINE=$(printf '%s' "${APT_LINE}" | tr -d '\r')
+ if [ -z "${APT_LINE}" ]; then
+ continue
+ else
+ local FIRST_FIELD
+ FIRST_FIELD=$(echo "${APT_LINE}" | cut -d' ' -f1)
+ if [ "${FIRST_FIELD}" = "${FINISH_LINE}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ local EXIT_CODE
+ EXIT_CODE=$(echo "${APT_LINE}" | cut -d' ' -f2)
+ if [ "${EXIT_CODE}" != "0" ]; then
+ false
+ fi
+ break
+ fi
+ fi
+ local COMPRESSED_ITEM=
+ local PREFIX
+ local PATTERN
+ local REPLACEMENT
+ local I=0
+ local LINE
+ local OLD_IFS=${IFS}
+ local IFS
+ IFS=$(printf '\n\r')
+ for LINE in ${apt_digested_SEDS}; do
+ I=$((1 + "$I"))
+ if [ "$I" -eq 1 ]; then
+ PREFIX="${LINE}"
+ continue
+ elif [ "$I" -eq 2 ]; then
+ PATTERN="${LINE}"
+ continue
+ elif [ "$I" -eq 3 ]; then
+ REPLACEMENT="${LINE}"
+ continue
+ elif [ "$I" -eq 4 ]; then
+ I=0
+ fi
+ if printf '%s' "${APT_LINE}" | grep -E "${PATTERN}" > /dev/null; then
+ COMPRESSED_ITEM=$(printf '%s' "${APT_LINE}" | sed -E "s|${PATTERN}|${REPLACEMENT}|")
+ #if [ "${PREFIX}" = "BECOME_NEXT_PREFIX" ]; then
+ # LEADER_PREFIX="${COMPRESSED_ITEM}"
+ # COMPRESSED_ITEM=IGNORE
+ #elif [ "${PREFIX}" = "FOLLOW_PREFIX" ]; then
+ # PREFIX="${LEADER_PREFIX}"
+ #fi
+ break
+ fi
+ done
+ IFS=${OLD_IFS}
+ if [ "${COMPRESSED_ITEM}" = 'IGNORE' ]; then
+ continue
+ elif [ -z "${COMPRESSED_ITEM}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ prefixed_msg_no_nl "${APT_LINE}"
+ LAST_PREFIX=
+ else
+ if [ "${PREFIX}" != "${LAST_PREFIX}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ prefixed_msg_no_nl "# ${PREFIX}"
+ LAST_PREFIX="${PREFIX}"
+ fi
+ printf ' %s' "${COMPRESSED_ITEM}"
+ fi
+ OUR_NEWLINE='\n\r'
+ done
+
+ prefixed_msg_exit
+}
+++ /dev/null
-. lib/prefixed_msg.sh
-
-# NB: to avoid confusing the IFS handling, ensure none of the lines is empty –
-# even if ignored!
-apt_get_digested_SEDS=$(cat << "DELIMITER"
-Get:
-Get:[[:digit:]]+ (.*)
-\1
---------------------
-Hit:
-Hit:[[:digit:]]+ (.*)
-\1
---------------------
-.
-Generation complete.
-IGNORE
---------------------
-.
-Preconfiguring packages \.\.\.
-IGNORE
---------------------
-.
-Preparing to unpack [[:print:]]+ \.\.\.
-IGNORE
---------------------
-.
-Unpacking [[:print:]]+ \([[:print:]]+\)( over \([[:print:]]+\))? \.\.\.
-IGNORE
---------------------
-Adding diversion(s):
-Adding 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)'
- \3:[\1 → \2]
---------------------
-Created symlink(s):
-Created symlink '([[:print:]]+)' → '([[:print:]]+)'\.
- [\1 → \2]
---------------------
-Installing new version of config file(s):
-Installing new version of config file ([[:print:]]+) \.\.\.
-\1
---------------------
-Processing triggers for:
-Processing triggers for ([[:print:]]+) \([[:print:]]+\) \.\.\.
-\1
---------------------
-Purging configuration files:
-Purging configuration files for ([[:print:]]+) \([[:print:]]+\) \.\.\.
-\1
---------------------
-Removing:
-Removing ([[:print:]]+) \([[:print:]]+\) \.\.\.
-\1
---------------------
-Removing diversion(s):
-Removing 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)
- \3:[\1 → \2]
---------------------
-Removing obsolete conffile(s):
-Removing obsolete conffile ([[:print:]]+) \.\.\.
-\1
---------------------
-Selecting previously unselected:
-Selecting previously unselected package ([[:print:]]+)\.
-\1
---------------------
-Setting up:
-Setting up ([[:print:]]+) \([[:print:]]+\) \.\.\.
-\1
---------------------
-Updating to current default:
-Updating ([[:print:]]+) to current default.
-\1
---------------------
-disabled or static unit, so not starting:
-([[:print:]]+) is a disabled or a static unit, not starting it\.
-\1
---------------------
-
-disabled or static unit not running, so not starting:
-([[:print:]]+) is a disabled or a static unit not running, not starting it\.
-\1
---------------------
-dpkg warns: unable to delete old directories (not empty):
-dpkg: warning: unable to delete old directory '"'"'([[:print:]]+)'"'"': Directory not empty
-\1
---------------------
-update-alternatives: providing in auto mode:
-update-alternatives: using ([[:print:]]+) to provide ([[:print:]]+) \(([[:print:]]+)\) in auto mode
- [\1 → \2 (\3)]
---------------------
-Warning: Problem unlinking files (Remove Caches/13: Permission denied):
-Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
-\1
---------------------
-.
-\(Reading database \.\.\. .*
-IGNORE
---------------------
-.
-WARNING: apt does not have a stable CLI interface.*
-IGNORE
---------------------
-Warning: Problem unlinking files (Remove Caches/13: Permission denied):
-Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
-\1
---------------------
-FOLLOW_PREFIX
-([[:print:]]+) depends on ([[:print:]]+)( \([>=]+ [[:print:]]+\))?\.
-[\2 → \1]
---------------------
-BECOME_NEXT_PREFIX
-dpkg: ([[:print:]]+): dependency problems, but removing anyway as you requested:
-dpkg warns: removing \1 despite dependency problems:
---------------------
-DELIMITER
-)
-
-apt_get_digested() {
- prefixed_msg_init 'apt_get_digested'
- local APT_GET_EXIT_CODE
- local FINISH_LINE='apt_get_digested_FINISH_LINE'
-
- run_apt() {
- set +e
- DEBIAN_FRONTEND=noninteractive apt -y "$@"
- APT_GET_EXIT_CODE=$?
- set -e
- echo "${FINISH_LINE} ${APT_GET_EXIT_CODE}"
- }
-
- local OUR_NEWLINE='\r' # be \n\r except on 1st run, so no empty 1st line
- local LAST_PREFIX=
- local LEADER_PREFIX
- local APT_LINE
- run_apt "$@" 2>&1 | while read -r APT_LINE; do
- APT_LINE=$(printf '%s' "${APT_LINE}" | tr -d '\r')
- if [ -z "${APT_LINE}" ]; then
- continue
- else
- local FIRST_FIELD
- FIRST_FIELD=$(echo "${APT_LINE}" | cut -d' ' -f1)
- if [ "${FIRST_FIELD}" = "${FINISH_LINE}" ]; then
- printf '%s' "${OUR_NEWLINE}"
- local EXIT_CODE
- EXIT_CODE=$(echo "${APT_LINE}" | cut -d' ' -f2)
- if [ "${EXIT_CODE}" != "0" ]; then
- false
- fi
- break
- fi
- fi
- local COMPRESSED_ITEM=
- local PREFIX
- local PATTERN
- local REPLACEMENT
- local I=0
- local LINE
- local OLD_IFS=${IFS}
- local IFS
- IFS=$(printf '\n\r')
- for LINE in ${apt_get_digested_SEDS}; do
- I=$((1 + "$I"))
- if [ "$I" -eq 1 ]; then
- PREFIX="${LINE}"
- continue
- elif [ "$I" -eq 2 ]; then
- PATTERN="${LINE}"
- continue
- elif [ "$I" -eq 3 ]; then
- REPLACEMENT="${LINE}"
- continue
- elif [ "$I" -eq 4 ]; then
- I=0
- fi
- if printf '%s' "${APT_LINE}" | grep -E "${PATTERN}" > /dev/null; then
- COMPRESSED_ITEM=$(printf '%s' "${APT_LINE}" | sed -E "s|${PATTERN}|${REPLACEMENT}|")
- #if [ "${PREFIX}" = "BECOME_NEXT_PREFIX" ]; then
- # LEADER_PREFIX="${COMPRESSED_ITEM}"
- # COMPRESSED_ITEM=IGNORE
- #elif [ "${PREFIX}" = "FOLLOW_PREFIX" ]; then
- # PREFIX="${LEADER_PREFIX}"
- #fi
- break
- fi
- done
- IFS=${OLD_IFS}
- if [ "${COMPRESSED_ITEM}" = 'IGNORE' ]; then
- continue
- elif [ -z "${COMPRESSED_ITEM}" ]; then
- printf '%s' "${OUR_NEWLINE}"
- prefixed_msg_no_nl "${APT_LINE}"
- LAST_PREFIX=
- else
- if [ "${PREFIX}" != "${LAST_PREFIX}" ]; then
- printf '%s' "${OUR_NEWLINE}"
- prefixed_msg_no_nl "# ${PREFIX}"
- LAST_PREFIX="${PREFIX}"
- fi
- printf ' %s' "${COMPRESSED_ITEM}"
- fi
- OUR_NEWLINE='\n\r'
- done
-
- prefixed_msg_exit
-}
+++ /dev/null
-../../../bookworm/scripts/lib/expect_n_args.sh
\ No newline at end of file
--- /dev/null
+. lib/abort.sh
+
+expect_n_args() {
+ _N_MIN_ARGS="$1"
+ _N_MAX_ARGS="$2"
+ _USAGE="$3"
+ shift 3
+ _ABORT_MSG=
+ if [ "$#" -lt "${_N_MIN_ARGS}" ]; then
+ _ABORT_MSG="missing arguments (got $# instead of ${_N_MIN_ARGS})."
+ elif [ "$#" -gt "${_N_MAX_ARGS}" ]; then
+ shift "${_N_MAX_ARGS}"
+ _ABORT_MSG="unexpected arguments beyond expected number (${_N_MAX_ARGS}): $*."
+ fi
+ if [ -n "${_ABORT_MSG}" ]; then
+ if [ -n "${_USAGE}" ]; then
+ _ABORT_MSG="${_ABORT_MSG} Expected arguments: ${_USAGE}"
+ fi
+ abort "Aborting due to ${_ABORT_MSG}"
+ fi
+}
. lib/abort.sh
get_mountable_device_path() {
- _PATH_DEV="/dev/$1"
- if [ ! -b "${_PATH_DEV}" ]; then
- abort "No block device at ${_PATH_DEV}."
- elif [ $(mount | grep -E "^${_PATH_DEV}" | wc -l) -gt 0 ]; then
- abort "${_PATH_DEV} already mounted."
+ local PATH_DEV
+ PATH_DEV="/dev/$1"
+ if [ ! -b "${PATH_DEV}" ]; then
+ abort "No block device at ${PATH_DEV}."
+ else
+ local COUNT
+ COUNT=$(mount | grep -cE "^${PATH_DEV}")
+ if [ "${COUNT}" -gt 0 ]; then
+ abort "${PATH_DEV} already mounted."
+ fi
fi
- printf "${_PATH_DEV}"
+ printf '%s' "${PATH_DEV}"
}
path_tmp_timestamped () {
- printf "/tmp/${1}_$(date +'%s')"
+ printf '/tmp/%s_%s' "$1" "$(date +'%s')"
}
+++ /dev/null
-../../../bookworm/scripts/lib/trapp.sh
\ No newline at end of file
--- /dev/null
+trapp() {
+ local COMMAND="$*"
+ if [ -z "${COMMAND}" ]; then
+ COMMAND='-'
+ fi
+ trap "${COMMAND}" EXIT TERM HUP INT
+}
-#!/bin/sh
+#!/usr/bin/env dash
# based on <https://wiki.debian.org/DebianInstaller/WritableUSBStick>
set -eu
-cd $(dirname "$0")
+PARENT_DIR=$(dirname "$0")
+cd "${PARENT_DIR}"
. lib/INSTALLER_VERSION.sh
. lib/abort.sh
. lib/abort_if_command_unknown.sh
. lib/path_tmp_timestamped.sh
. lib/trapp.sh
-expect_n_args 1 2 'DEVICE (e.g. "sdb") [PATH_FILE_ISO]' $@
+FILENAME_ISO="debian-${INSTALLER_VERSION}-amd64-netinst.iso"
+URL_ISO="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/${FILENAME_ISO}"
+PATH_MNT_ISO=/mnt/iso
+
+expect_n_args 1 2 'DEVICE (e.g. "sdb") [PATH_FILE_ISO]' "$@"
abort_if_not_user root
abort_if_command_unknown mkfs.vfat
abort_if_command_unknown parted
abort_if_command_unknown rsync
abort_if_command_unknown wget
-FILENAME_ISO="debian-${INSTALLER_VERSION}-amd64-netinst.iso"
+
if [ -z "$2" ]; then
+ echo "No file path set, so will try to retrieve image online from ${URL_ISO}."
abort_if_offline
else
+ echo "With file path set, checking if we can use file at ${PATH_FILE_ISO}."
PATH_FILE_ISO=$(realpath "$2")
- if [ ! "${FILENAME_ISO}" = $(basename "${PATH_FILE_ISO}") ]; then
+ BASENAME_FILE_ISO=$(basename "${PATH_FILE_ISO}")
+ if [ ! "${FILENAME_ISO}" = "${BASENAME_FILE_ISO}" ]; then
abort "basename of PATH_FILE_ISO != expected ${FILENAME_ISO}"
elif [ ! -f "${PATH_FILE_ISO}" ]; then
abort 'no file found at PATH_FILE_ISO'
fi
fi
-PATH_DEV="$(get_mountable_device_path $1)"
-PATH_MNT_ISO=/mnt/iso
+PATH_DEV=$(get_mountable_device_path "$1")
PATH_PROCESSING="$(path_tmp_timestamped make_writable_installer)"
-RM_PROCESSING="rm -rf ${PATH_PROCESSING}"
echo "Setting up processing directory at ${PATH_PROCESSING} …"
+RM_PROCESSING="rm -rf ${PATH_PROCESSING}"
mkdir "${PATH_PROCESSING}"
trapp "${RM_PROCESSING}"
cd "${PATH_PROCESSING}"
if [ -z "${PATH_FILE_ISO}" ]; then
echo "Retrieving ${FILENAME_ISO} …"
- URL_ISO="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/${FILENAME_ISO}"
wget --quiet --output-document "${FILENAME_ISO}" "${URL_ISO}"
else
echo "Linking to ${PATH_FILE_ISO} …"
- ln -s "${PATH_FILE_ISO}"
+ ln -s "${PATH_FILE_ISO}" .
fi
echo "Preparing partition/filesystem on ${PATH_DEV} …"
echo 'RSYNC ERRORS:'
cat "${FILENAME_RSYNC_ERRORS}"
echo '\nrsync encountered errors, see above – continue? (Y/N)'
- read ANSWER
+ read -r ANSWER
FIRST_CHAR=$(echo "${ANSWER}" | cut -c1)
- if ! [ "${FIRST_CHAR}" = 'y' -o "${FIRST_CHAR}" = 'Y' ]; then
+ if ! [ "${FIRST_CHAR}" = 'y' ] || [ "${FIRST_CHAR}" = 'Y' ]; then
abort 'as requested'
fi
fi