From c1480b39a9e993aaa74caabf6d5c8bb865b78784 Mon Sep 17 00:00:00 2001
From: Arthur Sengileyev <arthur.sengileyev@gmail.com>
Date: Tue, 16 Aug 2022 13:39:02 +0300
Subject: Improved Windows compatibility for machine command

Signed-off-by: Arthur Sengileyev <arthur.sengileyev@gmail.com>
---
 pkg/machine/machine_windows.go          | 20 ++++++++++++++++++++
 pkg/machine/qemu/machine.go             | 24 +++++-------------------
 pkg/machine/qemu/machine_unix.go        | 33 +++++++++++++++++++++++++++++++++
 pkg/machine/qemu/machine_unsupported.go |  4 ++--
 pkg/machine/qemu/machine_windows.go     | 27 +++++++++++++++++++++++++++
 pkg/machine/qemu/options_windows.go     | 13 +++++++++++++
 pkg/machine/wsl/machine.go              |  2 +-
 pkg/machine/wsl/util_windows.go         | 12 ------------
 8 files changed, 101 insertions(+), 34 deletions(-)
 create mode 100644 pkg/machine/machine_windows.go
 create mode 100644 pkg/machine/qemu/machine_unix.go
 create mode 100644 pkg/machine/qemu/machine_windows.go
 create mode 100644 pkg/machine/qemu/options_windows.go

(limited to 'pkg')

diff --git a/pkg/machine/machine_windows.go b/pkg/machine/machine_windows.go
new file mode 100644
index 000000000..c414986cf
--- /dev/null
+++ b/pkg/machine/machine_windows.go
@@ -0,0 +1,20 @@
+//go:build windows
+// +build windows
+
+package machine
+
+import (
+	"syscall"
+)
+
+func GetProcessState(pid int) (active bool, exitCode int) {
+	const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
+	handle, err := syscall.OpenProcess(da, false, uint32(pid))
+	if err != nil {
+		return false, int(syscall.ERROR_PROC_NOT_FOUND)
+	}
+
+	var code uint32
+	syscall.GetExitCodeProcess(handle, &code)
+	return code == 259, int(code)
+}
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index e97b68e31..b59f07876 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -1,5 +1,5 @@
-//go:build (amd64 && !windows) || (arm64 && !windows)
-// +build amd64,!windows arm64,!windows
+//go:build amd64 || arm64
+// +build amd64 arm64
 
 package qemu
 
@@ -33,7 +33,6 @@ import (
 	"github.com/digitalocean/go-qemu/qmp"
 	"github.com/docker/go-units"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/sys/unix"
 )
 
 var (
@@ -125,7 +124,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
 		return nil, err
 	}
 	vm.QMPMonitor = monitor
-	cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address.GetPath() + ",server=on,wait=off"}...)
+	cmd = append(cmd, []string{"-qmp", monitor.Network + ":" + monitor.Address.GetPath() + ",server=on,wait=off"}...)
 
 	// Add network
 	// Right now the mac address is hardcoded so that the host networking gives it a specific IP address.  This is
@@ -629,14 +628,9 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
 			break
 		}
 		// check if qemu is still alive
-		var status syscall.WaitStatus
-		pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
+		err := checkProcessStatus("qemu", cmd.Process.Pid, stderrBuf)
 		if err != nil {
-			return fmt.Errorf("failed to read qemu process status: %w", err)
-		}
-		if pid > 0 {
-			// child exited
-			return fmt.Errorf("qemu exited unexpectedly with exit code %d, stderr: %s", status.ExitStatus(), stderrBuf.String())
+			return err
 		}
 		time.Sleep(wait)
 		wait++
@@ -1724,14 +1718,6 @@ func (p *Provider) RemoveAndCleanMachines() error {
 	return prevErr
 }
 
-func isProcessAlive(pid int) bool {
-	err := unix.Kill(pid, syscall.Signal(0))
-	if err == nil || err == unix.EPERM {
-		return true
-	}
-	return false
-}
-
 func (p *Provider) VMType() string {
 	return vmtype
 }
diff --git a/pkg/machine/qemu/machine_unix.go b/pkg/machine/qemu/machine_unix.go
new file mode 100644
index 000000000..84ee191d1
--- /dev/null
+++ b/pkg/machine/qemu/machine_unix.go
@@ -0,0 +1,33 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package qemu
+
+import (
+	"bytes"
+	"fmt"
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+func isProcessAlive(pid int) bool {
+	err := unix.Kill(pid, syscall.Signal(0))
+	if err == nil || err == unix.EPERM {
+		return true
+	}
+	return false
+}
+
+func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) error {
+	var status syscall.WaitStatus
+	pid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil)
+	if err != nil {
+		return fmt.Errorf("failed to read qem%su process status: %w", processHint, err)
+	}
+	if pid > 0 {
+		// child exited
+		return fmt.Errorf("%s exited unexpectedly with exit code %d, stderr: %s", processHint, status.ExitStatus(), stderrBuf.String())
+	}
+	return nil
+}
diff --git a/pkg/machine/qemu/machine_unsupported.go b/pkg/machine/qemu/machine_unsupported.go
index 794e710f9..7a9a2531d 100644
--- a/pkg/machine/qemu/machine_unsupported.go
+++ b/pkg/machine/qemu/machine_unsupported.go
@@ -1,4 +1,4 @@
-//go:build (!amd64 && !arm64) || windows
-// +build !amd64,!arm64 windows
+//go:build (!amd64 && !arm64)
+// +build !amd64,!arm64
 
 package qemu
diff --git a/pkg/machine/qemu/machine_windows.go b/pkg/machine/qemu/machine_windows.go
new file mode 100644
index 000000000..6c63faf50
--- /dev/null
+++ b/pkg/machine/qemu/machine_windows.go
@@ -0,0 +1,27 @@
+package qemu
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/containers/podman/v4/pkg/machine"
+)
+
+func isProcessAlive(pid int) bool {
+	if checkProcessStatus("process", pid, nil) == nil {
+		return true
+	}
+	return false
+}
+
+func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) error {
+	active, exitCode := machine.GetProcessState(pid)
+	if !active {
+		if stderrBuf != nil {
+			return fmt.Errorf("%s exited unexpectedly, exit code: %d stderr: %s", processHint, exitCode, stderrBuf.String())
+		} else {
+			return fmt.Errorf("%s exited unexpectedly, exit code: %d", processHint, exitCode)
+		}
+	}
+	return nil
+}
diff --git a/pkg/machine/qemu/options_windows.go b/pkg/machine/qemu/options_windows.go
new file mode 100644
index 000000000..69652ee39
--- /dev/null
+++ b/pkg/machine/qemu/options_windows.go
@@ -0,0 +1,13 @@
+package qemu
+
+import (
+	"os"
+)
+
+func getRuntimeDir() (string, error) {
+	tmpDir, ok := os.LookupEnv("TEMP")
+	if !ok {
+		tmpDir = os.Getenv("LOCALAPPDATA") + "\\Temp"
+	}
+	return tmpDir, nil
+}
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index 8f6ef7a43..b89e2f720 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -1063,7 +1063,7 @@ func launchWinProxy(v *MachineVM) (bool, string, error) {
 	}
 
 	return globalName, pipePrefix + waitPipe, waitPipeExists(waitPipe, 30, func() error {
-		active, exitCode := getProcessState(cmd.Process.Pid)
+		active, exitCode := machine.GetProcessState(cmd.Process.Pid)
 		if !active {
 			return fmt.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode)
 		}
diff --git a/pkg/machine/wsl/util_windows.go b/pkg/machine/wsl/util_windows.go
index 43f54fdd4..6c74e5652 100644
--- a/pkg/machine/wsl/util_windows.go
+++ b/pkg/machine/wsl/util_windows.go
@@ -280,18 +280,6 @@ func obtainShutdownPrivilege() error {
 	return nil
 }
 
-func getProcessState(pid int) (active bool, exitCode int) {
-	const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
-	handle, err := syscall.OpenProcess(da, false, uint32(pid))
-	if err != nil {
-		return false, int(syscall.ERROR_PROC_NOT_FOUND)
-	}
-
-	var code uint32
-	syscall.GetExitCodeProcess(handle, &code)
-	return code == 259, int(code)
-}
-
 func addRunOnceRegistryEntry(command string) error {
 	k, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\RunOnce`, registry.WRITE)
 	if err != nil {
-- 
cgit v1.2.3-54-g00ecf