From f69ca4d02cbcca90b385c0397e30a5184ea54d1f Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 25 Dec 2025 11:10:17 +0200 Subject: [PATCH] enit: switch away from using udev for fstab device prefixes --- src/enit/blockdev.go | 83 ++++++++++++++++++++++++++++++++++++++++++++ src/enit/mount.go | 76 ++++++++++++++++++++++++++++++++++------ 2 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 src/enit/blockdev.go diff --git a/src/enit/blockdev.go b/src/enit/blockdev.go new file mode 100644 index 0000000..a1fb945 --- /dev/null +++ b/src/enit/blockdev.go @@ -0,0 +1,83 @@ +package main + +import ( + "os/exec" + "strings" +) + +type BlockDevice struct { + Device string + UUID string + PartUUID string + Label string + PartLabel string + Type string +} + +func GetBlockDevices() []BlockDevice { + cmd := exec.Command("/sbin/blkid") + out, err := cmd.Output() + if err != nil { + return make([]BlockDevice, 0) + } + + blockDevices := make([]BlockDevice, 0) + + for _, line := range strings.Split(string(out), "\n") { + line := strings.TrimSpace(line) + if len(line) == 0 { + continue + } + lineSplit := strings.SplitN(line, ": ", 2) + if len(lineSplit) != 2 { + return make([]BlockDevice, 0) + } + device := lineSplit[0] + line = lineSplit[1] + + fields := []string{} + sb := &strings.Builder{} + quoted := false + for _, r := range line { + if r == '"' { + quoted = !quoted + } else if !quoted && r == ' ' { + fields = append(fields, sb.String()) + sb.Reset() + } else { + sb.WriteRune(r) + } + } + if sb.Len() > 0 { + fields = append(fields, sb.String()) + } + + bd := BlockDevice{Device: device} + + for _, field := range fields { + fieldSplit := strings.SplitN(field, "=", 2) + if len(fieldSplit) != 2 { + return make([]BlockDevice, 0) + } + fieldName := fieldSplit[0] + fieldValue := fieldSplit[1] + + switch fieldName { + case "UUID": + bd.UUID = fieldValue + case "PARTUUID": + bd.PartUUID = fieldValue + case "LABEL": + bd.Label = fieldValue + case "PARTLABEL": + bd.PartLabel = fieldValue + case "TYPE": + bd.Type = fieldValue + } + } + + blockDevices = append(blockDevices, bd) + } + + return blockDevices +} diff --git a/src/enit/mount.go b/src/enit/mount.go index 237427f..4c546e5 100644 --- a/src/enit/mount.go +++ b/src/enit/mount.go @@ -158,23 +158,77 @@ func mountFstabEntries() (error, int) { fstype := fields[2] options := fields[3] - // Replace device prefixes - if cutSource, ok := strings.CutPrefix(source, "LABEL="); ok { - source = "/dev/disk/by-label/" + strings.ReplaceAll(cutSource, " ", "\\x20") - } else if cutSource, ok := strings.CutPrefix(source, "UUID="); ok { - source = "/dev/disk/by-uuid/" + cutSource - } else if cutSource, ok := strings.CutPrefix(source, "PARTLABEL="); ok { - source = "/dev/disk/by-partlabel/" + cutSource - } else if cutSource, ok := strings.CutPrefix(source, "PARTUUID="); ok { - source = "/dev/disk/by-partuuid/" + cutSource - } - + // Convert mount options flags, data, extra := convertMountOptions(options) + // Skip if noauto flag is set if slices.Contains(extra, "noauto") { continue } + // Get block devices + blockDevices := GetBlockDevices() + + // Replace device prefixes + if strings.Contains(source, "=") { + fieldSplit := strings.SplitN(source, "=", 2) + if len(fieldSplit) != 2 { + if slices.Contains(extra, "nofail") { + fmt.Printf("Warning: could not mount fstab entry on line %d: Formatting error\n", i+1) + continue + } else { + return fmt.Errorf("Formatting error"), i + 1 + } + } + + fieldName := fieldSplit[0] + fieldValue := fieldSplit[1] + + // Reset source field + source = "" + + for _, bd := range blockDevices { + bdField := "" + + switch fieldName { + case "LABEL": + bdField = bd.Label + case "UUID": + bdField = bd.UUID + case "PARTLABEL": + bdField = bd.PartLabel + case "PARTUUID": + bdField = bd.PartUUID + default: + if slices.Contains(extra, "nofail") { + fmt.Printf("Warning: could not mount fstab entry on line %d: Formatting error\n", i+1) + continue + } else { + return fmt.Errorf("Formatting error"), i + 1 + } + } + + if bdField == "" { + continue + } + + if bdField == fieldValue { + source = bd.Device + break + } + } + + // Ensure source was set + if source == "" { + if slices.Contains(extra, "nofail") { + fmt.Printf("Warning: could not mount fstab entry on line %d: could not resolve %s=\"%s\"\n", i+1, fieldName, fieldValue) + continue + } else { + return fmt.Errorf("could not resolve %s=\"%s\"", fieldName, fieldValue), i + 1 + } + } + } + if fstype == "swap" { b := append([]byte(source), 0) const SwapFlagPrioShift = 0