fsck.c revision 5220a6f3a1f5a7324898ecfe7649af254cf561a6
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2010 Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is free software; you can redistribute it and/or modify it
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering under the terms of the GNU Lesser General Public License as published by
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (at your option) any later version.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is distributed in the hope that it will be useful, but
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Lesser General Public License for more details.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering You should have received a copy of the GNU Lesser General Public License
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_skip = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_force = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_show_progress = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void start_target(const char *target) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to get D-Bus connection: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_info("Running request %s/start/replace", target);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Start these units only if we can replace base.target with it */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "org.freedesktop.systemd1.Manager",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "StartUnitReplace",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "sss", "basic.target", target, "replace");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Don't print a warning if we aren't called during startup */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to start unit: %s", bus_error_message(&error, -r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int parse_proc_cmdline(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = read_one_line_file("/proc/cmdline", &line);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else if (strneq(w, "fsck.mode=force", l))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_warning("Invalid fsck parameter. Ignoring.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void test_files(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Please pass 'fsck.mode=skip' on the kernel command line rather than creating /fastboot on the root file system.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Please pass 'fsck.mode=force' on the kernel command line rather than creating /forcefsck on the root file system.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (access("/run/systemd/show-status", F_OK) >= 0 || plymouth_running())
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic double percent(int pass, unsigned long cur, unsigned long max) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Values stolen from e2fsck */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering static const int pass_table[] = {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ((double) pass_table[pass] - (double) pass_table[pass-1]) *
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Only show one progress counter at max */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Only update once every 50ms */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (j = 0; j < (unsigned) clear; j++)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int i = 0, r = EXIT_FAILURE, q;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("This program expects one or no arguments.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Find root device */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to stat() the root directory: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Virtual root devices don't need an fsck */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* check if we are already writable */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (utimensat(AT_FDCWD, "/", times, 0) == 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_info("Root directory is writable, skipping check.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!(udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev))) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to detect root device.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!(device = udev_device_get_devnode(udev_device))) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to detect device node of root directory.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } else if (pid == 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("fsck failed with error code %i.", status.si_status);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("fsck failed due to unknown reason.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* System should be rebooted. */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else if (status.si_code == CLD_EXITED && (status.si_status & 6))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Some other problem */