# This file contains common functions used in init and in hooks msg () { [ "${quiet}" != "y" ] && echo $@ } err () { echo "ERROR: $@" } poll_device() { local device=$1 seconds=${2//[!0-9]} [ "${seconds:-x}" = x ] && seconds=10 deciseconds=$(( seconds * 10 )) # tenths of a second sleepinterval=1 [ -b "$device" ] && return 0 if [ "$udevd_running" -eq 1 ]; then msg "Waiting $seconds seconds for device $device ..." >&2 while [ ! -b "$device" -a "$deciseconds" -gt 0 ]; do if [ "$sleepinterval" -ge 10 ]; then sleep 1 deciseconds=$(( deciseconds - 10 )) else sleep .$sleepinterval deciseconds=$(( deciseconds - sleepinterval )) sleepinterval=$(( sleepinterval * 2 )) fi done fi [ -b "$device" ] } launch_interactive_shell() { export PS1='[rootfs \W]\$ ' [ "$1" = "--exec" ] && exec sh -i sh -i } major_minor_to_device() { local dev [ -e "/sys/dev/block/$1:$2" ] || return 1 if dev=$(readlink -f "/sys/dev/block/$1:$2" 2>/dev/null); then echo "/dev/${dev##*/}" return 0 fi return 1 } run_hookfunctions() { local hook fn=$1 desc=$2 shift 2 for hook in "$@"; do [ -x "/hooks/$hook" ] || continue unset "$fn" . "/hooks/$hook" type "$fn" >/dev/null || continue msg ":: running $desc [$hook]" "$fn" done } parse_cmdline() { local _w _quoted _lhs _rhs _cmdline read -r _cmdline /run/initramfs/root-fsck elif fsck_ret 4; then err "Bailing out. Run 'fsck $root' manually" printf '%s\n' \ "********** FILESYSTEM CHECK FAILED **********" \ "* *" \ "* Please run fsck manually. After leaving *" \ "* this maintenance shell, the system will *" \ "* reboot automatically. *" \ "* *" \ "*********************************************" launch_interactive_shell echo ":: Automatic reboot in progress" sleep 2 reboot -f elif fsck_ret 2; then printf '%s\n' \ "************** REBOOT REQUIRED **************" \ "* *" \ "* automatically restarting in 10 seconds *" \ "* *" \ "*********************************************" sleep 10 reboot -f elif fsck_ret 8; then err "fsck failed on '$root'" elif fsck_ret 16; then err "Failed to invoke fsck: usage or syntax error" elif fsck_ret 32; then echo ":: fsck cancelled on user request" elif fsck_ret 128; then err "fatal error invoking fsck" fi fi } resolve_device() { local major minor dev tag tagval device=$1 # attempt to resolve devices immediately. if this fails # and udev is running, fall back on lazy resolution using # /dev/disk/by-* symlinks. this is flexible enough to support # usage of tags without udev and "slow" devices like root on # USB, which might not immediately show up. case $device in UUID=*|LABEL=*|PARTUUID=*|PARTLABEL=*) dev=$(blkid -lt "$device" -o device) if [ -z "$dev" -a "$udevd_running" -eq 1 ]; then tag=$(awk -v t="${device%%=*}" 'BEGIN { print tolower(t) }') tagval=${device#*=} dev=/dev/disk/by-$tag/$tagval fi esac [ -n "$dev" ] && device=$dev case $device in # path to kernel named block device /dev/*) if poll_device "$device" "$rootdelay"; then echo "$device" return 0 fi ;; # hex encoded major/minor, such as from LILO [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]|[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]) major=$(( 0x0$device >> 8 )) minor=$(( 0x0$device & 0xff )) ;; 0x[0-9a-fA-F][0-9a-fA-F]*) major=$(( device >> 8 )) minor=$(( device & 0xff )) ;; esac if [ -n "$major" -a -n "$minor" ]; then device=$(major_minor_to_device "$major" "$minor" || echo '/dev/root') if [ ! -b "$device" ]; then msg "Creating device node with major $major and minor $minor." >&2 mknod "$device" b "$major" "$minor" fi echo "$device" return 0 fi return 1 } default_mount_handler() { if [ ! -b "$root" ]; then err "Unable to find root device '$root'." echo "You are being dropped to a recovery shell" echo " Type 'exit' to try and continue booting" launch_interactive_shell msg "Trying to continue (this will most likely fail) ..." fi msg ":: mounting '$root' on real root" if ! mount ${fstype:+-t $fstype} -o ${rwopt:-ro}${rootflags:+,$rootflags} "$root" "$1"; then echo "You are now being dropped into an emergency shell." launch_interactive_shell msg "Trying to continue (this will most likely fail) ..." fi } # vim: set ft=sh ts=4 sw=4 et: