mirror of
https://salsa.debian.org/kernel-team/initramfs-tools.git
synced 2026-01-26 07:37:54 +00:00
In some old shell versions, string comparisons in [ ... ] could go wrong if the first argument began with certain characters. It has been common practice to avoid this problem by prefixing both sides with 'x'. bash and dash have not had this problem for well over a decade, so clean this up. Further details are at <https://www.shellcheck.net/wiki/SC2268>. Signed-off-by: Ben Hutchings <benh@debian.org>
399 lines
6.7 KiB
Bash
Executable File
399 lines
6.7 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
BOOTDIR=/boot
|
|
CONF=/etc/initramfs-tools/update-initramfs.conf
|
|
mode=""
|
|
version=""
|
|
update_initramfs=yes
|
|
backup_initramfs=no
|
|
|
|
set -e
|
|
|
|
[ -r ${CONF} ] && . ${CONF}
|
|
|
|
if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] && [ $# = 1 ] && [ "$1" = -u ]; then
|
|
if dpkg-trigger --no-await update-initramfs; then
|
|
echo "update-initramfs: deferring update (trigger activated)"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
usage()
|
|
{
|
|
cat << EOF
|
|
|
|
Usage: update-initramfs {-c|-d|-u} [-k version] [-v] [-b directory]
|
|
|
|
Options:
|
|
-k version Specify kernel version or 'all'
|
|
-c Create a new initramfs
|
|
-u Update an existing initramfs
|
|
-d Remove an existing initramfs
|
|
-b directory Set alternate boot directory
|
|
-v Be verbose
|
|
|
|
See update-initramfs(8) for further details.
|
|
|
|
EOF
|
|
}
|
|
|
|
usage_error()
|
|
{
|
|
if [ -n "${1:-}" ]; then
|
|
printf "%s\\n\\n" "${*}" >&2
|
|
fi
|
|
usage >&2
|
|
exit 2
|
|
}
|
|
|
|
mild_panic()
|
|
{
|
|
if [ -n "${1:-}" ]; then
|
|
printf "%s\\n" "${*}" >&2
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
panic()
|
|
{
|
|
if [ -n "${1:-}" ]; then
|
|
printf "%s\\n" "${*}" >&2
|
|
fi
|
|
exit 1
|
|
}
|
|
|
|
verbose()
|
|
{
|
|
if [ "${verbose}" = 1 ]; then
|
|
printf "%s\\n" "${*}"
|
|
fi
|
|
}
|
|
|
|
set_initramfs()
|
|
{
|
|
initramfs="${BOOTDIR}/initrd.img-${version}"
|
|
}
|
|
|
|
|
|
# backup initramfs while running
|
|
backup_initramfs()
|
|
{
|
|
[ ! -r "${initramfs}" ] && return 0
|
|
initramfs_bak="${initramfs}.dpkg-bak"
|
|
[ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
|
|
ln -f "${initramfs}" "${initramfs_bak}" \
|
|
|| cp -a "${initramfs}" "${initramfs_bak}"
|
|
verbose "Keeping ${initramfs_bak}"
|
|
}
|
|
|
|
# keep booted initramfs
|
|
backup_booted_initramfs()
|
|
{
|
|
initramfs_bak="${initramfs}.dpkg-bak"
|
|
|
|
# first time run thus no backup
|
|
[ ! -r "${initramfs_bak}" ] && return 0
|
|
|
|
# chroot with no /proc
|
|
[ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
|
|
|
|
# no kept backup wanted
|
|
[ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
|
|
|
|
# no backup yet
|
|
if [ ! -r "${initramfs}.bak" ]; then
|
|
mv -f ${initramfs_bak} "${initramfs}.bak"
|
|
verbose "Backup ${initramfs}.bak"
|
|
return 0
|
|
fi
|
|
|
|
# keep booted initramfs
|
|
boot_initramfs=
|
|
uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
|
|
if [ -n "$uptime_days" ]; then
|
|
boot_initramfs=$(find "${initramfs}.bak" -mtime "+${uptime_days}")
|
|
fi
|
|
if [ -n "${boot_initramfs}" ]; then
|
|
mv -f "${initramfs_bak}" "${initramfs}.bak"
|
|
verbose "Backup ${initramfs}.bak"
|
|
return 0
|
|
fi
|
|
verbose "Removing current backup ${initramfs_bak}"
|
|
rm -f ${initramfs_bak}
|
|
}
|
|
|
|
# nuke generated copy
|
|
remove_initramfs_bak()
|
|
{
|
|
[ -z "${initramfs_bak:-}" ] && return 0
|
|
rm -f "${initramfs_bak}"
|
|
verbose "Removing ${initramfs_bak}"
|
|
}
|
|
|
|
|
|
generate_initramfs()
|
|
{
|
|
echo "update-initramfs: Generating ${initramfs}"
|
|
OPTS="-o"
|
|
if [ "${verbose}" = 1 ]; then
|
|
OPTS="-v ${OPTS}"
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
|
|
mv -f "${initramfs}.new" "${initramfs}"
|
|
# Guard against an unclean shutdown
|
|
sync -f "${initramfs}"
|
|
else
|
|
mkinitramfs_return="$?"
|
|
remove_initramfs_bak
|
|
rm -f "${initramfs}.new"
|
|
echo "update-initramfs: failed for ${initramfs} with $mkinitramfs_return." >&2
|
|
exit $mkinitramfs_return
|
|
fi
|
|
}
|
|
|
|
# Invoke bootloader
|
|
run_bootloader()
|
|
{
|
|
# invoke policy conformant bootloader hooks
|
|
if [ -d /etc/initramfs/post-update.d/ ]; then
|
|
run-parts --arg="${version}" --arg="${initramfs}" \
|
|
/etc/initramfs/post-update.d/
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# ro /boot is not modified
|
|
ro_boot_check()
|
|
{
|
|
# check irrelevant inside of a chroot
|
|
if [ ! -r /proc/mounts ] || ischroot; then
|
|
return 0
|
|
fi
|
|
|
|
# shellcheck disable=SC1004
|
|
boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
|
|
&& $2 == "/boot") print "ro"}' /proc/mounts)
|
|
if [ -n "${boot_opts}" ]; then
|
|
echo "W: /boot is ro mounted." >&2
|
|
echo "W: update-initramfs: Not updating ${initramfs}" >&2
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
get_sorted_versions()
|
|
{
|
|
version_list="$(
|
|
linux-version list |
|
|
while read -r version; do
|
|
test -e "${BOOTDIR}/initrd.img-$version" && echo "$version"
|
|
done |
|
|
linux-version sort --reverse
|
|
)"
|
|
verbose "Available versions: ${version_list}"
|
|
}
|
|
|
|
set_current_version()
|
|
{
|
|
if [ -f "/boot/initrd.img-$(uname -r)" ]; then
|
|
version=$(uname -r)
|
|
fi
|
|
}
|
|
|
|
set_linked_version()
|
|
{
|
|
linktarget=
|
|
if [ -e /initrd.img ] && [ -L /initrd.img ]; then
|
|
linktarget="$(basename "$(readlink /initrd.img)")"
|
|
fi
|
|
|
|
if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then
|
|
linktarget="$(basename "$(readlink /boot/initrd.img)")"
|
|
fi
|
|
|
|
if [ -z "${linktarget}" ]; then
|
|
return
|
|
fi
|
|
|
|
version="${linktarget##initrd.img-}"
|
|
}
|
|
|
|
set_highest_version()
|
|
{
|
|
get_sorted_versions
|
|
if [ -z "${version_list}" ]; then
|
|
version=
|
|
return
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
set -- ${version_list}
|
|
version=${1}
|
|
}
|
|
|
|
create()
|
|
{
|
|
if [ -z "${version}" ]; then
|
|
usage_error "Create mode requires a version argument"
|
|
fi
|
|
|
|
set_initramfs
|
|
|
|
generate_initramfs
|
|
|
|
run_bootloader
|
|
}
|
|
|
|
update()
|
|
{
|
|
if [ "${update_initramfs}" = "no" ]; then
|
|
echo "update-initramfs: Not updating initramfs."
|
|
exit 0
|
|
fi
|
|
|
|
if [ -z "${version}" ]; then
|
|
set_highest_version
|
|
fi
|
|
|
|
if [ -z "${version}" ]; then
|
|
set_linked_version
|
|
fi
|
|
|
|
if [ -z "${version}" ]; then
|
|
set_current_version
|
|
fi
|
|
|
|
if [ -z "${version}" ]; then
|
|
verbose "Nothing to do, exiting."
|
|
exit 0
|
|
fi
|
|
|
|
set_initramfs
|
|
|
|
ro_boot_check
|
|
|
|
backup_initramfs
|
|
|
|
generate_initramfs
|
|
|
|
run_bootloader
|
|
|
|
backup_booted_initramfs
|
|
}
|
|
|
|
delete()
|
|
{
|
|
if [ -z "${version}" ]; then
|
|
usage_error "Delete mode requires a version argument"
|
|
fi
|
|
|
|
set_initramfs
|
|
|
|
echo "update-initramfs: Deleting ${initramfs}"
|
|
|
|
rm -f "${initramfs}" "${initramfs}.bak"
|
|
}
|
|
|
|
# Defaults
|
|
verbose=0
|
|
|
|
##
|
|
|
|
OPTIONS=$(getopt -o "k:cudvtb:h?" --long help -n "$0" -- "$@") || usage_error
|
|
|
|
eval set -- "$OPTIONS"
|
|
|
|
while true; do
|
|
case "$1" in
|
|
-k)
|
|
version="$2"
|
|
shift 2
|
|
;;
|
|
-c)
|
|
mode="c"
|
|
shift
|
|
;;
|
|
-d)
|
|
mode="d"
|
|
shift
|
|
;;
|
|
-u)
|
|
mode="u"
|
|
shift
|
|
;;
|
|
-v)
|
|
verbose="1"
|
|
shift
|
|
;;
|
|
-t)
|
|
# accepted for compatibility, but ignored
|
|
shift
|
|
;;
|
|
-b)
|
|
BOOTDIR="$2"
|
|
if [ ! -d "${BOOTDIR}" ]; then
|
|
echo "E: ${BOOTDIR} is not a directory." >&2
|
|
exit 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-h|-\?|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ $# -ne 0 ]; then
|
|
printf "Extra argument '%s'\\n\\n" "$1" >&2
|
|
usage_error
|
|
fi
|
|
|
|
# Validate arguments
|
|
if [ -z "${mode}" ]; then
|
|
usage_error "You must specify at least one of -c, -u, or -d."
|
|
fi
|
|
|
|
if [ "${version}" = "all" ] \
|
|
|| { [ "${update_initramfs}" = "all" ] && [ -z "${version}" ]; }; then
|
|
case "${mode}" in
|
|
c)
|
|
version_list="$(linux-version list)"
|
|
;;
|
|
d | u)
|
|
get_sorted_versions
|
|
;;
|
|
esac
|
|
if [ -z "${version_list}" ]; then
|
|
verbose "Nothing to do, exiting."
|
|
exit 0
|
|
fi
|
|
|
|
OPTS="-b ${BOOTDIR}"
|
|
if [ "${verbose}" = "1" ]; then
|
|
OPTS="${OPTS} -v"
|
|
fi
|
|
for u_version in ${version_list}; do
|
|
verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
|
|
# shellcheck disable=SC2086
|
|
"${0}" -${mode} -k "${u_version}" ${OPTS}
|
|
done
|
|
exit 0
|
|
fi
|
|
|
|
|
|
case "${mode}" in
|
|
c)
|
|
create
|
|
;;
|
|
d)
|
|
delete
|
|
;;
|
|
u)
|
|
update
|
|
;;
|
|
esac
|