diff --git a/vm/os_specifics.go b/vm/os_specifics.go index 3dd2871..b097184 100644 --- a/vm/os_specifics.go +++ b/vm/os_specifics.go @@ -25,6 +25,7 @@ func terminateProcess(pid int) error { // This is never used except for a band-aid that would check // that there are no double-mounts. func checkDeviceSeemsMounted(devPathPrefix string) (bool, error) { + // Quite a bit hacky implementation, but it's to be used as a failsafe band-aid anyway. absDevPathPrefix, err := filepath.Abs(devPathPrefix) if err != nil { return false, errors.Wrap(err, "get abs path") diff --git a/vm/os_specifics_windows.go b/vm/os_specifics_windows.go index 7993d98..57cf814 100644 --- a/vm/os_specifics_windows.go +++ b/vm/os_specifics_windows.go @@ -5,7 +5,11 @@ package vm import ( "fmt" "os/exec" + "regexp" + "strings" "syscall" + + "github.com/pkg/errors" ) func prepareVMCmd(cmd *exec.Cmd) { @@ -19,7 +23,27 @@ func terminateProcess(pid int) error { return exec.Command("TASKKILL", "/T", "/F", "/PID", fmt.Sprint(pid)).Run() } +var physicalDriveRegexp = regexp.MustCompile(`PhysicalDrive(\d+)`) + +// This is never used except for a band-aid that would check +// that there are no double-mounts. func checkDeviceSeemsMounted(path string) (bool, error) { - // We do not have mount checks on Windows. - return false, nil + // Quite a bit hacky implementation, but it's to be used as a failsafe band-aid anyway. + matches := physicalDriveRegexp.FindAllStringSubmatch(path, 1) + if len(matches) == 0 { + return false, fmt.Errorf("bad device path '%v'", path) + } + + match := matches[0] + + if want, have := 2, len(match); want != have { + return false, fmt.Errorf("bad match items length: want %v, have %v (%v)", want, have, match) + } + + out, err := exec.Command("wmic", "path", "Win32_LogicalDiskToPartition", "get", "Antecedent").Output() + if err != nil { + return false, errors.Wrap(err, "exec wmic cmd") + } + + return strings.Contains(string(out), fmt.Sprintf("Disk #%v", match[1])), nil } diff --git a/vm/vm.go b/vm/vm.go index 842a14f..98dab15 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -222,7 +222,6 @@ func NewVM(logger *slog.Logger, cfg VMConfig) (*VM, error) { for _, dev := range cfg.PassthroughConfig.Block { // It's always a user's responsibility to ensure that no drives are mounted // in both host and guest system. This should serve as the last resort. - // TODO: Windows support. { seemsMounted, err := checkDeviceSeemsMounted(dev.Path) if err != nil {