#! /bin/sh ### BEGIN INIT INFO # Provides: checkroot mtab # Required-Start: mountdevsubfs hostname # Required-Stop: # Should-Start: keymap hwclockfirst hdparm bootlogd # Should-stop: # Default-Start: S # Default-Stop: # X-Interactive: true # Short-Description: Check to root file system. ### END INIT INFO # Include /usr/bin in path to find on_ac_power if /usr/ is on the root # partition. setglobal PATH = '/sbin:/bin:/usr/bin' setglobal FSCK_LOGFILE = '/var/log/fsck/checkroot' test $FSCKFIX || setglobal FSCKFIX = 'no' test $SULOGIN || setglobal SULOGIN = 'no' source /lib/init/vars.sh source /lib/lsb/init-functions source /lib/init/mount-functions.sh proc do_start { # Trap SIGINT so that we can handle user interrupt of fsck. trap "" INT # # Set SULOGIN in /etc/default/rcS to yes if you want a sulogin to # be spawned from this script *before anything else* with a timeout, # like sysv does. # test $SULOGIN = yes && sulogin -t 30 $CONSOLE setglobal KERNEL = $[uname -s] setglobal MACHINE = $[uname -m] read_fstab # # Activate the swap device(s) in /etc/fstab. This needs to be done # before fsck, since fsck can be quite memory-hungry. # setglobal ENABLE_SWAP = 'no' match $KERNEL { with Linux if test $NOSWAP = yes { test $VERBOSE = no || log_warning_msg "Not activating swap as requested via bootoption noswap." setglobal ENABLE_SWAP = 'no' } else { if test $swap_on_lv = yes { test $VERBOSE = no || log_warning_msg "Not activating swap on logical volume." } elif test $swap_on_file = yes { test $VERBOSE = no || log_warning_msg "Not activating swap on swapfile." } else { setglobal ENABLE_SWAP = 'yes' } } with * setglobal ENABLE_SWAP = 'yes' } if test $ENABLE_SWAP = yes { if test $VERBOSE = no { log_action_begin_msg "Activating swap" swapon -a -e >/dev/null !2 > !1 log_action_end_msg $Status } else { log_daemon_msg "Activating swap" swapon -a -v log_end_msg $Status } } # # Does the root device in /etc/fstab match with the actual device ? # If not we try to use the /dev/root alias device, and if that # fails we create a temporary node in /run. # # Do this only on Linux. Neither kFreeBSD nor Hurd have # /dev/root and the device ids used here are specific to # Linux. setglobal KERNEL = $[uname] if test $rootcheck = yes && test $KERNEL = Linux { setglobal ddev = $[mountpoint -qx $rootdev] setglobal rdev = $[mountpoint -d /] if test $ddev != $rdev && test $ddev != "4:0" { if test $[mountpoint -qx /dev/root] = "4:0" { setglobal rootdev = '/dev/root' } else { if \ rm -f /run/rootdev \ && mknod -m 600 /run/rootdev b $(rdev%:*) $(rdev#*:) \ && test -e /run/rootdev { setglobal rootdev = '/run/rootdev' } else { setglobal rootfatal = 'yes' } } } } # # Bother, said Pooh. # if test $rootfatal = yes { log_failure_msg "The device node $rootdev for the root filesystem is missing or incorrect or there is no entry for the root filesystem listed in /etc/fstab. The system is also unable to create a temporary node in /run. This means you have to fix the problem manually." log_warning_msg "A maintenance shell will now be started. CONTROL-D will terminate this shell and restart the system." # Start a single user shell on the console if ! sulogin $CONSOLE { log_failure_msg "Attempt to start maintenance shell failed. Will restart in 5 seconds." sleep 5 } test $VERBOSE = no || log_action_msg "Will now restart" reboot -f } # See if we're on AC Power. If not, we're not gonna run our # check. If on_ac_power (in /usr/) is unavailable, behave as # before and check all file systems needing it. # Disabled AC power check until fsck can be told to only check the # file system if it is corrupt when running on battery. (bug #526398) # if which on_ac_power >/dev/null 2>&1 && [ "$rootcheck" = yes ] # then # on_ac_power >/dev/null 2>&1 # if [ "$?" -eq 1 ] # then # log_warning_msg "On battery power, so skipping file system check." # rootcheck=no # fi # fi # # See if we want to check the root file system. # setglobal FSCKCODE = '0' if test -e /run/initramfs/fsck-root { setglobal rootcheck = 'no' } if is_fastboot_active { test $rootcheck = yes && log_warning_msg "Fast boot enabled, so skipping root file system check." setglobal rootcheck = 'no' } if which findmnt >/dev/null !2 > !1 { if test $[findmnt -f -n -o FSTYPE /] = "btrfs" { test $rootcheck = yes && log_warning_msg "btrfs root detected, so skipping root file system check." setglobal rootcheck = 'no' } } if test $rootcheck = yes { # # Ensure that root is quiescent and read-only before fsck'ing. # # mount -n -o remount,ro / would be the correct syntax but # mount can get confused when there is a "bind" mount defined # in fstab that bind-mounts "/" somewhere else. # # So we use mount -n -o remount,ro $rootdev / but that can # fail on older kernels on sparc64/alpha architectures due # to a bug in sys_mount(). # # As a compromise we try both. # if \ ! mount -n -o remount,ro $rootdev / \ && ! mount -n -o remount,ro -t dummytype $rootdev / !2 >/dev/null \ && ! mount -n -o remount,ro / !2 >/dev/null { log_failure_msg "Cannot check root file system because it is not mounted read-only." setglobal rootcheck = 'no' } } # # The actual checking is done here. # if test $rootcheck = yes { if test -f /forcefsck || grep -q -s -w -i "forcefsck" /proc/cmdline { setglobal force = '"-f'" } else { setglobal force = ''"" } if test $FSCKFIX = yes { setglobal fix = '"-y'" } else { setglobal fix = '"-a'" } setglobal spinner = '"-C'" match $TERM { with dumb|network|unknown|"" setglobal spinner = ''"" } # This Linux/s390x special case should go away. if test "$(KERNEL):$(MACHINE)" = Linux:s390x { setglobal spinner = ''"" } if test $VERBOSE = no { log_action_begin_msg "Checking root file system" logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -t $roottype $rootdev setglobal FSCKCODE = $Status if test $FSCKCODE = 0 { log_action_end_msg 0 } else { log_action_end_msg 1 "code $FSCKCODE" } } else { log_daemon_msg "Will now check root file system" logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t $roottype $rootdev setglobal FSCKCODE = $Status log_end_msg $FSCKCODE } } # # If there was a failure, drop into single-user mode. # # NOTE: "failure" is defined as exiting with a return code of # 4 or larger. A return code of 1 indicates that file system # errors were corrected but that the boot may proceed. A return # code of 2 or 3 indicates that the system should immediately reboot. # if test $FSCKCODE -eq 32 { log_warning_msg "File system check was interrupted by user" } elif test $FSCKCODE -gt 3 { # Surprise! Re-directing from a HERE document (as in "cat << EOF") # does not work because the root is currently read-only. log_failure_msg "An automatic file system check (fsck) of the root filesystem failed. A manual fsck must be performed, then the system restarted. The fsck should be performed in maintenance mode with the root filesystem mounted in read-only mode." log_warning_msg "The root filesystem is currently mounted in read-only mode. A maintenance shell will now be started. After performing system maintenance, press CONTROL-D to terminate the maintenance shell and restart the system." # Start a single user shell on the console if ! sulogin $CONSOLE { log_failure_msg "Attempt to start maintenance shell failed. Will restart in 5 seconds." sleep 5 } test $VERBOSE = no || log_action_msg "Will now restart" reboot -f } elif test $FSCKCODE -gt 1 { log_failure_msg "The file system check corrected errors on the root partition but requested that the system be restarted." log_warning_msg "The system will be restarted in 5 seconds." sleep 5 test $VERBOSE = no || log_action_msg "Will now restart" reboot -f } # # Remount root to final mode (rw or ro). # # See the comments above at the previous "mount -o remount" # for an explanation why we try this twice. # if ! mount -n -o remount,$rootopts,$rootmode $fstabroot / !2 >/dev/null { mount -n -o remount,$rootopts,$rootmode / } # If possible, migrate /etc/mtab to be a symlink to # /proc/mounts. Note that not all systems e.g. Hurd currently # support this. if test $rootmode != "ro" { mtab_migrate } if selinux_enabled && test -x /sbin/restorecon && test -r /etc/mtab { restorecon /etc/mtab } # # Remove /run/rootdev if we created it. # rm -f /run/rootdev # Update mount options for mounts created in early boot # S01mountkernfs.sh /etc/init.d/mountkernfs.sh reload # S03mountdevsubfs.sh /etc/init.d/mountdevsubfs.sh reload } proc do_status { # If / is read-write or swap is enabled, this script have done # its job. setglobal rootrw = 'false' setglobal swapon = 'false' if test -f /etc/mtab { if grep " / " /etc/mtab |grep -q rw { setglobal rootrw = 'true' } } if test -f /proc/swaps { if test $[cat /proc/swaps |grep -v ^Filename] { setglobal swapon = 'true' } } if test true = $rootrw || test true = $swapon { return 0 } else { return 4 } } match $1 { with start|"" do_start with restart|reload|force-reload echo "Error: argument '$1' not supported" > !2 exit 3 with stop # No-op with status do_status exit $? with * echo "Usage: checkroot.sh [start|stop]" > !2 exit 3 } :