anatol / booster

Fast and secure initramfs generator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Improve fsck handling

r0l1 opened this issue · comments

Quote from fsck man:

The exit code returned by fsck is the sum of the following conditions:
0 - No errors
1 - File system errors corrected
2 - System should be rebooted
4 - File system errors left uncorrected
8 - Operational error
16 - Usage or syntax error
32 - Fsck canceled by user request
128 - Shared library error
The exit code returned when multiple file systems are checked is the bit-wise OR of the exit codes for each file system that is checked.

Current code:

func fsck(dev string) error {
	if _, err := os.Stat("/usr/bin/fsck"); !os.IsNotExist(err) {
		cmd := exec.Command("/usr/bin/fsck", "-y", dev)
		if verbosityLevel >= levelDebug {
			cmd.Stdout = os.Stdout
		}
		if err := cmd.Run(); err != nil {
			if err, ok := err.(*exec.ExitError); ok {
				if err.ExitCode()&^0x1 != 0 {
					// bit 1 means errors were corrected successfully which is good
					return unwrapExitError(err)
				}
				return nil
			}

			return fmt.Errorf("fsck for %s: unknown error %v", dev, err)
		}
	}

	return nil
}

My personal improved code

  • Use fsck.ext4, because otherwise the incompatible busybox fsck will be used.
  • Bitwise checking should not be required, because we do not check multiple devices at once.
  • Ensure to check for exit code 2 and reboot
  • Hint: I enforce a fsck operation and removed the file exists check.
// TODO: check which filesystem type it is and select the correct fsck utility.
func fsck(dev string) (err error) {
	output, err := exec.Command("/usr/bin/fsck.ext4", "-y", dev).CombinedOutput()
	if err == nil {
		debug("fsck output: %s", string(output))
		return
	}

	if err, ok := err.(*exec.ExitError); ok {
		switch err.ExitCode() {
		case 0:
			return nil
		case 1: // File system errors corrected
			severe("fsck corrected filesystem errors: %s", string(output))
			return nil
		case 2: // File system errors corrected, system should be rebooted
			severe("fsck corrected filesystem errors: %s", string(output))
			syscall.Sync()
			fmt.Println("Reboot required")
			time.Sleep(3 * time.Second)
			return syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART)
		}
	}
	return fmt.Errorf("fsck for %s: unknown error %v\n%s", dev, err, string(output))
}