mirror of
https://salsa.debian.org/kernel-team/initramfs-tools.git
synced 2026-01-26 15:39:08 +00:00
"Ah. there were symlinks in / - tho they were never ever used on this system. Seems pretty broken to rely on symlinks that might (and are) years out of date." Reported-by: Peter Palfrader <weasel@debian.org> so no longer rely on this links like since 0.65, but use the "latest" according the dpkg higher heuristic check. that should make people more happy! also the symlinks should be phased out, only fallback to them if set_highest_version() finds nothing. (closes: #493863)
553 lines
10 KiB
Bash
Executable File
553 lines
10 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
STATEDIR=/var/lib/initramfs-tools
|
|
BOOTDIR=/boot
|
|
CONF=/etc/initramfs-tools/update-initramfs.conf
|
|
KPKGCONF=/etc/kernel-img.conf
|
|
USETRIGGERS=true
|
|
mode=""
|
|
version=""
|
|
|
|
set -e
|
|
|
|
[ -r ${CONF} ] && . ${CONF}
|
|
|
|
if $USETRIGGERS \
|
|
&& [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ] \
|
|
&& [ $# = 1 ] \
|
|
&& [ x"$1" = x-u ] \
|
|
&& dpkg-trigger --check-supported 2>/dev/null
|
|
then
|
|
if dpkg-trigger --no-await update-initramfs; then
|
|
echo "update-initramfs: deferring update (trigger activated)"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
usage()
|
|
{
|
|
if [ -n "${1}" ]; then
|
|
printf "${@}\n\n" >&2
|
|
fi
|
|
cat >&2 << EOF
|
|
Usage: ${0} [OPTION]...
|
|
|
|
Options:
|
|
-k [version] Specify kernel version or 'all'
|
|
-c Create a new initramfs
|
|
-u Update an existing initramfs
|
|
-d Remove an existing initramfs
|
|
-t Take over a custom initramfs with this one
|
|
-b Set alternate boot directory
|
|
-v Be verbose
|
|
-h This message
|
|
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
# chroot check
|
|
chrooted()
|
|
{
|
|
# borrowed from udev's postinst
|
|
if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
|
|
# the devicenumber/inode pair of / is the same as that of
|
|
# /sbin/init's root, so we're *not* in a chroot and hence
|
|
# return false.
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
mild_panic()
|
|
{
|
|
if [ -n "${1}" ]; then
|
|
printf "${@}\n" >&2
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
panic()
|
|
{
|
|
if [ -n "${1}" ]; then
|
|
printf "${@}\n" >&2
|
|
fi
|
|
exit 1
|
|
}
|
|
|
|
verbose()
|
|
{
|
|
if [ "${verbose}" = 1 ]; then
|
|
printf "${@}\n"
|
|
fi
|
|
}
|
|
|
|
version_exists()
|
|
{
|
|
[ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
|
|
return $?
|
|
}
|
|
|
|
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
|
|
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()
|
|
{
|
|
[ -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
|
|
if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
|
|
mv -f "${initramfs}.new" "${initramfs}"
|
|
set_sha1
|
|
else
|
|
mkinitramfs_return="$?"
|
|
remove_initramfs
|
|
rm -f "${initramfs}.new"
|
|
if [ "$mkinitramfs_return" = "2" ]; then
|
|
# minversion wasn't met, exit 0
|
|
exit 0
|
|
fi
|
|
echo "update-initramfs: failed for ${initramfs}"
|
|
exit $mkinitramfs_return
|
|
fi
|
|
}
|
|
|
|
# lilo call
|
|
run_lilo()
|
|
{
|
|
# show lilo errors on failure
|
|
if ! lilo -t > /dev/null 2>&1 ; then
|
|
echo "ERROR lilo fails for new ${initramfs}:"
|
|
echo
|
|
lilo -t
|
|
fi
|
|
lilo
|
|
}
|
|
|
|
# check if lilo is on mbr
|
|
mbr_check()
|
|
{
|
|
# try to discover grub|grub2 and be happy
|
|
[ -r /boot/grub/grub.cfg ] \
|
|
&& groot=$(awk '/^set root=/{print substr($2, 7, 3); exit}' \
|
|
/boot/grub/grub.cfg)
|
|
[ -r /boot/grub/menu.lst ] \
|
|
&& groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
|
|
/boot/grub/menu.lst)
|
|
[ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
|
|
&& dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
|
|
[ -n "${dev}" ] && [ -r ${dev} ] \
|
|
&& dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
|
|
| grep -q GRUB && return 0
|
|
|
|
# check out lilo.conf for validity
|
|
boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
|
|
[ -z "${boot}" ] && return 0
|
|
case ${boot} in
|
|
/dev/md/*)
|
|
if [ -r /proc/mdstat ]; then
|
|
MD=${boot#/dev/md/}
|
|
boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
|
|
/proc/mdstat)"
|
|
fi
|
|
;;
|
|
/dev/md*)
|
|
if [ -r /proc/mdstat ]; then
|
|
MD=${boot#/dev/}
|
|
boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
|
|
/proc/mdstat)"
|
|
fi
|
|
;;
|
|
esac
|
|
[ ! -r "${boot}" ] && return 0
|
|
dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
|
|
&& run_lilo && return 0
|
|
|
|
# no idea which bootloader is used
|
|
echo
|
|
echo "WARNING: grub and lilo installed."
|
|
echo "If you use grub as bootloader everything is fine."
|
|
echo "If you use lilo as bootloader you must run lilo!"
|
|
echo
|
|
}
|
|
|
|
# Invoke bootloader
|
|
run_bootloader()
|
|
{
|
|
# if both lilo and grub around, figure out if lilo needs to be run
|
|
if ( [ -x "$(command -v update-grub)" ] || [ -e /boot/grub/menu.lst ] \
|
|
|| [ -e /boot/grub/grub.cfg ] ) \
|
|
&& ( [ -e /etc/lilo.conf ] && [ -x /sbin/lilo ] ); then
|
|
[ -r "${KPKGCONF}" ] && \
|
|
do_b=$(awk '/^do_bootloader/{print $3}' "${KPKGCONF}")
|
|
if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
|
|
|| [ "${do_b}" = "YES" ]; then
|
|
run_lilo
|
|
return 0
|
|
elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
|
|
|| [ "${do_b}" = "NO" ]; then
|
|
return 0
|
|
fi
|
|
|
|
# do_bootloader unconfigured
|
|
mbr_check
|
|
return 0
|
|
fi
|
|
if [ -r /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
|
|
run_lilo
|
|
return 0
|
|
fi
|
|
if [ -x /sbin/elilo ]; then
|
|
elilo
|
|
return 0
|
|
fi
|
|
if [ -r /etc/zipl.conf ]; then
|
|
zipl
|
|
fi
|
|
if flash-kernel --supported >/dev/null 2>&1; then
|
|
flash-kernel
|
|
fi
|
|
}
|
|
|
|
compare_sha1()
|
|
{
|
|
sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
|
|
return $?
|
|
}
|
|
|
|
# Note that this must overwrite so that updates work.
|
|
set_sha1()
|
|
{
|
|
sha1sum "${initramfs}" > "${STATEDIR}/${version}"
|
|
}
|
|
|
|
delete_sha1()
|
|
{
|
|
rm -f "${STATEDIR}/${version}"
|
|
}
|
|
|
|
# ro /boot is not modified
|
|
ro_boot_check()
|
|
{
|
|
# check irrelevant inside of a chroot
|
|
if [ ! -r /proc/mounts ] || chrooted; then
|
|
return 0
|
|
fi
|
|
|
|
boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
|
|
&& $2 == "/boot") print "ro"}' /proc/mounts)
|
|
if [ -n "${boot_opts}" ]; then
|
|
echo "WARNING: /boot is ro mounted."
|
|
echo "update-initramfs: Not updating ${initramfs}"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
get_sorted_versions()
|
|
{
|
|
version_list=""
|
|
|
|
for gsv_x in "${STATEDIR}"/*; do
|
|
gsv_x="$(basename "${gsv_x}")"
|
|
if [ "${gsv_x}" = '*' ]; then
|
|
return 0
|
|
fi
|
|
worklist=""
|
|
for gsv_i in $version_list; do
|
|
if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
|
|
worklist="${worklist} ${gsv_x} ${gsv_i}"
|
|
gsv_x=""
|
|
else
|
|
worklist="${worklist} ${gsv_i}"
|
|
fi
|
|
done
|
|
if [ "${gsv_x}" != "" ]; then
|
|
worklist="${worklist} ${gsv_x}"
|
|
fi
|
|
version_list="${worklist}"
|
|
done
|
|
|
|
verbose "Available versions: ${version_list}"
|
|
}
|
|
|
|
set_current_version()
|
|
{
|
|
if [ -f /boot/initrd.img-`uname -r` ]; then
|
|
version=`uname -r`
|
|
fi
|
|
}
|
|
|
|
set_linked_version()
|
|
{
|
|
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
|
|
set -- ${version_list}
|
|
version=${1}
|
|
}
|
|
|
|
create()
|
|
{
|
|
if [ -z "${version}" ]; then
|
|
usage "Create mode requires a version argument"
|
|
fi
|
|
|
|
set_initramfs
|
|
|
|
if [ "${takeover}" = 0 ]; then
|
|
if version_exists "${version}"; then
|
|
panic "Cannot create version ${version}: already exists"
|
|
fi
|
|
|
|
if [ -e "${initramfs}" ]; then
|
|
panic "${initramfs} already exists, cannot create."
|
|
fi
|
|
fi
|
|
|
|
generate_initramfs
|
|
}
|
|
|
|
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
|
|
|
|
altered_check
|
|
|
|
backup_initramfs
|
|
|
|
generate_initramfs
|
|
|
|
run_bootloader
|
|
|
|
backup_booted_initramfs
|
|
}
|
|
|
|
delete()
|
|
{
|
|
if [ -z "${version}" ]; then
|
|
usage "Delete mode requires a version argument"
|
|
fi
|
|
|
|
set_initramfs
|
|
|
|
if [ ! -e "${initramfs}" ]; then
|
|
panic "Cannot delete ${initramfs}, doesn't exist."
|
|
fi
|
|
|
|
if ! version_exists "${version}"; then
|
|
panic "Cannot delete version ${version}: Not created by this utility."
|
|
fi
|
|
|
|
altered_check
|
|
|
|
echo "update-initramfs: Deleting ${initramfs}"
|
|
|
|
delete_sha1
|
|
|
|
rm -f "${initramfs}"
|
|
}
|
|
|
|
# Check for update mode on existing and modified initramfs
|
|
altered_check()
|
|
{
|
|
# No check on takeover
|
|
[ "${takeover}" = 1 ] && return 0
|
|
if [ ! -e "${initramfs}" ]; then
|
|
mild_panic "${initramfs} does not exist. Cannot update."
|
|
fi
|
|
if ! compare_sha1; then
|
|
echo "update-initramfs: ${initramfs} has been altered." >&2
|
|
mild_panic "update-initramfs: Cannot update. Override with -t option."
|
|
fi
|
|
}
|
|
|
|
# Defaults
|
|
verbose=0
|
|
yes=0
|
|
# We default to takeover=1 in Ubuntu, but not Debian
|
|
takeover=0
|
|
|
|
##
|
|
|
|
while getopts "k:cudyvtb:h?" flag; do
|
|
case "${flag}" in
|
|
k)
|
|
version="${OPTARG}"
|
|
;;
|
|
c)
|
|
mode="c"
|
|
;;
|
|
d)
|
|
mode="d"
|
|
;;
|
|
u)
|
|
mode="u"
|
|
;;
|
|
v)
|
|
verbose="1"
|
|
;;
|
|
y)
|
|
yes="1"
|
|
;;
|
|
t)
|
|
takeover="1"
|
|
;;
|
|
b)
|
|
BOOTDIR="${OPTARG}"
|
|
if [ ! -d "${BOOTDIR}" ]; then
|
|
echo "Error: ${BOOTDIR} is not a directory."
|
|
exit 1
|
|
fi
|
|
;;
|
|
h|?)
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validate arguments
|
|
if [ -z "${mode}" ]; then
|
|
usage "You must specify at least one of -c, -u, or -d."
|
|
fi
|
|
|
|
if [ "${version}" = "all" ] \
|
|
|| ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
|
|
: FIXME check for --yes, and if not ask are you sure
|
|
get_sorted_versions
|
|
if [ -z "${version_list}" ]; then
|
|
verbose "Nothing to do, exiting."
|
|
exit 0
|
|
fi
|
|
|
|
OPTS="-b ${BOOTDIR}"
|
|
if [ "${verbose}" = "1" ]; then
|
|
OPTS="${OPTS} -v"
|
|
fi
|
|
if [ "${takeover}" = "1" ]; then
|
|
OPTS="${OPTS} -t"
|
|
fi
|
|
if [ "${yes}" = "1" ]; then
|
|
OPTS="${OPTS} -y"
|
|
fi
|
|
for u_version in ${version_list}; do
|
|
# Don't stop if one version doesn't work.
|
|
set +e
|
|
verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
|
|
"${0}" -${mode} -k "${u_version}" ${OPTS}
|
|
set -e
|
|
done
|
|
exit 0
|
|
fi
|
|
|
|
|
|
case "${mode}" in
|
|
c)
|
|
create
|
|
;;
|
|
d)
|
|
delete
|
|
;;
|
|
u)
|
|
update
|
|
;;
|
|
esac
|