blob: 0065bcc8ffe26bf5d61d13b4ba9c2e741c1dc8ad [file] [log] [blame]
#!/bin/sh
fail(){
echo "$@" >&2
# The behaviour on failure of systemd when shutting down without a
# shutdownramfs is to freeze if it fails, but the behaviour of an initramfs
# on failure is to drop you into a recovery shell. The latter seems more
# useful.
exec /bin/sh
}
startswith(){
# Filter out lines that don't start with $1
# grep ^EXPR is usually sufficient, but would require escaping of EXPR.
# Instead this compares the line to the line with its prefix stripped,
# so if the line is different, then it started with that prefix.
# It's ugly, but is less logic than escaping the regular expression and
# using grep, more reliable than not making any effort to escape, and
# less surprising than requiring the parameter to be pre-escaped.
while read -r line; do
if [ "${line#"$1"}" != "$line" ]; then
printf '%s\n' "$line"
fi
done
}
recursive_umount(){
# Recursively unmount every mountpoint under $1.
# This works by filtering to select mountpoints from mountinfo that start
# with the absolute path of the directory given.
# It unmounts in reverse-order, so that it may unmount dependent mounts
# first, and it has to handle the paths having octal escape sequences.
set -- "$(readlink -f "$1")"
cut -d' ' -f5 /proc/self/mountinfo | startswith "$1" \
| sort -r | while read -r mp; do
umount "$(echo -e "$mp")"
done
}
# Give the rootfs another chance to write its state to disk.
sync
# Kill any http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/
# as we don't have any facility to cleanly shut them down in this initramfs.
killall5
# Recursively unmount the old root, so they have a chance of performing
# unmount-time cleanup.
recursive_umount /oldroot
case "$1" in
reboot|poweroff|halt)
if ! "$1" -f; then
fail "$1 command failed"
fi
;;
kexec)
# probably don't have this, but we'll try anyway
if ! kexec -e; then
fail "$1 command failed"
fi
;;
*)
fail "Unrecognized shutdown verb $1"
;;
esac