From ab6f0b6358549a345be3bdeab734d364ca141acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?= Date: Tue, 22 Jul 2025 11:00:33 +0200 Subject: [PATCH] remove dep on udev - remove the need to map host's /dev - remove race issues or need to have a working `udevadm settle` --- cmd/dkl-local-server/boot-img.go | 6 ++- cmd/dkl-local-server/udev.go | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 cmd/dkl-local-server/udev.go diff --git a/cmd/dkl-local-server/boot-img.go b/cmd/dkl-local-server/boot-img.go index 5d95783..dd1a17a 100644 --- a/cmd/dkl-local-server/boot-img.go +++ b/cmd/dkl-local-server/boot-img.go @@ -148,6 +148,7 @@ func setupBootImage(bootImg *os.File, ctx *renderContext) (err error) { }() log.Print("device: ", dev) + syncSysToDev() tempDir := bootImg.Name() + ".p1.mount" @@ -161,9 +162,10 @@ func setupBootImage(bootImg *os.File, ctx *renderContext) (err error) { os.RemoveAll(tempDir) }() - err = syscall.Mount(dev+"p1", tempDir, "vfat", 0, "") + devp1 := dev + "p1" + err = syscall.Mount(devp1, tempDir, "vfat", 0, "") if err != nil { - return fmt.Errorf("failed to mount %s to %s: %v", dev+"p1", tempDir, err) + return fmt.Errorf("failed to mount %s to %s: %v", devp1, tempDir, err) } defer func() { diff --git a/cmd/dkl-local-server/udev.go b/cmd/dkl-local-server/udev.go new file mode 100644 index 0000000..e2e49e0 --- /dev/null +++ b/cmd/dkl-local-server/udev.go @@ -0,0 +1,63 @@ +package main + +import ( + "bytes" + "log" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + + "golang.org/x/sys/unix" +) + +// Simulate a udev run for our needs +func syncSysToDev() { + // loop devices + sysPaths, _ := filepath.Glob("/sys/devices/virtual/block/loop*/**/dev") + for _, sysPath := range sysPaths { + mknodBlk(sysPath) + } +} + +func mknodBlk(sysPath string) { + devPath := "/dev/" + filepath.Base(filepath.Dir(sysPath)) + if _, err := os.Stat(devPath); os.IsNotExist(err) { + // ok + } else if err != nil { + log.Printf("stat %s failed: %v", devPath, err) + return + } else { + return // exists + } + + devBytes, err := os.ReadFile(sysPath) + if err != nil { + log.Printf("read %s failed: %v", sysPath, err) + return + } + devBytes = bytes.TrimSpace(devBytes) + + // rust: let Some(dev) = devBytes.split_once(':').filter_map(|a,b| Some(mkdev(a.parse().ok()?, b.parse().ok()?))); + majorStr, minorStr, ok := strings.Cut(string(devBytes), ":") + if !ok { + log.Printf("%s: invalid dev string: %s", sysPath, string(devBytes)) + return + } + major, err := strconv.ParseUint(majorStr, 10, 32) + if err != nil { + log.Printf("%s: invalid major: %q", sysPath, majorStr) + return + } + minor, err := strconv.ParseUint(minorStr, 10, 32) + if err != nil { + log.Printf("%s: invalid minor: %q", sysPath, minorStr) + return + } + + devMajMin := int(unix.Mkdev(uint32(major), uint32(minor))) + + log.Printf("mknod %s b %d %d", devPath, major, minor) + unix.Mknod(devPath, syscall.S_IFBLK|0o0600, devMajMin) +}