]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: optionally, run fsck before mounting dissected images
authorLennart Poettering <lennart@poettering.net>
Wed, 29 Jan 2020 18:13:24 +0000 (19:13 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 29 Jan 2020 18:29:44 +0000 (19:29 +0100)
Some file systems want us to run fsck before mounting, hence do so,
optionally.

src/shared/dissect-image.c
src/shared/dissect-image.h

index 62aa42d013c105d88bb87c7804681807a889821e..1ac6549ba543dbfbb4cfeaaa4bd02187c6940356 100644 (file)
@@ -28,6 +28,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "fsck-util.h"
 #include "gpt.h"
 #include "hexdecoct.h"
 #include "hostname-util.h"
@@ -896,6 +897,49 @@ static int is_loop_device(const char *path) {
         return true;
 }
 
+static int run_fsck(const char *node, const char *fstype) {
+        int r, exit_status;
+        pid_t pid;
+
+        assert(node);
+        assert(fstype);
+
+        r = fsck_exists(fstype);
+        if (r < 0) {
+                log_debug_errno(r, "Couldn't determine whether fsck for %s exists, proceeding anyway.", fstype);
+                return 0;
+        }
+        if (r == 0) {
+                log_debug("Not checking partition %s, as fsck for %s does not exist.", node, fstype);
+                return 0;
+        }
+
+        r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO, &pid);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to fork off fsck: %m");
+        if (r == 0) {
+                /* Child */
+                execl("/sbin/fsck", "/sbin/fsck", "-aT", node, NULL);
+                log_debug_errno(errno, "Failed to execl() fsck: %m");
+                _exit(FSCK_OPERATIONAL_ERROR);
+        }
+
+        exit_status = wait_for_terminate_and_check("fsck", pid, 0);
+        if (exit_status < 0)
+                return log_debug_errno(exit_status, "Failed to fork off /sbin/fsck: %m");
+
+        if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) {
+                log_debug("fsck failed with exit status %i.", exit_status);
+
+                if ((exit_status & (FSCK_SYSTEM_SHOULD_REBOOT|FSCK_ERRORS_LEFT_UNCORRECTED)) != 0)
+                        return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), "File system is corrupted, refusing.");
+
+                log_debug("Ignoring fsck error.");
+        }
+
+        return 0;
+}
+
 static int mount_partition(
                 DissectedPartition *m,
                 const char *where,
@@ -923,6 +967,12 @@ static int mount_partition(
 
         rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
 
+        if (FLAGS_SET(flags, DISSECT_IMAGE_FSCK) && rw) {
+                r = run_fsck(node, fstype);
+                if (r < 0)
+                        return r;
+        }
+
         if (directory) {
                 r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL);
                 if (r < 0)
index 359dc877d5890d75c42f50c00a8035d65289b0c0..6a666ca7c70bec70eaf39666b3705fdc10816040 100644 (file)
@@ -62,6 +62,7 @@ typedef enum DissectImageFlags {
         DISSECT_IMAGE_VALIDATE_OS         = 1 << 8,  /* Refuse mounting images that aren't identifiable as OS images */
         DISSECT_IMAGE_NO_UDEV             = 1 << 9,  /* Don't wait for udev initializing things */
         DISSECT_IMAGE_RELAX_VAR_CHECK     = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */
+        DISSECT_IMAGE_FSCK                = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
 } DissectImageFlags;
 
 struct DissectedImage {