From 4224b3f73110f6f0c6268eb1ae943bc24cf89baf Mon Sep 17 00:00:00 2001 From: Aleksandar Pesic Date: Sat, 13 Mar 2021 01:30:26 +0100 Subject: [PATCH] control/controlclient: use API to get Windows version number Fixes #1478 Signed-off-by: Aleksandar Pesic --- control/controlclient/hostinfo_windows.go | 20 ++++--------- .../controlclient/hostinfo_windows_test.go | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 control/controlclient/hostinfo_windows_test.go diff --git a/control/controlclient/hostinfo_windows.go b/control/controlclient/hostinfo_windows.go index 07cb4ce4e..81c438327 100644 --- a/control/controlclient/hostinfo_windows.go +++ b/control/controlclient/hostinfo_windows.go @@ -5,9 +5,9 @@ package controlclient import ( - "os/exec" - "strings" - "syscall" + "fmt" + + "golang.org/x/sys/windows" ) func init() { @@ -15,16 +15,6 @@ func init() { } func osVersionWindows() string { - cmd := exec.Command("cmd", "/c", "ver") - cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - out, _ := cmd.Output() // "\nMicrosoft Windows [Version 10.0.19041.388]\n\n" - s := strings.TrimSpace(string(out)) - s = strings.TrimPrefix(s, "Microsoft Windows [") - s = strings.TrimSuffix(s, "]") - - // "Version 10.x.y.z", with "Version" localized. Keep only stuff after the space. - if sp := strings.Index(s, " "); sp != -1 { - s = s[sp+1:] - } - return s // "10.0.19041.388", ideally + major, minor, build := windows.RtlGetNtVersionNumbers() + return fmt.Sprintf("%d.%d.%d", major, minor, build) } diff --git a/control/controlclient/hostinfo_windows_test.go b/control/controlclient/hostinfo_windows_test.go new file mode 100644 index 000000000..edfb9b0c1 --- /dev/null +++ b/control/controlclient/hostinfo_windows_test.go @@ -0,0 +1,28 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package controlclient + +import ( + "os/exec" + "regexp" + "testing" +) + +func TestOsVersionWindows(t *testing.T) { + out, err := exec.Command("cmd", "/c", "ver").Output() + if err != nil { + t.Fatalf("`ver` error: %v", err) + } + // Extract the version number from the output, and isolate the first three parts (major.minor.build) + rx := regexp.MustCompile(`(\d+\.\d+\.\d+)(\.\d+)?`) + m := rx.FindStringSubmatch(string(out)) + if m == nil { + t.Fatalf("no version number in `ver` output: %q", out) + } + got := osVersionWindows() + if m[1] != got { + t.Errorf("osVersionWindows got %q want %q", got, m[1]) + } +}