//go:build linux package client import ( "fmt" "log" "os" "path/filepath" "time" "golang.org/x/sys/unix" ) // createSocketPair creates a Unix domain socket pair func createSocketPair() ([2]int, error) { fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0) if err != nil { return [2]int{}, fmt.Errorf("socketpair: %w", err) } return fds, nil } func closeFDs(fds [2]int) { unix.Close(fds[0]) unix.Close(fds[1]) } func fdToFile(fd int, name string) *os.File { return os.NewFile(uintptr(fd), name) } // fixVHCIDevicePermissions waits for the VHCI-attached device to create // device nodes (e.g. /dev/video*) and sets them to world-accessible. // VHCI-created devices don't get normal udev rules applied, so they // default to root-only access. func fixVHCIDevicePermissions(port int) { // Wait for the device to finish enumerating and create device nodes // The kernel needs time to enumerate descriptors and bind drivers for attempt := 0; attempt < 10; attempt++ { time.Sleep(500 * time.Millisecond) // Find device nodes created by this VHCI port // VHCI creates devices under /sys/devices/platform/vhci_hcd.0/usbN/ // We look for video4linux devices matches, _ := filepath.Glob("/sys/devices/platform/vhci_hcd.0/usb*/*/video4linux/video*") for _, m := range matches { devName := filepath.Base(m) devPath := "/dev/" + devName if _, err := os.Stat(devPath); err == nil { if err := os.Chmod(devPath, 0666); err == nil { log.Printf("[use] set permissions 0666 on %s", devPath) } } } // Also check for other common device types (input, sound, etc.) for _, subsys := range []string{"sound/card*", "input/input*/event*"} { sysMatches, _ := filepath.Glob("/sys/devices/platform/vhci_hcd.0/usb*/*/" + subsys) for _, m := range sysMatches { devName := filepath.Base(m) devPath := "/dev/" + devName // For sound devices, also check /dev/snd/ if _, err := os.Stat(devPath); err == nil { os.Chmod(devPath, 0666) } devPath = "/dev/snd/" + devName if _, err := os.Stat(devPath); err == nil { os.Chmod(devPath, 0666) } } } if attempt == 0 { continue // first iteration: always wait more } // Check if we found any video devices if len(matches) > 0 { return } } }