diff options
author | rbalocca <rbalocca@vyatta.com> | 2008-10-28 14:49:35 -0700 |
---|---|---|
committer | rbalocca <rbalocca@vyatta.com> | 2008-10-28 14:49:35 -0700 |
commit | 3939e96a8830755228bd2bbedb50db6808d36f80 (patch) | |
tree | 6c55ccb42447ad90946ee6157dab49e573ec92d2 /update-initramfs | |
download | initramfs-tools-3939e96a8830755228bd2bbedb50db6808d36f80.tar.gz initramfs-tools-3939e96a8830755228bd2bbedb50db6808d36f80.zip |
initramfs-tools-0.92j from mirrrors.kernel.orgdebian/0.92j
Diffstat (limited to 'update-initramfs')
-rwxr-xr-x | update-initramfs | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/update-initramfs b/update-initramfs new file mode 100755 index 0000000..9830a7d --- /dev/null +++ b/update-initramfs @@ -0,0 +1,553 @@ +#!/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 and be happy + [ -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 /sbin/grub ] || [ -e /boot/grub/menu.lst ] \ + || [ -x /usr/sbin/grub ]; then + if [ -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 + else + mbr_check + return 0 + fi + fi + 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 + if glantank-update-kernel --supported >/dev/null 2>&1; then + glantank-update-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 [ -L /initrd.img ]; then + linktarget="$(basename "$(readlink /initrd.img)")" + fi + + if [ -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_linked_version + fi + + if [ -z "${version}" ]; then + set_highest_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 |